bitwrench 2.0.22 → 2.0.23

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 (88) hide show
  1. package/LICENSE.txt +1 -1
  2. package/README.md +4 -3
  3. package/bin/bwmcp.js +3 -0
  4. package/dist/bitwrench-bccl.cjs.js +1 -1
  5. package/dist/bitwrench-bccl.cjs.min.js +1 -1
  6. package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
  7. package/dist/bitwrench-bccl.esm.js +1 -1
  8. package/dist/bitwrench-bccl.esm.min.js +1 -1
  9. package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
  10. package/dist/bitwrench-bccl.umd.js +1 -1
  11. package/dist/bitwrench-bccl.umd.min.js +1 -1
  12. package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
  13. package/dist/bitwrench-code-edit.cjs.js +1 -1
  14. package/dist/bitwrench-code-edit.cjs.min.js +1 -1
  15. package/dist/bitwrench-code-edit.es5.js +1 -1
  16. package/dist/bitwrench-code-edit.es5.min.js +1 -1
  17. package/dist/bitwrench-code-edit.esm.js +1 -1
  18. package/dist/bitwrench-code-edit.esm.min.js +1 -1
  19. package/dist/bitwrench-code-edit.umd.js +1 -1
  20. package/dist/bitwrench-code-edit.umd.min.js +1 -1
  21. package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
  22. package/dist/bitwrench-debug.js +1 -1
  23. package/dist/bitwrench-debug.min.js +1 -1
  24. package/dist/bitwrench-lean.cjs.js +3 -3
  25. package/dist/bitwrench-lean.cjs.min.js +2 -2
  26. package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
  27. package/dist/bitwrench-lean.es5.js +3 -3
  28. package/dist/bitwrench-lean.es5.min.js +2 -2
  29. package/dist/bitwrench-lean.es5.min.js.gz +0 -0
  30. package/dist/bitwrench-lean.esm.js +3 -3
  31. package/dist/bitwrench-lean.esm.min.js +2 -2
  32. package/dist/bitwrench-lean.esm.min.js.gz +0 -0
  33. package/dist/bitwrench-lean.umd.js +3 -3
  34. package/dist/bitwrench-lean.umd.min.js +2 -2
  35. package/dist/bitwrench-lean.umd.min.js.gz +0 -0
  36. package/dist/bitwrench-util-css.cjs.js +1 -1
  37. package/dist/bitwrench-util-css.cjs.min.js +1 -1
  38. package/dist/bitwrench-util-css.es5.js +1 -1
  39. package/dist/bitwrench-util-css.es5.min.js +1 -1
  40. package/dist/bitwrench-util-css.esm.js +1 -1
  41. package/dist/bitwrench-util-css.esm.min.js +1 -1
  42. package/dist/bitwrench-util-css.umd.js +1 -1
  43. package/dist/bitwrench-util-css.umd.min.js +1 -1
  44. package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
  45. package/dist/bitwrench.cjs.js +3 -3
  46. package/dist/bitwrench.cjs.min.js +2 -2
  47. package/dist/bitwrench.cjs.min.js.gz +0 -0
  48. package/dist/bitwrench.css +1 -1
  49. package/dist/bitwrench.es5.js +3 -3
  50. package/dist/bitwrench.es5.min.js +2 -2
  51. package/dist/bitwrench.es5.min.js.gz +0 -0
  52. package/dist/bitwrench.esm.js +3 -3
  53. package/dist/bitwrench.esm.min.js +2 -2
  54. package/dist/bitwrench.esm.min.js.gz +0 -0
  55. package/dist/bitwrench.umd.js +3 -3
  56. package/dist/bitwrench.umd.min.js +2 -2
  57. package/dist/bitwrench.umd.min.js.gz +0 -0
  58. package/dist/builds.json +57 -57
  59. package/dist/bwserve.cjs.js +2 -2
  60. package/dist/bwserve.esm.js +2 -2
  61. package/dist/sri.json +45 -45
  62. package/docs/README.md +76 -0
  63. package/docs/app-patterns.md +264 -0
  64. package/docs/bitwrench-mcp.md +426 -0
  65. package/docs/bitwrench_api.md +2232 -0
  66. package/docs/bw-attach.md +399 -0
  67. package/docs/bwserve.md +841 -0
  68. package/docs/cli.md +307 -0
  69. package/docs/component-cheatsheet.md +144 -0
  70. package/docs/component-library.md +1099 -0
  71. package/docs/framework-translation-table.md +33 -0
  72. package/docs/llm-bitwrench-guide.md +672 -0
  73. package/docs/routing.md +562 -0
  74. package/docs/state-management.md +767 -0
  75. package/docs/taco-format.md +373 -0
  76. package/docs/theming.md +309 -0
  77. package/docs/thinking-in-bitwrench.md +1457 -0
  78. package/docs/tutorial-bwserve.md +297 -0
  79. package/docs/tutorial-embedded.md +314 -0
  80. package/docs/tutorial-website.md +255 -0
  81. package/package.json +11 -3
  82. package/readme.html +5 -4
  83. package/src/mcp/knowledge.js +231 -0
  84. package/src/mcp/live.js +226 -0
  85. package/src/mcp/server.js +216 -0
  86. package/src/mcp/tools.js +369 -0
  87. package/src/mcp/transport.js +55 -0
  88. package/src/version.js +3 -3
