@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,310 +1,310 @@
1
- /**
2
- * Component types and render context definitions.
3
- *
4
- * @module bquery/component
5
- */
6
-
7
- import type { SanitizeOptions } from '../security/types';
8
-
9
- /**
10
- * Defines a single prop's type and configuration.
11
- *
12
- * @template T - The TypeScript type of the prop value
13
- *
14
- * @example
15
- * ```ts
16
- * const myProp: PropDefinition<number> = {
17
- * type: Number,
18
- * required: false,
19
- * default: 0,
20
- * };
21
- * ```
22
- */
23
- export type PropDefinition<T = unknown> = {
24
- /** Constructor or converter function for the prop type */
25
- type:
26
- | StringConstructor
27
- | NumberConstructor
28
- | BooleanConstructor
29
- | ObjectConstructor
30
- | ArrayConstructor
31
- | { new (value: unknown): T }
32
- | ((value: unknown) => T);
33
- /** Whether the prop must be provided */
34
- required?: boolean;
35
- /** Default value when prop is not provided */
36
- default?: T;
37
- /** Optional validator function to validate prop values */
38
- validator?: (value: T) => boolean;
39
- /**
40
- * Explicitly control whether to invoke `type` with `new` (constructor) or as a plain function.
41
- * - `true`: Always use `new type(value)` (for class constructors, Date, etc.)
42
- * - `false`: Always call `type(value)` (for converter functions)
43
- * - `undefined` (default): Auto-detect based on heuristics with fallback
44
- */
45
- construct?: boolean;
46
- };
47
-
48
- /**
49
- * Resolves the concrete runtime state shape exposed by component APIs.
50
- *
51
- * When no explicit state generic is provided, component state falls back to
52
- * an untyped string-keyed record for backwards compatibility.
53
- */
54
- export type ComponentStateShape<TState extends Record<string, unknown> | undefined = undefined> =
55
- TState extends Record<string, unknown> ? TState : Record<string, unknown>;
56
-
57
- /**
58
- * Component state keys are string-based because runtime state access is backed
59
- * by plain object properties.
60
- */
61
- export type ComponentStateKey<TState extends Record<string, unknown> | undefined = undefined> =
62
- keyof ComponentStateShape<TState> & string;
63
-
64
- /**
65
- * Public component element instance shape exposed by lifecycle hooks and
66
- * `defineComponent()` return values.
67
- */
68
- export type ComponentElement<TState extends Record<string, unknown> | undefined = undefined> =
69
- HTMLElement & {
70
- /**
71
- * Updates a state property and triggers a re-render.
72
- *
73
- * @param key - The state property key
74
- * @param value - The new value
75
- */
76
- setState<TKey extends ComponentStateKey<TState>>(
77
- key: TKey,
78
- value: ComponentStateShape<TState>[TKey]
79
- ): void;
80
- /**
81
- * Gets a state property value.
82
- *
83
- * @param key - The state property key
84
- * @returns The current value
85
- */
86
- getState<TKey extends ComponentStateKey<TState>>(key: TKey): ComponentStateShape<TState>[TKey];
87
- /**
88
- * Gets a state property value with an explicit cast for backwards
89
- * compatibility with the pre-typed-state API.
90
- *
91
- * @param key - The state property key
92
- * @returns The current value cast to `TResult`
93
- */
94
- getState<TResult = unknown>(key: string): TResult;
95
- };
96
-
97
- /**
98
- * Constructor returned by `defineComponent()`.
99
- */
100
- export type ComponentClass<TState extends Record<string, unknown> | undefined = undefined> =
101
- CustomElementConstructor & {
102
- new (): ComponentElement<TState>;
103
- prototype: ComponentElement<TState>;
104
- readonly observedAttributes: string[];
105
- };
106
-
107
- /**
108
- * Minimal reactive source shape supported by component `signals`.
109
- *
110
- * @template T - Value exposed by the signal-like source
111
- */
112
- export type ComponentSignalLike<T = unknown> = {
113
- /** Gets the current reactive value */
114
- readonly value: T;
115
- /** Gets the current value without dependency tracking */
116
- peek(): T;
117
- };
118
-
119
- /**
120
- * Named reactive sources that can drive component re-renders.
121
- */
122
- export type ComponentSignals = Record<string, ComponentSignalLike<unknown>>;
123
-
124
- /**
125
- * Render context passed into a component render function.
126
- *
127
- * @template TProps - Type of the component's props
128
- * @template TState - Type of the component's internal state
129
- * @template TSignals - Declared reactive sources available during render
130
- */
131
- export type ComponentRenderContext<
132
- TProps extends Record<string, unknown>,
133
- TState extends Record<string, unknown> | undefined = undefined,
134
- TSignals extends ComponentSignals = Record<string, never>,
135
- > = {
136
- /** Typed props object populated from attributes */
137
- props: TProps;
138
- /** Internal mutable state object */
139
- state: ComponentStateShape<TState>;
140
- /** External reactive sources subscribed for re-rendering */
141
- signals: TSignals;
142
- /** Emit a custom event from the component */
143
- emit: (event: string, detail?: unknown) => void;
144
- };
145
-
146
- /**
147
- * Describes an observed attribute change that triggered a component update.
148
- */
149
- export type AttributeChange = {
150
- /** The observed attribute name */
151
- name: string;
152
- /** The previous serialized attribute value */
153
- oldValue: string | null;
154
- /** The next serialized attribute value */
155
- newValue: string | null;
156
- };
157
-
158
- /**
159
- * Complete component definition including props, state, styles, and lifecycle.
160
- *
161
- * @template TProps - Type of the component's props
162
- * @template TState - Type of the component's internal state
163
- */
164
- /*
165
- * Lifecycle hooks use dynamic `this` when declared with method/function syntax.
166
- * Arrow functions capture outer scope, so component APIs like `this.getState()`
167
- * are only available from method/function syntax.
168
- */
169
- type ComponentSanitizeOptions = Pick<SanitizeOptions, 'allowTags' | 'allowAttributes'>;
170
- type ComponentHook<
171
- TState extends Record<string, unknown> | undefined = undefined,
172
- TResult = void,
173
- > = {
174
- (this: ComponentElement<TState>): TResult;
175
- (): TResult;
176
- };
177
- type ComponentHookWithProps<
178
- TProps extends Record<string, unknown>,
179
- TState extends Record<string, unknown> | undefined = undefined,
180
- TResult = void,
181
- > = {
182
- (this: ComponentElement<TState>, newProps: TProps, oldProps: TProps): TResult;
183
- (newProps: TProps, oldProps: TProps): TResult;
184
- };
185
- type ComponentUpdatedHook<
186
- TState extends Record<string, unknown> | undefined = undefined,
187
- TResult = void,
188
- > = {
189
- (this: ComponentElement<TState>, change?: AttributeChange): TResult;
190
- (change?: AttributeChange): TResult;
191
- };
192
- type ComponentErrorHook<TState extends Record<string, unknown> | undefined = undefined> = {
193
- (this: ComponentElement<TState>, error: Error): void;
194
- (error: Error): void;
195
- };
196
-
197
- type ComponentAttributeChangedHook<TState extends Record<string, unknown> | undefined = undefined> =
198
- {
199
- (
200
- this: ComponentElement<TState>,
201
- name: string,
202
- oldValue: string | null,
203
- newValue: string | null
204
- ): void;
205
- (name: string, oldValue: string | null, newValue: string | null): void;
206
- };
207
-
208
- type ComponentStateDefinition<TState extends Record<string, unknown> | undefined = undefined> =
209
- TState extends Record<string, unknown>
210
- ? {
211
- /** Initial internal state */
212
- state: TState;
213
- }
214
- : {
215
- /** Initial internal state */
216
- state?: Record<string, unknown>;
217
- };
218
-
219
- type ComponentSignalsDefinition<TSignals extends ComponentSignals = Record<string, never>> =
220
- TSignals extends Record<string, never>
221
- ? {
222
- /** External signals/computed values that should trigger re-renders */
223
- signals?: TSignals;
224
- }
225
- : {
226
- /** External signals/computed values that should trigger re-renders */
227
- signals: TSignals;
228
- };
229
-
230
- /**
231
- * Controls Shadow DOM mode for the component.
232
- *
233
- * - `true` or `'open'` — attach an open shadow root (default)
234
- * - `'closed'` — attach a closed shadow root
235
- * - `false` — no shadow root; render directly into the host element
236
- */
237
- export type ShadowMode = boolean | 'open' | 'closed';
238
-
239
- export type ComponentDefinition<
240
- TProps extends Record<string, unknown> = Record<string, unknown>,
241
- TState extends Record<string, unknown> | undefined = undefined,
242
- TSignals extends ComponentSignals = Record<string, never>,
243
- > = ComponentStateDefinition<TState> &
244
- ComponentSignalsDefinition<TSignals> & {
245
- /** Prop definitions with types and defaults */
246
- props?: Record<keyof TProps, PropDefinition>;
247
- /**
248
- * CSS styles injected for the component.
249
- *
250
- * When `shadow` uses a shadow root (`true`, `'open'`, or `'closed'`), these
251
- * styles are scoped to that shadow tree. When `shadow` is `false`, the
252
- * generated `<style>` element is rendered into the host's light DOM and may
253
- * therefore affect surrounding markup according to normal CSS cascade rules.
254
- */
255
- styles?: string;
256
- /**
257
- * Controls Shadow DOM mode.
258
- *
259
- * - `true` or `'open'` — open shadow root (default)
260
- * - `'closed'` — closed shadow root
261
- * - `false` — no shadow root; render into the host element
262
- *
263
- * @default true
264
- */
265
- shadow?: ShadowMode;
266
- /**
267
- * Extra sanitizer options merged with the framework base allowlist during render.
268
- * Only opt in attributes/tags whose values you control or validate. Sensitive
269
- * attributes such as `style` are not value-sanitized and can reintroduce XSS
270
- * or UI-redressing risks if used with untrusted input.
271
- */
272
- sanitize?: ComponentSanitizeOptions;
273
- /**
274
- * Additional attributes to observe beyond those declared in `props`.
275
- *
276
- * Useful when you want `onAttributeChanged` to fire for attributes
277
- * that are not part of the typed props system.
278
- */
279
- observeAttributes?: string[];
280
- /** Lifecycle hook called before the component mounts (before first render) */
281
- beforeMount?: ComponentHook<TState>;
282
- /** Lifecycle hook called when component is added to DOM */
283
- connected?: ComponentHook<TState>;
284
- /** Lifecycle hook called when component is removed from DOM */
285
- disconnected?: ComponentHook<TState>;
286
- /**
287
- * Lifecycle hook called when the component is moved to a new document
288
- * (e.g. via `document.adoptNode`).
289
- */
290
- onAdopted?: ComponentHook<TState>;
291
- /**
292
- * Lifecycle hook called when any observed attribute changes.
293
- *
294
- * Observed attributes are automatically derived from `props` keys
295
- * plus any additional names in `observeAttributes`.
296
- *
297
- * @param name - The attribute name that changed
298
- * @param oldValue - The previous attribute value (null if added)
299
- * @param newValue - The new attribute value (null if removed)
300
- */
301
- onAttributeChanged?: ComponentAttributeChangedHook<TState>;
302
- /** Lifecycle hook called before an update render; return false to prevent */
303
- beforeUpdate?: ComponentHookWithProps<TProps, TState, boolean | void>;
304
- /** Lifecycle hook called after update renders; receives attribute change info when applicable */
305
- updated?: ComponentUpdatedHook<TState>;
306
- /** Error handler for errors during rendering or lifecycle */
307
- onError?: ComponentErrorHook<TState>;
308
- /** Render function returning HTML string */
309
- render: (context: ComponentRenderContext<TProps, TState, TSignals>) => string;
310
- };
1
+ /**
2
+ * Component types and render context definitions.
3
+ *
4
+ * @module bquery/component
5
+ */
6
+
7
+ import type { SanitizeOptions } from '../security/types';
8
+
9
+ /**
10
+ * Defines a single prop's type and configuration.
11
+ *
12
+ * @template T - The TypeScript type of the prop value
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const myProp: PropDefinition<number> = {
17
+ * type: Number,
18
+ * required: false,
19
+ * default: 0,
20
+ * };
21
+ * ```
22
+ */
23
+ export type PropDefinition<T = unknown> = {
24
+ /** Constructor or converter function for the prop type */
25
+ type:
26
+ | StringConstructor
27
+ | NumberConstructor
28
+ | BooleanConstructor
29
+ | ObjectConstructor
30
+ | ArrayConstructor
31
+ | { new (value: unknown): T }
32
+ | ((value: unknown) => T);
33
+ /** Whether the prop must be provided */
34
+ required?: boolean;
35
+ /** Default value when prop is not provided */
36
+ default?: T;
37
+ /** Optional validator function to validate prop values */
38
+ validator?: (value: T) => boolean;
39
+ /**
40
+ * Explicitly control whether to invoke `type` with `new` (constructor) or as a plain function.
41
+ * - `true`: Always use `new type(value)` (for class constructors, Date, etc.)
42
+ * - `false`: Always call `type(value)` (for converter functions)
43
+ * - `undefined` (default): Auto-detect based on heuristics with fallback
44
+ */
45
+ construct?: boolean;
46
+ };
47
+
48
+ /**
49
+ * Resolves the concrete runtime state shape exposed by component APIs.
50
+ *
51
+ * When no explicit state generic is provided, component state falls back to
52
+ * an untyped string-keyed record for backwards compatibility.
53
+ */
54
+ export type ComponentStateShape<TState extends Record<string, unknown> | undefined = undefined> =
55
+ TState extends Record<string, unknown> ? TState : Record<string, unknown>;
56
+
57
+ /**
58
+ * Component state keys are string-based because runtime state access is backed
59
+ * by plain object properties.
60
+ */
61
+ export type ComponentStateKey<TState extends Record<string, unknown> | undefined = undefined> =
62
+ keyof ComponentStateShape<TState> & string;
63
+
64
+ /**
65
+ * Public component element instance shape exposed by lifecycle hooks and
66
+ * `defineComponent()` return values.
67
+ */
68
+ export type ComponentElement<TState extends Record<string, unknown> | undefined = undefined> =
69
+ HTMLElement & {
70
+ /**
71
+ * Updates a state property and triggers a re-render.
72
+ *
73
+ * @param key - The state property key
74
+ * @param value - The new value
75
+ */
76
+ setState<TKey extends ComponentStateKey<TState>>(
77
+ key: TKey,
78
+ value: ComponentStateShape<TState>[TKey]
79
+ ): void;
80
+ /**
81
+ * Gets a state property value.
82
+ *
83
+ * @param key - The state property key
84
+ * @returns The current value
85
+ */
86
+ getState<TKey extends ComponentStateKey<TState>>(key: TKey): ComponentStateShape<TState>[TKey];
87
+ /**
88
+ * Gets a state property value with an explicit cast for backwards
89
+ * compatibility with the pre-typed-state API.
90
+ *
91
+ * @param key - The state property key
92
+ * @returns The current value cast to `TResult`
93
+ */
94
+ getState<TResult = unknown>(key: string): TResult;
95
+ };
96
+
97
+ /**
98
+ * Constructor returned by `defineComponent()`.
99
+ */
100
+ export type ComponentClass<TState extends Record<string, unknown> | undefined = undefined> =
101
+ CustomElementConstructor & {
102
+ new (): ComponentElement<TState>;
103
+ prototype: ComponentElement<TState>;
104
+ readonly observedAttributes: string[];
105
+ };
106
+
107
+ /**
108
+ * Minimal reactive source shape supported by component `signals`.
109
+ *
110
+ * @template T - Value exposed by the signal-like source
111
+ */
112
+ export type ComponentSignalLike<T = unknown> = {
113
+ /** Gets the current reactive value */
114
+ readonly value: T;
115
+ /** Gets the current value without dependency tracking */
116
+ peek(): T;
117
+ };
118
+
119
+ /**
120
+ * Named reactive sources that can drive component re-renders.
121
+ */
122
+ export type ComponentSignals = Record<string, ComponentSignalLike<unknown>>;
123
+
124
+ /**
125
+ * Render context passed into a component render function.
126
+ *
127
+ * @template TProps - Type of the component's props
128
+ * @template TState - Type of the component's internal state
129
+ * @template TSignals - Declared reactive sources available during render
130
+ */
131
+ export type ComponentRenderContext<
132
+ TProps extends Record<string, unknown>,
133
+ TState extends Record<string, unknown> | undefined = undefined,
134
+ TSignals extends ComponentSignals = Record<string, never>,
135
+ > = {
136
+ /** Typed props object populated from attributes */
137
+ props: TProps;
138
+ /** Internal mutable state object */
139
+ state: ComponentStateShape<TState>;
140
+ /** External reactive sources subscribed for re-rendering */
141
+ signals: TSignals;
142
+ /** Emit a custom event from the component */
143
+ emit: (event: string, detail?: unknown) => void;
144
+ };
145
+
146
+ /**
147
+ * Describes an observed attribute change that triggered a component update.
148
+ */
149
+ export type AttributeChange = {
150
+ /** The observed attribute name */
151
+ name: string;
152
+ /** The previous serialized attribute value */
153
+ oldValue: string | null;
154
+ /** The next serialized attribute value */
155
+ newValue: string | null;
156
+ };
157
+
158
+ /**
159
+ * Complete component definition including props, state, styles, and lifecycle.
160
+ *
161
+ * @template TProps - Type of the component's props
162
+ * @template TState - Type of the component's internal state
163
+ */
164
+ /*
165
+ * Lifecycle hooks use dynamic `this` when declared with method/function syntax.
166
+ * Arrow functions capture outer scope, so component APIs like `this.getState()`
167
+ * are only available from method/function syntax.
168
+ */
169
+ type ComponentSanitizeOptions = Pick<SanitizeOptions, 'allowTags' | 'allowAttributes'>;
170
+ type ComponentHook<
171
+ TState extends Record<string, unknown> | undefined = undefined,
172
+ TResult = void,
173
+ > = {
174
+ (this: ComponentElement<TState>): TResult;
175
+ (): TResult;
176
+ };
177
+ type ComponentHookWithProps<
178
+ TProps extends Record<string, unknown>,
179
+ TState extends Record<string, unknown> | undefined = undefined,
180
+ TResult = void,
181
+ > = {
182
+ (this: ComponentElement<TState>, newProps: TProps, oldProps: TProps): TResult;
183
+ (newProps: TProps, oldProps: TProps): TResult;
184
+ };
185
+ type ComponentUpdatedHook<
186
+ TState extends Record<string, unknown> | undefined = undefined,
187
+ TResult = void,
188
+ > = {
189
+ (this: ComponentElement<TState>, change?: AttributeChange): TResult;
190
+ (change?: AttributeChange): TResult;
191
+ };
192
+ type ComponentErrorHook<TState extends Record<string, unknown> | undefined = undefined> = {
193
+ (this: ComponentElement<TState>, error: Error): void;
194
+ (error: Error): void;
195
+ };
196
+
197
+ type ComponentAttributeChangedHook<TState extends Record<string, unknown> | undefined = undefined> =
198
+ {
199
+ (
200
+ this: ComponentElement<TState>,
201
+ name: string,
202
+ oldValue: string | null,
203
+ newValue: string | null
204
+ ): void;
205
+ (name: string, oldValue: string | null, newValue: string | null): void;
206
+ };
207
+
208
+ type ComponentStateDefinition<TState extends Record<string, unknown> | undefined = undefined> =
209
+ TState extends Record<string, unknown>
210
+ ? {
211
+ /** Initial internal state */
212
+ state: TState;
213
+ }
214
+ : {
215
+ /** Initial internal state */
216
+ state?: Record<string, unknown>;
217
+ };
218
+
219
+ type ComponentSignalsDefinition<TSignals extends ComponentSignals = Record<string, never>> =
220
+ TSignals extends Record<string, never>
221
+ ? {
222
+ /** External signals/computed values that should trigger re-renders */
223
+ signals?: TSignals;
224
+ }
225
+ : {
226
+ /** External signals/computed values that should trigger re-renders */
227
+ signals: TSignals;
228
+ };
229
+
230
+ /**
231
+ * Controls Shadow DOM mode for the component.
232
+ *
233
+ * - `true` or `'open'` — attach an open shadow root (default)
234
+ * - `'closed'` — attach a closed shadow root
235
+ * - `false` — no shadow root; render directly into the host element
236
+ */
237
+ export type ShadowMode = boolean | 'open' | 'closed';
238
+
239
+ export type ComponentDefinition<
240
+ TProps extends Record<string, unknown> = Record<string, unknown>,
241
+ TState extends Record<string, unknown> | undefined = undefined,
242
+ TSignals extends ComponentSignals = Record<string, never>,
243
+ > = ComponentStateDefinition<TState> &
244
+ ComponentSignalsDefinition<TSignals> & {
245
+ /** Prop definitions with types and defaults */
246
+ props?: Record<keyof TProps, PropDefinition>;
247
+ /**
248
+ * CSS styles injected for the component.
249
+ *
250
+ * When `shadow` uses a shadow root (`true`, `'open'`, or `'closed'`), these
251
+ * styles are scoped to that shadow tree. When `shadow` is `false`, the
252
+ * generated `<style>` element is rendered into the host's light DOM and may
253
+ * therefore affect surrounding markup according to normal CSS cascade rules.
254
+ */
255
+ styles?: string;
256
+ /**
257
+ * Controls Shadow DOM mode.
258
+ *
259
+ * - `true` or `'open'` — open shadow root (default)
260
+ * - `'closed'` — closed shadow root
261
+ * - `false` — no shadow root; render into the host element
262
+ *
263
+ * @default true
264
+ */
265
+ shadow?: ShadowMode;
266
+ /**
267
+ * Extra sanitizer options merged with the framework base allowlist during render.
268
+ * Only opt in attributes/tags whose values you control or validate. Sensitive
269
+ * attributes such as `style` are not value-sanitized and can reintroduce XSS
270
+ * or UI-redressing risks if used with untrusted input.
271
+ */
272
+ sanitize?: ComponentSanitizeOptions;
273
+ /**
274
+ * Additional attributes to observe beyond those declared in `props`.
275
+ *
276
+ * Useful when you want `onAttributeChanged` to fire for attributes
277
+ * that are not part of the typed props system.
278
+ */
279
+ observeAttributes?: string[];
280
+ /** Lifecycle hook called before the component mounts (before first render) */
281
+ beforeMount?: ComponentHook<TState>;
282
+ /** Lifecycle hook called when component is added to DOM */
283
+ connected?: ComponentHook<TState>;
284
+ /** Lifecycle hook called when component is removed from DOM */
285
+ disconnected?: ComponentHook<TState>;
286
+ /**
287
+ * Lifecycle hook called when the component is moved to a new document
288
+ * (e.g. via `document.adoptNode`).
289
+ */
290
+ onAdopted?: ComponentHook<TState>;
291
+ /**
292
+ * Lifecycle hook called when any observed attribute changes.
293
+ *
294
+ * Observed attributes are automatically derived from `props` keys
295
+ * plus any additional names in `observeAttributes`.
296
+ *
297
+ * @param name - The attribute name that changed
298
+ * @param oldValue - The previous attribute value (null if added)
299
+ * @param newValue - The new attribute value (null if removed)
300
+ */
301
+ onAttributeChanged?: ComponentAttributeChangedHook<TState>;
302
+ /** Lifecycle hook called before an update render; return false to prevent */
303
+ beforeUpdate?: ComponentHookWithProps<TProps, TState, boolean | void>;
304
+ /** Lifecycle hook called after update renders; receives attribute change info when applicable */
305
+ updated?: ComponentUpdatedHook<TState>;
306
+ /** Error handler for errors during rendering or lifecycle */
307
+ onError?: ComponentErrorHook<TState>;
308
+ /** Render function returning HTML string */
309
+ render: (context: ComponentRenderContext<TProps, TState, TSignals>) => string;
310
+ };