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.
- package/README.md +151 -0
- package/dist/regor.d.ts +120 -11
- package/dist/regor.es2015.cjs.js +258 -48
- package/dist/regor.es2015.cjs.prod.js +3 -3
- package/dist/regor.es2015.esm.js +258 -48
- package/dist/regor.es2015.esm.prod.js +3 -3
- package/dist/regor.es2015.iife.js +258 -48
- package/dist/regor.es2015.iife.prod.js +3 -3
- package/dist/regor.es2019.cjs.js +258 -48
- package/dist/regor.es2019.cjs.prod.js +3 -3
- package/dist/regor.es2019.esm.js +258 -48
- package/dist/regor.es2019.esm.prod.js +3 -3
- package/dist/regor.es2019.iife.js +258 -48
- package/dist/regor.es2019.iife.prod.js +3 -3
- package/dist/regor.es2022.cjs.js +256 -48
- package/dist/regor.es2022.cjs.prod.js +3 -3
- package/dist/regor.es2022.esm.js +256 -48
- package/dist/regor.es2022.esm.prod.js +3 -3
- package/dist/regor.es2022.iife.js +256 -48
- package/dist/regor.es2022.iife.prod.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,156 @@ HTML:
|
|
|
97
97
|
</div>
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
## Component Props Validation
|
|
101
|
+
|
|
102
|
+
Regor components can validate incoming props at runtime inside `context(head)`.
|
|
103
|
+
|
|
104
|
+
This is opt-in and local to the component author:
|
|
105
|
+
|
|
106
|
+
- it does not change `defineComponent(...)`
|
|
107
|
+
- it validates only the keys you list
|
|
108
|
+
- it follows `config.propValidationMode`
|
|
109
|
+
- it does not coerce values
|
|
110
|
+
- it does not mutate `head.props`
|
|
111
|
+
|
|
112
|
+
Use `head.validateProps(...)` together with `pval`:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { defineComponent, html, pval } from 'regor'
|
|
116
|
+
|
|
117
|
+
type EditorCard = {
|
|
118
|
+
title: string
|
|
119
|
+
count?: number
|
|
120
|
+
mode: 'create' | 'edit'
|
|
121
|
+
summary?: string
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const editorCard = defineComponent<EditorCard>(
|
|
125
|
+
html`<article>{{ summary }}</article>`,
|
|
126
|
+
{
|
|
127
|
+
props: ['title', 'count', 'mode'],
|
|
128
|
+
context: (head) => {
|
|
129
|
+
head.validateProps({
|
|
130
|
+
title: pval.isString,
|
|
131
|
+
count: pval.optional(pval.isNumber),
|
|
132
|
+
mode: pval.oneOf(['create', 'edit'] as const),
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
...head.props,
|
|
137
|
+
summary: `${head.props.title}:${head.props.mode}:${head.props.count ?? 'none'}`,
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Built-in validators
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import { pval } from 'regor'
|
|
148
|
+
|
|
149
|
+
pval.isString
|
|
150
|
+
pval.isNumber
|
|
151
|
+
pval.isBoolean
|
|
152
|
+
pval.isClass(MyClass)
|
|
153
|
+
pval.optional(pval.isString)
|
|
154
|
+
pval.nullable(pval.isNumber)
|
|
155
|
+
pval.oneOf(['create', 'edit'] as const)
|
|
156
|
+
pval.arrayOf(pval.isString)
|
|
157
|
+
pval.shape({ title: pval.isString, count: pval.isNumber })
|
|
158
|
+
pval.refOf(pval.isString)
|
|
159
|
+
pval.fail('title', 'expected non-empty string')
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Dynamic bindings and refs
|
|
163
|
+
|
|
164
|
+
Single-prop dynamic bindings like `:title="titleRef"` flow into component props as refs.
|
|
165
|
+
When validating those runtime values, use `pval.refOf(...)`:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
type CardProps = {
|
|
169
|
+
title: Ref<string>
|
|
170
|
+
summary?: string
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const card = defineComponent<CardProps>(html`<h3>{{ summary }}</h3>`, {
|
|
174
|
+
props: ['title'],
|
|
175
|
+
context: (head) => {
|
|
176
|
+
head.validateProps({
|
|
177
|
+
title: pval.refOf(pval.isString),
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
...head.props,
|
|
182
|
+
summary: head.props.title(),
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
For object-style `:context="{ ... }"` values, validate the plain runtime shape directly:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
head.validateProps({
|
|
192
|
+
meta: pval.shape({
|
|
193
|
+
slug: pval.isString,
|
|
194
|
+
}),
|
|
195
|
+
})
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Custom validators
|
|
199
|
+
|
|
200
|
+
Users can provide their own validators as long as they match the `PropValidator<T>` signature:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import { pval, type PropValidator } from 'regor'
|
|
204
|
+
|
|
205
|
+
const isNonEmptyString: PropValidator<string> = (value, name) => {
|
|
206
|
+
if (typeof value !== 'string' || value.trim() === '') {
|
|
207
|
+
pval.fail(name, 'expected non-empty string')
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
head.validateProps({
|
|
212
|
+
title: isNonEmptyString,
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Custom validators can also use the third `head` argument:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
const startsWithPrefix: PropValidator<string> = (value, name, head) => {
|
|
220
|
+
const ctx = head.requireContext(AppServices)
|
|
221
|
+
if (typeof value !== 'string' || !value.startsWith(ctx.prefix)) {
|
|
222
|
+
pval.fail(name, 'expected prefixed value')
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Validation mode
|
|
228
|
+
|
|
229
|
+
Validation behavior is controlled through `RegorConfig.propValidationMode`:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import { RegorConfig } from 'regor'
|
|
233
|
+
|
|
234
|
+
const config = new RegorConfig()
|
|
235
|
+
config.propValidationMode = 'warn'
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Available modes:
|
|
239
|
+
|
|
240
|
+
- `'throw'` (default): throw immediately on invalid prop
|
|
241
|
+
- `'warn'`: report through `warningHandler.warning(...)` and continue
|
|
242
|
+
- `'off'`: skip runtime prop validation entirely
|
|
243
|
+
|
|
244
|
+
Pass the config into `createApp(...)` when you want app-level control:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
createApp(appContext, template, config)
|
|
248
|
+
```
|
|
249
|
+
|
|
100
250
|
## Table Templates and Components
|
|
101
251
|
|
|
102
252
|
Regor preprocesses table-related templates to keep markup valid when using
|
|
@@ -223,6 +373,7 @@ These directives empower you to create dynamic and interactive user interfaces,
|
|
|
223
373
|
|
|
224
374
|
- **`createApp`** Similar to Vue's `createApp`, it initializes a Regor application instance.
|
|
225
375
|
- **`defineComponent`** Creates a Regor component instance.
|
|
376
|
+
- **`pval`** Built-in component prop validators used with `head.validateProps(...)`.
|
|
226
377
|
- **`toFragment`** Converts a JSON template to a document fragment.
|
|
227
378
|
- **`toJsonTemplate`** Converts a DOM element to a JSON template.
|
|
228
379
|
|
package/dist/regor.d.ts
CHANGED
|
@@ -1,5 +1,86 @@
|
|
|
1
1
|
// Generated by dts-bundle-generator v9.5.1
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Assertion-style runtime validator used by `head.validateProps(...)`.
|
|
5
|
+
*
|
|
6
|
+
* A validator should throw when the value is invalid and return normally when
|
|
7
|
+
* the value satisfies the expected runtime contract.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam TValue - Value type asserted by the validator when it succeeds.
|
|
10
|
+
* @param value - Raw incoming prop value.
|
|
11
|
+
* @param name - Prop name or nested path currently being validated.
|
|
12
|
+
* @param head - Current component head, useful for context-aware validation.
|
|
13
|
+
*/
|
|
14
|
+
export type PropValidator<TValue = unknown> = (value: unknown, name: string, head: ComponentHead<any>) => asserts value is TValue;
|
|
15
|
+
export type ValidationSchemaLike = Record<string, PropValidator<any>>;
|
|
16
|
+
/**
|
|
17
|
+
* Validation schema shape suggested by `ComponentHead<T>.props`.
|
|
18
|
+
*
|
|
19
|
+
* Every key is optional so component authors can validate only the subset they
|
|
20
|
+
* care about. Editor completion is still driven by the known prop keys.
|
|
21
|
+
*/
|
|
22
|
+
export type PropValidationSchemaFor<TProps extends object> = {
|
|
23
|
+
[TKey in keyof TProps]?: PropValidator<TProps[TKey]>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Infers the asserted value types from a validation schema.
|
|
27
|
+
*
|
|
28
|
+
* Keys whose values are not validators are ignored.
|
|
29
|
+
*/
|
|
30
|
+
export type InferPropValidationSchema<TSchema extends Record<string, unknown>> = {
|
|
31
|
+
[TKey in keyof TSchema as TSchema[TKey] extends PropValidator<any> ? TKey : never]: TSchema[TKey] extends PropValidator<infer TValue> ? TValue : never;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Built-in prop-validator namespace used with `head.validateProps(...)`.
|
|
35
|
+
*
|
|
36
|
+
* This namespace includes both ready-made validators and composition helpers.
|
|
37
|
+
* Custom validators can also use `pval.fail(...)` to produce the same
|
|
38
|
+
* structured failure shape as Regor's built-in validators.
|
|
39
|
+
*
|
|
40
|
+
* Example:
|
|
41
|
+
* ```ts
|
|
42
|
+
* head.validateProps({
|
|
43
|
+
* title: pval.isString,
|
|
44
|
+
* count: pval.optional(pval.isNumber),
|
|
45
|
+
* meta: pval.shape({
|
|
46
|
+
* slug: pval.isString,
|
|
47
|
+
* }),
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const pval: {
|
|
52
|
+
readonly fail: (name: string, message: string) => never;
|
|
53
|
+
readonly isString: PropValidator<string>;
|
|
54
|
+
readonly isNumber: PropValidator<number>;
|
|
55
|
+
readonly isBoolean: PropValidator<boolean>;
|
|
56
|
+
readonly isClass: <TValue extends object>(ctor: abstract new (...args: any[]) => TValue) => PropValidator<TValue>;
|
|
57
|
+
readonly optional: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue | undefined>;
|
|
58
|
+
readonly nullable: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue | null>;
|
|
59
|
+
readonly oneOf: <const TValue extends readonly unknown[]>(values: TValue) => PropValidator<TValue[number]>;
|
|
60
|
+
readonly arrayOf: <TValue>(validator: PropValidator<TValue>) => PropValidator<TValue[]>;
|
|
61
|
+
readonly shape: <TSchema extends ValidationSchemaLike>(schema: TSchema) => PropValidator<InferPropValidationSchema<TSchema>>;
|
|
62
|
+
readonly refOf: <TValue>(validator: PropValidator<TValue>) => PropValidator<AnyRef>;
|
|
63
|
+
};
|
|
64
|
+
export type PropValidationMode = "throw" | "warn" | "off";
|
|
65
|
+
export declare class RegorConfig {
|
|
66
|
+
static getDefault(): RegorConfig;
|
|
67
|
+
forGrowThreshold: number;
|
|
68
|
+
globalContext: Record<string, unknown>;
|
|
69
|
+
useInterpolation: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Controls how `head.validateProps(...)` behaves when a validator fails.
|
|
72
|
+
*
|
|
73
|
+
* - `'throw'` (default): rethrows the validation error immediately.
|
|
74
|
+
* - `'warn'`: forwards the validation error to `warningHandler.warning(...)`
|
|
75
|
+
* and continues.
|
|
76
|
+
* - `'off'`: skips runtime prop validation entirely.
|
|
77
|
+
*/
|
|
78
|
+
propValidationMode: PropValidationMode;
|
|
79
|
+
constructor(globalContext?: Record<string, unknown>);
|
|
80
|
+
addComponent<TContext extends IRegorContext | object = IRegorContext>(...components: Array<Component<TContext>>): void;
|
|
81
|
+
setDirectives(prefix: string): void;
|
|
82
|
+
updateDirectives(updater: (directiveMap: Record<string, Directive>, builtInNames: Record<string, string>) => void): void;
|
|
83
|
+
}
|
|
3
84
|
export type ContextClass<TValue extends object> = abstract new (...args: never[]) => TValue;
|
|
4
85
|
/**
|
|
5
86
|
* Runtime metadata passed to a component's `context(head)` factory.
|
|
@@ -111,7 +192,12 @@ export declare class ComponentHead<TContext extends IRegorContext | object = IRe
|
|
|
111
192
|
* Useful when post-assignment normalization is needed.
|
|
112
193
|
*/
|
|
113
194
|
onAutoPropsAssigned?: () => void;
|
|
114
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Runtime behavior used when `validateProps(...)` encounters invalid input.
|
|
197
|
+
* Defaults to `'throw'`.
|
|
198
|
+
*/
|
|
199
|
+
__propValidationMode: PropValidationMode;
|
|
200
|
+
constructor(props: TContext, element: Element, ctx: IRegorContext[], start: Comment, end: Comment, propValidationMode: PropValidationMode);
|
|
115
201
|
/**
|
|
116
202
|
* Emits a custom DOM event from the component host element.
|
|
117
203
|
*
|
|
@@ -170,22 +256,45 @@ export declare class ComponentHead<TContext extends IRegorContext | object = IRe
|
|
|
170
256
|
* @throws Error when no matching instance exists at the requested occurrence.
|
|
171
257
|
*/
|
|
172
258
|
requireContext<TValue extends object>(constructor: ContextClass<TValue>, occurrence?: number): TValue;
|
|
259
|
+
/**
|
|
260
|
+
* Validates selected incoming props using assertion-style validators.
|
|
261
|
+
*
|
|
262
|
+
* Only keys listed in `schema` are checked. Validation throws immediately
|
|
263
|
+
* on the first invalid prop and does not mutate `head.props`.
|
|
264
|
+
*
|
|
265
|
+
* The schema is keyed from `head.props`, so editor completion can suggest
|
|
266
|
+
* known prop names while still allowing you to validate only a subset.
|
|
267
|
+
*
|
|
268
|
+
* Validators typically come from `pval`, but custom user validators are also
|
|
269
|
+
* supported. Custom validators may throw their own `Error`, though `pval.fail(...)`
|
|
270
|
+
* is recommended so nested validators can preserve the exact failing prop path.
|
|
271
|
+
*
|
|
272
|
+
* Example:
|
|
273
|
+
* ```ts
|
|
274
|
+
* head.validateProps({
|
|
275
|
+
* title: pval.isString,
|
|
276
|
+
* count: pval.optional(pval.isNumber),
|
|
277
|
+
* })
|
|
278
|
+
* ```
|
|
279
|
+
*
|
|
280
|
+
* Example with a custom validator:
|
|
281
|
+
* ```ts
|
|
282
|
+
* const isNonEmptyString: PropValidator<string> = (value, name) => {
|
|
283
|
+
* if (typeof value !== 'string' || value.trim() === '') {
|
|
284
|
+
* pval.fail(name, 'expected non-empty string')
|
|
285
|
+
* }
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @param schema - Validators to apply to selected incoming props.
|
|
290
|
+
*/
|
|
291
|
+
validateProps<TSchema extends PropValidationSchemaFor<TContext>>(schema: TSchema): asserts this is ComponentHead<TContext & InferPropValidationSchema<TSchema>>;
|
|
173
292
|
/**
|
|
174
293
|
* Unmounts this component instance by removing nodes between `start` and `end`
|
|
175
294
|
* and calling unmount lifecycle handlers for captured contexts.
|
|
176
295
|
*/
|
|
177
296
|
unmount(): void;
|
|
178
297
|
}
|
|
179
|
-
export declare class RegorConfig {
|
|
180
|
-
static getDefault(): RegorConfig;
|
|
181
|
-
forGrowThreshold: number;
|
|
182
|
-
globalContext: Record<string, unknown>;
|
|
183
|
-
useInterpolation: boolean;
|
|
184
|
-
constructor(globalContext?: Record<string, unknown>);
|
|
185
|
-
addComponent<TContext extends IRegorContext | object = IRegorContext>(...components: Array<Component<TContext>>): void;
|
|
186
|
-
setDirectives(prefix: string): void;
|
|
187
|
-
updateDirectives(updater: (directiveMap: Record<string, Directive>, builtInNames: Record<string, string>) => void): void;
|
|
188
|
-
}
|
|
189
298
|
export type IsNull<T> = [
|
|
190
299
|
T
|
|
191
300
|
] extends [
|