@nisli/core 0.51.0 → 0.53.0
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 +26 -0
- package/dist/component.d.ts +133 -9
- package/dist/component.js +197 -9
- package/dist/component.js.map +1 -1
- package/dist/element-context.d.ts +81 -0
- package/dist/element-context.js +108 -0
- package/dist/element-context.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/projection.d.ts +44 -0
- package/dist/projection.js +155 -0
- package/dist/projection.js.map +1 -0
- package/dist/query.d.ts +5 -1
- package/dist/query.js +11 -4
- package/dist/query.js.map +1 -1
- package/dist/signal.d.ts +20 -0
- package/dist/signal.js +53 -3
- package/dist/signal.js.map +1 -1
- package/dist/template.d.ts +44 -0
- package/dist/template.js +159 -19
- package/dist/template.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,17 @@ A reactive web component framework. Signals, templates, dependency injection —
|
|
|
8
8
|
npm install @nisli/core
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
To add the source-first component registry with Tailwind v4 animations:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @nisli/core
|
|
15
|
+
npm install -D @nisli/ui tailwindcss tw-animate-css
|
|
16
|
+
npx nisli-ui init
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Then import `tailwindcss`, `tw-animate-css`, and the copied
|
|
20
|
+
`nisli-ui/styles/theme.css` in that order in your entry stylesheet.
|
|
21
|
+
|
|
11
22
|
## Quick Start
|
|
12
23
|
|
|
13
24
|
```typescript
|
|
@@ -101,6 +112,21 @@ await buildStaticSite({
|
|
|
101
112
|
`@nisli/ssg` owns static site generation; static rendering internals stay behind
|
|
102
113
|
the build tool.
|
|
103
114
|
|
|
115
|
+
## Vite HMR Plugin
|
|
116
|
+
|
|
117
|
+
`@nisli/core/vite-hmr` — a dev-only Vite plugin for granular component hot module replacement. Edit a component, it re-mounts in place with no page reload.
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
// vite.config.ts
|
|
121
|
+
import { nisliHmr } from '@nisli/core/vite-hmr';
|
|
122
|
+
|
|
123
|
+
export default defineConfig({
|
|
124
|
+
plugins: [nisliHmr()],
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Used in production by [backlog-mcp](https://github.com/gkoreli/backlog-mcp) — a single Vite process serves the SPA + API on one origin, with component edits hot-swapping via this plugin.
|
|
129
|
+
|
|
104
130
|
## Size
|
|
105
131
|
|
|
106
132
|
~2,600 lines of TypeScript. Zero dependencies.
|
package/dist/component.d.ts
CHANGED
|
@@ -13,17 +13,78 @@
|
|
|
13
13
|
import { type Signal, type ReadonlySignal } from './signal.js';
|
|
14
14
|
import type { TemplateResult } from './template.js';
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* Narrows one prop's reactive value to the runtime type its `attrs`
|
|
17
|
+
* declaration guarantees (ADR 0025 candidate (b)). Only the two kinds core
|
|
18
|
+
* reconciles to a NON-`undefined` runtime value narrow; everything else is
|
|
19
|
+
* left as the author's `T` (= `P[K]`):
|
|
20
|
+
*
|
|
21
|
+
* - `'boolean'` / `{ type:'boolean' }` (any default) → `boolean` — a declared
|
|
22
|
+
* boolean is absent→`false`, never `undefined`.
|
|
23
|
+
* - `{ type:'number'; default }` → `number` — the default guarantees a value.
|
|
24
|
+
* - `'number'` / `{ type:'number' }` WITHOUT a default → `number | undefined`.
|
|
25
|
+
* - `'string'` / `{ type:'string' }` / `'forward'` / undeclared → `T` unchanged
|
|
26
|
+
* (a string attr is genuinely absent→`undefined`; forwarding does not touch
|
|
27
|
+
* the value type).
|
|
28
|
+
*
|
|
29
|
+
* SOUND FALLBACK on an incompatible declaration: the narrowed runtime type is
|
|
30
|
+
* applied ONLY when the declared kind and `NonNullable<T>` (the prop's author
|
|
31
|
+
* type) agree EXACTLY — mutual assignability, BOTH directions. A one-way check
|
|
32
|
+
* (`boolean extends NonNullable<T>`) is unsound: it would still narrow a
|
|
33
|
+
* `boolean | string` prop to `boolean` (silently dropping `string`), and a
|
|
34
|
+
* one-way check the other way would widen a literal `true`/`1` prop. So a
|
|
35
|
+
* declaration is honored only when `NonNullable<T>` IS the kind — `boolean` for
|
|
36
|
+
* a boolean declaration, `number` for a numeric one — via {@link IsExactKind}.
|
|
37
|
+
* Every genuine mismatch or partial overlap (`boolean | string` declared
|
|
38
|
+
* `'boolean'`, `'boolean'` on a `string` prop, a numeric decl on a boolean prop,
|
|
39
|
+
* a literal `true`/`1` prop) falls back to `T` unchanged — never a compile-time
|
|
40
|
+
* lie about the value. The whole registry declares props as exactly `boolean` /
|
|
41
|
+
* `number`, so it narrows as before; only unions/literals/mismatches are refused.
|
|
42
|
+
*
|
|
43
|
+
* `D` is the declaration at that key (or `undefined` when the key is absent
|
|
44
|
+
* from the `attrs` map, in which case the caller passes `T` through directly).
|
|
45
|
+
*/
|
|
46
|
+
export type AttrValueType<T, D> = D extends 'boolean' ? (IsExactKind<T, boolean> extends true ? boolean : T) : D extends {
|
|
47
|
+
type: 'boolean';
|
|
48
|
+
} ? (IsExactKind<T, boolean> extends true ? boolean : T) : D extends {
|
|
49
|
+
type: 'number';
|
|
50
|
+
default: number;
|
|
51
|
+
} ? (IsExactKind<T, number> extends true ? number : T) : D extends 'number' ? (IsExactKind<T, number> extends true ? number | undefined : T) : D extends {
|
|
52
|
+
type: 'number';
|
|
53
|
+
} ? (IsExactKind<T, number> extends true ? number | undefined : T) : T;
|
|
54
|
+
/**
|
|
55
|
+
* `true` iff `NonNullable<T>` is EXACTLY `K` — mutually assignable in both
|
|
56
|
+
* directions (`NonNullable<T> extends K` AND `K extends NonNullable<T>`). The
|
|
57
|
+
* tuple wrappers block distribution so `boolean` (`= true | false`) is compared
|
|
58
|
+
* whole: `boolean | string` is NOT exactly `boolean` (fails the first arm), and
|
|
59
|
+
* `true` is NOT exactly `boolean` (fails the second), so both are refused.
|
|
18
60
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
61
|
+
type IsExactKind<T, K> = [
|
|
62
|
+
NonNullable<T>
|
|
63
|
+
] extends [K] ? ([K] extends [NonNullable<T>] ? true : false) : false;
|
|
64
|
+
/**
|
|
65
|
+
* Maps a props interface to reactive signals, narrowed by the `attrs`
|
|
66
|
+
* declaration `A` (ADR 0025 candidate (b)).
|
|
67
|
+
*
|
|
68
|
+
* Each prop `P[K]` becomes `Signal<AttrValueType<P[K], A[K]>>` when `K` is
|
|
69
|
+
* declared in `A`, otherwise `Signal<P[K]>`. So a declared `'boolean'` types as
|
|
70
|
+
* `Signal<boolean>` (not `Signal<boolean | undefined>`), retiring the
|
|
71
|
+
* registry's `as boolean` stopgap. `A` defaults to `{}` (no declared keys →
|
|
72
|
+
* every prop unchanged), so `ReactiveProps<P>` keeps its pre-candidate-(b)
|
|
73
|
+
* meaning and existing single-argument uses are unaffected.
|
|
74
|
+
*
|
|
75
|
+
* Optionality is stripped (`-?`): the props Proxy always returns a signal,
|
|
76
|
+
* even for props never set — an optional prop `variant?: T` is
|
|
77
|
+
* `Signal<T | undefined>`, not `Signal<T> | undefined`.
|
|
78
|
+
*/
|
|
79
|
+
export type ReactiveProps<P, A extends ComponentAttrs<P> = {}> = {
|
|
80
|
+
readonly [K in keyof P]-?: Signal<K extends keyof A ? AttrValueType<P[K], A[K]> : P[K]>;
|
|
21
81
|
};
|
|
22
82
|
/**
|
|
23
|
-
* The setup function signature. Receives reactive props
|
|
24
|
-
* Returns a TemplateResult to be
|
|
83
|
+
* The setup function signature. Receives reactive props (narrowed by the
|
|
84
|
+
* `attrs` declaration `A`) and the host element. Returns a TemplateResult to be
|
|
85
|
+
* mounted into the component.
|
|
25
86
|
*/
|
|
26
|
-
export type SetupFunction<P> = (props: ReactiveProps<P>, host: HTMLElement) => TemplateResult;
|
|
87
|
+
export type SetupFunction<P, A extends ComponentAttrs<P> = {}> = (props: ReactiveProps<P, A>, host: HTMLElement) => TemplateResult;
|
|
27
88
|
/**
|
|
28
89
|
* Accepts either a Signal<T> (reactive) or a plain T (static, auto-wrapped).
|
|
29
90
|
* This eliminates the need to wrap static values in `signal()` at call sites.
|
|
@@ -47,10 +108,70 @@ export interface HostAttrs {
|
|
|
47
108
|
export type ComponentFactory<P> = (props: {
|
|
48
109
|
[K in keyof P]: PropInput<P[K]>;
|
|
49
110
|
}, hostAttrs?: HostAttrs) => TemplateResult;
|
|
111
|
+
/**
|
|
112
|
+
* Opt-in attribute reactivity declaration (ADR 0025 item 3).
|
|
113
|
+
*
|
|
114
|
+
* Declares how a host attribute maps onto a prop signal, subsuming userland
|
|
115
|
+
* `attr()`/`boolAttr()`/`forwardedAttr()`. Unlike those (which read the
|
|
116
|
+
* attribute once at setup), a declared attribute is `observedAttributes`-wired,
|
|
117
|
+
* so `setAttribute()` AFTER mount writes the prop signal LIVE.
|
|
118
|
+
*
|
|
119
|
+
* - `'string'` — the attribute's string value (absent → `undefined`).
|
|
120
|
+
* - `'boolean'` — OUR boolean semantics: bare/any value → `true`, literal
|
|
121
|
+
* `"false"` → `false`, absent → `false`.
|
|
122
|
+
* - `'number'` — `Number(raw)`; absent → the default (else `undefined`); a
|
|
123
|
+
* non-numeric value behaves as absent → the default (else `undefined`), so a
|
|
124
|
+
* garbage attribute never propagates `NaN` into layout math.
|
|
125
|
+
* - `{ type: 'boolean', default: true }` — as above but absent → the default
|
|
126
|
+
* (so a default-`true` flag can be opted out with `attr="false"`).
|
|
127
|
+
* - `{ type: 'string', default: '…' }` — string with an absent-value default.
|
|
128
|
+
* - `{ type: 'number', default: 0 }` — number with an absent-value default.
|
|
129
|
+
* - `'forward'` — string semantics PLUS relocation: the attribute is removed
|
|
130
|
+
* from the (layout-transparent) host so `id`/`name` live only on the inner
|
|
131
|
+
* control (native form participation), matching `forwardedAttr()`.
|
|
132
|
+
*
|
|
133
|
+
* The observed attribute name is the kebab-case of the prop key (`className` ↔
|
|
134
|
+
* `class-name`, `showOutsideDays` ↔ `show-outside-days`, `id` ↔ `id`). The
|
|
135
|
+
* object forms accept an `attr` override for props whose native attribute is
|
|
136
|
+
* NOT the kebab derivation — e.g. `readOnly: { type: 'boolean', attr: 'readonly' }`
|
|
137
|
+
* (the native boolean attribute is `readonly`, not `read-only`). (v1.1)
|
|
138
|
+
*/
|
|
139
|
+
export type AttrDecl = 'string' | 'boolean' | 'number' | 'forward' | {
|
|
140
|
+
type: 'boolean';
|
|
141
|
+
default?: boolean;
|
|
142
|
+
attr?: string;
|
|
143
|
+
} | {
|
|
144
|
+
type: 'string';
|
|
145
|
+
default?: string;
|
|
146
|
+
attr?: string;
|
|
147
|
+
} | {
|
|
148
|
+
type: 'number';
|
|
149
|
+
default?: number;
|
|
150
|
+
attr?: string;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* The `attrs` declaration map for a props interface `P`: prop keys → attribute
|
|
154
|
+
* behavior. This is the type an `attrs` object satisfies; capture its literal
|
|
155
|
+
* type with `typeof` and pass it as `component`'s second type argument to
|
|
156
|
+
* unlock declared-type narrowing (ADR 0025 candidate (b)):
|
|
157
|
+
*
|
|
158
|
+
* ```ts
|
|
159
|
+
* const attrs = { checked: 'boolean' } satisfies ComponentAttrs<SwitchProps>;
|
|
160
|
+
* const Switch = component<SwitchProps, typeof attrs>('ui-switch', setup, { attrs });
|
|
161
|
+
* // inside setup: props.checked.value is `boolean`, not `boolean | undefined`
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export type ComponentAttrs<P> = Partial<Record<Extract<keyof P, string>, AttrDecl>>;
|
|
50
165
|
/** Options for component() registration */
|
|
51
|
-
export interface ComponentOptions {
|
|
166
|
+
export interface ComponentOptions<P = unknown> {
|
|
52
167
|
/** Custom error fallback renderer */
|
|
53
168
|
onError?: (error: Error, host: HTMLElement) => TemplateResult | string;
|
|
169
|
+
/**
|
|
170
|
+
* Opt-in attribute reactivity (ADR 0025 item 3). Maps prop keys
|
|
171
|
+
* to attribute declarations. Omitted entirely → zero cost (empty
|
|
172
|
+
* `observedAttributes`, no `attributeChangedCallback` work).
|
|
173
|
+
*/
|
|
174
|
+
attrs?: ComponentAttrs<P>;
|
|
54
175
|
}
|
|
55
176
|
/**
|
|
56
177
|
* Define a web component with typed props and a setup function.
|
|
@@ -72,4 +193,7 @@ export interface ComponentOptions {
|
|
|
72
193
|
* TaskItem({ task: taskSignal, selected: isSelected })
|
|
73
194
|
* ```
|
|
74
195
|
*/
|
|
75
|
-
export declare function component<P extends Record<string,
|
|
196
|
+
export declare function component<P extends object = Record<string, never>, A extends ComponentAttrs<P> = {}>(tagName: string, setup: SetupFunction<P, A>, ...[options]: [keyof A] extends [never] ? [options?: ComponentOptions<P>] : [options: ComponentOptions<P> & {
|
|
197
|
+
attrs: A;
|
|
198
|
+
}]): ComponentFactory<P>;
|
|
199
|
+
export {};
|
package/dist/component.js
CHANGED
|
@@ -22,6 +22,37 @@ setContextHook(() => {
|
|
|
22
22
|
}
|
|
23
23
|
return null;
|
|
24
24
|
});
|
|
25
|
+
const camelToKebab = (s) => s.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
26
|
+
const declType = (decl) => typeof decl === 'string' ? decl : decl.type;
|
|
27
|
+
/** The observed attribute name: an explicit `attr` override, else kebab(key). */
|
|
28
|
+
const declAttrName = (key, decl) => typeof decl === 'object' && decl.attr ? decl.attr : camelToKebab(key);
|
|
29
|
+
/** Resolve a raw attribute string (or null when absent) to the prop value. */
|
|
30
|
+
function resolveAttrValue(decl, raw) {
|
|
31
|
+
const t = declType(decl);
|
|
32
|
+
if (t === 'boolean') {
|
|
33
|
+
const def = typeof decl === 'object' && 'default' in decl && decl.default !== undefined
|
|
34
|
+
? decl.default
|
|
35
|
+
: false;
|
|
36
|
+
if (raw === null)
|
|
37
|
+
return def; // absent → declared default (else false)
|
|
38
|
+
return raw !== 'false'; // bare/any → true, literal "false" → false
|
|
39
|
+
}
|
|
40
|
+
if (t === 'number') {
|
|
41
|
+
const def = typeof decl === 'object' && 'default' in decl ? decl.default : undefined;
|
|
42
|
+
if (raw === null)
|
|
43
|
+
return def; // absent → declared default (else undefined)
|
|
44
|
+
const n = Number(raw);
|
|
45
|
+
// Garbage behaves as ABSENT → the declared default (else undefined). A
|
|
46
|
+
// default exists to guarantee non-undefined; letting garbage fall to
|
|
47
|
+
// literal undefined would reintroduce exactly what the default prevents.
|
|
48
|
+
return Number.isNaN(n) ? def : n;
|
|
49
|
+
}
|
|
50
|
+
// 'string' | 'forward'
|
|
51
|
+
if (raw === null) {
|
|
52
|
+
return typeof decl === 'object' && 'default' in decl ? decl.default : undefined;
|
|
53
|
+
}
|
|
54
|
+
return raw;
|
|
55
|
+
}
|
|
25
56
|
// ── Internal component host ─────────────────────────────────────────
|
|
26
57
|
class ComponentHostImpl {
|
|
27
58
|
element;
|
|
@@ -92,17 +123,86 @@ function createPropsProxy() {
|
|
|
92
123
|
* TaskItem({ task: taskSignal, selected: isSelected })
|
|
93
124
|
* ```
|
|
94
125
|
*/
|
|
95
|
-
export function component(tagName, setup,
|
|
126
|
+
export function component(tagName, setup,
|
|
127
|
+
// When `A` is explicitly given a non-empty attrs literal (the narrowing
|
|
128
|
+
// opt-in), the options argument — carrying `attrs: A` — is REQUIRED: a
|
|
129
|
+
// `component<P, typeof attrs>(tag, setup)` that types the props as narrowed but
|
|
130
|
+
// never actually wires the attrs at runtime would be a compile-time lie. When
|
|
131
|
+
// `A` is `{}` (the legacy default, no second type arg), options stays optional
|
|
132
|
+
// exactly as before. `attrs` in that legacy branch is still validated as
|
|
133
|
+
// `ComponentAttrs<P>` via `ComponentOptions<P>`.
|
|
134
|
+
...[options]) {
|
|
135
|
+
// Attribute-reactivity wiring (ADR 0025 item 3). Computed once
|
|
136
|
+
// per component definition; empty when no `attrs` declared (→ zero cost).
|
|
137
|
+
const attrEntries = new Map(); // by attrName
|
|
138
|
+
const attrEntriesByKey = new Map(); // by prop key
|
|
139
|
+
if (options?.attrs) {
|
|
140
|
+
for (const key of Object.keys(options.attrs)) {
|
|
141
|
+
const decl = options.attrs[key];
|
|
142
|
+
const attrName = declAttrName(key, decl);
|
|
143
|
+
const entry = { key, attrName, decl };
|
|
144
|
+
attrEntries.set(attrName, entry);
|
|
145
|
+
attrEntriesByKey.set(key, entry);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const observedList = Array.from(attrEntries.keys());
|
|
96
149
|
// The custom element class
|
|
97
150
|
class FrameworkComponent extends HTMLElement {
|
|
98
151
|
_host = null;
|
|
99
152
|
_propsProxy = null;
|
|
100
153
|
_mounted = false;
|
|
101
154
|
_templateResult = null;
|
|
155
|
+
_teardownScheduled = false;
|
|
156
|
+
// Props explicitly set via _setProp (factory / direct assignment) are
|
|
157
|
+
// "pinned": an explicit prop wins, so attribute writes no longer overwrite
|
|
158
|
+
// it. (Precedence ruling: prop-pins.)
|
|
159
|
+
_pinned = new Set();
|
|
160
|
+
// Guards our own removeAttribute() during 'forward' relocation from
|
|
161
|
+
// re-entering attributeChangedCallback.
|
|
162
|
+
_relocating = false;
|
|
163
|
+
/** The browser reads this once at define time. Empty → no callbacks. */
|
|
164
|
+
static get observedAttributes() {
|
|
165
|
+
return observedList;
|
|
166
|
+
}
|
|
102
167
|
constructor() {
|
|
103
168
|
super();
|
|
104
169
|
this._propsProxy = createPropsProxy();
|
|
105
170
|
}
|
|
171
|
+
/** Write one declared attribute onto its prop signal, honoring pinning. */
|
|
172
|
+
_applyAttr(entry, raw) {
|
|
173
|
+
if (declType(entry.decl) === 'forward') {
|
|
174
|
+
// Relocate off the layout-transparent host (no duplicate id/name), but
|
|
175
|
+
// only adopt the attribute's value when no explicit prop pinned it. A
|
|
176
|
+
// null `raw` here (absent OR already-relocated) is a NO-OP: the seed
|
|
177
|
+
// and attributeChangedCallback must not clobber an adopted value. The
|
|
178
|
+
// explicit unpin path (in _setProp) handles clearing.
|
|
179
|
+
if (raw !== null) {
|
|
180
|
+
if (!this._pinned.has(entry.key)) {
|
|
181
|
+
this._propsProxy.setProperty(entry.key, raw);
|
|
182
|
+
}
|
|
183
|
+
this._relocating = true;
|
|
184
|
+
this.removeAttribute(entry.attrName);
|
|
185
|
+
this._relocating = false;
|
|
186
|
+
}
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (this._pinned.has(entry.key))
|
|
190
|
+
return; // explicit prop wins
|
|
191
|
+
this._propsProxy.setProperty(entry.key, resolveAttrValue(entry.decl, raw));
|
|
192
|
+
}
|
|
193
|
+
/** Seed initial prop values from current attributes (incl. defaults). */
|
|
194
|
+
_seedAttrs() {
|
|
195
|
+
for (const entry of attrEntries.values()) {
|
|
196
|
+
this._applyAttr(entry, this.getAttribute(entry.attrName));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
attributeChangedCallback(name, _old, next) {
|
|
200
|
+
if (this._relocating)
|
|
201
|
+
return;
|
|
202
|
+
const entry = attrEntries.get(name);
|
|
203
|
+
if (entry)
|
|
204
|
+
this._applyAttr(entry, next);
|
|
205
|
+
}
|
|
106
206
|
connectedCallback() {
|
|
107
207
|
if (this._mounted)
|
|
108
208
|
return; // guard against re-connection
|
|
@@ -116,8 +216,27 @@ export function component(tagName, setup, options) {
|
|
|
116
216
|
untrack(() => {
|
|
117
217
|
const host = new ComponentHostImpl(this);
|
|
118
218
|
this._host = host;
|
|
219
|
+
// Canonical pre-setup order: SEED → CAPTURE → CONTEXT (then setup).
|
|
220
|
+
//
|
|
221
|
+
// SEED (ADR 0025 item 3): write prop signals from current
|
|
222
|
+
// attributes (incl. declared defaults and 'forward' relocation) so setup
|
|
223
|
+
// sees correct initial values. No-op when no attrs are declared.
|
|
224
|
+
if (attrEntries.size)
|
|
225
|
+
this._seedAttrs();
|
|
226
|
+
// CAPTURE (ADR 0025 item 1): snapshot the host's light-DOM
|
|
227
|
+
// children so children() can project them. Snapshot only — children()
|
|
228
|
+
// removes/projects on demand — so non-projecting components are
|
|
229
|
+
// untouched. Zero-cost when the host has no light DOM.
|
|
230
|
+
if (this.childNodes.length) {
|
|
231
|
+
this.__capturedChildren =
|
|
232
|
+
Array.from(this.childNodes);
|
|
233
|
+
}
|
|
119
234
|
try {
|
|
235
|
+
// CONTEXT is established by runWithContext(host, …) below; setup then
|
|
236
|
+
// runs with seed + capture already in place.
|
|
120
237
|
runWithContext(host, () => {
|
|
238
|
+
// The Proxy is runtime-untyped; the declared narrowing (A) is a
|
|
239
|
+
// compile-time view the setup function requested (ADR 0025 (b)).
|
|
121
240
|
this._templateResult = setup(this._propsProxy.props, this);
|
|
122
241
|
});
|
|
123
242
|
// Mount the template result
|
|
@@ -151,22 +270,91 @@ export function component(tagName, setup, options) {
|
|
|
151
270
|
});
|
|
152
271
|
}
|
|
153
272
|
disconnectedCallback() {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
273
|
+
// A same-tick remove+reinsert is a MOVE, not a removal: per WHATWG,
|
|
274
|
+
// append-based moves fire disconnected+connected (only moveBefore()
|
|
275
|
+
// preserves state). Moves happen routinely inside the framework —
|
|
276
|
+
// each() keyed reorders, light-DOM projection of nested components —
|
|
277
|
+
// and re-running setup on them duplicates rendered output and loses
|
|
278
|
+
// state. Defer teardown one microtask and skip it if the element is
|
|
279
|
+
// connected again; connectedCallback's _mounted guard then makes the
|
|
280
|
+
// whole move a no-op. True removals still dispose, one microtask
|
|
281
|
+
// later. See ADR 0023.
|
|
282
|
+
if (this._teardownScheduled)
|
|
283
|
+
return;
|
|
284
|
+
this._teardownScheduled = true;
|
|
285
|
+
queueMicrotask(() => {
|
|
286
|
+
this._teardownScheduled = false;
|
|
287
|
+
if (this.isConnected)
|
|
288
|
+
return;
|
|
289
|
+
this._mounted = false;
|
|
290
|
+
if (this._templateResult?.dispose) {
|
|
291
|
+
this._templateResult.dispose();
|
|
292
|
+
}
|
|
293
|
+
if (this._host) {
|
|
294
|
+
this._host.dispose();
|
|
295
|
+
this._host = null;
|
|
296
|
+
}
|
|
297
|
+
});
|
|
162
298
|
}
|
|
163
299
|
/**
|
|
164
300
|
* Set a prop value. Called by the factory and by direct property assignment.
|
|
165
301
|
* The Proxy intercepts and creates/updates backing signals.
|
|
302
|
+
*
|
|
303
|
+
* Precedence = DEFINED-write-pins (ADR 0025 item 3): a defined
|
|
304
|
+
* value pins the key so a declared attribute no longer overwrites it. An
|
|
305
|
+
* explicit `undefined` (e.g. a factory spreading an unset optional prop —
|
|
306
|
+
* `{...opts}` fires _setProp(key, undefined) per the Object.entries walk)
|
|
307
|
+
* must NOT pin; it falls back to the declared attribute/default, matching
|
|
308
|
+
* attr()'s coalesce. For a declared attribute, that fallback re-resolves
|
|
309
|
+
* from the current attribute, keeping declared-default booleans
|
|
310
|
+
* non-undefined.
|
|
166
311
|
*/
|
|
167
312
|
_setProp(key, value) {
|
|
313
|
+
if (value === undefined) {
|
|
314
|
+
this._pinned.delete(key);
|
|
315
|
+
const entry = attrEntriesByKey.get(key);
|
|
316
|
+
if (entry) {
|
|
317
|
+
const raw = this.getAttribute(entry.attrName);
|
|
318
|
+
// A 'forward' attribute is removed from the host on adoption, so an
|
|
319
|
+
// unpin can't re-read it — resolve the absent value directly to CLEAR
|
|
320
|
+
// a previously pinned id/name (rev audit fix). _applyAttr's forward
|
|
321
|
+
// branch deliberately no-ops on absent (so the seed/attr callback
|
|
322
|
+
// never clobber an adopted value); the explicit unpin does not.
|
|
323
|
+
if (raw === null && declType(entry.decl) === 'forward') {
|
|
324
|
+
this._propsProxy?.setProperty(key, resolveAttrValue(entry.decl, null));
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
this._applyAttr(entry, raw);
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
this._pinned.add(key);
|
|
334
|
+
}
|
|
168
335
|
this._propsProxy?.setProperty(key, value);
|
|
169
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Read a prop's backing signal (framework-internal). Used by children()
|
|
339
|
+
* to fold the factory `children` prop into the projection slot (ADR 0025
|
|
340
|
+
* item 1) without a new public read API.
|
|
341
|
+
*/
|
|
342
|
+
_propSignal(key) {
|
|
343
|
+
return this._propsProxy.props[key];
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Whether a prop is currently pinned by a defined factory/property write
|
|
347
|
+
* (framework-internal, like _propSignal). The attribute-as-truth open-state
|
|
348
|
+
* pattern needs this as its controlled-mode discriminator: a declared
|
|
349
|
+
* 'boolean' prop is never undefined (absent → false), so pin state is the
|
|
350
|
+
* ONLY way a component can tell "parent drives this" from "the attribute
|
|
351
|
+
* drives this" — e.g. setOpen() must not write the open attribute while a
|
|
352
|
+
* controlled parent has it pinned, or the DOM attribute diverges from the
|
|
353
|
+
* pinned state until the next prop write.
|
|
354
|
+
*/
|
|
355
|
+
_isPinned(key) {
|
|
356
|
+
return this._pinned.has(key);
|
|
357
|
+
}
|
|
170
358
|
}
|
|
171
359
|
// Register the custom element (if not already registered)
|
|
172
360
|
if (!customElements.get(tagName)) {
|
package/dist/component.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* element-context.ts — subtree-scoped context (provide / inject).
|
|
3
|
+
*
|
|
4
|
+
* The DOM-native equivalent of React/Radix context: a provider publishes a
|
|
5
|
+
* typed value on its host element, and descendant components `inject()` it by
|
|
6
|
+
* walking up the element tree. It replaces the userland `host.__uiX = state` +
|
|
7
|
+
* `host.closest('ui-x')` convention (stringly-typed, invisible to TypeScript,
|
|
8
|
+
* re-implemented per family) with an identity-keyed, end-to-end-typed primitive.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* interface TabsState { value: ReadonlySignal<string>; setValue(v: string): void }
|
|
12
|
+
* const TabsContext = createContext<TabsState>('Tabs');
|
|
13
|
+
*
|
|
14
|
+
* // provider setup:
|
|
15
|
+
* TabsContext.provide(host, state);
|
|
16
|
+
*
|
|
17
|
+
* // descendant setup:
|
|
18
|
+
* const tabs = TabsContext.inject(); // throws (error boundary) if absent
|
|
19
|
+
* const maybe = TabsContext.inject.optional(); // TabsState | undefined
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Design (see ADR 0025 §2):
|
|
23
|
+
*
|
|
24
|
+
* - **Typed, no string keys.** Each `createContext` mints a private `Symbol`
|
|
25
|
+
* used as the storage key; consumers reference the context object, never a
|
|
26
|
+
* string. Two contexts never collide even with the same `name` (name is for
|
|
27
|
+
* diagnostics only).
|
|
28
|
+
*
|
|
29
|
+
* - **Capture at setup, not at lookup.** `inject()` resolves during component
|
|
30
|
+
* setup, while the injecting host is still a DOM descendant of its provider.
|
|
31
|
+
* It returns the value *once*; because provider values carry signals,
|
|
32
|
+
* reactivity flows through them with no further tree-walks. This is what makes
|
|
33
|
+
* it **portal-safe**: after a subtree is reparented to `<body>` (dialog, menu,
|
|
34
|
+
* …) the injected value is already held, so the component keeps resolving its
|
|
35
|
+
* ORIGINAL provider — a later walk from the portaled host would find nothing.
|
|
36
|
+
* `inject()` therefore requires an active setup context when no host is passed.
|
|
37
|
+
*
|
|
38
|
+
* - **Zero cost for non-users.** Providing sets one symbol property on the host;
|
|
39
|
+
* injecting is a `parentElement` walk. Components that use neither pay nothing,
|
|
40
|
+
* and there is no global registry to maintain.
|
|
41
|
+
*/
|
|
42
|
+
export interface Inject<T> {
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the nearest provider's value by walking up from `host` (default:
|
|
45
|
+
* the current component's host, requiring a setup context). Throws if no
|
|
46
|
+
* provider is found — in a component this surfaces via the error boundary.
|
|
47
|
+
*/
|
|
48
|
+
(host?: HTMLElement): T;
|
|
49
|
+
/** Like `inject()` but returns `undefined` instead of throwing when absent. */
|
|
50
|
+
optional(host?: HTMLElement): T | undefined;
|
|
51
|
+
}
|
|
52
|
+
export interface Context<T> {
|
|
53
|
+
/** Diagnostic label (error messages); not an identity key. */
|
|
54
|
+
readonly name: string;
|
|
55
|
+
/** Publish `value` on `host` so descendants can `inject()` it. */
|
|
56
|
+
provide(host: HTMLElement, value: T): void;
|
|
57
|
+
/** Resolve this context from a descendant (see {@link Inject}). */
|
|
58
|
+
readonly inject: Inject<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Read the value provided on THIS host only — no ancestor walk. `undefined`
|
|
61
|
+
* if `host` is not a provider of this context. The low-level primitive for
|
|
62
|
+
* bespoke walks (e.g. "nearest provider of context A OR context B", which
|
|
63
|
+
* `inject` can't express in one pass); prefer `inject`/`inject.optional`
|
|
64
|
+
* for ordinary descendant resolution.
|
|
65
|
+
*/
|
|
66
|
+
peek(host: HTMLElement): T | undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create a subtree-scoped context. `name` is used only in diagnostics; the
|
|
70
|
+
* context's identity (a private symbol) is what keys storage and lookup.
|
|
71
|
+
*
|
|
72
|
+
* Pass `{ providerTag }` to name the provider element so a missing-provider
|
|
73
|
+
* `inject()` produces an ACTIONABLE, element-language error —
|
|
74
|
+
* `<injecting-tag> must be used inside <provider-tag>.` — instead of naming the
|
|
75
|
+
* private context object. Set it whenever consumers are DOM elements (the whole
|
|
76
|
+
* registry): it's the difference between a message a plain-HTML user can act on
|
|
77
|
+
* and one they can't.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createContext<T>(name: string, options?: {
|
|
80
|
+
providerTag?: string;
|
|
81
|
+
}): Context<T>;
|