@sanity/themer 0.0.0 → 0.2.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 +33 -58
- package/dist/index.d.ts +51 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/legacy.d.ts +7 -18
- package/dist/legacy.d.ts.map +1 -1
- package/dist/legacy.js +39 -39
- package/dist/legacy.js.map +1 -1
- package/dist/{_chunks/mix.js → mix-BfV6_Ke4.js} +1 -1
- package/dist/mix-BfV6_Ke4.js.map +1 -0
- package/dist/options-BaqJJgRs.d.ts +59 -0
- package/dist/options-BaqJJgRs.d.ts.map +1 -0
- package/dist/presets-DWzYcsLg.js +375 -0
- package/dist/presets-DWzYcsLg.js.map +1 -0
- package/dist/tool.d.ts +22 -15
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +608 -282
- package/dist/tool.js.map +1 -1
- package/package.json +24 -39
- package/dist/_chunks/mix.cjs +0 -52
- package/dist/_chunks/mix.cjs.map +0 -1
- 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/legacy.cjs +0 -1199
- package/dist/legacy.cjs.map +0 -1
- package/dist/legacy.d.cts +0 -166
- package/dist/legacy.d.cts.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,16 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { a as DEFAULT_BACKGROUND_DARK, c as resolveThemeOptions, i as DEFAULT_ACCENT, n as buildTheme, o as DEFAULT_BACKGROUND_LIGHT, r as buildPalette, s as deriveTextColor, t as presets } from "./presets-DWzYcsLg.js";
|
|
2
|
+
import { t as isColor } from "./mix-BfV6_Ke4.js";
|
|
3
|
+
import { COLOR_TINTS } from "@sanity/color";
|
|
4
|
+
import { c } from "react-compiler-runtime";
|
|
4
5
|
import { definePlugin } from "sanity";
|
|
5
|
-
import { Box, Button, Card, Code, Flex,
|
|
6
|
-
import { createContext, useContext, useEffect,
|
|
6
|
+
import { Box, Button, Card, Code, Flex, Grid, Layer, Stack, Text, ThemeProvider, Tooltip, useToast } from "@sanity/ui";
|
|
7
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
7
8
|
import { ClipboardIcon } from "@sanity/icons/Clipboard";
|
|
8
9
|
import { CloseIcon } from "@sanity/icons/Close";
|
|
9
10
|
import { ResetIcon } from "@sanity/icons/Reset";
|
|
11
|
+
import { registerLanguage } from "react-refractor";
|
|
12
|
+
import typescript from "refractor/typescript";
|
|
13
|
+
import { styled } from "styled-components";
|
|
10
14
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
15
|
import { ColorWheelIcon } from "@sanity/icons/ColorWheel";
|
|
12
16
|
/** @internal */
|
|
@@ -17,93 +21,112 @@ function useThemer() {
|
|
|
17
21
|
if (!context) throw Error("useThemer must be used within the `themerTool` plugin");
|
|
18
22
|
return context;
|
|
19
23
|
}
|
|
20
|
-
/** @internal */
|
|
21
|
-
const THEMER_FIELDS = [
|
|
22
|
-
{
|
|
23
|
-
key: "primary",
|
|
24
|
-
title: "Primary",
|
|
25
|
-
description: "Buttons, focus rings and links",
|
|
26
|
-
defaultValue: color.blue[500].hex
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
key: "gray",
|
|
30
|
-
title: "Gray",
|
|
31
|
-
description: "Neutral surfaces, borders and text",
|
|
32
|
-
defaultValue: color.gray[500].hex
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
key: "positive",
|
|
36
|
-
title: "Positive",
|
|
37
|
-
description: "Success accents",
|
|
38
|
-
defaultValue: color.green[500].hex
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
key: "caution",
|
|
42
|
-
title: "Caution",
|
|
43
|
-
description: "Warning accents",
|
|
44
|
-
defaultValue: color.yellow[500].hex
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
key: "critical",
|
|
48
|
-
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
|
|
63
|
-
}
|
|
64
|
-
];
|
|
65
24
|
/**
|
|
66
|
-
*
|
|
67
|
-
* `
|
|
25
|
+
* Reduces theme options to the minimal object that recreates them through
|
|
26
|
+
* `buildTheme`: the text color is dropped when it matches the one derived
|
|
27
|
+
* from the accent, and backgrounds and contrast are dropped when they match
|
|
28
|
+
* the defaults. Options that boil down to the stock Studio theme reduce to
|
|
29
|
+
* `null` — they need nothing from this package.
|
|
68
30
|
*
|
|
69
31
|
* @internal
|
|
70
32
|
*/
|
|
71
|
-
function
|
|
72
|
-
let
|
|
73
|
-
|
|
33
|
+
function minimizeOptions(options) {
|
|
34
|
+
let resolved = resolveThemeOptions(options), minimized = { accent: resolved.accent };
|
|
35
|
+
resolved.text !== deriveTextColor(resolved.accent) && (minimized.text = resolved.text);
|
|
36
|
+
let dark = resolved.background.dark === DEFAULT_BACKGROUND_DARK ? null : resolved.background.dark, light = resolved.background.light === DEFAULT_BACKGROUND_LIGHT ? null : resolved.background.light;
|
|
37
|
+
return (dark !== null || light !== null) && (minimized.background = {}, dark !== null && (minimized.background.dark = dark), light !== null && (minimized.background.light = light)), resolved.contrast !== 85 && (minimized.contrast = resolved.contrast), minimized.accent === DEFAULT_ACCENT && Object.keys(minimized).length === 1 ? null : minimized;
|
|
74
38
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
function sameColors(a, b) {
|
|
86
|
-
return THEMER_FIELDS.every(({ key }) => (a[key]?.toLowerCase() ?? void 0) === (b[key]?.toLowerCase() ?? void 0));
|
|
39
|
+
/**
|
|
40
|
+
* Whether two sets of theme options generate the same theme, comparing their
|
|
41
|
+
* resolved forms so that derived and explicit values (and hex casing) don't
|
|
42
|
+
* matter.
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
function sameOptions(a, b) {
|
|
47
|
+
let left = resolveThemeOptions(a), right = resolveThemeOptions(b);
|
|
48
|
+
return left.accent === right.accent && left.text === right.text && left.background.dark === right.background.dark && left.background.light === right.background.light && left.contrast === right.contrast;
|
|
87
49
|
}
|
|
88
|
-
/**
|
|
89
|
-
|
|
90
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Serializes theme options into the `buildTheme` call to paste into
|
|
52
|
+
* `sanity.config.ts`, keeping only what differs from the derived defaults.
|
|
53
|
+
*
|
|
54
|
+
* Options that boil down to the stock Studio theme need nothing from this
|
|
55
|
+
* package — so they serialize to a bare `buildTheme()` from `@sanity/ui/theme`
|
|
56
|
+
* instead.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
function createThemeSnippet(options) {
|
|
61
|
+
let minimized = minimizeOptions(options);
|
|
62
|
+
if (minimized === null) return "import {buildTheme} from '@sanity/ui/theme'\n\nexport const theme = buildTheme()\n";
|
|
63
|
+
let entries = [` accent: '${minimized.accent}',`];
|
|
64
|
+
if (minimized.text !== void 0 && entries.push(` text: '${minimized.text}',`), minimized.background) {
|
|
65
|
+
let parts = [];
|
|
66
|
+
minimized.background.dark !== void 0 && parts.push(`dark: '${minimized.background.dark}'`), minimized.background.light !== void 0 && parts.push(`light: '${minimized.background.light}'`), entries.push(` background: {${parts.join(", ")}},`);
|
|
67
|
+
}
|
|
68
|
+
return minimized.contrast !== void 0 && entries.push(` contrast: ${minimized.contrast},`), `import {buildTheme} from '@sanity/themer'\n\nexport const theme = buildTheme({\n${entries.join("\n")}\n})\n`;
|
|
91
69
|
}
|
|
70
|
+
registerLanguage(typescript);
|
|
92
71
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
72
|
+
* `<input type="color">` paints the color into a shadow-DOM swatch that brings
|
|
73
|
+
* its own border and padding, which then sits inside ours as a second border.
|
|
74
|
+
* Stripping that chrome leaves the themed border as the only one.
|
|
75
|
+
*/
|
|
76
|
+
const Swatch = styled.input.withConfig({
|
|
77
|
+
displayName: "Swatch",
|
|
78
|
+
componentId: "sc-lj4grb-0"
|
|
79
|
+
})`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;}`, Range = styled.input.withConfig({
|
|
80
|
+
displayName: "Range",
|
|
81
|
+
componentId: "sc-lj4grb-1"
|
|
82
|
+
})`display:block;width:100%;margin:0;accent-color:var(--card-focus-ring-color);`;
|
|
83
|
+
/**
|
|
84
|
+
* The themer sidebar: presets, the accent/text/background pickers and the
|
|
85
|
+
* contrast slider that generate the previewed `buildTheme` theme, plus the
|
|
86
|
+
* `buildTheme` snippet to make it permanent.
|
|
96
87
|
*
|
|
97
88
|
* @internal
|
|
98
89
|
*/
|
|
99
90
|
function ThemerSidebar() {
|
|
100
|
-
let {
|
|
91
|
+
let $ = c(117), { baseOptions, options, setOptions, setOpen } = useThemer(), toast = useToast(), active = options ?? baseOptions, t0;
|
|
92
|
+
$[0] === active ? t0 = $[1] : (t0 = resolveThemeOptions(active), $[0] = active, $[1] = t0);
|
|
93
|
+
let resolved = t0, t1;
|
|
94
|
+
$[2] === active ? t1 = $[3] : (t1 = buildPalette(active), $[2] = active, $[3] = t1);
|
|
95
|
+
let palette = t1, t2;
|
|
96
|
+
$[4] === active ? t2 = $[5] : (t2 = presets.find((preset) => sameOptions(preset.options, active))?.slug ?? "", $[4] = active, $[5] = t2);
|
|
97
|
+
let activePresetSlug = t2, t3;
|
|
98
|
+
$[6] === active ? t3 = $[7] : (t3 = createThemeSnippet(active), $[6] = active, $[7] = t3);
|
|
99
|
+
let snippet = t3, t4;
|
|
100
|
+
$[8] !== active || $[9] !== setOptions ? (t4 = (changes) => {
|
|
101
|
+
setOptions({
|
|
102
|
+
...active,
|
|
103
|
+
...changes
|
|
104
|
+
});
|
|
105
|
+
}, $[8] = active, $[9] = setOptions, $[10] = t4) : t4 = $[10];
|
|
106
|
+
let patch = t4, t5;
|
|
107
|
+
$[11] !== active || $[12] !== setOptions ? (t5 = (changes_0) => {
|
|
108
|
+
setOptions({
|
|
109
|
+
...active,
|
|
110
|
+
background: {
|
|
111
|
+
...active.background,
|
|
112
|
+
...changes_0
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}, $[11] = active, $[12] = setOptions, $[13] = t5) : t5 = $[13];
|
|
116
|
+
let patchBackground = t5, t6;
|
|
117
|
+
$[14] !== active || $[15] !== setOptions ? (t6 = (field) => {
|
|
101
118
|
let next = { ...active };
|
|
102
|
-
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
delete next[field], setOptions(next);
|
|
120
|
+
}, $[14] = active, $[15] = setOptions, $[16] = t6) : t6 = $[16];
|
|
121
|
+
let clearField = t6, t7;
|
|
122
|
+
$[17] !== active || $[18] !== setOptions ? (t7 = (key) => {
|
|
123
|
+
let background = { ...active.background };
|
|
124
|
+
delete background[key];
|
|
125
|
+
let next_0 = { ...active };
|
|
126
|
+
background.dark === void 0 && background.light === void 0 ? delete next_0.background : next_0.background = background, setOptions(next_0);
|
|
127
|
+
}, $[17] = active, $[18] = setOptions, $[19] = t7) : t7 = $[19];
|
|
128
|
+
let clearBackground = t7, t8;
|
|
129
|
+
$[20] !== snippet || $[21] !== toast ? (t8 = async () => {
|
|
107
130
|
try {
|
|
108
131
|
await navigator.clipboard.writeText(snippet), toast.push({
|
|
109
132
|
status: "success",
|
|
@@ -115,149 +138,397 @@ function ThemerSidebar() {
|
|
|
115
138
|
title: "Could not copy the theme"
|
|
116
139
|
});
|
|
117
140
|
}
|
|
118
|
-
};
|
|
119
|
-
|
|
141
|
+
}, $[20] = snippet, $[21] = toast, $[22] = t8) : t8 = $[22];
|
|
142
|
+
let handleCopy = t8, t9;
|
|
143
|
+
$[23] === Symbol.for("react.memo_cache_sentinel") ? (t9 = /* @__PURE__ */ jsx(Box, {
|
|
144
|
+
flex: 1,
|
|
145
|
+
paddingLeft: 1,
|
|
146
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
147
|
+
size: 1,
|
|
148
|
+
weight: "semibold",
|
|
149
|
+
children: "Themer"
|
|
150
|
+
})
|
|
151
|
+
}), $[23] = t9) : t9 = $[23];
|
|
152
|
+
let t10;
|
|
153
|
+
$[24] === setOpen ? t10 = $[25] : (t10 = /* @__PURE__ */ jsx(Card, {
|
|
154
|
+
borderBottom: !0,
|
|
155
|
+
padding: 3,
|
|
156
|
+
children: /* @__PURE__ */ jsxs(Flex, {
|
|
157
|
+
align: "center",
|
|
158
|
+
gap: 2,
|
|
159
|
+
children: [t9, /* @__PURE__ */ jsx(Button, {
|
|
160
|
+
icon: CloseIcon,
|
|
161
|
+
mode: "bleed",
|
|
162
|
+
onClick: () => setOpen(!1),
|
|
163
|
+
padding: 2,
|
|
164
|
+
title: "Close themer"
|
|
165
|
+
})]
|
|
166
|
+
})
|
|
167
|
+
}), $[24] = setOpen, $[25] = t10);
|
|
168
|
+
let t11;
|
|
169
|
+
$[26] === Symbol.for("react.memo_cache_sentinel") ? (t11 = /* @__PURE__ */ jsx(Text, {
|
|
170
|
+
size: 1,
|
|
171
|
+
weight: "medium",
|
|
172
|
+
children: "Presets"
|
|
173
|
+
}), $[26] = t11) : t11 = $[26];
|
|
174
|
+
let t12;
|
|
175
|
+
$[27] !== activePresetSlug || $[28] !== setOptions ? (t12 = presets.map((preset_0) => /* @__PURE__ */ jsx(PresetButton, {
|
|
176
|
+
active: preset_0.slug === activePresetSlug,
|
|
177
|
+
onClick: () => setOptions(preset_0.options),
|
|
178
|
+
preset: preset_0
|
|
179
|
+
}, preset_0.slug)), $[27] = activePresetSlug, $[28] = setOptions, $[29] = t12) : t12 = $[29];
|
|
180
|
+
let t13;
|
|
181
|
+
$[30] === t12 ? t13 = $[31] : (t13 = /* @__PURE__ */ jsxs(Stack, {
|
|
182
|
+
gap: 3,
|
|
183
|
+
children: [t11, /* @__PURE__ */ jsx(Grid, {
|
|
184
|
+
gap: 2,
|
|
185
|
+
gridTemplateColumns: 2,
|
|
186
|
+
children: t12
|
|
187
|
+
})]
|
|
188
|
+
}), $[30] = t12, $[31] = t13);
|
|
189
|
+
let t14;
|
|
190
|
+
$[32] === Symbol.for("react.memo_cache_sentinel") ? (t14 = /* @__PURE__ */ jsx(Text, {
|
|
191
|
+
size: 1,
|
|
192
|
+
weight: "medium",
|
|
193
|
+
children: "Colors"
|
|
194
|
+
}), $[32] = t14) : t14 = $[32];
|
|
195
|
+
let t15;
|
|
196
|
+
$[33] === patch ? t15 = $[34] : (t15 = (accent) => patch({ accent }), $[33] = patch, $[34] = t15);
|
|
197
|
+
let t16;
|
|
198
|
+
$[35] !== palette.blue || $[36] !== resolved.accent || $[37] !== t15 ? (t16 = /* @__PURE__ */ jsx(ColorRow, {
|
|
199
|
+
onChange: t15,
|
|
200
|
+
tints: palette.blue,
|
|
201
|
+
title: "Accent",
|
|
202
|
+
value: resolved.accent
|
|
203
|
+
}), $[35] = palette.blue, $[36] = resolved.accent, $[37] = t15, $[38] = t16) : t16 = $[38];
|
|
204
|
+
let t17 = active.text === void 0, t18;
|
|
205
|
+
$[39] === patch ? t18 = $[40] : (t18 = (text) => patch({ text }), $[39] = patch, $[40] = t18);
|
|
206
|
+
let t19;
|
|
207
|
+
$[41] === clearField ? t19 = $[42] : (t19 = () => clearField("text"), $[41] = clearField, $[42] = t19);
|
|
208
|
+
let t20;
|
|
209
|
+
$[43] !== palette.gray || $[44] !== resolved.text || $[45] !== t17 || $[46] !== t18 || $[47] !== t19 ? (t20 = /* @__PURE__ */ jsx(ColorRow, {
|
|
210
|
+
auto: t17,
|
|
211
|
+
onChange: t18,
|
|
212
|
+
onClear: t19,
|
|
213
|
+
tints: palette.gray,
|
|
214
|
+
title: "Text",
|
|
215
|
+
value: resolved.text
|
|
216
|
+
}), $[43] = palette.gray, $[44] = resolved.text, $[45] = t17, $[46] = t18, $[47] = t19, $[48] = t20) : t20 = $[48];
|
|
217
|
+
let t21 = active.background?.dark === void 0, t22;
|
|
218
|
+
$[49] === patchBackground ? t22 = $[50] : (t22 = (dark) => patchBackground({ dark }), $[49] = patchBackground, $[50] = t22);
|
|
219
|
+
let t23;
|
|
220
|
+
$[51] === clearBackground ? t23 = $[52] : (t23 = () => clearBackground("dark"), $[51] = clearBackground, $[52] = t23);
|
|
221
|
+
let t24;
|
|
222
|
+
$[53] !== palette.black || $[54] !== resolved.background.dark || $[55] !== t21 || $[56] !== t22 || $[57] !== t23 ? (t24 = /* @__PURE__ */ jsx(ColorRow, {
|
|
223
|
+
adjusted: palette.black,
|
|
224
|
+
auto: t21,
|
|
225
|
+
onChange: t22,
|
|
226
|
+
onClear: t23,
|
|
227
|
+
title: "Background · dark",
|
|
228
|
+
value: resolved.background.dark
|
|
229
|
+
}), $[53] = palette.black, $[54] = resolved.background.dark, $[55] = t21, $[56] = t22, $[57] = t23, $[58] = t24) : t24 = $[58];
|
|
230
|
+
let t25 = active.background?.light === void 0, t26;
|
|
231
|
+
$[59] === patchBackground ? t26 = $[60] : (t26 = (light) => patchBackground({ light }), $[59] = patchBackground, $[60] = t26);
|
|
232
|
+
let t27;
|
|
233
|
+
$[61] === clearBackground ? t27 = $[62] : (t27 = () => clearBackground("light"), $[61] = clearBackground, $[62] = t27);
|
|
234
|
+
let t28;
|
|
235
|
+
$[63] !== palette.white || $[64] !== resolved.background.light || $[65] !== t25 || $[66] !== t26 || $[67] !== t27 ? (t28 = /* @__PURE__ */ jsx(ColorRow, {
|
|
236
|
+
adjusted: palette.white,
|
|
237
|
+
auto: t25,
|
|
238
|
+
onChange: t26,
|
|
239
|
+
onClear: t27,
|
|
240
|
+
title: "Background · light",
|
|
241
|
+
value: resolved.background.light
|
|
242
|
+
}), $[63] = palette.white, $[64] = resolved.background.light, $[65] = t25, $[66] = t26, $[67] = t27, $[68] = t28) : t28 = $[68];
|
|
243
|
+
let t29;
|
|
244
|
+
$[69] !== t16 || $[70] !== t20 || $[71] !== t24 || $[72] !== t28 ? (t29 = /* @__PURE__ */ jsxs(Stack, {
|
|
245
|
+
gap: 3,
|
|
246
|
+
children: [t14, /* @__PURE__ */ jsxs(Stack, {
|
|
247
|
+
gap: 4,
|
|
248
|
+
children: [
|
|
249
|
+
t16,
|
|
250
|
+
t20,
|
|
251
|
+
t24,
|
|
252
|
+
t28
|
|
253
|
+
]
|
|
254
|
+
})]
|
|
255
|
+
}), $[69] = t16, $[70] = t20, $[71] = t24, $[72] = t28, $[73] = t29) : t29 = $[73];
|
|
256
|
+
let t30;
|
|
257
|
+
$[74] === Symbol.for("react.memo_cache_sentinel") ? (t30 = /* @__PURE__ */ jsx(Text, {
|
|
258
|
+
size: 1,
|
|
259
|
+
weight: "medium",
|
|
260
|
+
children: "Contrast"
|
|
261
|
+
}), $[74] = t30) : t30 = $[74];
|
|
262
|
+
let t31 = active.contrast === void 0 ? " · auto" : "", t32;
|
|
263
|
+
$[75] !== resolved.contrast || $[76] !== t31 ? (t32 = /* @__PURE__ */ jsxs(Stack, {
|
|
264
|
+
flex: 1,
|
|
265
|
+
gap: 2,
|
|
266
|
+
children: [t30, /* @__PURE__ */ jsxs(Text, {
|
|
267
|
+
muted: !0,
|
|
268
|
+
size: 0,
|
|
269
|
+
children: [resolved.contrast, t31]
|
|
270
|
+
})]
|
|
271
|
+
}), $[75] = resolved.contrast, $[76] = t31, $[77] = t32) : t32 = $[77];
|
|
272
|
+
let t33;
|
|
273
|
+
$[78] !== active.contrast || $[79] !== clearField ? (t33 = active.contrast !== void 0 && /* @__PURE__ */ jsx(Button, {
|
|
274
|
+
icon: ResetIcon,
|
|
275
|
+
mode: "bleed",
|
|
276
|
+
onClick: () => clearField("contrast"),
|
|
277
|
+
padding: 2,
|
|
278
|
+
title: "Reset to auto"
|
|
279
|
+
}), $[78] = active.contrast, $[79] = clearField, $[80] = t33) : t33 = $[80];
|
|
280
|
+
let t34;
|
|
281
|
+
$[81] !== t32 || $[82] !== t33 ? (t34 = /* @__PURE__ */ jsxs(Flex, {
|
|
282
|
+
align: "center",
|
|
283
|
+
gap: 2,
|
|
284
|
+
children: [t32, t33]
|
|
285
|
+
}), $[81] = t32, $[82] = t33, $[83] = t34) : t34 = $[83];
|
|
286
|
+
let t35;
|
|
287
|
+
$[84] === patch ? t35 = $[85] : (t35 = (event) => patch({ contrast: Number(event.currentTarget.value) }), $[84] = patch, $[85] = t35);
|
|
288
|
+
let t36;
|
|
289
|
+
$[86] !== resolved.contrast || $[87] !== t35 ? (t36 = /* @__PURE__ */ jsx(Range, {
|
|
290
|
+
"aria-label": "Contrast",
|
|
291
|
+
max: 100,
|
|
292
|
+
min: 15,
|
|
293
|
+
onChange: t35,
|
|
294
|
+
step: 1,
|
|
295
|
+
type: "range",
|
|
296
|
+
value: resolved.contrast
|
|
297
|
+
}), $[86] = resolved.contrast, $[87] = t35, $[88] = t36) : t36 = $[88];
|
|
298
|
+
let t37;
|
|
299
|
+
$[89] === Symbol.for("react.memo_cache_sentinel") ? (t37 = /* @__PURE__ */ jsx(Text, {
|
|
300
|
+
muted: !0,
|
|
301
|
+
size: 0,
|
|
302
|
+
children: "100 keeps text and borders neutral — lower values blend in the accent"
|
|
303
|
+
}), $[89] = t37) : t37 = $[89];
|
|
304
|
+
let t38;
|
|
305
|
+
$[90] !== t34 || $[91] !== t36 ? (t38 = /* @__PURE__ */ jsxs(Stack, {
|
|
306
|
+
gap: 3,
|
|
307
|
+
children: [
|
|
308
|
+
t34,
|
|
309
|
+
t36,
|
|
310
|
+
t37
|
|
311
|
+
]
|
|
312
|
+
}), $[90] = t34, $[91] = t36, $[92] = t38) : t38 = $[92];
|
|
313
|
+
let t39;
|
|
314
|
+
$[93] === Symbol.for("react.memo_cache_sentinel") ? (t39 = /* @__PURE__ */ jsx(Text, {
|
|
315
|
+
size: 1,
|
|
316
|
+
weight: "medium",
|
|
317
|
+
children: "Add to your config"
|
|
318
|
+
}), $[93] = t39) : t39 = $[93];
|
|
319
|
+
let t40;
|
|
320
|
+
$[94] === snippet ? t40 = $[95] : (t40 = /* @__PURE__ */ jsx(Card, {
|
|
321
|
+
border: !0,
|
|
322
|
+
overflow: "auto",
|
|
323
|
+
padding: 2,
|
|
324
|
+
radius: 2,
|
|
325
|
+
tone: "transparent",
|
|
326
|
+
children: /* @__PURE__ */ jsx(Code, {
|
|
327
|
+
language: "ts",
|
|
328
|
+
size: 0,
|
|
329
|
+
children: snippet
|
|
330
|
+
})
|
|
331
|
+
}), $[94] = snippet, $[95] = t40);
|
|
332
|
+
let t41;
|
|
333
|
+
$[96] === handleCopy ? t41 = $[97] : (t41 = /* @__PURE__ */ jsx(Button, {
|
|
334
|
+
icon: ClipboardIcon,
|
|
335
|
+
mode: "ghost",
|
|
336
|
+
onClick: () => void handleCopy(),
|
|
337
|
+
text: "Copy"
|
|
338
|
+
}), $[96] = handleCopy, $[97] = t41);
|
|
339
|
+
let t42 = options === null, t43;
|
|
340
|
+
$[98] === setOptions ? t43 = $[99] : (t43 = () => setOptions(null), $[98] = setOptions, $[99] = t43);
|
|
341
|
+
let t44;
|
|
342
|
+
$[100] !== t42 || $[101] !== t43 ? (t44 = /* @__PURE__ */ jsx(Button, {
|
|
343
|
+
disabled: t42,
|
|
344
|
+
icon: ResetIcon,
|
|
345
|
+
mode: "ghost",
|
|
346
|
+
onClick: t43,
|
|
347
|
+
text: "Reset",
|
|
348
|
+
tone: "critical"
|
|
349
|
+
}), $[100] = t42, $[101] = t43, $[102] = t44) : t44 = $[102];
|
|
350
|
+
let t45;
|
|
351
|
+
$[103] !== t41 || $[104] !== t44 ? (t45 = /* @__PURE__ */ jsxs(Flex, {
|
|
352
|
+
gap: 2,
|
|
353
|
+
children: [t41, t44]
|
|
354
|
+
}), $[103] = t41, $[104] = t44, $[105] = t45) : t45 = $[105];
|
|
355
|
+
let t46;
|
|
356
|
+
$[106] !== t40 || $[107] !== t45 ? (t46 = /* @__PURE__ */ jsxs(Stack, {
|
|
357
|
+
gap: 3,
|
|
358
|
+
children: [
|
|
359
|
+
t39,
|
|
360
|
+
t40,
|
|
361
|
+
t45
|
|
362
|
+
]
|
|
363
|
+
}), $[106] = t40, $[107] = t45, $[108] = t46) : t46 = $[108];
|
|
364
|
+
let t47;
|
|
365
|
+
$[109] !== t13 || $[110] !== t29 || $[111] !== t38 || $[112] !== t46 ? (t47 = /* @__PURE__ */ jsx(Box, {
|
|
366
|
+
flex: 1,
|
|
367
|
+
overflow: "auto",
|
|
368
|
+
padding: 3,
|
|
369
|
+
children: /* @__PURE__ */ jsxs(Stack, {
|
|
370
|
+
gap: 4,
|
|
371
|
+
children: [
|
|
372
|
+
t13,
|
|
373
|
+
t29,
|
|
374
|
+
t38,
|
|
375
|
+
t46
|
|
376
|
+
]
|
|
377
|
+
})
|
|
378
|
+
}), $[109] = t13, $[110] = t29, $[111] = t38, $[112] = t46, $[113] = t47) : t47 = $[113];
|
|
379
|
+
let t48;
|
|
380
|
+
return $[114] !== t10 || $[115] !== t47 ? (t48 = /* @__PURE__ */ jsx(Card, {
|
|
120
381
|
height: "fill",
|
|
121
382
|
children: /* @__PURE__ */ jsxs(Flex, {
|
|
122
383
|
direction: "column",
|
|
123
384
|
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
|
-
})]
|
|
385
|
+
children: [t10, t47]
|
|
220
386
|
})
|
|
221
|
-
});
|
|
387
|
+
}), $[114] = t10, $[115] = t47, $[116] = t48) : t48 = $[116], t48;
|
|
222
388
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
389
|
+
const paletteStyle = {
|
|
390
|
+
display: "flex",
|
|
391
|
+
gap: 1,
|
|
392
|
+
background: "var(--card-border-color)",
|
|
393
|
+
height: 21,
|
|
394
|
+
borderRadius: 3,
|
|
395
|
+
overflow: "hidden",
|
|
396
|
+
boxShadow: "inset 0 0 0 1px var(--card-border-color)"
|
|
397
|
+
};
|
|
398
|
+
/** A little palette of the colors a preset would apply */
|
|
399
|
+
function PresetButton(props) {
|
|
400
|
+
let $ = c(27), { active, onClick, preset } = props, t0;
|
|
401
|
+
$[0] === preset.options ? t0 = $[1] : (t0 = resolveThemeOptions(preset.options), $[0] = preset.options, $[1] = t0);
|
|
402
|
+
let resolved = t0, t1;
|
|
403
|
+
$[2] === resolved.accent ? t1 = $[3] : (t1 = ["accent", resolved.accent], $[2] = resolved.accent, $[3] = t1);
|
|
404
|
+
let t2;
|
|
405
|
+
$[4] === resolved.text ? t2 = $[5] : (t2 = ["text", resolved.text], $[4] = resolved.text, $[5] = t2);
|
|
406
|
+
let t3;
|
|
407
|
+
$[6] === resolved.background.dark ? t3 = $[7] : (t3 = ["dark", resolved.background.dark], $[6] = resolved.background.dark, $[7] = t3);
|
|
408
|
+
let t4;
|
|
409
|
+
$[8] === resolved.background.light ? t4 = $[9] : (t4 = ["light", resolved.background.light], $[8] = resolved.background.light, $[9] = t4);
|
|
410
|
+
let t5;
|
|
411
|
+
$[10] !== t1 || $[11] !== t2 || $[12] !== t3 || $[13] !== t4 ? (t5 = [
|
|
412
|
+
t1,
|
|
413
|
+
t2,
|
|
414
|
+
t3,
|
|
415
|
+
t4
|
|
416
|
+
], $[10] = t1, $[11] = t2, $[12] = t3, $[13] = t4, $[14] = t5) : t5 = $[14];
|
|
417
|
+
let swatches = t5, t6;
|
|
418
|
+
$[15] === swatches ? t6 = $[16] : (t6 = /* @__PURE__ */ jsx("span", {
|
|
419
|
+
style: paletteStyle,
|
|
420
|
+
children: swatches.map(_temp$1)
|
|
421
|
+
}), $[15] = swatches, $[16] = t6);
|
|
422
|
+
let t7;
|
|
423
|
+
$[17] === preset.title ? t7 = $[18] : (t7 = /* @__PURE__ */ jsx(Text, {
|
|
424
|
+
align: "left",
|
|
425
|
+
size: 1,
|
|
426
|
+
textOverflow: "ellipsis",
|
|
427
|
+
children: preset.title
|
|
428
|
+
}), $[17] = preset.title, $[18] = t7);
|
|
429
|
+
let t8;
|
|
430
|
+
$[19] !== t6 || $[20] !== t7 ? (t8 = /* @__PURE__ */ jsxs(Stack, {
|
|
431
|
+
as: "span",
|
|
432
|
+
gap: 2,
|
|
433
|
+
children: [t6, t7]
|
|
434
|
+
}), $[19] = t6, $[20] = t7, $[21] = t8) : t8 = $[21];
|
|
435
|
+
let t9;
|
|
436
|
+
return $[22] !== active || $[23] !== onClick || $[24] !== preset.title || $[25] !== t8 ? (t9 = /* @__PURE__ */ jsx(Button, {
|
|
437
|
+
mode: "ghost",
|
|
438
|
+
onClick,
|
|
439
|
+
padding: 2,
|
|
440
|
+
selected: active,
|
|
441
|
+
title: preset.title,
|
|
442
|
+
children: t8
|
|
443
|
+
}), $[22] = active, $[23] = onClick, $[24] = preset.title, $[25] = t8, $[26] = t9) : t9 = $[26], t9;
|
|
444
|
+
}
|
|
445
|
+
function _temp$1(t0) {
|
|
446
|
+
let [key, background] = t0;
|
|
447
|
+
return /* @__PURE__ */ jsx("span", { style: {
|
|
448
|
+
flex: 1,
|
|
449
|
+
background
|
|
450
|
+
} }, key);
|
|
451
|
+
}
|
|
452
|
+
const rampStyle = {
|
|
453
|
+
...paletteStyle,
|
|
454
|
+
height: 13,
|
|
455
|
+
borderRadius: 2
|
|
456
|
+
};
|
|
457
|
+
/**
|
|
458
|
+
* One color of the theme: a swatch with its value, an optional reset-to-auto
|
|
459
|
+
* button, and the generated 50–950 tint ramp for the scales it anchors.
|
|
460
|
+
*/
|
|
461
|
+
function ColorRow(props) {
|
|
462
|
+
let $ = c(27), { adjusted, auto, onChange, onClear, tints, title, value } = props, t0;
|
|
463
|
+
$[0] === title ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(Text, {
|
|
464
|
+
size: 1,
|
|
465
|
+
children: title
|
|
466
|
+
}), $[0] = title, $[1] = t0);
|
|
467
|
+
let t1 = adjusted !== void 0 && adjusted !== value ? ` → ${adjusted}` : "", t2 = auto ? " · auto" : "", t3;
|
|
468
|
+
$[2] !== t1 || $[3] !== t2 || $[4] !== value ? (t3 = /* @__PURE__ */ jsxs(Text, {
|
|
469
|
+
muted: !0,
|
|
470
|
+
size: 0,
|
|
471
|
+
textOverflow: "ellipsis",
|
|
472
|
+
children: [
|
|
473
|
+
value,
|
|
474
|
+
t1,
|
|
475
|
+
t2
|
|
476
|
+
]
|
|
477
|
+
}), $[2] = t1, $[3] = t2, $[4] = value, $[5] = t3) : t3 = $[5];
|
|
478
|
+
let t4;
|
|
479
|
+
$[6] !== t0 || $[7] !== t3 ? (t4 = /* @__PURE__ */ jsxs(Stack, {
|
|
480
|
+
flex: 1,
|
|
481
|
+
gap: 2,
|
|
482
|
+
children: [t0, t3]
|
|
483
|
+
}), $[6] = t0, $[7] = t3, $[8] = t4) : t4 = $[8];
|
|
484
|
+
let t5;
|
|
485
|
+
$[9] !== auto || $[10] !== onClear ? (t5 = onClear && !auto && /* @__PURE__ */ jsx(Button, {
|
|
486
|
+
icon: ResetIcon,
|
|
487
|
+
mode: "bleed",
|
|
488
|
+
onClick: onClear,
|
|
489
|
+
padding: 2,
|
|
490
|
+
title: "Reset to auto"
|
|
491
|
+
}), $[9] = auto, $[10] = onClear, $[11] = t5) : t5 = $[11];
|
|
492
|
+
let t6 = `${title} color`, t7;
|
|
493
|
+
$[12] === onChange ? t7 = $[13] : (t7 = (event) => onChange(event.currentTarget.value), $[12] = onChange, $[13] = t7);
|
|
494
|
+
let t8;
|
|
495
|
+
$[14] !== t6 || $[15] !== t7 || $[16] !== value ? (t8 = /* @__PURE__ */ jsx(Swatch, {
|
|
496
|
+
"aria-label": t6,
|
|
497
|
+
onChange: t7,
|
|
498
|
+
type: "color",
|
|
499
|
+
value
|
|
500
|
+
}), $[14] = t6, $[15] = t7, $[16] = value, $[17] = t8) : t8 = $[17];
|
|
501
|
+
let t9;
|
|
502
|
+
$[18] !== t4 || $[19] !== t5 || $[20] !== t8 ? (t9 = /* @__PURE__ */ jsxs(Flex, {
|
|
226
503
|
align: "center",
|
|
227
|
-
gap:
|
|
504
|
+
gap: 2,
|
|
228
505
|
children: [
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
233
|
-
size: 1,
|
|
234
|
-
weight: "medium",
|
|
235
|
-
children: field.title
|
|
236
|
-
}), /* @__PURE__ */ jsx(Text, {
|
|
237
|
-
muted: !0,
|
|
238
|
-
size: 0,
|
|
239
|
-
children: value ?? field.description
|
|
240
|
-
})]
|
|
241
|
-
}),
|
|
242
|
-
value !== void 0 && /* @__PURE__ */ jsx(Button, {
|
|
243
|
-
icon: CloseIcon,
|
|
244
|
-
mode: "bleed",
|
|
245
|
-
onClick: () => onChange(field.key, void 0),
|
|
246
|
-
padding: 2,
|
|
247
|
-
title: `Reset ${field.title}`
|
|
248
|
-
}),
|
|
249
|
-
/* @__PURE__ */ jsx("input", {
|
|
250
|
-
"aria-label": `${field.title} color`,
|
|
251
|
-
onChange: (event) => onChange(field.key, event.currentTarget.value),
|
|
252
|
-
style: swatchStyle,
|
|
253
|
-
type: "color",
|
|
254
|
-
value: expandHex(value ?? field.defaultValue)
|
|
255
|
-
})
|
|
506
|
+
t4,
|
|
507
|
+
t5,
|
|
508
|
+
t8
|
|
256
509
|
]
|
|
257
|
-
});
|
|
510
|
+
}), $[18] = t4, $[19] = t5, $[20] = t8, $[21] = t9) : t9 = $[21];
|
|
511
|
+
let t10;
|
|
512
|
+
$[22] === tints ? t10 = $[23] : (t10 = tints && /* @__PURE__ */ jsx("span", {
|
|
513
|
+
style: rampStyle,
|
|
514
|
+
children: COLOR_TINTS.map((tint) => /* @__PURE__ */ jsx("span", { style: {
|
|
515
|
+
flex: 1,
|
|
516
|
+
background: tints[tint]
|
|
517
|
+
} }, tint))
|
|
518
|
+
}), $[22] = tints, $[23] = t10);
|
|
519
|
+
let t11;
|
|
520
|
+
return $[24] !== t10 || $[25] !== t9 ? (t11 = /* @__PURE__ */ jsxs(Stack, {
|
|
521
|
+
gap: 2,
|
|
522
|
+
children: [t9, t10]
|
|
523
|
+
}), $[24] = t10, $[25] = t9, $[26] = t11) : t11 = $[26], t11;
|
|
258
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Narrow enough to leave the studio preview as much room as possible: it fits
|
|
527
|
+
* the widest picker label next to its swatch, and the code snippet scrolls
|
|
528
|
+
* horizontally rather than widening the sidebar.
|
|
529
|
+
*/
|
|
259
530
|
const sidebarStyle = {
|
|
260
|
-
width:
|
|
531
|
+
width: 240,
|
|
261
532
|
flex: "none",
|
|
262
533
|
borderLeft: "1px solid var(--card-border-color)",
|
|
263
534
|
boxSizing: "border-box",
|
|
@@ -270,52 +541,67 @@ const sidebarStyle = {
|
|
|
270
541
|
* @internal
|
|
271
542
|
*/
|
|
272
543
|
function ThemerActiveToolLayout(props) {
|
|
273
|
-
let { open } = useThemer();
|
|
274
|
-
|
|
544
|
+
let $ = c(9), { open } = useThemer(), t0;
|
|
545
|
+
$[0] === props ? t0 = $[1] : (t0 = props.renderDefault(props), $[0] = props, $[1] = t0);
|
|
546
|
+
let t1;
|
|
547
|
+
$[2] === t0 ? t1 = $[3] : (t1 = /* @__PURE__ */ jsx(Box, {
|
|
548
|
+
flex: 1,
|
|
549
|
+
height: "fill",
|
|
550
|
+
overflow: "auto",
|
|
551
|
+
children: t0
|
|
552
|
+
}), $[2] = t0, $[3] = t1);
|
|
553
|
+
let t2;
|
|
554
|
+
$[4] === open ? t2 = $[5] : (t2 = open && /* @__PURE__ */ jsx(Layer, {
|
|
555
|
+
height: "fill",
|
|
556
|
+
style: sidebarStyle,
|
|
557
|
+
zOffset: 100,
|
|
558
|
+
children: /* @__PURE__ */ jsx(ThemerSidebar, {})
|
|
559
|
+
}), $[4] = open, $[5] = t2);
|
|
560
|
+
let t3;
|
|
561
|
+
return $[6] !== t1 || $[7] !== t2 ? (t3 = /* @__PURE__ */ jsxs(Flex, {
|
|
275
562
|
height: "fill",
|
|
276
563
|
sizing: "border",
|
|
277
|
-
children: [
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
});
|
|
564
|
+
children: [t1, t2]
|
|
565
|
+
}), $[6] = t1, $[7] = t2, $[8] = t3) : t3 = $[8], t3;
|
|
566
|
+
}
|
|
567
|
+
const STORAGE_KEY = "sanityStudio:themer:options";
|
|
568
|
+
function sanitizeColor(value) {
|
|
569
|
+
return typeof value == "string" && isColor(value) ? value.toLowerCase() : null;
|
|
570
|
+
}
|
|
571
|
+
function sanitizeOptions(value) {
|
|
572
|
+
if (!value || typeof value != "object") return null;
|
|
573
|
+
let accent = sanitizeColor(Reflect.get(value, "accent"));
|
|
574
|
+
if (!accent) return null;
|
|
575
|
+
let options = { accent }, text = sanitizeColor(Reflect.get(value, "text"));
|
|
576
|
+
text && (options.text = text);
|
|
577
|
+
let background = Reflect.get(value, "background");
|
|
578
|
+
if (background && typeof background == "object") {
|
|
579
|
+
let dark = sanitizeColor(Reflect.get(background, "dark")), light = sanitizeColor(Reflect.get(background, "light"));
|
|
580
|
+
(dark || light) && (options.background = {}, dark && (options.background.dark = dark), light && (options.background.light = light));
|
|
581
|
+
}
|
|
582
|
+
let contrast = Reflect.get(value, "contrast");
|
|
583
|
+
return typeof contrast == "number" && Number.isFinite(contrast) && (options.contrast = Math.min(100, Math.max(15, contrast))), options;
|
|
289
584
|
}
|
|
290
|
-
const STORAGE_KEY = "sanityStudio:themer:colors";
|
|
291
585
|
/**
|
|
292
|
-
* Restores draft
|
|
293
|
-
* reloads.
|
|
586
|
+
* Restores draft theme options from localStorage, so theme drafts survive
|
|
587
|
+
* studio reloads.
|
|
294
588
|
*
|
|
295
589
|
* @internal
|
|
296
590
|
*/
|
|
297
|
-
function
|
|
591
|
+
function readStoredOptions() {
|
|
298
592
|
try {
|
|
299
593
|
if (typeof localStorage > "u") return null;
|
|
300
594
|
let raw = localStorage.getItem(STORAGE_KEY);
|
|
301
|
-
|
|
302
|
-
let parsed = JSON.parse(raw);
|
|
303
|
-
if (!parsed || typeof parsed != "object") return null;
|
|
304
|
-
let colors = {};
|
|
305
|
-
for (let { key } of THEMER_FIELDS) {
|
|
306
|
-
let value = Reflect.get(parsed, key);
|
|
307
|
-
typeof value == "string" && isColor(value) && (colors[key] = value);
|
|
308
|
-
}
|
|
309
|
-
return colors;
|
|
595
|
+
return raw ? sanitizeOptions(JSON.parse(raw)) : null;
|
|
310
596
|
} catch {
|
|
311
597
|
return null;
|
|
312
598
|
}
|
|
313
599
|
}
|
|
314
600
|
/** @internal */
|
|
315
|
-
function
|
|
601
|
+
function writeStoredOptions(options) {
|
|
316
602
|
try {
|
|
317
603
|
if (typeof localStorage > "u") return;
|
|
318
|
-
|
|
604
|
+
options === null ? localStorage.removeItem(STORAGE_KEY) : localStorage.setItem(STORAGE_KEY, JSON.stringify(options));
|
|
319
605
|
} catch {}
|
|
320
606
|
}
|
|
321
607
|
/**
|
|
@@ -330,56 +616,92 @@ function writeStoredColors(colors) {
|
|
|
330
616
|
* @internal
|
|
331
617
|
*/
|
|
332
618
|
function ThemerLayout(props) {
|
|
333
|
-
let {
|
|
334
|
-
|
|
335
|
-
let
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
619
|
+
let $ = c(13), { baseOptions, ...layoutProps } = props, [open, setOpen] = useState(!1), [options, setOptions] = useState(readStoredOptions), t0, t1;
|
|
620
|
+
$[0] === options ? (t0 = $[1], t1 = $[2]) : (t0 = () => writeStoredOptions(options), t1 = [options], $[0] = options, $[1] = t0, $[2] = t1), useEffect(t0, t1);
|
|
621
|
+
let t2;
|
|
622
|
+
$[3] === options ? t2 = $[4] : (t2 = options === null ? null : buildTheme(options), $[3] = options, $[4] = t2);
|
|
623
|
+
let theme = t2, t3;
|
|
624
|
+
$[5] !== baseOptions || $[6] !== open || $[7] !== options ? (t3 = {
|
|
625
|
+
baseOptions,
|
|
626
|
+
options,
|
|
627
|
+
setOptions,
|
|
342
628
|
open,
|
|
343
629
|
setOpen
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return /* @__PURE__ */ jsx(
|
|
630
|
+
}, $[5] = baseOptions, $[6] = open, $[7] = options, $[8] = t3) : t3 = $[8];
|
|
631
|
+
let context = t3, t4 = ThemerContext, t5 = theme === null ? layoutProps.renderDefault(layoutProps) : /* @__PURE__ */ jsx(ThemeProvider, {
|
|
632
|
+
theme,
|
|
633
|
+
children: layoutProps.renderDefault(layoutProps)
|
|
634
|
+
}), t6;
|
|
635
|
+
return $[9] !== context || $[10] !== t4.Provider || $[11] !== t5 ? (t6 = /* @__PURE__ */ jsx(t4.Provider, {
|
|
350
636
|
value: context,
|
|
351
|
-
children:
|
|
352
|
-
|
|
353
|
-
|
|
637
|
+
children: t5
|
|
638
|
+
}), $[9] = context, $[10] = t4.Provider, $[11] = t5, $[12] = t6) : t6 = $[12], t6;
|
|
639
|
+
}
|
|
640
|
+
function ThemerNavbarButton() {
|
|
641
|
+
let $ = c(7), { open, setOpen } = useThemer(), t0;
|
|
642
|
+
$[0] === Symbol.for("react.memo_cache_sentinel") ? (t0 = /* @__PURE__ */ jsx(Text, {
|
|
643
|
+
size: 1,
|
|
644
|
+
children: "Themer"
|
|
645
|
+
}), $[0] = t0) : t0 = $[0];
|
|
646
|
+
let t1;
|
|
647
|
+
$[1] !== open || $[2] !== setOpen ? (t1 = () => setOpen(!open), $[1] = open, $[2] = setOpen, $[3] = t1) : t1 = $[3];
|
|
648
|
+
let t2;
|
|
649
|
+
return $[4] !== open || $[5] !== t1 ? (t2 = /* @__PURE__ */ jsx(Tooltip, {
|
|
650
|
+
content: t0,
|
|
651
|
+
portal: !0,
|
|
652
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
653
|
+
"aria-label": "Themer",
|
|
654
|
+
icon: ColorWheelIcon,
|
|
655
|
+
mode: "bleed",
|
|
656
|
+
onClick: t1,
|
|
657
|
+
padding: 2,
|
|
658
|
+
selected: open
|
|
354
659
|
})
|
|
355
|
-
});
|
|
660
|
+
}), $[4] = open, $[5] = t1, $[6] = t2) : t2 = $[6], t2;
|
|
356
661
|
}
|
|
357
662
|
/**
|
|
358
663
|
* Adds the toggle that opens and closes the themer sidebar to the Studio
|
|
359
|
-
* navbar
|
|
664
|
+
* navbar — an icon button with a tooltip in the top bar (like the Tasks
|
|
665
|
+
* toggle), and a regular titled action in the narrow-screen sidebar menu.
|
|
360
666
|
*
|
|
361
667
|
* @internal
|
|
362
668
|
*/
|
|
363
669
|
function ThemerNavbar(props) {
|
|
364
|
-
let { open, setOpen } = useThemer();
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
670
|
+
let $ = c(7), { open, setOpen } = useThemer(), t0;
|
|
671
|
+
if ($[0] !== open || $[1] !== props || $[2] !== setOpen) {
|
|
672
|
+
let t1;
|
|
673
|
+
$[4] !== open || $[5] !== setOpen ? (t1 = () => setOpen(!open), $[4] = open, $[5] = setOpen, $[6] = t1) : t1 = $[6], t0 = props.renderDefault({
|
|
674
|
+
...props,
|
|
675
|
+
__internal_actions: [
|
|
676
|
+
...props.__internal_actions ?? [],
|
|
677
|
+
{
|
|
678
|
+
location: "topbar",
|
|
679
|
+
name: "themer-topbar",
|
|
680
|
+
render: _temp
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
icon: ColorWheelIcon,
|
|
684
|
+
location: "sidebar",
|
|
685
|
+
name: "themer-sidebar",
|
|
686
|
+
onAction: t1,
|
|
687
|
+
selected: open,
|
|
688
|
+
title: "Themer"
|
|
689
|
+
}
|
|
690
|
+
]
|
|
691
|
+
}), $[0] = open, $[1] = props, $[2] = setOpen, $[3] = t0;
|
|
692
|
+
} else t0 = $[3];
|
|
693
|
+
return t0;
|
|
694
|
+
}
|
|
695
|
+
function _temp() {
|
|
696
|
+
return /* @__PURE__ */ jsx(ThemerNavbarButton, {});
|
|
376
697
|
}
|
|
377
698
|
/**
|
|
378
|
-
* A Studio plugin that adds a themer sidebar for
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* regular appearance menu — the
|
|
699
|
+
* A Studio plugin that adds a themer sidebar for `buildTheme` themes: a
|
|
700
|
+
* navbar toggle opens the sidebar next to the active tool, where presets, the
|
|
701
|
+
* accent/text/background pickers and the contrast slider preview a
|
|
702
|
+
* `buildTheme` theme live on the whole Studio while you browse around.
|
|
703
|
+
* Toggle between light and dark mode with the regular appearance menu — the
|
|
704
|
+
* preview follows it.
|
|
383
705
|
*
|
|
384
706
|
* ```ts
|
|
385
707
|
* import {themerTool} from '@sanity/themer/tool'
|
|
@@ -391,15 +713,19 @@ function ThemerNavbar(props) {
|
|
|
391
713
|
* })
|
|
392
714
|
* ```
|
|
393
715
|
*
|
|
394
|
-
*
|
|
716
|
+
* This is experimental and may change or be removed in any release without
|
|
717
|
+
* notice — use at your own risk.
|
|
718
|
+
*
|
|
719
|
+
* @alpha
|
|
395
720
|
*/
|
|
396
721
|
const themerTool = definePlugin((options) => {
|
|
397
|
-
let
|
|
722
|
+
let baseOptions = options?.config ?? { accent: DEFAULT_ACCENT };
|
|
398
723
|
function ThemerLayoutWithOptions(props) {
|
|
399
|
-
|
|
724
|
+
let $ = c(2), t0;
|
|
725
|
+
return $[0] === props ? t0 = $[1] : (t0 = /* @__PURE__ */ jsx(ThemerLayout, {
|
|
400
726
|
...props,
|
|
401
|
-
|
|
402
|
-
});
|
|
727
|
+
baseOptions
|
|
728
|
+
}), $[0] = props, $[1] = t0), t0;
|
|
403
729
|
}
|
|
404
730
|
return {
|
|
405
731
|
name: "@sanity/themer/tool",
|