bitwrench 2.0.16 → 2.0.17

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 (42) hide show
  1. package/dist/bitwrench-bccl.cjs.js +6 -2
  2. package/dist/bitwrench-bccl.cjs.min.js +3 -3
  3. package/dist/bitwrench-bccl.esm.js +6 -2
  4. package/dist/bitwrench-bccl.esm.min.js +3 -3
  5. package/dist/bitwrench-bccl.umd.js +6 -2
  6. package/dist/bitwrench-bccl.umd.min.js +2 -2
  7. package/dist/bitwrench-code-edit.cjs.js +1 -1
  8. package/dist/bitwrench-code-edit.cjs.min.js +1 -1
  9. package/dist/bitwrench-code-edit.es5.js +1 -1
  10. package/dist/bitwrench-code-edit.es5.min.js +1 -1
  11. package/dist/bitwrench-code-edit.esm.js +1 -1
  12. package/dist/bitwrench-code-edit.esm.min.js +1 -1
  13. package/dist/bitwrench-code-edit.umd.js +1 -1
  14. package/dist/bitwrench-code-edit.umd.min.js +1 -1
  15. package/dist/bitwrench-lean.cjs.js +506 -154
  16. package/dist/bitwrench-lean.cjs.min.js +7 -7
  17. package/dist/bitwrench-lean.es5.js +517 -155
  18. package/dist/bitwrench-lean.es5.min.js +5 -5
  19. package/dist/bitwrench-lean.esm.js +505 -154
  20. package/dist/bitwrench-lean.esm.min.js +6 -6
  21. package/dist/bitwrench-lean.umd.js +506 -154
  22. package/dist/bitwrench-lean.umd.min.js +7 -7
  23. package/dist/bitwrench.cjs.js +511 -155
  24. package/dist/bitwrench.cjs.min.js +8 -8
  25. package/dist/bitwrench.es5.js +525 -156
  26. package/dist/bitwrench.es5.min.js +6 -6
  27. package/dist/bitwrench.esm.js +510 -155
  28. package/dist/bitwrench.esm.min.js +8 -8
  29. package/dist/bitwrench.umd.js +511 -155
  30. package/dist/bitwrench.umd.min.js +8 -8
  31. package/dist/builds.json +82 -82
  32. package/dist/bwserve.cjs.js +16 -2
  33. package/dist/bwserve.esm.js +16 -2
  34. package/dist/sri.json +34 -34
  35. package/package.json +4 -2
  36. package/readme.html +1 -1
  37. package/src/bitwrench-bccl.js +5 -1
  38. package/src/bitwrench.js +502 -151
  39. package/src/bwserve/index.js +12 -1
  40. package/src/bwserve/shell.js +3 -0
  41. package/src/cli/layout-default.js +47 -32
  42. package/src/version.js +3 -3
@@ -1,10 +1,11 @@
1
- /*! bitwrench v2.0.16 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
1
+ /*! bitwrench v2.0.17 | BSD-2-Clause | https://deftio.github.com/bitwrench/pages */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
4
  typeof define === 'function' && define.amd ? define(factory) :
