essor 0.0.13 → 0.0.14-beta.11

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.
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  /**
4
- * essor v0.0.13
4
+ * essor v0.0.14-beta.11
5
5
  * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
6
6
  * @license MIT
7
7
  **/
8
8
 
9
9
  // src/version.ts
10
- var essor_version = "0.0.13";
10
+ var essor_version = "0.0.14-beta.11";
11
11
 
12
12
  // ../shared/dist/shared.js
13
13
  var isObject = (val) => val !== null && typeof val === "object";
@@ -15,9 +15,6 @@ var isArray = Array.isArray;
15
15
  function isString(val) {
16
16
  return typeof val === "string";
17
17
  }
18
- function isNull(val) {
19
- return val === null;
20
- }
21
18
  function isSymbol(val) {
22
19
  return typeof val === "symbol";
23
20
  }
@@ -40,7 +37,10 @@ var isFunction = (val) => typeof val === "function";
40
37
  function isFalsy(x) {
41
38
  return x === false || x === null || x === void 0;
42
39
  }
43
- var isPrimitive = (val) => ["string", "number", "boolean", "symbol", "undefined"].includes(typeof val) || isNull(val);
40
+ function isHTMLElement(obj) {
41
+ if (!obj) return false;
42
+ return obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string";
43
+ }
44
44
  var isPlainObject = (val) => _toString.call(val) === "[object Object]";
