@bquery/bquery 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +760 -716
  2. package/dist/{a11y-C5QOVvRn.js → a11y-DVBCy09c.js} +3 -3
  3. package/dist/a11y-DVBCy09c.js.map +1 -0
  4. package/dist/a11y.es.mjs +1 -1
  5. package/dist/component/library.d.ts.map +1 -1
  6. package/dist/{component-CuuTijA6.js → component-L3-JfOFz.js} +5 -5
  7. package/dist/component-L3-JfOFz.js.map +1 -0
  8. package/dist/component.es.mjs +1 -1
  9. package/dist/{config-BW35FKuA.js → config-DhT9auRm.js} +1 -1
  10. package/dist/{config-BW35FKuA.js.map → config-DhT9auRm.js.map} +1 -1
  11. package/dist/{constraints-3lV9yyBw.js → constraints-D5RHQLmP.js} +1 -1
  12. package/dist/constraints-D5RHQLmP.js.map +1 -0
  13. package/dist/core/collection.d.ts +86 -0
  14. package/dist/core/collection.d.ts.map +1 -1
  15. package/dist/core/element.d.ts +28 -0
  16. package/dist/core/element.d.ts.map +1 -1
  17. package/dist/core/shared.d.ts +6 -0
  18. package/dist/core/shared.d.ts.map +1 -1
  19. package/dist/core-DdtZHzsS.js +168 -0
  20. package/dist/core-DdtZHzsS.js.map +1 -0
  21. package/dist/{core-Cjl7GUu8.js → core-EMYSLzaT.js} +289 -259
  22. package/dist/core-EMYSLzaT.js.map +1 -0
  23. package/dist/core.es.mjs +48 -47
  24. package/dist/{custom-directives-7wAShnnd.js → custom-directives-Dr4C5lVV.js} +1 -1
  25. package/dist/custom-directives-Dr4C5lVV.js.map +1 -0
  26. package/dist/{devtools-D2fQLhDN.js → devtools-BhB2iDPT.js} +2 -2
  27. package/dist/devtools-BhB2iDPT.js.map +1 -0
  28. package/dist/devtools.es.mjs +1 -1
  29. package/dist/{dnd-B8EgyzaI.js → dnd-NwZBYh4l.js} +1 -1
  30. package/dist/dnd-NwZBYh4l.js.map +1 -0
  31. package/dist/dnd.es.mjs +1 -1
  32. package/dist/{env-NeVmr4Gf.js → env-CTdvLaH2.js} +1 -1
  33. package/dist/env-CTdvLaH2.js.map +1 -0
  34. package/dist/forms/create-form.d.ts.map +1 -1
  35. package/dist/forms/index.d.ts +3 -2
  36. package/dist/forms/index.d.ts.map +1 -1
  37. package/dist/forms/types.d.ts +46 -0
  38. package/dist/forms/types.d.ts.map +1 -1
  39. package/dist/forms/use-field.d.ts +34 -0
  40. package/dist/forms/use-field.d.ts.map +1 -0
  41. package/dist/forms/validators.d.ts +25 -0
  42. package/dist/forms/validators.d.ts.map +1 -1
  43. package/dist/forms-UcRHsYxC.js +227 -0
  44. package/dist/forms-UcRHsYxC.js.map +1 -0
  45. package/dist/forms.es.mjs +14 -12
  46. package/dist/full.d.ts +17 -26
  47. package/dist/full.d.ts.map +1 -1
  48. package/dist/full.es.mjs +206 -181
  49. package/dist/full.iife.js +33 -33
  50. package/dist/full.iife.js.map +1 -1
  51. package/dist/full.umd.js +33 -33
  52. package/dist/full.umd.js.map +1 -1
  53. package/dist/function-Cybd57JV.js +33 -0
  54. package/dist/function-Cybd57JV.js.map +1 -0
  55. package/dist/{i18n-BnnhTFOS.js → i18n-kuF6Ekj6.js} +3 -3
  56. package/dist/i18n-kuF6Ekj6.js.map +1 -0
  57. package/dist/i18n.es.mjs +1 -1
  58. package/dist/index.es.mjs +251 -228
  59. package/dist/media/breakpoints.d.ts.map +1 -1
  60. package/dist/media/types.d.ts +2 -2
  61. package/dist/media/types.d.ts.map +1 -1
  62. package/dist/{media-Di2Ta22s.js → media-i-fB5WxI.js} +3 -3
  63. package/dist/media-i-fB5WxI.js.map +1 -0
  64. package/dist/media.es.mjs +1 -1
  65. package/dist/{motion-qPj_TYGv.js → motion-BJsAuULb.js} +2 -2
  66. package/dist/motion-BJsAuULb.js.map +1 -0
  67. package/dist/motion.es.mjs +1 -1
  68. package/dist/{mount-SM07RUa6.js → mount-B4Y8bk8Z.js} +5 -5
  69. package/dist/mount-B4Y8bk8Z.js.map +1 -0
  70. package/dist/{platform-CPbCprb6.js → platform-Dw2gE3zI.js} +3 -3
  71. package/dist/{platform-CPbCprb6.js.map → platform-Dw2gE3zI.js.map} +1 -1
  72. package/dist/platform.es.mjs +2 -2
  73. package/dist/plugin/registry.d.ts.map +1 -1
  74. package/dist/{plugin-cPoOHFLY.js → plugin-C2WuC8SF.js} +20 -18
  75. package/dist/plugin-C2WuC8SF.js.map +1 -0
  76. package/dist/plugin.es.mjs +1 -1
  77. package/dist/reactive/async-data.d.ts +28 -3
  78. package/dist/reactive/async-data.d.ts.map +1 -1
  79. package/dist/reactive/computed.d.ts +3 -0
  80. package/dist/reactive/computed.d.ts.map +1 -1
  81. package/dist/reactive/effect.d.ts +3 -0
  82. package/dist/reactive/effect.d.ts.map +1 -1
  83. package/dist/reactive/http.d.ts +194 -0
  84. package/dist/reactive/http.d.ts.map +1 -0
  85. package/dist/reactive/index.d.ts +2 -2
  86. package/dist/reactive/index.d.ts.map +1 -1
  87. package/dist/reactive/pagination.d.ts +126 -0
  88. package/dist/reactive/pagination.d.ts.map +1 -0
  89. package/dist/reactive/polling.d.ts +55 -0
  90. package/dist/reactive/polling.d.ts.map +1 -0
  91. package/dist/reactive/readonly.d.ts +20 -1
  92. package/dist/reactive/readonly.d.ts.map +1 -1
  93. package/dist/reactive/rest.d.ts +293 -0
  94. package/dist/reactive/rest.d.ts.map +1 -0
  95. package/dist/reactive/scope.d.ts +140 -0
  96. package/dist/reactive/scope.d.ts.map +1 -0
  97. package/dist/reactive/signal.d.ts +16 -2
  98. package/dist/reactive/signal.d.ts.map +1 -1
  99. package/dist/reactive/to-value.d.ts +57 -0
  100. package/dist/reactive/to-value.d.ts.map +1 -0
  101. package/dist/reactive/websocket.d.ts +285 -0
  102. package/dist/reactive/websocket.d.ts.map +1 -0
  103. package/dist/reactive-DwkhUJfP.js +1148 -0
  104. package/dist/reactive-DwkhUJfP.js.map +1 -0
  105. package/dist/reactive.es.mjs +38 -19
  106. package/dist/{registry-CWf368tT.js → registry-B08iilIh.js} +1 -1
  107. package/dist/{registry-CWf368tT.js.map → registry-B08iilIh.js.map} +1 -1
  108. package/dist/router/constraints.d.ts.map +1 -1
  109. package/dist/router/index.d.ts +1 -1
  110. package/dist/router/index.d.ts.map +1 -1
  111. package/dist/router/router.d.ts.map +1 -1
  112. package/dist/router/state.d.ts +25 -2
  113. package/dist/router/state.d.ts.map +1 -1
  114. package/dist/router-CQikC9Ed.js +492 -0
  115. package/dist/router-CQikC9Ed.js.map +1 -0
  116. package/dist/router.es.mjs +9 -8
  117. package/dist/ssr/hydrate.d.ts.map +1 -1
  118. package/dist/{ssr-B2qd_WBB.js → ssr-_dAcGdzu.js} +4 -4
  119. package/dist/ssr-_dAcGdzu.js.map +1 -0
  120. package/dist/ssr.es.mjs +1 -1
  121. package/dist/store/persisted.d.ts.map +1 -1
  122. package/dist/{store-DWpyH6p5.js → store-Cb3gPRve.js} +7 -7
  123. package/dist/store-Cb3gPRve.js.map +1 -0
  124. package/dist/store.es.mjs +2 -2
  125. package/dist/storybook.es.mjs.map +1 -1
  126. package/dist/{testing-CsqjNUyy.js → testing-C5Sjfsna.js} +8 -8
  127. package/dist/testing-C5Sjfsna.js.map +1 -0
  128. package/dist/testing.es.mjs +1 -1
  129. package/dist/{type-guards-Do9DWgNp.js → type-guards-BMX2c0LP.js} +1 -1
  130. package/dist/{type-guards-Do9DWgNp.js.map → type-guards-BMX2c0LP.js.map} +1 -1
  131. package/dist/untrack-D0fnO5k2.js +36 -0
  132. package/dist/untrack-D0fnO5k2.js.map +1 -0
  133. package/dist/view/custom-directives.d.ts.map +1 -1
  134. package/dist/view.es.mjs +4 -4
  135. package/package.json +177 -177
  136. package/src/a11y/announce.ts +131 -131
  137. package/src/a11y/audit.ts +314 -314
  138. package/src/a11y/index.ts +68 -68
  139. package/src/a11y/media-preferences.ts +255 -255
  140. package/src/a11y/roving-tab-index.ts +164 -164
  141. package/src/a11y/skip-link.ts +255 -255
  142. package/src/a11y/trap-focus.ts +184 -184
  143. package/src/a11y/types.ts +183 -183
  144. package/src/component/component.ts +599 -599
  145. package/src/component/html.ts +153 -153
  146. package/src/component/index.ts +52 -52
  147. package/src/component/library.ts +540 -542
  148. package/src/component/scope.ts +212 -212
  149. package/src/component/types.ts +310 -310
  150. package/src/core/collection.ts +876 -707
  151. package/src/core/element.ts +1015 -981
  152. package/src/core/env.ts +60 -60
  153. package/src/core/index.ts +49 -49
  154. package/src/core/shared.ts +77 -62
  155. package/src/core/utils/index.ts +148 -148
  156. package/src/devtools/devtools.ts +410 -410
  157. package/src/devtools/index.ts +48 -48
  158. package/src/devtools/types.ts +104 -104
  159. package/src/dnd/draggable.ts +296 -296
  160. package/src/dnd/droppable.ts +228 -228
  161. package/src/dnd/index.ts +62 -62
  162. package/src/dnd/sortable.ts +307 -307
  163. package/src/dnd/types.ts +293 -293
  164. package/src/forms/create-form.ts +320 -278
  165. package/src/forms/index.ts +70 -65
  166. package/src/forms/types.ts +203 -154
  167. package/src/forms/use-field.ts +231 -0
  168. package/src/forms/validators.ts +294 -265
  169. package/src/full.ts +554 -480
  170. package/src/i18n/formatting.ts +67 -67
  171. package/src/i18n/i18n.ts +200 -200
  172. package/src/i18n/index.ts +67 -67
  173. package/src/i18n/translate.ts +182 -182
  174. package/src/i18n/types.ts +171 -171
  175. package/src/index.ts +108 -108
  176. package/src/media/battery.ts +116 -116
  177. package/src/media/breakpoints.ts +129 -131
  178. package/src/media/clipboard.ts +80 -80
  179. package/src/media/device-sensors.ts +158 -158
  180. package/src/media/geolocation.ts +119 -119
  181. package/src/media/index.ts +76 -76
  182. package/src/media/media-query.ts +92 -92
  183. package/src/media/network.ts +115 -115
  184. package/src/media/types.ts +177 -177
  185. package/src/media/viewport.ts +84 -84
  186. package/src/motion/index.ts +57 -57
  187. package/src/motion/morph.ts +151 -151
  188. package/src/motion/parallax.ts +120 -120
  189. package/src/motion/reduced-motion.ts +66 -66
  190. package/src/motion/types.ts +271 -271
  191. package/src/motion/typewriter.ts +164 -164
  192. package/src/plugin/index.ts +37 -37
  193. package/src/plugin/registry.ts +284 -269
  194. package/src/plugin/types.ts +137 -137
  195. package/src/reactive/async-data.ts +250 -29
  196. package/src/reactive/computed.ts +144 -130
  197. package/src/reactive/effect.ts +29 -6
  198. package/src/reactive/http.ts +790 -0
  199. package/src/reactive/index.ts +60 -0
  200. package/src/reactive/pagination.ts +317 -0
  201. package/src/reactive/polling.ts +179 -0
  202. package/src/reactive/readonly.ts +52 -8
  203. package/src/reactive/rest.ts +859 -0
  204. package/src/reactive/scope.ts +276 -0
  205. package/src/reactive/signal.ts +61 -1
  206. package/src/reactive/to-value.ts +71 -0
  207. package/src/reactive/websocket.ts +849 -0
  208. package/src/router/bq-link.ts +279 -279
  209. package/src/router/constraints.ts +204 -201
  210. package/src/router/index.ts +49 -49
  211. package/src/router/match.ts +312 -312
  212. package/src/router/path-pattern.ts +52 -52
  213. package/src/router/query.ts +38 -38
  214. package/src/router/router.ts +421 -402
  215. package/src/router/state.ts +51 -3
  216. package/src/router/types.ts +139 -139
  217. package/src/router/use-route.ts +68 -68
  218. package/src/router/utils.ts +157 -157
  219. package/src/security/index.ts +12 -12
  220. package/src/ssr/hydrate.ts +84 -82
  221. package/src/ssr/index.ts +70 -70
  222. package/src/ssr/render.ts +508 -508
  223. package/src/ssr/serialize.ts +296 -296
  224. package/src/ssr/types.ts +81 -81
  225. package/src/store/create-store.ts +467 -467
  226. package/src/store/index.ts +27 -27
  227. package/src/store/persisted.ts +245 -249
  228. package/src/store/types.ts +247 -247
  229. package/src/store/utils.ts +135 -135
  230. package/src/storybook/index.ts +480 -480
  231. package/src/testing/index.ts +42 -42
  232. package/src/testing/testing.ts +593 -593
  233. package/src/testing/types.ts +170 -170
  234. package/src/view/custom-directives.ts +28 -30
  235. package/src/view/evaluate.ts +292 -292
  236. package/src/view/process.ts +108 -108
  237. package/dist/a11y-C5QOVvRn.js.map +0 -1
  238. package/dist/component-CuuTijA6.js.map +0 -1
  239. package/dist/constraints-3lV9yyBw.js.map +0 -1
  240. package/dist/core-Cjl7GUu8.js.map +0 -1
  241. package/dist/core-DnlyjbF2.js +0 -112
  242. package/dist/core-DnlyjbF2.js.map +0 -1
  243. package/dist/custom-directives-7wAShnnd.js.map +0 -1
  244. package/dist/devtools-D2fQLhDN.js.map +0 -1
  245. package/dist/dnd-B8EgyzaI.js.map +0 -1
  246. package/dist/env-NeVmr4Gf.js.map +0 -1
  247. package/dist/forms-C3yovgH9.js +0 -141
  248. package/dist/forms-C3yovgH9.js.map +0 -1
  249. package/dist/i18n-BnnhTFOS.js.map +0 -1
  250. package/dist/media-Di2Ta22s.js.map +0 -1
  251. package/dist/motion-qPj_TYGv.js.map +0 -1
  252. package/dist/mount-SM07RUa6.js.map +0 -1
  253. package/dist/plugin-cPoOHFLY.js.map +0 -1
  254. package/dist/reactive-Cfv0RK6x.js +0 -233
  255. package/dist/reactive-Cfv0RK6x.js.map +0 -1
  256. package/dist/router-BrthaP_z.js +0 -473
  257. package/dist/router-BrthaP_z.js.map +0 -1
  258. package/dist/ssr-B2qd_WBB.js.map +0 -1
  259. package/dist/store-DWpyH6p5.js.map +0 -1
  260. package/dist/testing-CsqjNUyy.js.map +0 -1
  261. package/dist/untrack-DJVQQ2WM.js +0 -33
  262. package/dist/untrack-DJVQQ2WM.js.map +0 -1
