seitu 0.15.1 → 0.16.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/dist/solid.d.mts +170 -0
- package/dist/solid.mjs +180 -0
- package/dist/svelte.d.mts +77 -0
- package/dist/svelte.mjs +91 -0
- package/package.json +32 -8
- package/skills/README.md +30 -40
- package/skills/seitu/SKILL.md +92 -0
- package/skills/{create-computed/SKILL.md → seitu/references/create-computed.md} +2 -15
- package/skills/{create-debounced-fn/SKILL.md → seitu/references/create-debounced-fn.md} +2 -15
- package/skills/{create-debounced/SKILL.md → seitu/references/create-debounced.md} +2 -15
- package/skills/{create-indexed-db-storage/SKILL.md → seitu/references/create-indexed-db-storage.md} +2 -15
- package/skills/{create-is-online/SKILL.md → seitu/references/create-is-online.md} +2 -15
- package/skills/{create-media-query/SKILL.md → seitu/references/create-media-query.md} +2 -15
- package/skills/{create-readable-subscription/SKILL.md → seitu/references/create-readable-subscription.md} +2 -15
- package/skills/{create-schema-store/SKILL.md → seitu/references/create-schema-store.md} +2 -15
- package/skills/{create-scroll-state/SKILL.md → seitu/references/create-scroll-state.md} +2 -15
- package/skills/{create-store/SKILL.md → seitu/references/create-store.md} +2 -15
- package/skills/{create-subscription/SKILL.md → seitu/references/create-subscription.md} +2 -14
- package/skills/{create-throttled-fn/SKILL.md → seitu/references/create-throttled-fn.md} +2 -15
- package/skills/{create-throttled/SKILL.md → seitu/references/create-throttled.md} +2 -15
- package/skills/{create-web-storage-value/SKILL.md → seitu/references/create-web-storage-value.md} +2 -15
- package/skills/{create-web-storage/SKILL.md → seitu/references/create-web-storage.md} +3 -17
- package/skills/{use-subscription-react/SKILL.md → seitu/references/react.md} +53 -24
- package/skills/seitu/references/solid.md +172 -0
- package/skills/seitu/references/svelte.md +122 -0
- package/skills/{use-subscription-vue/SKILL.md → seitu/references/vue.md} +9 -20
- package/skills/seitu-overview/SKILL.md +31 -10
- package/skills/subscription-react/SKILL.md +0 -96
package/dist/solid.d.mts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { _ as Readable, v as Subscribable } from "./index-DwN8Up-P.mjs";
|
|
2
|
+
import { Accessor, JSX } from "solid-js";
|
|
3
|
+
|
|
4
|
+
//#region src/solid/hooks.d.ts
|
|
5
|
+
interface UseSubscriptionOptions<S extends Subscribable<any> & Readable<any>, R = S['~']['output']> {
|
|
6
|
+
selector?: (value: S['~']['output']) => R;
|
|
7
|
+
isEqual?: (prev: R, next: R) => boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Use this primitive to subscribe to a reactive value. Accepts a subscription object
|
|
11
|
+
* directly, or an accessor/getter that returns one. The getter is reactive — when it
|
|
12
|
+
* reads a signal, the subscription is recreated and re-subscribed automatically.
|
|
13
|
+
*
|
|
14
|
+
* Returns a Solid `Accessor<R>`: call it (`value()`) to read the current value inside JSX
|
|
15
|
+
* or another reactive scope.
|
|
16
|
+
*
|
|
17
|
+
* @example Inline subscription
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
20
|
+
* import { useSubscription } from 'seitu/solid'
|
|
21
|
+
* import * as z from 'zod'
|
|
22
|
+
*
|
|
23
|
+
* function Counter() {
|
|
24
|
+
* const value = useSubscription(() => createWebStorageValue({
|
|
25
|
+
* type: 'sessionStorage',
|
|
26
|
+
* key: 'test',
|
|
27
|
+
* defaultValue: 0,
|
|
28
|
+
* schema: z.number(),
|
|
29
|
+
* }))
|
|
30
|
+
*
|
|
31
|
+
* return <div>{value()}</div>
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example Instance outside of component
|
|
36
|
+
* ```tsx
|
|
37
|
+
* import { createWebStorage } from 'seitu/web'
|
|
38
|
+
* import { useSubscription } from 'seitu/solid'
|
|
39
|
+
* import * as z from 'zod'
|
|
40
|
+
*
|
|
41
|
+
* const sessionStorage = createWebStorage({
|
|
42
|
+
* type: 'sessionStorage',
|
|
43
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
44
|
+
* defaultValues: { count: 0, name: '' },
|
|
45
|
+
* })
|
|
46
|
+
*
|
|
47
|
+
* function Counter() {
|
|
48
|
+
* const value = useSubscription(sessionStorage)
|
|
49
|
+
* return <div>{value().count}</div>
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example Subscription with selector
|
|
54
|
+
* ```tsx
|
|
55
|
+
* import { createWebStorage } from 'seitu/web'
|
|
56
|
+
* import { useSubscription } from 'seitu/solid'
|
|
57
|
+
* import * as z from 'zod'
|
|
58
|
+
*
|
|
59
|
+
* const sessionStorage = createWebStorage({
|
|
60
|
+
* type: 'sessionStorage',
|
|
61
|
+
* schemas: {
|
|
62
|
+
* count: z.number(),
|
|
63
|
+
* name: z.string(),
|
|
64
|
+
* },
|
|
65
|
+
* defaultValues: { count: 0, name: '' },
|
|
66
|
+
* })
|
|
67
|
+
*
|
|
68
|
+
* function Counter() {
|
|
69
|
+
* // Usage with selector, the accessor only updates when count changes
|
|
70
|
+
* const count = useSubscription(sessionStorage, { selector: value => value.count })
|
|
71
|
+
*
|
|
72
|
+
* return <div>{count()}</div>
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Reactive source (re-subscribes when a signal changes)
|
|
77
|
+
* ```tsx
|
|
78
|
+
* import { createSignal } from 'solid-js'
|
|
79
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
80
|
+
* import { useSubscription } from 'seitu/solid'
|
|
81
|
+
* import * as z from 'zod'
|
|
82
|
+
*
|
|
83
|
+
* function User() {
|
|
84
|
+
* const [userId, setUserId] = createSignal('user-1')
|
|
85
|
+
* const data = useSubscription(() => createWebStorageValue({
|
|
86
|
+
* type: 'localStorage',
|
|
87
|
+
* key: `user:${userId()}`,
|
|
88
|
+
* schema: z.object({ name: z.string() }),
|
|
89
|
+
* defaultValue: { name: '' },
|
|
90
|
+
* }))
|
|
91
|
+
*
|
|
92
|
+
* return <div>{data().name}</div>
|
|
93
|
+
* }
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example Ref example
|
|
97
|
+
* ```tsx
|
|
98
|
+
* import { createScrollState } from 'seitu/web'
|
|
99
|
+
* import { useSubscription } from 'seitu/solid'
|
|
100
|
+
*
|
|
101
|
+
* function Page() {
|
|
102
|
+
* let ref: HTMLDivElement | undefined
|
|
103
|
+
* const state = useSubscription(() => createScrollState({ element: () => ref, direction: 'vertical' }))
|
|
104
|
+
*
|
|
105
|
+
* return (
|
|
106
|
+
* <div ref={ref}>
|
|
107
|
+
* {String(state().top.reached)}
|
|
108
|
+
* </div>
|
|
109
|
+
* )
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
declare function useSubscription<S extends Subscribable<any> & Readable<any>, R = S['~']['output']>(source: S | Accessor<S>, options?: UseSubscriptionOptions<S, R>): Accessor<R>;
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/solid/components.d.ts
|
|
116
|
+
interface SubscriptionProps<S extends Subscribable<any> & Readable<any>, R = S['~']['output']> extends Pick<UseSubscriptionOptions<S, R>, 'selector'> {
|
|
117
|
+
value: S;
|
|
118
|
+
children: (value: Accessor<R>) => JSX.Element;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Declarative component that subscribes to a reactive value and passes an accessor to a render function.
|
|
122
|
+
* Unlike React, the children function runs once and receives a Solid `Accessor<R>` — call it (`value()`)
|
|
123
|
+
* inside the returned JSX so updates stay fine-grained. Use when you prefer a component API over the
|
|
124
|
+
* useSubscription primitive.
|
|
125
|
+
*
|
|
126
|
+
* @example Basic usage
|
|
127
|
+
* ```tsx
|
|
128
|
+
* import { createWebStorage } from 'seitu/web'
|
|
129
|
+
* import { Subscription } from 'seitu/solid'
|
|
130
|
+
* import * as z from 'zod'
|
|
131
|
+
*
|
|
132
|
+
* const sessionStorage = createWebStorage({
|
|
133
|
+
* type: 'sessionStorage',
|
|
134
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
135
|
+
* defaultValues: { count: 0, name: '' },
|
|
136
|
+
* })
|
|
137
|
+
*
|
|
138
|
+
* function Page() {
|
|
139
|
+
* return (
|
|
140
|
+
* <Subscription value={sessionStorage}>
|
|
141
|
+
* {value => <div>{value().count}</div>}
|
|
142
|
+
* </Subscription>
|
|
143
|
+
* )
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @example With selector
|
|
148
|
+
* ```tsx
|
|
149
|
+
* import { createWebStorage } from 'seitu/web'
|
|
150
|
+
* import { Subscription } from 'seitu/solid'
|
|
151
|
+
* import * as z from 'zod'
|
|
152
|
+
*
|
|
153
|
+
* const sessionStorage = createWebStorage({
|
|
154
|
+
* type: 'sessionStorage',
|
|
155
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
156
|
+
* defaultValues: { count: 0, name: '' },
|
|
157
|
+
* })
|
|
158
|
+
*
|
|
159
|
+
* function Page() {
|
|
160
|
+
* return (
|
|
161
|
+
* <Subscription value={sessionStorage} selector={v => v.count}>
|
|
162
|
+
* {count => <div>{count()}</div>}
|
|
163
|
+
* </Subscription>
|
|
164
|
+
* )
|
|
165
|
+
* }
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
declare function Subscription<S extends Subscribable<any> & Readable<any>, R = S['~']['output']>(props: SubscriptionProps<S, R>): JSX.Element;
|
|
169
|
+
//#endregion
|
|
170
|
+
export { Subscription, SubscriptionProps, UseSubscriptionOptions, useSubscription };
|
package/dist/solid.mjs
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { deepEqual } from "fast-equals";
|
|
2
|
+
import { createEffect, createMemo, createSignal, onCleanup } from "solid-js";
|
|
3
|
+
//#region src/solid/hooks.ts
|
|
4
|
+
/**
|
|
5
|
+
* Use this primitive to subscribe to a reactive value. Accepts a subscription object
|
|
6
|
+
* directly, or an accessor/getter that returns one. The getter is reactive — when it
|
|
7
|
+
* reads a signal, the subscription is recreated and re-subscribed automatically.
|
|
8
|
+
*
|
|
9
|
+
* Returns a Solid `Accessor<R>`: call it (`value()`) to read the current value inside JSX
|
|
10
|
+
* or another reactive scope.
|
|
11
|
+
*
|
|
12
|
+
* @example Inline subscription
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
15
|
+
* import { useSubscription } from 'seitu/solid'
|
|
16
|
+
* import * as z from 'zod'
|
|
17
|
+
*
|
|
18
|
+
* function Counter() {
|
|
19
|
+
* const value = useSubscription(() => createWebStorageValue({
|
|
20
|
+
* type: 'sessionStorage',
|
|
21
|
+
* key: 'test',
|
|
22
|
+
* defaultValue: 0,
|
|
23
|
+
* schema: z.number(),
|
|
24
|
+
* }))
|
|
25
|
+
*
|
|
26
|
+
* return <div>{value()}</div>
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Instance outside of component
|
|
31
|
+
* ```tsx
|
|
32
|
+
* import { createWebStorage } from 'seitu/web'
|
|
33
|
+
* import { useSubscription } from 'seitu/solid'
|
|
34
|
+
* import * as z from 'zod'
|
|
35
|
+
*
|
|
36
|
+
* const sessionStorage = createWebStorage({
|
|
37
|
+
* type: 'sessionStorage',
|
|
38
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
39
|
+
* defaultValues: { count: 0, name: '' },
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* function Counter() {
|
|
43
|
+
* const value = useSubscription(sessionStorage)
|
|
44
|
+
* return <div>{value().count}</div>
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example Subscription with selector
|
|
49
|
+
* ```tsx
|
|
50
|
+
* import { createWebStorage } from 'seitu/web'
|
|
51
|
+
* import { useSubscription } from 'seitu/solid'
|
|
52
|
+
* import * as z from 'zod'
|
|
53
|
+
*
|
|
54
|
+
* const sessionStorage = createWebStorage({
|
|
55
|
+
* type: 'sessionStorage',
|
|
56
|
+
* schemas: {
|
|
57
|
+
* count: z.number(),
|
|
58
|
+
* name: z.string(),
|
|
59
|
+
* },
|
|
60
|
+
* defaultValues: { count: 0, name: '' },
|
|
61
|
+
* })
|
|
62
|
+
*
|
|
63
|
+
* function Counter() {
|
|
64
|
+
* // Usage with selector, the accessor only updates when count changes
|
|
65
|
+
* const count = useSubscription(sessionStorage, { selector: value => value.count })
|
|
66
|
+
*
|
|
67
|
+
* return <div>{count()}</div>
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example Reactive source (re-subscribes when a signal changes)
|
|
72
|
+
* ```tsx
|
|
73
|
+
* import { createSignal } from 'solid-js'
|
|
74
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
75
|
+
* import { useSubscription } from 'seitu/solid'
|
|
76
|
+
* import * as z from 'zod'
|
|
77
|
+
*
|
|
78
|
+
* function User() {
|
|
79
|
+
* const [userId, setUserId] = createSignal('user-1')
|
|
80
|
+
* const data = useSubscription(() => createWebStorageValue({
|
|
81
|
+
* type: 'localStorage',
|
|
82
|
+
* key: `user:${userId()}`,
|
|
83
|
+
* schema: z.object({ name: z.string() }),
|
|
84
|
+
* defaultValue: { name: '' },
|
|
85
|
+
* }))
|
|
86
|
+
*
|
|
87
|
+
* return <div>{data().name}</div>
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example Ref example
|
|
92
|
+
* ```tsx
|
|
93
|
+
* import { createScrollState } from 'seitu/web'
|
|
94
|
+
* import { useSubscription } from 'seitu/solid'
|
|
95
|
+
*
|
|
96
|
+
* function Page() {
|
|
97
|
+
* let ref: HTMLDivElement | undefined
|
|
98
|
+
* const state = useSubscription(() => createScrollState({ element: () => ref, direction: 'vertical' }))
|
|
99
|
+
*
|
|
100
|
+
* return (
|
|
101
|
+
* <div ref={ref}>
|
|
102
|
+
* {String(state().top.reached)}
|
|
103
|
+
* </div>
|
|
104
|
+
* )
|
|
105
|
+
* }
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
function useSubscription(source, options) {
|
|
109
|
+
const { selector, isEqual = deepEqual } = options ?? {};
|
|
110
|
+
const getSource = typeof source === "function" ? source : () => source;
|
|
111
|
+
function getSnapshot(sub) {
|
|
112
|
+
return selector ? selector(sub.get()) : sub.get();
|
|
113
|
+
}
|
|
114
|
+
const sub = createMemo(() => getSource());
|
|
115
|
+
const [state, setState] = createSignal(getSnapshot(sub()), { equals: isEqual });
|
|
116
|
+
createEffect(() => {
|
|
117
|
+
const current = sub();
|
|
118
|
+
setState(() => getSnapshot(current));
|
|
119
|
+
onCleanup(current.subscribe(() => {
|
|
120
|
+
setState(() => getSnapshot(current));
|
|
121
|
+
}));
|
|
122
|
+
});
|
|
123
|
+
return state;
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/solid/components.ts
|
|
127
|
+
/**
|
|
128
|
+
* Declarative component that subscribes to a reactive value and passes an accessor to a render function.
|
|
129
|
+
* Unlike React, the children function runs once and receives a Solid `Accessor<R>` — call it (`value()`)
|
|
130
|
+
* inside the returned JSX so updates stay fine-grained. Use when you prefer a component API over the
|
|
131
|
+
* useSubscription primitive.
|
|
132
|
+
*
|
|
133
|
+
* @example Basic usage
|
|
134
|
+
* ```tsx
|
|
135
|
+
* import { createWebStorage } from 'seitu/web'
|
|
136
|
+
* import { Subscription } from 'seitu/solid'
|
|
137
|
+
* import * as z from 'zod'
|
|
138
|
+
*
|
|
139
|
+
* const sessionStorage = createWebStorage({
|
|
140
|
+
* type: 'sessionStorage',
|
|
141
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
142
|
+
* defaultValues: { count: 0, name: '' },
|
|
143
|
+
* })
|
|
144
|
+
*
|
|
145
|
+
* function Page() {
|
|
146
|
+
* return (
|
|
147
|
+
* <Subscription value={sessionStorage}>
|
|
148
|
+
* {value => <div>{value().count}</div>}
|
|
149
|
+
* </Subscription>
|
|
150
|
+
* )
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @example With selector
|
|
155
|
+
* ```tsx
|
|
156
|
+
* import { createWebStorage } from 'seitu/web'
|
|
157
|
+
* import { Subscription } from 'seitu/solid'
|
|
158
|
+
* import * as z from 'zod'
|
|
159
|
+
*
|
|
160
|
+
* const sessionStorage = createWebStorage({
|
|
161
|
+
* type: 'sessionStorage',
|
|
162
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
163
|
+
* defaultValues: { count: 0, name: '' },
|
|
164
|
+
* })
|
|
165
|
+
*
|
|
166
|
+
* function Page() {
|
|
167
|
+
* return (
|
|
168
|
+
* <Subscription value={sessionStorage} selector={v => v.count}>
|
|
169
|
+
* {count => <div>{count()}</div>}
|
|
170
|
+
* </Subscription>
|
|
171
|
+
* )
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
function Subscription(props) {
|
|
176
|
+
const value = useSubscription(() => props.value, { selector: props.selector });
|
|
177
|
+
return props.children(value);
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { Subscription, useSubscription };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { _ as Readable$1, v as Subscribable } from "./index-DwN8Up-P.mjs";
|
|
2
|
+
import { Readable } from "svelte/store";
|
|
3
|
+
|
|
4
|
+
//#region src/svelte/hooks.d.ts
|
|
5
|
+
interface UseSubscriptionOptions<S extends Subscribable<any> & Readable$1<any>, R = S['~']['output']> {
|
|
6
|
+
selector?: (value: S['~']['output']) => R;
|
|
7
|
+
isEqual?: (prev: R, next: R) => boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Use this function to subscribe to a reactive value from a Svelte component.
|
|
11
|
+
* Accepts a subscription object directly, or a factory function that is called
|
|
12
|
+
* once to create one.
|
|
13
|
+
*
|
|
14
|
+
* Returns a Svelte `Readable` store — read it with the `$` auto-subscription
|
|
15
|
+
* (`$value`) in markup. The underlying subscription is created lazily on the
|
|
16
|
+
* first subscriber and torn down when the last one leaves.
|
|
17
|
+
*
|
|
18
|
+
* @example Inline subscription
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <script lang="ts">
|
|
21
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
22
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
23
|
+
* import * as z from 'zod'
|
|
24
|
+
*
|
|
25
|
+
* const value = useSubscription(() => createWebStorageValue({
|
|
26
|
+
* type: 'sessionStorage',
|
|
27
|
+
* key: 'test',
|
|
28
|
+
* defaultValue: 0,
|
|
29
|
+
* schema: z.number(),
|
|
30
|
+
* }))
|
|
31
|
+
* </script>
|
|
32
|
+
*
|
|
33
|
+
* <div>{$value}</div>
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example Instance outside of component
|
|
37
|
+
* ```svelte
|
|
38
|
+
* <script lang="ts">
|
|
39
|
+
* import { createWebStorage } from 'seitu/web'
|
|
40
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
41
|
+
* import * as z from 'zod'
|
|
42
|
+
*
|
|
43
|
+
* const sessionStorage = createWebStorage({
|
|
44
|
+
* type: 'sessionStorage',
|
|
45
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
46
|
+
* defaultValues: { count: 0, name: '' },
|
|
47
|
+
* })
|
|
48
|
+
*
|
|
49
|
+
* const value = useSubscription(sessionStorage)
|
|
50
|
+
* </script>
|
|
51
|
+
*
|
|
52
|
+
* <div>{$value.count}</div>
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @example With selector
|
|
56
|
+
* ```svelte
|
|
57
|
+
* <script lang="ts">
|
|
58
|
+
* import { createWebStorage } from 'seitu/web'
|
|
59
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
60
|
+
* import * as z from 'zod'
|
|
61
|
+
*
|
|
62
|
+
* const sessionStorage = createWebStorage({
|
|
63
|
+
* type: 'sessionStorage',
|
|
64
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
65
|
+
* defaultValues: { count: 0, name: '' },
|
|
66
|
+
* })
|
|
67
|
+
*
|
|
68
|
+
* // Updates only when count changes
|
|
69
|
+
* const count = useSubscription(sessionStorage, { selector: v => v.count })
|
|
70
|
+
* </script>
|
|
71
|
+
*
|
|
72
|
+
* <div>{$count}</div>
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
declare function useSubscription<S extends Subscribable<any> & Readable$1<any>, R = S['~']['output']>(source: S | (() => S), options?: UseSubscriptionOptions<S, R>): Readable<R>;
|
|
76
|
+
//#endregion
|
|
77
|
+
export { UseSubscriptionOptions, useSubscription };
|
package/dist/svelte.mjs
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { deepEqual } from "fast-equals";
|
|
2
|
+
import { readable } from "svelte/store";
|
|
3
|
+
//#region src/svelte/hooks.ts
|
|
4
|
+
/**
|
|
5
|
+
* Use this function to subscribe to a reactive value from a Svelte component.
|
|
6
|
+
* Accepts a subscription object directly, or a factory function that is called
|
|
7
|
+
* once to create one.
|
|
8
|
+
*
|
|
9
|
+
* Returns a Svelte `Readable` store — read it with the `$` auto-subscription
|
|
10
|
+
* (`$value`) in markup. The underlying subscription is created lazily on the
|
|
11
|
+
* first subscriber and torn down when the last one leaves.
|
|
12
|
+
*
|
|
13
|
+
* @example Inline subscription
|
|
14
|
+
* ```svelte
|
|
15
|
+
* <script lang="ts">
|
|
16
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
17
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
18
|
+
* import * as z from 'zod'
|
|
19
|
+
*
|
|
20
|
+
* const value = useSubscription(() => createWebStorageValue({
|
|
21
|
+
* type: 'sessionStorage',
|
|
22
|
+
* key: 'test',
|
|
23
|
+
* defaultValue: 0,
|
|
24
|
+
* schema: z.number(),
|
|
25
|
+
* }))
|
|
26
|
+
* <\/script>
|
|
27
|
+
*
|
|
28
|
+
* <div>{$value}</div>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Instance outside of component
|
|
32
|
+
* ```svelte
|
|
33
|
+
* <script lang="ts">
|
|
34
|
+
* import { createWebStorage } from 'seitu/web'
|
|
35
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
36
|
+
* import * as z from 'zod'
|
|
37
|
+
*
|
|
38
|
+
* const sessionStorage = createWebStorage({
|
|
39
|
+
* type: 'sessionStorage',
|
|
40
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
41
|
+
* defaultValues: { count: 0, name: '' },
|
|
42
|
+
* })
|
|
43
|
+
*
|
|
44
|
+
* const value = useSubscription(sessionStorage)
|
|
45
|
+
* <\/script>
|
|
46
|
+
*
|
|
47
|
+
* <div>{$value.count}</div>
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example With selector
|
|
51
|
+
* ```svelte
|
|
52
|
+
* <script lang="ts">
|
|
53
|
+
* import { createWebStorage } from 'seitu/web'
|
|
54
|
+
* import { useSubscription } from 'seitu/svelte'
|
|
55
|
+
* import * as z from 'zod'
|
|
56
|
+
*
|
|
57
|
+
* const sessionStorage = createWebStorage({
|
|
58
|
+
* type: 'sessionStorage',
|
|
59
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
60
|
+
* defaultValues: { count: 0, name: '' },
|
|
61
|
+
* })
|
|
62
|
+
*
|
|
63
|
+
* // Updates only when count changes
|
|
64
|
+
* const count = useSubscription(sessionStorage, { selector: v => v.count })
|
|
65
|
+
* <\/script>
|
|
66
|
+
*
|
|
67
|
+
* <div>{$count}</div>
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
function useSubscription(source, options) {
|
|
71
|
+
const { selector, isEqual = deepEqual } = options ?? {};
|
|
72
|
+
const sub = typeof source === "function" ? source() : source;
|
|
73
|
+
function getSnapshot() {
|
|
74
|
+
return selector ? selector(sub.get()) : sub.get();
|
|
75
|
+
}
|
|
76
|
+
const initial = getSnapshot();
|
|
77
|
+
return readable(initial, (set) => {
|
|
78
|
+
let current = initial;
|
|
79
|
+
function refresh() {
|
|
80
|
+
const next = getSnapshot();
|
|
81
|
+
if (!isEqual(current, next)) {
|
|
82
|
+
current = next;
|
|
83
|
+
set(next);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
refresh();
|
|
87
|
+
return sub.subscribe(refresh);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { useSubscription };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "seitu",
|
|
3
3
|
"displayName": "Seitu",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.16.1",
|
|
6
6
|
"private": false,
|
|
7
7
|
"author": "Valerii Strilets",
|
|
8
8
|
"license": "MIT",
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
"typescript",
|
|
21
21
|
"react",
|
|
22
22
|
"vue",
|
|
23
|
+
"solid",
|
|
24
|
+
"solid-js",
|
|
25
|
+
"svelte",
|
|
23
26
|
"utils",
|
|
24
27
|
"type-safe",
|
|
25
28
|
"tanstack-intent"
|
|
@@ -45,6 +48,14 @@
|
|
|
45
48
|
"types": "./dist/vue/index.d.mts",
|
|
46
49
|
"import": "./dist/vue.mjs"
|
|
47
50
|
},
|
|
51
|
+
"./solid": {
|
|
52
|
+
"types": "./dist/solid/index.d.mts",
|
|
53
|
+
"import": "./dist/solid.mjs"
|
|
54
|
+
},
|
|
55
|
+
"./svelte": {
|
|
56
|
+
"types": "./dist/svelte/index.d.mts",
|
|
57
|
+
"import": "./dist/svelte.mjs"
|
|
58
|
+
},
|
|
48
59
|
"./utils": {
|
|
49
60
|
"types": "./dist/utils/index.d.mts",
|
|
50
61
|
"import": "./dist/utils.mjs"
|
|
@@ -62,6 +73,8 @@
|
|
|
62
73
|
"peerDependencies": {
|
|
63
74
|
"react": ">=19",
|
|
64
75
|
"react-dom": ">=19",
|
|
76
|
+
"solid-js": ">=1.9",
|
|
77
|
+
"svelte": ">=5",
|
|
65
78
|
"vue": ">=3.5"
|
|
66
79
|
},
|
|
67
80
|
"peerDependenciesMeta": {
|
|
@@ -71,6 +84,12 @@
|
|
|
71
84
|
"react-dom": {
|
|
72
85
|
"optional": true
|
|
73
86
|
},
|
|
87
|
+
"solid-js": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
90
|
+
"svelte": {
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
74
93
|
"vue": {
|
|
75
94
|
"optional": true
|
|
76
95
|
}
|
|
@@ -79,21 +98,26 @@
|
|
|
79
98
|
"fast-equals": "^6.0.0"
|
|
80
99
|
},
|
|
81
100
|
"devDependencies": {
|
|
101
|
+
"@solidjs/testing-library": "^0.8.10",
|
|
82
102
|
"@standard-schema/spec": "^1.1.0",
|
|
83
|
-
"@tanstack/intent": "^0.
|
|
103
|
+
"@tanstack/intent": "^0.3.2",
|
|
84
104
|
"@testing-library/jest-dom": "^6.9.1",
|
|
85
105
|
"@testing-library/react": "^16.3.2",
|
|
86
106
|
"@types/react": "^19.2.17",
|
|
107
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
87
108
|
"fake-indexeddb": "^6.2.5",
|
|
88
|
-
"happy-dom": "^20.10.
|
|
109
|
+
"happy-dom": "^20.10.6",
|
|
89
110
|
"react-dom": "^19.2.7",
|
|
90
|
-
"
|
|
111
|
+
"solid-js": "^1.9.13",
|
|
112
|
+
"svelte": "^5.56.4",
|
|
113
|
+
"tsdown": "^0.22.3",
|
|
91
114
|
"type-fest": "^5.7.0",
|
|
92
115
|
"typescript": "^6.0.3",
|
|
93
|
-
"vite": "^
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
116
|
+
"vite": "^8.1.2",
|
|
117
|
+
"vite-plugin-solid": "^2.11.12",
|
|
118
|
+
"vitest": "^4.1.9",
|
|
119
|
+
"vue": "^3.5.39",
|
|
120
|
+
"yaml": "^2.9.0",
|
|
97
121
|
"zod": "^4.4.3"
|
|
98
122
|
},
|
|
99
123
|
"scripts": {
|