@xingxingmofashu/ui 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -67,6 +67,52 @@ The package root resolves to `dist/index.css` through its `style` export. The
67
67
  stylesheet includes its own Tailwind source scan, so component utilities are
68
68
  generated without an extra `@source` directive.
69
69
 
70
+ ### Glass presets
71
+
72
+ Import the optional preset stylesheet:
73
+
74
+ ```css [app.css]
75
+ @import "@xingxingmofashu/ui/plugins/glass-preset/index.css";
76
+ ```
77
+
78
+ Then switch the shared glass material with `data-glass` on the root or any
79
+ container:
80
+
81
+ ```html
82
+ <html data-glass="thin">
83
+ <section data-glass="thick">...</section>
84
+ ```
85
+
86
+ `thin` is the default and the clearest, `regular` balances transparency with
87
+ text separation, and `thick` is the most readable over busy imagery. Presets
88
+ only override shared CSS variables. Without the plugin stylesheet, the main
89
+ stylesheet still uses the `thin` material.
90
+
91
+ The optional React plugin manages the attribute and persistence:
92
+
93
+ ```tsx
94
+ import {
95
+ GlassPresetProvider,
96
+ GlassPresetScope,
97
+ GlassPresetScript,
98
+ } from "@xingxingmofashu/ui/plugins/glass-preset";
99
+
100
+ // In <head>, before React hydrates.
101
+ <GlassPresetScript storageKey="app-glass" />;
102
+
103
+ // Around the application.
104
+ <GlassPresetProvider storageKey="app-glass">
105
+ {children}
106
+ </GlassPresetProvider>;
107
+
108
+ // Or scope one container without changing the global preset.
109
+ <GlassPresetScope preset="thick">{children}</GlassPresetScope>;
110
+ ```
111
+
112
+ The provider writes `data-glass` to `<html>` and exposes
113
+ `useGlassPreset()`. Pass `preset` and `onPresetChange` for controlled state, or
114
+ `defaultPreset` for an uncontrolled initial value.
115
+
70
116
  ## Usage
71
117
 
