@keboola/design 3.2.0 → 4.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/dist/index.cjs CHANGED
@@ -39,27 +39,9 @@ var ResizablePrimitive = require('react-resizable-panels');
39
39
  var RadixAvatar = require('@radix-ui/react-avatar');
40
40
  var RadixTabs = require('@radix-ui/react-tabs');
41
41
  var diff = require('diff');
42
- var view = require('@codemirror/view');
43
- var CodeMirror = require('@uiw/react-codemirror');
44
- var colors3 = require('@keboola/tailwind-config/colors');
45
- var state = require('@codemirror/state');
46
42
  var nodeDiff3 = require('node-diff3');
47
43
  var reactForm = require('@tanstack/react-form');
48
44
  var DOMPurify = require('dompurify');
49
- var autocomplete = require('@codemirror/autocomplete');
50
- var langJson = require('@codemirror/lang-json');
51
- var lint = require('@codemirror/lint');
52
- var merge = require('@codemirror/merge');
53
- var langJavascript = require('@codemirror/lang-javascript');
54
- var langPython = require('@codemirror/lang-python');
55
- var langSql = require('@codemirror/lang-sql');
56
- var language = require('@codemirror/language');
57
- var r = require('@codemirror/legacy-modes/mode/r');
58
- var shell = require('@codemirror/legacy-modes/mode/shell');
59
- var codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
60
- var codemirrorLangSfsql = require('@keboola/codemirror-lang-sfsql');
61
- var commands = require('@codemirror/commands');
62
- var codemirrorLangSql = require('@keboola/codemirror-lang-sql');
63
45
 
64
46
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
65
47
 
@@ -95,8 +77,6 @@ var BoringAvatar__default = /*#__PURE__*/_interopDefault(BoringAvatar);
95
77
  var ResizablePrimitive__namespace = /*#__PURE__*/_interopNamespace(ResizablePrimitive);
96
78
  var RadixAvatar__namespace = /*#__PURE__*/_interopNamespace(RadixAvatar);
97
79
  var RadixTabs__namespace = /*#__PURE__*/_interopNamespace(RadixTabs);
98
- var CodeMirror__default = /*#__PURE__*/_interopDefault(CodeMirror);
99
- var colors3__default = /*#__PURE__*/_interopDefault(colors3);
100
80
  var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
101
81
 
102
82
  var __defProp = Object.defineProperty;
