@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.
@@ -9,6 +9,7 @@ var classVarianceAuthority = require('class-variance-authority');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var lucide_react_star = require('lucide-react');
11
11
  var reactSlot = require('@radix-ui/react-slot');
12
+ var reactDom = require('react-dom');
12
13
  var DOMPurify = require('dompurify');
13
14
  var beautifulMermaid = require('beautiful-mermaid');
14
15
  var colors = require('@keboola/tailwind-config/colors');
@@ -34,7 +35,6 @@ var richText = require('@lexical/rich-text');
34
35
  var lexical = require('lexical');
35
36
  var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
36
37
  var sonner = require('sonner');
37
- var reactDom = require('react-dom');
38
38
  var utils = require('@lexical/utils');
39
39
  var DropdownMenuPrimitive3 = require('@radix-ui/react-dropdown-menu');
40
40
  var ScrollAreaPrimitive2 = require('@radix-ui/react-scroll-area');
@@ -378,6 +378,7 @@ var init_Tooltip = __esm({
378
378
  placement = "right",
379
379
  forceHide = false,
380
380
  forceShow = false,
381
+ delayDuration,
381
382
  // trigger props
382
383
  triggerAsChild = false
383
384
  }) => {
@@ -397,6 +398,7 @@ var init_Tooltip = __esm({
397
398
  {
398
399
  open: !!tooltip && (open || forceShow) && !forceHide,
399
400
  onOpenChange: setOpen,
401
+ delayDuration,
400
402
  disableHoverableContent: isActionVariant,
401
403
  children: [
402
404
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -633,6 +635,7 @@ var init_Keboola = __esm({
633
635
  width: size,
634
636
  height: size,
635
637
  viewBox: "0 0 300 512",
638
+ overflow: "visible",
636
639
  fill: color,
637
640
  className: cn("lucide", className),
638
641
  ...rest,
@@ -646,18 +649,49 @@ var init_Keboola = __esm({
646
649
  Keboola.displayName = "Keboola";
647
650
  }
648
651
  });
652
+ var Microsoft;
653
+ var init_Microsoft = __esm({
654
+ "src/icons/Microsoft.tsx"() {
655
+ init_utils2();
656
+ Microsoft = react.forwardRef(
657
+ ({ size = 24, className, children, ...rest }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
658
+ "svg",
659
+ {
660
+ ref,
661
+ xmlns: "http://www.w3.org/2000/svg",
662
+ width: size,
663
+ height: size,
664
+ viewBox: "0 0 21 21",
665
+ fill: "none",
666
+ className: cn("lucide", className),
667
+ ...rest,
668
+ children: [
669
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "0", y: "0", width: "10", height: "10", fill: "#F25022" }),
670
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "11", y: "0", width: "10", height: "10", fill: "#7FBA00" }),
671
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "0", y: "11", width: "10", height: "10", fill: "#00A4EF" }),
672
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "11", y: "11", width: "10", height: "10", fill: "#FFB900" }),
673
+ children
674
+ ]
675
+ }
676
+ )
677
+ );
678
+ Microsoft.displayName = "Microsoft";
679
+ }
680
+ });
649
681
 
650
682
  // src/icons/index.ts
651
683
  var icons_exports = {};
652
684
  __export(icons_exports, {
653
685
  Google: () => Google,
654
- Keboola: () => Keboola
686
+ Keboola: () => Keboola,
687
+ Microsoft: () => Microsoft
655
688
  });
656
689
  var init_icons = __esm({
657
690
  "src/icons/index.ts"() {
658
691
  __reExport(icons_exports, lucide_react_star__namespace);
659
692
  init_Google();
660
693
  init_Keboola();
694
+ init_Microsoft();
661
695
  }
662
696
  });
663
697
  var variants, argoVariants;
@@ -1184,10 +1218,13 @@ var init_ZoomableSvg = __esm({
1184
1218
  MIN_SCALE = 0.5;
1185
1219
  MAX_SCALE = 3;
1186
1220
  ZOOM_STEP = 0.1;
1187
- ZoomableSvg = ({ html, copyText, className }) => {
1221
+ ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
1188
1222
  const safeHtml = react.useMemo(
1189
- () => DOMPurify__default.default.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
1190
- [html]
1223
+ () => DOMPurify__default.default.sanitize(html, {
1224
+ USE_PROFILES: { svg: true, svgFilters: true },
1225
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
1226
+ }),
1227
+ [html, allowForeignObject]
1191
1228
  );
1192
1229
  const containerRef = react.useRef(null);
1193
1230
  const [scale, setScale] = react.useState(1);
@@ -1216,7 +1253,7 @@ var init_ZoomableSvg = __esm({
1216
1253
  };
1217
1254
  el.addEventListener("wheel", onWheel, { passive: false });
1218
1255
  return () => el.removeEventListener("wheel", onWheel);
1219
- }, []);
1256
+ }, [isFullscreen]);
1220
1257
  const didDragRef = react.useRef(false);
