regor 1.3.4 → 1.3.5

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/dist/regor.d.ts CHANGED
@@ -1,28 +1,133 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
+ /**
4
+ * Runtime metadata passed to a component's `context(head)` factory.
5
+ *
6
+ * `ComponentHead` gives component authors controlled access to:
7
+ * - incoming values from parent (`head.props`)
8
+ * - component mount boundaries (`head.start`, `head.end`)
9
+ * - parent-context event bridge (`head.emit(...)`)
10
+ * - optional behavior toggles (`head.autoProps`, `head.entangle`, `head.enableSwitch`)
11
+ *
12
+ * Typical usage:
13
+ * ```ts
14
+ * const Card = createComponent({
15
+ * template: `<article><h3 r-text="title"></h3></article>`,
16
+ * props: ['title'],
17
+ * context(head) {
18
+ * // read parent values
19
+ * const initialTitle = head.props.title
20
+ *
21
+ * // optional event to parent/listener
22
+ * const close = () => head.emit('close', { reason: 'user' })
23
+ *
24
+ * return { title: initialTitle, close }
25
+ * },
26
+ * })
27
+ * ```
28
+ */
3
29
  export declare class ComponentHead<TContext extends IRegorContext | object = IRegorContext> {
30
+ /**
31
+ * Values provided by parent for this component instance.
32
+ *
33
+ * Sources:
34
+ * - declared props via `props: ['foo']` + attribute binding (`:foo="..."`)
35
+ * - object binding via `:context="{ ... }"`
36
+ */
4
37
  props: TContext;
38
+ /**
39
+ * Comment node that marks the beginning of this mounted component block.
40
+ * Advanced use only.
41
+ */
5
42
  start: Comment;
43
+ /**
44
+ * Comment node that marks the end of this mounted component block.
45
+ * Advanced use only.
46
+ */
6
47
  end: Comment;
48
+ /**
49
+ * Captured context chain used by this component instance.
50
+ * Used internally for lifecycle/unmount behavior.
51
+ */
7
52
  ctx: IRegorContext[];
8
- /** Automatically assigns properties defined in the :props binding to the component context when enabled. If disabled, props should be manually assigned using head.props.
9
- * Default: true */
53
+ /**
54
+ * Controls whether Regor should automatically apply incoming `head.props`
55
+ * values to the component context after `context(head)` returns.
56
+ *
57
+ * Think of it as "auto wire parent inputs into my component fields".
58
+ *
59
+ * - `true` (default):
60
+ * - If a key exists in `head.props` but does not exist on the object
61
+ * returned by `context(head)`, Regor adds that key to component context.
62
+ * - Existing ref fields can receive incoming values automatically.
63
+ * - Ref-to-ref inputs can be entangled when `head.entangle` is enabled.
64
+ * - `false`:
65
+ * - Regor does not auto-apply props.
66
+ * - You fully control mapping manually inside `context(head)`.
67
+ *
68
+ * Use `false` when you need strict custom mapping/validation/transforms
69
+ * before any value touches component state.
70
+ *
71
+ * "Missing key" is always checked against the returned component context object.
72
+ *
73
+ * Example (auto add):
74
+ * ```ts
75
+ * // Parent passes: :context="{ badge: 'pro' }"
76
+ * context(head) {
77
+ * // Returned context has no "badge" key:
78
+ * return { name: ref('Ada') }
79
+ * }
80
+ * // Resulting component context becomes:
81
+ * // { name: ref('Ada'), badge: 'pro' }
82
+ * ```
83
+ *
84
+ * Example:
85
+ * ```ts
86
+ * context(head) {
87
+ * head.autoProps = false
88
+ * const title = ref((head.props.title as string) ?? 'Untitled')
89
+ * return { title }
90
+ * }
91
+ * ```
92
+ */
10
93
  autoProps: boolean;
11
- /** When both autoProps and entangle are enabled,
12
- * the refs defined in the component context (without using head.props)
13
- * become entangled with the head.props refs. (parent[ref] `<==>` component[ref])
14
- * This means that changes to parent[ref] reflect in component[ref], and vice versa.
15
- * Disable this flag to isolate refs created within the component context.
16
- * Default: true */
94
+ /**
95
+ * Enables two-way ref linking between incoming props and component context
96
+ * when `autoProps` is also enabled.
97
+ *
98
+ * - `true` (default): parent and component refs stay synchronized.
99
+ * - `false`: component keeps local ref isolation.
100
+ */
17
101
  entangle: boolean;
18
- /** enables slot context switch to the parent
19
- * Default: false */
102
+ /**
103
+ * Enables slot context switch behavior for advanced slot scenarios.
104
+ * Default: `false`.
105
+ */
20
106
  enableSwitch: boolean;
21
- /** A callback invoked after auto props get assigned to the component context. */
107
+ /**
108
+ * Optional hook called after automatic prop assignment completes.
109
+ * Useful when post-assignment normalization is needed.
110
+ */
22
111
  onAutoPropsAssigned?: () => void;
23
112
  constructor(props: TContext, element: Element, ctx: IRegorContext[], start: Comment, end: Comment);
24
- /** use arrow syntax to be called without using head.emit.bind(head) in Binder.ts. */
113
+ /**
114
+ * Emits a custom DOM event from the component host element.
115
+ *
116
+ * Example:
117
+ * ```ts
118
+ * head.emit('saved', { id: 42 })
119
+ * ```
120
+ *
121
+ * Parent markup can listen via regular event binding:
122
+ * ```html
123
+ * <MyComp @saved="onSaved"></MyComp>
124
+ * ```
125
+ */
25
126
  emit: (event: string, args: Record<string, unknown>) => void;
127
+ /**
128
+ * Unmounts this component instance by removing nodes between `start` and `end`
129
+ * and calling unmount lifecycle handlers for captured contexts.
130
+ */
26
131
  unmount(): void;
27
132
  }
28
133
  export declare class RegorConfig {
@@ -198,24 +303,77 @@ export interface Component<TContext extends IRegorContext | object = IRegorConte
198
303
  export type OnMounted = () => void;
199
304
  export type OnUnmounted = () => void;
200
305
  export interface CreateComponentOptions<TContext extends IRegorContext | object = IRegorContext> {
306
+ /**
307
+ * Enables interpolation transform inside the component template.
308
+ *
309
+ * When `true` (default), text like `{{ expr }}` / `[[ expr ]]` is converted
310
+ * to directive bindings during component template preparation.
311
+ *
312
+ * Set to `false` when the template should keep interpolation markers as plain text.
313
+ */
201
314
  useInterpolation?: boolean;
315
+ /**
316
+ * Regor configuration used while creating this component.
317
+ *
318
+ * Useful when the component must use a specific config instance
319
+ * (custom directives, global context, registered components).
320
+ */
202
321
  config?: RegorConfig;
203
322
  /**
204
- * A function that defines the Regor context for the component.
323
+ * Factory that creates the component context.
324
+ *
325
+ * `head` contains incoming parent-bound values (`head.props`) and mount controls.
326
+ *
327
+ * Example:
328
+ * ```ts
329
+ * context(head) {
330
+ * return {
331
+ * title: head.props.title ?? 'Untitled',
332
+ * close: () => head.emit('close', { reason: 'user' }),
333
+ * }
334
+ * }
335
+ * ```
205
336
  */
206
337
  context?(head: ComponentHead<TContext>): TContext;
338
+ /**
339
+ * Controls attribute fallthrough from component host to component root.
340
+ *
341
+ * - `true` (default): non-prop attributes like `class`, `style`, `id` are inherited.
342
+ * - `false`: host attributes are not forwarded automatically.
343
+ */
207
344
  inheritAttrs?: boolean;
208
345
  /**
209
- * Notes on component props:
210
- * The props defined in the props list can be used with :foo or r-bind:foo syntax.
211
- * `<MyComponent :prop-kebab-1="1" r-bind:prop-kebab-2="x ? 1 : 0" :props="{ propFoo3: true, propFoo4: x ? 'a' : 'b' }></MyComponent>`
212
- * It is required to define prop-kebab-1 and prop-kebab-2 in the props list camelized.
213
- * It is not required to define propFoo3 and propFoo4 in the props list because it uses :props binding. :props binding enables binding to arbitrary component properties regardless they are explicitly defined in props list.
346
+ * Declares prop names accepted via single-prop binding (`:foo`, `r-bind:foo`, `.foo`).
347
+ *
348
+ * Use camelCase names in this list.
349
+ * Kebab-case template attributes are matched to camelCase automatically.
350
+ *
351
+ * Example:
352
+ * ```ts
353
+ * props: ['userName', 'isActive']
354
+ * ```
355
+ * ```html
356
+ * <UserCard :user-name="name" r-bind:is-active="enabled"></UserCard>
357
+ * ```
358
+ *
359
+ * Note:
360
+ * `:context="{ ... }"` can assign arbitrary component fields even when
361
+ * they are not declared in `props`.
214
362
  */
215
363
  props?: string[];
216
- /** The default name of the component.
217
- * It is required if the component is registered using the Regor config.addComponent method.
218
- * It is not required if the component being registered in app or component scope. */
364
+ /**
365
+ * Default component name used by global registration (`config.addComponent(...)`).
366
+ *
367
+ * Required for global registration.
368
+ * Optional when component is provided via app/component local `components` context.
369
+ *
370
+ * Example:
371
+ * ```ts
372
+ * const Card = createComponent('<div>...</div>', { defaultName: 'CardView' })
373
+ * cfg.addComponent(Card)
374
+ * // usable as <CardView></CardView>
375
+ * ```
376
+ */
219
377
  defaultName?: string;
220
378
  }
221
379
  export interface Scope<TRegorContext> {
@@ -224,7 +382,81 @@ export interface Scope<TRegorContext> {
224
382
  [ScopeSymbol]: true;
225
383
  [key: string]: unknown;
226
384
  }
385
+ /**
386
+ * Creates and mounts a Regor application on an existing DOM root.
387
+ *
388
+ * The app can bind directly to existing markup or replace root content with
389
+ * a provided `template`/`json` before binding.
390
+ *
391
+ * @typeParam TRegorContext - Root app context type.
392
+ * @param context - App context object (or `useScope(... )` result).
393
+ * @param template - Mount target + optional template source.
394
+ * @param config -Optional Regor config. Uses `RegorConfig.getDefault()` when omitted.
395
+ *
396
+ * @returns App handle with:
397
+ * - `context`: the same context instance used for binding
398
+ * - `unbind()`: removes Regor observers/listeners from the root
399
+ * - `unmount()`: removes the root element from DOM
400
+ *
401
+ * @example
402
+ * ```ts
403
+ * const root = document.getElementById('app')!
404
+ * const app = createApp(
405
+ * { count: ref(0) },
406
+ * {
407
+ * element: root,
408
+ * template: `<button @click="count(count()+1)" r-text="count"></button>`,
409
+ * },
410
+ * )
411
+ * ```
412
+ *
413
+ * @example
414
+ * ```ts
415
+ * // Bind against existing markup without replacing it.
416
+ * const app = createApp(
417
+ * { user: ref('Ada') },
418
+ * { selector: '#header-island' },
419
+ * )
420
+ * ```
421
+ */
227
422
  export declare const createApp: <TRegorContext extends IRegorContext | object = IRegorContext>(context: TRegorContext | Scope<TRegorContext>, template?: Template | string, config?: RegorConfig) => App<TRegorContext>;
423
+ /**
424
+ * Creates a reusable Regor component definition.
425
+ *
426
+ * `createComponent` prepares a template once, then Regor clones/binds it for each
427
+ * component instance in the app.
428
+ *
429
+ * @typeParam TContext - Component context type.
430
+ * @param template Component template source:
431
+ * - inline HTML string
432
+ * - `Template` object (`template`, `element`, `selector`, or `json`)
433
+ * @param options Component options (`context`, `props`, `inheritAttrs`, etc.).
434
+ * You can also pass `string[]` as shorthand for `props`.
435
+ *
436
+ * @returns Component definition usable in app/component `components`.
437
+ *
438
+ * @example
439
+ * ```ts
440
+ * const UserCard = createComponent(
441
+ * `<article><h3 r-text="name"></h3></article>`,
442
+ * {
443
+ * props: ['name'],
444
+ * context: (head) => ({
445
+ * name: head.props.name ?? 'Anonymous',
446
+ * }),
447
+ * },
448
+ * )
449
+ * ```
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * // Props shorthand:
454
+ * const CounterLabel = createComponent(
455
+ * `<span r-text="value"></span>`,
456
+ * ['value'],
457
+ * )
458
+ * ```
459
+ */
228
460
  export declare const createComponent: <TContext extends IRegorContext | object = IRegorContext>(template: Template | string, options?: CreateComponentOptions<TContext> | string[]) => Component<TContext>;
229
461
  export declare const toFragment: (json: JSONTemplate | JSONTemplate[], isSVG?: boolean, config?: RegorConfig) => DocumentFragment;
230
462
  export declare const toJsonTemplate: (node: Element | Element[]) => JSONTemplate | JSONTemplate[];
@@ -247,30 +247,105 @@ var callUnmounted = (context) => {
247
247
  // src/app/ComponentHead.ts
248
248
  var ComponentHead = class {
249
249
  constructor(props, element, ctx, start, end) {
250
+ /**
251
+ * Values provided by parent for this component instance.
252
+ *
253
+ * Sources:
254
+ * - declared props via `props: ['foo']` + attribute binding (`:foo="..."`)
255
+ * - object binding via `:context="{ ... }"`
256
+ */
250
257
  __publicField(this, "props");
258
+ /**
259
+ * Comment node that marks the beginning of this mounted component block.
260
+ * Advanced use only.
261
+ */
251
262
  __publicField(this, "start");
263
+ /**
264
+ * Comment node that marks the end of this mounted component block.
265
+ * Advanced use only.
266
+ */
252
267
  __publicField(this, "end");
268
+ /**
269
+ * Captured context chain used by this component instance.
270
+ * Used internally for lifecycle/unmount behavior.
271
+ */
253
272
  __publicField(this, "ctx");
254
- /** Automatically assigns properties defined in the :props binding to the component context when enabled. If disabled, props should be manually assigned using head.props.
255
- * Default: true */
273
+ /**
274
+ * Controls whether Regor should automatically apply incoming `head.props`
275
+ * values to the component context after `context(head)` returns.
276
+ *
277
+ * Think of it as "auto wire parent inputs into my component fields".
278
+ *
279
+ * - `true` (default):
280
+ * - If a key exists in `head.props` but does not exist on the object
281
+ * returned by `context(head)`, Regor adds that key to component context.
282
+ * - Existing ref fields can receive incoming values automatically.
283
+ * - Ref-to-ref inputs can be entangled when `head.entangle` is enabled.
284
+ * - `false`:
285
+ * - Regor does not auto-apply props.
286
+ * - You fully control mapping manually inside `context(head)`.
287
+ *
288
+ * Use `false` when you need strict custom mapping/validation/transforms
289
+ * before any value touches component state.
290
+ *
291
+ * "Missing key" is always checked against the returned component context object.
292
+ *
293
+ * Example (auto add):
294
+ * ```ts
295
+ * // Parent passes: :context="{ badge: 'pro' }"
296
+ * context(head) {
297
+ * // Returned context has no "badge" key:
298
+ * return { name: ref('Ada') }
299
+ * }
300
+ * // Resulting component context becomes:
301
+ * // { name: ref('Ada'), badge: 'pro' }
302
+ * ```
303
+ *
304
+ * Example:
305
+ * ```ts
306
+ * context(head) {
307
+ * head.autoProps = false
308
+ * const title = ref((head.props.title as string) ?? 'Untitled')
309
+ * return { title }
310
+ * }
311
+ * ```
312
+ */
256
313
  __publicField(this, "autoProps", true);
257
- /** When both autoProps and entangle are enabled,
258
- * the refs defined in the component context (without using head.props)
259
- * become entangled with the head.props refs. (parent[ref] `<==>` component[ref])
260
- * This means that changes to parent[ref] reflect in component[ref], and vice versa.
261
- * Disable this flag to isolate refs created within the component context.
262
- * Default: true */
314
+ /**
315
+ * Enables two-way ref linking between incoming props and component context
316
+ * when `autoProps` is also enabled.
317
+ *
318
+ * - `true` (default): parent and component refs stay synchronized.
319
+ * - `false`: component keeps local ref isolation.
320
+ */
263
321
  __publicField(this, "entangle", true);
264
- /** enables slot context switch to the parent
265
- * Default: false */
322
+ /**
323
+ * Enables slot context switch behavior for advanced slot scenarios.
324
+ * Default: `false`.
325
+ */
266
326
  __publicField(this, "enableSwitch", false);
267
- /** A callback invoked after auto props get assigned to the component context. */
327
+ /**
328
+ * Optional hook called after automatic prop assignment completes.
329
+ * Useful when post-assignment normalization is needed.
330
+ */
268
331
  __publicField(this, "onAutoPropsAssigned");
269
332
  /**
270
333
  * @internal
271
334
  */
272
335
  __publicField(this, "__element");
273
- /** use arrow syntax to be called without using head.emit.bind(head) in Binder.ts. */
336
+ /**
337
+ * Emits a custom DOM event from the component host element.
338
+ *
339
+ * Example:
340
+ * ```ts
341
+ * head.emit('saved', { id: 42 })
342
+ * ```
343
+ *
344
+ * Parent markup can listen via regular event binding:
345
+ * ```html
346
+ * <MyComp @saved="onSaved"></MyComp>
347
+ * ```
348
+ */
274
349
  __publicField(this, "emit", (event, args) => {
275
350
  this.__element.dispatchEvent(
276
351
  new CustomEvent(event, { detail: args })
@@ -282,6 +357,10 @@ var ComponentHead = class {
282
357
  this.start = start;
283
358
  this.end = end;
284
359
  }
360
+ /**
361
+ * Unmounts this component instance by removing nodes between `start` and `end`
362
+ * and calling unmount lifecycle handlers for captured contexts.
363
+ */
285
364
  unmount() {
286
365
  let next = this.start.nextSibling;
287
366
  const end = this.end;
@@ -763,8 +842,8 @@ var observe = (source, observer, init, trackUnmount = true) => {
763
842
  return stop;
764
843
  };
765
844
 
766
- // src/directives/props.ts
767
- var propsDirective = {
845
+ // src/directives/context.ts
846
+ var contextDirective = {
768
847
  collectRefObj: true,
769
848
  onBind: (_, parseResult) => {
770
849
  const stopObserving = observe(
@@ -794,34 +873,6 @@ var propsDirective = {
794
873
  }
795
874
  };
796
875
 
797
- // src/directives/props-once.ts
798
- var propsOnceDirective = {
799
- collectRefObj: true,
800
- once: true,
801
- onBind: (_, parseResult) => {
802
- const value = parseResult.value();
803
- const ctx = parseResult.context;
804
- const obj = value[0];
805
- if (!isObject(obj)) {
806
- return () => {
807
- };
808
- }
809
- for (const item of Object.entries(obj)) {
810
- const key = item[0];
811
- const value2 = item[1];
812
- const ctxKey = ctx[key];
813
- if (ctxKey === value2) continue;
814
- if (isRef(ctxKey)) {
815
- ctxKey(value2);
816
- } else {
817
- ctx[key] = value2;
818
- }
819
- }
820
- return () => {
821
- };
822
- }
823
- };
824
-
825
876
  // src/reactivity/entangle.ts
826
877
  var entangle = (r1, r2) => {
827
878
  if (r1 === r2) return () => {
@@ -1284,18 +1335,19 @@ var ComponentBinder = class {
1284
1335
  const endOfComponent = new Comment(" end component: " + component.tagName);
1285
1336
  componentParent.insertBefore(startOfComponent, component);
1286
1337
  component.remove();
1287
- const propsName = binder.__config.__builtInNames.props;
1288
- const propsOnceName = binder.__config.__builtInNames.propsOnce;
1338
+ const contextName = binder.__config.__builtInNames.context;
1339
+ const contextAliasName = binder.__config.__builtInNames.contextAlias;
1289
1340
  const bindName = binder.__config.__builtInNames.bind;
1290
1341
  const getProps = (component2, capturedContext2) => {
1291
1342
  const props = {};
1292
- const hasProps = component2.hasAttribute(propsName);
1293
- const hasPropsOnce = component2.hasAttribute(propsOnceName);
1343
+ const hasContext = component2.hasAttribute(contextName);
1294
1344
  parser.__scoped(capturedContext2, () => {
1295
1345
  parser.__push(props);
1296
- if (hasProps) binder.__bind(propsDirective, component2, propsName);
1297
- if (hasPropsOnce)
1298
- binder.__bind(propsOnceDirective, component2, propsOnceName);
1346
+ if (hasContext) {
1347
+ binder.__bind(contextDirective, component2, contextName);
1348
+ } else if (component2.hasAttribute(contextAliasName)) {
1349
+ binder.__bind(contextDirective, component2, contextAliasName);
1350
+ }
1299
1351
  let definedProps = registeredComponent.props;
1300
1352
  if (!definedProps || definedProps.length === 0) return;
1301
1353
  definedProps = definedProps.map(camelize);
@@ -1352,8 +1404,20 @@ var ComponentBinder = class {
1352
1404
  if (key in componentCtx2) {
1353
1405
  const compValue = componentCtx2[key];
1354
1406
  if (compValue === propsValue) continue;
1355
- if (head2.entangle && isRef(compValue) && isRef(propsValue)) {
1356
- addUnbinder(startOfComponent, entangle(propsValue, compValue));
1407
+ if (isRef(compValue)) {
1408
+ if (isRef(propsValue)) {
1409
+ if (head2.entangle) {
1410
+ addUnbinder(
1411
+ startOfComponent,
1412
+ entangle(propsValue, compValue)
1413
+ );
1414
+ } else {
1415
+ compValue(propsValue());
1416
+ }
1417
+ } else {
1418
+ compValue(propsValue);
1419
+ }
1420
+ continue;
1357
1421
  }
1358
1422
  } else componentCtx2[key] = propsValue;
1359
1423
  }
@@ -1464,7 +1528,8 @@ var ComponentBinder = class {
1464
1528
  const inheritor = inheritorChildNodes[0];
1465
1529
  if (!inheritor) return;
1466
1530
  for (const attrName of component.getAttributeNames()) {
1467
- if (attrName === propsName || attrName === propsOnceName) continue;
1531
+ if (attrName === contextName || attrName === contextAliasName)
1532
+ continue;
1468
1533
  const value = component.getAttribute(attrName);
1469
1534
  if (attrName === "class") {
1470
1535
  inheritor.classList.add(...value.split(" "));
@@ -3347,6 +3412,7 @@ var _RegorConfig = class _RegorConfig {
3347
3412
  [`${prefix}show`]: showDirective,
3348
3413
  [`${prefix}model`]: modelDirective,
3349
3414
  ":style": styleDirective,
3415
+ [`${prefix}style`]: styleDirective,
3350
3416
  [`${prefix}bind:style`]: styleDirective,
3351
3417
  ":class": classDirective,
3352
3418
  [`${prefix}bind:class`]: classDirective,
@@ -3362,8 +3428,8 @@ var _RegorConfig = class _RegorConfig {
3362
3428
  pre: `${prefix}pre`,
3363
3429
  inherit: `${prefix}inherit`,
3364
3430
  text: `${prefix}text`,
3365
- props: ":props",
3366
- propsOnce: ":props-once",
3431
+ context: ":context",
3432
+ contextAlias: `${prefix}context`,
3367
3433
  bind: `${prefix}bind`,
3368
3434
  on: `${prefix}on`,
3369
3435
  keyBind: ":key",