sibujs 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/LICENSE +21 -21
  2. package/dist/build.cjs +20 -0
  3. package/dist/build.js +1 -1
  4. package/dist/cdn.global.js +4 -4
  5. package/dist/{chunk-MEZVEBPN.js → chunk-32ZISOLJ.js} +22 -0
  6. package/dist/{chunk-7TQKR4PP.js → chunk-AZ3ISID5.js} +4 -0
  7. package/dist/{chunk-3CRQALYP.js → chunk-DKOHBI74.js} +49 -2
  8. package/dist/{chunk-DTCOOBMX.js → chunk-OF7UZIVB.js} +1 -1
  9. package/dist/{chunk-N6IZB6KJ.js → chunk-PBHF5WKN.js} +56 -7
  10. package/dist/{customElement-BKQfbSZQ.d.ts → customElement-yz8uyk-0.d.cts} +52 -6
  11. package/dist/{customElement-BKQfbSZQ.d.cts → customElement-yz8uyk-0.d.ts} +52 -6
  12. package/dist/extras.cjs +111 -9
  13. package/dist/extras.d.cts +3 -2
  14. package/dist/extras.d.ts +3 -2
  15. package/dist/extras.js +9 -5
  16. package/dist/index.cjs +22 -0
  17. package/dist/index.d.cts +27 -2
  18. package/dist/index.d.ts +27 -2
  19. package/dist/index.js +5 -1
  20. package/dist/patterns.d.cts +8 -2
  21. package/dist/patterns.d.ts +8 -2
  22. package/dist/plugins.cjs +142 -1
  23. package/dist/plugins.d.cts +39 -3
  24. package/dist/plugins.d.ts +39 -3
  25. package/dist/plugins.js +119 -3
  26. package/dist/{ssr-WKUPVSSK.js → ssr-6GIMY5MX.js} +5 -3
  27. package/dist/ssr-BA6sxxUd.d.cts +135 -0
  28. package/dist/ssr-BA6sxxUd.d.ts +135 -0
  29. package/dist/ssr.cjs +5 -0
  30. package/dist/ssr.d.cts +3 -113
  31. package/dist/ssr.d.ts +3 -113
  32. package/dist/ssr.js +4 -2
  33. package/dist/ui.cjs +50 -2
  34. package/dist/ui.d.cts +1 -1
  35. package/dist/ui.d.ts +1 -1
  36. package/dist/ui.js +3 -1
  37. package/dist/widgets.cjs +56 -7
  38. package/dist/widgets.d.cts +4 -2
  39. package/dist/widgets.d.ts +4 -2
  40. package/dist/widgets.js +1 -1
  41. package/package.json +139 -139
@@ -35,6 +35,39 @@ declare function email(message?: string): ValidatorFn<string>;
35
35
  declare function min(minVal: number, message?: string): ValidatorFn<number>;
36
36
  declare function max(maxVal: number, message?: string): ValidatorFn<number>;
37
37
  declare function custom<T>(fn: (value: T) => boolean, message: string): ValidatorFn<T>;
38
+ /**
39
+ * Props returned by bindField, ready to spread into an input tag factory.
40
+ */
41
+ interface BoundFieldProps {
42
+ value: () => unknown;
43
+ on: {
44
+ input: (e: Event) => void;
45
+ change: (e: Event) => void;
46
+ blur: () => void;
47
+ };
48
+ [attr: string]: unknown;
49
+ }
50
+ /**
51
+ * Bind a FormField to an input element, eliminating the value/input/blur boilerplate.
52
+ *
53
+ * Works with text inputs (`input` event) and selects/checkboxes (`change` event).
54
+ *
55
+ * @param field A FormField from form().fields
56
+ * @param extras Additional props to merge (placeholder, class, disabled, etc.)
57
+ * @returns Props object ready to pass directly to a tag factory
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const f = form({ email: { initial: "", validators: [required(), email()] } });
62
+ *
63
+ * // Before — verbose
64
+ * input({ value: f.fields.email.value(), on: { input: e => f.fields.email.set(e.target.value), blur: () => f.fields.email.touch() } })
65
+ *
66
+ * // After — one-liner
67
+ * input(bindField(f.fields.email, { type: "email", placeholder: "Email" }))
68
+ * ```
69
+ */
70
+ declare function bindField<T>(field: FormField<T>, extras?: Record<string, unknown>): BoundFieldProps;
38
71
  declare function form<T extends Record<string, unknown>>(config: FormConfig<T>): FormReturn<T>;
39
72
 
