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.
@@ -309,6 +309,37 @@ var ComponentHead = class {
309
309
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
310
310
  );
311
311
  }
312
+ /**
313
+ * Validates selected incoming props using assertion-style validators.
314
+ *
315
+ * Only keys listed in `schema` are checked. Validation throws immediately
316
+ * on the first invalid prop and does not mutate `head.props`.
317
+ *
318
+ * The schema is keyed from `head.props`, so editor completion can suggest
319
+ * known prop names while still allowing you to validate only a subset.
320
+ *
321
+ * Validators typically come from `pval`, but custom user validators are also
322
+ * supported.
323
+ *
324
+ * Example:
325
+ * ```ts
326
+ * head.validateProps({
327
+ * title: pval.isString,
328
+ * count: pval.optional(pval.isNumber),
329
+ * })
330
+ * ```
331
+ *
332
+ * @param schema - Validators to apply to selected incoming props.
333
+ */
334
+ validateProps(schema) {
335
+ const props = this.props;
336
+ for (const name in schema) {
337
+ const validator = schema[name];
338
+ if (!validator) continue;
339
+ const validateProp = validator;
340
+ validateProp(props[name], name, this);
341
+ }
342
+ }
312
343
  /**
313
344
  * Unmounts this component instance by removing nodes between `start` and `end`
314
345
  * and calling unmount lifecycle handlers for captured contexts.
@@ -457,10 +488,13 @@ var IfBinder = class {
457
488
  }
458
489
  __bindAll(element) {
459
490
  const isIfElement = element.hasAttribute(this.__if);
460
- const elements = findElements(element, this.__ifSelector);
461
- for (const el of elements) {
462
- this.__bind(el);
463
- }
491
+ if (isIfElement) this.__bind(element);
492
+ this.__binder.__componentBinder.__forEachBindableDescendant(
493
+ element,
494
+ (el) => {
495
+ if (el.hasAttribute(this.__if)) this.__bind(el);
496
+ }
497
+ );
464
498
  return isIfElement;
465
499
  }
466
500
  __isProcessedOrMark(el) {
@@ -1246,6 +1280,15 @@ var ComponentBinder = class {
1246
1280
  }
1247
1281
  return false;
1248
1282
  }
1283
+ __isNamedSlotTemplateShortcut(node) {
1284
+ if (!isTemplate(node)) return false;
1285
+ const attributeNames = node.getAttributeNames();
1286
+ if (node.hasAttribute("name")) return true;
1287
+ return attributeNames.some((x) => x.startsWith("#"));
1288
+ }
1289
+ __isDefaultSlotTemplateShortcut(node) {
1290
+ return isTemplate(node) && node.getAttributeNames().length === 0;
1291
+ }
1249
1292
  __unwrapComponents(element) {
1250
1293
  const binder = this.__binder;
1251
1294
  const parser = binder.__parser;
@@ -1255,16 +1298,9 @@ var ComponentBinder = class {
1255
1298
  return;
1256
1299
  }
1257
1300
  const contextComponents = parser.__getComponents();
1258
- const contextComponentSelectors = parser.__getComponentSelectors();
1259
- const registeredSelector = this.__getRegisteredComponentSelector(registeredComponents);
1260
- const selector = [
1261
- ...registeredSelector ? [registeredSelector] : [],
1262
- ...contextComponentSelectors,
1263
- ...contextComponentSelectors.map(hyphenate)
1264
- ].join(",");
1301
+ const selector = this.__getComponentSelector();
1265
1302
  if (isNullOrWhitespace(selector)) return;
1266
- const list = element.querySelectorAll(selector);
1267
- const components = element.matches?.(selector) ? [element, ...list] : list;
1303
+ const components = this.__collectTopLevelComponentHosts(element, selector);
1268
1304
  for (const component of components) {
1269
1305
  if (component.hasAttribute(binder.__pre)) continue;
1270
1306
  const parent = component.parentNode;
@@ -1409,9 +1445,12 @@ var ComponentBinder = class {
1409
1445
  `template[name='${name}'], template[\\#${name}]`
1410
1446
  );
1411
1447
  if (!compTemplate && name === "default") {
1412
- compTemplate = component.querySelector("template:not([name])");
1413
- if (compTemplate && compTemplate.getAttributeNames().filter((x) => x.startsWith("#")).length > 0)
1414
- compTemplate = null;
1448
+ const unnamedTemplates = component.querySelectorAll(
1449
+ "template:not([name])"
1450
+ );
1451
+ compTemplate = [...unnamedTemplates].find(
1452
+ (x) => this.__isDefaultSlotTemplateShortcut(x)
1453
+ ) ?? null;
1415
1454
  }
1416
1455
  const createSwitchContext = (childNodes2) => {
1417
1456
  if (!head.enableSwitch) return;
@@ -1447,7 +1486,7 @@ var ComponentBinder = class {
1447
1486
  return;
1448
1487
  }
1449
1488
  const childNodes2 = [...getChildNodes(component)].filter(
1450
- (x) => !isTemplate(x)
1489
+ (x) => !this.__isNamedSlotTemplateShortcut(x)
1451
1490
  );
1452
1491
  for (const slotChild of childNodes2) {
1453
1492
  parent2.insertBefore(slotChild, slot);
@@ -1533,6 +1572,64 @@ var ComponentBinder = class {
1533
1572
  parser.__scoped(capturedContext, bindComponent);
1534
1573
  }
1535
1574
  }
1575
+ __getComponentSelector() {
1576
+ const binder = this.__binder;
1577
+ const parser = binder.__parser;
1578
+ const registeredComponents = binder.__config.__components;
1579
+ const contextComponentSelectors = parser.__getComponentSelectors();
1580
+ const registeredSelector = this.__getRegisteredComponentSelector(registeredComponents);
1581
+ return [
1582
+ ...registeredSelector ? [registeredSelector] : [],
1583
+ ...contextComponentSelectors,
1584
+ ...contextComponentSelectors.map(hyphenate)
1585
+ ].join(",");
1586
+ }
1587
+ __collectTopLevelComponentHosts(root, selector) {
1588
+ const result = [];
1589
+ if (isNullOrWhitespace(selector)) return result;
1590
+ if (root.matches?.(selector)) return [root];
1591
+ const stack = this.__getChildElements(root).reverse();
1592
+ while (stack.length > 0) {
1593
+ const current = stack.pop();
1594
+ if (current.matches(selector)) {
1595
+ result.push(current);
1596
+ continue;
1597
+ }
1598
+ stack.push(...this.__getChildElements(current).reverse());
1599
+ }
1600
+ return result;
1601
+ }
1602
+ __forEachBindableDescendant(root, action) {
1603
+ const selector = this.__getComponentSelector();
1604
+ const stack = this.__getChildElements(root).reverse();
1605
+ while (stack.length > 0) {
1606
+ const current = stack.pop();
1607
+ action(current);
1608
+ if (!isNullOrWhitespace(selector) && current.matches(selector)) continue;
1609
+ stack.push(...this.__getChildElements(current).reverse());
1610
+ }
1611
+ }
1612
+ __getChildElements(root) {
1613
+ const children = root?.children;
1614
+ if (children?.length != null) {
1615
+ const result = [];
1616
+ for (let i = 0; i < children.length; ++i) {
1617
+ const child = children[i];
1618
+ if (isElement(child)) result.push(child);
1619
+ }
1620
+ return result;
1621
+ }
1622
+ const childNodes = root?.childNodes;
1623
+ if (childNodes?.length != null) {
1624
+ const result = [];
1625
+ for (let i = 0; i < childNodes.length; ++i) {
1626
+ const child = childNodes[i];
1627
+ if (isElement(child)) result.push(child);
1628
+ }
1629
+ return result;
1630
+ }
1631
+ return [];
1632
+ }
1536
1633
  };
1537
1634
 
1538
1635
  // src/bind/DirectiveCollector.ts
@@ -1622,10 +1719,10 @@ var DirectiveCollector = class {
1622
1719
  };
1623
1720
  processNode(element);
1624
1721
  if (!isRecursive || !element.firstElementChild) return map;
1625
- const nodes = element.querySelectorAll("*");
1626
- for (const node of nodes) {
1627
- processNode(node);
1628
- }
1722
+ this.__binder.__componentBinder.__forEachBindableDescendant(
1723
+ element,
1724
+ processNode
1725
+ );
1629
1726
  return map;
1630
1727
  }
1631
1728
  };
@@ -1642,18 +1739,20 @@ var mount2 = (nodes, parent) => {
1642
1739
  var DynamicBinder = class {
1643
1740
  __binder;
1644
1741
  __is;
1645
- __isSelector;
1646
1742
  constructor(binder) {
1647
1743
  this.__binder = binder;
1648
1744
  this.__is = binder.__config.__builtInNames.is;
1649
- this.__isSelector = toSelector(this.__is) + ", [is]";
1650
1745
  }
1651
1746
  __bindAll(element) {
1652
1747
  const isComponentElement = element.hasAttribute(this.__is);
1653
- const elements = findElements(element, this.__isSelector);
1654
- for (const el of elements) {
1655
- this.__bind(el);
1656
- }
1748
+ if (isComponentElement || element.hasAttribute("is"))
1749
+ this.__bind(element);
1750
+ this.__binder.__componentBinder.__forEachBindableDescendant(
1751
+ element,
1752
+ (el) => {
1753
+ if (el.hasAttribute(this.__is) || el.hasAttribute("is")) this.__bind(el);
1754
+ }
1755
+ );
1657
1756
  return isComponentElement;
1658
1757
  }
1659
1758
  __bind(el) {
@@ -2125,10 +2224,13 @@ var ForBinder = class _ForBinder {
2125
2224
  }
2126
2225
  __bindAll(element) {
2127
2226
  const isForElement = element.hasAttribute(this.__for);
2128
- const elements = findElements(element, this.__forSelector);
2129
- for (const el of elements) {
2130
- this.__bindFor(el);
2131
- }
2227
+ if (isForElement) this.__bindFor(element);
2228
+ this.__binder.__componentBinder.__forEachBindableDescendant(
2229
+ element,
2230
+ (el) => {
2231
+ if (el.hasAttribute(this.__for)) this.__bindFor(el);
2232
+ }
2233
+ );
2132
2234
  return isForElement;
2133
2235
  }
2134
2236
  __isProcessedOrMark(el) {
@@ -2794,11 +2896,11 @@ var patchAttribute = (el, key, value, previousKey) => {
2794
2896
  }
2795
2897
  return;
2796
2898
  }
2797
- const isBoolean = key in booleanAttributes;
2798
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
2899
+ const isBoolean2 = key in booleanAttributes;
2900
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
2799
2901
  el.removeAttribute(key);
2800
2902
  } else {
2801
- el.setAttribute(key, isBoolean ? "" : value);
2903
+ el.setAttribute(key, isBoolean2 ? "" : value);
2802
2904
  }
2803
2905
  };
2804
2906
 
@@ -3048,7 +3150,7 @@ var decimalSeparators = /[.,' ·٫]/;
3048
3150
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3049
3151
  const isLazy = flags.lazy;
3050
3152
  const eventType = isLazy ? "change" : "input";
3051
- const isNumber = isNumberInput(el);
3153
+ const isNumber2 = isNumberInput(el);
3052
3154
  const trimmer = () => {
3053
3155
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3054
3156
  el.value = el.value.trim();
@@ -3078,7 +3180,7 @@ var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3078
3180
  if (!target || target.composing) return;
3079
3181
  let value = target.value;
3080
3182
  const flags2 = getFlags(parsedValue()[1]);
3081
- if (isNumber || flags2.number || flags2.int) {
3183
+ if (isNumber2 || flags2.number || flags2.int) {
3082
3184
  if (flags2.int) {
3083
3185
  value = parseInt(value);
3084
3186
  } else {
@@ -4383,12 +4485,12 @@ var Jsep = class {
4383
4485
  this.__gobbleSpaces();
4384
4486
  let ch = this.__code;
4385
4487
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4386
- let optional;
4488
+ let optional2;
4387
4489
  if (ch === QUMARK_CODE) {
4388
4490
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4389
4491
  break;
4390
4492
  }
4391
- optional = true;
4493
+ optional2 = true;
4392
4494
  this.__index += 2;
4393
4495
  this.__gobbleSpaces();
4394
4496
  ch = this.__code;
@@ -4414,7 +4516,7 @@ var Jsep = class {
4414
4516
  callee: node
4415
4517
  };
4416
4518
  } else {
4417
- if (optional) {
4519
+ if (optional2) {
4418
4520
  this.__index--;
4419
4521
  }
4420
4522
  this.__gobbleSpaces();
@@ -4425,7 +4527,7 @@ var Jsep = class {
4425
4527
  property: this.__gobbleIdentifier()
4426
4528
  };
4427
4529
  }
4428
- if (optional) {
4530
+ if (optional2) {
4429
4531
  node.optional = true;
4430
4532
  }
4431
4533
  this.__gobbleSpaces();
@@ -5943,6 +6045,112 @@ var defineComponent = (template, options = {}) => {
5943
6045
  };
5944
6046
  };
5945
6047
 
6048
+ // src/app/propValidators.ts
6049
+ var fail = (name, message) => {
6050
+ throw new Error(`Invalid prop "${name}": ${message}.`);
6051
+ };
6052
+ var describeValue = (value) => {
6053
+ if (value === null) return "null";
6054
+ if (value === void 0) return "undefined";
6055
+ if (typeof value === "string") return "string";
6056
+ if (typeof value === "number") return "number";
6057
+ if (typeof value === "boolean") return "boolean";
6058
+ if (typeof value === "bigint") return "bigint";
6059
+ if (typeof value === "symbol") return "symbol";
6060
+ if (typeof value === "function") return "function";
6061
+ if (isArray(value)) return "array";
6062
+ if (value instanceof Date) return "Date";
6063
+ if (value instanceof RegExp) return "RegExp";
6064
+ if (value instanceof Map) return "Map";
6065
+ if (value instanceof Set) return "Set";
6066
+ const ctorName = value?.constructor?.name;
6067
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
6068
+ };
6069
+ var formatLiteral = (value) => {
6070
+ if (typeof value === "string") return `"${value}"`;
6071
+ if (typeof value === "number" || typeof value === "boolean") {
6072
+ return String(value);
6073
+ }
6074
+ if (value === null) return "null";
6075
+ if (value === void 0) return "undefined";
6076
+ return describeValue(value);
6077
+ };
6078
+ var isString2 = (value, name) => {
6079
+ if (typeof value !== "string") fail(name, "expected string");
6080
+ };
6081
+ var isNumber = (value, name) => {
6082
+ if (typeof value !== "number") fail(name, "expected number");
6083
+ };
6084
+ var isBoolean = (value, name) => {
6085
+ if (typeof value !== "boolean") fail(name, "expected boolean");
6086
+ };
6087
+ var isClass = (ctor) => {
6088
+ return (value, name) => {
6089
+ if (!(value instanceof ctor)) {
6090
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
6091
+ }
6092
+ };
6093
+ };
6094
+ var optional = (validator) => {
6095
+ return (value, name, head) => {
6096
+ if (value === void 0) return;
6097
+ validator(value, name, head);
6098
+ };
6099
+ };
6100
+ var nullable = (validator) => {
6101
+ return (value, name, head) => {
6102
+ if (value === null) return;
6103
+ validator(value, name, head);
6104
+ };
6105
+ };
6106
+ var oneOf = (values) => {
6107
+ return (value, name) => {
6108
+ if (values.includes(value)) return;
6109
+ fail(
6110
+ name,
6111
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
6112
+ );
6113
+ };
6114
+ };
6115
+ var arrayOf = (validator) => {
6116
+ return (value, name, head) => {
6117
+ if (!isArray(value)) fail(name, "expected array");
6118
+ const items = value;
6119
+ for (let i = 0; i < items.length; ++i) {
6120
+ validator(items[i], `${name}[${i}]`, head);
6121
+ }
6122
+ };
6123
+ };
6124
+ var shape = (schema) => {
6125
+ return (value, name, head) => {
6126
+ if (!isObject(value)) fail(name, "expected object");
6127
+ const record = value;
6128
+ for (const key in schema) {
6129
+ const validator = schema[key];
6130
+ validator(record[key], `${name}.${key}`, head);
6131
+ }
6132
+ };
6133
+ };
6134
+ var refOf = (validator) => {
6135
+ return (value, name, head) => {
6136
+ if (!isRef(value)) fail(name, "expected ref");
6137
+ const refValue = value;
6138
+ validator(refValue(), `${name}.value`, head);
6139
+ };
6140
+ };
6141
+ var pval = {
6142
+ isString: isString2,
6143
+ isNumber,
6144
+ isBoolean,
6145
+ isClass,
6146
+ optional,
6147
+ nullable,
6148
+ oneOf,
6149
+ arrayOf,
6150
+ shape,
6151
+ refOf
6152
+ };
6153
+
5946
6154
  // src/composition/ContextRegistry.ts
5947
6155
  var ContextRegistry = class {
5948
6156
  byConstructor = /* @__PURE__ */ new Map();
@@ -6279,6 +6487,7 @@ export {
6279
6487
  onUnmounted,
6280
6488
  pause,
6281
6489
  persist,
6490
+ pval,
6282
6491
  raw,
6283
6492
  ref,
6284
6493
  removeNode,