seitu 0.9.1 → 0.10.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/core/schema-store.d.ts +10 -12
- package/dist/core/store.d.ts +1 -1
- package/dist/core/subscription.d.ts +1 -0
- package/dist/core-BFAZmVJI.js +167 -0
- package/dist/core.js +2 -2
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/validation.d.ts +27 -0
- package/dist/validate.d.ts +23 -0
- package/dist/web/index.d.ts +2 -4
- package/dist/web/web-storage-value.d.ts +59 -11
- package/dist/web/web-storage.d.ts +56 -11
- package/dist/web.js +125 -196
- package/package.json +5 -1
- package/dist/core-vtgV_plC.js +0 -187
- package/dist/web/local-storage-value.d.ts +0 -68
- package/dist/web/local-storage.d.ts +0 -50
- package/dist/web/session-storage-value.d.ts +0 -68
- package/dist/web/session-storage.d.ts +0 -50
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ValidationObjectSchemas, ValidationObjectSchemasOutput } from '../validate';
|
|
3
3
|
import type { Readable, Subscribable, Writable } from './index';
|
|
4
|
-
export type SchemaStoreSchema = Record<string, StandardSchemaV1<unknown, unknown>>;
|
|
5
|
-
export type SchemaStoreOutput<S extends SchemaStoreSchema> = Simplify<{
|
|
6
|
-
[K in keyof S]: StandardSchemaV1.InferOutput<S[K]>;
|
|
7
|
-
}>;
|
|
8
4
|
export interface SchemaStore<O extends Record<string, unknown>> extends Subscribable<O>, Readable<O>, Writable<Partial<O>, O> {
|
|
9
|
-
|
|
5
|
+
'~': {
|
|
6
|
+
getDefaultValue: <K extends keyof O>(key: K) => O[K];
|
|
7
|
+
} & Subscribable<O>['~'];
|
|
10
8
|
}
|
|
11
9
|
export interface SchemaStoreOptions<S extends Record<string, StandardSchemaV1>> {
|
|
12
10
|
schemas: S;
|
|
13
|
-
defaultValues:
|
|
11
|
+
defaultValues: ValidationObjectSchemasOutput<S>;
|
|
14
12
|
/**
|
|
15
13
|
* The provider to use for the schema store. If not provided, the schema store will
|
|
16
14
|
* use an in-memory provider.
|
|
@@ -35,10 +33,10 @@ export interface SchemaStoreOptions<S extends Record<string, StandardSchemaV1>>
|
|
|
35
33
|
* store.subscribe(console.log)
|
|
36
34
|
* ```
|
|
37
35
|
*/
|
|
38
|
-
export declare function createSchemaStore<S extends Record<string, StandardSchemaV1>>(options: SchemaStoreOptions<S>): SchemaStore<
|
|
39
|
-
export interface SchemaStoreProvider<S extends
|
|
40
|
-
get: () =>
|
|
41
|
-
set: (value: Partial<
|
|
36
|
+
export declare function createSchemaStore<S extends Record<string, StandardSchemaV1>>(options: SchemaStoreOptions<S>): SchemaStore<ValidationObjectSchemasOutput<S>>;
|
|
37
|
+
export interface SchemaStoreProvider<S extends ValidationObjectSchemas> {
|
|
38
|
+
get: () => ValidationObjectSchemasOutput<S>;
|
|
39
|
+
set: (value: Partial<ValidationObjectSchemasOutput<S>>) => void;
|
|
42
40
|
}
|
|
43
41
|
/**
|
|
44
42
|
* Creates an in-memory provider for a schema store. Use as the state backing when you don't
|
|
@@ -56,4 +54,4 @@ export interface SchemaStoreProvider<S extends SchemaStoreSchema> {
|
|
|
56
54
|
* })
|
|
57
55
|
* ```
|
|
58
56
|
*/
|
|
59
|
-
export declare function createSchemaStoreMemoryProvider<S extends
|
|
57
|
+
export declare function createSchemaStoreMemoryProvider<S extends ValidationObjectSchemas>(): SchemaStoreProvider<S>;
|
package/dist/core/store.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Readable, Subscribable, Writable } from './subscription';
|
|
|
2
2
|
export interface Store<T> extends Readable<T>, Writable<T, T>, Subscribable<T> {
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
|
-
* Creates a simple reactive store (minimal TanStack Store
|
|
5
|
+
* Creates a simple reactive store (minimal TanStack Store-style API).
|
|
6
6
|
*
|
|
7
7
|
* - **Standalone**: use `get()`, `set(value | updater)`, `subscribe(callback)` for any state.
|
|
8
8
|
* - **With schema-store**: use as the state backing for a memory provider.
|
|
@@ -26,6 +26,7 @@ export interface Writable<T, P = T> {
|
|
|
26
26
|
export interface Removable {
|
|
27
27
|
remove: () => void;
|
|
28
28
|
}
|
|
29
|
+
export declare function createReadableSubscription<T>(get: () => T, subscribe: (callback: () => any, options?: SubscribeOptions) => () => void, notify: () => void): Readable<T> & Subscribable<T>;
|
|
29
30
|
export declare function createSubscription(options?: {
|
|
30
31
|
onFirstSubscribe?: () => (void | (() => void));
|
|
31
32
|
}): {
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
//#region src/core/subscription.ts
|
|
2
|
+
function e(e, t, n) {
|
|
3
|
+
return {
|
|
4
|
+
get: e,
|
|
5
|
+
subscribe(n, r) {
|
|
6
|
+
return t(() => n(e()), r);
|
|
7
|
+
},
|
|
8
|
+
"~": {
|
|
9
|
+
output: null,
|
|
10
|
+
notify: n
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function t(e) {
|
|
15
|
+
let t = /* @__PURE__ */ new Set(), n = () => t.forEach((e) => e()), r;
|
|
16
|
+
return {
|
|
17
|
+
subscribe(n, i) {
|
|
18
|
+
return t.size === 0 && e?.onFirstSubscribe && (r = e.onFirstSubscribe() ?? void 0), i?.immediate && n(), t.add(n), () => {
|
|
19
|
+
t.delete(n), t.size === 0 && (r?.(), r = void 0);
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
notify: n
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/core/computed.ts
|
|
27
|
+
function n(n, r) {
|
|
28
|
+
let i = Array.isArray(n) ? n : [n], a = !Array.isArray(n), { subscribe: o, notify: s } = t({ onFirstSubscribe() {
|
|
29
|
+
let e = i.map((e) => e.subscribe(() => s()));
|
|
30
|
+
return () => e.forEach((e) => e());
|
|
31
|
+
} });
|
|
32
|
+
return e(() => r(a ? i[0].get() : i.map((e) => e.get())), o, s);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/core/debounce.ts
|
|
36
|
+
function r(n, r) {
|
|
37
|
+
let i = n.get(), a, { subscribe: o, notify: s } = t({ onFirstSubscribe() {
|
|
38
|
+
let e = n.subscribe(() => {
|
|
39
|
+
clearTimeout(a), a = setTimeout(() => {
|
|
40
|
+
i = n.get(), s();
|
|
41
|
+
}, r);
|
|
42
|
+
});
|
|
43
|
+
return () => {
|
|
44
|
+
clearTimeout(a), e();
|
|
45
|
+
};
|
|
46
|
+
} });
|
|
47
|
+
return e(() => i, o, s);
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/core/debounce-fn.ts
|
|
51
|
+
function i(n, r) {
|
|
52
|
+
let i, a, { subscribe: o, notify: s } = t();
|
|
53
|
+
return Object.assign((...e) => {
|
|
54
|
+
clearTimeout(a), a = setTimeout(() => {
|
|
55
|
+
i = n(...e), s();
|
|
56
|
+
}, r);
|
|
57
|
+
}, e(() => i, o, s));
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/utils.ts
|
|
61
|
+
function a(e) {
|
|
62
|
+
if (typeof e != "string") return e;
|
|
63
|
+
try {
|
|
64
|
+
return JSON.parse(e);
|
|
65
|
+
} catch {
|
|
66
|
+
return e;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/validate.ts
|
|
71
|
+
function o(e, t, n) {
|
|
72
|
+
let r = a(t), i = e["~standard"].validate(r);
|
|
73
|
+
if (i instanceof Promise) throw TypeError(`[${n.label}] Validation schema should not return a Promise.`);
|
|
74
|
+
if (!i.issues) return i.value;
|
|
75
|
+
if (n.onError) {
|
|
76
|
+
let t = n.onError(i.issues, r);
|
|
77
|
+
if (t !== void 0) {
|
|
78
|
+
let r = e["~standard"].validate(t);
|
|
79
|
+
if (r instanceof Promise) throw TypeError(`[${n.label}] Validation schema should not return a Promise.`);
|
|
80
|
+
if (r.issues) console.warn(`[${n.label}] Returned value invalid, returned default value instead`, JSON.stringify(r.issues, null, 2), { cause: r.issues });
|
|
81
|
+
else return r.value;
|
|
82
|
+
}
|
|
83
|
+
} else console.warn(`[${n.label}] Returned value invalid, returned default value instead`, JSON.stringify(i.issues, null, 2), { cause: i.issues });
|
|
84
|
+
return n.defaultValue;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/core/schema-store.ts
|
|
88
|
+
function s(n) {
|
|
89
|
+
let { subscribe: r, notify: i } = t(), a = { ...n.defaultValues }, s = n.provider ?? c(), l = () => {
|
|
90
|
+
let e = { ...a };
|
|
91
|
+
for (let [t, r] of Object.entries(n.schemas)) e[t] = o(r, s.get()[t], {
|
|
92
|
+
defaultValue: a[t],
|
|
93
|
+
label: `createSchemaStore:${String(t)}`
|
|
94
|
+
});
|
|
95
|
+
return e;
|
|
96
|
+
}, u = e(l, r, i);
|
|
97
|
+
return {
|
|
98
|
+
...u,
|
|
99
|
+
set: (e) => {
|
|
100
|
+
let t = typeof e == "function" ? e(l()) : e;
|
|
101
|
+
s.set(t), i();
|
|
102
|
+
},
|
|
103
|
+
"~": {
|
|
104
|
+
...u["~"],
|
|
105
|
+
getDefaultValue: (e) => a[e]
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function c() {
|
|
110
|
+
let e = l({});
|
|
111
|
+
return {
|
|
112
|
+
get: () => e.get(),
|
|
113
|
+
set: (t) => {
|
|
114
|
+
e.set(t);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/core/store.ts
|
|
120
|
+
function l(n) {
|
|
121
|
+
let r = n, { subscribe: i, notify: a } = t();
|
|
122
|
+
return {
|
|
123
|
+
...e(() => r, i, a),
|
|
124
|
+
set: (e) => {
|
|
125
|
+
let t = typeof e == "function" ? e(r) : e;
|
|
126
|
+
t !== r && (r = t, a());
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/core/throttle.ts
|
|
132
|
+
function u(n, r) {
|
|
133
|
+
let i = n.get(), a, o = !1, { subscribe: s, notify: c } = t({ onFirstSubscribe() {
|
|
134
|
+
let e = n.subscribe(() => {
|
|
135
|
+
if (a) {
|
|
136
|
+
o = !0;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
i = n.get(), c(), a = setTimeout(() => {
|
|
140
|
+
a = void 0, o && (o = !1, i = n.get(), c());
|
|
141
|
+
}, r);
|
|
142
|
+
});
|
|
143
|
+
return () => {
|
|
144
|
+
clearTimeout(a), a = void 0, o = !1, e();
|
|
145
|
+
};
|
|
146
|
+
} });
|
|
147
|
+
return e(() => i, s, c);
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/core/throttle-fn.ts
|
|
151
|
+
function d(n, r) {
|
|
152
|
+
let i, a, o, { subscribe: s, notify: c } = t();
|
|
153
|
+
return Object.assign((...e) => {
|
|
154
|
+
if (a) {
|
|
155
|
+
o = e;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
i = n(...e), c(), a = setTimeout(() => {
|
|
159
|
+
if (a = void 0, o) {
|
|
160
|
+
let e = o;
|
|
161
|
+
o = void 0, i = n(...e), c();
|
|
162
|
+
}
|
|
163
|
+
}, r);
|
|
164
|
+
}, e(() => i, s, c));
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
export { c as a, i as c, e as d, t as f, s as i, r as l, u as n, o, l as r, a as s, d as t, n as u };
|
package/dist/core.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, c as t,
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, c as t, d as n, f as r, i, l as a, n as o, r as s, t as c, u as l } from "./core-BFAZmVJI.js";
|
|
2
|
+
export { l as createComputed, a as createDebounce, t as createDebounceFn, n as createReadableSubscription, i as createSchemaStore, e as createSchemaStoreMemoryProvider, s as createStore, r as createSubscription, o as createThrottle, c as createThrottleFn };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './validation';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ValidationSchemaErrorProps } from '../validate';
|
|
2
|
+
/**
|
|
3
|
+
* Repair broken web storage value object if value was object but not all keys are in the default value object.
|
|
4
|
+
*
|
|
5
|
+
* @returns A new object with the existing keys in the value object that are not in the default value object.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { createWebStorageValue } from 'seitu/web'
|
|
10
|
+
* import { repairWebStorageValueObjectWithDefault } from 'seitu/utils'
|
|
11
|
+
* import * as z from 'zod'
|
|
12
|
+
*
|
|
13
|
+
* const value = createWebStorageValue({
|
|
14
|
+
* type: 'localStorage',
|
|
15
|
+
* schema: z.object({ a: z.number(), b: z.string() }),
|
|
16
|
+
* key: 'storage-key',
|
|
17
|
+
* defaultValue: { a: 0, b: 'default' },
|
|
18
|
+
* onValidationError: repairWebStorageValueObjectWithDefault,
|
|
19
|
+
* })
|
|
20
|
+
* value.get() // { a: 0, b: 'default' }
|
|
21
|
+
* window.localStorage.setItem('storage-key', JSON.stringify({ a: 1 }))
|
|
22
|
+
* value.get() // { a: 1, b: 'default' }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function repairWebStorageValueObjectWithDefault<O extends Record<string, unknown>>(props: ValidationSchemaErrorProps<O>): O & {
|
|
26
|
+
[k: string]: any;
|
|
27
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { Simplify } from './utils';
|
|
3
|
+
export type ValidationObjectSchemas = Record<string, StandardSchemaV1<unknown, unknown>>;
|
|
4
|
+
export type ValidationObjectSchemasOutput<S extends ValidationObjectSchemas> = Simplify<{
|
|
5
|
+
[K in keyof S]: StandardSchemaV1.InferOutput<S[K]>;
|
|
6
|
+
}>;
|
|
7
|
+
export interface ValidationSchemaErrorProps<O> {
|
|
8
|
+
defaultValue: O;
|
|
9
|
+
issues: StandardSchemaV1.Issue[];
|
|
10
|
+
value: unknown;
|
|
11
|
+
}
|
|
12
|
+
export interface ValidationSchemasErrorProps<O extends Record<string, unknown>> {
|
|
13
|
+
defaultValue: O[keyof O];
|
|
14
|
+
issues: StandardSchemaV1.Issue[];
|
|
15
|
+
value: unknown;
|
|
16
|
+
key: keyof O;
|
|
17
|
+
}
|
|
18
|
+
export interface ValidateSchemaOptions {
|
|
19
|
+
defaultValue: unknown;
|
|
20
|
+
label: string;
|
|
21
|
+
onError?: (issues: readonly StandardSchemaV1.Issue[], parsed: unknown) => unknown;
|
|
22
|
+
}
|
|
23
|
+
export declare function validateSchema(schema: StandardSchemaV1, value: unknown, options: ValidateSchemaOptions): unknown;
|
package/dist/web/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export * from './is-online';
|
|
2
|
-
export * from './local-storage';
|
|
3
|
-
export * from './local-storage-value';
|
|
4
2
|
export * from './media-query';
|
|
5
3
|
export * from './scroll-state';
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
4
|
+
export * from './web-storage';
|
|
5
|
+
export * from './web-storage-value';
|
|
@@ -1,26 +1,74 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
import type { Readable, Removable, Subscribable, Writable } from '../core/index';
|
|
3
|
+
import type { ValidationSchemaErrorProps, ValidationSchemasErrorProps } from '../validate';
|
|
3
4
|
import type { WebStorage } from './web-storage';
|
|
4
5
|
export interface WebStorageValue<V> extends Subscribable<V>, Readable<V>, Writable<V>, Removable {
|
|
5
6
|
}
|
|
6
7
|
export interface WebStorageValueOptionsWithStorage<Storage extends WebStorage<any>, K extends keyof Storage['~']['output']> {
|
|
7
8
|
storage: Storage;
|
|
8
9
|
key: K;
|
|
9
|
-
onValidationError?: (props:
|
|
10
|
-
issues: StandardSchemaV1.Issue[];
|
|
11
|
-
value: unknown;
|
|
12
|
-
}) => void;
|
|
10
|
+
onValidationError?: (props: ValidationSchemasErrorProps<Storage['~']['output']>) => void;
|
|
13
11
|
}
|
|
14
12
|
export interface WebStorageValueOptionsWithSchema<S extends StandardSchemaV1<unknown>> {
|
|
13
|
+
type: 'localStorage' | 'sessionStorage';
|
|
15
14
|
schema: S;
|
|
16
15
|
key: string;
|
|
17
16
|
defaultValue: StandardSchemaV1.InferOutput<S>;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Handle validation errors.
|
|
19
|
+
*
|
|
20
|
+
* If returns a value, it will be used as the value to validate and return.
|
|
21
|
+
* If returns undefined, the default value will be returned.
|
|
22
|
+
*/
|
|
23
|
+
onValidationError?: (props: ValidationSchemaErrorProps<StandardSchemaV1.InferOutput<S>>) => void | StandardSchemaV1.InferOutput<S>;
|
|
22
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a reactive handle for a localStorage or sessionStorage instance.
|
|
27
|
+
*
|
|
28
|
+
* @example Vanilla
|
|
29
|
+
* ```ts twoslash title="session-storage.ts"
|
|
30
|
+
* import { createWebStorage } from 'seitu/web'
|
|
31
|
+
* import * as z from 'zod'
|
|
32
|
+
*
|
|
33
|
+
* const sessionStorage = createWebStorage({
|
|
34
|
+
* type: 'sessionStorage',
|
|
35
|
+
* schemas: {
|
|
36
|
+
* token: z.string().nullable(),
|
|
37
|
+
* preferences: z.object({ theme: z.enum(['light', 'dark']) }),
|
|
38
|
+
* },
|
|
39
|
+
* defaultValues: { token: null, preferences: { theme: 'light' } },
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* sessionStorage.get() // { token: null, preferences: { theme: 'light' } }
|
|
43
|
+
* sessionStorage.set({ token: 'abc' })
|
|
44
|
+
* sessionStorage.get() // { token: 'abc', preferences: { theme: 'light' } }
|
|
45
|
+
* sessionStorage.subscribe(console.log)
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @example React
|
|
49
|
+
* ```tsx twoslash title="page.tsx"
|
|
50
|
+
* 'use client'
|
|
51
|
+
*
|
|
52
|
+
* import { createWebStorage } from 'seitu/web'
|
|
53
|
+
* import { useSubscription } from 'seitu/react'
|
|
54
|
+
* import * as z from 'zod'
|
|
55
|
+
*
|
|
56
|
+
* const sessionStorage = createWebStorage({
|
|
57
|
+
* type: 'sessionStorage',
|
|
58
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
59
|
+
* defaultValues: { count: 0, name: '' },
|
|
60
|
+
* })
|
|
61
|
+
*
|
|
62
|
+
* export default function Page() {
|
|
63
|
+
* const value = useSubscription(sessionStorage)
|
|
64
|
+
* return (
|
|
65
|
+
* <div>
|
|
66
|
+
* <span>{value.count}</span>
|
|
67
|
+
* <span>{value.name}</span>
|
|
68
|
+
* </div>
|
|
69
|
+
* )
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
23
73
|
export declare function createWebStorageValue<Storage extends WebStorage<any>, K extends keyof Storage['~']['output']>(options: WebStorageValueOptionsWithStorage<Storage, K>): WebStorageValue<Storage['~']['output'][K]>;
|
|
24
|
-
export declare function createWebStorageValue<S extends StandardSchemaV1<unknown>>(options: WebStorageValueOptionsWithSchema<S>
|
|
25
|
-
kind: 'sessionStorage' | 'localStorage';
|
|
26
|
-
}): WebStorageValue<StandardSchemaV1.InferOutput<S>>;
|
|
74
|
+
export declare function createWebStorageValue<S extends StandardSchemaV1<unknown>>(options: WebStorageValueOptionsWithSchema<S>): WebStorageValue<StandardSchemaV1.InferOutput<S>>;
|
|
@@ -1,18 +1,63 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import type { SchemaStore, SchemaStoreOptions
|
|
3
|
-
|
|
2
|
+
import type { SchemaStore, SchemaStoreOptions } from '../core/index';
|
|
3
|
+
import type { ValidationObjectSchemas, ValidationObjectSchemasOutput, ValidationSchemasErrorProps } from '../validate';
|
|
4
|
+
export interface WebStorageOptions<S extends ValidationObjectSchemas> extends Omit<SchemaStoreOptions<S>, 'provider'> {
|
|
5
|
+
type: 'localStorage' | 'sessionStorage';
|
|
4
6
|
keyTransform?: (key: keyof S) => string;
|
|
5
|
-
onValidationError?: <
|
|
6
|
-
issues: StandardSchemaV1.Issue[];
|
|
7
|
-
key: K;
|
|
8
|
-
value: unknown;
|
|
9
|
-
}) => void | StandardSchemaV1.InferOutput<S[K]>;
|
|
7
|
+
onValidationError?: (props: ValidationSchemasErrorProps<ValidationObjectSchemasOutput<S>>) => void | StandardSchemaV1.InferOutput<S[keyof S]>;
|
|
10
8
|
}
|
|
11
9
|
export interface WebStorage<O extends Record<string, unknown>> extends SchemaStore<O> {
|
|
12
10
|
'~': {
|
|
13
|
-
|
|
11
|
+
getDefaultValue: <K extends keyof O>(key: K) => O[K];
|
|
12
|
+
type: 'localStorage' | 'sessionStorage';
|
|
14
13
|
} & SchemaStore<O>['~'];
|
|
15
14
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Creates a reactive handle for a localStorage or sessionStorage instance.
|
|
17
|
+
*
|
|
18
|
+
* @example Vanilla
|
|
19
|
+
* ```ts twoslash title="session-storage.ts"
|
|
20
|
+
* import { createWebStorage } from 'seitu/web'
|
|
21
|
+
* import * as z from 'zod'
|
|
22
|
+
*
|
|
23
|
+
* const sessionStorage = createWebStorage({
|
|
24
|
+
* type: 'sessionStorage',
|
|
25
|
+
* schemas: {
|
|
26
|
+
* token: z.string().nullable(),
|
|
27
|
+
* preferences: z.object({ theme: z.enum(['light', 'dark']) }),
|
|
28
|
+
* },
|
|
29
|
+
* defaultValues: { token: null, preferences: { theme: 'light' } },
|
|
30
|
+
* })
|
|
31
|
+
*
|
|
32
|
+
* sessionStorage.get() // { token: null, preferences: { theme: 'light' } }
|
|
33
|
+
* sessionStorage.set({ token: 'abc' })
|
|
34
|
+
* sessionStorage.get() // { token: 'abc', preferences: { theme: 'light' } }
|
|
35
|
+
* sessionStorage.subscribe(console.log)
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example React
|
|
39
|
+
* ```tsx twoslash title="page.tsx"
|
|
40
|
+
* 'use client'
|
|
41
|
+
*
|
|
42
|
+
* import { createWebStorage } from 'seitu/web'
|
|
43
|
+
* import { useSubscription } from 'seitu/react'
|
|
44
|
+
* import * as z from 'zod'
|
|
45
|
+
*
|
|
46
|
+
* const sessionStorage = createWebStorage({
|
|
47
|
+
* type: 'sessionStorage',
|
|
48
|
+
* schemas: { count: z.number(), name: z.string() },
|
|
49
|
+
* defaultValues: { count: 0, name: '' },
|
|
50
|
+
* })
|
|
51
|
+
*
|
|
52
|
+
* export default function Page() {
|
|
53
|
+
* const value = useSubscription(sessionStorage)
|
|
54
|
+
* return (
|
|
55
|
+
* <div>
|
|
56
|
+
* <span>{value.count}</span>
|
|
57
|
+
* <span>{value.name}</span>
|
|
58
|
+
* </div>
|
|
59
|
+
* )
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function createWebStorage<S extends ValidationObjectSchemas>(options: WebStorageOptions<S>): WebStorage<ValidationObjectSchemasOutput<S>>;
|
package/dist/web.js
CHANGED
|
@@ -1,240 +1,169 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as e, f as t, o as n, s as r } from "./core-BFAZmVJI.js";
|
|
2
2
|
//#region src/web/is-online.ts
|
|
3
|
-
function
|
|
4
|
-
let { subscribe:
|
|
5
|
-
typeof window < "u" && (window.removeEventListener("online",
|
|
6
|
-
}) })
|
|
3
|
+
function i() {
|
|
4
|
+
let { subscribe: n, notify: r } = t({ onFirstSubscribe: () => (typeof window < "u" && (window.addEventListener("online", r), window.addEventListener("offline", r)), () => {
|
|
5
|
+
typeof window < "u" && (window.removeEventListener("online", r), window.removeEventListener("offline", r));
|
|
6
|
+
}) });
|
|
7
|
+
return e(() => typeof navigator > "u" ? !0 : navigator.onLine, n, r);
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/web/media-query.ts
|
|
11
|
+
function a(n) {
|
|
12
|
+
let r = typeof window > "u" ? null : window.matchMedia(n.query), { subscribe: i, notify: a } = t({ onFirstSubscribe: () => (r?.addEventListener("change", a), () => {
|
|
13
|
+
r?.removeEventListener("change", a);
|
|
14
|
+
}) });
|
|
15
|
+
return e(() => r?.matches ?? n.defaultMatches ?? !1, i, a);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/web/scroll-state.ts
|
|
19
|
+
var o = {
|
|
20
|
+
reached: !1,
|
|
21
|
+
remaining: 0
|
|
22
|
+
};
|
|
23
|
+
function s(e) {
|
|
24
|
+
let { direction: n = "both", threshold: r = 0 } = e, i = typeof r == "number" ? {
|
|
25
|
+
top: r,
|
|
26
|
+
bottom: r,
|
|
27
|
+
left: r,
|
|
28
|
+
right: r
|
|
29
|
+
} : {
|
|
30
|
+
top: r.top ?? 0,
|
|
31
|
+
bottom: r.bottom ?? 0,
|
|
32
|
+
left: r.left ?? 0,
|
|
33
|
+
right: r.right ?? 0
|
|
34
|
+
}, a = () => typeof e.element == "function" ? e.element() : e.element, s = () => {
|
|
35
|
+
let e = a(), t = (e, t) => ({
|
|
36
|
+
reached: e,
|
|
37
|
+
remaining: Math.max(0, t)
|
|
38
|
+
});
|
|
39
|
+
if (!e) return {
|
|
40
|
+
top: o,
|
|
41
|
+
bottom: o,
|
|
42
|
+
left: o,
|
|
43
|
+
right: o
|
|
44
|
+
};
|
|
45
|
+
let r = e.scrollTop, s = e.scrollHeight - e.scrollTop - e.clientHeight, c = e.scrollLeft, l = e.scrollWidth - e.scrollLeft - e.clientWidth;
|
|
46
|
+
return {
|
|
47
|
+
top: n === "horizontal" ? o : t(r <= i.top, r),
|
|
48
|
+
bottom: n === "horizontal" ? o : t(s <= i.bottom, s),
|
|
49
|
+
left: n === "vertical" ? o : t(c <= i.left, c),
|
|
50
|
+
right: n === "vertical" ? o : t(l <= i.right, l)
|
|
51
|
+
};
|
|
52
|
+
}, { subscribe: c, notify: l } = t({ onFirstSubscribe() {
|
|
53
|
+
let e = a();
|
|
54
|
+
if (!e) return;
|
|
55
|
+
let t = () => l();
|
|
56
|
+
return e.addEventListener("scroll", t, { passive: !0 }), () => e.removeEventListener("scroll", t);
|
|
57
|
+
} });
|
|
7
58
|
return {
|
|
8
|
-
get:
|
|
9
|
-
subscribe: (
|
|
59
|
+
get: s,
|
|
60
|
+
subscribe: (e, t = {}) => a() ? c(() => e(s()), t) : (e(s()), () => {}),
|
|
10
61
|
"~": {
|
|
11
62
|
output: null,
|
|
12
|
-
notify:
|
|
63
|
+
notify: l
|
|
13
64
|
}
|
|
14
65
|
};
|
|
15
66
|
}
|
|
16
67
|
//#endregion
|
|
17
68
|
//#region src/web/web-storage.ts
|
|
18
|
-
function r
|
|
19
|
-
let
|
|
69
|
+
function c(r) {
|
|
70
|
+
let i = !1, { subscribe: a, notify: o } = t({ onFirstSubscribe: () => {
|
|
20
71
|
let e = () => {
|
|
21
|
-
|
|
72
|
+
i || o();
|
|
22
73
|
};
|
|
23
74
|
return typeof window < "u" && window.addEventListener("storage", e), () => {
|
|
24
75
|
typeof window < "u" && window.removeEventListener("storage", e);
|
|
25
76
|
};
|
|
26
|
-
} }),
|
|
27
|
-
if (typeof window > "u") return
|
|
28
|
-
let
|
|
29
|
-
for (let
|
|
30
|
-
let a =
|
|
31
|
-
|
|
32
|
-
r[i] = n.defaultValues[i];
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
let o = e(a), s = n.schemas[i]["~standard"].validate(o);
|
|
36
|
-
if (s instanceof Promise) throw TypeError("[createWebStorage] Validation schema should not return a Promise.");
|
|
37
|
-
if (s.issues) if (n.onValidationError) {
|
|
38
|
-
let e = n.onValidationError({
|
|
39
|
-
issues: [...s.issues],
|
|
40
|
-
key: i,
|
|
41
|
-
value: o
|
|
42
|
-
});
|
|
43
|
-
if (e !== void 0) {
|
|
44
|
-
let t = n.schemas[i]["~standard"].validate(e);
|
|
45
|
-
if (t instanceof Promise) throw TypeError("[createWebStorage] Validation schema should not return a Promise.");
|
|
46
|
-
t.issues ? console.warn(`[createWebStorage] Returned value invalid for key ${i}, returned default value instead`, JSON.stringify(t.issues, null, 2), { cause: t.issues }) : r[i] = t.value;
|
|
47
|
-
}
|
|
48
|
-
} else console.warn(`[createWebStorage] Returned value invalid for key ${i}, returned default value instead`, JSON.stringify(s.issues, null, 2), { cause: s.issues }), r[i] = n.defaultValues[i];
|
|
49
|
-
else r[i] = s.value;
|
|
77
|
+
} }), s = { ...r.defaultValues }, c = Object.keys(r.defaultValues), l = /* @__PURE__ */ new Map(), u, d = () => {
|
|
78
|
+
if (typeof window > "u") return r.defaultValues;
|
|
79
|
+
let e = window[r.type], t = u !== void 0, i = {};
|
|
80
|
+
for (let n of c) {
|
|
81
|
+
let a = String(r.keyTransform ? r.keyTransform(n) : n), o = e.getItem(a);
|
|
82
|
+
i[n] = o, t && l.get(n) !== o && (t = !1);
|
|
50
83
|
}
|
|
51
|
-
return
|
|
52
|
-
|
|
84
|
+
if (t) return u;
|
|
85
|
+
let a = { ...r.defaultValues };
|
|
86
|
+
for (let e of c) {
|
|
87
|
+
let t = i[e];
|
|
88
|
+
t === null ? a[e] = r.defaultValues[e] : a[e] = n(r.schemas[e], t, {
|
|
89
|
+
defaultValue: r.defaultValues[e],
|
|
90
|
+
label: `createWebStorage:${String(e)}`,
|
|
91
|
+
onError: r.onValidationError ? (t, n) => r.onValidationError({
|
|
92
|
+
issues: [...t],
|
|
93
|
+
key: e,
|
|
94
|
+
value: n,
|
|
95
|
+
defaultValue: r.defaultValues[e]
|
|
96
|
+
}) : void 0
|
|
97
|
+
}), l.set(String(e), i[String(e)]);
|
|
98
|
+
}
|
|
99
|
+
return u = a, a;
|
|
100
|
+
}, f = e(d, a, o);
|
|
53
101
|
return {
|
|
54
|
-
|
|
102
|
+
...f,
|
|
55
103
|
set: (e) => {
|
|
56
|
-
let t = typeof e == "function" ? e(
|
|
104
|
+
let t = typeof e == "function" ? e(d()) : e;
|
|
57
105
|
if (typeof window > "u") return;
|
|
58
|
-
let
|
|
59
|
-
|
|
60
|
-
let
|
|
61
|
-
|
|
62
|
-
key:
|
|
63
|
-
newValue:
|
|
106
|
+
let n = window[r.type];
|
|
107
|
+
i = !0, Object.entries(t).forEach(([e, t]) => {
|
|
108
|
+
let i = typeof t == "string" ? t : JSON.stringify(t);
|
|
109
|
+
n.setItem(r.keyTransform ? r.keyTransform(e) : e, i), window.dispatchEvent(new StorageEvent("storage", {
|
|
110
|
+
key: r.keyTransform ? r.keyTransform(e) : e,
|
|
111
|
+
newValue: i
|
|
64
112
|
}));
|
|
65
|
-
}),
|
|
113
|
+
}), i = !1, u = void 0, o();
|
|
66
114
|
},
|
|
67
|
-
getDefaultValue: (e) => o[e],
|
|
68
|
-
subscribe: (e, t = {}) => i(() => e(s()), t),
|
|
69
115
|
"~": {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
116
|
+
...f["~"],
|
|
117
|
+
getDefaultValue: (e) => s[e],
|
|
118
|
+
type: r.type
|
|
73
119
|
}
|
|
74
120
|
};
|
|
75
121
|
}
|
|
76
122
|
//#endregion
|
|
77
|
-
//#region src/web/local-storage.ts
|
|
78
|
-
function i(e) {
|
|
79
|
-
return r({
|
|
80
|
-
kind: "localStorage",
|
|
81
|
-
...e
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
//#endregion
|
|
85
123
|
//#region src/web/web-storage-value.ts
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (n.key === void 0) throw Error(`[${a}] Key is required`);
|
|
90
|
-
if (!("schema" in n || "storage" in n)) throw Error(`[${a}] Either schema or storage must be provided`);
|
|
91
|
-
let o = ("schema" in n ? n.defaultValue : n.storage.getDefaultValue(n.key)) ?? null, { subscribe: s, notify: c } = t({ onFirstSubscribe: () => {
|
|
124
|
+
var l = Symbol("no-cache");
|
|
125
|
+
function u(i) {
|
|
126
|
+
let a = "storage" in i ? i.storage["~"].type : i.type, o = !1, s = ("schema" in i ? i.defaultValue : i.storage["~"].getDefaultValue(i.key)) ?? null, { subscribe: c, notify: u } = t({ onFirstSubscribe: () => {
|
|
92
127
|
let e = (e) => {
|
|
93
|
-
|
|
128
|
+
o || e.key === i.key && u();
|
|
94
129
|
};
|
|
95
130
|
return typeof window < "u" && window.addEventListener("storage", e), () => {
|
|
96
131
|
typeof window < "u" && window.removeEventListener("storage", e);
|
|
97
132
|
};
|
|
98
|
-
} }), l = () => {
|
|
99
|
-
if (typeof window > "u") return
|
|
100
|
-
let
|
|
101
|
-
if (
|
|
102
|
-
|
|
133
|
+
} }), d = l, f, p = () => {
|
|
134
|
+
if (typeof window > "u") return s;
|
|
135
|
+
let e = window[a].getItem(i.key);
|
|
136
|
+
if (d !== l && e === d) return f;
|
|
137
|
+
if (d = e, e === null) return f = s, f;
|
|
138
|
+
let t = r(e);
|
|
103
139
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (t !== void 0) {
|
|
114
|
-
let e = n.schema["~standard"].validate(t);
|
|
115
|
-
if (e instanceof Promise) throw TypeError("Validation schema should not return a Promise.");
|
|
116
|
-
if (e.issues) console.warn(`[${a}] Returned value invalid for key ${n.key}, returned default value instead`, JSON.stringify(e.issues, null, 2), { cause: e.issues });
|
|
117
|
-
else return e.value;
|
|
118
|
-
}
|
|
119
|
-
} else console.warn(`[${a}] Returned value invalid for key ${n.key}, returned default value instead`, JSON.stringify(e.issues, null, 2), { cause: e.issues });
|
|
120
|
-
return o;
|
|
121
|
-
}
|
|
122
|
-
return e.value;
|
|
123
|
-
} else return i;
|
|
140
|
+
return "schema" in i ? (f = n(i.schema, e, {
|
|
141
|
+
defaultValue: s,
|
|
142
|
+
label: `createWebStorageValue:${i.key}`,
|
|
143
|
+
onError: i.onValidationError ? (e, t) => i.onValidationError({
|
|
144
|
+
defaultValue: s,
|
|
145
|
+
issues: [...e],
|
|
146
|
+
value: t
|
|
147
|
+
}) : void 0
|
|
148
|
+
}), f) : (f = t, f);
|
|
124
149
|
} catch {
|
|
125
|
-
return
|
|
150
|
+
return f = s !== void 0 && typeof s != "string" ? s : t, f;
|
|
126
151
|
}
|
|
127
152
|
};
|
|
128
153
|
return {
|
|
129
|
-
|
|
154
|
+
...e(p, c, u),
|
|
130
155
|
set: (e) => {
|
|
131
156
|
if (typeof window > "u") return;
|
|
132
|
-
let t = window[
|
|
133
|
-
|
|
134
|
-
key:
|
|
135
|
-
newValue:
|
|
136
|
-
})),
|
|
157
|
+
let t = window[a], n = typeof e == "function" ? e(p()) : e;
|
|
158
|
+
o = !0, t.setItem(i.key, typeof n == "string" ? n : JSON.stringify(n)), window.dispatchEvent(new StorageEvent("storage", {
|
|
159
|
+
key: i.key,
|
|
160
|
+
newValue: n
|
|
161
|
+
})), o = !1, d = l, u();
|
|
137
162
|
},
|
|
138
|
-
subscribe: (e, t = {}) => s(() => e(l()), t),
|
|
139
163
|
remove: () => {
|
|
140
|
-
typeof window > "u" || window[
|
|
141
|
-
},
|
|
142
|
-
"~": {
|
|
143
|
-
output: null,
|
|
144
|
-
notify: c
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
//#endregion
|
|
149
|
-
//#region src/web/local-storage-value.ts
|
|
150
|
-
function o(e) {
|
|
151
|
-
return "storage" in e ? a(e) : a({
|
|
152
|
-
...e,
|
|
153
|
-
kind: "localStorage"
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
//#endregion
|
|
157
|
-
//#region src/web/media-query.ts
|
|
158
|
-
function s(e) {
|
|
159
|
-
let n = typeof window > "u" ? null : window.matchMedia(e.query), { subscribe: r, notify: i } = t({ onFirstSubscribe: () => (n?.addEventListener("change", i), () => {
|
|
160
|
-
n?.removeEventListener("change", i);
|
|
161
|
-
}) }), a = () => n?.matches ?? e.defaultMatches ?? !1;
|
|
162
|
-
return {
|
|
163
|
-
get: a,
|
|
164
|
-
subscribe: (e, t = {}) => r(() => e(a()), t),
|
|
165
|
-
"~": {
|
|
166
|
-
output: null,
|
|
167
|
-
notify: i
|
|
164
|
+
typeof window > "u" || (window[a].removeItem(i.key), d = l);
|
|
168
165
|
}
|
|
169
166
|
};
|
|
170
167
|
}
|
|
171
168
|
//#endregion
|
|
172
|
-
|
|
173
|
-
var c = {
|
|
174
|
-
reached: !1,
|
|
175
|
-
remaining: 0
|
|
176
|
-
};
|
|
177
|
-
function l(e) {
|
|
178
|
-
let { direction: n = "both", threshold: r = 0 } = e, { subscribe: i, notify: a } = t(), o = typeof r == "number" ? {
|
|
179
|
-
top: r,
|
|
180
|
-
bottom: r,
|
|
181
|
-
left: r,
|
|
182
|
-
right: r
|
|
183
|
-
} : {
|
|
184
|
-
top: r.top ?? 0,
|
|
185
|
-
bottom: r.bottom ?? 0,
|
|
186
|
-
left: r.left ?? 0,
|
|
187
|
-
right: r.right ?? 0
|
|
188
|
-
}, s = () => typeof e.element == "function" ? e.element() : e.element, l = () => {
|
|
189
|
-
let e = s(), t = (e, t) => ({
|
|
190
|
-
reached: e,
|
|
191
|
-
remaining: Math.max(0, t)
|
|
192
|
-
});
|
|
193
|
-
if (!e) return {
|
|
194
|
-
top: c,
|
|
195
|
-
bottom: c,
|
|
196
|
-
left: c,
|
|
197
|
-
right: c
|
|
198
|
-
};
|
|
199
|
-
let r = e.scrollTop, i = e.scrollHeight - e.scrollTop - e.clientHeight, a = e.scrollLeft, l = e.scrollWidth - e.scrollLeft - e.clientWidth;
|
|
200
|
-
return {
|
|
201
|
-
top: n === "horizontal" ? c : t(r <= o.top, r),
|
|
202
|
-
bottom: n === "horizontal" ? c : t(i <= o.bottom, i),
|
|
203
|
-
left: n === "vertical" ? c : t(a <= o.left, a),
|
|
204
|
-
right: n === "vertical" ? c : t(l <= o.right, l)
|
|
205
|
-
};
|
|
206
|
-
};
|
|
207
|
-
return {
|
|
208
|
-
get: l,
|
|
209
|
-
subscribe: (e, t = {}) => {
|
|
210
|
-
let n = s();
|
|
211
|
-
if (!n) return e(l()), () => {};
|
|
212
|
-
let r = i(() => e(l()), t), a = () => e(l());
|
|
213
|
-
return n.addEventListener("scroll", a, { passive: !0 }), () => {
|
|
214
|
-
r(), n.removeEventListener("scroll", a);
|
|
215
|
-
};
|
|
216
|
-
},
|
|
217
|
-
"~": {
|
|
218
|
-
output: null,
|
|
219
|
-
notify: a
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
//#endregion
|
|
224
|
-
//#region src/web/session-storage.ts
|
|
225
|
-
function u(e) {
|
|
226
|
-
return r({
|
|
227
|
-
kind: "sessionStorage",
|
|
228
|
-
...e
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
//#endregion
|
|
232
|
-
//#region src/web/session-storage-value.ts
|
|
233
|
-
function d(e) {
|
|
234
|
-
return "storage" in e ? a(e) : a({
|
|
235
|
-
...e,
|
|
236
|
-
kind: "sessionStorage"
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
//#endregion
|
|
240
|
-
export { n as createIsOnline, i as createLocalStorage, o as createLocalStorageValue, s as createMediaQuery, l as createScrollState, u as createSessionStorage, d as createSessionStorageValue };
|
|
169
|
+
export { i as createIsOnline, a as createMediaQuery, s as createScrollState, c as createWebStorage, u as createWebStorageValue };
|
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.10.1",
|
|
6
6
|
"private": false,
|
|
7
7
|
"author": "Valerii Strilets",
|
|
8
8
|
"license": "MIT",
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"./vue": {
|
|
40
40
|
"types": "./dist/vue/index.d.ts",
|
|
41
41
|
"import": "./dist/vue.js"
|
|
42
|
+
},
|
|
43
|
+
"./utils": {
|
|
44
|
+
"types": "./dist/utils/index.d.ts",
|
|
45
|
+
"import": "./dist/utils.js"
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"main": "./dist/core.js",
|
package/dist/core-vtgV_plC.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
//#region src/core/subscription.ts
|
|
2
|
-
function e(e) {
|
|
3
|
-
let t = /* @__PURE__ */ new Set(), n = () => t.forEach((e) => e()), r;
|
|
4
|
-
return {
|
|
5
|
-
subscribe(n, i) {
|
|
6
|
-
return t.size === 0 && e?.onFirstSubscribe && (r = e.onFirstSubscribe() ?? void 0), i?.immediate && n(), t.add(n), () => {
|
|
7
|
-
t.delete(n), t.size === 0 && (r?.(), r = void 0);
|
|
8
|
-
};
|
|
9
|
-
},
|
|
10
|
-
notify: n
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/core/computed.ts
|
|
15
|
-
function t(t, n) {
|
|
16
|
-
let { subscribe: r, notify: i } = e(), a = Array.isArray(t) ? t : [t], o = !Array.isArray(t), s = () => n(o ? a[0].get() : a.map((e) => e.get()));
|
|
17
|
-
for (let e of a) e.subscribe(() => i());
|
|
18
|
-
return {
|
|
19
|
-
get: s,
|
|
20
|
-
subscribe(e, t) {
|
|
21
|
-
return r(() => e(s()), t);
|
|
22
|
-
},
|
|
23
|
-
"~": {
|
|
24
|
-
output: null,
|
|
25
|
-
notify: i
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/core/debounce.ts
|
|
31
|
-
function n(t, n) {
|
|
32
|
-
let r = t.get(), i, { subscribe: a, notify: o } = e({ onFirstSubscribe() {
|
|
33
|
-
let e = t.subscribe(() => {
|
|
34
|
-
clearTimeout(i), i = setTimeout(() => {
|
|
35
|
-
r = t.get(), o();
|
|
36
|
-
}, n);
|
|
37
|
-
});
|
|
38
|
-
return () => {
|
|
39
|
-
clearTimeout(i), e();
|
|
40
|
-
};
|
|
41
|
-
} }), s = () => r;
|
|
42
|
-
return {
|
|
43
|
-
get: s,
|
|
44
|
-
subscribe(e, t) {
|
|
45
|
-
return a(() => e(s()), t);
|
|
46
|
-
},
|
|
47
|
-
"~": {
|
|
48
|
-
output: null,
|
|
49
|
-
notify: o
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
//#endregion
|
|
54
|
-
//#region src/core/debounce-fn.ts
|
|
55
|
-
function r(t, n) {
|
|
56
|
-
let r, i, { subscribe: a, notify: o } = e(), s = () => r;
|
|
57
|
-
return Object.assign((...e) => {
|
|
58
|
-
clearTimeout(i), i = setTimeout(() => {
|
|
59
|
-
r = t(...e), o();
|
|
60
|
-
}, n);
|
|
61
|
-
}, {
|
|
62
|
-
get: s,
|
|
63
|
-
subscribe: (e, t) => a(() => e(s()), t),
|
|
64
|
-
"~": {
|
|
65
|
-
output: void 0,
|
|
66
|
-
notify: o
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
//#endregion
|
|
71
|
-
//#region src/utils.ts
|
|
72
|
-
function i(e) {
|
|
73
|
-
if (typeof e != "string") return e;
|
|
74
|
-
try {
|
|
75
|
-
return JSON.parse(e);
|
|
76
|
-
} catch {
|
|
77
|
-
return e;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
//#endregion
|
|
81
|
-
//#region src/core/schema-store.ts
|
|
82
|
-
function a(t) {
|
|
83
|
-
let { subscribe: n, notify: r } = e(), a = { ...t.defaultValues }, s = t.provider ?? o(), c = () => {
|
|
84
|
-
let e = { ...a };
|
|
85
|
-
for (let [n, r] of Object.entries(t.schemas)) {
|
|
86
|
-
let t = s.get()[n], o = r["~standard"].validate(i(t));
|
|
87
|
-
if (o instanceof Promise) throw TypeError("[createStorage] Validation schema should not return a Promise.");
|
|
88
|
-
o.issues && console.warn(`[createSchemaStore] Returned value invalid for key ${String(n)}, returned default value instead`, JSON.stringify(o.issues, null, 2), { cause: o.issues }), e[n] = o.issues ? a[n] : o.value;
|
|
89
|
-
}
|
|
90
|
-
return e;
|
|
91
|
-
};
|
|
92
|
-
return {
|
|
93
|
-
get: c,
|
|
94
|
-
set: (e) => {
|
|
95
|
-
let t = typeof e == "function" ? e(c()) : e;
|
|
96
|
-
s.set(t), r();
|
|
97
|
-
},
|
|
98
|
-
getDefaultValue: (e) => a[e],
|
|
99
|
-
subscribe: (e, t) => n(() => e(c()), t),
|
|
100
|
-
"~": {
|
|
101
|
-
output: null,
|
|
102
|
-
notify: r
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
function o() {
|
|
107
|
-
let e = s({});
|
|
108
|
-
return {
|
|
109
|
-
get: () => e.get(),
|
|
110
|
-
set: (t) => {
|
|
111
|
-
e.set(t);
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region src/core/store.ts
|
|
117
|
-
function s(t) {
|
|
118
|
-
let n = t, { subscribe: r, notify: i } = e(), a = () => n;
|
|
119
|
-
return {
|
|
120
|
-
get: a,
|
|
121
|
-
set: (e) => {
|
|
122
|
-
let t = typeof e == "function" ? e(n) : e;
|
|
123
|
-
t !== n && (n = t, i());
|
|
124
|
-
},
|
|
125
|
-
subscribe(e, t) {
|
|
126
|
-
return r(() => e(a()), t);
|
|
127
|
-
},
|
|
128
|
-
"~": {
|
|
129
|
-
output: null,
|
|
130
|
-
notify: i
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
//#endregion
|
|
135
|
-
//#region src/core/throttle.ts
|
|
136
|
-
function c(t, n) {
|
|
137
|
-
let r = t.get(), i, a = !1, { subscribe: o, notify: s } = e({ onFirstSubscribe() {
|
|
138
|
-
let e = t.subscribe(() => {
|
|
139
|
-
if (i) {
|
|
140
|
-
a = !0;
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
r = t.get(), s(), i = setTimeout(() => {
|
|
144
|
-
i = void 0, a && (a = !1, r = t.get(), s());
|
|
145
|
-
}, n);
|
|
146
|
-
});
|
|
147
|
-
return () => {
|
|
148
|
-
clearTimeout(i), i = void 0, a = !1, e();
|
|
149
|
-
};
|
|
150
|
-
} }), c = () => r;
|
|
151
|
-
return {
|
|
152
|
-
get: c,
|
|
153
|
-
subscribe(e, t) {
|
|
154
|
-
return o(() => e(c()), t);
|
|
155
|
-
},
|
|
156
|
-
"~": {
|
|
157
|
-
output: null,
|
|
158
|
-
notify: s
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
//#endregion
|
|
163
|
-
//#region src/core/throttle-fn.ts
|
|
164
|
-
function l(t, n) {
|
|
165
|
-
let r, i, a, { subscribe: o, notify: s } = e(), c = () => r;
|
|
166
|
-
return Object.assign((...e) => {
|
|
167
|
-
if (i) {
|
|
168
|
-
a = e;
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
r = t(...e), s(), i = setTimeout(() => {
|
|
172
|
-
if (i = void 0, a) {
|
|
173
|
-
let e = a;
|
|
174
|
-
a = void 0, r = t(...e), s();
|
|
175
|
-
}
|
|
176
|
-
}, n);
|
|
177
|
-
}, {
|
|
178
|
-
get: c,
|
|
179
|
-
subscribe: (e, t) => o(() => e(c()), t),
|
|
180
|
-
"~": {
|
|
181
|
-
output: void 0,
|
|
182
|
-
notify: s
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
//#endregion
|
|
187
|
-
export { o as a, n as c, a as i, t as l, c as n, i as o, s as r, r as s, l as t, e as u };
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import type { LocalStorage } from './local-storage';
|
|
3
|
-
import type { WebStorageValue as LocalStorageValue, WebStorageValueOptionsWithSchema as LocalStorageValueOptionsWithSchema, WebStorageValueOptionsWithStorage as LocalStorageValueOptionsWithStorage } from './web-storage-value';
|
|
4
|
-
export type { LocalStorageValue, LocalStorageValueOptionsWithSchema, LocalStorageValueOptionsWithStorage, };
|
|
5
|
-
/**
|
|
6
|
-
* Creates a reactive handle for a single localStorage value.
|
|
7
|
-
*
|
|
8
|
-
* Two modes:
|
|
9
|
-
* - **Schema mode** (`schema`, `key`, `defaultValue`): standalone key with validation. Missing or
|
|
10
|
-
* invalid stored data returns `defaultValue`.
|
|
11
|
-
* - **Storage mode** (`storage`, `key`): binds to one key of a `createLocalStorage` instance.
|
|
12
|
-
* Type and default come from that storage.
|
|
13
|
-
*
|
|
14
|
-
* @example Vanilla
|
|
15
|
-
* ```ts twoslash title="local-storage-value.ts"
|
|
16
|
-
* import { createLocalStorageValue } from 'seitu/web'
|
|
17
|
-
* import * as z from 'zod'
|
|
18
|
-
*
|
|
19
|
-
* const value = createLocalStorageValue({
|
|
20
|
-
* key: 'count',
|
|
21
|
-
* defaultValue: 0,
|
|
22
|
-
* schema: z.number(),
|
|
23
|
-
* })
|
|
24
|
-
* value.get() // 0
|
|
25
|
-
* value.set(1)
|
|
26
|
-
* value.set(v => v + 1)
|
|
27
|
-
* value.subscribe(v => console.log(v))
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @example Storage mode
|
|
31
|
-
* ```ts twoslash title="local-storage-value.ts"
|
|
32
|
-
* import { createLocalStorage, createLocalStorageValue } from 'seitu/web'
|
|
33
|
-
* import * as z from 'zod'
|
|
34
|
-
*
|
|
35
|
-
* const storage = createLocalStorage({
|
|
36
|
-
* schemas: { count: z.number(), name: z.string() },
|
|
37
|
-
* defaultValues: { count: 0, name: '' },
|
|
38
|
-
* })
|
|
39
|
-
* const count = createLocalStorageValue({ storage, key: 'count' })
|
|
40
|
-
* count.set(5)
|
|
41
|
-
* storage.get().count === 5 // true
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @example React
|
|
45
|
-
* ```tsx twoslash title="page.tsx"
|
|
46
|
-
* 'use client'
|
|
47
|
-
*
|
|
48
|
-
* import { createLocalStorageValue } from 'seitu/web'
|
|
49
|
-
* import { useSubscription } from 'seitu/react'
|
|
50
|
-
* import * as z from 'zod'
|
|
51
|
-
*
|
|
52
|
-
* export default function Page() {
|
|
53
|
-
* const count = useSubscription(() => createLocalStorageValue({
|
|
54
|
-
* key: 'count',
|
|
55
|
-
* defaultValue: 0,
|
|
56
|
-
* schema: z.number(),
|
|
57
|
-
* }))
|
|
58
|
-
*
|
|
59
|
-
* return (
|
|
60
|
-
* <div>
|
|
61
|
-
* <span>{count}</span>
|
|
62
|
-
* </div>
|
|
63
|
-
* )
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
export declare function createLocalStorageValue<Storage extends LocalStorage<any>, K extends keyof Storage['~']['output']>(options: LocalStorageValueOptionsWithStorage<Storage, K>): LocalStorageValue<Storage['~']['output'][K]>;
|
|
68
|
-
export declare function createLocalStorageValue<S extends StandardSchemaV1<unknown>>(options: LocalStorageValueOptionsWithSchema<S>): LocalStorageValue<StandardSchemaV1.InferOutput<S>>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { SchemaStoreOutput, SchemaStoreSchema } from '../core/index';
|
|
2
|
-
import type { WebStorage as LocalStorage, WebStorageOptions as LocalStorageOptions } from './web-storage';
|
|
3
|
-
export type { LocalStorage, LocalStorageOptions };
|
|
4
|
-
/**
|
|
5
|
-
* Creates a reactive handle for a localStorage instance.
|
|
6
|
-
*
|
|
7
|
-
* @example Vanilla
|
|
8
|
-
* ```ts twoslash title="local-storage.ts"
|
|
9
|
-
* import { createLocalStorage } from 'seitu/web'
|
|
10
|
-
* import * as z from 'zod'
|
|
11
|
-
*
|
|
12
|
-
* const localStorage = createLocalStorage({
|
|
13
|
-
* schemas: {
|
|
14
|
-
* token: z.string().nullable(),
|
|
15
|
-
* preferences: z.object({ theme: z.enum(['light', 'dark']) }),
|
|
16
|
-
* },
|
|
17
|
-
* defaultValues: { token: null, preferences: { theme: 'light' } },
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* localStorage.get() // { token: null, preferences: { theme: 'light' } }
|
|
21
|
-
* localStorage.set({ token: 'abc' })
|
|
22
|
-
* localStorage.get() // { token: 'abc', preferences: { theme: 'light' } }
|
|
23
|
-
* localStorage.subscribe(console.log)
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @example React
|
|
27
|
-
* ```tsx twoslash title="page.tsx"
|
|
28
|
-
* 'use client'
|
|
29
|
-
*
|
|
30
|
-
* import { createLocalStorage } from 'seitu/web'
|
|
31
|
-
* import { useSubscription } from 'seitu/react'
|
|
32
|
-
* import * as z from 'zod'
|
|
33
|
-
*
|
|
34
|
-
* const localStorage = createLocalStorage({
|
|
35
|
-
* schemas: { count: z.number(), name: z.string() },
|
|
36
|
-
* defaultValues: { count: 0, name: '' },
|
|
37
|
-
* })
|
|
38
|
-
*
|
|
39
|
-
* export default function Page() {
|
|
40
|
-
* const value = useSubscription(localStorage)
|
|
41
|
-
* return (
|
|
42
|
-
* <div>
|
|
43
|
-
* <span>{value.count}</span>
|
|
44
|
-
* <span>{value.name}</span>
|
|
45
|
-
* </div>
|
|
46
|
-
* )
|
|
47
|
-
* }
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export declare function createLocalStorage<S extends SchemaStoreSchema>(options: LocalStorageOptions<S>): LocalStorage<SchemaStoreOutput<S>>;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
-
import type { SessionStorage } from './session-storage';
|
|
3
|
-
import type { WebStorageValue as SessionStorageValue, WebStorageValueOptionsWithSchema as SessionStorageValueOptionsWithSchema, WebStorageValueOptionsWithStorage as SessionStorageValueOptionsWithStorage } from './web-storage-value';
|
|
4
|
-
export type { SessionStorageValue, SessionStorageValueOptionsWithSchema, SessionStorageValueOptionsWithStorage, };
|
|
5
|
-
/**
|
|
6
|
-
* Creates a reactive handle for a single sessionStorage value.
|
|
7
|
-
*
|
|
8
|
-
* Two modes:
|
|
9
|
-
* - **Schema mode** (`schema`, `key`, `defaultValue`): standalone key with validation. Missing or
|
|
10
|
-
* invalid stored data returns `defaultValue`.
|
|
11
|
-
* - **Storage mode** (`storage`, `key`): binds to one key of a `createSessionStorage` instance.
|
|
12
|
-
* Type and default come from that storage.
|
|
13
|
-
*
|
|
14
|
-
* @example Vanilla
|
|
15
|
-
* ```ts twoslash title="session-storage-value.ts"
|
|
16
|
-
* import { createSessionStorageValue } from 'seitu/web'
|
|
17
|
-
* import * as z from 'zod'
|
|
18
|
-
*
|
|
19
|
-
* const value = createSessionStorageValue({
|
|
20
|
-
* key: 'count',
|
|
21
|
-
* defaultValue: 0,
|
|
22
|
-
* schema: z.number(),
|
|
23
|
-
* })
|
|
24
|
-
* value.get() // 0
|
|
25
|
-
* value.set(1)
|
|
26
|
-
* value.set(v => v + 1)
|
|
27
|
-
* value.subscribe(v => console.log(v))
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @example Storage mode
|
|
31
|
-
* ```ts twoslash title="session-storage-value.ts"
|
|
32
|
-
* import { createSessionStorage, createSessionStorageValue } from 'seitu/web'
|
|
33
|
-
* import * as z from 'zod'
|
|
34
|
-
*
|
|
35
|
-
* const storage = createSessionStorage({
|
|
36
|
-
* schemas: { count: z.number(), name: z.string() },
|
|
37
|
-
* defaultValues: { count: 0, name: '' },
|
|
38
|
-
* })
|
|
39
|
-
* const count = createSessionStorageValue({ storage, key: 'count' })
|
|
40
|
-
* count.set(5)
|
|
41
|
-
* storage.get().count === 5 // true
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @example React
|
|
45
|
-
* ```tsx twoslash title="page.tsx"
|
|
46
|
-
* 'use client'
|
|
47
|
-
*
|
|
48
|
-
* import { createSessionStorageValue } from 'seitu/web'
|
|
49
|
-
* import { useSubscription } from 'seitu/react'
|
|
50
|
-
* import * as z from 'zod'
|
|
51
|
-
*
|
|
52
|
-
* export default function Page() {
|
|
53
|
-
* const count = useSubscription(() => createSessionStorageValue({
|
|
54
|
-
* key: 'count',
|
|
55
|
-
* defaultValue: 0,
|
|
56
|
-
* schema: z.number(),
|
|
57
|
-
* }))
|
|
58
|
-
*
|
|
59
|
-
* return (
|
|
60
|
-
* <div>
|
|
61
|
-
* <span>{count}</span>
|
|
62
|
-
* </div>
|
|
63
|
-
* )
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
export declare function createSessionStorageValue<Storage extends SessionStorage<any>, K extends keyof Storage['~']['output']>(options: SessionStorageValueOptionsWithStorage<Storage, K>): SessionStorageValue<Storage['~']['output'][K]>;
|
|
68
|
-
export declare function createSessionStorageValue<S extends StandardSchemaV1<unknown>>(options: SessionStorageValueOptionsWithSchema<S>): SessionStorageValue<StandardSchemaV1.InferOutput<S>>;
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import type { SchemaStoreOutput, SchemaStoreSchema } from '../core/index';
|
|
2
|
-
import type { WebStorage as SessionStorage, WebStorageOptions as SessionStorageOptions } from './web-storage';
|
|
3
|
-
export type { SessionStorage, SessionStorageOptions };
|
|
4
|
-
/**
|
|
5
|
-
* Creates a reactive handle for a sessionStorage instance.
|
|
6
|
-
*
|
|
7
|
-
* @example Vanilla
|
|
8
|
-
* ```ts twoslash title="session-storage.ts"
|
|
9
|
-
* import { createSessionStorage } from 'seitu/web'
|
|
10
|
-
* import * as z from 'zod'
|
|
11
|
-
*
|
|
12
|
-
* const sessionStorage = createSessionStorage({
|
|
13
|
-
* schemas: {
|
|
14
|
-
* token: z.string().nullable(),
|
|
15
|
-
* preferences: z.object({ theme: z.enum(['light', 'dark']) }),
|
|
16
|
-
* },
|
|
17
|
-
* defaultValues: { token: null, preferences: { theme: 'light' } },
|
|
18
|
-
* })
|
|
19
|
-
*
|
|
20
|
-
* sessionStorage.get() // { token: null, preferences: { theme: 'light' } }
|
|
21
|
-
* sessionStorage.set({ token: 'abc' })
|
|
22
|
-
* sessionStorage.get() // { token: 'abc', preferences: { theme: 'light' } }
|
|
23
|
-
* sessionStorage.subscribe(console.log)
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @example React
|
|
27
|
-
* ```tsx twoslash title="page.tsx"
|
|
28
|
-
* 'use client'
|
|
29
|
-
*
|
|
30
|
-
* import { createSessionStorage } from 'seitu/web'
|
|
31
|
-
* import { useSubscription } from 'seitu/react'
|
|
32
|
-
* import * as z from 'zod'
|
|
33
|
-
*
|
|
34
|
-
* const sessionStorage = createSessionStorage({
|
|
35
|
-
* schemas: { count: z.number(), name: z.string() },
|
|
36
|
-
* defaultValues: { count: 0, name: '' },
|
|
37
|
-
* })
|
|
38
|
-
*
|
|
39
|
-
* export default function Page() {
|
|
40
|
-
* const value = useSubscription(sessionStorage)
|
|
41
|
-
* return (
|
|
42
|
-
* <div>
|
|
43
|
-
* <span>{value.count}</span>
|
|
44
|
-
* <span>{value.name}</span>
|
|
45
|
-
* </div>
|
|
46
|
-
* )
|
|
47
|
-
* }
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export declare function createSessionStorage<S extends SchemaStoreSchema>(options: SessionStorageOptions<S>): SessionStorage<SchemaStoreOutput<S>>;
|