@usenagi/core 0.3.0 → 0.4.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.ja.md CHANGED
@@ -32,9 +32,9 @@ GSAP、Lenis、IntersectionObserver などを `setup()` で初期化し、`useUn
32
32
  // counter.ts
33
33
  import { create, signal, useWatch, useDomRef } from "@usenagi/core";
34
34
 
35
- const { component } = create();
35
+ const app = create();
36
36
 
37
- component({
37
+ app.component({
38
38
  name: "counter",
39
39
  setup() {
40
40
  const { refs } = useDomRef<{
@@ -71,13 +71,14 @@ npm i @usenagi/core
71
71
  ### First component
72
72
 
73
73
  ```ts
74
- import { create, defineComponent, signal, useWatch, useDomRef } from "@usenagi/core";
74
+ import { create, defineComponent, propTypes, signal, useWatch, useDomRef } from "@usenagi/core";
75
75
 
76
76
  const Greeting = defineComponent({
77
77
  name: "greeting",
78
+ props: propTypes<{ name: string }>(),
78
79
  setup(el, props) {
79
80
  const { refs } = useDomRef<{ message: HTMLParagraphElement }>();
80
- const text = signal((props.name as string) ?? "world");
81
+ const text = signal(props.name ?? "world");
81
82
 
82
83
  useWatch(text, (v) => {
83
84
  refs.message.textContent = `Hello, ${v}!`;
@@ -118,6 +119,13 @@ app.component(Analytics, { when: idle() })(el);
118
119
 
119
120
  ## API
120
121
 
122
+ ### Component Definition
123
+
124
+ | API | 説明 |
125
+ | ---------------------- | ---------------------------------------------------------------- |
126
+ | `defineComponent(opts)` | 型安全な `ComponentSetup` 定義ヘルパー |
127
+ | `propTypes<T>()` | コンポーネント props の型マーカー(ランタイムコストゼロ) |
128
+
121
129
  ### Reactivity
122
130
 
123
131
  | API | 説明 |
@@ -174,7 +182,7 @@ setup(el) {
174
182
  | API | 説明 |
175
183
  | --------------------------------- | ----------------------------------------------------------- |
176
184
  | `useIntersectionWatch(cb, opts?)` | IntersectionObserver のラッパー。unmount 時に自動で切断する |
177
- | `useMediaQuery(query)` | `matchMedia` の結果を `ReadonlySignal<boolean>` で返す |
185
+ | `useMediaQuery(query, cb)` | query 一致時に callback を実行し、`matchesQuery` `ReadonlySignal<boolean>` で返す |
178
186
 
179
187
  ### Addons
180
188
 
@@ -205,8 +213,7 @@ import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
205
213
 
206
214
  | API | 説明 |
207
215
  | --- | --- |
208
- | `schedulerAddon(opts?)` | 遅延 mount 用 addon(内部で `createScheduler` を使用) |
209
- | `createScheduler(opts?)` | カスタム Scheduler 実装用の low-level API |
216
+ | `schedulerAddon(opts?)` | 遅延 mount 用 addon |
210
217
  | `visible(opts?)` | 要素が viewport に入ったときに解決する Cue |
211
218
  | `idle(timeout?)` | `requestIdleCallback` で解決する Cue |
212
219
  | `interaction(events?)` | 最初のユーザー操作で解決する Cue |
package/README.md CHANGED
@@ -32,9 +32,9 @@ You are free to implement `[data-component]` scanning, manifests, lazy imports,
32
32
  // counter.ts
33
33
  import { create, signal, useWatch, useDomRef } from "@usenagi/core";
34
34
 
35
- const { component } = create();
35
+ const app = create();
36
36
 
37
- component({
37
+ app.component({
38
38
  name: "counter",
39
39
  setup() {
40
40
  const { refs } = useDomRef<{
@@ -71,13 +71,14 @@ npm i @usenagi/core
71
71
  ### First component
72
72
 
73
73
  ```ts
74
- import { create, defineComponent, signal, useWatch, useDomRef } from "@usenagi/core";
74
+ import { create, defineComponent, propTypes, signal, useWatch, useDomRef } from "@usenagi/core";
75
75
 
76
76
  const Greeting = defineComponent({
77
77
  name: "greeting",
78
+ props: propTypes<{ name: string }>(),
78
79
  setup(el, props) {
79
80
  const { refs } = useDomRef<{ message: HTMLParagraphElement }>();
80
- const text = signal((props.name as string) ?? "world");
81
+ const text = signal(props.name ?? "world");
81
82
 
82
83
  useWatch(text, (v) => {
83
84
  refs.message.textContent = `Hello, ${v}!`;
@@ -118,6 +119,13 @@ An example of automatic mounting by combining `[data-component]` scanning, manif
118
119
 
119
120
  ## API
120
121
 
122
+ ### Component Definition
123
+
124
+ | API | Description |
125
+ | ---------------------- | --------------------------------------------------------------------------- |
126
+ | `defineComponent(opts)` | Type-safe helper to define a `ComponentSetup` object |
127
+ | `propTypes<T>()` | Type-only marker for declaring component props shape (zero runtime cost) |
128
+
121
129
  ### Reactivity
122
130
 
123
131
  | API | Description |
@@ -174,7 +182,7 @@ You can mount child components with `useSlot()`. You can pass values from parent
174
182
  | API | Description |
175
183
  | --------------------------------- | ------------------------------------------------------------------- |
176
184
  | `useIntersectionWatch(cb, opts?)` | IntersectionObserver wrapper; automatically disconnected on unmount |
177
- | `useMediaQuery(query)` | Returns `matchMedia` result as a `ReadonlySignal<boolean>` |
185
+ | `useMediaQuery(query, cb)` | Runs `callback` when the query matches; returns `matchesQuery` as `ReadonlySignal<boolean>` |
178
186
 
179
187
  ### Addons
180
188
 
@@ -205,8 +213,7 @@ import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
205
213
 
206
214
  | API | Description |
207
215
  | --- | --- |
208
- | `schedulerAddon(opts?)` | Addon for deferred mount (uses `createScheduler` internally) |
209
- | `createScheduler(opts?)` | Low-level API for custom Scheduler implementations |
216
+ | `schedulerAddon(opts?)` | Addon for deferred mount |
210
217
  | `visible(opts?)` | A Cue that resolves when the element enters the viewport |
211
218
  | `idle(timeout?)` | A Cue that resolves via `requestIdleCallback` |
212
219
  | `interaction(events?)` | A Cue that resolves on the first user interaction |
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e}function t(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function n(){let e=new Map;return{add(t){let n=e.get(t);n&&n.abort();let r=new AbortController;return e.set(t,r),{signal:r.signal,complete(){return e.get(t)!==r||r.signal.aborted?!1:(e.delete(t),!0)},abort(){e.get(t)===r&&(r.abort(),e.delete(t))}}},abort(t){let n=e.get(t);n&&(n.abort(),e.delete(t))}}}function r(e,n,r){if(r?.aborted)return;let{scheduler:a}=globalThis;if(typeof a?.postTask==`function`){a.postTask(e,{priority:n,signal:r}).catch(e=>{t(e)||queueMicrotask(()=>{throw e})});return}i(e,n,r)}function i(e,t,n){function r(){n?.aborted||e()}function i(e,t){let r=e();n?.addEventListener(`abort`,()=>t(r),{once:!0})}switch(t){case`user-blocking`:queueMicrotask(r);break;case`user-visible`:i(()=>requestAnimationFrame(r),cancelAnimationFrame);break;case`background`:typeof requestIdleCallback==`function`?i(()=>requestIdleCallback(r),cancelIdleCallback):i(()=>setTimeout(r,0),clearTimeout);break}}function a(e={}){let t=e.priority??`user-visible`;return{schedule(e,n={}){r(e,n.priority??t,n.signal)}}}function o(r){return e({name:`@usenagi/scheduler`,install(e){let i=a(r),o=n();e.addMountMiddleware((e,n,r)=>(n,a)=>{let s=o.add(n),c=()=>{i.schedule(()=>{s.complete()&&e(n,a)},{priority:r.priority,signal:s.signal})},{when:l}=r;l?l(n,s.signal).then(()=>{s.signal.aborted||c()},e=>{t(e)||(s.abort(),queueMicrotask(()=>{throw e}))}):c()}),e.addUnmountMiddleware(e=>t=>{t.forEach(o.abort),e(t)})}})}exports.createScheduler=a,exports.schedulerAddon=o;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e}function t(){let e=new Map;return{add(t){let n=e.get(t);n&&n.abort();let r=new AbortController;return e.set(t,r),{signal:r.signal,complete(){return e.get(t)!==r||r.signal.aborted?!1:(e.delete(t),!0)},abort(){e.get(t)===r&&(r.abort(),e.delete(t))}}},abort(t){let n=e.get(t);n&&(n.abort(),e.delete(t))}}}function n(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function r(e,t,r){if(r?.aborted)return;let{scheduler:a}=globalThis;if(typeof a?.postTask==`function`){a.postTask(e,{priority:t,signal:r}).catch(e=>{n(e)||queueMicrotask(()=>{throw e})});return}i(e,t,r)}function i(e,t,n){function r(){n?.aborted||e()}function i(e,t){let r=e();n?.addEventListener(`abort`,()=>t(r),{once:!0})}switch(t){case`user-blocking`:queueMicrotask(r);break;case`user-visible`:i(()=>requestAnimationFrame(r),cancelAnimationFrame);break;case`background`:typeof requestIdleCallback==`function`?i(()=>requestIdleCallback(r),cancelIdleCallback):i(()=>setTimeout(r,0),clearTimeout);break}}function a(e={}){let t=e.priority??`user-visible`;return{schedule(e,n={}){r(e,n.priority??t,n.signal)}}}function o(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function s(n){return e({name:`@usenagi/scheduler`,install(e){let r=a(n),i=t();e.addMountMiddleware((e,t,n)=>(t,a)=>{let s=i.add(t),c=()=>{r.schedule(()=>{s.complete()&&e(t,a)},{priority:n.priority,signal:s.signal})},{when:l}=n;l?l(t,s.signal).then(()=>{s.signal.aborted||c()},e=>{o(e)||(s.abort(),queueMicrotask(()=>{throw e}))}):c()}),e.addUnmountMiddleware(e=>t=>{t.forEach(i.abort),e(t)})}})}exports.schedulerAddon=s;
@@ -3,13 +3,8 @@ function e(e) {
3
3
  return e;
4
4
  }
5
5
  //#endregion
6
- //#region lib/utils/isAbortError.ts
7
- function t(e) {
8
- return (e instanceof DOMException || e instanceof Error) && e.name === "AbortError";
9
- }
10
- //#endregion
11
- //#region lib/addons/scheduler/pending.ts
12
- function n() {
6
+ //#region lib/addons/scheduler/_internal/pending.ts
7
+ function t() {
13
8
  let e = /* @__PURE__ */ new Map();
14
9
  return {
15
10
  add(t) {
@@ -33,22 +28,25 @@ function n() {
33
28
  };
34
29
  }
35
30
  //#endregion
36
- //#region lib/addons/scheduler/task.ts
37
- function r(e, n, r) {
31
+ //#region lib/addons/scheduler/_internal/schedule.ts
32
+ function n(e) {
33
+ return (e instanceof DOMException || e instanceof Error) && e.name === "AbortError";
34
+ }
35
+ function r(e, t, r) {
38
36
  if (r?.aborted) return;
39
37
  let { scheduler: a } = globalThis;
40
38
  if (typeof a?.postTask == "function") {
41
39
  a.postTask(e, {
42
- priority: n,
40
+ priority: t,
43
41
  signal: r
44
42
  }).catch((e) => {
45
- t(e) || queueMicrotask(() => {
43
+ n(e) || queueMicrotask(() => {
46
44
  throw e;
47
45
  });
48
46
  });
49
47
  return;
50
48
  }
51
- i(e, n, r);
49
+ i(e, t, r);
52
50
  }
53
51
  function i(e, t, n) {
54
52
  function r() {
@@ -70,8 +68,6 @@ function i(e, t, n) {
70
68
  break;
71
69
  }
72
70
  }
73
- //#endregion
74
- //#region lib/addons/scheduler/scheduler.ts
75
71
  function a(e = {}) {
76
72
  let t = e.priority ?? "user-visible";
77
73
  return { schedule(e, n = {}) {
@@ -79,33 +75,36 @@ function a(e = {}) {
79
75
  } };
80
76
  }
81
77
  //#endregion
82
- //#region lib/addons/scheduler/addon.ts
83
- function o(r) {
78
+ //#region lib/addons/scheduler/index.ts
79
+ function o(e) {
80
+ return (e instanceof DOMException || e instanceof Error) && e.name === "AbortError";
81
+ }
82
+ function s(n) {
84
83
  return e({
85
84
  name: "@usenagi/scheduler",
86
85
  install(e) {
87
- let i = a(r), o = n();
88
- e.addMountMiddleware((e, n, r) => (n, a) => {
89
- let s = o.add(n), c = () => {
90
- i.schedule(() => {
91
- s.complete() && e(n, a);
86
+ let r = a(n), i = t();
87
+ e.addMountMiddleware((e, t, n) => (t, a) => {
88
+ let s = i.add(t), c = () => {
89
+ r.schedule(() => {
90
+ s.complete() && e(t, a);
92
91
  }, {
93
- priority: r.priority,
92
+ priority: n.priority,
94
93
  signal: s.signal
95
94
  });
96
- }, { when: l } = r;
97
- l ? l(n, s.signal).then(() => {
95
+ }, { when: l } = n;
96
+ l ? l(t, s.signal).then(() => {
98
97
  s.signal.aborted || c();
99
98
  }, (e) => {
100
- t(e) || (s.abort(), queueMicrotask(() => {
99
+ o(e) || (s.abort(), queueMicrotask(() => {
101
100
  throw e;
102
101
  }));
103
102
  }) : c();
104
103
  }), e.addUnmountMiddleware((e) => (t) => {
105
- t.forEach(o.abort), e(t);
104
+ t.forEach(i.abort), e(t);
106
105
  });
107
106
  }
108
107
  });
109
108
  }
110
109
  //#endregion
111
- export { a as createScheduler, o as schedulerAddon };
110
+ export { s as schedulerAddon };
package/dist/main.es.js CHANGED
@@ -1,5 +1,10 @@
1
1
  //#region lib/core/addon.ts
2
- function e() {
2
+ function e(e) {
3
+ return e;
4
+ }
5
+ //#endregion
6
+ //#region lib/core/_internal/addonRegistry.ts
7
+ function t() {
3
8
  let e = /* @__PURE__ */ new Set(), t = [], n = [], r = [], i = {
4
9
  get installedAddons() {
5
10
  return e;
@@ -29,9 +34,6 @@ function e() {
29
34
  };
30
35
  return i;
31
36
  }
32
- function t(e) {
33
- return e;
34
- }
35
37
  //#endregion
36
38
  //#region lib/core/error.ts
37
39
  function n(e) {
@@ -62,7 +64,7 @@ function i(e) {
62
64
  return e instanceof r;
63
65
  }
64
66
  //#endregion
65
- //#region lib/core/internal/registry.ts
67
+ //#region lib/core/_internal/registry.ts
66
68
  var a = /* @__PURE__ */ new WeakMap();
67
69
  function o(e, t) {
68
70
  let n = a.get(e);
@@ -70,10 +72,10 @@ function o(e, t) {
70
72
  a.set(e, t);
71
73
  }
72
74
  //#endregion
73
- //#region lib/core/component.ts
75
+ //#region lib/core/_internal/component.ts
74
76
  var s = /* @__PURE__ */ function(e) {
75
77
  return e.MOUNTED = "Mounted", e.UNMOUNTED = "Unmounted", e;
76
- }({}), c = 0, l = class {
78
+ }(s || {}), c = 0, l = class {
77
79
  Mounted = [];
78
80
  Unmounted = [];
79
81
  parent = null;
@@ -121,67 +123,93 @@ var s = /* @__PURE__ */ function(e) {
121
123
  get childElements() {
122
124
  return this.#e.map((e) => e.element);
123
125
  }
124
- };
125
- function u(e) {
126
- return e;
127
- }
128
- //#endregion
129
- //#region lib/core/runtime.ts
130
- var d;
131
- function f(e) {
132
- if (!d) throw Error(`"${e}" called outside setup() will never be run.`);
133
- return d;
126
+ }, u;
127
+ function d(e) {
128
+ if (!u) throw Error(`"${e}" called outside setup() will never be run.`);
129
+ return u;
134
130
  }
135
- function p(e, t, n = {}) {
136
- let a = new l(t, e.name), o = d;
137
- d = a;
131
+ function f(e, t, n = {}) {
132
+ let a = new l(t, e.name), o = u;
133
+ u = a;
138
134
  try {
139
135
  o && (a.parent = o), a.props = n, a.current = e.setup(t, n) || {};
140
136
  } catch (e) {
141
- throw d = o, i(e) ? e : r.create("setup", a, e, o, { props: a.props });
137
+ throw u = o, i(e) ? e : r.create("setup", a, e, o, { props: a.props });
142
138
  }
143
- return d = o, a;
139
+ return u = o, a;
144
140
  }
145
141
  //#endregion
146
142
  //#region lib/core/app.ts
147
- function m() {
148
- let t = e(), n = (e) => {
143
+ function p() {
144
+ let e = t(), n = (e) => {
149
145
  for (let t of e) {
150
146
  let e = a.get(t);
151
147
  e && (e.onUnmount(), a.delete(t));
152
148
  }
153
149
  }, r = {
154
- install(...e) {
155
- return e.forEach(t.install), r;
150
+ install(...t) {
151
+ return t.forEach(e.install), r;
156
152
  },
157
- component(e, n = {}) {
158
- let r = t.composeComponent(e), i = t.composeMount((e, t) => {
159
- let n = p(r, e, t);
153
+ component(t, n = {}) {
154
+ let r = e.composeComponent(t), i = e.composeMount((e, t) => {
155
+ let n = f(r, e, t);
160
156
  return o(e, n), n.onMount(), n;
161
157
  }, r, n);
162
158
  return (e, t = {}) => i(e, t);
163
159
  },
164
- unmount(e) {
165
- t.composeUnmount(n)(e);
160
+ unmount(t) {
161
+ e.composeUnmount(n)(t);
166
162
  }
167
163
  };
168
164
  return r;
169
165
  }
170
166
  //#endregion
167
+ //#region lib/core/component.ts
168
+ function m(e) {
169
+ return e;
170
+ }
171
+ //#endregion
172
+ //#region lib/core/context.ts
173
+ function h() {
174
+ let e = Symbol();
175
+ return [{ _id: e }, () => {
176
+ let t = d("createContext.use");
177
+ for (; t !== null;) {
178
+ if (t.provides.has(e)) return t.provides.get(e);
179
+ t = t.parent;
180
+ }
181
+ throw Error("createContext.use: no provider found");
182
+ }];
183
+ }
184
+ function g(e, t) {
185
+ return (n) => ({
186
+ name: n.name,
187
+ setup(r, i) {
188
+ return d(`withContext.${n.name}`).provides.set(e._id, t), n.setup(r, i);
189
+ }
190
+ });
191
+ }
192
+ //#endregion
171
193
  //#region lib/core/lifecycle.ts
172
- function h(e) {
194
+ function _(e) {
173
195
  return (t) => {
174
- f(e)[e].push(t);
196
+ d(e)[e].push(t);
175
197
  };
176
198
  }
177
- var g = h(s.MOUNTED), _ = h(s.UNMOUNTED), v = Symbol("watch"), y = null, b = class {
199
+ var v = _(s.MOUNTED), y = _(s.UNMOUNTED);
200
+ //#endregion
201
+ //#region lib/core/props.ts
202
+ function b() {}
203
+ //#endregion
204
+ //#region lib/core/reactivity.ts
205
+ var x = Symbol("watch"), S = null, C = class {
178
206
  #e;
179
207
  #t = /* @__PURE__ */ new Set();
180
208
  constructor(e) {
181
209
  this.#e = e;
182
210
  }
183
211
  get value() {
184
- return y !== null && y.add(this), this.#e;
212
+ return S !== null && S.add(this), this.#e;
185
213
  }
186
214
  set value(e) {
187
215
  if (Object.is(e, this.#e)) return;
@@ -189,12 +217,12 @@ var g = h(s.MOUNTED), _ = h(s.UNMOUNTED), v = Symbol("watch"), y = null, b = cla
189
217
  this.#e = e;
190
218
  for (let n of Array.from(this.#t)) n(e, t);
191
219
  }
192
- [v](e) {
220
+ [x](e) {
193
221
  return this.#t.add(e), () => {
194
222
  this.#t.delete(e);
195
223
  };
196
224
  }
197
- }, x = (e) => new b(e), S = class {
225
+ }, w = (e) => new C(e), T = class {
198
226
  #e;
199
227
  constructor(e) {
200
228
  this.#e = e;
@@ -202,75 +230,54 @@ var g = h(s.MOUNTED), _ = h(s.UNMOUNTED), v = Symbol("watch"), y = null, b = cla
202
230
  get value() {
203
231
  return this.#e.value;
204
232
  }
205
- [v](e) {
206
- return this.#e[v](e);
233
+ [x](e) {
234
+ return this.#e[x](e);
207
235
  }
208
- }, C = (e) => new S(e);
209
- function w(e, t) {
210
- return e[v](t);
236
+ }, E = (e) => new T(e);
237
+ function D(e, t) {
238
+ return e[x](t);
211
239
  }
212
- function T(e, t) {
213
- _(w(e, t));
240
+ function O(e, t) {
241
+ y(D(e, t));
214
242
  }
215
- function E(e) {
216
- let t = x(void 0), n = [], r = () => {
243
+ function k(e) {
244
+ let t = w(void 0), n = [], r = () => {
217
245
  n.forEach((e) => {
218
246
  e();
219
247
  }), n = [];
220
248
  }, i = () => {
221
249
  r();
222
- let a = y, o = /* @__PURE__ */ new Set();
223
- y = o;
250
+ let a = S, o = /* @__PURE__ */ new Set();
251
+ S = o;
224
252
  let s;
225
253
  try {
226
254
  s = e();
227
255
  } finally {
228
- y = a;
256
+ S = a;
229
257
  }
230
258
  t.value = s;
231
- for (let e of o) n.push(e[v](() => {
259
+ for (let e of o) n.push(e[x](() => {
232
260
  i();
233
261
  }));
234
262
  };
235
- return i(), _(r), C(t);
236
- }
237
- //#endregion
238
- //#region lib/hooks/createContext.ts
239
- function D() {
240
- let e = Symbol();
241
- return [{ _id: e }, () => {
242
- let t = f("createContext.use");
243
- for (; t !== null;) {
244
- if (t.provides.has(e)) return t.provides.get(e);
245
- t = t.parent;
246
- }
247
- throw Error("createContext.use: no provider found");
248
- }];
249
- }
250
- function O(e, t) {
251
- return (n) => ({
252
- name: n.name,
253
- setup(r, i) {
254
- return f(`withContext.${n.name}`).provides.set(e._id, t), n.setup(r, i);
255
- }
256
- });
263
+ return i(), y(r), E(t);
257
264
  }
258
265
  //#endregion
259
- //#region lib/hooks/domRefs.ts
260
- function k(e, t) {
266
+ //#region lib/hooks/core/useDomRef.ts
267
+ function A(e, t) {
261
268
  return t.some((t) => t !== e && t.contains(e));
262
269
  }
263
- function A(e, t, n) {
264
- let r = `[data-ref="${CSS.escape(e)}"]`, i = Array.from(t.querySelectorAll(r)).filter((e) => !k(e, n));
270
+ function j(e, t, n) {
271
+ let r = `[data-ref="${CSS.escape(e)}"]`, i = Array.from(t.querySelectorAll(r)).filter((e) => !A(e, n));
265
272
  return i.length === 0 ? null : i.length === 1 ? i[0] : i;
266
273
  }
267
- function j(e, t) {
274
+ function M(e, t) {
268
275
  let n = /* @__PURE__ */ new Map();
269
276
  return new Proxy({}, {
270
277
  get(r, i) {
271
278
  if (typeof i == "symbol" || i === "then") return;
272
279
  if (n.has(i)) return n.get(i);
273
- let a = A(i, e, t());
280
+ let a = j(i, e, t());
274
281
  return n.set(i, a), a;
275
282
  },
276
283
  has(e, t) {
@@ -288,22 +295,43 @@ function j(e, t) {
288
295
  }
289
296
  });
290
297
  }
298
+ function N() {
299
+ let e = d("useDomRef");
300
+ return { refs: M(e.element, () => e.childElements) };
301
+ }
291
302
  //#endregion
292
- //#region lib/hooks/useDomRef.ts
293
- function M() {
294
- let e = f("useDomRef");
295
- return { refs: j(e.element, () => e.childElements) };
303
+ //#region lib/hooks/core/useSlot.ts
304
+ function P() {
305
+ let e = d("useSlot");
306
+ return {
307
+ addChild(t, n, r) {
308
+ let i = (t) => {
309
+ let i = f(n, t, r);
310
+ return e.addChild(i), i;
311
+ };
312
+ return Array.isArray(t) ? t.map((e) => i(e)) : [i(t)];
313
+ },
314
+ removeChild(t) {
315
+ t.forEach((t) => {
316
+ try {
317
+ e.removeChild(t);
318
+ } catch (n) {
319
+ console.error("[nagi] removeChild failed", r.create("removeChild", t, n, e));
320
+ }
321
+ });
322
+ }
323
+ };
296
324
  }
297
325
  //#endregion
298
326
  //#region lib/hooks/useEvent.ts
299
- function N(e, t, n, r) {
300
- g(() => (e.addEventListener(t, n, r), () => {
327
+ function F(e, t, n, r) {
328
+ v(() => (e.addEventListener(t, n, r), () => {
301
329
  e.removeEventListener(t, n, r);
302
330
  }));
303
331
  }
304
332
  //#endregion
305
333
  //#region lib/hooks/useIntersectionWatch.ts
306
- function P(e, t, n = {
334
+ function I(e, t, n = {
307
335
  rootMargin: "0px",
308
336
  threshold: .1
309
337
  }) {
@@ -313,9 +341,9 @@ function P(e, t, n = {
313
341
  r.observe(e);
314
342
  }) : r.observe(e);
315
343
  }
316
- i(e), _(() => {
344
+ v(() => (i(e), () => {
317
345
  r.disconnect();
318
- });
346
+ }));
319
347
  function a(e) {
320
348
  r.unobserve(e);
321
349
  }
@@ -323,40 +351,14 @@ function P(e, t, n = {
323
351
  }
324
352
  //#endregion
325
353
  //#region lib/hooks/useMediaQuery.ts
326
- function F(e, t) {
327
- let n = window.matchMedia(e), r = x(n.matches), i = null;
354
+ function L(e, t) {
355
+ let n = window.matchMedia(e), r = w(n.matches), i = null;
328
356
  function a(e) {
329
357
  r.value = e.matches, e.matches ? i = t() : (i?.(), i = null);
330
358
  }
331
- return g(() => (n.addEventListener("change", a), n.matches && (i = t()), () => {
359
+ return v(() => (n.addEventListener("change", a), n.matches && (i = t()), () => {
332
360
  i?.(), n.removeEventListener("change", a);
333
- })), { matchesQuery: C(r) };
334
- }
335
- //#endregion
336
- //#region lib/hooks/useSlot.ts
337
- function I() {
338
- let e = f("useSlot");
339
- return {
340
- addChild(t, n, r) {
341
- let i = (t) => {
342
- let i = p(n, t, r);
343
- return e.addChild(i), i;
344
- };
345
- return Array.isArray(t) ? t.map((e) => i(e)) : [i(t)];
346
- },
347
- removeChild(t) {
348
- t.forEach((t) => {
349
- try {
350
- e.removeChild(t);
351
- } catch (n) {
352
- console.error("[nagi] removeChild failed", r.create("removeChild", t, n, e));
353
- }
354
- });
355
- }
356
- };
361
+ })), { matchesQuery: E(r) };
357
362
  }
358
363
  //#endregion
359
- //#region lib/props.ts
360
- function L() {}
361
- //#endregion
362
- export { r as LifecycleError, m as create, D as createContext, t as defineAddon, u as defineComponent, i as isLifecycleError, L as propTypes, C as readonly, x as signal, E as useComputed, M as useDomRef, N as useEvent, P as useIntersectionWatch, F as useMediaQuery, g as useMount, I as useSlot, _ as useUnmount, T as useWatch, O as withContext };
364
+ export { r as LifecycleError, p as create, h as createContext, e as defineAddon, m as defineComponent, i as isLifecycleError, b as propTypes, E as readonly, w as signal, k as useComputed, N as useDomRef, F as useEvent, I as useIntersectionWatch, L as useMediaQuery, v as useMount, P as useSlot, y as useUnmount, O as useWatch, g as withContext };
package/dist/main.umd.js CHANGED
@@ -1 +1 @@
1
- (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Lake={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(){let e=new Set,t=[],n=[],r=[],i={get installedAddons(){return e},addComponentMiddleware(e){t.push(e)},addMountMiddleware(e){n.push(e)},addUnmountMiddleware(e){r.push(e)},composeComponent(e){return t.reduce((e,t)=>t(e),e)},composeMount(e,t,r){return n.reduce((e,n)=>n(e,t,r),e)},composeUnmount(e){return r.reduce((e,t)=>t(e),e)},install(t){if(e.has(t.name))throw Error(`[nagi] addon "${t.name}" is already installed`);t.install(i),e.add(t.name)}};return i}function n(e){return e}function r(e){let t=[],n=e;for(;n;)t.unshift(n.name),n=n.parent;return t.join(` > `)}var i=class e extends Error{details;constructor(e){super(`[nagi] Component error in phase "${e.phase}" for "${e.name}"${e.path?` (${e.path})`:``}`,{cause:e.cause}),this.name=`LifecycleError`,this.details=e}static create(t,n,i,a=n.parent,o){return new e({phase:t,name:n.name,uid:n.uid,path:r(n),parentName:a?.name,parentUid:a?.uid,element:n.element,cause:i,...o})}};function a(e){return e instanceof i}var o=new WeakMap;function s(e,t){let n=o.get(e);if(n)throw i.create(`mount`,t,Error(`Component "${n.name}" (${n.uid}) is already mounted on this element`),n);o.set(e,t)}var c=function(e){return e.MOUNTED=`Mounted`,e.UNMOUNTED=`Unmounted`,e}({}),l=0,u=class{Mounted=[];Unmounted=[];parent=null;#e=[];uid;name;current={};props={};element;provides=new Map;constructor(e,t){this.uid=`${t}.${l++}`,this.name=t,this.element=e}onMount=()=>{let e=[];for(let t of this.Mounted)try{let n=t();typeof n==`function`&&e.push(n)}catch(e){console.error(`[nagi] onMount hook failed`,i.create(`mount`,this,e))}this.Unmounted.push(...e)};onUnmount=()=>{for(let e of this.Unmounted)try{e()}catch(e){console.error(`[nagi] onUnmount cleanup failed`,i.create(`unmount`,this,e))}for(let e of this.#e)e.onUnmount()};addChild=e=>{this.#e.push(e),e.parent=this;try{e.onMount()}catch(t){let n=this.#e.indexOf(e);throw n!==-1&&this.#e.splice(n,1),e.parent=null,t}};removeChild=e=>{let t=this.#e.indexOf(e);t!==-1&&(this.#e.splice(t,1),e.parent=null,e.onUnmount())};get childElements(){return this.#e.map(e=>e.element)}};function d(e){return e}var f;function p(e){if(!f)throw Error(`"${e}" called outside setup() will never be run.`);return f}function m(e,t,n={}){let r=new u(t,e.name),o=f;f=r;try{o&&(r.parent=o),r.props=n,r.current=e.setup(t,n)||{}}catch(e){throw f=o,a(e)?e:i.create(`setup`,r,e,o,{props:r.props})}return f=o,r}function h(){let e=t(),n=e=>{for(let t of e){let e=o.get(t);e&&(e.onUnmount(),o.delete(t))}},r={install(...t){return t.forEach(e.install),r},component(t,n={}){let r=e.composeComponent(t),i=e.composeMount((e,t)=>{let n=m(r,e,t);return s(e,n),n.onMount(),n},r,n);return(e,t={})=>i(e,t)},unmount(t){e.composeUnmount(n)(t)}};return r}function g(e){return t=>{p(e)[e].push(t)}}var _=g(c.MOUNTED),v=g(c.UNMOUNTED),y=Symbol(`watch`),b=null,x=class{#e;#t=new Set;constructor(e){this.#e=e}get value(){return b!==null&&b.add(this),this.#e}set value(e){if(Object.is(e,this.#e))return;let t=this.#e;this.#e=e;for(let n of Array.from(this.#t))n(e,t)}[y](e){return this.#t.add(e),()=>{this.#t.delete(e)}}},S=e=>new x(e),C=class{#e;constructor(e){this.#e=e}get value(){return this.#e.value}[y](e){return this.#e[y](e)}},w=e=>new C(e);function T(e,t){return e[y](t)}function E(e,t){v(T(e,t))}function D(e){let t=S(void 0),n=[],r=()=>{n.forEach(e=>{e()}),n=[]},i=()=>{r();let a=b,o=new Set;b=o;let s;try{s=e()}finally{b=a}t.value=s;for(let e of o)n.push(e[y](()=>{i()}))};return i(),v(r),w(t)}function O(){let e=Symbol();return[{_id:e},()=>{let t=p(`createContext.use`);for(;t!==null;){if(t.provides.has(e))return t.provides.get(e);t=t.parent}throw Error(`createContext.use: no provider found`)}]}function k(e,t){return n=>({name:n.name,setup(r,i){return p(`withContext.${n.name}`).provides.set(e._id,t),n.setup(r,i)}})}function A(e,t){return t.some(t=>t!==e&&t.contains(e))}function j(e,t,n){let r=`[data-ref="${CSS.escape(e)}"]`,i=Array.from(t.querySelectorAll(r)).filter(e=>!A(e,n));return i.length===0?null:i.length===1?i[0]:i}function M(e,t){let n=new Map;return new Proxy({},{get(r,i){if(typeof i==`symbol`||i===`then`)return;if(n.has(i))return n.get(i);let a=j(i,e,t());return n.set(i,a),a},has(e,t){return typeof t==`string`},ownKeys(){return[]},getOwnPropertyDescriptor(){},set(){return!1},deleteProperty(){return!1}})}function N(){let e=p(`useDomRef`);return{refs:M(e.element,()=>e.childElements)}}function P(e,t,n,r){_(()=>(e.addEventListener(t,n,r),()=>{e.removeEventListener(t,n,r)}))}function F(e,t,n={rootMargin:`0px`,threshold:.1}){let r=new IntersectionObserver(t,n);function i(e){Array.isArray(e)?e.forEach(e=>{r.observe(e)}):r.observe(e)}i(e),v(()=>{r.disconnect()});function a(e){r.unobserve(e)}return{unwatch:a}}function I(e,t){let n=window.matchMedia(e),r=S(n.matches),i=null;function a(e){r.value=e.matches,e.matches?i=t():(i?.(),i=null)}return _(()=>(n.addEventListener(`change`,a),n.matches&&(i=t()),()=>{i?.(),n.removeEventListener(`change`,a)})),{matchesQuery:w(r)}}function L(){let e=p(`useSlot`);return{addChild(t,n,r){let i=t=>{let i=m(n,t,r);return e.addChild(i),i};return Array.isArray(t)?t.map(e=>i(e)):[i(t)]},removeChild(t){t.forEach(t=>{try{e.removeChild(t)}catch(n){console.error(`[nagi] removeChild failed`,i.create(`removeChild`,t,n,e))}})}}}function R(){}e.LifecycleError=i,e.create=h,e.createContext=O,e.defineAddon=n,e.defineComponent=d,e.isLifecycleError=a,e.propTypes=R,e.readonly=w,e.signal=S,e.useComputed=D,e.useDomRef=N,e.useEvent=P,e.useIntersectionWatch=F,e.useMediaQuery=I,e.useMount=_,e.useSlot=L,e.useUnmount=v,e.useWatch=E,e.withContext=k});
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.Nagi={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(e){return e}function n(){let e=new Set,t=[],n=[],r=[],i={get installedAddons(){return e},addComponentMiddleware(e){t.push(e)},addMountMiddleware(e){n.push(e)},addUnmountMiddleware(e){r.push(e)},composeComponent(e){return t.reduce((e,t)=>t(e),e)},composeMount(e,t,r){return n.reduce((e,n)=>n(e,t,r),e)},composeUnmount(e){return r.reduce((e,t)=>t(e),e)},install(t){if(e.has(t.name))throw Error(`[nagi] addon "${t.name}" is already installed`);t.install(i),e.add(t.name)}};return i}function r(e){let t=[],n=e;for(;n;)t.unshift(n.name),n=n.parent;return t.join(` > `)}var i=class e extends Error{details;constructor(e){super(`[nagi] Component error in phase "${e.phase}" for "${e.name}"${e.path?` (${e.path})`:``}`,{cause:e.cause}),this.name=`LifecycleError`,this.details=e}static create(t,n,i,a=n.parent,o){return new e({phase:t,name:n.name,uid:n.uid,path:r(n),parentName:a?.name,parentUid:a?.uid,element:n.element,cause:i,...o})}};function a(e){return e instanceof i}var o=new WeakMap;function s(e,t){let n=o.get(e);if(n)throw i.create(`mount`,t,Error(`Component "${n.name}" (${n.uid}) is already mounted on this element`),n);o.set(e,t)}var c=function(e){return e.MOUNTED=`Mounted`,e.UNMOUNTED=`Unmounted`,e}(c||{}),l=0,u=class{Mounted=[];Unmounted=[];parent=null;#e=[];uid;name;current={};props={};element;provides=new Map;constructor(e,t){this.uid=`${t}.${l++}`,this.name=t,this.element=e}onMount=()=>{let e=[];for(let t of this.Mounted)try{let n=t();typeof n==`function`&&e.push(n)}catch(e){console.error(`[nagi] onMount hook failed`,i.create(`mount`,this,e))}this.Unmounted.push(...e)};onUnmount=()=>{for(let e of this.Unmounted)try{e()}catch(e){console.error(`[nagi] onUnmount cleanup failed`,i.create(`unmount`,this,e))}for(let e of this.#e)e.onUnmount()};addChild=e=>{this.#e.push(e),e.parent=this;try{e.onMount()}catch(t){let n=this.#e.indexOf(e);throw n!==-1&&this.#e.splice(n,1),e.parent=null,t}};removeChild=e=>{let t=this.#e.indexOf(e);t!==-1&&(this.#e.splice(t,1),e.parent=null,e.onUnmount())};get childElements(){return this.#e.map(e=>e.element)}},d;function f(e){if(!d)throw Error(`"${e}" called outside setup() will never be run.`);return d}function p(e,t,n={}){let r=new u(t,e.name),o=d;d=r;try{o&&(r.parent=o),r.props=n,r.current=e.setup(t,n)||{}}catch(e){throw d=o,a(e)?e:i.create(`setup`,r,e,o,{props:r.props})}return d=o,r}function m(){let e=n(),t=e=>{for(let t of e){let e=o.get(t);e&&(e.onUnmount(),o.delete(t))}},r={install(...t){return t.forEach(e.install),r},component(t,n={}){let r=e.composeComponent(t),i=e.composeMount((e,t)=>{let n=p(r,e,t);return s(e,n),n.onMount(),n},r,n);return(e,t={})=>i(e,t)},unmount(n){e.composeUnmount(t)(n)}};return r}function h(e){return e}function g(){let e=Symbol();return[{_id:e},()=>{let t=f(`createContext.use`);for(;t!==null;){if(t.provides.has(e))return t.provides.get(e);t=t.parent}throw Error(`createContext.use: no provider found`)}]}function _(e,t){return n=>({name:n.name,setup(r,i){return f(`withContext.${n.name}`).provides.set(e._id,t),n.setup(r,i)}})}function v(e){return t=>{f(e)[e].push(t)}}var y=v(c.MOUNTED),b=v(c.UNMOUNTED);function x(){}var S=Symbol(`watch`),C=null,w=class{#e;#t=new Set;constructor(e){this.#e=e}get value(){return C!==null&&C.add(this),this.#e}set value(e){if(Object.is(e,this.#e))return;let t=this.#e;this.#e=e;for(let n of Array.from(this.#t))n(e,t)}[S](e){return this.#t.add(e),()=>{this.#t.delete(e)}}},T=e=>new w(e),E=class{#e;constructor(e){this.#e=e}get value(){return this.#e.value}[S](e){return this.#e[S](e)}},D=e=>new E(e);function O(e,t){return e[S](t)}function k(e,t){b(O(e,t))}function A(e){let t=T(void 0),n=[],r=()=>{n.forEach(e=>{e()}),n=[]},i=()=>{r();let a=C,o=new Set;C=o;let s;try{s=e()}finally{C=a}t.value=s;for(let e of o)n.push(e[S](()=>{i()}))};return i(),b(r),D(t)}function j(e,t){return t.some(t=>t!==e&&t.contains(e))}function M(e,t,n){let r=`[data-ref="${CSS.escape(e)}"]`,i=Array.from(t.querySelectorAll(r)).filter(e=>!j(e,n));return i.length===0?null:i.length===1?i[0]:i}function N(e,t){let n=new Map;return new Proxy({},{get(r,i){if(typeof i==`symbol`||i===`then`)return;if(n.has(i))return n.get(i);let a=M(i,e,t());return n.set(i,a),a},has(e,t){return typeof t==`string`},ownKeys(){return[]},getOwnPropertyDescriptor(){},set(){return!1},deleteProperty(){return!1}})}function P(){let e=f(`useDomRef`);return{refs:N(e.element,()=>e.childElements)}}function F(){let e=f(`useSlot`);return{addChild(t,n,r){let i=t=>{let i=p(n,t,r);return e.addChild(i),i};return Array.isArray(t)?t.map(e=>i(e)):[i(t)]},removeChild(t){t.forEach(t=>{try{e.removeChild(t)}catch(n){console.error(`[nagi] removeChild failed`,i.create(`removeChild`,t,n,e))}})}}}function I(e,t,n,r){y(()=>(e.addEventListener(t,n,r),()=>{e.removeEventListener(t,n,r)}))}function L(e,t,n={rootMargin:`0px`,threshold:.1}){let r=new IntersectionObserver(t,n);function i(e){Array.isArray(e)?e.forEach(e=>{r.observe(e)}):r.observe(e)}y(()=>(i(e),()=>{r.disconnect()}));function a(e){r.unobserve(e)}return{unwatch:a}}function R(e,t){let n=window.matchMedia(e),r=T(n.matches),i=null;function a(e){r.value=e.matches,e.matches?i=t():(i?.(),i=null)}return y(()=>(n.addEventListener(`change`,a),n.matches&&(i=t()),()=>{i?.(),n.removeEventListener(`change`,a)})),{matchesQuery:D(r)}}e.LifecycleError=i,e.create=m,e.createContext=g,e.defineAddon=t,e.defineComponent=h,e.isLifecycleError=a,e.propTypes=x,e.readonly=D,e.signal=T,e.useComputed=A,e.useDomRef=P,e.useEvent=I,e.useIntersectionWatch=L,e.useMediaQuery=R,e.useMount=y,e.useSlot=F,e.useUnmount=b,e.useWatch=k,e.withContext=_});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usenagi/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Composition-API ergonomics for vanilla DOM. Bring your own mounter.",
5
5
  "main": "./dist/main.umd.js",
6
6
  "module": "./dist/main.es.js",
@@ -61,10 +61,10 @@
61
61
  "devDependencies": {
62
62
  "@biomejs/biome": "^2.4.13",
63
63
  "happy-dom": "^20.9.0",
64
- "oxlint": "^1.61.0",
64
+ "oxlint": "^1.66.0",
65
65
  "typescript": "^6.0.3",
66
- "vite": "^8.0.10",
67
- "vitest": "^4.1.5"
66
+ "vite": "^8.0.14",
67
+ "vitest": "^4.1.7"
68
68
  },
69
69
  "type": "module",
70
70
  "sideEffects": false
@@ -0,0 +1,11 @@
1
+ import type { RefElement } from "../../../types";
2
+ type PendingMounts = {
3
+ add(el: RefElement): {
4
+ readonly signal: AbortSignal;
5
+ complete(): boolean;
6
+ abort(): void;
7
+ };
8
+ abort(el: RefElement): void;
9
+ };
10
+ declare function createPendingMounts(): PendingMounts;
11
+ export {};
@@ -0,0 +1,11 @@
1
+ import type { SchedulePriority } from "../../../types";
2
+ type Scheduler = {
3
+ schedule(task: () => void, options?: {
4
+ priority?: SchedulePriority;
5
+ signal?: AbortSignal;
6
+ }): void;
7
+ };
8
+ declare function createScheduler(opts?: {
9
+ priority?: SchedulePriority;
10
+ }): Scheduler;
11
+ export {};
@@ -1,2 +1,10 @@
1
- export { schedulerAddon } from "./addon";
2
- export { createScheduler } from "./scheduler";
1
+ import type { Cue, SchedulePriority } from "../../types";
2
+ declare module "../../core/addon" {
3
+ interface MountOptions {
4
+ priority?: SchedulePriority;
5
+ when?: Cue;
6
+ }
7
+ }
8
+ export declare function schedulerAddon(opts?: {
9
+ priority?: SchedulePriority;
10
+ }): import("../../main").Addon;
@@ -0,0 +1,10 @@
1
+ import type { ComponentSetup } from "../../types";
2
+ import type { Addon, AddonContext, MountFn, MountOptions, UnmountFn } from "../addon";
3
+ type AddonRegistry = AddonContext & {
4
+ composeComponent<S extends ComponentSetup>(setup: S): S;
5
+ composeMount(mountFn: MountFn, setup: ComponentSetup, opts: MountOptions): MountFn;
6
+ composeUnmount(unmountFn: UnmountFn): UnmountFn;
7
+ install(addon: Addon): void;
8
+ };
9
+ declare function createAddonRegistry(): AddonRegistry;
10
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { ComponentContext, ComponentSetup, ExposedSetup, RefElement } from "../../types";
2
+ declare enum LifecycleHooks {
3
+ MOUNTED = "Mounted",
4
+ UNMOUNTED = "Unmounted"
5
+ }
6
+ declare class ComponentContextImpl<T = any> implements ComponentContext<ExposedSetup<T>> {
7
+ #private;
8
+ private [LifecycleHooks.MOUNTED];
9
+ private [LifecycleHooks.UNMOUNTED];
10
+ parent: ComponentContextImpl | null;
11
+ readonly uid: string;
12
+ readonly name: ComponentContext["name"];
13
+ current: ExposedSetup<T>;
14
+ props: Parameters<ComponentSetup<T>["setup"]>[1];
15
+ element: ComponentContext["element"];
16
+ provides: Map<symbol, unknown>;
17
+ constructor(element: RefElement, name: string);
18
+ onMount: () => void;
19
+ onUnmount: () => void;
20
+ addChild: (child: ComponentContextImpl) => void;
21
+ removeChild: (child: ComponentContextImpl) => void;
22
+ get childElements(): RefElement[];
23
+ }
24
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { RefElement } from "../../types";
2
+ import type { ComponentContextImpl } from "./component";
3
+ declare const DOM_COMPONENT_INSTANCE: WeakMap<RefElement, ComponentContextImpl<any>>;
4
+ declare function bindDOMNodeToComponent(el: RefElement, component: ComponentContextImpl): void;
5
+ export {};
@@ -20,13 +20,6 @@ export type AddonContext = {
20
20
  addMountMiddleware(middleware: MountMiddleware): void;
21
21
  addUnmountMiddleware(middleware: UnmountMiddleware): void;
22
22
  };
23
- type AddonRegistry = AddonContext & {
24
- composeComponent<S extends ComponentSetup>(setup: S): S;
25
- composeMount(mountFn: MountFn, setup: ComponentSetup, opts: MountOptions): MountFn;
26
- composeUnmount(unmountFn: UnmountFn): UnmountFn;
27
- install(addon: Addon): void;
28
- };
29
- export declare function createAddonRegistry(): AddonRegistry;
30
23
  /**
31
24
  * Identity helper for type inference only — no runtime effect.
32
25
  */
@@ -1,9 +1,8 @@
1
- import type { ComponentSetup, RefElement } from "../types";
1
+ import type { ComponentContext, ComponentSetup, ExposedSetup, RefElement } from "../types";
2
2
  import type { Addon, MountOptions } from "./addon";
3
- import type { ComponentContext } from "./component";
4
3
  type App = {
5
4
  install(...addons: Addon[]): App;
6
- component<S extends ComponentSetup>(component: S, opts?: MountOptions): (el: RefElement, props?: Record<string, any>) => ComponentContext<ReturnType<S["setup"]>> | void;
5
+ component<S extends ComponentSetup>(component: S, opts?: MountOptions): (el: RefElement, props?: Record<string, any>) => ComponentContext<ExposedSetup<ReturnType<S["setup"]>>> | void;
7
6
  unmount(targets: RefElement[]): void;
8
7
  };
9
8
  export declare function create(): App;
@@ -1,26 +1,4 @@
1
1
  import type { ComponentProps, ComponentSetup, RefElement } from "../types";
2
- export declare enum LifecycleHooks {
3
- MOUNTED = "Mounted",
4
- UNMOUNTED = "Unmounted"
5
- }
6
- export declare class ComponentContext<T = any> {
7
- #private;
8
- private [LifecycleHooks.MOUNTED];
9
- private [LifecycleHooks.UNMOUNTED];
10
- parent: ComponentContext<T> | null;
11
- readonly uid: string;
12
- readonly name: string;
13
- current: ReturnType<ComponentSetup<T>["setup"]>;
14
- props: Parameters<ComponentSetup<T>["setup"]>[1];
15
- element: RefElement;
16
- provides: Map<symbol, unknown>;
17
- constructor(element: RefElement, name: string);
18
- onMount: () => void;
19
- onUnmount: () => void;
20
- addChild: (child: ComponentContext) => void;
21
- removeChild: (child: ComponentContext) => void;
22
- get childElements(): RefElement[];
23
- }
24
2
  export declare function defineComponent<SetupResult extends Record<string, unknown> | void, Props extends Record<string, unknown>>(opts: {
25
3
  name: string;
26
4
  props: Props;
@@ -1,5 +1,5 @@
1
1
  import type { RefElement } from "../types";
2
- import type { ComponentContext } from "./component";
2
+ import type { ComponentContextImpl } from "./_internal/component";
3
3
  export type LifecycleErrorDetails = {
4
4
  phase: "setup" | "mount" | "unmount" | "removeChild";
5
5
  name: string;
@@ -11,10 +11,9 @@ export type LifecycleErrorDetails = {
11
11
  props?: unknown;
12
12
  cause: unknown;
13
13
  };
14
- export declare function traceComponentTree(context: ComponentContext): string;
15
14
  export declare class LifecycleError extends Error {
16
15
  readonly details: LifecycleErrorDetails;
17
16
  constructor(details: LifecycleErrorDetails);
18
- static create(phase: LifecycleErrorDetails["phase"], target: ComponentContext, cause: unknown, parent?: ComponentContext | null | undefined, extra?: Partial<LifecycleErrorDetails>): LifecycleError;
17
+ static create(phase: LifecycleErrorDetails["phase"], target: ComponentContextImpl, cause: unknown, parent?: ComponentContextImpl | null | undefined, extra?: Partial<LifecycleErrorDetails>): LifecycleError;
19
18
  }
20
19
  export declare function isLifecycleError(error: unknown): error is LifecycleError;
@@ -1,4 +1,5 @@
1
- import { ComponentContext } from "./component";
1
+ import { ComponentContextImpl } from "./_internal/component";
2
2
  import type { ComponentSetup, RefElement } from "../types";
3
- export declare function getCurrentComponent(hookName: string): ComponentContext;
4
- export declare function createComponent(wrap: ComponentSetup, root: RefElement, props?: Record<string, any>): ComponentContext<any>;
3
+ declare function getCurrentComponent(hookName: string): ComponentContextImpl;
4
+ declare function createComponent<S extends ComponentSetup>(wrap: S, root: RefElement, props?: Record<string, any>): ComponentContextImpl<ReturnType<S["setup"]>>;
5
+ export {};
@@ -1,4 +1,4 @@
1
- import type { RefElement } from "../types";
1
+ import type { RefElement } from "../../types";
2
2
  export declare function useDomRef<T extends Record<string, RefElement | RefElement[] | null>>(): {
3
3
  refs: T;
4
4
  };
@@ -1,6 +1,5 @@
1
- import type { ComponentContext } from "../core/component";
2
- import type { ComponentSetup, RefElement } from "../types";
1
+ import type { ComponentContext, ComponentSetup, ExposedSetup, RefElement } from "../../types";
3
2
  export declare function useSlot(): {
4
- addChild<Child extends ComponentSetup>(targetOrTargets: RefElement | RefElement[], child: Child, props?: Partial<Parameters<Child["setup"]>[1]>): ComponentContext<ReturnType<Child["setup"]>>[];
3
+ addChild<Child extends ComponentSetup>(targetOrTargets: RefElement | RefElement[], child: Child, props?: Partial<Parameters<Child["setup"]>[1]>): ComponentContext<ExposedSetup<ReturnType<Child["setup"]>>>[];
5
4
  removeChild(children: ComponentContext[]): void;
6
5
  };
package/types/main.d.ts CHANGED
@@ -1,19 +1,18 @@
1
1
  export { defineAddon } from "./core/addon";
2
2
  export { create } from "./core/app";
3
3
  export { defineComponent } from "./core/component";
4
+ export { createContext, withContext } from "./core/context";
4
5
  export { isLifecycleError, LifecycleError } from "./core/error";
5
6
  export { useMount, useUnmount } from "./core/lifecycle";
7
+ export { propTypes } from "./core/props";
6
8
  export { readonly, signal, useComputed, useWatch } from "./core/reactivity";
7
- export { createContext, withContext } from "./hooks/createContext";
8
- export { useDomRef } from "./hooks/useDomRef";
9
+ export { useDomRef } from "./hooks/core/useDomRef";
10
+ export { useSlot } from "./hooks/core/useSlot";
9
11
  export { useEvent } from "./hooks/useEvent";
10
12
  export { useIntersectionWatch } from "./hooks/useIntersectionWatch";
11
13
  export { useMediaQuery } from "./hooks/useMediaQuery";
12
- export { useSlot } from "./hooks/useSlot";
13
- export { propTypes } from "./props";
14
- export type { Addon, AddonContext, ComponentMiddleware, MountFn, MountMiddleware, MountOptions, UnmountFn, UnmountMiddleware, } from "./core/addon";
15
- export type { ComponentContext } from "./core/component";
14
+ export type { Addon, AddonContext, MountOptions } from "./core/addon";
15
+ export type { Provider } from "./core/context";
16
16
  export type { LifecycleErrorDetails } from "./core/error";
17
17
  export type { ReadonlySignal, Signal } from "./core/reactivity";
18
- export type { Provider } from "./hooks/createContext";
19
- export type { ComponentSetup, Cue, IComponent, RefElement, SchedulePriority, Scheduler, } from "./types";
18
+ export type { Cleanup, ComponentContext, ComponentSetup, Cue, RefElement, SchedulePriority, } from "./types";
package/types/types.d.ts CHANGED
@@ -1,18 +1,20 @@
1
1
  export type RefElement = HTMLElement | SVGElement;
2
2
  export type ComponentProps<Props> = Readonly<Props>;
3
+ type IsAny<T> = 0 extends 1 & T ? true : false;
4
+ /** Normalize the return value of setup to the type stored in `current` (void / undefined → empty object). */
5
+ export type ExposedSetup<T> = IsAny<T> extends true ? Record<string, unknown> : [T] extends [void | undefined] ? Record<string, never> : T extends Record<string, unknown> ? T : Record<string, never>;
3
6
  export type ComponentSetup<SetupResult = void | Record<string, unknown>, Props extends Record<string, unknown> = Record<string, unknown>> = {
4
7
  name: string;
5
8
  setup(el: RefElement, props: ComponentProps<Props>): SetupResult;
6
9
  };
7
- /** @deprecated Use `ComponentSetup` instead. */
8
- export type IComponent<SetupResult = void | Record<string, unknown>, Props extends Record<string, unknown> = Record<string, unknown>> = ComponentSetup<SetupResult, Props>;
10
+ /** Mounted component instance exposed to app / hook callers. */
11
+ export type ComponentContext<Exposed extends Record<string, unknown> = Record<string, never>> = {
12
+ readonly current: Exposed;
13
+ readonly element: RefElement;
14
+ readonly name: string;
15
+ };
9
16
  export type Cleanup = () => void;
10
17
  export type LifecycleHandler = () => void | Cleanup;
11
18
  export type SchedulePriority = "user-blocking" | "user-visible" | "background";
12
- export type Scheduler = {
13
- schedule(task: () => void, options?: {
14
- priority?: SchedulePriority;
15
- signal?: AbortSignal;
16
- }): void;
17
- };
18
19
  export type Cue = (el: RefElement, signal: AbortSignal) => Promise<void>;
20
+ export {};
@@ -1,10 +0,0 @@
1
- import type { Cue, SchedulePriority } from "../../types";
2
- declare module "../../core/addon" {
3
- interface MountOptions {
4
- priority?: SchedulePriority;
5
- when?: Cue;
6
- }
7
- }
8
- export declare function schedulerAddon(opts?: {
9
- priority?: SchedulePriority;
10
- }): import("../../main").Addon;
@@ -1,11 +0,0 @@
1
- import type { RefElement } from "../../types";
2
- export type PendingMount = {
3
- readonly signal: AbortSignal;
4
- complete(): boolean;
5
- abort(): void;
6
- };
7
- export type PendingMounts = {
8
- add(el: RefElement): PendingMount;
9
- abort(el: RefElement): void;
10
- };
11
- export declare function createPendingMounts(): PendingMounts;
@@ -1,4 +0,0 @@
1
- import type { SchedulePriority, Scheduler } from "../../types";
2
- export declare function createScheduler(opts?: {
3
- priority?: SchedulePriority;
4
- }): Scheduler;
@@ -1,2 +0,0 @@
1
- import type { SchedulePriority } from "../../types";
2
- export declare function scheduleTask(task: () => void, priority: SchedulePriority, signal?: AbortSignal): void;
@@ -1,4 +0,0 @@
1
- import type { RefElement } from "../../types";
2
- import type { ComponentContext } from "../component";
3
- export declare const DOM_COMPONENT_INSTANCE: WeakMap<RefElement, ComponentContext<any>>;
4
- export declare function bindDOMNodeToComponent(el: RefElement, component: ComponentContext): void;
@@ -1,2 +0,0 @@
1
- import type { RefElement } from "../types";
2
- export declare function domRefs<T extends Record<string, RefElement | RefElement[] | null>>(scope: RefElement, getBoundaries: () => RefElement[]): T;
@@ -1 +0,0 @@
1
- export declare function isAbortError(error: unknown): boolean;
File without changes