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.
@@ -1,16 +1,14 @@
1
1
  import type { StandardSchemaV1 } from '@standard-schema/spec';
2
- import type { Simplify } from '../utils';
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
- getDefaultValue: <K extends keyof O>(key: K) => O[K];
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: SchemaStoreOutput<S>;
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<SchemaStoreOutput<S>>;
39
- export interface SchemaStoreProvider<S extends SchemaStoreSchema> {
40
- get: () => SchemaStoreOutput<S>;
41
- set: (value: Partial<SchemaStoreOutput<S>>) => void;
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 SchemaStoreSchema>(): SchemaStoreProvider<S>;
57
+ export declare function createSchemaStoreMemoryProvider<S extends ValidationObjectSchemas>(): SchemaStoreProvider<S>;
@@ -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 Storestyle API).
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, i as n, l as r, n as i, r as a, s as o, t as s, u as c } from "./core-vtgV_plC.js";
2
- export { r as createComputed, t as createDebounce, o as createDebounceFn, n as createSchemaStore, e as createSchemaStoreMemoryProvider, a as createStore, c as createSubscription, i as createThrottle, s as createThrottleFn };
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;
@@ -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 './session-storage';
7
- export * from './session-storage-value';
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
- onValidationError?: (props: {
19
- issues: StandardSchemaV1.Issue[];
20
- value: unknown;
21
- }) => void | StandardSchemaV1.InferOutput<S>;
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, SchemaStoreOutput, SchemaStoreSchema } from '../core/index';
3
- export interface WebStorageOptions<S extends SchemaStoreSchema> extends Omit<SchemaStoreOptions<S>, 'provider'> {
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?: <K extends keyof S>(props: {
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
- kind: 'sessionStorage' | 'localStorage';
11
+ getDefaultValue: <K extends keyof O>(key: K) => O[K];
12
+ type: 'localStorage' | 'sessionStorage';
14
13
  } & SchemaStore<O>['~'];
15
14
  }
16
- export declare function createWebStorage<S extends SchemaStoreSchema>(options: WebStorageOptions<S> & {
17
- kind: 'sessionStorage' | 'localStorage';
18
- }): WebStorage<SchemaStoreOutput<S>>;
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 { o as e, u as t } from "./core-vtgV_plC.js";
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 n() {
4
- let { subscribe: e, notify: n } = t({ onFirstSubscribe: () => (typeof window < "u" && (window.addEventListener("online", n), window.addEventListener("offline", n)), () => {
5
- typeof window < "u" && (window.removeEventListener("online", n), window.removeEventListener("offline", n));
6
- }) }), r = () => typeof navigator > "u" ? !0 : navigator.onLine;
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: r,
9
- subscribe: (t, n) => e(() => t(r()), n),
59
+ get: s,
60
+ subscribe: (e, t = {}) => a() ? c(() => e(s()), t) : (e(s()), () => {}),
10
61
  "~": {
11
62
  output: null,
12
- notify: n
63
+ notify: l
13
64
  }
14
65
  };
15
66
  }
16
67
  //#endregion
17
68
  //#region src/web/web-storage.ts
18
- function r(n) {
19
- let r = !1, { subscribe: i, notify: a } = t({ onFirstSubscribe: () => {
69
+ function c(r) {
70
+ let i = !1, { subscribe: a, notify: o } = t({ onFirstSubscribe: () => {
20
71
  let e = () => {
21
- r || a();
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
- } }), o = { ...n.defaultValues }, s = () => {
27
- if (typeof window > "u") return n.defaultValues;
28
- let t = window[n.kind], r = { ...n.defaultValues };
29
- for (let i in r) {
30
- let a = t.getItem(n.keyTransform ? n.keyTransform(i) : i);
31
- if (a === null) {
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 r;
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
- get: s,
102
+ ...f,
55
103
  set: (e) => {
56
- let t = typeof e == "function" ? e(s()) : e;
104
+ let t = typeof e == "function" ? e(d()) : e;
57
105
  if (typeof window > "u") return;
58
- let i = window[n.kind];
59
- r = !0, Object.entries(t).forEach(([e, t]) => {
60
- let r = typeof t == "string" ? t : JSON.stringify(t);
61
- i.setItem(n.keyTransform ? n.keyTransform(e) : e, r), window.dispatchEvent(new StorageEvent("storage", {
62
- key: n.keyTransform ? n.keyTransform(e) : e,
63
- newValue: r
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
- }), r = !1, a();
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
- kind: n.kind,
71
- output: null,
72
- notify: a
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
- function a(n) {
87
- let r = "storage" in n ? n.storage["~"].kind : n.kind, i = !1, a = `${r}Value`;
88
- if ("schema" in n && n.defaultValue === void 0) throw Error(`[${a}] Default value is required`);
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
- i || e.key === n.key && c();
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 o;
100
- let t = window[r].getItem(n.key);
101
- if (t === null) return o;
102
- let i = e(t);
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
- if ("schema" in n) {
105
- let e = n.schema["~standard"].validate(i);
106
- if (e instanceof Promise) throw TypeError("Validation schema should not return a Promise.");
107
- if (e.issues) {
108
- if (n.onValidationError) {
109
- let t = n.onValidationError({
110
- issues: [...e.issues],
111
- value: i
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 o !== void 0 && typeof o != "string" ? o : i;
150
+ return f = s !== void 0 && typeof s != "string" ? s : t, f;
126
151
  }
127
152
  };
128
153
  return {
129
- get: l,
154
+ ...e(p, c, u),
130
155
  set: (e) => {
131
156
  if (typeof window > "u") return;
132
- let t = window[r], a = typeof e == "function" ? e(l()) : e;
133
- i = !0, t.setItem(n.key, typeof a == "string" ? a : JSON.stringify(a)), window.dispatchEvent(new StorageEvent("storage", {
134
- key: n.key,
135
- newValue: a
136
- })), i = !1, c();
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[r].removeItem(n.key);
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
- //#region src/web/scroll-state.ts
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.9.1",
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",
@@ -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>>;