Chore: regenerate docs, lint
This commit is contained in:
parent
7b41b617f6
commit
bad0edd4b0
201 changed files with 6044 additions and 1750 deletions
|
@ -1,14 +1,42 @@
|
|||
import { Utils } from "../../Utils"
|
||||
/** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */
|
||||
export class ThemeMetaTagging {
|
||||
public static readonly themeName = "usersettings"
|
||||
public static readonly themeName = "usersettings"
|
||||
|
||||
public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) {
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )
|
||||
Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/</g,'<')?.replace(/>/g,'>') ?? '' )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) )
|
||||
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a )
|
||||
feat.properties['__current_backgroun'] = 'initial_value'
|
||||
}
|
||||
}
|
||||
public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) {
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () =>
|
||||
feat.properties._description
|
||||
.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)
|
||||
?.at(1)
|
||||
)
|
||||
Utils.AddLazyProperty(
|
||||
feat.properties,
|
||||
"_d",
|
||||
() => feat.properties._description?.replace(/</g, "<")?.replace(/>/g, ">") ?? ""
|
||||
)
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () =>
|
||||
((feat) => {
|
||||
const e = document.createElement("div")
|
||||
e.innerHTML = feat.properties._d
|
||||
return Array.from(e.getElementsByTagName("a")).filter(
|
||||
(a) => a.href.match(/mastodon|en.osm.town/) !== null
|
||||
)[0]?.href
|
||||
})(feat)
|
||||
)
|
||||
Utils.AddLazyProperty(feat.properties, "_mastodon_link", () =>
|
||||
((feat) => {
|
||||
const e = document.createElement("div")
|
||||
e.innerHTML = feat.properties._d
|
||||
return Array.from(e.getElementsByTagName("a")).filter(
|
||||
(a) => a.getAttribute("rel")?.indexOf("me") >= 0
|
||||
)[0]?.href
|
||||
})(feat)
|
||||
)
|
||||
Utils.AddLazyProperty(
|
||||
feat.properties,
|
||||
"_mastodon_candidate",
|
||||
() => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a
|
||||
)
|
||||
feat.properties["__current_backgroun"] = "initial_value"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
|
||||
/**
|
||||
* An A11Y feature which indicates how far away and in what direction the feature lies.
|
||||
*
|
||||
|
@ -30,9 +29,9 @@
|
|||
let bearing = Math.round(GeoOperations.bearing(mapCenter, fcenter))
|
||||
let dist = Math.round(GeoOperations.distanceBetween(fcenter, mapCenter))
|
||||
return { bearing, dist }
|
||||
},
|
||||
}
|
||||
)
|
||||
let bearingFromGps = state.geolocation.geolocationState.currentGPSLocation.mapD(coordinate => {
|
||||
let bearingFromGps = state.geolocation.geolocationState.currentGPSLocation.mapD((coordinate) => {
|
||||
return GeoOperations.bearing([coordinate.longitude, coordinate.latitude], fcenter)
|
||||
})
|
||||
let compass = Orientation.singleton.alpha
|
||||
|
@ -40,7 +39,8 @@
|
|||
let relativeDirections = Translations.t.general.visualFeedback.directionsRelative
|
||||
let absoluteDirections = Translations.t.general.visualFeedback.directionsAbsolute
|
||||
|
||||
let closeToCurrentLocation = state.geolocation.geolocationState.currentGPSLocation.map(gps => {
|
||||
let closeToCurrentLocation = state.geolocation.geolocationState.currentGPSLocation.map(
|
||||
(gps) => {
|
||||
if (!gps) {
|
||||
return false
|
||||
}
|
||||
|
@ -49,60 +49,69 @@
|
|||
const dist = GeoOperations.distanceBetween([gps.longitude, gps.latitude], mapCenter)
|
||||
return dist < Constants.viewportCenterCloseToGpsCutoff
|
||||
},
|
||||
[state.mapProperties.location],
|
||||
[state.mapProperties.location]
|
||||
)
|
||||
let labelFromCenter: Store<string> = bearingAndDist.mapD(
|
||||
({ bearing, dist }) => {
|
||||
const distHuman = GeoOperations.distanceToHuman(dist)
|
||||
const lang = Locale.language.data
|
||||
const t = absoluteDirections[GeoOperations.bearingToHuman(bearing)]
|
||||
const mainTr = Translations.t.general.visualFeedback.fromMapCenter.Subs({
|
||||
distance: distHuman,
|
||||
direction: t.textFor(lang),
|
||||
})
|
||||
return mainTr.textFor(lang)
|
||||
},
|
||||
[compass, Locale.language]
|
||||
)
|
||||
let labelFromCenter: Store<string> = bearingAndDist.mapD(({ bearing, dist }) => {
|
||||
const distHuman = GeoOperations.distanceToHuman(dist)
|
||||
const lang = Locale.language.data
|
||||
const t = absoluteDirections[GeoOperations.bearingToHuman(bearing)]
|
||||
const mainTr = Translations.t.general.visualFeedback.fromMapCenter.Subs({
|
||||
distance: distHuman,
|
||||
direction: t.textFor(lang),
|
||||
})
|
||||
return mainTr.textFor(lang)
|
||||
}, [compass, Locale.language])
|
||||
|
||||
|
||||
// Bearing and distance relative to the map center
|
||||
let bearingAndDistGps: Store<{
|
||||
bearing: number;
|
||||
dist: number
|
||||
} | undefined> = state.geolocation.geolocationState.currentGPSLocation.mapD(
|
||||
({ longitude, latitude }) => {
|
||||
let gps = [longitude, latitude]
|
||||
let bearing = Math.round(GeoOperations.bearing(gps, fcenter))
|
||||
let dist = Math.round(GeoOperations.distanceBetween(fcenter, gps))
|
||||
return { bearing, dist }
|
||||
},
|
||||
)
|
||||
let labelFromGps: Store<string | undefined> = bearingAndDistGps.mapD(({ bearing, dist }) => {
|
||||
const distHuman = GeoOperations.distanceToHuman(dist)
|
||||
const lang = Locale.language.data
|
||||
let bearingHuman: string
|
||||
if (compass.data !== undefined) {
|
||||
console.log("compass:", compass.data)
|
||||
const bearingRelative = bearing - compass.data
|
||||
const t = relativeDirections[GeoOperations.bearingToHumanRelative(bearingRelative)]
|
||||
bearingHuman = t.textFor(lang)
|
||||
} else {
|
||||
bearingHuman = absoluteDirections[GeoOperations.bearingToHuman(bearing)].textFor(lang)
|
||||
}
|
||||
const mainTr = Translations.t.general.visualFeedback.fromGps.Subs({
|
||||
distance: distHuman,
|
||||
direction: bearingHuman,
|
||||
})
|
||||
return mainTr.textFor(lang)
|
||||
}, [compass, Locale.language])
|
||||
|
||||
let label = labelFromCenter.map(labelFromCenter => {
|
||||
if (labelFromGps.data !== undefined) {
|
||||
if (closeToCurrentLocation.data) {
|
||||
return labelFromGps.data
|
||||
let bearingAndDistGps: Store<
|
||||
| {
|
||||
bearing: number
|
||||
dist: number
|
||||
}
|
||||
return labelFromCenter + ", " + labelFromGps.data
|
||||
}
|
||||
return labelFromCenter
|
||||
}, [labelFromGps])
|
||||
| undefined
|
||||
> = state.geolocation.geolocationState.currentGPSLocation.mapD(({ longitude, latitude }) => {
|
||||
let gps = [longitude, latitude]
|
||||
let bearing = Math.round(GeoOperations.bearing(gps, fcenter))
|
||||
let dist = Math.round(GeoOperations.distanceBetween(fcenter, gps))
|
||||
return { bearing, dist }
|
||||
})
|
||||
let labelFromGps: Store<string | undefined> = bearingAndDistGps.mapD(
|
||||
({ bearing, dist }) => {
|
||||
const distHuman = GeoOperations.distanceToHuman(dist)
|
||||
const lang = Locale.language.data
|
||||
let bearingHuman: string
|
||||
if (compass.data !== undefined) {
|
||||
console.log("compass:", compass.data)
|
||||
const bearingRelative = bearing - compass.data
|
||||
const t = relativeDirections[GeoOperations.bearingToHumanRelative(bearingRelative)]
|
||||
bearingHuman = t.textFor(lang)
|
||||
} else {
|
||||
bearingHuman = absoluteDirections[GeoOperations.bearingToHuman(bearing)].textFor(lang)
|
||||
}
|
||||
const mainTr = Translations.t.general.visualFeedback.fromGps.Subs({
|
||||
distance: distHuman,
|
||||
direction: bearingHuman,
|
||||
})
|
||||
return mainTr.textFor(lang)
|
||||
},
|
||||
[compass, Locale.language]
|
||||
)
|
||||
|
||||
let label = labelFromCenter.map(
|
||||
(labelFromCenter) => {
|
||||
if (labelFromGps.data !== undefined) {
|
||||
if (closeToCurrentLocation.data) {
|
||||
return labelFromGps.data
|
||||
}
|
||||
return labelFromCenter + ", " + labelFromGps.data
|
||||
}
|
||||
return labelFromCenter
|
||||
},
|
||||
[labelFromGps]
|
||||
)
|
||||
|
||||
function focusMap() {
|
||||
state.mapProperties.location.setData({ lon: fcenter[0], lat: fcenter[1] })
|
||||
|
@ -110,19 +119,33 @@
|
|||
</script>
|
||||
|
||||
{#if $bearingAndDistGps === undefined}
|
||||
<button class={twMerge("relative rounded-full soft p-1", size)} on:click={() => focusMap()}
|
||||
use:ariaLabelStore={label}>
|
||||
<Center class="w-7 h-7"/>
|
||||
<button
|
||||
class={twMerge("soft relative rounded-full p-1", size)}
|
||||
on:click={() => focusMap()}
|
||||
use:ariaLabelStore={label}
|
||||
>
|
||||
<Center class="h-7 w-7" />
|
||||
</button>
|
||||
{:else}
|
||||
<button class={twMerge("relative rounded-full soft", size)} on:click={() => focusMap()} use:ariaLabelStore={label}>
|
||||
<div class={twMerge("absolute top-0 left-0 flex items-center justify-center text-sm break-words",size)}>
|
||||
<button
|
||||
class={twMerge("soft relative rounded-full", size)}
|
||||
on:click={() => focusMap()}
|
||||
use:ariaLabelStore={label}
|
||||
>
|
||||
<div
|
||||
class={twMerge(
|
||||
"absolute top-0 left-0 flex items-center justify-center break-words text-sm",
|
||||
size
|
||||
)}
|
||||
>
|
||||
{GeoOperations.distanceToHuman($bearingAndDistGps?.dist)}
|
||||
</div>
|
||||
{#if $bearingFromGps !== undefined}
|
||||
<div class={twMerge("absolute top-0 left-0 rounded-full", size)}>
|
||||
<Compass_arrow class={size}
|
||||
style={`transform: rotate( calc( 45deg + ${$bearingFromGps - ($compass ?? 0)}deg) );`} />
|
||||
<Compass_arrow
|
||||
class={size}
|
||||
style={`transform: rotate( calc( 45deg + ${$bearingFromGps - ($compass ?? 0)}deg) );`}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</script>
|
||||
|
||||
<div class={twMerge("flex p-1 pl-2", cls)}>
|
||||
<div class="min-w-6 h-6 w-6 animate-spin self-center shrink-0">
|
||||
<div class="min-w-6 h-6 w-6 shrink-0 animate-spin self-center">
|
||||
<ToSvelte construct={Svg.loading_svg()} />
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
|
|
|
@ -28,8 +28,11 @@
|
|||
</script>
|
||||
|
||||
{#if isIcon}
|
||||
<button on:click={share} class="soft no-image-background m-0 h-8 w-8 p-0"
|
||||
use:ariaLabel={Translations.t.general.share}>
|
||||
<button
|
||||
on:click={share}
|
||||
class="soft no-image-background m-0 h-8 w-8 p-0"
|
||||
use:ariaLabel={Translations.t.general.share}
|
||||
>
|
||||
<slot name="content">
|
||||
<Share class="h-7 w-7 p-1" />
|
||||
</slot>
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
export let cls: string = ""
|
||||
// Text for the current language
|
||||
let txt: Store<string | undefined> = t?.current
|
||||
$: {txt = t?.current}
|
||||
$: {
|
||||
txt = t?.current
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $txt}
|
||||
|
|
|
@ -17,31 +17,48 @@
|
|||
let map = state.mapProperties
|
||||
|
||||
let currentLocation = state.geolocation.geolocationState.currentGPSLocation
|
||||
let distanceToCurrentLocation: Store<{ distance: string, distanceInMeters: number, bearing: number }> = map.location.mapD(({ lon, lat }) => {
|
||||
const current = currentLocation.data
|
||||
if (!current) {
|
||||
return undefined
|
||||
}
|
||||
const gps: [number, number] = [current.longitude, current.latitude]
|
||||
const mapCenter: [number, number] = [lon, lat]
|
||||
const distanceInMeters = Math.round(GeoOperations.distanceBetween(gps, mapCenter))
|
||||
const distance = GeoOperations.distanceToHuman(distanceInMeters)
|
||||
const bearing = Math.round(GeoOperations.bearing(gps, mapCenter))
|
||||
const bearingDirection = GeoOperations.bearingToHuman(bearing)
|
||||
return { distance, bearing, distanceInMeters, bearingDirection }
|
||||
}, [currentLocation])
|
||||
let distanceToCurrentLocation: Store<{
|
||||
distance: string
|
||||
distanceInMeters: number
|
||||
bearing: number
|
||||
}> = map.location.mapD(
|
||||
({ lon, lat }) => {
|
||||
const current = currentLocation.data
|
||||
if (!current) {
|
||||
return undefined
|
||||
}
|
||||
const gps: [number, number] = [current.longitude, current.latitude]
|
||||
const mapCenter: [number, number] = [lon, lat]
|
||||
const distanceInMeters = Math.round(GeoOperations.distanceBetween(gps, mapCenter))
|
||||
const distance = GeoOperations.distanceToHuman(distanceInMeters)
|
||||
const bearing = Math.round(GeoOperations.bearing(gps, mapCenter))
|
||||
const bearingDirection = GeoOperations.bearingToHuman(bearing)
|
||||
return { distance, bearing, distanceInMeters, bearingDirection }
|
||||
},
|
||||
[currentLocation]
|
||||
)
|
||||
let hasCompass = Orientation.singleton.gotMeasurement
|
||||
let compass = Orientation.singleton.alpha
|
||||
let relativeBearing: Store<{distance: string, bearing: Translation}> =
|
||||
compass.mapD(compass => {
|
||||
const bearing: Translation = relativeDir[GeoOperations.bearingToHumanRelative(distanceToCurrentLocation.data.bearing - compass)]
|
||||
return {bearing, distance: distanceToCurrentLocation.data.distance}
|
||||
}, [distanceToCurrentLocation])
|
||||
let viewportCenterDetails = Translations.DynamicSubstitute(t.viewportCenterDetails, relativeBearing)
|
||||
let viewportCenterDetailsAbsolute = Translations.DynamicSubstitute(t.viewportCenterDetails, distanceToCurrentLocation.mapD(({distance, bearing}) => {
|
||||
return {distance, bearing: t.directionsAbsolute[GeoOperations.bearingToHuman(bearing)]}
|
||||
}))
|
||||
|
||||
let relativeBearing: Store<{ distance: string; bearing: Translation }> = compass.mapD(
|
||||
(compass) => {
|
||||
const bearing: Translation =
|
||||
relativeDir[
|
||||
GeoOperations.bearingToHumanRelative(distanceToCurrentLocation.data.bearing - compass)
|
||||
]
|
||||
return { bearing, distance: distanceToCurrentLocation.data.distance }
|
||||
},
|
||||
[distanceToCurrentLocation]
|
||||
)
|
||||
let viewportCenterDetails = Translations.DynamicSubstitute(
|
||||
t.viewportCenterDetails,
|
||||
relativeBearing
|
||||
)
|
||||
let viewportCenterDetailsAbsolute = Translations.DynamicSubstitute(
|
||||
t.viewportCenterDetails,
|
||||
distanceToCurrentLocation.mapD(({ distance, bearing }) => {
|
||||
return { distance, bearing: t.directionsAbsolute[GeoOperations.bearingToHuman(bearing)] }
|
||||
})
|
||||
)
|
||||
</script>
|
||||
|
||||
{#if $currentLocation !== undefined}
|
||||
|
|
|
@ -45,9 +45,7 @@
|
|||
() => {
|
||||
displayLocation()
|
||||
},
|
||||
[
|
||||
Translations.t.hotkeyDocumentation.shakePhone
|
||||
]
|
||||
[Translations.t.hotkeyDocumentation.shakePhone]
|
||||
)
|
||||
|
||||
Motion.singleton.startListening()
|
||||
|
@ -56,9 +54,9 @@
|
|||
{#if currentLocation}
|
||||
<div
|
||||
aria-live="assertive"
|
||||
class="normal-background border-interactive rounded-full px-2 flex flex-col items-center"
|
||||
class="normal-background border-interactive flex flex-col items-center rounded-full px-2"
|
||||
>
|
||||
{currentLocation}.
|
||||
<MapCenterDetails {state}/>
|
||||
<MapCenterDetails {state} />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -32,10 +32,10 @@
|
|||
<!-- Title element-->
|
||||
<h3>
|
||||
<a href={`#${$tags.id}`}>
|
||||
<TagRenderingAnswer config={layer.title} {selectedElement} {state} {tags} {layer} />
|
||||
<TagRenderingAnswer config={layer.title} {selectedElement} {state} {tags} {layer} />
|
||||
</a>
|
||||
</h3>
|
||||
|
||||
|
||||
<div
|
||||
class="no-weblate title-icons links-as-button mr-2 flex flex-row flex-wrap items-center gap-x-0.5 p-1 pt-0.5 sm:pt-1"
|
||||
>
|
||||
|
|
|
@ -12,17 +12,24 @@
|
|||
let id = feature.properties.id
|
||||
let tags = state.featureProperties.getStore(id)
|
||||
let layer: LayerConfig = state.layout.getMatchingLayer(tags.data)
|
||||
|
||||
</script>
|
||||
|
||||
<span class="inline-flex gap-x-1">
|
||||
|
||||
<a class="small flex space-x-0.5 cursor-pointer w-fit items-center" href={`#${feature.properties.id}`}>
|
||||
{#if i !== undefined}
|
||||
<span class="font-bold">{i + 1} </span>
|
||||
{/if}
|
||||
<TagRenderingAnswer config={layer.title} extraClasses="inline-flex w-fit" {layer} selectedElement={feature} {state}
|
||||
{tags} />
|
||||
</a>
|
||||
<a
|
||||
class="small flex w-fit cursor-pointer items-center space-x-0.5"
|
||||
href={`#${feature.properties.id}`}
|
||||
>
|
||||
{#if i !== undefined}
|
||||
<span class="font-bold">{i + 1} </span>
|
||||
{/if}
|
||||
<TagRenderingAnswer
|
||||
config={layer.title}
|
||||
extraClasses="inline-flex w-fit"
|
||||
{layer}
|
||||
selectedElement={feature}
|
||||
{state}
|
||||
{tags}
|
||||
/>
|
||||
</a>
|
||||
<DirectionIndicator {feature} {state} />
|
||||
</span>
|
||||
|
|
|
@ -15,16 +15,17 @@
|
|||
const t = Translations.t.general.visualFeedback
|
||||
let map = state.mapProperties
|
||||
let centerFeatures = state.closestFeatures.features
|
||||
let translationWithLength = centerFeatures.mapD(cf => cf.length).mapD(n => {
|
||||
if (n === 1) {
|
||||
return t.oneFeatureInView
|
||||
}
|
||||
return t.closestFeaturesAre.Subs({ n })
|
||||
})
|
||||
|
||||
let translationWithLength = centerFeatures
|
||||
.mapD((cf) => cf.length)
|
||||
.mapD((n) => {
|
||||
if (n === 1) {
|
||||
return t.oneFeatureInView
|
||||
}
|
||||
return t.closestFeaturesAre.Subs({ n })
|
||||
})
|
||||
|
||||
let lastAction: UIEventSource<KeyNavigationEvent> = new UIEventSource<KeyNavigationEvent>(
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
state.mapProperties.onKeyNavigationEvent((event) => {
|
||||
lastAction.setData(event)
|
||||
|
@ -32,11 +33,11 @@
|
|||
lastAction.stabilized(750).addCallbackAndRunD((_) => lastAction.setData(undefined))
|
||||
</script>
|
||||
|
||||
<div aria-live="assertive" class="p-1 bg-white m-1 rounded">
|
||||
<div aria-live="assertive" class="m-1 rounded bg-white p-1">
|
||||
{#if $lastAction?.key === "out"}
|
||||
<Tr t={t.out.Subs({z: map.zoom.data - 1})} />
|
||||
<Tr t={t.out.Subs({ z: map.zoom.data - 1 })} />
|
||||
{:else if $lastAction?.key === "in"}
|
||||
<Tr t={t.out.Subs({z: map.zoom.data + 1})} />
|
||||
<Tr t={t.out.Subs({ z: map.zoom.data + 1 })} />
|
||||
{:else if $lastAction !== undefined}
|
||||
<Tr t={t[$lastAction.key]} />
|
||||
{:else if $centerFeatures?.length === 0}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
class="title-icons links-as-button flex flex-wrap items-center gap-x-0.5 self-end justify-self-end p-1 pt-0.5 sm:pt-1"
|
||||
>
|
||||
{#each favConfig.titleIcons as titleIconConfig}
|
||||
{#if titleIconBlacklist.indexOf(titleIconConfig.id) < 0 && (titleIconConfig.condition?.matchesProperties(properties) ?? true) && (titleIconConfig.metacondition?.matchesProperties({ ...properties, ...state.userRelatedState.preferencesAsTags.data }) ?? true) && titleIconConfig.IsKnown(properties)}
|
||||
{#if titleIconBlacklist.indexOf(titleIconConfig.id) < 0 && (titleIconConfig.condition?.matchesProperties(properties) ?? true) && (titleIconConfig.metacondition?.matchesProperties( { ...properties, ...state.userRelatedState.preferencesAsTags.data } ) ?? true) && titleIconConfig.IsKnown(properties)}
|
||||
<div class={titleIconConfig.renderIconClass ?? "flex h-8 w-8 items-center"}>
|
||||
<TagRenderingAnswer
|
||||
config={titleIconConfig}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
export let image: ProvidedImage
|
||||
export let clss: string = undefined
|
||||
|
||||
|
||||
let isLoaded = new UIEventSource(false)
|
||||
async function download() {
|
||||
const response = await fetch(image.url_hd ?? image.url)
|
||||
|
@ -28,11 +28,11 @@
|
|||
<div class={twMerge("relative h-full w-full", clss)}>
|
||||
<div class="panzoom-container focusable absolute top-0 left-0 h-full w-full overflow-hidden">
|
||||
{#if !$isLoaded}
|
||||
<div class="w-full h-full flex items-center justify-center">
|
||||
<Loading/>
|
||||
<div class="flex h-full w-full items-center justify-center">
|
||||
<Loading />
|
||||
</div>
|
||||
{/if}
|
||||
<ImagePreview {image} {isLoaded}/>
|
||||
{/if}
|
||||
<ImagePreview {image} {isLoaded} />
|
||||
</div>
|
||||
<div
|
||||
class="pointer-events-none absolute bottom-0 left-0 flex w-full flex-wrap items-end justify-between"
|
||||
|
|
|
@ -26,5 +26,11 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<img bind:this={panzoomEl} class="panzoom-image h-fit w-fit" on:load={() => {isLoaded?.setData(true)}}
|
||||
src={image.url_hd ?? image.url} />
|
||||
<img
|
||||
bind:this={panzoomEl}
|
||||
class="panzoom-image h-fit w-fit"
|
||||
on:load={() => {
|
||||
isLoaded?.setData(true)
|
||||
}}
|
||||
src={image.url_hd ?? image.url}
|
||||
/>
|
||||
|
|
|
@ -27,31 +27,31 @@
|
|||
|
||||
<LoginToggle {state}>
|
||||
<div class="my-4">
|
||||
{#if expanded}
|
||||
<NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer}>
|
||||
{#if expanded}
|
||||
<NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer}>
|
||||
<button
|
||||
slot="corner"
|
||||
class="no-image-background h-6 w-6 cursor-pointer border-none p-0"
|
||||
use:ariaLabel={t.close}
|
||||
on:click={() => {
|
||||
expanded = false
|
||||
}}
|
||||
>
|
||||
<XCircleIcon />
|
||||
</button>
|
||||
</NearbyImages>
|
||||
{:else}
|
||||
<button
|
||||
slot="corner"
|
||||
class="no-image-background h-6 w-6 cursor-pointer border-none p-0"
|
||||
use:ariaLabel={t.close}
|
||||
class="flex w-full items-center"
|
||||
style="margin-left: 0; margin-right: 0"
|
||||
on:click={() => {
|
||||
expanded = false
|
||||
expanded = true
|
||||
}}
|
||||
aria-expanded={expanded}
|
||||
>
|
||||
<XCircleIcon />
|
||||
<Camera_plus class="mr-2 block h-8 w-8 p-1" />
|
||||
<Tr t={t.seeNearby} />
|
||||
</button>
|
||||
</NearbyImages>
|
||||
{:else}
|
||||
<button
|
||||
class="flex w-full items-center"
|
||||
style="margin-left: 0; margin-right: 0"
|
||||
on:click={() => {
|
||||
expanded = true
|
||||
}}
|
||||
aria-expanded={expanded}
|
||||
>
|
||||
<Camera_plus class="mr-2 block h-8 w-8 p-1" />
|
||||
<Tr t={t.seeNearby} />
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</LoginToggle>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
>
|
||||
<Tr t={t.currentLicense.Subs({ license: $licenseStore })} />
|
||||
</button>
|
||||
<br/>
|
||||
<br />
|
||||
<Tr t={t.respectPrivacy} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
if (maxDistanceInMeters) {
|
||||
onDestroy(
|
||||
mla.location.addCallbackD((newLocation) => {
|
||||
const l : [number, number] = [newLocation.lon, newLocation.lat]
|
||||
const l: [number, number] = [newLocation.lon, newLocation.lat]
|
||||
const c: [number, number] = [initialCoordinate.lon, initialCoordinate.lat]
|
||||
const d = GeoOperations.distanceBetween(l, c)
|
||||
if (d <= maxDistanceInMeters) {
|
||||
|
|
|
@ -79,9 +79,9 @@
|
|||
},
|
||||
[valuesign, beta]
|
||||
)
|
||||
|
||||
function onSave(){
|
||||
if(_value.data){
|
||||
|
||||
function onSave() {
|
||||
if (_value.data) {
|
||||
value.setData(_value.data)
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +100,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button class="primary" on:click={() => onSave()}>
|
||||
Select this incline
|
||||
</button>
|
||||
|
||||
<button class="primary" on:click={() => onSave()}>Select this incline</button>
|
||||
|
||||
<div>
|
||||
<Tr t={Translations.t.validation.slope.inputExplanation} />
|
||||
</div>
|
||||
|
|
|
@ -39,7 +39,10 @@
|
|||
|
||||
{#if availableLanguages?.length > 1}
|
||||
<form class={twMerge("flex max-w-full items-center pr-4", clss)}>
|
||||
<label class="neutral-label flex max-w-full" use:ariaLabel={Translations.t.general.pickLanguage}>
|
||||
<label
|
||||
class="neutral-label flex max-w-full"
|
||||
use:ariaLabel={Translations.t.general.pickLanguage}
|
||||
>
|
||||
<LanguageIcon class="mr-1 h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
<Dropdown cls="max-w-full" value={assignTo}>
|
||||
{#if preferredFiltered}
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
if (_value.data !== fromUpstream && fromUpstream !== "") {
|
||||
_value.setData(fromUpstream)
|
||||
}
|
||||
}),
|
||||
})
|
||||
)
|
||||
} else {
|
||||
// Handled by the UnitInput
|
||||
|
@ -115,7 +115,7 @@
|
|||
Utils.sortedByLevenshteinDistance(
|
||||
type,
|
||||
Validators.AllValidators.map((v) => v.name),
|
||||
(v) => v,
|
||||
(v) => v
|
||||
)
|
||||
.slice(0, 5)
|
||||
.join(", ")
|
||||
|
@ -135,17 +135,16 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
{#if validator?.textArea}
|
||||
<textarea
|
||||
class="w-full"
|
||||
bind:value={$_value}
|
||||
inputmode={validator?.inputmode ?? "text"}
|
||||
placeholder={_placeholder}
|
||||
bind:this={htmlElem}
|
||||
/>
|
||||
<textarea
|
||||
class="w-full"
|
||||
bind:value={$_value}
|
||||
inputmode={validator?.inputmode ?? "text"}
|
||||
placeholder={_placeholder}
|
||||
bind:this={htmlElem}
|
||||
/>
|
||||
{:else}
|
||||
<div class={twMerge("inline-flex", cls)}>
|
||||
<input
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
let _rotation: Store<string> = rotation
|
||||
? tags.map((tags) => rotation.GetRenderValue(tags).Subs(tags).txt)
|
||||
: new ImmutableStore("0deg")
|
||||
if(rotation?.render?.txt === "{alpha}deg"){
|
||||
_rotation = Orientation.singleton.alpha.map(alpha => alpha ? (alpha)+"deg" : "0deg ")
|
||||
if (rotation?.render?.txt === "{alpha}deg") {
|
||||
_rotation = Orientation.singleton.alpha.map((alpha) => (alpha ? alpha + "deg" : "0deg "))
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -50,14 +50,14 @@
|
|||
window.requestAnimationFrame(() => {
|
||||
_map.resize()
|
||||
})
|
||||
_map.on("load", function() {
|
||||
_map.on("load", function () {
|
||||
_map.resize()
|
||||
const canvas = _map.getCanvas()
|
||||
const canvas = _map.getCanvas()
|
||||
if (interactive) {
|
||||
ariaLabel(canvas, Translations.t.general.visualFeedback.navigation)
|
||||
canvas.role = "application"
|
||||
canvas.tabIndex = 0
|
||||
}else{
|
||||
} else {
|
||||
canvas.tabIndex = -1
|
||||
_map.getContainer().tabIndex = -1
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if $isFavourite}
|
||||
<button
|
||||
class="m-0 h-8 w-8 p-0 soft no-image-background"
|
||||
class="soft no-image-background m-0 h-8 w-8 p-0"
|
||||
on:click={() => markFavourite(false)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isMarkedShort}
|
||||
>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
let txt = new UIEventSource(undefined)
|
||||
let _txt: string = undefined
|
||||
txt.addCallbackD(t => {
|
||||
txt.addCallbackD((t) => {
|
||||
_txt = t
|
||||
})
|
||||
$: {
|
||||
|
@ -60,15 +60,21 @@
|
|||
<LoginToggle ignoreLoading={true} {state}>
|
||||
<Tr slot="not-logged-in" t={t.loginToAddComment} />
|
||||
|
||||
<form class="m-0 px-2 py-1 flex flex-col border-2 border-black rounded-xl interactive border-interactive" on:submit|preventDefault={() => addComment()}>
|
||||
<form
|
||||
class="interactive border-interactive m-0 flex flex-col rounded-xl border-2 border-black px-2 py-1"
|
||||
on:submit|preventDefault={() => addComment()}
|
||||
>
|
||||
<label class="neutral-label font-bold">
|
||||
<Tr t={t.addAComment} />
|
||||
<textarea bind:value={_txt} class="w-full h-24 rounded-l border border-grey" rows="3"
|
||||
use:placeholder={t.addCommentPlaceholder} />
|
||||
<textarea
|
||||
bind:value={_txt}
|
||||
class="border-grey h-24 w-full rounded-l border"
|
||||
rows="3"
|
||||
use:placeholder={t.addCommentPlaceholder}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div class="flex flex-col">
|
||||
|
||||
{#if $txt?.length > 0}
|
||||
<button class="primary flex" on:click={() => addComment()}>
|
||||
<!-- Add a comment -->
|
||||
|
@ -81,7 +87,6 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
{#if !$isClosed}
|
||||
<button class="flex items-center" on:click={() => closeNote()}>
|
||||
<Resolved class="h-8 w-8 pr-2" />
|
||||
|
@ -102,10 +107,7 @@
|
|||
<Tr t={t.reopenNoteAndComment} />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</LoginToggle>
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
This theme does not include the layer 'note'. As a result, no nodes can be created
|
||||
</div>
|
||||
{:else if submitted}
|
||||
<Loading/>
|
||||
<Loading />
|
||||
{:else if created}
|
||||
<div class="thanks">
|
||||
<Tr t={Translations.t.notes.isCreated} />
|
||||
|
@ -111,7 +111,6 @@
|
|||
{:else}
|
||||
<form class="border-grey-500 rounded-sm border" on:submit|preventDefault={uploadNote}>
|
||||
<label class="neutral-label">
|
||||
|
||||
<Tr t={Translations.t.notes.createNoteIntro} />
|
||||
<div class="w-full p-1">
|
||||
<ValidatedInput autofocus={true} type="text" value={comment} />
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
}
|
||||
// TODO this has _to much_ values
|
||||
freeformInput.setData(unseenFreeformValues.join(";"))
|
||||
if(checkedMappings.length + 1 < mappings.length ){
|
||||
if (checkedMappings.length + 1 < mappings.length) {
|
||||
checkedMappings.push(unseenFreeformValues.length > 0)
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@
|
|||
initialize($tags, config)
|
||||
}
|
||||
|
||||
freeformInput.addCallbackAndRun(freeformValue => {
|
||||
freeformInput.addCallbackAndRun((freeformValue) => {
|
||||
console.log("FreeformValue:", freeformValue)
|
||||
if (!mappings || mappings?.length == 0 || config.freeform?.key === undefined) {
|
||||
return
|
||||
|
@ -151,7 +151,7 @@
|
|||
$freeformInput,
|
||||
selectedMapping,
|
||||
checkedMappings,
|
||||
tags.data,
|
||||
tags.data
|
||||
)
|
||||
} catch (e) {
|
||||
console.error("Could not calculate changeSpecification:", e)
|
||||
|
@ -202,7 +202,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
let featureSwitchIsTesting = state?.featureSwitchIsTesting ?? new ImmutableStore(false)
|
||||
let featureSwitchIsDebugging =
|
||||
state?.featureSwitches?.featureSwitchIsDebugging ?? new ImmutableStore(false)
|
||||
|
@ -214,7 +213,7 @@
|
|||
onDestroy(
|
||||
state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
|
||||
numberOfCs = ud.csCount
|
||||
}),
|
||||
})
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
@ -227,9 +226,9 @@
|
|||
>
|
||||
<label class="neutral-label">
|
||||
<div class="interactive sticky top-0 flex justify-between pt-1" style="z-index: 11">
|
||||
<span class="font-bold">
|
||||
<SpecialTranslation t={question} {tags} {state} {layer} feature={selectedElement} />
|
||||
</span>
|
||||
<span class="font-bold">
|
||||
<SpecialTranslation t={question} {tags} {state} {layer} feature={selectedElement} />
|
||||
</span>
|
||||
<slot name="upper-right" />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<StarsBar
|
||||
on:click={(e) => {
|
||||
confirmedScore = e.detail.score
|
||||
score=confirmedScore
|
||||
score = confirmedScore
|
||||
console.log("Confirmed score is:", confirmedScore)
|
||||
}}
|
||||
on:hover={(e) => {
|
||||
|
@ -86,11 +86,17 @@
|
|||
|
||||
{#if confirmedScore !== undefined}
|
||||
<label class="neutral-label">
|
||||
<Tr cls="font-bold mt-2" t={t.question_opinion} />
|
||||
<textarea autofocus bind:value={$opinion} inputmode="text" rows="3" class="mb-1 w-full"
|
||||
use:placeholder={t.reviewPlaceholder}/>
|
||||
<Tr cls="font-bold mt-2" t={t.question_opinion} />
|
||||
<textarea
|
||||
autofocus
|
||||
bind:value={$opinion}
|
||||
inputmode="text"
|
||||
rows="3"
|
||||
class="mb-1 w-full"
|
||||
use:placeholder={t.reviewPlaceholder}
|
||||
/>
|
||||
</label>
|
||||
|
||||
|
||||
<Checkbox selected={isAffiliated}>
|
||||
<div class="flex flex-col">
|
||||
<Tr t={t.i_am_affiliated} />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import Tr from "../Base/Tr.svelte"
|
||||
import { ariaLabel } from "../../Utils/ariaLabel"
|
||||
|
||||
export let review: Review & { kid: string,signature: string, madeByLoggedInUser: Store<boolean> }
|
||||
export let review: Review & { kid: string; signature: string; madeByLoggedInUser: Store<boolean> }
|
||||
let name = review.metadata.nickname
|
||||
name ??= ((review.metadata.given_name ?? "") + " " + (review.metadata.family_name ?? "")).trim()
|
||||
let d = new Date()
|
||||
|
@ -17,17 +17,25 @@
|
|||
|
||||
<div class={"low-interaction rounded-lg p-1 px-2 " + ($byLoggedInUser ? "border-interactive" : "")}>
|
||||
<div class="flex items-center justify-between">
|
||||
<div tabindex="0" use:ariaLabel={Translations.t.reviews.rated.Subs({n: ""+(Math.round(review.rating / 10)/2)})}>
|
||||
<div
|
||||
tabindex="0"
|
||||
use:ariaLabel={Translations.t.reviews.rated.Subs({
|
||||
n: "" + Math.round(review.rating / 10) / 2,
|
||||
})}
|
||||
>
|
||||
<StarsBar readonly={true} score={review.rating} />
|
||||
</div>
|
||||
<div class="flex flex-wrap space-x-2">
|
||||
<a href={`https://mangrove.reviews/list?kid=${encodeURIComponent(review.kid)}`} rel="noopener"
|
||||
target="_blank">
|
||||
<a
|
||||
href={`https://mangrove.reviews/list?kid=${encodeURIComponent(review.kid)}`}
|
||||
rel="noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{#if !name}
|
||||
<i>Anonymous</i>
|
||||
{:else}
|
||||
<span class="font-bold">
|
||||
{name}
|
||||
{name}
|
||||
</span>
|
||||
{/if}
|
||||
</a>
|
||||
|
@ -38,10 +46,13 @@
|
|||
</div>
|
||||
{#if review.opinion}
|
||||
<div class="link-no-underline">
|
||||
<a target="_blank" rel="noopener nofollow"
|
||||
href={`https://mangrove.reviews/list?signature=${encodeURIComponent(review.signature)}`}>
|
||||
{review.opinion}
|
||||
</a>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener nofollow"
|
||||
href={`https://mangrove.reviews/list?signature=${encodeURIComponent(review.signature)}`}
|
||||
>
|
||||
{review.opinion}
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{#if review.metadata.is_affiliated}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
export let i: number
|
||||
export let readonly = false
|
||||
|
||||
let dispatch = createEventDispatcher<{ hover: { score: number }, click: { score: number } }>()
|
||||
let dispatch = createEventDispatcher<{ hover: { score: number }; click: { score: number } }>()
|
||||
let container: HTMLElement
|
||||
|
||||
function getScore(e: MouseEvent): number {
|
||||
|
@ -35,16 +35,17 @@
|
|||
{:else}
|
||||
<Star_outline class={starSize} />
|
||||
{/if}
|
||||
|
||||
{:else}
|
||||
<button
|
||||
use:ariaLabel={Translations.t.reviews.rate.Subs({n: i+1})}
|
||||
class="small soft rounded-full no-image-background"
|
||||
use:ariaLabel={Translations.t.reviews.rate.Subs({ n: i + 1 })}
|
||||
class="small soft no-image-background rounded-full"
|
||||
style="padding: 0; border: none;"
|
||||
bind:this={container}
|
||||
on:click={(e) =>{ console.log("Dispatching click", e); return dispatch("click", { score: getScore(e) }); }}
|
||||
on:mousemove={(e) => dispatch("hover", { score: getScore(e) }
|
||||
)}
|
||||
on:click={(e) => {
|
||||
console.log("Dispatching click", e)
|
||||
return dispatch("click", { score: getScore(e) })
|
||||
}}
|
||||
on:mousemove={(e) => dispatch("hover", { score: getScore(e) })}
|
||||
>
|
||||
{#if score >= cutoff}
|
||||
<Star class={starSize} />
|
||||
|
|
|
@ -5,12 +5,11 @@
|
|||
import Translations from "../i18n/Translations"
|
||||
|
||||
export let score: Store<number>
|
||||
let scoreRounded = score.mapD(count => Math.round(count / 10) / 2)
|
||||
let scoreRounded = score.mapD((count) => Math.round(count / 10) / 2)
|
||||
</script>
|
||||
|
||||
{#if $score !== undefined && $score !== null}
|
||||
<div tabindex="0"
|
||||
use:ariaLabel={Translations.t.reviews.averageRating.Subs({n: $scoreRounded})}>
|
||||
<div tabindex="0" use:ariaLabel={Translations.t.reviews.averageRating.Subs({ n: $scoreRounded })}>
|
||||
<StarsBar readonly={true} score={$score} />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -13,7 +13,13 @@
|
|||
import type { MapProperties } from "../Models/MapProperties"
|
||||
import Geosearch from "./BigComponents/Geosearch.svelte"
|
||||
import Translations from "./i18n/Translations"
|
||||
import { CogIcon, EyeIcon, HeartIcon, MenuIcon, XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import {
|
||||
CogIcon,
|
||||
EyeIcon,
|
||||
HeartIcon,
|
||||
MenuIcon,
|
||||
XCircleIcon,
|
||||
} from "@rgossiaux/svelte-heroicons/solid"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||
import FloatOver from "./Base/FloatOver.svelte"
|
||||
|
@ -95,7 +101,7 @@
|
|||
})
|
||||
|
||||
let selectedLayer: Store<LayerConfig> = state.selectedElement.mapD((element) =>
|
||||
state.layout.getMatchingLayer(element.properties),
|
||||
state.layout.getMatchingLayer(element.properties)
|
||||
)
|
||||
let currentZoom = state.mapProperties.zoom
|
||||
let showCrosshair = state.userRelatedState.showCrosshair
|
||||
|
@ -121,10 +127,10 @@
|
|||
state.visualFeedbackViewportBounds.setData(bbox)
|
||||
}
|
||||
|
||||
viewport.addCallbackAndRunD(_ => {
|
||||
viewport.addCallbackAndRunD((_) => {
|
||||
updateViewport()
|
||||
})
|
||||
mapproperties.bounds.addCallbackAndRunD(_ => {
|
||||
mapproperties.bounds.addCallbackAndRunD((_) => {
|
||||
updateViewport()
|
||||
})
|
||||
let featureSwitches: FeatureSwitchState = state.featureSwitches
|
||||
|
@ -136,15 +142,15 @@
|
|||
onDestroy(
|
||||
rasterLayer.addCallbackAndRunD((l) => {
|
||||
rasterLayerName = l.properties.name
|
||||
}),
|
||||
})
|
||||
)
|
||||
let previewedImage = state.previewedImage
|
||||
|
||||
|
||||
let debug = state.featureSwitches.featureSwitchIsDebugging
|
||||
debug.addCallbackAndRun(dbg => {
|
||||
if(dbg){
|
||||
debug.addCallbackAndRun((dbg) => {
|
||||
if (dbg) {
|
||||
document.body.classList.add("debug")
|
||||
}else{
|
||||
} else {
|
||||
document.body.classList.remove("debug")
|
||||
}
|
||||
})
|
||||
|
@ -168,16 +174,20 @@
|
|||
|
||||
{#if $visualFeedback}
|
||||
<div
|
||||
class="absolute top-0 left-0 flex h-screen w-screen items-center justify-center overflow-hidden pointer-events-none"
|
||||
class="pointer-events-none absolute top-0 left-0 flex h-screen w-screen items-center justify-center overflow-hidden"
|
||||
>
|
||||
<div bind:this={$viewport} class:border={$visualFeedback} style="border: 2px solid #ff000044; width: 300px; height: 300px" />
|
||||
<div
|
||||
bind:this={$viewport}
|
||||
class:border={$visualFeedback}
|
||||
style="border: 2px solid #ff000044; width: 300px; height: 300px"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="pointer-events-none absolute top-0 left-0 w-full">
|
||||
<!-- Top components -->
|
||||
|
||||
<div class="pointer-events-auto float-right mt-1 px-1 max-[480px]:w-full sm:m-2 flex flex-col">
|
||||
<div class="pointer-events-auto float-right mt-1 flex flex-col px-1 max-[480px]:w-full sm:m-2">
|
||||
<If condition={state.visualFeedback}>
|
||||
<div class="w-fit">
|
||||
<VisualFeedbackPanel {state} />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"contributors": [
|
||||
{
|
||||
"commits": 6578,
|
||||
"commits": 6607,
|
||||
"contributor": "Pieter Vander Vennet"
|
||||
},
|
||||
{
|
||||
|
@ -21,7 +21,7 @@
|
|||
"contributor": "Christian Neumann"
|
||||
},
|
||||
{
|
||||
"commits": 31,
|
||||
"commits": 32,
|
||||
"contributor": "Hosted Weblate"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -397,8 +397,8 @@
|
|||
"ro"
|
||||
],
|
||||
"MG": [
|
||||
"mg",
|
||||
"fr"
|
||||
"fr",
|
||||
"mg"
|
||||
],
|
||||
"MH": [
|
||||
"en",
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"contributors": [
|
||||
{
|
||||
"commits": 320,
|
||||
"commits": 321,
|
||||
"contributor": "kjon"
|
||||
},
|
||||
{
|
||||
"commits": 298,
|
||||
"commits": 300,
|
||||
"contributor": "Pieter Vander Vennet"
|
||||
},
|
||||
{
|
||||
"commits": 178,
|
||||
"commits": 179,
|
||||
"contributor": "paunofu"
|
||||
},
|
||||
{
|
||||
|
@ -50,11 +50,11 @@
|
|||
},
|
||||
{
|
||||
"commits": 29,
|
||||
"contributor": "Artem"
|
||||
"contributor": "mcliquid"
|
||||
},
|
||||
{
|
||||
"commits": 25,
|
||||
"contributor": "mcliquid"
|
||||
"commits": 29,
|
||||
"contributor": "Artem"
|
||||
},
|
||||
{
|
||||
"commits": 25,
|
||||
|
@ -116,6 +116,10 @@
|
|||
"commits": 11,
|
||||
"contributor": "Túllio Franca"
|
||||
},
|
||||
{
|
||||
"commits": 10,
|
||||
"contributor": "Ettore Atalan"
|
||||
},
|
||||
{
|
||||
"commits": 10,
|
||||
"contributor": "brunnerpaul"
|
||||
|
@ -144,10 +148,6 @@
|
|||
"commits": 9,
|
||||
"contributor": "快乐的老鼠宝宝"
|
||||
},
|
||||
{
|
||||
"commits": 9,
|
||||
"contributor": "Ettore Atalan"
|
||||
},
|
||||
{
|
||||
"commits": 9,
|
||||
"contributor": "deep map"
|
||||
|
@ -296,6 +296,10 @@
|
|||
"commits": 4,
|
||||
"contributor": "Jan Zabel"
|
||||
},
|
||||
{
|
||||
"commits": 3,
|
||||
"contributor": "Lasse Liehu"
|
||||
},
|
||||
{
|
||||
"commits": 3,
|
||||
"contributor": "Peter Brodersen"
|
||||
|
@ -364,6 +368,10 @@
|
|||
"commits": 3,
|
||||
"contributor": "SiegbjornSitumeang"
|
||||
},
|
||||
{
|
||||
"commits": 2,
|
||||
"contributor": "larusalka"
|
||||
},
|
||||
{
|
||||
"commits": 2,
|
||||
"contributor": "Smith Brown"
|
||||
|
@ -468,10 +476,6 @@
|
|||
"commits": 2,
|
||||
"contributor": "Leo Alcaraz"
|
||||
},
|
||||
{
|
||||
"commits": 1,
|
||||
"contributor": "Lasse Liehu"
|
||||
},
|
||||
{
|
||||
"commits": 1,
|
||||
"contributor": "Federica Gaspari"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue