web_lib

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

commit 89ac1b591be31dec1d3c4f5674d31ba28d20ec41
parent 7c03b931d4ad30756f49ada8eaaeea67d26c792b
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Sat, 26 Oct 2024 19:12:01 +0000

apps-lib: add entry wrap component and edit entry components and types. edit select element. edit components, locales, styles, types, utils

Diffstat:
Mapps-lib/src/lib/components/button_carousel_pair.svelte | 2+-
Mapps-lib/src/lib/components/entry_line.svelte | 24+++++++-----------------
Dapps-lib/src/lib/components/entry_option.svelte | 79-------------------------------------------------------------------------------
Aapps-lib/src/lib/components/entry_select.svelte | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/entry_wrap.svelte | 22++++++++++++++++++++++
Mapps-lib/src/lib/components/layout_trellis_line.svelte | 5++++-
Aapps-lib/src/lib/el/select_el.svelte | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Dapps-lib/src/lib/el/select_element.svelte | 60------------------------------------------------------------
Aapps-lib/src/lib/el/select_menu.svelte | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/index.ts | 6++++--
Mapps-lib/src/lib/locales/en/icu.json | 2++
Mapps-lib/src/lib/types/components.ts | 35++++++++++++++++++++++-------------
Mapps-lib/src/lib/types/el.ts | 8+++-----
Mapps-lib/src/lib/utils/carousel.ts | 2+-
14 files changed, 258 insertions(+), 179 deletions(-)

