@sanity/themer 0.0.0 → 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/README.md +9 -89
- package/dist/{legacy.cjs → defaults-DJtuhI2W.js} +94 -56
- package/dist/defaults-DJtuhI2W.js.map +1 -0
- package/dist/legacy.d.ts +8 -90
- package/dist/legacy.d.ts.map +1 -1
- package/dist/legacy.js +2 -1199
- package/dist/tool.d.ts +20 -13
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +682 -250
- package/dist/tool.js.map +1 -1
- package/dist/types-DfPLuLv0.d.ts +74 -0
- package/dist/types-DfPLuLv0.d.ts.map +1 -0
- package/package.json +22 -39
- package/dist/_chunks/mix.cjs +0 -52
- package/dist/_chunks/mix.cjs.map +0 -1
- package/dist/_chunks/mix.js +0 -42
- package/dist/_chunks/mix.js.map +0 -1
- package/dist/_chunks/presets.cjs +0 -215
- package/dist/_chunks/presets.cjs.map +0 -1
- package/dist/_chunks/presets.js +0 -201
- package/dist/_chunks/presets.js.map +0 -1
- package/dist/_chunks/types.d.cts +0 -26
- package/dist/_chunks/types.d.cts.map +0 -1
- package/dist/_chunks/types.d.ts +0 -26
- package/dist/_chunks/types.d.ts.map +0 -1
- package/dist/index.cjs +0 -3
- package/dist/index.d.cts +0 -63
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts +0 -63
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/legacy.cjs.map +0 -1
- package/dist/legacy.d.cts +0 -166
- package/dist/legacy.d.cts.map +0 -1
- package/dist/legacy.js.map +0 -1
- package/dist/tool.cjs +0 -407
- package/dist/tool.cjs.map +0 -1
- package/dist/tool.d.cts +0 -45
- package/dist/tool.d.cts.map +0 -1
package/dist/tool.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { a as parseHuesFromUrl, c as isColor, i as createTheme, l as applyHues, o as createTonesFromHues, s as presets, t as hues } from "./defaults-DJtuhI2W.js";
|
|
2
|
+
import { COLOR_TINTS } from "@sanity/color";
|
|
3
|
+
import { c } from "react-compiler-runtime";
|
|
4
4
|
import { definePlugin } from "sanity";
|
|
5
|
-
import { Box, Button, Card, Code, Flex, Layer, Select, Stack, Text, ThemeProvider, useToast } from "@sanity/ui";
|
|
6
|
-
import { createContext, useContext, useEffect,
|
|
5
|
+
import { Box, Button, Card, Code, Flex, Grid, Layer, Select, Stack, Text, TextInput, ThemeProvider, Tooltip, useToast } from "@sanity/ui";
|
|
6
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
7
|
+
import { ChevronDownIcon } from "@sanity/icons/ChevronDown";
|
|
8
|
+
import { ChevronRightIcon } from "@sanity/icons/ChevronRight";
|
|
7
9
|
import { ClipboardIcon } from "@sanity/icons/Clipboard";
|
|
8
10
|
import { CloseIcon } from "@sanity/icons/Close";
|
|
9
11
|
import { ResetIcon } from "@sanity/icons/Reset";
|
|
12
|
+
import { registerLanguage } from "react-refractor";
|
|
13
|
+
import typescript from "refractor/typescript";
|
|
14
|
+
import { styled } from "styled-components";
|
|
10
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
16
|
import { ColorWheelIcon } from "@sanity/icons/ColorWheel";
|
|
12
17
|
/** @internal */
|
|
@@ -17,93 +22,193 @@ function useThemer() {
|
|
|
17
22
|
if (!context) throw Error("useThemer must be used within the `themerTool` plugin");
|
|
18
23
|
return context;
|
|
19
24
|
}
|
|
20
|
-
/**
|
|
21
|
-
|
|
25
|
+
/**
|
|
26
|
+
* The six hues in the order the hosted Themer service listed them, used for
|
|
27
|
+
* the sidebar's editors and the generated snippet alike.
|
|
28
|
+
*
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
const HUE_KEYS = [
|
|
32
|
+
"default",
|
|
33
|
+
"primary",
|
|
34
|
+
"transparent",
|
|
35
|
+
"positive",
|
|
36
|
+
"caution",
|
|
37
|
+
"critical"
|
|
38
|
+
], HUE_FIELDS = [
|
|
39
|
+
{
|
|
40
|
+
key: "default",
|
|
41
|
+
title: "Default",
|
|
42
|
+
description: "Text, icons and most surfaces"
|
|
43
|
+
},
|
|
22
44
|
{
|
|
23
45
|
key: "primary",
|
|
24
46
|
title: "Primary",
|
|
25
|
-
description: "
|
|
26
|
-
defaultValue: color.blue[500].hex
|
|
47
|
+
description: "Focus rings, links and primary buttons"
|
|
27
48
|
},
|
|
28
49
|
{
|
|
29
|
-
key: "
|
|
30
|
-
title: "
|
|
31
|
-
description: "
|
|
32
|
-
defaultValue: color.gray[500].hex
|
|
50
|
+
key: "transparent",
|
|
51
|
+
title: "Transparent",
|
|
52
|
+
description: "The backdrop behind panes"
|
|
33
53
|
},
|
|
34
54
|
{
|
|
35
55
|
key: "positive",
|
|
36
56
|
title: "Positive",
|
|
37
|
-
description: "Success
|
|
38
|
-
defaultValue: color.green[500].hex
|
|
57
|
+
description: "Success badges and prompts"
|
|
39
58
|
},
|
|
40
59
|
{
|
|
41
60
|
key: "caution",
|
|
42
61
|
title: "Caution",
|
|
43
|
-
description: "
|
|
44
|
-
defaultValue: color.yellow[500].hex
|
|
62
|
+
description: "Warnings and draft indicators"
|
|
45
63
|
},
|
|
46
64
|
{
|
|
47
65
|
key: "critical",
|
|
48
66
|
title: "Critical",
|
|
49
|
-
description: "Errors and destructive actions"
|
|
50
|
-
defaultValue: color.red[500].hex
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
key: "lightest",
|
|
54
|
-
title: "Lightest",
|
|
55
|
-
description: "Light mode background",
|
|
56
|
-
defaultValue: color.white.hex
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
key: "darkest",
|
|
60
|
-
title: "Darkest",
|
|
61
|
-
description: "Dark mode background",
|
|
62
|
-
defaultValue: color.black.hex
|
|
67
|
+
description: "Errors and destructive actions"
|
|
63
68
|
}
|
|
69
|
+
], MID_POINTS = [
|
|
70
|
+
50,
|
|
71
|
+
100,
|
|
72
|
+
200,
|
|
73
|
+
300,
|
|
74
|
+
400,
|
|
75
|
+
500,
|
|
76
|
+
600,
|
|
77
|
+
700,
|
|
78
|
+
800,
|
|
79
|
+
900,
|
|
80
|
+
950
|
|
81
|
+
], HUE_PROPERTIES = [
|
|
82
|
+
"mid",
|
|
83
|
+
"midPoint",
|
|
84
|
+
"lightest",
|
|
85
|
+
"darkest"
|
|
64
86
|
];
|
|
87
|
+
/** @internal */
|
|
88
|
+
function sameHues(a, b) {
|
|
89
|
+
return HUE_KEYS.every((key) => HUE_PROPERTIES.every((property) => {
|
|
90
|
+
let left = a[key][property], right = b[key][property];
|
|
91
|
+
return typeof left == "string" && typeof right == "string" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
65
94
|
/**
|
|
66
|
-
*
|
|
67
|
-
* `
|
|
95
|
+
* Reduces resolved hues to the minimal `PartialHues` that recreates them
|
|
96
|
+
* through the legacy `createTheme`. The subtlety is `applyHues`' quirk of
|
|
97
|
+
* resetting a customized `mid`'s mid point to 500: whenever `mid` is included,
|
|
98
|
+
* the baseline for `midPoint` is 500 rather than the hue's default.
|
|
68
99
|
*
|
|
69
100
|
* @internal
|
|
70
101
|
*/
|
|
71
|
-
function
|
|
72
|
-
let
|
|
73
|
-
|
|
102
|
+
function diffHues(hues$1) {
|
|
103
|
+
let diff = {};
|
|
104
|
+
for (let key of HUE_KEYS) {
|
|
105
|
+
let hue = hues$1[key], base = hues[key], patch = {};
|
|
106
|
+
hue.mid.toLowerCase() !== base.mid && (patch.mid = hue.mid.toLowerCase());
|
|
107
|
+
let impliedMidPoint = patch.mid === void 0 ? base.midPoint : 500;
|
|
108
|
+
hue.midPoint !== impliedMidPoint && (patch.midPoint = hue.midPoint), hue.lightest.toLowerCase() !== base.lightest && (patch.lightest = hue.lightest.toLowerCase()), hue.darkest.toLowerCase() !== base.darkest && (patch.darkest = hue.darkest.toLowerCase()), Object.keys(patch).length > 0 && (diff[key] = patch);
|
|
109
|
+
}
|
|
110
|
+
return diff;
|
|
74
111
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
padding: 0,
|
|
79
|
-
border: "1px solid var(--card-border-color)",
|
|
80
|
-
borderRadius: 6,
|
|
81
|
-
background: "transparent",
|
|
82
|
-
cursor: "pointer",
|
|
83
|
-
flex: "none"
|
|
84
|
-
};
|
|
85
|
-
function sameColors(a, b) {
|
|
86
|
-
return THEMER_FIELDS.every(({ key }) => (a[key]?.toLowerCase() ?? void 0) === (b[key]?.toLowerCase() ?? void 0));
|
|
112
|
+
function serializeHue(hue) {
|
|
113
|
+
let parts = [];
|
|
114
|
+
return hue.mid !== void 0 && parts.push(`mid: '${hue.mid}'`), hue.midPoint !== void 0 && parts.push(`midPoint: ${hue.midPoint}`), hue.lightest !== void 0 && parts.push(`lightest: '${hue.lightest}'`), hue.darkest !== void 0 && parts.push(`darkest: '${hue.darkest}'`), `{${parts.join(", ")}}`;
|
|
87
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Serializes hues into the `createTheme` call to paste into
|
|
118
|
+
* `sanity.config.ts`, keeping only what differs from the default hues.
|
|
119
|
+
*
|
|
120
|
+
* Hues that match the defaults entirely are the stock Studio theme, which
|
|
121
|
+
* needs nothing from this package — so they serialize to a bare `buildTheme()`
|
|
122
|
+
* instead.
|
|
123
|
+
*
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
function createThemeSnippet(hues) {
|
|
127
|
+
let diff = diffHues(hues), entries = [];
|
|
128
|
+
for (let key of HUE_KEYS) {
|
|
129
|
+
let patch = diff[key];
|
|
130
|
+
patch && entries.push(` ${key}: ${serializeHue(patch)},`);
|
|
131
|
+
}
|
|
132
|
+
return entries.length === 0 ? "import {buildTheme} from '@sanity/ui/theme'\n\nexport const theme = buildTheme()\n" : `import {createTheme} from '@sanity/themer/legacy'\n\nexport const theme = createTheme({\n${entries.join("\n")}\n})\n`;
|
|
133
|
+
}
|
|
134
|
+
registerLanguage(typescript);
|
|
135
|
+
/**
|
|
136
|
+
* The tool's take on the hosted service's presets: Tailwind Cyan is hidden and
|
|
137
|
+
* the default "Studio v3" preset reads just "Studio". The legacy `presets`
|
|
138
|
+
* export itself keeps both untouched, for parity with
|
|
139
|
+
* `https://themer.sanity.build/api/hues`.
|
|
140
|
+
*/
|
|
141
|
+
const TOOL_PRESETS = [];
|
|
142
|
+
for (let preset of presets) preset.slug !== "tw-cyan" && TOOL_PRESETS.push(preset.slug === "default" ? {
|
|
143
|
+
...preset,
|
|
144
|
+
title: "Studio"
|
|
145
|
+
} : preset);
|
|
146
|
+
/**
|
|
147
|
+
* `<input type="color">` paints the color into a shadow-DOM swatch that brings
|
|
148
|
+
* its own border and padding, which then sits inside ours as a second border.
|
|
149
|
+
* Stripping that chrome leaves the themed border as the only one.
|
|
150
|
+
*/
|
|
151
|
+
const Swatch = styled.input.withConfig({
|
|
152
|
+
displayName: "Swatch",
|
|
153
|
+
componentId: "sc-g4qzjc-0"
|
|
154
|
+
})`box-sizing:border-box;flex:none;width:33px;height:33px;padding:0;border:1px solid var(--card-border-color);border-radius:4px;background:none;cursor:pointer;&::-webkit-color-swatch-wrapper{padding:0;}&::-webkit-color-swatch{border:none;border-radius:3px;}&::-moz-color-swatch{border:none;border-radius:3px;}`;
|
|
88
155
|
/** Expands `#abc` to `#aabbcc`, which is the only format `<input type="color">` accepts */
|
|
89
156
|
function expandHex(hex) {
|
|
90
157
|
return hex.length === 4 ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex;
|
|
91
158
|
}
|
|
159
|
+
/** Prefixes bare query strings so `parseHuesFromUrl` accepts them too */
|
|
160
|
+
function normalizeImportUrl(input) {
|
|
161
|
+
let trimmed = input.trim();
|
|
162
|
+
return trimmed.startsWith("http") || trimmed.startsWith("?") ? trimmed : `?${trimmed}`;
|
|
163
|
+
}
|
|
92
164
|
/**
|
|
93
|
-
* The themer sidebar:
|
|
94
|
-
*
|
|
95
|
-
*
|
|
165
|
+
* The themer sidebar: presets, a themer.sanity.build URL importer and the
|
|
166
|
+
* per-hue editors of the hosted Themer service — mid color, mid point,
|
|
167
|
+
* lightest and darkest — that generate the previewed legacy theme, plus the
|
|
168
|
+
* `createTheme` snippet to make it permanent.
|
|
96
169
|
*
|
|
97
170
|
* @internal
|
|
98
171
|
*/
|
|
99
172
|
function ThemerSidebar() {
|
|
100
|
-
let {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
173
|
+
let $ = c(71), { baseHues, hues, setHues, setOpen } = useThemer(), toast = useToast(), [expandedHue, setExpandedHue] = useState(null), [importUrl, setImportUrl] = useState(""), active = hues ?? baseHues, t0;
|
|
174
|
+
$[0] === active ? t0 = $[1] : (t0 = createTonesFromHues(active), $[0] = active, $[1] = t0);
|
|
175
|
+
let tones = t0, t1;
|
|
176
|
+
$[2] === active ? t1 = $[3] : (t1 = TOOL_PRESETS.find((preset) => sameHues(preset.hues, active))?.slug ?? "", $[2] = active, $[3] = t1);
|
|
177
|
+
let activePresetSlug = t1, t2;
|
|
178
|
+
$[4] === active ? t2 = $[5] : (t2 = createThemeSnippet(active), $[4] = active, $[5] = t2);
|
|
179
|
+
let snippet = t2, t3;
|
|
180
|
+
$[6] !== active || $[7] !== setHues ? (t3 = (key, patch) => {
|
|
181
|
+
setHues({
|
|
182
|
+
...active,
|
|
183
|
+
[key]: {
|
|
184
|
+
...active[key],
|
|
185
|
+
...patch
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}, $[6] = active, $[7] = setHues, $[8] = t3) : t3 = $[8];
|
|
189
|
+
let handleHueChange = t3, t4;
|
|
190
|
+
$[9] === setHues ? t4 = $[10] : (t4 = (slug) => {
|
|
191
|
+
let preset_0 = TOOL_PRESETS.find((candidate) => candidate.slug === slug);
|
|
192
|
+
preset_0 && setHues(preset_0.hues);
|
|
193
|
+
}, $[9] = setHues, $[10] = t4);
|
|
194
|
+
let handlePresetChange = t4, t5;
|
|
195
|
+
$[11] !== importUrl || $[12] !== setHues || $[13] !== toast ? (t5 = () => {
|
|
196
|
+
if (importUrl.trim()) try {
|
|
197
|
+
setHues(parseHuesFromUrl(normalizeImportUrl(importUrl))), setImportUrl(""), toast.push({
|
|
198
|
+
status: "success",
|
|
199
|
+
title: "Imported theme from URL"
|
|
200
|
+
});
|
|
201
|
+
} catch (t6) {
|
|
202
|
+
let error = t6;
|
|
203
|
+
toast.push({
|
|
204
|
+
status: "error",
|
|
205
|
+
title: "Could not import the URL",
|
|
206
|
+
description: error instanceof Error ? error.message : String(error)
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}, $[11] = importUrl, $[12] = setHues, $[13] = toast, $[14] = t5) : t5 = $[14];
|
|
210
|
+
let handleImport = t5, t6;
|
|
211
|
+
$[15] !== snippet || $[16] !== toast ? (t6 = async () => {
|
|
107
212
|
try {
|
|
108
213
|
await navigator.clipboard.writeText(snippet), toast.push({
|
|
109
214
|
status: "success",
|
|
@@ -115,149 +220,419 @@ function ThemerSidebar() {
|
|
|
115
220
|
title: "Could not copy the theme"
|
|
116
221
|
});
|
|
117
222
|
}
|
|
118
|
-
};
|
|
119
|
-
|
|
223
|
+
}, $[15] = snippet, $[16] = toast, $[17] = t6) : t6 = $[17];
|
|
224
|
+
let handleCopy = t6, t7;
|
|
225
|
+
$[18] === Symbol.for("react.memo_cache_sentinel") ? (t7 = /* @__PURE__ */ jsx(Box, {
|
|
226
|
+
flex: 1,
|
|
227
|
+
paddingLeft: 1,
|
|
228
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
229
|
+
size: 1,
|
|
230
|
+
weight: "semibold",
|
|
231
|
+
children: "Themer"
|
|
232
|
+
})
|
|
233
|
+
}), $[18] = t7) : t7 = $[18];
|
|
234
|
+
let t8;
|
|
235
|
+
$[19] === setOpen ? t8 = $[20] : (t8 = /* @__PURE__ */ jsx(Card, {
|
|
236
|
+
borderBottom: !0,
|
|
237
|
+
padding: 3,
|
|
238
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
239
|
+
align: "center",
|
|
240
|
+
gap: 2,
|
|
241
|
+
children: [t7, /* @__PURE__ */ jsx(Button, {
|
|
242
|
+
icon: CloseIcon,
|
|
243
|
+
mode: "bleed",
|
|
244
|
+
onClick: () => setOpen(!1),
|
|
245
|
+
padding: 2,
|
|
246
|
+
title: "Close themer"
|
|
247
|
+
})]
|
|
248
|
+
})
|
|
249
|
+
}), $[19] = setOpen, $[20] = t8);
|
|
250
|
+
let t9;
|
|
251
|
+
$[21] === Symbol.for("react.memo_cache_sentinel") ? (t9 = /* @__PURE__ */ jsx(Text, {
|
|
252
|
+
size: 1,
|
|
253
|
+
weight: "medium",
|
|
254
|
+
children: "Presets"
|
|
255
|
+
}), $[21] = t9) : t9 = $[21];
|
|
256
|
+
let t10;
|
|
257
|
+
$[22] !== activePresetSlug || $[23] !== handlePresetChange ? (t10 = TOOL_PRESETS.map((preset_1) => /* @__PURE__ */ jsx(PresetButton, {
|
|
258
|
+
active: preset_1.slug === activePresetSlug,
|
|
259
|
+
onClick: handlePresetChange,
|
|
260
|
+
preset: preset_1
|
|
261
|
+
}, preset_1.slug)), $[22] = activePresetSlug, $[23] = handlePresetChange, $[24] = t10) : t10 = $[24];
|
|
262
|
+
let t11;
|
|
263
|
+
$[25] === t10 ? t11 = $[26] : (t11 = /* @__PURE__ */ jsxs(Stack, {
|
|
264
|
+
gap: 3,
|
|
265
|
+
children: [t9, /* @__PURE__ */ jsx(Grid, {
|
|
266
|
+
gap: 2,
|
|
267
|
+
gridTemplateColumns: 2,
|
|
268
|
+
children: t10
|
|
269
|
+
})]
|
|
270
|
+
}), $[25] = t10, $[26] = t11);
|
|
271
|
+
let t12;
|
|
272
|
+
$[27] === Symbol.for("react.memo_cache_sentinel") ? (t12 = /* @__PURE__ */ jsx(Text, {
|
|
273
|
+
size: 1,
|
|
274
|
+
weight: "medium",
|
|
275
|
+
children: "Import"
|
|
276
|
+
}), $[27] = t12) : t12 = $[27];
|
|
277
|
+
let t13;
|
|
278
|
+
$[28] === handleImport ? t13 = $[29] : (t13 = (event) => {
|
|
279
|
+
event.preventDefault(), handleImport();
|
|
280
|
+
}, $[28] = handleImport, $[29] = t13);
|
|
281
|
+
let t14;
|
|
282
|
+
$[30] === Symbol.for("react.memo_cache_sentinel") ? (t14 = (event_0) => setImportUrl(event_0.currentTarget.value), $[30] = t14) : t14 = $[30];
|
|
283
|
+
let t15;
|
|
284
|
+
$[31] === importUrl ? t15 = $[32] : (t15 = /* @__PURE__ */ jsx(Box, {
|
|
285
|
+
flex: 1,
|
|
286
|
+
children: /* @__PURE__ */ jsx(TextInput, {
|
|
287
|
+
"aria-label": "Hosted Themer URL",
|
|
288
|
+
fontSize: 1,
|
|
289
|
+
onChange: t14,
|
|
290
|
+
padding: 2,
|
|
291
|
+
placeholder: "themer.sanity.build URL",
|
|
292
|
+
value: importUrl
|
|
293
|
+
})
|
|
294
|
+
}), $[31] = importUrl, $[32] = t15);
|
|
295
|
+
let t16;
|
|
296
|
+
$[33] === Symbol.for("react.memo_cache_sentinel") ? (t16 = /* @__PURE__ */ jsx(Button, {
|
|
297
|
+
mode: "ghost",
|
|
298
|
+
padding: 2,
|
|
299
|
+
text: "Import",
|
|
300
|
+
type: "submit"
|
|
301
|
+
}), $[33] = t16) : t16 = $[33];
|
|
302
|
+
let t17;
|
|
303
|
+
$[34] === t15 ? t17 = $[35] : (t17 = /* @__PURE__ */ jsxs(Flex, {
|
|
304
|
+
gap: 2,
|
|
305
|
+
children: [t15, t16]
|
|
306
|
+
}), $[34] = t15, $[35] = t17);
|
|
307
|
+
let t18;
|
|
308
|
+
$[36] !== t13 || $[37] !== t17 ? (t18 = /* @__PURE__ */ jsxs(Stack, {
|
|
309
|
+
gap: 3,
|
|
310
|
+
children: [t12, /* @__PURE__ */ jsx("form", {
|
|
311
|
+
onSubmit: t13,
|
|
312
|
+
children: t17
|
|
313
|
+
})]
|
|
314
|
+
}), $[36] = t13, $[37] = t17, $[38] = t18) : t18 = $[38];
|
|
315
|
+
let t19;
|
|
316
|
+
$[39] === Symbol.for("react.memo_cache_sentinel") ? (t19 = /* @__PURE__ */ jsx(Text, {
|
|
317
|
+
size: 1,
|
|
318
|
+
weight: "medium",
|
|
319
|
+
children: "Hues"
|
|
320
|
+
}), $[39] = t19) : t19 = $[39];
|
|
321
|
+
let t20;
|
|
322
|
+
$[40] !== active || $[41] !== expandedHue || $[42] !== handleHueChange || $[43] !== tones ? (t20 = HUE_FIELDS.map((field) => /* @__PURE__ */ jsx(HueSection, {
|
|
323
|
+
expanded: expandedHue === field.key,
|
|
324
|
+
field,
|
|
325
|
+
hue: active[field.key],
|
|
326
|
+
onChange: handleHueChange,
|
|
327
|
+
onToggle: () => setExpandedHue(expandedHue === field.key ? null : field.key),
|
|
328
|
+
tints: tones[field.key]
|
|
329
|
+
}, field.key)), $[40] = active, $[41] = expandedHue, $[42] = handleHueChange, $[43] = tones, $[44] = t20) : t20 = $[44];
|
|
330
|
+
let t21;
|
|
331
|
+
$[45] === t20 ? t21 = $[46] : (t21 = /* @__PURE__ */ jsxs(Stack, {
|
|
332
|
+
gap: 3,
|
|
333
|
+
children: [t19, /* @__PURE__ */ jsx(Stack, {
|
|
334
|
+
gap: 1,
|
|
335
|
+
children: t20
|
|
336
|
+
})]
|
|
337
|
+
}), $[45] = t20, $[46] = t21);
|
|
338
|
+
let t22;
|
|
339
|
+
$[47] === Symbol.for("react.memo_cache_sentinel") ? (t22 = /* @__PURE__ */ jsx(Text, {
|
|
340
|
+
size: 1,
|
|
341
|
+
weight: "medium",
|
|
342
|
+
children: "Add to your config"
|
|
343
|
+
}), $[47] = t22) : t22 = $[47];
|
|
344
|
+
let t23;
|
|
345
|
+
$[48] === snippet ? t23 = $[49] : (t23 = /* @__PURE__ */ jsx(Card, {
|
|
346
|
+
border: !0,
|
|
347
|
+
overflow: "auto",
|
|
348
|
+
padding: 2,
|
|
349
|
+
radius: 2,
|
|
350
|
+
tone: "transparent",
|
|
351
|
+
children: /* @__PURE__ */ jsx(Code, {
|
|
352
|
+
language: "ts",
|
|
353
|
+
size: 0,
|
|
354
|
+
children: snippet
|
|
355
|
+
})
|
|
356
|
+
}), $[48] = snippet, $[49] = t23);
|
|
357
|
+
let t24;
|
|
358
|
+
$[50] === handleCopy ? t24 = $[51] : (t24 = /* @__PURE__ */ jsx(Button, {
|
|
359
|
+
icon: ClipboardIcon,
|
|
360
|
+
mode: "ghost",
|
|
361
|
+
onClick: () => void handleCopy(),
|
|
362
|
+
text: "Copy"
|
|
363
|
+
}), $[50] = handleCopy, $[51] = t24);
|
|
364
|
+
let t25 = hues === null, t26;
|
|
365
|
+
$[52] === setHues ? t26 = $[53] : (t26 = () => setHues(null), $[52] = setHues, $[53] = t26);
|
|
366
|
+
let t27;
|
|
367
|
+
$[54] !== t25 || $[55] !== t26 ? (t27 = /* @__PURE__ */ jsx(Button, {
|
|
368
|
+
disabled: t25,
|
|
369
|
+
icon: ResetIcon,
|
|
370
|
+
mode: "ghost",
|
|
371
|
+
onClick: t26,
|
|
372
|
+
text: "Reset",
|
|
373
|
+
tone: "critical"
|
|
374
|
+
}), $[54] = t25, $[55] = t26, $[56] = t27) : t27 = $[56];
|
|
375
|
+
let t28;
|
|
376
|
+
$[57] !== t24 || $[58] !== t27 ? (t28 = /* @__PURE__ */ jsxs(Flex, {
|
|
377
|
+
gap: 2,
|
|
378
|
+
children: [t24, t27]
|
|
379
|
+
}), $[57] = t24, $[58] = t27, $[59] = t28) : t28 = $[59];
|
|
380
|
+
let t29;
|
|
381
|
+
$[60] !== t23 || $[61] !== t28 ? (t29 = /* @__PURE__ */ jsxs(Stack, {
|
|
382
|
+
gap: 3,
|
|
383
|
+
children: [
|
|
384
|
+
t22,
|
|
385
|
+
t23,
|
|
386
|
+
t28
|
|
387
|
+
]
|
|
388
|
+
}), $[60] = t23, $[61] = t28, $[62] = t29) : t29 = $[62];
|
|
389
|
+
let t30;
|
|
390
|
+
$[63] !== t11 || $[64] !== t18 || $[65] !== t21 || $[66] !== t29 ? (t30 = /* @__PURE__ */ jsx(Box, {
|
|
391
|
+
flex: 1,
|
|
392
|
+
overflow: "auto",
|
|
393
|
+
padding: 3,
|
|
394
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
395
|
+
gap: 4,
|
|
396
|
+
children: [
|
|
397
|
+
t11,
|
|
398
|
+
t18,
|
|
399
|
+
t21,
|
|
400
|
+
t29
|
|
401
|
+
]
|
|
402
|
+
})
|
|
403
|
+
}), $[63] = t11, $[64] = t18, $[65] = t21, $[66] = t29, $[67] = t30) : t30 = $[67];
|
|
404
|
+
let t31;
|
|
405
|
+
return $[68] !== t30 || $[69] !== t8 ? (t31 = /* @__PURE__ */ jsx(Card, {
|
|
120
406
|
height: "fill",
|
|
121
407
|
children: /* @__PURE__ */ jsxs(Flex, {
|
|
122
408
|
direction: "column",
|
|
123
409
|
height: "fill",
|
|
124
|
-
children: [
|
|
125
|
-
borderBottom: !0,
|
|
126
|
-
padding: 3,
|
|
127
|
-
children: /* @__PURE__ */ jsxs(Flex, {
|
|
128
|
-
align: "center",
|
|
129
|
-
gap: 2,
|
|
130
|
-
children: [/* @__PURE__ */ jsx(Box, {
|
|
131
|
-
flex: 1,
|
|
132
|
-
paddingLeft: 1,
|
|
133
|
-
children: /* @__PURE__ */ jsx(Text, {
|
|
134
|
-
size: 1,
|
|
135
|
-
weight: "semibold",
|
|
136
|
-
children: "Themer"
|
|
137
|
-
})
|
|
138
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
139
|
-
icon: CloseIcon,
|
|
140
|
-
mode: "bleed",
|
|
141
|
-
onClick: () => setOpen(!1),
|
|
142
|
-
padding: 2,
|
|
143
|
-
title: "Close themer"
|
|
144
|
-
})]
|
|
145
|
-
})
|
|
146
|
-
}), /* @__PURE__ */ jsx(Box, {
|
|
147
|
-
flex: 1,
|
|
148
|
-
overflow: "auto",
|
|
149
|
-
padding: 4,
|
|
150
|
-
children: /* @__PURE__ */ jsxs(Stack, {
|
|
151
|
-
gap: 5,
|
|
152
|
-
children: [
|
|
153
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
154
|
-
gap: 3,
|
|
155
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
156
|
-
size: 1,
|
|
157
|
-
weight: "medium",
|
|
158
|
-
children: "Preset"
|
|
159
|
-
}), /* @__PURE__ */ jsxs(Select, {
|
|
160
|
-
onChange: (event) => handlePresetChange(event.currentTarget.value),
|
|
161
|
-
value: activePresetSlug,
|
|
162
|
-
children: [activePresetSlug === "" && /* @__PURE__ */ jsx("option", {
|
|
163
|
-
value: "",
|
|
164
|
-
children: "Custom"
|
|
165
|
-
}), presets.map((preset) => /* @__PURE__ */ jsx("option", {
|
|
166
|
-
value: preset.slug,
|
|
167
|
-
children: preset.title
|
|
168
|
-
}, preset.slug))]
|
|
169
|
-
})]
|
|
170
|
-
}),
|
|
171
|
-
/* @__PURE__ */ jsx(Stack, {
|
|
172
|
-
gap: 4,
|
|
173
|
-
children: THEMER_FIELDS.map((field) => /* @__PURE__ */ jsx(ColorField, {
|
|
174
|
-
field,
|
|
175
|
-
onChange: handleFieldChange,
|
|
176
|
-
value: active[field.key]
|
|
177
|
-
}, field.key))
|
|
178
|
-
}),
|
|
179
|
-
/* @__PURE__ */ jsxs(Stack, {
|
|
180
|
-
gap: 3,
|
|
181
|
-
children: [
|
|
182
|
-
/* @__PURE__ */ jsx(Text, {
|
|
183
|
-
size: 1,
|
|
184
|
-
weight: "medium",
|
|
185
|
-
children: "Add to your config"
|
|
186
|
-
}),
|
|
187
|
-
/* @__PURE__ */ jsx(Card, {
|
|
188
|
-
border: !0,
|
|
189
|
-
overflow: "auto",
|
|
190
|
-
padding: 3,
|
|
191
|
-
radius: 2,
|
|
192
|
-
tone: "transparent",
|
|
193
|
-
children: /* @__PURE__ */ jsx(Code, {
|
|
194
|
-
language: "ts",
|
|
195
|
-
size: 0,
|
|
196
|
-
children: snippet
|
|
197
|
-
})
|
|
198
|
-
}),
|
|
199
|
-
/* @__PURE__ */ jsxs(Flex, {
|
|
200
|
-
gap: 2,
|
|
201
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
202
|
-
icon: ClipboardIcon,
|
|
203
|
-
mode: "ghost",
|
|
204
|
-
onClick: () => void handleCopy(),
|
|
205
|
-
text: "Copy"
|
|
206
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
207
|
-
disabled: colors === null,
|
|
208
|
-
icon: ResetIcon,
|
|
209
|
-
mode: "ghost",
|
|
210
|
-
onClick: () => setColors(null),
|
|
211
|
-
text: "Reset",
|
|
212
|
-
tone: "critical"
|
|
213
|
-
})]
|
|
214
|
-
})
|
|
215
|
-
]
|
|
216
|
-
})
|
|
217
|
-
]
|
|
218
|
-
})
|
|
219
|
-
})]
|
|
410
|
+
children: [t8, t30]
|
|
220
411
|
})
|
|
221
|
-
});
|
|
412
|
+
}), $[68] = t30, $[69] = t8, $[70] = t31) : t31 = $[70], t31;
|
|
413
|
+
}
|
|
414
|
+
const paletteStyle = {
|
|
415
|
+
display: "flex",
|
|
416
|
+
gap: 1,
|
|
417
|
+
background: "var(--card-border-color)",
|
|
418
|
+
height: 21,
|
|
419
|
+
borderRadius: 3,
|
|
420
|
+
overflow: "hidden",
|
|
421
|
+
boxShadow: "inset 0 0 0 1px var(--card-border-color)"
|
|
422
|
+
};
|
|
423
|
+
/** A little color palette of the hue mid colors a preset would apply */
|
|
424
|
+
function PresetButton(props) {
|
|
425
|
+
let $ = c(17), { active, onClick, preset } = props, t0;
|
|
426
|
+
$[0] !== onClick || $[1] !== preset.slug ? (t0 = () => onClick(preset.slug), $[0] = onClick, $[1] = preset.slug, $[2] = t0) : t0 = $[2];
|
|
427
|
+
let t1 = preset.title, t2;
|
|
428
|
+
$[3] === preset.hues ? t2 = $[4] : (t2 = HUE_KEYS.map((key) => /* @__PURE__ */ jsx("span", { style: {
|
|
429
|
+
flex: 1,
|
|
430
|
+
background: preset.hues[key].mid
|
|
431
|
+
} }, key)), $[3] = preset.hues, $[4] = t2);
|
|
432
|
+
let t3;
|
|
433
|
+
$[5] === t2 ? t3 = $[6] : (t3 = /* @__PURE__ */ jsx("span", {
|
|
434
|
+
style: paletteStyle,
|
|
435
|
+
children: t2
|
|
436
|
+
}), $[5] = t2, $[6] = t3);
|
|
437
|
+
let t4;
|
|
438
|
+
$[7] === preset.title ? t4 = $[8] : (t4 = /* @__PURE__ */ jsx(Text, {
|
|
439
|
+
align: "left",
|
|
440
|
+
size: 1,
|
|
441
|
+
textOverflow: "ellipsis",
|
|
442
|
+
children: preset.title
|
|
443
|
+
}), $[7] = preset.title, $[8] = t4);
|
|
444
|
+
let t5;
|
|
445
|
+
$[9] !== t3 || $[10] !== t4 ? (t5 = /* @__PURE__ */ jsxs(Stack, {
|
|
446
|
+
as: "span",
|
|
447
|
+
gap: 2,
|
|
448
|
+
children: [t3, t4]
|
|
449
|
+
}), $[9] = t3, $[10] = t4, $[11] = t5) : t5 = $[11];
|
|
450
|
+
let t6;
|
|
451
|
+
return $[12] !== active || $[13] !== preset.title || $[14] !== t0 || $[15] !== t5 ? (t6 = /* @__PURE__ */ jsx(Button, {
|
|
452
|
+
mode: "ghost",
|
|
453
|
+
onClick: t0,
|
|
454
|
+
padding: 2,
|
|
455
|
+
selected: active,
|
|
456
|
+
title: t1,
|
|
457
|
+
children: t5
|
|
458
|
+
}), $[12] = active, $[13] = preset.title, $[14] = t0, $[15] = t5, $[16] = t6) : t6 = $[16], t6;
|
|
222
459
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
460
|
+
const rampStyle = {
|
|
461
|
+
...paletteStyle,
|
|
462
|
+
height: 13,
|
|
463
|
+
borderRadius: 2
|
|
464
|
+
};
|
|
465
|
+
/** One hue of the theme: a collapsible header with the generated tint ramp */
|
|
466
|
+
function HueSection(props) {
|
|
467
|
+
let $ = c(35), { expanded, field, hue, onChange, onToggle, tints } = props, t0 = expanded ? "transparent" : void 0, t1 = expanded ? 3 : 0, t2 = expanded ? 3 : 0, t3 = field.description, t4;
|
|
468
|
+
$[0] === expanded ? t4 = $[1] : (t4 = /* @__PURE__ */ jsx(Text, {
|
|
469
|
+
size: 1,
|
|
470
|
+
children: jsx(expanded ? ChevronDownIcon : ChevronRightIcon, {})
|
|
471
|
+
}), $[0] = expanded, $[1] = t4);
|
|
472
|
+
let t5;
|
|
473
|
+
$[2] === Symbol.for("react.memo_cache_sentinel") ? (t5 = { width: 76 }, $[2] = t5) : t5 = $[2];
|
|
474
|
+
let t6;
|
|
475
|
+
$[3] === field.title ? t6 = $[4] : (t6 = /* @__PURE__ */ jsx(Box, {
|
|
476
|
+
as: "span",
|
|
477
|
+
style: t5,
|
|
478
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
479
|
+
size: 1,
|
|
480
|
+
textOverflow: "ellipsis",
|
|
481
|
+
weight: "medium",
|
|
482
|
+
children: field.title
|
|
483
|
+
})
|
|
484
|
+
}), $[3] = field.title, $[4] = t6);
|
|
485
|
+
let t7;
|
|
486
|
+
$[5] === Symbol.for("react.memo_cache_sentinel") ? (t7 = {
|
|
487
|
+
...rampStyle,
|
|
488
|
+
flex: 1
|
|
489
|
+
}, $[5] = t7) : t7 = $[5];
|
|
490
|
+
let t8;
|
|
491
|
+
$[6] === tints ? t8 = $[7] : (t8 = COLOR_TINTS.map((tint) => /* @__PURE__ */ jsx("span", { style: {
|
|
492
|
+
flex: 1,
|
|
493
|
+
background: tints[tint].hex
|
|
494
|
+
} }, tint)), $[6] = tints, $[7] = t8);
|
|
495
|
+
let t9;
|
|
496
|
+
$[8] === t8 ? t9 = $[9] : (t9 = /* @__PURE__ */ jsx("span", {
|
|
497
|
+
style: t7,
|
|
498
|
+
children: t8
|
|
499
|
+
}), $[8] = t8, $[9] = t9);
|
|
500
|
+
let t10;
|
|
501
|
+
$[10] !== t4 || $[11] !== t6 || $[12] !== t9 ? (t10 = /* @__PURE__ */ jsxs(Flex, {
|
|
226
502
|
align: "center",
|
|
503
|
+
as: "span",
|
|
504
|
+
gap: 2,
|
|
505
|
+
children: [
|
|
506
|
+
t4,
|
|
507
|
+
t6,
|
|
508
|
+
t9
|
|
509
|
+
]
|
|
510
|
+
}), $[10] = t4, $[11] = t6, $[12] = t9, $[13] = t10) : t10 = $[13];
|
|
511
|
+
let t11;
|
|
512
|
+
$[14] !== expanded || $[15] !== field.description || $[16] !== onToggle || $[17] !== t10 ? (t11 = /* @__PURE__ */ jsx(Button, {
|
|
513
|
+
"aria-expanded": expanded,
|
|
514
|
+
mode: "bleed",
|
|
515
|
+
onClick: onToggle,
|
|
516
|
+
padding: 2,
|
|
517
|
+
title: t3,
|
|
518
|
+
children: t10
|
|
519
|
+
}), $[14] = expanded, $[15] = field.description, $[16] = onToggle, $[17] = t10, $[18] = t11) : t11 = $[18];
|
|
520
|
+
let t12;
|
|
521
|
+
$[19] !== expanded || $[20] !== field.description || $[21] !== field.key || $[22] !== field.title || $[23] !== hue || $[24] !== onChange ? (t12 = expanded && /* @__PURE__ */ jsxs(Stack, {
|
|
227
522
|
gap: 3,
|
|
523
|
+
paddingX: 3,
|
|
228
524
|
children: [
|
|
229
|
-
/* @__PURE__ */
|
|
230
|
-
|
|
525
|
+
/* @__PURE__ */ jsx(Text, {
|
|
526
|
+
muted: !0,
|
|
527
|
+
size: 0,
|
|
528
|
+
children: field.description
|
|
529
|
+
}),
|
|
530
|
+
/* @__PURE__ */ jsx(ColorRow, {
|
|
531
|
+
onChange: (mid) => onChange(field.key, { mid }),
|
|
532
|
+
title: "Mid",
|
|
533
|
+
value: hue.mid
|
|
534
|
+
}),
|
|
535
|
+
/* @__PURE__ */ jsxs(Flex, {
|
|
536
|
+
align: "center",
|
|
231
537
|
gap: 2,
|
|
232
|
-
children: [/* @__PURE__ */
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
children:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
538
|
+
children: [/* @__PURE__ */ jsxs(Stack, {
|
|
539
|
+
flex: 1,
|
|
540
|
+
gap: 2,
|
|
541
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
542
|
+
size: 1,
|
|
543
|
+
children: "Mid point"
|
|
544
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
545
|
+
muted: !0,
|
|
546
|
+
size: 0,
|
|
547
|
+
children: "The tint the mid color sits at"
|
|
548
|
+
})]
|
|
549
|
+
}), /* @__PURE__ */ jsx(Select, {
|
|
550
|
+
"aria-label": `${field.title} mid point`,
|
|
551
|
+
fontSize: 1,
|
|
552
|
+
onChange: (event) => {
|
|
553
|
+
let value = Number(event.currentTarget.value), midPoint = MID_POINTS.find((candidate) => candidate === value);
|
|
554
|
+
midPoint !== void 0 && onChange(field.key, { midPoint });
|
|
555
|
+
},
|
|
556
|
+
padding: 2,
|
|
557
|
+
value: hue.midPoint,
|
|
558
|
+
children: MID_POINTS.map(_temp$1)
|
|
240
559
|
})]
|
|
241
560
|
}),
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
padding: 2,
|
|
247
|
-
title: `Reset ${field.title}`
|
|
561
|
+
/* @__PURE__ */ jsx(ColorRow, {
|
|
562
|
+
onChange: (lightest) => onChange(field.key, { lightest }),
|
|
563
|
+
title: "Lightest",
|
|
564
|
+
value: hue.lightest
|
|
248
565
|
}),
|
|
249
|
-
/* @__PURE__ */ jsx(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
type: "color",
|
|
254
|
-
value: expandHex(value ?? field.defaultValue)
|
|
566
|
+
/* @__PURE__ */ jsx(ColorRow, {
|
|
567
|
+
onChange: (darkest) => onChange(field.key, { darkest }),
|
|
568
|
+
title: "Darkest",
|
|
569
|
+
value: hue.darkest
|
|
255
570
|
})
|
|
256
571
|
]
|
|
257
|
-
});
|
|
572
|
+
}), $[19] = expanded, $[20] = field.description, $[21] = field.key, $[22] = field.title, $[23] = hue, $[24] = onChange, $[25] = t12) : t12 = $[25];
|
|
573
|
+
let t13;
|
|
574
|
+
$[26] !== t1 || $[27] !== t11 || $[28] !== t12 || $[29] !== t2 ? (t13 = /* @__PURE__ */ jsxs(Stack, {
|
|
575
|
+
gap: t1,
|
|
576
|
+
paddingBottom: t2,
|
|
577
|
+
children: [t11, t12]
|
|
578
|
+
}), $[26] = t1, $[27] = t11, $[28] = t12, $[29] = t2, $[30] = t13) : t13 = $[30];
|
|
579
|
+
let t14;
|
|
580
|
+
return $[31] !== expanded || $[32] !== t0 || $[33] !== t13 ? (t14 = /* @__PURE__ */ jsx(Card, {
|
|
581
|
+
border: expanded,
|
|
582
|
+
radius: 2,
|
|
583
|
+
tone: t0,
|
|
584
|
+
children: t13
|
|
585
|
+
}), $[31] = expanded, $[32] = t0, $[33] = t13, $[34] = t14) : t14 = $[34], t14;
|
|
586
|
+
}
|
|
587
|
+
function _temp$1(midPoint_0) {
|
|
588
|
+
return /* @__PURE__ */ jsx("option", {
|
|
589
|
+
value: midPoint_0,
|
|
590
|
+
children: midPoint_0
|
|
591
|
+
}, midPoint_0);
|
|
592
|
+
}
|
|
593
|
+
function ColorRow(props) {
|
|
594
|
+
let $ = c(18), { onChange, title, value } = props, t0;
|
|
595
|
+
$[0] === title ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
|
|
596
|
+
size: 1,
|
|
597
|
+
children: title
|
|
598
|
+
}), $[0] = title, $[1] = t0);
|
|
599
|
+
let t1;
|
|
600
|
+
$[2] === value ? t1 = $[3] : (t1 = /* @__PURE__ */ jsx(Text, {
|
|
601
|
+
muted: !0,
|
|
602
|
+
size: 0,
|
|
603
|
+
children: value
|
|
604
|
+
}), $[2] = value, $[3] = t1);
|
|
605
|
+
let t2;
|
|
606
|
+
$[4] !== t0 || $[5] !== t1 ? (t2 = /* @__PURE__ */ jsxs(Stack, {
|
|
607
|
+
flex: 1,
|
|
608
|
+
gap: 2,
|
|
609
|
+
children: [t0, t1]
|
|
610
|
+
}), $[4] = t0, $[5] = t1, $[6] = t2) : t2 = $[6];
|
|
611
|
+
let t3 = `${title} color`, t4;
|
|
612
|
+
$[7] === onChange ? t4 = $[8] : (t4 = (event) => onChange(event.currentTarget.value), $[7] = onChange, $[8] = t4);
|
|
613
|
+
let t5;
|
|
614
|
+
$[9] === value ? t5 = $[10] : (t5 = expandHex(value), $[9] = value, $[10] = t5);
|
|
615
|
+
let t6;
|
|
616
|
+
$[11] !== t3 || $[12] !== t4 || $[13] !== t5 ? (t6 = /* @__PURE__ */ jsx(Swatch, {
|
|
617
|
+
"aria-label": t3,
|
|
618
|
+
onChange: t4,
|
|
619
|
+
type: "color",
|
|
620
|
+
value: t5
|
|
621
|
+
}), $[11] = t3, $[12] = t4, $[13] = t5, $[14] = t6) : t6 = $[14];
|
|
622
|
+
let t7;
|
|
623
|
+
return $[15] !== t2 || $[16] !== t6 ? (t7 = /* @__PURE__ */ jsxs(Flex, {
|
|
624
|
+
align: "center",
|
|
625
|
+
gap: 2,
|
|
626
|
+
children: [t2, t6]
|
|
627
|
+
}), $[15] = t2, $[16] = t6, $[17] = t7) : t7 = $[17], t7;
|
|
258
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Narrow enough to leave the studio preview as much room as possible: it fits
|
|
631
|
+
* the widest picker label next to its swatch, and the code snippet scrolls
|
|
632
|
+
* horizontally rather than widening the sidebar.
|
|
633
|
+
*/
|
|
259
634
|
const sidebarStyle = {
|
|
260
|
-
width:
|
|
635
|
+
width: 240,
|
|
261
636
|
flex: "none",
|
|
262
637
|
borderLeft: "1px solid var(--card-border-color)",
|
|
263
638
|
boxSizing: "border-box",
|
|
@@ -270,52 +645,69 @@ const sidebarStyle = {
|
|
|
270
645
|
* @internal
|
|
271
646
|
*/
|
|
272
647
|
function ThemerActiveToolLayout(props) {
|
|
273
|
-
let { open } = useThemer();
|
|
274
|
-
|
|
648
|
+
let $ = c(9), { open } = useThemer(), t0;
|
|
649
|
+
$[0] === props ? t0 = $[1] : (t0 = props.renderDefault(props), $[0] = props, $[1] = t0);
|
|
650
|
+
let t1;
|
|
651
|
+
$[2] === t0 ? t1 = $[3] : (t1 = /* @__PURE__ */ jsx(Box, {
|
|
652
|
+
flex: 1,
|
|
653
|
+
height: "fill",
|
|
654
|
+
overflow: "auto",
|
|
655
|
+
children: t0
|
|
656
|
+
}), $[2] = t0, $[3] = t1);
|
|
657
|
+
let t2;
|
|
658
|
+
$[4] === open ? t2 = $[5] : (t2 = open && /* @__PURE__ */ jsx(Layer, {
|
|
659
|
+
height: "fill",
|
|
660
|
+
style: sidebarStyle,
|
|
661
|
+
zOffset: 100,
|
|
662
|
+
children: /* @__PURE__ */ jsx(ThemerSidebar, {})
|
|
663
|
+
}), $[4] = open, $[5] = t2);
|
|
664
|
+
let t3;
|
|
665
|
+
return $[6] !== t1 || $[7] !== t2 ? (t3 = /* @__PURE__ */ jsxs(Flex, {
|
|
275
666
|
height: "fill",
|
|
276
667
|
sizing: "border",
|
|
277
|
-
children: [
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
668
|
+
children: [t1, t2]
|
|
669
|
+
}), $[6] = t1, $[7] = t2, $[8] = t3) : t3 = $[8], t3;
|
|
670
|
+
}
|
|
671
|
+
const STORAGE_KEY = "sanityStudio:themer:hues";
|
|
672
|
+
function sanitizeHue(value) {
|
|
673
|
+
if (!value || typeof value != "object") return null;
|
|
674
|
+
let mid = Reflect.get(value, "mid"), midPoint = Reflect.get(value, "midPoint"), lightest = Reflect.get(value, "lightest"), darkest = Reflect.get(value, "darkest");
|
|
675
|
+
return typeof mid != "string" || !isColor(mid) || typeof lightest != "string" || !isColor(lightest) || typeof darkest != "string" || !isColor(darkest) || typeof midPoint != "number" || !MID_POINTS.includes(midPoint) ? null : {
|
|
676
|
+
mid: mid.toLowerCase(),
|
|
677
|
+
midPoint,
|
|
678
|
+
lightest: lightest.toLowerCase(),
|
|
679
|
+
darkest: darkest.toLowerCase()
|
|
680
|
+
};
|
|
289
681
|
}
|
|
290
|
-
const STORAGE_KEY = "sanityStudio:themer:colors";
|
|
291
682
|
/**
|
|
292
|
-
* Restores draft
|
|
683
|
+
* Restores draft hues from localStorage, so theme drafts survive studio
|
|
293
684
|
* reloads.
|
|
294
685
|
*
|
|
295
686
|
* @internal
|
|
296
687
|
*/
|
|
297
|
-
function
|
|
688
|
+
function readStoredHues() {
|
|
298
689
|
try {
|
|
299
690
|
if (typeof localStorage > "u") return null;
|
|
300
691
|
let raw = localStorage.getItem(STORAGE_KEY);
|
|
301
692
|
if (!raw) return null;
|
|
302
693
|
let parsed = JSON.parse(raw);
|
|
303
694
|
if (!parsed || typeof parsed != "object") return null;
|
|
304
|
-
let
|
|
305
|
-
for (let
|
|
306
|
-
let
|
|
307
|
-
|
|
695
|
+
let hues = {};
|
|
696
|
+
for (let key of HUE_KEYS) {
|
|
697
|
+
let hue = sanitizeHue(Reflect.get(parsed, key));
|
|
698
|
+
if (!hue) return null;
|
|
699
|
+
hues[key] = hue;
|
|
308
700
|
}
|
|
309
|
-
return
|
|
701
|
+
return hues;
|
|
310
702
|
} catch {
|
|
311
703
|
return null;
|
|
312
704
|
}
|
|
313
705
|
}
|
|
314
706
|
/** @internal */
|
|
315
|
-
function
|
|
707
|
+
function writeStoredHues(hues) {
|
|
316
708
|
try {
|
|
317
709
|
if (typeof localStorage > "u") return;
|
|
318
|
-
|
|
710
|
+
hues === null ? localStorage.removeItem(STORAGE_KEY) : localStorage.setItem(STORAGE_KEY, JSON.stringify(hues));
|
|
319
711
|
} catch {}
|
|
320
712
|
}
|
|
321
713
|
/**
|
|
@@ -330,56 +722,92 @@ function writeStoredColors(colors) {
|
|
|
330
722
|
* @internal
|
|
331
723
|
*/
|
|
332
724
|
function ThemerLayout(props) {
|
|
333
|
-
let {
|
|
334
|
-
|
|
335
|
-
let
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
725
|
+
let $ = c(13), { baseHues, ...layoutProps } = props, [open, setOpen] = useState(!1), [hues, setHues] = useState(readStoredHues), t0, t1;
|
|
726
|
+
$[0] === hues ? (t0 = $[1], t1 = $[2]) : (t0 = () => writeStoredHues(hues), t1 = [hues], $[0] = hues, $[1] = t0, $[2] = t1), useEffect(t0, t1);
|
|
727
|
+
let t2;
|
|
728
|
+
$[3] === hues ? t2 = $[4] : (t2 = hues === null ? null : createTheme(hues), $[3] = hues, $[4] = t2);
|
|
729
|
+
let theme = t2, t3;
|
|
730
|
+
$[5] !== baseHues || $[6] !== hues || $[7] !== open ? (t3 = {
|
|
731
|
+
baseHues,
|
|
732
|
+
hues,
|
|
733
|
+
setHues,
|
|
342
734
|
open,
|
|
343
735
|
setOpen
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return /* @__PURE__ */ jsx(
|
|
736
|
+
}, $[5] = baseHues, $[6] = hues, $[7] = open, $[8] = t3) : t3 = $[8];
|
|
737
|
+
let context = t3, t4 = ThemerContext, t5 = theme === null ? layoutProps.renderDefault(layoutProps) : /* @__PURE__ */ jsx(ThemeProvider, {
|
|
738
|
+
theme,
|
|
739
|
+
children: layoutProps.renderDefault(layoutProps)
|
|
740
|
+
}), t6;
|
|
741
|
+
return $[9] !== context || $[10] !== t4.Provider || $[11] !== t5 ? (t6 = /* @__PURE__ */ jsx(t4.Provider, {
|
|
350
742
|
value: context,
|
|
351
|
-
children:
|
|
352
|
-
|
|
353
|
-
|
|
743
|
+
children: t5
|
|
744
|
+
}), $[9] = context, $[10] = t4.Provider, $[11] = t5, $[12] = t6) : t6 = $[12], t6;
|
|
745
|
+
}
|
|
746
|
+
function ThemerNavbarButton() {
|
|
747
|
+
let $ = c(7), { open, setOpen } = useThemer(), t0;
|
|
748
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx(Text, {
|
|
749
|
+
size: 1,
|
|
750
|
+
children: "Themer"
|
|
751
|
+
}), $[0] = t0) : t0 = $[0];
|
|
752
|
+
let t1;
|
|
753
|
+
$[1] !== open || $[2] !== setOpen ? (t1 = () => setOpen(!open), $[1] = open, $[2] = setOpen, $[3] = t1) : t1 = $[3];
|
|
754
|
+
let t2;
|
|
755
|
+
return $[4] !== open || $[5] !== t1 ? (t2 = /* @__PURE__ */ jsx(Tooltip, {
|
|
756
|
+
content: t0,
|
|
757
|
+
portal: !0,
|
|
758
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
759
|
+
"aria-label": "Themer",
|
|
760
|
+
icon: ColorWheelIcon,
|
|
761
|
+
mode: "bleed",
|
|
762
|
+
onClick: t1,
|
|
763
|
+
padding: 2,
|
|
764
|
+
selected: open
|
|
354
765
|
})
|
|
355
|
-
});
|
|
766
|
+
}), $[4] = open, $[5] = t1, $[6] = t2) : t2 = $[6], t2;
|
|
356
767
|
}
|
|
357
768
|
/**
|
|
358
769
|
* Adds the toggle that opens and closes the themer sidebar to the Studio
|
|
359
|
-
* navbar
|
|
770
|
+
* navbar — an icon button with a tooltip in the top bar (like the Tasks
|
|
771
|
+
* toggle), and a regular titled action in the narrow-screen sidebar menu.
|
|
360
772
|
*
|
|
361
773
|
* @internal
|
|
362
774
|
*/
|
|
363
775
|
function ThemerNavbar(props) {
|
|
364
|
-
let { open, setOpen } = useThemer();
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
776
|
+
let $ = c(7), { open, setOpen } = useThemer(), t0;
|
|
777
|
+
if ($[0] !== open || $[1] !== props || $[2] !== setOpen) {
|
|
778
|
+
let t1;
|
|
779
|
+
$[4] !== open || $[5] !== setOpen ? (t1 = () => setOpen(!open), $[4] = open, $[5] = setOpen, $[6] = t1) : t1 = $[6], t0 = props.renderDefault({
|
|
780
|
+
...props,
|
|
781
|
+
__internal_actions: [
|
|
782
|
+
...props.__internal_actions ?? [],
|
|
783
|
+
{
|
|
784
|
+
location: "topbar",
|
|
785
|
+
name: "themer-topbar",
|
|
786
|
+
render: _temp
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
icon: ColorWheelIcon,
|
|
790
|
+
location: "sidebar",
|
|
791
|
+
name: "themer-sidebar",
|
|
792
|
+
onAction: t1,
|
|
793
|
+
selected: open,
|
|
794
|
+
title: "Themer"
|
|
795
|
+
}
|
|
796
|
+
]
|
|
797
|
+
}), $[0] = open, $[1] = props, $[2] = setOpen, $[3] = t0;
|
|
798
|
+
} else t0 = $[3];
|
|
799
|
+
return t0;
|
|
800
|
+
}
|
|
801
|
+
function _temp() {
|
|
802
|
+
return /* @__PURE__ */ jsx(ThemerNavbarButton, {});
|
|
376
803
|
}
|
|
377
804
|
/**
|
|
378
|
-
* A Studio plugin that adds a themer sidebar for
|
|
379
|
-
* a navbar toggle opens the sidebar next to the active tool, where presets
|
|
380
|
-
* and
|
|
381
|
-
*
|
|
382
|
-
* regular appearance menu — the
|
|
805
|
+
* A Studio plugin that adds a themer sidebar for the legacy Themer themes:
|
|
806
|
+
* a navbar toggle opens the sidebar next to the active tool, where presets,
|
|
807
|
+
* per-hue editors and pasted themer.sanity.build URLs preview a legacy
|
|
808
|
+
* `createTheme` theme live on the whole Studio while you browse around.
|
|
809
|
+
* Toggle between light and dark mode with the regular appearance menu — the
|
|
810
|
+
* preview follows it.
|
|
383
811
|
*
|
|
384
812
|
* ```ts
|
|
385
813
|
* import {themerTool} from '@sanity/themer/tool'
|
|
@@ -391,15 +819,19 @@ function ThemerNavbar(props) {
|
|
|
391
819
|
* })
|
|
392
820
|
* ```
|
|
393
821
|
*
|
|
394
|
-
*
|
|
822
|
+
* This is experimental and may change or be removed in any release without
|
|
823
|
+
* notice — use at your own risk.
|
|
824
|
+
*
|
|
825
|
+
* @alpha
|
|
395
826
|
*/
|
|
396
827
|
const themerTool = definePlugin((options) => {
|
|
397
|
-
let
|
|
828
|
+
let baseHues = applyHues(options?.hues ?? {});
|
|
398
829
|
function ThemerLayoutWithOptions(props) {
|
|
399
|
-
|
|
830
|
+
let $ = c(2), t0;
|
|
831
|
+
return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(ThemerLayout, {
|
|
400
832
|
...props,
|
|
401
|
-
|
|
402
|
-
});
|
|
833
|
+
baseHues
|
|
834
|
+
}), $[0] = props, $[1] = t0), t0;
|
|
403
835
|
}
|
|
404
836
|
return {
|
|
405
837
|
name: "@sanity/themer/tool",
|