@@ -0,0 +1,2232 @@
1
+ # Bitwrench API Reference
2
+
3
+ ## Summary
4
+
5
+ | Field | Value |
6
+ |-------|-------|
7
+ | Version | 2.0.23 |
8
+ | Generated | 2026-03-28 |
9
+ | Total APIs | 100 |
10
+ | Categories | 12 |
11
+ | bitwrench.js | 3612 lines |
12
+ | bitwrench-bccl.js | 3793 lines |
13
+
14
+ ## Table of Contents
15
+
16
+ - [Core](#core) (5)
17
+ - [DOM Generation](#dom-generation) (10)
18
+ - [Identifiers](#identifiers) (4)
19
+ - [State Management](#state-management) (3)
20
+ - [Events (DOM)](#events-dom-) (2)
21
+ - [Pub/Sub](#pub-sub) (3)
22
+ - [CSS & Styling](#css-styling) (10)
23
+ - [Component Builders](#component-builders) (50)
24
+ - [Browser Utilities](#browser-utilities) (4)
25
+ - [Utilities](#utilities) (1)
26
+ - [Function Registry](#function-registry) (5)
27
+ - [Component](#component) (3)
28
+
29
+ ---
30
+
31
+ ## Core
32
+
33
+ ### `bw.isNodeJS()`
34
+
35
+ Detect if running in Node.js environment. Useful for writing isomorphic code that behaves differently in Node.js vs browser. Uses `process.versions.node` for reliable detection that works in both CJS and ESM.
36
+
37
+ **Returns:** `boolean` — if Node.js, false if browser
38
+
39
+ **Example:**
40
+ ```javascript
41
+ if (bw.isNodeJS()) { console.log('Running in Node.js'); } else { console.log('Running in browser'); }
42
+ ```
43
+
44
+ ---
45
+
46
+ ### `bw.parseJSONFlex(str)`
47
+
48
+ Parse a bwserve protocol message string, supporting both strict JSON and r-prefixed relaxed JSON (single-quoted strings, trailing commas). The r-prefix format is designed for C/C++ string literals where double-quote escaping is painful. The parser is a state machine that walks character by character — not a regex replace. Escaping: apostrophes inside single-quoted values must be escaped with backslash: r{'name':'Barry\'s room'}
49
+
50
+ **Parameters:**
51
+
52
+ | Name | Type | Description |
53
+ |------|------|-------------|
54
+ | `str` | `string` | - JSON or r-prefixed relaxed JSON string |
55
+
56
+ **Returns:** `Object` — message object
57
+
58
+ ---
59
+
60
+ ### `bw.apply(msg)`
61
+
62
+ Apply a bwserve protocol message to the DOM. Dispatches one of 9 message types: replace — bw.DOM(target, node) append — target.appendChild(bw.createDOM(node)) remove — bw.cleanup(target); target.remove() patch — bw.patch(target, content, attr) batch — iterate ops, call bw.apply for each message — bw.message(target, action, data) register — store a named function for later call() call — invoke a registered function exec — execute arbitrary JS (requires allowExec) Target resolution: Starts with '#' or '.' → CSS selector (querySelector) Otherwise → getElementById, then bw._el fallback
63
+
64
+ **Parameters:**
65
+
66
+ | Name | Type | Description |
67
+ |------|------|-------------|
68
+ | `msg` | `Object` | - Protocol message |
69
+
70
+ **Returns:** `boolean` — if the message was applied successfully
71
+
72
+ ---
73
+
74
+ ### `bw.colorInterp(x, in0, in1, colors, stretch)`
75
+
76
+ ---
77
+
78
+ ### `bw.makeDataTable(config)`
79
+
80
+ Create a ready-to-use data table with title and responsive wrapper. Convenience wrapper around `bw.makeTable()` that adds a title heading, responsive horizontal scroll container, and defaults to striped + hover. Use this for the common case; use `bw.makeTable()` when you need a bare table element with no wrapper.
81
+
82
+ **Parameters:**
83
+
84
+ | Name | Type | Description |
85
+ |------|------|-------------|
86
+ | `config` | `Object` | - Table configuration |
87
+ | `config.title` | `string` | - Table title heading |
88
+ | `config.data` | `Array<Object>` | - Array of row objects |
89
+ | `config.columns` | `Array<Object>` | - Column definitions |
90
+ | `config.className` | `string` | - Additional CSS classes for the table |
91
+ | `config.striped` | `boolean` | - Add striped row styling |
92
+ | `config.hover` | `boolean` | - Add hover row highlighting |
93
+ | `config.responsive` | `boolean` | - Wrap table in responsive overflow div |
94
+
95
+ **Returns:** `Object` — object for table with wrapper
96
+
97
+ **Example:**
98
+ ```javascript
99
+ const table = bw.makeDataTable({ title: "Users", data: [{ name: "Alice", role: "Admin" }], responsive: true });
100
+ ```
101
+
102
+ ---
103
+
104
+ ## DOM Generation
105
+
106
+ ### `bw.raw(str)`
107
+
108
+ Mark a string as raw HTML so it will not be escaped by bw.html() or bw.createDOM(). By default, bitwrench escapes all text content to prevent XSS. Use bw.raw() when you need to embed pre-sanitized HTML, entities, or inline markup.
109
+
110
+ **Parameters:**
111
+
112
+ | Name | Type | Description |
113
+ |------|------|-------------|
114
+ | `str` | `string` | - HTML string to mark as raw |
115
+
116
+ **Returns:** `Object` — object recognized by bw.html() and bw.createDOM()
117
+
118
+ **Example:**
119
+ ```javascript
120
+ bw.raw('Hello &mdash; World') // Used in TACO content: { t: 'p', c: bw.raw('Price: <strong>$9.99</strong>') }
121
+ ```
122
+
123
+ ---
124
+
125
+ ### `bw.html(taco, options = {})`
126
+
127
+ Convert a TACO object (or array of TACOs) to an HTML string. This is the core rendering function — it works in both Node.js and browsers. Use it for server-side rendering, static site generation, or generating HTML snippets. Content is HTML-escaped by default; pass `{ raw: true }` to insert raw HTML.
128
+
129
+ **Parameters:**
130
+
131
+ | Name | Type | Description |
132
+ |------|------|-------------|
133
+ | `taco` | `Object|Array|string` | - TACO object, array of TACOs, or string |
134
+ | `options` | `Object` | - Rendering options |
135
+ | `options.raw` | `boolean` | - If true, skip HTML escaping on content |
136
+
137
+ **Returns:** `string` — string
138
+
139
+ **Example:**
140
+ ```javascript
141
+ bw.html({ t: 'h1', c: 'Hello' }) // => '<h1>Hello</h1>' bw.html({ t: 'div', a: { class: 'card' }, c: [ { t: 'p', c: 'Content here' } ]}) // => '<div class="card"><p>Content here</p></div>'
142
+ ```
143
+
144
+ ---
145
+
146
+ ### `bw.htmlPage(opts)`
147
+
148
+ Generate a complete, self-contained HTML document from TACO content. Produces a full `<!DOCTYPE html>` page with configurable runtime injection, func registry emission (so serialized event handlers work), optional theme, and extra head elements. Designed for static site generation, offline/airgapped use, and the "static site that isn't static" workflow.
149
+
150
+ **Parameters:**
151
+
152
+ | Name | Type | Description |
153
+ |------|------|-------------|
154
+ | `opts` | `Object` | - Page options |
155
+ | `opts.body` | `Object|string|Array` | - Body content: TACO, string, or array |
156
+ | `opts.title` | `string` | - Page title |
157
+ | `opts.state` | `Object` | - State for ${expr} resolution in bw.html() |
158
+ | `opts.runtime` | `string` | - Runtime level: 'inline'|'cdn'|'shim'|'none' |
159
+ | `opts.css` | `string` | - Additional CSS for <style> block |
160
+ | `opts.theme` | `string|Object` | - Theme preset name or config object |
161
+ | `opts.head` | `Array` | - Extra TACO elements rendered into <head> |
162
+ | `opts.favicon` | `string` | - Favicon URL |
163
+ | `opts.lang` | `string` | - HTML lang attribute |
164
+
165
+ **Returns:** `string` — HTML document string
166
+
167
+ **Example:**
168
+ ```javascript
169
+ bw.htmlPage({ title: 'My App', body: { t: 'h1', c: 'Hello World' }, runtime: 'shim' })
170
+ ```
171
+
172
+ ---
173
+
174
+ ### `bw.createDOM(taco, options = {})`
175
+
176
+ Create a live DOM element from a TACO object (browser only). Unlike `bw.html()` which returns a string, this creates real DOM elements with event handlers, lifecycle hooks (mounted/unmount), and state. Used internally by `bw.DOM()`. Throws in Node.js — use `bw.html()` instead.
177
+
178
+ **Parameters:**
179
+
180
+ | Name | Type | Description |
181
+ |------|------|-------------|
182
+ | `taco` | `Object` | - TACO object with {t, a, c, o} |
183
+ | `options` | `Object` | - Creation options |
184
+
185
+ **Returns:** `Element|Text` — element or text node
186
+
187
+ **Example:**
188
+ ```javascript
189
+ var el = bw.createDOM({ t: 'button', a: { class: 'bw_btn', onclick: () => alert('clicked') }, c: 'Click Me' }); document.body.appendChild(el);
190
+ ```
191
+
192
+ ---
193
+
194
+ ### `bw.DOM(target, taco, options = {})`
195
+
196
+ Mount a TACO object into a DOM element, replacing its contents (browser only). This is the primary way to render bitwrench UI to the page. It cleans up any existing children (calling unmount hooks), then renders the TACO into the target. The target element itself is preserved — only its children change.
197
+
198
+ **Parameters:**
199
+
200
+ | Name | Type | Description |
201
+ |------|------|-------------|
202
+ | `target` | `string|Element` | - CSS selector or DOM element to mount into |
203
+ | `taco` | `Object` | - TACO object to render |
204
+ | `options` | `Object` | - Mount options |
205
+
206
+ **Returns:** `Element` — element
207
+
208
+ **Example:**
209
+ ```javascript
210
+ bw.DOM('#app', { t: 'div', a: { class: 'card' }, c: [ { t: 'h2', c: 'Hello' }, { t: 'p', c: 'Built with bitwrench.' } ] });
211
+ ```
212
+
213
+ ---
214
+
215
+ ### `bw.mount(target, taco, options)`
216
+
217
+ Mount a TACO into a target element and return the created root element. Like bw.DOM() but returns the root element of the TACO (not the container), giving direct access to el.bw handle methods.
218
+
219
+ **Parameters:**
220
+
221
+ | Name | Type | Description |
222
+ |------|------|-------------|
223
+ | `target` | `string|Element` | - CSS selector or DOM element |
224
+ | `taco` | `Object` | - TACO to render |
225
+ | `options` | `Object` | - Mount options |
226
+
227
+ **Returns:** `Element` — created root element
228
+
229
+ **Example:**
230
+ ```javascript
231
+ var el = bw.mount('#app', bw.makeCarousel({ items: slides })); el.bw.goToSlide(2); el.bw.next();
232
+ ```
233
+
234
+ ---
235
+
236
+ ### `bw.cleanup(element)`
237
+
238
+ Clean up a DOM element and all its children by calling unmount callbacks, removing pub/sub subscriptions, and clearing state/render references. Called automatically by `bw.DOM()` before re-rendering. Call manually when removing elements to prevent memory leaks from orphaned callbacks.
239
+
240
+ **Parameters:**
241
+
242
+ | Name | Type | Description |
243
+ |------|------|-------------|
244
+ | `element` | `Element` | - DOM element to clean up |
245
+
246
+ **Example:**
247
+ ```javascript
248
+ var el = document.querySelector('#my-widget'); bw.cleanup(el); // runs unmount hooks, clears _bw_state, _bw_render el.remove(); // safe to remove from DOM now
249
+ ```
250
+
251
+ ---
252
+
253
+ ### `bw.render(element, position, taco)`
254
+
255
+ Render a TACO object into the DOM at a specific position, returning a component handle. The handle provides full lifecycle control: state management, re-rendering, class manipulation, show/hide, event binding, and destroy. Components are tracked in a registry for later retrieval via `bw.getComponent()`.
256
+
257
+ **Parameters:**
258
+
259
+ | Name | Type | Description |
260
+ |------|------|-------------|
261
+ | `element` | `Element|string` | - Target element or CSS selector |
262
+ | `position` | `string` | - Position: 'replace', 'prepend', 'append', 'before', 'after' |
263
+ | `taco` | `Object` | - TACO object to render |
264
+
265
+ **Returns:** `Object` — handle with element, setState, update, destroy, etc.
266
+
267
+ **Example:**
268
+ ```javascript
269
+ var handle = bw.render('#app', 'append', { t: 'button', a: { class: 'bw_btn' }, c: 'Click Me', o: { state: { clicks: 0 } } }); handle.setState({ clicks: 1 }); handle.destroy();
270
+ ```
271
+
272
+ ---
273
+
274
+ ### `bw.getComponent(id)`
275
+
276
+ Get a component handle by its ID from the component registry.
277
+
278
+ **Parameters:**
279
+
280
+ | Name | Type | Description |
281
+ |------|------|-------------|
282
+ | `id` | `string` | - Component ID (from bw.render) |
283
+
284
+ **Returns:** `Object|null` — handle or null if not found
285
+
286
+ ---
287
+
288
+ ### `bw.getAllComponents()`
289
+
290
+ Get all registered component handles as a Map.
291
+
292
+ **Returns:** `Map` — of componentId → component handle
293
+
294
+ ---
295
+
296
+ ## Identifiers
297
+
298
+ ### `bw.uuid(prefix)`
299
+
300
+ Generate a unique identifier string for DOM elements or application use. Uses `crypto.randomUUID()` when available (modern browsers), otherwise falls back to a timestamp + counter + random combination. Optional prefix creates namespaced IDs like `bw_card_<hex>` for easier debugging.
301
+
302
+ **Parameters:**
303
+
304
+ | Name | Type | Description |
305
+ |------|------|-------------|
306
+ | `prefix` | `string` | - Optional namespace prefix (e.g. "card", "todo") |
307
+
308
+ **Returns:** `string` — identifier (e.g. "bw_card_a1b2c3d4")
309
+
310
+ **Example:**
311
+ ```javascript
312
+ bw.uuid() // => "bw_m3x9k_1_7f2h4j6a8" bw.uuid('card') // => "bw_card_a1b2c3d4e5f6"
313
+ ```
314
+
315
+ ---
316
+
317
+ ### `bw.assignUUID(taco, forceNew)`
318
+
319
+ Assign a UUID to a TACO object by appending a `bw_uuid_*` token to `taco.a.class`. Idempotent by default — calling twice returns the same UUID. Pass `forceNew=true` to replace an existing UUID (useful in loops where each TACO needs a unique ID).
320
+
321
+ **Parameters:**
322
+
323
+ | Name | Type | Description |
324
+ |------|------|-------------|
325
+ | `taco` | `Object` | - A TACO object `{t, a, c, o}` |
326
+ | `forceNew` | `boolean` | - If true, replaces any existing UUID with a new one |
327
+
328
+ **Returns:** `string` — UUID string (e.g. 'bw_uuid_a1b2c3d4e5')
329
+
330
+ **Example:**
331
+ ```javascript
332
+ var card = bw.makeStatCard({ value: '0', label: 'Scans' }); var uuid = bw.assignUUID(card); // 'bw_uuid_a1b2c3d4e5' var same = bw.assignUUID(card); // same UUID (idempotent) var diff = bw.assignUUID(card, true); // new UUID (forced)
333
+ ```
334
+
335
+ ---
336
+
337
+ ### `bw.getUUID(tacoOrElement)`
338
+
339
+ Read the UUID from a TACO object or DOM element. Pure getter, no side effects.
340
+
341
+ **Parameters:**
342
+
343
+ | Name | Type | Description |
344
+ |------|------|-------------|
345
+ | `tacoOrElement` | `Object|Element` | - A TACO object or DOM element |
346
+
347
+ **Returns:** `string|null` — UUID string, or null if none assigned
348
+
349
+ **Example:**
350
+ ```javascript
351
+ bw.getUUID(card) // 'bw_uuid_a1b2c3d4e5' (from TACO) bw.getUUID(domEl) // 'bw_uuid_a1b2c3d4e5' (from DOM element) bw.getUUID({t:'div'}) // null (no UUID)
352
+ ```
353
+
354
+ ---
355
+
356
+ ### `bw.escapeHTML(str)`
357
+
358
+ Escape HTML special characters to prevent XSS. Converts &, <, >, ", ', and / to their HTML entity equivalents. Used automatically by `bw.html()` unless raw mode is enabled.
359
+
360
+ **Parameters:**
361
+
362
+ | Name | Type | Description |
363
+ |------|------|-------------|
364
+ | `str` | `string` | - String to escape |
365
+
366
+ **Returns:** `string` — string safe for HTML insertion
367
+
368
+ **Example:**
369
+ ```javascript
370
+ bw.escapeHTML('<b>Hello</b> & "world"') // => '&lt;b&gt;Hello&lt;&#x2F;b&gt; &amp; &quot;world&quot;'
371
+ ```
372
+
373
+ ---
374
+
375
+ ## State Management
376
+
377
+ ### `bw.update(target)`
378
+
379
+ Trigger re-render of a component by calling its stored `o.render` function. This is the recommended way to update a component after changing its state. Calls `el._bw_render(el, state)` and emits `bw:statechange` so other components can react without tight coupling.
380
+
381
+ **Parameters:**
382
+
383
+ | Name | Type | Description |
384
+ |------|------|-------------|
385
+ | `target` | `string|Element` | - Element ID, bw_uuid_* class, CSS selector, or DOM element |
386
+
387
+ **Returns:** `Element|null` — element, or null if not found / no render function
388
+
389
+ **Example:**
390
+ ```javascript
391
+ // Given a counter element with o.render el._bw_state.count++; bw.update(el); // re-renders, emits bw:statechange
392
+ ```
393
+
394
+ ---
395
+
396
+ ### `bw.patch(id, content, attr)`
397
+
398
+ Targeted DOM update by element ID — change one element's content or attribute without rebuilding the entire component tree. Use `bw.patch()` for lightweight value updates (scores, labels, counters) and `bw.update()` for full structural re-renders.
399
+
400
+ **Parameters:**
401
+
402
+ | Name | Type | Description |
403
+ |------|------|-------------|
404
+ | `id` | `string|Element` | - Element ID, bw_uuid_* class, CSS selector, or DOM element. Uses node cache for O(1) lookup; falls back to DOM query on cache miss. |
405
+ | `content` | `string|Object` | - New text content, or TACO object to replace children |
406
+ | `attr` | `string` | - If provided, sets this attribute instead of content |
407
+
408
+ **Returns:** `Element|null` — patched element, or null if not found
409
+
410
+ **Example:**
411
+ ```javascript
412
+ bw.patch('score-display', '42'); // update text content bw.patch('status', 'active', 'class'); // update an attribute bw.patch('info', { t: 'em', c: 'new' }); // replace children with TACO
413
+ ```
414
+
415
+ ---
416
+
417
+ ### `bw.patchAll(patches)`
418
+
419
+ Batch version of `bw.patch()` — update multiple elements in one call. Useful for updating several independent values simultaneously, such as a dashboard with multiple counters.
420
+
421
+ **Parameters:**
422
+
423
+ | Name | Type | Description |
424
+ |------|------|-------------|
425
+ | `patches` | `Object` | - Map of { elementId: newContent, ... } |
426
+
427
+ **Returns:** `Object` — of { elementId: patchedElement|null, ... }
428
+
429
+ **Example:**
430
+ ```javascript
431
+ bw.patchAll({ 'cpu-display': '78%', 'mem-display': '4.2 GB', 'disk-display': '120 GB free' });
432
+ ```
433
+
434
+ ---
435
+
436
+ ## Events (DOM)
437
+
438
+ ### `bw.emit(target, eventName, detail)`
439
+
440
+ Emit a custom DOM event on an element. Events are prefixed with `bw:` to avoid collision with native events and bubble by default so ancestor elements can listen. Use with `bw.on()` for DOM-scoped communication between components.
441
+
442
+ **Parameters:**
443
+
444
+ | Name | Type | Description |
445
+ |------|------|-------------|
446
+ | `target` | `string|Element` | - Element ID, bw_uuid_* class, CSS selector, or DOM element. Uses node cache for O(1) lookup; falls back to DOM query on cache miss. |
447
+ | `eventName` | `string` | - Event name (will be prefixed with 'bw:') |
448
+ | `detail` | `*` | - Data to pass with the event |
449
+
450
+ **Example:**
451
+ ```javascript
452
+ bw.emit('#my-widget', 'statechange', { count: 42 }); // Dispatches CustomEvent 'bw:statechange' on the element
453
+ ```
454
+
455
+ ---
456
+
457
+ ### `bw.on(target, eventName, handler)`
458
+
459
+ Listen for a custom bitwrench event on a DOM element. Handler receives `(detail, event)` for convenience — the detail object is the first argument so you don't need to destructure `e.detail`. Events bubble, so you can listen on an ancestor element.
460
+
461
+ **Parameters:**
462
+
463
+ | Name | Type | Description |
464
+ |------|------|-------------|
465
+ | `target` | `string|Element` | - Element ID, bw_uuid_* class, CSS selector, or DOM element. Uses node cache for O(1) lookup; falls back to DOM query on cache miss. |
466
+ | `eventName` | `string` | - Event name (will be prefixed with 'bw:') |
467
+ | `handler` | `Function` | - Called with (detail, event) |
468
+
469
+ **Returns:** `Element|null` — element (for chaining), or null if not found
470
+
471
+ **Example:**
472
+ ```javascript
473
+ bw.on(document.body, 'statechange', function(detail) { console.log('State changed:', detail); });
474
+ ```
475
+
476
+ ---
477
+
478
+ ## Pub/Sub
479
+
480
+ ### `bw.pub(topic, detail)`
481
+
482
+ Publish to a topic, calling all subscribers in registration order. Application-scoped pub/sub decoupled from the DOM tree. Each subscriber is wrapped in try/catch so one bad handler can't break others. Use `bw.pub()`/`bw.sub()` for app-wide communication; use `bw.emit()`/`bw.on()` for DOM-scoped events.
483
+
484
+ **Parameters:**
485
+
486
+ | Name | Type | Description |
487
+ |------|------|-------------|
488
+ | `topic` | `string` | - Topic name (plain string, no prefix) |
489
+ | `detail` | `*` | - Data to pass to subscribers |
490
+
491
+ **Returns:** `number` — of successfully called subscribers
492
+
493
+ **Example:**
494
+ ```javascript
495
+ bw.pub('score:updated', { player: 'X', score: 10 });
496
+ ```
497
+
498
+ ---
499
+
500
+ ### `bw.sub(topic, handler, el)`
501
+
502
+ Subscribe to a topic. Returns an unsub() function. Optional third argument ties the subscription to a DOM element's lifecycle — when `bw.cleanup()` is called on that element, the subscription is automatically removed, preventing memory leaks.
503
+
504
+ **Parameters:**
505
+
506
+ | Name | Type | Description |
507
+ |------|------|-------------|
508
+ | `topic` | `string` | - Topic name |
509
+ | `handler` | `Function` | - Called with (detail) on each publish |
510
+ | `el` | `Element` | - Optional DOM element to tie lifecycle to |
511
+
512
+ **Returns:** `Function` — to unsubscribe
513
+
514
+ **Example:**
515
+ ```javascript
516
+ var unsub = bw.sub('score:updated', function(detail) { console.log(detail.player, 'scored', detail.score); }); // Later: unsub() to stop listening
517
+ ```
518
+
519
+ ---
520
+
521
+ ### `bw.unsub(topic, handler)`
522
+
523
+ Unsubscribe a handler by reference from a topic. Removes ALL instances of the given handler on the topic. Alternative to calling the unsub function returned by `bw.sub()`.
524
+
525
+ **Parameters:**
526
+
527
+ | Name | Type | Description |
528
+ |------|------|-------------|
529
+ | `topic` | `string` | - Topic name |
530
+ | `handler` | `Function` | - The handler to remove (by reference equality) |
531
+
532
+ **Returns:** `number` — of removed subscriptions
533
+
534
+ ---
535
+
536
+ ## CSS & Styling
537
+
538
+ ### `bw.css(rules, options = {})`
539
+
540
+ Generate CSS from JavaScript objects. Converts an object of `{ selector: { prop: value } }` rules into a CSS string. CamelCase property names are auto-converted to kebab-case (e.g. `fontSize` → `font-size`). Accepts nested arrays of rule objects.
541
+
542
+ **Parameters:**
543
+
544
+ | Name | Type | Description |
545
+ |------|------|-------------|
546
+ | `rules` | `Object|Array|string` | - CSS rules as JS objects, array of rule objects, or raw CSS string |
547
+ | `options` | `Object` | - Generation options |
548
+ | `options.minify` | `boolean` | - Minify output (no whitespace) |
549
+
550
+ **Returns:** `string` — string
551
+
552
+ **Example:**
553
+ ```javascript
554
+ bw.css({ '.card': { padding: '1rem', fontSize: '14px', borderRadius: '8px' } }) // => '.card {\n padding: 1rem;\n font-size: 14px;\n border-radius: 8px;\n}'
555
+ ```
556
+
557
+ ---
558
+
559
+ ### `bw.injectCSS(css, options = {})`
560
+
561
+ Inject CSS into the document head (browser only). Creates or reuses a `<style>` element (identified by `id`). Can accept raw CSS strings or JS rule objects (which are converted via `bw.css()`). By default appends to existing content; set `append: false` to replace.
562
+
563
+ **Parameters:**
564
+
565
+ | Name | Type | Description |
566
+ |------|------|-------------|
567
+ | `css` | `string|Object|Array` | - CSS string, or JS rule objects to convert |
568
+ | `options` | `Object` | - Injection options |
569
+ | `options.id` | `string` | - ID for the style element |
570
+ | `options.append` | `boolean` | - Append to existing CSS (false to replace) |
571
+
572
+ **Returns:** `Element` — style element
573
+
574
+ **Example:**
575
+ ```javascript
576
+ bw.injectCSS('.my-class { color: red; }'); bw.injectCSS({ '.card': { padding: '1rem' } }, { id: 'card-styles' });
577
+ ```
578
+
579
+ ---
580
+
581
+ ### `bw.s()`
582
+
583
+ Merge multiple style objects into one (left-to-right). Like `Object.assign()` for styles, but filters out null/undefined arguments. Compose inline styles or CSS rule objects without mutation.
584
+
585
+ **Parameters:**
586
+
587
+ | Name | Type | Description |
588
+ |------|------|-------------|
589
+ | `styles` | `...Object` | - Style objects to merge (left-to-right) |
590
+
591
+ **Returns:** `Object` — style object
592
+
593
+ **Example:**
594
+ ```javascript
595
+ var style = bw.s({ display: 'flex' }, { gap: '1rem' }, { color: 'red' }); // => { display: 'flex', gap: '1rem', color: 'red' }
596
+ ```
597
+
598
+ ---
599
+
600
+ ### `bw.responsive(selector, breakpoints)`
601
+
602
+ Generate responsive CSS with media query breakpoints. Produces a CSS string with `@media (min-width)` rules for standard breakpoints. These match the grid system and theme.breakpoints: sm: 576px, md: 768px, lg: 992px, xl: 1200px Pass the result to `bw.injectCSS()`.
603
+
604
+ **Parameters:**
605
+
606
+ | Name | Type | Description |
607
+ |------|------|-------------|
608
+ | `selector` | `string` | - CSS selector |
609
+ | `breakpoints` | `Object` | - Object with keys: base, sm, md, lg, xl |
610
+
611
+ **Returns:** `string` — CSS string (pass to bw.injectCSS)
612
+
613
+ **Example:**
614
+ ```javascript
615
+ var css = bw.responsive('.grid', { base: { gridTemplateColumns: '1fr' }, md: { gridTemplateColumns: '1fr 1fr' }, lg: { gridTemplateColumns: '1fr 1fr 1fr' } }); bw.injectCSS(css);
616
+ ```
617
+
618
+ ---
619
+
620
+ ### `bw.makeStyles(config)`
621
+
622
+ Generate a complete styles object from seed colors and layout config. Pure function — no DOM, no state, no side effects. All parameters are optional. Defaults to the bitwrench default palette.
623
+
624
+ **Parameters:**
625
+
626
+ | Name | Type | Description |
627
+ |------|------|-------------|
628
+ | `config` | `Object` | - Style configuration |
629
+ | `config.primary` | `string` | - Primary brand color hex |
630
+ | `config.secondary` | `string` | - Secondary color hex |
631
+ | `config.tertiary` | `string` | - Tertiary color hex (defaults to primary) |
632
+ | `config.spacing` | `string` | - 'compact' | 'normal' | 'spacious' |
633
+ | `config.radius` | `string` | - 'none' | 'sm' | 'md' | 'lg' | 'pill' |
634
+
635
+ **Returns:** `Object` — css, alternateCss, rules, alternateRules, palette, alternatePalette, isLightPrimary }
636
+
637
+ **Example:**
638
+ ```javascript
639
+ var styles = bw.makeStyles({ primary: '#4f46e5', secondary: '#d97706' }); console.log(styles.palette.primary.base); // '#4f46e5' // styles.css contains all themed CSS — nothing injected
640
+ ```
641
+
642
+ ---
643
+
644
+ ### `bw.applyStyles(styles, scope)`
645
+
646
+ Inject styles into the DOM with optional scoping. Takes a styles object from `makeStyles()` and creates a single `<style>` element in `<head>`. If a scope selector is provided, all CSS rules are wrapped under that selector. Alternate CSS is wrapped under `.bw_theme_alt`.
647
+
648
+ **Parameters:**
649
+
650
+ | Name | Type | Description |
651
+ |------|------|-------------|
652
+ | `styles` | `Object` | - Result of `bw.makeStyles()` |
653
+ | `scope` | `string` | - Scope selector (e.g. '#my-dashboard', '.preview'). Omit for global. |
654
+
655
+ **Returns:** `Element|null` — `<style>` element, or null in Node.js
656
+
657
+ **Example:**
658
+ ```javascript
659
+ var styles = bw.makeStyles({ primary: '#4f46e5' }); bw.applyStyles(styles); // global bw.applyStyles(styles, '#my-dashboard'); // scoped
660
+ ```
661
+
662
+ ---
663
+
664
+ ### `bw.loadStyles(config, scope)`
665
+
666
+ Generate and apply styles in one call. Convenience wrapper. Equivalent to: `bw.applyStyles(bw.makeStyles(config), scope)`
667
+
668
+ **Parameters:**
669
+
670
+ | Name | Type | Description |
671
+ |------|------|-------------|
672
+ | `config` | `Object` | - Style configuration (same as `makeStyles`) |
673
+ | `scope` | `string` | - Scope selector (same as `applyStyles`) |
674
+
675
+ **Returns:** `Element|null` — `<style>` element, or null in Node.js
676
+
677
+ **Example:**
678
+ ```javascript
679
+ bw.loadStyles(); // defaults, global bw.loadStyles({ primary: '#4f46e5' }); // custom, global bw.loadStyles({ primary: '#4f46e5' }, '#my-dashboard'); // custom, scoped
680
+ ```
681
+
682
+ ---
683
+
684
+ ### `bw.loadReset()`
685
+
686
+ Inject the CSS reset (box-sizing, html/body font, reduced-motion). Idempotent — if already injected, returns the existing `<style>` element.
687
+
688
+ **Returns:** `Element|null` — `<style>` element, or null in Node.js
689
+
690
+ **Example:**
691
+ ```javascript
692
+ bw.loadReset(); // inject once, safe to call multiple times
693
+ ```
694
+
695
+ ---
696
+
697
+ ### `bw.toggleStyles(scope)`
698
+
699
+ Toggle between primary and alternate palettes. Adds/removes the `bw_theme_alt` class on the scoping element. Without a scope, toggles on `<html>` (global). With a scope, toggles on the first matching element.
700
+
701
+ **Parameters:**
702
+
703
+ | Name | Type | Description |
704
+ |------|------|-------------|
705
+ | `scope` | `string` | - Scope selector (e.g. '#my-dashboard'). Omit for global. |
706
+
707
+ **Returns:** `string` — mode after toggle: 'primary' or 'alternate'
708
+
709
+ **Example:**
710
+ ```javascript
711
+ bw.toggleStyles(); // global toggle on <html> bw.toggleStyles('#my-dashboard'); // scoped toggle
712
+ ```
713
+
714
+ ---
715
+
716
+ ### `bw.clearStyles(scope)`
717
+
718
+ Remove injected styles for a given scope. Finds the `<style>` element by id and removes it. Also removes the `bw_theme_alt` class from the relevant element.
719
+
720
+ **Parameters:**
721
+
722
+ | Name | Type | Description |
723
+ |------|------|-------------|
724
+ | `scope` | `string` | - Scope selector. Omit to remove global styles. |
725
+
726
+ **Example:**
727
+ ```javascript
728
+ bw.clearStyles(); // remove global styles bw.clearStyles('#my-dashboard'); // remove scoped styles bw.clearStyles('reset'); // remove the CSS reset
729
+ ```
730
+
731
+ ---
732
+
733
+ ## Component Builders
734
+
735
+ ### `bw.makeTable(config)`
736
+
737
+ Create a sortable TACO table from an array of row objects. Returns a bare `<table>` TACO — no wrapper, title, or responsive scroll. Use this when you need full control over table placement, or when embedding the table inside your own layout. For a ready-to-use table with title, responsive wrapper, and defaults (striped + hover), use `bw.makeDataTable()`. Auto-detects columns from data keys if not specified. Supports click-to-sort headers with ascending/descending indicators.
738
+
739
+ **Parameters:**
740
+
741
+ | Name | Type | Description |
742
+ |------|------|-------------|
743
+ | `config` | `Object` | - Table configuration |
744
+ | `config.data` | `Array<Object>` | - Array of row objects to display |
745
+ | `config.columns` | `Array<Object>` | - Column definitions with key, label, render |
746
+ | `config.className` | `string` | - Additional CSS classes for table element |
747
+ | `config.sortable` | `boolean` | - Enable click-to-sort headers |
748
+ | `config.onSort` | `Function` | - Sort callback (column, direction) |
749
+ | `config.selectable` | `boolean` | - Enable row selection on click |
750
+ | `config.onRowClick` | `Function` | - Row click callback (row, index, event) |
751
+ | `config.pageSize` | `number` | - Rows per page (enables pagination when set) |
752
+ | `config.currentPage` | `number` | - Current page number (1-based) |
753
+ | `config.onPageChange` | `Function` | - Page change callback (newPage) |
754
+
755
+ **Returns:** `Object` — object for table (with optional pagination controls)
756
+
757
+ **Example:**
758
+ ```javascript
759
+ bw.makeTable({ data: [ { name: 'Alice', age: 30 }, { name: 'Bob', age: 25 } ], columns: [ { key: 'name', label: 'Name' }, { key: 'age', label: 'Age' } ], selectable: true, onRowClick: function(row, i) { console.log('clicked', row.name); }, pageSize: 10, currentPage: 1, onPageChange: function(page) { console.log('page', page); } });
760
+ ```
761
+
762
+ ---
763
+
764
+ ### `bw.makeTableFromArray(config)`
765
+
766
+ Create a table from a 2D array. Converts a 2D array into the object-array format that `bw.makeTable()` expects, then delegates. By default, the first row is used as column headers. All standard `makeTable` props (striped, hover, sortable, columns, onSort, etc.) are passed through.
767
+
768
+ **Parameters:**
769
+
770
+ | Name | Type | Description |
771
+ |------|------|-------------|
772
+ | `config` | `Object` | - Configuration object |
773
+ | `config.data` | `Array<Array>` | - 2D array of values |
774
+ | `config.headerRow` | `boolean` | - Treat first row as column headers |
775
+ | `config.striped` | `boolean` | - Striped rows |
776
+ | `config.hover` | `boolean` | - Hover highlight |
777
+ | `config.sortable` | `boolean` | - Enable sort |
778
+ | `config.columns` | `Array<Object>` | - Override auto-generated column defs |
779
+ | `config.className` | `string` | - Additional CSS classes |
780
+ | `config.onSort` | `Function` | - Sort callback |
781
+ | `config.sortColumn` | `string` | - Currently sorted column key |
782
+ | `config.sortDirection` | `string` | - Sort direction |
783
+
784
+ **Returns:** `Object` — object for table
785
+
786
+ **Example:**
787
+ ```javascript
788
+ bw.makeTableFromArray({ data: [ ['Name', 'Role', 'Status'], ['Alice', 'Engineer', 'Active'], ['Bob', 'Designer', 'Away'] ], striped: true, hover: true });
789
+ ```
790
+
791
+ ---
792
+
793
+ ### `bw.makeBarChart(config)`
794
+
795
+ Create a vertical bar chart from data. Renders a pure-CSS bar chart using flexbox and percentage heights. No canvas, SVG, or external charting library required.
796
+
797
+ **Parameters:**
798
+
799
+ | Name | Type | Description |
800
+ |------|------|-------------|
801
+ | `config` | `Object` | - Chart configuration |
802
+ | `config.data` | `Array<Object>` | - Array of data objects |
803
+ | `config.labelKey` | `string` | - Key for bar labels |
804
+ | `config.valueKey` | `string` | - Key for bar values |
805
+ | `config.title` | `string` | - Chart title |
806
+ | `config.color` | `string` | - Bar color (hex or CSS color) |
807
+ | `config.height` | `string` | - Height of the chart area |
808
+ | `config.formatValue` | `Function` | - Value label formatter: (value) => string |
809
+ | `config.showValues` | `boolean` | - Show value labels above bars |
810
+ | `config.showLabels` | `boolean` | - Show labels below bars |
811
+ | `config.className` | `string` | - Additional CSS classes |
812
+
813
+ **Returns:** `Object` — object
814
+
815
+ **Example:**
816
+ ```javascript
817
+ bw.makeBarChart({ data: [ { label: 'Jan', value: 12400 }, { label: 'Feb', value: 15800 }, { label: 'Mar', value: 9200 } ], title: 'Monthly Revenue', color: '#0077b6', formatValue: (v) => '$' + (v / 1000).toFixed(1) + 'k' });
818
+ ```
819
+
820
+ ---
821
+
822
+ ### `bw.makeCard(props = {})`
823
+
824
+ Create a card component with optional header, body, footer, and image support Supports images (top, bottom, left, right), shadow levels, subtitle, hover animation, and custom section class overrides. For horizontal image layouts (left/right), content is wrapped in a row grid.
825
+
826
+ **Parameters:**
827
+
828
+ | Name | Type | Description |
829
+ |------|------|-------------|
830
+ | `props` | `Object` | - Card configuration |
831
+ | `props.title` | `string` | - Card title displayed in the body |
832
+ | `props.subtitle` | `string` | - Card subtitle (muted text below title) |
833
+ | `props.content` | `string|Object|Array` | - Card body content (string, TACO, or array) |
834
+ | `props.footer` | `string|Object` | - Card footer content |
835
+ | `props.header` | `string|Object` | - Card header content |
836
+ | `props.image` | `Object` | - Card image configuration |
837
+ | `props.image.src` | `string` | - Image source URL |
838
+ | `props.image.alt` | `string` | - Image alt text |
839
+ | `props.imagePosition` | `string` | - Image position ("top", "bottom", "left", "right") |
840
+ | `props.variant` | `string` | - Color variant (e.g. "primary", "danger") |
841
+ | `props.bordered` | `boolean` | - Show card border |
842
+ | `props.shadow` | `string` | - Shadow level ("none", "sm", "md", "lg") |
843
+ | `props.hoverable` | `boolean` | - Enable hover lift animation |
844
+ | `props.className` | `string` | - Additional CSS classes |
845
+ | `props.style` | `Object` | - Inline style object |
846
+ | `props.headerClass` | `string` | - Additional header CSS classes |
847
+ | `props.bodyClass` | `string` | - Additional body CSS classes |
848
+ | `props.footerClass` | `string` | - Additional footer CSS classes |
849
+ | `props.state` | `Object` | - Component state object |
850
+
851
+ **Returns:** `Object` — object representing a card component
852
+
853
+ **Example:**
854
+ ```javascript
855
+ const card = makeCard({ title: "Status", content: "All systems operational", variant: "success" }); bw.DOM("#app", card);
856
+ ```
857
+
858
+ ---
859
+
860
+ ### `bw.makeButton(props = {})`
861
+
862
+ Create a button component
863
+
864
+ **Parameters:**
865
+
866
+ | Name | Type | Description |
867
+ |------|------|-------------|
868
+ | `props` | `Object` | - Button configuration |
869
+ | `props.text` | `string` | - Button label text |
870
+ | `props.variant` | `string` | - Color variant (e.g. "primary", "secondary", "danger") |
871
+ | `props.size` | `string` | - Size variant ("sm" or "lg") |
872
+ | `props.disabled` | `boolean` | - Whether the button is disabled |
873
+ | `props.onclick` | `Function` | - Click event handler |
874
+ | `props.type` | `string` | - HTML button type ("button", "submit", "reset") |
875
+ | `props.className` | `string` | - Additional CSS classes |
876
+ | `props.style` | `Object` | - Inline style object |
877
+
878
+ **Returns:** `Object` — object representing a button element
879
+
880
+ **Example:**
881
+ ```javascript
882
+ const btn = makeButton({ text: "Save", variant: "success", onclick: () => console.log("saved") }); // String shorthand: const ok = makeButton("OK");
883
+ ```
884
+
885
+ ---
886
+
887
+ ### `bw.makeContainer(props = {})`
888
+
889
+ Create a container component for centering and constraining content width
890
+
891
+ **Parameters:**
892
+
893
+ | Name | Type | Description |
894
+ |------|------|-------------|
895
+ | `props` | `Object` | - Container configuration |
896
+ | `props.fluid` | `boolean` | - Use full-width fluid container |
897
+ | `props.children` | `Array|Object|string` | - Child content |
898
+ | `props.className` | `string` | - Additional CSS classes |
899
+
900
+ **Returns:** `Object` — object representing a container div
901
+
902
+ **Example:**
903
+ ```javascript
904
+ const container = makeContainer({ fluid: true, children: [makeRow({ children: [...] })] });
905
+ ```
906
+
907
+ ---
908
+
909
+ ### `bw.makeRow(props = {})`
910
+
911
+ Create a flexbox row for the grid system
912
+
913
+ **Parameters:**
914
+
915
+ | Name | Type | Description |
916
+ |------|------|-------------|
917
+ | `props` | `Object` | - Row configuration |
918
+ | `props.children` | `Array|Object|string` | - Child columns |
919
+ | `props.className` | `string` | - Additional CSS classes |
920
+ | `props.gap` | `number` | - Gap size (1-5) applied via bw_g_{gap} class |
921
+
922
+ **Returns:** `Object` — object representing a grid row
923
+
924
+ **Example:**
925
+ ```javascript
926
+ const row = makeRow({ gap: 4, children: [makeCol({ size: 6, content: "Left" }), makeCol({ size: 6, content: "Right" })] });
927
+ ```
928
+
929
+ ---
930
+
931
+ ### `bw.makeCol(props = {})`
932
+
933
+ Create a grid column with responsive sizing Supports both fixed and responsive column sizes. Pass an object for responsive breakpoints (e.g. {xs: 12, md: 6, lg: 4}).
934
+
935
+ **Parameters:**
936
+
937
+ | Name | Type | Description |
938
+ |------|------|-------------|
939
+ | `props` | `Object` | - Column configuration |
940
+ | `props.size` | `number|Object` | - Column size (1-12) or responsive object {xs, sm, md, lg, xl} |
941
+ | `props.offset` | `number` | - Column offset (1-12) |
942
+ | `props.push` | `number` | - Column push (1-12) |
943
+ | `props.pull` | `number` | - Column pull (1-12) |
944
+ | `props.content` | `Array|Object|string` | - Column content (alias for children) |
945
+ | `props.children` | `Array|Object|string` | - Column content |
946
+ | `props.className` | `string` | - Additional CSS classes |
947
+
948
+ **Returns:** `Object` — object representing a grid column
949
+
950
+ **Example:**
951
+ ```javascript
952
+ const col = makeCol({ size: { xs: 12, md: 6 }, content: "Responsive column" });
953
+ ```
954
+
955
+ ---
956
+
957
+ ### `bw.makeNav(props = {})`
958
+
959
+ Create a navigation component with tabs or pills styling
960
+
961
+ **Parameters:**
962
+
963
+ | Name | Type | Description |
964
+ |------|------|-------------|
965
+ | `props` | `Object` | - Nav configuration |
966
+ | `props.items` | `Array<Object>` | - Navigation items |
967
+ | `props.items[].text` | `string` | - Item display text |
968
+ | `props.items[].href` | `string` | - Item link URL |
969
+ | `props.items[].active` | `boolean` | - Whether this item is active |
970
+ | `props.items[].disabled` | `boolean` | - Whether this item is disabled |
971
+ | `props.pills` | `boolean` | - Use pill styling instead of tabs |
972
+ | `props.vertical` | `boolean` | - Stack items vertically |
973
+ | `props.className` | `string` | - Additional CSS classes |
974
+
975
+ **Returns:** `Object` — object representing a nav element
976
+
977
+ **Example:**
978
+ ```javascript
979
+ const nav = makeNav({ pills: true, items: [ { text: "Home", href: "/", active: true }, { text: "About", href: "/about" } ] });
980
+ ```
981
+
982
+ ---
983
+
984
+ ### `bw.makeNavbar(props = {})`
985
+
986
+ Create a navbar component with brand and navigation links
987
+
988
+ **Parameters:**
989
+
990
+ | Name | Type | Description |
991
+ |------|------|-------------|
992
+ | `props` | `Object` | - Navbar configuration |
993
+ | `props.brand` | `string` | - Brand name or logo text |
994
+ | `props.brandHref` | `string` | - Brand link URL |
995
+ | `props.items` | `Array<Object>` | - Navigation items |
996
+ | `props.items[].text` | `string` | - Item display text |
997
+ | `props.items[].href` | `string` | - Item link URL |
998
+ | `props.items[].active` | `boolean` | - Whether this item is active |
999
+ | `props.dark` | `boolean` | - Use dark theme styling |
1000
+ | `props.className` | `string` | - Additional CSS classes |
1001
+
1002
+ **Returns:** `Object` — object representing a navbar element
1003
+
1004
+ **Example:**
1005
+ ```javascript
1006
+ const navbar = makeNavbar({ brand: "MyApp", dark: true, items: [ { text: "Home", href: "/", active: true }, { text: "Docs", href: "/docs" } ] });
1007
+ ```
1008
+
1009
+ ---
1010
+
1011
+ ### `bw.makeTabs(props = {})`
1012
+
1013
+ Create a tabbed interface with accessible tab navigation Each tab is rendered as a button with ARIA attributes for accessibility. Clicking a tab shows its content pane and hides others. The active tab can be set via activeIndex or by setting active:true on a tab item.
1014
+
1015
+ **Parameters:**
1016
+
1017
+ | Name | Type | Description |
1018
+ |------|------|-------------|
1019
+ | `props` | `Object` | - Tabs configuration |
1020
+ | `props.tabs` | `Array<Object>` | - Tab definitions |
1021
+ | `props.tabs[].label` | `string` | - Tab button label |
1022
+ | `props.tabs[].content` | `string|Object|Array` | - Tab pane content |
1023
+ | `props.tabs[].active` | `boolean` | - Whether this tab is initially active |
1024
+ | `props.activeIndex` | `number` | - Default active tab index (overridden by tab.active) |
1025
+
1026
+ **Returns:** `Object` — object representing a tabbed interface
1027
+
1028
+ **Example:**
1029
+ ```javascript
1030
+ const tabs = makeTabs({ tabs: [ { label: "Overview", content: "Tab 1 content", active: true }, { label: "Details", content: "Tab 2 content" } ] }); bw.DOM("#app", tabs);
1031
+ ```
1032
+
1033
+ ---
1034
+
1035
+ ### `bw.makeAlert(props = {})`
1036
+
1037
+ Create an alert/notification component
1038
+
1039
+ **Parameters:**
1040
+
1041
+ | Name | Type | Description |
1042
+ |------|------|-------------|
1043
+ | `props` | `Object` | - Alert configuration |
1044
+ | `props.content` | `string|Object|Array` | - Alert message content |
1045
+ | `props.variant` | `string` | - Color variant ("primary", "secondary", "success", "danger", "warning", "info", "light", "dark") |
1046
+ | `props.dismissible` | `boolean` | - Show a close button to dismiss the alert |
1047
+ | `props.className` | `string` | - Additional CSS classes |
1048
+
1049
+ **Returns:** `Object` — object representing an alert element
1050
+
1051
+ **Example:**
1052
+ ```javascript
1053
+ const alert = makeAlert({ content: "Operation completed successfully!", variant: "success", dismissible: true }); // String shorthand: const msg = makeAlert("Something happened");
1054
+ ```
1055
+
1056
+ ---
1057
+
1058
+ ### `bw.makeBadge(props = {})`
1059
+
1060
+ Create an inline badge/label component
1061
+
1062
+ **Parameters:**
1063
+
1064
+ | Name | Type | Description |
1065
+ |------|------|-------------|
1066
+ | `props` | `Object` | - Badge configuration |
1067
+ | `props.text` | `string` | - Badge display text |
1068
+ | `props.variant` | `string` | - Color variant |
1069
+ | `props.size` | `string` | - Size variant: 'sm' or 'lg' (default is medium) |
1070
+ | `props.pill` | `boolean` | - Use pill (rounded) shape |
1071
+ | `props.className` | `string` | - Additional CSS classes |
1072
+
1073
+ **Returns:** `Object` — object representing a badge span
1074
+
1075
+ **Example:**
1076
+ ```javascript
1077
+ const badge = makeBadge({ text: "New", variant: "danger", pill: true }); const small = makeBadge({ text: "3", variant: "info", size: "sm" }); // String shorthand: const tag = makeBadge("New");
1078
+ ```
1079
+
1080
+ ---
1081
+
1082
+ ### `bw.makeProgress(props = {})`
1083
+
1084
+ Create a progress bar component with ARIA accessibility
1085
+
1086
+ **Parameters:**
1087
+
1088
+ | Name | Type | Description |
1089
+ |------|------|-------------|
1090
+ | `props` | `Object` | - Progress bar configuration |
1091
+ | `props.value` | `number` | - Current progress value |
1092
+ | `props.max` | `number` | - Maximum value |
1093
+ | `props.variant` | `string` | - Color variant |
1094
+ | `props.striped` | `boolean` | - Use striped pattern |
1095
+ | `props.animated` | `boolean` | - Animate the stripes |
1096
+ | `props.label` | `string` | - Custom label text (defaults to percentage) |
1097
+ | `props.height` | `number` | - Custom height in pixels |
1098
+
1099
+ **Returns:** `Object` — object representing a progress bar
1100
+
1101
+ **Example:**
1102
+ ```javascript
1103
+ const progress = makeProgress({ value: 75, variant: "success", striped: true, animated: true });
1104
+ ```
1105
+
1106
+ ---
1107
+
1108
+ ### `bw.makeListGroup(props = {})`
1109
+
1110
+ Create a list group component for displaying lists of items Items can be simple strings or objects with text, active, disabled, href, and onclick properties. When interactive is true or items have href/onclick, items render as anchor tags.
1111
+
1112
+ **Parameters:**
1113
+
1114
+ | Name | Type | Description |
1115
+ |------|------|-------------|
1116
+ | `props` | `Object` | - List group configuration |
1117
+ | `props.items` | `Array<string|Object>` | - List items (strings or objects) |
1118
+ | `props.items[].text` | `string` | - Item display text |
1119
+ | `props.items[].active` | `boolean` | - Whether this item is active |
1120
+ | `props.items[].disabled` | `boolean` | - Whether this item is disabled |
1121
+ | `props.items[].href` | `string` | - Item link URL |
1122
+ | `props.items[].onclick` | `Function` | - Item click handler |
1123
+ | `props.flush` | `boolean` | - Remove borders for use inside cards |
1124
+ | `props.interactive` | `boolean` | - Make all items interactive (anchor tags) |
1125
+
1126
+ **Returns:** `Object` — object representing a list group
1127
+
1128
+ **Example:**
1129
+ ```javascript
1130
+ const list = makeListGroup({ interactive: true, items: [ { text: "Active item", active: true }, { text: "Regular item" }, { text: "Disabled item", disabled: true } ] });
1131
+ ```
1132
+
1133
+ ---
1134
+
1135
+ ### `bw.makeBreadcrumb(props = {})`
1136
+
1137
+ Create a breadcrumb navigation component The last item with active:true is rendered as plain text (no link). All other items render as anchor tags.
1138
+
1139
+ **Parameters:**
1140
+
1141
+ | Name | Type | Description |
1142
+ |------|------|-------------|
1143
+ | `props` | `Object` | - Breadcrumb configuration |
1144
+ | `props.items` | `Array<Object>` | - Breadcrumb items |
1145
+ | `props.items[].text` | `string` | - Item display text |
1146
+ | `props.items[].href` | `string` | - Item link URL |
1147
+ | `props.items[].active` | `boolean` | - Whether this is the current page |
1148
+
1149
+ **Returns:** `Object` — object representing a breadcrumb nav
1150
+
1151
+ **Example:**
1152
+ ```javascript
1153
+ const crumbs = makeBreadcrumb({ items: [ { text: "Home", href: "/" }, { text: "Products", href: "/products" }, { text: "Widget", active: true } ] });
1154
+ ```
1155
+
1156
+ ---
1157
+
1158
+ ### `bw.makeForm(props = {})`
1159
+
1160
+ Create a form wrapper with default submit prevention
1161
+
1162
+ **Parameters:**
1163
+
1164
+ | Name | Type | Description |
1165
+ |------|------|-------------|
1166
+ | `props` | `Object` | - Form configuration |
1167
+ | `props.children` | `Array|Object|string` | - Form contents (form groups, inputs, buttons) |
1168
+ | `props.onsubmit` | `Function` | - Submit handler (defaults to preventDefault) |
1169
+ | `props.className` | `string` | - Additional CSS classes |
1170
+
1171
+ **Returns:** `Object` — object representing a form element
1172
+
1173
+ **Example:**
1174
+ ```javascript
1175
+ const form = makeForm({ onsubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [ makeFormGroup({ label: "Name", input: makeInput({ placeholder: "Enter name" }) }), makeButton({ text: "Submit", type: "submit" }) ] });
1176
+ ```
1177
+
1178
+ ---
1179
+
1180
+ ### `bw.makeFormGroup(props = {})`
1181
+
1182
+ Create a form group with label, input, optional help text and validation feedback
1183
+
1184
+ **Parameters:**
1185
+
1186
+ | Name | Type | Description |
1187
+ |------|------|-------------|
1188
+ | `props` | `Object` | - Form group configuration |
1189
+ | `props.label` | `string` | - Label text |
1190
+ | `props.input` | `Object` | - Input TACO object (from makeInput, makeSelect, etc.) |
1191
+ | `props.help` | `string` | - Help text displayed below the input |
1192
+ | `props.id` | `string` | - Input ID (links label to input via for/id) |
1193
+ | `props.validation` | `string` | - Validation state ("valid" or "invalid") |
1194
+ | `props.feedback` | `string` | - Validation feedback text shown below input |
1195
+ | `props.required` | `boolean` | - Show required indicator (*) on label |
1196
+
1197
+ **Returns:** `Object` — object representing a form group
1198
+
1199
+ **Example:**
1200
+ ```javascript
1201
+ const group = makeFormGroup({ label: "Email", id: "email", input: makeInput({ type: "email", id: "email", placeholder: "you@example.com" }), validation: "invalid", feedback: "Please enter a valid email address." });
1202
+ ```
1203
+
1204
+ ---
1205
+
1206
+ ### `bw.makeInput(props = {})`
1207
+
1208
+ Create an input element with form control styling Additional event handlers (oninput, onchange, etc.) can be passed as extra properties and are spread onto the element attributes.
1209
+
1210
+ **Parameters:**
1211
+
1212
+ | Name | Type | Description |
1213
+ |------|------|-------------|
1214
+ | `props` | `Object` | - Input configuration |
1215
+ | `props.type` | `string` | - Input type ("text", "email", "password", "number", etc.) |
1216
+ | `props.placeholder` | `string` | - Placeholder text |
1217
+ | `props.value` | `string` | - Input value |
1218
+ | `props.id` | `string` | - Element ID |
1219
+ | `props.name` | `string` | - Input name attribute |
1220
+ | `props.disabled` | `boolean` | - Whether the input is disabled |
1221
+ | `props.readonly` | `boolean` | - Whether the input is read-only |
1222
+ | `props.required` | `boolean` | - Whether the input is required |
1223
+ | `props.className` | `string` | - Additional CSS classes |
1224
+ | `props.style` | `Object` | - Inline style object |
1225
+
1226
+ **Returns:** `Object` — object representing an input element
1227
+
1228
+ **Example:**
1229
+ ```javascript
1230
+ const input = makeInput({ type: "email", placeholder: "you@example.com", required: true, oninput: (e) => validate(e.target.value) });
1231
+ ```
1232
+
1233
+ ---
1234
+
1235
+ ### `bw.makeTextarea(props = {})`
1236
+
1237
+ Create a textarea element with form control styling
1238
+
1239
+ **Parameters:**
1240
+
1241
+ | Name | Type | Description |
1242
+ |------|------|-------------|
1243
+ | `props` | `Object` | - Textarea configuration |
1244
+ | `props.placeholder` | `string` | - Placeholder text |
1245
+ | `props.value` | `string` | - Textarea content |
1246
+ | `props.rows` | `number` | - Number of visible text rows |
1247
+ | `props.id` | `string` | - Element ID |
1248
+ | `props.name` | `string` | - Textarea name attribute |
1249
+ | `props.disabled` | `boolean` | - Whether the textarea is disabled |
1250
+ | `props.readonly` | `boolean` | - Whether the textarea is read-only |
1251
+ | `props.required` | `boolean` | - Whether the textarea is required |
1252
+ | `props.className` | `string` | - Additional CSS classes |
1253
+
1254
+ **Returns:** `Object` — object representing a textarea element
1255
+
1256
+ **Example:**
1257
+ ```javascript
1258
+ const textarea = makeTextarea({ rows: 5, placeholder: "Enter your message...", required: true });
1259
+ ```
1260
+
1261
+ ---
1262
+
1263
+ ### `bw.makeSelect(props = {})`
1264
+
1265
+ Create a select dropdown with options
1266
+
1267
+ **Parameters:**
1268
+
1269
+ | Name | Type | Description |
1270
+ |------|------|-------------|
1271
+ | `props` | `Object` | - Select configuration |
1272
+ | `props.options` | `Array<Object>` | - Dropdown options |
1273
+ | `props.options[].value` | `string` | - Option value |
1274
+ | `props.options[].text` | `string` | - Option display text (defaults to value) |
1275
+ | `props.value` | `string` | - Currently selected value |
1276
+ | `props.id` | `string` | - Element ID |
1277
+ | `props.name` | `string` | - Select name attribute |
1278
+ | `props.disabled` | `boolean` | - Whether the select is disabled |
1279
+ | `props.required` | `boolean` | - Whether the select is required |
1280
+ | `props.className` | `string` | - Additional CSS classes |
1281
+
1282
+ **Returns:** `Object` — object representing a select element
1283
+
1284
+ **Example:**
1285
+ ```javascript
1286
+ const select = makeSelect({ value: "b", options: [ { value: "a", text: "Option A" }, { value: "b", text: "Option B" }, { value: "c", text: "Option C" } ] });
1287
+ ```
1288
+
1289
+ ---
1290
+
1291
+ ### `bw.makeCheckbox(props = {})`
1292
+
1293
+ Create a checkbox input with label
1294
+
1295
+ **Parameters:**
1296
+
1297
+ | Name | Type | Description |
1298
+ |------|------|-------------|
1299
+ | `props` | `Object` | - Checkbox configuration |
1300
+ | `props.label` | `string` | - Checkbox label text |
1301
+ | `props.checked` | `boolean` | - Whether the checkbox is checked |
1302
+ | `props.id` | `string` | - Element ID (links label to checkbox) |
1303
+ | `props.name` | `string` | - Input name attribute |
1304
+ | `props.disabled` | `boolean` | - Whether the checkbox is disabled |
1305
+ | `props.value` | `string` | - Checkbox value attribute |
1306
+
1307
+ **Returns:** `Object` — object representing a checkbox form group
1308
+
1309
+ **Example:**
1310
+ ```javascript
1311
+ const checkbox = makeCheckbox({ label: "I agree to the terms", id: "agree", checked: false });
1312
+ ```
1313
+
1314
+ ---
1315
+
1316
+ ### `bw.makeStack(props = {})`
1317
+
1318
+ Create a flexbox stack layout (vertical or horizontal)
1319
+
1320
+ **Parameters:**
1321
+
1322
+ | Name | Type | Description |
1323
+ |------|------|-------------|
1324
+ | `props` | `Object` | - Stack configuration |
1325
+ | `props.children` | `Array|Object|string` | - Stack children |
1326
+ | `props.direction` | `string` | - Stack direction ("vertical" or "horizontal") |
1327
+ | `props.gap` | `number` | - Gap size (0-5) |
1328
+ | `props.className` | `string` | - Additional CSS classes |
1329
+
1330
+ **Returns:** `Object` — object representing a stack layout
1331
+
1332
+ **Example:**
1333
+ ```javascript
1334
+ const stack = makeStack({ direction: "horizontal", gap: 2, children: [ makeButton({ text: "Cancel", variant: "secondary" }), makeButton({ text: "Save", variant: "primary" }) ] });
1335
+ ```
1336
+
1337
+ ---
1338
+
1339
+ ### `bw.makeSpinner(props = {})`
1340
+
1341
+ Create a loading spinner indicator
1342
+
1343
+ **Parameters:**
1344
+
1345
+ | Name | Type | Description |
1346
+ |------|------|-------------|
1347
+ | `props` | `Object` | - Spinner configuration |
1348
+ | `props.variant` | `string` | - Color variant |
1349
+ | `props.size` | `string` | - Spinner size ("sm", "md", "lg") |
1350
+ | `props.type` | `string` | - Spinner type ("border" or "grow") |
1351
+
1352
+ **Returns:** `Object` — object representing a spinner with screen-reader text
1353
+
1354
+ **Example:**
1355
+ ```javascript
1356
+ const spinner = makeSpinner({ variant: "info", size: "sm" });
1357
+ ```
1358
+
1359
+ ---
1360
+
1361
+ ### `bw.makeHero(props = {})`
1362
+
1363
+ Create a hero section for landing pages and headers Supports gradient backgrounds, background images with overlays, and action buttons. Commonly used as the first visible section.
1364
+
1365
+ **Parameters:**
1366
+
1367
+ | Name | Type | Description |
1368
+ |------|------|-------------|
1369
+ | `props` | `Object` | - Hero configuration |
1370
+ | `props.title` | `string` | - Main headline text |
1371
+ | `props.subtitle` | `string` | - Supporting description text |
1372
+ | `props.content` | `string|Object|Array` | - Additional body content |
1373
+ | `props.variant` | `string` | - Background variant ("primary", "secondary", "light", "dark") |
1374
+ | `props.size` | `string` | - Vertical padding size ("sm", "md", "lg", "xl") |
1375
+ | `props.centered` | `boolean` | - Center-align text |
1376
+ | `props.overlay` | `boolean` | - Add dark overlay (for background images) |
1377
+ | `props.backgroundImage` | `string` | - Background image URL |
1378
+ | `props.actions` | `Array|Object` | - Call-to-action buttons |
1379
+ | `props.className` | `string` | - Additional CSS classes |
1380
+
1381
+ **Returns:** `Object` — object representing a hero section
1382
+
1383
+ **Example:**
1384
+ ```javascript
1385
+ const hero = makeHero({ title: "Welcome to Bitwrench", subtitle: "Build UIs with pure JavaScript", variant: "dark", actions: [ makeButton({ text: "Get Started", variant: "primary", size: "lg" }), makeButton({ text: "Learn More", variant: "outline-light", size: "lg" }) ] });
1386
+ ```
1387
+
1388
+ ---
1389
+
1390
+ ### `bw.makeFeatureGrid(props = {})`
1391
+
1392
+ Create a responsive feature grid for showcasing capabilities Renders features in an equal-width column grid with optional icons, titles, and descriptions.
1393
+
1394
+ **Parameters:**
1395
+
1396
+ | Name | Type | Description |
1397
+ |------|------|-------------|
1398
+ | `props` | `Object` | - Feature grid configuration |
1399
+ | `props.features` | `Array<Object>` | - Feature items |
1400
+ | `props.features[].icon` | `string` | - Icon content (emoji, HTML entity, or text) |
1401
+ | `props.features[].title` | `string` | - Feature title |
1402
+ | `props.features[].description` | `string` | - Feature description text |
1403
+ | `props.columns` | `number` | - Number of columns (divides 12-col grid) |
1404
+ | `props.centered` | `boolean` | - Center-align feature text |
1405
+ | `props.iconSize` | `string` | - Icon font size |
1406
+ | `props.className` | `string` | - Additional CSS classes |
1407
+
1408
+ **Returns:** `Object` — object representing a feature grid
1409
+
1410
+ **Example:**
1411
+ ```javascript
1412
+ const features = makeFeatureGrid({ columns: 3, features: [ { icon: "⚡", title: "Fast", description: "Zero build step" }, { icon: "📦", title: "Small", description: "Under 45KB gzipped" }, { icon: "🔧", title: "Flexible", description: "Pure JS objects" } ] });
1413
+ ```
1414
+
1415
+ ---
1416
+
1417
+ ### `bw.makeCTA(props = {})`
1418
+
1419
+ Create a call-to-action section with title, description, and action buttons
1420
+
1421
+ **Parameters:**
1422
+
1423
+ | Name | Type | Description |
1424
+ |------|------|-------------|
1425
+ | `props` | `Object` | - CTA configuration |
1426
+ | `props.title` | `string` | - CTA headline |
1427
+ | `props.description` | `string` | - CTA description text |
1428
+ | `props.actions` | `Array|Object` | - CTA buttons or content |
1429
+ | `props.variant` | `string` | - Background variant |
1430
+ | `props.centered` | `boolean` | - Center-align content |
1431
+ | `props.className` | `string` | - Additional CSS classes |
1432
+
1433
+ **Returns:** `Object` — object representing a CTA section
1434
+
1435
+ **Example:**
1436
+ ```javascript
1437
+ const cta = makeCTA({ title: "Ready to get started?", description: "Join thousands of developers using Bitwrench.", actions: [ makeButton({ text: "Sign Up Free", variant: "primary", size: "lg" }) ] });
1438
+ ```
1439
+
1440
+ ---
1441
+
1442
+ ### `bw.makeSection(props = {})`
1443
+
1444
+ Create a page section with optional centered header and background
1445
+
1446
+ **Parameters:**
1447
+
1448
+ | Name | Type | Description |
1449
+ |------|------|-------------|
1450
+ | `props` | `Object` | - Section configuration |
1451
+ | `props.title` | `string` | - Section title |
1452
+ | `props.subtitle` | `string` | - Section subtitle (muted) |
1453
+ | `props.content` | `string|Object|Array` | - Section body content |
1454
+ | `props.variant` | `string` | - Background variant ("default" for none, or a color name) |
1455
+ | `props.spacing` | `string` | - Vertical padding ("sm", "md", "lg", "xl") |
1456
+ | `props.className` | `string` | - Additional CSS classes |
1457
+
1458
+ **Returns:** `Object` — object representing a content section
1459
+
1460
+ **Example:**
1461
+ ```javascript
1462
+ const section = makeSection({ title: "Features", subtitle: "Everything you need to build great UIs", spacing: "lg", content: makeFeatureGrid({ features: [...] }) });
1463
+ ```
1464
+
1465
+ ---
1466
+
1467
+ ### `bw.makeCodeDemo(props = {})`
1468
+
1469
+ Create a code demo component for documentation pages Displays a live result alongside source code in a tabbed interface. Includes a copy-to-clipboard button on the code tab.
1470
+
1471
+ **Parameters:**
1472
+
1473
+ | Name | Type | Description |
1474
+ |------|------|-------------|
1475
+ | `props` | `Object` | - Code demo configuration |
1476
+ | `props.title` | `string` | - Demo title heading |
1477
+ | `props.description` | `string` | - Demo description text |
1478
+ | `props.code` | `string` | - Source code to display (adds a "Code" tab when present) |
1479
+ | `props.result` | `string|Object|Array` | - Live result content for the "Result" tab |
1480
+ | `props.language` | `string` | - Code language for syntax class |
1481
+
1482
+ **Returns:** `Object` — object representing a code demo with tabbed Result/Code views
1483
+
1484
+ **Example:**
1485
+ ```javascript
1486
+ const demo = makeCodeDemo({ title: "Button Example", description: "A simple primary button", code: 'makeButton({ text: "Click me" })', result: makeButton({ text: "Click me" }) });
1487
+ ```
1488
+
1489
+ ---
1490
+
1491
+ ### `bw.makePagination(props = {})`
1492
+
1493
+ Create a pagination navigation component
1494
+
1495
+ **Parameters:**
1496
+
1497
+ | Name | Type | Description |
1498
+ |------|------|-------------|
1499
+ | `props` | `Object` | - Pagination configuration |
1500
+ | `props.pages` | `number` | - Total number of pages |
1501
+ | `props.currentPage` | `number` | - Currently active page (1-based) |
1502
+ | `props.onPageChange` | `Function` | - Callback when page changes, receives page number |
1503
+ | `props.size` | `string` | - Size variant ("sm" or "lg") |
1504
+ | `props.className` | `string` | - Additional CSS classes |
1505
+
1506
+ **Returns:** `Object` — object representing a pagination nav
1507
+
1508
+ **Example:**
1509
+ ```javascript
1510
+ const pager = makePagination({ pages: 10, currentPage: 3, onPageChange: (page) => loadPage(page) });
1511
+ ```
1512
+
1513
+ ---
1514
+
1515
+ ### `bw.makeRadio(props = {})`
1516
+
1517
+ Create a radio button input with label
1518
+
1519
+ **Parameters:**
1520
+
1521
+ | Name | Type | Description |
1522
+ |------|------|-------------|
1523
+ | `props` | `Object` | - Radio configuration |
1524
+ | `props.label` | `string` | - Radio label text |
1525
+ | `props.name` | `string` | - Radio group name |
1526
+ | `props.value` | `string` | - Radio value attribute |
1527
+ | `props.checked` | `boolean` | - Whether the radio is selected |
1528
+ | `props.id` | `string` | - Element ID (links label to radio) |
1529
+ | `props.disabled` | `boolean` | - Whether the radio is disabled |
1530
+ | `props.className` | `string` | - Additional CSS classes |
1531
+
1532
+ **Returns:** `Object` — object representing a radio form group
1533
+
1534
+ **Example:**
1535
+ ```javascript
1536
+ const radio = makeRadio({ label: "Option A", name: "choice", value: "a", checked: true });
1537
+ ```
1538
+
1539
+ ---
1540
+
1541
+ ### `bw.makeButtonGroup(props = {})`
1542
+
1543
+ Create a button group wrapper
1544
+
1545
+ **Parameters:**
1546
+
1547
+ | Name | Type | Description |
1548
+ |------|------|-------------|
1549
+ | `props` | `Object` | - Button group configuration |
1550
+ | `props.children` | `Array` | - Button TACO objects to group |
1551
+ | `props.size` | `string` | - Size variant ("sm" or "lg") |
1552
+ | `props.vertical` | `boolean` | - Stack buttons vertically |
1553
+ | `props.className` | `string` | - Additional CSS classes |
1554
+
1555
+ **Returns:** `Object` — object representing a button group
1556
+
1557
+ **Example:**
1558
+ ```javascript
1559
+ const group = makeButtonGroup({ children: [ makeButton({ text: "Left", variant: "primary" }), makeButton({ text: "Middle", variant: "primary" }), makeButton({ text: "Right", variant: "primary" }) ] });
1560
+ ```
1561
+
1562
+ ---
1563
+
1564
+ ### `bw.makeAccordion(props = {})`
1565
+
1566
+ Create an accordion component with collapsible items
1567
+
1568
+ **Parameters:**
1569
+
1570
+ | Name | Type | Description |
1571
+ |------|------|-------------|
1572
+ | `props` | `Object` | - Accordion configuration |
1573
+ | `props.items` | `Array<Object>` | - Accordion items |
1574
+ | `props.items[].title` | `string` | - Header text for the accordion item |
1575
+ | `props.items[].content` | `string|Object|Array` | - Collapsible content |
1576
+ | `props.items[].open` | `boolean` | - Whether the item is initially open |
1577
+ | `props.multiOpen` | `boolean` | - Allow multiple items open simultaneously |
1578
+ | `props.className` | `string` | - Additional CSS classes |
1579
+
1580
+ **Returns:** `Object` — object representing an accordion
1581
+
1582
+ **Example:**
1583
+ ```javascript
1584
+ const accordion = makeAccordion({ items: [ { title: "Section 1", content: "Content 1", open: true }, { title: "Section 2", content: "Content 2" } ] });
1585
+ ```
1586
+
1587
+ ---
1588
+
1589
+ ### `bw.makeModal(props = {})`
1590
+
1591
+ Create a modal dialog overlay
1592
+
1593
+ **Parameters:**
1594
+
1595
+ | Name | Type | Description |
1596
+ |------|------|-------------|
1597
+ | `props` | `Object` | - Modal configuration |
1598
+ | `props.title` | `string` | - Modal title in header |
1599
+ | `props.content` | `string|Object|Array` | - Modal body content |
1600
+ | `props.footer` | `string|Object|Array` | - Modal footer content |
1601
+ | `props.size` | `string` | - Modal size ("sm", "lg", "xl") |
1602
+ | `props.closeButton` | `boolean` | - Show X close button in header |
1603
+ | `props.onClose` | `Function` | - Callback when modal is closed |
1604
+ | `props.className` | `string` | - Additional CSS classes |
1605
+
1606
+ **Returns:** `Object` — object representing a modal
1607
+
1608
+ **Example:**
1609
+ ```javascript
1610
+ const modal = makeModal({ title: "Confirm", content: "Are you sure?", footer: makeButton({ text: "OK", variant: "primary" }) });
1611
+ ```
1612
+
1613
+ ---
1614
+
1615
+ ### `bw.makeToast(props = {})`
1616
+
1617
+ Create a toast notification popup
1618
+
1619
+ **Parameters:**
1620
+
1621
+ | Name | Type | Description |
1622
+ |------|------|-------------|
1623
+ | `props` | `Object` | - Toast configuration |
1624
+ | `props.title` | `string` | - Toast title |
1625
+ | `props.content` | `string|Object|Array` | - Toast body content |
1626
+ | `props.variant` | `string` | - Color variant ("primary", "success", "danger", "warning", "info") |
1627
+ | `props.autoDismiss` | `boolean` | - Auto-dismiss after delay |
1628
+ | `props.delay` | `number` | - Auto-dismiss delay in ms |
1629
+ | `props.position` | `string` | - Container position |
1630
+ | `props.className` | `string` | - Additional CSS classes |
1631
+
1632
+ **Returns:** `Object` — object representing a toast
1633
+
1634
+ **Example:**
1635
+ ```javascript
1636
+ const toast = makeToast({ title: "Success", content: "File saved!", variant: "success" });
1637
+ ```
1638
+
1639
+ ---
1640
+
1641
+ ### `bw.makeDropdown(props = {})`
1642
+
1643
+ Create a dropdown menu triggered by a button
1644
+
1645
+ **Parameters:**
1646
+
1647
+ | Name | Type | Description |
1648
+ |------|------|-------------|
1649
+ | `props` | `Object` | - Dropdown configuration |
1650
+ | `props.trigger` | `string|Object` | - Button text or TACO for the trigger |
1651
+ | `props.items` | `Array<Object>` | - Menu items |
1652
+ | `props.items[].text` | `string` | - Item display text |
1653
+ | `props.items[].href` | `string` | - Item link URL |
1654
+ | `props.items[].onclick` | `Function` | - Item click handler |
1655
+ | `props.items[].divider` | `boolean` | - Render as a divider line |
1656
+ | `props.items[].disabled` | `boolean` | - Whether the item is disabled |
1657
+ | `props.align` | `string` | - Menu alignment ("start" or "end") |
1658
+ | `props.variant` | `string` | - Trigger button variant |
1659
+ | `props.className` | `string` | - Additional CSS classes |
1660
+
1661
+ **Returns:** `Object` — object representing a dropdown
1662
+
1663
+ **Example:**
1664
+ ```javascript
1665
+ const dropdown = makeDropdown({ trigger: "Actions", items: [ { text: "Edit", onclick: () => edit() }, { divider: true }, { text: "Delete", onclick: () => del() } ] });
1666
+ ```
1667
+
1668
+ ---
1669
+
1670
+ ### `bw.makeSwitch(props = {})`
1671
+
1672
+ Create a toggle switch (styled checkbox)
1673
+
1674
+ **Parameters:**
1675
+
1676
+ | Name | Type | Description |
1677
+ |------|------|-------------|
1678
+ | `props` | `Object` | - Switch configuration |
1679
+ | `props.label` | `string` | - Switch label text |
1680
+ | `props.checked` | `boolean` | - Whether the switch is on |
1681
+ | `props.id` | `string` | - Element ID (links label to switch) |
1682
+ | `props.name` | `string` | - Input name attribute |
1683
+ | `props.disabled` | `boolean` | - Whether the switch is disabled |
1684
+ | `props.className` | `string` | - Additional CSS classes |
1685
+
1686
+ **Returns:** `Object` — object representing a toggle switch
1687
+
1688
+ **Example:**
1689
+ ```javascript
1690
+ const toggle = makeSwitch({ label: "Dark mode", checked: false, onchange: (e) => toggleDark(e.target.checked) });
1691
+ ```
1692
+
1693
+ ---
1694
+
1695
+ ### `bw.makeSkeleton(props = {})`
1696
+
1697
+ Create a skeleton loading placeholder
1698
+
1699
+ **Parameters:**
1700
+
1701
+ | Name | Type | Description |
1702
+ |------|------|-------------|
1703
+ | `props` | `Object` | - Skeleton configuration |
1704
+ | `props.variant` | `string` | - Shape variant ("text", "circle", "rect") |
1705
+ | `props.width` | `string` | - Custom width (e.g. "200px", "100%") |
1706
+ | `props.height` | `string` | - Custom height (e.g. "20px") |
1707
+ | `props.count` | `number` | - Number of skeleton lines (for text variant) |
1708
+ | `props.className` | `string` | - Additional CSS classes |
1709
+
1710
+ **Returns:** `Object` — object representing a skeleton placeholder
1711
+
1712
+ **Example:**
1713
+ ```javascript
1714
+ const skeleton = makeSkeleton({ variant: "text", count: 3, width: "100%" });
1715
+ ```
1716
+
1717
+ ---
1718
+
1719
+ ### `bw.makeAvatar(props = {})`
1720
+
1721
+ Create a user avatar with image or initials fallback
1722
+
1723
+ **Parameters:**
1724
+
1725
+ | Name | Type | Description |
1726
+ |------|------|-------------|
1727
+ | `props` | `Object` | - Avatar configuration |
1728
+ | `props.src` | `string` | - Image source URL |
1729
+ | `props.alt` | `string` | - Image alt text |
1730
+ | `props.initials` | `string` | - Fallback initials (e.g. "JD") |
1731
+ | `props.size` | `string` | - Size ("sm", "md", "lg", "xl") |
1732
+ | `props.variant` | `string` | - Background color variant for initials |
1733
+ | `props.className` | `string` | - Additional CSS classes |
1734
+
1735
+ **Returns:** `Object` — object representing an avatar
1736
+
1737
+ **Example:**
1738
+ ```javascript
1739
+ const avatar = makeAvatar({ src: "/photo.jpg", alt: "Jane Doe", size: "lg" }); const avatarInitials = makeAvatar({ initials: "JD", variant: "success" });
1740
+ ```
1741
+
1742
+ ---
1743
+
1744
+ ### `bw.makeCarousel(props = {})`
1745
+
1746
+ Create a carousel/slideshow component with slide transitions Supports image slides, TACO content slides, captions, prev/next controls, dot indicators, and optional auto-play. Uses CSS translateX transitions.
1747
+
1748
+ **Parameters:**
1749
+
1750
+ | Name | Type | Description |
1751
+ |------|------|-------------|
1752
+ | `props` | `Object` | - Carousel configuration |
1753
+ | `props.items` | `Array<Object>` | - Slide items |
1754
+ | `props.items[].content` | `string|Object` | - Slide content (TACO, string, or img element) |
1755
+ | `props.items[].caption` | `string` | - Caption text shown at bottom of slide |
1756
+ | `props.showControls` | `boolean` | - Show prev/next arrow buttons |
1757
+ | `props.showIndicators` | `boolean` | - Show dot navigation |
1758
+ | `props.autoPlay` | `boolean` | - Auto-advance slides |
1759
+ | `props.interval` | `number` | - Auto-advance interval in ms |
1760
+ | `props.height` | `string` | - Carousel height |
1761
+ | `props.startIndex` | `number` | - Initial slide index |
1762
+ | `props.className` | `string` | - Additional CSS classes |
1763
+
1764
+ **Returns:** `Object` — object representing a carousel
1765
+
1766
+ **Example:**
1767
+ ```javascript
1768
+ const carousel = makeCarousel({ items: [ { content: { t: 'img', a: { src: 'photo.jpg' } }, caption: 'Photo 1' }, { content: { t: 'div', c: 'Text slide' } } ], autoPlay: true, interval: 3000 });
1769
+ ```
1770
+
1771
+ ---
1772
+
1773
+ ### `bw.makeStatCard(props = {})`
1774
+
1775
+ Create a stat card for dashboard metrics display Shows a large value with a label and optional change indicator. Designed for dashboard grid layouts with left-border accent.
1776
+
1777
+ **Parameters:**
1778
+
1779
+ | Name | Type | Description |
1780
+ |------|------|-------------|
1781
+ | `props` | `Object|string` | - Stat card configuration (string shorthand sets label) |
1782
+ | `props.value` | `string|number` | - The main stat value to display |
1783
+ | `props.label` | `string` | - Descriptive label below the value |
1784
+ | `props.change` | `number` | - Percentage change indicator (positive = green arrow, negative = red) |
1785
+ | `props.format` | `string` | - Value format ("number", "currency", "percent") |
1786
+ | `props.prefix` | `string` | - Custom prefix (e.g. "$") |
1787
+ | `props.suffix` | `string` | - Custom suffix (e.g. "%") |
1788
+ | `props.icon` | `string` | - Icon content (emoji or text) shown above value |
1789
+ | `props.variant` | `string` | - Left-border color variant ("primary", "success", "danger", etc.) |
1790
+ | `props.className` | `string` | - Additional CSS classes |
1791
+ | `props.style` | `Object` | - Inline style object |
1792
+
1793
+ **Returns:** `Object` — object representing a stat card
1794
+
1795
+ **Example:**
1796
+ ```javascript
1797
+ const stat = makeStatCard({ value: 2345, label: 'Active Users', change: 5.3, format: 'number', variant: 'primary' });
1798
+ ```
1799
+
1800
+ ---
1801
+
1802
+ ### `bw.makeTooltip(props = {})`
1803
+
1804
+ Create a tooltip wrapper around trigger content Wraps the trigger element in a container that shows tooltip text on hover and focus. Pure CSS-driven show/hide with JS lifecycle for event binding.
1805
+
1806
+ **Parameters:**
1807
+
1808
+ | Name | Type | Description |
1809
+ |------|------|-------------|
1810
+ | `props` | `Object` | - Tooltip configuration |
1811
+ | `props.content` | `string|Object|Array` | - Trigger content (what the user hovers/focuses) |
1812
+ | `props.text` | `string` | - Tooltip text to display |
1813
+ | `props.placement` | `string` | - Tooltip placement ("top", "bottom", "left", "right") |
1814
+ | `props.className` | `string` | - Additional CSS classes |
1815
+
1816
+ **Returns:** `Object` — object representing a tooltip wrapper
1817
+
1818
+ **Example:**
1819
+ ```javascript
1820
+ const tip = makeTooltip({ content: makeButton({ text: 'Hover me' }), text: 'This is a tooltip!', placement: 'top' });
1821
+ ```
1822
+
1823
+ ---
1824
+
1825
+ ### `bw.makePopover(props = {})`
1826
+
1827
+ Create a popover wrapper around trigger content Like a tooltip but richer — supports title + body content and is triggered by click rather than hover. Dismisses on click outside.
1828
+
1829
+ **Parameters:**
1830
+
1831
+ | Name | Type | Description |
1832
+ |------|------|-------------|
1833
+ | `props` | `Object` | - Popover configuration |
1834
+ | `props.trigger` | `string|Object|Array` | - Trigger content (what the user clicks) |
1835
+ | `props.title` | `string` | - Popover header title |
1836
+ | `props.content` | `string|Object|Array` | - Popover body content |
1837
+ | `props.placement` | `string` | - Placement ("top", "bottom", "left", "right") |
1838
+ | `props.className` | `string` | - Additional CSS classes |
1839
+
1840
+ **Returns:** `Object` — object representing a popover wrapper
1841
+
1842
+ **Example:**
1843
+ ```javascript
1844
+ const pop = makePopover({ trigger: makeButton({ text: 'Click me' }), title: 'Popover Title', content: 'Some helpful information here.', placement: 'bottom' });
1845
+ ```
1846
+
1847
+ ---
1848
+
1849
+ ### `bw.makeSearchInput(props = {})`
1850
+
1851
+ Create a search input with clear button Wraps a text input with a clear (×) button that appears when the field has content. Calls onSearch on Enter key.
1852
+
1853
+ **Parameters:**
1854
+
1855
+ | Name | Type | Description |
1856
+ |------|------|-------------|
1857
+ | `props` | `Object` | - Search input configuration |
1858
+ | `props.placeholder` | `string` | - Placeholder text |
1859
+ | `props.value` | `string` | - Initial value |
1860
+ | `props.onSearch` | `Function` | - Callback when Enter is pressed, receives value |
1861
+ | `props.onInput` | `Function` | - Callback on each keystroke, receives value |
1862
+ | `props.id` | `string` | - Element ID |
1863
+ | `props.name` | `string` | - Input name attribute |
1864
+ | `props.className` | `string` | - Additional CSS classes |
1865
+
1866
+ **Returns:** `Object` — object representing a search input
1867
+
1868
+ **Example:**
1869
+ ```javascript
1870
+ const search = makeSearchInput({ placeholder: 'Search users...', onSearch: (val) => filterUsers(val) });
1871
+ ```
1872
+
1873
+ ---
1874
+
1875
+ ### `bw.makeRange(props = {})`
1876
+
1877
+ Create a styled range slider input
1878
+
1879
+ **Parameters:**
1880
+
1881
+ | Name | Type | Description |
1882
+ |------|------|-------------|
1883
+ | `props` | `Object` | - Range configuration |
1884
+ | `props.min` | `number` | - Minimum value |
1885
+ | `props.max` | `number` | - Maximum value |
1886
+ | `props.step` | `number` | - Step increment |
1887
+ | `props.value` | `number` | - Current value |
1888
+ | `props.label` | `string` | - Label text |
1889
+ | `props.showValue` | `boolean` | - Show current value display |
1890
+ | `props.id` | `string` | - Element ID |
1891
+ | `props.name` | `string` | - Input name attribute |
1892
+ | `props.disabled` | `boolean` | - Whether the slider is disabled |
1893
+ | `props.className` | `string` | - Additional CSS classes |
1894
+
1895
+ **Returns:** `Object` — object representing a range input
1896
+
1897
+ **Example:**
1898
+ ```javascript
1899
+ const slider = makeRange({ min: 0, max: 100, value: 50, label: 'Volume', showValue: true, oninput: (e) => setVolume(e.target.value) });
1900
+ ```
1901
+
1902
+ ---
1903
+
1904
+ ### `bw.makeMediaObject(props = {})`
1905
+
1906
+ Create a media object layout (image + text side-by-side) Classic media object pattern: image/icon on one side, text content on the other, using flexbox. Supports reversed layout.
1907
+
1908
+ **Parameters:**
1909
+
1910
+ | Name | Type | Description |
1911
+ |------|------|-------------|
1912
+ | `props` | `Object` | - Media object configuration |
1913
+ | `props.src` | `string` | - Image source URL |
1914
+ | `props.alt` | `string` | - Image alt text |
1915
+ | `props.title` | `string` | - Title text |
1916
+ | `props.content` | `string|Object|Array` | - Body content |
1917
+ | `props.reverse` | `boolean` | - Put image on the right |
1918
+ | `props.imageSize` | `string` | - Image width/height |
1919
+ | `props.className` | `string` | - Additional CSS classes |
1920
+
1921
+ **Returns:** `Object` — object representing a media object
1922
+
1923
+ **Example:**
1924
+ ```javascript
1925
+ const media = makeMediaObject({ src: '/avatar.jpg', title: 'Jane Doe', content: 'Posted a comment 5 minutes ago.' });
1926
+ ```
1927
+
1928
+ ---
1929
+
1930
+ ### `bw.makeFileUpload(props = {})`
1931
+
1932
+ Create a file upload zone with drag-and-drop support Styled drop zone with file input. Supports drag-and-drop visuals and multiple file selection.
1933
+
1934
+ **Parameters:**
1935
+
1936
+ | Name | Type | Description |
1937
+ |------|------|-------------|
1938
+ | `props` | `Object` | - File upload configuration |
1939
+ | `props.accept` | `string` | - Accepted file types (e.g. "image/*", ".pdf,.doc") |
1940
+ | `props.multiple` | `boolean` | - Allow multiple file selection |
1941
+ | `props.onFiles` | `Function` | - Callback when files are selected, receives FileList |
1942
+ | `props.text` | `string` | - Zone label text |
1943
+ | `props.id` | `string` | - Element ID |
1944
+ | `props.className` | `string` | - Additional CSS classes |
1945
+
1946
+ **Returns:** `Object` — object representing a file upload zone
1947
+
1948
+ **Example:**
1949
+ ```javascript
1950
+ const upload = makeFileUpload({ accept: 'image/*', multiple: true, onFiles: (files) => uploadFiles(files) });
1951
+ ```
1952
+
1953
+ ---
1954
+
1955
+ ### `bw.makeTimeline(props = {})`
1956
+
1957
+ Create a vertical timeline for chronological event display Renders events as a vertical line with markers and content cards. Each item can have a colored variant marker.
1958
+
1959
+ **Parameters:**
1960
+
1961
+ | Name | Type | Description |
1962
+ |------|------|-------------|
1963
+ | `props` | `Object` | - Timeline configuration |
1964
+ | `props.items` | `Array<Object>` | - Timeline events |
1965
+ | `props.items[].title` | `string` | - Event title |
1966
+ | `props.items[].content` | `string|Object|Array` | - Event description content |
1967
+ | `props.items[].date` | `string` | - Date or time label |
1968
+ | `props.items[].variant` | `string` | - Marker color variant |
1969
+ | `props.className` | `string` | - Additional CSS classes |
1970
+
1971
+ **Returns:** `Object` — object representing a timeline
1972
+
1973
+ **Example:**
1974
+ ```javascript
1975
+ const timeline = makeTimeline({ items: [ { title: 'Project Started', date: 'Jan 2026', variant: 'primary' }, { title: 'Beta Release', date: 'Mar 2026', content: 'v2.0 beta shipped' }, { title: 'Stable Release', date: 'Jun 2026', variant: 'success' } ] });
1976
+ ```
1977
+
1978
+ ---
1979
+
1980
+ ### `bw.makeStepper(props = {})`
1981
+
1982
+ Create a multi-step wizard/progress indicator Displays numbered steps with active and completed states. Steps before currentStep are marked completed, the currentStep is active, and subsequent steps are pending.
1983
+
1984
+ **Parameters:**
1985
+
1986
+ | Name | Type | Description |
1987
+ |------|------|-------------|
1988
+ | `props` | `Object` | - Stepper configuration |
1989
+ | `props.steps` | `Array<Object>` | - Step definitions |
1990
+ | `props.steps[].label` | `string` | - Step label text |
1991
+ | `props.steps[].description` | `string` | - Optional step description |
1992
+ | `props.currentStep` | `number` | - Zero-based index of the active step |
1993
+ | `props.className` | `string` | - Additional CSS classes |
1994
+
1995
+ **Returns:** `Object` — object representing a stepper
1996
+
1997
+ **Example:**
1998
+ ```javascript
1999
+ const stepper = makeStepper({ currentStep: 1, steps: [ { label: 'Account', description: 'Create account' }, { label: 'Profile', description: 'Set up profile' }, { label: 'Confirm', description: 'Review & submit' } ] });
2000
+ ```
2001
+
2002
+ ---
2003
+
2004
+ ### `bw.makeChipInput(props = {})`
2005
+
2006
+ Create a chip/tag input for managing a list of items Displays existing chips with remove buttons and an input field for adding new ones. Chips are added on Enter and removed on clicking the × button.
2007
+
2008
+ **Parameters:**
2009
+
2010
+ | Name | Type | Description |
2011
+ |------|------|-------------|
2012
+ | `props` | `Object` | - Chip input configuration |
2013
+ | `props.chips` | `Array<string>` | - Initial chip values |
2014
+ | `props.placeholder` | `string` | - Input placeholder text |
2015
+ | `props.onAdd` | `Function` | - Callback when a chip is added, receives value |
2016
+ | `props.onRemove` | `Function` | - Callback when a chip is removed, receives value |
2017
+ | `props.className` | `string` | - Additional CSS classes |
2018
+
2019
+ **Returns:** `Object` — object representing a chip input
2020
+
2021
+ **Example:**
2022
+ ```javascript
2023
+ const tags = makeChipInput({ chips: ['JavaScript', 'CSS'], placeholder: 'Add tag...', onAdd: (val) => addTag(val), onRemove: (val) => removeTag(val) });
2024
+ ```
2025
+
2026
+ ---
2027
+
2028
+ ## Browser Utilities
2029
+
2030
+ ### `bw.setCookie(cname, cvalue, exdays, options = {})`
2031
+
2032
+ Set a browser cookie with expiration and options.
2033
+
2034
+ **Parameters:**
2035
+
2036
+ | Name | Type | Description |
2037
+ |------|------|-------------|
2038
+ | `cname` | `string` | - Cookie name |
2039
+ | `cvalue` | `string` | - Cookie value |
2040
+ | `exdays` | `number` | - Expiration in days from now |
2041
+ | `options` | `Object` | - Additional cookie options |
2042
+ | `options.path` | `string` | - Cookie path |
2043
+ | `options.domain` | `string` | - Cookie domain |
2044
+ | `options.secure` | `boolean` | - Secure flag |
2045
+ | `options.sameSite` | `string` | - SameSite attribute |
2046
+
2047
+ ---
2048
+
2049
+ ### `bw.getCookie(cname, defaultValue)`
2050
+
2051
+ Get a browser cookie value by name.
2052
+
2053
+ **Parameters:**
2054
+
2055
+ | Name | Type | Description |
2056
+ |------|------|-------------|
2057
+ | `cname` | `string` | - Cookie name |
2058
+ | `defaultValue` | `*` | - Default value if cookie not found |
2059
+
2060
+ **Returns:** `*` — value or default
2061
+
2062
+ ---
2063
+
2064
+ ### `bw.getURLParam(key, defaultValue)`
2065
+
2066
+ Get a URL query parameter value from the current page URL. Pass no key to get all parameters as an object. Returns `true` for present-but-empty parameters.
2067
+
2068
+ **Parameters:**
2069
+
2070
+ | Name | Type | Description |
2071
+ |------|------|-------------|
2072
+ | `key` | `string` | - Parameter name (omit to get all params) |
2073
+ | `defaultValue` | `*` | - Default if not found |
2074
+
2075
+ **Returns:** `*` — value, true (present but empty), or default
2076
+
2077
+ ---
2078
+
2079
+ ### `bw.copyToClipboard(text)`
2080
+
2081
+ Copy text to the system clipboard (browser only). Uses the modern Clipboard API when available, falls back to `document.execCommand('copy')`.
2082
+
2083
+ **Parameters:**
2084
+
2085
+ | Name | Type | Description |
2086
+ |------|------|-------------|
2087
+ | `text` | `string` | - Text to copy |
2088
+
2089
+ **Returns:** `Promise` — that resolves when copy is complete
2090
+
2091
+ ---
2092
+
2093
+ ## Utilities
2094
+
2095
+ ### `bw.h(tag, attrs, content, options)`
2096
+
2097
+ Hyperscript-style TACO constructor. A convenience helper that returns a canonical TACO object from positional arguments. The return value is a plain object — serializable, works with bwserve, and accepted everywhere TACO is accepted.
2098
+
2099
+ **Parameters:**
2100
+
2101
+ | Name | Type | Description |
2102
+ |------|------|-------------|
2103
+ | `tag` | `string` | - HTML tag name (e.g. 'div', 'p', 'section') |
2104
+ | `attrs` | `Object|null` | - HTML attributes object. Pass null or omit to skip. |
2105
+ | `content` | `*` | - Content: string, number, TACO object, or array of children. |
2106
+ | `options` | `Object` | - TACO options (state, lifecycle hooks, render fn). |
2107
+
2108
+ **Returns:** `Object` — TACO object {t, a?, c?, o?}
2109
+
2110
+ **Example:**
2111
+ ```javascript
2112
+ bw.h('div') // => { t: 'div' } bw.h('p', { class: 'bw_text_muted' }, 'Hello') // => { t: 'p', a: { class: 'bw_text_muted' }, c: 'Hello' } bw.h('ul', null, [ bw.h('li', null, 'one'), bw.h('li', null, 'two') ]) // => { t: 'ul', c: [{ t: 'li', c: 'one' }, { t: 'li', c: 'two' }] }
2113
+ ```
2114
+
2115
+ ---
2116
+
2117
+ ## Function Registry
2118
+
2119
+ ### `bw.funcRegister(fn, name)`
2120
+
2121
+ Register a function in the global function registry. Registered functions can be invoked by name in HTML string contexts (e.g., onclick attributes) via `bw.funcGetById()`. Useful for serializable event handlers, LLM wire format, and SSR.
2122
+
2123
+ **Parameters:**
2124
+
2125
+ | Name | Type | Description |
2126
+ |------|------|-------------|
2127
+ | `fn` | `Function` | - Function to register |
2128
+ | `name` | `string` | - Optional name. Auto-generated if omitted. |
2129
+
2130
+ **Returns:** `string` — registered name (use for dispatch)
2131
+
2132
+ ---
2133
+
2134
+ ### `bw.funcGetById(name, errFn)`
2135
+
2136
+ Retrieve a registered function by name. Returns the function if found, or `errFn` (or a no-op logger) if not.
2137
+
2138
+ **Parameters:**
2139
+
2140
+ | Name | Type | Description |
2141
+ |------|------|-------------|
2142
+ | `name` | `string` | - Registered function name |
2143
+ | `errFn` | `Function` | - Fallback if not found |
2144
+
2145
+ **Returns:** `Function` — registered function or fallback
2146
+
2147
+ ---
2148
+
2149
+ ### `bw.funcGetDispatchStr(name, argStr)`
2150
+
2151
+ Generate a dispatch string suitable for inline HTML event attributes.
2152
+
2153
+ **Parameters:**
2154
+
2155
+ | Name | Type | Description |
2156
+ |------|------|-------------|
2157
+ | `name` | `string` | - Registered function name |
2158
+ | `argStr` | `string` | - Arguments string (literal, not variable names) |
2159
+
2160
+ **Returns:** `string` — string like `"bw.funcGetById('name')(args)"`
2161
+
2162
+ ---
2163
+
2164
+ ### `bw.funcUnregister(name)`
2165
+
2166
+ Remove a function from the registry.
2167
+
2168
+ **Parameters:**
2169
+
2170
+ | Name | Type | Description |
2171
+ |------|------|-------------|
2172
+ | `name` | `string` | - Registered function name |
2173
+
2174
+ **Returns:** `boolean` — if removed, false if not found
2175
+
2176
+ ---
2177
+
2178
+ ### `bw.funcGetRegistry()`
2179
+
2180
+ Get a shallow copy of the function registry for inspection.
2181
+
2182
+ **Returns:** `Object` — of registry (name → function)
2183
+
2184
+ ---
2185
+
2186
+ ## Component
2187
+
2188
+ ### `bw.flush()`
2189
+
2190
+ No-op flush (ComponentHandle removed in v2.0.19). Kept as no-op for backward compatibility.
2191
+
2192
+ ---
2193
+
2194
+ ### `bw.message(target, action, data)`
2195
+
2196
+ Dispatch a message to a component by UUID, CSS class, or selector. Finds the element, looks up el.bw, and calls the named method. This is the bitwrench equivalent of Win32 SendMessage(hwnd, msg, wParam, lParam).
2197
+
2198
+ **Parameters:**
2199
+
2200
+ | Name | Type | Description |
2201
+ |------|------|-------------|
2202
+ | `target` | `string` | - Component UUID (bw_uuid_*), CSS class, or selector |
2203
+ | `action` | `string` | - Method name to call on el.bw |
2204
+ | `data` | `*` | - Data to pass to the method |
2205
+
2206
+ **Returns:** `boolean` — if message was dispatched successfully
2207
+
2208
+ **Example:**
2209
+ ```javascript
2210
+ bw.message('my_carousel', 'goToSlide', 2); // Or from SSE handler: es.onmessage = function(e) { var msg = JSON.parse(e.data); bw.message(msg.target, msg.action, msg.data); };
2211
+ ```
2212
+
2213
+ ---
2214
+
2215
+ ### `bw.inspect(target)`
2216
+
2217
+ Inspect a DOM element's bitwrench state, handle methods, and metadata. Works with DOM elements or CSS selectors.
2218
+
2219
+ **Parameters:**
2220
+
2221
+ | Name | Type | Description |
2222
+ |------|------|-------------|
2223
+ | `target` | `string|Element` | - Selector or DOM element |
2224
+
2225
+ **Returns:** `Element|null` — element, or null if not found
2226
+
2227
+ **Example:**
2228
+ ```javascript
2229
+ bw.inspect('#my-carousel'); bw.inspect($0);
2230
+ ```
2231
+
2232
+ ---