essor 0.0.14-beta.2 → 0.0.14-beta.21

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.14-beta.2
4
+ * essor v0.0.14-beta.21
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.14-beta.2";
10
+ var essor_version = "0.0.14-beta.21";
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,6 @@ 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);
44
40
  function isHTMLElement(obj) {
45
41
  if (!obj) return false;
46
42
  return obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string";
@@ -87,14 +83,22 @@ function escape(str) {
87
83
  function isExclude(key, exclude) {
88
84
  return isArray(exclude) ? exclude.includes(key) : isFunction(exclude) ? exclude(key) : false;
89
85
  }
90
- var kebabCase = (string) => {
91
- return string.replaceAll(/[A-Z]+/g, (match, offset) => {
92
- return `${offset > 0 ? "-" : ""}${match.toLocaleLowerCase()}`;
93
- });
94
- };
95
- var capitalizeFirstLetter = (inputString) => {
96
- 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
+ };
97
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
+ );
98
102
  function warn(msg, ...args) {
99
103
  console.warn.apply(console, [`[Essor warn]: ${msg}`].concat(args));
100
104
  }
@@ -166,14 +170,14 @@ function flushPreFlushCbs() {
166
170
  }
167
171
  }
168
172
  }
169
- function createScheduler(effect, flush) {
173
+ function createScheduler(effect2, flush) {
170
174
  if (flush === "sync") {
171
- return () => effect();
175
+ return () => effect2();
172
176
  } else if (flush === "pre") {
173
- return () => queuePreFlushCb(effect);
177
+ return () => queuePreFlushCb(effect2);
174
178
  } else {
175
179
  return () => {
176
- nextTick(() => queueJob(effect));
180
+ nextTick(() => queueJob(effect2));
177
181
  };
178
182
  }
179
183
  }
@@ -208,22 +212,31 @@ function trigger(target, key) {
208
212
  if (!depsMap) return;
209
213
  const dep = depsMap.get(key);
210
214
  if (dep) {
211
- dep.forEach((effect) => {
212
- if (hasOwn(effect, "active") && !effect.active) {
213
- dep.delete(effect);
215
+ dep.forEach((effect2) => {
216
+ if (hasOwn(effect2, "active") && !effect2.active) {
217
+ dep.delete(effect2);
214
218
  return;
215
219
  }
216
- inBatch ? batchQueue.add(effect) : effect();
220
+ inBatch ? batchQueue.add(effect2) : effect2();
217
221
  });
218
222
  }
219
223
  }
220
- var Signal = class {
224
+ var FunctionExt = class extends Function {
225
+ constructor(f) {
226
+ super();
227
+ return Object.setPrototypeOf(f, new.target.prototype);
228
+ }
229
+ };
230
+ var SignalImpl = class extends FunctionExt {
221
231
  /**
222
232
  * Creates a new Signal instance.
223
233
  * @param {T} value - The initial value of the Signal.
224
234
  * @param {boolean} [shallow] - Whether to create a shallow Signal.
225
235
  */
226
236
  constructor(value, shallow = false) {
237
+ super(() => {
238
+ return this.value;
239
+ });
227
240
  this.__signal = true;
228
241
  this.__shallow = shallow;
229
242
  this.__value = value;
@@ -234,8 +247,8 @@ var Signal = class {
234
247
  */
235
248
  get value() {
236
249
  track(this, SignalValueKey);
237
- if (isObject(this.__value) && !this.__shallow) {
238
- return reactive(this.__value);
250
+ if (isObject(this.__value)) {
251
+ return ReactiveImpl(this.__value, this.__shallow);
239
252
  }
240
253
  return this.__value;
241
254
  }
@@ -259,23 +272,30 @@ var Signal = class {
259
272
  peek() {
260
273
  return this.__value;
261
274
  }
275
+ // call set value
276
+ // it equals to this.value = value
277
+ set(value) {
278
+ this.value = value;
279
+ }
280
+ // call update
281
+ // it equals to this.value = fn(this.value)
282
+ update(fn) {
283
+ this.set(fn(this.peek()));
284
+ }
262
285
  };
263
- function useSignal(value) {
286
+ function signal(value) {
264
287
  if (isSignal(value)) {
265
288
  return value;
266
289
  }
267
- return new Signal(value);
268
- }
269
- function useShallowSignal(value) {
270
- return new Signal(value, true);
290
+ return new SignalImpl(value);
271
291
  }
272
292
  function shallowSignal(value) {
273
- return new Signal(value, true);
293
+ return new SignalImpl(value, true);
274
294
  }
275
295
  function isSignal(value) {
276
296
  return !!(value && (value == null ? void 0 : value.__signal));
277
297
  }
278
- var Computed = class {
298
+ var ComputedImpl = class {
279
299
  constructor(fn) {
280
300
  this.fn = fn;
281
301
  this.__computed = true;
@@ -308,13 +328,13 @@ var Computed = class {
308
328
  return this.__value;
309
329
  }
310
330
  };
311
- function useComputed(fn) {
312
- return new Computed(fn);
331
+ function computed(fn) {
332
+ return new ComputedImpl(fn);
313
333
  }
314
334
  function isComputed(value) {
315
335
  return !!(value && value.__computed);
316
336
  }
317
- function useEffect(fn, options = {}) {
337
+ function effect(fn, options = {}) {
318
338
  const { flush = "pre", onTrack, onTrigger } = options;
319
339
  function effectFn() {
320
340
  const prev = activeEffect;
@@ -342,7 +362,7 @@ function signalObject(initialValues, exclude) {
342
362
  return initialValues;
343
363
  }
344
364
  const signals = Object.entries(initialValues).reduce((acc, [key, value]) => {
345
- acc[key] = isExclude(key, exclude) || isSignal(value) ? value : useSignal(value);
365
+ acc[key] = isExclude(key, exclude) || isSignal(value) ? value : signal(value);
346
366
  return acc;
347
367
  }, {});
348
368
  return signals;
@@ -368,11 +388,11 @@ function toRaw(value) {
368
388
  function isReactive(obj) {
369
389
  return !!(obj && typeof obj === "object" && obj[ReactiveSymbol]);
370
390
  }
371
- function useReactive(initialValue, exclude) {
372
- return reactive(initialValue, false, exclude);
391
+ function reactive(initialValue, exclude) {
392
+ return ReactiveImpl(initialValue, false, exclude);
373
393
  }
374
394
  function shallowReactive(initialValue, exclude) {
375
- return reactive(initialValue, true, exclude);
395
+ return ReactiveImpl(initialValue, true, exclude);
376
396
  }
377
397
  var basicHandler = (shallow, exclude) => {
378
398
  return {
@@ -386,7 +406,7 @@ var basicHandler = (shallow, exclude) => {
386
406
  }
387
407
  track(target, key);
388
408
  if (isObject(value) && !shallow) {
389
- return reactive(value);
409
+ return ReactiveImpl(value);
390
410
  }
391
411
  return value;
392
412
  },
@@ -484,7 +504,7 @@ var ArrayHandler = (shallow, exclude) => {
484
504
  }
485
505
  track(target, "length");
486
506
  if (isObject(value) && !shallow) {
487
- return reactive(value);
507
+ return ReactiveImpl(value);
488
508
  }
489
509
  return value;
490
510
  },
@@ -632,7 +652,7 @@ var weakInstrumentations = {
632
652
  return result;
633
653
  }
634
654
  };
635
- function reactive(initialValue, shallow = false, exclude) {
655
+ function ReactiveImpl(initialValue, shallow = false, exclude) {
636
656
  if (!isObject(initialValue)) {
637
657
  return initialValue;
638
658
  }
@@ -695,11 +715,14 @@ function useBatch(fn) {
695
715
  }
696
716
  function runBatch() {
697
717
  if (batchQueue.size > 0) {
698
- batchQueue.forEach((effect) => effect());
718
+ batchQueue.forEach((effect2) => effect2());
699
719
  batchQueue.clear();
700
720
  }
701
721
  }
702
- function useWatch(source, cb, options) {
722
+ function ref() {
723
+ return shallowSignal(null);
724
+ }
725
+ function watch(source, cb, options) {
703
726
  return doWatch(source, cb, options);
704
727
  }
705
728
  var INITIAL_WATCHER_VALUE = void 0;
@@ -713,7 +736,7 @@ function queueWatcher(fn) {
713
736
  }
714
737
  }
715
738
  function flushWatchers() {
716
- watcher == null ? void 0 : watcher();
739
+ watcher && watcher();
717
740
  watcher = null;
718
741
  flushing = false;
719
742
  }
@@ -755,7 +778,7 @@ function doWatch(source, cb, { deep, immediate } = {}) {
755
778
  !runCb && (oldValue = newValue);
756
779
  }
757
780
  };
758
- const stop = useEffect(effectFn, { flush: "sync" });
781
+ const stop = effect(effectFn, { flush: "sync" });
759
782
  runCb = true;
760
783
  if (immediate) {
761
784
  effectFn();
@@ -799,7 +822,7 @@ function traverse(value, depth = Infinity, seen) {
799
822
  function createOptionsStore(options) {
800
823
  const { state, getters, actions } = options;
801
824
  const initState = __spreadValues({}, state);
802
- const reactiveState = useReactive(state);
825
+ const reactiveState = reactive(state);
803
826
  const subscriptions = [];
804
827
  const actionCallbacks = [];
805
828
  const default_actions = {
@@ -833,7 +856,7 @@ function createOptionsStore(options) {
833
856
  if (getter) {
834
857
  Object.defineProperty(store, key, {
835
858
  get() {
836
- return useComputed(() => getter.call(store, reactiveState)).value;
859
+ return computed(() => getter.call(store, reactiveState)).value;
837
860
  },
838
861
  enumerable: true,
839
862
  configurable: true
@@ -908,32 +931,27 @@ var CHILDREN_PROP = "children";
908
931
  var EMPTY_TEMPLATE = "";
909
932
  var FRAGMENT_PROP_KEY = "0";
910
933
  var SINGLE_PROP_KEY = "1";
934
+ var REF_KEY = "ref";
911
935
  var PLACEHOLDER = " __PLACEHOLDER__ ";
912
936
  var RenderContext = class {
913
937
  constructor() {
914
938
  this.renderMode = 0;
915
939
  }
916
- // Getter to check if the current mode is SSG
917
940
  get isSSG() {
918
941
  return this.renderMode === 1;
919
942
  }
920
- // Getter to check if the current mode is SSR
921
943
  get isSSR() {
922
944
  return this.renderMode === 2;
923
945
  }
924
- // Getter to check if the current mode is Client
925
946
  get isClient() {
926
947
  return this.renderMode === 0;
927
948
  }
928
- // Set render mode to SSR
929
949
  setSSR() {
930
950
  this.renderMode = 2;
931
951
  }
932
- // Set render mode to SSG
933
952
  setSSG() {
934
953
  this.renderMode = 1;
935
954
  }
936
- // Set render mode to Client
937
955
  setClient() {
938
956
  this.renderMode = 0;
939
957
  }
@@ -973,11 +991,9 @@ var _LifecycleContext = class _LifecycleContext2 {
973
991
  setContext(context, value) {
974
992
  _LifecycleContext2.context[context] = value;
975
993
  }
976
- // Initialize the static reference
977
994
  initRef() {
978
995
  _LifecycleContext2.ref = this;
979
996
  }
980
- // Remove the static reference
981
997
  removeRef() {
982
998
  _LifecycleContext2.ref = null;
983
999
  }
@@ -1002,7 +1018,6 @@ var SSGNode = class extends LifecycleContext {
1002
1018
  enterComponent(template, componentIndex);
1003
1019
  this.templates = this.processTemplate();
1004
1020
  }
1005
- // Process the template and return an array of processed strings
1006
1021
  processTemplate() {
1007
1022
  if (isArray(this.template)) {
1008
1023
  const htmlString = this.template.join(PLACEHOLDER);
@@ -1011,7 +1026,6 @@ var SSGNode = class extends LifecycleContext {
1011
1026
  }
1012
1027
  return [];
1013
1028
  }
1014
- // Process HTML string by adding component index and handling text nodes
1015
1029
  processHtmlString(htmlString) {
1016
1030
  return htmlString.replaceAll(/(<[^>]+>)|([^<]+)/g, (match, p1, p2) => {
1017
1031
  if (p1) {
@@ -1025,14 +1039,12 @@ var SSGNode = class extends LifecycleContext {
1025
1039
  return match;
1026
1040
  });
1027
1041
  }
1028
- // Mount the SSGNode and return the rendered string
1029
1042
  mount() {
1030
1043
  this.initRef();
1031
1044
  const output = this.render();
1032
1045
  this.removeRef();
1033
1046
  return output;
1034
1047
  }
1035
- // Render the SSGNode
1036
1048
  render() {
1037
1049
  if (isFunction(this.template)) {
1038
1050
  const root = this.template(this.props);
@@ -1044,7 +1056,6 @@ var SSGNode = class extends LifecycleContext {
1044
1056
  }
1045
1057
  return this.renderTemplate();
1046
1058
  }
1047
- // Render the template by processing props and children
1048
1059
  renderTemplate() {
1049
1060
  Object.entries(this.props).forEach(([key, cur]) => {
1050
1061
  const children = cur.children;
@@ -1060,10 +1071,9 @@ var SSGNode = class extends LifecycleContext {
1060
1071
  });
1061
1072
  return this.templates.join("");
1062
1073
  }
1063
- // Normalize props by removing children and handling signals
1064
1074
  normalizeProps(props) {
1065
1075
  Object.entries(props).forEach(([key, value]) => {
1066
- if (key === "children") {
1076
+ if (key === CHILDREN_PROP) {
1067
1077
  delete props[key];
1068
1078
  } else if (isFunction(value)) {
1069
1079
  delete props[key];
@@ -1072,11 +1082,9 @@ var SSGNode = class extends LifecycleContext {
1072
1082
  }
1073
1083
  });
1074
1084
  }
1075
- // Generate HTML attributes string from props
1076
1085
  generateAttributes(props) {
1077
- return Object.entries(props).filter(([key, value]) => key !== "children" && !isFunction(value)).map(([key, value]) => `${key}="${escape(String(value))}"`).join(" ");
1086
+ return Object.entries(props).filter(([key, value]) => key !== CHILDREN_PROP && !isFunction(value)).map(([key, value]) => `${key}="${escape(String(value))}"`).join(" ");
1078
1087
  }
1079
- // Render children and append them to the template
1080
1088
  renderChildren(children, findIndex) {
1081
1089
  children.forEach(([child]) => {
1082
1090
  componentIndex++;
@@ -1084,12 +1092,11 @@ var SSGNode = class extends LifecycleContext {
1084
1092
  this.templates[findIndex] += renderedChild;
1085
1093
  });
1086
1094
  }
1087
- // Render a single child node
1088
1095
  renderChild(child) {
1089
- if (isFunction(child)) {
1090
- return this.renderChild(child(this.props));
1091
- } else if (isSignal(child)) {
1096
+ if (isSignal(child)) {
1092
1097
  return `<!--${1}-${componentIndex}-->${child.value}<!$>`;
1098
+ } else if (isFunction(child)) {
1099
+ return this.renderChild(child(this.props));
1093
1100
  } else if (isSSGNode(child)) {
1094
1101
  const childResult = child.mount();
1095
1102
  return isFunction(childResult) ? childResult(this.props) : extractSignal(childResult);
@@ -1099,9 +1106,6 @@ var SSGNode = class extends LifecycleContext {
1099
1106
  }
1100
1107
  };
1101
1108
  var SELF_CLOSING_TAGS = "area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr".split(",");
1102
- 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(
1103
- ","
1104
- );
1105
1109
  function coerceNode(data) {
1106
1110
  if (isJsxElement(data) || data instanceof Node || isSSGNode(data)) {
1107
1111
  return data;
@@ -1218,58 +1222,18 @@ function bindNode(node, setter) {
1218
1222
  });
1219
1223
  }
1220
1224
  }
1221
- Promise.resolve();
1222
1225
  function addEventListener(node, eventName, handler) {
1223
1226
  node.addEventListener(eventName, handler);
1224
1227
  return () => node.removeEventListener(eventName, handler);
1225
1228
  }
1226
- function closeHtmlTags(input) {
1227
- const tagStack = [];
1228
- const output = [];
1229
- const tagPattern = /<\/?([\da-z-]+)([^>]*)>/gi;
1230
- let lastIndex = 0;
1231
- while (true) {
1232
- const match = tagPattern.exec(input);
1233
- if (!match) break;
1234
- const [fullMatch, tagName] = match;
1235
- const isEndTag = fullMatch[1] === "/";
1236
- output.push(input.slice(lastIndex, match.index));
1237
- lastIndex = match.index + fullMatch.length;
1238
- if (isEndTag) {
1239
- while (tagStack.length > 0 && tagStack[tagStack.length - 1] !== tagName) {
1240
- const unclosedTag = tagStack.pop();
1241
- if (unclosedTag) {
1242
- output.push(`</${unclosedTag}>`);
1243
- }
1244
- }
1245
- if (tagStack.length > 0) {
1246
- tagStack.pop();
1247
- }
1248
- } else if (!SELF_CLOSING_TAGS.includes(tagName)) {
1249
- tagStack.push(tagName);
1250
- }
1251
- output.push(fullMatch);
1252
- }
1253
- output.push(input.slice(lastIndex));
1254
- while (tagStack.length > 0) {
1255
- const unclosedTag = tagStack.pop();
1256
- if (unclosedTag) {
1257
- output.push(`</${unclosedTag}>`);
1258
- }
1259
- }
1260
- return output.join("");
1261
- }
1262
- function isHtmlTagName(tagName) {
1263
- return HTML_TAGS.includes(tagName);
1264
- }
1265
1229
  function convertToHtmlTag(tagName) {
1266
1230
  return SELF_CLOSING_TAGS.includes(tagName) ? `<${tagName}/>` : `<${tagName}></${tagName}>`;
1267
1231
  }
1268
- function extractSignal(signal) {
1269
- if (isSignal(signal)) {
1270
- return signal.value;
1232
+ function extractSignal(signal2) {
1233
+ if (isSignal(signal2)) {
1234
+ return signal2.value;
1271
1235
  } else {
1272
- return signal;
1236
+ return signal2;
1273
1237
  }
1274
1238
  }
1275
1239
  var ComponentNode = class extends LifecycleContext {
@@ -1281,30 +1245,30 @@ var ComponentNode = class extends LifecycleContext {
1281
1245
  this.emitter = /* @__PURE__ */ new Set();
1282
1246
  this.rootNode = null;
1283
1247
  this.trackMap = /* @__PURE__ */ new Map();
1284
- this.key || (this.key = props == null ? void 0 : props.key);
1285
- this.proxyProps = this.createProxyProps(props);
1248
+ this.nodes = [];
1249
+ this.parent = null;
1250
+ this.before = null;
1251
+ this.key || (this.key = props && props.key);
1252
+ this.proxyProps || (this.proxyProps = this.createProxyProps(props));
1286
1253
  }
1287
- // Create reactive props
1288
1254
  createProxyProps(props) {
1289
1255
  if (!props) return {};
1290
- return useReactive(
1256
+ return shallowReactive(
1291
1257
  props,
1292
1258
  (key) => startsWith(key, EVENT_PREFIX) || startsWith(key, UPDATE_PREFIX) || key === CHILDREN_PROP
1293
1259
  );
1294
1260
  }
1295
- // Getter for the first child node
1296
1261
  get firstChild() {
1297
1262
  var _a, _b;
1298
1263
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.firstChild) != null ? _b : null;
1299
1264
  }
1300
- // Getter to check if the node is connected to the DOM
1301
1265
  get isConnected() {
1302
1266
  var _a, _b;
1303
1267
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.isConnected) != null ? _b : false;
1304
1268
  }
1305
- // Method to mount the component to the DOM
1306
1269
  mount(parent, before) {
1307
1270
  var _a, _b, _c, _d;
1271
+ this.parent = parent;
1308
1272
  if (!isFunction(this.template)) {
1309
1273
  throw new Error("Template must be a function");
1310
1274
  }
@@ -1312,49 +1276,55 @@ var ComponentNode = class extends LifecycleContext {
1312
1276
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.mount(parent, before)) != null ? _b : [];
1313
1277
  }
1314
1278
  this.initRef();
1315
- this.rootNode = this.template(this.proxyProps);
1316
- const mountedNode = (_d = (_c = this.rootNode) == null ? void 0 : _c.mount(parent, before)) != null ? _d : [];
1279
+ this.rootNode = this.template(reactive(this.proxyProps, [CHILDREN_PROP]));
1280
+ this.nodes = (_d = (_c = this.rootNode) == null ? void 0 : _c.mount(parent, before)) != null ? _d : [];
1317
1281
  this.callMountHooks();
1318
1282
  this.patchProps(this.props);
1319
1283
  this.removeRef();
1320
- return mountedNode;
1284
+ return this.nodes;
1321
1285
  }
1322
- // Method to unmount the component from the DOM
1323
1286
  unmount() {
1324
1287
  var _a;
1325
- this.callDestroyHooks();
1326
- this.clearHooks();
1288
+ this.callLifecycleHooks("destroy");
1289
+ this.cleanup();
1327
1290
  (_a = this.rootNode) == null ? void 0 : _a.unmount();
1291
+ this.resetState();
1292
+ if (this.key) {
1293
+ componentCache.delete(this.key);
1294
+ }
1295
+ }
1296
+ resetState() {
1328
1297
  this.rootNode = null;
1329
1298
  this.proxyProps = {};
1330
- this.clearEmitter();
1299
+ this.nodes = [];
1300
+ this.parent = null;
1301
+ }
1302
+ callLifecycleHooks(type) {
1303
+ this.hooks[type].forEach((handler) => handler());
1331
1304
  }
1332
- // Private method to call mount hooks
1333
1305
  callMountHooks() {
1334
1306
  this.hooks.mounted.forEach((handler) => handler());
1335
1307
  }
1336
- // Private method to call destroy hooks
1337
1308
  callDestroyHooks() {
1338
1309
  this.hooks.destroy.forEach((handler) => handler());
1339
1310
  }
1340
- // Private method to clear the event emitter
1341
1311
  clearEmitter() {
1342
1312
  for (const cleanup of this.emitter) {
1343
1313
  cleanup();
1344
1314
  }
1345
1315
  this.emitter.clear();
1346
1316
  }
1347
- // Method to inherit properties from another ComponentNode
1348
1317
  inheritNode(node) {
1349
1318
  Object.assign(this.proxyProps, node.proxyProps);
1350
1319
  this.rootNode = node.rootNode;
1351
1320
  this.trackMap = node.trackMap;
1352
1321
  this.hooks = node.hooks;
1353
- const props = this.props;
1354
- this.props = node.props;
1355
- this.patchProps(props);
1322
+ if (hasChanged(node.props, this.props)) {
1323
+ const props = this.props;
1324
+ this.props = node.props;
1325
+ this.patchProps(props);
1326
+ }
1356
1327
  }
1357
- // Private method to get or create a NodeTrack
1358
1328
  getNodeTrack(trackKey) {
1359
1329
  let track2 = this.trackMap.get(trackKey);
1360
1330
  if (!track2) {
@@ -1365,7 +1335,6 @@ var ComponentNode = class extends LifecycleContext {
1365
1335
  track2.cleanup();
1366
1336
  return track2;
1367
1337
  }
1368
- // Method to patch props onto the component
1369
1338
  patchProps(props) {
1370
1339
  var _a;
1371
1340
  if (!props) {
@@ -1374,7 +1343,7 @@ var ComponentNode = class extends LifecycleContext {
1374
1343
  for (const [key, prop] of Object.entries(props)) {
1375
1344
  if (startsWith(key, EVENT_PREFIX) && ((_a = this.rootNode) == null ? void 0 : _a.firstChild)) {
1376
1345
  this.patchEventListener(key, prop);
1377
- } else if (key === "ref") {
1346
+ } else if (key === REF_KEY) {
1378
1347
  this.patchRef(prop);
1379
1348
  } else if (startsWith(key, UPDATE_PREFIX)) {
1380
1349
  this.patchUpdateHandler(key, prop);
@@ -1384,28 +1353,33 @@ var ComponentNode = class extends LifecycleContext {
1384
1353
  }
1385
1354
  this.props = props;
1386
1355
  }
1387
- // Private method to patch event listeners
1388
1356
  patchEventListener(key, prop) {
1389
1357
  const event = key.slice(2).toLowerCase();
1390
1358
  const cleanup = addEventListener(this.rootNode.nodes[0], event, prop);
1391
1359
  this.emitter.add(cleanup);
1392
1360
  }
1393
- // Private method to patch ref
1394
1361
  patchRef(prop) {
1395
1362
  var _a, _b;
1396
1363
  prop.value = (_b = (_a = this.rootNode) == null ? void 0 : _a.firstChild) != null ? _b : null;
1397
1364
  }
1398
- // Private method to patch update handlers
1399
1365
  patchUpdateHandler(key, prop) {
1400
- this.props[key] = extractSignal(prop);
1366
+ this.proxyProps[key] = extractSignal(prop);
1401
1367
  }
1402
- // Private method to patch normal props
1403
1368
  patchNormalProp(key, prop) {
1404
1369
  const track2 = this.getNodeTrack(key);
1405
- track2.cleanup = useEffect(() => {
1370
+ track2.cleanup = effect(() => {
1406
1371
  this.proxyProps[key] = isFunction(prop) ? prop() : prop;
1407
1372
  });
1408
1373
  }
1374
+ cleanup() {
1375
+ this.trackMap.forEach((track2) => {
1376
+ var _a;
1377
+ return (_a = track2.cleanup) == null ? void 0 : _a.call(track2);
1378
+ });
1379
+ this.trackMap.clear();
1380
+ this.emitter.forEach((cleanup) => cleanup());
1381
+ this.emitter.clear();
1382
+ }
1409
1383
  };
1410
1384
  function patchChildren(parent, childrenMap, nextChildren, before) {
1411
1385
  const result = /* @__PURE__ */ new Map();
@@ -1523,26 +1497,21 @@ var TemplateNode = class {
1523
1497
  this.trackMap = /* @__PURE__ */ new Map();
1524
1498
  this.bindValueKeys = [];
1525
1499
  this.parent = null;
1526
- this.key || (this.key = props == null ? void 0 : props.key);
1527
1500
  if (renderContext.isSSR) {
1528
1501
  this.componentIndex = getComponentIndex(this.template);
1529
1502
  }
1530
1503
  }
1531
- // Getter for the first child node
1532
1504
  get firstChild() {
1533
1505
  var _a;
1534
1506
  return (_a = this.nodes[0]) != null ? _a : null;
1535
1507
  }
1536
- // Getter to check if the node is connected to the DOM
1537
1508
  get isConnected() {
1538
1509
  return this.mounted;
1539
1510
  }
1540
- // Placeholder methods for event handling
1541
1511
  addEventListener() {
1542
1512
  }
1543
1513
  removeEventListener() {
1544
1514
  }
1545
- // Method to mount the node to the DOM
1546
1515
  mount(parent, before) {
1547
1516
  var _a;
1548
1517
  this.parent = parent;
@@ -1557,7 +1526,7 @@ var TemplateNode = class {
1557
1526
  const firstChild = cloneNode.firstChild;
1558
1527
  if ((_a = firstChild == null ? void 0 : firstChild.hasAttribute) == null ? void 0 : _a.call(firstChild, "_svg_")) {
1559
1528
  firstChild.remove();
1560
- firstChild == null ? void 0 : firstChild.childNodes.forEach((node) => {
1529
+ firstChild.childNodes.forEach((node) => {
1561
1530
  cloneNode.append(node);
1562
1531
  });
1563
1532
  }
@@ -1572,45 +1541,19 @@ var TemplateNode = class {
1572
1541
  this.mounted = true;
1573
1542
  return this.nodes;
1574
1543
  }
1575
- // Method to unmount the node from the DOM
1576
1544
  unmount() {
1577
- var _a, _b;
1578
1545
  this.trackMap.forEach((track2) => {
1579
- var _a2;
1580
- (_a2 = track2.cleanup) == null ? void 0 : _a2.call(track2);
1546
+ track2.cleanup && track2.cleanup();
1581
1547
  });
1582
1548
  this.trackMap.clear();
1583
1549
  this.treeMap.clear();
1584
1550
  this.nodes.forEach((node) => removeChild(node));
1585
- if (!this.template.innerHTML && !this.nodes.length) {
1586
- const children = (_b = (_a = this.props) == null ? void 0 : _a[FRAGMENT_PROP_KEY]) == null ? void 0 : _b.children;
1587
- if (children) {
1588
- if (isArray(children)) {
1589
- children.forEach((child) => {
1590
- this.deleteFragmentTextNode(child);
1591
- });
1592
- } else {
1593
- this.deleteFragmentTextNode(children);
1594
- }
1595
- }
1596
- }
1597
1551
  this.nodes = [];
1598
1552
  this.mounted = false;
1599
- }
1600
- deleteFragmentTextNode(child) {
1601
- var _a;
1602
- if (isPrimitive(child)) {
1603
- (_a = this.parent) == null ? void 0 : _a.childNodes.forEach((node) => {
1604
- var _a2;
1605
- if (node.nodeType === Node.TEXT_NODE && node.textContent === `${child}`) {
1606
- (_a2 = this.parent) == null ? void 0 : _a2.removeChild(node);
1607
- }
1608
- });
1609
- } else {
1610
- removeChild(child);
1553
+ if (this.key) {
1554
+ componentCache.delete(this.key);
1611
1555
  }
1612
1556
  }
1613
- // Method to inherit properties from another TemplateNode
1614
1557
  inheritNode(node) {
1615
1558
  this.mounted = node.mounted;
1616
1559
  this.nodes = node.nodes;
@@ -1620,12 +1563,11 @@ var TemplateNode = class {
1620
1563
  this.props = node.props;
1621
1564
  this.patchProps(props);
1622
1565
  }
1623
- // Private method to map SSG node tree
1624
1566
  mapSSGNodeTree(parent) {
1625
1567
  this.treeMap.set(0, parent);
1626
1568
  this.walkNodeTree(parent, this.handleSSGNode.bind(this));
1627
1569
  }
1628
- // Private method to map node tree
1570
+ // protected method to map node tree
1629
1571
  mapNodeTree(parent, tree) {
1630
1572
  let index = 1;
1631
1573
  this.treeMap.set(0, parent);
@@ -1636,7 +1578,6 @@ var TemplateNode = class {
1636
1578
  };
1637
1579
  this.walkNodeTree(tree, handleNode);
1638
1580
  }
1639
- // Private method to walk through the node tree
1640
1581
  walkNodeTree(node, handler) {
1641
1582
  if (node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
1642
1583
  handler(node);
@@ -1647,7 +1588,6 @@ var TemplateNode = class {
1647
1588
  child = child.nextSibling;
1648
1589
  }
1649
1590
  }
1650
- // Private method to handle SSG nodes
1651
1591
  handleSSGNode(node) {
1652
1592
  var _a;
1653
1593
  if (node.nodeType === Node.COMMENT_NODE) {
@@ -1663,7 +1603,6 @@ var TemplateNode = class {
1663
1603
  }
1664
1604
  }
1665
1605
  }
1666
- // Method to patch props onto the node
1667
1606
  patchProps(props) {
1668
1607
  if (!props) return;
1669
1608
  Object.entries(props).forEach(([key, value]) => {
@@ -1675,15 +1614,14 @@ var TemplateNode = class {
1675
1614
  });
1676
1615
  this.props = props;
1677
1616
  }
1678
- // Private method to patch a single prop
1679
1617
  patchProp(key, node, props, isRoot) {
1680
1618
  if (!props) return;
1681
1619
  Object.entries(props).forEach(([attr, value]) => {
1682
1620
  if (attr === CHILDREN_PROP && value) {
1683
1621
  this.patchChildren(key, node, value, isRoot);
1684
- } else if (attr === "ref") {
1622
+ } else if (attr === REF_KEY) {
1685
1623
  props[attr].value = node;
1686
- } else if (startsWith(attr, "on")) {
1624
+ } else if (startsWith(attr, EVENT_PREFIX)) {
1687
1625
  this.patchEventListener(key, node, attr, value);
1688
1626
  } else {
1689
1627
  if (this.bindValueKeys.includes(attr)) return;
@@ -1693,14 +1631,12 @@ var TemplateNode = class {
1693
1631
  });
1694
1632
  }
1695
1633
  getBindUpdateValue(props, key, attr) {
1696
- const UPDATE_PREFIX2 = "update";
1697
- const updateKey = `${UPDATE_PREFIX2}${capitalizeFirstLetter(attr)}`;
1634
+ const updateKey = `${UPDATE_PREFIX}${capitalize(attr)}`;
1698
1635
  if (updateKey && props[updateKey] && isFunction(props[updateKey])) {
1699
1636
  this.bindValueKeys.push(updateKey);
1700
1637
  return props[updateKey];
1701
1638
  }
1702
1639
  }
1703
- // Private method to patch children
1704
1640
  patchChildren(key, node, children, isRoot) {
1705
1641
  if (!isArray(children)) {
1706
1642
  const trackKey = `${key}:${CHILDREN_PROP}:0`;
@@ -1717,21 +1653,19 @@ var TemplateNode = class {
1717
1653
  });
1718
1654
  }
1719
1655
  }
1720
- // Private method to patch event listeners
1721
1656
  patchEventListener(key, node, attr, listener) {
1722
1657
  const eventName = attr.slice(2).toLowerCase();
1723
1658
  const track2 = this.getNodeTrack(`${key}:${attr}`);
1724
1659
  track2.cleanup = addEventListener(node, eventName, listener);
1725
1660
  }
1726
- // Private method to patch attributes
1727
1661
  patchAttribute(key, element, attr, value, updateFn) {
1728
1662
  const track2 = this.getNodeTrack(`${key}:${attr}`);
1729
- const val = isFunction(value) ? value() : value;
1730
- const triggerValue = isSignal(val) ? val : useSignal(val);
1731
- setAttribute(element, attr, triggerValue.value);
1732
- const cleanup = useEffect(() => {
1733
- const val2 = isFunction(value) ? value() : value;
1734
- triggerValue.value = isSignal(val2) ? val2.value : val2;
1663
+ const triggerValue = shallowSignal();
1664
+ const cleanup = effect(() => {
1665
+ const unFnValue = isFunction(value) ? value() : value;
1666
+ if (isPlainObject(unFnValue) && isPlainObject(triggerValue.peek()) && JSON.stringify(triggerValue.value) === JSON.stringify(unFnValue))
1667
+ return;
1668
+ triggerValue.value = isSignal(unFnValue) ? unFnValue.value : unFnValue;
1735
1669
  setAttribute(element, attr, triggerValue.value);
1736
1670
  });
1737
1671
  let cleanupBind;
@@ -1745,9 +1679,7 @@ var TemplateNode = class {
1745
1679
  cleanupBind && cleanupBind();
1746
1680
  };
1747
1681
  }
1748
- // Private method to get or create a NodeTrack
1749
1682
  getNodeTrack(trackKey, trackLastNodes, isRoot) {
1750
- var _a;
1751
1683
  let track2 = this.trackMap.get(trackKey);
1752
1684
  if (!track2) {
1753
1685
  track2 = { cleanup: () => {
@@ -1760,13 +1692,12 @@ var TemplateNode = class {
1760
1692
  }
1761
1693
  this.trackMap.set(trackKey, track2);
1762
1694
  }
1763
- (_a = track2.cleanup) == null ? void 0 : _a.call(track2);
1695
+ track2.cleanup && track2.cleanup();
1764
1696
  return track2;
1765
1697
  }
1766
- // Private method to patch a child node
1767
1698
  patchChild(track2, parent, child, before) {
1768
1699
  if (isFunction(child)) {
1769
- track2.cleanup = useEffect(() => {
1700
+ track2.cleanup = effect(() => {
1770
1701
  const nextNodes = coerceArray(child()).map(coerceNode);
1771
1702
  if (renderContext.isSSR) {
1772
1703
  track2.lastNodes = this.reconcileChildren(parent, nextNodes, before);
@@ -1787,7 +1718,6 @@ var TemplateNode = class {
1787
1718
  });
1788
1719
  }
1789
1720
  }
1790
- // Private method to reconcile children nodes
1791
1721
  reconcileChildren(parent, nextNodes, before) {
1792
1722
  const result = /* @__PURE__ */ new Map();
1793
1723
  const textNodes = Array.from(parent.childNodes).filter(
@@ -1812,18 +1742,36 @@ var TemplateNode = class {
1812
1742
  return result;
1813
1743
  }
1814
1744
  };
1815
- function h(template, props, key) {
1816
- if (isString(template)) {
1817
- if (isHtmlTagName(template)) {
1818
- const htmlTemplate = convertToHtmlTag(template);
1819
- props = { [SINGLE_PROP_KEY]: props };
1820
- return new TemplateNode(createTemplate(htmlTemplate), props, key);
1821
- } else if (template === EMPTY_TEMPLATE) {
1822
- props = { [FRAGMENT_PROP_KEY]: props };
1823
- return new TemplateNode(createTemplate(EMPTY_TEMPLATE), props, key);
1745
+ var componentCache = /* @__PURE__ */ new Map();
1746
+ function createNodeCache(NodeConstructor, template, props = {}, key) {
1747
+ if (key) {
1748
+ const cached = componentCache.get(key);
1749
+ if (cached) {
1750
+ return cached;
1824
1751
  }
1825
1752
  }
1826
- return isFunction(template) ? new ComponentNode(template, props, key) : new TemplateNode(template, props, key);
1753
+ if (typeof template === "string") {
1754
+ template = createTemplate(template);
1755
+ }
1756
+ const newNode = new NodeConstructor(template, props, key);
1757
+ if (key && newNode instanceof ComponentNode) {
1758
+ componentCache.set(key, newNode);
1759
+ }
1760
+ return newNode;
1761
+ }
1762
+ function h(template, props = {}, key) {
1763
+ if (template === EMPTY_TEMPLATE) {
1764
+ return Fragment(template, props);
1765
+ }
1766
+ if (isString(template)) {
1767
+ const htmlTemplate = convertToHtmlTag(template);
1768
+ const wrappedProps = { [SINGLE_PROP_KEY]: props };
1769
+ return createNodeCache(TemplateNode, htmlTemplate, wrappedProps, key);
1770
+ }
1771
+ if (isFunction(template)) {
1772
+ return createNodeCache(ComponentNode, template, props, key);
1773
+ }
1774
+ return createNodeCache(TemplateNode, template, props, key);
1827
1775
  }
1828
1776
  function isComponent(node) {
1829
1777
  return node instanceof ComponentNode;
@@ -1833,13 +1781,17 @@ function isJsxElement(node) {
1833
1781
  }
1834
1782
  function createTemplate(html) {
1835
1783
  const template = document.createElement("template");
1836
- template.innerHTML = closeHtmlTags(html);
1784
+ template.innerHTML = html;
1837
1785
  return template;
1838
1786
  }
1839
- function Fragment(props) {
1840
- return h(EMPTY_TEMPLATE, {
1841
- children: isArray(props.children) ? props.children.filter(Boolean) : [props.children]
1842
- });
1787
+ function Fragment(template, props) {
1788
+ const processedProps = props.children ? {
1789
+ [FRAGMENT_PROP_KEY]: {
1790
+ children: Array.isArray(props.children) ? props.children.filter(Boolean) : [props.children]
1791
+ }
1792
+ } : props;
1793
+ const templateElement = template === EMPTY_TEMPLATE ? createTemplate(EMPTY_TEMPLATE) : template;
1794
+ return createNodeCache(TemplateNode, templateElement, processedProps);
1843
1795
  }
1844
1796
  function onMount(cb) {
1845
1797
  assertInsideComponent("onMounted");
@@ -1857,18 +1809,15 @@ function assertInsideComponent(hookName, key) {
1857
1809
  );
1858
1810
  }
1859
1811
  }
1860
- function useProvide(key, value) {
1861
- assertInsideComponent("useProvide", key);
1812
+ function provide(key, value) {
1813
+ assertInsideComponent("provide", key);
1862
1814
  LifecycleContext.ref && LifecycleContext.ref.setContext(key, value);
1863
1815
  }
1864
- function useInject(key, defaultValue) {
1816
+ function inject(key, defaultValue) {
1865
1817
  var _a;
1866
- assertInsideComponent("useInject", key);
1818
+ assertInsideComponent("inject", key);
1867
1819
  return (_a = LifecycleContext.ref && LifecycleContext.ref.getContext(key)) != null ? _a : defaultValue;
1868
1820
  }
1869
- function useRef() {
1870
- return shallowSignal(null);
1871
- }
1872
1821
  function renderToString(component, props) {
1873
1822
  renderContext.setSSG();
1874
1823
  const ssrNode = new SSGNode(component, props || {});
@@ -1897,43 +1846,43 @@ if (globalThis) {
1897
1846
  globalThis.__essor_version__ = essor_version;
1898
1847
  }
1899
1848
  /**
1900
- * @estjs/signal v0.0.14-beta.2
1849
+ * @estjs/signal v0.0.14-beta.21
1901
1850
  * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
1902
1851
  * @license MIT
1903
1852
  **/
1904
1853
  /**
1905
- * @estjs/template v0.0.14-beta.2
1854
+ * @estjs/template v0.0.14-beta.21
1906
1855
  * (c) 2023-Present jiangxd <jiangxd2016@gmail.com>
1907
1856
  * @license MIT
1908
1857
  **/
1909
1858
 
1910
1859
  exports.Fragment = Fragment;
1911
1860
  exports.clearReactive = clearReactive;
1861
+ exports.computed = computed;
1912
1862
  exports.createStore = createStore;
1863
+ exports.effect = effect;
1913
1864
  exports.essor_version = essor_version;
1914
1865
  exports.h = h;
1915
1866
  exports.hydrate = hydrate;
1867
+ exports.inject = inject;
1916
1868
  exports.isComponent = isComponent;
1917
1869
  exports.isComputed = isComputed;
1918
1870
  exports.isJsxElement = isJsxElement;
1919
1871
  exports.isReactive = isReactive;
1920
1872
  exports.isSignal = isSignal;
1873
+ exports.nextTick = nextTick;
1921
1874
  exports.onDestroy = onDestroy;
1922
1875
  exports.onMount = onMount;
1876
+ exports.provide = provide;
1877
+ exports.reactive = reactive;
1878
+ exports.ref = ref;
1923
1879
  exports.renderToString = renderToString;
1924
1880
  exports.shallowReactive = shallowReactive;
1925
1881
  exports.shallowSignal = shallowSignal;
1882
+ exports.signal = signal;
1926
1883
  exports.signalObject = signalObject;
1927
1884
  exports.ssg = ssg;
1928
1885
  exports.template = createTemplate;
1929
1886
  exports.toRaw = toRaw;
1930
1887
  exports.useBatch = useBatch;
1931
- exports.useComputed = useComputed;
1932
- exports.useEffect = useEffect;
1933
- exports.useInject = useInject;
1934
- exports.useProvide = useProvide;
1935
- exports.useReactive = useReactive;
1936
- exports.useRef = useRef;
1937
- exports.useShallowSignal = useShallowSignal;
1938
- exports.useSignal = useSignal;
1939
- exports.useWatch = useWatch;
1888
+ exports.watch = watch;