@oscarpalmer/abydon 0.21.0 → 0.22.0

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.
@@ -156,6 +156,11 @@ function unsubscribe(state, callback) {
156
156
  //#endregion
157
157
  //#region node_modules/@oscarpalmer/mora/dist/value/reactive.mjs
158
158
  var Reactive = class {
159
+ /**
160
+ * Internal state of the reactive value
161
+ *
162
+ * @internal
163
+ */
159
164
  state = {
160
165
  computeds: /* @__PURE__ */ new Set(),
161
166
  effects: /* @__PURE__ */ new Set(),
@@ -269,6 +274,44 @@ function setValue$2(instance, state, callback) {
269
274
  }
270
275
  }
271
276
  //#endregion
277
+ //#region node_modules/@oscarpalmer/mora/node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
278
+ /**
279
+ * Is the value a key?
280
+ * @param value Value to check
281
+ * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
282
+ */
283
+ function isKey(value) {
284
+ return typeof value === "number" || typeof value === "string";
285
+ }
286
+ /**
287
+ * Is the value a plain object?
288
+ * @param value Value to check
289
+ * @returns `true` if the value is a plain object, otherwise `false`
290
+ */
291
+ function isPlainObject$1(value) {
292
+ if (value === null || typeof value !== "object") return false;
293
+ if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
294
+ const prototype = Object.getPrototypeOf(value);
295
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
296
+ }
297
+ //#endregion
298
+ //#region node_modules/@oscarpalmer/mora/node_modules/@oscarpalmer/atoms/dist/math.mjs
299
+ /**
300
+ * Round a number
301
+ * @param value Number to round
302
+ * @param decimals Number of decimal places to round to _(defaults to `0`)_
303
+ * @returns Rounded number, or `NaN` if the value if unable to be rounded
304
+ */
305
+ function round(value, decimals) {
306
+ return roundNumber(Math.round, value, decimals);
307
+ }
308
+ function roundNumber(callback, value, decimals) {
309
+ if (typeof value !== "number") return NaN;
310
+ if (typeof decimals !== "number" || decimals < 1) return callback(value);
311
+ const mod = 10 ** decimals;
312
+ return callback((value + Number.EPSILON) * mod) / mod;
313
+ }
314
+ //#endregion
272
315
  //#region node_modules/@oscarpalmer/mora/dist/helpers/value.mjs
273
316
  function emitValue(state) {
274
317
  for (const computed of state.computeds) computed.effect.dirty = true;
@@ -281,7 +324,7 @@ function equalArrays(state, first, second) {
281
324
  if (length !== second.length) return false;
282
325
  let offset = 0;
283
326
  if (length >= 100) {
284
- offset = Math.round(length / 10);
327
+ offset = round(length / 10);
285
328
  offset = offset > 25 ? 25 : offset;
286
329
  for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
287
330
  }
@@ -575,27 +618,6 @@ function setAtIndex(state, index, value) {
575
618
  if (actual > -1) state.value[actual] = value;
576
619
  }
577
620
  //#endregion
578
- //#region node_modules/@oscarpalmer/mora/node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
579
- /**
580
- * Is the value a key?
581
- * @param value Value to check
582
- * @returns `true` if the value is a `Key` _(`number` or `string`)_, otherwise `false`
583
- */
584
- function isKey(value) {
585
- return typeof value === "number" || typeof value === "string";
586
- }
587
- /**
588
- * Is the value a plain object?
589
- * @param value Value to check
590
- * @returns `true` if the value is a plain object, otherwise `false`
591
- */
592
- function isPlainObject$2(value) {
593
- if (value === null || typeof value !== "object") return false;
594
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
595
- const prototype = Object.getPrototypeOf(value);
596
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
597
- }
598
- //#endregion
599
621
  //#region node_modules/@oscarpalmer/mora/dist/value/store.mjs
600
622
  var Store = class extends Reactive {
601
623
  #keyed = /* @__PURE__ */ new Map();
@@ -636,11 +658,11 @@ var Store = class extends Reactive {
636
658
  */
637
659
  update(callback) {
638
660
  const updated = callback(this.state.value);
639
- if (updated == null || isPlainObject$2(updated)) setObject(this.state, updated);
661
+ if (updated == null || isPlainObject$1(updated)) setObject(this.state, updated);
640
662
  }
641
663
  };
642
664
  function isStoreObject(value) {
643
- return value == null || isPlainObject$2(value);
665
+ return value == null || isPlainObject$1(value);
644
666
  }
645
667
  function setObject(state, value) {
646
668
  startBatch();
@@ -671,11 +693,19 @@ function store(value, options) {
671
693
  //#endregion
672
694
  //#region node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
673
695
  /**
696
+ * Is the value a number?
697
+ * @param value Value to check
698
+ * @returns `true` if the value is a `number`, otherwise `false`
699
+ */
700
+ function isNumber(value) {
701
+ return typeof value === "number" && !Number.isNaN(value);
702
+ }
703
+ /**
674
704
  * Is the value a plain object?
675
705
  * @param value Value to check
676
706
  * @returns `true` if the value is a plain object, otherwise `false`
677
707
  */
678
- function isPlainObject$1(value) {
708
+ function isPlainObject(value) {
679
709
  if (value === null || typeof value !== "object") return false;
680
710
  if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
681
711
  const prototype = Object.getPrototypeOf(value);
@@ -688,14 +718,42 @@ function isPlainObject$1(value) {
688
718
  * @param value Original value
689
719
  * @returns String representation of the value
690
720
  */
691
- function getString$1(value) {
721
+ function getString(value) {
692
722
  if (typeof value === "string") return value;
693
723
  if (value == null) return "";
694
- if (typeof value === "function") return getString$1(value());
724
+ if (typeof value === "function") return getString(value());
695
725
  if (typeof value !== "object") return String(value);
696
726
  const asString = String(value.valueOf?.() ?? value);
697
727
  return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
698
728
  }
729
+ /**
730
+ * Join an array of values into a string _(while ignoring empty values)_
731
+ *
732
+ * _(`null`, `undefined`, and any values that become whitespace-only strings are considered empty)_
733
+ * @param array Array of values
734
+ * @param delimiter Delimiter to use between values
735
+ * @returns Joined string
736
+ */
737
+ function join(array, delimiter) {
738
+ if (!Array.isArray(array)) return "";
739
+ const { length } = array;
740
+ if (length === 0) return "";
741
+ const values = [];
742
+ for (let index = 0; index < length; index += 1) {
743
+ const item = getString(array[index]);
744
+ if (item.trim().length > 0) values.push(item);
745
+ }
746
+ return values.join(typeof delimiter === "string" ? delimiter : "");
747
+ }
748
+ /**
749
+ * Split a string into words _(and other readable parts)_
750
+ * @param value Original string
751
+ * @returns Array of words found in the string
752
+ */
753
+ function words(value) {
754
+ return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
755
+ }
756
+ const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
699
757
  //#endregion
700
758
  //#region node_modules/@oscarpalmer/atoms/dist/is.mjs
701
759
  /**
@@ -703,10 +761,10 @@ function getString$1(value) {
703
761
  * @param value Value to check
704
762
  * @returns `true` if the value is nullable or matches a whitespace-only string, otherwise `false`
705
763
  */
706
- function isNullableOrWhitespace$1(value) {
707
- return value == null || EXPRESSION_WHITESPACE$2.test(getString$1(value));
764
+ function isNullableOrWhitespace(value) {
765
+ return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
708
766
  }
709
- const EXPRESSION_WHITESPACE$2 = /^\s*$/;
767
+ const EXPRESSION_WHITESPACE$1 = /^\s*$/;
710
768
  //#endregion
711
769
  //#region node_modules/@oscarpalmer/toretto/dist/internal/is.mjs
712
770
  /**
@@ -743,85 +801,7 @@ const CHILD_NODE_TYPES = new Set([
743
801
  Node.DOCUMENT_TYPE_NODE
744
802
  ]);
745
803
  //#endregion
746
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/is.mjs
747
- /**
748
- * Is the value a number?
749
- * @param value Value to check
750
- * @returns `true` if the value is a `number`, otherwise `false`
751
- */
752
- function isNumber(value) {
753
- return typeof value === "number" && !Number.isNaN(value);
754
- }
755
- /**
756
- * Is the value a plain object?
757
- * @param value Value to check
758
- * @returns `true` if the value is a plain object, otherwise `false`
759
- */
760
- function isPlainObject(value) {
761
- if (value === null || typeof value !== "object") return false;
762
- if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
763
- const prototype = Object.getPrototypeOf(value);
764
- return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
765
- }
766
- //#endregion
767
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/array/compact.mjs
768
- function compact(array, strict) {
769
- if (!Array.isArray(array)) return [];
770
- if (strict === true) return array.filter(Boolean);
771
- const { length } = array;
772
- const compacted = [];
773
- for (let index = 0; index < length; index += 1) {
774
- const item = array[index];
775
- if (item != null) compacted.push(item);
776
- }
777
- return compacted;
778
- }
779
- //#endregion
780
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/string.mjs
781
- /**
782
- * Get the string value from any value
783
- * @param value Original value
784
- * @returns String representation of the value
785
- */
786
- function getString(value) {
787
- if (typeof value === "string") return value;
788
- if (value == null) return "";
789
- if (typeof value === "function") return getString(value());
790
- if (typeof value !== "object") return String(value);
791
- const asString = String(value.valueOf?.() ?? value);
792
- return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
793
- }
794
- /**
795
- * Join an array of values into a string
796
- * @param value Array of values
797
- * @param delimiter Delimiter to use between values
798
- * @returns Joined string
799
- */
800
- function join(value, delimiter) {
801
- return compact(value).map(getString).join(typeof delimiter === "string" ? delimiter : "");
802
- }
803
- /**
804
- * Split a string into words _(and other readable parts)_
805
- * @param value Original string
806
- * @returns Array of words found in the string
807
- */
808
- function words(value) {
809
- return typeof value === "string" ? value.match(EXPRESSION_WORDS) ?? [] : [];
810
- }
811
- const EXPRESSION_WORDS = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
812
- //#endregion
813
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/is.mjs
814
- /**
815
- * Is the value `undefined`, `null`, or a whitespace-only string?
816
- * @param value Value to check
817
- * @returns `true` if the value is nullable or a whitespace-only string, otherwise `false`
818
- */
819
- function isNullableOrWhitespace(value) {
820
- return value == null || EXPRESSION_WHITESPACE$1.test(getString(value));
821
- }
822
- const EXPRESSION_WHITESPACE$1 = /^\s*$/;
823
- //#endregion
824
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
804
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/number.mjs
825
805
  /**
826
806
  * Clamp a number between a minimum and maximum value
827
807
  * @param value Value to clamp
@@ -840,7 +820,7 @@ function clamp(value, minimum, maximum, loop) {
840
820
  return value > maximum ? loop === true ? minimum : maximum : value;
841
821
  }
842
822
  //#endregion
843
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
823
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/sized.mjs
844
824
  function getSizedMaximum(first, second) {
845
825
  let actual;
846
826
  if (typeof first === "number") actual = first;
@@ -850,7 +830,7 @@ function getSizedMaximum(first, second) {
850
830
  const MAXIMUM_ABSOLUTE = 16777216;
851
831
  const MAXIMUM_DEFAULT = 1048576;
852
832
  //#endregion
853
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
833
+ //#region node_modules/@oscarpalmer/atoms/dist/sized/map.mjs
854
834
  /**
855
835
  * A Map with a maximum size
856
836
  *
@@ -904,7 +884,10 @@ var SizedMap = class extends Map {
904
884
  }
905
885
  };
906
886
  //#endregion
907
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
887
+ //#region node_modules/@oscarpalmer/atoms/dist/function/memoize.mjs
888
+ /**
889
+ * A memoized function, caching and retrieving results based on the its parameters _(or a custom cache key)_
890
+ */
908
891
  var Memoized = class {
909
892
  #state;
910
893
  /**
@@ -1000,7 +983,7 @@ function memoize(callback, options) {
1000
983
  const DEFAULT_CACHE_SIZE = 1024;
1001
984
  const SEPARATOR = "_";
1002
985
  //#endregion
1003
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/string/case.mjs
986
+ //#region node_modules/@oscarpalmer/atoms/dist/string/case.mjs
1004
987
  /**
1005
988
  * Convert a string to camel case _(thisIsCamelCase)_
1006
989
  * @param value String to convert
@@ -1079,16 +1062,19 @@ const delimiters = {
1079
1062
  let memoizedCapitalize;
1080
1063
  //#endregion
1081
1064
  //#region node_modules/@oscarpalmer/toretto/dist/internal/element-value.mjs
1082
- function setElementValue(element, first, second, third, callback) {
1065
+ function normalizeKey(key, style) {
1066
+ return style && key.startsWith(CSS_VARIABLE_PREFIX) ? key : kebabCase(key);
1067
+ }
1068
+ function setElementValue(element, first, second, third, callback, style) {
1083
1069
  if (!isHTMLOrSVGElement(element)) return;
1084
- if (typeof first === "string") setElementValues(element, first, second, third, callback);
1085
- else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback);
1070
+ if (typeof first === "string") setElementValues(element, first, second, third, callback, style);
1071
+ else if (isAttribute(first)) setElementValues(element, first.name, first.value, third, callback, style);
1086
1072
  }
1087
- function setElementValues(element, first, second, third, callback) {
1073
+ function setElementValues(element, first, second, third, callback, style) {
1088
1074
  if (!isHTMLOrSVGElement(element)) return;
1089
1075
  const dispatch = third !== false;
1090
1076
  if (typeof first === "string") {
1091
- callback(element, kebabCase(first), second, dispatch);
1077
+ callback(element, normalizeKey(first, style), second, dispatch);
1092
1078
  return;
1093
1079
  }
1094
1080
  const isArray = Array.isArray(first);
@@ -1100,22 +1086,26 @@ function setElementValues(element, first, second, third, callback) {
1100
1086
  const { length } = entries;
1101
1087
  for (let index = 0; index < length; index += 1) {
1102
1088
  const entry = entries[index];
1103
- if (typeof entry === "object" && typeof entry?.name === "string") callback(element, kebabCase(entry.name), entry.value, dispatch);
1089
+ if (typeof entry === "object" && typeof entry?.name === "string") callback(element, normalizeKey(entry.name, style), entry.value, dispatch);
1104
1090
  }
1105
1091
  }
1106
1092
  function updateElementValue(element, key, value, set, remove, isBoolean, json) {
1107
1093
  if (isBoolean ? value == null : isNullableOrWhitespace(value)) remove.call(element, key);
1108
1094
  else set.call(element, key, json ? JSON.stringify(value) : String(value));
1109
1095
  }
1096
+ const CSS_VARIABLE_PREFIX = "--";
1110
1097
  //#endregion
1111
1098
  //#region node_modules/@oscarpalmer/toretto/dist/internal/property.mjs
1112
- function updateProperty$1(element, name, value, dispatch) {
1099
+ function updateProperty(element, name, value, dispatch) {
1113
1100
  let property = name;
1114
1101
  if (!(property in element)) property = camelCase(name);
1115
1102
  if (!(property in element) || Object.is(element[property], value)) return;
1116
1103
  element[property] = value;
1117
1104
  const event = dispatch && elementEvents[element.tagName]?.[property];
1118
- if (typeof event === "string") element.dispatchEvent(new Event(event, { bubbles: true }));
1105
+ if (typeof event === "string") element.dispatchEvent(new Event(event, {
1106
+ bubbles: true,
1107
+ cancelable: true
1108
+ }));
1119
1109
  }
1120
1110
  const elementEvents = {
1121
1111
  DETAILS: { open: "toggle" },
@@ -1166,9 +1156,6 @@ function isAttribute(value) {
1166
1156
  function _isBadAttribute(first, second, decode) {
1167
1157
  return handleAttribute(badAttributeHandler, decode, first, second);
1168
1158
  }
1169
- function _isBooleanAttribute(first, decode) {
1170
- return handleAttribute((name) => booleanAttributesSet.has(name?.toLowerCase()), decode, first, "");
1171
- }
1172
1159
  function _isInvalidBooleanAttribute(first, second, decode) {
1173
1160
  return handleAttribute(booleanAttributeHandler, decode, first, second);
1174
1161
  }
@@ -1179,7 +1166,7 @@ function updateAttribute(element, name, value, dispatch) {
1179
1166
  const lowerCaseName = name.toLowerCase();
1180
1167
  const isBoolean = booleanAttributesSet.has(lowerCaseName);
1181
1168
  const next = isBoolean ? value === true || typeof value === "string" && (value === "" || value.toLowerCase() === lowerCaseName) : value == null ? "" : value;
1182
- if (isBoolean || dispatchedAttributes.has(name)) updateProperty$1(element, name, next, dispatch);
1169
+ if (isBoolean || dispatchedAttributes.has(name)) updateProperty(element, name, next, dispatch);
1183
1170
  updateElementValue(element, name, isBoolean ? next ? "" : null : value, element.setAttribute, element.removeAttribute, isBoolean, false);
1184
1171
  }
1185
1172
  const EXPRESSION_CLOBBERED_NAME = /^(id|name)$/i;
@@ -1424,6 +1411,7 @@ window.templates = templates;
1424
1411
  const ARRAY_COMPARISON_ADDED = "added";
1425
1412
  const ARRAY_COMPARISON_DISSIMILAR = "dissimilar";
1426
1413
  const ARRAY_COMPARISON_REMOVED = "removed";
1414
+ const CHANGE_INPUTS = new Set(["checkbox", "radio"]);
1427
1415
  const ERROR_FRAGMENT = "Fragment function must return a Fragment instance";
1428
1416
  const ERROR_IDENTIFIER_DUPLICATE = "Duplicate identifier found: '<id>'";
1429
1417
  const ERROR_IDENTIFIER_TYPE = "Identifier cannot be null or undefined";
@@ -1438,39 +1426,23 @@ const EVENT_DEFAULTS = {
1438
1426
  SELECT: EVENT_CHANGE,
1439
1427
  TEXTAREA: EVENT_INPUT
1440
1428
  };
1441
- const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-]+)="<!--abydon.(\d+)-->"/g;
1442
- const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
1443
- const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
1429
+ const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?[\w-.]+(?::[a-z:]+)?)="<!--abydon.(\d+)-->"/g;
1430
+ const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^abydon-/;
1431
+ const EXPRESSION_ABYDON_CONTENT = /^abydon\.(\d+)$/;
1444
1432
  const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
1445
1433
  const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
1446
1434
  const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
1447
- const EXPRESSION_EVENT_CHANGE_TYPES = /^(checkbox|radio)$/;
1448
- const EXPRESSION_EVENT_NAME = /^@([\w-]+)(?::([a-z:]+))?$/i;
1435
+ const EXPRESSION_ATTRIBUTE_STYLE_PROPERTY = /^style\.--/;
1436
+ const EXPRESSION_EVENT_ATTRIBUTE = /^@([\w-]+)(?::([a-z:]+))?="$/i;
1437
+ const EXPRESSION_EVENT_NAME = /^@?([\w-]+)(?::([a-z:]+))?$/i;
1449
1438
  const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
1450
1439
  const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
1451
1440
  const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
1452
1441
  const EXPRESSION_EVENT_PREFIX = /^@/;
1453
- const EXPRESSION_PERIOD = /\./;
1454
- const EXPRESSION_TEXTAREA_VALUE = /<!--abydon\.(\d+)-->/;
1442
+ const EXPRESSION_TEXTAREA_VALUE = /(?:<|&lt;)!--abydon\.(\d+)--(?:>|&gt;)/;
1455
1443
  const NAME_FRAGMENT = "$fragment";
1456
1444
  const NAME_FRAGMENTS = "$fragments";
1457
- const PROPERTY_CHECKED = "checked";
1458
- const PROPERTY_VALUE = "value";
1459
- //#endregion
1460
- //#region node_modules/@oscarpalmer/atoms/dist/string/index.mjs
1461
- /**
1462
- * Parse a JSON string into its proper value _(or `undefined` if it fails)_
1463
- * @param value JSON string to parse
1464
- * @param reviver Reviver function to transform the parsed values
1465
- * @returns Parsed value or `undefined` if parsing fails
1466
- */
1467
- function parse$1(value, reviver) {
1468
- try {
1469
- return JSON.parse(value, reviver);
1470
- } catch {
1471
- return;
1472
- }
1473
- }
1445
+ const WHITESPACE = /\s+/g;
1474
1446
  //#endregion
1475
1447
  //#region src/helpers/index.ts
1476
1448
  function compareArrays(first, second) {
@@ -1480,9 +1452,19 @@ function compareArrays(first, second) {
1480
1452
  if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return ARRAY_COMPARISON_DISSIMILAR;
1481
1453
  return firstIsLarger ? ARRAY_COMPARISON_REMOVED : ARRAY_COMPARISON_ADDED;
1482
1454
  }
1455
+ /**
1456
+ * Is the value a Fragment?
1457
+ * @param value Value to check
1458
+ * @returns `true` if the value is a Fragment, otherwise `false`
1459
+ */
1483
1460
  function isFragment(value) {
1484
1461
  return isNamed(value, NAME_FRAGMENT);
1485
1462
  }
1463
+ /**
1464
+ * Is the value a Fragments?
1465
+ * @param value Value to check
1466
+ * @returns `true` if the value is a Fragments, otherwise `false`
1467
+ */
1486
1468
  function isFragments(value) {
1487
1469
  return isNamed(value, NAME_FRAGMENTS);
1488
1470
  }
@@ -1493,12 +1475,6 @@ function isNamed(value, name) {
1493
1475
  //#region src/fragments.ts
1494
1476
  var Fragments = class {
1495
1477
  #state;
1496
- /**
1497
- * Fragment items
1498
- */
1499
- get items() {
1500
- return this.#state.mapped;
1501
- }
1502
1478
  constructor(items, identify, fragment) {
1503
1479
  Object.defineProperty(this, NAME_FRAGMENTS, { value: true });
1504
1480
  this.#state = {
@@ -1509,13 +1485,13 @@ var Fragments = class {
1509
1485
  mapped: array([]),
1510
1486
  subscriber: void 0
1511
1487
  };
1512
- states.set(this, this.#state);
1488
+ fragmentsStates.set(this, this.#state);
1513
1489
  initializeFragments(this.#state);
1514
1490
  }
1515
1491
  };
1516
1492
  function handleFragments(item, remove) {
1517
- const state = isFragments(item) ? states.get(item) : item;
1518
- if (state != null) (remove ? removeFragments$1 : initializeFragments)(state);
1493
+ const state = isFragments(item) ? fragmentsStates.get(item) : item;
1494
+ (remove ? removeFragments$1 : initializeFragments)(state);
1519
1495
  }
1520
1496
  function handleItems(state, items) {
1521
1497
  const keys = /* @__PURE__ */ new Set();
@@ -1525,7 +1501,7 @@ function handleItems(state, items) {
1525
1501
  const item = items[index];
1526
1502
  const identifier = state.identify(item);
1527
1503
  if (identifier == null) throw new TypeError(ERROR_IDENTIFIER_TYPE);
1528
- const key = getString$1(identifier);
1504
+ const key = getString(identifier);
1529
1505
  if (keys.has(key)) throw new Error(ERROR_IDENTIFIER_DUPLICATE.replace("<>", key));
1530
1506
  let instance = state.instances[key];
1531
1507
  if (instance == null) {
@@ -1563,13 +1539,13 @@ function updateFragments(state, active) {
1563
1539
  state.instances = next;
1564
1540
  active?.clear();
1565
1541
  }
1566
- const states = /* @__PURE__ */ new WeakMap();
1542
+ const fragmentsStates = /* @__PURE__ */ new WeakMap();
1567
1543
  //#endregion
1568
1544
  //#region src/helpers/dom.ts
1569
1545
  function createNodes(value) {
1570
1546
  if (isFragment(value)) return value.get();
1571
1547
  if (isChildNode(value)) return [value];
1572
- return [new Text(getString$1(value))];
1548
+ return [new Text(getString(value))];
1573
1549
  }
1574
1550
  function isInputElement(node) {
1575
1551
  return node instanceof HTMLInputElement || node instanceof HTMLSelectElement;
@@ -1679,7 +1655,7 @@ const EVENT_TYPES = new Set([
1679
1655
  const HANDLER_ACTIVE = delegatedEventHandler.bind(false);
1680
1656
  const HANDLER_PASSIVE = delegatedEventHandler.bind(true);
1681
1657
  //#endregion
1682
- //#region node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
1658
+ //#region node_modules/@oscarpalmer/atoms/dist/internal/function/misc.mjs
1683
1659
  /**
1684
1660
  * A function that does nothing, which can be useful, I guess…
1685
1661
  */
@@ -1718,89 +1694,106 @@ function getOptions(options) {
1718
1694
  function getType(element, type) {
1719
1695
  if (type !== "on") return type;
1720
1696
  if (element instanceof HTMLInputElement) {
1721
- if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return EVENT_CHANGE;
1697
+ if (CHANGE_INPUTS.has(element.type)) return EVENT_CHANGE;
1722
1698
  return element.type === "submit" ? EVENT_SUBMIT : EVENT_INPUT;
1723
1699
  }
1724
1700
  return EVENT_DEFAULTS[element.tagName] ?? type;
1725
1701
  }
1726
1702
  function mapEvent(element, name, value) {
1727
- const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
1728
- if (type != null && typeof value === "function") on(element, getType(element, type), value, getOptions(options ?? ""));
1703
+ const [, type, options] = EXPRESSION_EVENT_NAME.exec(name);
1704
+ const values = Array.isArray(value) ? value : [value];
1705
+ const { length } = values;
1706
+ for (let index = 0; index < length; index += 1) {
1707
+ const item = values[index];
1708
+ if (typeof item === "function") on(element, getType(element, type), item, getOptions(options ?? ""));
1709
+ }
1729
1710
  }
1730
1711
  //#endregion
1731
- //#region node_modules/@oscarpalmer/toretto/dist/attribute/index.mjs
1732
- function isBooleanAttribute(first) {
1733
- return _isBooleanAttribute(first, true);
1734
- }
1712
+ //#region node_modules/@oscarpalmer/toretto/dist/style.mjs
1713
+ /**
1714
+ * Set a style on an element
1715
+ * @param element Element to set the style on
1716
+ * @param property Style name
1717
+ * @param value Style value
1718
+ */
1719
+ function setStyle(element, property, value) {
1720
+ setElementValues(element, property, value, null, updateStyleProperty, true);
1721
+ }
1722
+ function updateStyleProperty(element, key, value) {
1723
+ updateElementValue(element, key, value, function(property, style) {
1724
+ if (property.startsWith(VARIABLE_PREFIX)) this.style.setProperty(property, String(style));
1725
+ else this.style[property] = String(style);
1726
+ }, function(property) {
1727
+ if (property.startsWith(VARIABLE_PREFIX)) this.style.removeProperty(property);
1728
+ else this.style[property] = "";
1729
+ if (this.getAttribute(ATTRIBUTE_STYLE) === "") this.removeAttribute(ATTRIBUTE_STYLE);
1730
+ }, false, false);
1731
+ }
1732
+ const ATTRIBUTE_STYLE = "style";
1733
+ const VARIABLE_PREFIX = "--";
1735
1734
  //#endregion
1736
- //#region src/node/attribute/value.ts
1737
- function getCallback(element, name) {
1738
- if (isBooleanAttribute(name) && name in element) return name === "checked" ? updateChecked : updateProperty;
1739
- return name === "value" ? updateValue : setAttribute$1;
1735
+ //#region src/attribute/value.ts
1736
+ function getStyleValue(value, unit, isProperty) {
1737
+ if (removeStyleValue(value, unit, isProperty)) return;
1738
+ return value === true || value === "true" ? unit : `${getString(value)}${unit ?? ""}`;
1739
+ }
1740
+ function removeStyleValue(value, unit, isProperty) {
1741
+ if (value == null || value === false || isProperty && isNullableOrWhitespace(value)) return true;
1742
+ return unit == null && (value === true || value === "true");
1740
1743
  }
1741
1744
  function setAttribute(data, element, name, value) {
1742
1745
  switch (true) {
1743
1746
  case EXPRESSION_ATTRIBUTE_CLASS.test(name):
1744
- setClasses(data, element, name, value);
1747
+ setClassValues(data, element, name, value);
1745
1748
  return;
1746
1749
  case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
1747
- setStyle(data, element, name, value);
1750
+ setStyleValues(data, element, name, value);
1748
1751
  return;
1749
1752
  default:
1750
1753
  setValue(data, element, name, value);
1751
1754
  break;
1752
1755
  }
1753
1756
  }
1754
- function setClasses(data, element, name, value) {
1757
+ function setClassValues(data, element, name, value) {
1755
1758
  function update(value) {
1756
- if (value === true) element.classList.add(...classes);
1759
+ if (value === true || value === "true") element.classList.add(...classes);
1757
1760
  else element.classList.remove(...classes);
1758
1761
  }
1759
1762
  const classes = name.slice(6).split(".");
1760
1763
  if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
1761
1764
  else update(value);
1762
1765
  }
1763
- function setStyle(data, element, name, value) {
1764
- const [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name) ?? [];
1765
- if (property == null) return;
1766
+ function setStyleValues(data, element, name, value) {
1767
+ let [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name);
1768
+ const isProperty = EXPRESSION_ATTRIBUTE_STYLE_PROPERTY.test(name);
1769
+ property = camelCase(property);
1770
+ if (isProperty) property = `--${property}`;
1766
1771
  function update(value) {
1767
- if (value == null || value === false || value === true && unit == null) element.style.removeProperty(property);
1768
- else element.style.setProperty(property, value === true ? unit : String(value));
1772
+ setStyle(element, property, getStyleValue(value, unit, isProperty));
1769
1773
  }
1770
1774
  if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
1771
1775
  else update(value);
1772
1776
  }
1773
1777
  function setValue(data, element, name, value) {
1774
- const callback = getCallback(element, name);
1775
- if (isReactive(value)) data.mora.subscribers.add(value.subscribe((next) => {
1776
- callback(element, name, next);
1778
+ const isReactiveValue = isReactive(value);
1779
+ unsetValue(element, name, isReactiveValue ? value.peek() : value);
1780
+ if (isReactiveValue) data.mora.subscribers.add(value.subscribe((next) => {
1781
+ setAttribute$1(element, name, next);
1777
1782
  }));
1778
- else callback(element, name, value);
1779
- }
1780
- function updateChecked(element, name, value) {
1781
- updateElement(EVENT_CHANGE, PROPERTY_CHECKED, element, name, value, value === true);
1782
- }
1783
- function updateElement(event, property, element, name, value, next) {
1784
- if (!(property in element) || element[property] === next) return;
1785
- setAttribute$1(element, name, value);
1786
- if (element[property] === next) return;
1787
- element[property] = next;
1788
- element.dispatchEvent(new Event(event, { bubbles: true }));
1783
+ else setAttribute$1(element, name, value);
1789
1784
  }
1790
- function updateProperty(element, name, value) {
1791
- setAttribute$1(element, name, value === true);
1792
- }
1793
- function updateValue(element, name, value) {
1794
- updateElement(element instanceof HTMLSelectElement ? EVENT_CHANGE : EVENT_INPUT, PROPERTY_VALUE, element, name, value, String(value));
1785
+ function unsetValue(element, name, value) {
1786
+ if (name === "checked") element.checked = !(value === true || value === "true");
1787
+ if (name === "value") element.value = element.value === "" ? "_" : "";
1795
1788
  }
1796
1789
  //#endregion
1797
- //#region src/node/attribute/index.ts
1790
+ //#region src/attribute/index.ts
1798
1791
  function getValue(data, original) {
1799
- const matches = EXPRESSION_ABYDON_CONTENT.exec(original ?? "");
1792
+ const matches = EXPRESSION_ABYDON_CONTENT.exec(original);
1800
1793
  return matches == null ? original : data.values[+matches[1]];
1801
1794
  }
1802
1795
  function mapAttributes(data, element) {
1803
- const attributes = [...element.attributes];
1796
+ const attributes = [...element.attributes].sort((first, second) => first.name.localeCompare(second.name));
1804
1797
  const { length } = attributes;
1805
1798
  for (let index = 0; index < length; index += 1) {
1806
1799
  const { name, value } = attributes[index];
@@ -1811,25 +1804,17 @@ function mapAttributes(data, element) {
1811
1804
  case EXPRESSION_EVENT_PREFIX.test(actualName):
1812
1805
  mapEvent(element, actualName, actualValue);
1813
1806
  break;
1814
- case EXPRESSION_PERIOD.test(actualName):
1815
- case typeof actualValue === "function":
1816
- case isReactive(actualValue):
1807
+ default:
1817
1808
  mapValue$1(data, element, actualName, actualValue);
1818
1809
  break;
1819
- default: break;
1820
1810
  }
1821
1811
  }
1822
1812
  }
1823
1813
  function mapValue$1(data, element, name, value) {
1824
1814
  if (typeof value === "function") setComputedAttribute(data, element, name, value);
1825
1815
  else setAttribute(data, element, name, value);
1826
- if (!isInputElement(element) || !isSignal(value)) return;
1827
- let property;
1828
- if (name === "checked" && element.type === "checkbox") property = PROPERTY_CHECKED;
1829
- else if (name === "value") property = PROPERTY_VALUE;
1830
- if (property != null) mapEvent(element, "@on", () => {
1831
- const next = element[property];
1832
- value.set(parse$1(String(next)) ?? next);
1816
+ if (isInputElement(element) && isSignal(value) && name in element) mapEvent(element, "on", () => {
1817
+ value.set(element[name]);
1833
1818
  });
1834
1819
  }
1835
1820
  function setComputedAttribute(data, element, name, callback) {
@@ -1886,14 +1871,15 @@ function setArray(item, comment, value) {
1886
1871
  let templates = value.filter((item) => isFragment(item) && item.identifier != null);
1887
1872
  const next = templates.map((fragment) => fragment.identifier);
1888
1873
  const previous = item.fragments?.map((fragment) => fragment.identifier) ?? [];
1889
- if (new Set(next).size !== templates.length) templates = [];
1874
+ const nextSet = new Set(next);
1875
+ if (nextSet.size !== templates.length) templates = [];
1890
1876
  const noTemplates = templates.length === 0;
1891
1877
  if (noTemplates || item.nodes == null || previous.some((identifier) => identifier == null)) return {
1892
1878
  fragments: noTemplates ? void 0 : templates,
1893
1879
  nodes: setNodes(item, comment, noTemplates ? value.flatMap((item) => createNodes(item)) : templates.flatMap((template) => template.get()))
1894
1880
  };
1895
1881
  return handleArray({
1896
- next: new Set(next),
1882
+ next: nextSet,
1897
1883
  previous: new Set(previous)
1898
1884
  }, {
1899
1885
  templates,
@@ -1901,10 +1887,8 @@ function setArray(item, comment, value) {
1901
1887
  }, item.nodes);
1902
1888
  }
1903
1889
  function setNodes(item, comment, next) {
1904
- if (item.nodes == null) {
1905
- if (comment.parentNode != null) replaceNodes([comment], next);
1906
- else if (item.text?.parentNode != null) replaceNodes([item.text], next);
1907
- } else replaceNodes(item.nodes, next);
1890
+ if (item.nodes == null) replaceNodes([comment], next);
1891
+ else replaceNodes(item.nodes, next);
1908
1892
  removeFragments(item.fragments);
1909
1893
  return next;
1910
1894
  }
@@ -1915,15 +1899,13 @@ function setReactiveValue(data, comment, reactive) {
1915
1899
  data.mora.subscribers.add(reactive.subscribe((value) => {
1916
1900
  if (Array.isArray(value)) setReactiveValueForArray(item, comment, value);
1917
1901
  else setReactiveValueForSingle(item, comment, value);
1918
- item.nodes = [...item.nodes ?? [comment]];
1902
+ item.nodes ??= [comment];
1919
1903
  }));
1920
1904
  }
1921
1905
  function setReactiveValueForArray(item, comment, value) {
1922
- const result = setArray(item, comment, value);
1923
- item.fragments = typeof result === "boolean" ? void 0 : result?.fragments;
1924
- if (typeof result === "boolean") if (result) item.nodes = item.text == null ? [] : [item.text];
1925
- else item.nodes = void 0;
1926
- else item.nodes = result?.nodes;
1906
+ const { fragments, nodes } = setArray(item, comment, value);
1907
+ item.fragments = fragments;
1908
+ item.nodes = nodes;
1927
1909
  }
1928
1910
  function setReactiveValueForSingle(item, comment, value) {
1929
1911
  const valueIsFragment = isFragment(value);
@@ -1932,8 +1914,8 @@ function setReactiveValueForSingle(item, comment, value) {
1932
1914
  else item.nodes = setText(item, comment, value);
1933
1915
  }
1934
1916
  function setText(item, comment, value) {
1935
- const isNullable = isNullableOrWhitespace$1(value);
1936
- if (item.text != null) item.text.textContent = isNullable ? "" : getString$1(value);
1917
+ const isNullable = isNullableOrWhitespace(value);
1918
+ if (item.text != null) item.text.textContent = isNullable ? "" : getString(value);
1937
1919
  let result = false;
1938
1920
  if (item.nodes != null) {
1939
1921
  replaceText(item, comment, isNullable);
@@ -1949,7 +1931,7 @@ function setText(item, comment, value) {
1949
1931
  //#endregion
1950
1932
  //#region src/node/index.ts
1951
1933
  function mapNode(data, comment) {
1952
- const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent ?? "");
1934
+ const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent);
1953
1935
  const value = matches == null ? null : data.values[+matches[1]];
1954
1936
  if (value != null) mapValue(data, comment, value);
1955
1937
  }
@@ -1967,23 +1949,27 @@ function mapNodes(data, nodes) {
1967
1949
  }
1968
1950
  }
1969
1951
  function mapTextarea(data, element) {
1970
- const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
1952
+ const [, index] = EXPRESSION_TEXTAREA_VALUE.exec(element.textContent) ?? EXPRESSION_TEXTAREA_VALUE.exec(element.value) ?? [];
1971
1953
  if (index == null) return;
1954
+ element.textContent = "";
1972
1955
  element.value = "";
1973
1956
  const value = data.values[Number.parseInt(index, 10)];
1974
1957
  if (isSignal(value)) {
1975
- element.value = String(value.peek());
1976
- mapEvent(element, "@on", () => {
1958
+ element.value = getString(value.peek());
1959
+ mapEvent(element, "on", () => {
1977
1960
  value.set(element.value);
1978
1961
  });
1962
+ data.mora.subscribers.add(value.subscribe((value) => {
1963
+ element.value = getString(value);
1964
+ }));
1979
1965
  return;
1980
1966
  }
1981
1967
  let reactive;
1982
1968
  if (typeof value === "function") reactive = computed(value);
1983
1969
  else if (isComputed(value)) reactive = value;
1984
- if (reactive == null) element.value = String(value);
1970
+ if (reactive == null) element.value = "";
1985
1971
  else data.mora.subscribers.add(reactive.subscribe((value) => {
1986
- element.value = String(value);
1972
+ element.value = getString(value);
1987
1973
  }));
1988
1974
  }
1989
1975
  function mapValue(data, comment, value) {
@@ -1992,8 +1978,7 @@ function mapValue(data, comment, value) {
1992
1978
  setComputedValue(data, comment, value);
1993
1979
  break;
1994
1980
  case isFragments(value):
1995
- handleFragments(value, false);
1996
- setReactiveValue(data, comment, value.items);
1981
+ setFragmentsValue(data, comment, value);
1997
1982
  break;
1998
1983
  case isReactive(value):
1999
1984
  setReactiveValue(data, comment, value);
@@ -2017,17 +2002,24 @@ function setComputedValue(data, comment, callback) {
2017
2002
  data.mora.values.add(value);
2018
2003
  setReactiveValue(data, comment, value);
2019
2004
  }
2005
+ function setFragmentsValue(data, comment, fragments) {
2006
+ const state = fragmentsStates.get(fragments);
2007
+ handleFragments(state, false);
2008
+ setReactiveValue(data, comment, state.mapped);
2009
+ }
2020
2010
  //#endregion
2021
2011
  //#region src/parse.ts
2022
2012
  function handleExpression(data, prefix, expression) {
2023
2013
  if (Array.isArray(expression)) {
2014
+ if (EXPRESSION_EVENT_ATTRIBUTE.test(prefix.split(WHITESPACE).at(-1))) return transformExpression(prefix, data.values.push(expression) - 1);
2024
2015
  const { length } = expression;
2025
2016
  let expressions = "";
2026
2017
  for (let index = 0; index < length; index += 1) expressions += handleExpression(data, "", expression[index]);
2027
2018
  return `${prefix}${expressions}`;
2028
2019
  }
2029
2020
  if (typeof expression === "function" || typeof expression === "object" && expression != null) return transformExpression(prefix, data.values.push(expression) - 1);
2030
- return isNullableOrWhitespace$1(expression) ? prefix : `${prefix}${expression}`;
2021
+ const asString = getString(expression);
2022
+ return asString.trim().length === 0 ? prefix : `${prefix}${asString}`;
2031
2023
  }
2032
2024
  function parse(data) {
2033
2025
  if (data.template != null) return data.template;
@@ -2040,7 +2032,7 @@ function parse(data) {
2040
2032
  return data.template;
2041
2033
  }
2042
2034
  function transformAttribute(_, name, index) {
2043
- return `_${name}="@abydon.${index}@"`;
2035
+ return `abydon-${name}="abydon.${index}"`;
2044
2036
  }
2045
2037
  function transformExpression(prefix, index) {
2046
2038
  return `${prefix}<!--abydon.${index}-->`;
@@ -2054,6 +2046,12 @@ var Fragment = class {
2054
2046
  cache: true
2055
2047
  };
2056
2048
  /**
2049
+ * Is template caching enabled?
2050
+ */
2051
+ get caching() {
2052
+ return this.#configuration.cache;
2053
+ }
2054
+ /**
2057
2055
  * Fragment identifier
2058
2056
  */
2059
2057
  get identifier() {
@@ -2085,7 +2083,7 @@ var Fragment = class {
2085
2083
  * @returns Fragment
2086
2084
  */
2087
2085
  configure(configuration) {
2088
- const actual = isPlainObject$1(configuration) ? configuration : {};
2086
+ const actual = isPlainObject(configuration) ? configuration : {};
2089
2087
  if ("identifier" in actual) this.#configuration.identifier = actual.identifier;
2090
2088
  if (typeof actual.cache === "boolean") this.#configuration.cache = actual.cache;
2091
2089
  return this;
@@ -2099,9 +2097,9 @@ var Fragment = class {
2099
2097
  if (data.items.length === 0) {
2100
2098
  const templated = html$1(parse(data), { cache: this.#configuration.cache });
2101
2099
  data.items.splice(0, data.items.length, ...templated.map((node) => ({ nodes: [node] })));
2102
- mapNodes(data, data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []));
2100
+ mapNodes(data, data.items.flatMap((item) => item.nodes));
2103
2101
  }
2104
- return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []);
2102
+ return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes);
2105
2103
  }
2106
2104
  /**
2107
2105
  * Set an identifier for the fragment
@@ -2129,7 +2127,7 @@ function removeFragment(data) {
2129
2127
  const { fragments, nodes } = data.items[index];
2130
2128
  const fragmentsLength = fragments?.length ?? 0;
2131
2129
  for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
2132
- removeNodes(nodes ?? []);
2130
+ removeNodes(nodes);
2133
2131
  }
2134
2132
  data.items.length = 0;
2135
2133
  length = data.values.length;
@@ -2147,21 +2145,24 @@ function removeMora(data) {
2147
2145
  //#endregion
2148
2146
  //#region src/index.ts
2149
2147
  /**
2150
- * Create Fragments from a reactive array
2148
+ * Create a Fragments from a reactive array
2151
2149
  * @param array Reactive array
2152
2150
  * @param identify Function to identify item
2153
2151
  * @param fragment Function to create fragment from item
2154
2152
  * @returns Fragments
2155
2153
  */
2156
2154
  function fragments(array, identify, fragment) {
2155
+ if (!isArray(array)) throw new TypeError("Fragments array must be a reactive array");
2156
+ if (typeof identify !== "function") throw new TypeError("Fragments identify must be a function");
2157
+ if (typeof fragment !== "function") throw new TypeError("Fragments fragment must be a function");
2157
2158
  return new Fragments(array, identify, fragment);
2158
2159
  }
2159
2160
  /**
2160
- * Create Fragment from a template
2161
+ * Create a Fragment from a template
2161
2162
  * @returns Fragment
2162
2163
  */
2163
2164
  function html(template, ...values) {
2164
2165
  return new Fragment(template, values);
2165
2166
  }
2166
2167
  //#endregion
2167
- export { array, computed, effect, fragments, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
2168
+ export { array, computed, effect, fragments, html, isArray, isComputed, isEffect, isFragment, isFragments, isReactive, isSignal, signal, startBatch, stopBatch, store };