@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.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","names":[],"sources":["../src/tool/context.ts","../src/tool/fields.ts","../src/tool/snippet.ts","../src/tool/ThemerSidebar.tsx","../src/tool/ThemerActiveToolLayout.tsx","../src/tool/storage.ts","../src/tool/ThemerLayout.tsx","../src/tool/ThemerNavbar.tsx","../src/tool/plugin.tsx"],"sourcesContent":["import {createContext, useContext} from 'react'\n\nimport {CreateThemeOptions} from '../types'\n\n/** @internal */\nexport interface ThemerContextValue {\n /** The colors the Studio's configured theme was generated from */\n baseColors: CreateThemeOptions\n /** The draft colors, or `null` when the configured theme is untouched */\n colors: CreateThemeOptions | null\n setColors: (colors: CreateThemeOptions | null) => void\n /** Whether the themer sidebar is open */\n open: boolean\n setOpen: (open: boolean) => void\n}\n\n/** @internal */\nexport const ThemerContext = createContext<ThemerContextValue | null>(null)\n\n/** @internal */\nexport function useThemer(): ThemerContextValue {\n const context = useContext(ThemerContext)\n\n if (!context) {\n throw new Error('useThemer must be used within the `themerTool` plugin')\n }\n\n return context\n}\n","import {color} from '@sanity/color'\n\nimport {CreateThemeOptions} from '../types'\n\n/** @internal */\nexport interface ThemerField {\n key: keyof CreateThemeOptions\n title: string\n description: string\n /** The color the picker shows while the field is unset (6-digit hex) */\n defaultValue: string\n}\n\n/** @internal */\nexport const THEMER_FIELDS: ThemerField[] = [\n {\n key: 'primary',\n title: 'Primary',\n description: 'Buttons, focus rings and links',\n defaultValue: color.blue[500].hex,\n },\n {\n key: 'gray',\n title: 'Gray',\n description: 'Neutral surfaces, borders and text',\n defaultValue: color.gray[500].hex,\n },\n {\n key: 'positive',\n title: 'Positive',\n description: 'Success accents',\n defaultValue: color.green[500].hex,\n },\n {\n key: 'caution',\n title: 'Caution',\n description: 'Warning accents',\n defaultValue: color.yellow[500].hex,\n },\n {\n key: 'critical',\n title: 'Critical',\n description: 'Errors and destructive actions',\n defaultValue: color.red[500].hex,\n },\n {\n key: 'lightest',\n title: 'Lightest',\n description: 'Light mode background',\n defaultValue: color.white.hex,\n },\n {\n key: 'darkest',\n title: 'Darkest',\n description: 'Dark mode background',\n defaultValue: color.black.hex,\n },\n]\n","import {CreateThemeOptions} from '../types'\nimport {THEMER_FIELDS} from './fields'\n\n/**\n * Serializes colors into the `createTheme` call to paste into\n * `sanity.config.ts`.\n *\n * @internal\n */\nexport function createThemeSnippet(colors: CreateThemeOptions): string {\n const entries = THEMER_FIELDS.filter(({key}) => colors[key]).map(\n ({key}) => ` ${key}: '${colors[key]}',`,\n )\n\n const call = entries.length === 0 ? 'createTheme()' : `createTheme({\\n${entries.join('\\n')}\\n})`\n\n return `import {createTheme} from '@sanity/themer'\\n\\nexport const theme = ${call}\\n`\n}\n","import {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {ResetIcon} from '@sanity/icons/Reset'\nimport {Box, Button, Card, Code, Flex, Select, Stack, Text, useToast} from '@sanity/ui'\n\nimport {presets} from '../presets'\nimport {CreateThemeOptions} from '../types'\nimport {useThemer} from './context'\nimport {THEMER_FIELDS, ThemerField} from './fields'\nimport {createThemeSnippet} from './snippet'\n\nconst swatchStyle: React.CSSProperties = {\n width: 33,\n height: 33,\n padding: 0,\n border: '1px solid var(--card-border-color)',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n flex: 'none',\n}\n\nfunction sameColors(a: CreateThemeOptions, b: CreateThemeOptions): boolean {\n return THEMER_FIELDS.every(\n ({key}) => (a[key]?.toLowerCase() ?? undefined) === (b[key]?.toLowerCase() ?? undefined),\n )\n}\n\n/** Expands `#abc` to `#aabbcc`, which is the only format `<input type=\"color\">` accepts */\nfunction expandHex(hex: string): string {\n if (hex.length === 4) {\n return `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`\n }\n\n return hex\n}\n\n/**\n * The themer sidebar: a preset picker and a handful of color pickers that\n * generate the previewed theme, plus the `createTheme` snippet to make it\n * permanent.\n *\n * @internal\n */\nexport function ThemerSidebar() {\n const {baseColors, colors, setColors, setOpen} = useThemer()\n const toast = useToast()\n\n const active = colors ?? baseColors\n const activePresetSlug = presets.find((preset) => sameColors(preset.colors, active))?.slug ?? ''\n const snippet = createThemeSnippet(active)\n\n const handleFieldChange = (key: keyof CreateThemeOptions, value: string | undefined) => {\n const next = {...active}\n\n if (value === undefined) {\n delete next[key]\n } else {\n next[key] = value\n }\n\n setColors(next)\n }\n\n const handlePresetChange = (slug: string) => {\n const preset = presets.find((candidate) => candidate.slug === slug)\n\n if (preset) {\n setColors({...preset.colors})\n }\n }\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(snippet)\n toast.push({status: 'success', title: 'Copied theme to the clipboard'})\n } catch {\n toast.push({status: 'error', title: 'Could not copy the theme'})\n }\n }\n\n return (\n <Card height=\"fill\">\n <Flex direction=\"column\" height=\"fill\">\n <Card borderBottom padding={3}>\n <Flex align=\"center\" gap={2}>\n <Box flex={1} paddingLeft={1}>\n <Text size={1} weight=\"semibold\">\n Themer\n </Text>\n </Box>\n <Button\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={() => setOpen(false)}\n padding={2}\n title=\"Close themer\"\n />\n </Flex>\n </Card>\n\n <Box flex={1} overflow=\"auto\" padding={4}>\n <Stack gap={5}>\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Preset\n </Text>\n <Select\n onChange={(event) => handlePresetChange(event.currentTarget.value)}\n value={activePresetSlug}\n >\n {activePresetSlug === '' && <option value=\"\">Custom</option>}\n {presets.map((preset) => (\n <option key={preset.slug} value={preset.slug}>\n {preset.title}\n </option>\n ))}\n </Select>\n </Stack>\n\n <Stack gap={4}>\n {THEMER_FIELDS.map((field) => (\n <ColorField\n field={field}\n key={field.key}\n onChange={handleFieldChange}\n value={active[field.key]}\n />\n ))}\n </Stack>\n\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Add to your config\n </Text>\n <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n <Code language=\"ts\" size={0}>\n {snippet}\n </Code>\n </Card>\n <Flex gap={2}>\n <Button\n icon={ClipboardIcon}\n mode=\"ghost\"\n onClick={() => void handleCopy()}\n text=\"Copy\"\n />\n <Button\n disabled={colors === null}\n icon={ResetIcon}\n mode=\"ghost\"\n onClick={() => setColors(null)}\n text=\"Reset\"\n tone=\"critical\"\n />\n </Flex>\n </Stack>\n </Stack>\n </Box>\n </Flex>\n </Card>\n )\n}\n\nfunction ColorField(props: {\n field: ThemerField\n value: string | undefined\n onChange: (key: keyof CreateThemeOptions, value: string | undefined) => void\n}) {\n const {field, value, onChange} = props\n\n return (\n <Flex align=\"center\" gap={3}>\n <Stack flex={1} gap={2}>\n <Text size={1} weight=\"medium\">\n {field.title}\n </Text>\n <Text muted size={0}>\n {value ?? field.description}\n </Text>\n </Stack>\n {value !== undefined && (\n <Button\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={() => onChange(field.key, undefined)}\n padding={2}\n title={`Reset ${field.title}`}\n />\n )}\n <input\n aria-label={`${field.title} color`}\n onChange={(event) => onChange(field.key, event.currentTarget.value)}\n style={swatchStyle}\n type=\"color\"\n value={expandHex(value ?? field.defaultValue)}\n />\n </Flex>\n )\n}\n","import {Box, Flex, Layer} from '@sanity/ui'\nimport {type ActiveToolLayoutProps} from 'sanity'\n\nimport {useThemer} from './context'\nimport {ThemerSidebar} from './ThemerSidebar'\n\nconst sidebarStyle: React.CSSProperties = {\n width: 360,\n flex: 'none',\n borderLeft: '1px solid var(--card-border-color)',\n boxSizing: 'border-box',\n overflow: 'hidden',\n}\n\n/**\n * Renders the themer sidebar next to the active tool, so the user can browse\n * around their own studio while tweaking the theme.\n *\n * @internal\n */\nexport function ThemerActiveToolLayout(props: ActiveToolLayoutProps) {\n const {open} = useThemer()\n\n return (\n <Flex height=\"fill\" sizing=\"border\">\n <Box flex={1} height=\"fill\" overflow=\"auto\">\n {props.renderDefault(props)}\n </Box>\n\n {open && (\n <Layer height=\"fill\" style={sidebarStyle} zOffset={100}>\n <ThemerSidebar />\n </Layer>\n )}\n </Flex>\n )\n}\n","import {isColor} from '../lib/mix'\nimport {CreateThemeOptions} from '../types'\nimport {THEMER_FIELDS} from './fields'\n\nconst STORAGE_KEY = 'sanityStudio:themer:colors'\n\n/**\n * Restores draft colors from localStorage, so theme drafts survive studio\n * reloads.\n *\n * @internal\n */\nexport function readStoredColors(): CreateThemeOptions | null {\n try {\n if (typeof localStorage === 'undefined') return null\n\n const raw = localStorage.getItem(STORAGE_KEY)\n\n if (!raw) return null\n\n const parsed: unknown = JSON.parse(raw)\n\n if (!parsed || typeof parsed !== 'object') return null\n\n const colors: CreateThemeOptions = {}\n\n for (const {key} of THEMER_FIELDS) {\n const value: unknown = Reflect.get(parsed, key)\n\n if (typeof value === 'string' && isColor(value)) {\n colors[key] = value\n }\n }\n\n return colors\n } catch {\n return null\n }\n}\n\n/** @internal */\nexport function writeStoredColors(colors: CreateThemeOptions | null): void {\n try {\n if (typeof localStorage === 'undefined') return\n\n if (colors === null) {\n localStorage.removeItem(STORAGE_KEY)\n } else {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(colors))\n }\n } catch {\n // Storage can be unavailable (e.g. private browsing) — drafts just won't persist\n }\n}\n","import {ThemeProvider} from '@sanity/ui'\nimport {useEffect, useMemo, useState} from 'react'\nimport {type LayoutProps} from 'sanity'\n\nimport {createTheme} from '../createTheme'\nimport {CreateThemeOptions} from '../types'\nimport {ThemerContext, ThemerContextValue} from './context'\nimport {readStoredColors, writeStoredColors} from './storage'\n\n/**\n * Wraps the whole Studio so that draft themes generated by the themer sidebar\n * apply everywhere while the user browses around, and hosts the state that the\n * navbar toggle and the sidebar share.\n *\n * The draft theme provider inherits the color scheme from the Studio, so the\n * preview follows the appearance setting (light/dark/system) like any other\n * theme.\n *\n * @internal\n */\nexport function ThemerLayout(props: LayoutProps & {baseColors: CreateThemeOptions}) {\n const {baseColors, ...layoutProps} = props\n const [open, setOpen] = useState(false)\n const [colors, setColors] = useState<CreateThemeOptions | null>(readStoredColors)\n\n useEffect(() => writeStoredColors(colors), [colors])\n\n // The theme identity must be stable between renders: it feeds the\n // styled-components theme context for the whole Studio, and rebuilding it\n // would re-render everything\n const theme = useMemo(\n () => (colors === null ? null : createTheme({...baseColors, ...colors})),\n [baseColors, colors],\n )\n\n const context = useMemo<ThemerContextValue>(\n () => ({baseColors, colors, setColors, open, setOpen}),\n [baseColors, colors, open],\n )\n\n return (\n <ThemerContext.Provider value={context}>\n {theme === null ? (\n layoutProps.renderDefault(layoutProps)\n ) : (\n <ThemeProvider theme={theme}>{layoutProps.renderDefault(layoutProps)}</ThemeProvider>\n )}\n </ThemerContext.Provider>\n )\n}\n","import {ColorWheelIcon} from '@sanity/icons/ColorWheel'\nimport {type NavbarProps} from 'sanity'\n\nimport {useThemer} from './context'\n\n/**\n * Adds the toggle that opens and closes the themer sidebar to the Studio\n * navbar.\n *\n * @internal\n */\nexport function ThemerNavbar(props: NavbarProps) {\n const {open, setOpen} = useThemer()\n\n return props.renderDefault({\n ...props,\n __internal_actions: [\n ...(props.__internal_actions ?? []),\n {\n icon: ColorWheelIcon,\n location: 'topbar',\n name: 'themer',\n onAction: () => setOpen(!open),\n selected: open,\n title: 'Themer',\n },\n ],\n })\n}\n","import {definePlugin, type LayoutProps} from 'sanity'\n\nimport {CreateThemeOptions} from '../types'\nimport {ThemerActiveToolLayout} from './ThemerActiveToolLayout'\nimport {ThemerLayout} from './ThemerLayout'\nimport {ThemerNavbar} from './ThemerNavbar'\n\n/**\n * Options for the {@link themerTool} plugin.\n *\n * @public\n */\nexport interface ThemerToolOptions {\n /**\n * The colors that the Studio's configured theme was generated from — the\n * themer starts editing from these, so pass the same object that the\n * `theme` in the Studio config uses:\n *\n * ```ts\n * const colors = {primary: '#2276fc'}\n *\n * export default defineConfig({\n * theme: createTheme(colors),\n * plugins: [themerTool({colors})],\n * })\n * ```\n */\n colors?: CreateThemeOptions\n}\n\n/**\n * A Studio plugin that adds a themer sidebar for generating Studio themes:\n * a navbar toggle opens the sidebar next to the active tool, where presets\n * and color pickers preview a `createTheme` theme live on the whole Studio\n * while you browse around. Toggle between light and dark mode with the\n * regular appearance menu — the preview follows it.\n *\n * ```ts\n * import {themerTool} from '@sanity/themer/tool'\n * import {defineConfig} from 'sanity'\n *\n * export default defineConfig({\n * plugins: [themerTool()],\n * // ...rest of the config\n * })\n * ```\n *\n * @public\n */\nexport const themerTool = definePlugin<ThemerToolOptions | void>((options) => {\n const baseColors: CreateThemeOptions = options?.colors ?? {}\n\n function ThemerLayoutWithOptions(props: LayoutProps) {\n return <ThemerLayout {...props} baseColors={baseColors} />\n }\n\n return {\n name: '@sanity/themer/tool',\n studio: {\n components: {\n layout: ThemerLayoutWithOptions,\n navbar: ThemerNavbar,\n activeToolLayout: ThemerActiveToolLayout,\n },\n },\n }\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool.js","names":["createContext","useContext","BuildThemeOptions","ThemerContextValue","baseOptions","options","setOptions","open","setOpen","ThemerContext","useThemer","context","Error","BuildThemeOptions","DEFAULT_ACCENT","DEFAULT_BACKGROUND_DARK","DEFAULT_BACKGROUND_LIGHT","DEFAULT_CONTRAST","deriveTextColor","resolveThemeOptions","minimizeOptions","options","resolved","minimized","accent","text","dark","background","light","contrast","Object","keys","length","sameOptions","a","b","left","right","BuildThemeOptions","minimizeOptions","createThemeSnippet","options","minimized","entries","accent","text","undefined","push","background","parts","dark","light","join","contrast","COLOR_TINTS","ColorTintKey","ClipboardIcon","CloseIcon","ResetIcon","Box","Button","Card","Code","Flex","Grid","Stack","Text","useToast","useMemo","registerLanguage","typescript","styled","buildPalette","BuildThemeOptions","resolveThemeOptions","presets","ThemePreset","useThemer","sameOptions","createThemeSnippet","Swatch","input","Range","ThemerSidebar","$","_c","baseOptions","options","setOptions","setOpen","toast","active","t0","resolved","t1","palette","t2","find","preset","slug","activePresetSlug","t3","snippet","t4","changes","patch","t5","changes_0","background","patchBackground","t6","field","next","clearField","t7","key","next_0","dark","undefined","light","clearBackground","t8","navigator","clipboard","writeText","push","status","title","handleCopy","t9","Symbol","for","t10","t11","t12","map","preset_0","t13","t14","t15","accent","t16","blue","t17","text","t18","t19","t20","gray","t21","t22","t23","t24","black","t25","t26","t27","t28","white","t29","t30","t31","contrast","t32","t33","t34","t35","event","Number","currentTarget","value","t36","t37","t38","t39","t40","t41","t42","t43","t44","t45","t46","t47","t48","paletteStyle","React","CSSProperties","display","gap","height","borderRadius","overflow","boxShadow","PresetButton","props","onClick","swatches","const","_temp","flex","rampStyle","ColorRow","adjusted","auto","onChange","onClear","tints","tint","Box","Flex","Layer","ActiveToolLayoutProps","useThemer","ThemerSidebar","sidebarStyle","React","CSSProperties","width","flex","borderLeft","boxSizing","overflow","ThemerActiveToolLayout","props","$","_c","open","t0","renderDefault","t1","t2","t3","isColor","BuildThemeOptions","MAXIMUM_CONTRAST","MINIMUM_CONTRAST","STORAGE_KEY","sanitizeColor","value","toLowerCase","sanitizeOptions","accent","Reflect","get","options","text","background","dark","light","contrast","Number","isFinite","Math","min","max","readStoredOptions","localStorage","raw","getItem","JSON","parse","writeStoredOptions","removeItem","setItem","stringify","ThemeProvider","useEffect","useMemo","useState","LayoutProps","buildTheme","BuildThemeOptions","ThemerContext","ThemerContextValue","readStoredOptions","writeStoredOptions","ThemerLayout","props","$","_c","baseOptions","layoutProps","open","setOpen","options","setOptions","t0","t1","t2","theme","t3","context","t4","t5","renderDefault","t6","Provider","ColorWheelIcon","Button","Text","Tooltip","NavbarProps","useThemer","ThemerNavbarButton","$","_c","open","setOpen","t0","Symbol","for","t1","t2","ThemerNavbar","props","renderDefault","__internal_actions","location","name","render","_temp","icon","onAction","selected","title","definePlugin","LayoutProps","BuildThemeOptions","DEFAULT_ACCENT","ThemerActiveToolLayout","ThemerLayout","ThemerNavbar","ThemerToolOptions","config","themerTool","options","baseOptions","accent","ThemerLayoutWithOptions","props","$","_c","t0","name","studio","components","layout","navbar","activeToolLayout"],"sources":["../src/tool/context.ts","../src/tool/options.ts","../src/tool/snippet.ts","../src/tool/ThemerSidebar.tsx","../src/tool/ThemerActiveToolLayout.tsx","../src/tool/storage.ts","../src/tool/ThemerLayout.tsx","../src/tool/ThemerNavbar.tsx","../src/tool/plugin.tsx"],"sourcesContent":["import {createContext, useContext} from 'react'\n\nimport {BuildThemeOptions} from '../theme/options'\n\n/** @internal */\nexport interface ThemerContextValue {\n /** The theme options the Studio's configured theme was generated from */\n baseOptions: BuildThemeOptions\n /** The draft options, or `null` when the configured theme is untouched */\n options: BuildThemeOptions | null\n setOptions: (options: BuildThemeOptions | null) => void\n /** Whether the themer sidebar is open */\n open: boolean\n setOpen: (open: boolean) => void\n}\n\n/** @internal */\nexport const ThemerContext = createContext<ThemerContextValue | null>(null)\n\n/** @internal */\nexport function useThemer(): ThemerContextValue {\n const context = useContext(ThemerContext)\n\n if (!context) {\n throw new Error('useThemer must be used within the `themerTool` plugin')\n }\n\n return context\n}\n","import {\n BuildThemeOptions,\n DEFAULT_ACCENT,\n DEFAULT_BACKGROUND_DARK,\n DEFAULT_BACKGROUND_LIGHT,\n DEFAULT_CONTRAST,\n deriveTextColor,\n resolveThemeOptions,\n} from '../theme/options'\n\n/**\n * Reduces theme options to the minimal object that recreates them through\n * `buildTheme`: the text color is dropped when it matches the one derived\n * from the accent, and backgrounds and contrast are dropped when they match\n * the defaults. Options that boil down to the stock Studio theme reduce to\n * `null` — they need nothing from this package.\n *\n * @internal\n */\nexport function minimizeOptions(options: BuildThemeOptions): BuildThemeOptions | null {\n const resolved = resolveThemeOptions(options)\n const minimized: BuildThemeOptions = {accent: resolved.accent}\n\n if (resolved.text !== deriveTextColor(resolved.accent)) {\n minimized.text = resolved.text\n }\n\n const dark =\n resolved.background.dark === DEFAULT_BACKGROUND_DARK ? null : resolved.background.dark\n const light =\n resolved.background.light === DEFAULT_BACKGROUND_LIGHT ? null : resolved.background.light\n\n if (dark !== null || light !== null) {\n minimized.background = {}\n if (dark !== null) minimized.background.dark = dark\n if (light !== null) minimized.background.light = light\n }\n\n if (resolved.contrast !== DEFAULT_CONTRAST) {\n minimized.contrast = resolved.contrast\n }\n\n if (minimized.accent === DEFAULT_ACCENT && Object.keys(minimized).length === 1) {\n return null\n }\n\n return minimized\n}\n\n/**\n * Whether two sets of theme options generate the same theme, comparing their\n * resolved forms so that derived and explicit values (and hex casing) don't\n * matter.\n *\n * @internal\n */\nexport function sameOptions(a: BuildThemeOptions, b: BuildThemeOptions): boolean {\n const left = resolveThemeOptions(a)\n const right = resolveThemeOptions(b)\n\n return (\n left.accent === right.accent &&\n left.text === right.text &&\n left.background.dark === right.background.dark &&\n left.background.light === right.background.light &&\n left.contrast === right.contrast\n )\n}\n","import {BuildThemeOptions} from '../theme/options'\nimport {minimizeOptions} from './options'\n\n/**\n * Serializes theme options into the `buildTheme` call to paste into\n * `sanity.config.ts`, keeping only what differs from the derived defaults.\n *\n * Options that boil down to the stock Studio theme need nothing from this\n * package — so they serialize to a bare `buildTheme()` from `@sanity/ui/theme`\n * instead.\n *\n * @internal\n */\nexport function createThemeSnippet(options: BuildThemeOptions): string {\n const minimized = minimizeOptions(options)\n\n if (minimized === null) {\n return \"import {buildTheme} from '@sanity/ui/theme'\\n\\nexport const theme = buildTheme()\\n\"\n }\n\n const entries: string[] = [` accent: '${minimized.accent}',`]\n\n if (minimized.text !== undefined) {\n entries.push(` text: '${minimized.text}',`)\n }\n\n if (minimized.background) {\n const parts: string[] = []\n\n if (minimized.background.dark !== undefined) parts.push(`dark: '${minimized.background.dark}'`)\n if (minimized.background.light !== undefined) {\n parts.push(`light: '${minimized.background.light}'`)\n }\n\n entries.push(` background: {${parts.join(', ')}},`)\n }\n\n if (minimized.contrast !== undefined) {\n entries.push(` contrast: ${minimized.contrast},`)\n }\n\n return `import {buildTheme} from '@sanity/themer'\\n\\nexport const theme = buildTheme({\\n${entries.join('\\n')}\\n})\\n`\n}\n","import {COLOR_TINTS, ColorTintKey} from '@sanity/color'\nimport {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {ResetIcon} from '@sanity/icons/Reset'\nimport {Box, Button, Card, Code, Flex, Grid, Stack, Text, useToast} from '@sanity/ui'\nimport {useMemo} from 'react'\nimport {registerLanguage} from 'react-refractor'\nimport typescript from 'refractor/typescript'\nimport {styled} from 'styled-components'\n\nimport {buildPalette} from '../theme/buildPalette'\nimport {BuildThemeOptions, resolveThemeOptions} from '../theme/options'\nimport {presets, ThemePreset} from '../theme/presets'\nimport {useThemer} from './context'\nimport {sameOptions} from './options'\nimport {createThemeSnippet} from './snippet'\n\n// `Code` only highlights languages the surrounding app has registered with\n// react-refractor, and the Studio registers its own set from an async import\n// during startup — a race this sidebar keeps losing. Registering the one\n// language the snippet needs keeps it highlighted from the first render.\nregisterLanguage(typescript)\n\n/**\n * `<input type=\"color\">` paints the color into a shadow-DOM swatch that brings\n * its own border and padding, which then sits inside ours as a second border.\n * Stripping that chrome leaves the themed border as the only one.\n */\nconst Swatch = styled.input`\n box-sizing: border-box;\n flex: none;\n width: 33px;\n height: 33px;\n padding: 0;\n border: 1px solid var(--card-border-color);\n border-radius: 4px;\n background: none;\n cursor: pointer;\n\n &::-webkit-color-swatch-wrapper {\n padding: 0;\n }\n\n &::-webkit-color-swatch {\n border: none;\n border-radius: 3px;\n }\n\n &::-moz-color-swatch {\n border: none;\n border-radius: 3px;\n }\n`\n\n/** A native range input, themed through `accent-color` */\nconst Range = styled.input`\n display: block;\n width: 100%;\n margin: 0;\n accent-color: var(--card-focus-ring-color);\n`\n\n/**\n * The themer sidebar: presets, the accent/text/background pickers and the\n * contrast slider that generate the previewed `buildTheme` theme, plus the\n * `buildTheme` snippet to make it permanent.\n *\n * @internal\n */\nexport function ThemerSidebar() {\n const {baseOptions, options, setOptions, setOpen} = useThemer()\n const toast = useToast()\n\n const active = options ?? baseOptions\n const resolved = useMemo(() => resolveThemeOptions(active), [active])\n const palette = useMemo(() => buildPalette(active), [active])\n const activePresetSlug = presets.find((preset) => sameOptions(preset.options, active))?.slug ?? ''\n const snippet = createThemeSnippet(active)\n\n const patch = (changes: Partial<BuildThemeOptions>) => {\n setOptions({...active, ...changes})\n }\n\n const patchBackground = (changes: {dark?: string; light?: string}) => {\n setOptions({...active, background: {...active.background, ...changes}})\n }\n\n const clearField = (field: 'text' | 'contrast') => {\n const next = {...active}\n\n delete next[field]\n setOptions(next)\n }\n\n const clearBackground = (key: 'dark' | 'light') => {\n const background = {...active.background}\n\n delete background[key]\n\n const next = {...active}\n\n if (background.dark === undefined && background.light === undefined) {\n delete next.background\n } else {\n next.background = background\n }\n\n setOptions(next)\n }\n\n const handleCopy = async () => {\n try {\n await navigator.clipboard.writeText(snippet)\n toast.push({status: 'success', title: 'Copied theme to the clipboard'})\n } catch {\n toast.push({status: 'error', title: 'Could not copy the theme'})\n }\n }\n\n return (\n <Card height=\"fill\">\n <Flex direction=\"column\" height=\"fill\">\n <Card borderBottom padding={3}>\n <Flex align=\"center\" gap={2}>\n <Box flex={1} paddingLeft={1}>\n <Text size={1} weight=\"semibold\">\n Themer\n </Text>\n </Box>\n <Button\n icon={CloseIcon}\n mode=\"bleed\"\n onClick={() => setOpen(false)}\n padding={2}\n title=\"Close themer\"\n />\n </Flex>\n </Card>\n\n <Box flex={1} overflow=\"auto\" padding={3}>\n <Stack gap={4}>\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Presets\n </Text>\n <Grid gap={2} gridTemplateColumns={2}>\n {presets.map((preset) => (\n <PresetButton\n active={preset.slug === activePresetSlug}\n key={preset.slug}\n onClick={() => setOptions(preset.options)}\n preset={preset}\n />\n ))}\n </Grid>\n </Stack>\n\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Colors\n </Text>\n <Stack gap={4}>\n <ColorRow\n onChange={(accent) => patch({accent})}\n tints={palette.blue}\n title=\"Accent\"\n value={resolved.accent}\n />\n <ColorRow\n auto={active.text === undefined}\n onChange={(text) => patch({text})}\n onClear={() => clearField('text')}\n tints={palette.gray}\n title=\"Text\"\n value={resolved.text}\n />\n <ColorRow\n adjusted={palette.black}\n auto={active.background?.dark === undefined}\n onChange={(dark) => patchBackground({dark})}\n onClear={() => clearBackground('dark')}\n title=\"Background · dark\"\n value={resolved.background.dark}\n />\n <ColorRow\n adjusted={palette.white}\n auto={active.background?.light === undefined}\n onChange={(light) => patchBackground({light})}\n onClear={() => clearBackground('light')}\n title=\"Background · light\"\n value={resolved.background.light}\n />\n </Stack>\n </Stack>\n\n <Stack gap={3}>\n <Flex align=\"center\" gap={2}>\n <Stack flex={1} gap={2}>\n <Text size={1} weight=\"medium\">\n Contrast\n </Text>\n <Text muted size={0}>\n {resolved.contrast}\n {active.contrast === undefined ? ' · auto' : ''}\n </Text>\n </Stack>\n {active.contrast !== undefined && (\n <Button\n icon={ResetIcon}\n mode=\"bleed\"\n onClick={() => clearField('contrast')}\n padding={2}\n title=\"Reset to auto\"\n />\n )}\n </Flex>\n <Range\n aria-label=\"Contrast\"\n max={100}\n min={15}\n onChange={(event) => patch({contrast: Number(event.currentTarget.value)})}\n step={1}\n type=\"range\"\n value={resolved.contrast}\n />\n <Text muted size={0}>\n 100 keeps text and borders neutral — lower values blend in the accent\n </Text>\n </Stack>\n\n <Stack gap={3}>\n <Text size={1} weight=\"medium\">\n Add to your config\n </Text>\n <Card border overflow=\"auto\" padding={2} radius={2} tone=\"transparent\">\n <Code language=\"ts\" size={0}>\n {snippet}\n </Code>\n </Card>\n <Flex gap={2}>\n <Button\n icon={ClipboardIcon}\n mode=\"ghost\"\n onClick={() => void handleCopy()}\n text=\"Copy\"\n />\n <Button\n disabled={options === null}\n icon={ResetIcon}\n mode=\"ghost\"\n onClick={() => setOptions(null)}\n text=\"Reset\"\n tone=\"critical\"\n />\n </Flex>\n </Stack>\n </Stack>\n </Box>\n </Flex>\n </Card>\n )\n}\n\nconst paletteStyle: React.CSSProperties = {\n display: 'flex',\n // The gaps let the border color through, so a near-white light background\n // still reads as a swatch rather than a hole in the palette\n gap: 1,\n background: 'var(--card-border-color)',\n height: 21,\n borderRadius: 3,\n overflow: 'hidden',\n boxShadow: 'inset 0 0 0 1px var(--card-border-color)',\n}\n\n/** A little palette of the colors a preset would apply */\nfunction PresetButton(props: {active: boolean; onClick: () => void; preset: ThemePreset}) {\n const {active, onClick, preset} = props\n\n const swatches = useMemo(() => {\n const resolved = resolveThemeOptions(preset.options)\n\n return [\n ['accent', resolved.accent],\n ['text', resolved.text],\n ['dark', resolved.background.dark],\n ['light', resolved.background.light],\n ] as const\n }, [preset])\n\n return (\n <Button mode=\"ghost\" onClick={onClick} padding={2} selected={active} title={preset.title}>\n <Stack as=\"span\" gap={2}>\n <span style={paletteStyle}>\n {swatches.map(([key, background]) => (\n <span key={key} style={{flex: 1, background}} />\n ))}\n </span>\n <Text align=\"left\" size={1} textOverflow=\"ellipsis\">\n {preset.title}\n </Text>\n </Stack>\n </Button>\n )\n}\n\nconst rampStyle: React.CSSProperties = {\n ...paletteStyle,\n height: 13,\n borderRadius: 2,\n}\n\n/**\n * One color of the theme: a swatch with its value, an optional reset-to-auto\n * button, and the generated 50–950 tint ramp for the scales it anchors.\n */\nfunction ColorRow(props: {\n /** The color the generator actually applied, when it may differ from the input */\n adjusted?: string\n /** Whether the value is derived rather than explicitly set */\n auto?: boolean\n onChange: (value: string) => void\n onClear?: () => void\n /** The generated tint ramp this color anchors */\n tints?: Record<ColorTintKey, string>\n title: string\n value: string\n}) {\n const {adjusted, auto, onChange, onClear, tints, title, value} = props\n\n return (\n <Stack gap={2}>\n <Flex align=\"center\" gap={2}>\n <Stack flex={1} gap={2}>\n <Text size={1}>{title}</Text>\n <Text muted size={0} textOverflow=\"ellipsis\">\n {value}\n {adjusted !== undefined && adjusted !== value ? ` → ${adjusted}` : ''}\n {auto ? ' · auto' : ''}\n </Text>\n </Stack>\n {onClear && !auto && (\n <Button\n icon={ResetIcon}\n mode=\"bleed\"\n onClick={onClear}\n padding={2}\n title=\"Reset to auto\"\n />\n )}\n <Swatch\n aria-label={`${title} color`}\n onChange={(event) => onChange(event.currentTarget.value)}\n type=\"color\"\n value={value}\n />\n </Flex>\n {tints && (\n <span style={rampStyle}>\n {COLOR_TINTS.map((tint) => (\n <span key={tint} style={{flex: 1, background: tints[tint]}} />\n ))}\n </span>\n )}\n </Stack>\n )\n}\n","import {Box, Flex, Layer} from '@sanity/ui'\nimport {type ActiveToolLayoutProps} from 'sanity'\n\nimport {useThemer} from './context'\nimport {ThemerSidebar} from './ThemerSidebar'\n\n/**\n * Narrow enough to leave the studio preview as much room as possible: it fits\n * the widest picker label next to its swatch, and the code snippet scrolls\n * horizontally rather than widening the sidebar.\n */\nconst sidebarStyle: React.CSSProperties = {\n width: 240,\n flex: 'none',\n borderLeft: '1px solid var(--card-border-color)',\n boxSizing: 'border-box',\n overflow: 'hidden',\n}\n\n/**\n * Renders the themer sidebar next to the active tool, so the user can browse\n * around their own studio while tweaking the theme.\n *\n * @internal\n */\nexport function ThemerActiveToolLayout(props: ActiveToolLayoutProps) {\n const {open} = useThemer()\n\n return (\n <Flex height=\"fill\" sizing=\"border\">\n <Box flex={1} height=\"fill\" overflow=\"auto\">\n {props.renderDefault(props)}\n </Box>\n\n {open && (\n <Layer height=\"fill\" style={sidebarStyle} zOffset={100}>\n <ThemerSidebar />\n </Layer>\n )}\n </Flex>\n )\n}\n","import {isColor} from '../lib/mix'\nimport {BuildThemeOptions, MAXIMUM_CONTRAST, MINIMUM_CONTRAST} from '../theme/options'\n\nconst STORAGE_KEY = 'sanityStudio:themer:options'\n\nfunction sanitizeColor(value: unknown): string | null {\n return typeof value === 'string' && isColor(value) ? value.toLowerCase() : null\n}\n\nfunction sanitizeOptions(value: unknown): BuildThemeOptions | null {\n if (!value || typeof value !== 'object') return null\n\n const accent = sanitizeColor(Reflect.get(value, 'accent'))\n\n if (!accent) return null\n\n const options: BuildThemeOptions = {accent}\n const text = sanitizeColor(Reflect.get(value, 'text'))\n\n if (text) options.text = text\n\n const background: unknown = Reflect.get(value, 'background')\n\n if (background && typeof background === 'object') {\n const dark = sanitizeColor(Reflect.get(background, 'dark'))\n const light = sanitizeColor(Reflect.get(background, 'light'))\n\n if (dark || light) {\n options.background = {}\n if (dark) options.background.dark = dark\n if (light) options.background.light = light\n }\n }\n\n const contrast: unknown = Reflect.get(value, 'contrast')\n\n if (typeof contrast === 'number' && Number.isFinite(contrast)) {\n options.contrast = Math.min(MAXIMUM_CONTRAST, Math.max(MINIMUM_CONTRAST, contrast))\n }\n\n return options\n}\n\n/**\n * Restores draft theme options from localStorage, so theme drafts survive\n * studio reloads.\n *\n * @internal\n */\nexport function readStoredOptions(): BuildThemeOptions | null {\n try {\n if (typeof localStorage === 'undefined') return null\n\n const raw = localStorage.getItem(STORAGE_KEY)\n\n if (!raw) return null\n\n return sanitizeOptions(JSON.parse(raw))\n } catch {\n return null\n }\n}\n\n/** @internal */\nexport function writeStoredOptions(options: BuildThemeOptions | null): void {\n try {\n if (typeof localStorage === 'undefined') return\n\n if (options === null) {\n localStorage.removeItem(STORAGE_KEY)\n } else {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(options))\n }\n } catch {\n // Storage can be unavailable (e.g. private browsing) — drafts just won't persist\n }\n}\n","import {ThemeProvider} from '@sanity/ui'\nimport {useEffect, useMemo, useState} from 'react'\nimport {type LayoutProps} from 'sanity'\n\nimport {buildTheme} from '../theme/buildTheme'\nimport {BuildThemeOptions} from '../theme/options'\nimport {ThemerContext, ThemerContextValue} from './context'\nimport {readStoredOptions, writeStoredOptions} from './storage'\n\n/**\n * Wraps the whole Studio so that draft themes generated by the themer sidebar\n * apply everywhere while the user browses around, and hosts the state that the\n * navbar toggle and the sidebar share.\n *\n * The draft theme provider inherits the color scheme from the Studio, so the\n * preview follows the appearance setting (light/dark/system) like any other\n * theme.\n *\n * @internal\n */\nexport function ThemerLayout(props: LayoutProps & {baseOptions: BuildThemeOptions}) {\n const {baseOptions, ...layoutProps} = props\n const [open, setOpen] = useState(false)\n const [options, setOptions] = useState<BuildThemeOptions | null>(readStoredOptions)\n\n useEffect(() => writeStoredOptions(options), [options])\n\n // The theme identity must be stable between renders: it feeds the\n // styled-components theme context for the whole Studio, and rebuilding it\n // would re-render everything\n const theme = useMemo(() => (options === null ? null : buildTheme(options)), [options])\n\n const context = useMemo<ThemerContextValue>(\n () => ({baseOptions, options, setOptions, open, setOpen}),\n [baseOptions, options, open],\n )\n\n return (\n <ThemerContext.Provider value={context}>\n {theme === null ? (\n layoutProps.renderDefault(layoutProps)\n ) : (\n <ThemeProvider theme={theme}>{layoutProps.renderDefault(layoutProps)}</ThemeProvider>\n )}\n </ThemerContext.Provider>\n )\n}\n","import {ColorWheelIcon} from '@sanity/icons/ColorWheel'\nimport {Button, Text, Tooltip} from '@sanity/ui'\nimport {type NavbarProps} from 'sanity'\n\nimport {useThemer} from './context'\n\nfunction ThemerNavbarButton() {\n const {open, setOpen} = useThemer()\n\n return (\n <Tooltip content={<Text size={1}>Themer</Text>} portal>\n <Button\n aria-label=\"Themer\"\n icon={ColorWheelIcon}\n mode=\"bleed\"\n onClick={() => setOpen(!open)}\n // The Studio's own navbar buttons go through a wrapper that pins them\n // to this padding, where `@sanity/ui` defaults to a roomier 3\n padding={2}\n selected={open}\n />\n </Tooltip>\n )\n}\n\n/**\n * Adds the toggle that opens and closes the themer sidebar to the Studio\n * navbar — an icon button with a tooltip in the top bar (like the Tasks\n * toggle), and a regular titled action in the narrow-screen sidebar menu.\n *\n * @internal\n */\nexport function ThemerNavbar(props: NavbarProps) {\n const {open, setOpen} = useThemer()\n\n return props.renderDefault({\n ...props,\n __internal_actions: [\n ...(props.__internal_actions ?? []),\n {\n location: 'topbar',\n name: 'themer-topbar',\n render: () => <ThemerNavbarButton />,\n },\n {\n icon: ColorWheelIcon,\n location: 'sidebar',\n name: 'themer-sidebar',\n onAction: () => setOpen(!open),\n selected: open,\n title: 'Themer',\n },\n ],\n })\n}\n","import {definePlugin, type LayoutProps} from 'sanity'\n\nimport {BuildThemeOptions, DEFAULT_ACCENT} from '../theme/options'\nimport {ThemerActiveToolLayout} from './ThemerActiveToolLayout'\nimport {ThemerLayout} from './ThemerLayout'\nimport {ThemerNavbar} from './ThemerNavbar'\n\n/**\n * Options for the {@link themerTool} plugin.\n *\n * This is experimental and may change or be removed in any release without\n * notice — use at your own risk.\n *\n * @alpha\n */\nexport interface ThemerToolOptions {\n /**\n * The `buildTheme` options that the Studio's configured theme was generated\n * from — the themer starts editing from these, so pass the same object that\n * the `theme` in the Studio config uses:\n *\n * ```ts\n * const config: BuildThemeOptions = {accent: '#1cb485'}\n *\n * export default defineConfig({\n * theme: buildTheme(config),\n * plugins: [themerTool({config})],\n * })\n * ```\n */\n config?: BuildThemeOptions\n}\n\n/**\n * A Studio plugin that adds a themer sidebar for `buildTheme` themes: a\n * navbar toggle opens the sidebar next to the active tool, where presets, the\n * accent/text/background pickers and the contrast slider preview a\n * `buildTheme` theme live on the whole Studio while you browse around.\n * Toggle between light and dark mode with the regular appearance menu — the\n * preview follows it.\n *\n * ```ts\n * import {themerTool} from '@sanity/themer/tool'\n * import {defineConfig} from 'sanity'\n *\n * export default defineConfig({\n * plugins: [themerTool()],\n * // ...rest of the config\n * })\n * ```\n *\n * This is experimental and may change or be removed in any release without\n * notice — use at your own risk.\n *\n * @alpha\n */\nexport const themerTool = definePlugin<ThemerToolOptions | void>((options) => {\n const baseOptions = options?.config ?? {accent: DEFAULT_ACCENT}\n\n function ThemerLayoutWithOptions(props: LayoutProps) {\n return <ThemerLayout {...props} baseOptions={baseOptions} />\n }\n\n return {\n name: '@sanity/themer/tool',\n studio: {\n components: {\n layout: ThemerLayoutWithOptions,\n navbar: ThemerNavbar,\n activeToolLayout: ThemerActiveToolLayout,\n },\n },\n }\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/themer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Generate Sanity Studio themes, and preview them with a Studio tool.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -25,60 +25,45 @@
|
|
|
25
25
|
],
|
|
26
26
|
"type": "module",
|
|
27
27
|
"sideEffects": false,
|
|
28
|
-
"
|
|
29
|
-
"module": "./dist/index.js",
|
|
30
|
-
"types": "./dist/index.d.cts",
|
|
31
|
-
"typesVersions": {
|
|
32
|
-
"*": {
|
|
33
|
-
"legacy": [
|
|
34
|
-
"./dist/legacy.d.cts"
|
|
35
|
-
],
|
|
36
|
-
"tool": [
|
|
37
|
-
"./dist/tool.d.cts"
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
},
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
41
29
|
"exports": {
|
|
42
|
-
".":
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
},
|
|
46
|
-
"./legacy": {
|
|
47
|
-
"import": "./dist/legacy.js",
|
|
48
|
-
"require": "./dist/legacy.cjs"
|
|
49
|
-
},
|
|
50
|
-
"./tool": {
|
|
51
|
-
"import": "./dist/tool.js",
|
|
52
|
-
"require": "./dist/tool.cjs"
|
|
53
|
-
},
|
|
30
|
+
".": "./dist/index.js",
|
|
31
|
+
"./legacy": "./dist/legacy.js",
|
|
32
|
+
"./tool": "./dist/tool.js",
|
|
54
33
|
"./package.json": "./package.json"
|
|
55
34
|
},
|
|
56
|
-
"publishConfig": {
|
|
57
|
-
"access": "public"
|
|
58
|
-
},
|
|
59
35
|
"dependencies": {
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
36
|
+
"react-compiler-runtime": "1.0.0",
|
|
37
|
+
"react-refractor": "^4.0.0",
|
|
38
|
+
"refractor": "^5.0.0",
|
|
39
|
+
"@sanity/icons": "^5.2.1",
|
|
40
|
+
"@sanity/ui": "^3.5.0",
|
|
41
|
+
"@sanity/color": "^3.0.8"
|
|
63
42
|
},
|
|
64
43
|
"devDependencies": {
|
|
65
|
-
"@sanity/tsdown-config": "^0.
|
|
44
|
+
"@sanity/tsdown-config": "^0.21.1",
|
|
66
45
|
"@types/node": "^24.13.3",
|
|
67
46
|
"@types/react": "^19.2.17",
|
|
68
|
-
"react": "^
|
|
47
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
48
|
+
"react": "^19.2.8",
|
|
69
49
|
"rimraf": "^5.0.5",
|
|
70
|
-
"sanity": "^6.
|
|
71
|
-
"
|
|
72
|
-
"
|
|
50
|
+
"sanity": "^6.6.0",
|
|
51
|
+
"styled-components": "^6.4.4",
|
|
52
|
+
"tsdown": "^0.22.14",
|
|
53
|
+
"typescript": "7.0.2",
|
|
73
54
|
"vitest": "^4.1.10"
|
|
74
55
|
},
|
|
75
56
|
"peerDependencies": {
|
|
76
|
-
"react": "^
|
|
77
|
-
"sanity": "^
|
|
57
|
+
"react": "^19",
|
|
58
|
+
"sanity": "^6",
|
|
59
|
+
"styled-components": "^6"
|
|
78
60
|
},
|
|
79
61
|
"peerDependenciesMeta": {
|
|
80
62
|
"sanity": {
|
|
81
63
|
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"styled-components": {
|
|
66
|
+
"optional": true
|
|
82
67
|
}
|
|
83
68
|
},
|
|
84
69
|
"engines": {
|
package/dist/_chunks/mix.cjs
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Color mixing that is byte-for-byte compatible with the `mix` function from
|
|
3
|
-
* `polished`, which the hosted Themer service (themer.sanity.build) used to
|
|
4
|
-
* interpolate hue tints. Only opaque hex colors are supported, which is all
|
|
5
|
-
* the theme generators ever pass.
|
|
6
|
-
*
|
|
7
|
-
* @internal
|
|
8
|
-
*/
|
|
9
|
-
function mix(weight, color, otherColor) {
|
|
10
|
-
if (weight === 0) return otherColor;
|
|
11
|
-
let [r1, g1, b1] = hexToRgb(color), [r2, g2, b2] = hexToRgb(otherColor), w2 = 1 - weight;
|
|
12
|
-
return reduceHex(`#${channelToHex(Math.floor(r1 * weight + r2 * w2))}${channelToHex(Math.floor(g1 * weight + g2 * w2))}${channelToHex(Math.floor(b1 * weight + b2 * w2))}`);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Matches `#abc` and `#aabbcc` hex colors (the only formats the theme
|
|
16
|
-
* generators accept), same as the hosted Themer service did.
|
|
17
|
-
*
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
function isColor(input) {
|
|
21
|
-
return /^#(?:[0-9a-f]{3}){1,2}$/i.test(input);
|
|
22
|
-
}
|
|
23
|
-
function hexToRgb(color) {
|
|
24
|
-
if (!isColor(color)) throw TypeError(`Invalid color: ${JSON.stringify(color)} — expected a hex color`);
|
|
25
|
-
let hex = color.length === 4 ? `${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}` : color.slice(1);
|
|
26
|
-
return [
|
|
27
|
-
parseInt(hex.slice(0, 2), 16),
|
|
28
|
-
parseInt(hex.slice(2, 4), 16),
|
|
29
|
-
parseInt(hex.slice(4, 6), 16)
|
|
30
|
-
];
|
|
31
|
-
}
|
|
32
|
-
function channelToHex(value) {
|
|
33
|
-
let hex = value.toString(16);
|
|
34
|
-
return hex.length === 1 ? `0${hex}` : hex;
|
|
35
|
-
}
|
|
36
|
-
/** Shortens `#aabbcc` to `#abc` when possible, same as `polished` does */
|
|
37
|
-
function reduceHex(hex) {
|
|
38
|
-
return hex[1] === hex[2] && hex[3] === hex[4] && hex[5] === hex[6] ? `#${hex[1]}${hex[3]}${hex[5]}` : hex;
|
|
39
|
-
}
|
|
40
|
-
Object.defineProperty(exports, "n", {
|
|
41
|
-
enumerable: !0,
|
|
42
|
-
get: function() {
|
|
43
|
-
return mix;
|
|
44
|
-
}
|
|
45
|
-
}), Object.defineProperty(exports, "t", {
|
|
46
|
-
enumerable: !0,
|
|
47
|
-
get: function() {
|
|
48
|
-
return isColor;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
//# sourceMappingURL=mix.cjs.map
|
package/dist/_chunks/mix.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mix.cjs","names":[],"sources":["../../src/lib/mix.ts"],"sourcesContent":["/**\n * Color mixing that is byte-for-byte compatible with the `mix` function from\n * `polished`, which the hosted Themer service (themer.sanity.build) used to\n * interpolate hue tints. Only opaque hex colors are supported, which is all\n * the theme generators ever pass.\n *\n * @internal\n */\nexport function mix(weight: number, color: string, otherColor: string): string {\n // `polished` returns the other color as-is when the weight is 0\n if (weight === 0) return otherColor\n\n const [r1, g1, b1] = hexToRgb(color)\n const [r2, g2, b2] = hexToRgb(otherColor)\n\n const w2 = 1 - weight\n\n return reduceHex(\n `#${channelToHex(Math.floor(r1 * weight + r2 * w2))}${channelToHex(\n Math.floor(g1 * weight + g2 * w2),\n )}${channelToHex(Math.floor(b1 * weight + b2 * w2))}`,\n )\n}\n\n/**\n * Matches `#abc` and `#aabbcc` hex colors (the only formats the theme\n * generators accept), same as the hosted Themer service did.\n *\n * @internal\n */\nexport function isColor(input: string): boolean {\n return /^#(?:[0-9a-f]{3}){1,2}$/i.test(input)\n}\n\nfunction hexToRgb(color: string): [number, number, number] {\n if (!isColor(color)) {\n throw new TypeError(`Invalid color: ${JSON.stringify(color)} — expected a hex color`)\n }\n\n const hex =\n color.length === 4\n ? `${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}`\n : color.slice(1)\n\n return [\n parseInt(hex.slice(0, 2), 16),\n parseInt(hex.slice(2, 4), 16),\n parseInt(hex.slice(4, 6), 16),\n ]\n}\n\nfunction channelToHex(value: number): string {\n const hex = value.toString(16)\n\n return hex.length === 1 ? `0${hex}` : hex\n}\n\n/** Shortens `#aabbcc` to `#abc` when possible, same as `polished` does */\nfunction reduceHex(hex: string): string {\n if (hex[1] === hex[2] && hex[3] === hex[4] && hex[5] === hex[6]) {\n return `#${hex[1]}${hex[3]}${hex[5]}`\n }\n\n return hex\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,IAAI,QAAgB,OAAe,YAA4B;CAE7E,IAAI,WAAW,GAAG,OAAO;CAEzB,IAAM,CAAC,IAAI,IAAI,MAAM,SAAS,KAAK,GAC7B,CAAC,IAAI,IAAI,MAAM,SAAS,UAAU,GAElC,KAAK,IAAI;CAEf,OAAO,UACL,IAAI,aAAa,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC,IAAI,aACpD,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAClC,IAAI,aAAa,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC,GACpD;AACF;;;;;;;AAQA,SAAgB,QAAQ,OAAwB;CAC9C,OAAO,2BAA2B,KAAK,KAAK;AAC9C;AAEA,SAAS,SAAS,OAAyC;CACzD,IAAI,CAAC,QAAQ,KAAK,GAChB,MAAU,UAAU,kBAAkB,KAAK,UAAU,KAAK,EAAE,wBAAwB;CAGtF,IAAM,MACJ,MAAM,WAAW,IACb,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,OAChE,MAAM,MAAM,CAAC;CAEnB,OAAO;EACL,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;EAC5B,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;EAC5B,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;CAC9B;AACF;AAEA,SAAS,aAAa,OAAuB;CAC3C,IAAM,MAAM,MAAM,SAAS,EAAE;CAE7B,OAAO,IAAI,WAAW,IAAI,IAAI,QAAQ;AACxC;;AAGA,SAAS,UAAU,KAAqB;CAKtC,OAJI,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,KACpD,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,OAG5B;AACT"}
|
package/dist/_chunks/mix.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mix.js","names":[],"sources":["../../src/lib/mix.ts"],"sourcesContent":["/**\n * Color mixing that is byte-for-byte compatible with the `mix` function from\n * `polished`, which the hosted Themer service (themer.sanity.build) used to\n * interpolate hue tints. Only opaque hex colors are supported, which is all\n * the theme generators ever pass.\n *\n * @internal\n */\nexport function mix(weight: number, color: string, otherColor: string): string {\n // `polished` returns the other color as-is when the weight is 0\n if (weight === 0) return otherColor\n\n const [r1, g1, b1] = hexToRgb(color)\n const [r2, g2, b2] = hexToRgb(otherColor)\n\n const w2 = 1 - weight\n\n return reduceHex(\n `#${channelToHex(Math.floor(r1 * weight + r2 * w2))}${channelToHex(\n Math.floor(g1 * weight + g2 * w2),\n )}${channelToHex(Math.floor(b1 * weight + b2 * w2))}`,\n )\n}\n\n/**\n * Matches `#abc` and `#aabbcc` hex colors (the only formats the theme\n * generators accept), same as the hosted Themer service did.\n *\n * @internal\n */\nexport function isColor(input: string): boolean {\n return /^#(?:[0-9a-f]{3}){1,2}$/i.test(input)\n}\n\nfunction hexToRgb(color: string): [number, number, number] {\n if (!isColor(color)) {\n throw new TypeError(`Invalid color: ${JSON.stringify(color)} — expected a hex color`)\n }\n\n const hex =\n color.length === 4\n ? `${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}`\n : color.slice(1)\n\n return [\n parseInt(hex.slice(0, 2), 16),\n parseInt(hex.slice(2, 4), 16),\n parseInt(hex.slice(4, 6), 16),\n ]\n}\n\nfunction channelToHex(value: number): string {\n const hex = value.toString(16)\n\n return hex.length === 1 ? `0${hex}` : hex\n}\n\n/** Shortens `#aabbcc` to `#abc` when possible, same as `polished` does */\nfunction reduceHex(hex: string): string {\n if (hex[1] === hex[2] && hex[3] === hex[4] && hex[5] === hex[6]) {\n return `#${hex[1]}${hex[3]}${hex[5]}`\n }\n\n return hex\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,IAAI,QAAgB,OAAe,YAA4B;CAE7E,IAAI,WAAW,GAAG,OAAO;CAEzB,IAAM,CAAC,IAAI,IAAI,MAAM,SAAS,KAAK,GAC7B,CAAC,IAAI,IAAI,MAAM,SAAS,UAAU,GAElC,KAAK,IAAI;CAEf,OAAO,UACL,IAAI,aAAa,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC,IAAI,aACpD,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAClC,IAAI,aAAa,KAAK,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC,GACpD;AACF;;;;;;;AAQA,SAAgB,QAAQ,OAAwB;CAC9C,OAAO,2BAA2B,KAAK,KAAK;AAC9C;AAEA,SAAS,SAAS,OAAyC;CACzD,IAAI,CAAC,QAAQ,KAAK,GAChB,MAAU,UAAU,kBAAkB,KAAK,UAAU,KAAK,EAAE,wBAAwB;CAGtF,IAAM,MACJ,MAAM,WAAW,IACb,GAAG,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,OAChE,MAAM,MAAM,CAAC;CAEnB,OAAO;EACL,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;EAC5B,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;EAC5B,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;CAC9B;AACF;AAEA,SAAS,aAAa,OAAuB;CAC3C,IAAM,MAAM,MAAM,SAAS,EAAE;CAE7B,OAAO,IAAI,WAAW,IAAI,IAAI,QAAQ;AACxC;;AAGA,SAAS,UAAU,KAAqB;CAKtC,OAJI,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,IAAI,KACpD,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,OAG5B;AACT"}
|
package/dist/_chunks/presets.cjs
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
const require_mix = require("./mix.cjs");
|
|
2
|
-
let _sanity_color = require("@sanity/color"), _sanity_ui_theme = require("@sanity/ui/theme");
|
|
3
|
-
/** The palette hue that each themeable color drives */
|
|
4
|
-
const HUE_MAPPING = [
|
|
5
|
-
["gray", "gray"],
|
|
6
|
-
["primary", "blue"],
|
|
7
|
-
["positive", "green"],
|
|
8
|
-
["caution", "yellow"],
|
|
9
|
-
["critical", "red"]
|
|
10
|
-
];
|
|
11
|
-
/**
|
|
12
|
-
* Maps themeable colors to a `@sanity/ui` `ThemeConfig`, for when a theme
|
|
13
|
-
* needs further customization than `createTheme` exposes:
|
|
14
|
-
*
|
|
15
|
-
* ```ts
|
|
16
|
-
* import {themeConfigFromColors} from '@sanity/themer'
|
|
17
|
-
* import {buildTheme} from '@sanity/ui/theme'
|
|
18
|
-
*
|
|
19
|
-
* const theme = buildTheme({
|
|
20
|
-
* ...themeConfigFromColors({primary: '#2276fc'}),
|
|
21
|
-
* // ...other ThemeConfig properties
|
|
22
|
-
* })
|
|
23
|
-
* ```
|
|
24
|
-
*
|
|
25
|
-
* @public
|
|
26
|
-
*/
|
|
27
|
-
function themeConfigFromColors(colors) {
|
|
28
|
-
for (let [key, value] of Object.entries(colors)) if (typeof value == "string" && !require_mix.t(value)) throw TypeError(`Invalid color for ${JSON.stringify(key)}: ${JSON.stringify(value)} — expected a hex color`);
|
|
29
|
-
let anchored = !!(colors.lightest || colors.darkest);
|
|
30
|
-
if (!anchored && !HUE_MAPPING.some(([option]) => colors[option])) return {};
|
|
31
|
-
let lightest = (colors.lightest ?? _sanity_color.color.white.hex).toLowerCase(), darkest = (colors.darkest ?? _sanity_color.color.black.hex).toLowerCase(), palette = {
|
|
32
|
-
..._sanity_color.color,
|
|
33
|
-
black: darkest,
|
|
34
|
-
white: lightest
|
|
35
|
-
};
|
|
36
|
-
for (let [option, hueKey] of HUE_MAPPING) {
|
|
37
|
-
let mid = colors[option]?.toLowerCase();
|
|
38
|
-
(mid || anchored) && (palette[hueKey] = buildHueTints({
|
|
39
|
-
mid: mid ?? _sanity_color.color[hueKey][500].hex,
|
|
40
|
-
lightest,
|
|
41
|
-
darkest
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
return { palette };
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Generates a Sanity Studio theme from a handful of colors:
|
|
48
|
-
*
|
|
49
|
-
* ```ts
|
|
50
|
-
* import {createTheme} from '@sanity/themer'
|
|
51
|
-
* import {defineConfig} from 'sanity'
|
|
52
|
-
*
|
|
53
|
-
* export default defineConfig({
|
|
54
|
-
* theme: createTheme({primary: '#2276fc'}),
|
|
55
|
-
* // ...rest of the config
|
|
56
|
-
* })
|
|
57
|
-
* ```
|
|
58
|
-
*
|
|
59
|
-
* Calling it without options returns the default Sanity Studio theme.
|
|
60
|
-
*
|
|
61
|
-
* @public
|
|
62
|
-
*/
|
|
63
|
-
function createTheme(colors = {}) {
|
|
64
|
-
return (0, _sanity_ui_theme.buildTheme)(themeConfigFromColors(colors));
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Interpolates a full tint ramp (50–950) from a mid color placed at the 500
|
|
68
|
-
* tint, sliding towards `lightest` and `darkest` at the extremes.
|
|
69
|
-
*/
|
|
70
|
-
function buildHueTints(options) {
|
|
71
|
-
let { mid, lightest, darkest } = options;
|
|
72
|
-
return _sanity_color.COLOR_TINTS.reduce((tints, tintKey) => {
|
|
73
|
-
let tint = Number(tintKey);
|
|
74
|
-
return tint === 500 ? tints[tintKey] = mid : tint < 500 ? tints[tintKey] = require_mix.n(tint / 500, mid, lightest) : tints[tintKey] = require_mix.n((tint - 500) / 500, darkest, mid), tints;
|
|
75
|
-
}, {});
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Preset themes, carried over from the hosted Themer service
|
|
79
|
-
* (themer.sanity.build) and re-expressed as `createTheme` colors.
|
|
80
|
-
*
|
|
81
|
-
* ```ts
|
|
82
|
-
* import {createTheme, presets} from '@sanity/themer'
|
|
83
|
-
*
|
|
84
|
-
* const verdant = presets.find((preset) => preset.slug === 'verdant')
|
|
85
|
-
* const theme = createTheme(verdant.colors)
|
|
86
|
-
* ```
|
|
87
|
-
*
|
|
88
|
-
* @public
|
|
89
|
-
*/
|
|
90
|
-
const presets = [
|
|
91
|
-
{
|
|
92
|
-
slug: "default",
|
|
93
|
-
title: "Studio",
|
|
94
|
-
colors: {}
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
slug: "dew",
|
|
98
|
-
title: "Dew",
|
|
99
|
-
colors: {
|
|
100
|
-
gray: "#5e63b4",
|
|
101
|
-
primary: "#d1a308",
|
|
102
|
-
positive: "#43d675",
|
|
103
|
-
caution: "#fb9f24",
|
|
104
|
-
critical: "#f03e2f",
|
|
105
|
-
lightest: "#fcfcfd",
|
|
106
|
-
darkest: "#0d0d15"
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
slug: "pink-synth",
|
|
111
|
-
title: "Pink Synth",
|
|
112
|
-
colors: {
|
|
113
|
-
gray: "#8b6584",
|
|
114
|
-
primary: "#ec4899",
|
|
115
|
-
positive: "#10b981",
|
|
116
|
-
caution: "#fde047",
|
|
117
|
-
critical: "#fe3459",
|
|
118
|
-
lightest: "#f7f2f5",
|
|
119
|
-
darkest: "#171721"
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
slug: "pixel-art",
|
|
124
|
-
title: "Pixel Art",
|
|
125
|
-
colors: {
|
|
126
|
-
gray: "#57619c",
|
|
127
|
-
primary: "#f10784",
|
|
128
|
-
positive: "#43d675",
|
|
129
|
-
caution: "#fbd024",
|
|
130
|
-
lightest: "#fcfcfd",
|
|
131
|
-
darkest: "#0d0e15"
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
slug: "retro-colonial",
|
|
136
|
-
title: "Retro Colonial",
|
|
137
|
-
colors: {
|
|
138
|
-
gray: "#8bb9b5",
|
|
139
|
-
primary: "#fa7a78",
|
|
140
|
-
positive: "#43d675",
|
|
141
|
-
caution: "#fbd024",
|
|
142
|
-
critical: "#f02f53",
|
|
143
|
-
lightest: "#fcfdfd",
|
|
144
|
-
darkest: "#0d1515"
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
slug: "rosabel",
|
|
149
|
-
title: "Rosabel",
|
|
150
|
-
colors: {
|
|
151
|
-
gray: "#9d8966",
|
|
152
|
-
primary: "#ed2555",
|
|
153
|
-
positive: "#43d675",
|
|
154
|
-
caution: "#fbd024",
|
|
155
|
-
lightest: "#fdfdfc",
|
|
156
|
-
darkest: "#15120d"
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
slug: "stereofidelic",
|
|
161
|
-
title: "Stereofidelic",
|
|
162
|
-
colors: {
|
|
163
|
-
gray: "#678e9a",
|
|
164
|
-
primary: "#f13009",
|
|
165
|
-
positive: "#43d675",
|
|
166
|
-
caution: "#fbd024",
|
|
167
|
-
critical: "#f02f35",
|
|
168
|
-
lightest: "#fcfdfd",
|
|
169
|
-
darkest: "#0e1315"
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
slug: "tw-cyan",
|
|
174
|
-
title: "Tailwind Cyan",
|
|
175
|
-
colors: {
|
|
176
|
-
gray: "#677389",
|
|
177
|
-
primary: "#51b4d0",
|
|
178
|
-
positive: "#55b785",
|
|
179
|
-
caution: "#e2b53e",
|
|
180
|
-
critical: "#e14f62",
|
|
181
|
-
lightest: "#f9fafb",
|
|
182
|
-
darkest: "#101728"
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
slug: "verdant",
|
|
187
|
-
title: "Verdant",
|
|
188
|
-
colors: {
|
|
189
|
-
gray: "#5c9199",
|
|
190
|
-
primary: "#1cb485",
|
|
191
|
-
positive: "#43d675",
|
|
192
|
-
caution: "#fbd024",
|
|
193
|
-
lightest: "#fcfdfd",
|
|
194
|
-
darkest: "#0d1415"
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
];
|
|
198
|
-
Object.defineProperty(exports, "n", {
|
|
199
|
-
enumerable: !0,
|
|
200
|
-
get: function() {
|
|
201
|
-
return createTheme;
|
|
202
|
-
}
|
|
203
|
-
}), Object.defineProperty(exports, "r", {
|
|
204
|
-
enumerable: !0,
|
|
205
|
-
get: function() {
|
|
206
|
-
return themeConfigFromColors;
|
|
207
|
-
}
|
|
208
|
-
}), Object.defineProperty(exports, "t", {
|
|
209
|
-
enumerable: !0,
|
|
210
|
-
get: function() {
|
|
211
|
-
return presets;
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
//# sourceMappingURL=presets.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"presets.cjs","names":["isColor","color","COLOR_TINTS","mix"],"sources":["../../src/createTheme.ts","../../src/presets.ts"],"sourcesContent":["import {color, COLOR_TINTS, ColorHueKey, ColorTintKey} from '@sanity/color'\nimport {buildTheme, RootTheme, ThemeColorPalette, ThemeConfig} from '@sanity/ui/theme'\n\nimport {isColor, mix} from './lib/mix'\nimport {CreateThemeOptions} from './types'\n\n/** The palette hue that each themeable color drives */\nconst HUE_MAPPING: ReadonlyArray<[option: keyof CreateThemeOptions, hueKey: ColorHueKey]> = [\n ['gray', 'gray'],\n ['primary', 'blue'],\n ['positive', 'green'],\n ['caution', 'yellow'],\n ['critical', 'red'],\n]\n\n/**\n * Maps themeable colors to a `@sanity/ui` `ThemeConfig`, for when a theme\n * needs further customization than `createTheme` exposes:\n *\n * ```ts\n * import {themeConfigFromColors} from '@sanity/themer'\n * import {buildTheme} from '@sanity/ui/theme'\n *\n * const theme = buildTheme({\n * ...themeConfigFromColors({primary: '#2276fc'}),\n * // ...other ThemeConfig properties\n * })\n * ```\n *\n * @public\n */\nexport function themeConfigFromColors(colors: CreateThemeOptions): ThemeConfig {\n for (const [key, value] of Object.entries(colors)) {\n if (typeof value === 'string' && !isColor(value)) {\n throw new TypeError(\n `Invalid color for ${JSON.stringify(key)}: ${JSON.stringify(value)} — expected a hex color`,\n )\n }\n }\n\n const anchored = Boolean(colors.lightest || colors.darkest)\n\n if (!anchored && !HUE_MAPPING.some(([option]) => colors[option])) {\n return {}\n }\n\n const lightest = (colors.lightest ?? color.white.hex).toLowerCase()\n const darkest = (colors.darkest ?? color.black.hex).toLowerCase()\n\n const palette: ThemeColorPalette = {...color, black: darkest, white: lightest}\n\n for (const [option, hueKey] of HUE_MAPPING) {\n const mid = colors[option]?.toLowerCase()\n\n // Untouched ramps only need regenerating when the surface endpoints moved\n if (mid || anchored) {\n palette[hueKey] = buildHueTints({\n mid: mid ?? color[hueKey][500].hex,\n lightest,\n darkest,\n })\n }\n }\n\n return {palette}\n}\n\n/**\n * Generates a Sanity Studio theme from a handful of colors:\n *\n * ```ts\n * import {createTheme} from '@sanity/themer'\n * import {defineConfig} from 'sanity'\n *\n * export default defineConfig({\n * theme: createTheme({primary: '#2276fc'}),\n * // ...rest of the config\n * })\n * ```\n *\n * Calling it without options returns the default Sanity Studio theme.\n *\n * @public\n */\nexport function createTheme(colors: CreateThemeOptions = {}): RootTheme {\n return buildTheme(themeConfigFromColors(colors))\n}\n\n/**\n * Interpolates a full tint ramp (50–950) from a mid color placed at the 500\n * tint, sliding towards `lightest` and `darkest` at the extremes.\n */\nfunction buildHueTints(options: {\n mid: string\n lightest: string\n darkest: string\n}): Record<ColorTintKey, string> {\n const {mid, lightest, darkest} = options\n\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- the reduce assigns every COLOR_TINTS key, so the Partial is complete\n return COLOR_TINTS.reduce<Partial<Record<ColorTintKey, string>>>((tints, tintKey) => {\n const tint = Number(tintKey)\n\n if (tint === 500) {\n tints[tintKey] = mid\n } else if (tint < 500) {\n tints[tintKey] = mix(tint / 500, mid, lightest)\n } else {\n tints[tintKey] = mix((tint - 500) / 500, darkest, mid)\n }\n\n return tints\n }, {}) as Record<ColorTintKey, string>\n}\n","import {CreateThemeOptions} from './types'\n\n/**\n * A named set of colors for `createTheme`.\n *\n * @public\n */\nexport interface ThemePreset {\n slug: string\n title: string\n colors: CreateThemeOptions\n}\n\n/**\n * Preset themes, carried over from the hosted Themer service\n * (themer.sanity.build) and re-expressed as `createTheme` colors.\n *\n * ```ts\n * import {createTheme, presets} from '@sanity/themer'\n *\n * const verdant = presets.find((preset) => preset.slug === 'verdant')\n * const theme = createTheme(verdant.colors)\n * ```\n *\n * @public\n */\nexport const presets: ThemePreset[] = [\n {\n slug: 'default',\n title: 'Studio',\n colors: {},\n },\n {\n slug: 'dew',\n title: 'Dew',\n colors: {\n gray: '#5e63b4',\n primary: '#d1a308',\n positive: '#43d675',\n caution: '#fb9f24',\n critical: '#f03e2f',\n lightest: '#fcfcfd',\n darkest: '#0d0d15',\n },\n },\n {\n slug: 'pink-synth',\n title: 'Pink Synth',\n colors: {\n gray: '#8b6584',\n primary: '#ec4899',\n positive: '#10b981',\n caution: '#fde047',\n critical: '#fe3459',\n lightest: '#f7f2f5',\n darkest: '#171721',\n },\n },\n {\n slug: 'pixel-art',\n title: 'Pixel Art',\n colors: {\n gray: '#57619c',\n primary: '#f10784',\n positive: '#43d675',\n caution: '#fbd024',\n lightest: '#fcfcfd',\n darkest: '#0d0e15',\n },\n },\n {\n slug: 'retro-colonial',\n title: 'Retro Colonial',\n colors: {\n gray: '#8bb9b5',\n primary: '#fa7a78',\n positive: '#43d675',\n caution: '#fbd024',\n critical: '#f02f53',\n lightest: '#fcfdfd',\n darkest: '#0d1515',\n },\n },\n {\n slug: 'rosabel',\n title: 'Rosabel',\n colors: {\n gray: '#9d8966',\n primary: '#ed2555',\n positive: '#43d675',\n caution: '#fbd024',\n lightest: '#fdfdfc',\n darkest: '#15120d',\n },\n },\n {\n slug: 'stereofidelic',\n title: 'Stereofidelic',\n colors: {\n gray: '#678e9a',\n primary: '#f13009',\n positive: '#43d675',\n caution: '#fbd024',\n critical: '#f02f35',\n lightest: '#fcfdfd',\n darkest: '#0e1315',\n },\n },\n {\n slug: 'tw-cyan',\n title: 'Tailwind Cyan',\n colors: {\n gray: '#677389',\n primary: '#51b4d0',\n positive: '#55b785',\n caution: '#e2b53e',\n critical: '#e14f62',\n lightest: '#f9fafb',\n darkest: '#101728',\n },\n },\n {\n slug: 'verdant',\n title: 'Verdant',\n colors: {\n gray: '#5c9199',\n primary: '#1cb485',\n positive: '#43d675',\n caution: '#fbd024',\n lightest: '#fcfdfd',\n darkest: '#0d1415',\n },\n },\n]\n"],"mappings":";;;AAOA,MAAM,cAAsF;CAC1F,CAAC,QAAQ,MAAM;CACf,CAAC,WAAW,MAAM;CAClB,CAAC,YAAY,OAAO;CACpB,CAAC,WAAW,QAAQ;CACpB,CAAC,YAAY,KAAK;AACpB;;;;;;;;;;;;;;;;;AAkBA,SAAgB,sBAAsB,QAAyC;CAC7E,KAAK,IAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,OAAO,SAAU,YAAY,CAACA,YAAAA,EAAQ,KAAK,GAC7C,MAAU,UACR,qBAAqB,KAAK,UAAU,GAAG,EAAE,IAAI,KAAK,UAAU,KAAK,EAAE,wBACrE;CAIJ,IAAM,WAAW,GAAQ,OAAO,YAAY,OAAO;CAEnD,IAAI,CAAC,YAAY,CAAC,YAAY,MAAM,CAAC,YAAY,OAAO,OAAO,GAC7D,OAAO,CAAC;CAGV,IAAM,YAAY,OAAO,YAAYC,cAAAA,MAAM,MAAM,IAAA,CAAK,YAAY,GAC5D,WAAW,OAAO,WAAWA,cAAAA,MAAM,MAAM,IAAA,CAAK,YAAY,GAE1D,UAA6B;EAAC,GAAGA,cAAAA;EAAO,OAAO;EAAS,OAAO;CAAQ;CAE7E,KAAK,IAAM,CAAC,QAAQ,WAAW,aAAa;EAC1C,IAAM,MAAM,OAAO,OAAO,EAAE,YAAY;EAGxC,CAAI,OAAO,cACT,QAAQ,UAAU,cAAc;GAC9B,KAAK,OAAOA,cAAAA,MAAM,OAAO,CAAC,IAAI,CAAC;GAC/B;GACA;EACF,CAAC;CAEL;CAEA,OAAO,EAAC,QAAO;AACjB;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,YAAY,SAA6B,CAAC,GAAc;CACtE,QAAA,GAAA,iBAAA,WAAA,CAAkB,sBAAsB,MAAM,CAAC;AACjD;;;;;AAMA,SAAS,cAAc,SAIU;CAC/B,IAAM,EAAC,KAAK,UAAU,YAAW;CAGjC,OAAOC,cAAAA,YAAY,QAA+C,OAAO,YAAY;EACnF,IAAM,OAAO,OAAO,OAAO;EAU3B,OARI,SAAS,MACX,MAAM,WAAW,MACR,OAAO,MAChB,MAAM,WAAWC,YAAAA,EAAI,OAAO,KAAK,KAAK,QAAQ,IAE9C,MAAM,WAAWA,YAAAA,GAAK,OAAO,OAAO,KAAK,SAAS,GAAG,GAGhD;CACT,GAAG,CAAC,CAAC;AACP;;;;;;;;;;;;;;ACvFA,MAAa,UAAyB;CACpC;EACE,MAAM;EACN,OAAO;EACP,QAAQ,CAAC;CACX;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,UAAU;GACV,SAAS;EACX;CACF;CACA;EACE,MAAM;EACN,OAAO;EACP,QAAQ;GACN,MAAM;GACN,SAAS;GACT,UAAU;GACV,SAAS;GACT,UAAU;GACV,SAAS;EACX;CACF;AACF"}
|