web_lib

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

commit cf436cdd12b4fd643933d1a011e924ad58c085a2
parent b40650c35917a241bad42e89971cffbad17ccd1c
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Sat,  7 Dec 2024 18:55:20 +0000

apps-lib: add logo circle and tab float components. edit nav, splash screen. edit elements. add/edit locales, types, utils

Diffstat:
Aapps-lib/src/lib/components/logo_circle.svelte | 36++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/logo_circle_sm.svelte | 14++++++++++++++
Mapps-lib/src/lib/components/nav.svelte | 9++++++++-
Mapps-lib/src/lib/components/splash_screen.svelte | 8++------
Aapps-lib/src/lib/components/tabs_float.svelte | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/el/css_styles.svelte | 2+-
Mapps-lib/src/lib/el/image_path.svelte | 8++++----
Mapps-lib/src/lib/el/input_element.svelte | 5++++-
Mapps-lib/src/lib/el/textarea_element.svelte | 14++++++++++----
Mapps-lib/src/lib/global.d.ts | 1+
Mapps-lib/src/lib/index.ts | 3+++
Mapps-lib/src/lib/locales/en/common.json | 3+++
Mapps-lib/src/lib/types/components.ts | 7++++++-
Mapps-lib/src/lib/types/el.ts | 12++++--------
Mapps-lib/src/lib/utils/routes.ts | 2++
15 files changed, 199 insertions(+), 26 deletions(-)

