@sanity/themer

0.8.00.8.1
dist/ResizableSidebar-DD787kQr.js.map
~dist/ResizableSidebar-DD787kQr.js.mapModified
+1−1
Index: package/dist/ResizableSidebar-DD787kQr.js.map
===================================================================
--- package/dist/ResizableSidebar-DD787kQr.js.map
+++ package/dist/ResizableSidebar-DD787kQr.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"ResizableSidebar-DD787kQr.js","names":["root","() => lastGutter","() => {\n    const element = ref.current\n\n    if (!element) return undefined\n\n    // The reserved gutter is the part of the box the content cannot use\n    const measure = () => {\n      lastGutter = element.offsetWidth - element.clientWidth\n      setGutter(lastGutter)\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(element)\n\n    return () => observer.disconnect()\n  }","[]","{\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }","space[padding]","Math.max(0, space[padding] - gutter)","useMemo<ScrollAreaInset>(\n    () => ({\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }),\n    [gutter, padding, space],\n  )","{paddingRight: inset.right}","right","<ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>","ScrollAreaInsetContext.Provider","<Box\n      className={root}\n      flex={1}\n      overflow=\"auto\"\n      padding={padding}\n      ref={ref}\n      style={{paddingRight: inset.right}}\n    >\n      <ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>\n    </Box>","{marginLeft: -left, marginRight: -right, marginBottom: -bottom}","-left","-right","-bottom","<div style={{marginLeft: -left, marginRight: -right, marginBottom: -bottom}}>\n      {props.children}\n    </div>","children","_c","_temp","root","root","buildTheme(options)","useMemo(() => buildTheme(options), [options])","<MockStudio scheme=\"light\" />","<ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>","<MockStudio scheme=\"dark\" />","<ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>","<div aria-hidden className={root}>\n      <ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>\n      <ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>\n    </div>","assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })","bg","border","fg","<div className={logo} />","<div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>","<div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>","(width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          }","<div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>","(width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            )","<div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>","<div\n      className={studio[scheme]}\n      style={assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })}\n    >\n      <div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>\n\n      <div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>\n    </div>","studio[scheme]","width","FIELDS","_c","root","_temp","<Card overflow=\"hidden\" radius={3} shadow={1}>\n      <ThemePreview options={props.options} />\n    </Card>","options","_c","removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))","(theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        )","<ScrollArea padding={3}>\n      <Stack gap={5}>\n        {removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))}\n      </Stack>\n    </ScrollArea>","_c","<Text size={1}>{tooltip}</Text>","<Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />","buttonProps.text === undefined ? tooltip : undefined","<Tooltip animate content={<Text size={1}>{tooltip}</Text>} placement=\"bottom\" portal>\n      <Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />\n    </Tooltip>","_c","() => inputRef.current?.click()","<TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />","<input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />","<>\n      <TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />\n      <input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />\n    </>","_c","_Fragment","() => {\n    onPaletteRef.current = onPalette\n  }","[onPalette]","() => {\n    mountedRef.current = true\n\n    return () => {\n      mountedRef.current = false\n    }\n  }","[]","(file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    }","(swatch) => swatch === null","useCallback(\n    (file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    },\n    [toast],\n  )","{busy, pickImage}","_c","_temp","palette ? currentImageVariant(options, palette) : null","() => {\n    const row = rowRef.current\n\n    if (!row) return undefined\n\n    const measure = () => {\n      const visible =\n        row.clientWidth - ROW_PADDING - (Math.ceil(VISIBLE_VARIANTS) - 1) * VARIANT_GAP\n\n      // Each variant is its thumbnail plus the frame on either side\n      setThumbnailWidth(Math.max(24, Math.floor(visible / VISIBLE_VARIANTS) - VARIANT_FRAME * 2))\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(row)\n\n    return () => observer.disconnect()\n  }","[palette]","useMemo(() => {\n    if (!palette) return []\n\n    return IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )\n  }, [options, palette])","[]","IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )","(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }","() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }","(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }","event","<Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>","palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )","<Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>","palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )","{variant, title, options: variantOptions}","variant","title","<Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>","<Card\n      border\n      onDragEnter={(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }}\n      onDragLeave={() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }}\n      onDragOver={(event) => {\n        event.preventDefault()\n      }}\n      onDrop={(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }}\n      padding={3}\n      radius={3}\n      tone={dragging ? 'primary' : 'default'}\n    >\n      <Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>\n    </Card>","dragging ? 'primary' : 'default'","(event) => {\n        event.preventDefault()\n      }","_c","_Fragment","_temp","themes.find((candidate) => candidate.slug === slug && candidate.source === 'custom')","(candidate) => candidate.slug === slug && candidate.source === 'custom'","(variant: ImagePaletteVariant | null) => {\n    if (!theme.palette || variant === null) return\n\n    send({\n      type: 'theme.update',\n      slug,\n      options: applyImagePalette(theme.options, theme.palette, variant),\n    })\n  }","options","palette","() => send({type: 'flow.list'})","() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }","(options) => send({type: 'theme.update', slug, options})","(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })","() => send({type: 'theme.remove', slug})","(title) => send({type: 'theme.update', slug, title})","<ThemeEditorForm\n      focusTitle={focusTitle}\n      imageUrl={images[slug]}\n      onDone={() => send({type: 'flow.list'})}\n      onLucky={() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }}\n      onOptionsChange={(options) => send({type: 'theme.update', slug, options})}\n      onPalette={(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })\n      }\n      onRemove={() => send({type: 'theme.remove', slug})}\n      onTitleChange={(title) => send({type: 'theme.update', slug, title})}\n      onVariant={applyVariant}\n      options={theme.options}\n      palette={theme.palette}\n      split={split}\n      mobile={mobile}\n      title={theme.title}\n    />","images[slug]","title","resolveThemeOptions(options)","useMemo(() => resolveThemeOptions(options), [options])","buildPalette(options)","useMemo(() => buildPalette(options), [options])","(scheme: ThemeColorSchemeKey, changes: Partial<SchemeThemeOptions>) => {\n    const values: SchemeThemeOptions = {...options[scheme], ...changes}\n\n    // Clearing an option means falling back to its default, which is its absence\n    for (const key of SCHEME_OPTION_KEYS) {\n      if (values[key] === undefined) delete values[key]\n    }\n\n    const next: BuildThemeOptions = {...options}\n\n    if (Object.keys(values).length === 0) {\n      delete next[scheme]\n    } else {\n      next[scheme] = values\n    }\n\n    onOptionsChange(next)\n  }","<ThemeThumbnail options={options} />","<Text size={1} weight=\"medium\">\n              Title\n            </Text>","(event) => onTitleChange(event.currentTarget.value)","(event) => event.currentTarget.select()","<Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>","focusTitle ? (event) => event.currentTarget.select() : undefined","<ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />","SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))","scheme","changes","<ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>","<ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>","<TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />","<Box flex={1} />","<Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />","<Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>","<>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>\n    </>","event","<Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>","active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )","<Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>","<Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>","split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`","<Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>","(accent) => onChange({accent})","() => onChange({accent: undefined})","<ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />","accent","options.accent === undefined","`${name} accent`","(text) => onChange({text})","() => onChange({text: undefined})","<ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />","text","options.text === undefined","`${name} text`","(background) => onChange({background})","() => onChange({background: undefined})","<ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />","background","scheme === 'dark' ? palette.black : palette.white","options.background === undefined","`${name} background`","<Text size={1}>Contrast</Text>","<Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>","contrast","options.contrast === undefined ? ' · auto' : ''","options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )","<Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>","(event) => onChange({contrast: Number(event.currentTarget.value)})","<input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({contrast: Number(event.currentTarget.value)})}\n            step={1}\n            type=\"range\"\n            value={resolved.contrast}\n          />","`${name} contrast`","<Text muted size={0}>\n            100 keeps text and borders neutral — lower values blend in the accent\n          </Text>","<Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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>","<Card borderTop padding={3}>\n      <Stack gap={4}>\n        <Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>\n\n        <ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />\n        <ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />\n        <ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />\n\n        <Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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      </Stack>\n    </Card>","autoLabel = 'auto'","(event) => onChange(event.currentTarget.value)","<input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />","<Text size={1}>{title}</Text>","<Text muted size={0} textOverflow=\"ellipsis\">\n          {value}\n          {adjusted !== undefined && adjusted !== value ? ` → ${adjusted}` : ''}\n          {auto ? ` · ${autoLabel}` : ''}\n        </Text>","adjusted !== undefined && adjusted !== value ? ` → ${adjusted}` : ''","auto ? ` · ${autoLabel}` : ''","<Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>","onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )","<Flex align=\"center\" gap={2}>\n      <input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />\n      <Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>\n      {onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )}\n    </Flex>","_c","_temp","_Fragment","async (theme: SharedTheme) => {\n    const title = displayTitle(theme.title)\n\n    try {\n      await navigator.clipboard.writeText(encodeTheme(theme))\n      toast.push({\n        status: 'success',\n        title: `Copied ${title} as a code`,\n        description: 'Paste it in the themer of another Studio to add the theme there',\n      })\n    } catch {\n      toast.push({status: 'error', title: `Could not copy ${title}`})\n    }\n  }","(text: string) => {\n    const theme = decodeTheme(text)\n\n    if (!theme) return false\n\n    send({type: 'theme.import', title: theme.title, options: theme.options})\n    toast.push({status: 'success', title: `Added ${theme.title}`})\n\n    return true\n  }","theme","async () => {\n    let text: string\n\n    try {\n      text = await navigator.clipboard.readText()\n    } catch {\n      return 'no-clipboard'\n    }\n\n    return addThemeFromText(text) ? 'added' : 'no-theme'\n  }","text","{copyTheme, addThemeFromText, addThemeFromClipboard}","() => {\n    if (!open) return undefined\n\n    const handlePaste = (event: ClipboardEvent) => {\n      if (isEditable(event.target)) return\n\n      const theme = decodeTheme(event.clipboardData?.getData('text/plain') ?? '')\n\n      if (!theme) return\n\n      event.preventDefault()\n      send({type: 'theme.import', title: theme.title, options: theme.options})\n      toast.push({status: 'success', title: `Added ${theme.title}`})\n    }\n\n    document.addEventListener('paste', handlePaste)\n\n    return () => document.removeEventListener('paste', handlePaste)\n  }","[open, send, toast]","_c","() => {\n    if (addThemeFromText(text)) {\n      onClose()\n    } else {\n      setInvalid(true)\n    }\n  }","<Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />","text.trim()","<Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />","text.trim() === ''","<Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>","(event) => {\n          event.preventDefault()\n          add()\n        }","<Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>","(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }","event","<TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />","invalid ? 'themer-paste-error' : undefined","invalid ? 'That is not a theme code' : undefined","invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )","<Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>","<form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>","<Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>\n      }\n      header=\"Add a shared theme\"\n      id=\"themer-paste\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={0}\n    >\n      <form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>\n    </Dialog>","_c","frame","displayTitle(theme.title)","title","(candidate) => candidate.slug === theme.slug","slug","(to: number) => {\n    const order = themes.map((candidate) => candidate.slug)\n\n    order.splice(to, 0, ...order.splice(index, 1))\n    send({type: 'theme.reorder', order})\n  }","(candidate) => candidate.slug","() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }","() => {\n        dragged.current = true\n      }","{scale: 1.04}","() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }","(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }","<span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>","options","<Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>","active ? 'medium' : 'regular'","<button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>","<Text size={1}>Show more</Text>","<Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />","`Show more for ${title}`","() => moveTo(index - 1)","<MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />","index <= 0","() => moveTo(index + 1)","<MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />","index >= themes.length - 1","<MenuDivider />","theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )","source","() => send({type: 'theme.duplicate', slug: theme.slug})","<MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />","theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'","<MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />","theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )","<Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>","() => setMenuOpen(false)","() => setMenuOpen(true)","{animate: true, placement: 'bottom-end', portal: true, scheme}","<Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>","`themer-theme-${theme.slug}`","<div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>","<Reorder.Item\n      as=\"div\"\n      className={root}\n      dragControls={dragControls}\n      dragListener={false}\n      onDragEnd={() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }}\n      onDragStart={() => {\n        dragged.current = true\n      }}\n      ref={active ? scrollRefIntoViewIfNeeded : undefined}\n      value={theme.slug}\n      whileDrag={{scale: 1.04}}\n    >\n      <button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>\n\n      {/* The tooltip wraps a card rather than the button: the menu button\n          clones its button to wire it up, which a tooltip in between would\n          swallow. The card keeps the button dark, as it sits on the dark\n          half of the thumbnail, while the menu opens in the sidebar's scheme */}\n      <div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>\n    </Reorder.Item>","active ? scrollRefIntoViewIfNeeded : undefined","Reorder.Item","candidate","_c","_temp","frame","_Fragment","(palette, file) =>\n    send({\n      type: 'theme.add',\n      title: titleFromFileName(file.name),\n      options: optionsFromImagePalette(palette),\n      palette,\n      imageUrl: URL.createObjectURL(file),\n    })","(order: string[]) => send({type: 'theme.reorder', order})","themes.map((theme) => theme.slug)","(theme) => theme.slug","themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))","active.slug","(theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              )","theme","<MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>","Reorder.Group","removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )","length","<ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>","<Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>","<ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />","<TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />","<Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>","pasting && <PasteThemeDialog onClose={() => setPasting(false)} />","<>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>\n\n      {pasting && <PasteThemeDialog onClose={() => setPasting(false)} />}\n    </>","_c","_Fragment","createThemeSnippet(theme.options)","options","async () => {\n    try {\n      await navigator.clipboard.writeText(snippet)\n      toast.push({status: 'success', title: 'Copied the theme to the clipboard'})\n    } catch {\n      toast.push({status: 'error', title: 'Could not copy the theme'})\n    }\n  }","<Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>","<code>sanity.config.ts</code>","<code>theme</code>","<code>defineConfig</code>","displayTitle(theme.title)","title","<Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>","<Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>","<Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>","<Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>\n      }\n      header=\"Add to your config\"\n      id=\"themer-snippet\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={1}\n    >\n      <Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>\n    </Dialog>","_c","navbarHeight === null ? undefined : {height: navbarHeight}","!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )","<Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>","VIEW_TITLES[view.name]","view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )","name","<TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />","<Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>","<Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>","<Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>","view.name === 'list' && <ThemeList />","view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />","focusTitle","slug","view.name === 'removed' && <RemovedThemes />","<Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>","snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />","<Card height=\"fill\">\n      <Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>\n\n      {snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />}\n    </Card>","_c","_Fragment","() => writeStoredWidth(width)","[width]","(event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    }","useCallback(\n    (event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    },\n    [width],\n  )","(event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }","event","useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }, [])","(event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }","useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }, [])","(event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }","useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }, [])","overlay ? undefined : {width}","!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )","<Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>","<Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>","!overlay","<Layer\n      className={sidebar}\n      data-overlay={overlay}\n      style={overlay ? undefined : {width}}\n      zOffset={100}\n    >\n      <Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>\n    </Layer>","_c"],"sources":["../src/tool/ScrollArea.css.ts","../src/tool/ScrollArea.tsx","../src/tool/ThemePreview.css.ts","../src/tool/ThemePreview.tsx","../src/tool/ThemeThumbnail.tsx","../src/tool/RemovedThemes.css.ts","../src/tool/RemovedThemes.tsx","../src/tool/TooltipButton.tsx","../src/tool/ImageFileButton.tsx","../src/tool/imageFile.ts","../src/tool/useImagePalette.ts","../src/tool/ImagePaletteSection.css.ts","../src/tool/ImagePaletteSection.tsx","../src/tool/ThemeEditor.css.ts","../src/tool/ThemeEditor.tsx","../src/tool/share.ts","../src/tool/useThemeCodes.ts","../src/tool/PasteThemeDialog.tsx","../src/tool/ThemeCard.css.ts","../src/tool/ThemeCard.tsx","../src/tool/ThemeList.css.ts","../src/tool/ThemeList.tsx","../src/tool/snippet.ts","../src/tool/ThemeSnippetDialog.tsx","../src/tool/ThemerSidebar.css.ts","../src/tool/ThemerSidebar.tsx","../src/tool/ResizableSidebar.css.ts","../src/tool/ResizableSidebar.tsx"],"sourcesContent":["import {style} from '@vanilla-extract/css'\n\n/** Always reserves the scrollbar's space, so the content never shifts */\nexport const root = style({\n  scrollbarGutter: 'stable',\n})\n","import {Box, useTheme_v2} from '@sanity/ui'\nimport {createContext, useContext, useEffect, useMemo, useRef, useState} from 'react'\n\nimport {root} from './ScrollArea.css'\n\n/** How far the content of a scroll area sits from its edges, in pixels */\ninterface ScrollAreaInset {\n  left: number\n  right: number\n  bottom: number\n}\n\nconst ScrollAreaInsetContext = createContext<ScrollAreaInset>({left: 0, right: 0, bottom: 0})\n\n/**\n * The gutter the last scroll area measured. It is the same for every scroll\n * area (the reserved gutter does not depend on the content), so the next one\n * starts out with the right padding instead of shifting after its first\n * measurement — which would also throw off anything scrolling into view as\n * the content mounts.\n */\nlet lastGutter = 0\n\n/**\n * The scrolling body of a sidebar flow. It always reserves the scrollbar's\n * space, so the content does not shift when the list grows or shrinks past\n * the point where it needs to scroll — and it takes that space out of its\n * right padding, so the content stays centered rather than hugging the left.\n * With overlay scrollbars there is no gutter and the padding stays even.\n *\n * @internal\n */\nexport function ScrollArea(props: {children: React.ReactNode; padding: number}) {\n  const {children, padding} = props\n  const {space} = useTheme_v2()\n  const ref = useRef<HTMLDivElement | null>(null)\n  const [gutter, setGutter] = useState(() => lastGutter)\n\n  useEffect(() => {\n    const element = ref.current\n\n    if (!element) return undefined\n\n    // The reserved gutter is the part of the box the content cannot use\n    const measure = () => {\n      lastGutter = element.offsetWidth - element.clientWidth\n      setGutter(lastGutter)\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(element)\n\n    return () => observer.disconnect()\n  }, [])\n\n  const inset = useMemo<ScrollAreaInset>(\n    () => ({\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }),\n    [gutter, padding, space],\n  )\n\n  return (\n    <Box\n      className={root}\n      flex={1}\n      overflow=\"auto\"\n      padding={padding}\n      ref={ref}\n      style={{paddingRight: inset.right}}\n    >\n      <ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>\n    </Box>\n  )\n}\n\n/**\n * Content that runs edge to edge in a scroll area — up to the scrollbar —\n * instead of sitting inside its padding. It goes last: it runs down to the\n * bottom edge too.\n *\n * @internal\n */\nexport function ScrollAreaBleed(props: {children: React.ReactNode}) {\n  const {left, right, bottom} = useContext(ScrollAreaInsetContext)\n\n  return (\n    <div style={{marginLeft: -left, marginRight: -right, marginBottom: -bottom}}>\n      {props.children}\n    </div>\n  )\n}\n","import {createVar, style, styleVariants} from '@vanilla-extract/css'\n\n/**\n * The dark scheme covers the right side of the preview behind a diagonal cut,\n * like the \"Auto\" appearance preview in macOS System Settings shows both\n * schemes at once.\n */\nconst DARK_CLIP_PATH = 'polygon(58% 0, 100% 0, 100% 100%, 42% 100%)'\n\n/** The thickness of a line of text — bold enough to survive a half-size preview */\nconst LINE = 4\n\n/**\n * The colors a mockup paints with — only the ones the theme options change —\n * assigned per color scheme from the theme it previews\n */\nexport const colors = {\n  bg: createVar(),\n  fg: createVar(),\n  mutedFg: createVar(),\n  border: createVar(),\n  accent: createVar(),\n  avatar: createVar(),\n  selectedBg: createVar(),\n  selectedFg: createVar(),\n  inputBg: createVar(),\n  inputBorder: createVar(),\n}\n\nexport const root = style({\n  position: 'relative',\n  aspectRatio: '16 / 9',\n  overflow: 'hidden',\n})\n\nconst studioBase = style({\n  position: 'absolute',\n  inset: 0,\n  display: 'flex',\n  flexDirection: 'column',\n  background: colors.bg,\n})\n\nexport const studio = styleVariants({\n  light: [studioBase],\n  dark: [studioBase, {clipPath: DARK_CLIP_PATH}],\n})\n\nexport const navbar = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  gap: 5,\n  height: '18%',\n  padding: '0 5%',\n  borderBottom: `1px solid ${colors.border}`,\n})\n\nexport const logo = style({\n  flex: 'none',\n  width: 8,\n  height: 8,\n  borderRadius: 2,\n  background: colors.accent,\n})\n\nexport const spacer = style({\n  flex: 1,\n})\n\nexport const avatar = style({\n  flex: 'none',\n  width: 8,\n  height: 8,\n  borderRadius: '50%',\n  background: colors.avatar,\n})\n\nexport const body = style({\n  flex: 1,\n  display: 'flex',\n  minHeight: 0,\n})\n\nexport const list = style({\n  flex: 'none',\n  display: 'flex',\n  flexDirection: 'column',\n  width: '36%',\n  borderRight: `1px solid ${colors.border}`,\n})\n\nexport const listRow = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  height: '18%',\n  padding: '0 9%',\n  selectors: {\n    \"&[data-selected='true']\": {\n      background: colors.selectedBg,\n    },\n  },\n})\n\nexport const pane = style({\n  flex: 1,\n  display: 'flex',\n  flexDirection: 'column',\n  minWidth: 0,\n})\n\nexport const form = style({\n  flex: 1,\n  display: 'flex',\n  flexDirection: 'column',\n  gap: 7,\n  padding: '9% 8% 0',\n  minHeight: 0,\n  overflow: 'hidden',\n})\n\nexport const field = style({\n  flex: 'none',\n  display: 'flex',\n  flexDirection: 'column',\n  gap: 3,\n})\n\nexport const input = style({\n  height: 12,\n  borderRadius: 3,\n  background: colors.inputBg,\n  boxShadow: `inset 0 0 0 1px ${colors.inputBorder}`,\n})\n\nexport const footer = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  justifyContent: 'flex-end',\n  height: '20%',\n  padding: '0 8%',\n  borderTop: `1px solid ${colors.border}`,\n})\n\nexport const button = style({\n  width: '32%',\n  height: '50%',\n  borderRadius: 3,\n  background: colors.accent,\n})\n\nconst lineBase = style({\n  flex: 'none',\n  height: LINE,\n  borderRadius: LINE / 2,\n})\n\n/** A line of text, in one of the text colors — its width is set inline */\nexport const line = styleVariants({\n  fg: [lineBase, {background: colors.fg}],\n  muted: [lineBase, {background: colors.mutedFg}],\n  selected: [lineBase, {background: colors.selectedFg}],\n})\n","import {ThemeProvider, useTheme_v2} from '@sanity/ui'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\nimport {assignInlineVars} from '@vanilla-extract/dynamic'\nimport {useMemo} from 'react'\n\nimport {buildTheme} from '../theme/buildTheme'\nimport {BuildThemeOptions} from '../theme/options'\n\nimport {\n  avatar,\n  body,\n  button,\n  colors,\n  field,\n  footer,\n  form,\n  input,\n  line,\n  list,\n  listRow,\n  logo,\n  navbar,\n  pane,\n  root,\n  spacer,\n  studio,\n} from './ThemePreview.css'\n\n/** The document rows in the list pane — the widths of their title lines */\nconst LIST_ROWS = ['62%', '46%', '70%', '52%']\n\n/** The fields in the document form — the widths of their labels */\nconst FIELDS = ['32%', '24%']\n\n/**\n * A tiny, lo-fi mockup of a Studio in the given theme — the navbar over the\n * structure tool with a list of documents on the left and a document form on\n * the right — in both color schemes at once: the light scheme on the left and\n * the dark scheme on the right, split diagonally. It only paints colors the\n * theme options change (backgrounds, text, borders, the accent) so that a\n * glance shows what the theme does to the Studio — with few and bold enough\n * elements to still read when scaled down to a thumbnail.\n *\n * @internal\n */\nexport function ThemePreview(props: {options: BuildThemeOptions}) {\n  const {options} = props\n  const theme = useMemo(() => buildTheme(options), [options])\n\n  return (\n    <div aria-hidden className={root}>\n      <ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>\n      <ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>\n    </div>\n  )\n}\n\nfunction MockStudio(props: {scheme: ThemeColorSchemeKey}) {\n  const {scheme} = props\n  const {color} = useTheme_v2()\n  const selected = color.selectable.default.selected\n  const inputColor = color.input.default.enabled\n\n  return (\n    <div\n      className={studio[scheme]}\n      style={assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })}\n    >\n      <div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>\n\n      <div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n","import {Card} from '@sanity/ui'\n\nimport {BuildThemeOptions} from '../theme/options'\nimport {ThemePreview} from './ThemePreview'\n\n/**\n * The floating preview card of a theme: the lo-fi studio mockup on a raised,\n * rounded card, like the appearance previews in macOS System Settings.\n *\n * @internal\n */\nexport function ThemeThumbnail(props: {options: BuildThemeOptions}) {\n  return (\n    <Card overflow=\"hidden\" radius={3} shadow={1}>\n      <ThemePreview options={props.options} />\n    </Card>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** A removed theme's thumbnail, dimmed to read as removed */\nexport const removedThumbnail = style({\n  opacity: 0.6,\n})\n","import {Box, Button, Flex, Stack, Text} from '@sanity/ui'\n\nimport {useThemer} from './context'\nimport {ScrollArea} from './ScrollArea'\nimport {displayTitle} from './themes'\nimport {ThemeThumbnail} from './ThemeThumbnail'\n\nimport {removedThumbnail} from './RemovedThemes.css'\n\n/**\n * The flow for restoring removed themes: the presets and custom themes the\n * user took out of the list, each with a button to put it back — and, for\n * custom themes, one to delete it for good. The machine leaves the flow once\n * the last one is gone.\n *\n * @internal\n */\nexport function RemovedThemes() {\n  const {removed, send} = useThemer()\n\n  return (\n    <ScrollArea padding={3}>\n      <Stack gap={5}>\n        {removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))}\n      </Stack>\n    </ScrollArea>\n  )\n}\n","import {Button, ButtonProps, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\n\n/**\n * A button with an animated tooltip instead of a `title` attribute, sized like\n * the Studio's own buttons (`padding` and `gap` of 2). Icon-only buttons take\n * the tooltip as their accessible name.\n *\n * @internal\n */\nexport function TooltipButton(props: ButtonProps & {tooltip: string}) {\n  const {tooltip, ...buttonProps} = props\n\n  return (\n    <Tooltip animate content={<Text size={1}>{tooltip}</Text>} placement=\"bottom\" portal>\n      <Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />\n    </Tooltip>\n  )\n}\n","import {ImageIcon} from '@sanity/icons/Image'\nimport {ButtonProps} from '@sanity/ui'\nimport {useRef} from 'react'\n\nimport {TooltipButton} from './TooltipButton'\n\n/**\n * A button that opens the file picker for an image, and hands the chosen file\n * over — the picker is a hidden file input, so nothing is uploaded anywhere.\n *\n * @internal\n */\nexport function ImageFileButton(\n  props: {onFile: (file: File) => void; tooltip: string} & Pick<\n    ButtonProps,\n    'disabled' | 'loading' | 'mode' | 'padding' | 'text' | 'width'\n  >,\n) {\n  const {onFile, ...buttonProps} = props\n  const inputRef = useRef<HTMLInputElement | null>(null)\n\n  return (\n    <>\n      <TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />\n      <input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />\n    </>\n  )\n}\n","import {PixelData} from './imagePalette'\n\n/**\n * The longest side the image is scaled down to before its colors are read —\n * a few thousand pixels are plenty for a palette, and keep it instant\n */\nconst SAMPLE_SIZE = 96\n\n/**\n * Reads the pixels of an image file on device: the image is decoded, drawn\n * onto a small canvas and read back, so nothing leaves the browser.\n *\n * @internal\n */\nexport async function readImagePixels(file: Blob): Promise<PixelData> {\n  const image = await decodeImage(file)\n\n  try {\n    const scale = Math.min(1, SAMPLE_SIZE / Math.max(image.width, image.height))\n    const width = Math.max(1, Math.round(image.width * scale))\n    const height = Math.max(1, Math.round(image.height * scale))\n    const canvas = document.createElement('canvas')\n\n    canvas.width = width\n    canvas.height = height\n\n    const context = canvas.getContext('2d', {willReadFrequently: true})\n\n    if (!context) throw new Error('Could not draw the image')\n\n    context.drawImage(image, 0, 0, width, height)\n\n    return {data: context.getImageData(0, 0, width, height).data, width, height}\n  } finally {\n    // Where `createImageBitmap` is missing, `ImageBitmap` may be too\n    if (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) image.close()\n  }\n}\n\nasync function decodeImage(file: Blob): Promise<ImageBitmap | HTMLImageElement> {\n  if (typeof createImageBitmap === 'function') {\n    try {\n      return await createImageBitmap(file)\n    } catch {\n      // Some browsers cannot decode every format this way (e.g. SVG) — an\n      // image element handles whatever the browser can display\n    }\n  }\n\n  const url = URL.createObjectURL(file)\n\n  try {\n    return await new Promise<HTMLImageElement>((resolve, reject) => {\n      const image = new Image()\n\n      image.addEventListener('load', () => resolve(image), {once: true})\n      image.addEventListener('error', () => reject(new Error('Could not decode the image')), {\n        once: true,\n      })\n      image.src = url\n    })\n  } finally {\n    URL.revokeObjectURL(url)\n  }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useRef, useState} from 'react'\n\nimport {readImagePixels} from './imageFile'\nimport {extractImagePalette, ImagePalette} from './imagePalette'\n\n/**\n * Extracts the palette of image files on device and hands it to `onPalette`,\n * along with the file it came from. Failures end up as a toast.\n *\n * @internal\n */\nexport function useImagePalette(onPalette: (palette: ImagePalette, file: File) => void): {\n  busy: boolean\n  pickImage: (file: File) => void\n} {\n  const toast = useToast()\n  const [busy, setBusy] = useState(false)\n  const onPaletteRef = useRef(onPalette)\n  const mountedRef = useRef(true)\n  // Picks are numbered so that a slow earlier image cannot overwrite a later\n  // pick once its extraction finishes\n  const latestPickRef = useRef(0)\n\n  useEffect(() => {\n    onPaletteRef.current = onPalette\n  }, [onPalette])\n\n  useEffect(() => {\n    mountedRef.current = true\n\n    return () => {\n      mountedRef.current = false\n    }\n  }, [])\n\n  const pickImage = useCallback(\n    (file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    },\n    [toast],\n  )\n\n  return {busy, pickImage}\n}\n","import {createVar, style} from '@vanilla-extract/css'\n\nconst TILE_SIZE = 24\nconst TILE_GAP = 4\n\n/** The image spans both rows of tiles */\nconst IMAGE_SIZE = TILE_SIZE * 2 + TILE_GAP\n\n/** The variant previews are the theme thumbnails, laid out at this width and scaled down */\nexport const VARIANT_WIDTH = 144\n\nexport const VARIANT_GAP = 8\nexport const ROW_PADDING = 12\n\n/** The frame around a variant's thumbnail, on either side */\nexport const VARIANT_FRAME = 4\n\n/** The width of one variant's thumbnail, set on the row once it is measured */\nexport const variantWidth = createVar()\n\n/** How much a variant's thumbnail is scaled down from `VARIANT_WIDTH` */\nexport const variantScale = createVar()\n\nexport const paletteGrid = style({\n  display: 'grid',\n  gridTemplateColumns: `repeat(3, ${TILE_SIZE}px)`,\n  gridAutoRows: TILE_SIZE,\n  gap: TILE_GAP,\n  selectors: {\n    \"&[data-with-image='true']\": {\n      gridTemplateColumns: `${IMAGE_SIZE}px repeat(3, ${TILE_SIZE}px)`,\n    },\n  },\n})\n\nexport const imageTile = style({\n  display: 'block',\n  gridRow: 'span 2',\n  width: IMAGE_SIZE,\n  height: IMAGE_SIZE,\n  borderRadius: 3,\n  objectFit: 'cover',\n  boxShadow: 'inset 0 0 0 1px var(--card-border-color)',\n})\n\nexport const tile = style({\n  display: 'block',\n  borderRadius: 3,\n  boxShadow: 'inset 0 0 0 1px var(--card-border-color)',\n  selectors: {\n    \"&[data-empty='true']\": {\n      background:\n        'repeating-linear-gradient(-45deg, transparent 0 3px, var(--card-border-color) 3px 4px)',\n    },\n  },\n})\n\n/**\n * The variants scroll sideways and snap into place, bleeding into the card's\n * padding so the row runs from edge to edge\n */\nexport const variantRow = style({\n  display: 'flex',\n  gap: VARIANT_GAP,\n  margin: `0 -${ROW_PADDING}px`,\n  padding: `0 ${ROW_PADDING}px`,\n  overflowX: 'auto',\n  scrollSnapType: 'x mandatory',\n  scrollPaddingLeft: ROW_PADDING,\n  scrollbarWidth: 'thin',\n})\n\nexport const variantButton = style({\n  'appearance': 'none',\n  'flex': 'none',\n  'display': 'block',\n  'boxSizing': 'border-box',\n  'width': `calc(${variantWidth} + ${VARIANT_FRAME * 2}px)`,\n  'margin': 0,\n  'padding': 0,\n  'border': 0,\n  'background': 'none',\n  'color': 'inherit',\n  'font': 'inherit',\n  'textAlign': 'center',\n  'cursor': 'pointer',\n  'scrollSnapAlign': 'start',\n  ':focus': {\n    outline: 'none',\n  },\n})\n\n/**\n * Clips the scaled-down thumbnail to its visual size, with room for the ring\n * — drawn inside the frame, like the theme cards', so the scrolling row\n * never clips it\n */\nexport const variantFrame = style({\n  display: 'block',\n  boxSizing: 'border-box',\n  width: `calc(${variantWidth} + ${VARIANT_FRAME * 2}px)`,\n  height: `calc(${variantWidth} * 9 / 16 + ${VARIANT_FRAME * 2}px)`,\n  padding: VARIANT_FRAME,\n  borderRadius: 7,\n  overflow: 'hidden',\n  transition: 'box-shadow 100ms',\n  selectors: {\n    [`${variantButton}:hover &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-border-color)',\n    },\n    [`${variantButton}[aria-pressed='true'] &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-focus-ring-color)',\n    },\n    [`${variantButton}:focus-visible &`]: {\n      outline: '2px solid var(--card-focus-ring-color)',\n      outlineOffset: -2,\n    },\n  },\n})\n\nexport const variantScaleBox = style({\n  display: 'block',\n  width: VARIANT_WIDTH,\n  transform: `scale(${variantScale})`,\n  transformOrigin: 'top left',\n})\n","import {SparklesIcon} from '@sanity/icons/Sparkles'\nimport {Box, Card, Flex, Stack, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {assignInlineVars} from '@vanilla-extract/dynamic'\nimport {useEffect, useMemo, useRef, useState} from 'react'\n\nimport {BuildThemeOptions} from '../theme/options'\nimport {ImageFileButton} from './ImageFileButton'\nimport {\n  applyImagePalette,\n  currentImageVariant,\n  IMAGE_PALETTE_TITLES,\n  IMAGE_PALETTE_VARIANTS,\n  ImagePalette,\n  ImagePaletteKey,\n  ImagePaletteVariant,\n} from './imagePalette'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {TooltipButton} from './TooltipButton'\nimport {useImagePalette} from './useImagePalette'\n\nimport {\n  imageTile,\n  paletteGrid,\n  ROW_PADDING,\n  tile,\n  VARIANT_FRAME,\n  VARIANT_GAP,\n  VARIANT_WIDTH,\n  variantButton,\n  variantFrame,\n  variantRow,\n  variantScale,\n  variantScaleBox,\n  variantWidth,\n} from './ImagePaletteSection.css'\n\n/** The swatches on display: the vibrant family over the muted one */\nconst TILES: ImagePaletteKey[] = [\n  'vibrant',\n  'lightVibrant',\n  'darkVibrant',\n  'muted',\n  'lightMuted',\n  'darkMuted',\n]\n\n/**\n * How many variants show at once: two and a half, so that the cut-off third\n * one gives away that the row scrolls\n */\nconst VISIBLE_VARIANTS = 2.5\n\n/** The width of one variant, before the row has been measured */\nconst FALLBACK_VARIANT_WIDTH = 58\n\n/**\n * Takes the colors of a theme from an image, on device: the image is read\n * into a canvas and its palette extracted right there — nothing is uploaded.\n * Shows the image (while the session lasts) next to its palette, offers a\n * theme variant built around each swatch as a small preview, and a lucky\n * button that picks an interesting one.\n *\n * @internal\n */\nexport function ImagePaletteSection(props: {\n  imageUrl?: string\n  onPalette: (palette: ImagePalette, file: File) => void\n  onVariant: (variant: ImagePaletteVariant) => void\n  onLucky: () => void\n  options: BuildThemeOptions\n  palette?: ImagePalette\n}) {\n  const {imageUrl, onPalette, onVariant, onLucky, options, palette} = props\n  const {busy, pickImage} = useImagePalette(onPalette)\n  const [dragging, setDragging] = useState(false)\n  // `dragleave` also fires when the pointer crosses into a child, so the\n  // highlight tracks how deep the drag is rather than the last event\n  const dragDepth = useRef(0)\n  const current = palette ? currentImageVariant(options, palette) : null\n  const rowRef = useRef<HTMLDivElement | null>(null)\n  const [thumbnailWidth, setThumbnailWidth] = useState(FALLBACK_VARIANT_WIDTH)\n\n  // Size the variants to the row, so two and a half of them are in view\n  useEffect(() => {\n    const row = rowRef.current\n\n    if (!row) return undefined\n\n    const measure = () => {\n      const visible =\n        row.clientWidth - ROW_PADDING - (Math.ceil(VISIBLE_VARIANTS) - 1) * VARIANT_GAP\n\n      // Each variant is its thumbnail plus the frame on either side\n      setThumbnailWidth(Math.max(24, Math.floor(visible / VISIBLE_VARIANTS) - VARIANT_FRAME * 2))\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(row)\n\n    return () => observer.disconnect()\n  }, [palette])\n\n  const variants = useMemo(() => {\n    if (!palette) return []\n\n    return IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )\n  }, [options, palette])\n\n  return (\n    <Card\n      border\n      onDragEnter={(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }}\n      onDragLeave={() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }}\n      onDragOver={(event) => {\n        event.preventDefault()\n      }}\n      onDrop={(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }}\n      padding={3}\n      radius={3}\n      tone={dragging ? 'primary' : 'default'}\n    >\n      <Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>\n    </Card>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** A native color input, trimmed down to its swatch */\nexport const swatch = style({\n  boxSizing: 'border-box',\n  flex: 'none',\n  width: 33,\n  height: 33,\n  padding: 0,\n  border: '1px solid var(--card-border-color)',\n  borderRadius: 4,\n  background: 'none',\n  cursor: 'pointer',\n  selectors: {\n    '&::-webkit-color-swatch-wrapper': {\n      padding: 0,\n    },\n    '&::-webkit-color-swatch': {\n      border: 'none',\n      borderRadius: 3,\n    },\n    '&::-moz-color-swatch': {\n      border: 'none',\n      borderRadius: 3,\n    },\n  },\n})\n\n/** A native range input, themed through `accent-color` */\nexport const range = style({\n  display: 'block',\n  width: '100%',\n  margin: 0,\n  accentColor: 'var(--card-focus-ring-color)',\n})\n\n/** Lets the color row's text shrink and truncate instead of widening the row */\nexport const colorRowText = style({\n  minWidth: 0,\n})\n","import {ResetIcon} from '@sanity/icons/Reset'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Badge, Box, Button, Card, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\nimport {useMemo} from 'react'\nimport {useColorSchemeValue} from 'sanity'\n\nimport {buildPalette, GeneratedColorPalette} from '../theme/buildPalette'\nimport {\n  BuildThemeOptions,\n  ResolvedSchemeOptions,\n  resolveThemeOptions,\n  SCHEMES,\n  SchemeThemeOptions,\n} from '../theme/options'\nimport {useThemer} from './context'\nimport {\n  applyImagePalette,\n  currentImageVariant,\n  ImagePalette,\n  ImagePaletteVariant,\n  pickLuckyVariant,\n} from './imagePalette'\nimport {ImagePaletteSection} from './ImagePaletteSection'\nimport {ScrollArea, ScrollAreaBleed} from './ScrollArea'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {TooltipButton} from './TooltipButton'\n\nimport {colorRowText, range, swatch} from './ThemeEditor.css'\n\nconst SCHEME_TITLES: Record<ThemeColorSchemeKey, string> = {\n  dark: 'Dark mode',\n  light: 'Light mode',\n}\n\n/**\n * Where the split preview shows a scheme: the Studio's own scheme stays next\n * to the sidebar (or at the bottom, stacked on small screens), the other one\n * takes the far side\n */\nfunction splitHint(own: boolean, mobile: boolean): string {\n  if (mobile) return own ? 'Shown at the bottom' : 'Shown at the top'\n\n  return own ? 'Shown on the right, next to the themer' : 'Shown on the left'\n}\n\nconst SCHEME_OPTION_KEYS: Array<keyof SchemeThemeOptions> = [\n  'accent',\n  'text',\n  'background',\n  'contrast',\n]\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 */\n/**\n * The flow for editing one of the user's own themes: its title, a live\n * preview, and a card per color scheme with the accent/text/background\n * pickers and the contrast slider of that scheme. Every change applies to the\n * whole Studio right away — in the scheme the Studio is showing, or in both\n * side by side in the split preview.\n *\n * @internal\n */\nexport function ThemeEditor(props: {focusTitle: boolean; slug: string}) {\n  const {focusTitle, slug} = props\n  const {themes, images, split, mobile, send} = useThemer()\n  const theme = themes.find((candidate) => candidate.slug === slug && candidate.source === 'custom')\n\n  // The machine only enters the edit flow for a listed custom theme, and\n  // leaves it as soon as the theme is removed or deleted\n  if (!theme) return null\n\n  const applyVariant = (variant: ImagePaletteVariant | null) => {\n    if (!theme.palette || variant === null) return\n\n    send({\n      type: 'theme.update',\n      slug,\n      options: applyImagePalette(theme.options, theme.palette, variant),\n    })\n  }\n\n  return (\n    <ThemeEditorForm\n      focusTitle={focusTitle}\n      imageUrl={images[slug]}\n      onDone={() => send({type: 'flow.list'})}\n      onLucky={() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }}\n      onOptionsChange={(options) => send({type: 'theme.update', slug, options})}\n      onPalette={(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })\n      }\n      onRemove={() => send({type: 'theme.remove', slug})}\n      onTitleChange={(title) => send({type: 'theme.update', slug, title})}\n      onVariant={applyVariant}\n      options={theme.options}\n      palette={theme.palette}\n      split={split}\n      mobile={mobile}\n      title={theme.title}\n    />\n  )\n}\n\n// Split from `ThemeEditor` so that the derived values below can be hooks\n// while the editor bails out early when the theme is gone\nfunction ThemeEditorForm(props: {\n  focusTitle: boolean\n  imageUrl?: string\n  onDone: () => void\n  onLucky: () => void\n  onOptionsChange: (options: BuildThemeOptions) => void\n  onPalette: (palette: ImagePalette, file: File) => void\n  onRemove: () => void\n  onTitleChange: (title: string) => void\n  onVariant: (variant: ImagePaletteVariant) => void\n  options: BuildThemeOptions\n  palette?: ImagePalette\n  /** Whether the Studio shows in light and dark side by side */\n  split: boolean\n  /** Whether the split preview stacks, on a small screen */\n  mobile: boolean\n  title: string\n}) {\n  const {\n    focusTitle,\n    imageUrl,\n    onDone,\n    onLucky,\n    onOptionsChange,\n    onPalette,\n    onRemove,\n    onTitleChange,\n    onVariant,\n    options,\n    palette,\n    split,\n    mobile,\n    title,\n  } = props\n  // The scheme the Studio is showing, with the appearance setting resolved\n  const studioScheme = useColorSchemeValue()\n  const resolved = useMemo(() => resolveThemeOptions(options), [options])\n  const palettes = useMemo(() => buildPalette(options), [options])\n\n  const patchScheme = (scheme: ThemeColorSchemeKey, changes: Partial<SchemeThemeOptions>) => {\n    const values: SchemeThemeOptions = {...options[scheme], ...changes}\n\n    // Clearing an option means falling back to its default, which is its absence\n    for (const key of SCHEME_OPTION_KEYS) {\n      if (values[key] === undefined) delete values[key]\n    }\n\n    const next: BuildThemeOptions = {...options}\n\n    if (Object.keys(values).length === 0) {\n      delete next[scheme]\n    } else {\n      next[scheme] = values\n    }\n\n    onOptionsChange(next)\n  }\n\n  return (\n    <>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>\n    </>\n  )\n}\n\n/**\n * The colors of one scheme. The cards span the sidebar edge to edge, one\n * after the other with a border between them, in the sidebar's own scheme —\n * the swatches show the colors they edit. The scheme the Studio is showing is\n * marked as active: its changes show up in the Studio right away, the other\n * scheme's only once the appearance setting switches to it — or both are\n * active, in the split preview.\n */\nfunction SchemeCard(props: {\n  active: boolean\n  onChange: (changes: Partial<SchemeThemeOptions>) => void\n  options: SchemeThemeOptions\n  palette: GeneratedColorPalette\n  resolved: ResolvedSchemeOptions\n  scheme: ThemeColorSchemeKey\n  split: boolean\n  /** Where the split preview shows this scheme */\n  splitHint: string\n}) {\n  const {active, onChange, options, palette, resolved, scheme, split, splitHint} = props\n  const name = SCHEME_TITLES[scheme]\n\n  return (\n    <Card borderTop padding={3}>\n      <Stack gap={4}>\n        <Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>\n\n        <ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />\n        <ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />\n        <ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />\n\n        <Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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      </Stack>\n    </Card>\n  )\n}\n\n/** One color of a scheme: a swatch with its value and an optional reset button */\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 or a default rather than explicitly set */\n  auto?: boolean\n  /** What the value is when it is not set: derived (`auto`) or the stock one (`default`) */\n  autoLabel?: 'auto' | 'default'\n  /** The accessible name of the picker */\n  label: string\n  onChange: (value: string) => void\n  onClear?: () => void\n  title: string\n  value: string\n}) {\n  const {adjusted, auto, autoLabel = 'auto', label, onChange, onClear, title, value} = props\n\n  return (\n    <Flex align=\"center\" gap={2}>\n      <input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />\n      <Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>\n      {onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )}\n    </Flex>\n  )\n}\n","import {isColor} from '../lib/mix'\nimport {\n  BuildThemeOptions,\n  MAXIMUM_CONTRAST,\n  MINIMUM_CONTRAST,\n  SCHEMES,\n  SchemeThemeOptions,\n} from '../theme/options'\nimport {displayTitle} from './themes'\n\n/** What a theme code carries: a theme's title and its options @internal */\nexport interface SharedTheme {\n  title: string\n  options: BuildThemeOptions\n}\n\n/**\n * The version of the code format, the first byte of every code — bumped if\n * the layout below ever changes, so older codes can still be told apart\n */\nconst VERSION = 1\n\n/** The fields a scheme's options can set, in the order their bytes go */\nconst FIELDS = ['accent', 'text', 'background', 'contrast'] as const\n\n/**\n * Turns a theme into a short code to share in a message: `title`, and the\n * colors and contrasts of both schemes, packed into bytes — one flag byte says\n * which of the eight fields are set, each color is its three RGB bytes and a\n * contrast one byte, and the title takes up the rest — then base64url'd, so\n * it is one word without padding, safe in URLs and chat. A theme setting\n * everything comes to about 30 bytes plus its title.\n *\n * @internal\n */\nexport function encodeTheme(theme: SharedTheme): string {\n  const bytes: number[] = [VERSION, 0]\n  let flags = 0\n\n  SCHEMES.forEach((scheme, schemeIndex) => {\n    const options: SchemeThemeOptions = theme.options[scheme] ?? {}\n\n    FIELDS.forEach((field, fieldIndex) => {\n      const value = options[field]\n\n      if (value === undefined) return\n\n      if (field === 'contrast') {\n        if (typeof value !== 'number' || !Number.isFinite(value)) return\n\n        bytes.push(Math.round(Math.min(MAXIMUM_CONTRAST, Math.max(MINIMUM_CONTRAST, value))))\n      } else {\n        if (typeof value !== 'string' || !isColor(value)) return\n\n        bytes.push(...rgbBytes(value))\n      }\n\n      flags |= 1 << (schemeIndex * FIELDS.length + fieldIndex)\n    })\n  })\n\n  bytes[1] = flags\n  bytes.push(...new TextEncoder().encode(theme.title.trim()))\n\n  return toBase64Url(Uint8Array.from(bytes))\n}\n\n/**\n * Reads a theme back out of a code — as pasted, so surrounding whitespace and\n * words around the code are fine: the first word that is a code counts. `null`\n * when nothing in the text is one.\n *\n * @internal\n */\nexport function decodeTheme(text: string): SharedTheme | null {\n  for (const word of text.trim().split(/\\s+/)) {\n    const theme = decodeCode(word)\n\n    if (theme) return theme\n  }\n\n  return null\n}\n\nfunction decodeCode(code: string): SharedTheme | null {\n  const bytes = fromBase64Url(code)\n\n  if (!bytes || bytes.length < 2 || bytes[0] !== VERSION) return null\n\n  const flags = bytes[1]\n  const options: BuildThemeOptions = {}\n  let offset = 2\n\n  for (const [schemeIndex, scheme] of SCHEMES.entries()) {\n    const schemeOptions: SchemeThemeOptions = {}\n\n    for (const [fieldIndex, field] of FIELDS.entries()) {\n      if (!(flags & (1 << (schemeIndex * FIELDS.length + fieldIndex)))) continue\n\n      if (field === 'contrast') {\n        if (offset + 1 > bytes.length) return null\n\n        schemeOptions.contrast = Math.min(\n          MAXIMUM_CONTRAST,\n          Math.max(MINIMUM_CONTRAST, bytes[offset]),\n        )\n        offset += 1\n      } else {\n        if (offset + 3 > bytes.length) return null\n\n        schemeOptions[field] = hexColor(bytes.subarray(offset, offset + 3))\n        offset += 3\n      }\n    }\n\n    if (Object.keys(schemeOptions).length > 0) options[scheme] = schemeOptions\n  }\n\n  let title: string\n\n  try {\n    title = new TextDecoder('utf-8', {fatal: true}).decode(bytes.subarray(offset))\n  } catch {\n    return null\n  }\n\n  return {title: displayTitle(title), options}\n}\n\n/** The three RGB bytes of a `#rgb` or `#rrggbb` color */\nfunction rgbBytes(color: string): number[] {\n  const hex = color.length === 4 ? color.slice(1).replaceAll(/./g, '$&$&') : color.slice(1)\n\n  return [0, 2, 4].map((start) => parseInt(hex.slice(start, start + 2), 16))\n}\n\nfunction hexColor(rgb: Uint8Array): string {\n  return `#${[...rgb].map((byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n  let binary = ''\n\n  for (const byte of bytes) binary += String.fromCharCode(byte)\n\n  return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '')\n}\n\nfunction fromBase64Url(code: string): Uint8Array | null {\n  if (!/^[A-Za-z0-9_-]+$/.test(code)) return null\n\n  const base64 = code.replaceAll('-', '+').replaceAll('_', '/')\n\n  try {\n    return Uint8Array.from(atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '=')), (char) =>\n      char.charCodeAt(0),\n    )\n  } catch {\n    return null\n  }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useEffect} from 'react'\n\nimport {useThemer} from './context'\nimport {decodeTheme, encodeTheme, SharedTheme} from './share'\nimport {displayTitle} from './themes'\n\n/**\n * Copying a theme as a code to share, and adding a theme from a code someone\n * shared — with toasts telling how it went.\n *\n * @internal\n */\nexport function useThemeCodes(): {\n  copyTheme: (theme: SharedTheme) => Promise<void>\n  /** Adds the theme in the text, if there is one — the result says whether there was */\n  addThemeFromText: (text: string) => boolean\n  /** Adds the theme on the clipboard, if there is one and the browser hands the clipboard over */\n  addThemeFromClipboard: () => Promise<'added' | 'no-theme' | 'no-clipboard'>\n} {\n  const {send} = useThemer()\n  const toast = useToast()\n\n  const copyTheme = async (theme: SharedTheme) => {\n    const title = displayTitle(theme.title)\n\n    try {\n      await navigator.clipboard.writeText(encodeTheme(theme))\n      toast.push({\n        status: 'success',\n        title: `Copied ${title} as a code`,\n        description: 'Paste it in the themer of another Studio to add the theme there',\n      })\n    } catch {\n      toast.push({status: 'error', title: `Could not copy ${title}`})\n    }\n  }\n\n  const addThemeFromText = (text: string) => {\n    const theme = decodeTheme(text)\n\n    if (!theme) return false\n\n    send({type: 'theme.import', title: theme.title, options: theme.options})\n    toast.push({status: 'success', title: `Added ${theme.title}`})\n\n    return true\n  }\n\n  const addThemeFromClipboard = async () => {\n    let text: string\n\n    try {\n      text = await navigator.clipboard.readText()\n    } catch {\n      return 'no-clipboard'\n    }\n\n    return addThemeFromText(text) ? 'added' : 'no-theme'\n  }\n\n  return {copyTheme, addThemeFromText, addThemeFromClipboard}\n}\n\n/**\n * Adds a theme pasted anywhere in the Studio while the themer's list is\n * showing — pastes into inputs and other editable things are theirs.\n *\n * @internal\n */\nexport function usePasteThemeCodes(): void {\n  const {open, send} = useThemer()\n  const toast = useToast()\n\n  useEffect(() => {\n    if (!open) return undefined\n\n    const handlePaste = (event: ClipboardEvent) => {\n      if (isEditable(event.target)) return\n\n      const theme = decodeTheme(event.clipboardData?.getData('text/plain') ?? '')\n\n      if (!theme) return\n\n      event.preventDefault()\n      send({type: 'theme.import', title: theme.title, options: theme.options})\n      toast.push({status: 'success', title: `Added ${theme.title}`})\n    }\n\n    document.addEventListener('paste', handlePaste)\n\n    return () => document.removeEventListener('paste', handlePaste)\n  }, [open, send, toast])\n}\n\nfunction isEditable(target: EventTarget | null): boolean {\n  return (\n    target instanceof HTMLElement &&\n    (target.isContentEditable || target.matches('input, textarea, select'))\n  )\n}\n","import {Button, Card, Dialog, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport {useThemeCodes} from './useThemeCodes'\n\n/**\n * Where a theme code someone shared gets pasted by hand — for browsers that\n * do not hand the clipboard over, and for codes that are not on it.\n *\n * @internal\n */\nexport function PasteThemeDialog(props: {onClose: () => void}) {\n  const {onClose} = props\n  const {addThemeFromText} = useThemeCodes()\n  const [text, setText] = useState('')\n  const [invalid, setInvalid] = useState(false)\n\n  const add = () => {\n    if (addThemeFromText(text)) {\n      onClose()\n    } else {\n      setInvalid(true)\n    }\n  }\n\n  return (\n    <Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>\n      }\n      header=\"Add a shared theme\"\n      id=\"themer-paste\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={0}\n    >\n      <form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>\n    </Dialog>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\nexport const root = style({\n  position: 'relative',\n})\n\n/** A bare button, so that the thumbnail and the title can carry the styling */\nexport const pickButton = style({\n  'appearance': 'none',\n  'display': 'block',\n  'boxSizing': 'border-box',\n  'width': '100%',\n  'margin': 0,\n  'padding': 0,\n  'border': 0,\n  'background': 'none',\n  'color': 'inherit',\n  'font': 'inherit',\n  'textAlign': 'center',\n  'cursor': 'pointer',\n  ':focus': {\n    outline: 'none',\n  },\n})\n\n/**\n * Wraps the thumbnail with room for the ring that marks the applied theme —\n * hovering shows a faint ring, the applied theme the focus ring color, and\n * keyboard focus an outline. The rings are drawn inside the frame's padding,\n * so nothing sticks out to be clipped by the scrolling list.\n */\nexport const frame = style({\n  display: 'block',\n  padding: 4,\n  borderRadius: 10,\n  transition: 'box-shadow 100ms',\n  selectors: {\n    [`${pickButton}:hover &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-border-color)',\n    },\n    [`${pickButton}[aria-pressed='true'] &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-focus-ring-color)',\n    },\n    [`${pickButton}:focus-visible &`]: {\n      outline: '2px solid var(--card-focus-ring-color)',\n      outlineOffset: -2,\n    },\n  },\n})\n\n/**\n * The actions menu sits on the thumbnail's top right corner, like the actions\n * of an image input, and only shows on hover, on keyboard focus, and while it\n * is open — its popover is portaled, so an open menu does not count as focus\n * within\n */\nexport const menuSlot = style({\n  position: 'absolute',\n  top: 10,\n  right: 10,\n  opacity: 0,\n  transition: 'opacity 100ms',\n  selectors: {\n    [`${root}:hover &, ${root}:focus-within &, &[data-visible='true']`]: {\n      opacity: 1,\n    },\n  },\n})\n\n/** The dark card behind the menu button sizes to the button, not the slot */\nexport const menuCard = style({\n  display: 'inline-block',\n})\n","import {ArrowDownIcon} from '@sanity/icons/ArrowDown'\nimport {ArrowUpIcon} from '@sanity/icons/ArrowUp'\nimport {CopyIcon} from '@sanity/icons/Copy'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {EllipsisHorizontalIcon} from '@sanity/icons/EllipsisHorizontal'\nimport {ShareIcon} from '@sanity/icons/Share'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Text, useRootTheme} from '@sanity/ui'\nimport {Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {Reorder, useDragControls} from 'motion/react'\nimport {useRef, useState} from 'react'\nimport scrollIntoView from 'scroll-into-view-if-needed'\n\nimport {useThemer} from './context'\nimport {displayTitle, ThemerTheme} from './themes'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {useThemeCodes} from './useThemeCodes'\n\nimport {frame, menuCard, menuSlot, pickButton, root} from './ThemeCard.css'\n\n/**\n * Scrolls the applied theme's card into view when it is not already, as a\n * ref: the list scrolls to it as it mounts — coming back from the editor or\n * the removed themes — and when another theme gets applied\n */\nfunction scrollRefIntoViewIfNeeded(node: HTMLElement | null) {\n  if (node) scrollIntoView(node, {block: 'nearest', scrollMode: 'if-needed'})\n}\n\n/**\n * One theme in the list: the floating preview with the title below it, like\n * an appearance option in macOS System Settings. Clicking it applies the\n * theme to the whole Studio, dragging it moves the theme to another place in\n * the list; its menu holds the move, edit, duplicate and remove flows that\n * apply to the theme.\n *\n * @internal\n */\nexport function ThemeCard(props: {active: boolean; theme: ThemerTheme}) {\n  const {active, theme} = props\n  const {themes, send} = useThemer()\n  const {copyTheme} = useThemeCodes()\n  const {scheme} = useRootTheme()\n  const [menuOpen, setMenuOpen] = useState(false)\n  const dragControls = useDragControls()\n  // Letting go of a drag also clicks the card, and that click must not pick\n  const dragged = useRef(false)\n  const title = displayTitle(theme.title)\n  const index = themes.findIndex((candidate) => candidate.slug === theme.slug)\n\n  const moveTo = (to: number) => {\n    const order = themes.map((candidate) => candidate.slug)\n\n    order.splice(to, 0, ...order.splice(index, 1))\n    send({type: 'theme.reorder', order})\n  }\n\n  return (\n    <Reorder.Item\n      as=\"div\"\n      className={root}\n      dragControls={dragControls}\n      dragListener={false}\n      onDragEnd={() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }}\n      onDragStart={() => {\n        dragged.current = true\n      }}\n      ref={active ? scrollRefIntoViewIfNeeded : undefined}\n      value={theme.slug}\n      whileDrag={{scale: 1.04}}\n    >\n      <button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>\n\n      {/* The tooltip wraps a card rather than the button: the menu button\n          clones its button to wire it up, which a tooltip in between would\n          swallow. The card keeps the button dark, as it sits on the dark\n          half of the thumbnail, while the menu opens in the sidebar's scheme */}\n      <div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>\n    </Reorder.Item>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\nimport {MAXIMUM_WIDTH, MINIMUM_WIDTH} from './sidebarWidth'\n\nimport {sidebarContent} from './ResizableSidebar.css'\n\nconst CARD_GAP = 16\n\n/**\n * The theme cards flow into two columns once the sidebar has been dragged a\n * third of the way from its narrowest to its widest. The breakpoints are\n * container queries on the sidebar's content (`ResizableSidebar`), which is\n * as wide as the sidebar itself.\n */\nconst TWO_COLUMNS_FROM = MINIMUM_WIDTH + (MAXIMUM_WIDTH - MINIMUM_WIDTH) * 0.3\n\n/** Three columns on the wider small screens the sidebar covers, where two would be huge */\nconst THREE_COLUMNS_FROM = 480\n\n/**\n * The columns share the width equally whatever the titles: a plain `1fr` may\n * not shrink below a card's min-content width, and a card's title does not\n * wrap, so one long title would widen its column past the sidebar\n */\nconst COLUMN = 'minmax(0, 1fr)'\n\nexport const cardGrid = style({\n  'display': 'grid',\n  'gridTemplateColumns': COLUMN,\n  'gap': CARD_GAP,\n  '@container': {\n    [`${sidebarContent} (min-width: ${TWO_COLUMNS_FROM}px)`]: {\n      gridTemplateColumns: `repeat(2, ${COLUMN})`,\n    },\n    [`${sidebarContent} (min-width: ${THREE_COLUMNS_FROM}px)`]: {\n      gridTemplateColumns: `repeat(3, ${COLUMN})`,\n    },\n  },\n})\n","import {AddIcon} from '@sanity/icons/Add'\nimport {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {RestoreIcon} from '@sanity/icons/Restore'\nimport {Box, Button, Card, Flex, Stack} from '@sanity/ui'\nimport {MotionConfig, Reorder} from 'motion/react'\nimport {useState} from 'react'\n\nimport {useThemer} from './context'\nimport {ImageFileButton} from './ImageFileButton'\nimport {optionsFromImagePalette, titleFromFileName} from './imagePalette'\nimport {PasteThemeDialog} from './PasteThemeDialog'\nimport {ScrollArea} from './ScrollArea'\nimport {ThemeCard} from './ThemeCard'\nimport {TooltipButton} from './TooltipButton'\nimport {useImagePalette} from './useImagePalette'\nimport {usePasteThemeCodes, useThemeCodes} from './useThemeCodes'\n\nimport {cardGrid} from './ThemeList.css'\n\n/**\n * One column at the sidebar's default width; wider sidebars — and the\n * overlay on small screens — fit more cards per row\n */\n/**\n * The flow for picking a theme: a grid of theme cards — the configured theme,\n * the presets and the user's own themes — that drag into the order the user\n * wants, with the entry points to the add and restore flows below. A theme\n * code someone shared pastes right into the list, or through the paste button.\n *\n * @internal\n */\nexport function ThemeList() {\n  const {themes, removed, active, send} = useThemer()\n  const {addThemeFromClipboard} = useThemeCodes()\n  const [pasting, setPasting] = useState(false)\n\n  usePasteThemeCodes()\n\n  const {busy, pickImage} = useImagePalette((palette, file) =>\n    send({\n      type: 'theme.add',\n      title: titleFromFileName(file.name),\n      options: optionsFromImagePalette(palette),\n      palette,\n      imageUrl: URL.createObjectURL(file),\n    }),\n  )\n\n  return (\n    <>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>\n\n      {pasting && <PasteThemeDialog onClose={() => setPasting(false)} />}\n    </>\n  )\n}\n","import {BuildThemeOptions, SCHEMES, SchemeThemeOptions} 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 in\n * each scheme.\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 lines: string[] = []\n\n  for (const scheme of SCHEMES) {\n    const values = minimized[scheme]\n\n    if (values) lines.push(serializeScheme(scheme, values))\n  }\n\n  return `import {buildTheme} from '@sanity/themer'\\n\\nexport const theme = buildTheme({\\n${lines.join('\\n')}\\n})\\n`\n}\n\n/** A scheme with up to two options fits on one line, more spread out */\nfunction serializeScheme(scheme: string, values: SchemeThemeOptions): string {\n  const entries: string[] = []\n\n  if (values.accent !== undefined) entries.push(`accent: '${values.accent}'`)\n  if (values.text !== undefined) entries.push(`text: '${values.text}'`)\n  if (values.background !== undefined) entries.push(`background: '${values.background}'`)\n  if (values.contrast !== undefined) entries.push(`contrast: ${values.contrast}`)\n\n  if (entries.length <= 2) {\n    return `  ${scheme}: {${entries.join(', ')}},`\n  }\n\n  return `  ${scheme}: {\\n${entries.map((entry) => `    ${entry},`).join('\\n')}\\n  },`\n}\n","import {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {Box, Button, Card, Dialog, Flex, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {useToast} from '@sanity/ui/toast'\nimport {registerLanguage} from 'react-refractor'\nimport typescript from 'refractor/typescript'\n\nimport {createThemeSnippet} from './snippet'\nimport {displayTitle, ThemerTheme} from './themes'\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 dialog keeps losing. Registering the one\n// language the snippet needs keeps it highlighted from the first render.\nregisterLanguage(typescript)\n\n/**\n * Shows the `buildTheme` snippet that makes a theme permanent, in a dialog so\n * that it does not take up sidebar space or make the sidebar scroll as the\n * snippet changes shape with the theme.\n *\n * @internal\n */\nexport function ThemeSnippetDialog(props: {onClose: () => void; theme: ThemerTheme}) {\n  const {onClose, theme} = props\n  const toast = useToast()\n  const snippet = createThemeSnippet(theme.options)\n\n  const handleCopy = async () => {\n    try {\n      await navigator.clipboard.writeText(snippet)\n      toast.push({status: 'success', title: 'Copied the theme to the clipboard'})\n    } catch {\n      toast.push({status: 'error', title: 'Could not copy the theme'})\n    }\n  }\n\n  return (\n    <Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>\n      }\n      header=\"Add to your config\"\n      id=\"themer-snippet\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={1}\n    >\n      <Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>\n    </Dialog>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** Lets the title shrink and truncate instead of pushing the buttons out */\nexport const title = style({\n  minWidth: 0,\n})\n","import {ArrowLeftIcon} from '@sanity/icons/ArrowLeft'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {CodeBlockIcon} from '@sanity/icons/CodeBlock'\nimport {SplitVerticalIcon} from '@sanity/icons/SplitVertical'\nimport {Box, Card, Flex, Text} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport {useThemer} from './context'\nimport {RemovedThemes} from './RemovedThemes'\nimport {ThemeEditor} from './ThemeEditor'\nimport {ThemeList} from './ThemeList'\nimport {ThemeSnippetDialog} from './ThemeSnippetDialog'\nimport {TooltipButton} from './TooltipButton'\n\nimport {title} from './ThemerSidebar.css'\n\nconst VIEW_TITLES = {\n  list: 'Themer',\n  edit: 'Edit theme',\n  removed: 'Removed themes',\n} as const\n\n/**\n * The themer sidebar: a header that navigates between the flows and toggles\n * the split preview, the flow itself — picking a theme, editing one, or\n * restoring removed ones — and the dialog with the `buildTheme` snippet of\n * the applied theme.\n *\n * @internal\n */\nexport function ThemerSidebar() {\n  const {active, split, view, navbarHeight, send} = useThemer()\n  const [snippetOpen, setSnippetOpen] = useState(false)\n  const inList = view.name === 'list'\n\n  return (\n    <Card height=\"fill\">\n      <Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>\n\n      {snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />}\n    </Card>\n  )\n}\n","import {createContainer, createViewTransition, style} from '@vanilla-extract/css'\n\n/**\n * The view transition group of the sidebar, which the split preview's\n * transition (see `ThemerLayout.css.ts`) leaves alone: it never animates, and\n * the Studio copies animating underneath never paint over it\n */\nexport const sidebarTransition = createViewTransition()\n\n/** The sidebar's content, which the content's layout queries — as wide as the sidebar itself */\nexport const sidebarContent = createContainer()\n\nexport const sidebar = style({\n  flex: 'none',\n  viewTransitionName: sidebarTransition,\n  selectors: {\n    // On small screens the sidebar covers the Studio instead of standing next to it\n    \"&[data-overlay='true']\": {\n      position: 'absolute',\n      inset: 0,\n      width: 'auto',\n    },\n  },\n})\n\n/**\n * Draws the sidebar's border and gives the resize handle its card colors. It\n * does not clip, so the handle can straddle the border — the content is\n * clipped one level down instead.\n */\nexport const frame = style({\n  position: 'relative',\n})\n\n/**\n * Clips the content, and is the container its layout queries: as wide as\n * the sidebar, whether or not a scrollbar takes room inside — see the theme\n * grid's columns in `ThemeList.css.ts`\n */\nexport const content = style({\n  containerType: 'inline-size',\n  containerName: sidebarContent,\n})\n\n/**\n * The grab area along the sidebar's left edge. It straddles the border so it\n * is easy to hit, and highlights while hovered, focused or dragged.\n */\nexport const resizeHandle = style({\n  'position': 'absolute',\n  'top': 0,\n  'bottom': 0,\n  'left': -3,\n  'zIndex': 1,\n  'width': 7,\n  'cursor': 'col-resize',\n  'touchAction': 'none',\n  '::after': {\n    content: '',\n    position: 'absolute',\n    top: 0,\n    bottom: 0,\n    left: 2,\n    width: 3,\n    background: 'var(--card-focus-ring-color)',\n    opacity: 0,\n    transition: 'opacity 100ms',\n  },\n  ':focus': {\n    outline: 'none',\n  },\n  'selectors': {\n    \"&:hover::after, &:focus-visible::after, &[data-dragging='true']::after\": {\n      opacity: 1,\n    },\n  },\n})\n","import {Box, Card, Layer} from '@sanity/ui'\nimport {useCallback, useEffect, useRef, useState} from 'react'\n\nimport {MAXIMUM_WIDTH, MINIMUM_WIDTH} from './sidebarWidth'\nimport {ThemerSidebar} from './ThemerSidebar'\n\nimport {content, frame, resizeHandle, sidebar} from './ResizableSidebar.css'\n\n/** How far one arrow key press resizes the sidebar */\nconst KEYBOARD_STEP = 16\n\nconst WIDTH_STORAGE_KEY = 'sanityStudio:themer:width'\n\nfunction clampWidth(width: number): number {\n  return Math.min(MAXIMUM_WIDTH, Math.max(MINIMUM_WIDTH, Math.round(width)))\n}\n\nfunction readStoredWidth(): number {\n  try {\n    const stored = Number(localStorage.getItem(WIDTH_STORAGE_KEY))\n\n    return Number.isFinite(stored) && stored > 0 ? clampWidth(stored) : MINIMUM_WIDTH\n  } catch {\n    return MINIMUM_WIDTH\n  }\n}\n\nfunction writeStoredWidth(width: number): void {\n  try {\n    if (width === MINIMUM_WIDTH) {\n      localStorage.removeItem(WIDTH_STORAGE_KEY)\n    } else {\n      localStorage.setItem(WIDTH_STORAGE_KEY, String(width))\n    }\n  } catch {\n    // Storage can be unavailable (e.g. private browsing) — the width just won't persist\n  }\n}\n\n/**\n * The themer sidebar, in a layer along the right edge of the Studio. Its left\n * edge drags (or arrow-keys) it wider, up to twice its default width — the\n * width sticks between sessions. As an overlay (small screens) it covers the\n * Studio edge to edge instead, with nothing to resize.\n *\n * @internal\n */\nexport default function ResizableSidebar(props: {overlay: boolean}) {\n  const {overlay} = props\n  const [width, setWidth] = useState(readStoredWidth)\n  const [dragging, setDragging] = useState(false)\n  const drag = useRef<{pointerId: number; startX: number; startWidth: number} | null>(null)\n\n  useEffect(() => writeStoredWidth(width), [width])\n\n  const handlePointerDown = useCallback(\n    (event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    },\n    [width],\n  )\n\n  const handlePointerMove = useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }, [])\n\n  const handlePointerUp = useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }, [])\n\n  const handleKeyDown = useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }, [])\n\n  return (\n    <Layer\n      className={sidebar}\n      data-overlay={overlay}\n      style={overlay ? undefined : {width}}\n      zOffset={100}\n    >\n      <Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>\n    </Layer>\n  )\n}\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"ResizableSidebar-DD787kQr.js","names":["root","() => lastGutter","() => {\n    const element = ref.current\n\n    if (!element) return undefined\n\n    // The reserved gutter is the part of the box the content cannot use\n    const measure = () => {\n      lastGutter = element.offsetWidth - element.clientWidth\n      setGutter(lastGutter)\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(element)\n\n    return () => observer.disconnect()\n  }","[]","{\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }","space[padding]","Math.max(0, space[padding] - gutter)","useMemo<ScrollAreaInset>(\n    () => ({\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }),\n    [gutter, padding, space],\n  )","{paddingRight: inset.right}","right","<ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>","ScrollAreaInsetContext.Provider","<Box\n      className={root}\n      flex={1}\n      overflow=\"auto\"\n      padding={padding}\n      ref={ref}\n      style={{paddingRight: inset.right}}\n    >\n      <ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>\n    </Box>","{marginLeft: -left, marginRight: -right, marginBottom: -bottom}","-left","-right","-bottom","<div style={{marginLeft: -left, marginRight: -right, marginBottom: -bottom}}>\n      {props.children}\n    </div>","children","_c","_temp","root","root","buildTheme(options)","useMemo(() => buildTheme(options), [options])","<MockStudio scheme=\"light\" />","<ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>","<MockStudio scheme=\"dark\" />","<ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>","<div aria-hidden className={root}>\n      <ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>\n      <ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>\n    </div>","assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })","bg","border","fg","<div className={logo} />","<div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>","<div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>","(width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          }","<div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>","(width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            )","<div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>","<div\n      className={studio[scheme]}\n      style={assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })}\n    >\n      <div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>\n\n      <div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>\n    </div>","studio[scheme]","width","FIELDS","_c","root","_temp","<Card overflow=\"hidden\" radius={3} shadow={1}>\n      <ThemePreview options={props.options} />\n    </Card>","options","_c","removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))","(theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        )","<ScrollArea padding={3}>\n      <Stack gap={5}>\n        {removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))}\n      </Stack>\n    </ScrollArea>","_c","<Text size={1}>{tooltip}</Text>","<Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />","buttonProps.text === undefined ? tooltip : undefined","<Tooltip animate content={<Text size={1}>{tooltip}</Text>} placement=\"bottom\" portal>\n      <Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />\n    </Tooltip>","_c","() => inputRef.current?.click()","<TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />","<input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />","<>\n      <TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />\n      <input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />\n    </>","_c","_Fragment","() => {\n    onPaletteRef.current = onPalette\n  }","[onPalette]","() => {\n    mountedRef.current = true\n\n    return () => {\n      mountedRef.current = false\n    }\n  }","[]","(file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    }","(swatch) => swatch === null","useCallback(\n    (file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    },\n    [toast],\n  )","{busy, pickImage}","_c","_temp","palette ? currentImageVariant(options, palette) : null","() => {\n    const row = rowRef.current\n\n    if (!row) return undefined\n\n    const measure = () => {\n      const visible =\n        row.clientWidth - ROW_PADDING - (Math.ceil(VISIBLE_VARIANTS) - 1) * VARIANT_GAP\n\n      // Each variant is its thumbnail plus the frame on either side\n      setThumbnailWidth(Math.max(24, Math.floor(visible / VISIBLE_VARIANTS) - VARIANT_FRAME * 2))\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(row)\n\n    return () => observer.disconnect()\n    // oxlint-disable-next-line react/exhaustive-effect-dependencies -- the row only renders with a palette, so a new palette has a new row to observe\n  }","[palette]","useMemo(() => {\n    if (!palette) return []\n\n    return IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )\n  }, [options, palette])","[]","IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )","(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }","() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }","(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }","event","<Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>","palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )","<Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>","palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )","{variant, title, options: variantOptions}","variant","title","<Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>","<Card\n      border\n      onDragEnter={(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }}\n      onDragLeave={() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }}\n      onDragOver={(event) => {\n        event.preventDefault()\n      }}\n      onDrop={(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }}\n      padding={3}\n      radius={3}\n      tone={dragging ? 'primary' : 'default'}\n    >\n      <Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>\n    </Card>","dragging ? 'primary' : 'default'","(event) => {\n        event.preventDefault()\n      }","_c","_Fragment","_temp","themes.find((candidate) => candidate.slug === slug && candidate.source === 'custom')","(candidate) => candidate.slug === slug && candidate.source === 'custom'","(variant: ImagePaletteVariant | null) => {\n    if (!theme.palette || variant === null) return\n\n    send({\n      type: 'theme.update',\n      slug,\n      options: applyImagePalette(theme.options, theme.palette, variant),\n    })\n  }","options","palette","() => send({type: 'flow.list'})","() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }","(options) => send({type: 'theme.update', slug, options})","(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })","() => send({type: 'theme.remove', slug})","(title) => send({type: 'theme.update', slug, title})","<ThemeEditorForm\n      focusTitle={focusTitle}\n      imageUrl={images[slug]}\n      onDone={() => send({type: 'flow.list'})}\n      onLucky={() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }}\n      onOptionsChange={(options) => send({type: 'theme.update', slug, options})}\n      onPalette={(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })\n      }\n      onRemove={() => send({type: 'theme.remove', slug})}\n      onTitleChange={(title) => send({type: 'theme.update', slug, title})}\n      onVariant={applyVariant}\n      options={theme.options}\n      palette={theme.palette}\n      split={split}\n      mobile={mobile}\n      title={theme.title}\n    />","images[slug]","title","resolveThemeOptions(options)","useMemo(() => resolveThemeOptions(options), [options])","buildPalette(options)","useMemo(() => buildPalette(options), [options])","(scheme: ThemeColorSchemeKey, changes: Partial<SchemeThemeOptions>) => {\n    const values: SchemeThemeOptions = {...options[scheme], ...changes}\n\n    // Clearing an option means falling back to its default, which is its absence\n    for (const key of SCHEME_OPTION_KEYS) {\n      if (values[key] === undefined) delete values[key]\n    }\n\n    const next: BuildThemeOptions = {...options}\n\n    if (Object.keys(values).length === 0) {\n      delete next[scheme]\n    } else {\n      next[scheme] = values\n    }\n\n    onOptionsChange(next)\n  }","<ThemeThumbnail options={options} />","<Text size={1} weight=\"medium\">\n              Title\n            </Text>","(event) => onTitleChange(event.currentTarget.value)","(event) => event.currentTarget.select()","<Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>","focusTitle ? (event) => event.currentTarget.select() : undefined","<ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />","SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))","scheme","changes","<ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>","<ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>","<TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />","<Box flex={1} />","<Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />","<Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>","<>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>\n    </>","event","<Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>","active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )","<Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>","<Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>","split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`","<Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>","(accent) => onChange({accent})","() => onChange({accent: undefined})","<ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />","accent","options.accent === undefined","`${name} accent`","(text) => onChange({text})","() => onChange({text: undefined})","<ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />","text","options.text === undefined","`${name} text`","(background) => onChange({background})","() => onChange({background: undefined})","<ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />","background","scheme === 'dark' ? palette.black : palette.white","options.background === undefined","`${name} background`","<Text size={1}>Contrast</Text>","<Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>","contrast","options.contrast === undefined ? ' · auto' : ''","options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )","<Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>","(event) => onChange({contrast: Number(event.currentTarget.value)})","<input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({contrast: Number(event.currentTarget.value)})}\n            step={1}\n            type=\"range\"\n            value={resolved.contrast}\n          />","`${name} contrast`","<Text muted size={0}>\n            100 keeps text and borders neutral — lower values blend in the accent\n          </Text>","<Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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>","<Card borderTop padding={3}>\n      <Stack gap={4}>\n        <Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>\n\n        <ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />\n        <ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />\n        <ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />\n\n        <Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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      </Stack>\n    </Card>","autoLabel = 'auto'","(event) => onChange(event.currentTarget.value)","<input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />","<Text size={1}>{title}</Text>","<Text muted size={0} textOverflow=\"ellipsis\">\n          {value}\n          {adjusted !== undefined && adjusted !== value ? ` → ${adjusted}` : ''}\n          {auto ? ` · ${autoLabel}` : ''}\n        </Text>","adjusted !== undefined && adjusted !== value ? ` → ${adjusted}` : ''","auto ? ` · ${autoLabel}` : ''","<Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>","onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )","<Flex align=\"center\" gap={2}>\n      <input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />\n      <Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>\n      {onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )}\n    </Flex>","_c","_temp","_Fragment","async (theme: SharedTheme) => {\n    const title = displayTitle(theme.title)\n\n    try {\n      await navigator.clipboard.writeText(encodeTheme(theme))\n      toast.push({\n        status: 'success',\n        title: `Copied ${title} as a code`,\n        description: 'Paste it in the themer of another Studio to add the theme there',\n      })\n    } catch {\n      toast.push({status: 'error', title: `Could not copy ${title}`})\n    }\n  }","(text: string) => {\n    const theme = decodeTheme(text)\n\n    if (!theme) return false\n\n    send({type: 'theme.import', title: theme.title, options: theme.options})\n    toast.push({status: 'success', title: `Added ${theme.title}`})\n\n    return true\n  }","theme","async () => {\n    let text: string\n\n    try {\n      text = await navigator.clipboard.readText()\n    } catch {\n      return 'no-clipboard'\n    }\n\n    return addThemeFromText(text) ? 'added' : 'no-theme'\n  }","text","{copyTheme, addThemeFromText, addThemeFromClipboard}","() => {\n    if (!open) return undefined\n\n    const handlePaste = (event: ClipboardEvent) => {\n      if (isEditable(event.target)) return\n\n      const theme = decodeTheme(event.clipboardData?.getData('text/plain') ?? '')\n\n      if (!theme) return\n\n      event.preventDefault()\n      send({type: 'theme.import', title: theme.title, options: theme.options})\n      toast.push({status: 'success', title: `Added ${theme.title}`})\n    }\n\n    document.addEventListener('paste', handlePaste)\n\n    return () => document.removeEventListener('paste', handlePaste)\n  }","[open, send, toast]","_c","() => {\n    if (addThemeFromText(text)) {\n      onClose()\n    } else {\n      setInvalid(true)\n    }\n  }","<Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />","text.trim()","<Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />","text.trim() === ''","<Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>","(event) => {\n          event.preventDefault()\n          add()\n        }","<Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>","(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }","event","<TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />","invalid ? 'themer-paste-error' : undefined","invalid ? 'That is not a theme code' : undefined","invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )","<Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>","<form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>","<Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>\n      }\n      header=\"Add a shared theme\"\n      id=\"themer-paste\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={0}\n    >\n      <form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>\n    </Dialog>","_c","frame","displayTitle(theme.title)","title","(candidate) => candidate.slug === theme.slug","slug","(to: number) => {\n    const order = themes.map((candidate) => candidate.slug)\n\n    order.splice(to, 0, ...order.splice(index, 1))\n    send({type: 'theme.reorder', order})\n  }","(candidate) => candidate.slug","() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }","() => {\n        dragged.current = true\n      }","{scale: 1.04}","() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }","(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }","<span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>","options","<Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>","active ? 'medium' : 'regular'","<button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>","<Text size={1}>Show more</Text>","<Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />","`Show more for ${title}`","() => moveTo(index - 1)","<MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />","index <= 0","() => moveTo(index + 1)","<MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />","index >= themes.length - 1","<MenuDivider />","theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )","source","() => send({type: 'theme.duplicate', slug: theme.slug})","<MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />","theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'","<MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />","theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )","<Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>","() => setMenuOpen(false)","() => setMenuOpen(true)","{animate: true, placement: 'bottom-end', portal: true, scheme}","<Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>","`themer-theme-${theme.slug}`","<div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>","<Reorder.Item\n      as=\"div\"\n      className={root}\n      dragControls={dragControls}\n      dragListener={false}\n      onDragEnd={() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }}\n      onDragStart={() => {\n        dragged.current = true\n      }}\n      ref={active ? scrollRefIntoViewIfNeeded : undefined}\n      value={theme.slug}\n      whileDrag={{scale: 1.04}}\n    >\n      <button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>\n\n      {/* The tooltip wraps a card rather than the button: the menu button\n          clones its button to wire it up, which a tooltip in between would\n          swallow. The card keeps the button dark, as it sits on the dark\n          half of the thumbnail, while the menu opens in the sidebar's scheme */}\n      <div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>\n    </Reorder.Item>","active ? scrollRefIntoViewIfNeeded : undefined","Reorder.Item","candidate","_c","_temp","frame","_Fragment","(palette, file) =>\n    send({\n      type: 'theme.add',\n      title: titleFromFileName(file.name),\n      options: optionsFromImagePalette(palette),\n      palette,\n      imageUrl: URL.createObjectURL(file),\n    })","(order: string[]) => send({type: 'theme.reorder', order})","themes.map((theme) => theme.slug)","(theme) => theme.slug","themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))","active.slug","(theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              )","theme","<MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>","Reorder.Group","removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )","length","<ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>","<Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>","<ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />","<TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />","<Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>","pasting && <PasteThemeDialog onClose={() => setPasting(false)} />","<>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>\n\n      {pasting && <PasteThemeDialog onClose={() => setPasting(false)} />}\n    </>","_c","_Fragment","createThemeSnippet(theme.options)","options","async () => {\n    try {\n      await navigator.clipboard.writeText(snippet)\n      toast.push({status: 'success', title: 'Copied the theme to the clipboard'})\n    } catch {\n      toast.push({status: 'error', title: 'Could not copy the theme'})\n    }\n  }","<Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>","<code>sanity.config.ts</code>","<code>theme</code>","<code>defineConfig</code>","displayTitle(theme.title)","title","<Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>","<Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>","<Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>","<Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>\n      }\n      header=\"Add to your config\"\n      id=\"themer-snippet\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={1}\n    >\n      <Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>\n    </Dialog>","_c","navbarHeight === null ? undefined : {height: navbarHeight}","!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )","<Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>","VIEW_TITLES[view.name]","view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )","name","<TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />","<Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>","<Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>","<Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>","view.name === 'list' && <ThemeList />","view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />","focusTitle","slug","view.name === 'removed' && <RemovedThemes />","<Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>","snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />","<Card height=\"fill\">\n      <Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>\n\n      {snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />}\n    </Card>","_c","_Fragment","() => writeStoredWidth(width)","[width]","(event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    }","useCallback(\n    (event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    },\n    [width],\n  )","(event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }","event","useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }, [])","(event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }","useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }, [])","(event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }","useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }, [])","overlay ? undefined : {width}","!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )","<Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>","<Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>","!overlay","<Layer\n      className={sidebar}\n      data-overlay={overlay}\n      style={overlay ? undefined : {width}}\n      zOffset={100}\n    >\n      <Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>\n    </Layer>","_c"],"sources":["../src/tool/ScrollArea.css.ts","../src/tool/ScrollArea.tsx","../src/tool/ThemePreview.css.ts","../src/tool/ThemePreview.tsx","../src/tool/ThemeThumbnail.tsx","../src/tool/RemovedThemes.css.ts","../src/tool/RemovedThemes.tsx","../src/tool/TooltipButton.tsx","../src/tool/ImageFileButton.tsx","../src/tool/imageFile.ts","../src/tool/useImagePalette.ts","../src/tool/ImagePaletteSection.css.ts","../src/tool/ImagePaletteSection.tsx","../src/tool/ThemeEditor.css.ts","../src/tool/ThemeEditor.tsx","../src/tool/share.ts","../src/tool/useThemeCodes.ts","../src/tool/PasteThemeDialog.tsx","../src/tool/ThemeCard.css.ts","../src/tool/ThemeCard.tsx","../src/tool/ThemeList.css.ts","../src/tool/ThemeList.tsx","../src/tool/snippet.ts","../src/tool/ThemeSnippetDialog.tsx","../src/tool/ThemerSidebar.css.ts","../src/tool/ThemerSidebar.tsx","../src/tool/ResizableSidebar.css.ts","../src/tool/ResizableSidebar.tsx"],"sourcesContent":["import {style} from '@vanilla-extract/css'\n\n/** Always reserves the scrollbar's space, so the content never shifts */\nexport const root = style({\n  scrollbarGutter: 'stable',\n})\n","import {Box, useTheme_v2} from '@sanity/ui'\nimport {createContext, useContext, useEffect, useMemo, useRef, useState} from 'react'\n\nimport {root} from './ScrollArea.css'\n\n/** How far the content of a scroll area sits from its edges, in pixels */\ninterface ScrollAreaInset {\n  left: number\n  right: number\n  bottom: number\n}\n\nconst ScrollAreaInsetContext = createContext<ScrollAreaInset>({left: 0, right: 0, bottom: 0})\n\n/**\n * The gutter the last scroll area measured. It is the same for every scroll\n * area (the reserved gutter does not depend on the content), so the next one\n * starts out with the right padding instead of shifting after its first\n * measurement — which would also throw off anything scrolling into view as\n * the content mounts.\n */\nlet lastGutter = 0\n\n/**\n * The scrolling body of a sidebar flow. It always reserves the scrollbar's\n * space, so the content does not shift when the list grows or shrinks past\n * the point where it needs to scroll — and it takes that space out of its\n * right padding, so the content stays centered rather than hugging the left.\n * With overlay scrollbars there is no gutter and the padding stays even.\n *\n * @internal\n */\nexport function ScrollArea(props: {children: React.ReactNode; padding: number}) {\n  const {children, padding} = props\n  const {space} = useTheme_v2()\n  const ref = useRef<HTMLDivElement | null>(null)\n  const [gutter, setGutter] = useState(() => lastGutter)\n\n  useEffect(() => {\n    const element = ref.current\n\n    if (!element) return undefined\n\n    // The reserved gutter is the part of the box the content cannot use\n    const measure = () => {\n      lastGutter = element.offsetWidth - element.clientWidth\n      setGutter(lastGutter)\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(element)\n\n    return () => observer.disconnect()\n  }, [])\n\n  const inset = useMemo<ScrollAreaInset>(\n    () => ({\n      left: space[padding],\n      right: Math.max(0, space[padding] - gutter),\n      bottom: space[padding],\n    }),\n    [gutter, padding, space],\n  )\n\n  return (\n    <Box\n      className={root}\n      flex={1}\n      overflow=\"auto\"\n      padding={padding}\n      ref={ref}\n      style={{paddingRight: inset.right}}\n    >\n      <ScrollAreaInsetContext.Provider value={inset}>{children}</ScrollAreaInsetContext.Provider>\n    </Box>\n  )\n}\n\n/**\n * Content that runs edge to edge in a scroll area — up to the scrollbar —\n * instead of sitting inside its padding. It goes last: it runs down to the\n * bottom edge too.\n *\n * @internal\n */\nexport function ScrollAreaBleed(props: {children: React.ReactNode}) {\n  const {left, right, bottom} = useContext(ScrollAreaInsetContext)\n\n  return (\n    <div style={{marginLeft: -left, marginRight: -right, marginBottom: -bottom}}>\n      {props.children}\n    </div>\n  )\n}\n","import {createVar, style, styleVariants} from '@vanilla-extract/css'\n\n/**\n * The dark scheme covers the right side of the preview behind a diagonal cut,\n * like the \"Auto\" appearance preview in macOS System Settings shows both\n * schemes at once.\n */\nconst DARK_CLIP_PATH = 'polygon(58% 0, 100% 0, 100% 100%, 42% 100%)'\n\n/** The thickness of a line of text — bold enough to survive a half-size preview */\nconst LINE = 4\n\n/**\n * The colors a mockup paints with — only the ones the theme options change —\n * assigned per color scheme from the theme it previews\n */\nexport const colors = {\n  bg: createVar(),\n  fg: createVar(),\n  mutedFg: createVar(),\n  border: createVar(),\n  accent: createVar(),\n  avatar: createVar(),\n  selectedBg: createVar(),\n  selectedFg: createVar(),\n  inputBg: createVar(),\n  inputBorder: createVar(),\n}\n\nexport const root = style({\n  position: 'relative',\n  aspectRatio: '16 / 9',\n  overflow: 'hidden',\n})\n\nconst studioBase = style({\n  position: 'absolute',\n  inset: 0,\n  display: 'flex',\n  flexDirection: 'column',\n  background: colors.bg,\n})\n\nexport const studio = styleVariants({\n  light: [studioBase],\n  dark: [studioBase, {clipPath: DARK_CLIP_PATH}],\n})\n\nexport const navbar = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  gap: 5,\n  height: '18%',\n  padding: '0 5%',\n  borderBottom: `1px solid ${colors.border}`,\n})\n\nexport const logo = style({\n  flex: 'none',\n  width: 8,\n  height: 8,\n  borderRadius: 2,\n  background: colors.accent,\n})\n\nexport const spacer = style({\n  flex: 1,\n})\n\nexport const avatar = style({\n  flex: 'none',\n  width: 8,\n  height: 8,\n  borderRadius: '50%',\n  background: colors.avatar,\n})\n\nexport const body = style({\n  flex: 1,\n  display: 'flex',\n  minHeight: 0,\n})\n\nexport const list = style({\n  flex: 'none',\n  display: 'flex',\n  flexDirection: 'column',\n  width: '36%',\n  borderRight: `1px solid ${colors.border}`,\n})\n\nexport const listRow = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  height: '18%',\n  padding: '0 9%',\n  selectors: {\n    \"&[data-selected='true']\": {\n      background: colors.selectedBg,\n    },\n  },\n})\n\nexport const pane = style({\n  flex: 1,\n  display: 'flex',\n  flexDirection: 'column',\n  minWidth: 0,\n})\n\nexport const form = style({\n  flex: 1,\n  display: 'flex',\n  flexDirection: 'column',\n  gap: 7,\n  padding: '9% 8% 0',\n  minHeight: 0,\n  overflow: 'hidden',\n})\n\nexport const field = style({\n  flex: 'none',\n  display: 'flex',\n  flexDirection: 'column',\n  gap: 3,\n})\n\nexport const input = style({\n  height: 12,\n  borderRadius: 3,\n  background: colors.inputBg,\n  boxShadow: `inset 0 0 0 1px ${colors.inputBorder}`,\n})\n\nexport const footer = style({\n  flex: 'none',\n  display: 'flex',\n  alignItems: 'center',\n  justifyContent: 'flex-end',\n  height: '20%',\n  padding: '0 8%',\n  borderTop: `1px solid ${colors.border}`,\n})\n\nexport const button = style({\n  width: '32%',\n  height: '50%',\n  borderRadius: 3,\n  background: colors.accent,\n})\n\nconst lineBase = style({\n  flex: 'none',\n  height: LINE,\n  borderRadius: LINE / 2,\n})\n\n/** A line of text, in one of the text colors — its width is set inline */\nexport const line = styleVariants({\n  fg: [lineBase, {background: colors.fg}],\n  muted: [lineBase, {background: colors.mutedFg}],\n  selected: [lineBase, {background: colors.selectedFg}],\n})\n","import {ThemeProvider, useTheme_v2} from '@sanity/ui'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\nimport {assignInlineVars} from '@vanilla-extract/dynamic'\nimport {useMemo} from 'react'\n\nimport {buildTheme} from '../theme/buildTheme'\nimport type {BuildThemeOptions} from '../theme/options'\n\nimport {\n  avatar,\n  body,\n  button,\n  colors,\n  field,\n  footer,\n  form,\n  input,\n  line,\n  list,\n  listRow,\n  logo,\n  navbar,\n  pane,\n  root,\n  spacer,\n  studio,\n} from './ThemePreview.css'\n\n/** The document rows in the list pane — the widths of their title lines */\nconst LIST_ROWS = ['62%', '46%', '70%', '52%']\n\n/** The fields in the document form — the widths of their labels */\nconst FIELDS = ['32%', '24%']\n\n/**\n * A tiny, lo-fi mockup of a Studio in the given theme — the navbar over the\n * structure tool with a list of documents on the left and a document form on\n * the right — in both color schemes at once: the light scheme on the left and\n * the dark scheme on the right, split diagonally. It only paints colors the\n * theme options change (backgrounds, text, borders, the accent) so that a\n * glance shows what the theme does to the Studio — with few and bold enough\n * elements to still read when scaled down to a thumbnail.\n *\n * @internal\n */\nexport function ThemePreview(props: {options: BuildThemeOptions}) {\n  const {options} = props\n  const theme = useMemo(() => buildTheme(options), [options])\n\n  return (\n    <div aria-hidden className={root}>\n      <ThemeProvider scheme=\"light\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"light\" />\n      </ThemeProvider>\n      <ThemeProvider scheme=\"dark\" theme={theme} tone=\"default\">\n        <MockStudio scheme=\"dark\" />\n      </ThemeProvider>\n    </div>\n  )\n}\n\nfunction MockStudio(props: {scheme: ThemeColorSchemeKey}) {\n  const {scheme} = props\n  const {color} = useTheme_v2()\n  const selected = color.selectable.default.selected\n  const inputColor = color.input.default.enabled\n\n  return (\n    <div\n      className={studio[scheme]}\n      style={assignInlineVars({\n        [colors.bg]: color.bg,\n        [colors.fg]: color.fg,\n        [colors.mutedFg]: color.muted.fg,\n        [colors.border]: color.border,\n        [colors.accent]: color.button.default.primary.enabled.bg,\n        [colors.avatar]: color.avatar.blue.bg,\n        [colors.selectedBg]: selected.bg,\n        [colors.selectedFg]: selected.fg,\n        [colors.inputBg]: inputColor.bg,\n        [colors.inputBorder]: inputColor.border,\n      })}\n    >\n      <div className={navbar}>\n        <div className={logo} />\n        <div className={line.fg} style={{width: '22%'}} />\n        <div className={spacer} />\n        <div className={avatar} />\n      </div>\n\n      <div className={body}>\n        <div className={list}>\n          {LIST_ROWS.map((width, index) => {\n            const isSelected = index === 1\n\n            return (\n              <div className={listRow} data-selected={isSelected} key={width}>\n                <div className={isSelected ? line.selected : line.muted} style={{width}} />\n              </div>\n            )\n          })}\n        </div>\n\n        <div className={pane}>\n          <div className={form}>\n            <div className={line.fg} style={{width: '45%'}} />\n            {FIELDS.map((width) => (\n              <div className={field} key={width}>\n                <div className={line.muted} style={{width}} />\n                <div className={input} />\n              </div>\n            ))}\n          </div>\n          <div className={footer}>\n            <div className={button} />\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n","import {Card} from '@sanity/ui'\n\nimport type {BuildThemeOptions} from '../theme/options'\nimport {ThemePreview} from './ThemePreview'\n\n/**\n * The floating preview card of a theme: the lo-fi studio mockup on a raised,\n * rounded card, like the appearance previews in macOS System Settings.\n *\n * @internal\n */\nexport function ThemeThumbnail(props: {options: BuildThemeOptions}) {\n  return (\n    <Card overflow=\"hidden\" radius={3} shadow={1}>\n      <ThemePreview options={props.options} />\n    </Card>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** A removed theme's thumbnail, dimmed to read as removed */\nexport const removedThumbnail = style({\n  opacity: 0.6,\n})\n","import {Box, Button, Flex, Stack, Text} from '@sanity/ui'\n\nimport {useThemer} from './context'\nimport {ScrollArea} from './ScrollArea'\nimport {displayTitle} from './themes'\nimport {ThemeThumbnail} from './ThemeThumbnail'\n\nimport {removedThumbnail} from './RemovedThemes.css'\n\n/**\n * The flow for restoring removed themes: the presets and custom themes the\n * user took out of the list, each with a button to put it back — and, for\n * custom themes, one to delete it for good. The machine leaves the flow once\n * the last one is gone.\n *\n * @internal\n */\nexport function RemovedThemes() {\n  const {removed, send} = useThemer()\n\n  return (\n    <ScrollArea padding={3}>\n      <Stack gap={5}>\n        {removed.map((theme) => (\n          <Stack gap={3} key={theme.slug}>\n            <Box className={removedThumbnail}>\n              <ThemeThumbnail options={theme.options} />\n            </Box>\n            <Text align=\"center\" size={1} textOverflow=\"ellipsis\">\n              {displayTitle(theme.title)}\n            </Text>\n            <Flex gap={2} justify=\"center\">\n              <Button\n                mode=\"ghost\"\n                onClick={() => send({type: 'theme.restore', slug: theme.slug})}\n                padding={2}\n                text=\"Restore\"\n              />\n              {theme.source === 'custom' && (\n                <Button\n                  mode=\"ghost\"\n                  onClick={() => send({type: 'theme.delete', slug: theme.slug})}\n                  padding={2}\n                  text=\"Delete\"\n                  tone=\"critical\"\n                />\n              )}\n            </Flex>\n          </Stack>\n        ))}\n      </Stack>\n    </ScrollArea>\n  )\n}\n","import {Button, type ButtonProps, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\n\n/**\n * A button with an animated tooltip instead of a `title` attribute, sized like\n * the Studio's own buttons (`padding` and `gap` of 2). Icon-only buttons take\n * the tooltip as their accessible name.\n *\n * @internal\n */\nexport function TooltipButton(props: ButtonProps & {tooltip: string}) {\n  const {tooltip, ...buttonProps} = props\n\n  return (\n    <Tooltip animate content={<Text size={1}>{tooltip}</Text>} placement=\"bottom\" portal>\n      <Button\n        aria-label={buttonProps.text === undefined ? tooltip : undefined}\n        gap={2}\n        padding={2}\n        {...buttonProps}\n      />\n    </Tooltip>\n  )\n}\n","import {ImageIcon} from '@sanity/icons/Image'\nimport type {ButtonProps} from '@sanity/ui'\nimport {useRef} from 'react'\n\nimport {TooltipButton} from './TooltipButton'\n\n/**\n * A button that opens the file picker for an image, and hands the chosen file\n * over — the picker is a hidden file input, so nothing is uploaded anywhere.\n *\n * @internal\n */\nexport function ImageFileButton(\n  props: {onFile: (file: File) => void; tooltip: string} & Pick<\n    ButtonProps,\n    'disabled' | 'loading' | 'mode' | 'padding' | 'text' | 'width'\n  >,\n) {\n  const {onFile, ...buttonProps} = props\n  const inputRef = useRef<HTMLInputElement | null>(null)\n\n  return (\n    <>\n      <TooltipButton {...buttonProps} icon={ImageIcon} onClick={() => inputRef.current?.click()} />\n      <input\n        accept=\"image/*\"\n        hidden\n        onChange={(event) => {\n          const file = event.currentTarget.files?.[0]\n\n          // Picking the same file again should work, so the input forgets it\n          event.currentTarget.value = ''\n\n          if (file) onFile(file)\n        }}\n        ref={inputRef}\n        type=\"file\"\n      />\n    </>\n  )\n}\n","import type {PixelData} from './imagePalette'\n\n/**\n * The longest side the image is scaled down to before its colors are read —\n * a few thousand pixels are plenty for a palette, and keep it instant\n */\nconst SAMPLE_SIZE = 96\n\n/**\n * Reads the pixels of an image file on device: the image is decoded, drawn\n * onto a small canvas and read back, so nothing leaves the browser.\n *\n * @internal\n */\nexport async function readImagePixels(file: Blob): Promise<PixelData> {\n  const image = await decodeImage(file)\n\n  try {\n    const scale = Math.min(1, SAMPLE_SIZE / Math.max(image.width, image.height))\n    const width = Math.max(1, Math.round(image.width * scale))\n    const height = Math.max(1, Math.round(image.height * scale))\n    const canvas = document.createElement('canvas')\n\n    canvas.width = width\n    canvas.height = height\n\n    const context = canvas.getContext('2d', {willReadFrequently: true})\n\n    if (!context) throw new Error('Could not draw the image')\n\n    context.drawImage(image, 0, 0, width, height)\n\n    return {data: context.getImageData(0, 0, width, height).data, width, height}\n  } finally {\n    // Where `createImageBitmap` is missing, `ImageBitmap` may be too\n    if (typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap) image.close()\n  }\n}\n\nasync function decodeImage(file: Blob): Promise<ImageBitmap | HTMLImageElement> {\n  if (typeof createImageBitmap === 'function') {\n    try {\n      return await createImageBitmap(file)\n    } catch {\n      // Some browsers cannot decode every format this way (e.g. SVG) — an\n      // image element handles whatever the browser can display\n    }\n  }\n\n  const url = URL.createObjectURL(file)\n\n  try {\n    return await new Promise<HTMLImageElement>((resolve, reject) => {\n      const image = new Image()\n\n      image.addEventListener('load', () => resolve(image), {once: true})\n      image.addEventListener('error', () => reject(new Error('Could not decode the image')), {\n        once: true,\n      })\n      image.src = url\n    })\n  } finally {\n    URL.revokeObjectURL(url)\n  }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useCallback, useEffect, useRef, useState} from 'react'\n\nimport {readImagePixels} from './imageFile'\nimport {extractImagePalette, type ImagePalette} from './imagePalette'\n\n/**\n * Extracts the palette of image files on device and hands it to `onPalette`,\n * along with the file it came from. Failures end up as a toast.\n *\n * @internal\n */\nexport function useImagePalette(onPalette: (palette: ImagePalette, file: File) => void): {\n  busy: boolean\n  pickImage: (file: File) => void\n} {\n  const toast = useToast()\n  const [busy, setBusy] = useState(false)\n  const onPaletteRef = useRef(onPalette)\n  const mountedRef = useRef(true)\n  // Picks are numbered so that a slow earlier image cannot overwrite a later\n  // pick once its extraction finishes\n  const latestPickRef = useRef(0)\n\n  useEffect(() => {\n    onPaletteRef.current = onPalette\n  }, [onPalette])\n\n  useEffect(() => {\n    mountedRef.current = true\n\n    return () => {\n      mountedRef.current = false\n    }\n  }, [])\n\n  const pickImage = useCallback(\n    (file: File) => {\n      const pick = ++latestPickRef.current\n\n      setBusy(true)\n\n      // Whether this pick still matters: it is the latest one and the\n      // component that asked for it is still around\n      const isCurrent = () => mountedRef.current && latestPickRef.current === pick\n\n      const extract = async () => {\n        const palette = extractImagePalette(await readImagePixels(file))\n\n        if (!isCurrent()) return\n\n        if (Object.values(palette).every((swatch) => swatch === null)) {\n          toast.push({status: 'warning', title: 'Found no colors in that image'})\n        } else {\n          onPaletteRef.current(palette, file)\n        }\n      }\n\n      extract()\n        .catch(() => {\n          if (isCurrent()) toast.push({status: 'error', title: 'Could not read that image'})\n        })\n        .finally(() => {\n          if (isCurrent()) setBusy(false)\n        })\n    },\n    [toast],\n  )\n\n  return {busy, pickImage}\n}\n","import {createVar, style} from '@vanilla-extract/css'\n\nconst TILE_SIZE = 24\nconst TILE_GAP = 4\n\n/** The image spans both rows of tiles */\nconst IMAGE_SIZE = TILE_SIZE * 2 + TILE_GAP\n\n/** The variant previews are the theme thumbnails, laid out at this width and scaled down */\nexport const VARIANT_WIDTH = 144\n\nexport const VARIANT_GAP = 8\nexport const ROW_PADDING = 12\n\n/** The frame around a variant's thumbnail, on either side */\nexport const VARIANT_FRAME = 4\n\n/** The width of one variant's thumbnail, set on the row once it is measured */\nexport const variantWidth = createVar()\n\n/** How much a variant's thumbnail is scaled down from `VARIANT_WIDTH` */\nexport const variantScale = createVar()\n\nexport const paletteGrid = style({\n  display: 'grid',\n  gridTemplateColumns: `repeat(3, ${TILE_SIZE}px)`,\n  gridAutoRows: TILE_SIZE,\n  gap: TILE_GAP,\n  selectors: {\n    \"&[data-with-image='true']\": {\n      gridTemplateColumns: `${IMAGE_SIZE}px repeat(3, ${TILE_SIZE}px)`,\n    },\n  },\n})\n\nexport const imageTile = style({\n  display: 'block',\n  gridRow: 'span 2',\n  width: IMAGE_SIZE,\n  height: IMAGE_SIZE,\n  borderRadius: 3,\n  objectFit: 'cover',\n  boxShadow: 'inset 0 0 0 1px var(--card-border-color)',\n})\n\nexport const tile = style({\n  display: 'block',\n  borderRadius: 3,\n  boxShadow: 'inset 0 0 0 1px var(--card-border-color)',\n  selectors: {\n    \"&[data-empty='true']\": {\n      background:\n        'repeating-linear-gradient(-45deg, transparent 0 3px, var(--card-border-color) 3px 4px)',\n    },\n  },\n})\n\n/**\n * The variants scroll sideways and snap into place, bleeding into the card's\n * padding so the row runs from edge to edge\n */\nexport const variantRow = style({\n  display: 'flex',\n  gap: VARIANT_GAP,\n  margin: `0 -${ROW_PADDING}px`,\n  padding: `0 ${ROW_PADDING}px`,\n  overflowX: 'auto',\n  scrollSnapType: 'x mandatory',\n  scrollPaddingLeft: ROW_PADDING,\n  scrollbarWidth: 'thin',\n})\n\nexport const variantButton = style({\n  'appearance': 'none',\n  'flex': 'none',\n  'display': 'block',\n  'boxSizing': 'border-box',\n  'width': `calc(${variantWidth} + ${VARIANT_FRAME * 2}px)`,\n  'margin': 0,\n  'padding': 0,\n  'border': 0,\n  'background': 'none',\n  'color': 'inherit',\n  'font': 'inherit',\n  'textAlign': 'center',\n  'cursor': 'pointer',\n  'scrollSnapAlign': 'start',\n  ':focus': {\n    outline: 'none',\n  },\n})\n\n/**\n * Clips the scaled-down thumbnail to its visual size, with room for the ring\n * — drawn inside the frame, like the theme cards', so the scrolling row\n * never clips it\n */\nexport const variantFrame = style({\n  display: 'block',\n  boxSizing: 'border-box',\n  width: `calc(${variantWidth} + ${VARIANT_FRAME * 2}px)`,\n  height: `calc(${variantWidth} * 9 / 16 + ${VARIANT_FRAME * 2}px)`,\n  padding: VARIANT_FRAME,\n  borderRadius: 7,\n  overflow: 'hidden',\n  transition: 'box-shadow 100ms',\n  selectors: {\n    [`${variantButton}:hover &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-border-color)',\n    },\n    [`${variantButton}[aria-pressed='true'] &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-focus-ring-color)',\n    },\n    [`${variantButton}:focus-visible &`]: {\n      outline: '2px solid var(--card-focus-ring-color)',\n      outlineOffset: -2,\n    },\n  },\n})\n\nexport const variantScaleBox = style({\n  display: 'block',\n  width: VARIANT_WIDTH,\n  transform: `scale(${variantScale})`,\n  transformOrigin: 'top left',\n})\n","import {SparklesIcon} from '@sanity/icons/Sparkles'\nimport {Box, Card, Flex, Stack, Text} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {assignInlineVars} from '@vanilla-extract/dynamic'\nimport {useEffect, useMemo, useRef, useState} from 'react'\n\nimport type {BuildThemeOptions} from '../theme/options'\nimport {ImageFileButton} from './ImageFileButton'\nimport {\n  applyImagePalette,\n  currentImageVariant,\n  IMAGE_PALETTE_TITLES,\n  IMAGE_PALETTE_VARIANTS,\n  type ImagePalette,\n  type ImagePaletteKey,\n  type ImagePaletteVariant,\n} from './imagePalette'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {TooltipButton} from './TooltipButton'\nimport {useImagePalette} from './useImagePalette'\n\nimport {\n  imageTile,\n  paletteGrid,\n  ROW_PADDING,\n  tile,\n  VARIANT_FRAME,\n  VARIANT_GAP,\n  VARIANT_WIDTH,\n  variantButton,\n  variantFrame,\n  variantRow,\n  variantScale,\n  variantScaleBox,\n  variantWidth,\n} from './ImagePaletteSection.css'\n\n/** The swatches on display: the vibrant family over the muted one */\nconst TILES: ImagePaletteKey[] = [\n  'vibrant',\n  'lightVibrant',\n  'darkVibrant',\n  'muted',\n  'lightMuted',\n  'darkMuted',\n]\n\n/**\n * How many variants show at once: two and a half, so that the cut-off third\n * one gives away that the row scrolls\n */\nconst VISIBLE_VARIANTS = 2.5\n\n/** The width of one variant, before the row has been measured */\nconst FALLBACK_VARIANT_WIDTH = 58\n\n/**\n * Takes the colors of a theme from an image, on device: the image is read\n * into a canvas and its palette extracted right there — nothing is uploaded.\n * Shows the image (while the session lasts) next to its palette, offers a\n * theme variant built around each swatch as a small preview, and a lucky\n * button that picks an interesting one.\n *\n * @internal\n */\nexport function ImagePaletteSection(props: {\n  imageUrl?: string\n  onPalette: (palette: ImagePalette, file: File) => void\n  onVariant: (variant: ImagePaletteVariant) => void\n  onLucky: () => void\n  options: BuildThemeOptions\n  palette?: ImagePalette\n}) {\n  const {imageUrl, onPalette, onVariant, onLucky, options, palette} = props\n  const {busy, pickImage} = useImagePalette(onPalette)\n  const [dragging, setDragging] = useState(false)\n  // `dragleave` also fires when the pointer crosses into a child, so the\n  // highlight tracks how deep the drag is rather than the last event\n  const dragDepth = useRef(0)\n  const current = palette ? currentImageVariant(options, palette) : null\n  const rowRef = useRef<HTMLDivElement | null>(null)\n  const [thumbnailWidth, setThumbnailWidth] = useState(FALLBACK_VARIANT_WIDTH)\n\n  // Size the variants to the row, so two and a half of them are in view\n  useEffect(() => {\n    const row = rowRef.current\n\n    if (!row) return undefined\n\n    const measure = () => {\n      const visible =\n        row.clientWidth - ROW_PADDING - (Math.ceil(VISIBLE_VARIANTS) - 1) * VARIANT_GAP\n\n      // Each variant is its thumbnail plus the frame on either side\n      setThumbnailWidth(Math.max(24, Math.floor(visible / VISIBLE_VARIANTS) - VARIANT_FRAME * 2))\n    }\n\n    measure()\n\n    const observer = new ResizeObserver(measure)\n\n    observer.observe(row)\n\n    return () => observer.disconnect()\n    // oxlint-disable-next-line react/exhaustive-effect-dependencies -- the row only renders with a palette, so a new palette has a new row to observe\n  }, [palette])\n\n  const variants = useMemo(() => {\n    if (!palette) return []\n\n    return IMAGE_PALETTE_VARIANTS.flatMap((variant) =>\n      palette[variant] === null\n        ? []\n        : [\n            {\n              variant,\n              title: IMAGE_PALETTE_TITLES[variant],\n              options: applyImagePalette(options, palette, variant),\n            },\n          ],\n    )\n  }, [options, palette])\n\n  return (\n    <Card\n      border\n      onDragEnter={(event) => {\n        event.preventDefault()\n        dragDepth.current++\n        setDragging(true)\n      }}\n      onDragLeave={() => {\n        dragDepth.current = Math.max(0, dragDepth.current - 1)\n\n        if (dragDepth.current === 0) setDragging(false)\n      }}\n      onDragOver={(event) => {\n        event.preventDefault()\n      }}\n      onDrop={(event) => {\n        event.preventDefault()\n        dragDepth.current = 0\n        setDragging(false)\n\n        const file = event.dataTransfer.files[0]\n\n        if (file) pickImage(file)\n      }}\n      padding={3}\n      radius={3}\n      tone={dragging ? 'primary' : 'default'}\n    >\n      <Stack gap={3}>\n        <Flex align=\"center\" gap={2}>\n          <Box flex={1}>\n            <Text size={1} weight=\"medium\">\n              Image palette\n            </Text>\n          </Box>\n          {palette && (\n            <ImageFileButton\n              loading={busy}\n              mode=\"bleed\"\n              onFile={pickImage}\n              padding={2}\n              tooltip=\"Pick another image\"\n            />\n          )}\n        </Flex>\n\n        {palette ? (\n          <>\n            <div className={paletteGrid} data-with-image={imageUrl !== undefined}>\n              {imageUrl && <img alt=\"\" className={imageTile} src={imageUrl} />}\n              {TILES.map((key) => {\n                const hex = palette[key]\n                const title = IMAGE_PALETTE_TITLES[key]\n\n                return (\n                  <Tooltip\n                    animate\n                    content={\n                      <Text size={1}>\n                        {hex ? `${title} · ${hex}` : `No ${title.toLowerCase()} color`}\n                      </Text>\n                    }\n                    key={key}\n                    placement=\"bottom\"\n                    portal\n                  >\n                    <span\n                      className={tile}\n                      data-empty={hex === null}\n                      style={{background: hex ?? undefined}}\n                    />\n                  </Tooltip>\n                )\n              })}\n            </div>\n\n            <Stack gap={2}>\n              <Text muted size={0}>\n                Pick the swatch to build the theme around\n              </Text>\n              <div\n                className={variantRow}\n                ref={rowRef}\n                style={assignInlineVars({\n                  [variantWidth]: `${thumbnailWidth}px`,\n                  [variantScale]: String(thumbnailWidth / VARIANT_WIDTH),\n                })}\n              >\n                {variants.map(({variant, title, options: variantOptions}) => (\n                  // oxlint-disable-next-line control-has-associated-label -- the title below the thumbnail is the label, deeper than the rule looks\n                  <button\n                    aria-pressed={variant === current}\n                    className={variantButton}\n                    key={variant}\n                    onClick={() => onVariant(variant)}\n                    type=\"button\"\n                  >\n                    <span className={variantFrame}>\n                      <span className={variantScaleBox}>\n                        <ThemeThumbnail options={variantOptions} />\n                      </span>\n                    </span>\n                    <Box as=\"span\" display=\"block\" paddingTop={1}>\n                      <Text\n                        align=\"center\"\n                        as=\"span\"\n                        size={0}\n                        textOverflow=\"ellipsis\"\n                        weight={variant === current ? 'medium' : 'regular'}\n                      >\n                        {title}\n                      </Text>\n                    </Box>\n                  </button>\n                ))}\n              </div>\n            </Stack>\n\n            <TooltipButton\n              icon={SparklesIcon}\n              mode=\"ghost\"\n              onClick={onLucky}\n              text=\"I'm feeling lucky\"\n              tooltip=\"Build the theme around a swatch that looks interesting\"\n              width=\"fill\"\n            />\n          </>\n        ) : (\n          <Stack gap={3}>\n            <Text muted size={0}>\n              Take the accent, text and background colors from an image — read on device, nothing is\n              uploaded.\n            </Text>\n            <ImageFileButton\n              loading={busy}\n              mode=\"ghost\"\n              onFile={pickImage}\n              text=\"Pick an image\"\n              tooltip=\"Take the colors from an image on your device\"\n              width=\"fill\"\n            />\n          </Stack>\n        )}\n      </Stack>\n    </Card>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** A native color input, trimmed down to its swatch */\nexport const swatch = style({\n  boxSizing: 'border-box',\n  flex: 'none',\n  width: 33,\n  height: 33,\n  padding: 0,\n  border: '1px solid var(--card-border-color)',\n  borderRadius: 4,\n  background: 'none',\n  cursor: 'pointer',\n  selectors: {\n    '&::-webkit-color-swatch-wrapper': {\n      padding: 0,\n    },\n    '&::-webkit-color-swatch': {\n      border: 'none',\n      borderRadius: 3,\n    },\n    '&::-moz-color-swatch': {\n      border: 'none',\n      borderRadius: 3,\n    },\n  },\n})\n\n/** A native range input, themed through `accent-color` */\nexport const range = style({\n  display: 'block',\n  width: '100%',\n  margin: 0,\n  accentColor: 'var(--card-focus-ring-color)',\n})\n\n/** Lets the color row's text shrink and truncate instead of widening the row */\nexport const colorRowText = style({\n  minWidth: 0,\n})\n","import {ResetIcon} from '@sanity/icons/Reset'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Badge, Box, Button, Card, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {type ThemeColorSchemeKey} from '@sanity/ui/theme'\nimport {useMemo} from 'react'\nimport {useColorSchemeValue} from 'sanity'\n\nimport {buildPalette, type GeneratedColorPalette} from '../theme/buildPalette'\nimport {\n  type BuildThemeOptions,\n  type ResolvedSchemeOptions,\n  resolveThemeOptions,\n  SCHEMES,\n  type SchemeThemeOptions,\n} from '../theme/options'\nimport {useThemer} from './context'\nimport {\n  applyImagePalette,\n  currentImageVariant,\n  type ImagePalette,\n  type ImagePaletteVariant,\n  pickLuckyVariant,\n} from './imagePalette'\nimport {ImagePaletteSection} from './ImagePaletteSection'\nimport {ScrollArea, ScrollAreaBleed} from './ScrollArea'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {TooltipButton} from './TooltipButton'\n\nimport {colorRowText, range, swatch} from './ThemeEditor.css'\n\nconst SCHEME_TITLES: Record<ThemeColorSchemeKey, string> = {\n  dark: 'Dark mode',\n  light: 'Light mode',\n}\n\n/**\n * Where the split preview shows a scheme: the Studio's own scheme stays next\n * to the sidebar (or at the bottom, stacked on small screens), the other one\n * takes the far side\n */\nfunction splitHint(own: boolean, mobile: boolean): string {\n  if (mobile) return own ? 'Shown at the bottom' : 'Shown at the top'\n\n  return own ? 'Shown on the right, next to the themer' : 'Shown on the left'\n}\n\nconst SCHEME_OPTION_KEYS: Array<keyof SchemeThemeOptions> = [\n  'accent',\n  'text',\n  'background',\n  'contrast',\n]\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 */\n/**\n * The flow for editing one of the user's own themes: its title, a live\n * preview, and a card per color scheme with the accent/text/background\n * pickers and the contrast slider of that scheme. Every change applies to the\n * whole Studio right away — in the scheme the Studio is showing, or in both\n * side by side in the split preview.\n *\n * @internal\n */\nexport function ThemeEditor(props: {focusTitle: boolean; slug: string}) {\n  const {focusTitle, slug} = props\n  const {themes, images, split, mobile, send} = useThemer()\n  const theme = themes.find((candidate) => candidate.slug === slug && candidate.source === 'custom')\n\n  // The machine only enters the edit flow for a listed custom theme, and\n  // leaves it as soon as the theme is removed or deleted\n  if (!theme) return null\n\n  const applyVariant = (variant: ImagePaletteVariant | null) => {\n    if (!theme.palette || variant === null) return\n\n    send({\n      type: 'theme.update',\n      slug,\n      options: applyImagePalette(theme.options, theme.palette, variant),\n    })\n  }\n\n  return (\n    <ThemeEditorForm\n      focusTitle={focusTitle}\n      imageUrl={images[slug]}\n      onDone={() => send({type: 'flow.list'})}\n      onLucky={() => {\n        if (!theme.palette) return\n\n        applyVariant(\n          pickLuckyVariant(theme.palette, {\n            exclude: currentImageVariant(theme.options, theme.palette),\n          }),\n        )\n      }}\n      onOptionsChange={(options) => send({type: 'theme.update', slug, options})}\n      onPalette={(palette, file) =>\n        send({\n          type: 'theme.update',\n          slug,\n          options: applyImagePalette(theme.options, palette),\n          palette,\n          imageUrl: URL.createObjectURL(file),\n        })\n      }\n      onRemove={() => send({type: 'theme.remove', slug})}\n      onTitleChange={(title) => send({type: 'theme.update', slug, title})}\n      onVariant={applyVariant}\n      options={theme.options}\n      palette={theme.palette}\n      split={split}\n      mobile={mobile}\n      title={theme.title}\n    />\n  )\n}\n\n// Split from `ThemeEditor` so that the derived values below can be hooks\n// while the editor bails out early when the theme is gone\nfunction ThemeEditorForm(props: {\n  focusTitle: boolean\n  imageUrl?: string\n  onDone: () => void\n  onLucky: () => void\n  onOptionsChange: (options: BuildThemeOptions) => void\n  onPalette: (palette: ImagePalette, file: File) => void\n  onRemove: () => void\n  onTitleChange: (title: string) => void\n  onVariant: (variant: ImagePaletteVariant) => void\n  options: BuildThemeOptions\n  palette?: ImagePalette\n  /** Whether the Studio shows in light and dark side by side */\n  split: boolean\n  /** Whether the split preview stacks, on a small screen */\n  mobile: boolean\n  title: string\n}) {\n  const {\n    focusTitle,\n    imageUrl,\n    onDone,\n    onLucky,\n    onOptionsChange,\n    onPalette,\n    onRemove,\n    onTitleChange,\n    onVariant,\n    options,\n    palette,\n    split,\n    mobile,\n    title,\n  } = props\n  // The scheme the Studio is showing, with the appearance setting resolved\n  const studioScheme = useColorSchemeValue()\n  const resolved = useMemo(() => resolveThemeOptions(options), [options])\n  const palettes = useMemo(() => buildPalette(options), [options])\n\n  const patchScheme = (scheme: ThemeColorSchemeKey, changes: Partial<SchemeThemeOptions>) => {\n    const values: SchemeThemeOptions = {...options[scheme], ...changes}\n\n    // Clearing an option means falling back to its default, which is its absence\n    for (const key of SCHEME_OPTION_KEYS) {\n      if (values[key] === undefined) delete values[key]\n    }\n\n    const next: BuildThemeOptions = {...options}\n\n    if (Object.keys(values).length === 0) {\n      delete next[scheme]\n    } else {\n      next[scheme] = values\n    }\n\n    onOptionsChange(next)\n  }\n\n  return (\n    <>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          <ThemeThumbnail options={options} />\n\n          <Stack gap={2}>\n            <Text size={1} weight=\"medium\">\n              Title\n            </Text>\n            <TextInput\n              autoFocus={focusTitle}\n              fontSize={1}\n              onChange={(event) => onTitleChange(event.currentTarget.value)}\n              onFocus={focusTitle ? (event) => event.currentTarget.select() : undefined}\n              padding={2}\n              placeholder=\"Untitled theme\"\n              value={title}\n            />\n          </Stack>\n\n          <ImagePaletteSection\n            imageUrl={imageUrl}\n            onLucky={onLucky}\n            onPalette={onPalette}\n            onVariant={onVariant}\n            options={options}\n            palette={palette}\n          />\n\n          <ScrollAreaBleed>\n            {SCHEMES.map((scheme) => (\n              <SchemeCard\n                active={split || scheme === studioScheme}\n                key={scheme}\n                onChange={(changes) => patchScheme(scheme, changes)}\n                options={options[scheme] ?? {}}\n                palette={palettes[scheme]}\n                resolved={resolved[scheme]}\n                scheme={scheme}\n                split={split}\n                splitHint={splitHint(scheme === studioScheme, mobile)}\n              />\n            ))}\n          </ScrollAreaBleed>\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <TooltipButton\n            icon={TrashIcon}\n            mode=\"ghost\"\n            onClick={onRemove}\n            text=\"Remove\"\n            tone=\"critical\"\n            tooltip=\"Remove the theme — it can be restored until it is deleted\"\n          />\n          <Box flex={1} />\n          <Button mode=\"ghost\" onClick={onDone} padding={2} text=\"Done\" />\n        </Flex>\n      </Card>\n    </>\n  )\n}\n\n/**\n * The colors of one scheme. The cards span the sidebar edge to edge, one\n * after the other with a border between them, in the sidebar's own scheme —\n * the swatches show the colors they edit. The scheme the Studio is showing is\n * marked as active: its changes show up in the Studio right away, the other\n * scheme's only once the appearance setting switches to it — or both are\n * active, in the split preview.\n */\nfunction SchemeCard(props: {\n  active: boolean\n  onChange: (changes: Partial<SchemeThemeOptions>) => void\n  options: SchemeThemeOptions\n  palette: GeneratedColorPalette\n  resolved: ResolvedSchemeOptions\n  scheme: ThemeColorSchemeKey\n  split: boolean\n  /** Where the split preview shows this scheme */\n  splitHint: string\n}) {\n  const {active, onChange, options, palette, resolved, scheme, split, splitHint} = props\n  const name = SCHEME_TITLES[scheme]\n\n  return (\n    <Card borderTop padding={3}>\n      <Stack gap={4}>\n        <Stack gap={2}>\n          <Flex align=\"center\" gap={2}>\n            <Box flex={1}>\n              <Text size={1} weight=\"medium\">\n                {name}\n              </Text>\n            </Box>\n            {active && (\n              <Badge fontSize={0} tone=\"primary\">\n                Active\n              </Badge>\n            )}\n          </Flex>\n          <Text muted size={0}>\n            {split\n              ? splitHint\n              : active\n                ? 'Shown in the Studio right now'\n                : `Shown once the Studio appearance is ${scheme}`}\n          </Text>\n        </Stack>\n\n        <ColorRow\n          auto={options.accent === undefined}\n          autoLabel=\"default\"\n          label={`${name} accent`}\n          onChange={(accent) => onChange({accent})}\n          onClear={() => onChange({accent: undefined})}\n          title=\"Accent\"\n          value={resolved.accent}\n        />\n        <ColorRow\n          auto={options.text === undefined}\n          label={`${name} text`}\n          onChange={(text) => onChange({text})}\n          onClear={() => onChange({text: undefined})}\n          title=\"Text\"\n          value={resolved.text}\n        />\n        <ColorRow\n          adjusted={scheme === 'dark' ? palette.black : palette.white}\n          auto={options.background === undefined}\n          label={`${name} background`}\n          onChange={(background) => onChange({background})}\n          onClear={() => onChange({background: undefined})}\n          title=\"Background\"\n          value={resolved.background}\n        />\n\n        <Stack gap={3}>\n          <Flex align=\"center\" gap={2}>\n            <Stack flex={1} gap={2}>\n              <Text size={1}>Contrast</Text>\n              <Text muted size={0}>\n                {resolved.contrast}\n                {options.contrast === undefined ? ' · auto' : ''}\n              </Text>\n            </Stack>\n            {options.contrast !== undefined && (\n              <TooltipButton\n                icon={ResetIcon}\n                mode=\"bleed\"\n                onClick={() => onChange({contrast: undefined})}\n                padding={2}\n                tooltip=\"Reset to auto\"\n              />\n            )}\n          </Flex>\n          <input\n            aria-label={`${name} contrast`}\n            className={range}\n            max={100}\n            min={15}\n            onChange={(event) => onChange({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      </Stack>\n    </Card>\n  )\n}\n\n/** One color of a scheme: a swatch with its value and an optional reset button */\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 or a default rather than explicitly set */\n  auto?: boolean\n  /** What the value is when it is not set: derived (`auto`) or the stock one (`default`) */\n  autoLabel?: 'auto' | 'default'\n  /** The accessible name of the picker */\n  label: string\n  onChange: (value: string) => void\n  onClear?: () => void\n  title: string\n  value: string\n}) {\n  const {adjusted, auto, autoLabel = 'auto', label, onChange, onClear, title, value} = props\n\n  return (\n    <Flex align=\"center\" gap={2}>\n      <input\n        aria-label={label}\n        className={swatch}\n        onChange={(event) => onChange(event.currentTarget.value)}\n        type=\"color\"\n        value={value}\n      />\n      <Stack className={colorRowText} 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 ? ` · ${autoLabel}` : ''}\n        </Text>\n      </Stack>\n      {onClear && !auto && (\n        <TooltipButton\n          icon={ResetIcon}\n          mode=\"bleed\"\n          onClick={onClear}\n          padding={2}\n          tooltip={`Reset to ${autoLabel}`}\n        />\n      )}\n    </Flex>\n  )\n}\n","import {isColor} from '../lib/mix'\nimport {\n  type BuildThemeOptions,\n  MAXIMUM_CONTRAST,\n  MINIMUM_CONTRAST,\n  SCHEMES,\n  type SchemeThemeOptions,\n} from '../theme/options'\nimport {displayTitle} from './themes'\n\n/** What a theme code carries: a theme's title and its options @internal */\nexport interface SharedTheme {\n  title: string\n  options: BuildThemeOptions\n}\n\n/**\n * The version of the code format, the first byte of every code — bumped if\n * the layout below ever changes, so older codes can still be told apart\n */\nconst VERSION = 1\n\n/** The fields a scheme's options can set, in the order their bytes go */\nconst FIELDS = ['accent', 'text', 'background', 'contrast'] as const\n\n/**\n * Turns a theme into a short code to share in a message: `title`, and the\n * colors and contrasts of both schemes, packed into bytes — one flag byte says\n * which of the eight fields are set, each color is its three RGB bytes and a\n * contrast one byte, and the title takes up the rest — then base64url'd, so\n * it is one word without padding, safe in URLs and chat. A theme setting\n * everything comes to about 30 bytes plus its title.\n *\n * @internal\n */\nexport function encodeTheme(theme: SharedTheme): string {\n  const bytes: number[] = [VERSION, 0]\n  let flags = 0\n\n  SCHEMES.forEach((scheme, schemeIndex) => {\n    const options: SchemeThemeOptions = theme.options[scheme] ?? {}\n\n    FIELDS.forEach((field, fieldIndex) => {\n      const value = options[field]\n\n      if (value === undefined) return\n\n      if (field === 'contrast') {\n        if (typeof value !== 'number' || !Number.isFinite(value)) return\n\n        bytes.push(Math.round(Math.min(MAXIMUM_CONTRAST, Math.max(MINIMUM_CONTRAST, value))))\n      } else {\n        if (typeof value !== 'string' || !isColor(value)) return\n\n        bytes.push(...rgbBytes(value))\n      }\n\n      flags |= 1 << (schemeIndex * FIELDS.length + fieldIndex)\n    })\n  })\n\n  bytes[1] = flags\n  bytes.push(...new TextEncoder().encode(theme.title.trim()))\n\n  return toBase64Url(Uint8Array.from(bytes))\n}\n\n/**\n * Reads a theme back out of a code — as pasted, so surrounding whitespace and\n * words around the code are fine: the first word that is a code counts. `null`\n * when nothing in the text is one.\n *\n * @internal\n */\nexport function decodeTheme(text: string): SharedTheme | null {\n  for (const word of text.trim().split(/\\s+/)) {\n    const theme = decodeCode(word)\n\n    if (theme) return theme\n  }\n\n  return null\n}\n\nfunction decodeCode(code: string): SharedTheme | null {\n  const bytes = fromBase64Url(code)\n\n  if (!bytes || bytes.length < 2 || bytes[0] !== VERSION) return null\n\n  const flags = bytes[1]\n  const options: BuildThemeOptions = {}\n  let offset = 2\n\n  for (const [schemeIndex, scheme] of SCHEMES.entries()) {\n    const schemeOptions: SchemeThemeOptions = {}\n\n    for (const [fieldIndex, field] of FIELDS.entries()) {\n      if (!(flags & (1 << (schemeIndex * FIELDS.length + fieldIndex)))) continue\n\n      if (field === 'contrast') {\n        if (offset + 1 > bytes.length) return null\n\n        schemeOptions.contrast = Math.min(\n          MAXIMUM_CONTRAST,\n          Math.max(MINIMUM_CONTRAST, bytes[offset]),\n        )\n        offset += 1\n      } else {\n        if (offset + 3 > bytes.length) return null\n\n        schemeOptions[field] = hexColor(bytes.subarray(offset, offset + 3))\n        offset += 3\n      }\n    }\n\n    if (Object.keys(schemeOptions).length > 0) options[scheme] = schemeOptions\n  }\n\n  let title: string\n\n  try {\n    title = new TextDecoder('utf-8', {fatal: true}).decode(bytes.subarray(offset))\n  } catch {\n    return null\n  }\n\n  return {title: displayTitle(title), options}\n}\n\n/** The three RGB bytes of a `#rgb` or `#rrggbb` color */\nfunction rgbBytes(color: string): number[] {\n  const hex = color.length === 4 ? color.slice(1).replaceAll(/./g, '$&$&') : color.slice(1)\n\n  return [0, 2, 4].map((start) => parseInt(hex.slice(start, start + 2), 16))\n}\n\nfunction hexColor(rgb: Uint8Array): string {\n  return `#${[...rgb].map((byte) => byte.toString(16).padStart(2, '0')).join('')}`\n}\n\nfunction toBase64Url(bytes: Uint8Array): string {\n  let binary = ''\n\n  for (const byte of bytes) binary += String.fromCharCode(byte)\n\n  return btoa(binary).replaceAll('+', '-').replaceAll('/', '_').replace(/=+$/, '')\n}\n\nfunction fromBase64Url(code: string): Uint8Array | null {\n  if (!/^[A-Za-z0-9_-]+$/.test(code)) return null\n\n  const base64 = code.replaceAll('-', '+').replaceAll('_', '/')\n\n  try {\n    return Uint8Array.from(atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '=')), (char) =>\n      char.charCodeAt(0),\n    )\n  } catch {\n    return null\n  }\n}\n","import {useToast} from '@sanity/ui/toast'\nimport {useEffect} from 'react'\n\nimport {useThemer} from './context'\nimport {decodeTheme, encodeTheme, type SharedTheme} from './share'\nimport {displayTitle} from './themes'\n\n/**\n * Copying a theme as a code to share, and adding a theme from a code someone\n * shared — with toasts telling how it went.\n *\n * @internal\n */\nexport function useThemeCodes(): {\n  copyTheme: (theme: SharedTheme) => Promise<void>\n  /** Adds the theme in the text, if there is one — the result says whether there was */\n  addThemeFromText: (text: string) => boolean\n  /** Adds the theme on the clipboard, if there is one and the browser hands the clipboard over */\n  addThemeFromClipboard: () => Promise<'added' | 'no-theme' | 'no-clipboard'>\n} {\n  const {send} = useThemer()\n  const toast = useToast()\n\n  const copyTheme = async (theme: SharedTheme) => {\n    const title = displayTitle(theme.title)\n\n    try {\n      await navigator.clipboard.writeText(encodeTheme(theme))\n      toast.push({\n        status: 'success',\n        title: `Copied ${title} as a code`,\n        description: 'Paste it in the themer of another Studio to add the theme there',\n      })\n    } catch {\n      toast.push({status: 'error', title: `Could not copy ${title}`})\n    }\n  }\n\n  const addThemeFromText = (text: string) => {\n    const theme = decodeTheme(text)\n\n    if (!theme) return false\n\n    send({type: 'theme.import', title: theme.title, options: theme.options})\n    toast.push({status: 'success', title: `Added ${theme.title}`})\n\n    return true\n  }\n\n  const addThemeFromClipboard = async () => {\n    let text: string\n\n    try {\n      text = await navigator.clipboard.readText()\n    } catch {\n      return 'no-clipboard'\n    }\n\n    return addThemeFromText(text) ? 'added' : 'no-theme'\n  }\n\n  return {copyTheme, addThemeFromText, addThemeFromClipboard}\n}\n\n/**\n * Adds a theme pasted anywhere in the Studio while the themer's list is\n * showing — pastes into inputs and other editable things are theirs.\n *\n * @internal\n */\nexport function usePasteThemeCodes(): void {\n  const {open, send} = useThemer()\n  const toast = useToast()\n\n  useEffect(() => {\n    if (!open) return undefined\n\n    const handlePaste = (event: ClipboardEvent) => {\n      if (isEditable(event.target)) return\n\n      const theme = decodeTheme(event.clipboardData?.getData('text/plain') ?? '')\n\n      if (!theme) return\n\n      event.preventDefault()\n      send({type: 'theme.import', title: theme.title, options: theme.options})\n      toast.push({status: 'success', title: `Added ${theme.title}`})\n    }\n\n    document.addEventListener('paste', handlePaste)\n\n    return () => document.removeEventListener('paste', handlePaste)\n  }, [open, send, toast])\n}\n\nfunction isEditable(target: EventTarget | null): boolean {\n  return (\n    target instanceof HTMLElement &&\n    (target.isContentEditable || target.matches('input, textarea, select'))\n  )\n}\n","import {Button, Card, Dialog, Flex, Stack, Text, TextInput} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport {useThemeCodes} from './useThemeCodes'\n\n/**\n * Where a theme code someone shared gets pasted by hand — for browsers that\n * do not hand the clipboard over, and for codes that are not on it.\n *\n * @internal\n */\nexport function PasteThemeDialog(props: {onClose: () => void}) {\n  const {onClose} = props\n  const {addThemeFromText} = useThemeCodes()\n  const [text, setText] = useState('')\n  const [invalid, setInvalid] = useState(false)\n\n  const add = () => {\n    if (addThemeFromText(text)) {\n      onClose()\n    } else {\n      setInvalid(true)\n    }\n  }\n\n  return (\n    <Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button mode=\"ghost\" onClick={onClose} padding={2} text=\"Cancel\" />\n          <Button\n            disabled={text.trim() === ''}\n            onClick={add}\n            padding={2}\n            text=\"Add theme\"\n            tone=\"primary\"\n          />\n        </Flex>\n      }\n      header=\"Add a shared theme\"\n      id=\"themer-paste\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={0}\n    >\n      <form\n        onSubmit={(event) => {\n          event.preventDefault()\n          add()\n        }}\n      >\n        <Stack gap={3} padding={4}>\n          <Text muted size={1}>\n            Paste the code someone copied from their themer — the theme is added to your list and\n            applied.\n          </Text>\n          <TextInput\n            aria-describedby={invalid ? 'themer-paste-error' : undefined}\n            aria-invalid={invalid}\n            aria-label=\"Theme code\"\n            autoFocus\n            customValidity={invalid ? 'That is not a theme code' : undefined}\n            fontSize={1}\n            onChange={(event) => {\n              setText(event.currentTarget.value)\n              setInvalid(false)\n            }}\n            placeholder=\"AQ…\"\n            value={text}\n          />\n          {invalid && (\n            <Card id=\"themer-paste-error\" padding={3} radius={2} role=\"alert\" tone=\"critical\">\n              <Text size={1}>\n                That is not a theme code — codes are one word, copied from a theme&apos;s menu.\n              </Text>\n            </Card>\n          )}\n        </Stack>\n      </form>\n    </Dialog>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\nexport const root = style({\n  position: 'relative',\n})\n\n/** A bare button, so that the thumbnail and the title can carry the styling */\nexport const pickButton = style({\n  'appearance': 'none',\n  'display': 'block',\n  'boxSizing': 'border-box',\n  'width': '100%',\n  'margin': 0,\n  'padding': 0,\n  'border': 0,\n  'background': 'none',\n  'color': 'inherit',\n  'font': 'inherit',\n  'textAlign': 'center',\n  'cursor': 'pointer',\n  ':focus': {\n    outline: 'none',\n  },\n})\n\n/**\n * Wraps the thumbnail with room for the ring that marks the applied theme —\n * hovering shows a faint ring, the applied theme the focus ring color, and\n * keyboard focus an outline. The rings are drawn inside the frame's padding,\n * so nothing sticks out to be clipped by the scrolling list.\n */\nexport const frame = style({\n  display: 'block',\n  padding: 4,\n  borderRadius: 10,\n  transition: 'box-shadow 100ms',\n  selectors: {\n    [`${pickButton}:hover &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-border-color)',\n    },\n    [`${pickButton}[aria-pressed='true'] &`]: {\n      boxShadow: 'inset 0 0 0 2px var(--card-focus-ring-color)',\n    },\n    [`${pickButton}:focus-visible &`]: {\n      outline: '2px solid var(--card-focus-ring-color)',\n      outlineOffset: -2,\n    },\n  },\n})\n\n/**\n * The actions menu sits on the thumbnail's top right corner, like the actions\n * of an image input, and only shows on hover, on keyboard focus, and while it\n * is open — its popover is portaled, so an open menu does not count as focus\n * within\n */\nexport const menuSlot = style({\n  position: 'absolute',\n  top: 10,\n  right: 10,\n  opacity: 0,\n  transition: 'opacity 100ms',\n  selectors: {\n    [`${root}:hover &, ${root}:focus-within &, &[data-visible='true']`]: {\n      opacity: 1,\n    },\n  },\n})\n\n/** The dark card behind the menu button sizes to the button, not the slot */\nexport const menuCard = style({\n  display: 'inline-block',\n})\n","import {ArrowDownIcon} from '@sanity/icons/ArrowDown'\nimport {ArrowUpIcon} from '@sanity/icons/ArrowUp'\nimport {CopyIcon} from '@sanity/icons/Copy'\nimport {EditIcon} from '@sanity/icons/Edit'\nimport {EllipsisHorizontalIcon} from '@sanity/icons/EllipsisHorizontal'\nimport {ShareIcon} from '@sanity/icons/Share'\nimport {TrashIcon} from '@sanity/icons/Trash'\nimport {Box, Button, Card, Text, useRootTheme} from '@sanity/ui'\nimport {Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui/menu'\nimport {Tooltip} from '@sanity/ui/tooltip'\nimport {Reorder, useDragControls} from 'motion/react'\nimport {useRef, useState} from 'react'\nimport scrollIntoView from 'scroll-into-view-if-needed'\n\nimport {useThemer} from './context'\nimport {displayTitle, type ThemerTheme} from './themes'\nimport {ThemeThumbnail} from './ThemeThumbnail'\nimport {useThemeCodes} from './useThemeCodes'\n\nimport {frame, menuCard, menuSlot, pickButton, root} from './ThemeCard.css'\n\n/**\n * Scrolls the applied theme's card into view when it is not already, as a\n * ref: the list scrolls to it as it mounts — coming back from the editor or\n * the removed themes — and when another theme gets applied\n */\nfunction scrollRefIntoViewIfNeeded(node: HTMLElement | null) {\n  if (node) scrollIntoView(node, {block: 'nearest', scrollMode: 'if-needed'})\n}\n\n/**\n * One theme in the list: the floating preview with the title below it, like\n * an appearance option in macOS System Settings. Clicking it applies the\n * theme to the whole Studio, dragging it moves the theme to another place in\n * the list; its menu holds the move, edit, duplicate and remove flows that\n * apply to the theme.\n *\n * @internal\n */\nexport function ThemeCard(props: {active: boolean; theme: ThemerTheme}) {\n  const {active, theme} = props\n  const {themes, send} = useThemer()\n  const {copyTheme} = useThemeCodes()\n  const {scheme} = useRootTheme()\n  const [menuOpen, setMenuOpen] = useState(false)\n  const dragControls = useDragControls()\n  // Letting go of a drag also clicks the card, and that click must not pick\n  const dragged = useRef(false)\n  const title = displayTitle(theme.title)\n  const index = themes.findIndex((candidate) => candidate.slug === theme.slug)\n\n  const moveTo = (to: number) => {\n    const order = themes.map((candidate) => candidate.slug)\n\n    order.splice(to, 0, ...order.splice(index, 1))\n    send({type: 'theme.reorder', order})\n  }\n\n  return (\n    <Reorder.Item\n      as=\"div\"\n      className={root}\n      dragControls={dragControls}\n      dragListener={false}\n      onDragEnd={() => {\n        // The click lands before the next frame\n        requestAnimationFrame(() => {\n          dragged.current = false\n        })\n      }}\n      onDragStart={() => {\n        dragged.current = true\n      }}\n      ref={active ? scrollRefIntoViewIfNeeded : undefined}\n      value={theme.slug}\n      whileDrag={{scale: 1.04}}\n    >\n      <button\n        aria-pressed={active}\n        className={pickButton}\n        onClick={() => {\n          if (!dragged.current) send({type: 'theme.pick', slug: theme.slug})\n        }}\n        onPointerDown={(event) => {\n          // A mouse or pen drags the card off the button; a finger scrolls the\n          // list instead, and moves themes from the menu\n          if (event.pointerType !== 'touch') dragControls.start(event)\n        }}\n        type=\"button\"\n      >\n        <span className={frame}>\n          <ThemeThumbnail options={theme.options} />\n        </span>\n        <Box as=\"span\" display=\"block\" paddingTop={2} paddingX={2}>\n          <Text\n            align=\"center\"\n            as=\"span\"\n            size={1}\n            textOverflow=\"ellipsis\"\n            weight={active ? 'medium' : 'regular'}\n          >\n            {title}\n          </Text>\n        </Box>\n      </button>\n\n      {/* The tooltip wraps a card rather than the button: the menu button\n          clones its button to wire it up, which a tooltip in between would\n          swallow. The card keeps the button dark, as it sits on the dark\n          half of the thumbnail, while the menu opens in the sidebar's scheme */}\n      <div className={menuSlot} data-visible={menuOpen}>\n        <Tooltip animate content={<Text size={1}>Show more</Text>} placement=\"bottom\" portal>\n          <Card className={menuCard} radius={2} scheme=\"dark\">\n            <MenuButton\n              button={\n                <Button\n                  aria-label={`Show more for ${title}`}\n                  fontSize={1}\n                  icon={EllipsisHorizontalIcon}\n                  mode=\"ghost\"\n                  padding={1}\n                  radius={2}\n                />\n              }\n              id={`themer-theme-${theme.slug}`}\n              menu={\n                <Menu>\n                  <MenuItem\n                    disabled={index <= 0}\n                    icon={ArrowUpIcon}\n                    onClick={() => moveTo(index - 1)}\n                    text=\"Move up\"\n                  />\n                  <MenuItem\n                    disabled={index >= themes.length - 1}\n                    icon={ArrowDownIcon}\n                    onClick={() => moveTo(index + 1)}\n                    text=\"Move down\"\n                  />\n                  <MenuDivider />\n                  {theme.source === 'custom' && (\n                    <MenuItem\n                      icon={EditIcon}\n                      onClick={() => send({type: 'theme.edit', slug: theme.slug})}\n                      text=\"Edit\"\n                    />\n                  )}\n                  <MenuItem\n                    icon={CopyIcon}\n                    onClick={() => send({type: 'theme.duplicate', slug: theme.slug})}\n                    text={theme.source === 'custom' ? 'Duplicate' : 'Duplicate to edit'}\n                  />\n                  <MenuItem\n                    icon={ShareIcon}\n                    onClick={() => void copyTheme(theme)}\n                    text=\"Copy to share\"\n                  />\n                  {theme.source !== 'config' && (\n                    <>\n                      <MenuDivider />\n                      <MenuItem\n                        icon={TrashIcon}\n                        onClick={() => send({type: 'theme.remove', slug: theme.slug})}\n                        text=\"Remove\"\n                        tone=\"critical\"\n                      />\n                    </>\n                  )}\n                </Menu>\n              }\n              onClose={() => setMenuOpen(false)}\n              onOpen={() => setMenuOpen(true)}\n              popover={{animate: true, placement: 'bottom-end', portal: true, scheme}}\n            />\n          </Card>\n        </Tooltip>\n      </div>\n    </Reorder.Item>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\nimport {MAXIMUM_WIDTH, MINIMUM_WIDTH} from './sidebarWidth'\n\nimport {sidebarContent} from './ResizableSidebar.css'\n\nconst CARD_GAP = 16\n\n/**\n * The theme cards flow into two columns once the sidebar has been dragged a\n * third of the way from its narrowest to its widest. The breakpoints are\n * container queries on the sidebar's content (`ResizableSidebar`), which is\n * as wide as the sidebar itself.\n */\nconst TWO_COLUMNS_FROM = MINIMUM_WIDTH + (MAXIMUM_WIDTH - MINIMUM_WIDTH) * 0.3\n\n/** Three columns on the wider small screens the sidebar covers, where two would be huge */\nconst THREE_COLUMNS_FROM = 480\n\n/**\n * The columns share the width equally whatever the titles: a plain `1fr` may\n * not shrink below a card's min-content width, and a card's title does not\n * wrap, so one long title would widen its column past the sidebar\n */\nconst COLUMN = 'minmax(0, 1fr)'\n\nexport const cardGrid = style({\n  'display': 'grid',\n  'gridTemplateColumns': COLUMN,\n  'gap': CARD_GAP,\n  '@container': {\n    [`${sidebarContent} (min-width: ${TWO_COLUMNS_FROM}px)`]: {\n      gridTemplateColumns: `repeat(2, ${COLUMN})`,\n    },\n    [`${sidebarContent} (min-width: ${THREE_COLUMNS_FROM}px)`]: {\n      gridTemplateColumns: `repeat(3, ${COLUMN})`,\n    },\n  },\n})\n","import {AddIcon} from '@sanity/icons/Add'\nimport {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {RestoreIcon} from '@sanity/icons/Restore'\nimport {Box, Button, Card, Flex, Stack} from '@sanity/ui'\nimport {MotionConfig, Reorder} from 'motion/react'\nimport {useState} from 'react'\n\nimport {useThemer} from './context'\nimport {ImageFileButton} from './ImageFileButton'\nimport {optionsFromImagePalette, titleFromFileName} from './imagePalette'\nimport {PasteThemeDialog} from './PasteThemeDialog'\nimport {ScrollArea} from './ScrollArea'\nimport {ThemeCard} from './ThemeCard'\nimport {TooltipButton} from './TooltipButton'\nimport {useImagePalette} from './useImagePalette'\nimport {usePasteThemeCodes, useThemeCodes} from './useThemeCodes'\n\nimport {cardGrid} from './ThemeList.css'\n\n/**\n * One column at the sidebar's default width; wider sidebars — and the\n * overlay on small screens — fit more cards per row\n */\n/**\n * The flow for picking a theme: a grid of theme cards — the configured theme,\n * the presets and the user's own themes — that drag into the order the user\n * wants, with the entry points to the add and restore flows below. A theme\n * code someone shared pastes right into the list, or through the paste button.\n *\n * @internal\n */\nexport function ThemeList() {\n  const {themes, removed, active, send} = useThemer()\n  const {addThemeFromClipboard} = useThemeCodes()\n  const [pasting, setPasting] = useState(false)\n\n  usePasteThemeCodes()\n\n  const {busy, pickImage} = useImagePalette((palette, file) =>\n    send({\n      type: 'theme.add',\n      title: titleFromFileName(file.name),\n      options: optionsFromImagePalette(palette),\n      palette,\n      imageUrl: URL.createObjectURL(file),\n    }),\n  )\n\n  return (\n    <>\n      <ScrollArea padding={3}>\n        <Stack gap={4}>\n          {/* The group tells a column from a grid by measuring the cards, and\n              lets go of the layout animations for users who prefer reduced motion */}\n          <MotionConfig reducedMotion=\"user\">\n            <Reorder.Group\n              as=\"div\"\n              className={cardGrid}\n              onReorder={(order: string[]) => send({type: 'theme.reorder', order})}\n              values={themes.map((theme) => theme.slug)}\n            >\n              {themes.map((theme) => (\n                <ThemeCard active={theme.slug === active.slug} key={theme.slug} theme={theme} />\n              ))}\n            </Reorder.Group>\n          </MotionConfig>\n          {/* Trails the list rather than sitting in the footer, so the footer\n              does not shift when the first theme gets removed */}\n          {removed.length > 0 && (\n            <Button\n              gap={2}\n              icon={RestoreIcon}\n              mode=\"bleed\"\n              onClick={() => send({type: 'flow.removed'})}\n              padding={2}\n              text={`Show removed (${removed.length})`}\n              width=\"fill\"\n            />\n          )}\n        </Stack>\n      </ScrollArea>\n\n      <Card borderTop padding={3}>\n        <Flex gap={2}>\n          <Box flex={1}>\n            <TooltipButton\n              icon={AddIcon}\n              mode=\"ghost\"\n              onClick={() => send({type: 'theme.add'})}\n              text=\"Add theme\"\n              tooltip=\"Add a theme based on the applied one\"\n              width=\"fill\"\n            />\n          </Box>\n          <ImageFileButton\n            loading={busy}\n            mode=\"ghost\"\n            onFile={pickImage}\n            tooltip=\"Add a theme from the colors of an image\"\n          />\n          <TooltipButton\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={async () => {\n              // Straight from the clipboard where the browser allows; by hand otherwise\n              if ((await addThemeFromClipboard()) !== 'added') setPasting(true)\n            }}\n            tooltip=\"Add a theme from a code someone shared\"\n          />\n        </Flex>\n      </Card>\n\n      {pasting && <PasteThemeDialog onClose={() => setPasting(false)} />}\n    </>\n  )\n}\n","import {type BuildThemeOptions, SCHEMES, type SchemeThemeOptions} 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 in\n * each scheme.\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 lines: string[] = []\n\n  for (const scheme of SCHEMES) {\n    const values = minimized[scheme]\n\n    if (values) lines.push(serializeScheme(scheme, values))\n  }\n\n  return `import {buildTheme} from '@sanity/themer'\\n\\nexport const theme = buildTheme({\\n${lines.join('\\n')}\\n})\\n`\n}\n\n/** A scheme with up to two options fits on one line, more spread out */\nfunction serializeScheme(scheme: string, values: SchemeThemeOptions): string {\n  const entries: string[] = []\n\n  if (values.accent !== undefined) entries.push(`accent: '${values.accent}'`)\n  if (values.text !== undefined) entries.push(`text: '${values.text}'`)\n  if (values.background !== undefined) entries.push(`background: '${values.background}'`)\n  if (values.contrast !== undefined) entries.push(`contrast: ${values.contrast}`)\n\n  if (entries.length <= 2) {\n    return `  ${scheme}: {${entries.join(', ')}},`\n  }\n\n  return `  ${scheme}: {\\n${entries.map((entry) => `    ${entry},`).join('\\n')}\\n  },`\n}\n","import {ClipboardIcon} from '@sanity/icons/Clipboard'\nimport {Box, Button, Card, Dialog, Flex, Stack, Text} from '@sanity/ui'\nimport {Code} from '@sanity/ui/code'\nimport {useToast} from '@sanity/ui/toast'\nimport {registerLanguage} from 'react-refractor'\nimport typescript from 'refractor/typescript'\n\nimport {createThemeSnippet} from './snippet'\nimport {displayTitle, type ThemerTheme} from './themes'\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 dialog keeps losing. Registering the one\n// language the snippet needs keeps it highlighted from the first render.\nregisterLanguage(typescript)\n\n/**\n * Shows the `buildTheme` snippet that makes a theme permanent, in a dialog so\n * that it does not take up sidebar space or make the sidebar scroll as the\n * snippet changes shape with the theme.\n *\n * @internal\n */\nexport function ThemeSnippetDialog(props: {onClose: () => void; theme: ThemerTheme}) {\n  const {onClose, theme} = props\n  const toast = useToast()\n  const snippet = createThemeSnippet(theme.options)\n\n  const handleCopy = async () => {\n    try {\n      await navigator.clipboard.writeText(snippet)\n      toast.push({status: 'success', title: 'Copied the theme to the clipboard'})\n    } catch {\n      toast.push({status: 'error', title: 'Could not copy the theme'})\n    }\n  }\n\n  return (\n    <Dialog\n      animate\n      footer={\n        <Flex gap={2} justify=\"flex-end\" padding={3}>\n          <Button\n            gap={2}\n            icon={ClipboardIcon}\n            mode=\"ghost\"\n            onClick={() => void handleCopy()}\n            padding={2}\n            text=\"Copy\"\n          />\n        </Flex>\n      }\n      header=\"Add to your config\"\n      id=\"themer-snippet\"\n      onClickOutside={onClose}\n      onClose={onClose}\n      width={1}\n    >\n      <Box padding={4}>\n        <Stack gap={4}>\n          <Text muted size={1}>\n            Export this from <code>sanity.config.ts</code> and pass it as the <code>theme</code> of{' '}\n            <code>defineConfig</code> to make “{displayTitle(theme.title)}” the Studio theme without\n            this tool.\n          </Text>\n          <Card border overflow=\"auto\" padding={3} radius={2} tone=\"transparent\">\n            <Code language=\"ts\" size={1}>\n              {snippet}\n            </Code>\n          </Card>\n        </Stack>\n      </Box>\n    </Dialog>\n  )\n}\n","import {style} from '@vanilla-extract/css'\n\n/** Lets the title shrink and truncate instead of pushing the buttons out */\nexport const title = style({\n  minWidth: 0,\n})\n","import {ArrowLeftIcon} from '@sanity/icons/ArrowLeft'\nimport {CloseIcon} from '@sanity/icons/Close'\nimport {CodeBlockIcon} from '@sanity/icons/CodeBlock'\nimport {SplitVerticalIcon} from '@sanity/icons/SplitVertical'\nimport {Box, Card, Flex, Text} from '@sanity/ui'\nimport {useState} from 'react'\n\nimport {useThemer} from './context'\nimport {RemovedThemes} from './RemovedThemes'\nimport {ThemeEditor} from './ThemeEditor'\nimport {ThemeList} from './ThemeList'\nimport {ThemeSnippetDialog} from './ThemeSnippetDialog'\nimport {TooltipButton} from './TooltipButton'\n\nimport {title} from './ThemerSidebar.css'\n\nconst VIEW_TITLES = {\n  list: 'Themer',\n  edit: 'Edit theme',\n  removed: 'Removed themes',\n} as const\n\n/**\n * The themer sidebar: a header that navigates between the flows and toggles\n * the split preview, the flow itself — picking a theme, editing one, or\n * restoring removed ones — and the dialog with the `buildTheme` snippet of\n * the applied theme.\n *\n * @internal\n */\nexport function ThemerSidebar() {\n  const {active, split, view, navbarHeight, send} = useThemer()\n  const [snippetOpen, setSnippetOpen] = useState(false)\n  const inList = view.name === 'list'\n\n  return (\n    <Card height=\"fill\">\n      <Flex direction=\"column\" height=\"fill\">\n        {/* The header sits next to the Studio navbar and takes its height, so\n            the two bottom borders line up — whatever height the Studio, its\n            breakpoint or a custom navbar gives it */}\n        <Card\n          borderBottom\n          padding={3}\n          sizing=\"border\"\n          style={navbarHeight === null ? undefined : {height: navbarHeight}}\n        >\n          <Flex align=\"center\" gap={1} height=\"fill\">\n            {!inList && (\n              <TooltipButton\n                icon={ArrowLeftIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'flow.list'})}\n                padding={2}\n                tooltip=\"Back to the themes\"\n              />\n            )}\n            <Box className={title} flex={1}>\n              <Text size={1} textOverflow=\"ellipsis\" weight=\"semibold\">\n                {VIEW_TITLES[view.name]}\n              </Text>\n            </Box>\n            {/* Packed without gaps, so the title still fits next to them at the\n                narrowest sidebar width */}\n            <Flex>\n              {view.name !== 'removed' && (\n                <>\n                  <TooltipButton\n                    aria-pressed={split}\n                    icon={SplitVerticalIcon}\n                    mode=\"bleed\"\n                    onClick={() => send({type: 'preview.toggle'})}\n                    padding={2}\n                    selected={split}\n                    tooltip=\"Show light and dark side by side\"\n                  />\n                  <TooltipButton\n                    icon={CodeBlockIcon}\n                    mode=\"bleed\"\n                    onClick={() => setSnippetOpen(true)}\n                    padding={2}\n                    tooltip=\"Show the code for the applied theme\"\n                  />\n                </>\n              )}\n              <TooltipButton\n                icon={CloseIcon}\n                mode=\"bleed\"\n                onClick={() => send({type: 'sidebar.close'})}\n                padding={2}\n                tooltip=\"Close themer\"\n              />\n            </Flex>\n          </Flex>\n        </Card>\n\n        {view.name === 'list' && <ThemeList />}\n        {view.name === 'edit' && <ThemeEditor focusTitle={view.focusTitle} slug={view.slug} />}\n        {view.name === 'removed' && <RemovedThemes />}\n      </Flex>\n\n      {snippetOpen && <ThemeSnippetDialog onClose={() => setSnippetOpen(false)} theme={active} />}\n    </Card>\n  )\n}\n","import {createContainer, createViewTransition, style} from '@vanilla-extract/css'\n\n/**\n * The view transition group of the sidebar, which the split preview's\n * transition (see `ThemerLayout.css.ts`) leaves alone: it never animates, and\n * the Studio copies animating underneath never paint over it\n */\nexport const sidebarTransition = createViewTransition()\n\n/** The sidebar's content, which the content's layout queries — as wide as the sidebar itself */\nexport const sidebarContent = createContainer()\n\nexport const sidebar = style({\n  flex: 'none',\n  viewTransitionName: sidebarTransition,\n  selectors: {\n    // On small screens the sidebar covers the Studio instead of standing next to it\n    \"&[data-overlay='true']\": {\n      position: 'absolute',\n      inset: 0,\n      width: 'auto',\n    },\n  },\n})\n\n/**\n * Draws the sidebar's border and gives the resize handle its card colors. It\n * does not clip, so the handle can straddle the border — the content is\n * clipped one level down instead.\n */\nexport const frame = style({\n  position: 'relative',\n})\n\n/**\n * Clips the content, and is the container its layout queries: as wide as\n * the sidebar, whether or not a scrollbar takes room inside — see the theme\n * grid's columns in `ThemeList.css.ts`\n */\nexport const content = style({\n  containerType: 'inline-size',\n  containerName: sidebarContent,\n})\n\n/**\n * The grab area along the sidebar's left edge. It straddles the border so it\n * is easy to hit, and highlights while hovered, focused or dragged.\n */\nexport const resizeHandle = style({\n  'position': 'absolute',\n  'top': 0,\n  'bottom': 0,\n  'left': -3,\n  'zIndex': 1,\n  'width': 7,\n  'cursor': 'col-resize',\n  'touchAction': 'none',\n  '::after': {\n    content: '',\n    position: 'absolute',\n    top: 0,\n    bottom: 0,\n    left: 2,\n    width: 3,\n    background: 'var(--card-focus-ring-color)',\n    opacity: 0,\n    transition: 'opacity 100ms',\n  },\n  ':focus': {\n    outline: 'none',\n  },\n  'selectors': {\n    \"&:hover::after, &:focus-visible::after, &[data-dragging='true']::after\": {\n      opacity: 1,\n    },\n  },\n})\n","import {Box, Card, Layer} from '@sanity/ui'\nimport {useCallback, useEffect, useRef, useState} from 'react'\n\nimport {MAXIMUM_WIDTH, MINIMUM_WIDTH} from './sidebarWidth'\nimport {ThemerSidebar} from './ThemerSidebar'\n\nimport {content, frame, resizeHandle, sidebar} from './ResizableSidebar.css'\n\n/** How far one arrow key press resizes the sidebar */\nconst KEYBOARD_STEP = 16\n\nconst WIDTH_STORAGE_KEY = 'sanityStudio:themer:width'\n\nfunction clampWidth(width: number): number {\n  return Math.min(MAXIMUM_WIDTH, Math.max(MINIMUM_WIDTH, Math.round(width)))\n}\n\nfunction readStoredWidth(): number {\n  try {\n    const stored = Number(localStorage.getItem(WIDTH_STORAGE_KEY))\n\n    return Number.isFinite(stored) && stored > 0 ? clampWidth(stored) : MINIMUM_WIDTH\n  } catch {\n    return MINIMUM_WIDTH\n  }\n}\n\nfunction writeStoredWidth(width: number): void {\n  try {\n    if (width === MINIMUM_WIDTH) {\n      localStorage.removeItem(WIDTH_STORAGE_KEY)\n    } else {\n      localStorage.setItem(WIDTH_STORAGE_KEY, String(width))\n    }\n  } catch {\n    // Storage can be unavailable (e.g. private browsing) — the width just won't persist\n  }\n}\n\n/**\n * The themer sidebar, in a layer along the right edge of the Studio. Its left\n * edge drags (or arrow-keys) it wider, up to twice its default width — the\n * width sticks between sessions. As an overlay (small screens) it covers the\n * Studio edge to edge instead, with nothing to resize.\n *\n * @internal\n */\nexport default function ResizableSidebar(props: {overlay: boolean}) {\n  const {overlay} = props\n  const [width, setWidth] = useState(readStoredWidth)\n  const [dragging, setDragging] = useState(false)\n  const drag = useRef<{pointerId: number; startX: number; startWidth: number} | null>(null)\n\n  useEffect(() => writeStoredWidth(width), [width])\n\n  const handlePointerDown = useCallback(\n    (event: React.PointerEvent<HTMLDivElement>) => {\n      if (event.button !== 0) return\n\n      event.preventDefault()\n      event.currentTarget.setPointerCapture(event.pointerId)\n      drag.current = {pointerId: event.pointerId, startX: event.clientX, startWidth: width}\n      setDragging(true)\n    },\n    [width],\n  )\n\n  const handlePointerMove = useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    // The sidebar sits on the right, so dragging left makes it wider\n    setWidth(clampWidth(drag.current.startWidth - (event.clientX - drag.current.startX)))\n  }, [])\n\n  const handlePointerUp = useCallback((event: React.PointerEvent<HTMLDivElement>) => {\n    if (!drag.current || drag.current.pointerId !== event.pointerId) return\n\n    drag.current = null\n    setDragging(false)\n  }, [])\n\n  const handleKeyDown = useCallback((event: React.KeyboardEvent<HTMLDivElement>) => {\n    const steps: Record<string, number> = {\n      ArrowLeft: KEYBOARD_STEP,\n      ArrowRight: -KEYBOARD_STEP,\n      Home: MAXIMUM_WIDTH,\n      End: -MAXIMUM_WIDTH,\n    }\n    const step = steps[event.key]\n\n    if (step === undefined) return\n\n    event.preventDefault()\n    setWidth((current) => clampWidth(current + step))\n  }, [])\n\n  return (\n    <Layer\n      className={sidebar}\n      data-overlay={overlay}\n      style={overlay ? undefined : {width}}\n      zOffset={100}\n    >\n      <Card borderLeft={!overlay} className={frame} height=\"fill\">\n        {!overlay && (\n          <div\n            aria-label=\"Resize the themer\"\n            className={resizeHandle}\n            aria-orientation=\"vertical\"\n            aria-valuemax={MAXIMUM_WIDTH}\n            aria-valuemin={MINIMUM_WIDTH}\n            aria-valuenow={width}\n            data-dragging={dragging}\n            onDoubleClick={() => setWidth(MINIMUM_WIDTH)}\n            onKeyDown={handleKeyDown}\n            onPointerCancel={handlePointerUp}\n            onPointerDown={handlePointerDown}\n            onPointerMove={handlePointerMove}\n            onPointerUp={handlePointerUp}\n            // oxlint-disable-next-line prefer-tag-over-role -- a window splitter is a focusable, draggable separator, which an hr is not\n            role=\"separator\"\n            tabIndex={0}\n          />\n        )}\n        <Box className={content} height=\"fill\" overflow=\"hidden\">\n          <ThemerSidebar />\n        </Box>\n      </Card>\n    </Layer>\n  )\n}\n"],"mappings":"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"}
\ No newline at end of file