@bquery/bquery 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/README.md +586 -527
  2. package/dist/component/component.d.ts +13 -5
  3. package/dist/component/component.d.ts.map +1 -1
  4. package/dist/component/html.d.ts +40 -3
  5. package/dist/component/html.d.ts.map +1 -1
  6. package/dist/component/index.d.ts +4 -2
  7. package/dist/component/index.d.ts.map +1 -1
  8. package/dist/component/library.d.ts +34 -0
  9. package/dist/component/library.d.ts.map +1 -0
  10. package/dist/component/types.d.ts +132 -13
  11. package/dist/component/types.d.ts.map +1 -1
  12. package/dist/component-BEQgt5hl.js +600 -0
  13. package/dist/component-BEQgt5hl.js.map +1 -0
  14. package/dist/component.es.mjs +7 -184
  15. package/dist/config-DRmZZno3.js +40 -0
  16. package/dist/config-DRmZZno3.js.map +1 -0
  17. package/dist/core-BGQJVw0-.js +35 -0
  18. package/dist/core-BGQJVw0-.js.map +1 -0
  19. package/dist/core-CCEabVHl.js +648 -0
  20. package/dist/core-CCEabVHl.js.map +1 -0
  21. package/dist/core.es.mjs +45 -1261
  22. package/dist/effect-AFRW_Plg.js +84 -0
  23. package/dist/effect-AFRW_Plg.js.map +1 -0
  24. package/dist/full.d.ts +8 -8
  25. package/dist/full.d.ts.map +1 -1
  26. package/dist/full.es.mjs +101 -91
  27. package/dist/full.iife.js +173 -3
  28. package/dist/full.iife.js.map +1 -1
  29. package/dist/full.umd.js +173 -3
  30. package/dist/full.umd.js.map +1 -1
  31. package/dist/index.es.mjs +147 -139
  32. package/dist/motion/transition.d.ts +1 -1
  33. package/dist/motion/transition.d.ts.map +1 -1
  34. package/dist/motion/types.d.ts +11 -1
  35. package/dist/motion/types.d.ts.map +1 -1
  36. package/dist/motion-D9TcHxOF.js +415 -0
  37. package/dist/motion-D9TcHxOF.js.map +1 -0
  38. package/dist/motion.es.mjs +25 -361
  39. package/dist/object-qGpWr6-J.js +38 -0
  40. package/dist/object-qGpWr6-J.js.map +1 -0
  41. package/dist/platform/announcer.d.ts +59 -0
  42. package/dist/platform/announcer.d.ts.map +1 -0
  43. package/dist/platform/config.d.ts +92 -0
  44. package/dist/platform/config.d.ts.map +1 -0
  45. package/dist/platform/cookies.d.ts +45 -0
  46. package/dist/platform/cookies.d.ts.map +1 -0
  47. package/dist/platform/index.d.ts +8 -0
  48. package/dist/platform/index.d.ts.map +1 -1
  49. package/dist/platform/meta.d.ts +62 -0
  50. package/dist/platform/meta.d.ts.map +1 -0
  51. package/dist/platform-Dr9b6fsq.js +362 -0
  52. package/dist/platform-Dr9b6fsq.js.map +1 -0
  53. package/dist/platform.es.mjs +11 -248
  54. package/dist/reactive/async-data.d.ts +114 -0
  55. package/dist/reactive/async-data.d.ts.map +1 -0
  56. package/dist/reactive/index.d.ts +2 -2
  57. package/dist/reactive/index.d.ts.map +1 -1
  58. package/dist/reactive/signal.d.ts +2 -0
  59. package/dist/reactive/signal.d.ts.map +1 -1
  60. package/dist/reactive-DSkct0dO.js +254 -0
  61. package/dist/reactive-DSkct0dO.js.map +1 -0
  62. package/dist/reactive.es.mjs +18 -32
  63. package/dist/router-CbDhl8rS.js +188 -0
  64. package/dist/router-CbDhl8rS.js.map +1 -0
  65. package/dist/router.es.mjs +11 -200
  66. package/dist/sanitize-Bs2dkMby.js +313 -0
  67. package/dist/sanitize-Bs2dkMby.js.map +1 -0
  68. package/dist/security/constants.d.ts.map +1 -1
  69. package/dist/security/index.d.ts +4 -2
  70. package/dist/security/index.d.ts.map +1 -1
  71. package/dist/security/sanitize.d.ts +4 -1
  72. package/dist/security/sanitize.d.ts.map +1 -1
  73. package/dist/security/trusted-html.d.ts +53 -0
  74. package/dist/security/trusted-html.d.ts.map +1 -0
  75. package/dist/security.es.mjs +11 -56
  76. package/dist/store/define-store.d.ts +1 -1
  77. package/dist/store/define-store.d.ts.map +1 -1
  78. package/dist/store/mapping.d.ts +1 -1
  79. package/dist/store/mapping.d.ts.map +1 -1
  80. package/dist/store/persisted.d.ts +1 -1
  81. package/dist/store/persisted.d.ts.map +1 -1
  82. package/dist/store/types.d.ts +2 -2
  83. package/dist/store/types.d.ts.map +1 -1
  84. package/dist/store/watch.d.ts +1 -1
  85. package/dist/store/watch.d.ts.map +1 -1
  86. package/dist/store-BwDvI45q.js +263 -0
  87. package/dist/store-BwDvI45q.js.map +1 -0
  88. package/dist/store.es.mjs +12 -25
  89. package/dist/storybook/index.d.ts +37 -0
  90. package/dist/storybook/index.d.ts.map +1 -0
  91. package/dist/storybook.es.mjs +151 -0
  92. package/dist/storybook.es.mjs.map +1 -0
  93. package/dist/untrack-B0rVscTc.js +7 -0
  94. package/dist/untrack-B0rVscTc.js.map +1 -0
  95. package/dist/view-C70lA3vf.js +397 -0
  96. package/dist/view-C70lA3vf.js.map +1 -0
  97. package/dist/view.es.mjs +11 -430
  98. package/package.json +141 -132
  99. package/src/component/component.ts +524 -289
  100. package/src/component/html.ts +153 -53
  101. package/src/component/index.ts +50 -40
  102. package/src/component/library.ts +518 -0
  103. package/src/component/types.ts +256 -85
  104. package/src/core/collection.ts +628 -628
  105. package/src/core/element.ts +774 -774
  106. package/src/core/index.ts +48 -48
  107. package/src/core/utils/function.ts +151 -151
  108. package/src/full.ts +229 -187
  109. package/src/motion/animate.ts +113 -113
  110. package/src/motion/flip.ts +176 -176
  111. package/src/motion/scroll.ts +57 -57
  112. package/src/motion/spring.ts +150 -150
  113. package/src/motion/timeline.ts +246 -246
  114. package/src/motion/transition.ts +97 -51
  115. package/src/motion/types.ts +11 -1
  116. package/src/platform/announcer.ts +208 -0
  117. package/src/platform/config.ts +163 -0
  118. package/src/platform/cookies.ts +165 -0
  119. package/src/platform/index.ts +21 -0
  120. package/src/platform/meta.ts +168 -0
  121. package/src/platform/storage.ts +215 -215
  122. package/src/reactive/async-data.ts +486 -0
  123. package/src/reactive/core.ts +114 -114
  124. package/src/reactive/effect.ts +54 -54
  125. package/src/reactive/index.ts +15 -1
  126. package/src/reactive/internals.ts +122 -122
  127. package/src/reactive/signal.ts +9 -0
  128. package/src/security/constants.ts +3 -1
  129. package/src/security/index.ts +17 -10
  130. package/src/security/sanitize-core.ts +364 -364
  131. package/src/security/sanitize.ts +70 -66
  132. package/src/security/trusted-html.ts +71 -0
  133. package/src/store/define-store.ts +49 -48
  134. package/src/store/mapping.ts +74 -73
  135. package/src/store/persisted.ts +62 -61
  136. package/src/store/types.ts +92 -94
  137. package/src/store/watch.ts +53 -52
  138. package/src/storybook/index.ts +479 -0
  139. package/src/view/evaluate.ts +290 -290
  140. package/dist/batch-x7b2eZST.js +0 -13
  141. package/dist/batch-x7b2eZST.js.map +0 -1
  142. package/dist/component.es.mjs.map +0 -1
  143. package/dist/core-BhpuvPhy.js +0 -170
  144. package/dist/core-BhpuvPhy.js.map +0 -1
  145. package/dist/core.es.mjs.map +0 -1
  146. package/dist/full.es.mjs.map +0 -1
  147. package/dist/index.es.mjs.map +0 -1
  148. package/dist/motion.es.mjs.map +0 -1
  149. package/dist/persisted-DHoi3uEs.js +0 -278
  150. package/dist/persisted-DHoi3uEs.js.map +0 -1
  151. package/dist/platform.es.mjs.map +0 -1
  152. package/dist/reactive.es.mjs.map +0 -1
  153. package/dist/router.es.mjs.map +0 -1
  154. package/dist/sanitize-Cxvxa-DX.js +0 -283
  155. package/dist/sanitize-Cxvxa-DX.js.map +0 -1
  156. package/dist/security.es.mjs.map +0 -1
  157. package/dist/store.es.mjs.map +0 -1
  158. package/dist/type-guards-BdKlYYlS.js +0 -32
  159. package/dist/type-guards-BdKlYYlS.js.map +0 -1
  160. package/dist/untrack-DNnnqdlR.js +0 -6
  161. package/dist/untrack-DNnnqdlR.js.map +0 -1
  162. package/dist/view.es.mjs.map +0 -1
  163. package/dist/watch-DXXv3iAI.js +0 -58
  164. package/dist/watch-DXXv3iAI.js.map +0 -1
