@keboola/design 3.2.3 → 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.
@@ -0,0 +1,1976 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var autocomplete = require('@codemirror/autocomplete');
5
+ var langJson = require('@codemirror/lang-json');
6
+ var lint = require('@codemirror/lint');
7
+ var merge = require('@codemirror/merge');
8
+ var view = require('@codemirror/view');
9
+ var CodeMirror = require('@uiw/react-codemirror');
10
+ var clsx = require('clsx');
11
+ var tailwindMerge = require('tailwind-merge');
12
+ var reactTooltip = require('@radix-ui/react-tooltip');
13
+ var classVarianceAuthority = require('class-variance-authority');
14
+ var brandRegistry = require('@keboola/brand-registry');
15
+ var jsxRuntime = require('react/jsx-runtime');
16
+ var reactSlot = require('@radix-ui/react-slot');
17
+ var lucide_react_star = require('lucide-react');
18
+ var langJavascript = require('@codemirror/lang-javascript');
19
+ var langPython = require('@codemirror/lang-python');
20
+ var langSql = require('@codemirror/lang-sql');
21
+ var language = require('@codemirror/language');
22
+ var r = require('@codemirror/legacy-modes/mode/r');
23
+ var shell = require('@codemirror/legacy-modes/mode/shell');
24
+ var codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
25
+ var codemirrorLangSfsql = require('@keboola/codemirror-lang-sfsql');
26
+ var colors = require('@keboola/tailwind-config/colors');
27
+ var commands = require('@codemirror/commands');
28
+ var codemirrorLangSql = require('@keboola/codemirror-lang-sql');
29
+ var state = require('@codemirror/state');
30
+
31
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
32
+
33
+ function _interopNamespace(e) {
34
+ if (e && e.__esModule) return e;
35
+ var n = Object.create(null);
36
+ if (e) {
37
+ Object.keys(e).forEach(function (k) {
38
+ if (k !== 'default') {
39
+ var d = Object.getOwnPropertyDescriptor(e, k);
40
+ Object.defineProperty(n, k, d.get ? d : {
41
+ enumerable: true,
42
+ get: function () { return e[k]; }
43
+ });
44
+ }
45
+ });
46
+ }
47
+ n.default = e;
48
+ return Object.freeze(n);
49
+ }
50
+
51
+ var CodeMirror__default = /*#__PURE__*/_interopDefault(CodeMirror);
52
+ var lucide_react_star__namespace = /*#__PURE__*/_interopNamespace(lucide_react_star);
53
+ var colors__default = /*#__PURE__*/_interopDefault(colors);
54
+
55
+ var __defProp = Object.defineProperty;
56
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
57
+ var __getOwnPropNames = Object.getOwnPropertyNames;
58
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
59
+ var __export = (target, all) => {
60
+ for (var name in all)
61
+ __defProp(target, name, { get: all[name], enumerable: true });
62
+ };
63
+ var __copyProps = (to, from, except, desc) => {
64
+ if (from && typeof from === "object" || typeof from === "function") {
65
+ for (let key of __getOwnPropNames(from))
66
+ if (!__hasOwnProp.call(to, key) && key !== except)
67
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
68
+ }
69
+ return to;
70
+ };
71
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget);
72
+
73
+ // src/constants/keyCodes.ts
74
+ var keyCodes = {
75
+ ENTER: "Enter",
76
+ ESCAPE: "Escape",
77
+ SPACE: " "
78
+ };
79
+ var twMerge = tailwindMerge.extendTailwindMerge({
80
+ prefix: "tw-"
81
+ });
82
+ var cn = (...classes) => twMerge(clsx.clsx(...classes));
83
+
84
+ // src/utils/copyToClipboard.ts
85
+ var copyToClipboard = (text) => {
86
+ return navigator.clipboard.writeText(text);
87
+ };
88
+ var ThemeContext = react.createContext(null);
89
+
90
+ // src/components/internal/useIsLegacyBrand.ts
91
+ var useIsLegacyBrand = () => {
92
+ const context = react.use(ThemeContext);
93
+ return context === null || context.brand.id === brandRegistry.keboolaLegacy.id;
94
+ };
95
+ var tooltipVariants = classVarianceAuthority.cva(
96
+ [
97
+ "tailwindcss-preflight",
98
+ "tw-inline-block",
99
+ "tw-break-anywhere",
100
+ "tw-max-h-96",
101
+ "tw-overflow-y-auto",
102
+ "tw-z-[1060]",
103
+ // legacy (dark) chrome — default
104
+ "tw-rounded",
105
+ "tw-bg-neutral-800",
106
+ "tw-text-white",
107
+ // argo chrome overrides — semantic floating-panel tokens
108
+ "data-[argo=true]:tw-rounded-2xl",
109
+ "data-[argo=true]:tw-border",
110
+ "data-[argo=true]:tw-border-solid",
111
+ "data-[argo=true]:tw-border-border",
112
+ "data-[argo=true]:tw-bg-popover",
113
+ "data-[argo=true]:tw-text-popover-foreground",
114
+ "data-[argo=true]:tw-shadow-md",
115
+ // argo open animation
116
+ "data-[argo=true]:data-[state=delayed-open]:tw-animate-in",
117
+ "data-[argo=true]:data-[state=instant-open]:tw-animate-in",
118
+ "data-[argo=true]:data-[state=delayed-open]:tw-fade-in-0",
119
+ "data-[argo=true]:data-[state=instant-open]:tw-fade-in-0",
120
+ "data-[argo=true]:data-[state=delayed-open]:tw-zoom-in-95",
121
+ "data-[argo=true]:data-[state=instant-open]:tw-zoom-in-95",
122
+ // argo closed animation
123
+ "data-[argo=true]:data-[state=closed]:tw-animate-out",
124
+ "data-[argo=true]:data-[state=closed]:tw-fade-out-0",
125
+ "data-[argo=true]:data-[state=closed]:tw-zoom-out-95",
126
+ // argo position animation
127
+ "data-[argo=true]:data-[side=bottom]:tw-slide-in-from-top-2",
128
+ "data-[argo=true]:data-[side=left]:tw-slide-in-from-right-2",
129
+ "data-[argo=true]:data-[side=right]:tw-slide-in-from-left-2",
130
+ "data-[argo=true]:data-[side=top]:tw-slide-in-from-bottom-2"
131
+ ],
132
+ {
133
+ defaultVariants: {
134
+ variant: "action"
135
+ },
136
+ variants: {
137
+ variant: {
138
+ action: [
139
+ "tw-max-w-fit",
140
+ "tw-px-3",
141
+ "tw-py-2",
142
+ "tw-text-center",
143
+ "tw-text-xs",
144
+ "tw-font-medium",
145
+ "tw-uppercase",
146
+ "tw-tracking-wider"
147
+ ],
148
+ explanatory: [
149
+ "tw-max-w-80",
150
+ "tw-px-4",
151
+ "tw-py-3",
152
+ "tw-text-left",
153
+ "tw-text-sm",
154
+ "tw-font-normal"
155
+ ]
156
+ }
157
+ }
158
+ }
159
+ );
160
+ var TooltipContent = ({
161
+ className,
162
+ variant,
163
+ argo,
164
+ keepOpenOnPointerDownOutside = false,
165
+ children,
166
+ onPointerDownOutside,
167
+ sideOffset = 8,
168
+ collisionPadding = 8,
169
+ hideWhenDetached = true,
170
+ placement = "right",
171
+ ...rest
172
+ }) => {
173
+ const isLegacy = useIsLegacyBrand();
174
+ const renderArgo = !isLegacy || argo === true;
175
+ const handlePointerDownOutside = (event) => {
176
+ if (keepOpenOnPointerDownOutside) event.preventDefault();
177
+ onPointerDownOutside?.(event);
178
+ };
179
+ return /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
180
+ reactTooltip.Content,
181
+ {
182
+ ...rest,
183
+ "data-tooltip-content": renderArgo ? void 0 : true,
184
+ "data-argo": renderArgo,
185
+ sideOffset,
186
+ collisionPadding,
187
+ onPointerDownOutside: handlePointerDownOutside,
188
+ className: tooltipVariants({ className, variant }),
189
+ hideWhenDetached,
190
+ side: placement,
191
+ children
192
+ }
193
+ ) });
194
+ };
195
+ var DELAY_SHOW_TOOLTIP = 300;
196
+ var TooltipRoot = ({ children, delayDuration = DELAY_SHOW_TOOLTIP, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Root, { ...rest, delayDuration, children });
197
+ var TooltipTrigger = ({
198
+ ref,
199
+ children,
200
+ className,
201
+ keepOpenOnClick = false,
202
+ onClick,
203
+ onPointerDown,
204
+ asChild,
205
+ ...rest
206
+ }) => {
207
+ const handleClick = (event) => {
208
+ if (keepOpenOnClick) event.preventDefault();
209
+ onClick?.(event);
210
+ };
211
+ const handlePointerDown = (event) => {
212
+ if (keepOpenOnClick) event.preventDefault();
213
+ onPointerDown?.(event);
214
+ };
215
+ return /* @__PURE__ */ jsxRuntime.jsx(
216
+ reactTooltip.Trigger,
217
+ {
218
+ ...rest,
219
+ asChild: true,
220
+ ref,
221
+ className: cn("tailwindcss-preflight", className),
222
+ onClick: handleClick,
223
+ onPointerDown: handlePointerDown,
224
+ children: asChild ? children : (
225
+ // Default-mode trigger wraps children in a span so Radix has a
226
+ // single DOM element to attach handlers to. `tailwindcss-preflight`
227
+ // (merged in via Slot) activates Tailwind's preflight inside the
228
+ // span, which sets `svg { display: block }` — without an inline-flex
229
+ // container that would stack any bare Lucide icon onto its own
230
+ // line. `tw-inline-flex tw-items-center` keeps icon + text aligned.
231
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tw-inline-flex tw-items-center", children })
232
+ )
233
+ }
234
+ );
235
+ };
236
+ var ACTION_TOOLTIP_LIMIT = 30;
237
+ var Tooltip = ({
238
+ tooltip,
239
+ children,
240
+ className,
241
+ keepOpenOnTriggerClick = false,
242
+ variant,
243
+ argo,
244
+ placement = "right",
245
+ forceHide = false,
246
+ forceShow = false,
247
+ // trigger props
248
+ triggerAsChild = false
249
+ }) => {
250
+ const [open, setOpen] = react.useState(false);
251
+ const resolvedVariant = (() => {
252
+ if (!!variant) return variant;
253
+ if (typeof tooltip === "string" && tooltip.length > ACTION_TOOLTIP_LIMIT) return "explanatory";
254
+ return "action";
255
+ })();
256
+ const isActionVariant = resolvedVariant === "action";
257
+ const handleKeyUp = (event) => {
258
+ if (![keyCodes.ENTER, keyCodes.SPACE].includes(event.key)) return;
259
+ event.stopPropagation();
260
+ };
261
+ return /* @__PURE__ */ jsxRuntime.jsxs(
262
+ TooltipRoot,
263
+ {
264
+ open: !!tooltip && (open || forceShow) && !forceHide,
265
+ onOpenChange: setOpen,
266
+ disableHoverableContent: isActionVariant,
267
+ children: [
268
+ /* @__PURE__ */ jsxRuntime.jsx(
269
+ TooltipTrigger,
270
+ {
271
+ asChild: triggerAsChild,
272
+ keepOpenOnClick: keepOpenOnTriggerClick,
273
+ onKeyUp: handleKeyUp,
274
+ children
275
+ }
276
+ ),
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ TooltipContent,
279
+ {
280
+ className,
281
+ variant: resolvedVariant,
282
+ argo,
283
+ placement,
284
+ keepOpenOnPointerDownOutside: keepOpenOnTriggerClick,
285
+ children: tooltip
286
+ }
287
+ )
288
+ ]
289
+ }
290
+ );
291
+ };
292
+ Tooltip.Root = TooltipRoot;
293
+ Tooltip.Content = TooltipContent;
294
+ Tooltip.Trigger = TooltipTrigger;
295
+
296
+ // src/utils/escapeStringRegexp.ts
297
+ var escapeStringRegexp = (string) => string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
298
+ var helpVariants = classVarianceAuthority.cva(["tw-m-0", "tw-text-xs"], {
299
+ defaultVariants: {
300
+ state: "default"
301
+ },
302
+ variants: {
303
+ state: {
304
+ default: ["tw-text-muted-foreground"],
305
+ error: ["tw-text-destructive"],
306
+ warning: ["tw-text-warning-500"]
307
+ }
308
+ }
309
+ });
310
+ var HelpBlock = ({ children, className, state = "default", testId }) => {
311
+ if (!children) return null;
312
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { "data-testid": testId, className: helpVariants({ state, className }), children });
313
+ };
314
+
315
+ // src/icons/index.ts
316
+ var icons_exports = {};
317
+ __export(icons_exports, {
318
+ Keboola: () => Keboola
319
+ });
320
+ __reExport(icons_exports, lucide_react_star__namespace);
321
+ var Keboola = react.forwardRef(
322
+ ({ size = 24, color = "currentColor", className, children, ...rest }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
323
+ "svg",
324
+ {
325
+ ref,
326
+ xmlns: "http://www.w3.org/2000/svg",
327
+ width: size,
328
+ height: size,
329
+ viewBox: "0 0 300 512",
330
+ fill: color,
331
+ className: cn("lucide", className),
332
+ ...rest,
333
+ children: [
334
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M152 320C79.7 320 24.5 233.9 24.5 124.7C24.5 15.6 70.5 0 152 0s123.6 15.6 123.6 124.7C275.5 233.9 217.7 320 152 320zm-8.7-50.5c0-11.2-9.5-20.3-21.2-20.3s-21.2 9.1-21.2 20.3c0 11.2 9.5 20.3 21.2 20.3s21.2-9.1 21.2-20.3zm55.7 0c0-11.2-9.5-20.3-21.2-20.3s-21.2 9.1-21.2 20.3c0 11.2 9.5 20.3 21.2 20.3s21.2-9.1 21.2-20.3zm68.9 115.1c10.2 9.3 20.2 20.5 29 35c5.9 9.7 2.6 22.1-7.5 27.8c-3.4 1.9-7.1 2.8-10.7 2.8c-7.2 0-14.3-3.6-18.3-10c-6.8-11.1-13.8-18.9-21.7-26.1c-7.3-6.7-15.6-12.7-24.9-19.5c-.7-.5-1.4-1-2.1-1.5c-5-3.6-10-6.8-14.9-9.4c.6 1 1.2 2.1 1.8 3.2c14.4 26.4 29.2 63.1 29.2 104.9c0 11.2-9.5 20.3-21.2 20.3c-11.7 0-21.2-9.1-21.2-20.3c.1-31.8-11.6-62.3-23.8-84.9c-4-7.4-8-13.9-11.6-19.3c-3.4 5.2-7.2 11.3-11 18.3c-12.5 22.7-24.5 53.8-24.4 86c0 11.2-9.5 20.3-21.2 20.3s-21.2-9.1-21.2-20.3c.1-41.8 14.9-78.4 29.2-104.9c.6-1.1 1.2-2.1 1.8-3.2c-5 2.7-9.9 5.8-14.9 9.4c-.6 .5-1.3 .9-1.9 1.4c-9.5 6.9-17.8 12.9-25.1 19.7c-7.9 7.2-14.9 15.1-21.7 26.1c-5.9 9.7-18.9 12.9-29 7.2C.5 441.8-2.9 429.3 3.1 419.7c8.9-14.4 18.8-25.7 29-35c9.2-8.4 18.5-15.1 27.6-21.7c1-.7 2-1.4 3-2.2c4.7-3.5 9.6-6.7 14.6-9.6c-5-2.9-9.8-6.1-14.6-9.6C39.8 325 19.9 302.5 3.1 275.1c-5.9-9.7-2.6-22.1 7.5-27.8c10.1-5.7 23.1-2.5 29 7.2c14.6 23.7 31.1 42 48.7 54.9c18.9 13.7 37.4 20.5 56.5 21.5c1.7-.1 3.5-.1 5.2-.1c1.8 0 3.5 .1 5.2 .1c0 0 0 0 0 0c19.1-1.1 37.6-7.9 56.5-21.5c17.6-12.8 34.2-31.2 48.7-54.9c6-9.7 18.9-12.9 29-7.2c10.1 5.7 13.4 18.1 7.5 27.8c-16.8 27.4-36.7 49.9-59.6 66.6c-4.7 3.5-9.6 6.7-14.5 9.6c4.9 2.9 9.8 6.1 14.5 9.6c.9 .7 1.8 1.3 2.7 2c9.2 6.7 18.5 13.5 27.9 22z" }),
335
+ children
336
+ ]
337
+ }
338
+ )
339
+ );
340
+ Keboola.displayName = "Keboola";
341
+ var variants = classVarianceAuthority.cva(
342
+ [
343
+ "tailwindcss-preflight",
344
+ "tw-group/button",
345
+ "tw-border-box",
346
+ // layout
347
+ "tw-relative",
348
+ "tw-flex",
349
+ "tw-items-center",
350
+ "tw-justify-center",
351
+ "tw-gap-2",
352
+ // text
353
+ "tw-text-xs",
354
+ "tw-leading-5",
355
+ "tw-font-medium",
356
+ "tw-tracking-[1px]",
357
+ "tw-uppercase",
358
+ // border
359
+ "tw-rounded",
360
+ "tw-border",
361
+ "tw-border-transparent",
362
+ // styling
363
+ "tw-shadow-none",
364
+ "[a]:tw-cursor-pointer",
365
+ // explicitly set for anchor
366
+ "focus-visible:tw-outline",
367
+ "focus-visible:tw-outline-1",
368
+ "focus-visible:-tw-outline-offset-1",
369
+ "focus-visible:tw-outline-secondary-500",
370
+ "focus-visible:tw-ring-4",
371
+ "focus-visible:tw-ring-secondary-200",
372
+ // disabled
373
+ "disabled:tw-opacity-40",
374
+ "disabled:tw-cursor-not-allowed",
375
+ // anchor support
376
+ "!tw-no-underline",
377
+ "aria-disabled:tw-opacity-40",
378
+ "aria-disabled:tw-cursor-not-allowed",
379
+ "[&_svg]:tw-shrink-0"
380
+ ],
381
+ {
382
+ defaultVariants: {
383
+ size: "medium",
384
+ variant: "primary",
385
+ block: false
386
+ },
387
+ variants: {
388
+ block: {
389
+ true: ["tw-w-full"]
390
+ },
391
+ variant: {
392
+ primary: [
393
+ "tw-text-white",
394
+ "tw-bg-primary-500",
395
+ "focus:tw-text-white",
396
+ "hover:tw-text-white",
397
+ "hover:not-disabled:tw-bg-primary-600",
398
+ "active:not-disabled:tw-bg-primary-800",
399
+ // anchor disabled override
400
+ "aria-disabled:!tw-bg-primary-500"
401
+ ],
402
+ secondary: [
403
+ "tw-text-white",
404
+ "tw-bg-secondary-500",
405
+ "focus:tw-text-white",
406
+ "hover:tw-text-white",
407
+ "hover:not-disabled:tw-bg-secondary-700",
408
+ "active:not-disabled:tw-bg-secondary-800",
409
+ // anchor disabled override
410
+ "aria-disabled:!tw-bg-secondary-500"
411
+ ],
412
+ danger: [
413
+ "tw-text-white",
414
+ "tw-bg-error-500",
415
+ "focus:tw-text-white",
416
+ "hover:tw-text-white",
417
+ "hover:not-disabled:tw-bg-error-600",
418
+ "active:not-disabled:tw-bg-error-700",
419
+ // anchor disabled override
420
+ "aria-disabled:!tw-bg-error-500"
421
+ ],
422
+ invisible: [
423
+ "tw-text-neutral-800",
424
+ "tw-bg-transparent",
425
+ "focus:tw-text-neutral-800",
426
+ "hover:not-disabled:tw-bg-neutral-100",
427
+ "hover:tw-text-neutral-800",
428
+ "active:not-disabled:tw-bg-neutral-150",
429
+ // contrasting icon on hover/active
430
+ "[&_svg]:tw-text-neutral-400",
431
+ "[&_svg]:hover:not-disabled:tw-text-secondary-600",
432
+ "[&_svg]:active:not-disabled:tw-text-secondary-600",
433
+ // anchor disabled override
434
+ "aria-disabled:!tw-bg-transparent"
435
+ ],
436
+ outline: [
437
+ "tw-text-neutral-800",
438
+ "tw-bg-white",
439
+ // border
440
+ "!tw-border-neutral-200",
441
+ "hover:tw-text-neutral-800",
442
+ "focus:tw-text-neutral-800",
443
+ "hover:not-disabled:!tw-border-neutral-300",
444
+ "hover:not-disabled:tw-bg-neutral-100",
445
+ "active:not-disabled:tw-bg-neutral-200",
446
+ // contrasting icon hover, same as invisible
447
+ "[&_svg]:tw-text-neutral-400",
448
+ "[&_svg]:not-disabled:hover:tw-text-secondary-600",
449
+ "[&_svg]:active:not-disabled:tw-text-secondary-600",
450
+ // anchor disabled override
451
+ "aria-disabled:!tw-bg-white",
452
+ "aria-disabled:!tw-border-neutral-200"
453
+ ],
454
+ inline: [
455
+ "tw-text-neutral-800",
456
+ "tw-bg-transparent",
457
+ "tw-rounded-full",
458
+ "[&_svg]:tw-text-neutral-400",
459
+ "[&_svg]:not-disabled:hover:tw-text-secondary-600",
460
+ "[&_svg]:not-disabled:focus:tw-text-secondary-600"
461
+ ]
462
+ },
463
+ size: {
464
+ medium: [
465
+ "tw-max-h-10",
466
+ "tw-min-h-10",
467
+ "tw-px-4",
468
+ "tw-py-2.5",
469
+ '[&_svg:not([class*="tw-size-"])]:tw-size-4'
470
+ ],
471
+ small: [
472
+ "tw-max-h-8",
473
+ "tw-min-h-8",
474
+ "tw-px-4",
475
+ "tw-py-1.5",
476
+ '[&_svg:not([class*="tw-size-"])]:tw-size-4'
477
+ ],
478
+ large: [
479
+ "tw-max-h-12",
480
+ "tw-min-h-12",
481
+ "tw-px-4",
482
+ "tw-py-3.5",
483
+ '[&_svg:not([class*="tw-size-"])]:tw-size-4'
484
+ ],
485
+ "icon-lg": ["tw-size-12", "tw-p-0", '[&_svg:not([class*="tw-size-"])]:tw-size-6'],
486
+ icon: ["tw-size-10", "tw-p-0", '[&_svg:not([class*="tw-size-"])]:tw-size-4'],
487
+ "icon-sm": ["tw-size-8", "tw-p-0", '[&_svg:not([class*="tw-size-"])]:tw-size-4'],
488
+ "icon-xs": ["tw-size-6", "tw-p-0", '[&_svg:not([class*="tw-size-"])]:tw-size-4'],
489
+ "icon-2xs": [
490
+ "!tw-inline-flex",
491
+ "tw-size-5",
492
+ "tw-max-h-5",
493
+ '[&_svg:not([class*="tw-size-"])]:tw-size-3'
494
+ ],
495
+ "icon-3xs": ["tw-h-fit", "tw-w-fit", '[&_svg:not([class*="tw-size-"])]:tw-size-4']
496
+ }
497
+ }
498
+ }
499
+ );
500
+ var argoVariants = classVarianceAuthority.cva(
501
+ [
502
+ "tailwindcss-preflight",
503
+ // layout
504
+ "tw-relative",
505
+ "tw-inline-flex",
506
+ "tw-items-center",
507
+ "tw-justify-center",
508
+ "tw-whitespace-nowrap",
509
+ "tw-gap-2",
510
+ // border
511
+ "tw-border",
512
+ "tw-border-transparent",
513
+ "tw-rounded-lg",
514
+ // text
515
+ "tw-font-medium",
516
+ "tw-select-none",
517
+ // focus visible
518
+ "!tw-outline-none",
519
+ "focus-visible:tw-ring-2",
520
+ // disabled
521
+ "disabled:tw-cursor-not-allowed",
522
+ "disabled:tw-opacity-50",
523
+ "active:tw-opacity-60",
524
+ "tw-transition-all",
525
+ "tw-bg-clip-padding",
526
+ // anchor support
527
+ "!tw-no-underline",
528
+ "aria-disabled:tw-cursor-not-allowed",
529
+ "aria-disabled:tw-opacity-50",
530
+ // icon
531
+ "tw-shrink-0",
532
+ "[&_svg]:tw-pointer-events-none",
533
+ "[&_svg]:tw-shrink-0",
534
+ "[&_svg:not([class*='tw-size-'])]:tw-size-4"
535
+ ],
536
+ {
537
+ defaultVariants: {
538
+ variant: "primary",
539
+ size: "medium"
540
+ },
541
+ variants: {
542
+ block: {
543
+ true: ["tw-w-full"]
544
+ },
545
+ variant: {
546
+ primary: [
547
+ "tw-bg-primary",
548
+ "tw-text-primary-foreground",
549
+ "[a]:hover:tw-bg-primary/80",
550
+ "hover:not-disabled:tw-bg-primary/90",
551
+ "hover:tw-text-primary-foreground",
552
+ "focus:tw-text-primary-foreground",
553
+ "focus-visible:tw-border-primary",
554
+ "focus-visible:tw-ring-primary/50"
555
+ ],
556
+ secondary: [
557
+ "tw-bg-primary/10",
558
+ "tw-text-primary",
559
+ "hover:not-disabled:tw-bg-primary/20",
560
+ "focus-visible:tw-border-primary",
561
+ "focus-visible:tw-ring-primary/50"
562
+ ],
563
+ // should be called "destructive" by Figma
564
+ danger: [
565
+ "tw-bg-destructive",
566
+ "tw-text-destructive-foreground",
567
+ "hover:tw-text-destructive-foreground",
568
+ "focus:tw-text-destructive-foreground",
569
+ "focus-visible:tw-border-destructive",
570
+ "focus-visible:tw-ring-destructive/20"
571
+ ],
572
+ outline: [
573
+ "!tw-border-input",
574
+ "tw-bg-background",
575
+ "hover:not-disabled:tw-bg-accent",
576
+ "hover:not-disabled:tw-text-accent-foreground",
577
+ "hover:active:tw-bg-background",
578
+ "focus-visible:!tw-border-primary",
579
+ "focus-visible:tw-ring-primary/50"
580
+ ],
581
+ // should be called "ghost" by Figma
582
+ invisible: [
583
+ "tw-bg-transparent",
584
+ "tw-text-foreground",
585
+ "hover:not-disabled:tw-bg-accent",
586
+ "hover:not-disabled:tw-text-accent-foreground",
587
+ "hover:not-disabled:tw-border-accent",
588
+ "focus-visible:tw-ring-primary/50"
589
+ ],
590
+ // should be called "link" by Figma
591
+ inline: [
592
+ "tw-bg-transparent",
593
+ "tw-text-primary",
594
+ "hover:tw-underline",
595
+ "hover:active:tw-bg-transparent",
596
+ "focus-visible:tw-ring-primary/50"
597
+ ]
598
+ },
599
+ size: {
600
+ // should be called "default" by Figma
601
+ medium: ["tw-max-h-9", "tw-py-2", "tw-px-4", "tw-text-sm"],
602
+ // should be called "small" by Figma
603
+ small: ["tw-max-h-8", "tw-py-2", "tw-px-3", "tw-text-xs"],
604
+ // should be called "large" by Figma
605
+ large: ["tw-max-h-10", "tw-py-2.5", "tw-px-6", "tw-text-sm"],
606
+ "icon-lg": ["tw-size-10"],
607
+ icon: ["tw-size-9"],
608
+ "icon-sm": ["tw-size-8"],
609
+ // unsupported in ARGO, remove when old design is gone
610
+ "icon-xs": [],
611
+ "icon-2xs": [],
612
+ "icon-3xs": []
613
+ }
614
+ }
615
+ }
616
+ );
617
+ var Button = ({
618
+ ref,
619
+ children,
620
+ disabled = false,
621
+ className,
622
+ type = "button",
623
+ isLoading = false,
624
+ asChild = false,
625
+ onClick,
626
+ argo = false,
627
+ variant = "primary",
628
+ size = "medium",
629
+ block = false,
630
+ ...buttonProps
631
+ }) => {
632
+ const isLegacy = useIsLegacyBrand();
633
+ const renderArgo = !isLegacy || argo;
634
+ const Comp = asChild ? reactSlot.Root : "button";
635
+ const isIconOnly = String(size).startsWith("icon");
636
+ const classNames = renderArgo ? argoVariants({ variant, size, block, className }) : variants({ size, variant, block, className });
637
+ const handleClick = (event) => {
638
+ const isAnchor = event.currentTarget.tagName === "A";
639
+ if (isAnchor && disabled) {
640
+ event.preventDefault();
641
+ return;
642
+ }
643
+ onClick?.(event);
644
+ };
645
+ return /* @__PURE__ */ jsxRuntime.jsxs(
646
+ Comp,
647
+ {
648
+ ...buttonProps,
649
+ ref,
650
+ disabled,
651
+ "aria-disabled": disabled,
652
+ "data-variant": variant,
653
+ "data-icon-only": isIconOnly,
654
+ type,
655
+ onClick: handleClick,
656
+ className: cn(classNames),
657
+ children: [
658
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(icons_exports.Loader2, { className: "tw-size-4 tw-shrink-0 tw-animate-spin" }),
659
+ /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slottable, { children: isLoading && isIconOnly ? null : children })
660
+ ]
661
+ }
662
+ );
663
+ };
664
+ var Clipboard = ({
665
+ ref,
666
+ text: textProp,
667
+ children,
668
+ tooltip = "Copy to Clipboard",
669
+ tooltipPlacement = "top",
670
+ tooltipVariant: tooltipVariantProp = "action",
671
+ asChild = false,
672
+ onClick,
673
+ className,
674
+ ...restButtonProps
675
+ }) => {
676
+ const [isTooltipOpen, setIsTooltipOpen] = react.useState(false);
677
+ const [state, setState] = react.useState("ready");
678
+ const text = typeof textProp === "function" ? textProp() : textProp;
679
+ const copy = async (text2) => {
680
+ try {
681
+ if (!document.hasFocus()) window.focus();
682
+ await copyToClipboard(text2);
683
+ setState("copied");
684
+ } catch {
685
+ setState("error");
686
+ }
687
+ };
688
+ const handleOnClick = (event) => {
689
+ if (text && state === "ready") void copy(text);
690
+ onClick?.(event);
691
+ };
692
+ const handleOnOpenChange = (open) => {
693
+ if (!open && state !== "ready") setState("ready");
694
+ setIsTooltipOpen(open);
695
+ };
696
+ const tooltipContent = (() => {
697
+ if (!text) return "Nothing to copy";
698
+ if (state === "error") return "Failed to copy";
699
+ if (state === "copied") return "Copied to Clipboard";
700
+ return tooltip;
701
+ })();
702
+ const tooltipVariant = state === "ready" && !!text ? tooltipVariantProp : "action";
703
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip.Root, { open: isTooltipOpen, onOpenChange: handleOnOpenChange, children: [
704
+ /* @__PURE__ */ jsxRuntime.jsx(
705
+ Tooltip.Trigger,
706
+ {
707
+ ...restButtonProps,
708
+ asChild,
709
+ keepOpenOnClick: true,
710
+ onClick: handleOnClick,
711
+ className: cn("tw-cursor-pointer", className),
712
+ ref,
713
+ children: children ?? text
714
+ }
715
+ ),
716
+ /* @__PURE__ */ jsxRuntime.jsx(
717
+ Tooltip.Content,
718
+ {
719
+ keepOpenOnPointerDownOutside: true,
720
+ placement: tooltipPlacement,
721
+ variant: tooltipVariant,
722
+ children: tooltipContent
723
+ }
724
+ )
725
+ ] });
726
+ };
727
+ var DEFAULT_ICON = /* @__PURE__ */ jsxRuntime.jsx(icons_exports.Copy, {});
728
+ var ClipboardButton = ({
729
+ // clipboard props
730
+ text,
731
+ tooltip,
732
+ tooltipPlacement,
733
+ tooltipVariant,
734
+ // button props
735
+ icon = DEFAULT_ICON,
736
+ variant = "outline",
737
+ children,
738
+ ...rest
739
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
740
+ Clipboard,
741
+ {
742
+ asChild: true,
743
+ tooltip,
744
+ tooltipPlacement,
745
+ tooltipVariant,
746
+ text,
747
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { ...rest, variant, disabled: !text, children: [
748
+ icon,
749
+ children
750
+ ] })
751
+ }
752
+ );
753
+ var ButtonToolbar = ({ value, children }) => {
754
+ if (!value && !children) return null;
755
+ 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: [
756
+ !!value && /* @__PURE__ */ jsxRuntime.jsx(ClipboardButton, { size: "icon-sm", variant: "invisible", text: value }),
757
+ children
758
+ ] });
759
+ };
760
+ var baseThemeStyles = {
761
+ "*": { lineHeight: "20px" },
762
+ "*::selection": {
763
+ backgroundColor: colors__default.default.secondary[500],
764
+ color: `${colors__default.default.white} !important`
765
+ },
766
+ '&.cm-editor:has(.cm-content[contenteditable="false"])': { backgroundColor: colors__default.default.neutral[150] },
767
+ '&.cm-editor:has(.cm-content[contenteditable="false"]) .cm-gutters': {
768
+ backgroundColor: colors__default.default.neutral[200]
769
+ },
770
+ "&.cm-editor .cm-scroller": { overflowAnchor: "none" },
771
+ "&.cm-editor, &.cm-editor .cm-scroller": {
772
+ minHeight: "100%",
773
+ flexGrow: 1,
774
+ alignItems: "stretch !important",
775
+ outline: "none"
776
+ },
777
+ ".cm-gutter.cm-foldGutter": { display: "none !important" },
778
+ ".cm-gutter.cm-lineNumbers": { paddingLeft: "20px", paddingRight: "6px" },
779
+ ".cm-gutters": { height: "auto" },
780
+ // tokens overrides
781
+ ".cm-line .tok-string": { color: colors__default.default.warning[700] },
782
+ // merge (diff) view
783
+ '&[class*="cm-merge-"] .cm-deletedLine': { backgroundColor: colors__default.default.error[100] },
784
+ '&[class*="cm-merge-"] .cm-changedLine': { backgroundColor: colors__default.default.primary[100] },
785
+ '&[class*="cm-merge-"] .cm-deletedLineGutter': { backgroundColor: colors__default.default.error[200] },
786
+ '&[class*="cm-merge-"] .cm-changedLineGutter': { backgroundColor: colors__default.default.primary[200] },
787
+ '&[class*="cm-merge-"] .cm-deletedText': { background: colors__default.default.error[200] },
788
+ '&[class*="cm-merge-"] .cm-changedText': { background: colors__default.default.primary[200] },
789
+ '&[class*="cm-merge-"]': {
790
+ backgroundColor: `${colors__default.default.white} !important`
791
+ },
792
+ '&[class*="cm-merge-"] .cm-gutters': {
793
+ backgroundColor: `${colors__default.default.white} !important`
794
+ },
795
+ ".cm-changeGutter": { position: "absolute", zIndex: -1, width: "100%", paddingLeft: 0 },
796
+ '&[class*="cm-merge-"] .cm-changedLine,&[class*="cm-merge-"] .cm-line, &[class*="cm-merge-"] .cm-deletedChunk': { paddingLeft: 0 }
797
+ };
798
+ var BASIS_SETUP = { drawSelection: false };
799
+ var customTheme = codemirrorThemeGithub.githubLightInit({
800
+ settings: {
801
+ fontFamily: `'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', 'Liberation Mono', 'Courier New'`,
802
+ background: colors__default.default.neutral[50],
803
+ gutterBackground: colors__default.default.neutral[100],
804
+ gutterBorder: "transparent",
805
+ lineHighlight: "transparent",
806
+ selection: colors__default.default.secondary[500]
807
+ }
808
+ });
809
+ var getLanguageMode = (mode) => {
810
+ switch (mode) {
811
+ case "text/x-python":
812
+ return langPython.python();
813
+ case "text/x-sql":
814
+ return langSql.sql({ upperCaseKeywords: true });
815
+ case "text/x-sfsql":
816
+ return language.StreamLanguage.define(codemirrorLangSfsql.sfsql);
817
+ case "text/x-plsql":
818
+ return langSql.sql({ upperCaseKeywords: true, dialect: langSql.PLSQL });
819
+ case "text/x-rsrc":
820
+ return language.StreamLanguage.define(r.r);
821
+ case "text/x-sh":
822
+ return language.StreamLanguage.define(shell.shell);
823
+ case "text/javascript":
824
+ return langJavascript.javascript({ jsx: true });
825
+ case "text/typescript":
826
+ return langJavascript.javascript({ jsx: true, typescript: true });
827
+ default:
828
+ return langJson.json();
829
+ }
830
+ };
831
+ var KbdSeparator = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...props, className: cn("tw-text-xs tw-text-muted-foreground", className) });
832
+ var KbdGroup = ({
833
+ ref,
834
+ className,
835
+ children,
836
+ separator,
837
+ ...props
838
+ }) => {
839
+ return /* @__PURE__ */ jsxRuntime.jsx(
840
+ "kbd",
841
+ {
842
+ ...props,
843
+ ref,
844
+ className: cn("tw-inline-flex", "tw-items-center", "tw-gap-1", className),
845
+ children: separator ? (
846
+ // oxlint-disable-next-line react-x/no-children-to-array
847
+ react.Children.toArray(children).map((child, index) => (
848
+ // oxlint-disable-next-line
849
+ /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
850
+ index > 0 && /* @__PURE__ */ jsxRuntime.jsx(KbdSeparator, { children: separator }),
851
+ child
852
+ ] }, index)
853
+ ))
854
+ ) : children
855
+ }
856
+ );
857
+ };
858
+ var kbdVariants = classVarianceAuthority.cva(
859
+ [
860
+ "tailwindcss-preflight",
861
+ // style
862
+ "tw-pointer-events-none",
863
+ "tw-w-fit",
864
+ "tw-h-5",
865
+ "tw-min-w-5",
866
+ // layout
867
+ "tw-inline-flex",
868
+ "tw-items-center",
869
+ "tw-justify-center",
870
+ "tw-gap-1",
871
+ "tw-shrink-0",
872
+ // spacing
873
+ "tw-px-1",
874
+ '[&_svg:not([class*="size-"])]:tw-size-2.5',
875
+ "tw-text-xs",
876
+ "tw-font-medium",
877
+ "tw-rounded"
878
+ ],
879
+ {
880
+ defaultVariants: {
881
+ variant: "default"
882
+ },
883
+ variants: {
884
+ variant: {
885
+ default: "tw-bg-muted tw-text-muted-foreground",
886
+ primary: "tw-bg-white/20 tw-text-white"
887
+ }
888
+ }
889
+ }
890
+ );
891
+ var Kbd = ({ children, className, variant, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx("kbd", { ...rest, className: kbdVariants({ className, variant }), children });
892
+ Kbd.Group = KbdGroup;
893
+ Kbd.Separator = KbdSeparator;
894
+ var ToggleComponentHelp = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
895
+ "Use ",
896
+ /* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Ctrl+/" }),
897
+ " or ",
898
+ /* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "Command+/" }),
899
+ " to toggle comments."
900
+ ] });
901
+ var emptyArray = [];
902
+ var emptyObject = {};
903
+ var CodeEditor = ({
904
+ value,
905
+ previousValue,
906
+ onChange,
907
+ mode = "application/json",
908
+ placeholder = "",
909
+ readOnly = false,
910
+ autocompletions = emptyArray,
911
+ extraKeys = emptyObject,
912
+ withToggleCommentHint = false,
913
+ withAutofocus = false,
914
+ withLineNumbers = true,
915
+ withLineWrapping = true,
916
+ withCollapseUnchanged = false,
917
+ withCopyButton = true,
918
+ completeAny = false,
919
+ help = null,
920
+ helpPostfix = null,
921
+ renderAdditionalButtons,
922
+ className
923
+ }) => {
924
+ const commonExtensions = react.useMemo(() => {
925
+ return [
926
+ getLanguageMode(mode),
927
+ mode === "application/json" && lint.linter(langJson.jsonParseLinter()),
928
+ withLineWrapping ? view.EditorView.lineWrapping : [],
929
+ CodeMirror.EditorState.languageData.of(() => [
930
+ { autocomplete: completeAny ? autocomplete.completeAnyWord : autocompletions }
931
+ ]),
932
+ view.keymap.of(
933
+ Object.entries(extraKeys).map(([key, run]) => ({
934
+ key,
935
+ run: () => {
936
+ if (typeof run === "string") return run;
937
+ run();
938
+ return true;
939
+ }
940
+ }))
941
+ ),
942
+ autocomplete.autocompletion({ activateOnTyping: completeAny }),
943
+ view.EditorView.theme(baseThemeStyles)
944
+ ].filter(Boolean);
945
+ }, [autocompletions, completeAny, extraKeys, mode, withLineWrapping]);
946
+ const extensions = react.useMemo(() => {
947
+ return [
948
+ ...commonExtensions,
949
+ view.placeholder(placeholder),
950
+ view.EditorView.editable.of(!readOnly),
951
+ CodeMirror.EditorState.readOnly.of(readOnly),
952
+ previousValue ? merge.unifiedMergeView({
953
+ original: previousValue,
954
+ mergeControls: false,
955
+ highlightChanges: false,
956
+ collapseUnchanged: withCollapseUnchanged ? {} : void 0
957
+ }) : []
958
+ ];
959
+ }, [commonExtensions, placeholder, readOnly, previousValue, withCollapseUnchanged]);
960
+ const config = react.useMemo(() => {
961
+ return {
962
+ ...BASIS_SETUP,
963
+ lineNumbers: withLineNumbers
964
+ };
965
+ }, [withLineNumbers]);
966
+ return (
967
+ // oxlint-disable-next-line jsx-a11y/no-static-element-interactions
968
+ /* @__PURE__ */ jsxRuntime.jsxs(
969
+ "div",
970
+ {
971
+ className: cn(
972
+ "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",
973
+ { "tw-mt-5": !!renderAdditionalButtons },
974
+ className
975
+ ),
976
+ onKeyDown: (event) => {
977
+ if (event.key === keyCodes.ESCAPE) {
978
+ event.stopPropagation();
979
+ }
980
+ },
981
+ children: [
982
+ (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) }) }) }),
983
+ /* @__PURE__ */ jsxRuntime.jsx(
984
+ CodeMirror__default.default,
985
+ {
986
+ theme: customTheme,
987
+ value,
988
+ onChange,
989
+ extensions,
990
+ autoFocus: withAutofocus,
991
+ basicSetup: config
992
+ }
993
+ ),
994
+ !readOnly && (withToggleCommentHint || help || helpPostfix) && /* @__PURE__ */ jsxRuntime.jsxs(HelpBlock, { className: "tw-mt-2 tw-flex tw-flex-wrap tw-gap-1", children: [
995
+ help,
996
+ withToggleCommentHint ? /* @__PURE__ */ jsxRuntime.jsx(ToggleComponentHelp, {}) : null,
997
+ helpPostfix
998
+ ] })
999
+ ]
1000
+ }
1001
+ )
1002
+ );
1003
+ };
1004
+ var activeQueryFirstLine = view.Decoration.line({ class: "cm-active-query cm-active-query-first" });
1005
+ var activeQueryMiddleLine = view.Decoration.line({ class: "cm-active-query" });
1006
+ var activeQueryLastLine = view.Decoration.line({ class: "cm-active-query cm-active-query-last" });
1007
+ var activeQuerySingleLine = view.Decoration.line({
1008
+ class: "cm-active-query cm-active-query-first cm-active-query-last"
1009
+ });
1010
+ var findActiveQueryRange = (doc, cursorPos, boundaries) => {
1011
+ if (boundaries.length === 0) return null;
1012
+ let match = boundaries[boundaries.length - 1];
1013
+ for (const boundary of boundaries) {
1014
+ if (cursorPos <= boundary.to) {
1015
+ match = boundary;
1016
+ break;
1017
+ }
1018
+ }
1019
+ if (!match) return null;
1020
+ const queryText = doc.slice(match.from, match.to);
1021
+ const leadingWhitespace = queryText.length - queryText.trimStart().length;
1022
+ const trailingWhitespace = queryText.length - queryText.trimEnd().length;
1023
+ const trimmedStart = match.from + leadingWhitespace;
1024
+ const trimmedEnd = match.to - trailingWhitespace;
1025
+ if (trimmedStart >= trimmedEnd) return null;
1026
+ return { from: trimmedStart, to: trimmedEnd };
1027
+ };
1028
+ var computeBoundaries = (queries) => {
1029
+ const boundaries = [];
1030
+ let offset = 0;
1031
+ for (const query of queries) {
1032
+ boundaries.push({ from: offset, to: offset + query.length });
1033
+ offset += query.length;
1034
+ }
1035
+ return boundaries;
1036
+ };
1037
+ var mapBoundariesThroughChanges = (boundaries, changes) => {
1038
+ const prevLen = changes.length;
1039
+ const mapped = [];
1040
+ for (const b of boundaries) {
1041
+ const from = changes.mapPos(Math.max(0, Math.min(b.from, prevLen)), -1);
1042
+ const to = changes.mapPos(Math.max(0, Math.min(b.to, prevLen)), 1);
1043
+ if (from < to) mapped.push({ from, to });
1044
+ }
1045
+ return mapped;
1046
+ };
1047
+ var buildDecorations = (view$1, range) => {
1048
+ const startLine = view$1.state.doc.lineAt(range.from).number;
1049
+ const endLine = view$1.state.doc.lineAt(range.to).number;
1050
+ const decorations = [];
1051
+ for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
1052
+ const lineStart = view$1.state.doc.line(lineNum).from;
1053
+ if (startLine === endLine) {
1054
+ decorations.push(activeQuerySingleLine.range(lineStart));
1055
+ } else if (lineNum === startLine) {
1056
+ decorations.push(activeQueryFirstLine.range(lineStart));
1057
+ } else if (lineNum === endLine) {
1058
+ decorations.push(activeQueryLastLine.range(lineStart));
1059
+ } else {
1060
+ decorations.push(activeQueryMiddleLine.range(lineStart));
1061
+ }
1062
+ }
1063
+ return view.Decoration.set(decorations);
1064
+ };
1065
+ var activeQueryHighlight = (splitQueries) => {
1066
+ return [
1067
+ view.ViewPlugin.fromClass(
1068
+ class {
1069
+ decorations = view.Decoration.none;
1070
+ debounceTimer = null;
1071
+ seq = 0;
1072
+ cachedDoc = "";
1073
+ cachedBoundaries = [];
1074
+ destroyed = false;
1075
+ constructor(view) {
1076
+ this.scheduleDocParse(view);
1077
+ }
1078
+ update(update) {
1079
+ if (update.focusChanged && !update.view.hasFocus) {
1080
+ this.decorations = view.Decoration.none;
1081
+ return;
1082
+ }
1083
+ if (update.docChanged) {
1084
+ if (this.cachedBoundaries.length > 0) {
1085
+ this.cachedBoundaries = mapBoundariesThroughChanges(
1086
+ this.cachedBoundaries,
1087
+ update.changes
1088
+ );
1089
+ this.cachedDoc = update.state.doc.toString();
1090
+ this.updateFromCache(update.view);
1091
+ }
1092
+ this.scheduleDocParse(update.view);
1093
+ } else if (update.selectionSet || update.focusChanged && update.view.hasFocus) {
1094
+ this.updateFromCache(update.view);
1095
+ }
1096
+ }
1097
+ destroy() {
1098
+ this.destroyed = true;
1099
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
1100
+ }
1101
+ /**
1102
+ * Update decorations using cached query boundaries.
1103
+ * Only mutates this.decorations — does NOT call view.dispatch().
1104
+ * When called from update() (sync), CodeMirror picks up the new
1105
+ * decorations via the accessor. When called from the async
1106
+ * scheduleDocParse callback, the caller must dispatch separately.
1107
+ */
1108
+ updateFromCache(view$1) {
1109
+ if (!view$1.hasFocus) {
1110
+ this.decorations = view.Decoration.none;
1111
+ return;
1112
+ }
1113
+ const { main } = view$1.state.selection;
1114
+ if (main.from !== main.to) {
1115
+ this.decorations = view.Decoration.none;
1116
+ return;
1117
+ }
1118
+ const doc = view$1.state.doc.toString();
1119
+ if (doc !== this.cachedDoc) return;
1120
+ if (this.cachedBoundaries.length === 0) {
1121
+ this.decorations = view.Decoration.none;
1122
+ return;
1123
+ }
1124
+ const range = findActiveQueryRange(doc, main.head, this.cachedBoundaries);
1125
+ this.decorations = range ? buildDecorations(view$1, range) : view.Decoration.none;
1126
+ }
1127
+ /** Parse queries async (debounced) and update decorations. */
1128
+ scheduleDocParse(view$1) {
1129
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
1130
+ this.debounceTimer = setTimeout(async () => {
1131
+ const seq = ++this.seq;
1132
+ const doc = view$1.state.doc.toString();
1133
+ if (!doc.trim()) {
1134
+ this.cachedDoc = doc;
1135
+ this.cachedBoundaries = [];
1136
+ if (this.decorations !== view.Decoration.none) {
1137
+ this.decorations = view.Decoration.none;
1138
+ if (!this.destroyed) view$1.dispatch();
1139
+ }
1140
+ return;
1141
+ }
1142
+ let queries;
1143
+ try {
1144
+ queries = await splitQueries(doc);
1145
+ } catch {
1146
+ return;
1147
+ }
1148
+ if (this.destroyed || seq !== this.seq) return;
1149
+ this.cachedDoc = doc;
1150
+ this.cachedBoundaries = computeBoundaries(queries);
1151
+ this.updateFromCache(view$1);
1152
+ if (!this.destroyed) view$1.dispatch();
1153
+ }, 100);
1154
+ }
1155
+ },
1156
+ { decorations: (v) => v.decorations }
1157
+ ),
1158
+ view.EditorView.baseTheme({
1159
+ ".cm-active-query": {
1160
+ boxShadow: `inset -1px 0 0 0 ${colors__default.default.secondary[300]}, inset 1px 0 0 0 ${colors__default.default.secondary[300]}`,
1161
+ marginRight: "8px"
1162
+ },
1163
+ ".cm-active-query-first": {
1164
+ boxShadow: `inset -1px 0 0 0 ${colors__default.default.secondary[300]}, inset 1px 0 0 0 ${colors__default.default.secondary[300]}, inset 0 1px 0 0 ${colors__default.default.secondary[300]}`,
1165
+ borderRadius: "4px 4px 0 0"
1166
+ },
1167
+ ".cm-active-query-last": {
1168
+ boxShadow: `inset -1px 0 0 0 ${colors__default.default.secondary[300]}, inset 1px 0 0 0 ${colors__default.default.secondary[300]}, inset 0 -1px 0 0 ${colors__default.default.secondary[300]}`,
1169
+ borderRadius: "0 0 4px 4px"
1170
+ },
1171
+ ".cm-active-query-first.cm-active-query-last": {
1172
+ boxShadow: `inset 0 0 0 1px ${colors__default.default.secondary[300]}`,
1173
+ borderRadius: "4px"
1174
+ }
1175
+ })
1176
+ ];
1177
+ };
1178
+
1179
+ // src/components/CodeEditor/highlighting.ts
1180
+ var HighlightMarker = class extends view.GutterMarker {
1181
+ toDOM() {
1182
+ const marker = document.createElement("div");
1183
+ marker.className = "cm-highlight-marker";
1184
+ return marker;
1185
+ }
1186
+ };
1187
+ var highlightMarker = new HighlightMarker();
1188
+ var forEachLineInRange = (doc, from, to, callback) => {
1189
+ const results = [];
1190
+ const fromLine = Math.max(1, from + 1);
1191
+ const toLine = Math.min(doc.lines, to + 1);
1192
+ for (let i = fromLine; i <= toLine; i++) {
1193
+ const line = doc.line(i);
1194
+ results.push(callback(line.from));
1195
+ }
1196
+ return results;
1197
+ };
1198
+ var setHighlightedLinesEffect = state.StateEffect.define();
1199
+ var highlightedLinesField = state.StateField.define({
1200
+ create() {
1201
+ return null;
1202
+ },
1203
+ update(value, transaction) {
1204
+ for (const effect of transaction.effects) {
1205
+ if (effect.is(setHighlightedLinesEffect)) {
1206
+ return effect.value;
1207
+ }
1208
+ }
1209
+ return value;
1210
+ }
1211
+ });
1212
+ var highlightGutter = view.gutter({
1213
+ class: "cm-highlight-gutter",
1214
+ markers: (view) => {
1215
+ const highlightInfo = view.state.field(highlightedLinesField, false);
1216
+ if (!highlightInfo) {
1217
+ return state.RangeSet.empty;
1218
+ }
1219
+ const markers = forEachLineInRange(
1220
+ view.state.doc,
1221
+ highlightInfo.from,
1222
+ highlightInfo.to,
1223
+ (lineFrom) => highlightMarker.range(lineFrom)
1224
+ );
1225
+ return state.RangeSet.of(markers);
1226
+ }
1227
+ });
1228
+ var errorLineDecorations = state.StateField.define({
1229
+ create() {
1230
+ return view.Decoration.none;
1231
+ },
1232
+ update(decorations, transaction) {
1233
+ decorations = decorations.map(transaction.changes);
1234
+ for (const effect of transaction.effects) {
1235
+ if (!effect.is(setHighlightedLinesEffect)) {
1236
+ continue;
1237
+ }
1238
+ if (!effect.value || !effect.value.error) {
1239
+ return view.Decoration.none;
1240
+ }
1241
+ const decorationArray = forEachLineInRange(
1242
+ transaction.state.doc,
1243
+ effect.value.error.from,
1244
+ effect.value.error.to,
1245
+ (lineFrom) => view.Decoration.line({ class: "cm-error-line" }).range(lineFrom)
1246
+ );
1247
+ return view.Decoration.set(decorationArray);
1248
+ }
1249
+ return decorations;
1250
+ },
1251
+ provide: (f) => view.EditorView.decorations.from(f)
1252
+ });
1253
+ var processingLineDecorations = state.StateField.define({
1254
+ create() {
1255
+ return view.Decoration.none;
1256
+ },
1257
+ update(decorations, transaction) {
1258
+ decorations = decorations.map(transaction.changes);
1259
+ for (const effect of transaction.effects) {
1260
+ if (!effect.is(setHighlightedLinesEffect)) {
1261
+ continue;
1262
+ }
1263
+ if (!effect.value || !effect.value.processing) {
1264
+ return view.Decoration.none;
1265
+ }
1266
+ const decorationArray = forEachLineInRange(
1267
+ transaction.state.doc,
1268
+ effect.value.processing.from,
1269
+ effect.value.processing.to,
1270
+ (lineFrom) => view.Decoration.line({ class: "cm-processing-line" }).range(lineFrom)
1271
+ );
1272
+ return view.Decoration.set(decorationArray);
1273
+ }
1274
+ return decorations;
1275
+ },
1276
+ provide: (f) => view.EditorView.decorations.from(f)
1277
+ });
1278
+ var highlightedLinesTheme = view.EditorView.baseTheme({
1279
+ ".cm-highlight-gutter": {
1280
+ width: "2px",
1281
+ marginRight: "2px"
1282
+ },
1283
+ ".cm-highlight-marker": {
1284
+ width: "2px",
1285
+ height: "100%",
1286
+ backgroundColor: colors__default.default.secondary[500]
1287
+ },
1288
+ ".cm-error-line": {
1289
+ backgroundColor: `${colors__default.default.error[100]} !important`
1290
+ },
1291
+ ".cm-processing-line": {
1292
+ backgroundColor: `${colors__default.default.secondary[100]} !important`
1293
+ }
1294
+ });
1295
+ function highlightingExtension(queryParser) {
1296
+ return [
1297
+ highlightedLinesField,
1298
+ highlightGutter,
1299
+ errorLineDecorations,
1300
+ processingLineDecorations,
1301
+ highlightedLinesTheme,
1302
+ ...queryParser ? activeQueryHighlight(queryParser) : []
1303
+ ];
1304
+ }
1305
+ function updateHighlighting(view, lines) {
1306
+ view.dispatch({ effects: setHighlightedLinesEffect.of(lines ?? null) });
1307
+ }
1308
+ var setSearchEffect = state.StateEffect.define();
1309
+ function findMatches(doc, query) {
1310
+ if (!query) return [];
1311
+ const text = doc.toString();
1312
+ try {
1313
+ const regex = new RegExp(escapeStringRegexp(query), "gi");
1314
+ return Array.from(text.matchAll(regex)).map((match, index) => {
1315
+ const from = match.index;
1316
+ const to = from + match[0].length;
1317
+ return { from, to, text: match[0], localIndex: index };
1318
+ });
1319
+ } catch (e) {
1320
+ console.warn("Invalid search regex:", e);
1321
+ return [];
1322
+ }
1323
+ }
1324
+ function createDecorations(matches, selectedLocalIndex) {
1325
+ const decorations = matches.map((match) => {
1326
+ const isSelected = match.localIndex === selectedLocalIndex;
1327
+ const decoration = view.Decoration.mark({
1328
+ class: isSelected ? "cm-searchMatch-selected" : "cm-searchMatch"
1329
+ });
1330
+ return decoration.range(match.from, match.to);
1331
+ });
1332
+ return view.Decoration.set(decorations, true);
1333
+ }
1334
+ var searchField = state.StateField.define({
1335
+ create() {
1336
+ return {
1337
+ query: "",
1338
+ selectedMatchIndex: void 0,
1339
+ matches: [],
1340
+ decorations: view.Decoration.none
1341
+ };
1342
+ },
1343
+ update(state, tr) {
1344
+ let newState = state;
1345
+ for (const effect of tr.effects) {
1346
+ if (!effect.is(setSearchEffect)) {
1347
+ continue;
1348
+ }
1349
+ const { query, selectedMatchIndex } = effect.value;
1350
+ const matches = findMatches(tr.state.doc, query);
1351
+ const decorations = createDecorations(matches, selectedMatchIndex);
1352
+ newState = {
1353
+ query,
1354
+ selectedMatchIndex,
1355
+ matches,
1356
+ decorations
1357
+ };
1358
+ }
1359
+ if (tr.docChanged && newState.query) {
1360
+ const matches = findMatches(tr.state.doc, newState.query);
1361
+ const decorations = createDecorations(matches, newState.selectedMatchIndex);
1362
+ newState = {
1363
+ ...newState,
1364
+ matches,
1365
+ decorations
1366
+ };
1367
+ }
1368
+ return newState;
1369
+ },
1370
+ provide: (field) => view.EditorView.decorations.from(field, (state) => state.decorations)
1371
+ });
1372
+ var searchViewPlugin = view.ViewPlugin.fromClass(
1373
+ class {
1374
+ lastSelectedIndex;
1375
+ update(update) {
1376
+ const state = update.state.field(searchField);
1377
+ if (state.selectedMatchIndex !== void 0 && state.selectedMatchIndex !== this.lastSelectedIndex) {
1378
+ const match = state.matches[state.selectedMatchIndex];
1379
+ if (match) {
1380
+ requestAnimationFrame(() => {
1381
+ update.view.dispatch({
1382
+ effects: view.EditorView.scrollIntoView(match.from, { y: "center" })
1383
+ });
1384
+ });
1385
+ }
1386
+ this.lastSelectedIndex = state.selectedMatchIndex;
1387
+ }
1388
+ if (state.selectedMatchIndex === void 0) {
1389
+ this.lastSelectedIndex = void 0;
1390
+ }
1391
+ }
1392
+ }
1393
+ );
1394
+ var searchTheme = view.EditorView.baseTheme({
1395
+ ".cm-searchMatch": {
1396
+ backgroundColor: colors__default.default.secondary[100]
1397
+ },
1398
+ ".cm-searchMatch > span": {
1399
+ color: `${colors__default.default.secondary[600]} !important`
1400
+ },
1401
+ ".cm-searchMatch-selected": {
1402
+ backgroundColor: colors__default.default.secondary[600]
1403
+ },
1404
+ ".cm-searchMatch-selected > span": {
1405
+ color: `${colors__default.default.white} !important`
1406
+ }
1407
+ });
1408
+ function searchExtension() {
1409
+ return [searchField, searchViewPlugin, searchTheme];
1410
+ }
1411
+ function updateSearch(view, query, selectedMatchIndex) {
1412
+ view.dispatch({ effects: setSearchEffect.of({ query, selectedMatchIndex }) });
1413
+ }
1414
+ var BASIS_SETUP2 = {
1415
+ drawSelection: false,
1416
+ defaultKeymap: false,
1417
+ completionKeymap: false,
1418
+ searchKeymap: false
1419
+ };
1420
+ var CUSTOM_KEYMAP = [
1421
+ {
1422
+ key: "Escape",
1423
+ stopPropagation: true,
1424
+ run: (view) => {
1425
+ view.contentDOM.blur();
1426
+ return true;
1427
+ }
1428
+ }
1429
+ ];
1430
+ var theme = {
1431
+ ...baseThemeStyles,
1432
+ "&.cm-editor": {
1433
+ border: "solid 1px transparent",
1434
+ background: colors__default.default.white,
1435
+ borderRadius: "8px",
1436
+ paddingTop: "8px",
1437
+ paddingBottom: "8px"
1438
+ },
1439
+ '&.cm-editor:has(.cm-content[contenteditable="true"]):hover': {
1440
+ borderColor: colors__default.default.secondary[500]
1441
+ },
1442
+ '&.cm-editor:has(.cm-content[contenteditable="true"]):focus-within': {
1443
+ borderColor: colors__default.default.secondary[500],
1444
+ boxShadow: `0 0 0 4px ${colors__default.default.secondary[200]}`
1445
+ },
1446
+ "&.cm-editor .cm-scroller": { overflowAnchor: "none" },
1447
+ "&.cm-editor :is(.cm-gutters,.cm-scroller)": { background: colors__default.default.white },
1448
+ '&.cm-editor:has(.cm-content[contenteditable="false"])': { background: colors__default.default.neutral[100] },
1449
+ '&.cm-editor:has(.cm-content[contenteditable="false"]) :is(.cm-scroller,.cm-gutters)': {
1450
+ background: colors__default.default.neutral[100]
1451
+ }
1452
+ };
1453
+ var SqlEditor = ({
1454
+ value,
1455
+ onChange,
1456
+ onSelectionChange,
1457
+ onCreateEditor,
1458
+ onDestroyEditor,
1459
+ onBlurEditor,
1460
+ onFocusEditor,
1461
+ placeholder = "",
1462
+ searchQuery = "",
1463
+ searchMatchIndex,
1464
+ readOnly = false,
1465
+ extraKeys,
1466
+ queryParser,
1467
+ autoFocus = false,
1468
+ lineNumbers = true,
1469
+ className,
1470
+ schema,
1471
+ variables,
1472
+ defaultDatabase,
1473
+ defaultSchema,
1474
+ highlightLines,
1475
+ dialect
1476
+ }) => {
1477
+ const editorRef = react.useRef(null);
1478
+ const extensions = react.useMemo(() => {
1479
+ const baseKeymap = [...commands.defaultKeymap, ...CUSTOM_KEYMAP];
1480
+ return [
1481
+ CodeMirror.EditorView.lineWrapping,
1482
+ CodeMirror.keymap.of(extraKeys ? [...extraKeys, ...baseKeymap] : baseKeymap),
1483
+ ...codemirrorLangSql.installExtensions({ schema, defaultDatabase, defaultSchema, variables, dialect }),
1484
+ searchExtension(),
1485
+ highlightingExtension(queryParser),
1486
+ CodeMirror.EditorView.theme(theme),
1487
+ onBlurEditor ? CodeMirror.EditorView.domEventHandlers({ blur: (_, view) => onBlurEditor(view) }) : [],
1488
+ onFocusEditor ? CodeMirror.EditorView.domEventHandlers({ focus: (_, view) => onFocusEditor(view) }) : []
1489
+ ];
1490
+ }, [
1491
+ extraKeys,
1492
+ queryParser,
1493
+ schema,
1494
+ defaultDatabase,
1495
+ defaultSchema,
1496
+ variables,
1497
+ dialect,
1498
+ onBlurEditor,
1499
+ onFocusEditor
1500
+ ]);
1501
+ const defaultSetup = react.useMemo(() => {
1502
+ return { ...BASIS_SETUP2, lineNumbers };
1503
+ }, [lineNumbers]);
1504
+ react.useEffect(() => {
1505
+ if (editorRef.current?.view) {
1506
+ updateHighlighting(editorRef.current.view, highlightLines);
1507
+ }
1508
+ }, [highlightLines]);
1509
+ react.useEffect(() => {
1510
+ if (editorRef.current?.view) {
1511
+ updateSearch(editorRef.current.view, searchQuery, searchMatchIndex);
1512
+ }
1513
+ }, [searchQuery, searchMatchIndex]);
1514
+ react.useEffect(() => {
1515
+ if (!onDestroyEditor) return;
1516
+ return () => {
1517
+ onDestroyEditor();
1518
+ };
1519
+ }, [onDestroyEditor]);
1520
+ const handleOnCreate = react.useCallback(
1521
+ (view, state) => {
1522
+ onCreateEditor?.(view, state);
1523
+ if (highlightLines) {
1524
+ updateHighlighting(view, highlightLines);
1525
+ }
1526
+ if (searchQuery) {
1527
+ updateSearch(view, searchQuery, searchMatchIndex);
1528
+ }
1529
+ },
1530
+ [onCreateEditor, highlightLines, searchQuery, searchMatchIndex]
1531
+ );
1532
+ const handleOnUpdate = react.useCallback(
1533
+ (update) => {
1534
+ if (update.selectionSet) {
1535
+ const { main } = update.state.selection;
1536
+ const text = update.state.sliceDoc(main.from, main.to);
1537
+ onSelectionChange?.(text);
1538
+ }
1539
+ },
1540
+ [onSelectionChange]
1541
+ );
1542
+ return /* @__PURE__ */ jsxRuntime.jsx(
1543
+ CodeMirror__default.default,
1544
+ {
1545
+ ref: editorRef,
1546
+ theme: customTheme,
1547
+ extensions,
1548
+ value,
1549
+ onChange,
1550
+ onUpdate: handleOnUpdate,
1551
+ onCreateEditor: handleOnCreate,
1552
+ autoFocus,
1553
+ placeholder,
1554
+ className,
1555
+ readOnly,
1556
+ editable: !readOnly,
1557
+ basicSetup: defaultSetup
1558
+ }
1559
+ );
1560
+ };
1561
+
1562
+ // src/components/MergeEditor/constants.ts
1563
+ var CHANGE_CLASS = {
1564
+ SAFE: "safe"};
1565
+ var LINE_HEIGHT_PX = 20;
1566
+ var PANE_HEADER_HEIGHT_PX = 58;
1567
+ var AcceptButton = ({ side, onAccept, argo }) => {
1568
+ const label = `Accept ${side === "left" ? "production" : "branch"} version`;
1569
+ const Chevron = side === "left" ? icons_exports.ChevronsRight : icons_exports.ChevronsLeft;
1570
+ return /* @__PURE__ */ jsxRuntime.jsx(
1571
+ Button,
1572
+ {
1573
+ onClick: onAccept,
1574
+ variant: "outline",
1575
+ size: "icon-sm",
1576
+ title: label,
1577
+ "aria-label": label,
1578
+ argo,
1579
+ children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { className: "tw-size-5" })
1580
+ }
1581
+ );
1582
+ };
1583
+ var AcceptControls = ({
1584
+ conflicts,
1585
+ side,
1586
+ onAccept,
1587
+ onDismiss,
1588
+ contentRef,
1589
+ argo
1590
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
1591
+ "div",
1592
+ {
1593
+ className: cn(
1594
+ "tw-z-10 tw-flex tw-shrink-0 tw-flex-col tw-items-center",
1595
+ conflicts.length > 0 ? "tw-w-7" : "tw-w-0"
1596
+ ),
1597
+ children: conflicts.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1598
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-shrink-0", style: { height: `${PANE_HEADER_HEIGHT_PX}px` } }),
1599
+ /* @__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) => {
1600
+ const topLine = side === "left" ? conflict.oldStartLine : conflict.newStartLine;
1601
+ const topOffset = (topLine - 1) * LINE_HEIGHT_PX - 2;
1602
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1603
+ "div",
1604
+ {
1605
+ className: "tw-absolute tw-inset-x-0 tw-flex tw-flex-col tw-items-center tw-gap-0.5",
1606
+ style: { top: `${topOffset}px` },
1607
+ children: [
1608
+ /* @__PURE__ */ jsxRuntime.jsx(AcceptButton, { side, onAccept: () => onAccept(conflict), argo }),
1609
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
1610
+ Button,
1611
+ {
1612
+ onClick: () => onDismiss(conflict),
1613
+ variant: "outline",
1614
+ size: "icon-sm",
1615
+ title: "Dismiss",
1616
+ "aria-label": `Dismiss ${side === "left" ? "production" : "branch"} change`,
1617
+ argo,
1618
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons_exports.X, { className: "tw-size-4" })
1619
+ }
1620
+ )
1621
+ ]
1622
+ },
1623
+ conflict.id
1624
+ );
1625
+ }) }) })
1626
+ ] })
1627
+ }
1628
+ );
1629
+ var setHighlightedLines = state.StateEffect.define();
1630
+ var safeDecoration = view.Decoration.line({ class: "cm-merge-safe-line" });
1631
+ var conflictDecoration = view.Decoration.line({ class: "cm-merge-conflict-line" });
1632
+ var SafeGutterMarker = class extends view.GutterMarker {
1633
+ elementClass = "cm-merge-safe-gutter";
1634
+ };
1635
+ var ConflictGutterMarker = class extends view.GutterMarker {
1636
+ elementClass = "cm-merge-conflict-gutter";
1637
+ };
1638
+ var safeGutterMarker = new SafeGutterMarker();
1639
+ var conflictGutterMarker = new ConflictGutterMarker();
1640
+ var createDiffHighlightExtension = () => {
1641
+ const field = state.StateField.define({
1642
+ create: () => ({ decorations: view.Decoration.none, gutterMarkers: state.RangeSet.empty }),
1643
+ update(value, tr) {
1644
+ let payload = null;
1645
+ for (const effect of tr.effects) {
1646
+ if (effect.is(setHighlightedLines)) {
1647
+ payload = effect.value;
1648
+ }
1649
+ }
1650
+ if (!payload) {
1651
+ return {
1652
+ decorations: value.decorations.map(tr.changes),
1653
+ gutterMarkers: value.gutterMarkers.map(tr.changes)
1654
+ };
1655
+ }
1656
+ const decoBuilder = new state.RangeSetBuilder();
1657
+ const gutterBuilder = new state.RangeSetBuilder();
1658
+ const doc = tr.state.doc;
1659
+ const { lines, classification } = payload;
1660
+ const sorted = [...lines].filter((l) => l >= 1 && l <= doc.lines).sort((a, b) => a - b);
1661
+ for (const i of sorted) {
1662
+ const cls = classification.get(i);
1663
+ if (!cls) continue;
1664
+ const isSafe = cls === CHANGE_CLASS.SAFE;
1665
+ const line = doc.line(i);
1666
+ decoBuilder.add(line.from, line.from, isSafe ? safeDecoration : conflictDecoration);
1667
+ gutterBuilder.add(line.from, line.from, isSafe ? safeGutterMarker : conflictGutterMarker);
1668
+ }
1669
+ return {
1670
+ decorations: decoBuilder.finish(),
1671
+ gutterMarkers: gutterBuilder.finish()
1672
+ };
1673
+ },
1674
+ provide: (f) => [
1675
+ view.EditorView.decorations.from(f, (val) => val.decorations),
1676
+ view.gutterLineClass.from(f, (val) => val.gutterMarkers)
1677
+ ]
1678
+ });
1679
+ const theme2 = view.EditorView.theme({
1680
+ ".cm-merge-safe-line": {
1681
+ backgroundColor: `${colors__default.default.primary[100]} !important`,
1682
+ boxShadow: `inset 3px 0 0 ${colors__default.default.primary[500]}`
1683
+ },
1684
+ ".cm-merge-conflict-line": {
1685
+ backgroundColor: `${colors__default.default.warning[100]} !important`,
1686
+ boxShadow: `inset 3px 0 0 ${colors__default.default.warning[500]}`
1687
+ },
1688
+ ".cm-merge-safe-gutter": {
1689
+ backgroundColor: `${colors__default.default.primary[200]} !important`
1690
+ },
1691
+ ".cm-merge-conflict-gutter": {
1692
+ backgroundColor: `${colors__default.default.warning[200]} !important`
1693
+ }
1694
+ });
1695
+ return [field, theme2];
1696
+ };
1697
+ var updateHighlightedLines = (view, lines, classification) => {
1698
+ view.dispatch({ effects: setHighlightedLines.of({ lines, classification }) });
1699
+ };
1700
+ var EMPTY_LINES = /* @__PURE__ */ new Set();
1701
+ var EMPTY_CLASSIFICATION = /* @__PURE__ */ new Map();
1702
+ var MergePane = ({
1703
+ value,
1704
+ highlightedLines,
1705
+ lineClassification,
1706
+ readOnly = false,
1707
+ onChange,
1708
+ header,
1709
+ headerClassName,
1710
+ className,
1711
+ onScrollDOMReady,
1712
+ deleted = false
1713
+ }) => {
1714
+ const editorRef = react.useRef(null);
1715
+ const extensions = react.useMemo(
1716
+ () => [
1717
+ createDiffHighlightExtension(),
1718
+ view.EditorView.theme({
1719
+ "&.cm-editor": {
1720
+ height: "100%",
1721
+ backgroundColor: deleted ? colors__default.default.error[100] : colors__default.default.neutral[50],
1722
+ outline: "none"
1723
+ },
1724
+ ".cm-gutters": {
1725
+ backgroundColor: deleted ? colors__default.default.error[200] : colors__default.default.neutral[100]
1726
+ },
1727
+ "*": { lineHeight: `${LINE_HEIGHT_PX}px` },
1728
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 0 0 25px" }
1729
+ }),
1730
+ // Recalc viewport after every doc change so late-settling layouts (alerts
1731
+ // appearing above the editor) don't leave trailing lines blank.
1732
+ view.EditorView.updateListener.of((update) => {
1733
+ if (update.docChanged) {
1734
+ requestAnimationFrame(() => update.view.dispatch({}));
1735
+ }
1736
+ })
1737
+ ],
1738
+ [deleted]
1739
+ );
1740
+ react.useEffect(() => {
1741
+ const view = editorRef.current?.view;
1742
+ if (!view) return;
1743
+ updateHighlightedLines(
1744
+ view,
1745
+ deleted ? EMPTY_LINES : highlightedLines,
1746
+ deleted ? EMPTY_CLASSIFICATION : lineClassification
1747
+ );
1748
+ }, [highlightedLines, lineClassification, deleted]);
1749
+ const handleCreateEditor = react.useCallback(
1750
+ (view) => {
1751
+ updateHighlightedLines(
1752
+ view,
1753
+ deleted ? EMPTY_LINES : highlightedLines,
1754
+ deleted ? EMPTY_CLASSIFICATION : lineClassification
1755
+ );
1756
+ onScrollDOMReady?.(view.scrollDOM);
1757
+ },
1758
+ [highlightedLines, lineClassification, onScrollDOMReady, deleted]
1759
+ );
1760
+ react.useEffect(() => {
1761
+ return () => onScrollDOMReady?.(null);
1762
+ }, [onScrollDOMReady]);
1763
+ react.useEffect(() => {
1764
+ const view = editorRef.current?.view;
1765
+ const wrapper = view?.dom.parentElement;
1766
+ if (!view || !wrapper) return;
1767
+ const observer = new ResizeObserver(() => view.dispatch({}));
1768
+ observer.observe(wrapper);
1769
+ return () => observer.disconnect();
1770
+ }, []);
1771
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1772
+ "div",
1773
+ {
1774
+ className: cn(
1775
+ "tw-flex tw-min-w-0 tw-flex-1 tw-flex-col tw-overflow-hidden",
1776
+ className,
1777
+ deleted && "tw-border-error-300"
1778
+ ),
1779
+ children: [
1780
+ header && /* @__PURE__ */ jsxRuntime.jsx(
1781
+ "div",
1782
+ {
1783
+ className: cn(
1784
+ "tw-px-4 tw-py-3",
1785
+ deleted ? "tw-border-b tw-border-error-200 tw-bg-error-100" : "tw-bg-background",
1786
+ headerClassName
1787
+ ),
1788
+ children: header
1789
+ }
1790
+ ),
1791
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "tw-flex tw-h-0 tw-flex-1 tw-flex-col [&_>div]:tw-h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
1792
+ CodeMirror__default.default,
1793
+ {
1794
+ ref: editorRef,
1795
+ height: "100%",
1796
+ value,
1797
+ onChange,
1798
+ extensions,
1799
+ readOnly,
1800
+ onCreateEditor: handleCreateEditor,
1801
+ basicSetup: { lineNumbers: true, drawSelection: false }
1802
+ }
1803
+ ) })
1804
+ ]
1805
+ }
1806
+ );
1807
+ };
1808
+ var useScrollSync = () => {
1809
+ const scrollersRef = react.useRef([]);
1810
+ const followersRef = react.useRef(/* @__PURE__ */ new Map());
1811
+ const isSyncingRef = react.useRef(false);
1812
+ const scrollerCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
1813
+ const followerCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
1814
+ const updateFollowers = react.useCallback(() => {
1815
+ for (const [, { paneIndex, el }] of followersRef.current) {
1816
+ const scroller = scrollersRef.current[paneIndex];
1817
+ if (!scroller) continue;
1818
+ el.style.transform = `translateY(-${scroller.scrollTop}px)`;
1819
+ }
1820
+ }, []);
1821
+ const handleScroll = react.useCallback(
1822
+ (e) => {
1823
+ if (isSyncingRef.current) return;
1824
+ isSyncingRef.current = true;
1825
+ const sourceScrollTop = e.target.scrollTop;
1826
+ for (const scroller of scrollersRef.current) {
1827
+ if (!scroller || scroller === e.target) continue;
1828
+ const targetMax = Math.max(0, scroller.scrollHeight - scroller.clientHeight);
1829
+ scroller.scrollTop = Math.min(sourceScrollTop, targetMax);
1830
+ }
1831
+ updateFollowers();
1832
+ isSyncingRef.current = false;
1833
+ },
1834
+ [updateFollowers]
1835
+ );
1836
+ const registerScroller = react.useCallback(
1837
+ (index) => {
1838
+ const existing = scrollerCallbacksRef.current.get(index);
1839
+ if (existing) return existing;
1840
+ const callback = (el) => {
1841
+ const prev = scrollersRef.current[index];
1842
+ if (prev === el) return;
1843
+ prev?.removeEventListener("scroll", handleScroll);
1844
+ scrollersRef.current[index] = el;
1845
+ el?.addEventListener("scroll", handleScroll, { passive: true });
1846
+ };
1847
+ scrollerCallbacksRef.current.set(index, callback);
1848
+ return callback;
1849
+ },
1850
+ [handleScroll]
1851
+ );
1852
+ const registerFollower = react.useCallback((paneIndex, key) => {
1853
+ const existing = followerCallbacksRef.current.get(key);
1854
+ if (existing) return existing;
1855
+ const callback = (el) => {
1856
+ if (el) {
1857
+ followersRef.current.set(key, { paneIndex, el });
1858
+ } else {
1859
+ followersRef.current.delete(key);
1860
+ }
1861
+ };
1862
+ followerCallbacksRef.current.set(key, callback);
1863
+ return callback;
1864
+ }, []);
1865
+ return { registerScroller, registerFollower };
1866
+ };
1867
+ var EMPTY_LINES2 = /* @__PURE__ */ new Set();
1868
+ var EMPTY_CLASSIFICATION2 = /* @__PURE__ */ new Map();
1869
+ var MergeEditor = ({
1870
+ mergeValue,
1871
+ handleMergeChange,
1872
+ leftText,
1873
+ rightText,
1874
+ leftConflicts,
1875
+ rightConflicts,
1876
+ leftHighlightedLines,
1877
+ rightHighlightedLines,
1878
+ leftClassification,
1879
+ rightClassification,
1880
+ mergeHighlightedLines,
1881
+ mergeClassification,
1882
+ acceptLeft,
1883
+ acceptRight,
1884
+ dismissLeft,
1885
+ dismissRight,
1886
+ leftHeader,
1887
+ middleHeader,
1888
+ middleHeaderClassName,
1889
+ middleClassName,
1890
+ rightHeader,
1891
+ className,
1892
+ argo,
1893
+ leftDeleted = false,
1894
+ rightDeleted = false
1895
+ }) => {
1896
+ const { registerScroller, registerFollower } = useScrollSync();
1897
+ const anySideDeleted = leftDeleted || rightDeleted;
1898
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1899
+ "div",
1900
+ {
1901
+ className: cn(
1902
+ "tw-flex tw-h-full tw-min-h-0 tw-overflow-hidden tw-bg-background tw-gap-3",
1903
+ className
1904
+ ),
1905
+ children: [
1906
+ /* @__PURE__ */ jsxRuntime.jsx(
1907
+ MergePane,
1908
+ {
1909
+ value: leftText,
1910
+ highlightedLines: leftHighlightedLines,
1911
+ lineClassification: leftClassification,
1912
+ readOnly: true,
1913
+ header: leftHeader,
1914
+ className: "tw-rounded-r-lg tw-border tw-border-border",
1915
+ onScrollDOMReady: registerScroller(0),
1916
+ deleted: leftDeleted
1917
+ }
1918
+ ),
1919
+ /* @__PURE__ */ jsxRuntime.jsx(
1920
+ AcceptControls,
1921
+ {
1922
+ conflicts: leftDeleted ? [] : leftConflicts,
1923
+ side: "left",
1924
+ onAccept: acceptLeft,
1925
+ onDismiss: dismissLeft,
1926
+ contentRef: registerFollower(0, "left-controls"),
1927
+ argo
1928
+ }
1929
+ ),
1930
+ /* @__PURE__ */ jsxRuntime.jsx(
1931
+ MergePane,
1932
+ {
1933
+ value: mergeValue,
1934
+ highlightedLines: anySideDeleted ? EMPTY_LINES2 : mergeHighlightedLines,
1935
+ lineClassification: anySideDeleted ? EMPTY_CLASSIFICATION2 : mergeClassification,
1936
+ onChange: handleMergeChange,
1937
+ header: middleHeader,
1938
+ headerClassName: middleHeaderClassName,
1939
+ className: cn("tw-border tw-border-border tw-rounded-lg", middleClassName),
1940
+ onScrollDOMReady: registerScroller(1)
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ jsxRuntime.jsx(
1944
+ AcceptControls,
1945
+ {
1946
+ conflicts: rightDeleted ? [] : rightConflicts,
1947
+ side: "right",
1948
+ onAccept: acceptRight,
1949
+ onDismiss: dismissRight,
1950
+ contentRef: registerFollower(2, "right-controls"),
1951
+ argo
1952
+ }
1953
+ ),
1954
+ /* @__PURE__ */ jsxRuntime.jsx(
1955
+ MergePane,
1956
+ {
1957
+ value: rightText,
1958
+ highlightedLines: rightHighlightedLines,
1959
+ lineClassification: rightClassification,
1960
+ readOnly: true,
1961
+ header: rightHeader,
1962
+ className: "tw-rounded-l-lg tw-border tw-border-border",
1963
+ onScrollDOMReady: registerScroller(2),
1964
+ deleted: rightDeleted
1965
+ }
1966
+ )
1967
+ ]
1968
+ }
1969
+ );
1970
+ };
1971
+
1972
+ exports.CodeEditor = CodeEditor;
1973
+ exports.MergeEditor = MergeEditor;
1974
+ exports.SqlEditor = SqlEditor;
1975
+ //# sourceMappingURL=editors.cjs.map
1976
+ //# sourceMappingURL=editors.cjs.map