@bquery/bquery 1.4.0 → 1.5.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 (127) hide show
  1. package/README.md +139 -120
  2. package/dist/component/component.d.ts.map +1 -1
  3. package/dist/component/index.d.ts +2 -0
  4. package/dist/component/index.d.ts.map +1 -1
  5. package/dist/component/library.d.ts +34 -0
  6. package/dist/component/library.d.ts.map +1 -0
  7. package/dist/component/types.d.ts +10 -6
  8. package/dist/component/types.d.ts.map +1 -1
  9. package/dist/component-CY5MVoYN.js +531 -0
  10. package/dist/component-CY5MVoYN.js.map +1 -0
  11. package/dist/component.es.mjs +6 -184
  12. package/dist/config-DRmZZno3.js +40 -0
  13. package/dist/config-DRmZZno3.js.map +1 -0
  14. package/dist/core-CK2Mfpf4.js +648 -0
  15. package/dist/core-CK2Mfpf4.js.map +1 -0
  16. package/dist/core-DPdbItcq.js +112 -0
  17. package/dist/core-DPdbItcq.js.map +1 -0
  18. package/dist/core.es.mjs +45 -1261
  19. package/dist/full.d.ts +6 -6
  20. package/dist/full.d.ts.map +1 -1
  21. package/dist/full.es.mjs +98 -92
  22. package/dist/full.iife.js +173 -3
  23. package/dist/full.iife.js.map +1 -1
  24. package/dist/full.umd.js +173 -3
  25. package/dist/full.umd.js.map +1 -1
  26. package/dist/index.es.mjs +143 -139
  27. package/dist/motion/transition.d.ts +1 -1
  28. package/dist/motion/transition.d.ts.map +1 -1
  29. package/dist/motion/types.d.ts +11 -1
  30. package/dist/motion/types.d.ts.map +1 -1
  31. package/dist/motion-C5DRdPnO.js +415 -0
  32. package/dist/motion-C5DRdPnO.js.map +1 -0
  33. package/dist/motion.es.mjs +25 -361
  34. package/dist/object-qGpWr6-J.js +38 -0
  35. package/dist/object-qGpWr6-J.js.map +1 -0
  36. package/dist/platform/announcer.d.ts +59 -0
  37. package/dist/platform/announcer.d.ts.map +1 -0
  38. package/dist/platform/config.d.ts +92 -0
  39. package/dist/platform/config.d.ts.map +1 -0
  40. package/dist/platform/cookies.d.ts +45 -0
  41. package/dist/platform/cookies.d.ts.map +1 -0
  42. package/dist/platform/index.d.ts +8 -0
  43. package/dist/platform/index.d.ts.map +1 -1
  44. package/dist/platform/meta.d.ts +62 -0
  45. package/dist/platform/meta.d.ts.map +1 -0
  46. package/dist/platform-B7JhGBc7.js +361 -0
  47. package/dist/platform-B7JhGBc7.js.map +1 -0
  48. package/dist/platform.es.mjs +11 -248
  49. package/dist/reactive/async-data.d.ts +114 -0
  50. package/dist/reactive/async-data.d.ts.map +1 -0
  51. package/dist/reactive/index.d.ts +2 -2
  52. package/dist/reactive/index.d.ts.map +1 -1
  53. package/dist/reactive/signal.d.ts +2 -0
  54. package/dist/reactive/signal.d.ts.map +1 -1
  55. package/dist/reactive-BDya-ia8.js +253 -0
  56. package/dist/reactive-BDya-ia8.js.map +1 -0
  57. package/dist/reactive.es.mjs +18 -34
  58. package/dist/router-CijiICxt.js +188 -0
  59. package/dist/router-CijiICxt.js.map +1 -0
  60. package/dist/router.es.mjs +11 -200
  61. package/dist/sanitize-jyJ2ryE2.js +302 -0
  62. package/dist/sanitize-jyJ2ryE2.js.map +1 -0
  63. package/dist/security/constants.d.ts.map +1 -1
  64. package/dist/security.es.mjs +10 -56
  65. package/dist/store-CPK9E62U.js +262 -0
  66. package/dist/store-CPK9E62U.js.map +1 -0
  67. package/dist/store.es.mjs +12 -25
  68. package/dist/view-Cdi0g-qo.js +396 -0
  69. package/dist/view-Cdi0g-qo.js.map +1 -0
  70. package/dist/view.es.mjs +10 -430
  71. package/package.json +15 -11
  72. package/src/component/component.ts +319 -289
  73. package/src/component/index.ts +42 -40
  74. package/src/component/library.ts +504 -0
  75. package/src/component/types.ts +91 -85
  76. package/src/core/collection.ts +628 -628
  77. package/src/core/element.ts +774 -774
  78. package/src/core/index.ts +48 -48
  79. package/src/core/utils/function.ts +151 -151
  80. package/src/full.ts +223 -187
  81. package/src/motion/animate.ts +113 -113
  82. package/src/motion/flip.ts +176 -176
  83. package/src/motion/scroll.ts +57 -57
  84. package/src/motion/spring.ts +150 -150
  85. package/src/motion/timeline.ts +246 -246
  86. package/src/motion/transition.ts +53 -7
  87. package/src/motion/types.ts +208 -198
  88. package/src/platform/announcer.ts +208 -0
  89. package/src/platform/config.ts +163 -0
  90. package/src/platform/cookies.ts +165 -0
  91. package/src/platform/index.ts +39 -18
  92. package/src/platform/meta.ts +168 -0
  93. package/src/platform/storage.ts +215 -215
  94. package/src/reactive/async-data.ts +486 -0
  95. package/src/reactive/core.ts +114 -114
  96. package/src/reactive/effect.ts +54 -54
  97. package/src/reactive/index.ts +37 -23
  98. package/src/reactive/internals.ts +122 -122
  99. package/src/reactive/signal.ts +29 -20
  100. package/src/security/constants.ts +211 -209
  101. package/src/security/sanitize-core.ts +364 -364
  102. package/src/view/evaluate.ts +290 -290
  103. package/dist/batch-x7b2eZST.js +0 -13
  104. package/dist/batch-x7b2eZST.js.map +0 -1
  105. package/dist/component.es.mjs.map +0 -1
  106. package/dist/core-BhpuvPhy.js +0 -170
  107. package/dist/core-BhpuvPhy.js.map +0 -1
  108. package/dist/core.es.mjs.map +0 -1
  109. package/dist/full.es.mjs.map +0 -1
  110. package/dist/index.es.mjs.map +0 -1
  111. package/dist/motion.es.mjs.map +0 -1
  112. package/dist/persisted-DHoi3uEs.js +0 -278
  113. package/dist/persisted-DHoi3uEs.js.map +0 -1
  114. package/dist/platform.es.mjs.map +0 -1
  115. package/dist/reactive.es.mjs.map +0 -1
  116. package/dist/router.es.mjs.map +0 -1
  117. package/dist/sanitize-Cxvxa-DX.js +0 -283
  118. package/dist/sanitize-Cxvxa-DX.js.map +0 -1
  119. package/dist/security.es.mjs.map +0 -1
  120. package/dist/store.es.mjs.map +0 -1
  121. package/dist/type-guards-BdKlYYlS.js +0 -32
  122. package/dist/type-guards-BdKlYYlS.js.map +0 -1
  123. package/dist/untrack-DNnnqdlR.js +0 -6
  124. package/dist/untrack-DNnnqdlR.js.map +0 -1
  125. package/dist/view.es.mjs.map +0 -1
  126. package/dist/watch-DXXv3iAI.js +0 -58
  127. package/dist/watch-DXXv3iAI.js.map +0 -1
