@bquery/bquery 1.6.0 → 1.7.0
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.
- package/README.md +716 -586
- package/dist/a11y/announce.d.ts +43 -0
- package/dist/a11y/announce.d.ts.map +1 -0
- package/dist/a11y/audit.d.ts +42 -0
- package/dist/a11y/audit.d.ts.map +1 -0
- package/dist/a11y/index.d.ts +53 -0
- package/dist/a11y/index.d.ts.map +1 -0
- package/dist/a11y/media-preferences.d.ts +77 -0
- package/dist/a11y/media-preferences.d.ts.map +1 -0
- package/dist/a11y/roving-tab-index.d.ts +38 -0
- package/dist/a11y/roving-tab-index.d.ts.map +1 -0
- package/dist/a11y/skip-link.d.ts +37 -0
- package/dist/a11y/skip-link.d.ts.map +1 -0
- package/dist/a11y/trap-focus.d.ts +49 -0
- package/dist/a11y/trap-focus.d.ts.map +1 -0
- package/dist/a11y/types.d.ts +152 -0
- package/dist/a11y/types.d.ts.map +1 -0
- package/dist/a11y-C5QOVvRn.js +421 -0
- package/dist/a11y-C5QOVvRn.js.map +1 -0
- package/dist/a11y.es.mjs +14 -0
- package/dist/component/component.d.ts.map +1 -1
- package/dist/component/html.d.ts.map +1 -1
- package/dist/component/index.d.ts +2 -1
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/library.d.ts.map +1 -1
- package/dist/component/scope.d.ts +138 -0
- package/dist/component/scope.d.ts.map +1 -0
- package/dist/component/types.d.ts +53 -1
- package/dist/component/types.d.ts.map +1 -1
- package/dist/component-CuuTijA6.js +684 -0
- package/dist/component-CuuTijA6.js.map +1 -0
- package/dist/component.es.mjs +9 -6
- package/dist/{config-DRmZZno3.js → config-BW35FKuA.js} +4 -4
- package/dist/{config-DRmZZno3.js.map → config-BW35FKuA.js.map} +1 -1
- package/dist/constraints-3lV9yyBw.js +100 -0
- package/dist/constraints-3lV9yyBw.js.map +1 -0
- package/dist/core/collection.d.ts +48 -0
- package/dist/core/collection.d.ts.map +1 -1
- package/dist/core/element.d.ts +92 -0
- package/dist/core/element.d.ts.map +1 -1
- package/dist/core/env.d.ts +18 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/shared.d.ts +8 -0
- package/dist/core/shared.d.ts.map +1 -1
- package/dist/core/utils/index.d.ts +52 -41
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core-Cjl7GUu8.js +717 -0
- package/dist/core-Cjl7GUu8.js.map +1 -0
- package/dist/core-DnlyjbF2.js +112 -0
- package/dist/core-DnlyjbF2.js.map +1 -0
- package/dist/core.es.mjs +45 -44
- package/dist/custom-directives-7wAShnnd.js +9 -0
- package/dist/custom-directives-7wAShnnd.js.map +1 -0
- package/dist/devtools/devtools.d.ts +212 -0
- package/dist/devtools/devtools.d.ts.map +1 -0
- package/dist/devtools/index.d.ts +20 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/types.d.ts +69 -0
- package/dist/devtools/types.d.ts.map +1 -0
- package/dist/devtools-D2fQLhDN.js +122 -0
- package/dist/devtools-D2fQLhDN.js.map +1 -0
- package/dist/devtools.es.mjs +19 -0
- package/dist/dnd/draggable.d.ts +51 -0
- package/dist/dnd/draggable.d.ts.map +1 -0
- package/dist/dnd/droppable.d.ts +38 -0
- package/dist/dnd/droppable.d.ts.map +1 -0
- package/dist/dnd/index.d.ts +47 -0
- package/dist/dnd/index.d.ts.map +1 -0
- package/dist/dnd/sortable.d.ts +43 -0
- package/dist/dnd/sortable.d.ts.map +1 -0
- package/dist/dnd/types.d.ts +250 -0
- package/dist/dnd/types.d.ts.map +1 -0
- package/dist/dnd-B8EgyzaI.js +244 -0
- package/dist/dnd-B8EgyzaI.js.map +1 -0
- package/dist/dnd.es.mjs +6 -0
- package/dist/env-NeVmr4Gf.js +19 -0
- package/dist/env-NeVmr4Gf.js.map +1 -0
- package/dist/forms/create-form.d.ts +49 -0
- package/dist/forms/create-form.d.ts.map +1 -0
- package/dist/forms/index.d.ts +39 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/types.d.ts +139 -0
- package/dist/forms/types.d.ts.map +1 -0
- package/dist/forms/validators.d.ts +179 -0
- package/dist/forms/validators.d.ts.map +1 -0
- package/dist/forms-C3yovgH9.js +141 -0
- package/dist/forms-C3yovgH9.js.map +1 -0
- package/dist/forms.es.mjs +14 -0
- package/dist/full.d.ts +35 -7
- package/dist/full.d.ts.map +1 -1
- package/dist/full.es.mjs +182 -91
- package/dist/full.iife.js +47 -31
- package/dist/full.iife.js.map +1 -1
- package/dist/full.umd.js +47 -31
- package/dist/full.umd.js.map +1 -1
- package/dist/i18n/formatting.d.ts +40 -0
- package/dist/i18n/formatting.d.ts.map +1 -0
- package/dist/i18n/i18n.d.ts +48 -0
- package/dist/i18n/i18n.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +57 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/translate.d.ts +83 -0
- package/dist/i18n/translate.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +156 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n-BnnhTFOS.js +89 -0
- package/dist/i18n-BnnhTFOS.js.map +1 -0
- package/dist/i18n.es.mjs +6 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.mjs +227 -136
- package/dist/media/battery.d.ts +35 -0
- package/dist/media/battery.d.ts.map +1 -0
- package/dist/media/breakpoints.d.ts +51 -0
- package/dist/media/breakpoints.d.ts.map +1 -0
- package/dist/media/clipboard.d.ts +30 -0
- package/dist/media/clipboard.d.ts.map +1 -0
- package/dist/media/device-sensors.d.ts +54 -0
- package/dist/media/device-sensors.d.ts.map +1 -0
- package/dist/media/geolocation.d.ts +38 -0
- package/dist/media/geolocation.d.ts.map +1 -0
- package/dist/media/index.d.ts +42 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/media-query.d.ts +36 -0
- package/dist/media/media-query.d.ts.map +1 -0
- package/dist/media/network.d.ts +35 -0
- package/dist/media/network.d.ts.map +1 -0
- package/dist/media/types.d.ts +173 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/viewport.d.ts +32 -0
- package/dist/media/viewport.d.ts.map +1 -0
- package/dist/media-Di2Ta22s.js +340 -0
- package/dist/media-Di2Ta22s.js.map +1 -0
- package/dist/media.es.mjs +12 -0
- package/dist/motion/index.d.ts +7 -3
- package/dist/motion/index.d.ts.map +1 -1
- package/dist/motion/morph.d.ts +27 -0
- package/dist/motion/morph.d.ts.map +1 -0
- package/dist/motion/parallax.d.ts +30 -0
- package/dist/motion/parallax.d.ts.map +1 -0
- package/dist/motion/reduced-motion.d.ts +36 -3
- package/dist/motion/reduced-motion.d.ts.map +1 -1
- package/dist/motion/types.d.ts +58 -0
- package/dist/motion/types.d.ts.map +1 -1
- package/dist/motion/typewriter.d.ts +31 -0
- package/dist/motion/typewriter.d.ts.map +1 -0
- package/dist/motion-qPj_TYGv.js +530 -0
- package/dist/motion-qPj_TYGv.js.map +1 -0
- package/dist/motion.es.mjs +27 -23
- package/dist/{view-C70lA3vf.js → mount-SM07RUa6.js} +166 -160
- package/dist/mount-SM07RUa6.js.map +1 -0
- package/dist/{object-qGpWr6-J.js → object-BCk-1c8T.js} +5 -4
- package/dist/{object-qGpWr6-J.js.map → object-BCk-1c8T.js.map} +1 -1
- package/dist/{platform-Dr9b6fsq.js → platform-CPbCprb6.js} +21 -22
- package/dist/{platform-Dr9b6fsq.js.map → platform-CPbCprb6.js.map} +1 -1
- package/dist/platform.es.mjs +2 -2
- package/dist/plugin/index.d.ts +22 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/registry.d.ts +108 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/types.d.ts +110 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin-cPoOHFLY.js +64 -0
- package/dist/plugin-cPoOHFLY.js.map +1 -0
- package/dist/plugin.es.mjs +9 -0
- package/dist/reactive/computed.d.ts +7 -0
- package/dist/reactive/computed.d.ts.map +1 -1
- package/dist/reactive-Cfv0RK6x.js +233 -0
- package/dist/reactive-Cfv0RK6x.js.map +1 -0
- package/dist/reactive.es.mjs +19 -20
- package/dist/registry-CWf368tT.js +26 -0
- package/dist/registry-CWf368tT.js.map +1 -0
- package/dist/router/bq-link.d.ts +112 -0
- package/dist/router/bq-link.d.ts.map +1 -0
- package/dist/router/constraints.d.ts +9 -0
- package/dist/router/constraints.d.ts.map +1 -0
- package/dist/router/index.d.ts +14 -6
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/match.d.ts +0 -1
- package/dist/router/match.d.ts.map +1 -1
- package/dist/router/path-pattern.d.ts +14 -0
- package/dist/router/path-pattern.d.ts.map +1 -0
- package/dist/router/query.d.ts.map +1 -1
- package/dist/router/router.d.ts +3 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/types.d.ts +48 -4
- package/dist/router/types.d.ts.map +1 -1
- package/dist/router/use-route.d.ts +50 -0
- package/dist/router/use-route.d.ts.map +1 -0
- package/dist/router/utils.d.ts +3 -0
- package/dist/router/utils.d.ts.map +1 -1
- package/dist/router-BrthaP_z.js +473 -0
- package/dist/router-BrthaP_z.js.map +1 -0
- package/dist/router.es.mjs +13 -10
- package/dist/{sanitize-Bs2dkMby.js → sanitize-B1V4JswB.js} +2 -1
- package/dist/{sanitize-Bs2dkMby.js.map → sanitize-B1V4JswB.js.map} +1 -1
- package/dist/security/index.d.ts +2 -2
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security.es.mjs +1 -1
- package/dist/ssr/hydrate.d.ts +65 -0
- package/dist/ssr/hydrate.d.ts.map +1 -0
- package/dist/ssr/index.d.ts +59 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/render.d.ts +62 -0
- package/dist/ssr/render.d.ts.map +1 -0
- package/dist/ssr/serialize.d.ts +118 -0
- package/dist/ssr/serialize.d.ts.map +1 -0
- package/dist/ssr/types.d.ts +70 -0
- package/dist/ssr/types.d.ts.map +1 -0
- package/dist/ssr-B2qd_WBB.js +248 -0
- package/dist/ssr-B2qd_WBB.js.map +1 -0
- package/dist/ssr.es.mjs +9 -0
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/persisted.d.ts +38 -4
- package/dist/store/persisted.d.ts.map +1 -1
- package/dist/store/types.d.ts +138 -1
- package/dist/store/types.d.ts.map +1 -1
- package/dist/store/utils.d.ts +2 -2
- package/dist/store/utils.d.ts.map +1 -1
- package/dist/store-DWpyH6p5.js +338 -0
- package/dist/store-DWpyH6p5.js.map +1 -0
- package/dist/store.es.mjs +11 -10
- package/dist/storybook/index.d.ts.map +1 -1
- package/dist/storybook.es.mjs +1 -1
- package/dist/storybook.es.mjs.map +1 -1
- package/dist/testing/index.d.ts +23 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/testing.d.ts +156 -0
- package/dist/testing/testing.d.ts.map +1 -0
- package/dist/testing/types.d.ts +134 -0
- package/dist/testing/types.d.ts.map +1 -0
- package/dist/testing-CsqjNUyy.js +224 -0
- package/dist/testing-CsqjNUyy.js.map +1 -0
- package/dist/testing.es.mjs +9 -0
- package/dist/type-guards-Do9DWgNp.js +44 -0
- package/dist/type-guards-Do9DWgNp.js.map +1 -0
- package/dist/untrack-DJVQQ2WM.js +33 -0
- package/dist/untrack-DJVQQ2WM.js.map +1 -0
- package/dist/view/custom-directives.d.ts +20 -0
- package/dist/view/custom-directives.d.ts.map +1 -0
- package/dist/view/evaluate.d.ts.map +1 -1
- package/dist/view/process.d.ts.map +1 -1
- package/dist/view.es.mjs +9 -9
- package/package.json +177 -141
- package/src/a11y/announce.ts +131 -0
- package/src/a11y/audit.ts +314 -0
- package/src/a11y/index.ts +68 -0
- package/src/a11y/media-preferences.ts +255 -0
- package/src/a11y/roving-tab-index.ts +164 -0
- package/src/a11y/skip-link.ts +255 -0
- package/src/a11y/trap-focus.ts +184 -0
- package/src/a11y/types.ts +183 -0
- package/src/component/component.ts +104 -29
- package/src/component/html.ts +5 -5
- package/src/component/index.ts +2 -0
- package/src/component/library.ts +26 -2
- package/src/component/scope.ts +212 -0
- package/src/component/types.ts +94 -40
- package/src/core/collection.ts +707 -628
- package/src/core/element.ts +981 -774
- package/src/core/env.ts +60 -0
- package/src/core/index.ts +49 -48
- package/src/core/shared.ts +62 -13
- package/src/core/utils/index.ts +148 -83
- package/src/devtools/devtools.ts +410 -0
- package/src/devtools/index.ts +48 -0
- package/src/devtools/types.ts +104 -0
- package/src/dnd/draggable.ts +296 -0
- package/src/dnd/droppable.ts +228 -0
- package/src/dnd/index.ts +62 -0
- package/src/dnd/sortable.ts +307 -0
- package/src/dnd/types.ts +293 -0
- package/src/forms/create-form.ts +278 -0
- package/src/forms/index.ts +65 -0
- package/src/forms/types.ts +154 -0
- package/src/forms/validators.ts +265 -0
- package/src/full.ts +253 -2
- package/src/i18n/formatting.ts +67 -0
- package/src/i18n/i18n.ts +200 -0
- package/src/i18n/index.ts +67 -0
- package/src/i18n/translate.ts +182 -0
- package/src/i18n/types.ts +171 -0
- package/src/index.ts +108 -36
- package/src/media/battery.ts +116 -0
- package/src/media/breakpoints.ts +131 -0
- package/src/media/clipboard.ts +80 -0
- package/src/media/device-sensors.ts +158 -0
- package/src/media/geolocation.ts +119 -0
- package/src/media/index.ts +76 -0
- package/src/media/media-query.ts +92 -0
- package/src/media/network.ts +115 -0
- package/src/media/types.ts +177 -0
- package/src/media/viewport.ts +84 -0
- package/src/motion/index.ts +57 -48
- package/src/motion/morph.ts +151 -0
- package/src/motion/parallax.ts +120 -0
- package/src/motion/reduced-motion.ts +66 -17
- package/src/motion/types.ts +271 -208
- package/src/motion/typewriter.ts +164 -0
- package/src/plugin/index.ts +37 -0
- package/src/plugin/registry.ts +269 -0
- package/src/plugin/types.ts +137 -0
- package/src/reactive/computed.ts +130 -92
- package/src/router/bq-link.ts +279 -0
- package/src/router/constraints.ts +201 -0
- package/src/router/index.ts +49 -41
- package/src/router/match.ts +312 -106
- package/src/router/path-pattern.ts +52 -0
- package/src/router/query.ts +38 -35
- package/src/router/router.ts +402 -211
- package/src/router/types.ts +139 -93
- package/src/router/use-route.ts +68 -0
- package/src/router/utils.ts +157 -116
- package/src/security/index.ts +2 -7
- package/src/security/sanitize.ts +70 -70
- package/src/security/trusted-html.ts +71 -71
- package/src/ssr/hydrate.ts +82 -0
- package/src/ssr/index.ts +70 -0
- package/src/ssr/render.ts +508 -0
- package/src/ssr/serialize.ts +296 -0
- package/src/ssr/types.ts +81 -0
- package/src/store/create-store.ts +467 -329
- package/src/store/define-store.ts +49 -49
- package/src/store/index.ts +27 -22
- package/src/store/mapping.ts +74 -74
- package/src/store/persisted.ts +206 -19
- package/src/store/types.ts +157 -2
- package/src/store/utils.ts +135 -141
- package/src/store/watch.ts +53 -53
- package/src/storybook/index.ts +2 -1
- package/src/testing/index.ts +42 -0
- package/src/testing/testing.ts +593 -0
- package/src/testing/types.ts +170 -0
- package/src/view/custom-directives.ts +30 -0
- package/src/view/evaluate.ts +292 -290
- package/src/view/process.ts +108 -92
- package/dist/component-BEQgt5hl.js +0 -600
- package/dist/component-BEQgt5hl.js.map +0 -1
- package/dist/core-BGQJVw0-.js +0 -35
- package/dist/core-BGQJVw0-.js.map +0 -1
- package/dist/core-CCEabVHl.js +0 -648
- package/dist/core-CCEabVHl.js.map +0 -1
- package/dist/effect-AFRW_Plg.js +0 -84
- package/dist/effect-AFRW_Plg.js.map +0 -1
- package/dist/motion-D9TcHxOF.js +0 -415
- package/dist/motion-D9TcHxOF.js.map +0 -1
- package/dist/reactive-DSkct0dO.js +0 -254
- package/dist/reactive-DSkct0dO.js.map +0 -1
- package/dist/router-CbDhl8rS.js +0 -188
- package/dist/router-CbDhl8rS.js.map +0 -1
- package/dist/store-BwDvI45q.js +0 -263
- package/dist/store-BwDvI45q.js.map +0 -1
- package/dist/untrack-B0rVscTc.js +0 -7
- package/dist/untrack-B0rVscTc.js.map +0 -1
- package/dist/view-C70lA3vf.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-SM07RUa6.js","names":[],"sources":["../src/view/evaluate.ts","../src/view/directives/bind.ts","../src/view/directives/class.ts","../src/view/directives/for.ts","../src/view/directives/html.ts","../src/view/directives/if.ts","../src/view/directives/model.ts","../src/view/directives/on.ts","../src/view/directives/ref.ts","../src/view/directives/show.ts","../src/view/directives/style.ts","../src/view/directives/text.ts","../src/view/process.ts","../src/view/mount.ts"],"sourcesContent":["import { isPrototypePollutionKey } from '../core/utils/object';\r\nimport { isComputed, isSignal, type Signal } from '../reactive/index';\r\nimport type { BindingContext } from './types';\r\n\r\n/** Maximum number of cached expression functions before LRU eviction */\r\nconst MAX_CACHE_SIZE = 500;\r\n\r\n/** Compiled function type for expression evaluation */\r\ntype CompiledFn = (ctx: BindingContext) => unknown;\r\n\r\n/**\r\n * Simple LRU cache for compiled expression functions.\r\n * Uses Map's insertion order to track recency - accessed items are re-inserted.\r\n * @internal\r\n */\r\nclass LRUCache {\r\n private cache = new Map<string, CompiledFn>();\r\n private maxSize: number;\r\n\r\n constructor(maxSize: number) {\r\n this.maxSize = maxSize;\r\n }\r\n\r\n get(key: string): CompiledFn | undefined {\r\n const value = this.cache.get(key);\r\n if (value !== undefined) {\r\n // Move to end (most recently used) by re-inserting\r\n this.cache.delete(key);\r\n this.cache.set(key, value);\r\n }\r\n return value;\r\n }\r\n\r\n set(key: string, value: CompiledFn): void {\r\n // Delete first if exists to update insertion order\r\n if (this.cache.has(key)) {\r\n this.cache.delete(key);\r\n } else if (this.cache.size >= this.maxSize) {\r\n // Evict oldest (first) entry\r\n const oldest = this.cache.keys().next().value;\r\n if (oldest !== undefined) {\r\n this.cache.delete(oldest);\r\n }\r\n }\r\n this.cache.set(key, value);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n get size(): number {\r\n return this.cache.size;\r\n }\r\n}\r\n\r\n/** LRU cache for compiled evaluate functions, keyed by expression string */\r\nconst evaluateCache = new LRUCache(MAX_CACHE_SIZE);\r\n\r\n/** LRU cache for compiled evaluateRaw functions, keyed by expression string */\r\nconst evaluateRawCache = new LRUCache(MAX_CACHE_SIZE);\r\n\r\n/**\r\n * Clears all cached compiled expression functions.\r\n * Call this when unmounting views or to free memory after heavy template usage.\r\n *\r\n * @example\r\n * ```ts\r\n * import { clearExpressionCache } from 'bquery/view';\r\n *\r\n * // After destroying a view or when cleaning up\r\n * clearExpressionCache();\r\n * ```\r\n */\r\nexport const clearExpressionCache = (): void => {\r\n evaluateCache.clear();\r\n evaluateRawCache.clear();\r\n};\r\n\r\n/**\r\n * Creates a proxy that lazily unwraps signals/computed only when accessed.\r\n * This avoids subscribing to signals that aren't referenced in the expression.\r\n * @internal\r\n */\r\nconst createLazyContext = (context: BindingContext): BindingContext =>\r\n new Proxy(context, {\r\n get(target, prop: string | symbol) {\r\n // Only handle string keys for BindingContext indexing\r\n if (typeof prop !== 'string') {\r\n return Reflect.get(target, prop);\r\n }\r\n const value = target[prop];\r\n // Auto-unwrap signals/computed only when actually accessed\r\n if (isSignal(value) || isComputed(value)) {\r\n return (value as Signal<unknown>).value;\r\n }\r\n return value;\r\n },\r\n has(target, prop: string | symbol) {\r\n // Required for `with` statement to resolve identifiers correctly\r\n if (typeof prop !== 'string') {\r\n return Reflect.has(target, prop);\r\n }\r\n return prop in target;\r\n },\r\n });\r\n\r\n/**\r\n * Evaluates an expression in the given context using `new Function()`.\r\n *\r\n * Signals and computed values in the context are lazily unwrapped only when\r\n * accessed by the expression, avoiding unnecessary subscriptions to unused values.\r\n *\r\n * @security **WARNING:** This function uses dynamic code execution via `new Function()`.\r\n * - NEVER pass expressions derived from user input or untrusted sources\r\n * - Expressions should only come from developer-controlled templates\r\n * - Malicious expressions can access and exfiltrate context data\r\n * - Consider this equivalent to `eval()` in terms of security implications\r\n *\r\n * @internal\r\n */\r\nexport const evaluate = <T = unknown>(expression: string, context: BindingContext): T => {\r\n try {\r\n // Create a proxy that lazily unwraps signals/computed on access\r\n const lazyContext = createLazyContext(context);\r\n\r\n // Use cached function or compile and cache a new one\r\n let fn = evaluateCache.get(expression);\r\n if (!fn) {\r\n // Use `with` to enable direct property access from proxy scope.\r\n // Note: `new Function()` runs in non-strict mode, so `with` is allowed.\r\n fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (\r\n ctx: BindingContext\r\n ) => unknown;\r\n evaluateCache.set(expression, fn);\r\n }\r\n return fn(lazyContext) as T;\r\n } catch (error) {\r\n console.error(`bQuery view: Error evaluating \"${expression}\"`, error);\r\n return undefined as T;\r\n }\r\n};\r\n\r\n/**\r\n * Evaluates an expression and returns the raw value (for signal access).\r\n *\r\n * @security **WARNING:** Uses dynamic code execution. See {@link evaluate} for security notes.\r\n * @internal\r\n */\r\nexport const evaluateRaw = <T = unknown>(expression: string, context: BindingContext): T => {\r\n try {\r\n // Use cached function or compile and cache a new one\r\n let fn = evaluateRawCache.get(expression);\r\n if (!fn) {\r\n // Use `with` to enable direct property access from context scope.\r\n // Unlike `evaluate`, we don't use a lazy proxy - values are accessed directly.\r\n fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (\r\n ctx: BindingContext\r\n ) => unknown;\r\n evaluateRawCache.set(expression, fn);\r\n }\r\n return fn(context) as T;\r\n } catch (error) {\r\n console.error(`bQuery view: Error evaluating \"${expression}\"`, error);\r\n return undefined as T;\r\n }\r\n};\r\n\r\n/**\r\n * Parses object expression like \"{ active: isActive, disabled: !enabled }\".\r\n * Handles nested structures like function calls, arrays, and template literals.\r\n * @internal\r\n */\r\nexport const parseObjectExpression = (expression: string): Record<string, string> => {\r\n const result: Record<string, string> = {};\r\n\r\n // Remove outer braces and trim\r\n const inner = expression\r\n .trim()\r\n .replace(/^\\{|\\}$/g, '')\r\n .trim();\r\n if (!inner) return result;\r\n\r\n // Split by comma at depth 0, respecting strings and nesting\r\n const parts: string[] = [];\r\n let current = '';\r\n let depth = 0;\r\n let inString: string | null = null;\r\n\r\n for (let i = 0; i < inner.length; i++) {\r\n const char = inner[i];\r\n\r\n // Handle string literals: count consecutive backslashes before a quote\r\n // to correctly distinguish escaped quotes from end-of-string\r\n if (char === '\"' || char === \"'\" || char === '`') {\r\n let backslashCount = 0;\r\n let j = i - 1;\r\n while (j >= 0 && inner[j] === '\\\\') {\r\n backslashCount++;\r\n j--;\r\n }\r\n // Quote is escaped only if preceded by an odd number of backslashes\r\n if (backslashCount % 2 === 0) {\r\n if (inString === null) {\r\n inString = char;\r\n } else if (inString === char) {\r\n inString = null;\r\n }\r\n }\r\n current += char;\r\n continue;\r\n }\r\n\r\n // Skip if inside string\r\n if (inString !== null) {\r\n current += char;\r\n continue;\r\n }\r\n\r\n // Track nesting depth for parentheses, brackets, and braces\r\n if (char === '(' || char === '[' || char === '{') {\r\n depth++;\r\n current += char;\r\n } else if (char === ')' || char === ']' || char === '}') {\r\n depth--;\r\n current += char;\r\n } else if (char === ',' && depth === 0) {\r\n // Top-level comma - split point\r\n parts.push(current.trim());\r\n current = '';\r\n } else {\r\n current += char;\r\n }\r\n }\r\n\r\n // Add the last part\r\n if (current.trim()) {\r\n parts.push(current.trim());\r\n }\r\n\r\n // Parse each part to extract key and value\r\n for (const part of parts) {\r\n // Find the first colon at depth 0 (to handle ternary operators in values)\r\n let colonIndex = -1;\r\n let partDepth = 0;\r\n let partInString: string | null = null;\r\n\r\n for (let i = 0; i < part.length; i++) {\r\n const char = part[i];\r\n\r\n if (char === '\"' || char === \"'\" || char === '`') {\r\n let backslashCount = 0;\r\n let j = i - 1;\r\n while (j >= 0 && part[j] === '\\\\') {\r\n backslashCount++;\r\n j--;\r\n }\r\n if (backslashCount % 2 === 0) {\r\n if (partInString === null) {\r\n partInString = char;\r\n } else if (partInString === char) {\r\n partInString = null;\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n if (partInString !== null) continue;\r\n\r\n if (char === '(' || char === '[' || char === '{') {\r\n partDepth++;\r\n } else if (char === ')' || char === ']' || char === '}') {\r\n partDepth--;\r\n } else if (char === ':' && partDepth === 0) {\r\n colonIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n if (colonIndex > -1) {\r\n const key = part\r\n .slice(0, colonIndex)\r\n .trim()\r\n .replace(/^['\"]|['\"]$/g, '');\r\n if (isPrototypePollutionKey(key)) continue;\r\n const value = part.slice(colonIndex + 1).trim();\r\n result[key] = value;\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n","import { effect } from '../../reactive/index';\nimport { evaluate } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-bind:attr directive - attribute binding.\n * @internal\n */\nexport const handleBind = (attrName: string): DirectiveHandler => {\n return (el, expression, context, cleanups) => {\n const cleanup = effect(() => {\n const value = evaluate(expression, context);\n if (value == null || value === false) {\n el.removeAttribute(attrName);\n } else if (value === true) {\n el.setAttribute(attrName, '');\n } else {\n el.setAttribute(attrName, String(value));\n }\n });\n cleanups.push(cleanup);\n };\n};\n","import { effect } from '../../reactive/index';\nimport { evaluate, parseObjectExpression } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-class directive - dynamic class binding.\n * Tracks previously added classes to ensure proper cleanup when expressions change.\n * @internal\n */\nexport const handleClass: DirectiveHandler = (el, expression, context, cleanups) => {\n // Track classes added by this directive to clean them up on re-evaluation\n let previousClasses: Set<string> = new Set();\n\n const cleanup = effect(() => {\n const newClasses: Set<string> = new Set();\n\n if (expression.trimStart().startsWith('{')) {\n // Object syntax: { active: isActive, disabled: !enabled }\n const classMap = parseObjectExpression(expression);\n for (const [className, conditionExpr] of Object.entries(classMap)) {\n const condition = evaluate<boolean>(conditionExpr, context);\n el.classList.toggle(className, Boolean(condition));\n // Track class regardless of condition - toggle handles add/remove\n newClasses.add(className);\n }\n } else if (/^\\s*\\[/.test(expression)) {\n // Array literal syntax: [class1, class2]\n const classes = evaluate<string[]>(expression, context);\n if (Array.isArray(classes)) {\n for (const cls of classes) {\n if (cls) {\n el.classList.add(cls);\n newClasses.add(cls);\n }\n }\n }\n } else {\n // Single expression returning string or array\n const result = evaluate<string | string[]>(expression, context);\n if (typeof result === 'string') {\n result.split(/\\s+/).forEach((cls) => {\n if (cls) {\n el.classList.add(cls);\n newClasses.add(cls);\n }\n });\n } else if (Array.isArray(result)) {\n result.forEach((cls) => {\n if (cls) {\n el.classList.add(cls);\n newClasses.add(cls);\n }\n });\n }\n }\n\n // Remove classes that were previously added but are no longer in the new set\n // This keeps directive-managed classes in sync across all syntax forms and provides\n // defensive cleanup behavior for edge cases (e.g. external classList changes)\n for (const cls of previousClasses) {\n if (!newClasses.has(cls)) {\n el.classList.remove(cls);\n }\n }\n\n previousClasses = newClasses;\n });\n\n cleanups.push(cleanup);\n};\n","import { effect, signal, type CleanupFn, type Signal } from '../../reactive/index';\nimport { evaluate } from '../evaluate';\nimport type { BindingContext, DirectiveHandler } from '../types';\n\ntype ProcessElementFn = (\n el: Element,\n context: BindingContext,\n prefix: string,\n cleanups: CleanupFn[]\n) => void;\n\ntype ProcessChildrenFn = (\n el: Element,\n context: BindingContext,\n prefix: string,\n cleanups: CleanupFn[]\n) => void;\n\n/**\n * Represents a rendered item in bq-for with its DOM element and associated cleanup functions.\n * @internal\n */\ntype RenderedItem = {\n key: unknown;\n element: Element;\n cleanups: CleanupFn[];\n item: unknown;\n index: number;\n itemSignal: Signal<unknown>; // Reactive item value for item-dependent bindings\n indexSignal: Signal<number> | null; // Reactive index for index-dependent bindings\n};\n\n/**\n * Extracts a key from an item using the key expression or falls back to index.\n * @internal\n */\nconst getItemKey = (\n item: unknown,\n index: number,\n keyExpression: string | null,\n itemName: string,\n indexName: string | undefined,\n context: BindingContext\n): unknown => {\n if (!keyExpression) {\n return index; // Fallback to index-based keying\n }\n\n const keyContext: BindingContext = {\n ...context,\n [itemName]: item,\n };\n if (indexName) {\n keyContext[indexName] = index;\n }\n\n return evaluate(keyExpression, keyContext);\n};\n\n/**\n * Handles bq-for directive - list rendering with keyed reconciliation.\n *\n * Supports optional `:key` attribute for efficient DOM reuse:\n * ```html\n * <li bq-for=\"item in items\" :key=\"item.id\">...</li>\n * ```\n *\n * Without a key, falls back to index-based tracking (less efficient for reordering).\n *\n * @internal\n */\nexport const createForHandler = (options: {\n prefix: string;\n processElement: ProcessElementFn;\n processChildren: ProcessChildrenFn;\n}): DirectiveHandler => {\n const { prefix, processElement, processChildren } = options;\n\n return (el, expression, context, cleanups) => {\n const parent = el.parentNode;\n if (!parent) return;\n\n // Parse expression: \"item in items\" or \"(item, index) in items\"\n // Use \\S.* instead of .+ to prevent ReDoS by requiring non-whitespace start\n const match = expression.match(/^\\(?(\\w+)(?:\\s*,\\s*(\\w+))?\\)?\\s+in\\s+(\\S.*)$/);\n if (!match) {\n console.error(`bQuery view: Invalid bq-for expression \"${expression}\"`);\n return;\n }\n\n const [, itemName, indexName, listExpression] = match;\n\n // Extract :key attribute if present\n const keyExpression = el.getAttribute(':key') || el.getAttribute(`${prefix}-key`);\n\n const template = el.cloneNode(true) as Element;\n template.removeAttribute(`${prefix}-for`);\n template.removeAttribute(':key');\n template.removeAttribute(`${prefix}-key`);\n\n // Create placeholder comment\n const placeholder = document.createComment(`bq-for: ${expression}`);\n parent.replaceChild(placeholder, el);\n\n // Track rendered items by key for reconciliation\n let renderedItemsMap = new Map<unknown, RenderedItem>();\n let renderedOrder: unknown[] = [];\n\n /**\n * Creates a new DOM element for an item.\n */\n const createItemElement = (item: unknown, index: number, key: unknown): RenderedItem => {\n const clone = template.cloneNode(true) as Element;\n const itemCleanups: CleanupFn[] = [];\n\n // Create reactive signals for item and index\n const itemSig = signal(item);\n const indexSig = indexName ? signal(index) : null;\n\n const childContext: BindingContext = {\n ...context,\n [itemName]: itemSig,\n };\n if (indexName && indexSig) {\n childContext[indexName] = indexSig;\n }\n\n // Process bindings on the clone\n processElement(clone, childContext, prefix, itemCleanups);\n processChildren(clone, childContext, prefix, itemCleanups);\n\n return {\n key,\n element: clone,\n cleanups: itemCleanups,\n item,\n index,\n itemSignal: itemSig,\n indexSignal: indexSig,\n };\n };\n\n /**\n * Removes a rendered item and cleans up its effects.\n */\n const removeItem = (rendered: RenderedItem): void => {\n for (const cleanup of rendered.cleanups) {\n cleanup();\n }\n rendered.element.remove();\n };\n\n /**\n * Updates an existing item's data and index when reused.\n * Updates the reactive signals so bindings re-render.\n */\n const updateItem = (rendered: RenderedItem, newItem: unknown, newIndex: number): void => {\n // Update item if it changed\n if (!Object.is(rendered.item, newItem)) {\n rendered.item = newItem;\n rendered.itemSignal.value = newItem;\n }\n\n // Update index if it changed\n if (rendered.index !== newIndex) {\n rendered.index = newIndex;\n if (rendered.indexSignal) {\n rendered.indexSignal.value = newIndex;\n }\n }\n };\n\n const cleanup = effect(() => {\n const list = evaluate<unknown[]>(listExpression, context);\n\n if (!Array.isArray(list)) {\n // Clear all if list is invalid\n for (const rendered of renderedItemsMap.values()) {\n removeItem(rendered);\n }\n renderedItemsMap.clear();\n renderedOrder = [];\n return;\n }\n\n // Build new key order and detect changes\n const newKeys: unknown[] = [];\n const newItemsByKey = new Map<unknown, { item: unknown; index: number }>();\n const seenKeys = new Set<unknown>();\n\n list.forEach((item, index) => {\n let key = getItemKey(item, index, keyExpression, itemName, indexName, context);\n\n // Detect duplicate keys - warn developer and fall back to unique composite key\n if (seenKeys.has(key)) {\n console.warn(\n `bq-for: Duplicate key \"${String(key)}\" detected at index ${index}. ` +\n `Falling back to index-based key for this item. ` +\n `Ensure :key expressions produce unique values for each item.`\n );\n // Create a unique composite key to avoid corrupting rendered output\n key = { __bqDuplicateKey: key, __bqIndex: index };\n }\n seenKeys.add(key);\n\n newKeys.push(key);\n newItemsByKey.set(key, { item, index });\n });\n\n // Identify items to remove (in old but not in new)\n const keysToRemove: unknown[] = [];\n for (const key of renderedOrder) {\n if (!newItemsByKey.has(key)) {\n keysToRemove.push(key);\n }\n }\n\n // Remove deleted items\n for (const key of keysToRemove) {\n const rendered = renderedItemsMap.get(key);\n if (rendered) {\n removeItem(rendered);\n renderedItemsMap.delete(key);\n }\n }\n\n // Process new list: create new items, update indices, reorder\n const newRenderedMap = new Map<unknown, RenderedItem>();\n let lastInsertedElement: Element | Comment = placeholder;\n\n for (let i = 0; i < newKeys.length; i++) {\n const key = newKeys[i];\n const { item, index } = newItemsByKey.get(key)!;\n let rendered = renderedItemsMap.get(key);\n\n if (rendered) {\n // Reuse existing element\n updateItem(rendered, item, index);\n newRenderedMap.set(key, rendered);\n\n // Check if element needs to be moved\n const currentNext: ChildNode | null = lastInsertedElement.nextSibling;\n if (currentNext !== rendered.element) {\n // Move element to correct position\n lastInsertedElement.after(rendered.element);\n }\n lastInsertedElement = rendered.element;\n } else {\n // Create new element\n rendered = createItemElement(item, index, key);\n newRenderedMap.set(key, rendered);\n\n // Insert at correct position\n lastInsertedElement.after(rendered.element);\n lastInsertedElement = rendered.element;\n }\n }\n\n // Update tracking state\n renderedItemsMap = newRenderedMap;\n renderedOrder = newKeys;\n });\n\n // When the bq-for itself is cleaned up, also cleanup all rendered items\n cleanups.push(() => {\n cleanup();\n for (const rendered of renderedItemsMap.values()) {\n for (const itemCleanup of rendered.cleanups) {\n itemCleanup();\n }\n }\n renderedItemsMap.clear();\n });\n };\n};\n","import { effect } from '../../reactive/index';\nimport { sanitizeHtml } from '../../security/index';\nimport { evaluate } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-html directive - sets innerHTML (sanitized by default).\n * @internal\n */\nexport const handleHtml = (sanitize: boolean): DirectiveHandler => {\n return (el, expression, context, cleanups) => {\n const cleanup = effect(() => {\n const value = evaluate<string>(expression, context);\n const html = String(value ?? '');\n el.innerHTML = sanitize ? sanitizeHtml(html) : html;\n });\n cleanups.push(cleanup);\n };\n};\n","import { effect } from '../../reactive/index';\nimport { evaluate } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-if directive - conditional rendering.\n * @internal\n */\nexport const handleIf: DirectiveHandler = (el, expression, context, cleanups) => {\n const placeholder = document.createComment(`bq-if: ${expression}`);\n\n // Store original element state\n let isInserted = true;\n\n const cleanup = effect(() => {\n const condition = evaluate<boolean>(expression, context);\n\n if (condition && !isInserted) {\n // Insert element using replaceWith to handle moved elements\n placeholder.replaceWith(el);\n isInserted = true;\n } else if (!condition && isInserted) {\n // Remove element using replaceWith to handle moved elements\n el.replaceWith(placeholder);\n isInserted = false;\n }\n });\n\n cleanups.push(cleanup);\n};\n","import { effect, isSignal, type Signal } from '../../reactive/index';\nimport { evaluateRaw } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-model directive - two-way binding.\n * @internal\n */\nexport const handleModel: DirectiveHandler = (el, expression, context, cleanups) => {\n const input = el as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n const rawValue = evaluateRaw<Signal<unknown>>(expression, context);\n\n if (!isSignal(rawValue)) {\n console.warn(`bQuery view: bq-model requires a signal, got \"${expression}\"`);\n return;\n }\n\n const sig = rawValue as Signal<unknown>;\n\n // Initial value sync\n const isCheckbox = input.type === 'checkbox';\n const isRadio = input.type === 'radio';\n\n const updateInput = () => {\n if (isCheckbox) {\n (input as HTMLInputElement).checked = Boolean(sig.value);\n } else if (isRadio) {\n (input as HTMLInputElement).checked = sig.value === input.value;\n } else {\n input.value = String(sig.value ?? '');\n }\n };\n\n // Effect to sync signal -> input\n const cleanup = effect(() => {\n updateInput();\n });\n cleanups.push(cleanup);\n\n // Event listener to sync input -> signal\n const eventType = input.tagName === 'SELECT' ? 'change' : 'input';\n const handler = () => {\n if (isCheckbox) {\n sig.value = (input as HTMLInputElement).checked;\n } else if (isRadio) {\n if ((input as HTMLInputElement).checked) {\n sig.value = input.value;\n }\n } else {\n sig.value = input.value;\n }\n };\n\n input.addEventListener(eventType, handler);\n cleanups.push(() => input.removeEventListener(eventType, handler));\n};\n","import { evaluateRaw } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-on:event directive - event binding.\n * @internal\n */\nexport const handleOn = (eventName: string): DirectiveHandler => {\n return (el, expression, context, cleanups) => {\n const handler = (event: Event) => {\n // Add $event to context for expression evaluation\n const eventContext = { ...context, $event: event, $el: el };\n\n // Check if expression contains a function call (has parentheses)\n // If not, it might be a plain function reference like \"handleClick\"\n // Note: Method references like \"handlers.onClick\" will lose their receiver\n // when auto-invoked. For methods, use explicit calls: \"handlers.onClick($event)\"\n const containsCall = expression.includes('(');\n\n if (!containsCall) {\n // Evaluate the expression - if it returns a function, invoke it with $event\n const result = evaluateRaw<unknown>(expression, eventContext);\n if (typeof result === 'function') {\n // Auto-invoke with event. Note: `this` will be undefined for method references.\n // For proper method binding, use explicit syntax: \"obj.method($event)\"\n result(event);\n return;\n }\n // If not a function, the expression was already evaluated (e.g., \"count.value++\")\n return;\n }\n\n // Otherwise evaluate as expression using evaluateRaw to allow signal mutations\n // (e.g., \"count.value++\" or \"handleClick($event)\")\n evaluateRaw(expression, eventContext);\n };\n\n el.addEventListener(eventName, handler);\n cleanups.push(() => el.removeEventListener(eventName, handler));\n };\n};\n","import { isSignal, type Signal } from '../../reactive/index';\nimport { evaluateRaw } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Checks if an object has a writable `value` property.\n * Returns true if `value` is an own data property or an accessor with a setter.\n * @internal\n */\nfunction hasWritableValue(obj: object): obj is { value: Element | null } {\n const descriptor = Object.getOwnPropertyDescriptor(obj, 'value');\n if (!descriptor) return false;\n // Data property: check writable flag\n if ('value' in descriptor) return descriptor.writable === true;\n // Accessor property: check for setter\n return typeof descriptor.set === 'function';\n}\n\n/**\n * Handles bq-ref directive - element reference.\n * @internal\n */\nexport const handleRef: DirectiveHandler = (el, expression, context, cleanups) => {\n const rawValue = evaluateRaw<Signal<Element | null> | { value: Element | null }>(\n expression,\n context\n );\n\n if (isSignal(rawValue)) {\n rawValue.value = el;\n cleanups.push(() => {\n rawValue.value = null;\n });\n } else if (typeof rawValue === 'object' && rawValue !== null && hasWritableValue(rawValue)) {\n // Object with writable .value property (e.g., { value: null })\n rawValue.value = el;\n cleanups.push(() => {\n rawValue.value = null;\n });\n }\n};\n","import { effect } from '../../reactive/index';\nimport { evaluate } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-show directive - toggle visibility.\n * @internal\n */\nexport const handleShow: DirectiveHandler = (el, expression, context, cleanups) => {\n const htmlEl = el as HTMLElement;\n // Capture the computed display value to properly restore visibility.\n // If inline display is 'none' or empty, we need to use the computed value.\n // Use ownerDocument.defaultView for cross-document/iframe compatibility.\n let originalDisplay = htmlEl.style.display;\n if (!originalDisplay || originalDisplay === 'none') {\n const computed = htmlEl.ownerDocument.defaultView?.getComputedStyle(htmlEl).display ?? '';\n originalDisplay = computed !== 'none' ? computed : '';\n }\n\n const cleanup = effect(() => {\n const condition = evaluate<boolean>(expression, context);\n htmlEl.style.display = condition ? originalDisplay : 'none';\n });\n\n cleanups.push(cleanup);\n};\n","import { effect } from '../../reactive/index';\nimport { evaluate, parseObjectExpression } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-style directive - dynamic style binding.\n * @internal\n */\nexport const handleStyle: DirectiveHandler = (el, expression, context, cleanups) => {\n const htmlEl = el as HTMLElement;\n let appliedStyles: Set<string> = new Set();\n\n const cleanup = effect(() => {\n const newStyles = new Set<string>();\n\n if (expression.trimStart().startsWith('{')) {\n const styleMap = parseObjectExpression(expression);\n for (const [prop, valueExpr] of Object.entries(styleMap)) {\n const value = evaluate<string>(valueExpr, context);\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n htmlEl.style.setProperty(cssProp, String(value ?? ''));\n newStyles.add(cssProp);\n }\n } else {\n const result = evaluate<Record<string, string>>(expression, context);\n if (result && typeof result === 'object') {\n for (const [prop, value] of Object.entries(result)) {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n htmlEl.style.setProperty(cssProp, String(value ?? ''));\n newStyles.add(cssProp);\n }\n }\n }\n\n // Remove styles that were previously applied but are no longer present\n for (const cssProp of appliedStyles) {\n if (!newStyles.has(cssProp)) {\n htmlEl.style.removeProperty(cssProp);\n }\n }\n\n // Update the set of applied styles\n appliedStyles = newStyles;\n });\n\n cleanups.push(cleanup);\n};\n","import { effect } from '../../reactive/index';\nimport { evaluate } from '../evaluate';\nimport type { DirectiveHandler } from '../types';\n\n/**\n * Handles bq-text directive - sets text content.\n * @internal\n */\nexport const handleText: DirectiveHandler = (el, expression, context, cleanups) => {\n const cleanup = effect(() => {\n const value = evaluate(expression, context);\n el.textContent = String(value ?? '');\n });\n cleanups.push(cleanup);\n};\n","import type { CleanupFn } from '../reactive/index';\r\nimport { detectDevEnvironment } from '../core/env';\r\nimport { getCustomDirective } from './custom-directives';\r\nimport type { BindingContext, DirectiveHandler } from './types';\r\n\r\nexport type DirectiveHandlers = {\r\n text: DirectiveHandler;\r\n html: DirectiveHandler;\r\n if: DirectiveHandler;\r\n show: DirectiveHandler;\r\n class: DirectiveHandler;\r\n style: DirectiveHandler;\r\n model: DirectiveHandler;\r\n ref: DirectiveHandler;\r\n for: DirectiveHandler;\r\n bind: (attrName: string) => DirectiveHandler;\r\n on: (eventName: string) => DirectiveHandler;\r\n};\r\n\r\n/**\r\n * Processes a single element for directives.\r\n * @internal\r\n */\r\nexport const processElement = (\r\n el: Element,\r\n context: BindingContext,\r\n prefix: string,\r\n cleanups: CleanupFn[],\r\n handlers: DirectiveHandlers\r\n): void => {\r\n const attributes = Array.from(el.attributes);\r\n\r\n for (const attr of attributes) {\r\n const { name: attributeName, value } = attr;\r\n\r\n if (!attributeName.startsWith(`${prefix}-`)) continue;\r\n\r\n const directive = attributeName.slice(prefix.length + 1); // Remove prefix and dash\r\n\r\n // Handle bq-for specially (creates new scope)\r\n if (directive === 'for') {\r\n handlers.for(el, value, context, cleanups);\r\n return; // Don't process children, bq-for handles it\r\n }\r\n\r\n // Handle other directives\r\n if (directive === 'text') {\r\n handlers.text(el, value, context, cleanups);\r\n } else if (directive === 'html') {\r\n handlers.html(el, value, context, cleanups);\r\n } else if (directive === 'if') {\r\n handlers.if(el, value, context, cleanups);\r\n } else if (directive === 'show') {\r\n handlers.show(el, value, context, cleanups);\r\n } else if (directive === 'class') {\r\n handlers.class(el, value, context, cleanups);\r\n } else if (directive === 'style') {\r\n handlers.style(el, value, context, cleanups);\r\n } else if (directive === 'model') {\r\n handlers.model(el, value, context, cleanups);\r\n } else if (directive === 'ref') {\r\n handlers.ref(el, value, context, cleanups);\r\n } else if (directive.startsWith('bind:')) {\r\n const attrName = directive.slice(5);\r\n handlers.bind(attrName)(el, value, context, cleanups);\r\n } else if (directive.startsWith('on:')) {\r\n const eventName = directive.slice(3);\r\n handlers.on(eventName)(el, value, context, cleanups);\r\n } else {\r\n // Check for custom directives registered via plugins\r\n const customHandler = getCustomDirective(directive);\r\n if (customHandler) {\r\n customHandler(el, value, context, cleanups);\r\n } else if (\r\n detectDevEnvironment() &&\r\n typeof console !== 'undefined' &&\r\n typeof console.warn === 'function'\r\n ) {\r\n console.warn(\r\n `[bQuery][view] Unknown directive \"${attributeName}\" (parsed as \"${directive}\") on <${el.tagName.toLowerCase()}>. This may be a typo or a missing custom directive registration.`\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Recursively processes children of an element.\r\n * @internal\r\n */\r\nexport const processChildren = (\r\n el: Element,\r\n context: BindingContext,\r\n prefix: string,\r\n cleanups: CleanupFn[],\r\n handlers: DirectiveHandlers\r\n): void => {\r\n const children = Array.from(el.children);\r\n for (const child of children) {\r\n // Skip if element has bq-for (handled separately)\r\n if (!child.hasAttribute(`${prefix}-for`)) {\r\n processElement(child, context, prefix, cleanups, handlers);\r\n processChildren(child, context, prefix, cleanups, handlers);\r\n } else {\r\n processElement(child, context, prefix, cleanups, handlers);\r\n }\r\n }\r\n};\r\n","import type { CleanupFn } from '../reactive/index';\nimport {\n createForHandler,\n handleBind,\n handleClass,\n handleHtml,\n handleIf,\n handleModel,\n handleOn,\n handleRef,\n handleShow,\n handleStyle,\n handleText,\n} from './directives/index';\nimport { processChildren, processElement, type DirectiveHandlers } from './process';\nimport type { BindingContext, MountOptions, View } from './types';\n\n/**\n * Mounts a reactive view to an element.\n *\n * @param selector - CSS selector or Element\n * @param context - Binding context with signals, computed, and functions\n * @param options - Mount options\n * @returns The mounted View instance\n *\n * @security **WARNING:** Directive expressions (bq-text, bq-if, bq-on, etc.) are evaluated\n * using `new Function()` at runtime. This means:\n * - Template attributes must come from trusted sources only\n * - NEVER load templates containing bq-* attributes from user input or untrusted APIs\n * - If you must use external templates, validate/sanitize attribute values first\n *\n * @example\n * ```ts\n * import { mount } from 'bquery/view';\n * import { signal, computed } from 'bquery/reactive';\n *\n * const name = signal('World');\n * const greeting = computed(() => `Hello, ${name.value}!`);\n * const items = signal([\n * { id: 1, text: 'Item 1' },\n * { id: 2, text: 'Item 2' },\n * ]);\n *\n * const view = mount('#app', {\n * name,\n * greeting,\n * items,\n * addItem: () => {\n * items.value = [...items.value, { id: Date.now(), text: 'New Item' }];\n * },\n * });\n *\n * // Later, cleanup\n * view.destroy();\n * ```\n */\nexport const mount = (\n selector: string | Element,\n context: BindingContext,\n options: MountOptions = {}\n): View => {\n const { prefix = 'bq', sanitize = true } = options;\n\n const el = typeof selector === 'string' ? document.querySelector(selector) : selector;\n\n if (!el) {\n throw new Error(`bQuery view: Element \"${selector}\" not found.`);\n }\n\n // Reject if root element has bq-for directive\n // bq-for replaces the element with a placeholder comment, which would leave View.el detached\n if (el.hasAttribute(`${prefix}-for`)) {\n throw new Error(\n `bQuery view: Cannot mount on element with ${prefix}-for directive. ` +\n `Wrap the ${prefix}-for element in a container instead.`\n );\n }\n\n const cleanups: CleanupFn[] = [];\n\n const handlers: DirectiveHandlers = {\n text: handleText,\n html: handleHtml(sanitize),\n if: handleIf,\n show: handleShow,\n class: handleClass,\n style: handleStyle,\n model: handleModel,\n ref: handleRef,\n for: createForHandler({\n prefix,\n processElement: (node, nodeContext, nodePrefix, nodeCleanups) =>\n processElement(node, nodeContext, nodePrefix, nodeCleanups, handlers),\n processChildren: (node, nodeContext, nodePrefix, nodeCleanups) =>\n processChildren(node, nodeContext, nodePrefix, nodeCleanups, handlers),\n }),\n bind: handleBind,\n on: handleOn,\n };\n\n const processWithHandlers = (\n node: Element,\n nodeContext: BindingContext,\n nodeCleanups: CleanupFn[]\n ) => {\n // Check if element has bq-for before processing\n // bq-for replaces the element and handles its children internally\n const hasFor = node.hasAttribute(`${prefix}-for`);\n\n processElement(node, nodeContext, prefix, nodeCleanups, handlers);\n\n // Skip processChildren if bq-for was on this element - it handles children itself\n if (!hasFor) {\n processChildren(node, nodeContext, prefix, nodeCleanups, handlers);\n }\n };\n\n // Process the root element and its children\n processWithHandlers(el, context, cleanups);\n\n return {\n el,\n context,\n\n update: (newContext: Partial<BindingContext>) => {\n Object.assign(context, newContext);\n },\n\n destroy: () => {\n for (const cleanup of cleanups) {\n cleanup();\n }\n cleanups.length = 0;\n },\n };\n};\n\n/**\n * Creates a reactive template function.\n *\n * @param template - HTML template string\n * @returns A function that creates a mounted element with the given context\n *\n * @example\n * ```ts\n * import { createTemplate } from 'bquery/view';\n * import { signal } from 'bquery/reactive';\n *\n * const TodoItem = createTemplate(`\n * <li bq-class=\"{ completed: done }\">\n * <input type=\"checkbox\" bq-model=\"done\" />\n * <span bq-text=\"text\"></span>\n * </li>\n * `);\n *\n * const item = TodoItem({\n * done: signal(false),\n * text: 'Buy groceries',\n * });\n *\n * document.querySelector('#list').append(item.el);\n * ```\n */\nexport const createTemplate = (\n template: string,\n options: MountOptions = {}\n): ((context: BindingContext) => View) => {\n return (context: BindingContext) => {\n const container = document.createElement('div');\n container.innerHTML = template.trim();\n\n const el = container.firstElementChild;\n if (!el) {\n throw new Error('bQuery view: Template must contain a single root element.');\n }\n\n // We know at least one element exists (firstElementChild is not null above)\n // Reject if there are multiple root elements\n if (container.childElementCount > 1) {\n throw new Error(\n `bQuery view: Template must contain exactly one root element, found ${container.childElementCount}.`\n );\n }\n\n const { prefix = 'bq' } = options;\n // Reject templates with bq-for or bq-if on the root element\n // These directives replace the element with a placeholder comment, which would leave View.el detached\n // Since processing happens while el is still in the temporary container, the placeholder\n // would remain there while view.el is inserted elsewhere, causing desync on future toggles\n if (el.hasAttribute(`${prefix}-for`) || el.hasAttribute(`${prefix}-if`)) {\n const directive = el.hasAttribute(`${prefix}-for`) ? 'for' : 'if';\n throw new Error(\n `bQuery view: Template root element cannot have ${prefix}-${directive} directive. ` +\n `Wrap the ${prefix}-${directive} element in a container instead.`\n );\n }\n\n return mount(el, context, options);\n };\n};\n"],"mappings":"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"}
|
|
@@ -27,12 +27,13 @@ function a(t, o) {
|
|
|
27
27
|
return Object.prototype.hasOwnProperty.call(t, o);
|
|
28
28
|
}
|
|
29
29
|
export {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
u as a,
|
|
31
|
+
s as i,
|
|
32
32
|
a as n,
|
|
33
|
-
|
|
33
|
+
l as o,
|
|
34
34
|
c as r,
|
|
35
|
+
f as s,
|
|
35
36
|
i as t
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
//# sourceMappingURL=object-
|
|
39
|
+
//# sourceMappingURL=object-BCk-1c8T.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-
|
|
1
|
+
{"version":3,"file":"object-BCk-1c8T.js","names":[],"sources":["../src/core/utils/object.ts"],"sourcesContent":["/**\n * Object-focused utility helpers.\n *\n * @module bquery/core/utils/object\n */\n\n/**\n * Checks if a value is a plain object (not null, array, or class instance).\n *\n * @param value - The value to check\n * @returns True if the value is a plain object\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/**\n * Checks if a key could cause prototype pollution.\n * These keys are dangerous when used in object merging operations.\n *\n * @param key - The key to check\n * @returns True if the key is a prototype pollution vector\n *\n * @internal\n */\nexport function isPrototypePollutionKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype';\n}\n\n/**\n * Creates a deep clone using structuredClone if available, otherwise fallback to JSON.\n *\n * @template T - The type of value being cloned\n * @param value - The value to clone\n * @returns A deep copy of the value\n *\n * @remarks\n * When `structuredClone` is available (modern browsers, Node 17+, Bun), this function\n * provides full deep cloning including circular references, Date, Map, Set, ArrayBuffer, etc.\n *\n * **JSON fallback limitations** (older environments without `structuredClone`):\n * - **Throws** on circular references\n * - **Drops** functions, `undefined`, and Symbol properties\n * - **Transforms** Date → ISO string, Map/Set → empty object, BigInt → throws\n * - **Loses** prototype chains and non-enumerable properties\n *\n * For guaranteed safe cloning of arbitrary data, ensure your environment supports\n * `structuredClone` or pre-validate your data structure.\n *\n * @example\n * ```ts\n * const original = { nested: { value: 1 } };\n * const copy = clone(original);\n * copy.nested.value = 2;\n * console.log(original.nested.value); // 1\n * ```\n */\nexport function clone<T>(value: T): T {\n if (typeof structuredClone === 'function') {\n return structuredClone(value);\n }\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\n/**\n * Deep-merges plain objects into a new object.\n * Later sources override earlier ones for primitive values.\n * Objects are recursively merged.\n *\n * @param sources - Objects to merge\n * @returns A new object with all sources merged as an intersection type\n *\n * @remarks\n * This function uses overloads to provide accurate intersection types for up to 5 sources.\n * For more than 5 sources, the return type falls back to `Record<string, unknown>`.\n *\n * Note that deep merging creates a shallow intersection at the type level. Nested objects\n * are merged at runtime, but TypeScript sees them as intersected types which may not\n * perfectly represent the merged structure for deeply nested conflicting types.\n *\n * @example\n * ```ts\n * const result = merge(\n * { a: 1, nested: { x: 1 } },\n * { b: 2, nested: { y: 2 } }\n * );\n * // Result: { a: 1, b: 2, nested: { x: 1, y: 2 } }\n * // Type: { a: number; nested: { x: number } } & { b: number; nested: { y: number } }\n * ```\n *\n * @security This method is protected against prototype pollution attacks.\n * Keys like `__proto__`, `constructor`, and `prototype` are ignored.\n */\nexport function merge<T1 extends Record<string, unknown>>(source1: T1): T1;\nexport function merge<T1 extends Record<string, unknown>, T2 extends Record<string, unknown>>(\n source1: T1,\n source2: T2\n): T1 & T2;\nexport function merge<\n T1 extends Record<string, unknown>,\n T2 extends Record<string, unknown>,\n T3 extends Record<string, unknown>,\n>(source1: T1, source2: T2, source3: T3): T1 & T2 & T3;\nexport function merge<\n T1 extends Record<string, unknown>,\n T2 extends Record<string, unknown>,\n T3 extends Record<string, unknown>,\n T4 extends Record<string, unknown>,\n>(source1: T1, source2: T2, source3: T3, source4: T4): T1 & T2 & T3 & T4;\nexport function merge<\n T1 extends Record<string, unknown>,\n T2 extends Record<string, unknown>,\n T3 extends Record<string, unknown>,\n T4 extends Record<string, unknown>,\n T5 extends Record<string, unknown>,\n>(source1: T1, source2: T2, source3: T3, source4: T4, source5: T5): T1 & T2 & T3 & T4 & T5;\nexport function merge(...sources: Record<string, unknown>[]): Record<string, unknown>;\nexport function merge(...sources: Record<string, unknown>[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const source of sources) {\n for (const [key, value] of Object.entries(source)) {\n if (isPrototypePollutionKey(key)) continue;\n\n if (isPlainObject(value) && isPlainObject(result[key])) {\n result[key] = merge(\n result[key] as Record<string, unknown>,\n value as Record<string, unknown>\n );\n } else {\n result[key] = value;\n }\n }\n }\n return result;\n}\n\n/**\n * Picks specified keys from an object.\n *\n * @template T - The object type\n * @template K - The key type\n * @param obj - The source object\n * @param keys - Keys to pick\n * @returns A new object with only the specified keys\n *\n * @example\n * ```ts\n * const user = { name: 'John', age: 30, email: 'john@example.com' };\n * pick(user, ['name', 'email']); // { name: 'John', email: 'john@example.com' }\n * ```\n */\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: K[]\n): Pick<T, K> {\n const result = {} as Pick<T, K>;\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n return result;\n}\n\n/**\n * Omits specified keys from an object.\n *\n * @template T - The object type\n * @template K - The key type\n * @param obj - The source object\n * @param keys - Keys to omit\n * @returns A new object without the specified keys\n *\n * @example\n * ```ts\n * const user = { name: 'John', age: 30, password: 'secret' };\n * omit(user, ['password']); // { name: 'John', age: 30 }\n * ```\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n obj: T,\n keys: K[]\n): Omit<T, K> {\n const result = { ...obj };\n for (const key of keys) {\n delete result[key];\n }\n return result as Omit<T, K>;\n}\n\n/**\n * Checks if an object has a given own property.\n *\n * @template T - The object type\n * @param obj - The object to check\n * @param key - The property key\n * @returns True if the property exists on the object\n *\n * @example\n * ```ts\n * hasOwn({ a: 1 }, 'a'); // true\n * ```\n */\nexport function hasOwn<T extends object>(obj: T, key: PropertyKey): key is keyof T {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\n"],"mappings":"AAYA,SAAgB,EAAc,GAAkD;AAC9E,SAAO,OAAO,UAAU,SAAS,KAAK,CAAA,MAAW;;AAYnD,SAAgB,EAAwB,GAAsB;AAC5D,SAAO,MAAQ,eAAe,MAAQ,iBAAiB,MAAQ;;AA+BjE,SAAgB,EAAS,GAAa;AACpC,SAAI,OAAO,mBAAoB,aACtB,gBAAgB,CAAA,IAElB,KAAK,MAAM,KAAK,UAAU,CAAA,CAAM;;AAwDzC,SAAgB,KAAS,GAA6D;AACpF,QAAM,IAAkC,CAAA;AACxC,aAAW,KAAU,EACnB,YAAW,CAAC,GAAK,CAAA,KAAU,OAAO,QAAQ,CAAA;AACxC,IAAI,EAAwB,CAAA,MAExB,EAAc,CAAA,KAAU,EAAc,EAAO,CAAA,CAAA,IAC/C,EAAO,CAAA,IAAO,EACZ,EAAO,CAAA,GACP,CAAA,IAGF,EAAO,CAAA,IAAO;AAIpB,SAAO;;AAkBT,SAAgB,EACd,GACA,GACY;AACZ,QAAM,IAAS,CAAA;AACf,aAAW,KAAO,EAChB,CAAI,KAAO,MACT,EAAO,CAAA,IAAO,EAAI,CAAA;AAGtB,SAAO;;AAkBT,SAAgB,EACd,GACA,GACY;AACZ,QAAM,IAAS,EAAE,GAAG,EAAA;AACpB,aAAW,KAAO,EAChB,QAAO,EAAO,CAAA;AAEhB,SAAO;;AAgBT,SAAgB,EAAyB,GAAQ,GAAkC;AACjF,SAAO,OAAO,UAAU,eAAe,KAAK,GAAK,CAAA"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as p } from "./config-
|
|
3
|
-
import { n as v } from "./core-BGQJVw0-.js";
|
|
1
|
+
import { n as w, r as v } from "./core-DnlyjbF2.js";
|
|
2
|
+
import { n as p } from "./config-BW35FKuA.js";
|
|
4
3
|
var k = class {
|
|
5
4
|
constructor(e) {
|
|
6
5
|
this.bucketName = e, this.dbPromise = null, this.storeName = "blobs";
|
|
@@ -35,7 +34,7 @@ var k = class {
|
|
|
35
34
|
async keys() {
|
|
36
35
|
return (await this.withStore("readonly", (e) => e.getAllKeys())).map((e) => String(e));
|
|
37
36
|
}
|
|
38
|
-
},
|
|
37
|
+
}, J = { async open(e) {
|
|
39
38
|
return new k(e);
|
|
40
39
|
} }, N = class {
|
|
41
40
|
constructor(e) {
|
|
@@ -59,7 +58,7 @@ var k = class {
|
|
|
59
58
|
async keys() {
|
|
60
59
|
return (await this.cache.keys()).map((e) => e.url);
|
|
61
60
|
}
|
|
62
|
-
},
|
|
61
|
+
}, M = {
|
|
63
62
|
isSupported() {
|
|
64
63
|
return "caches" in window;
|
|
65
64
|
},
|
|
@@ -99,7 +98,7 @@ var k = class {
|
|
|
99
98
|
if (typeof document > "u") return;
|
|
100
99
|
const s = t.serialize ? t.serialize(r) : typeof r == "string" ? r : JSON.stringify(r), n = [`${encodeURIComponent(e)}=${encodeURIComponent(s)}`];
|
|
101
100
|
t.path && n.push(`Path=${t.path}`), t.domain && n.push(`Domain=${t.domain}`), typeof t.maxAge == "number" && n.push(`Max-Age=${t.maxAge}`), t.expires && n.push(`Expires=${t.expires.toUTCString()}`), t.sameSite && n.push(`SameSite=${t.sameSite}`), t.secure && n.push("Secure"), document.cookie = n.join("; ");
|
|
102
|
-
},
|
|
101
|
+
}, U = (e, r = {}) => {
|
|
103
102
|
const t = p().cookies, s = {
|
|
104
103
|
path: t?.path ?? "/",
|
|
105
104
|
sameSite: t?.sameSite ?? "Lax",
|
|
@@ -115,10 +114,10 @@ var k = class {
|
|
|
115
114
|
} catch (a) {
|
|
116
115
|
console.warn(`bQuery: Failed to deserialize cookie "${e}", using raw string value`, a), i = n ?? i;
|
|
117
116
|
}
|
|
118
|
-
const c =
|
|
117
|
+
const c = w(i);
|
|
119
118
|
if (typeof document > "u" || s.watch === !1) return c;
|
|
120
119
|
let o = !1;
|
|
121
|
-
return
|
|
120
|
+
return v(() => {
|
|
122
121
|
const a = c.value;
|
|
123
122
|
if (!o) {
|
|
124
123
|
o = !0;
|
|
@@ -130,7 +129,7 @@ var k = class {
|
|
|
130
129
|
}
|
|
131
130
|
D(e, a, s);
|
|
132
131
|
}), c;
|
|
133
|
-
},
|
|
132
|
+
}, R = {
|
|
134
133
|
isSupported() {
|
|
135
134
|
return "Notification" in window;
|
|
136
135
|
},
|
|
@@ -153,14 +152,14 @@ var k = class {
|
|
|
153
152
|
"clip:rect(0, 0, 0, 0)",
|
|
154
153
|
"white-space:nowrap",
|
|
155
154
|
"border:0"
|
|
156
|
-
].join(";"),
|
|
155
|
+
].join(";"), V = (e = {}) => {
|
|
157
156
|
const r = p().announcer, t = {
|
|
158
157
|
politeness: r?.politeness ?? "polite",
|
|
159
158
|
atomic: r?.atomic ?? !0,
|
|
160
159
|
delay: r?.delay ?? 16,
|
|
161
160
|
clearDelay: r?.clearDelay ?? 1e3,
|
|
162
161
|
...e
|
|
163
|
-
}, s =
|
|
162
|
+
}, s = w("");
|
|
164
163
|
if (typeof document > "u") return {
|
|
165
164
|
element: null,
|
|
166
165
|
message: s,
|
|
@@ -192,7 +191,7 @@ var k = class {
|
|
|
192
191
|
};
|
|
193
192
|
l.appendChild(i);
|
|
194
193
|
}
|
|
195
|
-
const o =
|
|
194
|
+
const o = v(() => {
|
|
196
195
|
i.textContent = s.value;
|
|
197
196
|
});
|
|
198
197
|
let a, m, u = !1;
|
|
@@ -230,7 +229,7 @@ var k = class {
|
|
|
230
229
|
t.setAttribute("data-bquery-page-meta", "true");
|
|
231
230
|
for (const [s, n] of Object.entries(r)) n !== void 0 && t.setAttribute(s, n);
|
|
232
231
|
return t;
|
|
233
|
-
},
|
|
232
|
+
}, W = (e) => {
|
|
234
233
|
if (typeof document > "u") return () => {
|
|
235
234
|
};
|
|
236
235
|
const r = p().pageMeta, t = e.title ? r?.titleTemplate ? r.titleTemplate(e.title) : e.title : void 0, s = [], n = [], i = document.title;
|
|
@@ -338,7 +337,7 @@ var k = class {
|
|
|
338
337
|
async keys() {
|
|
339
338
|
return (await this.withStore("readonly", (e) => e.getAllKeys())).map((e) => String(e));
|
|
340
339
|
}
|
|
341
|
-
},
|
|
340
|
+
}, Q = {
|
|
342
341
|
local() {
|
|
343
342
|
return new q();
|
|
344
343
|
},
|
|
@@ -350,13 +349,13 @@ var k = class {
|
|
|
350
349
|
}
|
|
351
350
|
};
|
|
352
351
|
export {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
352
|
+
U as a,
|
|
353
|
+
R as i,
|
|
354
|
+
W as n,
|
|
355
|
+
M as o,
|
|
356
|
+
V as r,
|
|
357
|
+
J as s,
|
|
358
|
+
Q as t
|
|
360
359
|
};
|
|
361
360
|
|
|
362
|
-
//# sourceMappingURL=platform-
|
|
361
|
+
//# sourceMappingURL=platform-CPbCprb6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-Dr9b6fsq.js","names":[],"sources":["../src/platform/buckets.ts","../src/platform/cache.ts","../src/platform/cookies.ts","../src/platform/notifications.ts","../src/platform/announcer.ts","../src/platform/meta.ts","../src/platform/storage.ts"],"sourcesContent":["/**\n * Storage Buckets API wrapper.\n * Provides a simplified interface for storing blobs and binary data.\n * Falls back to IndexedDB when Storage Buckets API is not available.\n */\n\n/**\n * Bucket interface for blob storage operations.\n */\nexport interface Bucket {\n /**\n * Store a blob in the bucket.\n * @param key - Unique identifier for the blob\n * @param data - Blob data to store\n */\n put(key: string, data: Blob): Promise<void>;\n\n /**\n * Retrieve a blob from the bucket.\n * @param key - Blob identifier\n * @returns The stored blob or null if not found\n */\n get(key: string): Promise<Blob | null>;\n\n /**\n * Remove a blob from the bucket.\n * @param key - Blob identifier\n */\n remove(key: string): Promise<void>;\n\n /**\n * List all keys in the bucket.\n * @returns Array of blob keys\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * IndexedDB-based bucket implementation.\n * Used as fallback when Storage Buckets API is unavailable.\n */\nclass IndexedDBBucket implements Bucket {\n private dbPromise: Promise<IDBDatabase> | null = null;\n private readonly storeName = 'blobs';\n\n constructor(private readonly bucketName: string) {}\n\n private openDB(): Promise<IDBDatabase> {\n if (this.dbPromise) return this.dbPromise;\n\n const dbName = `bquery-bucket-${this.bucketName}`;\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n\n return this.dbPromise;\n }\n\n private async withStore<T>(\n mode: IDBTransactionMode,\n operation: (store: IDBObjectStore) => IDBRequest<T>\n ): Promise<T> {\n const db = await this.openDB();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.storeName, mode);\n const store = tx.objectStore(this.storeName);\n const request = operation(store);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async put(key: string, data: Blob): Promise<void> {\n await this.withStore('readwrite', (store) => store.put(data, key));\n }\n\n async get(key: string): Promise<Blob | null> {\n const result = await this.withStore<Blob | undefined>('readonly', (store) => store.get(key));\n return result ?? null;\n }\n\n async remove(key: string): Promise<void> {\n await this.withStore('readwrite', (store) => store.delete(key));\n }\n\n async keys(): Promise<string[]> {\n const result = await this.withStore<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return result.map((key) => String(key));\n }\n}\n\n/**\n * Bucket manager for creating and accessing storage buckets.\n */\nexport const buckets = {\n /**\n * Open or create a storage bucket.\n * @param name - Bucket name\n * @returns Bucket instance for blob operations\n */\n async open(name: string): Promise<Bucket> {\n // Storage Buckets API is experimental; use IndexedDB fallback\n return new IndexedDBBucket(name);\n },\n};\n","/**\n * Cache Storage API wrapper.\n * Provides a simplified interface for caching responses and assets.\n */\n\n/**\n * Cache handle interface for managing cached resources.\n */\nexport interface CacheHandle {\n /**\n * Add a resource to the cache by URL.\n * Fetches the resource and stores the response.\n * @param url - URL to fetch and cache\n */\n add(url: string): Promise<void>;\n\n /**\n * Add multiple resources to the cache.\n * @param urls - Array of URLs to fetch and cache\n */\n addAll(urls: string[]): Promise<void>;\n\n /**\n * Store a custom response in the cache.\n * @param url - URL key for the cached response\n * @param response - Response object to cache\n */\n put(url: string, response: Response): Promise<void>;\n\n /**\n * Retrieve a cached response.\n * @param url - URL to look up\n * @returns Cached Response or undefined if not found\n */\n match(url: string): Promise<Response | undefined>;\n\n /**\n * Remove a cached response.\n * @param url - URL to remove from cache\n * @returns True if the entry was deleted\n */\n remove(url: string): Promise<boolean>;\n\n /**\n * Get all cached request URLs.\n * @returns Array of cached URLs\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * Internal cache handle implementation.\n */\nclass CacheHandleImpl implements CacheHandle {\n constructor(private readonly cache: Cache) {}\n\n async add(url: string): Promise<void> {\n await this.cache.add(url);\n }\n\n async addAll(urls: string[]): Promise<void> {\n await this.cache.addAll(urls);\n }\n\n async put(url: string, response: Response): Promise<void> {\n await this.cache.put(url, response);\n }\n\n async match(url: string): Promise<Response | undefined> {\n return this.cache.match(url);\n }\n\n async remove(url: string): Promise<boolean> {\n return this.cache.delete(url);\n }\n\n async keys(): Promise<string[]> {\n const requests = await this.cache.keys();\n return requests.map((req) => req.url);\n }\n}\n\n/**\n * Cache manager for accessing the Cache Storage API.\n */\nexport const cache = {\n /**\n * Check if Cache Storage API is supported.\n * @returns True if caches API is available\n */\n isSupported(): boolean {\n return 'caches' in window;\n },\n\n /**\n * Open or create a named cache.\n * @param name - Cache name\n * @returns CacheHandle for cache operations\n */\n async open(name: string): Promise<CacheHandle> {\n if (!this.isSupported()) {\n throw new Error('bQuery: Cache Storage API not supported');\n }\n const c = await caches.open(name);\n return new CacheHandleImpl(c);\n },\n\n /**\n * Delete a named cache.\n * @param name - Cache name to delete\n * @returns True if the cache was deleted\n */\n async delete(name: string): Promise<boolean> {\n if (!this.isSupported()) {\n return false;\n }\n return caches.delete(name);\n },\n\n /**\n * List all cache names.\n * @returns Array of cache names\n */\n async keys(): Promise<string[]> {\n if (!this.isSupported()) {\n return [];\n }\n return caches.keys();\n },\n};\n","/**\n * Reactive cookie helpers.\n *\n * @module bquery/platform\n */\n\nimport { effect, signal, type Signal } from '../reactive/signal';\nimport { getBqueryConfig } from './config';\n\n/** Options for useCookie(). */\nexport interface UseCookieOptions<T> {\n /** Default value when the cookie is not present. */\n defaultValue?: T;\n /** Cookie path. Defaults to the global config or `/`. */\n path?: string;\n /** Optional cookie domain. */\n domain?: string;\n /** Cookie SameSite attribute. */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /** Whether the cookie should be marked secure. */\n secure?: boolean;\n /** Cookie expiry date. */\n expires?: Date;\n /** Cookie max-age in seconds. */\n maxAge?: number;\n /** Automatically persist signal updates back to document.cookie. */\n watch?: boolean;\n /** Serialize a value before writing it into the cookie. */\n serialize?: (value: T) => string;\n /** Deserialize a cookie string into a typed value. */\n deserialize?: (value: string) => T;\n}\n\nconst readCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null;\n\n const prefix = `${encodeURIComponent(name)}=`;\n const segments = document.cookie ? document.cookie.split(';') : [];\n\n for (const segment of segments) {\n const normalizedSegment = segment.trim();\n if (normalizedSegment.startsWith(prefix)) {\n const rawValue = normalizedSegment.slice(prefix.length);\n try {\n return decodeURIComponent(rawValue);\n } catch {\n return rawValue;\n }\n }\n }\n\n return null;\n};\n\nconst requiresJsonParsing = (value: string): boolean => {\n const normalized = value.trim();\n return normalized.startsWith('{') || normalized.startsWith('[') || normalized.startsWith('\"');\n};\n\nconst removeCookie = (\n name: string,\n options: Pick<UseCookieOptions<unknown>, 'path' | 'domain' | 'sameSite' | 'secure'>\n): void => {\n if (typeof document === 'undefined') return;\n\n const segments = [`${encodeURIComponent(name)}=`, 'Expires=Thu, 01 Jan 1970 00:00:00 GMT'];\n\n if (options.path) segments.push(`Path=${options.path}`);\n if (options.domain) segments.push(`Domain=${options.domain}`);\n if (options.sameSite) segments.push(`SameSite=${options.sameSite}`);\n if (options.secure) segments.push('Secure');\n\n document.cookie = segments.join('; ');\n};\n\nconst writeCookie = <T>(name: string, value: T, options: UseCookieOptions<T>): void => {\n if (typeof document === 'undefined') return;\n\n const serialized = options.serialize\n ? options.serialize(value)\n : typeof value === 'string'\n ? value\n : JSON.stringify(value);\n\n const segments = [`${encodeURIComponent(name)}=${encodeURIComponent(serialized)}`];\n\n if (options.path) segments.push(`Path=${options.path}`);\n if (options.domain) segments.push(`Domain=${options.domain}`);\n if (typeof options.maxAge === 'number') segments.push(`Max-Age=${options.maxAge}`);\n if (options.expires) segments.push(`Expires=${options.expires.toUTCString()}`);\n if (options.sameSite) segments.push(`SameSite=${options.sameSite}`);\n if (options.secure) segments.push('Secure');\n\n document.cookie = segments.join('; ');\n};\n\n/**\n * Create a reactive cookie signal.\n *\n * @template T - Cookie value type\n * @param name - Cookie name\n * @param options - Read/write configuration for the cookie\n * @returns Reactive signal representing the cookie value\n *\n * @example\n * ```ts\n * const theme = useCookie('theme', { defaultValue: 'light' });\n * theme.value = 'dark';\n * ```\n */\nexport const useCookie = <T>(name: string, options: UseCookieOptions<T> = {}): Signal<T | null> => {\n const cookieConfig = getBqueryConfig().cookies;\n const resolvedOptions: UseCookieOptions<T> = {\n path: cookieConfig?.path ?? '/',\n sameSite: cookieConfig?.sameSite ?? 'Lax',\n secure: cookieConfig?.secure ?? false,\n watch: true,\n ...options,\n };\n\n if (resolvedOptions.sameSite === 'None') {\n resolvedOptions.secure = true;\n }\n\n const raw = readCookie(name);\n let initialValue = (resolvedOptions.defaultValue ?? null) as T | null;\n\n if (raw !== null) {\n try {\n initialValue = resolvedOptions.deserialize\n ? resolvedOptions.deserialize(raw)\n : requiresJsonParsing(raw)\n ? (JSON.parse(raw) as T)\n : ((raw as T) ?? initialValue);\n } catch (error) {\n console.warn(`bQuery: Failed to deserialize cookie \"${name}\", using raw string value`, error);\n initialValue = (raw as T) ?? initialValue;\n }\n }\n\n const cookie = signal<T | null>(initialValue);\n\n if (typeof document === 'undefined' || resolvedOptions.watch === false) {\n return cookie;\n }\n\n let initialized = false;\n effect(() => {\n const nextValue = cookie.value;\n\n if (!initialized) {\n initialized = true;\n return;\n }\n\n if (nextValue == null) {\n removeCookie(name, resolvedOptions);\n return;\n }\n\n writeCookie(name, nextValue, resolvedOptions);\n });\n\n return cookie;\n};\n","/**\n * Web Notifications API wrapper.\n * Provides a simplified interface for browser notifications.\n */\n\n/**\n * Notification options matching the standard NotificationOptions interface.\n */\nexport interface NotificationOptions {\n /** Body text of the notification */\n body?: string;\n /** Icon URL for the notification */\n icon?: string;\n /** Badge icon for mobile devices */\n badge?: string;\n /** Tag for grouping notifications */\n tag?: string;\n /** Whether to require user interaction */\n requireInteraction?: boolean;\n /** Vibration pattern for mobile devices */\n vibrate?: number[];\n /** Additional data attached to the notification */\n data?: unknown;\n}\n\n/**\n * Notifications manager providing a clean interface for web notifications.\n */\nexport const notifications = {\n /**\n * Check if notifications are supported.\n * @returns True if Notification API is available\n */\n isSupported(): boolean {\n return 'Notification' in window;\n },\n\n /**\n * Get current permission status.\n * @returns Current permission state\n */\n getPermission(): NotificationPermission {\n if (!this.isSupported()) return 'denied';\n return Notification.permission;\n },\n\n /**\n * Request notification permission from the user.\n * @returns Promise resolving to the permission result\n */\n async requestPermission(): Promise<NotificationPermission> {\n if (!this.isSupported()) {\n return 'denied';\n }\n\n if (Notification.permission === 'granted') {\n return 'granted';\n }\n\n if (Notification.permission === 'denied') {\n return 'denied';\n }\n\n return Notification.requestPermission();\n },\n\n /**\n * Send a notification.\n * Requires 'granted' permission.\n * @param title - Notification title\n * @param options - Optional notification settings\n * @returns The Notification instance or null if not permitted\n */\n send(title: string, options?: NotificationOptions): Notification | null {\n if (!this.isSupported()) {\n console.warn('bQuery: Notifications not supported in this browser');\n return null;\n }\n\n if (Notification.permission !== 'granted') {\n console.warn('bQuery: Notification permission not granted');\n return null;\n }\n\n return new Notification(title, options);\n },\n};\n","/**\n * Accessibility live-region announcer helpers.\n *\n * @module bquery/platform\n */\n\nimport { effect, signal, type Signal } from '../reactive/signal';\nimport { getBqueryConfig } from './config';\n\n/** Options for creating an announcer. */\nexport interface UseAnnouncerOptions {\n /** Live region politeness. */\n politeness?: 'polite' | 'assertive';\n /** Whether the live region should be atomic. */\n atomic?: boolean;\n /** Delay before applying the message. */\n delay?: number;\n /** Delay after which the message is cleared automatically. */\n clearDelay?: number;\n /** Optional element id for the live region. */\n id?: string;\n /** Optional CSS class name. */\n className?: string;\n /** Optional container used to append the live region. */\n container?: HTMLElement;\n}\n\n/** Runtime options for a single announcement. */\nexport interface AnnounceOptions {\n /** Override politeness for this specific announcement. */\n politeness?: 'polite' | 'assertive';\n /** Override the message delay for this specific announcement. */\n delay?: number;\n /** Override the auto-clear delay for this specific announcement. */\n clearDelay?: number;\n}\n\n/** Returned announcer API. */\nexport interface AnnouncerHandle {\n /** The live region element or null outside the DOM. */\n element: HTMLElement | null;\n /** Reactive message signal. */\n message: Signal<string>;\n /** Announce a message to assistive technologies. */\n announce: (value: string, options?: AnnounceOptions) => void;\n /** Clear the current announcement. */\n clear: () => void;\n /** Remove the live region if it was created by this announcer. */\n destroy: () => void;\n}\n\nconst visuallyHiddenStyle = [\n 'position:absolute',\n 'width:1px',\n 'height:1px',\n 'padding:0',\n 'margin:-1px',\n 'overflow:hidden',\n 'clip:rect(0, 0, 0, 0)',\n 'white-space:nowrap',\n 'border:0',\n].join(';');\n\n/**\n * Create or reuse an accessible live region.\n *\n * @param options - Live region configuration\n * @returns An announcer handle with announce(), clear(), and destroy()\n *\n * @example\n * ```ts\n * const announcer = useAnnouncer();\n * announcer.announce('Saved successfully');\n * ```\n */\nexport const useAnnouncer = (options: UseAnnouncerOptions = {}): AnnouncerHandle => {\n const defaults = getBqueryConfig().announcer;\n const resolvedOptions: Required<\n Pick<UseAnnouncerOptions, 'politeness' | 'atomic' | 'delay' | 'clearDelay'>\n > &\n UseAnnouncerOptions = {\n politeness: defaults?.politeness ?? 'polite',\n atomic: defaults?.atomic ?? true,\n delay: defaults?.delay ?? 16,\n clearDelay: defaults?.clearDelay ?? 1000,\n ...options,\n };\n\n const message = signal('');\n\n if (typeof document === 'undefined') {\n return {\n element: null,\n message,\n announce(value: string) {\n message.value = value;\n },\n clear() {\n message.value = '';\n },\n destroy() {\n message.value = '';\n },\n };\n }\n\n const existing = resolvedOptions.id ? document.getElementById(resolvedOptions.id) : null;\n const element = (existing ?? document.createElement('div')) as HTMLElement;\n const created = !existing;\n\n if (resolvedOptions.id) {\n element.id = resolvedOptions.id;\n }\n\n if (resolvedOptions.className) {\n element.className = resolvedOptions.className;\n }\n\n element.setAttribute('aria-live', resolvedOptions.politeness);\n element.setAttribute('aria-atomic', String(resolvedOptions.atomic));\n element.setAttribute('role', resolvedOptions.politeness === 'assertive' ? 'alert' : 'status');\n element.setAttribute('data-bquery-announcer', 'true');\n if (!element.getAttribute('style')) {\n element.setAttribute('style', visuallyHiddenStyle);\n }\n\n if (created) {\n const parent = resolvedOptions.container ?? document.body ?? document.documentElement;\n if (!parent) {\n return {\n element: null,\n message,\n announce(value: string) {\n message.value = value;\n },\n clear() {\n message.value = '';\n },\n destroy() {\n message.value = '';\n },\n };\n }\n parent.appendChild(element);\n }\n\n const disposeMessageEffect = effect(() => {\n element.textContent = message.value;\n });\n\n let messageTimer: ReturnType<typeof setTimeout> | undefined;\n let clearTimer: ReturnType<typeof setTimeout> | undefined;\n let destroyed = false;\n\n const clearTimers = (): void => {\n if (messageTimer) {\n clearTimeout(messageTimer);\n messageTimer = undefined;\n }\n if (clearTimer) {\n clearTimeout(clearTimer);\n clearTimer = undefined;\n }\n };\n\n const clear = (): void => {\n if (destroyed) return;\n clearTimers();\n message.value = '';\n };\n\n const announce = (value: string, announceOptions: AnnounceOptions = {}): void => {\n if (destroyed) return;\n const politeness = announceOptions.politeness ?? resolvedOptions.politeness;\n const delay = announceOptions.delay ?? resolvedOptions.delay;\n const clearDelay = announceOptions.clearDelay ?? resolvedOptions.clearDelay;\n\n clearTimers();\n\n element.setAttribute('aria-live', politeness);\n element.setAttribute('role', politeness === 'assertive' ? 'alert' : 'status');\n message.value = '';\n\n messageTimer = setTimeout(() => {\n if (destroyed) return;\n message.value = value;\n if (clearDelay > 0) {\n clearTimer = setTimeout(() => {\n if (destroyed) return;\n message.value = '';\n }, clearDelay);\n }\n }, delay);\n };\n\n const destroy = (): void => {\n if (destroyed) return;\n destroyed = true;\n clearTimers();\n message.value = '';\n disposeMessageEffect();\n if (created) {\n element.remove();\n }\n };\n\n return { element, message, announce, clear, destroy };\n};\n","/**\n * Document title and meta helpers.\n *\n * @module bquery/platform\n */\n\nimport { getBqueryConfig } from './config';\n\n/** Meta tag definition. */\nexport interface PageMetaTag {\n /** Standard meta name attribute. */\n name?: string;\n /** Open Graph / custom property attribute. */\n property?: string;\n /** http-equiv attribute. */\n httpEquiv?: string;\n /** Meta tag content. */\n content: string;\n}\n\n/** Link tag definition. */\nexport interface PageLinkTag {\n /** Link relation. */\n rel: string;\n /** Link URL. */\n href: string;\n /** Optional type attribute. */\n type?: string;\n /** Optional media query. */\n media?: string;\n /** Optional crossOrigin attribute. */\n crossOrigin?: 'anonymous' | 'use-credentials';\n}\n\n/** Page metadata definition. */\nexport interface PageMetaDefinition {\n /** Document title. */\n title?: string;\n /** Convenience shortcut for the description meta tag. */\n description?: string;\n /** Additional meta tags. */\n meta?: PageMetaTag[];\n /** Additional link tags. */\n link?: PageLinkTag[];\n /** Attributes applied to the html element. */\n htmlAttributes?: Record<string, string>;\n /** Attributes applied to the body element. */\n bodyAttributes?: Record<string, string>;\n}\n\n/** Cleanup function returned by definePageMeta(). */\nexport type PageMetaCleanup = () => void;\n\nconst setAttributes = (target: HTMLElement, attributes: Record<string, string>): (() => void) => {\n const previousValues = new Map<string, string | null>();\n\n for (const [name, value] of Object.entries(attributes)) {\n previousValues.set(name, target.getAttribute(name));\n target.setAttribute(name, value);\n }\n\n return () => {\n for (const [name, value] of previousValues.entries()) {\n if (value == null) {\n target.removeAttribute(name);\n } else {\n target.setAttribute(name, value);\n }\n }\n };\n};\n\nconst createElement = <T extends 'meta' | 'link'>(\n tagName: T,\n attributes: Record<string, string | undefined>\n): HTMLElementTagNameMap[T] => {\n const element = document.createElement(tagName);\n element.setAttribute('data-bquery-page-meta', 'true');\n\n for (const [name, value] of Object.entries(attributes)) {\n if (value !== undefined) {\n element.setAttribute(name, value);\n }\n }\n\n return element;\n};\n\n/**\n * Apply document metadata for the current page.\n *\n * @param definition - Title, meta tags, link tags, and document attributes\n * @returns Cleanup function that restores the previous document state\n *\n * @example\n * ```ts\n * const cleanup = definePageMeta({\n * title: 'Dashboard',\n * description: 'Overview of your account',\n * });\n * ```\n */\nexport const definePageMeta = (definition: PageMetaDefinition): PageMetaCleanup => {\n if (typeof document === 'undefined') {\n return () => {};\n }\n\n const config = getBqueryConfig().pageMeta;\n const title = definition.title\n ? config?.titleTemplate\n ? config.titleTemplate(definition.title)\n : definition.title\n : undefined;\n\n const inserted: HTMLElement[] = [];\n const restoreFns: Array<() => void> = [];\n const previousTitle = document.title;\n\n if (title !== undefined) {\n document.title = title;\n }\n\n const metaEntries = [...(definition.meta ?? [])];\n if (definition.description) {\n metaEntries.unshift({ name: 'description', content: definition.description });\n }\n\n for (const entry of metaEntries) {\n const meta = createElement('meta', {\n name: entry.name,\n property: entry.property,\n 'http-equiv': entry.httpEquiv,\n content: entry.content,\n });\n document.head.appendChild(meta);\n inserted.push(meta);\n }\n\n for (const entry of definition.link ?? []) {\n const link = createElement('link', {\n rel: entry.rel,\n href: entry.href,\n type: entry.type,\n media: entry.media,\n crossorigin: entry.crossOrigin,\n });\n document.head.appendChild(link);\n inserted.push(link);\n }\n\n if (definition.htmlAttributes) {\n restoreFns.push(setAttributes(document.documentElement, definition.htmlAttributes));\n }\n\n if (definition.bodyAttributes && document.body) {\n restoreFns.push(setAttributes(document.body, definition.bodyAttributes));\n }\n\n return () => {\n document.title = previousTitle;\n for (const restore of restoreFns.reverse()) {\n restore();\n }\n for (const element of inserted) {\n element.remove();\n }\n };\n};\n","/**\n * Unified storage adapters for web platform storage APIs.\n * Provides a consistent, promise-based interface with predictable errors.\n */\n\n/**\n * Common interface for all storage adapters.\n * All methods return promises for a unified async API.\n */\nexport interface StorageAdapter {\n /**\n * Retrieve a value by key.\n * @param key - The storage key\n * @returns The stored value or null if not found\n */\n get<T>(key: string): Promise<T | null>;\n\n /**\n * Store a value by key.\n * @param key - The storage key\n * @param value - The value to store\n */\n set<T>(key: string, value: T): Promise<void>;\n\n /**\n * Remove a value by key.\n * @param key - The storage key\n */\n remove(key: string): Promise<void>;\n\n /**\n * Clear all stored values.\n */\n clear(): Promise<void>;\n\n /**\n * Get all storage keys.\n * @returns Array of all keys\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * Abstract base class for web storage adapters (localStorage/sessionStorage).\n * Implements DRY principle by sharing common logic.\n */\nabstract class WebStorageAdapter implements StorageAdapter {\n constructor(protected readonly storage: Storage) {}\n\n async get<T>(key: string): Promise<T | null> {\n const raw = this.storage.getItem(key);\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n const serialized = typeof value === 'string' ? value : JSON.stringify(value);\n this.storage.setItem(key, serialized);\n }\n\n async remove(key: string): Promise<void> {\n this.storage.removeItem(key);\n }\n\n async clear(): Promise<void> {\n this.storage.clear();\n }\n\n async keys(): Promise<string[]> {\n const result: string[] = [];\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key !== null) {\n result.push(key);\n }\n }\n return result;\n }\n}\n\n/**\n * localStorage adapter with async interface.\n */\nclass LocalStorageAdapter extends WebStorageAdapter {\n constructor() {\n super(localStorage);\n }\n}\n\n/**\n * sessionStorage adapter with async interface.\n */\nclass SessionStorageAdapter extends WebStorageAdapter {\n constructor() {\n super(sessionStorage);\n }\n}\n\n/**\n * IndexedDB configuration options.\n */\nexport interface IndexedDBOptions {\n /** Database name */\n name: string;\n /** Object store name */\n store: string;\n /** Database version (optional) */\n version?: number;\n}\n\n/**\n * IndexedDB key-value adapter.\n * Wraps IndexedDB with a simple key-value interface.\n */\nclass IndexedDBAdapter implements StorageAdapter {\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(private readonly options: IndexedDBOptions) {}\n\n /**\n * Opens or creates the IndexedDB database.\n */\n private openDB(): Promise<IDBDatabase> {\n if (this.dbPromise) return this.dbPromise;\n\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(this.options.name, this.options.version ?? 1);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.options.store)) {\n db.createObjectStore(this.options.store);\n }\n };\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n\n return this.dbPromise;\n }\n\n /**\n * Executes a transaction on the object store.\n */\n private async withStore<T>(\n mode: IDBTransactionMode,\n operation: (store: IDBObjectStore) => IDBRequest<T>\n ): Promise<T> {\n const db = await this.openDB();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.options.store, mode);\n const store = tx.objectStore(this.options.store);\n const request = operation(store);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async get<T>(key: string): Promise<T | null> {\n const result = await this.withStore<T | undefined>('readonly', (store) => store.get(key));\n return result ?? null;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n await this.withStore('readwrite', (store) => store.put(value, key));\n }\n\n async remove(key: string): Promise<void> {\n await this.withStore('readwrite', (store) => store.delete(key));\n }\n\n async clear(): Promise<void> {\n await this.withStore('readwrite', (store) => store.clear());\n }\n\n async keys(): Promise<string[]> {\n const result = await this.withStore<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return result.map((key) => String(key));\n }\n}\n\n/**\n * Storage factory providing access to different storage adapters.\n */\nexport const storage = {\n /**\n * Create a localStorage adapter.\n * @returns StorageAdapter wrapping localStorage\n */\n local(): StorageAdapter {\n return new LocalStorageAdapter();\n },\n\n /**\n * Create a sessionStorage adapter.\n * @returns StorageAdapter wrapping sessionStorage\n */\n session(): StorageAdapter {\n return new SessionStorageAdapter();\n },\n\n /**\n * Create an IndexedDB adapter with key-value interface.\n * @param options - Database and store configuration\n * @returns StorageAdapter wrapping IndexedDB\n */\n indexedDB(options: IndexedDBOptions): StorageAdapter {\n return new IndexedDBAdapter(options);\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"platform-CPbCprb6.js","names":[],"sources":["../src/platform/buckets.ts","../src/platform/cache.ts","../src/platform/cookies.ts","../src/platform/notifications.ts","../src/platform/announcer.ts","../src/platform/meta.ts","../src/platform/storage.ts"],"sourcesContent":["/**\n * Storage Buckets API wrapper.\n * Provides a simplified interface for storing blobs and binary data.\n * Falls back to IndexedDB when Storage Buckets API is not available.\n */\n\n/**\n * Bucket interface for blob storage operations.\n */\nexport interface Bucket {\n /**\n * Store a blob in the bucket.\n * @param key - Unique identifier for the blob\n * @param data - Blob data to store\n */\n put(key: string, data: Blob): Promise<void>;\n\n /**\n * Retrieve a blob from the bucket.\n * @param key - Blob identifier\n * @returns The stored blob or null if not found\n */\n get(key: string): Promise<Blob | null>;\n\n /**\n * Remove a blob from the bucket.\n * @param key - Blob identifier\n */\n remove(key: string): Promise<void>;\n\n /**\n * List all keys in the bucket.\n * @returns Array of blob keys\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * IndexedDB-based bucket implementation.\n * Used as fallback when Storage Buckets API is unavailable.\n */\nclass IndexedDBBucket implements Bucket {\n private dbPromise: Promise<IDBDatabase> | null = null;\n private readonly storeName = 'blobs';\n\n constructor(private readonly bucketName: string) {}\n\n private openDB(): Promise<IDBDatabase> {\n if (this.dbPromise) return this.dbPromise;\n\n const dbName = `bquery-bucket-${this.bucketName}`;\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n\n return this.dbPromise;\n }\n\n private async withStore<T>(\n mode: IDBTransactionMode,\n operation: (store: IDBObjectStore) => IDBRequest<T>\n ): Promise<T> {\n const db = await this.openDB();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.storeName, mode);\n const store = tx.objectStore(this.storeName);\n const request = operation(store);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async put(key: string, data: Blob): Promise<void> {\n await this.withStore('readwrite', (store) => store.put(data, key));\n }\n\n async get(key: string): Promise<Blob | null> {\n const result = await this.withStore<Blob | undefined>('readonly', (store) => store.get(key));\n return result ?? null;\n }\n\n async remove(key: string): Promise<void> {\n await this.withStore('readwrite', (store) => store.delete(key));\n }\n\n async keys(): Promise<string[]> {\n const result = await this.withStore<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return result.map((key) => String(key));\n }\n}\n\n/**\n * Bucket manager for creating and accessing storage buckets.\n */\nexport const buckets = {\n /**\n * Open or create a storage bucket.\n * @param name - Bucket name\n * @returns Bucket instance for blob operations\n */\n async open(name: string): Promise<Bucket> {\n // Storage Buckets API is experimental; use IndexedDB fallback\n return new IndexedDBBucket(name);\n },\n};\n","/**\n * Cache Storage API wrapper.\n * Provides a simplified interface for caching responses and assets.\n */\n\n/**\n * Cache handle interface for managing cached resources.\n */\nexport interface CacheHandle {\n /**\n * Add a resource to the cache by URL.\n * Fetches the resource and stores the response.\n * @param url - URL to fetch and cache\n */\n add(url: string): Promise<void>;\n\n /**\n * Add multiple resources to the cache.\n * @param urls - Array of URLs to fetch and cache\n */\n addAll(urls: string[]): Promise<void>;\n\n /**\n * Store a custom response in the cache.\n * @param url - URL key for the cached response\n * @param response - Response object to cache\n */\n put(url: string, response: Response): Promise<void>;\n\n /**\n * Retrieve a cached response.\n * @param url - URL to look up\n * @returns Cached Response or undefined if not found\n */\n match(url: string): Promise<Response | undefined>;\n\n /**\n * Remove a cached response.\n * @param url - URL to remove from cache\n * @returns True if the entry was deleted\n */\n remove(url: string): Promise<boolean>;\n\n /**\n * Get all cached request URLs.\n * @returns Array of cached URLs\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * Internal cache handle implementation.\n */\nclass CacheHandleImpl implements CacheHandle {\n constructor(private readonly cache: Cache) {}\n\n async add(url: string): Promise<void> {\n await this.cache.add(url);\n }\n\n async addAll(urls: string[]): Promise<void> {\n await this.cache.addAll(urls);\n }\n\n async put(url: string, response: Response): Promise<void> {\n await this.cache.put(url, response);\n }\n\n async match(url: string): Promise<Response | undefined> {\n return this.cache.match(url);\n }\n\n async remove(url: string): Promise<boolean> {\n return this.cache.delete(url);\n }\n\n async keys(): Promise<string[]> {\n const requests = await this.cache.keys();\n return requests.map((req) => req.url);\n }\n}\n\n/**\n * Cache manager for accessing the Cache Storage API.\n */\nexport const cache = {\n /**\n * Check if Cache Storage API is supported.\n * @returns True if caches API is available\n */\n isSupported(): boolean {\n return 'caches' in window;\n },\n\n /**\n * Open or create a named cache.\n * @param name - Cache name\n * @returns CacheHandle for cache operations\n */\n async open(name: string): Promise<CacheHandle> {\n if (!this.isSupported()) {\n throw new Error('bQuery: Cache Storage API not supported');\n }\n const c = await caches.open(name);\n return new CacheHandleImpl(c);\n },\n\n /**\n * Delete a named cache.\n * @param name - Cache name to delete\n * @returns True if the cache was deleted\n */\n async delete(name: string): Promise<boolean> {\n if (!this.isSupported()) {\n return false;\n }\n return caches.delete(name);\n },\n\n /**\n * List all cache names.\n * @returns Array of cache names\n */\n async keys(): Promise<string[]> {\n if (!this.isSupported()) {\n return [];\n }\n return caches.keys();\n },\n};\n","/**\n * Reactive cookie helpers.\n *\n * @module bquery/platform\n */\n\nimport { effect, signal, type Signal } from '../reactive/signal';\nimport { getBqueryConfig } from './config';\n\n/** Options for useCookie(). */\nexport interface UseCookieOptions<T> {\n /** Default value when the cookie is not present. */\n defaultValue?: T;\n /** Cookie path. Defaults to the global config or `/`. */\n path?: string;\n /** Optional cookie domain. */\n domain?: string;\n /** Cookie SameSite attribute. */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /** Whether the cookie should be marked secure. */\n secure?: boolean;\n /** Cookie expiry date. */\n expires?: Date;\n /** Cookie max-age in seconds. */\n maxAge?: number;\n /** Automatically persist signal updates back to document.cookie. */\n watch?: boolean;\n /** Serialize a value before writing it into the cookie. */\n serialize?: (value: T) => string;\n /** Deserialize a cookie string into a typed value. */\n deserialize?: (value: string) => T;\n}\n\nconst readCookie = (name: string): string | null => {\n if (typeof document === 'undefined') return null;\n\n const prefix = `${encodeURIComponent(name)}=`;\n const segments = document.cookie ? document.cookie.split(';') : [];\n\n for (const segment of segments) {\n const normalizedSegment = segment.trim();\n if (normalizedSegment.startsWith(prefix)) {\n const rawValue = normalizedSegment.slice(prefix.length);\n try {\n return decodeURIComponent(rawValue);\n } catch {\n return rawValue;\n }\n }\n }\n\n return null;\n};\n\nconst requiresJsonParsing = (value: string): boolean => {\n const normalized = value.trim();\n return normalized.startsWith('{') || normalized.startsWith('[') || normalized.startsWith('\"');\n};\n\nconst removeCookie = (\n name: string,\n options: Pick<UseCookieOptions<unknown>, 'path' | 'domain' | 'sameSite' | 'secure'>\n): void => {\n if (typeof document === 'undefined') return;\n\n const segments = [`${encodeURIComponent(name)}=`, 'Expires=Thu, 01 Jan 1970 00:00:00 GMT'];\n\n if (options.path) segments.push(`Path=${options.path}`);\n if (options.domain) segments.push(`Domain=${options.domain}`);\n if (options.sameSite) segments.push(`SameSite=${options.sameSite}`);\n if (options.secure) segments.push('Secure');\n\n document.cookie = segments.join('; ');\n};\n\nconst writeCookie = <T>(name: string, value: T, options: UseCookieOptions<T>): void => {\n if (typeof document === 'undefined') return;\n\n const serialized = options.serialize\n ? options.serialize(value)\n : typeof value === 'string'\n ? value\n : JSON.stringify(value);\n\n const segments = [`${encodeURIComponent(name)}=${encodeURIComponent(serialized)}`];\n\n if (options.path) segments.push(`Path=${options.path}`);\n if (options.domain) segments.push(`Domain=${options.domain}`);\n if (typeof options.maxAge === 'number') segments.push(`Max-Age=${options.maxAge}`);\n if (options.expires) segments.push(`Expires=${options.expires.toUTCString()}`);\n if (options.sameSite) segments.push(`SameSite=${options.sameSite}`);\n if (options.secure) segments.push('Secure');\n\n document.cookie = segments.join('; ');\n};\n\n/**\n * Create a reactive cookie signal.\n *\n * @template T - Cookie value type\n * @param name - Cookie name\n * @param options - Read/write configuration for the cookie\n * @returns Reactive signal representing the cookie value\n *\n * @example\n * ```ts\n * const theme = useCookie('theme', { defaultValue: 'light' });\n * theme.value = 'dark';\n * ```\n */\nexport const useCookie = <T>(name: string, options: UseCookieOptions<T> = {}): Signal<T | null> => {\n const cookieConfig = getBqueryConfig().cookies;\n const resolvedOptions: UseCookieOptions<T> = {\n path: cookieConfig?.path ?? '/',\n sameSite: cookieConfig?.sameSite ?? 'Lax',\n secure: cookieConfig?.secure ?? false,\n watch: true,\n ...options,\n };\n\n if (resolvedOptions.sameSite === 'None') {\n resolvedOptions.secure = true;\n }\n\n const raw = readCookie(name);\n let initialValue = (resolvedOptions.defaultValue ?? null) as T | null;\n\n if (raw !== null) {\n try {\n initialValue = resolvedOptions.deserialize\n ? resolvedOptions.deserialize(raw)\n : requiresJsonParsing(raw)\n ? (JSON.parse(raw) as T)\n : ((raw as T) ?? initialValue);\n } catch (error) {\n console.warn(`bQuery: Failed to deserialize cookie \"${name}\", using raw string value`, error);\n initialValue = (raw as T) ?? initialValue;\n }\n }\n\n const cookie = signal<T | null>(initialValue);\n\n if (typeof document === 'undefined' || resolvedOptions.watch === false) {\n return cookie;\n }\n\n let initialized = false;\n effect(() => {\n const nextValue = cookie.value;\n\n if (!initialized) {\n initialized = true;\n return;\n }\n\n if (nextValue == null) {\n removeCookie(name, resolvedOptions);\n return;\n }\n\n writeCookie(name, nextValue, resolvedOptions);\n });\n\n return cookie;\n};\n","/**\n * Web Notifications API wrapper.\n * Provides a simplified interface for browser notifications.\n */\n\n/**\n * Notification options matching the standard NotificationOptions interface.\n */\nexport interface NotificationOptions {\n /** Body text of the notification */\n body?: string;\n /** Icon URL for the notification */\n icon?: string;\n /** Badge icon for mobile devices */\n badge?: string;\n /** Tag for grouping notifications */\n tag?: string;\n /** Whether to require user interaction */\n requireInteraction?: boolean;\n /** Vibration pattern for mobile devices */\n vibrate?: number[];\n /** Additional data attached to the notification */\n data?: unknown;\n}\n\n/**\n * Notifications manager providing a clean interface for web notifications.\n */\nexport const notifications = {\n /**\n * Check if notifications are supported.\n * @returns True if Notification API is available\n */\n isSupported(): boolean {\n return 'Notification' in window;\n },\n\n /**\n * Get current permission status.\n * @returns Current permission state\n */\n getPermission(): NotificationPermission {\n if (!this.isSupported()) return 'denied';\n return Notification.permission;\n },\n\n /**\n * Request notification permission from the user.\n * @returns Promise resolving to the permission result\n */\n async requestPermission(): Promise<NotificationPermission> {\n if (!this.isSupported()) {\n return 'denied';\n }\n\n if (Notification.permission === 'granted') {\n return 'granted';\n }\n\n if (Notification.permission === 'denied') {\n return 'denied';\n }\n\n return Notification.requestPermission();\n },\n\n /**\n * Send a notification.\n * Requires 'granted' permission.\n * @param title - Notification title\n * @param options - Optional notification settings\n * @returns The Notification instance or null if not permitted\n */\n send(title: string, options?: NotificationOptions): Notification | null {\n if (!this.isSupported()) {\n console.warn('bQuery: Notifications not supported in this browser');\n return null;\n }\n\n if (Notification.permission !== 'granted') {\n console.warn('bQuery: Notification permission not granted');\n return null;\n }\n\n return new Notification(title, options);\n },\n};\n","/**\n * Accessibility live-region announcer helpers.\n *\n * @module bquery/platform\n */\n\nimport { effect, signal, type Signal } from '../reactive/signal';\nimport { getBqueryConfig } from './config';\n\n/** Options for creating an announcer. */\nexport interface UseAnnouncerOptions {\n /** Live region politeness. */\n politeness?: 'polite' | 'assertive';\n /** Whether the live region should be atomic. */\n atomic?: boolean;\n /** Delay before applying the message. */\n delay?: number;\n /** Delay after which the message is cleared automatically. */\n clearDelay?: number;\n /** Optional element id for the live region. */\n id?: string;\n /** Optional CSS class name. */\n className?: string;\n /** Optional container used to append the live region. */\n container?: HTMLElement;\n}\n\n/** Runtime options for a single announcement. */\nexport interface AnnounceOptions {\n /** Override politeness for this specific announcement. */\n politeness?: 'polite' | 'assertive';\n /** Override the message delay for this specific announcement. */\n delay?: number;\n /** Override the auto-clear delay for this specific announcement. */\n clearDelay?: number;\n}\n\n/** Returned announcer API. */\nexport interface AnnouncerHandle {\n /** The live region element or null outside the DOM. */\n element: HTMLElement | null;\n /** Reactive message signal. */\n message: Signal<string>;\n /** Announce a message to assistive technologies. */\n announce: (value: string, options?: AnnounceOptions) => void;\n /** Clear the current announcement. */\n clear: () => void;\n /** Remove the live region if it was created by this announcer. */\n destroy: () => void;\n}\n\nconst visuallyHiddenStyle = [\n 'position:absolute',\n 'width:1px',\n 'height:1px',\n 'padding:0',\n 'margin:-1px',\n 'overflow:hidden',\n 'clip:rect(0, 0, 0, 0)',\n 'white-space:nowrap',\n 'border:0',\n].join(';');\n\n/**\n * Create or reuse an accessible live region.\n *\n * @param options - Live region configuration\n * @returns An announcer handle with announce(), clear(), and destroy()\n *\n * @example\n * ```ts\n * const announcer = useAnnouncer();\n * announcer.announce('Saved successfully');\n * ```\n */\nexport const useAnnouncer = (options: UseAnnouncerOptions = {}): AnnouncerHandle => {\n const defaults = getBqueryConfig().announcer;\n const resolvedOptions: Required<\n Pick<UseAnnouncerOptions, 'politeness' | 'atomic' | 'delay' | 'clearDelay'>\n > &\n UseAnnouncerOptions = {\n politeness: defaults?.politeness ?? 'polite',\n atomic: defaults?.atomic ?? true,\n delay: defaults?.delay ?? 16,\n clearDelay: defaults?.clearDelay ?? 1000,\n ...options,\n };\n\n const message = signal('');\n\n if (typeof document === 'undefined') {\n return {\n element: null,\n message,\n announce(value: string) {\n message.value = value;\n },\n clear() {\n message.value = '';\n },\n destroy() {\n message.value = '';\n },\n };\n }\n\n const existing = resolvedOptions.id ? document.getElementById(resolvedOptions.id) : null;\n const element = (existing ?? document.createElement('div')) as HTMLElement;\n const created = !existing;\n\n if (resolvedOptions.id) {\n element.id = resolvedOptions.id;\n }\n\n if (resolvedOptions.className) {\n element.className = resolvedOptions.className;\n }\n\n element.setAttribute('aria-live', resolvedOptions.politeness);\n element.setAttribute('aria-atomic', String(resolvedOptions.atomic));\n element.setAttribute('role', resolvedOptions.politeness === 'assertive' ? 'alert' : 'status');\n element.setAttribute('data-bquery-announcer', 'true');\n if (!element.getAttribute('style')) {\n element.setAttribute('style', visuallyHiddenStyle);\n }\n\n if (created) {\n const parent = resolvedOptions.container ?? document.body ?? document.documentElement;\n if (!parent) {\n return {\n element: null,\n message,\n announce(value: string) {\n message.value = value;\n },\n clear() {\n message.value = '';\n },\n destroy() {\n message.value = '';\n },\n };\n }\n parent.appendChild(element);\n }\n\n const disposeMessageEffect = effect(() => {\n element.textContent = message.value;\n });\n\n let messageTimer: ReturnType<typeof setTimeout> | undefined;\n let clearTimer: ReturnType<typeof setTimeout> | undefined;\n let destroyed = false;\n\n const clearTimers = (): void => {\n if (messageTimer) {\n clearTimeout(messageTimer);\n messageTimer = undefined;\n }\n if (clearTimer) {\n clearTimeout(clearTimer);\n clearTimer = undefined;\n }\n };\n\n const clear = (): void => {\n if (destroyed) return;\n clearTimers();\n message.value = '';\n };\n\n const announce = (value: string, announceOptions: AnnounceOptions = {}): void => {\n if (destroyed) return;\n const politeness = announceOptions.politeness ?? resolvedOptions.politeness;\n const delay = announceOptions.delay ?? resolvedOptions.delay;\n const clearDelay = announceOptions.clearDelay ?? resolvedOptions.clearDelay;\n\n clearTimers();\n\n element.setAttribute('aria-live', politeness);\n element.setAttribute('role', politeness === 'assertive' ? 'alert' : 'status');\n message.value = '';\n\n messageTimer = setTimeout(() => {\n if (destroyed) return;\n message.value = value;\n if (clearDelay > 0) {\n clearTimer = setTimeout(() => {\n if (destroyed) return;\n message.value = '';\n }, clearDelay);\n }\n }, delay);\n };\n\n const destroy = (): void => {\n if (destroyed) return;\n destroyed = true;\n clearTimers();\n message.value = '';\n disposeMessageEffect();\n if (created) {\n element.remove();\n }\n };\n\n return { element, message, announce, clear, destroy };\n};\n","/**\n * Document title and meta helpers.\n *\n * @module bquery/platform\n */\n\nimport { getBqueryConfig } from './config';\n\n/** Meta tag definition. */\nexport interface PageMetaTag {\n /** Standard meta name attribute. */\n name?: string;\n /** Open Graph / custom property attribute. */\n property?: string;\n /** http-equiv attribute. */\n httpEquiv?: string;\n /** Meta tag content. */\n content: string;\n}\n\n/** Link tag definition. */\nexport interface PageLinkTag {\n /** Link relation. */\n rel: string;\n /** Link URL. */\n href: string;\n /** Optional type attribute. */\n type?: string;\n /** Optional media query. */\n media?: string;\n /** Optional crossOrigin attribute. */\n crossOrigin?: 'anonymous' | 'use-credentials';\n}\n\n/** Page metadata definition. */\nexport interface PageMetaDefinition {\n /** Document title. */\n title?: string;\n /** Convenience shortcut for the description meta tag. */\n description?: string;\n /** Additional meta tags. */\n meta?: PageMetaTag[];\n /** Additional link tags. */\n link?: PageLinkTag[];\n /** Attributes applied to the html element. */\n htmlAttributes?: Record<string, string>;\n /** Attributes applied to the body element. */\n bodyAttributes?: Record<string, string>;\n}\n\n/** Cleanup function returned by definePageMeta(). */\nexport type PageMetaCleanup = () => void;\n\nconst setAttributes = (target: HTMLElement, attributes: Record<string, string>): (() => void) => {\n const previousValues = new Map<string, string | null>();\n\n for (const [name, value] of Object.entries(attributes)) {\n previousValues.set(name, target.getAttribute(name));\n target.setAttribute(name, value);\n }\n\n return () => {\n for (const [name, value] of previousValues.entries()) {\n if (value == null) {\n target.removeAttribute(name);\n } else {\n target.setAttribute(name, value);\n }\n }\n };\n};\n\nconst createElement = <T extends 'meta' | 'link'>(\n tagName: T,\n attributes: Record<string, string | undefined>\n): HTMLElementTagNameMap[T] => {\n const element = document.createElement(tagName);\n element.setAttribute('data-bquery-page-meta', 'true');\n\n for (const [name, value] of Object.entries(attributes)) {\n if (value !== undefined) {\n element.setAttribute(name, value);\n }\n }\n\n return element;\n};\n\n/**\n * Apply document metadata for the current page.\n *\n * @param definition - Title, meta tags, link tags, and document attributes\n * @returns Cleanup function that restores the previous document state\n *\n * @example\n * ```ts\n * const cleanup = definePageMeta({\n * title: 'Dashboard',\n * description: 'Overview of your account',\n * });\n * ```\n */\nexport const definePageMeta = (definition: PageMetaDefinition): PageMetaCleanup => {\n if (typeof document === 'undefined') {\n return () => {};\n }\n\n const config = getBqueryConfig().pageMeta;\n const title = definition.title\n ? config?.titleTemplate\n ? config.titleTemplate(definition.title)\n : definition.title\n : undefined;\n\n const inserted: HTMLElement[] = [];\n const restoreFns: Array<() => void> = [];\n const previousTitle = document.title;\n\n if (title !== undefined) {\n document.title = title;\n }\n\n const metaEntries = [...(definition.meta ?? [])];\n if (definition.description) {\n metaEntries.unshift({ name: 'description', content: definition.description });\n }\n\n for (const entry of metaEntries) {\n const meta = createElement('meta', {\n name: entry.name,\n property: entry.property,\n 'http-equiv': entry.httpEquiv,\n content: entry.content,\n });\n document.head.appendChild(meta);\n inserted.push(meta);\n }\n\n for (const entry of definition.link ?? []) {\n const link = createElement('link', {\n rel: entry.rel,\n href: entry.href,\n type: entry.type,\n media: entry.media,\n crossorigin: entry.crossOrigin,\n });\n document.head.appendChild(link);\n inserted.push(link);\n }\n\n if (definition.htmlAttributes) {\n restoreFns.push(setAttributes(document.documentElement, definition.htmlAttributes));\n }\n\n if (definition.bodyAttributes && document.body) {\n restoreFns.push(setAttributes(document.body, definition.bodyAttributes));\n }\n\n return () => {\n document.title = previousTitle;\n for (const restore of restoreFns.reverse()) {\n restore();\n }\n for (const element of inserted) {\n element.remove();\n }\n };\n};\n","/**\n * Unified storage adapters for web platform storage APIs.\n * Provides a consistent, promise-based interface with predictable errors.\n */\n\n/**\n * Common interface for all storage adapters.\n * All methods return promises for a unified async API.\n */\nexport interface StorageAdapter {\n /**\n * Retrieve a value by key.\n * @param key - The storage key\n * @returns The stored value or null if not found\n */\n get<T>(key: string): Promise<T | null>;\n\n /**\n * Store a value by key.\n * @param key - The storage key\n * @param value - The value to store\n */\n set<T>(key: string, value: T): Promise<void>;\n\n /**\n * Remove a value by key.\n * @param key - The storage key\n */\n remove(key: string): Promise<void>;\n\n /**\n * Clear all stored values.\n */\n clear(): Promise<void>;\n\n /**\n * Get all storage keys.\n * @returns Array of all keys\n */\n keys(): Promise<string[]>;\n}\n\n/**\n * Abstract base class for web storage adapters (localStorage/sessionStorage).\n * Implements DRY principle by sharing common logic.\n */\nabstract class WebStorageAdapter implements StorageAdapter {\n constructor(protected readonly storage: Storage) {}\n\n async get<T>(key: string): Promise<T | null> {\n const raw = this.storage.getItem(key);\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as T;\n } catch {\n return raw as unknown as T;\n }\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n const serialized = typeof value === 'string' ? value : JSON.stringify(value);\n this.storage.setItem(key, serialized);\n }\n\n async remove(key: string): Promise<void> {\n this.storage.removeItem(key);\n }\n\n async clear(): Promise<void> {\n this.storage.clear();\n }\n\n async keys(): Promise<string[]> {\n const result: string[] = [];\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key !== null) {\n result.push(key);\n }\n }\n return result;\n }\n}\n\n/**\n * localStorage adapter with async interface.\n */\nclass LocalStorageAdapter extends WebStorageAdapter {\n constructor() {\n super(localStorage);\n }\n}\n\n/**\n * sessionStorage adapter with async interface.\n */\nclass SessionStorageAdapter extends WebStorageAdapter {\n constructor() {\n super(sessionStorage);\n }\n}\n\n/**\n * IndexedDB configuration options.\n */\nexport interface IndexedDBOptions {\n /** Database name */\n name: string;\n /** Object store name */\n store: string;\n /** Database version (optional) */\n version?: number;\n}\n\n/**\n * IndexedDB key-value adapter.\n * Wraps IndexedDB with a simple key-value interface.\n */\nclass IndexedDBAdapter implements StorageAdapter {\n private dbPromise: Promise<IDBDatabase> | null = null;\n\n constructor(private readonly options: IndexedDBOptions) {}\n\n /**\n * Opens or creates the IndexedDB database.\n */\n private openDB(): Promise<IDBDatabase> {\n if (this.dbPromise) return this.dbPromise;\n\n this.dbPromise = new Promise((resolve, reject) => {\n const request = indexedDB.open(this.options.name, this.options.version ?? 1);\n\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.options.store)) {\n db.createObjectStore(this.options.store);\n }\n };\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n\n return this.dbPromise;\n }\n\n /**\n * Executes a transaction on the object store.\n */\n private async withStore<T>(\n mode: IDBTransactionMode,\n operation: (store: IDBObjectStore) => IDBRequest<T>\n ): Promise<T> {\n const db = await this.openDB();\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.options.store, mode);\n const store = tx.objectStore(this.options.store);\n const request = operation(store);\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async get<T>(key: string): Promise<T | null> {\n const result = await this.withStore<T | undefined>('readonly', (store) => store.get(key));\n return result ?? null;\n }\n\n async set<T>(key: string, value: T): Promise<void> {\n await this.withStore('readwrite', (store) => store.put(value, key));\n }\n\n async remove(key: string): Promise<void> {\n await this.withStore('readwrite', (store) => store.delete(key));\n }\n\n async clear(): Promise<void> {\n await this.withStore('readwrite', (store) => store.clear());\n }\n\n async keys(): Promise<string[]> {\n const result = await this.withStore<IDBValidKey[]>('readonly', (store) => store.getAllKeys());\n return result.map((key) => String(key));\n }\n}\n\n/**\n * Storage factory providing access to different storage adapters.\n */\nexport const storage = {\n /**\n * Create a localStorage adapter.\n * @returns StorageAdapter wrapping localStorage\n */\n local(): StorageAdapter {\n return new LocalStorageAdapter();\n },\n\n /**\n * Create a sessionStorage adapter.\n * @returns StorageAdapter wrapping sessionStorage\n */\n session(): StorageAdapter {\n return new SessionStorageAdapter();\n },\n\n /**\n * Create an IndexedDB adapter with key-value interface.\n * @param options - Database and store configuration\n * @returns StorageAdapter wrapping IndexedDB\n */\n indexedDB(options: IndexedDBOptions): StorageAdapter {\n return new IndexedDBAdapter(options);\n },\n};\n"],"mappings":"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"}
|
package/dist/platform.es.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as a, t as s } from "./config-
|
|
2
|
-
import { a as i, i as n, n as t, o as r, r as f, s as u, t as c } from "./platform-
|
|
1
|
+
import { n as a, t as s } from "./config-BW35FKuA.js";
|
|
2
|
+
import { a as i, i as n, n as t, o as r, r as f, s as u, t as c } from "./platform-CPbCprb6.js";
|
|
3
3
|
export {
|
|
4
4
|
u as buckets,
|
|
5
5
|
r as cache,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bQuery Plugin System — register plugins that extend bQuery with custom
|
|
3
|
+
* directives and components.
|
|
4
|
+
*
|
|
5
|
+
* @module bquery/plugin
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { use, isInstalled, getInstalledPlugins } from '@bquery/bquery/plugin';
|
|
10
|
+
*
|
|
11
|
+
* use({
|
|
12
|
+
* name: 'my-plugin',
|
|
13
|
+
* install(ctx, options) {
|
|
14
|
+
* ctx.directive('tooltip', (el, expr) => { ... });
|
|
15
|
+
* ctx.component('my-widget', MyWidgetElement);
|
|
16
|
+
* },
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export type { BQueryPlugin, CustomDirective, CustomDirectiveHandler, PluginInstallContext, } from './types';
|
|
21
|
+
export { use, isInstalled, getInstalledPlugins, getCustomDirective, getCustomDirectives, resetPlugins, } from './registry';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,YAAY,EACV,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,GAAG,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACb,MAAM,YAAY,CAAC"}
|