45
45
  function isStringNumber(val) {
46
46
  if (!isString(val)) {
@@ -83,14 +83,22 @@ function escape(str) {
83
83
  function isExclude(key, exclude) {
84
84
  return isArray(exclude) ? exclude.includes(key) : isFunction(exclude) ? exclude(key) : false;
85
85
  }
86
- var kebabCase = (string) => {
87
- return string.replaceAll(/[A-Z]+/g, (match, offset) => {
88
- return `${offset > 0 ? "-" : ""}${match.toLocaleLowerCase()}`;
89
- });
90
- };
91
- var capitalizeFirstLetter = (inputString) => {
92
- return inputString.charAt(0).toUpperCase() + inputString.slice(1);
86
+ var cacheStringFunction = (fn) => {
87
+ const cache = /* @__PURE__ */ Object.create(null);
88
+ return (str) => {
89
+ const hit = cache[str];
90
+ return hit || (cache[str] = fn(str));
91
+ };
93
92
  };
93
+ var hyphenateRE = /\B([A-Z])/g;
94
+ var kebabCase = cacheStringFunction(
95
+ (str) => str.replaceAll(hyphenateRE, "-$1").toLowerCase()
96
+ );
97
+ var capitalize = cacheStringFunction(
98
+ (str) => {
99
+ return str.charAt(0).toUpperCase() + str.slice(1);
100
+ }
101
+ );
94
102
  function warn(msg, ...args) {
95
103
  console.warn.apply(console, [`[Essor warn]: ${msg}`].concat(args));
96
104
  }
@@ -248,6 +256,9 @@ var Signal = class {
248
256
  trigger(this, SignalValueKey);
249
257
  }
250
258
  }
259
+ trigger() {
260
+ trigger(this, SignalValueKey);
261
+ }
251
262
  /**
252
263
  * Returns the current value without triggering reactivity.
253
264
  * @returns {T} The current value.
@@ -262,9 +273,6 @@ function useSignal(value) {
262
273
  }
263
274
  return new Signal(value);
264
275
  }
265
- function useShallowSignal(value) {
266
- return new Signal(value, true);
267
- }
268
276
  function shallowSignal(value) {
269
277
  return new Signal(value, true);
270
278
  }
@@ -709,7 +717,7 @@ function queueWatcher(fn) {
709
717
  }
710
718
  }
711
719
  function flushWatchers() {
712
- watcher == null ? void 0 : watcher();
720
+ watcher && watcher();
713
721
  watcher = null;
714
722
  flushing = false;
715
723
  }
@@ -904,32 +912,27 @@ var CHILDREN_PROP = "children";
904
912
  var EMPTY_TEMPLATE = "";
905
913
  var FRAGMENT_PROP_KEY = "0";
906
914
  var SINGLE_PROP_KEY = "1";
915
+ var REF_KEY = "ref";
907
916
  var PLACEHOLDER = " __PLACEHOLDER__ ";
908
917
  var RenderContext = class {
909
918
  constructor() {
910
919
  this.renderMode = 0;
911
920
  }
912
- // Getter to check if the current mode is SSG
913
921
  get isSSG() {
914
922
  return this.renderMode === 1;
915
923
  }
916
- // Getter to check if the current mode is SSR
917
924
  get isSSR() {
918
925
  return this.renderMode === 2;
919
926
  }
920
- // Getter to check if the current mode is Client
921
927
  get isClient() {
922
928
  return this.renderMode === 0;
923
929
  }
924
- // Set render mode to SSR
925
930
  setSSR() {
926
931
  this.renderMode = 2;
927
932
  }
928
- // Set render mode to SSG
929
933
  setSSG() {
930
934
  this.renderMode = 1;
931
935
  }
932
- // Set render mode to Client
933
936
  setClient() {
934
937
  this.renderMode = 0;
935
938
  }
@@ -969,11 +972,9 @@ var _LifecycleContext = class _LifecycleContext2 {
969
972
  setContext(context, value) {
970
973
  _LifecycleContext2.context[context] = value;
971
974
  }
972
- // Initialize the static reference
973
975
  initRef() {
974
976
  _LifecycleContext2.ref = this;
975
977
  }
976
- // Remove the static reference
977
978
  removeRef() {
978
979
  _LifecycleContext2.ref = null;
979
980
  }
@@ -998,7 +999,6 @@ var SSGNode = class extends LifecycleContext {
998
999
  enterComponent(template, componentIndex);
999
1000
  this.templates = this.processTemplate();
1000
1001
  }
1001
- // Process the template and return an array of processed strings
1002
1002
  processTemplate() {
1003
1003
  if (isArray(this.template)) {
1004
1004
  const htmlString = this.template.join(PLACEHOLDER);
@@ -1007,7 +1007,6 @@ var SSGNode = class extends LifecycleContext {
1007
1007
  }
1008
1008
  return [];
1009
1009
  }
1010
- // Process HTML string by adding component index and handling text nodes
1011
1010
  processHtmlString(htmlString) {
1012
1011
  return htmlString.replaceAll(/(<[^>]+>)|([^<]+)/g, (match, p1, p2) => {
1013
1012
  if (p1) {
@@ -1021,14 +1020,12 @@ var SSGNode = class extends LifecycleContext {
1021
1020
  return match;
1022
1021
  });
1023
1022
  }
1024
- // Mount the SSGNode and return the rendered string
1025
1023
  mount() {
1026
1024
  this.initRef();
1027
1025
  const output = this.render();
1028
1026
  this.removeRef();
1029
1027
  return output;
1030
1028
  }
1031
- // Render the SSGNode
1032
1029
  render() {
1033
1030
  if (isFunction(this.template)) {
1034
1031
  const root = this.template(this.props);
@@ -1040,7 +1037,6 @@ var SSGNode = class extends LifecycleContext {
1040
1037
  }
1041
1038
  return this.renderTemplate();
1042
1039
  }
1043
- // Render the template by processing props and children
1044
1040
  renderTemplate() {
1045
1041
  Object.entries(this.props).forEach(([key, cur]) => {
1046
1042
  const children = cur.children;
@@ -1056,10 +1052,9 @@ var SSGNode = class extends LifecycleContext {
1056
1052
  });
1057
1053
  return this.templates.join("");
1058
1054
  }
1059
- // Normalize props by removing children and handling signals
1060
1055
  normalizeProps(props) {
1061
1056
  Object.entries(props).forEach(([key, value]) => {
1062
- if (key === "children") {
1057
+ if (key === CHILDREN_PROP) {
1063
1058
  delete props[key];
1064
1059
  } else if (isFunction(value)) {
1065
1060
  delete props[key];
@@ -1068,11 +1063,9 @@ var SSGNode = class extends LifecycleContext {
1068
1063
  }
1069
1064
  });
1070
1065
  }
1071
- // Generate HTML attributes string from props
1072
1066
  generateAttributes(props) {
1073
- return Object.entries(props).filter(([key, value]) => key !== "children" && !isFunction(value)).map(([key, value]) => `${key}="${escape(String(value))}"`).join(" ");
1067
+ return Object.entries(props).filter(([key, value]) => key !== CHILDREN_PROP && !isFunction(value)).map(([key, value]) => `${key}="${escape(String(value))}"`).join(" ");
1074
1068
  }
1075
- // Render children and append them to the template
1076
1069
  renderChildren(children, findIndex) {
1077
1070
  children.forEach(([child]) => {
1078
1071
  componentIndex++;
@@ -1080,7 +1073,6 @@ var SSGNode = class extends LifecycleContext {
1080
1073
  this.templates[findIndex] += renderedChild;
1081
1074
  });
1082
1075
  }
1083
- // Render a single child node
1084
1076
  renderChild(child) {
1085
1077
  if (isFunction(child)) {
1086
1078
  return this.renderChild(child(this.props));
@@ -1095,9 +1087,6 @@ var SSGNode = class extends LifecycleContext {
1095
1087
  }
1096
1088
  };
1097
1089
  var SELF_CLOSING_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr".split(",");
1098
- var HTML_TAGS = "a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,body,br,button,canvas,caption,center,cite,code,col,colgroup,command,content,data,datalist,dd,del,details,dfn,dialog,dir,div,dl,dt,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,image,img,input,ins,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,menu,menuitem,meta,meter,nav,nobr,noframes,noscript,object,ol,optgroup,option,output,p,param,picture,plaintext,pre,progress,q,rb,rp,rt,rtc,ruby,s,samp,script,section,select,shadow,small,source,spacer,span,strike,strong,style,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,tt,u,ul,var,video,wbr,xmp".split(
1099
- ","
1100
- );
1101
1090
  function coerceNode(data) {
1102
1091
  if (isJsxElement(data) || data instanceof Node || isSSGNode(data)) {
1103
1092
  return data;
@@ -1214,12 +1203,14 @@ function bindNode(node, setter) {
1214
1203
  });
1215
1204
  }
1216
1205
  }
1217
- Promise.resolve();
1218
1206
  function addEventListener(node, eventName, handler) {
1219
1207
  node.addEventListener(eventName, handler);
1220
1208
  return () => node.removeEventListener(eventName, handler);
1221
1209
  }
1222
1210
  function closeHtmlTags(input) {
1211
+ if (!input) {
1212
+ return input;
1213
+ }
1223
1214
  const tagStack = [];
1224
1215
  const output = [];
1225
1216
  const tagPattern = /<\/?([\da-z-]+)([^>]*)>/gi;
@@ -1255,9 +1246,6 @@ function closeHtmlTags(input) {
1255
1246
  }
1256
1247
  return output.join("");
1257
1248
  }
1258
- function isHtmlTagName(tagName) {
1259
- return HTML_TAGS.includes(tagName);
1260
- }
1261
1249
  function convertToHtmlTag(tagName) {
1262
1250
  return SELF_CLOSING_TAGS.includes(tagName) ? `<${tagName}/>` : `<${tagName}></${tagName}>`;
1263
1251
  }
@@ -1277,28 +1265,24 @@ var ComponentNode = class extends LifecycleContext {
1277
1265
  this.emitter = /* @__PURE__ */ new Set();
1278
1266
  this.rootNode = null;
1279
1267
  this.trackMap = /* @__PURE__ */ new Map();
1280
- this.key || (this.key = props == null ? void 0 : props.key);
1268
+ this.key || (this.key = props && props.key);
1281
1269
  this.proxyProps = this.createProxyProps(props);
1282
1270
  }
1283
- // Create reactive props
1284
1271
  createProxyProps(props) {
1285
1272
  if (!props) return {};
1286
- return useReactive(
1273
+ return signalObject(
1287
1274
  props,
1288
1275
  (key) => startsWith(key, EVENT_PREFIX) || startsWith(key, UPDATE_PREFIX) || key === CHILDREN_PROP
1289
1276
  );
1290
1277
  }
1291
- // Getter for the first child node
1292
1278
  get firstChild() {
1293
1279
  var _a, _b;
1294
1280
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.firstChild) != null ? _b : null;
1295
1281
  }
1296
- // Getter to check if the node is connected to the DOM
1297
1282
  get isConnected() {
1298
1283
  var _a, _b;
1299
1284
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.isConnected) != null ? _b : false;
1300
1285
  }
1301
- // Method to mount the component to the DOM
1302
1286
  mount(parent, before) {
1303
1287
  var _a, _b, _c, _d;
1304
1288
  if (!isFunction(this.template)) {
@@ -1308,14 +1292,13 @@ var ComponentNode = class extends LifecycleContext {
1308
1292
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.mount(parent, before)) != null ? _b : [];
1309
1293
  }
1310
1294
  this.initRef();
1311
- this.rootNode = this.template(this.proxyProps);
1295
+ this.rootNode = this.template(useReactive(this.proxyProps, [CHILDREN_PROP]));
1312
1296
  const mountedNode = (_d = (_c = this.rootNode) == null ? void 0 : _c.mount(parent, before)) != null ? _d : [];
1313
1297
  this.callMountHooks();
1314
1298
  this.patchProps(this.props);
1315
1299
  this.removeRef();
1316
1300
  return mountedNode;
1317
1301
  }
1318
- // Method to unmount the component from the DOM
1319
1302
  unmount() {
1320
1303
  var _a;
1321
1304
  this.callDestroyHooks();
@@ -1325,22 +1308,18 @@ var ComponentNode = class extends LifecycleContext {
1325
1308
  this.proxyProps = {};
1326
1309
  this.clearEmitter();
1327
1310
  }
1328
- // Private method to call mount hooks
1329
1311
  callMountHooks() {
1330
1312
  this.hooks.mounted.forEach((handler) => handler());
1331
1313
  }
1332
- // Private method to call destroy hooks
1333
1314
  callDestroyHooks() {
1334
1315
  this.hooks.destroy.forEach((handler) => handler());
1335
1316
  }
1336
- // Private method to clear the event emitter
1337
1317
  clearEmitter() {
1338
1318
  for (const cleanup of this.emitter) {
1339
1319
  cleanup();
1340
1320
  }
1341
1321
  this.emitter.clear();
1342
1322
  }
1343
- // Method to inherit properties from another ComponentNode
1344
1323
  inheritNode(node) {
1345
1324
  Object.assign(this.proxyProps, node.proxyProps);
1346
1325
  this.rootNode = node.rootNode;
@@ -1350,7 +1329,6 @@ var ComponentNode = class extends LifecycleContext {
1350
1329
  this.props = node.props;
1351
1330
  this.patchProps(props);
1352
1331
  }
1353
- // Private method to get or create a NodeTrack
1354
1332
  getNodeTrack(trackKey) {
1355
1333
  let track2 = this.trackMap.get(trackKey);
1356
1334
  if (!track2) {
@@ -1361,7 +1339,6 @@ var ComponentNode = class extends LifecycleContext {
1361
1339
  track2.cleanup();
1362
1340
  return track2;
1363
1341
  }
1364
- // Method to patch props onto the component
1365
1342
  patchProps(props) {
1366
1343
  var _a;
1367
1344
  if (!props) {
@@ -1370,7 +1347,7 @@ var ComponentNode = class extends LifecycleContext {
1370
1347
  for (const [key, prop] of Object.entries(props)) {
1371
1348
  if (startsWith(key, EVENT_PREFIX) && ((_a = this.rootNode) == null ? void 0 : _a.firstChild)) {
1372
1349
  this.patchEventListener(key, prop);
1373
- } else if (key === "ref") {
1350
+ } else if (key === REF_KEY) {
1374
1351
  this.patchRef(prop);
1375
1352
  } else if (startsWith(key, UPDATE_PREFIX)) {
1376
1353
  this.patchUpdateHandler(key, prop);
@@ -1380,26 +1357,24 @@ var ComponentNode = class extends LifecycleContext {
1380
1357
  }
1381
1358
  this.props = props;
1382
1359
  }
1383
- // Private method to patch event listeners
1384
1360
  patchEventListener(key, prop) {
1385
1361
  const event = key.slice(2).toLowerCase();
1386
1362
  const cleanup = addEventListener(this.rootNode.nodes[0], event, prop);
1387
1363
  this.emitter.add(cleanup);
1388
1364
  }
1389
- // Private method to patch ref
1390
1365
  patchRef(prop) {
1391
1366
  var _a, _b;
1392
1367
  prop.value = (_b = (_a = this.rootNode) == null ? void 0 : _a.firstChild) != null ? _b : null;
1393
1368
  }
1394
- // Private method to patch update handlers
1395
1369
  patchUpdateHandler(key, prop) {
1396
1370
  this.props[key] = extractSignal(prop);
1397
1371
  }
1398
- // Private method to patch normal props
1399
1372
  patchNormalProp(key, prop) {
1373
+ var _a, _b;
1374
+ const newValue = (_b = (_a = this.proxyProps)[key]) != null ? _b : _a[key] = useSignal(prop);
1400
1375
  const track2 = this.getNodeTrack(key);
1401
1376
  track2.cleanup = useEffect(() => {
1402
- this.proxyProps[key] = isFunction(prop) ? prop() : prop;
1377
+ newValue.value = isFunction(prop) ? prop() : prop;
1403
1378
  });
1404
1379
  }
1405
1380
  };
@@ -1519,26 +1494,21 @@ var TemplateNode = class {
1519
1494
  this.trackMap = /* @__PURE__ */ new Map();
1520
1495
  this.bindValueKeys = [];
1521
1496
  this.parent = null;
1522
- this.key || (this.key = props == null ? void 0 : props.key);
1523
1497
  if (renderContext.isSSR) {
1524
1498
  this.componentIndex = getComponentIndex(this.template);
1525
1499
  }
1526
1500
  }
1527
- // Getter for the first child node
1528
1501
  get firstChild() {
1529
1502
  var _a;
1530
1503
  return (_a = this.nodes[0]) != null ? _a : null;
1531
1504
  }
1532
- // Getter to check if the node is connected to the DOM
1533
1505
  get isConnected() {
1534
1506
  return this.mounted;
1535
1507
  }
1536
- // Placeholder methods for event handling
1537
1508
  addEventListener() {
1538
1509
  }
1539
1510
  removeEventListener() {
1540
1511
  }
1541
- // Method to mount the node to the DOM
1542
1512
  mount(parent, before) {
1543
1513
  var _a;
1544
1514
  this.parent = parent;
@@ -1553,7 +1523,7 @@ var TemplateNode = class {
1553
1523
  const firstChild = cloneNode.firstChild;
1554
1524
  if ((_a = firstChild == null ? void 0 : firstChild.hasAttribute) == null ? void 0 : _a.call(firstChild, "_svg_")) {
1555
1525
  firstChild.remove();
1556
- firstChild == null ? void 0 : firstChild.childNodes.forEach((node) => {
1526
+ firstChild.childNodes.forEach((node) => {
1557
1527
  cloneNode.append(node);
1558
1528
  });
1559
1529
  }
@@ -1568,45 +1538,16 @@ var TemplateNode = class {
1568
1538
  this.mounted = true;
1569
1539
  return this.nodes;
1570
1540
  }
1571
- // Method to unmount the node from the DOM
1572
1541
  unmount() {
1573
- var _a, _b;
1574
1542
  this.trackMap.forEach((track2) => {
1575
- var _a2;
1576
- (_a2 = track2.cleanup) == null ? void 0 : _a2.call(track2);
1543
+ track2.cleanup && track2.cleanup();
1577
1544
  });
1578
1545
  this.trackMap.clear();
1579
1546
  this.treeMap.clear();
1580
1547
  this.nodes.forEach((node) => removeChild(node));
1581
- if (!this.template.innerHTML && !this.nodes.length) {
1582
- const children = (_b = (_a = this.props) == null ? void 0 : _a[FRAGMENT_PROP_KEY]) == null ? void 0 : _b.children;
1583
- if (children) {
1584
- if (isArray(children)) {
1585
- children.forEach((child) => {
1586
- this.deleteFragmentTextNode(child);
1587
- });
1588
- } else {
1589
- this.deleteFragmentTextNode(children);
1590
- }
1591
- }
1592
- }
1593
1548
  this.nodes = [];
1594
1549
  this.mounted = false;
1595
1550
  }
1596
- deleteFragmentTextNode(child) {
1597
- var _a;
1598
- if (isPrimitive(child)) {
1599
- (_a = this.parent) == null ? void 0 : _a.childNodes.forEach((node) => {
1600
- var _a2;
1601
- if (node.nodeType === Node.TEXT_NODE && node.textContent === `${child}`) {
1602
- (_a2 = this.parent) == null ? void 0 : _a2.removeChild(node);
1603
- }
1604
- });
1605
- } else {
1606
- removeChild(child);
1607
- }
1608
- }
1609
- // Method to inherit properties from another TemplateNode
1610
1551
  inheritNode(node) {
1611
1552
  this.mounted = node.mounted;
1612
1553
  this.nodes = node.nodes;
@@ -1616,12 +1557,11 @@ var TemplateNode = class {
1616
1557
  this.props = node.props;
1617
1558
  this.patchProps(props);
1618
1559
  }
1619
- // Private method to map SSG node tree
1620
1560
  mapSSGNodeTree(parent) {
1621
1561
  this.treeMap.set(0, parent);
1622
1562
  this.walkNodeTree(parent, this.handleSSGNode.bind(this));
1623
1563
  }
1624
- // Private method to map node tree
1564
+ // protected method to map node tree
1625
1565
  mapNodeTree(parent, tree) {
1626
1566
  let index = 1;
1627
1567
  this.treeMap.set(0, parent);
@@ -1632,7 +1572,6 @@ var TemplateNode = class {
1632
1572
  };
1633
1573
  this.walkNodeTree(tree, handleNode);
1634
1574
  }
1635
- // Private method to walk through the node tree
1636
1575
  walkNodeTree(node, handler) {
1637
1576
  if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
1638
1577
  handler(node);
@@ -1643,7 +1582,6 @@ var TemplateNode = class {
1643
1582
  child = child.nextSibling;
1644
1583
  }
1645
1584
  }
1646
- // Private method to handle SSG nodes
1647
1585
  handleSSGNode(node) {
1648
1586
  var _a;
1649
1587
  if (node.nodeType === Node.COMMENT_NODE) {
@@ -1659,7 +1597,6 @@ var TemplateNode = class {
1659
1597
  }
1660
1598
  }
1661
1599
  }
1662
- // Method to patch props onto the node
1663
1600
  patchProps(props) {
1664
1601
  if (!props) return;
1665
1602
  Object.entries(props).forEach(([key, value]) => {
@@ -1671,22 +1608,29 @@ var TemplateNode = class {
1671
1608
  });
1672
1609
  this.props = props;
1673
1610
  }
1674
- // Private method to patch a single prop
1675
1611
  patchProp(key, node, props, isRoot) {
1676
1612
  if (!props) return;
1677
1613
  Object.entries(props).forEach(([attr, value]) => {
1678
1614
  if (attr === CHILDREN_PROP && value) {
1679
1615
  this.patchChildren(key, node, value, isRoot);
1680
- } else if (attr === "ref") {
1616
+ } else if (attr === REF_KEY) {
1681
1617
  props[attr].value = node;
1682
- } else if (startsWith(attr, "on")) {
1618
+ } else if (startsWith(attr, EVENT_PREFIX)) {
1683
1619
  this.patchEventListener(key, node, attr, value);
1684
1620
  } else {
1685
- this.patchAttribute(key, node, attr, value);
1621
+ if (this.bindValueKeys.includes(attr)) return;
1622
+ const updateFn = this.getBindUpdateValue(props, key, attr);
1623
+ this.patchAttribute(key, node, attr, value, updateFn);
1686
1624
  }
1687
1625
  });
1688
1626
  }
1689
- // Private method to patch children
1627
+ getBindUpdateValue(props, key, attr) {
1628
+ const updateKey = `${UPDATE_PREFIX}${capitalize(attr)}`;
1629
+ if (updateKey && props[updateKey] && isFunction(props[updateKey])) {
1630
+ this.bindValueKeys.push(updateKey);
1631
+ return props[updateKey];
1632
+ }
1633
+ }
1690
1634
  patchChildren(key, node, children, isRoot) {
1691
1635
  if (!isArray(children)) {
1692
1636
  const trackKey = `${key}:${CHILDREN_PROP}:0`;
@@ -1703,34 +1647,27 @@ var TemplateNode = class {
1703
1647
  });
1704
1648
  }
1705
1649
  }
1706
- // Private method to patch event listeners
1707
1650
  patchEventListener(key, node, attr, listener) {
1708
1651
  const eventName = attr.slice(2).toLowerCase();
1709
1652
  const track2 = this.getNodeTrack(`${key}:${attr}`);
1710
1653
  track2.cleanup = addEventListener(node, eventName, listener);
1711
1654
  }
1712
- // Private method to patch attributes
1713
- patchAttribute(key, element, attr, value) {
1714
- var _a, _b;
1715
- const updateKey = `update${capitalizeFirstLetter(attr)}`;
1716
- if (this.bindValueKeys.includes(attr)) {
1717
- return;
1718
- }
1719
- if ((_a = this.props) == null ? void 0 : _a[updateKey]) {
1720
- this.bindValueKeys.push(updateKey);
1721
- }
1655
+ patchAttribute(key, element, attr, value, updateFn) {
1722
1656
  const track2 = this.getNodeTrack(`${key}:${attr}`);
1723
- const triggerValue = isSignal(value) ? value : useSignal(value);
1657
+ const val = isFunction(value) ? value() : value;
1658
+ const triggerValue = isSignal(val) ? val : shallowSignal(val);
1724
1659
  setAttribute(element, attr, triggerValue.value);
1725
1660
  const cleanup = useEffect(() => {
1726
- triggerValue.value = isSignal(value) ? value.value : value;
1661
+ const val2 = isFunction(value) ? value() : value;
1662
+ if (isPlainObject(val2) && isPlainObject(triggerValue.peek()) && JSON.stringify(triggerValue.value) === JSON.stringify(val2))
1663
+ return;
1664
+ triggerValue.value = isSignal(val2) ? val2.value : val2;
1727
1665
  setAttribute(element, attr, triggerValue.value);
1728
1666
  });
1729
1667
  let cleanupBind;
1730
- if (((_b = this.props) == null ? void 0 : _b[updateKey]) && !isComponent(attr)) {
1668
+ if (updateFn && isHTMLElement(element)) {
1731
1669
  cleanupBind = bindNode(element, (value2) => {
1732
- var _a2;
1733
- (_a2 = this.props) == null ? void 0 : _a2[updateKey](value2);
1670
+ updateFn(value2);
1734
1671
  });
1735
1672
  }
1736
1673
  track2.cleanup = () => {
@@ -1738,9 +1675,7 @@ var TemplateNode = class {
1738
1675
  cleanupBind && cleanupBind();
1739
1676
  };
1740
1677
  }
1741
- // Private method to get or create a NodeTrack
1742
1678
  getNodeTrack(trackKey, trackLastNodes, isRoot) {
1743
- var _a;
1744
1679
  let track2 = this.trackMap.get(trackKey);
1745
1680
  if (!track2) {
1746
1681
  track2 = { cleanup: () => {
@@ -1753,10 +1688,9 @@ var TemplateNode = class {
1753
1688
  }
1754
1689
  this.trackMap.set(trackKey, track2);
1755
1690
  }
1756
- (_a = track2.cleanup) == null ? void 0 : _a.call(track2);
1691
+ track2.cleanup && track2.cleanup();
1757
1692
  return track2;
1758
1693
  }
1759
- // Private method to patch a child node
1760
1694
  patchChild(track2, parent, child, before) {
1761
1695
  if (isFunction(child)) {
1762
1696
  track2.cleanup = useEffect(() => {
@@ -1780,7 +1714,6 @@ var TemplateNode = class {
1780
1714
  });
1781
1715
  }
1782
1716
  }
1783
- // Private method to reconcile children nodes
1784
1717
  reconcileChildren(parent, nextNodes, before) {
1785
1718
  const result = /* @__PURE__ */ new Map();
1786
1719
  const textNodes = Array.from(parent.childNodes).filter(
@@ -1805,18 +1738,38 @@ var TemplateNode = class {
1805
1738
  return result;
1806
1739
  }
1807
1740
  };
1741
+ var FragmentNode = class extends TemplateNode {
1742
+ unmount() {
1743
+ this.trackMap.forEach((track2) => {
1744
+ if (track2.lastNodes) {
1745
+ track2.lastNodes.forEach((node) => {
1746
+ removeChild(node);
1747
+ });
1748
+ }
1749
+ track2.cleanup && track2.cleanup();
1750
+ });
1751
+ this.trackMap.clear();
1752
+ this.treeMap.clear();
1753
+ this.nodes.forEach((node) => {
1754
+ removeChild(node);
1755
+ });
1756
+ this.nodes = [];
1757
+ this.mounted = false;
1758
+ }
1759
+ };
1808
1760
  function h(template, props, key) {
1761
+ if (template === EMPTY_TEMPLATE) {
1762
+ return Fragment(template, props);
1763
+ }
1809
1764
  if (isString(template)) {
1810
- if (isHtmlTagName(template)) {
1811
- const htmlTemplate = convertToHtmlTag(template);
1812
- props = { [SINGLE_PROP_KEY]: props };
1813
- return new TemplateNode(createTemplate(htmlTemplate), props, key);
1814
- } else if (template === EMPTY_TEMPLATE) {
1815
- props = { [FRAGMENT_PROP_KEY]: props };
1816
- return new TemplateNode(createTemplate(EMPTY_TEMPLATE), props, key);
1817
- }
1765
+ const htmlTemplate = convertToHtmlTag(template);
1766
+ props = { [SINGLE_PROP_KEY]: props };
1767
+ return new TemplateNode(createTemplate(htmlTemplate), props, key);
1768
+ }
1769
+ if (isFunction(template)) {
1770
+ return new ComponentNode(template, props, key);
1818
1771
  }
1819
- return isFunction(template) ? new ComponentNode(template, props, key) : new TemplateNode(template, props, key);
1772
+ return new TemplateNode(template, props, key);
1820
1773
  }
1821
1774
  function isComponent(node) {
1822
1775
  return node instanceof ComponentNode;
@@ -1829,10 +1782,18 @@ function createTemplate(html) {
1829
1782
  template.innerHTML = closeHtmlTags(html);
1830
1783
  return template;
1831
1784
  }
1832
- function Fragment(props) {
1833
- return h(EMPTY_TEMPLATE, {
1834
- children: isArray(props.children) ? props.children.filter(Boolean) : [props.children]
1835
- });
1785
+ function Fragment(template, props) {
1786
+ if (props.children) {
1787
+ props = {
1788
+ [FRAGMENT_PROP_KEY]: {
1789
+ children: isArray(props.children) ? props.children.filter(Boolean) : [props.children]
1790
+ }
1791
+ };
1792
+ }
1793
+ if (template === EMPTY_TEMPLATE) {
1794
+ template = createTemplate(EMPTY_TEMPLATE);
1795
+ }
1796
+ return new FragmentNode(template, props);
1836
1797
  }
1837
1798
  function onMount(cb) {
1838
1799
  assertInsideComponent("onMounted");
@@ -1890,12 +1851,12 @@ if (globalThis) {
1890
1851
  globalThis.__essor_version__ = essor_version;
1891
1852
  }
1892
1853
  /**
1893
- * @estjs/signal v0.0.13
1854
+ * @estjs/signal v0.0.14-beta.11
1894
1855
  * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
1895
1856
  * @license MIT
1896
1857
  **/
1897
1858
  /**
1898
- * @estjs/template v0.0.13
1859
+ * @estjs/template v0.0.14-beta.11
1899
1860
  * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
1900
1861
  * @license MIT
1901
1862
  **/
@@ -1911,6 +1872,7 @@ exports.isComputed = isComputed;
1911
1872
  exports.isJsxElement = isJsxElement;
1912
1873
  exports.isReactive = isReactive;
1913
1874
  exports.isSignal = isSignal;
1875
+ exports.nextTick = nextTick;
1914
1876
  exports.onDestroy = onDestroy;
1915
1877
  exports.onMount = onMount;
1916
1878
  exports.renderToString = renderToString;
@@ -1927,6 +1889,5 @@ exports.useInject = useInject;
1927
1889
  exports.useProvide = useProvide;
1928
1890
  exports.useReactive = useReactive;
1929
1891
  exports.useRef = useRef;
1930
- exports.useShallowSignal = useShallowSignal;
1931
1892
  exports.useSignal = useSignal;
1932
1893
  exports.useWatch = useWatch;