web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 22072f825e11cc176bf79a14685e82b54f208e89
parent 9868bde250bc427fb129970e47f9faf1287fa0c3
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Wed, 11 Sep 2024 11:30:46 +0000

apps-lib: add input select and notify glyph components, edit input form, edit trellis, add trade locale, add client stores, edit types, edit utils

Diffstat:
Mapps-lib/src/lib/components/input_form.svelte | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Aapps-lib/src/lib/components/input_select.svelte | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/notify_glyph.svelte | 24++++++++++++++++++++++++
Mapps-lib/src/lib/components/trellis.svelte | 4++--
Mapps-lib/src/lib/components/trellis_touch.svelte | 2+-
Mapps-lib/src/lib/index.ts | 2++
Mapps-lib/src/lib/locales/en/common.json | 3+++
Aapps-lib/src/lib/locales/en/trade.json | 38++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/locales/i18n.ts | 2+-
Mapps-lib/src/lib/stores/client.ts | 7+++++--
Mapps-lib/src/lib/types/client.ts | 10++++++++++
Mapps-lib/src/lib/types/components.ts | 33++++++++++++++++++++++++++++-----
Mapps-lib/src/lib/ui/css_static.svelte | 2+-
Mapps-lib/src/lib/utils/client.ts | 6+++---
14 files changed, 259 insertions(+), 43 deletions(-)

