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.
- package/dist/bitwrench-bccl.cjs.js +6 -2
- package/dist/bitwrench-bccl.cjs.min.js +3 -3
- package/dist/bitwrench-bccl.esm.js +6 -2
- package/dist/bitwrench-bccl.esm.min.js +3 -3
- package/dist/bitwrench-bccl.umd.js +6 -2
- package/dist/bitwrench-bccl.umd.min.js +2 -2
- package/dist/bitwrench-code-edit.cjs.js +1 -1
- package/dist/bitwrench-code-edit.cjs.min.js +1 -1
- package/dist/bitwrench-code-edit.es5.js +1 -1
- package/dist/bitwrench-code-edit.es5.min.js +1 -1
- package/dist/bitwrench-code-edit.esm.js +1 -1
- package/dist/bitwrench-code-edit.esm.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js +1 -1
- package/dist/bitwrench-lean.cjs.js +506 -154
- package/dist/bitwrench-lean.cjs.min.js +7 -7
- package/dist/bitwrench-lean.es5.js +517 -155
- package/dist/bitwrench-lean.es5.min.js +5 -5
- package/dist/bitwrench-lean.esm.js +505 -154
- package/dist/bitwrench-lean.esm.min.js +6 -6
- package/dist/bitwrench-lean.umd.js +506 -154
- package/dist/bitwrench-lean.umd.min.js +7 -7
- package/dist/bitwrench.cjs.js +511 -155
- package/dist/bitwrench.cjs.min.js +8 -8
- package/dist/bitwrench.es5.js +525 -156
- package/dist/bitwrench.es5.min.js +6 -6
- package/dist/bitwrench.esm.js +510 -155
- package/dist/bitwrench.esm.min.js +8 -8
- package/dist/bitwrench.umd.js +511 -155
- package/dist/bitwrench.umd.min.js +8 -8
- package/dist/builds.json +82 -82
- package/dist/bwserve.cjs.js +16 -2
- package/dist/bwserve.esm.js +16 -2
- package/dist/sri.json +34 -34
- package/package.json +4 -2
- package/readme.html +1 -1
- package/src/bitwrench-bccl.js +5 -1
- package/src/bitwrench.js +502 -151
- package/src/bwserve/index.js +12 -1
- package/src/bwserve/shell.js +3 -0
- package/src/cli/layout-default.js +47 -32
- package/src/version.js +3 -3
package/dist/bitwrench.es5.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
/*! bitwrench v2.0.
|
|
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.
|
|
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-
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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
|
* // => '<b>Hello</b> & "world"'
|
|
9486
9564
|
*/
|
|
9487
9565
|
bw.escapeHTML = function (str) {
|
|
9488
|
-
if (
|
|
9566
|
+
if (!_is(str, 'string')) return '';
|
|
9489
9567
|
var escapeMap = {
|
|
9490
9568
|
'&': '&',
|
|
9491
9569
|
'<': '<',
|
|
@@ -9562,7 +9640,7 @@
|
|
|
9562
9640
|
}
|
|
9563
9641
|
|
|
9564
9642
|
// Handle arrays of TACOs
|
|
9565
|
-
if (
|
|
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 (!
|
|
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 (
|
|
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 &&
|
|
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
|
-
//
|
|
9624
|
-
if (key.startsWith('on'))
|
|
9625
|
-
|
|
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 =
|
|
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 &&
|
|
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
|
+
'&': '&',
|
|
9898
|
+
'<': '<',
|
|
9899
|
+
'>': '>',
|
|
9900
|
+
'"': '"',
|
|
9901
|
+
"'": '''
|
|
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 (
|
|
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' &&
|
|
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 =
|
|
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') &&
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
10549
|
-
var fnID =
|
|
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
|
|
10569
|
-
|
|
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 (
|
|
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)
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
11175
|
+
_chp.getState = function () {
|
|
10894
11176
|
var clone = {};
|
|
10895
11177
|
for (var k in this._state) {
|
|
10896
|
-
if (
|
|
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
|
-
|
|
11190
|
+
_chp.setState = function (updates, opts) {
|
|
10909
11191
|
for (var k in updates) {
|
|
10910
|
-
if (
|
|
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
|
-
|
|
11209
|
+
_chp.push = function (key, val) {
|
|
10928
11210
|
var arr = this.get(key);
|
|
10929
|
-
var newArr =
|
|
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
|
-
|
|
11219
|
+
_chp.splice = function (key, start, deleteCount) {
|
|
10938
11220
|
var arr = this.get(key);
|
|
10939
|
-
var newArr =
|
|
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
|
-
|
|
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
|
-
|
|
11244
|
+
_chp._compileBindings = function () {
|
|
10963
11245
|
this._bindings = [];
|
|
10964
11246
|
this._refCounter = 0;
|
|
10965
|
-
var stateKeys =
|
|
11247
|
+
var stateKeys = _keys(this._state);
|
|
10966
11248
|
var self = this;
|
|
10967
11249
|
function walkTaco(taco, path) {
|
|
10968
|
-
if (
|
|
11250
|
+
if (!_is(taco, 'object') || !taco.t) return taco;
|
|
10969
11251
|
|
|
10970
11252
|
// Check content for bindings
|
|
10971
|
-
if (
|
|
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 (!
|
|
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 (
|
|
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 (
|
|
11304
|
+
if (_isA(taco.c)) {
|
|
11023
11305
|
for (var i = 0; i < taco.c.length; i++) {
|
|
11024
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
11164
|
-
if (!
|
|
11165
|
-
if (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
11234
|
-
if (!
|
|
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 (!
|
|
11238
|
-
if (key.startsWith('on') &&
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
11314
|
-
if (!
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11743
|
+
_chp._flush = function () {
|
|
11403
11744
|
this._scheduled = false;
|
|
11404
|
-
var changedKeys =
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
11973
|
+
_chp.action = function (name) {
|
|
11605
11974
|
var fn = this._actions[name];
|
|
11606
11975
|
if (!fn) {
|
|
11607
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
11749
|
-
|
|
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 &&
|
|
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 (
|
|
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 (!
|
|
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
|
-
|
|
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 (
|
|
12334
|
+
if (!_is(fn, 'function')) return false;
|
|
11966
12335
|
try {
|
|
11967
|
-
var args =
|
|
12336
|
+
var args = _isA(msg.args) ? msg.args : [];
|
|
11968
12337
|
fn.apply(null, args);
|
|
11969
12338
|
return true;
|
|
11970
12339
|
} catch (e) {
|
|
11971
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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 (
|
|
12521
|
+
if (_is(target, 'string')) {
|
|
12153
12522
|
el = bw.$(target)[0];
|
|
12154
12523
|
}
|
|
12155
12524
|
if (!el) {
|
|
12156
|
-
|
|
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
|
-
|
|
12163
|
-
|
|
12164
|
-
|
|
12165
|
-
|
|
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
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
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 (!
|
|
12204
|
-
if (
|
|
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 (
|
|
12593
|
+
if (_hop.call(node.a, key)) {
|
|
12225
12594
|
var v = node.a[key];
|
|
12226
|
-
if (
|
|
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 (
|
|
12616
|
+
if (_isA(node.c)) {
|
|
12248
12617
|
for (var k = 0; k < node.c.length; k++) walkExpressions(node.c[k]);
|
|
12249
|
-
} else if (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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 &&
|
|
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 (
|
|
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 ?
|
|
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 (
|
|
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 (!
|
|
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 (!
|
|
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 =
|
|
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 (
|
|
14185
|
+
if (_is(content, 'string')) {
|
|
13817
14186
|
this.element.textContent = content;
|
|
13818
14187
|
} else {
|
|
13819
14188
|
// Re-render for complex content
|