@keboola/design 13.2.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -1
- package/CHANGELOG.md +161 -0
- package/COMPONENT-API.md +52 -42
- package/dist/{AIKit-C5FbKjwa.js → AIKit-BRSZ3nY7.js} +2216 -302
- package/dist/AIKit-BRSZ3nY7.js.map +1 -0
- package/dist/{Alert-DuAGeYyM.js → Alert-CZ0dDsuk.js} +2 -2
- package/dist/{Alert-DuAGeYyM.js.map → Alert-CZ0dDsuk.js.map} +1 -1
- package/dist/{BrandEditor-Dq168RJc.js → BrandEditor-CN2HJ_12.js} +5 -5
- package/dist/{BrandEditor-Dq168RJc.js.map → BrandEditor-CN2HJ_12.js.map} +1 -1
- package/dist/{Breadcrumb-CUyYu5Bi.js → Breadcrumb-BnIlsoIH.js} +54 -12
- package/dist/Breadcrumb-BnIlsoIH.js.map +1 -0
- package/dist/{Checkbox-D9rafoKh.js → Checkbox-uFE8XLT_.js} +2 -2
- package/dist/{Checkbox-D9rafoKh.js.map → Checkbox-uFE8XLT_.js.map} +1 -1
- package/dist/{Clipboard-BHWUodAx.js → Clipboard-D-9XOqy4.js} +2 -2
- package/dist/{Clipboard-BHWUodAx.js.map → Clipboard-D-9XOqy4.js.map} +1 -1
- package/dist/{ClipboardButton-Urg-kZbh.js → ClipboardButton-DxvZG_H0.js} +2 -2
- package/dist/{ClipboardButton-Urg-kZbh.js.map → ClipboardButton-DxvZG_H0.js.map} +1 -1
- package/dist/{CodeEditor-Y0iE-SwV.js → CodeEditor-BfRSCKEs.js} +5 -5
- package/dist/{CodeEditor-Y0iE-SwV.js.map → CodeEditor-BfRSCKEs.js.map} +1 -1
- package/dist/{ColorInput-D1nC0X6i.js → ColorInput-CDKH8q_f.js} +2 -2
- package/dist/{ColorInput-D1nC0X6i.js.map → ColorInput-CDKH8q_f.js.map} +1 -1
- package/dist/{ColorModeSwitch-Cxee8jnB.js → ColorModeSwitch-DR6J2U6M.js} +2 -2
- package/dist/{ColorModeSwitch-Cxee8jnB.js.map → ColorModeSwitch-DR6J2U6M.js.map} +1 -1
- package/dist/{Combobox-B1Kjoy5J.js → Combobox-CEesMe2M.js} +240 -38
- package/dist/Combobox-CEesMe2M.js.map +1 -0
- package/dist/{Command-BuOA3V18.js → Command-T3MLRaen.js} +8 -4
- package/dist/Command-T3MLRaen.js.map +1 -0
- package/dist/{CopyField-DsOVtV2Q.js → CopyField-CNbCHw9a.js} +2 -2
- package/dist/{CopyField-DsOVtV2Q.js.map → CopyField-CNbCHw9a.js.map} +1 -1
- package/dist/{DateInput-BlKkequE.js → DateInput-ClK1lCxz.js} +2 -2
- package/dist/{DateInput-BlKkequE.js.map → DateInput-ClK1lCxz.js.map} +1 -1
- package/dist/{DateRangeInput-DOxJHw8V.js → DateRangeInput-DtlAffS1.js} +2 -2
- package/dist/{DateRangeInput-DOxJHw8V.js.map → DateRangeInput-DtlAffS1.js.map} +1 -1
- package/dist/{DropdownMenu-DtRYcKEx.js → DropdownMenu-B1gGvZoh.js} +2 -2
- package/dist/{DropdownMenu-DtRYcKEx.js.map → DropdownMenu-B1gGvZoh.js.map} +1 -1
- package/dist/{FieldItem-Cf1E3rfQ.js → FieldItem-CYvJyjiI.js} +3 -3
- package/dist/{FieldItem-Cf1E3rfQ.js.map → FieldItem-CYvJyjiI.js.map} +1 -1
- package/dist/{Form-CuaAn-lR.js → Form-CD55zJiy.js} +5 -5
- package/dist/{Form-CuaAn-lR.js.map → Form-CD55zJiy.js.map} +1 -1
- package/dist/{FormGroup-D4O96YPm.js → FormGroup-DiYFdEhH.js} +3 -3
- package/dist/{FormGroup-D4O96YPm.js.map → FormGroup-DiYFdEhH.js.map} +1 -1
- package/dist/{HoverCard-Cy6nhg4u.js → HoverCard-BBdPYqEf.js} +2 -2
- package/dist/HoverCard-BBdPYqEf.js.map +1 -0
- package/dist/{InlineEdit-DSMIEUUa.js → InlineEdit-D5RdunZo.js} +3 -3
- package/dist/{InlineEdit-DSMIEUUa.js.map → InlineEdit-D5RdunZo.js.map} +1 -1
- package/dist/{Kbd-Du93F3o4.js → Kbd-3YM7NQO4.js} +2 -2
- package/dist/{Kbd-Du93F3o4.js.map → Kbd-3YM7NQO4.js.map} +1 -1
- package/dist/MermaidDiagram-CeiOkI60.js +199 -0
- package/dist/MermaidDiagram-CeiOkI60.js.map +1 -0
- package/dist/{Modal-DQIauzar.js → Modal-DMZRswk4.js} +4 -3
- package/dist/Modal-DMZRswk4.js.map +1 -0
- package/dist/{MultiActionButtonGroup-xKqiucAN.js → MultiActionButtonGroup-CEv_txvz.js} +2 -2
- package/dist/{MultiActionButtonGroup-xKqiucAN.js.map → MultiActionButtonGroup-CEv_txvz.js.map} +1 -1
- package/dist/{RadioGroup-C2vk5acr.js → RadioGroup-C8EC3fqO.js} +2 -2
- package/dist/{RadioGroup-C2vk5acr.js.map → RadioGroup-C8EC3fqO.js.map} +1 -1
- package/dist/{Search-CVrv3hqf.js → Search-aaUMI4ix.js} +2 -2
- package/dist/{Search-CVrv3hqf.js.map → Search-aaUMI4ix.js.map} +1 -1
- package/dist/{SearchInput-BnU6YHgT.js → SearchInput-Dxi2GK4n.js} +2 -2
- package/dist/{SearchInput-BnU6YHgT.js.map → SearchInput-Dxi2GK4n.js.map} +1 -1
- package/dist/{SectionNav-XlhvXXdF.js → SectionNav-BnHOMLtE.js} +3 -3
- package/dist/{SectionNav-XlhvXXdF.js.map → SectionNav-BnHOMLtE.js.map} +1 -1
- package/dist/Sheet-utw4_rUa.js.map +1 -1
- package/dist/{Sidebar-CKaxOPwY.js → Sidebar-BAmux2Uj.js} +5 -5
- package/dist/{Sidebar-CKaxOPwY.js.map → Sidebar-BAmux2Uj.js.map} +1 -1
- package/dist/{Slider-Rcc2qVct.js → Slider-DbzzSDRV.js} +2 -2
- package/dist/{Slider-Rcc2qVct.js.map → Slider-DbzzSDRV.js.map} +1 -1
- package/dist/{Table-CgSC-fSo.js → Table-CilEvpMq.js} +62 -3
- package/dist/Table-CilEvpMq.js.map +1 -0
- package/dist/{TextInput-B5TDDOty.js → TextInput-K2DSDs5O.js} +2 -2
- package/dist/{TextInput-B5TDDOty.js.map → TextInput-K2DSDs5O.js.map} +1 -1
- package/dist/{ThemeProvider-Dt9b67sW.js → ThemeProvider-C8yaKlM1.js} +2 -2
- package/dist/{ThemeProvider-Dt9b67sW.js.map → ThemeProvider-C8yaKlM1.js.map} +1 -1
- package/dist/ToggleAllTooltip-Dlmq-yqS.js +37 -0
- package/dist/ToggleAllTooltip-Dlmq-yqS.js.map +1 -0
- package/dist/{ZoomableSvg-D8sXKpoV.js → ZoomableSvg-Dh1OstPN.js} +84 -80
- package/dist/ZoomableSvg-Dh1OstPN.js.map +1 -0
- package/dist/editors.js +3 -3
- package/dist/flint.js +10 -45
- package/dist/flint.js.map +1 -1
- package/dist/highlightCode-D354tCXO.js +81 -0
- package/dist/highlightCode-D354tCXO.js.map +1 -0
- package/dist/index.d.ts +792 -346
- package/dist/index.js +35 -35
- package/dist/internal/blocks/AIKit.js +2 -2
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ChipEditor.js +1 -1
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/ColorModeSwitch.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/internal/blocks/DiagramShared/DiagramSkeleton.js.map +1 -1
- package/dist/internal/blocks/ExportMenu.js +2 -2
- package/dist/internal/blocks/Form/connectors/ComboboxField.js +2 -2
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +1 -1
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/InlineEdit.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +204 -68
- package/dist/internal/blocks/MultiCombobox.js.map +1 -1
- package/dist/internal/blocks/PasswordInput.js +1 -1
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +2 -2
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/SplitButton.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/TimeInput.js +1 -1
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +1 -1
- package/dist/internal/components/DropdownMenu.js +1 -1
- package/dist/internal/components/HoverCard.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/Modal.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Skeleton/Skeleton.js +1 -1
- package/dist/internal/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/Table.js +1 -1
- package/dist/internal/components/ThemeProvider.js +1 -1
- package/dist/internal/components/Tooltip.js +1 -1
- package/dist/internal/components/Truncated.js +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/utils.js +1 -1
- package/dist/markdown-editor.js +6 -6
- package/dist/mermaid.d.ts +1 -2
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.js +98 -11
- package/dist/rjsf.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/svgCache-Dhmbe-7i.js +26 -0
- package/dist/svgCache-Dhmbe-7i.js.map +1 -0
- package/dist/svgTransforms-Hnvev3Vs.js +38 -0
- package/dist/svgTransforms-Hnvev3Vs.js.map +1 -0
- package/dist/testing.js +1 -1
- package/dist/{themeTokens-7DEab0kp.js → themeTokens-l2Fsfcs7.js} +3 -12
- package/dist/themeTokens-l2Fsfcs7.js.map +1 -0
- package/dist/{utils-p6tjltbX.js → utils-LQ4jJA-9.js} +18 -2
- package/dist/utils-LQ4jJA-9.js.map +1 -0
- package/dist/vega.js +1 -1
- package/dist/vegaTheme-BrmVoPEz.js +49 -0
- package/dist/vegaTheme-BrmVoPEz.js.map +1 -0
- package/dist/{vegaTheme-VQMWTlBw.js → vegaTokens-Ce07C0DH.js} +36 -44
- package/dist/vegaTokens-Ce07C0DH.js.map +1 -0
- package/package.json +3 -4
- package/src/styles.css +4 -4
- package/dist/AIKit-C5FbKjwa.js.map +0 -1
- package/dist/Breadcrumb-CUyYu5Bi.js.map +0 -1
- package/dist/Combobox-B1Kjoy5J.js.map +0 -1
- package/dist/Command-BuOA3V18.js.map +0 -1
- package/dist/DiagramSource-jTwmmi9g.js +0 -11
- package/dist/DiagramSource-jTwmmi9g.js.map +0 -1
- package/dist/HoverCard-Cy6nhg4u.js.map +0 -1
- package/dist/MermaidDiagram-D2ThT8Q-.js +0 -302
- package/dist/MermaidDiagram-D2ThT8Q-.js.map +0 -1
- package/dist/Modal-DQIauzar.js.map +0 -1
- package/dist/Table-CgSC-fSo.js.map +0 -1
- package/dist/ZoomableSvg-D8sXKpoV.js.map +0 -1
- package/dist/svgTransforms-Dw2hRA-i.js +0 -51
- package/dist/svgTransforms-Dw2hRA-i.js.map +0 -1
- package/dist/themeTokens-7DEab0kp.js.map +0 -1
- package/dist/utils-p6tjltbX.js.map +0 -1
- package/dist/vegaTheme-VQMWTlBw.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeEditor-Y0iE-SwV.js","names":["cmPlaceholder","placeholder"],"sources":["../src/components/CodeEditor/ButtonToolbar.tsx","../src/components/CodeEditor/modes/dbt.ts","../src/components/CodeEditor/modes/jsonnet.ts","../src/components/CodeEditor/diffWash.ts","../src/components/CodeEditor/syntaxPalette.ts","../src/components/CodeEditor/helpers.ts","../src/components/CodeEditor/editorChrome.ts","../src/components/CodeEditor/search.ts","../src/components/CodeEditor/ToggleComponentHelp.tsx","../src/components/CodeEditor/tokenTheme.ts","../src/components/CodeEditor/tooltips.ts","../src/components/CodeEditor/variableCompletion.ts","../src/components/CodeEditor/CodeEditor.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { ClipboardButton } from '../../blocks/ClipboardButton';\n\n// Floats over the top-right corner of the editor it is rendered into — private to\n// `CodeEditor`, which is the `relative` ancestor it positions against. `right-3`\n// leaves room for the scrollbar track, whose width the browser owns and no token\n// here describes.\nexport const ButtonToolbar = ({ value, children }: { value?: string; children?: ReactNode }) => {\n if (!value && !children) return null;\n\n return (\n <div className=\"tw:absolute tw:right-3 tw:top-1 tw:z-10 tw:flex tw:gap-0.5 tw:overflow-visible tw:rounded tw:border tw:border-solid tw:border-border tw:!bg-background tw:p-px tw:shadow-sm\">\n {!!value && <ClipboardButton size=\"icon-xs\" variant=\"invisible\" text={value} />}\n {children}\n </div>\n );\n};\n","import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';\nimport { simpleMode } from '@codemirror/legacy-modes/mode/simple-mode';\n\n// A dbt step is `dbt <command> [<subcommand>] [arguments, flags and selectors]`,\n// and the vocabulary below is grouped by the slot it belongs to — both to colour\n// it and to decide what is worth offering where.\nconst COMMANDS = [\n 'run-operation',\n 'run',\n 'test',\n 'seed',\n 'snapshot',\n 'list',\n 'ls',\n 'compile',\n 'build',\n 'deps',\n 'docs',\n 'source',\n];\nconst SUBCOMMANDS: Record<string, string[]> = { docs: ['generate'], source: ['freshness'] };\nconst ARGUMENTS = ['--select', '--exclude', '--selector', '--defer', '--resource-type', '-s'];\n// The arguments whose value is a graph selector, and so the only ones a selector\n// method has anything to attach to.\nconst SELECTORS = ['--select', '--exclude', '-s'];\nconst METHODS = [\n 'path:',\n 'source:',\n 'tag:',\n 'package:',\n 'config:',\n 'test_type:',\n 'test_name:',\n 'state:',\n 'exposure:',\n 'metric:',\n 'result:',\n 'source_status:',\n 'column_name:',\n];\nconst FLAGS = [\n '--fail-fast',\n '--warn-error',\n '--favor-state',\n '--vars',\n '--models',\n '--threads',\n '--profiles-dir',\n '--profile',\n '--full-refresh',\n];\n\n// A subcommand only ever highlights together with its command, so `dbt docs` stays\n// unpainted until `generate` follows it.\nconst COMMAND_PHRASES = COMMANDS.flatMap((command) => {\n const subcommands = SUBCOMMANDS[command];\n\n return subcommands ? subcommands.map((subcommand) => `${command} ${subcommand}`) : [command];\n});\n\n// Alternation is first-match, so a word that prefixes another has to come first\n// (`run-operation` before `run`, `--profiles-dir` before `--profile`). Sorting by\n// length keeps that true however the lists above are written.\nconst alternation = (list: string[]) => [...list].sort((a, b) => b.length - a.length).join('|');\n\n// Every keyword follows whitespace, so the leading run is part of the match.\n// Commands and arguments end on a word boundary; methods and flags carry their\n// own terminator (`:`) or need none.\nconst word = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})\\\\b`, 'i');\nconst prefix = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})`, 'i');\n\n// The word being completed: letters, digits, `_`, `-` and the `:` a selector\n// method ends with. Whitespace stays out of it, so a two-word label like `docs\n// generate` cannot stretch the match back across the words before the cursor.\nconst WORD = /[\\w:-]*$/;\n\nconst asOptions = (list: string[], type: string): Completion[] =>\n list.map((label) => ({ label, type }));\n\n// `type` drives the popup icon, so each group carries the one that matches the\n// colour the mode paints it in.\nconst DBT: Completion[] = [{ label: 'dbt', type: 'keyword' }];\nconst COMMAND_OPTIONS = asOptions(COMMANDS, 'keyword');\nconst SUBCOMMAND_OPTIONS: Record<string, Completion[]> = Object.fromEntries(\n Object.entries(SUBCOMMANDS).map(([command, subcommands]) => [\n command,\n asOptions(subcommands, 'keyword'),\n ]),\n);\nconst ARGUMENT_OPTIONS = asOptions(ARGUMENTS, 'variable');\nconst FLAG_OPTIONS = asOptions(FLAGS, 'constant');\nconst METHOD_OPTIONS = asOptions(METHODS, 'property');\n\n// Which slice of the vocabulary the cursor's slot can hold, given the words\n// already finished ahead of it. Offering the whole vocabulary everywhere proposes\n// `dbt` mid-command and a selector method with no selector to attach to.\nconst optionsAfter = (words: string[]): Completion[] => {\n const [step, command, ...rest] = words;\n\n if (step === undefined) return DBT;\n if (step.toLowerCase() !== 'dbt') return [];\n if (command === undefined) return COMMAND_OPTIONS;\n\n const subcommands = SUBCOMMAND_OPTIONS[command.toLowerCase()];\n if (subcommands && rest.length === 0) return subcommands;\n\n // A selector argument takes any number of space-separated values, so what\n // decides the slot is the last argument, not whether a selector appeared at all:\n // `--select tag:a tag:b` keeps offering methods, `--select a --profile p` stops.\n const lastArgument = rest.filter((it) => it.startsWith('-')).at(-1);\n const selecting = lastArgument !== undefined && SELECTORS.includes(lastArgument.toLowerCase());\n\n return selecting\n ? [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS, ...METHOD_OPTIONS]\n : [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS];\n};\n\nconst complete = (context: CompletionContext): CompletionResult | null => {\n const typed = context.matchBefore(WORD);\n\n // `WORD` also matches the empty string, so without this the popup would open on\n // every space. Asking for completions explicitly still opens it there.\n if (!typed?.text && !context.explicit) return null;\n\n const from = typed?.from ?? context.pos;\n const line = context.state.doc.lineAt(from);\n const options = optionsAfter(\n line.text\n .slice(0, from - line.from)\n .split(/\\s+/)\n .filter(Boolean),\n );\n\n return options.length > 0 ? { from, options, validFor: WORD } : null;\n};\n\nexport const dbt = simpleMode({\n languageData: {\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n commentTokens: { line: '--', block: { open: '/*', close: '*/' } },\n autocomplete: complete,\n },\n start: [\n { regex: /\"(?:[^\\\\]|\\\\.)*?(?:\"|$)/, token: 'string' },\n // Word-bounded, so `dbtX` is not a dbt step whose first word happens to\n // colour — the same thing the completion source asks of it.\n { regex: /dbt\\b/, token: 'keyword', sol: true },\n { regex: word(COMMAND_PHRASES), token: 'keyword' },\n { regex: word(ARGUMENTS), token: 'variableName' },\n { regex: prefix(METHODS), token: 'propertyName' },\n { regex: prefix(FLAGS), token: 'attributeName' },\n { regex: /(?:@|\\*|,|\\+\\d+|\\d+\\+|\\+)/, token: 'operator' },\n { regex: /'.*'/, token: 'string' },\n { regex: /true|false/, token: 'atom' },\n ],\n});\n","import type { StreamParser } from '@codemirror/language';\n\n/**\n * Port of google/codemirror-mode-jsonnet (Apache-2.0) to CodeMirror 6 tags.\n *\n * - Patterns are anchored with `^`: unanchored, `StringStream.match` scans the whole rest of the line.\n */\n\nconst COMMENT_END = /^\\*\\//;\nconst COMMENT_START = /^\\/\\/|^#/;\nconst C_COMMENT_START = /^\\/\\*/;\nconst TEXT_BLOCK = /^\\|\\|\\|/;\nconst TEXT_BLOCK_END = /^\\s*\\|\\|\\|/;\nconst RAW_DOUBLE = /^\"\"/;\nconst RAW_SINGLE = /^''/;\nconst CLOSE_DOUBLE = /^\"/;\nconst CLOSE_SINGLE = /^'/;\nconst ESCAPE = /^\\\\[\\\\\"'/bfnrt0]/;\nconst UNICODE_ESCAPE = /^\\\\u[0-9a-fA-F]{4}/;\nconst BACKSLASH = /^\\\\/;\nconst IMPORT = /^import(?:str)?\\s*(@?)([\"'])/;\nconst QUOTE = /^(@?)([\"'])/;\nconst ROOT = /^\\$/;\nconst NUMBER = /^(?:\\.\\d+|\\d+\\.?\\d*)(?:e[-+]?\\d+)?/i;\nconst OPERATOR = /^[-+/*=<>!&~^|$%]+/;\nconst IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*/;\n\nconst KEYWORDS: Record<string, 'keyword' | 'atom'> = {\n local: 'keyword',\n self: 'keyword',\n super: 'keyword',\n assert: 'keyword',\n function: 'keyword',\n if: 'keyword',\n then: 'keyword',\n else: 'keyword',\n for: 'keyword',\n in: 'keyword',\n tailstrict: 'keyword',\n error: 'keyword',\n true: 'atom',\n false: 'atom',\n null: 'atom',\n};\n\ntype State = {\n cComment: boolean;\n textBlock: boolean;\n textBlockIndent: number | null;\n string: boolean;\n importString: boolean;\n stringSingle: boolean;\n stringRaw: boolean;\n};\n\nexport const jsonnet: StreamParser<State> = {\n name: 'jsonnet',\n\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n languageData: { commentTokens: { line: '//', block: { open: '/*', close: '*/' } } },\n\n startState: () => ({\n cComment: false,\n textBlock: false,\n textBlockIndent: null,\n string: false,\n importString: false,\n stringSingle: false,\n stringRaw: false,\n }),\n\n token: (stream, state) => {\n if (state.cComment) {\n if (stream.match(COMMENT_END)) {\n state.cComment = false;\n return 'comment';\n }\n stream.next();\n return 'comment';\n }\n\n // Match the closing `|||` before measuring indent, or a block closed at column 0 never ends.\n if (state.textBlock) {\n if (state.textBlockIndent == null) {\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n state.textBlockIndent = stream.indentation();\n }\n if (stream.indentation() >= state.textBlockIndent) {\n stream.skipToEnd();\n return 'string';\n }\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n stream.next();\n return 'invalid';\n }\n\n if (state.string || state.importString) {\n const style = state.string ? 'string' : 'meta';\n\n if (state.stringRaw) {\n if (stream.match(state.stringSingle ? RAW_SINGLE : RAW_DOUBLE)) return 'escape';\n } else {\n if (stream.match(ESCAPE)) return 'escape';\n if (stream.match(UNICODE_ESCAPE)) return 'escape';\n if (stream.match(BACKSLASH)) return 'invalid';\n }\n\n if (stream.match(state.stringSingle ? CLOSE_SINGLE : CLOSE_DOUBLE)) {\n state.string = false;\n state.importString = false;\n return style;\n }\n\n stream.next();\n return style;\n }\n\n if (stream.match(COMMENT_START)) {\n stream.skipToEnd();\n return 'comment';\n }\n if (stream.match(C_COMMENT_START)) {\n state.cComment = true;\n return 'comment';\n }\n\n const imported = stream.match(IMPORT);\n if (Array.isArray(imported)) {\n state.importString = true;\n state.stringRaw = imported[1] === '@';\n state.stringSingle = imported[2] === \"'\";\n return 'meta';\n }\n\n const quoted = stream.match(QUOTE);\n if (Array.isArray(quoted)) {\n state.string = true;\n state.stringRaw = quoted[1] === '@';\n state.stringSingle = quoted[2] === \"'\";\n return 'string';\n }\n\n if (stream.match(TEXT_BLOCK)) {\n state.textBlock = true;\n state.textBlockIndent = null;\n return 'string';\n }\n\n if (stream.match(ROOT)) return 'keyword';\n if (stream.match(NUMBER)) return 'number';\n if (stream.match(OPERATOR)) return 'operator';\n\n // Consumed whole so that a keyword's prefix (`locally`) is not styled.\n const identifier = stream.match(IDENTIFIER);\n if (Array.isArray(identifier)) return KEYWORDS[identifier[0]] ?? null;\n\n stream.next();\n return null;\n },\n};\n","import type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * Alpha suffixes for the dark-scheme diff and state tints.\n *\n * - Line fill stays subtle for text to read; the gutter sits a step stronger.\n * - `DARK_LINE_ALPHA` is also appended by the static washes in `highlighting.ts` and `search.ts`.\n */\nexport const DARK_LINE_ALPHA = '29'; /* 16% */\nconst DARK_GUTTER_ALPHA = '47'; /* 28% */\n\n/**\n * The two diff fills per scheme: light uses the opaque pastel, dark the `500` hue at low alpha.\n *\n * - Imports nothing, so `MergeEditor` shares it without pulling in CodeMirror via `helpers.ts`.\n * - Shared by `helpers.ts` and `MergeEditor/decorations.ts`, so their alphas cannot drift.\n */\nexport const buildDiffWash = (scheme: ResolvedColorScheme) => {\n const dark = scheme === 'dark';\n\n return {\n line: (hue: string, pastel: string) => (dark ? `${hue}${DARK_LINE_ALPHA}` : pastel),\n gutter: (hue: string, pastel: string) => (dark ? `${hue}${DARK_GUTTER_ALPHA}` : pastel),\n };\n};\n","import { tags } from '@lezer/highlight';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * The tag colours layered over the stock github palette, per colour scheme.\n *\n * - Imports only tags and ramps, so `scripts/contrast-audit.ts` can measure it.\n * - These override stock rules for the same tag.\n * - Colours are chosen against `background` and `muted` (`variant=\"field\"`); ratios quote both.\n */\nexport const buildSyntaxPalette = (scheme: ResolvedColorScheme, foreground: string) => {\n const dark = scheme === 'dark';\n\n return [\n // Identifiers and brackets carry no colour, as on github.com.\n { tag: [tags.name, tags.special(tags.string), tags.bracket], color: foreground },\n // Functions — light `600` 6.13 / 5.84, dark `300` 9.62 / 7.80.\n { tag: tags.standard(tags.name), color: dark ? colors.purple[300] : colors.purple[600] },\n // Special vars — light `800` 7.26 / 6.92, dark `300` 13.49 / 10.94.\n { tag: tags.special(tags.name), color: dark ? colors.cyan[300] : colors.cyan[800] },\n // Strings — light `800` 7.23 / 6.89, dark `300` 13.53 / 10.97.\n { tag: tags.string, color: dark ? colors.warning[300] : colors.warning[800] },\n // Light-only fixes for stock colours below AA; `CONTRAST-AUDIT.md` has all surfaces.\n ...(dark\n ? []\n : [\n // Keywords — 5.96 / 5.69.\n { tag: [tags.keyword, tags.typeName, tags.typeOperator], color: colors.error[550] },\n // Comments — 6.44 / 6.15.\n { tag: tags.comment, color: colors.neutral[500] },\n // Markdown quotes — 7.15 / 6.82.\n { tag: tags.quote, color: colors.green[900] },\n // Lex errors — 7.81 / 7.45; stock red fails the read-only wash.\n { tag: tags.invalid, color: colors.error[700] },\n ]),\n // Dark only: `githubDarkStyle` has no `escape` rule, so escapes would blend into strings.\n ...(dark ? [{ tag: [tags.escape, tags.url, tags.link], color: colors.blue[300] }] : []),\n ];\n};\n","import { javascript } from '@codemirror/lang-javascript';\nimport { json, jsonParseLinter } from '@codemirror/lang-json';\nimport { python } from '@codemirror/lang-python';\nimport { MSSQL, MySQL, PLSQL, PostgreSQL, StandardSQL } from '@codemirror/lang-sql';\nimport { StreamLanguage } from '@codemirror/language';\nimport { r } from '@codemirror/legacy-modes/mode/r';\nimport { shell } from '@codemirror/legacy-modes/mode/shell';\nimport { toml } from '@codemirror/legacy-modes/mode/toml';\nimport type { LintSource } from '@codemirror/lint';\nimport { linter } from '@codemirror/lint';\nimport { githubDarkInit, githubLightInit } from '@uiw/codemirror-theme-github';\nimport type { BasicSetupOptions } from '@uiw/react-codemirror';\n\nimport { getSqlLanguageSupport } from '@keboola/codemirror-lang-sql';\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { resolveToken } from '../../utils/themeTokens';\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\nimport { dbt } from './modes/dbt';\nimport { jsonnet } from './modes/jsonnet';\nimport { buildDiffWash } from './diffWash';\nimport { buildSyntaxPalette } from './syntaxPalette';\n\n// One list for both the runtime whitelist and the type — a separate `LANGUAGE_MODE[]` copy drifts.\nexport const LANGUAGE_MODES = [\n 'application/json',\n 'text/plain',\n 'text/x-python',\n 'text/x-sql',\n 'text/x-mysql',\n 'text/x-pgsql',\n 'text/x-mssql',\n // Snowflake; the strings are a published prop contract.\n 'text/x-sfsql',\n 'text/x-bqsql',\n 'text/x-plsql',\n 'text/x-rsrc',\n 'text/x-sh',\n 'text/x-toml',\n 'text/jsonnet',\n 'text/x-dbt',\n 'text/javascript',\n 'text/typescript',\n] as const;\n\nexport type LANGUAGE_MODE = (typeof LANGUAGE_MODES)[number];\n\nexport const isLanguageMode = (mode: string): mode is LANGUAGE_MODE =>\n (LANGUAGE_MODES as readonly string[]).includes(mode);\n\n// - `readOnly` is only addressable through `contenteditable`.\n// - `fieldChrome` overrides the read-only wash by re-declaring this key; strings must match exactly.\nexport const READ_ONLY_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"false\"])';\nexport const EDITABLE_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"true\"])';\n\n/**\n * Editor chrome and the unified merge (diff) wash.\n *\n * - Chrome resolves from live `--*` tokens; fallbacks mirror light-mode values for SSR.\n * - Diff colours are fixed across brands; light/dark pairs from `buildDiffWash`, shared with\n * `MergeEditor/decorations.ts`.\n * - Only `CodeEditor`'s unified merge view uses this; `MergePane` has its own theme.\n */\nexport const buildBaseThemeStyles = (scheme: ResolvedColorScheme) => {\n const { line, gutter } = buildDiffWash(scheme);\n const dark = scheme === 'dark';\n\n return {\n '*': { lineHeight: '20px' },\n '*::selection': {\n backgroundColor: resolveToken('primary', '31 143 255'),\n color: `${resolveToken('primary-foreground', '255 255 255')} !important`,\n },\n // Dark uses `muted`: `secondary` is lighter there and drops `comment` to 4.27:1.\n // `--code-editor-surface` on an ancestor overrides body and gutters.\n [READ_ONLY_EDITOR]: {\n backgroundColor: `var(--code-editor-surface, ${\n dark ? resolveToken('muted', '38 38 45') : resolveToken('secondary', '226 232 240')\n })`,\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: {\n backgroundColor: `var(--code-editor-surface, ${resolveToken('border', '229 231 235')})`,\n },\n '&.cm-editor .cm-scroller': { overflowAnchor: 'none' },\n '&.cm-editor, &.cm-editor .cm-scroller': {\n minHeight: '100%',\n flexGrow: 1,\n alignItems: 'stretch !important',\n outline: 'none',\n },\n '.cm-gutter.cm-foldGutter': { display: 'none !important' },\n '.cm-gutter.cm-lineNumbers': { paddingLeft: '20px', paddingRight: '6px' },\n '.cm-gutters': { height: 'auto' },\n\n // merge (diff) view\n '&[class*=\"cm-merge-\"] .cm-deletedLine': {\n backgroundColor: line(colors.error[500], colors.error[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLine': {\n backgroundColor: line(colors.green[500], colors.green[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedLineGutter': {\n backgroundColor: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLineGutter': {\n backgroundColor: gutter(colors.green[500], colors.green[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedText': {\n background: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedText': {\n background: gutter(colors.green[500], colors.green[200]),\n },\n // Follows the page, not the diff — fixed white would be a light slab under dark.\n '&[class*=\"cm-merge-\"]': {\n backgroundColor: `${resolveToken('background', '249 250 251')} !important`,\n },\n '&[class*=\"cm-merge-\"] .cm-gutters': {\n backgroundColor: `${resolveToken('muted', '241 245 249')} !important`,\n },\n '.cm-changeGutter': { position: 'absolute', zIndex: -1, width: '100%', paddingLeft: 0 },\n '&[class*=\"cm-merge-\"] .cm-changedLine,&[class*=\"cm-merge-\"] .cm-line, &[class*=\"cm-merge-\"] .cm-deletedChunk':\n { paddingLeft: 0 },\n };\n};\n\n// - Fold gutter and active line are hidden by the themes anyway.\n// - `autocompletion`: `CodeEditor` and `SqlEditor` install their own; a second instance competes.\nconst ALWAYS_OFF = {\n autocompletion: false,\n drawSelection: false,\n foldGutter: false,\n foldKeymap: false,\n highlightActiveLine: false,\n highlightActiveLineGutter: false,\n} as const;\n\n// - `basicSetup` enables everything not skipped; a viewer drops editing commands.\n// - Search stays — Mod-f is useful on a viewer.\n// - `history` stays: flipping `readOnly` reconfigures the view, which would drop the undo stack.\nexport const buildBasicSetup = (readOnly: boolean): BasicSetupOptions => ({\n ...ALWAYS_OFF,\n ...(readOnly\n ? {\n closeBrackets: false,\n closeBracketsKeymap: false,\n lintKeymap: false,\n indentOnInput: false,\n rectangularSelection: false,\n dropCursor: false,\n highlightSelectionMatches: false,\n }\n : null),\n});\n\n/**\n * The syntax theme, per colour scheme.\n *\n * - Light github palette fails AA on dark surfaces, so the palette is picked by scheme.\n * - `githubDarkInit` sets the `EditorView.darkTheme` facet that every `&dark` rule keys off.\n * - `caret` and `selectionMatch` are pinned: the initialisers disagree on them.\n */\nexport const buildCustomTheme = (scheme: ResolvedColorScheme) => {\n const foreground = resolveToken('foreground', '30 41 59');\n const init = scheme === 'dark' ? githubDarkInit : githubLightInit;\n\n return init({\n settings: {\n fontFamily: `'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New'`,\n background: resolveToken('background', '249 250 251'),\n foreground,\n caret: foreground,\n gutterBackground: resolveToken('muted', '241 245 249'),\n gutterForeground: resolveToken('muted-foreground', '100 116 139'),\n gutterBorder: 'transparent',\n lineHighlight: 'transparent',\n selection: resolveToken('primary', '31 143 255'),\n selectionMatch: resolveToken('primary', '31 143 255', 0.1),\n },\n styles: buildSyntaxPalette(scheme, foreground),\n });\n};\n\nexport const getLanguageMode = (mode?: LANGUAGE_MODE) => {\n switch (mode) {\n case undefined:\n case 'application/json':\n return json();\n case 'text/x-python':\n return python();\n case 'text/x-sql':\n return getSqlLanguageSupport(StandardSQL);\n case 'text/x-mysql':\n return getSqlLanguageSupport(MySQL);\n case 'text/x-pgsql':\n return getSqlLanguageSupport(PostgreSQL);\n case 'text/x-mssql':\n return getSqlLanguageSupport(MSSQL);\n case 'text/x-sfsql':\n return getSqlLanguageSupport('snowflake');\n case 'text/x-bqsql':\n return getSqlLanguageSupport('bigquery');\n case 'text/x-plsql':\n return getSqlLanguageSupport(PLSQL);\n case 'text/x-rsrc':\n return StreamLanguage.define(r);\n case 'text/x-sh':\n return StreamLanguage.define(shell);\n case 'text/x-toml':\n return StreamLanguage.define(toml);\n case 'text/jsonnet':\n return StreamLanguage.define(jsonnet);\n case 'text/x-dbt':\n return StreamLanguage.define(dbt);\n case 'text/javascript':\n return javascript({ jsx: true });\n case 'text/typescript':\n return javascript({ jsx: true, typescript: true });\n // `text/plain` and any unmapped mode: unstyled, not coloured as JSON.\n default:\n return [];\n }\n};\n\n// A read-only editor can't act on lint errors; its underlines are noise.\nexport const shouldLintJson = (mode: LANGUAGE_MODE | undefined, readOnly: boolean): boolean =>\n mode === 'application/json' && !readOnly;\n\n/**\n * Wraps a lint source so a blank document produces no diagnostics.\n *\n * - For optional fields, where empty is valid but `jsonParseLinter` reports an error.\n */\nexport const skipBlankDocument =\n (source: LintSource): LintSource =>\n (view) =>\n view.state.doc.toString().trim() === '' ? [] : source(view);\n\n/**\n * The JSON linter, optionally blind to a blank document.\n *\n * - Opt-in: some callers rely on the marker alone to explain why empty disables their button.\n * - Not derivable from `variant` — whether blank is valid is the field's contract.\n */\nexport const buildJsonLinter = (allowBlankDocument: boolean) => {\n const source = jsonParseLinter();\n\n return linter(allowBlankDocument ? skipBlankDocument(source) : source);\n};\n","import { resolveToken } from '../../utils/themeTokens';\n\nimport { EDITABLE_EDITOR, READ_ONLY_EDITOR } from './helpers';\n\n/** Per-preset parts of an editor's outer chrome, mapped to selectors by `buildChromeStyles`. */\nexport type EditorChrome = {\n surface: string;\n borderColor: string;\n readOnlySurface: string;\n readOnlyBorderColor: string;\n /** `null`: no hover affordance (form inputs). */\n hoverBorderColor: string | null;\n focusBorderColor: string;\n focusRing: string;\n radius: string;\n paddingY: string;\n /** `null` leaves CodeMirror's own 6px/2px line inset alone. */\n paddingX: { left: string; right: string } | null;\n};\n\n/**\n * Mirrors `InputGroup` at each design language's `TextInput` sizing, so it reads as a form field.\n *\n * - Same colour-scheme tokens as `InputGroup`, so it follows light/dark.\n * - argo: `muted`/`input`, the editable argo field's pair.\n * - legacy: `secondary` as `variant=\"secondary\"`; readonly `muted`/`input` as base `InputGroup`.\n */\nexport const buildInputChrome = (isArgo: boolean): EditorChrome => {\n return {\n surface: isArgo\n ? resolveToken('muted', '241 245 249')\n : resolveToken('secondary', '226 232 240'),\n borderColor: isArgo\n ? resolveToken('input', '203 213 225')\n : resolveToken('secondary', '226 232 240'),\n readOnlySurface: resolveToken('muted', '241 245 249'),\n readOnlyBorderColor: resolveToken('input', '203 213 225'),\n hoverBorderColor: null,\n focusBorderColor: isArgo\n ? resolveToken('primary', '37 99 235')\n : resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', isArgo ? 0.5 : 0.3)}`,\n radius: isArgo ? 'var(--radius-lg, 0.25rem)' : '0.25rem',\n // 2px border + 2×this + `.cm-content`'s 4px + 20px line = a one-line `TextInput`:\n // argo `medium` (36px), legacy `default` (40px).\n paddingY: isArgo ? '3px' : '5px',\n // Tops `.cm-line`'s 6px/2px up to an input's 16px text inset.\n paddingX: { left: '10px', right: '14px' },\n };\n};\n\n/** The SQL workspace's notebook cell: a white canvas, not a form control. */\nexport const buildCanvasChrome = (): EditorChrome => ({\n surface: resolveToken('card', '255 255 255'),\n borderColor: 'transparent',\n readOnlySurface: resolveToken('muted', '241 245 249'),\n readOnlyBorderColor: 'transparent',\n hoverBorderColor: resolveToken('ring', '31 143 255'),\n focusBorderColor: resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', 0.3)}`,\n radius: '8px',\n paddingY: '8px',\n paddingX: null,\n});\n\n/** Spread over `buildBaseThemeStyles()`; read-only keys match the base's to replace its wash. */\nexport const buildChromeStyles = (chrome: EditorChrome) => ({\n '&.cm-editor': {\n border: `solid 1px ${chrome.borderColor}`,\n borderRadius: chrome.radius,\n backgroundColor: chrome.surface,\n paddingTop: chrome.paddingY,\n paddingBottom: chrome.paddingY,\n },\n '&.cm-editor :is(.cm-gutters,.cm-scroller)': { backgroundColor: chrome.surface },\n\n ...(chrome.paddingX\n ? {\n // Gutterless only: text aligns with a neighbouring `TextInput`'s; a gutter owns the edge.\n '&.cm-editor:not(:has(.cm-gutters)) .cm-content': {\n paddingLeft: chrome.paddingX.left,\n paddingRight: chrome.paddingX.right,\n },\n }\n : null),\n\n ...(chrome.hoverBorderColor\n ? { [`${EDITABLE_EDITOR}:hover`]: { borderColor: chrome.hoverBorderColor } }\n : null),\n [`${EDITABLE_EDITOR}:focus-within`]: {\n borderColor: chrome.focusBorderColor,\n boxShadow: chrome.focusRing,\n },\n\n [READ_ONLY_EDITOR]: {\n backgroundColor: chrome.readOnlySurface,\n borderColor: chrome.readOnlyBorderColor,\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: { backgroundColor: chrome.readOnlySurface },\n [`${READ_ONLY_EDITOR} .cm-scroller`]: { backgroundColor: chrome.readOnlySurface },\n});\n","import { StateEffect, StateField, type Text } from '@codemirror/state';\nimport {\n Decoration,\n type DecorationSet,\n EditorView,\n ViewPlugin,\n type ViewUpdate,\n} from '@codemirror/view';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { findLiteralMatches } from '../../utils/findLiteralMatches';\n\nimport { DARK_LINE_ALPHA } from './diffWash';\n\ntype SearchMatch = {\n from: number;\n to: number;\n localIndex: number;\n};\n\nconst setSearchEffect = StateEffect.define<{\n query: string;\n selectedMatchIndex?: number;\n}>();\n\ntype SearchState = {\n query: string;\n selectedMatchIndex?: number;\n matches: SearchMatch[];\n decorations: DecorationSet;\n};\n\nfunction findMatches(doc: Text, query: string): SearchMatch[] {\n // Before `doc.toString()`, which joins the whole rope.\n if (!query || query.length > doc.length) return [];\n\n return findLiteralMatches(doc.toString(), query).map((from, index) => ({\n from,\n to: from + query.length,\n localIndex: index,\n }));\n}\n\nfunction createDecorations(matches: SearchMatch[], selectedLocalIndex?: number): DecorationSet {\n const decorations = matches.map((match) => {\n const isSelected = match.localIndex === selectedLocalIndex;\n\n const decoration = Decoration.mark({\n class: isSelected ? 'cm-searchMatch-selected' : 'cm-searchMatch',\n });\n\n return decoration.range(match.from, match.to);\n });\n\n return Decoration.set(decorations, true);\n}\n\nconst searchField = StateField.define<SearchState>({\n create() {\n return {\n query: '',\n selectedMatchIndex: undefined,\n matches: [],\n decorations: Decoration.none,\n };\n },\n\n update(state, tr) {\n let newState = state;\n\n for (const effect of tr.effects) {\n if (!effect.is(setSearchEffect)) {\n continue;\n }\n\n const { query, selectedMatchIndex } = effect.value;\n\n const matches = findMatches(tr.state.doc, query);\n\n const decorations = createDecorations(matches, selectedMatchIndex);\n\n newState = {\n query,\n selectedMatchIndex,\n matches,\n decorations,\n };\n }\n\n if (tr.docChanged && newState.query) {\n const matches = findMatches(tr.state.doc, newState.query);\n const decorations = createDecorations(matches, newState.selectedMatchIndex);\n\n newState = {\n ...newState,\n matches,\n decorations,\n };\n }\n\n return newState;\n },\n\n provide: (field) => EditorView.decorations.from(field, (state) => state.decorations),\n});\n\nconst searchViewPlugin = ViewPlugin.fromClass(\n class {\n private lastSelectedIndex?: number;\n\n update(update: ViewUpdate) {\n const state = update.state.field(searchField);\n\n if (\n state.selectedMatchIndex !== undefined &&\n state.selectedMatchIndex !== this.lastSelectedIndex\n ) {\n const match = state.matches[state.selectedMatchIndex];\n\n if (match) {\n requestAnimationFrame(() => {\n update.view.dispatch({\n effects: EditorView.scrollIntoView(match.from, { y: 'center' }),\n });\n });\n }\n\n this.lastSelectedIndex = state.selectedMatchIndex;\n }\n\n if (state.selectedMatchIndex === undefined) {\n this.lastSelectedIndex = undefined;\n }\n }\n },\n);\n\n/**\n * Match and current-match fills, per colour scheme.\n *\n * - `&dark` keeps this a static base theme; it applies when the `EditorView.darkTheme` facet is set.\n * - Dark current match uses `neutral[900]` text: white on `blue[500]` is 2.55:1.\n */\nconst searchTheme = EditorView.baseTheme({\n '.cm-searchMatch': {\n backgroundColor: colors.blue[100],\n },\n '.cm-searchMatch > span': {\n color: `${colors.blue[700]} !important`,\n },\n '.cm-searchMatch-selected': {\n backgroundColor: colors.blue[700],\n },\n '.cm-searchMatch-selected > span': {\n color: `${colors.white} !important`,\n },\n\n '&dark .cm-searchMatch': {\n backgroundColor: `${colors.blue[500]}${DARK_LINE_ALPHA}`,\n },\n '&dark .cm-searchMatch > span': {\n color: `${colors.blue[200]} !important`,\n },\n '&dark .cm-searchMatch-selected': {\n backgroundColor: colors.blue[500],\n },\n '&dark .cm-searchMatch-selected > span': {\n color: `${colors.neutral[900]} !important`,\n },\n});\n\nexport function searchExtension() {\n return [searchField, searchViewPlugin, searchTheme];\n}\n\nexport function updateSearch(view: EditorView, query: string, selectedMatchIndex?: number) {\n view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });\n}\n","import { isMac } from '../../utils';\nimport { Kbd } from '../Kbd';\n\nexport const ToggleComponentHelp = () => (\n <div>\n Use <Kbd>{isMac ? 'Command+/' : 'Ctrl+/'}</Kbd> to toggle comments.\n </div>\n);\n","import { type Extension } from '@codemirror/state';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\nimport { useThemeAttributes } from '../ThemeProvider/useThemeAttributes';\n\n// Shared across instances: each theme's StyleModule appends rules to a document-level\n// stylesheet, so one module per theme keeps it constant-size however many editors mount.\nconst themeCache = new Map<string, Extension>();\n\n/**\n * A CodeMirror extension shared per `cacheKey`, rebuilt when the brand or light/dark mode changes.\n *\n * - `build` reads live `--*` values off `<html>`, a dependency no deps array can see.\n * - `scheme` comes from the same read as the key, for values that are a light/dark pair.\n * - `cacheKey` must include everything `build` closes over, or different inputs share a theme.\n */\nexport const useThemedExtension = (\n cacheKey: string,\n build: (scheme: ResolvedColorScheme) => Extension,\n): Extension => {\n const { scheme, cacheKey: themeKey } = useThemeAttributes();\n const key = `${themeKey} ${cacheKey}`;\n\n // Filling the module cache during render is idempotent.\n let cached = themeCache.get(key);\n if (!cached) {\n cached = build(scheme);\n themeCache.set(key, cached);\n }\n\n return cached;\n};\n","import { useMemo } from 'react';\nimport { Compartment, type Extension } from '@codemirror/state';\nimport { tooltips, ViewPlugin } from '@codemirror/view';\n\n// Whether this element becomes the containing block of a `position: fixed` descendant.\n// - Encodes the full CSS rule; `contain` and `will-change` are value lists, matched loosely.\n// - `content-visibility` is left to `crops`, the stronger of the two for our purposes.\nconst establishesFixedContainingBlock = (style: CSSStyleDeclaration) =>\n style.transform !== 'none' ||\n style.translate !== 'none' ||\n style.rotate !== 'none' ||\n style.scale !== 'none' ||\n style.perspective !== 'none' ||\n style.filter !== 'none' ||\n style.backdropFilter !== 'none' ||\n /\\b(paint|layout|strict|content)\\b/.test(style.contain) ||\n /\\b(transform|perspective|filter|contain)\\b/.test(style.willChange);\n\n// Crops even a fixed-position descendant; `content-visibility: auto` implies paint\n// containment without showing it in computed `contain`.\nconst crops = (style: CSSStyleDeclaration) =>\n style.overflowX !== 'visible' ||\n style.overflowY !== 'visible' ||\n style.maskImage !== 'none' ||\n style.contentVisibility !== 'visible' ||\n /\\b(paint|strict|content)\\b/.test(style.contain);\n\n/**\n * Where a tooltip can hang uncropped, or `null` for CodeMirror's default.\n *\n * - Hosts above the outermost cropper.\n * - Stops at the fixed containing block; nothing higher can crop.\n * - `<body>` and `<html>` never count as croppers.\n */\nconst findTooltipHost = (from: HTMLElement) => {\n let outermostCropper: HTMLElement | null = null;\n\n for (let node = from.parentElement; node && node !== document.body; node = node.parentElement) {\n const style = getComputedStyle(node);\n\n if (crops(style)) {\n outermostCropper = node;\n } else if (establishesFixedContainingBlock(style)) {\n return outermostCropper?.parentElement ?? node;\n }\n }\n\n return outermostCropper?.parentElement ?? null;\n};\n\n/**\n * `tooltips()`, re-hosted so the completion popup is never cropped.\n *\n * - Must survive a masked, scrolling `Modal` and kbc-ui's `content-visibility: auto` blocks.\n * - Not `document.body`: the popup would sit behind the modal, which disables pointer events there.\n * - The only tooltip host in either editor: CodeMirror takes the first parent configured.\n */\nconst tooltipsExtension = (): Extension => {\n // A compartment, because a prop-driven full reconfigure drops appended config but keeps compartments.\n const layer = new Compartment();\n\n return [\n layer.of(tooltips()),\n ViewPlugin.define((view) => {\n // Deferred: a plugin cannot dispatch while its view is being built, and reading styles\n // here would force a layout flush mid-commit. One-shot; later ancestor changes are missed.\n const scheduled = setTimeout(() => {\n if (!view.dom.isConnected) return;\n\n const parent = findTooltipHost(view.dom);\n if (parent) view.dispatch({ effects: layer.reconfigure(tooltips({ parent })) });\n });\n\n return { destroy: () => clearTimeout(scheduled) };\n }),\n ];\n};\n\n/**\n * The tooltips extension, built once per editor; a rebuild would drop the resolved host.\n */\nexport const useTooltipsExtension = () => useMemo(tooltipsExtension, []);\n","import type { Completion, CompletionContext, CompletionSource } from '@codemirror/autocomplete';\n\nimport { useStableCallback } from '../../hooks/useStableCallback';\n\nexport type EditorVariable = { name: string; value?: string };\n\n// Ranks variables above the language's many same-prefix keywords.\nconst BOOST = 2000;\n\n// - One brace or two: `closeBrackets` turns a typed `{` into `{}`.\n// - One name charset throughout; a narrower second one would start the range mid-name and never match.\nconst NAME = String.raw`[\\w-]*`;\nconst AT_CARET = new RegExp(String.raw`(?:\\{{1,2} ?)?${NAME}$`);\nconst NAME_AT_END = new RegExp(`${NAME}$`);\nconst OPENING = /\\{{1,2} ?$/;\nconst CLOSING = /^ ?\\}{1,2}/;\n\n/**\n * Completes a mustache-style `{{name}}` placeholder.\n */\nexport const completeVariables = (variables: EditorVariable[] = []): CompletionSource => {\n if (variables.length === 0) return () => null;\n\n const options: Completion[] = variables.map(({ name, value }) => ({\n // Bare name: the only spelling both editors' filters match, braces typed or not.\n label: name,\n displayLabel: `{{${name}}}`,\n detail: value,\n type: 'variable',\n boost: BOOST,\n apply: (view, completion, from, to) => {\n const { doc } = view.state;\n const line = doc.lineAt(from);\n const insert = `{{${completion.label}}}`;\n\n // Braces are found, not assumed: `closeBrackets` may have added a closing one.\n const opening = OPENING.exec(doc.sliceString(line.from, from));\n const closing = CLOSING.exec(doc.sliceString(to, line.to));\n const start = opening ? from - opening[0].length : from;\n const end = closing ? to + closing[0].length : to;\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length },\n });\n },\n }));\n\n return (context: CompletionContext) => {\n const match = context.matchBefore(AT_CARET);\n\n if (!match?.text) return null;\n\n const [name = ''] = NAME_AT_END.exec(match.text) ?? [];\n\n return { from: match.to - name.length, options };\n };\n};\n\n/**\n * The completion source both editors install, with a stable identity.\n *\n * - It keys their extension memo, while callers pass a fresh array on every store push.\n * - CodeMirror asks per request, so it still sees the latest variables.\n */\nexport const useVariableCompletion = (variables: EditorVariable[] = []): CompletionSource =>\n useStableCallback(completeVariables(variables));\n","import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\nimport type { KeyboardEvent, ReactNode } from 'react';\nimport type { CompletionSource } from '@codemirror/autocomplete';\nimport { autocompletion, completeAnyWord } from '@codemirror/autocomplete';\nimport { unifiedMergeView } from '@codemirror/merge';\nimport { EditorView, keymap, placeholder as cmPlaceholder } from '@codemirror/view';\nimport CodeMirror, {\n EditorState,\n type Extension,\n type ReactCodeMirrorRef,\n} from '@uiw/react-codemirror';\n\nimport { keyCodes } from '../../constants/keyCodes';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { cn } from '../../utils';\nimport { HelpBlock } from '../HelpBlock';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { ButtonToolbar } from './ButtonToolbar';\nimport { buildChromeStyles, buildInputChrome } from './editorChrome';\nimport type { LANGUAGE_MODE } from './helpers';\nimport {\n buildBaseThemeStyles,\n buildBasicSetup,\n buildCustomTheme,\n buildJsonLinter,\n getLanguageMode,\n shouldLintJson,\n} from './helpers';\nimport { searchExtension, updateSearch } from './search';\nimport { ToggleComponentHelp } from './ToggleComponentHelp';\nimport { useThemedExtension } from './tokenTheme';\nimport { useTooltipsExtension } from './tooltips';\nimport { type EditorVariable, useVariableCompletion } from './variableCompletion';\n\ntype Props = {\n value: string;\n previousValue?: string;\n /** `'field'`: `InputGroup` chrome, sized to content (don't pin height). `'plain'`: full-bleed panel. */\n variant?: 'plain' | 'field';\n mode?: LANGUAGE_MODE;\n placeholder?: string;\n /** Screen-reader name: the editor has no visible label of its own. */\n ariaLabel?: string;\n /** Prefer over `ariaLabel` inside a form. */\n ariaLabelledBy?: string;\n ariaDescribedBy?: string;\n /** Visual error styling is the caller's (`variant=\"field\"`). */\n ariaInvalid?: boolean;\n ariaRequired?: boolean;\n /** JSON modes: a blank document is not a parse error. Off by default: the mark explains a disabled Save. */\n allowBlankDocument?: boolean;\n /** Bound on CodeMirror's content node (the wrapper is not what gets focused). */\n onBlur?: () => void;\n /** Highlights matches; the find UI is the caller's. Omit both props to skip the search extension. */\n searchQuery?: string;\n searchMatchIndex?: number;\n readOnly?: boolean;\n /** Refuses edits without changing the look, e.g. during a save; `readOnly` makes a greyed viewer. */\n inputLocked?: boolean;\n /** One word per label (a space breaks matching; phrases go in `completionSource`). Pass a stable array. */\n autocompletions?: string[];\n /** Cursor-dependent completions; wins over `autocompletions` / `completeAny`. Memoize it. */\n completionSource?: CompletionSource;\n /** Completed into `{{name}}`, alongside `completionSource`. */\n variables?: EditorVariable[];\n /** `false` silences every source, the language's own included (e.g. shell mode used only for colours). */\n withCompletions?: boolean;\n extraKeys?: Record<string, () => void>;\n withToggleCommentHint?: boolean;\n withAutofocus?: boolean;\n withLineNumbers?: boolean;\n withLineWrapping?: boolean;\n withCollapseUnchanged?: boolean;\n withCopyButton?: boolean;\n completeAny?: boolean;\n help?: ReactNode;\n helpPostfix?: ReactNode;\n /** Toolbar actions beside the copy button; pass `size=\"icon-xs\"` buttons to fit the 28px chip. */\n renderAdditionalButtons?: (value?: string) => ReactNode;\n className?: string;\n} & (\n | { readOnly: true; onChange?: never }\n // `boolean`, not `false`: a permission-locked field still needs its handler when editable.\n | { readOnly?: boolean; onChange: (value: string) => void }\n);\n\nconst emptyObject = {};\n\nexport const CodeEditor = ({\n value,\n previousValue,\n onChange,\n variant = 'plain',\n mode = 'application/json',\n placeholder = '',\n ariaLabel,\n ariaLabelledBy,\n ariaDescribedBy,\n ariaInvalid,\n ariaRequired,\n allowBlankDocument = false,\n onBlur,\n searchQuery,\n searchMatchIndex,\n readOnly = false,\n inputLocked = false,\n autocompletions,\n completionSource,\n variables,\n withCompletions = true,\n extraKeys = emptyObject,\n withToggleCommentHint = false,\n withAutofocus = false,\n withLineNumbers = true,\n withLineWrapping = true,\n withCollapseUnchanged = false,\n withCopyButton = false,\n completeAny = false,\n help = null,\n helpPostfix = null,\n renderAdditionalButtons,\n className,\n}: Props) => {\n // A new handler identity rebuilds CodeMirror's extension tree; callers pass inline arrows.\n const handleChange = useStableCallback((next: string) => onChange?.(next));\n const handleBlur = useStableCallback(() => onBlur?.());\n\n // Presence, not truthiness, keeps the extension set stable while the query changes.\n const withSearch = searchQuery !== undefined;\n const withBlur = onBlur !== undefined;\n const editorRef = useRef<ReactCodeMirrorRef>(null);\n\n // `null` when empty, so the extension is left out.\n const contentAria = useMemo(() => {\n const attributes: Record<string, string> = {};\n if (ariaLabel !== undefined) attributes['aria-label'] = ariaLabel;\n if (ariaLabelledBy !== undefined) attributes['aria-labelledby'] = ariaLabelledBy;\n if (ariaDescribedBy !== undefined) attributes['aria-describedby'] = ariaDescribedBy;\n // Stringified: `contentAttributes` would drop a boolean `false`.\n if (ariaInvalid !== undefined) attributes['aria-invalid'] = String(ariaInvalid);\n if (ariaRequired !== undefined) attributes['aria-required'] = String(ariaRequired);\n return Object.keys(attributes).length > 0 ? attributes : null;\n }, [ariaLabel, ariaLabelledBy, ariaDescribedBy, ariaInvalid, ariaRequired]);\n\n useEffect(() => {\n const view = editorRef.current?.view;\n if (view && withSearch) updateSearch(view, searchQuery, searchMatchIndex);\n }, [withSearch, searchQuery, searchMatchIndex]);\n\n // A view created with a query already set (remount, tab switch) needs it applied on build.\n const handleCreateEditor = useStableCallback((view: EditorView) => {\n if (searchQuery) updateSearch(view, searchQuery, searchMatchIndex);\n });\n\n // Callers pass this inline; only the key set rebuilds the keymap, handlers are read on press.\n const extraKeysRef = useRef(extraKeys);\n useLayoutEffect(() => {\n extraKeysRef.current = extraKeys;\n });\n\n const boundKeysSignature = Object.keys(extraKeys).join('\\n');\n const boundKeys = useMemo(\n () => boundKeysSignature.split('\\n').filter(Boolean),\n [boundKeysSignature],\n );\n\n const tooltipLayer = useTooltipsExtension();\n\n // Built here, not inside `languageData.of`, which runs per completion request.\n const variableCompletion = useVariableCompletion(variables);\n\n // Key has no component prefix: shared with `SqlEditor`.\n const customTheme = useThemedExtension('editor:syntax', buildCustomTheme);\n\n // The brand is in the cache key: `useThemedExtension` caches per key and tracks only `<html>`.\n const isArgo = useArgoDesign();\n const isField = variant === 'field';\n const baseTheme = useThemedExtension(\n isField ? `code-editor:field:${isArgo ? 'argo' : 'legacy'}` : 'code-editor:chrome',\n (scheme) =>\n // `dark` activates every `&dark` rule (ours and CodeMirror's); set here so swapping the\n // github palette in `buildCustomTheme` cannot turn them off.\n EditorView.theme(\n {\n ...buildBaseThemeStyles(scheme),\n ...(isField ? buildChromeStyles(buildInputChrome(isArgo)) : null),\n },\n { dark: scheme === 'dark' },\n ),\n );\n\n const commonExtensions: Extension[] = useMemo(() => {\n const callerCompletions =\n completionSource ??\n (completeAny ? completeAnyWord : autocompletions?.length ? autocompletions : null);\n\n // An empty list is left out, or CodeMirror runs a never-matching source on every keystroke.\n const completionEntries = [\n ...(callerCompletions ? [{ autocomplete: callerCompletions }] : []),\n { autocomplete: variableCompletion },\n ];\n\n return [\n getLanguageMode(mode),\n shouldLintJson(mode, readOnly) ? buildJsonLinter(allowBlankDocument) : [],\n withLineWrapping ? EditorView.lineWrapping : [],\n EditorState.languageData.of(() => completionEntries),\n keymap.of(\n boundKeys.map((key) => ({\n key,\n run: () => {\n extraKeysRef.current[key]?.();\n return true;\n },\n })),\n ),\n readOnly || !withCompletions\n ? []\n : [\n // The only `autocompletion()` (`buildBasicSetup` disables basicSetup's). Not gated on\n // the completion props, so the language's own vocabulary still completes.\n autocompletion(),\n ],\n // On the focused content node (`div[role=\"textbox\"]`), not the wrapper.\n contentAria ? EditorView.contentAttributes.of(contentAria) : [],\n withBlur ? EditorView.domEventHandlers({ blur: handleBlur }) : [],\n withSearch ? searchExtension() : [],\n tooltipLayer,\n baseTheme,\n ];\n }, [\n autocompletions,\n completionSource,\n variableCompletion,\n completeAny,\n withCompletions,\n boundKeys,\n mode,\n readOnly,\n allowBlankDocument,\n withLineWrapping,\n baseTheme,\n contentAria,\n withBlur,\n handleBlur,\n withSearch,\n tooltipLayer,\n ]);\n\n const extensions = useMemo(() => {\n return [\n ...commonExtensions,\n cmPlaceholder(placeholder),\n EditorView.editable.of(!readOnly),\n // The lock is only this facet: `contenteditable` drives the read-only wash and `basicSetup`\n // holds the undo history, so neither is reconfigured.\n EditorState.readOnly.of(readOnly || inputLocked),\n previousValue\n ? unifiedMergeView({\n original: previousValue,\n mergeControls: false,\n highlightChanges: false,\n collapseUnchanged: withCollapseUnchanged ? {} : undefined,\n })\n : [],\n ];\n }, [commonExtensions, placeholder, readOnly, inputLocked, previousValue, withCollapseUnchanged]);\n\n const config = useMemo(() => {\n return {\n ...buildBasicSetup(readOnly),\n lineNumbers: withLineNumbers,\n // Mod-f would open CodeMirror's own search panel beside the caller's.\n ...(withSearch ? { searchKeymap: false } : null),\n };\n }, [withLineNumbers, readOnly, withSearch]);\n\n return (\n // oxlint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n data-variant={variant}\n className={cn(\n // Scoped to CodeMirror's box so the toolbar needn't undo it with `!important`.\n 'tw:relative tw:flex tw:min-h-0 tw:flex-col tw:[&_.cm-mergeViewEditor]:overflow-visible tw:[&_.cm-mergeViewEditors]:h-full tw:[&_.cm-mergeView]:h-full tw:[&_>.cm-theme]:h-full',\n // Field: transparent so square corners don't show; visible so the focus ring isn't cropped.\n isField\n ? 'tw:[&_>.cm-theme]:overflow-visible tw:[&_>.cm-theme]:bg-transparent'\n : 'tw:[&_>.cm-theme]:overflow-auto tw:[&_>.cm-theme]:bg-background',\n className,\n )}\n onKeyDown={(event: KeyboardEvent) => {\n if (event.key === keyCodes.ESCAPE) {\n event.stopPropagation();\n }\n }}\n >\n <ButtonToolbar value={withCopyButton ? value : undefined}>\n {renderAdditionalButtons?.(value)}\n </ButtonToolbar>\n <CodeMirror\n ref={editorRef}\n onCreateEditor={handleCreateEditor}\n theme={customTheme}\n value={value}\n onChange={handleChange}\n extensions={extensions}\n autoFocus={withAutofocus}\n basicSetup={config}\n />\n {!readOnly && (withToggleCommentHint || help || helpPostfix) && (\n <HelpBlock className=\"tw:mt-2 tw:flex tw:flex-wrap tw:gap-1\">\n {help}\n {withToggleCommentHint ? <ToggleComponentHelp /> : null}\n {helpPostfix}\n </HelpBlock>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CodeEditor-BfRSCKEs.js","names":["cmPlaceholder","placeholder"],"sources":["../src/components/CodeEditor/ButtonToolbar.tsx","../src/components/CodeEditor/modes/dbt.ts","../src/components/CodeEditor/modes/jsonnet.ts","../src/components/CodeEditor/diffWash.ts","../src/components/CodeEditor/syntaxPalette.ts","../src/components/CodeEditor/helpers.ts","../src/components/CodeEditor/editorChrome.ts","../src/components/CodeEditor/search.ts","../src/components/CodeEditor/ToggleComponentHelp.tsx","../src/components/CodeEditor/tokenTheme.ts","../src/components/CodeEditor/tooltips.ts","../src/components/CodeEditor/variableCompletion.ts","../src/components/CodeEditor/CodeEditor.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { ClipboardButton } from '../../blocks/ClipboardButton';\n\n// Floats over the top-right corner of the editor it is rendered into — private to\n// `CodeEditor`, which is the `relative` ancestor it positions against. `right-3`\n// leaves room for the scrollbar track, whose width the browser owns and no token\n// here describes.\nexport const ButtonToolbar = ({ value, children }: { value?: string; children?: ReactNode }) => {\n if (!value && !children) return null;\n\n return (\n <div className=\"tw:absolute tw:right-3 tw:top-1 tw:z-10 tw:flex tw:gap-0.5 tw:overflow-visible tw:rounded tw:border tw:border-solid tw:border-border tw:!bg-background tw:p-px tw:shadow-sm\">\n {!!value && <ClipboardButton size=\"icon-xs\" variant=\"invisible\" text={value} />}\n {children}\n </div>\n );\n};\n","import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';\nimport { simpleMode } from '@codemirror/legacy-modes/mode/simple-mode';\n\n// A dbt step is `dbt <command> [<subcommand>] [arguments, flags and selectors]`,\n// and the vocabulary below is grouped by the slot it belongs to — both to colour\n// it and to decide what is worth offering where.\nconst COMMANDS = [\n 'run-operation',\n 'run',\n 'test',\n 'seed',\n 'snapshot',\n 'list',\n 'ls',\n 'compile',\n 'build',\n 'deps',\n 'docs',\n 'source',\n];\nconst SUBCOMMANDS: Record<string, string[]> = { docs: ['generate'], source: ['freshness'] };\nconst ARGUMENTS = ['--select', '--exclude', '--selector', '--defer', '--resource-type', '-s'];\n// The arguments whose value is a graph selector, and so the only ones a selector\n// method has anything to attach to.\nconst SELECTORS = ['--select', '--exclude', '-s'];\nconst METHODS = [\n 'path:',\n 'source:',\n 'tag:',\n 'package:',\n 'config:',\n 'test_type:',\n 'test_name:',\n 'state:',\n 'exposure:',\n 'metric:',\n 'result:',\n 'source_status:',\n 'column_name:',\n];\nconst FLAGS = [\n '--fail-fast',\n '--warn-error',\n '--favor-state',\n '--vars',\n '--models',\n '--threads',\n '--profiles-dir',\n '--profile',\n '--full-refresh',\n];\n\n// A subcommand only ever highlights together with its command, so `dbt docs` stays\n// unpainted until `generate` follows it.\nconst COMMAND_PHRASES = COMMANDS.flatMap((command) => {\n const subcommands = SUBCOMMANDS[command];\n\n return subcommands ? subcommands.map((subcommand) => `${command} ${subcommand}`) : [command];\n});\n\n// Alternation is first-match, so a word that prefixes another has to come first\n// (`run-operation` before `run`, `--profiles-dir` before `--profile`). Sorting by\n// length keeps that true however the lists above are written.\nconst alternation = (list: string[]) => [...list].sort((a, b) => b.length - a.length).join('|');\n\n// Every keyword follows whitespace, so the leading run is part of the match.\n// Commands and arguments end on a word boundary; methods and flags carry their\n// own terminator (`:`) or need none.\nconst word = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})\\\\b`, 'i');\nconst prefix = (list: string[]) => new RegExp(`^\\\\s+(?:${alternation(list)})`, 'i');\n\n// The word being completed: letters, digits, `_`, `-` and the `:` a selector\n// method ends with. Whitespace stays out of it, so a two-word label like `docs\n// generate` cannot stretch the match back across the words before the cursor.\nconst WORD = /[\\w:-]*$/;\n\nconst asOptions = (list: string[], type: string): Completion[] =>\n list.map((label) => ({ label, type }));\n\n// `type` drives the popup icon, so each group carries the one that matches the\n// colour the mode paints it in.\nconst DBT: Completion[] = [{ label: 'dbt', type: 'keyword' }];\nconst COMMAND_OPTIONS = asOptions(COMMANDS, 'keyword');\nconst SUBCOMMAND_OPTIONS: Record<string, Completion[]> = Object.fromEntries(\n Object.entries(SUBCOMMANDS).map(([command, subcommands]) => [\n command,\n asOptions(subcommands, 'keyword'),\n ]),\n);\nconst ARGUMENT_OPTIONS = asOptions(ARGUMENTS, 'variable');\nconst FLAG_OPTIONS = asOptions(FLAGS, 'constant');\nconst METHOD_OPTIONS = asOptions(METHODS, 'property');\n\n// Which slice of the vocabulary the cursor's slot can hold, given the words\n// already finished ahead of it. Offering the whole vocabulary everywhere proposes\n// `dbt` mid-command and a selector method with no selector to attach to.\nconst optionsAfter = (words: string[]): Completion[] => {\n const [step, command, ...rest] = words;\n\n if (step === undefined) return DBT;\n if (step.toLowerCase() !== 'dbt') return [];\n if (command === undefined) return COMMAND_OPTIONS;\n\n const subcommands = SUBCOMMAND_OPTIONS[command.toLowerCase()];\n if (subcommands && rest.length === 0) return subcommands;\n\n // A selector argument takes any number of space-separated values, so what\n // decides the slot is the last argument, not whether a selector appeared at all:\n // `--select tag:a tag:b` keeps offering methods, `--select a --profile p` stops.\n const lastArgument = rest.filter((it) => it.startsWith('-')).at(-1);\n const selecting = lastArgument !== undefined && SELECTORS.includes(lastArgument.toLowerCase());\n\n return selecting\n ? [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS, ...METHOD_OPTIONS]\n : [...ARGUMENT_OPTIONS, ...FLAG_OPTIONS];\n};\n\nconst complete = (context: CompletionContext): CompletionResult | null => {\n const typed = context.matchBefore(WORD);\n\n // `WORD` also matches the empty string, so without this the popup would open on\n // every space. Asking for completions explicitly still opens it there.\n if (!typed?.text && !context.explicit) return null;\n\n const from = typed?.from ?? context.pos;\n const line = context.state.doc.lineAt(from);\n const options = optionsAfter(\n line.text\n .slice(0, from - line.from)\n .split(/\\s+/)\n .filter(Boolean),\n );\n\n return options.length > 0 ? { from, options, validFor: WORD } : null;\n};\n\nexport const dbt = simpleMode({\n languageData: {\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n commentTokens: { line: '--', block: { open: '/*', close: '*/' } },\n autocomplete: complete,\n },\n start: [\n { regex: /\"(?:[^\\\\]|\\\\.)*?(?:\"|$)/, token: 'string' },\n // Word-bounded, so `dbtX` is not a dbt step whose first word happens to\n // colour — the same thing the completion source asks of it.\n { regex: /dbt\\b/, token: 'keyword', sol: true },\n { regex: word(COMMAND_PHRASES), token: 'keyword' },\n { regex: word(ARGUMENTS), token: 'variableName' },\n { regex: prefix(METHODS), token: 'propertyName' },\n { regex: prefix(FLAGS), token: 'attributeName' },\n { regex: /(?:@|\\*|,|\\+\\d+|\\d+\\+|\\+)/, token: 'operator' },\n { regex: /'.*'/, token: 'string' },\n { regex: /true|false/, token: 'atom' },\n ],\n});\n","import type { StreamParser } from '@codemirror/language';\n\n/**\n * Port of google/codemirror-mode-jsonnet (Apache-2.0) to CodeMirror 6 tags.\n *\n * - Patterns are anchored with `^`: unanchored, `StringStream.match` scans the whole rest of the line.\n */\n\nconst COMMENT_END = /^\\*\\//;\nconst COMMENT_START = /^\\/\\/|^#/;\nconst C_COMMENT_START = /^\\/\\*/;\nconst TEXT_BLOCK = /^\\|\\|\\|/;\nconst TEXT_BLOCK_END = /^\\s*\\|\\|\\|/;\nconst RAW_DOUBLE = /^\"\"/;\nconst RAW_SINGLE = /^''/;\nconst CLOSE_DOUBLE = /^\"/;\nconst CLOSE_SINGLE = /^'/;\nconst ESCAPE = /^\\\\[\\\\\"'/bfnrt0]/;\nconst UNICODE_ESCAPE = /^\\\\u[0-9a-fA-F]{4}/;\nconst BACKSLASH = /^\\\\/;\nconst IMPORT = /^import(?:str)?\\s*(@?)([\"'])/;\nconst QUOTE = /^(@?)([\"'])/;\nconst ROOT = /^\\$/;\nconst NUMBER = /^(?:\\.\\d+|\\d+\\.?\\d*)(?:e[-+]?\\d+)?/i;\nconst OPERATOR = /^[-+/*=<>!&~^|$%]+/;\nconst IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*/;\n\nconst KEYWORDS: Record<string, 'keyword' | 'atom'> = {\n local: 'keyword',\n self: 'keyword',\n super: 'keyword',\n assert: 'keyword',\n function: 'keyword',\n if: 'keyword',\n then: 'keyword',\n else: 'keyword',\n for: 'keyword',\n in: 'keyword',\n tailstrict: 'keyword',\n error: 'keyword',\n true: 'atom',\n false: 'atom',\n null: 'atom',\n};\n\ntype State = {\n cComment: boolean;\n textBlock: boolean;\n textBlockIndent: number | null;\n string: boolean;\n importString: boolean;\n stringSingle: boolean;\n stringRaw: boolean;\n};\n\nexport const jsonnet: StreamParser<State> = {\n name: 'jsonnet',\n\n // `toggleComment` is a no-op without these, so Mod-/ silently does nothing.\n languageData: { commentTokens: { line: '//', block: { open: '/*', close: '*/' } } },\n\n startState: () => ({\n cComment: false,\n textBlock: false,\n textBlockIndent: null,\n string: false,\n importString: false,\n stringSingle: false,\n stringRaw: false,\n }),\n\n token: (stream, state) => {\n if (state.cComment) {\n if (stream.match(COMMENT_END)) {\n state.cComment = false;\n return 'comment';\n }\n stream.next();\n return 'comment';\n }\n\n // Match the closing `|||` before measuring indent, or a block closed at column 0 never ends.\n if (state.textBlock) {\n if (state.textBlockIndent == null) {\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n state.textBlockIndent = stream.indentation();\n }\n if (stream.indentation() >= state.textBlockIndent) {\n stream.skipToEnd();\n return 'string';\n }\n if (stream.match(TEXT_BLOCK_END)) {\n state.textBlock = false;\n return 'string';\n }\n stream.next();\n return 'invalid';\n }\n\n if (state.string || state.importString) {\n const style = state.string ? 'string' : 'meta';\n\n if (state.stringRaw) {\n if (stream.match(state.stringSingle ? RAW_SINGLE : RAW_DOUBLE)) return 'escape';\n } else {\n if (stream.match(ESCAPE)) return 'escape';\n if (stream.match(UNICODE_ESCAPE)) return 'escape';\n if (stream.match(BACKSLASH)) return 'invalid';\n }\n\n if (stream.match(state.stringSingle ? CLOSE_SINGLE : CLOSE_DOUBLE)) {\n state.string = false;\n state.importString = false;\n return style;\n }\n\n stream.next();\n return style;\n }\n\n if (stream.match(COMMENT_START)) {\n stream.skipToEnd();\n return 'comment';\n }\n if (stream.match(C_COMMENT_START)) {\n state.cComment = true;\n return 'comment';\n }\n\n const imported = stream.match(IMPORT);\n if (Array.isArray(imported)) {\n state.importString = true;\n state.stringRaw = imported[1] === '@';\n state.stringSingle = imported[2] === \"'\";\n return 'meta';\n }\n\n const quoted = stream.match(QUOTE);\n if (Array.isArray(quoted)) {\n state.string = true;\n state.stringRaw = quoted[1] === '@';\n state.stringSingle = quoted[2] === \"'\";\n return 'string';\n }\n\n if (stream.match(TEXT_BLOCK)) {\n state.textBlock = true;\n state.textBlockIndent = null;\n return 'string';\n }\n\n if (stream.match(ROOT)) return 'keyword';\n if (stream.match(NUMBER)) return 'number';\n if (stream.match(OPERATOR)) return 'operator';\n\n // Consumed whole so that a keyword's prefix (`locally`) is not styled.\n const identifier = stream.match(IDENTIFIER);\n if (Array.isArray(identifier)) return KEYWORDS[identifier[0]] ?? null;\n\n stream.next();\n return null;\n },\n};\n","import type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * Alpha suffixes for the dark-scheme diff and state tints.\n *\n * - Line fill stays subtle for text to read; the gutter sits a step stronger.\n * - `DARK_LINE_ALPHA` is also appended by the static washes in `highlighting.ts` and `search.ts`.\n */\nexport const DARK_LINE_ALPHA = '29'; /* 16% */\nconst DARK_GUTTER_ALPHA = '47'; /* 28% */\n\n/**\n * The two diff fills per scheme: light uses the opaque pastel, dark the `500` hue at low alpha.\n *\n * - Imports nothing, so `MergeEditor` shares it without pulling in CodeMirror via `helpers.ts`.\n * - Shared by `helpers.ts` and `MergeEditor/decorations.ts`, so their alphas cannot drift.\n */\nexport const buildDiffWash = (scheme: ResolvedColorScheme) => {\n const dark = scheme === 'dark';\n\n return {\n line: (hue: string, pastel: string) => (dark ? `${hue}${DARK_LINE_ALPHA}` : pastel),\n gutter: (hue: string, pastel: string) => (dark ? `${hue}${DARK_GUTTER_ALPHA}` : pastel),\n };\n};\n","import { tags } from '@lezer/highlight';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\n/**\n * The tag colours layered over the stock github palette, per colour scheme.\n *\n * - Imports only tags and ramps, so `scripts/contrast-audit.ts` can measure it.\n * - These override stock rules for the same tag.\n * - Colours are chosen against `background` and `muted` (`variant=\"field\"`); ratios quote both.\n */\nexport const buildSyntaxPalette = (scheme: ResolvedColorScheme, foreground: string) => {\n const dark = scheme === 'dark';\n\n return [\n // Identifiers and brackets carry no colour, as on github.com.\n { tag: [tags.name, tags.special(tags.string), tags.bracket], color: foreground },\n // Functions — light `600` 6.13 / 5.84, dark `300` 9.62 / 7.80.\n { tag: tags.standard(tags.name), color: dark ? colors.purple[300] : colors.purple[600] },\n // Special vars — light `800` 7.26 / 6.92, dark `300` 13.49 / 10.94.\n { tag: tags.special(tags.name), color: dark ? colors.cyan[300] : colors.cyan[800] },\n // Strings — light `800` 7.23 / 6.89, dark `300` 13.53 / 10.97.\n { tag: tags.string, color: dark ? colors.warning[300] : colors.warning[800] },\n // Light-only fixes for stock colours below AA; `CONTRAST-AUDIT.md` has all surfaces.\n ...(dark\n ? []\n : [\n // Keywords — 5.96 / 5.69.\n { tag: [tags.keyword, tags.typeName, tags.typeOperator], color: colors.error[550] },\n // Comments — 6.44 / 6.15.\n { tag: tags.comment, color: colors.neutral[500] },\n // Markdown quotes — 7.15 / 6.82.\n { tag: tags.quote, color: colors.green[900] },\n // Lex errors — 7.81 / 7.45; stock red fails the read-only wash.\n { tag: tags.invalid, color: colors.error[700] },\n ]),\n // Dark only: `githubDarkStyle` has no `escape` rule, so escapes would blend into strings.\n ...(dark ? [{ tag: [tags.escape, tags.url, tags.link], color: colors.blue[300] }] : []),\n ];\n};\n","import { javascript } from '@codemirror/lang-javascript';\nimport { json, jsonParseLinter } from '@codemirror/lang-json';\nimport { python } from '@codemirror/lang-python';\nimport { MSSQL, MySQL, PLSQL, PostgreSQL, StandardSQL } from '@codemirror/lang-sql';\nimport { StreamLanguage } from '@codemirror/language';\nimport { r } from '@codemirror/legacy-modes/mode/r';\nimport { shell } from '@codemirror/legacy-modes/mode/shell';\nimport { toml } from '@codemirror/legacy-modes/mode/toml';\nimport type { LintSource } from '@codemirror/lint';\nimport { linter } from '@codemirror/lint';\nimport { githubDarkInit, githubLightInit } from '@uiw/codemirror-theme-github';\nimport type { BasicSetupOptions } from '@uiw/react-codemirror';\n\nimport { getSqlLanguageSupport } from '@keboola/codemirror-lang-sql';\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { resolveToken } from '../../utils/themeTokens';\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\n\nimport { dbt } from './modes/dbt';\nimport { jsonnet } from './modes/jsonnet';\nimport { buildDiffWash } from './diffWash';\nimport { buildSyntaxPalette } from './syntaxPalette';\n\n// One list for both the runtime whitelist and the type — a separate `LANGUAGE_MODE[]` copy drifts.\nexport const LANGUAGE_MODES = [\n 'application/json',\n 'text/plain',\n 'text/x-python',\n 'text/x-sql',\n 'text/x-mysql',\n 'text/x-pgsql',\n 'text/x-mssql',\n // Snowflake; the strings are a published prop contract.\n 'text/x-sfsql',\n 'text/x-bqsql',\n 'text/x-plsql',\n 'text/x-rsrc',\n 'text/x-sh',\n 'text/x-toml',\n 'text/jsonnet',\n 'text/x-dbt',\n 'text/javascript',\n 'text/typescript',\n] as const;\n\nexport type LANGUAGE_MODE = (typeof LANGUAGE_MODES)[number];\n\nexport const isLanguageMode = (mode: string): mode is LANGUAGE_MODE =>\n (LANGUAGE_MODES as readonly string[]).includes(mode);\n\n// - `readOnly` is only addressable through `contenteditable`.\n// - `fieldChrome` overrides the read-only wash by re-declaring this key; strings must match exactly.\nexport const READ_ONLY_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"false\"])';\nexport const EDITABLE_EDITOR = '&.cm-editor:has(.cm-content[contenteditable=\"true\"])';\n\n/**\n * Editor chrome and the unified merge (diff) wash.\n *\n * - Chrome resolves from live `--*` tokens; fallbacks mirror light-mode values for SSR.\n * - Diff colours are fixed across brands; light/dark pairs from `buildDiffWash`, shared with\n * `MergeEditor/decorations.ts`.\n * - Only `CodeEditor`'s unified merge view uses this; `MergePane` has its own theme.\n */\nexport const buildBaseThemeStyles = (scheme: ResolvedColorScheme) => {\n const { line, gutter } = buildDiffWash(scheme);\n const dark = scheme === 'dark';\n\n return {\n '*': { lineHeight: '20px' },\n '*::selection': {\n backgroundColor: resolveToken('primary', '31 143 255'),\n color: `${resolveToken('primary-foreground', '255 255 255')} !important`,\n },\n // Dark uses `muted`: `secondary` is lighter there and drops `comment` to 4.27:1.\n // `--code-editor-surface` on an ancestor overrides body and gutters.\n [READ_ONLY_EDITOR]: {\n backgroundColor: `var(--code-editor-surface, ${\n dark ? resolveToken('muted', '38 38 45') : resolveToken('secondary', '226 232 240')\n })`,\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: {\n backgroundColor: `var(--code-editor-surface, ${resolveToken('border', '229 231 235')})`,\n },\n '&.cm-editor .cm-scroller': { overflowAnchor: 'none' },\n '&.cm-editor, &.cm-editor .cm-scroller': {\n minHeight: '100%',\n flexGrow: 1,\n alignItems: 'stretch !important',\n outline: 'none',\n },\n '.cm-gutter.cm-foldGutter': { display: 'none !important' },\n '.cm-gutter.cm-lineNumbers': { paddingLeft: '20px', paddingRight: '6px' },\n '.cm-gutters': { height: 'auto' },\n\n // merge (diff) view\n '&[class*=\"cm-merge-\"] .cm-deletedLine': {\n backgroundColor: line(colors.error[500], colors.error[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLine': {\n backgroundColor: line(colors.green[500], colors.green[100]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedLineGutter': {\n backgroundColor: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedLineGutter': {\n backgroundColor: gutter(colors.green[500], colors.green[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-deletedText': {\n background: gutter(colors.error[500], colors.error[200]),\n },\n '&[class*=\"cm-merge-\"] .cm-changedText': {\n background: gutter(colors.green[500], colors.green[200]),\n },\n // Follows the page, not the diff — fixed white would be a light slab under dark.\n '&[class*=\"cm-merge-\"]': {\n backgroundColor: `${resolveToken('background', '249 250 251')} !important`,\n },\n '&[class*=\"cm-merge-\"] .cm-gutters': {\n backgroundColor: `${resolveToken('muted', '241 245 249')} !important`,\n },\n '.cm-changeGutter': { position: 'absolute', zIndex: -1, width: '100%', paddingLeft: 0 },\n '&[class*=\"cm-merge-\"] .cm-changedLine,&[class*=\"cm-merge-\"] .cm-line, &[class*=\"cm-merge-\"] .cm-deletedChunk':\n { paddingLeft: 0 },\n };\n};\n\n// - Fold gutter and active line are hidden by the themes anyway.\n// - `autocompletion`: `CodeEditor` and `SqlEditor` install their own; a second instance competes.\nconst ALWAYS_OFF = {\n autocompletion: false,\n drawSelection: false,\n foldGutter: false,\n foldKeymap: false,\n highlightActiveLine: false,\n highlightActiveLineGutter: false,\n} as const;\n\n// - `basicSetup` enables everything not skipped; a viewer drops editing commands.\n// - Search stays — Mod-f is useful on a viewer.\n// - `history` stays: flipping `readOnly` reconfigures the view, which would drop the undo stack.\nexport const buildBasicSetup = (readOnly: boolean): BasicSetupOptions => ({\n ...ALWAYS_OFF,\n ...(readOnly\n ? {\n closeBrackets: false,\n closeBracketsKeymap: false,\n lintKeymap: false,\n indentOnInput: false,\n rectangularSelection: false,\n dropCursor: false,\n highlightSelectionMatches: false,\n }\n : null),\n});\n\n/**\n * The syntax theme, per colour scheme.\n *\n * - Light github palette fails AA on dark surfaces, so the palette is picked by scheme.\n * - `githubDarkInit` sets the `EditorView.darkTheme` facet that every `&dark` rule keys off.\n * - `caret` and `selectionMatch` are pinned: the initialisers disagree on them.\n */\nexport const buildCustomTheme = (scheme: ResolvedColorScheme) => {\n const foreground = resolveToken('foreground', '30 41 59');\n const init = scheme === 'dark' ? githubDarkInit : githubLightInit;\n\n return init({\n settings: {\n fontFamily: `'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New'`,\n background: resolveToken('background', '249 250 251'),\n foreground,\n caret: foreground,\n gutterBackground: resolveToken('muted', '241 245 249'),\n gutterForeground: resolveToken('muted-foreground', '100 116 139'),\n gutterBorder: 'transparent',\n lineHighlight: 'transparent',\n selection: resolveToken('primary', '31 143 255'),\n selectionMatch: resolveToken('primary', '31 143 255', 0.1),\n },\n styles: buildSyntaxPalette(scheme, foreground),\n });\n};\n\nexport const getLanguageMode = (mode?: LANGUAGE_MODE) => {\n switch (mode) {\n case undefined:\n case 'application/json':\n return json();\n case 'text/x-python':\n return python();\n case 'text/x-sql':\n return getSqlLanguageSupport(StandardSQL);\n case 'text/x-mysql':\n return getSqlLanguageSupport(MySQL);\n case 'text/x-pgsql':\n return getSqlLanguageSupport(PostgreSQL);\n case 'text/x-mssql':\n return getSqlLanguageSupport(MSSQL);\n case 'text/x-sfsql':\n return getSqlLanguageSupport('snowflake');\n case 'text/x-bqsql':\n return getSqlLanguageSupport('bigquery');\n case 'text/x-plsql':\n return getSqlLanguageSupport(PLSQL);\n case 'text/x-rsrc':\n return StreamLanguage.define(r);\n case 'text/x-sh':\n return StreamLanguage.define(shell);\n case 'text/x-toml':\n return StreamLanguage.define(toml);\n case 'text/jsonnet':\n return StreamLanguage.define(jsonnet);\n case 'text/x-dbt':\n return StreamLanguage.define(dbt);\n case 'text/javascript':\n return javascript({ jsx: true });\n case 'text/typescript':\n return javascript({ jsx: true, typescript: true });\n // `text/plain` and any unmapped mode: unstyled, not coloured as JSON.\n default:\n return [];\n }\n};\n\n// A read-only editor can't act on lint errors; its underlines are noise.\nexport const shouldLintJson = (mode: LANGUAGE_MODE | undefined, readOnly: boolean): boolean =>\n mode === 'application/json' && !readOnly;\n\n/**\n * Wraps a lint source so a blank document produces no diagnostics.\n *\n * - For optional fields, where empty is valid but `jsonParseLinter` reports an error.\n */\nexport const skipBlankDocument =\n (source: LintSource): LintSource =>\n (view) =>\n view.state.doc.toString().trim() === '' ? [] : source(view);\n\n/**\n * The JSON linter, optionally blind to a blank document.\n *\n * - Opt-in: some callers rely on the marker alone to explain why empty disables their button.\n * - Not derivable from `variant` — whether blank is valid is the field's contract.\n */\nexport const buildJsonLinter = (allowBlankDocument: boolean) => {\n const source = jsonParseLinter();\n\n return linter(allowBlankDocument ? skipBlankDocument(source) : source);\n};\n","import { resolveToken } from '../../utils/themeTokens';\n\nimport { EDITABLE_EDITOR, READ_ONLY_EDITOR } from './helpers';\n\n/** Per-preset parts of an editor's outer chrome, mapped to selectors by `buildChromeStyles`. */\nexport type EditorChrome = {\n surface: string;\n borderColor: string;\n readOnlySurface: string;\n readOnlyBorderColor: string;\n /** `null`: no hover affordance (form inputs). */\n hoverBorderColor: string | null;\n focusBorderColor: string;\n focusRing: string;\n radius: string;\n paddingY: string;\n /** `null` leaves CodeMirror's own 6px/2px line inset alone. */\n paddingX: { left: string; right: string } | null;\n};\n\n/**\n * Mirrors `InputGroup` at each design language's `TextInput` sizing, so it reads as a form field.\n *\n * - Same colour-scheme tokens as `InputGroup`, so it follows light/dark.\n * - argo: `muted`/`input`, the editable argo field's pair.\n * - legacy: `secondary` as `variant=\"secondary\"`; readonly `muted`/`input` as base `InputGroup`.\n */\nexport const buildInputChrome = (isArgo: boolean): EditorChrome => {\n return {\n surface: isArgo\n ? resolveToken('muted', '241 245 249')\n : resolveToken('secondary', '226 232 240'),\n borderColor: isArgo\n ? resolveToken('input', '203 213 225')\n : resolveToken('secondary', '226 232 240'),\n readOnlySurface: resolveToken('muted', '241 245 249'),\n readOnlyBorderColor: resolveToken('input', '203 213 225'),\n hoverBorderColor: null,\n focusBorderColor: isArgo\n ? resolveToken('primary', '37 99 235')\n : resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', isArgo ? 0.5 : 0.3)}`,\n radius: isArgo ? 'var(--radius-lg, 0.25rem)' : '0.25rem',\n // 2px border + 2×this + `.cm-content`'s 4px + 20px line = a one-line `TextInput`:\n // argo `medium` (36px), legacy `default` (40px).\n paddingY: isArgo ? '3px' : '5px',\n // Tops `.cm-line`'s 6px/2px up to an input's 16px text inset.\n paddingX: { left: '10px', right: '14px' },\n };\n};\n\n/** The SQL workspace's notebook cell: a white canvas, not a form control. */\nexport const buildCanvasChrome = (): EditorChrome => ({\n surface: resolveToken('card', '255 255 255'),\n borderColor: 'transparent',\n readOnlySurface: resolveToken('muted', '241 245 249'),\n readOnlyBorderColor: 'transparent',\n hoverBorderColor: resolveToken('ring', '31 143 255'),\n focusBorderColor: resolveToken('ring', '31 143 255'),\n focusRing: `0 0 0 4px ${resolveToken('ring', '31 143 255', 0.3)}`,\n radius: '8px',\n paddingY: '8px',\n paddingX: null,\n});\n\n/** Spread over `buildBaseThemeStyles()`; read-only keys match the base's to replace its wash. */\nexport const buildChromeStyles = (chrome: EditorChrome) => ({\n '&.cm-editor': {\n border: `solid 1px ${chrome.borderColor}`,\n borderRadius: chrome.radius,\n backgroundColor: chrome.surface,\n paddingTop: chrome.paddingY,\n paddingBottom: chrome.paddingY,\n },\n '&.cm-editor :is(.cm-gutters,.cm-scroller)': { backgroundColor: chrome.surface },\n\n ...(chrome.paddingX\n ? {\n // Gutterless only: text aligns with a neighbouring `TextInput`'s; a gutter owns the edge.\n '&.cm-editor:not(:has(.cm-gutters)) .cm-content': {\n paddingLeft: chrome.paddingX.left,\n paddingRight: chrome.paddingX.right,\n },\n }\n : null),\n\n ...(chrome.hoverBorderColor\n ? { [`${EDITABLE_EDITOR}:hover`]: { borderColor: chrome.hoverBorderColor } }\n : null),\n [`${EDITABLE_EDITOR}:focus-within`]: {\n borderColor: chrome.focusBorderColor,\n boxShadow: chrome.focusRing,\n },\n\n [READ_ONLY_EDITOR]: {\n backgroundColor: chrome.readOnlySurface,\n borderColor: chrome.readOnlyBorderColor,\n },\n [`${READ_ONLY_EDITOR} .cm-gutters`]: { backgroundColor: chrome.readOnlySurface },\n [`${READ_ONLY_EDITOR} .cm-scroller`]: { backgroundColor: chrome.readOnlySurface },\n});\n","import { StateEffect, StateField, type Text } from '@codemirror/state';\nimport {\n Decoration,\n type DecorationSet,\n EditorView,\n ViewPlugin,\n type ViewUpdate,\n} from '@codemirror/view';\n\nimport colors from '@keboola/tailwind-config/colors';\n\nimport { findLiteralMatches } from '../../utils/findLiteralMatches';\n\nimport { DARK_LINE_ALPHA } from './diffWash';\n\ntype SearchMatch = {\n from: number;\n to: number;\n localIndex: number;\n};\n\nconst setSearchEffect = StateEffect.define<{\n query: string;\n selectedMatchIndex?: number;\n}>();\n\ntype SearchState = {\n query: string;\n selectedMatchIndex?: number;\n matches: SearchMatch[];\n decorations: DecorationSet;\n};\n\nfunction findMatches(doc: Text, query: string): SearchMatch[] {\n // Before `doc.toString()`, which joins the whole rope.\n if (!query || query.length > doc.length) return [];\n\n return findLiteralMatches(doc.toString(), query).map((from, index) => ({\n from,\n to: from + query.length,\n localIndex: index,\n }));\n}\n\nfunction createDecorations(matches: SearchMatch[], selectedLocalIndex?: number): DecorationSet {\n const decorations = matches.map((match) => {\n const isSelected = match.localIndex === selectedLocalIndex;\n\n const decoration = Decoration.mark({\n class: isSelected ? 'cm-searchMatch-selected' : 'cm-searchMatch',\n });\n\n return decoration.range(match.from, match.to);\n });\n\n return Decoration.set(decorations, true);\n}\n\nconst searchField = StateField.define<SearchState>({\n create() {\n return {\n query: '',\n selectedMatchIndex: undefined,\n matches: [],\n decorations: Decoration.none,\n };\n },\n\n update(state, tr) {\n let newState = state;\n\n for (const effect of tr.effects) {\n if (!effect.is(setSearchEffect)) {\n continue;\n }\n\n const { query, selectedMatchIndex } = effect.value;\n\n const matches = findMatches(tr.state.doc, query);\n\n const decorations = createDecorations(matches, selectedMatchIndex);\n\n newState = {\n query,\n selectedMatchIndex,\n matches,\n decorations,\n };\n }\n\n if (tr.docChanged && newState.query) {\n const matches = findMatches(tr.state.doc, newState.query);\n const decorations = createDecorations(matches, newState.selectedMatchIndex);\n\n newState = {\n ...newState,\n matches,\n decorations,\n };\n }\n\n return newState;\n },\n\n provide: (field) => EditorView.decorations.from(field, (state) => state.decorations),\n});\n\nconst searchViewPlugin = ViewPlugin.fromClass(\n class {\n private lastSelectedIndex?: number;\n\n update(update: ViewUpdate) {\n const state = update.state.field(searchField);\n\n if (\n state.selectedMatchIndex !== undefined &&\n state.selectedMatchIndex !== this.lastSelectedIndex\n ) {\n const match = state.matches[state.selectedMatchIndex];\n\n if (match) {\n requestAnimationFrame(() => {\n update.view.dispatch({\n effects: EditorView.scrollIntoView(match.from, { y: 'center' }),\n });\n });\n }\n\n this.lastSelectedIndex = state.selectedMatchIndex;\n }\n\n if (state.selectedMatchIndex === undefined) {\n this.lastSelectedIndex = undefined;\n }\n }\n },\n);\n\n/**\n * Match and current-match fills, per colour scheme.\n *\n * - `&dark` keeps this a static base theme; it applies when the `EditorView.darkTheme` facet is set.\n * - Dark current match uses `neutral[900]` text: white on `blue[500]` is 2.55:1.\n */\nconst searchTheme = EditorView.baseTheme({\n '.cm-searchMatch': {\n backgroundColor: colors.blue[100],\n },\n '.cm-searchMatch > span': {\n color: `${colors.blue[700]} !important`,\n },\n '.cm-searchMatch-selected': {\n backgroundColor: colors.blue[700],\n },\n '.cm-searchMatch-selected > span': {\n color: `${colors.white} !important`,\n },\n\n '&dark .cm-searchMatch': {\n backgroundColor: `${colors.blue[500]}${DARK_LINE_ALPHA}`,\n },\n '&dark .cm-searchMatch > span': {\n color: `${colors.blue[200]} !important`,\n },\n '&dark .cm-searchMatch-selected': {\n backgroundColor: colors.blue[500],\n },\n '&dark .cm-searchMatch-selected > span': {\n color: `${colors.neutral[900]} !important`,\n },\n});\n\nexport function searchExtension() {\n return [searchField, searchViewPlugin, searchTheme];\n}\n\nexport function updateSearch(view: EditorView, query: string, selectedMatchIndex?: number) {\n view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });\n}\n","import { isMac } from '../../utils';\nimport { Kbd } from '../Kbd';\n\nexport const ToggleComponentHelp = () => (\n <div>\n Use <Kbd>{isMac ? 'Command+/' : 'Ctrl+/'}</Kbd> to toggle comments.\n </div>\n);\n","import { type Extension } from '@codemirror/state';\n\nimport type { ResolvedColorScheme } from '../ThemeProvider/types';\nimport { useThemeAttributes } from '../ThemeProvider/useThemeAttributes';\n\n// Shared across instances: each theme's StyleModule appends rules to a document-level\n// stylesheet, so one module per theme keeps it constant-size however many editors mount.\nconst themeCache = new Map<string, Extension>();\n\n/**\n * A CodeMirror extension shared per `cacheKey`, rebuilt when the brand or light/dark mode changes.\n *\n * - `build` reads live `--*` values off `<html>`, a dependency no deps array can see.\n * - `scheme` comes from the same read as the key, for values that are a light/dark pair.\n * - `cacheKey` must include everything `build` closes over, or different inputs share a theme.\n */\nexport const useThemedExtension = (\n cacheKey: string,\n build: (scheme: ResolvedColorScheme) => Extension,\n): Extension => {\n const { scheme, cacheKey: themeKey } = useThemeAttributes();\n const key = `${themeKey} ${cacheKey}`;\n\n // Filling the module cache during render is idempotent.\n let cached = themeCache.get(key);\n if (!cached) {\n cached = build(scheme);\n themeCache.set(key, cached);\n }\n\n return cached;\n};\n","import { useMemo } from 'react';\nimport { Compartment, type Extension } from '@codemirror/state';\nimport { tooltips, ViewPlugin } from '@codemirror/view';\n\n// Whether this element becomes the containing block of a `position: fixed` descendant.\n// - Encodes the full CSS rule; `contain` and `will-change` are value lists, matched loosely.\n// - `content-visibility` is left to `crops`, the stronger of the two for our purposes.\nconst establishesFixedContainingBlock = (style: CSSStyleDeclaration) =>\n style.transform !== 'none' ||\n style.translate !== 'none' ||\n style.rotate !== 'none' ||\n style.scale !== 'none' ||\n style.perspective !== 'none' ||\n style.filter !== 'none' ||\n style.backdropFilter !== 'none' ||\n /\\b(paint|layout|strict|content)\\b/.test(style.contain) ||\n /\\b(transform|perspective|filter|contain)\\b/.test(style.willChange);\n\n// Crops even a fixed-position descendant; `content-visibility: auto` implies paint\n// containment without showing it in computed `contain`.\nconst crops = (style: CSSStyleDeclaration) =>\n style.overflowX !== 'visible' ||\n style.overflowY !== 'visible' ||\n style.maskImage !== 'none' ||\n style.contentVisibility !== 'visible' ||\n /\\b(paint|strict|content)\\b/.test(style.contain);\n\n/**\n * Where a tooltip can hang uncropped, or `null` for CodeMirror's default.\n *\n * - Hosts above the outermost cropper.\n * - Stops at the fixed containing block; nothing higher can crop.\n * - `<body>` and `<html>` never count as croppers.\n */\nconst findTooltipHost = (from: HTMLElement) => {\n let outermostCropper: HTMLElement | null = null;\n\n for (let node = from.parentElement; node && node !== document.body; node = node.parentElement) {\n const style = getComputedStyle(node);\n\n if (crops(style)) {\n outermostCropper = node;\n } else if (establishesFixedContainingBlock(style)) {\n return outermostCropper?.parentElement ?? node;\n }\n }\n\n return outermostCropper?.parentElement ?? null;\n};\n\n/**\n * `tooltips()`, re-hosted so the completion popup is never cropped.\n *\n * - Must survive a masked, scrolling `Modal` and kbc-ui's `content-visibility: auto` blocks.\n * - Not `document.body`: the popup would sit behind the modal, which disables pointer events there.\n * - The only tooltip host in either editor: CodeMirror takes the first parent configured.\n */\nconst tooltipsExtension = (): Extension => {\n // A compartment, because a prop-driven full reconfigure drops appended config but keeps compartments.\n const layer = new Compartment();\n\n return [\n layer.of(tooltips()),\n ViewPlugin.define((view) => {\n // Deferred: a plugin cannot dispatch while its view is being built, and reading styles\n // here would force a layout flush mid-commit. One-shot; later ancestor changes are missed.\n const scheduled = setTimeout(() => {\n if (!view.dom.isConnected) return;\n\n const parent = findTooltipHost(view.dom);\n if (parent) view.dispatch({ effects: layer.reconfigure(tooltips({ parent })) });\n });\n\n return { destroy: () => clearTimeout(scheduled) };\n }),\n ];\n};\n\n/**\n * The tooltips extension, built once per editor; a rebuild would drop the resolved host.\n */\nexport const useTooltipsExtension = () => useMemo(tooltipsExtension, []);\n","import type { Completion, CompletionContext, CompletionSource } from '@codemirror/autocomplete';\n\nimport { useStableCallback } from '../../hooks/useStableCallback';\n\nexport type EditorVariable = { name: string; value?: string };\n\n// Ranks variables above the language's many same-prefix keywords.\nconst BOOST = 2000;\n\n// - One brace or two: `closeBrackets` turns a typed `{` into `{}`.\n// - One name charset throughout; a narrower second one would start the range mid-name and never match.\nconst NAME = String.raw`[\\w-]*`;\nconst AT_CARET = new RegExp(String.raw`(?:\\{{1,2} ?)?${NAME}$`);\nconst NAME_AT_END = new RegExp(`${NAME}$`);\nconst OPENING = /\\{{1,2} ?$/;\nconst CLOSING = /^ ?\\}{1,2}/;\n\n/**\n * Completes a mustache-style `{{name}}` placeholder.\n */\nexport const completeVariables = (variables: EditorVariable[] = []): CompletionSource => {\n if (variables.length === 0) return () => null;\n\n const options: Completion[] = variables.map(({ name, value }) => ({\n // Bare name: the only spelling both editors' filters match, braces typed or not.\n label: name,\n displayLabel: `{{${name}}}`,\n detail: value,\n type: 'variable',\n boost: BOOST,\n apply: (view, completion, from, to) => {\n const { doc } = view.state;\n const line = doc.lineAt(from);\n const insert = `{{${completion.label}}}`;\n\n // Braces are found, not assumed: `closeBrackets` may have added a closing one.\n const opening = OPENING.exec(doc.sliceString(line.from, from));\n const closing = CLOSING.exec(doc.sliceString(to, line.to));\n const start = opening ? from - opening[0].length : from;\n const end = closing ? to + closing[0].length : to;\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length },\n });\n },\n }));\n\n return (context: CompletionContext) => {\n const match = context.matchBefore(AT_CARET);\n\n if (!match?.text) return null;\n\n const [name = ''] = NAME_AT_END.exec(match.text) ?? [];\n\n return { from: match.to - name.length, options };\n };\n};\n\n/**\n * The completion source both editors install, with a stable identity.\n *\n * - It keys their extension memo, while callers pass a fresh array on every store push.\n * - CodeMirror asks per request, so it still sees the latest variables.\n */\nexport const useVariableCompletion = (variables: EditorVariable[] = []): CompletionSource =>\n useStableCallback(completeVariables(variables));\n","import { useEffect, useLayoutEffect, useMemo, useRef } from 'react';\nimport type { KeyboardEvent, ReactNode } from 'react';\nimport type { CompletionSource } from '@codemirror/autocomplete';\nimport { autocompletion, completeAnyWord } from '@codemirror/autocomplete';\nimport { unifiedMergeView } from '@codemirror/merge';\nimport { EditorView, keymap, placeholder as cmPlaceholder } from '@codemirror/view';\nimport CodeMirror, {\n EditorState,\n type Extension,\n type ReactCodeMirrorRef,\n} from '@uiw/react-codemirror';\n\nimport { keyCodes } from '../../constants/keyCodes';\nimport { useStableCallback } from '../../hooks/useStableCallback';\nimport { cn } from '../../utils';\nimport { HelpBlock } from '../HelpBlock';\nimport { useArgoDesign } from '../ThemeProvider/context';\n\nimport { ButtonToolbar } from './ButtonToolbar';\nimport { buildChromeStyles, buildInputChrome } from './editorChrome';\nimport type { LANGUAGE_MODE } from './helpers';\nimport {\n buildBaseThemeStyles,\n buildBasicSetup,\n buildCustomTheme,\n buildJsonLinter,\n getLanguageMode,\n shouldLintJson,\n} from './helpers';\nimport { searchExtension, updateSearch } from './search';\nimport { ToggleComponentHelp } from './ToggleComponentHelp';\nimport { useThemedExtension } from './tokenTheme';\nimport { useTooltipsExtension } from './tooltips';\nimport { type EditorVariable, useVariableCompletion } from './variableCompletion';\n\ntype Props = {\n value: string;\n previousValue?: string;\n /** `'field'`: `InputGroup` chrome, sized to content (don't pin height). `'plain'`: full-bleed panel. */\n variant?: 'plain' | 'field';\n mode?: LANGUAGE_MODE;\n placeholder?: string;\n /** Screen-reader name: the editor has no visible label of its own. */\n ariaLabel?: string;\n /** Prefer over `ariaLabel` inside a form. */\n ariaLabelledBy?: string;\n ariaDescribedBy?: string;\n /** Visual error styling is the caller's (`variant=\"field\"`). */\n ariaInvalid?: boolean;\n ariaRequired?: boolean;\n /** JSON modes: a blank document is not a parse error. Off by default: the mark explains a disabled Save. */\n allowBlankDocument?: boolean;\n /** Bound on CodeMirror's content node (the wrapper is not what gets focused). */\n onBlur?: () => void;\n /** Highlights matches; the find UI is the caller's. Omit both props to skip the search extension. */\n searchQuery?: string;\n searchMatchIndex?: number;\n readOnly?: boolean;\n /** Refuses edits without changing the look, e.g. during a save; `readOnly` makes a greyed viewer. */\n inputLocked?: boolean;\n /** One word per label (a space breaks matching; phrases go in `completionSource`). Pass a stable array. */\n autocompletions?: string[];\n /** Cursor-dependent completions; wins over `autocompletions` / `completeAny`. Memoize it. */\n completionSource?: CompletionSource;\n /** Completed into `{{name}}`, alongside `completionSource`. */\n variables?: EditorVariable[];\n /** `false` silences every source, the language's own included (e.g. shell mode used only for colours). */\n withCompletions?: boolean;\n extraKeys?: Record<string, () => void>;\n withToggleCommentHint?: boolean;\n withAutofocus?: boolean;\n withLineNumbers?: boolean;\n withLineWrapping?: boolean;\n withCollapseUnchanged?: boolean;\n withCopyButton?: boolean;\n completeAny?: boolean;\n help?: ReactNode;\n helpPostfix?: ReactNode;\n /** Toolbar actions beside the copy button; pass `size=\"icon-xs\"` buttons to fit the 28px chip. */\n renderAdditionalButtons?: (value?: string) => ReactNode;\n className?: string;\n} & (\n | { readOnly: true; onChange?: never }\n // `boolean`, not `false`: a permission-locked field still needs its handler when editable.\n | { readOnly?: boolean; onChange: (value: string) => void }\n);\n\nconst emptyObject = {};\n\nexport const CodeEditor = ({\n value,\n previousValue,\n onChange,\n variant = 'plain',\n mode = 'application/json',\n placeholder = '',\n ariaLabel,\n ariaLabelledBy,\n ariaDescribedBy,\n ariaInvalid,\n ariaRequired,\n allowBlankDocument = false,\n onBlur,\n searchQuery,\n searchMatchIndex,\n readOnly = false,\n inputLocked = false,\n autocompletions,\n completionSource,\n variables,\n withCompletions = true,\n extraKeys = emptyObject,\n withToggleCommentHint = false,\n withAutofocus = false,\n withLineNumbers = true,\n withLineWrapping = true,\n withCollapseUnchanged = false,\n withCopyButton = false,\n completeAny = false,\n help = null,\n helpPostfix = null,\n renderAdditionalButtons,\n className,\n}: Props) => {\n // A new handler identity rebuilds CodeMirror's extension tree; callers pass inline arrows.\n const handleChange = useStableCallback((next: string) => onChange?.(next));\n const handleBlur = useStableCallback(() => onBlur?.());\n\n // Presence, not truthiness, keeps the extension set stable while the query changes.\n const withSearch = searchQuery !== undefined;\n const withBlur = onBlur !== undefined;\n const editorRef = useRef<ReactCodeMirrorRef>(null);\n\n // `null` when empty, so the extension is left out.\n const contentAria = useMemo(() => {\n const attributes: Record<string, string> = {};\n if (ariaLabel !== undefined) attributes['aria-label'] = ariaLabel;\n if (ariaLabelledBy !== undefined) attributes['aria-labelledby'] = ariaLabelledBy;\n if (ariaDescribedBy !== undefined) attributes['aria-describedby'] = ariaDescribedBy;\n // Stringified: `contentAttributes` would drop a boolean `false`.\n if (ariaInvalid !== undefined) attributes['aria-invalid'] = String(ariaInvalid);\n if (ariaRequired !== undefined) attributes['aria-required'] = String(ariaRequired);\n return Object.keys(attributes).length > 0 ? attributes : null;\n }, [ariaLabel, ariaLabelledBy, ariaDescribedBy, ariaInvalid, ariaRequired]);\n\n useEffect(() => {\n const view = editorRef.current?.view;\n if (view && withSearch) updateSearch(view, searchQuery, searchMatchIndex);\n }, [withSearch, searchQuery, searchMatchIndex]);\n\n // A view created with a query already set (remount, tab switch) needs it applied on build.\n const handleCreateEditor = useStableCallback((view: EditorView) => {\n if (searchQuery) updateSearch(view, searchQuery, searchMatchIndex);\n });\n\n // Callers pass this inline; only the key set rebuilds the keymap, handlers are read on press.\n const extraKeysRef = useRef(extraKeys);\n useLayoutEffect(() => {\n extraKeysRef.current = extraKeys;\n });\n\n const boundKeysSignature = Object.keys(extraKeys).join('\\n');\n const boundKeys = useMemo(\n () => boundKeysSignature.split('\\n').filter(Boolean),\n [boundKeysSignature],\n );\n\n const tooltipLayer = useTooltipsExtension();\n\n // Built here, not inside `languageData.of`, which runs per completion request.\n const variableCompletion = useVariableCompletion(variables);\n\n // Key has no component prefix: shared with `SqlEditor`.\n const customTheme = useThemedExtension('editor:syntax', buildCustomTheme);\n\n // The brand is in the cache key: `useThemedExtension` caches per key and tracks only `<html>`.\n const isArgo = useArgoDesign();\n const isField = variant === 'field';\n const baseTheme = useThemedExtension(\n isField ? `code-editor:field:${isArgo ? 'argo' : 'legacy'}` : 'code-editor:chrome',\n (scheme) =>\n // `dark` activates every `&dark` rule (ours and CodeMirror's); set here so swapping the\n // github palette in `buildCustomTheme` cannot turn them off.\n EditorView.theme(\n {\n ...buildBaseThemeStyles(scheme),\n ...(isField ? buildChromeStyles(buildInputChrome(isArgo)) : null),\n },\n { dark: scheme === 'dark' },\n ),\n );\n\n const commonExtensions: Extension[] = useMemo(() => {\n const callerCompletions =\n completionSource ??\n (completeAny ? completeAnyWord : autocompletions?.length ? autocompletions : null);\n\n // An empty list is left out, or CodeMirror runs a never-matching source on every keystroke.\n const completionEntries = [\n ...(callerCompletions ? [{ autocomplete: callerCompletions }] : []),\n { autocomplete: variableCompletion },\n ];\n\n return [\n getLanguageMode(mode),\n shouldLintJson(mode, readOnly) ? buildJsonLinter(allowBlankDocument) : [],\n withLineWrapping ? EditorView.lineWrapping : [],\n EditorState.languageData.of(() => completionEntries),\n keymap.of(\n boundKeys.map((key) => ({\n key,\n run: () => {\n extraKeysRef.current[key]?.();\n return true;\n },\n })),\n ),\n readOnly || !withCompletions\n ? []\n : [\n // The only `autocompletion()` (`buildBasicSetup` disables basicSetup's). Not gated on\n // the completion props, so the language's own vocabulary still completes.\n autocompletion(),\n ],\n // On the focused content node (`div[role=\"textbox\"]`), not the wrapper.\n contentAria ? EditorView.contentAttributes.of(contentAria) : [],\n withBlur ? EditorView.domEventHandlers({ blur: handleBlur }) : [],\n withSearch ? searchExtension() : [],\n tooltipLayer,\n baseTheme,\n ];\n }, [\n autocompletions,\n completionSource,\n variableCompletion,\n completeAny,\n withCompletions,\n boundKeys,\n mode,\n readOnly,\n allowBlankDocument,\n withLineWrapping,\n baseTheme,\n contentAria,\n withBlur,\n handleBlur,\n withSearch,\n tooltipLayer,\n ]);\n\n const extensions = useMemo(() => {\n return [\n ...commonExtensions,\n cmPlaceholder(placeholder),\n EditorView.editable.of(!readOnly),\n // The lock is only this facet: `contenteditable` drives the read-only wash and `basicSetup`\n // holds the undo history, so neither is reconfigured.\n EditorState.readOnly.of(readOnly || inputLocked),\n previousValue\n ? unifiedMergeView({\n original: previousValue,\n mergeControls: false,\n highlightChanges: false,\n collapseUnchanged: withCollapseUnchanged ? {} : undefined,\n })\n : [],\n ];\n }, [commonExtensions, placeholder, readOnly, inputLocked, previousValue, withCollapseUnchanged]);\n\n const config = useMemo(() => {\n return {\n ...buildBasicSetup(readOnly),\n lineNumbers: withLineNumbers,\n // Mod-f would open CodeMirror's own search panel beside the caller's.\n ...(withSearch ? { searchKeymap: false } : null),\n };\n }, [withLineNumbers, readOnly, withSearch]);\n\n return (\n // oxlint-disable-next-line jsx-a11y/no-static-element-interactions\n <div\n data-variant={variant}\n className={cn(\n // Scoped to CodeMirror's box so the toolbar needn't undo it with `!important`.\n 'tw:relative tw:flex tw:min-h-0 tw:flex-col tw:[&_.cm-mergeViewEditor]:overflow-visible tw:[&_.cm-mergeViewEditors]:h-full tw:[&_.cm-mergeView]:h-full tw:[&_>.cm-theme]:h-full',\n // Field: transparent so square corners don't show; visible so the focus ring isn't cropped.\n isField\n ? 'tw:[&_>.cm-theme]:overflow-visible tw:[&_>.cm-theme]:bg-transparent'\n : 'tw:[&_>.cm-theme]:overflow-auto tw:[&_>.cm-theme]:bg-background',\n className,\n )}\n onKeyDown={(event: KeyboardEvent) => {\n if (event.key === keyCodes.ESCAPE) {\n event.stopPropagation();\n }\n }}\n >\n <ButtonToolbar value={withCopyButton ? value : undefined}>\n {renderAdditionalButtons?.(value)}\n </ButtonToolbar>\n <CodeMirror\n ref={editorRef}\n onCreateEditor={handleCreateEditor}\n theme={customTheme}\n value={value}\n onChange={handleChange}\n extensions={extensions}\n autoFocus={withAutofocus}\n basicSetup={config}\n />\n {!readOnly && (withToggleCommentHint || help || helpPostfix) && (\n <HelpBlock className=\"tw:mt-2 tw:flex tw:flex-wrap tw:gap-1\">\n {help}\n {withToggleCommentHint ? <ToggleComponentHelp /> : null}\n {helpPostfix}\n </HelpBlock>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from "./classNames-DcGnTh2N.js";
|
|
2
|
-
import { createChangeInputEvent } from "./utils-
|
|
2
|
+
import { createChangeInputEvent } from "./utils-LQ4jJA-9.js";
|
|
3
3
|
import { mergeRefs } from "./internal/utils/mergeRefs.js";
|
|
4
4
|
import { Pipette, X } from "./icons-ZIeZXXS7.js";
|
|
5
5
|
import { InputGroup } from "./InputGroup-Dm014ruw.js";
|
|
@@ -162,4 +162,4 @@ const ColorInput = ({ ref, state, variant, focusVariant, sizing, className, valu
|
|
|
162
162
|
//#endregion
|
|
163
163
|
export { ColorInput };
|
|
164
164
|
|
|
165
|
-
//# sourceMappingURL=ColorInput-
|
|
165
|
+
//# sourceMappingURL=ColorInput-CDKH8q_f.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorInput-D1nC0X6i.js","names":[],"sources":["../src/blocks/ColorInput/utils.ts","../src/blocks/ColorInput/ColorPicker.tsx","../src/blocks/ColorInput/ColorInput.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\n\nconst HEX_CHARSET = /^[0-9a-fA-F]+$/;\nconst COMPLETE_HEX_PATTERN = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\nconst MAX_HEX_BODY_LENGTH = 8;\n// Native <input type=\"color\"> default when fed anything unparseable.\nconst PICKER_FALLBACK = '#000000';\n\nconst extractHexBody = (value: unknown): string | null => {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed === '') return null;\n return trimmed.startsWith('#') ? trimmed.slice(1) : trimmed;\n};\n\nexport const isCompleteHexColor = (value: string): boolean => COMPLETE_HEX_PATTERN.test(value);\n\n// @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker\nexport const showPicker = (input: HTMLInputElement) => {\n const isShowPickerSupported = 'showPicker' in HTMLInputElement.prototype;\n isShowPickerSupported ? input.showPicker() : input.click();\n};\n\n/**\n * Coerces free-form text into a partial hex color (up to `#rrggbbaa`) for the text input.\n *\n * - Adds a missing `#`, keeps only the leading hex digits.\n * - `''` for non-strings or when no hex digits remain.\n * - May be a prefix (`#ab`) — gate rendering on `isCompleteHexColor`.\n */\nexport const coerceHexInputValue = (value?: string | null): string => {\n const body = extractHexBody(value);\n if (body === null) return '';\n const [validBody] = body.match(/^[0-9a-fA-F]+/) ?? [];\n if (!validBody) return '';\n return `#${validBody.slice(0, MAX_HEX_BODY_LENGTH)}`;\n};\n\n/**\n * Coerces any value into the lowercase `#rrggbb` the native `<input type=\"color\">` requires.\n *\n * - Shorthand is expanded, alpha dropped, anything invalid → `#000000`.\n * - Lowercased because the native picker lowercases, so values round-trip.\n */\nexport const coerceColorPickerValue = (value: ComponentProps<'input'>['value'] | null) => {\n const body = extractHexBody(value);\n if (body === null || !HEX_CHARSET.test(body)) return PICKER_FALLBACK;\n\n if (body.length === 3 || body.length === 4) {\n const [r, g, b] = body;\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n if (body.length === 6 || body.length === 8) {\n return `#${body.slice(0, 6).toLowerCase()}`;\n }\n return PICKER_FALLBACK;\n};\n","import { type ComponentProps, type ComponentRef, useRef } from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { Pipette } from '../../icons';\n\nimport { coerceColorPickerValue, showPicker } from './utils';\n\ntype Props = Omit<ComponentProps<'input'>, 'type'>;\n\nexport const ColorPicker = ({ value, disabled, readOnly, ...props }: Props) => {\n const pickerRef = useRef<ComponentRef<'input'>>(null);\n\n const handleOpenPicker = () => {\n if (!pickerRef.current) return;\n showPicker(pickerRef.current);\n };\n\n return (\n <div className=\"tw:relative\">\n <input\n {...props}\n ref={pickerRef}\n type=\"color\"\n value={coerceColorPickerValue(value)}\n tabIndex={-1}\n aria-hidden\n className=\"tw:pointer-events-none tw:absolute tw:left-0 tw:top-full tw:size-0 tw:opacity-0\"\n disabled={disabled}\n readOnly={readOnly}\n />\n <InputGroup.Button\n onMouseDown={(event) => event.preventDefault()}\n disabled={disabled || readOnly}\n onClick={handleOpenPicker}\n aria-label=\"Pick color\"\n >\n <Pipette className=\"tw:size-4\" />\n </InputGroup.Button>\n </div>\n );\n};\n","import { useRef } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { X } from '../../icons';\nimport { cn, createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { ColorPicker } from './ColorPicker';\nimport { coerceHexInputValue, isCompleteHexColor } from './utils';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<ComponentProps<typeof InputGroup.Input>, 'value' | 'defaultValue'>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: string | null;\n defaultValue?: string | null;\n onValueChange?: (value: string) => void;\n onValueBlur?: (value: string) => void;\n allowClear?: boolean;\n };\n\nexport const ColorInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n defaultValue,\n allowClear = false,\n\n // input props\n disabled,\n readOnly,\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [value, setValue] = useControllableState<string>({\n // A `null` controlled value stays controlled (coerced to ''); `undefined` is uncontrolled.\n prop: valueProp === null ? '' : valueProp,\n defaultProp: defaultValue ?? '',\n onChange: onValueChange,\n });\n\n const isControlled = valueProp !== undefined;\n\n const canClear = allowClear && !!value && !disabled && !readOnly;\n const swatchColor = coerceHexInputValue(value);\n const isValidSwatch = isCompleteHexColor(swatchColor);\n\n // Preserve raw text while the user is typing — sanitise on blur.\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n setValue(event.target.value);\n onChange?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n const sanitizedNewValue = coerceHexInputValue(newValue);\n\n if (sanitizedNewValue !== newValue) {\n // In controlled mode, let the parent decide whether to apply the\n // sanitised value via `onValueChange` — don't fight its `value` prop.\n if (!isControlled) event.target.value = sanitizedNewValue;\n setValue(sanitizedNewValue);\n }\n\n onValueBlur?.(sanitizedNewValue);\n onBlur?.(event);\n };\n\n const handlePickerChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n setValue(coerceHexInputValue(event.target.value));\n onChange?.(event);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setValue('');\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Addon\n align=\"inline-start\"\n className={cn(\n { 'tw:-ml-7 tw:opacity-0': !value },\n 'tw:transition-[opacity,margin]',\n 'tw:ease-linear',\n 'tw:duration-200',\n )}\n >\n <div\n style={isValidSwatch ? { background: swatchColor } : undefined}\n className={cn(\n 'tw:size-5',\n 'tw:shrink-0',\n 'tw:rounded-sm',\n 'tw:border',\n 'tw:border-solid',\n 'tw:border-neutral-300',\n {\n 'tw:bg-[linear-gradient(to_top_right,transparent_calc(50%_-_1px),theme(colors.red.300)_calc(50%_-_1px),theme(colors.red.300)_calc(50%_+_1px),transparent_calc(50%_+_1px))]':\n !isValidSwatch,\n },\n )}\n />\n </InputGroup.Addon>\n\n <InputGroup.Input\n {...restInputProps}\n type=\"text\"\n ref={mergeRefs(ref ?? null, inputRef)}\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n // prevents input focus stealing\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n aria-label=\"Clear color\"\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n <ColorPicker\n disabled={disabled}\n readOnly={readOnly}\n value={value}\n onChange={handlePickerChange}\n />\n </InputGroup.Addon>\n </InputGroup>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ColorInput-CDKH8q_f.js","names":[],"sources":["../src/blocks/ColorInput/utils.ts","../src/blocks/ColorInput/ColorPicker.tsx","../src/blocks/ColorInput/ColorInput.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\n\nconst HEX_CHARSET = /^[0-9a-fA-F]+$/;\nconst COMPLETE_HEX_PATTERN = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\nconst MAX_HEX_BODY_LENGTH = 8;\n// Native <input type=\"color\"> default when fed anything unparseable.\nconst PICKER_FALLBACK = '#000000';\n\nconst extractHexBody = (value: unknown): string | null => {\n if (typeof value !== 'string') return null;\n const trimmed = value.trim();\n if (trimmed === '') return null;\n return trimmed.startsWith('#') ? trimmed.slice(1) : trimmed;\n};\n\nexport const isCompleteHexColor = (value: string): boolean => COMPLETE_HEX_PATTERN.test(value);\n\n// @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/showPicker\nexport const showPicker = (input: HTMLInputElement) => {\n const isShowPickerSupported = 'showPicker' in HTMLInputElement.prototype;\n isShowPickerSupported ? input.showPicker() : input.click();\n};\n\n/**\n * Coerces free-form text into a partial hex color (up to `#rrggbbaa`) for the text input.\n *\n * - Adds a missing `#`, keeps only the leading hex digits.\n * - `''` for non-strings or when no hex digits remain.\n * - May be a prefix (`#ab`) — gate rendering on `isCompleteHexColor`.\n */\nexport const coerceHexInputValue = (value?: string | null): string => {\n const body = extractHexBody(value);\n if (body === null) return '';\n const [validBody] = body.match(/^[0-9a-fA-F]+/) ?? [];\n if (!validBody) return '';\n return `#${validBody.slice(0, MAX_HEX_BODY_LENGTH)}`;\n};\n\n/**\n * Coerces any value into the lowercase `#rrggbb` the native `<input type=\"color\">` requires.\n *\n * - Shorthand is expanded, alpha dropped, anything invalid → `#000000`.\n * - Lowercased because the native picker lowercases, so values round-trip.\n */\nexport const coerceColorPickerValue = (value: ComponentProps<'input'>['value'] | null) => {\n const body = extractHexBody(value);\n if (body === null || !HEX_CHARSET.test(body)) return PICKER_FALLBACK;\n\n if (body.length === 3 || body.length === 4) {\n const [r, g, b] = body;\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n if (body.length === 6 || body.length === 8) {\n return `#${body.slice(0, 6).toLowerCase()}`;\n }\n return PICKER_FALLBACK;\n};\n","import { type ComponentProps, type ComponentRef, useRef } from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { Pipette } from '../../icons';\n\nimport { coerceColorPickerValue, showPicker } from './utils';\n\ntype Props = Omit<ComponentProps<'input'>, 'type'>;\n\nexport const ColorPicker = ({ value, disabled, readOnly, ...props }: Props) => {\n const pickerRef = useRef<ComponentRef<'input'>>(null);\n\n const handleOpenPicker = () => {\n if (!pickerRef.current) return;\n showPicker(pickerRef.current);\n };\n\n return (\n <div className=\"tw:relative\">\n <input\n {...props}\n ref={pickerRef}\n type=\"color\"\n value={coerceColorPickerValue(value)}\n tabIndex={-1}\n aria-hidden\n className=\"tw:pointer-events-none tw:absolute tw:left-0 tw:top-full tw:size-0 tw:opacity-0\"\n disabled={disabled}\n readOnly={readOnly}\n />\n <InputGroup.Button\n onMouseDown={(event) => event.preventDefault()}\n disabled={disabled || readOnly}\n onClick={handleOpenPicker}\n aria-label=\"Pick color\"\n >\n <Pipette className=\"tw:size-4\" />\n </InputGroup.Button>\n </div>\n );\n};\n","import { useRef } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\n\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { X } from '../../icons';\nimport { cn, createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { ColorPicker } from './ColorPicker';\nimport { coerceHexInputValue, isCompleteHexColor } from './utils';\n\ntype InputGroupProps = Pick<\n ComponentProps<typeof InputGroup>,\n 'variant' | 'focusVariant' | 'state' | 'sizing'\n>;\n\ntype InputGroupInputProps = Omit<ComponentProps<typeof InputGroup.Input>, 'value' | 'defaultValue'>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: string | null;\n defaultValue?: string | null;\n onValueChange?: (value: string) => void;\n onValueBlur?: (value: string) => void;\n allowClear?: boolean;\n };\n\nexport const ColorInput = ({\n ref,\n\n // group props\n state,\n variant,\n focusVariant,\n sizing,\n className,\n\n // own props\n value: valueProp,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n defaultValue,\n allowClear = false,\n\n // input props\n disabled,\n readOnly,\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [value, setValue] = useControllableState<string>({\n // A `null` controlled value stays controlled (coerced to ''); `undefined` is uncontrolled.\n prop: valueProp === null ? '' : valueProp,\n defaultProp: defaultValue ?? '',\n onChange: onValueChange,\n });\n\n const isControlled = valueProp !== undefined;\n\n const canClear = allowClear && !!value && !disabled && !readOnly;\n const swatchColor = coerceHexInputValue(value);\n const isValidSwatch = isCompleteHexColor(swatchColor);\n\n // Preserve raw text while the user is typing — sanitise on blur.\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n setValue(event.target.value);\n onChange?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n const sanitizedNewValue = coerceHexInputValue(newValue);\n\n if (sanitizedNewValue !== newValue) {\n // In controlled mode, let the parent decide whether to apply the\n // sanitised value via `onValueChange` — don't fight its `value` prop.\n if (!isControlled) event.target.value = sanitizedNewValue;\n setValue(sanitizedNewValue);\n }\n\n onValueBlur?.(sanitizedNewValue);\n onBlur?.(event);\n };\n\n const handlePickerChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n setValue(coerceHexInputValue(event.target.value));\n onChange?.(event);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setValue('');\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n return (\n <InputGroup\n state={state}\n variant={variant}\n sizing={sizing}\n focusVariant={focusVariant}\n className={className}\n >\n <InputGroup.Addon\n align=\"inline-start\"\n className={cn(\n { 'tw:-ml-7 tw:opacity-0': !value },\n 'tw:transition-[opacity,margin]',\n 'tw:ease-linear',\n 'tw:duration-200',\n )}\n >\n <div\n style={isValidSwatch ? { background: swatchColor } : undefined}\n className={cn(\n 'tw:size-5',\n 'tw:shrink-0',\n 'tw:rounded-sm',\n 'tw:border',\n 'tw:border-solid',\n 'tw:border-neutral-300',\n {\n 'tw:bg-[linear-gradient(to_top_right,transparent_calc(50%_-_1px),theme(colors.red.300)_calc(50%_-_1px),theme(colors.red.300)_calc(50%_+_1px),transparent_calc(50%_+_1px))]':\n !isValidSwatch,\n },\n )}\n />\n </InputGroup.Addon>\n\n <InputGroup.Input\n {...restInputProps}\n type=\"text\"\n ref={mergeRefs(ref ?? null, inputRef)}\n value={value}\n onChange={handleChange}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n // prevents input focus stealing\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n aria-label=\"Clear color\"\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n <ColorPicker\n disabled={disabled}\n readOnly={readOnly}\n value={value}\n onChange={handlePickerChange}\n />\n </InputGroup.Addon>\n </InputGroup>\n );\n};\n"],"mappings":";;;;;;;;;AAEA,MAAM,cAAc;AACpB,MAAM,uBAAuB;AAC7B,MAAM,sBAAsB;AAE5B,MAAM,kBAAkB;AAExB,MAAM,kBAAkB,UAAkC;CACxD,IAAI,OAAO,UAAU,UAAU,OAAO;CACtC,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,YAAY,IAAI,OAAO;CAC3B,OAAO,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AACtD;AAEA,MAAa,sBAAsB,UAA2B,qBAAqB,KAAK,KAAK;AAG7F,MAAa,cAAc,UAA4B;CAErD,gBAD8C,iBAAiB,YACvC,MAAM,WAAW,IAAI,MAAM,MAAM;AAC3D;;;;;;;;AASA,MAAa,uBAAuB,UAAkC;CACpE,MAAM,OAAO,eAAe,KAAK;CACjC,IAAI,SAAS,MAAM,OAAO;CAC1B,MAAM,CAAC,aAAa,KAAK,MAAM,eAAe,KAAK,CAAC;CACpD,IAAI,CAAC,WAAW,OAAO;CACvB,OAAO,IAAI,UAAU,MAAM,GAAG,mBAAmB;AACnD;;;;;;;AAQA,MAAa,0BAA0B,UAAmD;CACxF,MAAM,OAAO,eAAe,KAAK;CACjC,IAAI,SAAS,QAAQ,CAAC,YAAY,KAAK,IAAI,GAAG,OAAO;CAErD,IAAI,KAAK,WAAW,KAAK,KAAK,WAAW,GAAG;EAC1C,MAAM,CAAC,GAAG,GAAG,KAAK;EAClB,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,YAAY;CACjD;CACA,IAAI,KAAK,WAAW,KAAK,KAAK,WAAW,GACvC,OAAO,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY;CAE1C,OAAO;AACT;;;AC/CA,MAAa,eAAe,EAAE,OAAO,UAAU,UAAU,GAAG,YAAmB;CAC7E,MAAM,YAAY,OAA8B,IAAI;CAEpD,MAAM,yBAAyB;EAC7B,IAAI,CAAC,UAAU,SAAS;EACxB,WAAW,UAAU,OAAO;CAC9B;CAEA,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,oBAAC,SAAD;GACE,GAAI;GACJ,KAAK;GACL,MAAK;GACL,OAAO,uBAAuB,KAAK;GACnC,UAAU;GACV,eAAA;GACA,WAAU;GACA;GACA;EACX,CAAA,GACD,oBAAC,WAAW,QAAZ;GACE,cAAc,UAAU,MAAM,eAAe;GAC7C,UAAU,YAAY;GACtB,SAAS;GACT,cAAW;GAEX,UAAA,oBAAC,SAAD,EAAS,WAAU,YAAa,CAAA;EACf,CAAA,CAChB;;AAET;;;ACPA,MAAa,cAAc,EACzB,KAGA,OACA,SACA,cACA,QACA,WAGA,OAAO,WACP,eACA,aACA,UACA,QACA,cACA,aAAa,OAGb,UACA,UACA,GAAG,qBACQ;CACX,MAAM,WAAW,OAA8B,IAAI;CAEnD,MAAM,CAAC,OAAO,YAAY,qBAA6B;EAErD,MAAM,cAAc,OAAO,KAAK;EAChC,aAAa,gBAAgB;EAC7B,UAAU;CACZ,CAAC;CAED,MAAM,eAAe,cAAc,KAAA;CAEnC,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;CACxD,MAAM,cAAc,oBAAoB,KAAK;CAC7C,MAAM,gBAAgB,mBAAmB,WAAW;CAGpD,MAAM,gBAAsD,UAAU;EACpE,SAAS,MAAM,OAAO,KAAK;EAC3B,WAAW,KAAK;CAClB;CAEA,MAAM,cAAmD,UAAU;EACjE,MAAM,WAAW,MAAM,OAAO;EAC9B,MAAM,oBAAoB,oBAAoB,QAAQ;EAEtD,IAAI,sBAAsB,UAAU;GAGlC,IAAI,CAAC,cAAc,MAAM,OAAO,QAAQ;GACxC,SAAS,iBAAiB;EAC5B;EAEA,cAAc,iBAAiB;EAC/B,SAAS,KAAK;CAChB;CAEA,MAAM,sBAA4D,UAAU;EAC1E,SAAS,oBAAoB,MAAM,OAAO,KAAK,CAAC;EAChD,WAAW,KAAK;CAClB;CAEA,MAAM,oBAA0D;EAC9D,IAAI,CAAC,SAAS,SAAS;EACvB,SAAS,QAAQ,QAAQ;EACzB,SAAS,EAAE;EACX,WAAW,uBAAuB,SAAS,OAAO,CAAC;CACrD;CAEA,OACE,qBAAC,YAAD;EACS;EACE;EACD;EACM;EACH;EALb,UAAA;GAOE,oBAAC,WAAW,OAAZ;IACE,OAAM;IACN,WAAW,GACT,EAAE,yBAAyB,CAAC,MAAM,GAClC,kCACA,kBACA,iBACF;IAEA,UAAA,oBAAC,OAAD;KACE,OAAO,gBAAgB,EAAE,YAAY,YAAY,IAAI,KAAA;KACrD,WAAW,GACT,aACA,eACA,iBACA,aACA,mBACA,yBACA,EACE,6KACE,CAAC,cACL,CACF;IACD,CAAA;GACe,CAAA;GAElB,oBAAC,WAAW,OAAZ;IACE,GAAI;IACJ,MAAK;IACL,KAAK,UAAU,OAAO,MAAM,QAAQ;IAC7B;IACP,UAAU;IACV,QAAQ;IACE;IACA;GACX,CAAA;GAED,qBAAC,WAAW,OAAZ;IAAkB,OAAM;IAAxB,UAAA,CACG,YACC,oBAAC,WAAW,QAAZ;KAEE,cAAc,UAAU,MAAM,eAAe;KAC7C,SAAS;KACT,cAAW;KAEX,UAAA,oBAAC,GAAD,EAAG,WAAU,YAAa,CAAA;IACT,CAAA,GAErB,oBAAC,aAAD;KACY;KACA;KACH;KACP,UAAU;IACX,CAAA,CACe;;EACR;;AAEhB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Monitor, Moon, Sun } from "./icons-ZIeZXXS7.js";
|
|
2
2
|
import { Button } from "./Button-D2JqBAq7.js";
|
|
3
|
-
import { DropdownMenu } from "./DropdownMenu-
|
|
3
|
+
import { DropdownMenu } from "./DropdownMenu-B1gGvZoh.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/blocks/ColorModeSwitch/ColorModeSwitch.tsx
|
|
6
6
|
const OPTIONS = [
|
|
@@ -64,4 +64,4 @@ const ColorModeSwitch = ({ value, onValueChange, size = "small", className }) =>
|
|
|
64
64
|
//#endregion
|
|
65
65
|
export { ColorModeSwitch };
|
|
66
66
|
|
|
67
|
-
//# sourceMappingURL=ColorModeSwitch-
|
|
67
|
+
//# sourceMappingURL=ColorModeSwitch-DR6J2U6M.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorModeSwitch-
|
|
1
|
+
{"version":3,"file":"ColorModeSwitch-DR6J2U6M.js","names":[],"sources":["../src/blocks/ColorModeSwitch/ColorModeSwitch.tsx"],"sourcesContent":["import { Button } from '../../components/Button';\nimport { DropdownMenu } from '../../components/DropdownMenu';\nimport type { ColorScheme } from '../../components/ThemeProvider';\nimport type { LucideIcon } from '../../icons';\nimport { Monitor, Moon, Sun } from '../../icons';\n\ntype Props = {\n /** Controlled — pair with `onValueChange`. */\n value: ColorScheme;\n onValueChange: (value: ColorScheme) => void;\n size?: 'small' | 'medium';\n className?: string;\n};\n\nconst OPTIONS: { value: ColorScheme; label: string; icon: LucideIcon }[] = [\n { value: 'light', label: 'Light', icon: Sun },\n { value: 'dark', label: 'Dark', icon: Moon },\n { value: 'system', label: 'System', icon: Monitor },\n];\n\nconst triggerSizeMap = { small: 'icon-sm', medium: 'icon' } as const;\n\n/**\n * Light / dark / system switch: an icon button opening a radio `DropdownMenu`.\n *\n * - Controlled: owns no state; wire it to the same state as `ThemeProvider.colorScheme`.\n * - The trigger's `aria-label` names the current scheme.\n */\nexport const ColorModeSwitch = ({ value, onValueChange, size = 'small', className }: Props) => {\n const active = OPTIONS.find((option) => option.value === value);\n const ActiveIcon = active?.icon ?? Monitor;\n const activeLabel = active?.label ?? 'System';\n\n return (\n <DropdownMenu>\n <DropdownMenu.Trigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n size={triggerSizeMap[size]}\n aria-label={`Color mode: ${activeLabel}`}\n title={`Color mode: ${activeLabel}`}\n className={className}\n >\n <ActiveIcon className=\"tw:size-4\" />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.RadioGroup value={value} onValueChange={onValueChange}>\n {OPTIONS.map(({ value: option, label, icon: Icon }) => (\n <DropdownMenu.RadioItem\n key={option}\n value={option}\n icon={<Icon />}\n indicator=\"check\"\n indicatorAlign=\"end\"\n closeOnSelect\n >\n {label}\n </DropdownMenu.RadioItem>\n ))}\n </DropdownMenu.RadioGroup>\n </DropdownMenu.Content>\n </DropdownMenu>\n );\n};\n"],"mappings":";;;;;AAcA,MAAM,UAAqE;CACzE;EAAE,OAAO;EAAS,OAAO;EAAS,MAAM;CAAI;CAC5C;EAAE,OAAO;EAAQ,OAAO;EAAQ,MAAM;CAAK;CAC3C;EAAE,OAAO;EAAU,OAAO;EAAU,MAAM;CAAQ;AACpD;AAEA,MAAM,iBAAiB;CAAE,OAAO;CAAW,QAAQ;AAAO;;;;;;;AAQ1D,MAAa,mBAAmB,EAAE,OAAO,eAAe,OAAO,SAAS,gBAAuB;CAC7F,MAAM,SAAS,QAAQ,MAAM,WAAW,OAAO,UAAU,KAAK;CAC9D,MAAM,aAAa,QAAQ,QAAQ;CACnC,MAAM,cAAc,QAAQ,SAAS;CAErC,OACE,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,aAAa,SAAd;EAAsB,SAAA;EACpB,UAAA,oBAAC,QAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAM,eAAe;GACrB,cAAY,eAAe;GAC3B,OAAO,eAAe;GACX;GAEX,UAAA,oBAAC,YAAD,EAAY,WAAU,YAAa,CAAA;EAC7B,CAAA;CACY,CAAA,GACtB,oBAAC,aAAa,SAAd;EAAsB,OAAM;EAC1B,UAAA,oBAAC,aAAa,YAAd;GAAgC;GAAsB;GACnD,UAAA,QAAQ,KAAK,EAAE,OAAO,QAAQ,OAAO,MAAM,WAC1C,oBAAC,aAAa,WAAd;IAEE,OAAO;IACP,MAAM,oBAAC,MAAD,CAAO,CAAA;IACb,WAAU;IACV,gBAAe;IACf,eAAA;IAEC,UAAA;GACqB,GARjB,MAQiB,CACzB;EACsB,CAAA;CACL,CAAA,CACV,EAAA,CAAA;AAElB"}
|