diff --git a/apps-lib/src/lib/components/input_form.svelte b/apps-lib/src/lib/components/input_form.svelte @@ -1,42 +1,77 @@ <script lang="ts"> - import { kv, type IInputFormBasis } from "$lib"; - import type { ThemeLayer } from "@radroots/theme"; + import { fmt_cl, Glyph, kv, parse_layer, type IInputFormBasis } from "$lib"; import { onMount } from "svelte"; + let el: HTMLInputElement | null; + export let basis: IInputFormBasis; $: basis = basis; - let layer: ThemeLayer = 0; - $: layer = basis.layer; - - let el: HTMLInputElement | null; - + $: layer = + typeof basis.layer === `boolean` ? false : parse_layer(basis.layer, 1); + $: classes_layer = + typeof layer === `boolean` + ? `bg-transparent` + : `bg-layer-${layer}-surface`; + $: classes_wrap = `px-4`; onMount(async () => { try { - if (basis.sync) await $kv.set(basis.id, ""); + if (basis.sync) { + const kv_val = await kv.get(basis.id); + if (kv_val) el.value = kv_val; + await kv.set(basis.id, kv_val || ""); + } } catch (e) { console.log(`e `, e); } }); </script> -<input - bind:this={el} - type="text" - class={`form-input text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl placeholder:font-[300] caret-layer-${layer}-glyph`} - id={basis.id} - placeholder={basis.placeholder || ""} - on:input={async ({ currentTarget: el }) => { - const val = el.value - .split("") - .filter((char) => basis.field.charset.test(char)) - .join(""); - if (!basis.field.validate.test(val) && basis.field.validateKeypress) - el.classList.add(`form-input-invalid`); - else el.classList.remove("form-entry-invalid"); - el.value = val; - if (basis.sync) { - await $kv.set(basis.id, val); - } - }} -/> +<div + class={`${fmt_cl(basis.classes_wrap)} relative form-line-wrap ${classes_wrap} ${classes_layer} transition-all`} +> + <input + bind:this={el} + type="text" + id={basis.id} + class={`${fmt_cl(basis.classes)} form-input h-full text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} + placeholder={basis.placeholder || ""} + on:input={async ({ currentTarget: el }) => { + let pass = true; + const val = el.value + .split("") + .filter((char) => basis.field.charset.test(char)) + .join(""); + if ( + !basis.field.validate.test(val) && + basis.field.validate_keypress + ) { + //el.classList.add(`form-invalid-layer-${layer}`); + pass = false; + } else { + //el.classList.remove(`form-invalid-layer-${layer}`); + } + el.value = val; + if (basis.sync) await kv.set(basis.id, val); + if (basis.callback) await basis.callback({ val, pass }); + }} + /> + {#if basis.notify_inline} + {#if `glyph` in basis.notify_inline} + <div + class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-3 justify-end items-center translate-x-[34px] fade-in transition-all`} + > + <Glyph + basis={typeof basis.notify_inline.glyph === `string` + ? { + key: basis.notify_inline.glyph, + dim: `xs+`, + weight: `bold`, + classes: `text-layer-${layer}-glyph`, + } + : basis.notify_inline.glyph} + /> + </div> + {/if} + {/if} +</div> diff --git a/apps-lib/src/lib/components/input_select.svelte b/apps-lib/src/lib/components/input_select.svelte @@ -0,0 +1,78 @@ +<script lang="ts"> + import { + fmt_cl, + type IInputSelectBasis, + kv, + Loading, + parse_layer, + } from "$lib"; + import Glyph from "$lib/ui/glyph.svelte"; + import { onMount } from "svelte"; + + let el: HTMLSelectElement | null; + + export let value: string; + export let basis: IInputSelectBasis; + $: basis = basis; + + $: layer = + typeof basis.layer === `boolean` ? false : parse_layer(basis.layer, 1); + $: classes_layer = + typeof layer === `boolean` + ? `bg-transparent` + : `bg-layer-${layer}-surface`; + $: classes_wrap = typeof layer === `boolean` ? `` : `px-4`; + + onMount(async () => { + try { + if (basis.sync) await kv.set(basis.id, basis.options[0].value); + } catch (e) { + console.log(`e `, e); + } + }); +</script> + +<div + class={`${fmt_cl(basis.classes_wrap)} relative form-line-wrap ${classes_wrap} ${classes_layer} transition-all`} +> + {#if basis.loading} + <div class={`flex flex-row w-full justify-center items-center`}> + <Loading basis={{ dim: `xs-` }} /> + </div> + {:else} + <select + bind:this={el} + bind:value + class={`${fmt_cl(basis.classes)} z-10 form-select form-line-select text-layer-${layer}-glyph`} + on:change={async ({ currentTarget: el }) => { + const val = el.value; + if (basis.sync) await kv.set(basis.id, val); + if (basis.callback) await basis.callback(val); + }} + > + {#each basis.options as opt} + <option + value={opt.value} + disabled={!!opt.disabled} + selected={!!opt.selected} + > + {opt.label || opt.value} + </option> + {/each} + </select> + {/if} + {#if !basis.hide_arrows} + <div + class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-3 justify-end items-center`} + > + <Glyph + basis={{ + key: `caret-up-down`, + dim: `xs`, + weight: `bold`, + classes: `text-layer-${layer}-glyph`, + }} + /> + </div> + {/if} +</div> diff --git a/apps-lib/src/lib/components/notify_glyph.svelte b/apps-lib/src/lib/components/notify_glyph.svelte @@ -0,0 +1,24 @@ +<script lang="ts"> + import { Glyph, type GlyphKey, type IGlyph } from "$lib"; + import type { ThemeLayer } from "@radroots/theme"; + + export let basis: { + glyph: GlyphKey | IGlyph; + layer: ThemeLayer; + }; +</script> + +<div + class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-3 justify-end items-center translate-x-[34px] fade-in transition-all`} +> + <Glyph + basis={typeof basis.glyph === `string` + ? { + key: basis.glyph, + dim: `xs+`, + weight: `bold`, + classes: `text-layer-${basis.layer}-glyph`, + } + : basis.glyph} + /> +</div> diff --git a/apps-lib/src/lib/components/trellis.svelte b/apps-lib/src/lib/components/trellis.svelte @@ -5,7 +5,7 @@ import TrellisTitle from "./trellis_title.svelte"; import TrellisTouch from "./trellis_touch.svelte"; - const class_rounded = `xl`; + const class_rounded = `2xl`; export let basis: { args: ITrellis }; $: ({ args } = basis); @@ -96,4 +96,4 @@ </div> {/if} </div> -<div class={`hidden rounded-xl first:rounded-t-xl last:rounded-b-xl`}></div> +<div class={`hidden rounded-2xl first:rounded-t-2xl last:rounded-b-2xl`}></div> diff --git a/apps-lib/src/lib/components/trellis_touch.svelte b/apps-lib/src/lib/components/trellis_touch.svelte @@ -14,7 +14,7 @@ <div class={`flex flex-row flex-grow overflow-x-hidden`}> <div - class={`${fmt_trellis(hide_border_b, hide_border_t)} flex flex-row h-full w-full justify-center items-center border-t-line border-layer-${layer}-surface-edge transition-all`} + class={`${fmt_trellis(hide_border_b, hide_border_t)} flex flex-row h-full w-full justify-center items-center border-t-line border-layer-${layer}-surface-edge/40 transition-all`} > <button class={`relative group flex flex-row h-line w-full pr-[2px] justify-between items-center transition-all`} diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -2,8 +2,10 @@ export * from "./locales/i18n" export { default as Envelope } from "./components/envelope.svelte" export { default as EnvelopeTitled } from "./components/envelope_titled.svelte" export { default as InputForm } from "./components/input_form.svelte" +export { default as InputSelect } from "./components/input_select.svelte" export { default as LoadingView } from "./components/loading_view.svelte" export { default as Nav } from "./components/nav.svelte" +export { default as NotifyGlyph } from "./components/notify_glyph.svelte" export { default as Tabs } from "./components/tabs.svelte" export { default as Trellis } from "./components/trellis.svelte" export { default as TrellisDefaultLabel } from "./components/trellis_default_label.svelte" diff --git a/apps-lib/src/lib/locales/en/common.json b/apps-lib/src/lib/locales/en/common.json @@ -1,4 +1,7 @@ { + "other": "Other", + "add_new_location": "Add new location", + "no_locations_saved": "No locations saved", "no_items_to_display": "No items to display", "cancel": "Cancel", "add": "Add" diff --git a/apps-lib/src/lib/locales/en/trade.json b/apps-lib/src/lib/locales/en/trade.json @@ -0,0 +1,37 @@ +{ + "quantity": { + "mass_unit": { + "g": "Gram", + "g_pl": "Grams", + "g_ab": "g.", + "hg": "100 Gram", + "hg_pl": "100 Grams", + "hg_ab": "100g.", + "kg": "Kilogram", + "kg_pl": "Kilograms", + "kg_ab": "kg.", + "lb": "Pound", + "lb_pl": "Pounds", + "lb_ab": "lb." + } + }, + "currency": { + "usd": { + "symbol": "$", + "name": "United States Dollar", + "name_short": "U.S. Dollar" + }, + "eur": { + "symbol": "€", + "name": "Euro", + "name_short": "Euro" + } + }, + "product": { + "key": { + "coffee": "Coffee", + "cacao": "Cacao", + "maca": "Maca" + } + } +} +\ No newline at end of file diff --git a/apps-lib/src/lib/locales/i18n.ts b/apps-lib/src/lib/locales/i18n.ts @@ -7,7 +7,7 @@ type LanguageConfig = { default?: string; }; -const locales_files = [`app`, `common`] as const; +const locales_files = [`app`, `common`, `trade`] as const; const translations_keys: Record<Locale, any> = { en: { locales_keys }, }; diff --git a/apps-lib/src/lib/stores/client.ts b/apps-lib/src/lib/stores/client.ts @@ -4,8 +4,11 @@ import { writable } from "svelte/store"; export const app_qp = queryParameters(); -export const kv = writable<Keyva>(); -if (typeof window !== 'undefined') kv.set(new Keyva({ name: 'app-kv' })); +//export const kv = writable<Keyva>(); +//if (typeof window !== 'undefined') kv.set(new Keyva({ name: 'app-kv' })); + +export let kv: Keyva; +if (typeof window !== 'undefined') kv = new Keyva({ name: 'app-kv' }); export const app_layout = writable<AppLayoutKey>(`base`); diff --git a/apps-lib/src/lib/types/client.ts b/apps-lib/src/lib/types/client.ts @@ -27,7 +27,9 @@ export type GeometryGlyphDimension = | `${GeometryDimension}+`; +//export type CallbackPromiseGenericReturn<T1, T2> = (value: T1) => Promise<T2>; export type CallbackPromiseGeneric<T> = (value: T) => Promise<void>; +//export type CallbackPromiseReturn<T> = () => Promise<T>; export type CallbackPromise = () => Promise<void>; export type NavigationRoute = string; //@todo @@ -72,6 +74,14 @@ export type ILyOpt = { layer?: ThemeLayer; }; +export type ILyTs = { + layer: ThemeLayer | false; +}; + +export type ILyOptTs = { + layer?: ThemeLayer | false; +}; + export type IGl = { glyph: IGlyph; } diff --git a/apps-lib/src/lib/types/components.ts b/apps-lib/src/lib/types/components.ts @@ -1,5 +1,5 @@ -import type { CallbackPromise, CallbackPromiseGeneric, ICb, IClOpt, IGl, IGlOpt, ILabelFieldsOpt, ILabelOpt, ILabelOptFieldsOpt, ILy, ILyOpt } from "./client"; -import type { GlyphKey, GlyphWeight } from "./ui"; +import type { CallbackPromise, CallbackPromiseGeneric, ICb, ICbGOpt, IClOpt, IGl, IGlOpt, ILabelFieldsOpt, ILabelOpt, ILabelOptFieldsOpt, ILyOpt, ILyOptTs } from "./client"; +import type { GlyphKey, GlyphWeight, IGlyph } from "./ui"; export type ITabsBasisList = { icon: GlyphKey; @@ -19,19 +19,42 @@ export type ITabsBasis = { export type IFormField = { validate: RegExp; charset: RegExp; - validateKeypress?: boolean; + validate_keypress?: boolean; }; -export type IInputFormBasis = IClOpt & ILy & { +export type IInputFormBasis = IClOpt & ILyOptTs & ICbGOpt<{ val: string; pass: boolean; }> & { + classes_wrap?: string; id: string; placeholder?: string; label?: string; hidden?: boolean; validate?: RegExp; sync?: boolean; - field: IFormField + field: IFormField; + notify_inline?: { + glyph: GlyphKey | IGlyph; + }; +}; + +export type IInputSelectBasisOption = { + value: string; + label?: string; + disabled?: boolean; + selected?: boolean; }; +export type IInputSelectBasis = IClOpt & ILyOptTs & ICbGOpt<string> & { + classes_wrap?: string; + id: string; + label?: string; + hidden?: boolean; + hide_arrows?: boolean; + sync?: boolean; + loading?: boolean; + options: IInputSelectBasisOption[]; +}; + + export type IEnvelopeBasis = ILyOpt & IClOpt & IEnvelopeKind & { visible: boolean; diff --git a/apps-lib/src/lib/ui/css_static.svelte b/apps-lib/src/lib/ui/css_static.svelte @@ -1 +1 @@ -<div class="hidden bg-layer-0-surface active:bg-layer-0-surface group-active:bg-layer-0-surface focus:bg-layer-0-surface group-focus:bg-layer-0-surface border-layer-0-surface active:border-layer-0-surface group-active:border-layer-0-surface focus:border-layer-0-surface group-focus:border-layer-0-surface bg-layer-0-surface_a active:bg-layer-0-surface_a group-active:bg-layer-0-surface_a focus:bg-layer-0-surface_a group-focus:bg-layer-0-surface_a border-layer-0-surface_a active:border-layer-0-surface_a group-active:border-layer-0-surface_a focus:border-layer-0-surface_a group-focus:border-layer-0-surface_a bg-layer-0-surface-edge active:bg-layer-0-surface-edge group-active:bg-layer-0-surface-edge focus:bg-layer-0-surface-edge group-focus:bg-layer-0-surface-edge border-layer-0-surface-edge active:border-layer-0-surface-edge group-active:border-layer-0-surface-edge focus:border-layer-0-surface-edge group-focus:border-layer-0-surface-edge bg-layer-0-surface-blur active:bg-layer-0-surface-blur group-active:bg-layer-0-surface-blur focus:bg-layer-0-surface-blur group-focus:bg-layer-0-surface-blur border-layer-0-surface-blur active:border-layer-0-surface-blur group-active:border-layer-0-surface-blur focus:border-layer-0-surface-blur group-focus:border-layer-0-surface-blur bg-layer-1-surface active:bg-layer-1-surface group-active:bg-layer-1-surface focus:bg-layer-1-surface group-focus:bg-layer-1-surface border-layer-1-surface active:border-layer-1-surface group-active:border-layer-1-surface focus:border-layer-1-surface group-focus:border-layer-1-surface bg-layer-1-surface_a active:bg-layer-1-surface_a group-active:bg-layer-1-surface_a focus:bg-layer-1-surface_a group-focus:bg-layer-1-surface_a border-layer-1-surface_a active:border-layer-1-surface_a group-active:border-layer-1-surface_a focus:border-layer-1-surface_a group-focus:border-layer-1-surface_a bg-layer-1-surface-edge active:bg-layer-1-surface-edge group-active:bg-layer-1-surface-edge focus:bg-layer-1-surface-edge group-focus:bg-layer-1-surface-edge border-layer-1-surface-edge active:border-layer-1-surface-edge group-active:border-layer-1-surface-edge focus:border-layer-1-surface-edge group-focus:border-layer-1-surface-edge bg-layer-2-surface active:bg-layer-2-surface group-active:bg-layer-2-surface focus:bg-layer-2-surface group-focus:bg-layer-2-surface border-layer-2-surface active:border-layer-2-surface group-active:border-layer-2-surface focus:border-layer-2-surface group-focus:border-layer-2-surface bg-layer-2-surface_a active:bg-layer-2-surface_a group-active:bg-layer-2-surface_a focus:bg-layer-2-surface_a group-focus:bg-layer-2-surface_a border-layer-2-surface_a active:border-layer-2-surface_a group-active:border-layer-2-surface_a focus:border-layer-2-surface_a group-focus:border-layer-2-surface_a bg-layer-2-surface-edge active:bg-layer-2-surface-edge group-active:bg-layer-2-surface-edge focus:bg-layer-2-surface-edge group-focus:bg-layer-2-surface-edge border-layer-2-surface-edge active:border-layer-2-surface-edge group-active:border-layer-2-surface-edge focus:border-layer-2-surface-edge group-focus:border-layer-2-surface-edge text-layer-0-glyph active:text-layer-0-glyph group-active:text-layer-0-glyph focus:text-layer-0-glyph group-focus:text-layer-0-glyph text-layer-0-glyph_a active:text-layer-0-glyph_a group-active:text-layer-0-glyph_a focus:text-layer-0-glyph_a group-focus:text-layer-0-glyph_a text-layer-0-glyph-hl active:text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl focus:text-layer-0-glyph-hl group-focus:text-layer-0-glyph-hl text-layer-0-glyph-hl_a active:text-layer-0-glyph-hl_a group-active:text-layer-0-glyph-hl_a focus:text-layer-0-glyph-hl_a group-focus:text-layer-0-glyph-hl_a text-layer-0-glyph-shade active:text-layer-0-glyph-shade group-active:text-layer-0-glyph-shade focus:text-layer-0-glyph-shade group-focus:text-layer-0-glyph-shade text-layer-0-glyph-label active:text-layer-0-glyph-label group-active:text-layer-0-glyph-label focus:text-layer-0-glyph-label group-focus:text-layer-0-glyph-label text-layer-1-glyph active:text-layer-1-glyph group-active:text-layer-1-glyph focus:text-layer-1-glyph group-focus:text-layer-1-glyph text-layer-1-glyph_a active:text-layer-1-glyph_a group-active:text-layer-1-glyph_a focus:text-layer-1-glyph_a group-focus:text-layer-1-glyph_a text-layer-1-glyph_pl active:text-layer-1-glyph_pl group-active:text-layer-1-glyph_pl focus:text-layer-1-glyph_pl group-focus:text-layer-1-glyph_pl text-layer-1-glyph-hl active:text-layer-1-glyph-hl group-active:text-layer-1-glyph-hl focus:text-layer-1-glyph-hl group-focus:text-layer-1-glyph-hl text-layer-1-glyph-hl_a active:text-layer-1-glyph-hl_a group-active:text-layer-1-glyph-hl_a focus:text-layer-1-glyph-hl_a group-focus:text-layer-1-glyph-hl_a text-layer-1-glyph-shade active:text-layer-1-glyph-shade group-active:text-layer-1-glyph-shade focus:text-layer-1-glyph-shade group-focus:text-layer-1-glyph-shade text-layer-1-glyph-label active:text-layer-1-glyph-label group-active:text-layer-1-glyph-label focus:text-layer-1-glyph-label group-focus:text-layer-1-glyph-label text-layer-2-glyph active:text-layer-2-glyph group-active:text-layer-2-glyph focus:text-layer-2-glyph group-focus:text-layer-2-glyph text-layer-2-glyph_a active:text-layer-2-glyph_a group-active:text-layer-2-glyph_a focus:text-layer-2-glyph_a group-focus:text-layer-2-glyph_a text-layer-2-glyph_pl active:text-layer-2-glyph_pl group-active:text-layer-2-glyph_pl focus:text-layer-2-glyph_pl group-focus:text-layer-2-glyph_pl text-layer-2-glyph-hl active:text-layer-2-glyph-hl group-active:text-layer-2-glyph-hl focus:text-layer-2-glyph-hl group-focus:text-layer-2-glyph-hl text-layer-2-glyph-hl_a active:text-layer-2-glyph-hl_a group-active:text-layer-2-glyph-hl_a focus:text-layer-2-glyph-hl_a group-focus:text-layer-2-glyph-hl_a text-layer-2-glyph-shade active:text-layer-2-glyph-shade group-active:text-layer-2-glyph-shade focus:text-layer-2-glyph-shade group-focus:text-layer-2-glyph-shade"></div> +<div class="hidden bg-layer-0-surface active:bg-layer-0-surface group-active:bg-layer-0-surface focus:bg-layer-0-surface group-focus:bg-layer-0-surface border-layer-0-surface active:border-layer-0-surface group-active:border-layer-0-surface focus:border-layer-0-surface group-focus:border-layer-0-surface bg-layer-0-surface_a active:bg-layer-0-surface_a group-active:bg-layer-0-surface_a focus:bg-layer-0-surface_a group-focus:bg-layer-0-surface_a border-layer-0-surface_a active:border-layer-0-surface_a group-active:border-layer-0-surface_a focus:border-layer-0-surface_a group-focus:border-layer-0-surface_a bg-layer-0-surface-edge active:bg-layer-0-surface-edge group-active:bg-layer-0-surface-edge focus:bg-layer-0-surface-edge group-focus:bg-layer-0-surface-edge border-layer-0-surface-edge active:border-layer-0-surface-edge group-active:border-layer-0-surface-edge focus:border-layer-0-surface-edge group-focus:border-layer-0-surface-edge bg-layer-0-surface-blur active:bg-layer-0-surface-blur group-active:bg-layer-0-surface-blur focus:bg-layer-0-surface-blur group-focus:bg-layer-0-surface-blur border-layer-0-surface-blur active:border-layer-0-surface-blur group-active:border-layer-0-surface-blur focus:border-layer-0-surface-blur group-focus:border-layer-0-surface-blur bg-layer-1-surface active:bg-layer-1-surface group-active:bg-layer-1-surface focus:bg-layer-1-surface group-focus:bg-layer-1-surface border-layer-1-surface active:border-layer-1-surface group-active:border-layer-1-surface focus:border-layer-1-surface group-focus:border-layer-1-surface bg-layer-1-surface_a active:bg-layer-1-surface_a group-active:bg-layer-1-surface_a focus:bg-layer-1-surface_a group-focus:bg-layer-1-surface_a border-layer-1-surface_a active:border-layer-1-surface_a group-active:border-layer-1-surface_a focus:border-layer-1-surface_a group-focus:border-layer-1-surface_a bg-layer-1-surface-edge active:bg-layer-1-surface-edge group-active:bg-layer-1-surface-edge focus:bg-layer-1-surface-edge group-focus:bg-layer-1-surface-edge border-layer-1-surface-edge active:border-layer-1-surface-edge group-active:border-layer-1-surface-edge focus:border-layer-1-surface-edge group-focus:border-layer-1-surface-edge bg-layer-1-surface-err active:bg-layer-1-surface-err group-active:bg-layer-1-surface-err focus:bg-layer-1-surface-err group-focus:bg-layer-1-surface-err border-layer-1-surface-err active:border-layer-1-surface-err group-active:border-layer-1-surface-err focus:border-layer-1-surface-err group-focus:border-layer-1-surface-err bg-layer-2-surface active:bg-layer-2-surface group-active:bg-layer-2-surface focus:bg-layer-2-surface group-focus:bg-layer-2-surface border-layer-2-surface active:border-layer-2-surface group-active:border-layer-2-surface focus:border-layer-2-surface group-focus:border-layer-2-surface bg-layer-2-surface_a active:bg-layer-2-surface_a group-active:bg-layer-2-surface_a focus:bg-layer-2-surface_a group-focus:bg-layer-2-surface_a border-layer-2-surface_a active:border-layer-2-surface_a group-active:border-layer-2-surface_a focus:border-layer-2-surface_a group-focus:border-layer-2-surface_a bg-layer-2-surface-edge active:bg-layer-2-surface-edge group-active:bg-layer-2-surface-edge focus:bg-layer-2-surface-edge group-focus:bg-layer-2-surface-edge border-layer-2-surface-edge active:border-layer-2-surface-edge group-active:border-layer-2-surface-edge focus:border-layer-2-surface-edge group-focus:border-layer-2-surface-edge text-layer-0-glyph active:text-layer-0-glyph group-active:text-layer-0-glyph focus:text-layer-0-glyph group-focus:text-layer-0-glyph text-layer-0-glyph_a active:text-layer-0-glyph_a group-active:text-layer-0-glyph_a focus:text-layer-0-glyph_a group-focus:text-layer-0-glyph_a text-layer-0-glyph-hl active:text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl focus:text-layer-0-glyph-hl group-focus:text-layer-0-glyph-hl text-layer-0-glyph-hl_a active:text-layer-0-glyph-hl_a group-active:text-layer-0-glyph-hl_a focus:text-layer-0-glyph-hl_a group-focus:text-layer-0-glyph-hl_a text-layer-0-glyph-shade active:text-layer-0-glyph-shade group-active:text-layer-0-glyph-shade focus:text-layer-0-glyph-shade group-focus:text-layer-0-glyph-shade text-layer-0-glyph-label active:text-layer-0-glyph-label group-active:text-layer-0-glyph-label focus:text-layer-0-glyph-label group-focus:text-layer-0-glyph-label text-layer-1-glyph active:text-layer-1-glyph group-active:text-layer-1-glyph focus:text-layer-1-glyph group-focus:text-layer-1-glyph text-layer-1-glyph_a active:text-layer-1-glyph_a group-active:text-layer-1-glyph_a focus:text-layer-1-glyph_a group-focus:text-layer-1-glyph_a text-layer-1-glyph_pl active:text-layer-1-glyph_pl group-active:text-layer-1-glyph_pl focus:text-layer-1-glyph_pl group-focus:text-layer-1-glyph_pl text-layer-1-glyph-hl active:text-layer-1-glyph-hl group-active:text-layer-1-glyph-hl focus:text-layer-1-glyph-hl group-focus:text-layer-1-glyph-hl text-layer-1-glyph-hl_a active:text-layer-1-glyph-hl_a group-active:text-layer-1-glyph-hl_a focus:text-layer-1-glyph-hl_a group-focus:text-layer-1-glyph-hl_a text-layer-1-glyph-shade active:text-layer-1-glyph-shade group-active:text-layer-1-glyph-shade focus:text-layer-1-glyph-shade group-focus:text-layer-1-glyph-shade text-layer-1-glyph-label active:text-layer-1-glyph-label group-active:text-layer-1-glyph-label focus:text-layer-1-glyph-label group-focus:text-layer-1-glyph-label text-layer-2-glyph active:text-layer-2-glyph group-active:text-layer-2-glyph focus:text-layer-2-glyph group-focus:text-layer-2-glyph text-layer-2-glyph_a active:text-layer-2-glyph_a group-active:text-layer-2-glyph_a focus:text-layer-2-glyph_a group-focus:text-layer-2-glyph_a text-layer-2-glyph_pl active:text-layer-2-glyph_pl group-active:text-layer-2-glyph_pl focus:text-layer-2-glyph_pl group-focus:text-layer-2-glyph_pl text-layer-2-glyph-hl active:text-layer-2-glyph-hl group-active:text-layer-2-glyph-hl focus:text-layer-2-glyph-hl group-focus:text-layer-2-glyph-hl text-layer-2-glyph-hl_a active:text-layer-2-glyph-hl_a group-active:text-layer-2-glyph-hl_a focus:text-layer-2-glyph-hl_a group-focus:text-layer-2-glyph-hl_a text-layer-2-glyph-shade active:text-layer-2-glyph-shade group-active:text-layer-2-glyph-shade focus:text-layer-2-glyph-shade group-focus:text-layer-2-glyph-shade"></div> diff --git a/apps-lib/src/lib/utils/client.ts b/apps-lib/src/lib/utils/client.ts @@ -65,9 +65,9 @@ export function time_now_ms(): number { return Math.floor(new Date().getTime() / 1000); }; -export const fmt_id = (id: string): string => { - const pref = location.pathname.slice(1, -1).replaceAll(`-`, `_`).replaceAll(`/`, `-`).replaceAll(`--`, `-`) - return `${pref}-${id}` +export const fmt_id = (id?: string): string => { + const pref = location.pathname.slice(1, -1).replaceAll(`-`, `_`).replaceAll(`/`, `-`).replaceAll(`--`, `-`); + return `${pref}${id ? `-${id}` : ``}` }; export const fmt_capitalize = (val: string): string => {