@sanity/themer

0.8.00.8.1
dist/presets-CqBgS3A-.js.map
~dist/presets-CqBgS3A-.js.mapModified
+1−1
Index: package/dist/presets-CqBgS3A-.js.map
===================================================================
--- package/dist/presets-CqBgS3A-.js.map
+++ package/dist/presets-CqBgS3A-.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"presets-CqBgS3A-.js","names":["buildTheme","buildUITheme"],"sources":["../src/theme/hsl.ts","../src/lib/mix.ts","../src/theme/options.ts","../src/theme/buildPalette.ts","../src/theme/buildTheme.ts","../src/theme/presets.ts"],"sourcesContent":["/**\n * Color math for the palette generator, kept at full float precision: unlike\n * the HSL helpers in `@sanity/ui/theme`, nothing is rounded between the two\n * conversions, so `hslToHex(hexToHsl(hex))` returns `hex` unchanged for every\n * color. `buildTheme` relies on that to reproduce the stock `@sanity/color`\n * palette byte-for-byte when it is called with the stock anchor colors.\n */\n\n/**\n * A color in HSL space: `h` in degrees within `[0, 360)`, `s` and `l` as\n * fractions within `[0, 1]`.\n *\n * @internal\n */\nexport interface Hsl {\n  h: number\n  s: number\n  l: number\n}\n\n/** @internal */\nexport function hexToHsl(hex: string): Hsl {\n  const [r, g, b] = parseHex(hex)\n\n  const max = Math.max(r, g, b)\n  const min = Math.min(r, g, b)\n  const delta = max - min\n\n  const l = (max + min) / 2\n\n  if (delta === 0) {\n    return {h: 0, s: 0, l}\n  }\n\n  const s = delta / (1 - Math.abs(2 * l - 1))\n\n  let h: number\n\n  if (max === r) {\n    h = ((g - b) / delta) % 6\n  } else if (max === g) {\n    h = (b - r) / delta + 2\n  } else {\n    h = (r - g) / delta + 4\n  }\n\n  return {h: normalizeHue(h * 60), s, l}\n}\n\n/** @internal */\nexport function hslToHex(hsl: Hsl): string {\n  const h = normalizeHue(hsl.h)\n  const s = clamp01(hsl.s)\n  const l = clamp01(hsl.l)\n\n  const c = (1 - Math.abs(2 * l - 1)) * s\n  const x = c * (1 - Math.abs(((h / 60) % 2) - 1))\n  const m = l - c / 2\n\n  let r = 0\n  let g = 0\n  let b = 0\n\n  if (h < 60) {\n    r = c\n    g = x\n  } else if (h < 120) {\n    r = x\n    g = c\n  } else if (h < 180) {\n    g = c\n    b = x\n  } else if (h < 240) {\n    g = x\n    b = c\n  } else if (h < 300) {\n    r = x\n    b = c\n  } else {\n    r = c\n    b = x\n  }\n\n  return `#${channelToHex(r + m)}${channelToHex(g + m)}${channelToHex(b + m)}`\n}\n\n/**\n * Rotates `from` towards `to` along the shortest arc of the hue circle.\n *\n * @internal\n */\nexport function mixHue(from: number, to: number, amount: number): number {\n  const delta = ((((to - from) % 360) + 540) % 360) - 180\n\n  return normalizeHue(from + delta * amount)\n}\n\n/**\n * The WCAG relative luminance of a hex color, between 0 (black) and 1 (white).\n *\n * @internal\n */\nexport function relativeLuminance(hex: string): number {\n  const [r, g, b] = parseHex(hex)\n\n  return 0.2126 * linearChannel(r) + 0.7152 * linearChannel(g) + 0.0722 * linearChannel(b)\n}\n\nfunction linearChannel(value: number): number {\n  return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4\n}\n\n/** Parses `#abc` and `#aabbcc` hex colors into channel fractions of 1 */\nfunction parseHex(hex: string): [number, number, number] {\n  const expanded =\n    hex.length === 4 ? `${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex.slice(1)\n\n  return [\n    parseInt(expanded.slice(0, 2), 16) / 255,\n    parseInt(expanded.slice(2, 4), 16) / 255,\n    parseInt(expanded.slice(4, 6), 16) / 255,\n  ]\n}\n\nfunction channelToHex(value: number): string {\n  return Math.round(clamp01(value) * 255)\n    .toString(16)\n    .padStart(2, '0')\n}\n\nfunction normalizeHue(hue: number): number {\n  return ((hue % 360) + 360) % 360\n}\n\nfunction clamp01(value: number): number {\n  return Math.min(1, Math.max(0, value))\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 * The `mix` function this module was named for moved to `@sanity/themer-legacy`\n * along with the legacy generator; `isColor` stays here for `theme/options.ts`\n * and `tool/storage.ts`.\n *\n * @internal\n */\nexport function isColor(input: string): boolean {\n  return /^#(?:[0-9a-f]{3}){1,2}$/i.test(input)\n}\n","import {black, blue, gray, white} from '@sanity/color'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\n\nimport {isColor} from '../lib/mix'\nimport {hexToHsl, hslToHex} from './hsl'\n\n/**\n * The colors of one color scheme, for {@link BuildThemeOptions}. Every color\n * is a hex color (`#rgb` or `#rrggbb`), and everything is optional: omitted\n * options fall back to the stock Studio colors, so an empty object reproduces\n * the stock scheme exactly.\n *\n * @public\n */\nexport interface SchemeThemeOptions {\n  /**\n   * The accent color — the brand color of the scheme. Replaces the `blue`\n   * scale of the palette, which Sanity UI uses for primary buttons, focus\n   * rings and links.\n   *\n   * The stock accent is `#556bfc` (`blue/500` of `@sanity/color`).\n   */\n  accent?: string\n\n  /**\n   * The background of the scheme — every other color of the scheme is\n   * blended onto it. The dark scheme's background replaces `black` in the\n   * palette and the light scheme's replaces `white`.\n   *\n   * It is kept far enough from the text and accent colors to stay usable:\n   * a dark background is made darker until it has enough contrast with them\n   * (it can never be lighter than either), and a light background can never\n   * be darker than either.\n   *\n   * The stock backgrounds are `#0d0e12` (dark) and `#ffffff` (light).\n   */\n  background?: string\n\n  /**\n   * How strongly text and borders separate from the accent color, between 15\n   * and 100. The default is 85, which uses the text color as-is. Above 85 the\n   * text scale loses its tint until it is fully neutral at 100 — a high\n   * contrast scheme with no mixing of the text and accent colors. Below 85\n   * more and more of the accent color mixes into the text scale, giving text\n   * and borders more color, until the scale fully adopts the accent hue and\n   * saturation at 15.\n   */\n  contrast?: number\n\n  /**\n   * The text color. Replaces the `gray` scale of the palette, which Sanity UI\n   * uses for text, icons, borders and neutral surfaces. When omitted, it is\n   * derived from the accent color: a mostly desaturated version of it, the\n   * way the stock `gray` scale carries a hint of the stock blue.\n   *\n   * The stock text color is `#727892` (`gray/500` of `@sanity/color`).\n   */\n  text?: string\n}\n\n/**\n * Options for {@link buildTheme} and {@link buildPalette}: the colors of the\n * dark and the light scheme, each with its own accent, text, background and\n * contrast — so the two schemes can differ in more than their background.\n * Both schemes are optional, and so is every color: whatever is omitted\n * falls back to the stock Studio colors, so `buildTheme({})` matches\n * `buildTheme()` from `@sanity/ui/theme` exactly.\n *\n * @public\n */\nexport interface BuildThemeOptions {\n  /** The colors of the dark scheme */\n  dark?: SchemeThemeOptions\n  /** The colors of the light scheme */\n  light?: SchemeThemeOptions\n}\n\n/**\n * {@link SchemeThemeOptions} with every option filled in: colors normalized\n * to lowercase `#rrggbb`, the text color derived from the accent when it was\n * omitted, and the contrast clamped into its valid range.\n *\n * @internal\n */\nexport interface ResolvedSchemeOptions {\n  accent: string\n  background: string\n  contrast: number\n  text: string\n}\n\n/** {@link BuildThemeOptions} with both schemes resolved @internal */\nexport type ResolvedThemeOptions = Record<ThemeColorSchemeKey, ResolvedSchemeOptions>\n\n/** The color schemes, in the order the tool presents them @internal */\nexport const SCHEMES: ThemeColorSchemeKey[] = ['light', 'dark']\n\n/** The stock accent color — `blue/500` of `@sanity/color` @internal */\nexport const DEFAULT_ACCENT: string = blue[500].hex\n\n/** The stock text color — `gray/500` of `@sanity/color` @internal */\nexport const DEFAULT_TEXT: string = gray[500].hex\n\n/** The stock backgrounds — `black` and `white` of `@sanity/color` @internal */\nexport const DEFAULT_BACKGROUND: Record<ThemeColorSchemeKey, string> = {\n  dark: black.hex,\n  light: white.hex,\n}\n\n/** The contrast that applies the text color as-is @internal */\nexport const DEFAULT_CONTRAST = 85\n\n/** @internal */\nexport const MINIMUM_CONTRAST = 15\n\n/** @internal */\nexport const MAXIMUM_CONTRAST = 100\n\n/** The keys of the options shape before they were grouped by scheme */\nconst FLAT_OPTION_KEYS = ['accent', 'text', 'background', 'contrast']\n\n/** @internal */\nexport function resolveThemeOptions(options: BuildThemeOptions = {}): ResolvedThemeOptions {\n  if (FLAT_OPTION_KEYS.some((key) => key in options)) {\n    throw new TypeError(\n      'The `buildTheme` options are grouped by color scheme: pass `{light: {accent, text, background, contrast}, dark: {…}}` instead of one set of colors for both',\n    )\n  }\n\n  return {\n    dark: resolveSchemeOptions(options.dark ?? {}, 'dark'),\n    light: resolveSchemeOptions(options.light ?? {}, 'light'),\n  }\n}\n\nfunction resolveSchemeOptions(\n  options: SchemeThemeOptions,\n  scheme: ThemeColorSchemeKey,\n): ResolvedSchemeOptions {\n  const accent =\n    options.accent === undefined\n      ? DEFAULT_ACCENT\n      : normalizeColor(options.accent, `${scheme}.accent`)\n\n  return {\n    accent,\n    background:\n      options.background === undefined\n        ? DEFAULT_BACKGROUND[scheme]\n        : normalizeColor(options.background, `${scheme}.background`),\n    contrast: normalizeContrast(options.contrast, scheme),\n    text:\n      options.text === undefined\n        ? deriveTextColor(accent)\n        : normalizeColor(options.text, `${scheme}.text`),\n  }\n}\n\n/**\n * Derives the text color from an accent color, keeping the relationship the\n * stock palette has between `gray/500` and `blue/500`: the text color takes\n * the accent's hue (offset the way the stock gray is offset from the stock\n * blue), carries about an eighth of its saturation, and keeps the stock text\n * lightness. Deriving from the stock accent returns the stock text color.\n *\n * @internal\n */\nexport function deriveTextColor(accent: string): string {\n  const accentHsl = hexToHsl(normalizeColor(accent, 'accent'))\n  const defaultAccent = hexToHsl(DEFAULT_ACCENT)\n  const defaultText = hexToHsl(DEFAULT_TEXT)\n\n  return hslToHex({\n    h: defaultText.h + (accentHsl.h - defaultAccent.h),\n    s: Math.min(1, defaultText.s * (accentHsl.s / defaultAccent.s)),\n    l: defaultText.l,\n  })\n}\n\nfunction normalizeColor(value: string, name: string): string {\n  if (typeof value !== 'string' || !isColor(value)) {\n    throw new TypeError(\n      `Invalid \\`${name}\\` color: ${JSON.stringify(value)} — expected a hex color like #556bfc`,\n    )\n  }\n\n  const lower = value.toLowerCase()\n\n  return lower.length === 4\n    ? `#${lower[1]}${lower[1]}${lower[2]}${lower[2]}${lower[3]}${lower[3]}`\n    : lower\n}\n\nfunction normalizeContrast(value: number | undefined, scheme: ThemeColorSchemeKey): number {\n  if (value === undefined) {\n    return DEFAULT_CONTRAST\n  }\n\n  if (typeof value !== 'number' || !Number.isFinite(value)) {\n    throw new TypeError(\n      `Invalid \\`${scheme}.contrast\\`: ${JSON.stringify(value)} — expected a number between ${MINIMUM_CONTRAST} and ${MAXIMUM_CONTRAST}`,\n    )\n  }\n\n  return Math.min(MAXIMUM_CONTRAST, Math.max(MINIMUM_CONTRAST, value))\n}\n","import {color, COLOR_TINTS, ColorHueKey, ColorTintKey, ColorTints} from '@sanity/color'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\n\nimport {hexToHsl, Hsl, hslToHex, mixHue, relativeLuminance} from './hsl'\nimport {\n  BuildThemeOptions,\n  DEFAULT_ACCENT,\n  DEFAULT_CONTRAST,\n  DEFAULT_TEXT,\n  MAXIMUM_CONTRAST,\n  MINIMUM_CONTRAST,\n  ResolvedSchemeOptions,\n  resolveThemeOptions,\n} from './options'\n\n/**\n * The lightness band the accent and text colors are clamped into — anchors\n * outside it would squeeze most of their scale's tints into an\n * indistinguishable sliver, messing with the rest of the scale.\n */\nconst MINIMUM_ANCHOR_LIGHTNESS = 0.25\nconst MAXIMUM_ANCHOR_LIGHTNESS = 0.75\n\n/**\n * The contrast ratio the dark background must reach against the 400 tints of\n * the text and accent scales — the tints Sanity UI paints muted text and\n * solid buttons with on dark backgrounds. The stock palette sits at ~6.8.\n */\nconst MINIMUM_DARK_BACKGROUND_CONTRAST = 4.5\n\n/** How much lightness each step of a background adjustment removes or adds */\nconst BACKGROUND_LIGHTNESS_STEP = 0.005\n\n/**\n * A color palette generated by {@link buildPalette}: the `palette` config of\n * `buildTheme` from `@sanity/ui/theme`, with every color as a hex string.\n *\n * @public\n */\nexport type GeneratedColorPalette = {black: string; white: string} & Record<\n  ColorHueKey,\n  Record<ColorTintKey, string>\n>\n\n/**\n * The palettes generated by {@link buildPalette} — one per color scheme.\n *\n * @public\n */\nexport type GeneratedColorPalettes = Record<ThemeColorSchemeKey, GeneratedColorPalette>\n\n/**\n * Generates a Sanity UI color palette for each color scheme from the theme\n * options: in each palette the scheme's accent color replaces the `blue`\n * scale, its text color the `gray` scale, and the backgrounds replace `black`\n * and `white`. All other hues keep their stock `@sanity/color` values. Called\n * with the stock colors, both palettes come back as the stock palette\n * byte-for-byte.\n *\n * ```ts\n * import {buildPalette} from '@sanity/themer'\n *\n * const {light, dark} = buildPalette({light: {accent: '#556bfc'}})\n * ```\n *\n * @public\n */\nexport function buildPalette(options: BuildThemeOptions = {}): GeneratedColorPalettes {\n  const resolved = resolveThemeOptions(options)\n\n  return {\n    dark: buildSchemePalette('dark', resolved.dark, resolved.light.background),\n    light: buildSchemePalette('light', resolved.light, resolved.dark.background),\n  }\n}\n\n/**\n * Generates the palette of one scheme. The scheme's own background takes the\n * slot the scheme paints with (`black` for dark, `white` for light), while\n * the other slot — which a scheme only touches for a few inverted details —\n * takes the other scheme's background, so the theme stays one palette.\n */\nfunction buildSchemePalette(\n  key: ThemeColorSchemeKey,\n  scheme: ResolvedSchemeOptions,\n  otherBackground: string,\n): GeneratedColorPalette {\n  const accentAnchor = clampAnchorLightness(hexToHsl(scheme.accent))\n  const textAnchor = clampAnchorLightness(hexToHsl(scheme.text))\n  const grayAnchor = applyContrast(textAnchor, accentAnchor, scheme.contrast)\n\n  const blueTints = remapTints(color.blue, hexToHsl(DEFAULT_ACCENT), accentAnchor)\n  const grayTints = remapTints(color.gray, hexToHsl(DEFAULT_TEXT), grayAnchor)\n\n  const anchorLuminances = [\n    relativeLuminance(hslToHex(grayAnchor)),\n    relativeLuminance(hslToHex(accentAnchor)),\n  ]\n\n  const darkBackground = key === 'dark' ? scheme.background : otherBackground\n  const lightBackground = key === 'light' ? scheme.background : otherBackground\n\n  return {\n    black: darkenBackground(darkBackground, {\n      anchorLuminances,\n      tints: [grayTints['400'], blueTints['400']],\n    }),\n    white: lightenBackground(lightBackground, anchorLuminances),\n    gray: grayTints,\n    blue: blueTints,\n    purple: tintHexes(color.purple),\n    magenta: tintHexes(color.magenta),\n    red: tintHexes(color.red),\n    orange: tintHexes(color.orange),\n    yellow: tintHexes(color.yellow),\n    green: tintHexes(color.green),\n    cyan: tintHexes(color.cyan),\n  }\n}\n\n/**\n * Mixes the accent color into the text color according to the contrast: 85\n * applies the text color as-is, 100 removes its tint entirely, and lower\n * values rotate and saturate it towards the accent.\n */\nfunction applyContrast(text: Hsl, accent: Hsl, contrast: number): Hsl {\n  if (contrast === DEFAULT_CONTRAST) {\n    return text\n  }\n\n  if (contrast > DEFAULT_CONTRAST) {\n    const amount = (contrast - DEFAULT_CONTRAST) / (MAXIMUM_CONTRAST - DEFAULT_CONTRAST)\n\n    return {h: text.h, s: text.s * (1 - amount), l: text.l}\n  }\n\n  const amount = (DEFAULT_CONTRAST - contrast) / (DEFAULT_CONTRAST - MINIMUM_CONTRAST)\n\n  return {\n    h: mixHue(text.h, accent.h, amount),\n    s: text.s + (accent.s - text.s) * amount,\n    l: text.l,\n  }\n}\n\n/**\n * Rebuilds a stock tint scale around a new anchor color, where `from` is the\n * scale's stock 500 tint: hues rotate along, saturation scales\n * proportionally, and lightness is remapped piecewise so the anchor takes the\n * new lightness while the scale keeps spanning light to dark. When the anchor\n * matches the stock one, every tint comes back unchanged.\n */\nfunction remapTints(tints: ColorTints, from: Hsl, to: Hsl): Record<ColorTintKey, string> {\n  const rotation = to.h - from.h\n  const result: Partial<Record<ColorTintKey, string>> = {}\n\n  for (const tint of COLOR_TINTS) {\n    const value = hexToHsl(tints[tint].hex)\n\n    result[tint] = hslToHex({\n      h: value.h + rotation,\n      s: remapSaturation(value.s, from.s, to.s),\n      l: remapLightness(value.l, from.l, to.l),\n    })\n  }\n\n  // oxlint-disable-next-line no-unsafe-type-assertion -- the loop assigns every tint key\n  return result as Record<ColorTintKey, string>\n}\n\nfunction remapSaturation(value: number, from: number, to: number): number {\n  if (from === to) {\n    return value\n  }\n\n  return Math.min(1, value * (to / from))\n}\n\nfunction remapLightness(value: number, from: number, to: number): number {\n  if (from === to) {\n    return value\n  }\n\n  if (value <= from) {\n    return value * (to / from)\n  }\n\n  return to + ((value - from) * (1 - to)) / (1 - from)\n}\n\nfunction clampAnchorLightness(anchor: Hsl): Hsl {\n  const l = Math.min(MAXIMUM_ANCHOR_LIGHTNESS, Math.max(MINIMUM_ANCHOR_LIGHTNESS, anchor.l))\n\n  return l === anchor.l ? anchor : {...anchor, l}\n}\n\n/**\n * Enforces the dark background rules: it can never be lighter than the text\n * or accent colors, and it must reach enough contrast with the 400 tints of\n * their scales — it is made darker until it does (or bottoms out at black).\n */\nfunction darkenBackground(\n  hex: string,\n  rules: {anchorLuminances: number[]; tints: string[]},\n): string {\n  const maximumLuminance = Math.min(...rules.anchorLuminances)\n  const tintLuminances = rules.tints.map((tint) => relativeLuminance(tint))\n\n  const isDarkEnough = (background: string): boolean => {\n    const luminance = relativeLuminance(background)\n\n    return (\n      luminance < maximumLuminance &&\n      tintLuminances.every(\n        (tintLuminance) =>\n          (tintLuminance + 0.05) / (luminance + 0.05) >= MINIMUM_DARK_BACKGROUND_CONTRAST,\n      )\n    )\n  }\n\n  const {h, s, l} = hexToHsl(hex)\n  let lightness = l\n  let current = hex\n\n  while (!isDarkEnough(current) && lightness > 0) {\n    lightness = Math.max(0, lightness - BACKGROUND_LIGHTNESS_STEP)\n    current = hslToHex({h, s, l: lightness})\n  }\n\n  return current\n}\n\n/**\n * Enforces the light background rule: it can never be darker than the text\n * or accent colors — it is made lighter until it is (or tops out at white).\n */\nfunction lightenBackground(hex: string, anchorLuminances: number[]): string {\n  const minimumLuminance = Math.max(...anchorLuminances)\n\n  const {h, s, l} = hexToHsl(hex)\n  let lightness = l\n  let current = hex\n\n  while (relativeLuminance(current) <= minimumLuminance && lightness < 1) {\n    lightness = Math.min(1, lightness + BACKGROUND_LIGHTNESS_STEP)\n    current = hslToHex({h, s, l: lightness})\n  }\n\n  return current\n}\n\nfunction tintHexes(tints: ColorTints): Record<ColorTintKey, string> {\n  const result: Partial<Record<ColorTintKey, string>> = {}\n\n  for (const tint of COLOR_TINTS) {\n    result[tint] = tints[tint].hex\n  }\n\n  // oxlint-disable-next-line no-unsafe-type-assertion -- the loop assigns every tint key\n  return result as Record<ColorTintKey, string>\n}\n","import {\n  buildTheme as buildUITheme,\n  RootTheme,\n  ThemeColorSchemes_v2,\n  v0_v2,\n  v2_v0,\n} from '@sanity/ui/theme'\n\nimport {buildPalette} from './buildPalette'\nimport {BuildThemeOptions} from './options'\n\n/**\n * Generates a Studio theme from a handful of colors per color scheme, by\n * replacing the color palette that the `buildTheme` from `@sanity/ui/theme`\n * otherwise fills with `@sanity/color`: in each scheme the accent color\n * replaces the `blue` scale (primary buttons, focus rings, links), the\n * optional text color the `gray` scale (text, icons, borders), and the\n * optional background replaces `black` (dark) or `white` (light). The result\n * is the same type of theme that `@sanity/ui/theme` builds, ready for the\n * `theme` property of a Studio config.\n *\n * ```ts\n * import {buildTheme} from '@sanity/themer'\n * import {defineConfig} from 'sanity'\n *\n * export const theme = buildTheme({\n *   light: {\n *     accent: '#556bfc',\n *     text: '#727892', // optional — derived from `accent` when omitted\n *     background: '#ffffff', // optional\n *     contrast: 85, // optional, 15–100\n *   },\n *   dark: {\n *     accent: '#556bfc',\n *     background: '#0d0e12',\n *   },\n * })\n *\n * export default defineConfig({\n *   theme,\n *   // ...rest of the config\n * })\n * ```\n *\n * Every option is optional and falls back to the stock Studio colors: called\n * with the stock colors — like the example — or with no options at all, it\n * returns the exact same colors as `buildTheme()` from `@sanity/ui/theme`.\n *\n * @public\n */\nexport function buildTheme(options: BuildThemeOptions = {}): RootTheme {\n  const palettes = buildPalette(options)\n\n  // Sanity UI renders both schemes of a theme from one palette, so each\n  // scheme gets a theme of its own palette, and the two are composed into one\n  // theme that takes its light scheme from the one and its dark scheme from\n  // the other. The scheme getters keep Sanity UI's lazy rendering: a scheme is\n  // only computed once something reads it.\n  const light = v0_v2(buildUITheme({palette: palettes.light}))\n  const dark = v0_v2(buildUITheme({palette: palettes.dark}))\n\n  const color: ThemeColorSchemes_v2 = {\n    get light() {\n      return light.color.light\n    },\n    get dark() {\n      return dark.color.dark\n    },\n  }\n\n  return v2_v0({...light, color})\n}\n","import {BuildThemeOptions} from './options'\n\n/**\n * A preset theme: a named set of {@link BuildThemeOptions} ready to pass to\n * `buildTheme`.\n *\n * @public\n */\nexport interface ThemePreset {\n  slug: string\n  title: string\n  /** The preset's theme options, ready to pass to `buildTheme` */\n  options: BuildThemeOptions\n}\n\n/**\n * The hosted Themer presets had one accent and one text color for both\n * schemes, and a background per scheme\n */\nfunction scheme(accent: string, text: string, backgrounds: {dark: string; light: string}) {\n  return {\n    dark: {accent, text, background: backgrounds.dark},\n    light: {accent, text, background: backgrounds.light},\n  } satisfies BuildThemeOptions\n}\n\n/**\n * Preset themes for `buildTheme`, carried over from the hosted Themer service\n * (themer.sanity.build) presets: each one maps the legacy preset's primary\n * hue to `accent`, its default hue to `text` and its lightest/darkest colors\n * to the backgrounds of the light and dark scheme.\n *\n * ```ts\n * import {buildTheme, presets} from '@sanity/themer'\n *\n * const verdant = presets.find((preset) => preset.slug === 'verdant')\n * const theme = buildTheme(verdant.options)\n * ```\n *\n * @public\n */\nexport const presets: ThemePreset[] = [\n  {\n    slug: 'studio',\n    title: 'Studio',\n    options: {},\n  },\n  {\n    slug: 'dew',\n    title: 'Dew',\n    options: scheme('#d1a308', '#5e63b4', {dark: '#0d0d15', light: '#fcfcfd'}),\n  },\n  {\n    slug: 'pink-synth',\n    title: 'Pink Synth',\n    options: scheme('#ec4899', '#8b6584', {dark: '#171721', light: '#f7f2f5'}),\n  },\n  {\n    slug: 'pixel-art',\n    title: 'Pixel Art',\n    options: scheme('#f10784', '#57619c', {dark: '#0d0e15', light: '#fcfcfd'}),\n  },\n  {\n    slug: 'retro-colonial',\n    title: 'Retro Colonial',\n    options: scheme('#fa7a78', '#8bb9b5', {dark: '#0d1515', light: '#fcfdfd'}),\n  },\n  {\n    slug: 'rosabel',\n    title: 'Rosabel',\n    options: scheme('#ed2555', '#9d8966', {dark: '#15120d', light: '#fdfdfc'}),\n  },\n  {\n    slug: 'stereofidelic',\n    title: 'Stereofidelic',\n    options: scheme('#f13009', '#678e9a', {dark: '#0e1315', light: '#fcfdfd'}),\n  },\n  {\n    slug: 'verdant',\n    title: 'Verdant',\n    options: scheme('#1cb485', '#5c9199', {dark: '#0d1415', light: '#fcfdfd'}),\n  },\n]\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"presets-CqBgS3A-.js","names":["buildTheme","buildUITheme"],"sources":["../src/theme/hsl.ts","../src/lib/mix.ts","../src/theme/options.ts","../src/theme/buildPalette.ts","../src/theme/buildTheme.ts","../src/theme/presets.ts"],"sourcesContent":["/**\n * Color math for the palette generator, kept at full float precision: unlike\n * the HSL helpers in `@sanity/ui/theme`, nothing is rounded between the two\n * conversions, so `hslToHex(hexToHsl(hex))` returns `hex` unchanged for every\n * color. `buildTheme` relies on that to reproduce the stock `@sanity/color`\n * palette byte-for-byte when it is called with the stock anchor colors.\n */\n\n/**\n * A color in HSL space: `h` in degrees within `[0, 360)`, `s` and `l` as\n * fractions within `[0, 1]`.\n *\n * @internal\n */\nexport interface Hsl {\n  h: number\n  s: number\n  l: number\n}\n\n/** @internal */\nexport function hexToHsl(hex: string): Hsl {\n  const [r, g, b] = parseHex(hex)\n\n  const max = Math.max(r, g, b)\n  const min = Math.min(r, g, b)\n  const delta = max - min\n\n  const l = (max + min) / 2\n\n  if (delta === 0) {\n    return {h: 0, s: 0, l}\n  }\n\n  const s = delta / (1 - Math.abs(2 * l - 1))\n\n  let h: number\n\n  if (max === r) {\n    h = ((g - b) / delta) % 6\n  } else if (max === g) {\n    h = (b - r) / delta + 2\n  } else {\n    h = (r - g) / delta + 4\n  }\n\n  return {h: normalizeHue(h * 60), s, l}\n}\n\n/** @internal */\nexport function hslToHex(hsl: Hsl): string {\n  const h = normalizeHue(hsl.h)\n  const s = clamp01(hsl.s)\n  const l = clamp01(hsl.l)\n\n  const c = (1 - Math.abs(2 * l - 1)) * s\n  const x = c * (1 - Math.abs(((h / 60) % 2) - 1))\n  const m = l - c / 2\n\n  let r = 0\n  let g = 0\n  let b = 0\n\n  if (h < 60) {\n    r = c\n    g = x\n  } else if (h < 120) {\n    r = x\n    g = c\n  } else if (h < 180) {\n    g = c\n    b = x\n  } else if (h < 240) {\n    g = x\n    b = c\n  } else if (h < 300) {\n    r = x\n    b = c\n  } else {\n    r = c\n    b = x\n  }\n\n  return `#${channelToHex(r + m)}${channelToHex(g + m)}${channelToHex(b + m)}`\n}\n\n/**\n * Rotates `from` towards `to` along the shortest arc of the hue circle.\n *\n * @internal\n */\nexport function mixHue(from: number, to: number, amount: number): number {\n  const delta = ((((to - from) % 360) + 540) % 360) - 180\n\n  return normalizeHue(from + delta * amount)\n}\n\n/**\n * The WCAG relative luminance of a hex color, between 0 (black) and 1 (white).\n *\n * @internal\n */\nexport function relativeLuminance(hex: string): number {\n  const [r, g, b] = parseHex(hex)\n\n  return 0.2126 * linearChannel(r) + 0.7152 * linearChannel(g) + 0.0722 * linearChannel(b)\n}\n\nfunction linearChannel(value: number): number {\n  return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4\n}\n\n/** Parses `#abc` and `#aabbcc` hex colors into channel fractions of 1 */\nfunction parseHex(hex: string): [number, number, number] {\n  const expanded =\n    hex.length === 4 ? `${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}` : hex.slice(1)\n\n  return [\n    parseInt(expanded.slice(0, 2), 16) / 255,\n    parseInt(expanded.slice(2, 4), 16) / 255,\n    parseInt(expanded.slice(4, 6), 16) / 255,\n  ]\n}\n\nfunction channelToHex(value: number): string {\n  return Math.round(clamp01(value) * 255)\n    .toString(16)\n    .padStart(2, '0')\n}\n\nfunction normalizeHue(hue: number): number {\n  return ((hue % 360) + 360) % 360\n}\n\nfunction clamp01(value: number): number {\n  return Math.min(1, Math.max(0, value))\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 * The `mix` function this module was named for moved to `@sanity/themer-legacy`\n * along with the legacy generator; `isColor` stays here for `theme/options.ts`\n * and `tool/storage.ts`.\n *\n * @internal\n */\nexport function isColor(input: string): boolean {\n  return /^#(?:[0-9a-f]{3}){1,2}$/i.test(input)\n}\n","import {black, blue, gray, white} from '@sanity/color'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\n\nimport {isColor} from '../lib/mix'\nimport {hexToHsl, hslToHex} from './hsl'\n\n/**\n * The colors of one color scheme, for {@link BuildThemeOptions}. Every color\n * is a hex color (`#rgb` or `#rrggbb`), and everything is optional: omitted\n * options fall back to the stock Studio colors, so an empty object reproduces\n * the stock scheme exactly.\n *\n * @public\n */\nexport interface SchemeThemeOptions {\n  /**\n   * The accent color — the brand color of the scheme. Replaces the `blue`\n   * scale of the palette, which Sanity UI uses for primary buttons, focus\n   * rings and links.\n   *\n   * The stock accent is `#556bfc` (`blue/500` of `@sanity/color`).\n   */\n  accent?: string\n\n  /**\n   * The background of the scheme — every other color of the scheme is\n   * blended onto it. The dark scheme's background replaces `black` in the\n   * palette and the light scheme's replaces `white`.\n   *\n   * It is kept far enough from the text and accent colors to stay usable:\n   * a dark background is made darker until it has enough contrast with them\n   * (it can never be lighter than either), and a light background can never\n   * be darker than either.\n   *\n   * The stock backgrounds are `#0d0e12` (dark) and `#ffffff` (light).\n   */\n  background?: string\n\n  /**\n   * How strongly text and borders separate from the accent color, between 15\n   * and 100. The default is 85, which uses the text color as-is. Above 85 the\n   * text scale loses its tint until it is fully neutral at 100 — a high\n   * contrast scheme with no mixing of the text and accent colors. Below 85\n   * more and more of the accent color mixes into the text scale, giving text\n   * and borders more color, until the scale fully adopts the accent hue and\n   * saturation at 15.\n   */\n  contrast?: number\n\n  /**\n   * The text color. Replaces the `gray` scale of the palette, which Sanity UI\n   * uses for text, icons, borders and neutral surfaces. When omitted, it is\n   * derived from the accent color: a mostly desaturated version of it, the\n   * way the stock `gray` scale carries a hint of the stock blue.\n   *\n   * The stock text color is `#727892` (`gray/500` of `@sanity/color`).\n   */\n  text?: string\n}\n\n/**\n * Options for {@link buildTheme} and {@link buildPalette}: the colors of the\n * dark and the light scheme, each with its own accent, text, background and\n * contrast — so the two schemes can differ in more than their background.\n * Both schemes are optional, and so is every color: whatever is omitted\n * falls back to the stock Studio colors, so `buildTheme({})` matches\n * `buildTheme()` from `@sanity/ui/theme` exactly.\n *\n * @public\n */\nexport interface BuildThemeOptions {\n  /** The colors of the dark scheme */\n  dark?: SchemeThemeOptions\n  /** The colors of the light scheme */\n  light?: SchemeThemeOptions\n}\n\n/**\n * {@link SchemeThemeOptions} with every option filled in: colors normalized\n * to lowercase `#rrggbb`, the text color derived from the accent when it was\n * omitted, and the contrast clamped into its valid range.\n *\n * @internal\n */\nexport interface ResolvedSchemeOptions {\n  accent: string\n  background: string\n  contrast: number\n  text: string\n}\n\n/** {@link BuildThemeOptions} with both schemes resolved @internal */\nexport type ResolvedThemeOptions = Record<ThemeColorSchemeKey, ResolvedSchemeOptions>\n\n/** The color schemes, in the order the tool presents them @internal */\nexport const SCHEMES: ThemeColorSchemeKey[] = ['light', 'dark']\n\n/** The stock accent color — `blue/500` of `@sanity/color` @internal */\nexport const DEFAULT_ACCENT: string = blue[500].hex\n\n/** The stock text color — `gray/500` of `@sanity/color` @internal */\nexport const DEFAULT_TEXT: string = gray[500].hex\n\n/** The stock backgrounds — `black` and `white` of `@sanity/color` @internal */\nexport const DEFAULT_BACKGROUND: Record<ThemeColorSchemeKey, string> = {\n  dark: black.hex,\n  light: white.hex,\n}\n\n/** The contrast that applies the text color as-is @internal */\nexport const DEFAULT_CONTRAST = 85\n\n/** @internal */\nexport const MINIMUM_CONTRAST = 15\n\n/** @internal */\nexport const MAXIMUM_CONTRAST = 100\n\n/** The keys of the options shape before they were grouped by scheme */\nconst FLAT_OPTION_KEYS = ['accent', 'text', 'background', 'contrast']\n\n/** @internal */\nexport function resolveThemeOptions(options: BuildThemeOptions = {}): ResolvedThemeOptions {\n  if (FLAT_OPTION_KEYS.some((key) => key in options)) {\n    throw new TypeError(\n      'The `buildTheme` options are grouped by color scheme: pass `{light: {accent, text, background, contrast}, dark: {…}}` instead of one set of colors for both',\n    )\n  }\n\n  return {\n    dark: resolveSchemeOptions(options.dark ?? {}, 'dark'),\n    light: resolveSchemeOptions(options.light ?? {}, 'light'),\n  }\n}\n\nfunction resolveSchemeOptions(\n  options: SchemeThemeOptions,\n  scheme: ThemeColorSchemeKey,\n): ResolvedSchemeOptions {\n  const accent =\n    options.accent === undefined\n      ? DEFAULT_ACCENT\n      : normalizeColor(options.accent, `${scheme}.accent`)\n\n  return {\n    accent,\n    background:\n      options.background === undefined\n        ? DEFAULT_BACKGROUND[scheme]\n        : normalizeColor(options.background, `${scheme}.background`),\n    contrast: normalizeContrast(options.contrast, scheme),\n    text:\n      options.text === undefined\n        ? deriveTextColor(accent)\n        : normalizeColor(options.text, `${scheme}.text`),\n  }\n}\n\n/**\n * Derives the text color from an accent color, keeping the relationship the\n * stock palette has between `gray/500` and `blue/500`: the text color takes\n * the accent's hue (offset the way the stock gray is offset from the stock\n * blue), carries about an eighth of its saturation, and keeps the stock text\n * lightness. Deriving from the stock accent returns the stock text color.\n *\n * @internal\n */\nexport function deriveTextColor(accent: string): string {\n  const accentHsl = hexToHsl(normalizeColor(accent, 'accent'))\n  const defaultAccent = hexToHsl(DEFAULT_ACCENT)\n  const defaultText = hexToHsl(DEFAULT_TEXT)\n\n  return hslToHex({\n    h: defaultText.h + (accentHsl.h - defaultAccent.h),\n    s: Math.min(1, defaultText.s * (accentHsl.s / defaultAccent.s)),\n    l: defaultText.l,\n  })\n}\n\nfunction normalizeColor(value: string, name: string): string {\n  if (typeof value !== 'string' || !isColor(value)) {\n    throw new TypeError(\n      `Invalid \\`${name}\\` color: ${JSON.stringify(value)} — expected a hex color like #556bfc`,\n    )\n  }\n\n  const lower = value.toLowerCase()\n\n  return lower.length === 4\n    ? `#${lower[1]}${lower[1]}${lower[2]}${lower[2]}${lower[3]}${lower[3]}`\n    : lower\n}\n\nfunction normalizeContrast(value: number | undefined, scheme: ThemeColorSchemeKey): number {\n  if (value === undefined) {\n    return DEFAULT_CONTRAST\n  }\n\n  if (typeof value !== 'number' || !Number.isFinite(value)) {\n    throw new TypeError(\n      `Invalid \\`${scheme}.contrast\\`: ${JSON.stringify(value)} — expected a number between ${MINIMUM_CONTRAST} and ${MAXIMUM_CONTRAST}`,\n    )\n  }\n\n  return Math.min(MAXIMUM_CONTRAST, Math.max(MINIMUM_CONTRAST, value))\n}\n","import {\n  color,\n  COLOR_TINTS,\n  type ColorHueKey,\n  type ColorTintKey,\n  type ColorTints,\n} from '@sanity/color'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\n\nimport {hexToHsl, type Hsl, hslToHex, mixHue, relativeLuminance} from './hsl'\nimport {\n  type BuildThemeOptions,\n  DEFAULT_ACCENT,\n  DEFAULT_CONTRAST,\n  DEFAULT_TEXT,\n  MAXIMUM_CONTRAST,\n  MINIMUM_CONTRAST,\n  type ResolvedSchemeOptions,\n  resolveThemeOptions,\n} from './options'\n\n/**\n * The lightness band the accent and text colors are clamped into — anchors\n * outside it would squeeze most of their scale's tints into an\n * indistinguishable sliver, messing with the rest of the scale.\n */\nconst MINIMUM_ANCHOR_LIGHTNESS = 0.25\nconst MAXIMUM_ANCHOR_LIGHTNESS = 0.75\n\n/**\n * The contrast ratio the dark background must reach against the 400 tints of\n * the text and accent scales — the tints Sanity UI paints muted text and\n * solid buttons with on dark backgrounds. The stock palette sits at ~6.8.\n */\nconst MINIMUM_DARK_BACKGROUND_CONTRAST = 4.5\n\n/** How much lightness each step of a background adjustment removes or adds */\nconst BACKGROUND_LIGHTNESS_STEP = 0.005\n\n/**\n * A color palette generated by {@link buildPalette}: the `palette` config of\n * `buildTheme` from `@sanity/ui/theme`, with every color as a hex string.\n *\n * @public\n */\nexport type GeneratedColorPalette = {black: string; white: string} & Record<\n  ColorHueKey,\n  Record<ColorTintKey, string>\n>\n\n/**\n * The palettes generated by {@link buildPalette} — one per color scheme.\n *\n * @public\n */\nexport type GeneratedColorPalettes = Record<ThemeColorSchemeKey, GeneratedColorPalette>\n\n/**\n * Generates a Sanity UI color palette for each color scheme from the theme\n * options: in each palette the scheme's accent color replaces the `blue`\n * scale, its text color the `gray` scale, and the backgrounds replace `black`\n * and `white`. All other hues keep their stock `@sanity/color` values. Called\n * with the stock colors, both palettes come back as the stock palette\n * byte-for-byte.\n *\n * ```ts\n * import {buildPalette} from '@sanity/themer'\n *\n * const {light, dark} = buildPalette({light: {accent: '#556bfc'}})\n * ```\n *\n * @public\n */\nexport function buildPalette(options: BuildThemeOptions = {}): GeneratedColorPalettes {\n  const resolved = resolveThemeOptions(options)\n\n  return {\n    dark: buildSchemePalette('dark', resolved.dark, resolved.light.background),\n    light: buildSchemePalette('light', resolved.light, resolved.dark.background),\n  }\n}\n\n/**\n * Generates the palette of one scheme. The scheme's own background takes the\n * slot the scheme paints with (`black` for dark, `white` for light), while\n * the other slot — which a scheme only touches for a few inverted details —\n * takes the other scheme's background, so the theme stays one palette.\n */\nfunction buildSchemePalette(\n  key: ThemeColorSchemeKey,\n  scheme: ResolvedSchemeOptions,\n  otherBackground: string,\n): GeneratedColorPalette {\n  const accentAnchor = clampAnchorLightness(hexToHsl(scheme.accent))\n  const textAnchor = clampAnchorLightness(hexToHsl(scheme.text))\n  const grayAnchor = applyContrast(textAnchor, accentAnchor, scheme.contrast)\n\n  const blueTints = remapTints(color.blue, hexToHsl(DEFAULT_ACCENT), accentAnchor)\n  const grayTints = remapTints(color.gray, hexToHsl(DEFAULT_TEXT), grayAnchor)\n\n  const anchorLuminances = [\n    relativeLuminance(hslToHex(grayAnchor)),\n    relativeLuminance(hslToHex(accentAnchor)),\n  ]\n\n  const darkBackground = key === 'dark' ? scheme.background : otherBackground\n  const lightBackground = key === 'light' ? scheme.background : otherBackground\n\n  return {\n    black: darkenBackground(darkBackground, {\n      anchorLuminances,\n      tints: [grayTints['400'], blueTints['400']],\n    }),\n    white: lightenBackground(lightBackground, anchorLuminances),\n    gray: grayTints,\n    blue: blueTints,\n    purple: tintHexes(color.purple),\n    magenta: tintHexes(color.magenta),\n    red: tintHexes(color.red),\n    orange: tintHexes(color.orange),\n    yellow: tintHexes(color.yellow),\n    green: tintHexes(color.green),\n    cyan: tintHexes(color.cyan),\n  }\n}\n\n/**\n * Mixes the accent color into the text color according to the contrast: 85\n * applies the text color as-is, 100 removes its tint entirely, and lower\n * values rotate and saturate it towards the accent.\n */\nfunction applyContrast(text: Hsl, accent: Hsl, contrast: number): Hsl {\n  if (contrast === DEFAULT_CONTRAST) {\n    return text\n  }\n\n  if (contrast > DEFAULT_CONTRAST) {\n    const amount = (contrast - DEFAULT_CONTRAST) / (MAXIMUM_CONTRAST - DEFAULT_CONTRAST)\n\n    return {h: text.h, s: text.s * (1 - amount), l: text.l}\n  }\n\n  const amount = (DEFAULT_CONTRAST - contrast) / (DEFAULT_CONTRAST - MINIMUM_CONTRAST)\n\n  return {\n    h: mixHue(text.h, accent.h, amount),\n    s: text.s + (accent.s - text.s) * amount,\n    l: text.l,\n  }\n}\n\n/**\n * Rebuilds a stock tint scale around a new anchor color, where `from` is the\n * scale's stock 500 tint: hues rotate along, saturation scales\n * proportionally, and lightness is remapped piecewise so the anchor takes the\n * new lightness while the scale keeps spanning light to dark. When the anchor\n * matches the stock one, every tint comes back unchanged.\n */\nfunction remapTints(tints: ColorTints, from: Hsl, to: Hsl): Record<ColorTintKey, string> {\n  const rotation = to.h - from.h\n  const result: Partial<Record<ColorTintKey, string>> = {}\n\n  for (const tint of COLOR_TINTS) {\n    const value = hexToHsl(tints[tint].hex)\n\n    result[tint] = hslToHex({\n      h: value.h + rotation,\n      s: remapSaturation(value.s, from.s, to.s),\n      l: remapLightness(value.l, from.l, to.l),\n    })\n  }\n\n  // oxlint-disable-next-line no-unsafe-type-assertion -- the loop assigns every tint key\n  return result as Record<ColorTintKey, string>\n}\n\nfunction remapSaturation(value: number, from: number, to: number): number {\n  if (from === to) {\n    return value\n  }\n\n  return Math.min(1, value * (to / from))\n}\n\nfunction remapLightness(value: number, from: number, to: number): number {\n  if (from === to) {\n    return value\n  }\n\n  if (value <= from) {\n    return value * (to / from)\n  }\n\n  return to + ((value - from) * (1 - to)) / (1 - from)\n}\n\nfunction clampAnchorLightness(anchor: Hsl): Hsl {\n  const l = Math.min(MAXIMUM_ANCHOR_LIGHTNESS, Math.max(MINIMUM_ANCHOR_LIGHTNESS, anchor.l))\n\n  return l === anchor.l ? anchor : {...anchor, l}\n}\n\n/**\n * Enforces the dark background rules: it can never be lighter than the text\n * or accent colors, and it must reach enough contrast with the 400 tints of\n * their scales — it is made darker until it does (or bottoms out at black).\n */\nfunction darkenBackground(\n  hex: string,\n  rules: {anchorLuminances: number[]; tints: string[]},\n): string {\n  const maximumLuminance = Math.min(...rules.anchorLuminances)\n  const tintLuminances = rules.tints.map((tint) => relativeLuminance(tint))\n\n  const isDarkEnough = (background: string): boolean => {\n    const luminance = relativeLuminance(background)\n\n    return (\n      luminance < maximumLuminance &&\n      tintLuminances.every(\n        (tintLuminance) =>\n          (tintLuminance + 0.05) / (luminance + 0.05) >= MINIMUM_DARK_BACKGROUND_CONTRAST,\n      )\n    )\n  }\n\n  const {h, s, l} = hexToHsl(hex)\n  let lightness = l\n  let current = hex\n\n  while (!isDarkEnough(current) && lightness > 0) {\n    lightness = Math.max(0, lightness - BACKGROUND_LIGHTNESS_STEP)\n    current = hslToHex({h, s, l: lightness})\n  }\n\n  return current\n}\n\n/**\n * Enforces the light background rule: it can never be darker than the text\n * or accent colors — it is made lighter until it is (or tops out at white).\n */\nfunction lightenBackground(hex: string, anchorLuminances: number[]): string {\n  const minimumLuminance = Math.max(...anchorLuminances)\n\n  const {h, s, l} = hexToHsl(hex)\n  let lightness = l\n  let current = hex\n\n  while (relativeLuminance(current) <= minimumLuminance && lightness < 1) {\n    lightness = Math.min(1, lightness + BACKGROUND_LIGHTNESS_STEP)\n    current = hslToHex({h, s, l: lightness})\n  }\n\n  return current\n}\n\nfunction tintHexes(tints: ColorTints): Record<ColorTintKey, string> {\n  const result: Partial<Record<ColorTintKey, string>> = {}\n\n  for (const tint of COLOR_TINTS) {\n    result[tint] = tints[tint].hex\n  }\n\n  // oxlint-disable-next-line no-unsafe-type-assertion -- the loop assigns every tint key\n  return result as Record<ColorTintKey, string>\n}\n","import {\n  buildTheme as buildUITheme,\n  type RootTheme,\n  type ThemeColorSchemes_v2,\n  v0_v2,\n  v2_v0,\n} from '@sanity/ui/theme'\n\nimport {buildPalette} from './buildPalette'\nimport type {BuildThemeOptions} from './options'\n\n/**\n * Generates a Studio theme from a handful of colors per color scheme, by\n * replacing the color palette that the `buildTheme` from `@sanity/ui/theme`\n * otherwise fills with `@sanity/color`: in each scheme the accent color\n * replaces the `blue` scale (primary buttons, focus rings, links), the\n * optional text color the `gray` scale (text, icons, borders), and the\n * optional background replaces `black` (dark) or `white` (light). The result\n * is the same type of theme that `@sanity/ui/theme` builds, ready for the\n * `theme` property of a Studio config.\n *\n * ```ts\n * import {buildTheme} from '@sanity/themer'\n * import {defineConfig} from 'sanity'\n *\n * export const theme = buildTheme({\n *   light: {\n *     accent: '#556bfc',\n *     text: '#727892', // optional — derived from `accent` when omitted\n *     background: '#ffffff', // optional\n *     contrast: 85, // optional, 15–100\n *   },\n *   dark: {\n *     accent: '#556bfc',\n *     background: '#0d0e12',\n *   },\n * })\n *\n * export default defineConfig({\n *   theme,\n *   // ...rest of the config\n * })\n * ```\n *\n * Every option is optional and falls back to the stock Studio colors: called\n * with the stock colors — like the example — or with no options at all, it\n * returns the exact same colors as `buildTheme()` from `@sanity/ui/theme`.\n *\n * @public\n */\nexport function buildTheme(options: BuildThemeOptions = {}): RootTheme {\n  const palettes = buildPalette(options)\n\n  // Sanity UI renders both schemes of a theme from one palette, so each\n  // scheme gets a theme of its own palette, and the two are composed into one\n  // theme that takes its light scheme from the one and its dark scheme from\n  // the other. The scheme getters keep Sanity UI's lazy rendering: a scheme is\n  // only computed once something reads it.\n  const light = v0_v2(buildUITheme({palette: palettes.light}))\n  const dark = v0_v2(buildUITheme({palette: palettes.dark}))\n\n  const color: ThemeColorSchemes_v2 = {\n    get light() {\n      return light.color.light\n    },\n    get dark() {\n      return dark.color.dark\n    },\n  }\n\n  return v2_v0({...light, color})\n}\n","import type {BuildThemeOptions} from './options'\n\n/**\n * A preset theme: a named set of {@link BuildThemeOptions} ready to pass to\n * `buildTheme`.\n *\n * @public\n */\nexport interface ThemePreset {\n  slug: string\n  title: string\n  /** The preset's theme options, ready to pass to `buildTheme` */\n  options: BuildThemeOptions\n}\n\n/**\n * The hosted Themer presets had one accent and one text color for both\n * schemes, and a background per scheme\n */\nfunction scheme(accent: string, text: string, backgrounds: {dark: string; light: string}) {\n  return {\n    dark: {accent, text, background: backgrounds.dark},\n    light: {accent, text, background: backgrounds.light},\n  } satisfies BuildThemeOptions\n}\n\n/**\n * Preset themes for `buildTheme`, carried over from the hosted Themer service\n * (themer.sanity.build) presets: each one maps the legacy preset's primary\n * hue to `accent`, its default hue to `text` and its lightest/darkest colors\n * to the backgrounds of the light and dark scheme.\n *\n * ```ts\n * import {buildTheme, presets} from '@sanity/themer'\n *\n * const verdant = presets.find((preset) => preset.slug === 'verdant')\n * const theme = buildTheme(verdant.options)\n * ```\n *\n * @public\n */\nexport const presets: ThemePreset[] = [\n  {\n    slug: 'studio',\n    title: 'Studio',\n    options: {},\n  },\n  {\n    slug: 'dew',\n    title: 'Dew',\n    options: scheme('#d1a308', '#5e63b4', {dark: '#0d0d15', light: '#fcfcfd'}),\n  },\n  {\n    slug: 'pink-synth',\n    title: 'Pink Synth',\n    options: scheme('#ec4899', '#8b6584', {dark: '#171721', light: '#f7f2f5'}),\n  },\n  {\n    slug: 'pixel-art',\n    title: 'Pixel Art',\n    options: scheme('#f10784', '#57619c', {dark: '#0d0e15', light: '#fcfcfd'}),\n  },\n  {\n    slug: 'retro-colonial',\n    title: 'Retro Colonial',\n    options: scheme('#fa7a78', '#8bb9b5', {dark: '#0d1515', light: '#fcfdfd'}),\n  },\n  {\n    slug: 'rosabel',\n    title: 'Rosabel',\n    options: scheme('#ed2555', '#9d8966', {dark: '#15120d', light: '#fdfdfc'}),\n  },\n  {\n    slug: 'stereofidelic',\n    title: 'Stereofidelic',\n    options: scheme('#f13009', '#678e9a', {dark: '#0e1315', light: '#fcfdfd'}),\n  },\n  {\n    slug: 'verdant',\n    title: 'Verdant',\n    options: scheme('#1cb485', '#5c9199', {dark: '#0d1415', light: '#fcfdfd'}),\n  },\n]\n"],"mappings":"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"}
\ No newline at end of file