regor 1.4.6 → 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.
@@ -137,7 +137,180 @@ var callUnmounted = (context) => {
137
137
  context.unmounted?.();
138
138
  };
139
139
 
140
+ // src/log/warnings.ts
141
+ var warnings = {
142
+ [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
143
+ [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
144
+ [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
145
+ [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
146
+ [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
147
+ [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
148
+ [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
149
+ msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
150
+ args: [e]
151
+ }),
152
+ [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
153
+ [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
154
+ };
155
+ var warning = (type, ...args) => {
156
+ const msg = warnings[type];
157
+ const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
158
+ const handler = warningHandler.warning;
159
+ if (!handler) return;
160
+ if (isString(item)) handler(item);
161
+ else handler(item, ...item.args);
162
+ };
163
+ var warningHandler = {
164
+ warning: console.warn
165
+ };
166
+
167
+ // src/reactivity/refSymbols.ts
168
+ var refSymbol = Symbol("ref");
169
+ var srefSymbol = Symbol("sref");
170
+ var rawSymbol = Symbol("raw");
171
+
172
+ // src/reactivity/isRef.ts
173
+ var isRef = (value) => {
174
+ return value != null && value[srefSymbol] === 1;
175
+ };
176
+
177
+ // src/app/propValidators.ts
178
+ var PropValidationError = class extends Error {
179
+ propPath;
180
+ detail;
181
+ constructor(propPath, detail) {
182
+ super(detail);
183
+ this.name = "PropValidationError";
184
+ this.propPath = propPath;
185
+ this.detail = detail;
186
+ }
187
+ };
188
+ var fail = (name, message) => {
189
+ throw new PropValidationError(name, `${message}.`);
190
+ };
191
+ var describeValue = (value) => {
192
+ if (value === null) return "null";
193
+ if (value === void 0) return "undefined";
194
+ if (typeof value === "string") return "string";
195
+ if (typeof value === "number") return "number";
196
+ if (typeof value === "boolean") return "boolean";
197
+ if (typeof value === "bigint") return "bigint";
198
+ if (typeof value === "symbol") return "symbol";
199
+ if (typeof value === "function") return "function";
200
+ if (isArray(value)) return "array";
201
+ if (value instanceof Date) return "Date";
202
+ if (value instanceof RegExp) return "RegExp";
203
+ if (value instanceof Map) return "Map";
204
+ if (value instanceof Set) return "Set";
205
+ const ctorName = value?.constructor?.name;
206
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
207
+ };
208
+ var formatLiteral = (value) => {
209
+ if (typeof value === "string") return `"${value}"`;
210
+ if (typeof value === "number" || typeof value === "boolean") {
211
+ return String(value);
212
+ }
213
+ if (value === null) return "null";
214
+ if (value === void 0) return "undefined";
215
+ return describeValue(value);
216
+ };
217
+ var isString2 = (value, name) => {
218
+ if (typeof value !== "string") fail(name, "expected string");
219
+ };
220
+ var isNumber = (value, name) => {
221
+ if (typeof value !== "number") fail(name, "expected number");
222
+ };
223
+ var isBoolean = (value, name) => {
224
+ if (typeof value !== "boolean") fail(name, "expected boolean");
225
+ };
226
+ var isClass = (ctor) => {
227
+ return (value, name) => {
228
+ if (!(value instanceof ctor)) {
229
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
230
+ }
231
+ };
232
+ };
233
+ var optional = (validator) => {
234
+ return (value, name, head) => {
235
+ if (value === void 0) return;
236
+ validator(value, name, head);
237
+ };
238
+ };
239
+ var nullable = (validator) => {
240
+ return (value, name, head) => {
241
+ if (value === null) return;
242
+ validator(value, name, head);
243
+ };
244
+ };
245
+ var oneOf = (values) => {
246
+ return (value, name) => {
247
+ if (values.includes(value)) return;
248
+ fail(
249
+ name,
250
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
251
+ );
252
+ };
253
+ };
254
+ var arrayOf = (validator) => {
255
+ return (value, name, head) => {
256
+ if (!isArray(value)) fail(name, "expected array");
257
+ const items = value;
258
+ for (let i = 0; i < items.length; ++i) {
259
+ validator(items[i], `${name}[${i}]`, head);
260
+ }
261
+ };
262
+ };
263
+ var shape = (schema) => {
264
+ return (value, name, head) => {
265
+ if (!isObject(value)) fail(name, "expected object");
266
+ const record = value;
267
+ for (const key in schema) {
268
+ const validator = schema[key];
269
+ validator(record[key], `${name}.${key}`, head);
270
+ }
271
+ };
272
+ };
273
+ var refOf = (validator) => {
274
+ return (value, name, head) => {
275
+ if (!isRef(value)) fail(name, "expected ref");
276
+ const refValue = value;
277
+ validator(refValue(), `${name}.value`, head);
278
+ };
279
+ };
280
+ var pval = {
281
+ fail,
282
+ isString: isString2,
283
+ isNumber,
284
+ isBoolean,
285
+ isClass,
286
+ optional,
287
+ nullable,
288
+ oneOf,
289
+ arrayOf,
290
+ shape,
291
+ refOf
292
+ };
293
+
140
294
  // src/app/ComponentHead.ts
295
+ var formatComponentValidationError = (element, propName, error) => {
296
+ const tagName = element.tagName?.toLowerCase?.() || "unknown";
297
+ const finalPropName = error instanceof PropValidationError ? error.propPath : propName;
298
+ const detail = error instanceof PropValidationError ? error.detail : error instanceof Error ? error.message : String(error);
299
+ if (error instanceof Error) {
300
+ return new Error(
301
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
302
+ {
303
+ cause: error
304
+ }
305
+ );
306
+ }
307
+ return new Error(
308
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
309
+ {
310
+ cause: error
311
+ }
312
+ );
313
+ };
141
314
  var ComponentHead = class {
142
315
  /**
143
316
  * Values provided by parent for this component instance.
@@ -225,12 +398,18 @@ var ComponentHead = class {
225
398
  * @internal
226
399
  */
227
400
  __element;
228
- constructor(props, element, ctx, start, end) {
401
+ /**
402
+ * Runtime behavior used when `validateProps(...)` encounters invalid input.
403
+ * Defaults to `'throw'`.
404
+ */
405
+ __propValidationMode;
406
+ constructor(props, element, ctx, start, end, propValidationMode) {
229
407
  this.props = props;
230
408
  this.__element = element;
231
409
  this.ctx = ctx;
232
410
  this.start = start;
233
411
  this.end = end;
412
+ this.__propValidationMode = propValidationMode;
234
413
  }
235
414
  /**
236
415
  * Emits a custom DOM event from the component host element.
@@ -319,7 +498,8 @@ var ComponentHead = class {
319
498
  * known prop names while still allowing you to validate only a subset.
320
499
  *
321
500
  * Validators typically come from `pval`, but custom user validators are also
322
- * supported.
501
+ * supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
502
+ * is recommended so nested validators can preserve the exact failing prop path.
323
503
  *
324
504
  * Example:
325
505
  * ```ts
@@ -329,15 +509,38 @@ var ComponentHead = class {
329
509
  * })
330
510
  * ```
331
511
  *
512
+ * Example with a custom validator:
513
+ * ```ts
514
+ * const isNonEmptyString: PropValidator<string> = (value, name) => {
515
+ * if (typeof value !== 'string' || value.trim() === '') {
516
+ * pval.fail(name, 'expected non-empty string')
517
+ * }
518
+ * }
519
+ * ```
520
+ *
332
521
  * @param schema - Validators to apply to selected incoming props.
333
522
  */
334
523
  validateProps(schema) {
524
+ if (this.__propValidationMode === "off") return;
335
525
  const props = this.props;
336
526
  for (const name in schema) {
337
527
  const validator = schema[name];
338
528
  if (!validator) continue;
339
529
  const validateProp = validator;
340
- validateProp(props[name], name, this);
530
+ try {
531
+ validateProp(props[name], name, this);
532
+ } catch (error) {
533
+ const enrichedError = formatComponentValidationError(
534
+ this.__element,
535
+ name,
536
+ error
537
+ );
538
+ if (this.__propValidationMode === "warn") {
539
+ warningHandler.warning(enrichedError.message, enrichedError);
540
+ continue;
541
+ }
542
+ throw enrichedError;
543
+ }
341
544
  }
342
545
  }
343
546
  /**
@@ -373,33 +576,6 @@ var addUnbinder = (node, unbinder) => {
373
576
  getBindData(node).unbinders.push(unbinder);
374
577
  };
375
578
 
376
- // src/log/warnings.ts
377
- var warnings = {
378
- [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
379
- [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
380
- [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
381
- [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
382
- [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
383
- [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
384
- [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
385
- msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
386
- args: [e]
387
- }),
388
- [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
389
- [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
390
- };
391
- var warning = (type, ...args) => {
392
- const msg = warnings[type];
393
- const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
394
- const handler = warningHandler.warning;
395
- if (!handler) return;
396
- if (isString(item)) handler(item);
397
- else handler(item, ...item.args);
398
- };
399
- var warningHandler = {
400
- warning: console.warn
401
- };
402
-
403
579
  // src/bind/switch.ts
404
580
  var switches = {};
405
581
  var switchCounter = {};
@@ -803,16 +979,6 @@ var isScope = (value) => {
803
979
  return scopeSymbol2 in value;
804
980
  };
805
981
 
806
- // src/reactivity/refSymbols.ts
807
- var refSymbol = Symbol("ref");
808
- var srefSymbol = Symbol("sref");
809
- var rawSymbol = Symbol("raw");
810
-
811
- // src/reactivity/isRef.ts
812
- var isRef = (value) => {
813
- return value != null && value[srefSymbol] === 1;
814
- };
815
-
816
982
  // src/directives/context.ts
817
983
  var contextDirective = {
818
984
  collectRefObj: true,
@@ -1380,7 +1546,8 @@ var ComponentBinder = class {
1380
1546
  component,
1381
1547
  capturedContext,
1382
1548
  startOfComponent,
1383
- endOfComponent
1549
+ endOfComponent,
1550
+ binder.__config.propValidationMode
1384
1551
  );
1385
1552
  const componentCtx2 = useScope(() => {
1386
1553
  return registeredComponent.context(head2) ?? {};
@@ -3794,6 +3961,15 @@ var RegorConfig = class _RegorConfig {
3794
3961
  forGrowThreshold = 10;
3795
3962
  globalContext;
3796
3963
  useInterpolation = true;
3964
+ /**
3965
+ * Controls how `head.validateProps(...)` behaves when a validator fails.
3966
+ *
3967
+ * - `'throw'` (default): rethrows the validation error immediately.
3968
+ * - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
3969
+ * and continues.
3970
+ * - `'off'`: skips runtime prop validation entirely.
3971
+ */
3972
+ propValidationMode = "throw";
3797
3973
  constructor(globalContext) {
3798
3974
  this.setDirectives("r-");
3799
3975
  if (globalContext) {
@@ -6045,112 +6221,6 @@ var defineComponent = (template, options = {}) => {
6045
6221
  };
6046
6222
  };
6047
6223
 
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
-
6154
6224
  // src/composition/ContextRegistry.ts
6155
6225
  var ContextRegistry = class {
6156
6226
  byConstructor = /* @__PURE__ */ new Map();