@snowztech/ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +60 -0
- package/dist/chunk-XYNFF4B5.js +178 -0
- package/dist/chunk-XYNFF4B5.js.map +1 -0
- package/dist/client.cjs +158 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +22 -0
- package/dist/client.d.ts +22 -0
- package/dist/client.js +112 -0
- package/dist/client.js.map +1 -0
- package/dist/index.cjs +534 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +142 -0
- package/dist/index.d.ts +142 -0
- package/dist/index.js +279 -0
- package/dist/index.js.map +1 -0
- package/package.json +79 -0
- package/src/tokens.css +252 -0
package/dist/client.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { CheckIcon } from './chunk-XYNFF4B5.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function ThemeToggle({
|
|
7
|
+
size = 12,
|
|
8
|
+
storageKey = "theme",
|
|
9
|
+
defaultTheme = "dark",
|
|
10
|
+
className,
|
|
11
|
+
style
|
|
12
|
+
}) {
|
|
13
|
+
const [theme, setTheme] = React.useState(defaultTheme);
|
|
14
|
+
const [mounted, setMounted] = React.useState(false);
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
const stored = localStorage.getItem(storageKey) ?? defaultTheme;
|
|
17
|
+
setTheme(stored);
|
|
18
|
+
setMounted(true);
|
|
19
|
+
}, [storageKey, defaultTheme]);
|
|
20
|
+
const toggle = () => {
|
|
21
|
+
const next = theme === "dark" ? "light" : "dark";
|
|
22
|
+
setTheme(next);
|
|
23
|
+
localStorage.setItem(storageKey, next);
|
|
24
|
+
if (next === "light") document.documentElement.setAttribute("data-theme", "light");
|
|
25
|
+
else document.documentElement.removeAttribute("data-theme");
|
|
26
|
+
};
|
|
27
|
+
const filled = theme === "dark";
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
"button",
|
|
30
|
+
{
|
|
31
|
+
type: "button",
|
|
32
|
+
onClick: toggle,
|
|
33
|
+
"aria-label": `switch to ${filled ? "light" : "dark"} mode`,
|
|
34
|
+
className,
|
|
35
|
+
style: {
|
|
36
|
+
appearance: "none",
|
|
37
|
+
border: "none",
|
|
38
|
+
background: "transparent",
|
|
39
|
+
padding: 6,
|
|
40
|
+
cursor: "pointer",
|
|
41
|
+
display: "inline-flex",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center",
|
|
44
|
+
opacity: mounted ? 1 : 0,
|
|
45
|
+
transition: "opacity 200ms",
|
|
46
|
+
...style
|
|
47
|
+
},
|
|
48
|
+
children: /* @__PURE__ */ jsx(
|
|
49
|
+
"span",
|
|
50
|
+
{
|
|
51
|
+
style: {
|
|
52
|
+
display: "inline-block",
|
|
53
|
+
width: size,
|
|
54
|
+
height: size,
|
|
55
|
+
borderRadius: "50%",
|
|
56
|
+
border: `1px solid var(--sn-fg-muted)`,
|
|
57
|
+
background: filled ? "var(--sn-fg)" : "transparent",
|
|
58
|
+
transition: "background 160ms ease"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function CopyButton({ value, size = 14, className, style }) {
|
|
66
|
+
const [copied, setCopied] = React.useState(false);
|
|
67
|
+
const onCopy = async () => {
|
|
68
|
+
try {
|
|
69
|
+
await navigator.clipboard.writeText(value);
|
|
70
|
+
setCopied(true);
|
|
71
|
+
setTimeout(() => setCopied(false), 1200);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return /* @__PURE__ */ jsx(
|
|
76
|
+
"button",
|
|
77
|
+
{
|
|
78
|
+
type: "button",
|
|
79
|
+
onClick: onCopy,
|
|
80
|
+
"aria-label": copied ? "copied" : "copy",
|
|
81
|
+
className,
|
|
82
|
+
style: {
|
|
83
|
+
appearance: "none",
|
|
84
|
+
border: "1px solid transparent",
|
|
85
|
+
background: "transparent",
|
|
86
|
+
color: copied ? "var(--sn-success)" : "var(--sn-fg-muted)",
|
|
87
|
+
padding: 6,
|
|
88
|
+
cursor: "pointer",
|
|
89
|
+
display: "inline-flex",
|
|
90
|
+
alignItems: "center",
|
|
91
|
+
justifyContent: "center",
|
|
92
|
+
borderRadius: "var(--sn-r-xs)",
|
|
93
|
+
transition: "color 120ms ease, border-color 120ms ease",
|
|
94
|
+
...style
|
|
95
|
+
},
|
|
96
|
+
onMouseEnter: (e) => {
|
|
97
|
+
if (!copied) e.currentTarget.style.color = "var(--sn-fg)";
|
|
98
|
+
},
|
|
99
|
+
onMouseLeave: (e) => {
|
|
100
|
+
if (!copied) e.currentTarget.style.color = "var(--sn-fg-muted)";
|
|
101
|
+
},
|
|
102
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, { size }) : /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
103
|
+
/* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "11", height: "11", rx: "1.5" }),
|
|
104
|
+
/* @__PURE__ */ jsx("path", { d: "M5 15V5a1 1 0 0 1 1-1h10" })
|
|
105
|
+
] })
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export { CopyButton, ThemeToggle };
|
|
111
|
+
//# sourceMappingURL=client.js.map
|
|
112
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/theme-toggle.tsx","../src/copy-button.tsx"],"names":["React2","jsx"],"mappings":"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","file":"client.js","sourcesContent":["import * as React from \"react\";\n\nexport type Theme = \"light\" | \"dark\";\n\nexport interface ThemeToggleProps {\n size?: number;\n storageKey?: string;\n defaultTheme?: Theme;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function ThemeToggle({\n size = 12,\n storageKey = \"theme\",\n defaultTheme = \"dark\",\n className,\n style,\n}: ThemeToggleProps) {\n const [theme, setTheme] = React.useState<Theme>(defaultTheme);\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n const stored = (localStorage.getItem(storageKey) as Theme | null) ?? defaultTheme;\n setTheme(stored);\n setMounted(true);\n }, [storageKey, defaultTheme]);\n\n const toggle = () => {\n const next: Theme = theme === \"dark\" ? \"light\" : \"dark\";\n setTheme(next);\n localStorage.setItem(storageKey, next);\n if (next === \"light\") document.documentElement.setAttribute(\"data-theme\", \"light\");\n else document.documentElement.removeAttribute(\"data-theme\");\n };\n\n const filled = theme === \"dark\";\n\n return (\n <button\n type=\"button\"\n onClick={toggle}\n aria-label={`switch to ${filled ? \"light\" : \"dark\"} mode`}\n className={className}\n style={{\n appearance: \"none\",\n border: \"none\",\n background: \"transparent\",\n padding: 6,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: mounted ? 1 : 0,\n transition: \"opacity 200ms\",\n ...style,\n }}\n >\n <span\n style={{\n display: \"inline-block\",\n width: size,\n height: size,\n borderRadius: \"50%\",\n border: `1px solid var(--sn-fg-muted)`,\n background: filled ? \"var(--sn-fg)\" : \"transparent\",\n transition: \"background 160ms ease\",\n }}\n />\n </button>\n );\n}\n","import * as React from \"react\";\nimport { CheckIcon } from \"./icons\";\n\nexport interface CopyButtonProps {\n value: string;\n size?: number;\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport function CopyButton({ value, size = 14, className, style }: CopyButtonProps) {\n const [copied, setCopied] = React.useState(false);\n\n const onCopy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1200);\n } catch {\n // ignored\n }\n };\n\n return (\n <button\n type=\"button\"\n onClick={onCopy}\n aria-label={copied ? \"copied\" : \"copy\"}\n className={className}\n style={{\n appearance: \"none\",\n border: \"1px solid transparent\",\n background: \"transparent\",\n color: copied ? \"var(--sn-success)\" : \"var(--sn-fg-muted)\",\n padding: 6,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: \"var(--sn-r-xs)\",\n transition: \"color 120ms ease, border-color 120ms ease\",\n ...style,\n }}\n onMouseEnter={(e) => {\n if (!copied) e.currentTarget.style.color = \"var(--sn-fg)\";\n }}\n onMouseLeave={(e) => {\n if (!copied) e.currentTarget.style.color = \"var(--sn-fg-muted)\";\n }}\n >\n {copied ? (\n <CheckIcon size={size} />\n ) : (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"1.5\" />\n <path d=\"M5 15V5a1 1 0 0 1 1-1h10\" />\n </svg>\n )}\n </button>\n );\n}\n"]}
|