package/README.md CHANGED
@@ -16,17 +16,21 @@
16
16
  [![CodeFactor](https://www.codefactor.io/repository/github/bquery/bquery/badge)](https://www.codefactor.io/repository/github/bquery/bquery)
17
17
  [![JsDelivr](https://data.jsdelivr.com/v1/package/npm/@bquery/bquery/badge)](https://www.jsdelivr.com/package/npm/@bquery/bquery)
18
18
 
19
+ </p>
20
+
19
21
  **The jQuery for the modern Web Platform.**
20
22
 
21
- bQuery.js is a slim, TypeScript-first library that combines jQuery's direct DOM workflow with modern features like reactivity, Web Components, and motion utilities — without a mandatory build step.
23
+ bQuery.js is a slim, TypeScript-first library that combines jQuery's direct DOM workflow with modern features like reactivity, async data composables, Web Components, motion utilities, routing, stores, and declarative views — without a mandatory build step.
22
24
 
23
25
  ## Highlights
24
26
 
25
- - **Zerobuild capable**: runs directly in the browser; build tools are optional.
26
- - **Security‑focused**: DOM writes are sanitized by default; Trusted Types supported.
27
- - **Modular**: the core stays small; extra modules are opt‑in.
28
- - **TypeScript‑first**: clear types and strong IDE support.
27
+ - **Zero-build capable**: runs directly in the browser; build tools are optional.
28
+ - **Async data built-in**: fetch and async state composables integrate directly with signals.
29
+ - **Security-focused**: DOM writes are sanitized by default; Trusted Types supported.
30
+ - **Modular**: the core stays small; extra modules are opt-in.
31
+ - **TypeScript-first**: clear types and strong IDE support.
29
32
  - **Tree-shakeable**: import only what you need.
33
+ - **Storybook-ready**: default components can be previewed and developed in Storybook.
30
34
 
31
35
  ## Installation
32
36
 
@@ -76,11 +80,17 @@ pnpm add @bquery/bquery
76
80
  </script>
77
81
  ```
78
82
 
79
- ### Import Strategies
83
+ ## Import Strategies
80
84
 
81
85
  ```ts
82
86
  // Full bundle (all modules)
83
- import { $, signal, component } from '@bquery/bquery';
87
+ import {
88
+ $,
89
+ signal,
90
+ component,
91
+ registerDefaultComponents,
92
+ defineBqueryConfig,
93
+ } from '@bquery/bquery';
84
94
 
85
95
  // Core only
86
96
  import { $, $$ } from '@bquery/bquery/core';
@@ -88,12 +98,36 @@ import { $, $$ } from '@bquery/bquery/core';
88
98
  // Core utilities (named exports, tree-shakeable)
89
99
  import { debounce, merge, uid, once, utils } from '@bquery/bquery/core';
90
100
 
91
- // À la carte (individual modules)
92
- import { signal, computed, effect, linkedSignal, persistedSignal } from '@bquery/bquery/reactive';
93
- import { component, defineComponent, html } from '@bquery/bquery/component';
101
+ // Reactive only
102
+ import {
103
+ signal,
104
+ computed,
105
+ effect,
106
+ linkedSignal,
107
+ persistedSignal,
108
+ useAsyncData,
109
+ useFetch,
110
+ createUseFetch,
111
+ } from '@bquery/bquery/reactive';
112
+
113
+ // Components only
114
+ import {
115
+ component,
116
+ defineComponent,
117
+ html,
118
+ registerDefaultComponents,
119
+ } from '@bquery/bquery/component';
120
+
121
+ // Motion only
94
122
  import { transition, spring, animate, timeline } from '@bquery/bquery/motion';
123
+
124
+ // Security only
95
125
  import { sanitize } from '@bquery/bquery/security';
96
- import { storage, cache } from '@bquery/bquery/platform';
126
+
127
+ // Platform only
128
+ import { storage, cache, useCookie, definePageMeta, useAnnouncer } from '@bquery/bquery/platform';
129
+
130
+ // Router, Store, View
97
131
  import { createRouter, navigate } from '@bquery/bquery/router';
98
132
  import { createStore, defineStore } from '@bquery/bquery/store';
99
133
  import { mount, createTemplate } from '@bquery/bquery/view';
@@ -104,11 +138,11 @@ import { mount, createTemplate } from '@bquery/bquery/view';
104
138
  | Module | Description | Size (gzip) |
105
139
  | ------------- | -------------------------------------------------- | ----------- |
106
140
  | **Core** | Selectors, DOM manipulation, events, utilities | ~11.3 KB |
107
- | **Reactive** | `signal`, `computed`, `effect`, `batch` | ~0.3 KB |
108
- | **Component** | Lightweight Web Components with props | ~1.9 KB |
141
+ | **Reactive** | `signal`, `computed`, `effect`, async data/fetch | ~0.3 KB |
142
+ | **Component** | Lightweight Web Components with props + defaults | ~1.9 KB |
109
143
  | **Motion** | View transitions, FLIP, timelines, scroll, springs | ~4.0 KB |
110
144
  | **Security** | HTML sanitizing, Trusted Types, CSP | ~0.7 KB |
111
- | **Platform** | Storage, cache, notifications, buckets | ~2.2 KB |
145
+ | **Platform** | Storage, cache, cookies, meta, announcers, config | ~2.2 KB |
112
146
  | **Router** | SPA routing, navigation guards, history API | ~2.2 KB |
113
147
  | **Store** | Signal-based state management, persistence | ~0.3 KB |
114
148
  | **View** | Declarative DOM bindings, directives | ~4.3 KB |
@@ -120,45 +154,23 @@ import { mount, createTemplate } from '@bquery/bquery/view';
120
154
  ```ts
121
155
  import { $, $$ } from '@bquery/bquery/core';
122
156
 
123
- // jQuery-style selectors
124
157
  $('#save').on('click', (event) => {
125
158
  console.log('Saved', event.type);
126
159
  });
127
160
 
128
- // Event delegation for dynamic content
129
161
  $('#list').delegate('click', '.item', (event, target) => {
130
162
  console.log('Item clicked', target.textContent);
131
163
  });
132
164
 
133
- // Method chaining
134
165
  $('#box').addClass('active').css({ opacity: '0.8' }).attr('data-state', 'ready');
135
166
 
136
- // CSS getter (computed style)
137
- const color = $('#box').css('color'); // Returns computed style value
167
+ const color = $('#box').css('color');
138
168
 
139
- // Selector matching
140
169
  if ($('#el').is('.active')) {
141
170
  console.log('Element is active');
142
171
  }
143
172
 
144
- // DOM manipulation
145
- $('#content').wrap('div');
146
- $('#content').unwrap(); // Remove parent wrapper
147
-
148
- // Attribute helpers
149
- $('#dialog').toggleAttr('open');
150
-
151
- // Smooth scrolling
152
- $('#section').scrollTo({ behavior: 'smooth' });
153
-
154
- // Form serialization
155
- const formData = $('form').serialize(); // Returns object
156
- const queryString = $('form').serializeString(); // Returns URL-encoded string
157
-
158
- // Collections
159
- $$('.items').addClass('highlight');
160
- $$('.items').append('<li class="item">New</li>');
161
- $$('.container').find('.item').addClass('found'); // Find descendants across collection
173
+ $$('.container').find('.item').addClass('found');
162
174
  ```
163
175
 
164
176
  ### Reactive – signals
@@ -181,24 +193,19 @@ effect(() => {
181
193
  console.log('Count changed', count.value);
182
194
  });
183
195
 
184
- // Watch with cleanup support
185
- const stop = watch(count, (newVal, oldVal) => {
196
+ watch(count, (newVal, oldVal) => {
186
197
  console.log(`Changed from ${oldVal} to ${newVal}`);
187
198
  });
188
199
 
189
- // Read-only signal wrapper
190
200
  const readOnlyCount = readonly(count);
191
201
 
192
- // Batch updates for performance
193
202
  batch(() => {
194
203
  count.value++;
195
204
  count.value++;
196
205
  });
197
206
 
198
- // Dispose signal (remove all subscribers)
199
207
  count.dispose();
200
208
 
201
- // Writable computed (linked signal)
202
209
  const first = signal('Ada');
203
210
  const last = signal('Lovelace');
204
211
  const fullName = linkedSignal(
@@ -213,17 +220,44 @@ const fullName = linkedSignal(
213
220
  fullName.value = 'Grace Hopper';
214
221
  ```
215
222
 
223
+ ### Reactive – async data & fetch
224
+
225
+ ```ts
226
+ import { signal, useFetch, createUseFetch } from '@bquery/bquery/reactive';
227
+
228
+ const userId = signal(1);
229
+
230
+ const user = useFetch<{ id: number; name: string }>(() => `/users/${userId.value}`, {
231
+ baseUrl: 'https://api.example.com',
232
+ watch: [userId],
233
+ query: { include: 'profile' },
234
+ });
235
+
236
+ const useApiFetch = createUseFetch({
237
+ baseUrl: 'https://api.example.com',
238
+ headers: { 'x-client': 'bquery-readme' },
239
+ });
240
+
241
+ const settings = useApiFetch<{ theme: string }>('/settings');
242
+
243
+ console.log(user.pending.value, user.data.value, settings.error.value);
244
+ ```
245
+
216
246
  ### Components – Web Components
217
247
 
218
248
  ```ts
219
- import { component, defineComponent, html } from '@bquery/bquery/component';
249
+ import {
250
+ component,
251
+ defineComponent,
252
+ html,
253
+ registerDefaultComponents,
254
+ } from '@bquery/bquery/component';
220
255
 
221
256
  component('user-card', {
222
257
  props: {
223
258
  username: { type: String, required: true },
224
259
  age: { type: Number, validator: (v) => v >= 0 && v <= 150 },
225
260
  },
226
- // Extended lifecycle hooks
227
261
  beforeMount() {
228
262
  console.log('About to mount');
229
263
  },
@@ -231,7 +265,6 @@ component('user-card', {
231
265
  console.log('Mounted');
232
266
  },
233
267
  beforeUpdate(props) {
234
- // Return false to prevent update
235
268
  return props.username !== '';
236
269
  },
237
270
  onError(error) {
@@ -242,12 +275,15 @@ component('user-card', {
242
275
  },
243
276
  });
244
277
 
245
- // Optional: create the class without auto-registration
246
278
  const UserCard = defineComponent('user-card', {
247
279
  props: { username: { type: String, required: true } },
248
280
  render: ({ props }) => html`<div>Hello ${props.username}</div>`,
249
281
  });
282
+
250
283
  customElements.define('user-card', UserCard);
284
+
285
+ const tags = registerDefaultComponents({ prefix: 'ui' });
286
+ console.log(tags.button); // ui-button
251
287
  ```
252
288
 
253
289
  ### Motion – animations
@@ -255,18 +291,20 @@ customElements.define('user-card', UserCard);
255
291
  ```ts
256
292
  import { animate, keyframePresets, spring, transition } from '@bquery/bquery/motion';
257
293
 
258
- // View transitions (with fallback)
259
- await transition(() => {
260
- $('#content').text('Updated');
294
+ await transition({
295
+ update: () => {
296
+ $('#content').text('Updated');
297
+ },
298
+ classes: ['page-transition'],
299
+ types: ['navigation'],
300
+ skipOnReducedMotion: true,
261
301
  });
262
302
 
263
- // Web Animations helper
264
303
  await animate(card, {
265
304
  keyframes: keyframePresets.pop(),
266
305
  options: { duration: 240, easing: 'ease-out' },
267
306
  });
268
307
 
269
- // Spring physics
270
308
  const x = spring(0, { stiffness: 120, damping: 14 });
271
309
  x.onChange((value) => {
272
310
  element.style.transform = `translateX(${value}px)`;
@@ -276,44 +314,47 @@ await x.to(100);
276
314
 
277
315
  ### Security – sanitizing
278
316
 
279
- Internally modularized (sanitize core, Trusted Types, CSP helpers) — the public API remains unchanged. For legacy deep imports, `@bquery/bquery/security/sanitize` also re-exports `generateNonce()` and `isTrustedTypesSupported()`.
280
-
281
317
  ```ts
282
318
  import { sanitize, escapeHtml } from '@bquery/bquery/security';
283
319
 
284
- // Sanitize HTML (removes dangerous elements like script, iframe, svg)
285
320
  const safeHtml = sanitize(userInput);
286
-
287
- // DOM clobbering protection (reserved IDs are blocked)
288
- const safe = sanitize('<form id="cookie">...</form>'); // id stripped
289
-
290
- // Unicode bypass protection in URLs
321
+ const safe = sanitize('<form id="cookie">...</form>');
291
322
  const urlSafe = sanitize('<a href="java\u200Bscript:alert(1)">click</a>');
292
-
293
- // Automatic link security (adds rel="noopener noreferrer" to external/target="_blank" links)
294
323
  const secureLink = sanitize('<a href="https://external.com" target="_blank">Link</a>');
295
-
296
- // srcset validation (per-URL; entire attribute removed if any entry is unsafe)
297
- const safeSrcset = sanitize('<img srcset="safe.jpg 1x, javascript:alert(1) 2x">'); // <img>
298
-
299
- // Form action validation (blocks javascript: protocol)
324
+ const safeSrcset = sanitize('<img srcset="safe.jpg 1x, javascript:alert(1) 2x">');
300
325
  const safeForm = sanitize('<form action="javascript:alert(1)">...</form>');
301
-
302
- // Escape for text display
303
326
  const escaped = escapeHtml('<script>alert(1)</script>');
304
327
  ```
305
328
 
306
- ### Platform – storage & APIs
329
+ ### Platform – config, cookies & accessibility
307
330
 
308
331
  ```ts
309
- import { storage, notifications } from '@bquery/bquery/platform';
332
+ import {
333
+ defineBqueryConfig,
334
+ useCookie,
335
+ definePageMeta,
336
+ useAnnouncer,
337
+ storage,
338
+ notifications,
339
+ } from '@bquery/bquery/platform';
340
+
341
+ defineBqueryConfig({
342
+ fetch: { baseUrl: 'https://api.example.com' },
343
+ transitions: { skipOnReducedMotion: true, classes: ['page-transition'] },
344
+ components: { prefix: 'ui' },
345
+ });
346
+
347
+ const theme = useCookie<'light' | 'dark'>('theme', { defaultValue: 'light' });
348
+ const cleanupMeta = definePageMeta({ title: 'Dashboard' });
349
+ const announcer = useAnnouncer();
350
+
351
+ theme.value = 'dark';
352
+ announcer.announce('Preferences saved');
353
+ cleanupMeta();
310
354
 
311
- // Unified storage API
312
355
  const local = storage.local();
313
- await local.set('theme', 'dark');
314
- const theme = await local.get<string>('theme');
356
+ await local.set('theme', theme.value);
315
357
 
316
- // Notifications
317
358
  const permission = await notifications.requestPermission();
318
359
  if (permission === 'granted') {
319
360
  notifications.send('Build complete', {
@@ -324,12 +365,10 @@ if (permission === 'granted') {
324
365
 
325
366
  ### Router – SPA navigation
326
367
 
327
- Internally, the router has been split into focused submodules (matching, navigation, state, links, utilities) with no public API changes.
328
-
329
368
  ```ts
369
+ import { effect } from '@bquery/bquery/reactive';
330
370
  import { createRouter, navigate, currentRoute } from '@bquery/bquery/router';
331
371
 
332
- // Create router with routes
333
372
  const router = createRouter({
334
373
  routes: [
335
374
  { path: '/', name: 'home', component: HomePage },
@@ -338,20 +377,13 @@ const router = createRouter({
338
377
  ],
339
378
  });
340
379
 
341
- // Navigation guards
342
- router.beforeEach(async (to, from) => {
380
+ router.beforeEach(async (to) => {
343
381
  if (to.path === '/admin' && !isAuthenticated()) {
344
- await navigate('/login'); // Redirect
345
- return false; // Cancel original navigation
382
+ await navigate('/login');
383
+ return false;
346
384
  }
347
385
  });
348
386
 
349
- // Navigate programmatically
350
- await navigate('/user/42');
351
- await navigate('/search?q=bquery'); // Query params in path
352
- await navigate('/login', { replace: true }); // Replace history entry
353
-
354
- // Reactive current route
355
387
  effect(() => {
356
388
  console.log('Current path:', currentRoute.value.path);
357
389
  });
@@ -360,9 +392,14 @@ effect(() => {
360
392
  ### Store – state management
361
393
 
362
394
  ```ts
363
- import { createStore, createPersistedStore } from '@bquery/bquery/store';
395
+ import {
396
+ createStore,
397
+ createPersistedStore,
398
+ defineStore,
399
+ mapGetters,
400
+ watchStore,
401
+ } from '@bquery/bquery/store';
364
402
 
365
- // Create a store (returns the store instance directly)
366
403
  const counterStore = createStore({
367
404
  id: 'counter',
368
405
  state: () => ({ count: 0, name: 'Counter' }),
@@ -373,25 +410,14 @@ const counterStore = createStore({
373
410
  increment() {
374
411
  this.count++;
375
412
  },
376
- async fetchCount() {
377
- this.count = await api.getCount();
378
- },
379
413
  },
380
414
  });
381
415
 
382
- // Use the store
383
- counterStore.increment();
384
- console.log(counterStore.doubled); // Reactive getter
385
-
386
- // Persisted store (localStorage)
387
416
  const settingsStore = createPersistedStore({
388
417
  id: 'settings',
389
418
  state: () => ({ theme: 'dark', language: 'en' }),
390
419
  });
391
420
 
392
- // Factory-style store definition (Pinia-style)
393
- import { defineStore, mapGetters, watchStore } from '@bquery/bquery/store';
394
-
395
421
  const useCounter = defineStore('counter', {
396
422
  state: () => ({ count: 0 }),
397
423
  getters: {
@@ -418,29 +444,18 @@ watchStore(
418
444
 
419
445
  ### View – declarative bindings
420
446
 
421
- Internally modularized into focused submodules; the public API remains unchanged.
422
-
423
447
  ```ts
424
448
  import { mount, createTemplate } from '@bquery/bquery/view';
425
449
  import { signal } from '@bquery/bquery/reactive';
426
450
 
427
- // Mount reactive bindings to DOM
428
451
  const count = signal(0);
429
452
  const items = signal(['Apple', 'Banana', 'Cherry']);
430
453
 
431
- const app = mount('#app', {
454
+ mount('#app', {
432
455
  count,
433
456
  items,
434
457
  increment: () => count.value++,
435
458
  });
436
-
437
- // In HTML:
438
- // <p bq-text="count"></p>
439
- // <button bq-on:click="increment">+1</button>
440
- // <ul><li bq-for="item in items" bq-text="item"></li></ul>
441
- // <input bq-model="count" type="number" />
442
- // <div bq-if="count > 5">Count is high!</div>
443
- // <div bq-class="{ active: count > 0 }"></div>
444
459
  ```
445
460
 
446
461
  ## Browser Support
@@ -477,8 +492,8 @@ bun install
477
492
  # Start VitePress docs
478
493
  bun run dev
479
494
 
480
- # Run Vite playground
481
- bun run playground
495
+ # Run Storybook
496
+ bun run storybook
482
497
 
483
498
  # Run tests
484
499
  bun test
@@ -486,6 +501,9 @@ bun test
486
501
  # Build library
487
502
  bun run build
488
503
 
504
+ # Build docs
505
+ bun run build:docs
506
+
489
507
  # Generate API documentation
490
508
  bun run docs:api
491
509
  ```
@@ -496,16 +514,17 @@ bun run docs:api
496
514
  bQuery.js
497
515
  ├── src/
498
516
  │ ├── core/ # Selectors, DOM ops, events, utils
499
- │ ├── reactive/ # Signals, computed, effects
500
- │ ├── component/ # Web Components helper
517
+ │ ├── reactive/ # Signals, computed, effects, async data
518
+ │ ├── component/ # Web Components helper + default library
501
519
  │ ├── motion/ # View transitions, FLIP, springs
502
520
  │ ├── security/ # Sanitizer, CSP, Trusted Types
503
- │ ├── platform/ # Storage, cache, notifications
521
+ │ ├── platform/ # Storage, cache, cookies, meta, config
504
522
  │ ├── router/ # SPA routing, navigation guards
505
523
  │ ├── store/ # State management, persistence
506
524
  │ └── view/ # Declarative DOM bindings
507
525
  ├── docs/ # VitePress documentation
508
- ├── playground/ # Vite demo app
526
+ ├── .storybook/ # Storybook config
527
+ ├── stories/ # Component stories
509
528
  ├── tests/ # bun:test suites
510
529
  └── dist/ # Built files (ESM, UMD, IIFE)
511
530
  ```
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/component/component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAkB,MAAM,SAAS,CAAC;AAEnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,SAAS,MAAM,EACf,YAAY,mBAAmB,CAAC,MAAM,CAAC,KACtC,OAAO,WA4MT,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,SAAS,MAAM,EACf,YAAY,mBAAmB,CAAC,MAAM,CAAC,KACtC,IAMF,CAAC"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/component/component.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAkB,MAAM,SAAS,CAAC;AAEnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,SAAS,MAAM,EACf,YAAY,mBAAmB,CAAC,MAAM,CAAC,KACtC,OAAO,WA0OT,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,SAAS,MAAM,EACf,YAAY,mBAAmB,CAAC,MAAM,CAAC,KACtC,IAMF,CAAC"}
@@ -36,5 +36,7 @@
36
36
  */
37
37
  export { component, defineComponent } from './component';
38
38
  export { html, safeHtml } from './html';
39
+ export { registerDefaultComponents } from './library';
40
+ export type { DefaultComponentLibraryOptions, RegisteredDefaultComponents } from './library';
39
41
  export type { ComponentDefinition, ComponentRenderContext, PropDefinition } from './types';
40
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/component/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACxC,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/component/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,8BAA8B,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAC7F,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Default component library based on native Web Components.
3
+ *
4
+ * @module bquery/component
5
+ */
6
+ /** Options for registering the default component library. */
7
+ export interface DefaultComponentLibraryOptions {
8
+ /** Prefix used for all registered component tags. Defaults to `bq`. */
9
+ prefix?: string;
10
+ }
11
+ /** Tag names returned by registerDefaultComponents(). */
12
+ export interface RegisteredDefaultComponents {
13
+ /** Button component tag name. */
14
+ button: string;
15
+ /** Card component tag name. */
16
+ card: string;
17
+ /** Input component tag name. */
18
+ input: string;
19
+ /** Textarea component tag name. */
20
+ textarea: string;
21
+ /** Checkbox component tag name. */
22
+ checkbox: string;
23
+ }
24
+ /**
25
+ * Register a default set of foundational UI components.
26
+ *
27
+ * The library is intentionally small and dependency-free, providing common
28
+ * primitives that can be themed via shadow parts and CSS custom properties.
29
+ *
30
+ * @param options - Optional registration settings such as a custom tag prefix
31
+ * @returns The registered tag names for each component
32
+ */
33
+ export declare const registerDefaultComponents: (options?: DefaultComponentLibraryOptions) => RegisteredDefaultComponents;
34
+ //# sourceMappingURL=library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/component/library.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,6DAA6D;AAC7D,MAAM,WAAW,8BAA8B;IAC7C,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yDAAyD;AACzD,MAAM,WAAW,2BAA2B;IAC1C,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAwJD;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,GACpC,UAAS,8BAAmC,KAC3C,2BAuTF,CAAC"}
@@ -52,6 +52,9 @@ export type ComponentRenderContext<TProps extends Record<string, unknown>> = {
52
52
  *
53
53
  * @template TProps - Type of the component's props
54
54
  */
55
+ type ComponentHook<TResult = void> = ((this: HTMLElement) => TResult) | (() => TResult);
56
+ type ComponentHookWithProps<TProps extends Record<string, unknown>, TResult = void> = ((this: HTMLElement, props: TProps) => TResult) | ((props: TProps) => TResult);
57
+ type ComponentErrorHook = ((this: HTMLElement, error: Error) => void) | ((error: Error) => void);
55
58
  export type ComponentDefinition<TProps extends Record<string, unknown> = Record<string, unknown>> = {
56
59
  /** Prop definitions with types and defaults */
57
60
  props?: Record<keyof TProps, PropDefinition>;
@@ -60,18 +63,19 @@ export type ComponentDefinition<TProps extends Record<string, unknown> = Record<
60
63
  /** CSS styles scoped to the component's shadow DOM */
61
64
  styles?: string;
62
65
  /** Lifecycle hook called before the component mounts (before first render) */
63
- beforeMount?: () => void;
66
+ beforeMount?: ComponentHook;
64
67
  /** Lifecycle hook called when component is added to DOM */
65
- connected?: () => void;
68
+ connected?: ComponentHook;
66
69
  /** Lifecycle hook called when component is removed from DOM */
67
- disconnected?: () => void;
70
+ disconnected?: ComponentHook;
68
71
  /** Lifecycle hook called before an update render; return false to prevent */
69
- beforeUpdate?: (props: TProps) => boolean | void;
72
+ beforeUpdate?: ComponentHookWithProps<TProps, boolean | void>;
70
73
  /** Lifecycle hook called after reactive updates trigger a render */
71
- updated?: () => void;
74
+ updated?: ComponentHook;
72
75
  /** Error handler for errors during rendering or lifecycle */
73
- onError?: (error: Error) => void;
76
+ onError?: ComponentErrorHook;
74
77
  /** Render function returning HTML string */
75
78
  render: (context: ComponentRenderContext<TProps>) => string;
76
79
  };
80
+ export {};
77
81
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI;IACxC,0DAA0D;IAC1D,IAAI,EACA,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,GAChB;QAAE,KAAK,KAAK,EAAE,OAAO,GAAG,CAAC,CAAA;KAAE,GAC3B,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,0DAA0D;IAC1D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAClC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC3E,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9F;IACE,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,MAAM,EAAE,cAAc,CAAC,CAAC;IAC7C,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACjD,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,4CAA4C;IAC5C,MAAM,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC;CAC7D,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/component/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI;IACxC,0DAA0D;IAC1D,IAAI,EACA,iBAAiB,GACjB,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,gBAAgB,GAChB;QAAE,KAAK,KAAK,EAAE,OAAO,GAAG,CAAC,CAAA;KAAE,GAC3B,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,0DAA0D;IAC1D,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IAClC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,sBAAsB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC3E,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF;;;;GAIG;AACH,KAAK,aAAa,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;AACxF,KAAK,sBAAsB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,IAC9E,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAC/C,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AACjC,KAAK,kBAAkB,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC;AAEjG,MAAM,MAAM,mBAAmB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC9F;IACE,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,MAAM,EAAE,cAAc,CAAC,CAAC;IAC7C,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,+DAA+D;IAC/D,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;IAC9D,oEAAoE;IACpE,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,4CAA4C;IAC5C,MAAM,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC;CAC7D,CAAC"}