Merge branch 'develop'

This commit is contained in:
Pieter Vander Vennet 2024-07-15 10:16:07 +02:00
commit 7b47cff62e
483 changed files with 11615 additions and 16323 deletions

View file

@ -5,6 +5,7 @@ import List from "../UI/Base/List"
import Title from "../UI/Base/Title"
import { BBox } from "./BBox"
import { Feature, Geometry, MultiPolygon, Polygon } from "geojson"
import MarkdownUtils from "../Utils/MarkdownUtils"
export interface ExtraFuncParams {
/**
@ -517,16 +518,16 @@ export class ExtraFunctions {
return record
}
public static HelpText(): BaseUIElement {
const elems = []
public static HelpText(): string {
const elems: string[] = []
for (const func of ExtraFunctions.allFuncs) {
elems.push(new Title(func._name, 3), func._doc, new List(func._args ?? [], true))
elems.push("### "+func._name, func._doc, MarkdownUtils.list(func._args))
}
return new Combine([
return [
ExtraFunctions.intro,
new List(ExtraFunctions.allFuncs.map((func) => `[${func._name}](#${func._name})`)),
MarkdownUtils.list(ExtraFunctions.allFuncs.map((func) => `[${func._name}](#${func._name})`)),
...elems,
])
].join("\n")
}
}

View file

@ -78,7 +78,14 @@ export class WikimediaImageProvider extends ImageProvider {
return new SvelteUIElement(Wikimedia_commons_white).SetStyle("width:2em;height: 2em")
}
public PrepUrl(value: string): ProvidedImage {
public PrepUrl(value: NonNullable<string>): ProvidedImage
public PrepUrl(value: undefined): undefined
public PrepUrl(value: string): ProvidedImage
public PrepUrl(value: string | undefined): ProvidedImage | undefined{
if(value === undefined){
return undefined
}
value = WikimediaImageProvider.removeCommonsPrefix(value)
if (value.startsWith("File:")) {

View file

@ -13,14 +13,11 @@ import { ChangesetHandler, ChangesetTag } from "./ChangesetHandler"
import { OsmConnection } from "./OsmConnection"
import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"
import OsmObjectDownloader from "./OsmObjectDownloader"
import Combine from "../../UI/Base/Combine"
import BaseUIElement from "../../UI/BaseUIElement"
import Title from "../../UI/Base/Title"
import Table from "../../UI/Base/Table"
import ChangeLocationAction from "./Actions/ChangeLocationAction"
import ChangeTagAction from "./Actions/ChangeTagAction"
import FeatureSwitchState from "../State/FeatureSwitchState"
import DeleteAction from "./Actions/DeleteAction"
import MarkdownUtils from "../../Utils/MarkdownUtils"
/**
* Handles all changes made to OSM.
@ -43,7 +40,7 @@ export class Changes {
private _nextId: number = -1 // Newly assigned ID's are negative
private readonly previouslyCreated: OsmObject[] = []
private readonly _leftRightSensitive: boolean
private readonly _changesetHandler: ChangesetHandler
public readonly _changesetHandler: ChangesetHandler
private readonly _reportError?: (string: string | Error) => void
constructor(
@ -116,7 +113,7 @@ export class Changes {
return changes
}
public static getDocs(): BaseUIElement {
public static getDocs(): string {
function addSource(items: any[], src: string) {
items.forEach((i) => {
i["source"] = src
@ -188,27 +185,27 @@ export class Changes {
...ReplaceGeometryAction.metatags,
...SplitAction.metatags,*/
]
return new Combine([
new Title("Metatags on a changeset", 1),
return [
"# Metatags on a changeset",
"You might encounter the following metatags on a changeset:",
new Table(
MarkdownUtils.table(
["key", "value", "explanation", "source"],
metatagsDocs.map(({ key, value, docs, source, changeType, specialMotivation }) => [
key ?? changeType?.join(", ") ?? "",
value,
new Combine([
[
docs,
specialMotivation
? "This might give a reason per modified node or way"
: "",
]),
].join("\n"),
source,
]),
),
])
].join("\n\n")
}
private static GetNeededIds(changes: ChangeDescription[]) {
public static GetNeededIds(changes: ChangeDescription[]) {
return Utils.Dedup(changes.filter((c) => c.id >= 0).map((c) => c.type + "/" + c.id))
}
@ -519,7 +516,7 @@ export class Changes {
const osmObj = await downloader.DownloadObjectAsync(id, 0)
return { id, osmObj }
} catch (e) {
const msg = "Could not download OSM-object" +
const msg = "Could not download OSM-object " +
id +
" trying again before dropping it from the changes (" +
e +
@ -529,7 +526,7 @@ export class Changes {
return { id, osmObj }
}
} catch (e) {
const msg = "Could not download OSM-object" +
const msg = "Could not download OSM-object " +
id +
" dropping it from the changes (" +
e +

View file

@ -25,7 +25,7 @@ export class ChangesetHandler {
* Contains previously rewritten IDs
* @private
*/
private readonly _remappings = new Map<string, string>()
public readonly _remappings = new Map<string, string>()
private readonly _reportError: (e: string | Error) => void
constructor(
@ -187,7 +187,7 @@ export class ChangesetHandler {
await this.UpdateTags(csId, rewrittenTags)
} catch (e) {
if (this._reportError) {
this._reportError("Could not reuse changeset, might be closed: " + e.stacktrace ?? "" + e)
this._reportError("Could not reuse changeset "+csId+", might be closed: " + (e.stacktrace ?? ("" + e)))
}
console.warn("Could not upload, changeset is probably closed: ", e)
openChangeset.setData(undefined)

View file

@ -766,29 +766,27 @@ export default class SimpleMetaTaggers {
return somethingChanged
}
public static HelpText(): BaseUIElement {
const subElements: (string | BaseUIElement)[] = [
new Combine([
public static HelpText(): string {
const subElements: string[] = [
[
"Metatags are extra tags available, in order to display more data or to give better questions.",
"They are calculated automatically on every feature when the data arrives in the webbrowser. This document gives an overview of the available metatags.",
"**Hint:** when using metatags, add the [query parameter](URL_Parameters.md) `debug=true` to the URL. This will include a box in the popup for features which shows all the properties of the object",
]).SetClass("flex-col"),
].join("\n"),
]
subElements.push(new Title("Metatags calculated by MapComplete", 2))
subElements.push("## Metatags calculated by MapComplete")
subElements.push(
new FixedUiElement(
"The following values are always calculated, by default, by MapComplete and are available automatically on all elements in every theme"
)
)
for (const metatag of SimpleMetaTaggers.metatags) {
subElements.push(
new Title(metatag.keys.join(", "), 3),
"### "+metatag.keys.join(", "),
metatag.doc,
metatag.isLazy ? "This is a lazy metatag and is only calculated when needed" : ""
)
}
return new Combine(subElements).SetClass("flex-col")
return subElements.join("\n\n")
}
}

View file

@ -119,6 +119,8 @@ export interface WikidataAdvancedSearchoptions extends WikidataSearchoptions {
notInstanceOf?: number[]
}
interface SparqlResult {results: { bindings: {item, label, description, num}[] }}
/**
* Utility functions around wikidata
*/
@ -202,7 +204,7 @@ export default class Wikidata {
} ORDER BY ASC(?num) LIMIT ${options?.maxCount ?? 20}`
const url = wds.sparqlQuery(sparql)
const result = await Utils.downloadJson(url)
const result = await Utils.downloadJson<SparqlResult>(url)
/*The full uri of the wikidata-item*/
return result.results.bindings.map(({ item, label, description, num }) => ({
@ -389,7 +391,7 @@ export default class Wikidata {
' SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }\n' +
"}"
const url = wds.sparqlQuery(query)
const result = await Utils.downloadJsonCached(url, 24 * 60 * 60 * 1000)
const result = await Utils.downloadJsonCached<SparqlResult>(url, 24 * 60 * 60 * 1000)
return result.results.bindings
}
@ -420,7 +422,7 @@ export default class Wikidata {
}
const url = "https://www.wikidata.org/wiki/Special:EntityData/" + id + ".json"
const entities = (await Utils.downloadJsonCached(url, 10000)).entities
const entities = (await Utils.downloadJsonCached<{entities}>(url, 10000)).entities
const firstKey = <string>Array.from(Object.keys(entities))[0] // Roundabout way to fetch the entity; it might have been a redirect
const response = entities[firstKey]

View file

@ -215,7 +215,7 @@ export default class Wikipedia {
}
private async GetArticleUncachedAsync(pageName: string): Promise<string> {
const response = await Utils.downloadJson(this.getDataUrl(pageName))
const response = await Utils.downloadJson<any>(this.getDataUrl(pageName))
if (response?.parse?.text === undefined) {
return undefined
}

View file

@ -11,6 +11,7 @@ import { RegexTag } from "../../Logic/Tags/RegexTag"
import BaseUIElement from "../../UI/BaseUIElement"
import Table from "../../UI/Base/Table"
import Combine from "../../UI/Base/Combine"
import MarkdownUtils from "../../Utils/MarkdownUtils"
export type FilterConfigOption = {
question: Translation
osmTags: TagsFilter | undefined
@ -199,20 +200,20 @@ export default class FilterConfig {
)
}
public GenerateDocs(): BaseUIElement {
public GenerateDocs(): string {
const hasField = this.options.some((opt) => opt.fields?.length > 0)
return new Table(
return MarkdownUtils.table(
Utils.NoNull(["id", "question", "osmTags", hasField ? "fields" : undefined]),
this.options.map((opt, i) => {
const isDefault = this.options.length > 1 && (this.defaultSelection ?? 0) == i
return Utils.NoNull([
return <string[]> Utils.NoNull([
this.id + "." + i,
isDefault
? new Combine([opt.question.SetClass("font-bold"), "(default)"])
? `*${opt.question.txt}* (default)`
: opt.question,
opt.osmTags?.asHumanString(false, false, {}) ?? "",
opt.osmTags?.asHumanString() ?? "",
opt.fields?.length > 0
? new Combine(opt.fields.map((f) => f.name + " (" + f.type + ")"))
? (opt.fields.map((f) => f.name + " (" + f.type + ")")).join(" ")
: undefined,
])
})

View file

@ -133,7 +133,16 @@ export interface MappingConfigJson {
* question: What extra tags should be added to the object if this object is chosen?
* type: simple_tag
*
* If chosen as answer, these tags will be applied onto the object, together with the tags from the `if`
* If chosen as answer, these tags will be applied onto the object, together with the tags from the `if`.
* Note that if the contributor picks this mapping, saves and then changes their mind and uses a different mapping,
* the extraTags will reside.
* E.g. when picking `memorial:type=bench`, then `amenity=bench` will also be applied.
* If someone later on changes the type to `memorial:statue`, `amenity=bench` will stay onto the object
* (which is the desired behaviour, see e.g. for https://www.openstreetmap.org/node/5620038478)
* Use 'ifNot' to explicitly remove an tag if this is important
*
* If someone marks the question as 'unknown', the extra tags will not be erased
*
* Not compatible with multiAnswer.
*
* This can be used e.g. to erase other keys which indicate the 'not' value:
@ -280,6 +289,11 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
* group: expert
*/
postfixDistinguished?: string
/**
* Extra arguments to configure the input element
* group: hidden
*/
helperArgs: any
}
/**

View file

@ -14,13 +14,9 @@ import WithContextLoader from "./WithContextLoader"
import LineRenderingConfig from "./LineRenderingConfig"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
import BaseUIElement from "../../UI/BaseUIElement"
import Combine from "../../UI/Base/Combine"
import Title from "../../UI/Base/Title"
import List from "../../UI/Base/List"
import Link from "../../UI/Base/Link"
import { Utils } from "../../Utils"
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
import Table from "../../UI/Base/Table"
import FilterConfigJson from "./Json/FilterConfigJson"
import { Overpass } from "../../Logic/Osm/Overpass"
import { FixedUiElement } from "../../UI/Base/FixedUiElement"
@ -28,6 +24,7 @@ import { ImmutableStore } from "../../Logic/UIEventSource"
import { OsmTags } from "../OsmFeature"
import Constants from "../Constants"
import { QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson"
import MarkdownUtils from "../../Utils/MarkdownUtils"
export default class LayerConfig extends WithContextLoader {
public static readonly syncSelectionAllowed = ["no", "local", "theme-only", "global"] as const
@ -90,7 +87,7 @@ export default class LayerConfig extends WithContextLoader {
overpassScript: json.source["overpassScript"],
isOsmCache: json.source["isOsmCache"],
mercatorCrs: json.source["mercatorCrs"],
idKey: json.source["idKey"],
idKey: json.source["idKey"]
},
json.id
)
@ -159,7 +156,7 @@ export default class LayerConfig extends WithContextLoader {
let preciseInput: PreciseInput = {
preferredBackground: ["photo"],
snapToLayers: undefined,
maxSnapDistance: undefined,
maxSnapDistance: undefined
}
if (pr["preciseInput"] !== undefined) {
throw (
@ -172,7 +169,7 @@ export default class LayerConfig extends WithContextLoader {
let snapToLayers = pr.snapToLayer
preciseInput = {
snapToLayers,
maxSnapDistance: pr.maxSnapDistance ?? 10,
maxSnapDistance: pr.maxSnapDistance ?? 10
}
}
@ -184,7 +181,7 @@ export default class LayerConfig extends WithContextLoader {
`${translationContext}.presets.${i}.description`
),
preciseInput: preciseInput,
exampleImages: pr.exampleImages,
exampleImages: pr.exampleImages
}
return config
})
@ -306,7 +303,7 @@ export default class LayerConfig extends WithContextLoader {
}
this.titleIcons = this.ParseTagRenderings(<TagRenderingConfigJson[]>json.titleIcons ?? [], {
readOnlyMode: true,
readOnlyMode: true
})
this.title = this.tr("title", undefined, translationContext)
@ -366,8 +363,8 @@ export default class LayerConfig extends WithContextLoader {
}[] = [],
addedByDefault = false,
canBeIncluded = true
): BaseUIElement {
const extraProps: (string | BaseUIElement)[] = []
): string {
const extraProps: string[] = []
extraProps.push("This layer is shown at zoomlevel **" + this.minzoom + "** and higher")
if (canBeIncluded) {
@ -404,13 +401,11 @@ export default class LayerConfig extends WithContextLoader {
if (this.source?.geojsonSource !== undefined) {
extraProps.push(
new Combine([
Utils.runningFromConsole
? "<img src='../warning.svg' height='1rem'/>"
: undefined,
[
"<img src='../warning.svg' height='1rem'/>",
"This layer is loaded from an external source, namely ",
new FixedUiElement(this.source.geojsonSource).SetClass("code"),
])
"`" + this.source.geojsonSource + "`"
].join("\n\n")
)
}
} else {
@ -419,44 +414,44 @@ export default class LayerConfig extends WithContextLoader {
)
}
let usingLayer: BaseUIElement[] = []
let usingLayer: string[] = []
if (!addedByDefault) {
if (usedInThemes?.length > 0) {
usingLayer = [
new Title("Themes using this layer", 2),
new List(
"## Themes using this layer",
MarkdownUtils.list(
(usedInThemes ?? []).map(
(id) => new Link(id, "https://mapcomplete.org/" + id)
(id) => (`[${id}](https://mapcomplete.org/${id})`)
)
),
)
]
} else if (this.source !== null) {
usingLayer = [new FixedUiElement("No themes use this layer")]
usingLayer = ["No themes use this layer"]
}
}
for (const dep of dependencies) {
extraProps.push(
new Combine([
[
"This layer will automatically load ",
new Link(dep.neededLayer, "./" + dep.neededLayer + ".md"),
(`[${dep.neededLayer}](./${dep.neededLayer}.md)`),
" into the layout as it depends on it: ",
dep.reason,
"(" + dep.context + ")",
])
"(" + dep.context + ")"
].join(" ")
)
}
for (const revDep of Utils.Dedup(layerIsNeededBy?.get(this.id) ?? [])) {
extraProps.push(
new Combine([
[
"This layer is needed as dependency for layer",
new Link(revDep, "#" + revDep),
])
(`[${revDep}](#${revDep})`)
].join(" ")
)
}
const tableRows = Utils.NoNull(
const tableRows: string[][] = Utils.NoNull(
this.tagRenderings
.map((tr) => tr.FreeformValues())
.map((values) => {
@ -467,32 +462,28 @@ export default class LayerConfig extends WithContextLoader {
Link.OsmWiki(values.key, v, true).SetClass("mr-2")
) ?? ["_no preset options defined, or no values in them_"]
return [
new Combine([
new Link(
"<img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'>",
"https://taginfo.openstreetmap.org/keys/" + values.key + "#values",
true
),
Link.OsmWiki(values.key),
]).SetClass("flex"),
[
`<a target="_blank" href='https://taginfo.openstreetmap.org/keys/${ values.key}#values'><img src='https://mapcomplete.org/assets/svg/statistics.svg' height='18px'></a>]`,
Link.OsmWiki(values.key)
].join(" "),
values.type === undefined
? "Multiple choice"
: new Link(values.type, "../SpecialInputElements.md#" + values.type),
new Combine(embedded).SetClass("flex"),
: `[${values.type}](../SpecialInputElements.md#${values.type})`,
embedded.join(" ")
]
})
)
let quickOverview: BaseUIElement = undefined
let quickOverview: string[] = []
if (tableRows.length > 0) {
quickOverview = new Combine([
new FixedUiElement("Warning: ").SetClass("bold"),
quickOverview = [
("**Warning:**"),
"this quick overview is incomplete",
new Table(
MarkdownUtils.table(
["attribute", "type", "values which are supported by this layer"],
tableRows
).SetClass("zebra-table"),
]).SetClass("flex-col flex")
)
]
}
let iconImg: BaseUIElement = new FixedUiElement("")
@ -503,35 +494,36 @@ export default class LayerConfig extends WithContextLoader {
.map(
(mr) =>
mr.RenderIcon(new ImmutableStore<OsmTags>({ id: "node/-1" }), {
includeBadges: false,
includeBadges: false
}).html
)
.find((i) => i !== undefined)
}
let overpassLink: BaseUIElement = undefined
let overpassLink: string = undefined
if (this.source !== undefined) {
try {
overpassLink = new Link(
"Execute on overpass",
overpassLink = (
"[Execute on overpass](" +
Overpass.AsOverpassTurboLink(<TagsFilter>this.source.osmTags.optimize())
.replaceAll("(", "%28")
.replaceAll(")", "%29")
+ ")"
)
} catch (e) {
console.error("Could not generate overpasslink for " + this.id)
}
}
const filterDocs: (string | BaseUIElement)[] = []
const filterDocs: (string)[] = []
if (this.filters.length > 0) {
filterDocs.push(new Title("Filters", 4))
filterDocs.push("#### Filters")
filterDocs.push(...this.filters.map((filter) => filter.GenerateDocs()))
}
const tagsDescription = []
const tagsDescription: string[] = []
if (this.source !== null) {
tagsDescription.push(new Title("Basic tags for this layer", 2))
tagsDescription.push("## Basic tags for this layer")
const neededTags = <TagsFilter>this.source.osmTags.optimize()
if (neededTags["and"]) {
@ -549,8 +541,8 @@ export default class LayerConfig extends WithContextLoader {
} else {
tagsDescription.push(
"Elements must match the expression **" +
neededTags.asHumanString(true, false, {}) +
"**"
neededTags.asHumanString(true, false, {}) +
"**"
)
}
@ -559,20 +551,19 @@ export default class LayerConfig extends WithContextLoader {
tagsDescription.push("This is a special layer - data is not sourced from OpenStreetMap")
}
return new Combine([
new Combine([new Title(this.id, 1), iconImg, this.description, "\n"]).SetClass(
"flex flex-col"
),
new List(extraProps),
return [
[
"# " + this.id+"\n",
iconImg,
this.description, "\n"].join("\n\n"),
MarkdownUtils.list(extraProps),
...usingLayer,
...tagsDescription,
new Title("Supported attributes", 2),
"## Supported attributes",
quickOverview,
...this.tagRenderings.map((tr) => tr.GenerateDocumentation()),
...filterDocs,
])
.SetClass("flex-col")
.SetClass("link-underline")
...filterDocs
] .join("\n\n")
}
public CustomCodeSnippets(): string[] {

View file

@ -69,6 +69,7 @@ export default class TagRenderingConfig {
readonly inline: boolean
readonly default?: string
readonly postfixDistinguished?: string
readonly args?: any
}
public readonly multiAnswer: boolean
@ -203,6 +204,7 @@ export default class TagRenderingConfig {
inline: json.freeform.inline ?? false,
default: json.freeform.default,
postfixDistinguished: json.freeform.postfixDistinguished?.trim(),
args: json.freeform.helperArgs
}
if (json.freeform["extraTags"] !== undefined) {
throw `Freeform.extraTags is defined. This should probably be 'freeform.addExtraTag' (at ${context})`
@ -911,6 +913,24 @@ export default class TagRenderingConfig {
return Utils.NoNull(tags)
}
/**
* The keys that should be erased if one has to revert to 'unknown'.
* Might give undefined
*/
public settableKeys(): string[] | undefined {
const toDelete = new Set<string>()
if(this.freeform){
toDelete.add(this.freeform.key)
}
for (const mapping of this.mappings) {
for (const usedKey of mapping.if.usedKeys()) {
toDelete.add(usedKey)
}
}
return Array.from(toDelete)
}
}
export class TagRenderingConfigUtils {

View file

@ -900,6 +900,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
username: this.osmConnection.userDetails.data?.name,
userid: this.osmConnection.userDetails.data?.uid,
pendingChanges: this.changes.pendingChanges.data,
previousChanges: this.changes.allChanges.data,
changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings)
}),
})
}

View file

