web_lib

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

commit f1bb73fc7c3ffcfb51be7f987a043ef75c749257
parent d58bc3e68e4a5bf701c1a0bc07abbeb341b476fd
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Thu,  7 Aug 2025 17:11:20 +0000

apps-lib: restructure library modules

Diffstat:
Mapps-lib/.gitignore | 50++++++++++++++++++++++++--------------------------
Mapps-lib/package.json | 29++++++++++++++++-------------
Dapps-lib/src/lib/components/button/button-horizontal-pair-slide.svelte | 45---------------------------------------------
Dapps-lib/src/lib/components/button/button-label-dashed.svelte | 24------------------------
Dapps-lib/src/lib/components/button/button-label-glyph.svelte | 42------------------------------------------
Dapps-lib/src/lib/components/button/button-layout-pair.svelte | 65-----------------------------------------------------------------
Dapps-lib/src/lib/components/button/button-layout.svelte | 51---------------------------------------------------
Dapps-lib/src/lib/components/button/button-round-nav.svelte | 24------------------------
Dapps-lib/src/lib/components/button/button-round.svelte | 25-------------------------
Dapps-lib/src/lib/components/button/button-simple-glyph.svelte | 30------------------------------
Dapps-lib/src/lib/components/button/button-simple.svelte | 22----------------------
Dapps-lib/src/lib/components/button/glyph-button-simple.svelte | 46----------------------------------------------
Dapps-lib/src/lib/components/button/glyph-button.svelte | 19-------------------
Dapps-lib/src/lib/components/carousel/carousel-flow-item.svelte | 19-------------------
Dapps-lib/src/lib/components/carousel/carousel-flow.svelte | 53-----------------------------------------------------
Dapps-lib/src/lib/components/carousel/carousel-item.svelte | 19-------------------
Dapps-lib/src/lib/components/carousel/carousel.svelte | 24------------------------
Dapps-lib/src/lib/components/envelope/envelope-lower-full.svelte | 29-----------------------------
Dapps-lib/src/lib/components/envelope/map-location-select-envelope.svelte | 97-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/float/float-page.svelte | 12------------
Dapps-lib/src/lib/components/form/entry-line-idb.svelte | 68--------------------------------------------------------------------
Dapps-lib/src/lib/components/form/entry-line.svelte | 71-----------------------------------------------------------------------
Dapps-lib/src/lib/components/form/entry-multiline.svelte | 49-------------------------------------------------
Dapps-lib/src/lib/components/form/entry-select.svelte | 54------------------------------------------------------
Dapps-lib/src/lib/components/form/entry-wrap.svelte | 32--------------------------------
Dapps-lib/src/lib/components/form/form-entry-input.svelte | 44--------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-price-quantity.svelte | 117-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-price.svelte | 122-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-quantity.svelte | 105-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-select-input.svelte | 94-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-select.svelte | 56--------------------------------------------------------
Dapps-lib/src/lib/components/form/form-entry-textarea.svelte | 55-------------------------------------------------------
Dapps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte | 36------------------------------------
Dapps-lib/src/lib/components/form/form-line-ledger-select.svelte | 88-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-line-ledger.svelte | 92-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/form/form-review-display.svelte | 43-------------------------------------------
Dapps-lib/src/lib/components/form/trade_field_display_kv.svelte | 81-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/glyph/glyph-circle.svelte | 20--------------------
Dapps-lib/src/lib/components/glyph/glyph.svelte | 19-------------------
Dapps-lib/src/lib/components/label/label-display.svelte | 31-------------------------------
Dapps-lib/src/lib/components/layout/layout-bottom-button.svelte | 22----------------------
Dapps-lib/src/lib/components/layout/layout-page.svelte | 19-------------------
Dapps-lib/src/lib/components/layout/layout-trellis-line.svelte | 62--------------------------------------------------------------
Dapps-lib/src/lib/components/layout/layout-trellis.svelte | 19-------------------
Dapps-lib/src/lib/components/layout/layout-view.svelte | 54------------------------------------------------------
Dapps-lib/src/lib/components/layout/layout-window.svelte | 36------------------------------------
Dapps-lib/src/lib/components/lib/css.svelte | 2--
Dapps-lib/src/lib/components/lib/empty.svelte | 3---
Dapps-lib/src/lib/components/lib/fade.svelte | 22----------------------
Dapps-lib/src/lib/components/lib/image-blob.svelte | 26--------------------------
Dapps-lib/src/lib/components/lib/image-path.svelte | 21---------------------
Dapps-lib/src/lib/components/lib/image-src.svelte | 18------------------
Dapps-lib/src/lib/components/lib/image.svelte | 16----------------
Dapps-lib/src/lib/components/lib/input-idb.svelte | 120-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/input-value.svelte | 67-------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/input.svelte | 114-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/label-swap.svelte | 37-------------------------------------
Dapps-lib/src/lib/components/lib/load-symbol-white.svelte | 70----------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/load-symbol.svelte | 70----------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/logo-circle-sm.svelte | 14--------------
Dapps-lib/src/lib/components/lib/logo-letters.svelte | 5-----
Dapps-lib/src/lib/components/lib/logo_circle.svelte | 18------------------
Dapps-lib/src/lib/components/lib/select-menu.svelte | 80-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/select.svelte | 120-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/splash_screen.svelte | 14--------------
Dapps-lib/src/lib/components/lib/swipe.svelte | 45---------------------------------------------
Dapps-lib/src/lib/components/lib/text-area.svelte | 76----------------------------------------------------------------------------
Dapps-lib/src/lib/components/lib/theme.svelte | 17-----------------
Dapps-lib/src/lib/components/lib/toast.svelte | 53-----------------------------------------------------
Dapps-lib/src/lib/components/lib/wrap-border.svelte | 23-----------------------
Dapps-lib/src/lib/components/map/map-marker-area-display.svelte | 57---------------------------------------------------------
Dapps-lib/src/lib/components/map/map-marker-area.svelte | 49-------------------------------------------------
Dapps-lib/src/lib/components/map/map.svelte | 42------------------------------------------
Dapps-lib/src/lib/components/marker/marker-indexed-view.svelte | 31-------------------------------
Dapps-lib/src/lib/components/navigation/navigation-tabs.svelte | 99-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/navigation/page-header.svelte | 59-----------------------------------------------------------
Dapps-lib/src/lib/components/navigation/page-toolbar.svelte | 60------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-default-label.svelte | 37-------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-end.svelte | 35-----------------------------------
Dapps-lib/src/lib/components/trellis/trellis-input.svelte | 83-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-line.svelte | 56--------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-offset.svelte | 74--------------------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-row-display-value.svelte | 43-------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-row-label.svelte | 62--------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-select.svelte | 67-------------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-title.svelte | 68--------------------------------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis-touch.svelte | 42------------------------------------------
Dapps-lib/src/lib/components/trellis/trellis.svelte | 152-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/upload/image-upload-add-photo.svelte | 47-----------------------------------------------
Dapps-lib/src/lib/components/upload/image-upload-buttons-aspect.svelte | 95-------------------------------------------------------------------------------
Dapps-lib/src/lib/components/upload/image-upload-simple.svelte | 69---------------------------------------------------------------------
Dapps-lib/src/lib/components/window/window-resize-listener.svelte | 38--------------------------------------
Dapps-lib/src/lib/components/window/window-safari-listener.svelte | 38--------------------------------------
Dapps-lib/src/lib/features/farm/farms-add-casli-detail.svelte | 97-------------------------------------------------------------------------------
Dapps-lib/src/lib/features/farm/farms-add-casli-map.svelte | 94-------------------------------------------------------------------------------
Dapps-lib/src/lib/features/farm/farms-display-li-el.svelte | 107-------------------------------------------------------------------------------
Dapps-lib/src/lib/features/farm/farms-products-review-card.svelte | 132-------------------------------------------------------------------------------
Mapps-lib/src/lib/index.ts | 133+++----------------------------------------------------------------------------
Dapps-lib/src/lib/store/app.ts | 26--------------------------
Dapps-lib/src/lib/store/client.ts | 44--------------------------------------------
Dapps-lib/src/lib/store/component.ts | 5-----
Dapps-lib/src/lib/store/layout.ts | 3---
Dapps-lib/src/lib/store/ndk.ts | 24------------------------
Dapps-lib/src/lib/store/nostr.ts | 16----------------
Aapps-lib/src/lib/stores/ndk.ts | 21+++++++++++++++++++++
Aapps-lib/src/lib/stores/theme.ts | 14++++++++++++++
Dapps-lib/src/lib/types/component.ts | 252-------------------------------------------------------------------------------
Dapps-lib/src/lib/types/context.ts | 23-----------------------
Dapps-lib/src/lib/types/interface.ts | 228-------------------------------------------------------------------------------
Mapps-lib/src/lib/types/lib.ts | 29++---------------------------
Aapps-lib/src/lib/types/ndk.ts | 4++++
Dapps-lib/src/lib/types/view/farm.ts | 34----------------------------------
Dapps-lib/src/lib/types/view/lib.ts | 11-----------
Dapps-lib/src/lib/types/view/profile.ts | 14--------------
Dapps-lib/src/lib/util/carousel.ts | 87-------------------------------------------------------------------------------
Dapps-lib/src/lib/util/casl.ts | 20--------------------
Dapps-lib/src/lib/util/context/lib.ts | 11-----------
Dapps-lib/src/lib/util/idb.ts | 55-------------------------------------------------------
Dapps-lib/src/lib/util/lib.ts | 107-------------------------------------------------------------------------------
Dapps-lib/src/lib/util/nostr/nostr-poll-relays.ts | 72------------------------------------------------------------------------
Dapps-lib/src/lib/util/nostr/nostr-sync.ts | 64----------------------------------------------------------------
Dapps-lib/src/lib/util/service/nostr-event-classified.ts | 274-------------------------------------------------------------------------------
Dapps-lib/src/lib/util/service/nostr-sync.ts | 43-------------------------------------------
Dapps-lib/src/lib/util/styles.ts | 46----------------------------------------------
Dapps-lib/src/lib/util/validation/farm.ts | 29-----------------------------
Dapps-lib/src/lib/util/view.ts | 13-------------
Aapps-lib/src/lib/utils/idb/lib.ts | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/utils/lib.ts | 42++++++++++++++++++++++++++++++++++++++++++
Dapps-lib/src/lib/view/farms-add.svelte | 223-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/farms-details.svelte | 268-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/farms-products-add.svelte | 669-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/farms.svelte | 90-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/home.svelte | 59-----------------------------------------------------------
Dapps-lib/src/lib/view/notifications.svelte | 34----------------------------------
Dapps-lib/src/lib/view/profile-edit.svelte | 105-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/profile.svelte | 306-------------------------------------------------------------------------------
Dapps-lib/src/lib/view/settings.svelte | 108-------------------------------------------------------------------------------
137 files changed, 215 insertions(+), 8576 deletions(-)

