@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/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"]}