@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,114 +1,114 @@
1
- /**
2
- * Core reactive signals.
3
- */
4
-
5
- import {
6
- getCurrentObserver,
7
- registerDependency,
8
- removeDependency,
9
- scheduleObserver,
10
- type ReactiveSource,
11
- } from './internals';
12
-
13
- /**
14
- * A reactive value container that notifies subscribers on change.
15
- *
16
- * Signals are the foundational primitive of the reactive system.
17
- * Reading a signal's value inside an effect or computed automatically
18
- * establishes a reactive dependency.
19
- *
20
- * @template T - The type of the stored value
21
- */
22
- export class Signal<T> implements ReactiveSource {
23
- private subscribers = new Set<() => void>();
24
-
25
- /**
26
- * Creates a new signal with an initial value.
27
- * @param _value - The initial value
28
- */
29
- constructor(private _value: T) {}
30
-
31
- /**
32
- * Gets the current value and tracks the read if inside an observer.
33
- * During untrack calls, getCurrentObserver returns undefined, preventing dependency tracking.
34
- */
35
- get value(): T {
36
- const current = getCurrentObserver();
37
- if (current) {
38
- this.subscribers.add(current);
39
- registerDependency(current, this);
40
- }
41
- return this._value;
42
- }
43
-
44
- /**
45
- * Sets a new value and notifies all subscribers if the value changed.
46
- * Uses Object.is for equality comparison.
47
- */
48
- set value(next: T) {
49
- if (Object.is(this._value, next)) return;
50
- this._value = next;
51
- // Create snapshot to avoid issues with subscribers modifying the set during iteration
52
- const subscribersSnapshot = Array.from(this.subscribers);
53
- for (const subscriber of subscribersSnapshot) {
54
- scheduleObserver(subscriber);
55
- }
56
- }
57
-
58
- /**
59
- * Reads the current value without tracking.
60
- * Useful when you need the value but don't want to create a dependency.
61
- *
62
- * @returns The current value
63
- */
64
- peek(): T {
65
- return this._value;
66
- }
67
-
68
- /**
69
- * Updates the value using a function.
70
- * Useful for updates based on the current value.
71
- *
72
- * @param updater - Function that receives current value and returns new value
73
- */
74
- update(updater: (current: T) => T): void {
75
- this.value = updater(this._value);
76
- }
77
-
78
- /**
79
- * Removes all subscribers from this signal.
80
- * Use this when a signal is no longer needed to prevent memory leaks.
81
- *
82
- * @example
83
- * ```ts
84
- * const count = signal(0);
85
- * effect(() => console.log(count.value));
86
- * count.dispose(); // All subscribers removed
87
- * ```
88
- */
89
- dispose(): void {
90
- // Remove this signal from each subscriber's dependency set
91
- // so the observer no longer holds a strong reference to it
92
- for (const subscriber of this.subscribers) {
93
- removeDependency(subscriber, this);
94
- }
95
- this.subscribers.clear();
96
- }
97
-
98
- /**
99
- * Removes an observer from this signal's subscriber set.
100
- * @internal
101
- */
102
- unsubscribe(observer: () => void): void {
103
- this.subscribers.delete(observer);
104
- }
105
- }
106
-
107
- /**
108
- * Creates a new reactive signal.
109
- *
110
- * @template T - The type of the signal value
111
- * @param value - The initial value
112
- * @returns A new Signal instance
113
- */
114
- export const signal = <T>(value: T): Signal<T> => new Signal(value);
1
+ /**
2
+ * Core reactive signals.
3
+ */
4
+
5
+ import {
6
+ getCurrentObserver,
7
+ registerDependency,
8
+ removeDependency,
9
+ scheduleObserver,
10
+ type ReactiveSource,
11
+ } from './internals';
12
+
13
+ /**
14
+ * A reactive value container that notifies subscribers on change.
15
+ *
16
+ * Signals are the foundational primitive of the reactive system.
17
+ * Reading a signal's value inside an effect or computed automatically
18
+ * establishes a reactive dependency.
19
+ *
20
+ * @template T - The type of the stored value
21
+ */
22
+ export class Signal<T> implements ReactiveSource {
23
+ private subscribers = new Set<() => void>();
24
+
25
+ /**
26
+ * Creates a new signal with an initial value.
27
+ * @param _value - The initial value
28
+ */
29
+ constructor(private _value: T) {}
30
+
31
+ /**
32
+ * Gets the current value and tracks the read if inside an observer.
33
+ * During untrack calls, getCurrentObserver returns undefined, preventing dependency tracking.
34
+ */
35
+ get value(): T {
36
+ const current = getCurrentObserver();
37
+ if (current) {
38
+ this.subscribers.add(current);
39
+ registerDependency(current, this);
40
+ }
41
+ return this._value;
42
+ }
43
+
44
+ /**
45
+ * Sets a new value and notifies all subscribers if the value changed.
46
+ * Uses Object.is for equality comparison.
47
+ */
48
+ set value(next: T) {
49
+ if (Object.is(this._value, next)) return;
50
+ this._value = next;
51
+ // Create snapshot to avoid issues with subscribers modifying the set during iteration
52
+ const subscribersSnapshot = Array.from(this.subscribers);
53
+ for (const subscriber of subscribersSnapshot) {
54
+ scheduleObserver(subscriber);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Reads the current value without tracking.
60
+ * Useful when you need the value but don't want to create a dependency.
61
+ *
62
+ * @returns The current value
63
+ */
64
+ peek(): T {
65
+ return this._value;
66
+ }
67
+
68
+ /**
69
+ * Updates the value using a function.
70
+ * Useful for updates based on the current value.
71
+ *
72
+ * @param updater - Function that receives current value and returns new value
73
+ */
74
+ update(updater: (current: T) => T): void {
75
+ this.value = updater(this._value);
76
+ }
77
+
78
+ /**
79
+ * Removes all subscribers from this signal.
80
+ * Use this when a signal is no longer needed to prevent memory leaks.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const count = signal(0);
85
+ * effect(() => console.log(count.value));
86
+ * count.dispose(); // All subscribers removed
87
+ * ```
88
+ */
89
+ dispose(): void {
90
+ // Remove this signal from each subscriber's dependency set
91
+ // so the observer no longer holds a strong reference to it
92
+ for (const subscriber of this.subscribers) {
93
+ removeDependency(subscriber, this);
94
+ }
95
+ this.subscribers.clear();
96
+ }
97
+
98
+ /**
99
+ * Removes an observer from this signal's subscriber set.
100
+ * @internal
101
+ */
102
+ unsubscribe(observer: () => void): void {
103
+ this.subscribers.delete(observer);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Creates a new reactive signal.
109
+ *
110
+ * @template T - The type of the signal value
111
+ * @param value - The initial value
112
+ * @returns A new Signal instance
113
+ */
114
+ export const signal = <T>(value: T): Signal<T> => new Signal(value);
@@ -1,54 +1,54 @@
1
- /**
2
- * Reactive effects.
3
- */
4
-
5
- import { CleanupFn, Observer, track, clearDependencies } from './internals';
6
-
7
- /**
8
- * Creates a side effect that automatically re-runs when dependencies change.
9
- *
10
- * The effect runs immediately upon creation and then re-runs whenever
11
- * any signal or computed value read inside it changes.
12
- *
13
- * @param fn - The effect function to run
14
- * @returns A cleanup function to stop the effect
15
- */
16
- export const effect = (fn: () => void | CleanupFn): CleanupFn => {
17
- let cleanupFn: CleanupFn | void;
18
- let isDisposed = false;
19
-
20
- const runCleanup = (): void => {
21
- if (cleanupFn) {
22
- try {
23
- cleanupFn();
24
- } catch (error) {
25
- console.error('bQuery reactive: Error in effect cleanup', error);
26
- }
27
- cleanupFn = undefined;
28
- }
29
- };
30
-
31
- const observer: Observer = () => {
32
- if (isDisposed) return;
33
-
34
- runCleanup();
35
-
36
- // Clear old dependencies before running to avoid stale subscriptions
37
- clearDependencies(observer);
38
-
39
- try {
40
- cleanupFn = track(observer, fn);
41
- } catch (error) {
42
- console.error('bQuery reactive: Error in effect', error);
43
- }
44
- };
45
-
46
- observer();
47
-
48
- return () => {
49
- isDisposed = true;
50
- runCleanup();
51
- // Clean up all dependencies when effect is disposed
52
- clearDependencies(observer);
53
- };
54
- };
1
+ /**
2
+ * Reactive effects.
3
+ */
4
+
5
+ import { CleanupFn, Observer, track, clearDependencies } from './internals';
6
+
7
+ /**
8
+ * Creates a side effect that automatically re-runs when dependencies change.
9
+ *
10
+ * The effect runs immediately upon creation and then re-runs whenever
11
+ * any signal or computed value read inside it changes.
12
+ *
13
+ * @param fn - The effect function to run
14
+ * @returns A cleanup function to stop the effect
15
+ */
16
+ export const effect = (fn: () => void | CleanupFn): CleanupFn => {
17
+ let cleanupFn: CleanupFn | void;
18
+ let isDisposed = false;
19
+
20
+ const runCleanup = (): void => {
21
+ if (cleanupFn) {
22
+ try {
23
+ cleanupFn();
24
+ } catch (error) {
25
+ console.error('bQuery reactive: Error in effect cleanup', error);
26
+ }
27
+ cleanupFn = undefined;
28
+ }
29
+ };
30
+
31
+ const observer: Observer = () => {
32
+ if (isDisposed) return;
33
+
34
+ runCleanup();
35
+
36
+ // Clear old dependencies before running to avoid stale subscriptions
37
+ clearDependencies(observer);
38
+
39
+ try {
40
+ cleanupFn = track(observer, fn);
41
+ } catch (error) {
42
+ console.error('bQuery reactive: Error in effect', error);
43
+ }
44
+ };
45
+
46
+ observer();
47
+
48
+ return () => {
49
+ isDisposed = true;
50
+ runCleanup();
51
+ // Clean up all dependencies when effect is disposed
52
+ clearDependencies(observer);
53
+ };
54
+ };
@@ -9,6 +9,7 @@ export {
9
9
  Signal,
10
10
  batch,
11
11
  computed,
12
+ createUseFetch,
12
13
  effect,
13
14
  isComputed,
14
15
  isSignal,
@@ -16,8 +17,21 @@ export {
16
17
  persistedSignal,
17
18
  readonly,
18
19
  signal,
20
+ useAsyncData,
21
+ useFetch,
19
22
  untrack,
20
23
  watch,
21
24
  } from './signal';
22
25
 
23
- export type { CleanupFn, LinkedSignal, Observer, ReadonlySignal } from './signal';
26
+ export type {
27
+ AsyncDataState,
28
+ AsyncDataStatus,
29
+ AsyncWatchSource,
30
+ CleanupFn,
31
+ FetchInput,
32
+ LinkedSignal,
33
+ Observer,
34
+ ReadonlySignal,
35
+ UseAsyncDataOptions,
36
+ UseFetchOptions,
37
+ } from './signal';
@@ -1,122 +1,122 @@
1
- /**
2
- * Internal reactive plumbing shared across primitives.
3
- * @internal
4
- */
5
-
6
- export type Observer = () => void;
7
- export type CleanupFn = () => void;
8
-
9
- /**
10
- * Interface for reactive sources (Signals, Computed) that can unsubscribe observers.
11
- * @internal
12
- */
13
- export interface ReactiveSource {
14
- unsubscribe(observer: Observer): void;
15
- }
16
-
17
- const observerStack: Observer[] = [];
18
- let batchDepth = 0;
19
- const pendingObservers = new Set<Observer>();
20
-
21
- // Track dependencies for each observer to enable cleanup
22
- const observerDependencies = new WeakMap<Observer, Set<ReactiveSource>>();
23
-
24
- export const track = <T>(observer: Observer, fn: () => T): T => {
25
- observerStack.push(observer);
26
- try {
27
- return fn();
28
- } finally {
29
- observerStack.pop();
30
- }
31
- };
32
-
33
- export const getCurrentObserver = (): Observer | undefined =>
34
- observerStack[observerStack.length - 1];
35
-
36
- /**
37
- * Executes a function without exposing the current observer to dependencies.
38
- * Unlike disabling tracking globally, this still allows nested reactive internals
39
- * (e.g., computed recomputation) to track their own dependencies.
40
- * @internal
41
- */
42
- export const withoutCurrentObserver = <T>(fn: () => T): T => {
43
- // Push undefined to temporarily "hide" the current observer
44
- // This way, Signal.value reads won't link to the previous observer,
45
- // but nested track() calls (e.g., computed recompute) still work normally.
46
- observerStack.push(undefined as unknown as Observer);
47
- try {
48
- return fn();
49
- } finally {
50
- observerStack.pop();
51
- }
52
- };
53
-
54
- export const scheduleObserver = (observer: Observer): void => {
55
- if (batchDepth > 0) {
56
- pendingObservers.add(observer);
57
- return;
58
- }
59
- observer();
60
- };
61
-
62
- const flushObservers = (): void => {
63
- for (const observer of Array.from(pendingObservers)) {
64
- pendingObservers.delete(observer);
65
- try {
66
- observer();
67
- } catch (error) {
68
- console.error('bQuery reactive: Error in observer during batch flush', error);
69
- }
70
- }
71
- };
72
-
73
- export const beginBatch = (): void => {
74
- batchDepth += 1;
75
- };
76
-
77
- export const endBatch = (): void => {
78
- if (batchDepth <= 0) return;
79
- batchDepth -= 1;
80
- if (batchDepth === 0) {
81
- flushObservers();
82
- }
83
- };
84
-
85
- /**
86
- * Registers a dependency between an observer and a reactive source.
87
- * @internal
88
- */
89
- export const registerDependency = (observer: Observer, source: ReactiveSource): void => {
90
- let deps = observerDependencies.get(observer);
91
- if (!deps) {
92
- deps = new Set();
93
- observerDependencies.set(observer, deps);
94
- }
95
- deps.add(source);
96
- };
97
-
98
- /**
99
- * Removes a specific source from an observer's dependency set.
100
- * Used when a source (e.g. Signal) is disposed to prevent stale references.
101
- * @internal
102
- */
103
- export const removeDependency = (observer: Observer, source: ReactiveSource): void => {
104
- const deps = observerDependencies.get(observer);
105
- if (deps) {
106
- deps.delete(source);
107
- }
108
- };
109
-
110
- /**
111
- * Clears all dependencies for an observer, unsubscribing from all sources.
112
- * @internal
113
- */
114
- export const clearDependencies = (observer: Observer): void => {
115
- const deps = observerDependencies.get(observer);
116
- if (deps) {
117
- for (const source of deps) {
118
- source.unsubscribe(observer);
119
- }
120
- deps.clear();
121
- }
122
- };
1
+ /**
2
+ * Internal reactive plumbing shared across primitives.
3
+ * @internal
4
+ */
5
+
6
+ export type Observer = () => void;
7
+ export type CleanupFn = () => void;
8
+
9
+ /**
10
+ * Interface for reactive sources (Signals, Computed) that can unsubscribe observers.
11
+ * @internal
12
+ */
13
+ export interface ReactiveSource {
14
+ unsubscribe(observer: Observer): void;
15
+ }
16
+
17
+ const observerStack: Observer[] = [];
18
+ let batchDepth = 0;
19
+ const pendingObservers = new Set<Observer>();
20
+
21
+ // Track dependencies for each observer to enable cleanup
22
+ const observerDependencies = new WeakMap<Observer, Set<ReactiveSource>>();
23
+
24
+ export const track = <T>(observer: Observer, fn: () => T): T => {
25
+ observerStack.push(observer);
26
+ try {
27
+ return fn();
28
+ } finally {
29
+ observerStack.pop();
30
+ }
31
+ };
32
+
33
+ export const getCurrentObserver = (): Observer | undefined =>
34
+ observerStack[observerStack.length - 1];
35
+
36
+ /**
37
+ * Executes a function without exposing the current observer to dependencies.
38
+ * Unlike disabling tracking globally, this still allows nested reactive internals
39
+ * (e.g., computed recomputation) to track their own dependencies.
40
+ * @internal
41
+ */
42
+ export const withoutCurrentObserver = <T>(fn: () => T): T => {
43
+ // Push undefined to temporarily "hide" the current observer
44
+ // This way, Signal.value reads won't link to the previous observer,
45
+ // but nested track() calls (e.g., computed recompute) still work normally.
46
+ observerStack.push(undefined as unknown as Observer);
47
+ try {
48
+ return fn();
49
+ } finally {
50
+ observerStack.pop();
51
+ }
52
+ };
53
+
54
+ export const scheduleObserver = (observer: Observer): void => {
55
+ if (batchDepth > 0) {
56
+ pendingObservers.add(observer);
57
+ return;
58
+ }
59
+ observer();
60
+ };
61
+
62
+ const flushObservers = (): void => {
63
+ for (const observer of Array.from(pendingObservers)) {
64
+ pendingObservers.delete(observer);
65
+ try {
66
+ observer();
67
+ } catch (error) {
68
+ console.error('bQuery reactive: Error in observer during batch flush', error);
69
+ }
70
+ }
71
+ };
72
+
73
+ export const beginBatch = (): void => {
74
+ batchDepth += 1;
75
+ };
76
+
77
+ export const endBatch = (): void => {
78
+ if (batchDepth <= 0) return;
79
+ batchDepth -= 1;
80
+ if (batchDepth === 0) {
81
+ flushObservers();
82
+ }
83
+ };
84
+
85
+ /**
86
+ * Registers a dependency between an observer and a reactive source.
87
+ * @internal
88
+ */
89
+ export const registerDependency = (observer: Observer, source: ReactiveSource): void => {
90
+ let deps = observerDependencies.get(observer);
91
+ if (!deps) {
92
+ deps = new Set();
93
+ observerDependencies.set(observer, deps);
94
+ }
95
+ deps.add(source);
96
+ };
97
+
98
+ /**
99
+ * Removes a specific source from an observer's dependency set.
100
+ * Used when a source (e.g. Signal) is disposed to prevent stale references.
101
+ * @internal
102
+ */
103
+ export const removeDependency = (observer: Observer, source: ReactiveSource): void => {
104
+ const deps = observerDependencies.get(observer);
105
+ if (deps) {
106
+ deps.delete(source);
107
+ }
108
+ };
109
+
110
+ /**
111
+ * Clears all dependencies for an observer, unsubscribing from all sources.
112
+ * @internal
113
+ */
114
+ export const clearDependencies = (observer: Observer): void => {
115
+ const deps = observerDependencies.get(observer);
116
+ if (deps) {
117
+ for (const source of deps) {
118
+ source.unsubscribe(observer);
119
+ }
120
+ deps.clear();
121
+ }
122
+ };
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  export { batch } from './batch';
8
+ export { createUseFetch, useAsyncData, useFetch } from './async-data';
8
9
  export { Computed, computed } from './computed';
9
10
  export { Signal, signal } from './core';
10
11
  export { effect } from './effect';
@@ -16,5 +17,13 @@ export { untrack } from './untrack';
16
17
  export { watch } from './watch';
17
18
 
18
19
  export type { CleanupFn, Observer } from './internals';
20
+ export type {
21
+ AsyncDataState,
22
+ AsyncDataStatus,
23
+ AsyncWatchSource,
24
+ FetchInput,
25
+ UseAsyncDataOptions,
26
+ UseFetchOptions,
27
+ } from './async-data';
19
28
  export type { LinkedSignal } from './linked';
20
29
  export type { ReadonlySignal } from './readonly';
@@ -116,7 +116,9 @@ export const DANGEROUS_TAGS = new Set([
116
116
  'style',
117
117
  'base',
118
118
  'template',
119
- 'slot',
119
+ // 'slot' is intentionally excluded here so component shadow markup can opt in
120
+ // via sanitizeHtml(..., { allowTags: ['slot'] }). It remains disallowed by default
121
+ // for general HTML writes, because DEFAULT_ALLOWED_TAGS does not include it.
120
122
  'math',
121
123
  'svg',
122
124
  'foreignobject',
@@ -1,10 +1,17 @@
1
- /**
2
- * Security module providing sanitization, CSP compatibility, and Trusted Types.
3
- *
4
- * @module bquery/security
5
- */
6
-
7
- export { generateNonce, hasCSPDirective } from './csp';
8
- export { escapeHtml, sanitizeHtml as sanitize, sanitizeHtml, stripTags } from './sanitize';
9
- export { createTrustedHtml, getTrustedTypesPolicy, isTrustedTypesSupported } from './trusted-types';
10
- export type { SanitizeOptions } from './types';
1
+ /**
2
+ * Security module providing sanitization, CSP compatibility, and Trusted Types.
3
+ *
4
+ * @module bquery/security
5
+ */
6
+
7
+ export { generateNonce, hasCSPDirective } from './csp';
8
+ export {
9
+ escapeHtml,
10
+ sanitizeHtml as sanitize,
11
+ sanitizeHtml,
12
+ stripTags,
13
+ } from './sanitize';
14
+ export { trusted } from './trusted-html';
15
+ export { createTrustedHtml, getTrustedTypesPolicy, isTrustedTypesSupported } from './trusted-types';
16
+ export type { SanitizedHtml, TrustedHtml } from './trusted-html';
17
+ export type { SanitizeOptions } from './sanitize';