shadimage
tool-ui
blockcode-blocksource: ok · hit

Code Block

Display syntax-highlighted code snippets.

npx shadcn add "https://www.tool-ui.com/r/code-block.json"
free

Visual style

terminal-mono

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · light
iconslucide-react
formszod

Registry dependencies

buttoncollapsible

Files11 · source cached 10/9/2026, 4:05:22 AM

components/tool-ui/code-block/_adapter.tsx
/**
 * Adapter: UI and utility re-exports for copy-standalone portability.
 *
 * When copying this component to another project, update these imports
 * to match your project's paths:
 *
 *   cn          → Your Tailwind merge utility (e.g., "@/lib/utils", "~/lib/cn")
 *   Button      → shadcn/ui Button
 *   Collapsible → shadcn/ui Collapsible
 */

export { cn } from "@/lib/utils";
export { Button } from "@/components/ui/button";
export { Collapsible, CollapsibleTrigger } from "@/components/ui/collapsible";
components/tool-ui/code-block/code-block.tsx
"use client";

import {
  useState,
  useCallback,
  useEffect,
  createContext,
  use,
  type ReactNode,
} from "react";
import {
  createHighlighter,
  createJavaScriptRegexEngine,
  type Highlighter,
} from "shiki";
import { Copy, Check, ChevronDown, ChevronUp } from "lucide-react";
import pierreDarkTheme from "../shared/pierre-dark-theme.js";
import pierreLightTheme from "../shared/pierre-light-theme.js";
import type { CodeBlockLineNumbersMode, CodeBlockProps } from "./schema";
import { useCopyToClipboard } from "../shared/use-copy-to-clipboard";

import { Button, cn, Collapsible, CollapsibleTrigger } from "./_adapter";

const COPY_ID = "codeblock-code";
const MAX_HTML_CACHE_ENTRIES = 64;

let highlighterPromise: Promise<Highlighter> | null = null;

function getHighlighter(): Promise<Highlighter> {
  if (!highlighterPromise) {
    highlighterPromise = createHighlighter({
      themes: [pierreDarkTheme as never, pierreLightTheme as never],
      langs: [],
      engine: createJavaScriptRegexEngine(),
    });
  }
  return highlighterPromise;
}

const htmlCache = new Map<string, string>();

function getCacheKey(
  code: string,
  language: string,
  theme: string,
  lineNumbers: CodeBlockLineNumbersMode,
  highlightLines?: number[],
): string {
  return JSON.stringify({
    code,
    language,
    theme,
    lineNumbers,
    highlightLines: highlightLines ?? null,
  });
}

function setCachedHtml(cacheKey: string, html: string): void {
  if (htmlCache.has(cacheKey)) {
    htmlCache.set(cacheKey, html);
    return;
  }

  if (htmlCache.size >= MAX_HTML_CACHE_ENTRIES) {
    const oldestKey = htmlCache.keys().next().value;
    if (typeof oldestKey === "string") {
      htmlCache.delete(oldestKey);
    }
  }

  htmlCache.set(cacheKey, html);
}

const LANGUAGE_DISPLAY_NAMES: Record<string, string> = {
  typescript: "TypeScript",
  javascript: "JavaScript",
  python: "Python",
  tsx: "TSX",
  jsx: "JSX",
  json: "JSON",
  bash: "Bash",
  shell: "Shell",
  css: "CSS",
  html: "HTML",
  markdown: "Markdown",
  sql: "SQL",
  yaml: "YAML",
  go: "Go",
  rust: "Rust",
  text: "Plain Text",
};

function getLanguageDisplayName(lang: string): string {
  return LANGUAGE_DISPLAY_NAMES[lang.toLowerCase()] || lang.toUpperCase();
}

function getSystemTheme(): "light" | "dark" {
  if (typeof window === "undefined") return "light";
  return window.matchMedia?.("(prefers-color-scheme: dark)").matches
    ? "dark"
    : "light";
}

function getDocumentTheme(): "light" | "dark" | null {
  if (typeof document === "undefined") return null;
  const root = document.documentElement;
  const dataTheme = root.getAttribute("data-theme")?.toLowerCase();
  if (dataTheme === "dark") return "dark";
  if (dataTheme === "light") return "light";
  if (root.classList.contains("dark")) return "dark";
  if (root.classList.contains("light")) return "light";
  return null;
}

function useResolvedTheme(): "light" | "dark" {
  const [theme, setTheme] = useState<"light" | "dark">(() => {
    return getDocumentTheme() ?? getSystemTheme();
  });

  useEffect(() => {
    if (typeof window === "undefined" || typeof document === "undefined") {
      return;
    }

    const update = () => setTheme(getDocumentTheme() ?? getSystemTheme());

    const mql = window.matchMedia?.("(prefers-color-scheme: dark)");
    mql?.addEventListener("change", update);

    const observer = new MutationObserver(update);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class", "data-theme"],
    });

    return () => {
      mql?.removeEventListener("change", update);
      observer.disconnect();
    };
  }, []);

  return theme;
}

export type CodeBlockRootProps = CodeBlockProps & {
  children: ReactNode;
  expanded?: boolean;
  defaultExpanded?: boolean;
  onExpandedChange?: (expanded: boolean) => void;
};

type CodeBlockSharedState = {
  id: string;
  code: string;
  language: string;
  filename?: string;
  highlightedHtml: string | null;
  isCopied: boolean;
  copyCode: () => void;
  lineCount: number;
  isCollapsed: boolean;
  shouldCollapse: boolean;
  toggleExpanded: () => void;
};

const CodeBlockContext = createContext<CodeBlockSharedState | null>(null);

function useCodeBlock(): CodeBlockSharedState {
  const context = use(CodeBlockContext);
  if (!context) {
    throw new Error(
      "CodeBlock subcomponents must be used within <CodeBlock.Root>.",
    );
  }
  return context;
}

function CodeBlockRoot({
  id,
  code,
  language = "text",
  lineNumbers = "visible",
  filename,
  highlightLines,
  maxCollapsedLines,
  className,
  children,
  expanded: expandedProp,
  defaultExpanded = false,
  onExpandedChange,
}: CodeBlockRootProps) {
  const resolvedTheme = useResolvedTheme();
  const [expandedState, setExpandedState] = useState(defaultExpanded);
  const { copiedId, copy } = useCopyToClipboard();
  const isCopied = copiedId === COPY_ID;

  const expanded = expandedProp ?? expandedState;
  const setExpanded = useCallback(
    (nextExpanded: boolean) => {
      if (expandedProp === undefined) {
        setExpandedState(nextExpanded);
      }
      onExpandedChange?.(nextExpanded);
    },
    [expandedProp, onExpandedChange],
  );

  const theme = resolvedTheme === "dark" ? "pierre-dark" : "pierre-light";
  const cacheKey = getCacheKey(
    code,
    language,
    theme,
    lineNumbers,
    highlightLines,
  );

  const [highlightedHtml, setHighlightedHtml] = useState<string | null>(
    () => htmlCache.get(cacheKey) ?? null,
  );

  useEffect(() => {
    const cached = htmlCache.get(cacheKey);
    if (cached) {
      setHighlightedHtml(cached);
      return;
    }

    let cancelled = false;
    const showLineNumbers = lineNumbers === "visible";

    async function highlight() {
      if (!code) {
        if (!cancelled) setHighlightedHtml("");
        return;
      }

      try {
        const highlighter = await getHighlighter();
        const loadedLangs = highlighter.getLoadedLanguages();

        if (!loadedLangs.includes(language)) {
          await highlighter.loadLanguage(
            language as Parameters<Highlighter["loadLanguage"]>[0],
          );
        }

        const lineCount = code.split("\n").length;
        const lineNumberWidth = `${String(lineCount).length + 0.5}ch`;

        const html = highlighter.codeToHtml(code, {
          lang: language,
          theme,
          transformers: [
            {
              line(node, line) {
                node.properties["data-line"] = line;
                if (highlightLines?.includes(line)) {
                  const highlightBg =
                    resolvedTheme === "dark"
                      ? "rgba(255,255,255,0.1)"
                      : "rgba(0,0,0,0.05)";
                  node.properties.style = `background:${highlightBg};`;
                }
                if (showLineNumbers) {
                  node.children.unshift({
                    type: "element",
                    tagName: "span",
                    properties: {
                      style: `display:inline-block;width:${lineNumberWidth};text-align:right;margin-right:1.5em;user-select:none;opacity:0.5;`,
                      "aria-hidden": "true",
                    },
                    children: [{ type: "text", value: String(line) }],
                  });
                }
              },
            },
          ],
        });
        if (!cancelled) {
          setCachedHtml(cacheKey, html);
          setHighlightedHtml(html);
        }
      } catch {
        const escaped = code
          .replace(/&/g, "&amp;")
          .replace(/</g, "&lt;")
          .replace(/>/g, "&gt;");
        if (!cancelled) {
          setHighlightedHtml(`<pre><code>${escaped}</code></pre>`);
        }
      }
    }
    void highlight();
    return () => {
      cancelled = true;
    };
  }, [
    cacheKey,
    code,
    language,
    lineNumbers,
    theme,
    highlightLines,
    resolvedTheme,
  ]);

  const lineCount = code.split("\n").length;
  const shouldCollapse = !!maxCollapsedLines && lineCount > maxCollapsedLines;
  const isCollapsed = shouldCollapse && !expanded;

  const copyCode = useCallback(() => {
    void copy(code, COPY_ID);
  }, [code, copy]);

  const toggleExpanded = useCallback(() => {
    setExpanded(!expanded);
  }, [expanded, setExpanded]);

  const state: CodeBlockSharedState = {
    id,
    code,
    language,
    filename,
    highlightedHtml,
    isCopied,
    copyCode,
    lineCount,
    shouldCollapse,
    isCollapsed,
    toggleExpanded,
  };

  return (
    <CodeBlockContext.Provider value={state}>
      <div
        className={cn(
          "@container flex w-full min-w-80 flex-col gap-3",
          className,
        )}
        data-tool-ui-id={id}
        data-slot="code-block"
      >
        <div className="border-border bg-card overflow-hidden rounded-lg border shadow-xs">
          <Collapsible open={!isCollapsed}>{children}</Collapsible>
        </div>
      </div>
    </CodeBlockContext.Provider>
  );
}