72
118
  ```tsx
package/dist/index.css CHANGED
@@ -1 +1 @@
1
- @import "./keyframes.css";@source "./**/*.mjs";@source "./**/*.{ts,tsx}";@custom-variant ui-light (&:where(.light, .light *, [data-theme="light"], [data-theme="light"] *));@custom-variant ui-dark (&:where(.dark, .dark *, [data-theme="dark"], [data-theme="dark"] *));@layer theme{:host,:root{--ui-ink:#1f1f1f;--ui-ink-active:#000;--ui-surface:#fff;--ui-glass-surface:hsla(0,0%,100%,.2);--ui-glass-border:rgba(31,31,31,.16);--ui-glass-focus:rgba(0,0,0,.6);--ui-glass-inner-border:rgba(0,0,0,.9);--ui-glass-rim:hsla(0,0%,100%,.2);--ui-glass-highlight:hsla(0,0%,100%,.8);--ui-glass-glare-stop:15%;--ui-glass-tone:brightness(0.98);--ui-glass-contrast:1.05;--ui-drop-shadow-label:drop-shadow(0 25px 3px hsla(0,0%,40%,.15));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.9),inset -2px 2px 1px -1px hsla(0,0%,100%,.9),inset 6px -6px 1px -6px hsla(0,0%,100%,.55),inset -6px 6px 1px -6px hsla(0,0%,100%,.55),inset 0 0 2px rgba(0,0,0,.8),0 4px 8px rgba(0,0,0,.2)}.dark,[data-theme=dark]{--ui-ink:#f5f5f5;--ui-ink-active:#fff;--ui-surface:#141414;--ui-glass-surface:hsla(0,0%,8%,.62);--ui-glass-border:hsla(0,0%,100%,.2);--ui-glass-focus:hsla(0,0%,100%,.7);--ui-glass-inner-border:hsla(0,0%,100%,.4);--ui-glass-rim:hsla(0,0%,100%,.25);--ui-glass-highlight:hsla(0,0%,100%,.45);--ui-glass-tone:brightness(0.95);--ui-glass-contrast:1;--ui-drop-shadow-label:drop-shadow(0 25px 3px rgba(0,0,0,.45));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.35),inset -2px 2px 1px -1px hsla(0,0%,100%,.35),inset 6px -6px 1px -6px hsla(0,0%,100%,.2),inset -6px 6px 1px -6px hsla(0,0%,100%,.2),inset 0 0 2px rgba(0,0,0,.9),0 4px 8px rgba(0,0,0,.35)}.light,[data-theme=light]{--ui-ink:#1f1f1f;--ui-ink-active:#000;--ui-surface:#fff;--ui-glass-surface:hsla(0,0%,100%,.2);--ui-glass-border:rgba(31,31,31,.16);--ui-glass-focus:rgba(0,0,0,.6);--ui-glass-inner-border:rgba(0,0,0,.9);--ui-glass-rim:hsla(0,0%,100%,.2);--ui-glass-highlight:hsla(0,0%,100%,.8);--ui-glass-glare-stop:15%;--ui-glass-tone:brightness(0.98);--ui-glass-contrast:1.05;--ui-drop-shadow-label:drop-shadow(0 25px 3px hsla(0,0%,40%,.15));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.9),inset -2px 2px 1px -1px hsla(0,0%,100%,.9),inset 6px -6px 1px -6px hsla(0,0%,100%,.55),inset -6px 6px 1px -6px hsla(0,0%,100%,.55),inset 0 0 2px rgba(0,0,0,.8),0 4px 8px rgba(0,0,0,.2)}:host,:root{--ui-glass-blur:4px;--ui-glass-saturate:150%;--ui-glass-chip-blur:8px;--ui-glass-inner-inset:8px;--ui-glass-inner-offset:1px;--ui-glass-inner-blur:8px;--ui-glass-highlight-blur:7px;--ui-glass-rim-inset:9px;--ui-glass-rim-blur:1px}}@theme inline{--color-ui-ink:var(--ui-ink);--color-ui-ink-active:var(--ui-ink-active);--color-ui-surface:var(--ui-surface);--color-ui-glass-surface:var(--ui-glass-surface);--color-ui-glass-border:var(--ui-glass-border);--color-ui-glass-focus:var(--ui-glass-focus);--color-ui-glass-inner-border:var(--ui-glass-inner-border);--color-ui-glass-rim:var(--ui-glass-rim);--color-ui-glass-highlight:var(--ui-glass-highlight)}@layer components{.ui-glass{backdrop-filter:blur(var(--ui-glass-blur,4px)) saturate(var(--ui-glass-saturate,150%));background-color:var(--ui-glass-surface);border:1px double var(--ui-glass-border);box-shadow:var(--ui-shadow-glass);filter:var(--ui-glass-tone,brightness(.98)) contrast(var(--ui-glass-contrast,1.05));position:relative}.ui-glass-inner:before{border:1px solid var(--ui-glass-inner-border);bottom:calc(var(--ui-glass-inner-inset, 8px) - var(--ui-glass-inner-offset, 1px));filter:blur(var(--ui-glass-inner-blur,8px));left:var(--ui-glass-inner-inset,8px);right:var(--ui-glass-inner-inset,8px);top:calc(var(--ui-glass-inner-inset, 8px) + var(--ui-glass-inner-offset, 1px));z-index:1}.ui-glass-highlight:after,.ui-glass-inner:before{border-radius:inherit;content:"";pointer-events:none;position:absolute}.ui-glass-highlight:after{background:linear-gradient(45deg,var(--ui-glass-highlight) 0,transparent var(--ui-glass-glare-stop),transparent calc(100% - var(--ui-glass-glare-stop)),var(--ui-glass-highlight) 100%);filter:blur(var(--ui-glass-highlight-blur,7px));inset:0;z-index:3}.ui-glass-rim{border:1px solid var(--ui-glass-rim);border-radius:inherit;filter:blur(var(--ui-glass-rim-blur,1px));height:calc(100% - var(--ui-glass-rim-inset, 9px));left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);width:calc(100% - var(--ui-glass-rim-inset, 9px));z-index:2}.ui-glass-chip{backdrop-filter:blur(var(--ui-glass-chip-blur,8px)) saturate(var(--ui-glass-saturate,150%));background-color:var(--ui-glass-surface);border:1px solid var(--ui-glass-border);box-shadow:inset 0 1px 0 var(--ui-glass-highlight)}}
1
+ @import "./keyframes.css";@source "./**/*.mjs";@source "./**/*.{ts,tsx}";@custom-variant ui-light (&:where(.light, .light *, [data-theme="light"], [data-theme="light"] *));@custom-variant ui-dark (&:where(.dark, .dark *, [data-theme="dark"], [data-theme="dark"] *));@layer theme{:host,:root{color-scheme:light;--ui-ink:#1f1f1f;--ui-ink-active:#000;--ui-surface:#fff;--ui-glass-surface:hsla(0,0%,100%,.2);--ui-glass-border:rgba(31,31,31,.16);--ui-glass-focus:rgba(0,0,0,.6);--ui-glass-inner-border:rgba(0,0,0,.9);--ui-glass-rim:hsla(0,0%,100%,.2);--ui-glass-highlight:hsla(0,0%,100%,.8);--ui-glass-glare-stop:15%;--ui-glass-tone:brightness(0.98);--ui-glass-contrast:1.05;--ui-drop-shadow-label:drop-shadow(0 25px 3px hsla(0,0%,40%,.15));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.9),inset -2px 2px 1px -1px hsla(0,0%,100%,.9),inset 6px -6px 1px -6px hsla(0,0%,100%,.55),inset -6px 6px 1px -6px hsla(0,0%,100%,.55),inset 0 0 2px rgba(0,0,0,.8),0 4px 8px rgba(0,0,0,.2)}.dark,[data-theme=dark]{color-scheme:dark;--ui-ink:#f5f5f5;--ui-ink-active:#fff;--ui-surface:#141414;--ui-glass-surface:hsla(0,0%,8%,.62);--ui-glass-border:hsla(0,0%,100%,.2);--ui-glass-focus:hsla(0,0%,100%,.7);--ui-glass-inner-border:hsla(0,0%,100%,.4);--ui-glass-rim:hsla(0,0%,100%,.25);--ui-glass-highlight:hsla(0,0%,100%,.45);--ui-glass-tone:brightness(0.95);--ui-glass-contrast:1;--ui-drop-shadow-label:drop-shadow(0 25px 3px rgba(0,0,0,.45));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.35),inset -2px 2px 1px -1px hsla(0,0%,100%,.35),inset 6px -6px 1px -6px hsla(0,0%,100%,.2),inset -6px 6px 1px -6px hsla(0,0%,100%,.2),inset 0 0 2px rgba(0,0,0,.9),0 4px 8px rgba(0,0,0,.35)}.light,[data-theme=light]{color-scheme:light;--ui-ink:#1f1f1f;--ui-ink-active:#000;--ui-surface:#fff;--ui-glass-surface:hsla(0,0%,100%,.2);--ui-glass-border:rgba(31,31,31,.16);--ui-glass-focus:rgba(0,0,0,.6);--ui-glass-inner-border:rgba(0,0,0,.9);--ui-glass-rim:hsla(0,0%,100%,.2);--ui-glass-highlight:hsla(0,0%,100%,.8);--ui-glass-glare-stop:15%;--ui-glass-tone:brightness(0.98);--ui-glass-contrast:1.05;--ui-drop-shadow-label:drop-shadow(0 25px 3px hsla(0,0%,40%,.15));--ui-shadow-glass:inset 2px -2px 1px -1px hsla(0,0%,100%,.9),inset -2px 2px 1px -1px hsla(0,0%,100%,.9),inset 6px -6px 1px -6px hsla(0,0%,100%,.55),inset -6px 6px 1px -6px hsla(0,0%,100%,.55),inset 0 0 2px rgba(0,0,0,.8),0 4px 8px rgba(0,0,0,.2)}:host,:root{--ui-glass-blur:4px;--ui-glass-saturate:150%;--ui-glass-chip-blur:8px;--ui-glass-inner-inset:8px;--ui-glass-inner-offset:1px;--ui-glass-inner-blur:8px;--ui-glass-highlight-blur:7px;--ui-glass-rim-inset:9px;--ui-glass-rim-blur:1px}}@theme inline{--color-ui-ink:var(--ui-ink);--color-ui-ink-active:var(--ui-ink-active);--color-ui-surface:var(--ui-surface);--color-ui-glass-surface:var(--ui-glass-surface);--color-ui-glass-border:var(--ui-glass-border);--color-ui-glass-focus:var(--ui-glass-focus);--color-ui-glass-inner-border:var(--ui-glass-inner-border);--color-ui-glass-rim:var(--ui-glass-rim);--color-ui-glass-highlight:var(--ui-glass-highlight)}@layer components{.ui-glass{backdrop-filter:blur(var(--ui-glass-blur,4px)) saturate(var(--ui-glass-saturate,150%));background-color:var(--ui-glass-surface);border:1px double var(--ui-glass-border);box-shadow:var(--ui-shadow-glass);filter:var(--ui-glass-tone,brightness(.98)) contrast(var(--ui-glass-contrast,1.05));position:relative}.ui-glass-inner:before{border:1px solid var(--ui-glass-inner-border);bottom:calc(var(--ui-glass-inner-inset, 8px) - var(--ui-glass-inner-offset, 1px));filter:blur(var(--ui-glass-inner-blur,8px));left:var(--ui-glass-inner-inset,8px);right:var(--ui-glass-inner-inset,8px);top:calc(var(--ui-glass-inner-inset, 8px) + var(--ui-glass-inner-offset, 1px));z-index:1}.ui-glass-highlight:after,.ui-glass-inner:before{border-radius:inherit;content:"";pointer-events:none;position:absolute}.ui-glass-highlight:after{background:linear-gradient(45deg,var(--ui-glass-highlight) 0,transparent var(--ui-glass-glare-stop),transparent calc(100% - var(--ui-glass-glare-stop)),var(--ui-glass-highlight) 100%);filter:blur(var(--ui-glass-highlight-blur,7px));inset:0;z-index:3}.ui-glass-rim{border:1px solid var(--ui-glass-rim);border-radius:inherit;filter:blur(var(--ui-glass-rim-blur,1px));height:calc(100% - var(--ui-glass-rim-inset, 9px));left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);width:calc(100% - var(--ui-glass-rim-inset, 9px));z-index:2}.ui-glass-chip{backdrop-filter:blur(var(--ui-glass-chip-blur,8px)) saturate(var(--ui-glass-saturate,150%));background-color:var(--ui-glass-surface);border:1px solid var(--ui-glass-border);box-shadow:inset 0 1px 0 var(--ui-glass-highlight)}}
@@ -0,0 +1 @@
1
+ @layer theme{[data-glass=thin],[data-glass=thin]:is(.light,.dark,[data-theme=light],[data-theme=dark]){--ui-glass-surface:light-dark(hsla(0,0%,100%,.2),hsla(0,0%,8%,.62));--ui-glass-border:light-dark(rgba(31,31,31,.16),hsla(0,0%,100%,.2));--ui-glass-blur:4px;--ui-glass-saturate:150%}[data-glass=regular],[data-glass=regular]:is(.light,.dark,[data-theme=light],[data-theme=dark]){--ui-glass-surface:light-dark(hsla(0,0%,100%,.35),hsla(0,0%,8%,.68));--ui-glass-border:light-dark(rgba(31,31,31,.2),hsla(0,0%,100%,.24));--ui-glass-blur:16px;--ui-glass-saturate:140%}[data-glass=thick],[data-glass=thick]:is(.light,.dark,[data-theme=light],[data-theme=dark]){--ui-glass-surface:light-dark(hsla(0,0%,100%,.45),hsla(0,0%,8%,.72));--ui-glass-border:light-dark(rgba(31,31,31,.24),hsla(0,0%,100%,.28));--ui-glass-blur:16px;--ui-glass-saturate:140%}}
@@ -0,0 +1,3 @@
1
+ export { GlassPresetProvider, useGlassPreset, type GlassPreset, type GlassPresetProviderProps, } from "./src/provider";
2
+ export { GlassPresetScope, type GlassPresetScopeProps } from "./src/scope";
3
+ export { GlassPresetScript, getGlassPresetScript, type GlassPresetScriptOptions, type GlassPresetScriptProps, } from "./src/script";
@@ -0,0 +1,9 @@
1
+ export {
2
+ GlassPresetProvider,
3
+ useGlassPreset
4
+ } from "./src/provider.mjs";
5
+ export { GlassPresetScope } from "./src/scope.mjs";
6
+ export {
7
+ GlassPresetScript,
8
+ getGlassPresetScript
9
+ } from "./src/script.mjs";
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ /** Shared glass material presets exposed by `data-glass`. */
3
+ declare const GLASS_PRESETS: readonly ["thin", "regular", "thick"];
4
+ type GlassPreset = (typeof GLASS_PRESETS)[number];
5
+ type GlassPresetProviderProps = {
6
+ /** Controlled preset. Omit to let the provider manage its own state. */
7
+ preset?: GlassPreset;
8
+ /** Initial preset when the provider is uncontrolled. @default "thin" */
9
+ defaultPreset?: GlassPreset;
10
+ /** Optional `localStorage` key used to persist and restore the preset. */
11
+ storageKey?: string;
12
+ /** Called whenever `setPreset` requests a new preset. */
13
+ onPresetChange?: (preset: GlassPreset) => void;
14
+ children?: React.ReactNode;
15
+ };
16
+ type GlassPresetContextValue = {
17
+ preset: GlassPreset;
18
+ setPreset: (preset: GlassPreset) => void;
19
+ };
20
+ declare function GlassPresetProvider({ preset, defaultPreset, storageKey, onPresetChange, children, }: GlassPresetProviderProps): React.JSX.Element;
21
+ declare function useGlassPreset(): GlassPresetContextValue;
22
+ export { GlassPresetProvider, useGlassPreset };
23
+ export type { GlassPreset, GlassPresetProviderProps };
@@ -0,0 +1,113 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ const GLASS_PRESETS = ["thin", "regular", "thick"];
4
+ const DEFAULT_GLASS_PRESET = "thin";
5
+ function isGlassPreset(value) {
6
+ return typeof value === "string" && GLASS_PRESETS.includes(value);
7
+ }
8
+ const GlassPresetContext = React.createContext(null);
9
+ function readInitialPreset(defaultPreset, storageKey) {
10
+ if (typeof window !== "undefined" && storageKey) {
11
+ try {
12
+ const stored = window.localStorage.getItem(storageKey);
13
+ if (isGlassPreset(stored)) {
14
+ return stored;
15
+ }
16
+ } catch {
17
+ }
18
+ }
19
+ if (typeof document !== "undefined") {
20
+ const attribute = document.documentElement.dataset.glass;
21
+ if (isGlassPreset(attribute)) {
22
+ return attribute;
23
+ }
24
+ }
25
+ return defaultPreset;
26
+ }
27
+ function createGlassPresetStore(defaultPreset, storageKey) {
28
+ const serverSnapshot = {
29
+ preset: defaultPreset,
30
+ hydrated: false
31
+ };
32
+ let snapshot = serverSnapshot;
33
+ const listeners = /* @__PURE__ */ new Set();
34
+ return {
35
+ subscribe(listener) {
36
+ listeners.add(listener);
37
+ return () => {
38
+ listeners.delete(listener);
39
+ };
40
+ },
41
+ getSnapshot() {
42
+ if (!snapshot.hydrated) {
43
+ snapshot = {
44
+ preset: readInitialPreset(defaultPreset, storageKey),
45
+ hydrated: true
46
+ };
47
+ }
48
+ return snapshot;
49
+ },
50
+ getServerSnapshot() {
51
+ return serverSnapshot;
52
+ },
53
+ setPreset(preset) {
54
+ snapshot = { preset, hydrated: true };
55
+ for (const listener of listeners) {
56
+ listener();
57
+ }
58
+ }
59
+ };
60
+ }
61
+ function GlassPresetProvider({
62
+ preset,
63
+ defaultPreset = DEFAULT_GLASS_PRESET,
64
+ storageKey,
65
+ onPresetChange,
66
+ children
67
+ }) {
68
+ const controlled = preset !== void 0;
69
+ const [store] = React.useState(
70
+ () => createGlassPresetStore(defaultPreset, storageKey)
71
+ );
72
+ const persisted = React.useSyncExternalStore(
73
+ store.subscribe,
74
+ store.getSnapshot,
75
+ store.getServerSnapshot
76
+ );
77
+ const activePreset = preset ?? persisted.preset;
78
+ const setPreset = React.useCallback(
79
+ (next) => {
80
+ if (!controlled) {
81
+ store.setPreset(next);
82
+ }
83
+ onPresetChange?.(next);
84
+ },
85
+ [controlled, onPresetChange, store]
86
+ );
87
+ React.useEffect(() => {
88
+ if (!persisted.hydrated) {
89
+ return;
90
+ }
91
+ document.documentElement.dataset.glass = activePreset;
92
+ if (!storageKey) {
93
+ return;
94
+ }
95
+ try {
96
+ window.localStorage.setItem(storageKey, activePreset);
97
+ } catch {
98
+ }
99
+ }, [activePreset, persisted.hydrated, storageKey]);
100
+ const value = React.useMemo(
101
+ () => ({ preset: activePreset, setPreset }),
102
+ [activePreset, setPreset]
103
+ );
104
+ return /* @__PURE__ */ React.createElement(GlassPresetContext.Provider, { value }, children);
105
+ }
106
+ function useGlassPreset() {
107
+ const context = React.useContext(GlassPresetContext);
108
+ if (context === null) {
109
+ throw new Error("useGlassPreset must be used inside GlassPresetProvider");
110
+ }
111
+ return context;
112
+ }
113
+ export { GlassPresetProvider, useGlassPreset };
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ import type { GlassPreset } from "./provider";
3
+ type GlassPresetScopeProps = Omit<React.ComponentProps<"div">, "data-glass"> & {
4
+ /** Preset applied to this container and inherited by its descendants. */
5
+ preset: GlassPreset;
6
+ };
7
+ /**
8
+ * Applies a glass preset to a container without changing the global preset.
9
+ */
10
+ declare function GlassPresetScope({ preset, children, ...props }: GlassPresetScopeProps): React.JSX.Element;
11
+ export { GlassPresetScope };
12
+ export type { GlassPresetScopeProps };
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ function GlassPresetScope({
3
+ preset,
4
+ children,
5
+ ...props
6
+ }) {
7
+ return /* @__PURE__ */ React.createElement("div", { ...props, "data-glass": preset }, children);
8
+ }
9
+ export { GlassPresetScope };
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import type { GlassPreset } from "./provider";
3
+ type GlassPresetScriptOptions = {
4
+ /** `localStorage` key read before React hydrates. */
5
+ storageKey?: string;
6
+ /** Preset used when storage and the existing attribute are both empty. */
7
+ defaultPreset?: GlassPreset;
8
+ };
9
+ type GlassPresetScriptProps = GlassPresetScriptOptions & {
10
+ /** CSP nonce for the inline script. */
11
+ nonce?: string;
12
+ };
13
+ /**
14
+ * Returns the inline script that applies the persisted preset before React
15
+ * hydrates. Render it in `<head>` to avoid a flash of the default material.
16
+ */
17
+ declare function getGlassPresetScript({ storageKey, defaultPreset, }?: GlassPresetScriptOptions): string;
18
+ declare function GlassPresetScript({ storageKey, defaultPreset, nonce, }: GlassPresetScriptProps): React.JSX.Element;
19
+ export { GlassPresetScript, getGlassPresetScript };
20
+ export type { GlassPresetScriptOptions, GlassPresetScriptProps };
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ function toScriptLiteral(value) {
3
+ return JSON.stringify(value ?? null).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
4
+ }
5
+ function getGlassPresetScript({
6
+ storageKey,
7
+ defaultPreset = "thin"
8
+ } = {}) {
9
+ const key = storageKey === void 0 ? "null" : toScriptLiteral(storageKey);
10
+ const fallback = toScriptLiteral(defaultPreset);
11
+ return `(()=>{const presets=["thin","regular","thick"],root=document.documentElement;let stored=null;try{const key=${key};stored=key===null?null:localStorage.getItem(key)}catch{}const current=root.dataset.glass,preset=presets.includes(stored)?stored:presets.includes(current)?current:${fallback};root.dataset.glass=preset})()`;
12
+ }
13
+ function GlassPresetScript({
14
+ storageKey,
15
+ defaultPreset,
16
+ nonce
17
+ }) {
18
+ return /* @__PURE__ */ React.createElement(
19
+ "script",
20
+ {
21
+ nonce,
22
+ dangerouslySetInnerHTML: {
23
+ __html: getGlassPresetScript({ storageKey, defaultPreset })
24
+ }
25
+ }
26
+ );
27
+ }
28
+ export { GlassPresetScript, getGlassPresetScript };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingxingmofashu/ui",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Accessible React components with a Liquid Glass visual style for React 19 and Tailwind CSS 4.",
5
5
  "license": "MIT",
6
6
  "author": "xingxingmofashu",
@@ -34,6 +34,12 @@
34
34
  "default": "./dist/theme/*.mjs"
35
35
  },
36
36
  "./index.css": "./dist/index.css",
37
+ "./plugins/*/index.css": "./dist/plugins/*/index.css",
38
+ "./plugins/*": {
39
+ "types": "./dist/plugins/*/index.d.ts",
40
+ "import": "./dist/plugins/*/index.mjs",
41
+ "default": "./dist/plugins/*/index.mjs"
42
+ },
37
43
  "./package.json": "./package.json"
38
44
  },
39
45
  "main": "./dist/index.mjs",