@@ -168,7 +148,6 @@ var createChangeInputEvent = (input) => {
168
148
  // src/constants/keyCodes.ts
169
149
  var keyCodes = {
170
150
  ENTER: "Enter",
171
- ESCAPE: "Escape",
172
151
  SPACE: " "
173
152
  };
174
153
  var ThemeContext = react.createContext(null);
@@ -6904,8 +6883,8 @@ var coerceColorPickerValue = (value) => {
6904
6883
  const body = extractHexBody(value);
6905
6884
  if (body === null || !HEX_CHARSET.test(body)) return PICKER_FALLBACK;
6906
6885
  if (body.length === 3 || body.length === 4) {
6907
- const [r2, g, b] = body;
6908
- return `#${r2}${r2}${g}${g}${b}${b}`.toLowerCase();
6886
+ const [r, g, b] = body;
6887
+ return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
6909
6888
  }
6910
6889
  if (body.length === 6 || body.length === 8) {
6911
6890
  return `#${body.slice(0, 6).toLowerCase()}`;
@@ -9346,7 +9325,11 @@ var AlertRoot = ({
9346
9325
  "has-[[data-slot=alert-icon]]:tw-gap-x-2",
9347
9326
  // fonts
9348
9327
  "tw-text-sm",
9328
+ // Legacy keeps the fixed neutral text; argo uses the semantic foreground
9329
+ // so the alert flips with the brand's light/dark palette (the categorical
9330
+ // variant tint stays — only the text token becomes brand-aware).
9349
9331
  "tw-text-neutral-800",
9332
+ "data-[argo=true]:tw-text-foreground",
9350
9333
  "tw-text-left",
9351
9334
  "tw-p-4",
9352
9335
  // border
@@ -10320,17 +10303,40 @@ var AIGradientsSvg = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "0", h
10320
10303
  // src/components/ThemeProvider/brandToCssVars.ts
10321
10304
  var brandToCssVars = (brand, resolvedMode) => {
10322
10305
  const vars = {};
10323
- const colors8 = resolvedMode === "dark" ? brand.colorsDark : brand.colors;
10324
- if (colors8) {
10325
- vars["--color-background"] = colors8.background;
10326
- vars["--color-foreground"] = colors8.foreground;
10327
- vars["--color-muted"] = colors8.muted;
10328
- vars["--color-muted-foreground"] = colors8.mutedForeground;
10329
- vars["--color-border"] = colors8.border;
10330
- vars["--color-primary"] = colors8.primary;
10331
- vars["--color-primary-foreground"] = colors8.primaryForeground;
10332
- vars["--color-destructive"] = colors8.destructive;
10333
- vars["--color-destructive-foreground"] = colors8.destructiveForeground;
10306
+ const colors = resolvedMode === "dark" ? brand.colorsDark : brand.colors;
10307
+ if (colors) {
10308
+ vars["--color-background"] = colors.background;
10309
+ vars["--color-foreground"] = colors.foreground;
10310
+ vars["--color-muted"] = colors.muted;
10311
+ vars["--color-muted-foreground"] = colors.mutedForeground;
10312
+ vars["--color-border"] = colors.border;
10313
+ vars["--color-primary"] = colors.primary;
10314
+ vars["--color-primary-foreground"] = colors.primaryForeground;
10315
+ vars["--color-destructive"] = colors.destructive;
10316
+ vars["--color-destructive-foreground"] = colors.destructiveForeground;
10317
+ if (colors.accent !== void 0) vars["--color-accent"] = colors.accent;
10318
+ if (colors.accentForeground !== void 0)
10319
+ vars["--color-accent-foreground"] = colors.accentForeground;
10320
+ }
10321
+ const sidebar = resolvedMode === "dark" ? brand.sidebarColorsDark : brand.sidebarColors;
10322
+ if (sidebar) {
10323
+ const sidebarVars = {
10324
+ "--color-sidebar": sidebar.sidebar,
10325
+ "--color-sidebar-foreground": sidebar.sidebarForeground,
10326
+ "--color-sidebar-primary": sidebar.sidebarPrimary,
10327
+ "--color-sidebar-primary-foreground": sidebar.sidebarPrimaryForeground,
10328
+ "--color-sidebar-accent": sidebar.sidebarAccent,
10329
+ "--color-sidebar-accent-foreground": sidebar.sidebarAccentForeground,
10330
+ "--color-sidebar-border": sidebar.sidebarBorder,
10331
+ "--color-sidebar-ring": sidebar.sidebarRing
10332
+ };
10333
+ for (const [name, value] of Object.entries(sidebarVars)) {
10334
+ if (value !== void 0) vars[name] = value;
10335
+ }
10336
+ }
10337
+ const fontFamily = brand.typography?.fontFamily?.trim();
10338
+ if (fontFamily) {
10339
+ vars["--font-sans"] = fontFamily;
10334
10340
  }
10335
10341
  if (brand.radii) {
10336
10342
  vars["--radius-sm"] = brand.radii.sm;
@@ -10418,7 +10424,7 @@ var useTheme = () => {
10418
10424
  const context = react.use(ThemeContext);
10419
10425
  if (context === null) {
10420
10426
  throw new Error(
10421
- "useTheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider brand={...}> from @keboola/design."
10427
+ "useTheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider> from @keboola/design."
10422
10428
  );
10423
10429
  }
10424
10430
  return context;
@@ -10427,7 +10433,7 @@ var useColorScheme = () => {
10427
10433
  const context = react.use(ThemeContext);
10428
10434
  if (context === null) {
10429
10435
  throw new Error(
10430
- "useColorScheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider colorScheme={...}> from @keboola/design."
10436
+ "useColorScheme must be used within a <ThemeProvider>. Wrap your app root with <ThemeProvider> from @keboola/design."
10431
10437
  );
10432
10438
  }
10433
10439
  return { colorScheme: context.colorScheme, resolvedMode: context.resolvedMode };
@@ -10688,6 +10694,7 @@ var PageLayout = Object.assign(Root25, {
10688
10694
  // src/blocks/PageHeader/styles.ts
10689
10695
  var titleRowClass = "tw-flex tw-flex-wrap tw-items-center tw-gap-x-3 tw-gap-y-2";
10690
10696
  var titleClass = "tw-m-0 tw-text-3xl tw-font-semibold tw-leading-9 tw-text-foreground tw-break-words";
10697
+ var titleCompactClass = "tw-m-0 tw-text-xl tw-font-semibold tw-leading-7 tw-text-foreground tw-break-words";
10691
10698
  var badgesClass = "tw-flex tw-flex-wrap tw-items-center tw-gap-2 [&_[data-slot=badge]]:tw-rounded-full [&_[data-slot=badge]]:tw-normal-case [&_[data-slot=badge]]:tw-tracking-normal [&_[data-slot=badge]]:tw-py-0";
10692
10699
  var descriptionClass = "tw-m-0 tw-max-w-[800px] tw-break-words tw-text-sm tw-leading-5 tw-text-muted-foreground";
10693
10700
  var PageHeaderDetail = ({
@@ -10699,6 +10706,7 @@ var PageHeaderDetail = ({
10699
10706
  titleIcon,
10700
10707
  badges,
10701
10708
  description,
10709
+ compact = false,
10702
10710
  primaryAction,
10703
10711
  secondaryAction,
10704
10712
  headerNav,
@@ -10712,7 +10720,7 @@ var PageHeaderDetail = ({
10712
10720
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tw-flex tw-min-w-0 tw-flex-1 tw-flex-col tw-gap-2 tw-pr-2", children: [
10713
10721
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: titleRowClass, children: [
10714
10722
  titleIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tw-flex tw-shrink-0 tw-items-center", children: titleIcon }),
10715
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: titleClass, children: title }),
10723
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: compact ? titleCompactClass : titleClass, children: title }),
10716
10724
  badges && /* @__PURE__ */ jsxRuntime.jsx("div", { className: badgesClass, children: badges })
10717
10725
  ] }),
10718
10726
  description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: descriptionClass, children: description })
@@ -14000,423 +14008,6 @@ var DiffView = ({
14000
14008
  }
14001
14009
  );
14002
14010
  };
14003
-
14004
- // src/components/MergeEditor/constants.ts
14005
- var CHUNK_TYPE = {
14006
- UNCHANGED: "unchanged",
14007
- ADDED: "added",
14008
- REMOVED: "removed"
14009
- };
14010
- var CHANGE_CLASS = {
14011
- SAFE: "safe",
14012
- CONFLICT: "conflict"
14013
- };
14014
- var LINE_HEIGHT_PX = 20;
14015
- var PANE_HEADER_HEIGHT_PX = 58;
14016
- var AcceptButton = ({ side, onAccept, argo }) => {
14017
- const label = `Accept ${side === "left" ? "production" : "branch"} version`;
14018
- const Chevron = side === "left" ? icons_exports.ChevronsRight : icons_exports.ChevronsLeft;
14019
- return /* @__PURE__ */ jsxRuntime.jsx(
14020
- Button,
14021
- {
14022
- onClick: onAccept,
14023
- variant: "outline",
14024
- size: "icon-sm",
14025
- title: label,
14026
- "aria-label": label,
14027
- argo,
14028
- children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { className: "tw-size-5" })
14029
- }
14030
- );
14031
- };
14032
- var AcceptControls = ({
14033
- conflicts,
14034
- side,
14035
- onAccept,
14036
- onDismiss,
14037
- contentRef,
14038
- argo
14039
- }) => /* @__PURE__ */ jsxRuntime.jsx(
14040
- "div",
14041
- {
14042
- className: cn(
14043
- "tw-z-10 tw-flex tw-shrink-0 tw-flex-col tw-items-center",
14044
- conflicts.length > 0 ? "tw-w-7" : "tw-w-0"
14045
- ),
14046
- children: conflicts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14047
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-shrink-0", style: { height: `${PANE_HEADER_HEIGHT_PX}px` } }),
14048
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-relative tw-w-full tw-flex-1 tw-overflow-y-clip tw-overflow-x-visible", children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: contentRef, className: "tw-relative tw-size-full", children: conflicts.map((conflict) => {
14049
- const topLine = side === "left" ? conflict.oldStartLine : conflict.newStartLine;
14050
- const topOffset = (topLine - 1) * LINE_HEIGHT_PX - 2;
14051
- return /* @__PURE__ */ jsxRuntime.jsxs(
14052
- "div",
14053
- {
14054
- className: "tw-absolute tw-inset-x-0 tw-flex tw-flex-col tw-items-center tw-gap-0.5",
14055
- style: { top: `${topOffset}px` },
14056
- children: [
14057
- /* @__PURE__ */ jsxRuntime.jsx(AcceptButton, { side, onAccept: () => onAccept(conflict), argo }),
14058
- onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
14059
- Button,
14060
- {
14061
- onClick: () => onDismiss(conflict),
14062
- variant: "outline",
14063
- size: "icon-sm",
14064
- title: "Dismiss",
14065
- "aria-label": `Dismiss ${side === "left" ? "production" : "branch"} change`,
14066
- argo,
14067
- children: /* @__PURE__ */ jsxRuntime.jsx(icons_exports.X, { className: "tw-size-4" })
14068
- }
14069
- )
14070
- ]
14071
- },
14072
- conflict.id
14073
- );
14074
- }) }) })
14075
- ] })
14076
- }
14077
- );
14078
- var setHighlightedLines = state.StateEffect.define();
14079
- var safeDecoration = view.Decoration.line({ class: "cm-merge-safe-line" });
14080
- var conflictDecoration = view.Decoration.line({ class: "cm-merge-conflict-line" });
14081
- var SafeGutterMarker = class extends view.GutterMarker {
14082
- elementClass = "cm-merge-safe-gutter";
14083
- };
14084
- var ConflictGutterMarker = class extends view.GutterMarker {
14085
- elementClass = "cm-merge-conflict-gutter";
14086
- };
14087
- var safeGutterMarker = new SafeGutterMarker();
14088
- var conflictGutterMarker = new ConflictGutterMarker();
14089
- var createDiffHighlightExtension = () => {
14090
- const field = state.StateField.define({
14091
- create: () => ({ decorations: view.Decoration.none, gutterMarkers: state.RangeSet.empty }),
14092
- update(value, tr) {
14093
- let payload = null;
14094
- for (const effect of tr.effects) {
14095
- if (effect.is(setHighlightedLines)) {
14096
- payload = effect.value;
14097
- }
14098
- }
14099
- if (!payload) {
14100
- return {
14101
- decorations: value.decorations.map(tr.changes),
14102
- gutterMarkers: value.gutterMarkers.map(tr.changes)
14103
- };
14104
- }
14105
- const decoBuilder = new state.RangeSetBuilder();
14106
- const gutterBuilder = new state.RangeSetBuilder();
14107
- const doc = tr.state.doc;
14108
- const { lines, classification } = payload;
14109
- const sorted = [...lines].filter((l) => l >= 1 && l <= doc.lines).sort((a, b) => a - b);
14110
- for (const i of sorted) {
14111
- const cls = classification.get(i);
14112
- if (!cls) continue;
14113
- const isSafe = cls === CHANGE_CLASS.SAFE;
14114
- const line = doc.line(i);
14115
- decoBuilder.add(line.from, line.from, isSafe ? safeDecoration : conflictDecoration);
14116
- gutterBuilder.add(line.from, line.from, isSafe ? safeGutterMarker : conflictGutterMarker);
14117
- }
14118
- return {
14119
- decorations: decoBuilder.finish(),
14120
- gutterMarkers: gutterBuilder.finish()
14121
- };
14122
- },
14123
- provide: (f) => [
14124
- view.EditorView.decorations.from(f, (val) => val.decorations),
14125
- view.gutterLineClass.from(f, (val) => val.gutterMarkers)
14126
- ]
14127
- });
14128
- const theme2 = view.EditorView.theme({
14129
- ".cm-merge-safe-line": {
14130
- backgroundColor: `${colors3__default.default.primary[100]} !important`,
14131
- boxShadow: `inset 3px 0 0 ${colors3__default.default.primary[500]}`
14132
- },
14133
- ".cm-merge-conflict-line": {
14134
- backgroundColor: `${colors3__default.default.warning[100]} !important`,
14135
- boxShadow: `inset 3px 0 0 ${colors3__default.default.warning[500]}`
14136
- },
14137
- ".cm-merge-safe-gutter": {
14138
- backgroundColor: `${colors3__default.default.primary[200]} !important`
14139
- },
14140
- ".cm-merge-conflict-gutter": {
14141
- backgroundColor: `${colors3__default.default.warning[200]} !important`
14142
- }
14143
- });
14144
- return [field, theme2];
14145
- };
14146
- var updateHighlightedLines = (view, lines, classification) => {
14147
- view.dispatch({ effects: setHighlightedLines.of({ lines, classification }) });
14148
- };
14149
- var EMPTY_LINES = /* @__PURE__ */ new Set();
14150
- var EMPTY_CLASSIFICATION = /* @__PURE__ */ new Map();
14151
- var MergePane = ({
14152
- value,
14153
- highlightedLines,
14154
- lineClassification,
14155
- readOnly = false,
14156
- onChange,
14157
- header,
14158
- headerClassName,
14159
- className,
14160
- onScrollDOMReady,
14161
- deleted = false
14162
- }) => {
14163
- const editorRef = react.useRef(null);
14164
- const extensions = react.useMemo(
14165
- () => [
14166
- createDiffHighlightExtension(),
14167
- view.EditorView.theme({
14168
- "&.cm-editor": {
14169
- height: "100%",
14170
- backgroundColor: deleted ? colors3__default.default.error[100] : colors3__default.default.neutral[50],
14171
- outline: "none"
14172
- },
14173
- ".cm-gutters": {
14174
- backgroundColor: deleted ? colors3__default.default.error[200] : colors3__default.default.neutral[100]
14175
- },
14176
- "*": { lineHeight: `${LINE_HEIGHT_PX}px` },
14177
- ".cm-lineNumbers .cm-gutterElement": { padding: "0 0 0 25px" }
14178
- }),
14179
- // Recalc viewport after every doc change so late-settling layouts (alerts
14180
- // appearing above the editor) don't leave trailing lines blank.
14181
- view.EditorView.updateListener.of((update) => {
14182
- if (update.docChanged) {
14183
- requestAnimationFrame(() => update.view.dispatch({}));
14184
- }
14185
- })
14186
- ],
14187
- [deleted]
14188
- );
14189
- react.useEffect(() => {
14190
- const view = editorRef.current?.view;
14191
- if (!view) return;
14192
- updateHighlightedLines(
14193
- view,
14194
- deleted ? EMPTY_LINES : highlightedLines,
14195
- deleted ? EMPTY_CLASSIFICATION : lineClassification
14196
- );
14197
- }, [highlightedLines, lineClassification, deleted]);
14198
- const handleCreateEditor = react.useCallback(
14199
- (view) => {
14200
- updateHighlightedLines(
14201
- view,
14202
- deleted ? EMPTY_LINES : highlightedLines,
14203
- deleted ? EMPTY_CLASSIFICATION : lineClassification
14204
- );
14205
- onScrollDOMReady?.(view.scrollDOM);
14206
- },
14207
- [highlightedLines, lineClassification, onScrollDOMReady, deleted]
14208
- );
14209
- react.useEffect(() => {
14210
- return () => onScrollDOMReady?.(null);
14211
- }, [onScrollDOMReady]);
14212
- react.useEffect(() => {
14213
- const view = editorRef.current?.view;
14214
- const wrapper = view?.dom.parentElement;
14215
- if (!view || !wrapper) return;
14216
- const observer = new ResizeObserver(() => view.dispatch({}));
14217
- observer.observe(wrapper);
14218
- return () => observer.disconnect();
14219
- }, []);
14220
- return /* @__PURE__ */ jsxRuntime.jsxs(
14221
- "div",
14222
- {
14223
- className: cn(
14224
- "tw-flex tw-min-w-0 tw-flex-1 tw-flex-col tw-overflow-hidden",
14225
- className,
14226
- deleted && "tw-border-error-300"
14227
- ),
14228
- children: [
14229
- header && /* @__PURE__ */ jsxRuntime.jsx(
14230
- "div",
14231
- {
14232
- className: cn(
14233
- "tw-px-4 tw-py-3",
14234
- deleted ? "tw-border-b tw-border-error-200 tw-bg-error-100" : "tw-bg-background",
14235
- headerClassName
14236
- ),
14237
- children: header
14238
- }
14239
- ),
14240
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-flex tw-h-0 tw-flex-1 tw-flex-col [&_>div]:tw-h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
14241
- CodeMirror__default.default,
14242
- {
14243
- ref: editorRef,
14244
- height: "100%",
14245
- value,
14246
- onChange,
14247
- extensions,
14248
- readOnly,
14249
- onCreateEditor: handleCreateEditor,
14250
- basicSetup: { lineNumbers: true, drawSelection: false }
14251
- }
14252
- ) })
14253
- ]
14254
- }
14255
- );
14256
- };
14257
- var useScrollSync = () => {
14258
- const scrollersRef = react.useRef([]);
14259
- const followersRef = react.useRef(/* @__PURE__ */ new Map());
14260
- const isSyncingRef = react.useRef(false);
14261
- const scrollerCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
14262
- const followerCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
14263
- const updateFollowers = react.useCallback(() => {
14264
- for (const [, { paneIndex, el }] of followersRef.current) {
14265
- const scroller = scrollersRef.current[paneIndex];
14266
- if (!scroller) continue;
14267
- el.style.transform = `translateY(-${scroller.scrollTop}px)`;
14268
- }
14269
- }, []);
14270
- const handleScroll = react.useCallback(
14271
- (e) => {
14272
- if (isSyncingRef.current) return;
14273
- isSyncingRef.current = true;
14274
- const sourceScrollTop = e.target.scrollTop;
14275
- for (const scroller of scrollersRef.current) {
14276
- if (!scroller || scroller === e.target) continue;
14277
- const targetMax = Math.max(0, scroller.scrollHeight - scroller.clientHeight);
14278
- scroller.scrollTop = Math.min(sourceScrollTop, targetMax);
14279
- }
14280
- updateFollowers();
14281
- isSyncingRef.current = false;
14282
- },
14283
- [updateFollowers]
14284
- );
14285
- const registerScroller = react.useCallback(
14286
- (index) => {
14287
- const existing = scrollerCallbacksRef.current.get(index);
14288
- if (existing) return existing;
14289
- const callback = (el) => {
14290
- const prev = scrollersRef.current[index];
14291
- if (prev === el) return;
14292
- prev?.removeEventListener("scroll", handleScroll);
14293
- scrollersRef.current[index] = el;
14294
- el?.addEventListener("scroll", handleScroll, { passive: true });
14295
- };
14296
- scrollerCallbacksRef.current.set(index, callback);
14297
- return callback;
14298
- },
14299
- [handleScroll]
14300
- );
14301
- const registerFollower = react.useCallback((paneIndex, key) => {
14302
- const existing = followerCallbacksRef.current.get(key);
14303
- if (existing) return existing;
14304
- const callback = (el) => {
14305
- if (el) {
14306
- followersRef.current.set(key, { paneIndex, el });
14307
- } else {
14308
- followersRef.current.delete(key);
14309
- }
14310
- };
14311
- followerCallbacksRef.current.set(key, callback);
14312
- return callback;
14313
- }, []);
14314
- return { registerScroller, registerFollower };
14315
- };
14316
- var EMPTY_LINES2 = /* @__PURE__ */ new Set();
14317
- var EMPTY_CLASSIFICATION2 = /* @__PURE__ */ new Map();
14318
- var MergeEditor = ({
14319
- mergeValue,
14320
- handleMergeChange,
14321
- leftText,
14322
- rightText,
14323
- leftConflicts,
14324
- rightConflicts,
14325
- leftHighlightedLines,
14326
- rightHighlightedLines,
14327
- leftClassification,
14328
- rightClassification,
14329
- mergeHighlightedLines,
14330
- mergeClassification,
14331
- acceptLeft,
14332
- acceptRight,
14333
- dismissLeft,
14334
- dismissRight,
14335
- leftHeader,
14336
- middleHeader,
14337
- middleHeaderClassName,
14338
- middleClassName,
14339
- rightHeader,
14340
- className,
14341
- argo,
14342
- leftDeleted = false,
14343
- rightDeleted = false
14344
- }) => {
14345
- const { registerScroller, registerFollower } = useScrollSync();
14346
- const anySideDeleted = leftDeleted || rightDeleted;
14347
- return /* @__PURE__ */ jsxRuntime.jsxs(
14348
- "div",
14349
- {
14350
- className: cn(
14351
- "tw-flex tw-h-full tw-min-h-0 tw-overflow-hidden tw-bg-background tw-gap-3",
14352
- className
14353
- ),
14354
- children: [
14355
- /* @__PURE__ */ jsxRuntime.jsx(
14356
- MergePane,
14357
- {
14358
- value: leftText,
14359
- highlightedLines: leftHighlightedLines,
14360
- lineClassification: leftClassification,
14361
- readOnly: true,
14362
- header: leftHeader,
14363
- className: "tw-rounded-r-lg tw-border tw-border-border",
14364
- onScrollDOMReady: registerScroller(0),
14365
- deleted: leftDeleted
14366
- }
14367
- ),
14368
- /* @__PURE__ */ jsxRuntime.jsx(
14369
- AcceptControls,
14370
- {
14371
- conflicts: leftDeleted ? [] : leftConflicts,
14372
- side: "left",
14373
- onAccept: acceptLeft,
14374
- onDismiss: dismissLeft,
14375
- contentRef: registerFollower(0, "left-controls"),
14376
- argo
14377
- }
14378
- ),
14379
- /* @__PURE__ */ jsxRuntime.jsx(
14380
- MergePane,
14381
- {
14382
- value: mergeValue,
14383
- highlightedLines: anySideDeleted ? EMPTY_LINES2 : mergeHighlightedLines,
14384
- lineClassification: anySideDeleted ? EMPTY_CLASSIFICATION2 : mergeClassification,
14385
- onChange: handleMergeChange,
14386
- header: middleHeader,
14387
- headerClassName: middleHeaderClassName,
14388
- className: cn("tw-border tw-border-border tw-rounded-lg", middleClassName),
14389
- onScrollDOMReady: registerScroller(1)
14390
- }
14391
- ),
14392
- /* @__PURE__ */ jsxRuntime.jsx(
14393
- AcceptControls,
14394
- {
14395
- conflicts: rightDeleted ? [] : rightConflicts,
14396
- side: "right",
14397
- onAccept: acceptRight,
14398
- onDismiss: dismissRight,
14399
- contentRef: registerFollower(2, "right-controls"),
14400
- argo
14401
- }
14402
- ),
14403
- /* @__PURE__ */ jsxRuntime.jsx(
14404
- MergePane,
14405
- {
14406
- value: rightText,
14407
- highlightedLines: rightHighlightedLines,
14408
- lineClassification: rightClassification,
14409
- readOnly: true,
14410
- header: rightHeader,
14411
- className: "tw-rounded-l-lg tw-border tw-border-border",
14412
- onScrollDOMReady: registerScroller(2),
14413
- deleted: rightDeleted
14414
- }
14415
- )
14416
- ]
14417
- }
14418
- );
14419
- };
14420
14011
  var PaneHeader = ({ label, sublabel }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
14421
14012
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "tw-m-0 tw-text-sm tw-font-medium tw-text-foreground", children: label }),
14422
14013
  sublabel && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "tw-m-0 tw-text-xs tw-text-muted-foreground", children: sublabel })
