web_lib

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

commit 2e42594ad550e2bc0c19e16c22614ca4880a690e
parent 9443e0a83a7a3eb082f543b61de8e4db6e6fcea3
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Mon, 26 Aug 2024 10:53:29 +0000

apps-lib: add trellis component, temporarily define stores in `app` lib

Diffstat:
Aapps-lib/src/lib/components/trellis.svelte | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_default_label.svelte | 38++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_end.svelte | 31+++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_offset.svelte | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_row_display_value.svelte | 41+++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_row_label.svelte | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_title.svelte | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/components/trellis_touch.svelte | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/index.ts | 15+++++++++++++--
Dapps-lib/src/lib/stores/client.ts | 24------------------------
Dapps-lib/src/lib/types.ts | 14--------------
Aapps-lib/src/lib/types/client.ts | 181+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/types/trellis.ts | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapps-lib/src/lib/types/ui.ts | 10++++++++++
Aapps-lib/src/lib/ui/fill.svelte | 3+++
Aapps-lib/src/lib/ui/glyph.svelte | 37+++++++++++++++++++++++++++++++++++++
Mapps-lib/src/lib/utils/client.ts | 30++++++++++++++++++++++++++++--
17 files changed, 808 insertions(+), 42 deletions(-)

diff --git a/apps-lib/src/lib/components/trellis.svelte b/apps-lib/src/lib/components/trellis.svelte @@ -0,0 +1,107 @@ +<script lang="ts"> + import { + fmt_cl, + parse_layer, + t, + trellis_default_label, + trellis_offset, + trellis_title, + trellis_touch, + type ITrellis, + } from ".."; + + const class_rounded = `xl`; + + export let basis: { args: ITrellis }; + $: ({ args } = basis); + $: hide_border_t = + typeof args.hide_border_top === `boolean` ? args.hide_border_top : true; + $: hide_border_b = + typeof args.hide_border_bottom === `boolean` + ? args.hide_border_bottom + : true; + $: hide_rounded = + typeof args.hide_rounded === `boolean` ? args.hide_rounded : false; + $: set_title_background = + typeof args.set_title_background === `boolean` + ? args.set_title_background + : false; + $: set_default_background = + typeof args.set_default_background === `boolean` + ? args.set_default_background + : false; +</script> + +<div + id={basis.args.id || ""} + class={`${fmt_cl(args.classes)} flex flex-col w-full`} + data-view={basis.args.view || ""} +> + <div + class={`relative flex flex-col h-auto w-auto gap-[3px] ${set_title_background ? `bg-layer-${args.layer}-surface` : ``}`} + > + {#if args.title && (!args.default_el || (args.default_el && args.default_el.show_title))} + <svelte:component + this={trellis_title} + basis={args.title} + layer={parse_layer(args.layer - 1)} + /> + {/if} + {#if args.default_el} + <div + class={`flex flex-col h-auto w-full justify-center items-center`} + > + {#if $$slots.default_el} + <slot name="default_el" /> + {:else if args.default_el} + <svelte:component + this={trellis_default_label} + layer={parse_layer(args.layer - 1)} + labels={args.default_el.labels + ? args.default_el.labels + : [ + { + label: `${$t(`glossary.no_items_to_display`)}.`, + }, + ]} + /> + {/if} + </div> + {:else if args.list} + <div class={`flex flex-col w-full justify-center items-center`}> + {#each args.list as basis} + <div + class={`${basis.hide_field ? "hidden" : ""} group flex flex-row h-full w-full justify-end items-center bg-layer-${args.layer}-surface ${basis.full_rounded ? `rounded-${class_rounded}` : ``} ${hide_rounded ? `` : `first:rounded-t-${class_rounded} last:rounded-b-${class_rounded}`} ${!basis.hide_active ? `active:bg-layer-${args.layer}-surface_a` : ``} transition-all`} + > + <div + class={`flex flex-row h-full w-full gap-1 items-center overflow-y-hidden`} + > + <svelte:component + this={trellis_offset} + basis={basis.offset} + /> + {#if `touch` in basis && basis.touch} + <svelte:component + this={trellis_touch} + basis={basis.touch} + layer={args.layer} + {hide_border_b} + {hide_border_t} + hide_active={!!basis.hide_active} + /> + {/if} + </div> + </div> + {/each} + </div> + {/if} + </div> + {#if $$slots.append} + <div + class={`flex flex-col w-full ${set_default_background ? `bg-layer-${args.layer}-surface` : ``}`} + > + <slot name="append" /> + </div> + {/if} +</div> +<div class={`hidden rounded-xl first:rounded-t-xl last:rounded-b-xl`}></div> diff --git a/apps-lib/src/lib/components/trellis_default_label.svelte b/apps-lib/src/lib/components/trellis_default_label.svelte @@ -0,0 +1,38 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { fmt_cl, type ITrellisDefaultLabel } from ".."; + + export let classes = ``; + export let layer: ThemeLayer; + export let labels: ITrellisDefaultLabel[]; +</script> + +<div class={`${fmt_cl(classes)} flex flex-row`}> + <p + class={`glyph font-sans text-labelTrellis text-layer-${layer}-glyph-shade`} + > + {#each labels as label} + <span + class={`${fmt_cl(label.classes)} glyph font-sans text-labelTrellis`} + > + {#if `route` in label} + <a href={label.route}> + {label.label} + </a> + {:else if `callback` in label} + <button + class={``} + on:click|preventDefault={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_end.svelte b/apps-lib/src/lib/components/trellis_end.svelte @@ -0,0 +1,31 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { glyph, type ITrellisBasisTouchEnd } from ".."; + + export let basis: ITrellisBasisTouchEnd; + export let layer: ThemeLayer; + export let hide_active: boolean; +</script> + +<div + class={`absolute top-0 right-0 h-full w-max flex flex-row justify-center items-center`} +> + <button + class={`flex pr-3`} + on:click|preventDefault={async (ev) => { + if (basis.callback) await basis.callback(ev); + }} + > + {#if basis.icon} + <svelte:component + this={glyph} + basis={{ + classes: `text-layer-${layer}-glyph-shade ${hide_active ? `` : `group-active:text-layer-${layer}-glyph_a`} translate-y-[1px] opacity-70`, + dim: `xs-`, + weight: `bold`, + ...basis.icon, + }} + /> + {/if} + </button> +</div> diff --git a/apps-lib/src/lib/components/trellis_offset.svelte b/apps-lib/src/lib/components/trellis_offset.svelte @@ -0,0 +1,51 @@ +<script lang="ts"> + import { + fill, + fmt_cl, + glyph, + type ITrellisBasisOffset, + type ITrellisBasisOffsetMod, + } from ".."; + + export let basis: ITrellisBasisOffset | undefined; + + let mod: ITrellisBasisOffsetMod = `sm`; + $: mod = basis && basis.mod ? basis.mod : `sm`; +</script> + +{#if mod !== `none`} + <div class={`flex flex-row h-full`}> + {#if mod === `sm`} + <div class={`${fmt_cl(``)} flex flex-row h-full w-[22px]`}> + <svelte:component this={fill} /> + </div> + {:else if mod === `glyph`} + <div class={`flex flex-row pr-[2px]`}> + <div + class={`${fmt_cl(``)} flex flex-row h-full w-trellisOffset`} + > + <svelte:component this={fill} /> + </div> + </div> + {:else if typeof mod === `object`} + <div + class={`flex flex-row h-full min-w-[20px] w-trellisOffset justify-center items-center`} + > + <button + class={`fade-in pl-2 translate-x-[3px] translate-y-[1px]`} + on:click|preventDefault={async (ev) => { + if (typeof basis !== `boolean` && basis?.callback) + await basis.callback(ev); + }} + > + <svelte:component + this={glyph} + basis={{ + ...mod, + }} + /> + </button> + </div> + {/if} + </div> +{/if} diff --git a/apps-lib/src/lib/components/trellis_row_display_value.svelte b/apps-lib/src/lib/components/trellis_row_display_value.svelte @@ -0,0 +1,41 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { + fmt_cl, + get_label_classes, + glyph, + type ITrellisKindDisplayValue, + } from ".."; + + export let basis: ITrellisKindDisplayValue; + export let layer: ThemeLayer; + export let hide_active: boolean; + export let end_offset: boolean = false; +</script> + +<button + class={`z-10 flex flex-grow justify-end ${end_offset ? `pr-[22px]` : ``}`} + on:click|preventDefault={async (ev) => { + if (basis && basis.callback) await basis.callback(ev); + }} +> + {#if `icon` in basis} + <svelte:component + this={glyph} + basis={{ + classes: + basis.icon.classes || + `text-layer-${layer}-glyph-shade ${hide_active ? `` : `group-active:text-layer-${layer}-glyph_a`}`, + key: basis.icon.key, + weight: `bold`, + dim: `sm`, + }} + /> + {:else if basis.label} + <p + class={`${fmt_cl(basis.label.classes)} glyph font-sans text-lineTrellis line-clamp-1 ${get_label_classes(layer, basis.label.kind, hide_active)} transition-all`} + > + {basis.label.value} + </p> + {/if} +</button> diff --git a/apps-lib/src/lib/components/trellis_row_label.svelte b/apps-lib/src/lib/components/trellis_row_label.svelte @@ -0,0 +1,53 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { fmt_cl, get_label_classes, glyph, type ILabelTupFields } from ".."; + + export let basis: ILabelTupFields; + export let layer: ThemeLayer; + export let hide_active: boolean; +</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 w-content items-center`}> + {#each basis.left as title_l} + <div + class={`flex flex-row h-full max-w-fit gap-1 items-center ${title_l.hide_truncate ? `` : `truncate`}`} + > + {#if title_l.icon} + <svelte:component + this={glyph} + basis={{ ...title_l.icon }} + /> + {/if} + <p + class={`${fmt_cl(title_l.classes)} ${get_label_classes(layer, title_l.kind, hide_active)} ${title_l.hide_truncate ? `` : `truncate`} glyph font-sans text-lineTrellis transition-all`} + > + {title_l.value || ``} + </p> + </div> + {/each} + </div> + {/if} + {#if basis.right && basis.right.length} + <div class={`flex flex-row h-full w-content items-center justify-end`}> + {#each basis.right.reverse() as title_r} + <div + class={`${fmt_cl(title_r.classes)} flex flex-row h-full max-w-fit gap-1 items-center ${title_r.hide_truncate ? `` : `truncate`}`} + > + {#if title_r.icon} + <svelte:component + this={glyph} + basis={{ ...title_r.icon }} + /> + {/if} + <p + class={`${get_label_classes(layer, title_r.kind, hide_active)} ${title_r.hide_truncate ? `` : `truncate`} glyph truncate font-sans text-lineTrellis transition-all`} + > + {title_r.value || ``} + </p> + </div> + {/each} + </div> + {/if} +</div> diff --git a/apps-lib/src/lib/components/trellis_title.svelte b/apps-lib/src/lib/components/trellis_title.svelte @@ -0,0 +1,59 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { fill, fmt_cl, glyph, type ITrellisTitle } from ".."; + + export let basis: ITrellisTitle; + export let layer: ThemeLayer; + + $: mod = basis && basis.mod ? basis.mod : `sm`; +</script> + +<div + class={`${fmt_cl(basis.classes)} flex flex-row h-[24px] w-full pl-[6px] 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]` : ``}`} + on:click|preventDefault={async () => { + if (basis && basis.callback) await basis.callback(); + }} + > + {#if basis.value === true} + <svelte:component this={fill} /> + {:else} + <p + class={`glyph font-sans text-labelTrellis 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`} + on:click|preventDefault={async () => { + if (basis.link && basis.link.callback) + await basis.link.callback(); + }} + > + {#if basis.link.glyph} + <p + class={`${fmt_cl(basis.link.glyph.classes)} glyph font-sans text-labelTrellis uppercase fade-in`} + > + {basis.link.glyph.value || ``} + </p> + {/if} + {#if basis.link.icon} + <div class={`flex flex-row w-max`}> + <svelte:component + this={glyph} + basis={{ + ...basis.link.icon, + dim: `xs-`, + classes: `${fmt_cl(basis.link.icon.classes)} fade-in`, + }} + /> + </div> + {/if} + </button> + {/if} +</div> diff --git a/apps-lib/src/lib/components/trellis_touch.svelte b/apps-lib/src/lib/components/trellis_touch.svelte @@ -0,0 +1,64 @@ +<script lang="ts"> + import type { ThemeLayer } from "@radroots/theme"; + import { + fmt_trellis, + sleep, + trellis_end, + trellis_row_display_value, + trellis_row_label, + type ITrellisBasisTouch, + } from ".."; + + export let basis: ITrellisBasisTouch; + export let layer: ThemeLayer; + export let hide_border_t: boolean; + export let hide_border_b: boolean; + export let hide_active: boolean; +</script> + +<div class={`flex flex-row flex-grow overflow-x-hidden`}> + <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 transition-all`} + > + <button + class={`relative group flex flex-row h-line w-full pl-[2px] pr-[2px] justify-between items-center transition-all`} + on:click={async (ev) => { + await sleep(100); + if (basis.callback) await basis.callback(ev); + }} + > + <div + class={`flex flex-row h-full w-full justify-between items-center`} + > + <svelte:component + this={trellis_row_label} + basis={basis.label} + {layer} + {hide_active} + /> + {#if basis.display} + <svelte:component + this={trellis_row_display_value} + basis={{ + ...basis.display, + callback: async (ev) => { + //@todo + }, + }} + {layer} + {hide_active} + end_offset={!!basis.end} + /> + {/if} + </div> + {#if basis.end} + <svelte:component + this={trellis_end} + basis={basis.end} + {layer} + {hide_active} + /> + {/if} + </button> + </div> +</div> diff --git a/apps-lib/src/lib/index.ts b/apps-lib/src/lib/index.ts @@ -1,6 +1,17 @@ export * from "./locales/i18n" -export * from "./stores/client" -export * from "./types" +export { default as trellis } from "./components/trellis.svelte" +export { default as trellis_default_label } from "./components/trellis_default_label.svelte" +export { default as trellis_end } from "./components/trellis_end.svelte" +export { default as trellis_offset } from "./components/trellis_offset.svelte" +export { default as trellis_row_display_value } from "./components/trellis_row_display_value.svelte" +export { default as trellis_row_label } from "./components/trellis_row_label.svelte" +export { default as trellis_title } from "./components/trellis_title.svelte" +export { default as trellis_touch } from "./components/trellis_touch.svelte" +export * from "./types/client" +export * from "./types/trellis" +export * from "./types/ui" export { default as css_static } from "./ui/css_static.svelte" +export { default as fill } from "./ui/fill.svelte" +export { default as glyph } from "./ui/glyph.svelte" export * from "./utils/client" export * from "./utils/dom" diff --git a/apps-lib/src/lib/stores/client.ts b/apps-lib/src/lib/stores/client.ts @@ -1,24 +0,0 @@ -import type { AppLayoutKey, NavigationPreviousParam } from "$lib/types"; -import { type ColorMode, type ThemeKey } from "@radroots/theme"; -import { writable } from "svelte/store"; - -export const app_thc = writable<ColorMode>(`light`); -export const app_thm = writable<ThemeKey>(`os`); - -export const app_config = writable<boolean>(true); -export const app_render = writable<boolean>(true); -export const app_lo = writable<AppLayoutKey>(`base`); -export const app_win = writable<[number, number]>([0, 0]); - -export const app_nav_visible = writable<boolean>(false); -export const app_nav_blur = writable<boolean>(false); - -export const app_tabs_visible = writable<boolean>(false); -export const app_tabs_blur = writable<boolean>(false); -export const app_tab_active = writable<number>(0); - -export const app_key = writable<string>(``); -export const app_pwa_polyfills = writable<boolean>(false); -export const app_sqlite = writable<boolean>(false); - -export const app_nav = writable<NavigationPreviousParam[]>([]); diff --git a/apps-lib/src/lib/types.ts b/apps-lib/src/lib/types.ts @@ -1,14 +0,0 @@ -import type { Snippet } from "svelte"; - -export type AppLayoutKey = 'lg' | 'base'; -type NavigationRouteBasis = string; -export type AnchorRoute = `/${string}`; -export type NavigationRouteParamPublicKey = `pk`; -export type NavigationRouteParamId = `id`; -export type NavigationRouteParamKey = NavigationRouteParamPublicKey | NavigationRouteParamId; -export type NavigationParamTuple = [NavigationRouteParamKey, string]; -export type NavigationPreviousParam = { route: NavigationRouteBasis, params?: NavigationParamTuple[] } - -export type PropChildren = { - children: Snippet; -}; diff --git a/apps-lib/src/lib/types/client.ts b/apps-lib/src/lib/types/client.ts @@ -0,0 +1,181 @@ +import type { ThemeLayer } from "@radroots/theme"; +import type { IGlyph } from "./ui"; +import type { Snippet } from "svelte"; + +export type PropChildren = { + children: Snippet; +}; + +export type AppLayoutKey = 'lg' | 'base'; +type NavigationRouteBasis = string; +export type AnchorRoute = `/${string}`; +export type NavigationRouteParamPublicKey = `pk`; +export type NavigationRouteParamId = `id`; +export type NavigationRouteParamCmd = `cmd`; +export type NavigationRouteParamKey = NavigationRouteParamPublicKey | NavigationRouteParamId | NavigationRouteParamCmd; +export type NavigationParamTuple = [NavigationRouteParamKey, string]; +export type NavigationPreviousParam = { route: NavigationRouteBasis, label?: string; params?: NavigationParamTuple[] } + +export type GeometryScreenPositionHorizontal = `left` | `center` | `right`; +export type GeometryScreenPositionVertical = `top` | `center` | `bottom`; +export type GeometryScreenPosition = `${GeometryScreenPositionVertical}-${GeometryScreenPositionHorizontal}`; +export type GeometryCardinalDirection = `up` | `down` | `left` | `right`; +export type GeometryDimension = + `xs` | + `sm` | + `md` | + `lg` | + `xl`; +export type GeometryGlyphDimension = + | `${GeometryDimension}` + | `${GeometryDimension}-` + | `${GeometryDimension}+`; + +export type GlyphKey = | + `devices` | + `lock-key` | + `gear-fine` | + `bell-simple` | + `envelope` | + `house-line` | + `arrows-left-right` | + `list-plus` | + `squares-four` | + `list-plus` | + `app-window` | + `circle-notch` | + `subtract-square` | + `device-tablet-speaker` | + `weather-cloud` | + `warning` | + `circle-notch` | + `minus` | + `key` | + `arrow-u-up-left` | + `arrow-counter-clockwise` | + `circle` | + `check-circle` | + `circle-dashed` | + `dots-three` | + `cards-three` | + `lightning` | + `cards` | + `note-pencil` | + `tray` | + `calendar-dots` | + `notepad` | + `network` | + `calendar-blank` | + `chats-circle` | + `plant` | + `farm` | + `magnifying-glass` | + `chat-circle-dots` | + `dots-three-outline` | + `copy` | + `circles-four` | + `waveform` | + `film-strip` | + `arrow-up` | + `arrow-circle-up` | + `plus` | + `funnel-simple` | + `user` | + `camera` | + `check` | + `file` | + `share-network` | + `question` | + `minus-circle` | + `globe-simple` | + `globe` | + `warning-circle` | + `x` | + `info` | + `caret-${GeometryCardinalDirection}` | + `caret-up-down`; + +export type GlyphWeight = `light` | `regular` | `fill` | `bold`; // `thin` `duotone` + +export type CallbackPromiseGeneric<T> = (value: T) => Promise<void>; +export type CallbackPromise = () => Promise<void>; + +export type NavigationRoute = string; //@todo + +export type IRoute = { + route: NavigationRoute; +}; + +export type IRouteOpt = { + route?: NavigationRoute; +}; + +export type ICbGR<T> = ICbG<T> | IRoute + +export type ICb = { + callback: CallbackPromise; +}; + +export type ICbOpt = { + callback?: CallbackPromise; +}; + +export type ICbG<T> = { + callback: CallbackPromiseGeneric<T>; +}; + +export type ICbGOpt<T> = { + callback?: CallbackPromiseGeneric<T>; +}; + +export type ICbROpt = ICbOpt | IRouteOpt + +export type IClOpt = { + classes?: string; +}; + +export type ILy = { + layer: ThemeLayer; +}; + +export type IGlOpt = { + icon?: IGlyph; +} + +export type IGlyphOpt = { + glyph?: IGlyphFields; +}; + +export type IGlyphFields = { + value: string; + classes?: string; +}; + +export type ILabel = { + label: ILableFields; +}; + +export type ILabelOpt = { + label?: ILableFields; +}; + +export type ILabelTup = { + label: ILabelTupFields; +}; + +export type ILabelTupFields = { + left?: ILableFields[]; + right?: ILableFields[]; +}; + +export type ILableFields = IGlOpt & { + value: string; + swap?: string; + classes?: string + kind?: LabelFieldKind + hide_truncate?: boolean; + hide_active?: boolean; +}; + +export type LabelFieldKind = `link` | `on` | `shade`; + diff --git a/apps-lib/src/lib/types/trellis.ts b/apps-lib/src/lib/types/trellis.ts @@ -0,0 +1,92 @@ +import type { GlyphKey, ICbGOpt, ICbOpt, ICbROpt, IClOpt, IGlyphOpt, ILabel, ILabelTup, ILy } from "./client"; +import type { IGlyph } from "./ui"; + +export type ITrellis = ILy & + IClOpt & + ITrellisStyles & { + id?: string; + view?: string; + title?: ITrellisTitle; + description?: ITrellisDescription; + default_el?: ITrellisDefault; + list?: ITrellisKind[]; + }; + +export type ITrellisTitle = ICbOpt & + IClOpt & { + mod?: ITrellisBasisOffsetMod, + value: string | true; + link?: ICbOpt & + IClOpt & + IGlyphOpt & { + icon?: IGlyph; + }; + }; + +export type ITrellisDescription = string | true; + +export type ITrellisDefault = { + labels?: ITrellisDefaultLabel[]; + show_title?: boolean; +}; + +export type ITrellisDefaultLabel = ICbROpt & { + label: string; + classes?: string; +}; + +export type ITrellisStyles = { + hide_rounded?: boolean; + hide_border_top?: boolean; + hide_border_bottom?: boolean; + set_title_background?: boolean; + set_default_background?: boolean; +}; + +export type ITrellisBasisOffsetModKey = 'none' | 'sm' | 'glyph'; +export type ITrellisBasisOffsetMod = ITrellisBasisOffsetModKey | IGlyph; + +export type ITrellisKind = ( + | ITrellisKindTouch +); + +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 ITrellisKindDisplayValue = ICbGOpt<MouseEvent> & + (ITrellisKindDisplayValueIcon | ILabel); + +export type ITrellisBasisTouchEnd = ICbGOpt<MouseEvent> & { + icon: IGlyph; +}; + +export type ITrellisKindDisplayValueIcon = { + icon: { + classes?: string; + key: GlyphKey; + }; +}; + + +export type ITrellisKindTouch = ITrellisBasis & { + touch: ITrellisBasisTouch; +}; + +export type ITrellisBasisTouch = ICbGOpt<MouseEvent> & + ILabelTup & { + end?: ITrellisBasisTouchEnd; + display?: ITrellisKindDisplayValue; + }; diff --git a/apps-lib/src/lib/types/ui.ts b/apps-lib/src/lib/types/ui.ts @@ -0,0 +1,10 @@ +import type { ThemeLayer } from "@radroots/theme"; +import type { GeometryGlyphDimension, ICbOpt, GlyphKey, GlyphWeight } from "./client"; + +export type IGlyph = ICbOpt & { + layer?: ThemeLayer; + classes?: string; + weight?: GlyphWeight; + key: GlyphKey; + dim?: GeometryGlyphDimension; +}; diff --git a/apps-lib/src/lib/ui/fill.svelte b/apps-lib/src/lib/ui/fill.svelte @@ -0,0 +1,3 @@ +<div class={`flex flex-fill text-transparent`}> + <p class={`font-sans`}>{`~`}</p> +</div> diff --git a/apps-lib/src/lib/ui/glyph.svelte b/apps-lib/src/lib/ui/glyph.svelte @@ -0,0 +1,37 @@ +<script lang="ts"> + import type { GeometryGlyphDimension } from "../types/client"; + import type { IGlyph } from "../types/ui"; + import { fmt_cl } from "../utils/client"; + + const glyph_map: Map<GeometryGlyphDimension, string> = new Map([ + [`xs-`, `text-[13px]`], + [`xs`, `text-[15px]`], + [`xs+`, `text-[18px]`], + [`sm`, `text-[20px]`], + [`sm+`, `text-[21px]`], + [`md-`, `text-[23px]`], + [`md`, `text-[24px]`], + [`md+`, `text-[27px]`], + [`lg`, `text-[28px]`], + [`xl`, `text-[30px]`], + ]); + + let { basis }: { basis: IGlyph } = $props(); + + let weight = $derived( + !basis?.weight || basis?.weight === `regular` ? `` : `-${basis.weight}`, + ); + + let dimension = $derived( + basis?.dim ? glyph_map.get(basis.dim) : glyph_map.get(`sm`), + ); +</script> + +<button + class={`${fmt_cl(basis.classes)} flex flex-row justify-center items-center transition-all ${dimension}`} + onclick={async () => { + if (basis.callback) await basis.callback(); + }} +> + <i class="ph{weight} ph-{basis.key}"></i> +</button> diff --git a/apps-lib/src/lib/utils/client.ts b/apps-lib/src/lib/utils/client.ts @@ -1,12 +1,38 @@ +import type { LabelFieldKind } from "$lib/types/client"; +import type { ColorMode, ThemeKey, ThemeLayer } from "@radroots/theme"; + export const sleep = async (ms: number): Promise<void> => { await new Promise((resolve) => setTimeout(resolve, ms)); }; -export const theme_set = (theme_key: string, color_mode: string): void => { +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 fmtcl = (classes?: string): string => { +export const toggle_color_mode = (color_mode: ColorMode): ColorMode => { + return color_mode === `light` ? `dark` : `light`; +}; + +export const fmt_cl = (classes?: string): string => { return classes ? classes : ``; +}; + +export function get_label_classes(layer: ThemeLayer, label_kind: LabelFieldKind | undefined, hide_active: boolean): string { + return `text-layer-${layer}-glyph${label_kind ? `-${label_kind}` : ``} ${hide_active ? `` : `group-active:text-layer-${layer}-glyph${label_kind ? `-${label_kind}_a` : `_a`}`}` +} + +export function parse_layer(layer?: number): ThemeLayer { + switch (layer) { + case 0: + case 1: + case 2: + return layer; + default: + return 0; + } +}; + +export function fmt_trellis(hide_border_t: boolean, hide_border_b: boolean): string { + return `${hide_border_t ? `group-first:border-t-0` : `group-first:border-t-line`} ${hide_border_b ? `group-last:border-b-0` : `group-last:border-b-line`}`; }; \ No newline at end of file