web_lib

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

commit 4a39d47fad5354487ae07ad02e8a3c47ccf5d039
parent a53b78919cb063750e653a1c9e37bf575f19a72c
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Wed, 16 Oct 2024 21:03:48 +0000

apps-lib: edit entry, layout, trellis components. edit app controls module exports. add components, locales, stores, types, utils. edit ui components

Diffstat:
Mapps-lib/src/lib/components/app_controls.svelte | 46++++------------------------------------------
Aapps-lib/src/lib/components/entry_line.svelte | 41+++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/entry_multiline.svelte | 41+++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/entry_option.svelte | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/components/envelope_lower.svelte | 9+++++++--
Dapps-lib/src/lib/components/input_form.svelte | 85-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/input_select.svelte | 82-------------------------------------------------------------------------------
Aapps-lib/src/lib/components/layout_area.svelte | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/components/layout_trellis_line.svelte | 11+++++++----
Mapps-lib/src/lib/components/layout_window.svelte | 4++--
Mapps-lib/src/lib/components/loading_view.svelte | 2+-
Mapps-lib/src/lib/components/nav_option.svelte | 3---
Mapps-lib/src/lib/components/notify_glyph.svelte | 2+-
Mapps-lib/src/lib/components/trellis_row_display_value.svelte | 2+-
Mapps-lib/src/lib/components/trellis_row_label.svelte | 4++--
Mapps-lib/src/lib/index.ts | 8+++++---
Mapps-lib/src/lib/locales/en/app.json | 23++++++++++++++++++++++-
Mapps-lib/src/lib/locales/en/common.json | 16++++++++++++++++
Aapps-lib/src/lib/locales/en/error.json | 16++++++++++++++++
Aapps-lib/src/lib/locales/en/eula.json | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/locales/en/icu.json | 17+++++++++++++++++
Aapps-lib/src/lib/locales/en/model.json | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dapps-lib/src/lib/locales/en/model_fields.json | 48------------------------------------------------
Mapps-lib/src/lib/locales/i18n.ts | 2+-
Mapps-lib/src/lib/stores/client.ts | 6++++--
Mapps-lib/src/lib/types/client.ts | 16++++++++++++++++
Mapps-lib/src/lib/types/components.ts | 37++++++++++++++++---------------------
Mapps-lib/src/lib/types/ui.ts | 13+++++++------
Mapps-lib/src/lib/ui/css_styles.svelte | 5+++--
Mapps-lib/src/lib/ui/input_element.svelte | 26++++++++++++++++----------
Mapps-lib/src/lib/ui/textarea_element.svelte | 2+-
Mapps-lib/src/lib/utils/carousel.ts | 3+++
Mapps-lib/src/lib/utils/client.ts | 40+++++++++++++++++++++++++++++++++++++++-
Mapps-lib/src/lib/utils/conf.ts | 4+++-
Mapps-lib/src/lib/utils/routes.ts | 22+++++-----------------
35 files changed, 535 insertions(+), 339 deletions(-)

