@bquery/bquery 1.5.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 (106) hide show
  1. package/README.md +586 -546
  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 +2 -2
  7. package/dist/component/index.d.ts.map +1 -1
  8. package/dist/component/library.d.ts.map +1 -1
  9. package/dist/component/types.d.ts +131 -16
  10. package/dist/component/types.d.ts.map +1 -1
  11. package/dist/component-BEQgt5hl.js +600 -0
  12. package/dist/component-BEQgt5hl.js.map +1 -0
  13. package/dist/component.es.mjs +7 -6
  14. package/dist/config-DRmZZno3.js.map +1 -1
  15. package/dist/core-BGQJVw0-.js +35 -0
  16. package/dist/core-BGQJVw0-.js.map +1 -0
  17. package/dist/{core-CK2Mfpf4.js → core-CCEabVHl.js} +2 -2
  18. package/dist/{core-CK2Mfpf4.js.map → core-CCEabVHl.js.map} +1 -1
  19. package/dist/core.es.mjs +1 -1
  20. package/dist/effect-AFRW_Plg.js +84 -0
  21. package/dist/effect-AFRW_Plg.js.map +1 -0
  22. package/dist/full.d.ts +4 -4
  23. package/dist/full.d.ts.map +1 -1
  24. package/dist/full.es.mjs +98 -94
  25. package/dist/full.iife.js +14 -14
  26. package/dist/full.iife.js.map +1 -1
  27. package/dist/full.umd.js +14 -14
  28. package/dist/full.umd.js.map +1 -1
  29. package/dist/index.es.mjs +143 -139
  30. package/dist/{motion-C5DRdPnO.js → motion-D9TcHxOF.js} +1 -1
  31. package/dist/{motion-C5DRdPnO.js.map → motion-D9TcHxOF.js.map} +1 -1
  32. package/dist/motion.es.mjs +1 -1
  33. package/dist/{platform-B7JhGBc7.js → platform-Dr9b6fsq.js} +21 -20
  34. package/dist/platform-Dr9b6fsq.js.map +1 -0
  35. package/dist/platform.es.mjs +1 -1
  36. package/dist/{reactive-BDya-ia8.js → reactive-DSkct0dO.js} +51 -50
  37. package/dist/reactive-DSkct0dO.js.map +1 -0
  38. package/dist/reactive.es.mjs +19 -17
  39. package/dist/{router-CijiICxt.js → router-CbDhl8rS.js} +3 -3
  40. package/dist/{router-CijiICxt.js.map → router-CbDhl8rS.js.map} +1 -1
  41. package/dist/router.es.mjs +1 -1
  42. package/dist/{sanitize-jyJ2ryE2.js → sanitize-Bs2dkMby.js} +94 -83
  43. package/dist/sanitize-Bs2dkMby.js.map +1 -0
  44. package/dist/security/index.d.ts +4 -2
  45. package/dist/security/index.d.ts.map +1 -1
  46. package/dist/security/sanitize.d.ts +4 -1
  47. package/dist/security/sanitize.d.ts.map +1 -1
  48. package/dist/security/trusted-html.d.ts +53 -0
  49. package/dist/security/trusted-html.d.ts.map +1 -0
  50. package/dist/security.es.mjs +10 -9
  51. package/dist/store/define-store.d.ts +1 -1
  52. package/dist/store/define-store.d.ts.map +1 -1
  53. package/dist/store/mapping.d.ts +1 -1
  54. package/dist/store/mapping.d.ts.map +1 -1
  55. package/dist/store/persisted.d.ts +1 -1
  56. package/dist/store/persisted.d.ts.map +1 -1
  57. package/dist/store/types.d.ts +2 -2
  58. package/dist/store/types.d.ts.map +1 -1
  59. package/dist/store/watch.d.ts +1 -1
  60. package/dist/store/watch.d.ts.map +1 -1
  61. package/dist/{store-CPK9E62U.js → store-BwDvI45q.js} +49 -48
  62. package/dist/{store-CPK9E62U.js.map → store-BwDvI45q.js.map} +1 -1
  63. package/dist/store.es.mjs +1 -1
  64. package/dist/storybook/index.d.ts +37 -0
  65. package/dist/storybook/index.d.ts.map +1 -0
  66. package/dist/storybook.es.mjs +151 -0
  67. package/dist/storybook.es.mjs.map +1 -0
  68. package/dist/untrack-B0rVscTc.js +7 -0
  69. package/dist/untrack-B0rVscTc.js.map +1 -0
  70. package/dist/{view-Cdi0g-qo.js → view-C70lA3vf.js} +29 -28
  71. package/dist/{view-Cdi0g-qo.js.map → view-C70lA3vf.js.map} +1 -1
  72. package/dist/view.es.mjs +9 -8
  73. package/package.json +141 -136
  74. package/src/component/component.ts +259 -54
  75. package/src/component/html.ts +153 -53
  76. package/src/component/index.ts +10 -2
  77. package/src/component/library.ts +42 -28
  78. package/src/component/types.ts +184 -19
  79. package/src/full.ts +8 -2
  80. package/src/motion/transition.ts +97 -97
  81. package/src/motion/types.ts +208 -208
  82. package/src/platform/announcer.ts +208 -208
  83. package/src/platform/config.ts +163 -163
  84. package/src/platform/cookies.ts +165 -165
  85. package/src/platform/index.ts +39 -39
  86. package/src/platform/meta.ts +168 -168
  87. package/src/reactive/async-data.ts +486 -486
  88. package/src/reactive/index.ts +37 -37
  89. package/src/reactive/signal.ts +29 -29
  90. package/src/security/constants.ts +211 -211
  91. package/src/security/index.ts +17 -10
  92. package/src/security/sanitize.ts +70 -66
  93. package/src/security/trusted-html.ts +71 -0
  94. package/src/store/define-store.ts +49 -48
  95. package/src/store/mapping.ts +74 -73
  96. package/src/store/persisted.ts +62 -61
  97. package/src/store/types.ts +92 -94
  98. package/src/store/watch.ts +53 -52
  99. package/src/storybook/index.ts +479 -0
  100. package/dist/component-CY5MVoYN.js +0 -531
  101. package/dist/component-CY5MVoYN.js.map +0 -1
  102. package/dist/core-DPdbItcq.js +0 -112
  103. package/dist/core-DPdbItcq.js.map +0 -1
  104. package/dist/platform-B7JhGBc7.js.map +0 -1
  105. package/dist/reactive-BDya-ia8.js.map +0 -1
  106. package/dist/sanitize-jyJ2ryE2.js.map +0 -1
