@usenagi/core 0.2.0 → 0.3.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 +67 -46
- package/README.md +62 -41
- package/dist/addons/scheduler.cjs.js +1 -1
- package/dist/addons/scheduler.es.js +76 -17
- package/dist/main.es.js +55 -65
- package/dist/main.umd.js +1 -1
- package/package.json +1 -1
- package/types/addons/scheduler/addon.d.ts +10 -0
- package/types/addons/scheduler/index.d.ts +2 -4
- package/types/addons/scheduler/pending.d.ts +11 -0
- package/types/addons/scheduler/scheduler.d.ts +4 -0
- package/types/core/addon.d.ts +35 -0
- package/types/core/app.d.ts +6 -23
- package/types/core/component.d.ts +14 -5
- package/types/core/runtime.d.ts +1 -1
- package/types/hooks/useSlot.d.ts +1 -1
- package/types/main.d.ts +3 -0
- package/types/props.d.ts +2 -0
- package/types/types.d.ts +2 -2
- package/types/core/internal/pending.d.ts +0 -11
package/README.ja.md
CHANGED
|
@@ -95,10 +95,10 @@ create().component(Greeting)(document.querySelector("#app")!);
|
|
|
95
95
|
|
|
96
96
|
```ts
|
|
97
97
|
import { create } from "@usenagi/core";
|
|
98
|
-
import {
|
|
98
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
99
99
|
import { visible, idle } from "@usenagi/core/addons/cue";
|
|
100
100
|
|
|
101
|
-
const app = create(
|
|
101
|
+
const app = create().install(schedulerAddon());
|
|
102
102
|
|
|
103
103
|
// mount when the element enters the viewport
|
|
104
104
|
app.component(HeavyWidget, { when: visible() })(el);
|
|
@@ -107,7 +107,7 @@ app.component(HeavyWidget, { when: visible() })(el);
|
|
|
107
107
|
app.component(Analytics, { when: idle() })(el);
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
`when` は `setup()` の前に待機する条件、`priority` は `setup()` を含む mount task の実行タイミングを決める。
|
|
110
|
+
`schedulerAddon()` を使うと、`when` は `setup()` の前に待機する条件、`priority` は `setup()` を含む mount task の実行タイミングを決める。
|
|
111
111
|
|
|
112
112
|
### BYO mounter recipe
|
|
113
113
|
|
|
@@ -120,12 +120,12 @@ app.component(Analytics, { when: idle() })(el);
|
|
|
120
120
|
|
|
121
121
|
### Reactivity
|
|
122
122
|
|
|
123
|
-
| API | 説明
|
|
124
|
-
| ---------------------- |
|
|
125
|
-
| `signal(value)` | `.value` を持つリアクティブな値コンテナを作成する
|
|
126
|
-
| `readonly(signal)` | 書き込み可能な `signal` の読み取り専用ラッパー
|
|
127
|
-
| `useComputed(fn)` | `signal` の依存を自動追跡する派生値
|
|
128
|
-
| `useWatch(target, cb)` | 値変更時に `cb` を呼ぶ。unmount 時に自動で購読解除する
|
|
123
|
+
| API | 説明 |
|
|
124
|
+
| ---------------------- | ------------------------------------------------------ |
|
|
125
|
+
| `signal(value)` | `.value` を持つリアクティブな値コンテナを作成する |
|
|
126
|
+
| `readonly(signal)` | 書き込み可能な `signal` の読み取り専用ラッパー |
|
|
127
|
+
| `useComputed(fn)` | `signal` の依存を自動追跡する派生値 |
|
|
128
|
+
| `useWatch(target, cb)` | 値変更時に `cb` を呼ぶ。unmount 時に自動で購読解除する |
|
|
129
129
|
|
|
130
130
|
```ts
|
|
131
131
|
const width = signal(10);
|
|
@@ -139,10 +139,10 @@ useWatch(area, (v) => {
|
|
|
139
139
|
|
|
140
140
|
### Lifecycle
|
|
141
141
|
|
|
142
|
-
| API | 説明
|
|
143
|
-
| ---------------- |
|
|
144
|
-
| `useMount(fn)` | コンポーネントのマウント完了後に1回実行する
|
|
145
|
-
| `useUnmount(fn)` | unmount 時に実行する。クリーンアップに使う
|
|
142
|
+
| API | 説明 |
|
|
143
|
+
| ---------------- | ------------------------------------------- |
|
|
144
|
+
| `useMount(fn)` | コンポーネントのマウント完了後に1回実行する |
|
|
145
|
+
| `useUnmount(fn)` | unmount 時に実行する。クリーンアップに使う |
|
|
146
146
|
|
|
147
147
|
```ts
|
|
148
148
|
import gsap from 'gsap';
|
|
@@ -157,11 +157,11 @@ setup(el) {
|
|
|
157
157
|
|
|
158
158
|
ルート要素には **`setup(el)`** を、**`[data-ref]`** の子要素には **`useDomRef()`** を使う。
|
|
159
159
|
|
|
160
|
-
| API | 説明
|
|
161
|
-
| ------------------------------ |
|
|
162
|
-
| `useDomRef<T>()` | `[data-ref]` 要素への型付きアクセス
|
|
163
|
-
| `useEvent(el, event, handler)` | イベントリスナーを追加する。unmount 時に自動で除去する
|
|
164
|
-
| `useSlot()` | 子コンポーネントをマウントする。親の unmount に連動する
|
|
160
|
+
| API | 説明 |
|
|
161
|
+
| ------------------------------ | ------------------------------------------------------- |
|
|
162
|
+
| `useDomRef<T>()` | `[data-ref]` 要素への型付きアクセス |
|
|
163
|
+
| `useEvent(el, event, handler)` | イベントリスナーを追加する。unmount 時に自動で除去する |
|
|
164
|
+
| `useSlot()` | 子コンポーネントをマウントする。親の unmount に連動する |
|
|
165
165
|
|
|
166
166
|
### Parent / child
|
|
167
167
|
|
|
@@ -171,39 +171,60 @@ setup(el) {
|
|
|
171
171
|
|
|
172
172
|
### Observers
|
|
173
173
|
|
|
174
|
-
| API | 説明
|
|
175
|
-
| --------------------------------- |
|
|
176
|
-
| `useIntersectionWatch(cb, opts?)` | IntersectionObserver のラッパー。unmount 時に自動で切断する
|
|
177
|
-
| `useMediaQuery(query)` | `matchMedia` の結果を `ReadonlySignal<boolean>` で返す
|
|
174
|
+
| API | 説明 |
|
|
175
|
+
| --------------------------------- | ----------------------------------------------------------- |
|
|
176
|
+
| `useIntersectionWatch(cb, opts?)` | IntersectionObserver のラッパー。unmount 時に自動で切断する |
|
|
177
|
+
| `useMediaQuery(query)` | `matchMedia` の結果を `ReadonlySignal<boolean>` で返す |
|
|
178
178
|
|
|
179
179
|
### Addons
|
|
180
180
|
|
|
181
181
|
```ts
|
|
182
|
-
import {
|
|
182
|
+
import { create, defineAddon } from "@usenagi/core";
|
|
183
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
184
|
+
|
|
185
|
+
const app = create().install(schedulerAddon(), myAddon());
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| API | 説明 |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `defineAddon({ name, install(ctx) })` | addon を定義する(`ctx` は `AddonContext`) |
|
|
191
|
+
| `app.install(...addons)` | app に addon を登録する(複数可) |
|
|
192
|
+
| `ctx.addMountMiddleware` / `addUnmountMiddleware` / `addComponentMiddleware` | mount / unmount / ComponentSetup の middleware を追加する |
|
|
193
|
+
| `ctx.installedAddons` | この app に install 済みの addon 名 |
|
|
194
|
+
|
|
195
|
+
`addMountMiddleware` / `addUnmountMiddleware` / `addComponentMiddleware` は **後から install した addon ほど外側**に適用される(`install(a, b)` なら実行順は `b → a → コア`)。
|
|
196
|
+
|
|
197
|
+
遅延 mount には `schedulerAddon()` が必要。`when` や `priority` を使う場合も同様で、これらの mount option は scheduler addon が解釈する。addon の状態(scheduler / pending)は **各 app の `install` ごと**に作られる。
|
|
198
|
+
|
|
199
|
+
#### Scheduler + cue
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
183
203
|
import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
|
|
184
204
|
```
|
|
185
205
|
|
|
186
|
-
| API
|
|
187
|
-
|
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
206
|
+
| API | 説明 |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| `schedulerAddon(opts?)` | 遅延 mount 用 addon(内部で `createScheduler` を使用) |
|
|
209
|
+
| `createScheduler(opts?)` | カスタム Scheduler 実装用の low-level API |
|
|
210
|
+
| `visible(opts?)` | 要素が viewport に入ったときに解決する Cue |
|
|
211
|
+
| `idle(timeout?)` | `requestIdleCallback` で解決する Cue |
|
|
212
|
+
| `interaction(events?)` | 最初のユーザー操作で解決する Cue |
|
|
213
|
+
| `media(query)` | media query が一致したときに解決する Cue |
|
|
193
214
|
|
|
194
215
|
---
|
|
195
216
|
|
|
196
217
|
## Comparison
|
|
197
218
|
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
| Inline JS in HTML
|
|
201
|
-
| Composition-style setup
|
|
202
|
-
| BYO mounter
|
|
203
|
-
| Async mount cue
|
|
204
|
-
| Lifecycle cleanup
|
|
205
|
-
|
|
|
206
|
-
| Core gzip
|
|
219
|
+
| | **nagi** | Alpine.js | Stimulus | petite-vue |
|
|
220
|
+
| -------------------------- | -------- | --------- | -------- | ---------- |
|
|
221
|
+
| Inline JS in HTML | ✗ | ◯ | ✗ | ◯ |
|
|
222
|
+
| Composition-style setup | ◯ | △ | ✗ | ◯ |
|
|
223
|
+
| BYO mounter | ◯ | △ | △ | △ |
|
|
224
|
+
| Async mount cue | ◯ | ✗ | ✗ | ✗ |
|
|
225
|
+
| Lifecycle cleanup | ◯ | △ | ◯ | △ |
|
|
226
|
+
| computed (derived signals) | ◯ | ◯ | ✗ | ◯ |
|
|
227
|
+
| Core gzip | ~2.5 kB | ~16 kB | ~8 kB | ~6 kB |
|
|
207
228
|
|
|
208
229
|
(◯ = 組み込み、△ = 利用側の実装・規約で対応可能、✗ = 主な機能ではない)
|
|
209
230
|
|
|
@@ -233,13 +254,13 @@ import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
|
|
|
233
254
|
|
|
234
255
|
## Examples
|
|
235
256
|
|
|
236
|
-
| Example | 説明
|
|
237
|
-
| ----------------------------------------------------- |
|
|
238
|
-
| [basic-counter](./examples/basic-counter/) | 最小の `signal` + `useWatch` 例
|
|
239
|
-
| [computed](./examples/computed/) | `useComputed` による派生値(width × height = area)
|
|
240
|
-
| [parent-child](./examples/parent-child/) | `createContext` + `withContext` + `useSlot`
|
|
241
|
-
| [lenis-scroll-scene](./examples/lenis-scroll-scene/) | Lenis + `useComputed` によるスクロール進捗連動
|
|
242
|
-
| [byo-mounter recipe](./examples/recipes/byo-mounter/) | `[data-component]` スキャン + manifest + cue
|
|
257
|
+
| Example | 説明 |
|
|
258
|
+
| ----------------------------------------------------- | --------------------------------------------------- |
|
|
259
|
+
| [basic-counter](./examples/basic-counter/) | 最小の `signal` + `useWatch` 例 |
|
|
260
|
+
| [computed](./examples/computed/) | `useComputed` による派生値(width × height = area) |
|
|
261
|
+
| [parent-child](./examples/parent-child/) | `createContext` + `withContext` + `useSlot` |
|
|
262
|
+
| [lenis-scroll-scene](./examples/lenis-scroll-scene/) | Lenis + `useComputed` によるスクロール進捗連動 |
|
|
263
|
+
| [byo-mounter recipe](./examples/recipes/byo-mounter/) | `[data-component]` スキャン + manifest + cue |
|
|
243
264
|
|
|
244
265
|
---
|
|
245
266
|
|
package/README.md
CHANGED
|
@@ -95,10 +95,10 @@ If delayed mounting is required, add the scheduler / cue addons.
|
|
|
95
95
|
|
|
96
96
|
```ts
|
|
97
97
|
import { create } from "@usenagi/core";
|
|
98
|
-
import {
|
|
98
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
99
99
|
import { visible, idle } from "@usenagi/core/addons/cue";
|
|
100
100
|
|
|
101
|
-
const app = create(
|
|
101
|
+
const app = create().install(schedulerAddon());
|
|
102
102
|
|
|
103
103
|
// mount when the element enters the viewport
|
|
104
104
|
app.component(HeavyWidget, { when: visible() })(el);
|
|
@@ -107,7 +107,7 @@ app.component(HeavyWidget, { when: visible() })(el);
|
|
|
107
107
|
app.component(Analytics, { when: idle() })(el);
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
`when` is a condition to wait for before `setup()`, and `priority` determines the execution timing of the mount task that includes `setup()`.
|
|
110
|
+
With `schedulerAddon()`, `when` is a condition to wait for before `setup()`, and `priority` determines the execution timing of the mount task that includes `setup()`.
|
|
111
111
|
|
|
112
112
|
### BYO mounter recipe
|
|
113
113
|
|
|
@@ -120,10 +120,10 @@ An example of automatic mounting by combining `[data-component]` scanning, manif
|
|
|
120
120
|
|
|
121
121
|
### Reactivity
|
|
122
122
|
|
|
123
|
-
| API | Description
|
|
124
|
-
| ---------------------- |
|
|
125
|
-
| `signal(value)` | Creates a reactive value container (`.value`)
|
|
126
|
-
| `readonly(signal)` | Read-only wrapper around a writable `signal`
|
|
123
|
+
| API | Description |
|
|
124
|
+
| ---------------------- | ----------------------------------------------------------------- |
|
|
125
|
+
| `signal(value)` | Creates a reactive value container (`.value`) |
|
|
126
|
+
| `readonly(signal)` | Read-only wrapper around a writable `signal` |
|
|
127
127
|
| `useComputed(fn)` | Derived value that auto-tracks `signal` dependencies |
|
|
128
128
|
| `useWatch(target, cb)` | Calls `cb` on value change; automatically unsubscribes on unmount |
|
|
129
129
|
|
|
@@ -139,10 +139,10 @@ useWatch(area, (v) => {
|
|
|
139
139
|
|
|
140
140
|
### Lifecycle
|
|
141
141
|
|
|
142
|
-
| API | Description
|
|
143
|
-
| ---------------- |
|
|
144
|
-
| `useMount(fn)` | Runs once after the component mounts
|
|
145
|
-
| `useUnmount(fn)` | Runs on unmount; use for cleanup
|
|
142
|
+
| API | Description |
|
|
143
|
+
| ---------------- | ------------------------------------ |
|
|
144
|
+
| `useMount(fn)` | Runs once after the component mounts |
|
|
145
|
+
| `useUnmount(fn)` | Runs on unmount; use for cleanup |
|
|
146
146
|
|
|
147
147
|
```ts
|
|
148
148
|
import gsap from 'gsap';
|
|
@@ -157,11 +157,11 @@ setup(el) {
|
|
|
157
157
|
|
|
158
158
|
Use **`setup(el)`** for the root element and **`useDomRef()`** for `[data-ref]` descendants.
|
|
159
159
|
|
|
160
|
-
| API | Description
|
|
161
|
-
| ------------------------------ |
|
|
162
|
-
| `useDomRef<T>()` | Typed access to `[data-ref]` elements
|
|
163
|
-
| `useEvent(el, event, handler)` | Adds an event listener; automatically removed on unmount
|
|
164
|
-
| `useSlot()` | Mounts child components; tied to the parent's unmount
|
|
160
|
+
| API | Description |
|
|
161
|
+
| ------------------------------ | -------------------------------------------------------- |
|
|
162
|
+
| `useDomRef<T>()` | Typed access to `[data-ref]` elements |
|
|
163
|
+
| `useEvent(el, event, handler)` | Adds an event listener; automatically removed on unmount |
|
|
164
|
+
| `useSlot()` | Mounts child components; tied to the parent's unmount |
|
|
165
165
|
|
|
166
166
|
### Parent / child
|
|
167
167
|
|
|
@@ -174,36 +174,57 @@ You can mount child components with `useSlot()`. You can pass values from parent
|
|
|
174
174
|
| API | Description |
|
|
175
175
|
| --------------------------------- | ------------------------------------------------------------------- |
|
|
176
176
|
| `useIntersectionWatch(cb, opts?)` | IntersectionObserver wrapper; automatically disconnected on unmount |
|
|
177
|
-
| `useMediaQuery(query)` | Returns `matchMedia` result as a `ReadonlySignal<boolean>`
|
|
177
|
+
| `useMediaQuery(query)` | Returns `matchMedia` result as a `ReadonlySignal<boolean>` |
|
|
178
178
|
|
|
179
179
|
### Addons
|
|
180
180
|
|
|
181
181
|
```ts
|
|
182
|
-
import {
|
|
182
|
+
import { create, defineAddon } from "@usenagi/core";
|
|
183
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
184
|
+
|
|
185
|
+
const app = create().install(schedulerAddon(), myAddon());
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| API | Description |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `defineAddon({ name, install(ctx) })` | Defines an addon (`ctx` is `AddonContext`) |
|
|
191
|
+
| `app.install(...addons)` | Registers one or more addons on the app |
|
|
192
|
+
| `ctx.addMountMiddleware` / `addUnmountMiddleware` / `addComponentMiddleware` | Add mount / unmount / ComponentSetup middleware |
|
|
193
|
+
| `ctx.installedAddons` | Addon names already installed on this app |
|
|
194
|
+
|
|
195
|
+
`addMountMiddleware`, `addUnmountMiddleware`, and `addComponentMiddleware` apply **outermost for addons installed later** (`install(a, b)` runs as `b → a → core`).
|
|
196
|
+
|
|
197
|
+
Deferred mounting requires `schedulerAddon()`. The same applies when using `when` or `priority`; these mount options are interpreted by the scheduler addon. Addon state (scheduler / pending) is created **per app `install`**, not per addon instance.
|
|
198
|
+
|
|
199
|
+
#### Scheduler + cue
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { schedulerAddon } from "@usenagi/core/addons/scheduler";
|
|
183
203
|
import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
|
|
184
204
|
```
|
|
185
205
|
|
|
186
|
-
| API
|
|
187
|
-
|
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
206
|
+
| API | Description |
|
|
207
|
+
| --- | --- |
|
|
208
|
+
| `schedulerAddon(opts?)` | Addon for deferred mount (uses `createScheduler` internally) |
|
|
209
|
+
| `createScheduler(opts?)` | Low-level API for custom Scheduler implementations |
|
|
210
|
+
| `visible(opts?)` | A Cue that resolves when the element enters the viewport |
|
|
211
|
+
| `idle(timeout?)` | A Cue that resolves via `requestIdleCallback` |
|
|
212
|
+
| `interaction(events?)` | A Cue that resolves on the first user interaction |
|
|
213
|
+
| `media(query)` | A Cue that resolves when the media query matches |
|
|
193
214
|
|
|
194
215
|
---
|
|
195
216
|
|
|
196
217
|
## Comparison
|
|
197
218
|
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
| Inline JS in HTML
|
|
201
|
-
| Composition-style setup
|
|
202
|
-
| BYO mounter
|
|
203
|
-
| Async mount cue
|
|
204
|
-
| Lifecycle cleanup
|
|
205
|
-
|
|
|
206
|
-
| Core gzip
|
|
219
|
+
| | **nagi** | Alpine.js | Stimulus | petite-vue |
|
|
220
|
+
| -------------------------- | -------- | --------- | -------- | ---------- |
|
|
221
|
+
| Inline JS in HTML | ✗ | ◯ | ✗ | ◯ |
|
|
222
|
+
| Composition-style setup | ◯ | △ | ✗ | ◯ |
|
|
223
|
+
| BYO mounter | ◯ | △ | △ | △ |
|
|
224
|
+
| Async mount cue | ◯ | ✗ | ✗ | ✗ |
|
|
225
|
+
| Lifecycle cleanup | ◯ | △ | ◯ | △ |
|
|
226
|
+
| computed (derived signals) | ◯ | ◯ | ✗ | ◯ |
|
|
227
|
+
| Core gzip | ~2.5 kB | ~16 kB | ~8 kB | ~6 kB |
|
|
207
228
|
|
|
208
229
|
(◯ = built-in, △ = handled via userland/convention, ✗ = not a primary feature)
|
|
209
230
|
|
|
@@ -233,13 +254,13 @@ import { visible, idle, interaction, media } from "@usenagi/core/addons/cue";
|
|
|
233
254
|
|
|
234
255
|
## Examples
|
|
235
256
|
|
|
236
|
-
| Example | Description
|
|
237
|
-
| ----------------------------------------------------- |
|
|
238
|
-
| [basic-counter](./examples/basic-counter/) | Minimal `signal` + `useWatch` example
|
|
239
|
-
| [computed](./examples/computed/)
|
|
240
|
-
| [parent-child](./examples/parent-child/) | `createContext` + `withContext` + `useSlot`
|
|
241
|
-
| [lenis-scroll-scene](./examples/lenis-scroll-scene/) | Scroll-progress animation with Lenis + `useComputed`
|
|
242
|
-
| [byo-mounter recipe](./examples/recipes/byo-mounter/) | `[data-component]` scanning + manifest + cue
|
|
257
|
+
| Example | Description |
|
|
258
|
+
| ----------------------------------------------------- | -------------------------------------------------------- |
|
|
259
|
+
| [basic-counter](./examples/basic-counter/) | Minimal `signal` + `useWatch` example |
|
|
260
|
+
| [computed](./examples/computed/) | Derived value with `useComputed` (width × height = area) |
|
|
261
|
+
| [parent-child](./examples/parent-child/) | `createContext` + `withContext` + `useSlot` |
|
|
262
|
+
| [lenis-scroll-scene](./examples/lenis-scroll-scene/) | Scroll-progress animation with Lenis + `useComputed` |
|
|
263
|
+
| [byo-mounter recipe](./examples/recipes/byo-mounter/) | `[data-component]` scanning + manifest + cue |
|
|
243
264
|
|
|
244
265
|
---
|
|
245
266
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function t(t,r,
|
|
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,26 +1,56 @@
|
|
|
1
|
-
//#region lib/
|
|
1
|
+
//#region lib/core/addon.ts
|
|
2
2
|
function e(e) {
|
|
3
|
+
return e;
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region lib/utils/isAbortError.ts
|
|
7
|
+
function t(e) {
|
|
3
8
|
return (e instanceof DOMException || e instanceof Error) && e.name === "AbortError";
|
|
4
9
|
}
|
|
5
10
|
//#endregion
|
|
11
|
+
//#region lib/addons/scheduler/pending.ts
|
|
12
|
+
function n() {
|
|
13
|
+
let e = /* @__PURE__ */ new Map();
|
|
14
|
+
return {
|
|
15
|
+
add(t) {
|
|
16
|
+
let n = e.get(t);
|
|
17
|
+
n && n.abort();
|
|
18
|
+
let r = new AbortController();
|
|
19
|
+
return e.set(t, r), {
|
|
20
|
+
signal: r.signal,
|
|
21
|
+
complete() {
|
|
22
|
+
return e.get(t) !== r || r.signal.aborted ? !1 : (e.delete(t), !0);
|
|
23
|
+
},
|
|
24
|
+
abort() {
|
|
25
|
+
e.get(t) === r && (r.abort(), e.delete(t));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
abort(t) {
|
|
30
|
+
let n = e.get(t);
|
|
31
|
+
n && (n.abort(), e.delete(t));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
6
36
|
//#region lib/addons/scheduler/task.ts
|
|
7
|
-
function
|
|
8
|
-
if (
|
|
37
|
+
function r(e, n, r) {
|
|
38
|
+
if (r?.aborted) return;
|
|
9
39
|
let { scheduler: a } = globalThis;
|
|
10
40
|
if (typeof a?.postTask == "function") {
|
|
11
|
-
a.postTask(
|
|
12
|
-
priority:
|
|
13
|
-
signal:
|
|
14
|
-
}).catch((
|
|
15
|
-
e
|
|
16
|
-
throw
|
|
41
|
+
a.postTask(e, {
|
|
42
|
+
priority: n,
|
|
43
|
+
signal: r
|
|
44
|
+
}).catch((e) => {
|
|
45
|
+
t(e) || queueMicrotask(() => {
|
|
46
|
+
throw e;
|
|
17
47
|
});
|
|
18
48
|
});
|
|
19
49
|
return;
|
|
20
50
|
}
|
|
21
|
-
|
|
51
|
+
i(e, n, r);
|
|
22
52
|
}
|
|
23
|
-
function
|
|
53
|
+
function i(e, t, n) {
|
|
24
54
|
function r() {
|
|
25
55
|
n?.aborted || e();
|
|
26
56
|
}
|
|
@@ -41,12 +71,41 @@ function n(e, t, n) {
|
|
|
41
71
|
}
|
|
42
72
|
}
|
|
43
73
|
//#endregion
|
|
44
|
-
//#region lib/addons/scheduler/
|
|
45
|
-
function
|
|
46
|
-
let
|
|
47
|
-
return { schedule(e,
|
|
48
|
-
|
|
74
|
+
//#region lib/addons/scheduler/scheduler.ts
|
|
75
|
+
function a(e = {}) {
|
|
76
|
+
let t = e.priority ?? "user-visible";
|
|
77
|
+
return { schedule(e, n = {}) {
|
|
78
|
+
r(e, n.priority ?? t, n.signal);
|
|
49
79
|
} };
|
|
50
80
|
}
|
|
51
81
|
//#endregion
|
|
52
|
-
|
|
82
|
+
//#region lib/addons/scheduler/addon.ts
|
|
83
|
+
function o(r) {
|
|
84
|
+
return e({
|
|
85
|
+
name: "@usenagi/scheduler",
|
|
86
|
+
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);
|
|
92
|
+
}, {
|
|
93
|
+
priority: r.priority,
|
|
94
|
+
signal: s.signal
|
|
95
|
+
});
|
|
96
|
+
}, { when: l } = r;
|
|
97
|
+
l ? l(n, s.signal).then(() => {
|
|
98
|
+
s.signal.aborted || c();
|
|
99
|
+
}, (e) => {
|
|
100
|
+
t(e) || (s.abort(), queueMicrotask(() => {
|
|
101
|
+
throw e;
|
|
102
|
+
}));
|
|
103
|
+
}) : c();
|
|
104
|
+
}), e.addUnmountMiddleware((e) => (t) => {
|
|
105
|
+
t.forEach(o.abort), e(t);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { a as createScheduler, o as schedulerAddon };
|
package/dist/main.es.js
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
//#region lib/
|
|
2
|
-
function e(
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
};
|
|
1
|
+
//#region lib/core/addon.ts
|
|
2
|
+
function e() {
|
|
3
|
+
let e = /* @__PURE__ */ new Set(), t = [], n = [], r = [], i = {
|
|
4
|
+
get installedAddons() {
|
|
5
|
+
return e;
|
|
6
|
+
},
|
|
7
|
+
addComponentMiddleware(e) {
|
|
8
|
+
t.push(e);
|
|
9
|
+
},
|
|
10
|
+
addMountMiddleware(e) {
|
|
11
|
+
n.push(e);
|
|
12
|
+
},
|
|
13
|
+
addUnmountMiddleware(e) {
|
|
14
|
+
r.push(e);
|
|
15
|
+
},
|
|
16
|
+
composeComponent(e) {
|
|
17
|
+
return t.reduce((e, t) => t(e), e);
|
|
18
|
+
},
|
|
19
|
+
composeMount(e, t, r) {
|
|
20
|
+
return n.reduce((e, n) => n(e, t, r), e);
|
|
23
21
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
composeUnmount(e) {
|
|
23
|
+
return r.reduce((e, t) => t(e), e);
|
|
24
|
+
},
|
|
25
|
+
install(t) {
|
|
26
|
+
if (e.has(t.name)) throw Error(`[nagi] addon "${t.name}" is already installed`);
|
|
27
|
+
t.install(i), e.add(t.name);
|
|
27
28
|
}
|
|
28
29
|
};
|
|
30
|
+
return i;
|
|
31
|
+
}
|
|
32
|
+
function t(e) {
|
|
33
|
+
return e;
|
|
29
34
|
}
|
|
30
35
|
//#endregion
|
|
31
36
|
//#region lib/core/error.ts
|
|
@@ -118,12 +123,7 @@ var s = /* @__PURE__ */ function(e) {
|
|
|
118
123
|
}
|
|
119
124
|
};
|
|
120
125
|
function u(e) {
|
|
121
|
-
return e
|
|
122
|
-
name: e.name,
|
|
123
|
-
setup(n) {
|
|
124
|
-
return e.setup(n, t);
|
|
125
|
-
}
|
|
126
|
-
}) : e;
|
|
126
|
+
return e;
|
|
127
127
|
}
|
|
128
128
|
//#endregion
|
|
129
129
|
//#region lib/core/runtime.ts
|
|
@@ -132,7 +132,7 @@ function f(e) {
|
|
|
132
132
|
if (!d) throw Error(`"${e}" called outside setup() will never be run.`);
|
|
133
133
|
return d;
|
|
134
134
|
}
|
|
135
|
-
function p(e, t, n) {
|
|
135
|
+
function p(e, t, n = {}) {
|
|
136
136
|
let a = new l(t, e.name), o = d;
|
|
137
137
|
d = a;
|
|
138
138
|
try {
|
|
@@ -144,41 +144,28 @@ function p(e, t, n) {
|
|
|
144
144
|
}
|
|
145
145
|
//#endregion
|
|
146
146
|
//#region lib/core/app.ts
|
|
147
|
-
function m(
|
|
148
|
-
let
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
});
|
|
164
|
-
};
|
|
165
|
-
a ? a(s, u.signal).then(() => {
|
|
166
|
-
u.signal.aborted || d();
|
|
167
|
-
}, (t) => {
|
|
168
|
-
e(t) || (u.abort(), queueMicrotask(() => {
|
|
169
|
-
throw t;
|
|
170
|
-
}));
|
|
171
|
-
}) : d();
|
|
172
|
-
};
|
|
147
|
+
function m() {
|
|
148
|
+
let t = e(), n = (e) => {
|
|
149
|
+
for (let t of e) {
|
|
150
|
+
let e = a.get(t);
|
|
151
|
+
e && (e.onUnmount(), a.delete(t));
|
|
152
|
+
}
|
|
153
|
+
}, r = {
|
|
154
|
+
install(...e) {
|
|
155
|
+
return e.forEach(t.install), r;
|
|
156
|
+
},
|
|
157
|
+
component(e, n = {}) {
|
|
158
|
+
let r = t.composeComponent(e), i = t.composeMount((e, t) => {
|
|
159
|
+
let n = p(r, e, t);
|
|
160
|
+
return o(e, n), n.onMount(), n;
|
|
161
|
+
}, r, n);
|
|
162
|
+
return (e, t = {}) => i(e, t);
|
|
173
163
|
},
|
|
174
164
|
unmount(e) {
|
|
175
|
-
|
|
176
|
-
i.abort(t);
|
|
177
|
-
let e = a.get(t);
|
|
178
|
-
e && (e.onUnmount(), a.delete(t));
|
|
179
|
-
}
|
|
165
|
+
t.composeUnmount(n)(e);
|
|
180
166
|
}
|
|
181
167
|
};
|
|
168
|
+
return r;
|
|
182
169
|
}
|
|
183
170
|
//#endregion
|
|
184
171
|
//#region lib/core/lifecycle.ts
|
|
@@ -350,7 +337,7 @@ function F(e, t) {
|
|
|
350
337
|
function I() {
|
|
351
338
|
let e = f("useSlot");
|
|
352
339
|
return {
|
|
353
|
-
addChild(t, n, r
|
|
340
|
+
addChild(t, n, r) {
|
|
354
341
|
let i = (t) => {
|
|
355
342
|
let i = p(n, t, r);
|
|
356
343
|
return e.addChild(i), i;
|
|
@@ -369,4 +356,7 @@ function I() {
|
|
|
369
356
|
};
|
|
370
357
|
}
|
|
371
358
|
//#endregion
|
|
372
|
-
|
|
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 };
|
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(
|
|
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});
|
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
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,11 @@
|
|
|
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;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ComponentSetup, RefElement } from "../types";
|
|
2
|
+
declare const mountOptionsBrand: unique symbol;
|
|
3
|
+
/** Options for `app.component(setup, opts)` — extended by mount addons. */
|
|
4
|
+
export interface MountOptions {
|
|
5
|
+
readonly [mountOptionsBrand]?: never;
|
|
6
|
+
}
|
|
7
|
+
/** Mount after addon middleware runs — may return void when mount is deferred (e.g. scheduler). */
|
|
8
|
+
export type MountFn = (el: RefElement, props: Record<string, any>) => any;
|
|
9
|
+
export type UnmountFn = (targets: RefElement[]) => void;
|
|
10
|
+
export type ComponentMiddleware = <S extends ComponentSetup>(comp: S) => S;
|
|
11
|
+
export type MountMiddleware = (next: MountFn, setup: ComponentSetup, opts: MountOptions) => MountFn;
|
|
12
|
+
export type UnmountMiddleware = (next: UnmountFn) => UnmountFn;
|
|
13
|
+
export type Addon = {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
install(ctx: AddonContext): void;
|
|
16
|
+
};
|
|
17
|
+
export type AddonContext = {
|
|
18
|
+
readonly installedAddons: ReadonlySet<string>;
|
|
19
|
+
addComponentMiddleware(middleware: ComponentMiddleware): void;
|
|
20
|
+
addMountMiddleware(middleware: MountMiddleware): void;
|
|
21
|
+
addUnmountMiddleware(middleware: UnmountMiddleware): void;
|
|
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
|
+
/**
|
|
31
|
+
* Identity helper for type inference only — no runtime effect.
|
|
32
|
+
*/
|
|
33
|
+
export declare function defineAddon(addon: Addon): Addon;
|
|
34
|
+
export declare function defineAddon<TOptions>(factory: (options?: TOptions) => Addon): (options?: TOptions) => Addon;
|
|
35
|
+
export {};
|
package/types/core/app.d.ts
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
|
-
import type { ComponentSetup,
|
|
1
|
+
import type { ComponentSetup, RefElement } from "../types";
|
|
2
|
+
import type { Addon, MountOptions } from "./addon";
|
|
2
3
|
import type { ComponentContext } from "./component";
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type AsyncAppOptions = AppOptions & {
|
|
7
|
-
when?: Cue;
|
|
8
|
-
};
|
|
9
|
-
type SyncApp = {
|
|
10
|
-
component<S extends ComponentSetup>(wrap: S, opts?: AppOptions): (el: RefElement, props?: Record<string, any>) => ComponentContext<ReturnType<S["setup"]>>;
|
|
11
|
-
unmount(targets: RefElement[]): void;
|
|
12
|
-
};
|
|
13
|
-
type AsyncApp = {
|
|
14
|
-
component<S extends ComponentSetup>(wrap: S, opts?: AsyncAppOptions): (el: RefElement, props?: Record<string, any>) => void;
|
|
4
|
+
type App = {
|
|
5
|
+
install(...addons: Addon[]): App;
|
|
6
|
+
component<S extends ComponentSetup>(component: S, opts?: MountOptions): (el: RefElement, props?: Record<string, any>) => ComponentContext<ReturnType<S["setup"]>> | void;
|
|
15
7
|
unmount(targets: RefElement[]): void;
|
|
16
8
|
};
|
|
17
|
-
export declare function create():
|
|
18
|
-
export declare function create(config: {
|
|
19
|
-
scheduler?: undefined;
|
|
20
|
-
}): SyncApp;
|
|
21
|
-
export declare function create(config: {
|
|
22
|
-
scheduler: Scheduler;
|
|
23
|
-
}): AsyncApp;
|
|
24
|
-
export declare function create(config: {
|
|
25
|
-
scheduler?: Scheduler | undefined;
|
|
26
|
-
}): SyncApp | AsyncApp;
|
|
9
|
+
export declare function create(): App;
|
|
27
10
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentSetup, RefElement } from "../types";
|
|
1
|
+
import type { ComponentProps, ComponentSetup, RefElement } from "../types";
|
|
2
2
|
export declare enum LifecycleHooks {
|
|
3
3
|
MOUNTED = "Mounted",
|
|
4
4
|
UNMOUNTED = "Unmounted"
|
|
@@ -21,8 +21,17 @@ export declare class ComponentContext<T = any> {
|
|
|
21
21
|
removeChild: (child: ComponentContext) => void;
|
|
22
22
|
get childElements(): RefElement[];
|
|
23
23
|
}
|
|
24
|
-
export declare function defineComponent<
|
|
24
|
+
export declare function defineComponent<SetupResult extends Record<string, unknown> | void, Props extends Record<string, unknown>>(opts: {
|
|
25
25
|
name: string;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
props: Props;
|
|
27
|
+
setup(el: RefElement, props: ComponentProps<Props>): SetupResult;
|
|
28
|
+
}): ComponentSetup<SetupResult, Props>;
|
|
29
|
+
export declare function defineComponent<SetupResult extends Record<string, unknown> | void, Props extends Record<string, unknown>>(opts: {
|
|
30
|
+
name: string;
|
|
31
|
+
setup(el: RefElement, props: ComponentProps<Props>): SetupResult;
|
|
32
|
+
}): ComponentSetup<SetupResult, Props>;
|
|
33
|
+
export declare function defineComponent<SetupResult extends Record<string, unknown> | void>(opts: {
|
|
34
|
+
name: string;
|
|
35
|
+
setup(el: RefElement): SetupResult;
|
|
36
|
+
}): ComponentSetup<SetupResult, Record<string, never>>;
|
|
37
|
+
export declare function defineComponent(opts: ComponentSetup): ComponentSetup;
|
package/types/core/runtime.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ComponentContext } from "./component";
|
|
2
2
|
import type { ComponentSetup, RefElement } from "../types";
|
|
3
3
|
export declare function getCurrentComponent(hookName: string): ComponentContext;
|
|
4
|
-
export declare function createComponent(wrap: ComponentSetup, root: RefElement, props
|
|
4
|
+
export declare function createComponent(wrap: ComponentSetup, root: RefElement, props?: Record<string, any>): ComponentContext<any>;
|
package/types/hooks/useSlot.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ComponentContext } from "../core/component";
|
|
2
2
|
import type { ComponentSetup, RefElement } from "../types";
|
|
3
3
|
export declare function useSlot(): {
|
|
4
|
-
addChild<Child extends ComponentSetup>(targetOrTargets: RefElement | RefElement[], child: Child, props?: Parameters<Child["setup"]>[1]): ComponentContext<ReturnType<Child["setup"]>>[];
|
|
4
|
+
addChild<Child extends ComponentSetup>(targetOrTargets: RefElement | RefElement[], child: Child, props?: Partial<Parameters<Child["setup"]>[1]>): ComponentContext<ReturnType<Child["setup"]>>[];
|
|
5
5
|
removeChild(children: ComponentContext[]): void;
|
|
6
6
|
};
|
package/types/main.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { defineAddon } from "./core/addon";
|
|
1
2
|
export { create } from "./core/app";
|
|
2
3
|
export { defineComponent } from "./core/component";
|
|
3
4
|
export { isLifecycleError, LifecycleError } from "./core/error";
|
|
@@ -9,6 +10,8 @@ export { useEvent } from "./hooks/useEvent";
|
|
|
9
10
|
export { useIntersectionWatch } from "./hooks/useIntersectionWatch";
|
|
10
11
|
export { useMediaQuery } from "./hooks/useMediaQuery";
|
|
11
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";
|
|
12
15
|
export type { ComponentContext } from "./core/component";
|
|
13
16
|
export type { LifecycleErrorDetails } from "./core/error";
|
|
14
17
|
export type { ReadonlySignal, Signal } from "./core/reactivity";
|
package/types/props.d.ts
ADDED
package/types/types.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export type RefElement = HTMLElement | SVGElement;
|
|
2
2
|
export type ComponentProps<Props> = Readonly<Props>;
|
|
3
|
-
export type ComponentSetup<SetupResult = void | Record<string, unknown>, Props = Record<string, unknown>> = {
|
|
3
|
+
export type ComponentSetup<SetupResult = void | Record<string, unknown>, Props extends Record<string, unknown> = Record<string, unknown>> = {
|
|
4
4
|
name: string;
|
|
5
5
|
setup(el: RefElement, props: ComponentProps<Props>): SetupResult;
|
|
6
6
|
};
|
|
7
7
|
/** @deprecated Use `ComponentSetup` instead. */
|
|
8
|
-
export type IComponent<SetupResult = void | Record<string, unknown>, Props = Record<string, unknown>> = ComponentSetup<SetupResult, Props>;
|
|
8
|
+
export type IComponent<SetupResult = void | Record<string, unknown>, Props extends Record<string, unknown> = Record<string, unknown>> = ComponentSetup<SetupResult, Props>;
|
|
9
9
|
export type Cleanup = () => void;
|
|
10
10
|
export type LifecycleHandler = () => void | Cleanup;
|
|
11
11
|
export type SchedulePriority = "user-blocking" | "user-visible" | "background";
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { RefElement } from "../../types";
|
|
2
|
-
export type PendingMountTask = {
|
|
3
|
-
readonly signal: AbortSignal;
|
|
4
|
-
complete(): boolean;
|
|
5
|
-
abort(): void;
|
|
6
|
-
};
|
|
7
|
-
export type PendingMountTasks = {
|
|
8
|
-
add(el: RefElement): PendingMountTask;
|
|
9
|
-
abort(el: RefElement): void;
|
|
10
|
-
};
|
|
11
|
-
export declare function createPendingMountTasks(): PendingMountTasks;
|