diff --git a/apps-lib/src/lib/components/app_controls.svelte b/apps-lib/src/lib/components/app_controls.svelte @@ -1,49 +1,11 @@ -<script lang="ts" context="module"> - const toast_ms = 1500; - - export const init_toast = (): void => { - app_toast.set(false); - }; - - export const show_toast = async (opts: { - args: IToast | string; - callback?: CallbackPromise; - }): Promise<void> => { - try { - const basis: IToast = - typeof opts.args === `string` - ? { - layer: 1, - label: { - value: opts.args, - }, - } - : opts.args; - app_toast.set(basis); - await sleep(toast_ms); - init_toast(); - if (opts.callback) await opts.callback(); - } catch (e) { - console.log(`(error) show_toast `, e); - } - }; -</script> - <script lang="ts"> - import { - app_layout, - app_toast, - app_win, - sleep, - type CallbackPromise, - type IToast, - } from "$lib"; + import { app_layout, app_toast, app_win, wind } from "$lib"; import Toast from "$lib/ui/toast.svelte"; import { onMount } from "svelte"; onMount(async () => { try { - app_win.set([window.innerHeight, window.innerWidth]); + app_win.set({ h: window.innerHeight, w: window.innerWidth }); app_toast.set(false); } catch (e) { console.log(`(layout mount) `, e); @@ -51,8 +13,8 @@ } }); - app_win.subscribe(([win_h, win_w]) => { - if (win_h > 800) app_layout.set(`mobile_y`); + app_win.subscribe((_app_win) => { + if (_app_win.h > wind.app.layout.mobile_y.h) app_layout.set(`mobile_y`); }); </script> diff --git a/apps-lib/src/lib/components/entry_line.svelte b/apps-lib/src/lib/components/entry_line.svelte @@ -0,0 +1,41 @@ +<script lang="ts"> + import { fmt_cl, Glyph, parse_layer, type IEntryLine } from "$lib"; + import InputElement from "$lib/ui/input_element.svelte"; + + export let basis: IEntryLine; + $: basis = basis; + + $: layer = + typeof basis.el?.layer === `boolean` + ? false + : parse_layer(basis.el?.layer, 1); + $: classes_layer = + typeof layer === `boolean` + ? `bg-transparent` + : `bg-layer-${layer}-surface`; +</script> + +<div + id={basis.id_wrap || null} + class={`${fmt_cl(basis.classes_wrap)} relative el-responsive entry-line-wrap px-2 ${classes_layer}`} +> + <InputElement basis={basis.el} /> + {#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/entry_multiline.svelte b/apps-lib/src/lib/components/entry_multiline.svelte @@ -0,0 +1,41 @@ +<script lang="ts"> + import { fmt_cl, Glyph, parse_layer, type IEntryMultiLine } from "$lib"; + import TextareaElement from "$lib/ui/textarea_element.svelte"; + + export let basis: IEntryMultiLine; + $: basis = basis; + + $: layer = + typeof basis.el?.layer === `boolean` + ? false + : parse_layer(basis.el?.layer, 1); + $: classes_layer = + typeof layer === `boolean` + ? `bg-transparent` + : `bg-layer-${layer}-surface`; +</script> + +<div + id={basis.id_wrap || null} + class={`${fmt_cl(basis.classes_wrap)} relative el-responsive entry-textarea-wrap ${classes_layer}`} +> + <TextareaElement basis={basis.el} /> + {#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/entry_option.svelte b/apps-lib/src/lib/components/entry_option.svelte @@ -0,0 +1,74 @@ +<!-- svelte-ignore a11y-no-noninteractive-tabindex --> +<script lang="ts"> + import { fmt_cl, type IEntryOption, 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: IEntryOption; + $: basis = basis; + + $: layer = + typeof basis.layer === `boolean` ? false : parse_layer(basis.layer, 1); + $: classes_layer = + typeof layer === `boolean` + ? `bg-transparent` + : `bg-layer-${layer}-surface px-4`; + + onMount(async () => { + try { + if (basis.sync && basis.id) + await kv.set(basis.id, basis.options[0].value); + } catch (e) {} + }); +</script> + +<div + id={basis.id_wrap || null} + tabindex={-1} + class={`${fmt_cl(basis.classes_wrap)} relative el-responsive entry-line-wrap ${classes_layer}`} +> + {#if basis.loading} + <div class={`flex flex-row w-full justify-center items-center`}> + <Loading basis={{ dim: `sm`, blades: 6 }} /> + </div> + {:else} + <select + bind:this={el} + bind:value + id={basis.id || null} + class={`${fmt_cl(basis.classes)} z-10 el-select entry-line-fluid text-layer-${layer}-glyph`} + on:change={async ({ currentTarget: el }) => { + const val = el.value; + if (basis.sync && basis.id) 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/envelope_lower.svelte b/apps-lib/src/lib/components/envelope_lower.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { Fill, t, type CallbackPromise } from "$lib"; + import { app_tilt, Fill, t, type CallbackPromise } from "$lib"; import { quintInOut } from "svelte/easing"; import { fly } from "svelte/transition"; @@ -9,13 +9,17 @@ }; $: basis = basis; + + $: if (basis.visible) { + app_tilt.set(true); + } </script> {#if basis.visible} <div in:fly={{ y: `100%`, easing: quintInOut }} out:fly={{ y: `100%`, easing: quintInOut }} - class={`z-20 absolute bottom-0 left-0 flex flex-col h-[calc(100vh-30px)] w-full justify-start items-start bg-layer-1-surface rounded-t-2xl overflow-y-scroll scroll-hide`} + class={`z-20 absolute bottom-0 left-0 flex flex-col h-[calc(100vh-12%)] w-full justify-start items-start bg-layer-1-surface rounded-t-2xl overflow-y-scroll scroll-hide`} > <div class={`sticky top-0 left-0 grid grid-cols-12 flex flex-row h-12 w-full px-4 pb-2 justify-center items-center bg-layer-1-surface/60 backdrop-blur-md`} @@ -26,6 +30,7 @@ <button class={`flex flex-row justify-center items-center`} on:click={async () => { + app_tilt.set(false); await basis.close(); }} > diff --git a/apps-lib/src/lib/components/input_form.svelte b/apps-lib/src/lib/components/input_form.svelte @@ -1,85 +0,0 @@ -<script lang="ts"> - 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; - - $: id = basis.id ? basis.id : 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`; - $: sync_init = - typeof basis.sync_init === `boolean` ? basis.sync_init : true; - - onMount(async () => { - try { - if (basis.id) { - if (sync_init) await kv.set(basis.id, ``); - else 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) {} - }); -</script> - -<div - class={`${fmt_cl(basis.classes_wrap)} relative form-line-wrap ${classes_wrap} ${classes_layer} transition-all`} -> - <input - bind:this={el} - type="text" - {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; - let val = el.value; - if (basis.field) { - 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 @@ -1,82 +0,0 @@ -<!-- svelte-ignore a11y-no-noninteractive-tabindex --> -<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`; - $: classes_focus = basis.id_wrap ? `form-line-active` : ``; - - onMount(async () => { - try { - if (basis.sync && basis.id) - await kv.set(basis.id, basis.options[0].value); - } catch (e) {} - }); -</script> - -<div - id={basis.id_wrap || null} - tabindex={-1} - class={`${fmt_cl(basis.classes_wrap)} relative form-line-wrap ${classes_wrap} ${classes_layer} ${classes_focus} transition-all`} -> - {#if basis.loading} - <div class={`flex flex-row w-full justify-center items-center`}> - <Loading basis={{ dim: `sm`, blades: 6 }} /> - </div> - {:else} - <select - bind:this={el} - bind:value - id={basis.id || null} - 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 && basis.id) 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/layout_area.svelte b/apps-lib/src/lib/components/layout_area.svelte @@ -0,0 +1,59 @@ +<script lang="ts"> + import { + type AppLayoutKey, + type IClOpt, + app_layout, + fmt_cl, + nav_blur, + tabs_blur, + } from "$lib"; + import { onDestroy, onMount } from "svelte"; + + const styles: Record<AppLayoutKey, string> = { + mobile_base: "pt-4", + mobile_y: "pt-16 pb-10", + }; + + export let basis: + | (IClOpt & { fade?: boolean; hide_padding?: boolean }) + | undefined = undefined; + $: basis = basis; + + let el: HTMLElement | null; + + onMount(async () => { + try { + el?.addEventListener("scroll", scrollChange); + } catch (e) { + } finally { + } + }); + + onDestroy(async () => { + try { + el?.removeEventListener("scroll", scrollChange); + } catch (e) { + } finally { + } + }); + + $: classes_fade = basis?.fade ? `fade-in` : ``; + + const scrollChange = (): void => { + if (Math.max(el?.scrollTop || 0, 0) > 10) nav_blur.set(true); + else nav_blur.set(false); + if (Math.max(el?.scrollTop || 0, 0) > 10) tabs_blur.set(true); + else tabs_blur.set(false); + }; +</script> + +<div + bind:this={el} + class={`${fmt_cl(basis?.classes)} absolute top-0 left-0 flex flex-col h-[100vh] w-full justify-center items-center ${classes_fade}`} +> + <div + class={`flex flex-col h-view_${$app_layout} w-full justify-start items-start overflow-y-scroll scroll-hide -translate-y-h_view_offset_${$app_layout}`} + > + <slot /> + </div> +</div> diff --git a/apps-lib/src/lib/components/layout_trellis_line.svelte b/apps-lib/src/lib/components/layout_trellis_line.svelte @@ -1,13 +1,16 @@ <script lang="ts"> import { fmt_cl, type ICb, type IClOpt, type ILabel } from "$lib"; - export let basis: ILabel & { - notify?: IClOpt & ICb & ILabel; - }; + export let basis: ILabel & + IClOpt & { + notify?: IClOpt & ICb & ILabel; + }; $: basis = basis; </script> -<div class={`flex flex-col w-trellis_line gap-1 justify-start items-center`}> +<div + class={`${fmt_cl(basis.classes)} flex flex-col w-trellis_line gap-[0.375rem] justify-start items-center`} +> <div class={`flex flex-row h-5 w-full px-2 gap-2 justify-start items-center`} > diff --git a/apps-lib/src/lib/components/layout_window.svelte b/apps-lib/src/lib/components/layout_window.svelte @@ -1,9 +1,9 @@ <script> - import Blur from "$lib/ui/blur.svelte"; + import { Blur, app_tilt } from "$lib"; </script> <div - class={`relative flex flex-col h-[100vh] w-full overflow-x-hidden overflow-y-hidden bg-layer-0-surface`} + class={`relative flex flex-col h-[100vh] w-full overflow-x-hidden overflow-y-hidden bg-layer-0-surface ${$app_tilt ? `scale-[96%] translate-y-4 rounded-t-[3.5rem]` : ``} delay-75 duration-200 ease-in-out transition-all`} > <div class={`flex flex-col h-full w-full`}> <slot /> diff --git a/apps-lib/src/lib/components/loading_view.svelte b/apps-lib/src/lib/components/loading_view.svelte @@ -5,5 +5,5 @@ <div class={`absolute top-0 left-0 flex flex-row h-[100vh] w-full justify-center items-center`} > - <Loading basis={{ dim: `xl` }} /> + <Loading basis={{ dim: `lg` }} /> </div> diff --git a/apps-lib/src/lib/components/nav_option.svelte b/apps-lib/src/lib/components/nav_option.svelte @@ -14,9 +14,6 @@ $: basis = basis; $: layer = parse_layer(1); - - //$: classes_wrap = - // `label` in basis && ; </script> {#if basis?.loading} diff --git a/apps-lib/src/lib/components/notify_glyph.svelte b/apps-lib/src/lib/components/notify_glyph.svelte @@ -10,7 +10,7 @@ </script> <div - class={`${fmt_cl(basis.classes)} z-5 absolute right-0 top-0 flex flex-row h-full pr-3 justify-end items-center fade-in transition-all`} + class={`${fmt_cl(basis.classes)} z-10 absolute right-0 top-0 flex flex-row h-full pr-3 justify-end items-center fade-in transition-all`} > <Glyph basis={typeof basis.glyph === `string` diff --git a/apps-lib/src/lib/components/trellis_row_display_value.svelte b/apps-lib/src/lib/components/trellis_row_display_value.svelte @@ -33,7 +33,7 @@ {:else if basis.label} {#if `value` in basis.label} <p - class={`${fmt_cl(basis.label.classes)} font-sans text-trellisLine line-clamp-1 ${get_label_classes(layer, basis.label.kind, hide_active)} transition-all`} + class={`${fmt_cl(basis.label.classes)} font-sans text-line_display line-clamp-1 ${get_label_classes(layer, basis.label.kind, hide_active)} transition-all`} > {basis.label.value} </p> diff --git a/apps-lib/src/lib/components/trellis_row_label.svelte b/apps-lib/src/lib/components/trellis_row_label.svelte @@ -25,7 +25,7 @@ </div> {:else if `value` in title_l} <p - class={`${fmt_cl(title_l.classes)} ${get_label_classes(layer, title_l.kind, hide_active)} ${title_l.hide_truncate ? `` : `truncate`} font-sans text-trellisLine transition-all`} + class={`${fmt_cl(title_l.classes)} ${get_label_classes(layer, title_l.kind, hide_active)} ${title_l.hide_truncate ? `` : `truncate`} font-sans text-line_display transition-all`} > {title_l.value || ``} </p> @@ -46,7 +46,7 @@ <Glyph basis={{ ...title_r.glyph }} /> {:else if `value` in title_r} <p - class={`${fmt_cl(title_r.classes)} ${get_label_classes(layer, title_r.kind, hide_active)} ${title_r.hide_truncate ? `` : `truncate`} font-sans text-trellisLine transition-all`} + class={`${fmt_cl(title_r.classes)} ${get_label_classes(layer, title_r.kind, hide_active)} ${title_r.hide_truncate ? `` : `truncate`} font-sans text-line_display transition-all`} > {title_r.value || ``} </p> diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -37,20 +37,22 @@ export { default as Tabs } from "./components/tabs.svelte"; export { default as TrellisTitle } from "./components/trellis_title.svelte"; export { default as TrellisTouch } from "./components/trellis_touch.svelte"; export { default as Trellis } from "./components/trellis.svelte"; -export { default as AppControls, init_toast, show_toast } from "./components/app_controls.svelte"; +export { default as AppControls } from "./components/app_controls.svelte"; +export { default as EntryLine } from "./components/entry_line.svelte"; export { default as TrellisRowDisplayValue } from "./components/trellis_row_display_value.svelte"; export { default as EnvelopeButtons } from "./components/envelope_buttons.svelte"; export { default as LayoutWindow } from "./components/layout_window.svelte"; +export { default as EntryMultiline } from "./components/entry_multiline.svelte"; export { default as LayoutTrellisLine } from "./components/layout_trellis_line.svelte"; export { default as NotifyGlyph } from "./components/notify_glyph.svelte"; export { default as TrellisDefaultLabel } from "./components/trellis_default_label.svelte"; +export { default as LayoutArea } from "./components/layout_area.svelte"; export { default as EnvelopeTitled } from "./components/envelope_titled.svelte"; export { default as ButtonLoading } from "./components/button_loading.svelte"; -export { default as InputForm } from "./components/input_form.svelte"; export { default as TrellisOffset } from "./components/trellis_offset.svelte"; export { default as Nav } from "./components/nav.svelte"; +export { default as EntryOption } from "./components/entry_option.svelte"; export { default as LoadingView } from "./components/loading_view.svelte"; export { default as NavOption } from "./components/nav_option.svelte"; -export { default as InputSelect } from "./components/input_select.svelte"; export { default as TrellisRowLabel } from "./components/trellis_row_label.svelte"; export { default as LayoutView } from "./components/layout_view.svelte"; diff --git a/apps-lib/src/lib/locales/en/app.json b/apps-lib/src/lib/locales/en/app.json @@ -1,3 +1,24 @@ { - "name": "Radroots" + "calendar": { + "weekday": { + "0": "Sunday", + "1": "Monday", + "2": "Tuesday", + "3": "Wednesday", + "4": "Thursday", + "5": "Friday", + "6": "Saturday" + } + }, + "name": "Radroots", + "page": { + "conf": { + "init": { + "notification": { + "no_profile_name": "Your profile will be created without a name. You can change this later in Settings > Profile", + "welcome": "Welcome! Your device was configured. To view or change your configuration go to Settings > Configuration" + } + } + } + } } \ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/common.json b/apps-lib/src/lib/locales/en/common.json @@ -1,9 +1,11 @@ { + "accept": "Accept", "active": "Active", "add": "Add", "add_current_location": "Add current location", "add_map_location": "Add map location", "add_new_location": "Add new location", + "agree": "Agree", "authenticated": "Authenticated", "back": "Back", "bank_account": "Bank account", @@ -18,21 +20,27 @@ "description": "Description", "details": "Details", "device": "Device", + "disagree": "Disagree", "disconnect": "Disconnect", "done": "Done", "edit": "Edit", "from": "From", "hex": "Hex", "inbox": "Inbox", + "items": "Items", "key": "Key", + "keypair": "Keypair", "keys": "Keys", "list": "List", + "listing": "Listing", "location": "Location", "locations": "Locations", "lot": "Lot", "lot_name": "Lot name", + "map": "Map", "message": "Message", "messages": "Messages", + "no": "No", "no_items_to_display": "No items to display", "no_locations_saved": "No locations saved", "not_connected": "Not connected", @@ -40,11 +48,15 @@ "nsec": "Nsec", "optional": "Optional", "other": "Other", + "page": "Page", "per": "Per", "personal": "Personal", "photos": "Photos", + "preview": "Preview", "price": "Price", + "process": "Process", "product": "Product", + "product_location": "Product location", "product_name": "Product name", "products": "Products", "profile": "Profile", @@ -52,11 +64,14 @@ "profiles": "Profiles", "public_key": "Public key", "quantity": "Quantity", + "quit": "Quit", "relay": "Relay", "relays": "Relays", + "review": "Review", "secret_key": "Secret key", "settings": "Settings", "setup": "Setup", + "skip": "Skip", "socials": "Socials", "status": "Status", "subject": "Subject", @@ -69,5 +84,6 @@ "url": "URL", "wallet": "Wallet", "website": "Website", + "yes": "Yes", "your_name": "Your name" } \ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/error.json b/apps-lib/src/lib/locales/en/error.json @@ -0,0 +1,15 @@ +{ + "client": { + "page": { + "status": { + "404": "The page was not found" + } + }, + "unhandled": "There was an error during your request" + }, + "geolocation": { + "request": { + "current": "Geolocation request failure" + } + } +} +\ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/eula.json b/apps-lib/src/lib/locales/en/eula.json @@ -0,0 +1,47 @@ +{ + "acceptance_of_terms": { + "body": "By using our Application, you signify your acceptance of this EULA. If you do not agree to this EULA, you may not use our Application.", + "title": "Acceptance of Terms" + }, + "changes": { + "body": "We reserve the right to update or modify this EULA at any time and without prior notice. Your continued use of our application following any changes to this EULA will be deemed to be your acceptance of such changes.", + "title": "Changes to EULA" + }, + "consequences_of_violation": { + "body": "Any violation of this EULA, including the prohibited content and conduct outlined above, may result in the termination of your access to our application.", + "title": "Consequences of Violation" + }, + "contact": { + "body": "If you have any questions about this EULA, please contact us at info@radroots.org", + "title": "Contact Information" + }, + "disclaimer": { + "body": "Our application is provided \"as is\" and \"as available\" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose. We do not guarantee that our application will be uninterrupted or error-free. In no event shall Radroots Inc. be liable for any damages whatsoever, including but not limited to direct, indirect, special, incidental, or consequential damages, arising out of or in connection with the use or inability to use our application.", + "title": "Disclaimer of Warranties and Limitation of Liability" + }, + "error": { + "required": "The user agreement is required to use the application" + }, + "introduction": { + "body": "This End User License Agreement (\"EULA\") is a legal agreement between you and Radroots Inc. for the use of our mobile application Radroots. By installing, accessing, or using our application, you agree to be bound by the terms and conditions of this EULA.", + "title": "Introduction" + }, + "prohibited_conduct": { + "body_li_0_0": "Harasses or bullies others", + "body_li_0_1": "Impersonates others", + "body_li_0_2": "Is intended to intimidate or threaten others", + "body_li_0_3": "Is intended to promote or incite violence", + "title": "You also agree not to engage in any conduct that:" + }, + "prohibited_content": { + "body_0_title": "You agree not to use our application to create, upload, post, send, or store any content that:", + "body_li_0_0": "Is illegal, infringing, or fraudulent", + "body_li_0_1": "Is pornographic, obscene, or offensive", + "body_li_0_2": "Is discriminatory or promotes hate speech", + "body_li_0_3": "Is harmful to minors", + "body_li_0_4": "Is intended to harass or bully others", + "body_li_0_5": "Is intended to impersonate others", + "title": "Prohibited Content and Conduct" + }, + "title": "End User License Agreement" +} +\ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/icu.json b/apps-lib/src/lib/locales/en/icu.json @@ -2,15 +2,22 @@ "*_as": "{value} as", "*_available": "{value} Available", "*_copied": "{value} copied", + "*_description": "{value} description", "*_details": "{value} details", "*_name": "{value} name", + "*_summary": "{value} summary", + "*_title": "{value} title", "*_your_device": "{value} your device", "add_*": "Add {value}", "add_a_*": "Add a {value}", + "add_existing_*": "Add existing {value}", "as_*": "As {value}", "choose_a_*": "Choose a {}", + "click_to_add_a_*": "Click to add a {value}", + "configure_*": "Configure {value}", "connect_*": "Connect {value}", "connected_*": "Connected {value}", + "create_new_*": "Create new {value}", "delete_*": "Delete {value}", "disconnect_*": "Disconnect {value}", "edit_*": "Edit {value}", @@ -19,19 +26,29 @@ "enter_new_*": "Enter new {value}", "enter_number_of_*_per_order": "Enter number of {value} per order", "enter_the_*": "Enter the {value}", + "error_loading_*": "Error loading {value}", + "go_*": "Go {value}", "invalid_*": "Invalid {value}", "invalid_*_entry": "Invalid {value} entry", "listing_*": "Listing {value}", + "name_your_*": "Name your {value}", + "new_*": "New {value}", "no_*": "No {value}", "no_*_published": "No {value} published", + "no_*_selected": "No {value} selected", + "no_*_to_display": "No {value} to display", "nostr_*": "Nostr {value}", "post_*": "Post {value}", "set_as_*": "Set as {value}", "show_*": "Show {value}", "the_*_is_available": "The {value} is available", + "the_*_is_missing": "The {value} is missing", "the_*_is_registered": "The {value} is registered", "total_*": "Total {value}", + "unable_to_save_*": "Unable to save {value}", "unconnected_*": "Unconnected {value}", + "use_existing_*": "Use existing {value}", + "valid_*": "Valid {value}", "view_*": "View {value}", "your_*": "Your {value}" } \ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/model.json b/apps-lib/src/lib/locales/en/model.json @@ -0,0 +1,56 @@ +{ + "location_gcs": { + "gc_admin1_id": "", + "gc_admin1_name": "", + "gc_country_id": "", + "gc_country_name": "", + "gc_id": "", + "gc_name": "", + "geohash": "Geohash", + "label": "Label", + "lat": "Latitude", + "lng": "Longitude" + }, + "nostr_profile": { + "about": "About", + "banner": "Profile banner", + "display_name": "Display name", + "lud06": "Payment request", + "lud16": "Payment address", + "name": "Profile name", + "nip05": "Profile address", + "picture": "Profile photo", + "public_key": "Public key", + "website": "Website" + }, + "nostr_relay": { + "contact": "Administrator contact", + "data": "Additional information", + "description": "Relay description", + "name": "Relay name", + "pubkey": "Administrator", + "relay_id": "", + "software": "Software", + "supported_nips": "Supported NIPs", + "url": "Relay endpoint", + "version": "Software version" + }, + "trade_product": { + "key": "Product name", + "lot": "Product lot", + "notes": "Notes", + "price_amt": "Price", + "price_currency": "Currency", + "price_qty_amt": "", + "price_qty_unit": "", + "process": "Processing method", + "profile": "Flavor profile", + "qty_amt": "Quantity", + "qty_avail": "Quantity available", + "qty_label": "Quantity label", + "qty_unit": "Quantity unit", + "summary": "Listing summary", + "title": "Listing title", + "year": "Year" + } +} +\ No newline at end of file diff --git a/apps-lib/src/lib/locales/en/model_fields.json b/apps-lib/src/lib/locales/en/model_fields.json @@ -1,47 +0,0 @@ -{ - "about": "About", - "banner": "Banner", - "contact": "", - "data": "", - "description": "Relay Description", - "display_name": "Display Name", - "gc_admin1_id": "", - "gc_admin1_name": "", - "gc_country_id": "", - "gc_country_name": "", - "gc_id": "", - "gc_name": "", - "geohash": "Geohash", - "key": "Key", - "label": "Label", - "lat": "Latitude", - "lng": "Longitude", - "lot": "Lot", - "lud06": "LUD 06", - "lud16": "LUD 16", - "name": "Profile Name", - "nip05": "NIP 05", - "notes": "Notes", - "picture": "Picture", - "price_amt": "Price", - "price_currency": "Currency", - "price_qty_amt": "Price", - "price_qty_unit": "Unit", - "process": "Process", - "profile": "Profile", - "pubkey": "Relay Admin", - "public_key": "Public Key", - "qty_amt": "Quantity Amount", - "qty_avail": "Quantity Available", - "qty_label": "Quantity Label", - "qty_unit": "Quantity Unit", - "relay_id": "", - "software": "Software", - "summary": "", - "supported_nips": "Supported NIPs", - "title": "", - "url": "", - "version": "Version", - "website": "Website", - "year": "Year" -} -\ No newline at end of file diff --git a/apps-lib/src/lib/locales/i18n.ts b/apps-lib/src/lib/locales/i18n.ts @@ -11,7 +11,7 @@ type LanguageConfig = { value?: string; }; -const locales_files = [`app`, `common`, `currency`, `icu`, `measurement`, `model_fields`, `trade`] as const; +const locales_files = [`app`, `common`, `currency`, `error`, `eula`, `icu`, `measurement`, `model`, `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 @@ -18,9 +18,11 @@ export let kv: Keyva; if (typeof window !== 'undefined') kv = new Keyva({ name: kv_name }); export const app_layout = writable<AppLayoutKey>(`mobile_base`); -export const app_config = writable<boolean>(false); +export const app_config = writable<boolean>(true); export const app_render = writable<boolean>(false); -export const app_win = writable<[number, number]>([0, 0]); +export const app_tilt = writable<boolean>(false); +export const app_loading = writable<boolean>(false); +export const app_win = writable<{ h: number, w: number }>({ h: 0, w: 0 }); export const app_notify = writable<string>(``); export const app_toast = writable<IToast | false>(false); export const app_submit_route = writable<NavigationPreviousParam | undefined>(undefined); diff --git a/apps-lib/src/lib/types/client.ts b/apps-lib/src/lib/types/client.ts @@ -43,6 +43,18 @@ export type IRouteOpt = { export type ICbGR<T> = ICbG<T> | IRoute +export type IId = { + id: string; +}; + +export type IIdOpt = { + id?: string; +}; + +export type IIdWrapOpt = { + id_wrap?: string; +}; + export type ICb = { callback: CallbackPromise; }; @@ -61,6 +73,10 @@ export type ICbGOpt<T> = { export type ICbROpt = ICbOpt | IRouteOpt +export type IClWrapOpt = { + classes_wrap?: string; +}; + export type IClOpt = { classes?: string; }; diff --git a/apps-lib/src/lib/types/components.ts b/apps-lib/src/lib/types/components.ts @@ -1,10 +1,9 @@ import type { NavigationRoute } from "$lib/utils/routes"; -import type { CallbackPromise, CallbackPromiseGeneric, ICb, ICbG, ICbGOpt, ICbOpt, IClOpt, IGl, IGlOpt, ILabel, ILabelFieldsOpt, ILabelOpt, ILabelOptFieldsOpt, ILyOpt, ILyOptTs, NavigationParamTuple } from "./client"; -import type { GlyphKey, GlyphWeight, IGlyph } from "./ui"; +import type { CallbackPromise, CallbackPromiseGeneric, ICb, ICbG, ICbGOpt, ICbOpt, IClOpt, IClWrapOpt, IGl, IGlOpt, IIdOpt, IIdWrapOpt, ILabel, ILabelFieldsOpt, ILabelOpt, ILabelOptFieldsOpt, ILyOpt, ILyOptTs, NavigationParamTuple } from "./client"; +import type { GlyphKey, GlyphWeight, IGlyph, IInputElement, ITextAreaElement } from "./ui"; -export type ITabsBasisList = { +export type ITabsBasisList = IClOpt & { icon: GlyphKey; - classes?: string; active_weight?: GlyphWeight; force_weight?: GlyphWeight indicator?: string; @@ -24,38 +23,34 @@ export type IFormField = { validate_keypress?: boolean; }; -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; - sync_init?: boolean; - field?: IFormField; +export type IEntryLine = IIdWrapOpt & IClWrapOpt & { + el: IInputElement; notify_inline?: { glyph: GlyphKey | IGlyph; }; -}; +} + +export type IEntryMultiLine = IIdWrapOpt & IClWrapOpt & { + el: ITextAreaElement; + notify_inline?: { + glyph: GlyphKey | IGlyph; + }; +} -export type IInputSelectBasisOption = { +export type IEntryOptionOption = { value: string; label?: string; disabled?: boolean; selected?: boolean; }; -export type IInputSelectBasis = IClOpt & ILyOptTs & ICbGOpt<string> & { - classes_wrap?: string; - id_wrap?: string; - id?: string; +export type IEntryOption = IIdOpt & IIdWrapOpt & IClWrapOpt & IClOpt & ILyOptTs & ICbGOpt<string> & { label?: string; hidden?: boolean; hide_arrows?: boolean; sync?: boolean; loading?: boolean; - options: IInputSelectBasisOption[]; + options: IEntryOptionOption[]; }; diff --git a/apps-lib/src/lib/types/ui.ts b/apps-lib/src/lib/types/ui.ts @@ -1,9 +1,12 @@ -import type { CallbackPromiseGeneric, GeometryCardinalDirection, GeometryDimension, GeometryGlyphDimension, ICbGOpt, ICbOpt, IClOpt, IFormField, ILy, ILyOptTs } from "$lib"; +import type { CallbackPromiseGeneric, GeometryCardinalDirection, GeometryDimension, GeometryGlyphDimension, ICbGOpt, ICbOpt, IClOpt, IFormField, IId, ILy, ILyOptTs } from "$lib"; import type { ThemeLayer } from "@radroots/theme"; export type GlyphKeyCurrency = `dollar` | `eur`; export type GlyphKey = | + `asterisk` | + `asterisk-simple` | + `subtitles-slash` | `cardholder` | `globe-x` | `exclamation-mark` | @@ -128,8 +131,7 @@ export type ISelectElement = ILy & options: { group?: string | true; entries: ISelectOption<string>[] }[]; }; -export type IInputElement = IClOpt & ILyOptTs & { - id: string; +export type IInputElement = IId & IClOpt & ILyOptTs & { placeholder?: string; label?: string; hidden?: boolean; @@ -140,13 +142,12 @@ export type IInputElement = IClOpt & ILyOptTs & { /*notify_inline?: { glyph: GlyphKey | IGlyph; };*/ - callback?: CallbackPromiseGeneric<{ val: string; pass: boolean; }>; + callback?: CallbackPromiseGeneric<{ value: string; pass: boolean; }>; callback_keydown?: CallbackPromiseGeneric<{ key: string; el: HTMLInputElement }>; on_mount?: CallbackPromiseGeneric<HTMLInputElement>; }; -export type ITextAreaElement = IClOpt & ILyOptTs & { - id: string; +export type ITextAreaElement = IId & IClOpt & ILyOptTs & { placeholder?: string; label?: string; hidden?: boolean; diff --git a/apps-lib/src/lib/ui/css_styles.svelte b/apps-lib/src/lib/ui/css_styles.svelte @@ -1,2 +1,3 @@ <div class="hidden h-[12px] w-[12px] h-[16px] w-[16px] h-[17px] w-[17px] h-[18px] w-[18px] h-[20px] w-[20px] h-[24px] w-[24px] h-[28px] w-[28px] h-[36px] w-[36px]"></div> -<div class="hidden text-[12px] text-[15px] text-[16px] text-[18px] text-[20px] text-[21px] text-[23px] text-[24px] text-[26px] text-[28px] text-[30px] text-[36px] text-[40px]"></div> -\ No newline at end of file +<div class="hidden text-[12px] text-[15px] text-[16px] text-[18px] text-[20px] text-[21px] text-[23px] text-[24px] text-[26px] text-[28px] text-[30px] text-[36px] text-[40px]"></div> +<div class="hidden h-tabs_mobile_base pt-h_tabs_mobile_base pb-h_tabs_mobile_base translate-y-h_tabs_mobile_base -translate-y-h_tabs_mobile_base h-tabs_mobile_y pt-h_tabs_mobile_y pb-h_tabs_mobile_y translate-y-h_tabs_mobile_y -translate-y-h_tabs_mobile_y h-nav_mobile_base pt-h_nav_mobile_base pb-h_nav_mobile_base translate-y-h_nav_mobile_base -translate-y-h_nav_mobile_base h-nav_mobile_y pt-h_nav_mobile_y pb-h_nav_mobile_y translate-y-h_nav_mobile_y -translate-y-h_nav_mobile_y h-view_mobile_base pt-h_view_mobile_base pb-h_view_mobile_base translate-y-h_view_mobile_base -translate-y-h_view_mobile_base h-view_mobile_y pt-h_view_mobile_y pb-h_view_mobile_y translate-y-h_view_mobile_y -translate-y-h_view_mobile_y h-view_offset_mobile_base pt-h_view_offset_mobile_base pb-h_view_offset_mobile_base translate-y-h_view_offset_mobile_base -translate-y-h_view_offset_mobile_base h-view_offset_mobile_y pt-h_view_offset_mobile_y pb-h_view_offset_mobile_y translate-y-h_view_offset_mobile_y -translate-y-h_view_offset_mobile_y w-mobile_base w-mobile_y top-dim_map_offset_top_mobile_base top-dim_map_offset_top_mobile_y"></div> +\ No newline at end of file diff --git a/apps-lib/src/lib/ui/input_element.svelte b/apps-lib/src/lib/ui/input_element.svelte @@ -1,5 +1,11 @@ <script lang="ts"> - import { type IInputElement, fmt_cl, kv, parse_layer } from "$lib"; + import { + type IInputElement, + fmt_cl, + kv, + parse_layer, + value_constrain, + } from "$lib"; import { onMount } from "svelte"; let el: HTMLInputElement | null = null; @@ -28,7 +34,9 @@ } } if (basis.on_mount) await basis.on_mount(el); - } catch (e) {} + } catch (e) { + console.log(`e input mount`, e); + } }); </script> @@ -36,26 +44,24 @@ bind:this={el} {id} type="text" - class={`${fmt_cl(basis.classes)} form-input text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} + class={`${fmt_cl(basis.classes)} el-input 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; let val = el.value; if (basis.field) { - val = el.value - .split("") - .filter((char) => basis.field.charset.test(char)) - .join(""); + val = value_constrain(basis.field.charset, val); + el.value = val; if ( !basis.field.validate.test(val) && basis.field.validate_keypress ) { - pass = false; + //@todo set styles } + pass = basis.field.validate.test(val); } - el.value = val; if (basis.sync) await kv.set(basis.id, val); - if (basis.callback) await basis.callback({ val, pass }); + if (basis.callback) await basis.callback({ value: val, pass }); }} on:keydown={async (ev) => { if (basis.callback_keydown) diff --git a/apps-lib/src/lib/ui/textarea_element.svelte b/apps-lib/src/lib/ui/textarea_element.svelte @@ -36,7 +36,7 @@ bind:this={el} {id} contenteditable="true" - class={`${fmt_cl(basis.classes)} form-textarea bg-layer-${layer}-surface text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} + class={`${fmt_cl(basis.classes)} el-textarea w-full bg-layer-${layer}-surface 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; diff --git a/apps-lib/src/lib/utils/carousel.ts b/apps-lib/src/lib/utils/carousel.ts @@ -44,9 +44,12 @@ export const carousel_next = async <T extends string>( if (get_store(carousel_active)) return; carousel_active.set(true); const slide_item = get_slide_item<T>(view); + console.log(`slide_item `, slide_item) const slide_container = get_slide_container<T>(view); + console.log(`slide_container `, slide_container) if (slide_container && slide_item) { const slide_w = slide_item?.clientWidth || 0; + console.log(`slide_w `, slide_w) slide_container.scrollLeft += slide_w; carousel_index.set( Math.min(get_store(carousel_index) + 1, get_store(carousel_index_max)), diff --git a/apps-lib/src/lib/utils/client.ts b/apps-lib/src/lib/utils/client.ts @@ -1,5 +1,5 @@ import { goto } from "$app/navigation"; -import type { AnchorRoute, AppLayoutKey, CallbackPromiseGeneric, GlyphKey, LabelFieldKind, NavigationParamTuple, NavigationRoute, NavigationRouteParamKey } from "$lib"; +import { app_toast, TOAST_MS, type AnchorRoute, type AppLayoutKey, type CallbackPromise, type CallbackPromiseGeneric, type GlyphKey, type IToast, type LabelFieldKind, type NavigationParamTuple, type NavigationRoute, type NavigationRouteParamKey } from "$lib"; import type { ColorMode, ThemeKey, ThemeLayer } from "@radroots/theme"; export const sleep = async (ms: number): Promise<void> => { @@ -115,6 +115,10 @@ export const route = async (route: NavigationRoute, params_list?: NavigationPara } } +//export const route_sync = (route: NavigationRoute): void => { +// goto(route); +//}; + export const get_layout = (val: string | false): AppLayoutKey => { switch (val) { case `mobile_base`: @@ -131,4 +135,38 @@ export const view_effect = <T extends string>(view: T): void => { `hidden`, el.getAttribute(`data-view`) !== view, ); +}; + + +export const init_toast = (): void => { + app_toast.set(false); +}; + +export const show_toast = async (opts: { + args: IToast | string; + callback?: CallbackPromise; +}): Promise<void> => { + try { + const basis: IToast = typeof opts.args === `string` + ? { + layer: 1, + label: { + value: opts.args, + }, + } + : opts.args; + app_toast.set(basis); + await sleep(TOAST_MS); + init_toast(); + if (opts.callback) await opts.callback(); + } catch (e) { + console.log(`(error) show_toast `, e); + } +}; + +export const value_constrain = (regex_charset: RegExp, value: string): string => { + return value + .split("") + .filter((char) => regex_charset.test(char)) + .join(""); }; \ No newline at end of file diff --git a/apps-lib/src/lib/utils/conf.ts b/apps-lib/src/lib/utils/conf.ts @@ -1,5 +1,7 @@ import type { ClientWindow } from "$lib/types/conf"; +export const TOAST_MS = 1500; + export const wind: ClientWindow = { app: { layout: { @@ -7,7 +9,7 @@ export const wind: ClientWindow = { h: 600 }, mobile_y: { - h: 768 + h: 750 } } } diff --git a/apps-lib/src/lib/utils/routes.ts b/apps-lib/src/lib/utils/routes.ts @@ -1,9 +1,6 @@ export type NavigationRoute = | "/" - | "/map" - | "/map/choose-location" | "/models/location-gcs" - | "/models/location-gcs/view-map" | "/models/nostr-profile" | "/models/nostr-profile/edit/field" | "/models/nostr-profile/view" @@ -11,22 +8,16 @@ export type NavigationRoute = | "/models/nostr-relay/view" | "/models/trade-product" | "/models/trade-product/add" - | "/nostr" - | "/nostr/keys" - | "/nostr/notes" - | "/nostr/notes/post" - | "/nostr/profile" | "/settings" | "/test" - | "/conf/init"; + | "/conf/error" + | "/conf/init" + | "/map"; export function parse_route(route: string): NavigationRoute { switch (route) { case "/": - case "/map": - case "/map/choose-location": case "/models/location-gcs": - case "/models/location-gcs/view-map": case "/models/nostr-profile": case "/models/nostr-profile/edit/field": case "/models/nostr-profile/view": @@ -34,14 +25,11 @@ export function parse_route(route: string): NavigationRoute { case "/models/nostr-relay/view": case "/models/trade-product": case "/models/trade-product/add": - case "/nostr": - case "/nostr/keys": - case "/nostr/notes": - case "/nostr/notes/post": - case "/nostr/profile": case "/settings": case "/test": + case "/conf/error": case "/conf/init": + case "/map": return route; default: return "/";