regor 1.4.5 → 1.4.7

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.
@@ -87,6 +87,7 @@ __export(index_exports, {
87
87
  onUnmounted: () => onUnmounted,
88
88
  pause: () => pause,
89
89
  persist: () => persist,
90
+ pval: () => pval,
90
91
  raw: () => raw,
91
92
  ref: () => ref,
92
93
  removeNode: () => removeNode,
@@ -245,9 +246,184 @@ var callUnmounted = (context) => {
245
246
  (_b = context.unmounted) == null ? void 0 : _b.call(context);
246
247
  };
247
248
 
249
+ // src/log/warnings.ts
250
+ var warnings = {
251
+ [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
252
+ [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
253
+ [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
254
+ [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
255
+ [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
256
+ [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
257
+ [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
258
+ msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
259
+ args: [e]
260
+ }),
261
+ [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
262
+ [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
263
+ };
264
+ var warning = (type, ...args) => {
265
+ const msg = warnings[type];
266
+ const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
267
+ const handler = warningHandler.warning;
268
+ if (!handler) return;
269
+ if (isString(item)) handler(item);
270
+ else handler(item, ...item.args);
271
+ };
272
+ var warningHandler = {
273
+ warning: console.warn
274
+ };
275
+
276
+ // src/reactivity/refSymbols.ts
277
+ var refSymbol = Symbol("ref");
278
+ var srefSymbol = Symbol("sref");
279
+ var rawSymbol = Symbol("raw");
280
+
281
+ // src/reactivity/isRef.ts
282
+ var isRef = (value) => {
283
+ return value != null && value[srefSymbol] === 1;
284
+ };
285
+
286
+ // src/app/propValidators.ts
287
+ var PropValidationError = class extends Error {
288
+ constructor(propPath, detail) {
289
+ super(detail);
290
+ __publicField(this, "propPath");
291
+ __publicField(this, "detail");
292
+ this.name = "PropValidationError";
293
+ this.propPath = propPath;
294
+ this.detail = detail;
295
+ }
296
+ };
297
+ var fail = (name, message) => {
298
+ throw new PropValidationError(name, `${message}.`);
299
+ };
300
+ var describeValue = (value) => {
301
+ var _a;
302
+ if (value === null) return "null";
303
+ if (value === void 0) return "undefined";
304
+ if (typeof value === "string") return "string";
305
+ if (typeof value === "number") return "number";
306
+ if (typeof value === "boolean") return "boolean";
307
+ if (typeof value === "bigint") return "bigint";
308
+ if (typeof value === "symbol") return "symbol";
309
+ if (typeof value === "function") return "function";
310
+ if (isArray(value)) return "array";
311
+ if (value instanceof Date) return "Date";
312
+ if (value instanceof RegExp) return "RegExp";
313
+ if (value instanceof Map) return "Map";
314
+ if (value instanceof Set) return "Set";
315
+ const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
316
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
317
+ };
318
+ var formatLiteral = (value) => {
319
+ if (typeof value === "string") return `"${value}"`;
320
+ if (typeof value === "number" || typeof value === "boolean") {
321
+ return String(value);
322
+ }
323
+ if (value === null) return "null";
324
+ if (value === void 0) return "undefined";
325
+ return describeValue(value);
326
+ };
327
+ var isString2 = (value, name) => {
328
+ if (typeof value !== "string") fail(name, "expected string");
329
+ };
330
+ var isNumber = (value, name) => {
331
+ if (typeof value !== "number") fail(name, "expected number");
332
+ };
333
+ var isBoolean = (value, name) => {
334
+ if (typeof value !== "boolean") fail(name, "expected boolean");
335
+ };
336
+ var isClass = (ctor) => {
337
+ return (value, name) => {
338
+ if (!(value instanceof ctor)) {
339
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
340
+ }
341
+ };
342
+ };
343
+ var optional = (validator) => {
344
+ return (value, name, head) => {
345
+ if (value === void 0) return;
346
+ validator(value, name, head);
347
+ };
348
+ };
349
+ var nullable = (validator) => {
350
+ return (value, name, head) => {
351
+ if (value === null) return;
352
+ validator(value, name, head);
353
+ };
354
+ };
355
+ var oneOf = (values) => {
356
+ return (value, name) => {
357
+ if (values.includes(value)) return;
358
+ fail(
359
+ name,
360
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
361
+ );
362
+ };
363
+ };
364
+ var arrayOf = (validator) => {
365
+ return (value, name, head) => {
366
+ if (!isArray(value)) fail(name, "expected array");
367
+ const items = value;
368
+ for (let i = 0; i < items.length; ++i) {
369
+ validator(items[i], `${name}[${i}]`, head);
370
+ }
371
+ };
372
+ };
373
+ var shape = (schema) => {
374
+ return (value, name, head) => {
375
+ if (!isObject(value)) fail(name, "expected object");
376
+ const record = value;
377
+ for (const key in schema) {
378
+ const validator = schema[key];
379
+ validator(record[key], `${name}.${key}`, head);
380
+ }
381
+ };
382
+ };
383
+ var refOf = (validator) => {
384
+ return (value, name, head) => {
385
+ if (!isRef(value)) fail(name, "expected ref");
386
+ const refValue = value;
387
+ validator(refValue(), `${name}.value`, head);
388
+ };
389
+ };
390
+ var pval = {
391
+ fail,
392
+ isString: isString2,
393
+ isNumber,
394
+ isBoolean,
395
+ isClass,
396
+ optional,
397
+ nullable,
398
+ oneOf,
399
+ arrayOf,
400
+ shape,
401
+ refOf
402
+ };
403
+
248
404
  // src/app/ComponentHead.ts
405
+ var formatComponentValidationError = (element, propName, error) => {
406
+ var _a, _b;
407
+ const tagName = ((_b = (_a = element.tagName) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) || "unknown";
408
+ const finalPropName = error instanceof PropValidationError ? error.propPath : propName;
409
+ const detail = error instanceof PropValidationError ? error.detail : error instanceof Error ? error.message : String(error);
410
+ if (error instanceof Error) {
411
+ return new Error(
412
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
413
+ {
414
+ cause: error
415
+ }
416
+ );
417
+ }
418
+ return new Error(
419
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
420
+ {
421
+ cause: error
422
+ }
423
+ );
424
+ };
249
425
  var ComponentHead = class {
250
- constructor(props, element, ctx, start, end) {
426
+ constructor(props, element, ctx, start, end, propValidationMode) {
251
427
  /**
252
428
  * Values provided by parent for this component instance.
253
429
  *
@@ -334,6 +510,11 @@ var ComponentHead = class {
334
510
  * @internal
335
511
  */
336
512
  __publicField(this, "__element");
513
+ /**
514
+ * Runtime behavior used when `validateProps(...)` encounters invalid input.
515
+ * Defaults to `'throw'`.
516
+ */
517
+ __publicField(this, "__propValidationMode");
337
518
  /**
338
519
  * Emits a custom DOM event from the component host element.
339
520
  *
@@ -357,6 +538,7 @@ var ComponentHead = class {
357
538
  this.ctx = ctx;
358
539
  this.start = start;
359
540
  this.end = end;
541
+ this.__propValidationMode = propValidationMode;
360
542
  }
361
543
  /**
362
544
  * Finds a parent context instance by constructor type from the captured
@@ -418,6 +600,61 @@ var ComponentHead = class {
418
600
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
419
601
  );
420
602
  }
603
+ /**
604
+ * Validates selected incoming props using assertion-style validators.
605
+ *
606
+ * Only keys listed in `schema` are checked. Validation throws immediately
607
+ * on the first invalid prop and does not mutate `head.props`.
608
+ *
609
+ * The schema is keyed from `head.props`, so editor completion can suggest
610
+ * known prop names while still allowing you to validate only a subset.
611
+ *
612
+ * Validators typically come from `pval`, but custom user validators are also
613
+ * supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
614
+ * is recommended so nested validators can preserve the exact failing prop path.
615
+ *
616
+ * Example:
617
+ * ```ts
618
+ * head.validateProps({
619
+ * title: pval.isString,
620
+ * count: pval.optional(pval.isNumber),
621
+ * })
622
+ * ```
623
+ *
624
+ * Example with a custom validator:
625
+ * ```ts
626
+ * const isNonEmptyString: PropValidator<string> = (value, name) => {
627
+ * if (typeof value !== 'string' || value.trim() === '') {
628
+ * pval.fail(name, 'expected non-empty string')
629
+ * }
630
+ * }
631
+ * ```
632
+ *
633
+ * @param schema - Validators to apply to selected incoming props.
634
+ */
635
+ validateProps(schema) {
636
+ if (this.__propValidationMode === "off") return;
637
+ const props = this.props;
638
+ for (const name in schema) {
639
+ const validator = schema[name];
640
+ if (!validator) continue;
641
+ const validateProp = validator;
642
+ try {
643
+ validateProp(props[name], name, this);
644
+ } catch (error) {
645
+ const enrichedError = formatComponentValidationError(
646
+ this.__element,
647
+ name,
648
+ error
649
+ );
650
+ if (this.__propValidationMode === "warn") {
651
+ warningHandler.warning(enrichedError.message, enrichedError);
652
+ continue;
653
+ }
654
+ throw enrichedError;
655
+ }
656
+ }
657
+ }
421
658
  /**
422
659
  * Unmounts this component instance by removing nodes between `start` and `end`
423
660
  * and calling unmount lifecycle handlers for captured contexts.
@@ -451,33 +688,6 @@ var addUnbinder = (node, unbinder) => {
451
688
  getBindData(node).unbinders.push(unbinder);
452
689
  };
453
690
 
454
- // src/log/warnings.ts
455
- var warnings = {
456
- [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
457
- [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
458
- [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
459
- [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
460
- [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
461
- [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
462
- [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
463
- msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
464
- args: [e]
465
- }),
466
- [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
467
- [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
468
- };
469
- var warning = (type, ...args) => {
470
- const msg = warnings[type];
471
- const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
472
- const handler = warningHandler.warning;
473
- if (!handler) return;
474
- if (isString(item)) handler(item);
475
- else handler(item, ...item.args);
476
- };
477
- var warningHandler = {
478
- warning: console.warn
479
- };
480
-
481
691
  // src/bind/switch.ts
482
692
  var switches = {};
483
693
  var switchCounter = {};
@@ -883,16 +1093,6 @@ var isScope = (value) => {
883
1093
  return scopeSymbol2 in value;
884
1094
  };
885
1095
 
886
- // src/reactivity/refSymbols.ts
887
- var refSymbol = Symbol("ref");
888
- var srefSymbol = Symbol("sref");
889
- var rawSymbol = Symbol("raw");
890
-
891
- // src/reactivity/isRef.ts
892
- var isRef = (value) => {
893
- return value != null && value[srefSymbol] === 1;
894
- };
895
-
896
1096
  // src/directives/context.ts
897
1097
  var contextDirective = {
898
1098
  collectRefObj: true,
@@ -1465,7 +1665,8 @@ var ComponentBinder = class {
1465
1665
  component,
1466
1666
  capturedContext,
1467
1667
  startOfComponent,
1468
- endOfComponent
1668
+ endOfComponent,
1669
+ binder.__config.propValidationMode
1469
1670
  );
1470
1671
  const componentCtx2 = useScope(() => {
1471
1672
  var _a2;
@@ -3003,11 +3204,11 @@ var patchAttribute = (el, key, value, previousKey) => {
3003
3204
  }
3004
3205
  return;
3005
3206
  }
3006
- const isBoolean = key in booleanAttributes;
3007
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
3207
+ const isBoolean2 = key in booleanAttributes;
3208
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
3008
3209
  el.removeAttribute(key);
3009
3210
  } else {
3010
- el.setAttribute(key, isBoolean ? "" : value);
3211
+ el.setAttribute(key, isBoolean2 ? "" : value);
3011
3212
  }
3012
3213
  };
3013
3214
 
@@ -3257,7 +3458,7 @@ var decimalSeparators = /[.,' ·٫]/;
3257
3458
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3258
3459
  const isLazy = flags.lazy;
3259
3460
  const eventType = isLazy ? "change" : "input";
3260
- const isNumber = isNumberInput(el);
3461
+ const isNumber2 = isNumberInput(el);
3261
3462
  const trimmer = () => {
3262
3463
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3263
3464
  el.value = el.value.trim();
@@ -3287,7 +3488,7 @@ var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3287
3488
  if (!target || target.composing) return;
3288
3489
  let value = target.value;
3289
3490
  const flags2 = getFlags(parsedValue()[1]);
3290
- if (isNumber || flags2.number || flags2.int) {
3491
+ if (isNumber2 || flags2.number || flags2.int) {
3291
3492
  if (flags2.int) {
3292
3493
  value = parseInt(value);
3293
3494
  } else {
@@ -3893,6 +4094,15 @@ var _RegorConfig = class _RegorConfig {
3893
4094
  __publicField(this, "forGrowThreshold", 10);
3894
4095
  __publicField(this, "globalContext");
3895
4096
  __publicField(this, "useInterpolation", true);
4097
+ /**
4098
+ * Controls how `head.validateProps(...)` behaves when a validator fails.
4099
+ *
4100
+ * - `'throw'` (default): rethrows the validation error immediately.
4101
+ * - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
4102
+ * and continues.
4103
+ * - `'off'`: skips runtime prop validation entirely.
4104
+ */
4105
+ __publicField(this, "propValidationMode", "throw");
3896
4106
  this.setDirectives("r-");
3897
4107
  if (globalContext) {
3898
4108
  this.globalContext = globalContext;
@@ -4602,12 +4812,12 @@ var Jsep = class {
4602
4812
  this.__gobbleSpaces();
4603
4813
  let ch = this.__code;
4604
4814
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4605
- let optional;
4815
+ let optional2;
4606
4816
  if (ch === QUMARK_CODE) {
4607
4817
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4608
4818
  break;
4609
4819
  }
4610
- optional = true;
4820
+ optional2 = true;
4611
4821
  this.__index += 2;
4612
4822
  this.__gobbleSpaces();
4613
4823
  ch = this.__code;
@@ -4633,7 +4843,7 @@ var Jsep = class {
4633
4843
  callee: node
4634
4844
  };
4635
4845
  } else {
4636
- if (optional) {
4846
+ if (optional2) {
4637
4847
  this.__index--;
4638
4848
  }
4639
4849
  this.__gobbleSpaces();
@@ -4644,7 +4854,7 @@ var Jsep = class {
4644
4854
  property: this.__gobbleIdentifier()
4645
4855
  };
4646
4856
  }
4647
- if (optional) {
4857
+ if (optional2) {
4648
4858
  node.optional = true;
4649
4859
  }
4650
4860
  this.__gobbleSpaces();