1221
1258
  const handleMouseDown = react.useCallback(
1222
1259
  (e) => {
@@ -1323,14 +1360,18 @@ var init_ZoomableSvg = __esm({
1323
1360
  }
1324
1361
  );
1325
1362
  if (isFullscreen) {
1326
- return /* @__PURE__ */ jsxRuntime.jsx(
1327
- "div",
1328
- {
1329
- role: "presentation",
1330
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1331
- onClick: stopPropagation,
1332
- children: diagramContent
1333
- }
1363
+ return reactDom.createPortal(
1364
+ /* @__PURE__ */ jsxRuntime.jsx(
1365
+ "div",
1366
+ {
1367
+ role: "presentation",
1368
+ "data-testid": "zoomable-svg-fullscreen",
1369
+ className: "tailwindcss-preflight tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1370
+ onClick: stopPropagation,
1371
+ children: diagramContent
1372
+ }
1373
+ ),
1374
+ document.body
1334
1375
  );
1335
1376
  }
1336
1377
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1354,26 +1395,64 @@ var init_ZoomableSvg2 = __esm({
1354
1395
  }
1355
1396
  });
1356
1397
 
1398
+ // src/blocks/MermaidDiagram/svgTransforms.ts
1399
+ var HTML_TAG, FOREIGN_OBJECT, ROOT_SVG_TAG, flattenForeignObjectLabels, STYLE_ATTR, makeResponsive;
1400
+ var init_svgTransforms = __esm({
1401
+ "src/blocks/MermaidDiagram/svgTransforms.ts"() {
1402
+ HTML_TAG = /<[^>]+>/g;
1403
+ FOREIGN_OBJECT = /(<foreignObject\b[^>]*>)([\s\S]*?)(<\/foreignObject>)/g;
1404
+ ROOT_SVG_TAG = /^(\s*<svg\b)([^>]*)(>)/i;
1405
+ flattenForeignObjectLabels = (svg) => svg.replace(FOREIGN_OBJECT, (_match, open, inner, close) => {
1406
+ const text = inner.replace(HTML_TAG, " ").replace(/\s+/g, " ").trim();
1407
+ return `${open}${text}${close}`;
1408
+ });
1409
+ STYLE_ATTR = /\s+style="([^"]*)"/i;
1410
+ makeResponsive = (svgString) => {
1411
+ const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1412
+ const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1413
+ return svgString.replace(ROOT_SVG_TAG, (_match, open, attrs, close) => {
1414
+ const existingStyle = attrs.match(STYLE_ATTR)?.[1] ?? "";
1415
+ const styleDecls = existingStyle.replace(/max-width:\s*[^;"]*;?\s*/gi, "").replace(/\s+/g, " ").trim().replace(/;$/, "");
1416
+ let nextAttrs = attrs.replace(/\s+width="[^"]*"/i, "").replace(/\s+height="[^"]*"/i, "").replace(STYLE_ATTR, "");
1417
+ nextAttrs += ' width="100%"';
1418
+ const styleParts = [styleDecls, vbWidth ? `max-width: ${vbWidth}px` : ""].filter(Boolean).join("; ");
1419
+ if (styleParts) nextAttrs += ` style="${styleParts}"`;
1420
+ return `${open}${nextAttrs}${close}`;
1421
+ });
1422
+ };
1423
+ }
1424
+ });
1425
+
1357
1426
  // src/blocks/MermaidDiagram/MermaidDiagram.tsx
1358
1427
  var MermaidDiagram_exports = {};
1359
1428
  __export(MermaidDiagram_exports, {
1360
1429
  MermaidDiagram: () => MermaidDiagram
1361
1430
  });
1362
- var PRIMARY_FALLBACK_CHANNELS, resolvePrimary, mermaidPromise, getMermaid, stripFontImports, tryFastRender, makeResponsive, RENDER_DEBOUNCE_MS, svgCache, resolveSyncSvg, MermaidDiagram;
1431
+ var PRIMARY_FALLBACK_CHANNELS, resolvePrimary, mermaidPromise, registerLucideIconPack, getMermaid, stripFontImports, hasIconSyntax, tryFastRender, RENDER_DEBOUNCE_MS, svgCache, resolveSyncSvg, MermaidDiagram;
1363
1432
  var init_MermaidDiagram = __esm({
1364
1433
  "src/blocks/MermaidDiagram/MermaidDiagram.tsx"() {
1365
1434
  init_Skeleton();
1366
1435
  init_ZoomableSvg2();
1367
1436
  init_utils2();
1437
+ init_svgTransforms();
1368
1438
  PRIMARY_FALLBACK_CHANNELS = "31 143 255";
1369
1439
  resolvePrimary = () => {
1370
1440
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1371
1441
  return `rgb(${channels})`;
1372
1442
  };
1373
1443
  mermaidPromise = null;
1444
+ registerLucideIconPack = (m) => {
1445
+ m.registerIconPacks([
1446
+ {
1447
+ name: "lucide",
1448
+ loader: () => import('@iconify-json/lucide/icons.json').then((mod) => mod.default)
1449
+ }
1450
+ ]);
1451
+ };
1374
1452
  getMermaid = () => {
1375
1453
  if (!mermaidPromise) {
1376
1454
  mermaidPromise = import('mermaid').then((m) => {
1455
+ registerLucideIconPack(m.default);
1377
1456
  m.default.initialize({
1378
1457
  startOnLoad: false,
1379
1458
  securityLevel: "strict",
@@ -1437,7 +1516,9 @@ var init_MermaidDiagram = __esm({
1437
1516
  return mermaidPromise;
1438
1517
  };
1439
1518
  stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1519
+ hasIconSyntax = (code) => /@\{[^}]*\bicon\s*:/.test(code) || /\b(?:icon|service|group)\b[^\n(]*\(\s*[\w-]+:/.test(code) || /\bfa[bslr]?:fa-/.test(code);
1440
1520
  tryFastRender = (code) => {
1521
+ if (hasIconSyntax(code)) return null;
1441
1522
  try {
1442
1523
  return stripFontImports(
1443
1524
  beautifulMermaid.renderMermaidSVG(code, {
@@ -1447,27 +1528,11 @@ var init_MermaidDiagram = __esm({
1447
1528
  font: "Inter, system-ui, sans-serif"
1448
1529
  })
1449
1530
  );
1450
- } catch {
1531
+ } catch (err) {
1532
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1451
1533
  return null;
1452
1534
  }
1453
1535
  };
1454
- makeResponsive = (svgString) => {
1455
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1456
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1457
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1458
- if (!vbWidth) return result;
1459
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1460
- if (hasStyle) {
1461
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1462
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1463
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1464
- return `${pre} style="${combined}"`;
1465
- });
1466
- } else {
1467
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1468
- }
1469
- return result;
1470
- };
1471
1536
  RENDER_DEBOUNCE_MS = 300;
1472
1537
  svgCache = /* @__PURE__ */ new Map();
1473
1538
  resolveSyncSvg = (code) => {
@@ -1508,8 +1573,9 @@ var init_MermaidDiagram = __esm({
1508
1573
  try {
1509
1574
  const result = await mermaidModule.default.render(rendererId, code, container);
1510
1575
  if (renderIdRef.current === currentRenderId && result) {
1511
- svgCache.set(code, result.svg);
1512
- setSvg(result.svg);
1576
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1577
+ svgCache.set(code, svgOutput);
1578
+ setSvg(svgOutput);
1513
1579
  setRenderFailed(false);
1514
1580
  }
1515
1581
  } finally {
@@ -1556,7 +1622,8 @@ var init_MermaidDiagram = __esm({
1556
1622
  copyText: `\`\`\`mermaid
1557
1623
  ${code}
1558
1624
  \`\`\``,
1559
- className: "tw-my-3"
1625
+ className: "tw-my-3",
1626
+ allowForeignObject: true
1560
1627
  },
1561
1628
  code
1562
1629
  );
@@ -1566,7 +1633,7 @@ ${code}
1566
1633
  }
1567
1634
  });
1568
1635
 
1569
- // src/components/MarkdownEditor/MarkdownEditor.tsx
1636
+ // src/blocks/MarkdownEditor/MarkdownEditor.tsx
1570
1637
  init_utils2();
1571
1638
  var ImageRendererContext = react.createContext(null);
1572
1639
  var ImageRendererProvider = ImageRendererContext;
@@ -1662,7 +1729,7 @@ var $isImageNode = (node) => {
1662
1729
  return node instanceof ImageNode;
1663
1730
  };
1664
1731
 
1665
- // src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1732
+ // src/blocks/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1666
1733
  init_Skeleton();
1667
1734
  var MermaidDiagram2 = react.lazy(
1668
1735
  () => Promise.resolve().then(() => (init_MermaidDiagram(), MermaidDiagram_exports)).then(
@@ -1745,11 +1812,7 @@ init_context();
1745
1812
 
1746
1813
  // src/components/Toast/ToastAction.tsx
1747
1814
  init_utils2();
1748
- var ToastAction = ({
1749
- ref,
1750
- className,
1751
- ...rest
1752
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1815
+ var ToastAction = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1753
1816
  "button",
1754
1817
  {
1755
1818
  ...rest,
@@ -1780,12 +1843,7 @@ var ToastAction = ({
1780
1843
 
1781
1844
  // src/components/Toast/ToastDescription.tsx
1782
1845
  init_utils2();
1783
- var ToastDescription = ({
1784
- ref,
1785
- className,
1786
- children,
1787
- ...rest
1788
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1846
+ var ToastDescription = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1789
1847
  "div",
1790
1848
  {
1791
1849
  ref,
@@ -1806,11 +1864,7 @@ var ToastDescription = ({
1806
1864
  // src/components/Toast/ToastDismiss.tsx
1807
1865
  init_icons();
1808
1866
  init_utils2();
1809
- var ToastDismiss = ({
1810
- ref,
1811
- className,
1812
- ...rest
1813
- }) => /* @__PURE__ */ jsxRuntime.jsxs(
1867
+ var ToastDismiss = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxRuntime.jsxs(
1814
1868
  "button",
1815
1869
  {
1816
1870
  ref,
@@ -1840,13 +1894,7 @@ var ToastDismiss = ({
1840
1894
 
1841
1895
  // src/components/Toast/ToastDuration.tsx
1842
1896
  init_utils2();
1843
- var ToastDuration = ({
1844
- ref,
1845
- duration,
1846
- className,
1847
- style,
1848
- ...rest
1849
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1897
+ var ToastDuration = ({ ref, duration, className, style, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1850
1898
  "span",
1851
1899
  {
1852
1900
  ...rest,
@@ -1877,12 +1925,7 @@ var ToastDuration = ({
1877
1925
 
1878
1926
  // src/components/Toast/ToastTitle.tsx
1879
1927
  init_utils2();
1880
- var ToastTitle = ({
1881
- ref,
1882
- className,
1883
- children,
1884
- ...rest
1885
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1928
+ var ToastTitle = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1886
1929
  "div",
1887
1930
  {
1888
1931
  ref,
@@ -2067,7 +2110,7 @@ toast.info = (title, options) => toast({
2067
2110
  toast.dismiss = (toastId) => sonner.toast.dismiss(toastId);
2068
2111
  toast.dismissAll = () => sonner.toast.dismiss();
2069
2112
 
2070
- // src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx
2113
+ // src/blocks/MarkdownEditor/plugins/ImagePastePlugin.tsx
2071
2114
  var ACCEPTED_IMAGE_TYPES = [
2072
2115
  "image/png",
2073
2116
  "image/jpeg",
@@ -2345,7 +2388,7 @@ var postprocessMarkdown = (markdown) => {
2345
2388
  };
2346
2389
  var unescapeMarkdownText = (markdown) => markdown.replace(/\\([*_`~\\])/g, "$1");
2347
2390
 
2348
- // src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2391
+ // src/blocks/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2349
2392
  var IMPORT_TAG = "markdown-import";
2350
2393
  var MarkdownSyncPlugin = ({
2351
2394
  value,
@@ -2391,13 +2434,9 @@ var MarkdownSyncPlugin = ({
2391
2434
  return null;
2392
2435
  };
2393
2436
 
2394
- // src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx
2437
+ // src/blocks/MarkdownEditor/plugins/ToolbarPlugin.tsx
2395
2438
  init_icons();
2396
2439
 
2397
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2398
- init_icons();
2399
- init_utils2();
2400
-
2401
2440
  // src/components/DropdownMenu/DropdownMenu.tsx
2402
2441
  init_context();
2403
2442
 
@@ -2956,11 +2995,7 @@ var DropdownMenuSubTrigger = ({ className, children, ...props }) => {
2956
2995
 
2957
2996
  // src/components/DropdownMenu/DropdownMenuTrigger.tsx
2958
2997
  init_utils2();
2959
- var DropdownMenuTrigger = ({
2960
- ref,
2961
- className,
2962
- ...props
2963
- }) => /* @__PURE__ */ jsxRuntime.jsx(
2998
+ var DropdownMenuTrigger = ({ ref, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2964
2999
  DropdownMenuPrimitive3.Trigger,
2965
3000
  {
2966
3001
  ...props,
@@ -2992,8 +3027,10 @@ DropdownMenu.RadioGroup = DropdownMenuRadioGroup;
2992
3027
  DropdownMenu.RadioItem = DropdownMenuRadioItem;
2993
3028
  DropdownMenu.ItemDescription = DropdownMenuItemDescription;
2994
3029
 
2995
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
3030
+ // src/blocks/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2996
3031
  init_Tooltip2();
3032
+ init_icons();
3033
+ init_utils2();
2997
3034
  var ALIGNMENT_OPTIONS = [
2998
3035
  { value: "left", label: "Left", icon: icons_exports.AlignLeft },
2999
3036
  { value: "center", label: "Center", icon: icons_exports.AlignCenter },
@@ -3057,11 +3094,9 @@ var AlignmentDropdown = ({
3057
3094
  )) })
3058
3095
  ] });
3059
3096
  };
3060
-
3061
- // src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx
3097
+ init_Tooltip2();
3062
3098
  init_icons();
3063
3099
  init_utils2();
3064
- init_Tooltip2();
3065
3100
  var BLOCK_TYPE_META = {
3066
3101
  paragraph: { label: "Normal", icon: icons_exports.Type, selectable: true },
3067
3102
  h1: { label: "Heading 1", icon: icons_exports.Heading1, selectable: true },
@@ -3145,76 +3180,7 @@ var BlockTypeDropdown = ({
3145
3180
  ] });
3146
3181
  };
3147
3182
 
3148
- // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
3149
- init_icons();
3150
- init_Button2();
3151
- var buttonGroupVariant = classVarianceAuthority.cva(
3152
- ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
3153
- {
3154
- defaultVariants: {
3155
- variant: "inline",
3156
- space: "small"
3157
- },
3158
- variants: {
3159
- variant: {
3160
- inline: [],
3161
- block: [
3162
- "tw-w-full",
3163
- "tw-flex-col",
3164
- "sm:tw-flex-row",
3165
- "[&_a]:tw-flex-1",
3166
- "[&>button:not([data-icon-only=true])]:tw-flex-1"
3167
- ]
3168
- },
3169
- space: {
3170
- "extra-small": "tw-gap-1",
3171
- "little-small": "tw-gap-2",
3172
- small: "tw-gap-3",
3173
- medium: "tw-gap-4",
3174
- large: "tw-gap-6",
3175
- compact: [
3176
- "tw-border-collapse",
3177
- "!tw-gap-0",
3178
- // ensure that focus visible outline is at the top
3179
- "[&>*:focus-visible]:!tw-z-10",
3180
- "[&>*:not(:first-child)]:tw-rounded-l-none",
3181
- "[&>*:not(:last-child)]:tw-rounded-r-none",
3182
- "[&>*:not(:last-child)]:tw-border-r-0",
3183
- "[&>*:not(:first-child)]:tw-border-l-0",
3184
- // separator
3185
- "[&>*:not(:first-child)]:before:tw-content",
3186
- "[&>*:not(:first-child)]:before:tw-absolute",
3187
- "[&>*:not(:first-child)]:before:tw-left-0",
3188
- "[&>*:not(:first-child)]:before:tw-h-full",
3189
- "[&>*:not(:first-child)]:before:tw-w-px",
3190
- "[&>*:not(:first-child)]:before:tw-bg-black/10"
3191
- ]
3192
- }
3193
- }
3194
- }
3195
- );
3196
- var ButtonGroup = ({
3197
- ref,
3198
- children,
3199
- space = "small",
3200
- className,
3201
- variant,
3202
- ...rest
3203
- }) => {
3204
- return /* @__PURE__ */ jsxRuntime.jsx(
3205
- "div",
3206
- {
3207
- ref,
3208
- ...rest,
3209
- role: "group",
3210
- "data-variant": variant,
3211
- className: buttonGroupVariant({ variant, className, space }),
3212
- children
3213
- }
3214
- );
3215
- };
3216
-
3217
- // src/components/FormGroup/FormGroup.tsx
3183
+ // src/blocks/FormGroup/FormGroup.tsx
3218
3184
  init_utils2();
3219
3185
  var FormGroupContext = react.createContext({
3220
3186
  state: "default"
@@ -3274,12 +3240,7 @@ var InputGroupAddon = ({
3274
3240
  // src/components/InputGroup/InputGroupButton.tsx
3275
3241
  init_utils2();
3276
3242
  init_Button2();
3277
- var InputGroupButton = ({
3278
- ref,
3279
- className,
3280
- tabIndex = -1,
3281
- ...props
3282
- }) => /* @__PURE__ */ jsxRuntime.jsx(
3243
+ var InputGroupButton = ({ ref, className, tabIndex = -1, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
3283
3244
  Button,
3284
3245
  {
3285
3246
  ...props,
@@ -3293,11 +3254,7 @@ var InputGroupButton = ({
3293
3254
 
3294
3255
  // src/components/InputGroup/InputGroupInput.tsx
3295
3256
  init_utils2();
3296
- var InputGroupInput = ({
3297
- ref,
3298
- className,
3299
- ...inputProps
3300
- }) => /* @__PURE__ */ jsxRuntime.jsx(
3257
+ var InputGroupInput = ({ ref, className, ...inputProps }) => /* @__PURE__ */ jsxRuntime.jsx(
3301
3258
  "input",
3302
3259
  {
3303
3260
  ...inputProps,
@@ -3542,8 +3499,15 @@ var inputGroupVariants = classVarianceAuthority.cva(
3542
3499
  "tw-border-input",
3543
3500
  "tw-text-foreground",
3544
3501
  "has-[:is(input,textarea):disabled]:tw-opacity-50",
3502
+ // readonly: keep the themed input surface/border. The base layer's fixed
3503
+ // `neutral-150` (a light grey) is correct for the legacy light chrome but
3504
+ // collides with argo's themed `foreground` text — light-on-light, invisible
3505
+ // in dark mode. Re-pin to the same `muted`/`input` tokens the editable argo
3506
+ // input uses (validated AA), so readonly stays legible in every scheme.
3507
+ "has-[:is(input,textarea)[readonly]]:tw-bg-muted",
3508
+ "has-[:is(input,textarea)[readonly]]:tw-border-input",
3545
3509
  // higher specificity than has-[:is(input,textarea):focus] — prevents focus border on readonly
3546
- "has-[:is(input,textarea)[readonly]:focus]:tw-border-neutral-150",
3510
+ "has-[:is(input,textarea)[readonly]:focus]:tw-border-input",
3547
3511
  // aria-invalid on the control surfaces the error chrome without a `state` prop — the
3548
3512
  // accessible path (uses the themeable `destructive` status token).
3549
3513
  "has-[:is(input,textarea)[aria-invalid=true]]:tw-border-destructive",
@@ -3624,6 +3588,29 @@ InputGroup.Addon = InputGroupAddon;
3624
3588
  InputGroup.Button = InputGroupButton;
3625
3589
  InputGroup.TextArea = InputGroupTextArea;
3626
3590
  InputGroup.Text = InputGroupText;
3591
+ var useControllableState = ({
3592
+ prop,
3593
+ defaultProp,
3594
+ onChange
3595
+ }) => {
3596
+ const [uncontrolled, setUncontrolled] = react.useState(defaultProp);
3597
+ const isControlled = prop !== void 0;
3598
+ const value = prop !== void 0 ? prop : uncontrolled;
3599
+ const valueRef = react.useRef(value);
3600
+ valueRef.current = value;
3601
+ const onChangeRef = react.useRef(onChange);
3602
+ onChangeRef.current = onChange;
3603
+ const setValue = react.useCallback(
3604
+ (next) => {
3605
+ const nextValue = typeof next === "function" ? next(valueRef.current) : next;
3606
+ valueRef.current = nextValue;
3607
+ if (!isControlled) setUncontrolled(nextValue);
3608
+ onChangeRef.current?.(nextValue);
3609
+ },
3610
+ [isControlled]
3611
+ );
3612
+ return [value, setValue];
3613
+ };
3627
3614
 
3628
3615
  // src/blocks/ColorInput/ColorInput.tsx
3629
3616
  init_icons();
@@ -3720,13 +3707,13 @@ var ColorInput = ({
3720
3707
  ...restInputProps
3721
3708
  }) => {
3722
3709
  const inputRef = react.useRef(null);
3723
- const [internalValue, setInternalValue] = react.useState(defaultValue ?? "");
3710
+ const [value, setValue] = useControllableState({
3711
+ // A `null` controlled value stays controlled (coerced to ''); `undefined` is uncontrolled.
3712
+ prop: valueProp === null ? "" : valueProp,
3713
+ defaultProp: defaultValue ?? "",
3714
+ onChange: onValueChange
3715
+ });
3724
3716
  const isControlled = valueProp !== void 0;
3725
- const value = isControlled ? valueProp ?? "" : internalValue;
3726
- const setValue = (nextValue) => {
3727
- if (!isControlled) setInternalValue(nextValue);
3728
- onValueChange?.(nextValue);
3729
- };
3730
3717
  const canClear = allowClear && !!value && !disabled && !readOnly;
3731
3718
  const swatchColor = coerceHexInputValue(value);
3732
3719
  const isValidSwatch = isCompleteHexColor(swatchColor);
@@ -3829,15 +3816,12 @@ var ColorInput = ({
3829
3816
  }
3830
3817
  );
3831
3818
  };
3832
- var FormGroupColorInput = ({
3833
- ref,
3834
- ...props
3835
- }) => {
3819
+ var FormGroupColorInput = ({ ref, ...props }) => {
3836
3820
  const { state } = useFormGroupContext();
3837
3821
  return /* @__PURE__ */ jsxRuntime.jsx(ColorInput, { state, ...props, ref });
3838
3822
  };
3839
3823
 
3840
- // src/components/FormGroup/FormGroupError.tsx
3824
+ // src/blocks/FormGroup/FormGroupError.tsx
3841
3825
  init_utils2();
3842
3826
  var toMessage = (entry) => typeof entry === "string" ? entry : entry?.message;
3843
3827
  var FormGroupError = ({ children, className, errors, ...rest }) => {
@@ -3924,10 +3908,7 @@ var NumberInput = ({
3924
3908
  }
3925
3909
  );
3926
3910
  };
3927
- var FormGroupNumberInput = ({
3928
- ref,
3929
- ...props
3930
- }) => {
3911
+ var FormGroupNumberInput = ({ ref, ...props }) => {
3931
3912
  const { state } = useFormGroupContext();
3932
3913
  return /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...props, ref, state });
3933
3914
  };
@@ -3939,8 +3920,18 @@ var Textarea = ({
3939
3920
  variant,
3940
3921
  sizing,
3941
3922
  focusVariant,
3923
+ // value handling
3924
+ value: valueProp,
3925
+ defaultValue,
3926
+ onValueChange,
3942
3927
  ...rest
3943
3928
  }) => {
3929
+ const [value, setValue] = useControllableState({
3930
+ // `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled, coerced to ''.
3931
+ prop: valueProp === void 0 ? void 0 : valueProp ?? "",
3932
+ defaultProp: defaultValue ?? "",
3933
+ onChange: onValueChange
3934
+ });
3944
3935
  return /* @__PURE__ */ jsxRuntime.jsx(
3945
3936
  InputGroup,
3946
3937
  {
@@ -3949,7 +3940,7 @@ var Textarea = ({
3949
3940
  focusVariant,
3950
3941
  variant,
3951
3942
  className: containerClassName,
3952
- children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup.TextArea, { ...rest, ref })
3943
+ children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup.TextArea, { ...rest, ref, value, onValueChange: setValue })
3953
3944
  }
3954
3945
  );
3955
3946
  };
@@ -3957,12 +3948,10 @@ var FormGroupTextarea = (props) => {
3957
3948
  const { state } = useFormGroupContext();
3958
3949
  return /* @__PURE__ */ jsxRuntime.jsx(Textarea, { state, ...props });
3959
3950
  };
3960
-
3961
- // src/components/Input/Input.tsx
3962
3951
  init_icons();
3963
3952
  init_utils2();
3964
3953
 
3965
- // src/components/Input/utils.ts
3954
+ // src/blocks/TextInput/utils.ts
3966
3955
  init_utils2();
3967
3956
  var genInputTestId = (prefix = "") => {
3968
3957
  const ps = createPrefixedString(prefix);
@@ -3973,7 +3962,11 @@ var genInputTestId = (prefix = "") => {
3973
3962
  clearButton: ps`clear-button`
3974
3963
  };
3975
3964
  };
3976
- var Input = ({
3965
+ var sanitizeTextInputValue = (value) => {
3966
+ if (typeof value === "string" && value.trim() === "") return "";
3967
+ return value;
3968
+ };
3969
+ var TextInput = ({
3977
3970
  ref: forwardedRef,
3978
3971
  state = "default",
3979
3972
  sizing = "default",
@@ -3995,23 +3988,28 @@ var Input = ({
3995
3988
  focusVariant = "default",
3996
3989
  onChange,
3997
3990
  onBlur,
3998
- value,
3991
+ onValueChange,
3992
+ onValueBlur,
3993
+ value: valueProp,
3999
3994
  defaultValue,
4000
3995
  ...inputProps
4001
3996
  }) => {
4002
- const [hasUncontrolledValue, setHasUncontrolledValue] = react.useState(() => !!defaultValue);
4003
- const hasValue = !!value || hasUncontrolledValue;
4004
3997
  const inputRef = react.useRef(null);
3998
+ const [value, setValue] = useControllableState({
3999
+ // `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled and coerced
4000
+ // to a string. Whitespace-only input collapses to '' via `sanitizeTextInputValue`.
4001
+ prop: valueProp === void 0 ? void 0 : sanitizeTextInputValue(valueProp) ?? "",
4002
+ defaultProp: sanitizeTextInputValue(defaultValue) ?? "",
4003
+ onChange: onValueChange
4004
+ });
4005
4005
  const testId = genInputTestId(prefixTestId);
4006
- const isClearButtonVisible = hasValue && !disabled && !readOnly || !!onClear;
4006
+ const isClearButtonVisible = !!value && !disabled && !readOnly || !!onClear;
4007
4007
  const handleChange = (event) => {
4008
- const val = event.target.value;
4009
- setHasUncontrolledValue(val !== "");
4008
+ setValue(event.target.value);
4010
4009
  onChange?.(event);
4011
4010
  };
4012
4011
  const handleBlur = (event) => {
4013
- const val = event.target.value;
4014
- setHasUncontrolledValue(val !== "");
4012
+ onValueBlur?.(event.target.value);
4015
4013
  onBlur?.(event);
4016
4014
  };
4017
4015
  const handleClear = () => {
@@ -4019,11 +4017,8 @@ var Input = ({
4019
4017
  inputRef.current.value = "";
4020
4018
  inputRef.current.focus();
4021
4019
  onClear?.();
4022
- setHasUncontrolledValue(false);
4023
- onChange?.(createChangeInputEvent(inputRef.current));
4020
+ handleChange(createChangeInputEvent(inputRef.current));
4024
4021
  };
4025
- const isControlled = value !== void 0;
4026
- const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
4027
4022
  return /* @__PURE__ */ jsxRuntime.jsxs(
4028
4023
  InputGroup,
4029
4024
  {
@@ -4039,7 +4034,7 @@ var Input = ({
4039
4034
  InputGroup.Input,
4040
4035
  {
4041
4036
  ...inputProps,
4042
- ...valueProp,
4037
+ value,
4043
4038
  autoFocus,
4044
4039
  type,
4045
4040
  onChange: handleChange,
@@ -4078,48 +4073,7 @@ var Input = ({
4078
4073
  }
4079
4074
  );
4080
4075
  };
4081
- var sanitizeTextInputValue = (value) => {
4082
- if (typeof value === "string" && value.trim() === "") return "";
4083
- return value;
4084
- };
4085
- var TextInput = ({
4086
- ref,
4087
- value,
4088
- defaultValue,
4089
- type = "text",
4090
- variant,
4091
- onValueChange,
4092
- onChange,
4093
- onValueBlur,
4094
- onBlur,
4095
- ...props
4096
- }) => {
4097
- const handleChange = (event) => {
4098
- onValueChange?.(event.target.value);
4099
- onChange?.(event);
4100
- };
4101
- const handleBlur = (event) => {
4102
- onValueBlur?.(event.target.value);
4103
- onBlur?.(event);
4104
- };
4105
- return /* @__PURE__ */ jsxRuntime.jsx(
4106
- Input,
4107
- {
4108
- ...props,
4109
- ref,
4110
- onChange: handleChange,
4111
- onBlur: handleBlur,
4112
- type,
4113
- variant,
4114
- value: sanitizeTextInputValue(value),
4115
- defaultValue: sanitizeTextInputValue(defaultValue)
4116
- }
4117
- );
4118
- };
4119
- var FormGroupTextInput = ({
4120
- ref,
4121
- ...props
4122
- }) => {
4076
+ var FormGroupTextInput = ({ ref, ...props }) => {
4123
4077
  const { state } = useFormGroupContext();
4124
4078
  return /* @__PURE__ */ jsxRuntime.jsx(TextInput, { state, ...props, ref });
4125
4079
  };
@@ -4133,6 +4087,74 @@ FormGroup.NumberInput = FormGroupNumberInput;
4133
4087
  FormGroup.ColorInput = FormGroupColorInput;
4134
4088
  FormGroup.Textarea = FormGroupTextarea;
4135
4089
 
4090
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4091
+ init_Button2();
4092
+ var buttonGroupVariant = classVarianceAuthority.cva(
4093
+ ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
4094
+ {
4095
+ defaultVariants: {
4096
+ variant: "inline",
4097
+ space: "small"
4098
+ },
4099
+ variants: {
4100
+ variant: {
4101
+ inline: [],
4102
+ block: [
4103
+ "tw-w-full",
4104
+ "tw-flex-col",
4105
+ "sm:tw-flex-row",
4106
+ "[&_a]:tw-flex-1",
4107
+ "[&>button:not([data-icon-only=true])]:tw-flex-1"
4108
+ ]
4109
+ },
4110
+ space: {
4111
+ "extra-small": "tw-gap-1",
4112
+ "little-small": "tw-gap-2",
4113
+ small: "tw-gap-3",
4114
+ medium: "tw-gap-4",
4115
+ large: "tw-gap-6",
4116
+ compact: [
4117
+ "tw-border-collapse",
4118
+ "!tw-gap-0",
4119
+ // ensure that focus visible outline is at the top
4120
+ "[&>*:focus-visible]:!tw-z-10",
4121
+ "[&>*:not(:first-child)]:tw-rounded-l-none",
4122
+ "[&>*:not(:last-child)]:tw-rounded-r-none",
4123
+ "[&>*:not(:last-child)]:tw-border-r-0",
4124
+ "[&>*:not(:first-child)]:tw-border-l-0",
4125
+ // separator
4126
+ "[&>*:not(:first-child)]:before:tw-content",
4127
+ "[&>*:not(:first-child)]:before:tw-absolute",
4128
+ "[&>*:not(:first-child)]:before:tw-left-0",
4129
+ "[&>*:not(:first-child)]:before:tw-h-full",
4130
+ "[&>*:not(:first-child)]:before:tw-w-px",
4131
+ "[&>*:not(:first-child)]:before:tw-bg-black/10"
4132
+ ]
4133
+ }
4134
+ }
4135
+ }
4136
+ );
4137
+ var ButtonGroup = ({
4138
+ ref,
4139
+ children,
4140
+ space = "small",
4141
+ className,
4142
+ variant,
4143
+ ...rest
4144
+ }) => {
4145
+ return /* @__PURE__ */ jsxRuntime.jsx(
4146
+ "div",
4147
+ {
4148
+ ref,
4149
+ ...rest,
4150
+ role: "group",
4151
+ "data-variant": variant,
4152
+ className: buttonGroupVariant({ variant, className, space }),
4153
+ children
4154
+ }
4155
+ );
4156
+ };
4157
+
4136
4158
  // src/components/Label/Label.tsx
4137
4159
  init_utils2();
4138
4160
  var Optional = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...props, "aria-hidden": true, className: cn("tw-ml-0.5", "tw-text-muted-foreground", className), children: "(optional)" });
@@ -4153,9 +4175,12 @@ var Label2 = ({ className, children, id, htmlFor, ...rest }) => /* @__PURE__ */
4153
4175
  Label2.Optional = Optional;
4154
4176
  Label2.Required = Required;
4155
4177
 
4156
- // src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4157
- init_utils2();
4178
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4179
+ init_icons();
4180
+
4181
+ // src/blocks/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4158
4182
  init_Tooltip2();
4183
+ init_utils2();
4159
4184
  var ToolbarButton = ({
4160
4185
  active,
4161
4186
  disabled,
@@ -4533,7 +4558,7 @@ var ToolbarPlugin = () => {
4533
4558
  );
4534
4559
  };
4535
4560
 
4536
- // src/components/MarkdownEditor/theme.ts
4561
+ // src/blocks/MarkdownEditor/theme.ts
4537
4562
  var editorTheme = {
4538
4563
  link: "tw-cursor-pointer !tw-text-primary tw-underline",
4539
4564
  text: {