@keboola/design 9.0.0 → 10.1.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.
Files changed (84) hide show
  1. package/AGENTS.md +117 -40
  2. package/COMPONENT-API.md +31 -9
  3. package/README.md +3 -3
  4. package/dist/MermaidDiagram-EOKJHQQV.js +10 -0
  5. package/dist/MermaidDiagram-EOKJHQQV.js.map +1 -0
  6. package/dist/charts.d.ts +31 -2
  7. package/dist/charts.js +6 -9
  8. package/dist/charts.js.map +1 -1
  9. package/dist/chunk-63NSN2VL.js +274 -0
  10. package/dist/chunk-63NSN2VL.js.map +1 -0
  11. package/dist/{rjsf.cjs → chunk-6FPEI4EM.js} +1560 -5712
  12. package/dist/chunk-6FPEI4EM.js.map +1 -0
  13. package/dist/chunk-7PUUHEJQ.js +1313 -0
  14. package/dist/chunk-7PUUHEJQ.js.map +1 -0
  15. package/dist/chunk-BOHNXTMM.js +606 -0
  16. package/dist/chunk-BOHNXTMM.js.map +1 -0
  17. package/dist/{testing.cjs → chunk-C3L3TBBT.js} +33 -164
  18. package/dist/chunk-C3L3TBBT.js.map +1 -0
  19. package/dist/chunk-CTCFYWJC.js +407 -0
  20. package/dist/chunk-CTCFYWJC.js.map +1 -0
  21. package/dist/chunk-ESBL3IPF.js +23 -0
  22. package/dist/chunk-ESBL3IPF.js.map +1 -0
  23. package/dist/chunk-IJTHFNNJ.js +261 -0
  24. package/dist/chunk-IJTHFNNJ.js.map +1 -0
  25. package/dist/chunk-JP7PNHLH.js +40 -0
  26. package/dist/chunk-JP7PNHLH.js.map +1 -0
  27. package/dist/chunk-KPNAW5MU.js +229 -0
  28. package/dist/chunk-KPNAW5MU.js.map +1 -0
  29. package/dist/chunk-L37JJ6MR.js +152 -0
  30. package/dist/chunk-L37JJ6MR.js.map +1 -0
  31. package/dist/chunk-Q7NWXLCT.js +90 -0
  32. package/dist/chunk-Q7NWXLCT.js.map +1 -0
  33. package/dist/chunk-SYIEF644.js +1016 -0
  34. package/dist/chunk-SYIEF644.js.map +1 -0
  35. package/dist/chunk-VMFSRV5H.js +16 -0
  36. package/dist/chunk-VMFSRV5H.js.map +1 -0
  37. package/dist/chunk-VPPM7UUQ.js +47 -0
  38. package/dist/chunk-VPPM7UUQ.js.map +1 -0
  39. package/dist/chunk-XV3UUOYF.js +845 -0
  40. package/dist/chunk-XV3UUOYF.js.map +1 -0
  41. package/dist/editors.d.ts +53 -5
  42. package/dist/editors.js +85 -2097
  43. package/dist/editors.js.map +1 -1
  44. package/dist/icons.d.ts +29 -8
  45. package/dist/icons.js +2 -361
  46. package/dist/icons.js.map +1 -1
  47. package/dist/index.d.ts +735 -426
  48. package/dist/index.js +5029 -13796
  49. package/dist/index.js.map +1 -1
  50. package/dist/markdown-editor.js +41 -3426
  51. package/dist/markdown-editor.js.map +1 -1
  52. package/dist/mermaid.js +8 -1129
  53. package/dist/mermaid.js.map +1 -1
  54. package/dist/rjsf.js +97 -9240
  55. package/dist/rjsf.js.map +1 -1
  56. package/dist/styles.css +1 -1
  57. package/dist/testing.js +5 -357
  58. package/dist/testing.js.map +1 -1
  59. package/package.json +29 -74
  60. package/src/styles.css +60 -3
  61. package/src/theme.css +1 -0
  62. package/dist/charts.cjs +0 -268
  63. package/dist/charts.cjs.map +0 -1
  64. package/dist/charts.d.cts +0 -181
  65. package/dist/constants-D3gaMY-W.d.cts +0 -39
  66. package/dist/editors.cjs +0 -2456
  67. package/dist/editors.cjs.map +0 -1
  68. package/dist/editors.d.cts +0 -141
  69. package/dist/icons.cjs +0 -23888
  70. package/dist/icons.cjs.map +0 -1
  71. package/dist/icons.d.cts +0 -20
  72. package/dist/index.cjs +0 -24817
  73. package/dist/index.cjs.map +0 -1
  74. package/dist/index.d.cts +0 -10413
  75. package/dist/markdown-editor.cjs +0 -4636
  76. package/dist/markdown-editor.cjs.map +0 -1
  77. package/dist/markdown-editor.d.cts +0 -75
  78. package/dist/mermaid.cjs +0 -1138
  79. package/dist/mermaid.cjs.map +0 -1
  80. package/dist/mermaid.d.cts +0 -15
  81. package/dist/rjsf.cjs.map +0 -1
  82. package/dist/rjsf.d.cts +0 -55
  83. package/dist/testing.cjs.map +0 -1
  84. package/dist/testing.d.cts +0 -25
