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.
@@ -180,9 +180,184 @@ var callUnmounted = (context) => {
180
180
  (_b = context.unmounted) == null ? void 0 : _b.call(context);
181
181
  };
182
182
 
183
+ // src/log/warnings.ts
184
+ var warnings = {
185
+ [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
186
+ [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
187
+ [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
188
+ [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
189
+ [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
190
+ [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
191
+ [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
192
+ msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
193
+ args: [e]
194
+ }),
195
+ [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
196
+ [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
197
+ };
198
+ var warning = (type, ...args) => {
199
+ const msg = warnings[type];
200
+ const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
201
+ const handler = warningHandler.warning;
202
+ if (!handler) return;
203
+ if (isString(item)) handler(item);
204
+ else handler(item, ...item.args);
205
+ };
206
+ var warningHandler = {
207
+ warning: console.warn
208
+ };
209
+
210
+ // src/reactivity/refSymbols.ts
211
+ var refSymbol = Symbol("ref");
212
+ var srefSymbol = Symbol("sref");
213
+ var rawSymbol = Symbol("raw");
214
+
215
+ // src/reactivity/isRef.ts
216
+ var isRef = (value) => {
217
+ return value != null && value[srefSymbol] === 1;
218
+ };
219
+
220
+ // src/app/propValidators.ts
221
+ var PropValidationError = class extends Error {
222
+ constructor(propPath, detail) {
223
+ super(detail);
224
+ __publicField(this, "propPath");
225
+ __publicField(this, "detail");
226
+ this.name = "PropValidationError";
227
+ this.propPath = propPath;
228
+ this.detail = detail;
229
+ }
230
+ };
231
+ var fail = (name, message) => {
232
+ throw new PropValidationError(name, `${message}.`);
233
+ };
234
+ var describeValue = (value) => {
235
+ var _a;
236
+ if (value === null) return "null";
237
+ if (value === void 0) return "undefined";
238
+ if (typeof value === "string") return "string";
239
+ if (typeof value === "number") return "number";
240
+ if (typeof value === "boolean") return "boolean";
241
+ if (typeof value === "bigint") return "bigint";
242
+ if (typeof value === "symbol") return "symbol";
243
+ if (typeof value === "function") return "function";
244
+ if (isArray(value)) return "array";
245
+ if (value instanceof Date) return "Date";
246
+ if (value instanceof RegExp) return "RegExp";
247
+ if (value instanceof Map) return "Map";
248
+ if (value instanceof Set) return "Set";
249
+ const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
250
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
251
+ };
252
+ var formatLiteral = (value) => {
253
+ if (typeof value === "string") return `"${value}"`;
254
+ if (typeof value === "number" || typeof value === "boolean") {
255
+ return String(value);
256
+ }
257
+ if (value === null) return "null";
258
+ if (value === void 0) return "undefined";
259
+ return describeValue(value);
260
+ };
261
+ var isString2 = (value, name) => {
262
+ if (typeof value !== "string") fail(name, "expected string");
263
+ };
264
+ var isNumber = (value, name) => {
265
+ if (typeof value !== "number") fail(name, "expected number");
266
+ };
267
+ var isBoolean = (value, name) => {
268
+ if (typeof value !== "boolean") fail(name, "expected boolean");
269
+ };
270
+ var isClass = (ctor) => {
271
+ return (value, name) => {
272
+ if (!(value instanceof ctor)) {
273
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
274
+ }
275
+ };
276
+ };
277
+ var optional = (validator) => {
278
+ return (value, name, head) => {
279
+ if (value === void 0) return;
280
+ validator(value, name, head);
281
+ };
282
+ };
283
+ var nullable = (validator) => {
284
+ return (value, name, head) => {
285
+ if (value === null) return;
286
+ validator(value, name, head);
287
+ };
288
+ };
289
+ var oneOf = (values) => {
290
+ return (value, name) => {
291
+ if (values.includes(value)) return;
292
+ fail(
293
+ name,
294
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
295
+ );
296
+ };
297
+ };
298
+ var arrayOf = (validator) => {
299
+ return (value, name, head) => {
300
+ if (!isArray(value)) fail(name, "expected array");
301
+ const items = value;
302
+ for (let i = 0; i < items.length; ++i) {
303
+ validator(items[i], `${name}[${i}]`, head);
304
+ }
305
+ };
306
+ };
307
+ var shape = (schema) => {
308
+ return (value, name, head) => {
309
+ if (!isObject(value)) fail(name, "expected object");
310
+ const record = value;
311
+ for (const key in schema) {
312
+ const validator = schema[key];
313
+ validator(record[key], `${name}.${key}`, head);
314
+ }
315
+ };
316
+ };
317
+ var refOf = (validator) => {
318
+ return (value, name, head) => {
319
+ if (!isRef(value)) fail(name, "expected ref");
320
+ const refValue = value;
321
+ validator(refValue(), `${name}.value`, head);
322
+ };
323
+ };
324
+ var pval = {
325
+ fail,
326
+ isString: isString2,
327
+ isNumber,
328
+ isBoolean,
329
+ isClass,
330
+ optional,
331
+ nullable,
332
+ oneOf,
333
+ arrayOf,
334
+ shape,
335
+ refOf
336
+ };
337
+
183
338
  // src/app/ComponentHead.ts
339
+ var formatComponentValidationError = (element, propName, error) => {
340
+ var _a, _b;
341
+ const tagName = ((_b = (_a = element.tagName) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) || "unknown";
342
+ const finalPropName = error instanceof PropValidationError ? error.propPath : propName;
343
+ const detail = error instanceof PropValidationError ? error.detail : error instanceof Error ? error.message : String(error);
344
+ if (error instanceof Error) {
345
+ return new Error(
346
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
347
+ {
348
+ cause: error
349
+ }
350
+ );
351
+ }
352
+ return new Error(
353
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
354
+ {
355
+ cause: error
356
+ }
357
+ );
358
+ };
184
359
  var ComponentHead = class {
185
- constructor(props, element, ctx, start, end) {
360
+ constructor(props, element, ctx, start, end, propValidationMode) {
186
361
  /**
187
362
  * Values provided by parent for this component instance.
188
363
  *
@@ -269,6 +444,11 @@ var ComponentHead = class {
269
444
  * @internal
270
445
  */
271
446
  __publicField(this, "__element");
447
+ /**
448
+ * Runtime behavior used when `validateProps(...)` encounters invalid input.
449
+ * Defaults to `'throw'`.
450
+ */
451
+ __publicField(this, "__propValidationMode");
272
452
  /**
273
453
  * Emits a custom DOM event from the component host element.
274
454
  *
@@ -292,6 +472,7 @@ var ComponentHead = class {
292
472
  this.ctx = ctx;
293
473
  this.start = start;
294
474
  this.end = end;
475
+ this.__propValidationMode = propValidationMode;
295
476
  }
296
477
  /**
297
478
  * Finds a parent context instance by constructor type from the captured
@@ -353,6 +534,61 @@ var ComponentHead = class {
353
534
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
354
535
  );
355
536
  }
537
+ /**
538
+ * Validates selected incoming props using assertion-style validators.
539
+ *
540
+ * Only keys listed in `schema` are checked. Validation throws immediately
541
+ * on the first invalid prop and does not mutate `head.props`.
542
+ *
543
+ * The schema is keyed from `head.props`, so editor completion can suggest
544
+ * known prop names while still allowing you to validate only a subset.
545
+ *
546
+ * Validators typically come from `pval`, but custom user validators are also
547
+ * supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
548
+ * is recommended so nested validators can preserve the exact failing prop path.
549
+ *
550
+ * Example:
551
+ * ```ts
552
+ * head.validateProps({
553
+ * title: pval.isString,
554
+ * count: pval.optional(pval.isNumber),
555
+ * })
556
+ * ```
557
+ *
558
+ * Example with a custom validator:
559
+ * ```ts
560
+ * const isNonEmptyString: PropValidator<string> = (value, name) => {
561
+ * if (typeof value !== 'string' || value.trim() === '') {
562
+ * pval.fail(name, 'expected non-empty string')
563
+ * }
564
+ * }
565
+ * ```
566
+ *
567
+ * @param schema - Validators to apply to selected incoming props.
568
+ */
569
+ validateProps(schema) {
570
+ if (this.__propValidationMode === "off") return;
571
+ const props = this.props;
572
+ for (const name in schema) {
573
+ const validator = schema[name];
574
+ if (!validator) continue;
575
+ const validateProp = validator;
576
+ try {
577
+ validateProp(props[name], name, this);
578
+ } catch (error) {
579
+ const enrichedError = formatComponentValidationError(
580
+ this.__element,
581
+ name,
582
+ error
583
+ );
584
+ if (this.__propValidationMode === "warn") {
585
+ warningHandler.warning(enrichedError.message, enrichedError);
586
+ continue;
587
+ }
588
+ throw enrichedError;
589
+ }
590
+ }
591
+ }
356
592
  /**
357
593
  * Unmounts this component instance by removing nodes between `start` and `end`
358
594
  * and calling unmount lifecycle handlers for captured contexts.
@@ -386,33 +622,6 @@ var addUnbinder = (node, unbinder) => {
386
622
  getBindData(node).unbinders.push(unbinder);
387
623
  };
388
624
 
389
- // src/log/warnings.ts
390
- var warnings = {
391
- [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
392
- [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
393
- [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
394
- [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
395
- [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
396
- [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
397
- [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
398
- msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
399
- args: [e]
400
- }),
401
- [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
402
- [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
403
- };
404
- var warning = (type, ...args) => {
405
- const msg = warnings[type];
406
- const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
407
- const handler = warningHandler.warning;
408
- if (!handler) return;
409
- if (isString(item)) handler(item);
410
- else handler(item, ...item.args);
411
- };
412
- var warningHandler = {
413
- warning: console.warn
414
- };
415
-
416
625
  // src/bind/switch.ts
417
626
  var switches = {};
418
627
  var switchCounter = {};
@@ -818,16 +1027,6 @@ var isScope = (value) => {
818
1027
  return scopeSymbol2 in value;
819
1028
  };
820
1029
 
821
- // src/reactivity/refSymbols.ts
822
- var refSymbol = Symbol("ref");
823
- var srefSymbol = Symbol("sref");
824
- var rawSymbol = Symbol("raw");
825
-
826
- // src/reactivity/isRef.ts
827
- var isRef = (value) => {
828
- return value != null && value[srefSymbol] === 1;
829
- };
830
-
831
1030
  // src/directives/context.ts
832
1031
  var contextDirective = {
833
1032
  collectRefObj: true,
@@ -1400,7 +1599,8 @@ var ComponentBinder = class {
1400
1599
  component,
1401
1600
  capturedContext,
1402
1601
  startOfComponent,
1403
- endOfComponent
1602
+ endOfComponent,
1603
+ binder.__config.propValidationMode
1404
1604
  );
1405
1605
  const componentCtx2 = useScope(() => {
1406
1606
  var _a2;
@@ -2938,11 +3138,11 @@ var patchAttribute = (el, key, value, previousKey) => {
2938
3138
  }
2939
3139
  return;
2940
3140
  }
2941
- const isBoolean = key in booleanAttributes;
2942
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
3141
+ const isBoolean2 = key in booleanAttributes;
3142
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
2943
3143
  el.removeAttribute(key);
2944
3144
  } else {
2945
- el.setAttribute(key, isBoolean ? "" : value);
3145
+ el.setAttribute(key, isBoolean2 ? "" : value);
2946
3146
  }
2947
3147
  };
2948
3148
 
@@ -3192,7 +3392,7 @@ var decimalSeparators = /[.,' ·٫]/;
3192
3392
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3193
3393
  const isLazy = flags.lazy;
3194
3394
  const eventType = isLazy ? "change" : "input";
3195
- const isNumber = isNumberInput(el);
3395
+ const isNumber2 = isNumberInput(el);
3196
3396
  const trimmer = () => {
3197
3397
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3198
3398
  el.value = el.value.trim();
@@ -3222,7 +3422,7 @@ var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3222
3422
  if (!target || target.composing) return;
3223
3423
  let value = target.value;
3224
3424
  const flags2 = getFlags(parsedValue()[1]);
3225
- if (isNumber || flags2.number || flags2.int) {
3425
+ if (isNumber2 || flags2.number || flags2.int) {
3226
3426
  if (flags2.int) {
3227
3427
  value = parseInt(value);
3228
3428
  } else {
@@ -3828,6 +4028,15 @@ var _RegorConfig = class _RegorConfig {
3828
4028
  __publicField(this, "forGrowThreshold", 10);
3829
4029
  __publicField(this, "globalContext");
3830
4030
  __publicField(this, "useInterpolation", true);
4031
+ /**
4032
+ * Controls how `head.validateProps(...)` behaves when a validator fails.
4033
+ *
4034
+ * - `'throw'` (default): rethrows the validation error immediately.
4035
+ * - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
4036
+ * and continues.
4037
+ * - `'off'`: skips runtime prop validation entirely.
4038
+ */
4039
+ __publicField(this, "propValidationMode", "throw");
3831
4040
  this.setDirectives("r-");
3832
4041
  if (globalContext) {
3833
4042
  this.globalContext = globalContext;
@@ -4537,12 +4746,12 @@ var Jsep = class {
4537
4746
  this.__gobbleSpaces();
4538
4747
  let ch = this.__code;
4539
4748
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4540
- let optional;
4749
+ let optional2;
4541
4750
  if (ch === QUMARK_CODE) {
4542
4751
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4543
4752
  break;
4544
4753
  }
4545
- optional = true;
4754
+ optional2 = true;
4546
4755
  this.__index += 2;
4547
4756
  this.__gobbleSpaces();
4548
4757
  ch = this.__code;
@@ -4568,7 +4777,7 @@ var Jsep = class {
4568
4777
  callee: node
4569
4778
  };
4570
4779
  } else {
4571
- if (optional) {
4780
+ if (optional2) {
4572
4781
  this.__index--;
4573
4782
  }
4574
4783
  this.__gobbleSpaces();
@@ -4579,7 +4788,7 @@ var Jsep = class {
4579
4788
  property: this.__gobbleIdentifier()
4580
4789
  };
4581
4790
  }
4582
- if (optional) {
4791
+ if (optional2) {
4583
4792
  node.optional = true;
4584
4793
  }
4585
4794
  this.__gobbleSpaces();
@@ -6460,6 +6669,7 @@ export {
6460
6669
  onUnmounted,
6461
6670
  pause,
6462
6671
  persist,
6672
+ pval,
6463
6673
  raw,
6464
6674
  ref,
6465
6675
  removeNode,