@keboola/design 1.0.0 → 1.2.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,4278 @@
1
+ import { clsx } from 'clsx';
2
+ import { extendTailwindMerge } from 'tailwind-merge';
3
+ import { Portal, Content, Root, Trigger } from '@radix-ui/react-tooltip';
4
+ import { cva } from 'class-variance-authority';
5
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
6
+ import { createContext, lazy, Suspense, use, useId, useState, useRef, useEffect, useCallback, useMemo } from 'react';
7
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
8
+ import '@awesome.me/kit-be8bcf7e5e/icons';
9
+ import { Root as Root$2, Slottable } from '@radix-ui/react-slot';
10
+ import { Tooltip as Tooltip$1, cn as cn$1 } from '@keboola/design';
11
+ import { renderMermaidSVG } from 'beautiful-mermaid';
12
+ import colors from '@keboola/tailwind-config/colors';
13
+ import { CodeNode, $isCodeNode, $createCodeNode } from '@lexical/code';
14
+ import { LinkNode, $isLinkNode, TOGGLE_LINK_COMMAND, $createLinkNode } from '@lexical/link';
15
+ import { ListNode, ListItemNode, $isListNode, REMOVE_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND } from '@lexical/list';
16
+ import { CHECK_LIST, TRANSFORMERS, $convertFromMarkdownString, $convertToMarkdownString } from '@lexical/markdown';
17
+ import { AutoFocusPlugin } from '@lexical/react/LexicalAutoFocusPlugin';
18
+ import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
19
+ import { ClickableLinkPlugin } from '@lexical/react/LexicalClickableLinkPlugin';
20
+ import { LexicalComposer } from '@lexical/react/LexicalComposer';
21
+ import { ContentEditable } from '@lexical/react/LexicalContentEditable';
22
+ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
23
+ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
24
+ import { HorizontalRuleNode, $createHorizontalRuleNode, $isHorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
25
+ import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin';
26
+ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
27
+ import { ListPlugin } from '@lexical/react/LexicalListPlugin';
28
+ import { MarkdownShortcutPlugin } from '@lexical/react/LexicalMarkdownShortcutPlugin';
29
+ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
30
+ import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin';
31
+ import { HeadingNode, QuoteNode, $isHeadingNode, $isQuoteNode, $createQuoteNode, $createHeadingNode } from '@lexical/rich-text';
32
+ import { DecoratorNode, $getSelection, $isRangeSelection, FORMAT_TEXT_COMMAND, $createParagraphNode, PASTE_COMMAND, COMMAND_PRIORITY_CRITICAL, DROP_COMMAND, KEY_DOWN_COMMAND, COMMAND_PRIORITY_HIGH, $insertNodes, $getNodeByKey, $setSelection, FORMAT_ELEMENT_COMMAND, $createTextNode } from 'lexical';
33
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
34
+ import { toast as toast$1 } from 'sonner';
35
+ import { createPortal } from 'react-dom';
36
+ import { $getNearestBlockElementAncestorOrThrow } from '@lexical/utils';
37
+ import * as DropdownMenuPrimitive3 from '@radix-ui/react-dropdown-menu';
38
+ import { Root as Root$1, Group, Trigger as Trigger$1 } from '@radix-ui/react-dropdown-menu';
39
+ import * as ScrollAreaPrimitive2 from '@radix-ui/react-scroll-area';
40
+ import TextareaAutosize from 'react-textarea-autosize';
41
+ import * as RLabel from '@radix-ui/react-label';
42
+
43
+ var __defProp = Object.defineProperty;
44
+ var __getOwnPropNames = Object.getOwnPropertyNames;
45
+ var __esm = (fn, res) => function __init() {
46
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
47
+ };
48
+ var __export = (target, all) => {
49
+ for (var name in all)
50
+ __defProp(target, name, { get: all[name], enumerable: true });
51
+ };
52
+ var twMerge, cn;
53
+ var init_classNames = __esm({
54
+ "src/utils/classNames.ts"() {
55
+ twMerge = extendTailwindMerge({
56
+ prefix: "tw-"
57
+ });
58
+ cn = (...classes) => twMerge(clsx(...classes));
59
+ }
60
+ });
61
+
62
+ // src/utils/copyToClipboard.ts
63
+ var copyToClipboard;
64
+ var init_copyToClipboard = __esm({
65
+ "src/utils/copyToClipboard.ts"() {
66
+ copyToClipboard = (text) => {
67
+ return navigator.clipboard.writeText(text);
68
+ };
69
+ }
70
+ });
71
+
72
+ // src/utils/createChangeInputEvent.ts
73
+ var createChangeInputEvent;
74
+ var init_createChangeInputEvent = __esm({
75
+ "src/utils/createChangeInputEvent.ts"() {
76
+ createChangeInputEvent = (input) => {
77
+ const changeEvent = {
78
+ target: input,
79
+ currentTarget: input,
80
+ type: "change",
81
+ nativeEvent: new Event("change", { bubbles: true }),
82
+ bubbles: true,
83
+ cancelable: false,
84
+ defaultPrevented: false,
85
+ eventPhase: 2,
86
+ // AT_TARGET
87
+ isTrusted: false,
88
+ // Synthetic events are not trusted
89
+ preventDefault: () => {
90
+ },
91
+ // Provide dummy functions if not needed
92
+ isDefaultPrevented: () => false,
93
+ stopPropagation: () => {
94
+ },
95
+ isPropagationStopped: () => false,
96
+ persist: () => {
97
+ },
98
+ timeStamp: Date.now()
99
+ };
100
+ Object.defineProperty(changeEvent, "target", {
101
+ value: input,
102
+ writable: false
103
+ });
104
+ return changeEvent;
105
+ };
106
+ }
107
+ });
108
+
109
+ // src/constants/keyCodes.ts
110
+ var keyCodes;
111
+ var init_keyCodes = __esm({
112
+ "src/constants/keyCodes.ts"() {
113
+ keyCodes = {
114
+ ENTER: "Enter",
115
+ ESCAPE: "Escape",
116
+ SPACE: " "
117
+ };
118
+ }
119
+ });
120
+ var tooltipVariants, TooltipContent;
121
+ var init_TooltipContent = __esm({
122
+ "src/components/Tooltip/TooltipContent.tsx"() {
123
+ tooltipVariants = cva(
124
+ [
125
+ "tailwindcss-preflight",
126
+ "tw-inline-block",
127
+ "tw-rounded",
128
+ "tw-bg-neutral-800",
129
+ "tw-text-white",
130
+ "tw-break-anywhere",
131
+ "tw-max-h-96",
132
+ "tw-overflow-y-auto",
133
+ "tw-z-[1060]"
134
+ ],
135
+ {
136
+ defaultVariants: {
137
+ variant: "action"
138
+ },
139
+ variants: {
140
+ variant: {
141
+ action: [
142
+ "tw-max-w-fit",
143
+ "tw-px-3",
144
+ "tw-py-2",
145
+ "tw-text-center",
146
+ "tw-text-xs",
147
+ "tw-font-medium",
148
+ "tw-uppercase",
149
+ "tw-tracking-wider"
150
+ ],
151
+ explanatory: [
152
+ "tw-max-w-80",
153
+ "tw-px-4",
154
+ "tw-py-3",
155
+ "tw-text-left",
156
+ "tw-text-sm",
157
+ "tw-font-normal"
158
+ ]
159
+ }
160
+ }
161
+ }
162
+ );
163
+ TooltipContent = ({
164
+ className,
165
+ variant,
166
+ keepOpenOnPointerDownOutside = false,
167
+ children,
168
+ onPointerDownOutside,
169
+ sideOffset = 8,
170
+ collisionPadding = 8,
171
+ hideWhenDetached = true,
172
+ placement = "right",
173
+ ...rest
174
+ }) => {
175
+ const handlePointerDownOutside = (event) => {
176
+ if (keepOpenOnPointerDownOutside) event.preventDefault();
177
+ onPointerDownOutside?.(event);
178
+ };
179
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(
180
+ Content,
181
+ {
182
+ ...rest,
183
+ "data-tooltip-content": true,
184
+ sideOffset,
185
+ collisionPadding,
186
+ onPointerDownOutside: handlePointerDownOutside,
187
+ className: tooltipVariants({ className, variant }),
188
+ hideWhenDetached,
189
+ side: placement,
190
+ children
191
+ }
192
+ ) });
193
+ };
194
+ }
195
+ });
196
+ var DELAY_SHOW_TOOLTIP, TooltipRoot;
197
+ var init_TooltipRoot = __esm({
198
+ "src/components/Tooltip/TooltipRoot.tsx"() {
199
+ DELAY_SHOW_TOOLTIP = 300;
200
+ TooltipRoot = ({ children, delayDuration = DELAY_SHOW_TOOLTIP, ...rest }) => /* @__PURE__ */ jsx(Root, { ...rest, delayDuration, children });
201
+ }
202
+ });
203
+ var TooltipTrigger;
204
+ var init_TooltipTrigger = __esm({
205
+ "src/components/Tooltip/TooltipTrigger.tsx"() {
206
+ init_utils();
207
+ TooltipTrigger = ({
208
+ ref,
209
+ children,
210
+ className,
211
+ keepOpenOnClick = false,
212
+ onClick,
213
+ onPointerDown,
214
+ asChild,
215
+ ...rest
216
+ }) => {
217
+ const handleClick = (event) => {
218
+ if (keepOpenOnClick) event.preventDefault();
219
+ onClick?.(event);
220
+ };
221
+ const handePointerDown = (event) => {
222
+ if (keepOpenOnClick) event.preventDefault();
223
+ onPointerDown?.(event);
224
+ };
225
+ return /* @__PURE__ */ jsx(
226
+ Trigger,
227
+ {
228
+ ...rest,
229
+ asChild: true,
230
+ ref,
231
+ className: cn("tailwindcss-preflight", className),
232
+ onClick: handleClick,
233
+ onPointerDown: handePointerDown,
234
+ children: asChild ? children : /* @__PURE__ */ jsx("span", { children })
235
+ }
236
+ );
237
+ };
238
+ }
239
+ });
240
+ var ACTION_TOOLTIP_LIMIT, Tooltip;
241
+ var init_Tooltip = __esm({
242
+ "src/components/Tooltip/Tooltip.tsx"() {
243
+ init_keyCodes();
244
+ init_TooltipContent();
245
+ init_TooltipRoot();
246
+ init_TooltipTrigger();
247
+ ACTION_TOOLTIP_LIMIT = 30;
248
+ Tooltip = ({
249
+ tooltip,
250
+ children,
251
+ className,
252
+ keepOpenOnTriggerClick = false,
253
+ variant,
254
+ placement = "right",
255
+ forceHide = false,
256
+ forceShow = false,
257
+ // trigger props
258
+ triggerAsChild = false
259
+ }) => {
260
+ const [open, setOpen] = useState(false);
261
+ const resolvedVariant = (() => {
262
+ if (!!variant) return variant;
263
+ if (typeof tooltip === "string" && tooltip.length > ACTION_TOOLTIP_LIMIT) return "explanatory";
264
+ return "action";
265
+ })();
266
+ const isActionVariant = resolvedVariant === "action";
267
+ const handleKeyUp = (event) => {
268
+ if (![keyCodes.ENTER, keyCodes.SPACE].includes(event.key)) return;
269
+ event.stopPropagation();
270
+ };
271
+ return /* @__PURE__ */ jsxs(
272
+ TooltipRoot,
273
+ {
274
+ open: !!tooltip && (open || forceShow) && !forceHide,
275
+ onOpenChange: setOpen,
276
+ disableHoverableContent: isActionVariant,
277
+ children: [
278
+ /* @__PURE__ */ jsx(
279
+ TooltipTrigger,
280
+ {
281
+ asChild: triggerAsChild,
282
+ keepOpenOnClick: keepOpenOnTriggerClick,
283
+ onKeyUp: handleKeyUp,
284
+ children
285
+ }
286
+ ),
287
+ /* @__PURE__ */ jsx(
288
+ TooltipContent,
289
+ {
290
+ className,
291
+ variant: resolvedVariant,
292
+ placement,
293
+ keepOpenOnPointerDownOutside: keepOpenOnTriggerClick,
294
+ children: tooltip
295
+ }
296
+ )
297
+ ]
298
+ }
299
+ );
300
+ };
301
+ Tooltip.Root = TooltipRoot;
302
+ Tooltip.Content = TooltipContent;
303
+ Tooltip.Trigger = TooltipTrigger;
304
+ }
305
+ });
306
+
307
+ // src/components/Tooltip/index.ts
308
+ var init_Tooltip2 = __esm({
309
+ "src/components/Tooltip/index.ts"() {
310
+ init_Tooltip();
311
+ }
312
+ });
313
+ var init_decorators = __esm({
314
+ "src/utils/decorators.tsx"() {
315
+ }
316
+ });
317
+
318
+ // src/utils/createPrefixedString.ts
319
+ var createPrefixedString;
320
+ var init_createPrefixedString = __esm({
321
+ "src/utils/createPrefixedString.ts"() {
322
+ createPrefixedString = (prefix) => (literals) => literals.reduce((acc, literal) => acc + literal, `${prefix}-`);
323
+ }
324
+ });
325
+
326
+ // src/utils/escapeStringRegexp.ts
327
+ var init_escapeStringRegexp = __esm({
328
+ "src/utils/escapeStringRegexp.ts"() {
329
+ }
330
+ });
331
+
332
+ // src/utils/mergeRefs.ts
333
+ function setRef(ref, value) {
334
+ if (typeof ref === "function") {
335
+ ref(value);
336
+ } else if (ref != null) {
337
+ ref.current = value;
338
+ }
339
+ }
340
+ var mergeRefs;
341
+ var init_mergeRefs = __esm({
342
+ "src/utils/mergeRefs.ts"() {
343
+ mergeRefs = (...refs) => {
344
+ return (node) => refs.forEach((ref) => setRef(ref, node));
345
+ };
346
+ }
347
+ });
348
+
349
+ // src/utils/noop.ts
350
+ var init_noop = __esm({
351
+ "src/utils/noop.ts"() {
352
+ }
353
+ });
354
+
355
+ // src/utils/debounce.ts
356
+ var init_debounce = __esm({
357
+ "src/utils/debounce.ts"() {
358
+ }
359
+ });
360
+
361
+ // src/utils/isMac.ts
362
+ var getIsMac;
363
+ var init_isMac = __esm({
364
+ "src/utils/isMac.ts"() {
365
+ getIsMac = () => {
366
+ if (typeof navigator !== "undefined" && "userAgentData" in navigator) {
367
+ const platform = navigator.userAgentData.platform;
368
+ if (typeof platform === "string") {
369
+ return platform.toLowerCase() === "macos";
370
+ }
371
+ }
372
+ if (typeof navigator !== "undefined" && typeof navigator.platform === "string") {
373
+ return navigator.platform.toUpperCase().indexOf("MAC") >= 0;
374
+ }
375
+ return false;
376
+ };
377
+ getIsMac();
378
+ }
379
+ });
380
+ var init_useSHA256 = __esm({
381
+ "src/utils/useSHA256.ts"() {
382
+ }
383
+ });
384
+
385
+ // src/utils/index.ts
386
+ var init_utils = __esm({
387
+ "src/utils/index.ts"() {
388
+ init_classNames();
389
+ init_copyToClipboard();
390
+ init_createChangeInputEvent();
391
+ init_decorators();
392
+ init_createPrefixedString();
393
+ init_escapeStringRegexp();
394
+ init_mergeRefs();
395
+ init_noop();
396
+ init_debounce();
397
+ init_isMac();
398
+ init_useSHA256();
399
+ }
400
+ });
401
+ var HEIGHT_CLASS_NAME, ANIMATION_CLASS_NAME, Skeleton;
402
+ var init_Skeleton = __esm({
403
+ "src/components/Skeleton/Skeleton.tsx"() {
404
+ init_utils();
405
+ HEIGHT_CLASS_NAME = {
406
+ xxs: "tw-h-3 tw-rounded",
407
+ xs: "tw-h-4 tw-rounded",
408
+ sm: "tw-h-5 tw-rounded",
409
+ md: "tw-h-6 tw-rounded-md",
410
+ lg: "tw-h-8 tw-rounded-lg",
411
+ xl: "tw-h-10 tw-rounded-lg",
412
+ "2xl": "tw-h-12 tw-rounded-lg"
413
+ };
414
+ ANIMATION_CLASS_NAME = cn(
415
+ // base styles
416
+ "tw-relative",
417
+ "tw-overflow-hidden",
418
+ "tw-pointer-events-none",
419
+ "tw-bg-neutral-150",
420
+ // before
421
+ 'before:tw-content-[""]',
422
+ "before:tw-opacity-100",
423
+ "before:tw-absolute",
424
+ "before:tw-inset-0",
425
+ "before:-tw-translate-x-full",
426
+ "before:tw-animate-[shimmer_2s_infinite]",
427
+ "before:tw-bg-gradient-to-r",
428
+ "before:tw-from-transparent",
429
+ "before:tw-to-transparent",
430
+ "before:tw-via-neutral-50"
431
+ );
432
+ Skeleton = ({ height = "md", className, count = 1 }) => {
433
+ const prefixId = useId();
434
+ const keys = Array.from({ length: count }, (_, i) => `${prefixId}-${i}`);
435
+ return /* @__PURE__ */ jsx(Fragment, { children: keys.map((key) => /* @__PURE__ */ jsx("div", { className: cn(HEIGHT_CLASS_NAME[height], ANIMATION_CLASS_NAME, className) }, key)) });
436
+ };
437
+ }
438
+ });
439
+ var Icon;
440
+ var init_Icon = __esm({
441
+ "src/components/Icon/Icon.tsx"() {
442
+ Icon = ({ ref, icon, ...rest }) => /* @__PURE__ */ jsx(FontAwesomeIcon, { ...rest, ref, icon });
443
+ }
444
+ });
445
+ var init_Icon2 = __esm({
446
+ "src/components/Icon/index.ts"() {
447
+ init_Icon();
448
+ }
449
+ });
450
+ var variants, argoVariants;
451
+ var init_styles = __esm({
452
+ "src/components/Button/styles.ts"() {
453
+ variants = cva(
454
+ [
455
+ "tailwindcss-preflight",
456
+ "tw-group/button",
457
+ "tw-border-box",
458
+ // layout
459
+ "tw-relative",
460
+ "tw-flex",
461
+ "tw-items-center",
462
+ "tw-justify-center",
463
+ "tw-gap-2",
464
+ // text
465
+ "tw-text-xs",
466
+ "tw-leading-5",
467
+ "tw-font-medium",
468
+ "tw-tracking-[1px]",
469
+ "tw-uppercase",
470
+ // border
471
+ "tw-rounded",
472
+ "tw-border",
473
+ "tw-border-transparent",
474
+ // styling
475
+ "tw-shadow-none",
476
+ "[a]:tw-cursor-pointer",
477
+ // explicitly set for anchor
478
+ "focus-visible:tw-outline",
479
+ "focus-visible:tw-outline-1",
480
+ "focus-visible:-tw-outline-offset-1",
481
+ "focus-visible:tw-outline-secondary-500",
482
+ "focus-visible:tw-ring-4",
483
+ "focus-visible:tw-ring-secondary-200",
484
+ // disabled
485
+ "disabled:tw-opacity-40",
486
+ "disabled:tw-cursor-not-allowed",
487
+ // anchor support
488
+ "!tw-no-underline",
489
+ "aria-disabled:tw-opacity-40",
490
+ "aria-disabled:tw-cursor-not-allowed",
491
+ "[&_svg]:tw-shrink-0"
492
+ ],
493
+ {
494
+ defaultVariants: {
495
+ size: "medium",
496
+ variant: "primary",
497
+ block: false
498
+ },
499
+ variants: {
500
+ block: {
501
+ true: ["tw-w-full"]
502
+ },
503
+ variant: {
504
+ primary: [
505
+ "tw-text-white",
506
+ "tw-bg-primary-500",
507
+ "focus:tw-text-white",
508
+ "hover:tw-text-white",
509
+ "hover:not-disabled:tw-bg-primary-600",
510
+ "active:not-disabled:tw-bg-primary-800",
511
+ // anchor disabled override
512
+ "aria-disabled:!tw-bg-primary-500"
513
+ ],
514
+ secondary: [
515
+ "tw-text-white",
516
+ "tw-bg-secondary-500",
517
+ "focus:tw-text-white",
518
+ "hover:tw-text-white",
519
+ "hover:not-disabled:tw-bg-secondary-700",
520
+ "active:not-disabled:tw-bg-secondary-800",
521
+ // anchor disabled override
522
+ "aria-disabled:!tw-bg-secondary-500"
523
+ ],
524
+ danger: [
525
+ "tw-text-white",
526
+ "tw-bg-error-500",
527
+ "focus:tw-text-white",
528
+ "hover:tw-text-white",
529
+ "hover:not-disabled:tw-bg-error-600",
530
+ "active:not-disabled:tw-bg-error-700",
531
+ // anchor disabled override
532
+ "aria-disabled:!tw-bg-error-500"
533
+ ],
534
+ invisible: [
535
+ "tw-text-neutral-800",
536
+ "tw-bg-transparent",
537
+ "focus:tw-text-neutral-800",
538
+ "hover:not-disabled:tw-bg-neutral-100",
539
+ "hover:tw-text-neutral-800",
540
+ "active:not-disabled:tw-bg-neutral-150",
541
+ // contrasting icon on hover/active
542
+ "[&_svg]:tw-text-neutral-400",
543
+ "[&_svg]:hover:not-disabled:tw-text-secondary-600",
544
+ "[&_svg]:active:not-disabled:tw-text-secondary-600",
545
+ // anchor disabled override
546
+ "aria-disabled:!tw-bg-transparent"
547
+ ],
548
+ outline: [
549
+ "tw-text-neutral-800",
550
+ "tw-bg-white",
551
+ // border
552
+ "!tw-border-neutral-200",
553
+ "hover:tw-text-neutral-800",
554
+ "focus:tw-text-neutral-800",
555
+ "hover:not-disabled:!tw-border-neutral-300",
556
+ "hover:not-disabled:tw-bg-neutral-100",
557
+ "active:not-disabled:tw-bg-neutral-200",
558
+ // contrasting icon hover, same as invisible
559
+ "[&_svg]:tw-text-neutral-400",
560
+ "[&_svg]:not-disabled:hover:tw-text-secondary-600",
561
+ "[&_svg]:active:not-disabled:tw-text-secondary-600",
562
+ // anchor disabled override
563
+ "aria-disabled:!tw-bg-white",
564
+ "aria-disabled:!tw-border-neutral-200"
565
+ ],
566
+ inline: [
567
+ "tw-text-neutral-800",
568
+ "tw-bg-transparent",
569
+ "tw-rounded-full",
570
+ "[&_svg]:tw-text-neutral-400",
571
+ "[&_svg]:not-disabled:hover:tw-text-secondary-600",
572
+ "[&_svg]:not-disabled:focus:tw-text-secondary-600"
573
+ ]
574
+ },
575
+ size: {
576
+ medium: ["tw-max-h-10", "tw-min-h-10", "tw-px-4", "tw-py-2.5", "[&_svg]:tw-size-4"],
577
+ small: ["tw-max-h-8", "tw-min-h-8", "tw-px-4", "tw-py-1.5", "[&_svg]:tw-size-4"],
578
+ large: ["tw-max-h-12", "tw-min-h-12", "tw-px-4", "tw-py-3.5", "[&_svg]:tw-size-4"],
579
+ "icon-lg": ["tw-size-12", "tw-p-0", "[&_svg]:tw-size-6"],
580
+ icon: ["tw-size-10", "tw-p-0", "[&_svg]:tw-size-4"],
581
+ "icon-sm": ["tw-size-8", "tw-p-0", "[&_svg]:tw-size-4"],
582
+ "icon-xs": ["tw-size-6", "tw-p-0", "[&_svg]:tw-size-4"],
583
+ "icon-2xs": ["!tw-inline-flex", "tw-size-5", "tw-max-h-5", "[&_svg]:tw-size-3"],
584
+ "icon-3xs": ["tw-h-fit", "tw-w-fit", "[&_svg]:tw-size-4"]
585
+ }
586
+ }
587
+ }
588
+ );
589
+ argoVariants = cva(
590
+ [
591
+ "tailwindcss-preflight",
592
+ // layout
593
+ "tw-relative",
594
+ "tw-inline-flex",
595
+ "tw-items-center",
596
+ "tw-justify-center",
597
+ "tw-whitespace-nowrap",
598
+ "tw-gap-2",
599
+ // border
600
+ "tw-border",
601
+ "tw-border-transparent",
602
+ "tw-rounded-lg",
603
+ // text
604
+ "tw-font-medium",
605
+ "tw-select-none",
606
+ // focus visible
607
+ "!tw-outline-none",
608
+ "focus-visible:tw-ring-2",
609
+ // disabled
610
+ "disabled:tw-cursor-not-allowed",
611
+ "disabled:tw-opacity-50",
612
+ "active:tw-opacity-60",
613
+ "tw-transition-all",
614
+ "tw-bg-clip-padding",
615
+ // anchor support
616
+ "!tw-no-underline",
617
+ // icon
618
+ "tw-shrink-0",
619
+ "[&_svg]:tw-pointer-events-none",
620
+ "[&_svg]:tw-shrink-0",
621
+ "[&_svg:not([class*='tw-size-'])]:tw-size-4"
622
+ ],
623
+ {
624
+ defaultVariants: {
625
+ variant: "primary",
626
+ size: "medium"
627
+ },
628
+ variants: {
629
+ block: {
630
+ true: ["tw-w-full"]
631
+ },
632
+ variant: {
633
+ primary: [
634
+ "tw-bg-primary",
635
+ "tw-text-primary-foreground",
636
+ "[a]:hover:tw-bg-primary/80",
637
+ "hover:not-disabled:tw-bg-primary/90",
638
+ "hover:tw-text-primary-foreground",
639
+ "focus:tw-text-primary-foreground",
640
+ "focus-visible:tw-border-primary",
641
+ "focus-visible:tw-ring-primary/50"
642
+ ],
643
+ secondary: [
644
+ "tw-bg-secondary",
645
+ "tw-text-secondary-foreground",
646
+ "hover:tw-bg-secondary/80",
647
+ "hover:tw-text-secondary-foreground",
648
+ "focus:tw-text-secondary-foreground",
649
+ "focus-visible:tw-border-secondary",
650
+ "focus-visible:tw-ring-primary/50"
651
+ ],
652
+ // should be called "destructive" by Figma
653
+ danger: [
654
+ "tw-bg-destructive",
655
+ "tw-text-destructive-foreground",
656
+ "hover:tw-text-destructive-foreground",
657
+ "focus:tw-text-destructive-foreground",
658
+ "focus-visible:tw-border-destructive",
659
+ "focus-visible:tw-ring-destructive/20"
660
+ ],
661
+ outline: [
662
+ "!tw-border-input",
663
+ "tw-bg-background",
664
+ "hover:not-disabled:tw-bg-accent",
665
+ "hover:not-disabled:tw-text-accent-foreground",
666
+ "hover:active:tw-bg-background",
667
+ "focus-visible:!tw-border-primary",
668
+ "focus-visible:tw-ring-primary/50"
669
+ ],
670
+ // should be called "ghost" by Figma
671
+ invisible: [
672
+ "tw-bg-transparent",
673
+ "tw-text-foreground",
674
+ "hover:not-disabled:tw-bg-accent",
675
+ "hover:not-disabled:tw-text-accent-foreground",
676
+ "hover:not-disabled:tw-border-accent",
677
+ "focus-visible:tw-ring-primary/50"
678
+ ],
679
+ // should be called "link" by Figma
680
+ inline: [
681
+ "tw-bg-transparent",
682
+ "tw-text-primary",
683
+ "hover:tw-underline",
684
+ "hover:active:tw-bg-transparent",
685
+ "focus-visible:tw-ring-primary/50"
686
+ ]
687
+ },
688
+ size: {
689
+ // should be called "default" by Figma
690
+ medium: ["tw-max-h-9", "tw-py-2", "tw-px-4", "tw-text-sm"],
691
+ // should be called "small" by Figma
692
+ small: ["tw-max-h-8", "tw-py-2", "tw-px-3", "tw-text-xs"],
693
+ // should be called "large" by Figma
694
+ large: ["tw-max-h-10", "tw-py-2.5", "tw-px-6", "tw-text-sm"],
695
+ "icon-lg": ["tw-size-10"],
696
+ icon: ["tw-size-9"],
697
+ "icon-sm": ["tw-size-8"],
698
+ // unsupported in ARGO, remove when old design is gone
699
+ "icon-xs": [],
700
+ "icon-2xs": [],
701
+ "icon-3xs": []
702
+ }
703
+ }
704
+ }
705
+ );
706
+ }
707
+ });
708
+ var Button;
709
+ var init_Button = __esm({
710
+ "src/components/Button/Button.tsx"() {
711
+ init_utils();
712
+ init_Icon2();
713
+ init_styles();
714
+ Button = ({
715
+ ref,
716
+ children,
717
+ disabled = false,
718
+ className,
719
+ type = "button",
720
+ icon: iconProp,
721
+ isLoading = false,
722
+ asChild = false,
723
+ onClick,
724
+ argo = false,
725
+ variant = "primary",
726
+ size = "medium",
727
+ block = false,
728
+ ...buttonProps
729
+ }) => {
730
+ const Comp = asChild ? Root$2 : "button";
731
+ const icon = isLoading ? "spinner" : iconProp;
732
+ const classNames = argo ? argoVariants({ variant, size, block, className }) : variants({
733
+ size,
734
+ variant,
735
+ block,
736
+ className
737
+ });
738
+ const handleClick = (event) => {
739
+ const isAnchor = event.currentTarget.tagName === "A";
740
+ if (isAnchor && disabled) {
741
+ event.preventDefault();
742
+ return;
743
+ }
744
+ onClick?.(event);
745
+ };
746
+ return /* @__PURE__ */ jsxs(
747
+ Comp,
748
+ {
749
+ ...buttonProps,
750
+ ref,
751
+ disabled,
752
+ "aria-disabled": disabled,
753
+ "data-variant": variant,
754
+ "data-icon-only": !children,
755
+ type,
756
+ onClick: handleClick,
757
+ className: cn(classNames),
758
+ children: [
759
+ icon && /* @__PURE__ */ jsx(Icon, { spin: isLoading, icon }),
760
+ /* @__PURE__ */ jsx(Slottable, { children })
761
+ ]
762
+ }
763
+ );
764
+ };
765
+ }
766
+ });
767
+ var init_ButtonInline = __esm({
768
+ "src/components/Button/ButtonInline.tsx"() {
769
+ cva(
770
+ [
771
+ "tailwindcss-preflight",
772
+ "tw-inline-flex",
773
+ "tw-items-center",
774
+ "tw-gap-2",
775
+ "tw-underline-offset-2",
776
+ "disabled:tw-opacity-40",
777
+ "disabled:tw-cursor-not-allowed",
778
+ "disabled:tw-text-neutral-500",
779
+ "disabled:tw-no-underline",
780
+ "[&_svg]:disabled:tw-text-neutral-400"
781
+ ],
782
+ {
783
+ defaultVariants: {
784
+ variant: "link",
785
+ color: "link"
786
+ },
787
+ variants: {
788
+ color: {
789
+ link: [
790
+ "tw-text-secondary-500",
791
+ "hover:tw-text-secondary-600",
792
+ "[&_svg]:tw-text-secondary-500"
793
+ ],
794
+ dark: ["tw-text-neutral-800 [&_svg]:tw-text-neutral-400"],
795
+ danger: ["tw-text-error-500 [&_svg]:tw-text-error-500"],
796
+ muted: ["tw-text-muted-foreground [&_svg]:tw-text-muted-foreground"],
797
+ custom: []
798
+ },
799
+ variant: {
800
+ link: ["tw-underline", "hover:tw-no-underline"],
801
+ "link-reverse": ["tw-no-underline", "", "hover:tw-underline"],
802
+ custom: []
803
+ }
804
+ }
805
+ }
806
+ );
807
+ }
808
+ });
809
+
810
+ // src/components/Button/index.ts
811
+ var init_Button2 = __esm({
812
+ "src/components/Button/index.ts"() {
813
+ init_Button();
814
+ init_ButtonInline();
815
+ }
816
+ });
817
+ var Clipboard;
818
+ var init_Clipboard = __esm({
819
+ "src/components/Clipboard/Clipboard.tsx"() {
820
+ init_utils();
821
+ Clipboard = ({
822
+ ref,
823
+ text: textProp,
824
+ children,
825
+ tooltip = "Copy to Clipboard",
826
+ tooltipPlacement = "top",
827
+ tooltipVariant: tooltipVariantProp = "action",
828
+ asChild = false,
829
+ onClick,
830
+ className,
831
+ ...restButtonProps
832
+ }) => {
833
+ const [isTooltipOpen, setIsTooltipOpen] = useState(false);
834
+ const [state, setState] = useState("ready");
835
+ const text = typeof textProp === "function" ? textProp() : textProp;
836
+ const copy = async (text2) => {
837
+ try {
838
+ if (!document.hasFocus()) window.focus();
839
+ await copyToClipboard(text2);
840
+ setState("copied");
841
+ } catch {
842
+ setState("error");
843
+ }
844
+ };
845
+ const handleOnClick = (event) => {
846
+ if (text && state === "ready") void copy(text);
847
+ onClick?.(event);
848
+ };
849
+ const handleOnOpenChange = (open) => {
850
+ if (!open && state !== "ready") setState("ready");
851
+ setIsTooltipOpen(open);
852
+ };
853
+ const tooltipContent = (() => {
854
+ if (!text) return "Nothing to copy";
855
+ if (state === "error") return "Failed to copy";
856
+ if (state === "copied") return "Copied to Clipboard";
857
+ return tooltip;
858
+ })();
859
+ const tooltipVariant = state === "ready" && !!text ? tooltipVariantProp : "action";
860
+ return /* @__PURE__ */ jsxs(Tooltip$1.Root, { open: isTooltipOpen, onOpenChange: handleOnOpenChange, children: [
861
+ /* @__PURE__ */ jsx(
862
+ Tooltip$1.Trigger,
863
+ {
864
+ ...restButtonProps,
865
+ asChild,
866
+ keepOpenOnClick: true,
867
+ onClick: handleOnClick,
868
+ className: cn$1("tw-cursor-pointer", className),
869
+ ref,
870
+ children: children ?? text
871
+ }
872
+ ),
873
+ /* @__PURE__ */ jsx(
874
+ Tooltip$1.Content,
875
+ {
876
+ keepOpenOnPointerDownOutside: true,
877
+ placement: tooltipPlacement,
878
+ variant: tooltipVariant,
879
+ children: tooltipContent
880
+ }
881
+ )
882
+ ] });
883
+ };
884
+ }
885
+ });
886
+
887
+ // src/components/Clipboard/index.ts
888
+ var init_Clipboard2 = __esm({
889
+ "src/components/Clipboard/index.ts"() {
890
+ init_Clipboard();
891
+ }
892
+ });
893
+ var DEFAULT_ICON, ClipboardButton;
894
+ var init_ClipboardButton = __esm({
895
+ "src/blocks/ClipboardButton/ClipboardButton.tsx"() {
896
+ init_Button2();
897
+ init_Clipboard2();
898
+ DEFAULT_ICON = "copy";
899
+ ClipboardButton = ({
900
+ // clipboard props
901
+ text,
902
+ tooltip,
903
+ tooltipPlacement,
904
+ tooltipVariant,
905
+ // button props
906
+ icon = DEFAULT_ICON,
907
+ variant = "outline",
908
+ children,
909
+ ...rest
910
+ }) => /* @__PURE__ */ jsx(
911
+ Clipboard,
912
+ {
913
+ asChild: true,
914
+ tooltip,
915
+ tooltipPlacement,
916
+ tooltipVariant,
917
+ text,
918
+ children: /* @__PURE__ */ jsx(Button, { ...rest, icon, variant, disabled: !text, children })
919
+ }
920
+ );
921
+ }
922
+ });
923
+
924
+ // src/blocks/ClipboardButton/index.ts
925
+ var init_ClipboardButton2 = __esm({
926
+ "src/blocks/ClipboardButton/index.ts"() {
927
+ init_ClipboardButton();
928
+ }
929
+ });
930
+ var MIN_SCALE, MAX_SCALE, ZOOM_STEP, ZoomableSvg;
931
+ var init_ZoomableSvg = __esm({
932
+ "src/components/ZoomableSvg/ZoomableSvg.tsx"() {
933
+ init_ClipboardButton2();
934
+ init_utils();
935
+ init_Button2();
936
+ init_Tooltip2();
937
+ MIN_SCALE = 0.5;
938
+ MAX_SCALE = 3;
939
+ ZOOM_STEP = 0.1;
940
+ ZoomableSvg = ({ html, copyText, className }) => {
941
+ const containerRef = useRef(null);
942
+ const [scale, setScale] = useState(1);
943
+ const [translate, setTranslate] = useState({ x: 0, y: 0 });
944
+ const [isFullscreen, setIsFullscreen] = useState(false);
945
+ useEffect(() => {
946
+ if (!isFullscreen) return;
947
+ const onKeyDown = (e) => {
948
+ if (e.key === "Escape") {
949
+ e.stopPropagation();
950
+ setIsFullscreen(false);
951
+ }
952
+ };
953
+ document.addEventListener("keydown", onKeyDown, { capture: true });
954
+ return () => document.removeEventListener("keydown", onKeyDown, { capture: true });
955
+ }, [isFullscreen]);
956
+ const dragRef = useRef(null);
957
+ useEffect(() => {
958
+ const el = containerRef.current;
959
+ if (!el) return;
960
+ const onWheel = (e) => {
961
+ if (!e.ctrlKey && !e.metaKey) return;
962
+ e.preventDefault();
963
+ const delta = e.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;
964
+ setScale((s) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s + delta)));
965
+ };
966
+ el.addEventListener("wheel", onWheel, { passive: false });
967
+ return () => el.removeEventListener("wheel", onWheel);
968
+ }, []);
969
+ const didDragRef = useRef(false);
970
+ const handleMouseDown = useCallback(
971
+ (e) => {
972
+ if (e.button !== 0) return;
973
+ e.preventDefault();
974
+ didDragRef.current = false;
975
+ dragRef.current = {
976
+ startX: e.clientX,
977
+ startY: e.clientY,
978
+ startTx: translate.x,
979
+ startTy: translate.y
980
+ };
981
+ },
982
+ [translate]
983
+ );
984
+ const handleMouseMove = useCallback((e) => {
985
+ if (!dragRef.current) return;
986
+ didDragRef.current = true;
987
+ setTranslate({
988
+ x: dragRef.current.startTx + e.clientX - dragRef.current.startX,
989
+ y: dragRef.current.startTy + e.clientY - dragRef.current.startY
990
+ });
991
+ }, []);
992
+ const handleMouseUp = useCallback(() => {
993
+ dragRef.current = null;
994
+ }, []);
995
+ const handleReset = useCallback(() => {
996
+ setScale(1);
997
+ setTranslate({ x: 0, y: 0 });
998
+ }, []);
999
+ const isZoomed = Math.abs(scale - 1) > 1e-3 || translate.x !== 0 || translate.y !== 0;
1000
+ const handleClick = useCallback((e) => {
1001
+ if (didDragRef.current) {
1002
+ e.stopPropagation();
1003
+ }
1004
+ }, []);
1005
+ const stopPropagation = useCallback((e) => {
1006
+ e.stopPropagation();
1007
+ }, []);
1008
+ const diagramContent = /* @__PURE__ */ jsxs(
1009
+ "div",
1010
+ {
1011
+ role: "presentation",
1012
+ className: cn("tw-group/zoom tw-relative", isFullscreen && "tw-h-full"),
1013
+ onClick: handleClick,
1014
+ children: [
1015
+ /* @__PURE__ */ jsx(
1016
+ "div",
1017
+ {
1018
+ role: "presentation",
1019
+ ref: containerRef,
1020
+ className: cn(
1021
+ "tw-overflow-hidden tw-cursor-grab active:tw-cursor-grabbing tw-p-3",
1022
+ isFullscreen && "tw-h-full"
1023
+ ),
1024
+ onMouseDown: handleMouseDown,
1025
+ onMouseMove: handleMouseMove,
1026
+ onMouseUp: handleMouseUp,
1027
+ onMouseLeave: handleMouseUp,
1028
+ children: /* @__PURE__ */ jsx(
1029
+ "div",
1030
+ {
1031
+ className: cn(
1032
+ "tw-flex tw-justify-center tw-origin-center",
1033
+ isFullscreen && "tw-h-full [&>svg]:tw-h-full"
1034
+ ),
1035
+ style: { transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})` },
1036
+ dangerouslySetInnerHTML: { __html: html }
1037
+ }
1038
+ )
1039
+ }
1040
+ ),
1041
+ /* @__PURE__ */ jsxs(
1042
+ "div",
1043
+ {
1044
+ role: "presentation",
1045
+ className: "tw-absolute tw-right-1 tw-top-1 tw-flex tw-gap-1 tw-opacity-0 tw-transition-opacity group-hover/zoom:tw-opacity-100",
1046
+ onClick: stopPropagation,
1047
+ children: [
1048
+ isZoomed && /* @__PURE__ */ jsx(Tooltip, { tooltip: "Reset zoom", placement: "top", triggerAsChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "outline", onClick: handleReset, argo: true, children: "Reset" }) }),
1049
+ copyText && /* @__PURE__ */ jsx(
1050
+ ClipboardButton,
1051
+ {
1052
+ text: copyText,
1053
+ tooltip: "Copy code",
1054
+ size: "icon-sm",
1055
+ variant: "outline",
1056
+ argo: true
1057
+ }
1058
+ ),
1059
+ /* @__PURE__ */ jsx(
1060
+ Tooltip,
1061
+ {
1062
+ tooltip: isFullscreen ? "Exit fullscreen" : "Fullscreen",
1063
+ placement: "top",
1064
+ triggerAsChild: true,
1065
+ children: /* @__PURE__ */ jsx(
1066
+ Button,
1067
+ {
1068
+ size: "icon-sm",
1069
+ variant: "outline",
1070
+ icon: isFullscreen ? "down-left-and-up-right-to-center" : "up-right-and-down-left-from-center",
1071
+ "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
1072
+ onClick: () => setIsFullscreen((f) => !f),
1073
+ argo: true
1074
+ }
1075
+ )
1076
+ }
1077
+ )
1078
+ ]
1079
+ }
1080
+ )
1081
+ ]
1082
+ }
1083
+ );
1084
+ if (isFullscreen) {
1085
+ return /* @__PURE__ */ jsx(
1086
+ "div",
1087
+ {
1088
+ role: "presentation",
1089
+ className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-neutral-50 tw-p-4",
1090
+ onClick: stopPropagation,
1091
+ children: diagramContent
1092
+ }
1093
+ );
1094
+ }
1095
+ return /* @__PURE__ */ jsx(
1096
+ "div",
1097
+ {
1098
+ className: cn(
1099
+ "tw-overflow-hidden tw-rounded-md tw-border tw-border-neutral-150 tw-bg-neutral-50",
1100
+ className
1101
+ ),
1102
+ children: diagramContent
1103
+ }
1104
+ );
1105
+ };
1106
+ }
1107
+ });
1108
+
1109
+ // src/components/ZoomableSvg/index.ts
1110
+ var init_ZoomableSvg2 = __esm({
1111
+ "src/components/ZoomableSvg/index.ts"() {
1112
+ init_ZoomableSvg();
1113
+ }
1114
+ });
1115
+
1116
+ // src/blocks/MermaidDiagram/MermaidDiagram.tsx
1117
+ var MermaidDiagram_exports = {};
1118
+ __export(MermaidDiagram_exports, {
1119
+ MermaidDiagram: () => MermaidDiagram
1120
+ });
1121
+ var mermaidPromise, getMermaid, stripFontImports, tryFastRender, makeResponsive, RENDER_DEBOUNCE_MS, svgCache, MermaidDiagram;
1122
+ var init_MermaidDiagram = __esm({
1123
+ "src/blocks/MermaidDiagram/MermaidDiagram.tsx"() {
1124
+ init_Skeleton();
1125
+ init_ZoomableSvg2();
1126
+ init_utils();
1127
+ mermaidPromise = null;
1128
+ getMermaid = () => {
1129
+ if (!mermaidPromise) {
1130
+ mermaidPromise = import('mermaid').then((m) => {
1131
+ m.default.initialize({
1132
+ startOnLoad: false,
1133
+ securityLevel: "strict",
1134
+ theme: "base",
1135
+ themeVariables: {
1136
+ primaryColor: colors.secondary[100],
1137
+ primaryTextColor: colors.neutral[800],
1138
+ primaryBorderColor: colors.secondary[700],
1139
+ secondaryColor: colors.white,
1140
+ secondaryTextColor: colors.neutral[800],
1141
+ secondaryBorderColor: colors.neutral[150],
1142
+ tertiaryColor: colors.warning[100],
1143
+ tertiaryTextColor: colors.neutral[800],
1144
+ tertiaryBorderColor: colors.warning[500],
1145
+ lineColor: colors.neutral[300],
1146
+ textColor: colors.neutral[800],
1147
+ mainBkg: colors.secondary[100],
1148
+ nodeBorder: colors.secondary[700],
1149
+ clusterBkg: colors.white,
1150
+ clusterBorder: colors.neutral[150],
1151
+ titleColor: colors.neutral[800],
1152
+ edgeLabelBackground: colors.white,
1153
+ nodeTextColor: colors.neutral[800],
1154
+ actorBorder: colors.secondary[700],
1155
+ actorBkg: colors.secondary[100],
1156
+ actorTextColor: colors.neutral[800],
1157
+ actorLineColor: colors.neutral[300],
1158
+ signalColor: colors.neutral[800],
1159
+ signalTextColor: colors.neutral[800],
1160
+ labelBoxBkgColor: colors.secondary[100],
1161
+ labelBoxBorderColor: colors.secondary[700],
1162
+ labelTextColor: colors.neutral[800],
1163
+ loopTextColor: colors.neutral[800],
1164
+ noteBorderColor: colors.warning[500],
1165
+ noteBkgColor: colors.warning[100],
1166
+ noteTextColor: colors.neutral[800],
1167
+ sectionBkgColor: colors.secondary[100],
1168
+ altSectionBkgColor: colors.white,
1169
+ sectionBkgColor2: colors.neutral[100],
1170
+ taskBorderColor: colors.secondary[700],
1171
+ taskBkgColor: colors.secondary[100],
1172
+ taskTextColor: colors.neutral[800],
1173
+ taskTextDarkColor: colors.neutral[800],
1174
+ taskTextLightColor: colors.neutral[800],
1175
+ activeTaskBorderColor: colors.primary.DEFAULT,
1176
+ activeTaskBkgColor: colors.secondary[200],
1177
+ doneTaskBorderColor: colors.primary[600],
1178
+ doneTaskBkgColor: colors.primary[100],
1179
+ critBorderColor: colors.error[500],
1180
+ critBkgColor: colors.error[100],
1181
+ fontFamily: "Inter, system-ui, sans-serif",
1182
+ fontSize: "14px"
1183
+ }
1184
+ });
1185
+ return m;
1186
+ }).catch((err) => {
1187
+ mermaidPromise = null;
1188
+ throw err;
1189
+ });
1190
+ }
1191
+ return mermaidPromise;
1192
+ };
1193
+ stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1194
+ tryFastRender = (code) => {
1195
+ try {
1196
+ return stripFontImports(
1197
+ renderMermaidSVG(code, {
1198
+ bg: colors.white,
1199
+ fg: colors.neutral[800],
1200
+ transparent: true,
1201
+ font: "Inter, system-ui, sans-serif"
1202
+ })
1203
+ );
1204
+ } catch {
1205
+ return null;
1206
+ }
1207
+ };
1208
+ makeResponsive = (svgString) => {
1209
+ const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1210
+ const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1211
+ let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1212
+ if (!vbWidth) return result;
1213
+ const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1214
+ if (hasStyle) {
1215
+ result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1216
+ const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1217
+ const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1218
+ return `${pre} style="${combined}"`;
1219
+ });
1220
+ } else {
1221
+ result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1222
+ }
1223
+ return result;
1224
+ };
1225
+ RENDER_DEBOUNCE_MS = 300;
1226
+ svgCache = /* @__PURE__ */ new Map();
1227
+ MermaidDiagram = ({ code }) => {
1228
+ const id = useId();
1229
+ const [svg, setSvg] = useState(() => {
1230
+ const cached = svgCache.get(code);
1231
+ if (cached) return cached;
1232
+ const fast = tryFastRender(code);
1233
+ if (fast) {
1234
+ svgCache.set(code, fast);
1235
+ return fast;
1236
+ }
1237
+ return null;
1238
+ });
1239
+ const [renderFailed, setRenderFailed] = useState(false);
1240
+ const debounceRef = useRef(null);
1241
+ const renderIdRef = useRef(0);
1242
+ const [prevCode, setPrevCode] = useState(code);
1243
+ if (code !== prevCode) {
1244
+ setPrevCode(code);
1245
+ const cached = svgCache.get(code);
1246
+ const fast = cached ?? tryFastRender(code);
1247
+ if (fast && !cached) svgCache.set(code, fast);
1248
+ setSvg(fast);
1249
+ setRenderFailed(false);
1250
+ }
1251
+ useEffect(() => {
1252
+ if (svgCache.has(code)) {
1253
+ setSvg(svgCache.get(code));
1254
+ setRenderFailed(false);
1255
+ return;
1256
+ }
1257
+ const fastResult = tryFastRender(code);
1258
+ if (fastResult) {
1259
+ svgCache.set(code, fastResult);
1260
+ setSvg(fastResult);
1261
+ setRenderFailed(false);
1262
+ return;
1263
+ }
1264
+ setSvg(null);
1265
+ const currentRenderId = ++renderIdRef.current;
1266
+ setRenderFailed(false);
1267
+ if (debounceRef.current) {
1268
+ clearTimeout(debounceRef.current);
1269
+ }
1270
+ debounceRef.current = setTimeout(() => {
1271
+ getMermaid().then(async (mermaidModule) => {
1272
+ if (renderIdRef.current !== currentRenderId) return;
1273
+ const rendererId = `mermaid-${id.replaceAll(":", "")}`;
1274
+ const container = document.createElement("div");
1275
+ container.style.visibility = "hidden";
1276
+ container.style.position = "absolute";
1277
+ container.style.top = "-9999px";
1278
+ container.style.width = "900px";
1279
+ document.body.appendChild(container);
1280
+ try {
1281
+ const result = await mermaidModule.default.render(rendererId, code, container);
1282
+ if (renderIdRef.current === currentRenderId && result) {
1283
+ svgCache.set(code, result.svg);
1284
+ setSvg(result.svg);
1285
+ setRenderFailed(false);
1286
+ }
1287
+ } finally {
1288
+ container.remove();
1289
+ }
1290
+ }).catch((err) => {
1291
+ if (renderIdRef.current === currentRenderId) {
1292
+ console.error("[MermaidDiagram] fallback failed:", err);
1293
+ setSvg(null);
1294
+ setRenderFailed(true);
1295
+ }
1296
+ });
1297
+ }, RENDER_DEBOUNCE_MS);
1298
+ const timer = debounceRef.current;
1299
+ const renderId = renderIdRef;
1300
+ return () => {
1301
+ renderId.current++;
1302
+ if (timer) {
1303
+ clearTimeout(timer);
1304
+ }
1305
+ };
1306
+ }, [code, id]);
1307
+ const processedSvg = svg ? makeResponsive(svg) : null;
1308
+ if (renderFailed) {
1309
+ return /* @__PURE__ */ jsx(
1310
+ "pre",
1311
+ {
1312
+ className: cn(
1313
+ "tw-my-3 tw-overflow-auto tw-whitespace-pre-wrap tw-break-all",
1314
+ "tw-py-3 tw-px-4",
1315
+ "tw-bg-neutral-50",
1316
+ "tw-rounded-md tw-text-neutral-400",
1317
+ "tw-text-sm tw-font-mono"
1318
+ ),
1319
+ children: /* @__PURE__ */ jsx("code", { children: code })
1320
+ }
1321
+ );
1322
+ }
1323
+ if (processedSvg) {
1324
+ return /* @__PURE__ */ jsx(
1325
+ ZoomableSvg,
1326
+ {
1327
+ html: processedSvg,
1328
+ copyText: `\`\`\`mermaid
1329
+ ${code}
1330
+ \`\`\``,
1331
+ className: "tw-my-3"
1332
+ },
1333
+ code
1334
+ );
1335
+ }
1336
+ return /* @__PURE__ */ jsx("div", { className: "tw-my-3 tw-overflow-hidden tw-rounded-md tw-border tw-border-neutral-150 tw-bg-neutral-50 tw-p-6", children: /* @__PURE__ */ jsx(Skeleton, { className: "tw-h-40" }) });
1337
+ };
1338
+ }
1339
+ });
1340
+
1341
+ // src/components/MarkdownEditor/MarkdownEditor.tsx
1342
+ init_utils();
1343
+ var ImageRendererContext = createContext(null);
1344
+ var ImageRendererProvider = ImageRendererContext;
1345
+ var useImageRenderer = () => use(ImageRendererContext);
1346
+ var isPlaceholder = (src) => src.startsWith("upload-placeholder-");
1347
+ var ImageNodeComponent = ({ src, alt }) => {
1348
+ const renderer = useImageRenderer();
1349
+ if (isPlaceholder(src)) {
1350
+ return /* @__PURE__ */ jsx("span", { className: "tw-inline-flex tw-items-center tw-gap-1 tw-rounded tw-bg-neutral-100 tw-px-2 tw-py-1 tw-text-xs tw-text-neutral-400", children: "Uploading image\u2026" });
1351
+ }
1352
+ if (renderer) return /* @__PURE__ */ jsx(Fragment, { children: renderer({ src, alt }) });
1353
+ return /* @__PURE__ */ jsx("img", { src, alt });
1354
+ };
1355
+ var ImageNode = class _ImageNode extends DecoratorNode {
1356
+ __src;
1357
+ __altText;
1358
+ static getType() {
1359
+ return "image";
1360
+ }
1361
+ static clone(node) {
1362
+ return new _ImageNode(node.__src, node.__altText, node.__key);
1363
+ }
1364
+ constructor(src, altText, key) {
1365
+ super(key);
1366
+ this.__src = src;
1367
+ this.__altText = altText;
1368
+ }
1369
+ getSrc() {
1370
+ return this.__src;
1371
+ }
1372
+ getAlt() {
1373
+ return this.__altText;
1374
+ }
1375
+ setSrc(src) {
1376
+ const writable = this.getWritable();
1377
+ writable.__src = src;
1378
+ }
1379
+ setAlt(altText) {
1380
+ const writable = this.getWritable();
1381
+ writable.__altText = altText;
1382
+ }
1383
+ createDOM(config) {
1384
+ const span = document.createElement("span");
1385
+ const className = config.theme.image;
1386
+ if (typeof className === "string") {
1387
+ span.className = className;
1388
+ }
1389
+ return span;
1390
+ }
1391
+ updateDOM() {
1392
+ return false;
1393
+ }
1394
+ decorate() {
1395
+ return /* @__PURE__ */ jsx(ImageNodeComponent, { src: this.__src, alt: this.__altText });
1396
+ }
1397
+ isInline() {
1398
+ return true;
1399
+ }
1400
+ static importJSON(serializedNode) {
1401
+ return $createImageNode(serializedNode.src, serializedNode.altText);
1402
+ }
1403
+ exportJSON() {
1404
+ return {
1405
+ type: "image",
1406
+ version: 1,
1407
+ src: this.__src,
1408
+ altText: this.__altText
1409
+ };
1410
+ }
1411
+ exportDOM() {
1412
+ const element = document.createElement("img");
1413
+ element.setAttribute("src", this.__src);
1414
+ element.setAttribute("alt", this.__altText);
1415
+ return { element };
1416
+ }
1417
+ static importDOM() {
1418
+ return {
1419
+ img: () => ({
1420
+ conversion: (domNode) => {
1421
+ const src = domNode.getAttribute("src") || "";
1422
+ const alt = domNode.getAttribute("alt") || "";
1423
+ return { node: $createImageNode(src, alt) };
1424
+ },
1425
+ priority: 0
1426
+ })
1427
+ };
1428
+ }
1429
+ };
1430
+ var $createImageNode = (src, altText) => {
1431
+ return new ImageNode(src, altText);
1432
+ };
1433
+ var $isImageNode = (node) => {
1434
+ return node instanceof ImageNode;
1435
+ };
1436
+
1437
+ // src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1438
+ init_Skeleton();
1439
+ var MermaidDiagram2 = lazy(
1440
+ () => Promise.resolve().then(() => (init_MermaidDiagram(), MermaidDiagram_exports)).then(
1441
+ (m) => ({ default: m.MermaidDiagram }),
1442
+ (error) => {
1443
+ console.error("[MarkdownEditor] failed to load MermaidDiagram chunk", error);
1444
+ return {
1445
+ default: ({ code }) => /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: code }) })
1446
+ };
1447
+ }
1448
+ )
1449
+ );
1450
+ var MermaidNodeComponent = ({ code }) => {
1451
+ return /* @__PURE__ */ jsx(
1452
+ Suspense,
1453
+ {
1454
+ fallback: /* @__PURE__ */ jsx("div", { className: "tw-my-3 tw-overflow-hidden tw-rounded-card tw-border tw-border-neutral-150 tw-bg-neutral-50 tw-p-6", children: /* @__PURE__ */ jsx(Skeleton, { className: "tw-h-40" }) }),
1455
+ children: /* @__PURE__ */ jsx(MermaidDiagram2, { code })
1456
+ }
1457
+ );
1458
+ };
1459
+ var MermaidNode = class _MermaidNode extends DecoratorNode {
1460
+ __code;
1461
+ static getType() {
1462
+ return "mermaid";
1463
+ }
1464
+ static clone(node) {
1465
+ return new _MermaidNode(node.__code, node.__key);
1466
+ }
1467
+ constructor(code, key) {
1468
+ super(key);
1469
+ this.__code = code;
1470
+ }
1471
+ getCode() {
1472
+ return this.__code;
1473
+ }
1474
+ setCode(code) {
1475
+ const writable = this.getWritable();
1476
+ writable.__code = code;
1477
+ }
1478
+ createDOM() {
1479
+ const div = document.createElement("div");
1480
+ div.setAttribute("data-lexical-mermaid", "true");
1481
+ return div;
1482
+ }
1483
+ updateDOM() {
1484
+ return false;
1485
+ }
1486
+ decorate() {
1487
+ return /* @__PURE__ */ jsx(MermaidNodeComponent, { code: this.__code });
1488
+ }
1489
+ isInline() {
1490
+ return false;
1491
+ }
1492
+ static importJSON(serializedNode) {
1493
+ return $createMermaidNode(serializedNode.code);
1494
+ }
1495
+ exportJSON() {
1496
+ return {
1497
+ type: "mermaid",
1498
+ version: 1,
1499
+ code: this.__code
1500
+ };
1501
+ }
1502
+ };
1503
+ var $createMermaidNode = (code) => {
1504
+ return new MermaidNode(code);
1505
+ };
1506
+ var $isMermaidNode = (node) => {
1507
+ return node instanceof MermaidNode;
1508
+ };
1509
+
1510
+ // src/components/Toast/toast.tsx
1511
+ init_utils();
1512
+
1513
+ // src/components/Toast/ToastRoot.tsx
1514
+ init_utils();
1515
+ init_Icon2();
1516
+
1517
+ // src/components/Toast/ToastAction.tsx
1518
+ init_utils();
1519
+ var ToastAction = ({
1520
+ ref,
1521
+ className,
1522
+ ...rest
1523
+ }) => /* @__PURE__ */ jsx(
1524
+ "button",
1525
+ {
1526
+ ...rest,
1527
+ ref,
1528
+ "data-slot": "toast-action",
1529
+ type: "button",
1530
+ className: cn(
1531
+ // layout
1532
+ "tw-col-start-3",
1533
+ "tw-row-start-1",
1534
+ "tw-flex",
1535
+ "tw-items-center",
1536
+ "tw-justify-center",
1537
+ // font
1538
+ "tw-text-xs",
1539
+ "tw-font-medium",
1540
+ "tw-text-primary",
1541
+ // sizing
1542
+ "tw-px-2",
1543
+ "tw-h-6",
1544
+ // styles
1545
+ "tw-bg-primary-foreground",
1546
+ "tw-rounded",
1547
+ className
1548
+ )
1549
+ }
1550
+ );
1551
+
1552
+ // src/components/Toast/ToastDescription.tsx
1553
+ init_utils();
1554
+ var ToastDescription = ({
1555
+ ref,
1556
+ className,
1557
+ children,
1558
+ ...rest
1559
+ }) => /* @__PURE__ */ jsx(
1560
+ "div",
1561
+ {
1562
+ ref,
1563
+ "data-slot": "toast-description",
1564
+ className: cn(
1565
+ "tw-col-start-2",
1566
+ "tw-font-normal",
1567
+ "tw-break-words",
1568
+ "tw-text-white",
1569
+ "group-data-[variant=default]/toast:tw-text-muted-foreground",
1570
+ className
1571
+ ),
1572
+ ...rest,
1573
+ children
1574
+ }
1575
+ );
1576
+
1577
+ // src/components/Toast/ToastDismiss.tsx
1578
+ init_utils();
1579
+ init_Icon2();
1580
+ var ToastDismiss = ({
1581
+ ref,
1582
+ className,
1583
+ ...rest
1584
+ }) => /* @__PURE__ */ jsxs(
1585
+ "button",
1586
+ {
1587
+ ref,
1588
+ "data-slot": "toast-dismiss",
1589
+ className: cn(
1590
+ "tw-flex",
1591
+ "tw-justify-center",
1592
+ "tw-col-start-4",
1593
+ "tw-row-start-1",
1594
+ "tailwindcss-preflight",
1595
+ "[&_svg]:tw-aspect-square",
1596
+ "[&_svg]:tw-size-4",
1597
+ "[&_svg]:tw-p-1",
1598
+ "tw-text-white",
1599
+ "group-data-[variant=default]/toast:[&_svg]:tw-text-popover-foreground",
1600
+ className
1601
+ ),
1602
+ type: "button",
1603
+ ...rest,
1604
+ children: [
1605
+ /* @__PURE__ */ jsx(Icon, { icon: "times" }),
1606
+ /* @__PURE__ */ jsx("span", { className: "tw-sr-only", children: "Dismiss" })
1607
+ ]
1608
+ }
1609
+ );
1610
+
1611
+ // src/components/Toast/ToastDuration.tsx
1612
+ init_utils();
1613
+ var ToastDuration = ({
1614
+ ref,
1615
+ duration,
1616
+ className,
1617
+ style,
1618
+ ...rest
1619
+ }) => /* @__PURE__ */ jsx(
1620
+ "span",
1621
+ {
1622
+ ...rest,
1623
+ ref,
1624
+ className: cn(
1625
+ "tw-bg-white/30",
1626
+ "group-data-[variant=default]/toast:tw-bg-popover-foreground/20",
1627
+ "tw-rounded-bl-lg",
1628
+ "tw-mx-px",
1629
+ // positioning
1630
+ "tw-absolute",
1631
+ "tw-bottom-0",
1632
+ "tw-left-0",
1633
+ // sizing
1634
+ "tw-h-1",
1635
+ // animation
1636
+ "tw-animate-toast-progress",
1637
+ "group-hover/toast:[animation-play-state:paused]",
1638
+ className
1639
+ ),
1640
+ style: {
1641
+ animationDuration: `${duration}ms`,
1642
+ ...style
1643
+ }
1644
+ }
1645
+ );
1646
+
1647
+ // src/components/Toast/ToastTitle.tsx
1648
+ init_utils();
1649
+ var ToastTitle = ({
1650
+ ref,
1651
+ className,
1652
+ children,
1653
+ ...rest
1654
+ }) => /* @__PURE__ */ jsx(
1655
+ "div",
1656
+ {
1657
+ ref,
1658
+ "data-slot": "toast-title",
1659
+ className: cn(
1660
+ "tw-col-start-2",
1661
+ "tw-text-sm",
1662
+ "tw-leading-6",
1663
+ "tw-min-h-6",
1664
+ "tw-self-center",
1665
+ "tw-text-white",
1666
+ "group-data-[variant=default]/toast:tw-text-popover-foreground",
1667
+ "tw-break-words",
1668
+ "tw-font-medium",
1669
+ className
1670
+ ),
1671
+ ...rest,
1672
+ children
1673
+ }
1674
+ );
1675
+ var variants2 = cva(
1676
+ [
1677
+ "tailwindcss-preflight",
1678
+ "tw-group/toast",
1679
+ "tw-relative",
1680
+ // layout
1681
+ "tw-grid",
1682
+ "tw-grid-cols-[0_1fr_auto_auto]",
1683
+ "tw-items-start",
1684
+ "has-[[data-slot=toast-description]]:tw-grid-rows-[auto_auto]",
1685
+ "has-[[data-slot=toast-icon]]:tw-grid-cols-[auto_1fr_auto_auto]",
1686
+ "[&_[data-slot=toast-icon]]:tw-mr-2",
1687
+ "[&_[data-slot=toast-title]]:tw-mr-2.5",
1688
+ "[&_[data-slot=toast-description]]:tw-mr-2.5",
1689
+ "[&_[data-slot=toast-action]]:tw-mr-2",
1690
+ "[&_[data-slot=toast-description]]:tw-col-end-3",
1691
+ "tw-gap-y-0",
1692
+ // styles
1693
+ "tw-p-4",
1694
+ "tw-rounded-lg",
1695
+ "tw-shadow-md"
1696
+ ],
1697
+ {
1698
+ defaultVariants: {
1699
+ variant: "info"
1700
+ },
1701
+ variants: {
1702
+ variant: {
1703
+ default: "tw-border tw-border-border tw-bg-popover",
1704
+ error: "tw-bg-error-550",
1705
+ info: "tw-bg-secondary-600",
1706
+ success: "tw-bg-primary-700",
1707
+ warning: "tw-bg-warning-550"
1708
+ }
1709
+ }
1710
+ }
1711
+ );
1712
+ var DEFAULT_VARIANT_ICON = {
1713
+ error: "exclamation-triangle",
1714
+ info: "info-circle",
1715
+ success: "check-circle",
1716
+ warning: "exclamation-circle"
1717
+ };
1718
+ var ToastRoot = ({
1719
+ id,
1720
+ title,
1721
+ description,
1722
+ action,
1723
+ duration = Infinity,
1724
+ variant = "info",
1725
+ loading = false,
1726
+ icon: iconProp
1727
+ }) => {
1728
+ const icon = (() => {
1729
+ if (loading) return "spinner";
1730
+ if (iconProp) return iconProp;
1731
+ if (variant === "default" || variant === null) return null;
1732
+ return DEFAULT_VARIANT_ICON[variant];
1733
+ })();
1734
+ const handleActionClick = (event) => {
1735
+ toast$1.dismiss(id);
1736
+ action?.onClick(event);
1737
+ };
1738
+ return /* @__PURE__ */ jsxs("div", { "data-variant": variant, className: cn(variants2({ variant })), children: [
1739
+ icon && /* @__PURE__ */ jsx(
1740
+ Icon,
1741
+ {
1742
+ "data-slot": "toast-icon",
1743
+ spin: loading,
1744
+ className: cn(
1745
+ // styles
1746
+ "tw-aspect-square",
1747
+ "tw-size-4",
1748
+ "tw-shrink-0",
1749
+ "tw-p-1",
1750
+ "tw-text-white",
1751
+ "group-data-[variant=default]/toast:tw-text-popover-foreground"
1752
+ ),
1753
+ icon
1754
+ }
1755
+ ),
1756
+ /* @__PURE__ */ jsx(ToastTitle, { children: title }),
1757
+ description && /* @__PURE__ */ jsx(ToastDescription, { children: description }),
1758
+ action && /* @__PURE__ */ jsx(ToastAction, { style: action?.actionButtonStyle, onClick: handleActionClick, children: action.label }),
1759
+ /* @__PURE__ */ jsx(ToastDismiss, { onClick: () => toast$1.dismiss(id) }),
1760
+ duration !== Infinity && /* @__PURE__ */ jsx(ToastDuration, { duration })
1761
+ ] });
1762
+ };
1763
+ var toast = ({
1764
+ onAutoClose,
1765
+ onDismiss,
1766
+ testId,
1767
+ toasterId,
1768
+ dismissible = true,
1769
+ position,
1770
+ title: titleProp,
1771
+ ...toast2
1772
+ }) => {
1773
+ const duration = (() => {
1774
+ if (typeof toast2.duration === "number") return toast2.duration;
1775
+ if (toast2.variant === "error" || toast2.variant === "warning") return Infinity;
1776
+ return toast2.duration ?? 5e3;
1777
+ })();
1778
+ const renderCustomToast = (id) => {
1779
+ const title = typeof titleProp === "function" ? titleProp({ dismiss: () => toast$1.dismiss(id) }) : titleProp;
1780
+ return /* @__PURE__ */ jsx(ToastRoot, { ...toast2, id, title, duration });
1781
+ };
1782
+ return toast$1.custom(renderCustomToast, {
1783
+ // toast generated by sonner will always have an id, but we want to allow users to specify their own id if they want to
1784
+ // can not pass undefined, as it will break dismiss
1785
+ ...toast2.id != null ? { id: toast2.id } : {},
1786
+ unstyled: true,
1787
+ position,
1788
+ onAutoClose,
1789
+ onDismiss,
1790
+ testId,
1791
+ toasterId,
1792
+ dismissible,
1793
+ duration,
1794
+ // override defult focus-visible styles to match our design
1795
+ className: cn("tw-rounded-lg", "focus-visible:!tw-ring-4", "focus-visible:!tw-ring-primary/50")
1796
+ });
1797
+ };
1798
+ toast.success = (title, options) => toast({
1799
+ ...options,
1800
+ title,
1801
+ variant: "success"
1802
+ });
1803
+ toast.error = (title, options) => toast({
1804
+ ...options,
1805
+ title,
1806
+ variant: "error",
1807
+ duration: options?.duration ?? Infinity
1808
+ });
1809
+ toast.warning = (title, options) => toast({
1810
+ ...options,
1811
+ title,
1812
+ variant: "warning",
1813
+ duration: options?.duration ?? Infinity
1814
+ });
1815
+ toast.info = (title, options) => toast({
1816
+ ...options,
1817
+ title,
1818
+ variant: "info"
1819
+ });
1820
+ toast.dismiss = (toastId) => toast$1.dismiss(toastId);
1821
+ toast.dismissAll = () => toast$1.dismiss();
1822
+
1823
+ // src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx
1824
+ var ACCEPTED_IMAGE_TYPES = [
1825
+ "image/png",
1826
+ "image/jpeg",
1827
+ "image/gif",
1828
+ "image/webp",
1829
+ "image/svg+xml"
1830
+ ];
1831
+ var MAX_IMAGE_SIZE = 10 * 1024 * 1024;
1832
+ var PLACEHOLDER_PREFIX = "upload-placeholder-";
1833
+ var generatePlaceholderId = () => {
1834
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
1835
+ return crypto.randomUUID();
1836
+ }
1837
+ return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
1838
+ };
1839
+ var isAcceptedImageType = (type) => ACCEPTED_IMAGE_TYPES.includes(type);
1840
+ var getImageFilesFromDataTransfer = (dataTransfer) => {
1841
+ if (!dataTransfer) return [];
1842
+ if (dataTransfer.items.length > 0) {
1843
+ const files = [];
1844
+ for (const item of dataTransfer.items) {
1845
+ if (item.kind === "file" && isAcceptedImageType(item.type)) {
1846
+ const file = item.getAsFile();
1847
+ if (file) files.push(file);
1848
+ }
1849
+ }
1850
+ if (files.length > 0) return files;
1851
+ }
1852
+ return Array.from(dataTransfer.files).filter((file) => isAcceptedImageType(file.type));
1853
+ };
1854
+ var escapeMarkdownAlt = (text) => text.replace(/[[\]()]/g, "");
1855
+ var ImagePastePlugin = ({ onImageUpload }) => {
1856
+ const [editor] = useLexicalComposerContext();
1857
+ const onImageUploadRef = useRef(onImageUpload);
1858
+ onImageUploadRef.current = onImageUpload;
1859
+ useEffect(() => {
1860
+ const uploadFile = (file) => {
1861
+ const upload = onImageUploadRef.current;
1862
+ if (!upload) return;
1863
+ if (file.size > MAX_IMAGE_SIZE) {
1864
+ toast.error(`Image "${file.name}" is too large. Maximum size is 10 MB.`);
1865
+ return;
1866
+ }
1867
+ let nodeKey = null;
1868
+ editor.update(() => {
1869
+ const placeholderNode = $createImageNode(
1870
+ `${PLACEHOLDER_PREFIX}${generatePlaceholderId()}`,
1871
+ "Uploading image\u2026"
1872
+ );
1873
+ $insertNodes([placeholderNode]);
1874
+ nodeKey = placeholderNode.getKey();
1875
+ });
1876
+ if (!nodeKey) return;
1877
+ const capturedKey = nodeKey;
1878
+ upload(file).then(({ url }) => {
1879
+ editor.update(() => {
1880
+ const node = $getNodeByKey(capturedKey);
1881
+ if ($isImageNode(node)) {
1882
+ const altText = escapeMarkdownAlt(file.name.replace(/\.[^.]+$/, "") || "image");
1883
+ node.setSrc(url);
1884
+ node.setAlt(altText);
1885
+ }
1886
+ });
1887
+ }).catch((error) => {
1888
+ console.error("[MarkdownEditor] image upload failed", error);
1889
+ toast.error(`Failed to upload "${file.name}". Please try again.`);
1890
+ editor.update(() => {
1891
+ const node = $getNodeByKey(capturedKey);
1892
+ if (node) node.remove();
1893
+ });
1894
+ });
1895
+ };
1896
+ const removePaste = editor.registerCommand(
1897
+ PASTE_COMMAND,
1898
+ (event) => {
1899
+ if (!onImageUploadRef.current) return false;
1900
+ if (!(event instanceof ClipboardEvent)) return false;
1901
+ const files = getImageFilesFromDataTransfer(event.clipboardData);
1902
+ if (files.length === 0) return false;
1903
+ event.preventDefault();
1904
+ Promise.resolve().then(() => files.forEach(uploadFile));
1905
+ return true;
1906
+ },
1907
+ COMMAND_PRIORITY_CRITICAL
1908
+ );
1909
+ const removeDrop = editor.registerCommand(
1910
+ DROP_COMMAND,
1911
+ (event) => {
1912
+ if (!onImageUploadRef.current) return false;
1913
+ const files = getImageFilesFromDataTransfer(event.dataTransfer);
1914
+ if (files.length === 0) return false;
1915
+ event.preventDefault();
1916
+ Promise.resolve().then(() => files.forEach(uploadFile));
1917
+ return true;
1918
+ },
1919
+ COMMAND_PRIORITY_CRITICAL
1920
+ );
1921
+ return () => {
1922
+ removePaste();
1923
+ removeDrop();
1924
+ };
1925
+ }, [editor]);
1926
+ return null;
1927
+ };
1928
+ var KeyboardPlugin = ({ onSave, onCancel }) => {
1929
+ const [editor] = useLexicalComposerContext();
1930
+ const onSaveRef = useRef(onSave);
1931
+ onSaveRef.current = onSave;
1932
+ const onCancelRef = useRef(onCancel);
1933
+ onCancelRef.current = onCancel;
1934
+ useEffect(() => {
1935
+ return editor.registerCommand(
1936
+ KEY_DOWN_COMMAND,
1937
+ (event) => {
1938
+ if (event.key === "Enter" && (event.ctrlKey || event.metaKey)) {
1939
+ event.preventDefault();
1940
+ onSaveRef.current?.();
1941
+ return true;
1942
+ }
1943
+ if (event.key === "Escape") {
1944
+ onCancelRef.current?.();
1945
+ return true;
1946
+ }
1947
+ return false;
1948
+ },
1949
+ COMMAND_PRIORITY_HIGH
1950
+ );
1951
+ }, [editor]);
1952
+ return null;
1953
+ };
1954
+ var IMAGE = {
1955
+ dependencies: [ImageNode],
1956
+ export: (node) => {
1957
+ if (!$isImageNode(node)) return null;
1958
+ return `![${node.getAlt()}](${node.getSrc()})`;
1959
+ },
1960
+ importRegExp: /!\[([^\]]*)\]\(([^)]+)\)/,
1961
+ regExp: /!\[([^\]]*)\]\(([^)]+)\)$/,
1962
+ replace: (textNode, match) => {
1963
+ const [, alt = "", src = ""] = match;
1964
+ const imageNode = $createImageNode(src, alt);
1965
+ textNode.replace(imageNode);
1966
+ },
1967
+ trigger: ")",
1968
+ type: "text-match"
1969
+ };
1970
+ var HORIZONTAL_RULE = {
1971
+ dependencies: [HorizontalRuleNode],
1972
+ export: (node) => {
1973
+ return $isHorizontalRuleNode(node) ? "---" : null;
1974
+ },
1975
+ regExp: /^(---|\*\*\*|___)$/,
1976
+ replace: (parentNode) => {
1977
+ const node = $createHorizontalRuleNode();
1978
+ parentNode.replace(node);
1979
+ },
1980
+ type: "element"
1981
+ };
1982
+ var MERMAID = {
1983
+ dependencies: [MermaidNode],
1984
+ export: (node) => {
1985
+ if (!$isMermaidNode(node)) return null;
1986
+ return "```mermaid\n" + node.getCode() + "\n```";
1987
+ },
1988
+ regExpStart: /^[ \t]*(`{3,})mermaid(?:\s.*)?$/,
1989
+ regExpEnd: {
1990
+ optional: true,
1991
+ regExp: /^[ \t]*`{3,}$/
1992
+ },
1993
+ replace: (rootNode, _children, _startMatch, _endMatch, linesInBetween) => {
1994
+ if (!linesInBetween) return;
1995
+ const code = linesInBetween.join("\n").trim();
1996
+ if (code) {
1997
+ rootNode.append($createMermaidNode(code));
1998
+ }
1999
+ },
2000
+ handleImportAfterStartMatch: ({
2001
+ lines,
2002
+ rootNode,
2003
+ startLineIndex,
2004
+ startMatch
2005
+ }) => {
2006
+ const fence = startMatch[1];
2007
+ if (!fence) return [false, startLineIndex];
2008
+ const fenceLength = fence.trim().length;
2009
+ const endRegex = new RegExp(`^[ \\t]*\`{${fenceLength},}$`);
2010
+ for (let i = startLineIndex + 1; i < lines.length; i++) {
2011
+ if (endRegex.test(lines[i] ?? "")) {
2012
+ const code2 = lines.slice(startLineIndex + 1, i).join("\n").trim();
2013
+ if (code2) {
2014
+ rootNode.append($createMermaidNode(code2));
2015
+ }
2016
+ return [true, i];
2017
+ }
2018
+ }
2019
+ const code = lines.slice(startLineIndex + 1).join("\n").trim();
2020
+ if (code) {
2021
+ rootNode.append($createMermaidNode(code));
2022
+ }
2023
+ return [true, lines.length - 1];
2024
+ },
2025
+ type: "multiline-element"
2026
+ };
2027
+ var CUSTOM_TRANSFORMERS = [
2028
+ IMAGE,
2029
+ HORIZONTAL_RULE,
2030
+ CHECK_LIST,
2031
+ MERMAID,
2032
+ ...TRANSFORMERS
2033
+ ];
2034
+ var TABLE_FENCE_LANG = "__kbc_table__";
2035
+ var isTableLine = (line) => {
2036
+ const trimmed = line.trim();
2037
+ return trimmed.startsWith("|") && trimmed.endsWith("|");
2038
+ };
2039
+ var CODE_FENCE_REGEX = /^[ \t]*`{3,}/;
2040
+ var preprocessMarkdown = (markdown) => {
2041
+ const lines = markdown.split("\n");
2042
+ const result = [];
2043
+ let tableLines = [];
2044
+ let insideCodeFence = false;
2045
+ const flushTable = () => {
2046
+ if (tableLines.length >= 2) {
2047
+ result.push(`\`\`\`${TABLE_FENCE_LANG}`);
2048
+ result.push(...tableLines);
2049
+ result.push("```");
2050
+ } else {
2051
+ result.push(...tableLines);
2052
+ }
2053
+ tableLines = [];
2054
+ };
2055
+ for (const line of lines) {
2056
+ if (CODE_FENCE_REGEX.test(line)) {
2057
+ if (tableLines.length > 0) flushTable();
2058
+ insideCodeFence = !insideCodeFence;
2059
+ result.push(line);
2060
+ continue;
2061
+ }
2062
+ if (insideCodeFence) {
2063
+ result.push(line);
2064
+ continue;
2065
+ }
2066
+ if (isTableLine(line)) {
2067
+ tableLines.push(line);
2068
+ } else {
2069
+ if (tableLines.length > 0) flushTable();
2070
+ result.push(line);
2071
+ }
2072
+ }
2073
+ if (tableLines.length > 0) flushTable();
2074
+ return result.join("\n");
2075
+ };
2076
+ var postprocessMarkdown = (markdown) => {
2077
+ const regex = new RegExp(`\`\`\`${TABLE_FENCE_LANG}\\n([\\s\\S]*?)\\n\`\`\``, "g");
2078
+ return markdown.replace(regex, "$1");
2079
+ };
2080
+
2081
+ // src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2082
+ var IMPORT_TAG = "markdown-import";
2083
+ var MarkdownSyncPlugin = ({ value, editable, onChange }) => {
2084
+ const [editor] = useLexicalComposerContext();
2085
+ const lastExportedRef = useRef(value);
2086
+ const onChangeRef = useRef(onChange);
2087
+ onChangeRef.current = onChange;
2088
+ useEffect(() => {
2089
+ editor.setEditable(editable);
2090
+ }, [editor, editable]);
2091
+ useEffect(() => {
2092
+ if (value === lastExportedRef.current) return;
2093
+ lastExportedRef.current = value;
2094
+ editor.update(
2095
+ () => {
2096
+ $convertFromMarkdownString(preprocessMarkdown(value), CUSTOM_TRANSFORMERS);
2097
+ },
2098
+ { tag: IMPORT_TAG }
2099
+ );
2100
+ }, [editor, value]);
2101
+ useEffect(() => {
2102
+ return editor.registerUpdateListener(({ tags }) => {
2103
+ if (tags.has(IMPORT_TAG)) return;
2104
+ editor.getEditorState().read(() => {
2105
+ const raw = $convertToMarkdownString(CUSTOM_TRANSFORMERS);
2106
+ const markdown = postprocessMarkdown(raw);
2107
+ if (markdown !== lastExportedRef.current) {
2108
+ lastExportedRef.current = markdown;
2109
+ onChangeRef.current?.(markdown);
2110
+ }
2111
+ });
2112
+ });
2113
+ }, [editor]);
2114
+ return null;
2115
+ };
2116
+
2117
+ // src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx
2118
+ init_Icon2();
2119
+
2120
+ // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2121
+ init_utils();
2122
+
2123
+ // src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx
2124
+ init_utils();
2125
+
2126
+ // src/components/DropdownMenu/DropdownMenuItemIndicator.tsx
2127
+ init_Icon2();
2128
+ var variants3 = cva(
2129
+ [
2130
+ "tailwindcss-preflight",
2131
+ "tw-pointer-events-none",
2132
+ // sizing
2133
+ "tw-size-4",
2134
+ "tw-aspect-square",
2135
+ "tw-shrink-0",
2136
+ // layout
2137
+ "tw-flex",
2138
+ "tw-items-center",
2139
+ "tw-justify-center"
2140
+ ],
2141
+ {
2142
+ variants: {
2143
+ variant: {
2144
+ none: [],
2145
+ radio: [
2146
+ "tw-border",
2147
+ "tw-border-solid",
2148
+ "tw-border-border",
2149
+ "tw-rounded-full",
2150
+ "tw-bg-white",
2151
+ "[&_svg]:tw-size-2",
2152
+ "[&_svg]:data-[state=unchecked]:tw-hidden",
2153
+ "group-data-[variant=argo]/dropdown-menu-content:[&_svg]:tw-text-primary",
2154
+ "group-data-[variant=default]/dropdown-menu-content:[&_svg]:tw-text-secondary-500"
2155
+ ],
2156
+ check: ["[&_svg]:tw-size-3.5", "[&_svg]:tw-text-primary"],
2157
+ checkbox: [
2158
+ "[&_svg]:tw-text-white",
2159
+ "tw-border",
2160
+ "tw-border-solid",
2161
+ "tw-border-neutral-200",
2162
+ "tw-rounded",
2163
+ "[&_svg]:tw-size-3",
2164
+ "[&_svg]:data-[state=unchecked]:tw-hidden",
2165
+ "group-data-[variant=argo]/dropdown-menu-content:data-[state=checked]:tw-border-primary",
2166
+ "group-data-[variant=argo]/dropdown-menu-content:data-[state=checked]:tw-bg-primary",
2167
+ "group-data-[variant=default]/dropdown-menu-content:data-[state=checked]:tw-border-secondary-500",
2168
+ "group-data-[variant=default]/dropdown-menu-content:data-[state=checked]:tw-bg-secondary-500"
2169
+ ],
2170
+ switch: [
2171
+ "tw-size-5",
2172
+ "tw-text-neutral-400",
2173
+ "data-[state=unchecked]:tw-rotate-180",
2174
+ "group-data-[variant=default]/dropdown-menu-content:data-[state=checked]:tw-text-secondary-500",
2175
+ "group-data-[variant=argo]/dropdown-menu-content:data-[state=checked]:tw-text-primary"
2176
+ ]
2177
+ }
2178
+ }
2179
+ }
2180
+ );
2181
+ var DropdownMenuItemIndicator = ({
2182
+ variant,
2183
+ className,
2184
+ forceMount: forceMountProp,
2185
+ ...rest
2186
+ }) => {
2187
+ const icon = (() => {
2188
+ if (variant === "switch") return "toggle-large-on";
2189
+ if (variant === "radio") return "circle";
2190
+ return "check";
2191
+ })();
2192
+ const forceMount = (() => {
2193
+ if (forceMountProp) return true;
2194
+ return variant === "check" ? void 0 : true;
2195
+ })();
2196
+ if (variant === "none") return null;
2197
+ return /* @__PURE__ */ jsx(
2198
+ DropdownMenuPrimitive3.ItemIndicator,
2199
+ {
2200
+ ...rest,
2201
+ forceMount,
2202
+ className: variants3({ variant, className }),
2203
+ children: /* @__PURE__ */ jsx(Icon, { icon })
2204
+ }
2205
+ );
2206
+ };
2207
+
2208
+ // src/components/DropdownMenu/ItemIcon.tsx
2209
+ init_utils();
2210
+ init_Icon2();
2211
+ var ItemIcon = ({ className, ...props }) => /* @__PURE__ */ jsx(
2212
+ Icon,
2213
+ {
2214
+ ...props,
2215
+ className: cn(
2216
+ "tw-aspect-square",
2217
+ "tw-p-0.5",
2218
+ "tw-size-4",
2219
+ "group-data-[variant=default]/dropdown-menu-content:tw-text-neutral-400",
2220
+ "group-data-[variant=argo]/dropdown-menu-content:tw-text-primary",
2221
+ "group-data-[variant=argo]/dropdown-menu-content:group-aria-disabled:tw-text-muted-foreground",
2222
+ "group-data-[variant=default]/dropdown-menu-content:group-hover:tw-text-secondary-500",
2223
+ className
2224
+ )
2225
+ }
2226
+ );
2227
+
2228
+ // src/components/DropdownMenu/styles.ts
2229
+ init_utils();
2230
+ var itemVariants = cn(
2231
+ // reset
2232
+ "tailwindcss-preflight",
2233
+ "tw-outline-none",
2234
+ "tw-group",
2235
+ "tw-peer",
2236
+ "tw-relative",
2237
+ // positioning
2238
+ "tw-flex",
2239
+ "tw-flex-1",
2240
+ "tw-items-center",
2241
+ "tw-gap-2",
2242
+ "tw-cursor-pointer",
2243
+ "tw-select-none",
2244
+ "tw-transition-colors",
2245
+ // spacing
2246
+ "tw-p-2",
2247
+ // typography
2248
+ "tw-font-sans",
2249
+ "tw-text-sm",
2250
+ "aria-disabled:tw-pointer-events-none",
2251
+ "aria-disabled:tw-opacity-50",
2252
+ "focus-visible:tw-outline-none",
2253
+ "group-data-[variant=default]/dropdown-menu-content:tw-rounded",
2254
+ "group-data-[variant=default]/dropdown-menu-content:focus:tw-bg-neutral-100",
2255
+ "group-data-[variant=default]/dropdown-menu-content:focus:tw-text-neutral-900",
2256
+ "group-data-[variant=default]/dropdown-menu-content:hover:tw-bg-neutral-100",
2257
+ "group-data-[variant=default]/dropdown-menu-content:hover:tw-text-neutral-900",
2258
+ "group-data-[variant=argo]/dropdown-menu-content:tw-rounded-md",
2259
+ "group-data-[variant=argo]/dropdown-menu-content:tw-text-slate-800",
2260
+ "group-data-[variant=argo]/dropdown-menu-content:focus:tw-text-slate-800",
2261
+ "group-data-[variant=argo]/dropdown-menu-content:focus:tw-bg-sky-100",
2262
+ "group-data-[variant=argo]/dropdown-menu-content:hover:tw-text-slate-800",
2263
+ "group-data-[variant=argo]/dropdown-menu-content:hover:tw-bg-sky-100"
2264
+ );
2265
+ var contentVariants = cn(
2266
+ "tailwindcss-preflight",
2267
+ "tw-group/dropdown-menu-content",
2268
+ "tw-z-[1040]",
2269
+ "tw-bg-white",
2270
+ // positioning
2271
+ "tw-flex",
2272
+ "tw-flex-col",
2273
+ "tw-origin-[--radix-dropdown-menu-content-transform-origin]",
2274
+ // sizing
2275
+ "tw-max-h-[var(--radix-dropdown-menu-content-available-height)]",
2276
+ "tw-min-w-32",
2277
+ // border
2278
+ "tw-border",
2279
+ "tw-shadow-md",
2280
+ "data-[variant=default]:tw-rounded-md",
2281
+ "data-[variant=argo]:tw-rounded-2xl",
2282
+ // animations
2283
+ "data-[state=open]:tw-animate-in",
2284
+ "data-[state=open]:tw-fade-in-0",
2285
+ "data-[state=open]:tw-zoom-in-95",
2286
+ "data-[state=closed]:tw-animate-out",
2287
+ "data-[state=closed]:tw-fade-out-0",
2288
+ "data-[state=closed]:tw-zoom-out-95",
2289
+ "data-[side=bottom]:tw-slide-in-from-top-2",
2290
+ "data-[side=left]:tw-slide-in-from-right-2",
2291
+ "data-[side=right]:tw-slide-in-from-left-2",
2292
+ "data-[side=top]:tw-slide-in-from-bottom-2"
2293
+ );
2294
+ var DropdownMenuCheckboxItem = ({
2295
+ className,
2296
+ children,
2297
+ checked,
2298
+ closeOnSelect = false,
2299
+ onSelect,
2300
+ indicatorAlign = "start",
2301
+ indicator = "checkbox",
2302
+ isLoading = false,
2303
+ ...props
2304
+ }) => {
2305
+ const isAtStart = indicatorAlign === "start";
2306
+ const indicatorEle = isLoading ? /* @__PURE__ */ jsx(ItemIcon, { spin: true, icon: "spinner", className: isAtStart ? "" : "tw-ml-auto" }) : /* @__PURE__ */ jsx(DropdownMenuItemIndicator, { variant: indicator, className: isAtStart ? "" : "tw-ml-auto" });
2307
+ const handleSelect = (event) => {
2308
+ if (!closeOnSelect) event.preventDefault();
2309
+ onSelect?.(event);
2310
+ };
2311
+ return /* @__PURE__ */ jsxs(
2312
+ DropdownMenuPrimitive3.CheckboxItem,
2313
+ {
2314
+ className: cn(itemVariants, className),
2315
+ checked,
2316
+ onSelect: handleSelect,
2317
+ ...props,
2318
+ children: [
2319
+ isAtStart && indicatorEle,
2320
+ children,
2321
+ !isAtStart && indicatorEle
2322
+ ]
2323
+ }
2324
+ );
2325
+ };
2326
+
2327
+ // src/components/DropdownMenu/DropdownMenuContent.tsx
2328
+ init_utils();
2329
+
2330
+ // src/components/ScrollArea/ScrollArea.tsx
2331
+ init_utils();
2332
+
2333
+ // src/components/ScrollArea/ScrollBar.tsx
2334
+ init_utils();
2335
+ var ScrollBar = ({ className, orientation = "vertical", ...props }) => /* @__PURE__ */ jsx(
2336
+ ScrollAreaPrimitive2.ScrollAreaScrollbar,
2337
+ {
2338
+ orientation,
2339
+ className: cn(
2340
+ "tw-flex tw-touch-none tw-select-none tw-transition-color",
2341
+ '[data-state="hidden"]:tw-bg-pink-500',
2342
+ {
2343
+ "tw-h-full tw-w-2.5 tw-p-px": orientation === "vertical",
2344
+ "tw-h-2.5 tw-flex-col tw-p-px": orientation === "horizontal"
2345
+ },
2346
+ className
2347
+ ),
2348
+ ...props,
2349
+ children: /* @__PURE__ */ jsx(
2350
+ ScrollAreaPrimitive2.ScrollAreaThumb,
2351
+ {
2352
+ className: cn(
2353
+ "tw-relative",
2354
+ "tw-flex-1",
2355
+ "tw-rounded-full",
2356
+ "tw-bg-neutral-200",
2357
+ "hover:tw-bg-neutral-400"
2358
+ )
2359
+ }
2360
+ )
2361
+ }
2362
+ );
2363
+ var ScrollArea = ({
2364
+ ref,
2365
+ className,
2366
+ children,
2367
+ viewPortClassName,
2368
+ orientation,
2369
+ scrollBarClassName,
2370
+ ...props
2371
+ }) => /* @__PURE__ */ jsxs(
2372
+ ScrollAreaPrimitive2.Root,
2373
+ {
2374
+ "data-slot": "scroll-area",
2375
+ className: cn(
2376
+ "tw-peer/scroll-area tw-relative tw-overflow-hidden focus-visible:tw-outline-none",
2377
+ className
2378
+ ),
2379
+ ...props,
2380
+ children: [
2381
+ /* @__PURE__ */ jsx(
2382
+ ScrollAreaPrimitive2.Viewport,
2383
+ {
2384
+ ref,
2385
+ className: cn(
2386
+ "tw-h-full tw-w-full tw-rounded-[inherit] focus-visible:tw-outline-none",
2387
+ viewPortClassName
2388
+ ),
2389
+ children
2390
+ }
2391
+ ),
2392
+ orientation ? /* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2393
+ /* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation: "vertical" }),
2394
+ /* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation: "horizontal" })
2395
+ ] }),
2396
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive2.Corner, {})
2397
+ ]
2398
+ }
2399
+ );
2400
+ var DropdownMenuContext = createContext({
2401
+ variant: "default"
2402
+ });
2403
+ var useDropdownMenuContext = () => use(DropdownMenuContext);
2404
+ var DropdownMenuContent = ({
2405
+ className,
2406
+ sideOffset = 4,
2407
+ forceMount,
2408
+ children,
2409
+ viewPortClassName,
2410
+ container,
2411
+ ...props
2412
+ }) => {
2413
+ const { variant } = useDropdownMenuContext();
2414
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive3.Portal, { forceMount: forceMount || void 0, container, children: /* @__PURE__ */ jsx(
2415
+ DropdownMenuPrimitive3.Content,
2416
+ {
2417
+ ...props,
2418
+ "data-variant": variant,
2419
+ sideOffset,
2420
+ className: contentVariants,
2421
+ children: /* @__PURE__ */ jsx(
2422
+ ScrollArea,
2423
+ {
2424
+ className,
2425
+ viewPortClassName: cn(
2426
+ "tw-p-2",
2427
+ "tw-max-h-[var(--radix-dropdown-menu-content-available-height)]",
2428
+ viewPortClassName
2429
+ ),
2430
+ scrollBarClassName: "tw-w-1.5",
2431
+ children
2432
+ }
2433
+ )
2434
+ }
2435
+ ) });
2436
+ };
2437
+
2438
+ // src/components/DropdownMenu/DropdownMenuItem.tsx
2439
+ init_utils();
2440
+ var DropdownMenuItem = ({
2441
+ ref,
2442
+ className,
2443
+ asModalTrigger = false,
2444
+ onSelect,
2445
+ onPointerLeave,
2446
+ onPointerMove,
2447
+ children,
2448
+ asChild,
2449
+ icon: iconProp,
2450
+ iconClassName,
2451
+ isLoading = false,
2452
+ ...props
2453
+ }) => {
2454
+ const Comp = asChild ? Root$2 : "div";
2455
+ const icon = isLoading ? "spinner" : iconProp;
2456
+ const handleOnSelect = (event) => {
2457
+ if (asModalTrigger) event.preventDefault();
2458
+ onSelect?.(event);
2459
+ };
2460
+ const handlePointerLeave = (event) => {
2461
+ if (asModalTrigger) event.preventDefault();
2462
+ onPointerLeave?.(event);
2463
+ };
2464
+ const handlePointerMove = (event) => {
2465
+ if (asModalTrigger) event.preventDefault();
2466
+ onPointerMove?.(event);
2467
+ };
2468
+ return /* @__PURE__ */ jsx(
2469
+ DropdownMenuPrimitive3.Item,
2470
+ {
2471
+ ...props,
2472
+ ref,
2473
+ onSelect: handleOnSelect,
2474
+ onPointerLeave: handlePointerLeave,
2475
+ onPointerMove: handlePointerMove,
2476
+ className: cn(itemVariants, className),
2477
+ asChild: true,
2478
+ children: /* @__PURE__ */ jsxs(Comp, { children: [
2479
+ icon && /* @__PURE__ */ jsx(ItemIcon, { spin: isLoading, icon, className: iconClassName }),
2480
+ /* @__PURE__ */ jsx(Slottable, { children })
2481
+ ] })
2482
+ }
2483
+ );
2484
+ };
2485
+
2486
+ // src/components/DropdownMenu/DropdownMenuItemDescription.tsx
2487
+ init_utils();
2488
+ var descriptionVariants = cva(
2489
+ [
2490
+ "tw-box-border",
2491
+ "tw-ml-auto",
2492
+ "tw-font-sans",
2493
+ "tw-tracking-normal",
2494
+ "tw-font-normal",
2495
+ "tw-text-xs",
2496
+ "tw-text-muted-foreground"
2497
+ ],
2498
+ {
2499
+ variants: {
2500
+ hideOnHover: {
2501
+ true: ["group-focus-within:tw-hidden", "group-hover:tw-hidden"],
2502
+ false: []
2503
+ }
2504
+ },
2505
+ defaultVariants: {}
2506
+ }
2507
+ );
2508
+ var DropdownMenuItemDescription = ({
2509
+ className,
2510
+ children,
2511
+ hideOnHover = false,
2512
+ ...props
2513
+ }) => {
2514
+ return /* @__PURE__ */ jsx("span", { ...props, className: cn(descriptionVariants({ hideOnHover }), className), children });
2515
+ };
2516
+
2517
+ // src/components/DropdownMenu/DropdownMenuLabel.tsx
2518
+ init_utils();
2519
+ var DropdownMenuLabel = ({ className, ...props }) => {
2520
+ return /* @__PURE__ */ jsx(
2521
+ DropdownMenuPrimitive3.Label,
2522
+ {
2523
+ className: cn(
2524
+ "tw-p-2",
2525
+ "tw-font-medium",
2526
+ "tw-text-xs",
2527
+ "tw-text-muted-foreground",
2528
+ className
2529
+ ),
2530
+ ...props
2531
+ }
2532
+ );
2533
+ };
2534
+ var DropdownMenuRadioGroup = ({
2535
+ value,
2536
+ defaultValue,
2537
+ onValueChange,
2538
+ ...props
2539
+ }) => {
2540
+ const handleChange = (value2) => {
2541
+ onValueChange?.(value2);
2542
+ };
2543
+ return /* @__PURE__ */ jsx(
2544
+ DropdownMenuPrimitive3.RadioGroup,
2545
+ {
2546
+ ...props,
2547
+ value,
2548
+ defaultValue,
2549
+ onValueChange: handleChange
2550
+ }
2551
+ );
2552
+ };
2553
+
2554
+ // src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioItem.tsx
2555
+ init_utils();
2556
+ var DropdownMenuRadioItem = ({
2557
+ className,
2558
+ children,
2559
+ closeOnSelect,
2560
+ onSelect,
2561
+ indicatorAlign = "start",
2562
+ indicator = "radio",
2563
+ icon,
2564
+ iconClassName,
2565
+ isLoading = false,
2566
+ ...props
2567
+ }) => {
2568
+ const isAtStart = indicatorAlign === "start";
2569
+ const indicatorEle = isLoading ? /* @__PURE__ */ jsx(ItemIcon, { spin: true, icon: "spinner", className: iconClassName }) : /* @__PURE__ */ jsx(DropdownMenuItemIndicator, { variant: indicator });
2570
+ const handleSelect = (event) => {
2571
+ if (!closeOnSelect) event.preventDefault();
2572
+ onSelect?.(event);
2573
+ };
2574
+ return /* @__PURE__ */ jsxs(
2575
+ DropdownMenuPrimitive3.RadioItem,
2576
+ {
2577
+ className: cn(
2578
+ itemVariants,
2579
+ "data-[state=checked]:tw-cursor-default",
2580
+ {
2581
+ "data-[state=checked]:tw-bg-neutral-100": indicator === "none",
2582
+ "group-data-[variant=argo]/dropdown-menu-content:data-[state=checked]:tw-bg-sky-100": indicator === "check"
2583
+ },
2584
+ className
2585
+ ),
2586
+ onSelect: handleSelect,
2587
+ ...props,
2588
+ children: [
2589
+ isAtStart && indicatorEle,
2590
+ icon && /* @__PURE__ */ jsx(ItemIcon, { icon, className: iconClassName }),
2591
+ /* @__PURE__ */ jsx("span", { className: "tw-flex tw-min-w-0 tw-flex-1 tw-items-center tw-gap-2", children }),
2592
+ !isAtStart && indicatorEle
2593
+ ]
2594
+ }
2595
+ );
2596
+ };
2597
+
2598
+ // src/components/DropdownMenu/DropdownMenuSeparator.tsx
2599
+ init_utils();
2600
+ var DropdownMenuSeparator = ({ className, ...props }) => /* @__PURE__ */ jsx(
2601
+ DropdownMenuPrimitive3.Separator,
2602
+ {
2603
+ className: cn(
2604
+ "tw-relative",
2605
+ "tw-z-10",
2606
+ // layout
2607
+ "tw-flex",
2608
+ "tw-items-center",
2609
+ "tw-justify-center",
2610
+ "tw-w-full",
2611
+ // separator line
2612
+ 'before:tw-content-[""]',
2613
+ "before:tw-w-full",
2614
+ "before:tw-h-px",
2615
+ "group-data-[variant=default]/dropdown-menu-content:tw-py-2",
2616
+ "group-data-[variant=default]/dropdown-menu-content:before:tw-bg-neutral-150",
2617
+ "group-data-[variant=argo]/dropdown-menu-content:tw-py-1",
2618
+ "group-data-[variant=argo]/dropdown-menu-content:before:tw-bg-border",
2619
+ className
2620
+ ),
2621
+ ...props
2622
+ }
2623
+ );
2624
+ var DropdownMenuSub = DropdownMenuPrimitive3.Sub;
2625
+
2626
+ // src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubContent.tsx
2627
+ init_utils();
2628
+ var DropdownMenuSubContent = ({ className, ...props }) => {
2629
+ const { variant } = useDropdownMenuContext();
2630
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive3.Portal, { children: /* @__PURE__ */ jsx(
2631
+ DropdownMenuPrimitive3.SubContent,
2632
+ {
2633
+ "data-variant": variant,
2634
+ className: cn(contentVariants, "tw-z-[1041]", "tw-p-2", className),
2635
+ ...props
2636
+ }
2637
+ ) });
2638
+ };
2639
+
2640
+ // src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubTrigger.tsx
2641
+ init_utils();
2642
+ init_Icon2();
2643
+ var DropdownMenuSubTrigger = ({ className, children, ...props }) => {
2644
+ return /* @__PURE__ */ jsxs(DropdownMenuPrimitive3.SubTrigger, { className: cn(itemVariants, className), ...props, children: [
2645
+ children,
2646
+ /* @__PURE__ */ jsx(Icon, { icon: "chevron-right", className: "tw-ml-auto" })
2647
+ ] });
2648
+ };
2649
+
2650
+ // src/components/DropdownMenu/DropdownMenuTrigger.tsx
2651
+ init_utils();
2652
+ var DropdownMenuTrigger = ({
2653
+ ref,
2654
+ className,
2655
+ ...props
2656
+ }) => /* @__PURE__ */ jsx(
2657
+ Trigger$1,
2658
+ {
2659
+ ...props,
2660
+ ref,
2661
+ "data-slot": "dropdown-menu-trigger",
2662
+ className: cn("tw-group/dropdown-menu-trigger", className)
2663
+ }
2664
+ );
2665
+ var DropdownMenu = ({
2666
+ // change a default value to false, for modal property, as it is not used in most cases
2667
+ modal = false,
2668
+ variant = "default",
2669
+ ...props
2670
+ }) => {
2671
+ const contextValue = useMemo(() => ({ variant }), [variant]);
2672
+ return /* @__PURE__ */ jsx(DropdownMenuContext, { value: contextValue, children: /* @__PURE__ */ jsx(Root$1, { ...props, modal }) });
2673
+ };
2674
+ DropdownMenu.Trigger = DropdownMenuTrigger;
2675
+ DropdownMenu.Content = DropdownMenuContent;
2676
+ DropdownMenu.Group = Group;
2677
+ DropdownMenu.Sub = DropdownMenuSub;
2678
+ DropdownMenu.SubContent = DropdownMenuSubContent;
2679
+ DropdownMenu.SubTrigger = DropdownMenuSubTrigger;
2680
+ DropdownMenu.Separator = DropdownMenuSeparator;
2681
+ DropdownMenu.Label = DropdownMenuLabel;
2682
+ DropdownMenu.Item = DropdownMenuItem;
2683
+ DropdownMenu.CheckboxItem = DropdownMenuCheckboxItem;
2684
+ DropdownMenu.RadioGroup = DropdownMenuRadioGroup;
2685
+ DropdownMenu.RadioItem = DropdownMenuRadioItem;
2686
+ DropdownMenu.ItemDescription = DropdownMenuItemDescription;
2687
+
2688
+ // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2689
+ init_Icon2();
2690
+ init_Tooltip2();
2691
+ var ALIGNMENT_OPTIONS = [
2692
+ { value: "left", label: "Left", icon: ["far", "align-left"] },
2693
+ { value: "center", label: "Center", icon: ["far", "align-center"] },
2694
+ { value: "right", label: "Right", icon: ["far", "align-right"] },
2695
+ { value: "justify", label: "Justify", icon: ["far", "align-justify"] }
2696
+ ];
2697
+ var ALIGNMENT_ICONS = Object.fromEntries(
2698
+ ALIGNMENT_OPTIONS.map(({ value, icon }) => [value, icon])
2699
+ );
2700
+ var AlignmentDropdown = ({
2701
+ editor,
2702
+ alignment
2703
+ }) => {
2704
+ const savedSelectionRef = useRef(null);
2705
+ const handleOpenChange = (open) => {
2706
+ if (open) {
2707
+ editor.getEditorState().read(() => {
2708
+ const selection = $getSelection();
2709
+ savedSelectionRef.current = selection ? selection.clone() : null;
2710
+ });
2711
+ }
2712
+ };
2713
+ const handleSelect = (align) => {
2714
+ editor.update(() => {
2715
+ if (savedSelectionRef.current) {
2716
+ $setSelection(savedSelectionRef.current);
2717
+ }
2718
+ editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, align);
2719
+ });
2720
+ };
2721
+ return /* @__PURE__ */ jsxs(DropdownMenu, { onOpenChange: handleOpenChange, children: [
2722
+ /* @__PURE__ */ jsx(Tooltip, { tooltip: "Text alignment", placement: "top", triggerAsChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2723
+ "button",
2724
+ {
2725
+ type: "button",
2726
+ className: cn(
2727
+ "tw-flex tw-h-7 tw-cursor-pointer tw-items-center tw-gap-1 tw-rounded tw-border-0 tw-bg-transparent tw-px-1.5 tw-text-xs tw-text-neutral-600",
2728
+ "hover:tw-bg-neutral-100"
2729
+ ),
2730
+ children: [
2731
+ /* @__PURE__ */ jsx(Icon, { icon: ALIGNMENT_ICONS[alignment] ?? ["far", "align-left"], fixedWidth: true }),
2732
+ /* @__PURE__ */ jsx(Icon, { icon: ["fas", "caret-down"], className: "tw-text-[8px]" })
2733
+ ]
2734
+ }
2735
+ ) }) }),
2736
+ /* @__PURE__ */ jsx(DropdownMenu.Content, { align: "start", className: "tw-min-w-32", children: ALIGNMENT_OPTIONS.map(({ value, label, icon }) => /* @__PURE__ */ jsxs(
2737
+ DropdownMenu.Item,
2738
+ {
2739
+ onSelect: () => handleSelect(value),
2740
+ className: cn(
2741
+ "tw-flex tw-items-center tw-gap-2",
2742
+ alignment === value && "tw-bg-secondary-50 tw-text-secondary-500"
2743
+ ),
2744
+ children: [
2745
+ /* @__PURE__ */ jsx(Icon, { icon, fixedWidth: true }),
2746
+ label
2747
+ ]
2748
+ },
2749
+ value
2750
+ )) })
2751
+ ] });
2752
+ };
2753
+
2754
+ // src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx
2755
+ init_utils();
2756
+ init_Icon2();
2757
+ init_Tooltip2();
2758
+ var BLOCK_TYPE_META = {
2759
+ paragraph: { label: "Normal", icon: ["far", "font"], selectable: true },
2760
+ h1: { label: "Heading 1", icon: ["far", "h1"], selectable: true },
2761
+ h2: { label: "Heading 2", icon: ["far", "h2"], selectable: true },
2762
+ h3: { label: "Heading 3", icon: ["far", "h3"], selectable: true },
2763
+ bullet: { label: "Bullet List", icon: ["far", "list-ul"], selectable: false },
2764
+ number: { label: "Numbered List", icon: ["far", "list-ol"], selectable: false },
2765
+ quote: { label: "Quote", icon: ["far", "block-quote"], selectable: false },
2766
+ code: { label: "Code Block", icon: "square-code", selectable: false }
2767
+ };
2768
+ var BLOCK_TYPE_OPTIONS = Object.entries(BLOCK_TYPE_META).filter(([, meta]) => meta.selectable).map(([value, { label, icon }]) => ({ value, label, icon }));
2769
+ var isBlockType = (value) => Object.prototype.hasOwnProperty.call(BLOCK_TYPE_META, value);
2770
+ var BlockTypeDropdown = ({
2771
+ editor,
2772
+ blockType
2773
+ }) => {
2774
+ const savedSelectionRef = useRef(null);
2775
+ const currentMeta = isBlockType(blockType) ? BLOCK_TYPE_META[blockType] : null;
2776
+ const handleOpenChange = (open) => {
2777
+ if (open) {
2778
+ editor.getEditorState().read(() => {
2779
+ const selection = $getSelection();
2780
+ savedSelectionRef.current = selection ? selection.clone() : null;
2781
+ });
2782
+ }
2783
+ };
2784
+ const handleSelect = (type) => {
2785
+ editor.update(() => {
2786
+ if (savedSelectionRef.current) {
2787
+ $setSelection(savedSelectionRef.current);
2788
+ }
2789
+ const selection = $getSelection();
2790
+ if (!$isRangeSelection(selection)) return;
2791
+ if (type === "bullet") {
2792
+ editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0);
2793
+ return;
2794
+ }
2795
+ if (type === "number") {
2796
+ editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0);
2797
+ return;
2798
+ }
2799
+ const anchorNode = selection.anchor.getNode();
2800
+ const element = $getNearestBlockElementAncestorOrThrow(anchorNode);
2801
+ const newNode = type === "h1" || type === "h2" || type === "h3" ? $createHeadingNode(type) : type === "quote" ? $createQuoteNode() : type === "code" ? $createCodeNode() : $createParagraphNode();
2802
+ element.getChildren().forEach((child) => newNode.append(child));
2803
+ element.replace(newNode);
2804
+ });
2805
+ };
2806
+ return /* @__PURE__ */ jsxs(DropdownMenu, { onOpenChange: handleOpenChange, children: [
2807
+ /* @__PURE__ */ jsx(Tooltip, { tooltip: "Change block type", placement: "top", triggerAsChild: true, children: /* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
2808
+ "button",
2809
+ {
2810
+ type: "button",
2811
+ className: cn(
2812
+ "tw-flex tw-h-7 tw-cursor-pointer tw-items-center tw-gap-1.5 tw-rounded tw-border-0 tw-bg-transparent tw-px-1.5 tw-text-xs tw-text-neutral-600",
2813
+ "hover:tw-bg-neutral-100"
2814
+ ),
2815
+ children: [
2816
+ /* @__PURE__ */ jsx(Icon, { icon: currentMeta?.icon ?? ["far", "font"], fixedWidth: true }),
2817
+ currentMeta?.label ?? "Normal",
2818
+ /* @__PURE__ */ jsx(Icon, { icon: ["fas", "caret-down"], className: "tw-text-[8px]" })
2819
+ ]
2820
+ }
2821
+ ) }) }),
2822
+ /* @__PURE__ */ jsx(DropdownMenu.Content, { align: "start", className: "tw-min-w-40", children: BLOCK_TYPE_OPTIONS.map(({ value, label, icon }) => /* @__PURE__ */ jsxs(
2823
+ DropdownMenu.Item,
2824
+ {
2825
+ onSelect: () => handleSelect(value),
2826
+ className: cn(
2827
+ "tw-flex tw-items-center tw-gap-2",
2828
+ blockType === value && "tw-bg-secondary-50 tw-text-secondary-500"
2829
+ ),
2830
+ children: [
2831
+ /* @__PURE__ */ jsx(Icon, { icon, fixedWidth: true }),
2832
+ label
2833
+ ]
2834
+ },
2835
+ value
2836
+ )) })
2837
+ ] });
2838
+ };
2839
+
2840
+ // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
2841
+ init_Button2();
2842
+ var buttonGroupVariant = cva(
2843
+ ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
2844
+ {
2845
+ defaultVariants: {
2846
+ variant: "inline",
2847
+ space: "small"
2848
+ },
2849
+ variants: {
2850
+ variant: {
2851
+ inline: [],
2852
+ block: [
2853
+ "tw-w-full",
2854
+ "tw-flex-col",
2855
+ "sm:tw-flex-row",
2856
+ "[&_a]:tw-flex-1",
2857
+ "[&>button:not([data-icon-only=true])]:tw-flex-1"
2858
+ ]
2859
+ },
2860
+ space: {
2861
+ "extra-small": "tw-gap-1",
2862
+ "little-small": "tw-gap-2",
2863
+ small: "tw-gap-3",
2864
+ medium: "tw-gap-4",
2865
+ large: "tw-gap-6",
2866
+ compact: [
2867
+ "tw-border-collapse",
2868
+ "!tw-gap-0",
2869
+ // ensure that focus visible outline is at the top
2870
+ "[&>*:focus-visible]:!tw-z-10",
2871
+ "[&>*:not(:first-child)]:tw-rounded-l-none",
2872
+ "[&>*:not(:last-child)]:tw-rounded-r-none",
2873
+ "[&>*:not(:last-child)]:tw-border-r-0",
2874
+ "[&>*:not(:first-child)]:tw-border-l-0",
2875
+ // separator
2876
+ "[&>*:not(:first-child)]:before:tw-content",
2877
+ "[&>*:not(:first-child)]:before:tw-absolute",
2878
+ "[&>*:not(:first-child)]:before:tw-left-0",
2879
+ "[&>*:not(:first-child)]:before:tw-h-full",
2880
+ "[&>*:not(:first-child)]:before:tw-w-px",
2881
+ "[&>*:not(:first-child)]:before:tw-bg-black/10"
2882
+ ]
2883
+ }
2884
+ }
2885
+ }
2886
+ );
2887
+ var ButtonGroup = ({
2888
+ ref,
2889
+ children,
2890
+ space = "small",
2891
+ className,
2892
+ variant,
2893
+ ...rest
2894
+ }) => {
2895
+ return /* @__PURE__ */ jsx(
2896
+ "div",
2897
+ {
2898
+ ref,
2899
+ ...rest,
2900
+ role: "group",
2901
+ "data-variant": variant,
2902
+ className: buttonGroupVariant({ variant, className, space }),
2903
+ children
2904
+ }
2905
+ );
2906
+ };
2907
+
2908
+ // src/components/FormGroup/FormGroup.tsx
2909
+ init_utils();
2910
+ var FormGroupContext = createContext({
2911
+ state: "default"
2912
+ });
2913
+ var FormGroupProvider = FormGroupContext;
2914
+ var useFormGroupContext = () => use(FormGroupContext);
2915
+
2916
+ // src/components/InputGroup/InputGroup.tsx
2917
+ init_utils();
2918
+
2919
+ // src/components/InputGroup/InputGroupAddon.tsx
2920
+ init_utils();
2921
+ var addonVariants = cva(["tw-flex", "tw-items-center", "tw-gap-1"], {
2922
+ defaultVariants: {
2923
+ align: "inline-start"
2924
+ },
2925
+ variants: {
2926
+ align: {
2927
+ "inline-start": ["tw-order-first", "[&:not(:empty)]:tw-pl-4"],
2928
+ "inline-end": ["tw-order-last", "[&:not(:empty)]:tw-pr-4"],
2929
+ "block-start": [
2930
+ "tw-order-first",
2931
+ // `tw-w-full` needs to be empty-conditional too — when the addon
2932
+ // has no content the root stays in flex-row, and a 100%-wide
2933
+ // empty addon would claim half of the input row beside the input.
2934
+ "[&:not(:empty)]:tw-w-full",
2935
+ "[&:not(:empty)]:tw-px-4",
2936
+ "[&:not(:empty)]:tw-py-1.5"
2937
+ ],
2938
+ "block-end": [
2939
+ "tw-order-last",
2940
+ "[&:not(:empty)]:tw-w-full",
2941
+ "[&:not(:empty)]:tw-px-4",
2942
+ "[&:not(:empty)]:tw-py-1.5"
2943
+ ]
2944
+ }
2945
+ }
2946
+ });
2947
+ var InputGroupAddon = ({
2948
+ children,
2949
+ align = "inline-start",
2950
+ className,
2951
+ ...props
2952
+ }) => /* @__PURE__ */ jsx("div", { ...props, "data-align": align, className: cn(addonVariants({ align, className })), children });
2953
+
2954
+ // src/components/InputGroup/InputGroupButton.tsx
2955
+ init_utils();
2956
+ init_Button2();
2957
+ var InputGroupButton = ({
2958
+ ref,
2959
+ className,
2960
+ tabIndex = -1,
2961
+ ...props
2962
+ }) => /* @__PURE__ */ jsx(
2963
+ Button,
2964
+ {
2965
+ argo: true,
2966
+ ...props,
2967
+ tabIndex,
2968
+ ref,
2969
+ variant: "invisible",
2970
+ size: "icon-sm",
2971
+ className: cn("tw-size-5", "[&_svg]:tw-text-muted-foreground", className)
2972
+ }
2973
+ );
2974
+
2975
+ // src/components/InputGroup/InputGroupInput.tsx
2976
+ init_utils();
2977
+ var InputGroupInput = ({
2978
+ ref,
2979
+ className,
2980
+ ...inputProps
2981
+ }) => /* @__PURE__ */ jsx(
2982
+ "input",
2983
+ {
2984
+ ...inputProps,
2985
+ ref,
2986
+ className: cn(
2987
+ "tw-w-full",
2988
+ "tw-bg-transparent",
2989
+ "tw-outline-none",
2990
+ // font
2991
+ "tw-font-sans",
2992
+ "tw-text-sm",
2993
+ // placeholder
2994
+ "placeholder:tw-text-neutral-400",
2995
+ "placeholder:tw-font-normal",
2996
+ // disabled
2997
+ "disabled:tw-cursor-not-allowed",
2998
+ className
2999
+ )
3000
+ }
3001
+ );
3002
+
3003
+ // src/components/InputGroup/InputGroupText.tsx
3004
+ init_utils();
3005
+ var InputGroupText = ({ className, ...props }) => /* @__PURE__ */ jsx(
3006
+ "span",
3007
+ {
3008
+ className: cn(
3009
+ "tw-flex",
3010
+ "tw-items-center",
3011
+ "tw-gap-2",
3012
+ "tw-text-sm",
3013
+ "tw-text-muted-foreground",
3014
+ "[&_svg]:tw-pointer-events-none",
3015
+ '[&_svg:not([class*="tw-size-"])]:tw-size-4',
3016
+ className
3017
+ ),
3018
+ ...props
3019
+ }
3020
+ );
3021
+
3022
+ // src/components/InputGroup/InputGroupTextArea.tsx
3023
+ init_utils();
3024
+ var InputGroupTextArea = ({
3025
+ ref,
3026
+ className,
3027
+ onChange,
3028
+ onValueChange,
3029
+ value,
3030
+ defaultValue,
3031
+ onBlur,
3032
+ onValueBlur,
3033
+ disableResize = false,
3034
+ minRows = 1,
3035
+ maxRows = 4,
3036
+ ...props
3037
+ }) => {
3038
+ const handleChange = (event) => {
3039
+ onValueChange?.(event.target.value);
3040
+ onChange?.(event);
3041
+ };
3042
+ const handleBlur = (event) => {
3043
+ onValueBlur?.(event.target.value);
3044
+ onBlur?.(event);
3045
+ };
3046
+ return /* @__PURE__ */ jsx(
3047
+ TextareaAutosize,
3048
+ {
3049
+ ...props,
3050
+ ref,
3051
+ value: value ?? void 0,
3052
+ defaultValue: defaultValue ?? void 0,
3053
+ onChange: handleChange,
3054
+ onBlur: handleBlur,
3055
+ minRows,
3056
+ maxRows: maxRows === "unlimited" ? void 0 : maxRows,
3057
+ className: cn(
3058
+ "tw-w-full",
3059
+ "tw-bg-transparent",
3060
+ "tw-outline-none",
3061
+ "tw-px-4",
3062
+ // font
3063
+ "tw-font-sans",
3064
+ "tw-text-sm",
3065
+ // placeholder
3066
+ "placeholder:tw-text-neutral-400",
3067
+ "placeholder:tw-font-normal",
3068
+ // disabled
3069
+ "disabled:tw-cursor-not-allowed",
3070
+ {
3071
+ "tw-resize-none": disableResize
3072
+ },
3073
+ className
3074
+ )
3075
+ }
3076
+ );
3077
+ };
3078
+ var inputGroupVariants = cva(
3079
+ [
3080
+ "tailwindcss-preflight",
3081
+ "tw-group",
3082
+ "tw-overflow-hidden",
3083
+ "tw-box-border",
3084
+ // positioning
3085
+ "tw-flex",
3086
+ "tw-items-center",
3087
+ // base
3088
+ "tw-rounded",
3089
+ "tw-border",
3090
+ "tw-border-solid",
3091
+ "tw-border-neutral-200",
3092
+ "tw-text-neutral-800",
3093
+ "tw-transition",
3094
+ // focus
3095
+ "has-[:is(input,textarea):focus]:tw-ring-4",
3096
+ // readonly
3097
+ "has-[:is(input,textarea)[readonly]]:tw-bg-neutral-150",
3098
+ "has-[:is(input,textarea)[readonly]]:focus-within:tw-ring-0",
3099
+ "has-[:is(input,textarea)[readonly]]:tw-border-neutral-150",
3100
+ // disabled cursor (opacity owned by variant)
3101
+ "has-[:is(input,textarea):disabled]:tw-cursor-not-allowed",
3102
+ // textarea: top-align addons, allow vertical expansion, own its y-padding
3103
+ "has-[textarea]:tw-items-start",
3104
+ "has-[[data-align=block-start]:not(:empty)]:tw-flex-wrap",
3105
+ "has-[[data-align=block-end]:not(:empty)]:tw-flex-wrap",
3106
+ "[&>input]:has-[[data-align=block-start]:not(:empty)]:tw-w-auto",
3107
+ "[&>input]:has-[[data-align=block-start]:not(:empty)]:tw-flex-1",
3108
+ "[&>input]:has-[[data-align=block-end]:not(:empty)]:tw-w-auto",
3109
+ "[&>input]:has-[[data-align=block-end]:not(:empty)]:tw-flex-1",
3110
+ "[&>input]:tw-px-4",
3111
+ "[&>input]:has-[[data-align=inline-start]:not(:empty)]:tw-pl-2",
3112
+ "[&>input]:has-[[data-align=inline-end]:not(:empty)]:tw-pr-2"
3113
+ ],
3114
+ {
3115
+ defaultVariants: {
3116
+ variant: "primary",
3117
+ state: "default",
3118
+ sizing: "default",
3119
+ focusVariant: "default"
3120
+ },
3121
+ compoundVariants: [
3122
+ {
3123
+ variant: "secondary",
3124
+ state: "error",
3125
+ className: ["tw-bg-error-100"]
3126
+ },
3127
+ {
3128
+ variant: "secondary",
3129
+ state: "warning",
3130
+ className: ["tw-bg-warning-100"]
3131
+ },
3132
+ {
3133
+ variant: "primary",
3134
+ state: "default",
3135
+ focusVariant: "off",
3136
+ className: ["has-[:is(input,textarea):focus]:tw-border-neutral-200"]
3137
+ },
3138
+ {
3139
+ variant: "secondary",
3140
+ state: "default",
3141
+ focusVariant: "off",
3142
+ className: ["has-[:is(input,textarea):focus]:tw-border-neutral-100"]
3143
+ },
3144
+ {
3145
+ variant: ["primary", "secondary"],
3146
+ state: "error",
3147
+ focusVariant: "on",
3148
+ className: ["!tw-border-error-500", "!tw-ring-error-200"]
3149
+ },
3150
+ {
3151
+ variant: ["primary", "secondary"],
3152
+ state: "warning",
3153
+ focusVariant: "on",
3154
+ className: ["!tw-border-warning-500", "!tw-ring-warning-200"]
3155
+ },
3156
+ // --- argo ---
3157
+ {
3158
+ variant: "argo",
3159
+ state: "default",
3160
+ className: [
3161
+ "has-[:is(input,textarea):focus]:tw-border-primary",
3162
+ "has-[:is(input,textarea):focus]:tw-ring-primary/50"
3163
+ ]
3164
+ },
3165
+ {
3166
+ variant: "argo",
3167
+ state: "error",
3168
+ className: [
3169
+ "tw-border-destructive",
3170
+ "has-[:is(input,textarea):focus]:tw-border-destructive",
3171
+ "has-[:is(input,textarea):focus]:tw-ring-destructive/20"
3172
+ ]
3173
+ },
3174
+ {
3175
+ variant: "argo",
3176
+ focusVariant: "on",
3177
+ className: ["!tw-border-primary", "!tw-ring-primary/50"]
3178
+ },
3179
+ {
3180
+ variant: "argo",
3181
+ state: "error",
3182
+ focusVariant: "on",
3183
+ className: ["!tw-border-destructive", "!tw-ring-destructive/20"]
3184
+ },
3185
+ {
3186
+ variant: "argo",
3187
+ state: "default",
3188
+ focusVariant: "off",
3189
+ className: ["has-[:is(input,textarea):focus]:tw-border-input"]
3190
+ }
3191
+ ],
3192
+ variants: {
3193
+ focusVariant: {
3194
+ default: [],
3195
+ on: ["!tw-border-secondary-500", "!tw-ring-secondary-200", "!tw-ring-4"],
3196
+ off: ["has-[:is(input,textarea):focus]:!tw-ring-0"]
3197
+ },
3198
+ variant: {
3199
+ primary: ["tw-bg-white", "has-[:is(input,textarea):disabled]:tw-opacity-40"],
3200
+ secondary: [
3201
+ "tw-bg-neutral-100",
3202
+ "tw-border-neutral-100",
3203
+ "has-[:is(input,textarea):disabled]:tw-opacity-40"
3204
+ ],
3205
+ argo: [
3206
+ "tw-bg-background",
3207
+ "tw-border-input",
3208
+ "tw-rounded-lg",
3209
+ "tw-text-foreground",
3210
+ "has-[:is(input,textarea):disabled]:tw-opacity-50",
3211
+ // higher specificity than has-[:is(input,textarea):focus] — prevents focus border on readonly
3212
+ "has-[:is(input,textarea)[readonly]:focus]:tw-border-neutral-150"
3213
+ ]
3214
+ },
3215
+ sizing: {
3216
+ default: [
3217
+ "[&>:is(input,textarea)]:tw-py-2.5",
3218
+ "[&>:is(input,textarea)]:tw-leading-[18px]",
3219
+ "[&>textarea]:!tw-min-h-[calc(2.5rem-2px)]"
3220
+ ],
3221
+ small: [
3222
+ "[&>:is(input,textarea)]:tw-py-2",
3223
+ "[&>:is(input,textarea)]:tw-leading-[16px]",
3224
+ "[&>textarea]:!tw-min-h-[calc(2rem-2px)]"
3225
+ ],
3226
+ medium: [
3227
+ "[&>:is(input,textarea)]:tw-py-2",
3228
+ "[&>:is(input,textarea)]:tw-leading-[18px]",
3229
+ "[&>textarea]:!tw-min-h-[calc(2.25rem-2px)]"
3230
+ ]
3231
+ },
3232
+ state: {
3233
+ default: [
3234
+ "has-[:is(input,textarea):focus]:tw-border-secondary-500",
3235
+ "has-[:is(input,textarea):focus]:tw-ring-secondary-200"
3236
+ ],
3237
+ error: [
3238
+ "tw-border-error-500",
3239
+ "has-[:is(input,textarea):focus]:tw-border-error-500",
3240
+ "has-[:is(input,textarea):focus]:tw-ring-error-200"
3241
+ ],
3242
+ warning: [
3243
+ "tw-border-warning-500",
3244
+ "has-[:is(input,textarea):focus]:tw-border-warning-500",
3245
+ "has-[:is(input,textarea):focus]:tw-ring-warning-200"
3246
+ ]
3247
+ }
3248
+ }
3249
+ }
3250
+ );
3251
+ var InputGroupRoot = ({
3252
+ ref,
3253
+ children,
3254
+ state,
3255
+ variant,
3256
+ sizing,
3257
+ focusVariant,
3258
+ className,
3259
+ ...props
3260
+ }) => /* @__PURE__ */ jsx(
3261
+ "div",
3262
+ {
3263
+ ...props,
3264
+ ref,
3265
+ className: cn(inputGroupVariants({ state, variant, sizing, focusVariant, className })),
3266
+ children
3267
+ }
3268
+ );
3269
+ var InputGroup = InputGroupRoot;
3270
+ InputGroup.Input = InputGroupInput;
3271
+ InputGroup.Addon = InputGroupAddon;
3272
+ InputGroup.Button = InputGroupButton;
3273
+ InputGroup.TextArea = InputGroupTextArea;
3274
+ InputGroup.Text = InputGroupText;
3275
+
3276
+ // src/blocks/ColorInput/ColorInput.tsx
3277
+ init_utils();
3278
+
3279
+ // src/blocks/ColorInput/utils.ts
3280
+ var HEX_CHARSET = /^[0-9a-fA-F]+$/;
3281
+ var COMPLETE_HEX_PATTERN = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
3282
+ var MAX_HEX_BODY_LENGTH = 8;
3283
+ var PICKER_FALLBACK = "#000000";
3284
+ var extractHexBody = (value) => {
3285
+ if (typeof value !== "string") return null;
3286
+ const trimmed = value.trim();
3287
+ if (trimmed === "") return null;
3288
+ return trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
3289
+ };
3290
+ var isCompleteHexColor = (value) => COMPLETE_HEX_PATTERN.test(value);
3291
+ var showPicker = (input) => {
3292
+ const isShowPickerSupported = "showPicker" in HTMLInputElement.prototype;
3293
+ isShowPickerSupported ? input.showPicker() : input.click();
3294
+ };
3295
+ var coerceHexInputValue = (value) => {
3296
+ const body = extractHexBody(value);
3297
+ if (body === null) return "";
3298
+ const [validBody] = body.match(/^[0-9a-fA-F]+/) ?? [];
3299
+ if (!validBody) return "";
3300
+ return `#${validBody.slice(0, MAX_HEX_BODY_LENGTH)}`;
3301
+ };
3302
+ var coerceColorPickerValue = (value) => {
3303
+ const body = extractHexBody(value);
3304
+ if (body === null || !HEX_CHARSET.test(body)) return PICKER_FALLBACK;
3305
+ if (body.length === 3 || body.length === 4) {
3306
+ const [r, g, b] = body;
3307
+ return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
3308
+ }
3309
+ if (body.length === 6 || body.length === 8) {
3310
+ return `#${body.slice(0, 6).toLowerCase()}`;
3311
+ }
3312
+ return PICKER_FALLBACK;
3313
+ };
3314
+ var ColorPicker = ({ value, disabled, readOnly, ...props }) => {
3315
+ const pickerRef = useRef(null);
3316
+ const handleOpenPicker = () => {
3317
+ if (!pickerRef.current) return;
3318
+ showPicker(pickerRef.current);
3319
+ };
3320
+ return /* @__PURE__ */ jsxs("div", { className: "tw-relative", children: [
3321
+ /* @__PURE__ */ jsx(
3322
+ "input",
3323
+ {
3324
+ ...props,
3325
+ ref: pickerRef,
3326
+ type: "color",
3327
+ value: coerceColorPickerValue(value),
3328
+ tabIndex: -1,
3329
+ "aria-hidden": true,
3330
+ className: "tw-pointer-events-none tw-absolute tw-left-0 tw-top-full tw-size-0 tw-opacity-0",
3331
+ disabled,
3332
+ readOnly
3333
+ }
3334
+ ),
3335
+ /* @__PURE__ */ jsx(
3336
+ InputGroup.Button,
3337
+ {
3338
+ onMouseDown: (event) => event.preventDefault(),
3339
+ disabled: disabled || readOnly,
3340
+ icon: "eye-dropper",
3341
+ onClick: handleOpenPicker,
3342
+ "aria-label": "Pick color"
3343
+ }
3344
+ )
3345
+ ] });
3346
+ };
3347
+ var ColorInput = ({
3348
+ ref,
3349
+ // group props
3350
+ state,
3351
+ variant,
3352
+ focusVariant,
3353
+ sizing,
3354
+ className,
3355
+ // own props
3356
+ value: valueProp,
3357
+ onValueChange,
3358
+ onValueBlur,
3359
+ onChange,
3360
+ onBlur,
3361
+ defaultValue,
3362
+ allowClear = false,
3363
+ // input props
3364
+ disabled,
3365
+ readOnly,
3366
+ ...restInputProps
3367
+ }) => {
3368
+ const inputRef = useRef(null);
3369
+ const [internalValue, setInternalValue] = useState(defaultValue ?? "");
3370
+ const isControlled = valueProp !== void 0;
3371
+ const value = isControlled ? valueProp ?? "" : internalValue;
3372
+ const setValue = (nextValue) => {
3373
+ if (!isControlled) setInternalValue(nextValue);
3374
+ onValueChange?.(nextValue);
3375
+ };
3376
+ const canClear = allowClear && !!value && !disabled && !readOnly;
3377
+ const swatchColor = coerceHexInputValue(value);
3378
+ const isValidSwatch = isCompleteHexColor(swatchColor);
3379
+ const handleChange = (event) => {
3380
+ setValue(event.target.value);
3381
+ onChange?.(event);
3382
+ };
3383
+ const handleBlur = (event) => {
3384
+ const newValue = event.target.value;
3385
+ const sanitizedNewValue = coerceHexInputValue(newValue);
3386
+ if (sanitizedNewValue !== newValue) {
3387
+ if (!isControlled) event.target.value = sanitizedNewValue;
3388
+ setValue(sanitizedNewValue);
3389
+ }
3390
+ onValueBlur?.(sanitizedNewValue);
3391
+ onBlur?.(event);
3392
+ };
3393
+ const handlePickerChange = (event) => {
3394
+ setValue(coerceHexInputValue(event.target.value));
3395
+ onChange?.(event);
3396
+ };
3397
+ const handleClear = () => {
3398
+ if (!inputRef.current) return;
3399
+ inputRef.current.value = "";
3400
+ setValue("");
3401
+ onChange?.(createChangeInputEvent(inputRef.current));
3402
+ };
3403
+ return /* @__PURE__ */ jsxs(
3404
+ InputGroup,
3405
+ {
3406
+ state,
3407
+ variant,
3408
+ sizing,
3409
+ focusVariant,
3410
+ className,
3411
+ children: [
3412
+ /* @__PURE__ */ jsx(
3413
+ InputGroup.Addon,
3414
+ {
3415
+ align: "inline-start",
3416
+ className: cn(
3417
+ { "-tw-ml-7 tw-opacity-0": !value },
3418
+ "tw-transition-[opacity,margin]",
3419
+ "tw-ease-linear",
3420
+ "tw-duration-200"
3421
+ ),
3422
+ children: /* @__PURE__ */ jsx(
3423
+ "div",
3424
+ {
3425
+ style: isValidSwatch ? { background: swatchColor } : void 0,
3426
+ className: cn(
3427
+ "tw-size-5",
3428
+ "tw-shrink-0",
3429
+ "tw-rounded-sm",
3430
+ "tw-border",
3431
+ "tw-border-solid",
3432
+ "tw-border-neutral-300",
3433
+ {
3434
+ "tw-bg-[linear-gradient(to_top_right,transparent_calc(50%_-_1px),theme(colors.red.300)_calc(50%_-_1px),theme(colors.red.300)_calc(50%_+_1px),transparent_calc(50%_+_1px))]": !isValidSwatch
3435
+ }
3436
+ )
3437
+ }
3438
+ )
3439
+ }
3440
+ ),
3441
+ /* @__PURE__ */ jsx(
3442
+ InputGroup.Input,
3443
+ {
3444
+ ...restInputProps,
3445
+ type: "text",
3446
+ ref: mergeRefs(ref ?? null, inputRef),
3447
+ value,
3448
+ onChange: handleChange,
3449
+ onBlur: handleBlur,
3450
+ disabled,
3451
+ readOnly
3452
+ }
3453
+ ),
3454
+ /* @__PURE__ */ jsxs(InputGroup.Addon, { align: "inline-end", children: [
3455
+ canClear && /* @__PURE__ */ jsx(
3456
+ InputGroup.Button,
3457
+ {
3458
+ icon: "xmark",
3459
+ onMouseDown: (event) => event.preventDefault(),
3460
+ onClick: handleClear,
3461
+ "aria-label": "Clear color"
3462
+ }
3463
+ ),
3464
+ /* @__PURE__ */ jsx(
3465
+ ColorPicker,
3466
+ {
3467
+ disabled,
3468
+ readOnly,
3469
+ value,
3470
+ onChange: handlePickerChange
3471
+ }
3472
+ )
3473
+ ] })
3474
+ ]
3475
+ }
3476
+ );
3477
+ };
3478
+ var FormGroupColorInput = ({
3479
+ ref,
3480
+ ...props
3481
+ }) => {
3482
+ const { state } = useFormGroupContext();
3483
+ return /* @__PURE__ */ jsx(ColorInput, { state, ...props, ref });
3484
+ };
3485
+ var helpVariants = cva(["tw-m-0", "tw-text-xs"], {
3486
+ defaultVariants: {
3487
+ state: "default"
3488
+ },
3489
+ variants: {
3490
+ state: {
3491
+ default: ["tw-text-neutral-500"],
3492
+ error: ["tw-text-error-500"],
3493
+ warning: ["tw-text-warning-500"]
3494
+ }
3495
+ }
3496
+ });
3497
+ var HelpBlock = ({ children, className, state = "default", testId }) => {
3498
+ if (!children) return null;
3499
+ return /* @__PURE__ */ jsx("p", { "data-testid": testId, className: helpVariants({ state, className }), children });
3500
+ };
3501
+ var FormGroupHelp = ({ children, ...rest }) => {
3502
+ const formGroupContext = useFormGroupContext();
3503
+ return /* @__PURE__ */ jsx(HelpBlock, { state: formGroupContext.state, ...rest, children });
3504
+ };
3505
+ var toNumberOrNull = (event) => Number.isNaN(event.target.valueAsNumber) ? null : event.target.valueAsNumber;
3506
+ var NumberInput = ({
3507
+ ref,
3508
+ state,
3509
+ variant,
3510
+ focusVariant,
3511
+ sizing,
3512
+ className,
3513
+ value,
3514
+ defaultValue,
3515
+ onValueChange,
3516
+ onValueBlur,
3517
+ onChange,
3518
+ onBlur,
3519
+ prefix,
3520
+ suffix,
3521
+ ...inputProps
3522
+ }) => {
3523
+ const handleChange = (event) => {
3524
+ onValueChange?.(toNumberOrNull(event));
3525
+ onChange?.(event);
3526
+ };
3527
+ const handleBlur = (event) => {
3528
+ onValueBlur?.(toNumberOrNull(event));
3529
+ onBlur?.(event);
3530
+ };
3531
+ const isControlled = value !== void 0;
3532
+ const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
3533
+ return /* @__PURE__ */ jsxs(
3534
+ InputGroup,
3535
+ {
3536
+ state,
3537
+ variant,
3538
+ sizing,
3539
+ focusVariant,
3540
+ className,
3541
+ children: [
3542
+ prefix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-start", children: prefix }),
3543
+ /* @__PURE__ */ jsx(
3544
+ InputGroup.Input,
3545
+ {
3546
+ ...inputProps,
3547
+ ...valueProp,
3548
+ ref,
3549
+ type: "number",
3550
+ onChange: handleChange,
3551
+ onBlur: handleBlur
3552
+ }
3553
+ ),
3554
+ suffix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-end", children: suffix })
3555
+ ]
3556
+ }
3557
+ );
3558
+ };
3559
+ var FormGroupNumberInput = ({
3560
+ ref,
3561
+ ...props
3562
+ }) => {
3563
+ const { state } = useFormGroupContext();
3564
+ return /* @__PURE__ */ jsx(NumberInput, { ...props, ref, state });
3565
+ };
3566
+ var Textarea = ({
3567
+ ref,
3568
+ containerClassName,
3569
+ // group props
3570
+ state = "default",
3571
+ variant = "primary",
3572
+ sizing,
3573
+ focusVariant,
3574
+ ...rest
3575
+ }) => {
3576
+ return /* @__PURE__ */ jsx(
3577
+ InputGroup,
3578
+ {
3579
+ state,
3580
+ sizing,
3581
+ focusVariant,
3582
+ variant,
3583
+ className: containerClassName,
3584
+ children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref })
3585
+ }
3586
+ );
3587
+ };
3588
+ var FormGroupTextarea = (props) => {
3589
+ const { state } = useFormGroupContext();
3590
+ return /* @__PURE__ */ jsx(Textarea, { state, ...props });
3591
+ };
3592
+
3593
+ // src/components/Input/Input.tsx
3594
+ init_utils();
3595
+
3596
+ // src/components/Input/utils.ts
3597
+ init_utils();
3598
+ var genInputTestId = (prefix = "") => {
3599
+ const ps = createPrefixedString(prefix);
3600
+ return {
3601
+ toString: () => prefix,
3602
+ inputWrapper: ps`input-wrapper`,
3603
+ input: ps`input`,
3604
+ clearButton: ps`clear-button`
3605
+ };
3606
+ };
3607
+ var Input = ({
3608
+ ref: forwardedRef,
3609
+ state = "default",
3610
+ sizing = "default",
3611
+ className,
3612
+ prefix = null,
3613
+ rightSuffix = null,
3614
+ rightSuffixVariant = "default",
3615
+ leftSuffix = null,
3616
+ allowClear = false,
3617
+ onClear,
3618
+ disabled = false,
3619
+ testId: prefixTestId = "",
3620
+ autoFocus = false,
3621
+ id,
3622
+ name,
3623
+ variant,
3624
+ readOnly,
3625
+ type = "text",
3626
+ focusVariant = "default",
3627
+ onChange,
3628
+ onBlur,
3629
+ value,
3630
+ defaultValue,
3631
+ ...inputProps
3632
+ }) => {
3633
+ const [hasUncontrolledValue, setHasUncontrolledValue] = useState(() => !!defaultValue);
3634
+ const hasValue = !!value || hasUncontrolledValue;
3635
+ const inputRef = useRef(null);
3636
+ const testId = genInputTestId(prefixTestId);
3637
+ const isClearButtonVisible = hasValue && !disabled && !readOnly || !!onClear;
3638
+ const handleChange = (event) => {
3639
+ const val = event.target.value;
3640
+ setHasUncontrolledValue(val !== "");
3641
+ onChange?.(event);
3642
+ };
3643
+ const handleBlur = (event) => {
3644
+ const val = event.target.value;
3645
+ setHasUncontrolledValue(val !== "");
3646
+ onBlur?.(event);
3647
+ };
3648
+ const handleClear = () => {
3649
+ if (inputRef.current === null) return;
3650
+ inputRef.current.value = "";
3651
+ inputRef.current.focus();
3652
+ onClear?.();
3653
+ setHasUncontrolledValue(false);
3654
+ onChange?.(createChangeInputEvent(inputRef.current));
3655
+ };
3656
+ const isControlled = value !== void 0;
3657
+ const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
3658
+ return /* @__PURE__ */ jsxs(
3659
+ InputGroup,
3660
+ {
3661
+ state,
3662
+ variant,
3663
+ sizing,
3664
+ focusVariant,
3665
+ className,
3666
+ "data-testid": testId.inputWrapper,
3667
+ children: [
3668
+ prefix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-start", children: prefix }),
3669
+ /* @__PURE__ */ jsx(
3670
+ InputGroup.Input,
3671
+ {
3672
+ ...inputProps,
3673
+ ...valueProp,
3674
+ autoFocus,
3675
+ type,
3676
+ onChange: handleChange,
3677
+ onBlur: handleBlur,
3678
+ ref: mergeRefs(forwardedRef ?? null, inputRef),
3679
+ disabled,
3680
+ id,
3681
+ name,
3682
+ readOnly,
3683
+ "data-testid": testId.input
3684
+ }
3685
+ ),
3686
+ (leftSuffix || allowClear || rightSuffix) && /* @__PURE__ */ jsxs(InputGroup.Addon, { align: "inline-end", children: [
3687
+ leftSuffix,
3688
+ allowClear && isClearButtonVisible && /* @__PURE__ */ jsx(
3689
+ InputGroup.Button,
3690
+ {
3691
+ icon: "xmark",
3692
+ onMouseDown: (e) => e.preventDefault(),
3693
+ onClick: handleClear,
3694
+ "data-testid": testId.clearButton
3695
+ }
3696
+ ),
3697
+ rightSuffix && /* @__PURE__ */ jsx(
3698
+ "div",
3699
+ {
3700
+ className: cn({
3701
+ "tw-whitespace-nowrap tw-bg-neutral-200 tw-px-4 -tw-mr-4 tw-py-2.5": rightSuffixVariant === "addon"
3702
+ }),
3703
+ children: rightSuffix
3704
+ }
3705
+ )
3706
+ ] })
3707
+ ]
3708
+ }
3709
+ );
3710
+ };
3711
+ var sanitizeTextInputValue = (value) => {
3712
+ if (typeof value === "string" && value.trim() === "") return "";
3713
+ return value;
3714
+ };
3715
+ var TextInput = ({
3716
+ ref,
3717
+ value,
3718
+ defaultValue,
3719
+ type = "text",
3720
+ onValueChange,
3721
+ onChange,
3722
+ onValueBlur,
3723
+ onBlur,
3724
+ ...props
3725
+ }) => {
3726
+ const handleChange = (event) => {
3727
+ onValueChange?.(event.target.value);
3728
+ onChange?.(event);
3729
+ };
3730
+ const handleBlur = (event) => {
3731
+ onValueBlur?.(event.target.value);
3732
+ onBlur?.(event);
3733
+ };
3734
+ return /* @__PURE__ */ jsx(
3735
+ Input,
3736
+ {
3737
+ ...props,
3738
+ ref,
3739
+ onChange: handleChange,
3740
+ onBlur: handleBlur,
3741
+ type,
3742
+ value: sanitizeTextInputValue(value),
3743
+ defaultValue: sanitizeTextInputValue(defaultValue)
3744
+ }
3745
+ );
3746
+ };
3747
+ var FormGroupTextInput = ({
3748
+ ref,
3749
+ ...props
3750
+ }) => {
3751
+ const { state } = useFormGroupContext();
3752
+ return /* @__PURE__ */ jsx(TextInput, { state, ...props, ref });
3753
+ };
3754
+ var FormGroup = ({ className, children, state, testId }) => {
3755
+ return /* @__PURE__ */ jsx(FormGroupProvider, { value: { state }, children: /* @__PURE__ */ jsx("div", { "data-testid": testId, className: cn("tw-flex tw-flex-col tw-gap-1", className), children }) });
3756
+ };
3757
+ FormGroup.Help = FormGroupHelp;
3758
+ FormGroup.TextInput = FormGroupTextInput;
3759
+ FormGroup.NumberInput = FormGroupNumberInput;
3760
+ FormGroup.ColorInput = FormGroupColorInput;
3761
+ FormGroup.Textarea = FormGroupTextarea;
3762
+
3763
+ // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
3764
+ init_Icon2();
3765
+
3766
+ // src/components/Label/Label.tsx
3767
+ init_utils();
3768
+ var Optional = ({ className }) => /* @__PURE__ */ jsx("span", { className: cn("tw-text-neutral-400", className), children: "(optional)" });
3769
+ var Label2 = ({ className, children, id, htmlFor, ...rest }) => {
3770
+ return /* @__PURE__ */ jsx(
3771
+ RLabel.Root,
3772
+ {
3773
+ ...rest,
3774
+ id: id?.toString(),
3775
+ htmlFor: htmlFor?.toString(),
3776
+ className: cn(
3777
+ "tw-m-0 tw-text-neutral-800 tw-font-normal peer-disabled:tw-opacity-50",
3778
+ className
3779
+ ),
3780
+ children
3781
+ }
3782
+ );
3783
+ };
3784
+ Label2.Optional = Optional;
3785
+
3786
+ // src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
3787
+ init_utils();
3788
+ init_Tooltip2();
3789
+ var ToolbarButton = ({
3790
+ active,
3791
+ disabled,
3792
+ onClick,
3793
+ tooltip,
3794
+ children,
3795
+ className: extraClassName
3796
+ }) => /* @__PURE__ */ jsx(Tooltip, { tooltip, placement: "top", triggerAsChild: true, children: /* @__PURE__ */ jsx(
3797
+ "button",
3798
+ {
3799
+ type: "button",
3800
+ disabled,
3801
+ onClick,
3802
+ className: cn(
3803
+ "tw-flex tw-h-7 tw-min-w-7 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border-0 tw-bg-transparent tw-px-1 tw-text-xs tw-text-neutral-600",
3804
+ "hover:tw-bg-neutral-100 disabled:tw-cursor-not-allowed disabled:tw-opacity-30",
3805
+ active && "tw-bg-secondary-100 tw-text-secondary-500",
3806
+ extraClassName
3807
+ ),
3808
+ children
3809
+ }
3810
+ ) });
3811
+ var insertLink = (editor, url, label, savedSelection) => {
3812
+ editor.update(() => {
3813
+ $setSelection(savedSelection);
3814
+ const selection = $getSelection();
3815
+ if ($isRangeSelection(selection)) {
3816
+ const selectedText = selection.getTextContent();
3817
+ if (selectedText && label === selectedText) {
3818
+ editor.dispatchCommand(TOGGLE_LINK_COMMAND, url);
3819
+ return;
3820
+ }
3821
+ }
3822
+ const linkNode = $createLinkNode(url);
3823
+ const textNode = $createTextNode(label || url);
3824
+ linkNode.append(textNode);
3825
+ if ($isRangeSelection(selection)) {
3826
+ selection.insertNodes([linkNode]);
3827
+ }
3828
+ });
3829
+ };
3830
+ var LinkPanel = ({ editor, isLink }) => {
3831
+ const [open, setOpen] = useState(false);
3832
+ const [url, setUrl] = useState("");
3833
+ const [label, setLabel] = useState("");
3834
+ const savedSelectionRef = useRef(null);
3835
+ const panelRef = useRef(null);
3836
+ const handleOpen = () => {
3837
+ editor.getEditorState().read(() => {
3838
+ const selection = $getSelection();
3839
+ savedSelectionRef.current = selection ? selection.clone() : null;
3840
+ if ($isRangeSelection(selection)) {
3841
+ const text = selection.getTextContent();
3842
+ if (text) setLabel(text);
3843
+ }
3844
+ });
3845
+ setOpen(true);
3846
+ };
3847
+ const handleClose = () => {
3848
+ setOpen(false);
3849
+ setUrl("");
3850
+ setLabel("");
3851
+ savedSelectionRef.current = null;
3852
+ editor.focus();
3853
+ };
3854
+ const handleSubmit = () => {
3855
+ const trimmedUrl = url.trim();
3856
+ if (!trimmedUrl) return;
3857
+ insertLink(editor, trimmedUrl, label.trim(), savedSelectionRef.current);
3858
+ handleClose();
3859
+ };
3860
+ const handleKeyDown = (e) => {
3861
+ if (e.key === "Enter") {
3862
+ e.preventDefault();
3863
+ handleSubmit();
3864
+ }
3865
+ if (e.key === "Escape") {
3866
+ e.preventDefault();
3867
+ handleClose();
3868
+ }
3869
+ };
3870
+ if (isLink) {
3871
+ return /* @__PURE__ */ jsx(
3872
+ ToolbarButton,
3873
+ {
3874
+ active: true,
3875
+ onClick: () => editor.dispatchCommand(TOGGLE_LINK_COMMAND, null),
3876
+ tooltip: "Remove Link",
3877
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "link"] })
3878
+ }
3879
+ );
3880
+ }
3881
+ return /* @__PURE__ */ jsxs("div", { className: "tw-relative", children: [
3882
+ /* @__PURE__ */ jsx(ToolbarButton, { active: open, onClick: handleOpen, tooltip: "Insert Link", children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "link"] }) }),
3883
+ open && /* @__PURE__ */ jsx(
3884
+ "div",
3885
+ {
3886
+ ref: panelRef,
3887
+ className: "tw-absolute tw-left-0 tw-top-full tw-z-50 tw-mt-1 tw-w-80 tw-rounded-md tw-border tw-border-neutral-200 tw-bg-white tw-p-3 tw-shadow-lg",
3888
+ children: /* @__PURE__ */ jsxs("div", { className: "tw-flex tw-flex-col tw-gap-2", children: [
3889
+ /* @__PURE__ */ jsxs(FormGroup, { children: [
3890
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "link-label", className: "tw-mb-1 tw-text-xs", children: "Label" }),
3891
+ /* @__PURE__ */ jsx(
3892
+ TextInput,
3893
+ {
3894
+ id: "link-label",
3895
+ autoFocus: true,
3896
+ placeholder: "Link text",
3897
+ value: label,
3898
+ onValueChange: setLabel,
3899
+ onKeyDown: handleKeyDown,
3900
+ variant: "secondary"
3901
+ }
3902
+ )
3903
+ ] }),
3904
+ /* @__PURE__ */ jsxs(FormGroup, { children: [
3905
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "link-url", className: "tw-mb-1 tw-text-xs", children: "URL" }),
3906
+ /* @__PURE__ */ jsx(
3907
+ TextInput,
3908
+ {
3909
+ id: "link-url",
3910
+ placeholder: "https://\u2026",
3911
+ value: url,
3912
+ onValueChange: setUrl,
3913
+ onKeyDown: handleKeyDown,
3914
+ variant: "secondary"
3915
+ }
3916
+ )
3917
+ ] }),
3918
+ /* @__PURE__ */ jsxs(ButtonGroup, { children: [
3919
+ /* @__PURE__ */ jsx(Button, { size: "small", variant: "outline", onClick: handleClose, children: "Cancel" }),
3920
+ /* @__PURE__ */ jsx(Button, { size: "small", onClick: handleSubmit, disabled: !url.trim(), children: "Add link" })
3921
+ ] })
3922
+ ] })
3923
+ }
3924
+ )
3925
+ ] });
3926
+ };
3927
+ var ToolbarDivider = () => /* @__PURE__ */ jsx("div", { className: "tw-mx-0.5 tw-h-5 tw-w-px tw-bg-neutral-200" });
3928
+ var ELEMENT_FORMAT_TYPES = ["left", "center", "right", "justify", "start", "end", ""];
3929
+ var isElementFormatType = (value) => ELEMENT_FORMAT_TYPES.includes(value);
3930
+ var toElementFormatType = (value) => isElementFormatType(value) ? value : "left";
3931
+ var ToolbarPlugin = () => {
3932
+ const [editor] = useLexicalComposerContext();
3933
+ const [isBold, setIsBold] = useState(false);
3934
+ const [isItalic, setIsItalic] = useState(false);
3935
+ const [isUnderline, setIsUnderline] = useState(false);
3936
+ const [isStrikethrough, setIsStrikethrough] = useState(false);
3937
+ const [isCode, setIsCode] = useState(false);
3938
+ const [isLink, setIsLink] = useState(false);
3939
+ const [blockType, setBlockType] = useState("paragraph");
3940
+ const [alignment, setAlignment] = useState("left");
3941
+ const [isVisible, setIsVisible] = useState(false);
3942
+ const [position, setPosition] = useState(null);
3943
+ const toolbarRef = useRef(null);
3944
+ const isMouseDownRef = useRef(false);
3945
+ const hasSelectionRef = useRef(false);
3946
+ const updatePosition = useCallback(() => {
3947
+ const nativeSelection = window.getSelection();
3948
+ if (!nativeSelection || nativeSelection.rangeCount === 0) return;
3949
+ const range = nativeSelection.getRangeAt(0);
3950
+ const rect = range.getBoundingClientRect();
3951
+ if (rect.width > 0) {
3952
+ const toolbarWidth = toolbarRef.current?.offsetWidth ?? 300;
3953
+ setPosition({
3954
+ top: rect.top + window.scrollY - 8,
3955
+ left: Math.max(8, rect.left + window.scrollX + rect.width / 2 - toolbarWidth / 2)
3956
+ });
3957
+ }
3958
+ }, []);
3959
+ useEffect(() => {
3960
+ const handleMouseDown = () => {
3961
+ isMouseDownRef.current = true;
3962
+ };
3963
+ const handleMouseUp = () => {
3964
+ isMouseDownRef.current = false;
3965
+ if (hasSelectionRef.current) {
3966
+ setIsVisible(true);
3967
+ }
3968
+ };
3969
+ document.addEventListener("mousedown", handleMouseDown);
3970
+ document.addEventListener("mouseup", handleMouseUp);
3971
+ return () => {
3972
+ document.removeEventListener("mousedown", handleMouseDown);
3973
+ document.removeEventListener("mouseup", handleMouseUp);
3974
+ };
3975
+ }, []);
3976
+ const updateToolbar = useCallback(() => {
3977
+ const selection = $getSelection();
3978
+ if (!$isRangeSelection(selection)) {
3979
+ hasSelectionRef.current = false;
3980
+ setIsVisible(false);
3981
+ return;
3982
+ }
3983
+ const hasSelection = !selection.isCollapsed() && selection.getTextContent().length > 0;
3984
+ hasSelectionRef.current = hasSelection;
3985
+ if (!hasSelection) {
3986
+ setIsVisible(false);
3987
+ } else if (!isMouseDownRef.current) {
3988
+ setIsVisible(true);
3989
+ }
3990
+ if (hasSelection) {
3991
+ updatePosition();
3992
+ }
3993
+ setIsBold(selection.hasFormat("bold"));
3994
+ setIsItalic(selection.hasFormat("italic"));
3995
+ setIsUnderline(selection.hasFormat("underline"));
3996
+ setIsStrikethrough(selection.hasFormat("strikethrough"));
3997
+ setIsCode(selection.hasFormat("code"));
3998
+ const node = selection.anchor.getNode();
3999
+ const parent = node.getParent();
4000
+ setIsLink($isLinkNode(parent) || $isLinkNode(node));
4001
+ const blockElement = $getNearestBlockElementAncestorOrThrow(node);
4002
+ if ($isListNode(blockElement)) {
4003
+ const listType = blockElement.getListType();
4004
+ setBlockType(listType === "number" ? "number" : "bullet");
4005
+ } else if ($isHeadingNode(blockElement)) {
4006
+ setBlockType(blockElement.getTag());
4007
+ } else if ($isCodeNode(blockElement)) {
4008
+ setBlockType("code");
4009
+ } else if ($isQuoteNode(blockElement)) {
4010
+ setBlockType("quote");
4011
+ } else {
4012
+ setBlockType("paragraph");
4013
+ }
4014
+ setAlignment(toElementFormatType(blockElement.getFormatType()));
4015
+ }, [updatePosition]);
4016
+ useEffect(() => {
4017
+ const unregisterUpdate = editor.registerUpdateListener(({ editorState }) => {
4018
+ editorState.read(() => {
4019
+ updateToolbar();
4020
+ });
4021
+ });
4022
+ return () => {
4023
+ unregisterUpdate();
4024
+ };
4025
+ }, [editor, updateToolbar]);
4026
+ if (!isVisible || !position) return null;
4027
+ return createPortal(
4028
+ /* @__PURE__ */ jsxs(
4029
+ "div",
4030
+ {
4031
+ ref: toolbarRef,
4032
+ role: "toolbar",
4033
+ "aria-label": "Formatting options",
4034
+ onMouseDown: (e) => e.preventDefault(),
4035
+ style: { top: position.top, left: position.left },
4036
+ className: "tw-absolute tw-z-[1060] tw-flex tw--translate-y-full tw-items-center tw-gap-0.5 tw-rounded-lg tw-border tw-border-neutral-200 tw-bg-white tw-px-1.5 tw-py-1 tw-shadow-lg",
4037
+ children: [
4038
+ /* @__PURE__ */ jsx(BlockTypeDropdown, { editor, blockType }),
4039
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
4040
+ /* @__PURE__ */ jsx(
4041
+ ToolbarButton,
4042
+ {
4043
+ active: isBold,
4044
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold"),
4045
+ tooltip: "Bold (Ctrl+B)",
4046
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "bold"] })
4047
+ }
4048
+ ),
4049
+ /* @__PURE__ */ jsx(
4050
+ ToolbarButton,
4051
+ {
4052
+ active: isItalic,
4053
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic"),
4054
+ tooltip: "Italic (Ctrl+I)",
4055
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "italic"] })
4056
+ }
4057
+ ),
4058
+ /* @__PURE__ */ jsx(
4059
+ ToolbarButton,
4060
+ {
4061
+ active: isUnderline,
4062
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline"),
4063
+ tooltip: "Underline (Ctrl+U)",
4064
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "underline"] })
4065
+ }
4066
+ ),
4067
+ /* @__PURE__ */ jsx(
4068
+ ToolbarButton,
4069
+ {
4070
+ active: isStrikethrough,
4071
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough"),
4072
+ tooltip: "Strikethrough",
4073
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "strikethrough"] })
4074
+ }
4075
+ ),
4076
+ /* @__PURE__ */ jsx(
4077
+ ToolbarButton,
4078
+ {
4079
+ active: isCode,
4080
+ onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code"),
4081
+ tooltip: "Inline Code",
4082
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "code"] })
4083
+ }
4084
+ ),
4085
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
4086
+ /* @__PURE__ */ jsx(LinkPanel, { editor, isLink }),
4087
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
4088
+ /* @__PURE__ */ jsx(
4089
+ ToolbarButton,
4090
+ {
4091
+ active: blockType === "bullet",
4092
+ onClick: () => {
4093
+ if (blockType === "bullet") {
4094
+ editor.dispatchCommand(REMOVE_LIST_COMMAND, void 0);
4095
+ } else {
4096
+ editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, void 0);
4097
+ }
4098
+ },
4099
+ tooltip: "Bullet List",
4100
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "list-ul"] })
4101
+ }
4102
+ ),
4103
+ /* @__PURE__ */ jsx(
4104
+ ToolbarButton,
4105
+ {
4106
+ active: blockType === "number",
4107
+ onClick: () => {
4108
+ if (blockType === "number") {
4109
+ editor.dispatchCommand(REMOVE_LIST_COMMAND, void 0);
4110
+ } else {
4111
+ editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, void 0);
4112
+ }
4113
+ },
4114
+ tooltip: "Numbered List",
4115
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "list-ol"] })
4116
+ }
4117
+ ),
4118
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
4119
+ /* @__PURE__ */ jsx(AlignmentDropdown, { editor, alignment }),
4120
+ /* @__PURE__ */ jsx(ToolbarDivider, {}),
4121
+ /* @__PURE__ */ jsx(
4122
+ ToolbarButton,
4123
+ {
4124
+ active: blockType === "quote",
4125
+ onClick: () => {
4126
+ editor.update(() => {
4127
+ const selection = $getSelection();
4128
+ if (!$isRangeSelection(selection)) return;
4129
+ const anchorNode = selection.anchor.getNode();
4130
+ const element = $getNearestBlockElementAncestorOrThrow(anchorNode);
4131
+ const newNode = blockType === "quote" ? $createParagraphNode() : $createQuoteNode();
4132
+ element.getChildren().forEach((child) => newNode.append(child));
4133
+ element.replace(newNode);
4134
+ });
4135
+ },
4136
+ tooltip: "Quote",
4137
+ children: /* @__PURE__ */ jsx(Icon, { icon: ["far", "block-quote"] })
4138
+ }
4139
+ ),
4140
+ /* @__PURE__ */ jsx(
4141
+ ToolbarButton,
4142
+ {
4143
+ active: blockType === "code",
4144
+ onClick: () => {
4145
+ editor.update(() => {
4146
+ const selection = $getSelection();
4147
+ if (!$isRangeSelection(selection)) return;
4148
+ const anchorNode = selection.anchor.getNode();
4149
+ const element = $getNearestBlockElementAncestorOrThrow(anchorNode);
4150
+ const newNode = blockType === "code" ? $createParagraphNode() : $createCodeNode();
4151
+ element.getChildren().forEach((child) => newNode.append(child));
4152
+ element.replace(newNode);
4153
+ });
4154
+ },
4155
+ tooltip: "Code Block",
4156
+ children: /* @__PURE__ */ jsx(Icon, { icon: "square-code" })
4157
+ }
4158
+ )
4159
+ ]
4160
+ }
4161
+ ),
4162
+ document.body
4163
+ );
4164
+ };
4165
+
4166
+ // src/components/MarkdownEditor/theme.ts
4167
+ var editorTheme = {
4168
+ link: "tw-cursor-pointer !tw-text-secondary-500 tw-underline",
4169
+ text: {
4170
+ bold: "tw-font-bold",
4171
+ italic: "tw-italic",
4172
+ strikethrough: "tw-line-through",
4173
+ underline: "tw-underline",
4174
+ code: "tw-rounded tw-bg-neutral-100 tw-px-1 tw-py-0.5 tw-font-mono tw-text-[0.85em]"
4175
+ },
4176
+ list: {
4177
+ ol: "!tw-list-decimal",
4178
+ ul: "!tw-list-disc",
4179
+ checklist: "!tw-list-none !tw-pl-0",
4180
+ listitemChecked: [
4181
+ "tw-relative !tw-pl-6 tw-list-none tw-outline-none tw-line-through tw-text-neutral-400",
4182
+ 'before:tw-content-[""] before:tw-absolute before:tw-left-0 before:tw-top-[3px]',
4183
+ "before:tw-size-4 before:tw-rounded before:tw-border before:tw-border-solid",
4184
+ "before:tw-bg-secondary-500 before:tw-border-secondary-500 before:tw-cursor-pointer",
4185
+ 'after:tw-content-[""] after:tw-absolute after:tw-left-[5.5px] after:tw-top-[5.5px]',
4186
+ "after:tw-w-1 after:tw-h-2 after:tw-border-white after:tw-border-solid",
4187
+ "after:tw-border-r-[1.5px] after:tw-border-b-[1.5px] after:tw-border-t-0 after:tw-border-l-0",
4188
+ "after:tw-rotate-45"
4189
+ ].join(" "),
4190
+ listitemUnchecked: [
4191
+ "tw-relative !tw-pl-6 tw-list-none tw-outline-none",
4192
+ 'before:tw-content-[""] before:tw-absolute before:tw-left-0 before:tw-top-[3px]',
4193
+ "before:tw-size-4 before:tw-rounded before:tw-border before:tw-border-solid",
4194
+ "before:tw-border-neutral-200 before:tw-bg-white before:tw-cursor-pointer"
4195
+ ].join(" ")
4196
+ }
4197
+ };
4198
+ var EDITOR_NODES = [
4199
+ ImageNode,
4200
+ MermaidNode,
4201
+ HeadingNode,
4202
+ QuoteNode,
4203
+ ListNode,
4204
+ ListItemNode,
4205
+ CodeNode,
4206
+ LinkNode,
4207
+ HorizontalRuleNode
4208
+ ];
4209
+ var MarkdownEditor = ({
4210
+ value,
4211
+ onChange,
4212
+ readOnly = false,
4213
+ placeholder,
4214
+ autoFocus = false,
4215
+ disabled = false,
4216
+ onSave,
4217
+ onCancel,
4218
+ onImageUpload,
4219
+ className,
4220
+ imageRenderer,
4221
+ showToolbar = false
4222
+ }) => {
4223
+ const editable = !readOnly && !disabled;
4224
+ const [initialConfig] = useState(() => ({
4225
+ namespace: "MarkdownEditor",
4226
+ theme: editorTheme,
4227
+ nodes: EDITOR_NODES,
4228
+ onError: (error) => {
4229
+ console.error("[MarkdownEditor] uncaught editor error", error);
4230
+ },
4231
+ editable,
4232
+ editorState: () => {
4233
+ $convertFromMarkdownString(preprocessMarkdown(value), CUSTOM_TRANSFORMERS);
4234
+ }
4235
+ }));
4236
+ return /* @__PURE__ */ jsx(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx(ImageRendererProvider, { value: imageRenderer ?? null, children: /* @__PURE__ */ jsxs("div", { className: cn("tw-prose", className), children: [
4237
+ showToolbar && editable && /* @__PURE__ */ jsx(ToolbarPlugin, {}),
4238
+ /* @__PURE__ */ jsx(
4239
+ "div",
4240
+ {
4241
+ className: cn(
4242
+ "tw-relative tw-rounded-md tw-p-2 tw-transition-colors",
4243
+ editable && "tw-cursor-text hover:tw-bg-neutral-50 focus-within:tw-ring-2 focus-within:tw-ring-secondary-500/40"
4244
+ ),
4245
+ children: /* @__PURE__ */ jsx(
4246
+ RichTextPlugin,
4247
+ {
4248
+ contentEditable: /* @__PURE__ */ jsx(
4249
+ ContentEditable,
4250
+ {
4251
+ className: "tw-min-h-[100px] tw-outline-none",
4252
+ "aria-placeholder": placeholder ?? "",
4253
+ placeholder: placeholder ? /* @__PURE__ */ jsx("div", { className: "tw-pointer-events-none tw-absolute tw-left-2 tw-top-[calc(0.5rem+0.35em)] tw-select-none tw-text-neutral-400", children: placeholder }) : /* @__PURE__ */ jsx("div", {})
4254
+ }
4255
+ ),
4256
+ ErrorBoundary: LexicalErrorBoundary
4257
+ }
4258
+ )
4259
+ }
4260
+ ),
4261
+ /* @__PURE__ */ jsx(HistoryPlugin, {}),
4262
+ /* @__PURE__ */ jsx(LinkPlugin, {}),
4263
+ /* @__PURE__ */ jsx(ClickableLinkPlugin, { newTab: true }),
4264
+ /* @__PURE__ */ jsx(ListPlugin, {}),
4265
+ /* @__PURE__ */ jsx(CheckListPlugin, {}),
4266
+ /* @__PURE__ */ jsx(HorizontalRulePlugin, {}),
4267
+ /* @__PURE__ */ jsx(TabIndentationPlugin, {}),
4268
+ /* @__PURE__ */ jsx(MarkdownShortcutPlugin, { transformers: CUSTOM_TRANSFORMERS }),
4269
+ /* @__PURE__ */ jsx(MarkdownSyncPlugin, { value, editable, onChange }),
4270
+ /* @__PURE__ */ jsx(ImagePastePlugin, { onImageUpload }),
4271
+ /* @__PURE__ */ jsx(KeyboardPlugin, { onSave, onCancel }),
4272
+ autoFocus && /* @__PURE__ */ jsx(AutoFocusPlugin, {})
4273
+ ] }) }) });
4274
+ };
4275
+
4276
+ export { MarkdownEditor };
4277
+ //# sourceMappingURL=markdown-editor.js.map
4278
+ //# sourceMappingURL=markdown-editor.js.map