shadimage
tool-ui
blockcode-diffsource: ok · hit

Code Diff

Code Diff component for AI interfaces.

npx shadcn add "https://www.tool-ui.com/r/code-diff.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

Files10 · source cached 10/9/2026, 12:01:32 PM

components/tool-ui/code-diff/_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-diff/code-diff.tsx
"use client";

import {
  useState,
  useCallback,
  useEffect,
  useMemo,
  createContext,
  use,
  type ReactNode,
} from "react";
import {
  FileDiff as PierreFileDiff,
  PatchDiff as PierrePatchDiff,
} from "@pierre/diffs/react";
import { parseDiffFromFile, RegisteredCustomThemes } from "@pierre/diffs";
import type { FileDiffMetadata, ThemesType } from "@pierre/diffs";
import { Copy, Check, ChevronDown, ChevronUp } from "lucide-react";
import type { CodeDiffProps } from "./schema";
import { useCopyToClipboard } from "../shared/use-copy-to-clipboard";
import { Button, cn, Collapsible, CollapsibleTrigger } from "./_adapter";

/*
 * Pierre's shared_highlighter registers custom themes with dynamic imports
 * (`import("../themes/pierre-dark.js")`) that fail under Turbopack because the
 * package `exports` field doesn't include those subpaths. We override the
 * RegisteredCustomThemes map entries with loaders that point to local vendored
 * theme files in `components/tool-ui/shared`, which Turbopack can resolve.
 */
RegisteredCustomThemes.set("pierre-dark", () =>
  import("../shared/pierre-dark-theme.js").then((m) => m.default as never),
);
RegisteredCustomThemes.set("pierre-light", () =>
  import("../shared/pierre-light-theme.js").then((m) => m.default as never),
);

const COPY_ID = "codediff-code";

/* ── Theme detection (mirrors CodeBlock) ────────────────────────── */

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;
}

/* ── Language display names (mirrors CodeBlock) ─────────────────── */

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();
}

/* ── Shared context ─────────────────────────────────────────────── */

type CodeDiffSharedState = {
  id: string;
  isPatchMode: boolean;
  language: string;
  lineNumbers: "visible" | "hidden";
  filename?: string;
  diffStyle: "unified" | "split";
  copyableCode: string;
  isCopied: boolean;
  copyCode: () => void;
  isCollapsed: boolean;
  shouldCollapse: boolean;
  toggleExpanded: () => void;
  resolvedTheme: "light" | "dark";
  pierreThemes: ThemesType;
  fileDiffMetadata: FileDiffMetadata | null;
  patch: string | null;
  additions: number;
  deletions: number;
};

const CodeDiffContext = createContext<CodeDiffSharedState | null>(null);

function useCodeDiff(): CodeDiffSharedState {
  const context = use(CodeDiffContext);
  if (!context) {
    throw new Error(
      "CodeDiff subcomponents must be used within <CodeDiff.Root>.",
    );
  }
  return context;
}

/* ── Subcomponents ──────────────────────────────────────────────── */

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

