commit ef61c74a4f335e2a178c88226f29bc0b1ac4a2df parent eb762ba6b84f803ca5903169cfa1a403703453e6 Author: triesap <137732411+triesap@users.noreply.github.com> Date: Sat, 2 Nov 2024 07:41:52 +0000 apps-lib: add image path element. edit controls add app tilt effect on envelope visible subscription. edit envelope lower add rendering logic and inner scroll container. edit button layout basis type. edit layout view styles. edit nav option styles. edit input element add bind value export. edit select element rendering logic. add/edit locales, stores, types, utils Diffstat:
18 files changed, 235 insertions(+), 123 deletions(-)
diff --git a/apps-lib/src/lib/components/app_controls.svelte b/apps-lib/src/lib/components/app_controls.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { app_layout, app_toast, app_win, Toast, wind } from "$lib"; - import { onMount } from "svelte"; - - onMount(async () => { - try { - app_win.set({ h: window.innerHeight, w: window.innerWidth }); - app_toast.set(false); - } catch (e) { - console.log(`(layout mount) `, e); - } finally { - } - }); - - app_win.subscribe((_app_win) => { - if (_app_win.h > wind.app.layout.mobile_y.h) app_layout.set(`mobile_y`); - }); -</script> - -{#if $app_toast} - <Toast basis={$app_toast} /> -{/if} diff --git a/apps-lib/src/lib/components/button_layout.svelte b/apps-lib/src/lib/components/button_layout.svelte @@ -1,28 +1,33 @@ <script lang="ts"> import { app_layout, + fmt_cl, parse_layer, type CallbackPromise, + type IClOpt, type ILyOpt, } from "$lib"; - export let basis: ILyOpt & { - disabled?: boolean; - label: string; - callback: CallbackPromise; - }; + export let basis: ILyOpt & + IClOpt & { + classes_inner?: string; + hide_active?: boolean; + disabled?: boolean; + label: string; + callback: CallbackPromise; + }; $: layer = parse_layer(basis.layer, 1); </script> <button - class={`group flex flex-row h-touch_guide w-${$app_layout} justify-center items-center bg-layer-${layer}-surface round-44 ${basis.disabled ? `opacity-60` : `touch-layer-${layer}`} transition-all`} + class={`${fmt_cl(basis.classes)} group flex flex-row h-touch_guide w-${$app_layout} justify-center items-center bg-layer-${layer}-surface round-44 ${!basis.hide_active ? `active:bg-layer-${layer}-surface_a` : ``} ${basis.disabled ? `opacity-60` : ``} el-re`} on:click|stopPropagation={async () => { if (!basis.disabled) await basis.callback(); }} > <p - class={`font-sans font-[600] tracking-wide text-layer-${layer}-glyph_d ${basis.disabled ? `` : `group-active:text-layer-${layer}-glyph/40 `}transition-all`} + class={`${fmt_cl(basis.classes_inner)} font-sans font-[600] tracking-wide text-layer-${layer}-glyph_d ${basis.disabled ? `` : `group-active:text-layer-${layer}-glyph/40 `} el-re`} > {basis.label} </p> diff --git a/apps-lib/src/lib/components/controls.svelte b/apps-lib/src/lib/components/controls.svelte @@ -0,0 +1,35 @@ +<script lang="ts"> + import { + app_layout, + app_tilt, + app_toast, + app_win, + envelope_visible, + Toast, + wind, + } from "$lib"; + import { onMount } from "svelte"; + + onMount(async () => { + try { + app_win.set({ h: window.innerHeight, w: window.innerWidth }); + app_toast.set(false); + } catch (e) { + console.log(`(layout mount) `, e); + } finally { + } + }); + + app_win.subscribe((_app_win) => { + if (_app_win.h > wind.app.layout.mobile_y.h) app_layout.set(`mobile_y`); + }); + + envelope_visible.subscribe(async (_envelope_visible) => { + if (_envelope_visible) app_tilt.set(true); + else app_tilt.set(false); + }); +</script> + +{#if $app_toast} + <Toast basis={$app_toast} /> +{/if} diff --git a/apps-lib/src/lib/components/envelope_lower.svelte b/apps-lib/src/lib/components/envelope_lower.svelte @@ -1,30 +1,34 @@ <script lang="ts"> - import { app_tilt, Fill, t, type CallbackPromise } from "$lib"; + import { envelope_visible, Fill, t, type CallbackPromise } from "$lib"; import { quintInOut } from "svelte/easing"; import { fly } from "svelte/transition"; + let el_c: HTMLDivElement; + + let el_c_scrolled = false; + export let basis: { - visible: boolean; close: CallbackPromise; label_close?: string | true; }; $: basis = basis; - $: if (basis.visible) { - app_tilt.set(true); - } - const handle_close = async (): Promise<void> => { try { - app_tilt.set(false); + envelope_visible.set(false); await basis.close(); } catch (e) { console.log(`(error) handle_close `, e); } }; + + const handle_scroll = (): void => { + if (el_c.scrollTop > 10) el_c_scrolled = true; + else el_c_scrolled = false; + }; </script> -{#if basis.visible} +{#if $envelope_visible} <div in:fly={{ y: `100%`, easing: quintInOut }} out:fly={{ y: `100%`, easing: quintInOut }} @@ -39,10 +43,10 @@ <Fill /> </button> <div - class={`flex flex-col h-[calc(100vh-12%)] w-full justify-start justify-start items-start bg-layer-1-surface rounded-t-2xl`} + class={`relative flex flex-col h-[calc(100vh-12%)] w-full justify-start justify-start items-start bg-layer-1-surface rounded-t-2xl overflow-hidden`} > <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`} + class={`absolute z-10 top-0 left-0 grid grid-cols-12 flex flex-row h-12 w-full px-4 pb-2 justify-center items-center ${el_c_scrolled ? `bg-layer-1-surface/30 backdrop-blur-lg` : ``} el-re`} > <div class={`col-span-4 flex flex-row h-full justify-start items-end`} @@ -83,7 +87,9 @@ </div> </div> <div - class={`flex flex-col w-full justify-start items-center overflow-y-scroll overflow-x-hidden scroll-hide`} + bind:this={el_c} + on:scroll={handle_scroll} + class={`flex flex-col w-full pt-12 justify-start items-center overflow-y-scroll overflow-x-hidden scroll-hide`} > <slot /> </div> diff --git a/apps-lib/src/lib/components/layout_view.svelte b/apps-lib/src/lib/components/layout_view.svelte @@ -4,6 +4,7 @@ type IClOpt, app_layout, fmt_cl, + layout_view_cover, nav_blur, nav_visible, tabs_blur, @@ -16,9 +17,7 @@ mobile_y: "pt-16 pb-10", }; - export let basis: - | (IClOpt & { fade?: boolean; hide_padding?: boolean }) - | undefined = undefined; + export let basis: (IClOpt & { fade?: boolean }) | undefined = undefined; $: basis = basis; let el: HTMLElement | null; @@ -43,7 +42,6 @@ ? `pt-h_nav_${$app_layout} ${styles[$app_layout]}` : styles[$app_layout]; $: classes_tabs = $tabs_visible ? `pb-h_tabs_${$app_layout}` : ``; - $: classes_fade = basis?.fade ? `fade-in` : ``; const scrollChange = (): void => { if (Math.max(el?.scrollTop || 0, 0) > 10) nav_blur.set(true); @@ -55,7 +53,7 @@ <div bind:this={el} - class={`${fmt_cl(basis?.classes)} absolute top-0 left-0 flex flex-col h-[100vh] w-full justify-start items-center overflow-y-scroll scroll-hide ${!basis?.hide_padding ? classes_layout : ``} ${classes_tabs} ${classes_fade}`} + class={`${fmt_cl(basis?.classes)} absolute top-0 left-0 flex flex-col h-[100vh] w-full justify-start items-center overflow-y-scroll scroll-hide ${$layout_view_cover ? `` : classes_layout} ${$layout_view_cover ? `` : classes_tabs} ${basis?.fade ? `fade-in` : ``}`} > <slot /> </div> diff --git a/apps-lib/src/lib/components/nav_option.svelte b/apps-lib/src/lib/components/nav_option.svelte @@ -46,14 +46,14 @@ > <div class="swap-on"> <p - class={`${fmt_cl(basis?.label?.swap?.on.classes || `text-navPrevious text-layer-${layer}-glyph-hl group-active:opacity-60`)} font-sans -translate-y-[1px] transition-all`} + class={`${fmt_cl(basis?.label?.swap?.on.classes || `text-navPrevious text-layer-${layer}-glyph-hl group-active:opacity-70`)} font-sans -translate-y-[1px] el-re`} > {basis?.label?.swap?.on.value} </p> </div> <div class="swap-off"> <p - class={`${fmt_cl(basis?.label?.swap?.off.classes || `text-navPrevious text-layer-${layer}-glyph-hl group-active:opacity-60`)} font-sans -translate-y-[1px] transition-all`} + class={`${fmt_cl(basis?.label?.swap?.off.classes || `text-navPrevious text-layer-${layer}-glyph-hl group-active:opacity-70`)} font-sans -translate-y-[1px] el-re`} > {basis?.label?.swap?.off.value} </p> @@ -61,7 +61,7 @@ </label> {:else if `value` in basis?.label} <p - class={`${fmt_cl(basis?.label.classes)} font-sans text-navPrevious text-layer-1-glyph-hl group-active:opacity-60 transition-opacity`} + class={`${fmt_cl(basis?.label.classes)} font-sans text-navPrevious text-layer-1-glyph-hl group-active:opacity-70 el-re`} > {basis?.label.value} </p> @@ -70,7 +70,7 @@ <Glyph basis={{ key: basis?.label?.glyph?.key, - classes: `text-layer-1-glyph-hl group-active:opacity-60 ${basis?.label?.glyph?.classes}`, + classes: `text-layer-1-glyph-hl group-active:opacity-70 ${basis?.label?.glyph?.classes}`, weight: `bold`, dim: `md`, }} diff --git a/apps-lib/src/lib/el/image_path.svelte b/apps-lib/src/lib/el/image_path.svelte @@ -0,0 +1,37 @@ +<script lang="ts"> + import type { IClOpt } from "$lib/types/client"; + import { fmt_cl } from "$lib/utils/client"; + import { onMount } from "svelte"; + + export let basis: IClOpt & { + path?: string; + alt?: string; + }; + + let img_src = ``; + + onMount(async () => { + try { + if (basis.path) img_src = basis.path; + } catch (e) { + } finally { + } + }); +</script> + +{#if img_src} + <img + class={`${fmt_cl(basis.path)}`} + src={img_src} + alt={basis.alt || null} + /> +{/if} + +<style> + img { + height: 100%; + width: 100%; + object-fit: cover; + display: block; + } +</style> diff --git a/apps-lib/src/lib/el/input_element.svelte b/apps-lib/src/lib/el/input_element.svelte @@ -10,42 +10,32 @@ let el: HTMLInputElement | null = null; + export let value: string = ``; export let basis: IInputElement; - $: basis = basis; - - $: id = basis?.id ? basis?.id : null; - $: layer = - typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer, 1); //@todo onMount(async () => { try { - await kv_init(); + if (basis.id && basis.sync_init) { + const sync_val = await kv.get(basis.id); + await kv.set(basis.id, sync_val || ``); + } } catch (e) { - console.log(`e input mount`, e); + } finally { } }); - const kv_init = async (): Promise<void> => { - try { - if (basis?.id) { - if (basis?.sync_init) - await kv.set( - basis?.id, - typeof basis?.sync_init === `string` - ? basis?.sync_init - : ``, - ); - if (basis?.sync) { - const kv_val = await kv.get(basis?.id); - if (kv_val && el) el.value = kv_val; - else await kv.set(basis?.id, ``); - } - } - if (basis?.on_mount) await basis?.on_mount(el); - } catch (e) { - console.log(`(error) kv_init `, e); - } - }; + $: basis = basis; + $: id = basis?.id ? basis?.id : null; + $: layer = + typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer, 1); //@todo + + $: if (basis?.id && basis?.sync) { + (async () => { + try { + await kv.set(basis?.id, value); + } catch (e) {} + })(); + } const handle_on_input = async (el: HTMLInputElement): Promise<void> => { try { @@ -72,10 +62,7 @@ <input bind:this={el} - {id} - type="text" - class={`${fmt_cl(basis?.classes)} el-input text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph el-re`} - placeholder={basis?.placeholder || ""} + bind:value on:input={async ({ currentTarget: el }) => { await handle_on_input(el); }} @@ -89,4 +76,8 @@ el: ev.currentTarget, }); }} + {id} + type="text" + class={`${fmt_cl(basis?.classes)} el-input text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph el-re`} + placeholder={basis?.placeholder || ""} /> diff --git a/apps-lib/src/lib/el/select_element.svelte b/apps-lib/src/lib/el/select_element.svelte @@ -2,11 +2,13 @@ import { fmt_cl, Glyph, kv, parse_layer, type ISelectElement } from "$lib"; import { onMount } from "svelte"; + let el: HTMLSelectElement | null = null; + export let value: string; export let basis: ISelectElement; - $: basis = basis; - let el: HTMLSelectElement | null = null; + $: basis = basis; + $: id = basis?.id ? basis?.id : null; $: layer = typeof basis?.layer === `boolean` ? parse_layer(0) @@ -16,31 +18,22 @@ onMount(async () => { try { - await kv_init(); - } catch (e) { - console.log(`e select mount`, e); - } - }); - const kv_init = async (): Promise<void> => { - try { - if (basis?.id) { - if (basis?.sync_init) - await kv.set( - basis?.id, - typeof basis?.sync_init === `string` - ? basis?.sync_init - : ``, - ); - if (basis?.sync) { - const kv_val = await kv.get(basis?.id); - if (kv_val && el) el.value = kv_val; - else await kv.set(basis?.id, ``); - } + if (basis.id && basis.sync_init) { + const sync_val = await kv.get(basis.id); + await kv.set(basis.id, sync_val || ``); } } catch (e) { - console.log(`(error) kv_init `, e); + } finally { } - }; + }); + + $: if (basis?.id && basis?.sync) { + (async () => { + try { + await kv.set(basis?.id, value); + } catch (e) {} + })(); + } const handle_on_change = async (el: HTMLSelectElement): Promise<void> => { try { @@ -70,12 +63,13 @@ </div> {/if} <select - class={`${fmt_cl(basis.classes)} z-10 el-select ${classes_layer}`} bind:this={el} bind:value on:change={async ({ currentTarget: el }) => { handle_on_change(el); }} + {id} + class={`${fmt_cl(basis.classes)} z-10 el-select ${classes_layer}`} > {#each basis.options as opt_g} {#if opt_g.group} diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -8,6 +8,7 @@ export * from "./types/nostr"; export { default as Blur } from "./el/blur.svelte"; export { default as SelectElement } from "./el/select_element.svelte"; export { default as Toast } from "./el/toast.svelte"; +export { default as ImagePath } from "./el/image_path.svelte"; export { default as GlyphCircle } from "./el/glyph_circle.svelte"; export { default as TextareaElement } from "./el/textarea_element.svelte"; export { default as CssStatic } from "./el/css_static.svelte"; @@ -45,8 +46,8 @@ export { default as ButtonOptsDisplay } from "./components/button_opts_display.s 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 Controls } from "./components/controls.svelte"; export { default as ButtonOptsStatic } from "./components/button_opts_static.svelte"; -export { default as AppControls } from "./components/app_controls.svelte"; export { default as EntryLine } from "./components/entry_line.svelte"; export { default as SplashScreen } from "./components/splash_screen.svelte"; export { default as TrellisRowDisplayValue } from "./components/trellis_row_display_value.svelte"; diff --git a/apps-lib/src/lib/locales/en/common.json b/apps-lib/src/lib/locales/en/common.json @@ -20,6 +20,8 @@ "connected": "Connected", "connection": "Connection", "continue": "Continue", + "date_created": "Date created", + "date_modified": "Date modified", "delete": "Delete", "description": "Description", "details": "Details", @@ -30,6 +32,8 @@ "done": "Done", "edit": "Edit", "end_date": "End date", + "file_name": "File name", + "file_size": "File size", "filters": "Filters", "from": "From", "hex": "Hex", diff --git a/apps-lib/src/lib/locales/en/icu.json b/apps-lib/src/lib/locales/en/icu.json @@ -13,10 +13,12 @@ "*_the": "{value} the", "*_title": "{value} title", "*_your_device": "{value} your device", + "a_*_is_required": "A {value} is required", "add_*": "Add {value}", "add_a_*": "Add a {value}", "add_existing_*": "Add existing {value}", "as_*": "As {value}", + "choose_*": "Choose {value}", "choose_a_*": "Choose a {}", "click_to_add_a_*": "Click to add a {value}", "configure_*": "Configure {value}", @@ -49,6 +51,7 @@ "no_*_to_display": "No {value} to display", "nostr_*": "Nostr {value}", "post_*": "Post {value}", + "primary_*": "Primary {value}", "set_as_*": "Set as {value}", "show_*": "Show {value}", "the_*": "The {value}", diff --git a/apps-lib/src/lib/locales/en/trade.json b/apps-lib/src/lib/locales/en/trade.json @@ -34,6 +34,66 @@ "semi_washed": "Semi-Washed", "washed": "Washed", "wet_hulled": "Wet-Hulled" + }, + "profile": { + "apricot": "Apricot", + "banana": "Banana", + "bergamot": "Bergamot", + "berry": "Berry", + "black cherry": "Black Cherry", + "black currant": "Black Currant", + "black tea": "Black Tea", + "blueberry": "Blueberry", + "brown sugar": "Brown Sugar", + "caramel": "Caramel", + "cherry": "Cherry", + "chocolate": "Chocolate", + "cola": "Cola", + "cranberry": "Cranberry", + "ctrius": "Ctrius", + "dark chocolate": "Dark Chocolate", + "dried dates": "Dried Dates", + "dried fig": "Dried Fig", + "golden raisin": "Golden Raisin", + "grape": "Grape", + "grapefruit": "Grapefruit", + "green apple": "Green Apple", + "green grape": "Green Grape", + "green tea": "Green Tea", + "jasmine honeysuckle": "Jasmine Honeysuckle", + "lemon": "Lemon", + "licorice/anise": "Licorice/Anise", + "lychee": "Lychee", + "magnolia": "Magnolia", + "mandarin": "Mandarin", + "mango": "Mango", + "maple syrup": "Maple Syrup", + "marshmallow": "Marshmallow", + "milk chocolate": "Milk Chocolate", + "natural": "Natural", + "nectarine": "Nectarine", + "nougat": "Nougat", + "nut": "Nut", + "orange": "Orange", + "orange blossom": "Orange Blossom", + "peach": "Peach", + "pineapple": "Pineapple", + "plum": "Plum", + "prune": "Prune", + "raisin": "Raisin", + "raspberry": "Raspberry", + "red apple": "Red Apple", + "red currant": "Red Currant", + "red grape": "Red Grape", + "roses": "Roses", + "star fruit": "Star Fruit", + "stronefruit": "Stronefruit", + "sugar cane": "Sugar Cane", + "sweet bread pastry": "Sweet Bread Pastry", + "tamarind": "Tamarind", + "tropical fruit": "Tropical Fruit", + "vanilla": "Vanilla", + "white grape": "White Grape" } }, "maca": { diff --git a/apps-lib/src/lib/stores/client.ts b/apps-lib/src/lib/stores/client.ts @@ -41,6 +41,8 @@ export const nav_visible = writable<boolean>(false); export const nav_blur = writable<boolean>(false); export const nav_prev = writable<NavigationPreviousParam[]>([]); +export const layout_view_cover = writable<boolean>(false); + export const tabs_visible = writable<boolean>(false); export const tabs_blur = writable<boolean>(false); export const tabs_active = writable<number>(0); @@ -50,6 +52,8 @@ export const carousel_index = writable<number>(0); export const carousel_index_max = writable<number>(0); export const carousel_num = writable<number>(1); +export const envelope_visible = writable<boolean>(false); + export const nostr_ndk_configured = writable<boolean>(false); export const nostr_relays_poll_documents = writable<boolean>(false); export const nostr_relays_poll_documents_count = writable<number>(0); diff --git a/apps-lib/src/lib/types/el.ts b/apps-lib/src/lib/types/el.ts @@ -144,8 +144,8 @@ export type ISelectOption<T extends string> = { export type ISelectElement = IIdOpt & IClOpt & ILyOptTs & ICbGOpt<ISelectOption<string>> & { - sync?: true; - sync_init?: true | string; + sync?: boolean; + sync_init?: boolean; options: { group?: string | true; entries: ISelectOption<string>[] }[]; show_arrows?: 'l' | 'r'; }; @@ -155,8 +155,8 @@ export type IInputElement = IId & IClOpt & ILyOptTs & { label?: string; hidden?: boolean; validate?: RegExp; - sync?: true; - sync_init?: true | string; + sync?: boolean; + sync_init?: boolean; field?: IFormField; /*notify_inline?: { glyph: GlyphKey | IGlyph; diff --git a/apps-lib/src/lib/utils/client.ts b/apps-lib/src/lib/utils/client.ts @@ -109,18 +109,18 @@ export const as_glyph_key = (val: string): GlyphKey => { return val as GlyphKey; } -export const route = async (route: NavigationRoute, params_list?: NavigationParamTuple[]): Promise<void> => { +export const route = async (nav_route: NavigationRoute, params_list?: NavigationParamTuple[]): Promise<void> => { try { - if (params_list && params_list.length) await goto(encode_qp_route(route, params_list)); - else await goto(route); + if (params_list && params_list.length) await goto(encode_qp_route(nav_route, params_list)); + else await goto(nav_route); } catch (e) { console.log(`(error) route `, e); } } -//export const route_sync = (route: NavigationRoute): void => { -// goto(route); -//}; +export const route_sync = (nav_route: NavigationRoute): void => { + route(nav_route); +}; export const get_layout = (val: string | false): AppLayoutKey => { switch (val) { diff --git a/apps-lib/src/lib/utils/numbers.ts b/apps-lib/src/lib/utils/numbers.ts @@ -1,7 +1,7 @@ import { locale } from "$lib/locales/i18n"; import { get as get_store } from "svelte/store"; -export const price_locale_fmt = (currency: string, value: string): string => { +export const fmt_price = (currency: string, value: string): string => { const value_num = parseFloat(value); const res = new Intl.NumberFormat(get_store(locale), { style: 'currency', diff --git a/apps-lib/src/lib/utils/routes.ts b/apps-lib/src/lib/utils/routes.ts @@ -9,9 +9,7 @@ export type NavigationRoute = | "/models/trade-product" | "/models/trade-product/add" | "/settings" - | "/test" - | "/cfg/error" - | "/cfg/init"; + | "/test"; export function parse_route(route: string): NavigationRoute { switch (route) { @@ -26,8 +24,6 @@ export function parse_route(route: string): NavigationRoute { case "/models/trade-product/add": case "/settings": case "/test": - case "/cfg/error": - case "/cfg/init": return route; default: return "/";