essor 0.0.6-beta.8 → 0.0.6

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.
@@ -15,9 +15,15 @@ var __spreadValues = (a, b) => {
15
15
  return a;
16
16
  };
17
17
 
18
+ // src/version.ts
19
+ var __essor_version = "0.0.6-beta.16";
20
+
18
21
  // ../shared/dist/essor-shared.js
19
22
  var isObject = (val) => val !== null && typeof val === "object";
20
23
  var isArray = Array.isArray;
24
+ function isString(val) {
25
+ return typeof val === "string";
26
+ }
21
27
  function isNull(val) {
22
28
  return val === null;
23
29
  }
@@ -29,14 +35,18 @@ function isFalsy(x) {
29
35
  return x === false || x === null || x === void 0 || x === "";
30
36
  }
31
37
  var isPrimitive = (val) => ["string", "number", "boolean", "symbol", "undefined"].includes(typeof val) || isNull(val);
38
+ var isHtmlElement = (val) => {
39
+ return val instanceof HTMLElement || val instanceof SVGElement;
40
+ };
32
41
  function coerceArray(data) {
33
42
  return Array.isArray(data) ? data.flat() : [data];
34
43
  }
35
- function hasChanged(value, oldValue) {
36
- return !Object.is(value, oldValue);
37
- }
44
+ var hasChanged = (value, oldValue) => value !== oldValue && (value === value || oldValue === oldValue);
38
45
  var noop = Function.prototype;
39
46
  function startsWith(str, searchString) {
47
+ if (!isString(str)) {
48
+ return false;
49
+ }
40
50
  return str.indexOf(searchString) === 0;
41
51
  }
42
52
  function deepClone(obj, hash = /* @__PURE__ */ new WeakMap()) {
@@ -140,11 +150,17 @@ function deepEqual(a, b, seen = /* @__PURE__ */ new WeakMap()) {
140
150
  }
141
151
  return true;
142
152
  }
153
+ function isExclude(key, exclude) {
154
+ return Array.isArray(exclude) ? exclude.includes(key) : isFunction(exclude) ? exclude(key) : false;
155
+ }
143
156
  var kebabCase = (string) => {
144
157
  return string.replaceAll(/[A-Z]+/g, (match, offset) => {
145
158
  return `${offset > 0 ? "-" : ""}${match.toLocaleLowerCase()}`;
146
159
  });
147
160
  };
161
+ var capitalizeFirstLetter = (inputString) => {
162
+ return inputString.charAt(0).toUpperCase() + inputString.slice(1);
163
+ };
148
164
 
149
165
  // src/signal/signal.ts
150
166
  var activeEffect = null;
@@ -152,6 +168,7 @@ var activeComputed = null;
152
168
  var computedSet = /* @__PURE__ */ new Set();
153
169
  var targetMap = /* @__PURE__ */ new WeakMap();
154
170
  var EffectDeps = /* @__PURE__ */ new Set();