diff --git a/apps-lib/src/lib/components/logo_circle.svelte b/apps-lib/src/lib/components/logo_circle.svelte @@ -0,0 +1,36 @@ +<script lang="ts"> + let separator = ` • `; + let array = []; + $: array = [`radroots`, `radroots`].map((i) => [separator, ...i]).flat(); +</script> + +<div + class={`relative flex flex-col h-[196px] w-full justify-center items-center`} +> + <div + class={`flex flex-row h-32 w-32 justify-center items-center bg-layer-2-surface rounded-full`} + > + <p class={`font-sans font-[900] text-4xl text-layer-0-glyph`}> + {"»`,-"} + </p> + </div> + {#each array as char, index} + <div + class={`char font-sans text-layer-0-glyph text-center uppercase`} + style="--angle: {`${(1 / array.length) * index + 0.18}turn`}" + > + {char} + </div> + {/each} +</div> + +<style> + .char { + width: 1em; + height: 100%; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%) rotate(var(--angle, 0deg)); + } +</style> diff --git a/apps-lib/src/lib/components/logo_circle_sm.svelte b/apps-lib/src/lib/components/logo_circle_sm.svelte @@ -0,0 +1,14 @@ +<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/nav.svelte b/apps-lib/src/lib/components/nav.svelte @@ -7,6 +7,7 @@ Fill, fmt_cl, Glyph, + Loading, nav_blur, nav_prev, nav_visible, @@ -82,7 +83,13 @@ <div class={`col-span-4 flex flex-row w-full justify-start items-center`} > - {#if basis.prev.kind === `arrow`} + {#if basis.prev.loading} + <div + class={`flex flex-row pl-4 justify-center items-center`} + > + <Loading /> + </div> + {:else if basis.prev.kind === `arrow`} <div class={`flex flex-row w-full pl-8 justify-start items-center`} > diff --git a/apps-lib/src/lib/components/splash_screen.svelte b/apps-lib/src/lib/components/splash_screen.svelte @@ -1,13 +1,9 @@ <script lang="ts"> - import { Fill } from "$lib"; + import { LogoCircle } from "$lib"; </script> <div class={`z-50 absolute top-0 left-0 flex flex-row h-[100vh] w-full justify-center items-center bg-layer-0-surface`} > - <div - class={`flex flex-row h-10 w-10 justify-start items-center bg-layer-2-surface rounded-full`} - > - <Fill /> - </div> + <LogoCircle /> </div> diff --git a/apps-lib/src/lib/components/tabs_float.svelte b/apps-lib/src/lib/components/tabs_float.svelte @@ -0,0 +1,101 @@ +<script lang="ts"> + import { page } from "$app/stores"; + import { Fill, Glyph, nav_prev, route } from "$lib"; +</script> + +<div + class={`absolute bottom-0 left-0 h-24 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.0rem] 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`} + on:click={async () => { + await route(`/`); + }} + > + <Glyph + basis={{ + classes: `text-[26px] text-layer-0-glyph/80 rotate-90`, + weight: $page.url.pathname !== `/` ? `bold` : `fill`, + key: `columns`, + }} + /> + </button> + <button + class={`relative col-span-1 flex flex-row justify-center items-center`} + on:click={async () => { + await route(`/`); + }} + > + <Glyph + basis={{ + classes: `text-[24px] text-layer-0-glyph/80`, + weight: + $page.url.pathname === `/search` ? `fill` : `bold`, + key: `magnifying-glass`, + }} + /> + </button> + <button + class={`relative col-span-1 flex flex-row justify-center items-center`} + on:click={async () => { + $nav_prev.push({ + route: `/`, + label: `Home`, + }); + route(`/settings/profile`); + }} + > + <Glyph + basis={{ + classes: `text-[24px] text-layer-0-glyph/80`, + weight: $page.url.pathname.startsWith( + `/settings/profile`, + ) + ? `fill` + : `bold`, + key: `user`, + }} + /> + </button> + <button + class={`relative col-span-1 flex flex-row h-full justify-center items-center`} + on:click={async () => {}} + > + <Glyph + basis={{ + classes: `text-[24px] text-layer-0-glyph/80`, + weight: $page.url.pathname.startsWith(`/notifications`) + ? `fill` + : `bold`, + key: `bell`, + }} + /> + <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`} + > + <Fill /> + </div> + </div> + </button> + </div> + <button + class={`flex flex-row h-[3.0rem] w-[3.0rem] justify-center items-center bg-layer-1-surface rounded-full backdrop-blur-lg`} + on:click={async () => {}} + > + <Glyph + basis={{ + classes: `text-[22px] text-layer-0-glyph/80`, + weight: `bold`, + key: `plus`, + }} + /> + </button> + </div> +</div> diff --git a/apps-lib/src/lib/el/css_styles.svelte b/apps-lib/src/lib/el/css_styles.svelte @@ -1,3 +1,3 @@ <div class="hidden h-[12px] w-[12px] h-[16px] w-[16px] h-[17px] w-[17px] h-[18px] w-[18px] h-[20px] w-[20px] h-[22px] w-[22px] h-[24px] w-[24px] h-[28px] w-[28px] h-[36px] w-[36px]"></div> -<div class="hidden text-[12px] text-[15px] text-[16px] text-[18px] text-[19px] text-[20px] text-[21px] text-[23px] text-[24px] text-[26px] text-[28px] text-[30px] text-[36px] text-[40px]"></div> +<div class="hidden 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]"></div> <div class="hidden h-tabs_mobile_base pt-h_tabs_mobile_base pb-h_tabs_mobile_base translate-y-h_tabs_mobile_base -translate-y-h_tabs_mobile_base h-tabs_mobile_y pt-h_tabs_mobile_y pb-h_tabs_mobile_y translate-y-h_tabs_mobile_y -translate-y-h_tabs_mobile_y h-nav_mobile_base pt-h_nav_mobile_base pb-h_nav_mobile_base translate-y-h_nav_mobile_base -translate-y-h_nav_mobile_base h-nav_mobile_y pt-h_nav_mobile_y pb-h_nav_mobile_y translate-y-h_nav_mobile_y -translate-y-h_nav_mobile_y h-view_mobile_base pt-h_view_mobile_base pb-h_view_mobile_base translate-y-h_view_mobile_base -translate-y-h_view_mobile_base h-view_mobile_y pt-h_view_mobile_y pb-h_view_mobile_y translate-y-h_view_mobile_y -translate-y-h_view_mobile_y h-view_offset_mobile_base pt-h_view_offset_mobile_base pb-h_view_offset_mobile_base translate-y-h_view_offset_mobile_base -translate-y-h_view_offset_mobile_base h-view_offset_mobile_y pt-h_view_offset_mobile_y pb-h_view_offset_mobile_y translate-y-h_view_offset_mobile_y -translate-y-h_view_offset_mobile_y h-trellis_centered_mobile_base pt-h_trellis_centered_mobile_base pb-h_trellis_centered_mobile_base translate-y-h_trellis_centered_mobile_base -translate-y-h_trellis_centered_mobile_base h-trellis_centered_mobile_y pt-h_trellis_centered_mobile_y pb-h_trellis_centered_mobile_y translate-y-h_trellis_centered_mobile_y -translate-y-h_trellis_centered_mobile_y w-mobile_base w-mobile_y top-dim_map_offset_top_mobile_base top-dim_map_offset_top_mobile_y"></div> \ No newline at end of file diff --git a/apps-lib/src/lib/el/image_path.svelte b/apps-lib/src/lib/el/image_path.svelte @@ -29,12 +29,12 @@ {#if img_src} <img - id={basis.id || null} - class={`${fmt_cl(basis.path)}`} + id={basis?.id || null} + class={`${fmt_cl(basis?.classes)}`} src={img_src} - alt={basis.alt || null} + alt={basis?.alt || null} on:click|stopPropagation={async (ev) => { - if (basis.callback) await basis.callback(ev); + if (basis?.callback) await basis.callback(ev); }} /> {/if} diff --git a/apps-lib/src/lib/el/input_element.svelte b/apps-lib/src/lib/el/input_element.svelte @@ -30,7 +30,7 @@ $: classes_layer = typeof basis?.layer === `boolean` ? `` - : `text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`; + : `bg-layer-${layer}-surface text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`; $: if (basis?.id && basis?.sync && value) { (async () => { try { @@ -84,6 +84,9 @@ on:blur={async ({ currentTarget: el }) => { if (basis.callback_blur) await basis.callback_blur({ el }); }} + on:focus={async ({ currentTarget: el }) => { + if (basis.callback_focus) await basis.callback_focus({ el }); + }} on:keydown={async (ev) => { if (basis?.callback_keydown) await basis?.callback_keydown({ diff --git a/apps-lib/src/lib/el/textarea_element.svelte b/apps-lib/src/lib/el/textarea_element.svelte @@ -73,15 +73,21 @@ <textarea bind:this={el} bind:value - {id} - contenteditable="true" - class={`${fmt_cl(basis.classes)} el-textarea w-full bg-layer-${layer}-surface text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} - placeholder={basis.placeholder || ``} on:input={async ({ currentTarget: el }) => { await handle_on_input(el); }} + on:blur={async ({ currentTarget: el }) => { + if (basis.callback_blur) await basis.callback_blur({ el }); + }} + on:focus={async ({ currentTarget: el }) => { + if (basis.callback_focus) await basis.callback_focus({ el }); + }} on:keydown={async (ev) => { if (basis.callback_keydown) await basis.callback_keydown({ key: ev.key }); }} + {id} + contenteditable="true" + class={`${fmt_cl(basis.classes)} el-textarea w-full bg-layer-${layer}-surface text-layer-${layer}-glyph placeholder:text-layer-${layer}-glyph_pl caret-layer-${layer}-glyph`} + placeholder={basis.placeholder || ``} /> diff --git a/apps-lib/src/lib/global.d.ts b/apps-lib/src/lib/global.d.ts @@ -1,4 +1,5 @@ declare module "$app/navigation"; +declare module "$app/stores"; declare class Keyva { /** diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -67,10 +67,13 @@ export { default as BadgeInfoKey } from "./components/badge_info_key.svelte"; export { default as EnvelopeTitled } from "./components/envelope_titled.svelte"; export { default as ButtonLoading } from "./components/button_loading.svelte"; export { default as TrellisOffset } from "./components/trellis_offset.svelte"; +export { default as LogoCircleSm } from "./components/logo_circle_sm.svelte"; export { default as EntrySelect } from "./components/entry_select.svelte"; export { default as Nav } from "./components/nav.svelte"; export { default as ButtonLayoutPair } from "./components/button_layout_pair.svelte"; +export { default as TabsFloat } from "./components/tabs_float.svelte"; export { default as LoadingView } from "./components/loading_view.svelte"; export { default as NavOption } from "./components/nav_option.svelte"; +export { default as LogoCircle } from "./components/logo_circle.svelte"; export { default as TrellisRowLabel } from "./components/trellis_row_label.svelte"; export { default as LayoutView } from "./components/layout_view.svelte"; diff --git a/apps-lib/src/lib/locales/en/common.json b/apps-lib/src/lib/locales/en/common.json @@ -20,10 +20,12 @@ "bio": "Bio", "business_name": "Business name", "cancel": "Cancel", + "choose_a_profile_name": "Choose a profile name", "close": "Close", "color_mode": "Color mode", "complete": "Complete", "configure": "Configure", + "configure_your_device": "Configure your device", "connect": "Connect", "connected": "Connected", "connection": "Connection", @@ -131,6 +133,7 @@ "subject": "Subject", "submit": "Submit", "summary": "Summary", + "terms_of_use_agreement": "Terms of Use agreement", "title": "Title", "to": "To", "unlock": "Unlock", diff --git a/apps-lib/src/lib/types/components.ts b/apps-lib/src/lib/types/components.ts @@ -92,13 +92,18 @@ export type IEnvelopeTitledBasis = { } }; +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 = { - prev: ICbOpt & { + prev: ICbOpt & ILoadingOpt & { label?: string; route: NavigationRoute | [NavigationRoute, NavigationParamTuple[]]; prevent_route?: { diff --git a/apps-lib/src/lib/types/el.ts b/apps-lib/src/lib/types/el.ts @@ -4,6 +4,7 @@ import type { ThemeLayer } from "@radroots/theme"; export type GlyphKeyCurrency = `dollar` | `eur`; export type GlyphKey = | + `images-square` | `bell` | `columns` | `bold` | @@ -167,14 +168,11 @@ export type IInputElement = IId & IClOpt & ILyOptTs & { hidden?: boolean; validate?: RegExp; sync?: boolean; - // sync_init?: string; field?: IFormField; - /*notify_inline?: { - glyph: GlyphKey | IGlyph; - };*/ callback?: CallbackPromiseGeneric<{ value: string; pass: boolean; }>; callback_keydown?: CallbackPromiseGeneric<{ key: string; el: HTMLInputElement }>; callback_blur?: CallbackPromiseGeneric<{ el: HTMLInputElement }>; + callback_focus?: CallbackPromiseGeneric<{ el: HTMLInputElement }>; on_mount?: CallbackPromiseGeneric<HTMLInputElement>; }; @@ -184,12 +182,10 @@ export type ITextAreaElement = IId & IClOpt & ILyOptTs & { hidden?: boolean; validate?: RegExp; sync?: true; - //sync_init?: true | string; field?: IFormField; - /*notify_inline?: { - glyph: GlyphKey | IGlyph; - };*/ callback?: CallbackPromiseGeneric<{ value: string; pass: boolean; }>; callback_keydown?: CallbackPromiseGeneric<{ key: string; }>; + callback_blur?: CallbackPromiseGeneric<{ el: HTMLTextAreaElement }>; + callback_focus?: CallbackPromiseGeneric<{ el: HTMLTextAreaElement }>; on_mount?: CallbackPromiseGeneric<HTMLTextAreaElement>; }; \ No newline at end of file diff --git a/apps-lib/src/lib/utils/routes.ts b/apps-lib/src/lib/utils/routes.ts @@ -12,6 +12,7 @@ export type NavigationRoute = | "/settings" | "/settings/nostr" | "/settings/profile" + | "/settings/profile/edit" | "/test" | "/cfg/error" | "/cfg/init"; @@ -31,6 +32,7 @@ export function parse_route(route: string): NavigationRoute { case "/settings": case "/settings/nostr": case "/settings/profile": + case "/settings/profile/edit": case "/test": case "/cfg/error": case "/cfg/init":