package/dist/mermaid.cjs DELETED
@@ -1,1138 +0,0 @@
1
- 'use strict';
2
-
3
- var react = require('react');
4
- var beautifulMermaid = require('beautiful-mermaid');
5
- var colors = require('@keboola/tailwind-config/colors');
6
- var reactDom = require('react-dom');
7
- var DOMPurify = require('dompurify');
8
- var reactSlot = require('@radix-ui/react-slot');
9
- var lucideReact = require('lucide-react');
10
- var clsx = require('clsx');
11
- var tailwindMerge = require('tailwind-merge');
12
- var reactTooltip = require('@radix-ui/react-tooltip');
13
- var classVarianceAuthority = require('class-variance-authority');
14
- var brandRegistry = require('@keboola/brand-registry');
15
- var jsxRuntime = require('react/jsx-runtime');
16
-
17
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
-
19
- var colors__default = /*#__PURE__*/_interopDefault(colors);
20
- var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
21
-
22
- // src/blocks/MermaidDiagram/MermaidDiagram.tsx
23
- var twMerge = tailwindMerge.extendTailwindMerge({
24
- prefix: "tw"
25
- });
26
- var cn = (...classes) => twMerge(clsx.clsx(...classes));
27
-
28
- // src/utils/copyToClipboard.ts
29
- var copyToClipboard = (text) => {
30
- return navigator.clipboard.writeText(text);
31
- };
32
-
33
- // src/constants/keyCodes.ts
34
- var keyCodes = {
35
- ENTER: "Enter",
36
- SPACE: " "
37
- };
38
-
39
- // src/components/ThemeProvider/utils.ts
40
- var createTheme = (brand) => ({
41
- id: brand.id,
42
- name: brand.name,
43
- shell: brand.shell,
44
- logo: brand.logo
45
- });
46
-
47
- // src/components/ThemeProvider/defaults.ts
48
- [brandRegistry.keboolaLegacySidebar.id, brandRegistry.keboolaLegacyTopnav.id];
49
- var DEFAULT_COLOR_SCHEME = "light";
50
- var DEFAULT_BRAND_ID = "design-system";
51
- var defaultBrand = {
52
- id: DEFAULT_BRAND_ID,
53
- name: "Design System",
54
- shell: "sidebar"};
55
- var defaultTheme = createTheme(defaultBrand);
56
-
57
- // src/components/ThemeProvider/context.tsx
58
- var noop = () => void 0;
59
- var defaultContext = {
60
- scheme: DEFAULT_COLOR_SCHEME,
61
- resolvedScheme: DEFAULT_COLOR_SCHEME,
62
- setScheme: noop,
63
- brandId: defaultTheme.id,
64
- setBrand: noop,
65
- themes: [defaultTheme],
66
- currentTheme: defaultTheme
67
- };
68
- react.createContext(defaultContext);
69
- var ArgoDesignContext = react.createContext(true);
70
- var useArgoDesign = () => react.use(ArgoDesignContext);
71
- var tooltipVariants = classVarianceAuthority.cva(
72
- [
73
- "tailwindcss-preflight",
74
- "tw:inline-block",
75
- "tw:break-anywhere",
76
- "tw:max-h-96",
77
- "tw:overflow-y-auto",
78
- "tw:z-[1060]",
79
- // legacy (dark) chrome — default
80
- "tw:rounded",
81
- "tw:bg-neutral-800",
82
- "tw:text-white",
83
- // argo chrome overrides — semantic floating-panel tokens
84
- "tw:data-[argo=true]:rounded-2xl",
85
- "tw:data-[argo=true]:border",
86
- "tw:data-[argo=true]:border-solid",
87
- "tw:data-[argo=true]:border-border",
88
- "tw:data-[argo=true]:bg-popover",
89
- "tw:data-[argo=true]:text-popover-foreground",
90
- "tw:data-[argo=true]:shadow-md",
91
- // argo open animation
92
- "tw:data-[argo=true]:data-[state=delayed-open]:animate-in",
93
- "tw:data-[argo=true]:data-[state=instant-open]:animate-in",
94
- "tw:data-[argo=true]:data-[state=delayed-open]:fade-in-0",
95
- "tw:data-[argo=true]:data-[state=instant-open]:fade-in-0",
96
- "tw:data-[argo=true]:data-[state=delayed-open]:zoom-in-95",
97
- "tw:data-[argo=true]:data-[state=instant-open]:zoom-in-95",
98
- // argo closed animation
99
- "tw:data-[argo=true]:data-[state=closed]:animate-out",
100
- "tw:data-[argo=true]:data-[state=closed]:fade-out-0",
101
- "tw:data-[argo=true]:data-[state=closed]:zoom-out-95",
102
- // argo position animation
103
- "tw:data-[argo=true]:data-[side=bottom]:slide-in-from-top-2",
104
- "tw:data-[argo=true]:data-[side=left]:slide-in-from-right-2",
105
- "tw:data-[argo=true]:data-[side=right]:slide-in-from-left-2",
106
- "tw:data-[argo=true]:data-[side=top]:slide-in-from-bottom-2"
107
- ],
108
- {
109
- defaultVariants: {
110
- variant: "action"
111
- },
112
- variants: {
113
- variant: {
114
- action: [
115
- "tw:max-w-fit",
116
- "tw:px-3",
117
- "tw:py-2",
118
- "tw:text-center",
119
- "tw:text-xs",
120
- "tw:font-medium",
121
- // Legacy chrome uppercases the action tooltip; the Keboola V2 brand
122
- // (`data-brand="keboola"`) renders it in standard case instead.
123
- "tw:uppercase",
124
- "tw:tracking-wider",
125
- "tw:[[data-brand=keboola]_&]:normal-case",
126
- "tw:[[data-brand=keboola]_&]:tracking-normal"
127
- ],
128
- explanatory: [
129
- "tw:max-w-80",
130
- "tw:px-4",
131
- "tw:py-3",
132
- "tw:text-left",
133
- "tw:text-sm",
134
- "tw:font-normal"
135
- ]
136
- }
137
- }
138
- }
139
- );
140
- var TooltipContent = ({
141
- className,
142
- variant,
143
- keepOpenOnPointerDownOutside = false,
144
- children,
145
- onPointerDownOutside,
146
- sideOffset = 8,
147
- collisionPadding = 8,
148
- hideWhenDetached = true,
149
- placement = "right",
150
- ...rest
151
- }) => {
152
- const renderArgo = useArgoDesign();
153
- const handlePointerDownOutside = (event) => {
154
- if (keepOpenOnPointerDownOutside) event.preventDefault();
155
- onPointerDownOutside?.(event);
156
- };
157
- return /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
158
- reactTooltip.Content,
159
- {
160
- ...rest,
161
- "data-tooltip-content": renderArgo ? void 0 : true,
162
- "data-argo": renderArgo,
163
- sideOffset,
164
- collisionPadding,
165
- onPointerDownOutside: handlePointerDownOutside,
166
- className: tooltipVariants({ className, variant }),
167
- hideWhenDetached,
168
- side: placement,
169
- children
170
- }
171
- ) });
172
- };
173
- var DELAY_SHOW_TOOLTIP = 300;
174
- var TooltipRoot = ({ children, delayDuration = DELAY_SHOW_TOOLTIP, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Root, { ...rest, delayDuration, children });
175
- var TooltipTrigger = ({
176
- ref,
177
- children,
178
- className,
179
- keepOpenOnClick = false,
180
- onClick,
181
- onPointerDown,
182
- asChild,
183
- ...rest
184
- }) => {
185
- const handleClick = (event) => {
186
- if (keepOpenOnClick) event.preventDefault();
187
- onClick?.(event);
188
- };
189
- const handlePointerDown = (event) => {
190
- if (keepOpenOnClick) event.preventDefault();
191
- onPointerDown?.(event);
192
- };
193
- return /* @__PURE__ */ jsxRuntime.jsx(
194
- reactTooltip.Trigger,
195
- {
196
- ...rest,
197
- asChild: true,
198
- ref,
199
- className: cn("tailwindcss-preflight", className),
200
- onClick: handleClick,
201
- onPointerDown: handlePointerDown,
202
- children: asChild ? children : (
203
- // Default-mode trigger wraps children in a span so Radix has a
204
- // single DOM element to attach handlers to. `tailwindcss-preflight`
205
- // (merged in via Slot) activates Tailwind's preflight inside the
206
- // span, which sets `svg { display: block }` — without an inline-flex
207
- // container that would stack any bare Lucide icon onto its own
208
- // line. `tw:inline-flex tw:items-center` keeps icon + text aligned.
209
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tw:inline-flex tw:items-center", children })
210
- )
211
- }
212
- );
213
- };
214
- var ACTION_TOOLTIP_LIMIT = 30;
215
- var Tooltip = ({
216
- tooltip,
217
- children,
218
- className,
219
- keepOpenOnTriggerClick = false,
220
- variant,
221
- placement = "right",
222
- forceHide = false,
223
- forceShow = false,
224
- delayDuration,
225
- // trigger props
226
- triggerAsChild = false
227
- }) => {
228
- const [open, setOpen] = react.useState(false);
229
- const resolvedVariant = (() => {
230
- if (!!variant) return variant;
231
- if (typeof tooltip === "string" && tooltip.length > ACTION_TOOLTIP_LIMIT) return "explanatory";
232
- return "action";
233
- })();
234
- const isActionVariant = resolvedVariant === "action";
235
- const handleKeyUp = (event) => {
236
- if (![keyCodes.ENTER, keyCodes.SPACE].includes(event.key)) return;
237
- event.stopPropagation();
238
- };
239
- return /* @__PURE__ */ jsxRuntime.jsxs(
240
- TooltipRoot,
241
- {
242
- open: !!tooltip && (open || forceShow) && !forceHide,
243
- onOpenChange: setOpen,
244
- delayDuration,
245
- disableHoverableContent: isActionVariant,
246
- children: [
247
- /* @__PURE__ */ jsxRuntime.jsx(
248
- TooltipTrigger,
249
- {
250
- asChild: triggerAsChild,
251
- keepOpenOnClick: keepOpenOnTriggerClick,
252
- onKeyUp: handleKeyUp,
253
- children
254
- }
255
- ),
256
- /* @__PURE__ */ jsxRuntime.jsx(
257
- TooltipContent,
258
- {
259
- className,
260
- variant: resolvedVariant,
261
- placement,
262
- keepOpenOnPointerDownOutside: keepOpenOnTriggerClick,
263
- children: tooltip
264
- }
265
- )
266
- ]
267
- }
268
- );
269
- };
270
- Tooltip.Root = TooltipRoot;
271
- Tooltip.Content = TooltipContent;
272
- Tooltip.Trigger = TooltipTrigger;
273
- var variants = classVarianceAuthority.cva(
274
- [
275
- "tailwindcss-preflight",
276
- "tw:group/button",
277
- "tw:border-box",
278
- // layout
279
- "tw:relative",
280
- "tw:flex",
281
- "tw:items-center",
282
- "tw:justify-center",
283
- "tw:gap-2",
284
- // text — chrome weight/tracking are brand-overridable tokens
285
- // (`--font-weight-medium` / `--letter-spacing-chrome`). Casing: standard case is
286
- // the default; only legacy brands (`keboola-legacy-*`) uppercase the chrome, so
287
- // modern brands (incl. Keboola V2) read naturally. Mirrors the V2 standard-case
288
- // treatment shipped for Tooltip/Badge (PR 7629).
289
- "tw:text-xs",
290
- "tw:leading-5",
291
- "tw:font-medium",
292
- "tw:[[data-brand^=keboola-legacy]_&]:tracking-chrome",
293
- "tw:[[data-brand^=keboola-legacy]_&]:uppercase",
294
- // border — legacy (non-argo) chrome uses a fixed radius, not the brand token.
295
- "tw:rounded",
296
- "tw:border",
297
- "tw:border-transparent",
298
- // styling
299
- "tw:shadow-none",
300
- "tw:[a]:cursor-pointer",
301
- // explicitly set for anchor
302
- "tw:focus-visible:outline",
303
- "tw:focus-visible:outline-1",
304
- "tw:focus-visible:-outline-offset-1",
305
- "tw:focus-visible:outline-ring",
306
- "tw:focus-visible:ring-4",
307
- "tw:focus-visible:ring-ring/30",
308
- // disabled
309
- "tw:disabled:opacity-40",
310
- "tw:disabled:cursor-not-allowed",
311
- // anchor support
312
- "tw:!no-underline",
313
- "tw:aria-disabled:opacity-40",
314
- "tw:aria-disabled:cursor-not-allowed",
315
- "tw:[&_svg]:shrink-0"
316
- ],
317
- {
318
- defaultVariants: {
319
- size: "medium",
320
- variant: "primary",
321
- block: false
322
- },
323
- variants: {
324
- block: {
325
- true: ["tw:w-full"]
326
- },
327
- variant: {
328
- primary: [
329
- "tw:text-white",
330
- "tw:bg-primary-500",
331
- "tw:focus:text-white",
332
- "tw:hover:text-white",
333
- "tw:hover:not-disabled:bg-primary-600",
334
- "tw:active:not-disabled:bg-primary-800",
335
- // anchor disabled override
336
- "tw:aria-disabled:!bg-primary-500"
337
- ],
338
- secondary: [
339
- "tw:text-white",
340
- "tw:bg-secondary-500",
341
- "tw:focus:text-white",
342
- "tw:hover:text-white",
343
- "tw:hover:not-disabled:bg-secondary-700",
344
- "tw:active:not-disabled:bg-secondary-800",
345
- // anchor disabled override
346
- "tw:aria-disabled:!bg-secondary-500"
347
- ],
348
- danger: [
349
- "tw:text-white",
350
- "tw:bg-error-500",
351
- "tw:focus:text-white",
352
- "tw:hover:text-white",
353
- "tw:hover:not-disabled:bg-error-600",
354
- "tw:active:not-disabled:bg-error-700",
355
- // anchor disabled override
356
- "tw:aria-disabled:!bg-error-500"
357
- ],
358
- invisible: [
359
- "tw:text-neutral-800",
360
- "tw:bg-transparent",
361
- "tw:focus:text-neutral-800",
362
- "tw:hover:not-disabled:bg-neutral-100",
363
- "tw:hover:text-neutral-800",
364
- "tw:active:not-disabled:bg-neutral-150",
365
- // contrasting icon on hover/active
366
- "tw:[&_svg]:text-neutral-400",
367
- "tw:hover:not-disabled:[&_svg]:text-secondary-600",
368
- "tw:active:not-disabled:[&_svg]:text-secondary-600",
369
- // anchor disabled override
370
- "tw:aria-disabled:!bg-transparent"
371
- ],
372
- outline: [
373
- "tw:text-neutral-800",
374
- "tw:bg-white",
375
- // border
376
- "tw:!border-neutral-200",
377
- "tw:hover:text-neutral-800",
378
- "tw:focus:text-neutral-800",
379
- "tw:hover:not-disabled:!border-neutral-300",
380
- "tw:hover:not-disabled:bg-neutral-100",
381
- "tw:active:not-disabled:bg-neutral-200",
382
- // contrasting icon hover, same as invisible
383
- "tw:[&_svg]:text-neutral-400",
384
- "tw:not-disabled:hover:[&_svg]:text-secondary-600",
385
- "tw:active:not-disabled:[&_svg]:text-secondary-600",
386
- // anchor disabled override
387
- "tw:aria-disabled:!bg-white",
388
- "tw:aria-disabled:!border-neutral-200"
389
- ],
390
- inline: [
391
- "tw:text-neutral-800",
392
- "tw:bg-transparent",
393
- "tw:rounded-full",
394
- "tw:[&_svg]:text-neutral-400",
395
- "tw:not-disabled:hover:[&_svg]:text-secondary-600",
396
- "tw:not-disabled:focus:[&_svg]:text-secondary-600"
397
- ]
398
- },
399
- size: {
400
- medium: [
401
- "tw:max-h-10",
402
- "tw:min-h-10",
403
- "tw:px-4",
404
- "tw:py-2.5",
405
- 'tw:[&_svg:not([class*="tw:size-"])]:size-4'
406
- ],
407
- small: [
408
- "tw:max-h-8",
409
- "tw:min-h-8",
410
- "tw:px-4",
411
- "tw:py-1.5",
412
- 'tw:[&_svg:not([class*="tw:size-"])]:size-4'
413
- ],
414
- large: [
415
- "tw:max-h-12",
416
- "tw:min-h-12",
417
- "tw:px-4",
418
- "tw:py-3.5",
419
- 'tw:[&_svg:not([class*="tw:size-"])]:size-4'
420
- ],
421
- "icon-lg": ["tw:size-12", "tw:p-0", 'tw:[&_svg:not([class*="tw:size-"])]:size-6'],
422
- icon: ["tw:size-10", "tw:p-0", 'tw:[&_svg:not([class*="tw:size-"])]:size-4'],
423
- "icon-sm": ["tw:size-8", "tw:p-0", 'tw:[&_svg:not([class*="tw:size-"])]:size-4'],
424
- "icon-xs": ["tw:size-6", "tw:p-0", 'tw:[&_svg:not([class*="tw:size-"])]:size-4'],
425
- "icon-2xs": [
426
- "tw:!inline-flex",
427
- "tw:size-5",
428
- "tw:max-h-5",
429
- 'tw:[&_svg:not([class*="tw:size-"])]:size-3'
430
- ],
431
- "icon-3xs": ["tw:h-fit", "tw:w-fit", 'tw:[&_svg:not([class*="tw:size-"])]:size-4']
432
- }
433
- }
434
- }
435
- );
436
- var argoVariants = classVarianceAuthority.cva(
437
- [
438
- "tailwindcss-preflight",
439
- // layout
440
- "tw:relative",
441
- "tw:inline-flex",
442
- "tw:items-center",
443
- "tw:justify-center",
444
- "tw:whitespace-nowrap",
445
- "tw:gap-2",
446
- // border
447
- "tw:border",
448
- "tw:border-transparent",
449
- "tw:rounded-[var(--radius-lg,0.25rem)]",
450
- // text
451
- "tw:font-medium",
452
- "tw:select-none",
453
- // focus visible
454
- "tw:!outline-hidden",
455
- "tw:focus-visible:ring-2",
456
- // disabled
457
- "tw:disabled:cursor-not-allowed",
458
- "tw:disabled:opacity-50",
459
- "tw:active:opacity-60",
460
- "tw:transition-all",
461
- "tw:bg-clip-padding",
462
- // anchor support
463
- "tw:!no-underline",
464
- "tw:aria-disabled:cursor-not-allowed",
465
- "tw:aria-disabled:opacity-50",
466
- // icon
467
- "tw:shrink-0",
468
- "tw:[&_svg]:pointer-events-none",
469
- "tw:[&_svg]:shrink-0",
470
- "tw:[&_svg:not([class*='tw:size-'])]:size-4"
471
- ],
472
- {
473
- defaultVariants: {
474
- variant: "primary",
475
- size: "medium"
476
- },
477
- variants: {
478
- block: {
479
- true: ["tw:w-full"]
480
- },
481
- variant: {
482
- primary: [
483
- "tw:bg-primary",
484
- "tw:text-primary-foreground",
485
- "tw:[a]:hover:bg-primary/80",
486
- "tw:hover:not-disabled:bg-primary/90",
487
- "tw:hover:text-primary-foreground",
488
- "tw:focus:text-primary-foreground",
489
- "tw:focus-visible:border-primary",
490
- "tw:focus-visible:ring-ring/50"
491
- ],
492
- secondary: [
493
- "tw:bg-primary/10",
494
- "tw:text-primary",
495
- "tw:hover:not-disabled:bg-primary/20",
496
- "tw:focus-visible:border-primary",
497
- "tw:focus-visible:ring-ring/50"
498
- ],
499
- // should be called "destructive" by Figma
500
- danger: [
501
- "tw:bg-destructive",
502
- "tw:text-destructive-foreground",
503
- "tw:hover:text-destructive-foreground",
504
- "tw:focus:text-destructive-foreground",
505
- "tw:focus-visible:border-destructive",
506
- "tw:focus-visible:ring-destructive/20"
507
- ],
508
- outline: [
509
- "tw:!border-input",
510
- "tw:bg-background",
511
- // Semantic base text color so the label/icon flips in dark mode
512
- // (matches `invisible`); previously unset → inherited a fixed dark color.
513
- "tw:text-foreground",
514
- // Hover follows the brand primary (translucent tint), matching the
515
- // `secondary` variant — not the fixed `accent` blue.
516
- "tw:hover:not-disabled:bg-primary/10",
517
- "tw:hover:not-disabled:text-primary",
518
- "tw:hover:active:bg-background",
519
- "tw:focus-visible:!border-primary",
520
- "tw:focus-visible:ring-ring/50"
521
- ],
522
- // should be called "ghost" by Figma
523
- invisible: [
524
- "tw:bg-transparent",
525
- "tw:text-foreground",
526
- "tw:hover:not-disabled:bg-primary/10",
527
- "tw:hover:not-disabled:text-primary",
528
- "tw:hover:not-disabled:border-primary/10",
529
- "tw:focus-visible:ring-ring/50"
530
- ],
531
- // should be called "link" by Figma
532
- inline: [
533
- "tw:bg-transparent",
534
- "tw:text-primary",
535
- "tw:hover:underline",
536
- "tw:hover:active:bg-transparent",
537
- "tw:focus-visible:ring-ring/50"
538
- ]
539
- },
540
- size: {
541
- // should be called "default" by Figma
542
- medium: ["tw:max-h-9", "tw:py-2", "tw:px-4", "tw:text-sm"],
543
- // should be called "small" by Figma
544
- small: ["tw:max-h-8", "tw:py-2", "tw:px-3", "tw:text-xs"],
545
- // should be called "large" by Figma
546
- large: ["tw:max-h-10", "tw:py-2.5", "tw:px-6", "tw:text-sm"],
547
- "icon-lg": ["tw:size-10"],
548
- icon: ["tw:size-9"],
549
- "icon-sm": ["tw:size-8"],
550
- // unsupported in ARGO, remove when old design is gone
551
- "icon-xs": [],
552
- "icon-2xs": [],
553
- "icon-3xs": []
554
- }
555
- }
556
- }
557
- );
558
- var Button = ({
559
- ref,
560
- children,
561
- disabled = false,
562
- className,
563
- type = "button",
564
- isLoading = false,
565
- asChild = false,
566
- onClick,
567
- variant = "primary",
568
- size = "medium",
569
- block = false,
570
- ...buttonProps
571
- }) => {
572
- const renderArgo = useArgoDesign();
573
- const Comp = asChild ? reactSlot.Root : "button";
574
- const isIconOnly = String(size).startsWith("icon");
575
- const classNames = renderArgo ? argoVariants({ variant, size, block, className }) : variants({ size, variant, block, className });
576
- const handleClick = (event) => {
577
- const isAnchor = event.currentTarget.tagName === "A";
578
- if (isAnchor && disabled) {
579
- event.preventDefault();
580
- return;
581
- }
582
- onClick?.(event);
583
- };
584
- return /* @__PURE__ */ jsxRuntime.jsxs(
585
- Comp,
586
- {
587
- ...buttonProps,
588
- ref,
589
- disabled,
590
- "aria-disabled": disabled,
591
- "data-variant": variant,
592
- "data-icon-only": isIconOnly,
593
- type,
594
- onClick: handleClick,
595
- className: cn(classNames),
596
- children: [
597
- isLoading && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "tw:size-4 tw:shrink-0 tw:animate-spin" }),
598
- /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slottable, { children: isLoading && isIconOnly ? null : children })
599
- ]
600
- }
601
- );
602
- };
603
- var Clipboard2 = ({
604
- ref,
605
- text: textProp,
606
- children,
607
- tooltip = "Copy to Clipboard",
608
- tooltipPlacement = "top",
609
- tooltipVariant: tooltipVariantProp = "action",
610
- asChild = false,
611
- onClick,
612
- className,
613
- ...restButtonProps
614
- }) => {
615
- const [isTooltipOpen, setIsTooltipOpen] = react.useState(false);
616
- const [state, setState] = react.useState("ready");
617
- const text = typeof textProp === "function" ? textProp() : textProp;
618
- const copy = async (text2) => {
619
- try {
620
- if (!document.hasFocus()) window.focus();
621
- await copyToClipboard(text2);
622
- setState("copied");
623
- } catch {
624
- setState("error");
625
- }
626
- };
627
- const handleOnClick = (event) => {
628
- setIsTooltipOpen(true);
629
- if (text && state === "ready") void copy(text);
630
- onClick?.(event);
631
- };
632
- const handleOnOpenChange = (open) => {
633
- if (!open && state !== "ready") setState("ready");
634
- setIsTooltipOpen(open);
635
- };
636
- const tooltipContent = (() => {
637
- if (!text) return "Nothing to copy";
638
- if (state === "error") return "Failed to copy";
639
- if (state === "copied") return "Copied to Clipboard";
640
- return tooltip;
641
- })();
642
- const tooltipVariant = state === "ready" && !!text ? tooltipVariantProp : "action";
643
- const hasTooltipContent = tooltipContent !== null && tooltipContent !== void 0;
644
- return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip.Root, { open: isTooltipOpen, onOpenChange: handleOnOpenChange, children: [
645
- /* @__PURE__ */ jsxRuntime.jsx(
646
- Tooltip.Trigger,
647
- {
648
- ...restButtonProps,
649
- asChild,
650
- keepOpenOnClick: true,
651
- onClick: handleOnClick,
652
- className: cn("tw:cursor-pointer", className),
653
- ref,
654
- children: children ?? text
655
- }
656
- ),
657
- hasTooltipContent && /* @__PURE__ */ jsxRuntime.jsx(
658
- Tooltip.Content,
659
- {
660
- keepOpenOnPointerDownOutside: true,
661
- placement: tooltipPlacement,
662
- variant: tooltipVariant,
663
- children: tooltipContent
664
- }
665
- )
666
- ] });
667
- };
668
- var DEFAULT_ICON = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, {});
669
- var DEFAULT_ARIA_LABEL = "Copy";
670
- var ClipboardButton = ({
671
- // clipboard props
672
- text,
673
- tooltip,
674
- tooltipPlacement,
675
- tooltipVariant,
676
- // button props
677
- icon = DEFAULT_ICON,
678
- variant = "outline",
679
- children,
680
- ...rest
681
- }) => {
682
- const defaultAriaLabel = typeof tooltip === "string" && tooltip.trim() ? tooltip : DEFAULT_ARIA_LABEL;
683
- const ariaLabel = rest["aria-label"] ?? (children == null ? defaultAriaLabel : void 0);
684
- return /* @__PURE__ */ jsxRuntime.jsx(
685
- Clipboard2,
686
- {
687
- asChild: true,
688
- tooltip,
689
- tooltipPlacement,
690
- tooltipVariant,
691
- text,
692
- children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { ...rest, "aria-label": ariaLabel, variant, disabled: !text, children: [
693
- icon,
694
- children
695
- ] })
696
- }
697
- );
698
- };
699
- var MIN_SCALE = 0.5;
700
- var MAX_SCALE = 3;
701
- var ZOOM_STEP = 0.1;
702
- var ZoomableSvg = ({
703
- html,
704
- copyText,
705
- className,
706
- allowForeignObject,
707
- renderActions
708
- }) => {
709
- const safeHtml = react.useMemo(
710
- () => DOMPurify__default.default.sanitize(html, {
711
- USE_PROFILES: { svg: true, svgFilters: true },
712
- ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
713
- }),
714
- [html, allowForeignObject]
715
- );
716
- const containerRef = react.useRef(null);
717
- const [scale, setScale] = react.useState(1);
718
- const [translate, setTranslate] = react.useState({ x: 0, y: 0 });
719
- const [isFullscreen, setIsFullscreen] = react.useState(false);
720
- react.useEffect(() => {
721
- if (!isFullscreen) return;
722
- const onKeyDown = (e) => {
723
- if (e.key === "Escape") {
724
- e.stopPropagation();
725
- setIsFullscreen(false);
726
- }
727
- };
728
- document.addEventListener("keydown", onKeyDown, { capture: true });
729
- return () => document.removeEventListener("keydown", onKeyDown, { capture: true });
730
- }, [isFullscreen]);
731
- const dragRef = react.useRef(null);
732
- react.useEffect(() => {
733
- const el = containerRef.current;
734
- if (!el) return;
735
- const onWheel = (e) => {
736
- if (!e.ctrlKey && !e.metaKey) return;
737
- e.preventDefault();
738
- const delta = e.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;
739
- setScale((s) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s + delta)));
740
- };
741
- el.addEventListener("wheel", onWheel, { passive: false });
742
- return () => el.removeEventListener("wheel", onWheel);
743
- }, [isFullscreen]);
744
- const didDragRef = react.useRef(false);
745
- const handleMouseDown = react.useCallback(
746
- (e) => {
747
- if (e.button !== 0) return;
748
- e.preventDefault();
749
- didDragRef.current = false;
750
- dragRef.current = {
751
- startX: e.clientX,
752
- startY: e.clientY,
753
- startTx: translate.x,
754
- startTy: translate.y
755
- };
756
- },
757
- [translate]
758
- );
759
- const handleMouseMove = react.useCallback((e) => {
760
- if (!dragRef.current) return;
761
- didDragRef.current = true;
762
- setTranslate({
763
- x: dragRef.current.startTx + e.clientX - dragRef.current.startX,
764
- y: dragRef.current.startTy + e.clientY - dragRef.current.startY
765
- });
766
- }, []);
767
- const handleMouseUp = react.useCallback(() => {
768
- dragRef.current = null;
769
- }, []);
770
- const handleReset = react.useCallback(() => {
771
- setScale(1);
772
- setTranslate({ x: 0, y: 0 });
773
- }, []);
774
- const isZoomed = Math.abs(scale - 1) > 1e-3 || translate.x !== 0 || translate.y !== 0;
775
- const handleClick = react.useCallback((e) => {
776
- if (didDragRef.current) {
777
- e.stopPropagation();
778
- }
779
- }, []);
780
- const stopPropagation = react.useCallback((e) => {
781
- e.stopPropagation();
782
- }, []);
783
- const diagramContent = /* @__PURE__ */ jsxRuntime.jsxs(
784
- "div",
785
- {
786
- role: "presentation",
787
- className: cn("tw:group/zoom tw:relative", isFullscreen && "tw:h-full"),
788
- onClick: handleClick,
789
- children: [
790
- /* @__PURE__ */ jsxRuntime.jsx(
791
- "div",
792
- {
793
- role: "presentation",
794
- ref: containerRef,
795
- className: cn(
796
- "tw:overflow-hidden tw:cursor-grab tw:active:cursor-grabbing tw:p-3",
797
- isFullscreen && "tw:h-full"
798
- ),
799
- onMouseDown: handleMouseDown,
800
- onMouseMove: handleMouseMove,
801
- onMouseUp: handleMouseUp,
802
- onMouseLeave: handleMouseUp,
803
- children: /* @__PURE__ */ jsxRuntime.jsx(
804
- "div",
805
- {
806
- className: cn(
807
- "tw:flex tw:justify-center tw:origin-center",
808
- isFullscreen && "tw:h-full tw:[&>svg]:h-full"
809
- ),
810
- style: { transform: `translate(${translate.x}px, ${translate.y}px) scale(${scale})` },
811
- dangerouslySetInnerHTML: { __html: safeHtml }
812
- }
813
- )
814
- }
815
- ),
816
- /* @__PURE__ */ jsxRuntime.jsxs(
817
- "div",
818
- {
819
- role: "presentation",
820
- className: "tw:absolute tw:right-1 tw:top-1 tw:flex tw:gap-1 tw:opacity-0 tw:transition-opacity tw:focus-within:opacity-100 tw:group-hover/zoom:opacity-100",
821
- onClick: stopPropagation,
822
- children: [
823
- isZoomed && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { tooltip: "Reset zoom", placement: "top", triggerAsChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "small", variant: "outline", onClick: handleReset, children: "Reset" }) }),
824
- copyText && /* @__PURE__ */ jsxRuntime.jsx(ClipboardButton, { text: copyText, tooltip: "Copy code", size: "icon-sm", variant: "outline" }),
825
- renderActions?.(safeHtml),
826
- /* @__PURE__ */ jsxRuntime.jsx(
827
- Tooltip,
828
- {
829
- tooltip: isFullscreen ? "Exit fullscreen" : "Fullscreen",
830
- placement: "top",
831
- triggerAsChild: true,
832
- children: /* @__PURE__ */ jsxRuntime.jsx(
833
- Button,
834
- {
835
- size: "icon-sm",
836
- variant: "outline",
837
- "aria-label": isFullscreen ? "Exit fullscreen" : "Fullscreen",
838
- onClick: () => setIsFullscreen((f) => !f),
839
- children: isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { className: "tw:size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { className: "tw:size-4" })
840
- }
841
- )
842
- }
843
- )
844
- ]
845
- }
846
- )
847
- ]
848
- }
849
- );
850
- if (isFullscreen) {
851
- return reactDom.createPortal(
852
- /* @__PURE__ */ jsxRuntime.jsx(
853
- "div",
854
- {
855
- role: "presentation",
856
- "data-testid": "zoomable-svg-fullscreen",
857
- className: "tw:fixed tw:inset-0 tw:z-[1060] tw:bg-muted tw:p-4 tailwindcss-preflight",
858
- onClick: stopPropagation,
859
- children: diagramContent
860
- }
861
- ),
862
- document.body
863
- );
864
- }
865
- return /* @__PURE__ */ jsxRuntime.jsx(
866
- "div",
867
- {
868
- className: cn(
869
- "tw:overflow-hidden tw:rounded-md tw:border tw:border-border tw:bg-muted",
870
- className
871
- ),
872
- children: diagramContent
873
- }
874
- );
875
- };
876
- var HEIGHT_CLASS_NAME = {
877
- xxs: "tw:h-3 tw:rounded",
878
- xs: "tw:h-4 tw:rounded",
879
- sm: "tw:h-5 tw:rounded",
880
- md: "tw:h-6 tw:rounded-md",
881
- lg: "tw:h-8 tw:rounded-lg",
882
- xl: "tw:h-10 tw:rounded-lg",
883
- "2xl": "tw:h-12 tw:rounded-lg"
884
- };
885
- var ANIMATION_CLASS_NAME = cn(
886
- // base styles
887
- "tw:relative",
888
- "tw:overflow-hidden",
889
- "tw:pointer-events-none",
890
- "tw:bg-skeleton",
891
- // before
892
- 'tw:before:content-[""]',
893
- "tw:before:opacity-100",
894
- "tw:before:absolute",
895
- "tw:before:inset-0",
896
- "tw:before:-translate-x-full",
897
- "tw:before:animate-[shimmer_2s_infinite]",
898
- "tw:before:bg-gradient-to-r",
899
- "tw:before:from-transparent",
900
- "tw:before:to-transparent",
901
- "tw:before:via-white/40"
902
- );
903
- var Skeleton = ({ height = "md", className, count = 1 }) => {
904
- const prefixId = react.useId();
905
- const keys = Array.from({ length: count }, (_, i) => `${prefixId}-${i}`);
906
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: keys.map((key) => /* @__PURE__ */ jsxRuntime.jsx(
907
- "div",
908
- {
909
- "data-skeleton": "true",
910
- className: cn(HEIGHT_CLASS_NAME[height], ANIMATION_CLASS_NAME, className)
911
- },
912
- key
913
- )) });
914
- };
915
- var DiagramSkeleton = () => /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(Skeleton, { className: "tw:h-40" }) });
916
-
917
- // src/blocks/MermaidDiagram/svgTransforms.ts
918
- var HTML_TAG = /<[^>]+>/g;
919
- var FOREIGN_OBJECT = /(<foreignObject\b[^>]*>)([\s\S]*?)(<\/foreignObject>)/g;
920
- var ROOT_SVG_TAG = /^(\s*<svg\b)([^>]*)(>)/i;
921
- var flattenForeignObjectLabels = (svg) => svg.replace(FOREIGN_OBJECT, (_match, open, inner, close) => {
922
- const text = inner.replace(HTML_TAG, " ").replace(/\s+/g, " ").trim();
923
- return `${open}${text}${close}`;
924
- });
925
- var STYLE_ATTR = /\s+style="([^"]*)"/i;
926
- var makeResponsive = (svgString) => {
927
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
928
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
929
- return svgString.replace(ROOT_SVG_TAG, (_match, open, attrs, close) => {
930
- const existingStyle = attrs.match(STYLE_ATTR)?.[1] ?? "";
931
- const styleDecls = existingStyle.replace(/max-width:\s*[^;"]*;?\s*/gi, "").replace(/\s+/g, " ").trim().replace(/;$/, "");
932
- let nextAttrs = attrs.replace(/\s+width="[^"]*"/i, "").replace(/\s+height="[^"]*"/i, "").replace(STYLE_ATTR, "");
933
- nextAttrs += ' width="100%"';
934
- const styleParts = [styleDecls, vbWidth ? `max-width: ${vbWidth}px` : ""].filter(Boolean).join("; ");
935
- if (styleParts) nextAttrs += ` style="${styleParts}"`;
936
- return `${open}${nextAttrs}${close}`;
937
- });
938
- };
939
- var PRIMARY_FALLBACK_CHANNELS = "31 143 255";
940
- var resolvePrimary = () => {
941
- const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--primary").trim() || PRIMARY_FALLBACK_CHANNELS;
942
- return `rgb(${channels})`;
943
- };
944
- var mermaidPromise = null;
945
- var registerLucideIconPack = (m) => {
946
- m.registerIconPacks([
947
- {
948
- name: "lucide",
949
- loader: () => import('@iconify-json/lucide/icons.json').then((mod) => mod.default)
950
- }
951
- ]);
952
- };
953
- var getMermaid = () => {
954
- if (!mermaidPromise) {
955
- mermaidPromise = import('mermaid').then((m) => {
956
- registerLucideIconPack(m.default);
957
- m.default.initialize({
958
- startOnLoad: false,
959
- securityLevel: "strict",
960
- theme: "base",
961
- themeVariables: {
962
- primaryColor: colors__default.default.blue[100],
963
- primaryTextColor: colors__default.default.neutral[800],
964
- primaryBorderColor: colors__default.default.blue[700],
965
- secondaryColor: colors__default.default.white,
966
- secondaryTextColor: colors__default.default.neutral[800],
967
- secondaryBorderColor: colors__default.default.neutral[150],
968
- tertiaryColor: colors__default.default.warning[100],
969
- tertiaryTextColor: colors__default.default.neutral[800],
970
- tertiaryBorderColor: colors__default.default.warning[500],
971
- lineColor: colors__default.default.neutral[300],
972
- textColor: colors__default.default.neutral[800],
973
- mainBkg: colors__default.default.blue[100],
974
- nodeBorder: colors__default.default.blue[700],
975
- clusterBkg: colors__default.default.white,
976
- clusterBorder: colors__default.default.neutral[150],
977
- titleColor: colors__default.default.neutral[800],
978
- edgeLabelBackground: colors__default.default.white,
979
- nodeTextColor: colors__default.default.neutral[800],
980
- actorBorder: colors__default.default.blue[700],
981
- actorBkg: colors__default.default.blue[100],
982
- actorTextColor: colors__default.default.neutral[800],
983
- actorLineColor: colors__default.default.neutral[300],
984
- signalColor: colors__default.default.neutral[800],
985
- signalTextColor: colors__default.default.neutral[800],
986
- labelBoxBkgColor: colors__default.default.blue[100],
987
- labelBoxBorderColor: colors__default.default.blue[700],
988
- labelTextColor: colors__default.default.neutral[800],
989
- loopTextColor: colors__default.default.neutral[800],
990
- noteBorderColor: colors__default.default.warning[500],
991
- noteBkgColor: colors__default.default.warning[100],
992
- noteTextColor: colors__default.default.neutral[800],
993
- sectionBkgColor: colors__default.default.blue[100],
994
- altSectionBkgColor: colors__default.default.white,
995
- sectionBkgColor2: colors__default.default.neutral[100],
996
- taskBorderColor: colors__default.default.blue[700],
997
- taskBkgColor: colors__default.default.blue[100],
998
- taskTextColor: colors__default.default.neutral[800],
999
- taskTextDarkColor: colors__default.default.neutral[800],
1000
- taskTextLightColor: colors__default.default.neutral[800],
1001
- activeTaskBorderColor: resolvePrimary(),
1002
- activeTaskBkgColor: colors__default.default.blue[200],
1003
- doneTaskBorderColor: colors__default.default.green[600],
1004
- doneTaskBkgColor: colors__default.default.green[100],
1005
- critBorderColor: colors__default.default.error[500],
1006
- critBkgColor: colors__default.default.error[100],
1007
- fontFamily: "Inter, system-ui, sans-serif",
1008
- fontSize: "14px"
1009
- }
1010
- });
1011
- return m;
1012
- }).catch((err) => {
1013
- mermaidPromise = null;
1014
- throw err;
1015
- });
1016
- }
1017
- return mermaidPromise;
1018
- };
1019
- var stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1020
- var hasIconSyntax = (code) => /@\{[^}]*\bicon\s*:/.test(code) || /\b(?:icon|service|group)\b[^\n(]*\(\s*[\w-]+:/.test(code) || /\bfa[bslr]?:fa-/.test(code);
1021
- var tryFastRender = (code) => {
1022
- if (hasIconSyntax(code)) return null;
1023
- try {
1024
- return stripFontImports(
1025
- beautifulMermaid.renderMermaidSVG(code, {
1026
- bg: colors__default.default.white,
1027
- fg: colors__default.default.neutral[800],
1028
- transparent: true,
1029
- font: "Inter, system-ui, sans-serif"
1030
- })
1031
- );
1032
- } catch (err) {
1033
- console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1034
- return null;
1035
- }
1036
- };
1037
- var RENDER_DEBOUNCE_MS = 300;
1038
- var svgCache = /* @__PURE__ */ new Map();
1039
- var resolveSyncSvg = (code) => {
1040
- const cached = svgCache.get(code);
1041
- if (cached) return cached;
1042
- const fast = tryFastRender(code);
1043
- if (fast) svgCache.set(code, fast);
1044
- return fast;
1045
- };
1046
- var MermaidDiagram = ({ code, renderActions }) => {
1047
- const id = react.useId();
1048
- const [svg, setSvg] = react.useState(() => resolveSyncSvg(code));
1049
- const [renderFailed, setRenderFailed] = react.useState(false);
1050
- const debounceRef = react.useRef(null);
1051
- const renderIdRef = react.useRef(0);
1052
- const [prevCode, setPrevCode] = react.useState(code);
1053
- if (code !== prevCode) {
1054
- setPrevCode(code);
1055
- setSvg(resolveSyncSvg(code));
1056
- setRenderFailed(false);
1057
- }
1058
- react.useEffect(() => {
1059
- if (svgCache.has(code)) return;
1060
- const currentRenderId = ++renderIdRef.current;
1061
- if (debounceRef.current) {
1062
- clearTimeout(debounceRef.current);
1063
- }
1064
- debounceRef.current = setTimeout(() => {
1065
- getMermaid().then(async (mermaidModule) => {
1066
- if (renderIdRef.current !== currentRenderId) return;
1067
- const rendererId = `mermaid-${id.replaceAll(":", "")}`;
1068
- const container = document.createElement("div");
1069
- container.style.visibility = "hidden";
1070
- container.style.position = "absolute";
1071
- container.style.top = "-9999px";
1072
- container.style.width = "900px";
1073
- document.body.appendChild(container);
1074
- try {
1075
- const result = await mermaidModule.default.render(rendererId, code, container);
1076
- if (renderIdRef.current === currentRenderId && result) {
1077
- const svgOutput = flattenForeignObjectLabels(result.svg);
1078
- svgCache.set(code, svgOutput);
1079
- setSvg(svgOutput);
1080
- setRenderFailed(false);
1081
- }
1082
- } finally {
1083
- container.remove();
1084
- }
1085
- }).catch((err) => {
1086
- if (renderIdRef.current === currentRenderId) {
1087
- console.error("[MermaidDiagram] fallback failed:", err);
1088
- setSvg(null);
1089
- setRenderFailed(true);
1090
- }
1091
- });
1092
- }, RENDER_DEBOUNCE_MS);
1093
- const timer = debounceRef.current;
1094
- const renderId = renderIdRef;
1095
- return () => {
1096
- renderId.current++;
1097
- if (timer) {
1098
- clearTimeout(timer);
1099
- }
1100
- };
1101
- }, [code, id]);
1102
- const processedSvg = svg ? makeResponsive(svg) : null;
1103
- if (renderFailed) {
1104
- return /* @__PURE__ */ jsxRuntime.jsx(
1105
- "pre",
1106
- {
1107
- className: cn(
1108
- "tw:my-3 tw:overflow-auto tw:whitespace-pre-wrap tw:break-all",
1109
- "tw:py-3 tw:px-4",
1110
- "tw:bg-neutral-50",
1111
- "tw:rounded-md tw:text-neutral-400",
1112
- "tw:text-sm tw:font-mono"
1113
- ),
1114
- children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: code })
1115
- }
1116
- );
1117
- }
1118
- if (processedSvg) {
1119
- return /* @__PURE__ */ jsxRuntime.jsx(
1120
- ZoomableSvg,
1121
- {
1122
- html: processedSvg,
1123
- copyText: `\`\`\`mermaid
1124
- ${code}
1125
- \`\`\``,
1126
- className: "tw:my-3",
1127
- allowForeignObject: true,
1128
- renderActions
1129
- },
1130
- code
1131
- );
1132
- }
1133
- return /* @__PURE__ */ jsxRuntime.jsx(DiagramSkeleton, {});
1134
- };
1135
-
1136
- exports.MermaidDiagram = MermaidDiagram;
1137
- //# sourceMappingURL=mermaid.cjs.map
1138
- //# sourceMappingURL=mermaid.cjs.map