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