@keboola/design 6.3.0 → 6.5.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.
@@ -7,6 +7,7 @@ import { cva } from 'class-variance-authority';
7
7
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
8
8
  import * as lucide_react_star from 'lucide-react';
9
9
  import { Root as Root$2, Slottable } from '@radix-ui/react-slot';
10
+ import { createPortal } from 'react-dom';
10
11
  import DOMPurify from 'dompurify';
11
12
  import { renderMermaidSVG } from 'beautiful-mermaid';
12
13
  import colors from '@keboola/tailwind-config/colors';
@@ -32,7 +33,6 @@ import { HeadingNode, QuoteNode, $isHeadingNode, $isQuoteNode, $createQuoteNode,
32
33
  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
34
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
34
35
  import { toast as toast$1 } from 'sonner';
35
- import { createPortal } from 'react-dom';
36
36
  import { $getNearestBlockElementAncestorOrThrow } from '@lexical/utils';
37
37
  import * as DropdownMenuPrimitive3 from '@radix-ui/react-dropdown-menu';
38
38
  import { Root as Root$1, Group, Trigger as Trigger$1 } from '@radix-ui/react-dropdown-menu';
@@ -349,6 +349,7 @@ var init_Tooltip = __esm({
349
349
  placement = "right",
350
350
  forceHide = false,
351
351
  forceShow = false,
352
+ delayDuration,
352
353
  // trigger props
353
354
  triggerAsChild = false
354
355
  }) => {
@@ -368,6 +369,7 @@ var init_Tooltip = __esm({
368
369
  {
369
370
  open: !!tooltip && (open || forceShow) && !forceHide,
370
371
  onOpenChange: setOpen,
372
+ delayDuration,
371
373
  disableHoverableContent: isActionVariant,
372
374
  children: [
373
375
  /* @__PURE__ */ jsx(
@@ -604,6 +606,7 @@ var init_Keboola = __esm({
604
606
  width: size,
605
607
  height: size,
606
608
  viewBox: "0 0 300 512",
609
+ overflow: "visible",
607
610
  fill: color,
608
611
  className: cn("lucide", className),
609
612
  ...rest,
@@ -617,18 +620,49 @@ var init_Keboola = __esm({
617
620
  Keboola.displayName = "Keboola";
618
621
  }
619
622
  });
623
+ var Microsoft;
624
+ var init_Microsoft = __esm({
625
+ "src/icons/Microsoft.tsx"() {
626
+ init_utils2();
627
+ Microsoft = forwardRef(
628
+ ({ size = 24, className, children, ...rest }, ref) => /* @__PURE__ */ jsxs(
629
+ "svg",
630
+ {
631
+ ref,
632
+ xmlns: "http://www.w3.org/2000/svg",
633
+ width: size,
634
+ height: size,
635
+ viewBox: "0 0 21 21",
636
+ fill: "none",
637
+ className: cn("lucide", className),
638
+ ...rest,
639
+ children: [
640
+ /* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "10", height: "10", fill: "#F25022" }),
641
+ /* @__PURE__ */ jsx("rect", { x: "11", y: "0", width: "10", height: "10", fill: "#7FBA00" }),
642
+ /* @__PURE__ */ jsx("rect", { x: "0", y: "11", width: "10", height: "10", fill: "#00A4EF" }),
643
+ /* @__PURE__ */ jsx("rect", { x: "11", y: "11", width: "10", height: "10", fill: "#FFB900" }),
644
+ children
645
+ ]
646
+ }
647
+ )
648
+ );
649
+ Microsoft.displayName = "Microsoft";
650
+ }
651
+ });
620
652
 
621
653
  // src/icons/index.ts
622
654
  var icons_exports = {};
623
655
  __export(icons_exports, {
624
656
  Google: () => Google,
625
- Keboola: () => Keboola
657
+ Keboola: () => Keboola,
658
+ Microsoft: () => Microsoft
626
659
  });
627
660
  var init_icons = __esm({
628
661
  "src/icons/index.ts"() {
629
662
  __reExport(icons_exports, lucide_react_star);
630
663
  init_Google();
631
664
  init_Keboola();
665
+ init_Microsoft();
632
666
  }
633
667
  });
634
668
  var variants, argoVariants;
@@ -1155,10 +1189,13 @@ var init_ZoomableSvg = __esm({
1155
1189
  MIN_SCALE = 0.5;
1156
1190
  MAX_SCALE = 3;
1157
1191
  ZOOM_STEP = 0.1;
1158
- ZoomableSvg = ({ html, copyText, className }) => {
1192
+ ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
1159
1193
  const safeHtml = useMemo(
1160
- () => DOMPurify.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
1161
- [html]
1194
+ () => DOMPurify.sanitize(html, {
1195
+ USE_PROFILES: { svg: true, svgFilters: true },
1196
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
1197
+ }),
1198
+ [html, allowForeignObject]
1162
1199
  );
1163
1200
  const containerRef = useRef(null);
1164
1201
  const [scale, setScale] = useState(1);
@@ -1187,7 +1224,7 @@ var init_ZoomableSvg = __esm({
1187
1224
  };
1188
1225
  el.addEventListener("wheel", onWheel, { passive: false });
1189
1226
  return () => el.removeEventListener("wheel", onWheel);
1190
- }, []);
1227
+ }, [isFullscreen]);
1191
1228
  const didDragRef = useRef(false);
1192
1229
  const handleMouseDown = useCallback(
1193
1230
  (e) => {
@@ -1294,14 +1331,18 @@ var init_ZoomableSvg = __esm({
1294
1331
  }
1295
1332
  );
1296
1333
  if (isFullscreen) {
1297
- return /* @__PURE__ */ jsx(
1298
- "div",
1299
- {
1300
- role: "presentation",
1301
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1302
- onClick: stopPropagation,
1303
- children: diagramContent
1304
- }
1334
+ return createPortal(
1335
+ /* @__PURE__ */ jsx(
1336
+ "div",
1337
+ {
1338
+ role: "presentation",
1339
+ "data-testid": "zoomable-svg-fullscreen",
1340
+ className: "tailwindcss-preflight tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1341
+ onClick: stopPropagation,
1342
+ children: diagramContent
1343
+ }
1344
+ ),
1345
+ document.body
1305
1346
  );
1306
1347
  }
1307
1348
  return /* @__PURE__ */ jsx(
@@ -1325,26 +1366,64 @@ var init_ZoomableSvg2 = __esm({
1325
1366
  }
1326
1367
  });
1327
1368
 
1369
+ // src/blocks/MermaidDiagram/svgTransforms.ts
1370
+ var HTML_TAG, FOREIGN_OBJECT, ROOT_SVG_TAG, flattenForeignObjectLabels, STYLE_ATTR, makeResponsive;
1371
+ var init_svgTransforms = __esm({
1372
+ "src/blocks/MermaidDiagram/svgTransforms.ts"() {
1373
+ HTML_TAG = /<[^>]+>/g;
1374
+ FOREIGN_OBJECT = /(<foreignObject\b[^>]*>)([\s\S]*?)(<\/foreignObject>)/g;
1375
+ ROOT_SVG_TAG = /^(\s*<svg\b)([^>]*)(>)/i;
1376
+ flattenForeignObjectLabels = (svg) => svg.replace(FOREIGN_OBJECT, (_match, open, inner, close) => {
1377
+ const text = inner.replace(HTML_TAG, " ").replace(/\s+/g, " ").trim();
1378
+ return `${open}${text}${close}`;
1379
+ });
1380
+ STYLE_ATTR = /\s+style="([^"]*)"/i;
1381
+ makeResponsive = (svgString) => {
1382
+ const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1383
+ const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1384
+ return svgString.replace(ROOT_SVG_TAG, (_match, open, attrs, close) => {
1385
+ const existingStyle = attrs.match(STYLE_ATTR)?.[1] ?? "";
1386
+ const styleDecls = existingStyle.replace(/max-width:\s*[^;"]*;?\s*/gi, "").replace(/\s+/g, " ").trim().replace(/;$/, "");
1387
+ let nextAttrs = attrs.replace(/\s+width="[^"]*"/i, "").replace(/\s+height="[^"]*"/i, "").replace(STYLE_ATTR, "");
1388
+ nextAttrs += ' width="100%"';
1389
+ const styleParts = [styleDecls, vbWidth ? `max-width: ${vbWidth}px` : ""].filter(Boolean).join("; ");
1390
+ if (styleParts) nextAttrs += ` style="${styleParts}"`;
1391
+ return `${open}${nextAttrs}${close}`;
1392
+ });
1393
+ };
1394
+ }
1395
+ });
1396
+
1328
1397
  // src/blocks/MermaidDiagram/MermaidDiagram.tsx
1329
1398
  var MermaidDiagram_exports = {};
1330
1399
  __export(MermaidDiagram_exports, {
1331
1400
  MermaidDiagram: () => MermaidDiagram
1332
1401
  });
1333
- var PRIMARY_FALLBACK_CHANNELS, resolvePrimary, mermaidPromise, getMermaid, stripFontImports, tryFastRender, makeResponsive, RENDER_DEBOUNCE_MS, svgCache, resolveSyncSvg, MermaidDiagram;
1402
+ var PRIMARY_FALLBACK_CHANNELS, resolvePrimary, mermaidPromise, registerLucideIconPack, getMermaid, stripFontImports, hasIconSyntax, tryFastRender, RENDER_DEBOUNCE_MS, svgCache, resolveSyncSvg, MermaidDiagram;
1334
1403
  var init_MermaidDiagram = __esm({
1335
1404
  "src/blocks/MermaidDiagram/MermaidDiagram.tsx"() {
1336
1405
  init_Skeleton();
1337
1406
  init_ZoomableSvg2();
1338
1407
  init_utils2();
1408
+ init_svgTransforms();
1339
1409
  PRIMARY_FALLBACK_CHANNELS = "31 143 255";
1340
1410
  resolvePrimary = () => {
1341
1411
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1342
1412
  return `rgb(${channels})`;
1343
1413
  };
1344
1414
  mermaidPromise = null;
1415
+ registerLucideIconPack = (m) => {
1416
+ m.registerIconPacks([
1417
+ {
1418
+ name: "lucide",
1419
+ loader: () => import('@iconify-json/lucide/icons.json').then((mod) => mod.default)
1420
+ }
1421
+ ]);
1422
+ };
1345
1423
  getMermaid = () => {
1346
1424
  if (!mermaidPromise) {
1347
1425
  mermaidPromise = import('mermaid').then((m) => {
1426
+ registerLucideIconPack(m.default);
1348
1427
  m.default.initialize({
1349
1428
  startOnLoad: false,
1350
1429
  securityLevel: "strict",
@@ -1408,7 +1487,9 @@ var init_MermaidDiagram = __esm({
1408
1487
  return mermaidPromise;
1409
1488
  };
1410
1489
  stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1490
+ hasIconSyntax = (code) => /@\{[^}]*\bicon\s*:/.test(code) || /\b(?:icon|service|group)\b[^\n(]*\(\s*[\w-]+:/.test(code) || /\bfa[bslr]?:fa-/.test(code);
1411
1491
  tryFastRender = (code) => {
1492
+ if (hasIconSyntax(code)) return null;
1412
1493
  try {
1413
1494
  return stripFontImports(
1414
1495
  renderMermaidSVG(code, {
@@ -1418,27 +1499,11 @@ var init_MermaidDiagram = __esm({
1418
1499
  font: "Inter, system-ui, sans-serif"
1419
1500
  })
1420
1501
  );
1421
- } catch {
1502
+ } catch (err) {
1503
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1422
1504
  return null;
1423
1505
  }
1424
1506
  };
1425
- makeResponsive = (svgString) => {
1426
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1427
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1428
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1429
- if (!vbWidth) return result;
1430
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1431
- if (hasStyle) {
1432
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1433
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1434
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1435
- return `${pre} style="${combined}"`;
1436
- });
1437
- } else {
1438
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1439
- }
1440
- return result;
1441
- };
1442
1507
  RENDER_DEBOUNCE_MS = 300;
1443
1508
  svgCache = /* @__PURE__ */ new Map();
1444
1509
  resolveSyncSvg = (code) => {
@@ -1479,8 +1544,9 @@ var init_MermaidDiagram = __esm({
1479
1544
  try {
1480
1545
  const result = await mermaidModule.default.render(rendererId, code, container);
1481
1546
  if (renderIdRef.current === currentRenderId && result) {
1482
- svgCache.set(code, result.svg);
1483
- setSvg(result.svg);
1547
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1548
+ svgCache.set(code, svgOutput);
1549
+ setSvg(svgOutput);
1484
1550
  setRenderFailed(false);
1485
1551
  }
1486
1552
  } finally {
@@ -1527,7 +1593,8 @@ var init_MermaidDiagram = __esm({
1527
1593
  copyText: `\`\`\`mermaid
1528
1594
  ${code}
1529
1595
  \`\`\``,
1530
- className: "tw-my-3"
1596
+ className: "tw-my-3",
1597
+ allowForeignObject: true
1531
1598
  },
1532
1599
  code
1533
1600
  );
@@ -1537,7 +1604,7 @@ ${code}
1537
1604
  }
1538
1605
  });
1539
1606
 
1540
- // src/components/MarkdownEditor/MarkdownEditor.tsx
1607
+ // src/blocks/MarkdownEditor/MarkdownEditor.tsx
1541
1608
  init_utils2();
1542
1609
  var ImageRendererContext = createContext(null);
1543
1610
  var ImageRendererProvider = ImageRendererContext;
@@ -1633,7 +1700,7 @@ var $isImageNode = (node) => {
1633
1700
  return node instanceof ImageNode;
1634
1701
  };
1635
1702
 
1636
- // src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1703
+ // src/blocks/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1637
1704
  init_Skeleton();
1638
1705
  var MermaidDiagram2 = lazy(
1639
1706
  () => Promise.resolve().then(() => (init_MermaidDiagram(), MermaidDiagram_exports)).then(
@@ -1716,11 +1783,7 @@ init_context();
1716
1783
 
1717
1784
  // src/components/Toast/ToastAction.tsx
1718
1785
  init_utils2();
1719
- var ToastAction = ({
1720
- ref,
1721
- className,
1722
- ...rest
1723
- }) => /* @__PURE__ */ jsx(
1786
+ var ToastAction = ({ ref, className, ...rest }) => /* @__PURE__ */ jsx(
1724
1787
  "button",
1725
1788
  {
1726
1789
  ...rest,
@@ -1751,12 +1814,7 @@ var ToastAction = ({
1751
1814
 
1752
1815
  // src/components/Toast/ToastDescription.tsx
1753
1816
  init_utils2();
1754
- var ToastDescription = ({
1755
- ref,
1756
- className,
1757
- children,
1758
- ...rest
1759
- }) => /* @__PURE__ */ jsx(
1817
+ var ToastDescription = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsx(
1760
1818
  "div",
1761
1819
  {
1762
1820
  ref,
@@ -1777,11 +1835,7 @@ var ToastDescription = ({
1777
1835
  // src/components/Toast/ToastDismiss.tsx
1778
1836
  init_icons();
1779
1837
  init_utils2();
1780
- var ToastDismiss = ({
1781
- ref,
1782
- className,
1783
- ...rest
1784
- }) => /* @__PURE__ */ jsxs(
1838
+ var ToastDismiss = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxs(
1785
1839
  "button",
1786
1840
  {
1787
1841
  ref,
@@ -1811,13 +1865,7 @@ var ToastDismiss = ({
1811
1865
 
1812
1866
  // src/components/Toast/ToastDuration.tsx
1813
1867
  init_utils2();
1814
- var ToastDuration = ({
1815
- ref,
1816
- duration,
1817
- className,
1818
- style,
1819
- ...rest
1820
- }) => /* @__PURE__ */ jsx(
1868
+ var ToastDuration = ({ ref, duration, className, style, ...rest }) => /* @__PURE__ */ jsx(
1821
1869
  "span",
1822
1870
  {
1823
1871
  ...rest,
@@ -1848,12 +1896,7 @@ var ToastDuration = ({
1848
1896
 
1849
1897
  // src/components/Toast/ToastTitle.tsx
1850
1898
  init_utils2();
1851
- var ToastTitle = ({
1852
- ref,
1853
- className,
1854
- children,
1855
- ...rest
1856
- }) => /* @__PURE__ */ jsx(
1899
+ var ToastTitle = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsx(
1857
1900
  "div",
1858
1901
  {
1859
1902
  ref,
@@ -2038,7 +2081,7 @@ toast.info = (title, options) => toast({
2038
2081
  toast.dismiss = (toastId) => toast$1.dismiss(toastId);
2039
2082
  toast.dismissAll = () => toast$1.dismiss();
2040
2083
 
2041
- // src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx
2084
+ // src/blocks/MarkdownEditor/plugins/ImagePastePlugin.tsx
2042
2085
  var ACCEPTED_IMAGE_TYPES = [
2043
2086
  "image/png",
2044
2087
  "image/jpeg",
@@ -2316,7 +2359,7 @@ var postprocessMarkdown = (markdown) => {
2316
2359
  };
2317
2360
  var unescapeMarkdownText = (markdown) => markdown.replace(/\\([*_`~\\])/g, "$1");
2318
2361
 
2319
- // src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2362
+ // src/blocks/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2320
2363
  var IMPORT_TAG = "markdown-import";
2321
2364
  var MarkdownSyncPlugin = ({
2322
2365
  value,
@@ -2362,13 +2405,9 @@ var MarkdownSyncPlugin = ({
2362
2405
  return null;
2363
2406
  };
2364
2407
 
2365
- // src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx
2408
+ // src/blocks/MarkdownEditor/plugins/ToolbarPlugin.tsx
2366
2409
  init_icons();
2367
2410
 
2368
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2369
- init_icons();
2370
- init_utils2();
2371
-
2372
2411
  // src/components/DropdownMenu/DropdownMenu.tsx
2373
2412
  init_context();
2374
2413
 
@@ -2927,11 +2966,7 @@ var DropdownMenuSubTrigger = ({ className, children, ...props }) => {
2927
2966
 
2928
2967
  // src/components/DropdownMenu/DropdownMenuTrigger.tsx
2929
2968
  init_utils2();
2930
- var DropdownMenuTrigger = ({
2931
- ref,
2932
- className,
2933
- ...props
2934
- }) => /* @__PURE__ */ jsx(
2969
+ var DropdownMenuTrigger = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(
2935
2970
  Trigger$1,
2936
2971
  {
2937
2972
  ...props,
@@ -2963,8 +2998,10 @@ DropdownMenu.RadioGroup = DropdownMenuRadioGroup;
2963
2998
  DropdownMenu.RadioItem = DropdownMenuRadioItem;
2964
2999
  DropdownMenu.ItemDescription = DropdownMenuItemDescription;
2965
3000
 
2966
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
3001
+ // src/blocks/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2967
3002
  init_Tooltip2();
3003
+ init_icons();
3004
+ init_utils2();
2968
3005
  var ALIGNMENT_OPTIONS = [
2969
3006
  { value: "left", label: "Left", icon: icons_exports.AlignLeft },
2970
3007
  { value: "center", label: "Center", icon: icons_exports.AlignCenter },
@@ -3028,11 +3065,9 @@ var AlignmentDropdown = ({
3028
3065
  )) })
3029
3066
  ] });
3030
3067
  };
3031
-
3032
- // src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx
3068
+ init_Tooltip2();
3033
3069
  init_icons();
3034
3070
  init_utils2();
3035
- init_Tooltip2();
3036
3071
  var BLOCK_TYPE_META = {
3037
3072
  paragraph: { label: "Normal", icon: icons_exports.Type, selectable: true },
3038
3073
  h1: { label: "Heading 1", icon: icons_exports.Heading1, selectable: true },
@@ -3116,76 +3151,7 @@ var BlockTypeDropdown = ({
3116
3151
  ] });
3117
3152
  };
3118
3153
 
3119
- // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
3120
- init_icons();
3121
- init_Button2();
3122
- var buttonGroupVariant = cva(
3123
- ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
3124
- {
3125
- defaultVariants: {
3126
- variant: "inline",
3127
- space: "small"
3128
- },
3129
- variants: {
3130
- variant: {
3131
- inline: [],
3132
- block: [
3133
- "tw-w-full",
3134
- "tw-flex-col",
3135
- "sm:tw-flex-row",
3136
- "[&_a]:tw-flex-1",
3137
- "[&>button:not([data-icon-only=true])]:tw-flex-1"
3138
- ]
3139
- },
3140
- space: {
3141
- "extra-small": "tw-gap-1",
3142
- "little-small": "tw-gap-2",
3143
- small: "tw-gap-3",
3144
- medium: "tw-gap-4",
3145
- large: "tw-gap-6",
3146
- compact: [
3147
- "tw-border-collapse",
3148
- "!tw-gap-0",
3149
- // ensure that focus visible outline is at the top
3150
- "[&>*:focus-visible]:!tw-z-10",
3151
- "[&>*:not(:first-child)]:tw-rounded-l-none",
3152
- "[&>*:not(:last-child)]:tw-rounded-r-none",
3153
- "[&>*:not(:last-child)]:tw-border-r-0",
3154
- "[&>*:not(:first-child)]:tw-border-l-0",
3155
- // separator
3156
- "[&>*:not(:first-child)]:before:tw-content",
3157
- "[&>*:not(:first-child)]:before:tw-absolute",
3158
- "[&>*:not(:first-child)]:before:tw-left-0",
3159
- "[&>*:not(:first-child)]:before:tw-h-full",
3160
- "[&>*:not(:first-child)]:before:tw-w-px",
3161
- "[&>*:not(:first-child)]:before:tw-bg-black/10"
3162
- ]
3163
- }
3164
- }
3165
- }
3166
- );
3167
- var ButtonGroup = ({
3168
- ref,
3169
- children,
3170
- space = "small",
3171
- className,
3172
- variant,
3173
- ...rest
3174
- }) => {
3175
- return /* @__PURE__ */ jsx(
3176
- "div",
3177
- {
3178
- ref,
3179
- ...rest,
3180
- role: "group",
3181
- "data-variant": variant,
3182
- className: buttonGroupVariant({ variant, className, space }),
3183
- children
3184
- }
3185
- );
3186
- };
3187
-
3188
- // src/components/FormGroup/FormGroup.tsx
3154
+ // src/blocks/FormGroup/FormGroup.tsx
3189
3155
  init_utils2();
3190
3156
  var FormGroupContext = createContext({
3191
3157
  state: "default"
@@ -3245,12 +3211,7 @@ var InputGroupAddon = ({
3245
3211
  // src/components/InputGroup/InputGroupButton.tsx
3246
3212
  init_utils2();
3247
3213
  init_Button2();
3248
- var InputGroupButton = ({
3249
- ref,
3250
- className,
3251
- tabIndex = -1,
3252
- ...props
3253
- }) => /* @__PURE__ */ jsx(
3214
+ var InputGroupButton = ({ ref, className, tabIndex = -1, ...props }) => /* @__PURE__ */ jsx(
3254
3215
  Button,
3255
3216
  {
3256
3217
  ...props,
@@ -3264,11 +3225,7 @@ var InputGroupButton = ({
3264
3225
 
3265
3226
  // src/components/InputGroup/InputGroupInput.tsx
3266
3227
  init_utils2();
3267
- var InputGroupInput = ({
3268
- ref,
3269
- className,
3270
- ...inputProps
3271
- }) => /* @__PURE__ */ jsx(
3228
+ var InputGroupInput = ({ ref, className, ...inputProps }) => /* @__PURE__ */ jsx(
3272
3229
  "input",
3273
3230
  {
3274
3231
  ...inputProps,
@@ -3513,8 +3470,15 @@ var inputGroupVariants = cva(
3513
3470
  "tw-border-input",
3514
3471
  "tw-text-foreground",
3515
3472
  "has-[:is(input,textarea):disabled]:tw-opacity-50",
3473
+ // readonly: keep the themed input surface/border. The base layer's fixed
3474
+ // `neutral-150` (a light grey) is correct for the legacy light chrome but
3475
+ // collides with argo's themed `foreground` text — light-on-light, invisible
3476
+ // in dark mode. Re-pin to the same `muted`/`input` tokens the editable argo
3477
+ // input uses (validated AA), so readonly stays legible in every scheme.
3478
+ "has-[:is(input,textarea)[readonly]]:tw-bg-muted",
3479
+ "has-[:is(input,textarea)[readonly]]:tw-border-input",
3516
3480
  // higher specificity than has-[:is(input,textarea):focus] — prevents focus border on readonly
3517
- "has-[:is(input,textarea)[readonly]:focus]:tw-border-neutral-150",
3481
+ "has-[:is(input,textarea)[readonly]:focus]:tw-border-input",
3518
3482
  // aria-invalid on the control surfaces the error chrome without a `state` prop — the
3519
3483
  // accessible path (uses the themeable `destructive` status token).
3520
3484
  "has-[:is(input,textarea)[aria-invalid=true]]:tw-border-destructive",
@@ -3595,6 +3559,29 @@ InputGroup.Addon = InputGroupAddon;
3595
3559
  InputGroup.Button = InputGroupButton;
3596
3560
  InputGroup.TextArea = InputGroupTextArea;
3597
3561
  InputGroup.Text = InputGroupText;
3562
+ var useControllableState = ({
3563
+ prop,
3564
+ defaultProp,
3565
+ onChange
3566
+ }) => {
3567
+ const [uncontrolled, setUncontrolled] = useState(defaultProp);
3568
+ const isControlled = prop !== void 0;
3569
+ const value = prop !== void 0 ? prop : uncontrolled;
3570
+ const valueRef = useRef(value);
3571
+ valueRef.current = value;
3572
+ const onChangeRef = useRef(onChange);
3573
+ onChangeRef.current = onChange;
3574
+ const setValue = useCallback(
3575
+ (next) => {
3576
+ const nextValue = typeof next === "function" ? next(valueRef.current) : next;
3577
+ valueRef.current = nextValue;
3578
+ if (!isControlled) setUncontrolled(nextValue);
3579
+ onChangeRef.current?.(nextValue);
3580
+ },
3581
+ [isControlled]
3582
+ );
3583
+ return [value, setValue];
3584
+ };
3598
3585
 
3599
3586
  // src/blocks/ColorInput/ColorInput.tsx
3600
3587
  init_icons();
@@ -3691,13 +3678,13 @@ var ColorInput = ({
3691
3678
  ...restInputProps
3692
3679
  }) => {
3693
3680
  const inputRef = useRef(null);
3694
- const [internalValue, setInternalValue] = useState(defaultValue ?? "");
3681
+ const [value, setValue] = useControllableState({
3682
+ // A `null` controlled value stays controlled (coerced to ''); `undefined` is uncontrolled.
3683
+ prop: valueProp === null ? "" : valueProp,
3684
+ defaultProp: defaultValue ?? "",
3685
+ onChange: onValueChange
3686
+ });
3695
3687
  const isControlled = valueProp !== void 0;
3696
- const value = isControlled ? valueProp ?? "" : internalValue;
3697
- const setValue = (nextValue) => {
3698
- if (!isControlled) setInternalValue(nextValue);
3699
- onValueChange?.(nextValue);
3700
- };
3701
3688
  const canClear = allowClear && !!value && !disabled && !readOnly;
3702
3689
  const swatchColor = coerceHexInputValue(value);
3703
3690
  const isValidSwatch = isCompleteHexColor(swatchColor);
@@ -3800,15 +3787,12 @@ var ColorInput = ({
3800
3787
  }
3801
3788
  );
3802
3789
  };
3803
- var FormGroupColorInput = ({
3804
- ref,
3805
- ...props
3806
- }) => {
3790
+ var FormGroupColorInput = ({ ref, ...props }) => {
3807
3791
  const { state } = useFormGroupContext();
3808
3792
  return /* @__PURE__ */ jsx(ColorInput, { state, ...props, ref });
3809
3793
  };
3810
3794
 
3811
- // src/components/FormGroup/FormGroupError.tsx
3795
+ // src/blocks/FormGroup/FormGroupError.tsx
3812
3796
  init_utils2();
3813
3797
  var toMessage = (entry) => typeof entry === "string" ? entry : entry?.message;
3814
3798
  var FormGroupError = ({ children, className, errors, ...rest }) => {
@@ -3895,10 +3879,7 @@ var NumberInput = ({
3895
3879
  }
3896
3880
  );
3897
3881
  };
3898
- var FormGroupNumberInput = ({
3899
- ref,
3900
- ...props
3901
- }) => {
3882
+ var FormGroupNumberInput = ({ ref, ...props }) => {
3902
3883
  const { state } = useFormGroupContext();
3903
3884
  return /* @__PURE__ */ jsx(NumberInput, { ...props, ref, state });
3904
3885
  };
@@ -3910,8 +3891,18 @@ var Textarea = ({
3910
3891
  variant,
3911
3892
  sizing,
3912
3893
  focusVariant,
3894
+ // value handling
3895
+ value: valueProp,
3896
+ defaultValue,
3897
+ onValueChange,
3913
3898
  ...rest
3914
3899
  }) => {
3900
+ const [value, setValue] = useControllableState({
3901
+ // `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled, coerced to ''.
3902
+ prop: valueProp === void 0 ? void 0 : valueProp ?? "",
3903
+ defaultProp: defaultValue ?? "",
3904
+ onChange: onValueChange
3905
+ });
3915
3906
  return /* @__PURE__ */ jsx(
3916
3907
  InputGroup,
3917
3908
  {
@@ -3920,7 +3911,7 @@ var Textarea = ({
3920
3911
  focusVariant,
3921
3912
  variant,
3922
3913
  className: containerClassName,
3923
- children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref })
3914
+ children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref, value, onValueChange: setValue })
3924
3915
  }
3925
3916
  );
3926
3917
  };
@@ -3928,12 +3919,10 @@ var FormGroupTextarea = (props) => {
3928
3919
  const { state } = useFormGroupContext();
3929
3920
  return /* @__PURE__ */ jsx(Textarea, { state, ...props });
3930
3921
  };
3931
-
3932
- // src/components/Input/Input.tsx
3933
3922
  init_icons();
3934
3923
  init_utils2();
3935
3924
 
3936
- // src/components/Input/utils.ts
3925
+ // src/blocks/TextInput/utils.ts
3937
3926
  init_utils2();
3938
3927
  var genInputTestId = (prefix = "") => {
3939
3928
  const ps = createPrefixedString(prefix);
@@ -3944,7 +3933,11 @@ var genInputTestId = (prefix = "") => {
3944
3933
  clearButton: ps`clear-button`
3945
3934
  };
3946
3935
  };
3947
- var Input = ({
3936
+ var sanitizeTextInputValue = (value) => {
3937
+ if (typeof value === "string" && value.trim() === "") return "";
3938
+ return value;
3939
+ };
3940
+ var TextInput = ({
3948
3941
  ref: forwardedRef,
3949
3942
  state = "default",
3950
3943
  sizing = "default",
@@ -3966,23 +3959,28 @@ var Input = ({
3966
3959
  focusVariant = "default",
3967
3960
  onChange,
3968
3961
  onBlur,
3969
- value,
3962
+ onValueChange,
3963
+ onValueBlur,
3964
+ value: valueProp,
3970
3965
  defaultValue,
3971
3966
  ...inputProps
3972
3967
  }) => {
3973
- const [hasUncontrolledValue, setHasUncontrolledValue] = useState(() => !!defaultValue);
3974
- const hasValue = !!value || hasUncontrolledValue;
3975
3968
  const inputRef = useRef(null);
3969
+ const [value, setValue] = useControllableState({
3970
+ // `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled and coerced
3971
+ // to a string. Whitespace-only input collapses to '' via `sanitizeTextInputValue`.
3972
+ prop: valueProp === void 0 ? void 0 : sanitizeTextInputValue(valueProp) ?? "",
3973
+ defaultProp: sanitizeTextInputValue(defaultValue) ?? "",
3974
+ onChange: onValueChange
3975
+ });
3976
3976
  const testId = genInputTestId(prefixTestId);
3977
- const isClearButtonVisible = hasValue && !disabled && !readOnly || !!onClear;
3977
+ const isClearButtonVisible = !!value && !disabled && !readOnly || !!onClear;
3978
3978
  const handleChange = (event) => {
3979
- const val = event.target.value;
3980
- setHasUncontrolledValue(val !== "");
3979
+ setValue(event.target.value);
3981
3980
  onChange?.(event);
3982
3981
  };
3983
3982
  const handleBlur = (event) => {
3984
- const val = event.target.value;
3985
- setHasUncontrolledValue(val !== "");
3983
+ onValueBlur?.(event.target.value);
3986
3984
  onBlur?.(event);
3987
3985
  };
3988
3986
  const handleClear = () => {
@@ -3990,11 +3988,8 @@ var Input = ({
3990
3988
  inputRef.current.value = "";
3991
3989
  inputRef.current.focus();
3992
3990
  onClear?.();
3993
- setHasUncontrolledValue(false);
3994
- onChange?.(createChangeInputEvent(inputRef.current));
3991
+ handleChange(createChangeInputEvent(inputRef.current));
3995
3992
  };
3996
- const isControlled = value !== void 0;
3997
- const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
3998
3993
  return /* @__PURE__ */ jsxs(
3999
3994
  InputGroup,
4000
3995
  {
@@ -4010,7 +4005,7 @@ var Input = ({
4010
4005
  InputGroup.Input,
4011
4006
  {
4012
4007
  ...inputProps,
4013
- ...valueProp,
4008
+ value,
4014
4009
  autoFocus,
4015
4010
  type,
4016
4011
  onChange: handleChange,
@@ -4049,48 +4044,7 @@ var Input = ({
4049
4044
  }
4050
4045
  );
4051
4046
  };
4052
- var sanitizeTextInputValue = (value) => {
4053
- if (typeof value === "string" && value.trim() === "") return "";
4054
- return value;
4055
- };
4056
- var TextInput = ({
4057
- ref,
4058
- value,
4059
- defaultValue,
4060
- type = "text",
4061
- variant,
4062
- onValueChange,
4063
- onChange,
4064
- onValueBlur,
4065
- onBlur,
4066
- ...props
4067
- }) => {
4068
- const handleChange = (event) => {
4069
- onValueChange?.(event.target.value);
4070
- onChange?.(event);
4071
- };
4072
- const handleBlur = (event) => {
4073
- onValueBlur?.(event.target.value);
4074
- onBlur?.(event);
4075
- };
4076
- return /* @__PURE__ */ jsx(
4077
- Input,
4078
- {
4079
- ...props,
4080
- ref,
4081
- onChange: handleChange,
4082
- onBlur: handleBlur,
4083
- type,
4084
- variant,
4085
- value: sanitizeTextInputValue(value),
4086
- defaultValue: sanitizeTextInputValue(defaultValue)
4087
- }
4088
- );
4089
- };
4090
- var FormGroupTextInput = ({
4091
- ref,
4092
- ...props
4093
- }) => {
4047
+ var FormGroupTextInput = ({ ref, ...props }) => {
4094
4048
  const { state } = useFormGroupContext();
4095
4049
  return /* @__PURE__ */ jsx(TextInput, { state, ...props, ref });
4096
4050
  };
@@ -4104,6 +4058,74 @@ FormGroup.NumberInput = FormGroupNumberInput;
4104
4058
  FormGroup.ColorInput = FormGroupColorInput;
4105
4059
  FormGroup.Textarea = FormGroupTextarea;
4106
4060
 
4061
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4062
+ init_Button2();
4063
+ var buttonGroupVariant = cva(
4064
+ ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
4065
+ {
4066
+ defaultVariants: {
4067
+ variant: "inline",
4068
+ space: "small"
4069
+ },
4070
+ variants: {
4071
+ variant: {
4072
+ inline: [],
4073
+ block: [
4074
+ "tw-w-full",
4075
+ "tw-flex-col",
4076
+ "sm:tw-flex-row",
4077
+ "[&_a]:tw-flex-1",
4078
+ "[&>button:not([data-icon-only=true])]:tw-flex-1"
4079
+ ]
4080
+ },
4081
+ space: {
4082
+ "extra-small": "tw-gap-1",
4083
+ "little-small": "tw-gap-2",
4084
+ small: "tw-gap-3",
4085
+ medium: "tw-gap-4",
4086
+ large: "tw-gap-6",
4087
+ compact: [
4088
+ "tw-border-collapse",
4089
+ "!tw-gap-0",
4090
+ // ensure that focus visible outline is at the top
4091
+ "[&>*:focus-visible]:!tw-z-10",
4092
+ "[&>*:not(:first-child)]:tw-rounded-l-none",
4093
+ "[&>*:not(:last-child)]:tw-rounded-r-none",
4094
+ "[&>*:not(:last-child)]:tw-border-r-0",
4095
+ "[&>*:not(:first-child)]:tw-border-l-0",
4096
+ // separator
4097
+ "[&>*:not(:first-child)]:before:tw-content",
4098
+ "[&>*:not(:first-child)]:before:tw-absolute",
4099
+ "[&>*:not(:first-child)]:before:tw-left-0",
4100
+ "[&>*:not(:first-child)]:before:tw-h-full",
4101
+ "[&>*:not(:first-child)]:before:tw-w-px",
4102
+ "[&>*:not(:first-child)]:before:tw-bg-black/10"
4103
+ ]
4104
+ }
4105
+ }
4106
+ }
4107
+ );
4108
+ var ButtonGroup = ({
4109
+ ref,
4110
+ children,
4111
+ space = "small",
4112
+ className,
4113
+ variant,
4114
+ ...rest
4115
+ }) => {
4116
+ return /* @__PURE__ */ jsx(
4117
+ "div",
4118
+ {
4119
+ ref,
4120
+ ...rest,
4121
+ role: "group",
4122
+ "data-variant": variant,
4123
+ className: buttonGroupVariant({ variant, className, space }),
4124
+ children
4125
+ }
4126
+ );
4127
+ };
4128
+
4107
4129
  // src/components/Label/Label.tsx
4108
4130
  init_utils2();
4109
4131
  var Optional = ({ className, ...props }) => /* @__PURE__ */ jsx("span", { ...props, "aria-hidden": true, className: cn("tw-ml-0.5", "tw-text-muted-foreground", className), children: "(optional)" });
@@ -4124,9 +4146,12 @@ var Label2 = ({ className, children, id, htmlFor, ...rest }) => /* @__PURE__ */
4124
4146
  Label2.Optional = Optional;
4125
4147
  Label2.Required = Required;
4126
4148
 
4127
- // src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4128
- init_utils2();
4149
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4150
+ init_icons();
4151
+
4152
+ // src/blocks/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4129
4153
  init_Tooltip2();
4154
+ init_utils2();
4130
4155
  var ToolbarButton = ({
4131
4156
  active,
4132
4157
  disabled,
@@ -4504,7 +4529,7 @@ var ToolbarPlugin = () => {
4504
4529
  );
4505
4530
  };
4506
4531
 
4507
- // src/components/MarkdownEditor/theme.ts
4532
+ // src/blocks/MarkdownEditor/theme.ts
4508
4533
  var editorTheme = {
4509
4534
  link: "tw-cursor-pointer !tw-text-primary tw-underline",
4510
4535
  text: {