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