export type CodeBlockSectionProps = {
  className?: string;
};

function CodeBlockHeader({ className }: CodeBlockSectionProps) {
  const { language, filename, isCopied, copyCode } = useCodeBlock();
  return (
    <div
      className={cn(
        "bg-card flex items-center justify-between border-b px-4 py-2",
        className,
      )}
    >
      <div className="flex items-center gap-1">
        <span className="text-muted-foreground text-sm">
          {getLanguageDisplayName(language)}
        </span>
        {filename && (
          <>
            <span className="text-muted-foreground/50">•</span>
            <span className="text-foreground text-sm font-medium">
              {filename}
            </span>
          </>
        )}
      </div>
      <Button
        variant="ghost"
        size="sm"
        onClick={copyCode}
        className="h-7 w-7 p-0"
        aria-label={isCopied ? "Copied" : "Copy code"}
      >
        {isCopied ? (
          <Check className="h-4 w-4 text-green-700 dark:text-green-400" />
        ) : (
          <Copy className="text-muted-foreground h-4 w-4" />
        )}
      </Button>
    </div>
  );
}

function CodeBlockContent({ className }: CodeBlockSectionProps) {
  const { highlightedHtml, isCollapsed } = useCodeBlock();
  return (
    <div
      className={cn(
        "overflow-x-auto overflow-y-clip text-[13px] leading-[1.4] [&_pre]:bg-transparent [&_pre]:py-4",
        isCollapsed && "max-h-[200px]",
        className,
      )}
    >
      {highlightedHtml && (
        <div dangerouslySetInnerHTML={{ __html: highlightedHtml }} />
      )}
    </div>
  );
}

function CodeBlockCollapseToggle({ className }: CodeBlockSectionProps) {
  const { shouldCollapse, isCollapsed, toggleExpanded, lineCount } =
    useCodeBlock();

  if (!shouldCollapse) return null;

  return (
    <CollapsibleTrigger asChild>
      <Button
        variant="ghost"
        onClick={toggleExpanded}
        className={cn(
          "text-muted-foreground w-full rounded-none border-t font-normal",
          className,
        )}
      >
        {isCollapsed ? (
          <>
            <ChevronDown className="mr-1 size-4" />
            Show all {lineCount} lines
          </>
        ) : (
          <>
            <ChevronUp className="mr-2 h-4 w-4" />
            Collapse
          </>
        )}
      </Button>
    </CollapsibleTrigger>
  );
}

export type CodeBlockComposedProps = Omit<CodeBlockRootProps, "children">;

function CodeBlockComposed(props: CodeBlockComposedProps) {
  return (
    <CodeBlockRoot {...props}>
      <CodeBlockHeader />
      <CodeBlockContent />
      <CodeBlockCollapseToggle />
    </CodeBlockRoot>
  );
}

type CodeBlockComponent = typeof CodeBlockComposed & {
  Root: typeof CodeBlockRoot;
  Header: typeof CodeBlockHeader;
  Content: typeof CodeBlockContent;
  CollapseToggle: typeof CodeBlockCollapseToggle;
};

export const CodeBlock = Object.assign(CodeBlockComposed, {
  Root: CodeBlockRoot,
  Header: CodeBlockHeader,
  Content: CodeBlockContent,
  CollapseToggle: CodeBlockCollapseToggle,
}) as CodeBlockComponent;
components/tool-ui/code-block/index.tsx
export { CodeBlock } from "./code-block";
export type {
  CodeBlockRootProps,
  CodeBlockComposedProps,
  CodeBlockSectionProps,
} from "./code-block";
export type {
  CodeBlockProps,
  CodeBlockLineNumbersMode,
  SerializableCodeBlock,
} from "./schema";
components/tool-ui/code-block/README.md
# Code Block

Implementation for the "code-block" Tool UI surface.

## Files

- public exports: components/tool-ui/code-block/index.tsx
- serializable schema + parse helpers: components/tool-ui/code-block/schema.ts

## Companion assets

- Docs page: app/docs/code-block/content.mdx
- Preset payload: lib/presets/code-block.ts

## Quick check

Run this after edits:

pnpm test
components/tool-ui/code-block/schema.ts
import { z } from "zod";
import { defineToolUiContract } from "../shared/contract";
import {
  ToolUIIdSchema,
  ToolUIReceiptSchema,
  ToolUIRoleSchema,
} from "../shared/schema";

export const CodeBlockPropsSchema = z.object({
  id: ToolUIIdSchema,
  role: ToolUIRoleSchema.optional(),
  receipt: ToolUIReceiptSchema.optional(),
  code: z.string(),
  language: z.string().trim().min(1).default("text"),
  lineNumbers: z.enum(["visible", "hidden"]).default("visible"),
  filename: z.string().optional(),
  highlightLines: z.array(z.number().int().positive()).optional(),
  maxCollapsedLines: z.number().min(1).optional(),
  className: z.string().optional(),
});

export type CodeBlockProps = z.infer<typeof CodeBlockPropsSchema>;
export type CodeBlockLineNumbersMode = CodeBlockProps["lineNumbers"];

export const SerializableCodeBlockSchema = CodeBlockPropsSchema.omit({
  className: true,
});

export type SerializableCodeBlock = z.infer<typeof SerializableCodeBlockSchema>;

const SerializableCodeBlockSchemaContract = defineToolUiContract(
  "CodeBlock",
  SerializableCodeBlockSchema,
);

export const parseSerializableCodeBlock: (
  input: unknown,
) => SerializableCodeBlock = SerializableCodeBlockSchemaContract.parse;

export const safeParseSerializableCodeBlock: (
  input: unknown,
) => SerializableCodeBlock | null =
  SerializableCodeBlockSchemaContract.safeParse;
components/tool-ui/shared/contract.ts
import { z } from "zod";
import { parseWithSchema, safeParseWithSchema } from "./parse";

export interface ToolUiContract<T> {
  schema: z.ZodType<T>;
  parse: (input: unknown) => T;
  safeParse: (input: unknown) => T | null;
}

export function defineToolUiContract<T>(
  componentName: string,
  schema: z.ZodType<T>,
): ToolUiContract<T> {
  return {
    schema,
    parse: (input: unknown) => parseWithSchema(schema, input, componentName),
    safeParse: (input: unknown) => safeParseWithSchema(schema, input),
  };
}
components/tool-ui/shared/parse.ts
import { z } from "zod";

function formatZodPath(path: Array<string | number | symbol>): string {
  if (path.length === 0) return "root";
  return path
    .map((segment) =>
      typeof segment === "number" ? `[${segment}]` : String(segment),
    )
    .join(".");
}

/**
 * Format Zod errors into a compact `path: message` string.
 */
export function formatZodError(error: z.ZodError): string {
  const parts = error.issues.map((issue) => {
    const path = formatZodPath(issue.path);
    return `${path}: ${issue.message}`;
  });

  return Array.from(new Set(parts)).join("; ");
}

/**
 * Parse unknown input and throw a readable error.
 */
export function parseWithSchema<T>(
  schema: z.ZodType<T>,
  input: unknown,
  name: string,
): T {
  const res = schema.safeParse(input);
  if (!res.success) {
    throw new Error(`Invalid ${name} payload: ${formatZodError(res.error)}`);
  }
  return res.data;
}

/**
 * Parse unknown input, returning `null` instead of throwing on failure.
 *
 * Use this in assistant-ui `render` functions where `args` stream in
 * incrementally and may be incomplete until the tool call finishes.
 */