@@ -14446,6 +14037,17 @@ var ConflictStatusIndicator = ({ remainingConflicts, remainingSafeChanges }) =>
14446
14037
  }
14447
14038
  );
14448
14039
  };
14040
+
14041
+ // src/components/MergeEditor/constants.ts
14042
+ var CHUNK_TYPE = {
14043
+ UNCHANGED: "unchanged",
14044
+ ADDED: "added",
14045
+ REMOVED: "removed"
14046
+ };
14047
+ var CHANGE_CLASS = {
14048
+ SAFE: "safe",
14049
+ CONFLICT: "conflict"
14050
+ };
14449
14051
  var computeDiffChunks = (oldText, newText) => {
14450
14052
  const changes = diff.diffLines(oldText, newText);
14451
14053
  const chunks = [];
@@ -15058,6 +14660,7 @@ var SelectField = ({
15058
14660
  required,
15059
14661
  help,
15060
14662
  className,
14663
+ items,
15061
14664
  options,
15062
14665
  placeholder,
15063
14666
  triggerClassName,
@@ -15067,6 +14670,7 @@ var SelectField = ({
15067
14670
  ...rootProps
15068
14671
  }) => {
15069
14672
  const field = useFieldContext();
14673
+ const resolved = items ?? options ?? [];
15070
14674
  return /* @__PURE__ */ jsxRuntime.jsx(FieldShell, { field, label, required, help, className, children: /* @__PURE__ */ jsxRuntime.jsxs(
15071
14675
  Select.Root,
15072
14676
  {
@@ -15088,7 +14692,7 @@ var SelectField = ({
15088
14692
  onBlur: field.handleBlur
15089
14693
  }
15090
14694
  ),
15091
- /* @__PURE__ */ jsxRuntime.jsx(Select.Content, { variant: variant === "argo" ? "argo" : "default", children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(Select.Item, { value: option.value, children: option.label }, option.value)) })
14695
+ /* @__PURE__ */ jsxRuntime.jsx(Select.Content, { variant: variant === "argo" ? "argo" : "default", children: resolved.map((option) => /* @__PURE__ */ jsxRuntime.jsx(Select.Item, { value: option.value, children: option.label }, option.value)) })
15092
14696
  ]
15093
14697
  }
15094
14698
  ) });
@@ -15413,751 +15017,6 @@ var ZoomableSvg = ({ html, copyText, className }) => {
15413
15017
  }
15414
15018
  );
15415
15019
  };
