regor 1.4.4 → 1.4.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.
@@ -88,6 +88,7 @@ var Regor = (() => {
88
88
  onUnmounted: () => onUnmounted,
89
89
  pause: () => pause,
90
90
  persist: () => persist,
91
+ pval: () => pval,
91
92
  raw: () => raw,
92
93
  ref: () => ref,
93
94
  removeNode: () => removeNode,
@@ -418,6 +419,37 @@ var Regor = (() => {
418
419
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
419
420
  );
420
421
  }
422
+ /**
423
+ * Validates selected incoming props using assertion-style validators.
424
+ *
425
+ * Only keys listed in `schema` are checked. Validation throws immediately
426
+ * on the first invalid prop and does not mutate `head.props`.
427
+ *
428
+ * The schema is keyed from `head.props`, so editor completion can suggest
429
+ * known prop names while still allowing you to validate only a subset.
430
+ *
431
+ * Validators typically come from `pval`, but custom user validators are also
432
+ * supported.
433
+ *
434
+ * Example:
435
+ * ```ts
436
+ * head.validateProps({
437
+ * title: pval.isString,
438
+ * count: pval.optional(pval.isNumber),
439
+ * })
440
+ * ```
441
+ *
442
+ * @param schema - Validators to apply to selected incoming props.
443
+ */
444
+ validateProps(schema) {
445
+ const props = this.props;
446
+ for (const name in schema) {
447
+ const validator = schema[name];
448
+ if (!validator) continue;
449
+ const validateProp = validator;
450
+ validateProp(props[name], name, this);
451
+ }
452
+ }
421
453
  /**
422
454
  * Unmounts this component instance by removing nodes between `start` and `end`
423
455
  * and calling unmount lifecycle handlers for captured contexts.
@@ -566,10 +598,13 @@ var Regor = (() => {
566
598
  }
567
599
  __bindAll(element) {
568
600
  const isIfElement = element.hasAttribute(this.__if);
569
- const elements = findElements(element, this.__ifSelector);
570
- for (const el of elements) {
571
- this.__bind(el);
572
- }
601
+ if (isIfElement) this.__bind(element);
602
+ this.__binder.__componentBinder.__forEachBindableDescendant(
603
+ element,
604
+ (el) => {
605
+ if (el.hasAttribute(this.__if)) this.__bind(el);
606
+ }
607
+ );
573
608
  return isIfElement;
574
609
  }
575
610
  __isProcessedOrMark(el) {
@@ -1361,8 +1396,16 @@ var Regor = (() => {
1361
1396
  }
1362
1397
  return false;
1363
1398
  }
1399
+ __isNamedSlotTemplateShortcut(node) {
1400
+ if (!isTemplate(node)) return false;
1401
+ const attributeNames = node.getAttributeNames();
1402
+ if (node.hasAttribute("name")) return true;
1403
+ return attributeNames.some((x) => x.startsWith("#"));
1404
+ }
1405
+ __isDefaultSlotTemplateShortcut(node) {
1406
+ return isTemplate(node) && node.getAttributeNames().length === 0;
1407
+ }
1364
1408
  __unwrapComponents(element) {
1365
- var _a;
1366
1409
  const binder = this.__binder;
1367
1410
  const parser = binder.__parser;
1368
1411
  const registeredComponents = binder.__config.__components;
@@ -1371,16 +1414,9 @@ var Regor = (() => {
1371
1414
  return;
1372
1415
  }
1373
1416
  const contextComponents = parser.__getComponents();
1374
- const contextComponentSelectors = parser.__getComponentSelectors();
1375
- const registeredSelector = this.__getRegisteredComponentSelector(registeredComponents);
1376
- const selector = [
1377
- ...registeredSelector ? [registeredSelector] : [],
1378
- ...contextComponentSelectors,
1379
- ...contextComponentSelectors.map(hyphenate)
1380
- ].join(",");
1417
+ const selector = this.__getComponentSelector();
1381
1418
  if (isNullOrWhitespace(selector)) return;
1382
- const list = element.querySelectorAll(selector);
1383
- const components = ((_a = element.matches) == null ? void 0 : _a.call(element, selector)) ? [element, ...list] : list;
1419
+ const components = this.__collectTopLevelComponentHosts(element, selector);
1384
1420
  for (const component of components) {
1385
1421
  if (component.hasAttribute(binder.__pre)) continue;
1386
1422
  const parent = component.parentNode;
@@ -1454,7 +1490,7 @@ var Regor = (() => {
1454
1490
  };
1455
1491
  const capturedContext = [...parser.__capture()];
1456
1492
  const createComponentCtx = () => {
1457
- var _a2;
1493
+ var _a;
1458
1494
  const props = getProps(component, capturedContext);
1459
1495
  const head2 = new ComponentHead(
1460
1496
  props,
@@ -1464,8 +1500,8 @@ var Regor = (() => {
1464
1500
  endOfComponent
1465
1501
  );
1466
1502
  const componentCtx2 = useScope(() => {
1467
- var _a3;
1468
- return (_a3 = registeredComponent.context(head2)) != null ? _a3 : {};
1503
+ var _a2;
1504
+ return (_a2 = registeredComponent.context(head2)) != null ? _a2 : {};
1469
1505
  }).context;
1470
1506
  if (head2.autoProps) {
1471
1507
  for (const [key, propsValue] of Object.entries(props)) {
@@ -1489,7 +1525,7 @@ var Regor = (() => {
1489
1525
  }
1490
1526
  } else componentCtx2[key] = propsValue;
1491
1527
  }
1492
- (_a2 = head2.onAutoPropsAssigned) == null ? void 0 : _a2.call(head2);
1528
+ (_a = head2.onAutoPropsAssigned) == null ? void 0 : _a.call(head2);
1493
1529
  }
1494
1530
  return { componentCtx: componentCtx2, head: head2 };
1495
1531
  };
@@ -1498,6 +1534,7 @@ var Regor = (() => {
1498
1534
  const len = childNodes.length;
1499
1535
  const isEmptyComponent = component.childNodes.length === 0;
1500
1536
  const expandSlot = (slot) => {
1537
+ var _a;
1501
1538
  const parent2 = slot.parentElement;
1502
1539
  let name = slot.name;
1503
1540
  if (isNullOrWhitespace(name)) {
@@ -1527,9 +1564,12 @@ var Regor = (() => {
1527
1564
  `template[name='${name}'], template[\\#${name}]`
1528
1565
  );
1529
1566
  if (!compTemplate && name === "default") {
1530
- compTemplate = component.querySelector("template:not([name])");
1531
- if (compTemplate && compTemplate.getAttributeNames().filter((x) => x.startsWith("#")).length > 0)
1532
- compTemplate = null;
1567
+ const unnamedTemplates = component.querySelectorAll(
1568
+ "template:not([name])"
1569
+ );
1570
+ compTemplate = (_a = [...unnamedTemplates].find(
1571
+ (x) => this.__isDefaultSlotTemplateShortcut(x)
1572
+ )) != null ? _a : null;
1533
1573
  }
1534
1574
  const createSwitchContext = (childNodes2) => {
1535
1575
  if (!head.enableSwitch) return;
@@ -1565,7 +1605,7 @@ var Regor = (() => {
1565
1605
  return;
1566
1606
  }
1567
1607
  const childNodes2 = [...getChildNodes(component)].filter(
1568
- (x) => !isTemplate(x)
1608
+ (x) => !this.__isNamedSlotTemplateShortcut(x)
1569
1609
  );
1570
1610
  for (const slotChild of childNodes2) {
1571
1611
  parent2.insertBefore(slotChild, slot);
@@ -1651,6 +1691,65 @@ var Regor = (() => {
1651
1691
  parser.__scoped(capturedContext, bindComponent);
1652
1692
  }
1653
1693
  }
1694
+ __getComponentSelector() {
1695
+ const binder = this.__binder;
1696
+ const parser = binder.__parser;
1697
+ const registeredComponents = binder.__config.__components;
1698
+ const contextComponentSelectors = parser.__getComponentSelectors();
1699
+ const registeredSelector = this.__getRegisteredComponentSelector(registeredComponents);
1700
+ return [
1701
+ ...registeredSelector ? [registeredSelector] : [],
1702
+ ...contextComponentSelectors,
1703
+ ...contextComponentSelectors.map(hyphenate)
1704
+ ].join(",");
1705
+ }
1706
+ __collectTopLevelComponentHosts(root, selector) {
1707
+ var _a;
1708
+ const result = [];
1709
+ if (isNullOrWhitespace(selector)) return result;
1710
+ if ((_a = root.matches) == null ? void 0 : _a.call(root, selector)) return [root];
1711
+ const stack = this.__getChildElements(root).reverse();
1712
+ while (stack.length > 0) {
1713
+ const current = stack.pop();
1714
+ if (current.matches(selector)) {
1715
+ result.push(current);
1716
+ continue;
1717
+ }
1718
+ stack.push(...this.__getChildElements(current).reverse());
1719
+ }
1720
+ return result;
1721
+ }
1722
+ __forEachBindableDescendant(root, action) {
1723
+ const selector = this.__getComponentSelector();
1724
+ const stack = this.__getChildElements(root).reverse();
1725
+ while (stack.length > 0) {
1726
+ const current = stack.pop();
1727
+ action(current);
1728
+ if (!isNullOrWhitespace(selector) && current.matches(selector)) continue;
1729
+ stack.push(...this.__getChildElements(current).reverse());
1730
+ }
1731
+ }
1732
+ __getChildElements(root) {
1733
+ const children = root == null ? void 0 : root.children;
1734
+ if ((children == null ? void 0 : children.length) != null) {
1735
+ const result = [];
1736
+ for (let i = 0; i < children.length; ++i) {
1737
+ const child = children[i];
1738
+ if (isElement(child)) result.push(child);
1739
+ }
1740
+ return result;
1741
+ }
1742
+ const childNodes = root == null ? void 0 : root.childNodes;
1743
+ if ((childNodes == null ? void 0 : childNodes.length) != null) {
1744
+ const result = [];
1745
+ for (let i = 0; i < childNodes.length; ++i) {
1746
+ const child = childNodes[i];
1747
+ if (isElement(child)) result.push(child);
1748
+ }
1749
+ return result;
1750
+ }
1751
+ return [];
1752
+ }
1654
1753
  };
1655
1754
 
1656
1755
  // src/bind/DirectiveCollector.ts
@@ -1743,10 +1842,10 @@ var Regor = (() => {
1743
1842
  };
1744
1843
  processNode(element);
1745
1844
  if (!isRecursive || !element.firstElementChild) return map;
1746
- const nodes = element.querySelectorAll("*");
1747
- for (const node of nodes) {
1748
- processNode(node);
1749
- }
1845
+ this.__binder.__componentBinder.__forEachBindableDescendant(
1846
+ element,
1847
+ processNode
1848
+ );
1750
1849
  return map;
1751
1850
  }
1752
1851
  };
@@ -1764,17 +1863,19 @@ var Regor = (() => {
1764
1863
  constructor(binder) {
1765
1864
  __publicField(this, "__binder");
1766
1865
  __publicField(this, "__is");
1767
- __publicField(this, "__isSelector");
1768
1866
  this.__binder = binder;
1769
1867
  this.__is = binder.__config.__builtInNames.is;
1770
- this.__isSelector = toSelector(this.__is) + ", [is]";
1771
1868
  }
1772
1869
  __bindAll(element) {
1773
1870
  const isComponentElement = element.hasAttribute(this.__is);
1774
- const elements = findElements(element, this.__isSelector);
1775
- for (const el of elements) {
1776
- this.__bind(el);
1777
- }
1871
+ if (isComponentElement || element.hasAttribute("is"))
1872
+ this.__bind(element);
1873
+ this.__binder.__componentBinder.__forEachBindableDescendant(
1874
+ element,
1875
+ (el) => {
1876
+ if (el.hasAttribute(this.__is) || el.hasAttribute("is")) this.__bind(el);
1877
+ }
1878
+ );
1778
1879
  return isComponentElement;
1779
1880
  }
1780
1881
  __bind(el) {
@@ -2251,10 +2352,13 @@ var Regor = (() => {
2251
2352
  }
2252
2353
  __bindAll(element) {
2253
2354
  const isForElement = element.hasAttribute(this.__for);
2254
- const elements = findElements(element, this.__forSelector);
2255
- for (const el of elements) {
2256
- this.__bindFor(el);
2257
- }
2355
+ if (isForElement) this.__bindFor(element);
2356
+ this.__binder.__componentBinder.__forEachBindableDescendant(
2357
+ element,
2358
+ (el) => {
2359
+ if (el.hasAttribute(this.__for)) this.__bindFor(el);
2360
+ }
2361
+ );
2258
2362
  return isForElement;
2259
2363
  }
2260
2364
  __isProcessedOrMark(el) {
@@ -2931,11 +3035,11 @@ var Regor = (() => {
2931
3035
  }
2932
3036
  return;
2933
3037
  }
2934
- const isBoolean = key in booleanAttributes;
2935
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
3038
+ const isBoolean2 = key in booleanAttributes;
3039
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
2936
3040
  el.removeAttribute(key);
2937
3041
  } else {
2938
- el.setAttribute(key, isBoolean ? "" : value);
3042
+ el.setAttribute(key, isBoolean2 ? "" : value);
2939
3043
  }
2940
3044
  };
2941
3045
 
@@ -3185,7 +3289,7 @@ var Regor = (() => {
3185
3289
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3186
3290
  const isLazy = flags.lazy;
3187
3291
  const eventType = isLazy ? "change" : "input";
3188
- const isNumber = isNumberInput(el);
3292
+ const isNumber2 = isNumberInput(el);
3189
3293
  const trimmer = () => {
3190
3294
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3191
3295
  el.value = el.value.trim();
@@ -3215,7 +3319,7 @@ var Regor = (() => {
3215
3319
  if (!target || target.composing) return;
3216
3320
  let value = target.value;
3217
3321
  const flags2 = getFlags(parsedValue()[1]);
3218
- if (isNumber || flags2.number || flags2.int) {
3322
+ if (isNumber2 || flags2.number || flags2.int) {
3219
3323
  if (flags2.int) {
3220
3324
  value = parseInt(value);
3221
3325
  } else {
@@ -4530,12 +4634,12 @@ var Regor = (() => {
4530
4634
  this.__gobbleSpaces();
4531
4635
  let ch = this.__code;
4532
4636
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4533
- let optional;
4637
+ let optional2;
4534
4638
  if (ch === QUMARK_CODE) {
4535
4639
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4536
4640
  break;
4537
4641
  }
4538
- optional = true;
4642
+ optional2 = true;
4539
4643
  this.__index += 2;
4540
4644
  this.__gobbleSpaces();
4541
4645
  ch = this.__code;
@@ -4561,7 +4665,7 @@ var Regor = (() => {
4561
4665
  callee: node
4562
4666
  };
4563
4667
  } else {
4564
- if (optional) {
4668
+ if (optional2) {
4565
4669
  this.__index--;
4566
4670
  }
4567
4671
  this.__gobbleSpaces();
@@ -4572,7 +4676,7 @@ var Regor = (() => {
4572
4676
  property: this.__gobbleIdentifier()
4573
4677
  };
4574
4678
  }
4575
- if (optional) {
4679
+ if (optional2) {
4576
4680
  node.optional = true;
4577
4681
  }
4578
4682
  this.__gobbleSpaces();
@@ -6102,6 +6206,113 @@ var Regor = (() => {
6102
6206
  };
6103
6207
  };
6104
6208
 
6209
+ // src/app/propValidators.ts
6210
+ var fail = (name, message) => {
6211
+ throw new Error(`Invalid prop "${name}": ${message}.`);
6212
+ };
6213
+ var describeValue = (value) => {
6214
+ var _a;
6215
+ if (value === null) return "null";
6216
+ if (value === void 0) return "undefined";
6217
+ if (typeof value === "string") return "string";
6218
+ if (typeof value === "number") return "number";
6219
+ if (typeof value === "boolean") return "boolean";
6220
+ if (typeof value === "bigint") return "bigint";
6221
+ if (typeof value === "symbol") return "symbol";
6222
+ if (typeof value === "function") return "function";
6223
+ if (isArray(value)) return "array";
6224
+ if (value instanceof Date) return "Date";
6225
+ if (value instanceof RegExp) return "RegExp";
6226
+ if (value instanceof Map) return "Map";
6227
+ if (value instanceof Set) return "Set";
6228
+ const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
6229
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
6230
+ };
6231
+ var formatLiteral = (value) => {
6232
+ if (typeof value === "string") return `"${value}"`;
6233
+ if (typeof value === "number" || typeof value === "boolean") {
6234
+ return String(value);
6235
+ }
6236
+ if (value === null) return "null";
6237
+ if (value === void 0) return "undefined";
6238
+ return describeValue(value);
6239
+ };
6240
+ var isString2 = (value, name) => {
6241
+ if (typeof value !== "string") fail(name, "expected string");
6242
+ };
6243
+ var isNumber = (value, name) => {
6244
+ if (typeof value !== "number") fail(name, "expected number");
6245
+ };
6246
+ var isBoolean = (value, name) => {
6247
+ if (typeof value !== "boolean") fail(name, "expected boolean");
6248
+ };
6249
+ var isClass = (ctor) => {
6250
+ return (value, name) => {
6251
+ if (!(value instanceof ctor)) {
6252
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
6253
+ }
6254
+ };
6255
+ };
6256
+ var optional = (validator) => {
6257
+ return (value, name, head) => {
6258
+ if (value === void 0) return;
6259
+ validator(value, name, head);
6260
+ };
6261
+ };
6262
+ var nullable = (validator) => {
6263
+ return (value, name, head) => {
6264
+ if (value === null) return;
6265
+ validator(value, name, head);
6266
+ };
6267
+ };
6268
+ var oneOf = (values) => {
6269
+ return (value, name) => {
6270
+ if (values.includes(value)) return;
6271
+ fail(
6272
+ name,
6273
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
6274
+ );
6275
+ };
6276
+ };
6277
+ var arrayOf = (validator) => {
6278
+ return (value, name, head) => {
6279
+ if (!isArray(value)) fail(name, "expected array");
6280
+ const items = value;
6281
+ for (let i = 0; i < items.length; ++i) {
6282
+ validator(items[i], `${name}[${i}]`, head);
6283
+ }
6284
+ };
6285
+ };
6286
+ var shape = (schema) => {
6287
+ return (value, name, head) => {
6288
+ if (!isObject(value)) fail(name, "expected object");
6289
+ const record = value;
6290
+ for (const key in schema) {
6291
+ const validator = schema[key];
6292
+ validator(record[key], `${name}.${key}`, head);
6293
+ }
6294
+ };
6295
+ };
6296
+ var refOf = (validator) => {
6297
+ return (value, name, head) => {
6298
+ if (!isRef(value)) fail(name, "expected ref");
6299
+ const refValue = value;
6300
+ validator(refValue(), `${name}.value`, head);
6301
+ };
6302
+ };
6303
+ var pval = {
6304
+ isString: isString2,
6305
+ isNumber,
6306
+ isBoolean,
6307
+ isClass,
6308
+ optional,
6309
+ nullable,
6310
+ oneOf,
6311
+ arrayOf,
6312
+ shape,
6313
+ refOf
6314
+ };
6315
+
6105
6316
  // src/composition/ContextRegistry.ts
6106
6317
  var ContextRegistry = class {
6107
6318
  constructor() {