@ -1,8 +1,8 @@
<script lang="ts">
import { createEventDispatcher } from "svelte"
import { XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
import { ariaLabel } from "../../Utils/ariaLabel"
import Translations from "../i18n/Translations"
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
/**
* The slotted element will be shown on top, with a lower-opacity border
@ -37,13 +37,14 @@
</div>
<slot name="close-button">
<!-- The close button is placed _after_ the default slot in order to always paint it on top -->
<button
class="absolute right-10 top-10 h-8 w-8 cursor-pointer rounded-full border-none bg-white p-0"
<div
class="absolute right-10 top-10 cursor-pointer border-none p-0 m-0 bg-white rounded-full border-0"
style="margin: -0.25rem"
on:click={() => dispatch("close")}
use:ariaLabel={Translations.t.general.backToMap}
>
<XCircleIcon />
</button>
<XCircleIcon class="w-8 h-8" />
</div>
</slot>
</div>
</div>

View file

@ -3,11 +3,13 @@ import Combine from "./Combine"
import BaseUIElement from "../BaseUIElement"
import Title from "./Title"
import Table from "./Table"
import { UIEventSource } from "../../Logic/UIEventSource"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import { VariableUiElement } from "./VariableUIElement"
import { Translation } from "../i18n/Translation"
import { FixedUiElement } from "./FixedUiElement"
import Translations from "../i18n/Translations"
import MarkdownUtils from "../../Utils/MarkdownUtils"
import Locale from "../i18n/Locale"
export default class Hotkeys {
public static readonly _docs: UIEventSource<
@ -28,18 +30,18 @@ export default class Hotkeys {
public static RegisterHotkey(
key: (
| {
ctrl: string
}
ctrl: string
}
| {
shift: string
}
shift: string
}
| {
alt: string
}
alt: string
}
| {
nomod: string
}
) & {
nomod: string
}
) & {
onUp?: boolean
},
documentation: string | Translation,
@ -61,7 +63,7 @@ export default class Hotkeys {
return
}
if (key["ctrl"] !== undefined) {
document.addEventListener("keydown", function (event) {
document.addEventListener("keydown", function(event) {
if (event.ctrlKey && event.key === keycode) {
if (action() !== false) {
event.preventDefault()
@ -69,7 +71,7 @@ export default class Hotkeys {
}
})
} else if (key["shift"] !== undefined) {
document.addEventListener(type, function (event) {
document.addEventListener(type, function(event) {
if (Hotkeys.textElementSelected(event)) {
// A text element is selected, we don't do anything special
return
@ -81,7 +83,7 @@ export default class Hotkeys {
}
})
} else if (key["alt"] !== undefined) {
document.addEventListener(type, function (event) {
document.addEventListener(type, function(event) {
if (event.altKey && event.key === keycode) {
if (action() !== false) {
event.preventDefault()
@ -89,7 +91,7 @@ export default class Hotkeys {
}
})
} else if (key["nomod"] !== undefined) {
document.addEventListener(type, function (event) {
document.addEventListener(type, function(event) {
if (Hotkeys.textElementSelected(event) && keycode !== "Escape") {
// A text element is selected, we don't do anything special
return
@ -104,61 +106,71 @@ export default class Hotkeys {
}
}
static generateDocumentation(): BaseUIElement {
return new VariableUiElement(
Hotkeys._docs.mapD((docs) => {
let byKey: [string, string | Translation, Translation[] | undefined][] = docs
.map(({ key, documentation, alsoTriggeredBy }) => {
const modifiers = Object.keys(key).filter(
(k) => k !== "nomod" && k !== "onUp"
)
let keycode: string =
key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"]
if (keycode.length == 1) {
keycode = keycode.toUpperCase()
}
if (keycode === " ") {
keycode = "Spacebar"
}
modifiers.push(keycode)
return <[string, string | Translation, Translation[] | undefined]>[
modifiers.join("+"),
documentation,
alsoTriggeredBy,
]
})
.sort()
byKey = Utils.NoNull(byKey)
for (let i = byKey.length - 1; i > 0; i--) {
if (byKey[i - 1][0] === byKey[i][0]) {
byKey.splice(i, 1)
}
static prepareDocumentation(docs: {
key: { ctrl?: string; shift?: string; alt?: string; nomod?: string; onUp?: boolean }
documentation: string | Translation
alsoTriggeredBy: Translation[]
}[]){
let byKey: [string, string | Translation, Translation[] | undefined][] = docs
.map(({ key, documentation, alsoTriggeredBy }) => {
const modifiers = Object.keys(key).filter(
(k) => k !== "nomod" && k !== "onUp"
)
let keycode: string =
key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"]
if (keycode.length == 1) {
keycode = keycode.toUpperCase()
}
const t = Translations.t.hotkeyDocumentation
return new Combine([
new Title(t.title, 1),
t.intro,
new Table(
[t.key, t.action],
byKey.map(([key, doc, alsoTriggeredBy]) => {
let keyEl: BaseUIElement = new FixedUiElement(key).SetClass(
"literal-code w-fit h-fit"
)
if (alsoTriggeredBy?.length > 0) {
keyEl = new Combine([keyEl, ...alsoTriggeredBy]).SetClass(
"flex gap-x-4 items-center"
)
}
return [keyEl, doc]
})
),
])
if (keycode === " ") {
keycode = "Spacebar"
}
modifiers.push(keycode)
return <[string, string | Translation, Translation[] | undefined]>[
modifiers.join("+"),
documentation,
alsoTriggeredBy
]
})
)
.sort()
byKey = Utils.NoNull(byKey)
for (let i = byKey.length - 1; i > 0; i--) {
if (byKey[i - 1][0] === byKey[i][0]) {
byKey.splice(i, 1)
}
}
return byKey
}
static generateDocumentationDynamic(): BaseUIElement {
return new VariableUiElement(Hotkeys._docs.map((_) => Hotkeys.generateDocumentation()))
static generateDocumentationFor(docs: {
key: { ctrl?: string; shift?: string; alt?: string; nomod?: string; onUp?: boolean }
documentation: string | Translation
alsoTriggeredBy: Translation[]
}[], language: string): string {
const tr = Translations.t.hotkeyDocumentation
function t(t: Translation | string){
if(typeof t === "string"){
return t
}
return t.textFor(language)
}
const contents: string[][] = this.prepareDocumentation(docs)
.map(([key, doc, alsoTriggeredBy]) => {
let keyEl: string = [key, ...(alsoTriggeredBy??[])].map(k => "`"+t(k)+"`").join(" ")
return [keyEl, t(doc)]
})
return [
"# "+t(tr.title),
t(tr.intro),
MarkdownUtils.table(
[t(tr.key), t(tr.action)],
contents
)
].join("\n")
}
public static generateDocumentation(language?: string){
return Hotkeys.generateDocumentationFor(Hotkeys._docs.data, language?? Locale.language.data)
}
private static textElementSelected(event: KeyboardEvent): boolean {

View file

@ -1,14 +1,14 @@
import Combine from "./Combine"
import Svg from "../../Svg"
import Translations from "../i18n/Translations"
import BaseUIElement from "../BaseUIElement"
import SvelteUIElement from "./SvelteUIElement"
import {default as LoadingSvg} from "../../assets/svg/Loading.svelte"
export default class Loading extends Combine {
constructor(msg?: BaseUIElement | string) {
const t = Translations.W(msg) ?? Translations.t.general.loading
t.SetClass("pl-2")
super([
Svg.loading_svg()
new SvelteUIElement(LoadingSvg)
.SetClass("animate-spin self-center")
.SetStyle("width: 1.5rem; height: 1.5rem; min-width: 1.5rem;"),
t,

View file

@ -26,7 +26,7 @@ export default class SvelteUIElement<
constructor(svelteElement, props?: Props, events?: Events, slots?: Slots) {
super()
this._svelteComponent = svelteElement
this._svelteComponent = <any> svelteElement
this._props = props ?? <Props>{}
this._events = events
this._slots = slots

View file

@ -98,7 +98,7 @@ export default class TableOfContents {
const intro = md.substring(0, firstTitleIndex)
const splitPoint = intro.lastIndexOf("\n")
return md.substring(0, splitPoint) + toc + md.substring(splitPoint)
return md.substring(0, splitPoint) +"\n" toc + md.substring(splitPoint)
}
public static generateStructure(

View file

@ -0,0 +1,14 @@
<script lang="ts">
import Translations from "../i18n/Translations"
</script>
<div class="flex h-full flex-col">
<h2 class="low-interaction m-0 flex items-center p-4 drop-shadow-md">
<slot name="title" />
</h2>
<div class="flex h-full flex-col overflow-auto border-b-2 p-4">
<slot />
</div>
</div>

View file

@ -5,6 +5,8 @@
*/
import { Utils } from "../Utils"
/* @deprecated
*/
export default abstract class BaseUIElement {
protected _constructedHtmlElement: HTMLElement
protected isDestroyed = false

View file

@ -1,15 +1,12 @@
<script lang="ts">
import Translations from "../i18n/Translations"
import { Utils } from "../../Utils"
import Hotkeys from "../Base/Hotkeys"
import Constants from "../../Models/Constants"
import Tr from "../Base/Tr.svelte"
import Add from "../../assets/svg/Add.svelte"
import Github from "../../assets/svg/Github.svelte"
import DocumentChartBar from "@babeard/svelte-heroicons/outline/DocumentChartBar"
import Mastodon from "../../assets/svg/Mastodon.svelte"
import Liberapay from "../../assets/svg/Liberapay.svelte"
import ToSvelte from "../Base/ToSvelte.svelte"
import { EyeIcon } from "@rgossiaux/svelte-heroicons/solid"
import MapillaryLink from "./MapillaryLink.svelte"
import OpenJosm from "../Base/OpenJosm.svelte"
@ -18,24 +15,28 @@
import Community from "../../assets/svg/Community.svelte"
import Bug from "../../assets/svg/Bug.svelte"
import ThemeViewState from "../../Models/ThemeViewState"
import DocumentChartBar from "@babeard/svelte-heroicons/outline/DocumentChartBar"
export let state: ThemeViewState
let layout = state.layout
let featureSwitches = state.featureSwitches
let showHome = featureSwitches.featureSwitchBackToThemeOverview
</script>
<div class="link-underline links-w-full m-2 flex flex-col gap-y-1">
<Tr t={Translations.t.general.aboutMapComplete.intro} />
<a class="flex" href={Utils.HomepageLink()}>
<Add class="h-6 w-6" />
{#if Utils.isIframe}
<Tr t={Translations.t.general.seeIndex} />
{:else}
<Tr t={Translations.t.general.backToIndex} />
{/if}
</a>
{#if $showHome}
<a class="flex" href={Utils.HomepageLink()}>
<Add class="h-6 w-6" />
{#if Utils.isIframe}
<Tr t={Translations.t.general.seeIndex} />
{:else}
<Tr t={Translations.t.general.backToIndex} />
{/if}
</a>
{/if}
<a class="flex" href="https://github.com/pietervdvn/MapComplete/" target="_blank">
<Github class="h-6 w-6" />

View file

@ -9,6 +9,7 @@
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import Filter from "../../assets/svg/Filter.svelte"
import TitledPanel from "../Base/TitledPanel.svelte"
export let state: ThemeViewState
let layout = state.layout
@ -46,12 +47,12 @@
}
</script>
<div class="flex h-full flex-col">
<h2 class="low-interaction m-0 flex items-center p-4 drop-shadow-md">
<TitledPanel>
<div class="flex" slot="title">
<Filter class="h-6 w-6 pr-2" />
<Tr t={Translations.t.general.menu.filter} />
</h2>
<div class="flex h-full flex-col overflow-auto border-b-2 p-4">
</div>
{#each layout.layers as layer}
<Filterview
zoomlevel={state.mapProperties.zoom}
@ -76,5 +77,7 @@
zoomlevel={state.mapProperties.zoom}
/>
{/each}
</div>
</div>
</TitledPanel>

View file

@ -0,0 +1,55 @@
<script lang="ts">
import Hotkeys from "../Base/Hotkeys"
import { Translation } from "../i18n/Translation"
import { Utils } from "../../Utils"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
let keys = Hotkeys._docs
const t = Translations.t.hotkeyDocumentation
let byKey = Hotkeys.prepareDocumentation($keys)
$: {
byKey = Hotkeys.prepareDocumentation($keys)
}
</script>
<AccordionSingle>
<div slot="header">
<Tr t={t.title} />
</div>
<Tr t={t.intro} />
<table>
<tr>
<th>
<Tr t={t.key}></Tr>
</th>
<th>
<Tr t={t.action} />
</th>
</tr>
{#each byKey as [key, doc, alsoTriggeredBy] }
<tr>
<td class="flex items-center justify-center">
{#if alsoTriggeredBy}
<div class="flex items-center justify-center gap-x-1">
<div class="literal-code w-fit h-fit">{key}</div>
<div class="literal-code w-fit h-fit">{alsoTriggeredBy}</div>
</div>
{:else}
<div class="literal-code w-fit h-fit flex items-center w-full">{key}</div>
{/if}
</td>
<td>
<Tr t={doc} />
</td>
</tr>
{/each}
</table>
</AccordionSingle>

View file

@ -30,7 +30,7 @@
/**
* The start coordinate
*/
export let coordinate: { lon: number; lat: number }
export let coordinate: { lon: number; lat: number } = undefined
/**
* The center of the map at all times
@ -43,8 +43,8 @@
if (coordinate === undefined) {
coordinate = value.data
}
export let snapToLayers: string[] | undefined
export let targetLayer: LayerConfig | undefined
export let snapToLayers: string[] | undefined = undefined
export let targetLayer: LayerConfig | undefined = undefined
export let maxSnapDistance: number = undefined
export let presetProperties: Tag[] = []
let presetPropertiesUnpacked = TagUtils.KVtoProperties(presetProperties)

View file

@ -13,8 +13,6 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource"
import Svg from "../../Svg"
import ToSvelte from "../Base/ToSvelte.svelte"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import Search_disable from "../../assets/svg/Search_disable.svelte"

View file

@ -0,0 +1,59 @@
<script lang="ts">
import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
import Translations from "../i18n/Translations"
import Loading from "../Base/Loading.svelte"
import Hotkeys from "../Base/Hotkeys"
import { createEventDispatcher, onDestroy } from "svelte"
import { placeholder } from "../../Utils/placeholder"
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
import { ariaLabel } from "../../Utils/ariaLabel"
import { Translation } from "../i18n/Translation"
const dispatch = createEventDispatcher<{search: string}>()
export let searchValue: UIEventSource<string>
export let placeholderText: Translation = Translations.t.general.search.search
export let feedback = new UIEventSource<string>(undefined)
let isRunning: boolean = false
let inputElement: HTMLInputElement
function _performSearch(){
dispatch("search", searchValue.data)
}
</script>
<div class="normal-background flex justify-between rounded-full">
<form class="flex w-full flex-wrap" on:submit|preventDefault={() => {}}>
{#if isRunning}
<Loading>{Translations.t.general.search.searching}</Loading>
{:else}
<div class="flex w-full border border-gray-300 rounded-full">
<input
type="search"
class="w-full outline-none mx-2"
bind:this={inputElement}
on:keypress={(keypr) => {
feedback.set(undefined)
return keypr.key === "Enter" ? _performSearch() : undefined
}}
bind:value={$searchValue}
use:placeholder={placeholderText}
use:ariaLabel={Translations.t.general.search.search}
/>
<SearchIcon aria-hidden="true" class="h-6 w-6 self-end" on:click={event => _performSearch()} />
</div>
{#if $feedback !== undefined}
<!-- The feedback is _always_ shown for screenreaders and to make sure that the searchfield can still be selected by tabbing-->
<div class="alert" role="alert" aria-live="assertive">
{$feedback}
</div>
{/if}
{/if}
</form>
</div>

View file

@ -72,14 +72,14 @@
{/if}
</div>
<slot name="close-button">
<button
class="mt-2 h-fit shrink-0 rounded-full border-none p-0"
<div
class="mt-2 h-fit shrink-0 rounded-full border-none p-0 cursor-pointer"
on:click={() => state.selectedElement.setData(undefined)}
style="border: 0 !important; padding: 0 !important;"
use:ariaLabel={Translations.t.general.backToMap}
>
<XCircleIcon aria-hidden={true} class="h-8 w-8" />
</button>
</div>
</slot>
</div>

View file

@ -22,6 +22,8 @@
selectedElement.properties.id
)
let isAddNew = tags.mapD(t => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false)
function getLayer(properties: Record<string, string>) {
if (properties.id === "settings") {
return UserRelatedState.usersettingsConfig
@ -76,7 +78,10 @@
</div>
{:else}
<div
class="selected-element-view flex h-full w-full flex-col gap-y-1 overflow-y-auto p-1 px-4"
class="selected-element-view flex h-full w-full flex-col gap-y-1 overflow-y-auto"
class:p1={!$isAddNew}
class:px-4={!$isAddNew}
tabindex="-1"
>
{#each $knownTagRenderings as config (config.id)}

View file

@ -1,51 +0,0 @@
import Combine from "../Base/Combine"
import Translations from "../i18n/Translations"
import BaseUIElement from "../BaseUIElement"
import { VariableUiElement } from "../Base/VariableUIElement"
import { Store } from "../../Logic/UIEventSource"
import { LicenseInfo } from "../../Logic/ImageProviders/LicenseInfo"
import { FixedUiElement } from "../Base/FixedUiElement"
import Link from "../Base/Link"
/**
* Small box in the bottom left of an image, e.g. the image in a popup
*/
export default class Attribution extends VariableUiElement {
constructor(license: Store<LicenseInfo>, icon: BaseUIElement, date?: Date) {
if (license === undefined) {
throw "No license source given in the attribution element"
}
super(
license.map((license: LicenseInfo) => {
if (license === undefined) {
return undefined
}
let title = undefined
if (license?.title) {
title = Translations.W(license?.title).SetClass("block")
if (license.informationLocation) {
title = new Link(title, license.informationLocation.href, true)
}
}
return new Combine([
icon
?.SetClass("block left")
.SetStyle("height: 2em; width: 2em; padding-right: 0.5em;"),
new Combine([
title,
Translations.W(license?.artist ?? "").SetClass("block font-bold"),
Translations.W(license?.license ?? license?.licenseShortName),
date === undefined
? undefined
: new FixedUiElement(date.toLocaleDateString()),
]).SetClass("flex flex-col"),
]).SetClass(
"flex flex-row bg-black text-white text-sm absolute bottom-0 left-0 p-0.5 pl-5 pr-3 rounded-lg no-images"
)
})
)
}
}

View file

@ -2,12 +2,13 @@ import { Store } from "../../Logic/UIEventSource"
import Translations from "../i18n/Translations"
import Toggle, { ClickableToggle } from "../Input/Toggle"
import Combine from "../Base/Combine"
import Svg from "../../Svg"
import { Tag } from "../../Logic/Tags/Tag"
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction"
import { Changes } from "../../Logic/Osm/Changes"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
import SvelteUIElement from "../Base/SvelteUIElement"
import Delete_icon from "../../assets/svg/Delete_icon.svelte"
export default class DeleteImage extends Toggle {
constructor(
@ -48,7 +49,7 @@ export default class DeleteImage extends Toggle {
.Clone()
.SetClass("bg-white pl-4 pr-4")
.SetStyle("border-bottom-left-radius:30rem; border-bottom-right-radius: 30rem;")
const openDelete = Svg.delete_icon_svg().SetStyle("width: 2em; height: 2em; display:block;")
const openDelete = new SvelteUIElement(Delete_icon).SetStyle("width: 2em; height: 2em; display:block;")
const deleteDialog = new ClickableToggle(
new Combine([deleteButton, cancelButton]).SetClass("flex flex-col background-black"),
openDelete

View file

@ -0,0 +1,145 @@
<script lang="ts">
/**
* Allows to search through wikidata and to select one value
*/
import Translations from "../../i18n/Translations"
import Tr from "../../Base/Tr.svelte"
import { ImmutableStore, Store, Stores, UIEventSource } from "../../../Logic/UIEventSource"
import Wikidata, { WikidataResponse } from "../../../Logic/Web/Wikidata"
import Locale from "../../i18n/Locale"
import SearchField from "../../BigComponents/SearchField.svelte"
import Loading from "../../Base/Loading.svelte"
import Wikidatapreview from "../../Wikipedia/Wikidatapreview.svelte"
import { Utils } from "../../../Utils"
import WikidataValidator from "../Validators/WikidataValidator"
const t = Translations.t.general.wikipedia
export let searchValue = new UIEventSource("Tom boonen")
export let placeholder = t.searchWikidata
export let allowMultiple = false
export let notInstanceOf: number[] = []
export let instanceOf: number[] = []
export let value: UIEventSource<string>
let selectedWikidataSingle: WikidataResponse = undefined
let selectedMany: Record<string, boolean> = {}
let previouslySeen = new Map<string, WikidataResponse>()
$:{
if (selectedWikidataSingle) {
value.setData(selectedWikidataSingle.id)
}
}
$:{
console.log(selectedMany)
const v = []
for (const id in selectedMany) {
if (selectedMany[id]) {
v.push(id)
}
}
value.setData(v.join(";"))
}
let tooShort = new ImmutableStore<{ success: WikidataResponse[] }>({ success: undefined })
let searchResult: Store<{ success?: WikidataResponse[]; error?: any }> = searchValue
.bind((searchText) => {
if (searchText.length < 3 && !searchText.match(/[qQ][0-9]+/)) {
return tooShort
}
const lang = Locale.language.data
const key = lang + ":" + searchText
let promise = WikidataValidator._searchCache.get(key)
if (promise === undefined) {
promise = Wikidata.searchAndFetch(searchText, {
lang,
maxCount: 5,
notInstanceOf,
instanceOf
})
WikidataValidator._searchCache.set(key, promise)
}
return Stores.FromPromiseWithErr(promise)
})
let selectedWithoutSearch: Store<WikidataResponse[]> = searchResult.map(sr => {
for (const wikidataItem of sr?.success ?? []) {
console.log("Saving", wikidataItem.id)
previouslySeen.set(wikidataItem.id, wikidataItem)
}
let knownIds: Set<string> = new Set(sr?.success?.map(item => item.id))
const seen = [selectedWikidataSingle]
for (const id in selectedMany) {
if (selectedMany[id]) {
const item = previouslySeen.get(id)
seen.push(item)
}
}
return Utils.NoNull(seen).filter(i => !knownIds.has(i.id))
})
</script>
<h3>
<Tr t={Translations.t.general.wikipedia.searchWikidata} />
</h3>
<form>
<SearchField {searchValue} placeholderText={placeholder}></SearchField>
{#if $searchValue.trim().length === 0}
<Tr cls="w-full flex justify-center p-4" t={ t.doSearch} />
{:else if $searchValue.trim().length < 3}
<Tr t={ t.searchToShort} />
{:else if $searchResult === undefined}
<div class="w-full flex justify-center p-4">
<Loading>
<Tr t={Translations.t.general.loading} />
</Loading>
</div>
{:else if $searchResult.error !== undefined}
<div class="w-full flex justify-center p-4">
<Tr cls="alert" t={t.failed} />
</div>
{:else if $searchResult.success}
{#if $searchResult.success.length === 0}
<Tr cls="w-full flex justify-center p-4" t={ t.noResults.Subs({search: $searchValue})} />
{:else}
{#each $searchResult.success as wikidata}
<label class="low-interaction m-4 p-2 rounded-xl flex items-center">
{#if allowMultiple}
<input type="checkbox" bind:checked={selectedMany[wikidata.id]} />
{:else}
<input type="radio" name="selectedWikidata" value={wikidata} bind:group={selectedWikidataSingle} />
{/if}
<Wikidatapreview {wikidata} />
</label>
{/each}
{/if}
{/if}
{#each $selectedWithoutSearch as wikidata}
<label class="low-interaction m-4 p-2 rounded-xl flex items-center">
{#if allowMultiple}
<input type="checkbox" bind:checked={selectedMany[wikidata.id]} />
{:else}
<input type="radio" name="selectedWikidata" value={wikidata} bind:group={selectedWikidataSingle} />
{/if}
<Wikidatapreview {wikidata} />
</label>
{/each}
</form>

View file

@ -19,6 +19,8 @@
import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte"
import SlopeInput from "./Helpers/SlopeInput.svelte"
import type { SpecialVisualizationState } from "../SpecialVisualization"
import WikidataInput from "./Helpers/WikidataInput.svelte"
import WikidataInputHelper from "./WikidataInputHelper.svelte"
export let type: ValidatorType
export let value: UIEventSource<string | object>
@ -26,17 +28,13 @@
export let feature: Feature
export let args: (string | number | boolean)[] = undefined
export let state: SpecialVisualizationState
export let helperArgs: (string | number | boolean)[]
export let key: string
export let extraTags: UIEventSource<Record<string, string>>
let properties = { feature, args: args ?? [] }
</script>
{#if type === "translation"}
<TranslationInput {value} on:submit {args} />
{:else if type === "direction"}
<DirectionInput {value} mapProperties={InputHelpers.constructMapProperties(properties)} />
<DirectionInput {value} mapProperties={InputHelpers.constructMapProperties( { feature, args: args ?? [] })} />
{:else if type === "date"}
<DateInput {value} />
{:else if type === "color"}
@ -52,5 +50,5 @@
{:else if type === "slope"}
<SlopeInput {value} {feature} {state} />
{:else if type === "wikidata"}
<ToSvelte construct={() => InputHelpers.constructWikidataHelper(value, properties)} />
<WikidataInputHelper {value} {feature} {state} {args}/>
{/if}

View file

@ -1,10 +1,6 @@
import { UIEventSource } from "../../Logic/UIEventSource"
import { MapProperties } from "../../Models/MapProperties"
import WikidataSearchBox from "../Wikipedia/WikidataSearchBox"
import Wikidata from "../../Logic/Web/Wikidata"
import { Utils } from "../../Utils"
import Locale from "../i18n/Locale"
import { Feature } from "geojson"
import { GeoOperations } from "../../Logic/GeoOperations"
@ -68,67 +64,5 @@ export default class InputHelpers {
return mapProperties
}
public static constructWikidataHelper(
value: UIEventSource<string>,
props: InputHelperProperties
) {
const inputHelperOptions = props
const args = inputHelperOptions.args ?? []
const searchKey: string = <string>args[0] ?? "name"
const searchFor: string =
searchKey
.split(";")
.map((k) => inputHelperOptions.feature?.properties[k]?.toLowerCase())
.find((foundValue) => !!foundValue) ?? ""
let searchForValue: UIEventSource<string> = new UIEventSource(searchFor)
const options: any = args[1]
if (searchFor !== undefined && options !== undefined) {
const prefixes = <string[] | Record<string, string[]>>options["removePrefixes"] ?? []
const postfixes = <string[] | Record<string, string[]>>options["removePostfixes"] ?? []
const defaultValueCandidate = Locale.language.map((lg) => {
const prefixesUnrwapped: RegExp[] = (
Array.isArray(prefixes) ? prefixes : prefixes[lg] ?? []
).map((s) => new RegExp("^" + s, "i"))
const postfixesUnwrapped: RegExp[] = (
Array.isArray(postfixes) ? postfixes : postfixes[lg] ?? []
).map((s) => new RegExp(s + "$", "i"))
let clipped = searchFor
for (const postfix of postfixesUnwrapped) {
const match = searchFor.match(postfix)
if (match !== null) {
clipped = searchFor.substring(0, searchFor.length - match[0].length)
break
}
}
for (const prefix of prefixesUnrwapped) {
const match = searchFor.match(prefix)
if (match !== null) {
clipped = searchFor.substring(match[0].length)
break
}
}
return clipped
})
defaultValueCandidate.addCallbackAndRun((clipped) => searchForValue.setData(clipped))
}
let instanceOf: number[] = Utils.NoNull(
(options?.instanceOf ?? []).map((i) => Wikidata.QIdToNumber(i))
)
let notInstanceOf: number[] = Utils.NoNull(
(options?.notInstanceOf ?? []).map((i) => Wikidata.QIdToNumber(i))
)
return new WikidataSearchBox({
value,
searchText: searchForValue,
instanceOf,
notInstanceOf,
})
}
}

View file

@ -99,15 +99,15 @@ export default class Validators {
private static _byType = Validators._byTypeConstructor()
public static HelpText(): BaseUIElement {
const explanations: BaseUIElement[] = Validators.AllValidators.map((type) =>
new Combine([new Title(type.name, 3), type.explanation]).SetClass("flex flex-col")
public static HelpText(): string {
const explanations: string[] = Validators.AllValidators.flatMap((type) =>
["### "+type.name, type.explanation]
)
return new Combine([
new Title("Available types for text fields", 1),
return [
"# Available types for text fields",
"The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them",
...explanations,
]).SetClass("flex flex-col")
].join("\n")
}
private static _byTypeConstructor(): Map<ValidatorType, Validator> {

View file

@ -1,13 +1,101 @@
import Combine from "../../Base/Combine"
import Wikidata from "../../../Logic/Web/Wikidata"
import WikidataSearchBox from "../../Wikipedia/WikidataSearchBox"
import Wikidata, { WikidataResponse } from "../../../Logic/Web/Wikidata"
import { Validator } from "../Validator"
import { Translation } from "../../i18n/Translation"
import Translations from "../../i18n/Translations"
import Title from "../../Base/Title"
import Table from "../../Base/Table"
import MarkdownUtils from "../../../Utils/MarkdownUtils"
export default class WikidataValidator extends Validator {
public static readonly _searchCache = new Map<string, Promise<WikidataResponse[]>>()
public static docs = new Combine([
new Title("Helper arguments"),
new Table(
["name", "doc"],
[
[
"key",
"the value of this tag will initialize search (default: name). This can be a ';'-separated list in which case every key will be inspected. The non-null value will be used as search",
],
[
"options",
new Combine([
"A JSON-object of type `{ removePrefixes: string[], removePostfixes: string[] }`.",
MarkdownUtils.table(
["subarg", "doc"],
[
[
"removePrefixes",
"remove these snippets of text from the start of the passed string to search. This is either a list OR a hash of languages to a list. The individual strings are interpreted as case ignoring regexes",
],
[
"removePostfixes",
"remove these snippets of text from the end of the passed string to search. This is either a list OR a hash of languages to a list. The individual strings are interpreted as case ignoring regexes.",
],
[
"instanceOf",
"A list of Q-identifier which indicates that the search results _must_ be an entity of this type, e.g. [`Q5`](https://www.wikidata.org/wiki/Q5) for humans",
],
[
"notInstanceof",
"A list of Q-identifiers which indicates that the search results _must not_ be an entity of this type, e.g. [`Q79007`](https://www.wikidata.org/wiki/Q79007) to filter away all streets from the search results",
],
["multiple",
"If 'yes' or 'true', will allow to select multiple values at once"]
]
),
]),
],
]
),
new Title("Example usage"),
`The following is the 'freeform'-part of a layer config which will trigger a search for the wikidata item corresponding with the name of the selected feature. It will also remove '-street', '-square', ... if found at the end of the name
\`\`\`json
"freeform": {
"key": "name:etymology:wikidata",
"type": "wikidata",
"helperArgs": [
"name",
{
"removePostfixes": {"en": [
"street",
"boulevard",
"path",
"square",
"plaza",
],
"nl": ["straat","plein","pad","weg",laan"],
"fr":["route (de|de la|de l'| de le)"]
},
"#": "Remove streets and parks from the search results:"
"notInstanceOf": ["Q79007","Q22698"]
}
]
}
\`\`\`
Another example is to search for species and trees:
\`\`\`json
"freeform": {
"key": "species:wikidata",
"type": "wikidata",
"helperArgs": [
"species",
{
"instanceOf": [10884, 16521]
}]
}
\`\`\`
`,
])
constructor() {
super("wikidata", new Combine(["A wikidata identifier, e.g. Q42.", WikidataSearchBox.docs]))
super("wikidata", new Combine(["A wikidata identifier, e.g. Q42.", WikidataValidator.docs]))
}
public isValid(str): boolean {
@ -44,4 +132,48 @@ export default class WikidataValidator extends Validator {
}
return out
}
/**
*
* @param searchTerm
* @param postfixesToRemove
* @param prefixesToRemove
* @param language
*
*
* WikidataValidator.removePostAndPrefixes("Elf-Julistraat", [], ["straat", "laan"], "nl") // => "Elf-Juli"
* WikidataValidator.removePostAndPrefixes("Elf-Julistraat", [], {"nl":["straat", "laan"], "en": ["street"]}, "nl") // => "Elf-Juli"
* WikidataValidator.removePostAndPrefixes("Elf-Julistraat", [], {"nl":["straat", "laan"], "en": ["street"]}, "en") // => "Elf-Julistraat"
*/
public static removePostAndPrefixes(searchTerm: string, prefixesToRemove: string[] | Record<string, string[]>, postfixesToRemove: string[] | Record<string, string[]>, language: string): string {
const prefixes = prefixesToRemove
const postfixes = postfixesToRemove
const prefixesUnwrapped: RegExp[] = (
Array.isArray(prefixes) ? prefixes : prefixes[language] ?? []
).map((s) => new RegExp("^" + s, "i"))
const postfixesUnwrapped: RegExp[] = (
Array.isArray(postfixes) ? postfixes : postfixes[language] ?? []
).map((s) => new RegExp(s + "$", "i"))
let clipped = searchTerm.trim()
for (const postfix of postfixesUnwrapped) {
const match = searchTerm.trim().match(postfix)
if (match !== null) {
clipped = searchTerm.trim().substring(0, searchTerm.trim().length - match[0].length)
break
}
}
for (const prefix of prefixesUnwrapped) {
const match = searchTerm.trim().match(prefix)
if (match !== null) {
clipped = searchTerm.trim().substring(match[0].length)
break
}
}
return clipped
}
}

View file

@ -0,0 +1,58 @@
<script lang="ts">/**
*
Wrapper around 'WikidataInput.svelte' which handles the arguments
*/
import { UIEventSource } from "../../Logic/UIEventSource"
import Locale from "../i18n/Locale"
import { Utils } from "../../Utils"
import Wikidata from "../../Logic/Web/Wikidata"
import WikidataInput from "./Helpers/WikidataInput.svelte"
import type { Feature } from "geojson"
import { onDestroy } from "svelte"
import WikidataValidator from "./Validators/WikidataValidator"
export let args: (string | number | boolean)[] = []
export let feature: Feature
export let value: UIEventSource<string>
let searchKey: string = <string>args[0] ?? "name"
let searchFor: string =
searchKey
.split(";")
.map((k) => feature?.properties[k]?.toLowerCase())
.find((foundValue) => !!foundValue) ?? ""
const options: any = args[1]
console.log(">>>", args)
let searchForValue: UIEventSource<string> = new UIEventSource(searchFor)
onDestroy(
Locale.language.addCallbackAndRunD(lg => {
console.log(options)
if (searchFor !== undefined && options !== undefined) {
const post = options["removePostfixes"] ?? []
const pre = options["removePrefixes"] ?? []
const clipped = WikidataValidator.removePostAndPrefixes(searchFor, pre, post, lg)
console.log("Got clipped value:", clipped, post, pre)
searchForValue.setData(clipped)
}
})
)
let instanceOf: number[] = Utils.NoNull(
(options?.instanceOf ?? []).map((i) => Wikidata.QIdToNumber(i))
)
let notInstanceOf: number[] = Utils.NoNull(
(options?.notInstanceOf ?? []).map((i) => Wikidata.QIdToNumber(i))
)
let allowMultipleArg = options?.["multiple"]
let allowMultiple = allowMultipleArg === "yes" || (""+allowMultipleArg) === "true"
</script>
<WikidataInput searchValue={searchForValue} {value} {instanceOf} {notInstanceOf} {allowMultiple}/>

View file

@ -24,6 +24,10 @@
{#if iconItem?.startsWith("<")}
{@html iconItem}
{:else if color === "white"}
<span class="light-icon">
<Icon icon={iconItem} {color} {emojiHeight} />
</span>
{:else}
<Icon icon={iconItem} {color} {emojiHeight} />
{/if}

View file

@ -11,6 +11,7 @@
import UserRelatedState from "../../Logic/State/UserRelatedState"
import Translations from "../i18n/Translations"
import Tr from "../Base/Tr.svelte"
import TitledPanel from "../Base/TitledPanel.svelte"
export let availableLayers: Store<RasterLayerPolygon[]>
export let mapproperties: MapProperties
@ -50,12 +51,8 @@
}
</script>
<div class="flex h-full flex-col">
<slot name="title">
<h2>
<Tr t={Translations.t.general.backgroundMap} />
</h2>
</slot>
<TitledPanel>
<Tr slot="title" t={Translations.t.general.backgroundMap} />
<div class="grid h-full w-full grid-cols-1 gap-2 md:grid-cols-2">
<RasterLayerPicker
@ -91,4 +88,4 @@
{visible}
/>
</div>
</div>
</TitledPanel>

View file

@ -77,7 +77,7 @@
{#if hasLayers}
<form class="flex h-full w-full flex-col" on:submit|preventDefault={() => {}}>
<button tabindex="-1" on:click={() => apply()} class="m-0 h-full w-full cursor-pointer p-1">
<button tabindex="-1" on:click={() => apply()} class="m-0 p-0 rounded-none h-full w-full cursor-pointer border-none">
<span class="pointer-events-none relative h-full w-full">
<OverlayMap
interactive={false}

View file

@ -453,7 +453,7 @@ export class OH {
/*
This function converts a number of ranges (generated by OpeningHours.js) into all the hours of day that a change occurs.
E.g.
Monday, some business is opended from 9:00 till 17:00
Monday, some business is opened from 9:00 till 17:00
Tuesday from 9:30 till 18:00
Wednesday from 9:30 till 12:30
This function will extract all those moments of change and will return 9:00, 9:30, 12:30, 17:00 and 18:00

View file

@ -1,12 +1,13 @@
/**
* A single opening hours range, shown on top of the OH-picker table
*/
import Svg from "../../Svg"
import { Utils } from "../../Utils"
import Combine from "../Base/Combine"
import { OH, OpeningHour } from "./OpeningHours"
import BaseUIElement from "../BaseUIElement"
import { FixedUiElement } from "../Base/FixedUiElement"
import SvelteUIElement from "../Base/SvelteUIElement"
import Delete_icon from "../../assets/svg/Delete_icon.svelte"
export default class OpeningHoursRange extends BaseUIElement {
private _oh: OpeningHour
@ -30,7 +31,7 @@ export default class OpeningHoursRange extends BaseUIElement {
Utils.TwoDigits(oh.endHour) + ":" + Utils.TwoDigits(oh.endMinutes)
)
const deleteRange = Svg.delete_icon_svg()
const deleteRange = new SvelteUIElement(Delete_icon)
.SetClass("rounded-full w-6 h-6 block bg-black pointer-events-auto ")
.onClick(() => {
this._onDelete()

View file

@ -4,14 +4,13 @@
*/
import { createEventDispatcher } from "svelte"
import type { PlantNetSpeciesMatch } from "../../Logic/Web/PlantNet"
import { UIEventSource } from "../../Logic/UIEventSource"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import Wikidata from "../../Logic/Web/Wikidata"
import NextButton from "../Base/NextButton.svelte"
import Loading from "../Base/Loading.svelte"
import WikidataPreviewBox from "../Wikipedia/WikidataPreviewBox"
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
import ToSvelte from "../Base/ToSvelte.svelte"
import WikidatapreviewWithLoading from "../Wikipedia/WikidatapreviewWithLoading.svelte"
export let species: PlantNetSpeciesMatch
let wikidata = UIEventSource.FromPromise(
@ -46,16 +45,12 @@
/>
</Loading>
{:else}
<ToSvelte
construct={() =>
new WikidataPreviewBox(wikidataId, {
imageStyle: "max-width: 8rem; width: unset; height: 8rem",
extraItems: [
t.matchPercentage
.Subs({ match: Math.round(species.score * 100) })
.SetClass("thanks w-fit self-center"),
],
}).SetClass("w-full")}
/>
<WikidatapreviewWithLoading wikidataId={wikidataId} imageStyle="max-width: 8rem; width: unset; height: 8rem">
<div slot="extra">
<Tr cls="thanks w-fit self-center" t={ t.matchPercentage
.Subs({ match: Math.round(species.score * 100) })}/>
</div>
</WikidatapreviewWithLoading>
{/if}
</NextButton>

View file

@ -36,6 +36,7 @@
import { Translation } from "../../i18n/Translation"
import ToSvelte from "../../Base/ToSvelte.svelte"
import BaseUIElement from "../../BaseUIElement"
import TitledPanel from "../../Base/TitledPanel.svelte"
export let coordinate: { lon: number; lat: number }
export let state: SpecialVisualizationState
@ -116,7 +117,7 @@
theme: state.layout?.id ?? "unkown",
changeType: "create",
snapOnto: snapToWay,
reusePointWithinMeters: 1,
reusePointWithinMeters: 1
})
await state.changes.applyAction(newElementAction)
state.newFeatures.features.ping()
@ -186,40 +187,50 @@
/>
{:else if !$layerIsDisplayed}
<!-- Check that the layer is enabled, so that we don't add a duplicate -->
<div class="alert flex items-center justify-center">
<EyeOffIcon class="w-8" />
<Tr
t={Translations.t.general.add.layerNotEnabled.Subs({ layer: selectedPreset.layer.name })}
/>
</div>
<TitledPanel>
<Tr slot="title" t={Translations.t.general.add.intro} />
<div class="flex flex-wrap-reverse md:flex-nowrap">
<button
class="flex w-full gap-x-1"
on:click={() => {
<div class="alert flex items-center justify-center">
<EyeOffIcon class="w-8" />
<Tr
t={Translations.t.general.add.layerNotEnabled.Subs({ layer: selectedPreset.layer.name })}
/>
</div>
<div class="flex flex-wrap-reverse md:flex-nowrap">
<button
class="flex w-full gap-x-1"
on:click={() => {
abort()
state.guistate.openFilterView(selectedPreset.layer)
}}
>
<Layers class="w-12" />
<Tr t={Translations.t.general.add.openLayerControl} />
</button>
>
<Layers class="w-12" />
<Tr t={Translations.t.general.add.openLayerControl} />
</button>
<button
class="primary flex w-full gap-x-1"
on:click={() => {
<button
class="primary flex w-full gap-x-1"
on:click={() => {
layerIsDisplayed.setData(true)
abort()
}}
>
<EyeIcon class="w-12" />
<Tr
t={Translations.t.general.add.enableLayer.Subs({ name: selectedPreset.layer.name })}
/>
</button>
</div>
>
<EyeIcon class="w-12" />
<Tr
t={Translations.t.general.add.enableLayer.Subs({ name: selectedPreset.layer.name })}
/>
</button>
</div>
</TitledPanel>
{:else if $layerHasFilters}
<!-- Some filters are enabled. The feature to add might already be mapped, but hidden -->
<TitledPanel>
<Tr slot="title" t={Translations.t.general.add.intro} />
<!-- Some filters are enabled. The feature to add might already be mapped, but hidden -->
<div class="alert flex items-center justify-center">
<EyeOffIcon class="w-8" />
<Tr t={Translations.t.general.add.disableFiltersExplanation} />
@ -246,13 +257,14 @@
<Tr t={Translations.t.general.add.openLayerControl} />
</button>
</div>
</TitledPanel>
{:else if !confirmedCategory}
<!-- Second, confirm the category -->
<h2 class="mr-12">
<Tr
<TitledPanel>
<Tr slot="title"
t={Translations.t.general.add.confirmTitle.Subs({ title: selectedPreset.preset.title })}
/>
</h2>
{#if selectedPreset.preset.description}
<Tr t={selectedPreset.preset.description} />
@ -293,6 +305,8 @@
</div>
</NextButton>
</div>
</TitledPanel>
{:else if _globalFilter?.length > 0 && _globalFilter?.length > checkedOfGlobalFilters}
<Tr t={_globalFilter[checkedOfGlobalFilters].onNewPoint?.safetyCheck} cls="mx-12" />
<SubtleButton
@ -366,7 +380,9 @@
</div>
</div>
{:else}
<Loading><Tr t={Translations.t.general.add.creating} /></Loading>
<Loading>
<Tr t={Translations.t.general.add.creating} />
</Loading>
{/if}
</div>
</LoginToggle>

View file

@ -13,6 +13,7 @@
import ToSvelte from "../../Base/ToSvelte.svelte"
import BaseUIElement from "../../BaseUIElement"
import Combine from "../../Base/Combine"
import TitledPanel from "../../Base/TitledPanel.svelte"
/**
* This component lists all the presets and allows the user to select one
@ -79,7 +80,7 @@
text: Translations.t.general.add.addNew.Subs(
{ category: preset.title },
preset.title["context"]
),
)
}
presets.push(simplified)
}
@ -96,11 +97,9 @@
}>()
</script>
<div class="flex w-full flex-col">
<h2 class="mr-12">
<!-- The title gets a big right margin to give place to the 'close'-button, see https://github.com/pietervdvn/MapComplete/issues/1445 -->
<Tr t={Translations.t.general.add.intro} />
</h2>
<TitledPanel>
<Tr slot="title" t={Translations.t.general.add.intro} />
{#each presets as preset}
<NextButton on:click={() => dispatch("select", preset)}>
@ -115,4 +114,4 @@
</div>
</NextButton>
{/each}
</div>
</TitledPanel>

View file

@ -16,11 +16,10 @@
import TagHint from "../TagHint.svelte"
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
import { Store } from "../../../Logic/UIEventSource"
import Svg from "../../../Svg"
import ToSvelte from "../../Base/ToSvelte.svelte"
import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid"
import FilteredLayer from "../../../Models/FilteredLayer"
import Confirm from "../../../assets/svg/Confirm.svelte"
import Layers from "../../../assets/svg/Layers.svelte"
export let importFlow: ImportFlow<ImportFlowArguments>
let state = importFlow.state
@ -77,7 +76,7 @@
state.guistate.openFilterView(filteredLayer.layerDef)
}}
>
<ToSvelte construct={Svg.layers_svg().SetClass("w-12")} />
<Layers class="w-12"/>
<Tr t={Translations.t.general.add.openLayerControl} />
</button>
@ -120,7 +119,7 @@
state.guistate.openFilterView(filteredLayer.layerDef)
}}
>
<ToSvelte construct={Svg.layers_svg().SetClass("w-12")} />
<Layers class="w-12"/>
<Tr t={Translations.t.general.add.openLayerControl} />
</button>
</div>

View file

@ -1,6 +1,5 @@
import { SubtleButton } from "../Base/SubtleButton"
import BaseUIElement from "../BaseUIElement"
import Svg from "../../Svg"
import { OsmConnection, OsmServiceState } from "../../Logic/Osm/OsmConnection"
import { VariableUiElement } from "../Base/VariableUIElement"
import Loading from "../Base/Loading"
@ -8,6 +7,9 @@ import Translations from "../i18n/Translations"
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
import Combine from "../Base/Combine"
import { Translation } from "../i18n/Translation"
import SvelteUIElement from "../Base/SvelteUIElement"
import Login from "../../assets/svg/Login.svelte"
import Invalid from "../../assets/svg/Invalid.svelte"
class LoginButton extends SubtleButton {
constructor(
@ -17,7 +19,7 @@ class LoginButton extends SubtleButton {
},
icon?: BaseUIElement | string
) {
super(icon ?? Svg.login_svg(), text)
super(icon ?? new SvelteUIElement(Login), text)
this.onClick(() => {
state.osmConnection?.AttemptLogin()
})
@ -65,7 +67,7 @@ export class LoginToggle extends VariableUiElement {
const apiTranslation = offlineModes[apiState]
if (apiTranslation !== undefined) {
return new Combine([
Svg.invalid_svg().SetClass("w-8 h-8 m-2 shrink-0"),
new SvelteUIElement(Invalid).SetClass("w-8 h-8 m-2 shrink-0"),
apiTranslation,
]).SetClass("flex items-center alert max-w-64")
}
@ -84,7 +86,7 @@ export class LoginToggle extends VariableUiElement {
return new LoginButton(
Translations.t.general.loginFailed,
state,
Svg.invalid_svg()
new SvelteUIElement(Invalid)
)
},
[state.featureSwitchUserbadge, state.osmConnection?.apiIsOnline]

View file

@ -17,7 +17,7 @@ export class CloseNoteButton implements SpecialVisualization {
public readonly funcName = "close_note"
public readonly needsUrls = [Constants.osmAuthConfig.url]
public readonly docs =
"Button to close a note. A predifined text can be defined to close the note with. If the note is already closed, will show a small text."
"Button to close a note. A predefined text can be defined to close the note with. If the note is already closed, will show a small text."
public readonly args = [
{
name: "text",

View file

@ -13,13 +13,12 @@
import LoginToggle from "../../Base/LoginToggle.svelte"
import FilteredLayer from "../../../Models/FilteredLayer"
import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte"
import ToSvelte from "../../Base/ToSvelte.svelte"
import Svg from "../../../Svg"
import Layers from "../../../assets/svg/Layers.svelte"
import AddSmall from "../../../assets/svg/AddSmall.svelte"
import type { OsmTags } from "../../../Models/OsmFeature"
import Loading from "../../Base/Loading.svelte"
import NextButton from "../../Base/NextButton.svelte"
import Note from "../../../assets/svg/Note.svelte"
export let coordinate: UIEventSource<{ lon: number; lat: number }>
export let state: SpecialVisualizationState
@ -124,7 +123,7 @@
<div class="h-56 w-full">
<NewPointLocationInput value={coordinate} {state}>
<div class="h-20 w-full pb-10" slot="image">
<ToSvelte construct={Svg.note_svg().SetClass("h-10 w-full")} />
<Note class="h-10 w-full"/>
</div>
</NewPointLocationInput>
</div>

View file

@ -1,7 +1,5 @@
<script lang="ts">
import type { OsmTags } from "../../Models/OsmFeature"
import Svg from "../../Svg"
import ToSvelte from "../Base/ToSvelte.svelte"
import { Utils } from "../../Utils"
import { Store } from "../../Logic/UIEventSource"
import Envelope from "../../assets/svg/Envelope.svelte"

View file

@ -15,7 +15,6 @@
export let unvalidatedText: UIEventSource<string> = new UIEventSource<string>(value.data)
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
export let extraTags: UIEventSource<Record<string, string>>
export let feature: Feature = undefined
export let state: SpecialVisualizationState
@ -28,8 +27,6 @@
inline = false
inline = config.freeform?.inline
}
let helperArgs = config.freeform?.helperArgs
let key = config.freeform?.key
const dispatch = createEventDispatcher<{ selected }>()
export let feedback: UIEventSource<Translation>
@ -73,14 +70,11 @@
{/if}
<InputHelper
args={config.freeform.helperArgs}
args={config.freeform.args}
{feature}
type={config.freeform.type}
{value}
{state}
{helperArgs}
{key}
{extraTags}
on:submit
/>
</div>

View file

@ -17,7 +17,7 @@
/**
* Css classes to apply
*/
export let clss: string = ""
export let clss: string = "ml-2"
export let mapping: {
readonly then: Translation
readonly searchTerms?: Record<string, string[]>
@ -41,8 +41,7 @@
`mapping-icon-${mapping.iconClass ?? "small"}-height mapping-icon-${
mapping.iconClass ?? "small"
}-width`,
"mr-2",
"shrink-0 mx-2"
"shrink-0"
)}
clss={`mapping-icon-${mapping.iconClass ?? "small"}`}
/>

View file

@ -32,6 +32,7 @@
import { And } from "../../../Logic/Tags/And"
import { get } from "svelte/store"
import Markdown from "../../Base/Markdown.svelte"
import { Utils } from "../../../Utils"
export let config: TagRenderingConfig
export let tags: UIEventSource<Record<string, string>>
@ -42,7 +43,7 @@
export let selectedTags: UploadableTag = undefined
export let extraTags: UIEventSource<Record<string, string>> = new UIEventSource({})
export let allowDeleteOfFreeform: boolean = false
export let allowDeleteOfFreeform: boolean = true
export let clss = "interactive border-interactive"
@ -141,7 +142,9 @@
feedback.setData(undefined)
}
let usedKeys: string[] = config.usedTags().flatMap((t) => t.usedKeys())
let usedKeys: string[] = Utils.Dedup(config.usedTags().flatMap((t) => t.usedKeys()))
let keysToDeleteOnUnknown = config.settableKeys()
/**
* The 'minimalTags' is a subset of the tags of the feature, only containing the values relevant for this object.
* The main goal is to be stable and only 'ping' when an actual change is relevant
@ -193,10 +196,12 @@
$: {
if (
config.freeform?.key &&
allowDeleteOfFreeform &&
$freeformInput === undefined &&
$freeformInputUnvalidated === "" &&
(config?.mappings?.length ?? 0) === 0
!$freeformInput &&
!$freeformInputUnvalidated &&
!checkedMappings?.some(m => m) &&
$tags[config.freeform.key] // We need to have a current value in order to delete it
) {
selectedTags = new Tag(config.freeform.key, "")
} else {
@ -360,7 +365,7 @@
{/if}
{/if}
{#if config.freeform?.key && !(config?.mappings?.filter((m) => m.hideInAnswer != true)?.length > 0)}
{#if config?.freeform?.key && !(config?.mappings?.filter((m) => m.hideInAnswer != true)?.length > 0)}
<!-- There are no options to choose from, simply show the input element: fill out the text field -->
<FreeformInput
{config}
@ -480,6 +485,9 @@
<Tr t={$feedback} />
</div>
{/if}
<!--{#if keysToDeleteOnUnknown?.some(k => !! $tags[k])}
Mark as unknown (delete {keysToDeleteOnUnknown?.filter(k => !! $tags[k]).join(";")})
{/if}-->
<div
class="sticky bottom-0 flex flex-wrap-reverse items-stretch justify-end sm:flex-nowrap"
style="z-index: 11"
@ -487,7 +495,7 @@
<!-- TagRenderingQuestion-buttons -->
<slot name="cancel" />
<slot name="save-button" {selectedTags}>
{#if allowDeleteOfFreeform && (config?.mappings?.length ?? 0) === 0 && $freeformInput === undefined && $freeformInputUnvalidated === ""}
{#if config.freeform?.key && allowDeleteOfFreeform && !checkedMappings?.some(m => m) && !$freeformInput && !$freeformInputUnvalidated && $tags[config.freeform.key]}
<button
class="primary flex"
on:click|stopPropagation|preventDefault={() => onSave()}
@ -513,12 +521,14 @@
<TagHint {state} tags={selectedTags} currentProperties={$tags} />
<span class="flex flex-wrap">
{#if $featureSwitchIsTesting}
<button class="small" on:click={() => console.log("Configuration is ", config)}>
<div class="alert">
Testmode &nbsp;
</button>
</div>
{/if}
{#if $featureSwitchIsTesting || $featureSwitchIsDebugging}
<span class="subtle">{config.id}</span>
<a class="small" on:click={() => console.log("Configuration is ", config)}>
{config.id}
</a>
{/if}
</span>
</span>

View file

@ -28,7 +28,7 @@
export let selectedTags: UploadableTag = undefined
export let extraTags: UIEventSource<Record<string, string>> = new UIEventSource({})
export let allowDeleteOfFreeform: boolean = false
export let allowDeleteOfFreeform: boolean = true
let dynamicConfig = TagRenderingConfigUtils.withNameSuggestionIndex(config, tags, selectedElement)
</script>

View file

@ -7,28 +7,29 @@ import { QueryParameters } from "../Logic/Web/QueryParameters"
import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig"
import ThemeViewStateHashActor from "../Logic/Web/ThemeViewStateHashActor"
import MarkdownUtils from "../Utils/MarkdownUtils"
export default class QueryParameterDocumentation {
private static QueryParamDocsIntro = [
new Title("URL-parameters and URL-hash", 1),
private static QueryParamDocsIntro: string[] = [
"# URL-parameters and URL-hash",
"This document gives an overview of which URL-parameters can be used to influence MapComplete.",
new Title("What is a URL parameter?", 2),
"## What is a URL parameter?",
'"URL-parameters are extra parts of the URL used to set the state.',
"For example, if the url is `https://mapcomplete.org/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`, " +
"the URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all separated by `&`, namely: ",
new List(
MarkdownUtils.list(
[
"The url-parameter `lat` is `51.0` in this instance",
"The url-parameter `lon` is `4.3` in this instance",
"The url-parameter `z` is `5` in this instance",
"The url-parameter `test` is `true` in this instance",
].map((s) => Translations.W(s))
]
),
"Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case.",
]
public static UrlParamDocs(): Map<string, string> {
const dummyLayout = new LayoutConfig({
const dummyLayout = new LayoutConfig(<any>{
id: "&gt;theme&lt;",
title: { en: "<theme>" },
description: "A theme to generate docs with",
@ -59,26 +60,26 @@ export default class QueryParameterDocumentation {
QueryParameters.GetQueryParameter(
"layer-&lt;layer-id&gt;",
"true",
"Wether or not the layer with id <layer-id> is shown"
"Whether the layer with id <layer-id> is shown"
)
return QueryParameters.documentation
}
public static GenerateQueryParameterDocs(): BaseUIElement {
const docs: (string | BaseUIElement)[] = [
public static GenerateQueryParameterDocs(): string {
const docs: string[] = [
...QueryParameterDocumentation.QueryParamDocsIntro,
...ThemeViewStateHashActor.documentation,
]
this.UrlParamDocs().forEach((value, key) => {
const c = new Combine([
new Title(key, 2),
const c = [
"## "+key,
value,
QueryParameters.defaults[key] === undefined
? "No default value set"
: `The default value is _${QueryParameters.defaults[key]}_`,
])
].join("\n\n")
docs.push(c)
})
return new Combine(docs).SetClass("flex flex-col")
return docs.join("\n\n")
}
}

View file

@ -0,0 +1,7 @@
import { Store } from "../../Logic/UIEventSource"
export interface MCService {
name: string
status: Store<"online" | "degraded" | "offline">,
message?: Store<undefined | string>
}

View file

@ -0,0 +1,22 @@
<script lang="ts">
import StatusIcon from "./StatusIcon.svelte"
import type { MCService } from "./MCService.js"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
export let service: MCService
let status = service.status
let msg = service.message
</script>
<AccordionSingle>
<h3 slot="header" class="flex items-center m-0"> <StatusIcon status={$status}/> {service.name}</h3>
<div class="mx-4">
{#if $msg}
{$msg}
{:else}
No extra information available
{/if}
</div>
</AccordionSingle>

View file

@ -0,0 +1,352 @@
<script lang="ts">
import { Store, Stores, UIEventSource } from "../../Logic/UIEventSource"
import StatusIcon from "./StatusIcon.svelte"
import type { MCService } from "./MCService"
import ServiceIndicator from "./ServiceIndicator.svelte"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import Constants from "../../Models/Constants"
import { Utils } from "../../Utils"
import Loading from "../Base/Loading.svelte"
import Checkbox from "../Base/Checkbox.svelte"
let services: MCService[] = []
let recheckSignal: UIEventSource<any> = new UIEventSource<any>(undefined)
let checkSignal = Stores.Chronic(10000)
let autoCheckAgain = new UIEventSource<boolean>(false)
function testDownload(url: string, raw: boolean = false): Store<{ success } | { error }> {
const src = new UIEventSource(undefined)
function check() {
const promise = raw ? Utils.download(url) : Utils.downloadJson(url)
promise
?.then((d) => src.setData({ success: d }))
?.catch((err) => src.setData({ error: err }))
}
check()
recheckSignal.addCallback(_ => check())
checkSignal.addCallback(_ => {
if (autoCheckAgain.data) {
check()
}
})
return src
}
function simpleMessage(s: Store<{ success: any } | { error: any }>): Store<string> {
return s.mapD(s => {
if (s["success"]) {
return JSON.stringify(s["success"])
}
return s["error"]
})
}
{
const connection = new OsmConnection()
const osmApi = connection.apiIsOnline
services.push({
name: connection.Backend(),
status: osmApi.mapD(serviceState => {
switch (serviceState) {
case "offline":
return "offline"
case "online":
return "online"
case "readonly":
return "degraded"
case "unknown":
return undefined
case "unreachable":
return "offline"
}
}),
message: osmApi,
})
}
{
const s = "https://studio.mapcomplete.org"
const status = testDownload(s + "/overview")
services.push({
name: s,
status: status.mapD(s => {
if (s["error"]) {
return "offline"
}
const files: string[] = s["success"]["allFiles"]
if (files.length < 10) {
return "offline"
}
if (files.length < 100) {
return "degraded"
}
return "online"
}),
message: status.mapD(s => {
if (s["error"]) {
return s["error"]
}
const files: string[] = s["success"]["allFiles"]
return "Contains " + (files.length ?? "no") + " files"
}),
})
}
{
services.push(
{
name: Constants.GeoIpServer,
status: testDownload(Constants.GeoIpServer + "/status").mapD(result => {
if (result["success"].online) {
return "online"
}
if (result["error"]) {
return "offline"
} else {
return "degraded"
}
}),
message: simpleMessage(
testDownload(Constants.GeoIpServer + "/ip"),
),
},
)
}
{
const s = Constants.ErrorReportServer
const status = testDownload(s.replace(/\/report$/, "/status"))
services.push({
name: s,
status: status.mapD(s => {
if (s["error"]) {
return "offline"
}
const data = s["success"]
if (data["errors_today"] === 0) {
return "online"
}
return "degraded"
}),
message: simpleMessage(status),
})
}
{
const s = Constants.linkedDataProxy.replace(/\/[^/]*$/, "")
const status = testDownload(s + "/status")
services.push({
name: s,
status: status.mapD(s => {
if (s["error"]) {
return "offline"
}
const data = s["success"]
if (data.cached_entries < 10 || data.uptime < 60 * 60) {
return "degraded"
}
return "online"
}),
message: simpleMessage(status),
})
}
{
const s = Constants.SummaryServer
const status = testDownload(s + "/summary/status.json")
services.push({
name: s,
status: status.mapD(s => {
if (s["error"]) {
return "offline"
}
console.log(s)
const attributes = s["success"]["meta"]
const lastUpdate = new Date(attributes["current_timestamp"])
console.log("Last update:", lastUpdate, attributes["current_timestamp"], attributes)
const timediffSec = (new Date().getTime() - lastUpdate.getTime()) / 1000
const timediffDays = timediffSec / (60 * 60 * 26)
if (timediffDays > 7) {
return "degraded"
}
return "online"
}),
message: status.mapD(s => {
if (s["error"]) {
return s["error"]
}
const attributes = s["success"]["meta"]
const lastUpdate = new Date(attributes["current_timestamp"])
const timediffSec = (new Date().getTime() - lastUpdate.getTime()) / 1000
const timediffDays = timediffSec / (60 * 60 * 26)
const json = JSON.stringify(s["success"], null, " ")
return "Database is " + Math.floor(timediffDays) + " days out of sync\n\n" + json
}),
})
}
{
const s = Constants.countryCoderEndpoint
const status = testDownload(s + "/0.0.0.json")
services.push({
name: s,
status: status.mapD(s => {
if (s["error"]) {
return "offline"
}
const arr = s["success"]
if (Array.isArray(arr)) {
return "online"
}
return "degraded"
}),
message: status.map(s => JSON.stringify(s)),
})
}
{
for (const defaultOverpassUrl of Constants.defaultOverpassUrls) {
const statusUrl = defaultOverpassUrl.replace(/\/interpreter$/, "/status")
const status = testDownload(statusUrl, true)
services.push({
name: "Overpass-server: " + defaultOverpassUrl,
status: status.mapD(result => {
if (result["error"]) {
return "offline"
}
// "Connected as: 3587935836
// Current time: 2024-07-14T00:35:58Z
// Announced endpoint: gall.openstreetmap.de
// Rate limit: 6
// 6 slots available now.
// Currently running queries (pid, space limit, time limit, start time):\n"
const msgs = result["success"].split("\n")
return "online"
}),
message: simpleMessage(status),
})
}
}
{
services.push({
name: "Mangrove reviews",
status: testDownload("https://api.mangrove.reviews", true).mapD(r => {
if (r["success"]) {
return "online"
}
return "offline"
}),
})
}
let all = new UIEventSource<"online" | "degraded" | "offline">("online")
let someLoading = new UIEventSource(true)
function setAll() {
const data = Utils.NoNull(services.map(s => s.status.data))
someLoading.setData(data.length !== services.length)
if (data.some(d => d === "offline")) {
all.setData("offline")
} else if (data.some(d => d === "degraded")) {
all.setData("degraded")
} else if (data.some(d => d === "online")) {
all.setData("online")
} else {
all.setData(undefined)
}
}
for (const service of services) {
service.status.addCallbackD(() => {
setAll()
})
}
const trafficLightUrl = "http://traffic_light_bicycle.local/"
let trafficLightIsOnline = testDownload(trafficLightUrl + "/status", true)
let enableTrafficLight = new UIEventSource(true)
/**
* So... IN my room, there is a traffic light. Like, an actual traffic light with bicycles.
* I put in an ESP32 and can now control it remotely - which is precisely what this code does.
* @param state
*/
async function setTrafficLight(state: "online" | "degraded" | "offline") {
try {
const url = trafficLightUrl
const status = await Utils.downloadJson(url + "status")
console.log(status)
if (!enableTrafficLight.data) {
await Utils.download(url + "configure?mode=0")
return
}
switch (state) {
case "offline":
await Utils.download(url + "configure?mode=3")
break
case "degraded":
await Utils.download(url + "configure?mode=2")
break
case "online":
await Utils.download(url + "configure?mode=1")
break
default:
await Utils.download(url + "configure?mode=7")
break
}
} catch (e) {
console.log("Could not connect to the traffic light")
}
}
all.addCallbackAndRunD(state => {
setTrafficLight(state)
})
enableTrafficLight.addCallbackAndRunD(_ => {
setTrafficLight(all.data)
})
</script>
<h1>MapComplete status indicators</h1>
<div class="flex">
{#if $someLoading}
<Loading />
{/if}
<StatusIcon status={$all} cls="w-16 h-16" />
<button on:click={() => recheckSignal.ping()}>Check again</button>
<Checkbox selected={autoCheckAgain}>
Automatically check again every 10s
</Checkbox>
</div>
{#if $trafficLightIsOnline?.["success"] }
<Checkbox selected={enableTrafficLight}>Enable traffic light</Checkbox>
{/if}
{#each services as service}
<ServiceIndicator {service} />
{/each}

View file

@ -0,0 +1,28 @@
<script lang="ts">
import Loading from "../Base/Loading.svelte"
import CheckCircle from "@babeard/svelte-heroicons/mini/CheckCircle"
import XCircle from "@rgossiaux/svelte-heroicons/solid/XCircle"
import { twJoin } from "tailwind-merge"
import { XIcon } from "@rgossiaux/svelte-heroicons/outline"
import Exclamation from "@rgossiaux/svelte-heroicons/solid/Exclamation"
import Check from "@babeard/svelte-heroicons/mini/Check"
import { XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
export let status: "online" | "degraded" | "offline"
export let cls: string = "w-6 h-6 mx-1"
</script>
{#if status === "online"}
<CheckCircle class={twJoin(cls,"rounded-full shrink-0")} style="color: #22cc22" />
{:else if status === "degraded"}
<Exclamation class={twJoin(cls,"rounded-full shrink-0")} style="color: #eecc22" />
{:else if status === "offline"}
<XCircleIcon class={twJoin(cls,"rounded-full shrink-0")} style="color: #bb2222" />
{:else if status === undefined}
<div class={twJoin(cls,"rounded-full shrink-0")}>
<Loading />
</div>
{:else}
? {status}
{/if}

11
src/UI/StatusGui.ts Normal file
View file

@ -0,0 +1,11 @@
import StatusGUI from "./Status/StatusGUI.svelte"
export default class StatusGui {
public setup() {
new StatusGUI({
target: document.getElementById("main"),
})
}
}
new StatusGui().setup()

View file

@ -182,7 +182,7 @@
{:else if typeof value === "string"}
Builtin: <b>{value}</b>
{:else}
<Tr cls="font-bold" t={Translations.T(value.question ?? value.render)} />
<Tr cls="font-bold" t={Translations.T(value?.question ?? value?.render)}/>
{/if}
</span>
<div class="normal-background p-2">

View file

@ -74,6 +74,7 @@
import AboutMapComplete from "./BigComponents/AboutMapComplete.svelte"
import IfNot from "./Base/IfNot.svelte"
import Hotkeys from "./Base/Hotkeys"
import HotkeyTable from "./BigComponents/HotkeyTable.svelte"
export let state: ThemeViewState
let layout = state.layout
@ -472,13 +473,6 @@
<If condition={state.previewedImage.map((i) => i !== undefined)}>
<FloatOver on:close={() => state.previewedImage.setData(undefined)}>
<button
class="absolute right-4 top-4 h-8 w-8 rounded-full p-0"
on:click={() => previewedImage.setData(undefined)}
slot="close-button"
>
<XCircleIcon />
</button>
<ImageOperations image={$previewedImage} />
</FloatOver>
</If>
@ -550,7 +544,6 @@
state.guistate.backgroundLayerSelectionIsOpened.setData(false)
}}
>
<div class="h-full p-2">
<RasterLayerOverview
{availableLayers}
map={state.map}
@ -558,7 +551,6 @@
userstate={state.userRelatedState}
visible={state.guistate.backgroundLayerSelectionIsOpened}
/>
</div>
</FloatOver>
</IfHidden>
@ -584,7 +576,7 @@
<div slot="content0" class="flex flex-col">
<AboutMapComplete {state} />
<div class="m-2 flex flex-col">
<ToSvelte construct={Hotkeys.generateDocumentationDynamic} />
<HotkeyTable/>
</div>
</div>

View file

@ -1,34 +1,21 @@
import { VariableUiElement } from "../Base/VariableUIElement"
import { Store } from "../../Logic/UIEventSource"
import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata"
import { Translation, TypedTranslation } from "../i18n/Translation"
import { FixedUiElement } from "../Base/FixedUiElement"
import Loading from "../Base/Loading"
import { TypedTranslation } from "../i18n/Translation"
import Translations from "../i18n/Translations"
import Combine from "../Base/Combine"
import Img from "../Base/Img"
import { WikimediaImageProvider } from "../../Logic/ImageProviders/WikimediaImageProvider"
import Link from "../Base/Link"
import BaseUIElement from "../BaseUIElement"
import { Utils } from "../../Utils"
import SvelteUIElement from "../Base/SvelteUIElement"
import { default as Wikidata_icon } from "../../assets/svg/Wikidata.svelte"
import Gender_male from "../../assets/svg/Gender_male.svelte"
import Gender_female from "../../assets/svg/Gender_female.svelte"
import Gender_inter from "../../assets/svg/Gender_inter.svelte"
import Gender_trans from "../../assets/svg/Gender_trans.svelte"
import Gender_queer from "../../assets/svg/Gender_queer.svelte"
export default class WikidataPreviewBox extends VariableUiElement {
export default class WikidataPreviewBox {
private static isHuman = [{ p: 31 /*is a*/, q: 5 /* human */ }]
// @ts-ignore
private static extraProperties: {
public static extraProperties: {
requires?: { p: number; q?: number }[]
property: string
textMode?: Map<string, string>
display:
| TypedTranslation<{ value }>
| Map<string, string | (() => BaseUIElement) /*If translation: Subs({value: * }) */>
textMode?: Map<string, string>
| Map<string, any>,
}[] = [
{
requires: WikidataPreviewBox.isHuman,
@ -36,34 +23,28 @@ export default class WikidataPreviewBox extends VariableUiElement {
display: new Map([
[
"Q6581097",
() => new SvelteUIElement(Gender_male).SetStyle("width: 1rem; height: auto"),
Gender_male
],
[
"Q6581072",
() => new SvelteUIElement(Gender_female).SetStyle("width: 1rem; height: auto"),
Gender_female
],
[
"Q1097630",
() => new SvelteUIElement(Gender_inter).SetStyle("width: 1rem; height: auto"),
Gender_inter
],
[
"Q1052281",
() =>
new SvelteUIElement(Gender_trans).SetStyle(
"width: 1rem; height: auto"
) /*'transwomen'*/,
Gender_trans /*'transwomen'*/
],
[
"Q2449503",
() =>
new SvelteUIElement(Gender_trans).SetStyle(
"width: 1rem; height: auto"
) /*'transmen'*/,
Gender_trans /*'transmen'*/
],
[
"Q48270",
() => new SvelteUIElement(Gender_queer).SetStyle("width: 1rem; height: auto"),
],
Gender_queer
]
]),
textMode: new Map([
["Q6581097", "♂️"],
@ -71,158 +52,19 @@ export default class WikidataPreviewBox extends VariableUiElement {
["Q1097630", "⚥️"],
["Q1052281", "🏳️‍⚧️" /*'transwomen'*/],
["Q2449503", "🏳️‍⚧️" /*'transmen'*/],
["Q48270", "🏳️‍🌈 ⚧"],
]),
["Q48270", "🏳️‍🌈 ⚧"]
])
},
{
property: "P569",
requires: WikidataPreviewBox.isHuman,
display: Translations.t.general.wikipedia.previewbox.born,
display: Translations.t.general.wikipedia.previewbox.born
},
{
property: "P570",
requires: WikidataPreviewBox.isHuman,
display: Translations.t.general.wikipedia.previewbox.died,
},
display: Translations.t.general.wikipedia.previewbox.died
}
]
constructor(
wikidataId: Store<string>,
options?: {
noImages?: boolean
imageStyle?: string
whileLoading?: BaseUIElement | string
extraItems?: (BaseUIElement | string)[]
}
) {
let inited = false
const wikidata = wikidataId.stabilized(250).bind((id) => {
if (id === undefined || id === "" || id === "Q") {
return null
}
inited = true
return Wikidata.LoadWikidataEntry(id)
})
super(
wikidata.map((maybeWikidata) => {
if (maybeWikidata === null || !inited) {
return options?.whileLoading
}
if (maybeWikidata === undefined) {
return new Loading(Translations.t.general.loading)
}
if (maybeWikidata["error"] !== undefined) {
return new FixedUiElement(maybeWikidata["error"]).SetClass("alert")
}
const wikidata = <WikidataResponse>maybeWikidata["success"]
console.log(">>>> got wikidata", wikidata)
return WikidataPreviewBox.WikidataResponsePreview(wikidata, options)
})
)
}
public static WikidataResponsePreview(
wikidata: WikidataResponse,
options?: {
noImages?: boolean
imageStyle?: string
extraItems?: (BaseUIElement | string)[]
}
): BaseUIElement {
console.log(">>> constructing wikidata preview box", wikidata.labels)
const link = new Link(
new Combine([
wikidata.id,
options?.noImages
? wikidata.id
: new SvelteUIElement(Wikidata_icon)
.SetStyle("width: 2.5rem")
.SetClass("block"),
]).SetClass("flex"),
Wikidata.IdToArticle(wikidata.id),
true
)?.SetClass("must-link")
let info = new Combine([
new Combine([
Translation.fromMap(wikidata.labels)?.SetClass("font-bold"),
link,
]).SetClass("flex justify-between flex-wrap-reverse"),
Translation.fromMap(wikidata.descriptions, true),
WikidataPreviewBox.QuickFacts(wikidata, options),
...(options?.extraItems ?? []),
]).SetClass("flex flex-col link-underline")
let imageUrl = undefined
if (wikidata.claims.get("P18")?.size > 0) {
imageUrl = Array.from(wikidata.claims.get("P18"))[0]
}
if (imageUrl && !options?.noImages) {
imageUrl = WikimediaImageProvider.singleton.PrepUrl(imageUrl).url
info = new Combine([
new Img(imageUrl)
.SetStyle(options?.imageStyle ?? "max-width: 5rem; width: unset; height: 4rem")
.SetClass("rounded-xl mr-2"),
info.SetClass("w-full"),
]).SetClass("flex")
}
info.SetClass("p-2 w-full")
return info
}
public static QuickFacts(
wikidata: WikidataResponse,
options?: { noImages?: boolean }
): BaseUIElement {
const els: BaseUIElement[] = []
for (const extraProperty of WikidataPreviewBox.extraProperties) {
let hasAllRequirements = true
for (const requirement of extraProperty.requires) {
if (!wikidata.claims?.has("P" + requirement.p)) {
hasAllRequirements = false
break
}
if (!wikidata.claims?.get("P" + requirement.p).has("Q" + requirement.q)) {
hasAllRequirements = false
break
}
}
if (!hasAllRequirements) {
continue
}
const key = extraProperty.property
const display =
(options?.noImages ? extraProperty.textMode : extraProperty.display) ??
extraProperty.display
if (wikidata.claims?.get(key) === undefined) {
continue
}
const value: string[] = Array.from(wikidata.claims.get(key))
if (display instanceof Translation) {
els.push(display.Subs({ value: value.join(", ") }).SetClass("m-2"))
continue
}
const constructors = Utils.NoNull(value.map((property) => display.get(property)))
const elems = constructors.map((v) => {
if (typeof v === "string") {
return new FixedUiElement(v)
} else {
return v()
}
})
els.push(new Combine(elems).SetClass("flex m-2"))
}
if (els.length === 0) {
return undefined
}
return new Combine(els).SetClass("flex")
}
}

View file

@ -0,0 +1,49 @@
<script lang="ts">
import { Translation } from "../i18n/Translation"
import WikidataPreviewBox from "./WikidataPreviewBox"
import { WikidataResponse } from "../../Logic/Web/Wikidata"
import Tr from "../Base/Tr.svelte"
export let wikidata: WikidataResponse
let propertiesToRender = WikidataPreviewBox.extraProperties.filter(property => {
for (const requirement of property.requires) {
if (!wikidata.claims?.has("P" + requirement.p)) {
return false
}
if (!wikidata.claims?.get("P" + requirement.p).has("Q" + requirement.q)) {
return false
}
const key = property.property
if (wikidata.claims?.get(key) === undefined) {
return false
}
return true
}
})
function getProperty(property: {property: string}){
const key = property.property
const value = Array.from(wikidata.claims?.get(key)).join(", ")
return value
}
</script>
{#if propertiesToRender.length > 0}
<div class="flex justify-start items-center">
{#each propertiesToRender as property}
{#if typeof property.display === "string" }
{property.display}
{:else if property.display instanceof Translation}
<Tr cls="m-2 shrink-0"
t={property.display.Subs({value: getProperty(property)}) } />
{:else}
<svelte:component this={property.display.get(getProperty(property))} class="h-6 w-fit m-1"/>
{/if}
{/each}
</div>
{/if}

View file

@ -1,223 +0,0 @@
import Combine from "../Base/Combine"
import { InputElement } from "../Input/InputElement"
import { TextField } from "../Input/TextField"
import Translations from "../i18n/Translations"
import { ImmutableStore, Store, Stores, UIEventSource } from "../../Logic/UIEventSource"
import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata"
import Locale from "../i18n/Locale"
import { VariableUiElement } from "../Base/VariableUIElement"
import WikidataPreviewBox from "./WikidataPreviewBox"
import Title from "../Base/Title"
import Svg from "../../Svg"
import Loading from "../Base/Loading"
import Table from "../Base/Table"
import SvelteUIElement from "../Base/SvelteUIElement"
import Search from "../../assets/svg/Search.svelte"
export default class WikidataSearchBox extends InputElement<string> {
public static docs = new Combine([
new Title("Helper arguments"),
new Table(
["name", "doc"],
[
[
"key",
"the value of this tag will initialize search (default: name). This can be a ';'-separated list in which case every key will be inspected. The non-null value will be used as search",
],
[
"options",
new Combine([
"A JSON-object of type `{ removePrefixes: string[], removePostfixes: string[] }`.",
new Table(
["subarg", "doc"],
[
[
"removePrefixes",
"remove these snippets of text from the start of the passed string to search. This is either a list OR a hash of languages to a list. The individual strings are interpreted as case ignoring regexes",
],
[
"removePostfixes",
"remove these snippets of text from the end of the passed string to search. This is either a list OR a hash of languages to a list. The individual strings are interpreted as case ignoring regexes.",
],
[
"instanceOf",
"A list of Q-identifier which indicates that the search results _must_ be an entity of this type, e.g. [`Q5`](https://www.wikidata.org/wiki/Q5) for humans",
],
[
"notInstanceof",
"A list of Q-identifiers which indicates that the search results _must not_ be an entity of this type, e.g. [`Q79007`](https://www.wikidata.org/wiki/Q79007) to filter away all streets from the search results",
],
]
),
]),
],
]
),
new Title("Example usage"),
`The following is the 'freeform'-part of a layer config which will trigger a search for the wikidata item corresponding with the name of the selected feature. It will also remove '-street', '-square', ... if found at the end of the name
\`\`\`json
"freeform": {
"key": "name:etymology:wikidata",
"type": "wikidata",
"helperArgs": [
"name",
{
"removePostfixes": {"en": [
"street",
"boulevard",
"path",
"square",
"plaza",
],
"nl": ["straat","plein","pad","weg",laan"],
"fr":["route (de|de la|de l'| de le)"]
},
"#": "Remove streets and parks from the search results:"
"notInstanceOf": ["Q79007","Q22698"]
}
]
}
\`\`\`
Another example is to search for species and trees:
\`\`\`json
"freeform": {
"key": "species:wikidata",
"type": "wikidata",
"helperArgs": [
"species",
{
"instanceOf": [10884, 16521]
}]
}
\`\`\`
`,
])
private static readonly _searchCache = new Map<string, Promise<WikidataResponse[]>>()
private readonly wikidataId: UIEventSource<string>
private readonly searchText: UIEventSource<string>
private readonly instanceOf?: number[]
private readonly notInstanceOf?: number[]
constructor(options?: {
searchText?: UIEventSource<string>
value?: UIEventSource<string>
notInstanceOf?: number[]
instanceOf?: number[]
}) {
super()
this.searchText = options?.searchText
this.wikidataId = options?.value ?? new UIEventSource<string>(undefined)
this.instanceOf = options?.instanceOf
this.notInstanceOf = options?.notInstanceOf
}
GetValue(): UIEventSource<string> {
return this.wikidataId
}
IsValid(t: string): boolean {
return t.startsWith("Q") && !isNaN(Number(t.substring(1)))
}
protected InnerConstructElement(): HTMLElement {
const searchField = new TextField({
placeholder: Translations.t.general.wikipedia.searchWikidata,
value: this.searchText,
inputStyle: "width: calc(100% - 0.5rem); border: 1px solid black",
})
const selectedWikidataId = this.wikidataId
const tooShort = new ImmutableStore<{ success: WikidataResponse[] }>({ success: undefined })
const searchResult: Store<{ success?: WikidataResponse[]; error?: any }> = searchField
.GetValue()
.bind((searchText) => {
if (searchText.length < 3 && !searchText.match(/[qQ][0-9]+/)) {
return tooShort
}
const lang = Locale.language.data
const key = lang + ":" + searchText
let promise = WikidataSearchBox._searchCache.get(key)
if (promise === undefined) {
promise = Wikidata.searchAndFetch(searchText, {
lang,
maxCount: 5,
notInstanceOf: this.notInstanceOf,
instanceOf: this.instanceOf,
})
WikidataSearchBox._searchCache.set(key, promise)
}
return Stores.FromPromiseWithErr(promise)
})
const previews = new VariableUiElement(
searchResult.map(
(searchResultsOrFail) => {
if (searchField.GetValue().data.length === 0) {
return Translations.t.general.wikipedia.doSearch
}
if (searchField.GetValue().data.length < 3) {
return Translations.t.general.wikipedia.searchToShort
}
if (searchResultsOrFail === undefined) {
return new Loading(Translations.t.general.loading)
}
if (searchResultsOrFail.error !== undefined) {
return new Combine([
Translations.t.general.wikipedia.failed.Clone().SetClass("alert"),
searchResultsOrFail.error,
])
}
const searchResults = searchResultsOrFail.success
if (searchResults.length === 0) {
return Translations.t.general.wikipedia.noResults.Subs({
search: searchField.GetValue().data ?? "",
})
}
return new Combine(
searchResults.map((wikidataresponse) => {
const el = WikidataPreviewBox.WikidataResponsePreview(
wikidataresponse
).SetClass(
"rounded-xl p-1 sm:p-2 md:p-3 m-px border-2 sm:border-4 transition-colors"
)
el.onClick(() => {
selectedWikidataId.setData(wikidataresponse.id)
})
selectedWikidataId.addCallbackAndRunD((selected) => {
if (selected === wikidataresponse.id) {
el.SetClass("subtle-background border-attention")
} else {
el.RemoveClass("subtle-background")
el.RemoveClass("border-attention")
}
})
return el
})
).SetClass("flex flex-col")
},
[searchField.GetValue()]
)
)
return new Combine([
new Title(Translations.t.general.wikipedia.searchWikidata, 3).SetClass("m-2"),
new Combine([
new SvelteUIElement(Search).SetClass("w-6"),
searchField.SetClass("m-2 w-full"),
]).SetClass("flex"),
previews,
])
.SetClass("flex flex-col border-2 border-black rounded-xl m-2 p-2")
.ConstructElement()
}
}

View file

@ -0,0 +1,42 @@
<script lang="ts">
import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata"
import { Translation } from "../i18n/Translation"
import { WikimediaImageProvider } from "../../Logic/ImageProviders/WikimediaImageProvider"
import { default as Wikidata_icon } from "../../assets/svg/Wikidata.svelte"
import WikidataQuickfacts from "./WikidataQuickfacts.svelte"
import Tr from "../Base/Tr.svelte"
export let wikidata: WikidataResponse
export let imageStyle: string = "max-width: 5rem; width: unset; height: 4rem"
let imageProperty: string | undefined = Array.from(wikidata?.claims?.get("P18") ?? [])[0]
let imageUrl = WikimediaImageProvider.singleton.PrepUrl(imageProperty)?.url
</script>
<div class="flex w-full p-2 flex-wrap">
{#if imageUrl}
<img src={imageUrl} style={imageStyle} class="mr-2" />
{/if}
<div class="flex flex-col flex-grow">
<div class="flex w-full justify-between flex-wrap">
<Tr cls="font-bold" t={ Translation.fromMap(wikidata.labels) } />
<a href={Wikidata.IdToArticle(wikidata.id)} target="_blank" class="flex must-link items-center">
<Wikidata_icon class="w-10" /> {wikidata.id}
</a>
</div>
<Tr t={ Translation.fromMap(wikidata.descriptions, true)} />
<div class="flex">
<WikidataQuickfacts {wikidata} />
</div>
<slot name="extra"></slot>
</div>
</div>

View file

@ -0,0 +1,35 @@
<script lang="ts">
import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata"
import Translations from "../i18n/Translations"
import { FixedUiElement } from "../Base/FixedUiElement"
import { Store } from "../../Logic/UIEventSource"
import Wikidatapreview from "./Wikidatapreview.svelte"
import Tr from "../Base/Tr.svelte"
import Loading from "../Base/Loading.svelte"
export let wikidataId: Store<string>
export let imageStyle: string = undefined
let wikidata: Store<{ success: WikidataResponse } | { error: any }> = wikidataId.stabilized(100).bind((id) => {
if (id === undefined || id === "" || id === "Q") {
return null
}
return Wikidata.LoadWikidataEntry(id)
})
</script>
{#if $wikidata === undefined}
<Loading>
<Tr t={Translations.t.general.loading} />
</Loading>
{:else if $wikidata["error"]}
<div class="alert">
{$wikidata["error"]}
</div>
{:else}
<Wikidatapreview {imageStyle} wikidata={$wikidata["success"]}>
<slot name="extra" slot="extra" />
</Wikidatapreview>
{/if}

View file

@ -3,13 +3,11 @@
import { Store } from "../../Logic/UIEventSource"
import FromHtml from "../Base/FromHtml.svelte"
import Loading from "../Base/Loading.svelte"
import { Disclosure, DisclosureButton, DisclosurePanel } from "@rgossiaux/svelte-headlessui"
import { ChevronRightIcon } from "@rgossiaux/svelte-heroicons/solid"
import ToSvelte from "../Base/ToSvelte.svelte"
import WikidataPreviewBox from "./WikidataPreviewBox"
import Tr from "../Base/Tr.svelte"
import Translations from "../i18n/Translations"
import Wikipedia from "../../assets/svg/Wikipedia.svelte"
import Wikidatapreview from "./Wikidatapreview.svelte"
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
/**
* Shows a wikipedia-article + wikidata preview for the given item
@ -20,42 +18,33 @@
)
</script>
{#if $titleOnly}
<Loading>{$wikipediaDetails.title}</Loading>
{/if}
{#if $wikipediaDetails.articleUrl}
<a class="flex" href={$wikipediaDetails.articleUrl} rel="noreferrer" target="_blank">
<Wikipedia class="h-6 w-6" />
<Tr t={Translations.t.general.wikipedia.fromWikipedia} />
</a>
{/if}
{#if $wikipediaDetails.wikidata}
<ToSvelte
construct={() => WikidataPreviewBox.WikidataResponsePreview($wikipediaDetails.wikidata)}
/>
{/if}
{#if $wikipediaDetails.articleUrl}
{#if $wikipediaDetails.firstParagraph === "" || $wikipediaDetails.firstParagraph === undefined}
<Loading>
<Tr t={Translations.t.general.wikipedia.loading} />
</Loading>
{:else}
<FromHtml clss="wikipedia-article" src={$wikipediaDetails.firstParagraph} />
<Disclosure let:open>
<DisclosureButton>
<span class="flex">
<ChevronRightIcon
style={(open ? "transform: rotate(90deg); " : "") +
" transition: all .25s linear; width: 1.5rem; height: 1.5rem"}
/>
<Tr t={Translations.t.general.wikipedia.readMore} />
</span>
</DisclosureButton>
<DisclosurePanel>
<FromHtml clss="wikipedia-article" src={$wikipediaDetails.restOfArticle} />
</DisclosurePanel>
</Disclosure>
<div class="low-interaction border-gray-300 border-dashed rounded-xl p-2 flex flex-col">
{#if $titleOnly}
<Loading>{$wikipediaDetails.title}</Loading>
{/if}
{/if}
{#if $wikipediaDetails.wikidata}
<Wikidatapreview wikidata={$wikipediaDetails.wikidata} />
{/if}
{#if $wikipediaDetails.articleUrl}
{#if $wikipediaDetails.firstParagraph === "" || $wikipediaDetails.firstParagraph === undefined}
<Loading>
<Tr t={Translations.t.general.wikipedia.loading} />
</Loading>
{:else}
<FromHtml clss="wikipedia-article" src={$wikipediaDetails.firstParagraph} />
{#if $wikipediaDetails.articleUrl}
<a class="flex self-end my-2" href={$wikipediaDetails.articleUrl} rel="noreferrer" target="_blank">
<Wikipedia class="h-6 w-6" />
<Tr t={Translations.t.general.wikipedia.fromWikipedia} />
</a>
{/if}
<AccordionSingle>
<Tr slot="header" t={Translations.t.general.wikipedia.readMore} />
<FromHtml clss="wikipedia-article" src={$wikipediaDetails.restOfArticle} />
</AccordionSingle>
{/if}
{/if}
</div>

View file

@ -26,9 +26,7 @@ export class Translation extends BaseUIElement {
) {
super()
this._strictLanguages = strictLanguages
if (strictLanguages) {
console.log(">>> strict:", translations)
}
if (translations === undefined) {
console.error("Translation without content at " + context)
throw `Translation without content (${context})`
@ -138,7 +136,6 @@ export class Translation extends BaseUIElement {
static fromMap(transl: Map<string, string>, strictLanguages: boolean = false) {
const translations = {}
console.log("Strict:", strictLanguages)
let hasTranslation = false
transl?.forEach((value, key) => {
translations[key] = value

View file

@ -382,13 +382,15 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
/**
* Creates a new array with all elements from 'arr' in such a way that every element will be kept only once
* Elements are returned in the same order as they appear in the lists
* @param arr
* @constructor
* Elements are returned in the same order as they appear in the lists.
* Null/Undefined is returned as is. If an emtpy array is given, a new empty array will be returned
*/
public static Dedup(arr: NonNullable<string[]>): NonNullable<string[]>
public static Dedup(arr: undefined):undefined
public static Dedup(arr: string[] | undefined): string[] | undefined
public static Dedup(arr: string[]): string[] {
if (arr === undefined) {
return undefined
if (arr === undefined || arr === null) {
return arr
}
const newArr = []
for (const string of arr) {
@ -1265,13 +1267,21 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
return track[str2.length][str1.length]
}
public static MapToObj<V>(
d: Map<string, V>
): Record<string, V>;
public static MapToObj<V, T>(
d: Map<string, V>,
onValue: (t: V, key: string) => T
): Record<string, T>
public static MapToObj<V, T>(
d: Map<string, V>,
onValue: (t: V, key: string) => T = undefined
): Record<string, T> {
const o = {}
const keys = Array.from(d.keys())
keys.sort()
onValue ??= (v => <any> v)
for (const key of keys) {
o[key] = onValue(d.get(key), key)
}

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 163.890625 344.988281 C 158.277344 356.675781 141.632812 356.675781 136.019531 344.988281 L 41.4375 148.097656 C 36.507812 137.839844 43.988281 125.953125 55.375 125.953125 L 244.535156 125.953125 C 255.917969 125.953125 263.398438 137.839844 258.46875 148.097656 Z M 163.890625 344.988281 "/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 303 151.453125 C 303 235.101562 235.171875 302.910156 151.5 302.910156 C 67.828125 302.910156 0 235.101562 0 151.453125 C 0 67.808594 67.828125 0 151.5 0 C 235.171875 0 303 67.808594 303 151.453125 Z M 303 151.453125 "/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.101015 291.358766 L 5.785842 275.043593 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.125279 274.965231 L 5.810459 291.28005 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 163.890625 344.988281 C 158.277344 356.675781 141.632812 356.675781 136.019531 344.988281 L 41.4375 148.097656 C 36.507812 137.839844 43.988281 125.953125 55.375 125.953125 L 244.535156 125.953125 C 255.917969 125.953125 263.398438 137.839844 258.46875 148.097656 Z M 163.890625 344.988281 "/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 303 151.453125 C 303 235.101562 235.171875 302.910156 151.5 302.910156 C 67.828125 302.910156 0 235.101562 0 151.453125 C 0 67.808594 67.828125 0 151.5 0 C 235.171875 0 303 67.808594 303 151.453125 Z M 303 151.453125 "/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.101015 291.358766 L 5.785842 275.043593 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> <path style="fill: none !important;stroke-width:7.514114;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 22.125279 274.965231 L 5.810459 291.28005 " transform="matrix(4.837809,-4.836357,4.837809,4.836357,-1287.063942,-1153.71106)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill-rule:nonzero;fill:rgb(21.568628%,83.92157%,28.627452%);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(37.64706%,37.64706%,37.64706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 98 49.021438 C 98 76.083729 76.062292 98.021438 49 98.021438 C 21.937708 98.021438 0 76.083729 0 49.021438 C 0 21.959146 21.937708 0.0214375 49 0.0214375 C 76.062292 0.0214375 98 21.959146 98 49.021438 Z M 98 49.021438 " transform="matrix(3.826531,0,0,3.826531,0,0)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 185.398438 53.390625 C 176.808594 53.523438 168.636719 57.125 162.738281 63.378906 C 157.074219 69.394531 153.96875 77.378906 154.085938 85.640625 L 154.085938 152.132812 L 88.527344 152.132812 C 79.929688 152.011719 71.644531 155.371094 65.566406 161.453125 C 56.40625 170.613281 53.710938 184.414062 58.761719 196.347656 C 63.808594 208.28125 75.585938 215.960938 88.539062 215.765625 L 154.085938 215.765625 L 154.085938 281.003906 C 153.898438 292.488281 159.917969 303.183594 169.835938 308.984375 C 179.753906 314.785156 192.027344 314.785156 201.945312 308.992188 C 211.863281 303.199219 217.890625 292.503906 217.707031 281.019531 L 217.707031 215.765625 L 283.894531 215.765625 C 295.296875 215.820312 305.855469 209.769531 311.574219 199.90625 C 317.292969 190.042969 317.296875 177.871094 311.582031 168.007812 C 305.871094 158.140625 295.3125 152.085938 283.910156 152.132812 L 217.703125 152.132812 L 217.703125 85.640625 C 217.820312 77.042969 214.453125 68.765625 208.367188 62.6875 C 202.28125 56.613281 193.996094 53.261719 185.398438 53.390625 Z M 185.398438 53.390625 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill-rule:nonzero;fill:rgb(21.568628%,83.92157%,28.627452%);fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(37.64706%,37.64706%,37.64706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 98 49.021438 C 98 76.083729 76.062292 98.021438 49 98.021438 C 21.937708 98.021438 0 76.083729 0 49.021438 C 0 21.959146 21.937708 0.0214375 49 0.0214375 C 76.062292 0.0214375 98 21.959146 98 49.021438 Z M 98 49.021438 " transform="matrix(3.826531,0,0,3.826531,0,0)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 185.398438 53.390625 C 176.808594 53.523438 168.636719 57.125 162.738281 63.378906 C 157.074219 69.394531 153.96875 77.378906 154.085938 85.640625 L 154.085938 152.132812 L 88.527344 152.132812 C 79.929688 152.011719 71.644531 155.371094 65.566406 161.453125 C 56.40625 170.613281 53.710938 184.414062 58.761719 196.347656 C 63.808594 208.28125 75.585938 215.960938 88.539062 215.765625 L 154.085938 215.765625 L 154.085938 281.003906 C 153.898438 292.488281 159.917969 303.183594 169.835938 308.984375 C 179.753906 314.785156 192.027344 314.785156 201.945312 308.992188 C 211.863281 303.199219 217.890625 292.503906 217.707031 281.019531 L 217.707031 215.765625 L 283.894531 215.765625 C 295.296875 215.820312 305.855469 209.769531 311.574219 199.90625 C 317.292969 190.042969 317.296875 177.871094 311.582031 168.007812 C 305.871094 158.140625 295.3125 152.085938 283.910156 152.132812 L 217.703125 152.132812 L 217.703125 85.640625 C 217.820312 77.042969 214.453125 68.765625 208.367188 62.6875 C 202.28125 56.613281 193.996094 53.261719 185.398438 53.390625 Z M 185.398438 53.390625 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 151.5 0 C 67.828125 0 0 67.808594 0 151.453125 C 0.0742188 203.539062 26.914062 251.933594 71.0625 279.589844 C 83.773438 287.726562 98.976562 305.320312 111.8125 321.363281 C 125.679688 338.699219 133.386719 374.292969 150.203125 374.5625 C 167.015625 374.292969 174.730469 338.699219 188.597656 321.363281 C 199.703125 307.480469 211.496094 292.414062 224.496094 283.984375 C 272.859375 257.398438 302.933594 206.628906 303 151.453125 C 303 67.808594 235.171875 0 151.5 0 Z M 151.5 0 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="303px" height="374px" viewBox="0 0 303 374" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(43.921569%,77.254903%,28.627452%);fill-opacity:1;" d="M 151.5 0 C 67.828125 0 0 67.808594 0 151.453125 C 0.0742188 203.539062 26.914062 251.933594 71.0625 279.589844 C 83.773438 287.726562 98.976562 305.320312 111.8125 321.363281 C 125.679688 338.699219 133.386719 374.292969 150.203125 374.5625 C 167.015625 374.292969 174.730469 338.699219 188.597656 321.363281 C 199.703125 307.480469 211.496094 292.414062 224.496094 283.984375 C 272.859375 257.398438 302.933594 206.628906 303 151.453125 C 303 67.808594 235.171875 0 151.5 0 Z M 151.5 0 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:5.291667;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 14.287499 23.618748 L 4.143209 13.229167 L 14.287499 2.871556 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> <path style="fill: none !important;stroke-width:3.96875;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 5.532271 13.229167 C 12.346946 13.21704 23.467714 13.190031 23.8125 13.200504 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:5.291667;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 14.287499 23.618748 L 4.143209 13.229167 L 14.287499 2.871556 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> <path style="fill: none !important;stroke-width:3.96875;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 5.532271 13.229167 C 12.346946 13.21704 23.467714 13.190031 23.8125 13.200504 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,0)"/> </g> </svg>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="268px" height="373px" viewBox="0 0 268 373" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 88.972656 57.019531 C 69.667969 77.699219 74.996094 110.734375 74.996094 110.734375 C 74.996094 110.734375 94.699219 134.046875 133.414062 134.046875 C 172.128906 134.046875 191.84375 110.734375 191.84375 110.734375 C 191.84375 110.734375 197.09375 78.144531 178.199219 57.4375 C 190.019531 50.871094 196.980469 41.378906 194.105469 34.921875 C 190.839844 27.648438 176.441406 27 161.882812 33.476562 C 156.472656 35.878906 151.863281 38.929688 148.28125 42.175781 C 143.742188 41.355469 138.925781 40.796875 133.414062 40.796875 C 128.28125 40.796875 123.714844 41.285156 119.414062 41.980469 C 115.886719 38.792969 111.359375 35.835938 106.074219 33.476562 C 91.515625 27.023438 77.09375 27.671875 73.851562 34.921875 C 71.023438 41.242188 77.609375 50.472656 88.972656 57.019531 Z M 235.433594 207.535156 C 232.417969 206.898438 229.542969 206.535156 226.761719 206.261719 C 226.761719 205.488281 226.898438 204.757812 226.898438 203.960938 C 226.898438 191.726562 225.164062 180.046875 222.355469 168.949219 C 228.359375 169.460938 236.003906 168.082031 243.738281 164.65625 C 258.296875 158.179688 267.472656 147.035156 264.230469 139.808594 C 260.992188 132.535156 246.566406 131.886719 232.007812 138.363281 C 225.207031 141.390625 219.664062 145.453125 215.945312 149.621094 C 213.113281 142.972656 209.917969 136.585938 206.152344 130.78125 C 195.132812 139.945312 174.273438 153.625 145.15625 156.664062 L 145.15625 273.875 C 145.15625 273.875 145.0625 285.53125 133.460938 285.53125 C 121.867188 285.53125 121.777344 273.875 121.777344 273.875 L 121.777344 156.710938 C 92.636719 153.671875 71.765625 139.964844 60.765625 130.824219 C 57.160156 136.402344 54.058594 142.480469 51.296875 148.800781 C 47.542969 144.929688 42.304688 141.207031 35.972656 138.382812 C 21.414062 131.929688 6.992188 132.578125 3.75 139.828125 C 0.5 147.082031 9.683594 158.203125 24.242188 164.679688 C 31.488281 167.902344 38.675781 169.347656 44.496094 169.085938 C 41.699219 180.160156 39.941406 191.792969 39.941406 203.984375 C 39.941406 204.78125 40.082031 205.535156 40.101562 206.351562 C 37.648438 206.625 35.105469 206.992188 32.515625 207.535156 C 13.539062 211.453125 -0.996094 221.242188 0.078125 229.324219 C 1.148438 237.453125 17.421875 240.796875 36.441406 236.859375 C 38.917969 236.359375 41.347656 235.722656 43.664062 235.015625 C 47.007812 249.882812 52.359375 263.675781 59.761719 275.5625 C 55.371094 277.769531 50.804688 281.023438 46.605469 285.257812 C 34.96875 296.871094 30.246094 310.984375 36.0625 316.789062 C 41.882812 322.597656 56.019531 317.882812 67.660156 306.296875 C 71.070312 302.878906 73.808594 299.285156 75.929688 295.730469 C 91.824219 311.257812 111.734375 320.546875 133.460938 320.546875 C 155.492188 320.546875 175.734375 310.984375 191.707031 295.070312 C 193.855469 298.828125 196.730469 302.652344 200.335938 306.25 C 211.949219 317.859375 226.121094 322.574219 231.941406 316.769531 C 237.757812 310.960938 233.035156 296.871094 221.398438 285.257812 C 216.902344 280.75 212.019531 277.335938 207.363281 275.082031 C 214.710938 263.246094 220.003906 249.449219 223.316406 234.628906 C 225.9375 235.445312 228.675781 236.222656 231.550781 236.835938 C 250.5625 240.773438 266.832031 237.40625 267.925781 229.300781 C 268.953125 221.242188 254.417969 211.453125 235.433594 207.535156 Z M 235.433594 207.535156 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="268px" height="373px" viewBox="0 0 268 373" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 88.972656 57.019531 C 69.667969 77.699219 74.996094 110.734375 74.996094 110.734375 C 74.996094 110.734375 94.699219 134.046875 133.414062 134.046875 C 172.128906 134.046875 191.84375 110.734375 191.84375 110.734375 C 191.84375 110.734375 197.09375 78.144531 178.199219 57.4375 C 190.019531 50.871094 196.980469 41.378906 194.105469 34.921875 C 190.839844 27.648438 176.441406 27 161.882812 33.476562 C 156.472656 35.878906 151.863281 38.929688 148.28125 42.175781 C 143.742188 41.355469 138.925781 40.796875 133.414062 40.796875 C 128.28125 40.796875 123.714844 41.285156 119.414062 41.980469 C 115.886719 38.792969 111.359375 35.835938 106.074219 33.476562 C 91.515625 27.023438 77.09375 27.671875 73.851562 34.921875 C 71.023438 41.242188 77.609375 50.472656 88.972656 57.019531 Z M 235.433594 207.535156 C 232.417969 206.898438 229.542969 206.535156 226.761719 206.261719 C 226.761719 205.488281 226.898438 204.757812 226.898438 203.960938 C 226.898438 191.726562 225.164062 180.046875 222.355469 168.949219 C 228.359375 169.460938 236.003906 168.082031 243.738281 164.65625 C 258.296875 158.179688 267.472656 147.035156 264.230469 139.808594 C 260.992188 132.535156 246.566406 131.886719 232.007812 138.363281 C 225.207031 141.390625 219.664062 145.453125 215.945312 149.621094 C 213.113281 142.972656 209.917969 136.585938 206.152344 130.78125 C 195.132812 139.945312 174.273438 153.625 145.15625 156.664062 L 145.15625 273.875 C 145.15625 273.875 145.0625 285.53125 133.460938 285.53125 C 121.867188 285.53125 121.777344 273.875 121.777344 273.875 L 121.777344 156.710938 C 92.636719 153.671875 71.765625 139.964844 60.765625 130.824219 C 57.160156 136.402344 54.058594 142.480469 51.296875 148.800781 C 47.542969 144.929688 42.304688 141.207031 35.972656 138.382812 C 21.414062 131.929688 6.992188 132.578125 3.75 139.828125 C 0.5 147.082031 9.683594 158.203125 24.242188 164.679688 C 31.488281 167.902344 38.675781 169.347656 44.496094 169.085938 C 41.699219 180.160156 39.941406 191.792969 39.941406 203.984375 C 39.941406 204.78125 40.082031 205.535156 40.101562 206.351562 C 37.648438 206.625 35.105469 206.992188 32.515625 207.535156 C 13.539062 211.453125 -0.996094 221.242188 0.078125 229.324219 C 1.148438 237.453125 17.421875 240.796875 36.441406 236.859375 C 38.917969 236.359375 41.347656 235.722656 43.664062 235.015625 C 47.007812 249.882812 52.359375 263.675781 59.761719 275.5625 C 55.371094 277.769531 50.804688 281.023438 46.605469 285.257812 C 34.96875 296.871094 30.246094 310.984375 36.0625 316.789062 C 41.882812 322.597656 56.019531 317.882812 67.660156 306.296875 C 71.070312 302.878906 73.808594 299.285156 75.929688 295.730469 C 91.824219 311.257812 111.734375 320.546875 133.460938 320.546875 C 155.492188 320.546875 175.734375 310.984375 191.707031 295.070312 C 193.855469 298.828125 196.730469 302.652344 200.335938 306.25 C 211.949219 317.859375 226.121094 322.574219 231.941406 316.769531 C 237.757812 310.960938 233.035156 296.871094 221.398438 285.257812 C 216.902344 280.75 212.019531 277.335938 207.363281 275.082031 C 214.710938 263.246094 220.003906 249.449219 223.316406 234.628906 C 225.9375 235.445312 228.675781 236.222656 231.550781 236.835938 C 250.5625 240.773438 266.832031 237.40625 267.925781 229.300781 C 268.953125 221.242188 254.417969 211.453125 235.433594 207.535156 Z M 235.433594 207.535156 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="544.02838" height="544.02838" viewBox="0 0 544.02838 544.02838" version="1.1" id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <path d="m 365.63918,111.75001 h -62.375 V 15.9375 c 0,-8.75 -7,-15.9375 -15.625,-15.9375 h -31.1875 c -8.5625,0 -15.625,7.1875 -15.625,15.9375 v 95.81251 h -62.375 l 93.5625,127.75 z" id="path1" style="fill:{color};fill-opacity:1" /> <path d="m 432.27837,365.63919 v -62.375 h 95.8125 c 8.75,0 15.9375,-7 15.9375,-15.625 v -31.1875 c 0,-8.5625 -7.1875,-15.625 -15.9375,-15.625 h -95.8125 v -62.375 l -127.75,93.5625 z" id="path1-5" style="fill:{color};fill-opacity:1" /> <path d="m 178.38918,432.27838 h 62.375 v 95.8125 c 0,8.75 7,15.9375 15.625,15.9375 h 31.1875 c 8.5625,0 15.625,-7.1875 15.625,-15.9375 v -95.8125 h 62.375 l -93.5625,-127.75 z" id="path2" style="fill:{color};fill-opacity:1" /> <path d="m 111.75,178.38919 v 62.375 H 15.9375 c -8.75,0 -15.9375,7 -15.9375,15.625 v 31.1875 c 0,8.5625 7.1875,15.625 15.9375,15.625 H 111.75 v 62.375 l 127.74999,-93.5625 z" id="path3" style="fill:{color};fill-opacity:1" /> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="544.02838" height="544.02838" viewBox="0 0 544.02838 544.02838" version="1.1" id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <path d="m 365.63918,111.75001 h -62.375 V 15.9375 c 0,-8.75 -7,-15.9375 -15.625,-15.9375 h -31.1875 c -8.5625,0 -15.625,7.1875 -15.625,15.9375 v 95.81251 h -62.375 l 93.5625,127.75 z" id="path1" style="fill:{color};fill-opacity:1" /> <path d="m 432.27837,365.63919 v -62.375 h 95.8125 c 8.75,0 15.9375,-7 15.9375,-15.625 v -31.1875 c 0,-8.5625 -7.1875,-15.625 -15.9375,-15.625 h -95.8125 v -62.375 l -127.75,93.5625 z" id="path1-5" style="fill:{color};fill-opacity:1" /> <path d="m 178.38918,432.27838 h 62.375 v 95.8125 c 0,8.75 7,15.9375 15.625,15.9375 h 31.1875 c 8.5625,0 15.625,-7.1875 15.625,-15.9375 v -95.8125 h 62.375 l -93.5625,-127.75 z" id="path2" style="fill:{color};fill-opacity:1" /> <path d="m 111.75,178.38919 v 62.375 H 15.9375 c -8.75,0 -15.9375,7 -15.9375,15.625 v 31.1875 c 0,8.5625 7.1875,15.625 15.9375,15.625 H 111.75 v 62.375 l 127.74999,-93.5625 z" id="path3" style="fill:{color};fill-opacity:1" /> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="374px" height="259px" viewBox="0 0 374 259" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 2.999896 7.285624 L 10.826182 14.99991 L 23.000104 3.00009 " transform="matrix(14.384615,0,0,14.388889,0,0)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="374px" height="259px" viewBox="0 0 374 259" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 2.999896 7.285624 L 10.826182 14.99991 L 23.000104 3.00009 " transform="matrix(14.384615,0,0,14.388889,0,0)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg1" sodipodi:docname="circle.svg" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="2.056" inkscape:cx="187.5" inkscape:cy="187.5" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <path style="fill:{color}" class="selectable" d="M 375,187.5 C 375,291.05469 291.05469,375 187.5,375 83.945312,375 0,291.05469 0,187.5 0,83.945312 83.945312,0 187.5,0 291.05469,0 375,83.945312 375,187.5 Z m 0,0" id="path1" /> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg1" sodipodi:docname="circle.svg" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="2.056" inkscape:cx="187.5" inkscape:cy="187.5" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <path style="fill:{color}" class="selectable" d="M 375,187.5 C 375,291.05469 291.05469,375 187.5,375 83.945312,375 0,291.05469 0,187.5 0,83.945312 83.945312,0 187.5,0 291.05469,0 375,83.945312 375,187.5 Z m 0,0" id="path1" /> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.932292 L 66.551042 55.932292 " transform="matrix(3.75,0,0,3.75,0,0)"/> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.534375 L 46 27.729167 " transform="matrix(3.75,0,0,3.75,0,0)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.932292 L 66.551042 55.932292 " transform="matrix(3.75,0,0,3.75,0,0)"/> <path style="fill: none !important;stroke-width:9;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 46 55.534375 L 46 27.729167 " transform="matrix(3.75,0,0,3.75,0,0)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.165924 293.603402 L 3.541282 273.978759 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:6.012921;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.195414 273.884226 L 3.571047 293.508593 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:6.012842;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.165924 293.603402 L 3.541282 273.978759 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:6.012921;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 23.195414 273.884226 L 3.571047 293.508593 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="1124.975mm" height="1111.9373mm" viewBox="0 0 1124.975 1111.9373" version="1.1" id="svg5" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs2" /> <g id="layer1" transform="translate(429.38456,373.85159)" style="display:inline"> <path id="path858" d="m 465.50195,-1412.9824 c -48.13018,0 -95.14167,6.6605 -140.92968,19.3242 -517.78906,36.4545 -1004.59215,263.4542 -1364.78127,639.11132 -125.578,130.97093 -232.0356,276.80492 -318.709,432.875 l -3.0996,0.006 0.012,5.62891 c -169.1451,306.7883664 -260.6208,653.52706 -260.8652,1009.62695 v 0.0645 c 0,555.45592 220.6943,1088.26072 613.4609,1481.02732 378.0703,378.0702 885.96964,596.0875 1418.85161,611.92 18.51351,1.9864 37.20113,3.0136 56.06054,3.0136 17.25834,0 34.36078,-0.9283 51.33008,-2.5937 224.45873,-4.8504 444.64455,-45.7063 652.83597,-119.1836 -60.8675,-43.0776 -118.1478,-91.0122 -171.27933,-143.334 -121.72268,40.4323 -230.24225,90.5328 -428.68164,58.6602 l -3.38086,-1775.19732 233.78516,-0.44532 c 42.42213,-67.09791 90.54812,-130.41487 143.84375,-189.24804 l -377.98828,0.7207 -1.43946,-755.89648 634.26176,-1.38672 c 32.7782,154.928763 56.3858,319.47347 69.9629,489.41797 58.6612,-33.17515 119.6711,-62.01386 182.541,-86.28516 -13.1747,-138.65014 -32.7954,-273.7956044 -58.7852,-403.55664 l 791.918,-1.73242 c 54.2995,111.507047 97.5037,228.170813 129.2012,348.26953 72.3897,18.82425 143.1313,43.49582 211.5273,73.77148 -80.6791,-402.00209 -278.3137,-774.77273 -572.5098,-1068.96875 -363.7812,-363.78173 -847.7515,-579.57553 -1358.52731,-609.49993 -41.8967,-10.5343 -84.78727,-16.1094 -128.61524,-16.1094 z m 96.98438,204.4375 c 159.67283,49.2174 326.54513,218.8615 462.03907,516.93552 49.6393,109.20202 92.1295,232.60044 128.4531,364.44727 l -588.81053,1.28711 z m -188.97461,0.9179 1.67969,882.16411 -597.98243,1.30664 c 36.4911,-132.99204 79.25432,-257.42426 129.269536,-367.45313 133.780665,-294.30513 298.164144,-463.66612 455.992184,-515.27932 3.68603,-0.2115 7.36574,-0.4597 11.04102,-0.7383 z m 591.27148,61.1954 c 320.2851,85.8427 615.6781,254.12924 854.2344,492.68551 99.0716,99.07158 185.6177,208.20254 259.6738,324.5625 l -729.584,1.59375 c -41.2536,-159.09493 -91.7465,-308.46744 -152.5469,-442.22266 -67.1207,-147.65948 -144.9895,-275.0596 -231.7773,-376.6191 z m -1003.50195,5.9433 c -84.79247,100.5848 -161.00089,225.84047 -226.83789,370.6758 -61.29809,134.85015 -112.17438,285.51379 -153.59961,446.08594 l -720.14645,1.57422 c 67.8012,-107.37947 146.33969,-208.61822 235.49997,-301.60743 238.54174,-248.78579 538.10225,-425.81263 865.08398,-516.72853 z m 414.26953,1004.00002 1.43945,755.8418 -727.68554,1.38671 c 4.20418,-264.24481 32.77031,-520.983169 82.2207,-755.82031 z m -837.92773,1.83203 c -47.33699,237.75431 -73.46184,493.4318 -77.33789,755.75781 l -892.42186,1.70117 c 10.0141,-264.11069 74.8439,-521.07351 188.0937,-755.75 z m 839.72656,942.98437 1.3457,707.00198 -646.08984,1.414 c -46.71986,-220.2353 -75.01919,-459.8106 -82.07617,-707.03121 z m -915.85156,1.74415 c 6.57514,245.41033 32.61831,484.16193 77.38867,707.09573 l -784.53902,1.7148 c -105.8005,-220.1735 -168.8074,-460.0874 -184.1446,-707.11327 z m 917.55859,894.23433 1.68359,884.2715 C 217.38802,2544.4462 45.439072,2373.9426 -93.521484,2068.2422 -142.93255,1959.5424 -185.25941,1836.7732 -221.48047,1705.6211 Z m -796.66211,1.7422 c 41.17164,158.3984 91.48351,307.1603 152.04883,440.3985 69.28935,152.4302 150.07483,283.1451 240.259765,386.2558 C -344.1327,2446.5457 -638.16035,2278.6776 -875.7832,2041.0547 -977.36504,1939.4729 -1065.801,1827.3298 -1141.0586,1707.6328 Z" transform="scale(0.26458333)" /> <path id="path928" d="" /> <path id="path890" d="" /> <path id="path3123" d="m 500.42418,99.52416 c -162.9348,1.72512 -108.06353,223.75011 -69.65465,274.06343 l 1.09709,35.29034 c -176.038,13.83721 -191.80907,75.90897 -198.43798,158.82719 -2.02223,25.29521 3.89762,50.2628 9.81667,80.72646 97.56502,-0.71585 177.50757,-0.62612 275.07185,-0.49796 84.27329,-45.47436 147.33813,-122.20106 175.63579,-213.68411 -28.16643,-12.43076 -66.9608,-21.14889 -120.68876,-25.37209 l 1.09762,-35.29036 C 613.0731,322.8775 663.35897,97.79884 500.42418,99.52416 Z" /> </g> </svg>
<!-- Created with Inkscape (http://www.inkscape.org/) --> <svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="1124.975mm" height="1111.9373mm" viewBox="0 0 1124.975 1111.9373" version="1.1" id="svg5" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs2" /> <g id="layer1" transform="translate(429.38456,373.85159)" style="display:inline"> <path id="path858" d="m 465.50195,-1412.9824 c -48.13018,0 -95.14167,6.6605 -140.92968,19.3242 -517.78906,36.4545 -1004.59215,263.4542 -1364.78127,639.11132 -125.578,130.97093 -232.0356,276.80492 -318.709,432.875 l -3.0996,0.006 0.012,5.62891 c -169.1451,306.7883664 -260.6208,653.52706 -260.8652,1009.62695 v 0.0645 c 0,555.45592 220.6943,1088.26072 613.4609,1481.02732 378.0703,378.0702 885.96964,596.0875 1418.85161,611.92 18.51351,1.9864 37.20113,3.0136 56.06054,3.0136 17.25834,0 34.36078,-0.9283 51.33008,-2.5937 224.45873,-4.8504 444.64455,-45.7063 652.83597,-119.1836 -60.8675,-43.0776 -118.1478,-91.0122 -171.27933,-143.334 -121.72268,40.4323 -230.24225,90.5328 -428.68164,58.6602 l -3.38086,-1775.19732 233.78516,-0.44532 c 42.42213,-67.09791 90.54812,-130.41487 143.84375,-189.24804 l -377.98828,0.7207 -1.43946,-755.89648 634.26176,-1.38672 c 32.7782,154.928763 56.3858,319.47347 69.9629,489.41797 58.6612,-33.17515 119.6711,-62.01386 182.541,-86.28516 -13.1747,-138.65014 -32.7954,-273.7956044 -58.7852,-403.55664 l 791.918,-1.73242 c 54.2995,111.507047 97.5037,228.170813 129.2012,348.26953 72.3897,18.82425 143.1313,43.49582 211.5273,73.77148 -80.6791,-402.00209 -278.3137,-774.77273 -572.5098,-1068.96875 -363.7812,-363.78173 -847.7515,-579.57553 -1358.52731,-609.49993 -41.8967,-10.5343 -84.78727,-16.1094 -128.61524,-16.1094 z m 96.98438,204.4375 c 159.67283,49.2174 326.54513,218.8615 462.03907,516.93552 49.6393,109.20202 92.1295,232.60044 128.4531,364.44727 l -588.81053,1.28711 z m -188.97461,0.9179 1.67969,882.16411 -597.98243,1.30664 c 36.4911,-132.99204 79.25432,-257.42426 129.269536,-367.45313 133.780665,-294.30513 298.164144,-463.66612 455.992184,-515.27932 3.68603,-0.2115 7.36574,-0.4597 11.04102,-0.7383 z m 591.27148,61.1954 c 320.2851,85.8427 615.6781,254.12924 854.2344,492.68551 99.0716,99.07158 185.6177,208.20254 259.6738,324.5625 l -729.584,1.59375 c -41.2536,-159.09493 -91.7465,-308.46744 -152.5469,-442.22266 -67.1207,-147.65948 -144.9895,-275.0596 -231.7773,-376.6191 z m -1003.50195,5.9433 c -84.79247,100.5848 -161.00089,225.84047 -226.83789,370.6758 -61.29809,134.85015 -112.17438,285.51379 -153.59961,446.08594 l -720.14645,1.57422 c 67.8012,-107.37947 146.33969,-208.61822 235.49997,-301.60743 238.54174,-248.78579 538.10225,-425.81263 865.08398,-516.72853 z m 414.26953,1004.00002 1.43945,755.8418 -727.68554,1.38671 c 4.20418,-264.24481 32.77031,-520.983169 82.2207,-755.82031 z m -837.92773,1.83203 c -47.33699,237.75431 -73.46184,493.4318 -77.33789,755.75781 l -892.42186,1.70117 c 10.0141,-264.11069 74.8439,-521.07351 188.0937,-755.75 z m 839.72656,942.98437 1.3457,707.00198 -646.08984,1.414 c -46.71986,-220.2353 -75.01919,-459.8106 -82.07617,-707.03121 z m -915.85156,1.74415 c 6.57514,245.41033 32.61831,484.16193 77.38867,707.09573 l -784.53902,1.7148 c -105.8005,-220.1735 -168.8074,-460.0874 -184.1446,-707.11327 z m 917.55859,894.23433 1.68359,884.2715 C 217.38802,2544.4462 45.439072,2373.9426 -93.521484,2068.2422 -142.93255,1959.5424 -185.25941,1836.7732 -221.48047,1705.6211 Z m -796.66211,1.7422 c 41.17164,158.3984 91.48351,307.1603 152.04883,440.3985 69.28935,152.4302 150.07483,283.1451 240.259765,386.2558 C -344.1327,2446.5457 -638.16035,2278.6776 -875.7832,2041.0547 -977.36504,1939.4729 -1065.801,1827.3298 -1141.0586,1707.6328 Z" transform="scale(0.26458333)" /> <path id="path928" d="" /> <path id="path890" d="" /> <path id="path3123" d="m 500.42418,99.52416 c -162.9348,1.72512 -108.06353,223.75011 -69.65465,274.06343 l 1.09709,35.29034 c -176.038,13.83721 -191.80907,75.90897 -198.43798,158.82719 -2.02223,25.29521 3.89762,50.2628 9.81667,80.72646 97.56502,-0.71585 177.50757,-0.62612 275.07185,-0.49796 84.27329,-45.47436 147.33813,-122.20106 175.63579,-213.68411 -28.16643,-12.43076 -66.9608,-21.14889 -120.68876,-25.37209 l 1.09762,-35.29036 C 613.0731,322.8775 663.35897,97.79884 500.42418,99.52416 Z" /> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F4900C" cx="18" cy="18" r="18"/><circle fill="#FFD983" cx="18" cy="18" r="14.5"/><circle fill="#F5F8FA" cx="18" cy="18" r="13"/><path fill="#CCD6DD" d="M18 8l1.531 6.304 5.54-3.375-3.375 5.54L28 18l-6.304 1.531 3.375 5.54-5.54-3.375L18 28l-1.531-6.304-5.54 3.375 3.375-5.54L8 18l6.304-1.531-3.375-5.54 5.54 3.375z"/><path fill="#292F33" d="M17.343 20.748l8.777 5.381-5.379-8.778z"/><path fill="#DD2E44" d="M18.657 15.267L9.879 9.886l5.38 8.779z"/><circle fill="#8899A6" cx="18" cy="18.008" r="3.055"/><circle fill="#F5F8FA" cx="18" cy="18.008" r="1.648"/></svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#F4900C" cx="18" cy="18" r="18"/><circle fill="#FFD983" cx="18" cy="18" r="14.5"/><circle fill="#F5F8FA" cx="18" cy="18" r="13"/><path fill="#CCD6DD" d="M18 8l1.531 6.304 5.54-3.375-3.375 5.54L28 18l-6.304 1.531 3.375 5.54-5.54-3.375L18 28l-1.531-6.304-5.54 3.375 3.375-5.54L8 18l6.304-1.531-3.375-5.54 5.54 3.375z"/><path fill="#292F33" d="M17.343 20.748l8.777 5.381-5.379-8.778z"/><path fill="#DD2E44" d="M18.657 15.267L9.879 9.886l5.38 8.779z"/><circle fill="#8899A6" cx="18" cy="18.008" r="3.055"/><circle fill="#F5F8FA" cx="18" cy="18.008" r="1.648"/></svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg1" sodipodi:docname="compass_arrow.svg" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="1.0410569" inkscape:cx="33.139398" inkscape:cy="182.98711" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <path id="rect2" style="fill:{color};stroke:none;stroke-linecap:round;fill-opacity:1;stroke-opacity:1" d="M 16.835505,17.477497 79.869453,33.962116 V 80.511444 H 33.96212 Z" sodipodi:nodetypes="ccccc" /> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg1" sodipodi:docname="compass_arrow.svg" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs1" /> <sodipodi:namedview id="namedview1" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:showpageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:zoom="1.0410569" inkscape:cx="33.139398" inkscape:cy="182.98711" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg1" /> <path id="rect2" style="fill:{color};stroke:none;stroke-linecap:round;fill-opacity:1;stroke-opacity:1" d="M 16.835505,17.477497 79.869453,33.962116 V 80.511444 H 33.96212 Z" sodipodi:nodetypes="ccccc" /> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="157.33984" height="157.33984" viewBox="0 0 157.33984 157.33984" version="1.1" id="svg9" sodipodi:docname="confirm.svg" inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs13" /> <sodipodi:namedview id="namedview11" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.312" inkscape:cx="-18.598616" inkscape:cy="57.093426" inkscape:current-layer="svg9" /> <path style="fill:#35d447;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 157.33984,78.66796 c 0,43.44922 -35.21875,78.67188 -78.66796,78.67188 C 35.22266,157.33984 0,122.11718 0,78.66796 0,35.22265 35.22266,0 78.67188,0 c 43.44921,0 78.66796,35.22265 78.66796,78.66796 z m 0,0" id="path4" /> <path style="fill: none !important;stroke:#ffffff;stroke-width:19.7495;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" d="m 37.69921,75.49609 35.55078,39.5 47.39844,-63.19922" id="path6" /> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="157.33984" height="157.33984" viewBox="0 0 157.33984 157.33984" version="1.1" id="svg9" sodipodi:docname="confirm.svg" inkscape:version="1.1.2 (1:1.1+202202050950+0a00cf5339)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs13" /> <sodipodi:namedview id="namedview11" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.312" inkscape:cx="-18.598616" inkscape:cy="57.093426" inkscape:current-layer="svg9" /> <path style="fill:#35d447;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 157.33984,78.66796 c 0,43.44922 -35.21875,78.67188 -78.66796,78.67188 C 35.22266,157.33984 0,122.11718 0,78.66796 0,35.22265 35.22266,0 78.67188,0 c 43.44921,0 78.66796,35.22265 78.66796,78.66796 z m 0,0" id="path4" /> <path style="fill: none !important;stroke:#ffffff;stroke-width:19.7495;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" d="m 37.69921,75.49609 35.55078,39.5 47.39844,-63.19922" id="path6" /> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg5" sodipodi:docname="copyright.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs9" /> <sodipodi:namedview id="namedview7" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.4012481" inkscape:cx="194.06574" inkscape:cy="30.192632" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg5" /> <g id="surface1" transform="matrix(1.2644961,0,0,1.2644961,-49.593016,-49.593016)"> <path style="fill:{color};fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 159.26562,170.73437 c 0.73438,-4.85156 2.35157,-9.11718 4.41016,-12.79296 2.0625,-3.67579 5,-6.76172 8.67969,-9.11719 3.52734,-2.20313 7.9375,-3.23438 13.3789,-3.37891 3.38282,0.14453 6.47266,0.73438 9.26563,1.91016 2.94141,1.32422 5.58594,3.08594 7.64453,5.29297 2.05859,2.20703 3.67969,4.85156 5,7.79297 1.32422,2.9414 1.91406,6.17578 2.05859,9.41406 h 26.32422 c -0.29297,-6.91406 -1.61718,-13.23438 -4.11718,-18.97266 -2.5,-5.73437 -5.88282,-10.73437 -10.29297,-14.85156 -4.41407,-4.11719 -9.70703,-7.35156 -15.88282,-9.70312 -6.17578,-2.35547 -12.9414,-3.38282 -20.4414,-3.38282 -9.5586,0 -17.9375,1.61719 -24.9961,5 -7.05859,3.38281 -12.9414,7.79297 -17.64843,13.52735 -4.70313,5.73437 -8.23438,12.35156 -10.44141,20 -2.20312,7.64453 -3.52734,15.58593 -3.52734,24.11718 v 3.96875 c 0,8.52735 1.17578,16.46875 3.38281,24.11719 2.20312,7.64453 5.73437,14.26172 10.44141,19.85156 4.70312,5.58594 10.58593,10.14453 17.64453,13.38282 7.05859,3.23437 15.4414,5 25,5 6.91015,0 13.3789,-1.17969 19.41015,-3.38282 6.02735,-2.20703 11.32422,-5.29687 15.87891,-9.26562 4.55859,-3.96875 8.23828,-8.52735 10.88281,-13.82422 2.64844,-5.29297 4.26563,-10.87891 4.41406,-16.91016 h -26.32421 c -0.14454,3.08985 -0.88282,5.88282 -2.20704,8.53125 -1.32031,2.64453 -3.08593,4.85157 -5.29296,6.76172 -2.20313,1.91406 -4.70313,3.38281 -7.64454,4.41406 -2.79687,1.02735 -5.73437,1.32032 -8.82421,1.46875 -5.29297,-0.14843 -9.70704,-1.17578 -13.08594,-3.38281 -3.67969,-2.35156 -6.61719,-5.4414 -8.67969,-9.11719 -2.05859,-3.67578 -3.67578,-8.08593 -4.41016,-12.9375 -0.73437,-4.85546 -1.17578,-9.85546 -1.17578,-14.70703 v -3.96875 c 0,-5.14843 0.44141,-10 1.17578,-14.85547 z M 187.5,40.449219 c -81.17187,0 -147.050781,65.878911 -147.050781,147.050781 0,81.17187 65.878911,147.05078 147.050781,147.05078 81.17187,0 147.05078,-65.87891 147.05078,-147.05078 0,-81.17187 -65.87891,-147.050781 -147.05078,-147.050781 z m 0,264.691401 c -64.84766,0 -117.640625,-52.79296 -117.640625,-117.64062 0,-64.84766 52.792965,-117.640625 117.640625,-117.640625 64.84766,0 117.64062,52.792965 117.64062,117.640625 0,64.84766 -52.79296,117.64062 -117.64062,117.64062 z m 0,0" id="path2" /> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg5" sodipodi:docname="copyright.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <defs id="defs9" /> <sodipodi:namedview id="namedview7" pagecolor="#505050" bordercolor="#eeeeee" borderopacity="1" inkscape:pageshadow="0" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" showgrid="false" inkscape:zoom="2.4012481" inkscape:cx="194.06574" inkscape:cy="30.192632" inkscape:window-width="1920" inkscape:window-height="995" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg5" /> <g id="surface1" transform="matrix(1.2644961,0,0,1.2644961,-49.593016,-49.593016)"> <path style="fill:{color};fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 159.26562,170.73437 c 0.73438,-4.85156 2.35157,-9.11718 4.41016,-12.79296 2.0625,-3.67579 5,-6.76172 8.67969,-9.11719 3.52734,-2.20313 7.9375,-3.23438 13.3789,-3.37891 3.38282,0.14453 6.47266,0.73438 9.26563,1.91016 2.94141,1.32422 5.58594,3.08594 7.64453,5.29297 2.05859,2.20703 3.67969,4.85156 5,7.79297 1.32422,2.9414 1.91406,6.17578 2.05859,9.41406 h 26.32422 c -0.29297,-6.91406 -1.61718,-13.23438 -4.11718,-18.97266 -2.5,-5.73437 -5.88282,-10.73437 -10.29297,-14.85156 -4.41407,-4.11719 -9.70703,-7.35156 -15.88282,-9.70312 -6.17578,-2.35547 -12.9414,-3.38282 -20.4414,-3.38282 -9.5586,0 -17.9375,1.61719 -24.9961,5 -7.05859,3.38281 -12.9414,7.79297 -17.64843,13.52735 -4.70313,5.73437 -8.23438,12.35156 -10.44141,20 -2.20312,7.64453 -3.52734,15.58593 -3.52734,24.11718 v 3.96875 c 0,8.52735 1.17578,16.46875 3.38281,24.11719 2.20312,7.64453 5.73437,14.26172 10.44141,19.85156 4.70312,5.58594 10.58593,10.14453 17.64453,13.38282 7.05859,3.23437 15.4414,5 25,5 6.91015,0 13.3789,-1.17969 19.41015,-3.38282 6.02735,-2.20703 11.32422,-5.29687 15.87891,-9.26562 4.55859,-3.96875 8.23828,-8.52735 10.88281,-13.82422 2.64844,-5.29297 4.26563,-10.87891 4.41406,-16.91016 h -26.32421 c -0.14454,3.08985 -0.88282,5.88282 -2.20704,8.53125 -1.32031,2.64453 -3.08593,4.85157 -5.29296,6.76172 -2.20313,1.91406 -4.70313,3.38281 -7.64454,4.41406 -2.79687,1.02735 -5.73437,1.32032 -8.82421,1.46875 -5.29297,-0.14843 -9.70704,-1.17578 -13.08594,-3.38281 -3.67969,-2.35156 -6.61719,-5.4414 -8.67969,-9.11719 -2.05859,-3.67578 -3.67578,-8.08593 -4.41016,-12.9375 -0.73437,-4.85546 -1.17578,-9.85546 -1.17578,-14.70703 v -3.96875 c 0,-5.14843 0.44141,-10 1.17578,-14.85547 z M 187.5,40.449219 c -81.17187,0 -147.050781,65.878911 -147.050781,147.050781 0,81.17187 65.878911,147.05078 147.050781,147.05078 81.17187,0 147.05078,-65.87891 147.05078,-147.05078 0,-81.17187 -65.87891,-147.050781 -147.05078,-147.050781 z m 0,264.691401 c -64.84766,0 -117.640625,-52.79296 -117.640625,-117.64062 0,-64.84766 52.792965,-117.640625 117.640625,-117.640625 64.84766,0 117.64062,52.792965 117.64062,117.640625 0,64.84766 -52.79296,117.64062 -117.64062,117.64062 z m 0,0" id="path2" /> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="9" height="9" viewBox="0 0 9 9" version="1.1" sodipodi:docname="cross.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns="http://www.w3.org/2000/svg" > <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 1,4.5 H 8" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,1 V 4" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,5 V 8" id="path941"/> <path style="fill: none !important;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 3.5,5 v 3.5 h 2 v -3 h 3 v -2 h -3 v -3 h -2 v 3 h -3 v 2 h3" id="path941"/> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="9" height="9" viewBox="0 0 9 9" version="1.1" sodipodi:docname="cross.svg" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" xmlns="http://www.w3.org/2000/svg" > <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 1,4.5 H 8" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,1 V 4" id="path941"/> <path style="fill: none !important;stroke:{color};stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 4.5,5 V 8" id="path941"/> <path style="fill: none !important;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50314403" d="M 3.5,5 v 3.5 h 2 v -3 h 3 v -2 h -3 v -3 h -2 v 3 h -3 v 2 h3" id="path941"/> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.97295 289.3838 L 7.74695 278.1578 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.989705 278.103849 L 7.763705 289.329515 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.97295 289.3838 L 7.74695 278.1578 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> <path style="fill: none !important;stroke-width:3.439583;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 18.989705 278.103849 L 7.763705 289.329515 " transform="matrix(11.65716,0,0,11.65716,130.176942,-3023.744742)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg15" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <path id="path2" style="color:{color};fill:{color};fill-opacity:0.988235;stroke-linecap:round;stroke-linejoin:round;stroke:#ccccccaa ;stroke-width: 8" d="M 187.5 0.17578125 A 15 15 0 0 0 172.5 15.175781 L 172.5 43.708984 C 104.37541 50.343145 49.843699 104.61884 42.837891 172.63672 L 14.765625 172.63672 A 14.86235 14.86235 0 0 0 -0.09765625 187.5 A 14.86235 14.86235 0 0 0 14.765625 202.36133 L 42.837891 202.36133 C 49.842792 270.37794 104.37427 324.65648 172.5 331.29102 L 172.5 360.10156 A 15 15 0 0 0 187.5 375.10156 A 15 15 0 0 0 202.5 360.10156 L 202.5 331.08594 C 269.70108 323.65092 323.26953 269.82518 330.26953 202.5 L 360.08203 202.5 A 15 15 0 0 0 375.08203 187.5 A 15 15 0 0 0 360.08203 172.5 L 330.26953 172.5 C 323.26946 105.17266 269.70061 51.348735 202.5 43.914062 L 202.5 15.175781 A 15 15 0 0 0 187.5 0.17578125 z M 186.5625 80.511719 C 245.87515 80.511719 293.55078 128.18741 293.55078 187.5 C 293.55078 246.80822 245.87443 294.48828 186.5625 294.48828 C 127.25056 294.48828 79.574219 246.80822 79.574219 187.5 C 79.574219 128.1874 127.24984 80.511719 186.5625 80.511719 z M 187.5 139.21094 C 160.83203 139.21094 139.21094 160.83203 139.21094 187.5 C 139.21094 214.16797 160.83203 235.78906 187.5 235.78906 C 214.16797 235.78906 235.78906 214.16797 235.78906 187.5 C 235.78906 160.83203 214.16797 139.21094 187.5 139.21094 z " /> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus width="375px" height="375px" viewBox="0 0 375 375" version="1.1" id="svg15" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <path id="path2" style="color:{color};fill:{color};fill-opacity:0.988235;stroke-linecap:round;stroke-linejoin:round;stroke:#ccccccaa ;stroke-width: 8" d="M 187.5 0.17578125 A 15 15 0 0 0 172.5 15.175781 L 172.5 43.708984 C 104.37541 50.343145 49.843699 104.61884 42.837891 172.63672 L 14.765625 172.63672 A 14.86235 14.86235 0 0 0 -0.09765625 187.5 A 14.86235 14.86235 0 0 0 14.765625 202.36133 L 42.837891 202.36133 C 49.842792 270.37794 104.37427 324.65648 172.5 331.29102 L 172.5 360.10156 A 15 15 0 0 0 187.5 375.10156 A 15 15 0 0 0 202.5 360.10156 L 202.5 331.08594 C 269.70108 323.65092 323.26953 269.82518 330.26953 202.5 L 360.08203 202.5 A 15 15 0 0 0 375.08203 187.5 A 15 15 0 0 0 360.08203 172.5 L 330.26953 172.5 C 323.26946 105.17266 269.70061 51.348735 202.5 43.914062 L 202.5 15.175781 A 15 15 0 0 0 187.5 0.17578125 z M 186.5625 80.511719 C 245.87515 80.511719 293.55078 128.18741 293.55078 187.5 C 293.55078 246.80822 245.87443 294.48828 186.5625 294.48828 C 127.25056 294.48828 79.574219 246.80822 79.574219 187.5 C 79.574219 128.1874 127.24984 80.511719 186.5625 80.511719 z M 187.5 139.21094 C 160.83203 139.21094 139.21094 160.83203 139.21094 187.5 C 139.21094 214.16797 160.83203 235.78906 187.5 235.78906 C 214.16797 235.78906 235.78906 214.16797 235.78906 187.5 C 235.78906 160.83203 214.16797 139.21094 187.5 139.21094 z " /> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:2.645833;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 22.034555 283.770823 C 22.034555 288.670301 18.062773 292.642358 13.16302 292.642358 C 8.263267 292.642358 4.291486 288.670301 4.291486 283.770823 C 4.291486 278.871071 8.263267 274.899289 13.16302 274.899289 C 18.062773 274.899289 22.034555 278.871071 22.034555 283.770823 Z M 22.034555 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.097239;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 3.28414 283.770823 L 1.041796 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 25.405787 283.770823 L 23.286365 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 295.948823 L 13.229166 293.831329 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 275.057488 L 13.229166 271.612392 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(33.333334%,33.333334%,92.54902%);fill-opacity:0.988235;" d="M 238.824219 161.203125 L 229.523438 161.203125 L 229.523438 134.96875 C 229.523438 134.96875 229.523438 91.246094 186.066406 91.246094 C 142.609375 91.246094 142.609375 134.96875 142.609375 134.96875 L 142.609375 161.203125 L 133.308594 161.203125 C 124.042969 161.203125 116.535156 168.757812 116.535156 178.082031 L 116.535156 249.347656 C 116.582031 258.636719 124.078125 266.136719 133.308594 266.136719 L 238.824219 266.136719 C 248.085938 266.136719 255.597656 258.582031 255.597656 249.261719 L 255.597656 178.082031 C 255.597656 168.757812 248.085938 161.203125 238.824219 161.203125 Z M 186.066406 231.160156 C 176.464844 231.160156 168.683594 223.328125 168.683594 213.671875 C 168.683594 204.011719 176.464844 196.179688 186.066406 196.179688 C 195.664062 196.179688 203.449219 204.011719 203.449219 213.671875 C 203.449219 223.328125 195.664062 231.160156 186.066406 231.160156 Z M 212.140625 161.203125 L 159.992188 161.203125 L 159.992188 139.339844 C 159.992188 126.226562 159.992188 108.734375 186.066406 108.734375 C 212.140625 108.734375 212.140625 126.226562 212.140625 139.339844 Z M 212.140625 161.203125 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:2.645833;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 22.034555 283.770823 C 22.034555 288.670301 18.062773 292.642358 13.16302 292.642358 C 8.263267 292.642358 4.291486 288.670301 4.291486 283.770823 C 4.291486 278.871071 8.263267 274.899289 13.16302 274.899289 C 18.062773 274.899289 22.034555 278.871071 22.034555 283.770823 Z M 22.034555 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.097239;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 3.28414 283.770823 L 1.041796 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 25.405787 283.770823 L 23.286365 283.770823 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 295.948823 L 13.229166 293.831329 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style="fill: none !important;stroke-width:2.116667;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(33.333334%,33.333334%,92.54902%);stroke-opacity:0.988235;stroke-miterlimit:4;" d="M 13.229166 275.057488 L 13.229166 271.612392 " transform="matrix(14.173228,0,0,14.173228,0.0000135166,-3834.448583)"/> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(33.333334%,33.333334%,92.54902%);fill-opacity:0.988235;" d="M 238.824219 161.203125 L 229.523438 161.203125 L 229.523438 134.96875 C 229.523438 134.96875 229.523438 91.246094 186.066406 91.246094 C 142.609375 91.246094 142.609375 134.96875 142.609375 134.96875 L 142.609375 161.203125 L 133.308594 161.203125 C 124.042969 161.203125 116.535156 168.757812 116.535156 178.082031 L 116.535156 249.347656 C 116.582031 258.636719 124.078125 266.136719 133.308594 266.136719 L 238.824219 266.136719 C 248.085938 266.136719 255.597656 258.582031 255.597656 249.261719 L 255.597656 178.082031 C 255.597656 168.757812 248.085938 161.203125 238.824219 161.203125 Z M 186.066406 231.160156 C 176.464844 231.160156 168.683594 223.328125 168.683594 213.671875 C 168.683594 204.011719 176.464844 196.179688 186.066406 196.179688 C 195.664062 196.179688 203.449219 204.011719 203.449219 213.671875 C 203.449219 223.328125 195.664062 231.160156 186.066406 231.160156 Z M 212.140625 161.203125 L 159.992188 161.203125 L 159.992188 139.339844 C 159.992188 126.226562 159.992188 108.734375 186.066406 108.734375 C 212.140625 108.734375 212.140625 126.226562 212.140625 139.339844 Z M 212.140625 161.203125 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,0%,0%);fill-opacity:1;" d="M 148.457031 148.796875 L 148.457031 269.332031 C 148.457031 271.285156 147.828125 272.890625 146.574219 274.144531 C 145.316406 275.402344 143.714844 276.027344 141.761719 276.027344 L 128.367188 276.027344 C 126.414062 276.027344 124.808594 275.402344 123.554688 274.144531 C 122.296875 272.890625 121.671875 271.285156 121.671875 269.332031 L 121.671875 148.796875 C 121.671875 146.84375 122.296875 145.238281 123.554688 143.984375 C 124.808594 142.726562 126.414062 142.101562 128.367188 142.101562 L 141.761719 142.101562 C 143.714844 142.101562 145.316406 142.726562 146.574219 143.984375 C 147.828125 145.238281 148.457031 146.84375 148.457031 148.796875 Z M 202.027344 148.796875 L 202.027344 269.332031 C 202.027344 271.285156 201.398438 272.890625 200.144531 274.144531 C 198.890625 275.402344 197.285156 276.027344 195.332031 276.027344 L 181.9375 276.027344 C 179.984375 276.027344 178.382812 275.402344 177.125 274.144531 C 175.871094 272.890625 175.242188 271.285156 175.242188 269.332031 L 175.242188 148.796875 C 175.242188 146.84375 175.871094 145.238281 177.125 143.984375 C 178.382812 142.726562 179.984375 142.101562 181.9375 142.101562 L 195.332031 142.101562 C 197.285156 142.101562 198.890625 142.726562 200.144531 143.984375 C 201.398438 145.238281 202.027344 146.84375 202.027344 148.796875 Z M 255.597656 148.796875 L 255.597656 269.332031 C 255.597656 271.285156 254.972656 272.890625 253.714844 274.144531 C 252.460938 275.402344 250.855469 276.027344 248.902344 276.027344 L 235.511719 276.027344 C 233.558594 276.027344 231.953125 275.402344 230.695312 274.144531 C 229.441406 272.890625 228.8125 271.285156 228.8125 269.332031 L 228.8125 148.796875 C 228.8125 146.84375 229.441406 145.238281 230.695312 143.984375 C 231.953125 142.726562 233.558594 142.101562 235.511719 142.101562 L 248.902344 142.101562 C 250.855469 142.101562 252.460938 142.726562 253.714844 143.984375 C 254.972656 145.238281 255.597656 146.84375 255.597656 148.796875 Z M 282.386719 300.304688 L 282.386719 101.921875 L 94.886719 101.921875 L 94.886719 300.304688 C 94.886719 303.371094 95.375 306.199219 96.351562 308.777344 C 97.328125 311.359375 98.335938 313.242188 99.382812 314.429688 C 100.429688 315.613281 101.164062 316.207031 101.582031 316.207031 L 275.6875 316.207031 C 276.105469 316.207031 276.839844 315.613281 277.886719 314.429688 C 278.933594 313.242188 279.945312 311.359375 280.921875 308.777344 C 281.898438 306.199219 282.386719 303.371094 282.386719 300.304688 Z M 141.761719 75.136719 L 235.511719 75.136719 L 225.464844 50.652344 C 224.488281 49.398438 223.304688 48.628906 221.90625 48.351562 L 155.570312 48.351562 C 154.175781 48.628906 152.992188 49.398438 152.015625 50.652344 Z M 335.957031 81.832031 L 335.957031 95.226562 C 335.957031 97.179688 335.328125 98.78125 334.074219 100.039062 C 332.816406 101.292969 331.214844 101.921875 329.261719 101.921875 L 309.171875 101.921875 L 309.171875 300.304688 C 309.171875 311.882812 305.890625 321.894531 299.335938 330.332031 C 292.777344 338.773438 284.894531 342.992188 275.6875 342.992188 L 101.582031 342.992188 C 92.375 342.992188 84.492188 338.914062 77.933594 330.75 C 71.378906 322.589844 68.097656 312.71875 68.097656 301.140625 L 68.097656 101.921875 L 48.011719 101.921875 C 46.058594 101.921875 44.453125 101.292969 43.195312 100.039062 C 41.941406 98.78125 41.3125 97.179688 41.3125 95.226562 L 41.3125 81.832031 C 41.3125 79.878906 41.941406 78.273438 43.195312 77.019531 C 44.453125 75.765625 46.058594 75.136719 48.011719 75.136719 L 112.671875 75.136719 L 127.320312 40.1875 C 129.414062 35.027344 133.179688 30.632812 138.621094 27.003906 C 144.0625 23.378906 149.574219 21.566406 155.152344 21.566406 L 222.117188 21.566406 C 227.699219 21.566406 233.207031 23.378906 238.648438 27.003906 C 244.089844 30.632812 247.855469 35.027344 249.949219 40.1875 L 264.597656 75.136719 L 329.261719 75.136719 C 331.214844 75.136719 332.816406 75.765625 334.074219 77.019531 C 335.328125 78.273438 335.957031 79.878906 335.957031 81.832031 Z M 335.957031 81.832031 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,0%,0%);fill-opacity:1;" d="M 148.457031 148.796875 L 148.457031 269.332031 C 148.457031 271.285156 147.828125 272.890625 146.574219 274.144531 C 145.316406 275.402344 143.714844 276.027344 141.761719 276.027344 L 128.367188 276.027344 C 126.414062 276.027344 124.808594 275.402344 123.554688 274.144531 C 122.296875 272.890625 121.671875 271.285156 121.671875 269.332031 L 121.671875 148.796875 C 121.671875 146.84375 122.296875 145.238281 123.554688 143.984375 C 124.808594 142.726562 126.414062 142.101562 128.367188 142.101562 L 141.761719 142.101562 C 143.714844 142.101562 145.316406 142.726562 146.574219 143.984375 C 147.828125 145.238281 148.457031 146.84375 148.457031 148.796875 Z M 202.027344 148.796875 L 202.027344 269.332031 C 202.027344 271.285156 201.398438 272.890625 200.144531 274.144531 C 198.890625 275.402344 197.285156 276.027344 195.332031 276.027344 L 181.9375 276.027344 C 179.984375 276.027344 178.382812 275.402344 177.125 274.144531 C 175.871094 272.890625 175.242188 271.285156 175.242188 269.332031 L 175.242188 148.796875 C 175.242188 146.84375 175.871094 145.238281 177.125 143.984375 C 178.382812 142.726562 179.984375 142.101562 181.9375 142.101562 L 195.332031 142.101562 C 197.285156 142.101562 198.890625 142.726562 200.144531 143.984375 C 201.398438 145.238281 202.027344 146.84375 202.027344 148.796875 Z M 255.597656 148.796875 L 255.597656 269.332031 C 255.597656 271.285156 254.972656 272.890625 253.714844 274.144531 C 252.460938 275.402344 250.855469 276.027344 248.902344 276.027344 L 235.511719 276.027344 C 233.558594 276.027344 231.953125 275.402344 230.695312 274.144531 C 229.441406 272.890625 228.8125 271.285156 228.8125 269.332031 L 228.8125 148.796875 C 228.8125 146.84375 229.441406 145.238281 230.695312 143.984375 C 231.953125 142.726562 233.558594 142.101562 235.511719 142.101562 L 248.902344 142.101562 C 250.855469 142.101562 252.460938 142.726562 253.714844 143.984375 C 254.972656 145.238281 255.597656 146.84375 255.597656 148.796875 Z M 282.386719 300.304688 L 282.386719 101.921875 L 94.886719 101.921875 L 94.886719 300.304688 C 94.886719 303.371094 95.375 306.199219 96.351562 308.777344 C 97.328125 311.359375 98.335938 313.242188 99.382812 314.429688 C 100.429688 315.613281 101.164062 316.207031 101.582031 316.207031 L 275.6875 316.207031 C 276.105469 316.207031 276.839844 315.613281 277.886719 314.429688 C 278.933594 313.242188 279.945312 311.359375 280.921875 308.777344 C 281.898438 306.199219 282.386719 303.371094 282.386719 300.304688 Z M 141.761719 75.136719 L 235.511719 75.136719 L 225.464844 50.652344 C 224.488281 49.398438 223.304688 48.628906 221.90625 48.351562 L 155.570312 48.351562 C 154.175781 48.628906 152.992188 49.398438 152.015625 50.652344 Z M 335.957031 81.832031 L 335.957031 95.226562 C 335.957031 97.179688 335.328125 98.78125 334.074219 100.039062 C 332.816406 101.292969 331.214844 101.921875 329.261719 101.921875 L 309.171875 101.921875 L 309.171875 300.304688 C 309.171875 311.882812 305.890625 321.894531 299.335938 330.332031 C 292.777344 338.773438 284.894531 342.992188 275.6875 342.992188 L 101.582031 342.992188 C 92.375 342.992188 84.492188 338.914062 77.933594 330.75 C 71.378906 322.589844 68.097656 312.71875 68.097656 301.140625 L 68.097656 101.921875 L 48.011719 101.921875 C 46.058594 101.921875 44.453125 101.292969 43.195312 100.039062 C 41.941406 98.78125 41.3125 97.179688 41.3125 95.226562 L 41.3125 81.832031 C 41.3125 79.878906 41.941406 78.273438 43.195312 77.019531 C 44.453125 75.765625 46.058594 75.136719 48.011719 75.136719 L 112.671875 75.136719 L 127.320312 40.1875 C 129.414062 35.027344 133.179688 30.632812 138.621094 27.003906 C 144.0625 23.378906 149.574219 21.566406 155.152344 21.566406 L 222.117188 21.566406 C 227.699219 21.566406 233.207031 23.378906 238.648438 27.003906 C 244.089844 30.632812 247.855469 35.027344 249.949219 40.1875 L 264.597656 75.136719 L 329.261719 75.136719 C 331.214844 75.136719 332.816406 75.765625 334.074219 77.019531 C 335.328125 78.273438 335.957031 79.878906 335.957031 81.832031 Z M 335.957031 81.832031 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns="http://www.w3.org/2000/svg" version="1.0" width="860.50732pt" height="860.50732pt" viewBox="0 0 860.50732 860.50732" preserveAspectRatio="xMidYMid meet" id="svg14" sodipodi:docname="direction_gradient.svg" inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> <defs id="defs18"> <linearGradient inkscape:collect="always" id="linearGradient832"> <stop style="stop-color:{color};stop-opacity:1;" offset="0" id="stop828"/> <stop style="stop-color:{color};stop-opacity:0;" offset="1" id="stop830"/> </linearGradient> <radialGradient inkscape:collect="always" xlink:href="#linearGradient832" id="radialGradient838" cx="430.25363" cy="519.61188" fx="430.25363" fy="519.61188" r="305.54589" gradientTransform="matrix(0.95288409,-0.94890664,0.94542304,0.94938587,-470.98122,345.21193)" gradientUnits="userSpaceOnUse"/> </defs> <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="999" id="namedview16" showgrid="false" showguides="true" inkscape:guide-bbox="true" inkscape:zoom="0.70710678" inkscape:cx="279.00239" inkscape:cy="856.75313" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg14"> <sodipodi:guide position="430.25363,862.49682" orientation="1,0" id="guide832" inkscape:locked="false"/> <sodipodi:guide position="-42.427977,430.25368" orientation="0,1" id="guide834" inkscape:locked="false"/> <sodipodi:guide position="398.27788,720.18823" orientation="0,1" id="guide840" inkscape:locked="false"/> </sodipodi:namedview> <metadata id="metadata2"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> </cc:Work> </rdf:RDF> </metadata> <path style="fill:url(#radialGradient838);fill-opacity:1;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z" id="path836" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns="http://www.w3.org/2000/svg" version="1.0" width="860.50732pt" height="860.50732pt" viewBox="0 0 860.50732 860.50732" preserveAspectRatio="xMidYMid meet" id="svg14" sodipodi:docname="direction_gradient.svg" inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"> <defs id="defs18"> <linearGradient inkscape:collect="always" id="linearGradient832"> <stop style="stop-color:{color};stop-opacity:1;" offset="0" id="stop828"/> <stop style="stop-color:{color};stop-opacity:0;" offset="1" id="stop830"/> </linearGradient> <radialGradient inkscape:collect="always" xlink:href="#linearGradient832" id="radialGradient838" cx="430.25363" cy="519.61188" fx="430.25363" fy="519.61188" r="305.54589" gradientTransform="matrix(0.95288409,-0.94890664,0.94542304,0.94938587,-470.98122,345.21193)" gradientUnits="userSpaceOnUse"/> </defs> <sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="999" id="namedview16" showgrid="false" showguides="true" inkscape:guide-bbox="true" inkscape:zoom="0.70710678" inkscape:cx="279.00239" inkscape:cy="856.75313" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="svg14"> <sodipodi:guide position="430.25363,862.49682" orientation="1,0" id="guide832" inkscape:locked="false"/> <sodipodi:guide position="-42.427977,430.25368" orientation="0,1" id="guide834" inkscape:locked="false"/> <sodipodi:guide position="398.27788,720.18823" orientation="0,1" id="guide840" inkscape:locked="false"/> </sodipodi:namedview> <metadata id="metadata2"> Created by potrace 1.15, written by Peter Selinger 2001-2017 <rdf:RDF> <cc:Work rdf:about=""> <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <dc:title/> </cc:Work> </rdf:RDF> </metadata> <path style="fill:url(#radialGradient838);fill-opacity:1;stroke:none;stroke-width:2.83464575;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M 735.79979,124.70799 C 654.79116,43.598883 544.88842,-2.0206645 430.25389,-2.121103 315.61937,-2.0206592 205.71663,43.598888 124.70801,124.70799 l 305.54588,305.54589 z" id="path836" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(97.254902%,100%,96.078432%);stroke-opacity:1;stroke-miterlimit:4;" d="M -177.48351 -16.993714 C -177.484166 101.48875 -226.288922 214.739751 -312.411923 296.10684 C -398.528411 377.467771 -514.363074 419.770216 -632.651731 413.060164 " transform="matrix(-0.316636,-0.299423,0.299423,-0.316636,0,0)"/> <path style="fill: none !important;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 743.478328 134.561833 L 430.253662 430.253662 L 117.002105 134.508051 " transform="matrix(0.435789,0,0,0.435789,0,0)"/> <path style="fill: none !important;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M -177.48351 -16.993714 C -177.484166 101.48875 -226.288922 214.739751 -312.411923 296.10684 C -398.528411 377.467771 -514.363074 419.770216 -632.651731 413.060164 " transform="matrix(-0.316636,-0.299423,0.299423,-0.316636,0,0)"/> <path style="fill: none !important;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 743.478328 134.561833 L 430.253662 430.253662 L 117.002105 134.508051 " transform="matrix(0.435789,0,0,0.435789,0,0)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(97.254902%,100%,96.078432%);stroke-opacity:1;stroke-miterlimit:4;" d="M -177.48351 -16.993714 C -177.484166 101.48875 -226.288922 214.739751 -312.411923 296.10684 C -398.528411 377.467771 -514.363074 419.770216 -632.651731 413.060164 " transform="matrix(-0.316636,-0.299423,0.299423,-0.316636,0,0)"/> <path style="fill: none !important;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:4;" d="M 743.478328 134.561833 L 430.253662 430.253662 L 117.002105 134.508051 " transform="matrix(0.435789,0,0,0.435789,0,0)"/> <path style="fill: none !important;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M -177.48351 -16.993714 C -177.484166 101.48875 -226.288922 214.739751 -312.411923 296.10684 C -398.528411 377.467771 -514.363074 419.770216 -632.651731 413.060164 " transform="matrix(-0.316636,-0.299423,0.299423,-0.316636,0,0)"/> <path style="fill: none !important;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 743.478328 134.561833 L 430.253662 430.253662 L 117.002105 134.508051 " transform="matrix(0.435789,0,0,0.435789,0,0)"/> </g> </svg>

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown version="1.1" id="elevator" x="0px" y="0px" viewBox="0 0 65.9 66" style="enable-background:new 0 0 65.9 66;" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"> <path d="M 48.2,15.6 H 19.3 c -1.6,0 -2.8,1.3 -2.8,2.8 v 29 c 0,1.6 1.3,2.8 2.8,2.8 h 28.9 c 1.6,0 2.8,-1.3 2.8,-2.8 V 18.5 C 51,17 49.7,15.6 48.2,15.6 Z m 0.3,30.7 c 0,0.8 -0.6,1.4 -1.4,1.4 H 20.4 C 19.6,47.7 19,47.1 19,46.3 V 19.6 c 0,-0.8 0.6,-1.4 1.4,-1.4 h 26.7 c 0.8,0 1.4,0.6 1.4,1.4 z" id="path2"/> <polygon points="29.4,9.5 33.7,5.5 38.1,9.5 35.3,9.5 35.3,13.5 32.2,13.5 32.2,9.5 " id="polygon8"/> <polygon points="38.1,56.6 33.7,60.5 29.4,56.6 32.2,56.6 32.2,52.5 35.3,52.5 35.3,56.6 " id="polygon10"/> <circle cx="28.6" cy="21.4" r="1.9" id="circle12"/> <path d="m 29.1,35.6 c 0,-0.2 -0.2,-0.5 -0.5,-0.5 -0.3,0 -0.5,0.2 -0.5,0.5 v 1.7 3 5 c 0,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -1.2,-0.5 -1.2,-1.2 V 40.5 37.3 33.2 32 28.2 28.3 c 0,-0.2 -0.1,-0.4 -0.4,-0.4 -0.2,0 -0.4,0.2 -0.4,0.4 v 1.3 3.5 1.8 c 0,0.4 -0.3,0.7 -0.7,0.7 -0.4,0 -0.7,-0.3 -0.7,-0.7 v -1 -3.5 -4.2 c 0,-1 0.8,-1.9 1.9,-1.9 h 5.2 0.3 c 0.2,0 0.5,0.1 0.6,0.3 l 2.1,2.1 2.5,-2.5 c 0.4,-0.4 1,-0.4 1.3,0 0.4,0.4 0.4,1 0,1.3 l -3.2,3.2 C 34,28.9 33.8,29 33.5,29 33.3,29 33,28.9 32.8,28.7 L 32,27.9 31.8,27.8 h -0.2 c -0.2,0 -0.4,0.2 -0.4,0.4 v 1.6 10.6 l 7.68e-4,4.906766 c 9.4e-5,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -0.957071,-0.484801 -0.957071,-1.184801 0,0 0.0563,-6.496244 0.0563,-9.721965 z" id="path14" /> <circle cx="42.400002" cy="21" r="1.5" id="circle16"/> <circle cx="42.400002" cy="24.5" r="1.5" id="circle18"/> <circle cx="42.400002" cy="28.200001" r="1.5" id="circle20"/> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus version="1.1" id="elevator" x="0px" y="0px" viewBox="0 0 65.9 66" style="enable-background:new 0 0 65.9 66;" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"> <path d="M 48.2,15.6 H 19.3 c -1.6,0 -2.8,1.3 -2.8,2.8 v 29 c 0,1.6 1.3,2.8 2.8,2.8 h 28.9 c 1.6,0 2.8,-1.3 2.8,-2.8 V 18.5 C 51,17 49.7,15.6 48.2,15.6 Z m 0.3,30.7 c 0,0.8 -0.6,1.4 -1.4,1.4 H 20.4 C 19.6,47.7 19,47.1 19,46.3 V 19.6 c 0,-0.8 0.6,-1.4 1.4,-1.4 h 26.7 c 0.8,0 1.4,0.6 1.4,1.4 z" id="path2"/> <polygon points="29.4,9.5 33.7,5.5 38.1,9.5 35.3,9.5 35.3,13.5 32.2,13.5 32.2,9.5 " id="polygon8"/> <polygon points="38.1,56.6 33.7,60.5 29.4,56.6 32.2,56.6 32.2,52.5 35.3,52.5 35.3,56.6 " id="polygon10"/> <circle cx="28.6" cy="21.4" r="1.9" id="circle12"/> <path d="m 29.1,35.6 c 0,-0.2 -0.2,-0.5 -0.5,-0.5 -0.3,0 -0.5,0.2 -0.5,0.5 v 1.7 3 5 c 0,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -1.2,-0.5 -1.2,-1.2 V 40.5 37.3 33.2 32 28.2 28.3 c 0,-0.2 -0.1,-0.4 -0.4,-0.4 -0.2,0 -0.4,0.2 -0.4,0.4 v 1.3 3.5 1.8 c 0,0.4 -0.3,0.7 -0.7,0.7 -0.4,0 -0.7,-0.3 -0.7,-0.7 v -1 -3.5 -4.2 c 0,-1 0.8,-1.9 1.9,-1.9 h 5.2 0.3 c 0.2,0 0.5,0.1 0.6,0.3 l 2.1,2.1 2.5,-2.5 c 0.4,-0.4 1,-0.4 1.3,0 0.4,0.4 0.4,1 0,1.3 l -3.2,3.2 C 34,28.9 33.8,29 33.5,29 33.3,29 33,28.9 32.8,28.7 L 32,27.9 31.8,27.8 h -0.2 c -0.2,0 -0.4,0.2 -0.4,0.4 v 1.6 10.6 l 7.68e-4,4.906766 c 9.4e-5,0.6 -0.6,1.2 -1.2,1.2 -0.6,0 -0.957071,-0.484801 -0.957071,-1.184801 0,0 0.0563,-6.496244 0.0563,-9.721965 z" id="path14" /> <circle cx="42.400002" cy="21" r="1.5" id="circle16"/> <circle cx="42.400002" cy="24.5" r="1.5" id="circle18"/> <circle cx="42.400002" cy="28.200001" r="1.5" id="circle20"/> </svg>

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:8.16402;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 9.669812 22.725188 L 42.932875 56.977438 C 42.932875 56.977438 55.27575 71.374687 69.062625 56.977438 C 88.864187 36.300688 103.1225 22.224062 103.1225 22.224062 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 9.902563 22.944875 L 102.88975 22.461562 L 102.88975 92.383938 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 102.88975 92.383938 L 9.902563 92.866062 L 9.902563 22.944875 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:2.889384;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 15.059875 89.897312 L 52.138375 60.1255 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:2.894905;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 59.644562 61.332 L 98.072063 89.495937 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style="fill: none !important;stroke-width:8.16402;stroke-linecap:round;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 9.669812 22.725188 L 42.932875 56.977438 C 42.932875 56.977438 55.27575 71.374687 69.062625 56.977438 C 88.864187 36.300688 103.1225 22.224062 103.1225 22.224062 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 9.902563 22.944875 L 102.88975 22.461562 L 102.88975 92.383938 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 102.88975 92.383938 L 9.902563 92.866062 L 9.902563 22.944875 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:2.889384;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 15.059875 89.897312 L 52.138375 60.1255 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> <path style="fill: none !important;stroke-width:2.894905;stroke-linecap:butt;stroke-linejoin:miter;stroke:{color};stroke-opacity:1;stroke-miterlimit:4;" d="M 59.644562 61.332 L 98.072063 89.495937 " transform="matrix(3.289474,0,0,3.289474,0,0)"/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 343.453125 190.519531 C 322.914062 158.628906 297.171875 134.777344 266.222656 118.964844 C 274.46875 133.019531 278.589844 148.222656 278.589844 164.574219 C 278.589844 189.574219 269.703125 210.960938 251.933594 228.730469 C 234.164062 246.5 212.777344 255.386719 187.777344 255.386719 C 162.777344 255.386719 141.394531 246.5 123.621094 228.730469 C 105.851562 210.960938 96.96875 189.574219 96.96875 164.574219 C 96.96875 148.222656 101.089844 133.019531 109.332031 118.964844 C 78.386719 134.777344 52.644531 158.628906 32.101562 190.519531 C 50.074219 218.222656 72.609375 240.285156 99.703125 256.703125 C 126.796875 273.121094 156.15625 281.332031 187.777344 281.332031 C 219.398438 281.332031 248.757812 273.121094 275.851562 256.703125 C 302.945312 240.285156 325.480469 218.222656 343.453125 190.519531 Z M 197.507812 112.683594 C 197.507812 109.980469 196.5625 107.683594 194.671875 105.789062 C 192.777344 103.898438 190.480469 102.953125 187.777344 102.953125 C 170.886719 102.953125 156.394531 109 144.296875 121.09375 C 132.203125 133.1875 126.15625 147.683594 126.15625 164.574219 C 126.15625 167.277344 127.101562 169.574219 128.996094 171.464844 C 130.886719 173.359375 133.183594 174.304688 135.886719 174.304688 C 138.589844 174.304688 140.886719 173.359375 142.777344 171.464844 C 144.671875 169.574219 145.617188 167.277344 145.617188 164.574219 C 145.617188 152.953125 149.738281 143.019531 157.980469 134.777344 C 166.222656 126.535156 176.15625 122.410156 187.777344 122.410156 C 190.480469 122.410156 192.777344 121.464844 194.671875 119.574219 C 196.5625 117.683594 197.507812 115.386719 197.507812 112.683594 Z M 369.398438 190.519531 C 369.398438 195.113281 368.046875 199.777344 365.347656 204.507812 C 346.425781 235.585938 320.988281 260.484375 289.027344 279.203125 C 257.070312 297.917969 223.320312 307.277344 187.777344 307.277344 C 152.238281 307.277344 118.488281 297.886719 86.527344 279.101562 C 54.570312 260.316406 29.128906 235.453125 10.210938 204.507812 C 7.507812 199.777344 6.15625 195.113281 6.15625 190.519531 C 6.15625 185.925781 7.507812 181.261719 10.210938 176.535156 C 29.128906 145.585938 54.570312 120.722656 86.527344 101.9375 C 118.488281 83.15625 152.238281 73.761719 187.777344 73.761719 C 223.320312 73.761719 257.070312 83.15625 289.027344 101.9375 C 320.988281 120.722656 346.425781 145.585938 365.347656 176.535156 C 368.046875 181.261719 369.398438 185.925781 369.398438 190.519531 Z M 369.398438 190.519531 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1"> <g id="surface1"> <path style=" stroke:none;fill-rule:nonzero;fill:{color};fill-opacity:1;" d="M 343.453125 190.519531 C 322.914062 158.628906 297.171875 134.777344 266.222656 118.964844 C 274.46875 133.019531 278.589844 148.222656 278.589844 164.574219 C 278.589844 189.574219 269.703125 210.960938 251.933594 228.730469 C 234.164062 246.5 212.777344 255.386719 187.777344 255.386719 C 162.777344 255.386719 141.394531 246.5 123.621094 228.730469 C 105.851562 210.960938 96.96875 189.574219 96.96875 164.574219 C 96.96875 148.222656 101.089844 133.019531 109.332031 118.964844 C 78.386719 134.777344 52.644531 158.628906 32.101562 190.519531 C 50.074219 218.222656 72.609375 240.285156 99.703125 256.703125 C 126.796875 273.121094 156.15625 281.332031 187.777344 281.332031 C 219.398438 281.332031 248.757812 273.121094 275.851562 256.703125 C 302.945312 240.285156 325.480469 218.222656 343.453125 190.519531 Z M 197.507812 112.683594 C 197.507812 109.980469 196.5625 107.683594 194.671875 105.789062 C 192.777344 103.898438 190.480469 102.953125 187.777344 102.953125 C 170.886719 102.953125 156.394531 109 144.296875 121.09375 C 132.203125 133.1875 126.15625 147.683594 126.15625 164.574219 C 126.15625 167.277344 127.101562 169.574219 128.996094 171.464844 C 130.886719 173.359375 133.183594 174.304688 135.886719 174.304688 C 138.589844 174.304688 140.886719 173.359375 142.777344 171.464844 C 144.671875 169.574219 145.617188 167.277344 145.617188 164.574219 C 145.617188 152.953125 149.738281 143.019531 157.980469 134.777344 C 166.222656 126.535156 176.15625 122.410156 187.777344 122.410156 C 190.480469 122.410156 192.777344 121.464844 194.671875 119.574219 C 196.5625 117.683594 197.507812 115.386719 197.507812 112.683594 Z M 369.398438 190.519531 C 369.398438 195.113281 368.046875 199.777344 365.347656 204.507812 C 346.425781 235.585938 320.988281 260.484375 289.027344 279.203125 C 257.070312 297.917969 223.320312 307.277344 187.777344 307.277344 C 152.238281 307.277344 118.488281 297.886719 86.527344 279.101562 C 54.570312 260.316406 29.128906 235.453125 10.210938 204.507812 C 7.507812 199.777344 6.15625 195.113281 6.15625 190.519531 C 6.15625 185.925781 7.507812 181.261719 10.210938 176.535156 C 29.128906 145.585938 54.570312 120.722656 86.527344 101.9375 C 118.488281 83.15625 152.238281 73.761719 187.777344 73.761719 C 223.320312 73.761719 257.070312 83.15625 289.027344 101.9375 C 320.988281 120.722656 346.425781 145.585938 365.347656 176.535156 C 368.046875 181.261719 369.398438 185.925781 369.398438 190.519531 Z M 369.398438 190.519531 "/> </g> </svg>

View file

@ -1,4 +1,4 @@
<script>
export let color = "#000000"
</script>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown xmlns="http://www.w3.org/2000/svg" width="328px" height="374px" viewBox="0 0 328 374" version="1.1"> <g id="surface1"> <path d="M 204.175781 186.890625 L 204.175781 350.699219 C 204.683594 353.851562 204.40625 357.082031 203.367188 360.09375 C 202.328125 363.105469 200.5625 365.8125 198.230469 367.957031 C 194.390625 371.824219 189.195312 374 183.78125 374 C 178.363281 374 173.171875 371.824219 169.332031 367.957031 L 128.335938 326.378906 C 126.113281 324.152344 124.421875 321.4375 123.390625 318.445312 C 122.363281 315.453125 122.019531 312.269531 122.390625 309.121094 L 122.390625 187.09375 L 4.328125 33.679688 C 1 29.34375 -0.503906 23.851562 0.148438 18.398438 C 0.800781 12.945312 3.558594 7.976562 7.8125 4.578125 C 11.417969 1.644531 15.898438 0.0273438 20.519531 0 L 307.480469 0 C 312.105469 0.0273438 316.582031 1.644531 320.1875 4.578125 C 324.445312 7.976562 327.199219 12.945312 327.851562 18.398438 C 328.503906 23.851562 327 29.34375 323.671875 33.679688 L 205.609375 187.09375 Z M 204.175781 186.890625 "/> </g> </svg>
<svg {...$$restProps} on:click on:mouseover on:mouseenter on:mouseleave on:keydown on:focus xmlns="http://www.w3.org/2000/svg" width="328px" height="374px" viewBox="0 0 328 374" version="1.1"> <g id="surface1"> <path d="M 204.175781 186.890625 L 204.175781 350.699219 C 204.683594 353.851562 204.40625 357.082031 203.367188 360.09375 C 202.328125 363.105469 200.5625 365.8125 198.230469 367.957031 C 194.390625 371.824219 189.195312 374 183.78125 374 C 178.363281 374 173.171875 371.824219 169.332031 367.957031 L 128.335938 326.378906 C 126.113281 324.152344 124.421875 321.4375 123.390625 318.445312 C 122.363281 315.453125 122.019531 312.269531 122.390625 309.121094 L 122.390625 187.09375 L 4.328125 33.679688 C 1 29.34375 -0.503906 23.851562 0.148438 18.398438 C 0.800781 12.945312 3.558594 7.976562 7.8125 4.578125 C 11.417969 1.644531 15.898438 0.0273438 20.519531 0 L 307.480469 0 C 312.105469 0.0273438 316.582031 1.644531 320.1875 4.578125 C 324.445312 7.976562 327.199219 12.945312 327.851562 18.398438 C 328.503906 23.851562 327 29.34375 323.671875 33.679688 L 205.609375 187.09375 Z M 204.175781 186.890625 "/> </g> </svg>

Some files were not shown because too many files have changed in this diff Show more