seitu 0.12.1 → 0.14.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/dist/core-BKImMfak.mjs +308 -0
- package/dist/core.d.mts +2 -0
- package/dist/core.mjs +2 -0
- package/dist/index-Dzu3WPwr.d.mts +207 -0
- package/dist/{react/hooks.d.ts → react.d.mts} +73 -7
- package/dist/react.mjs +176 -0
- package/dist/{utils/validation.d.ts → utils.d.mts} +7 -3
- package/dist/utils.mjs +2 -0
- package/dist/validate-IWiN_jFZ.d.mts +93 -0
- package/dist/validation-B8XxyKZ0.mjs +32 -0
- package/dist/{vue/composables.d.ts → vue.d.mts} +10 -6
- package/dist/vue.mjs +87 -0
- package/dist/web.d.mts +383 -0
- package/dist/web.mjs +461 -0
- package/package.json +24 -25
- package/dist/core/computed.d.ts +0 -33
- package/dist/core/debounce-fn.d.ts +0 -21
- package/dist/core/debounce.d.ts +0 -19
- package/dist/core/index.d.ts +0 -8
- package/dist/core/schema-store.d.ts +0 -35
- package/dist/core/store.d.ts +0 -20
- package/dist/core/subscription.d.ts +0 -35
- package/dist/core/throttle-fn.d.ts +0 -23
- package/dist/core/throttle.d.ts +0 -19
- package/dist/core-CIQELdxV.js +0 -158
- package/dist/core.js +0 -2
- package/dist/react/components.d.ts +0 -58
- package/dist/react/index.d.ts +0 -2
- package/dist/react.js +0 -19
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils.d.ts +0 -7
- package/dist/utils.js +0 -9
- package/dist/validate.d.ts +0 -19
- package/dist/vue/index.d.ts +0 -1
- package/dist/vue/test-utils.d.ts +0 -2
- package/dist/vue.js +0 -22
- package/dist/web/index.d.ts +0 -5
- package/dist/web/is-online.d.ts +0 -33
- package/dist/web/media-query.d.ts +0 -77
- package/dist/web/scroll-state.d.ts +0 -111
- package/dist/web/web-storage-value.d.ts +0 -74
- package/dist/web/web-storage.d.ts +0 -70
- package/dist/web.js +0 -179
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
//#region src/core/subscription.ts
|
|
2
|
+
function createReadableSubscription(get, subscribe, notify) {
|
|
3
|
+
return {
|
|
4
|
+
get,
|
|
5
|
+
subscribe(callback, options) {
|
|
6
|
+
return subscribe(() => callback(get()), options);
|
|
7
|
+
},
|
|
8
|
+
"~": {
|
|
9
|
+
output: null,
|
|
10
|
+
notify
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function createSubscription(options) {
|
|
15
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
16
|
+
const notify = () => subscribers.forEach((cb) => cb());
|
|
17
|
+
let onEmpty;
|
|
18
|
+
return {
|
|
19
|
+
subscribe(callback, opts) {
|
|
20
|
+
if (subscribers.size === 0 && options?.onFirstSubscribe) onEmpty = options.onFirstSubscribe() ?? void 0;
|
|
21
|
+
if (opts?.immediate) callback();
|
|
22
|
+
subscribers.add(callback);
|
|
23
|
+
return () => {
|
|
24
|
+
subscribers.delete(callback);
|
|
25
|
+
if (subscribers.size === 0) {
|
|
26
|
+
onEmpty?.();
|
|
27
|
+
onEmpty = void 0;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
notify
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/core/computed.ts
|
|
36
|
+
function createComputed(source, transform) {
|
|
37
|
+
const sources = Array.isArray(source) ? source : [source];
|
|
38
|
+
const isSingle = !Array.isArray(source);
|
|
39
|
+
const { subscribe, notify } = createSubscription({ onFirstSubscribe() {
|
|
40
|
+
const unsubscribes = sources.map((s) => s.subscribe(() => notify()));
|
|
41
|
+
return () => unsubscribes.forEach((u) => u());
|
|
42
|
+
} });
|
|
43
|
+
const get = () => transform(isSingle ? sources[0].get() : sources.map((s) => s.get()));
|
|
44
|
+
return createReadableSubscription(get, subscribe, notify);
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/core/debounced.ts
|
|
48
|
+
/**
|
|
49
|
+
* Creates a debounced readable that delays updates from a source subscribable.
|
|
50
|
+
*
|
|
51
|
+
* The debounced store will only emit the latest value after `wait` milliseconds
|
|
52
|
+
* of inactivity from the source.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts twoslash
|
|
56
|
+
* import { createStore, createDebounced } from 'seitu'
|
|
57
|
+
*
|
|
58
|
+
* const store = createStore('')
|
|
59
|
+
* const debounced = createDebounced(store, 300)
|
|
60
|
+
* debounced.subscribe(value => console.log('debounced:', value))
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
function createDebounced(source, wait) {
|
|
64
|
+
let state = source.get();
|
|
65
|
+
let timeoutId;
|
|
66
|
+
const { subscribe, notify } = createSubscription({ onFirstSubscribe() {
|
|
67
|
+
const unsubscribe = source.subscribe(() => {
|
|
68
|
+
clearTimeout(timeoutId);
|
|
69
|
+
timeoutId = setTimeout(() => {
|
|
70
|
+
state = source.get();
|
|
71
|
+
notify();
|
|
72
|
+
}, wait);
|
|
73
|
+
});
|
|
74
|
+
return () => {
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
unsubscribe();
|
|
77
|
+
};
|
|
78
|
+
} });
|
|
79
|
+
const get = () => state;
|
|
80
|
+
return createReadableSubscription(get, subscribe, notify);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/core/debounced-fn.ts
|
|
84
|
+
/**
|
|
85
|
+
* Wraps a plain function in a debounced callable that also acts as a subscribable.
|
|
86
|
+
*
|
|
87
|
+
* Each call resets the debounce timer. When the timer fires, the wrapped function
|
|
88
|
+
* is invoked and its return value becomes the current state, notifying subscribers.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts twoslash
|
|
92
|
+
* import { createDebouncedFn } from 'seitu'
|
|
93
|
+
*
|
|
94
|
+
* const search = createDebouncedFn((query: string) => fetch(`/api?q=${query}`), 300)
|
|
95
|
+
* search.subscribe(result => console.log('result:', result))
|
|
96
|
+
* search('hello') // debounced — fires after 300ms of inactivity
|
|
97
|
+
* search.get() // latest return value (undefined until first call)
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
function createDebouncedFn(fn, wait) {
|
|
101
|
+
let state;
|
|
102
|
+
let timeoutId;
|
|
103
|
+
const { subscribe, notify } = createSubscription();
|
|
104
|
+
const get = () => state;
|
|
105
|
+
return Object.assign((...args) => {
|
|
106
|
+
clearTimeout(timeoutId);
|
|
107
|
+
timeoutId = setTimeout(() => {
|
|
108
|
+
state = fn(...args);
|
|
109
|
+
notify();
|
|
110
|
+
}, wait);
|
|
111
|
+
}, createReadableSubscription(get, subscribe, notify));
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/utils.ts
|
|
115
|
+
function tryParseJson(value) {
|
|
116
|
+
if (typeof value !== "string") return value;
|
|
117
|
+
try {
|
|
118
|
+
return JSON.parse(value);
|
|
119
|
+
} catch {
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/validate.ts
|
|
125
|
+
function validateSchema(schema, value, options) {
|
|
126
|
+
const parsed = tryParseJson(value);
|
|
127
|
+
const result = schema["~standard"].validate(parsed);
|
|
128
|
+
if (result instanceof Promise) throw new TypeError(`[${options.label}] Validation schema should not return a Promise.`);
|
|
129
|
+
if (!result.issues) return result.value;
|
|
130
|
+
if (options.onError) {
|
|
131
|
+
const corrected = options.onError(result.issues, parsed);
|
|
132
|
+
if (corrected !== void 0) {
|
|
133
|
+
const validated = schema["~standard"].validate(corrected);
|
|
134
|
+
if (validated instanceof Promise) throw new TypeError(`[${options.label}] Validation schema should not return a Promise.`);
|
|
135
|
+
if (validated.issues) console.warn(`[${options.label}] Returned value invalid, returned default value instead`, JSON.stringify(validated.issues, null, 2), { cause: validated.issues });
|
|
136
|
+
else return validated.value;
|
|
137
|
+
}
|
|
138
|
+
} else console.warn(`[${options.label}] Returned value invalid, returned default value instead`, JSON.stringify(result.issues, null, 2), { cause: result.issues });
|
|
139
|
+
return options.defaultValue;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/core/schema-store.ts
|
|
143
|
+
/**
|
|
144
|
+
* Creates a reactive schema store: state is validated on read, supports partial `set`, and
|
|
145
|
+
* falls back to default values when validation fails.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts twoslash
|
|
149
|
+
* import { createSchemaStore } from 'seitu'
|
|
150
|
+
* import * as z from 'zod'
|
|
151
|
+
*
|
|
152
|
+
* const store = createSchemaStore({
|
|
153
|
+
* schema: z.object({ count: z.number(), name: z.string() }),
|
|
154
|
+
* defaultValue: { count: 0, name: '' },
|
|
155
|
+
* })
|
|
156
|
+
* store.get()
|
|
157
|
+
* store.set({ count: 1, name: 'alice' })
|
|
158
|
+
* store.subscribe(console.log)
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
function createSchemaStore(options) {
|
|
162
|
+
const store = createStore(options.defaultValue);
|
|
163
|
+
const get = () => {
|
|
164
|
+
const stored = store.get();
|
|
165
|
+
return validateSchema(options.schema, stored, {
|
|
166
|
+
defaultValue: options.defaultValue,
|
|
167
|
+
label: "createSchemaStore",
|
|
168
|
+
onError: options.onValidationError ? (issues, parsed) => options.onValidationError({
|
|
169
|
+
issues: [...issues],
|
|
170
|
+
value: parsed,
|
|
171
|
+
defaultValue: options.defaultValue
|
|
172
|
+
}) : void 0
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
return {
|
|
176
|
+
...createReadableSubscription(get, store.subscribe, store["~"].notify),
|
|
177
|
+
set: (value) => {
|
|
178
|
+
const newValue = typeof value === "function" ? value(get()) : value;
|
|
179
|
+
store.set(newValue);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region src/core/store.ts
|
|
185
|
+
/**
|
|
186
|
+
* Creates a simple reactive store (minimal TanStack Store-style API).
|
|
187
|
+
*
|
|
188
|
+
* - **Standalone**: use `get()`, `set(value | updater)`, `subscribe(callback)` for any state.
|
|
189
|
+
* - **With schema-store**: use as the state backing for a memory provider.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts twoslash
|
|
193
|
+
* import { createStore } from 'seitu'
|
|
194
|
+
*
|
|
195
|
+
* const store = createStore({ count: 0 })
|
|
196
|
+
* store.set(prev => ({ ...prev, count: prev.count + 1 }))
|
|
197
|
+
* store.subscribe(state => console.log(state))
|
|
198
|
+
* store.get() // { count: 0 }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
function createStore(initial) {
|
|
202
|
+
let state = initial;
|
|
203
|
+
const { subscribe, notify } = createSubscription();
|
|
204
|
+
const get = () => state;
|
|
205
|
+
return {
|
|
206
|
+
...createReadableSubscription(get, subscribe, notify),
|
|
207
|
+
set: (value) => {
|
|
208
|
+
const next = typeof value === "function" ? value(state) : value;
|
|
209
|
+
if (next === state) return;
|
|
210
|
+
state = next;
|
|
211
|
+
notify();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region src/core/throttled.ts
|
|
217
|
+
/**
|
|
218
|
+
* Creates a throttled readable that rate-limits updates from a source subscribable.
|
|
219
|
+
*
|
|
220
|
+
* Emits the latest value at most once every `wait` milliseconds. The first update
|
|
221
|
+
* fires immediately, then subsequent updates are batched until the interval elapses.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```ts twoslash
|
|
225
|
+
* import { createStore, createThrottled } from 'seitu'
|
|
226
|
+
*
|
|
227
|
+
* const store = createStore('')
|
|
228
|
+
* const throttled = createThrottled(store, 300)
|
|
229
|
+
* throttled.subscribe(value => console.log('throttled:', value))
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
function createThrottled(source, wait) {
|
|
233
|
+
let state = source.get();
|
|
234
|
+
let timeoutId;
|
|
235
|
+
let hasTrailing = false;
|
|
236
|
+
const { subscribe, notify } = createSubscription({ onFirstSubscribe() {
|
|
237
|
+
const unsubscribe = source.subscribe(() => {
|
|
238
|
+
if (timeoutId) {
|
|
239
|
+
hasTrailing = true;
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
state = source.get();
|
|
243
|
+
notify();
|
|
244
|
+
timeoutId = setTimeout(() => {
|
|
245
|
+
timeoutId = void 0;
|
|
246
|
+
if (hasTrailing) {
|
|
247
|
+
hasTrailing = false;
|
|
248
|
+
state = source.get();
|
|
249
|
+
notify();
|
|
250
|
+
}
|
|
251
|
+
}, wait);
|
|
252
|
+
});
|
|
253
|
+
return () => {
|
|
254
|
+
clearTimeout(timeoutId);
|
|
255
|
+
timeoutId = void 0;
|
|
256
|
+
hasTrailing = false;
|
|
257
|
+
unsubscribe();
|
|
258
|
+
};
|
|
259
|
+
} });
|
|
260
|
+
const get = () => state;
|
|
261
|
+
return createReadableSubscription(get, subscribe, notify);
|
|
262
|
+
}
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region src/core/throttled-fn.ts
|
|
265
|
+
/**
|
|
266
|
+
* Wraps a plain function in a throttled callable that also acts as a subscribable.
|
|
267
|
+
*
|
|
268
|
+
* The first call fires immediately. Subsequent calls within the `wait` window are
|
|
269
|
+
* batched — only the last one fires when the interval elapses. The return value of
|
|
270
|
+
* the wrapped function becomes the current state, notifying subscribers.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```ts twoslash
|
|
274
|
+
* import { createThrottledFn } from 'seitu'
|
|
275
|
+
*
|
|
276
|
+
* const log = createThrottledFn((msg: string) => console.log(msg), 300)
|
|
277
|
+
* log.subscribe(result => console.log('result:', result))
|
|
278
|
+
* log('hello') // fires immediately
|
|
279
|
+
* log('world') // throttled — fires after 300ms
|
|
280
|
+
* log.get() // latest return value (undefined until first call)
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
function createThrottledFn(fn, wait) {
|
|
284
|
+
let state;
|
|
285
|
+
let timeoutId;
|
|
286
|
+
let trailingArgs;
|
|
287
|
+
const { subscribe, notify } = createSubscription();
|
|
288
|
+
const get = () => state;
|
|
289
|
+
return Object.assign((...args) => {
|
|
290
|
+
if (timeoutId) {
|
|
291
|
+
trailingArgs = args;
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
state = fn(...args);
|
|
295
|
+
notify();
|
|
296
|
+
timeoutId = setTimeout(() => {
|
|
297
|
+
timeoutId = void 0;
|
|
298
|
+
if (trailingArgs) {
|
|
299
|
+
const args = trailingArgs;
|
|
300
|
+
trailingArgs = void 0;
|
|
301
|
+
state = fn(...args);
|
|
302
|
+
notify();
|
|
303
|
+
}
|
|
304
|
+
}, wait);
|
|
305
|
+
}, createReadableSubscription(get, subscribe, notify));
|
|
306
|
+
}
|
|
307
|
+
//#endregion
|
|
308
|
+
export { validateSchema as a, createDebounced as c, createSubscription as d, createSchemaStore as i, createComputed as l, createThrottled as n, tryParseJson as o, createStore as r, createDebouncedFn as s, createThrottledFn as t, createReadableSubscription as u };
|
package/dist/core.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { S as createSubscription, _ as Readable, a as Store, b as Writable, c as SchemaStoreOptions, d as createDebouncedFn, f as Debounced, g as Clearable, h as createComputed, i as createThrottled, l as createSchemaStore, m as Computed, n as createThrottledFn, o as createStore, p as createDebounced, r as Throttled, s as SchemaStore, t as ThrottledFn, u as DebouncedFn, v as Subscribable, x as createReadableSubscription, y as SubscribeOptions } from "./index-Dzu3WPwr.mjs";
|
|
2
|
+
export { Clearable, Computed, Debounced, DebouncedFn, Readable, SchemaStore, SchemaStoreOptions, Store, Subscribable, SubscribeOptions, Throttled, ThrottledFn, Writable, createComputed, createDebounced, createDebouncedFn, createReadableSubscription, createSchemaStore, createStore, createSubscription, createThrottled, createThrottledFn };
|
package/dist/core.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { c as createDebounced, d as createSubscription, i as createSchemaStore, l as createComputed, n as createThrottled, r as createStore, s as createDebouncedFn, t as createThrottledFn, u as createReadableSubscription } from "./core-BKImMfak.mjs";
|
|
2
|
+
export { createComputed, createDebounced, createDebouncedFn, createReadableSubscription, createSchemaStore, createStore, createSubscription, createThrottled, createThrottledFn };
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { i as StandardSchemaV1, r as ValidationSchemaOutput, t as ValidationSchemaErrorProps } from "./validate-IWiN_jFZ.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/subscription.d.ts
|
|
4
|
+
interface SubscribeOptions {
|
|
5
|
+
/**
|
|
6
|
+
* When `true`, the callback is invoked immediately with the current value upon subscribing.
|
|
7
|
+
*/
|
|
8
|
+
immediate?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface Subscribable<V> {
|
|
11
|
+
'subscribe': (callback: (value: V) => any, options?: SubscribeOptions) => () => void;
|
|
12
|
+
'~': {
|
|
13
|
+
/**
|
|
14
|
+
* Type type with returned value of the subscription.
|
|
15
|
+
*/
|
|
16
|
+
output: V;
|
|
17
|
+
/**
|
|
18
|
+
* A function that notifies all subscribers that the value has changed.
|
|
19
|
+
*/
|
|
20
|
+
notify: () => void;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
interface Readable<T> {
|
|
24
|
+
get: () => T;
|
|
25
|
+
}
|
|
26
|
+
interface Writable<T, P = T> {
|
|
27
|
+
set: (value: T | ((prev: P) => T)) => any;
|
|
28
|
+
}
|
|
29
|
+
interface Clearable {
|
|
30
|
+
clear: () => void;
|
|
31
|
+
}
|
|
32
|
+
declare function createReadableSubscription<T>(get: () => T, subscribe: (callback: () => any, options?: SubscribeOptions) => () => void, notify: () => void): Readable<T> & Subscribable<T>;
|
|
33
|
+
declare function createSubscription(options?: {
|
|
34
|
+
onFirstSubscribe?: () => (void | (() => void));
|
|
35
|
+
}): {
|
|
36
|
+
subscribe: (callback: () => any, options?: SubscribeOptions) => () => void;
|
|
37
|
+
notify: () => void;
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/core/computed.d.ts
|
|
41
|
+
interface Computed<T> extends Readable<T>, Subscribable<T> {}
|
|
42
|
+
type Source<T = unknown> = Readable<T> & Subscribable<T>;
|
|
43
|
+
type SourceValues<S extends readonly Source[]> = { [K in keyof S]: S[K] extends Source<infer V> ? V : never };
|
|
44
|
+
/**
|
|
45
|
+
* Creates a computed (derived) subscription from a subscription or an array of subscriptions.
|
|
46
|
+
* The computed value is updated whenever any subscription updates.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts twoslash
|
|
50
|
+
* import { createComputed, createStore } from 'seitu'
|
|
51
|
+
*
|
|
52
|
+
* const count = createStore({ a: 1, b: 2 })
|
|
53
|
+
* const sum = createComputed(count, s => s.a + s.b)
|
|
54
|
+
* sum.get() // 3
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts twoslash
|
|
59
|
+
* import { createComputed, createStore } from 'seitu'
|
|
60
|
+
*
|
|
61
|
+
* const a = createStore(1)
|
|
62
|
+
* const b = createStore(2)
|
|
63
|
+
* const sum = createComputed([a, b], ([a, b]) => a + b)
|
|
64
|
+
* sum.get() // 3
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
declare function createComputed<S extends readonly Source[], R>(sources: [...S], transform: (values: SourceValues<S>) => R): Computed<R>;
|
|
68
|
+
declare function createComputed<T, R>(source: Source<T>, transform: (value: T) => R): Computed<R>;
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/core/debounced.d.ts
|
|
71
|
+
interface Debounced<T> extends Readable<T>, Subscribable<T> {}
|
|
72
|
+
/**
|
|
73
|
+
* Creates a debounced readable that delays updates from a source subscribable.
|
|
74
|
+
*
|
|
75
|
+
* The debounced store will only emit the latest value after `wait` milliseconds
|
|
76
|
+
* of inactivity from the source.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts twoslash
|
|
80
|
+
* import { createStore, createDebounced } from 'seitu'
|
|
81
|
+
*
|
|
82
|
+
* const store = createStore('')
|
|
83
|
+
* const debounced = createDebounced(store, 300)
|
|
84
|
+
* debounced.subscribe(value => console.log('debounced:', value))
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function createDebounced<T>(source: Readable<T> & Subscribable<T>, wait: number): Debounced<T>;
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/core/debounced-fn.d.ts
|
|
90
|
+
interface DebouncedFn<F extends (...args: any[]) => any> extends Readable<ReturnType<F> | undefined>, Subscribable<ReturnType<F> | undefined> {
|
|
91
|
+
(...args: Parameters<F>): void;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Wraps a plain function in a debounced callable that also acts as a subscribable.
|
|
95
|
+
*
|
|
96
|
+
* Each call resets the debounce timer. When the timer fires, the wrapped function
|
|
97
|
+
* is invoked and its return value becomes the current state, notifying subscribers.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts twoslash
|
|
101
|
+
* import { createDebouncedFn } from 'seitu'
|
|
102
|
+
*
|
|
103
|
+
* const search = createDebouncedFn((query: string) => fetch(`/api?q=${query}`), 300)
|
|
104
|
+
* search.subscribe(result => console.log('result:', result))
|
|
105
|
+
* search('hello') // debounced — fires after 300ms of inactivity
|
|
106
|
+
* search.get() // latest return value (undefined until first call)
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
declare function createDebouncedFn<F extends (...args: any[]) => any>(fn: F, wait: number): DebouncedFn<F>;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/core/schema-store.d.ts
|
|
112
|
+
interface SchemaStore<O> extends Subscribable<O>, Readable<O>, Writable<O, O> {}
|
|
113
|
+
interface SchemaStoreOptions<S extends StandardSchemaV1<unknown>> {
|
|
114
|
+
schema: S;
|
|
115
|
+
defaultValue: ValidationSchemaOutput<S>;
|
|
116
|
+
/**
|
|
117
|
+
* Handle validation errors.
|
|
118
|
+
*
|
|
119
|
+
* If returns a value, it will be validated and used as the store value.
|
|
120
|
+
* If returns undefined, the default value will be returned.
|
|
121
|
+
*/
|
|
122
|
+
onValidationError?: (props: ValidationSchemaErrorProps<ValidationSchemaOutput<S>>) => void | ValidationSchemaOutput<S>;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Creates a reactive schema store: state is validated on read, supports partial `set`, and
|
|
126
|
+
* falls back to default values when validation fails.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts twoslash
|
|
130
|
+
* import { createSchemaStore } from 'seitu'
|
|
131
|
+
* import * as z from 'zod'
|
|
132
|
+
*
|
|
133
|
+
* const store = createSchemaStore({
|
|
134
|
+
* schema: z.object({ count: z.number(), name: z.string() }),
|
|
135
|
+
* defaultValue: { count: 0, name: '' },
|
|
136
|
+
* })
|
|
137
|
+
* store.get()
|
|
138
|
+
* store.set({ count: 1, name: 'alice' })
|
|
139
|
+
* store.subscribe(console.log)
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
declare function createSchemaStore<S extends StandardSchemaV1<unknown>>(options: SchemaStoreOptions<S>): SchemaStore<ValidationSchemaOutput<S>>;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/core/store.d.ts
|
|
145
|
+
interface Store<T> extends Readable<T>, Writable<T, T>, Subscribable<T> {}
|
|
146
|
+
/**
|
|
147
|
+
* Creates a simple reactive store (minimal TanStack Store-style API).
|
|
148
|
+
*
|
|
149
|
+
* - **Standalone**: use `get()`, `set(value | updater)`, `subscribe(callback)` for any state.
|
|
150
|
+
* - **With schema-store**: use as the state backing for a memory provider.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts twoslash
|
|
154
|
+
* import { createStore } from 'seitu'
|
|
155
|
+
*
|
|
156
|
+
* const store = createStore({ count: 0 })
|
|
157
|
+
* store.set(prev => ({ ...prev, count: prev.count + 1 }))
|
|
158
|
+
* store.subscribe(state => console.log(state))
|
|
159
|
+
* store.get() // { count: 0 }
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
declare function createStore<T>(initial: T): Store<T>;
|
|
163
|
+
//#endregion
|
|
164
|
+
//#region src/core/throttled.d.ts
|
|
165
|
+
interface Throttled<T> extends Readable<T>, Subscribable<T> {}
|
|
166
|
+
/**
|
|
167
|
+
* Creates a throttled readable that rate-limits updates from a source subscribable.
|
|
168
|
+
*
|
|
169
|
+
* Emits the latest value at most once every `wait` milliseconds. The first update
|
|
170
|
+
* fires immediately, then subsequent updates are batched until the interval elapses.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts twoslash
|
|
174
|
+
* import { createStore, createThrottled } from 'seitu'
|
|
175
|
+
*
|
|
176
|
+
* const store = createStore('')
|
|
177
|
+
* const throttled = createThrottled(store, 300)
|
|
178
|
+
* throttled.subscribe(value => console.log('throttled:', value))
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
declare function createThrottled<T>(source: Readable<T> & Subscribable<T>, wait: number): Throttled<T>;
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/core/throttled-fn.d.ts
|
|
184
|
+
interface ThrottledFn<F extends (...args: any[]) => any> extends Readable<ReturnType<F> | undefined>, Subscribable<ReturnType<F> | undefined> {
|
|
185
|
+
(...args: Parameters<F>): void;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Wraps a plain function in a throttled callable that also acts as a subscribable.
|
|
189
|
+
*
|
|
190
|
+
* The first call fires immediately. Subsequent calls within the `wait` window are
|
|
191
|
+
* batched — only the last one fires when the interval elapses. The return value of
|
|
192
|
+
* the wrapped function becomes the current state, notifying subscribers.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts twoslash
|
|
196
|
+
* import { createThrottledFn } from 'seitu'
|
|
197
|
+
*
|
|
198
|
+
* const log = createThrottledFn((msg: string) => console.log(msg), 300)
|
|
199
|
+
* log.subscribe(result => console.log('result:', result))
|
|
200
|
+
* log('hello') // fires immediately
|
|
201
|
+
* log('world') // throttled — fires after 300ms
|
|
202
|
+
* log.get() // latest return value (undefined until first call)
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare function createThrottledFn<F extends (...args: any[]) => any>(fn: F, wait: number): ThrottledFn<F>;
|
|
206
|
+
//#endregion
|
|
207
|
+
export { createSubscription as S, Readable as _, Store as a, Writable as b, SchemaStoreOptions as c, createDebouncedFn as d, Debounced as f, Clearable as g, createComputed as h, createThrottled as i, createSchemaStore as l, Computed as m, createThrottledFn as n, createStore as o, createDebounced as p, Throttled as r, SchemaStore as s, ThrottledFn as t, DebouncedFn as u, Subscribable as v, createReadableSubscription as x, SubscribeOptions as y };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as React from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { _ as Readable, v as Subscribable } from "./index-Dzu3WPwr.mjs";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/react/hooks.d.ts
|
|
5
|
+
interface UseSubscriptionOptions<S extends Subscribable<any> & Readable<any>, R = S['~']['output']> {
|
|
6
|
+
selector?: (value: S['~']['output']) => R;
|
|
7
|
+
deps?: React$1.DependencyList;
|
|
8
|
+
isEqual?: (prev: R, next: R) => boolean;
|
|
7
9
|
}
|
|
8
10
|
/**
|
|
9
11
|
* Use this hook to subscribe to a reactive value. Accepts a subscription object
|
|
@@ -95,4 +97,68 @@ export interface UseSubscriptionOptions<S extends Subscribable<any> & Readable<a
|
|
|
95
97
|
* }
|
|
96
98
|
* ```
|
|
97
99
|
*/
|
|
98
|
-
|
|
100
|
+
declare function useSubscription<S extends Subscribable<any> & Readable<any>, R = S['~']['output']>(source: S | (() => S), options?: UseSubscriptionOptions<S, R>): R;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/react/components.d.ts
|
|
103
|
+
interface SubscriptionProps<S extends Subscribable<any> & Readable<any>, R = S['~']['output']> extends Pick<UseSubscriptionOptions<S, R>, 'selector'> {
|
|
104
|
+
value: S;
|
|
105
|
+
children: (value: R) => React.ReactNode;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Declarative component that subscribes to a reactive value and passes it to a render function.
|
|
109
|
+
* Re-renders when the value (or selected value) changes. Use when you prefer a component API
|
|
110
|
+
* over the useSubscription hook.
|
|
111
|
+
*
|
|
112
|
+
* @example Basic usage
|
|
113
|
+
* ```tsx twoslash title="/app/page.tsx"
|
|
114
|
+
* 'use client'
|
|
115
|
+
*
|
|
116
|
+
* import { createWebStorage } from 'seitu/web'
|
|
117
|
+
* import { Subscription } from 'seitu/react'
|
|
118
|
+
* import * as z from 'zod'
|
|
119
|
+
*
|
|
120
|
+
* const sessionStorage = createWebStorage({
|
|
121
|
+
* type: 'sessionStorage',
|
|
122
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
123
|
+
* defaultValues: { count: 0, name: '' },
|
|
124
|
+
* })
|
|
125
|
+
*
|
|
126
|
+
* export default function Page() {
|
|
127
|
+
* return (
|
|
128
|
+
* <Subscription value={sessionStorage}>
|
|
129
|
+
* {(value) => <div>{value.count}</div>}
|
|
130
|
+
* </Subscription>
|
|
131
|
+
* )
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @example With selector
|
|
136
|
+
* ```tsx twoslash title="/app/page.tsx"
|
|
137
|
+
* 'use client'
|
|
138
|
+
*
|
|
139
|
+
* import { createWebStorage } from 'seitu/web'
|
|
140
|
+
* import { Subscription } from 'seitu/react'
|
|
141
|
+
* import * as z from 'zod'
|
|
142
|
+
*
|
|
143
|
+
* const sessionStorage = createWebStorage({
|
|
144
|
+
* type: 'sessionStorage',
|
|
145
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
146
|
+
* defaultValues: { count: 0, name: '' },
|
|
147
|
+
* })
|
|
148
|
+
*
|
|
149
|
+
* export default function Page() {
|
|
150
|
+
* return (
|
|
151
|
+
* <Subscription value={sessionStorage} selector={(v) => v.count}>
|
|
152
|
+
* {(count) => <div>{count}</div>}
|
|
153
|
+
* </Subscription>
|
|
154
|
+
* )
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
declare function Subscription<S extends Subscribable<any> & Readable<any>, R = S['~']['output']>({
|
|
159
|
+
value,
|
|
160
|
+
selector,
|
|
161
|
+
children
|
|
162
|
+
}: SubscriptionProps<S, R>): React$1.ReactNode;
|
|
163
|
+
//#endregion
|
|
164
|
+
export { Subscription, SubscriptionProps, UseSubscriptionOptions, useSubscription };
|