export function safeParseWithSchema<T>(
  schema: z.ZodType<T>,
  input: unknown,
): T | null {
  const res = schema.safeParse(input);
  return res.success ? res.data : null;
}
components/tool-ui/shared/pierre-dark-theme.js
//#region src/themes/pierre-dark.json
var name = "pierre-dark";
var type = "dark";
var colors = {
  "editor.background": "#070707",
  "editor.foreground": "#fbfbfb",
  foreground: "#fbfbfb",
  focusBorder: "#009fff",
  "selection.background": "#19283c",
  "editor.selectionBackground": "#009fff4d",
  "editor.lineHighlightBackground": "#19283c8c",
  "editorCursor.foreground": "#009fff",
  "editorLineNumber.foreground": "#84848A",
  "editorLineNumber.activeForeground": "#adadb1",
  "editorIndentGuide.background": "#39393c",
  "editorIndentGuide.activeBackground": "#2e2e30",
  "diffEditor.insertedTextBackground": "#00cab11a",
  "diffEditor.deletedTextBackground": "#ff2e3f1a",
  "sideBar.background": "#141415",
  "sideBar.foreground": "#adadb1",
  "sideBar.border": "#070707",
  "sideBarTitle.foreground": "#fbfbfb",
  "sideBarSectionHeader.background": "#141415",
  "sideBarSectionHeader.foreground": "#adadb1",
  "sideBarSectionHeader.border": "#070707",
  "activityBar.background": "#141415",
  "activityBar.foreground": "#fbfbfb",
  "activityBar.border": "#070707",
  "activityBar.activeBorder": "#009fff",
  "activityBarBadge.background": "#009fff",
  "activityBarBadge.foreground": "#070707",
  "titleBar.activeBackground": "#141415",
  "titleBar.activeForeground": "#fbfbfb",
  "titleBar.inactiveBackground": "#141415",
  "titleBar.inactiveForeground": "#84848A",
  "titleBar.border": "#070707",
  "list.activeSelectionBackground": "#19283c99",
  "list.activeSelectionForeground": "#fbfbfb",
  "list.inactiveSelectionBackground": "#19283c73",
  "list.hoverBackground": "#19283c59",
  "list.focusOutline": "#009fff",
  "tab.activeBackground": "#070707",
  "tab.activeForeground": "#fbfbfb",
  "tab.activeBorderTop": "#009fff",
  "tab.inactiveBackground": "#141415",
  "tab.inactiveForeground": "#84848A",
  "tab.border": "#070707",
  "editorGroupHeader.tabsBackground": "#141415",
  "editorGroupHeader.tabsBorder": "#070707",
  "panel.background": "#141415",
  "panel.border": "#070707",
  "panelTitle.activeBorder": "#009fff",
  "panelTitle.activeForeground": "#fbfbfb",
  "panelTitle.inactiveForeground": "#84848A",
  "statusBar.background": "#141415",
  "statusBar.foreground": "#adadb1",
  "statusBar.border": "#070707",
  "statusBar.noFolderBackground": "#141415",
  "statusBar.debuggingBackground": "#ffca00",
  "statusBar.debuggingForeground": "#070707",
  "statusBarItem.remoteBackground": "#141415",
  "statusBarItem.remoteForeground": "#adadb1",
  "input.background": "#1F1F21",
  "input.border": "#424245",
  "input.foreground": "#fbfbfb",
  "input.placeholderForeground": "#79797F",
  "dropdown.background": "#1F1F21",
  "dropdown.border": "#424245",
  "dropdown.foreground": "#fbfbfb",
  "button.background": "#009fff",
  "button.foreground": "#070707",
  "button.hoverBackground": "#0190e6",
  "textLink.foreground": "#009fff",
  "textLink.activeForeground": "#009fff",
  "gitDecoration.addedResourceForeground": "#00cab1",
  "gitDecoration.conflictingResourceForeground": "#ffca00",
  "gitDecoration.modifiedResourceForeground": "#009fff",
  "gitDecoration.deletedResourceForeground": "#ff2e3f",
  "gitDecoration.untrackedResourceForeground": "#00cab1",
  "gitDecoration.ignoredResourceForeground": "#84848A",
  "terminal.titleForeground": "#adadb1",
  "terminal.titleInactiveForeground": "#84848A",
  "terminal.background": "#141415",
  "terminal.foreground": "#adadb1",
  "terminal.ansiBlack": "#141415",
  "terminal.ansiRed": "#ff2e3f",
  "terminal.ansiGreen": "#0dbe4e",
  "terminal.ansiYellow": "#ffca00",
  "terminal.ansiBlue": "#009fff",
  "terminal.ansiMagenta": "#c635e4",
  "terminal.ansiCyan": "#08c0ef",
  "terminal.ansiWhite": "#c6c6c8",
  "terminal.ansiBrightBlack": "#141415",
  "terminal.ansiBrightRed": "#ff2e3f",
  "terminal.ansiBrightGreen": "#0dbe4e",
  "terminal.ansiBrightYellow": "#ffca00",
  "terminal.ansiBrightBlue": "#009fff",
  "terminal.ansiBrightMagenta": "#c635e4",
  "terminal.ansiBrightCyan": "#08c0ef",
  "terminal.ansiBrightWhite": "#c6c6c8",
};
var tokenColors = [
  {
    scope: ["comment", "punctuation.definition.comment"],
    settings: { foreground: "#84848A" },
  },
  {
    scope: "comment markup.link",
    settings: { foreground: "#84848A" },
  },
  {
    scope: ["string", "constant.other.symbol"],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: [
      "punctuation.definition.string.begin",
      "punctuation.definition.string.end",
    ],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: ["constant.numeric", "constant.language.boolean"],
    settings: { foreground: "#68cdf2" },
  },
  {
    scope: "constant",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "punctuation.definition.constant",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "constant.language",
    settings: { foreground: "#68cdf2" },
  },
  {
    scope: "variable.other.constant",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "keyword",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.control",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: ["storage", "storage.type", "storage.modifier"],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "token.storage",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "keyword.operator.new",
      "keyword.operator.expression.instanceof",
      "keyword.operator.expression.typeof",
      "keyword.operator.expression.void",
      "keyword.operator.expression.delete",
      "keyword.operator.expression.in",
      "keyword.operator.expression.of",
      "keyword.operator.expression.keyof",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.operator.delete",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: ["variable", "identifier", "meta.definition.variable"],
    settings: { foreground: "#ffa359" },
  },
  {
    scope: [
      "variable.other.readwrite",
      "meta.object-literal.key",
      "support.variable.property",
      "support.variable.object.process",
      "support.variable.object.node",
    ],
    settings: { foreground: "#ffa359" },
  },
  {
    scope: "variable.language",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "variable.parameter.function",
    settings: { foreground: "#adadb1" },
  },
  {
    scope: "function.parameter",
    settings: { foreground: "#adadb1" },
  },
  {
    scope: "variable.parameter",
    settings: { foreground: "#adadb1" },
  },
  {
    scope: "variable.parameter.function.language.python",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "variable.parameter.function.python",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: [
      "support.function",
      "entity.name.function",
      "meta.function-call",
      "meta.require",
      "support.function.any-method",
      "variable.function",
    ],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "keyword.other.special-method",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "entity.name.function",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "support.function.console",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: [
      "support.type",
      "entity.name.type",
      "entity.name.class",
      "storage.type",
    ],
    settings: { foreground: "#d568ea" },
  },
  {
    scope: ["support.class", "entity.name.type.class"],
    settings: { foreground: "#d568ea" },
  },
  {
    scope: [
      "entity.name.class",
      "variable.other.class.js",
      "variable.other.class.ts",
    ],
    settings: { foreground: "#d568ea" },
  },
  {
    scope: "entity.name.class.identifier.namespace.type",
    settings: { foreground: "#d568ea" },
  },
  {
    scope: "entity.name.type.namespace",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "entity.other.inherited-class",
    settings: { foreground: "#d568ea" },
  },
  {
    scope: "entity.name.namespace",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "keyword.operator",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "keyword.operator.logical",
      "keyword.operator.bitwise",
      "keyword.operator.channel",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: [
      "keyword.operator.arithmetic",
      "keyword.operator.comparison",
      "keyword.operator.relational",
      "keyword.operator.increment",
      "keyword.operator.decrement",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.assignment",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.assignment.compound",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "keyword.operator.assignment.compound.js",
      "keyword.operator.assignment.compound.ts",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.ternary",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.operator.optional",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "punctuation",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.separator.delimiter",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.separator.key-value",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.terminator",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace.square",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace.round",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "function.brace",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "punctuation.definition.parameters",
      "punctuation.definition.typeparameters",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["punctuation.definition.block", "punctuation.definition.tag"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["meta.tag.tsx", "meta.tag.jsx", "meta.tag.js", "meta.tag.ts"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "keyword.operator.expression.import",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "keyword.operator.module",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "support.type.object.console",
    settings: { foreground: "#ffa359" },
  },
  {
    scope: [
      "support.module.node",
      "support.type.object.module",
      "entity.name.type.module",
    ],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "support.constant.math",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "support.constant.property.math",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "support.constant.json",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "support.type.object.dom",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["support.variable.dom", "support.variable.property.dom"],
    settings: { foreground: "#ffa359" },
  },
  {
    scope: "support.variable.property.process",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "meta.property.object",
    settings: { foreground: "#ffa359" },
  },
  {
    scope: "variable.parameter.function.js",
    settings: { foreground: "#ffa359" },
  },
  {
    scope: ["keyword.other.template.begin", "keyword.other.template.end"],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: [
      "keyword.other.substitution.begin",
      "keyword.other.substitution.end",
    ],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: [
      "punctuation.definition.template-expression.begin",
      "punctuation.definition.template-expression.end",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "meta.template.expression",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.section.embedded",
    settings: { foreground: "#ffa359" },
  },
  {
    scope: "variable.interpolation",
    settings: { foreground: "#ffa359" },
  },
  {
    scope: [
      "punctuation.section.embedded.begin",
      "punctuation.section.embedded.end",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "punctuation.quasi.element",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "support.type.primitive.ts",
      "support.type.builtin.ts",
      "support.type.primitive.tsx",
      "support.type.builtin.tsx",
    ],
    settings: { foreground: "#d568ea" },
  },
  {
    scope: "support.type.type.flowtype",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "support.type.primitive",
    settings: { foreground: "#d568ea" },
  },
  {
    scope: "support.variable.magic.python",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "variable.parameter.function.language.special.self.python",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "punctuation.separator.period.python",
      "punctuation.separator.element.python",
      "punctuation.parenthesis.begin.python",
      "punctuation.parenthesis.end.python",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "punctuation.definition.arguments.begin.python",
      "punctuation.definition.arguments.end.python",
      "punctuation.separator.arguments.python",
      "punctuation.definition.list.begin.python",
      "punctuation.definition.list.end.python",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.type.python",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.logical.python",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "meta.function-call.generic.python",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "constant.character.format.placeholder.other.python",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "meta.function.decorator.python",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: [
      "support.token.decorator.python",
      "meta.function.decorator.identifier.python",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "storage.modifier.lifetime.rust",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.function.std.rust",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "entity.name.lifetime.rust",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "variable.language.rust",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "keyword.operator.misc.rust",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "keyword.operator.sigil.rust",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "support.constant.core.rust",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: ["meta.function.c", "meta.function.cpp"],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: [
      "punctuation.section.block.begin.bracket.curly.cpp",
      "punctuation.section.block.end.bracket.curly.cpp",
      "punctuation.terminator.statement.c",
      "punctuation.section.block.begin.bracket.curly.c",
      "punctuation.section.block.end.bracket.curly.c",
      "punctuation.section.parens.begin.bracket.round.c",
      "punctuation.section.parens.end.bracket.round.c",
      "punctuation.section.parameters.begin.bracket.round.c",
      "punctuation.section.parameters.end.bracket.round.c",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "keyword.operator.assignment.c",
      "keyword.operator.comparison.c",
      "keyword.operator.c",
      "keyword.operator.increment.c",
      "keyword.operator.decrement.c",
      "keyword.operator.bitwise.shift.c",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "keyword.operator.assignment.cpp",
      "keyword.operator.comparison.cpp",
      "keyword.operator.cpp",
      "keyword.operator.increment.cpp",
      "keyword.operator.decrement.cpp",
      "keyword.operator.bitwise.shift.cpp",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: ["punctuation.separator.c", "punctuation.separator.cpp"],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: ["support.type.posix-reserved.c", "support.type.posix-reserved.cpp"],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["keyword.operator.sizeof.c", "keyword.operator.sizeof.cpp"],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "variable.c",
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["storage.type.annotation.java", "storage.type.object.array.java"],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "source.java",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: [
      "punctuation.section.block.begin.java",
      "punctuation.section.block.end.java",
      "punctuation.definition.method-parameters.begin.java",
      "punctuation.definition.method-parameters.end.java",
      "meta.method.identifier.java",
      "punctuation.section.method.begin.java",
      "punctuation.section.method.end.java",
      "punctuation.terminator.java",
      "punctuation.section.class.begin.java",
      "punctuation.section.class.end.java",
      "punctuation.section.inner-class.begin.java",
      "punctuation.section.inner-class.end.java",
      "meta.method-call.java",
      "punctuation.section.class.begin.bracket.curly.java",
      "punctuation.section.class.end.bracket.curly.java",
      "punctuation.section.method.begin.bracket.curly.java",
      "punctuation.section.method.end.bracket.curly.java",
      "punctuation.separator.period.java",
      "punctuation.bracket.angle.java",
      "punctuation.definition.annotation.java",
      "meta.method.body.java",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.method.java",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: [
      "storage.modifier.import.java",
      "storage.type.java",
      "storage.type.generic.java",
    ],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "keyword.operator.instanceof.java",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "meta.definition.variable.name.java",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "token.variable.parameter.java",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "import.storage.java",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "token.package.keyword",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "token.package",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "token.storage.type.java",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "keyword.operator.assignment.go",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: ["keyword.operator.arithmetic.go", "keyword.operator.address.go"],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "entity.name.package.go",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "support.other.namespace.use.php",
      "support.other.namespace.use-as.php",
      "support.other.namespace.php",
      "entity.other.alias.php",
      "meta.interface.php",
    ],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "keyword.operator.error-control.php",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.operator.type.php",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "punctuation.section.array.begin.php",
      "punctuation.section.array.end.php",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "storage.type.php",
      "meta.other.type.phpdoc.php",
      "keyword.other.type.php",
      "keyword.other.array.phpdoc.php",
    ],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "meta.function-call.php",
      "meta.function-call.object.php",
      "meta.function-call.static.php",
    ],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: [
      "punctuation.definition.parameters.begin.bracket.round.php",
      "punctuation.definition.parameters.end.bracket.round.php",
      "punctuation.separator.delimiter.php",
      "punctuation.section.scope.begin.php",
      "punctuation.section.scope.end.php",
      "punctuation.terminator.expression.php",
      "punctuation.definition.arguments.begin.bracket.round.php",
      "punctuation.definition.arguments.end.bracket.round.php",
      "punctuation.definition.storage-type.begin.bracket.round.php",
      "punctuation.definition.storage-type.end.bracket.round.php",
      "punctuation.definition.array.begin.bracket.round.php",
      "punctuation.definition.array.end.bracket.round.php",
      "punctuation.definition.begin.bracket.round.php",
      "punctuation.definition.end.bracket.round.php",
      "punctuation.definition.begin.bracket.curly.php",
      "punctuation.definition.end.bracket.curly.php",
      "punctuation.definition.section.switch-block.end.bracket.curly.php",
      "punctuation.definition.section.switch-block.start.bracket.curly.php",
      "punctuation.definition.section.switch-block.begin.bracket.curly.php",
      "punctuation.definition.section.switch-block.end.bracket.curly.php",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "support.constant.ext.php",
      "support.constant.std.php",
      "support.constant.core.php",
      "support.constant.parser-token.php",
    ],
    settings: { foreground: "#ffd452" },
  },
  {
    scope: ["entity.name.goto-label.php", "support.other.php"],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: [
      "keyword.operator.logical.php",
      "keyword.operator.bitwise.php",
      "keyword.operator.arithmetic.php",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.regexp.php",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.operator.comparison.php",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["keyword.operator.heredoc.php", "keyword.operator.nowdoc.php"],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "variable.other.class.php",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "invalid.illegal.non-null-typehinted.php",
    settings: { foreground: "#f44747" },
  },
  {
    scope: "variable.other.generic-type.haskell",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "storage.type.haskell",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "storage.type.cs",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "entity.name.variable.local.cs",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "entity.name.label.cs",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "entity.name.scope-resolution.function.call",
      "entity.name.scope-resolution.function.definition",
    ],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "punctuation.definition.delayed.unison",
      "punctuation.definition.list.begin.unison",
      "punctuation.definition.list.end.unison",
      "punctuation.definition.ability.begin.unison",
      "punctuation.definition.ability.end.unison",
      "punctuation.operator.assignment.as.unison",
      "punctuation.separator.pipe.unison",
      "punctuation.separator.delimiter.unison",
      "punctuation.definition.hash.unison",
    ],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "support.constant.edge",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "support.type.prelude.elm",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.constant.elm",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "entity.global.clojure",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "meta.symbol.clojure",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "constant.keyword.clojure",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["meta.arguments.coffee", "variable.parameter.function.coffee"],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "storage.modifier.import.groovy",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "meta.method.groovy",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "meta.definition.variable.name.groovy",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "meta.definition.class.inherited.classes.groovy",
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: "support.variable.semantic.hlsl",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "support.type.texture.hlsl",
      "support.type.sampler.hlsl",
      "support.type.object.hlsl",
      "support.type.object.rw.hlsl",
      "support.type.fx.hlsl",
      "support.type.object.hlsl",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: ["text.variable", "text.bracketed"],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: ["support.type.swift", "support.type.vb.asp"],
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "meta.scope.prerequisites.makefile",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "source.makefile",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "source.ini",
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: "constant.language.symbol.ruby",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["function.parameter.ruby", "function.parameter.cs"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "constant.language.symbol.elixir",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope:
      "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade",
    settings: { foreground: "#ff678d" },
  },
  {
    scope:
      "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "entity.name.function.xi",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "entity.name.class.xi",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "constant.character.character-class.regexp.xi",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "constant.regexp.xi",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "keyword.control.xi",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "invalid.xi",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "beginning.punctuation.definition.quote.markdown.xi",
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: "beginning.punctuation.definition.list.markdown.xi",
    settings: { foreground: "#84848A" },
  },
  {
    scope: "constant.character.xi",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "accent.xi",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "wikiword.xi",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "constant.other.color.rgb-value.xi",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "punctuation.definition.tag.xi",
    settings: { foreground: "#84848A" },
  },
  {
    scope: [
      "support.constant.property-value.scss",
      "support.constant.property-value.css",
    ],
    settings: { foreground: "#ffd452" },
  },
  {
    scope: [
      "keyword.operator.css",
      "keyword.operator.scss",
      "keyword.operator.less",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: [
      "support.constant.color.w3c-standard-color-name.css",
      "support.constant.color.w3c-standard-color-name.scss",
    ],
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "punctuation.separator.list.comma.css",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.type.vendored.property-name.css",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name.css",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.constant.property-value",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.constant.font-name",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "entity.other.attribute-name.class.css",
    settings: {
      foreground: "#61d5c0",
      fontStyle: "normal",
    },
  },
  {
    scope: "entity.other.attribute-name.id",
    settings: {
      foreground: "#9d6afb",
      fontStyle: "normal",
    },
  },
  {
    scope: [
      "entity.other.attribute-name.pseudo-element",
      "entity.other.attribute-name.pseudo-class",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "meta.selector",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "selector.sass",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "rgb-value",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "inline-color-decoration rgb-value",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "less rgb-value",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "control.elements",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "keyword.operator.less",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "entity.name.tag",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "entity.other.attribute-name",
    settings: {
      foreground: "#61d5c0",
      fontStyle: "normal",
    },
  },
  {
    scope: "constant.character.entity",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "meta.tag",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "invalid.illegal.bad-ampersand.html",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "markup.heading",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: [
      "markup.heading punctuation.definition.heading",
      "entity.name.section",
    ],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "entity.name.section.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "punctuation.definition.heading.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "markup.heading.setext",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "markup.heading.setext.1.markdown",
      "markup.heading.setext.2.markdown",
    ],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: ["markup.bold", "todo.bold"],
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "punctuation.definition.bold",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: "punctuation.definition.bold.markdown",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: ["markup.italic", "punctuation.definition.italic", "todo.emphasis"],
    settings: {
      foreground: "#ff678d",
      fontStyle: "italic",
    },
  },
  {
    scope: "emphasis md",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "markup.italic.markdown",
    settings: { fontStyle: "italic" },
  },
  {
    scope: [
      "markup.underline.link.markdown",
      "markup.underline.link.image.markdown",
    ],
    settings: { foreground: "#ff678d" },
  },
  {
    scope: [
      "string.other.link.title.markdown",
      "string.other.link.description.markdown",
    ],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "punctuation.definition.metadata.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: ["markup.inline.raw.markdown", "markup.inline.raw.string.markdown"],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: "punctuation.definition.list.begin.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "punctuation.definition.list.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "beginning.punctuation.definition.list.markdown",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: [
      "punctuation.definition.string.begin.markdown",
      "punctuation.definition.string.end.markdown",
    ],
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "markup.quote.markdown",
    settings: { foreground: "#84848A" },
  },
  {
    scope: "keyword.other.unit",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "markup.changed.diff",
    settings: { foreground: "#ffca00" },
  },
  {
    scope: [
      "meta.diff.header.from-file",
      "meta.diff.header.to-file",
      "punctuation.definition.from-file.diff",
      "punctuation.definition.to-file.diff",
    ],
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "markup.inserted.diff",
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: "markup.deleted.diff",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "string.regexp",
    settings: { foreground: "#64d1db" },
  },
  {
    scope: "constant.other.character-class.regexp",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "keyword.operator.quantifier.regexp",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "constant.character.escape",
    settings: { foreground: "#68cdf2" },
  },
  {
    scope: "source.json meta.structure.dictionary.json > string.quoted.json",
    settings: { foreground: "#ff6762" },
  },
  {
    scope:
      "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: [
      "source.json meta.structure.dictionary.json > value.json > string.quoted.json",
      "source.json meta.structure.array.json > value.json > string.quoted.json",
      "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation",
      "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation",
    ],
    settings: { foreground: "#5ecc71" },
  },
  {
    scope: [
      "source.json meta.structure.dictionary.json > constant.language.json",
      "source.json meta.structure.array.json > constant.language.json",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name.json",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "support.type.property-name.json punctuation",
    settings: { foreground: "#ff6762" },
  },
  {
    scope: "punctuation.definition.block.sequence.item.yaml",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "block.scope.end",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "block.scope.begin",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "token.info-token",
    settings: { foreground: "#9d6afb" },
  },
  {
    scope: "token.warn-token",
    settings: { foreground: "#ffd452" },
  },
  {
    scope: "token.error-token",
    settings: { foreground: "#f44747" },
  },
  {
    scope: "token.debug-token",
    settings: { foreground: "#ff678d" },
  },
  {
    scope: "invalid.illegal",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.broken",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.deprecated",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.unimplemented",
    settings: { foreground: "#ffffff" },
  },
];
var semanticTokenColors = {
  comment: "#84848A",
  string: "#5ecc71",
  number: "#68cdf2",
  regexp: "#64d1db",
  keyword: "#ff678d",
  variable: "#ffa359",
  parameter: "#adadb1",
  property: "#ffa359",
  function: "#9d6afb",
  method: "#9d6afb",
  type: "#d568ea",
  class: "#d568ea",
  namespace: "#ffca00",
  enumMember: "#08c0ef",
  "variable.constant": "#ffd452",
  "variable.defaultLibrary": "#ffca00",
};
var pierre_dark_default = {
  name,
  type,
  colors,
  tokenColors,
  semanticTokenColors,
};

//#endregion
export {
  colors,
  pierre_dark_default as default,
  name,
  semanticTokenColors,
  tokenColors,
  type,
};
components/tool-ui/shared/pierre-light-theme.js
//#region src/themes/pierre-light.json
var name = "pierre-light";
var type = "light";
var colors = {
  "editor.background": "#ffffff",
  "editor.foreground": "#070707",
  foreground: "#070707",
  focusBorder: "#009fff",
  "selection.background": "#dfebff",
  "editor.selectionBackground": "#009fff2e",
  "editor.lineHighlightBackground": "#dfebff8c",
  "editorCursor.foreground": "#009fff",
  "editorLineNumber.foreground": "#84848A",
  "editorLineNumber.activeForeground": "#6C6C71",
  "editorIndentGuide.background": "#eeeeef",
  "editorIndentGuide.activeBackground": "#dbdbdd",
  "diffEditor.insertedTextBackground": "#00cab133",
  "diffEditor.deletedTextBackground": "#ff2e3f33",
  "sideBar.background": "#f8f8f8",
  "sideBar.foreground": "#6C6C71",
  "sideBar.border": "#eeeeef",
  "sideBarTitle.foreground": "#070707",
  "sideBarSectionHeader.background": "#f8f8f8",
  "sideBarSectionHeader.foreground": "#6C6C71",
  "sideBarSectionHeader.border": "#eeeeef",
  "activityBar.background": "#f8f8f8",
  "activityBar.foreground": "#070707",
  "activityBar.border": "#eeeeef",
  "activityBar.activeBorder": "#009fff",
  "activityBarBadge.background": "#009fff",
  "activityBarBadge.foreground": "#ffffff",
  "titleBar.activeBackground": "#f8f8f8",
  "titleBar.activeForeground": "#070707",
  "titleBar.inactiveBackground": "#f8f8f8",
  "titleBar.inactiveForeground": "#84848A",
  "titleBar.border": "#eeeeef",
  "list.activeSelectionBackground": "#dfebffcc",
  "list.activeSelectionForeground": "#070707",
  "list.inactiveSelectionBackground": "#dfebff73",
  "list.hoverBackground": "#dfebff59",
  "list.focusOutline": "#009fff",
  "tab.activeBackground": "#ffffff",
  "tab.activeForeground": "#070707",
  "tab.activeBorderTop": "#009fff",
  "tab.inactiveBackground": "#f8f8f8",
  "tab.inactiveForeground": "#84848A",
  "tab.border": "#eeeeef",
  "editorGroupHeader.tabsBackground": "#f8f8f8",
  "editorGroupHeader.tabsBorder": "#eeeeef",
  "panel.background": "#f8f8f8",
  "panel.border": "#eeeeef",
  "panelTitle.activeBorder": "#009fff",
  "panelTitle.activeForeground": "#070707",
  "panelTitle.inactiveForeground": "#84848A",
  "statusBar.background": "#f8f8f8",
  "statusBar.foreground": "#6C6C71",
  "statusBar.border": "#eeeeef",
  "statusBar.noFolderBackground": "#f8f8f8",
  "statusBar.debuggingBackground": "#ffca00",
  "statusBar.debuggingForeground": "#ffffff",
  "statusBarItem.remoteBackground": "#f8f8f8",
  "statusBarItem.remoteForeground": "#6C6C71",
  "input.background": "#f2f2f3",
  "input.border": "#dbdbdd",
  "input.foreground": "#070707",
  "input.placeholderForeground": "#8E8E95",
  "dropdown.background": "#f2f2f3",
  "dropdown.border": "#dbdbdd",
  "dropdown.foreground": "#070707",
  "button.background": "#009fff",
  "button.foreground": "#ffffff",
  "button.hoverBackground": "#1aa9ff",
  "textLink.foreground": "#009fff",
  "textLink.activeForeground": "#009fff",
  "gitDecoration.addedResourceForeground": "#00cab1",
  "gitDecoration.conflictingResourceForeground": "#ffca00",
  "gitDecoration.modifiedResourceForeground": "#009fff",
  "gitDecoration.deletedResourceForeground": "#ff2e3f",
  "gitDecoration.untrackedResourceForeground": "#00cab1",
  "gitDecoration.ignoredResourceForeground": "#84848A",
  "terminal.titleForeground": "#6C6C71",
  "terminal.titleInactiveForeground": "#84848A",
  "terminal.background": "#f8f8f8",
  "terminal.foreground": "#6C6C71",
  "terminal.ansiBlack": "#1F1F21",
  "terminal.ansiRed": "#ff2e3f",
  "terminal.ansiGreen": "#0dbe4e",
  "terminal.ansiYellow": "#ffca00",
  "terminal.ansiBlue": "#009fff",
  "terminal.ansiMagenta": "#c635e4",
  "terminal.ansiCyan": "#08c0ef",
  "terminal.ansiWhite": "#c6c6c8",
  "terminal.ansiBrightBlack": "#1F1F21",
  "terminal.ansiBrightRed": "#ff2e3f",
  "terminal.ansiBrightGreen": "#0dbe4e",
  "terminal.ansiBrightYellow": "#ffca00",
  "terminal.ansiBrightBlue": "#009fff",
  "terminal.ansiBrightMagenta": "#c635e4",
  "terminal.ansiBrightCyan": "#08c0ef",
  "terminal.ansiBrightWhite": "#c6c6c8",
};
var tokenColors = [
  {
    scope: ["comment", "punctuation.definition.comment"],
    settings: { foreground: "#84848A" },
  },
  {
    scope: "comment markup.link",
    settings: { foreground: "#84848A" },
  },
  {
    scope: ["string", "constant.other.symbol"],
    settings: { foreground: "#199f43" },
  },
  {
    scope: [
      "punctuation.definition.string.begin",
      "punctuation.definition.string.end",
    ],
    settings: { foreground: "#199f43" },
  },
  {
    scope: ["constant.numeric", "constant.language.boolean"],
    settings: { foreground: "#1ca1c7" },
  },
  {
    scope: "constant",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "punctuation.definition.constant",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "constant.language",
    settings: { foreground: "#1ca1c7" },
  },
  {
    scope: "variable.other.constant",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.control",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: ["storage", "storage.type", "storage.modifier"],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "token.storage",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "keyword.operator.new",
      "keyword.operator.expression.instanceof",
      "keyword.operator.expression.typeof",
      "keyword.operator.expression.void",
      "keyword.operator.expression.delete",
      "keyword.operator.expression.in",
      "keyword.operator.expression.of",
      "keyword.operator.expression.keyof",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.operator.delete",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: ["variable", "identifier", "meta.definition.variable"],
    settings: { foreground: "#d47628" },
  },
  {
    scope: [
      "variable.other.readwrite",
      "meta.object-literal.key",
      "support.variable.property",
      "support.variable.object.process",
      "support.variable.object.node",
    ],
    settings: { foreground: "#d47628" },
  },
  {
    scope: "variable.language",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "variable.parameter.function",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "function.parameter",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "variable.parameter",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "variable.parameter.function.language.python",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "variable.parameter.function.python",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "support.function",
      "entity.name.function",
      "meta.function-call",
      "meta.require",
      "support.function.any-method",
      "variable.function",
    ],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "keyword.other.special-method",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "entity.name.function",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "support.function.console",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: [
      "support.type",
      "entity.name.type",
      "entity.name.class",
      "storage.type",
    ],
    settings: { foreground: "#c635e4" },
  },
  {
    scope: ["support.class", "entity.name.type.class"],
    settings: { foreground: "#c635e4" },
  },
  {
    scope: [
      "entity.name.class",
      "variable.other.class.js",
      "variable.other.class.ts",
    ],
    settings: { foreground: "#c635e4" },
  },
  {
    scope: "entity.name.class.identifier.namespace.type",
    settings: { foreground: "#c635e4" },
  },
  {
    scope: "entity.name.type.namespace",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.other.inherited-class",
    settings: { foreground: "#c635e4" },
  },
  {
    scope: "entity.name.namespace",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword.operator",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "keyword.operator.logical",
      "keyword.operator.bitwise",
      "keyword.operator.channel",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: [
      "keyword.operator.arithmetic",
      "keyword.operator.comparison",
      "keyword.operator.relational",
      "keyword.operator.increment",
      "keyword.operator.decrement",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.assignment",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.assignment.compound",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "keyword.operator.assignment.compound.js",
      "keyword.operator.assignment.compound.ts",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.ternary",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.operator.optional",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "punctuation",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.separator.delimiter",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.separator.key-value",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.terminator",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace.square",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.brace.round",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "function.brace",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "punctuation.definition.parameters",
      "punctuation.definition.typeparameters",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["punctuation.definition.block", "punctuation.definition.tag"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["meta.tag.tsx", "meta.tag.jsx", "meta.tag.js", "meta.tag.ts"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "keyword.operator.expression.import",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "keyword.operator.module",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "support.type.object.console",
    settings: { foreground: "#d47628" },
  },
  {
    scope: [
      "support.module.node",
      "support.type.object.module",
      "entity.name.type.module",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "support.constant.math",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "support.constant.property.math",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "support.constant.json",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "support.type.object.dom",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["support.variable.dom", "support.variable.property.dom"],
    settings: { foreground: "#d47628" },
  },
  {
    scope: "support.variable.property.process",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "meta.property.object",
    settings: { foreground: "#d47628" },
  },
  {
    scope: "variable.parameter.function.js",
    settings: { foreground: "#d47628" },
  },
  {
    scope: ["keyword.other.template.begin", "keyword.other.template.end"],
    settings: { foreground: "#199f43" },
  },
  {
    scope: [
      "keyword.other.substitution.begin",
      "keyword.other.substitution.end",
    ],
    settings: { foreground: "#199f43" },
  },
  {
    scope: [
      "punctuation.definition.template-expression.begin",
      "punctuation.definition.template-expression.end",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "meta.template.expression",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "punctuation.section.embedded",
    settings: { foreground: "#d47628" },
  },
  {
    scope: "variable.interpolation",
    settings: { foreground: "#d47628" },
  },
  {
    scope: [
      "punctuation.section.embedded.begin",
      "punctuation.section.embedded.end",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "punctuation.quasi.element",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "support.type.primitive.ts",
      "support.type.builtin.ts",
      "support.type.primitive.tsx",
      "support.type.builtin.tsx",
    ],
    settings: { foreground: "#c635e4" },
  },
  {
    scope: "support.type.type.flowtype",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "support.type.primitive",
    settings: { foreground: "#c635e4" },
  },
  {
    scope: "support.variable.magic.python",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "variable.parameter.function.language.special.self.python",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "punctuation.separator.period.python",
      "punctuation.separator.element.python",
      "punctuation.parenthesis.begin.python",
      "punctuation.parenthesis.end.python",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "punctuation.definition.arguments.begin.python",
      "punctuation.definition.arguments.end.python",
      "punctuation.separator.arguments.python",
      "punctuation.definition.list.begin.python",
      "punctuation.definition.list.end.python",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.type.python",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.logical.python",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "meta.function-call.generic.python",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "constant.character.format.placeholder.other.python",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "meta.function.decorator.python",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: [
      "support.token.decorator.python",
      "meta.function.decorator.identifier.python",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "storage.modifier.lifetime.rust",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.function.std.rust",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "entity.name.lifetime.rust",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "variable.language.rust",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "keyword.operator.misc.rust",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "keyword.operator.sigil.rust",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "support.constant.core.rust",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: ["meta.function.c", "meta.function.cpp"],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: [
      "punctuation.section.block.begin.bracket.curly.cpp",
      "punctuation.section.block.end.bracket.curly.cpp",
      "punctuation.terminator.statement.c",
      "punctuation.section.block.begin.bracket.curly.c",
      "punctuation.section.block.end.bracket.curly.c",
      "punctuation.section.parens.begin.bracket.round.c",
      "punctuation.section.parens.end.bracket.round.c",
      "punctuation.section.parameters.begin.bracket.round.c",
      "punctuation.section.parameters.end.bracket.round.c",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "keyword.operator.assignment.c",
      "keyword.operator.comparison.c",
      "keyword.operator.c",
      "keyword.operator.increment.c",
      "keyword.operator.decrement.c",
      "keyword.operator.bitwise.shift.c",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "keyword.operator.assignment.cpp",
      "keyword.operator.comparison.cpp",
      "keyword.operator.cpp",
      "keyword.operator.increment.cpp",
      "keyword.operator.decrement.cpp",
      "keyword.operator.bitwise.shift.cpp",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: ["punctuation.separator.c", "punctuation.separator.cpp"],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: ["support.type.posix-reserved.c", "support.type.posix-reserved.cpp"],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["keyword.operator.sizeof.c", "keyword.operator.sizeof.cpp"],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "variable.c",
    settings: { foreground: "#79797F" },
  },
  {
    scope: ["storage.type.annotation.java", "storage.type.object.array.java"],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "source.java",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: [
      "punctuation.section.block.begin.java",
      "punctuation.section.block.end.java",
      "punctuation.definition.method-parameters.begin.java",
      "punctuation.definition.method-parameters.end.java",
      "meta.method.identifier.java",
      "punctuation.section.method.begin.java",
      "punctuation.section.method.end.java",
      "punctuation.terminator.java",
      "punctuation.section.class.begin.java",
      "punctuation.section.class.end.java",
      "punctuation.section.inner-class.begin.java",
      "punctuation.section.inner-class.end.java",
      "meta.method-call.java",
      "punctuation.section.class.begin.bracket.curly.java",
      "punctuation.section.class.end.bracket.curly.java",
      "punctuation.section.method.begin.bracket.curly.java",
      "punctuation.section.method.end.bracket.curly.java",
      "punctuation.separator.period.java",
      "punctuation.bracket.angle.java",
      "punctuation.definition.annotation.java",
      "meta.method.body.java",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "meta.method.java",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: [
      "storage.modifier.import.java",
      "storage.type.java",
      "storage.type.generic.java",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword.operator.instanceof.java",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "meta.definition.variable.name.java",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "token.variable.parameter.java",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "import.storage.java",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "token.package.keyword",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "token.package",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "token.storage.type.java",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword.operator.assignment.go",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: ["keyword.operator.arithmetic.go", "keyword.operator.address.go"],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "entity.name.package.go",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "support.other.namespace.use.php",
      "support.other.namespace.use-as.php",
      "support.other.namespace.php",
      "entity.other.alias.php",
      "meta.interface.php",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword.operator.error-control.php",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.operator.type.php",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "punctuation.section.array.begin.php",
      "punctuation.section.array.end.php",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "storage.type.php",
      "meta.other.type.phpdoc.php",
      "keyword.other.type.php",
      "keyword.other.array.phpdoc.php",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "meta.function-call.php",
      "meta.function-call.object.php",
      "meta.function-call.static.php",
    ],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: [
      "punctuation.definition.parameters.begin.bracket.round.php",
      "punctuation.definition.parameters.end.bracket.round.php",
      "punctuation.separator.delimiter.php",
      "punctuation.section.scope.begin.php",
      "punctuation.section.scope.end.php",
      "punctuation.terminator.expression.php",
      "punctuation.definition.arguments.begin.bracket.round.php",
      "punctuation.definition.arguments.end.bracket.round.php",
      "punctuation.definition.storage-type.begin.bracket.round.php",
      "punctuation.definition.storage-type.end.bracket.round.php",
      "punctuation.definition.array.begin.bracket.round.php",
      "punctuation.definition.array.end.bracket.round.php",
      "punctuation.definition.begin.bracket.round.php",
      "punctuation.definition.end.bracket.round.php",
      "punctuation.definition.begin.bracket.curly.php",
      "punctuation.definition.end.bracket.curly.php",
      "punctuation.definition.section.switch-block.end.bracket.curly.php",
      "punctuation.definition.section.switch-block.start.bracket.curly.php",
      "punctuation.definition.section.switch-block.begin.bracket.curly.php",
      "punctuation.definition.section.switch-block.end.bracket.curly.php",
    ],
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "support.constant.ext.php",
      "support.constant.std.php",
      "support.constant.core.php",
      "support.constant.parser-token.php",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: ["entity.name.goto-label.php", "support.other.php"],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: [
      "keyword.operator.logical.php",
      "keyword.operator.bitwise.php",
      "keyword.operator.arithmetic.php",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "keyword.operator.regexp.php",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.operator.comparison.php",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["keyword.operator.heredoc.php", "keyword.operator.nowdoc.php"],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "variable.other.class.php",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "invalid.illegal.non-null-typehinted.php",
    settings: { foreground: "#f44747" },
  },
  {
    scope: "variable.other.generic-type.haskell",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "storage.type.haskell",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "storage.type.cs",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.name.variable.local.cs",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "entity.name.label.cs",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "entity.name.scope-resolution.function.call",
      "entity.name.scope-resolution.function.definition",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "punctuation.definition.delayed.unison",
      "punctuation.definition.list.begin.unison",
      "punctuation.definition.list.end.unison",
      "punctuation.definition.ability.begin.unison",
      "punctuation.definition.ability.end.unison",
      "punctuation.operator.assignment.as.unison",
      "punctuation.separator.pipe.unison",
      "punctuation.separator.delimiter.unison",
      "punctuation.definition.hash.unison",
    ],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "support.constant.edge",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "support.type.prelude.elm",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.constant.elm",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.global.clojure",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "meta.symbol.clojure",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "constant.keyword.clojure",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["meta.arguments.coffee", "variable.parameter.function.coffee"],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "storage.modifier.import.groovy",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "meta.method.groovy",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "meta.definition.variable.name.groovy",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "meta.definition.class.inherited.classes.groovy",
    settings: { foreground: "#199f43" },
  },
  {
    scope: "support.variable.semantic.hlsl",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "support.type.texture.hlsl",
      "support.type.sampler.hlsl",
      "support.type.object.hlsl",
      "support.type.object.rw.hlsl",
      "support.type.fx.hlsl",
      "support.type.object.hlsl",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: ["text.variable", "text.bracketed"],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: ["support.type.swift", "support.type.vb.asp"],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "meta.scope.prerequisites.makefile",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "source.makefile",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "source.ini",
    settings: { foreground: "#199f43" },
  },
  {
    scope: "constant.language.symbol.ruby",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: ["function.parameter.ruby", "function.parameter.cs"],
    settings: { foreground: "#79797F" },
  },
  {
    scope: "constant.language.symbol.elixir",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope:
      "text.html.laravel-blade source.php.embedded.line.html entity.name.tag.laravel-blade",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope:
      "text.html.laravel-blade source.php.embedded.line.html support.constant.laravel-blade",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "entity.name.function.xi",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.name.class.xi",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "constant.character.character-class.regexp.xi",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "constant.regexp.xi",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "keyword.control.xi",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "invalid.xi",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "beginning.punctuation.definition.quote.markdown.xi",
    settings: { foreground: "#199f43" },
  },
  {
    scope: "beginning.punctuation.definition.list.markdown.xi",
    settings: { foreground: "#84848A" },
  },
  {
    scope: "constant.character.xi",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "accent.xi",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "wikiword.xi",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "constant.other.color.rgb-value.xi",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "punctuation.definition.tag.xi",
    settings: { foreground: "#84848A" },
  },
  {
    scope: [
      "support.constant.property-value.scss",
      "support.constant.property-value.css",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "keyword.operator.css",
      "keyword.operator.scss",
      "keyword.operator.less",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: [
      "support.constant.color.w3c-standard-color-name.css",
      "support.constant.color.w3c-standard-color-name.scss",
    ],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "punctuation.separator.list.comma.css",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.type.vendored.property-name.css",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name.css",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.constant.property-value",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "support.constant.font-name",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.other.attribute-name.class.css",
    settings: {
      foreground: "#16a994",
      fontStyle: "normal",
    },
  },
  {
    scope: "entity.other.attribute-name.id",
    settings: {
      foreground: "#7b43f8",
      fontStyle: "normal",
    },
  },
  {
    scope: [
      "entity.other.attribute-name.pseudo-element",
      "entity.other.attribute-name.pseudo-class",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "meta.selector",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "selector.sass",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "rgb-value",
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "inline-color-decoration rgb-value",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "less rgb-value",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "control.elements",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "keyword.operator.less",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "entity.name.tag",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "entity.other.attribute-name",
    settings: {
      foreground: "#16a994",
      fontStyle: "normal",
    },
  },
  {
    scope: "constant.character.entity",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "meta.tag",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "invalid.illegal.bad-ampersand.html",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "markup.heading",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: [
      "markup.heading punctuation.definition.heading",
      "entity.name.section",
    ],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "entity.name.section.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "punctuation.definition.heading.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "markup.heading.setext",
    settings: { foreground: "#79797F" },
  },
  {
    scope: [
      "markup.heading.setext.1.markdown",
      "markup.heading.setext.2.markdown",
    ],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: ["markup.bold", "todo.bold"],
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "punctuation.definition.bold",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "punctuation.definition.bold.markdown",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: ["markup.italic", "punctuation.definition.italic", "todo.emphasis"],
    settings: {
      foreground: "#fc2b73",
      fontStyle: "italic",
    },
  },
  {
    scope: "emphasis md",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "markup.italic.markdown",
    settings: { fontStyle: "italic" },
  },
  {
    scope: [
      "markup.underline.link.markdown",
      "markup.underline.link.image.markdown",
    ],
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: [
      "string.other.link.title.markdown",
      "string.other.link.description.markdown",
    ],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "punctuation.definition.metadata.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: ["markup.inline.raw.markdown", "markup.inline.raw.string.markdown"],
    settings: { foreground: "#199f43" },
  },
  {
    scope: "punctuation.definition.list.begin.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "punctuation.definition.list.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "beginning.punctuation.definition.list.markdown",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: [
      "punctuation.definition.string.begin.markdown",
      "punctuation.definition.string.end.markdown",
    ],
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "markup.quote.markdown",
    settings: { foreground: "#84848A" },
  },
  {
    scope: "keyword.other.unit",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "markup.changed.diff",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: [
      "meta.diff.header.from-file",
      "meta.diff.header.to-file",
      "punctuation.definition.from-file.diff",
      "punctuation.definition.to-file.diff",
    ],
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "markup.inserted.diff",
    settings: { foreground: "#199f43" },
  },
  {
    scope: "markup.deleted.diff",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "string.regexp",
    settings: { foreground: "#17a5af" },
  },
  {
    scope: "constant.other.character-class.regexp",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "keyword.operator.quantifier.regexp",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "constant.character.escape",
    settings: { foreground: "#1ca1c7" },
  },
  {
    scope: "source.json meta.structure.dictionary.json > string.quoted.json",
    settings: { foreground: "#d52c36" },
  },
  {
    scope:
      "source.json meta.structure.dictionary.json > string.quoted.json > punctuation.string",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: [
      "source.json meta.structure.dictionary.json > value.json > string.quoted.json",
      "source.json meta.structure.array.json > value.json > string.quoted.json",
      "source.json meta.structure.dictionary.json > value.json > string.quoted.json > punctuation",
      "source.json meta.structure.array.json > value.json > string.quoted.json > punctuation",
    ],
    settings: { foreground: "#199f43" },
  },
  {
    scope: [
      "source.json meta.structure.dictionary.json > constant.language.json",
      "source.json meta.structure.array.json > constant.language.json",
    ],
    settings: { foreground: "#08c0ef" },
  },
  {
    scope: "support.type.property-name.json",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "support.type.property-name.json punctuation",
    settings: { foreground: "#d52c36" },
  },
  {
    scope: "punctuation.definition.block.sequence.item.yaml",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "block.scope.end",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "block.scope.begin",
    settings: { foreground: "#79797F" },
  },
  {
    scope: "token.info-token",
    settings: { foreground: "#7b43f8" },
  },
  {
    scope: "token.warn-token",
    settings: { foreground: "#d5a910" },
  },
  {
    scope: "token.error-token",
    settings: { foreground: "#f44747" },
  },
  {
    scope: "token.debug-token",
    settings: { foreground: "#fc2b73" },
  },
  {
    scope: "invalid.illegal",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.broken",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.deprecated",
    settings: { foreground: "#ffffff" },
  },
  {
    scope: "invalid.unimplemented",
    settings: { foreground: "#ffffff" },
  },
];
var semanticTokenColors = {
  comment: "#84848A",
  string: "#199f43",
  number: "#1ca1c7",
  regexp: "#17a5af",
  keyword: "#fc2b73",
  variable: "#d47628",
  parameter: "#79797F",
  property: "#d47628",
  function: "#7b43f8",
  method: "#7b43f8",
  type: "#c635e4",
  class: "#c635e4",
  namespace: "#d5a910",
  enumMember: "#08c0ef",
  "variable.constant": "#d5a910",
  "variable.defaultLibrary": "#d5a910",
};
var pierre_light_default = {
  name,
  type,
  colors,
  tokenColors,
  semanticTokenColors,
};

//#endregion
export {
  colors,
  pierre_light_default as default,
  name,
  semanticTokenColors,
  tokenColors,
  type,
};
components/tool-ui/shared/schema.ts
import { z } from "zod";
import type { ReactNode } from "react";

/**
 * Tool UI conventions:
 * - Serializable schemas are JSON-safe (no callbacks/ReactNode/`className`).
 * - Schema: `SerializableXSchema`
 * - Parser: `parseSerializableX(input: unknown)` (throws on invalid)
 * - Safe parser: `safeParseSerializableX(input: unknown)` (returns `null` on invalid)
 * - Actions: `LocalActions` for non-receipt actions and `DecisionActions` for consequential actions
 * - Root attrs: `data-tool-ui-id` + `data-slot`
 */

/**
 * Schema for tool UI identity.
 *
 * Every tool UI should have a unique identifier that:
 * - Is stable across re-renders
 * - Is meaningful (not auto-generated)
 * - Is unique within the conversation
 *
 * Format recommendation: `{component-type}-{semantic-identifier}`
 * Examples: "data-table-expenses-q3", "option-list-deploy-target"
 */
export const ToolUIIdSchema = z.string().min(1);

export type ToolUIId = z.infer<typeof ToolUIIdSchema>;

/**
 * Primary role of a Tool UI surface in a chat context.
 */
export const ToolUIRoleSchema = z.enum([
  "information",
  "decision",
  "control",
  "state",
  "composite",
]);

export type ToolUIRole = z.infer<typeof ToolUIRoleSchema>;

export const ToolUIReceiptOutcomeSchema = z.enum([
  "success",
  "partial",
  "failed",
  "cancelled",
]);

export type ToolUIReceiptOutcome = z.infer<typeof ToolUIReceiptOutcomeSchema>;

/**
 * Optional receipt metadata: a durable summary of an outcome.
 */
export const ToolUIReceiptSchema = z.object({
  outcome: ToolUIReceiptOutcomeSchema,
  summary: z.string().min(1),
  identifiers: z.record(z.string(), z.string()).optional(),
  at: z.string().datetime(),
});

export type ToolUIReceipt = z.infer<typeof ToolUIReceiptSchema>;

/**
 * Base schema for Tool UI payloads (id + optional role/receipt).
 */
export const ToolUISurfaceSchema = z.object({
  id: ToolUIIdSchema,
  role: ToolUIRoleSchema.optional(),
  receipt: ToolUIReceiptSchema.optional(),
});

export type ToolUISurface = z.infer<typeof ToolUISurfaceSchema>;

export const ActionSchema = z.object({
  id: z.string().min(1),
  label: z.string().min(1),
  /**
   * Canonical narration the assistant can use after this action is taken.
   *
   * Example: "I exported the table as CSV." / "I opened the link in a new tab."
   */
  sentence: z.string().optional(),
  confirmLabel: z.string().optional(),
  variant: z
    .enum(["default", "destructive", "secondary", "ghost", "outline"])
    .optional(),
  icon: z.custom<ReactNode>().optional(),
  loading: z.boolean().optional(),
  disabled: z.boolean().optional(),
  shortcut: z.string().optional(),
});

export type Action = z.infer<typeof ActionSchema>;
export type LocalAction = Action;
export type DecisionAction = Action;

export const DecisionResultSchema = z.object({
  kind: z.literal("decision"),
  version: z.literal(1),
  decisionId: z.string().min(1),
  actionId: z.string().min(1),
  actionLabel: z.string().min(1),
  at: z.string().datetime(),
  payload: z.record(z.string(), z.unknown()).optional(),
});

export type DecisionResult<
  TPayload extends Record<string, unknown> = Record<string, unknown>,
> = Omit<z.infer<typeof DecisionResultSchema>, "payload"> & {
  payload?: TPayload;
};

export function createDecisionResult<
  TPayload extends Record<string, unknown> = Record<string, unknown>,
>(args: {
  decisionId: string;
  action: { id: string; label: string };
  payload?: TPayload;
}): DecisionResult<TPayload> {
  return {
    kind: "decision",
    version: 1,
    decisionId: args.decisionId,
    actionId: args.action.id,
    actionLabel: args.action.label,
    at: new Date().toISOString(),
    payload: args.payload,
  };
}

export const ActionButtonsPropsSchema = z.object({
  actions: z.array(ActionSchema).min(1),
  align: z.enum(["left", "center", "right"]).optional(),
  confirmTimeout: z.number().positive().optional(),
  className: z.string().optional(),
});

export const SerializableActionSchema = ActionSchema.omit({ icon: true });
export const SerializableActionsSchema = ActionButtonsPropsSchema.extend({
  actions: z.array(SerializableActionSchema),
}).omit({ className: true });

export interface ActionsConfig {
  items: Action[];
  align?: "left" | "center" | "right";
  confirmTimeout?: number;
}

export const SerializableActionsConfigSchema = z.object({
  items: z.array(SerializableActionSchema).min(1),
  align: z.enum(["left", "center", "right"]).optional(),
  confirmTimeout: z.number().positive().optional(),
});

export type SerializableActionsConfig = z.infer<
  typeof SerializableActionsConfigSchema
>;

export type SerializableAction = z.infer<typeof SerializableActionSchema>;
components/tool-ui/shared/use-copy-to-clipboard.ts
"use client";

import { useCallback, useEffect, useState } from "react";

function fallbackCopyToClipboard(text: string): boolean {
  const textArea = document.createElement("textarea");
  try {
    textArea.value = text;
    textArea.setAttribute("readonly", "");
    textArea.style.position = "fixed";
    textArea.style.top = "-9999px";
    textArea.style.left = "-9999px";
    document.body.appendChild(textArea);
    textArea.select();
    return document.execCommand("copy");
  } catch {
    return false;
  } finally {
    if (textArea.parentNode) {
      textArea.parentNode.removeChild(textArea);
    }
  }
}

export function useCopyToClipboard(options?: { resetAfterMs?: number }): {
  copiedId: string | null;
  copy: (text: string, id?: string) => Promise<boolean>;
} {
  const resetAfterMs = options?.resetAfterMs ?? 2000;
  const [copiedId, setCopiedId] = useState<string | null>(null);

  const copy = useCallback(async (text: string, id: string = "default") => {
    let ok = false;
    try {
      if (navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text);
        ok = true;
      } else {
        ok = fallbackCopyToClipboard(text);
      }
    } catch {
      ok = fallbackCopyToClipboard(text);
    }

    if (ok) {
      setCopiedId(id);
    }

    return ok;
  }, []);

  useEffect(() => {
    if (!copiedId) return;
    const timeout = setTimeout(() => setCopiedId(null), resetAfterMs);
    return () => clearTimeout(timeout);
  }, [copiedId, resetAfterMs]);

  return { copiedId, copy };
}

More from tool-ui

Browse all components in this library →