15416
- var ButtonToolbar = ({ value, children }) => {
15417
- if (!value && !children) return null;
15418
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "tw-pointer-events-auto tw-ml-auto tw-mr-4 tw-flex tw-w-fit tw-gap-1 tw-overflow-visible tw-rounded-lg tw-border tw-border-solid tw-border-border !tw-bg-background tw-p-[3px] tw-shadow", children: [
15419
- !!value && /* @__PURE__ */ jsxRuntime.jsx(ClipboardButton, { size: "icon-sm", variant: "invisible", text: value }),
15420
- children
15421
- ] });
15422
- };
15423
- var baseThemeStyles = {
15424
- "*": { lineHeight: "20px" },
15425
- "*::selection": {
15426
- backgroundColor: colors3__default.default.secondary[500],
15427
- color: `${colors3__default.default.white} !important`
15428
- },
15429
- '&.cm-editor:has(.cm-content[contenteditable="false"])': { backgroundColor: colors3__default.default.neutral[150] },
15430
- '&.cm-editor:has(.cm-content[contenteditable="false"]) .cm-gutters': {
15431
- backgroundColor: colors3__default.default.neutral[200]
15432
- },
15433
- "&.cm-editor .cm-scroller": { overflowAnchor: "none" },
15434
- "&.cm-editor, &.cm-editor .cm-scroller": {
15435
- minHeight: "100%",
15436
- flexGrow: 1,
15437
- alignItems: "stretch !important",
15438
- outline: "none"
15439
- },
15440
- ".cm-gutter.cm-foldGutter": { display: "none !important" },
15441
- ".cm-gutter.cm-lineNumbers": { paddingLeft: "20px", paddingRight: "6px" },
15442
- ".cm-gutters": { height: "auto" },
15443
- // tokens overrides
15444
- ".cm-line .tok-string": { color: colors3__default.default.warning[700] },
15445
- // merge (diff) view
15446
- '&[class*="cm-merge-"] .cm-deletedLine': { backgroundColor: colors3__default.default.error[100] },
15447
- '&[class*="cm-merge-"] .cm-changedLine': { backgroundColor: colors3__default.default.primary[100] },
15448
- '&[class*="cm-merge-"] .cm-deletedLineGutter': { backgroundColor: colors3__default.default.error[200] },
15449
- '&[class*="cm-merge-"] .cm-changedLineGutter': { backgroundColor: colors3__default.default.primary[200] },
15450
- '&[class*="cm-merge-"] .cm-deletedText': { background: colors3__default.default.error[200] },
15451
- '&[class*="cm-merge-"] .cm-changedText': { background: colors3__default.default.primary[200] },
15452
- '&[class*="cm-merge-"]': {
15453
- backgroundColor: `${colors3__default.default.white} !important`
15454
- },
15455
- '&[class*="cm-merge-"] .cm-gutters': {
15456
- backgroundColor: `${colors3__default.default.white} !important`
15457
- },
15458
- ".cm-changeGutter": { position: "absolute", zIndex: -1, width: "100%", paddingLeft: 0 },
15459
- '&[class*="cm-merge-"] .cm-changedLine,&[class*="cm-merge-"] .cm-line, &[class*="cm-merge-"] .cm-deletedChunk': { paddingLeft: 0 }
15460
- };
15461
- var BASIS_SETUP = { drawSelection: false };
15462
- var customTheme = codemirrorThemeGithub.githubLightInit({
15463
- settings: {
15464
- fontFamily: `'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New'`,
15465
- background: colors3__default.default.neutral[50],
15466
- gutterBackground: colors3__default.default.neutral[100],
15467
- gutterBorder: "transparent",
15468
- lineHighlight: "transparent",
15469
- selection: colors3__default.default.secondary[500]
15470
- }
15471
- });
15472
- var getLanguageMode = (mode) => {
15473
- switch (mode) {
15474
- case "text/x-python":
15475
- return langPython.python();
15476
- case "text/x-sql":
15477
- return langSql.sql({ upperCaseKeywords: true });
15478
- case "text/x-sfsql":
15479
- return language.StreamLanguage.define(codemirrorLangSfsql.sfsql);
15480
- case "text/x-plsql":
15481
- return langSql.sql({ upperCaseKeywords: true, dialect: langSql.PLSQL });
15482
- case "text/x-rsrc":
15483
- return language.StreamLanguage.define(r.r);
15484
- case "text/x-sh":
15485
- return language.StreamLanguage.define(shell.shell);
15486
- case "text/javascript":
15487
- return langJavascript.javascript({ jsx: true });
15488
- case "text/typescript":
15489
- return langJavascript.javascript({ jsx: true, typescript: true });
15490
- default:
15491
- return langJson.json();
15492
- }
15493
- };
15494
- var ToggleComponentHelp = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15495
- "Use ",
15496
- /* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Ctrl+/" }),
15497
- " or ",
15498
- /* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Command+/" }),
15499
- " to toggle comments."
15500
- ] });
15501
- var emptyArray = [];
15502
- var emptyObject = {};
15503
- var CodeEditor = ({
15504
- value,
15505
- previousValue,
15506
- onChange,
15507
- mode = "application/json",
15508
- placeholder = "",
15509
- readOnly = false,
15510
- autocompletions = emptyArray,
15511
- extraKeys = emptyObject,
15512
- withToggleCommentHint = false,
15513
- withAutofocus = false,
15514
- withLineNumbers = true,
15515
- withLineWrapping = true,
15516
- withCollapseUnchanged = false,
15517
- withCopyButton = true,
15518
- completeAny = false,
15519
- help = null,
15520
- helpPostfix = null,
15521
- renderAdditionalButtons,
15522
- className
15523
- }) => {
15524
- const commonExtensions = react.useMemo(() => {
15525
- return [
15526
- getLanguageMode(mode),
15527
- mode === "application/json" && lint.linter(langJson.jsonParseLinter()),
15528
- withLineWrapping ? view.EditorView.lineWrapping : [],
15529
- CodeMirror.EditorState.languageData.of(() => [
15530
- { autocomplete: completeAny ? autocomplete.completeAnyWord : autocompletions }
15531
- ]),
15532
- view.keymap.of(
15533
- Object.entries(extraKeys).map(([key, run]) => ({
15534
- key,
15535
- run: () => {
15536
- if (typeof run === "string") return run;
15537
- run();
15538
- return true;
15539
- }
15540
- }))
15541
- ),
15542
- autocomplete.autocompletion({ activateOnTyping: completeAny }),
15543
- view.EditorView.theme(baseThemeStyles)
15544
- ].filter(Boolean);
15545
- }, [autocompletions, completeAny, extraKeys, mode, withLineWrapping]);
15546
- const extensions = react.useMemo(() => {
15547
- return [
15548
- ...commonExtensions,
15549
- view.placeholder(placeholder),
15550
- view.EditorView.editable.of(!readOnly),
15551
- CodeMirror.EditorState.readOnly.of(readOnly),
15552
- previousValue ? merge.unifiedMergeView({
15553
- original: previousValue,
15554
- mergeControls: false,
15555
- highlightChanges: false,
15556
- collapseUnchanged: withCollapseUnchanged ? {} : void 0
15557
- }) : []
15558
- ];
15559
- }, [commonExtensions, placeholder, readOnly, previousValue, withCollapseUnchanged]);
15560
- const config = react.useMemo(() => {
15561
- return {
15562
- ...BASIS_SETUP,
15563
- lineNumbers: withLineNumbers
15564
- };
15565
- }, [withLineNumbers]);
15566
- return (
15567
- // oxlint-disable-next-line jsx-a11y/no-static-element-interactions
15568
- /* @__PURE__ */ jsxRuntime.jsxs(
15569
- "div",
15570
- {
15571
- className: cn(
15572
- "tw-relative tw-flex tw-min-h-0 tw-flex-col [&_.cm-mergeViewEditor]:tw-overflow-visible [&_.cm-mergeViewEditors]:tw-h-full [&_.cm-mergeView]:tw-h-full [&_>div]:tw-h-full [&_>div]:tw-overflow-auto [&_>div]:tw-bg-background",
15573
- { "tw-mt-5": !!renderAdditionalButtons },
15574
- className
15575
- ),
15576
- onKeyDown: (event) => {
15577
- if (event.key === keyCodes.ESCAPE) {
15578
- event.stopPropagation();
15579
- }
15580
- },
15581
- children: [
15582
- (withCopyButton || renderAdditionalButtons) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-pointer-events-none tw-absolute tw-z-10 tw-flex !tw-h-auto tw-w-full tw-translate-y-[calc(-100%_+_8px)] !tw-overflow-visible !tw-bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(ButtonToolbar, { value: withCopyButton ? value : void 0, children: renderAdditionalButtons?.(value) }) }) }),
15583
- /* @__PURE__ */ jsxRuntime.jsx(
15584
- CodeMirror__default.default,
15585
- {
15586
- theme: customTheme,
15587
- value,
15588
- onChange,
15589
- extensions,
15590
- autoFocus: withAutofocus,
15591
- basicSetup: config
15592
- }
15593
- ),
15594
- !readOnly && (withToggleCommentHint || help || helpPostfix) && /* @__PURE__ */ jsxRuntime.jsxs(HelpBlock, { className: "tw-mt-2 tw-flex tw-flex-wrap tw-gap-1", children: [
15595
- help,
15596
- withToggleCommentHint ? /* @__PURE__ */ jsxRuntime.jsx(ToggleComponentHelp, {}) : null,
15597
- helpPostfix
15598
- ] })
15599
- ]
15600
- }
15601
- )
15602
- );
15603
- };
15604
- var activeQueryFirstLine = view.Decoration.line({ class: "cm-active-query cm-active-query-first" });
15605
- var activeQueryMiddleLine = view.Decoration.line({ class: "cm-active-query" });
15606
- var activeQueryLastLine = view.Decoration.line({ class: "cm-active-query cm-active-query-last" });
15607
- var activeQuerySingleLine = view.Decoration.line({
15608
- class: "cm-active-query cm-active-query-first cm-active-query-last"
15609
- });
15610
- var findActiveQueryRange = (doc, cursorPos, boundaries) => {
15611
- if (boundaries.length === 0) return null;
15612
- let match = boundaries[boundaries.length - 1];
15613
- for (const boundary of boundaries) {
15614
- if (cursorPos <= boundary.to) {
15615
- match = boundary;
15616
- break;
15617
- }
15618
- }
15619
- if (!match) return null;
15620
- const queryText = doc.slice(match.from, match.to);
15621
- const leadingWhitespace = queryText.length - queryText.trimStart().length;
15622
- const trailingWhitespace = queryText.length - queryText.trimEnd().length;
15623
- const trimmedStart = match.from + leadingWhitespace;
15624
- const trimmedEnd = match.to - trailingWhitespace;
15625
- if (trimmedStart >= trimmedEnd) return null;
15626
- return { from: trimmedStart, to: trimmedEnd };
15627
- };
15628
- var computeBoundaries = (queries) => {
15629
- const boundaries = [];
15630
- let offset = 0;
15631
- for (const query of queries) {
15632
- boundaries.push({ from: offset, to: offset + query.length });
15633
- offset += query.length;
15634
- }
15635
- return boundaries;
15636
- };
15637
- var mapBoundariesThroughChanges = (boundaries, changes) => {
15638
- const prevLen = changes.length;
15639
- const mapped = [];
15640
- for (const b of boundaries) {
15641
- const from = changes.mapPos(Math.max(0, Math.min(b.from, prevLen)), -1);
15642
- const to = changes.mapPos(Math.max(0, Math.min(b.to, prevLen)), 1);
15643
- if (from < to) mapped.push({ from, to });
15644
- }
15645
- return mapped;
15646
- };
15647
- var buildDecorations = (view$1, range) => {
15648
- const startLine = view$1.state.doc.lineAt(range.from).number;
15649
- const endLine = view$1.state.doc.lineAt(range.to).number;
15650
- const decorations = [];
15651
- for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
15652
- const lineStart = view$1.state.doc.line(lineNum).from;
15653
- if (startLine === endLine) {
15654
- decorations.push(activeQuerySingleLine.range(lineStart));
15655
- } else if (lineNum === startLine) {
15656
- decorations.push(activeQueryFirstLine.range(lineStart));
15657
- } else if (lineNum === endLine) {
15658
- decorations.push(activeQueryLastLine.range(lineStart));
15659
- } else {
15660
- decorations.push(activeQueryMiddleLine.range(lineStart));
15661
- }
15662
- }
15663
- return view.Decoration.set(decorations);
15664
- };
15665
- var activeQueryHighlight = (splitQueries) => {
15666
- return [
15667
- view.ViewPlugin.fromClass(
15668
- class {
15669
- decorations = view.Decoration.none;
15670
- debounceTimer = null;
15671
- seq = 0;
15672
- cachedDoc = "";
15673
- cachedBoundaries = [];
15674
- destroyed = false;
15675
- constructor(view) {
15676
- this.scheduleDocParse(view);
15677
- }
15678
- update(update) {
15679
- if (update.focusChanged && !update.view.hasFocus) {
15680
- this.decorations = view.Decoration.none;
15681
- return;
15682
- }
15683
- if (update.docChanged) {
15684
- if (this.cachedBoundaries.length > 0) {
15685
- this.cachedBoundaries = mapBoundariesThroughChanges(
15686
- this.cachedBoundaries,
15687
- update.changes
15688
- );
15689
- this.cachedDoc = update.state.doc.toString();
15690
- this.updateFromCache(update.view);
15691
- }
15692
- this.scheduleDocParse(update.view);
15693
- } else if (update.selectionSet || update.focusChanged && update.view.hasFocus) {
15694
- this.updateFromCache(update.view);
15695
- }
15696
- }
15697
- destroy() {
15698
- this.destroyed = true;
15699
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
15700
- }
15701
- /**
15702
- * Update decorations using cached query boundaries.
15703
- * Only mutates this.decorations — does NOT call view.dispatch().
15704
- * When called from update() (sync), CodeMirror picks up the new
15705
- * decorations via the accessor. When called from the async
15706
- * scheduleDocParse callback, the caller must dispatch separately.
15707
- */
15708
- updateFromCache(view$1) {
15709
- if (!view$1.hasFocus) {
15710
- this.decorations = view.Decoration.none;
15711
- return;
15712
- }
15713
- const { main } = view$1.state.selection;
15714
- if (main.from !== main.to) {
15715
- this.decorations = view.Decoration.none;
15716
- return;
15717
- }
15718
- const doc = view$1.state.doc.toString();
15719
- if (doc !== this.cachedDoc) return;
15720
- if (this.cachedBoundaries.length === 0) {
15721
- this.decorations = view.Decoration.none;
15722
- return;
15723
- }
15724
- const range = findActiveQueryRange(doc, main.head, this.cachedBoundaries);
15725
- this.decorations = range ? buildDecorations(view$1, range) : view.Decoration.none;
15726
- }
15727
- /** Parse queries async (debounced) and update decorations. */
15728
- scheduleDocParse(view$1) {
15729
- if (this.debounceTimer) clearTimeout(this.debounceTimer);
15730
- this.debounceTimer = setTimeout(async () => {
15731
- const seq = ++this.seq;
15732
- const doc = view$1.state.doc.toString();
15733
- if (!doc.trim()) {
15734
- this.cachedDoc = doc;
15735
- this.cachedBoundaries = [];
15736
- if (this.decorations !== view.Decoration.none) {
15737
- this.decorations = view.Decoration.none;
15738
- if (!this.destroyed) view$1.dispatch();
15739
- }
15740
- return;
15741
- }
15742
- let queries;
15743
- try {
15744
- queries = await splitQueries(doc);
15745
- } catch {
15746
- return;
15747
- }
15748
- if (this.destroyed || seq !== this.seq) return;
15749
- this.cachedDoc = doc;
15750
- this.cachedBoundaries = computeBoundaries(queries);
15751
- this.updateFromCache(view$1);
15752
- if (!this.destroyed) view$1.dispatch();
15753
- }, 100);
15754
- }
15755
- },
15756
- { decorations: (v) => v.decorations }
15757
- ),
15758
- view.EditorView.baseTheme({
15759
- ".cm-active-query": {
15760
- boxShadow: `inset -1px 0 0 0 ${colors3__default.default.secondary[300]}, inset 1px 0 0 0 ${colors3__default.default.secondary[300]}`,
15761
- marginRight: "8px"
15762
- },
15763
- ".cm-active-query-first": {
15764
- boxShadow: `inset -1px 0 0 0 ${colors3__default.default.secondary[300]}, inset 1px 0 0 0 ${colors3__default.default.secondary[300]}, inset 0 1px 0 0 ${colors3__default.default.secondary[300]}`,
15765
- borderRadius: "4px 4px 0 0"
15766
- },
15767
- ".cm-active-query-last": {
15768
- boxShadow: `inset -1px 0 0 0 ${colors3__default.default.secondary[300]}, inset 1px 0 0 0 ${colors3__default.default.secondary[300]}, inset 0 -1px 0 0 ${colors3__default.default.secondary[300]}`,
15769
- borderRadius: "0 0 4px 4px"
15770
- },
15771
- ".cm-active-query-first.cm-active-query-last": {
15772
- boxShadow: `inset 0 0 0 1px ${colors3__default.default.secondary[300]}`,
15773
- borderRadius: "4px"
15774
- }
15775
- })
15776
- ];
15777
- };
15778
-
15779
- // src/components/CodeEditor/highlighting.ts
15780
- var HighlightMarker = class extends view.GutterMarker {
15781
- toDOM() {
15782
- const marker = document.createElement("div");
15783
- marker.className = "cm-highlight-marker";
15784
- return marker;
15785
- }
15786
- };
15787
- var highlightMarker = new HighlightMarker();
15788
- var forEachLineInRange = (doc, from, to, callback) => {
15789
- const results = [];
15790
- const fromLine = Math.max(1, from + 1);
15791
- const toLine = Math.min(doc.lines, to + 1);
15792
- for (let i = fromLine; i <= toLine; i++) {
15793
- const line = doc.line(i);
15794
- results.push(callback(line.from));
15795
- }
15796
- return results;
15797
- };
15798
- var setHighlightedLinesEffect = state.StateEffect.define();
15799
- var highlightedLinesField = state.StateField.define({
15800
- create() {
15801
- return null;
15802
- },
15803
- update(value, transaction) {
15804
- for (const effect of transaction.effects) {
15805
- if (effect.is(setHighlightedLinesEffect)) {
15806
- return effect.value;
15807
- }
15808
- }
15809
- return value;
15810
- }
15811
- });
15812
- var highlightGutter = view.gutter({
15813
- class: "cm-highlight-gutter",
15814
- markers: (view) => {
15815
- const highlightInfo = view.state.field(highlightedLinesField, false);
15816
- if (!highlightInfo) {
15817
- return state.RangeSet.empty;
15818
- }
15819
- const markers = forEachLineInRange(
15820
- view.state.doc,
15821
- highlightInfo.from,
15822
- highlightInfo.to,
15823
- (lineFrom) => highlightMarker.range(lineFrom)
15824
- );
15825
- return state.RangeSet.of(markers);
15826
- }
15827
- });
15828
- var errorLineDecorations = state.StateField.define({
15829
- create() {
15830
- return view.Decoration.none;
15831
- },
15832
- update(decorations, transaction) {
15833
- decorations = decorations.map(transaction.changes);
15834
- for (const effect of transaction.effects) {
15835
- if (!effect.is(setHighlightedLinesEffect)) {
15836
- continue;
15837
- }
15838
- if (!effect.value || !effect.value.error) {
15839
- return view.Decoration.none;
15840
- }
15841
- const decorationArray = forEachLineInRange(
15842
- transaction.state.doc,
15843
- effect.value.error.from,
15844
- effect.value.error.to,
15845
- (lineFrom) => view.Decoration.line({ class: "cm-error-line" }).range(lineFrom)
15846
- );
15847
- return view.Decoration.set(decorationArray);
15848
- }
15849
- return decorations;
15850
- },
15851
- provide: (f) => view.EditorView.decorations.from(f)
15852
- });
15853
- var processingLineDecorations = state.StateField.define({
15854
- create() {
15855
- return view.Decoration.none;
15856
- },
15857
- update(decorations, transaction) {
15858
- decorations = decorations.map(transaction.changes);
15859
- for (const effect of transaction.effects) {
15860
- if (!effect.is(setHighlightedLinesEffect)) {
15861
- continue;
15862
- }
15863
- if (!effect.value || !effect.value.processing) {
15864
- return view.Decoration.none;
15865
- }
15866
- const decorationArray = forEachLineInRange(
15867
- transaction.state.doc,
15868
- effect.value.processing.from,
15869
- effect.value.processing.to,
15870
- (lineFrom) => view.Decoration.line({ class: "cm-processing-line" }).range(lineFrom)
15871
- );
15872
- return view.Decoration.set(decorationArray);
15873
- }
15874
- return decorations;
15875
- },
15876
- provide: (f) => view.EditorView.decorations.from(f)
15877
- });
15878
- var highlightedLinesTheme = view.EditorView.baseTheme({
15879
- ".cm-highlight-gutter": {
15880
- width: "2px",
15881
- marginRight: "2px"
15882
- },
15883
- ".cm-highlight-marker": {
15884
- width: "2px",
15885
- height: "100%",
15886
- backgroundColor: colors3__default.default.secondary[500]
15887
- },
15888
- ".cm-error-line": {
15889
- backgroundColor: `${colors3__default.default.error[100]} !important`
15890
- },
15891
- ".cm-processing-line": {
15892
- backgroundColor: `${colors3__default.default.secondary[100]} !important`
15893
- }
15894
- });
15895
- function highlightingExtension(queryParser) {
15896
- return [
15897
- highlightedLinesField,
15898
- highlightGutter,
15899
- errorLineDecorations,
15900
- processingLineDecorations,
15901
- highlightedLinesTheme,
15902
- ...queryParser ? activeQueryHighlight(queryParser) : []
15903
- ];
15904
- }
15905
- function updateHighlighting(view, lines) {
15906
- view.dispatch({ effects: setHighlightedLinesEffect.of(lines ?? null) });
15907
- }
15908
- var setSearchEffect = state.StateEffect.define();
15909
- function findMatches(doc, query) {
15910
- if (!query) return [];
15911
- const text = doc.toString();
15912
- try {
15913
- const regex = new RegExp(escapeStringRegexp(query), "gi");
15914
- return Array.from(text.matchAll(regex)).map((match, index) => {
15915
- const from = match.index;
15916
- const to = from + match[0].length;
15917
- return { from, to, text: match[0], localIndex: index };
15918
- });
15919
- } catch (e) {
15920
- console.warn("Invalid search regex:", e);
15921
- return [];
15922
- }
15923
- }
15924
- function createDecorations(matches, selectedLocalIndex) {
15925
- const decorations = matches.map((match) => {
15926
- const isSelected = match.localIndex === selectedLocalIndex;
15927
- const decoration = view.Decoration.mark({
15928
- class: isSelected ? "cm-searchMatch-selected" : "cm-searchMatch"
15929
- });
15930
- return decoration.range(match.from, match.to);
15931
- });
15932
- return view.Decoration.set(decorations, true);
15933
- }
15934
- var searchField = state.StateField.define({
15935
- create() {
15936
- return {
15937
- query: "",
15938
- selectedMatchIndex: void 0,
15939
- matches: [],
15940
- decorations: view.Decoration.none
15941
- };
15942
- },
15943
- update(state, tr) {
15944
- let newState = state;
15945
- for (const effect of tr.effects) {
15946
- if (!effect.is(setSearchEffect)) {
15947
- continue;
15948
- }
15949
- const { query, selectedMatchIndex } = effect.value;
15950
- const matches = findMatches(tr.state.doc, query);
15951
- const decorations = createDecorations(matches, selectedMatchIndex);
15952
- newState = {
15953
- query,
15954
- selectedMatchIndex,
15955
- matches,
15956
- decorations
15957
- };
15958
- }
15959
- if (tr.docChanged && newState.query) {
15960
- const matches = findMatches(tr.state.doc, newState.query);
15961
- const decorations = createDecorations(matches, newState.selectedMatchIndex);
15962
- newState = {
15963
- ...newState,
15964
- matches,
15965
- decorations
15966
- };
15967
- }
15968
- return newState;
15969
- },
15970
- provide: (field) => view.EditorView.decorations.from(field, (state) => state.decorations)
15971
- });
15972
- var searchViewPlugin = view.ViewPlugin.fromClass(
15973
- class {
15974
- lastSelectedIndex;
15975
- update(update) {
15976
- const state = update.state.field(searchField);
15977
- if (state.selectedMatchIndex !== void 0 && state.selectedMatchIndex !== this.lastSelectedIndex) {
15978
- const match = state.matches[state.selectedMatchIndex];
15979
- if (match) {
15980
- requestAnimationFrame(() => {
15981
- update.view.dispatch({
15982
- effects: view.EditorView.scrollIntoView(match.from, { y: "center" })
15983
- });
15984
- });
15985
- }
15986
- this.lastSelectedIndex = state.selectedMatchIndex;
15987
- }
15988
- if (state.selectedMatchIndex === void 0) {
15989
- this.lastSelectedIndex = void 0;
15990
- }
15991
- }
15992
- }
15993
- );
15994
- var searchTheme = view.EditorView.baseTheme({
15995
- ".cm-searchMatch": {
15996
- backgroundColor: colors3__default.default.secondary[100]
15997
- },
15998
- ".cm-searchMatch > span": {
15999
- color: `${colors3__default.default.secondary[600]} !important`
16000
- },
16001
- ".cm-searchMatch-selected": {
16002
- backgroundColor: colors3__default.default.secondary[600]
16003
- },
16004
- ".cm-searchMatch-selected > span": {
16005
- color: `${colors3__default.default.white} !important`
16006
- }
16007
- });
16008
- function searchExtension() {
16009
- return [searchField, searchViewPlugin, searchTheme];
16010
- }
16011
- function updateSearch(view, query, selectedMatchIndex) {
16012
- view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });
16013
- }
16014
- var BASIS_SETUP2 = {
16015
- drawSelection: false,
16016
- defaultKeymap: false,
16017
- completionKeymap: false,
16018
- searchKeymap: false
16019
- };
16020
- var CUSTOM_KEYMAP = [
16021
- {
16022
- key: "Escape",
16023
- stopPropagation: true,
16024
- run: (view) => {
16025
- view.contentDOM.blur();
16026
- return true;
16027
- }
16028
- }
16029
- ];
16030
- var theme = {
16031
- ...baseThemeStyles,
16032
- "&.cm-editor": {
16033
- border: "solid 1px transparent",
16034
- background: colors3__default.default.white,
16035
- borderRadius: "8px",
16036
- paddingTop: "8px",
16037
- paddingBottom: "8px"
16038
- },
16039
- '&.cm-editor:has(.cm-content[contenteditable="true"]):hover': {
16040
- borderColor: colors3__default.default.secondary[500]
16041
- },
16042
- '&.cm-editor:has(.cm-content[contenteditable="true"]):focus-within': {
16043
- borderColor: colors3__default.default.secondary[500],
16044
- boxShadow: `0 0 0 4px ${colors3__default.default.secondary[200]}`
16045
- },
16046
- "&.cm-editor .cm-scroller": { overflowAnchor: "none" },
16047
- "&.cm-editor :is(.cm-gutters,.cm-scroller)": { background: colors3__default.default.white },
16048
- '&.cm-editor:has(.cm-content[contenteditable="false"])': { background: colors3__default.default.neutral[100] },
16049
- '&.cm-editor:has(.cm-content[contenteditable="false"]) :is(.cm-scroller,.cm-gutters)': {
16050
- background: colors3__default.default.neutral[100]
16051
- }
16052
- };
16053
- var SqlEditor = ({
16054
- value,
16055
- onChange,
16056
- onSelectionChange,
16057
- onCreateEditor,
16058
- onDestroyEditor,
16059
- onBlurEditor,
16060
- onFocusEditor,
16061
- placeholder = "",
16062
- searchQuery = "",
16063
- searchMatchIndex,
16064
- readOnly = false,
16065
- extraKeys,
16066
- queryParser,
16067
- autoFocus = false,
16068
- lineNumbers = true,
16069
- className,
16070
- schema,
16071
- variables,
16072
- defaultDatabase,
16073
- defaultSchema,
16074
- highlightLines,
16075
- dialect
16076
- }) => {
16077
- const editorRef = react.useRef(null);
16078
- const extensions = react.useMemo(() => {
16079
- const baseKeymap = [...commands.defaultKeymap, ...CUSTOM_KEYMAP];
16080
- return [
16081
- CodeMirror.EditorView.lineWrapping,
16082
- CodeMirror.keymap.of(extraKeys ? [...extraKeys, ...baseKeymap] : baseKeymap),
16083
- ...codemirrorLangSql.installExtensions({ schema, defaultDatabase, defaultSchema, variables, dialect }),
16084
- searchExtension(),
16085
- highlightingExtension(queryParser),
16086
- CodeMirror.EditorView.theme(theme),
16087
- onBlurEditor ? CodeMirror.EditorView.domEventHandlers({ blur: (_, view) => onBlurEditor(view) }) : [],
16088
- onFocusEditor ? CodeMirror.EditorView.domEventHandlers({ focus: (_, view) => onFocusEditor(view) }) : []
16089
- ];
16090
- }, [
16091
- extraKeys,
16092
- queryParser,
16093
- schema,
16094
- defaultDatabase,
16095
- defaultSchema,
16096
- variables,
16097
- dialect,
16098
- onBlurEditor,
16099
- onFocusEditor
16100
- ]);
16101
- const defaultSetup = react.useMemo(() => {
16102
- return { ...BASIS_SETUP2, lineNumbers };
16103
- }, [lineNumbers]);
16104
- react.useEffect(() => {
16105
- if (editorRef.current?.view) {
16106
- updateHighlighting(editorRef.current.view, highlightLines);
16107
- }
16108
- }, [highlightLines]);
16109
- react.useEffect(() => {
16110
- if (editorRef.current?.view) {
16111
- updateSearch(editorRef.current.view, searchQuery, searchMatchIndex);
16112
- }
16113
- }, [searchQuery, searchMatchIndex]);
16114
- react.useEffect(() => {
16115
- if (!onDestroyEditor) return;
16116
- return () => {
16117
- onDestroyEditor();
16118
- };
16119
- }, [onDestroyEditor]);
16120
- const handleOnCreate = react.useCallback(
16121
- (view, state) => {
16122
- onCreateEditor?.(view, state);
16123
- if (highlightLines) {
16124
- updateHighlighting(view, highlightLines);
16125
- }
16126
- if (searchQuery) {
16127
- updateSearch(view, searchQuery, searchMatchIndex);
16128
- }
16129
- },
16130
- [onCreateEditor, highlightLines, searchQuery, searchMatchIndex]
16131
- );
16132
- const handleOnUpdate = react.useCallback(
16133
- (update) => {
16134
- if (update.selectionSet) {
16135
- const { main } = update.state.selection;
16136
- const text = update.state.sliceDoc(main.from, main.to);
16137
- onSelectionChange?.(text);
16138
- }
16139
- },
16140
- [onSelectionChange]
16141
- );
16142
- return /* @__PURE__ */ jsxRuntime.jsx(
16143
- CodeMirror__default.default,
16144
- {
16145
- ref: editorRef,
16146
- theme: customTheme,
16147
- extensions,
16148
- value,
16149
- onChange,
16150
- onUpdate: handleOnUpdate,
16151
- onCreateEditor: handleOnCreate,
16152
- autoFocus,
16153
- placeholder,
16154
- className,
16155
- readOnly,
16156
- editable: !readOnly,
16157
- basicSetup: defaultSetup
16158
- }
16159
- );
16160
- };
16161
15020
 
