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.
@@ -142,9 +142,184 @@ var callUnmounted = (context) => {
142
142
  (_b = context.unmounted) == null ? void 0 : _b.call(context);
143
143
  };
144
144
 
145
+ // src/log/warnings.ts
146
+ var warnings = {
147
+ [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
148
+ [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
149
+ [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
150
+ [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
151
+ [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
152
+ [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
153
+ [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
154
+ msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
155
+ args: [e]
156
+ }),
157
+ [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
158
+ [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
159
+ };
160
+ var warning = (type, ...args) => {
161
+ const msg = warnings[type];
162
+ const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
163
+ const handler = warningHandler.warning;
164
+ if (!handler) return;
165
+ if (isString(item)) handler(item);
166
+ else handler(item, ...item.args);
167
+ };
168
+ var warningHandler = {
169
+ warning: console.warn
170
+ };
171
+
172
+ // src/reactivity/refSymbols.ts
173
+ var refSymbol = Symbol("ref");
174
+ var srefSymbol = Symbol("sref");
175
+ var rawSymbol = Symbol("raw");
176
+
177
+ // src/reactivity/isRef.ts
178
+ var isRef = (value) => {
179
+ return value != null && value[srefSymbol] === 1;
180
+ };
181
+
182
+ // src/app/propValidators.ts
183
+ var PropValidationError = class extends Error {
184
+ constructor(propPath, detail) {
185
+ super(detail);
186
+ __publicField(this, "propPath");
187
+ __publicField(this, "detail");
188
+ this.name = "PropValidationError";
189
+ this.propPath = propPath;
190
+ this.detail = detail;
191
+ }
192
+ };
193
+ var fail = (name, message) => {
194
+ throw new PropValidationError(name, `${message}.`);
195
+ };
196
+ var describeValue = (value) => {
197
+ var _a;
198
+ if (value === null) return "null";
199
+ if (value === void 0) return "undefined";
200
+ if (typeof value === "string") return "string";
201
+ if (typeof value === "number") return "number";
202
+ if (typeof value === "boolean") return "boolean";
203
+ if (typeof value === "bigint") return "bigint";
204
+ if (typeof value === "symbol") return "symbol";
205
+ if (typeof value === "function") return "function";
206
+ if (isArray(value)) return "array";
207
+ if (value instanceof Date) return "Date";
208
+ if (value instanceof RegExp) return "RegExp";
209
+ if (value instanceof Map) return "Map";
210
+ if (value instanceof Set) return "Set";
211
+ const ctorName = (_a = value == null ? void 0 : value.constructor) == null ? void 0 : _a.name;
212
+ return ctorName && ctorName !== "Object" ? ctorName : "object";
213
+ };
214
+ var formatLiteral = (value) => {
215
+ if (typeof value === "string") return `"${value}"`;
216
+ if (typeof value === "number" || typeof value === "boolean") {
217
+ return String(value);
218
+ }
219
+ if (value === null) return "null";
220
+ if (value === void 0) return "undefined";
221
+ return describeValue(value);
222
+ };
223
+ var isString2 = (value, name) => {
224
+ if (typeof value !== "string") fail(name, "expected string");
225
+ };
226
+ var isNumber = (value, name) => {
227
+ if (typeof value !== "number") fail(name, "expected number");
228
+ };
229
+ var isBoolean = (value, name) => {
230
+ if (typeof value !== "boolean") fail(name, "expected boolean");
231
+ };
232
+ var isClass = (ctor) => {
233
+ return (value, name) => {
234
+ if (!(value instanceof ctor)) {
235
+ fail(name, `expected instance of ${ctor.name || "provided class"}`);
236
+ }
237
+ };
238
+ };
239
+ var optional = (validator) => {
240
+ return (value, name, head) => {
241
+ if (value === void 0) return;
242
+ validator(value, name, head);
243
+ };
244
+ };
245
+ var nullable = (validator) => {
246
+ return (value, name, head) => {
247
+ if (value === null) return;
248
+ validator(value, name, head);
249
+ };
250
+ };
251
+ var oneOf = (values) => {
252
+ return (value, name) => {
253
+ if (values.includes(value)) return;
254
+ fail(
255
+ name,
256
+ `expected one of ${values.map((x) => formatLiteral(x)).join(", ")}`
257
+ );
258
+ };
259
+ };
260
+ var arrayOf = (validator) => {
261
+ return (value, name, head) => {
262
+ if (!isArray(value)) fail(name, "expected array");
263
+ const items = value;
264
+ for (let i = 0; i < items.length; ++i) {
265
+ validator(items[i], `${name}[${i}]`, head);
266
+ }
267
+ };
268
+ };
269
+ var shape = (schema) => {
270
+ return (value, name, head) => {
271
+ if (!isObject(value)) fail(name, "expected object");
272
+ const record = value;
273
+ for (const key in schema) {
274
+ const validator = schema[key];
275
+ validator(record[key], `${name}.${key}`, head);
276
+ }
277
+ };
278
+ };
279
+ var refOf = (validator) => {
280
+ return (value, name, head) => {
281
+ if (!isRef(value)) fail(name, "expected ref");
282
+ const refValue = value;
283
+ validator(refValue(), `${name}.value`, head);
284
+ };
285
+ };
286
+ var pval = {
287
+ fail,
288
+ isString: isString2,
289
+ isNumber,
290
+ isBoolean,
291
+ isClass,
292
+ optional,
293
+ nullable,
294
+ oneOf,
295
+ arrayOf,
296
+ shape,
297
+ refOf
298
+ };
299
+
145
300
  // src/app/ComponentHead.ts
301
+ var formatComponentValidationError = (element, propName, error) => {
302
+ var _a, _b;
303
+ const tagName = ((_b = (_a = element.tagName) == null ? void 0 : _a.toLowerCase) == null ? void 0 : _b.call(_a)) || "unknown";
304
+ const finalPropName = error instanceof PropValidationError ? error.propPath : propName;
305
+ const detail = error instanceof PropValidationError ? error.detail : error instanceof Error ? error.message : String(error);
306
+ if (error instanceof Error) {
307
+ return new Error(
308
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
309
+ {
310
+ cause: error
311
+ }
312
+ );
313
+ }
314
+ return new Error(
315
+ `Invalid prop "${finalPropName}" on <${tagName}>: ${detail}`,
316
+ {
317
+ cause: error
318
+ }
319
+ );
320
+ };
146
321
  var ComponentHead = class {
147
- constructor(props, element, ctx, start, end) {
322
+ constructor(props, element, ctx, start, end, propValidationMode) {
148
323
  /**
149
324
  * Values provided by parent for this component instance.
150
325
  *
@@ -231,6 +406,11 @@ var ComponentHead = class {
231
406
  * @internal
232
407
  */
233
408
  __publicField(this, "__element");
409
+ /**
410
+ * Runtime behavior used when `validateProps(...)` encounters invalid input.
411
+ * Defaults to `'throw'`.
412
+ */
413
+ __publicField(this, "__propValidationMode");
234
414
  /**
235
415
  * Emits a custom DOM event from the component host element.
236
416
  *
@@ -254,6 +434,7 @@ var ComponentHead = class {
254
434
  this.ctx = ctx;
255
435
  this.start = start;
256
436
  this.end = end;
437
+ this.__propValidationMode = propValidationMode;
257
438
  }
258
439
  /**
259
440
  * Finds a parent context instance by constructor type from the captured
@@ -315,6 +496,61 @@ var ComponentHead = class {
315
496
  `${constructor} was not found in the context stack at occurrence ${occurrence}.`
316
497
  );
317
498
  }
499
+ /**
500
+ * Validates selected incoming props using assertion-style validators.
501
+ *
502
+ * Only keys listed in `schema` are checked. Validation throws immediately
503
+ * on the first invalid prop and does not mutate `head.props`.
504
+ *
505
+ * The schema is keyed from `head.props`, so editor completion can suggest
506
+ * known prop names while still allowing you to validate only a subset.
507
+ *
508
+ * Validators typically come from `pval`, but custom user validators are also
509
+ * supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
510
+ * is recommended so nested validators can preserve the exact failing prop path.
511
+ *
512
+ * Example:
513
+ * ```ts
514
+ * head.validateProps({
515
+ * title: pval.isString,
516
+ * count: pval.optional(pval.isNumber),
517
+ * })
518
+ * ```
519
+ *
520
+ * Example with a custom validator:
521
+ * ```ts
522
+ * const isNonEmptyString: PropValidator<string> = (value, name) => {
523
+ * if (typeof value !== 'string' || value.trim() === '') {
524
+ * pval.fail(name, 'expected non-empty string')
525
+ * }
526
+ * }
527
+ * ```
528
+ *
529
+ * @param schema - Validators to apply to selected incoming props.
530
+ */
531
+ validateProps(schema) {
532
+ if (this.__propValidationMode === "off") return;
533
+ const props = this.props;
534
+ for (const name in schema) {
535
+ const validator = schema[name];
536
+ if (!validator) continue;
537
+ const validateProp = validator;
538
+ try {
539
+ validateProp(props[name], name, this);
540
+ } catch (error) {
541
+ const enrichedError = formatComponentValidationError(
542
+ this.__element,
543
+ name,
544
+ error
545
+ );
546
+ if (this.__propValidationMode === "warn") {
547
+ warningHandler.warning(enrichedError.message, enrichedError);
548
+ continue;
549
+ }
550
+ throw enrichedError;
551
+ }
552
+ }
553
+ }
318
554
  /**
319
555
  * Unmounts this component instance by removing nodes between `start` and `end`
320
556
  * and calling unmount lifecycle handlers for captured contexts.
@@ -348,33 +584,6 @@ var addUnbinder = (node, unbinder) => {
348
584
  getBindData(node).unbinders.push(unbinder);
349
585
  };
350
586
 
351
- // src/log/warnings.ts
352
- var warnings = {
353
- [8 /* ModelRequiresRef */]: (el) => `Model binding requires a ref at ${el.outerHTML}`,
354
- [7 /* ModelNotSupportOnElement */]: (el) => `Model binding is not supported on ${el.tagName} element at ${el.outerHTML}`,
355
- [0 /* MissingBindingExpression */]: (name, el) => `${name} binding expression is missing at ${el.outerHTML}`,
356
- [1 /* InvalidForExpression */]: (name, forPath, el) => `invalid ${name} expression: ${forPath} at ${el.outerHTML}`,
357
- [2 /* BindingRequiresObjectExpressions */]: (name, el) => `${name} requires object expression at ${el.outerHTML}`,
358
- [3 /* KeyIsEmpty */]: (name, el) => `${name} binder: key is empty on ${el.outerHTML}.`,
359
- [4 /* PropertyAssignmentFailed */]: (key, tag, value, e) => ({
360
- msg: `Failed setting prop "${key}" on <${tag.toLowerCase()}>: value ${value} is invalid.`,
361
- args: [e]
362
- }),
363
- [5 /* MissingEventType */]: (name, el) => `${name} binding missing event type at ${el.outerHTML}`,
364
- [6 /* ErrorLog */]: (msg, e) => ({ msg, args: [e] })
365
- };
366
- var warning = (type, ...args) => {
367
- const msg = warnings[type];
368
- const item = isFunction(msg) ? msg.call(warnings, ...args) : msg;
369
- const handler = warningHandler.warning;
370
- if (!handler) return;
371
- if (isString(item)) handler(item);
372
- else handler(item, ...item.args);
373
- };
374
- var warningHandler = {
375
- warning: console.warn
376
- };
377
-
378
587
  // src/bind/switch.ts
379
588
  var switches = {};
380
589
  var switchCounter = {};
@@ -780,16 +989,6 @@ var isScope = (value) => {
780
989
  return scopeSymbol2 in value;
781
990
  };
782
991
 
783
- // src/reactivity/refSymbols.ts
784
- var refSymbol = Symbol("ref");
785
- var srefSymbol = Symbol("sref");
786
- var rawSymbol = Symbol("raw");
787
-
788
- // src/reactivity/isRef.ts
789
- var isRef = (value) => {
790
- return value != null && value[srefSymbol] === 1;
791
- };
792
-
793
992
  // src/directives/context.ts
794
993
  var contextDirective = {
795
994
  collectRefObj: true,
@@ -1362,7 +1561,8 @@ var ComponentBinder = class {
1362
1561
  component,
1363
1562
  capturedContext,
1364
1563
  startOfComponent,
1365
- endOfComponent
1564
+ endOfComponent,
1565
+ binder.__config.propValidationMode
1366
1566
  );
1367
1567
  const componentCtx2 = useScope(() => {
1368
1568
  var _a2;
@@ -2900,11 +3100,11 @@ var patchAttribute = (el, key, value, previousKey) => {
2900
3100
  }
2901
3101
  return;
2902
3102
  }
2903
- const isBoolean = key in booleanAttributes;
2904
- if (isNullOrUndefined(value) || isBoolean && !includeBooleanAttr(value)) {
3103
+ const isBoolean2 = key in booleanAttributes;
3104
+ if (isNullOrUndefined(value) || isBoolean2 && !includeBooleanAttr(value)) {
2905
3105
  el.removeAttribute(key);
2906
3106
  } else {
2907
- el.setAttribute(key, isBoolean ? "" : value);
3107
+ el.setAttribute(key, isBoolean2 ? "" : value);
2908
3108
  }
2909
3109
  };
2910
3110
 
@@ -3154,7 +3354,7 @@ var decimalSeparators = /[.,' ·٫]/;
3154
3354
  var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3155
3355
  const isLazy = flags.lazy;
3156
3356
  const eventType = isLazy ? "change" : "input";
3157
- const isNumber = isNumberInput(el);
3357
+ const isNumber2 = isNumberInput(el);
3158
3358
  const trimmer = () => {
3159
3359
  if (!flags.trim && !getFlags(parsedValue()[1]).trim) return;
3160
3360
  el.value = el.value.trim();
@@ -3184,7 +3384,7 @@ var handleInputAndTextArea = (el, flags, getModelRef, parsedValue) => {
3184
3384
  if (!target || target.composing) return;
3185
3385
  let value = target.value;
3186
3386
  const flags2 = getFlags(parsedValue()[1]);
3187
- if (isNumber || flags2.number || flags2.int) {
3387
+ if (isNumber2 || flags2.number || flags2.int) {
3188
3388
  if (flags2.int) {
3189
3389
  value = parseInt(value);
3190
3390
  } else {
@@ -3790,6 +3990,15 @@ var _RegorConfig = class _RegorConfig {
3790
3990
  __publicField(this, "forGrowThreshold", 10);
3791
3991
  __publicField(this, "globalContext");
3792
3992
  __publicField(this, "useInterpolation", true);
3993
+ /**
3994
+ * Controls how `head.validateProps(...)` behaves when a validator fails.
3995
+ *
3996
+ * - `'throw'` (default): rethrows the validation error immediately.
3997
+ * - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
3998
+ * and continues.
3999
+ * - `'off'`: skips runtime prop validation entirely.
4000
+ */
4001
+ __publicField(this, "propValidationMode", "throw");
3793
4002
  this.setDirectives("r-");
3794
4003
  if (globalContext) {
3795
4004
  this.globalContext = globalContext;
@@ -4499,12 +4708,12 @@ var Jsep = class {
4499
4708
  this.__gobbleSpaces();
4500
4709
  let ch = this.__code;
4501
4710
  while (ch === PERIOD_CODE || ch === OBRACK_CODE || ch === OPAREN_CODE || ch === QUMARK_CODE) {
4502
- let optional;
4711
+ let optional2;
4503
4712
  if (ch === QUMARK_CODE) {
4504
4713
  if (this.__expr.charCodeAt(this.__index + 1) !== PERIOD_CODE) {
4505
4714
  break;
4506
4715
  }
4507
- optional = true;
4716
+ optional2 = true;
4508
4717
  this.__index += 2;
4509
4718
  this.__gobbleSpaces();
4510
4719
  ch = this.__code;
@@ -4530,7 +4739,7 @@ var Jsep = class {
4530
4739
  callee: node
4531
4740
  };
4532
4741
  } else {
4533
- if (optional) {
4742
+ if (optional2) {
4534
4743
  this.__index--;
4535
4744
  }
4536
4745
  this.__gobbleSpaces();
@@ -4541,7 +4750,7 @@ var Jsep = class {
4541
4750
  property: this.__gobbleIdentifier()
4542
4751
  };
4543
4752
  }
4544
- if (optional) {
4753
+ if (optional2) {
4545
4754
  node.optional = true;
4546
4755
  }
4547
4756
  this.__gobbleSpaces();
@@ -6422,6 +6631,7 @@ export {
6422
6631
  onUnmounted,
6423
6632
  pause,
6424
6633
  persist,
6634
+ pval,
6425
6635
  raw,
6426
6636
  ref,
6427
6637
  removeNode,