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