@@ -1,290 +1,290 @@
1
- import { isComputed, isSignal, type Signal } from '../reactive/index';
2
- import type { BindingContext } from './types';
3
-
4
- /** Maximum number of cached expression functions before LRU eviction */
5
- const MAX_CACHE_SIZE = 500;
6
-
7
- /** Compiled function type for expression evaluation */
8
- type CompiledFn = (ctx: BindingContext) => unknown;
9
-
10
- /**
11
- * Simple LRU cache for compiled expression functions.
12
- * Uses Map's insertion order to track recency - accessed items are re-inserted.
13
- * @internal
14
- */
15
- class LRUCache {
16
- private cache = new Map<string, CompiledFn>();
17
- private maxSize: number;
18
-
19
- constructor(maxSize: number) {
20
- this.maxSize = maxSize;
21
- }
22
-
23
- get(key: string): CompiledFn | undefined {
24
- const value = this.cache.get(key);
25
- if (value !== undefined) {
26
- // Move to end (most recently used) by re-inserting
27
- this.cache.delete(key);
28
- this.cache.set(key, value);
29
- }
30
- return value;
31
- }
32
-
33
- set(key: string, value: CompiledFn): void {
34
- // Delete first if exists to update insertion order
35
- if (this.cache.has(key)) {
36
- this.cache.delete(key);
37
- } else if (this.cache.size >= this.maxSize) {
38
- // Evict oldest (first) entry
39
- const oldest = this.cache.keys().next().value;
40
- if (oldest !== undefined) {
41
- this.cache.delete(oldest);
42
- }
43
- }
44
- this.cache.set(key, value);
45
- }
46
-
47
- clear(): void {
48
- this.cache.clear();
49
- }
50
-
51
- get size(): number {
52
- return this.cache.size;
53
- }
54
- }
55
-
56
- /** LRU cache for compiled evaluate functions, keyed by expression string */
57
- const evaluateCache = new LRUCache(MAX_CACHE_SIZE);
58
-
59
- /** LRU cache for compiled evaluateRaw functions, keyed by expression string */
60
- const evaluateRawCache = new LRUCache(MAX_CACHE_SIZE);
61
-
62
- /**
63
- * Clears all cached compiled expression functions.
64
- * Call this when unmounting views or to free memory after heavy template usage.
65
- *
66
- * @example
67
- * ```ts
68
- * import { clearExpressionCache } from 'bquery/view';
69
- *
70
- * // After destroying a view or when cleaning up
71
- * clearExpressionCache();
72
- * ```
73
- */
74
- export const clearExpressionCache = (): void => {
75
- evaluateCache.clear();
76
- evaluateRawCache.clear();
77
- };
78
-
79
- /**
80
- * Creates a proxy that lazily unwraps signals/computed only when accessed.
81
- * This avoids subscribing to signals that aren't referenced in the expression.
82
- * @internal
83
- */
84
- const createLazyContext = (context: BindingContext): BindingContext =>
85
- new Proxy(context, {
86
- get(target, prop: string | symbol) {
87
- // Only handle string keys for BindingContext indexing
88
- if (typeof prop !== 'string') {
89
- return Reflect.get(target, prop);
90
- }
91
- const value = target[prop];
92
- // Auto-unwrap signals/computed only when actually accessed
93
- if (isSignal(value) || isComputed(value)) {
94
- return (value as Signal<unknown>).value;
95
- }
96
- return value;
97
- },
98
- has(target, prop: string | symbol) {
99
- // Required for `with` statement to resolve identifiers correctly
100
- if (typeof prop !== 'string') {
101
- return Reflect.has(target, prop);
102
- }
103
- return prop in target;
104
- },
105
- });
106
-
107
- /**
108
- * Evaluates an expression in the given context using `new Function()`.
109
- *
110
- * Signals and computed values in the context are lazily unwrapped only when
111
- * accessed by the expression, avoiding unnecessary subscriptions to unused values.
112
- *
113
- * @security **WARNING:** This function uses dynamic code execution via `new Function()`.
114
- * - NEVER pass expressions derived from user input or untrusted sources
115
- * - Expressions should only come from developer-controlled templates
116
- * - Malicious expressions can access and exfiltrate context data
117
- * - Consider this equivalent to `eval()` in terms of security implications
118
- *
119
- * @internal
120
- */
121
- export const evaluate = <T = unknown>(expression: string, context: BindingContext): T => {
122
- try {
123
- // Create a proxy that lazily unwraps signals/computed on access
124
- const lazyContext = createLazyContext(context);
125
-
126
- // Use cached function or compile and cache a new one
127
- let fn = evaluateCache.get(expression);
128
- if (!fn) {
129
- // Use `with` to enable direct property access from proxy scope.
130
- // Note: `new Function()` runs in non-strict mode, so `with` is allowed.
131
- fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (
132
- ctx: BindingContext
133
- ) => unknown;
134
- evaluateCache.set(expression, fn);
135
- }
136
- return fn(lazyContext) as T;
137
- } catch (error) {
138
- console.error(`bQuery view: Error evaluating "${expression}"`, error);
139
- return undefined as T;
140
- }
141
- };
142
-
143
- /**
144
- * Evaluates an expression and returns the raw value (for signal access).
145
- *
146
- * @security **WARNING:** Uses dynamic code execution. See {@link evaluate} for security notes.
147
- * @internal
148
- */
149
- export const evaluateRaw = <T = unknown>(expression: string, context: BindingContext): T => {
150
- try {
151
- // Use cached function or compile and cache a new one
152
- let fn = evaluateRawCache.get(expression);
153
- if (!fn) {
154
- // Use `with` to enable direct property access from context scope.
155
- // Unlike `evaluate`, we don't use a lazy proxy - values are accessed directly.
156
- fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (
157
- ctx: BindingContext
158
- ) => unknown;
159
- evaluateRawCache.set(expression, fn);
160
- }
161
- return fn(context) as T;
162
- } catch (error) {
163
- console.error(`bQuery view: Error evaluating "${expression}"`, error);
164
- return undefined as T;
165
- }
166
- };
167
-
168
- /**
169
- * Parses object expression like "{ active: isActive, disabled: !enabled }".
170
- * Handles nested structures like function calls, arrays, and template literals.
171
- * @internal
172
- */
173
- export const parseObjectExpression = (expression: string): Record<string, string> => {
174
- const result: Record<string, string> = {};
175
-
176
- // Remove outer braces and trim
177
- const inner = expression
178
- .trim()
179
- .replace(/^\{|\}$/g, '')
180
- .trim();
181
- if (!inner) return result;
182
-
183
- // Split by comma at depth 0, respecting strings and nesting
184
- const parts: string[] = [];
185
- let current = '';
186
- let depth = 0;
187
- let inString: string | null = null;
188
-
189
- for (let i = 0; i < inner.length; i++) {
190
- const char = inner[i];
191
-
192
- // Handle string literals: count consecutive backslashes before a quote
193
- // to correctly distinguish escaped quotes from end-of-string
194
- if (char === '"' || char === "'" || char === '`') {
195
- let backslashCount = 0;
196
- let j = i - 1;
197
- while (j >= 0 && inner[j] === '\\') {
198
- backslashCount++;
199
- j--;
200
- }
201
- // Quote is escaped only if preceded by an odd number of backslashes
202
- if (backslashCount % 2 === 0) {
203
- if (inString === null) {
204
- inString = char;
205
- } else if (inString === char) {
206
- inString = null;
207
- }
208
- }
209
- current += char;
210
- continue;
211
- }
212
-
213
- // Skip if inside string
214
- if (inString !== null) {
215
- current += char;
216
- continue;
217
- }
218
-
219
- // Track nesting depth for parentheses, brackets, and braces
220
- if (char === '(' || char === '[' || char === '{') {
221
- depth++;
222
- current += char;
223
- } else if (char === ')' || char === ']' || char === '}') {
224
- depth--;
225
- current += char;
226
- } else if (char === ',' && depth === 0) {
227
- // Top-level comma - split point
228
- parts.push(current.trim());
229
- current = '';
230
- } else {
231
- current += char;
232
- }
233
- }
234
-
235
- // Add the last part
236
- if (current.trim()) {
237
- parts.push(current.trim());
238
- }
239
-
240
- // Parse each part to extract key and value
241
- for (const part of parts) {
242
- // Find the first colon at depth 0 (to handle ternary operators in values)
243
- let colonIndex = -1;
244
- let partDepth = 0;
245
- let partInString: string | null = null;
246
-
247
- for (let i = 0; i < part.length; i++) {
248
- const char = part[i];
249
-
250
- if (char === '"' || char === "'" || char === '`') {
251
- let backslashCount = 0;
252
- let j = i - 1;
253
- while (j >= 0 && part[j] === '\\') {
254
- backslashCount++;
255
- j--;
256
- }
257
- if (backslashCount % 2 === 0) {
258
- if (partInString === null) {
259
- partInString = char;
260
- } else if (partInString === char) {
261
- partInString = null;
262
- }
263
- }
264
- continue;
265
- }
266
-
267
- if (partInString !== null) continue;
268
-
269
- if (char === '(' || char === '[' || char === '{') {
270
- partDepth++;
271
- } else if (char === ')' || char === ']' || char === '}') {
272
- partDepth--;
273
- } else if (char === ':' && partDepth === 0) {
274
- colonIndex = i;
275
- break;
276
- }
277
- }
278
-
279
- if (colonIndex > -1) {
280
- const key = part
281
- .slice(0, colonIndex)
282
- .trim()
283
- .replace(/^['"]|['"]$/g, '');
284
- const value = part.slice(colonIndex + 1).trim();
285
- result[key] = value;
286
- }
287
- }
288
-
289
- return result;
290
- };
1
+ import { isComputed, isSignal, type Signal } from '../reactive/index';
2
+ import type { BindingContext } from './types';
3
+
4
+ /** Maximum number of cached expression functions before LRU eviction */
5
+ const MAX_CACHE_SIZE = 500;
6
+
7
+ /** Compiled function type for expression evaluation */
8
+ type CompiledFn = (ctx: BindingContext) => unknown;
9
+
10
+ /**
11
+ * Simple LRU cache for compiled expression functions.
12
+ * Uses Map's insertion order to track recency - accessed items are re-inserted.
13
+ * @internal
14
+ */
15
+ class LRUCache {
16
+ private cache = new Map<string, CompiledFn>();
17
+ private maxSize: number;
18
+
19
+ constructor(maxSize: number) {
20
+ this.maxSize = maxSize;
21
+ }
22
+
23
+ get(key: string): CompiledFn | undefined {
24
+ const value = this.cache.get(key);
25
+ if (value !== undefined) {
26
+ // Move to end (most recently used) by re-inserting
27
+ this.cache.delete(key);
28
+ this.cache.set(key, value);
29
+ }
30
+ return value;
31
+ }
32
+
33
+ set(key: string, value: CompiledFn): void {
34
+ // Delete first if exists to update insertion order
35
+ if (this.cache.has(key)) {
36
+ this.cache.delete(key);
37
+ } else if (this.cache.size >= this.maxSize) {
38
+ // Evict oldest (first) entry
39
+ const oldest = this.cache.keys().next().value;
40
+ if (oldest !== undefined) {
41
+ this.cache.delete(oldest);
42
+ }
43
+ }
44
+ this.cache.set(key, value);
45
+ }
46
+
47
+ clear(): void {
48
+ this.cache.clear();
49
+ }
50
+
51
+ get size(): number {
52
+ return this.cache.size;
53
+ }
54
+ }
55
+
56
+ /** LRU cache for compiled evaluate functions, keyed by expression string */
57
+ const evaluateCache = new LRUCache(MAX_CACHE_SIZE);
58
+
59
+ /** LRU cache for compiled evaluateRaw functions, keyed by expression string */
60
+ const evaluateRawCache = new LRUCache(MAX_CACHE_SIZE);
61
+
62
+ /**
63
+ * Clears all cached compiled expression functions.
64
+ * Call this when unmounting views or to free memory after heavy template usage.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * import { clearExpressionCache } from 'bquery/view';
69
+ *
70
+ * // After destroying a view or when cleaning up
71
+ * clearExpressionCache();
72
+ * ```
73
+ */
74
+ export const clearExpressionCache = (): void => {
75
+ evaluateCache.clear();
76
+ evaluateRawCache.clear();
77
+ };
78
+
79
+ /**
80
+ * Creates a proxy that lazily unwraps signals/computed only when accessed.
81
+ * This avoids subscribing to signals that aren't referenced in the expression.
82
+ * @internal
83
+ */
84
+ const createLazyContext = (context: BindingContext): BindingContext =>
85
+ new Proxy(context, {
86
+ get(target, prop: string | symbol) {
87
+ // Only handle string keys for BindingContext indexing
88
+ if (typeof prop !== 'string') {
89
+ return Reflect.get(target, prop);
90
+ }
91
+ const value = target[prop];
92
+ // Auto-unwrap signals/computed only when actually accessed
93
+ if (isSignal(value) || isComputed(value)) {
94
+ return (value as Signal<unknown>).value;
95
+ }
96
+ return value;
97
+ },
98
+ has(target, prop: string | symbol) {
99
+ // Required for `with` statement to resolve identifiers correctly
100
+ if (typeof prop !== 'string') {
101
+ return Reflect.has(target, prop);
102
+ }
103
+ return prop in target;
104
+ },
105
+ });
106
+
107
+ /**
108
+ * Evaluates an expression in the given context using `new Function()`.
109
+ *
110
+ * Signals and computed values in the context are lazily unwrapped only when
111
+ * accessed by the expression, avoiding unnecessary subscriptions to unused values.
112
+ *
113
+ * @security **WARNING:** This function uses dynamic code execution via `new Function()`.
114
+ * - NEVER pass expressions derived from user input or untrusted sources
115
+ * - Expressions should only come from developer-controlled templates
116
+ * - Malicious expressions can access and exfiltrate context data
117
+ * - Consider this equivalent to `eval()` in terms of security implications
118
+ *
119
+ * @internal
120
+ */
121
+ export const evaluate = <T = unknown>(expression: string, context: BindingContext): T => {
122
+ try {
123
+ // Create a proxy that lazily unwraps signals/computed on access
124
+ const lazyContext = createLazyContext(context);
125
+
126
+ // Use cached function or compile and cache a new one
127
+ let fn = evaluateCache.get(expression);
128
+ if (!fn) {
129
+ // Use `with` to enable direct property access from proxy scope.
130
+ // Note: `new Function()` runs in non-strict mode, so `with` is allowed.
131
+ fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (
132
+ ctx: BindingContext
133
+ ) => unknown;
134
+ evaluateCache.set(expression, fn);
135
+ }
136
+ return fn(lazyContext) as T;
137
+ } catch (error) {
138
+ console.error(`bQuery view: Error evaluating "${expression}"`, error);
139
+ return undefined as T;
140
+ }
141
+ };
142
+
143
+ /**
144
+ * Evaluates an expression and returns the raw value (for signal access).
145
+ *
146
+ * @security **WARNING:** Uses dynamic code execution. See {@link evaluate} for security notes.
147
+ * @internal
148
+ */
149
+ export const evaluateRaw = <T = unknown>(expression: string, context: BindingContext): T => {
150
+ try {
151
+ // Use cached function or compile and cache a new one
152
+ let fn = evaluateRawCache.get(expression);
153
+ if (!fn) {
154
+ // Use `with` to enable direct property access from context scope.
155
+ // Unlike `evaluate`, we don't use a lazy proxy - values are accessed directly.
156
+ fn = new Function('$ctx', `with($ctx) { return (${expression}); }`) as (
157
+ ctx: BindingContext
158
+ ) => unknown;
159
+ evaluateRawCache.set(expression, fn);
160
+ }
161
+ return fn(context) as T;
162
+ } catch (error) {
163
+ console.error(`bQuery view: Error evaluating "${expression}"`, error);
164
+ return undefined as T;
165
+ }
166
+ };
167
+
168
+ /**
169
+ * Parses object expression like "{ active: isActive, disabled: !enabled }".
170
+ * Handles nested structures like function calls, arrays, and template literals.
171
+ * @internal
172
+ */
173
+ export const parseObjectExpression = (expression: string): Record<string, string> => {
174
+ const result: Record<string, string> = {};
175
+
176
+ // Remove outer braces and trim
177
+ const inner = expression
178
+ .trim()
179
+ .replace(/^\{|\}$/g, '')
180
+ .trim();
181
+ if (!inner) return result;
182
+
183
+ // Split by comma at depth 0, respecting strings and nesting
184
+ const parts: string[] = [];
185
+ let current = '';
186
+ let depth = 0;
187
+ let inString: string | null = null;
188
+
189
+ for (let i = 0; i < inner.length; i++) {
190
+ const char = inner[i];
191
+
192
+ // Handle string literals: count consecutive backslashes before a quote
193
+ // to correctly distinguish escaped quotes from end-of-string
194
+ if (char === '"' || char === "'" || char === '`') {
195
+ let backslashCount = 0;
196
+ let j = i - 1;
197
+ while (j >= 0 && inner[j] === '\\') {
198
+ backslashCount++;
199
+ j--;
200
+ }
201
+ // Quote is escaped only if preceded by an odd number of backslashes
202
+ if (backslashCount % 2 === 0) {
203
+ if (inString === null) {
204
+ inString = char;
205
+ } else if (inString === char) {
206
+ inString = null;
207
+ }
208
+ }
209
+ current += char;
210
+ continue;
211
+ }
212
+
213
+ // Skip if inside string
214
+ if (inString !== null) {
215
+ current += char;
216
+ continue;
217
+ }
218
+
219
+ // Track nesting depth for parentheses, brackets, and braces
220
+ if (char === '(' || char === '[' || char === '{') {
221
+ depth++;
222
+ current += char;
223
+ } else if (char === ')' || char === ']' || char === '}') {
224
+ depth--;
225
+ current += char;
226
+ } else if (char === ',' && depth === 0) {
227
+ // Top-level comma - split point
228
+ parts.push(current.trim());
229
+ current = '';
230
+ } else {
231
+ current += char;
232
+ }
233
+ }
234
+
235
+ // Add the last part
236
+ if (current.trim()) {
237
+ parts.push(current.trim());
238
+ }
239
+
240
+ // Parse each part to extract key and value
241
+ for (const part of parts) {
242
+ // Find the first colon at depth 0 (to handle ternary operators in values)
243
+ let colonIndex = -1;
244
+ let partDepth = 0;
245
+ let partInString: string | null = null;
246
+
247
+ for (let i = 0; i < part.length; i++) {
248
+ const char = part[i];
249
+
250
+ if (char === '"' || char === "'" || char === '`') {
251
+ let backslashCount = 0;
252
+ let j = i - 1;
253
+ while (j >= 0 && part[j] === '\\') {
254
+ backslashCount++;
255
+ j--;
256
+ }
257
+ if (backslashCount % 2 === 0) {
258
+ if (partInString === null) {
259
+ partInString = char;
260
+ } else if (partInString === char) {
261
+ partInString = null;
262
+ }
263
+ }
264
+ continue;
265
+ }
266
+
267
+ if (partInString !== null) continue;
268
+
269
+ if (char === '(' || char === '[' || char === '{') {
270
+ partDepth++;
271
+ } else if (char === ')' || char === ']' || char === '}') {
272
+ partDepth--;
273
+ } else if (char === ':' && partDepth === 0) {
274
+ colonIndex = i;
275
+ break;
276
+ }
277
+ }
278
+
279
+ if (colonIndex > -1) {
280
+ const key = part
281
+ .slice(0, colonIndex)
282
+ .trim()
283
+ .replace(/^['"]|['"]$/g, '');
284
+ const value = part.slice(colonIndex + 1).trim();
285
+ result[key] = value;
286
+ }
287
+ }
288
+
289
+ return result;
290
+ };
@@ -1,13 +0,0 @@
1
- import { e as t, b } from "./core-BhpuvPhy.js";
2
- const e = (a) => {
3
- b();
4
- try {
5
- a();
6
- } finally {
7
- t();
8
- }
9
- };
10
- export {
11
- e as b
12
- };
13
- //# sourceMappingURL=batch-x7b2eZST.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"batch-x7b2eZST.js","sources":["../src/reactive/batch.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"],"names":["batch","fn","beginBatch","endBatch"],"mappings":";AAcO,MAAMA,IAAQ,CAACC,MAAyB;AAC7C,EAAAC,EAAA;AACA,MAAI;AACF,IAAAD,EAAA;AAAA,EACF,UAAA;AACE,IAAAE,EAAA;AAAA,EACF;AACF;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"component.es.mjs","sources":["../src/component/props.ts","../src/component/component.ts","../src/component/html.ts"],"sourcesContent":["/**\n * Prop coercion utilities.\n *\n * @module bquery/component\n */\n\nimport type { PropDefinition } from './types';\n\n/**\n * Coerces a string attribute value into a typed prop value.\n * Supports String, Number, Boolean, Object, Array, and custom converters.\n *\n * @internal\n * @template T - The target type\n * @param rawValue - The raw string value from the attribute\n * @param config - The prop definition with type information\n * @returns The coerced value of type T\n */\nexport const coercePropValue = <T>(rawValue: string, config: PropDefinition<T>): T => {\n const { type } = config;\n\n if (type === String) return rawValue as T;\n\n if (type === Number) {\n return Number(rawValue) as T;\n }\n\n if (type === Boolean) {\n const normalized = rawValue.trim().toLowerCase();\n if (normalized === '' || normalized === 'true' || normalized === '1') {\n return true as T;\n }\n if (normalized === 'false' || normalized === '0') {\n return false as T;\n }\n return Boolean(rawValue) as T;\n }\n\n if (type === Object || type === Array) {\n try {\n return JSON.parse(rawValue) as T;\n } catch {\n return rawValue as T;\n }\n }\n\n if (typeof type === 'function') {\n const callable = type as (value: unknown) => T;\n const constructable = type as new (value: unknown) => T;\n\n // Explicit construct mode takes precedence\n if (config.construct === true) {\n return Reflect.construct(constructable, [rawValue]) as T;\n }\n if (config.construct === false) {\n return callable(rawValue);\n }\n\n // Auto-detect: Check if type is constructable\n // A function is considered constructable if:\n // 1. It has a prototype with properties beyond just constructor, OR\n // 2. Its prototype.constructor is not itself (inherited), OR\n // 3. It's a class (toString starts with \"class\")\n const hasPrototype = type.prototype !== undefined && type.prototype !== null;\n const prototypeProps = hasPrototype ? Object.getOwnPropertyNames(type.prototype) : [];\n const hasPrototypeMethods = prototypeProps.length > 1;\n const hasInheritedConstructor = hasPrototype && type.prototype.constructor !== type;\n const isClassSyntax = /^class\\s/.test(Function.prototype.toString.call(type));\n\n const isConstructable = hasPrototypeMethods || hasInheritedConstructor || isClassSyntax;\n\n // For constructable types (e.g. Date, custom classes), prefer `new` to avoid\n // silent wrong-type returns (Date() returns string, new Date() returns Date)\n if (isConstructable) {\n try {\n return Reflect.construct(constructable, [rawValue]) as T;\n } catch {\n // Fall back to calling as function if construction fails\n return callable(rawValue);\n }\n }\n\n // For non-constructable types (arrow functions, plain functions), call directly\n // but fall back to constructor if result is undefined (common for function constructors)\n try {\n const result = callable(rawValue);\n\n // If calling without `new` returned undefined and the function has a prototype,\n // it's likely a function constructor that should be called with `new`\n if (result === undefined && hasPrototype) {\n try {\n return Reflect.construct(constructable, [rawValue]) as T;\n } catch {\n // Construction also failed, return the undefined\n return result as T;\n }\n }\n\n return result as T;\n } catch (error) {\n // Fall back to constructor if error indicates 'new' is required\n const isNewRequired =\n error instanceof TypeError &&\n /cannot be invoked without 'new'|is not a function/i.test(error.message);\n\n if (isNewRequired) {\n return Reflect.construct(constructable, [rawValue]) as T;\n }\n\n // Rethrow original error for non-constructable converters\n throw error;\n }\n }\n\n return rawValue as T;\n};\n","/**\n * Web Component factory and registry.\n *\n * @module bquery/component\n */\n\nimport { sanitizeHtml } from '../security/sanitize';\nimport { coercePropValue } from './props';\nimport type { ComponentDefinition, PropDefinition } from './types';\n\n/**\n * Creates a custom element class for a component definition.\n *\n * This is useful when you want to extend or register the class manually\n * (e.g. with different tag names in tests or custom registries).\n *\n * @template TProps - Type of the component's props\n * @param tagName - The custom element tag name (used for diagnostics)\n * @param definition - The component configuration\n */\nexport const defineComponent = <TProps extends Record<string, unknown>>(\n tagName: string,\n definition: ComponentDefinition<TProps>\n): typeof HTMLElement => {\n class BQueryComponent extends HTMLElement {\n /** Internal state object for the component */\n private readonly state = { ...(definition.state ?? {}) };\n /** Typed props object populated from attributes */\n private props = {} as TProps;\n /** Tracks missing required props for validation during connectedCallback */\n private missingRequiredProps = new Set<string>();\n /** Tracks whether the component has completed its initial mount */\n private hasMounted = false;\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n this.syncProps();\n }\n\n /**\n * Returns the list of attributes to observe for changes.\n */\n static get observedAttributes(): string[] {\n return Object.keys(definition.props ?? {});\n }\n\n /**\n * Called when the element is added to the DOM.\n */\n connectedCallback(): void {\n try {\n // Defer initial render until all required props are present\n // This allows attributes to be set after element creation\n if (this.missingRequiredProps.size > 0) {\n // Component will mount once all required props are satisfied\n // via attributeChangedCallback\n return;\n }\n this.mount();\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Performs the initial mount of the component.\n * Called when the element is connected and all required props are present.\n * @internal\n */\n private mount(): void {\n if (this.hasMounted) return;\n definition.beforeMount?.call(this);\n definition.connected?.call(this);\n this.render();\n this.hasMounted = true;\n }\n\n /**\n * Called when the element is removed from the DOM.\n */\n disconnectedCallback(): void {\n try {\n definition.disconnected?.call(this);\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Called when an observed attribute changes.\n */\n attributeChangedCallback(\n _name: string,\n _oldValue: string | null,\n _newValue: string | null\n ): void {\n try {\n this.syncProps();\n\n if (this.hasMounted) {\n // Component already mounted - trigger update render\n this.render(true);\n } else if (this.isConnected && this.missingRequiredProps.size === 0) {\n // All required props are now satisfied and element is connected\n // Trigger the deferred initial mount\n this.mount();\n }\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n\n /**\n * Handles errors during component lifecycle.\n * @internal\n */\n private handleError(error: Error): void {\n if (definition.onError) {\n definition.onError.call(this, error);\n } else {\n console.error(`bQuery component error in <${tagName}>:`, error);\n }\n }\n\n /**\n * Updates a state property and triggers a re-render.\n *\n * @param key - The state property key\n * @param value - The new value\n */\n setState(key: string, value: unknown): void {\n this.state[key] = value;\n this.render(true);\n }\n\n /**\n * Gets a state property value.\n *\n * @param key - The state property key\n * @returns The current value\n */\n getState<T = unknown>(key: string): T {\n return this.state[key] as T;\n }\n\n /**\n * Synchronizes props from attributes.\n * @internal\n */\n private syncProps(): void {\n const props = definition.props ?? {};\n for (const [key, config] of Object.entries(props) as [string, PropDefinition][]) {\n const attrValue = this.getAttribute(key);\n let value: unknown;\n\n if (attrValue == null) {\n if (config.required && config.default === undefined) {\n // Mark as missing instead of throwing - validate during connectedCallback\n this.missingRequiredProps.add(key);\n value = undefined;\n } else {\n value = config.default ?? undefined;\n }\n } else {\n // Attribute is present, remove from missing set if it was there\n if (this.missingRequiredProps.has(key)) {\n this.missingRequiredProps.delete(key);\n }\n value = coercePropValue(attrValue, config);\n }\n\n if (config.validator && value !== undefined) {\n const isValid = config.validator(value);\n if (!isValid) {\n throw new Error(\n `bQuery component: validation failed for prop \"${key}\" with value ${JSON.stringify(value)}`\n );\n }\n }\n\n (this.props as Record<string, unknown>)[key] = value;\n }\n }\n\n /**\n * Renders the component to its shadow root.\n * @internal\n */\n private render(triggerUpdated = false): void {\n try {\n if (triggerUpdated && definition.beforeUpdate) {\n const shouldUpdate = definition.beforeUpdate.call(this, this.props);\n if (shouldUpdate === false) return;\n }\n\n const emit = (event: string, detail?: unknown): void => {\n this.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, composed: true }));\n };\n\n if (!this.shadowRoot) return;\n\n const markup = definition.render({\n props: this.props,\n state: this.state,\n emit,\n });\n\n const sanitizedMarkup = sanitizeHtml(markup);\n this.shadowRoot.innerHTML = sanitizedMarkup;\n\n if (definition.styles) {\n const styleElement = document.createElement('style');\n styleElement.textContent = definition.styles;\n this.shadowRoot.prepend(styleElement);\n }\n\n if (triggerUpdated) {\n definition.updated?.call(this);\n }\n } catch (error) {\n this.handleError(error as Error);\n }\n }\n }\n\n return BQueryComponent;\n};\n\n/**\n * Defines and registers a custom Web Component.\n *\n * This function creates a new custom element with the given tag name\n * and configuration. The component uses Shadow DOM for encapsulation\n * and automatically re-renders when observed attributes change.\n *\n * @template TProps - Type of the component's props\n * @param tagName - The custom element tag name (must contain a hyphen)\n * @param definition - The component configuration\n *\n * @example\n * ```ts\n * component('counter-button', {\n * props: {\n * start: { type: Number, default: 0 },\n * },\n * state: { count: 0 },\n * styles: `\n * button { padding: 0.5rem 1rem; }\n * `,\n * connected() {\n * // Use event delegation on shadow root so handler survives re-renders\n * const handleClick = (event: Event) => {\n * const target = event.target as HTMLElement | null;\n * if (target?.matches('button')) {\n * this.setState('count', (this.getState('count') as number) + 1);\n * }\n * };\n * this.shadowRoot?.addEventListener('click', handleClick);\n * // Store handler for cleanup\n * (this as any)._handleClick = handleClick;\n * },\n * disconnected() {\n * // Clean up event listener to prevent memory leaks\n * const handleClick = (this as any)._handleClick;\n * if (handleClick) {\n * this.shadowRoot?.removeEventListener('click', handleClick);\n * }\n * },\n * render({ props, state }) {\n * return html`\n * <button>\n * Count: ${state.count}\n * </button>\n * `;\n * },\n * });\n * ```\n */\nexport const component = <TProps extends Record<string, unknown>>(\n tagName: string,\n definition: ComponentDefinition<TProps>\n): void => {\n const elementClass = defineComponent(tagName, definition);\n\n if (!customElements.get(tagName)) {\n customElements.define(tagName, elementClass);\n }\n};\n","/**\n * Tagged template literal for creating HTML strings.\n *\n * This function handles interpolation of values into HTML templates,\n * converting null/undefined to empty strings.\n *\n * @param strings - Template literal string parts\n * @param values - Interpolated values\n * @returns Combined HTML string\n *\n * @example\n * ```ts\n * const name = 'World';\n * const greeting = html`<h1>Hello, ${name}!</h1>`;\n * // Result: '<h1>Hello, World!</h1>'\n * ```\n */\nexport const html = (strings: TemplateStringsArray, ...values: unknown[]): string => {\n return strings.reduce((acc, part, index) => `${acc}${part}${values[index] ?? ''}`, '');\n};\n\n/**\n * Escapes HTML entities in interpolated values for XSS prevention.\n * Use this when you need to safely embed user content in templates.\n *\n * @param strings - Template literal string parts\n * @param values - Interpolated values to escape\n * @returns Combined HTML string with escaped values\n *\n * @example\n * ```ts\n * const userInput = '<script>alert(\"xss\")</script>';\n * const safe = safeHtml`<div>${userInput}</div>`;\n * // Result: '<div>&lt;script&gt;alert(\"xss\")&lt;/script&gt;</div>'\n * ```\n */\nexport const safeHtml = (strings: TemplateStringsArray, ...values: unknown[]): string => {\n const escapeMap: Record<string, string> = {\n '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#x27;',\n '`': '&#x60;',\n };\n\n const escape = (value: unknown): string => {\n const str = String(value ?? '');\n return str.replace(/[&<>\"'`]/g, (char) => escapeMap[char]);\n };\n\n return strings.reduce((acc, part, index) => `${acc}${part}${escape(values[index])}`, '');\n};\n"],"names":["coercePropValue","rawValue","config","type","normalized","callable","constructable","hasPrototype","hasPrototypeMethods","hasInheritedConstructor","isClassSyntax","result","error","defineComponent","tagName","definition","BQueryComponent","_name","_oldValue","_newValue","key","value","props","attrValue","triggerUpdated","emit","event","detail","markup","sanitizedMarkup","sanitizeHtml","styleElement","component","elementClass","html","strings","values","acc","part","index","safeHtml","escapeMap","escape","char"],"mappings":"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"}