Style: bring index page (and legacy subtle button) in line with the new style
This commit is contained in:
parent
8ed0a32d15
commit
64e791dbfb
13 changed files with 126 additions and 203 deletions
|
@ -27,7 +27,7 @@ export default class AllThemesGui {
|
||||||
new LoginToggle(undefined, Translations.t.index.logIn, {
|
new LoginToggle(undefined, Translations.t.index.logIn, {
|
||||||
osmConnection,
|
osmConnection,
|
||||||
featureSwitchUserbadge: new ImmutableStore(true),
|
featureSwitchUserbadge: new ImmutableStore(true),
|
||||||
}),
|
}).SetClass("flex justify-center w-full"),
|
||||||
Translations.t.general.aboutMapComplete.intro.SetClass("link-underline"),
|
Translations.t.general.aboutMapComplete.intro.SetClass("link-underline"),
|
||||||
new FixedUiElement("v" + Constants.vNumber).SetClass("block"),
|
new FixedUiElement("v" + Constants.vNumber).SetClass("block"),
|
||||||
])
|
])
|
||||||
|
|
|
@ -4,13 +4,15 @@ import { UIElement } from "../UIElement"
|
||||||
import { VariableUiElement } from "./VariableUIElement"
|
import { VariableUiElement } from "./VariableUIElement"
|
||||||
import Lazy from "./Lazy"
|
import Lazy from "./Lazy"
|
||||||
import Loading from "./Loading"
|
import Loading from "./Loading"
|
||||||
import SubtleButtonSvelte from "./SubtleButton.svelte"
|
|
||||||
import SvelteUIElement from "./SvelteUIElement"
|
import SvelteUIElement from "./SvelteUIElement"
|
||||||
import SubtleLink from "./SubtleLink.svelte";
|
import SubtleLink from "./SubtleLink.svelte";
|
||||||
import Translations from "../i18n/Translations";
|
import Translations from "../i18n/Translations";
|
||||||
import Combine from "./Combine";
|
import Combine from "./Combine";
|
||||||
import Img from "./Img";
|
import Img from "./Img";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
export class SubtleButton extends UIElement {
|
export class SubtleButton extends UIElement {
|
||||||
private readonly imageUrl: string | BaseUIElement
|
private readonly imageUrl: string | BaseUIElement
|
||||||
private readonly message: string | BaseUIElement
|
private readonly message: string | BaseUIElement
|
||||||
|
@ -42,7 +44,7 @@ export class SubtleButton extends UIElement {
|
||||||
return new SvelteUIElement(SubtleLink, {href: this.options.url, newTab: this.options.newTab})
|
return new SvelteUIElement(SubtleLink, {href: this.options.url, newTab: this.options.newTab})
|
||||||
}
|
}
|
||||||
|
|
||||||
const classes = "block flex p-3 my-2 bg-subtle rounded-lg hover:shadow-xl hover:bg-unsubtle transition-colors transition-shadow link-no-underline";
|
const classes = "button";
|
||||||
const message = Translations.W(this.message)?.SetClass("block overflow-ellipsis no-images flex-shrink");
|
const message = Translations.W(this.message)?.SetClass("block overflow-ellipsis no-images flex-shrink");
|
||||||
let img;
|
let img;
|
||||||
const imgClasses = "block justify-center flex-none mr-4 " + (this.options?.imgSize ?? "h-11 w-11")
|
const imgClasses = "block justify-center flex-none mr-4 " + (this.options?.imgSize ?? "h-11 w-11")
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
class={(options.extraClasses??"") + 'flex hover:shadow-xl transition-[color,background-color,box-shadow] hover:bg-unsubtle cursor-pointer'}
|
class={(options.extraClasses??"") + ' button text-ellipsis'}
|
||||||
{href}
|
{href}
|
||||||
target={(newTab ? "_blank" : undefined) }
|
target={(newTab ? "_blank" : undefined) }
|
||||||
>
|
>
|
||||||
|
@ -48,16 +48,3 @@
|
||||||
|
|
||||||
<slot/>
|
<slot/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
span,
|
|
||||||
a {
|
|
||||||
@apply flex p-3 my-2 py-4 rounded-lg shrink-0;
|
|
||||||
@apply items-center w-full no-underline;
|
|
||||||
@apply bg-subtle text-black;
|
|
||||||
|
|
||||||
:global(span) {
|
|
||||||
@apply block text-ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
export let onMainScreen: boolean = true
|
export let onMainScreen: boolean = true
|
||||||
|
|
||||||
const prefix = "mapcomplete-hidden-theme-"
|
const prefix = "mapcomplete-hidden-theme-"
|
||||||
const hiddenThemes: LayoutInformation[] = themeOverview.filter(
|
const hiddenThemes: LayoutInformation[] = (themeOverview["default"] ?? themeOverview)?.filter(
|
||||||
(layout) => layout.hideFromOverview
|
(layout) => layout.hideFromOverview
|
||||||
)
|
) ?? []
|
||||||
const userPreferences = state.osmConnection.preferencesHandler.preferences
|
const userPreferences = state.osmConnection.preferencesHandler.preferences
|
||||||
const t = Translations.t.general.morescreen
|
const t = Translations.t.general.morescreen
|
||||||
|
|
||||||
|
@ -45,3 +45,4 @@
|
||||||
</p>
|
</p>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</ThemesList>
|
</ThemesList>
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
import Svg from "../../Svg"
|
import Svg from "../../Svg"
|
||||||
import Combine from "../Base/Combine"
|
import Combine from "../Base/Combine"
|
||||||
import { SubtleButton } from "../Base/SubtleButton"
|
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
import BaseUIElement from "../BaseUIElement"
|
import LayoutConfig, {LayoutInformation} from "../../Models/ThemeConfig/LayoutConfig"
|
||||||
import LayoutConfig, { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
import {ImmutableStore, Store, UIEventSource} from "../../Logic/UIEventSource"
|
||||||
import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
|
|
||||||
import Loc from "../../Models/Loc"
|
import Loc from "../../Models/Loc"
|
||||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
||||||
import { Utils } from "../../Utils"
|
import {Utils} from "../../Utils"
|
||||||
import Title from "../Base/Title"
|
|
||||||
import themeOverview from "../../assets/generated/theme_overview.json"
|
import themeOverview from "../../assets/generated/theme_overview.json"
|
||||||
import { Translation } from "../i18n/Translation"
|
import {TextField} from "../Input/TextField"
|
||||||
import { TextField } from "../Input/TextField"
|
|
||||||
import Locale from "../i18n/Locale"
|
import Locale from "../i18n/Locale"
|
||||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||||
import ThemesList from "./ThemesList.svelte"
|
import ThemesList from "./ThemesList.svelte"
|
||||||
|
|
|
@ -1,64 +1,36 @@
|
||||||
<script lang="ts" context="module">
|
<script context="module" lang="ts">
|
||||||
export interface Theme {
|
export interface Theme {
|
||||||
id: string
|
id: string
|
||||||
icon: string
|
icon: string
|
||||||
title: any
|
title: any
|
||||||
shortDescription: any
|
shortDescription: any
|
||||||
definition?: any
|
definition?: any
|
||||||
mustHaveLanguage?: boolean
|
mustHaveLanguage?: boolean
|
||||||
hideFromOverview: boolean
|
hideFromOverview: boolean
|
||||||
keywords?: any[]
|
keywords?: any[]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
import {UIEventSource} from "../../Logic/UIEventSource"
|
||||||
import Svg from "../../Svg"
|
import Svg from "../../Svg"
|
||||||
import SubtleButton from "../Base/SubtleButton.svelte"
|
import SubtleButton from "../Base/SubtleButton.svelte"
|
||||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
import Tr from "../Base/Tr.svelte";
|
import Tr from "../Base/Tr.svelte";
|
||||||
|
|
||||||
export let search: UIEventSource<string>
|
export let search: UIEventSource<string>
|
||||||
|
|
||||||
const t = Translations.t.general.morescreen
|
const t = Translations.t.general.morescreen
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<span>
|
<div class="w-full">
|
||||||
<h5>{t.noMatchingThemes.toString()}</h5>
|
<h5>{t.noMatchingThemes.toString()}</h5>
|
||||||
<button
|
<div class="flex justify-center">
|
||||||
on:click={() => {
|
|
||||||
search.setData("")
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SubtleButton>
|
|
||||||
<span slot="image">
|
|
||||||
<ToSvelte construct={Svg.search_disable_svg().SetClass("w-6 mr-2")} />
|
|
||||||
</span>
|
|
||||||
<Tr t={t.noSearch} slot="message"/>
|
|
||||||
</SubtleButton>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<style lang="scss">
|
<button on:click={() => search.setData("")}>
|
||||||
span {
|
<ToSvelte construct={Svg.search_disable_svg().SetClass("w-6 mr-2")}/>
|
||||||
@apply flex flex-col items-center w-full;
|
<Tr slot="message" t={t.noSearch}/>
|
||||||
|
</button>
|
||||||
h5 {
|
</div>
|
||||||
@apply w-max font-bold;
|
</div>
|
||||||
}
|
|
||||||
|
|
||||||
// SubtleButton
|
|
||||||
button {
|
|
||||||
@apply h-12;
|
|
||||||
|
|
||||||
span {
|
|
||||||
@apply w-max;
|
|
||||||
|
|
||||||
:global(img) {
|
|
||||||
@apply h-6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
<span>
|
<span>
|
||||||
{t.hookMore.toString()}
|
{t.hookMore.toString()}
|
||||||
</span>
|
</span>
|
||||||
|
<div class="w-full">
|
||||||
|
|
||||||
<SubtleLink href="./professional.html">
|
<SubtleLink href="./professional.html">
|
||||||
<Tr slot="message" t={t.button} />
|
<div class="w-full">
|
||||||
|
<Tr slot="message" t={t.button} />
|
||||||
|
</div>
|
||||||
</SubtleLink>
|
</SubtleLink>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
div {
|
|
||||||
@apply flex flex-col border border-gray-300 p-2 rounded-lg;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
<img slot="image" src={theme.icon} class="block h-11 w-11 bg-red mx-4" alt=""/>
|
<img slot="image" src={theme.icon} class="block h-11 w-11 bg-red mx-4" alt=""/>
|
||||||
<span class="flex flex-col text-ellipsis overflow-hidden">
|
<span class="flex flex-col text-ellipsis overflow-hidden">
|
||||||
<Tr t={title}/>
|
<Tr t={title}/>
|
||||||
<span class="subtle max-h-12">
|
<span class="subtle max-h-12 truncate text-ellipsis">
|
||||||
<Tr t={description}/>
|
<Tr t={description}/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
$: filteredThemes = themes.filter((theme) => MoreScreen.MatchesLayout(theme, $search))
|
$: filteredThemes = themes.filter((theme) => MoreScreen.MatchesLayout(theme, $search))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section class="w-full">
|
||||||
<slot name="title" />
|
<slot name="title" />
|
||||||
{#if onMainScreen}
|
{#if onMainScreen}
|
||||||
<div class="md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div class="md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
@ -51,13 +51,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if filteredThemes.length == 0}
|
{#if filteredThemes.length === 0}
|
||||||
<NoThemeResultButton {search} />
|
<NoThemeResultButton {search} />
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
section {
|
|
||||||
@apply flex flex-col;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,37 +1,39 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
import {OsmConnection} from "../../Logic/Osm/OsmConnection"
|
||||||
import { Store, Stores, UIEventSource } from "../../Logic/UIEventSource"
|
import {Store, Stores, UIEventSource} from "../../Logic/UIEventSource"
|
||||||
import type Loc from "../../Models/Loc"
|
import type Loc from "../../Models/Loc"
|
||||||
import { Utils } from "../../Utils"
|
import {Utils} from "../../Utils"
|
||||||
import ThemesList from "./ThemesList.svelte"
|
import ThemesList from "./ThemesList.svelte"
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
||||||
|
|
||||||
export let search: UIEventSource<string>
|
export let search: UIEventSource<string>
|
||||||
export let state: UserRelatedState & {
|
export let state: UserRelatedState & {
|
||||||
osmConnection: OsmConnection
|
osmConnection: OsmConnection
|
||||||
locationControl?: UIEventSource<Loc>
|
locationControl?: UIEventSource<Loc>
|
||||||
}
|
}
|
||||||
export let onMainScreen: boolean = true
|
export let onMainScreen: boolean = true
|
||||||
|
|
||||||
const t = Translations.t.general
|
const t = Translations.t.general
|
||||||
const currentIds: Store<string[]> = state.installedUserThemes
|
const currentIds: Store<string[]> = state.installedUserThemes
|
||||||
const stableIds = Stores.ListStabilized<string>(currentIds)
|
const stableIds = Stores.ListStabilized<string>(currentIds)
|
||||||
let customThemes
|
let customThemes
|
||||||
$: customThemes = Utils.NoNull($stableIds.map((id) => state.GetUnofficialTheme(id)))
|
$: customThemes = Utils.NoNull($stableIds.map((id) => state.GetUnofficialTheme(id)))
|
||||||
$: console.log("Custom themes are", customThemes)
|
$: console.log("Custom themes are", customThemes)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ThemesList
|
{#if customThemes.length > 0}
|
||||||
{search}
|
<ThemesList
|
||||||
{state}
|
{search}
|
||||||
{onMainScreen}
|
{state}
|
||||||
themes={customThemes}
|
{onMainScreen}
|
||||||
isCustom={true}
|
themes={customThemes}
|
||||||
hideThemes={false}
|
isCustom={true}
|
||||||
>
|
hideThemes={false}
|
||||||
<svelte:fragment slot="title">
|
>
|
||||||
<!-- TODO: Change string to exclude html -->
|
<svelte:fragment slot="title">
|
||||||
{@html t.customThemeIntro.toString()}
|
<!-- TODO: Change string to exclude html -->
|
||||||
</svelte:fragment>
|
{@html t.customThemeIntro.toString()}
|
||||||
</ThemesList>
|
</svelte:fragment>
|
||||||
|
</ThemesList>
|
||||||
|
{/if}
|
||||||
|
|
54
Utils.ts
54
Utils.ts
|
@ -704,10 +704,10 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
if (Array.isArray(leaf)) {
|
if (Array.isArray(leaf)) {
|
||||||
for (let i = 0; i < (<any[]>leaf).length; i++) {
|
for (let i = 0; i < (<any[]>leaf).length; i++) {
|
||||||
const l = (<any[]>leaf)[i]
|
const l = (<any[]>leaf)[i]
|
||||||
collectedList.push({ leaf: l, path: [...travelledPath, "" + i] })
|
collectedList.push({leaf: l, path: [...travelledPath, "" + i]})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
collectedList.push({ leaf, path: travelledPath })
|
collectedList.push({leaf, path: travelledPath})
|
||||||
}
|
}
|
||||||
return collectedList
|
return collectedList
|
||||||
}
|
}
|
||||||
|
@ -785,7 +785,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const cp = { ...json }
|
const cp = {...json}
|
||||||
for (const key in json) {
|
for (const key in json) {
|
||||||
cp[key] = Utils.WalkJson(json[key], f, isLeaf, [...path, key])
|
cp[key] = Utils.WalkJson(json[key], f, isLeaf, [...path, key])
|
||||||
}
|
}
|
||||||
|
@ -915,11 +915,11 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
const xhr = new XMLHttpRequest()
|
const xhr = new XMLHttpRequest()
|
||||||
xhr.onload = () => {
|
xhr.onload = () => {
|
||||||
if (xhr.status == 200) {
|
if (xhr.status == 200) {
|
||||||
resolve({ content: xhr.response })
|
resolve({content: xhr.response})
|
||||||
} else if (xhr.status === 302) {
|
} else if (xhr.status === 302) {
|
||||||
resolve({ redirect: xhr.getResponseHeader("location") })
|
resolve({redirect: xhr.getResponseHeader("location")})
|
||||||
} else if (xhr.status === 509 || xhr.status === 429) {
|
} else if (xhr.status === 509 || xhr.status === 429) {
|
||||||
resolve({ error: "rate limited", url, statuscode: xhr.status })
|
resolve({error: "rate limited", url, statuscode: xhr.status})
|
||||||
} else {
|
} else {
|
||||||
resolve({
|
resolve({
|
||||||
error: "other error: " + xhr.statusText,
|
error: "other error: " + xhr.statusText,
|
||||||
|
@ -989,10 +989,10 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
}
|
}
|
||||||
const promise =
|
const promise =
|
||||||
/*NO AWAIT as we work with the promise directly */ Utils.downloadJsonAdvanced(
|
/*NO AWAIT as we work with the promise directly */ Utils.downloadJsonAdvanced(
|
||||||
url,
|
url,
|
||||||
headers
|
headers
|
||||||
)
|
)
|
||||||
Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() })
|
Utils._download_cache.set(url, {promise, timestamp: new Date().getTime()})
|
||||||
return await promise
|
return await promise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,11 +1011,11 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
const injected = Utils.injectedDownloads[url]
|
const injected = Utils.injectedDownloads[url]
|
||||||
if (injected !== undefined) {
|
if (injected !== undefined) {
|
||||||
console.log("Using injected resource for test for URL", url)
|
console.log("Using injected resource for test for URL", url)
|
||||||
return new Promise((resolve, _) => resolve({ content: injected }))
|
return new Promise((resolve, _) => resolve({content: injected}))
|
||||||
}
|
}
|
||||||
const result = await Utils.downloadAdvanced(
|
const result = await Utils.downloadAdvanced(
|
||||||
url,
|
url,
|
||||||
Utils.Merge({ accept: "application/json" }, headers ?? {})
|
Utils.Merge({accept: "application/json"}, headers ?? {})
|
||||||
)
|
)
|
||||||
if (result["error"] !== undefined) {
|
if (result["error"] !== undefined) {
|
||||||
return <{ error: string; url: string; statuscode?: number }>result
|
return <{ error: string; url: string; statuscode?: number }>result
|
||||||
|
@ -1023,12 +1023,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
const data = result["content"]
|
const data = result["content"]
|
||||||
try {
|
try {
|
||||||
if (typeof data === "string") {
|
if (typeof data === "string") {
|
||||||
return { content: JSON.parse(data) }
|
return {content: JSON.parse(data)}
|
||||||
}
|
}
|
||||||
return { content: data }
|
return {content: data}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Could not parse ", data, "due to", e, "\n", e.stack)
|
console.error("Could not parse ", data, "due to", e, "\n", e.stack)
|
||||||
return { error: "malformed", url }
|
return {error: "malformed", url}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1052,7 +1052,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
const element = document.createElement("a")
|
const element = document.createElement("a")
|
||||||
let file
|
let file
|
||||||
if (typeof contents === "string") {
|
if (typeof contents === "string") {
|
||||||
file = new Blob([contents], { type: options?.mimetype ?? "text/plain" })
|
file = new Blob([contents], {type: options?.mimetype ?? "text/plain"})
|
||||||
} else {
|
} else {
|
||||||
file = contents
|
file = contents
|
||||||
}
|
}
|
||||||
|
@ -1169,7 +1169,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return "https://mapcomplete.osm.be"
|
return "https://mapcomplete.osm.be"
|
||||||
}
|
}
|
||||||
const path = (window.location.protocol+ window.location.host + window.location.pathname) .split("/")
|
const path = (window.location.protocol + "//" + window.location.host + window.location.pathname).split("/")
|
||||||
path.pop()
|
path.pop()
|
||||||
path.push("index.html")
|
path.push("index.html")
|
||||||
return path.join("/")
|
return path.join("/")
|
||||||
|
@ -1318,7 +1318,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
if (match == undefined) {
|
if (match == undefined) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return { r: Number(match[1]), g: Number(match[2]), b: Number(match[3]) }
|
return {r: Number(match[1]), g: Number(match[2]), b: Number(match[3])}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hex.startsWith("#")) {
|
if (!hex.startsWith("#")) {
|
||||||
|
@ -1366,7 +1366,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
d.setUTCMinutes(0)
|
d.setUTCMinutes(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static scrollIntoView(element: HTMLBaseElement){
|
public static scrollIntoView(element: HTMLBaseElement) {
|
||||||
console.log("Scrolling into view:", element)
|
console.log("Scrolling into view:", element)
|
||||||
// Is the element completely in the view?
|
// Is the element completely in the view?
|
||||||
const parentRect = Utils.findParentWithScrolling(
|
const parentRect = Utils.findParentWithScrolling(
|
||||||
|
@ -1384,6 +1384,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
console.log("Actually scrolling...")
|
console.log("Actually scrolling...")
|
||||||
element.scrollIntoView({behavior: "smooth", block: "nearest"})
|
element.scrollIntoView({behavior: "smooth", block: "nearest"})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static findParentWithScrolling(element: HTMLBaseElement): HTMLBaseElement {
|
public static findParentWithScrolling(element: HTMLBaseElement): HTMLBaseElement {
|
||||||
// Check if the element itself has scrolling
|
// Check if the element itself has scrolling
|
||||||
if (element.scrollHeight > element.clientHeight) {
|
if (element.scrollHeight > element.clientHeight) {
|
||||||
|
@ -1396,7 +1397,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the element has a parent, repeat the process for the parent element
|
// If the element has a parent, repeat the process for the parent element
|
||||||
return Utils.findParentWithScrolling(<HTMLBaseElement> element.parentElement)
|
return Utils.findParentWithScrolling(<HTMLBaseElement>element.parentElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1428,12 +1429,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
private static colorDiff(
|
|
||||||
c0: { r: number; g: number; b: number },
|
|
||||||
c1: { r: number; g: number; b: number }
|
|
||||||
) {
|
|
||||||
return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b)
|
|
||||||
}
|
|
||||||
|
|
||||||
static SameObject(a: any, b: any) {
|
static SameObject(a: any, b: any) {
|
||||||
if (a === b) {
|
if (a === b) {
|
||||||
|
@ -1463,4 +1458,11 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static colorDiff(
|
||||||
|
c0: { r: number; g: number; b: number },
|
||||||
|
c1: { r: number; g: number; b: number }
|
||||||
|
) {
|
||||||
|
return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,6 +397,8 @@ select:hover {
|
||||||
.subtle {
|
.subtle {
|
||||||
/* For all information that is not important for 99% of the users */
|
/* For all information that is not important for 99% of the users */
|
||||||
color: #999;
|
color: #999;
|
||||||
|
font-size: medium;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-underline .subtle a {
|
.link-underline .subtle a {
|
||||||
|
|
|
@ -800,11 +800,6 @@ video {
|
||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-2 {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.my-4 {
|
.my-4 {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -815,6 +810,11 @@ video {
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mx-10 {
|
.mx-10 {
|
||||||
margin-left: 2.5rem;
|
margin-left: 2.5rem;
|
||||||
margin-right: 2.5rem;
|
margin-right: 2.5rem;
|
||||||
|
@ -1137,11 +1137,6 @@ video {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-max {
|
|
||||||
width: -webkit-max-content;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-96 {
|
.w-96 {
|
||||||
width: 24rem;
|
width: 24rem;
|
||||||
}
|
}
|
||||||
|
@ -1150,6 +1145,11 @@ video {
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-max {
|
||||||
|
width: -webkit-max-content;
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
||||||
.w-48 {
|
.w-48 {
|
||||||
width: 12rem;
|
width: 12rem;
|
||||||
}
|
}
|
||||||
|
@ -1493,11 +1493,6 @@ video {
|
||||||
background-color: rgb(248 113 113 / var(--tw-bg-opacity));
|
background-color: rgb(248 113 113 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-subtle {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(219 234 254 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-white {
|
.bg-white {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
|
@ -1553,10 +1548,6 @@ video {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-3 {
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-8 {
|
.p-8 {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
@ -1571,11 +1562,6 @@ video {
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.py-4 {
|
|
||||||
padding-top: 1rem;
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.px-3 {
|
.px-3 {
|
||||||
padding-left: 0.75rem;
|
padding-left: 0.75rem;
|
||||||
padding-right: 0.75rem;
|
padding-right: 0.75rem;
|
||||||
|
@ -1848,18 +1834,6 @@ video {
|
||||||
transition-duration: 150ms;
|
transition-duration: 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transition-shadow {
|
|
||||||
transition-property: box-shadow;
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
transition-duration: 150ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transition-\[color\2c background-color\2c box-shadow\] {
|
|
||||||
transition-property: color,background-color,box-shadow;
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
transition-duration: 150ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transition {
|
.transition {
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter;
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter;
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
||||||
|
@ -2246,6 +2220,8 @@ select:hover {
|
||||||
.subtle {
|
.subtle {
|
||||||
/* For all information that is not important for 99% of the users */
|
/* For all information that is not important for 99% of the users */
|
||||||
color: #999;
|
color: #999;
|
||||||
|
font-size: medium;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-underline .subtle a {
|
.link-underline .subtle a {
|
||||||
|
@ -2432,11 +2408,6 @@ a.link-underline {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:bg-unsubtle:hover {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(191 219 254 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:bg-indigo-200:hover {
|
.hover\:bg-indigo-200:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(199 210 254 / var(--tw-bg-opacity));
|
background-color: rgb(199 210 254 / var(--tw-bg-opacity));
|
||||||
|
@ -2451,12 +2422,6 @@ a.link-underline {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:shadow-xl:hover {
|
|
||||||
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
||||||
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
|
|
||||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.max-\[480px\]\:w-full {
|
.max-\[480px\]\:w-full {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue