@mintjamsinc/ichigojs 0.1.76 → 0.1.78

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.
@@ -2,6 +2,7 @@ import { VLogManager } from "./util/VLogManager";
2
2
  import { VApplicationOptions } from "./VApplicationOptions";
3
3
  import { VBindings } from "./VBindings";
4
4
  import { VNode } from "./VNode";
5
+ import { VNodeInit } from "./VNodeInit";
5
6
  import { VDirectiveParserRegistry } from "./directives/VDirectiveParserRegistry";
6
7
  import { VComponentRegistry } from "./components/VComponentRegistry";
7
8
  import { VApplicationInit } from "./VApplicationInit";
@@ -52,11 +53,28 @@ export declare class VApplication {
52
53
  * object is exposed to data(), methods, and expressions as `$refs`. Non-reactive by design.
53
54
  */
54
55
  get refs(): Record<string, Element | Element[]>;
56
+ /**
57
+ * The custom element hosting this application when it powers a component
58
+ * (see the #hostElement field). Undefined for regular applications.
59
+ */
60
+ get hostElement(): HTMLElement | undefined;
61
+ set hostElement(element: HTMLElement | undefined);
62
+ /**
63
+ * Creates a VNode. Directives that need to build VNode trees at runtime
64
+ * (e.g. the scoped slot outlet) call this instead of constructing VNode
65
+ * directly, so they can keep their VNode import type-only and avoid a
66
+ * VNode -> VDirectiveManager -> directive -> VNode module cycle.
67
+ * @param init The initialization arguments for the virtual node.
68
+ * @returns The created VNode.
69
+ */
70
+ createVNode(init: VNodeInit): VNode;
55
71
  /**
56
72
  * Mounts the application.
57
73
  * @param target The CSS selector string or HTMLElement to mount the application to.
74
+ * @returns This application instance, so `VDOM.createApp(...).mount('#app')`
75
+ * can be assigned for later access (e.g. `app.bindings`, `app.unmount()`).
58
76
  */
59
- mount(target: string | HTMLElement): void;
77
+ mount(target: string | HTMLElement): this;
60
78
  /**
61
79
  * Unmounts the application and cleans up resources.
62
80
  */
@@ -11,9 +11,12 @@ export type VComputedDefinition = (() => unknown) | {
11
11
  export interface VApplicationOptions {
12
12
  /**
13
13
  * A function that returns the initial data for the application.
14
+ * Optional: an application (or component) whose state comes entirely from
15
+ * props, computed properties, or methods may omit it — the runtime already
16
+ * treats it as optional.
14
17
  * @returns The initial data for the application.
15
18
  */
16
- data: () => unknown;
19
+ data?: () => unknown;
17
20
  /**
18
21
  * A dictionary of computed properties for the application.
19
22
  * Each key is the name of the computed property, and the value is either:
@@ -1,16 +1,60 @@
1
1
  import { VApplicationOptions } from '../VApplicationOptions';
2
+ /**
3
+ * Per-prop declaration options.
4
+ *
5
+ * All checks (type, required, validator) report console warnings only; values
6
+ * are never rejected or coerced. This mirrors the philosophy of the `emits`
7
+ * declaration: the declaration documents the contract and helps development,
8
+ * without changing runtime behavior.
9
+ */
10
+ export interface PropOptions {
11
+ /**
12
+ * Expected type(s), given as constructor functions
13
+ * (String, Number, Boolean, Array, Object, Function, Date, or any class).
14
+ * When omitted, any type is accepted. null/undefined values always pass
15
+ * the type check (undefined is subject to `default`/`required` instead,
16
+ * and null is treated as an explicit "no value").
17
+ */
18
+ type?: Function | Function[];
19
+ /**
20
+ * Default value applied when the prop is undefined at mount time, or when
21
+ * the parent later assigns undefined.
22
+ *
23
+ * Object/Array defaults must be declared as a factory function
24
+ * (e.g. `default: () => []`) so that instances are not shared across
25
+ * component instances. A function default is treated as the value itself
26
+ * only when `type` includes Function; otherwise it is called as a factory.
27
+ */
28
+ default?: any;
29
+ /**
30
+ * When true, a warning is logged if the prop is still undefined at mount
31
+ * time (after `default` resolution). The mount proceeds either way.
32
+ */
33
+ required?: boolean;
34
+ /**
35
+ * Custom validator. A falsy return value logs a warning.
36
+ * Called for every non-null/undefined value delivered to the component.
37
+ */
38
+ validator?: (value: any) => boolean;
39
+ }
40
+ /**
41
+ * Props declaration: either a simple list of prop names, or a record of
42
+ * per-prop options. Use `null` (or `{}`) as the value for a prop that needs
43
+ * no constraints, e.g. `props: { target: null, size: { default: 'md' } }`.
44
+ */
45
+ export type PropsDeclaration = string[] | Record<string, PropOptions | null>;
2
46
  /**
3
47
  * Options for defining a Web Component backed by ichigo.js reactivity.
4
48
  * Extends VApplicationOptions with component-specific settings.
5
49
  */
6
50
  export interface IchigoComponentOptions extends VApplicationOptions {
7
51
  /**
8
- * List of property names to receive from the parent via attribute/property binding.
9
- * Each name in this list will be exposed as a property setter on the custom element.
10
- * When the parent updates a bound value (e.g., :items="items"), the component's
11
- * reactive bindings are updated automatically.
52
+ * Properties to receive from the parent via property binding.
53
+ * Each declared prop is exposed as a property accessor on the custom
54
+ * element. When the parent updates a bound value (e.g., :items="items"),
55
+ * the component's reactive bindings are updated automatically.
12
56
  */
13
- props?: string[];
57
+ props?: PropsDeclaration;
14
58
  /**
15
59
  * CSS selector for the <template> element that defines this component's markup.
16
60
  * Example: '#my-card' targets <template id="my-card">.
@@ -1,26 +1,67 @@
1
1
  import { VApplicationOptions } from '../VApplicationOptions';
2
+ import { PropOptions } from './IchigoComponentOptions';
3
+ import type { VNode } from '../VNode';
4
+ /**
5
+ * A scoped slot template captured from the host element's children:
6
+ * the `<template v-slot:name="scopeVar">` element and the scope variable name
7
+ * its content receives the slot props under (may be empty when no variable
8
+ * was declared).
9
+ */
10
+ export interface ScopedSlotEntry {
11
+ template: HTMLTemplateElement;
12
+ scopeVar: string;
13
+ }
2
14
  /**
3
15
  * Base class for ichigo.js-backed Web Components (Light DOM, no Shadow DOM).
4
16
  *
5
17
  * Mount timing:
6
18
  * - If the component declares no props, the VApplication is mounted synchronously
7
19
  * at the end of connectedCallback (the template is known, no props to wait for).
8
- * - If the component declares props, the VApplication is mounted the first time
9
- * _setProp() is called after connectedCallback has prepared the DOM. This
10
- * guarantees that the parent framework (e.g. ichigo.js VBindDirective) has
11
- * already delivered at least one prop value before data() is evaluated.
20
+ * - If the component declares props, a mount microtask is scheduled at the end of
21
+ * connectedCallback. Prop values delivered synchronously by the parent framework
22
+ * (VBindDirective runs within the parent's mount task) are stored before the
23
+ * microtask fires, so data() can read them. A component used without any prop
24
+ * binding still mounts — with its declared defaults — instead of waiting forever.
12
25
  *
13
- * Subclasses must set the static fields _template, _props and _buildOptions before
14
- * calling customElements.define(). defineComponent() handles this automatically.
26
+ * Slot content is captured on the first connection and cached, so a component
27
+ * that is moved in the DOM (e.g. reordered by v-for) re-expands its template
28
+ * and redistributes the same slot nodes on reconnection.
29
+ *
30
+ * Subclasses must set the static fields _template, _props, _propOptions and
31
+ * _buildOptions before calling customElements.define(). defineComponent()
32
+ * handles this automatically.
15
33
  */
16
34
  export declare class IchigoElement extends HTMLElement {
17
35
  #private;
36
+ /**
37
+ * True once this element's children are the expanded component template.
38
+ * Read by VNode during compilation: a parent application must not compile
39
+ * an expanded component's internals as its own template (the internals
40
+ * belong to this component's VApplication and scope).
41
+ */
42
+ _ichigoExpanded: boolean;
43
+ /**
44
+ * Host context installed by the parent application's VNode when it
45
+ * compiles this element. Gives component-boundary features (e.g. scoped
46
+ * slot outlets) access to the parent scope. Undefined when the element is
47
+ * placed outside any ichigo application.
48
+ */
49
+ _ichigoHost?: {
50
+ vNode: VNode;
51
+ };
52
+ /**
53
+ * The scoped slot templates captured from this element's children, keyed
54
+ * by slot name ('default' for `v-slot` without a name). Read by
55
+ * VSlotOutletDirective when the component template renders a `<slot>`.
56
+ */
57
+ get _ichigoScopedSlots(): Map<string, ScopedSlotEntry> | undefined;
18
58
  connectedCallback(): void;
19
59
  disconnectedCallback(): void;
20
60
  /**
21
61
  * Called by the property setters generated by defineComponent().
22
62
  * Before mount: stores the value and schedules a mount microtask.
23
63
  * After mount: pushes the value directly into the reactive bindings.
64
+ * An undefined value is replaced by the prop's declared default, if any.
24
65
  */
25
66
  _setProp(name: string, value: any): void;
26
67
  /**
@@ -32,9 +73,16 @@ export declare class IchigoElement extends HTMLElement {
32
73
  */
33
74
  static _template: string;
34
75
  /**
35
- * List of declared prop names. Used to decide whether to defer mounting.
76
+ * List of declared prop names. Used to decide whether to defer mounting,
77
+ * and by VBindDirective to resolve kebab-case attributes to prop names.
36
78
  */
37
79
  static _props: string[];
80
+ /**
81
+ * Per-prop declaration options (type / default / required / validator),
82
+ * keyed by prop name. Normalized by defineComponent(): a prop declared
83
+ * without options gets an empty object.
84
+ */
85
+ static _propOptions: Record<string, PropOptions>;
38
86
  /**
39
87
  * Factory that builds VApplicationOptions from the current prop values.
40
88
  * Implemented by defineComponent() as a closure that captures the user's options.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Registry of custom element tag names defined via defineComponent().
3
+ *
4
+ * VNode consults this registry during compilation to recognize component
5
+ * boundaries: the children of an already-expanded ichigo component belong to
6
+ * the component's own VApplication and must not be compiled by the parent
7
+ * application (doing so would strip the component's directives and evaluate
8
+ * its template expressions in the wrong scope).
9
+ */
10
+ export declare class IchigoElementRegistry {
11
+ #private;
12
+ /**
13
+ * Registers a component tag name. Called by defineComponent().
14
+ * @param tagName The custom element tag name (case-insensitive).
15
+ */
16
+ static add(tagName: string): void;
17
+ /**
18
+ * Checks whether a tag name belongs to a component defined via defineComponent().
19
+ * @param tagName The tag name to check (case-insensitive; nodeName is accepted as-is).
20
+ */
21
+ static has(tagName: string): boolean;
22
+ }
@@ -16,9 +16,8 @@ import { IchigoComponentOptions } from './IchigoComponentOptions';
16
16
  * ```typescript
17
17
  * defineComponent('my-list', {
18
18
  * template: '#my-list',
19
- * props: ['items'],
20
- * data() {
21
- * return { items: this.items ?? [] };
19
+ * props: {
20
+ * items: { type: Array, default: () => [] },
22
21
  * },
23
22
  * });
24
23
  * ```
@@ -28,6 +27,10 @@ import { IchigoComponentOptions } from './IchigoComponentOptions';
28
27
  * </my-list>
29
28
  * ```
30
29
  *
30
+ * Props may be declared as a simple name list (`props: ['items']`) or as a
31
+ * record with per-prop options (type / default / required / validator).
32
+ * See {@link PropOptions} for the declaration semantics.
33
+ *
31
34
  * @param tagName Custom element tag name (must contain a hyphen, e.g. 'my-card').
32
35
  * @param options Component options including template selector and optional props.
33
36
  */
@@ -0,0 +1,114 @@
1
+ import type { VNode } from "../VNode";
2
+ import { VBindingsPreparer } from "../VBindingsPreparer";
3
+ import { VDirective } from "./VDirective";
4
+ import { VDOMUpdater } from "../VDOMUpdater";
5
+ /**
6
+ * Renders a scoped slot outlet: a `<slot>` element inside a component template
7
+ * whose host element received a matching `<template v-slot:name="scope">` from
8
+ * the parent.
9
+ *
10
+ * The slot content is compiled in the PARENT application's scope (the scope in
11
+ * which the template was authored), extended with the slot props — the values
12
+ * bound on the `<slot>` outlet with `v-bind` / `:` — exposed under the single
13
+ * scope variable declared in `v-slot` (e.g. `v-slot:item="row"` makes
14
+ * `row.node`, `row.index`, ... available):
15
+ *
16
+ * ```html
17
+ * <!-- component template -->
18
+ * <li v-for="(node, i) of items">
19
+ * <slot name="item" :node="node" :index="i">fallback</slot>
20
+ * </li>
21
+ *
22
+ * <!-- usage -->
23
+ * <my-tree :items="nodes">
24
+ * <template v-slot:item="row">{{ row.node.label }} ({{ appTitle }})</template>
25
+ * </my-tree>
26
+ * ```
27
+ *
28
+ * This directive is created only when a scoped template for the slot's name
29
+ * exists (see {@link VSlotOutletDirective.tryCreate}); otherwise `<slot>`
30
+ * elements keep their existing behavior (static distribution at expansion,
31
+ * or fallback content compiled in the component scope).
32
+ *
33
+ * Rendering happens synchronously in onMount — before the component
34
+ * application would compile the slot's fallback children — by replacing the
35
+ * `<slot>` element with a clone of the scoped template's content. The content
36
+ * VNode is attached under the host element's VNode in the parent application,
37
+ * so parent-side data changes flow through the normal update cycle; slot-prop
38
+ * changes on the component side are pushed by this directive's domUpdater.
39
+ */
40
+ export declare class VSlotOutletDirective implements VDirective {
41
+ #private;
42
+ /**
43
+ * Creates a slot outlet directive for the given `<slot>` VNode when a
44
+ * scoped template for its slot name was captured on the host element.
45
+ * Returns undefined when there is nothing to do (no component host, no
46
+ * scoped template for this name) so the `<slot>` element keeps its
47
+ * existing behavior.
48
+ */
49
+ static tryCreate(vNode: VNode): VSlotOutletDirective | undefined;
50
+ private constructor();
51
+ /**
52
+ * @inheritdoc
53
+ */
54
+ get name(): string;
55
+ /**
56
+ * @inheritdoc
57
+ */
58
+ get vNode(): VNode;
59
+ /**
60
+ * @inheritdoc
61
+ */
62
+ get needsAnchor(): boolean;
63
+ /**
64
+ * @inheritdoc
65
+ */
66
+ get bindingsPreparer(): VBindingsPreparer | undefined;
67
+ /**
68
+ * @inheritdoc
69
+ */
70
+ get domUpdater(): VDOMUpdater | undefined;
71
+ /**
72
+ * @inheritdoc
73
+ */
74
+ get templatize(): boolean;
75
+ /**
76
+ * @inheritdoc
77
+ */
78
+ get dependentIdentifiers(): string[];
79
+ /**
80
+ * @inheritdoc
81
+ *
82
+ * The initial render happens here — synchronously during VNode
83
+ * construction, after the directives are created and BEFORE the component
84
+ * application compiles the slot element's children. This guarantees the
85
+ * outlet renders exactly once regardless of whether its slot props have
86
+ * reactive identifiers, and removes the fallback children before they
87
+ * could be compiled in the component scope.
88
+ */
89
+ get onMount(): (() => void) | undefined;
90
+ /**
91
+ * @inheritdoc
92
+ */
93
+ get onMounted(): (() => void) | undefined;
94
+ /**
95
+ * @inheritdoc
96
+ */
97
+ get onUpdate(): (() => void) | undefined;
98
+ /**
99
+ * @inheritdoc
100
+ */
101
+ get onUpdated(): (() => void) | undefined;
102
+ /**
103
+ * @inheritdoc
104
+ */
105
+ get onUnmount(): (() => void) | undefined;
106
+ /**
107
+ * @inheritdoc
108
+ */
109
+ get onUnmounted(): (() => void) | undefined;
110
+ /**
111
+ * @inheritdoc
112
+ */
113
+ destroy(): void;
114
+ }
@@ -5,6 +5,6 @@ export { ReactiveProxy } from './ichigo/util/ReactiveProxy';
5
5
  export { ExpressionUtils } from './ichigo/util/ExpressionUtils';
6
6
  export { toDisplayString } from './ichigo/util/DisplayString';
7
7
  export { defineComponent } from './ichigo/components/defineComponent';
8
- export type { IchigoComponentOptions } from './ichigo/components/IchigoComponentOptions';
8
+ export type { IchigoComponentOptions, PropOptions, PropsDeclaration } from './ichigo/components/IchigoComponentOptions';
9
9
  export { IchigoElement } from './ichigo/components/IchigoElement';
10
10
  export type { VEmitOptions } from './ichigo/VEmitOptions';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mintjamsinc/ichigojs",
3
- "version": "0.1.76",
3
+ "version": "0.1.78",
4
4
  "description": "ichigo.js - Simple and intuitive reactive framework. Lightweight, fast, and user-friendly virtual DOM library",
5
5
  "main": "./dist/ichigo.cjs",
6
6
  "module": "./dist/ichigo.esm.js",