5
5
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bw = factory());
6
6
  })(this, (function () { 'use strict';
7
7
 
8
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
9
  function _arrayLikeToArray(r, a) {
9
10
  (null == a || a > r.length) && (a = r.length);
10
11
  for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
@@ -189,14 +190,14 @@
189
190
  */
190
191
 
191
192
  var VERSION_INFO = {
192
- version: '2.0.16',
193
+ version: '2.0.17',
193
194
  name: 'bitwrench',
194
195
  description: 'A library for javascript UI functions.',
195
196
  license: 'BSD-2-Clause',
196
197
  homepage: 'https://deftio.github.com/bitwrench/pages',
197
198
  repository: 'git+https://github.com/deftio/bitwrench.git',
198
199
  author: 'manu a. chatterjee <deftio@deftio.com> (https://deftio.com/)',
199
- buildDate: '2026-03-12T08:05:52.043Z'
200
+ buildDate: '2026-03-13T23:15:10.823Z'
200
201
  };
201
202
 
202
203
  /**
@@ -9080,7 +9081,14 @@
9080
9081
  function make(type, props) {
9081
9082
  var def = BCCL[type];
9082
9083
  if (!def) throw new Error('bw.make: unknown component type "' + type + '". Available: ' + Object.keys(BCCL).join(', '));
9083
- return def.make(props || {});
9084
+ var taco = def.make(props || {});
9085
+ if (taco && _typeof(taco) === 'object') {
9086
+ taco._bwFactory = {
9087
+ type: type,
9088
+ props: props || {}
9089
+ };
9090
+ }
9091
+ return taco;
9084
9092
  }
9085
9093
 
9086
9094
  var components = /*#__PURE__*/Object.freeze({
@@ -9193,7 +9201,7 @@
9193
9201
  __monkey_patch_is_nodejs__: {
9194
9202
  _value: 'ignore',
9195
9203
  set: function set(x) {
9196
- this._value = typeof x === 'boolean' ? x : 'ignore';
9204
+ this._value = _is(x, 'boolean') ? x : 'ignore';
9197
9205
  },
9198
9206
  get: function get() {
9199
9207
  return this._value;
@@ -9241,6 +9249,76 @@
9241
9249
  configurable: true
9242
9250
  });
9243
9251
 
9252
+ // ── Internal aliases ─────────────────────────────────────────────────────
9253
+ // Short names for frequently-used builtins and internal methods.
9254
+ // Same pattern as v1 (_to = bw.typeOf, etc.).
9255
+ //
9256
+ // Why: Terser can't shorten global property chains (console.warn,
9257
+ // Object.prototype.hasOwnProperty, Array.isArray, document.createElement)
9258
+ // because it can't prove they're side-effect-free. We can, so we alias
9259
+ // them here. Each alias saves bytes in the minified output, and the short
9260
+ // names also reduce visual noise in the hot paths (binding pipeline,
9261
+ // createDOM, etc.).
9262
+ //
9263
+ // Alias Target Sites
9264
+ // ───────── ────────────────────────────────────── ─────
9265
+ // _hop Object.prototype.hasOwnProperty 15
9266
+ // _isA Array.isArray 25
9267
+ // _keys Object.keys 7
9268
+ // _to bw.typeOf (type string) 26
9269
+ // _is type check boolean: _is(x,'string') ~50
9270
+ // _cw console.warn 8
9271
+ // _cl console.log 11
9272
+ // _ce console.error 4
9273
+ // _chp ComponentHandle.prototype 28 (defined after constructor)
9274
+ //
9275
+ // Note: document.createElement etc. are NOT aliased because they require
9276
+ // `this === document` and .bind() would add overhead on every call.
9277
+ // Console aliases use thin wrappers (not direct refs) so test monkey-
9278
+ // patching of console.warn/log/error continues to work.
9279
+ //
9280
+ // `typeof x` for UNDECLARED globals (window, document, process, require,
9281
+ // EventSource, navigator, Promise, __filename, import.meta) MUST stay as
9282
+ // raw `typeof` — calling _to(x) when x doesn't exist throws ReferenceError.
9283
+ //
9284
+ // ── v1 functional type helpers (kept for reference, not currently used) ──
9285
+ // _toa(x, type, trueVal, falseVal) — bw.typeAssign:
9286
+ // returns trueVal if _to(x)===type, else falseVal.
9287
+ // Replaces: (typeof x === 'string') ? A : B → _toa(x,'string',A,B)
9288
+ // _toc(x, type, trueVal, falseVal) — bw.typeConvert:
9289
+ // same as _toa but if trueVal/falseVal are functions, calls them with x.
9290
+ // Replaces: typeof x === 'string' ? fn(x) : default → _toc(x,'string',fn,default)
9291
+ // Uncomment if pattern frequency justifies them:
9292
+ // var _toa = function(x, t, y, n) { return _to(x) === t ? y : n; };
9293
+ // var _toc = function(x, t, y, n) { var r = _to(x)===t; return r ? (_to(y)==='function'?y(x):y) : (_to(n)==='function'?n(x):n); };
9294
+ // ─────────────────────────────────────────────────────────────────────────
9295
+ var _hop = Object.prototype.hasOwnProperty;
9296
+ var _isA = Array.isArray;
9297
+ var _keys = Object.keys;
9298
+ var _to = typeOf; // imported from bitwrench-utils.js
9299
+ var _is = function _is(x, t) {
9300
+ var r = _to(x);
9301
+ return r === t || r.toLowerCase() === t;
9302
+ };
9303
+ // Console aliases use thin wrappers (not direct references) so that test
9304
+ // code can monkey-patch console.warn/log/error and the patches take effect.
9305
+ var _cw = function _cw() {
9306
+ console.warn.apply(console, arguments);
9307
+ };
9308
+ var _cl = function _cl() {
9309
+ console.log.apply(console, arguments);
9310
+ };
9311
+ var _ce = function _ce() {
9312
+ console.error.apply(console, arguments);
9313
+ };
9314
+
9315
+ /**
9316
+ * Debug flag. When true, emits console.warn for silent binding failures
9317
+ * (missing paths, null refs, auto-created intermediate objects).
9318
+ * @type {boolean}
9319
+ */
9320
+ bw.debug = false;
9321
+
9244
9322
  /**
9245
9323
  * Lazy-resolve Node.js `fs` module.
9246
9324
  * Tries require('fs') first (available in CJS/UMD Node.js builds),
@@ -9390,7 +9468,7 @@
9390
9468
  */
9391
9469
  bw._el = function (id) {
9392
9470
  // Pass-through for DOM elements
9393
- if (typeof id !== 'string') return id || null;
9471
+ if (!_is(id, 'string')) return id || null;
9394
9472
  if (!id) return null;
9395
9473
  if (!bw._isBrowser) return null;
9396
9474
 
@@ -9485,7 +9563,7 @@
9485
9563
  * // => '&lt;b&gt;Hello&lt;&#x2F;b&gt; &amp; &quot;world&quot;'
9486
9564
  */
9487
9565
  bw.escapeHTML = function (str) {
9488
- if (typeof str !== 'string') return '';
9566
+ if (!_is(str, 'string')) return '';
9489
9567
  var escapeMap = {
9490
9568
  '&': '&amp;',
9491
9569
  '<': '&lt;',
@@ -9562,7 +9640,7 @@
9562
9640
  }
9563
9641
 
9564
9642
  // Handle arrays of TACOs
9565
- if (Array.isArray(taco)) {
9643
+ if (_isA(taco)) {
9566
9644
  return taco.map(function (t) {
9567
9645
  return bw.html(t, options);
9568
9646
  }).join('');
@@ -9585,17 +9663,17 @@
9585
9663
  if (taco && taco._bwEach && options.state) {
9586
9664
  var eachExpr = taco.expr.replace(/^\$\{|\}$/g, '');
9587
9665
  var arr = bw._evaluatePath(options.state, eachExpr);
9588
- if (!Array.isArray(arr)) return '';
9666
+ if (!_isA(arr)) return '';
9589
9667
  return arr.map(function (item, idx) {
9590
9668
  return bw.html(taco.factory(item, idx), options);
9591
9669
  }).join('');
9592
9670
  }
9593
9671
 
9594
9672
  // Handle primitives and non-TACO objects
9595
- if (_typeof(taco) !== 'object' || !taco.t) {
9673
+ if (!_is(taco, 'object') || !taco.t) {
9596
9674
  var str = options.raw ? String(taco) : bw.escapeHTML(String(taco));
9597
9675
  // Resolve template bindings if state provided
9598
- if (options.state && typeof str === 'string' && str.indexOf('${') >= 0) {
9676
+ if (options.state && _is(str, 'string') && str.indexOf('${') >= 0) {
9599
9677
  str = bw._resolveTemplate(str, options.state, !!options.compile);
9600
9678
  }
9601
9679
  return str;
@@ -9620,9 +9698,17 @@
9620
9698
  // Skip null, undefined, false
9621
9699
  if (value == null || value === false) continue;
9622
9700
 
9623
- // Skip event handlers (they're for DOM only)
9624
- if (key.startsWith('on')) continue;
9625
- if (key === 'style' && _typeof(value) === 'object') {
9701
+ // Serialize event handlers via funcRegister
9702
+ if (key.startsWith('on')) {
9703
+ if (_is(value, 'function')) {
9704
+ var fnId = bw.funcRegister(value);
9705
+ attrStr += ' ' + key + '="' + bw.funcGetDispatchStr(fnId, 'event') + '"';
9706
+ } else if (_is(value, 'string')) {
9707
+ attrStr += ' ' + key + '="' + bw.escapeHTML(value) + '"';
9708
+ }
9709
+ continue;
9710
+ }
9711
+ if (key === 'style' && _is(value, 'object')) {
9626
9712
  // Convert style object to string
9627
9713
  var styleStr = Object.entries(value).filter(function (_ref) {
9628
9714
  var _ref2 = _slicedToArray(_ref, 2),
@@ -9639,7 +9725,7 @@
9639
9725
  }
9640
9726
  } else if (key === 'class') {
9641
9727
  // Handle class as array or string
9642
- var classStr = Array.isArray(value) ? value.filter(Boolean).join(' ') : String(value);
9728
+ var classStr = _isA(value) ? value.filter(Boolean).join(' ') : String(value);
9643
9729
  if (classStr) {
9644
9730
  attrStr += " class=\"".concat(bw.escapeHTML(classStr), "\"");
9645
9731
  }
@@ -9675,12 +9761,184 @@
9675
9761
  // Process content recursively
9676
9762
  var contentStr = content != null ? bw.html(content, options) : '';
9677
9763
  // Resolve template bindings in content if state provided
9678
- if (options.state && typeof contentStr === 'string' && contentStr.indexOf('${') >= 0) {
9764
+ if (options.state && _is(contentStr, 'string') && contentStr.indexOf('${') >= 0) {
9679
9765
  contentStr = bw._resolveTemplate(contentStr, options.state, !!options.compile);
9680
9766
  }
9681
9767
  return "<".concat(tag).concat(attrStr, ">").concat(contentStr, "</").concat(tag, ">");
9682
9768
  };
9683
9769
 
9770
+ /**
9771
+ * Generate a complete, self-contained HTML document from TACO content.
9772
+ *
9773
+ * Produces a full `<!DOCTYPE html>` page with configurable runtime injection,
9774
+ * func registry emission (so serialized event handlers work), optional theme,
9775
+ * and extra head elements. Designed for static site generation, offline/airgapped
9776
+ * use, and the "static site that isn't static" workflow.
9777
+ *
9778
+ * @param {Object} [opts={}] - Page options
9779
+ * @param {Object|string|Array} [opts.body=''] - Body content: TACO, string, or array
9780
+ * @param {string} [opts.title='bitwrench'] - Page title
9781
+ * @param {Object} [opts.state] - State for ${expr} resolution in bw.html()
9782
+ * @param {string} [opts.runtime='shim'] - Runtime level: 'inline'|'cdn'|'shim'|'none'
9783
+ * @param {string} [opts.css=''] - Additional CSS for <style> block
9784
+ * @param {string|Object} [opts.theme=null] - Theme preset name or config object
9785
+ * @param {Array} [opts.head=[]] - Extra TACO elements rendered into <head>
9786
+ * @param {string} [opts.favicon=''] - Favicon URL
9787
+ * @param {string} [opts.lang='en'] - HTML lang attribute
9788
+ * @returns {string} Complete HTML document string
9789
+ * @category DOM Generation
9790
+ * @see bw.html
9791
+ * @example
9792
+ * bw.htmlPage({
9793
+ * title: 'My App',
9794
+ * body: { t: 'h1', c: 'Hello World' },
9795
+ * runtime: 'shim'
9796
+ * })
9797
+ */
9798
+ bw.htmlPage = function (opts) {
9799
+ opts = opts || {};
9800
+ var title = opts.title || 'bitwrench';
9801
+ var body = opts.body || '';
9802
+ var state = opts.state || undefined;
9803
+ var runtime = opts.runtime || 'shim';
9804
+ var css = opts.css || '';
9805
+ var theme = opts.theme || null;
9806
+ var headExtra = opts.head || [];
9807
+ var favicon = opts.favicon || '';
9808
+ var lang = opts.lang || 'en';
9809
+
9810
+ // Snapshot funcRegistry counter before rendering
9811
+ var fnCounterBefore = bw._fnIDCounter;
9812
+
9813
+ // Render body content
9814
+ var bodyHTML = '';
9815
+ if (_is(body, 'string')) {
9816
+ bodyHTML = body;
9817
+ } else {
9818
+ var htmlOpts = {};
9819
+ if (state) htmlOpts.state = state;
9820
+ bodyHTML = bw.html(body, htmlOpts);
9821
+ }
9822
+
9823
+ // Collect functions registered during this render
9824
+ var fnCounterAfter = bw._fnIDCounter;
9825
+ var registryEntries = '';
9826
+ for (var i = fnCounterBefore; i < fnCounterAfter; i++) {
9827
+ var fnKey = 'bw_fn_' + i;
9828
+ if (bw._fnRegistry[fnKey]) {
9829
+ registryEntries += 'bw._fnRegistry[\'' + fnKey + '\']=' + bw._fnRegistry[fnKey].toString() + ';\n';
9830
+ }
9831
+ }
9832
+
9833
+ // Build runtime script for <head>
9834
+ var runtimeHead = '';
9835
+ if (runtime === 'inline') {
9836
+ // Read UMD bundle synchronously if in Node.js
9837
+ var umdSource = null;
9838
+ if (bw._isNode) {
9839
+ try {
9840
+ var fs = typeof require === 'function' ? require('fs') : null;
9841
+ var pathMod = typeof require === 'function' ? require('path') : null;
9842
+ if (fs && pathMod) {
9843
+ // Resolve dist/ relative to this source file
9844
+ var srcDir = '';
9845
+ try {
9846
+ srcDir = pathMod.dirname(typeof __filename !== 'undefined' ? __filename : '');
9847
+ } catch (e2) {/* ESM: __filename not available */}
9848
+ if (!srcDir && typeof ({ url: (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bitwrench.es5.js', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bitwrench.es5.js', document.baseURI).href))) {
9849
+ var url = typeof require === 'function' ? require('url') : null;
9850
+ if (url && url.fileURLToPath) srcDir = pathMod.dirname(url.fileURLToPath((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('bitwrench.es5.js', document.baseURI).href))));
9851
+ }
9852
+ if (srcDir) {
9853
+ var distPath = pathMod.resolve(srcDir, '../dist/bitwrench.umd.min.js');
9854
+ umdSource = fs.readFileSync(distPath, 'utf8');
9855
+ }
9856
+ }
9857
+ } catch (e) {/* fall through */}
9858
+ }
9859
+ if (umdSource) {
9860
+ runtimeHead = '<script>' + umdSource + '</script>';
9861
+ } else {
9862
+ // Fallback to shim in browser or if dist not available
9863
+ runtimeHead = '<script>' + bw._FUNC_REGISTRY_SHIM + '</script>';
9864
+ }
9865
+ } else if (runtime === 'cdn') {
9866
+ runtimeHead = '<script src="https://cdn.jsdelivr.net/npm/bitwrench@2/dist/bitwrench.umd.min.js"></script>';
9867
+ } else if (runtime === 'shim') {
9868
+ runtimeHead = '<script>' + bw._FUNC_REGISTRY_SHIM + '</script>';
9869
+ }
9870
+ // runtime === 'none' → empty
9871
+
9872
+ // Theme CSS
9873
+ var themeCSS = '';
9874
+ if (theme) {
9875
+ var themeConfig = _is(theme, 'string') ? THEME_PRESETS[theme.toLowerCase()] || null : theme;
9876
+ if (themeConfig) {
9877
+ var themeResult = bw.generateTheme('', Object.assign({}, themeConfig, {
9878
+ inject: false
9879
+ }));
9880
+ themeCSS = themeResult.css;
9881
+ }
9882
+ }
9883
+
9884
+ // Extra <head> elements
9885
+ var headHTML = '';
9886
+ if (_isA(headExtra) && headExtra.length > 0) {
9887
+ headHTML = headExtra.map(function (el) {
9888
+ return bw.html(el);
9889
+ }).join('\n');
9890
+ }
9891
+
9892
+ // Favicon
9893
+ var faviconTag = '';
9894
+ if (favicon) {
9895
+ var safeFavicon = favicon.replace(/[&<>"']/g, function (c) {
9896
+ return {
9897
+ '&': '&amp;',
9898
+ '<': '&lt;',
9899
+ '>': '&gt;',
9900
+ '"': '&quot;',
9901
+ "'": '&#39;'
9902
+ }[c];
9903
+ });
9904
+ faviconTag = '<link rel="icon" href="' + safeFavicon + '">';
9905
+ }
9906
+
9907
+ // Escaped title
9908
+ var safeTitle = bw.escapeHTML(title);
9909
+
9910
+ // Combine all CSS
9911
+ var allCSS = (themeCSS ? themeCSS + '\n' : '') + css;
9912
+
9913
+ // Body-end script: registry entries + optional loadDefaultStyles
9914
+ var bodyEndScript = '';
9915
+ var bodyEndParts = [];
9916
+ if (registryEntries) {
9917
+ bodyEndParts.push(registryEntries);
9918
+ }
9919
+ if (runtime === 'inline' || runtime === 'cdn') {
9920
+ bodyEndParts.push('if(typeof bw!=="undefined"){bw.loadDefaultStyles();}');
9921
+ }
9922
+ if (bodyEndParts.length > 0) {
9923
+ bodyEndScript = '<script>\n' + bodyEndParts.join('\n') + '\n</script>';
9924
+ }
9925
+
9926
+ // Assemble document
9927
+ var parts = ['<!DOCTYPE html>', '<html lang="' + lang + '">', '<head>', '<meta charset="UTF-8">', '<meta name="viewport" content="width=device-width, initial-scale=1">'];
9928
+ parts.push('<title>' + safeTitle + '</title>');
9929
+ if (faviconTag) parts.push(faviconTag);
9930
+ if (runtimeHead) parts.push(runtimeHead);
9931
+ if (headHTML) parts.push(headHTML);
9932
+ if (allCSS) parts.push('<style>' + allCSS + '</style>');
9933
+ parts.push('</head>');
9934
+ parts.push('<body>');
9935
+ parts.push(bodyHTML);
9936
+ if (bodyEndScript) parts.push(bodyEndScript);
9937
+ parts.push('</body>');
9938
+ parts.push('</html>');
9939
+ return parts.join('\n');
9940
+ };
9941
+
9684
9942
  /**
9685
9943
  * Create a live DOM element from a TACO object (browser only).
9686
9944
  *
@@ -9726,7 +9984,7 @@
9726
9984
  }
9727
9985
 
9728
9986
  // Handle text nodes
9729
- if (_typeof(taco) !== 'object' || !taco.t) {
9987
+ if (!_is(taco, 'object') || !taco.t) {
9730
9988
  return document.createTextNode(String(taco));
9731
9989
  }
9732
9990
  var tag = taco.t,
@@ -9745,16 +10003,16 @@
9745
10003
  key = _Object$entries2$_i[0],
9746
10004
  value = _Object$entries2$_i[1];
9747
10005
  if (value == null || value === false) continue;
9748
- if (key === 'style' && _typeof(value) === 'object') {
10006
+ if (key === 'style' && _is(value, 'object')) {
9749
10007
  // Apply styles directly
9750
10008
  Object.assign(el.style, value);
9751
10009
  } else if (key === 'class') {
9752
10010
  // Handle class as array or string
9753
- var classStr = Array.isArray(value) ? value.filter(Boolean).join(' ') : String(value);
10011
+ var classStr = _isA(value) ? value.filter(Boolean).join(' ') : String(value);
9754
10012
  if (classStr) {
9755
10013
  el.className = classStr;
9756
10014
  }
9757
- } else if (key.startsWith('on') && typeof value === 'function') {
10015
+ } else if (key.startsWith('on') && _is(value, 'function')) {
9758
10016
  // Event handlers
9759
10017
  var eventName = key.slice(2).toLowerCase();
9760
10018
  el.addEventListener(eventName, value);
@@ -9774,7 +10032,7 @@
9774
10032
  // Children with data-bw_id or id attributes get local refs on the parent,
9775
10033
  // so o.render functions can access them without any DOM lookup.
9776
10034
  if (content != null) {
9777
- if (Array.isArray(content)) {
10035
+ if (_isA(content)) {
9778
10036
  content.forEach(function (child) {
9779
10037
  if (child != null) {
9780
10038
  // Handle ComponentHandle in content arrays (Level 2 children)
@@ -9794,20 +10052,20 @@
9794
10052
  if (childEl._bw_refs) {
9795
10053
  if (!el._bw_refs) el._bw_refs = {};
9796
10054
  for (var rk in childEl._bw_refs) {
9797
- if (Object.prototype.hasOwnProperty.call(childEl._bw_refs, rk)) {
10055
+ if (_hop.call(childEl._bw_refs, rk)) {
9798
10056
  el._bw_refs[rk] = childEl._bw_refs[rk];
9799
10057
  }
9800
10058
  }
9801
10059
  }
9802
10060
  }
9803
10061
  });
9804
- } else if (_typeof(content) === 'object' && content.__bw_raw) {
10062
+ } else if (_is(content, 'object') && content.__bw_raw) {
9805
10063
  // Raw HTML content — inject via innerHTML
9806
10064
  el.innerHTML = content.v;
9807
10065
  } else if (content._bwComponent === true) {
9808
10066
  // Single ComponentHandle as content
9809
10067
  content.mount(el);
9810
- } else if (_typeof(content) === 'object' && content.t) {
10068
+ } else if (_is(content, 'object') && content.t) {
9811
10069
  var childEl = bw.createDOM(content, options);
9812
10070
  el.appendChild(childEl);
9813
10071
  var childBwId = content.a ? content.a['data-bw_id'] || content.a.id : null;
@@ -9818,7 +10076,7 @@
9818
10076
  if (childEl._bw_refs) {
9819
10077
  if (!el._bw_refs) el._bw_refs = {};
9820
10078
  for (var rk in childEl._bw_refs) {
9821
- if (Object.prototype.hasOwnProperty.call(childEl._bw_refs, rk)) {
10079
+ if (_hop.call(childEl._bw_refs, rk)) {
9822
10080
  el._bw_refs[rk] = childEl._bw_refs[rk];
9823
10081
  }
9824
10082
  }
@@ -9850,7 +10108,7 @@
9850
10108
  if (opts.render) {
9851
10109
  el._bw_render = opts.render;
9852
10110
  if (opts.mounted) {
9853
- console.warn('bw.createDOM: o.render and o.mounted are mutually exclusive. o.render wins.');
10111
+ _cw('bw.createDOM: o.render and o.mounted are mutually exclusive. o.render wins.');
9854
10112
  }
9855
10113
 
9856
10114
  // Queue initial render (same timing as mounted)
@@ -9922,7 +10180,7 @@
9922
10180
  // Get target element (use cache-backed lookup)
9923
10181
  var targetEl = bw._el(target);
9924
10182
  if (!targetEl) {
9925
- console.error('bw.DOM: Target element not found:', target);
10183
+ _ce('bw.DOM: Target element not found:', target);
9926
10184
  return null;
9927
10185
  }
9928
10186
 
@@ -9960,7 +10218,7 @@
9960
10218
  targetEl.appendChild(taco.element);
9961
10219
  }
9962
10220
  // Handle arrays
9963
- else if (Array.isArray(taco)) {
10221
+ else if (_isA(taco)) {
9964
10222
  taco.forEach(function (t) {
9965
10223
  if (t != null) {
9966
10224
  if (t._bwComponent === true) {
@@ -9995,7 +10253,7 @@
9995
10253
  bw.compileProps = function (handle) {
9996
10254
  var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
9997
10255
  var compiledProps = {};
9998
- Object.keys(props).forEach(function (key) {
10256
+ _keys(props).forEach(function (key) {
9999
10257
  // Create getter/setter for each prop
10000
10258
  Object.defineProperty(compiledProps, key, {
10001
10259
  get: function get() {
@@ -10306,17 +10564,17 @@
10306
10564
  if (attr) {
10307
10565
  // Patch an attribute
10308
10566
  el.setAttribute(attr, String(content));
10309
- } else if (Array.isArray(content)) {
10567
+ } else if (_isA(content)) {
10310
10568
  // Patch with array of children (strings and/or TACOs)
10311
10569
  el.innerHTML = '';
10312
10570
  content.forEach(function (item) {
10313
- if (typeof item === 'string' || typeof item === 'number') {
10571
+ if (_is(item, 'string') || _is(item, 'number')) {
10314
10572
  el.appendChild(document.createTextNode(String(item)));
10315
10573
  } else if (item && item.t) {
10316
10574
  el.appendChild(bw.createDOM(item));
10317
10575
  }
10318
10576
  });
10319
- } else if (_typeof(content) === 'object' && content !== null && content.t) {
10577
+ } else if (_is(content, 'object') && content.t) {
10320
10578
  // Patch with a TACO — replace children
10321
10579
  el.innerHTML = '';
10322
10580
  el.appendChild(bw.createDOM(content));
@@ -10347,7 +10605,7 @@
10347
10605
  bw.patchAll = function (patches) {
10348
10606
  var results = {};
10349
10607
  for (var id in patches) {
10350
- if (Object.prototype.hasOwnProperty.call(patches, id)) {
10608
+ if (_hop.call(patches, id)) {
10351
10609
  results[id] = bw.patch(id, patches[id]);
10352
10610
  }
10353
10611
  }
@@ -10444,7 +10702,7 @@
10444
10702
  snapshot[i].handler(detail);
10445
10703
  called++;
10446
10704
  } catch (err) {
10447
- console.warn('bw.pub: subscriber error on topic "' + topic + '":', err);
10705
+ _cw('bw.pub: subscriber error on topic "' + topic + '":', err);
10448
10706
  }
10449
10707
  }
10450
10708
  return called;
@@ -10545,8 +10803,8 @@
10545
10803
  * @see bw.funcGetDispatchStr
10546
10804
  */
10547
10805
  bw.funcRegister = function (fn, name) {
10548
- if (typeof fn !== 'function') return '';
10549
- var fnID = typeof name === 'string' && name.length > 0 ? name : 'bw_fn_' + bw._fnIDCounter++;
10806
+ if (!_is(fn, 'function')) return '';
10807
+ var fnID = _is(name, 'string') && name.length > 0 ? name : 'bw_fn_' + bw._fnIDCounter++;
10550
10808
  bw._fnRegistry[fnID] = fn;
10551
10809
  return fnID;
10552
10810
  };
@@ -10565,8 +10823,8 @@
10565
10823
  bw.funcGetById = function (name, errFn) {
10566
10824
  name = String(name);
10567
10825
  if (name in bw._fnRegistry) return bw._fnRegistry[name];
10568
- return typeof errFn === 'function' ? errFn : function () {
10569
- console.warn('bw.funcGetById: unregistered fn "' + name + '"');
10826
+ return _is(errFn, 'function') ? errFn : function () {
10827
+ _cw('bw.funcGetById: unregistered fn "' + name + '"');
10570
10828
  };
10571
10829
  };
10572
10830
 
@@ -10608,13 +10866,23 @@
10608
10866
  bw.funcGetRegistry = function () {
10609
10867
  var copy = {};
10610
10868
  for (var k in bw._fnRegistry) {
10611
- if (Object.prototype.hasOwnProperty.call(bw._fnRegistry, k)) {
10869
+ if (_hop.call(bw._fnRegistry, k)) {
10612
10870
  copy[k] = bw._fnRegistry[k];
10613
10871
  }
10614
10872
  }
10615
10873
  return copy;
10616
10874
  };
10617
10875
 
10876
+ /**
10877
+ * Minimal runtime shim for funcRegister dispatch in static HTML.
10878
+ * When embedded in a `<script>` tag, provides just enough infrastructure
10879
+ * for `bw.funcGetById()` calls to resolve. The actual function bodies
10880
+ * are emitted separately as `bw._fnRegistry['bw_fn_X'] = ...;` assignments.
10881
+ * @type {string}
10882
+ * @category Function Registry
10883
+ */
10884
+ bw._FUNC_REGISTRY_SHIM = '(function(){var bw=window.bw||(window.bw={});' + 'if(!bw._fnRegistry)bw._fnRegistry={};' + 'bw.funcGetById=function(n){return bw._fnRegistry[n]||function(){' + 'console.warn("bw: unregistered fn "+n)};};' + 'bw.funcRegister=function(fn,name){' + 'var id=name||("bw_fn_"+(bw._fnIDCounter=(bw._fnIDCounter||0)+1));' + 'bw._fnRegistry[id]=fn;return id;};' + 'window.bw=bw;})();';
10885
+
10618
10886
  // ===================================================================================
10619
10887
  // Template Binding Utilities
10620
10888
  // ===================================================================================
@@ -10646,7 +10914,10 @@
10646
10914
  var parts = path.split('.');
10647
10915
  var val = state;
10648
10916
  for (var i = 0; i < parts.length; i++) {
10649
- if (val == null) return '';
10917
+ if (val == null) {
10918
+ if (bw.debug) _cw('bw.debug: _evaluatePath — null at key "' + parts[i] + '" in path "' + path + '"');
10919
+ return '';
10920
+ }
10650
10921
  val = val[parts[i]];
10651
10922
  }
10652
10923
  return val == null ? '' : val;
@@ -10666,7 +10937,7 @@
10666
10937
  */
10667
10938
  bw._compiledExprs = {};
10668
10939
  bw._resolveTemplate = function (str, state, compile) {
10669
- if (typeof str !== 'string' || str.indexOf('${') < 0) return str;
10940
+ if (!_is(str, 'string') || str.indexOf('${') < 0) return str;
10670
10941
  var bindings = bw._parseBindings(str);
10671
10942
  if (bindings.length === 0) return str;
10672
10943
  var result = '';
@@ -10689,6 +10960,7 @@
10689
10960
  try {
10690
10961
  val = bw._compiledExprs[b.expr](state);
10691
10962
  } catch (e) {
10963
+ if (bw.debug) _cw('bw.debug: _resolveTemplate — Tier 2 eval failed for "${' + b.expr + '}":', e.message);
10692
10964
  val = '';
10693
10965
  }
10694
10966
  } else {
@@ -10796,7 +11068,7 @@
10796
11068
  this._state = {};
10797
11069
  if (o.state) {
10798
11070
  for (var k in o.state) {
10799
- if (Object.prototype.hasOwnProperty.call(o.state, k)) {
11071
+ if (_hop.call(o.state, k)) {
10800
11072
  this._state[k] = o.state[k];
10801
11073
  }
10802
11074
  }
@@ -10805,7 +11077,7 @@
10805
11077
  this._actions = {};
10806
11078
  if (o.actions) {
10807
11079
  for (var k2 in o.actions) {
10808
- if (Object.prototype.hasOwnProperty.call(o.actions, k2)) {
11080
+ if (_hop.call(o.actions, k2)) {
10809
11081
  this._actions[k2] = o.actions[k2];
10810
11082
  }
10811
11083
  }
@@ -10815,7 +11087,7 @@
10815
11087
  if (o.methods) {
10816
11088
  var self = this;
10817
11089
  for (var k3 in o.methods) {
10818
- if (Object.prototype.hasOwnProperty.call(o.methods, k3)) {
11090
+ if (_hop.call(o.methods, k3)) {
10819
11091
  this._methods[k3] = o.methods[k3];
10820
11092
  (function (methodName, methodFn) {
10821
11093
  self[methodName] = function () {
@@ -10848,14 +11120,23 @@
10848
11120
  this._compile = !!o.compile;
10849
11121
  this._bw_refs = {};
10850
11122
  this._refCounter = 0;
11123
+ // Child component ownership (Bug #5)
11124
+ this._children = [];
11125
+ this._parent = null;
11126
+ // Factory metadata for BCCL rebuild (Bug #6)
11127
+ this._factory = taco._bwFactory || null;
10851
11128
  }
10852
11129
 
11130
+ // Short alias for ComponentHandle.prototype (see alias block at top of file).
11131
+ // 28 method definitions × 25 chars = ~700B raw savings in minified output.
11132
+ var _chp = ComponentHandle.prototype;
11133
+
10853
11134
  // ── State Methods ──
10854
11135
 
10855
11136
  /**
10856
11137
  * Get a state value. Dot-path supported: `get('user.name')`
10857
11138
  */
10858
- ComponentHandle.prototype.get = function (key) {
11139
+ _chp.get = function (key) {
10859
11140
  return bw._evaluatePath(this._state, key);
10860
11141
  };
10861
11142
 
@@ -10865,12 +11146,13 @@
10865
11146
  * @param {*} value - New value
10866
11147
  * @param {Object} [opts] - Options. `{sync: true}` for immediate flush.
10867
11148
  */
10868
- ComponentHandle.prototype.set = function (key, value, opts) {
11149
+ _chp.set = function (key, value, opts) {
10869
11150
  // Dot-path set
10870
11151
  var parts = key.split('.');
10871
11152
  var obj = this._state;
10872
11153
  for (var i = 0; i < parts.length - 1; i++) {
10873
- if (obj[parts[i]] == null || _typeof(obj[parts[i]]) !== 'object') {
11154
+ if (!_is(obj[parts[i]], 'object')) {
11155
+ if (bw.debug) _cw('bw.debug: set() — auto-creating intermediate "' + parts[i] + '" in path "' + key + '"');
10874
11156
  obj[parts[i]] = {};
10875
11157
  }
10876
11158
  obj = obj[parts[i]];
@@ -10890,10 +11172,10 @@
10890
11172
  /**
10891
11173
  * Get a shallow clone of the full state.
10892
11174
  */
10893
- ComponentHandle.prototype.getState = function () {
11175
+ _chp.getState = function () {
10894
11176
  var clone = {};
10895
11177
  for (var k in this._state) {
10896
- if (Object.prototype.hasOwnProperty.call(this._state, k)) {
11178
+ if (_hop.call(this._state, k)) {
10897
11179
  clone[k] = this._state[k];
10898
11180
  }
10899
11181
  }
@@ -10905,9 +11187,9 @@
10905
11187
  * @param {Object} updates - Key-value pairs to merge
10906
11188
  * @param {Object} [opts] - Options. `{sync: true}` for immediate flush.
10907
11189
  */
10908
- ComponentHandle.prototype.setState = function (updates, opts) {
11190
+ _chp.setState = function (updates, opts) {
10909
11191
  for (var k in updates) {
10910
- if (Object.prototype.hasOwnProperty.call(updates, k)) {
11192
+ if (_hop.call(updates, k)) {
10911
11193
  this._state[k] = updates[k];
10912
11194
  this._dirtyKeys[k] = true;
10913
11195
  }
@@ -10924,9 +11206,9 @@
10924
11206
  /**
10925
11207
  * Push a value onto an array in state. Clones the array.
10926
11208
  */
10927
- ComponentHandle.prototype.push = function (key, val) {
11209
+ _chp.push = function (key, val) {
10928
11210
  var arr = this.get(key);
10929
- var newArr = Array.isArray(arr) ? arr.slice() : [];
11211
+ var newArr = _isA(arr) ? arr.slice() : [];
10930
11212
  newArr.push(val);
10931
11213
  this.set(key, newArr);
10932
11214
  };
@@ -10934,9 +11216,9 @@
10934
11216
  /**
10935
11217
  * Splice an array in state. Clones the array.
10936
11218
  */
10937
- ComponentHandle.prototype.splice = function (key, start, deleteCount) {
11219
+ _chp.splice = function (key, start, deleteCount) {
10938
11220
  var arr = this.get(key);
10939
- var newArr = Array.isArray(arr) ? arr.slice() : [];
11221
+ var newArr = _isA(arr) ? arr.slice() : [];
10940
11222
  var args = [start, deleteCount].concat(Array.prototype.slice.call(arguments, 3));
10941
11223
  Array.prototype.splice.apply(newArr, args);
10942
11224
  this.set(key, newArr);
@@ -10944,7 +11226,7 @@
10944
11226
 
10945
11227
  // ── Scheduling ──
10946
11228
 
10947
- ComponentHandle.prototype._scheduleDirty = function () {
11229
+ _chp._scheduleDirty = function () {
10948
11230
  if (!this._scheduled) {
10949
11231
  this._scheduled = true;
10950
11232
  bw._dirtyComponents.push(this);
@@ -10959,16 +11241,16 @@
10959
11241
  * Creates binding descriptors with refIds for targeted DOM updates.
10960
11242
  * @private
10961
11243
  */
10962
- ComponentHandle.prototype._compileBindings = function () {
11244
+ _chp._compileBindings = function () {
10963
11245
  this._bindings = [];
10964
11246
  this._refCounter = 0;
10965
- var stateKeys = Object.keys(this._state);
11247
+ var stateKeys = _keys(this._state);
10966
11248
  var self = this;
10967
11249
  function walkTaco(taco, path) {
10968
- if (taco == null || _typeof(taco) !== 'object' || !taco.t) return taco;
11250
+ if (!_is(taco, 'object') || !taco.t) return taco;
10969
11251
 
10970
11252
  // Check content for bindings
10971
- if (typeof taco.c === 'string' && taco.c.indexOf('${') >= 0) {
11253
+ if (_is(taco.c, 'string') && taco.c.indexOf('${') >= 0) {
10972
11254
  var refId = 'bw_ref_' + self._refCounter++;
10973
11255
  var parsed = bw._parseBindings(taco.c);
10974
11256
  var deps = [];
@@ -10990,10 +11272,10 @@
10990
11272
  // Check attributes for bindings
10991
11273
  if (taco.a) {
10992
11274
  for (var attrName in taco.a) {
10993
- if (!Object.prototype.hasOwnProperty.call(taco.a, attrName)) continue;
11275
+ if (!_hop.call(taco.a, attrName)) continue;
10994
11276
  if (attrName === 'data-bw_ref') continue;
10995
11277
  var attrVal = taco.a[attrName];
10996
- if (typeof attrVal === 'string' && attrVal.indexOf('${') >= 0) {
11278
+ if (_is(attrVal, 'string') && attrVal.indexOf('${') >= 0) {
10997
11279
  var refId2 = 'bw_ref_' + self._refCounter++;
10998
11280
  var parsed2 = bw._parseBindings(attrVal);
10999
11281
  var deps2 = [];
@@ -11019,9 +11301,34 @@
11019
11301
  }
11020
11302
 
11021
11303
  // Recurse into children
11022
- if (Array.isArray(taco.c)) {
11304
+ if (_isA(taco.c)) {
11023
11305
  for (var i = 0; i < taco.c.length; i++) {
11024
- if (taco.c[i] && _typeof(taco.c[i]) === 'object' && taco.c[i].t) {
11306
+ // Wrap string children with ${expr} in a span so patches target the span, not the parent
11307
+ if (_is(taco.c[i], 'string') && taco.c[i].indexOf('${') >= 0) {
11308
+ var mixedRefId = 'bw_ref_' + self._refCounter++;
11309
+ var mixedParsed = bw._parseBindings(taco.c[i]);
11310
+ var mixedDeps = [];
11311
+ for (var mi = 0; mi < mixedParsed.length; mi++) {
11312
+ mixedDeps = mixedDeps.concat(bw._extractDeps(mixedParsed[mi].expr, stateKeys));
11313
+ }
11314
+ self._bindings.push({
11315
+ expr: taco.c[i],
11316
+ type: 'content',
11317
+ refId: mixedRefId,
11318
+ deps: mixedDeps,
11319
+ template: taco.c[i]
11320
+ });
11321
+ // Replace string with a span wrapper so textContent targets the span only
11322
+ taco.c[i] = {
11323
+ t: 'span',
11324
+ a: {
11325
+ 'data-bw_ref': mixedRefId,
11326
+ style: 'display:contents'
11327
+ },
11328
+ c: taco.c[i]
11329
+ };
11330
+ }
11331
+ if (_is(taco.c[i], 'object') && taco.c[i].t) {
11025
11332
  walkTaco(taco.c[i], path.concat(i));
11026
11333
  }
11027
11334
  // Handle bw.when/bw.each markers
@@ -11056,7 +11363,7 @@
11056
11363
  taco.c[i]._refId = eachRefId;
11057
11364
  }
11058
11365
  }
11059
- } else if (taco.c && _typeof(taco.c) === 'object' && taco.c.t) {
11366
+ } else if (_is(taco.c, 'object') && taco.c.t) {
11060
11367
  walkTaco(taco.c, path.concat(0));
11061
11368
  }
11062
11369
  return taco;
@@ -11070,7 +11377,7 @@
11070
11377
  * Build ref map from the live DOM after createDOM.
11071
11378
  * @private
11072
11379
  */
11073
- ComponentHandle.prototype._collectRefs = function () {
11380
+ _chp._collectRefs = function () {
11074
11381
  this._bw_refs = {};
11075
11382
  if (!this.element) return;
11076
11383
  var els = this.element.querySelectorAll('[data-bw_ref]');
@@ -11091,7 +11398,7 @@
11091
11398
  * Creates DOM, compiles bindings, registers actions, and calls lifecycle hooks.
11092
11399
  * @param {Element} parentEl - DOM element to mount into
11093
11400
  */
11094
- ComponentHandle.prototype.mount = function (parentEl) {
11401
+ _chp.mount = function (parentEl) {
11095
11402
  // willMount hook
11096
11403
  if (this._hooks.willMount) this._hooks.willMount(this);
11097
11404
 
@@ -11113,7 +11420,7 @@
11113
11420
  // Register named actions in function registry
11114
11421
  var self = this;
11115
11422
  for (var actionName in this._actions) {
11116
- if (Object.prototype.hasOwnProperty.call(this._actions, actionName)) {
11423
+ if (_hop.call(this._actions, actionName)) {
11117
11424
  var registeredName = this._bwId + '_' + actionName;
11118
11425
  (function (aName) {
11119
11426
  bw.funcRegister(function (evt) {
@@ -11132,6 +11439,11 @@
11132
11439
  this.element = bw.createDOM(tacoForDOM);
11133
11440
  this.element._bwComponentHandle = this;
11134
11441
  this.element.setAttribute('data-bw_comp_id', this._bwId);
11442
+
11443
+ // Restore o.render from original TACO (stripped by _tacoForDOM)
11444
+ if (this.taco.o && this.taco.o.render) {
11445
+ this.element._bw_render = this.taco.o.render;
11446
+ }
11135
11447
  if (this._userTag) {
11136
11448
  this.element.classList.add(this._userTag);
11137
11449
  }
@@ -11146,6 +11458,16 @@
11146
11458
  this._resolveAndApplyAll();
11147
11459
  this.mounted = true;
11148
11460
 
11461
+ // Scan for child ComponentHandles and link parent/child (Bug #5)
11462
+ var childEls = this.element.querySelectorAll('[data-bw_comp_id]');
11463
+ for (var ci = 0; ci < childEls.length; ci++) {
11464
+ var ch = childEls[ci]._bwComponentHandle;
11465
+ if (ch && ch !== this && !ch._parent) {
11466
+ ch._parent = this;
11467
+ this._children.push(ch);
11468
+ }
11469
+ }
11470
+
11149
11471
  // mounted hook (backward compat: fn.length === 2 wraps (el, state))
11150
11472
  if (this._hooks.mounted) {
11151
11473
  if (this._hooks.mounted.length === 2) {
@@ -11154,15 +11476,20 @@
11154
11476
  this._hooks.mounted(this);
11155
11477
  }
11156
11478
  }
11479
+
11480
+ // Invoke o.render on initial mount (if present)
11481
+ if (this.element._bw_render) {
11482
+ this.element._bw_render(this.element, this._state);
11483
+ }
11157
11484
  };
11158
11485
 
11159
11486
  /**
11160
11487
  * Prepare TACO for initial render: resolve when/each markers.
11161
11488
  * @private
11162
11489
  */
11163
- ComponentHandle.prototype._prepareTaco = function (taco) {
11164
- if (!taco || _typeof(taco) !== 'object') return;
11165
- if (Array.isArray(taco.c)) {
11490
+ _chp._prepareTaco = function (taco) {
11491
+ if (!_is(taco, 'object')) return;
11492
+ if (_isA(taco.c)) {
11166
11493
  for (var i = taco.c.length - 1; i >= 0; i--) {
11167
11494
  var child = taco.c[i];
11168
11495
  if (child && child._bwWhen) {
@@ -11203,7 +11530,7 @@
11203
11530
  var eachExprStr = child.expr.replace(/^\$\{|\}$/g, '');
11204
11531
  var arr = bw._evaluatePath(this._state, eachExprStr);
11205
11532
  var items = [];
11206
- if (Array.isArray(arr)) {
11533
+ if (_isA(arr)) {
11207
11534
  for (var j = 0; j < arr.length; j++) {
11208
11535
  items.push(child.factory(arr[j], j));
11209
11536
  }
@@ -11217,11 +11544,11 @@
11217
11544
  c: items
11218
11545
  };
11219
11546
  }
11220
- if (taco.c[i] && _typeof(taco.c[i]) === 'object' && taco.c[i].t) {
11547
+ if (_is(taco.c[i], 'object') && taco.c[i].t) {
11221
11548
  this._prepareTaco(taco.c[i]);
11222
11549
  }
11223
11550
  }
11224
- } else if (taco.c && _typeof(taco.c) === 'object' && taco.c.t) {
11551
+ } else if (_is(taco.c, 'object') && taco.c.t) {
11225
11552
  this._prepareTaco(taco.c);
11226
11553
  }
11227
11554
  };
@@ -11230,12 +11557,12 @@
11230
11557
  * Wire action name strings (in onclick etc.) to dispatch function calls.
11231
11558
  * @private
11232
11559
  */
11233
- ComponentHandle.prototype._wireActions = function (taco) {
11234
- if (!taco || _typeof(taco) !== 'object' || !taco.t) return;
11560
+ _chp._wireActions = function (taco) {
11561
+ if (!_is(taco, 'object') || !taco.t) return;
11235
11562
  if (taco.a) {
11236
11563
  for (var key in taco.a) {
11237
- if (!Object.prototype.hasOwnProperty.call(taco.a, key)) continue;
11238
- if (key.startsWith('on') && typeof taco.a[key] === 'string') {
11564
+ if (!_hop.call(taco.a, key)) continue;
11565
+ if (key.startsWith('on') && _is(taco.a[key], 'string')) {
11239
11566
  var actionName = taco.a[key];
11240
11567
  if (actionName in this._actions) {
11241
11568
  var registeredName = this._bwId + '_' + actionName;
@@ -11249,11 +11576,11 @@
11249
11576
  }
11250
11577
  }
11251
11578
  }
11252
- if (Array.isArray(taco.c)) {
11579
+ if (_isA(taco.c)) {
11253
11580
  for (var i = 0; i < taco.c.length; i++) {
11254
11581
  this._wireActions(taco.c[i]);
11255
11582
  }
11256
- } else if (taco.c && _typeof(taco.c) === 'object' && taco.c.t) {
11583
+ } else if (_is(taco.c, 'object') && taco.c.t) {
11257
11584
  this._wireActions(taco.c);
11258
11585
  }
11259
11586
  };
@@ -11262,7 +11589,7 @@
11262
11589
  * Deep-clone a TACO tree, preserving _bwWhen/_bwEach markers and their factories.
11263
11590
  * @private
11264
11591
  */
11265
- ComponentHandle.prototype._deepCloneTaco = function (taco) {
11592
+ _chp._deepCloneTaco = function (taco) {
11266
11593
  if (taco == null) return taco;
11267
11594
  // Preserve _bwWhen / _bwEach markers (contain functions)
11268
11595
  if (taco._bwWhen) {
@@ -11281,22 +11608,22 @@
11281
11608
  _refId: taco._refId
11282
11609
  };
11283
11610
  }
11284
- if (_typeof(taco) !== 'object' || !taco.t) return taco;
11611
+ if (!_is(taco, 'object') || !taco.t) return taco;
11285
11612
  var result = {
11286
11613
  t: taco.t
11287
11614
  };
11288
11615
  if (taco.a) {
11289
11616
  result.a = {};
11290
11617
  for (var k in taco.a) {
11291
- if (Object.prototype.hasOwnProperty.call(taco.a, k)) result.a[k] = taco.a[k];
11618
+ if (_hop.call(taco.a, k)) result.a[k] = taco.a[k];
11292
11619
  }
11293
11620
  }
11294
11621
  if (taco.c != null) {
11295
- if (Array.isArray(taco.c)) {
11622
+ if (_isA(taco.c)) {
11296
11623
  result.c = taco.c.map(function (child) {
11297
11624
  return this._deepCloneTaco(child);
11298
11625
  }.bind(this));
11299
- } else if (_typeof(taco.c) === 'object') {
11626
+ } else if (_is(taco.c, 'object')) {
11300
11627
  result.c = this._deepCloneTaco(taco.c);
11301
11628
  } else {
11302
11629
  result.c = taco.c;
@@ -11310,31 +11637,34 @@
11310
11637
  * Create a copy of TACO suitable for createDOM (strips o to prevent double lifecycle).
11311
11638
  * @private
11312
11639
  */
11313
- ComponentHandle.prototype._tacoForDOM = function (taco) {
11314
- if (!taco || _typeof(taco) !== 'object' || !taco.t) return taco;
11640
+ _chp._tacoForDOM = function (taco) {
11641
+ if (!_is(taco, 'object') || !taco.t) return taco;
11315
11642
  var result = {
11316
11643
  t: taco.t
11317
11644
  };
11318
11645
  if (taco.a) result.a = taco.a;
11319
11646
  if (taco.c != null) {
11320
- if (Array.isArray(taco.c)) {
11647
+ if (_isA(taco.c)) {
11321
11648
  result.c = taco.c.map(function (child) {
11322
11649
  return this._tacoForDOM(child);
11323
11650
  }.bind(this));
11324
- } else if (_typeof(taco.c) === 'object' && taco.c.t) {
11651
+ } else if (_is(taco.c, 'object') && taco.c.t) {
11325
11652
  result.c = this._tacoForDOM(taco.c);
11326
11653
  } else {
11327
11654
  result.c = taco.c;
11328
11655
  }
11329
11656
  }
11330
11657
  // Intentionally strip o (no mounted/unmount/state/render on sub-elements)
11658
+ if (taco.o && (taco.o.mounted || taco.o.render || taco.o.unmount)) {
11659
+ _cw('bw: _tacoForDOM stripped o.mounted/render/unmount from child <' + taco.t + '>. Use onclick attribute or bw.component() for child interactivity.');
11660
+ }
11331
11661
  return result;
11332
11662
  };
11333
11663
 
11334
11664
  /**
11335
11665
  * Unmount: remove from DOM, deactivate, preserve state for re-mount.
11336
11666
  */
11337
- ComponentHandle.prototype.unmount = function () {
11667
+ _chp.unmount = function () {
11338
11668
  if (!this.mounted) return;
11339
11669
 
11340
11670
  // unmount hook
@@ -11368,11 +11698,22 @@
11368
11698
  /**
11369
11699
  * Destroy: unmount + clear state + unregister actions.
11370
11700
  */
11371
- ComponentHandle.prototype.destroy = function () {
11701
+ _chp.destroy = function () {
11372
11702
  // willDestroy hook
11373
11703
  if (this._hooks.willDestroy) {
11374
11704
  this._hooks.willDestroy(this);
11375
11705
  }
11706
+
11707
+ // Cascade destroy to children depth-first (Bug #5)
11708
+ for (var ci = this._children.length - 1; ci >= 0; ci--) {
11709
+ this._children[ci].destroy();
11710
+ }
11711
+ this._children = [];
11712
+ if (this._parent) {
11713
+ var idx = this._parent._children.indexOf(this);
11714
+ if (idx >= 0) this._parent._children.splice(idx, 1);
11715
+ this._parent = null;
11716
+ }
11376
11717
  this.unmount();
11377
11718
 
11378
11719
  // Unregister actions from function registry
@@ -11399,12 +11740,37 @@
11399
11740
  * Flush dirty state: resolve changed bindings and apply to DOM.
11400
11741
  * @private
11401
11742
  */
11402
- ComponentHandle.prototype._flush = function () {
11743
+ _chp._flush = function () {
11403
11744
  this._scheduled = false;
11404
- var changedKeys = Object.keys(this._dirtyKeys);
11745
+ var changedKeys = _keys(this._dirtyKeys);
11405
11746
  this._dirtyKeys = {};
11406
11747
  if (changedKeys.length === 0 || !this.mounted) return;
11407
11748
 
11749
+ // Factory rebuild: if a BCCL factory exists and changed keys overlap factory props,
11750
+ // rebuild the TACO from the factory with merged state (Bug #6)
11751
+ if (this._factory) {
11752
+ var rebuildNeeded = false;
11753
+ for (var fi = 0; fi < changedKeys.length; fi++) {
11754
+ if (_hop.call(this._factory.props, changedKeys[fi])) {
11755
+ rebuildNeeded = true;
11756
+ break;
11757
+ }
11758
+ }
11759
+ if (rebuildNeeded) {
11760
+ var merged = {};
11761
+ for (var mk in this._factory.props) if (_hop.call(this._factory.props, mk)) merged[mk] = this._factory.props[mk];
11762
+ for (var sk in this._state) if (_hop.call(this._state, sk)) merged[sk] = this._state[sk];
11763
+ this._factory.props = merged;
11764
+ var newTaco = bw.make(this._factory.type, merged);
11765
+ newTaco._bwFactory = this._factory;
11766
+ this.taco = newTaco;
11767
+ this._originalTaco = this._deepCloneTaco(newTaco);
11768
+ this._render();
11769
+ if (this._hooks.onUpdate) this._hooks.onUpdate(this, changedKeys);
11770
+ return;
11771
+ }
11772
+ }
11773
+
11408
11774
  // willUpdate hook
11409
11775
  if (this._hooks.willUpdate) {
11410
11776
  this._hooks.willUpdate(this, changedKeys);
@@ -11442,7 +11808,7 @@
11442
11808
  * Returns list of patches to apply.
11443
11809
  * @private
11444
11810
  */
11445
- ComponentHandle.prototype._resolveBindings = function (changedKeys) {
11811
+ _chp._resolveBindings = function (changedKeys) {
11446
11812
  var patches = [];
11447
11813
  for (var i = 0; i < this._bindings.length; i++) {
11448
11814
  var b = this._bindings[i];
@@ -11478,11 +11844,14 @@
11478
11844
  * Apply patches to DOM.
11479
11845
  * @private
11480
11846
  */
11481
- ComponentHandle.prototype._applyPatches = function (patches) {
11847
+ _chp._applyPatches = function (patches) {
11482
11848
  for (var i = 0; i < patches.length; i++) {
11483
11849
  var p = patches[i];
11484
11850
  var el = this._bw_refs[p.refId];
11485
- if (!el) continue;
11851
+ if (!el) {
11852
+ if (bw.debug) _cw('bw.debug: _applyPatches — ref "' + p.refId + '" not found in DOM');
11853
+ continue;
11854
+ }
11486
11855
  if (p.type === 'content') {
11487
11856
  el.textContent = p.value;
11488
11857
  } else if (p.type === 'attribute') {
@@ -11499,7 +11868,7 @@
11499
11868
  * Resolve all bindings and apply (used for initial render).
11500
11869
  * @private
11501
11870
  */
11502
- ComponentHandle.prototype._resolveAndApplyAll = function () {
11871
+ _chp._resolveAndApplyAll = function () {
11503
11872
  var patches = [];
11504
11873
  for (var i = 0; i < this._bindings.length; i++) {
11505
11874
  var b = this._bindings[i];
@@ -11521,7 +11890,7 @@
11521
11890
  * Full re-render for structural changes (when/each branch switches).
11522
11891
  * @private
11523
11892
  */
11524
- ComponentHandle.prototype._render = function () {
11893
+ _chp._render = function () {
11525
11894
  if (!this.element || !this.element.parentNode) return;
11526
11895
  var parent = this.element.parentNode;
11527
11896
  var nextSibling = this.element.nextSibling;
@@ -11560,7 +11929,7 @@
11560
11929
  * @param {string} event - Event name (e.g., 'click')
11561
11930
  * @param {Function} handler - Event handler
11562
11931
  */
11563
- ComponentHandle.prototype.on = function (event, handler) {
11932
+ _chp.on = function (event, handler) {
11564
11933
  if (this.element) {
11565
11934
  this.element.addEventListener(event, handler);
11566
11935
  }
@@ -11575,7 +11944,7 @@
11575
11944
  * @param {string} event - Event name
11576
11945
  * @param {Function} handler - Handler to remove
11577
11946
  */
11578
- ComponentHandle.prototype.off = function (event, handler) {
11947
+ _chp.off = function (event, handler) {
11579
11948
  if (this.element) {
11580
11949
  this.element.removeEventListener(event, handler);
11581
11950
  }
@@ -11590,7 +11959,7 @@
11590
11959
  * @param {Function} handler - Handler function
11591
11960
  * @returns {Function} Unsubscribe function
11592
11961
  */
11593
- ComponentHandle.prototype.sub = function (topic, handler) {
11962
+ _chp.sub = function (topic, handler) {
11594
11963
  var unsub = bw.sub(topic, handler);
11595
11964
  this._subs.push(unsub);
11596
11965
  return unsub;
@@ -11601,10 +11970,10 @@
11601
11970
  * @param {string} name - Action name
11602
11971
  * @param {...*} args - Arguments passed after comp
11603
11972
  */
11604
- ComponentHandle.prototype.action = function (name) {
11973
+ _chp.action = function (name) {
11605
11974
  var fn = this._actions[name];
11606
11975
  if (!fn) {
11607
- console.warn('ComponentHandle.action: unknown action "' + name + '"');
11976
+ _cw('ComponentHandle.action: unknown action "' + name + '"');
11608
11977
  return;
11609
11978
  }
11610
11979
  var args = [this].concat(Array.prototype.slice.call(arguments, 1));
@@ -11616,7 +11985,7 @@
11616
11985
  * @param {string} sel - CSS selector
11617
11986
  * @returns {Element|null}
11618
11987
  */
11619
- ComponentHandle.prototype.select = function (sel) {
11988
+ _chp.select = function (sel) {
11620
11989
  return this.element ? this.element.querySelector(sel) : null;
11621
11990
  };
11622
11991
 
@@ -11625,7 +11994,7 @@
11625
11994
  * @param {string} sel - CSS selector
11626
11995
  * @returns {Element[]}
11627
11996
  */
11628
- ComponentHandle.prototype.selectAll = function (sel) {
11997
+ _chp.selectAll = function (sel) {
11629
11998
  if (!this.element) return [];
11630
11999
  return Array.prototype.slice.call(this.element.querySelectorAll(sel));
11631
12000
  };
@@ -11636,7 +12005,7 @@
11636
12005
  * @param {string} tag - User-defined identifier (e.g. 'dashboard_prod_east')
11637
12006
  * @returns {ComponentHandle} this (for chaining)
11638
12007
  */
11639
- ComponentHandle.prototype.userTag = function (tag) {
12008
+ _chp.userTag = function (tag) {
11640
12009
  this._userTag = tag;
11641
12010
  if (this.element) {
11642
12011
  this.element.classList.add(tag);
@@ -11745,8 +12114,8 @@
11745
12114
  }
11746
12115
  if (!el || !el._bwComponentHandle) return false;
11747
12116
  var comp = el._bwComponentHandle;
11748
- if (typeof comp[action] !== 'function') {
11749
- console.warn('bw.message: unknown action "' + action + '" on component ' + target);
12117
+ if (!_is(comp[action], 'function')) {
12118
+ _cw('bw.message: unknown action "' + action + '" on component ' + target);
11750
12119
  return false;
11751
12120
  }
11752
12121
  comp[action](data);
@@ -11783,7 +12152,7 @@
11783
12152
  },
11784
12153
  focus: function focus(selector) {
11785
12154
  var el = bw._el(selector);
11786
- if (el && typeof el.focus === 'function') el.focus();
12155
+ if (el && _is(el.focus, 'function')) el.focus();
11787
12156
  },
11788
12157
  download: function download(filename, content, mimeType) {
11789
12158
  if (typeof document === 'undefined') return;
@@ -11938,11 +12307,11 @@
11938
12307
  } else if (type === 'remove') {
11939
12308
  var toRemove = bw._el(target);
11940
12309
  if (!toRemove) return false;
11941
- if (typeof bw.cleanup === 'function') bw.cleanup(toRemove);
12310
+ if (_is(bw.cleanup, 'function')) bw.cleanup(toRemove);
11942
12311
  toRemove.remove();
11943
12312
  return true;
11944
12313
  } else if (type === 'batch') {
11945
- if (!Array.isArray(msg.ops)) return false;
12314
+ if (!_isA(msg.ops)) return false;
11946
12315
  var allOk = true;
11947
12316
  msg.ops.forEach(function (op) {
11948
12317
  if (!bw.clientApply(op)) allOk = false;
@@ -11956,24 +12325,24 @@
11956
12325
  bw._clientFunctions[msg.name] = new Function('return ' + msg.body)();
11957
12326
  return true;
11958
12327
  } catch (e) {
11959
- console.error('[bw] register error:', msg.name, e);
12328
+ _ce('[bw] register error:', msg.name, e);
11960
12329
  return false;
11961
12330
  }
11962
12331
  } else if (type === 'call') {
11963
12332
  if (!msg.name) return false;
11964
12333
  var fn = bw._clientFunctions[msg.name] || bw._builtinClientFunctions[msg.name];
11965
- if (typeof fn !== 'function') return false;
12334
+ if (!_is(fn, 'function')) return false;
11966
12335
  try {
11967
- var args = Array.isArray(msg.args) ? msg.args : [];
12336
+ var args = _isA(msg.args) ? msg.args : [];
11968
12337
  fn.apply(null, args);
11969
12338
  return true;
11970
12339
  } catch (e) {
11971
- console.error('[bw] call error:', msg.name, e);
12340
+ _ce('[bw] call error:', msg.name, e);
11972
12341
  return false;
11973
12342
  }
11974
12343
  } else if (type === 'exec') {
11975
12344
  if (!bw._allowExec) {
11976
- console.warn('[bw] exec rejected: allowExec is not enabled');
12345
+ _cw('[bw] exec rejected: allowExec is not enabled');
11977
12346
  return false;
11978
12347
  }
11979
12348
  if (!msg.code) return false;
@@ -11981,7 +12350,7 @@
11981
12350
  new Function(msg.code)();
11982
12351
  return true;
11983
12352
  } catch (e) {
11984
- console.error('[bw] exec error:', e);
12353
+ _ce('[bw] exec error:', e);
11985
12354
  return false;
11986
12355
  }
11987
12356
  }
@@ -12026,7 +12395,7 @@
12026
12395
  }
12027
12396
  function handleMessage(data) {
12028
12397
  try {
12029
- var msg = typeof data === 'string' ? bw.clientParse(data) : data;
12398
+ var msg = _is(data, 'string') ? bw.clientParse(data) : data;
12030
12399
  if (onMessage) onMessage(msg);
12031
12400
  if (handlers.message) handlers.message(msg);
12032
12401
  bw.clientApply(msg);
@@ -12062,7 +12431,7 @@
12062
12431
  fetch(url).then(function (r) {
12063
12432
  return r.json();
12064
12433
  }).then(function (msgs) {
12065
- if (Array.isArray(msgs)) {
12434
+ if (_isA(msgs)) {
12066
12435
  msgs.forEach(handleMessage);
12067
12436
  } else if (msgs && msgs.type) {
12068
12437
  handleMessage(msgs);
@@ -12149,20 +12518,20 @@
12149
12518
  el = target.element;
12150
12519
  comp = target;
12151
12520
  } else {
12152
- if (typeof target === 'string') {
12521
+ if (_is(target, 'string')) {
12153
12522
  el = bw.$(target)[0];
12154
12523
  }
12155
12524
  if (!el) {
12156
- console.warn('bw.inspect: element not found');
12525
+ _cw('bw.inspect: element not found');
12157
12526
  return null;
12158
12527
  }
12159
12528
  comp = el._bwComponentHandle;
12160
12529
  }
12161
12530
  if (!comp) {
12162
- console.log('bw.inspect: no ComponentHandle on this element');
12163
- console.log(' Tag:', el.tagName);
12164
- console.log(' Classes:', el.className);
12165
- console.log(' _bw_state:', el._bw_state || '(none)');
12531
+ _cl('bw.inspect: no ComponentHandle on this element');
12532
+ _cl(' Tag:', el.tagName);
12533
+ _cl(' Classes:', el.className);
12534
+ _cl(' _bw_state:', el._bw_state || '(none)');
12166
12535
  return null;
12167
12536
  }
12168
12537
  var deps = comp._bindings.reduce(function (s, b) {
@@ -12171,13 +12540,13 @@
12171
12540
  return a.indexOf(v) === i;
12172
12541
  });
12173
12542
  console.group('Component: ' + comp._bwId);
12174
- console.log('State:', comp._state);
12175
- console.log('Bindings:', comp._bindings.length, '(deps:', deps, ')');
12176
- console.log('Methods:', Object.keys(comp._methods));
12177
- console.log('Actions:', Object.keys(comp._actions));
12178
- console.log('User tag:', comp._userTag || '(none)');
12179
- console.log('Mounted:', comp.mounted);
12180
- console.log('Element:', comp.element);
12543
+ _cl('State:', comp._state);
12544
+ _cl('Bindings:', comp._bindings.length, '(deps:', deps, ')');
12545
+ _cl('Methods:', _keys(comp._methods));
12546
+ _cl('Actions:', _keys(comp._actions));
12547
+ _cl('User tag:', comp._userTag || '(none)');
12548
+ _cl('Mounted:', comp.mounted);
12549
+ _cl('Element:', comp.element);
12181
12550
  console.groupEnd();
12182
12551
  return comp;
12183
12552
  };
@@ -12200,8 +12569,8 @@
12200
12569
  // Pre-extract all binding expressions
12201
12570
  var precompiled = [];
12202
12571
  function walkExpressions(node) {
12203
- if (!node || _typeof(node) !== 'object') return;
12204
- if (typeof node.c === 'string' && node.c.indexOf('${') >= 0) {
12572
+ if (!_is(node, 'object')) return;
12573
+ if (_is(node.c, 'string') && node.c.indexOf('${') >= 0) {
12205
12574
  var parsed = bw._parseBindings(node.c);
12206
12575
  for (var i = 0; i < parsed.length; i++) {
12207
12576
  try {
@@ -12221,9 +12590,9 @@
12221
12590
  }
12222
12591
  if (node.a) {
12223
12592
  for (var key in node.a) {
12224
- if (Object.prototype.hasOwnProperty.call(node.a, key)) {
12593
+ if (_hop.call(node.a, key)) {
12225
12594
  var v = node.a[key];
12226
- if (typeof v === 'string' && v.indexOf('${') >= 0) {
12595
+ if (_is(v, 'string') && v.indexOf('${') >= 0) {
12227
12596
  var parsed2 = bw._parseBindings(v);
12228
12597
  for (var j = 0; j < parsed2.length; j++) {
12229
12598
  try {
@@ -12244,9 +12613,9 @@
12244
12613
  }
12245
12614
  }
12246
12615
  }
12247
- if (Array.isArray(node.c)) {
12616
+ if (_isA(node.c)) {
12248
12617
  for (var k = 0; k < node.c.length; k++) walkExpressions(node.c[k]);
12249
- } else if (node.c && _typeof(node.c) === 'object' && node.c.t) {
12618
+ } else if (_is(node.c, 'object') && node.c.t) {
12250
12619
  walkExpressions(node.c);
12251
12620
  }
12252
12621
  }
@@ -12257,7 +12626,7 @@
12257
12626
  handle._precompiledBindings = precompiled;
12258
12627
  if (initialState) {
12259
12628
  for (var k in initialState) {
12260
- if (Object.prototype.hasOwnProperty.call(initialState, k)) {
12629
+ if (_hop.call(initialState, k)) {
12261
12630
  handle._state[k] = initialState[k];
12262
12631
  }
12263
12632
  }
@@ -12291,21 +12660,21 @@
12291
12660
  minify = _options$minify === void 0 ? false : _options$minify,
12292
12661
  _options$pretty = options.pretty,
12293
12662
  pretty = _options$pretty === void 0 ? !minify : _options$pretty;
12294
- if (typeof rules === 'string') return rules;
12663
+ if (_is(rules, 'string')) return rules;
12295
12664
  var css = '';
12296
12665
  var indent = pretty ? ' ' : '';
12297
12666
  var newline = pretty ? '\n' : '';
12298
12667
  var space = pretty ? ' ' : '';
12299
- if (Array.isArray(rules)) {
12668
+ if (_isA(rules)) {
12300
12669
  css = rules.map(function (rule) {
12301
12670
  return bw.css(rule, options);
12302
12671
  }).join(newline);
12303
- } else if (_typeof(rules) === 'object') {
12672
+ } else if (_is(rules, 'object')) {
12304
12673
  Object.entries(rules).forEach(function (_ref5) {
12305
12674
  var _ref6 = _slicedToArray(_ref5, 2),
12306
12675
  selector = _ref6[0],
12307
12676
  styles = _ref6[1];
12308
- if (_typeof(styles) === 'object' && !Array.isArray(styles)) {
12677
+ if (_is(styles, 'object')) {
12309
12678
  // Handle @media, @keyframes, @supports — recurse into nested block
12310
12679
  if (selector.charAt(0) === '@') {
12311
12680
  var inner = bw.css(styles, options);
@@ -12359,7 +12728,7 @@
12359
12728
  bw.injectCSS = function (css) {
12360
12729
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
12361
12730
  if (!bw._isBrowser) {
12362
- console.warn('bw.injectCSS requires a DOM environment');
12731
+ _cw('bw.injectCSS requires a DOM environment');
12363
12732
  return null;
12364
12733
  }
12365
12734
  var _options$id = options.id,
@@ -12377,7 +12746,7 @@
12377
12746
  }
12378
12747
 
12379
12748
  // Convert CSS if needed
12380
- var cssStr = typeof css === 'string' ? css : bw.css(css, options);
12749
+ var cssStr = _is(css, 'string') ? css : bw.css(css, options);
12381
12750
 
12382
12751
  // Set or append CSS
12383
12752
  if (append && styleEl.textContent) {
@@ -12406,7 +12775,7 @@
12406
12775
  var result = {};
12407
12776
  for (var i = 0; i < arguments.length; i++) {
12408
12777
  var arg = arguments[i];
12409
- if (arg && _typeof(arg) === 'object') Object.assign(result, arg);
12778
+ if (_is(arg, 'object')) Object.assign(result, arg);
12410
12779
  }
12411
12780
  return result;
12412
12781
  };
@@ -12651,7 +13020,7 @@
12651
13020
  xl: '1200px'
12652
13021
  };
12653
13022
  var parts = [];
12654
- Object.keys(breakpoints).forEach(function (key) {
13023
+ _keys(breakpoints).forEach(function (key) {
12655
13024
  var rules = {};
12656
13025
  if (key === 'base') {
12657
13026
  rules[selector] = breakpoints[key];
@@ -12723,18 +13092,18 @@
12723
13092
  if (!selector) return [];
12724
13093
 
12725
13094
  // Already an array
12726
- if (Array.isArray(selector)) return selector;
13095
+ if (_isA(selector)) return selector;
12727
13096
 
12728
13097
  // Single element
12729
13098
  if (selector.nodeType) return [selector];
12730
13099
 
12731
13100
  // NodeList or HTMLCollection
12732
- if (selector.length !== undefined && typeof selector !== 'string') {
13101
+ if (selector.length !== undefined && !_is(selector, 'string')) {
12733
13102
  return Array.from(selector);
12734
13103
  }
12735
13104
 
12736
13105
  // CSS selector string
12737
- if (typeof selector === 'string') {
13106
+ if (_is(selector, 'string')) {
12738
13107
  return Array.from(document.querySelectorAll(selector));
12739
13108
  }
12740
13109
  return [];
@@ -13252,7 +13621,7 @@
13252
13621
  cls = cls.trim();
13253
13622
 
13254
13623
  // Auto-detect columns if not provided
13255
- var cols = columns || (data.length > 0 ? Object.keys(data[0]).map(function (key) {
13624
+ var cols = columns || (data.length > 0 ? _keys(data[0]).map(function (key) {
13256
13625
  return {
13257
13626
  key: key,
13258
13627
  label: key
@@ -13271,7 +13640,7 @@
13271
13640
  var bVal = b[currentSortColumn];
13272
13641
 
13273
13642
  // Handle different types
13274
- if (typeof aVal === 'number' && typeof bVal === 'number') {
13643
+ if (_is(aVal, 'number') && _is(bVal, 'number')) {
13275
13644
  return currentSortDirection === 'asc' ? aVal - bVal : bVal - aVal;
13276
13645
  }
13277
13646
 
@@ -13395,7 +13764,7 @@
13395
13764
  headerRow = _config$headerRow === void 0 ? true : _config$headerRow,
13396
13765
  columns = config.columns,
13397
13766
  rest = _objectWithoutProperties(config, _excluded);
13398
- if (!Array.isArray(data) || data.length === 0) {
13767
+ if (!_isA(data) || data.length === 0) {
13399
13768
  return bw.makeTable(_objectSpread2({
13400
13769
  data: [],
13401
13770
  columns: columns || []
@@ -13492,7 +13861,7 @@
13492
13861
  showLabels = _config$showLabels === void 0 ? true : _config$showLabels,
13493
13862
  _config$className2 = config.className,
13494
13863
  className = _config$className2 === void 0 ? '' : _config$className2;
13495
- if (!Array.isArray(data) || data.length === 0) {
13864
+ if (!_isA(data) || data.length === 0) {
13496
13865
  return {
13497
13866
  t: 'div',
13498
13867
  a: {
@@ -13675,7 +14044,7 @@
13675
14044
  bw.render = function (element, position, taco) {
13676
14045
  var _taco$o4, _taco$o5, _taco$o6;
13677
14046
  // Get target element
13678
- var targetEl = typeof element === 'string' ? document.querySelector(element) : element;
14047
+ var targetEl = _is(element, 'string') ? document.querySelector(element) : element;
13679
14048
  if (!targetEl) {
13680
14049
  return {
13681
14050
  object_type: 'error',
@@ -13813,7 +14182,7 @@
13813
14182
  setContent: function setContent(content) {
13814
14183
  this._taco.c = content;
13815
14184
  if (this.element) {
13816
- if (typeof content === 'string') {
14185
+ if (_is(content, 'string')) {
13817
14186
  this.element.textContent = content;
13818
14187
  } else {
13819
14188
  // Re-render for complex content