neko-vue 0.1.0 → 0.1.1
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/CHANGELOG.md +2 -3
- package/README.md +85 -34
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
3
|
+
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
|
+
## [0.1.1](https://github.com/AscaL/neko-vue/compare/v0.1.0...v0.1.1) (2026-04-04)
|
|
7
6
|
|
|
8
7
|
## [0.1.0] - 2026-04-04
|
|
9
8
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Vue 3 helpers for a classic viewport-fixed desktop pet: typed options, `loadNekoRuntime()`, `useNeko()`, and `NekoPet`. The default path uses programmatic `createNeko` only (no `data-autostart`).
|
|
4
4
|
|
|
5
|
-
The pet **engine always comes from this package** (a dynamically imported chunk in `dist/`). There is **no** supported option to load `createNeko` from a remote URL or a separate script tag—only the bundled runtime, unless you assign **`
|
|
5
|
+
The pet **engine always comes from this package** (a dynamically imported chunk in `dist/`). There is **no** supported option to load `createNeko` from a remote URL or a separate script tag—only the bundled runtime, unless you assign **`globalThis.createNeko`** yourself first (in browsers usually **`window.createNeko`**; advanced / tests).
|
|
6
6
|
|
|
7
7
|
**Peer dependency:** `vue` ^3.4 or ^3.5.
|
|
8
8
|
|
|
@@ -12,19 +12,19 @@ The pet **engine always comes from this package** (a dynamically imported chunk
|
|
|
12
12
|
|
|
13
13
|
| Capability | Details |
|
|
14
14
|
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
-
| **Typed engine API** | `NekoOptions`, `NekoInstance`, `BehaviorMode`, `
|
|
16
|
-
| **Bundled runtime** |
|
|
17
|
-
| **`<NekoPet />`** | Declarative
|
|
18
|
-
| **`useNeko()`** | Same options as **`NekoPet`**
|
|
19
|
-
| **`loadNekoRuntime()`** |
|
|
20
|
-
| **Placement helpers** |
|
|
15
|
+
| **Typed engine API** | `NekoOptions`, `NekoInstance`, `BehaviorMode`, `BehaviorModes`, `DEFAULT_NEKO_BEHAVIOR_CYCLE`, `NEKOJS_SPRITE_SIZE` — aligned with **`createNeko`**. |
|
|
16
|
+
| **Bundled runtime** | Engine lives in **`dist/`** as a separate chunk; your bundler loads it via **dynamic `import`** (no extra HTTP URL in this API). Same chunk **`loadNekoRuntime()`** / **`useNeko`** pull in. |
|
|
17
|
+
| **`<NekoPet />`** | Declarative wrapper: placement (**`start-corner`**, **`anchor-selector`**), **`mode`** (`follow` / `rest`), engine tuning (**`speed`**, **`fps`**, **`behavior-mode`**, **`behavior-cycle`**, **`cursor-standoff-px`**, …), motion gate, **`debug`**. |
|
|
18
|
+
| **`useNeko()`** | Same options as **`NekoPet`** plus **`anchorRef`**; returns **`instance`**, **`isReady`**, **`error`**, **`skippedForReducedMotion`**, **`mode`**, **`petInteractionAwake`**, **`setMode`**, **`destroy`**, etc. Calls **`loadNekoRuntime()`** internally. |
|
|
19
|
+
| **`loadNekoRuntime()`** | Returns **`Promise<CreateNekoFn>`** — the typed **`createNeko`** factory. **Browser:** if **`globalThis.createNeko`** already exists (tests / custom setup), resolves to that; else **one shared promise** dynamic-imports the bundled runtime once. **Not in browser (e.g. SSR):** rejects immediately with a clear error (do not call on the server). |
|
|
20
|
+
| **Placement helpers** | **`NekoStartCorner`**, **`NekoPlacementInput`**, **`cornerToStartXY`**, **`resolveStartPosition`** — corner / anchor → **`startX`** / **`startY`**. In **`useNeko`**, a **`ResizeObserver`** is attached only when **`anchorRef`** is set (not for **`anchorSelector`** alone). |
|
|
21
21
|
| **Motion & a11y** | `prefersReducedMotion()`; composable and component skip the pet when user prefers reduced motion (with opt-out on `NekoPet`). |
|
|
22
22
|
| **Lifecycle** | Unmount → `stop()` + `destroy()`; bundled runtime removes listeners via **`AbortController`**. |
|
|
23
23
|
| **Debug** | `nekoVueDebug()` for optional placement / recreate logging. |
|
|
24
24
|
|
|
25
25
|
## Source layout (this repo)
|
|
26
26
|
|
|
27
|
-
Library code under **`src/`** is grouped by role
|
|
27
|
+
Library code under **`src/`** is grouped by role. **`vite.config.ts`** **`pack.entry`** maps **`src/index.ts`** plus **`src/entries/*.ts`** to published **`dist/*.mjs`**; **`pack.exports: false`** leaves **`package.json` `exports`** as the source of truth (see [Subpath imports](#subpath-imports)).
|
|
28
28
|
|
|
29
29
|
| Folder | Role |
|
|
30
30
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
@@ -33,16 +33,25 @@ Library code under **`src/`** is grouped by role (public API remains **`neko-vue
|
|
|
33
33
|
| **`src/vue/`** | `useNeko.ts`, `NekoPet.ts` (`defineComponent`, not an SFC). |
|
|
34
34
|
| **`src/placement/`** | Corner / anchor → `startX` / `startY` resolution. |
|
|
35
35
|
| **`src/utils/`** | `prefersReducedMotion`, `nekoVueDebug`. |
|
|
36
|
-
| **`src/
|
|
36
|
+
| **`src/entries/`** | Thin barrels for **`neko-vue/types`**, **`/placement`**, **`/runtime`**, **`/vue`** (see **`vite.config.ts`** **`pack.entry`**). |
|
|
37
|
+
| **`src/index.ts`** | Root public re-exports (full API). |
|
|
37
38
|
| **`src/env.d.ts`** | Vite / client typings. |
|
|
38
39
|
|
|
39
40
|
## Install
|
|
40
41
|
|
|
42
|
+
**Vue is a peer dependency** — `neko-vue` does not ship its own copy of Vue (that would risk two Vue runtimes in one app). In a normal Vue 3 app you already have **`vue`** in `package.json`, so add only this package:
|
|
43
|
+
|
|
41
44
|
```bash
|
|
42
|
-
npm install neko-vue
|
|
45
|
+
npm install neko-vue
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
Same idea with **pnpm**, **Yarn**, or **Bun** (for example `pnpm add neko-vue`). Your app must satisfy **`vue` ^3.4 or ^3.5** (see `peerDependencies` in `package.json`); npm will warn if it’s missing.
|
|
49
|
+
|
|
50
|
+
**Greenfield / no Vue yet** — install both once:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install neko-vue vue
|
|
54
|
+
```
|
|
46
55
|
|
|
47
56
|
### Subpath imports
|
|
48
57
|
|
|
@@ -53,7 +62,7 @@ Besides the root entry (`neko-vue`), published builds expose **conditional expor
|
|
|
53
62
|
| **`neko-vue`** | Full public API (root barrel). |
|
|
54
63
|
| **`neko-vue/types`** | `BehaviorMode`, `BehaviorModes`, `DEFAULT_NEKO_BEHAVIOR_CYCLE`, `NEKOJS_SPRITE_SIZE`, `NekoOptions`, `NekoInstance`, `CreateNekoFn`, `LoadNekoRuntimeOptions` — no Vue, no loader. |
|
|
55
64
|
| **`neko-vue/placement`** | `cornerToStartXY`, `resolveStartPosition`, `NekoStartCorner`, `NekoPlacementInput` — no Vue. |
|
|
56
|
-
| **`neko-vue/runtime`** | `loadNekoRuntime` only
|
|
65
|
+
| **`neko-vue/runtime`** | `loadNekoRuntime` only — pulls the bundled engine chunk when called. |
|
|
57
66
|
| **`neko-vue/vue`** | `useNeko`, `NekoPet`, `UseNekoOptions`, `NekoFollowMode` — **requires Vue**; still loads the engine when you create a pet. |
|
|
58
67
|
|
|
59
68
|
Your bundler decides how much code stays in the bundle; these subpaths make dependencies explicit and avoid importing the root barrel when you only need types or placement helpers.
|
|
@@ -128,7 +137,7 @@ If the user prefers reduced motion, **`NekoPet`** and **`useNeko`** **skip** loa
|
|
|
128
137
|
|
|
129
138
|
### 7. SSR (Nuxt, custom SSR)
|
|
130
139
|
|
|
131
|
-
Never call **`useNeko`**, render **`NekoPet`**, or **`loadNekoRuntime`** on the server. Use a **`.client.vue`** component or **`<ClientOnly>`** (see [Nuxt
|
|
140
|
+
Never call **`useNeko`**, render **`NekoPet`**, or **`loadNekoRuntime`** on the server. Use a **`.client.vue`** component or **`<ClientOnly>`** (see [Nuxt 4](#4-nuxt-4) below).
|
|
132
141
|
|
|
133
142
|
### 8. When something looks wrong
|
|
134
143
|
|
|
@@ -161,13 +170,13 @@ TypeScript picks up types from the published `dist` typings; no extra `@types` p
|
|
|
161
170
|
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
162
171
|
| **`<NekoPet />`** | You want declarative props (`speed`, `start-corner`, `mode`, …) and minimal setup code. |
|
|
163
172
|
| **`useNeko()`** | You need a **handle** (`setMode`, `destroy`, refs to `instance` / `isReady` / `error`) or **`anchorRef`** to tie the start position to another element. |
|
|
164
|
-
| **`loadNekoRuntime()`** | Advanced: ensure a typed
|
|
173
|
+
| **`loadNekoRuntime()`** | Advanced: ensure a typed **`createNeko`** after the bundled runtime is loaded, or reuse an existing **`globalThis.createNeko`** (e.g. tests). |
|
|
165
174
|
|
|
166
|
-
By default, **`loadNekoRuntime()`** loads the **bundled** engine (dynamic import, no extra network hop for the pet). If **`
|
|
175
|
+
By default, **`loadNekoRuntime()`** loads the **bundled** engine (dynamic import, no extra network hop for the pet). If **`globalThis.createNeko`** is already a function when the loader runs, that implementation is used instead (typical in **tests** or custom setups).
|
|
167
176
|
|
|
168
177
|
### 3. Vite, Vue CLI, or a plain SPA
|
|
169
178
|
|
|
170
|
-
1. Install
|
|
179
|
+
1. Install **`neko-vue`** (and **`vue`** if the project does not already depend on it).
|
|
171
180
|
2. Use **`NekoPet`** in any component that only runs on the client (typical SPA entry is client-only already):
|
|
172
181
|
|
|
173
182
|
```vue
|
|
@@ -182,13 +191,17 @@ import { NekoPet } from "neko-vue";
|
|
|
182
191
|
|
|
183
192
|
3. If you prefer the composable, call **`useNeko()` inside `setup()`** (or `<script setup>`) — see the [Composable](#composable) section.
|
|
184
193
|
|
|
185
|
-
### 4. Nuxt
|
|
194
|
+
### 4. Nuxt 4
|
|
195
|
+
|
|
196
|
+
These notes match **[Nuxt 4](https://nuxt.com/)** (Vue 3). The pet is **browser-only**; keep it off the server render path.
|
|
197
|
+
|
|
198
|
+
1. **Install:** add **`neko-vue`** with your package manager (`npm install neko-vue`, `pnpm add neko-vue`, …). You do **not** need a Nuxt module for this library. Nuxt already depends on **Vue 3**.
|
|
186
199
|
|
|
187
|
-
|
|
200
|
+
2. **Client-only rendering** (pick one):
|
|
201
|
+
- Put the pet in a component named **`*.client.vue`** under **`components/`**, or
|
|
202
|
+
- Wrap it with **[`<ClientOnly>`](https://nuxt.com/docs/4.x/api/components/client-only)**.
|
|
188
203
|
|
|
189
|
-
|
|
190
|
-
- Put the pet in a **`.client.vue`** component, or
|
|
191
|
-
- Wrap with [`<ClientOnly>`](https://nuxt.com/docs/api/components/client-only).
|
|
204
|
+
For **`.client.vue`**, Nuxt only treats the file as client-only when you use **[auto-imports](https://nuxt.com/docs/4.x/guide/directory-structure/components#client-components)** or import from **`#components`**. Importing the file by **filesystem path** (e.g. `~/components/Foo.client.vue`) does **not** apply the client-only transform—use **`import { NekoPetClient } from '#components'`** or drop the import and use the auto-registered name.
|
|
192
205
|
|
|
193
206
|
```vue
|
|
194
207
|
<!-- components/NekoPetClient.client.vue -->
|
|
@@ -202,9 +215,9 @@ import { NekoPet } from "neko-vue";
|
|
|
202
215
|
```
|
|
203
216
|
|
|
204
217
|
```vue
|
|
205
|
-
<!-- pages/index.vue
|
|
218
|
+
<!-- e.g. app/pages/index.vue (Nuxt 4 default `app/` layout) or pages/index.vue if you use a classic root `pages/` dir -->
|
|
206
219
|
<script setup lang="ts">
|
|
207
|
-
import NekoPetClient from "
|
|
220
|
+
import { NekoPetClient } from "#components";
|
|
208
221
|
</script>
|
|
209
222
|
|
|
210
223
|
<template>
|
|
@@ -216,7 +229,7 @@ import NekoPetClient from "~/components/NekoPetClient.client.vue";
|
|
|
216
229
|
</template>
|
|
217
230
|
```
|
|
218
231
|
|
|
219
|
-
|
|
232
|
+
Alternatively, omit the script import and use **`<NekoPetClient />`** if the file **`components/NekoPetClient.client.vue`** is picked up by Nuxt’s component scanner.
|
|
220
233
|
|
|
221
234
|
### 5. Global registration (optional)
|
|
222
235
|
|
|
@@ -276,7 +289,30 @@ import { BehaviorMode, NekoPet } from "neko-vue";
|
|
|
276
289
|
</template>
|
|
277
290
|
```
|
|
278
291
|
|
|
279
|
-
`NekoPet` is implemented as `defineComponent` (TypeScript) for reliable library builds; use it like any other Vue component. It **exposes** `{ instance }` (
|
|
292
|
+
`NekoPet` is implemented as `defineComponent` (TypeScript) for reliable library builds; use it like any other Vue component. It **exposes** `{ instance }` (**`shallowRef<NekoInstance | null>`** from the internal **`useNeko`**). On the parent **`ref`**, Vue **unwraps** exposed refs, so **`childRef.instance`** matches the live pet handle from **`useNeko()`’s `instance`** (same timing: **`null`** until ready).
|
|
293
|
+
|
|
294
|
+
### `NekoPet` props (reference)
|
|
295
|
+
|
|
296
|
+
In **templates**, use **kebab-case** for multi-word names (Vue maps them to camelCase). Types below match **`NekoPet`** / **`UseNekoOptions`** / **`NekoOptions`**.
|
|
297
|
+
|
|
298
|
+
| Prop (script) | Template (kebab) | Type | Default | Summary |
|
|
299
|
+
| ------------- | ------------------ | ---- | ------- | ------- |
|
|
300
|
+
| **`speed`** | `speed` | `number` | _(omit)_ | Pixels per engine logic tick (`createNeko`; default **24**; engine logic ~5 ticks/sec). |
|
|
301
|
+
| **`fps`** | `fps` | `number` | _(omit)_ | Sprite animation frame rate (default in engine **120**). |
|
|
302
|
+
| **`behaviorMode`** | `behavior-mode` | `BehaviorMode` (number) | _(omit)_ | **Initial** mode at create; live mode changes by **clicking the pet** when `allowBehaviorChange` is true. |
|
|
303
|
+
| **`idleThreshold`** | `idle-threshold` | `number` | _(omit)_ | Idle distance in px (engine default **6**). |
|
|
304
|
+
| **`cursorStandoffPx`** | `cursor-standoff-px` | `number` | _(omit / 0)_ | Chase mode: minimum distance from pointer in px; **0** or omit = sit on cursor. |
|
|
305
|
+
| **`allowBehaviorChange`** | `allow-behavior-change` | `boolean` | **`undefined`** | **`undefined`** = omit field → engine default **`true`**. **`false`** disables click-to-cycle. |
|
|
306
|
+
| **`behaviorCycle`** | `behavior-cycle` | `BehaviorMode[]` | _(omit)_ | Pet-click order; omit for **`DEFAULT_NEKO_BEHAVIOR_CYCLE`**. |
|
|
307
|
+
| **`startX`** | `start-x` | `number` | _(omit)_ | Initial / home X (**0** valid). |
|
|
308
|
+
| **`startY`** | `start-y` | `number` | _(omit)_ | Initial / home Y (**0** valid). |
|
|
309
|
+
| **`autoStart`** | `auto-start` | `boolean` | **`true`** | After `createNeko`, run the loop unless **`mode="rest"`** or **`false`**. |
|
|
310
|
+
| **`respectReducedMotion`** | `respect-reduced-motion` | `boolean` | **`true`** | Skip pet when user prefers reduced motion. |
|
|
311
|
+
| **`startCorner`** | `start-corner` | `string` | _(omit)_ | **`top-left`** \| **`top-right`** \| **`bottom-left`** \| **`bottom-right`** for axes without `startX`/`startY`. |
|
|
312
|
+
| **`anchorSelector`** | `anchor-selector` | `string` | _(omit)_ | `document.querySelector` for anchor; waits for non-zero layout. Prefer **`anchorRef`** in **`useNeko`**. |
|
|
313
|
+
| **`mode`** | `mode` | **`follow`** \| **`rest`** | **`follow`** | **`follow`** = loop runs; **`rest`** = stop at resolved home after create. |
|
|
314
|
+
| **`restUntilFirstPetInteraction`** | `rest-until-first-pet-interaction` | `boolean` | **`undefined`** | First pointer-down on sprite wakes **`follow`** without consuming first cycle step. |
|
|
315
|
+
| **`debug`** | `debug` | `boolean` | **`false`** | **`[neko-vue]`** console logs for placement / recreates. |
|
|
280
316
|
|
|
281
317
|
**`allowBehaviorChange`:** Omit the prop to keep the **engine default** (`true`). A plain optional `Boolean` prop in Vue would otherwise become `false` when unset; here the default is explicitly `undefined`, and options passed to `createNeko` omit `undefined` fields so engine defaults apply.
|
|
282
318
|
|
|
@@ -318,6 +354,18 @@ const {
|
|
|
318
354
|
</script>
|
|
319
355
|
```
|
|
320
356
|
|
|
357
|
+
### `useNeko()` return value (reference)
|
|
358
|
+
|
|
359
|
+
| Name | What it is |
|
|
360
|
+
| ---- | ----------- |
|
|
361
|
+
| **`instance`** | **`ShallowRef<NekoInstance \| null>`** — set after load + `createNeko`; **`null`** before ready, after **`destroy`**, or while skipped for reduced motion / deferred anchor. |
|
|
362
|
+
| **`error`** | **`Ref<Error \| null>`** — load / `createNeko` failure; cleared at the start of each recreate attempt. |
|
|
363
|
+
| **`isReady`** | **`Ref<boolean>`**, **`true`** once `createNeko` succeeded for the current mount cycle. |
|
|
364
|
+
| **`skippedForReducedMotion`** | **`Ref<boolean>`**, **`true`** when the pet was skipped because the user prefers reduced motion (default gate on). |
|
|
365
|
+
| **`mode`** | Readonly ref: current **`follow`** / **`rest`**; drive with **`setMode`**, **`restAtOrigin`**, **`resumeFollow`**, or a reactive **`mode`** in options. |
|
|
366
|
+
| **`petInteractionAwake`** | Readonly ref; with **`restUntilFirstPetInteraction`**, **`true`** after the first pointer-down on the sprite wakes **`follow`**. |
|
|
367
|
+
| **`setMode`**, **`restAtOrigin`**, **`resumeFollow`**, **`destroy`** | Imperative controls (see [Follow vs rest (`mode`)](#follow-vs-rest-mode) in the composable section below). |
|
|
368
|
+
|
|
321
369
|
**Custom click cycle and pointer standoff** (same options on **`NekoPet`** as props):
|
|
322
370
|
|
|
323
371
|
```ts
|
|
@@ -368,6 +416,7 @@ useNeko(
|
|
|
368
416
|
- **`startX` / `startY`** — passed through to `createNeko` (remember `0` is valid).
|
|
369
417
|
- **`startCorner`** — `top-left` | `top-right` | `bottom-left` | `bottom-right`; fills axes that `startX`/`startY` leave out, using `document.documentElement.clientWidth` and `window.innerHeight` minus `NEKOJS_SPRITE_SIZE` (32).
|
|
370
418
|
- **`anchorRef`** (in `setup`) or **`anchorSelector`** (on `NekoPet`) — use the element’s top-left in viewport space when coordinates are omitted. If you pass either one, **`createNeko` waits** until the matched element exists and has **positive width and height** (`getBoundingClientRect()`, with `offsetWidth` / `offsetHeight` as a fallback) so the pet does not spawn at a bogus position while the anchor is still mounting or collapsed.
|
|
419
|
+
- **`ResizeObserver`** (in **`useNeko`** only): attached when **`anchorRef`** points at an element, so layout changes on that node can trigger a recreate. There is **no** observer for **`anchorSelector`** alone.
|
|
371
420
|
|
|
372
421
|
Resolution order per axis: **explicit coordinate → anchor → corner → 0**.
|
|
373
422
|
|
|
@@ -395,7 +444,7 @@ Returning to home after the cat has moved uses a **fresh instance** (destroy + c
|
|
|
395
444
|
|
|
396
445
|
Use this when you call **`createNeko`** outside **`useNeko`** / **`NekoPet`** (e.g. a custom lifecycle).
|
|
397
446
|
|
|
398
|
-
- If **`
|
|
447
|
+
- If **`globalThis.createNeko`** already exists, **`loadNekoRuntime()`** resolves to it immediately (no import).
|
|
399
448
|
- Otherwise it performs a **one-time** dynamic import of the bundled runtime (same code path as **`useNeko`**).
|
|
400
449
|
|
|
401
450
|
```ts
|
|
@@ -410,7 +459,7 @@ neko.start();
|
|
|
410
459
|
|
|
411
460
|
## Nuxt / SSR
|
|
412
461
|
|
|
413
|
-
The pet runtime is **browser-only**. Do not run
|
|
462
|
+
The pet runtime is **browser-only**. Do not run **`loadNekoRuntime`**, **`useNeko`**, or mount **`NekoPet`** on the server. In **Nuxt 4**, use a **`*.client.vue`** component (with [auto-import or `#components`](https://nuxt.com/docs/4.x/guide/directory-structure/components#client-components)) and/or [`<ClientOnly>`](https://nuxt.com/docs/4.x/api/components/client-only). See [Nuxt 4](#4-nuxt-4) above.
|
|
414
463
|
|
|
415
464
|
## Motion preferences
|
|
416
465
|
|
|
@@ -456,10 +505,11 @@ vp test
|
|
|
456
505
|
Runs Vitest against **`loadNekoRuntime`**, `useNeko`, and `NekoPet` (tests set **`window.createNeko`** mocks; happy-dom), including checks that optional fields are not sent as `undefined`, that **`behaviorCycle`** / **`cursorStandoffPx`** reach `createNeko` when set, that anchor `ResizeObserver` does not recreate the pet when the layout size is unchanged, and that **`createNeko` is deferred** until an anchor element has non-zero layout when `anchorRef` is used.
|
|
457
506
|
|
|
458
507
|
```bash
|
|
459
|
-
vp check
|
|
508
|
+
vp run check
|
|
509
|
+
vp run check:playground
|
|
460
510
|
```
|
|
461
511
|
|
|
462
|
-
Runs format, lint, and TypeScript
|
|
512
|
+
Or **`bun run check:all`** — library paths first, then **`playground/src`** and **`playground/vite.config.ts`** (bare **`vp check`** would typecheck the playground against root `node_modules` and fail). Runs format, lint, and TypeScript via Vite+.
|
|
463
513
|
|
|
464
514
|
```bash
|
|
465
515
|
vp pack
|
|
@@ -467,11 +517,11 @@ vp pack
|
|
|
467
517
|
|
|
468
518
|
Produces **`dist/`** (ESM + `.d.mts`). The playground and any `file:` consumer need a successful pack.
|
|
469
519
|
|
|
470
|
-
**CI:** Pushes and pull requests against **`main`** run [`.github/workflows/ci.yml`](./.github/workflows/ci.yml):
|
|
520
|
+
**CI:** Pushes and pull requests against **`main`** run [`.github/workflows/ci.yml`](./.github/workflows/ci.yml): **`actions/checkout@v6`**, **`voidzero-dev/setup-vp`** (Node **24**), **`npm install --prefix playground`**, **`vp run check && vp run check:playground`**, **`vp test`**, **`vp pack`**.
|
|
471
521
|
|
|
472
522
|
#### 2. Visual / manual test in the browser (playground)
|
|
473
523
|
|
|
474
|
-
The **[playground](./playground/)** app
|
|
524
|
+
The **[playground](./playground/)** app aliases **`neko-vue`** to **`../src/index.ts`** in **`playground/vite.config.ts`** so local edits hit the library source without reinstalling. Published consumers still use **`dist/`** via **`package.json` `exports`**. The playground uses **Vue Router** so each integration style has its **own route** (one pet on screen at a time):
|
|
475
525
|
|
|
476
526
|
| Route | Demo file | What it shows |
|
|
477
527
|
| ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
@@ -505,14 +555,14 @@ More detail: [playground/README.md](./playground/README.md).
|
|
|
505
555
|
|
|
506
556
|
#### 3. Try it inside another Vue app on your machine
|
|
507
557
|
|
|
508
|
-
- **Option A — `npm pack` / `pnpm pack`:** From the repo root, run `vp pack`, then `npm pack` (or equivalent). In your app, install the generated `.tgz` (e.g. `npm install ../path/to/neko-vue-0.
|
|
558
|
+
- **Option A — `npm pack` / `pnpm pack`:** From the repo root, run `vp pack`, then `npm pack` (or equivalent). In your app, install the generated `.tgz` (e.g. `npm install ../path/to/neko-vue-0.1.0.tgz`; the filename matches **`version`** in root `package.json`).
|
|
509
559
|
- **Option B — `file:` dependency:** Point your app’s `package.json` at the folder that contains a built **`dist/`** (same as publishing layout).
|
|
510
560
|
|
|
511
561
|
Ensure **`vp pack`** has been run so `exports` and types resolve.
|
|
512
562
|
|
|
513
563
|
### Package entry shape
|
|
514
564
|
|
|
515
|
-
**neko-vue**
|
|
565
|
+
**neko-vue** is one npm package with a root export (`"."` → `dist/index.mjs`) plus conditional **`exports`** subpaths **`/types`**, **`/placement`**, **`/runtime`**, **`/vue`** (each with **`types`** + **`import`**) — see [Subpath imports](#subpath-imports). A dedicated **Nuxt module** would still typically be a **separate package** if you want zero-config Nuxt integration beyond the steps in [Nuxt 4](#4-nuxt-4).
|
|
516
566
|
|
|
517
567
|
---
|
|
518
568
|
|
|
@@ -522,5 +572,6 @@ Ensure **`vp pack`** has been run so `exports` and types resolve.
|
|
|
522
572
|
vp install
|
|
523
573
|
vp test
|
|
524
574
|
vp pack
|
|
525
|
-
vp check
|
|
575
|
+
vp run check
|
|
576
|
+
vp run check:playground
|
|
526
577
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neko-vue",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Vue 3 desktop pet — typed runtime, composable, and NekoPet component.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"composable",
|
|
@@ -67,13 +67,17 @@
|
|
|
67
67
|
"check": "vp check src tests vite.config.ts",
|
|
68
68
|
"check:playground": "vp check playground/src playground/vite.config.ts",
|
|
69
69
|
"check:all": "vp check src tests vite.config.ts && vp check playground/src playground/vite.config.ts",
|
|
70
|
-
"prepublishOnly": "vp run build"
|
|
70
|
+
"prepublishOnly": "vp run build",
|
|
71
|
+
"release": "commit-and-tag-version"
|
|
71
72
|
},
|
|
72
73
|
"devDependencies": {
|
|
74
|
+
"@commitlint/cli": "^20.5.0",
|
|
75
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
73
76
|
"@types/node": "^25.5.2",
|
|
74
77
|
"@typescript/native-preview": "7.0.0-dev.20260404.1",
|
|
75
78
|
"@vue/test-utils": "^2.4.6",
|
|
76
79
|
"bumpp": "^11.0.1",
|
|
80
|
+
"commit-and-tag-version": "^12.7.1",
|
|
77
81
|
"happy-dom": "^20.8.9",
|
|
78
82
|
"typescript": "^6.0.2",
|
|
79
83
|
"vite-plus": "^0.1.15",
|