@@ -1 +0,0 @@
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":";;;;;;AAKA,IAAM,IAAiB,KAUjB,IAAN,MAAe;AAAA,EAIb,YAAY,GAAiB;iBAHb,oBAAI,IAAA,GAIlB,KAAK,UAAU;AAAA;EAGjB,IAAI,GAAqC;AACvC,UAAM,IAAQ,KAAK,MAAM,IAAI,CAAA;AAC7B,WAAI,MAAU,WAEZ,KAAK,MAAM,OAAO,CAAA,GAClB,KAAK,MAAM,IAAI,GAAK,CAAA,IAEf;AAAA;EAGT,IAAI,GAAa,GAAyB;AAExC,QAAI,KAAK,MAAM,IAAI,CAAA,EACjB,MAAK,MAAM,OAAO,CAAA;AAAA,aACT,KAAK,MAAM,QAAQ,KAAK,SAAS;AAE1C,YAAM,IAAS,KAAK,MAAM,KAAA,EAAO,KAAA,EAAO;AACxC,MAAI,MAAW,UACb,KAAK,MAAM,OAAO,CAAA;AAAA;AAGtB,SAAK,MAAM,IAAI,GAAK,CAAA;AAAA;EAGtB,QAAc;AACZ,SAAK,MAAM,MAAA;AAAA;EAGb,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA;GAKhB,IAAgB,IAAI,EAAS,CAAA,GAG7B,IAAmB,IAAI,EAAS,CAAA,GAczB,KAAA,MAAmC;AAC9C,EAAA,EAAc,MAAA,GACd,EAAiB,MAAA;GAQb,IAAA,CAAqB,MACzB,IAAI,MAAM,GAAS;AAAA,EACjB,IAAI,GAAQ,GAAuB;AAEjC,QAAI,OAAO,KAAS,SAClB,QAAO,QAAQ,IAAI,GAAQ,CAAA;AAE7B,UAAM,IAAQ,EAAO,CAAA;AAErB,WAAI,EAAS,CAAA,KAAU,EAAW,CAAA,IACxB,EAA0B,QAE7B;AAAA;EAET,IAAI,GAAQ,GAAuB;AAEjC,WAAI,OAAO,KAAS,WACX,QAAQ,IAAI,GAAQ,CAAA,IAEtB,KAAQ;AAAA;CAElB,GAgBU,IAAA,CAAyB,GAAoB,MAA+B;AACvF,MAAI;AAEF,UAAM,IAAc,EAAkB,CAAA;AAGtC,QAAI,IAAK,EAAc,IAAI,CAAA;AAC3B,WAAK,MAGH,IAAK,IAAI,SAAS,QAAQ,wBAAwB,CAAA,MAAW,GAG7D,EAAc,IAAI,GAAY,CAAA,IAEzB,EAAG,CAAA;AAAA,WACH,GAAO;AACd,YAAQ,MAAM,kCAAkC,CAAA,KAAe,CAAA;AAC/D;AAAA;GAUS,IAAA,CAA4B,GAAoB,MAA+B;AAC1F,MAAI;AAEF,QAAI,IAAK,EAAiB,IAAI,CAAA;AAC9B,WAAK,MAGH,IAAK,IAAI,SAAS,QAAQ,wBAAwB,CAAA,MAAW,GAG7D,EAAiB,IAAI,GAAY,CAAA,IAE5B,EAAG,CAAA;AAAA,WACH,GAAO;AACd,YAAQ,MAAM,kCAAkC,CAAA,KAAe,CAAA;AAC/D;AAAA;GASS,IAAA,CAAyB,MAA+C;AACnF,QAAM,IAAiC,CAAA,GAGjC,IAAQ,EACX,KAAA,EACA,QAAQ,YAAY,EAAA,EACpB,KAAA;AACH,MAAI,CAAC,EAAO,QAAO;AAGnB,QAAM,IAAkB,CAAA;AACxB,MAAI,IAAU,IACV,IAAQ,GACR,IAA0B;AAE9B,WAAS,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;AACrC,UAAM,IAAO,EAAM,CAAA;AAInB,QAAI,MAAS,OAAO,MAAS,OAAO,MAAS,KAAK;AAChD,UAAI,IAAiB,GACjB,IAAI,IAAI;AACZ,aAAO,KAAK,KAAK,EAAM,CAAA,MAAO;AAC5B,QAAA,KACA;AAGF,MAAI,IAAiB,MAAM,MACrB,MAAa,OACf,IAAW,IACF,MAAa,MACtB,IAAW,QAGf,KAAW;AACX;AAAA;AAIF,QAAI,MAAa,MAAM;AACrB,MAAA,KAAW;AACX;AAAA;AAIF,IAAI,MAAS,OAAO,MAAS,OAAO,MAAS,OAC3C,KACA,KAAW,KACF,MAAS,OAAO,MAAS,OAAO,MAAS,OAClD,KACA,KAAW,KACF,MAAS,OAAO,MAAU,KAEnC,EAAM,KAAK,EAAQ,KAAA,CAAM,GACzB,IAAU,MAEV,KAAW;AAAA;AAKf,EAAI,EAAQ,KAAA,KACV,EAAM,KAAK,EAAQ,KAAA,CAAM;AAI3B,aAAW,KAAQ,GAAO;AAExB,QAAI,IAAa,IACb,IAAY,GACZ,IAA8B;AAElC,aAAS,IAAI,GAAG,IAAI,EAAK,QAAQ,KAAK;AACpC,YAAM,IAAO,EAAK,CAAA;AAElB,UAAI,MAAS,OAAO,MAAS,OAAO,MAAS,KAAK;AAChD,YAAI,IAAiB,GACjB,IAAI,IAAI;AACZ,eAAO,KAAK,KAAK,EAAK,CAAA,MAAO;AAC3B,UAAA,KACA;AAEF,QAAI,IAAiB,MAAM,MACrB,MAAiB,OACnB,IAAe,IACN,MAAiB,MAC1B,IAAe;AAGnB;AAAA;AAGF,UAAI,MAAiB;AAErB,YAAI,MAAS,OAAO,MAAS,OAAO,MAAS,IAC3C,CAAA;AAAA,iBACS,MAAS,OAAO,MAAS,OAAO,MAAS,IAClD,CAAA;AAAA,iBACS,MAAS,OAAO,MAAc,GAAG;AAC1C,UAAA,IAAa;AACb;AAAA;;;AAIJ,QAAI,IAAa,IAAI;AACnB,YAAM,IAAM,EACT,MAAM,GAAG,CAAA,EACT,KAAA,EACA,QAAQ,gBAAgB,EAAA;AAC3B,UAAI,EAAwB,CAAA,EAAM;AAElC,MAAA,EAAO,CAAA,IADO,EAAK,MAAM,IAAa,CAAA,EAAG,KAAA;AAAA;;AAK7C,SAAO;GC1RI,IAAA,CAAc,MACzB,CAAQ,GAAI,GAAY,GAAS,MAAa;AAC5C,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAQ,EAAS,GAAY,CAAA;AACnC,IAAI,KAAS,QAAQ,MAAU,KAC7B,EAAG,gBAAgB,CAAA,IACV,MAAU,KACnB,EAAG,aAAa,GAAU,EAAA,IAE1B,EAAG,aAAa,GAAU,OAAO,CAAA,CAAM;AAAA;AAG3C,EAAA,EAAS,KAAK,CAAA;GCXL,IAAA,CAAiC,GAAI,GAAY,GAAS,MAAa;AAElF,MAAI,IAA+B,oBAAI,IAAA;AAEvC,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAA0B,oBAAI,IAAA;AAEpC,QAAI,EAAW,UAAA,EAAY,WAAW,GAAA,GAAM;AAE1C,YAAM,IAAW,EAAsB,CAAA;AACvC,iBAAW,CAAC,GAAW,CAAA,KAAkB,OAAO,QAAQ,CAAA,GAAW;AACjE,cAAM,IAAY,EAAkB,GAAe,CAAA;AACnD,QAAA,EAAG,UAAU,OAAO,GAAW,EAAQ,CAAU,GAEjD,EAAW,IAAI,CAAA;AAAA;eAER,SAAS,KAAK,CAAA,GAAa;AAEpC,YAAM,IAAU,EAAmB,GAAY,CAAA;AAC/C,UAAI,MAAM,QAAQ,CAAA;mBACL,KAAO,EAChB,CAAI,MACF,EAAG,UAAU,IAAI,CAAA,GACjB,EAAW,IAAI,CAAA;AAAA,WAIhB;AAEL,YAAM,IAAS,EAA4B,GAAY,CAAA;AACvD,MAAI,OAAO,KAAW,WACpB,EAAO,MAAM,KAAA,EAAO,QAAA,CAAS,MAAQ;AACnC,QAAI,MACF,EAAG,UAAU,IAAI,CAAA,GACjB,EAAW,IAAI,CAAA;AAAA,WAGV,MAAM,QAAQ,CAAA,KACvB,EAAO,QAAA,CAAS,MAAQ;AACtB,QAAI,MACF,EAAG,UAAU,IAAI,CAAA,GACjB,EAAW,IAAI,CAAA;AAAA;;AASvB,eAAW,KAAO,EAChB,CAAK,EAAW,IAAI,CAAA,KAClB,EAAG,UAAU,OAAO,CAAA;AAIxB,IAAA,IAAkB;AAAA;AAGpB,EAAA,EAAS,KAAK,CAAA;GChCV,KAAA,CACJ,GACA,GACA,GACA,GACA,GACA,MACY;AACZ,MAAI,CAAC,EACH,QAAO;AAGT,QAAM,IAA6B;AAAA,IACjC,GAAG;AAAA,KACF,CAAA,GAAW;AAAA;AAEd,SAAI,MACF,EAAW,CAAA,IAAa,IAGnB,EAAS,GAAe,CAAA;GAepB,KAAA,CAAoB,MAIT;AACtB,QAAM,EAAE,QAAA,GAAQ,gBAAA,GAAgB,iBAAA,EAAA,IAAoB;AAEpD,SAAA,CAAQ,GAAI,GAAY,GAAS,MAAa;AAC5C,UAAM,IAAS,EAAG;AAClB,QAAI,CAAC,EAAQ;AAIb,UAAM,IAAQ,EAAW,MAAM,8CAAA;AAC/B,QAAI,CAAC,GAAO;AACV,cAAQ,MAAM,2CAA2C,CAAA,GAAW;AACpE;AAAA;AAGF,UAAM,CAAA,EAAG,GAAU,GAAW,CAAA,IAAkB,GAG1C,IAAgB,EAAG,aAAa,MAAA,KAAW,EAAG,aAAa,GAAG,CAAA,MAAO,GAErE,IAAW,EAAG,UAAU,EAAA;AAC9B,IAAA,EAAS,gBAAgB,GAAG,CAAA,MAAO,GACnC,EAAS,gBAAgB,MAAA,GACzB,EAAS,gBAAgB,GAAG,CAAA,MAAO;AAGnC,UAAM,IAAc,SAAS,cAAc,WAAW,CAAA,EAAA;AACtD,IAAA,EAAO,aAAa,GAAa,CAAA;AAGjC,QAAI,IAAmB,oBAAI,IAAA,GACvB,IAA2B,CAAA;AAK/B,UAAM,IAAA,CAAqB,GAAe,GAAe,MAA+B;AACtF,YAAM,IAAQ,EAAS,UAAU,EAAA,GAC3B,IAA4B,CAAA,GAG5B,IAAU,EAAO,CAAA,GACjB,IAAW,IAAY,EAAO,CAAA,IAAS,MAEvC,IAA+B;AAAA,QACnC,GAAG;AAAA,SACF,CAAA,GAAW;AAAA;AAEd,aAAI,KAAa,MACf,EAAa,CAAA,IAAa,IAI5B,EAAe,GAAO,GAAc,GAAQ,CAAA,GAC5C,EAAgB,GAAO,GAAc,GAAQ,CAAA,GAEtC;AAAA,QACL,KAAA;AAAA,QACA,SAAS;AAAA,QACT,UAAU;AAAA,QACV,MAAA;AAAA,QACA,OAAA;AAAA,QACA,YAAY;AAAA,QACZ,aAAa;AAAA;OAOX,IAAA,CAAc,MAAiC;AACnD,iBAAW,KAAW,EAAS,SAC7B,CAAA,EAAA;AAEF,MAAA,EAAS,QAAQ,OAAA;AAAA,OAOb,IAAA,CAAc,GAAwB,GAAkB,MAA2B;AAEvF,MAAK,OAAO,GAAG,EAAS,MAAM,CAAA,MAC5B,EAAS,OAAO,GAChB,EAAS,WAAW,QAAQ,IAI1B,EAAS,UAAU,MACrB,EAAS,QAAQ,GACb,EAAS,gBACX,EAAS,YAAY,QAAQ;AAAA,OAK7B,IAAU,EAAA,MAAa;AAC3B,YAAM,IAAO,EAAoB,GAAgB,CAAA;AAEjD,UAAI,CAAC,MAAM,QAAQ,CAAA,GAAO;AAExB,mBAAW,KAAY,EAAiB,OAAA,EACtC,CAAA,EAAW,CAAA;AAEb,QAAA,EAAiB,MAAA,GACjB,IAAgB,CAAA;AAChB;AAAA;AAIF,YAAM,IAAqB,CAAA,GACrB,IAAgB,oBAAI,IAAA,GACpB,IAAW,oBAAI,IAAA;AAErB,MAAA,EAAK,QAAA,CAAS,GAAM,MAAU;AAC5B,YAAI,IAAM,GAAW,GAAM,GAAO,GAAe,GAAU,GAAW,CAAA;AAGtE,QAAI,EAAS,IAAI,CAAA,MACf,QAAQ,KACN,0BAA0B,OAAO,CAAA,CAAI,uBAAuB,CAAA,+GAAM,GAKpE,IAAM;AAAA,UAAE,kBAAkB;AAAA,UAAK,WAAW;AAAA,YAE5C,EAAS,IAAI,CAAA,GAEb,EAAQ,KAAK,CAAA,GACb,EAAc,IAAI,GAAK;AAAA,UAAE,MAAA;AAAA,UAAM,OAAA;AAAA,SAAO;AAAA;AAIxC,YAAM,IAA0B,CAAA;AAChC,iBAAW,KAAO,EAChB,CAAK,EAAc,IAAI,CAAA,KACrB,EAAa,KAAK,CAAA;AAKtB,iBAAW,KAAO,GAAc;AAC9B,cAAM,IAAW,EAAiB,IAAI,CAAA;AACtC,QAAI,MACF,EAAW,CAAA,GACX,EAAiB,OAAO,CAAA;AAAA;AAK5B,YAAM,IAAiB,oBAAI,IAAA;AAC3B,UAAI,IAAyC;AAE7C,eAAS,IAAI,GAAG,IAAI,EAAQ,QAAQ,KAAK;AACvC,cAAM,IAAM,EAAQ,CAAA,GACd,EAAE,MAAA,GAAM,OAAA,EAAA,IAAU,EAAc,IAAI,CAAA;AAC1C,YAAI,IAAW,EAAiB,IAAI,CAAA;AAEpC,QAAI,KAEF,EAAW,GAAU,GAAM,CAAA,GAC3B,EAAe,IAAI,GAAK,CAAA,GAGc,EAAoB,gBACtC,EAAS,WAE3B,EAAoB,MAAM,EAAS,OAAA,GAErC,IAAsB,EAAS,YAG/B,IAAW,EAAkB,GAAM,GAAO,CAAA,GAC1C,EAAe,IAAI,GAAK,CAAA,GAGxB,EAAoB,MAAM,EAAS,OAAA,GACnC,IAAsB,EAAS;AAAA;AAKnC,MAAA,IAAmB,GACnB,IAAgB;AAAA;AAIlB,IAAA,EAAS,KAAA,MAAW;AAClB,MAAA,EAAA;AACA,iBAAW,KAAY,EAAiB,OAAA,EACtC,YAAW,KAAe,EAAS,SACjC,CAAA,EAAA;AAGJ,MAAA,EAAiB,MAAA;AAAA;;GCtQV,KAAA,CAAc,MACzB,CAAQ,GAAI,GAAY,GAAS,MAAa;AAC5C,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAQ,EAAiB,GAAY,CAAA,GACrC,IAAO,OAAO,KAAS,EAAA;AAC7B,IAAA,EAAG,YAAY,IAAW,EAAa,CAAA,IAAQ;AAAA;AAEjD,EAAA,EAAS,KAAK,CAAA;GCRL,KAAA,CAA8B,GAAI,GAAY,GAAS,MAAa;AAC/E,QAAM,IAAc,SAAS,cAAc,UAAU,CAAA,EAAA;AAGrD,MAAI,IAAa;AAEjB,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAY,EAAkB,GAAY,CAAA;AAEhD,IAAI,KAAa,CAAC,KAEhB,EAAY,YAAY,CAAA,GACxB,IAAa,MACJ,CAAC,KAAa,MAEvB,EAAG,YAAY,CAAA,GACf,IAAa;AAAA;AAIjB,EAAA,EAAS,KAAK,CAAA;GCpBH,KAAA,CAAiC,GAAI,GAAY,GAAS,MAAa;AAClF,QAAM,IAAQ,GACR,IAAW,EAA6B,GAAY,CAAA;AAE1D,MAAI,CAAC,EAAS,CAAA,GAAW;AACvB,YAAQ,KAAK,iDAAiD,CAAA,GAAW;AACzE;AAAA;AAGF,QAAM,IAAM,GAGN,IAAa,EAAM,SAAS,YAC5B,IAAU,EAAM,SAAS,SAEzB,IAAA,MAAoB;AACxB,IAAI,IACD,EAA2B,UAAU,EAAQ,EAAI,QACzC,IACR,EAA2B,UAAU,EAAI,UAAU,EAAM,QAE1D,EAAM,QAAQ,OAAO,EAAI,SAAS,EAAA;AAAA,KAKhC,IAAU,EAAA,MAAa;AAC3B,IAAA,EAAA;AAAA;AAEF,EAAA,EAAS,KAAK,CAAA;AAGd,QAAM,IAAY,EAAM,YAAY,WAAW,WAAW,SACpD,IAAA,MAAgB;AACpB,IAAI,IACF,EAAI,QAAS,EAA2B,UAC/B,IACJ,EAA2B,YAC9B,EAAI,QAAQ,EAAM,SAGpB,EAAI,QAAQ,EAAM;AAAA;AAItB,EAAA,EAAM,iBAAiB,GAAW,CAAA,GAClC,EAAS,KAAA,MAAW,EAAM,oBAAoB,GAAW,CAAA,CAAQ;GC/CtD,KAAA,CAAY,MACvB,CAAQ,GAAI,GAAY,GAAS,MAAa;AAC5C,QAAM,IAAA,CAAW,MAAiB;AAEhC,UAAM,IAAe;AAAA,MAAE,GAAG;AAAA,MAAS,QAAQ;AAAA,MAAO,KAAK;AAAA;AAQvD,QAAI,CAFiB,EAAW,SAAS,GAAA,GAEtB;AAEjB,YAAM,IAAS,EAAqB,GAAY,CAAA;AAChD,UAAI,OAAO,KAAW,YAAY;AAGhC,QAAA,EAAO,CAAA;AACP;AAAA;AAGF;AAAA;AAKF,IAAA,EAAY,GAAY,CAAA;AAAA;AAG1B,EAAA,EAAG,iBAAiB,GAAW,CAAA,GAC/B,EAAS,KAAA,MAAW,EAAG,oBAAoB,GAAW,CAAA,CAAQ;;AC7BlE,SAAS,GAAiB,GAA+C;AACvE,QAAM,IAAa,OAAO,yBAAyB,GAAK,OAAA;AACxD,SAAK,IAED,WAAW,IAAmB,EAAW,aAAa,KAEnD,OAAO,EAAW,OAAQ,aAJT;;AAW1B,IAAa,KAAA,CAA+B,GAAI,GAAY,GAAS,MAAa;AAChF,QAAM,IAAW,EACf,GACA,CAAA;AAGF,EAAI,EAAS,CAAA,KACX,EAAS,QAAQ,GACjB,EAAS,KAAA,MAAW;AAClB,IAAA,EAAS,QAAQ;AAAA,QAEV,OAAO,KAAa,YAAY,MAAa,QAAQ,GAAiB,CAAA,MAE/E,EAAS,QAAQ,GACjB,EAAS,KAAA,MAAW;AAClB,IAAA,EAAS,QAAQ;AAAA;GC7BV,KAAA,CAAgC,GAAI,GAAY,GAAS,MAAa;AACjF,QAAM,IAAS;AAIf,MAAI,IAAkB,EAAO,MAAM;AACnC,MAAI,CAAC,KAAmB,MAAoB,QAAQ;AAClD,UAAM,IAAW,EAAO,cAAc,aAAa,iBAAiB,CAAA,EAAQ,WAAW;AACvF,IAAA,IAAkB,MAAa,SAAS,IAAW;AAAA;AAGrD,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAY,EAAkB,GAAY,CAAA;AAChD,IAAA,EAAO,MAAM,UAAU,IAAY,IAAkB;AAAA;AAGvD,EAAA,EAAS,KAAK,CAAA;GChBH,KAAA,CAAiC,GAAI,GAAY,GAAS,MAAa;AAClF,QAAM,IAAS;AACf,MAAI,IAA6B,oBAAI,IAAA;AAErC,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAY,oBAAI,IAAA;AAEtB,QAAI,EAAW,UAAA,EAAY,WAAW,GAAA,GAAM;AAC1C,YAAM,IAAW,EAAsB,CAAA;AACvC,iBAAW,CAAC,GAAM,CAAA,KAAc,OAAO,QAAQ,CAAA,GAAW;AACxD,cAAM,IAAQ,EAAiB,GAAW,CAAA,GACpC,IAAU,EAAK,QAAQ,YAAY,KAAA,EAAO,YAAA;AAChD,QAAA,EAAO,MAAM,YAAY,GAAS,OAAO,KAAS,EAAA,CAAG,GACrD,EAAU,IAAI,CAAA;AAAA;WAEX;AACL,YAAM,IAAS,EAAiC,GAAY,CAAA;AAC5D,UAAI,KAAU,OAAO,KAAW,SAC9B,YAAW,CAAC,GAAM,CAAA,KAAU,OAAO,QAAQ,CAAA,GAAS;AAClD,cAAM,IAAU,EAAK,QAAQ,YAAY,KAAA,EAAO,YAAA;AAChD,QAAA,EAAO,MAAM,YAAY,GAAS,OAAO,KAAS,EAAA,CAAG,GACrD,EAAU,IAAI,CAAA;AAAA;;AAMpB,eAAW,KAAW,EACpB,CAAK,EAAU,IAAI,CAAA,KACjB,EAAO,MAAM,eAAe,CAAA;AAKhC,IAAA,IAAgB;AAAA;AAGlB,EAAA,EAAS,KAAK,CAAA;GCrCH,KAAA,CAAgC,GAAI,GAAY,GAAS,MAAa;AACjF,QAAM,IAAU,EAAA,MAAa;AAC3B,UAAM,IAAQ,EAAS,GAAY,CAAA;AACnC,IAAA,EAAG,cAAc,OAAO,KAAS,EAAA;AAAA;AAEnC,EAAA,EAAS,KAAK,CAAA;GCUH,IAAA,CACX,GACA,GACA,GACA,GACA,MACS;AACT,QAAM,IAAa,MAAM,KAAK,EAAG,UAAA;AAEjC,aAAW,KAAQ,GAAY;AAC7B,UAAM,EAAE,MAAM,GAAe,OAAA,EAAA,IAAU;AAEvC,QAAI,CAAC,EAAc,WAAW,GAAG,CAAA,GAAO,EAAK;AAE7C,UAAM,IAAY,EAAc,MAAM,EAAO,SAAS,CAAA;AAGtD,QAAI,MAAc,OAAO;AACvB,MAAA,EAAS,IAAI,GAAI,GAAO,GAAS,CAAA;AACjC;AAAA;AAIF,QAAI,MAAc,OAChB,CAAA,EAAS,KAAK,GAAI,GAAO,GAAS,CAAA;AAAA,aACzB,MAAc,OACvB,CAAA,EAAS,KAAK,GAAI,GAAO,GAAS,CAAA;AAAA,aACzB,MAAc,KACvB,CAAA,EAAS,GAAG,GAAI,GAAO,GAAS,CAAA;AAAA,aACvB,MAAc,OACvB,CAAA,EAAS,KAAK,GAAI,GAAO,GAAS,CAAA;AAAA,aACzB,MAAc,QACvB,CAAA,EAAS,MAAM,GAAI,GAAO,GAAS,CAAA;AAAA,aAC1B,MAAc,QACvB,CAAA,EAAS,MAAM,GAAI,GAAO,GAAS,CAAA;AAAA,aAC1B,MAAc,QACvB,CAAA,EAAS,MAAM,GAAI,GAAO,GAAS,CAAA;AAAA,aAC1B,MAAc,MACvB,CAAA,EAAS,IAAI,GAAI,GAAO,GAAS,CAAA;AAAA,aACxB,EAAU,WAAW,OAAA,GAAU;AACxC,YAAM,IAAW,EAAU,MAAM,CAAA;AACjC,MAAA,EAAS,KAAK,CAAA,EAAU,GAAI,GAAO,GAAS,CAAA;AAAA,eACnC,EAAU,WAAW,KAAA,GAAQ;AACtC,YAAM,IAAY,EAAU,MAAM,CAAA;AAClC,MAAA,EAAS,GAAG,CAAA,EAAW,GAAI,GAAO,GAAS,CAAA;AAAA,WACtC;AAEL,YAAM,IAAgB,EAAmB,CAAA;AACzC,MAAI,IACF,EAAc,GAAI,GAAO,GAAS,CAAA,IAElC,EAAA,KACA,OAAO,UAAY,OACnB,OAAO,QAAQ,QAAS,cAExB,QAAQ,KACN,qCAAqC,CAAA,iBAA8B,CAAA,UAAmB,EAAG,QAAQ,YAAA,CAAa,mEAAC;AAAA;;GAW5G,IAAA,CACX,GACA,GACA,GACA,GACA,MACS;AACT,QAAM,IAAW,MAAM,KAAK,EAAG,QAAA;AAC/B,aAAW,KAAS,EAElB,CAAK,EAAM,aAAa,GAAG,CAAA,MAAO,IAIhC,EAAe,GAAO,GAAS,GAAQ,GAAU,CAAA,KAHjD,EAAe,GAAO,GAAS,GAAQ,GAAU,CAAA,GACjD,EAAgB,GAAO,GAAS,GAAQ,GAAU,CAAA;GC9C3C,KAAA,CACX,GACA,GACA,IAAwB,CAAA,MACf;AACT,QAAM,EAAE,QAAA,IAAS,MAAM,UAAA,IAAW,GAAA,IAAS,GAErC,IAAK,OAAO,KAAa,WAAW,SAAS,cAAc,CAAA,IAAY;AAE7E,MAAI,CAAC,EACH,OAAM,IAAI,MAAM,yBAAyB,CAAA,cAAS;AAKpD,MAAI,EAAG,aAAa,GAAG,CAAA,MAAO,EAC5B,OAAM,IAAI,MACR,6CAA6C,CAAA,4BAC/B,CAAA,sCAAO;AAIzB,QAAM,IAAwB,CAAA,GAExB,IAA8B;AAAA,IAClC,MAAM;AAAA,IACN,MAAM,GAAW,CAAA;AAAA,IACjB,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK,GAAiB;AAAA,MACpB,QAAA;AAAA,MACA,gBAAA,CAAiB,GAAM,GAAa,GAAY,MAC9C,EAAe,GAAM,GAAa,GAAY,GAAc,CAAA;AAAA,MAC9D,iBAAA,CAAkB,GAAM,GAAa,GAAY,MAC/C,EAAgB,GAAM,GAAa,GAAY,GAAc,CAAA;AAAA,KAChE;AAAA,IACD,MAAM;AAAA,IACN,IAAI;AAAA;AAqBN,UAlBM,CACJ,GACA,GACA,MACG;AAGH,UAAM,IAAS,EAAK,aAAa,GAAG,CAAA,MAAO;AAE3C,IAAA,EAAe,GAAM,GAAa,GAAQ,GAAc,CAAA,GAGnD,KACH,EAAgB,GAAM,GAAa,GAAQ,GAAc,CAAA;AAAA,KAKzC,GAAI,GAAS,CAAA,GAE1B;AAAA,IACL,IAAA;AAAA,IACA,SAAA;AAAA,IAEA,QAAA,CAAS,MAAwC;AAC/C,aAAO,OAAO,GAAS,CAAA;AAAA;IAGzB,SAAA,MAAe;AACb,iBAAW,KAAW,EACpB,CAAA,EAAA;AAEF,MAAA,EAAS,SAAS;AAAA;;GA+BX,KAAA,CACX,GACA,IAAwB,CAAA,MAExB,CAAQ,MAA4B;AAClC,QAAM,IAAY,SAAS,cAAc,KAAA;AACzC,EAAA,EAAU,YAAY,EAAS,KAAA;AAE/B,QAAM,IAAK,EAAU;AACrB,MAAI,CAAC,EACH,OAAM,IAAI,MAAM,2DAAA;AAKlB,MAAI,EAAU,oBAAoB,EAChC,OAAM,IAAI,MACR,sEAAsE,EAAU,iBAAA,GAAkB;AAItG,QAAM,EAAE,QAAA,IAAS,KAAA,IAAS;AAK1B,MAAI,EAAG,aAAa,GAAG,CAAA,MAAO,KAAU,EAAG,aAAa,GAAG,CAAA,KAAO,GAAO;AACvE,UAAM,IAAY,EAAG,aAAa,GAAG,CAAA,MAAO,IAAS,QAAQ;AAC7D,UAAM,IAAI,MACR,kDAAkD,CAAA,IAAU,CAAA,wBAC9C,CAAA,IAAU,CAAA,kCAAU;AAAA;AAItC,SAAO,GAAM,GAAI,GAAS,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-cPoOHFLY.js","names":[],"sources":["../src/plugin/registry.ts"],"sourcesContent":["/**\r\n * Global plugin registry for bQuery.\r\n *\r\n * Provides `use()` to register plugins and query helpers consumed by\r\n * other modules (e.g. the view module reads custom directives from here).\r\n *\r\n * @module bquery/plugin\r\n */\r\n\r\nimport { registerCustomDirectiveResolver } from '../view/custom-directives';\r\nimport type {\r\n BQueryPlugin,\r\n CustomDirective,\r\n CustomDirectiveHandler,\r\n PluginInstallContext,\r\n} from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal registries\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Set of installed plugin names — prevents double-install. */\r\nconst installedPlugins = new Set<string>();\r\n\r\n/** Custom directives contributed by plugins. */\r\nconst customDirectives = new Map<string, CustomDirectiveHandler>();\r\n\r\ntype PendingComponentRegistration = {\r\n tagName: string;\r\n constructor: CustomElementConstructor;\r\n options?: ElementDefinitionOptions;\r\n};\r\n\r\nregisterCustomDirectiveResolver((name) => customDirectives.get(name));\r\n\r\n/**\r\n * Restore the directive registry to a previously captured snapshot.\r\n *\r\n * Used to roll back partial plugin installation when `install()` or staged\r\n * `customElements.define()` calls fail after directives were already registered.\r\n *\r\n * @internal\r\n */\r\nconst restoreDirectiveSnapshot = (\r\n directivesSnapshot: ReadonlyMap<string, CustomDirectiveHandler>\r\n): void => {\r\n customDirectives.clear();\r\n for (const [name, handler] of directivesSnapshot) {\r\n customDirectives.set(name, handler);\r\n }\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Install context factory\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Build the `PluginInstallContext` handed to each plugin's `install()`.\r\n * @internal\r\n */\r\nconst createInstallContext = (\r\n pendingComponents: PendingComponentRegistration[]\r\n): PluginInstallContext => ({\r\n directive(name: string, handler: CustomDirectiveHandler): void {\r\n if (typeof name !== 'string' || name.length === 0) {\r\n throw new Error('bQuery plugin directive: name must be a non-empty string');\r\n }\r\n if (name.startsWith('bq-')) {\r\n const suggestedName = name.slice(3);\r\n throw new Error(\r\n `bQuery plugin directive: name \"${name}\" must be provided without the \"bq-\" prefix` +\r\n (suggestedName ? ` (use \"${suggestedName}\")` : '')\r\n );\r\n }\r\n if (typeof handler !== 'function') {\r\n throw new Error(`bQuery plugin directive: handler for \"${name}\" must be a function`);\r\n }\r\n if (customDirectives.has(name)) {\r\n throw new Error(`bQuery plugin directive: a directive named \"${name}\" is already registered`);\r\n }\r\n customDirectives.set(name, handler);\r\n },\r\n\r\n component(\r\n tagName: string,\r\n constructor: CustomElementConstructor,\r\n options?: ElementDefinitionOptions\r\n ): void {\r\n if (typeof tagName !== 'string' || tagName.length === 0) {\r\n throw new Error('bQuery plugin component: tagName must be a non-empty string');\r\n }\r\n if (!tagName.includes('-')) {\r\n throw new Error(\r\n `bQuery plugin component: tagName \"${tagName}\" must be a valid custom element name containing a hyphen`\r\n );\r\n }\r\n if (typeof constructor !== 'function') {\r\n throw new Error(`bQuery plugin component: constructor for \"${tagName}\" must be a function`);\r\n }\r\n if (typeof customElements === 'undefined') {\r\n if (typeof console !== 'undefined' && typeof console.warn === 'function') {\r\n console.warn(\r\n `[bQuery] plugin component \"${tagName}\" was not registered because customElements is not available in this environment.`\r\n );\r\n }\r\n return;\r\n }\r\n // Idempotent — skip if already defined or already staged during this install\r\n if (\r\n !customElements.get(tagName) &&\r\n !pendingComponents.some((entry) => entry.tagName === tagName)\r\n ) {\r\n pendingComponents.push({ tagName, constructor, options });\r\n }\r\n },\r\n});\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Register a bQuery plugin.\r\n *\r\n * Plugins are installed at most once (identified by `plugin.name`).\r\n * Duplicate calls with the same name are silently ignored.\r\n *\r\n * @param plugin - The plugin object implementing `{ name, install }`.\r\n * @param options - Optional configuration forwarded to `plugin.install()`.\r\n * @throws If `plugin` is not a valid plugin object.\r\n *\r\n * @example\r\n * ```ts\r\n * import { use } from '@bquery/bquery/plugin';\r\n *\r\n * use({\r\n * name: 'highlight',\r\n * install(ctx) {\r\n * ctx.directive('highlight', (el, expr) => {\r\n * (el as HTMLElement).style.background = String(expr);\r\n * });\r\n * },\r\n * });\r\n * ```\r\n */\r\nexport const use = <TOptions = unknown>(\r\n plugin: BQueryPlugin<TOptions>,\r\n options?: TOptions\r\n): void => {\r\n if (!plugin || typeof plugin !== 'object') {\r\n throw new Error('bQuery plugin: use() expects a plugin object with { name, install }');\r\n }\r\n if (typeof plugin.name !== 'string' || plugin.name.length === 0) {\r\n throw new Error('bQuery plugin: plugin must have a non-empty \"name\" property');\r\n }\r\n if (typeof plugin.install !== 'function') {\r\n throw new Error(`bQuery plugin: plugin \"${plugin.name}\" must have an \"install\" function`);\r\n }\r\n\r\n // Deduplicate\r\n if (installedPlugins.has(plugin.name)) return;\r\n\r\n const pendingComponents: PendingComponentRegistration[] = [];\r\n const ctx = createInstallContext(pendingComponents);\r\n const directivesSnapshot = new Map(customDirectives);\r\n\r\n try {\r\n plugin.install(ctx, options);\r\n } catch (error) {\r\n restoreDirectiveSnapshot(directivesSnapshot);\r\n throw error;\r\n }\r\n\r\n try {\r\n for (const entry of pendingComponents) {\r\n if (!customElements.get(entry.tagName)) {\r\n customElements.define(entry.tagName, entry.constructor, entry.options);\r\n }\r\n }\r\n } catch (error) {\r\n restoreDirectiveSnapshot(directivesSnapshot);\r\n throw error;\r\n }\r\n\r\n installedPlugins.add(plugin.name);\r\n};\r\n\r\n/**\r\n * Check whether a plugin with the given name has been installed.\r\n *\r\n * @param name - The plugin name to check.\r\n * @returns `true` if the plugin was previously installed via `use()`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { isInstalled } from '@bquery/bquery/plugin';\r\n *\r\n * if (!isInstalled('my-plugin')) {\r\n * use(myPlugin);\r\n * }\r\n * ```\r\n */\r\nexport const isInstalled = (name: string): boolean => installedPlugins.has(name);\r\n\r\n/**\r\n * Return a read-only snapshot of all installed plugin names.\r\n *\r\n * @returns Array of plugin name strings.\r\n *\r\n * @example\r\n * ```ts\r\n * import { getInstalledPlugins } from '@bquery/bquery/plugin';\r\n * console.log(getInstalledPlugins()); // ['my-plugin', 'other-plugin']\r\n * ```\r\n */\r\nexport const getInstalledPlugins = (): readonly string[] => [...installedPlugins];\r\n\r\n/**\r\n * Retrieve the handler for a custom directive registered by a plugin.\r\n *\r\n * This is used internally by the view module's `processElement` to\r\n * resolve directives that aren't built-in.\r\n *\r\n * @param name - Directive name **without** prefix (e.g. `'tooltip'`).\r\n * @returns The handler, or `undefined` if none is registered.\r\n *\r\n * @example\r\n * ```ts\r\n * import { getCustomDirective } from '@bquery/bquery/plugin';\r\n * const handler = getCustomDirective('tooltip');\r\n * ```\r\n */\r\nexport const getCustomDirective = (name: string): CustomDirectiveHandler | undefined =>\r\n customDirectives.get(name);\r\n\r\n/**\r\n * Return a read-only snapshot of all registered custom directives.\r\n *\r\n * @returns Array of `{ name, handler }` descriptors.\r\n *\r\n * @example\r\n * ```ts\r\n * import { getCustomDirectives } from '@bquery/bquery/plugin';\r\n * for (const { name, handler } of getCustomDirectives()) {\r\n * console.log(`Directive: bq-${name}`);\r\n * }\r\n * ```\r\n */\r\nexport const getCustomDirectives = (): readonly CustomDirective[] =>\r\n [...customDirectives.entries()].map(([name, handler]) => ({ name, handler }));\r\n\r\n/**\r\n * Reset all plugin registrations.\r\n *\r\n * Clears all installed plugins and custom directives.\r\n *\r\n * This utility is primarily intended for tests and other isolated environments\r\n * that need to reinitialize plugin state between runs.\r\n *\r\n * @example\r\n * ```ts\r\n * import { resetPlugins } from '@bquery/bquery/plugin';\r\n * afterEach(() => resetPlugins());\r\n * ```\r\n */\r\nexport const resetPlugins = (): void => {\r\n installedPlugins.clear();\r\n customDirectives.clear();\r\n};\r\n"],"mappings":";AAsBA,IAAM,IAAmB,oBAAI,IAAA,GAGvB,IAAmB,oBAAI,IAAA;AAQ7B,EAAA,CAAiC,MAAS,EAAiB,IAAI,CAAA,CAAK;AAUpE,IAAM,IAAA,CACJ,MACS;AACT,EAAA,EAAiB,MAAA;AACjB,aAAW,CAAC,GAAM,CAAA,KAAY,EAC5B,CAAA,EAAiB,IAAI,GAAM,CAAA;GAYzB,IAAA,CACJ,OAC0B;AAAA,EAC1B,UAAU,GAAc,GAAuC;AAC7D,QAAI,OAAO,KAAS,YAAY,EAAK,WAAW,EAC9C,OAAM,IAAI,MAAM,0DAAA;AAElB,QAAI,EAAK,WAAW,KAAA,GAAQ;AAC1B,YAAM,IAAgB,EAAK,MAAM,CAAA;AACjC,YAAM,IAAI,MACR,kCAAkC,CAAA,iDAC/B,IAAgB,UAAU,CAAA,OAAoB,GAAA;AAAA;AAGrD,QAAI,OAAO,KAAY,WACrB,OAAM,IAAI,MAAM,yCAAyC,CAAA,sBAAK;AAEhE,QAAI,EAAiB,IAAI,CAAA,EACvB,OAAM,IAAI,MAAM,+CAA+C,CAAA,yBAAK;AAEtE,IAAA,EAAiB,IAAI,GAAM,CAAA;AAAA;EAG7B,UACE,GACA,GACA,GACM;AACN,QAAI,OAAO,KAAY,YAAY,EAAQ,WAAW,EACpD,OAAM,IAAI,MAAM,6DAAA;AAElB,QAAI,CAAC,EAAQ,SAAS,GAAA,EACpB,OAAM,IAAI,MACR,qCAAqC,CAAA,2DAAQ;AAGjD,QAAI,OAAO,KAAgB,WACzB,OAAM,IAAI,MAAM,6CAA6C,CAAA,sBAAQ;AAEvE,QAAI,OAAO,iBAAmB,KAAa;AACzC,MAAI,OAAO,UAAY,OAAe,OAAO,QAAQ,QAAS,cAC5D,QAAQ,KACN,8BAA8B,CAAA,mFAAQ;AAG1C;AAAA;AAGF,IACE,CAAC,eAAe,IAAI,CAAA,KACpB,CAAC,EAAkB,KAAA,CAAM,MAAU,EAAM,YAAY,CAAA,KAErD,EAAkB,KAAK;AAAA,MAAE,SAAA;AAAA,MAAS,aAAA;AAAA,MAAa,SAAA;AAAA,KAAS;AAAA;IAiCjD,IAAA,CACX,GACA,MACS;AACT,MAAI,CAAC,KAAU,OAAO,KAAW,SAC/B,OAAM,IAAI,MAAM,qEAAA;AAElB,MAAI,OAAO,EAAO,QAAS,YAAY,EAAO,KAAK,WAAW,EAC5D,OAAM,IAAI,MAAM,6DAAA;AAElB,MAAI,OAAO,EAAO,WAAY,WAC5B,OAAM,IAAI,MAAM,0BAA0B,EAAO,IAAA,mCAAK;AAIxD,MAAI,EAAiB,IAAI,EAAO,IAAA,EAAO;AAEvC,QAAM,IAAoD,CAAA,GACpD,IAAM,EAAqB,CAAA,GAC3B,IAAqB,IAAI,IAAI,CAAA;AAEnC,MAAI;AACF,IAAA,EAAO,QAAQ,GAAK,CAAA;AAAA,WACb,GAAO;AACd,UAAA,EAAyB,CAAA,GACnB;AAAA;AAGR,MAAI;AACF,eAAW,KAAS,EAClB,CAAK,eAAe,IAAI,EAAM,OAAA,KAC5B,eAAe,OAAO,EAAM,SAAS,EAAM,aAAa,EAAM,OAAA;AAAA,WAG3D,GAAO;AACd,UAAA,EAAyB,CAAA,GACnB;AAAA;AAGR,EAAA,EAAiB,IAAI,EAAO,IAAA;GAkBjB,IAAA,CAAe,MAA0B,EAAiB,IAAI,CAAA,GAa9D,IAAA,MAA+C,CAAC,GAAG,CAAA,GAiBnD,IAAA,CAAsB,MACjC,EAAiB,IAAI,CAAA,GAeV,IAAA,MACX,CAAC,GAAG,EAAiB,QAAA,CAAS,EAAE,IAAA,CAAK,CAAC,GAAM,CAAA,OAAc;AAAA,EAAE,MAAA;AAAA,EAAM,SAAA;EAAS,GAgBhE,IAAA,MAA2B;AACtC,EAAA,EAAiB,MAAA,GACjB,EAAiB,MAAA"}
@@ -1,233 +0,0 @@
1
- import { a as R } from "./object-BCk-1c8T.js";
2
- import { i as E, n as v, o as q, r as g, t as k } from "./core-DnlyjbF2.js";
3
- import { n as U } from "./config-BW35FKuA.js";
4
- import { n as B, r as b, t as S } from "./untrack-DJVQQ2WM.js";
5
- var F = (e) => {
6
- E();
7
- try {
8
- e();
9
- } finally {
10
- q();
11
- }
12
- }, I = (e) => {
13
- if (e instanceof Error) return e;
14
- if (typeof e == "string") return new Error(e);
15
- try {
16
- return new Error(JSON.stringify(e));
17
- } catch {
18
- return new Error(String(e));
19
- }
20
- }, O = (e) => typeof e == "function" ? e() : e.value, p = (...e) => {
21
- const t = new Headers();
22
- for (const a of e)
23
- a && new Headers(a).forEach((r, s) => {
24
- t.set(s, r);
25
- });
26
- return t;
27
- }, x = (e) => typeof e == "string" || e instanceof Blob || e instanceof FormData || e instanceof URLSearchParams || typeof ArrayBuffer < "u" && e instanceof ArrayBuffer || typeof ReadableStream < "u" && e instanceof ReadableStream ? !0 : typeof e == "object" && e !== null && ArrayBuffer.isView(e), _ = (e, t) => e == null || x(e) ? e : (t.has("content-type") || t.set("content-type", "application/json"), JSON.stringify(e)), L = (e) => typeof e == "function" ? e() : e, A = (e, t) => {
28
- for (const [a, r] of Object.entries(t))
29
- if (r != null) {
30
- if (Array.isArray(r)) {
31
- for (const s of r) s != null && e.searchParams.append(a, String(s));
32
- continue;
33
- }
34
- e.searchParams.set(a, String(r));
35
- }
36
- }, M = (e, t) => {
37
- const a = typeof window < "u" && /^https?:/i.test(window.location.href) ? window.location.href : "http://localhost", r = t ? new URL(t, a).toString() : a;
38
- return e instanceof URL ? new URL(e.toString(), r) : new URL(e, r);
39
- }, j = async (e, t) => {
40
- if (t === "response") return e;
41
- if (t === "text") return await e.text();
42
- if (t === "blob") return await e.blob();
43
- if (t === "arrayBuffer") return await e.arrayBuffer();
44
- if (t === "formData") return await e.formData();
45
- const a = await e.text();
46
- if (a)
47
- try {
48
- return JSON.parse(a);
49
- } catch (r) {
50
- const s = e.url ? ` for ${e.url}` : "";
51
- throw new Error(`Failed to parse JSON response${s} (status ${e.status}): ${r instanceof Error ? r.message : String(r)}`);
52
- }
53
- }, w = (e) => {
54
- const t = e?.trim();
55
- return t ? t.toUpperCase() : void 0;
56
- }, D = (e, t, a) => {
57
- const r = t instanceof Request ? w(t.method) : void 0;
58
- return e ?? r ?? (a ? "POST" : void 0);
59
- }, P = (e, t, a) => e || (t instanceof Request ? void 0 : a), T = (e) => {
60
- const t = w(e.method);
61
- let a;
62
- if (t !== "GET" && t !== "HEAD" && !e.bodyUsed) try {
63
- a = e.clone().body ?? void 0;
64
- } catch {
65
- a = void 0;
66
- }
67
- return {
68
- method: t,
69
- headers: e.headers,
70
- body: a,
71
- cache: e.cache,
72
- credentials: e.credentials,
73
- integrity: e.integrity,
74
- keepalive: e.keepalive,
75
- mode: e.mode,
76
- redirect: e.redirect,
77
- referrer: e.referrer,
78
- referrerPolicy: e.referrerPolicy,
79
- signal: e.signal
80
- };
81
- }, V = (e, t = {}) => {
82
- const a = t.immediate ?? !0, r = v(t.defaultValue), s = v(null), n = v("idle"), o = b(() => n.value === "pending");
83
- let c = 0, f = !1, y = () => {
84
- };
85
- const h = () => {
86
- c += 1, r.value = t.defaultValue, s.value = null, n.value = "idle";
87
- }, m = () => {
88
- f || (f = !0, c += 1, y());
89
- }, d = async () => {
90
- if (f) return r.peek();
91
- const i = ++c;
92
- n.value = "pending", s.value = null;
93
- try {
94
- const l = await e(), u = t.transform ? t.transform(l) : l;
95
- return f || i !== c ? r.peek() : (r.value = u, n.value = "success", t.onSuccess?.(u), u);
96
- } catch (l) {
97
- const u = I(l);
98
- return f || i !== c || (s.value = u, n.value = "error", t.onError?.(u)), r.peek();
99
- }
100
- };
101
- if (t.watch?.length) {
102
- let i = !1;
103
- y = g(() => {
104
- for (const l of t.watch ?? []) O(l);
105
- if (!i) {
106
- i = !0, a && S(() => d());
107
- return;
108
- }
109
- S(() => d());
110
- });
111
- } else a && d();
112
- return {
113
- data: r,
114
- error: s,
115
- status: n,
116
- pending: o,
117
- execute: d,
118
- refresh: d,
119
- clear: h,
120
- dispose: m
121
- };
122
- }, $ = (e, t = {}) => {
123
- const a = U().fetch, r = t.parseAs ?? a?.parseAs ?? "json", s = t.fetcher ?? fetch;
124
- return V(async () => {
125
- const n = L(e), o = typeof n == "string" || n instanceof URL ? M(n, t.baseUrl ?? a?.baseUrl) : n instanceof Request && t.query ? new URL(n.url) : null;
126
- o && t.query && A(o, t.query);
127
- const c = p(a?.headers, n instanceof Request ? n.headers : void 0, t.headers), f = t.body != null, y = w(t.method), h = D(y, n, f), m = h === "GET" || h === "HEAD" ? h : null;
128
- if (f && m) throw new Error(`Cannot send a request body with ${m} requests`);
129
- const d = P(y, n, h), i = {
130
- ...t,
131
- method: d,
132
- headers: c,
133
- body: _(t.body, c)
134
- };
135
- delete i.baseUrl, delete i.query, delete i.parseAs, delete i.fetcher, delete i.defaultValue, delete i.immediate, delete i.watch, delete i.transform, delete i.onSuccess, delete i.onError;
136
- let l = o ?? n;
137
- n instanceof Request && o && o.toString() !== n.url && (l = new Request(o.toString(), T(n)));
138
- const u = await s(l, i);
139
- if (!u.ok) throw Object.assign(/* @__PURE__ */ new Error(`Request failed with status ${u.status}`), {
140
- response: u,
141
- status: u.status,
142
- statusText: u.statusText
143
- });
144
- return j(u, r);
145
- }, t);
146
- };
147
- function H(e = {}) {
148
- return (t, a = {}) => {
149
- const r = e, s = R({}, r.query ?? {}, a.query ?? {});
150
- return $(t, {
151
- ...r,
152
- ...a,
153
- headers: p(r.headers, a.headers),
154
- query: Object.keys(s).length > 0 ? s : void 0
155
- });
156
- };
157
- }
158
- var G = (e, t) => {
159
- const a = b(e);
160
- return {
161
- get value() {
162
- return a.value;
163
- },
164
- set value(r) {
165
- t(r);
166
- },
167
- peek() {
168
- return a.peek();
169
- }
170
- };
171
- }, Q = (e, t) => {
172
- let a = !1, r = null;
173
- try {
174
- if (r = globalThis.localStorage, r) {
175
- const o = `__bquery_test_${Math.random().toString(36).slice(2, 9)}__`, c = "__test__";
176
- try {
177
- r.setItem(o, c), r.getItem(o), a = !0;
178
- } finally {
179
- try {
180
- r.removeItem(o);
181
- } catch {
182
- }
183
- }
184
- }
185
- } catch {
186
- a = !1;
187
- }
188
- let s = t;
189
- if (a && r) try {
190
- const o = r.getItem(e);
191
- o !== null && (s = JSON.parse(o));
192
- } catch {
193
- }
194
- const n = v(s);
195
- return a && r && g(() => {
196
- try {
197
- r.setItem(e, JSON.stringify(n.value));
198
- } catch {
199
- }
200
- }), n;
201
- }, W = (e) => ({
202
- get value() {
203
- return e.value;
204
- },
205
- peek() {
206
- return e.peek();
207
- }
208
- }), K = (e) => e instanceof k, X = (e) => e instanceof B, Y = (e, t, a = {}) => {
209
- const { immediate: r = !1, equals: s = Object.is } = a;
210
- let n, o = !0;
211
- return g(() => {
212
- const c = e.value;
213
- if (o) {
214
- o = !1, n = c, r && t(c, void 0);
215
- return;
216
- }
217
- s(c, n) || (t(c, n), n = c);
218
- });
219
- };
220
- export {
221
- Q as a,
222
- V as c,
223
- W as i,
224
- $ as l,
225
- X as n,
226
- G as o,
227
- K as r,
228
- H as s,
229
- Y as t,
230
- F as u
231
- };
232
-
233
- //# sourceMappingURL=reactive-Cfv0RK6x.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reactive-Cfv0RK6x.js","names":[],"sources":["../src/reactive/batch.ts","../src/reactive/async-data.ts","../src/reactive/linked.ts","../src/reactive/persisted.ts","../src/reactive/readonly.ts","../src/reactive/type-guards.ts","../src/reactive/watch.ts"],"sourcesContent":["/**\n * Batched reactive updates.\n */\n\nimport { beginBatch, endBatch } from './internals';\n\n/**\n * Batches multiple signal updates into a single notification cycle.\n *\n * Updates made inside the batch function are deferred until the batch\n * completes, preventing intermediate re-renders and improving performance.\n *\n * @param fn - Function containing multiple signal updates\n */\nexport const batch = (fn: () => void): void => {\n beginBatch();\n try {\n fn();\n } finally {\n endBatch();\n }\n};\n","/**\n * Async data and fetch composables built on bQuery signals.\n *\n * @module bquery/reactive\n */\n\nimport { merge } from '../core/utils/object';\nimport { getBqueryConfig, type BqueryFetchParseAs } from '../platform/config';\nimport { computed } from './computed';\nimport { effect } from './effect';\nimport { Signal, signal } from './core';\nimport { untrack } from './untrack';\n\n/** Allowed status values for async composables. */\nexport type AsyncDataStatus = 'idle' | 'pending' | 'success' | 'error';\n\n/** Reactive source types that can trigger refreshes. */\nexport type AsyncWatchSource = (() => unknown) | { value: unknown };\n\n/** Options shared by async composables. */\nexport interface UseAsyncDataOptions<TResult, TData = TResult> {\n /** Run the handler immediately (default: true). */\n immediate?: boolean;\n /** Default data value before the first successful execution. */\n defaultValue?: TData;\n /** Optional reactive sources that trigger refreshes when they change. */\n watch?: AsyncWatchSource[];\n /** Transform the resolved value before storing it. */\n transform?: (value: TResult) => TData;\n /** Called after a successful execution. */\n onSuccess?: (value: TData) => void;\n /** Called after a failed execution. */\n onError?: (error: Error) => void;\n}\n\n/** Return value of useAsyncData() and useFetch(). */\nexport interface AsyncDataState<TData> {\n /** Reactive data signal. */\n data: Signal<TData | undefined>;\n /** Last error encountered by the composable. */\n error: Signal<Error | null>;\n /** Current lifecycle status. */\n status: Signal<AsyncDataStatus>;\n /** Computed boolean that mirrors `status === 'pending'`. */\n pending: { readonly value: boolean; peek(): boolean };\n /** Execute the handler manually. Returns the cached data value when called after dispose(). */\n execute: () => Promise<TData | undefined>;\n /** Alias for execute(). */\n refresh: () => Promise<TData | undefined>;\n /** Clear data, error, and status back to the initial state. */\n clear: () => void;\n /** Dispose reactive watchers and prevent future executions. */\n dispose: () => void;\n}\n\n/** Options for useFetch(). */\nexport interface UseFetchOptions<TResponse = unknown, TData = TResponse>\n extends UseAsyncDataOptions<TResponse, TData>, Omit<RequestInit, 'body' | 'headers'> {\n /** Base URL prepended to relative URLs. */\n baseUrl?: string;\n /** Query parameters appended to the request URL. */\n query?: Record<string, unknown>;\n /** Request headers. */\n headers?: HeadersInit;\n /** Request body, including plain objects for JSON requests. */\n body?: BodyInit | Record<string, unknown> | unknown[] | null;\n /** Override the parser used for the response body. */\n parseAs?: BqueryFetchParseAs;\n /** Custom fetch implementation for testing or adapters. */\n fetcher?: typeof fetch;\n}\n\n/** Input accepted by useFetch(). */\nexport type FetchInput = string | URL | Request | (() => string | URL | Request);\n\nconst normalizeError = (error: unknown): Error => {\n if (error instanceof Error) return error;\n if (typeof error === 'string') {\n return new Error(error);\n }\n\n try {\n return new Error(JSON.stringify(error));\n } catch {\n return new Error(String(error));\n }\n};\n\nconst readWatchSource = (source: AsyncWatchSource): unknown => {\n if (typeof source === 'function') {\n return source();\n }\n return source.value;\n};\n\nconst toHeaders = (...sources: Array<HeadersInit | undefined>): Headers => {\n const headers = new Headers();\n for (const source of sources) {\n if (!source) continue;\n new Headers(source).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n return headers;\n};\n\nconst isBodyLike = (value: unknown): value is BodyInit => {\n if (typeof value === 'string') return true;\n if (value instanceof Blob || value instanceof FormData || value instanceof URLSearchParams) {\n return true;\n }\n if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) return true;\n if (typeof ReadableStream !== 'undefined' && value instanceof ReadableStream) return true;\n return typeof value === 'object' && value !== null && ArrayBuffer.isView(value);\n};\n\nconst serializeBody = (\n body: UseFetchOptions['body'],\n headers: Headers\n): BodyInit | null | undefined => {\n if (body == null) return body;\n if (isBodyLike(body)) return body;\n\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n\n return JSON.stringify(body);\n};\n\nconst resolveInput = (input: FetchInput): string | URL | Request => {\n return typeof input === 'function' ? input() : input;\n};\n\nconst appendQuery = (url: URL, query: Record<string, unknown>): void => {\n for (const [key, value] of Object.entries(query)) {\n if (value == null) continue;\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item != null) {\n url.searchParams.append(key, String(item));\n }\n }\n continue;\n }\n\n url.searchParams.set(key, String(value));\n }\n};\n\nconst toUrl = (input: string | URL, baseUrl?: string): URL => {\n const runtimeBase =\n typeof window !== 'undefined' && /^https?:/i.test(window.location.href)\n ? window.location.href\n : 'http://localhost';\n const base = baseUrl ? new URL(baseUrl, runtimeBase).toString() : runtimeBase;\n return input instanceof URL ? new URL(input.toString(), base) : new URL(input, base);\n};\n\nconst parseResponse = async <TResponse>(\n response: Response,\n parseAs: BqueryFetchParseAs\n): Promise<TResponse> => {\n if (parseAs === 'response') return response as TResponse;\n if (parseAs === 'text') return (await response.text()) as TResponse;\n if (parseAs === 'blob') return (await response.blob()) as TResponse;\n if (parseAs === 'arrayBuffer') return (await response.arrayBuffer()) as TResponse;\n if (parseAs === 'formData') return (await response.formData()) as TResponse;\n\n const text = await response.text();\n if (!text) {\n return undefined as TResponse;\n }\n\n try {\n return JSON.parse(text) as TResponse;\n } catch (error) {\n const detail = response.url ? ` for ${response.url}` : '';\n throw new Error(\n `Failed to parse JSON response${detail} (status ${response.status}): ${error instanceof Error ? error.message : String(error)}`\n );\n }\n};\n\nconst normalizeMethod = (method?: string): string | undefined => {\n const normalized = method?.trim();\n return normalized ? normalized.toUpperCase() : undefined;\n};\n\nconst resolveMethod = (\n explicitMethod: string | undefined,\n requestInput: string | URL | Request,\n bodyProvided: boolean\n): string | undefined => {\n const requestMethod =\n requestInput instanceof Request ? normalizeMethod(requestInput.method) : undefined;\n return explicitMethod ?? requestMethod ?? (bodyProvided ? 'POST' : undefined);\n};\n\nconst resolveRequestInitMethod = (\n explicitMethod: string | undefined,\n requestInput: string | URL | Request,\n method: string | undefined\n): string | undefined => {\n if (explicitMethod) return explicitMethod;\n return requestInput instanceof Request ? undefined : method;\n};\n\nconst toRequestInit = (request: Request): RequestInit => {\n const requestMethod = normalizeMethod(request.method);\n let body: BodyInit | undefined;\n if (requestMethod !== 'GET' && requestMethod !== 'HEAD' && !request.bodyUsed) {\n try {\n body = request.clone().body ?? undefined;\n } catch {\n body = undefined;\n }\n }\n\n return {\n method: requestMethod,\n headers: request.headers,\n body,\n cache: request.cache,\n credentials: request.credentials,\n integrity: request.integrity,\n keepalive: request.keepalive,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n };\n};\n\n/**\n * Create a reactive wrapper around an async resolver.\n *\n * @template TResult - Raw result type returned by the handler\n * @template TData - Stored data type after optional transformation\n * @param handler - Async function to execute\n * @param options - Execution, transform, and refresh options\n * @returns Reactive data state with execute(), refresh(), and clear()\n *\n * @example\n * ```ts\n * const user = useAsyncData(() => fetch('/api/user').then((res) => res.json()));\n * ```\n */\nexport const useAsyncData = <TResult, TData = TResult>(\n handler: () => Promise<TResult>,\n options: UseAsyncDataOptions<TResult, TData> = {}\n): AsyncDataState<TData> => {\n const immediate = options.immediate ?? true;\n const data = signal<TData | undefined>(options.defaultValue);\n const error = signal<Error | null>(null);\n const status = signal<AsyncDataStatus>('idle');\n const pending = computed(() => status.value === 'pending');\n let executionId = 0;\n let disposed = false;\n let stopWatching = (): void => {};\n\n const clear = (): void => {\n executionId += 1;\n data.value = options.defaultValue;\n error.value = null;\n status.value = 'idle';\n };\n\n const dispose = (): void => {\n if (disposed) return;\n disposed = true;\n executionId += 1;\n stopWatching();\n };\n\n const execute = async (): Promise<TData | undefined> => {\n if (disposed) {\n return data.peek();\n }\n\n const currentExecution = ++executionId;\n status.value = 'pending';\n error.value = null;\n\n try {\n const resolved = await handler();\n const transformed = options.transform\n ? options.transform(resolved)\n : (resolved as unknown as TData);\n\n if (disposed || currentExecution !== executionId) {\n return data.peek();\n }\n\n data.value = transformed;\n status.value = 'success';\n options.onSuccess?.(transformed);\n return transformed;\n } catch (caught) {\n const normalizedError = normalizeError(caught);\n\n if (disposed || currentExecution !== executionId) {\n return data.peek();\n }\n\n error.value = normalizedError;\n status.value = 'error';\n options.onError?.(normalizedError);\n return data.peek();\n }\n };\n\n if (options.watch?.length) {\n let initialized = false;\n stopWatching = effect(() => {\n for (const source of options.watch ?? []) {\n readWatchSource(source);\n }\n\n if (!initialized) {\n initialized = true;\n if (immediate) {\n void untrack(() => execute());\n }\n return;\n }\n\n void untrack(() => execute());\n });\n } else if (immediate) {\n void execute();\n }\n\n return {\n data,\n error,\n status,\n pending,\n execute,\n refresh: execute,\n clear,\n dispose,\n };\n};\n\n/**\n * Reactive fetch composable using the browser Fetch API.\n *\n * @template TResponse - Raw parsed response type\n * @template TData - Stored response type after optional transformation\n * @param input - Request URL, Request object, or lazy input factory\n * @param options - Request and reactive state options\n * @returns Reactive fetch state with execute(), refresh(), and clear()\n *\n * @example\n * ```ts\n * const users = useFetch<{ id: number; name: string }[]>('/api/users');\n * ```\n */\nexport const useFetch = <TResponse = unknown, TData = TResponse>(\n input: FetchInput,\n options: UseFetchOptions<TResponse, TData> = {}\n): AsyncDataState<TData> => {\n const fetchConfig = getBqueryConfig().fetch;\n const parseAs = options.parseAs ?? fetchConfig?.parseAs ?? 'json';\n const fetcher = options.fetcher ?? fetch;\n\n return useAsyncData<TResponse, TData>(async () => {\n const requestInput = resolveInput(input);\n const requestUrl =\n typeof requestInput === 'string' || requestInput instanceof URL\n ? toUrl(requestInput, options.baseUrl ?? fetchConfig?.baseUrl)\n : requestInput instanceof Request && options.query\n ? new URL(requestInput.url)\n : null;\n\n if (requestUrl && options.query) {\n appendQuery(requestUrl, options.query);\n }\n\n const headers = toHeaders(\n fetchConfig?.headers,\n requestInput instanceof Request ? requestInput.headers : undefined,\n options.headers\n );\n const bodyProvided = options.body != null;\n const explicitMethod = normalizeMethod(options.method);\n const method = resolveMethod(explicitMethod, requestInput, bodyProvided);\n const bodylessMethod = method === 'GET' || method === 'HEAD' ? method : null;\n if (bodyProvided && bodylessMethod) {\n throw new Error(`Cannot send a request body with ${bodylessMethod} requests`);\n }\n const requestInitMethod = resolveRequestInitMethod(explicitMethod, requestInput, method);\n const requestInit: RequestInit = {\n ...options,\n method: requestInitMethod,\n headers,\n body: serializeBody(options.body, headers),\n };\n\n delete (requestInit as Partial<UseFetchOptions>).baseUrl;\n delete (requestInit as Partial<UseFetchOptions>).query;\n delete (requestInit as Partial<UseFetchOptions>).parseAs;\n delete (requestInit as Partial<UseFetchOptions>).fetcher;\n delete (requestInit as Partial<UseFetchOptions>).defaultValue;\n delete (requestInit as Partial<UseFetchOptions>).immediate;\n delete (requestInit as Partial<UseFetchOptions>).watch;\n delete (requestInit as Partial<UseFetchOptions>).transform;\n delete (requestInit as Partial<UseFetchOptions>).onSuccess;\n delete (requestInit as Partial<UseFetchOptions>).onError;\n\n let requestTarget: Request | string | URL = requestUrl ?? requestInput;\n if (\n requestInput instanceof Request &&\n requestUrl &&\n requestUrl.toString() !== requestInput.url\n ) {\n // Rebuild Request inputs when query params changed so the updated URL is preserved.\n // String/URL inputs already use `requestUrl` directly, so only Request objects need rebuilding.\n requestTarget = new Request(requestUrl.toString(), toRequestInit(requestInput));\n }\n const response = await fetcher(requestTarget, requestInit);\n\n if (!response.ok) {\n throw Object.assign(new Error(`Request failed with status ${response.status}`), {\n response,\n status: response.status,\n statusText: response.statusText,\n });\n }\n\n return parseResponse<TResponse>(response, parseAs);\n }, options);\n};\n\n/**\n * Create a preconfigured useFetch() helper.\n *\n * @param defaults - Default request options merged into every useFetch() call\n * @returns A useFetch-compatible function with merged defaults\n *\n * @example\n * ```ts\n * const useApiFetch = createUseFetch({ baseUrl: 'https://api.example.com' });\n * const profile = useApiFetch('/profile');\n * ```\n */\n/** Overload for factories without a configured transform, preserving per-call `TResponse -> TData` inference. */\nexport function createUseFetch<TDefaultResponse = unknown>(\n defaults?: UseFetchOptions<TDefaultResponse, TDefaultResponse>\n): <TResponse = TDefaultResponse, TData = TResponse>(\n input: FetchInput,\n options?: UseFetchOptions<TResponse, TData>\n) => AsyncDataState<TData>;\n\n/** Overload for factories with a configured transform, preserving the transformed factory data type by default. */\nexport function createUseFetch<TDefaultResponse = unknown, TDefaultData = TDefaultResponse>(\n defaults: UseFetchOptions<TDefaultResponse, TDefaultData>\n): <TResponse = TDefaultResponse, TData = TDefaultData>(\n input: FetchInput,\n options?: UseFetchOptions<TResponse, TData>\n) => AsyncDataState<TData>;\n\nexport function createUseFetch<TDefaultResponse = unknown, TDefaultData = TDefaultResponse>(\n defaults: UseFetchOptions<TDefaultResponse, TDefaultData> = {}\n) {\n return <TResponse = TDefaultResponse, TData = TDefaultData>(\n input: FetchInput,\n options: UseFetchOptions<TResponse, TData> = {}\n ): AsyncDataState<TData> => {\n const resolvedDefaults = defaults as unknown as UseFetchOptions<TResponse, TData>;\n const mergedQuery = merge({}, resolvedDefaults.query ?? {}, options.query ?? {}) as Record<\n string,\n unknown\n >;\n\n return useFetch<TResponse, TData>(input, {\n ...resolvedDefaults,\n ...options,\n headers: toHeaders(resolvedDefaults.headers, options.headers),\n query: Object.keys(mergedQuery).length > 0 ? mergedQuery : undefined,\n });\n };\n}\n","/**\n * Linked (writable) computed helpers.\n */\n\nimport { computed, Computed } from './computed';\n\n/**\n * A writable computed-like signal.\n */\nexport interface LinkedSignal<T> {\n /** Gets or sets the current value with dependency tracking. */\n value: T;\n /** Gets the current value without dependency tracking. */\n peek(): T;\n}\n\n/**\n * Creates a writable computed signal by linking a getter and setter.\n *\n * @template T - The derived value type\n * @param getValue - Getter that derives the current value\n * @param setValue - Setter that writes back to underlying signals\n * @returns A writable computed-like signal\n *\n * @example\n * ```ts\n * const first = signal('Ada');\n * const last = signal('Lovelace');\n * const fullName = linkedSignal(\n * () => `${first.value} ${last.value}`,\n * (next) => {\n * const [a, b] = next.split(' ');\n * first.value = a ?? '';\n * last.value = b ?? '';\n * }\n * );\n * ```\n */\nexport const linkedSignal = <T>(\n getValue: () => T,\n setValue: (value: T) => void\n): LinkedSignal<T> => {\n const derived: Computed<T> = computed(getValue);\n\n return {\n get value(): T {\n return derived.value;\n },\n set value(next: T) {\n setValue(next);\n },\n peek(): T {\n return derived.peek();\n },\n };\n};\n","/**\n * LocalStorage-backed signals.\n */\n\nimport { signal, Signal } from './core';\nimport { effect } from './effect';\n\n/**\n * Creates a signal that persists to localStorage.\n *\n * @template T - The type of the signal value\n * @param key - The localStorage key\n * @param initialValue - The initial value if not found in storage\n * @returns A Signal that syncs with localStorage (falls back to in-memory if unavailable)\n */\nexport const persistedSignal = <T>(key: string, initialValue: T): Signal<T> => {\n // Check if localStorage is available and accessible\n let hasLocalStorage = false;\n let storage: Storage | null = null;\n\n try {\n // In Safari private mode, accessing localStorage can throw SecurityError\n storage = globalThis.localStorage;\n if (storage) {\n // Test actual access to ensure it's not just present but usable\n // Use a randomized test key to avoid overwriting real user data\n const testKey = `__bquery_test_${Math.random().toString(36).slice(2, 9)}__`;\n const testValue = '__test__';\n try {\n storage.setItem(testKey, testValue);\n storage.getItem(testKey);\n hasLocalStorage = true;\n } finally {\n // Ensure we don't leave any test data behind\n try {\n storage.removeItem(testKey);\n } catch {\n // Ignore cleanup errors (e.g., storage becoming unavailable)\n }\n }\n }\n } catch {\n // localStorage unavailable or access denied (Safari private mode, sandboxed iframes, etc.)\n hasLocalStorage = false;\n }\n\n let stored: T = initialValue;\n\n if (hasLocalStorage && storage) {\n try {\n const raw = storage.getItem(key);\n if (raw !== null) {\n stored = JSON.parse(raw) as T;\n }\n } catch {\n // Use initial value on parse error or access denial\n }\n }\n\n const sig = signal(stored);\n\n // Only set up persistence effect if localStorage is available\n if (hasLocalStorage && storage) {\n effect(() => {\n try {\n storage!.setItem(key, JSON.stringify(sig.value));\n } catch {\n // Ignore storage errors (quota exceeded, sandboxed iframes, etc.)\n }\n });\n }\n\n return sig;\n};\n","/**\n * Read-only signal wrappers.\n */\n\nimport type { Signal } from './core';\n\n/**\n * A readonly wrapper around a signal that prevents writes.\n * Provides read-only access to a signal's value while maintaining reactivity.\n *\n * @template T - The type of the wrapped value\n */\nexport interface ReadonlySignal<T> {\n /** Gets the current value with dependency tracking. */\n readonly value: T;\n /** Gets the current value without dependency tracking. */\n peek(): T;\n}\n\n/**\n * Creates a read-only view of a signal.\n * Useful for exposing reactive state without allowing modifications.\n *\n * @template T - The type of the signal value\n * @param sig - The signal to wrap\n * @returns A readonly signal wrapper\n */\nexport const readonly = <T>(sig: Signal<T>): ReadonlySignal<T> => ({\n get value(): T {\n return sig.value;\n },\n peek(): T {\n return sig.peek();\n },\n});\n","/**\n * Type guards for reactive primitives.\n */\n\nimport { Computed } from './computed';\nimport { Signal } from './core';\n\n/**\n * Type guard to check if a value is a Signal instance.\n *\n * @param value - The value to check\n * @returns True if the value is a Signal\n */\nexport const isSignal = (value: unknown): value is Signal<unknown> => value instanceof Signal;\n\n/**\n * Type guard to check if a value is a Computed instance.\n *\n * @param value - The value to check\n * @returns True if the value is a Computed\n */\nexport const isComputed = (value: unknown): value is Computed<unknown> => value instanceof Computed;\n","/**\n * Value watching helpers.\n */\n\nimport type { Computed } from './computed';\nimport type { Signal } from './core';\nimport type { CleanupFn } from './internals';\n\nimport { effect } from './effect';\n\n/**\n * Options for the watch function.\n */\nexport interface WatchOptions<T> {\n /** If true, the callback is invoked immediately with the current value. */\n immediate?: boolean;\n /** Custom equality function. Defaults to Object.is. */\n equals?: (a: T, b: T | undefined) => boolean;\n}\n\n/**\n * Watches a signal or computed value and calls a callback with old and new values.\n * Unlike effect, watch provides access to the previous value.\n * The callback is only invoked when the value actually changes (compared via Object.is or custom equals).\n *\n * @template T - The type of the watched value\n * @param source - The signal or computed to watch\n * @param callback - Function called with (newValue, oldValue) on changes\n * @param options - Watch options\n * @returns A cleanup function to stop watching\n *\n * @example\n * ```ts\n * const count = signal(0);\n * watch(count, (newVal, oldVal) => {\n * console.log(`Changed from ${oldVal} to ${newVal}`);\n * });\n *\n * // With custom equality for objects\n * const user = signal({ id: 1, name: 'Alice' });\n * watch(user, (newVal, oldVal) => { ... }, {\n * equals: (a, b) => a?.id === b?.id\n * });\n * ```\n */\nexport const watch = <T>(\n source: Signal<T> | Computed<T>,\n callback: (newValue: T, oldValue: T | undefined) => void,\n options: WatchOptions<T> = {}\n): CleanupFn => {\n const { immediate = false, equals = Object.is } = options;\n let oldValue: T | undefined;\n let isFirst = true;\n\n return effect(() => {\n const newValue = source.value;\n\n if (isFirst) {\n isFirst = false;\n oldValue = newValue;\n if (immediate) {\n callback(newValue, undefined);\n }\n return;\n }\n\n // Only call callback if value actually changed\n if (!equals(newValue, oldValue)) {\n callback(newValue, oldValue);\n oldValue = newValue;\n }\n });\n};\n"],"mappings":"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"}