@epoch32/visage 1.0.0 → 1.1.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/api/client.d.ts +5 -0
- package/dist/api/file-router.d.ts +29 -0
- package/dist/api/handler.d.ts +15 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/{src/api → api}/index.js +87 -2
- package/dist/api/middleware.d.ts +11 -0
- package/dist/api/pragma.d.ts +21 -0
- package/dist/api/procedure.d.ts +66 -0
- package/dist/api/types.d.ts +181 -0
- package/dist/charts/Area.d.ts +18 -0
- package/dist/charts/Axis.d.ts +21 -0
- package/dist/charts/Bar.d.ts +10 -0
- package/dist/charts/CartesianGrid.d.ts +10 -0
- package/dist/charts/Chart.d.ts +16 -0
- package/dist/charts/Cursor.d.ts +8 -0
- package/dist/charts/Legend.d.ts +9 -0
- package/dist/charts/Line.d.ts +18 -0
- package/dist/charts/Pie.d.ts +12 -0
- package/dist/charts/Tooltip.d.ts +12 -0
- package/dist/charts/context.d.ts +20 -0
- package/dist/charts/index.d.ts +14 -0
- package/dist/{src/charts → charts}/index.js +87 -2
- package/dist/charts/path.d.ts +27 -0
- package/dist/charts/scale.d.ts +23 -0
- package/dist/charts/types.d.ts +43 -0
- package/dist/devtools/DomTab.d.ts +6 -0
- package/dist/devtools/GraphInspector.d.ts +11 -0
- package/dist/devtools/GraphTab.d.ts +10 -0
- package/dist/devtools/QueryTab.d.ts +10 -0
- package/dist/devtools/RpcTab.d.ts +10 -0
- package/dist/devtools/SignalsTab.d.ts +10 -0
- package/dist/devtools/component.d.ts +2 -0
- package/dist/devtools/highlighter.d.ts +2 -0
- package/dist/devtools/hub.d.ts +41 -0
- package/dist/devtools/index.d.ts +9 -0
- package/dist/{src/devtools → devtools}/index.js +87 -2
- package/dist/devtools/styles.d.ts +1 -0
- package/dist/devtools/types.d.ts +44 -0
- package/dist/dom/async.d.ts +41 -0
- package/dist/dom/control-flow.d.ts +53 -0
- package/dist/dom/index.d.ts +3 -0
- package/dist/{src/dom → dom}/index.js +87 -2
- package/dist/dom/lazy.d.ts +30 -0
- package/dist/dom/render.d.ts +23 -0
- package/dist/dom/resource.d.ts +34 -0
- package/dist/form/form.d.ts +41 -0
- package/dist/form/index.d.ts +2 -0
- package/dist/{src/form → form}/index.js +87 -2
- package/dist/form/schema.d.ts +96 -0
- package/dist/index.d.ts +15 -0
- package/dist/{src/index.js → index.js} +87 -2
- package/dist/jsx-dev-runtime/index.d.ts +1 -0
- package/dist/jsx-runtime/index.d.ts +8 -0
- package/dist/{src/jsx-runtime → jsx-runtime}/index.js +87 -2
- package/dist/jsx-runtime/jsx.d.ts +278 -0
- package/dist/query/create-mutation.d.ts +3 -0
- package/dist/query/create-query.d.ts +4 -0
- package/dist/query/focus-manager.d.ts +14 -0
- package/dist/query/index.d.ts +9 -0
- package/dist/{src/query → query}/index.js +87 -2
- package/dist/query/mutation-cache.d.ts +24 -0
- package/dist/query/online-manager.d.ts +14 -0
- package/dist/query/query-cache.d.ts +69 -0
- package/dist/query/query-client.d.ts +46 -0
- package/dist/query/types.d.ts +131 -0
- package/dist/query/utils.d.ts +16 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/{src/router → router}/index.js +87 -2
- package/dist/router/router.d.ts +91 -0
- package/dist/rpc/client.d.ts +2 -0
- package/dist/rpc/error.d.ts +16 -0
- package/dist/rpc/index.d.ts +7 -0
- package/dist/{src/rpc → rpc}/index.js +87 -2
- package/dist/rpc/procedure.d.ts +8 -0
- package/dist/rpc/router.d.ts +19 -0
- package/dist/rpc/server.d.ts +3 -0
- package/dist/rpc/types.d.ts +200 -0
- package/dist/server/hydrate.d.ts +5 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/{src/server → server}/index.js +87 -2
- package/dist/server/render-to-stream.d.ts +9 -0
- package/dist/server/render-to-string.d.ts +6 -0
- package/dist/signals/computed.d.ts +61 -0
- package/dist/signals/context.d.ts +44 -0
- package/dist/signals/effect.d.ts +56 -0
- package/dist/signals/index.d.ts +8 -0
- package/dist/{src/signals → signals}/index.js +87 -2
- package/dist/signals/scope.d.ts +61 -0
- package/dist/signals/signal.d.ts +40 -0
- package/dist/signals/store.d.ts +45 -0
- package/dist/signals/system.d.ts +56 -0
- package/dist/signals/types.d.ts +58 -0
- package/dist/style/component.d.ts +49 -0
- package/dist/style/create-style.d.ts +63 -0
- package/dist/style/cx.d.ts +18 -0
- package/dist/style/hash.d.ts +8 -0
- package/dist/style/index.d.ts +8 -0
- package/dist/{src/style → style}/index.js +87 -2
- package/dist/style/layout.d.ts +129 -0
- package/dist/style/manager.d.ts +31 -0
- package/dist/style/parser.d.ts +12 -0
- package/dist/style/scale.d.ts +82 -0
- package/dist/template/index.d.ts +1 -0
- package/dist/{src/template → template}/index.js +87 -2
- package/dist/template/template.d.ts +8 -0
- package/dist/ui/accordion.d.ts +81 -0
- package/dist/ui/command-dialog.d.ts +10 -0
- package/dist/ui/command.d.ts +103 -0
- package/dist/ui/data-table.d.ts +38 -0
- package/dist/ui/dialog.d.ts +102 -0
- package/dist/ui/dropdown-menu.d.ts +92 -0
- package/dist/ui/icon.d.ts +18 -0
- package/dist/ui/index.d.ts +14 -0
- package/dist/{src/ui → ui}/index.js +87 -2
- package/dist/ui/layout.d.ts +1 -0
- package/dist/ui/popover.d.ts +68 -0
- package/dist/ui/switch.d.ts +31 -0
- package/dist/ui/tabs.d.ts +71 -0
- package/dist/ui/toast.d.ts +91 -0
- package/dist/ui/tooltip.d.ts +64 -0
- package/dist/ui/utils.d.ts +21 -0
- package/dist/virtual/index.d.ts +2 -0
- package/dist/{src/virtual → virtual}/index.js +87 -2
- package/dist/virtual/virtual-list.d.ts +21 -0
- package/dist/virtual/virtualizer.d.ts +31 -0
- package/dist/vite/hmr.d.ts +7 -0
- package/dist/vite/index.d.ts +3 -0
- package/dist/{src/vite → vite}/index.js +4 -0
- package/dist/vite/lucide.d.ts +27 -0
- package/dist/vite/plugin.d.ts +3 -0
- package/dist/vite/rpc-middleware.d.ts +5 -0
- package/dist/vite/types.d.ts +59 -0
- package/package.json +40 -40
- package/src/signals/index.ts +1 -0
- package/src/signals/signal.ts +110 -2
- package/src/signals/types.ts +9 -0
- package/src/vite/plugin.ts +4 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VisageVitePlugin } from "./types";
|
|
2
|
+
export interface VisageLucideOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Module aliases to intercept and translate.
|
|
5
|
+
* Defaults to `["lucide-react"]`.
|
|
6
|
+
*/
|
|
7
|
+
aliases?: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Official Visage Lucide Vite Plugin
|
|
11
|
+
*
|
|
12
|
+
* Statically transforms `import { Icon } from "lucide-react"` at build time into
|
|
13
|
+
* native, tree-shaken Visage SVG component instances using `createIcon` and `lucide`.
|
|
14
|
+
*
|
|
15
|
+
* Example:
|
|
16
|
+
* ```ts
|
|
17
|
+
* // vite.config.ts
|
|
18
|
+
* import { defineConfig } from "vite";
|
|
19
|
+
* import visage, { visageLucide } from "visage/vite";
|
|
20
|
+
*
|
|
21
|
+
* export default defineConfig({
|
|
22
|
+
* plugins: [visage(), visageLucide()]
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function visageLucide(options?: VisageLucideOptions): VisageVitePlugin;
|
|
27
|
+
export default visageLucide;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { VisagePluginOptions } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Attach Visage RPC handler to Vite's Connect dev server middleware
|
|
4
|
+
*/
|
|
5
|
+
export declare function createViteRpcMiddleware(options: NonNullable<VisagePluginOptions["rpc"]>): (req: any, res: any, next: () => void) => Promise<void>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { createRouter } from "../rpc/router";
|
|
2
|
+
/**
|
|
3
|
+
* Options for the Visage Vite Plugin
|
|
4
|
+
*/
|
|
5
|
+
export interface VisagePluginOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Automatically auto-inject Visage DevTools in development mode
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
devtools?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Enable Hot Module Replacement (HMR) with signal state preservation
|
|
13
|
+
* @default true
|
|
14
|
+
*/
|
|
15
|
+
hmr?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Extract static <Style> blocks into production CSS bundle
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
extractCss?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Enable Server-Side Rendering (SSR) pipeline
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
ssr?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Optional full-stack RPC router configuration for Vite dev server middleware
|
|
28
|
+
*/
|
|
29
|
+
rpc?: {
|
|
30
|
+
router: ReturnType<typeof createRouter<any>>;
|
|
31
|
+
endpoint?: string;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Minimal interface representation of Vite Plugin to ensure zero hard runtime dependencies
|
|
36
|
+
*/
|
|
37
|
+
export interface VisageVitePlugin {
|
|
38
|
+
name: string;
|
|
39
|
+
enforce?: "pre" | "post";
|
|
40
|
+
apply?: "serve" | "build" | ((config: any, env: {
|
|
41
|
+
command: string;
|
|
42
|
+
mode: string;
|
|
43
|
+
}) => boolean);
|
|
44
|
+
config?: (config: any, env: any) => any;
|
|
45
|
+
configResolved?: (config: any) => void;
|
|
46
|
+
configureServer?: (server: any) => void | Promise<void>;
|
|
47
|
+
resolveId?: (source: string, importer?: string, options?: any) => Promise<string | null | undefined> | string | null | undefined;
|
|
48
|
+
load?: (id: string, options?: any) => Promise<string | null | undefined> | string | null | undefined;
|
|
49
|
+
transform?: (code: string, id: string, options?: {
|
|
50
|
+
ssr?: boolean;
|
|
51
|
+
}) => Promise<{
|
|
52
|
+
code: string;
|
|
53
|
+
map?: any;
|
|
54
|
+
} | null> | {
|
|
55
|
+
code: string;
|
|
56
|
+
map?: any;
|
|
57
|
+
} | null;
|
|
58
|
+
transformIndexHtml?: (html: string) => string | Promise<string>;
|
|
59
|
+
}
|
package/package.json
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epoch32/visage",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Lightning-fast, zero-VDOM, fine-grained reactive UI library with full TypeScript support",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./
|
|
7
|
-
"types": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"types": "./
|
|
11
|
-
"import": "./
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
12
|
},
|
|
13
13
|
"./signals": {
|
|
14
|
-
"types": "./
|
|
15
|
-
"import": "./
|
|
14
|
+
"types": "./dist/signals/index.d.ts",
|
|
15
|
+
"import": "./dist/signals/index.js"
|
|
16
16
|
},
|
|
17
17
|
"./dom": {
|
|
18
|
-
"types": "./
|
|
19
|
-
"import": "./
|
|
18
|
+
"types": "./dist/dom/index.d.ts",
|
|
19
|
+
"import": "./dist/dom/index.js"
|
|
20
20
|
},
|
|
21
21
|
"./router": {
|
|
22
|
-
"types": "./
|
|
23
|
-
"import": "./
|
|
22
|
+
"types": "./dist/router/index.d.ts",
|
|
23
|
+
"import": "./dist/router/index.js"
|
|
24
24
|
},
|
|
25
25
|
"./template": {
|
|
26
|
-
"types": "./
|
|
27
|
-
"import": "./
|
|
26
|
+
"types": "./dist/template/index.d.ts",
|
|
27
|
+
"import": "./dist/template/index.js"
|
|
28
28
|
},
|
|
29
29
|
"./server": {
|
|
30
|
-
"types": "./
|
|
31
|
-
"import": "./
|
|
30
|
+
"types": "./dist/server/index.d.ts",
|
|
31
|
+
"import": "./dist/server/index.js"
|
|
32
32
|
},
|
|
33
33
|
"./form": {
|
|
34
|
-
"types": "./
|
|
35
|
-
"import": "./
|
|
34
|
+
"types": "./dist/form/index.d.ts",
|
|
35
|
+
"import": "./dist/form/index.js"
|
|
36
36
|
},
|
|
37
37
|
"./virtual": {
|
|
38
|
-
"types": "./
|
|
39
|
-
"import": "./
|
|
38
|
+
"types": "./dist/virtual/index.d.ts",
|
|
39
|
+
"import": "./dist/virtual/index.js"
|
|
40
40
|
},
|
|
41
41
|
"./query": {
|
|
42
|
-
"types": "./
|
|
43
|
-
"import": "./
|
|
42
|
+
"types": "./dist/query/index.d.ts",
|
|
43
|
+
"import": "./dist/query/index.js"
|
|
44
44
|
},
|
|
45
45
|
"./rpc": {
|
|
46
|
-
"types": "./
|
|
47
|
-
"import": "./
|
|
46
|
+
"types": "./dist/rpc/index.d.ts",
|
|
47
|
+
"import": "./dist/rpc/index.js"
|
|
48
48
|
},
|
|
49
49
|
"./api": {
|
|
50
|
-
"types": "./
|
|
51
|
-
"import": "./
|
|
50
|
+
"types": "./dist/api/index.d.ts",
|
|
51
|
+
"import": "./dist/api/index.js"
|
|
52
52
|
},
|
|
53
53
|
"./style": {
|
|
54
|
-
"types": "./
|
|
55
|
-
"import": "./
|
|
54
|
+
"types": "./dist/style/index.d.ts",
|
|
55
|
+
"import": "./dist/style/index.js"
|
|
56
56
|
},
|
|
57
57
|
"./devtools": {
|
|
58
|
-
"types": "./
|
|
59
|
-
"import": "./
|
|
58
|
+
"types": "./dist/devtools/index.d.ts",
|
|
59
|
+
"import": "./dist/devtools/index.js"
|
|
60
60
|
},
|
|
61
61
|
"./vite": {
|
|
62
|
-
"types": "./
|
|
63
|
-
"import": "./
|
|
62
|
+
"types": "./dist/vite/index.d.ts",
|
|
63
|
+
"import": "./dist/vite/index.js"
|
|
64
64
|
},
|
|
65
65
|
"./ui": {
|
|
66
|
-
"types": "./
|
|
67
|
-
"import": "./
|
|
66
|
+
"types": "./dist/ui/index.d.ts",
|
|
67
|
+
"import": "./dist/ui/index.js"
|
|
68
68
|
},
|
|
69
69
|
"./charts": {
|
|
70
|
-
"types": "./
|
|
71
|
-
"import": "./
|
|
70
|
+
"types": "./dist/charts/index.d.ts",
|
|
71
|
+
"import": "./dist/charts/index.js"
|
|
72
72
|
},
|
|
73
73
|
"./jsx-runtime": {
|
|
74
|
-
"types": "./
|
|
75
|
-
"import": "./
|
|
74
|
+
"types": "./dist/jsx-runtime/index.d.ts",
|
|
75
|
+
"import": "./dist/jsx-runtime/index.js"
|
|
76
76
|
},
|
|
77
77
|
"./jsx-dev-runtime": {
|
|
78
|
-
"types": "./
|
|
79
|
-
"import": "./
|
|
78
|
+
"types": "./dist/jsx-runtime/index.d.ts",
|
|
79
|
+
"import": "./dist/jsx-runtime/index.js"
|
|
80
80
|
}
|
|
81
81
|
},
|
|
82
82
|
"sideEffects": false,
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"package.json"
|
|
101
101
|
],
|
|
102
102
|
"scripts": {
|
|
103
|
-
"build": "bun build src/index.ts src/signals/index.ts src/dom/index.ts src/template/index.ts src/api/index.ts src/rpc/index.ts src/query/index.ts src/style/index.ts src/devtools/index.ts src/ui/index.ts src/virtual/index.ts src/form/index.ts src/server/index.ts src/router/index.ts src/vite/index.ts src/jsx-runtime/index.ts src/charts/index.ts --outdir dist/",
|
|
103
|
+
"build": "bun build src/index.ts src/signals/index.ts src/dom/index.ts src/template/index.ts src/api/index.ts src/rpc/index.ts src/query/index.ts src/style/index.ts src/devtools/index.ts src/ui/index.ts src/virtual/index.ts src/form/index.ts src/server/index.ts src/router/index.ts src/vite/index.ts src/jsx-runtime/index.ts src/charts/index.ts --root src --outdir dist/ && bun x tsc -p tsconfig.build.json && cp src/jsx-runtime/jsx.d.ts dist/jsx-runtime/jsx.d.ts",
|
|
104
104
|
"test": "bun test",
|
|
105
105
|
"test:watch": "bun test --watch",
|
|
106
106
|
"test:coverage": "bun test --coverage",
|
package/src/signals/index.ts
CHANGED
package/src/signals/signal.ts
CHANGED
|
@@ -22,11 +22,13 @@ export class Signal<T> implements IDependency {
|
|
|
22
22
|
private _value: T;
|
|
23
23
|
private _subscribers: Set<ISubscriber> = new Set();
|
|
24
24
|
private _equals: (a: T, b: T) => boolean;
|
|
25
|
+
private _onSet?: (val: T) => void;
|
|
25
26
|
version = 0;
|
|
26
27
|
|
|
27
|
-
constructor(initialValue: T, equals?: (a: T, b: T) => boolean) {
|
|
28
|
+
constructor(initialValue: T, equals?: (a: T, b: T) => boolean, onSet?: (val: T) => void) {
|
|
28
29
|
this._value = initialValue;
|
|
29
30
|
this._equals = equals ?? Object.is;
|
|
31
|
+
this._onSet = onSet;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
get(): T {
|
|
@@ -58,6 +60,9 @@ export class Signal<T> implements IDependency {
|
|
|
58
60
|
|
|
59
61
|
this._value = newValue;
|
|
60
62
|
this.version++;
|
|
63
|
+
if (this._onSet) {
|
|
64
|
+
this._onSet(newValue);
|
|
65
|
+
}
|
|
61
66
|
batch(() => {
|
|
62
67
|
this.notify();
|
|
63
68
|
});
|
|
@@ -117,6 +122,43 @@ export class Signal<T> implements IDependency {
|
|
|
117
122
|
* @param optionsOrEquals - Custom equality comparison function or SignalOptions
|
|
118
123
|
* @returns A writable reactive signal function accessor
|
|
119
124
|
*/
|
|
125
|
+
function resolveStorage(storageOption?: "local" | "session" | Storage): Storage | null {
|
|
126
|
+
if (storageOption && typeof storageOption === "object") {
|
|
127
|
+
return storageOption;
|
|
128
|
+
}
|
|
129
|
+
if (storageOption === "session") {
|
|
130
|
+
try {
|
|
131
|
+
if (typeof sessionStorage !== "undefined") return sessionStorage;
|
|
132
|
+
} catch {}
|
|
133
|
+
try {
|
|
134
|
+
if (typeof window !== "undefined" && (window as any).sessionStorage) {
|
|
135
|
+
return (window as any).sessionStorage;
|
|
136
|
+
}
|
|
137
|
+
} catch {}
|
|
138
|
+
try {
|
|
139
|
+
if (typeof globalThis !== "undefined" && (globalThis as any).sessionStorage) {
|
|
140
|
+
return (globalThis as any).sessionStorage;
|
|
141
|
+
}
|
|
142
|
+
} catch {}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
if (typeof localStorage !== "undefined") return localStorage;
|
|
148
|
+
} catch {}
|
|
149
|
+
try {
|
|
150
|
+
if (typeof window !== "undefined" && (window as any).localStorage) {
|
|
151
|
+
return (window as any).localStorage;
|
|
152
|
+
}
|
|
153
|
+
} catch {}
|
|
154
|
+
try {
|
|
155
|
+
if (typeof globalThis !== "undefined" && (globalThis as any).localStorage) {
|
|
156
|
+
return (globalThis as any).localStorage;
|
|
157
|
+
}
|
|
158
|
+
} catch {}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
120
162
|
export function signal<T>(
|
|
121
163
|
initialValue: T,
|
|
122
164
|
optionsOrEquals?: ((a: T, b: T) => boolean) | SignalOptions<T>
|
|
@@ -125,7 +167,73 @@ export function signal<T>(
|
|
|
125
167
|
const isInternal = typeof optionsOrEquals === "object" ? optionsOrEquals?.internal : false;
|
|
126
168
|
const customName = typeof optionsOrEquals === "object" ? optionsOrEquals?.name : undefined;
|
|
127
169
|
|
|
128
|
-
const
|
|
170
|
+
const persistOption = typeof optionsOrEquals === "object" ? optionsOrEquals?.persist : undefined;
|
|
171
|
+
const persistConfig = persistOption
|
|
172
|
+
? typeof persistOption === "string"
|
|
173
|
+
? { key: persistOption }
|
|
174
|
+
: persistOption
|
|
175
|
+
: undefined;
|
|
176
|
+
|
|
177
|
+
let effectiveInitial = initialValue;
|
|
178
|
+
const storage = persistConfig ? resolveStorage(persistConfig.storage) : null;
|
|
179
|
+
const serialize = persistConfig?.serialize ?? JSON.stringify;
|
|
180
|
+
const deserialize = persistConfig?.deserialize ?? JSON.parse;
|
|
181
|
+
|
|
182
|
+
if (persistConfig && storage) {
|
|
183
|
+
try {
|
|
184
|
+
const stored = storage.getItem(persistConfig.key);
|
|
185
|
+
if (stored !== null) {
|
|
186
|
+
effectiveInitial = deserialize(stored);
|
|
187
|
+
}
|
|
188
|
+
} catch {
|
|
189
|
+
// Fallback cleanly to initialValue
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
let isSyncing = false;
|
|
194
|
+
const onSet =
|
|
195
|
+
persistConfig && storage
|
|
196
|
+
? (val: T) => {
|
|
197
|
+
if (isSyncing) return;
|
|
198
|
+
try {
|
|
199
|
+
storage.setItem(persistConfig.key, serialize(val));
|
|
200
|
+
} catch {
|
|
201
|
+
// Gracefully handle storage quota or access errors
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
: undefined;
|
|
205
|
+
|
|
206
|
+
const s = new Signal(effectiveInitial, equals, onSet);
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
persistConfig &&
|
|
210
|
+
storage &&
|
|
211
|
+
(persistConfig.syncTabs ?? true) &&
|
|
212
|
+
typeof window !== "undefined" &&
|
|
213
|
+
typeof window.addEventListener === "function"
|
|
214
|
+
) {
|
|
215
|
+
const onStorage = (e: StorageEvent) => {
|
|
216
|
+
if (e.key === persistConfig.key) {
|
|
217
|
+
try {
|
|
218
|
+
const nextVal = e.newValue !== null ? deserialize(e.newValue) : initialValue;
|
|
219
|
+
isSyncing = true;
|
|
220
|
+
try {
|
|
221
|
+
s.set(nextVal);
|
|
222
|
+
} finally {
|
|
223
|
+
isSyncing = false;
|
|
224
|
+
}
|
|
225
|
+
} catch {
|
|
226
|
+
// Ignore external malformed entries
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
window.addEventListener("storage", onStorage);
|
|
231
|
+
if (currentScope) {
|
|
232
|
+
currentScope.addCleanup(() => {
|
|
233
|
+
window.removeEventListener("storage", onStorage);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
129
237
|
|
|
130
238
|
const accessor = ((...args: [value?: T]): T => {
|
|
131
239
|
if (args.length === 0) {
|
package/src/signals/types.ts
CHANGED
|
@@ -29,10 +29,19 @@ export interface WritableSignal<T> extends ReadonlySignal<T> {
|
|
|
29
29
|
value: T;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
export interface PersistOptions<T> {
|
|
33
|
+
key: string;
|
|
34
|
+
storage?: "local" | "session" | Storage;
|
|
35
|
+
serialize?: (value: T) => string;
|
|
36
|
+
deserialize?: (raw: string) => T;
|
|
37
|
+
syncTabs?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
32
40
|
export interface SignalOptions<T> {
|
|
33
41
|
name?: string;
|
|
34
42
|
equals?: (a: T, b: T) => boolean;
|
|
35
43
|
internal?: boolean;
|
|
44
|
+
persist?: string | PersistOptions<T>;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
export interface ComputedOptions {
|
package/src/vite/plugin.ts
CHANGED
|
@@ -57,6 +57,10 @@ export function visage(options: VisagePluginOptions = {}): VisageVitePlugin[] {
|
|
|
57
57
|
]
|
|
58
58
|
},
|
|
59
59
|
resolve: {
|
|
60
|
+
alias: [
|
|
61
|
+
{ find: /^visage\/(.*)/, replacement: "@epoch32/visage/$1" },
|
|
62
|
+
{ find: /^visage$/, replacement: "@epoch32/visage" }
|
|
63
|
+
],
|
|
60
64
|
dedupe: ["@epoch32/visage", "visage"]
|
|
61
65
|
}
|
|
62
66
|
};
|