diff --git a/apps-lib/src/lib/components/button_carousel_pair.svelte b/apps-lib/src/lib/components/button_carousel_pair.svelte @@ -18,7 +18,7 @@ <div class={`flex flex-col justify-center items-center`}> <button - class={`group flex flex-row h-touch_guide w-${$app_layout} justify-center items-center bg-layer-1-surface rounded-touch ${basis.continue.disabled ? `opacity-60` : `touch-layer-1`} transition-all`} + class={`group flex flex-row h-touch_guide w-${$app_layout} justify-center items-center bg-layer-1-surface rounde-40 ${basis.continue.disabled ? `opacity-60` : `touch-layer-1`} transition-all`} on:click|stopPropagation={async () => { if (!basis.continue.disabled) await basis.continue.callback(); }} diff --git a/apps-lib/src/lib/components/entry_line.svelte b/apps-lib/src/lib/components/entry_line.svelte @@ -1,6 +1,6 @@ <script lang="ts"> import { - fmt_cl, + EntryWrap, Glyph, InputElement, Loading, @@ -13,28 +13,18 @@ $: basis = basis; $: layer = - typeof basis.el?.layer === `boolean` + typeof basis.wrap?.layer === `boolean` ? false - : parse_layer(basis.el?.layer, 1); - $: classes_layer = - typeof layer === `boolean` - ? `bg-transparent` - : `bg-layer-${layer}-surface`; - $: clases_style = - basis.style === `guide` ? `h-entry_guide rounded-touch` : ``; - + : parse_layer(basis.wrap?.layer, 1); let loading_dim: ILoadingDimension = `sm`; - $: loading_dim = basis.style === `guide` ? `md` : `sm`; + $: loading_dim = basis.wrap?.style === `guide` ? `md` : `sm`; </script> -<div - id={basis.id_wrap || null} - class={`${fmt_cl(basis.classes)} relative el-re entry-line-wrap px-2 ${classes_layer} ${clases_style}`} -> +<EntryWrap basis={basis?.wrap}> <InputElement basis={basis.el} /> {#if basis.loading} <div - class={`z-5 absolute el-re right-0 top-0 flex flex-row h-full pr-4 justify-end items-center fade-in`} + class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-4 justify-end items-center fade-in el-re`} > <Loading basis={{ @@ -60,4 +50,4 @@ </div> {/if} {/if} -</div> +</EntryWrap> diff --git a/apps-lib/src/lib/components/entry_option.svelte b/apps-lib/src/lib/components/entry_option.svelte @@ -1,79 +0,0 @@ -<!-- svelte-ignore a11y-no-noninteractive-tabindex --> -<script lang="ts"> - import { - fmt_cl, - Glyph, - type IEntryOption, - kv, - Loading, - parse_layer, - } from "$lib"; - 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> - -<button - id={basis.id_wrap || null} - class={`${fmt_cl(basis.classes_wrap)} relative el-re entry-line-wrap ${classes_layer}`} -> - {#if basis.loading} - <div class={`flex flex-row w-full justify-center items-center`}> - <Loading basis={{ dim: `sm`, blades: 8 }} /> - </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} -</button> diff --git a/apps-lib/src/lib/components/entry_select.svelte b/apps-lib/src/lib/components/entry_select.svelte @@ -0,0 +1,76 @@ +<!-- svelte-ignore a11y-no-noninteractive-tabindex --> +<script lang="ts"> + import { + fmt_cl, + Glyph, + type IEntrySelect, + kv, + Loading, + parse_layer, + } from "$lib"; + import { onMount } from "svelte"; + import EntryWrap from "./entry_wrap.svelte"; + + let el: HTMLSelectElement | null; + + export let value: string; + export let basis: IEntrySelect; + $: basis = basis; + + $: layer = + typeof basis?.wrap.layer === `boolean` + ? parse_layer(0) + : parse_layer(basis?.wrap.layer, 1); + + onMount(async () => { + try { + if (basis?.el.sync && basis?.el.id) + await kv.set(basis?.el.id, basis?.el.options[0].value); + } catch (e) {} + }); +</script> + +<EntryWrap basis={basis?.wrap}> + {#if basis?.loading} + <div class={`flex flex-row w-full justify-center items-center`}> + <Loading basis={{ dim: `sm`, blades: 8 }} /> + </div> + {:else} + <select + bind:this={el} + bind:value + id={basis?.el.id || null} + class={`${fmt_cl(basis?.el.classes)} z-10 el-select entry-line-fluid text-layer-${layer}-glyph`} + on:change={async ({ currentTarget: el }) => { + const val = el.value; + if (basis?.el.sync && basis?.el.id) + await kv.set(basis?.el.id, val); + if (basis?.el.callback) await basis?.el.callback(val); + }} + > + {#each basis?.el.options as opt} + <option + value={opt.value} + disabled={!!opt.disabled} + selected={!!opt.selected} + > + {opt.label || opt.value} + </option> + {/each} + </select> + {/if} + {#if !basis?.el.hide_arrows} + <div + class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-4 justify-end items-center`} + > + <Glyph + basis={{ + key: `caret-up-down`, + dim: `xs`, + weight: `bold`, + classes: `text-layer-${layer}-glyph`, + }} + /> + </div> + {/if} +</EntryWrap> diff --git a/apps-lib/src/lib/components/entry_wrap.svelte b/apps-lib/src/lib/components/entry_wrap.svelte @@ -0,0 +1,22 @@ +<script lang="ts"> + import { fmt_cl, parse_layer, type IEntryWrap } from "$lib"; + + export let basis: IEntryWrap | undefined = undefined; + + $: layer = + typeof basis?.layer === `boolean` + ? false + : parse_layer(basis?.layer, 1); + $: classes_layer = + layer === false + ? `bg-transparent` + : `bg-layer-${layer}-surface ${basis?.style_a ? `active:bg-layer-${layer}-surface_a` : ``}`; + $: classes_h = basis?.style ? basis?.style : `form_line`; +</script> + +<button + id={basis?.id || null} + class={`${fmt_cl(basis?.classes)} relative entry-line-wrap pl-6 pr-4 h-${classes_h} rounded-entry ${classes_layer} el-re`} +> + <slot /> +</button> diff --git a/apps-lib/src/lib/components/layout_trellis_line.svelte b/apps-lib/src/lib/components/layout_trellis_line.svelte @@ -6,6 +6,7 @@ type ILabel, type ILabelOpt, } from "$lib"; + import { fade } from "svelte/transition"; export let basis: | (ILabelOpt & @@ -32,7 +33,9 @@ {/if} {#if basis?.notify} <div - class={`${fmt_cl(basis?.notify.classes)} flex flex-row justify-start items-center fade-in transition-all`} + in:fade={{ duration: 200 }} + out:fade={{ delay: 50, duration: 200 }} + class={`${fmt_cl(basis?.notify.classes)} flex flex-row justify-start items-center transition-all`} > <button class={`flex flex-row justify-center items-center`} diff --git a/apps-lib/src/lib/el/select_el.svelte b/apps-lib/src/lib/el/select_el.svelte @@ -0,0 +1,52 @@ +<script lang="ts"> + import { fmt_cl, parse_layer, type ISelectElement } from "$lib"; + + export let value: string; + export let basis: ISelectElement; + $: basis = basis; + + let el_wrap: HTMLDivElement | null = null; + let el_select: HTMLSelectElement | null = null; + $: layer = + typeof basis?.layer === `boolean` + ? parse_layer(0) + : parse_layer(basis.layer, 0); + $: classes_layer = + typeof basis?.layer === `boolean` ? `` : `text-layer-${layer}-glyph`; +</script> + +<select + class={`${fmt_cl(basis.classes)} z-10 el-select ${classes_layer}`} + bind:this={el_select} + bind:value + on:change={async (e) => { + const opt = basis.options + .map((i) => i.entries) + .reduce((_, j) => j, []) + .find((k) => k.value === e.currentTarget?.value); + if (basis.callback && opt) await basis.callback(opt); + if (el_select) el_select.value = value; + }} +> + {#each basis.options as opt_g} + {#if opt_g.group} + <optgroup> + {#each opt_g.entries as opt} + <option + label={opt_g.group === true + ? `-`.repeat(21) + : opt_g.group || ``} + > + {opt.label} + </option> + {/each} + </optgroup> + {:else} + {#each opt_g.entries as opt} + <option value={opt.value} disabled={!!opt.disabled}> + {opt.label} + </option> + {/each} + {/if} + {/each} +</select> diff --git a/apps-lib/src/lib/el/select_element.svelte b/apps-lib/src/lib/el/select_element.svelte @@ -1,60 +0,0 @@ -<script lang="ts"> - import type { ISelectElement } from "$lib"; - - export let basis: { args: ISelectElement }; - $: ({ args } = basis); - - const value = `~`; - - let el_wrap: HTMLDivElement | null = null; - let el_select: HTMLSelectElement | null = null; - let layer = args?.layer || 0; -</script> - -<div - class={`relative flex flex-row h-max w-auto justify-center items-center`} - bind:this={el_wrap} -> - <div - class={`z-50 absolute top-0 left-0 flex flex-row h-full w-full justify-end items-center text-layer-${layer}-glyph`} - > - <select - class={`select select-ghost h-full w-full bg-transparent focus:border-0 focus:outline-0 text-transparent focus:text-transparent`} - bind:this={el_select} - {value} - on:change={async (e) => { - const opt = args.options - .map((i) => i.entries) - .reduce((_, j) => j, []) - .find((k) => k.value === e.currentTarget?.value); - if (args.callback && opt) await args.callback(opt); - if (el_select) el_select.value = value; - }} - > - {#each args.options as optg} - {#if optg.group} - <optgroup> - {#each optg.entries as opt} - <option - label={optg.group === true - ? `-`.repeat(21) - : optg.group || ``} - > - {opt.label} - </option> - {/each} - </optgroup> - {:else} - {#each optg.entries as opt} - <option value={opt.value} disabled={!!opt.disabled}> - {opt.label} - </option> - {/each} - {/if} - {/each} - </select> - </div> - <div class={`z-10 flex flex-row h-full w-full`}> - <slot name="element" /> - </div> -</div> diff --git a/apps-lib/src/lib/el/select_menu.svelte b/apps-lib/src/lib/el/select_menu.svelte @@ -0,0 +1,64 @@ +<script lang="ts"> + import { fmt_cl, parse_layer, type ISelectElement } from "$lib"; + + export let value: string; + export let basis: ISelectElement; + $: basis = basis; + + let el_wrap: HTMLDivElement | null = null; + let el_select: HTMLSelectElement | null = null; + $: layer = + typeof basis?.layer === `boolean` + ? parse_layer(0) + : parse_layer(basis.layer, 0); + $: classes_layer = + typeof basis?.layer === `boolean` ? `` : `text-layer-${layer}-glyph`; +</script> + +<div + class={`relative flex flex-row h-max w-auto justify-center items-center`} + bind:this={el_wrap} +> + <div + class={`${fmt_cl(basis.classes)} z-10 absolute top-0 left-0 flex flex-row h-full w-full justify-end items-center ${classes_layer}`} + > + <select + class={`select select-ghost h-full w-full bg-transparent focus:border-0 focus:outline-0 text-transparent focus:text-transparent`} + bind:this={el_select} + bind:value + on:change={async (e) => { + const opt = basis.options + .map((i) => i.entries) + .reduce((_, j) => j, []) + .find((k) => k.value === e.currentTarget?.value); + if (basis.callback && opt) await basis.callback(opt); + if (el_select) el_select.value = value; + }} + > + {#each basis.options as opt_g} + {#if opt_g.group} + <optgroup> + {#each opt_g.entries as opt} + <option + label={opt_g.group === true + ? `-`.repeat(21) + : opt_g.group || ``} + > + {opt.label} + </option> + {/each} + </optgroup> + {:else} + {#each opt_g.entries as opt} + <option value={opt.value} disabled={!!opt.disabled}> + {opt.label} + </option> + {/each} + {/if} + {/each} + </select> + </div> + <div class={`z-10 flex flex-row h-full w-full`}> + <slot name="element" /> + </div> +</div> diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -6,19 +6,20 @@ export * from "./types/conf"; export * from "./types/el"; 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 GlyphCircle } from "./el/glyph_circle.svelte"; export { default as TextareaElement } from "./el/textarea_element.svelte"; export { default as CssStatic } from "./el/css_static.svelte"; export { default as Divider } from "./el/divider.svelte"; export { default as LabelSwap } from "./el/label_swap.svelte"; +export { default as SelectMenu } from "./el/select_menu.svelte"; export { default as Glyph } from "./el/glyph.svelte"; export { default as CssStyles } from "./el/css_styles.svelte"; export { default as Loading } from "./el/loading.svelte"; export { default as InputElement } from "./el/input_element.svelte"; export { default as Fill } from "./el/fill.svelte"; export { default as FillWhite } from "./el/fill_white.svelte"; +export { default as SelectEl } from "./el/select_el.svelte"; export * from "./stores/ndk"; export * from "./stores/client"; export * from "./utils/routes"; @@ -51,6 +52,7 @@ export { default as ButtonCarouselPair } from "./components/button_carousel_pair 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 EntryWrap } from "./components/entry_wrap.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"; @@ -58,8 +60,8 @@ 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 TrellisOffset } from "./components/trellis_offset.svelte"; +export { default as EntrySelect } from "./components/entry_select.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 TrellisRowLabel } from "./components/trellis_row_label.svelte"; diff --git a/apps-lib/src/lib/locales/en/icu.json b/apps-lib/src/lib/locales/en/icu.json @@ -6,6 +6,7 @@ "*_details": "{value} details", "*_failure": "{value} failure", "*_list": "{value} list", + "*_month": "{value} month", "*_name": "{value} name", "*_summary": "{value} summary", "*_title": "{value} title", @@ -51,6 +52,7 @@ "the_*_is_available": "The {value} is available", "the_*_is_missing": "The {value} is missing", "the_*_is_registered": "The {value} is registered", + "the_current_entry_*_will_be_deleted": "The current entry \"{value}\" will be deleted", "this_*": "This {value}", "total_*": "Total {value}", "unable_to_save_*": "Unable to save {value}", diff --git a/apps-lib/src/lib/types/components.ts b/apps-lib/src/lib/types/components.ts @@ -22,14 +22,21 @@ export type IFormField = { validate_keypress?: boolean; }; -export type ILineStyle = `guide`; -export type IEntryLine = IIdWrapOpt & IClOpt & ILoadingOpt & { +export type IEntryStyle = `guide` | `form_line`; +export type IEntryWrap = IClOpt & IIdOpt & ILyOptTs & { + style?: IEntryStyle; + style_a?: true; +} + +export type IEntryLine = ILoadingOpt & { + wrap?: IEntryWrap; el: IInputElement; - style?: ILineStyle notify_inline?: { glyph: GlyphKey | IGlyph; }; -} +}; + + export type IEntryMultiLine = IIdWrapOpt & IClWrapOpt & { el: ITextAreaElement; @@ -38,20 +45,22 @@ export type IEntryMultiLine = IIdWrapOpt & IClWrapOpt & { }; } -export type IEntryOptionOption = { +export type IEntrySelectOption = { value: string; label?: string; disabled?: boolean; selected?: boolean; }; -export type IEntryOption = IIdOpt & IIdWrapOpt & IClWrapOpt & IClOpt & ILyOptTs & ICbGOpt<string> & { - label?: string; - hidden?: boolean; - hide_arrows?: boolean; - sync?: boolean; - loading?: boolean; - options: IEntryOptionOption[]; +export type IEntrySelect = ILoadingOpt & { + wrap: IEntryWrap; + el: IIdOpt & IClOpt & ICbGOpt<string> & { + label?: string; + hidden?: boolean; + hide_arrows?: boolean; + sync?: boolean; + options: IEntrySelectOption[]; + } }; @@ -96,5 +105,5 @@ export type INavBasis = { export type IDisplayLine = IIdWrapOpt & IClOpt & ILabelValue & ILyOpt & { - style?: ILineStyle + style?: IEntryStyle } \ No newline at end of file diff --git a/apps-lib/src/lib/types/el.ts b/apps-lib/src/lib/types/el.ts @@ -1,9 +1,10 @@ -import type { CallbackPromiseGeneric, GeometryCardinalDirection, GeometryDimension, GeometryGlyphDimension, ICbGOpt, ICbOpt, IClOpt, IFormField, IId, IIdOpt, ILy, ILyOptTs } from "$lib"; +import type { CallbackPromiseGeneric, GeometryCardinalDirection, GeometryDimension, GeometryGlyphDimension, ICbGOpt, ICbOpt, IClOpt, IFormField, IId, IIdOpt, ILyOptTs } from "$lib"; import type { ThemeLayer } from "@radroots/theme"; export type GlyphKeyCurrency = `dollar` | `eur`; export type GlyphKey = | + `funnel` | `users-three` | `note-blank` | `user-circle-plus` | @@ -138,11 +139,8 @@ export type ISelectOption<T extends string> = { disabled?: boolean; }; -export type ISelectElement = ILy & +export type ISelectElement = IIdOpt & IClOpt & ILyOptTs & ICbGOpt<ISelectOption<string>> & { - id?: string; - classes?: string; - mask?: boolean; options: { group?: string | true; entries: ISelectOption<string>[] }[]; }; diff --git a/apps-lib/src/lib/utils/carousel.ts b/apps-lib/src/lib/utils/carousel.ts @@ -7,7 +7,7 @@ import { } from "$lib"; import { get as get_store } from 'svelte/store'; -const CAROUSEL_DELAY_MS = 150; +const CAROUSEL_DELAY_MS = 250; const get_slide_container = <T extends string>( view: T,