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.
@@ -50,6 +50,7 @@ __export(index_exports, {
50
50
  onUnmounted: () => onUnmounted,
51
51
  pause: () => pause,
52
52
  persist: () => persist,
53
+ pval: () => pval,
53
54
  raw: () => raw,
54
55
  ref: () => ref,
55
56
  removeNode: () => removeNode,
@@ -208,9 +209,184 @@ var callUnmounted = (context) => {
208
209
  (_b = context.unmounted) == null ? void 0 : _b.call(context);
209
210
  };
210
211
 
212
+ // src/log/warnings.ts
213
+ var warnings = {
214
+ [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
215
+ [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
216
+ [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
217
+ [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
218
+ [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
219
+ [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
220
+ [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
221
+ msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
222
+ args: [e]
223
+ }),
224
+ [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
225
+ [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
226
+ };
227
+ var warning = (type, ...args) => {
228
+ const msg = warnings[type];
229
+ const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
230
+ const handler = warningHandler.warning;
231
+ if (!handler) return;
232
+ if (isString(item)) handler(item);
233
+ else handler(item, ...item.args);
234
+ };
235
+ var warningHandler = {
236
+ warning: console.warn
237
+ };
238
+
239
+ // src/reactivity/refSymbols.ts
240
+ var refSymbol = Symbol("ref");
241
+ var srefSymbol = Symbol("sref");
242
+ var rawSymbol = Symbol("raw");
243
+
244
+ // src/reactivity/isRef.ts
245
+ var isRef = (value) => {
246
+ return value != null && value[srefSymbol] === 1;
247
+ };
248
+
249
+ // src/app/propValidators.ts
250
+ var PropValidationError = class extends Error {
251
+ constructor(propPath, detail) {
252
+ super(detail);
253
+ __publicField(this, "propPath");
254
+ __publicField(this, "detail");
255
+ this.name = "PropValidationError";
256
+ this.propPath = propPath;
257
+ this.detail = detail;
258
+ }
259
+ };
260
+ var fail = (name, message) => {
261
+ throw new PropValidationError(name, `${message}.`);
262
+ };
263
+ var describeValue = (value) => {
264
+ var _a;
265
+ if (value === null) return "null";
266
+ if (value === void 0) return "undefined";
267
+ if (typeof value === "string") return "string";
268
+ if (typeof value === "number") return "number";
269
+ if (typeof value === "boolean") return "boolean";
270
+ if (typeof value === "bigint") return "bigint";
271
+ if (typeof value === "symbol") return "symbol";
272
+ if (typeof value === "function") return "function";
273
+ if (isArray(value)) return "array";
274
+ if (value instanceof Date) return "Date";
275
+ if (value instanceof RegExp) return "RegExp";
276
+ if (value instanceof Map) return "Map";
277
+ if (value instanceof Set) return "Set";
278
+ const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
279
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
280
+ };
281
+ var formatLiteral = (value) => {
282
+ if (typeof value === "string") return `"${value}"`;
283
+ if (typeof value === "number" || typeof value === "boolean") {
284
+ return String(value);
285
+ }
286
+ if (value === null) return "null";
287
+ if (value === void 0) return "undefined";
288
+ return describeValue(value);
289
+ };
290
+ var isString2 = (value, name) => {
291
+ if (typeof value !== "string") fail(name, "expected string");
292
+ };
293
+ var isNumber = (value, name) => {
294
+ if (typeof value !== "number") fail(name, "expected number");
295
+ };
296
+ var isBoolean = (value, name) => {
297
+ if (typeof value !== "boolean") fail(name, "expected boolean");
298
+ };
299
+ var isClass = (ctor) => {
300
+ return (value, name) => {
301
+ if (!(value instanceof ctor)) {
302
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
303
+ }
304
+ };
305
+ };
306
+ var optional = (validator) => {
307
+ return (value, name, head) => {
308
+ if (value === void 0) return;
309
+ validator(value, name, head);
310
+ };
311
+ };
312
+ var nullable = (validator) => {
313
+ return (value, name, head) => {
314
+ if (value === null) return;
315
+ validator(value, name, head);
316
+ };
317
+ };
318
+ var oneOf = (values) => {
319
+ return (value, name) => {
320
+ if (values.includes(value)) return;
321
+ fail(
322
+ name,
323
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
324
+ );
325
+ };
326
+ };
327
+ var arrayOf = (validator) => {
328
+ return (value, name, head) => {
329
+ if (!isArray(value)) fail(name, "expected array");
330
+ const items = value;
331
+ for (let i = 0; i < items.length; ++i) {
332
+ validator(items[i], `${name}[${i}]`, head);
333
+ }
334
+ };
335
+ };
336
+ var shape = (schema) => {
337
+ return (value, name, head) => {
338
+ if (!isObject(value)) fail(name, "expected object");
339
+ const record = value;
340
+ for (const key in schema) {
341
+ const validator = schema[key];
342
+ validator(record[key], `${name}.${key}`, head);
343
+ }
344
+ };
345
+ };
346
+ var refOf = (validator) => {
347
+ return (value, name, head) => {
348
+ if (!isRef(value)) fail(name, "expected ref");
349
+ const refValue = value;
350
+ validator(refValue(), `${name}.value`, head);
351
+ };
352
+ };
353
+ var pval = {
354
+ fail,
355
+ isString: isString2,
356
+ isNumber,
357
+ isBoolean,
358
+ isClass,
359
+ optional,
360
+ nullable,
361
+ oneOf,
362
+ arrayOf,
363
+ shape,
364
+ refOf
365
+ };
366
+
211
367
  // src/app/ComponentHead.ts
368
+ var formatComponentValidationError = (element, propName, error) => {
369
+ var _a, _b;
370
+ const tagName = ((_b = (_a = element.tagName) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) || "unknown";
371
+ const finalPropName = error instanceof PropValidationError ? error.propPath : propName;
372
+ const detail = error instanceof PropValidationError ? error.detail : error instanceof Error ? error.message : String(error);
373
+ if (error instanceof Error) {
374
+ return new Error(
375
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
376
+ {
377
+ cause: error
378
+ }
379
+ );
380
+ }
381
+ return new Error(
382
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
383
+ {
384
+ cause: error
385
+ }
386
+ );
387
+ };
212
388
  var ComponentHead = class {
213
- constructor(props, element, ctx, start, end) {
389
+ constructor(props, element, ctx, start, end, propValidationMode) {
214
390
  /**
215
391
  * Values provided by parent for this component instance.
216
392
  *
@@ -297,6 +473,11 @@ var ComponentHead = class {
297
473
  * @internal
298
474
  */
299
475
  __publicField(this, "__element");
476
+ /**
477
+ * Runtime behavior used when `validateProps(...)` encounters invalid input.
478
+ * Defaults to `'throw'`.
479
+ */
480
+ __publicField(this, "__propValidationMode");
300
481
  /**
301
482
  * Emits a custom DOM event from the component host element.
302
483
  *
@@ -320,6 +501,7 @@ var ComponentHead = class {
320
501
  this.ctx = ctx;
321
502
  this.start = start;
322
503
  this.end = end;
504
+ this.__propValidationMode = propValidationMode;
323
505
  }
324
506
  /**
325
507
  * Finds a parent context instance by constructor type from the captured
@@ -381,6 +563,61 @@ var ComponentHead = class {
381
563
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
382
564
  );
383
565
  }
566
+ /**
567
+ * Validates selected incoming props using assertion-style validators.
568
+ *
569
+ * Only keys listed in `schema` are checked. Validation throws immediately
570
+ * on the first invalid prop and does not mutate `head.props`.
571
+ *
572
+ * The schema is keyed from `head.props`, so editor completion can suggest
573
+ * known prop names while still allowing you to validate only a subset.
574
+ *
575
+ * Validators typically come from `pval`, but custom user validators are also
576
+ * supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
577
+ * is recommended so nested validators can preserve the exact failing prop path.
578
+ *
579
+ * Example:
580
+ * ```ts
581
+ * head.validateProps({
582
+ * title: pval.isString,
583
+ * count: pval.optional(pval.isNumber),
584
+ * })
585
+ * ```
586
+ *
587
+ * Example with a custom validator:
588
+ * ```ts
589
+ * const isNonEmptyString: PropValidator<string> = (value, name) => {
590
+ * if (typeof value !== 'string' || value.trim() === '') {
591
+ * pval.fail(name, 'expected non-empty string')
592
+ * }
593
+ * }
594
+ * ```
595
+ *
596
+ * @param schema - Validators to apply to selected incoming props.
597
+ */
598
+ validateProps(schema) {
599
+ if (this.__propValidationMode === "off") return;
600
+ const props = this.props;
601
+ for (const name in schema) {
602
+ const validator = schema[name];
603
+ if (!validator) continue;
604
+ const validateProp = validator;
605
+ try {
606
+ validateProp(props[name], name, this);
607
+ } catch (error) {
608
+ const enrichedError = formatComponentValidationError(
609
+ this.__element,
610
+ name,
611
+ error
612
+ );
613
+ if (this.__propValidationMode === "warn") {
614
+ warningHandler.warning(enrichedError.message, enrichedError);
615
+ continue;
616
+ }
617
+ throw enrichedError;
618
+ }
619
+ }
620
+ }
384
621
  /**
385
622
  * Unmounts this component instance by removing nodes between `start` and `end`
386
623
  * and calling unmount lifecycle handlers for captured contexts.
@@ -414,33 +651,6 @@ var addUnbinder = (node, unbinder) => {
414
651
  getBindData(node).unbinders.push(unbinder);
415
652
  };
416
653
 
417
- // src/log/warnings.ts
418
- var warnings = {
419
- [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
420
- [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
421
- [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
422
- [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
423
- [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
424
- [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
425
- [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
426
- msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
427
- args: [e]
428
- }),
429
- [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
430
- [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
431
- };
432
- var warning = (type, ...args) => {
433
- const msg = warnings[type];
434
- const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
435
- const handler = warningHandler.warning;
436
- if (!handler) return;
437
- if (isString(item)) handler(item);
438
- else handler(item, ...item.args);
439
- };
440
- var warningHandler = {
441
- warning: console.warn
442
- };
443
-
444
654
  // src/bind/switch.ts
445
655
  var switches = {};
446
656
  var switchCounter = {};
@@ -846,16 +1056,6 @@ var isScope = (value) => {
846
1056
  return scopeSymbol2 in value;
847
1057
  };
848
1058
 
849
- // src/reactivity/refSymbols.ts
850
- var refSymbol = Symbol("ref");
851
- var srefSymbol = Symbol("sref");
852
- var rawSymbol = Symbol("raw");
853
-
854
- // src/reactivity/isRef.ts
855
- var isRef = (value) => {
856
- return value != null && value[srefSymbol] === 1;
857
- };
858
-
859
1059
  // src/directives/context.ts
860
1060
  var contextDirective = {
861
1061
  collectRefObj: true,
@@ -1428,7 +1628,8 @@ var ComponentBinder = class {
1428
1628
  component,
1429
1629
  capturedContext,
1430
1630
  startOfComponent,
1431
- endOfComponent
1631
+ endOfComponent,
1632
+ binder.__config.propValidationMode
1432
1633
  );
1433
1634
  const componentCtx2 = useScope(() => {
1434
1635
  var _a2;
@@ -2966,11 +3167,11 @@ var patchAttribute = (el, key, value, previousKey) => {
2966
3167
  }
2967
3168
  return;
2968
3169
  }
2969
- const isBoolean = key in booleanAttributes;
2970
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
3170
+ const isBoolean2 = key in booleanAttributes;
3171
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
2971
3172
  el.removeAttribute(key);
2972
3173
  } else {
2973
- el.setAttribute(key, isBoolean ? "" : value);
3174
+ el.setAttribute(key, isBoolean2 ? "" : value);
2974
3175
  }
2975
3176
  };
2976
3177
 
@@ -3220,7 +3421,7 @@ var decimalSeparators = /[.,' ·٫]/;
3220
3421
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3221
3422
  const isLazy = flags.lazy;
3222
3423
  const eventType = isLazy ? "change" : "input";
3223
- const isNumber = isNumberInput(el);
3424
+ const isNumber2 = isNumberInput(el);
3224
3425
  const trimmer = () => {
3225
3426
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3226
3427
  el.value = el.value.trim();
@@ -3250,7 +3451,7 @@ var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3250
3451
  if (!target || target.composing) return;
3251
3452
  let value = target.value;
3252
3453
  const flags2 = getFlags(parsedValue()[1]);
3253
- if (isNumber || flags2.number || flags2.int) {
3454
+ if (isNumber2 || flags2.number || flags2.int) {
3254
3455
  if (flags2.int) {
3255
3456
  value = parseInt(value);
3256
3457
  } else {
@@ -3856,6 +4057,15 @@ var _RegorConfig = class _RegorConfig {
3856
4057
  __publicField(this, "forGrowThreshold", 10);
3857
4058
  __publicField(this, "globalContext");
3858
4059
  __publicField(this, "useInterpolation", true);
4060
+ /**
4061
+ * Controls how `head.validateProps(...)` behaves when a validator fails.
4062
+ *
4063
+ * - `'throw'` (default): rethrows the validation error immediately.
4064
+ * - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
4065
+ * and continues.
4066
+ * - `'off'`: skips runtime prop validation entirely.
4067
+ */
4068
+ __publicField(this, "propValidationMode", "throw");
3859
4069
  this.setDirectives("r-");
3860
4070
  if (globalContext) {
3861
4071
  this.globalContext = globalContext;
@@ -4565,12 +4775,12 @@ var Jsep = class {
4565
4775
  this.__gobbleSpaces();
4566
4776
  let ch = this.__code;
4567
4777
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4568
- let optional;
4778
+ let optional2;
4569
4779
  if (ch === QUMARK_CODE) {
4570
4780
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4571
4781
  break;
4572
4782
  }
4573
- optional = true;
4783
+ optional2 = true;
4574
4784
  this.__index += 2;
4575
4785
  this.__gobbleSpaces();
4576
4786
  ch = this.__code;
@@ -4596,7 +4806,7 @@ var Jsep = class {
4596
4806
  callee: node
4597
4807
  };
4598
4808
  } else {
4599
- if (optional) {
4809
+ if (optional2) {
4600
4810
  this.__index--;
4601
4811
  }
4602
4812
  this.__gobbleSpaces();
@@ -4607,7 +4817,7 @@ var Jsep = class {
4607
4817
  property: this.__gobbleIdentifier()
4608
4818
  };
4609
4819
  }
4610
- if (optional) {
4820
+ if (optional2) {
4611
4821
  node.optional = true;
4612
4822
  }
4613
4823
  this.__gobbleSpaces();