bitwrench 2.0.32 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +211 -125
  2. package/dist/bitwrench-bccl.cjs.js +349 -188
  3. package/dist/bitwrench-bccl.cjs.min.js +2 -39
  4. package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
  5. package/dist/bitwrench-bccl.esm.js +349 -188
  6. package/dist/bitwrench-bccl.esm.min.js +2 -39
  7. package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
  8. package/dist/bitwrench-bccl.umd.js +349 -188
  9. package/dist/bitwrench-bccl.umd.min.js +2 -39
  10. package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
  11. package/dist/bitwrench-code-edit.cjs.js +17 -6
  12. package/dist/bitwrench-code-edit.cjs.min.js +2 -20
  13. package/dist/bitwrench-code-edit.es5.js +8 -3
  14. package/dist/bitwrench-code-edit.es5.min.js +2 -19
  15. package/dist/bitwrench-code-edit.esm.js +17 -6
  16. package/dist/bitwrench-code-edit.esm.min.js +2 -19
  17. package/dist/bitwrench-code-edit.umd.js +17 -6
  18. package/dist/bitwrench-code-edit.umd.min.js +2 -19
  19. package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
  20. package/dist/bitwrench-debug.js +1 -1
  21. package/dist/bitwrench-debug.min.js +1 -1
  22. package/dist/bitwrench-lean.cjs.js +2492 -1628
  23. package/dist/bitwrench-lean.cjs.min.js +2 -80
  24. package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
  25. package/dist/bitwrench-lean.es5.js +2740 -1838
  26. package/dist/bitwrench-lean.es5.min.js +2 -49
  27. package/dist/bitwrench-lean.es5.min.js.gz +0 -0
  28. package/dist/bitwrench-lean.esm.js +2492 -1628
  29. package/dist/bitwrench-lean.esm.min.js +2 -80
  30. package/dist/bitwrench-lean.esm.min.js.gz +0 -0
  31. package/dist/bitwrench-lean.umd.js +2492 -1628
  32. package/dist/bitwrench-lean.umd.min.js +2 -80
  33. package/dist/bitwrench-lean.umd.min.js.gz +0 -0
  34. package/dist/bitwrench-util-color.cjs.js +251 -0
  35. package/dist/bitwrench-util-color.cjs.min.js +3 -0
  36. package/dist/bitwrench-util-color.es5.js +256 -0
  37. package/dist/bitwrench-util-color.es5.min.js +3 -0
  38. package/dist/bitwrench-util-color.esm.js +241 -0
  39. package/dist/bitwrench-util-color.esm.min.js +3 -0
  40. package/dist/bitwrench-util-color.umd.js +257 -0
  41. package/dist/bitwrench-util-color.umd.min.js +3 -0
  42. package/dist/bitwrench-util-css.cjs.js +2 -1
  43. package/dist/bitwrench-util-css.cjs.min.js +2 -21
  44. package/dist/bitwrench-util-css.es5.js +2 -1
  45. package/dist/bitwrench-util-css.es5.min.js +2 -20
  46. package/dist/bitwrench-util-css.esm.js +2 -1
  47. package/dist/bitwrench-util-css.esm.min.js +1 -19
  48. package/dist/bitwrench-util-css.umd.js +2 -1
  49. package/dist/bitwrench-util-css.umd.min.js +2 -20
  50. package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
  51. package/dist/bitwrench.cjs.js +2826 -1801
  52. package/dist/bitwrench.cjs.min.js +2 -99
  53. package/dist/bitwrench.cjs.min.js.gz +0 -0
  54. package/dist/bitwrench.css +403 -479
  55. package/dist/bitwrench.d.ts +70 -73
  56. package/dist/bitwrench.es5.js +3106 -2020
  57. package/dist/bitwrench.es5.min.js +2 -67
  58. package/dist/bitwrench.es5.min.js.gz +0 -0
  59. package/dist/bitwrench.esm.js +2826 -1801
  60. package/dist/bitwrench.esm.min.js +2 -99
  61. package/dist/bitwrench.esm.min.js.gz +0 -0
  62. package/dist/bitwrench.min.css +1 -1
  63. package/dist/bitwrench.umd.js +2826 -1801
  64. package/dist/bitwrench.umd.min.js +2 -99
  65. package/dist/bitwrench.umd.min.js.gz +0 -0
  66. package/dist/builds.json +222 -134
  67. package/dist/bwserve.cjs.js +289 -282
  68. package/dist/bwserve.d.ts +157 -0
  69. package/dist/bwserve.esm.js +290 -283
  70. package/dist/sri.json +54 -46
  71. package/docs/README.md +6 -3
  72. package/docs/app-patterns.md +7 -6
  73. package/docs/bitwrench-for-wasm.md +53 -54
  74. package/docs/bitwrench-mcp.md +2 -2
  75. package/docs/bitwrench-northstar-principles.md +406 -0
  76. package/docs/bitwrench-taco-schema-discussion.md +2 -2
  77. package/docs/bitwrench_api.md +191 -106
  78. package/docs/bitwrench_typescript_usage.md +5 -5
  79. package/docs/bw-attach.md +29 -75
  80. package/docs/bwserve.md +200 -168
  81. package/docs/cli.md +36 -12
  82. package/docs/component-cheatsheet.md +2 -2
  83. package/docs/component-library.md +4 -4
  84. package/docs/component-lifecycle.md +234 -0
  85. package/docs/drift-lint.md +268 -0
  86. package/docs/framework-translation-table.md +4 -4
  87. package/docs/llm-bitwrench-guide.md +60 -50
  88. package/docs/routing.md +11 -13
  89. package/docs/state-management.md +110 -109
  90. package/docs/taco-format.md +13 -14
  91. package/docs/theming.md +13 -3
  92. package/docs/thinking-in-bitwrench.md +858 -983
  93. package/docs/tutorial-bwserve.md +37 -36
  94. package/docs/tutorial-embedded.md +10 -21
  95. package/docs/tutorial-website.md +2 -2
  96. package/package.json +38 -7
  97. package/readme.html +262 -161
  98. package/src/bitwrench-bccl-entry.js +2 -2
  99. package/src/bitwrench-bccl.js +346 -185
  100. package/src/bitwrench-code-edit.js +16 -5
  101. package/src/bitwrench-color-utils.js +117 -181
  102. package/src/bitwrench-file-ops.js +2 -2
  103. package/src/bitwrench-lean.js +4 -3
  104. package/src/bitwrench-router.js +5 -2
  105. package/src/bitwrench-styles.js +420 -504
  106. package/src/bitwrench-util-color.js +240 -0
  107. package/src/bitwrench-util-css.js +1 -0
  108. package/src/bitwrench-utils.js +4 -0
  109. package/src/bitwrench.d.ts +70 -73
  110. package/src/bitwrench.h +5 -0
  111. package/src/bitwrench.js +1939 -933
  112. package/src/bwserve/attach.js +0 -1
  113. package/src/bwserve/bwclient.js +172 -32
  114. package/src/bwserve/bwshell.js +0 -4
  115. package/src/bwserve/client.js +59 -220
  116. package/src/bwserve/index.js +59 -26
  117. package/src/bwserve.d.ts +157 -0
  118. package/src/bwserve.h +5 -0
  119. package/src/cli/attach.js +12 -75
  120. package/src/cli/convert.js +2 -2
  121. package/src/cli/serve.js +37 -35
  122. package/src/generate-css.js +1 -1
  123. package/src/mcp/knowledge.js +4 -4
  124. package/src/mcp/live.js +21 -13
  125. package/src/mcp/tools.js +0 -1
  126. package/src/version.js +3 -7