diff --git a/apps-lib/.gitignore b/apps-lib/.gitignore @@ -1,40 +1,37 @@ -# dependencies node_modules -.pnp -.pnp.js - -# testing -coverage - -# svelte -.svelte-kit - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# turbo -.turbo - # Output .output +.vercel +.netlify +.wrangler +/.svelte-kit /build dist +.turbo -# local env files -.env* -!.env.example +# OS +.DS_Store +Thumbs.db +# Env +.env +.env.* +!.env.example +!.env.test # Vite vite.config.js.timestamp-* vite.config.ts.timestamp-* +vite.config.dev* + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# secrets +*.pem # local .tmp* @@ -43,5 +40,6 @@ vite.config.ts.timestamp-* .vscode notes*.txt notes*.md -git-diff.txt +notes*.json +git-diff*.txt justfile diff --git a/apps-lib/package.json b/apps-lib/package.json @@ -1,13 +1,14 @@ { - "name": "@radroots/lib-app", + "name": "@radroots/apps-lib", "version": "0.0.0", "private": true, "license": "GPLv3", "scripts": { "dev": "svelte-package -w", - "prebuild": "npm run check", + "prebuild": "npm run clean && npm run check", "build": "svelte-package", "preview": "vite preview", + "clean": "rimraf dist && rimraf tsconfig.tsbuildinfo", "prepare": "svelte-kit sync || echo ''", "prepack": "svelte-kit sync && svelte-package && publint", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", @@ -31,33 +32,35 @@ } }, "peerDependencies": { - "@sveltejs/kit": "^2.16.0", + "@sveltejs/kit": "^2.22.0", "svelte": "^5.0.0" }, "devDependencies": { "@sveltejs/adapter-auto": "^4.0.0", - "@sveltejs/kit": "^2.16.0", + "@sveltejs/kit": "^2.22.0", "@sveltejs/package": "^2.0.0", - "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@sveltejs/vite-plugin-svelte": "^6.0.0", "@types/node": "^22.5.0", "publint": "^0.3.2", "svelte": "^5.0.0", "svelte-check": "^4.0.0", "typescript": "5.8.3", - "vite": "^6.0.0" + "vite": "7.0.6" }, "dependencies": { - "@nostr-dev-kit/ndk": "^2.11.0", - "@nostr-dev-kit/ndk-cache-dexie": "^2.5.9", - "@nostr-dev-kit/ndk-svelte": "^2.4.0", "@radroots/locales": "*", + "@radroots/utils": "*", "@radroots/utils-nostr": "*", "@radroots/radroots-common-bindings": "*", - "@radroots/theme": "*", - "@radroots/util": "*", + "@nostr-dev-kit/ndk": "2.14.33", + "@nostr-dev-kit/ndk-cache-dexie": "2.6.34", + "@nostr-dev-kit/ndk-svelte": "2.4.38", + "@sveltekit-i18n/base": "^1.3.7", + "@sveltekit-i18n/parser-icu": "^1.0.8", "luxon": "^3.5.0", - "svelte-maplibre": "1.0.0-next.12", + "sveltekit-i18n": "^2.4.2", + "svelte-maplibre": "1.2.0", "sveltekit-search-params": "^3.0.0", - "zod": "^3.23.8" + "zod": "^4.0.5" } } \ No newline at end of file diff --git a/apps-lib/src/lib/components/button/button-horizontal-pair-slide.svelte b/apps-lib/src/lib/components/button/button-horizontal-pair-slide.svelte @@ -1,45 +0,0 @@ -<script lang="ts"> - import { Empty } from "$root"; - - let { - basis, - toggle = $bindable(false), - }: { - basis: { - label_l: string; - label_r: string; - }; - toggle: boolean; - } = $props(); -</script> - -<button - class={`group relative flex flex-row h-[38px] w-full justify-between items-center rounded-touch bg-layer-2-surface`} - onclick={async () => { - toggle = !toggle; - }} -> - <div - class={`z-10 flex flex-row h-full basis-1/2 justify-center items-center bg-transparent`} - > - <p - class={`font-sans font-[400] text-[16px] tracking-wide ${!toggle ? `text-white/60` : `text-layer-0-glyph`} el-re`} - > - {basis.label_l} - </p> - </div> - <div - class={`z-10 flex flex-row h-full basis-1/2 justify-center items-center bg-transparent`} - > - <p - class={`font-sans font-[400] text-[16px] tracking-wide ${toggle ? `text-white/60` : `text-layer-0-glyph`} el-re`} - > - {basis.label_r} - </p> - </div> - <div - class={`z-5 absolute top-0 bottom-0 flex flex-row h-full w-[50%] justify-center items-center rounded-touch bg-th-black transition-all duration-[400ms] ${toggle ? `translate-x-full` : `translate-x-0`}`} - > - <Empty /> - </div> -</button> diff --git a/apps-lib/src/lib/components/button/button-label-dashed.svelte b/apps-lib/src/lib/components/button/button-label-dashed.svelte @@ -1,24 +0,0 @@ -<script lang="ts"> - import { type ICb } from "$root"; - - let { - basis, - }: { - basis: ICb & { - label: string; - }; - } = $props(); -</script> - -<button - class={`flex flex-row h-line_button w-full justify-center items-center`} - onclick={async () => { - await basis.callback(); - }} -> - <p - class={`font-sans font-[500] text-lg text-layer-0-glyph-hl tracking-wide`} - > - {`- ${basis.label} -`} - </p> -</button> diff --git a/apps-lib/src/lib/components/button/button-label-glyph.svelte b/apps-lib/src/lib/components/button/button-label-glyph.svelte @@ -1,42 +0,0 @@ -<script lang="ts"> - import { Glyph, type ICb } from "$root"; - import { type GlyphKey } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis: ICb & { - label: string; - glyph?: GlyphKey; - ring?: boolean; - }; - children?: Snippet; - } = $props(); -</script> - -<div class={`flex flex-col w-full gap-1 justify-center items-center`}> - <button - class={`flex flex-row h-12 w-12 p-2 justify-center items-center rounded-2xl bg-layer-1-surface ${basis.ring ? `ring-[4px] ring-layer-2-surface/40` : ``} el-re`} - onclick={async () => { - await basis.callback(); - }} - > - {#if basis.glyph} - <Glyph - basis={{ - classes: `text-layer-0-glyph/80`, - dim: `sm`, - - key: basis.glyph, - }} - /> - {:else if children} - {@render children()} - {/if} - </button> - <p class={`font-sans font-[400] text-sm text-layer-0-glyph el-re`}> - {basis.label} - </p> -</div> diff --git a/apps-lib/src/lib/components/button/button-layout-pair.svelte b/apps-lib/src/lib/components/button/button-layout-pair.svelte @@ -1,65 +0,0 @@ -<script lang="ts"> - import { - app_lo, - ButtonLayout, - Empty, - type IClOpt, - type IDisabledOpt, - type ILoadingOpt, - } from "$root"; - import { fmt_cl, type CallbackPromise } from "@radroots/util"; - - let { - basis, - }: { - basis: IClOpt & { - continue: IDisabledOpt & - ILoadingOpt & { - label: string; - callback: CallbackPromise; - }; - back?: IDisabledOpt & { - visible: boolean; - label?: string; - callback: CallbackPromise; - }; - }; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis.classes)} flex flex-col gap-1 justify-center items-center ${basis?.back?.visible ? `-translate-y-8` : ``} el-re`} -> - <ButtonLayout - basis={{ - disabled: basis.continue.disabled, - label: basis.continue.label, - callback: basis.continue.callback, - }} - /> - {#if basis.back} - <div class={`flex flex-col justify-center items-center el-re`}> - {#if basis.back.visible} - <button - class={`group flex flex-row h-12 w-lo_${$app_lo} justify-center items-center fade-in el-re`} - onclick={async (ev) => { - ev.stopPropagation(); - if (!basis.back?.disabled) await basis.back?.callback(); - }} - > - <p - class={`font-sans font-[600] tracking-wide text-layer-1-glyph-shade ${basis.back?.disabled ? `` : `group-active:text-layer-1-glyph/40`} el-re`} - > - {basis.back.label || ``} - </p> - </button> - {:else} - <div - class={`flex flex-row h-4 w-full justify-start items-center`} - > - <Empty /> - </div> - {/if} - </div> - {/if} -</div> diff --git a/apps-lib/src/lib/components/button/button-layout.svelte b/apps-lib/src/lib/components/button/button-layout.svelte @@ -1,51 +0,0 @@ -<script lang="ts"> - import { - app_lo, - LoadSymbol, - type IClOpt, - type IDisabledOpt, - type ILoadingOpt, - type ILyOpt, - } from "$root"; - import { fmt_cl, parse_layer, type CallbackPromise } from "@radroots/util"; - - let { - basis, - }: { - basis: ILyOpt & - IClOpt & - IDisabledOpt & - ILoadingOpt & { - classes_inner?: string; - hide_active?: boolean; - label: string; - callback: CallbackPromise; - }; - } = $props(); - - const layer = $derived(parse_layer(basis.layer, 1)); - - const classes_active = $derived( - !basis.hide_active - ? `layer-1-active-surface layer-1-active-raise-less layer-1-active-ring-less` - : ``, - ); -</script> - -<button - class={`${fmt_cl(basis.classes)} group flex flex-row h-touch_guide w-lo_${$app_lo} justify-center items-center bg-layer-${layer}-surface rounded-touch ${basis.disabled ? `opacity-60` : classes_active} el-re`} - onclick={async (ev) => { - ev.stopPropagation(); - if (!basis.disabled) await basis.callback(); - }} -> - {#if basis.loading} - <LoadSymbol basis={{ dim: `md` }} /> - {:else} - <p - class={`${fmt_cl(basis.classes_inner)} font-sans font-[600] tracking-wide text-layer-${layer}-glyph-shade ${basis.disabled ? `` : `group-active:text-layer-${layer}-glyph/40 `} el-re`} - > - {basis.label || ``} - </p> - {/if} -</button> diff --git a/apps-lib/src/lib/components/button/button-round-nav.svelte b/apps-lib/src/lib/components/button/button-round-nav.svelte @@ -1,24 +0,0 @@ -<script lang="ts"> - import { Glyph, LoadSymbol, type IButtonNavRound } from "$root"; - - let { basis }: { basis: IButtonNavRound } = $props(); -</script> - -<button - class={`flex flex-row h-12 w-12 justify-center items-center bg-layer-1-surface rounded-full el-re`} - disabled={!!basis.disabled} - onclick={basis.callback} -> - {#if basis.loading} - <LoadSymbol /> - {:else} - <Glyph - basis={{ - classes: `text-layer-0-glyph`, - dim: `sm+`, - - key: basis.glyph, - }} - /> - {/if} -</button> diff --git a/apps-lib/src/lib/components/button/button-round.svelte b/apps-lib/src/lib/components/button/button-round.svelte @@ -1,25 +0,0 @@ -<script lang="ts"> - import { LoadSymbol, type IButtonRound } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { - basis, - }: { - basis: IButtonRound; - } = $props(); -</script> - -<button - class={`${fmt_cl(basis.classes)} group flex flex-row h-touch_guide w-full justify-center items-center rounded-full el-re`} - onclick={async () => { - await basis.callback(); - }} -> - {#if basis.loading} - <LoadSymbol basis={{ dim: `md` }} /> - {:else} - <p class={`font-sans font-[500] text-[16px]`}> - {basis.label} - </p> - {/if} -</button> diff --git a/apps-lib/src/lib/components/button/button-simple-glyph.svelte b/apps-lib/src/lib/components/button/button-simple-glyph.svelte @@ -1,30 +0,0 @@ -<script lang="ts"> - import { type ILyOpt } from "$root"; - import { parse_layer, type CallbackPromise } from "@radroots/util"; - - let { - basis, - }: { - basis: ILyOpt & { - label: string; - callback: CallbackPromise; - allow_propogation?: boolean; - }; - } = $props(); - - const layer = $derived(parse_layer(basis?.layer ? basis.layer : 1)); -</script> - -<button - class={`group flex flex-row h-[3.5rem] w-full justify-center items-center rounded-touch`} - onclick={async (ev) => { - if (!basis.allow_propogation) ev.stopPropagation(); - await basis.callback(); - }} -> - <p - class={`font-sans font-[700] text-xl text-layer-${layer}-glyph capitalize tracking-wider opacity-active`} - > - {basis.label} - </p> -</button> diff --git a/apps-lib/src/lib/components/button/button-simple.svelte b/apps-lib/src/lib/components/button/button-simple.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { type IButtonSimple } from "$root"; - import { parse_layer } from "@radroots/util"; - - let { basis }: { basis: IButtonSimple } = $props(); - - const layer = $derived(parse_layer(basis.layer || 1)); -</script> - -<button - class={`group flex flex-row h-line_button w-full justify-center items-center rounded-touch bg-layer-${layer}-surface layer-${layer}-active-surface layer-${layer}-active-ring`} - onclick={async (ev) => { - if (!basis.allow_propogation) ev.stopPropagation(); - await basis.callback(); - }} -> - <p - class={`font-sans font-[600] text-xl text-layer-0-glyph capitalize tracking-wider opacity-active`} - > - {basis.label} - </p> -</button> diff --git a/apps-lib/src/lib/components/button/glyph-button-simple.svelte b/apps-lib/src/lib/components/button/glyph-button-simple.svelte @@ -1,46 +0,0 @@ -<script lang="ts"> - import { Glyph, type IClOpt } from "$root"; - import { - fmt_cl, - type CallbackPromise, - type GlyphKey, - } from "@radroots/util"; - - let { - basis, - }: { - basis: IClOpt & { - kind?: `primary` | `neutral`; - label: string; - callback: CallbackPromise; - glyph?: GlyphKey; - }; - } = $props(); - - const classes_kind = $derived( - basis.kind === `neutral` - ? `text-layer-0-glyph-shade` - : `text-layer-0-glyph-hl`, - ); -</script> - -<button - class={`${fmt_cl(basis.classes)} group flex flex-row justify-center items-center`} - onclick={basis.callback} -> - {#if basis.glyph} - <Glyph - basis={{ - classes: `${classes_kind}`, - dim: `sm+`, - - key: basis.glyph, - }} - /> - {/if} - <p - class={`font-sans font-[600] text-line_label ${classes_kind} opacity-active`} - > - {basis.label} - </p> -</button> diff --git a/apps-lib/src/lib/components/button/glyph-button.svelte b/apps-lib/src/lib/components/button/glyph-button.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { glyph_style_map, type IGlyph } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IGlyph } = $props(); - const styles = $derived( - basis?.dim ? glyph_style_map.get(basis.dim) : glyph_style_map.get(`sm`), - ); -</script> - -<!-- svelte-ignore a11y_consider_explicit_label --> -<button - class={`${fmt_cl(basis.classes)} flex flex-col justify-center items-center text-[${styles?.gl_1}px] el-re`} - onclick={async () => { - if (basis.callback) await basis.callback(); - }} -> - <i class={`ph-bold ph-${basis.key}`}></i> -</button> diff --git a/apps-lib/src/lib/components/carousel/carousel-flow-item.svelte b/apps-lib/src/lib/components/carousel/carousel-flow-item.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis?: IClOpt; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col flex-shrink-0 h-full w-full justify-start items-start`} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/carousel/carousel-flow.svelte b/apps-lib/src/lib/components/carousel/carousel-flow.svelte @@ -1,53 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { handle_err, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import { onDestroy, onMount, type Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis: IClOpt & { - index: number; - slide_duration?: number; - }; - children: Snippet; - } = $props(); - - let el_parent: HTMLDivElement | null = $state(null); - let duration: number = $state(basis.slide_duration ?? 500); - let offset_w: number = $state(0); - - onMount(async () => { - try { - handle_resize(); - if (browser) window.addEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (browser) window.removeEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const handle_resize = (): void => { - if (el_parent && el_parent.children.length > 0) - offset_w = (el_parent.children[0] as HTMLElement).offsetWidth; - }; -</script> - -<div class={`${fmt_cl(basis?.classes)}relative flex flex-col w-full`}> - <div - bind:this={el_parent} - class={`flex flex-grow transition-transform`} - style={`transform: translateX(-${Math.max(basis?.index, 0) * offset_w}px); transition: transform ${duration}ms ease-out;`} - > - {@render children()} - </div> -</div> diff --git a/apps-lib/src/lib/components/carousel/carousel-item.svelte b/apps-lib/src/lib/components/carousel/carousel-item.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col flex-shrink-0 w-[100vw] justify-start items-center`} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/carousel/carousel.svelte b/apps-lib/src/lib/components/carousel/carousel.svelte @@ -1,24 +0,0 @@ -<script lang="ts"> - import { casl_i, type IBasisOpt, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} relative flex flex-col w-full overflow-hidden`} -> - <div - class={`flex h-full transition-transform duration-500`} - style={`transform: translateX(-${Math.max($casl_i, 0) * 100}vw)`} - > - {@render children()} - </div> -</div> diff --git a/apps-lib/src/lib/components/envelope/envelope-lower-full.svelte b/apps-lib/src/lib/components/envelope/envelope-lower-full.svelte @@ -1,29 +0,0 @@ -<script lang="ts"> - import type { Snippet } from "svelte"; - import { quintInOut } from "svelte/easing"; - import { fly } from "svelte/transition"; - - let { - basis, - children, - }: { - basis: { - visible: boolean; - }; - children: Snippet; - } = $props(); -</script> - -{#if basis.visible} - <div - in:fly={{ y: `100%`, easing: quintInOut }} - out:fly={{ y: `100%`, easing: quintInOut }} - class={`z-50 absolute bottom-0 left-0 flex flex-col h-[100vh] w-full justify-start items-start bg-transparent el-re`} - > - <div - class={`z-[100] [flex flex-col h-full w-full justify-start items-center overflow-y-scroll overflow-x-hidden scroll-hide el-re`} - > - {@render children()} - </div> - </div> -{/if} diff --git a/apps-lib/src/lib/components/envelope/map-location-select-envelope.svelte b/apps-lib/src/lib/components/envelope/map-location-select-envelope.svelte @@ -1,97 +0,0 @@ -<script lang="ts"> - import { - ButtonLayoutPair, - EnvelopeLowerFull, - Map, - MapMarkerArea, - } from "$root"; - import { - cfg_map, - parse_geol_point_tup, - type CallbackPromiseGeneric, - type GeocoderReverseResult, - type GeolocationPoint, - } from "@radroots/util"; - import LayoutBottomButton from "../layout/layout-bottom-button.svelte"; - - let { - basis, - map_geop = $bindable(undefined), - map_geoc = $bindable(undefined), - }: { - basis: { - visible: boolean; - on_submit: CallbackPromiseGeneric< - | { - map_geop: GeolocationPoint | undefined; - map_geoc: GeocoderReverseResult | undefined; - } - | undefined - >; - }; - map_geop?: GeolocationPoint; - map_geoc?: GeocoderReverseResult; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - let map_init = $state(false); - - $effect(() => { - if (basis.visible && map && map_geop && !map_init) { - map.setCenter(parse_geol_point_tup(map_geop)); - map_init = true; - } - }); - - $effect(() => { - if (basis.visible === false) map_init = false; //@todo - }); -</script> - -<EnvelopeLowerFull - basis={{ - visible: basis.visible, - }} -> - <div - class={`relative flex flex-col h-full w-full justify-center items-center bg-layer-1-surface`} - > - <Map - bind:map - basis={{ - zoom_click_off: true, - }} - > - {#if map_geop} - <MapMarkerArea - bind:map_geop - bind:map_geoc - basis={{ - show_display: !!map_geop, - }} - /> - {/if} - </Map> - <LayoutBottomButton> - <ButtonLayoutPair - basis={{ - continue: { - label: `Choose location`, - disabled: false, - callback: async () => { - await basis.on_submit({ map_geoc, map_geop }); - if (map) map.setCenter(cfg_map.coords.default); - }, - }, - back: { - label: `Back`, - visible: true, - callback: async () => { - await basis.on_submit(undefined); - }, - }, - }} - /> - </LayoutBottomButton> - </div> -</EnvelopeLowerFull> diff --git a/apps-lib/src/lib/components/float/float-page.svelte b/apps-lib/src/lib/components/float/float-page.svelte @@ -1,12 +0,0 @@ -<script lang="ts"> - import type { IFloatPage } from "$lib/types/component"; - import type { Snippet } from "svelte"; - - let { basis, children }: { basis: IFloatPage; children: Snippet } = - $props(); -</script> - -<div class={`absolute top-10 ${basis.posx}-6 flex flex-row`}> - {@render children()} -</div> -<div class="hidden left-6 right-6"></div> diff --git a/apps-lib/src/lib/components/form/entry-line-idb.svelte b/apps-lib/src/lib/components/form/entry-line-idb.svelte @@ -1,68 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - Glyph, - Input, - LoadSymbol, - type IEntryLineIdb, - } from "$root"; - import { fmt_cl, parse_layer, type LoadingDimension } from "@radroots/util"; - - let { - basis, - }: { - basis: IEntryLineIdb; - } = $props(); - - const layer = $derived( - parse_layer( - typeof basis.wrap?.layer === `boolean` ? 0 : basis.wrap?.layer, - ), - ); - - const classes_layer = $derived( - typeof basis.wrap?.layer === `boolean` - ? `` - : `text-layer-${layer}-glyph`, - ); - - const loading_dim: LoadingDimension = $derived( - basis.wrap?.style === `guide` ? `md` : `sm`, - ); -</script> - -<EntryWrap basis={basis?.wrap}> - <Input - basis={{ - ...basis.el, - classes: `h-entry_line ${fmt_cl(basis.el.classes)}`, - }} - /> - {#if basis.loading} - <div - class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-4 justify-end items-center fade-in el-re`} - > - <LoadSymbol - basis={{ - dim: loading_dim, - }} - /> - </div> - {:else if basis.notify_inline} - {#if `glyph` in basis.notify_inline} - <div - class={`z-5 absolute el-re right-0 top-0 flex flex-row h-full pr-3 justify-end items-center translate-x-[34px] fade-in`} - > - <Glyph - basis={typeof basis.notify_inline.glyph === `string` - ? { - key: basis.notify_inline.glyph, - dim: `xs+`, - classes: `${classes_layer}`, - } - : basis.notify_inline.glyph} - /> - </div> - {/if} - {/if} -</EntryWrap> diff --git a/apps-lib/src/lib/components/form/entry-line.svelte b/apps-lib/src/lib/components/form/entry-line.svelte @@ -1,71 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - Glyph, - InputValue, - LoadSymbol, - type IEntryLine, - } from "$root"; - import { parse_layer, type LoadingDimension } from "@radroots/util"; - - let { - basis, - value = $bindable(``), - }: { - basis: IEntryLine; - value: string; - } = $props(); - - const layer = $derived( - parse_layer( - typeof basis.wrap?.layer === `boolean` ? 0 : basis.wrap?.layer, - ), - ); - - const classes_layer = $derived( - typeof basis.wrap?.layer === `boolean` - ? `` - : `text-layer-${layer}-glyph`, - ); - - const loading_dim: LoadingDimension = $derived( - basis.wrap?.style === `guide` ? `md` : `sm`, - ); -</script> - -<EntryWrap basis={basis?.wrap}> - <InputValue - bind:value - basis={{ - ...basis.el, - classes: `h-entry_line ${basis.el.classes}`, - }} - /> - {#if basis.loading} - <div - class={`z-5 absolute right-0 top-0 flex flex-row h-full pr-4 justify-end items-center fade-in el-re`} - > - <LoadSymbol - basis={{ - dim: loading_dim, - }} - /> - </div> - {:else if basis.notify_inline} - {#if `glyph` in basis.notify_inline} - <div - class={`z-5 absolute el-re right-0 top-0 flex flex-row h-full pr-3 justify-end items-center translate-x-[34px] fade-in`} - > - <Glyph - basis={typeof basis.notify_inline.glyph === `string` - ? { - key: basis.notify_inline.glyph, - dim: `xs+`, - classes: `${classes_layer}`, - } - : basis.notify_inline.glyph} - /> - </div> - {/if} - {/if} -</EntryWrap> diff --git a/apps-lib/src/lib/components/form/entry-multiline.svelte b/apps-lib/src/lib/components/form/entry-multiline.svelte @@ -1,49 +0,0 @@ -<script lang="ts"> - import { Glyph, TextArea, type IEntryMultiLine } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - - let { - basis, - value = $bindable(``), - }: { - basis: IEntryMultiLine; - value: string; - } = $props(); - - const layer = $derived( - parse_layer( - typeof basis.wrap?.layer === `boolean` ? 0 : basis.wrap?.layer, - ), - ); - - const classes_layer = $derived( - typeof layer === `boolean` - ? `bg-transparent` - : `bg-layer-${layer}-surface`, - ); -</script> - -<div - id={basis.wrap?.id || null} - class={`${fmt_cl(basis.wrap?.classes)} relative el-re entry-textarea-wrap ${classes_layer}`} -> - <TextArea bind:value 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 `} - > - <Glyph - basis={typeof basis.notify_inline.glyph === `string` - ? { - key: basis.notify_inline.glyph, - dim: `xs+`, - - classes: `text-layer-${layer}-glyph`, - } - : basis.notify_inline.glyph} - /> - </div> - {/if} - {/if} -</div> diff --git a/apps-lib/src/lib/components/form/entry-select.svelte b/apps-lib/src/lib/components/form/entry-select.svelte @@ -1,54 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - Glyph, - LoadSymbol, - Select, - type IEntrySelect, - } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - - let { - basis, - value = $bindable(``), - }: { - basis: IEntrySelect; - value: string; - } = $props(); - - const layer = $derived( - typeof basis?.wrap.layer === `boolean` - ? parse_layer(0) - : parse_layer(basis?.wrap.layer, 1), - ); -</script> - -<EntryWrap basis={basis?.wrap}> - {#if basis?.loading} - <div class={`flex flex-row w-full justify-center items-center`}> - <LoadSymbol basis={{ dim: `sm`, blades: 8 }} /> - </div> - {:else} - <Select - bind:value - basis={{ - ...basis.el, - classes: `${fmt_cl(basis.el.classes)} w-full`, - }} - /> - {/if} - {#if !basis?.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`, - - classes: `text-layer-${layer}-glyph_d`, - }} - /> - </div> - {/if} -</EntryWrap> diff --git a/apps-lib/src/lib/components/form/entry-wrap.svelte b/apps-lib/src/lib/components/form/entry-wrap.svelte @@ -1,32 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IEntryWrap } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IEntryWrap>; - children: Snippet; - } = $props(); - - const layer = $derived( - typeof basis?.layer === `boolean` - ? parse_layer(0) - : parse_layer(basis?.layer), - ); - - const classes_layer = $derived( - typeof basis?.layer === `boolean` - ? `bg-transparent` - : `bg-layer-${layer}-surface ${basis?.style_a ? `active:bg-layer-${layer}-surface_a` : ``}`, - ); -</script> - -<button - id={basis?.id || null} - class={`${fmt_cl(basis?.classes)} relative entry-line-wrap ${!basis?.no_pad ? ` pl-6 pr-4` : ``} h-entry_${basis?.style ? basis.style : `line`} rounded-touch ${classes_layer} el-re`} -> - {@render children()} -</button> diff --git a/apps-lib/src/lib/components/form/form-entry-input.svelte b/apps-lib/src/lib/components/form/form-entry-input.svelte @@ -1,44 +0,0 @@ -<script lang="ts"> - import { EntryLine, fmt_id, LayoutTrellisLine, type IIdOpt } from "$root"; - import { type FormField } from "@radroots/util"; - - let { - basis, - val = $bindable(``), - }: { - basis: IIdOpt & { - entry_label: string; - input_placeholder?: string; - input_field?: FormField; - }; - val: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: basis.entry_label || ``, - }, - }} -> - <EntryLine - bind:value={val} - basis={{ - wrap: { - id: id ? fmt_id(`${id}_wrap`) : undefined, - layer: 1, - }, - el: { - id: id ? fmt_id(id) : undefined, - layer: 1, - classes: `fade-in`, - placeholder: basis.input_placeholder || ``, - field: basis.input_field || undefined, - field_constrain: !!basis.input_field, - }, - }} - /> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-price-quantity.svelte b/apps-lib/src/lib/components/form/form-entry-price-quantity.svelte @@ -1,117 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - fmt_id, - get_context, - Input, - LayoutTrellisLine, - lib_fmt_price, - lib_parse_currency_marker, - Select, - } from "$root"; - import { - fiat_currencies, - mass_units, - num_str, - type ElementCallbackValue, - type FormField, - } from "@radroots/util"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - val_input_price = $bindable(``), - val_sel_currency = $bindable(``), - val_sel_qty_unit = $bindable(``), - }: { - basis: { - id?: string; - input_field?: FormField; - callback_input: ElementCallbackValue; - }; - val_input_price: string; - val_sel_currency: string; - val_sel_qty_unit: string; - } = $props(); - - const id = $derived(basis.id ? basis.id : ``); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: `${$ls(`icu.*_price`, { value: `${$ls(`common.product`)}` })} (${val_sel_currency}/${`${$ls(`units.mass.unit.${val_sel_qty_unit}_ab`)}`})`, - }, - }} -> - <EntryWrap - basis={{ - id: id ? fmt_id(`${id}_wrap`) : undefined, - layer: 1, - }} - > - <div class={`flex flex-row justify-start pr-1 items-center`}> - <Select - bind:value={val_sel_currency} - basis={{ - id: id ? fmt_id(`${id}_sel_currency`) : undefined, - layer: 1, - sync: true, - classes: `w-fit font-sans font-[400] ${val_input_price ? `text-layer-1-glyph_d` : `text-layer-1-glyph_pl`} el-re`, - options: [ - { - entries: fiat_currencies.map((i) => ({ - value: `${i}`, - label: lib_parse_currency_marker($locale, i), - })), - }, - ], - }} - /> - </div> - <Input - bind:value={val_input_price} - basis={{ - id: id ? fmt_id(`${id}_input_price`) : undefined, - layer: 1, - sync: true, - placeholder: `${$ls(`icu.enter_the_*`, { value: `${$ls(`common.price`)}`.toLowerCase() })}`, - field: basis.input_field, - callback: basis.callback_input, - callback_blur: async ({ el }) => { - if (!el.value) return; - el.value = lib_fmt_price( - $locale, - el.value, - val_sel_currency, - ).slice(1); - //@todo fmt handles 'en' only - }, - }} - /> - <div class={`flex flex-row gap-2 justify-end items-center`}> - <p class={`font-sans font-[400] text-layer-1-glyph_d lowercase`}> - {num_str(1)} - </p> - <Select - bind:value={val_sel_qty_unit} - basis={{ - id: id ? fmt_id(`${id}_sel_qty_unit`) : undefined, - sync: true, - layer: 1, - classes: `w-fit font-sans font-[400]`, - show_arrows: `r`, - options: [ - { - entries: mass_units.map((i) => ({ - value: i, - label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), - })), - }, - ], - }} - /> - </div> - </EntryWrap> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-price.svelte b/apps-lib/src/lib/components/form/form-entry-price.svelte @@ -1,122 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - fmt_id, - get_context, - Input, - LayoutTrellisLine, - lib_fmt_price, - lib_parse_currency_marker, - Select, - type IIdOpt, - } from "$root"; - import { - fiat_currencies, - form_fields, - mass_units, - type ElementCallbackValue, - } from "@radroots/util"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - val_input_price = $bindable(``), - val_sel_currency = $bindable(``), - val_sel_quantity_unit = $bindable(``), - }: { - basis: IIdOpt & { - display_symbol?: boolean; - entry_label?: string; - input_placeholder?: string; - callback_input?: ElementCallbackValue; - }; - val_input_price: string; - val_sel_currency: string; - val_sel_quantity_unit: string; - } = $props(); - - const id = $derived(basis.id ? basis.id : ``); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: basis.entry_label || ``, - }, - }} -> - <EntryWrap - basis={{ - id: id ? fmt_id(`${id}_wrap`) : undefined, - layer: 1, - }} - > - <Input - bind:value={val_input_price} - basis={{ - id: id ? fmt_id(`${id}_input_price`) : undefined, - layer: 1, - sync: true, - placeholder: basis.input_placeholder, - field: form_fields.price, - callback: basis.callback_input, - callback_blur: async ({ el }) => { - if (!el.value) return; - el.value = lib_fmt_price( - $locale, - el.value, - val_sel_currency, - ).slice(1); - //@todo fmt handles 'en' only - }, - }} - /> - <div - class={`absolute right-4 flex flex-row justify-start items-center`} - > - <Select - bind:value={val_sel_currency} - basis={{ - id: id ? fmt_id(`${id}_sel_currency`) : undefined, - layer: 1, - sync: true, - classes: `w-fitfont-sans font-[400] el-re`, - options: [ - { - entries: fiat_currencies.map((i) => ({ - value: i, - label: basis.display_symbol - ? lib_parse_currency_marker($locale, i) - : i.toUpperCase(), - })), - }, - ], - }} - /> - <div class={`flex flex-row px-2 justify-start items-center`}> - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {`/`} - </p> - </div> - <Select - bind:value={val_sel_quantity_unit} - basis={{ - id: id ? fmt_id(`${id}_sel_qty_unit`) : undefined, - sync: true, - layer: 1, - classes: `w-fit font-sans font-[400]`, - show_arrows: `r`, - options: [ - { - entries: mass_units.map((i) => ({ - value: i, - label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), - })), - }, - ], - }} - /> - </div> - </EntryWrap> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-quantity.svelte b/apps-lib/src/lib/components/form/form-entry-quantity.svelte @@ -1,105 +0,0 @@ -<script lang="ts"> - import { - EntryWrap, - fmt_id, - get_context, - Input, - LayoutTrellisLine, - Select, - type IIdOpt, - } from "$root"; - import { - form_fields, - mass_units, - type ElementCallbackValue, - } from "@radroots/util"; - - const { ls } = get_context(`lib`); - - let { - basis, - val_input_quantity = $bindable(``), - val_sel_quantity_unit = $bindable(``), - val_sel_quantity_label = $bindable(``), - }: { - basis: IIdOpt & { - display_symbol?: boolean; - entry_label?: string; - input_placeholder?: string; - callback_input?: ElementCallbackValue; - }; - val_input_quantity: string; - val_sel_quantity_unit: string; - val_sel_quantity_label: string; - } = $props(); - - const id = $derived(basis.id ? basis.id : ``); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: basis.entry_label || ``, - }, - }} -> - <EntryWrap - basis={{ - id: id ? fmt_id(`${id}_wrap`) : undefined, - layer: 1, - }} - > - <Input - bind:value={val_input_quantity} - basis={{ - id: id ? fmt_id(`${id}_input_quantity`) : undefined, - layer: 1, - sync: true, - placeholder: basis.input_placeholder, - field: form_fields.quantity, - callback: basis.callback_input, - }} - /> - <div - class={`absolute right-4 flex flex-row gap-1 justify-start items-center`} - > - <Select - bind:value={val_sel_quantity_unit} - basis={{ - id: id ? fmt_id(`${id}_sel_quantity_unit`) : undefined, - layer: 1, - sync: true, - classes: `w-fit font-sans font-[400] el-re`, - options: [ - { - entries: mass_units.map((i) => ({ - value: i, - label: `${$ls(`units.mass.unit.${i}_ab`)}`.toLowerCase(), - })), - }, - ], - }} - /> - <Select - bind:value={val_sel_quantity_label} - basis={{ - id: id ? fmt_id(`${id}_sel_quantity_label`) : undefined, - sync: true, - layer: 1, - classes: `w-fit font-sans font-[400] pr-2`, - show_arrows: `r`, - options: [ - { - entries: [ - { - value: `bag`, - label: `${$ls(`common.bag`)}`.toLowerCase(), - }, - ], - }, - ], - }} - /> - </div> - </EntryWrap> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-select-input.svelte b/apps-lib/src/lib/components/form/form-entry-select-input.svelte @@ -1,94 +0,0 @@ -<script lang="ts"> - import { - EntryLine, - EntrySelect, - fmt_id, - get_context, - LayoutTrellisLine, - type ISelectCallback, - type ISelectOption, - } from "$root"; - import { - type CallbackPromiseGeneric, - type FormField, - } from "@radroots/util"; - - const { ls } = get_context(`lib`); - - let { - basis, - val_sel = $bindable(``), - val_sel_input = $bindable(``), - }: { - basis: { - id: string; - visible_input: boolean; - callback_select: ISelectCallback; - callback_visible: CallbackPromiseGeneric<boolean>; - select_entries: ISelectOption<string>[]; - input_placeholder?: string; - input_field?: FormField; - entry_label?: string; - }; - val_sel: string; - val_sel_input: string; - } = $props(); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: basis.entry_label || ``, - }, - notify: basis.visible_input - ? { - label: { - value: `${$ls(`common.close`)}`, - }, - callback: async () => { - await basis.callback_visible(false); - }, - } - : undefined, - }} -> - {#if !basis.visible_input} - <EntrySelect - bind:value={val_sel} - basis={{ - wrap: { - id: fmt_id(`${basis.id}_wrap`), - layer: 1, - }, - el: { - id: fmt_id(basis.id), - sync: true, - layer: 1, - options: [ - { - entries: basis.select_entries, - }, - ], - callback: basis.callback_select, - }, - }} - /> - {:else} - <EntryLine - bind:value={val_sel_input} - basis={{ - wrap: { - id: fmt_id(`${basis.id}_wrap`), - layer: 1, - }, - el: { - layer: 1, - classes: `fade-in`, - placeholder: basis.input_placeholder || ``, - field: basis.input_field || undefined, - field_constrain: !!basis.input_field, - }, - }} - /> - {/if} -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-select.svelte b/apps-lib/src/lib/components/form/form-entry-select.svelte @@ -1,56 +0,0 @@ -<script lang="ts"> - import { - EntrySelect, - fmt_id, - LayoutTrellisLine, - type IClOpt, - type IIdOpt, - type ISelectCallback, - type ISelectOption, - } from "$root"; - - let { - basis, - val = $bindable(``), - }: { - basis: IIdOpt & - IClOpt & { - callback?: ISelectCallback; - entries: ISelectOption<string>[]; - entry_label?: string; - }; - val: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<LayoutTrellisLine - basis={{ - label: { - value: basis.entry_label || ``, - }, - }} -> - <EntrySelect - bind:value={val} - basis={{ - wrap: { - id: id ? fmt_id(`${id}_wrap`) : undefined, - layer: 1, - }, - el: { - id: id ? fmt_id(id) : undefined, - classes: basis.classes, - sync: true, - layer: 1, - options: [ - { - entries: basis.entries, - }, - ], - callback: basis.callback, - }, - }} - /> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-entry-textarea.svelte b/apps-lib/src/lib/components/form/form-entry-textarea.svelte @@ -1,55 +0,0 @@ -<script lang="ts"> - import { - EntryMultiline, - LayoutTrellisLine, - fmt_id, - type IIdOpt, - } from "$root"; - import { - type ElementCallbackValueKeydown, - type FormField, - } from "@radroots/util"; - - let { - basis, - val = $bindable(``), - }: { - basis: IIdOpt & { - entry_label?: string; - placeholder?: string; - field?: FormField; - callback_keydown?: ElementCallbackValueKeydown<HTMLTextAreaElement>; - }; - val: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<LayoutTrellisLine - basis={{ - classes: `h-full`, - label: { - value: basis.entry_label || ``, - }, - }} -> - <EntryMultiline - bind:value={val} - basis={{ - wrap: { - id: id ? fmt_id(`${id}_wrap`) : undefined, - classes: `h-full`, - }, - el: { - classes: `h-full overflow-hidden`, - id: id ? fmt_id(id) : undefined, - sync: true, - placeholder: basis.placeholder || ``, - field: basis.field || undefined, - field_constrain: !!basis.field, - callback_keydown: basis.callback_keydown, - }, - }} - /> -</LayoutTrellisLine> diff --git a/apps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte b/apps-lib/src/lib/components/form/form-line-ledger-label-select-label.svelte @@ -1,36 +0,0 @@ -<script lang="ts"> - import { symbols } from "@radroots/util"; - - let { - basis, - }: { - basis: { - label: string; - }; - } = $props(); -</script> - -<div class={`flex flex-row justify-start items-center`}> - <p - class={`pr-[13px] font-sansd text-trellis_ti text-layer-0-glyph-label uppercase`} - > - {`(${basis.label}`} - </p> - <div - class={`relative flex flex-row justify-start items-center -translate-x-[10px] -translate-y-[1px]`} - > - <p - class={`absolute font-sansd text-trellis_ti text-layer-0-glyph-label uppercase scale-y-[70%] scale-x-[80%] -translate-y-[1px]`} - > - {`${symbols.up}`} - </p> - <p - class={`absolute font-sansd text-trellis_ti text-layer-0-glyph-label uppercase scale-y-[70%] scale-x-[80%] translate-y-[2px]`} - > - {`${symbols.down}`} - </p> - </div> - <p class={`font-sansd text-trellis_ti text-layer-0-glyph-label uppercase`}> - {`)`} - </p> -</div> diff --git a/apps-lib/src/lib/components/form/form-line-ledger-select.svelte b/apps-lib/src/lib/components/form/form-line-ledger-select.svelte @@ -1,88 +0,0 @@ -<script lang="ts"> - import { - fmt_id, - Input, - Select, - type IIdOpt, - type ISelectCallback, - type ISelectOption, - } from "$root"; - import { type ElementCallbackValueKeydown } from "@radroots/util"; - - let { - basis, - value_input = $bindable(``), - value_sel = $bindable(``), - }: { - basis: IIdOpt & { - display_value?: string; - label?: string; - input: { - placeholder?: string; - callback_keydown?: - | ElementCallbackValueKeydown<HTMLInputElement> - | undefined; - }; - select: { - entries: ISelectOption<string>[]; - callback?: ISelectCallback; - }; - }; - value_input?: string; - value_sel?: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<div class={`flex flex-col w-full gap-2 justify-start items-start`}> - {#if basis.label} - <div class={`flex flex-row w-full justify-start items-center`}> - <p - class={`font-sansd text-trellis_ti text-layer-0-glyph-label uppercase`} - > - {basis.label} - </p> - </div> - {/if} - <div - class={`relative flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`} - > - {#if basis.display_value} - <p class={`font-sans font-[400] text-layer-0-glyph text-form_base`}> - {basis.display_value} - </p> - {:else} - <Input - bind:value={value_input} - basis={{ - id: id ? fmt_id(`${id}_input`) : undefined, - layer: 0, - classes: `h-10 placeholder:text-[1.1rem]`, - placeholder: basis.input.placeholder || ``, - callback_keydown: basis.input.callback_keydown, - }} - /> - <div - class={`absolute right-0 flex flex-row justify-center items-center`} - > - <Select - bind:value={value_sel} - basis={{ - classes: `w-fit text-layer-1-glyph`, - id: id ? fmt_id(`${id}_sel`) : undefined, - sync: true, - layer: 1, - show_arrows: `r`, - options: [ - { - entries: basis.select.entries, - }, - ], - callback: basis.select.callback, - }} - /> - </div> - {/if} - </div> -</div> diff --git a/apps-lib/src/lib/components/form/form-line-ledger.svelte b/apps-lib/src/lib/components/form/form-line-ledger.svelte @@ -1,92 +0,0 @@ -<script lang="ts"> - import { - fmt_id, - Input, - SelectMenu, - type IIdOpt, - type ISelectOption, - } from "$root"; - import { - type ElementCallbackValueKeydown, - type FormField, - } from "@radroots/util"; - import FormLineLedgerLabelSelectLabel from "./form-line-ledger-label-select-label.svelte"; - - let { - basis, - value = $bindable(``), - value_label_sel = $bindable(``), - }: { - basis: IIdOpt & { - display_value?: string; - label?: string; - label_select?: { - label: string; - entries: ISelectOption<string>[]; - }; - input?: { - placeholder?: string; - field?: FormField; - callback_keydown?: - | ElementCallbackValueKeydown<HTMLInputElement> - | undefined; - }; - }; - value?: string; - value_label_sel?: string; - } = $props(); - - const id = $derived(basis.id || ``); -</script> - -<div class={`flex flex-col w-full gap-2 justify-start items-start`}> - {#if basis.label} - <div class={`flex flex-row w-full justify-start gap-1 items-center`}> - <p - class={`font-sansd text-trellis_ti text-layer-0-glyph-label uppercase`} - > - {basis.label} - </p> - {#if basis.label_select} - <SelectMenu - bind:value={value_label_sel} - basis={{ - layer: 0, - options: [ - { - entries: basis.label_select.entries, - }, - ], - }} - > - <FormLineLedgerLabelSelectLabel - basis={{ - label: basis.label_select.label, - }} - /> - </SelectMenu> - {/if} - </div> - {/if} - <div - class={`flex flex-row h-12 w-full justify-start items-center border-y-line border-layer-0-surface-edge`} - > - {#if basis.display_value} - <p class={`font-sans font-[400] text-layer-1-glyph text-form_base`}> - {basis.display_value} - </p> - {:else if basis.input} - <Input - bind:value - basis={{ - id: id ? fmt_id(id) : undefined, - layer: 0, - classes: `h-10 placeholder:text-[1.1rem]`, - field: basis.input.field || undefined, - placeholder: basis.input.placeholder || ``, - callback_keydown: basis.input.callback_keydown, - }} - /> - {/if} - </div> -</div> diff --git a/apps-lib/src/lib/components/form/form-review-display.svelte b/apps-lib/src/lib/components/form/form-review-display.svelte @@ -1,43 +0,0 @@ -<script lang="ts"> - import { Glyph, type IClOpt, type IClOptWrap } from "$root"; - import { fmt_cl, type CallbackPromise } from "@radroots/util"; - - let { - basis, - }: { - basis: IClOpt & - IClOptWrap & { - label: string; - value: string; - value_pl?: string; - handle_back: CallbackPromise; - }; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis.classes_wr)} flex flex-row h-6 w-full justify-between items-start`} -> - <p - class={`font-sans font-[500] text-layer-1-glyph_d tracking-tight capitalize`} - > - {basis.label} - </p> - <button - class={`flex flex-row max-w-[210px] gap-1 justify-end items-start`} - onclick={async () => {}} - > - <p - class={`${fmt_cl(basis.classes)} font-sans font-[400] text-[1.05rem] text-justify truncate text-layer-1-glyph_d`} - > - {basis.value || basis.value_pl || ``} - </p> - <Glyph - basis={{ - classes: `text-layer-0-glyph pt-1`, - dim: `xs`, - key: `caret-right`, - }} - /> - </button> -</div> diff --git a/apps-lib/src/lib/components/form/trade_field_display_kv.svelte b/apps-lib/src/lib/components/form/trade_field_display_kv.svelte @@ -1,81 +0,0 @@ -<script lang="ts"> - import { fmt_id, Glyph, idb, type IClOpt } from "$root"; - import { el_focus, fmt_cl, type CallbackPromise } from "@radroots/util"; - - let { - basis, - }: { - basis: IClOpt & { - visible: boolean; - label: string; - display: IClOpt & { - undef?: string; - nostyle?: boolean; - } & ( - | { - kv: string; - } - | { - value: string; - } - ); - - kv_wrap?: string; - handle_back: CallbackPromise; - }; - } = $props(); - - const classes_undef = $derived( - basis.visible && - ((`kv` in basis.display && !idb.get(fmt_id(basis.display.kv))) || - (`value` in basis.display && !basis.display.value)) - ? `opacity-60` - : ``, - ); -</script> - -<div - class={`${fmt_cl(basis.classes)} flex flex-row h-6 w-full justify-between items-start`} -> - <p - class={`font-sans font-[500] text-layer-1-glyph_d tracking-tight capitalize`} - > - {basis.label} - </p> - {#if basis.visible} - <button - class={`flex flex-row max-w-[210px] gap-1 justify-end items-start`} - onclick={async () => { - await el_focus( - fmt_id( - basis.kv_wrap - ? basis.kv_wrap - : `kv` in basis.display - ? `${basis.display.kv}_wrap` - : ``, - ), - async () => await basis.handle_back(), - ); - }} - > - <p - class={`${fmt_cl(basis.display.classes)} font-sans font-[400] text-[1.05rem] text-justify truncate text-layer-1-glyph_d ${classes_undef} ${basis.display.nostyle ? `` : `capitalize`}`} - > - {#if `kv` in basis.display} - {#await idb.get(fmt_id(basis.display.kv)) then kv_val} - {kv_val || basis.display.undef || ``} - {/await} - {:else} - {basis.display.value || basis.display.undef || ``} - {/if} - </p> - <Glyph - basis={{ - classes: `text-layer-0-glyph ${classes_undef} pt-1`, - dim: `xs`, - key: `caret-right`, - }} - /> - </button> - {/if} -</div> diff --git a/apps-lib/src/lib/components/glyph/glyph-circle.svelte b/apps-lib/src/lib/components/glyph/glyph-circle.svelte @@ -1,20 +0,0 @@ -<script lang="ts"> - import { GlyphButton, glyph_style_map, type IGlyphCircle } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IGlyphCircle } = $props(); - - const styles = $derived( - basis?.glyph?.dim - ? glyph_style_map.get(basis?.glyph?.dim) - : glyph_style_map.get(`sm`), - ); -</script> - -{#if styles?.dim_1} - <div - class={`${fmt_cl(basis?.classes_wrap)} flex flex-col h-[${styles?.dim_1}px] w-[${styles?.dim_1}px] justify-center items-center rounded-full el-re`} - > - <GlyphButton basis={basis?.glyph} /> - </div> -{/if} diff --git a/apps-lib/src/lib/components/glyph/glyph.svelte b/apps-lib/src/lib/components/glyph/glyph.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { glyph_style_map, type IGlyph } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IGlyph } = $props(); - - const styles = $derived( - basis?.dim ? glyph_style_map.get(basis.dim) : glyph_style_map.get(`sm`), - ); - - const weight = $derived(basis.weight ? `-${basis.weight}` : `-bold`); -</script> - -<div - id={basis.id || null} - class={`${fmt_cl(basis.classes)} flex flex-row text-[${styles?.gl_1}px] justify-center items-center`} -> - <i class={`ph${weight} ph-${basis.key}`}></i> -</div> diff --git a/apps-lib/src/lib/components/label/label-display.svelte b/apps-lib/src/lib/components/label/label-display.svelte @@ -1,31 +0,0 @@ -<script lang="ts"> - import { type ILabelDisplay } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - - let { basis }: { basis: ILabelDisplay } = $props(); - - const layer = $derived( - typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer, 1), - ); - - const classes_layer = $derived( - typeof layer === `boolean` - ? `bg-transparent` - : `bg-layer-${layer}-surface`, - ); - - const clases_style = $derived( - basis.style === `guide` ? `h-entry_guide rounded-touch` : ``, - ); -</script> - -<div - id={basis.id_wrap || null} - class={`${fmt_cl(basis.classes)} relative el-re entry-line-wrap px-2 ${classes_layer} ${clases_style}`} -> - <p - class={`${fmt_cl(basis.label.classes)} font-sans font-[400] text-layer-0-glyph`} - > - {basis.label.value} - </p> -</div> diff --git a/apps-lib/src/lib/components/layout/layout-bottom-button.svelte b/apps-lib/src/lib/components/layout/layout-bottom-button.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { app_lo } from "$lib/store/app"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis?: { - hidden: boolean; - }; - children: Snippet; - } = $props(); -</script> - -{#if !basis?.hidden} - <div - class={`z-10 absolute bottom-0 h-lo_bottom_button_${$app_lo} flex flex-col w-full px-4 gap-1 justify-start items-center`} - > - {@render children()} - </div> -{/if} diff --git a/apps-lib/src/lib/components/layout/layout-page.svelte b/apps-lib/src/lib/components/layout/layout-page.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col w-full pt-4 px-4 pb-24 gap-4 justify-center items-center`} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/layout/layout-trellis-line.svelte b/apps-lib/src/lib/components/layout/layout-trellis-line.svelte @@ -1,62 +0,0 @@ -<script lang="ts"> - import { - app_lo, - Glyph, - type IBasisOpt, - type ILayoutTrellisLine, - } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - import { fade } from "svelte/transition"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<ILayoutTrellisLine>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col w-lo_line_entry_${$app_lo} gap-[6px] justify-start items-center`} -> - {#if (basis?.label && `value` in basis?.label) || basis?.notify} - <div - class={`flex flex-row h-5 w-full px-2 gap-[6px] justify-start items-center`} - > - {#if basis?.label && `value` in basis?.label} - <p - class={`${fmt_cl(basis?.label.classes)} font-sans font-[400] uppercase text-layer-0-glyph text-sm`} - > - {basis?.label.value} - </p> - {/if} - {#if basis?.notify} - <button - in:fade={{ duration: 200 }} - out:fade={{ delay: 50, duration: 200 }} - onclick={async () => { - await basis?.notify?.callback(); - }} - class={`${fmt_cl(basis?.notify.classes)} flex flex-row gap-1 justify-end items-center text-layer-0-glyph/80 el-re`} - > - {#if `glyph` in basis?.notify && basis?.notify?.glyph && basis.notify.glyph_first} - <Glyph basis={basis.notify.glyph} /> - {/if} - {#if `label` in basis?.notify && basis?.notify?.label && `value` in basis?.notify?.label} - <p - class={`${fmt_cl(basis?.notify.label.classes)} font-sans font-[500] uppercase text-xs`} - > - {basis?.notify.label.value} - </p> - {/if} - {#if `glyph` in basis?.notify && basis?.notify?.glyph && !basis.notify.glyph_first} - <Glyph basis={basis.notify.glyph} /> - {/if} - </button> - {/if} - </div> - {/if} - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/layout/layout-trellis.svelte b/apps-lib/src/lib/components/layout/layout-trellis.svelte @@ -1,19 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt>; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis?.classes)} flex flex-col pb-12 gap-6 justify-center items-center scroll-hide`} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/layout/layout-view.svelte b/apps-lib/src/lib/components/layout/layout-view.svelte @@ -1,54 +0,0 @@ -<script lang="ts"> - import { - nav_blur, - ph_blur, - tabs_blur, - type IBasisOpt, - type IClOpt, - } from "$root"; - import { fmt_cl } from "@radroots/util"; - import { onDestroy, onMount, type Snippet } from "svelte"; - - let { - basis = undefined, - el = $bindable(null), - children, - }: { - el?: HTMLDivElement | null; - basis?: IBasisOpt<IClOpt & { fade?: boolean }>; - children: Snippet; - } = $props(); - - onMount(async () => { - try { - el?.addEventListener("scroll", scrollChange); - } catch (e) { - } finally { - } - }); - - onDestroy(async () => { - try { - el?.removeEventListener("scroll", scrollChange); - } catch (e) { - } finally { - } - }); - - 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); - if (Math.max(el?.scrollTop || 0, 0) > 30) ph_blur.set(true); - else ph_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-start items-center scroll-hide overflow-auto`} - class:fade-in={basis?.fade} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/layout/layout-window.svelte b/apps-lib/src/lib/components/layout/layout-window.svelte @@ -1,36 +0,0 @@ -<script lang="ts"> - import { - app_lo, - app_tilt, - envelope_tilt, - envelope_visible, - handle_err, - window_set, - } from "$root"; - import { onMount } from "svelte"; - - let { children } = $props(); - - onMount(async () => { - try { - window_set(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - envelope_visible.subscribe(async (_envelope_visible) => { - if (_envelope_visible && $envelope_tilt) app_tilt.set(true); - else app_tilt.set(false); - }); -</script> - -<div - class={`relative lg:hidden flex flex-col h-[100vh] w-full bg-layer-0-surface ${$app_tilt ? `scale-y-[96%] translate-y-4 rounded-t-[3rem]` : ``} overflow-x-hidden overflow-y-scroll scroll-hide delay-75 duration-200 el-re`} -> - {#if $app_lo} - <div class={`flex flex-col h-full w-full`}> - {@render children()} - </div> - {/if} -</div> diff --git a/apps-lib/src/lib/components/lib/css.svelte b/apps-lib/src/lib/components/lib/css.svelte @@ -1 +0,0 @@ -<div class="hidden -bottom-lo_bottom_button_ios0 -bottom-lo_bottom_button_ios1 -bottom-lo_bottom_button_webm0 -bottom-lo_bottom_button_webm1 -bottom-lo_view_main_ios0 -bottom-lo_view_main_ios1 -bottom-lo_view_main_webm0 -bottom-lo_view_main_webm1 -bottom-nav_page_header_ios0 -bottom-nav_page_header_ios1 -bottom-nav_page_header_webm0 -bottom-nav_page_header_webm1 -bottom-nav_page_toolbar_ios0 -bottom-nav_page_toolbar_ios1 -bottom-nav_page_toolbar_webm0 -bottom-nav_page_toolbar_webm1 -bottom-nav_tabs_ios0 -bottom-nav_tabs_ios1 -bottom-nav_tabs_webm0 -bottom-nav_tabs_webm1 -left-lo_ios0 -left-lo_ios1 -left-lo_line_entry_ios0 -left-lo_line_entry_ios1 -left-lo_line_entry_webm0 -left-lo_line_entry_webm1 -left-lo_textdesc_ios0 -left-lo_textdesc_ios1 -left-lo_textdesc_webm0 -left-lo_textdesc_webm1 -left-lo_webm0 -left-lo_webm1 -right-lo_ios0 -right-lo_ios1 -right-lo_line_entry_ios0 -right-lo_line_entry_ios1 -right-lo_line_entry_webm0 -right-lo_line_entry_webm1 -right-lo_textdesc_ios0 -right-lo_textdesc_ios1 -right-lo_textdesc_webm0 -right-lo_textdesc_webm1 -right-lo_webm0 -right-lo_webm1 -top-lo_bottom_button_ios0 -top-lo_bottom_button_ios1 -top-lo_bottom_button_webm0 -top-lo_bottom_button_webm1 -top-lo_view_main_ios0 -top-lo_view_main_ios1 -top-lo_view_main_webm0 -top-lo_view_main_webm1 -top-nav_page_header_ios0 -top-nav_page_header_ios1 -top-nav_page_header_webm0 -top-nav_page_header_webm1 -top-nav_page_toolbar_ios0 -top-nav_page_toolbar_ios1 -top-nav_page_toolbar_webm0 -top-nav_page_toolbar_webm1 -top-nav_tabs_ios0 -top-nav_tabs_ios1 -top-nav_tabs_webm0 -top-nav_tabs_webm1 -translate-x-w_lo_ios0 -translate-x-w_lo_ios1 -translate-x-w_lo_line_entry_ios0 -translate-x-w_lo_line_entry_ios1 -translate-x-w_lo_line_entry_webm0 -translate-x-w_lo_line_entry_webm1 -translate-x-w_lo_textdesc_ios0 -translate-x-w_lo_textdesc_ios1 -translate-x-w_lo_textdesc_webm0 -translate-x-w_lo_textdesc_webm1 -translate-x-w_lo_webm0 -translate-x-w_lo_webm1 -translate-y-h_lo_bottom_button_ios0 -translate-y-h_lo_bottom_button_ios1 -translate-y-h_lo_bottom_button_webm0 -translate-y-h_lo_bottom_button_webm1 -translate-y-h_lo_view_main_ios0 -translate-y-h_lo_view_main_ios1 -translate-y-h_lo_view_main_webm0 -translate-y-h_lo_view_main_webm1 -translate-y-h_nav_page_header_ios0 -translate-y-h_nav_page_header_ios1 -translate-y-h_nav_page_header_webm0 -translate-y-h_nav_page_header_webm1 -translate-y-h_nav_page_toolbar_ios0 -translate-y-h_nav_page_toolbar_ios1 -translate-y-h_nav_page_toolbar_webm0 -translate-y-h_nav_page_toolbar_webm1 -translate-y-h_nav_tabs_ios0 -translate-y-h_nav_tabs_ios1 -translate-y-h_nav_tabs_webm0 -translate-y-h_nav_tabs_webm1 active:bg-layer-0-glyph active:bg-layer-0-glyph-hl active:bg-layer-0-glyph-hl_a active:bg-layer-0-glyph-label active:bg-layer-0-glyph-shade active:bg-layer-0-glyph_a active:bg-layer-0-glyph_pl active:bg-layer-0-surface active:bg-layer-0-surface-blur active:bg-layer-0-surface-edge active:bg-layer-0-surface_a active:bg-layer-0-surface_w active:bg-layer-1-glyph active:bg-layer-1-glyph-hl active:bg-layer-1-glyph-hl_a active:bg-layer-1-glyph-label active:bg-layer-1-glyph-shade active:bg-layer-1-glyph_a active:bg-layer-1-glyph_d active:bg-layer-1-glyph_pl active:bg-layer-1-surface active:bg-layer-1-surface-edge active:bg-layer-1-surface-err active:bg-layer-1-surface-focus active:bg-layer-1-surface_a active:bg-layer-2-glyph active:bg-layer-2-glyph-hl active:bg-layer-2-glyph-hl_a active:bg-layer-2-glyph-shade active:bg-layer-2-glyph_a active:bg-layer-2-glyph_d active:bg-layer-2-glyph_pl active:bg-layer-2-surface active:bg-layer-2-surface-edge active:bg-layer-2-surface_a active:bg-radroots-accent-focus active:border-layer-0-glyph active:border-layer-0-glyph-hl active:border-layer-0-glyph-hl_a active:border-layer-0-glyph-label active:border-layer-0-glyph-shade active:border-layer-0-glyph_a active:border-layer-0-glyph_pl active:border-layer-0-surface active:border-layer-0-surface-blur active:border-layer-0-surface-edge active:border-layer-0-surface_a active:border-layer-0-surface_w active:border-layer-1-glyph active:border-layer-1-glyph-hl active:border-layer-1-glyph-hl_a active:border-layer-1-glyph-label active:border-layer-1-glyph-shade active:border-layer-1-glyph_a active:border-layer-1-glyph_d active:border-layer-1-glyph_pl active:border-layer-1-surface active:border-layer-1-surface-edge active:border-layer-1-surface-err active:border-layer-1-surface-focus active:border-layer-1-surface_a active:border-layer-2-glyph active:border-layer-2-glyph-hl active:border-layer-2-glyph-hl_a active:border-layer-2-glyph-shade active:border-layer-2-glyph_a active:border-layer-2-glyph_d active:border-layer-2-glyph_pl active:border-layer-2-surface active:border-layer-2-surface-edge active:border-layer-2-surface_a active:border-radroots-accent-focus active:text-layer-0-glyph active:text-layer-0-glyph-hl active:text-layer-0-glyph-hl_a active:text-layer-0-glyph-label active:text-layer-0-glyph-shade active:text-layer-0-glyph_a active:text-layer-0-glyph_pl active:text-layer-0-surface active:text-layer-0-surface-blur active:text-layer-0-surface-edge active:text-layer-0-surface_a active:text-layer-0-surface_w active:text-layer-1-glyph active:text-layer-1-glyph-hl active:text-layer-1-glyph-hl_a active:text-layer-1-glyph-label active:text-layer-1-glyph-shade active:text-layer-1-glyph_a active:text-layer-1-glyph_d active:text-layer-1-glyph_pl active:text-layer-1-surface active:text-layer-1-surface-edge active:text-layer-1-surface-err active:text-layer-1-surface-focus active:text-layer-1-surface_a active:text-layer-2-glyph active:text-layer-2-glyph-hl active:text-layer-2-glyph-hl_a active:text-layer-2-glyph-shade active:text-layer-2-glyph_a active:text-layer-2-glyph_d active:text-layer-2-glyph_pl active:text-layer-2-surface active:text-layer-2-surface-edge active:text-layer-2-surface_a active:text-radroots-accent-focus bg-layer-0-glyph bg-layer-0-glyph-hl bg-layer-0-glyph-hl_a bg-layer-0-glyph-label bg-layer-0-glyph-shade bg-layer-0-glyph_a bg-layer-0-glyph_pl bg-layer-0-surface bg-layer-0-surface-blur bg-layer-0-surface-edge bg-layer-0-surface_a bg-layer-0-surface_w bg-layer-1-glyph bg-layer-1-glyph-hl bg-layer-1-glyph-hl_a bg-layer-1-glyph-label bg-layer-1-glyph-shade bg-layer-1-glyph_a bg-layer-1-glyph_d bg-layer-1-glyph_pl bg-layer-1-surface bg-layer-1-surface-edge bg-layer-1-surface-err bg-layer-1-surface-focus bg-layer-1-surface_a bg-layer-2-glyph bg-layer-2-glyph-hl bg-layer-2-glyph-hl_a bg-layer-2-glyph-shade bg-layer-2-glyph_a bg-layer-2-glyph_d bg-layer-2-glyph_pl bg-layer-2-surface bg-layer-2-surface-edge bg-layer-2-surface_a bg-radroots-accent-focus border-layer-0-glyph border-layer-0-glyph-hl border-layer-0-glyph-hl_a border-layer-0-glyph-label border-layer-0-glyph-shade border-layer-0-glyph_a border-layer-0-glyph_pl border-layer-0-surface border-layer-0-surface-blur border-layer-0-surface-edge border-layer-0-surface_a border-layer-0-surface_w border-layer-1-glyph border-layer-1-glyph-hl border-layer-1-glyph-hl_a border-layer-1-glyph-label border-layer-1-glyph-shade border-layer-1-glyph_a border-layer-1-glyph_d border-layer-1-glyph_pl border-layer-1-surface border-layer-1-surface-edge border-layer-1-surface-err border-layer-1-surface-focus border-layer-1-surface_a border-layer-2-glyph border-layer-2-glyph-hl border-layer-2-glyph-hl_a border-layer-2-glyph-shade border-layer-2-glyph_a border-layer-2-glyph_d border-layer-2-glyph_pl border-layer-2-surface border-layer-2-surface-edge border-layer-2-surface_a border-radroots-accent-focus bottom-lo_bottom_button_ios0 bottom-lo_bottom_button_ios1 bottom-lo_bottom_button_webm0 bottom-lo_bottom_button_webm1 bottom-lo_view_main_ios0 bottom-lo_view_main_ios1 bottom-lo_view_main_webm0 bottom-lo_view_main_webm1 bottom-nav_page_header_ios0 bottom-nav_page_header_ios1 bottom-nav_page_header_webm0 bottom-nav_page_header_webm1 bottom-nav_page_toolbar_ios0 bottom-nav_page_toolbar_ios1 bottom-nav_page_toolbar_webm0 bottom-nav_page_toolbar_webm1 bottom-nav_tabs_ios0 bottom-nav_tabs_ios1 bottom-nav_tabs_webm0 bottom-nav_tabs_webm1 focus:bg-layer-0-glyph focus:bg-layer-0-glyph-hl focus:bg-layer-0-glyph-hl_a focus:bg-layer-0-glyph-label focus:bg-layer-0-glyph-shade focus:bg-layer-0-glyph_a focus:bg-layer-0-glyph_pl focus:bg-layer-0-surface focus:bg-layer-0-surface-blur focus:bg-layer-0-surface-edge focus:bg-layer-0-surface_a focus:bg-layer-0-surface_w focus:bg-layer-1-glyph focus:bg-layer-1-glyph-hl focus:bg-layer-1-glyph-hl_a focus:bg-layer-1-glyph-label focus:bg-layer-1-glyph-shade focus:bg-layer-1-glyph_a focus:bg-layer-1-glyph_d focus:bg-layer-1-glyph_pl focus:bg-layer-1-surface focus:bg-layer-1-surface-edge focus:bg-layer-1-surface-err focus:bg-layer-1-surface-focus focus:bg-layer-1-surface_a focus:bg-layer-2-glyph focus:bg-layer-2-glyph-hl focus:bg-layer-2-glyph-hl_a focus:bg-layer-2-glyph-shade focus:bg-layer-2-glyph_a focus:bg-layer-2-glyph_d focus:bg-layer-2-glyph_pl focus:bg-layer-2-surface focus:bg-layer-2-surface-edge focus:bg-layer-2-surface_a focus:bg-radroots-accent-focus focus:border-layer-0-glyph focus:border-layer-0-glyph-hl focus:border-layer-0-glyph-hl_a focus:border-layer-0-glyph-label focus:border-layer-0-glyph-shade focus:border-layer-0-glyph_a focus:border-layer-0-glyph_pl focus:border-layer-0-surface focus:border-layer-0-surface-blur focus:border-layer-0-surface-edge focus:border-layer-0-surface_a focus:border-layer-0-surface_w focus:border-layer-1-glyph focus:border-layer-1-glyph-hl focus:border-layer-1-glyph-hl_a focus:border-layer-1-glyph-label focus:border-layer-1-glyph-shade focus:border-layer-1-glyph_a focus:border-layer-1-glyph_d focus:border-layer-1-glyph_pl focus:border-layer-1-surface focus:border-layer-1-surface-edge focus:border-layer-1-surface-err focus:border-layer-1-surface-focus focus:border-layer-1-surface_a focus:border-layer-2-glyph focus:border-layer-2-glyph-hl focus:border-layer-2-glyph-hl_a focus:border-layer-2-glyph-shade focus:border-layer-2-glyph_a focus:border-layer-2-glyph_d focus:border-layer-2-glyph_pl focus:border-layer-2-surface focus:border-layer-2-surface-edge focus:border-layer-2-surface_a focus:border-radroots-accent-focus focus:text-layer-0-glyph focus:text-layer-0-glyph-hl focus:text-layer-0-glyph-hl_a focus:text-layer-0-glyph-label focus:text-layer-0-glyph-shade focus:text-layer-0-glyph_a focus:text-layer-0-glyph_pl focus:text-layer-0-surface focus:text-layer-0-surface-blur focus:text-layer-0-surface-edge focus:text-layer-0-surface_a focus:text-layer-0-surface_w focus:text-layer-1-glyph focus:text-layer-1-glyph-hl focus:text-layer-1-glyph-hl_a focus:text-layer-1-glyph-label focus:text-layer-1-glyph-shade focus:text-layer-1-glyph_a focus:text-layer-1-glyph_d focus:text-layer-1-glyph_pl focus:text-layer-1-surface focus:text-layer-1-surface-edge focus:text-layer-1-surface-err focus:text-layer-1-surface-focus focus:text-layer-1-surface_a focus:text-layer-2-glyph focus:text-layer-2-glyph-hl focus:text-layer-2-glyph-hl_a focus:text-layer-2-glyph-shade focus:text-layer-2-glyph_a focus:text-layer-2-glyph_d focus:text-layer-2-glyph_pl focus:text-layer-2-surface focus:text-layer-2-surface-edge focus:text-layer-2-surface_a focus:text-radroots-accent-focus group-active:bg-layer-0-glyph group-active:bg-layer-0-glyph-hl group-active:bg-layer-0-glyph-hl_a group-active:bg-layer-0-glyph-label group-active:bg-layer-0-glyph-shade group-active:bg-layer-0-glyph_a group-active:bg-layer-0-glyph_pl group-active:bg-layer-0-surface group-active:bg-layer-0-surface-blur group-active:bg-layer-0-surface-edge group-active:bg-layer-0-surface_a group-active:bg-layer-0-surface_w group-active:bg-layer-1-glyph group-active:bg-layer-1-glyph-hl group-active:bg-layer-1-glyph-hl_a group-active:bg-layer-1-glyph-label group-active:bg-layer-1-glyph-shade group-active:bg-layer-1-glyph_a group-active:bg-layer-1-glyph_d group-active:bg-layer-1-glyph_pl group-active:bg-layer-1-surface group-active:bg-layer-1-surface-edge group-active:bg-layer-1-surface-err group-active:bg-layer-1-surface-focus group-active:bg-layer-1-surface_a group-active:bg-layer-2-glyph group-active:bg-layer-2-glyph-hl group-active:bg-layer-2-glyph-hl_a group-active:bg-layer-2-glyph-shade group-active:bg-layer-2-glyph_a group-active:bg-layer-2-glyph_d group-active:bg-layer-2-glyph_pl group-active:bg-layer-2-surface group-active:bg-layer-2-surface-edge group-active:bg-layer-2-surface_a group-active:bg-radroots-accent-focus group-active:border-layer-0-glyph group-active:border-layer-0-glyph-hl group-active:border-layer-0-glyph-hl_a group-active:border-layer-0-glyph-label group-active:border-layer-0-glyph-shade group-active:border-layer-0-glyph_a group-active:border-layer-0-glyph_pl group-active:border-layer-0-surface group-active:border-layer-0-surface-blur group-active:border-layer-0-surface-edge group-active:border-layer-0-surface_a group-active:border-layer-0-surface_w group-active:border-layer-1-glyph group-active:border-layer-1-glyph-hl group-active:border-layer-1-glyph-hl_a group-active:border-layer-1-glyph-label group-active:border-layer-1-glyph-shade group-active:border-layer-1-glyph_a group-active:border-layer-1-glyph_d group-active:border-layer-1-glyph_pl group-active:border-layer-1-surface group-active:border-layer-1-surface-edge group-active:border-layer-1-surface-err group-active:border-layer-1-surface-focus group-active:border-layer-1-surface_a group-active:border-layer-2-glyph group-active:border-layer-2-glyph-hl group-active:border-layer-2-glyph-hl_a group-active:border-layer-2-glyph-shade group-active:border-layer-2-glyph_a group-active:border-layer-2-glyph_d group-active:border-layer-2-glyph_pl group-active:border-layer-2-surface group-active:border-layer-2-surface-edge group-active:border-layer-2-surface_a group-active:border-radroots-accent-focus group-active:text-layer-0-glyph group-active:text-layer-0-glyph-hl group-active:text-layer-0-glyph-hl_a group-active:text-layer-0-glyph-label group-active:text-layer-0-glyph-shade group-active:text-layer-0-glyph_a group-active:text-layer-0-glyph_pl group-active:text-layer-0-surface group-active:text-layer-0-surface-blur group-active:text-layer-0-surface-edge group-active:text-layer-0-surface_a group-active:text-layer-0-surface_w group-active:text-layer-1-glyph group-active:text-layer-1-glyph-hl group-active:text-layer-1-glyph-hl_a group-active:text-layer-1-glyph-label group-active:text-layer-1-glyph-shade group-active:text-layer-1-glyph_a group-active:text-layer-1-glyph_d group-active:text-layer-1-glyph_pl group-active:text-layer-1-surface group-active:text-layer-1-surface-edge group-active:text-layer-1-surface-err group-active:text-layer-1-surface-focus group-active:text-layer-1-surface_a group-active:text-layer-2-glyph group-active:text-layer-2-glyph-hl group-active:text-layer-2-glyph-hl_a group-active:text-layer-2-glyph-shade group-active:text-layer-2-glyph_a group-active:text-layer-2-glyph_d group-active:text-layer-2-glyph_pl group-active:text-layer-2-surface group-active:text-layer-2-surface-edge group-active:text-layer-2-surface_a group-active:text-radroots-accent-focus group-focus:bg-layer-0-glyph group-focus:bg-layer-0-glyph-hl group-focus:bg-layer-0-glyph-hl_a group-focus:bg-layer-0-glyph-label group-focus:bg-layer-0-glyph-shade group-focus:bg-layer-0-glyph_a group-focus:bg-layer-0-glyph_pl group-focus:bg-layer-0-surface group-focus:bg-layer-0-surface-blur group-focus:bg-layer-0-surface-edge group-focus:bg-layer-0-surface_a group-focus:bg-layer-0-surface_w group-focus:bg-layer-1-glyph group-focus:bg-layer-1-glyph-hl group-focus:bg-layer-1-glyph-hl_a group-focus:bg-layer-1-glyph-label group-focus:bg-layer-1-glyph-shade group-focus:bg-layer-1-glyph_a group-focus:bg-layer-1-glyph_d group-focus:bg-layer-1-glyph_pl group-focus:bg-layer-1-surface group-focus:bg-layer-1-surface-edge group-focus:bg-layer-1-surface-err group-focus:bg-layer-1-surface-focus group-focus:bg-layer-1-surface_a group-focus:bg-layer-2-glyph group-focus:bg-layer-2-glyph-hl group-focus:bg-layer-2-glyph-hl_a group-focus:bg-layer-2-glyph-shade group-focus:bg-layer-2-glyph_a group-focus:bg-layer-2-glyph_d group-focus:bg-layer-2-glyph_pl group-focus:bg-layer-2-surface group-focus:bg-layer-2-surface-edge group-focus:bg-layer-2-surface_a group-focus:bg-radroots-accent-focus group-focus:border-layer-0-glyph group-focus:border-layer-0-glyph-hl group-focus:border-layer-0-glyph-hl_a group-focus:border-layer-0-glyph-label group-focus:border-layer-0-glyph-shade group-focus:border-layer-0-glyph_a group-focus:border-layer-0-glyph_pl group-focus:border-layer-0-surface group-focus:border-layer-0-surface-blur group-focus:border-layer-0-surface-edge group-focus:border-layer-0-surface_a group-focus:border-layer-0-surface_w group-focus:border-layer-1-glyph group-focus:border-layer-1-glyph-hl group-focus:border-layer-1-glyph-hl_a group-focus:border-layer-1-glyph-label group-focus:border-layer-1-glyph-shade group-focus:border-layer-1-glyph_a group-focus:border-layer-1-glyph_d group-focus:border-layer-1-glyph_pl group-focus:border-layer-1-surface group-focus:border-layer-1-surface-edge group-focus:border-layer-1-surface-err group-focus:border-layer-1-surface-focus group-focus:border-layer-1-surface_a group-focus:border-layer-2-glyph group-focus:border-layer-2-glyph-hl group-focus:border-layer-2-glyph-hl_a group-focus:border-layer-2-glyph-shade group-focus:border-layer-2-glyph_a group-focus:border-layer-2-glyph_d group-focus:border-layer-2-glyph_pl group-focus:border-layer-2-surface group-focus:border-layer-2-surface-edge group-focus:border-layer-2-surface_a group-focus:border-radroots-accent-focus group-focus:text-layer-0-glyph group-focus:text-layer-0-glyph-hl group-focus:text-layer-0-glyph-hl_a group-focus:text-layer-0-glyph-label group-focus:text-layer-0-glyph-shade group-focus:text-layer-0-glyph_a group-focus:text-layer-0-glyph_pl group-focus:text-layer-0-surface group-focus:text-layer-0-surface-blur group-focus:text-layer-0-surface-edge group-focus:text-layer-0-surface_a group-focus:text-layer-0-surface_w group-focus:text-layer-1-glyph group-focus:text-layer-1-glyph-hl group-focus:text-layer-1-glyph-hl_a group-focus:text-layer-1-glyph-label group-focus:text-layer-1-glyph-shade group-focus:text-layer-1-glyph_a group-focus:text-layer-1-glyph_d group-focus:text-layer-1-glyph_pl group-focus:text-layer-1-surface group-focus:text-layer-1-surface-edge group-focus:text-layer-1-surface-err group-focus:text-layer-1-surface-focus group-focus:text-layer-1-surface_a group-focus:text-layer-2-glyph group-focus:text-layer-2-glyph-hl group-focus:text-layer-2-glyph-hl_a group-focus:text-layer-2-glyph-shade group-focus:text-layer-2-glyph_a group-focus:text-layer-2-glyph_d group-focus:text-layer-2-glyph_pl group-focus:text-layer-2-surface group-focus:text-layer-2-surface-edge group-focus:text-layer-2-surface_a group-focus:text-radroots-accent-focus h-[12px] h-[16px] h-[17px] h-[18px] h-[20px] h-[22px] h-[24px] h-[28px] h-[36px] h-lo_bottom_button_ios0 h-lo_bottom_button_ios1 h-lo_bottom_button_webm0 h-lo_bottom_button_webm1 h-lo_view_main_ios0 h-lo_view_main_ios1 h-lo_view_main_webm0 h-lo_view_main_webm1 h-nav_page_header_ios0 h-nav_page_header_ios1 h-nav_page_header_webm0 h-nav_page_header_webm1 h-nav_page_toolbar_ios0 h-nav_page_toolbar_ios1 h-nav_page_toolbar_webm0 h-nav_page_toolbar_webm1 h-nav_tabs_ios0 h-nav_tabs_ios1 h-nav_tabs_webm0 h-nav_tabs_webm1 left-lo_ios0 left-lo_ios1 left-lo_line_entry_ios0 left-lo_line_entry_ios1 left-lo_line_entry_webm0 left-lo_line_entry_webm1 left-lo_textdesc_ios0 left-lo_textdesc_ios1 left-lo_textdesc_webm0 left-lo_textdesc_webm1 left-lo_webm0 left-lo_webm1 max-h-lo_bottom_button_ios0 max-h-lo_bottom_button_ios1 max-h-lo_bottom_button_webm0 max-h-lo_bottom_button_webm1 max-h-lo_view_main_ios0 max-h-lo_view_main_ios1 max-h-lo_view_main_webm0 max-h-lo_view_main_webm1 max-h-nav_page_header_ios0 max-h-nav_page_header_ios1 max-h-nav_page_header_webm0 max-h-nav_page_header_webm1 max-h-nav_page_toolbar_ios0 max-h-nav_page_toolbar_ios1 max-h-nav_page_toolbar_webm0 max-h-nav_page_toolbar_webm1 max-h-nav_tabs_ios0 max-h-nav_tabs_ios1 max-h-nav_tabs_webm0 max-h-nav_tabs_webm1 max-w-lo_ios0 max-w-lo_ios1 max-w-lo_line_entry_ios0 max-w-lo_line_entry_ios1 max-w-lo_line_entry_webm0 max-w-lo_line_entry_webm1 max-w-lo_textdesc_ios0 max-w-lo_textdesc_ios1 max-w-lo_textdesc_webm0 max-w-lo_textdesc_webm1 max-w-lo_webm0 max-w-lo_webm1 min-h-lo_bottom_button_ios0 min-h-lo_bottom_button_ios1 min-h-lo_bottom_button_webm0 min-h-lo_bottom_button_webm1 min-h-lo_view_main_ios0 min-h-lo_view_main_ios1 min-h-lo_view_main_webm0 min-h-lo_view_main_webm1 min-h-nav_page_header_ios0 min-h-nav_page_header_ios1 min-h-nav_page_header_webm0 min-h-nav_page_header_webm1 min-h-nav_page_toolbar_ios0 min-h-nav_page_toolbar_ios1 min-h-nav_page_toolbar_webm0 min-h-nav_page_toolbar_webm1 min-h-nav_tabs_ios0 min-h-nav_tabs_ios1 min-h-nav_tabs_webm0 min-h-nav_tabs_webm1 min-w-lo_ios0 min-w-lo_ios1 min-w-lo_line_entry_ios0 min-w-lo_line_entry_ios1 min-w-lo_line_entry_webm0 min-w-lo_line_entry_webm1 min-w-lo_textdesc_ios0 min-w-lo_textdesc_ios1 min-w-lo_textdesc_webm0 min-w-lo_textdesc_webm1 min-w-lo_webm0 min-w-lo_webm1 pb-h_lo_bottom_button_ios0 pb-h_lo_bottom_button_ios1 pb-h_lo_bottom_button_webm0 pb-h_lo_bottom_button_webm1 pb-h_lo_view_main_ios0 pb-h_lo_view_main_ios1 pb-h_lo_view_main_webm0 pb-h_lo_view_main_webm1 pb-h_nav_page_header_ios0 pb-h_nav_page_header_ios1 pb-h_nav_page_header_webm0 pb-h_nav_page_header_webm1 pb-h_nav_page_toolbar_ios0 pb-h_nav_page_toolbar_ios1 pb-h_nav_page_toolbar_webm0 pb-h_nav_page_toolbar_webm1 pb-h_nav_tabs_ios0 pb-h_nav_tabs_ios1 pb-h_nav_tabs_webm0 pb-h_nav_tabs_webm1 pl-w_lo_ios0 pl-w_lo_ios1 pl-w_lo_line_entry_ios0 pl-w_lo_line_entry_ios1 pl-w_lo_line_entry_webm0 pl-w_lo_line_entry_webm1 pl-w_lo_textdesc_ios0 pl-w_lo_textdesc_ios1 pl-w_lo_textdesc_webm0 pl-w_lo_textdesc_webm1 pl-w_lo_webm0 pl-w_lo_webm1 pr-w_lo_ios0 pr-w_lo_ios1 pr-w_lo_line_entry_ios0 pr-w_lo_line_entry_ios1 pr-w_lo_line_entry_webm0 pr-w_lo_line_entry_webm1 pr-w_lo_textdesc_ios0 pr-w_lo_textdesc_ios1 pr-w_lo_textdesc_webm0 pr-w_lo_textdesc_webm1 pr-w_lo_webm0 pr-w_lo_webm1 pt-h_lo_bottom_button_ios0 pt-h_lo_bottom_button_ios1 pt-h_lo_bottom_button_webm0 pt-h_lo_bottom_button_webm1 pt-h_lo_view_main_ios0 pt-h_lo_view_main_ios1 pt-h_lo_view_main_webm0 pt-h_lo_view_main_webm1 pt-h_nav_page_header_ios0 pt-h_nav_page_header_ios1 pt-h_nav_page_header_webm0 pt-h_nav_page_header_webm1 pt-h_nav_page_toolbar_ios0 pt-h_nav_page_toolbar_ios1 pt-h_nav_page_toolbar_webm0 pt-h_nav_page_toolbar_webm1 pt-h_nav_tabs_ios0 pt-h_nav_tabs_ios1 pt-h_nav_tabs_webm0 pt-h_nav_tabs_webm1 right-lo_ios0 right-lo_ios1 right-lo_line_entry_ios0 right-lo_line_entry_ios1 right-lo_line_entry_webm0 right-lo_line_entry_webm1 right-lo_textdesc_ios0 right-lo_textdesc_ios1 right-lo_textdesc_webm0 right-lo_textdesc_webm1 right-lo_webm0 right-lo_webm1 text-[12px] text-[15px] text-[16px] text-[18px] text-[19px] text-[20px] text-[21px] text-[23px] text-[24px] text-[26px] text-[27px] text-[28px] text-[30px] text-[36px] text-[40px] text-layer-0-glyph text-layer-0-glyph-hl text-layer-0-glyph-hl_a text-layer-0-glyph-label text-layer-0-glyph-shade text-layer-0-glyph_a text-layer-0-glyph_pl text-layer-0-surface text-layer-0-surface-blur text-layer-0-surface-edge text-layer-0-surface_a text-layer-0-surface_w text-layer-1-glyph text-layer-1-glyph-hl text-layer-1-glyph-hl_a text-layer-1-glyph-label text-layer-1-glyph-shade text-layer-1-glyph_a text-layer-1-glyph_d text-layer-1-glyph_pl text-layer-1-surface text-layer-1-surface-edge text-layer-1-surface-err text-layer-1-surface-focus text-layer-1-surface_a text-layer-2-glyph text-layer-2-glyph-hl text-layer-2-glyph-hl_a text-layer-2-glyph-shade text-layer-2-glyph_a text-layer-2-glyph_d text-layer-2-glyph_pl text-layer-2-surface text-layer-2-surface-edge text-layer-2-surface_a text-radroots-accent-focus top-lo_bottom_button_ios0 top-lo_bottom_button_ios1 top-lo_bottom_button_webm0 top-lo_bottom_button_webm1 top-lo_view_main_ios0 top-lo_view_main_ios1 top-lo_view_main_webm0 top-lo_view_main_webm1 top-nav_page_header_ios0 top-nav_page_header_ios1 top-nav_page_header_webm0 top-nav_page_header_webm1 top-nav_page_toolbar_ios0 top-nav_page_toolbar_ios1 top-nav_page_toolbar_webm0 top-nav_page_toolbar_webm1 top-nav_tabs_ios0 top-nav_tabs_ios1 top-nav_tabs_webm0 top-nav_tabs_webm1 translate-x-w_lo_ios0 translate-x-w_lo_ios1 translate-x-w_lo_line_entry_ios0 translate-x-w_lo_line_entry_ios1 translate-x-w_lo_line_entry_webm0 translate-x-w_lo_line_entry_webm1 translate-x-w_lo_textdesc_ios0 translate-x-w_lo_textdesc_ios1 translate-x-w_lo_textdesc_webm0 translate-x-w_lo_textdesc_webm1 translate-x-w_lo_webm0 translate-x-w_lo_webm1 translate-y-h_lo_bottom_button_ios0 translate-y-h_lo_bottom_button_ios1 translate-y-h_lo_bottom_button_webm0 translate-y-h_lo_bottom_button_webm1 translate-y-h_lo_view_main_ios0 translate-y-h_lo_view_main_ios1 translate-y-h_lo_view_main_webm0 translate-y-h_lo_view_main_webm1 translate-y-h_nav_page_header_ios0 translate-y-h_nav_page_header_ios1 translate-y-h_nav_page_header_webm0 translate-y-h_nav_page_header_webm1 translate-y-h_nav_page_toolbar_ios0 translate-y-h_nav_page_toolbar_ios1 translate-y-h_nav_page_toolbar_webm0 translate-y-h_nav_page_toolbar_webm1 translate-y-h_nav_tabs_ios0 translate-y-h_nav_tabs_ios1 translate-y-h_nav_tabs_webm0 translate-y-h_nav_tabs_webm1 w-[12px] w-[16px] w-[17px] w-[18px] w-[20px] w-[22px] w-[24px] w-[28px] w-[36px] w-lo_ios0 w-lo_ios1 w-lo_line_entry_ios0 w-lo_line_entry_ios1 w-lo_line_entry_webm0 w-lo_line_entry_webm1 w-lo_textdesc_ios0 w-lo_textdesc_ios1 w-lo_textdesc_webm0 w-lo_textdesc_webm1 w-lo_webm0 w-lo_webm1"></div> -\ No newline at end of file diff --git a/apps-lib/src/lib/components/lib/empty.svelte b/apps-lib/src/lib/components/lib/empty.svelte @@ -1,3 +0,0 @@ -<div class={`flex flex-fill text-transparent bg-transparent`}> - <p class={`font-sans`}>{`~`}</p> -</div> diff --git a/apps-lib/src/lib/components/lib/fade.svelte b/apps-lib/src/lib/components/lib/fade.svelte @@ -1,22 +0,0 @@ -<script lang="ts"> - import { type IBasisOpt, type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - import { fade, type FadeParams } from "svelte/transition"; - - let { - basis = undefined, - children, - }: { - basis?: IBasisOpt<IClOpt> & { in?: FadeParams; out?: FadeParams }; - children: Snippet; - } = $props(); -</script> - -<div - in:fade={basis?.in || { duration: 200 }} - out:fade={basis?.out || { delay: 50, duration: 200 }} - class={`${fmt_cl(basis?.classes)} flex`} -> - {@render children()} -</div> diff --git a/apps-lib/src/lib/components/lib/image-blob.svelte b/apps-lib/src/lib/components/lib/image-blob.svelte @@ -1,26 +0,0 @@ -<script lang="ts"> - import { type IImageBlob } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IImageBlob } = $props(); - - const img_src = $derived( - basis.data - ? URL.createObjectURL( - new Blob([basis.data], { - type: "image/jpeg", - }), - ) - : undefined, - ); -</script> - -{#if img_src} - <img - id={basis?.id || null} - class={`${fmt_cl(basis?.classes)}`} - src={img_src || null} - alt={basis?.alt || null} - style={`height: 100%; width: 100%; object-fit: cover; display: block;`} - /> -{/if} diff --git a/apps-lib/src/lib/components/lib/image-path.svelte b/apps-lib/src/lib/components/lib/image-path.svelte @@ -1,21 +0,0 @@ -<script lang="ts"> - import { get_context, ImageBlob, type IImagePath } from "$root"; - import ImageSrc from "./image-src.svelte"; - - const { lc_img_bin } = get_context(`lib`); - let { basis }: { basis: IImagePath } = $props(); - - const img_path = $derived(basis.path); -</script> - -{#if img_path} - {@const is_bin = img_path.startsWith(`file:`)} - - {#if is_bin} - {#await lc_img_bin(img_path) then data} - <ImageBlob basis={{ data, ...basis }} /> - {/await} - {:else} - <ImageSrc basis={{ src: img_path, ...basis }} /> - {/if} -{/if} diff --git a/apps-lib/src/lib/components/lib/image-src.svelte b/apps-lib/src/lib/components/lib/image-src.svelte @@ -1,18 +0,0 @@ -<script lang="ts"> - import { type IImageSource } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IImageSource } = $props(); - - const img_src = $derived(basis.src); -</script> - -{#if img_src} - <img - id={basis?.id || null} - class={`${fmt_cl(basis?.classes)}`} - src={img_src || null} - alt={basis?.alt || null} - style={`height: 100%; width: 100%; object-fit: cover; display: block;`} - /> -{/if} diff --git a/apps-lib/src/lib/components/lib/image.svelte b/apps-lib/src/lib/components/lib/image.svelte @@ -1,16 +0,0 @@ -<script lang="ts"> - import { type IImage } from "$root"; - import { fmt_cl } from "@radroots/util"; - - let { basis }: { basis: IImage } = $props(); -</script> - -{#if basis.src} - <img - id={basis?.id || null} - class={`${fmt_cl(basis?.classes)}`} - src={basis.src} - alt={basis?.alt || null} - style={`height: 100%; width: 100%; object-fit: cover; display: block;`} - /> -{/if} diff --git a/apps-lib/src/lib/components/lib/input-idb.svelte b/apps-lib/src/lib/components/lib/input-idb.svelte @@ -1,120 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { handle_err, idb, type IInput } from "$root"; - import { fmt_cl, parse_layer, value_constrain } from "@radroots/util"; - import { onMount } from "svelte"; - - let { - basis, - el = $bindable(null), - value = $bindable(``), - }: { - basis: IInput<string>; - el?: HTMLInputElement | null; - value?: string; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - const layer = $derived( - typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer), - ); - const classes_layer = $derived( - typeof basis?.layer === `boolean` || typeof basis?.layer === `undefined` - ? `` - : `bg-layer-${layer}-surface text-layer-${layer}-glyph_d placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`, - ); - - let value_local = $state(value); - - const sync_from_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - const kv_val = await idb.get(id); - if ( - kv_val !== null && - kv_val !== undefined && - kv_val !== value_local - ) { - value_local = kv_val; - } else if (kv_val === null || kv_val === undefined) { - value_local = ``; - await idb.set(id, ``); - } - } catch (e) { - handle_err(e, `sync_from_idb`); - } - }; - - const sync_to_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - await idb.set(id, value_local || ``); - } catch (e) { - handle_err(e, `input_idb_sync`); - } - }; - - onMount(async () => { - await sync_from_idb(); - if (basis?.callback_mount && el) { - try { - await basis.callback_mount({ el }); - } catch (e) { - handle_err(e, `callback_mount`); - } - } - }); - - $effect(() => { - if (id && basis?.sync && browser && idb) { - (async () => { - await sync_to_idb(); - })(); - } - }); - - const handle_on_input = async (): Promise<void> => { - try { - let updatedVal = value_local; - let pass = true; - if (basis?.field) { - updatedVal = value_constrain(basis.field.charset, updatedVal); - if (updatedVal !== value_local) { - value_local = updatedVal; - } - pass = basis.field.validate.test(updatedVal); - } - if (basis?.callback) { - await basis.callback({ value: updatedVal, pass }); - } - } catch (e) { - handle_err(e, `handle_on_input`); - } - }; -</script> - -<input - bind:this={el} - bind:value={value_local} - disabled={!!basis.disabled} - oninput={async () => await handle_on_input()} - onblur={async ({ currentTarget: el }) => { - if (basis.callback_blur) await basis.callback_blur({ el }); - }} - onfocus={async ({ currentTarget: el }) => { - if (id && basis.sync && browser && idb) await sync_from_idb(); - if (basis.callback_focus) await basis.callback_focus({ el }); - }} - onkeydown={async (ev) => { - if (basis?.callback_keydown) - await basis.callback_keydown({ - key: ev.key, - key_s: ev.key === `Enter`, - el: ev.currentTarget, - }); - }} - {id} - type="text" - class={`${fmt_cl(basis?.classes)} el-input ${classes_layer} el-re`} - placeholder={basis?.placeholder || ``} -/> diff --git a/apps-lib/src/lib/components/lib/input-value.svelte b/apps-lib/src/lib/components/lib/input-value.svelte @@ -1,67 +0,0 @@ -<script lang="ts"> - import { type IInputValue } from "$root"; - import { fmt_cl, parse_layer, value_constrain } from "@radroots/util"; - - let { - basis, - el = $bindable(null), - value = $bindable(``), - }: { - basis: IInputValue<string>; - el?: HTMLInputElement | null; - value: string; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - const layer = $derived( - typeof basis?.layer === `boolean` - ? parse_layer(0) - : parse_layer(basis?.layer), - ); - - const classes_layer = $derived( - typeof basis?.layer === `boolean` || typeof basis?.layer === `undefined` - ? `` - : `bg-layer-${layer}-surface text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`, - ); - - const handle_on_input = async (): Promise<void> => { - try { - let val_cur = value; - let pass = true; - if (basis?.field) { - val_cur = value_constrain(basis.field.charset, val_cur); - if (val_cur !== value) value = val_cur; - pass = basis.field.validate.test(val_cur); - } - if (basis?.callback) await basis.callback({ value: val_cur, pass }); - } catch (e) { - console.error(`(error) handle_on_input`, e); - } - }; -</script> - -<input - bind:this={el} - bind:value - disabled={!!basis.disabled} - oninput={handle_on_input} - onblur={async ({ currentTarget: el }) => { - if (basis.callback_blur) await basis.callback_blur({ el }); - }} - onfocus={async ({ currentTarget: el }) => { - if (basis.callback_focus) await basis.callback_focus({ el }); - }} - onkeydown={async (ev) => { - if (basis?.callback_keydown) - await basis.callback_keydown({ - key: ev.key, - key_s: ev.key === `Enter`, - el: ev.currentTarget, - }); - }} - {id} - type="text" - class={`${fmt_cl(basis?.classes)} el-input ${classes_layer} el-re`} - placeholder={basis?.placeholder || ``} -/> diff --git a/apps-lib/src/lib/components/lib/input.svelte b/apps-lib/src/lib/components/lib/input.svelte @@ -1,114 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { handle_err, idb, type IInput } from "$root"; - import { fmt_cl, parse_layer, value_constrain } from "@radroots/util"; - import { onMount } from "svelte"; - - let { - basis, - el = $bindable(null), - value = $bindable(``), - }: { - basis: IInput<string>; - el?: HTMLInputElement | null; - value?: string; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - const layer = $derived( - typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer), - ); - const classes_layer = $derived( - typeof basis?.layer === `boolean` || typeof basis?.layer === `undefined` - ? `` - : `bg-layer-${layer}-surface text-layer-${layer}-glyph_d placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`, - ); - - const sync_from_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - const kv_val = await idb.get(id); - if (kv_val !== null && kv_val !== undefined && kv_val !== value) { - value = kv_val; - } else if (kv_val === null || kv_val === undefined) { - value = ``; - await idb.set(id, ``); - } - } catch (e) { - handle_err(e, `sync_from_idb`); - } - }; - - const sync_to_idb = async (): Promise<void> => { - if (!browser || !idb || !id) return; - try { - await idb.set(id, value || ``); - } catch (e) { - handle_err(e, `input_idb_sync`); - } - }; - - onMount(async () => { - await sync_from_idb(); - if (basis?.callback_mount && el) { - try { - await basis.callback_mount({ el }); - } catch (e) { - handle_err(e, `callback_mount`); - } - } - }); - - $effect(() => { - if (id && basis?.sync && browser && idb) { - (async () => { - await sync_to_idb(); - })(); - } - }); - - const handle_on_input = async (): Promise<void> => { - try { - let val_cur = value; - let pass = true; - if (basis?.field) { - val_cur = value_constrain(basis.field?.charset, val_cur); - if (val_cur !== value) { - value = val_cur; - } - pass = basis.field?.validate.test(val_cur); - } - if (basis?.callback) { - await basis.callback({ value: val_cur, pass }); - } - } catch (e) { - handle_err(e, `handle_on_input`); - } - }; -</script> - -<input - bind:this={el} - bind:value - disabled={!!basis.disabled} - oninput={handle_on_input} - onblur={async ({ currentTarget: el }) => { - if (basis.callback_blur) await basis.callback_blur({ el }); - }} - onfocus={async ({ currentTarget: el }) => { - if (id && basis.sync && browser && idb) await sync_from_idb(); - if (basis.callback_focus) await basis.callback_focus({ el }); - }} - onkeydown={async (ev) => { - if (basis?.callback_keydown) - await basis.callback_keydown({ - key: ev.key, - key_s: ev.key === `Enter`, - el: ev.currentTarget, - }); - }} - {id} - type="text" - class={`${fmt_cl(basis?.classes)} el-input ${classes_layer} el-re`} - placeholder={basis?.placeholder || ``} -/> diff --git a/apps-lib/src/lib/components/lib/label-swap.svelte b/apps-lib/src/lib/components/lib/label-swap.svelte @@ -1,37 +0,0 @@ -<script lang="ts"> - import { type ILabelSwap, type ILyOpt } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - - let { - basis, - el = $bindable(null), - }: { - basis: ILabelSwap & ILyOpt; - el?: HTMLLabelElement | null; - } = $props(); - - const layer = $derived(parse_layer(basis?.layer ? basis.layer : 1)); -</script> - -<div class={`flex flex-row justify-start items-center`}> - <!-- svelte-ignore a11y_label_has_associated_control --> - <label - bind:this={el} - class={`swap${basis.swap.toggle ? ` swap-active` : ``}`} - > - <div class="swap-on"> - <p - class={`${fmt_cl(basis.swap.on.classes || `text-nav_prev text-layer-${layer}-glyph-hl group-active:opacity-60`)} font-sans -translate-y-[1px] el-re`} - > - {basis.swap.on.value} - </p> - </div> - <div class="swap-off"> - <p - class={`${fmt_cl(basis.swap.off.classes || `text-nav_prev text-layer-${layer}-glyph-hl group-active:opacity-60`)} font-sans -translate-y-[1px] el-re`} - > - {basis.swap.off.value} - </p> - </div> - </label> -</div> diff --git a/apps-lib/src/lib/components/lib/load-symbol-white.svelte b/apps-lib/src/lib/components/lib/load-symbol-white.svelte @@ -1,70 +0,0 @@ -<script lang="ts"> - import { loading_style_map, type ILoadSymbol } from "$root"; - - let { - basis = undefined, - }: { - basis?: ILoadSymbol; - } = $props(); - - const styles = $derived( - basis?.dim - ? loading_style_map.get(basis?.dim) - : loading_style_map.get("sm"), - ); - - const num_blades = $derived(basis?.blades || 8); -</script> - -<div - class={`relative flex flex-row justify-center items-center h-[${styles?.dim_1}px] w-[${styles?.dim_1}px] fade-in el-re`} -> - <div - class={`${num_blades === 12 ? `spinner12-white center` : `spinner8-white center`} text-[${styles?.gl_2 || styles?.dim_1}px]`} - > - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - {#if num_blades === 12} - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade-white` : `spinner8-blade-white`}`} - ></div> - {/if} - </div> -</div> diff --git a/apps-lib/src/lib/components/lib/load-symbol.svelte b/apps-lib/src/lib/components/lib/load-symbol.svelte @@ -1,70 +0,0 @@ -<script lang="ts"> - import { type ILoadSymbol, loading_style_map } from "$root"; - - let { - basis = undefined, - }: { - basis?: ILoadSymbol; - } = $props(); - - const styles = $derived( - basis?.dim - ? loading_style_map.get(basis?.dim) - : loading_style_map.get("sm"), - ); - - const num_blades = $derived(basis?.blades || 8); -</script> - -<div - class={`relative flex flex-row justify-center items-center h-[${styles?.dim_1}px] w-[${styles?.dim_1}px] fade-in el-re`} -> - <div - class={`${num_blades === 12 ? `spinner12 center` : `spinner8 center`} text-[${styles?.gl_2 || styles?.dim_1}px]`} - > - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - {#if num_blades === 12} - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - <div - class={`${num_blades === 12 ? `spinner12-blade` : `spinner8-blade`}`} - ></div> - {/if} - </div> -</div> diff --git a/apps-lib/src/lib/components/lib/logo-circle-sm.svelte b/apps-lib/src/lib/components/lib/logo-circle-sm.svelte @@ -1,14 +0,0 @@ -<div - class={`relative flex flex-row h-12 w-12 justify-center items-center bg-layer-2-surface rounded-full`} -> - <p - class={`font-sans font-[900] text-[1.5rem] text-layer-0-glyph -tracking-[0.4rem] -translate-x-[2px]`} - > - {"»`,"} - </p> - <p - class={`font-sans font-[900] text-[1.5rem] text-layer-0-glyph translate-x-[3px]`} - > - {"-"} - </p> -</div> diff --git a/apps-lib/src/lib/components/lib/logo-letters.svelte b/apps-lib/src/lib/components/lib/logo-letters.svelte @@ -1,5 +0,0 @@ -<p - class={`font-sansd italic font-[700] text-[1.7rem] text-layer-0-glyph lowercase`} -> - {`radroots`} -</p> diff --git a/apps-lib/src/lib/components/lib/logo_circle.svelte b/apps-lib/src/lib/components/lib/logo_circle.svelte @@ -1,18 +0,0 @@ -<div - class={`relative flex flex-col h-[196px] w-full justify-center items-center`} -> - <div - class={`relative flex flex-row h-36 w-36 justify-center items-center bg-layer-2-surface rounded-full`} - > - <p - class={`font-sans font-[900] text-6xl text-layer-0-glyph -tracking-[0.4rem] -translate-x-[6px]`} - > - {"»`,"} - </p> - <p - class={`font-sans font-[900] text-6xl text-layer-0-glyph translate-x-[8px]`} - > - {"-"} - </p> - </div> -</div> diff --git a/apps-lib/src/lib/components/lib/select-menu.svelte b/apps-lib/src/lib/components/lib/select-menu.svelte @@ -1,80 +0,0 @@ -<script lang="ts"> - import { type ISelect } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis, - value = $bindable(``), - el_wrap = $bindable(null), - el_select = $bindable(null), - children, - }: { - basis: ISelect; - value: string; - el_wrap?: HTMLDivElement | null; - el_select?: HTMLSelectElement | null; - children?: Snippet; - } = $props(); - - const layer = $derived( - parse_layer(typeof basis?.layer === `boolean` ? basis.layer : 0), - ); - - const classes_layer = $derived( - 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-20 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 - onchange={async (e) => { - const opt = basis.options - .map((i) => i.entries) - .reduce((_, j) => j, []) - .find( - (k: { value: string }) => - 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> - {#if children} - <div class={`z-10 flex flex-row h-full w-full`}> - {@render children()} - </div> - {/if} -</div> diff --git a/apps-lib/src/lib/components/lib/select.svelte b/apps-lib/src/lib/components/lib/select.svelte @@ -1,120 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { Glyph, handle_err, idb, type ISelect } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - import { onMount } from "svelte"; - - let { - basis, - value = $bindable(``), - el = $bindable(null), - }: { - basis: ISelect; - value: string; - el?: HTMLSelectElement | null; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - - const layer = $derived( - typeof basis?.layer === `boolean` - ? parse_layer(0) - : parse_layer(basis.layer), - ); - - const classes_layer = $derived( - typeof basis?.layer === `boolean` - ? `` - : !value - ? `text-layer-${layer}-glyph/60` - : `text-layer-${layer}-glyph_d`, - ); - - onMount(async () => { - try { - if (id && basis?.sync_init && browser) { - const sync_val = await idb.get(id); - await idb.set(id, sync_val || ``); - } - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - $effect(() => { - if (browser && id && basis?.sync) { - (async () => { - await idb.set(id, value); - })(); - } - }); - - const handle_on_change = async (el: HTMLSelectElement): Promise<void> => { - try { - const opt = basis.options - .map((i) => i.entries) - .reduce((_, j) => j, []) - .find((k) => k.value === el?.value); - if (el) el.value = value; - if (basis?.sync && id && browser) await idb.set(id, value); - if (basis.callback && opt) await basis.callback(opt); - } catch (e) { - console.log(`(error) handle_on_change `, e); - } - }; -</script> - -{#if basis?.show_arrows === "l"} - <div class={`flex flex-row pr-[2px] justify-center items-center`}> - <Glyph - basis={{ - key: `caret-up-down`, - dim: `xs`, - - classes: `text-layer-${layer}-glyph translate-y-[1px]`, - }} - /> - </div> -{/if} -<select - bind:this={el} - bind:value - onchange={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} - <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> -{#if basis?.show_arrows === "r"} - <div class={`flex flex-row pl-[2px] justify-center items-center`}> - <Glyph - basis={{ - key: `caret-up-down`, - dim: `xs`, - classes: `text-layer-${layer}-glyph`, - }} - /> - </div> -{/if} diff --git a/apps-lib/src/lib/components/lib/splash_screen.svelte b/apps-lib/src/lib/components/lib/splash_screen.svelte @@ -1,14 +0,0 @@ -<script lang="ts"> - import { LogoCircle } from "$root"; -</script> - -<div - class={`z-50 absolute top-0 left-0 flex flex-col h-[100vh] w-full justify-center items-center bg-layer-0-surface`} -> - <LogoCircle /> - <p - class={`font-sansd italic font-[700] text-[1.2rem] text-layer-0-glyph lowercase -translate-y-2`} - > - {`radroots`} - </p> -</div> diff --git a/apps-lib/src/lib/components/lib/swipe.svelte b/apps-lib/src/lib/components/lib/swipe.svelte @@ -1,45 +0,0 @@ -<script lang="ts"> - import type { Snippet } from "svelte"; - import { fade } from "svelte/transition"; - - const DELTA_X_THRESHOLD = 120; - - let { - visible = $bindable(false), - children, - }: { - visible: boolean; - children: Snippet; - } = $props(); - - let swipe_start_x = $state<number | null>(null); - let swipe_delta_x = $state<number>(0); - - const on_pointer_down = (event: PointerEvent): void => { - swipe_start_x = event.clientX; - }; - - const on_pointer_move = (event: PointerEvent): void => { - if (swipe_start_x !== null) - swipe_delta_x = event.clientX - swipe_start_x; - }; - - const on_pointer_up = (): void => { - if (Math.abs(swipe_delta_x) > DELTA_X_THRESHOLD) visible = false; - swipe_start_x = null; - swipe_delta_x = 0; - }; -</script> - -{#if visible} - <div - out:fade={{ duration: 100 }} - class={`flex flex-row w-full`} - onpointerdown={on_pointer_down} - onpointermove={on_pointer_move} - onpointerup={on_pointer_up} - style="transform: translateX({swipe_delta_x}px); transition: transform 0.2s ease;" - > - {@render children()} - </div> -{/if} diff --git a/apps-lib/src/lib/components/lib/text-area.svelte b/apps-lib/src/lib/components/lib/text-area.svelte @@ -1,76 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { idb, type ITextArea } from "$root"; - import { - fmt_cl, - fmt_textarea_value, - parse_layer, - value_constrain_textarea, - } from "@radroots/util"; - - let { - basis, - value = $bindable(``), - el = $bindable(null), - }: { - basis: ITextArea; - value?: string; - el?: HTMLTextAreaElement | null; - } = $props(); - - const id = $derived(basis?.id ? basis.id : null); - const layer = $derived( - typeof basis.layer === `boolean` ? 0 : parse_layer(basis.layer, 1), - ); - - $effect(() => { - if (browser && id && basis?.sync && value) idb.set(id, value); - }); - - const handle_on_input = async (el: HTMLTextAreaElement): Promise<void> => { - try { - let pass = true; - let val = el?.value; - if (basis?.field && el) { - val = value_constrain_textarea(basis?.field.charset, val); - el.value = fmt_textarea_value(val); - if ( - !basis?.field.validate.test(val) && - basis?.field_constrain - ) { - //@todo set styles - } - pass = basis?.field.validate.test(val); - } - if (basis?.callback) await basis?.callback({ value: val, pass }); - } catch (e) { - console.log(`(error) handle_on_input `, e); - } - }; -</script> - -<textarea - bind:this={el} - bind:value - oninput={async ({ currentTarget: el }) => { - await handle_on_input(el); - }} - onblur={async ({ currentTarget: el }) => { - if (basis.callback_blur) await basis.callback_blur({ el }); - }} - onfocus={async ({ currentTarget: el }) => { - if (basis.callback_focus) await basis.callback_focus({ el }); - }} - onkeydown={async (ev) => { - if (basis.callback_keydown) - await basis.callback_keydown({ - key: ev.key, - key_s: ev.key === `Enter`, - el: ev.currentTarget, - }); - }} - {id} - contenteditable="true" - class={`${fmt_cl(basis.classes)} el-textarea py-4 px-[18px] w-full bg-layer-${layer}-surface text-layer-${layer}-glyph_d placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} - placeholder={basis.placeholder || ``} -></textarea> diff --git a/apps-lib/src/lib/components/lib/theme.svelte b/apps-lib/src/lib/components/lib/theme.svelte @@ -1,17 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { app_th, app_thc, theme_set } from "$root"; - import { parse_color_mode, parse_theme_key } from "@radroots/theme"; - - app_thc.subscribe( - (_app_thc) => - browser && - theme_set(parse_theme_key($app_thc), parse_color_mode(_app_thc)), - ); - - app_th.subscribe( - (_app_th) => - browser && - theme_set(parse_theme_key(_app_th), parse_color_mode($app_thc)), - ); -</script> diff --git a/apps-lib/src/lib/components/lib/toast.svelte b/apps-lib/src/lib/components/lib/toast.svelte @@ -1,53 +0,0 @@ -<script lang="ts"> - import { - app_lo, - Glyph, - toast_layout_map, - toast_style_map, - type IToast, - type IToastKind, - } from "$root"; - - import { fmt_cl, get_layout_default, parse_layer } from "@radroots/util"; - - let { basis }: { basis: IToast } = $props(); - - const styles: IToastKind[] = $derived( - basis?.styles ? basis.styles : [`simple`], - ); - const layout = $derived(get_layout_default($app_lo)); - const layer = $derived(basis.layer ? parse_layer(basis.layer) : 1); -</script> - -<div - class={`${fmt_cl(toast_layout_map.get(layout))} z-[1000] h-[100vh] toast w-full ${basis.position || `top-center`} `} -> - <div class={`flex flex-row w-full h-max justify-center pb-2`}> - <div - class={`${fmt_cl(basis.classes)} relative grid grid-cols-12 h-max items-center justify-center ${styles.includes(`simple`) ? `bg-layer-${layer}-surface` : ``} ${fmt_cl(styles.map((style) => fmt_cl(toast_style_map.get(style)?.outer)).join(` `))}`} - > - <div - class={`absolute top-0 left-4 flex flex-row h-full items-center text-layer-${layer}-glyph`} - > - <Glyph - basis={{ - key: `info`, - dim: `md`, - ...basis.glyph, - }} - /> - </div> - <div - class={`col-span-12 flex flex-row pl-1 ${fmt_cl(styles.map((style) => fmt_cl(toast_style_map.get(style)?.inner)).join(` `))}`} - > - {#if `value` in basis.label} - <p - class={`font-sans font-[500] truncate text-layer-${layer}-glyph -translate-y-[1px]`} - > - {basis.label.value} - </p> - {/if} - </div> - </div> - </div> -</div> diff --git a/apps-lib/src/lib/components/lib/wrap-border.svelte b/apps-lib/src/lib/components/lib/wrap-border.svelte @@ -1,23 +0,0 @@ -<script lang="ts"> - import { type IClOpt } from "$root"; - import { fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - basis, - children, - }: { - basis: IClOpt; - children: Snippet; - } = $props(); -</script> - -<div - class={`${fmt_cl(basis.classes)} relative flex flex-col w-full py-[4px] px-[4px] justify-start items-center rounded-[32px] overflow-hidden bg-white shadow-sm`} -> - <div - class={`flex flex-row h-full w-full justify-center items-center bg-white/30 overflow-hidden rounded-[28px]`} - > - {@render children()} - </div> -</div> diff --git a/apps-lib/src/lib/components/map/map-marker-area-display.svelte b/apps-lib/src/lib/components/map/map-marker-area-display.svelte @@ -1,57 +0,0 @@ -<script lang="ts"> - import { Fade, Glyph, type IBasisOpt } from "$root"; - - let { - basis = undefined, - }: { - basis?: IBasisOpt<{ - primary: string; - admin: string; - country: string; - }>; - } = $props(); -</script> - -{#if basis} - <Fade - basis={{ - classes: `flex-col w-full justify-center items-start`, - }} - > - <div - class={`flex flex-col w-fit px-5 py-[10px] justify-start items-start bg-layer-1-surface rounded-3xl shadow-lg`} - > - <div class={`flex flex-col w-full gap-1 justify-start items-start`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-[0.95rem] text-layer-2-glyph`} - > - {basis.primary} - </p> - <Glyph - basis={{ - classes: `text-layer-2-glyph -translate-y-[2px]`, - dim: `xs`, - - key: `map-pin-simple`, - }} - /> - </div> - <div - class={`flex flex-row w-full gap-1 justify-start items-center`} - > - <p - class={`font-sans font-[600] text-[0.95rem] tracking-tight text-layer-2-glyph`} - > - {`${basis.admin},`} - </p> - <p - class={`font-sans font-[600] text-[0.95rem] tracking-tight text-layer-2-glyph`} - > - {`${basis.country}`} - </p> - </div> - </div> - </div> - </Fade> -{/if} diff --git a/apps-lib/src/lib/components/map/map-marker-area.svelte b/apps-lib/src/lib/components/map/map-marker-area.svelte @@ -1,49 +0,0 @@ -<script lang="ts"> - import { - get_context, - MapMarkerAreaDisplay, - type IMapMarkerArea, - } from "$root"; - import { - type GeocoderReverseResult, - type GeolocationPoint, - } from "@radroots/util"; - import { Marker, Popup } from "svelte-maplibre"; - - const { lc_geocode } = get_context(`lib`); - - let { - basis, - map_geop = $bindable(), - map_geoc = $bindable(undefined), - }: { - basis: IMapMarkerArea; - map_geop: GeolocationPoint; - map_geoc?: GeocoderReverseResult | undefined; - } = $props(); -</script> - -<Marker - bind:lngLat={map_geop} - draggable={!basis.no_drag} - class={`flex flex-row h-[100px] w-[100px] bg-blue-400/20 border-[2px] border-white justify-center items-center rounded-full shadow-lg`} - ondragend={async () => { - if (!map_geop) return; - const geoc = await lc_geocode(map_geop); - if (geoc) map_geoc = geoc; - }} -> - {#if basis.show_display} - <Popup open={basis.show_display} offset={[0, -55]}> - <MapMarkerAreaDisplay - basis={map_geoc - ? { - primary: map_geoc.name, - admin: map_geoc.admin1_name, - country: map_geoc.country_name, - } - : undefined} - /> - </Popup> - {/if} -</Marker> diff --git a/apps-lib/src/lib/components/map/map.svelte b/apps-lib/src/lib/components/map/map.svelte @@ -1,42 +0,0 @@ -<script lang="ts"> - import { app_thc, type IClOpt } from "$root"; - import { cfg_map, fmt_cl } from "@radroots/util"; - import type { Snippet } from "svelte"; - import { MapLibre } from "svelte-maplibre"; - - let { - basis = undefined, - map = $bindable(undefined), - children, - }: { - basis?: IClOpt & { - interactive?: boolean; - zoom_click_off?: boolean; - }; - map?: maplibregl.Map; - interactive?: boolean; - children: Snippet; - } = $props(); - - const interactive = $derived( - typeof basis?.interactive === `boolean` ? basis?.interactive : true, - ); - - const zoomOnDoubleClick = $derived( - typeof basis?.zoom_click_off === `boolean` - ? basis?.zoom_click_off - : true, - ); -</script> - -<MapLibre - bind:map - class="{fmt_cl(basis?.classes)} relative h-full w-full" - zoom={10} - style={cfg_map.styles.base[$app_thc]} - attributionControl={false} - {interactive} - {zoomOnDoubleClick} -> - {@render children()} -</MapLibre> diff --git a/apps-lib/src/lib/components/marker/marker-indexed-view.svelte b/apps-lib/src/lib/components/marker/marker-indexed-view.svelte @@ -1,31 +0,0 @@ -<script lang="ts"> - import { Empty } from "$root"; - import { type CallbackPromiseGeneric } from "@radroots/util"; - - let { - basis, - }: { - basis: { - index_curr: number; - index_max: number; - callback_index: CallbackPromiseGeneric<number>; - }; - } = $props(); -</script> - -<div class={`flex flex-row w-full justify-start items-center`}> - <div - class={`flex flex-row h-[5px] w-full gap-[6px] justify-start items-center`} - > - {#each Array(basis.index_max).fill(0) as _, index} - <button - class={`flex flex-row flex-grow h-full justify-start items-center ${basis.index_curr >= index ? `bg-layer-0-glyph` : `bg-layer-2-surface`} rounded-full el-re`} - onclick={async () => { - await basis.callback_index(index); - }} - > - <Empty /> - </button> - {/each} - </div> -</div> diff --git a/apps-lib/src/lib/components/navigation/navigation-tabs.svelte b/apps-lib/src/lib/components/navigation/navigation-tabs.svelte @@ -1,99 +0,0 @@ -<script lang="ts"> - import { goto } from "$app/navigation"; - import { page } from "$app/state"; - import { app_lo, Empty, Glyph } from "$root"; -</script> - -<div - class={`fixed bottom-0 left-0 h-nav_tabs_${$app_lo} flex flex-row w-full pt-2 justify-center items-start`} -> - <div class={`flex flex-row justify-between gap-10 items-center`}> - <div - class={`grid grid-cols-4 flex flex-row h-[3.1rem] px-6 gap-6 justify-start items-center bg-layer-1-surface rounded-full backdrop-blur-lg`} - > - <button - class={`col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/`); - }} - > - <Glyph - basis={{ - classes: `text-[26px] text-layer-0-glyph/80 rotate-90`, - key: `columns`, - weight: page.url.pathname === `/` ? `fill` : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/search`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-layer-0-glyph/80`, - key: `magnifying-glass`, - weight: page.url.pathname.includes(`search`) - ? `fill` - : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row justify-center items-center`} - onclick={async () => { - goto(`/profile`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-layer-0-glyph/80`, - key: `user`, - weight: page.url.pathname.includes(`profile`) - ? `fill` - : `bold`, - }} - /> - </button> - <button - class={`relative col-span-1 flex flex-row h-full justify-center items-center`} - onclick={async () => { - await goto(`/notifications`); - }} - > - <Glyph - basis={{ - classes: `text-[24px] text-layer-0-glyph/80`, - key: `bell`, - weight: page.url.pathname.includes(`notifications`) - ? `fill` - : `bold`, - }} - /> - <div - class={`absolute top-2 -right-1 flex flex-row justify-start items-center`} - > - <div - class={`flex flex-row h-2 w-2 justify-start items-center bg-yellow-400 rounded-full`} - > - <Empty /> - </div> - </div> - </button> - </div> - <button - class={`flex flex-row h-[3.1rem] w-[3.1rem] justify-center items-center bg-layer-1-surface rounded-full backdrop-blur-lg`} - onclick={async () => {}} - > - <Glyph - basis={{ - classes: `text-[22px] text-layer-0-glyph/80`, - - key: `plus`, - }} - /> - </button> - </div> -</div> diff --git a/apps-lib/src/lib/components/navigation/page-header.svelte b/apps-lib/src/lib/components/navigation/page-header.svelte @@ -1,59 +0,0 @@ -<script lang="ts"> - import { - app_lo, - callback_route, - Empty, - ph_blur, - type IPageHeader, - } from "$root"; - import type { Snippet } from "svelte"; - import { fade } from "svelte/transition"; - - let { - basis, - children, - }: { - basis: IPageHeader<string>; - children?: Snippet; - } = $props(); -</script> - -{#if $ph_blur} - <div - in:fade={{ duration: 50 }} - out:fade={{ delay: 50, duration: 200 }} - class={`z-20 fixed top-0 left-0 flex flex-row h-nav_page_header_${$app_lo} w-full justify-center items-center bg-layer-0-surface-blur/30 backdrop-blur-lg`} - > - <Empty /> - </div> -{/if} -<div - class={`z-20 sticky top-0 flex flex-row min-h-nav_page_header_${$app_lo} h-nav_page_header_${$app_lo} w-full px-6 justify-between items-center`} -> - <div class={`flex flex-row justify-start items-center`}> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - if (basis.callback_route) - await callback_route(basis.callback_route); - }} - > - <p - class={`font-sansd font-[700] text-2xl text-layer-0-glyph capitalize max-w-lo_${$app_lo} truncate`} - > - {basis.label || ``} - </p> - </button> - </div> - {#if children} - {#if !$ph_blur} - <div - in:fade={{ duration: 50 }} - out:fade={{ delay: 50, duration: 200 }} - class={`flex flex-row justify-center items-center`} - > - {@render children()} - </div> - {/if} - {/if} -</div> diff --git a/apps-lib/src/lib/components/navigation/page-toolbar.svelte b/apps-lib/src/lib/components/navigation/page-toolbar.svelte @@ -1,60 +0,0 @@ -<script lang="ts"> - import { goto } from "$app/navigation"; - import { - app_lo, - Glyph, - LogoCircleSm, - PageHeader, - type IBasisOpt, - type IPageToolbar, - } from "$root"; - import type { Snippet } from "svelte"; - import LogoLetters from "../lib/logo-letters.svelte"; - - let { - basis = undefined, - header_option, - }: { - basis?: IBasisOpt<IPageToolbar<string>>; - header_option?: Snippet; - } = $props(); -</script> - -<div - class={`flex flex-row min-h-nav_page_toolbar_${$app_lo} h-nav_page_toolbar_${$app_lo} w-full px-6 justify-between items-end`} -> - <div class={`flex flex-row w-full justify-between items-center`}> - <button - class={`flex flex-row gap-2 justify-start items-center`} - onclick={async () => { - if (basis?.callback) await basis.callback(); - else await goto(`/`); - }} - > - <LogoCircleSm /> - <LogoLetters /> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - await goto(`/settings`); - }} - > - <Glyph - basis={{ - classes: `text-layer-0-glyph`, - dim: `lg`, - - key: `gear`, - }} - /> - </button> - </div> -</div> -{#if basis?.header} - <PageHeader basis={basis.header}> - {#if header_option} - {@render header_option()} - {/if} - </PageHeader> -{/if} diff --git a/apps-lib/src/lib/components/trellis/trellis-default-label.svelte b/apps-lib/src/lib/components/trellis/trellis-default-label.svelte @@ -1,37 +0,0 @@ -<script lang="ts"> - import { type ITrellisDefaultLabel } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl } from "@radroots/util"; - - let { - layer, - labels, - classes = ``, - }: { - layer: ThemeLayer; - labels: ITrellisDefaultLabel[]; - classes?: string; - } = $props(); -</script> - -<div class={`${fmt_cl(classes)} flex flex-row`}> - <p class={`font-sans text-trellis_ti text-layer-${layer}-glyph-shade`}> - {#each labels as label} - <span class={`${fmt_cl(label.classes)} font-sans text-trellis_ti`}> - {#if `callback` in label} - <button - class={``} - onclick={async () => { - if (`callback` in label && label.callback) - await label.callback(); - }} - > - {label.label} - </button> - {:else} - {label.label} - {/if} - </span> - {/each} - </p> -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-end.svelte b/apps-lib/src/lib/components/trellis/trellis-end.svelte @@ -1,35 +0,0 @@ -<script lang="ts"> - import { Glyph, type ITrellisBasisTouchEnd } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - - let { - basis, - layer, - hide_active, - }: { - basis: ITrellisBasisTouchEnd; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<div - class={`absolute top-0 right-0 h-full w-max flex flex-row justify-center items-center`} -> - <button - class={`flex pr-3`} - onclick={async (ev) => { - if (basis.callback) await basis.callback(ev); - }} - > - {#if basis.glyph} - <Glyph - basis={{ - classes: `text-layer-${layer}-glyph-shade ${hide_active ? `` : `group-active:text-layer-${layer}-glyph_a`} translate-y-[1px] opacity-70`, - dim: `xs+`, - ...basis.glyph, - }} - /> - {/if} - </button> -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-input.svelte b/apps-lib/src/lib/components/trellis/trellis-input.svelte @@ -1,83 +0,0 @@ -<script lang="ts"> - import { Glyph, Input, LoadSymbol, type ITrellisBasisInput } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl, fmt_trellis } from "@radroots/util"; - - let { - basis, - layer, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisInput; - layer: ThemeLayer; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); -</script> - -<div class={`flex flex-row flex-grow h-full w-full`}> - <div - class={`${fmt_trellis(hide_border_b, hide_border_t)} flex flex-row h-line w-full justify-start items-center border-t-line border-layer-${layer}-surface-edge overflow-hidden`} - > - {#if basis.line_label && basis.line_label.value} - <div - class={`${fmt_cl(basis.line_label.classes)} flex flex-row h-full justify-start items-center overflow-x-hidden`} - > - <p class={`font-sans text-layer-${layer}-glyph_b`}> - {basis.line_label.value} - </p> - </div> - {/if} - <div - class={`relative flex flex-row flex-grow h-full pr-12 justify-start items-center`} - > - <Input - basis={{ - ...basis.basis, - layer: layer, - }} - /> - {#if basis.action} - {#if basis.action.visible} - <div - class={`absolute top-0 right-0 flex flex-row h-full w-12 pr-4 justify-end items-center fade-in`} - > - {#if basis.action.loading} - <div class={`flex flex-row fade-in`}> - <LoadSymbol - basis={{ - dim: `glyph-send-button`, - blades: 8, - classes: `text-layer-${layer}-glyph el-re`, - }} - /> - </div> - {:else} - <button - class={`group fade-in-long`} - onclick={async () => { - if (basis.action?.callback) - await basis.action.callback(); - }} - > - <Glyph - basis={basis.action.glyph - ? { - dim: `md-`, - ...basis.action.glyph, - } - : { - key: `plus`, - classes: `text-layer-${layer}-glyph`, - dim: `md-`, - }} - /> - </button> - {/if} - </div> - {/if} - {/if} - </div> - </div> -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-line.svelte b/apps-lib/src/lib/components/trellis/trellis-line.svelte @@ -1,56 +0,0 @@ -<script lang="ts"> - import { LoadSymbol } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_trellis, type CallbackPromiseGeneric } from "@radroots/util"; - import type { Snippet } from "svelte"; - - let { - loading = false, - layer, - callback, - hide_border_b, - hide_border_t, - children, - el_end, - }: { - loading?: boolean; - layer: ThemeLayer; - callback?: CallbackPromiseGeneric<MouseEvent>; - hide_border_b: boolean; - hide_border_t: boolean; - children: Snippet; - el_end?: Snippet; - } = $props(); -</script> - -<button - class={`flex flex-row flex-grow overflow-hidden`} - onclick={async (ev) => { - if (callback) await callback(ev); - }} -> - <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 el-re`} - > - {#if loading} - <div - class={`flex flex-row h-full w-full justify-center items-center`} - > - <LoadSymbol basis={{ dim: `sm` }} /> - </div> - {:else} - <div - class={`relative group flex flex-row h-line w-full pr-[2px] justify-between items-center el-re`} - > - <div - class={`flex flex-row h-full w-trellis_display justify-between items-center`} - > - {@render children()} - </div> - {#if el_end} - {@render el_end()} - {/if} - </div> - {/if} - </div> -</button> diff --git a/apps-lib/src/lib/components/trellis/trellis-offset.svelte b/apps-lib/src/lib/components/trellis/trellis-offset.svelte @@ -1,74 +0,0 @@ -<script lang="ts"> - import { - Empty, - Glyph, - GlyphCircle, - LoadSymbol, - type ITrellisBasisOffset, - type ITrellisBasisOffsetMod, - } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl } from "@radroots/util"; - - let { - basis = undefined, - layer, - }: { - basis?: ITrellisBasisOffset; - layer: ThemeLayer; - } = $props(); - - const mod: ITrellisBasisOffsetMod = $derived(basis?.mod ? basis.mod : `sm`); -</script> - -<div class={`flex flex-row h-full`}> - {#if mod === `sm`} - <div class={`${fmt_cl(``)} flex flex-row h-full w-[22px]`}> - <Empty /> - </div> - {:else if mod === `glyph`} - <div class={`flex flex-row pr-[2px]`}> - <div class={`${fmt_cl(``)} flex flex-row h-full w-trellisOffset`}> - <Empty /> - </div> - </div> - {:else if typeof mod === `object`} - <div - class={`flex flex-row h-full min-w-[20px] w-trellisOffset justify-center items-center pr-3`} - > - <button - class={`fade-in pl-2 translate-x-[3px] translate-y-[1px]`} - onclick={async (ev) => { - if (mod.loading) return; - else if (typeof basis !== `boolean` && basis?.callback) - await basis.callback(ev); - }} - > - {#if mod.loading} - <LoadSymbol basis={{ blades: 8, dim: `xs` }} /> - {:else if `glyph` in mod} - <Glyph - basis={{ - classes: mod.glyph.classes - ? mod.glyph.classes - : `text-layer-${layer}-glyph`, - ...mod.glyph, - }} - /> - {:else if `glyph_circle` in mod} - <GlyphCircle - basis={{ - classes_wrap: mod.glyph_circle?.classes_wrap, - glyph: { - classes: mod.glyph_circle?.glyph?.classes - ? mod.glyph_circle?.glyph?.classes - : `text-layer-${layer}-glyph`, - ...mod.glyph_circle?.glyph, - }, - }} - /> - {/if} - </button> - </div> - {/if} -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-row-display-value.svelte b/apps-lib/src/lib/components/trellis/trellis-row-display-value.svelte @@ -1,43 +0,0 @@ -<script lang="ts"> - import { Glyph, type ITrellisKindDisplayValue } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl, get_label_classes_kind } from "@radroots/util"; - - let { - basis, - layer, - hide_active, - }: { - basis: ITrellisKindDisplayValue; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<button - class={`z-10 flex flex-grow justify-end`} - onclick={async (ev) => { - ev.stopPropagation(); - if (basis.callback) await basis.callback(ev); - }} -> - {#if `icon` in basis} - <Glyph - basis={{ - classes: - basis.icon.classes || - `${get_label_classes_kind(layer, `shade`, hide_active)}`, - key: basis.icon.key, - dim: `sm`, - }} - /> - {:else if basis.label} - {#if `value` in basis.label} - <p - class={`${fmt_cl(basis.label.classes)} font-sans text-line_d_e line-clamp-1 text-layer-0-glyph-label el-re`} - > - {basis.label.value} - </p> - {/if} - {/if} -</button> diff --git a/apps-lib/src/lib/components/trellis/trellis-row-label.svelte b/apps-lib/src/lib/components/trellis/trellis-row-label.svelte @@ -1,62 +0,0 @@ -<script lang="ts"> - import { GlyphButton, type ILabelTupFields } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl, get_label_classes_kind } from "@radroots/util"; - - let { - basis, - layer, - hide_active, - }: { - basis: ILabelTupFields; - layer: ThemeLayer; - hide_active: boolean; - } = $props(); -</script> - -<div class={`flex flex-row h-full items-center justify-between`}> - {#if basis.left && basis.left.length} - <div class={`flex flex-row h-full items-center truncate`}> - {#each basis.left as title_l} - <div - class={`${fmt_cl(title_l.classes_wrap)} flex flex-row h-full items-center ${get_label_classes_kind(layer, undefined, hide_active)} ${title_l.hide_truncate ? `` : `truncate`}`} - > - {#if `glyph` in title_l} - <div - class={`flex flex-row justify-start items-center pr-2`} - > - <GlyphButton basis={{ ...title_l.glyph }} /> - </div> - {:else if `value` in title_l} - <p - class={`${fmt_cl(title_l.classes)} font-sans text-line_d ${title_l.hide_truncate ? `` : `truncate`} el-re`} - > - {title_l.value || ``} - </p> - {/if} - </div> - {/each} - </div> - {/if} - {#if basis.right && basis.right.length} - <div - class={`flex flex-row h-full w-content items-center justify-end pr-4`} - > - {#each basis.right.reverse() as title_r} - <div - class={`${fmt_cl(title_r.classes_wrap)} flex flex-row h-full gap-1 items-center ${title_r.hide_truncate ? `` : `truncate`}`} - > - {#if `glyph` in title_r} - <GlyphButton basis={{ ...title_r.glyph }} /> - {:else if `value` in title_r} - <p - class={`${fmt_cl(title_r.classes)} font-sans text-line_d text-layer-${layer}-glyph_d ${title_r.hide_truncate ? `` : `truncate`} el-re`} - > - {title_r.value || ``} - </p> - {/if} - </div> - {/each} - </div> - {/if} -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-select.svelte b/apps-lib/src/lib/components/trellis/trellis-select.svelte @@ -1,67 +0,0 @@ -<script lang="ts"> - import { - LoadSymbol, - SelectMenu, - TrellisEnd, - TrellisLine, - TrellisRowDisplayValue, - TrellisRowLabel, - type ITrellisBasisSelect, - } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - - let { - basis, - layer, - hide_active, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisSelect; - layer: ThemeLayer; - hide_active: boolean; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); - - const loading = $derived( - typeof basis?.loading === `boolean` ? basis.loading : false, - ); - - const value = $derived(basis.el.value); -</script> - -<TrellisLine - {layer} - {loading} - {hide_border_b} - {hide_border_t} - callback={basis.callback} -> - <TrellisRowLabel basis={basis.label} {layer} {hide_active} /> - {#if basis.display} - <div class={`flex flex-row pr-3 justify-center items-end`}> - <SelectMenu {value} basis={basis.el}> - {#if basis.display.loading} - <div - class={`flex flex-row h-full w-full justify-end items-center`} - > - <LoadSymbol basis={{ dim: `sm` }} /> - </div> - {:else} - <TrellisRowDisplayValue - basis={{ ...basis.display }} - {layer} - {hide_active} - /> - {/if} - </SelectMenu> - </div> - {/if} - - {#snippet el_end()} - {#if basis.end} - <TrellisEnd basis={basis.end} {layer} {hide_active} /> - {/if} - {/snippet} -</TrellisLine> diff --git a/apps-lib/src/lib/components/trellis/trellis-title.svelte b/apps-lib/src/lib/components/trellis/trellis-title.svelte @@ -1,68 +0,0 @@ -<script lang="ts"> - import { Empty, Glyph, LabelSwap, type ITrellisTitle } from "$root"; - import type { ThemeLayer } from "@radroots/theme"; - import { fmt_cl } from "@radroots/util"; - - let { - basis, - layer = 0, - }: { - basis: ITrellisTitle; - layer: ThemeLayer; - } = $props(); - - const mod = $derived(basis?.mod ? basis.mod : `sm`); -</script> - -<div - class={`${fmt_cl(basis.classes)} flex flex-row h-[24px] w-full pl-[2px] gap-1 items-center`} -> - <button - class={`flex flex-row h-full w-max items-center gap-1 ${mod === `glyph` ? `pl-[36px]` : mod === `sm` ? `pl-[16px]` : ``}`} - onclick={async () => { - if (basis && basis.callback) await basis.callback(); - }} - > - {#if basis.value === true} - <Empty /> - {:else} - <p - class={`font-sans text-trellis_ti text-layer-${layer}-glyph-label uppercase`} - > - {basis.value || ``} - </p> - {/if} - </button> - {#if basis.link} - <button - class={`${fmt_cl(basis.link.classes)} group flex flex-row h-full w-max items-center`} - onclick={async () => { - if (basis.link && basis.link.callback) - await basis.link.callback(); - }} - > - {#if basis.link.label} - {#if `swap` in basis.link.label} - <LabelSwap basis={basis.link.label} /> - {:else if `value` in basis.link.label} - <p - class={`${fmt_cl(basis.link.label.classes)} font-sans text-trellis_ti uppercase fade-in`} - > - {basis.link.label.value || ``} - </p> - {/if} - {/if} - {#if basis.link.glyph} - <div class={`flex flex-row w-max`}> - <Glyph - basis={{ - ...basis.link.glyph, - dim: `xs-`, - classes: `${fmt_cl(basis.link.glyph.classes)} fade-in`, - }} - /> - </div> - {/if} - </button> - {/if} -</div> diff --git a/apps-lib/src/lib/components/trellis/trellis-touch.svelte b/apps-lib/src/lib/components/trellis/trellis-touch.svelte @@ -1,42 +0,0 @@ -<script lang="ts"> - import { - TrellisEnd, - TrellisLine, - TrellisRowDisplayValue, - TrellisRowLabel, - type ITrellisBasisTouch, - } from "$root"; - import type { ThemeLayer } from "@radroots/util"; - - let { - basis, - layer, - hide_active, - hide_border_b, - hide_border_t, - }: { - basis: ITrellisBasisTouch; - layer: ThemeLayer; - hide_active: boolean; - hide_border_b: boolean; - hide_border_t: boolean; - } = $props(); -</script> - -<TrellisLine {layer} {hide_border_b} {hide_border_t} callback={basis.callback}> - <TrellisRowLabel basis={basis.label} {layer} {hide_active} /> - {#if basis.display} - <TrellisRowDisplayValue - basis={{ - ...basis.display, - }} - {layer} - {hide_active} - /> - {/if} - {#snippet el_end()} - {#if basis.end} - <TrellisEnd basis={basis.end} {layer} {hide_active} /> - {/if} - {/snippet} -</TrellisLine> diff --git a/apps-lib/src/lib/components/trellis/trellis.svelte b/apps-lib/src/lib/components/trellis/trellis.svelte @@ -1,152 +0,0 @@ -<script lang="ts"> - import { - app_lo, - get_context, - TrellisDefaultLabel, - TrellisInput, - TrellisOffset, - TrellisSelect, - TrellisTitle, - TrellisTouch, - type ITrellis, - } from "$root"; - import { fmt_cl, parse_layer } from "@radroots/util"; - import type { Snippet } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - el_default, - el_offset, - el_append, - }: { - basis: ITrellis; - el_default?: Snippet; - el_offset?: Snippet; - el_append?: Snippet; - } = $props(); - - const hide_border_t = $derived( - typeof basis.hide_border_top === `boolean` - ? basis.hide_border_top - : true, - ); - - const hide_border_b = $derived( - typeof basis.hide_border_bottom === `boolean` - ? basis.hide_border_bottom - : true, - ); - - const hide_rounded = $derived( - typeof basis.hide_rounded === `boolean` ? basis.hide_rounded : false, - ); - - const set_title_background = $derived( - typeof basis.set_title_background === `boolean` - ? basis.set_title_background - : false, - ); - - const set_default_background = $derived( - typeof basis.set_default_background === `boolean` - ? basis.set_default_background - : false, - ); -</script> - -<div - id={basis.id || ``} - class={`${fmt_cl(basis.classes)} flex flex-col`} - data-view={basis.view || ``} -> - <div - class={`relative flex flex-col h-auto w-lo_${$app_lo} gap-[3px] ${set_title_background ? `bg-layer-${basis.layer}-surface` : ``}`} - > - {#if basis.title && (!basis.default_el || (basis.default_el && basis.default_el.show_title))} - <TrellisTitle - basis={basis.title} - layer={parse_layer(basis.layer - 1)} - /> - {/if} - {#if basis.default_el} - <div - class={`flex flex-col h-auto w-full justify-center items-center`} - > - {#if el_default} - {@render el_default()} - {:else if basis.default_el} - <TrellisDefaultLabel - layer={parse_layer(basis.layer - 1)} - labels={basis.default_el.labels - ? basis.default_el.labels - : [ - { - label: `${$ls(`common.no_items_to_display`)}.`, - }, - ]} - /> - {/if} - </div> - {:else if basis.list} - <div class={`flex flex-col w-full justify-center items-center`}> - {#each basis.list as li} - {#if li} - <div - class={`${li.hide_field ? `hidden` : ``} group flex flex-row h-full w-full justify-end items-center bg-layer-${basis.layer}-surface ${li.full_rounded ? `rounded-touch` : ``} ${hide_rounded ? `` : `first:rounded-t-2xl last:rounded-b-2xl`} ${!li.hide_active ? `active:bg-layer-${basis.layer}-surface_a` : ``} el-re`} - > - <div - class={`flex flex-row h-full w-full gap-1 items-center overflow-y-hidden`} - > - {#if !basis.hide_offset} - <TrellisOffset - basis={li.offset} - layer={basis.layer} - /> - {/if} - {#if el_offset} - {@render el_offset()} - {/if} - {#if `touch` in li && li.touch} - <TrellisTouch - basis={li.touch} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - hide_active={!!li.hide_active} - /> - {:else if `input` in li && li.input} - <TrellisInput - basis={li.input} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - /> - {:else if `select` in li && li.select} - <TrellisSelect - basis={li.select} - layer={basis.layer} - {hide_border_b} - {hide_border_t} - hide_active={!!li.hide_active} - /> - {/if} - </div> - </div> - {/if} - {/each} - </div> - {/if} - </div> - {#if el_append} - <div - class={`flex flex-col w-full ${set_default_background ? `bg-layer-${basis.layer}-surface` : ``}`} - > - {@render el_append()} - </div> - {/if} -</div> -<div - class={`hidden group-first:border-t-0 group-first:border-t-line group-first:border-b-0 group-first:border-b-line`} -></div> diff --git a/apps-lib/src/lib/components/upload/image-upload-add-photo.svelte b/apps-lib/src/lib/components/upload/image-upload-add-photo.svelte @@ -1,47 +0,0 @@ -<script lang="ts"> - import { get_context, Glyph, LoadSymbol } from "$root"; - - const { ls, lc_photos_add } = get_context(`lib`); - - let { - basis, - photo_path = $bindable(``), - }: { - basis: { - loading?: boolean; - }; - photo_path: string; - } = $props(); -</script> - -<div class={`relative flex flex-row w-full justify-center items-center`}> - <button - class={`flex flex-row h-[5rem] w-[5rem] justify-center items-center bg-layer-1-surface/60 rounded-full`} - onclick={async () => { - const photo_paths_add = await lc_photos_add(); - if (photo_paths_add) photo_path = photo_paths_add[0]; - }} - > - {#if basis.loading} - <LoadSymbol basis={{ dim: `md` }} /> - {:else} - <Glyph - basis={{ - classes: `text-[40px] text-layer-2-glyph`, - dim: `sm`, - key: `camera`, - }} - /> - {/if} - - <div - class={`absolute -bottom-[1.8rem] flex flex-row justify-start items-center`} - > - <p - class={`font-arch font-[600] text-sm text-layer-0-glyph capitalize`} - > - {`${$ls(`icu.add_*`, { value: `${$ls(`common.photo`)}` })}`} - </p> - </div> - </button> -</div> diff --git a/apps-lib/src/lib/components/upload/image-upload-buttons-aspect.svelte b/apps-lib/src/lib/components/upload/image-upload-buttons-aspect.svelte @@ -1,95 +0,0 @@ -<script lang="ts"> - import { ButtonLabelGlyph, Empty } from "$root"; - import { - type CallbackPromiseGeneric, - type ImageAspectRatio, - } from "@radroots/util"; - - let { - basis, - }: { - basis: { - callback: CallbackPromiseGeneric<ImageAspectRatio>; - }; - } = $props(); - - let ratio_curr: ImageAspectRatio = $state(`auto`); -</script> - -<div class={`flex flex-row w-full justify-around items-center`}> - <ButtonLabelGlyph - basis={{ - glyph: `crop`, - label: `Auto`, - ring: ratio_curr === `auto`, - callback: async () => { - ratio_curr = `auto`; - await basis.callback(`auto`); - }, - }} - /> - <ButtonLabelGlyph - basis={{ - label: `1:1`, - ring: ratio_curr === `1/1`, - callback: async () => { - ratio_curr = `1/1`; - await basis.callback(`1/1`); - }, - }} - > - <div - class={`flex flex-row h-5 w-5 justify-start items-center rounded-md bg-layer-2-surface shadow-lg`} - > - <Empty /> - </div> - </ButtonLabelGlyph> - <ButtonLabelGlyph - basis={{ - label: `4:3`, - ring: ratio_curr === `4/3`, - callback: async () => { - ratio_curr = `4/3`; - await basis.callback(`4/3`); - }, - }} - > - <div - class={`flex flex-row w-5 aspect-[4/3] justify-start items-center rounded-md bg-layer-2-surface shadow-lg rotate-90`} - > - <Empty /> - </div> - </ButtonLabelGlyph> - <ButtonLabelGlyph - basis={{ - label: `16:9`, - ring: ratio_curr === `16/9`, - callback: async () => { - ratio_curr = `16/9`; - await basis.callback(`16/9`); - }, - }} - > - <div - class={`flex flex-row w-5 aspect-[16/9] justify-start items-center rounded-md bg-layer-2-surface shadow-lg rotate-90`} - > - <Empty /> - </div> - </ButtonLabelGlyph> - <ButtonLabelGlyph - basis={{ - label: `3:4`, - ring: ratio_curr === `3/4`, - callback: async () => { - ratio_curr = `3/4`; - await basis.callback(`3/4`); - }, - }} - > - <div - class={`flex flex-row w-5 aspect-[3/4] justify-start items-center rounded-md bg-layer-2-surface shadow-lg`} - > - <Empty /> - </div> - </ButtonLabelGlyph> -</div> diff --git a/apps-lib/src/lib/components/upload/image-upload-simple.svelte b/apps-lib/src/lib/components/upload/image-upload-simple.svelte @@ -1,69 +0,0 @@ -<script lang="ts"> - import { - get_context, - Glyph, - ImagePath, - ImageUploadButtonsAspect, - } from "$root"; - import { list_assign } from "@radroots/util"; - - const { ls, lc_photos_add } = get_context(`lib`); - - let { - photo_paths = $bindable([]), - }: { - photo_paths: string[]; - } = $props(); - - let img_path = $state(``); - - $effect(() => { - console.log(`img_path `, img_path); - }); -</script> - -<div class={`flex flex-col w-full gap-4 justify-center items-center`}> - {#if img_path} - <div - class={`flex flex-row h-[20rem] w-full gap-2 justify-center items-center rounded-3xl bg-layer-1-surface/60 overflow-hidden`} - > - <ImagePath basis={{ path: img_path }} /> - </div> - {:else} - <button - class={`flex flex-row w-full justify-center items-center`} - onclick={async () => { - const photo_paths_add = await lc_photos_add(); - if (photo_paths_add) { - photo_paths = list_assign(photo_paths, photo_paths_add); - img_path = photo_paths[0]; - } - }} - > - <div - class={`flex flex-row h-[20rem] w-full gap-2 justify-center items-center border-line border-layer-0-glyph/20 border-[3px] border-dashed rounded-3xl bg-layer-1-surface/60`} - > - <Glyph - basis={{ - classes: `text-layer-0-glyph/80`, - dim: `sm`, - - key: `upload-simple`, - }} - /> - <p - class={`font-sans font-[400] text-layer-0-glyph/80 capitalize`} - > - {`${$ls(`icu.upload_*`, { value: `${$ls(`common.image`)}` })}`} - </p> - </div> - </button> - {/if} - <ImageUploadButtonsAspect - basis={{ - callback: async (ratio) => { - // @todo - }, - }} - /> -</div> diff --git a/apps-lib/src/lib/components/window/window-resize-listener.svelte b/apps-lib/src/lib/components/window/window-resize-listener.svelte @@ -1,38 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { handle_err, win_h, win_w } from "$root"; - import { onDestroy, onMount } from "svelte"; - - let last_h = $state(0); - let last_w = $state(0); - - onMount(async () => { - try { - handle_resize(); - if (browser) window.addEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (browser) window.removeEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const handle_resize = (): void => { - if (!browser) return; - const { innerHeight: h, innerWidth: w } = window; - if (Math.abs(h - last_h) > 4) { - last_h = h; - win_h.set(h); - } - if (Math.abs(w - last_w) > 4) { - last_w = w; - win_w.set(w); - } - }; -</script> diff --git a/apps-lib/src/lib/components/window/window-safari-listener.svelte b/apps-lib/src/lib/components/window/window-safari-listener.svelte @@ -1,38 +0,0 @@ -<script lang="ts"> - import { browser } from "$app/environment"; - import { lo_browser_safarinav } from "$lib/store/layout"; - import { handle_err } from "$root"; - import { onDestroy, onMount } from "svelte"; - - const HEIGHT_THRESHOLD = 60; - let h_prev = $state(0); - - onMount(async () => { - try { - handle_resize(); - if (browser) window.addEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (browser) window.removeEventListener(`resize`, handle_resize); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const handle_resize = (): void => { - if (!browser) return; - const { innerHeight: h_curr } = window; - if (h_prev !== undefined) { - const h_del = Math.abs(h_curr - h_prev); - if (h_del > HEIGHT_THRESHOLD) { - lo_browser_safarinav.set(h_curr < h_prev); - } - } - h_prev = h_curr; - }; -</script> diff --git a/apps-lib/src/lib/features/farm/farms-add-casli-detail.svelte b/apps-lib/src/lib/features/farm/farms-add-casli-detail.svelte @@ -1,97 +0,0 @@ -<script lang="ts"> - import { CarouselItem, FormLineLedger, get_context } from "$root"; - import { area_units, form_fields } from "@radroots/util"; - - const { ls } = get_context(`lib`); - - let { - val_farmname = $bindable(``), - val_farmaddress = $bindable(``), - val_farmarea = $bindable(``), - val_farmarea_unit = $bindable(``), - val_farmcontact = $bindable(``), - farm_geop_lat, - farm_geop_lng, - }: { - val_farmname: string; - val_farmaddress: string; - val_farmarea: string; - val_farmarea_unit: string; - val_farmcontact: string; - farm_geop_lat: string; - farm_geop_lng: string; - } = $props(); -</script> - -<CarouselItem> - <div - class={`flex flex-col h-[100vh] w-full px-6 pt-2 gap-4 justify-start items-center`} - > - <FormLineLedger - bind:value={val_farmaddress} - basis={{ - id: `farm_location`, - label: `${$ls(`common.farm_location`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_location`)}`.toLowerCase() })}`, - }, - }} - /> - - <FormLineLedger - basis={{ - id: `farm_coordinates`, - label: `${$ls(`common.farm_coordinates`)}`, - display_value: - farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : undefined, - input: - farm_geop_lat && farm_geop_lng - ? undefined - : { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_coordinates`)}`.toLowerCase() })}`, - }, - }} - /> - <FormLineLedger - bind:value={val_farmname} - basis={{ - id: `farm_name`, - label: `${$ls(`common.farm_name`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_name`)}`.toLowerCase() })}`, - }, - }} - /> - <FormLineLedger - bind:value={val_farmarea} - bind:value_label_sel={val_farmarea_unit} - basis={{ - id: `farm_size`, - label: `${$ls(`common.farm_size`)}`, - label_select: { - label: `${$ls(`units.area.${val_farmarea_unit}_ab`)}`, - entries: area_units.map((i) => ({ - value: i, - label: `${$ls(`units.area.${i}`)}`, - })), - }, - input: { - placeholder: `${`${$ls(`icu.enter_*`, { value: `${$ls(`common.farm_size`)}`.toLowerCase() })}`} ${`${$ls(`units.area.${val_farmarea_unit}_pl`)}`.toLowerCase()}`, - field: form_fields.farm_size, - }, - }} - /> - <FormLineLedger - bind:value={val_farmcontact} - basis={{ - id: `farm_contact`, - label: `${$ls(`common.farm_contact`)}`, - input: { - placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.contact_name`)}`.toLowerCase() })}`, - }, - }} - /> - </div> -</CarouselItem> diff --git a/apps-lib/src/lib/features/farm/farms-add-casli-map.svelte b/apps-lib/src/lib/features/farm/farms-add-casli-map.svelte @@ -1,94 +0,0 @@ -<script lang="ts"> - import Fade from "$lib/components/lib/fade.svelte"; - import { - CarouselItem, - Map, - MapMarkerArea, - WrapBorder, - app_lo, - focus_map_marker, - geop_is_valid, - get_context, - handle_err, - } from "$root"; - import { - type GeocoderReverseResult, - type GeolocationPoint, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { lc_geop_current, lc_geocode } = get_context(`lib`); - - let { - map_geoc = $bindable(undefined), - map_geop = $bindable(undefined), - farm_geop_lat, - farm_geop_lng, - }: { - map_geoc: GeocoderReverseResult | undefined; - map_geop: GeolocationPoint | undefined; - farm_geop_lat: string; - farm_geop_lng: string; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - - const is_valid_geop = $derived(geop_is_valid(map_geop)); - - onMount(async () => { - try { - const geop = await lc_geop_current(); - if (!geop) return; - map_geop = { ...geop }; - const geoc = await lc_geocode(geop); - if (!geoc) return; - map_geoc = geoc; - if (map) map.setCenter([map_geop.lng, map_geop.lat]); - focus_map_marker(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<CarouselItem> - <div - class={`flex flex-col h-[100vh] w-full px-6 gap-4 justify-start items-center`} - > - <WrapBorder basis={{ classes: `h-lo_view_main_${$app_lo}` }}> - <Map bind:map> - {#if map_geop} - <MapMarkerArea - bind:map_geop - bind:map_geoc - basis={{ - show_display: true, - }} - /> - {/if} - </Map> - </WrapBorder> - {#if is_valid_geop} - <Fade> - <div - class={`flex flex-col w-full gap-1 justify-center items-center`} - > - <div - class={`flex flex-row w-full gap-2 justify-center items-center`} - > - <p - class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} - > - {farm_geop_lat} - </p> - <p - class={`font-sans font-[500] text-layer-0-glyph tracking-tightest`} - > - {farm_geop_lng} - </p> - </div> - </div> - </Fade> - {/if} - </div> -</CarouselItem> diff --git a/apps-lib/src/lib/features/farm/farms-display-li-el.svelte b/apps-lib/src/lib/features/farm/farms-display-li-el.svelte @@ -1,107 +0,0 @@ -<script lang="ts"> - import { get_context, Map, MapMarkerArea } from "$root"; - import { - fmt_geolocation_address, - geol_lat_fmt, - geol_lng_fmt, - parse_geol_point_tup, - parse_tup_geop_point, - type CallbackPromiseGeneric, - type FarmExtended, - type GeolocationPointTuple, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - on_handle_farm_view, - }: { - basis: FarmExtended; - on_handle_farm_view: CallbackPromiseGeneric<string>; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - let map_center: GeolocationPointTuple = $state([0, 0]); - - onMount(async () => { - if (basis.location?.point) - map_center = parse_geol_point_tup(basis.location.point); - if (map) map.setCenter(map_center); - }); - - const map_geop = $derived(parse_tup_geop_point(map_center)); - - const farm_addr_fmt = $derived( - basis.location?.address - ? fmt_geolocation_address(basis.location.address) - : ``, - ); - - const farm_geop_lat = $derived( - basis.location?.point - ? geol_lat_fmt(basis.location.point.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - basis.location?.point - ? geol_lng_fmt(basis.location.point.lng, `dms`, $locale, 3) - : ``, - ); -</script> - -<button - class={`z-10 relative flex flex-col w-full p-4 gap-3 justify-start items-center bg-layer-1-surface layer-1-active-raise-less layer-1-active-ring rounded-3xl el-re`} - onclick={async () => { - if (basis.farm.id) await on_handle_farm_view(basis.farm.id); - }} -> - <div class={`flex flex-col w-full gap-2 justify-center items-center`}> - <div class={`flex flex-row w-full justify-between items-center`}> - <p class={`font-sans font-[500] text-3xl text-layer-0-glyph`}> - {basis.farm.name} - </p> - - <div - class={`flex flex-row h-6 px-2 py-1 justify-center items-center bg-lime-400 rounded-lg`} - > - <p class={`font-sans font-[700] text-white`}> - {`${$ls(`common.farm`)}`} - </p> - </div> - </div> - <div class={`flex flex-col w-full justify-center items-center`}> - <div class={`flex flex-row w-full justify-start items-center`}> - <p class={`font-sans font-[500] text-lg text-layer-0-glyph`}> - {farm_addr_fmt} - </p> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <p class={`font-sans font-[500] text-lg text-layer-0-glyph`}> - {farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : ``} - </p> - </div> - </div> - </div> - <div - class={`flex flex-col h-[16rem] w-full justify-center items-center rounded-2xl overflow-hidden`} - > - <Map - bind:map - basis={{ - interactive: false, - }} - > - <MapMarkerArea - {map_geop} - basis={{ - no_drag: true, - }} - /> - </Map> - </div> -</button> diff --git a/apps-lib/src/lib/features/farm/farms-products-review-card.svelte b/apps-lib/src/lib/features/farm/farms-products-review-card.svelte @@ -1,132 +0,0 @@ -<script lang="ts"> - import { - app_lo, - get_context, - Glyph, - ImagePath, - lib_parse_currency_marker, - type IViewFarmsProductsAddSubmitPayload, - } from "$root"; - import { parse_geocode_address, symbols } from "@radroots/util"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - }: { - basis: { - data: IViewFarmsProductsAddSubmitPayload | undefined; - }; - } = $props(); - - //@todo -</script> - -<div - class={`flex flex-col h-[20rem] w-lo_line_entry_${$app_lo} justify-start items-start rounded-touch bg-layer-1-surface overflow-hidden`} -> - <div class={`flex flex-row h-[10rem] w-full justify-center items-center`}> - {#if basis.data?.photos.length} - <ImagePath - basis={{ - path: basis.data.photos[0], - }} - /> - {:else} - <div - class={`flex flex-row h-full w-full justify-center items-center bg-layer-2-surface`} - > - <div class={`flex flex-col justify-start items-center`}> - <Glyph - basis={{ - classes: `text-layer-0-glyph`, - dim: `sm`, - key: `image-broken`, - }} - /> - <p - class={`font-sans font-[400] text-sm text-layer-0-glyph`} - > - {`No photo`} - </p> - </div> - </div> - {/if} - </div> - <div - class={`flex flex-col h-[10rem] w-full px-3 py-2 justify-start items-center`} - > - {#if basis.data} - {@const data_geoc_address = parse_geocode_address( - basis.data.geocode_result, - )} - <div class={`flex flex-row w-full justify-between items-center`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-xl text-th-black capitalize`} - > - {basis.data.product} - </p> - </div> - <div - class={`flex flex-row gap-[2px] justify-start items-center`} - > - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`${lib_parse_currency_marker($locale, basis.data.price_currency)}${basis.data.price_amount}`} - </p> - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`/`} - </p> - <p class={`font-sans font-[600] text-xl text-th-black`}> - {`${$ls(`units.mass.unit.${basis.data.price_quantity_unit}_ab`)}`} - </p> - </div> - </div> - <div class={`flex flex-row w-full justify-between items-center`}> - <div class={`flex flex-row gap-1 justify-start items-center`}> - <p - class={`font-sans font-[600] text-lg text-layer-1-glyph capitalize`} - > - {basis.data.process} - </p> - <p - class={`font-sans font-[600] text-xl text-layer-1-glyph`} - > - {symbols.bullet} - </p> - <p - class={`font-sans font-[600] text-lg text-layer-1-glyph`} - > - {`${basis.data.quantity_amount} ${$ls(`units.mass.unit.${basis.data.quantity_unit}_ab`)} ${basis.data.quantity_label}`} - </p> - </div> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <p - class={`font-sans font-[400] text-sm text-th-black capitalize line-clamp-2 overflow-hidden text-ellipsis`} - > - {basis.data.description} - </p> - </div> - {#if data_geoc_address} - <div - class={`flex flex-row w-full pt-2 justify-between items-center`} - > - <div - class={`flex flex-row gap-1 justify-start items-center`} - > - <p class={`font-sans font-[600] text-th-black`}> - {`${data_geoc_address.primary}, ${data_geoc_address.admin}`} - </p> - <p class={`font-sans font-[600] text-th-black`}> - {symbols.bullet} - </p> - <p class={`font-sans font-[600] text-th-black`}> - {`${data_geoc_address.country}`} - </p> - </div> - </div> - {/if} - {/if} - </div> -</div> diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -1,129 +1,6 @@ -export { default as ButtonHorizontalPairSlide } from "./components/button/button-horizontal-pair-slide.svelte" -export { default as ButtonLabelDashed } from "./components/button/button-label-dashed.svelte" -export { default as ButtonLabelGlyph } from "./components/button/button-label-glyph.svelte" -export { default as ButtonLayoutPair } from "./components/button/button-layout-pair.svelte" -export { default as ButtonLayout } from "./components/button/button-layout.svelte" -export { default as ButtonRoundNav } from "./components/button/button-round-nav.svelte" -export { default as ButtonRound } from "./components/button/button-round.svelte" -export { default as ButtonSimpleGlyph } from "./components/button/button-simple-glyph.svelte" -export { default as ButtonSimple } from "./components/button/button-simple.svelte" -export { default as GlyphButtonSimple } from "./components/button/glyph-button-simple.svelte" -export { default as GlyphButton } from "./components/button/glyph-button.svelte" -export { default as CarouselFlowItem } from "./components/carousel/carousel-flow-item.svelte" -export { default as CarouselFlow } from "./components/carousel/carousel-flow.svelte" -export { default as CarouselItem } from "./components/carousel/carousel-item.svelte" -export { default as Carousel } from "./components/carousel/carousel.svelte" -export { default as EnvelopeLowerFull } from "./components/envelope/envelope-lower-full.svelte" -export { default as MapLocationSelectEnvelope } from "./components/envelope/map-location-select-envelope.svelte" -export { default as FloatPage } from "./components/float/float-page.svelte" -export { default as EntryLineIdb } from "./components/form/entry-line-idb.svelte" -export { default as EntryLine } from "./components/form/entry-line.svelte" -export { default as EntryMultiline } from "./components/form/entry-multiline.svelte" -export { default as EntrySelect } from "./components/form/entry-select.svelte" -export { default as EntryWrap } from "./components/form/entry-wrap.svelte" -export { default as FormEntryInput } from "./components/form/form-entry-input.svelte" -export { default as FormEntryPriceQuantity } from "./components/form/form-entry-price-quantity.svelte" -export { default as FormEntryPrice } from "./components/form/form-entry-price.svelte" -export { default as FormEntryQuantity } from "./components/form/form-entry-quantity.svelte" -export { default as FormEntrySelectInput } from "./components/form/form-entry-select-input.svelte" -export { default as FormEntrySelect } from "./components/form/form-entry-select.svelte" -export { default as FormEntryTextarea } from "./components/form/form-entry-textarea.svelte" -export { default as FormLineLedgerLabelSelectLabel } from "./components/form/form-line-ledger-label-select-label.svelte" -export { default as FormLineLedgerSelect } from "./components/form/form-line-ledger-select.svelte" -export { default as FormLineLedger } from "./components/form/form-line-ledger.svelte" -export { default as FormReviewDisplay } from "./components/form/form-review-display.svelte" -export { default as TradeFieldDisplayKv } from "./components/form/trade_field_display_kv.svelte" -export { default as GlyphCircle } from "./components/glyph/glyph-circle.svelte" -export { default as Glyph } from "./components/glyph/glyph.svelte" -export { default as LabelDisplay } from "./components/label/label-display.svelte" -export { default as LayoutBottomButton } from "./components/layout/layout-bottom-button.svelte" -export { default as LayoutPage } from "./components/layout/layout-page.svelte" -export { default as LayoutTrellisLine } from "./components/layout/layout-trellis-line.svelte" -export { default as LayoutTrellis } from "./components/layout/layout-trellis.svelte" -export { default as LayoutView } from "./components/layout/layout-view.svelte" -export { default as LayoutWindow } from "./components/layout/layout-window.svelte" -export { default as Css } from "./components/lib/css.svelte" -export { default as Empty } from "./components/lib/empty.svelte" -export { default as Fade } from "./components/lib/fade.svelte" -export { default as ImageBlob } from "./components/lib/image-blob.svelte" -export { default as ImagePath } from "./components/lib/image-path.svelte" -export { default as ImageSrc } from "./components/lib/image-src.svelte" -export { default as Image } from "./components/lib/image.svelte" -export { default as InputIdb } from "./components/lib/input-idb.svelte" -export { default as InputValue } from "./components/lib/input-value.svelte" -export { default as Input } from "./components/lib/input.svelte" -export { default as LabelSwap } from "./components/lib/label-swap.svelte" -export { default as LoadSymbolWhite } from "./components/lib/load-symbol-white.svelte" -export { default as LoadSymbol } from "./components/lib/load-symbol.svelte" -export { default as LogoCircleSm } from "./components/lib/logo-circle-sm.svelte" -export { default as LogoLetters } from "./components/lib/logo-letters.svelte" -export { default as LogoCircle } from "./components/lib/logo_circle.svelte" -export { default as SelectMenu } from "./components/lib/select-menu.svelte" -export { default as Select } from "./components/lib/select.svelte" -export { default as SplashScreen } from "./components/lib/splash_screen.svelte" -export { default as Swipe } from "./components/lib/swipe.svelte" -export { default as TextArea } from "./components/lib/text-area.svelte" -export { default as Theme } from "./components/lib/theme.svelte" -export { default as Toast } from "./components/lib/toast.svelte" -export { default as WrapBorder } from "./components/lib/wrap-border.svelte" -export { default as MapMarkerAreaDisplay } from "./components/map/map-marker-area-display.svelte" -export { default as MapMarkerArea } from "./components/map/map-marker-area.svelte" -export { default as Map } from "./components/map/map.svelte" -export { default as MarkerIndexedView } from "./components/marker/marker-indexed-view.svelte" -export { default as NavigationTabs } from "./components/navigation/navigation-tabs.svelte" -export { default as PageHeader } from "./components/navigation/page-header.svelte" -export { default as PageToolbar } from "./components/navigation/page-toolbar.svelte" -export { default as TrellisDefaultLabel } from "./components/trellis/trellis-default-label.svelte" -export { default as TrellisEnd } from "./components/trellis/trellis-end.svelte" -export { default as TrellisInput } from "./components/trellis/trellis-input.svelte" -export { default as TrellisLine } from "./components/trellis/trellis-line.svelte" -export { default as TrellisOffset } from "./components/trellis/trellis-offset.svelte" -export { default as TrellisRowDisplayValue } from "./components/trellis/trellis-row-display-value.svelte" -export { default as TrellisRowLabel } from "./components/trellis/trellis-row-label.svelte" -export { default as TrellisSelect } from "./components/trellis/trellis-select.svelte" -export { default as TrellisTitle } from "./components/trellis/trellis-title.svelte" -export { default as TrellisTouch } from "./components/trellis/trellis-touch.svelte" -export { default as Trellis } from "./components/trellis/trellis.svelte" -export { default as ImageUploadAddPhoto } from "./components/upload/image-upload-add-photo.svelte" -export { default as ImageUploadButtonsAspect } from "./components/upload/image-upload-buttons-aspect.svelte" -export { default as ImageUploadSimple } from "./components/upload/image-upload-simple.svelte" -export { default as WindowResizeListener } from "./components/window/window-resize-listener.svelte" -export { default as WindowSafariListener } from "./components/window/window-safari-listener.svelte" -export { default as FarmsAddCasliDetail } from "./features/farm/farms-add-casli-detail.svelte" -export { default as FarmsAddCasliMap } from "./features/farm/farms-add-casli-map.svelte" -export { default as FarmsDisplayLiEl } from "./features/farm/farms-display-li-el.svelte" -export { default as FarmsProductsReviewCard } from "./features/farm/farms-products-review-card.svelte" -export * from "./store/app.js" -export * from "./store/client.js" -export * from "./store/component.js" -export * from "./store/layout.js" -export * from "./store/ndk.js" -export * from "./store/nostr.js" -export * from "./types/component.js" -export * from "./types/context.js" -export * from "./types/interface.js" +export * from "./stores/ndk.js" +export * from "./stores/theme.js" export * from "./types/lib.js" -export * from "./types/view/farm.js" -export * from "./types/view/lib.js" -export * from "./types/view/profile.js" -export * from "./util/carousel.js" -export * from "./util/casl.js" -export * from "./util/context/lib.js" -export * from "./util/idb.js" -export * from "./util/lib.js" -export * from "./util/nostr/nostr-poll-relays.js" -export * from "./util/nostr/nostr-sync.js" -export * from "./util/service/nostr-event-classified.js" -export * from "./util/service/nostr-sync.js" -export * from "./util/styles.js" -export * from "./util/validation/farm.js" -export * from "./util/view.js" -export { default as FarmsAdd } from "./view/farms-add.svelte" -export { default as FarmsDetails } from "./view/farms-details.svelte" -export { default as FarmsProductsAdd } from "./view/farms-products-add.svelte" -export { default as Farms } from "./view/farms.svelte" -export { default as Home } from "./view/home.svelte" -export { default as Notifications } from "./view/notifications.svelte" -export { default as ProfileEdit } from "./view/profile-edit.svelte" -export { default as Profile } from "./view/profile.svelte" -export { default as Settings } from "./view/settings.svelte" +export * from "./types/ndk.js" +export * from "./utils/idb/lib.js" +export * from "./utils/lib.js" diff --git a/apps-lib/src/lib/store/app.ts b/apps-lib/src/lib/store/app.ts @@ -1,26 +0,0 @@ -import { type IToast } from "$root"; -import type { ColorMode, ThemeKey } from "@radroots/theme"; -import type { AppConfigType, AppLayoutKey, BrowserPlatformInfo } from "@radroots/util"; -import { writable } from "svelte/store"; - -export const app_lo = writable<AppLayoutKey>(); -export const app_platform = writable<BrowserPlatformInfo | undefined>(undefined); -export const app_cfg_type = writable<AppConfigType>(`personal`); -export const app_init = writable<boolean>(false); -export const app_tilt = writable<boolean>(false); -export const app_loading = writable<boolean>(false); -export const app_splash = writable<boolean>(true); -export const app_notify = writable<string>(``); -export const app_toast = writable<IToast | false>(false); -export const app_blur = writable<boolean>(false); -export const app_db = writable<boolean>(false); -export const app_geoc = writable<boolean>(false); -export const app_thc = writable<ColorMode>(`light`); -export const app_th = writable<ThemeKey>(); -export const app_nostr_profiles = writable<string[]>([]); -export const app_load = writable<boolean>(false); - -export const search_results = writable<any[]>([]); - -export const win_h = writable<number>(0); -export const win_w = writable<number>(0); diff --git a/apps-lib/src/lib/store/client.ts b/apps-lib/src/lib/store/client.ts @@ -1,44 +0,0 @@ -import type { NavigationPreviousParam, NavigationRouteParamField, NavigationRouteParamId, NavigationRouteParamLat, NavigationRouteParamLng, NavigationRouteParamNostrPublicKey, NavigationRouteParamRef } from "$root"; -import { writable } from "svelte/store"; -import { queryParam, queryParameters } from "sveltekit-search-params"; - -export const qp = queryParameters(); -export const qp_id = queryParam<NavigationRouteParamId>("id"); -export const qp_field = queryParam<NavigationRouteParamField>("field"); -export const qp_ref = queryParam<NavigationRouteParamRef>("ref"); -export const qp_lat = queryParam<NavigationRouteParamLat>("lat"); -export const qp_lng = queryParam<NavigationRouteParamLng>("lng"); -export const qp_keynostr = queryParam<NavigationRouteParamNostrPublicKey>("key_nostr"); - -export const app_pwa_polyfills = writable<boolean>(false); - -export const nav_visible = writable<boolean>(false); -export const nav_blur = writable<boolean>(false); -export const nav_prev = writable<NavigationPreviousParam<string>[]>([]); - -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); - -export const ph_blur = writable<boolean>(false); - -export const carousel_active = writable<boolean>(false); -export const carousel_index = writable<number>(0); -export const carousel_index_max = writable<number>(0); -const fn_carousel_num = (num_i: number, num_min: number) => { - const store = writable<number>(num_i); - return { - subscribe: store.subscribe, - set: (num: number) => { - store.set(Math.max(num, num_min)); - }, - update: (updater: (num: number) => number) => { - store.update((num) => Math.max(updater(num), num_min)); - } - }; -} -export const carousel_num = fn_carousel_num(1, 1); -export const envelope_visible = writable<boolean>(false); -export const envelope_tilt = writable<boolean>(true); diff --git a/apps-lib/src/lib/store/component.ts b/apps-lib/src/lib/store/component.ts @@ -1,4 +0,0 @@ -import { writable } from "svelte/store"; - -export const casl_i = writable<number>(0); -export const casl_imax = writable<number>(0); -\ No newline at end of file diff --git a/apps-lib/src/lib/store/layout.ts b/apps-lib/src/lib/store/layout.ts @@ -1,3 +0,0 @@ -import { writable } from "svelte/store"; - -export const lo_browser_safarinav = writable<boolean>(false); diff --git a/apps-lib/src/lib/store/ndk.ts b/apps-lib/src/lib/store/ndk.ts @@ -1,24 +0,0 @@ -import { type NDKCacheAdapter, type NDKUser } from "@nostr-dev-kit/ndk"; -import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie"; -import NDKSvelte from "@nostr-dev-kit/ndk-svelte"; -import { writable } from "svelte/store"; - -//@ts-ignore -const ndk_cache_name = import.meta.env.VITE_PUBLIC_NDK_CACHE_NAME; -if (!ndk_cache_name) throw new Error('Error: VITE_PUBLIC_NDK_CACHE_NAME is required'); - -//@ts-ignore -const ndk_client_name = import.meta.env.VITE_PUBLIC_NDK_CLIENT_NAME; -if (!ndk_client_name) throw new Error('Error: VITE_PUBLIC_NDK_CLIENT_NAME is required'); - - -let cacheAdapter: NDKCacheAdapter | undefined; -if (typeof window !== `undefined`) cacheAdapter = new NDKCacheAdapterDexie({ dbName: ndk_cache_name }); - -const ndk_svelte = new NDKSvelte({ - cacheAdapter, - clientName: ndk_client_name, -}); - -export const ndk = writable<NDKSvelte>(ndk_svelte); -export const ndk_user = writable<NDKUser>(); diff --git a/apps-lib/src/lib/store/nostr.ts b/apps-lib/src/lib/store/nostr.ts @@ -1,16 +0,0 @@ -import { writable } from "svelte/store"; - -export const nostr_ndk_configured = writable(false); - -export const nostr_sync_prevent = writable(false); -export const nostr_sync_attempts = writable(0); -export const nostr_sync_attempts_max = writable(8); -export const nostr_sync_stop = writable(true); - -export const nostr_poll_relays_prevent = writable(false); -export const nostr_poll_relays_attempts = writable(0); -export const nostr_poll_relays_attempts_max = writable(0); -export const nostr_poll_relays_stop = writable(true); - -export const nostr_relays_connected = writable<string[]>([]); - diff --git a/apps-lib/src/lib/stores/ndk.ts b/apps-lib/src/lib/stores/ndk.ts @@ -0,0 +1,21 @@ +import { type NDKCacheAdapter, type NDKUser } from "@nostr-dev-kit/ndk"; +import NDKCacheAdapterDexie from "@nostr-dev-kit/ndk-cache-dexie"; +import NDKSvelte from "@nostr-dev-kit/ndk-svelte"; +import { writable } from "svelte/store"; + +const NDK_CACHE_NAME = import.meta.env.VITE_PUBLIC_NDK_CACHE_NAME; +if (!NDK_CACHE_NAME) throw new Error('Error: VITE_PUBLIC_NDK_CACHE_NAME is required'); + +const NDK_CLIENT_NAME = import.meta.env.VITE_PUBLIC_NDK_CLIENT_NAME; +if (!NDK_CLIENT_NAME) throw new Error('Error: VITE_PUBLIC_NDK_CLIENT_NAME is required'); + +let cacheAdapter: NDKCacheAdapter | undefined; +if (typeof window !== `undefined`) cacheAdapter = new NDKCacheAdapterDexie({ dbName: NDK_CACHE_NAME }); + +const ndk_svelte = new NDKSvelte({ + cacheAdapter, + clientName: NDK_CLIENT_NAME, +}); + +export const ndk = writable<NDKSvelte>(ndk_svelte); +export const ndk_user = writable<NDKUser>(); diff --git a/apps-lib/src/lib/stores/theme.ts b/apps-lib/src/lib/stores/theme.ts @@ -0,0 +1,13 @@ +import type { ThemeMode } from "$lib/types/lib"; +import { get_store } from "$lib/utils/lib"; +import { type CallbackPromiseGeneric } from "@radroots/utils"; +import { writable } from "svelte/store"; + +export const theme_mode = writable<ThemeMode>(`light`); +export const theme_key = writable<string>(`default`); + +export const theme_toggle = async (callback: CallbackPromiseGeneric<ThemeMode>): Promise<void> => { + const mode = get_store(theme_mode) === `light` ? `dark` : `light`; + theme_mode.set(mode); + await callback(mode); +}; +\ No newline at end of file diff --git a/apps-lib/src/lib/types/component.ts b/apps-lib/src/lib/types/component.ts @@ -1,252 +0,0 @@ -import type { CallbackRoute, ICb, ICbG, ICbGOpt, ICbOpt, IClOpt, IDisabledOpt, IEntryWrap, IGl, IGlOpt, IGlyphKey, IIdGOpt, IIdOpt, ILabel, ILabelOpt, ILabelTup, ILoadingOpt, ILy, ILyOpt, INavigationRoutePreventRouteNav, NavigationRouteParamKey } from "$root"; -import type { CallbackPromise, CallbackPromiseGeneric, ElementCallbackMount, ElementCallbackValue, ElementCallbackValueBlur, ElementCallbackValueKeydown, FormField, GeometryGlyphDimension, GeometryScreenPosition, GeometryScreenPositionHorizontal, GlyphKey, GlyphWeight, NavigationParamTuple } from "@radroots/util"; - -export type IButtonNavRound = ICb & IDisabledOpt & ILoadingOpt & IGlyphKey; - -export type IFloatPage = { - posx: Omit<GeometryScreenPositionHorizontal, "center">; -} -export type IToastKind = `simple`; - -export type IToast = IClOpt & - ILabel & IGlOpt & ILyOpt & { - styles?: IToastKind[]; - position?: GeometryScreenPosition; - }; - -export type IGlyph = ICbOpt & IIdOpt & ILyOpt & IClOpt & { - weight?: GlyphWeight; - key: GlyphKey; - dim?: GeometryGlyphDimension; -}; - -export type IInput<T extends string> = IIdGOpt<T> & IClOpt & ILyOpt & IDisabledOpt & { - placeholder?: string; - label?: string; - hidden?: boolean; - validate?: RegExp; - sync?: boolean; - field?: FormField; - field_constrain?: boolean; - callback?: ElementCallbackValue, - callback_keydown?: ElementCallbackValueKeydown<HTMLInputElement>, - callback_blur?: ElementCallbackValueBlur<HTMLInputElement>; - callback_focus?: ElementCallbackValueBlur<HTMLInputElement>; - callback_mount?: ElementCallbackMount<HTMLInputElement>; -}; - -export type IInputValue<T extends string> = Omit<IInput<T>, `sync`>; - -export type ISelectOption<T extends string> = IDisabledOpt & { - value: T; - label: string; -}; - -export type ISelectCallback = CallbackPromiseGeneric<ISelectOption<string>> - -export type ISelect = IIdOpt & IClOpt & ILyOpt & { - callback?: ISelectCallback; - sync?: boolean; - sync_init?: boolean; - options: { group?: string | true; entries: ISelectOption<string>[] }[]; - show_arrows?: 'l' | 'r'; -}; - -export type ITextArea = IIdOpt & IClOpt & ILyOpt & { - placeholder?: string; - label?: string; - hidden?: boolean; - validate?: RegExp; - sync?: true; - field?: FormField; - field_constrain?: boolean; - callback?: ElementCallbackValue, - callback_keydown?: ElementCallbackValueKeydown<HTMLTextAreaElement>, - callback_blur?: ElementCallbackValueBlur<HTMLTextAreaElement>; - callback_focus?: ElementCallbackValueBlur<HTMLTextAreaElement>; - callback_mount?: ElementCallbackMount<HTMLTextAreaElement>; -}; - -export type INavigationRoute<T extends string> = { - route: T | [T, NavigationParamTuple<NavigationRouteParamKey>[]]; -}; - -export type IPageToolbar<T extends string> = ICbOpt & { - header?: IPageHeader<T>; -}; - -export type IPageHeader<T extends string> = { - label: string; - callback_route?: CallbackRoute<T>; -}; - -export type IGlyphCircle = { - classes_wrap: string; - glyph: IGlyph -}; - -export type ITrellis = ILy & - IClOpt & - ITrellisStyles & { - id?: string; - view?: string; - title?: ITrellisTitle; - description?: ITrellisDescription; - default_el?: ITrellisDefault; - list?: (ITrellisKind | undefined)[]; - hide_offset?: true; - }; - -export type ITrellisStyles = { - hide_rounded?: boolean; - hide_border_top?: boolean; - hide_border_bottom?: boolean; - set_title_background?: boolean; - set_default_background?: boolean; -}; - -export type ITrellisTitle = ICbOpt & - IClOpt & { - mod?: ITrellisBasisOffsetMod, - value: string | true; - link?: ICbOpt & - IClOpt & - IGlOpt & ILabelOpt; - }; - -export type ITrellisDescription = string | true; - -export type ITrellisBasisOffsetModKey = 'sm' | 'glyph'; -export type ITrellisBasisOffsetMod = ITrellisBasisOffsetModKey | (({ glyph: IGlyph } | { glyph_circle: IGlyphCircle }) & { - loading?: boolean; -}); - -export type ITrellisDefault = { - labels?: ITrellisDefaultLabel[]; - show_title?: boolean; -}; - -export type ITrellisDefaultLabel = ICbOpt & { - label: string; - classes?: string; -}; - -export type ITrellisKind = ( - | ITrellisKindTouch - | ITrellisKindInput - | ITrellisKindSelect -); - -export type ITrellisBasis = { - loading?: boolean; - hide_active?: boolean; - hide_field?: boolean; - offset?: ITrellisBasisOffset; - full_rounded?: boolean; -}; - -export type ITrellisBasisOffset = ICbGOpt<MouseEvent> & - IClOpt & { - mod?: ITrellisBasisOffsetMod; - classes?: string; - hide_space?: boolean; - hide_offset?: boolean; - }; - -export type ITrellisKindDisplay = { - display?: ITrellisKindDisplayValue; -} -export type ITrellisKindDisplayValue = ICbGOpt<MouseEvent> & ILoadingOpt & - (ITrellisKindDisplayValueIcon | ILabel); - - -export type ITrellisKindDisplayValueIcon = { - icon: { - classes?: string; - key: GlyphKey; - }; -}; -export type ITrellisKindTouch = ITrellisBasis & { - touch: ITrellisBasisTouch; -}; - -export type ITrellisBasisTouch = ICbGOpt<MouseEvent> & - ILabelTup & ITrellisKindDisplay & { - end?: ITrellisBasisTouchEnd; - }; - -export type ITrellisKindInput = ITrellisBasis & { - input: ITrellisBasisInput; -}; - -export type ITrellisBasisInput = { - basis: IInput<string>; - line_label?: { - classes?: string; - value: string; - }; - action?: { - visible: boolean; - loading?: boolean; - callback?: CallbackPromise; - glyph?: IGlyph - }; -}; - -export type ITrellisKindSelect = ITrellisBasis & { - select: ITrellisBasisSelect; -}; - -export type ITrellisBasisSelect = ICbGOpt<MouseEvent> & - ILabelTup & ITrellisKindDisplay & ILoadingOpt & { - end?: ITrellisBasisTouchEnd; - el: ISelect & { value: string; }; - }; - -export type ITrellisBasisTouchEnd = ICbGOpt<MouseEvent> & IGl; - -export type INavBasisPrev = IClOpt & ICbG< - HTMLLabelElement | null -> & IGlOpt & ILabelOpt & IDisabledOpt & { - loading?: boolean; -}; -export type INavBasisOption = IClOpt & ICbG< - HTMLLabelElement | null -> & IGlOpt & ILabelOpt & IDisabledOpt & { - loading?: boolean; -}; -export type INavBasis<T extends string> = { - prev: ICbOpt & ILoadingOpt & INavigationRoute<T> & INavigationRoutePreventRouteNav & { - label?: string; - kind?: 'arrow' - }; - title?: ICbOpt & ILabel; - option?: INavBasisOption; -}; - -export type IEntrySelect = ILoadingOpt & { - wrap: IEntryWrap; - el: ISelect; - hide_arrows?: boolean; -}; - -export type IButtonSimple = ILyOpt & { - label: string; - callback: CallbackPromise; - allow_propogation?: boolean; -}; - -export type IMapMarkerArea = { - show_display?: boolean; - no_drag?: boolean; -} - -export type ILayoutTrellisLine = ILabelOpt & - IClOpt & { - notify?: IClOpt & - ICb & - ILabelOpt & - IGlOpt & { - glyph_first?: boolean; - }; - }; diff --git a/apps-lib/src/lib/types/context.ts b/apps-lib/src/lib/types/context.ts @@ -1,22 +0,0 @@ -import type { LocalCallbackColorMode, LocalCallbackGeocode, LocalCallbackGeocodeCurrent, LocalCallbackGuiAlert, LocalCallbackGuiConfirm, LocalCallbackImgBin, LocalCallbackPhotosAddMultiple, LocalCallbackPhotosUpload } from "$root"; -import type { I18nTranslateFunction, I18nTranslateLocale } from "@radroots/util"; - -export type ContextKeys = - | `lib`; - -export type ContextMap = { - lib: LibContext; -}; - -export type LibContext = { - ls: I18nTranslateFunction; - locale: I18nTranslateLocale; - lc_color_mode: LocalCallbackColorMode; - lc_gui_alert: LocalCallbackGuiAlert; - lc_gui_confirm: LocalCallbackGuiConfirm; - lc_geocode: LocalCallbackGeocode; - lc_photos_add: LocalCallbackPhotosAddMultiple; - lc_img_bin: LocalCallbackImgBin; - lc_geop_current: LocalCallbackGeocodeCurrent; - lc_photos_upload: LocalCallbackPhotosUpload; -}; -\ No newline at end of file diff --git a/apps-lib/src/lib/types/interface.ts b/apps-lib/src/lib/types/interface.ts @@ -1,228 +0,0 @@ -import type { IGlyph, IInput, IInputValue, ISelect, ITextArea } from "$root"; -import type { CallbackPromise, CallbackPromiseGeneric, EntryStyle, GlyphKey, LayerGlyphBasisKind, LoadingBlades, LoadingDimension, SvelteTransitionConfig, ThemeLayer } from "@radroots/util"; - -export type IDisabled = { - disabled: boolean | never; -}; - -export type IDisabledOpt = Partial<IDisabled>; - -export type IBasisOpt<T extends object> = T | undefined; - -export type IBasis<T> = { - basis: T; -}; - -export type ICb = { - callback: CallbackPromise | never; -}; - -export type ICbOpt = Partial<ICb>; - -export type ICbG<T> = { - callback: CallbackPromiseGeneric<T> | never; -}; - -export type ICbMouseEventOpt = ICbGOpt< - MouseEvent & { - currentTarget: EventTarget & HTMLImageElement; - } ->; - -export type ICbGOpt<T> = Partial<ICbG<T>>; - -export type ICl = { - classes: string | never; -}; - -export type IClOpt = Partial<ICl>; - -export type IClWrap = { - classes_wr: string | never; -}; - -export type IClOptWrap = Partial<IClWrap>; - -export type IId = { - id: string | never; -}; - -export type IIdOpt = Partial<IId>; - -export type IGl = { - glyph: IGlyph | never; -}; - -export type IGlOpt = Partial<IGl>; - -export type IGlyphKey = { - glyph: GlyphKey -}; - -export type ILy = { - layer: ThemeLayer | never; -}; - -export type ILyOpt = Partial<ILy>; - -export type ILableFieldsSwap = { - toggle: boolean; - on: IClOpt & { - value: string; - }, - off: IClOpt & { - value: string; - }, -}; - -export type ILabelSwap = { - swap: ILableFieldsSwap; -} - -export type ILabelTupFields = { - left?: ILableFields[]; - right?: ILableFields[]; -}; - -export type ILabelTup = { - label: ILabelTupFields; -}; - -export type ILableFields = & { - classes_wrap?: string - classes?: string; - kind?: LayerGlyphBasisKind; - hide_truncate?: boolean; - hide_active?: boolean; -} & ( - ({ - value: string; - } | ILabelSwap) - | IGl - ); - -export type ILabel = { - label: ILableFields; -}; - -export type ILabelOpt = Partial<ILabel>; - -export type ILoadSymbol = IClOpt & { - color?: 'white'; - blades?: LoadingBlades; - dim?: LoadingDimension; -}; - -export type IIdG<T extends string> = { - id: T | never; -}; - -export type IIdGOpt<T extends string> = Partial<IIdG<T>>; - -export type IIdWrap = { - id_wrap: string | never; -}; - -export type IIdWrapOpt = Partial<IIdWrap>; - -export type ILabelValue = { - label: IClOpt & { - value: string; - }; -}; - -export type ILabelDisplay = IIdWrapOpt & IClOpt & ILabelValue & ILyOpt & { - style?: EntryStyle; -}; - - -export type ILoading = { - loading: boolean | never; -}; - -export type ILoadingOpt = Partial<ILoading>; - -export type IEntryWrap = IClOpt & IIdOpt & ILyOpt & { - style?: EntryStyle; - style_a?: true; - no_pad?: true; - fade?: { - in?: SvelteTransitionConfig; - out?: SvelteTransitionConfig; - }; -} - -export type IEntryLine = ILoadingOpt & { - wrap?: IEntryWrap; - el: IInputValue<string>; - notify_inline?: { - glyph: GlyphKey | IGlyph; - }; -}; - -export type IEntryLineIdb = ILoadingOpt & { - wrap?: IEntryWrap; - el: IInput<string>; - notify_inline?: { - glyph: GlyphKey | IGlyph; - }; -}; - -export type IEntryLineSelectIdb = ILoadingOpt & { - wrap?: IEntryWrap; - el_input: IInput<string>; - el_sel: ISelect; - /*notify_inline?: { - glyph: GlyphKey | IGlyph; - };*/ -}; - -export type IEntryMultiLine = { - wrap?: IEntryWrap; - el: ITextArea; - notify_inline?: { - glyph: GlyphKey | IGlyph; - }; -} - -export type IEnvelopeLower = { - visible: boolean; - close: CallbackPromise; - full_cover?: boolean; - label_close?: string | true; -}; - -export type IButtonRound = IClOpt & ILoadingOpt & { - label: string; - callback: CallbackPromise; -}; - -export type INavigationRoutePreventRouteNav = { - prevent_route?: { - callback: CallbackPromise; - }; -}; - -export type INavigationRoutePreventRoute = { - prevent_route: CallbackPromise; -}; - -export type IImage = IIdOpt & IClOpt & { - src?: string; - alt?: string; -}; - -export type IImageBlob = IIdOpt & IClOpt & { - data: Uint8Array | undefined; - alt?: string; -}; - -export type IImageSource = IIdOpt & IClOpt & { - src?: string; - alt?: string; -}; - -export type IImagePath = Omit<IImage, 'src'> & { - path?: string; -}; - diff --git a/apps-lib/src/lib/types/lib.ts b/apps-lib/src/lib/types/lib.ts @@ -1,26 +1 @@ -import type { INavigationRoute, ISelectOption } from "$root"; -import type { CallbackPromise, CallbackPromiseFull, CallbackPromiseGeneric, CallbackPromiseResult, GeocoderReverseResult, GeolocationPoint, IClientGeolocationPosition, MediaImageUploadResult, NavigationParamTuple } from "@radroots/util"; - -export type CallbackRoute<T extends string> = CallbackPromise | INavigationRoute<T>; - -export type NavigationRouteParamId = `id`; -export type NavigationRouteParamField = `field`; -export type NavigationRouteParamRef = `ref`; -export type NavigationRouteParamLat = `lat`; -export type NavigationRouteParamLng = `lng`; -export type NavigationRouteParamNostrPublicKey = `key_nostr`; -export type NavigationRouteParamKey = NavigationRouteParamId | NavigationRouteParamField | NavigationRouteParamRef | NavigationRouteParamLat | NavigationRouteParamLng | NavigationRouteParamNostrPublicKey; -export type NavigationRouteParamTuple = NavigationParamTuple<NavigationRouteParamKey>; -export type NavigationPreviousParam<T extends string> = { route: T, label?: string; params?: NavigationRouteParamTuple[] } - -export type LocalCallbackColorMode = CallbackPromiseGeneric<ISelectOption<string>> -export type LocalCallbackGuiAlert = CallbackPromiseFull<string, boolean>; -export type LocalCallbackGuiConfirm = CallbackPromiseFull<string | { message: string; ok?: string; cancel?: string }, boolean>; -export type LocalCallbackGeocode = CallbackPromiseFull<GeolocationPoint, GeocoderReverseResult | undefined>; -export type LocalCallbackGeocodeCurrent = CallbackPromiseResult<IClientGeolocationPosition>; -export type LocalCallbackImgBin = CallbackPromiseFull<string, Uint8Array | undefined>; -export type LocalCallbackPhotosAdd = CallbackPromiseResult<string>; -export type LocalCallbackPhotosAddMultiple = CallbackPromiseResult<string[]>; -export type LocalCallbackPhotosUpload = CallbackPromiseFull<{ url: string, path: string }, MediaImageUploadResult | undefined>; - -export type MaplibreMap = maplibregl.Map; -\ No newline at end of file +export type ThemeMode = 'light' | 'dark'; +\ No newline at end of file diff --git a/apps-lib/src/lib/types/ndk.ts b/apps-lib/src/lib/types/ndk.ts @@ -0,0 +1,3 @@ +import type { NDKEvent } from "@nostr-dev-kit/ndk"; + +export type LibNdkEvent = NDKEvent; +\ No newline at end of file diff --git a/apps-lib/src/lib/types/view/farm.ts b/apps-lib/src/lib/types/view/farm.ts @@ -1,34 +0,0 @@ -import type { FarmExtended, GeocoderReverseResult, GeolocationPoint } from "@radroots/util"; - -export type IViewFarmsData = { - list: FarmExtended[]; -}; - -export type IViewFarmsDetailsData = FarmExtended; - -export type IViewFarmsProductsAddData = FarmExtended; - -export type IViewFarmsProductsAddSubmitPayload = { - product: string; - process: string; - description: string; - price_amount: number; - price_currency: string; - price_quantity_unit: string; - photos: string[]; - quantity_amount: number; - quantity_unit: string; - quantity_label: string; - geolocation_point: GeolocationPoint; - geocode_result: GeocoderReverseResult; -}; - -export type IViewFarmsAddSubmission = { - farm_name: string; - farm_area?: number; - farm_area_unit?: string; - farm_contact_name?: string; - geolocation_point: GeolocationPoint; - geocode_result: GeocoderReverseResult; -}; - diff --git a/apps-lib/src/lib/types/view/lib.ts b/apps-lib/src/lib/types/view/lib.ts @@ -1,11 +0,0 @@ -import type { CallbackPromiseGeneric } from "@radroots/util"; - -export type IViewHomeData = {}; - -export type IViewOnMount<TypeCallbackParam> = { - on_mount: CallbackPromiseGeneric<TypeCallbackParam>; -}; - -export type IViewOnDestroy<TypeCallbackParam> = { - on_destroy: CallbackPromiseGeneric<TypeCallbackParam>; -}; diff --git a/apps-lib/src/lib/types/view/profile.ts b/apps-lib/src/lib/types/view/profile.ts @@ -1,14 +0,0 @@ -export type IViewProfileData = { - public_key: string; - name?: string; - display_name?: string; - about?: string; - picture?: string; -}; - -export type ViewProfileEditFieldKey = `name` | `display_name` | `about`; - -export type IViewProfileEditData = { - public_key: string; - field: ViewProfileEditFieldKey; -}; diff --git a/apps-lib/src/lib/util/carousel.ts b/apps-lib/src/lib/util/carousel.ts @@ -1,87 +0,0 @@ -import { - carousel_active, - carousel_index, - carousel_index_max, - carousel_num, - get_store -} from "$root"; -import { exe_iter } from "@radroots/util"; - -const CAROUSEL_DELAY_MS = 150; - -const get_slide_container = <T extends string>( - view: T, -): Element | undefined => { - const el = document.querySelector( - `[data-carousel-container="${view}"]`, - ); - return el ? el : undefined; -}; - -const get_slide_item = <T extends string>(view: T): Element | undefined => { - const el = document.querySelector(`[data-carousel-item="${view}"]`); - return el ? el : undefined; -}; - -const carousel_dec_handler = async <T extends string>( - view: T, -): Promise<void> => { - const $carousel_active = get_store(carousel_active); - if ($carousel_active) return; - carousel_active.set(true); - const slide_item = get_slide_item<T>(view); - const slide_container = get_slide_container<T>(view); - if (slide_container && slide_item) { - const slide_w = slide_item?.clientWidth || 0; - slide_container.scrollLeft -= slide_w; - const $carousel_index = get_store(carousel_index); - carousel_index.set(Math.max($carousel_index - 1, 0)); - } - carousel_active.set(false); -}; - -const carousel_inc_handler = async <T extends string>( - view: T, -): Promise<void> => { - const $carousel_active = get_store(carousel_active); - if ($carousel_active) return; - carousel_active.set(true); - const slide_item = get_slide_item<T>(view); - const slide_container = get_slide_container<T>(view); - if (slide_container && slide_item) { - const slide_w = slide_item?.clientWidth || 0; - slide_container.scrollLeft += slide_w; - const $carousel_index = get_store(carousel_index); - const $carousel_index_max = get_store(carousel_index_max); - carousel_index.set( - Math.min($carousel_index + 1, $carousel_index_max), - ); - } - carousel_active.set(false); -}; - -export const carousel_inc = async <T extends string>( - view: T, - duration: number = CAROUSEL_DELAY_MS -): Promise<void> => { - const $carousel_num = get_store(carousel_num); - carousel_num.set(1); - await exe_iter(async () => carousel_inc_handler(view), $carousel_num, duration); -}; - - -export const carousel_dec = async <T extends string>( - view: T, - duration: number = CAROUSEL_DELAY_MS -): Promise<void> => { - const $carousel_num = get_store(carousel_num); - carousel_num.set(1); - await exe_iter(async () => carousel_dec_handler(view), $carousel_num, duration); -}; - -export const carousel_init = async <T extends string>(view: T, num_max: number): Promise<void> => { - await carousel_dec(view); - carousel_index.set(0); - carousel_index_max.set(num_max); - carousel_num.set(1); -}; diff --git a/apps-lib/src/lib/util/casl.ts b/apps-lib/src/lib/util/casl.ts @@ -1,20 +0,0 @@ -import { casl_i, casl_imax, get_store } from "$root"; - -export const casl_inc = async (opts?: 'noflow'): Promise<void> => { - const $casl_i = get_store(casl_i); - const $casl_imax = get_store(casl_imax); - if (opts === 'noflow' && $casl_i < $casl_imax) casl_i.set($casl_i + 1); - else casl_i.set(($casl_i + 1) % ($casl_imax + 1)); -}; - -export const casl_dec = async (opts?: 'noflow'): Promise<void> => { - const $casl_i = get_store(casl_i); - const $casl_imax = get_store(casl_imax); - if (opts === 'noflow' && $casl_i > 0) casl_i.set($casl_i - 1); - else casl_i.set(($casl_i - 1 + ($casl_imax + 1)) % ($casl_imax + 1)); -}; - -export const casl_init = (index_curr: number, index_max: number): void => { - casl_i.set(index_curr); - casl_imax.set(index_max); -}; diff --git a/apps-lib/src/lib/util/context/lib.ts b/apps-lib/src/lib/util/context/lib.ts @@ -1,10 +0,0 @@ -import type { ContextMap } from "$lib/types/context"; -import { getContext, setContext } from "svelte"; - -export const get_context = <K extends keyof ContextMap>(key: K): ContextMap[K] => { - return getContext(key) as ContextMap[K]; -}; - -export const set_context = <K extends keyof ContextMap>(key: K, value: ContextMap[K]): void => { - setContext(key, value); -}; -\ No newline at end of file diff --git a/apps-lib/src/lib/util/idb.ts b/apps-lib/src/lib/util/idb.ts @@ -1,54 +0,0 @@ -import { browser } from "$app/environment"; -import { fmt_id } from "$root"; - -//@ts-ignore -const idb_name = import.meta.env.VITE_PUBLIC_IDB_NAME; -if (!idb_name) throw new Error('Error: VITE_PUBLIC_IDB_NAME is required'); - -export let idb: Keyva; -if (browser) idb = new Keyva({ name: idb_name }); - -export const idb_init = async (): Promise<void> => { - if (!browser) return; - const range = Keyva.prefix(`*`); - const idb_list = await idb.each({ range }, `keys`); - await Promise.all(idb_list.map((i) => idb.delete(i))); -}; - -export const idb_init_page = async (): Promise<void> => { - if (!browser) return; - const idb_pref = fmt_id(); - const range = Keyva.prefix(idb_pref); - const idb_list = await idb.each({ range }, `keys`); - await Promise.all(idb_list.map((i) => idb.delete(i))); -}; - -export const idb_sync = async (list: [string, string][]): Promise<void> => { - if (!browser) return; - for (const [key, val] of list) await idb.set(key, val); -}; - -export class IdbLib<T extends string> { - private _idb: Keyva; - - constructor(kv: Keyva) { - this._idb = kv; - } - public init = async () => { - await idb_init_page(); - } - - public save = async (key: T, value: string) => { - await this._idb.set(fmt_id(key), value); - } - - public read = async (key: T): Promise<string | undefined> => { - const result = await this._idb.get<string>(fmt_id(key)); - if (result) return result; - return undefined; - } - - public del = async (key: T) => { - await this._idb.delete(fmt_id(key)); - } -} -\ No newline at end of file diff --git a/apps-lib/src/lib/util/lib.ts b/apps-lib/src/lib/util/lib.ts @@ -1,106 +0,0 @@ -import { browser } from "$app/environment"; -import { goto } from "$app/navigation"; -import { page } from "$app/state"; -import { win_h, win_w, type CallbackRoute, type NavigationRouteParamKey } from "$root"; -import type { ColorMode, ThemeKey } from "@radroots/theme"; -import { encode_route, fmt_geometry_point_coords, fmt_price, geo_point_to_geometry, parse_currency_marker, type GeolocationPoint, type GeometryPoint, type IErrorCatchCallback } from "@radroots/util"; -import { get } from "svelte/store"; - -export const get_store = get; - -export const theme_set = (theme_key: ThemeKey, color_mode: ColorMode): void => { - const data_theme = `${theme_key}_${color_mode}`; - document.documentElement.setAttribute("data-theme", data_theme); -}; - -export const fmt_id = (id?: string): string => { - if (!browser) return ``; - const pref = location?.pathname.slice(1, -1).replaceAll(`-`, `_`).replaceAll(`/`, `-`).replaceAll(`--`, `-`); - return `*${pref}${id ? `-${id}` : ``}` -}; - -export const catch_err = async (e: unknown, func: string, callback: (opts: IErrorCatchCallback) => Promise<void>): Promise<void> => { - let name = ``; - let message = ``; - let stack = ``; - let url = ``; - if (e instanceof Error) { - name = e.name; - message = e.message; - stack = e.stack || ``; - url = page.url.pathname; - } - await callback({ name, message, stack, url, func }); -}; - -export const handle_err = async (e: unknown, fcall: string): Promise<void> => { - try { - return void await catch_err(e, fcall, async (opts) => { - console.log(`handle_err e `, e) - console.log(JSON.stringify(opts, null, 4), `handle_err opts`) - }); - } catch (e) { - console.log(`(handle_err) `, e) - } -}; - -export const callback_route = async <T extends string>(callback_route: CallbackRoute<T>): Promise<void> => { - if (`route` in callback_route) { - if (typeof callback_route.route === `string`) return void await goto(callback_route.route); - else return void await goto( - encode_route<string, NavigationRouteParamKey>( - callback_route.route[0], - callback_route.route[1], - ), - ); - } - return void await callback_route(); -}; - -export const query_params_clear = async (): Promise<void> => { - page.url && await goto(page.url.pathname, { replaceState: true }) -}; - -export const lib_fmt_price = (locale: string, value: string, currency: string): string => { - return fmt_price(locale, value, currency); -}; - -export const lib_parse_currency_marker = (locale: string, currency: string): string => { - return parse_currency_marker(locale, currency); -}; - -export const lib_fmt_geometry_point_coords = (locale: string, point: GeometryPoint): string => { - return fmt_geometry_point_coords(point, locale); -}; - -export const loc_fmt_geo_point_coords = (locale: string, geo_point: GeolocationPoint): string => { - const point = geo_point_to_geometry(geo_point); - if (!point) return ``; //@todo - return fmt_geometry_point_coords(point, locale); -}; - - -export const view_effect = <T extends string>(view: T): void => { - if (!browser) return; - for (const el of document.querySelectorAll(`[data-view]`)) { - if (el.getAttribute(`data-view`) !== view) el.classList.add(`hidden`) - else el.classList.remove(`hidden`) - } -}; - -export const window_set = (): void => { - if (!browser) return; - win_h.set(window.innerHeight); - win_w.set(window.innerWidth); -}; - -export const geop_is_valid = (point?: GeolocationPoint): boolean => { - if (!point) return false; - return !(point.lat === 0 && point.lng === 0); -}; -export const geop_init = (): GeolocationPoint => ({ lat: 0, lng: 0 }); - -export const focus_map_marker = (): void => { - const el = document.querySelector(".maplibregl-marker"); - if (el instanceof HTMLElement) el.click(); -}; -\ No newline at end of file diff --git a/apps-lib/src/lib/util/nostr/nostr-poll-relays.ts b/apps-lib/src/lib/util/nostr/nostr-poll-relays.ts @@ -1,72 +0,0 @@ -import { get_store, handle_err, ndk_user, nostr_poll_relays_attempts, nostr_poll_relays_attempts_max, nostr_poll_relays_stop, nostr_relays_connected } from "$root"; -import { type CallbackPromiseFull, type CallbackPromiseGeneric, type ErrorMessage, type I18nTranslateFunction, type IHttpResponse } from "@radroots/util"; -import { lib_nostr_relay_build_information_document, type NostrRelayInformationDocumentFields } from "@radroots/utils-nostr"; - -export const nostr_poll_relays_retry_handler = async (callback: () => Promise<any>) => { - let current_count = 0; - const attempts_max = get_store(nostr_poll_relays_attempts_max); - - nostr_poll_relays_attempts.set(0); - nostr_poll_relays_stop.set(false); - - const exe = async () => { - if (get_store(nostr_poll_relays_stop)) return; - console.log(`[nostr poll relays] attempt ${current_count}`) - try { - await callback(); - } catch (e) { - current_count += 1; - nostr_poll_relays_attempts.set(current_count); - if (current_count < attempts_max) { - await new Promise((res) => setTimeout(res, 2000)); - await exe(); - } else nostr_poll_relays_stop.set(true); - } - }; - - await exe(); -}; - -export const nostr_poll_relays_handler = async (opts: { - ls: I18nTranslateFunction; - callback_alert: CallbackPromiseGeneric<string>; - callback_relay_urls: CallbackPromiseFull<string, { id: string; url: string; }[]>; - callback_fetch_document: CallbackPromiseFull<string, IHttpResponse | ErrorMessage<string>>; - callback_set_relay_document: CallbackPromiseGeneric<{ url: string; doc: NostrRelayInformationDocumentFields; }>; -}): Promise<void> => { - try { - const { ls, callback_alert, callback_relay_urls, callback_fetch_document, callback_set_relay_document } = opts; - const $ls = get_store(ls); - const $ndk_user = get_store(ndk_user); - const public_key = $ndk_user?.pubkey; - if (!public_key) return void await callback_alert(`${$ls(`error.client.nostr.missing_public_key`)}`); - const $nostr_relays_connected = get_store(nostr_relays_connected); - - const relay_urls = await callback_relay_urls(public_key); - const unconnected_relays = relay_urls.filter( - (i) => !$nostr_relays_connected.includes(i.id), - ); - if (unconnected_relays.length === 0) return void nostr_poll_relays_stop.set(true); - - for (const relay of unconnected_relays) { - const res = await callback_fetch_document(relay.url); - if (`err` in res) continue; - else if (res.status === 200 && res.data) { - const doc = lib_nostr_relay_build_information_document(res.data); - if (!doc) continue; - await callback_set_relay_document({ url: relay.url, doc }); - nostr_relays_connected.set( - Array.from( - new Set([ - ...$nostr_relays_connected, - relay.id, - ]), - ), - ); - } - - } - } catch (e) { - await handle_err(e, `nostr_poll_relays_handler`); - } -}; diff --git a/apps-lib/src/lib/util/nostr/nostr-sync.ts b/apps-lib/src/lib/util/nostr/nostr-sync.ts @@ -1,63 +0,0 @@ -import { get_store, handle_err, ndk_user, nostr_sync, nostr_sync_attempts, nostr_sync_attempts_max, nostr_sync_prevent, nostr_sync_stop } from "$root"; -import { throw_err, type CallbackPromiseFull, type CallbackPromiseGeneric, type I18nTranslateFunction } from "@radroots/util"; -import type { INostrMetadata } from "@radroots/utils-nostr"; - -export const nostr_sync_retry_handler = async (callback: () => Promise<any>) => { - let current_count = 0; - const attempts_max = get_store(nostr_sync_attempts_max); - - nostr_sync_attempts.set(0); - nostr_sync_stop.set(false); - - const exe = async () => { - if (get_store(nostr_sync_stop)) return; - console.log(`[nostr sync] attempt ${current_count}`) - try { - await callback(); - } catch (e) { - current_count += 1; - nostr_sync_attempts.set(current_count); - if (current_count < attempts_max) { - await new Promise((res) => setTimeout(res, 500)); - await exe(); - } else nostr_sync_stop.set(true); - } - }; - - await exe(); -}; - -export const nostr_sync_handler = async (opts: { - ls: I18nTranslateFunction; - callback_alert: CallbackPromiseGeneric<string>; - callback_confirm: CallbackPromiseFull<string, boolean>; - callback_metadata: CallbackPromiseFull<string, INostrMetadata>; - callback_relay_urls: CallbackPromiseFull<string, { id: string; url: string; }[]>; -}): Promise<void> => { - try { - const { ls, callback_alert, callback_confirm, callback_metadata, callback_relay_urls } = opts; - const $ls = get_store(ls); - const $ndk_user = get_store(ndk_user); - const public_key = $ndk_user.pubkey; - if (!public_key) return void await callback_alert(`${$ls(`error.client.nostr.missing_public_key`)}`); - - const $nostr_sync_prevent = get_store(nostr_sync_prevent); - if ($nostr_sync_prevent) { - const confirm = await callback_confirm(`${$ls(`error.client.nostr.sync_disabled`)}`); - if (confirm) nostr_sync_prevent.set(false); - else return; - } - - const metadata = await callback_metadata(public_key); - const ev = await nostr_sync.metadata({ metadata }); - if (`err` in ev) throw_err(ev); - await ev.publish(); - - const relays = await callback_relay_urls(public_key); - for (const relay of relays) { - //@todo - } - } catch (e) { - await handle_err(e, `nostr_sync_handler`); - } -}; -\ No newline at end of file diff --git a/apps-lib/src/lib/util/service/nostr-event-classified.ts b/apps-lib/src/lib/util/service/nostr-event-classified.ts @@ -1,274 +0,0 @@ -import type { NDKEvent } from '@nostr-dev-kit/ndk'; -import type NDKSvelte from '@nostr-dev-kit/ndk-svelte'; -import { derived, writable, type Readable, type Unsubscriber, type Writable } from 'svelte/store'; - -const E_REF = 'e_ref'; - -export interface NostrEventsClassifiedBundle { - event: NDKEvent; - job_results: NDKEvent[]; - job_feedback: NDKEvent[]; - loading: boolean; - on_job_result?: (callback: (ev: NDKEvent) => void) => Unsubscriber; -} - -export type NostrEventClassifiedSubscriptionServiceBundleStore = Readable<NostrEventsClassifiedBundle>; -export type NostrEventClassifiedSubscriptionServiceStore = Readable<Map<string, NostrEventsClassifiedBundle>>; -export type NostrEventClassifiedSubscriptionServiceOnJobResult = Readable<NDKEvent | undefined>; - -export class NostrEventClassifiedSubscriptionService { - private ndk: NDKSvelte; - private subscription: ReturnType<NDKSvelte['subscribe']> | null = null; - private filter_subscription: Unsubscriber | null = null; - - private filter_authors: Writable<string[] | undefined> = writable(); - private filter_kinds: Writable<number[]> = writable([30402, 6300, 7000]); - - private events_list: Writable<NDKEvent[]> = writable([]); - private job_results: Writable<NDKEvent[]> = writable([]); - private job_feedback: Writable<NDKEvent[]> = writable([]); - - private loading_map: Writable<Record<string, boolean>> = writable({}); - public loading: Readable<Record<string, boolean>> = this.loading_map; - - private timeouts: Map<string, number> = new Map(); - - private bundle_map: Map<string, Writable<NostrEventsClassifiedBundle>> = new Map(); - - private job_results_notification: Writable<NDKEvent | undefined> = writable(undefined); - public readonly on_job_result: NostrEventClassifiedSubscriptionServiceOnJobResult = this.job_results_notification; - - public store: NostrEventClassifiedSubscriptionServiceStore; - - private load_complete = false; - - constructor(ndk: NDKSvelte) { - this.ndk = ndk; - - this.store = derived( - [this.events_list, this.job_results, this.job_feedback, this.loading_map], - ([$events, $results, $feedback, $loading]) => { - const map = new Map<string, NostrEventsClassifiedBundle>(); - - for (const ev of $events) { - if (!ev.id) continue; - - const bundle: NostrEventsClassifiedBundle = { - event: ev, - job_results: [], - job_feedback: [], - loading: Boolean($loading[ev.id]), - on_job_result: (callback: (ev: NDKEvent) => void): Unsubscriber => { - const ev_id = ev.id!; - const subscription_start_time = Date.now(); - - const unsubscribe = this.job_results.subscribe((list: NDKEvent[]) => { - for (const e of list) { - const ref_id = e.tags?.find(([tag]) => tag === E_REF)?.[1]; - const ev_created_at = (e.created_at ?? 0) * 1000; - if (ref_id === ev_id && ev_created_at > subscription_start_time) callback(e); - } - }); - - return unsubscribe; - }, - }; - - map.set(ev.id, bundle); - - if (!this.bundle_map.has(ev.id)) { - this.bundle_map.set(ev.id, writable(bundle)); - } else { - this.bundle_map.get(ev.id)!.set(bundle); - } - } - - for (const ev of $results) { - const ref = ev.tags?.find(([tag]) => tag === E_REF)?.[1]; - if (ref && map.has(ref)) { - map.get(ref)!.job_results.push(ev); - } - } - - for (const ev of $feedback) { - const ref = ev.tags?.find(([tag]) => tag === E_REF)?.[1]; - if (ref && map.has(ref)) { - map.get(ref)!.job_feedback.push(ev); - } - } - - for (const [id, bundle] of map.entries()) { - if (this.bundle_map.has(id)) { - this.bundle_map.get(id)!.set(bundle); - } - } - - return map; - } - ); - - this.filter_subscription = derived( - [this.filter_authors, this.filter_kinds], - ([$authors, $kinds]) => ({ authors: $authors, kinds: $kinds }) - ).subscribe(({ authors, kinds }) => { - this.restart_subscription(authors, kinds); - }); - - this.restart_subscription(undefined, [30402, 6300, 7000]); - } - - public set_filter_authors(authors: string[]): void { - this.filter_authors.set(authors); - } - - public set_filter_kinds(kinds: number[]): void { - this.filter_kinds.set(kinds); - } - - public get_event_bundle(eventId: string): NostrEventClassifiedSubscriptionServiceBundleStore | undefined { - if (!this.bundle_map.has(eventId)) { - return undefined; - } - return this.bundle_map.get(eventId)!; - } - - public async await_job_request(event_id: string): Promise<NDKEvent> { - this.loading_map.update(states => ({ ...states, [event_id]: true })); - this.clear_timeout(event_id); - - try { - const result = await new Promise<NDKEvent>((resolve, reject) => { - let unsubscribe_res: Unsubscriber; - let unsubscribe_fb: Unsubscriber; - let seen_jobres = false; - let seen_jobfb = false; - - const cleanup_subs = () => { - unsubscribe_res(); - unsubscribe_fb(); - }; - - const on_response = (ev: NDKEvent) => { - cleanup_subs(); - this.clear_timeout(event_id); - resolve(ev); - setTimeout(() => { - this.loading_map.update(states => { - const { [event_id]: _, ...rest } = states; - return rest; - }); - }, 0); - }; - - unsubscribe_res = this.job_results.subscribe(list => { - if (!seen_jobres) { seen_jobres = true; return; } - const ev = list.find(e => - e.tags?.find(([t]) => t === E_REF)?.[1] === event_id - ); - if (ev) on_response(ev); - }); - - unsubscribe_fb = this.job_feedback.subscribe(list => { - if (!seen_jobfb) { seen_jobfb = true; return; } - const ev = list.find(e => - e.tags?.find(([t]) => t === E_REF)?.[1] === event_id - ); - if (ev) on_response(ev); - }); - - const timeout_id = window.setTimeout(() => { - cleanup_subs(); - this.loading_map.update(states => { - const { [event_id]: _, ...rest } = states; - return rest; - }); - this.clear_timeout(event_id); - reject(new Error(`Timeout waiting for job result for event ${event_id}`)); - }, 7000); - - this.timeouts.set(event_id, timeout_id); - }); - - return result; - } catch (err) { - this.loading_map.update(states => { - const { [event_id]: _, ...rest } = states; - return rest; - }); - throw err; - } - } - - private restart_subscription(authors?: string[], kinds: number[] = []): void { - if (this.subscription) { - this.subscription.stop(); - this.subscription = null; - } - - this.events_list.set([]); - this.job_results.set([]); - this.job_feedback.set([]); - this.clear_all_loading(); - - this.load_complete = false; - - const filter = { kinds, ...(authors ? { authors } : {}) }; - const sub = this.ndk.subscribe(filter, { closeOnEose: false }); - - sub.on('event', (event: NDKEvent) => { - console.log(`event `, event.kind, event.id) - switch (event.kind) { - case 30402: - event.tags.forEach(i => { - if (i[0].includes(`price`) || i[0].includes(`quantity`)) console.log(i.join(`, `)) - }) - this.events_list.update(arr => [...arr, event]); - break; - case 6300: - this.job_results.update(arr => [...arr, event]); - if (this.load_complete) { - this.job_results_notification.set(event); - } - break; - case 7000: - this.job_feedback.update(arr => [...arr, event]); - break; - } - }); - - sub.on('eose', () => { - this.load_complete = true; - }); - - sub.start(); - this.subscription = sub; - } - - private clear_timeout(event_id: string) { - const to = this.timeouts.get(event_id); - if (to !== undefined) { - clearTimeout(to); - this.timeouts.delete(event_id); - } - } - - private clear_all_loading() { - for (const to of this.timeouts.values()) { - clearTimeout(to); - } - this.timeouts.clear(); - this.loading_map.set({}); - } - - public destroy(): void { - if (this.subscription) { - this.subscription.stop(); - this.subscription = null; - } - if (this.filter_subscription) { - this.filter_subscription(); - this.filter_subscription = null; - } - this.clear_all_loading(); - } -} diff --git a/apps-lib/src/lib/util/service/nostr-sync.ts b/apps-lib/src/lib/util/service/nostr-sync.ts @@ -1,42 +0,0 @@ -import { get_store, handle_err, ndk, ndk_user } from "$root"; -import type { NDKEvent, NDKUser } from "@nostr-dev-kit/ndk"; -import type NDKSvelte from "@nostr-dev-kit/ndk-svelte"; -import { err_msg, type ErrorMessage } from "@radroots/util"; -import { ndk_event_metadata, type INostrMetadata } from "@radroots/utils-nostr"; - -export type INostrSyncServiceMetadata = { - metadata: INostrMetadata; -}; - -export type INostrSyncService = { - metadata: (opts: INostrSyncServiceMetadata) => Promise<NDKEvent | ErrorMessage<string>>; -}; - -export class NostrSyncService implements INostrSyncService { - constructor() { } - - private config = (): { $ndk: NDKSvelte; $ndk_user: NDKUser } => { - const $ndk = get_store(ndk); - const $ndk_user = get_store(ndk_user); - return { $ndk, $ndk_user }; - } - - public metadata = async (opts: INostrSyncServiceMetadata): Promise<NDKEvent | ErrorMessage<string>> => { - try { - const { $ndk: ndk, $ndk_user: ndk_user } = this.config(); - const { metadata: data } = opts; - const ev = await ndk_event_metadata({ - ndk, - ndk_user, - data, - }); - if (ev) return ev; - return err_msg(`error.nostr.sync.metadata.missing_event`); - } catch (e) { - await handle_err(e, `metadata`); - return err_msg(`error.nostr.sync.failure`); //@todo - } - } -} - -export const nostr_sync = new NostrSyncService(); -\ No newline at end of file diff --git a/apps-lib/src/lib/util/styles.ts b/apps-lib/src/lib/util/styles.ts @@ -1,45 +0,0 @@ -import type { IToastKind } from "$lib/types/component"; -import type { AppLayoutKey, GeometryGlyphDimension, LoadingDimension } from "@radroots/util"; - -export const glyph_style_map: Map<GeometryGlyphDimension, { gl_1: number; dim_1?: number; }> = new Map([ - ["xs--", { gl_1: 12 }], - ["xs-", { gl_1: 12, dim_1: 17 }], - ["xs", { gl_1: 15, dim_1: 18 }], - ["xs+", { gl_1: 18, dim_1: 20 }], - ["sm-", { gl_1: 19, dim_1: 22 }], - ["sm", { gl_1: 20, dim_1: 24 }], - ["sm+", { gl_1: 21 }], - ["md-", { gl_1: 23 }], - ["md", { gl_1: 24 }], - ["md+", { gl_1: 26 }], - ["lg-", { gl_1: 27 }], - ["lg", { gl_1: 28 }], - ["xl", { gl_1: 30 }], - ["xl+", { gl_1: 40 }], -]); - -export const loading_style_map: Map<LoadingDimension, { dim_1: number; gl_2: number }> = new Map([ - ["glyph-send-button", { dim_1: 20, gl_2: 20 }], - ["xs", { dim_1: 12, gl_2: 12 }], - ["sm", { dim_1: 16, gl_2: 16 }], - ["md", { dim_1: 20, gl_2: 20 }], - ["lg", { dim_1: 28, gl_2: 28 }], - ["xl", { dim_1: 36, gl_2: 36 }], -]); - -export const toast_layout_map: Map<AppLayoutKey, string> = new Map([ - [`ios0`, `pt-8`], - [`ios1`, `pt-16`], - [`webm0`, `pt-8`], - [`webm1`, `pt-16`], -]); - -export const toast_style_map: Map<IToastKind, { inner: string; outer: string }> = new Map([ - [ - `simple`, - { - inner: `justify-center`, - outer: `min-h-toast_min w-full px-4 rounded-2xl shadow-sm`, - }, - ], -]); -\ No newline at end of file diff --git a/apps-lib/src/lib/util/validation/farm.ts b/apps-lib/src/lib/util/validation/farm.ts @@ -1,28 +0,0 @@ -import { dev } from "$app/environment"; -import type { IViewFarmsAddSubmission, IViewFarmsProductsAddSubmitPayload } from "$lib/types/view/farm"; -import { form_fields, schema_geocode_result, schema_geolocation_point, util_rxp, zf_numf_pos, zf_numi_pos, zf_price } from "@radroots/util"; -import { z } from "zod"; - -export const schema_view_farms_add_submission: z.ZodSchema<IViewFarmsAddSubmission> = z.object({ - farm_name: z.string().regex(form_fields.farm_name.validate), - farm_area: zf_numf_pos.optional(), - farm_area_unit: z.string().regex(form_fields.area_unit.validate).optional(), - farm_contact_name: z.string().regex(form_fields.contact_name.validate).optional(), - geolocation_point: schema_geolocation_point, - geocode_result: schema_geocode_result, -}); - -export const schema_view_farms_products_add_submission: z.ZodSchema<IViewFarmsProductsAddSubmitPayload> = z.object({ - product: z.string().regex(form_fields.product_key.validate), - process: z.string().regex(form_fields.product_process.validate), - description: z.string().regex(form_fields.product_description.validate), - price_amount: zf_price, - price_currency: z.string().regex(form_fields.price_currency.validate), - price_quantity_unit: z.string().regex(form_fields.quantity_unit.validate), - photos: z.array(z.string().regex(dev ? util_rxp.url_image_upload_dev : util_rxp.url_image_upload)), - quantity_amount: zf_numi_pos, - quantity_unit: z.string().regex(form_fields.quantity_unit.validate), - quantity_label: z.string().regex(form_fields.quantity_label.validate), - geolocation_point: schema_geolocation_point, - geocode_result: schema_geocode_result, -}); -\ No newline at end of file diff --git a/apps-lib/src/lib/util/view.ts b/apps-lib/src/lib/util/view.ts @@ -1,12 +0,0 @@ -import type { ViewProfileEditFieldKey } from "$root"; - -export const parse_view_profile_field_key = (val?: string | null): ViewProfileEditFieldKey | undefined => { - switch (val) { - case `name`: - case `display_name`: - case `about`: - return val; - default: - return undefined; - } -}; -\ No newline at end of file diff --git a/apps-lib/src/lib/utils/idb/lib.ts b/apps-lib/src/lib/utils/idb/lib.ts @@ -0,0 +1,87 @@ +import { browser } from '$app/environment'; +import { fmt_id } from '../lib'; + +const IDB_NAME = import.meta.env.VITE_PUBLIC_IDB_NAME; +if (!IDB_NAME) throw new Error('VITE_PUBLIC_IDB_NAME is required'); + + +let _kv: Keyva | null = null; +export function get_idb(): Keyva { + if (!browser) throw new Error('IndexedDB not available on server'); + if (!_kv) _kv = new Keyva({ name: IDB_NAME }); + return _kv; +} + +export class IdbLib< + CKey extends string, + CMap extends Record<CKey, any>, + SKey extends string, + SMap extends Record<SKey, any> +> { + private get kv(): Keyva { + return get_idb(); + } + + public async save_global(key: CKey, value: CMap[CKey]): Promise<void> { + await this.kv.set(key, value); + } + + public async read_global<K extends CKey>(key: K): Promise<CMap[K] | undefined> { + const result = await this.kv.get<CMap[K]>(key); + return result ? result : undefined; + } + + public async del_global(key: CKey): Promise<void> { + await this.kv.delete(key); + } + + public async list_global(): Promise<Array<[CKey, CMap[CKey]]>> { + const entries = await this.kv.each<CMap[CKey]>(); + return entries.map(([rk, v]) => [rk as CKey, v]); + } + + private keyof(key: SKey): string { + return fmt_id(key); + } + + public async save(key: SKey, value: SMap[SKey]): Promise<void> { + await this.kv.set(this.keyof(key), value); + } + + public async read(key: SKey): Promise<SMap[SKey] | undefined> { + const result = await this.kv.get<SMap[SKey]>(this.keyof(key)); + return result ? result : undefined; + } + + public async del(key: SKey): Promise<void> { + await this.kv.delete(this.keyof(key)); + } + + public async list(): Promise<Array<[SKey, SMap[SKey]]>> { + const prefix = fmt_id(); + const range = Keyva.prefix(prefix); + const entries = await this.kv.each<SMap[SKey]>({ range }); + return entries.map(([rk, v]) => { + const str = String(rk); + const suffix = str.startsWith(prefix) ? str.slice(prefix.length) : str; + return [suffix as SKey, v]; + }); + } + + public async clear_all(): Promise<void> { + const range = Keyva.prefix('*'); + const keys = await this.kv.each({ range }, 'keys'); + if (keys.length) await Promise.all(keys.map((k) => this.kv.delete(k))); + } + + public async clear_scope(): Promise<void> { + const prefix = fmt_id(); + const range = Keyva.prefix(prefix); + const keys = await this.kv.each({ range }, 'keys'); + if (keys.length) await Promise.all(keys.map((k) => this.kv.delete(k))); + } + + public async sync_batch(entries: Array<[string, any]>): Promise<void> { + if (entries.length) await this.kv.set(entries); + } +} diff --git a/apps-lib/src/lib/utils/lib.ts b/apps-lib/src/lib/utils/lib.ts @@ -0,0 +1,41 @@ +import { browser } from '$app/environment'; +import type { ThemeMode } from '$lib/types/lib'; +import { get } from "svelte/store"; + +export const get_store = get; + +export const trim_slashes = (path: string): string => + path.replace(/^\/+|\/+$/g, ''); + +export const normalize_path = (path: string): string => + path + .replace(/-/g, '_') + .replace(/\//g, '-') + .replace(/-+/g, '-'); + +export const sanitize_path = (id: string): string => + id.replace(/[^A-Za-z0-9_-]+/g, ''); + +export const fmt_id = (raw_id?: string): string => { + if (!browser) return ''; + const pathname = window.location.pathname; + const trimmed = trim_slashes(pathname); + const prefix = normalize_path(trimmed); + const suffix = raw_id ? `-${sanitize_path(raw_id)}` : ''; + return `*${prefix}${suffix}`; +}; + +export const build_storage_key = ( + raw_id: string, + base_prefix: string +): string => + `${fmt_id()}-${sanitize_path(raw_id)}` + .replace(new RegExp(`^\\*${normalize_path(trim_slashes(base_prefix))}-?`), '*'); + +export const get_system_theme = (): ThemeMode => { + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +}; + +export const theme_set = (theme_key: string, color_mode: ThemeMode): void => { + document.documentElement.setAttribute("data-theme", `${theme_key}_${color_mode}`); +}; +\ No newline at end of file diff --git a/apps-lib/src/lib/view/farms-add.svelte b/apps-lib/src/lib/view/farms-add.svelte @@ -1,223 +0,0 @@ -<script lang="ts"> - import LayoutBottomButton from "$lib/components/layout/layout-bottom-button.svelte"; - import { schema_view_farms_add_submission } from "$lib/util/validation/farm"; - import { - app_platform, - ButtonLayoutPair, - Carousel, - casl_dec, - casl_i, - casl_inc, - casl_init, - FarmsAddCasliDetail, - FarmsAddCasliMap, - fmt_id, - focus_map_marker, - geop_init, - geop_is_valid, - get_context, - handle_err, - LayoutView, - PageToolbar, - type CallbackRoute, - type IViewFarmsAddSubmission, - } from "$root"; - import { - el_id, - geol_lat_fmt, - geol_lng_fmt, - parse_float, - parse_geocode_address, - type CallbackPromiseGeneric, - type GeocoderReverseResult, - type GeolocationAddress, - type GeolocationPoint, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls, locale, lc_gui_alert, lc_geop_current, lc_geocode } = - get_context(`lib`); - - let { - basis, - }: { - basis: { - callback_route?: CallbackRoute<string>; - on_submit: CallbackPromiseGeneric<{ - payload: IViewFarmsAddSubmission; - }>; - }; - } = $props(); - - let map_geop: GeolocationPoint = $state(geop_init()); - let map_geoc: GeocoderReverseResult | undefined = $state(undefined); - - let val_farmname = $state(``); - let val_farmaddress = $state(``); - let val_farmcontact = $state(``); - let val_farmarea = $state(``); - let val_farmarea_unit = $state(`ac`); - - const disabled_submit = $derived($casl_i === 1 && !val_farmname); - - onMount(async () => { - try { - casl_init(0, 2); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - const farm_geop_lat = $derived( - geop_is_valid(map_geop) - ? geol_lat_fmt(map_geop.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - geop_is_valid(map_geop) - ? geol_lng_fmt(map_geop.lng, `dms`, $locale, 3) - : ``, - ); - - const farm_geolocation_address: GeolocationAddress | undefined = $derived( - parse_geocode_address(map_geoc), - ); - - $effect(() => { - if (farm_geolocation_address) - val_farmaddress = `${farm_geolocation_address.primary}, ${farm_geolocation_address.admin}, ${farm_geolocation_address.country}`; - }); - - const handle_enter_location = async (): Promise<void> => { - map_geoc = undefined; - map_geop = geop_init(); - val_farmaddress = ``; - await handle_continue(); - el_id(fmt_id(`farm_location`))?.focus(); - }; - - const handle_continue_1 = async (): Promise<void> => { - if (!map_geop || !map_geoc) - return void lc_gui_alert(`No farm location provided.`); //@todo - const farms_add_submission = schema_view_farms_add_submission.safeParse( - { - farm_name: val_farmname, - farm_area: val_farmarea ? parse_float(val_farmarea) : undefined, - farm_area_unit: - val_farmarea && val_farmarea_unit - ? val_farmarea_unit - : undefined, - farm_contact_name: val_farmcontact - ? val_farmcontact - : undefined, - geolocation_point: map_geop, - geocode_result: map_geoc, - } satisfies IViewFarmsAddSubmission, - ); - - if (!farms_add_submission.success) { - return void lc_gui_alert( - `Request invalid: ${farms_add_submission.error}`, - ); //@todo - } - await basis.on_submit({ payload: farms_add_submission.data }); - }; - - const handle_continue = async (): Promise<void> => { - switch ($casl_i) { - case 1: - return await handle_continue_1(); - default: - await casl_inc(); - } - }; - - const handle_back = async (): Promise<void> => { - switch ($casl_i) { - case 1: { - if (!geop_is_valid(map_geop)) { - const geop_cur = await lc_geop_current(); - if (geop_cur) { - map_geop = geop_cur; - const geoc_cur = await lc_geocode(geop_cur); - if (geoc_cur) map_geoc = geoc_cur; - focus_map_marker(); - } - } - } - default: - return await casl_dec(); - } - }; -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)} / ${`${$ls(`common.add`)}`}`, - callback_route: basis.callback_route, - }, - }} - > - {#snippet header_option()} - <!-- @todo {#if $casl_i === 0} - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - await handle_enter_location(); - }} - > - <p - class={`font-sans font-[600] text-[18px] text-layer-0-glyph-hl`} - > - {`${$ls(`common.enter_location`)}`} - </p> - <Glyph - basis={{ - classes: `text-layer-0-glyph-hl`, - dim: `md`, - key: `caret-right`, - }} - /> - </button> - {/if}--> - {/snippet} - </PageToolbar> - <Carousel> - <FarmsAddCasliMap - bind:map_geop - bind:map_geoc - {farm_geop_lat} - {farm_geop_lng} - /> - <FarmsAddCasliDetail - bind:val_farmname - bind:val_farmaddress - bind:val_farmcontact - bind:val_farmarea - bind:val_farmarea_unit - {farm_geop_lat} - {farm_geop_lng} - /> - </Carousel> -</LayoutView> -{#if $app_platform?.browser !== `safari`} - <LayoutBottomButton> - <ButtonLayoutPair - basis={{ - continue: { - label: `${$ls(`common.continue`)}`, - disabled: disabled_submit, - callback: handle_continue, - }, - back: { - label: `${$ls(`common.back`)}`, - visible: $casl_i > 0, - callback: handle_back, - }, - }} - /> - </LayoutBottomButton> -{/if} diff --git a/apps-lib/src/lib/view/farms-details.svelte b/apps-lib/src/lib/view/farms-details.svelte @@ -1,268 +0,0 @@ -<script lang="ts"> - import { - ButtonSimple, - Empty, - get_context, - Glyph, - handle_err, - LayoutPage, - LayoutView, - Map, - MapMarkerArea, - PageToolbar, - type CallbackRoute, - type IViewFarmsDetailsData, - } from "$root"; - import { - fmt_geolocation_address, - geol_lat_fmt, - geol_lng_fmt, - parse_geol_point_tup, - parse_tup_geop_point, - type CallbackPromiseGeneric, - type GeolocationPointTuple, - type IViewBasis, - } from "@radroots/util"; - import { onDestroy, onMount } from "svelte"; - - const { ls, locale } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data: IViewFarmsDetailsData; - callback_route?: CallbackRoute<string>; - on_handle_farm_lot_add: CallbackPromiseGeneric<string>; - on_handle_farm_products_view: CallbackPromiseGeneric<string>; - on_handle_farm_orders_view: CallbackPromiseGeneric<string>; - }>; - } = $props(); - - let map: maplibregl.Map | undefined = $state(undefined); - let map_center: GeolocationPointTuple = $state([0, 0]); - - onMount(async () => { - try { - if (basis.on_mount) await basis.on_mount(); - if (basis.data?.location) - map_center = parse_geol_point_tup(basis.data?.location.point); - if (map) { - map.setCenter(map_center); - map.setZoom(11); - } - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (basis.on_destroy) await basis.on_destroy(); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const map_geop = $derived(parse_tup_geop_point(map_center)); - - const farm_addr_fmt = $derived( - basis.data?.location?.address - ? fmt_geolocation_address(basis.data?.location.address) - : ``, - ); - - const farm_geop_lat = $derived( - basis.data?.location?.point - ? geol_lat_fmt(basis.data?.location.point.lat, `dms`, $locale, 3) - : ``, - ); - - const farm_geop_lng = $derived( - basis.data?.location?.point - ? geol_lng_fmt(basis.data?.location.point.lng, `dms`, $locale, 3) - : ``, - ); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)}${basis.data?.farm.name ? ` / ${basis.data?.farm.name}` : ``}`, - callback_route: basis.callback_route, - }, - }} - /> - <LayoutPage> - <div - class={`flex flex-row h-[12rem] w-full justify-start items-center`} - > - <div - class={`flex flex-col basis-1/2 h-full p-4 gap-2 justify-start items-center`} - > - <div class={`flex flex-col w-full justify-start items-center`}> - <div - class={`flex flex-row w-full justify-start items-center`} - > - <p - class={`font-sans font-[500] text-lg text-layer-0-glyph`} - > - {farm_addr_fmt} - </p> - </div> - <div - class={`flex flex-row w-full justify-start items-center`} - > - <p - class={`font-sans font-[500] text-lg text-layer-0-glyph tracking-tight`} - > - {farm_geop_lat && farm_geop_lng - ? `${farm_geop_lat}, ${farm_geop_lng}` - : ``} - </p> - </div> - </div> - </div> - <div - class={`flex flex-col basis-1/2 h-full justify-start items-center`} - > - <div - class={`flex flex-col h-full w-full p-4 gap-4 justify-start items-center bg-layer-1-surface rounded-2xl`} - > - <p - class={`font-sans font-[500] text-sm text-layer-0-glyph`} - > - {`Farm Info`} - </p> - <div - class={`flex flex-col w-full gap-1 justify-start items-center`} - > - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`Farm Size:`} - </p> - - {#if basis.data?.farm.area && basis.data?.farm.area_unit} - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`${basis.data?.farm.area} ${basis.data?.farm.area_unit}`} - </p> - {:else} - <div - class={`flex flex-row gap-line justify-start items-center`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph_pl`} - > - {`Add`} - </p> - <Glyph - basis={{ - classes: `text-layer-0-glyph_pl`, - dim: `xs`, - key: `caret-right`, - }} - /> - </div> - {/if} - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`Farm Lots:`} - </p> - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`${basis.data?.lots?.length || 0}`} - </p> - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`Products:`} - </p> - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`${0}`} - </p> - </div> - <div - class={`flex flex-row w-full gap-4 justify-between items-center`} - > - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`Orders:`} - </p> - <p - class={`font-sans font-[400] text-layer-0-glyph`} - > - {`${0}`} - </p> - </div> - </div> - </div> - </div> - </div> - <div class={`flex flex-col w-full gap-3 justify-center items-center`}> - <ButtonSimple - basis={{ - label: `View Products`, - callback: async () => { - if (basis.data?.farm.id) - await basis.on_handle_farm_products_view( - basis.data?.farm.id, - ); - }, - }} - /> - <ButtonSimple - basis={{ - label: `View Orders`, - callback: async () => { - if (basis.data?.farm.id) - await basis.on_handle_farm_orders_view( - basis.data?.farm.id, - ); - }, - }} - /> - </div> - <div - class={`flex flex-col flex-shrink-0 h-[16rem] w-full justify-center items-center rounded-2xl overflow-hidden`} - > - <Map - bind:map - basis={{ - interactive: false, - }} - > - <MapMarkerArea - {map_geop} - basis={{ - no_drag: true, - }} - /> - </Map> - </div> - <div - class={`flex flex-col h-[12rem] w-full justify-center items-center`} - > - <Empty /> - </div> - </LayoutPage> -</LayoutView> diff --git a/apps-lib/src/lib/view/farms-products-add.svelte b/apps-lib/src/lib/view/farms-products-add.svelte @@ -1,669 +0,0 @@ -<script lang="ts"> - import { - app_lo, - ButtonLayoutPair, - Carousel, - CarouselItem, - casl_dec, - casl_i, - casl_imax, - casl_inc, - casl_init, - FarmsProductsReviewCard, - fmt_id, - FormEntryPrice, - FormEntryQuantity, - FormEntrySelect, - FormEntrySelectInput, - FormEntryTextarea, - get_context, - handle_err, - idb, - ImageUploadSimple, - LayoutBottomButton, - LayoutView, - loc_fmt_geo_point_coords, - MapLocationSelectEnvelope, - MarkerIndexedView, - PageToolbar, - schema_view_farms_products_add_submission, - type CallbackRoute, - type ISelectOption, - type IViewFarmsProductsAddData, - type IViewFarmsProductsAddSubmitPayload, - } from "$root"; - import { - el_id, - fmt_geocode_address, - fmt_geolocation_address, - form_fields, - location_basis_to_geo_point, - obj_keys_maxnum, - parse_float, - parse_geop_point, - parse_int, - parse_trade_key, - sleep, - str_trunc, - trade, - trade_keys, - type CallbackPromiseFull, - type CallbackPromiseGeneric, - type GeocoderReverseResult, - type GeolocationPoint, - type IViewBasis, - type LocationBasis, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls, locale, lc_geocode, lc_gui_alert, lc_geop_current } = - get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data: IViewFarmsProductsAddData; - callback_route?: CallbackRoute<string>; - on_handle_farm_lot_add: CallbackPromiseGeneric<string>; - on_handle_photo_envelope_edit: CallbackPromiseGeneric<number>; - on_handle_tradepr_key_toggle: CallbackPromiseFull<boolean, string>; - on_submit: CallbackPromiseGeneric<{ - payload: IViewFarmsProductsAddSubmitPayload; - farm_id: string; - geolocation_id?: string; - }>; - }>; - } = $props(); - - const casl_param: Record< - "default", - { - index_map: Record<number, { label_desc: string }>; - } - > = { - default: { - index_map: { - 0: { - label_desc: `${$ls(`icu.add_*`, { value: `${$ls(`icu.*_information`, { value: `${$ls(`common.product`)}` })}` })}`, - }, - 1: { - label_desc: `${$ls(`icu.upload_*`, { value: `${$ls(`common.images`)}` })}`, - }, - 2: { - label_desc: `${$ls(`icu.*_price`, { value: `${$ls(`common.product`)}` })}`, - }, - 3: { - label_desc: `${$ls(`icu.add_*`, { value: `${$ls(`common.location`)}` })}`, - }, - 4: { - label_desc: `${$ls(`common.review`)}`, - }, - }, - }, - }; - - let choose_location_map_geop: GeolocationPoint | undefined = - $state(undefined); - let choose_location_map_geoc: GeocoderReverseResult | undefined = - $state(undefined); - - let loading_submit = $state(false); - let payload_submit: IViewFarmsProductsAddSubmitPayload | undefined = - $state(undefined); - - let photo_paths = $state([]); - - let product_key_sel = $state(`cacao`); - let product_key_sel_input = $state(``); - let product_key_sel_toggle = $state(false); - - let product_process_sel = $state(`raw`); - let product_process_sel_input = $state(``); - let product_process_sel_toggle = $state(false); - - let product_description_input = $state(`Cool Description`); - - let product_location_sel = $state(``); - let product_location_map_toggle = $state(false); - let product_location_sel_geoc: GeocoderReverseResult | undefined = - $state(undefined); - - let product_price_cur_sel = $state(`usd`); - let product_price_input = $state(`4.50`); - let product_price_qty_unit_sel = $state(`lb`); - - let product_quantity_input = $state(`60`); - let product_quantity_unit_sel = $state(`kg`); - let product_quantity_label_sel = $state(`bag`); - - const tradepr_key_parsed = $derived(parse_trade_key(product_key_sel)); - - const product_process_list = $derived( - tradepr_key_parsed ? trade.key[tradepr_key_parsed].process : [], - ); - - const list_farm_geolocations: LocationBasis[] = $derived( - [ - basis.data?.location ? basis.data?.location : undefined, - ...(basis.data?.lots?.length - ? [...basis.data?.lots.map((i) => i.location)] - : []), - ].filter((i) => typeof i !== `undefined`), - ); - - const find_location_by_id = (id: string): LocationBasis | undefined => { - return list_farm_geolocations.find((i) => i.id === id) || undefined; - }; - - const product_geolocation_id: string | undefined = $derived( - product_location_sel === `*map-current` - ? undefined - : find_location_by_id(product_location_sel)?.id, - ); - - const product_location: LocationBasis | undefined = $derived( - product_location_sel - ? find_location_by_id(product_location_sel) - : undefined, - ); - - $effect(() => { - console.log(`choose_location_map_geoc `, choose_location_map_geoc); - }); - - $effect(() => { - console.log(`product_location_sel_geoc `, product_location_sel_geoc); - }); - - const product_geolocation_point: GeolocationPoint | undefined = $derived( - product_location_sel === `*map-current` - ? choose_location_map_geop - : location_basis_to_geo_point(product_location) || undefined, - ); - - const product_geocode_reverse: GeocoderReverseResult | undefined = $derived( - product_location_sel === `*map-current` - ? choose_location_map_geoc - : product_location_sel_geoc, - ); - - const entries_farm_location: ISelectOption<string>[] = $derived( - basis.data?.location - ? [ - { - value: basis.data.location.id, - label: basis.data.location.address - ? fmt_geolocation_address(basis.data.location.address) - : basis.data.location.point - ? loc_fmt_geo_point_coords( - $locale, - basis.data.location.point, - ) - : ``, - }, - ] - : [], - ); - const entries_farm_lots_locations: ISelectOption<string>[] = $derived( - basis.data?.lots?.length - ? basis.data.lots - .filter( - (i) => - i.location && - i.location?.address && - !entries_farm_location - .map((i) => i.value) - .includes(i.location.id), - ) - .map(({ location }) => - location && location.address - ? { - value: location.id, - label: `${location.address.primary}, ${location.address.admin}, ${location.address.country}`, - } - : undefined, - ) - .filter((i) => typeof i !== `undefined`) - : [], - ); - - $effect(() => { - if (product_key_sel === ``) product_process_sel = ``; - }); - - onMount(async () => { - try { - casl_init(0, obj_keys_maxnum(casl_param.default.index_map)); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - const handle_sel_key = async (value: string): Promise<void> => { - if (value in trade.key) product_process_sel = ``; - el_id(fmt_id(`key_wrap`))?.classList.remove(`layer-1-ring-apply`); - if (value === `*other`) { - await handle_tradepr_key_toggle(true); - product_process_sel = ``; - } - }; - - const handle_tradepr_key_toggle = async ( - input_visible: boolean, - ): Promise<void> => { - product_key_sel_toggle = input_visible; - if (input_visible) { - product_key_sel_input = ``; - } else { - product_key_sel = ``; - product_key_sel_input = ``; - } - }; - - const handle_sel_process = async (value: string): Promise<void> => { - el_id(fmt_id(`process_wrap`))?.classList.remove(`layer-1-ring-apply`); - if (value === `*other`) handle_product_process_toggle(true); - else if (value === `*choose-product`) { - product_process_sel = ``; - el_id(fmt_id(`key_wrap`))?.classList.add(`layer-1-ring-apply`); - await sleep(1000); - el_id(fmt_id(`key_wrap`))?.classList.remove(`layer-1-ring-apply`); - } - }; - - const handle_product_process_toggle = async ( - input_visible: boolean, - ): Promise<void> => { - product_process_sel_toggle = input_visible; - if (input_visible) { - product_process_sel = ``; - product_process_sel_input = ``; - } - }; - - const handle_product_location_sel = async ( - value: string, - ): Promise<void> => { - console.log(`value `, value); - el_id(fmt_id(`location_wrap`))?.classList.remove(`layer-1-ring-apply`); - if (value === `*map`) { - product_location_sel_geoc = undefined; - if (choose_location_map_geop) choose_location_map_geop = undefined; - if (choose_location_map_geoc) choose_location_map_geoc = undefined; - const geop = await lc_geop_current(); - if (!geop) { - return void (await lc_gui_alert( - `${$ls(`icu.failure_reading_*`, { value: `${$ls(`common.location`)}`.toLowerCase() })}`, - )); - } - const geoc = await lc_geocode(geop); - if (!geoc) return; //@todo - choose_location_map_geoc = geoc; - choose_location_map_geop = parse_geop_point(geop); - product_location_map_toggle = true; - await sleep(1000); - product_location_sel = ``; - } else if (value) { - const value_product_location = find_location_by_id(value); - if (!value_product_location) return; //@todo - const geoc = await lc_geocode(value_product_location.point); - if (geoc) product_location_sel_geoc = geoc; - } - }; - - const continue_0 = async (): Promise<void> => { - for (const kv_id of [`key`, `process`, `description`]) { - const val = await idb.get(fmt_id(kv_id)); - if (!val) - return void (await lc_gui_alert( - `${$ls(`farm.product.validation.${kv_id}.required`)}`, - )); - } - await casl_inc(); - }; - - const continue_1 = async (): Promise<void> => { - if (!photo_paths.length) - return void (await lc_gui_alert( - `Upload a product photo`, //@todo - )); - await casl_inc(); - }; - - const continue_2 = async (): Promise<void> => { - await casl_inc(); - }; - - const continue_3 = async (): Promise<void> => { - if (!product_geolocation_point || !product_geocode_reverse) - return void (await lc_gui_alert(`Product location not provided`)); - const vp_payload_submit = - schema_view_farms_products_add_submission.safeParse({ - product: product_key_sel_input || product_key_sel, - process: product_process_sel_input || product_process_sel, - description: product_description_input, - price_amount: parse_float(product_price_input, 1.0), - price_currency: product_price_cur_sel, - price_quantity_unit: product_price_qty_unit_sel, - quantity_amount: parse_int(product_quantity_input, 1), - quantity_unit: product_quantity_unit_sel, - quantity_label: product_quantity_label_sel, - photos: photo_paths, - geolocation_point: product_geolocation_point, - geocode_result: product_geocode_reverse, - } satisfies IViewFarmsProductsAddSubmitPayload); - if (!vp_payload_submit.success) - return void (await lc_gui_alert( - `Errors: ${vp_payload_submit.error}`, - )); - payload_submit = vp_payload_submit.data; - await casl_inc(); - }; - - const continue_4 = async (): Promise<void> => { - if (!payload_submit) - return void (await lc_gui_alert(`${$ls(`error.default.failure`)}`)); - loading_submit = true; - try { - await basis.on_submit({ - payload: payload_submit, - farm_id: basis.data.farm.id, - geolocation_id: product_geolocation_id, - }); - } catch { - } finally { - loading_submit = false; - } - }; - - const handle_continue = async (): Promise<void> => { - try { - switch ($casl_i) { - case 0: - return await continue_0(); - case 1: - return await continue_1(); - case 2: - return await continue_2(); - case 3: - return await continue_3(); - case 4: - return await continue_4(); - } - } catch (e) { - await handle_err(e, `handle_continue`); - } - }; - - const handle_back = async (): Promise<void> => { - try { - switch ($casl_i) { - default: - return await casl_dec(); - } - } catch (e) { - await handle_err(e, `handle_back`); - } - }; -</script> - -<LayoutView basis={{ classes: `` }}> - <PageToolbar - basis={{ - header: { - label: `${`${$ls(`common.farm`)}`} / ${`${$ls(`common.product`)}`}`, - callback_route: basis.callback_route || { route: `/farms` }, - }, - }} - /> - <LayoutBottomButton> - <ButtonLayoutPair - basis={{ - continue: { - label: - $casl_i === $casl_imax - ? `${$ls(`common.post`)}` - : `${$ls(`common.continue`)}`, - disabled: false, - loading: loading_submit, - callback: handle_continue, - }, - back: { - label: `${$ls(`common.back`)}`, - visible: $casl_i > 0, - callback: handle_back, - }, - }} - /> - </LayoutBottomButton> - <div - class={`flex flex-col w-lo_line_entry_${$app_lo} pt-4 pb-6 px-1 gap-4 justify-center items-center`} - > - <div class={`flex flex-row h-2 w-full justify-start items-center`}> - <p - class={`font-sans font-[500] text-sm text-layer-0-glyph/60 capitalize`} - > - {casl_param.default.index_map[$casl_i]?.label_desc} - </p> - </div> - <MarkerIndexedView - basis={{ - index_max: $casl_imax + 1, - index_curr: $casl_i, - callback_index: async (index) => { - casl_i.set(index); - }, - }} - /> - </div> - <Carousel> - <CarouselItem basis={{ classes: `gap-4` }}> - <FormEntrySelectInput - bind:val_sel={product_key_sel} - bind:val_sel_input={product_key_sel_input} - basis={{ - id: `key`, - entry_label: `${$ls(`common.product`)}`, - visible_input: product_key_sel_toggle, - input_placeholder: `${$ls(`icu.enter_the_*`, { value: `${$ls(`icu.*_name`, { value: `${$ls(`common.product`)}` })}`.toLowerCase() })}`, - input_field: form_fields.product_key, - callback_visible: handle_tradepr_key_toggle, - callback_select: async ({ value }) => { - await handle_sel_key(value); - }, - select_entries: [ - { - value: ``, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.product`)}`.toLowerCase() })}`, - disabled: true, - }, - ...trade_keys.map((i) => ({ - value: i, - label: `${$ls(`products.key.${i}.name`)}`, - })), - { - value: `*other`, - label: - product_key_sel === `*other` - ? `` - : `${$ls(`common.other`)}`, - }, - ], - }} - /> - <FormEntrySelectInput - bind:val_sel={product_process_sel} - bind:val_sel_input={product_process_sel_input} - basis={{ - id: `process`, - entry_label: `${$ls(`common.process`)}`, - visible_input: product_process_sel_toggle, - input_placeholder: `${$ls(`icu.enter_the_*`, { value: `${$ls(`common.process`)}`.toLowerCase() })}`, - input_field: form_fields.product_process, - callback_visible: handle_product_process_toggle, - callback_select: async ({ value }) => - await handle_sel_process(value), - select_entries: product_process_list.length - ? [ - { - value: ``, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.process`)}`.toLowerCase() })}`, - disabled: true, - }, - ...product_process_list.map((i) => ({ - value: i, - label: `${$ls(`products.key.${tradepr_key_parsed}.process.${i}`)}`, - })), - { - value: `*other`, - label: - product_key_sel === `*other` - ? `` - : `${$ls(`common.other`)}`, - }, - ] - : [ - { - value: ``, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.process`)}`.toLowerCase() })}`, - disabled: true, - }, - { - value: `*choose-product`, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.product`)}`.toLowerCase() })}`, - }, - ] - .concat( - product_key_sel === `*other` - ? [ - ...trade.default.process.map( - (i) => ({ - value: i, - label: `${$ls(`products.default.process.${i}`)}`, - }), - ), - { - value: `*other`, - label: `${$ls(`common.other`)}`, - }, - ] - : [], - ) - .filter((i) => - product_key_sel - ? i.value !== `*choose-product` - : true, - ), - }} - /> - <FormEntryTextarea - bind:val={product_description_input} - basis={{ - id: `description`, - entry_label: `${$ls(`common.description`)}`, - field: form_fields.product_description, - placeholder: `${$ls(`common.describe_your_product`)}`, - }} - /> - </CarouselItem> - <CarouselItem basis={{ classes: `px-4` }}> - <ImageUploadSimple bind:photo_paths /> - </CarouselItem> - <CarouselItem basis={{ classes: `gap-4` }}> - <FormEntryPrice - bind:val_input_price={product_price_input} - bind:val_sel_currency={product_price_cur_sel} - bind:val_sel_quantity_unit={product_price_qty_unit_sel} - basis={{ - id: `price`, - entry_label: `price`, - input_placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.price`)}` })}`, - }} - /> - <FormEntryQuantity - bind:val_input_quantity={product_quantity_input} - bind:val_sel_quantity_unit={product_quantity_unit_sel} - bind:val_sel_quantity_label={product_quantity_label_sel} - basis={{ - id: `quantity`, - entry_label: `quantity`, - input_placeholder: `${$ls(`icu.enter_*`, { value: `${$ls(`common.quantity`)}` })}`, - }} - /> - </CarouselItem> - <CarouselItem> - <FormEntrySelect - bind:val={product_location_sel} - basis={{ - id: `location`, - entry_label: `${$ls(`common.location`)}`, - callback: async ({ value }) => - await handle_product_location_sel(value), - entries: choose_location_map_geoc - ? [ - { - value: ``, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.location`)}`.toLowerCase() })}`, - disabled: true, - }, - { - value: `*map`, - label: `${$ls(`common.choose_on_map`)}`, - }, - { - value: `*map-current`, - label: `${str_trunc(fmt_geocode_address(choose_location_map_geoc))} (map)`, - }, - ...entries_farm_location, - ...entries_farm_lots_locations, - ] - : [ - { - value: ``, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.location`)}`.toLowerCase() })}`, - disabled: true, - }, - ...entries_farm_location, - ...entries_farm_lots_locations, - { - value: `*map`, - label: `${$ls(`common.choose_on_map`)}`, - }, - ], - }} - /> - </CarouselItem> - <CarouselItem> - <div class={`flex flex-col w-full justify-center items-center`}> - <FarmsProductsReviewCard - basis={{ - data: payload_submit, - }} - /> - </div> - </CarouselItem> - </Carousel> -</LayoutView> -<MapLocationSelectEnvelope - bind:map_geop={choose_location_map_geop} - bind:map_geoc={choose_location_map_geoc} - basis={{ - visible: product_location_map_toggle, - on_submit: async (params) => { - try { - if (!params) { - choose_location_map_geoc = undefined; - return; - } - const { map_geoc, map_geop } = params; - if (map_geoc && map_geop) product_location_sel = `*map-current`; - else product_location_sel = ``; - } catch (e) { - await handle_err(e, `on_submit`); - } finally { - product_location_map_toggle = false; - } - }, - }} -/> diff --git a/apps-lib/src/lib/view/farms.svelte b/apps-lib/src/lib/view/farms.svelte @@ -1,90 +0,0 @@ -<script lang="ts"> - import { - ButtonLabelDashed, - Fade, - FarmsDisplayLiEl, - get_context, - GlyphButtonSimple, - handle_err, - idb_init_page, - LayoutPage, - LayoutView, - PageToolbar, - type CallbackRoute, - type IViewFarmsData, - } from "$root"; - import { - type CallbackPromise, - type CallbackPromiseGeneric, - type IViewBasis, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data?: IViewFarmsData; - callback_route?: CallbackRoute<string>; - on_handle_farm_add: CallbackPromise; - on_handle_farm_view: CallbackPromiseGeneric<string>; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.farms`)}`, - callback_route: basis.callback_route, - }, - }} - > - {#snippet header_option()} - {#if basis.data?.list.length} - <Fade> - <GlyphButtonSimple - basis={{ - label: `${$ls(`icu.add_*`, { value: `${$ls(`common.farm`)}` })}`, - callback: async () => { - await basis.on_handle_farm_add(); - }, - }} - /> - </Fade> - {/if} - {/snippet} - </PageToolbar> - <LayoutPage> - {#if basis.data} - {#if basis.data?.list.length} - {#each basis.data?.list || [] as li} - <FarmsDisplayLiEl - basis={li} - on_handle_farm_view={basis.on_handle_farm_view} - /> - {/each} - {:else} - <ButtonLabelDashed - basis={{ - label: `Add farm`, - callback: async () => { - await basis.on_handle_farm_add(); - }, - }} - /> - {/if} - {/if} - </LayoutPage> -</LayoutView> diff --git a/apps-lib/src/lib/view/home.svelte b/apps-lib/src/lib/view/home.svelte @@ -1,59 +0,0 @@ -<script lang="ts"> - import { - ButtonSimple, - get_context, - handle_err, - idb_init_page, - LayoutPage, - LayoutView, - NavigationTabs, - PageToolbar, - type IViewHomeData, - } from "$root"; - import { type CallbackPromise, type IViewBasis } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - data?: IViewHomeData; - on_handle_farms: CallbackPromise; - on_handle_products: CallbackPromise; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -{#if basis.data} - {@const { data: basis_data } = basis} - <LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.general`)}`, - }, - }} - /> - <LayoutPage> - <ButtonSimple - basis={{ - label: `${$ls(`common.farms`)}`, - callback: async () => { - await basis.on_handle_farms(); - }, - }} - /> - </LayoutPage> - </LayoutView> - <NavigationTabs /> -{/if} diff --git a/apps-lib/src/lib/view/notifications.svelte b/apps-lib/src/lib/view/notifications.svelte @@ -1,34 +0,0 @@ -<script lang="ts"> - import { LayoutView, NavigationTabs, PageToolbar } from "$root"; - import type { I18nTranslateFunction } from "@radroots/util"; - - let notifications: any[] = []; - - let { basis, ls }: { basis: {}; ls: I18nTranslateFunction } = $props(); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.notifications`)} (${notifications.length})`, - }, - }} - /> - <div class={`flex flex-col w-full px-4 gap-6 justify-center items-center`}> - {#if notifications.length} - {#each notifications as li} - <div class={`flex flex-row w-full justify-center items-center`}> - {li} - </div> - {/each} - {:else} - <div class={`flex flex-row w-full justify-center items-center`}> - <p class={`font-sans font-[500] text-layer-0-glyph capitalize`}> - {`${$ls(`icu.no_*`, { value: `${$ls(`common.notifications`)}` })}`} - </p> - </div> - {/if} - </div> -</LayoutView> -<NavigationTabs /> diff --git a/apps-lib/src/lib/view/profile-edit.svelte b/apps-lib/src/lib/view/profile-edit.svelte @@ -1,105 +0,0 @@ -<script lang="ts"> - import ButtonRoundNav from "$lib/components/button/button-round-nav.svelte"; - import FloatPage from "$lib/components/float/float-page.svelte"; - import Empty from "$lib/components/lib/empty.svelte"; - import { - fmt_id, - get_context, - handle_err, - idb_init_page, - Input, - LayoutPage, - LayoutView, - NavigationTabs, - type IViewProfileEditData, - type ViewProfileEditFieldKey, - } from "$root"; - import { - type CallbackPromiseGeneric, - type ElementCallbackValue, - type IViewBasis, - } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - val_field = $bindable(``), - }: { - basis: IViewBasis<{ - data?: IViewProfileEditData; - on_handle_back: CallbackPromiseGeneric<{ - field: ViewProfileEditFieldKey; - public_key: string; - }>; - on_handle_input: ElementCallbackValue; - }>; - val_field: string; - } = $props(); - - const param: Record<ViewProfileEditFieldKey, { placeholder: string }> = { - name: { - placeholder: `${$ls(`icu.enter_*`, { value: `profile username` })}`, //@todo - }, - display_name: { - placeholder: `${$ls(`icu.enter_*`, { value: `profile display name` })}`, //@todo - }, - about: { - placeholder: `${$ls(`icu.enter_*`, { value: `profile bio` })}`, //@todo - }, - }; - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - const input_placeholder = $derived( - basis.data?.field ? param[basis.data.field]?.placeholder : ``, - ); -</script> - -{#if basis.data} - {@const { data: basis_data } = basis} - <LayoutView> - <LayoutPage> - <div class={`flex flex-row h-20 w-full justify-start items-center`}> - <Empty /> - </div> - {#if basis.data.field} - <Input - bind:value={val_field} - basis={{ - id: fmt_id(`field`), - sync: true, - classes: `pl-6 h-entry_line text-layer-1-glyph bg-layer-1-surface rounded-2xl`, - placeholder: input_placeholder, - callback: basis.on_handle_input, - }} - /> - {/if} - </LayoutPage> - </LayoutView> - <FloatPage - basis={{ - posx: `left`, - }} - > - <ButtonRoundNav - basis={{ - glyph: `arrow-left`, - callback: async () => { - await basis.on_handle_back({ - field: basis_data.field, - public_key: basis_data.public_key, - }); - }, - }} - /> - </FloatPage> - <NavigationTabs /> -{/if} diff --git a/apps-lib/src/lib/view/profile.svelte b/apps-lib/src/lib/view/profile.svelte @@ -1,306 +0,0 @@ -<script lang="ts"> - import { - ButtonRoundNav, - FloatPage, - get_context, - Glyph, - handle_err, - idb_init_page, - ImagePath, - ImageUploadAddPhoto, - NavigationTabs, - SelectMenu, - type IViewOnDestroy, - type IViewProfileData, - type ViewProfileEditFieldKey, - } from "$root"; - import { - symbols, - type CallbackPromise, - type CallbackPromiseGeneric, - type IViewBasis, - } from "@radroots/util"; - import { onDestroy, onMount } from "svelte"; - - const { ls } = get_context(`lib`); - - let { - basis, - photo_path = $bindable(``), - }: { - basis: IViewBasis<{ - data?: IViewProfileData; - loading_photo_upload: boolean; - loading_photo_upload_open: boolean; - on_handle_back: CallbackPromiseGeneric<{ - is_photo_existing: boolean; - }>; - on_handle_photo_options: CallbackPromise; - on_handle_edit_profile_field: CallbackPromiseGeneric<{ - field: ViewProfileEditFieldKey; - }>; - }> & - IViewOnDestroy<{ public_key: string }>; - photo_path: string; - } = $props(); - - type ViewDisplay = `photos` | `following` | `followers`; - let view_display: ViewDisplay = $state(`photos`); - - let val_sel_options_button = $state(``); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); - - onDestroy(async () => { - try { - if (basis.data?.public_key) - await basis.on_destroy({ - public_key: basis.data.public_key, - }); - } catch (e) { - handle_err(e, `on_destroy`); - } - }); - - const photo_overlay_visible = $derived( - !!(basis.data?.picture || photo_path), - ); - - const classes_photo_overlay_glyph = $derived( - photo_overlay_visible ? `text-white` : `text-layer-0-glyph`, - ); - - const classes_photo_overlay_glyph_opt = $derived( - photo_overlay_visible ? `text-gray-300` : `text-layer-0-glyph`, - ); - - const classes_photo_overlay_glyph_opt_selected = $derived( - photo_overlay_visible ? `text-white` : `text-layer-1-glyph_d`, - ); -</script> - -{#if basis.data} - <div - class={`relative flex flex-col min-h-[525px] h-[525px] w-full justify-center items-center bg-layer-2-surface fade-in`} - > - <FloatPage - basis={{ - posx: `left`, - }} - > - <ButtonRoundNav - basis={{ - glyph: `arrow-left`, - loading: basis.loading_photo_upload, - callback: async () => { - await basis.on_handle_back({ - is_photo_existing: photo_overlay_visible, - }); - }, - }} - /> - </FloatPage> - <FloatPage - basis={{ - posx: `right`, - }} - > - <SelectMenu - bind:value={val_sel_options_button} - basis={{ - layer: 0, - options: [ - { - entries: [ - { - value: `*add-new`, - label: `Add new photo`, - }, - ], - }, - ], - }} - > - <ButtonRoundNav - basis={{ - glyph: `images-square`, - callback: basis.on_handle_photo_options, - }} - /> - </SelectMenu> - </FloatPage> - {#if basis.data.picture || photo_path} - {@const img_path = photo_path || basis.data.picture || ``} - <ImagePath basis={{ path: img_path }} /> - {:else} - <div - class={`flex flex-row justify-start items-center -translate-y-8`} - > - <ImageUploadAddPhoto - bind:photo_path - basis={{ - loading: basis.loading_photo_upload_open, - }} - /> - </div> - {/if} - <div - class={`absolute bottom-0 left-0 flex flex-col h-[calc(100%-100%/1.618)] w-full px-6 gap-2 justify-end items-center`} - > - <div - class={`flex flex-col w-full gap-[2px] justify-center items-center`} - > - <div - class={`flex flex-row h-10 w-full justify-start items-center`} - > - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `display_name`, - }); - }} - > - <p - class={`font-sansd font-[600] text-[2rem] ${classes_photo_overlay_glyph} ${basis.data?.name ? `` : `capitalize opacity-active`} el-re`} - > - {#if basis.data?.display_name} - {`${basis.data?.display_name}`} - {:else if basis.data?.name} - {`${basis.data?.display_name || basis.data?.name || ``}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.profile_name`)}` })}`}`} - {/if} - </p> - </button> - </div> - <div - class={`flex flex-row w-full gap-[6px] justify-start items-center`} - > - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `name`, - }); - }} - > - <p - class={`font-sansd font-[600] text-[1.1rem] ${classes_photo_overlay_glyph} ${basis.data?.name ? `` : `capitalize opacity-active`} el-re`} - > - {#if basis.data?.name} - {`@${basis.data.name}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.username`)}` })}`}`} - {/if} - </p> - </button> - <p - class={`font-sans font-[400] ${classes_photo_overlay_glyph}`} - > - {symbols.bullet} - </p> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - alert(`@todo!`); - }} - > - <Glyph - basis={{ - classes: `${classes_photo_overlay_glyph}`, - dim: `xs`, - - key: `link-simple`, - }} - /> - </button> - </div> - <div class={`flex flex-row w-full justify-start items-center`}> - <button - class={`group flex flex-row justify-center items-center`} - onclick={async () => { - await basis.on_handle_edit_profile_field({ - field: `about`, - }); - }} - > - <p - class={`font-sansd font-[400] text-[1.1rem] ${classes_photo_overlay_glyph} ${basis.data?.about ? `` : `capitalize opacity-active`}`} - > - {#if basis.data?.about} - {`${basis.data.about}`} - {:else} - {`+ ${`${$ls(`icu.add_*`, { value: `${$ls(`common.bio`)}` })}`}`} - {/if} - </p> - </button> - </div> - </div> - <div - class={`flex flex-row w-full pt-2 pb-6 gap-2 justify-start items-center`} - > - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `photos`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `photos` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.photos`)}`} - </p> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `following`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `following` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.following`)}`} - </p> - </button> - <button - class={`flex flex-row justify-center items-center`} - onclick={async () => { - view_display = `followers`; - }} - > - <p - class={`font-sans text-[1.1rem] font-[600] capitalize ${view_display === `followers` ? classes_photo_overlay_glyph_opt_selected : classes_photo_overlay_glyph_opt} el-re`} - > - {`${$ls(`common.followers`)}`} - </p> - </button> - </div> - </div> - </div> - <div - class={`flex flex-col w-full min-h-[500px] justify-start items-center`} - > - {#if view_display === `photos`} - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {view_display} - </p> - {:else if view_display === `following`} - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {view_display} - </p> - {:else if view_display === `followers`} - <p class={`font-sans font-[400] text-layer-0-glyph`}> - {view_display} - </p> - {/if} - </div> - <NavigationTabs /> -{/if} diff --git a/apps-lib/src/lib/view/settings.svelte b/apps-lib/src/lib/view/settings.svelte @@ -1,108 +0,0 @@ -<script lang="ts"> - import { - app_thc, - get_context, - handle_err, - idb_init_page, - LayoutTrellis, - LayoutView, - PageToolbar, - Trellis, - type ITrellisKind, - } from "$root"; - import { symbols, type IViewBasis } from "@radroots/util"; - import { onMount } from "svelte"; - - const { ls, lc_color_mode } = get_context(`lib`); - - let { - basis, - }: { - basis: IViewBasis<{ - trellis_2?: (ITrellisKind | undefined)[]; - }>; - } = $props(); - - onMount(async () => { - try { - if (!basis.kv_init_prevent) await idb_init_page(); - } catch (e) { - handle_err(e, `on_mount`); - } - }); -</script> - -<LayoutView> - <PageToolbar - basis={{ - header: { - label: `${$ls(`common.settings`)}`, - }, - }} - /> - <LayoutTrellis> - <Trellis - basis={{ - layer: 1, - title: { - value: `Appearance`, - }, - list: [ - { - hide_active: true, - select: { - label: { - left: [ - { - value: `${$ls(`common.color_mode`)}`, - classes: `capitalize`, - }, - ], - }, - display: { - label: { - value: `${$app_thc}`, - classes: `capitalize`, - }, - }, - el: { - value: $app_thc, - options: [ - { - entries: [ - { - value: symbols.bullet, - label: `${$ls(`icu.choose_*`, { value: `${$ls(`common.color_mode`)}`.toLowerCase() })}`, - disabled: true, - }, - { - value: `light`, - label: `${$ls(`common.light`)}`, - }, - { - value: `dark`, - label: `${$ls(`common.dark`)}`, - }, - ], - }, - ], - callback: lc_color_mode, - }, - end: { - glyph: { - key: `caret-right`, - }, - }, - }, - }, - ], - }} - /> - <Trellis - basis={{ - layer: 1, - list: basis.trellis_2, - }} - /> - </LayoutTrellis> -</LayoutView>