171
+ var arrayMethods = ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
155
172
  function track(target, key) {
156
173
  let depsMap = targetMap.get(target);
157
174
  if (!depsMap) {
@@ -163,8 +180,7 @@ function track(target, key) {
163
180
  dep = /* @__PURE__ */ new Set();
164
181
  depsMap.set(key, dep);
165
182
  }
166
- if (activeEffect)
167
- dep.add(activeEffect);
183
+ if (activeEffect) dep.add(activeEffect);
168
184
  if (activeComputed) {
169
185
  computedSet.add(activeComputed);
170
186
  }
@@ -184,14 +200,18 @@ function trigger(target, key) {
184
200
  }
185
201
  var Signal = class {
186
202
  constructor(value) {
203
+ // @ts-ignore
204
+ this.__activeEffect = null;
187
205
  this._value = value;
188
206
  }
189
207
  valueOf() {
190
208
  track(this, "value");
209
+ this.__triggerObject();
191
210
  return this._value;
192
211
  }
193
212
  toString() {
194
213
  track(this, "value");
214
+ this.__triggerObject();
195
215
  return String(this._value);
196
216
  }
197
217
  toJSON() {
@@ -199,11 +219,28 @@ var Signal = class {
199
219
  }
200
220
  get value() {
201
221
  track(this, "value");
222
+ this.__triggerObject();
202
223
  return this._value;
203
224
  }
225
+ // if the value is not a primitive or an HTML element, create a reactive proxy
226
+ __triggerObject() {
227
+ if (activeEffect) {
228
+ this.__activeEffect = activeEffect;
229
+ }
230
+ this._reactive = isPrimitive(this._value) || isHtmlElement(this._value) ? this._value : useReactive(this._value);
231
+ }
204
232
  set value(newValue) {
205
- if (this._value !== newValue) {
233
+ if (isSignal(newValue)) {
234
+ console.warn("Signal cannot be set to another signal, use .peek() instead");
235
+ newValue = newValue.peek();
236
+ }
237
+ if (hasChanged(newValue, this._value)) {
206
238
  this._value = newValue;
239
+ if (!isPrimitive(this._value) && !isHtmlElement(this._value) && !activeEffect) {
240
+ activeEffect = this.__activeEffect;
241
+ this.__triggerObject();
242
+ activeEffect = null;
243
+ }
207
244
  trigger(this, "value");
208
245
  }
209
246
  }
@@ -237,7 +274,7 @@ var Computed = class {
237
274
  }
238
275
  run() {
239
276
  const newValue = this.fn();
240
- if (newValue !== this._value) {
277
+ if (hasChanged(newValue, this._value)) {
241
278
  this._value = newValue;
242
279
  this._deps.forEach((effect) => effect());
243
280
  }
@@ -270,30 +307,32 @@ function useEffect(fn) {
270
307
  activeEffect = null;
271
308
  };
272
309
  }
273
- function shouldExclude(key, exclude) {
274
- return Array.isArray(exclude) ? exclude.includes(key) : isFunction(exclude) ? exclude(key) : false;
275
- }
276
310
  function signalObject(initialValues, exclude) {
277
311
  const signals = Object.entries(initialValues).reduce((acc, [key, value]) => {
278
- acc[key] = shouldExclude(key, exclude) || isSignal(value) ? value : useSignal(value);
312
+ acc[key] = isExclude(key, exclude) || isSignal(value) ? value : useSignal(value);
279
313
  return acc;
280
314
  }, {});
281
315
  return signals;
282
316
  }
283
317
  function unSignal(signal, exclude) {
284
- if (!signal)
285
- return {};
318
+ if (!signal) return {};
286
319
  if (isSignal(signal)) {
287
320
  return signal.peek();
288
321
  }
289
- return Object.entries(signal).reduce((acc, [key, value]) => {
290
- if (shouldExclude(key, exclude)) {
291
- acc[key] = value;
292
- } else {
293
- acc[key] = isSignal(value) ? value.peek() : value;
294
- }
295
- return acc;
296
- }, {});
322
+ if (isArray(signal)) {
323
+ return signal.map((value) => unSignal(value, exclude));
324
+ }
325
+ if (isObject(signal)) {
326
+ return Object.entries(signal).reduce((acc, [key, value]) => {
327
+ if (isExclude(key, exclude)) {
328
+ acc[key] = value;
329
+ } else {
330
+ acc[key] = isSignal(value) ? value.peek() : value;
331
+ }
332
+ return acc;
333
+ }, {});
334
+ }
335
+ return signal;
297
336
  }
298
337
  var REACTIVE_MARKER = Symbol("useReactive");
299
338
  function isReactive(obj) {
@@ -306,7 +345,7 @@ function unReactive(obj) {
306
345
  return Object.assign({}, obj);
307
346
  }
308
347
  var reactiveMap = /* @__PURE__ */ new WeakMap();
309
- function useReactive(initialValue) {
348
+ function useReactive(initialValue, exclude) {
310
349
  if (!isObject(initialValue)) {
311
350
  return initialValue;
312
351
  }
@@ -316,11 +355,32 @@ function useReactive(initialValue) {
316
355
  if (reactiveMap.has(initialValue)) {
317
356
  return reactiveMap.get(initialValue);
318
357
  }
358
+ if (Array.isArray(initialValue)) {
359
+ arrayMethods.forEach((method) => {
360
+ const originalMethod = initialValue[method];
361
+ track(initialValue, "length");
362
+ Object.defineProperties(initialValue, {
363
+ [method]: {
364
+ value(...args) {
365
+ const result = originalMethod.apply(this, args);
366
+ trigger(initialValue, "length");
367
+ return result;
368
+ },
369
+ enumerable: false,
370
+ configurable: true,
371
+ writable: true
372
+ }
373
+ });
374
+ });
375
+ }
319
376
  const handler = {
320
377
  get(target, key, receiver) {
321
- if (key === REACTIVE_MARKER)
322
- return true;
323
- const value = Reflect.get(target, key, receiver);
378
+ if (key === REACTIVE_MARKER || startsWith(key, "_")) return true;
379
+ const getValue = Reflect.get(target, key, receiver);
380
+ const value = isSignal(getValue) ? getValue.value : getValue;
381
+ if (isExclude(key, exclude)) {
382
+ return value;
383
+ }
324
384
  track(target, key);
325
385
  if (isObject(value)) {
326
386
  return useReactive(value);
@@ -328,6 +388,10 @@ function useReactive(initialValue) {
328
388
  return value;
329
389
  },
330
390
  set(target, key, value, receiver) {
391
+ if (isExclude(key, exclude)) {
392
+ Reflect.set(target, key, value, receiver);
393
+ return true;
394
+ }
331
395
  let oldValue = Reflect.get(target, key, receiver);
332
396
  if (isSignal(oldValue)) {
333
397
  oldValue = oldValue.value;
@@ -357,7 +421,7 @@ function useReactive(initialValue) {
357
421
 
358
422
  // src/warning.ts
359
423
  function warn(msg, ...args) {
360
- console.warn.apply(console, [`[Essor Router warn]: ${msg}`].concat(args));
424
+ console.warn.apply(console, [`[Essor warn]: ${msg}`].concat(args));
361
425
  }
362
426
 
363
427
  // src/signal/watch.ts
@@ -373,12 +437,9 @@ function doWatch(source, cb, options) {
373
437
  getter = () => __spreadValues({}, source);
374
438
  } else if (isArray(source)) {
375
439
  getter = () => source.map((s) => {
376
- if (isSignal(s) || isComputed(s))
377
- return s.value;
378
- if (isReactive(s))
379
- return __spreadValues({}, s);
380
- if (isFunction(s))
381
- return s();
440
+ if (isSignal(s) || isComputed(s)) return s.value;
441
+ if (isReactive(s)) return __spreadValues({}, s);
442
+ if (isFunction(s)) return s();
382
443
  return warn("Invalid source", s);
383
444
  });
384
445
  } else if (isFunction(source)) {
@@ -406,8 +467,7 @@ function doWatch(source, cb, options) {
406
467
  return stop;
407
468
  }
408
469
  function traverse(value, seen = /* @__PURE__ */ new Set()) {
409
- if (!isObject(value) || seen.has(value))
410
- return value;
470
+ if (!isObject(value) || seen.has(value)) return value;
411
471
  seen.add(value);
412
472
  if (isArray(value)) {
413
473
  value.forEach((item) => traverse(item, seen));
@@ -503,7 +563,7 @@ var _ComponentNode = class _ComponentNode {
503
563
  this.trackMap = /* @__PURE__ */ new Map();
504
564
  this.proxyProps = signalObject(
505
565
  props,
506
- (key2) => startsWith(key2, "on") || startsWith(key2, "update:")
566
+ (key2) => startsWith(key2, "on") || startsWith(key2, "update")
507
567
  );
508
568
  }
509
569
  addEventListener() {
@@ -558,7 +618,7 @@ var _ComponentNode = class _ComponentNode {
558
618
  return (_b = (_a = this.rootNode) == null ? void 0 : _a.mount(parent, before)) != null ? _b : [];
559
619
  }
560
620
  _ComponentNode.ref = this;
561
- this.rootNode = this.template(this.proxyProps);
621
+ this.rootNode = this.template(useReactive(this.proxyProps, ["children"]));
562
622
  _ComponentNode.ref = null;
563
623
  this.mounted = true;
564
624
  const mountedNode = (_d = (_c = this.rootNode) == null ? void 0 : _c.mount(parent, before)) != null ? _d : [];
@@ -592,13 +652,13 @@ var _ComponentNode = class _ComponentNode {
592
652
  } else if (isFunction(prop)) {
593
653
  props[key]((_c = this.rootNode) == null ? void 0 : _c.nodes[0]);
594
654
  }
595
- } else if (startsWith(key, "update:")) {
655
+ } else if (startsWith(key, "update")) {
596
656
  props[key] = isSignal(prop) ? prop.value : prop;
597
657
  } else {
598
658
  const newValue = (_e = (_d = this.proxyProps)[key]) != null ? _e : _d[key] = useSignal(prop);
599
659
  const track2 = this.getNodeTrack(key);
600
660
  track2.cleanup = useEffect(() => {
601
- newValue.value = prop;
661
+ newValue.value = isFunction(prop) ? prop() : prop;
602
662
  });
603
663
  }
604
664
  }
@@ -610,8 +670,17 @@ _ComponentNode.context = {};
610
670
  var ComponentNode = _ComponentNode;
611
671
 
612
672
  // src/template/template.ts
613
- function h(template2, props, key) {
614
- return isFunction(template2) ? new ComponentNode(template2, props, key) : new TemplateNode(template2, props, key);
673
+ function h(_template, props, key) {
674
+ if (isString(_template)) {
675
+ if (isHtmlTagName(_template)) {
676
+ _template = convertToHtmlTag(_template);
677
+ props = {
678
+ 1: props
679
+ };
680
+ }
681
+ _template = template(_template);
682
+ }
683
+ return isFunction(_template) ? new ComponentNode(_template, props, key) : new TemplateNode(_template, props, key);
615
684
  }
616
685
  function isJsxElement(node) {
617
686
  return node instanceof ComponentNode || node instanceof TemplateNode;
@@ -742,6 +811,173 @@ function addEventListener(node, eventName, handler) {
742
811
  node.addEventListener(eventName, handler);
743
812
  return () => node.removeEventListener(eventName, handler);
744
813
  }
814
+ var selfClosingTags = [
815
+ "area",
816
+ "base",
817
+ "br",
818
+ "col",
819
+ "embed",
820
+ "hr",
821
+ "img",
822
+ "input",
823
+ "link",
824
+ "meta",
825
+ "param",
826
+ "source",
827
+ "track",
828
+ "wbr"
829
+ ];
830
+ var htmlTags = [
831
+ "a",
832
+ "abbr",
833
+ "acronym",
834
+ "address",
835
+ "applet",
836
+ "area",
837
+ "article",
838
+ "aside",
839
+ "audio",
840
+ "b",
841
+ "base",
842
+ "basefont",
843
+ "bdi",
844
+ "bdo",
845
+ "bgsound",
846
+ "big",
847
+ "blink",
848
+ "blockquote",
849
+ "body",
850
+ "br",
851
+ "button",
852
+ "canvas",
853
+ "caption",
854
+ "center",
855
+ "cite",
856
+ "code",
857
+ "col",
858
+ "colgroup",
859
+ "command",
860
+ "content",
861
+ "data",
862
+ "datalist",
863
+ "dd",
864
+ "del",
865
+ "details",
866
+ "dfn",
867
+ "dialog",
868
+ "dir",
869
+ "div",
870
+ "dl",
871
+ "dt",
872
+ "em",
873
+ "embed",
874
+ "fieldset",
875
+ "figcaption",
876
+ "figure",
877
+ "font",
878
+ "footer",
879
+ "form",
880
+ "frame",
881
+ "frameset",
882
+ "h1",
883
+ "h2",
884
+ "h3",
885
+ "h4",
886
+ "h5",
887
+ "h6",
888
+ "head",
889
+ "header",
890
+ "hgroup",
891
+ "hr",
892
+ "html",
893
+ "i",
894
+ "iframe",
895
+ "image",
896
+ "img",
897
+ "input",
898
+ "ins",
899
+ "kbd",
900
+ "keygen",
901
+ "label",
902
+ "legend",
903
+ "li",
904
+ "link",
905
+ "listing",
906
+ "main",
907
+ "map",
908
+ "mark",
909
+ "marquee",
910
+ "menu",
911
+ "menuitem",
912
+ "meta",
913
+ "meter",
914
+ "nav",
915
+ "nobr",
916
+ "noframes",
917
+ "noscript",
918
+ "object",
919
+ "ol",
920
+ "optgroup",
921
+ "option",
922
+ "output",
923
+ "p",
924
+ "param",
925
+ "picture",
926
+ "plaintext",
927
+ "pre",
928
+ "progress",
929
+ "q",
930
+ "rb",
931
+ "rp",
932
+ "rt",
933
+ "rtc",
934
+ "ruby",
935
+ "s",
936
+ "samp",
937
+ "script",
938
+ "section",
939
+ "select",
940
+ "shadow",
941
+ "small",
942
+ "source",
943
+ "spacer",
944
+ "span",
945
+ "strike",
946
+ "strong",
947
+ "style",
948
+ "sub",
949
+ "summary",
950
+ "sup",
951
+ "table",
952
+ "tbody",
953
+ "td",
954
+ "template",
955
+ "textarea",
956
+ "tfoot",
957
+ "th",
958
+ "thead",
959
+ "time",
960
+ "title",
961
+ "tr",
962
+ "track",
963
+ "tt",
964
+ "u",
965
+ "ul",
966
+ "var",
967
+ "video",
968
+ "wbr",
969
+ "xmp"
970
+ ];
971
+ function isHtmlTagName(str) {
972
+ return htmlTags.includes(str);
973
+ }
974
+ function convertToHtmlTag(tag) {
975
+ if (selfClosingTags.includes(tag)) {
976
+ return `<${tag}/>`;
977
+ } else {
978
+ return `<${tag}></${tag}>`;
979
+ }
980
+ }
745
981
 
746
982
  // src/template/patch.ts
747
983
  function patchChildren(parent, childrenMap, nextChildren, before) {
@@ -966,11 +1202,8 @@ var TemplateNode = class _TemplateNode {
966
1202
  const track2 = this.getNodeTrack(trackKey, true, isRoot);
967
1203
  patchChild(track2, node, props.children, null);
968
1204
  } else {
969
- props.children.forEach((item, index) => {
1205
+ props.children.filter(Boolean).forEach((item, index) => {
970
1206
  var _a;
971
- if (!item) {
972
- return;
973
- }
974
1207
  const [child, path] = isArray(item) ? item : [item, null];
975
1208
  const before = isNil(path) ? null : (_a = this.treeMap.get(path)) != null ? _a : null;
976
1209
  const trackKey = `${key}:${attr}:${index}`;
@@ -989,16 +1222,17 @@ var TemplateNode = class _TemplateNode {
989
1222
  const track2 = this.getNodeTrack(`${key}:${attr}`);
990
1223
  const listener = props[attr];
991
1224
  track2.cleanup = addEventListener(node, eventName, listener);
992
- } else if (!startsWith(attr, "update:")) {
1225
+ } else if (!startsWith(attr, "update")) {
993
1226
  const track2 = this.getNodeTrack(`${key}:${attr}`);
994
1227
  const val = props[attr];
995
1228
  const triggerValue = isSignal(val) ? val : useSignal(val);
1229
+ patchAttribute(track2, node, attr, triggerValue.value);
996
1230
  const cleanup = useEffect(() => {
997
1231
  triggerValue.value = isSignal(val) ? val.value : val;
998
1232
  patchAttribute(track2, node, attr, triggerValue.value);
999
1233
  });
1000
1234
  let cleanupBind;
1001
- const updateKey = `update:${attr}`;
1235
+ const updateKey = `update${capitalizeFirstLetter(attr)}`;
1002
1236
  if (props[updateKey]) {
1003
1237
  cleanupBind = binNode(node, (value) => {
1004
1238
  props[updateKey](value);
@@ -1053,7 +1287,7 @@ function onDestroy(cb) {
1053
1287
  }
1054
1288
  function throwIfOutsideComponent(hook) {
1055
1289
  if (!ComponentNode.ref) {
1056
- throw new Error(
1290
+ console.error(
1057
1291
  `"${hook}" can only be called within the component function body
1058
1292
  and cannot be used in asynchronous or deferred calls.`
1059
1293
  );
@@ -1089,43 +1323,39 @@ function useRef() {
1089
1323
  });
1090
1324
  }
1091
1325
 
1092
- // src/version.ts
1093
- var __essor_version = "0.0.6-beta.7";
1094
-
1095
1326
  // src/server/index.ts
1096
- function ssrtmpl(templates = []) {
1097
- return templates.reduce((acc, template2, index) => {
1098
- acc[index + 1] = { template: template2 };
1099
- return acc;
1100
- }, {});
1101
- }
1102
1327
  function jsonToAttrs(json) {
1103
- return Object.entries(json).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" ");
1328
+ return Object.entries(json).map(([key, value]) => `${key}=${JSON.stringify(escape(String(value)))}`).join(" ");
1104
1329
  }
1105
- function ssr(template2, props) {
1330
+ function renderTemplate(template2, props) {
1106
1331
  if (isFunction(template2)) {
1107
1332
  return template2(props);
1108
1333
  }
1334
+ const templates = Array.isArray(template2) ? template2.reduce((acc, tmpl, index) => {
1335
+ acc[index + 1] = { template: tmpl };
1336
+ return acc;
1337
+ }, {}) : template2;
1109
1338
  const childrenMap = {};
1110
1339
  const newTemplate = {};
1111
- if (isObject(template2)) {
1112
- Object.entries(template2).forEach(([key, tmpl]) => {
1340
+ if (isObject(templates)) {
1341
+ for (const [key, tmpl] of Object.entries(templates)) {
1113
1342
  const prop = props[key];
1114
1343
  if (prop) {
1115
- Object.keys(prop).forEach((propKey) => {
1344
+ for (const propKey in prop) {
1116
1345
  if (startsWith(propKey, "on") && isFunction(prop[propKey])) {
1117
1346
  delete prop[propKey];
1118
1347
  }
1119
- });
1348
+ }
1120
1349
  if (prop.children) {
1121
- prop.children.forEach(([child, idx]) => {
1122
- childrenMap[idx] = [...childrenMap[idx] || [], child];
1123
- });
1350
+ for (const [child, idx] of prop.children) {
1351
+ if (!childrenMap[idx]) childrenMap[idx] = [];
1352
+ childrenMap[idx].push(child);
1353
+ }
1124
1354
  delete prop.children;
1125
1355
  }
1126
1356
  }
1127
1357
  newTemplate[key] = { template: tmpl.template, prop };
1128
- });
1358
+ }
1129
1359
  }
1130
1360
  return Object.entries(newTemplate).map(([key, { template: tmpl, prop }]) => {
1131
1361
  let str = tmpl;
@@ -1133,17 +1363,21 @@ function ssr(template2, props) {
1133
1363
  str += ` ${jsonToAttrs(prop)}`;
1134
1364
  }
1135
1365
  if (childrenMap[key]) {
1136
- str += childrenMap[key].map((child) => ssr(child, prop)).join("");
1366
+ str += childrenMap[key].map((child) => renderTemplate(child, prop)).join("");
1137
1367
  }
1138
1368
  return str;
1139
1369
  }).join("");
1140
1370
  }
1141
1371
  function renderToString(component, props) {
1142
- return ssr(component, props);
1372
+ return renderTemplate(component, props);
1373
+ }
1374
+ function ssgRender(component, root, props = {}) {
1375
+ root.innerHTML = renderTemplate(component, props);
1143
1376
  }
1144
- function ssgRender(component, root) {
1145
- root.innerHTML = "";
1146
- component.mount(root);
1377
+
1378
+ // src/index.ts
1379
+ if (globalThis) {
1380
+ globalThis.__essor_version = __essor_version;
1147
1381
  }
1148
1382
 
1149
- export { ComponentNode, Fragment, TemplateNode, __essor_version, createStore, h, isComputed, isJsxElement, isReactive, isSignal, nextTick, onDestroy, onMount, renderToString, signalObject, ssgRender, ssr, ssrtmpl, template, unReactive, unSignal, useComputed, useEffect, useInject, useProvide, useReactive, useRef, useSignal, useWatch };
1383
+ export { ComponentNode, Fragment, TemplateNode, __essor_version, createStore, h, isComputed, isJsxElement, isReactive, isSignal, nextTick, onDestroy, onMount, renderTemplate, renderToString, signalObject, ssgRender, template, unReactive, unSignal, useComputed, useEffect, useInject, useProvide, useReactive, useRef, useSignal, useWatch };