@sigrea/vue 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,7 @@
33
33
  npm install @sigrea/vue @sigrea/core vue
34
34
  ```
35
35
 
36
- Requires Vue 3.4+ and Node.js 20 or later.
36
+ Requires Vue 3.4+ and Node.js 24 or later.
37
37
 
38
38
  ## Quick Start
39
39
 
@@ -57,20 +57,36 @@ const value = useSignal(count);
57
57
 
58
58
  ```ts
59
59
  // CounterMolecule.ts
60
- import { molecule, signal } from "@sigrea/core";
60
+ import { molecule, readonly, signal } from "@sigrea/core";
61
61
 
62
- export const CounterMolecule = molecule((props: { initialCount: number }) => {
62
+ type CounterProps = {
63
+ initialCount: number;
64
+ initialStep: number;
65
+ };
66
+
67
+ export const CounterMolecule = molecule((props: CounterProps) => {
63
68
  const count = signal(props.initialCount);
69
+ const step = signal(props.initialStep);
64
70
 
65
- const increment = () => {
66
- count.value += 1;
67
- };
71
+ function setStep(next: number) {
72
+ step.value = next;
73
+ }
74
+
75
+ function increment() {
76
+ count.value += step.value;
77
+ }
68
78
 
69
- const reset = () => {
79
+ function reset() {
70
80
  count.value = props.initialCount;
71
- };
81
+ }
72
82
 
73
- return { count, increment, reset };
83
+ return {
84
+ count: readonly(count),
85
+ step: readonly(step),
86
+ setStep,
87
+ increment,
88
+ reset,
89
+ };
74
90
  });
75
91
  ```
76
92
 
@@ -80,16 +96,23 @@ export const CounterMolecule = molecule((props: { initialCount: number }) => {
80
96
  import { useMolecule, useSignal } from "@sigrea/vue";
81
97
  import { CounterMolecule } from "./CounterMolecule";
82
98
 
83
- const props = defineProps<{ initialCount: number }>();
84
- const counter = useMolecule(CounterMolecule, props);
85
- const value = useSignal(counter.count);
99
+ const props = defineProps<{ initialCount: number; initialStep: number }>();
100
+
101
+ const counter = useMolecule(CounterMolecule, {
102
+ initialCount: props.initialCount,
103
+ initialStep: props.initialStep,
104
+ });
105
+
106
+ const count = useSignal(counter.count);
107
+ const step = useSignal(counter.step);
86
108
  </script>
87
109
 
88
110
  <template>
89
111
  <div>
90
- <span>{{ value }}</span>
112
+ <span>{{ count }}</span>
91
113
  <button @click="counter.increment">Increment</button>
92
114
  <button @click="counter.reset">Reset</button>
115
+ <button @click="counter.setStep(step + 1)">Step +</button>
93
116
  </div>
94
117
  </template>
95
118
  ```
@@ -122,7 +145,7 @@ const model = useMutableSignal(count);
122
145
  import { deepSignal } from "@sigrea/core";
123
146
  import { useDeepSignal } from "@sigrea/vue";
124
147
 
125
- const profile = deepSignal({ name: "Sigrea" });
148
+ const profile = deepSignal({ name: "Mendako" });
126
149
  const model = useDeepSignal(profile);
127
150
  </script>
128
151
 
@@ -140,11 +163,11 @@ const model = useDeepSignal(profile);
140
163
 
141
164
  ```ts
142
165
  function useSignal<T>(
143
- signal: Signal<T> | ReadonlySignal<T>
166
+ signal: Signal<T> | ReadonlySignal<T> | Computed<T>
144
167
  ): DeepReadonly<ShallowRef<T>>
145
168
  ```
146
169
 
147
- Subscribes to a signal or computed value and returns a readonly Vue ref that updates when the signal changes. The subscription is cleaned up when the component unmounts.
170
+ Subscribes to a signal or computed value and returns a readonly Vue ref that updates when the signal changes. The subscription is cleaned up when the component unmounts, or after server rendering, including any `onServerPrefetch()` work, completes.
148
171
 
149
172
  ### useComputed
150
173
 
@@ -152,7 +175,7 @@ Subscribes to a signal or computed value and returns a readonly Vue ref that upd
152
175
  function useComputed<T>(source: Computed<T>): DeepReadonly<ShallowRef<T>>
153
176
  ```
154
177
 
155
- Subscribes to a computed value and returns a readonly Vue ref that updates when the computed value changes. The subscription is cleaned up when the component unmounts.
178
+ Subscribes to a computed value and returns a readonly Vue ref that updates when the computed value changes. The subscription is cleaned up when the component unmounts, or after server rendering, including any `onServerPrefetch()` work, completes.
156
179
 
157
180
  ### useDeepSignal
158
181
 
@@ -160,7 +183,7 @@ Subscribes to a computed value and returns a readonly Vue ref that updates when
160
183
  function useDeepSignal<T extends object>(signal: DeepSignal<T>): ShallowRef<T>
161
184
  ```
162
185
 
163
- Subscribes to a deep signal and returns a mutable Vue ref. Updates to the deep signal trigger reactivity, and the subscription is cleaned up when the component unmounts. Templates unwrap the ref automatically, so accessing nested properties requires no `.value`. In script blocks, use `state.value` to access the underlying object.
186
+ Subscribes to a deep signal and returns a mutable Vue ref. Updates to the deep signal trigger reactivity, and the subscription is cleaned up when the component unmounts, or after server rendering, including any `onServerPrefetch()` work, completes. Templates unwrap the ref automatically, so accessing nested properties requires no `.value`. In script blocks, use `state.value` to access the underlying object.
164
187
 
165
188
  ### useMutableSignal
166
189
 
@@ -173,7 +196,7 @@ Wraps a Sigrea signal as a Vue `WritableComputedRef` for two-way bindings like `
173
196
  ### useMolecule
174
197
 
175
198
  ```ts
176
- function useMolecule<TReturn extends object, TProps = void>(
199
+ function useMolecule<TReturn extends object, TProps extends object | void = void>(
177
200
  molecule: MoleculeFactory<TReturn, TProps>,
178
201
  ...args: MoleculeArgs<TProps>
179
202
  ): MoleculeInstance<TReturn>
@@ -181,6 +204,24 @@ function useMolecule<TReturn extends object, TProps = void>(
181
204
 
182
205
  Mounts a molecule factory and returns its MoleculeInstance. Sigrea augments the molecule with lifecycle metadata: `onMount` callbacks run after the component mounts, and `onUnmount` callbacks run before it unmounts.
183
206
 
207
+ **Server Rendering**
208
+
209
+ During server rendering, `useMolecule` creates the molecule instance for the render pass but does not mount it. `onMount`, `watch`, `watchEffect`, `onActivated`, and `onDeactivated` do not run on the server. Unmounted instances created during SSR are disposed automatically in a microtask after server rendering, including any `onServerPrefetch()` work, completes.
210
+
211
+ **KeepAlive Support**
212
+
213
+ When used inside Vue's `<KeepAlive>`, molecule side effects are automatically managed for optimal resource efficiency:
214
+
215
+ - **On deactivation** (`onDeactivated`): `watch` effects and ongoing work are paused via `unmountMolecule`. The molecule instance itself remains alive, preserving its internal state.
216
+ - **On reactivation** (`onActivated`): Side effects resume via `mountMolecule`, allowing watches and subscriptions to pick up where they left off.
217
+ - **On final unmount**: The molecule is fully disposed via `disposeMolecule`, releasing all resources.
218
+
219
+ This design prevents unnecessary computation and subscriptions while components are cached but invisible, reducing CPU and memory usage without losing state.
220
+
221
+ **Props Handling**
222
+
223
+ Props are treated as an initial snapshot. Updating component props does not recreate the molecule instance or update the snapshot; model dynamic values via signals or explicit molecule methods (for example, `setStep`).
224
+
184
225
  ## Testing
185
226
 
186
227
  ```ts
@@ -227,7 +268,7 @@ createApp(App).mount("#app");
227
268
 
228
269
  ## Development
229
270
 
230
- This repo targets Node.js 20 or later.
271
+ This repo targets Node.js 24 or later.
231
272
 
232
273
  If you use mise:
233
274
 
package/dist/index.cjs CHANGED
@@ -3,15 +3,145 @@
3
3
  const vue = require('vue');
4
4
  const core = require('@sigrea/core');
5
5
 
6
+ const IS_SERVER = typeof window === "undefined";
7
+ const cleanupStates = /* @__PURE__ */ new WeakMap();
8
+ const wrappedSsrRenderComponents = /* @__PURE__ */ new WeakSet();
9
+ function getCleanupState(instance) {
10
+ const existing = cleanupStates.get(instance);
11
+ if (existing !== void 0) {
12
+ return existing;
13
+ }
14
+ const state = {
15
+ cleanups: [],
16
+ registered: false,
17
+ renderWrapped: false,
18
+ flushed: false
19
+ };
20
+ cleanupStates.set(instance, state);
21
+ return state;
22
+ }
23
+ function flushSsrCleanups(instance, state) {
24
+ if (state.flushed) {
25
+ return;
26
+ }
27
+ state.flushed = true;
28
+ cleanupStates.delete(instance);
29
+ const errors = [];
30
+ const cleanups = state.cleanups.splice(0);
31
+ for (const cleanup of cleanups) {
32
+ try {
33
+ cleanup();
34
+ } catch (error) {
35
+ errors.push(error);
36
+ }
37
+ }
38
+ if (errors.length === 1) {
39
+ throw errors[0];
40
+ }
41
+ if (errors.length > 1) {
42
+ throw new AggregateError(errors, "Failed to run SSR cleanups.");
43
+ }
44
+ }
45
+ function queueSsrCleanup(instance, state) {
46
+ queueMicrotask(() => {
47
+ flushSsrCleanups(instance, state);
48
+ });
49
+ }
50
+ function wrapInstanceRender(instance, state) {
51
+ if (state.renderWrapped || state.flushed) {
52
+ return;
53
+ }
54
+ const renderInstance = instance;
55
+ const render = renderInstance.render;
56
+ if (typeof render !== "function") {
57
+ return;
58
+ }
59
+ state.renderWrapped = true;
60
+ renderInstance.render = ((...args) => {
61
+ try {
62
+ return render(...args);
63
+ } finally {
64
+ queueSsrCleanup(instance, state);
65
+ }
66
+ });
67
+ }
68
+ function wrapComponentSsrRender(component) {
69
+ if (wrappedSsrRenderComponents.has(component)) {
70
+ return;
71
+ }
72
+ const ssrRender = component.ssrRender;
73
+ if (typeof ssrRender !== "function") {
74
+ return;
75
+ }
76
+ wrappedSsrRenderComponents.add(component);
77
+ component.ssrRender = ((...args) => {
78
+ const instance = vue.getCurrentInstance();
79
+ const state = instance === null ? void 0 : cleanupStates.get(instance);
80
+ try {
81
+ return ssrRender(...args);
82
+ } finally {
83
+ if (instance !== null && state !== void 0) {
84
+ queueSsrCleanup(instance, state);
85
+ }
86
+ }
87
+ });
88
+ }
89
+ function registerSsrCleanup(cleanup) {
90
+ if (!IS_SERVER) {
91
+ return;
92
+ }
93
+ const instance = vue.getCurrentInstance();
94
+ if (instance === null) {
95
+ return;
96
+ }
97
+ const state = getCleanupState(instance);
98
+ state.cleanups.push(cleanup);
99
+ if (state.registered) {
100
+ return;
101
+ }
102
+ state.registered = true;
103
+ vue.onServerPrefetch(() => {
104
+ wrapInstanceRender(instance, state);
105
+ wrapComponentSsrRender(instance.type);
106
+ });
107
+ }
108
+
6
109
  function useMolecule(molecule, ...args) {
7
110
  if (vue.getCurrentInstance() === null) {
8
111
  throw new Error(
9
112
  "useMolecule can only be used within a Vue component setup()."
10
113
  );
11
114
  }
12
- const instance = molecule(...args);
13
- vue.onScopeDispose(() => {
115
+ const props = args.length === 0 ? void 0 : args[0];
116
+ if (props !== void 0 && (typeof props !== "object" || props === null)) {
117
+ throw new TypeError("useMolecule props must be an object.");
118
+ }
119
+ const snapshot = props === void 0 ? void 0 : { ...vue.toRaw(props) };
120
+ const moleculeArgs = snapshot === void 0 ? [] : [snapshot];
121
+ const instance = molecule(...moleculeArgs);
122
+ const disposeState = { disposed: false };
123
+ const dispose = () => {
124
+ if (disposeState.disposed) {
125
+ return;
126
+ }
127
+ disposeState.disposed = true;
14
128
  core.disposeMolecule(instance);
129
+ };
130
+ registerSsrCleanup(dispose);
131
+ vue.onMounted(() => {
132
+ core.mountMolecule(instance);
133
+ });
134
+ vue.onActivated(() => {
135
+ core.mountMolecule(instance);
136
+ });
137
+ vue.onDeactivated(() => {
138
+ core.unmountMolecule(instance);
139
+ });
140
+ vue.onBeforeUnmount(() => {
141
+ core.unmountMolecule(instance);
142
+ });
143
+ vue.onScopeDispose(() => {
144
+ dispose();
15
145
  });
16
146
  return instance;
17
147
  }
@@ -32,8 +162,17 @@ function useSnapshot(handler, options) {
32
162
  vue.triggerRef(state);
33
163
  };
34
164
  const unsubscribe = handler.subscribe(update);
35
- vue.onScopeDispose(() => {
165
+ const unsubscribeState = { active: true };
166
+ const cleanup = () => {
167
+ if (!unsubscribeState.active) {
168
+ return;
169
+ }
170
+ unsubscribeState.active = false;
36
171
  unsubscribe();
172
+ };
173
+ registerSsrCleanup(cleanup);
174
+ vue.onScopeDispose(() => {
175
+ cleanup();
37
176
  });
38
177
  if (options?.mode === "mutable") {
39
178
  return state;
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
5
+ declare function useMolecule<TReturn extends object, TProps extends object | void = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
5
+ declare function useMolecule<TReturn extends object, TProps extends object | void = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { MoleculeFactory, MoleculeArgs, MoleculeInstance, Signal, ReadonlySignal
2
2
  import * as vue from 'vue';
3
3
  import { DeepReadonly, ShallowRef } from 'vue';
4
4
 
5
- declare function useMolecule<TReturn extends object, TProps = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
5
+ declare function useMolecule<TReturn extends object, TProps extends object | void = void>(molecule: MoleculeFactory<TReturn, TProps>, ...args: MoleculeArgs<TProps>): MoleculeInstance<TReturn>;
6
6
 
7
7
  type ReadableSignal<T> = Signal<T> | ReadonlySignal<T>;
8
8
  declare function useSignal<T>(source: ReadableSignal<T>): Readonly<vue.Ref<vue.DeepReadonly<T>, vue.DeepReadonly<T>>>;
package/dist/index.mjs CHANGED
@@ -1,5 +1,108 @@
1
- import { getCurrentInstance, onScopeDispose, shallowRef, readonly, triggerRef, computed } from 'vue';
2
- import { disposeMolecule, createSignalHandler, createComputedHandler, createDeepSignalHandler } from '@sigrea/core';
1
+ import { getCurrentInstance, onServerPrefetch, toRaw, onMounted, onActivated, onDeactivated, onBeforeUnmount, onScopeDispose, shallowRef, readonly, triggerRef, computed } from 'vue';
2
+ import { mountMolecule, unmountMolecule, disposeMolecule, createSignalHandler, createComputedHandler, createDeepSignalHandler } from '@sigrea/core';
3
+
4
+ const IS_SERVER = typeof window === "undefined";
5
+ const cleanupStates = /* @__PURE__ */ new WeakMap();
6
+ const wrappedSsrRenderComponents = /* @__PURE__ */ new WeakSet();
7
+ function getCleanupState(instance) {
8
+ const existing = cleanupStates.get(instance);
9
+ if (existing !== void 0) {
10
+ return existing;
11
+ }
12
+ const state = {
13
+ cleanups: [],
14
+ registered: false,
15
+ renderWrapped: false,
16
+ flushed: false
17
+ };
18
+ cleanupStates.set(instance, state);
19
+ return state;
20
+ }
21
+ function flushSsrCleanups(instance, state) {
22
+ if (state.flushed) {
23
+ return;
24
+ }
25
+ state.flushed = true;
26
+ cleanupStates.delete(instance);
27
+ const errors = [];
28
+ const cleanups = state.cleanups.splice(0);
29
+ for (const cleanup of cleanups) {
30
+ try {
31
+ cleanup();
32
+ } catch (error) {
33
+ errors.push(error);
34
+ }
35
+ }
36
+ if (errors.length === 1) {
37
+ throw errors[0];
38
+ }
39
+ if (errors.length > 1) {
40
+ throw new AggregateError(errors, "Failed to run SSR cleanups.");
41
+ }
42
+ }
43
+ function queueSsrCleanup(instance, state) {
44
+ queueMicrotask(() => {
45
+ flushSsrCleanups(instance, state);
46
+ });
47
+ }
48
+ function wrapInstanceRender(instance, state) {
49
+ if (state.renderWrapped || state.flushed) {
50
+ return;
51
+ }
52
+ const renderInstance = instance;
53
+ const render = renderInstance.render;
54
+ if (typeof render !== "function") {
55
+ return;
56
+ }
57
+ state.renderWrapped = true;
58
+ renderInstance.render = ((...args) => {
59
+ try {
60
+ return render(...args);
61
+ } finally {
62
+ queueSsrCleanup(instance, state);
63
+ }
64
+ });
65
+ }
66
+ function wrapComponentSsrRender(component) {
67
+ if (wrappedSsrRenderComponents.has(component)) {
68
+ return;
69
+ }
70
+ const ssrRender = component.ssrRender;
71
+ if (typeof ssrRender !== "function") {
72
+ return;
73
+ }
74
+ wrappedSsrRenderComponents.add(component);
75
+ component.ssrRender = ((...args) => {
76
+ const instance = getCurrentInstance();
77
+ const state = instance === null ? void 0 : cleanupStates.get(instance);
78
+ try {
79
+ return ssrRender(...args);
80
+ } finally {
81
+ if (instance !== null && state !== void 0) {
82
+ queueSsrCleanup(instance, state);
83
+ }
84
+ }
85
+ });
86
+ }
87
+ function registerSsrCleanup(cleanup) {
88
+ if (!IS_SERVER) {
89
+ return;
90
+ }
91
+ const instance = getCurrentInstance();
92
+ if (instance === null) {
93
+ return;
94
+ }
95
+ const state = getCleanupState(instance);
96
+ state.cleanups.push(cleanup);
97
+ if (state.registered) {
98
+ return;
99
+ }
100
+ state.registered = true;
101
+ onServerPrefetch(() => {
102
+ wrapInstanceRender(instance, state);
103
+ wrapComponentSsrRender(instance.type);
104
+ });
105
+ }
3
106
 
4
107
  function useMolecule(molecule, ...args) {
5
108
  if (getCurrentInstance() === null) {
@@ -7,9 +110,36 @@ function useMolecule(molecule, ...args) {
7
110
  "useMolecule can only be used within a Vue component setup()."
8
111
  );
9
112
  }
10
- const instance = molecule(...args);
11
- onScopeDispose(() => {
113
+ const props = args.length === 0 ? void 0 : args[0];
114
+ if (props !== void 0 && (typeof props !== "object" || props === null)) {
115
+ throw new TypeError("useMolecule props must be an object.");
116
+ }
117
+ const snapshot = props === void 0 ? void 0 : { ...toRaw(props) };
118
+ const moleculeArgs = snapshot === void 0 ? [] : [snapshot];
119
+ const instance = molecule(...moleculeArgs);
120
+ const disposeState = { disposed: false };
121
+ const dispose = () => {
122
+ if (disposeState.disposed) {
123
+ return;
124
+ }
125
+ disposeState.disposed = true;
12
126
  disposeMolecule(instance);
127
+ };
128
+ registerSsrCleanup(dispose);
129
+ onMounted(() => {
130
+ mountMolecule(instance);
131
+ });
132
+ onActivated(() => {
133
+ mountMolecule(instance);
134
+ });
135
+ onDeactivated(() => {
136
+ unmountMolecule(instance);
137
+ });
138
+ onBeforeUnmount(() => {
139
+ unmountMolecule(instance);
140
+ });
141
+ onScopeDispose(() => {
142
+ dispose();
13
143
  });
14
144
  return instance;
15
145
  }
@@ -30,8 +160,17 @@ function useSnapshot(handler, options) {
30
160
  triggerRef(state);
31
161
  };
32
162
  const unsubscribe = handler.subscribe(update);
33
- onScopeDispose(() => {
163
+ const unsubscribeState = { active: true };
164
+ const cleanup = () => {
165
+ if (!unsubscribeState.active) {
166
+ return;
167
+ }
168
+ unsubscribeState.active = false;
34
169
  unsubscribe();
170
+ };
171
+ registerSsrCleanup(cleanup);
172
+ onScopeDispose(() => {
173
+ cleanup();
35
174
  });
36
175
  if (options?.mode === "mutable") {
37
176
  return state;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigrea/vue",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Vue adapter bindings for Sigrea molecule modules.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  "url": "https://github.com/sigrea/vue/issues"
18
18
  },
19
19
  "engines": {
20
- "node": ">=20"
20
+ "node": ">=24"
21
21
  },
22
22
  "sideEffects": false,
23
23
  "exports": {
@@ -29,16 +29,8 @@
29
29
  },
30
30
  "main": "./dist/index.cjs",
31
31
  "types": "./dist/index.d.ts",
32
- "files": [
33
- "dist"
34
- ],
35
- "keywords": [
36
- "signals",
37
- "reactivity",
38
- "vue",
39
- "molecule",
40
- "typescript"
41
- ],
32
+ "files": ["dist"],
33
+ "keywords": ["signals", "reactivity", "vue", "molecule", "typescript"],
42
34
  "scripts": {
43
35
  "dev": "vite --config playground/vite.config.ts",
44
36
  "build": "unbuild",
@@ -53,28 +45,27 @@
53
45
  "cicheck": "pnpm test && pnpm typecheck && pnpm format:fix"
54
46
  },
55
47
  "peerDependencies": {
56
- "@sigrea/core": "^0.4.3",
48
+ "@sigrea/core": "^0.6.0",
57
49
  "vue": "^3.4.0"
58
50
  },
59
51
  "devDependencies": {
60
52
  "@biomejs/biome": "1.9.4",
53
+ "@sigrea/core": "^0.6.0",
61
54
  "@vitejs/plugin-vue": "^5.1.4",
62
- "@vue/test-utils": "^2.4.0",
63
55
  "@vitest/coverage-v8": "^3.2.4",
56
+ "@vue/test-utils": "^2.4.0",
57
+ "baseline-browser-mapping": "^2.9.13",
64
58
  "changelogen": "^0.6.2",
59
+ "jsdom": "^24.1.3",
65
60
  "lefthook": "1.13.6",
66
61
  "tsx": "^4.20.5",
67
62
  "typescript": "5.9.3",
68
63
  "unbuild": "3.6.1",
69
64
  "vite": "^5.4.6",
70
65
  "vitest": "^3.2.4",
71
- "vue": "^3.4.0",
72
- "jsdom": "^24.1.3"
66
+ "vue": "^3.4.0"
73
67
  },
74
68
  "pnpm": {
75
- "onlyBuiltDependencies": [
76
- "lefthook",
77
- "@biomejs/biome"
78
- ]
69
+ "onlyBuiltDependencies": ["lefthook", "@biomejs/biome"]
79
70
  }
80
71
  }