@sigrea/vue adapts @sigrea/core logic modules and signals to Vue 3’s Composition API. It keeps lifecycle scopes aligned with component mounts, forwards deep reactivity, and ships composables that feel first-class inside <script setup> or traditional setup functions.
pnpm add @sigrea/vue @sigrea/core vueVue 3.4+ and Node.js 20+ are required. Equivalent npm or yarn commands work as expected.
- Signal readers –
useSignalconsumes shallow signals and computed values inside Vue components. - Deep signal access –
useDeepSignalexposes deeply reactive objects with automatic cleanup. - Derived state –
useComputedmirrors Vue’scomputed, but tracks through Sigrea scopes. - Logic lifecycles –
useLogicmountsdefineLogicfactories while honoringonMount/onUnmount. - Snapshots –
useSnapshotgrants direct access to low-level signal handlers when needed. - Writable bridge –
useMutableSignalexposes primitivesignal()values asWritableComputedRefs for two-way bindings.
<script setup lang="ts">
import { signal } from "@sigrea/core";
import { useSignal } from "@sigrea/vue";
const count = signal(0);
const value = useSignal(count);
</script>
<template>
<span>{{ value }}</span>
</template>// CounterLogic.ts
import { defineLogic, signal } from "@sigrea/core";
export const CounterLogic = defineLogic<{ initialCount: number }>()((props) => {
const count = signal(props.initialCount);
const increment = () => {
count.value += 1;
};
const reset = () => {
count.value = props.initialCount;
};
return { count, increment, reset };
});// Counter.vue
<script setup lang="ts">
import { useLogic, useSignal } from "@sigrea/vue";
import { CounterLogic } from "./CounterLogic";
const props = defineProps<{ initialCount: number }>();
const counter = useLogic(CounterLogic, props);
const value = useSignal(counter.count);
</script>
<template>
<div>
<span>{{ value }}</span>
<button @click="counter.increment">Increment</button>
<button @click="counter.reset">Reset</button>
</div>
</template><script setup lang="ts">
import { signal } from "@sigrea/core";
import { useMutableSignal } from "@sigrea/vue";
const count = signal(0);
const model = useMutableSignal(count);
</script>
<template>
<label>
Count
<input type="number" v-model.number="model" />
</label>
</template>useMutableSignal expects a writable signal produced by signal(). Passing a readonly signal throws at runtime so incorrect bindings fail fast.
<script setup lang="ts">
import { deepSignal } from "@sigrea/core";
import { useDeepSignal } from "@sigrea/vue";
const profile = deepSignal({ name: "Sigrea" });
const model = useDeepSignal(profile);
</script>
<template>
<label>
Name
<input v-model="model.name" />
</label>
</template>pnpm install– install dependenciespnpm test– run the Vitest suitepnpm build– emit distributable artifactspnpm dev– launch the playground counter demo
MIT — see LICENSE.