40
73
  interface VirtualListProps<T> {
@@ -135,6 +168,10 @@ declare function announce(message: string, priority?: "polite" | "assertive"): v
135
168
  * scopedStyle creates component-scoped CSS by generating a unique scope ID
136
169
  * and prefixing all selectors.
137
170
  * Returns the scope attribute name and injects the CSS into the document.
171
+ *
172
+ * CSS is sanitized to remove dangerous patterns (`url()`, `@import`,
173
+ * `expression()`, `-moz-binding`, `behavior`). If you need `url()` for
174
+ * background images, use inline styles via the `style` prop instead.
138
175
  */
139
176
  declare function scopedStyle(css: string): {
140
177
  scope: string;
@@ -188,15 +225,24 @@ interface Toast {
188
225
  message: string;
189
226
  type?: "info" | "success" | "error" | "warning";
190
227
  }
191
- declare function toast(options?: {
192
- duration?: number;
193
- maxToasts?: number;
194
- }): {
228
+ interface ToastInstance {
195
229
  toasts: () => Toast[];
196
230
  show: (message: string, type?: Toast["type"]) => string;
231
+ /** Show an info toast. */
232
+ info: (message: string) => string;
233
+ /** Show a success toast. */
234
+ success: (message: string) => string;
235
+ /** Show an error toast. */
236
+ error: (message: string) => string;
237
+ /** Show a warning toast. */
238
+ warning: (message: string) => string;
197
239
  dismiss: (id: string) => void;
198
240
  dismissAll: () => void;
199
- };
241
+ }
242
+ declare function toast(options?: {
243
+ duration?: number;
244
+ maxToasts?: number;
245
+ }): ToastInstance;
200
246
 
201
247
  /**
202
248
  * infiniteScroll combines IntersectionObserver with a data-fetching trigger
@@ -259,4 +305,4 @@ declare function defineElement(name: string, component: (props: Record<string, u
259
305
  */
260
306
  declare function svgElement(tag: string, props?: Record<string, unknown>, ...nodes: (SVGElement | string)[]): SVGElement;
261
307
 
262
- export { max as A, maxLength as B, type CustomElementOptions as C, min as D, minLength as E, type FieldConfig as F, pagination as G, phoneMask as H, type IntersectionResult as I, removeScopedStyle as J, required as K, scopedStyle as L, type MaskOptions as M, ssnMask as N, svgElement as O, timeMask as P, toast as Q, withScopedStyle as R, zipMask as S, type Toast as T, type ValidatorFn as V, FocusTrap as a, type FormConfig as b, type FormField as c, type FormReturn as d, VirtualList as e, type VirtualListProps as f, announce as g, aria as h, bindAttrs as i, bindBoolAttr as j, bindData as k, creditCardMask as l, custom as m, dateMask as n, defineElement as o, dialog as p, email as q, eventBus as r, focus as s, form as t, hotkey as u, infiniteScroll as v, inputMask as w, intersection as x, lazyLoad as y, matchesPattern as z };
308
+ export { lazyLoad as A, type BoundFieldProps as B, type CustomElementOptions as C, matchesPattern as D, max as E, type FieldConfig as F, maxLength as G, min as H, type IntersectionResult as I, minLength as J, pagination as K, phoneMask as L, type MaskOptions as M, removeScopedStyle as N, required as O, scopedStyle as P, ssnMask as Q, svgElement as R, timeMask as S, type Toast as T, toast as U, type ValidatorFn as V, withScopedStyle as W, zipMask as X, FocusTrap as a, type FormConfig as b, type FormField as c, type FormReturn as d, type ToastInstance as e, VirtualList as f, type VirtualListProps as g, announce as h, aria as i, bindAttrs as j, bindBoolAttr as k, bindData as l, bindField as m, creditCardMask as n, custom as o, dateMask as p, defineElement as q, dialog as r, email as s, eventBus as t, focus as u, form as v, hotkey as w, infiniteScroll as x, inputMask as y, intersection as z };
package/dist/extras.cjs CHANGED
@@ -40,6 +40,7 @@ __export(extras_exports, {
40
40
  bindAttrs: () => bindAttrs,
41
41
  bindBoolAttr: () => bindBoolAttr,
42
42
  bindData: () => bindData,
43
+ bindField: () => bindField,
43
44
  block: () => block,
44
45
  bounceIn: () => bounceIn,
45
46
  bounceOut: () => bounceOut,
@@ -267,6 +268,7 @@ __export(extras_exports, {
267
268
  triggerPluginError: () => triggerPluginError,
268
269
  triggerPluginMount: () => triggerPluginMount,
269
270
  triggerPluginUnmount: () => triggerPluginUnmount,
271
+ trustHTML: () => trustHTML,
270
272
  uniqueId: () => uniqueId,
271
273
  validateProps: () => validateProps,
272
274
  validators: () => validators,
@@ -2948,6 +2950,34 @@ function max(maxVal, message) {
2948
2950
  function custom(fn, message) {
2949
2951
  return (value) => fn(value) ? null : message;
2950
2952
  }
2953
+ function bindField(field, extras) {
2954
+ const fieldOn = {
2955
+ input: (e) => {
2956
+ const target = e.target;
2957
+ if (target.type === "checkbox") {
2958
+ field.set(target.checked);
2959
+ } else {
2960
+ field.set(target.value);
2961
+ }
2962
+ },
2963
+ change: (e) => {
2964
+ const target = e.target;
2965
+ if ("checked" in target && target.type === "checkbox") {
2966
+ field.set(target.checked);
2967
+ } else {
2968
+ field.set(target.value);
2969
+ }
2970
+ },
2971
+ blur: () => field.touch()
2972
+ };
2973
+ const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
2974
+ const mergedOn = extraOn && typeof extraOn === "object" ? { ...fieldOn, ...extraOn } : fieldOn;
2975
+ return {
2976
+ value: field.value,
2977
+ on: mergedOn,
2978
+ ...restExtras
2979
+ };
2980
+ }
2951
2981
  function form(config) {
2952
2982
  const fieldEntries = Object.entries(config);
2953
2983
  const fieldMap = {};
@@ -3326,10 +3356,19 @@ function announce(message, priority = "polite") {
3326
3356
 
3327
3357
  // src/ui/scopedStyle.ts
3328
3358
  var scopeCounter = 0;
3359
+ function sanitizeCSS(css) {
3360
+ let sanitized = css.replace(/@import\s+[^;]+;/gi, "/* @import removed */");
3361
+ sanitized = sanitized.replace(/url\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* url() removed */");
3362
+ sanitized = sanitized.replace(/expression\s*\(\s*(?:"[^"]*"|'[^']*'|[^)]*)\s*\)/gi, "/* expression() removed */");
3363
+ sanitized = sanitized.replace(/-moz-binding\s*:[^;]+;/gi, "/* -moz-binding removed */");
3364
+ sanitized = sanitized.replace(/behavior\s*:[^;]+;/gi, "/* behavior removed */");
3365
+ return sanitized;
3366
+ }
3329
3367
  function scopedStyle(css) {
3330
3368
  const id = `sibu-s${scopeCounter++}`;
3331
3369
  const attr = `data-${id}`;
3332
- const scopedCSS = css.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, delimiter) => {
3370
+ const safeCss = sanitizeCSS(css);
3371
+ const scopedCSS = safeCss.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, (match, selector, delimiter) => {
3333
3372
  const trimmed = selector.trim();
3334
3373
  if (trimmed.startsWith("@") || trimmed.startsWith("from") || trimmed.startsWith("to") || /^\d+%$/.test(trimmed)) {
3335
3374
  return match;
@@ -3562,7 +3601,16 @@ function toast(options) {
3562
3601
  timers.delete(id);
3563
3602
  }
3564
3603
  }
3565
- return { toasts, show, dismiss, dismissAll };
3604
+ return {
3605
+ toasts,
3606
+ show,
3607
+ info: (message) => show(message, "info"),
3608
+ success: (message) => show(message, "success"),
3609
+ error: (message) => show(message, "error"),
3610
+ warning: (message) => show(message, "warning"),
3611
+ dismiss,
3612
+ dismissAll
3613
+ };
3566
3614
  }
3567
3615
 
3568
3616
  // src/ui/infiniteScroll.ts
@@ -4484,6 +4532,9 @@ function hydrateNode(serverNode, clientNode) {
4484
4532
  hydrateNode(serverChildren[i2], clientChildren[i2]);
4485
4533
  }
4486
4534
  }
4535
+ function trustHTML(html2) {
4536
+ return html2;
4537
+ }
4487
4538
  function renderToDocument(component, options = {}) {
4488
4539
  let content;
4489
4540
  try {
@@ -7976,26 +8027,75 @@ function fileUpload(options) {
7976
8027
  function contentEditable() {
7977
8028
  const [content, setContent] = signal("");
7978
8029
  const [isFocused, setFocused] = signal(false);
7979
- function execCommand(command, value) {
7980
- if (typeof document !== "undefined" && document.execCommand) {
7981
- document.execCommand(command, false, value ?? "");
8030
+ function wrapSelection(tagName) {
8031
+ if (typeof window === "undefined") return;
8032
+ const selection = window.getSelection();
8033
+ if (!selection || selection.rangeCount === 0 || selection.isCollapsed) return;
8034
+ const range = selection.getRangeAt(0);
8035
+ const ancestor = range.commonAncestorContainer;
8036
+ const existingWrap = findAncestorByTag(
8037
+ ancestor instanceof HTMLElement ? ancestor : ancestor.parentElement,
8038
+ tagName
8039
+ );
8040
+ let targetNode = null;
8041
+ if (existingWrap) {
8042
+ const parent = existingWrap.parentNode;
8043
+ if (parent) {
8044
+ const firstChild = existingWrap.firstChild;
8045
+ const lastChild = existingWrap.lastChild;
8046
+ while (existingWrap.firstChild) {
8047
+ parent.insertBefore(existingWrap.firstChild, existingWrap);
8048
+ }
8049
+ parent.removeChild(existingWrap);
8050
+ if (firstChild && lastChild) {
8051
+ const newRange = document.createRange();
8052
+ newRange.setStartBefore(firstChild);
8053
+ newRange.setEndAfter(lastChild);
8054
+ selection.removeAllRanges();
8055
+ selection.addRange(newRange);
8056
+ return;
8057
+ }
8058
+ }
8059
+ } else {
8060
+ const wrapper = document.createElement(tagName);
8061
+ try {
8062
+ range.surroundContents(wrapper);
8063
+ } catch {
8064
+ const fragment = range.extractContents();
8065
+ wrapper.appendChild(fragment);
8066
+ range.insertNode(wrapper);
8067
+ }
8068
+ targetNode = wrapper;
8069
+ }
8070
+ if (targetNode) {
8071
+ selection.removeAllRanges();
8072
+ const newRange = document.createRange();
8073
+ newRange.selectNodeContents(targetNode);
8074
+ selection.addRange(newRange);
7982
8075
  }
7983
8076
  }
8077
+ function findAncestorByTag(el, tagName) {
8078
+ const upper = tagName.toUpperCase();
8079
+ while (el) {
8080
+ if (el.tagName === upper) return el;
8081
+ el = el.parentElement;
8082
+ }
8083
+ return null;
8084
+ }
7984
8085
  function bold() {
7985
- execCommand("bold");
8086
+ wrapSelection("strong");
7986
8087
  }
7987
8088
  function italic() {
7988
- execCommand("italic");
8089
+ wrapSelection("em");
7989
8090
  }
7990
8091
  function underline() {
7991
- execCommand("underline");
8092
+ wrapSelection("u");
7992
8093
  }
7993
8094
  return {
7994
8095
  content,
7995
8096
  setContent,
7996
8097
  isFocused,
7997
8098
  setFocused,
7998
- execCommand,
7999
8099
  bold,
8000
8100
  italic,
8001
8101
  underline
@@ -8480,6 +8580,7 @@ var materialAdapter = componentAdapter(materialConfig);
8480
8580
  bindAttrs,
8481
8581
  bindBoolAttr,
8482
8582
  bindData,
8583
+ bindField,
8483
8584
  block,
8484
8585
  bounceIn,
8485
8586
  bounceOut,
@@ -8707,6 +8808,7 @@ var materialAdapter = componentAdapter(materialConfig);
8707
8808
  triggerPluginError,
8708
8809
  triggerPluginMount,
8709
8810
  triggerPluginUnmount,
8811
+ trustHTML,
8710
8812
  uniqueId,
8711
8813
  validateProps,
8712
8814
  validators,
package/dist/extras.d.cts CHANGED
@@ -3,9 +3,10 @@ export { battery, clipboard, colorScheme, draggable, dropZone, formatCurrency, f
3
3
  export { GlobalStore, MachineConfig, MachineReturn, Middleware, OptimisticAction, PersistOptions, Selector, TimeTravelReturn, createEffect, createMemo, createSignal, globalStore, machine, optimistic, optimisticList, persisted, timeline } from './patterns.cjs';
4
4
  export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as composable, d as compose, e as createGuard, f as createSlots, g as defineComponent, h as defineSlottedComponent, i as defineStrictComponent, v as validateProps, j as validators, w as withBoundary, k as withDefaults, l as withProps, m as withWrapper } from './contracts-DOrhwbke.cjs';
5
5
  export { AnimationPreset, PresetOptions, SlideDirection, SpringOptions, TransitionGroup, TransitionGroupOptions, TransitionOptions, animate, bounceIn, bounceOut, fadeIn, fadeOut, flipIn, pulse, reducedMotion, scaleDown, scaleUp, sequence, shake, slideIn, slideOut, spring, springSignal, stagger, transition, viewTransition } from './motion.cjs';
6
- export { C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, V as ValidatorFn, e as VirtualList, f as VirtualListProps, g as announce, h as aria, i as bindAttrs, j as bindBoolAttr, k as bindData, l as creditCardMask, m as custom, n as dateMask, o as defineElement, p as dialog, q as email, r as eventBus, s as focus, t as form, u as hotkey, v as infiniteScroll, w as inputMask, x as intersection, y as lazyLoad, z as matchesPattern, A as max, B as maxLength, D as min, E as minLength, G as pagination, H as phoneMask, J as removeScopedStyle, K as required, L as scopedStyle, N as ssnMask, O as svgElement, P as timeMask, Q as toast, R as withScopedStyle, S as zipMask } from './customElement-BKQfbSZQ.cjs';
6
+ export { B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, e as ToastInstance, V as ValidatorFn, f as VirtualList, g as VirtualListProps, h as announce, i as aria, j as bindAttrs, k as bindBoolAttr, l as bindData, m as bindField, n as creditCardMask, o as custom, p as dateMask, q as defineElement, r as dialog, s as email, t as eventBus, u as focus, v as form, w as hotkey, x as infiniteScroll, y as inputMask, z as intersection, A as lazyLoad, D as matchesPattern, E as max, G as maxLength, H as min, J as minLength, K as pagination, L as phoneMask, N as removeScopedStyle, O as required, P as scopedStyle, Q as ssnMask, R as svgElement, S as timeMask, U as toast, W as withScopedStyle, X as zipMask } from './customElement-yz8uyk-0.cjs';
7
7
  export { ChunkConfig, DOMPool, Features, NormalizeResult, NormalizedEntities, NormalizedSchema, NormalizedState, NormalizedStoreActions, Priority, PriorityLevel, block, cloneTemplate, conditional, createChunkRegistry, deferredValue, denormalize, devOnly, domPool, flushScheduler, hoistable, lazyChunk, noSideEffect, normalize, normalizedStore, pendingTasks, precompile, prefetch, preloadImage, preloadModule, preloadModules, preloadResource, processInChunks, pure, resetIdCounter, scheduleUpdate, setIdPrefix, startTransition, staticTemplate, transitionState, uniqueId, yieldToMain } from './performance.cjs';
8
- export { ActionFn, ActionResult, Head, ISROptions, MicroApp, MicroAppConfig, MiddlewareFn, SSGOptions, SSGResult, ScrollRestorationOptions, ServiceWorkerState, SharedScope, UseWorkerFnReturn, UseWorkerReturn, WasmConfig, WasmModuleState, WorkerPool, clearWasmCache, collectStream, composeMiddleware, createAction, createISR, createMicroApp, createMiddlewareChain, createSharedScope, createWasmBridge, createWorkerPool, defineRemoteComponent, deserializeState, generateStaticSite, hydrate, hydrateIslands, hydrateProgressively, isWasmCached, island, loadRemoteModule, loadWasmModule, preloadWasm, renderToDocument, renderToReadableStream, renderToStream, renderToString, renderToSuspenseStream, resetSSRState, scrollRestoration, serializeState, serviceWorker, setCanonical, setStructuredData, ssrSuspense, suspenseSwapScript, wasm, worker, workerFn } from './ssr.cjs';
8
+ export { ActionFn, ActionResult, Head, ISROptions, MicroApp, MicroAppConfig, MiddlewareFn, SSGOptions, SSGResult, ScrollRestorationOptions, ServiceWorkerState, SharedScope, UseWorkerFnReturn, UseWorkerReturn, WasmConfig, WasmModuleState, WorkerPool, clearWasmCache, composeMiddleware, createAction, createISR, createMicroApp, createMiddlewareChain, createSharedScope, createWasmBridge, createWorkerPool, defineRemoteComponent, generateStaticSite, isWasmCached, loadRemoteModule, loadWasmModule, preloadWasm, scrollRestoration, serviceWorker, setCanonical, setStructuredData, wasm, worker, workerFn } from './ssr.cjs';
9
+ export { T as TrustedHTML, c as collectStream, d as deserializeState, h as hydrate, a as hydrateIslands, b as hydrateProgressively, i as island, r as renderToDocument, e as renderToReadableStream, f as renderToStream, g as renderToString, j as renderToSuspenseStream, k as resetSSRState, s as serializeState, l as ssrSuspense, m as suspenseSwapScript, t as trustHTML } from './ssr-BA6sxxUd.cjs';
9
10
  export { P as PluginContext, S as SibuPlugin, c as createPlugin, i as inject, p as plugin, r as resetPlugins, t as triggerPluginError, a as triggerPluginMount, b as triggerPluginUnmount } from './plugin-Bek4RhJY.cjs';
10
11
  export { M as Migration, S as SemVer, V as VERSION, b as bundlerMetadata, c as checkCompatibility, a as compareSemVer, d as createBootSequence, e as createBundle, f as createMigrationRunner, g as createModuleRegistry, h as createSSRCache, i as createTestHarness, j as deferNonCritical, k as env, l as healthCheck, m as lazyModule, p as packageInfo, n as parseSemVer, o as preloadCritical, q as prerenderRoutes, s as satisfies } from './startup-0Qv6aosO.cjs';
11
12
  export { DevToolsEvent, DevtoolsOverlayOptions, ProfilerResult, ReactiveNodeInfo, SibuError, checkLeaks, clearDebugValues, clearHMRState, clearPerformanceData, createDevtoolsOverlay, createErrorReporter, createHMRBoundary, createProfiler, debugLog, debugValue, devState, disableDebug, enableDebug, formatError, getActiveDevTools, getDebugValues, getDependencies, getPerformanceReport, getSignalName, getSubscriberCount, hmrState, initDevTools, inspectSignal, isDebugEnabled, isHMRAvailable, measureRender, perfTracker, registerHMR, runCleanups, startMeasure, trackCleanup, walkDependencyGraph, withErrorTracking } from './devtools.cjs';
package/dist/extras.d.ts CHANGED
@@ -3,9 +3,10 @@ export { battery, clipboard, colorScheme, draggable, dropZone, formatCurrency, f
3
3
  export { GlobalStore, MachineConfig, MachineReturn, Middleware, OptimisticAction, PersistOptions, Selector, TimeTravelReturn, createEffect, createMemo, createSignal, globalStore, machine, optimistic, optimisticList, persisted, timeline } from './patterns.js';
4
4
  export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as composable, d as compose, e as createGuard, f as createSlots, g as defineComponent, h as defineSlottedComponent, i as defineStrictComponent, v as validateProps, j as validators, w as withBoundary, k as withDefaults, l as withProps, m as withWrapper } from './contracts-DOrhwbke.js';
5
5
  export { AnimationPreset, PresetOptions, SlideDirection, SpringOptions, TransitionGroup, TransitionGroupOptions, TransitionOptions, animate, bounceIn, bounceOut, fadeIn, fadeOut, flipIn, pulse, reducedMotion, scaleDown, scaleUp, sequence, shake, slideIn, slideOut, spring, springSignal, stagger, transition, viewTransition } from './motion.js';
6
- export { C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, V as ValidatorFn, e as VirtualList, f as VirtualListProps, g as announce, h as aria, i as bindAttrs, j as bindBoolAttr, k as bindData, l as creditCardMask, m as custom, n as dateMask, o as defineElement, p as dialog, q as email, r as eventBus, s as focus, t as form, u as hotkey, v as infiniteScroll, w as inputMask, x as intersection, y as lazyLoad, z as matchesPattern, A as max, B as maxLength, D as min, E as minLength, G as pagination, H as phoneMask, J as removeScopedStyle, K as required, L as scopedStyle, N as ssnMask, O as svgElement, P as timeMask, Q as toast, R as withScopedStyle, S as zipMask } from './customElement-BKQfbSZQ.js';
6
+ export { B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, e as ToastInstance, V as ValidatorFn, f as VirtualList, g as VirtualListProps, h as announce, i as aria, j as bindAttrs, k as bindBoolAttr, l as bindData, m as bindField, n as creditCardMask, o as custom, p as dateMask, q as defineElement, r as dialog, s as email, t as eventBus, u as focus, v as form, w as hotkey, x as infiniteScroll, y as inputMask, z as intersection, A as lazyLoad, D as matchesPattern, E as max, G as maxLength, H as min, J as minLength, K as pagination, L as phoneMask, N as removeScopedStyle, O as required, P as scopedStyle, Q as ssnMask, R as svgElement, S as timeMask, U as toast, W as withScopedStyle, X as zipMask } from './customElement-yz8uyk-0.js';
7
7
  export { ChunkConfig, DOMPool, Features, NormalizeResult, NormalizedEntities, NormalizedSchema, NormalizedState, NormalizedStoreActions, Priority, PriorityLevel, block, cloneTemplate, conditional, createChunkRegistry, deferredValue, denormalize, devOnly, domPool, flushScheduler, hoistable, lazyChunk, noSideEffect, normalize, normalizedStore, pendingTasks, precompile, prefetch, preloadImage, preloadModule, preloadModules, preloadResource, processInChunks, pure, resetIdCounter, scheduleUpdate, setIdPrefix, startTransition, staticTemplate, transitionState, uniqueId, yieldToMain } from './performance.js';
8
- export { ActionFn, ActionResult, Head, ISROptions, MicroApp, MicroAppConfig, MiddlewareFn, SSGOptions, SSGResult, ScrollRestorationOptions, ServiceWorkerState, SharedScope, UseWorkerFnReturn, UseWorkerReturn, WasmConfig, WasmModuleState, WorkerPool, clearWasmCache, collectStream, composeMiddleware, createAction, createISR, createMicroApp, createMiddlewareChain, createSharedScope, createWasmBridge, createWorkerPool, defineRemoteComponent, deserializeState, generateStaticSite, hydrate, hydrateIslands, hydrateProgressively, isWasmCached, island, loadRemoteModule, loadWasmModule, preloadWasm, renderToDocument, renderToReadableStream, renderToStream, renderToString, renderToSuspenseStream, resetSSRState, scrollRestoration, serializeState, serviceWorker, setCanonical, setStructuredData, ssrSuspense, suspenseSwapScript, wasm, worker, workerFn } from './ssr.js';
8
+ export { ActionFn, ActionResult, Head, ISROptions, MicroApp, MicroAppConfig, MiddlewareFn, SSGOptions, SSGResult, ScrollRestorationOptions, ServiceWorkerState, SharedScope, UseWorkerFnReturn, UseWorkerReturn, WasmConfig, WasmModuleState, WorkerPool, clearWasmCache, composeMiddleware, createAction, createISR, createMicroApp, createMiddlewareChain, createSharedScope, createWasmBridge, createWorkerPool, defineRemoteComponent, generateStaticSite, isWasmCached, loadRemoteModule, loadWasmModule, preloadWasm, scrollRestoration, serviceWorker, setCanonical, setStructuredData, wasm, worker, workerFn } from './ssr.js';
9
+ export { T as TrustedHTML, c as collectStream, d as deserializeState, h as hydrate, a as hydrateIslands, b as hydrateProgressively, i as island, r as renderToDocument, e as renderToReadableStream, f as renderToStream, g as renderToString, j as renderToSuspenseStream, k as resetSSRState, s as serializeState, l as ssrSuspense, m as suspenseSwapScript, t as trustHTML } from './ssr-BA6sxxUd.js';
9
10
  export { P as PluginContext, S as SibuPlugin, c as createPlugin, i as inject, p as plugin, r as resetPlugins, t as triggerPluginError, a as triggerPluginMount, b as triggerPluginUnmount } from './plugin-Bek4RhJY.js';
10
11
  export { M as Migration, S as SemVer, V as VERSION, b as bundlerMetadata, c as checkCompatibility, a as compareSemVer, d as createBootSequence, e as createBundle, f as createMigrationRunner, g as createModuleRegistry, h as createSSRCache, i as createTestHarness, j as deferNonCritical, k as env, l as healthCheck, m as lazyModule, p as packageInfo, n as parseSemVer, o as preloadCritical, q as prerenderRoutes, s as satisfies } from './startup-0Qv6aosO.js';
11
12
  export { DevToolsEvent, DevtoolsOverlayOptions, ProfilerResult, ReactiveNodeInfo, SibuError, checkLeaks, clearDebugValues, clearHMRState, clearPerformanceData, createDevtoolsOverlay, createErrorReporter, createHMRBoundary, createProfiler, debugLog, debugValue, devState, disableDebug, enableDebug, formatError, getActiveDevTools, getDebugValues, getDependencies, getPerformanceReport, getSignalName, getSubscriberCount, hmrState, initDevTools, inspectSignal, isDebugEnabled, isHMRAvailable, measureRender, perfTracker, registerHMR, runCleanups, startMeasure, trackCleanup, walkDependencyGraph, withErrorTracking } from './devtools.js';
package/dist/extras.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  preloadCritical,
66
66
  prerenderRoutes,
67
67
  satisfies
68
- } from "./chunk-DTCOOBMX.js";
68
+ } from "./chunk-OF7UZIVB.js";
69
69
  import {
70
70
  Head,
71
71
  clearWasmCache,
@@ -99,6 +99,7 @@ import {
99
99
  bindAttrs,
100
100
  bindBoolAttr,
101
101
  bindData,
102
+ bindField,
102
103
  creditCardMask,
103
104
  custom,
104
105
  dateMask,
@@ -129,7 +130,7 @@ import {
129
130
  toast,
130
131
  withScopedStyle,
131
132
  zipMask
132
- } from "./chunk-3CRQALYP.js";
133
+ } from "./chunk-DKOHBI74.js";
133
134
  import {
134
135
  RenderProp,
135
136
  assertType,
@@ -157,7 +158,7 @@ import {
157
158
  select,
158
159
  tabs,
159
160
  tooltip
160
- } from "./chunk-N6IZB6KJ.js";
161
+ } from "./chunk-PBHF5WKN.js";
161
162
  import {
162
163
  collectStream,
163
164
  deserializeState,
@@ -173,8 +174,9 @@ import {
173
174
  resetSSRState,
174
175
  serializeState,
175
176
  ssrSuspense,
176
- suspenseSwapScript
177
- } from "./chunk-7TQKR4PP.js";
177
+ suspenseSwapScript,
178
+ trustHTML
179
+ } from "./chunk-AZ3ISID5.js";
178
180
  import {
179
181
  battery,
180
182
  clipboard,
@@ -323,6 +325,7 @@ export {
323
325
  bindAttrs,
324
326
  bindBoolAttr,
325
327
  bindData,
328
+ bindField,
326
329
  block,
327
330
  bounceIn,
328
331
  bounceOut,
@@ -550,6 +553,7 @@ export {
550
553
  triggerPluginError,
551
554
  triggerPluginMount,
552
555
  triggerPluginUnmount,
556
+ trustHTML,
553
557
  uniqueId,
554
558
  validateProps,
555
559
  validators,
package/dist/index.cjs CHANGED
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  article: () => article,
38
38
  aside: () => aside,
39
39
  audio: () => audio,
40
+ autoResize: () => autoResize,
40
41
  b: () => b,
41
42
  base: () => base,
42
43
  batch: () => batch,
@@ -61,6 +62,7 @@ __export(index_exports, {
61
62
  col: () => col,
62
63
  colgroup: () => colgroup,
63
64
  context: () => context,
65
+ copyOnClick: () => copyOnClick,
64
66
  customElement: () => customElement,
65
67
  data: () => data,
66
68
  datalist: () => datalist,
@@ -1811,6 +1813,24 @@ var longPress = (element, options) => {
1811
1813
  element.removeEventListener("pointerleave", cancel);
1812
1814
  };
1813
1815
  };
1816
+ var copyOnClick = (element, getText) => {
1817
+ const handler = () => {
1818
+ const text2 = typeof getText === "function" ? getText() : element.textContent ?? "";
1819
+ navigator.clipboard.writeText(text2);
1820
+ };
1821
+ element.addEventListener("click", handler);
1822
+ return () => element.removeEventListener("click", handler);
1823
+ };
1824
+ var autoResize = (element) => {
1825
+ const resize = () => {
1826
+ element.style.overflow = "hidden";
1827
+ element.style.height = "auto";
1828
+ element.style.height = `${element.scrollHeight}px`;
1829
+ };
1830
+ resize();
1831
+ element.addEventListener("input", resize);
1832
+ return () => element.removeEventListener("input", resize);
1833
+ };
1814
1834
  var trapFocus = (element) => {
1815
1835
  const focusable = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
1816
1836
  const handler = (e) => {
@@ -2831,6 +2851,7 @@ function Loading(props = {}) {
2831
2851
  article,
2832
2852
  aside,
2833
2853
  audio,
2854
+ autoResize,
2834
2855
  b,
2835
2856
  base,
2836
2857
  batch,
@@ -2855,6 +2876,7 @@ function Loading(props = {}) {
2855
2876
  col,
2856
2877
  colgroup,
2857
2878
  context,
2879
+ copyOnClick,
2858
2880
  customElement,
2859
2881
  data,
2860
2882
  datalist,
package/dist/index.d.cts CHANGED
@@ -289,7 +289,7 @@ declare function getSlot(slots: Slots | undefined, name?: string): SlotFn | unde
289
289
  * div({ nodes: [show(() => visible(), span({ nodes: "I toggle!" }))] });
290
290
  * ```
291
291
  */
292
- declare function show(condition: () => boolean, element: HTMLElement): HTMLElement;
292
+ declare function show<T extends Element>(condition: () => boolean, element: T): T;
293
293
  /**
294
294
  * Conditional rendering directive. Renders content only when condition is true.
295
295
  * When false, renders nothing (comment placeholder). Re-evaluates reactively.
@@ -429,6 +429,31 @@ interface LongPressOptions {
429
429
  * ```
430
430
  */
431
431
  declare const longPress: ActionFn<LongPressOptions>;
432
+ /**
433
+ * Copies the element's textContent to the clipboard on click.
434
+ * Optionally accepts a custom getter for the text to copy.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * // Copy element text
439
+ * action(el, copyOnClick);
440
+ *
441
+ * // Copy custom value
442
+ * action(el, copyOnClick, () => secretToken());
443
+ * ```
444
+ */
445
+ declare const copyOnClick: ActionFn<(() => string) | undefined>;
446
+ /**
447
+ * Auto-resizes a textarea to fit its content.
448
+ * Adjusts height on input and on initial attach.
449
+ *
450
+ * @example
451
+ * ```ts
452
+ * const ta = textarea({ placeholder: "Type here..." });
453
+ * action(ta, autoResize);
454
+ * ```
455
+ */
456
+ declare const autoResize: ActionFn<void>;
432
457
  /**
433
458
  * Traps keyboard focus within the element (Tab and Shift+Tab cycle).
434
459
  * Essential for accessible modals and dialogs.
@@ -1057,4 +1082,4 @@ interface LoadingProps {
1057
1082
  */
1058
1083
  declare function Loading(props?: LoadingProps): HTMLElement;
1059
1084
 
1060
- export { type ActionFn, type ArrayActions, type Context, DynamicComponent, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, Fragment, KeepAlive, type KeepAliveOptions, Loading, type LoadingProps, type LongPressOptions, NodeChild, NodeChildren, Portal, type Ref, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, a, abbr, action, address, area, array, article, aside, audio, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, customElement, data, datalist, dd, deepEqual, deepSignal, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, memo, memoFn, menu, meta, meter, mount, nav, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strong, style, sub, summary, sup, svg, symbol, table, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
1085
+ export { type ActionFn, type ArrayActions, type Context, DynamicComponent, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, Fragment, KeepAlive, type KeepAliveOptions, Loading, type LoadingProps, type LongPressOptions, NodeChild, NodeChildren, Portal, type Ref, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, a, abbr, action, address, area, array, article, aside, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, customElement, data, datalist, dd, deepEqual, deepSignal, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, memo, memoFn, menu, meta, meter, mount, nav, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strong, style, sub, summary, sup, svg, symbol, table, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
package/dist/index.d.ts CHANGED
@@ -289,7 +289,7 @@ declare function getSlot(slots: Slots | undefined, name?: string): SlotFn | unde
289
289
  * div({ nodes: [show(() => visible(), span({ nodes: "I toggle!" }))] });
290
290
  * ```
291
291
  */
292
- declare function show(condition: () => boolean, element: HTMLElement): HTMLElement;
292
+ declare function show<T extends Element>(condition: () => boolean, element: T): T;
293
293
  /**
294
294
  * Conditional rendering directive. Renders content only when condition is true.
295
295
  * When false, renders nothing (comment placeholder). Re-evaluates reactively.
@@ -429,6 +429,31 @@ interface LongPressOptions {
429
429
  * ```
430
430
  */
431
431
  declare const longPress: ActionFn<LongPressOptions>;
432
+ /**
433
+ * Copies the element's textContent to the clipboard on click.
434
+ * Optionally accepts a custom getter for the text to copy.
435
+ *
436
+ * @example
437
+ * ```ts
438
+ * // Copy element text
439
+ * action(el, copyOnClick);
440
+ *
441
+ * // Copy custom value
442
+ * action(el, copyOnClick, () => secretToken());
443
+ * ```
444
+ */
445
+ declare const copyOnClick: ActionFn<(() => string) | undefined>;
446
+ /**
447
+ * Auto-resizes a textarea to fit its content.
448
+ * Adjusts height on input and on initial attach.
449
+ *
450
+ * @example
451
+ * ```ts
452
+ * const ta = textarea({ placeholder: "Type here..." });
453
+ * action(ta, autoResize);
454
+ * ```
455
+ */
456
+ declare const autoResize: ActionFn<void>;
432
457
  /**
433
458
  * Traps keyboard focus within the element (Tab and Shift+Tab cycle).
434
459
  * Essential for accessible modals and dialogs.
@@ -1057,4 +1082,4 @@ interface LoadingProps {
1057
1082
  */
1058
1083
  declare function Loading(props?: LoadingProps): HTMLElement;
1059
1084
 
1060
- export { type ActionFn, type ArrayActions, type Context, DynamicComponent, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, Fragment, KeepAlive, type KeepAliveOptions, Loading, type LoadingProps, type LongPressOptions, NodeChild, NodeChildren, Portal, type Ref, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, a, abbr, action, address, area, array, article, aside, audio, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, customElement, data, datalist, dd, deepEqual, deepSignal, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, memo, memoFn, menu, meta, meter, mount, nav, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strong, style, sub, summary, sup, svg, symbol, table, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
1085
+ export { type ActionFn, type ArrayActions, type Context, DynamicComponent, type EffectOptions, ErrorBoundary, type ErrorBoundaryProps, Fragment, KeepAlive, type KeepAliveOptions, Loading, type LoadingProps, type LongPressOptions, NodeChild, NodeChildren, Portal, type Ref, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, a, abbr, action, address, area, array, article, aside, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, customElement, data, datalist, dd, deepEqual, deepSignal, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, memo, memoFn, menu, meta, meter, mount, nav, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerComponent, registerDisposer, resolveComponent, rp, rt, ruby, s, samp, script, section, select, setGlobalErrorHandler, show, signal, slot, small, source, span, stop, store, strong, style, sub, summary, sup, svg, symbol, table, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track, trapFocus, tspan, u, ul, unregisterComponent, untracked, use, var_, video, watch, when, withSSR, writable };
package/dist/index.js CHANGED
@@ -8,9 +8,11 @@ import {
8
8
  Suspense,
9
9
  action,
10
10
  array,
11
+ autoResize,
11
12
  catchError,
12
13
  catchErrorAsync,
13
14
  clickOutside,
15
+ copyOnClick,
14
16
  deepEqual,
15
17
  deepSignal,
16
18
  each,
@@ -36,7 +38,7 @@ import {
36
38
  unregisterComponent,
37
39
  when,
38
40
  writable
39
- } from "./chunk-MEZVEBPN.js";
41
+ } from "./chunk-32ZISOLJ.js";
40
42
  import {
41
43
  a,
42
44
  abbr,
@@ -231,6 +233,7 @@ export {
231
233
  article,
232
234
  aside,
233
235
  audio,
236
+ autoResize,
234
237
  b,
235
238
  base,
236
239
  batch,
@@ -255,6 +258,7 @@ export {
255
258
  col,
256
259
  colgroup,
257
260
  context,
261
+ copyOnClick,
258
262
  customElement,
259
263
  data,
260
264
  datalist,
@@ -58,11 +58,17 @@ interface PersistOptions<T = unknown> {
58
58
  * Encrypt the serialized value before writing to storage.
59
59
  * Paired with `decrypt` for reading. Use for sensitive data.
60
60
  *
61
+ * **Security:** Use a real encryption algorithm (e.g. AES-GCM via Web Crypto API).
62
+ * Do NOT use `btoa()`/`atob()` — Base64 is encoding, not encryption, and provides
63
+ * zero confidentiality.
64
+ *
61
65
  * @example
62
66
  * ```ts
67
+ * // Example using a simple XOR cipher for illustration — in production,
68
+ * // use crypto.subtle.encrypt() with AES-GCM or a proven library.
63
69
  * persisted("token", "", {
64
- * encrypt: (v) => btoa(v), // or use Web Crypto API
65
- * decrypt: (v) => atob(v),
70
+ * encrypt: (v) => myAesGcmEncrypt(v, secretKey),
71
+ * decrypt: (v) => myAesGcmDecrypt(v, secretKey),
66
72
  * });
67
73
  * ```
68
74
  */
@@ -58,11 +58,17 @@ interface PersistOptions<T = unknown> {
58
58
  * Encrypt the serialized value before writing to storage.
59
59
  * Paired with `decrypt` for reading. Use for sensitive data.
60
60
  *
61
+ * **Security:** Use a real encryption algorithm (e.g. AES-GCM via Web Crypto API).
62
+ * Do NOT use `btoa()`/`atob()` — Base64 is encoding, not encryption, and provides
63
+ * zero confidentiality.
64
+ *
61
65
  * @example
62
66
  * ```ts
67
+ * // Example using a simple XOR cipher for illustration — in production,
68
+ * // use crypto.subtle.encrypt() with AES-GCM or a proven library.
63
69
  * persisted("token", "", {
64
- * encrypt: (v) => btoa(v), // or use Web Crypto API
65
- * decrypt: (v) => atob(v),
70
+ * encrypt: (v) => myAesGcmEncrypt(v, secretKey),
71
+ * decrypt: (v) => myAesGcmDecrypt(v, secretKey),
66
72
  * });
67
73
  * ```
68
74
  */