16162
15021
  Object.defineProperty(exports, "Slot", {
16163
15022
  enumerable: true,
@@ -16223,7 +15082,6 @@ exports.Checkbox = Checkbox;
16223
15082
  exports.Clipboard = Clipboard;
16224
15083
  exports.ClipboardButton = ClipboardButton;
16225
15084
  exports.ClipboardInline = ClipboardInline;
16226
- exports.CodeEditor = CodeEditor;
16227
15085
  exports.Collapse = Collapse;
16228
15086
  exports.Collapsible = Collapsible;
16229
15087
  exports.CollapsiblePanel = CollapsiblePanel;
@@ -16263,7 +15121,6 @@ exports.Kbd = Kbd;
16263
15121
  exports.Label = Label2;
16264
15122
  exports.Link = Link;
16265
15123
  exports.MarkedText = MarkedText;
16266
- exports.MergeEditor = MergeEditor;
16267
15124
  exports.MessageBubble = MessageBubble;
16268
15125
  exports.Modal = Modal;
16269
15126
  exports.MultiActionButtonGroup = MultiActionButtonGroup;
@@ -16304,7 +15161,6 @@ exports.Skeleton = Skeleton;
16304
15161
  exports.SkeletonList = SkeletonList;
16305
15162
  exports.Slider = Slider;
16306
15163
  exports.SplitButton = SplitButton;
16307
- exports.SqlEditor = SqlEditor;
16308
15164
  exports.Stepper = Stepper;
16309
15165
  exports.SuggestedPrompt = SuggestedPrompt;
16310
15166
  exports.Switch = Switch;