<path d="M15 2.005h2v5h-2z" fill="currentColor"></path>
</svg>
</button>
+
+ <p>Counter :{{ counterStore.n }}</p>
+
+ <button @click="counterStore.increment">Increment</button>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watchEffect } from 'vue'
+import { useCounter } from '../stores/counter'
const isBrowser = typeof window !== 'undefined'
return !window.matchMedia(PREFERS_LIGHT).matches
}
+const counterStore = useCounter()
+
const storageKey = 'pinia-color-scheme'
const localIsDark = ref(isDarkMode())
--- /dev/null
+import { defineStore } from '../../../src'
+import { useUserStore } from './user'
+
+export const useCartStore = defineStore({
+ id: 'cart',
+ state: () => ({
+ rawItems: [] as string[],
+ }),
+ getters: {
+ items: (state) =>
+ state.rawItems.reduce((items, item) => {
+ const existingItem = items.find((it) => it.name === item)
+
+ if (!existingItem) {
+ items.push({ name: item, amount: 1 })
+ } else {
+ existingItem.amount++
+ }
+
+ return items
+ }, [] as Array<{ name: string; amount: number }>),
+ },
+ actions: {
+ addItem(name: string) {
+ this.rawItems.push(name)
+ },
+
+ removeItem(name: string) {
+ const i = this.rawItems.lastIndexOf(name)
+ if (i > -1) this.rawItems.splice(i, 1)
+ },
+
+ async purchaseItems() {
+ const user = useUserStore()
+ if (!user.name) return
+
+ console.log('Purchasing', this.items)
+ const n = this.items.length
+ this.rawItems = []
+
+ return n
+ },
+ },
+})
--- /dev/null
+import { defineStore } from '../../../src'
+
+const delay = (t: number) => new Promise((r) => setTimeout(r, t))
+
+export const useCounter = defineStore({
+ id: 'counter',
+
+ state: () => ({
+ n: 0,
+ incrementedTimes: 0,
+ decrementedTimes: 0,
+ }),
+
+ getters: {
+ double: (state) => state.n * 2,
+ },
+
+ actions: {
+ increment(amount = 1) {
+ if (typeof amount !== 'number') {
+ amount = 1
+ }
+ this.incrementedTimes++
+ this.n += amount
+ },
+
+ async decrementToZero(interval: number = 300, usePatch = true) {
+ if (this.n <= 0) return
+
+ while (this.n > 0) {
+ if (usePatch) {
+ this.$patch({
+ n: this.n - 1,
+ decrementedTimes: this.decrementedTimes + 1,
+ })
+ // this.$patch(state => {
+ // state.n--
+ // state.decrementedTimes++
+ // })
+ } else {
+ this.n--
+ }
+ await delay(interval)
+ }
+ },
+ },
+})
--- /dev/null
+import { defineStore } from '../../../src'
+
+export const useUserStore = defineStore({
+ id: 'user',
+ state: () => ({
+ name: 'Eduardo',
+ isAdmin: true,
+ }),
+ actions: {
+ /**
+ * Attempt to login a user
+ */
+ async login(user: string, password: string) {
+ const userData = await apiLogin(user, password)
+
+ this.patch({
+ name: user,
+ ...userData,
+ })
+ },
+ logout() {
+ this.patch({
+ name: '',
+ isAdmin: false,
+ })
+
+ // we could do other stuff like redirecting the user
+ },
+ },
+})
+
+/**
+ * Simulate a login
+ */
+function apiLogin(a: string, p: string) {
+ if (a === 'ed' && p === 'ed') return Promise.resolve({ isAdmin: true })
+ if (p === 'ed') return Promise.resolve({ isAdmin: false })
+ return Promise.reject(new Error('invalid credentials'))
+}
import Theme from 'vitepress/theme'
import './custom.css'
import './code-theme.css'
+import { createPinia } from '../../../src'
const { Layout } = Theme
/** @type {import('vitepress').Theme} */
const config = {
...Theme,
+ enhanceApp({ app }) {
+ app.use(createPinia())
+ },
}
export default config
--- /dev/null
+import { defineConfig } from 'vite'
+
+console.log('loaded config')
+
+export default defineConfig({
+ define: {
+ __DEV__: 'true',
+ __BROWSER__: 'true',
+ },
+})