web_lib

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

input-pwa.svelte (3592B)


      1 <script lang="ts">
      2     import { browser } from "$app/environment";
      3     import { idb_kv } from "$lib/utils/keyval";
      4     import {
      5         fmt_cl,
      6         type IInput,
      7         parse_layer,
      8         value_constrain,
      9     } from "@radroots/apps-lib";
     10     import { handle_err } from "@radroots/utils";
     11     import { onMount } from "svelte";
     12 
     13     let {
     14         basis,
     15         el = $bindable(null),
     16         value = $bindable(``),
     17     }: {
     18         basis: IInput<string>;
     19         el?: HTMLInputElement | null;
     20         value?: string;
     21     } = $props();
     22 
     23     const id = $derived(basis?.id ? basis.id : null);
     24     const layer = $derived(
     25         typeof basis?.layer === `boolean` ? 0 : parse_layer(basis?.layer),
     26     );
     27     const classes_layer = $derived(
     28         typeof basis?.layer === `boolean` || typeof basis?.layer === `undefined`
     29             ? ``
     30             : `bg-ly${layer} text-ly${layer}-gl_d placeholder:text-ly${layer}-gl_pl caret-ly${layer}-gl`,
     31     );
     32 
     33     const sync_from_idb = async (): Promise<void> => {
     34         if (!browser || !id || !idb_kv) return;
     35         try {
     36             const kv_val = await idb_kv.get<string | undefined>(id);
     37             if (kv_val !== null && kv_val !== undefined && kv_val !== value) {
     38                 value = kv_val;
     39             } else if (kv_val === null || kv_val === undefined) {
     40                 value = ``;
     41                 await idb_kv.set(id, ``);
     42             }
     43         } catch (e) {
     44             handle_err(e, `sync_from_idb`);
     45         }
     46     };
     47 
     48     const sync_to_idb = async (): Promise<void> => {
     49         if (!browser || !id || !idb_kv) return;
     50         try {
     51             await idb_kv.set(id, value || ``);
     52         } catch (e) {
     53             handle_err(e, `input_idb_sync`);
     54         }
     55     };
     56 
     57     onMount(async () => {
     58         await sync_from_idb();
     59         if (basis?.callback_mount && el) {
     60             try {
     61                 await basis.callback_mount({ el });
     62             } catch (e) {
     63                 handle_err(e, `callback_mount`);
     64             }
     65         }
     66     });
     67 
     68     $effect(() => {
     69         if (id && basis?.sync && browser) {
     70             (async () => {
     71                 await sync_to_idb();
     72             })();
     73         }
     74     });
     75 
     76     const handle_on_input = async (): Promise<void> => {
     77         try {
     78             let val_cur = value;
     79             let pass = true;
     80             if (basis?.field) {
     81                 val_cur = value_constrain(basis.field?.charset, val_cur);
     82                 if (val_cur !== value) {
     83                     value = val_cur;
     84                 }
     85                 pass = basis.field?.validate.test(val_cur);
     86             }
     87             if (basis?.callback) {
     88                 await basis.callback({ value: val_cur, pass });
     89             }
     90         } catch (e) {
     91             handle_err(e, `handle_on_input`);
     92         }
     93     };
     94 </script>
     95 
     96 <input
     97     bind:this={el}
     98     bind:value
     99     disabled={!!basis.disabled}
    100     oninput={handle_on_input}
    101     onblur={async ({ currentTarget: el }) => {
    102         if (basis.callback_blur) await basis.callback_blur({ el });
    103     }}
    104     onfocus={async ({ currentTarget: el }) => {
    105         if (id && basis.sync && browser) await sync_from_idb();
    106         if (basis.callback_focus) await basis.callback_focus({ el });
    107     }}
    108     onkeydown={async (ev) => {
    109         if (basis?.callback_keydown)
    110             await basis.callback_keydown({
    111                 key: ev.key,
    112                 key_s: ev.key === `Enter`,
    113                 el: ev.currentTarget,
    114             });
    115     }}
    116     {id}
    117     type="text"
    118     class={`${fmt_cl(basis?.classes)} el-input ${classes_layer} el-re`}
    119     placeholder={basis?.placeholder || ``}
    120 />