function CodeDiffRoot({
  id,
  oldCode,
  newCode,
  patch,
  language = "text",
  filename,
  lineNumbers = "visible",
  diffStyle = "unified",
  maxCollapsedLines,
  className,
  children,
  expanded: expandedProp,
  defaultExpanded = false,
  onExpandedChange,
}: CodeDiffRootProps) {
  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 pierreThemes: ThemesType = {
    dark: "pierre-dark",
    light: "pierre-light",
  };

  // Auto-detect mode: if `patch` is provided, use patch mode; otherwise files mode
  const isPatchMode = !!patch;

  const fileDiffMetadata = useMemo(() => {
    if (isPatchMode) return null;
    return parseDiffFromFile(
      {
        name: filename ?? "file",
        contents: oldCode ?? "",
        lang: language as never,
      },
      {
        name: filename ?? "file",
        contents: newCode ?? "",
        lang: language as never,
      },
    );
  }, [isPatchMode, oldCode, newCode, filename, language]);

  const copyableCode = isPatchMode ? (patch ?? "") : (newCode ?? oldCode ?? "");

  const lineCount = useMemo(() => {
    if (isPatchMode) {
      return (patch ?? "").split("\n").length;
    }
    if (fileDiffMetadata) {
      return fileDiffMetadata.unifiedLineCount;
    }
    return 0;
  }, [isPatchMode, patch, fileDiffMetadata]);

  const { additions, deletions } = useMemo(() => {
    if (!isPatchMode && fileDiffMetadata) {
      let add = 0;
      let del = 0;
      for (const hunk of fileDiffMetadata.hunks) {
        add += hunk.additionLines;
        del += hunk.deletionLines;
      }
      return { additions: add, deletions: del };
    }
    if (isPatchMode && patch) {
      let add = 0;
      let del = 0;
      for (const line of patch.split("\n")) {
        if (line.startsWith("+") && !line.startsWith("+++ ")) add++;
        else if (line.startsWith("-") && !line.startsWith("--- ")) del++;
      }
      return { additions: add, deletions: del };
    }
    return { additions: 0, deletions: 0 };
  }, [isPatchMode, fileDiffMetadata, patch]);

  const shouldCollapse = !!maxCollapsedLines && lineCount > maxCollapsedLines;
  const isCollapsed = shouldCollapse && !expanded;

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

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

  const state: CodeDiffSharedState = {
    id,
    isPatchMode,
    language,
    lineNumbers,
    filename,
    diffStyle,
    copyableCode,
    isCopied,
    copyCode,
    isCollapsed,
    shouldCollapse,
    toggleExpanded,
    resolvedTheme,
    pierreThemes,
    fileDiffMetadata,
    patch: isPatchMode ? (patch ?? null) : null,
    additions,
    deletions,
  };

  return (
    <CodeDiffContext.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-diff"
      >
        <div className="border-border bg-card overflow-hidden rounded-lg border shadow-xs">
          <Collapsible open={!isCollapsed}>{children}</Collapsible>
        </div>
      </div>
    </CodeDiffContext.Provider>
  );
}

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

function CodeDiffHeader({ className }: CodeDiffSectionProps) {
  const { language, filename, isCopied, copyCode, additions, deletions } =
    useCodeDiff();
  const hasChanges = additions > 0 || deletions > 0;
  return (
    <div
      className={cn(
        "bg-card flex items-center justify-between gap-2 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">&bull;</span>
            <span className="text-foreground text-sm font-medium">
              {filename}
            </span>
          </>
        )}
      </div>
      {hasChanges && (
        <span className="ml-auto text-xs font-mono tabular-nums">
          {additions > 0 && (
            <span style={{ color: "#00cab1" }}>+{additions}</span>
          )}
          {additions > 0 && deletions > 0 && " "}
          {deletions > 0 && (
            <span style={{ color: "#ff2e3f" }}>-{deletions}</span>
          )}
        </span>
      )}
      <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 CodeDiffContent({ className }: CodeDiffSectionProps) {
  const {
    isPatchMode,
    diffStyle,
    lineNumbers,
    isCollapsed,
    resolvedTheme,
    pierreThemes,
    fileDiffMetadata,
    patch,
  } = useCodeDiff();

  const disableLineNumbers = lineNumbers === "hidden";

  return (
    <div
      className={cn(
        "overflow-x-auto overflow-y-clip text-sm",
        isCollapsed && "max-h-[200px]",
        className,
      )}
    >
      {!isPatchMode && fileDiffMetadata && (
        <PierreFileDiff
          fileDiff={fileDiffMetadata}
          options={{
            theme: pierreThemes,
            themeType: resolvedTheme,
            diffStyle,
            disableFileHeader: true,
            disableLineNumbers,
          }}
        />
      )}
      {isPatchMode && patch && (
        <PierrePatchDiff
          patch={patch}
          options={{
            theme: pierreThemes,
            themeType: resolvedTheme,
            diffStyle,
            disableFileHeader: true,
            disableLineNumbers,
          }}
        />
      )}
    </div>
  );
}

function CodeDiffCollapseToggle({ className }: CodeDiffSectionProps) {
  const { shouldCollapse, isCollapsed, toggleExpanded } = useCodeDiff();

  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 full diff
          </>
        ) : (
          <>
            <ChevronUp className="mr-2 h-4 w-4" />
            Collapse
          </>
        )}
      </Button>
    </CollapsibleTrigger>
  );
}