@@ -0,0 +1,240 @@
1
+ /**
2
+ * bitwrench-util-color.js - Legacy color parsing and conversion utilities
3
+ *
4
+ * Self-contained module providing CSS color parsing, RGB/HSL conversion,
5
+ * and multi-stop color interpolation. Extracted from bitwrench core in v2.1.
6
+ *
7
+ * Can be loaded standalone (browser script tag after bitwrench.umd.js),
8
+ * or imported as an ES module / CJS module.
9
+ *
10
+ * @module bitwrench-util-color
11
+ * @license BSD-2-Clause
12
+ * @author M A Chatterjee <deftio [at] deftio [dot] com>
13
+ */
14
+
15
+ function _clip(val, min, max) {
16
+ return Math.max(min, Math.min(max, val));
17
+ }
18
+
19
+ function _mapScale(x, in0, in1, out0, out1, options) {
20
+ if (!options) options = {};
21
+ var doClip = options.clip || false;
22
+ var expScale = options.expScale || 1;
23
+ var normalized = (x - in0) / (in1 - in0);
24
+ if (expScale !== 1) normalized = Math.pow(normalized, expScale);
25
+ var result = normalized * (out1 - out0) + out0;
26
+ if (doClip) {
27
+ var mn = Math.min(out0, out1);
28
+ var mx = Math.max(out0, out1);
29
+ result = Math.max(mn, Math.min(mx, result));
30
+ }
31
+ return result;
32
+ }
33
+
34
+ /**
35
+ * Convert HSL to RGB.
36
+ * @param {number|Array} h - Hue 0-360, or [h,s,l,a] array
37
+ * @param {number} [s] - Saturation 0-100
38
+ * @param {number} [l] - Lightness 0-100
39
+ * @param {number} [a=255] - Alpha 0-255
40
+ * @param {boolean} [rnd=true] - Round results
41
+ * @returns {Array} [r, g, b, a, "rgb"]
42
+ */
43
+ export function colorHslToRgb(h, s, l, a, rnd) {
44
+ if (a === undefined) a = 255;
45
+ if (rnd === undefined) rnd = true;
46
+ if (Array.isArray(h)) {
47
+ s = h[1]; l = h[2]; a = h[3] !== undefined ? h[3] : 255; h = h[0];
48
+ }
49
+
50
+ var hNorm = h / 360;
51
+ var sNorm = s / 100;
52
+ var lNorm = l / 100;
53
+
54
+ var r, g, b;
55
+
56
+ if (sNorm === 0) {
57
+ r = g = b = lNorm * 255;
58
+ } else {
59
+ var hue2rgb = function(p, q, t) {
60
+ if (t < 0) t += 1;
61
+ if (t > 1) t -= 1;
62
+ if (t < 1/6) return p + (q - p) * 6 * t;
63
+ if (t < 1/2) return q;
64
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
65
+ return p;
66
+ };
67
+
68
+ var q = lNorm < 0.5 ? lNorm * (1 + sNorm) : lNorm + sNorm - lNorm * sNorm;
69
+ var p = 2 * lNorm - q;
70
+
71
+ r = hue2rgb(p, q, hNorm + 1/3) * 255;
72
+ g = hue2rgb(p, q, hNorm) * 255;
73
+ b = hue2rgb(p, q, hNorm - 1/3) * 255;
74
+ }
75
+
76
+ if (rnd) {
77
+ r = Math.round(r);
78
+ g = Math.round(g);
79
+ b = Math.round(b);
80
+ a = Math.round(a);
81
+ }
82
+
83
+ return [r, g, b, a, "rgb"];
84
+ }
85
+
86
+ /**
87
+ * Convert RGB to HSL.
88
+ * @param {number|Array} r - Red 0-255, or [r,g,b,a] array
89
+ * @param {number} [g] - Green 0-255
90
+ * @param {number} [b] - Blue 0-255
91
+ * @param {number} [a=255] - Alpha 0-255
92
+ * @param {boolean} [rnd=true] - Round results
93
+ * @returns {Array} [h, s, l, a, "hsl"]
94
+ */
95
+ export function colorRgbToHsl(r, g, b, a, rnd) {
96
+ if (a === undefined) a = 255;
97
+ if (rnd === undefined) rnd = true;
98
+ if (Array.isArray(r)) {
99
+ g = r[1]; b = r[2]; a = r[3] !== undefined ? r[3] : 255; r = r[0];
100
+ }
101
+
102
+ r /= 255;
103
+ g /= 255;
104
+ b /= 255;
105
+
106
+ var max = Math.max(r, g, b);
107
+ var min = Math.min(r, g, b);
108
+ var h, s, l = (max + min) / 2;
109
+
110
+ if (max === min) {
111
+ h = s = 0;
112
+ } else {
113
+ var d = max - min;
114
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
115
+
116
+ switch (max) {
117
+ case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;
118
+ case g: h = ((b - r) / d + 2) / 6; break;
119
+ case b: h = ((r - g) / d + 4) / 6; break;
120
+ }
121
+ }
122
+
123
+ h *= 360;
124
+ s *= 100;
125
+ l *= 100;
126
+
127
+ if (rnd) {
128
+ h = Math.round(h);
129
+ s = Math.round(s);
130
+ l = Math.round(l);
131
+ a = Math.round(a);
132
+ }
133
+
134
+ return [h, s, l, a, "hsl"];
135
+ }
136
+
137
+ /**
138
+ * Parse a CSS color string to [r, g, b, a, "rgb"].
139
+ * Handles #hex, rgb(), rgba(), hsl(), hsla(), and bitwrench color arrays.
140
+ * @param {string|Array} s - Color string or array
141
+ * @param {number} [defAlpha=255] - Default alpha
142
+ * @returns {Array} [r, g, b, a, "rgb"]
143
+ */
144
+ export function colorParse(s, defAlpha) {
145
+ if (defAlpha === undefined) defAlpha = 255;
146
+ var r = [0, 0, 0, defAlpha, "rgb"];
147
+
148
+ if (Array.isArray(s)) {
149
+ var df = [0, 0, 0, 255, "rgb"];
150
+ for (var p = 0; p < s.length && p < df.length; p++) {
151
+ df[p] = s[p];
152
+ }
153
+ return df;
154
+ }
155
+
156
+ s = String(s).replace(/\s/g, "");
157
+
158
+ if (s[0] === "#") {
159
+ var hex = s.slice(1);
160
+ if (hex.length === 3 || hex.length === 4) {
161
+ for (var i = 0; i < hex.length; i++) {
162
+ r[i] = parseInt(hex[i] + hex[i], 16);
163
+ }
164
+ } else if (hex.length === 6 || hex.length === 8) {
165
+ for (var j = 0; j < hex.length; j += 2) {
166
+ r[j / 2] = parseInt(hex.substring(j, j + 2), 16);
167
+ }
168
+ }
169
+ } else {
170
+ var match = s.match(/^(rgb|hsl)a?\(([^)]+)\)$/i);
171
+ if (match) {
172
+ var type = match[1].toLowerCase();
173
+ var values = match[2].split(",").map(function(v) { return parseFloat(v); });
174
+
175
+ if (type === "rgb") {
176
+ r[0] = values[0] || 0;
177
+ r[1] = values[1] || 0;
178
+ r[2] = values[2] || 0;
179
+ r[3] = values[3] !== undefined ? values[3] * 255 : defAlpha;
180
+ r[4] = "rgb";
181
+ } else if (type === "hsl") {
182
+ var rgb = colorHslToRgb(values[0] || 0, values[1] || 0, values[2] || 0,
183
+ values[3] !== undefined ? values[3] * 255 : defAlpha);
184
+ return rgb;
185
+ }
186
+ }
187
+ }
188
+
189
+ return r;
190
+ }
191
+
192
+ /**
193
+ * Interpolate between N colors based on a mapped position.
194
+ * @param {number} x - Input value
195
+ * @param {number} in0 - Input range start
196
+ * @param {number} in1 - Input range end
197
+ * @param {Array} colors - Array of color strings
198
+ * @param {number} [stretch] - Exponential scaling factor
199
+ * @returns {Array} [r, g, b, a, "rgb"]
200
+ */
201
+ export function colorInterp(x, in0, in1, colors, stretch) {
202
+ var c = Array.isArray(colors) ? colors : ["#000", "#fff"];
203
+ c = c.length === 0 ? ["#000", "#fff"] : c;
204
+ if (c.length === 1) return c[0];
205
+
206
+ c = c.map(function(col) { return colorParse(col); });
207
+
208
+ var a = _mapScale(x, in0, in1, 0, c.length - 1, { clip: true, expScale: stretch });
209
+ var i = _clip(Math.floor(a), 0, c.length - 2);
210
+ var r = a - i;
211
+
212
+ var interp = function(idx) { return _mapScale(r, 0, 1, c[i][idx], c[i + 1][idx], { clip: true }); };
213
+ return [interp(0), interp(1), interp(2), interp(3), "rgb"];
214
+ }
215
+
216
+ var utilColor = {
217
+ colorParse: colorParse,
218
+ colorRgbToHsl: colorRgbToHsl,
219
+ colorHslToRgb: colorHslToRgb,
220
+ colorInterp: colorInterp
221
+ };
222
+
223
+ /**
224
+ * Install color utilities onto a bitwrench instance.
225
+ * @param {Object} bw - The bitwrench object to extend
226
+ */
227
+ export function install(bw) {
228
+ if (!bw) return;
229
+ bw.colorParse = colorParse;
230
+ bw.colorRgbToHsl = colorRgbToHsl;
231
+ bw.colorHslToRgb = colorHslToRgb;
232
+ bw.colorInterp = colorInterp;
233
+ }
234
+
235
+ if (typeof window !== 'undefined' && window.bw) {
236
+ install(window.bw);
237
+ }
238
+
239
+ export { utilColor };
240
+ export default utilColor;
@@ -220,6 +220,7 @@ function install(bw) {
220
220
  }