@@ -1,208 +1,208 @@
1
- /**
2
- * Accessibility live-region announcer helpers.
3
- *
4
- * @module bquery/platform
5
- */
6
-
7
- import { effect, signal, type Signal } from '../reactive/signal';
8
- import { getBqueryConfig } from './config';
9
-
10
- /** Options for creating an announcer. */
11
- export interface UseAnnouncerOptions {
12
- /** Live region politeness. */
13
- politeness?: 'polite' | 'assertive';
14
- /** Whether the live region should be atomic. */
15
- atomic?: boolean;
16
- /** Delay before applying the message. */
17
- delay?: number;
18
- /** Delay after which the message is cleared automatically. */
19
- clearDelay?: number;
20
- /** Optional element id for the live region. */
21
- id?: string;
22
- /** Optional CSS class name. */
23
- className?: string;
24
- /** Optional container used to append the live region. */
25
- container?: HTMLElement;
26
- }
27
-
28
- /** Runtime options for a single announcement. */
29
- export interface AnnounceOptions {
30
- /** Override politeness for this specific announcement. */
31
- politeness?: 'polite' | 'assertive';
32
- /** Override the message delay for this specific announcement. */
33
- delay?: number;
34
- /** Override the auto-clear delay for this specific announcement. */
35
- clearDelay?: number;
36
- }
37
-
38
- /** Returned announcer API. */
39
- export interface AnnouncerHandle {
40
- /** The live region element or null outside the DOM. */
41
- element: HTMLElement | null;
42
- /** Reactive message signal. */
43
- message: Signal<string>;
44
- /** Announce a message to assistive technologies. */
45
- announce: (value: string, options?: AnnounceOptions) => void;
46
- /** Clear the current announcement. */
47
- clear: () => void;
48
- /** Remove the live region if it was created by this announcer. */
49
- destroy: () => void;
50
- }
51
-
52
- const visuallyHiddenStyle = [
53
- 'position:absolute',
54
- 'width:1px',
55
- 'height:1px',
56
- 'padding:0',
57
- 'margin:-1px',
58
- 'overflow:hidden',
59
- 'clip:rect(0, 0, 0, 0)',
60
- 'white-space:nowrap',
61
- 'border:0',
62
- ].join(';');
63
-
64
- /**
65
- * Create or reuse an accessible live region.
66
- *
67
- * @param options - Live region configuration
68
- * @returns An announcer handle with announce(), clear(), and destroy()
69
- *
70
- * @example
71
- * ```ts
72
- * const announcer = useAnnouncer();
73
- * announcer.announce('Saved successfully');
74
- * ```
75
- */
76
- export const useAnnouncer = (options: UseAnnouncerOptions = {}): AnnouncerHandle => {
77
- const defaults = getBqueryConfig().announcer;
78
- const resolvedOptions: Required<
79
- Pick<UseAnnouncerOptions, 'politeness' | 'atomic' | 'delay' | 'clearDelay'>
80
- > &
81
- UseAnnouncerOptions = {
82
- politeness: defaults?.politeness ?? 'polite',
83
- atomic: defaults?.atomic ?? true,
84
- delay: defaults?.delay ?? 16,
85
- clearDelay: defaults?.clearDelay ?? 1000,
86
- ...options,
87
- };
88
-
89
- const message = signal('');
90
-
91
- if (typeof document === 'undefined') {
92
- return {
93
- element: null,
94
- message,
95
- announce(value: string) {
96
- message.value = value;
97
- },
98
- clear() {
99
- message.value = '';
100
- },
101
- destroy() {
102
- message.value = '';
103
- },
104
- };
105
- }
106
-
107
- const existing = resolvedOptions.id ? document.getElementById(resolvedOptions.id) : null;
108
- const element = (existing ?? document.createElement('div')) as HTMLElement;
109
- const created = !existing;
110
-
111
- if (resolvedOptions.id) {
112
- element.id = resolvedOptions.id;
113
- }
114
-
115
- if (resolvedOptions.className) {
116
- element.className = resolvedOptions.className;
117
- }
118
-
119
- element.setAttribute('aria-live', resolvedOptions.politeness);
120
- element.setAttribute('aria-atomic', String(resolvedOptions.atomic));
121
- element.setAttribute('role', resolvedOptions.politeness === 'assertive' ? 'alert' : 'status');
122
- element.setAttribute('data-bquery-announcer', 'true');
123
- if (!element.getAttribute('style')) {
124
- element.setAttribute('style', visuallyHiddenStyle);
125
- }
126
-
127
- if (created) {
128
- const parent = resolvedOptions.container ?? document.body ?? document.documentElement;
129
- if (!parent) {
130
- return {
131
- element: null,
132
- message,
133
- announce(value: string) {
134
- message.value = value;
135
- },
136
- clear() {
137
- message.value = '';
138
- },
139
- destroy() {
140
- message.value = '';
141
- },
142
- };
143
- }
144
- parent.appendChild(element);
145
- }
146
-
147
- const disposeMessageEffect = effect(() => {
148
- element.textContent = message.value;
149
- });
150
-
151
- let messageTimer: ReturnType<typeof setTimeout> | undefined;
152
- let clearTimer: ReturnType<typeof setTimeout> | undefined;
153
- let destroyed = false;
154
-
155
- const clearTimers = (): void => {
156
- if (messageTimer) {
157
- clearTimeout(messageTimer);
158
- messageTimer = undefined;
159
- }
160
- if (clearTimer) {
161
- clearTimeout(clearTimer);
162
- clearTimer = undefined;
163
- }
164
- };
165
-
166
- const clear = (): void => {
167
- if (destroyed) return;
168
- clearTimers();
169
- message.value = '';
170
- };
171
-
172
- const announce = (value: string, announceOptions: AnnounceOptions = {}): void => {
173
- if (destroyed) return;
174
- const politeness = announceOptions.politeness ?? resolvedOptions.politeness;
175
- const delay = announceOptions.delay ?? resolvedOptions.delay;
176
- const clearDelay = announceOptions.clearDelay ?? resolvedOptions.clearDelay;
177
-
178
- clearTimers();
179
-
180
- element.setAttribute('aria-live', politeness);
181
- element.setAttribute('role', politeness === 'assertive' ? 'alert' : 'status');
182
- message.value = '';
183
-
184
- messageTimer = setTimeout(() => {
185
- if (destroyed) return;
186
- message.value = value;
187
- if (clearDelay > 0) {
188
- clearTimer = setTimeout(() => {
189
- if (destroyed) return;
190
- message.value = '';
191
- }, clearDelay);
192
- }
193
- }, delay);
194
- };
195
-
196
- const destroy = (): void => {
197
- if (destroyed) return;
198
- destroyed = true;
199
- clearTimers();
200
- message.value = '';
201
- disposeMessageEffect();
202
- if (created) {
203
- element.remove();
204
- }
205
- };
206
-
207
- return { element, message, announce, clear, destroy };
208
- };
1
+ /**
2
+ * Accessibility live-region announcer helpers.
3
+ *
4
+ * @module bquery/platform
5
+ */
6
+
7
+ import { effect, signal, type Signal } from '../reactive/signal';
8
+ import { getBqueryConfig } from './config';
9
+
10
+ /** Options for creating an announcer. */
11
+ export interface UseAnnouncerOptions {
12
+ /** Live region politeness. */
13
+ politeness?: 'polite' | 'assertive';
14
+ /** Whether the live region should be atomic. */
15
+ atomic?: boolean;
16
+ /** Delay before applying the message. */
17
+ delay?: number;
18
+ /** Delay after which the message is cleared automatically. */
19
+ clearDelay?: number;
20
+ /** Optional element id for the live region. */
21
+ id?: string;
22
+ /** Optional CSS class name. */
23
+ className?: string;
24
+ /** Optional container used to append the live region. */
25
+ container?: HTMLElement;
26
+ }
27
+
28
+ /** Runtime options for a single announcement. */
29
+ export interface AnnounceOptions {
30
+ /** Override politeness for this specific announcement. */
31
+ politeness?: 'polite' | 'assertive';
32
+ /** Override the message delay for this specific announcement. */
33
+ delay?: number;
34
+ /** Override the auto-clear delay for this specific announcement. */
35
+ clearDelay?: number;
36
+ }
37
+
38
+ /** Returned announcer API. */
39
+ export interface AnnouncerHandle {
40
+ /** The live region element or null outside the DOM. */
41
+ element: HTMLElement | null;
42
+ /** Reactive message signal. */
43
+ message: Signal<string>;
44
+ /** Announce a message to assistive technologies. */
45
+ announce: (value: string, options?: AnnounceOptions) => void;
46
+ /** Clear the current announcement. */
47
+ clear: () => void;
48
+ /** Remove the live region if it was created by this announcer. */
49
+ destroy: () => void;
50
+ }
51
+
52
+ const visuallyHiddenStyle = [
53
+ 'position:absolute',
54
+ 'width:1px',
55
+ 'height:1px',
56
+ 'padding:0',
57
+ 'margin:-1px',
58
+ 'overflow:hidden',
59
+ 'clip:rect(0, 0, 0, 0)',
60
+ 'white-space:nowrap',
61
+ 'border:0',
62
+ ].join(';');
63
+
64
+ /**
65
+ * Create or reuse an accessible live region.
66
+ *
67
+ * @param options - Live region configuration
68
+ * @returns An announcer handle with announce(), clear(), and destroy()
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const announcer = useAnnouncer();
73
+ * announcer.announce('Saved successfully');
74
+ * ```
75
+ */
76
+ export const useAnnouncer = (options: UseAnnouncerOptions = {}): AnnouncerHandle => {
77
+ const defaults = getBqueryConfig().announcer;
78
+ const resolvedOptions: Required<
79
+ Pick<UseAnnouncerOptions, 'politeness' | 'atomic' | 'delay' | 'clearDelay'>
80
+ > &
81
+ UseAnnouncerOptions = {
82
+ politeness: defaults?.politeness ?? 'polite',
83
+ atomic: defaults?.atomic ?? true,
84
+ delay: defaults?.delay ?? 16,
85
+ clearDelay: defaults?.clearDelay ?? 1000,
86
+ ...options,
87
+ };
88
+
89
+ const message = signal('');
90
+
91
+ if (typeof document === 'undefined') {
92
+ return {
93
+ element: null,
94
+ message,
95
+ announce(value: string) {
96
+ message.value = value;
97
+ },
98
+ clear() {
99
+ message.value = '';
100
+ },
101
+ destroy() {
102
+ message.value = '';
103
+ },
104
+ };
105
+ }
106
+
107
+ const existing = resolvedOptions.id ? document.getElementById(resolvedOptions.id) : null;
108
+ const element = (existing ?? document.createElement('div')) as HTMLElement;
109
+ const created = !existing;
110
+
111
+ if (resolvedOptions.id) {
112
+ element.id = resolvedOptions.id;
113
+ }
114
+
115
+ if (resolvedOptions.className) {
116
+ element.className = resolvedOptions.className;
117
+ }
118
+
119
+ element.setAttribute('aria-live', resolvedOptions.politeness);
120
+ element.setAttribute('aria-atomic', String(resolvedOptions.atomic));
121
+ element.setAttribute('role', resolvedOptions.politeness === 'assertive' ? 'alert' : 'status');
122
+ element.setAttribute('data-bquery-announcer', 'true');
123
+ if (!element.getAttribute('style')) {
124
+ element.setAttribute('style', visuallyHiddenStyle);
125
+ }
126
+
127
+ if (created) {
128
+ const parent = resolvedOptions.container ?? document.body ?? document.documentElement;
129
+ if (!parent) {
130
+ return {
131
+ element: null,
132
+ message,
133
+ announce(value: string) {
134
+ message.value = value;
135
+ },
136
+ clear() {
137
+ message.value = '';
138
+ },
139
+ destroy() {
140
+ message.value = '';
141
+ },
142
+ };
143
+ }
144
+ parent.appendChild(element);
145
+ }
146
+
147
+ const disposeMessageEffect = effect(() => {
148
+ element.textContent = message.value;
149
+ });
150
+
151
+ let messageTimer: ReturnType<typeof setTimeout> | undefined;
152
+ let clearTimer: ReturnType<typeof setTimeout> | undefined;
153
+ let destroyed = false;
154
+
155
+ const clearTimers = (): void => {
156
+ if (messageTimer) {
157
+ clearTimeout(messageTimer);
158
+ messageTimer = undefined;
159
+ }
160
+ if (clearTimer) {
161
+ clearTimeout(clearTimer);
162
+ clearTimer = undefined;
163
+ }
164
+ };
165
+
166
+ const clear = (): void => {
167
+ if (destroyed) return;
168
+ clearTimers();
169
+ message.value = '';
170
+ };
171
+
172
+ const announce = (value: string, announceOptions: AnnounceOptions = {}): void => {
173
+ if (destroyed) return;
174
+ const politeness = announceOptions.politeness ?? resolvedOptions.politeness;
175
+ const delay = announceOptions.delay ?? resolvedOptions.delay;
176
+ const clearDelay = announceOptions.clearDelay ?? resolvedOptions.clearDelay;
177
+
178
+ clearTimers();
179
+
180
+ element.setAttribute('aria-live', politeness);
181
+ element.setAttribute('role', politeness === 'assertive' ? 'alert' : 'status');
182
+ message.value = '';
183
+
184
+ messageTimer = setTimeout(() => {
185
+ if (destroyed) return;
186
+ message.value = value;
187
+ if (clearDelay > 0) {
188
+ clearTimer = setTimeout(() => {
189
+ if (destroyed) return;
190
+ message.value = '';
191
+ }, clearDelay);
192
+ }
193
+ }, delay);
194
+ };
195
+
196
+ const destroy = (): void => {
197
+ if (destroyed) return;
198
+ destroyed = true;
199
+ clearTimers();
200
+ message.value = '';
201
+ disposeMessageEffect();
202
+ if (created) {
203
+ element.remove();
204
+ }
205
+ };
206
+
207
+ return { element, message, announce, clear, destroy };
208
+ };