/* ── Composed preset (callable as a flat component) ─────────────── */

export type CodeDiffComposedProps = Omit<CodeDiffRootProps, "children">;

function CodeDiffComposed(props: CodeDiffComposedProps) {
  return (
    <CodeDiffRoot {...props}>
      <CodeDiffHeader />
      <CodeDiffContent />
      <CodeDiffCollapseToggle />
    </CodeDiffRoot>
  );
}

/* ── Compound export: CodeDiff is callable AND has subcomponents ── */

type CodeDiffComponent = typeof CodeDiffComposed & {
  Root: typeof CodeDiffRoot;
  Header: typeof CodeDiffHeader;
  Content: typeof CodeDiffContent;
  CollapseToggle: typeof CodeDiffCollapseToggle;
};

export const CodeDiff = Object.assign(CodeDiffComposed, {
  Root: CodeDiffRoot,
  Header: CodeDiffHeader,
  Content: CodeDiffContent,
  CollapseToggle: CodeDiffCollapseToggle,
}) as CodeDiffComponent;
components/tool-ui/code-diff/index.tsx
export { CodeDiff } from "./code-diff";
export type {
  CodeDiffRootProps,
  CodeDiffComposedProps,
  CodeDiffSectionProps,
} from "./code-diff";
export type { CodeDiffProps, SerializableCodeDiff } from "./schema";
components/tool-ui/code-diff/schema.ts
import { z } from "zod";
import { defineToolUiContract } from "../shared/contract";
import {
  ToolUIIdSchema,
  ToolUIReceiptSchema,
  ToolUIRoleSchema,
} from "../shared/schema";

const CodeDiffPropsSchemaBase = z.object({
  id: ToolUIIdSchema,
  role: ToolUIRoleSchema.optional(),
  receipt: ToolUIReceiptSchema.optional(),
  oldCode: z.string().optional(),
  newCode: z.string().optional(),
  patch: z.string().optional(),
  language: z.string().trim().min(1).default("text"),
  filename: z.string().optional(),
  lineNumbers: z.enum(["visible", "hidden"]).default("visible"),
  diffStyle: z.enum(["unified", "split"]).default("unified"),
  maxCollapsedLines: z.number().min(1).optional(),
  className: z.string().optional(),
});

function validateCodeDiffInputMode(
  data: { patch?: string; oldCode?: string; newCode?: string },
  ctx: z.RefinementCtx,
) {
  const hasPatch = !!data.patch;
  const hasFiles = !!data.oldCode || !!data.newCode;

  if (!hasPatch && !hasFiles) {
    ctx.addIssue({
      code: "custom",
      message:
        "Provide either a patch string or at least one of oldCode/newCode",
    });
  }

  if (hasPatch && hasFiles) {
    ctx.addIssue({
      code: "custom",
      message:
        "Cannot mix patch mode with oldCode/newCode — use one or the other",
    });
  }
}

export const CodeDiffPropsSchema = CodeDiffPropsSchemaBase.superRefine(
  validateCodeDiffInputMode,
);

export type CodeDiffProps = z.infer<typeof CodeDiffPropsSchema>;

export const SerializableCodeDiffSchema = CodeDiffPropsSchemaBase.omit({
  className: true,
}).superRefine(validateCodeDiffInputMode);

export type SerializableCodeDiff = z.infer<typeof SerializableCodeDiffSchema>;

const SerializableCodeDiffSchemaContract = defineToolUiContract(
  "CodeDiff",
  SerializableCodeDiffSchema,
);

export const parseSerializableCodeDiff: (
  input: unknown,
) => SerializableCodeDiff = SerializableCodeDiffSchemaContract.parse;

export const safeParseSerializableCodeDiff: (
  input: unknown,
) => SerializableCodeDiff | null = SerializableCodeDiffSchemaContract.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 →