221
221
 
222
222
  // Auto-install if bw is on window (script tag usage)
223
+ /* c8 ignore next 3 -- module-level auto-install; only runs at import time in browser */
223
224
  if (typeof window !== 'undefined' && window.bw) {
224
225
  install(window.bw);
225
226
  }
@@ -267,6 +267,7 @@ export function loremIpsum(numChars, startSpot, startWithCapitalLetter = true) {
267
267
  startSpot = (startSpot + 1) % lorem.length;
268
268
  skippedChars++;
269
269
  // Prevent infinite loop in case entire lorem is spaces/punctuation
270
+ /* c8 ignore next -- lorem text always contains letters; this is a defensive guard */
270
271
  if (skippedChars >= lorem.length) {
271
272
  startSpot = 0;
272
273
  skippedChars = 0;
@@ -297,6 +298,7 @@ export function loremIpsum(numChars, startSpot, startWithCapitalLetter = true) {
297
298
  // Ensure capital letter at start if requested
298
299
  if (startWithCapitalLetter) {
299
300
  let c = result[0].toUpperCase();
301
+ /* c8 ignore next -- while loop at L266 skips past non-letters, so first char is always a letter */
300
302
  c = /[A-Z]/.test(c) ? c : "L"; // Use "L" as default if first char isn't a letter
301
303
  result = c + result.substring(1);
302
304
  }
@@ -363,7 +365,9 @@ export function naturalCompare(as, bs) {
363
365
  }
364
366
 
365
367
  // Split into chunks of digits/non-digits
368
+ /* c8 ignore next -- match always succeeds for strings that pass the digit check above */
366
369
  const aParts = a.match(/(\d+|\D+)/g) || [];
370
+ /* c8 ignore next -- match always succeeds for strings that pass the digit check above */
367
371
  const bParts = b.match(/(\d+|\D+)/g) || [];
368
372
 
369
373
  const len = Math.min(aParts.length, bParts.length);
@@ -64,16 +64,20 @@ export interface TacoOptions {
64
64
  state?: Record<string, any>;
65
65
  /** Called after element created and in DOM */
66
66
  mounted?: (el: HTMLElement, state?: Record<string, any>) => void;
67
- /** Called on bw.cleanup() */
67
+ /** Called on bw.unmount() */
68
68
  unmount?: (el: HTMLElement, state?: Record<string, any>) => void;
69
- /** Called by bw.update(); stored on el._bw_render */
69
+ /** Called by bw.refresh(); stored on el._bw_render */
70
70
  render?: (el: HTMLElement, state?: Record<string, any>) => void;
71
- /** Methods attached to el.bw namespace */
71
+ /** Methods attached to el.bw namespace (e.g. handle.update dispatched by bw.update()) */
72
72
  handle?: Record<string, (el: HTMLElement, ...args: any[]) => any>;
73
73
  /** Slot selectors: auto-generates el.bw.setName()/getName() */
74
74
  slots?: Record<string, string>;
75
75
  /** Component type identifier (used internally by BCCL) */
76
76
  type?: string;
77
+ /** User tag for bw.message() addressing */
78
+ userTag?: string;
79
+ /** Declarative event handlers for bw.actions */
80
+ events?: Record<string, (data: any, el: HTMLElement) => void>;
77
81
  }
78
82
 
79
83
  /**
@@ -316,27 +320,51 @@ export interface Bitwrench {
316
320
  /** Generate complete HTML page string */
317
321
  htmlPage(opts: { title?: string; css?: string; content?: TacoContent; favicon?: string; [key: string]: any }): string;
318
322
  /** Create DOM element from TACO (browser only). SVG TACOs ({t:'svg',...}) use createElementNS. */
319
- createDOM(taco: Taco | TacoContent, options?: Record<string, any>): HTMLElement | SVGElement | DocumentFragment;
320
- /** Mount TACO into target, replacing contents */
321
- DOM(target: string | HTMLElement, taco: Taco | TacoContent, options?: Record<string, any>): void;
322
- /** Mount TACO and return root element (for el.bw access) */
323
- mount(target: string | HTMLElement, taco: Taco | TacoContent, options?: Record<string, any>): HTMLElement;
323
+ create(taco: Taco | TacoContent, options?: Record<string, any>): HTMLElement | SVGElement | DocumentFragment;
324
+ /** Mount TACO into target, replacing contents. Alias for bw.mount(). Returns the first created element. */
325
+ DOM(target: string | HTMLElement, taco: Taco | TacoContent, options?: Record<string, any>): HTMLElement | null;
326
+ /** Mount TACO into target, replacing contents. Returns the first created element. */
327
+ mount(target: string | HTMLElement, taco: Taco | TacoContent, options?: Record<string, any>): HTMLElement | null;
324
328
  /** Mark string as pre-escaped HTML */
325
329
  raw(str: string): BwRaw;
326
330
  /** Escape HTML special characters */
327
331
  escapeHTML(str: string): string;
328
332
 
329
333
  // -- Lifecycle & State ----------------------------------------------------
330
- /** Call el._bw_render to re-render element */
331
- update(target: string | HTMLElement): void;
334
+ /** Dispatch data to el.bw.update(data) if defined */
335
+ update(ref: string | HTMLElement, data?: any): void;
336
+ /** Re-render element by calling el._bw_render */
337
+ refresh(ref: string | HTMLElement): void;
338
+ /** Set a named slot value via el.bw.setName(value) */
339
+ updateSlot(ref: string | HTMLElement, name: string, value: any): boolean;
340
+ /** Unmount element: fire unmount hooks, clean subscriptions, remove from cache */
341
+ unmount(element: HTMLElement): void;
342
+ /** Fire mounted() hooks on an element subtree */
343
+ mountTree(element: HTMLElement): void;
344
+ /** Unmount all lifecycle-managed children of element */
345
+ unmountChildren(element: HTMLElement): void;
346
+ /** Wire TACO options onto an existing DOM element (for post-creation hydration) */
347
+ hydrate(element: HTMLElement, taco: Taco): void;
348
+ /** Mark element as detach-exempt (survives parent unmount) */
349
+ detach(element: HTMLElement): void;
350
+ /** Append TACO as child of target */
351
+ append(target: string | HTMLElement, content: Taco | TacoContent): HTMLElement;
352
+ /** Replace target's content with new TACO */
353
+ replace(target: string | HTMLElement, content: Taco | TacoContent): HTMLElement;
354
+ /** Remove element from DOM with unmount */
355
+ remove(target: string | HTMLElement): void;
332
356
  /** Quick-patch element content or attribute */
333
357
  patch(id: string | HTMLElement, content?: TacoContent, attr?: string): HTMLElement | null;
334
358
  /** RFC 6902 JSON Patch on plain objects. Mutates and returns obj. @see bw.patch */
335
359
  jsonPatch(obj: object, ops: Array<{ op: string; path: string; value?: any; from?: string }>): object;
336
360
  /** Batch patch multiple elements */
337
361
  patchAll(patches: Record<string, TacoContent> | Array<{ id: string; content?: TacoContent; attr?: string }>): Record<string, HTMLElement>;
338
- /** Clean up lifecycle hooks, subscriptions, cache */
339
- cleanup(element: HTMLElement): void;
362
+ /** Janitor: document-level cleanup for orphaned lifecycle elements */
363
+ janitor(options?: { verbose?: boolean }): void;
364
+ /** Reconcile children of parent with new TACO list */
365
+ syncChildren(parent: HTMLElement, items: Taco[], options?: { key?: string }): void;
366
+ /** Declared dataflow: recompute fn(inputs...) on any input publish, publish result to outTopic. Returns disposer. */
367
+ derive(inputs: string[], fn: (...values: any[]) => any, outTopic: string, opts?: { seed?: any[]; immediate?: boolean; el?: HTMLElement }): () => void;
340
368
 
341
369
  // -- DOM Selection --------------------------------------------------------
342
370
  /** Resolve target to first matching element. Optional apply: string (textContent), function, TACO (mount), or array. @see bw.$ */
@@ -345,8 +373,8 @@ export interface Bitwrench {
345
373
  $(selector: string | HTMLElement | HTMLElement[], apply?: string | number | boolean | Function | object | any[]): HTMLElement[];
346
374
  /** Dispatch DOM event */
347
375
  emit(target: string | HTMLElement, eventName: string, detail?: any): void;
348
- /** Add event listener */
349
- on(target: string | HTMLElement, eventName: string, handler: (e: Event) => void): void;
376
+ /** Add event listener; returns unsubscribe function */
377
+ on(target: string | HTMLElement, eventName: string, handler: (e: Event) => void): () => void;
350
378
 
351
379
  // -- Pub/Sub --------------------------------------------------------------
352
380
  /** Publish to topic. Fires exact-match and wildcard subscribers. */
@@ -355,6 +383,8 @@ export interface Bitwrench {
355
383
  sub(topic: string, handler: (detail: any, topic?: string) => void, el?: HTMLElement): () => void;
356
384
  /** Unsubscribe handler from topic */
357
385
  unsub(topic: string, handler: Function): number;
386
+ /** Subscribe to topic for a single delivery; auto-unsubscribes after first fire. Returns unsub(). */
387
+ once(topic: string, handler: (detail: any) => void, el?: HTMLElement): () => void;
358
388
 
359
389
  // -- UUID & Identity ------------------------------------------------------
360
390
  /** Generate unique ID */
@@ -364,13 +394,27 @@ export interface Bitwrench {
364
394
  /** Read UUID from TACO or DOM element */
365
395
  getUUID(tacoOrElement: Taco | HTMLElement): string | null;
366
396
 
367
- // -- Component Messages ---------------------------------------------------
397
+ // -- Component Messages & Wire Protocol -----------------------------------
368
398
  /** Call method on el.bw: el.bw[action](data) */
369
399
  message(target: string | HTMLElement, action: string, data?: any): any;
400
+ /** Extract form data from a form or container element */
401
+ formData(target: string | HTMLElement): Record<string, any>;
370
402
  /** Execute wire-protocol message object */
371
- apply(msg: Record<string, any>): any;
403
+ apply(msg: Record<string, any>): boolean;
372
404
  /** Inspect DOM element and subtree, returning plain-object tree with bitwrench metadata */
373
405
  inspect(target: string | HTMLElement, depth?: number): Record<string, any> | null;
406
+ /** Document-level delegated action dispatcher */
407
+ actions: { enable(): void; disable(): void; _ensureInstalled(): void; _reset(): void };
408
+ /** Remote connection (set by bwclient or bw.connect) */
409
+ remote: { send(msg: any): void; close?(): void } | null;
410
+ /** Register a named remote function for bw.apply({type:'call'}) */
411
+ registerRemote(name: string, fn: Function): void;
412
+ /** Connect to a bwserve instance via SSE */
413
+ connect(url: string, options?: Record<string, any>): { send(msg: any): void; close(): void };
414
+ /** Set theme mode ('primary' or 'alternate') on matching elements */
415
+ setThemeMode(mode: string, scope?: string | HTMLElement): { mode: string; count: number };
416
+ /** Load structural CSS only (no theming) */
417
+ loadStructural(): void;
374
418
 
375
419
  // -- Function Registry ----------------------------------------------------
376
420
  funcRegister(fn: Function, name?: string): string;
@@ -379,16 +423,16 @@ export interface Bitwrench {
379
423
  funcUnregister(name: string): void;
380
424
  funcGetRegistry(): Record<string, Function>;
381
425
 
382
- // -- Component Registry ---------------------------------------------------
383
- render(element: HTMLElement, position: string, taco: Taco): string;
384
- getComponent(id: string): Record<string, any> | null;
385
- getAllComponents(): Map<string, any>;
426
+ // -- Render (convenience factory over append/replace) --------------------
427
+ render(target: string | HTMLElement, position: 'append' | 'prepend' | 'replace' | 'before' | 'after', taco: Taco): { el: HTMLElement | null; ok: boolean; error: string | null };
386
428
 
387
429
  // -- CSS & Styles ---------------------------------------------------------
388
430
  /** Generate CSS string from JS object */
389
431
  css(rules: Record<string, any>, options?: { scopeSelector?: string; selector?: string }): string;
390
432
  /** Inject CSS into document */
391
433
  injectCSS(css: string, options?: { id?: string; append?: boolean; scope?: string }): HTMLElement;
434
+ /** Merge style objects (shallow Object.assign). Use to compose inline styles. */
435
+ s(...objs: Record<string, string | number>[]): Record<string, string | number>;
392
436
  /** Responsive media query helper */
393
437
  responsive(selector: string, breakpoints: Record<string, Record<string, any>>): string;
394
438
  /** Generate styles from config */
@@ -401,8 +445,6 @@ export interface Bitwrench {
401
445
  loadReset(): void;
402
446
  /** Toggle between primary/alternate theme palettes on all matching elements. @see bw.applyStyles */
403
447
  toggleThemeMode(scope?: string | HTMLElement): string;
404
- /** @deprecated Use bw.toggleThemeMode() instead. Alias kept for one release cycle. */
405
- toggleStyles(scope?: string | HTMLElement): string;
406
448
  /** Remove injected styles */
407
449
  clearStyles(scope?: string): void;
408
450
  /** Generate type scale from base + ratio */
@@ -485,55 +527,8 @@ export interface Bitwrench {
485
527
  makeDataTable(config?: TableConfig): Taco;
486
528
  makeBarChart(config?: ComponentConfig): Taco;
487
529
 
488
- // -- Corresponding create* (return DOM Element) ---------------------------
489
- createCard(config?: CardConfig | string): HTMLElement;
490
- createButton(config?: ButtonConfig | string): HTMLElement;
491
- createContainer(config?: ComponentConfig): HTMLElement;
492
- createRow(config?: ComponentConfig): HTMLElement;
493
- createCol(config?: ComponentConfig): HTMLElement;
494
- createStack(config?: ComponentConfig): HTMLElement;
495
- createSection(config?: ComponentConfig): HTMLElement;
496
- createNav(config?: NavConfig): HTMLElement;
497
- createNavbar(config?: ComponentConfig): HTMLElement;
498
- createBreadcrumb(config?: ComponentConfig): HTMLElement;
499
- createTabs(config?: TabsConfig): HTMLElement;
500
- createPagination(config?: ComponentConfig): HTMLElement;
501
- createAlert(config?: AlertConfig | string): HTMLElement;
502
- createBadge(config?: ComponentConfig | string): HTMLElement;
503
- createProgress(config?: ComponentConfig): HTMLElement;
504
- createSpinner(config?: ComponentConfig): HTMLElement;
505
- createToast(config?: ComponentConfig): HTMLElement;
506
- createTooltip(config?: ComponentConfig): HTMLElement;
507
- createPopover(config?: ComponentConfig): HTMLElement;
508
- createListGroup(config?: ComponentConfig): HTMLElement;
509
- createAccordion(config?: AccordionConfig): HTMLElement;
510
- createCarousel(config?: CarouselConfig): HTMLElement;
511
- createTimeline(config?: ComponentConfig): HTMLElement;
512
- createStepper(config?: ComponentConfig): HTMLElement;
513
- createChipInput(config?: ComponentConfig): HTMLElement;
514
- createModal(config?: ModalConfig): HTMLElement;
515
- createDropdown(config?: ComponentConfig): HTMLElement;
516
- createForm(config?: ComponentConfig): HTMLElement;
517
- createFormGroup(config?: ComponentConfig): HTMLElement;
518
- createInput(config?: InputConfig): HTMLElement;
519
- createTextarea(config?: ComponentConfig): HTMLElement;
520
- createSelect(config?: ComponentConfig): HTMLElement;
521
- createCheckbox(config?: ComponentConfig): HTMLElement;
522
- createRadio(config?: ComponentConfig): HTMLElement;
523
- createSwitch(config?: ComponentConfig): HTMLElement;
524
- createRange(config?: ComponentConfig): HTMLElement;
525
- createFileUpload(config?: ComponentConfig): HTMLElement;
526
- createSearchInput(config?: ComponentConfig): HTMLElement;
527
- createButtonGroup(config?: ComponentConfig): HTMLElement;
528
- createHero(config?: ComponentConfig): HTMLElement;
529
- createFeatureGrid(config?: ComponentConfig): HTMLElement;
530
- createCTA(config?: ComponentConfig): HTMLElement;
531
- createCodeDemo(config?: ComponentConfig): HTMLElement;
532
- createSkeleton(config?: ComponentConfig): HTMLElement;
533
- createAvatar(config?: ComponentConfig): HTMLElement;
534
- createStatCard(config?: ComponentConfig): HTMLElement;
535
- createMediaObject(config?: ComponentConfig): HTMLElement;
536
- createTable(config?: TableConfig): HTMLElement;
530
+ /** List available BCCL component types, or get factory for a type */
531
+ catalog(type?: string): Record<string, any>;
537
532
 
538
533
  // -- Array Utilities ------------------------------------------------------
539
534
  arrayUniq(arr: any[]): any[];
@@ -599,9 +594,11 @@ export interface Bitwrench {
599
594
  _unmountCallbacks: Map<string, Function>;
600
595
  _topics: Record<string, any[]>;
601
596
  _fnRegistry: Record<string, Function>;
602
- _componentRegistry: Map<string, any>;
603
597
  _clientFunctions: Record<string, Function>;
604
- _allowExec: boolean;
598
+ _clientRemotes: Record<string, Function>;
599
+ _wireListeners: Record<string, () => void>;
600
+ _mounted: Record<string, boolean>;
601
+ _detached: Record<string, boolean>;
605
602
  }
606
603
 
607
604
  /** The bw namespace (default export) */
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Shim header for the Arduino library layout ("recursive" layout adds only
3
+ * src/ to the include path). The real header lives in embedded_c/bitwrench.h.
4
+ */
5
+ #include "../embedded_c/bitwrench.h"