@keboola/design 6.4.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,
@@ -1215,10 +1218,13 @@ var init_ZoomableSvg = __esm({
1215
1218
  MIN_SCALE = 0.5;
1216
1219
  MAX_SCALE = 3;
1217
1220
  ZOOM_STEP = 0.1;
1218
- ZoomableSvg = ({ html, copyText, className }) => {
1221
+ ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
1219
1222
  const safeHtml = react.useMemo(
1220
- () => DOMPurify__default.default.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
1221
- [html]
1223
+ () => DOMPurify__default.default.sanitize(html, {
1224
+ USE_PROFILES: { svg: true, svgFilters: true },
1225
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
1226
+ }),
1227
+ [html, allowForeignObject]
1222
1228
  );
1223
1229
  const containerRef = react.useRef(null);
1224
1230
  const [scale, setScale] = react.useState(1);
@@ -1247,7 +1253,7 @@ var init_ZoomableSvg = __esm({
1247
1253
  };
1248
1254
  el.addEventListener("wheel", onWheel, { passive: false });
1249
1255
  return () => el.removeEventListener("wheel", onWheel);
1250
- }, []);
1256
+ }, [isFullscreen]);
1251
1257
  const didDragRef = react.useRef(false);
1252
1258
  const handleMouseDown = react.useCallback(
1253
1259
  (e) => {
@@ -1354,14 +1360,18 @@ var init_ZoomableSvg = __esm({
1354
1360
  }
1355
1361
  );
1356
1362
  if (isFullscreen) {
1357
- return /* @__PURE__ */ jsxRuntime.jsx(
1358
- "div",
1359
- {
1360
- role: "presentation",
1361
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1362
- onClick: stopPropagation,
1363
- children: diagramContent
1364
- }
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
1365
1375
  );
1366
1376
  }
1367
1377
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1385,26 +1395,64 @@ var init_ZoomableSvg2 = __esm({
1385
1395
  }
1386
1396
  });
1387
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
+
1388
1426
  // src/blocks/MermaidDiagram/MermaidDiagram.tsx
1389
1427
  var MermaidDiagram_exports = {};
1390
1428
  __export(MermaidDiagram_exports, {
1391
1429
  MermaidDiagram: () => MermaidDiagram
1392
1430
  });
1393
- 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;
1394
1432
  var init_MermaidDiagram = __esm({
1395
1433
  "src/blocks/MermaidDiagram/MermaidDiagram.tsx"() {
1396
1434
  init_Skeleton();
1397
1435
  init_ZoomableSvg2();
1398
1436
  init_utils2();
1437
+ init_svgTransforms();
1399
1438
  PRIMARY_FALLBACK_CHANNELS = "31 143 255";
1400
1439
  resolvePrimary = () => {
1401
1440
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1402
1441
  return `rgb(${channels})`;
1403
1442
  };
1404
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
+ };
1405
1452
  getMermaid = () => {
1406
1453
  if (!mermaidPromise) {
1407
1454
  mermaidPromise = import('mermaid').then((m) => {
1455
+ registerLucideIconPack(m.default);
1408
1456
  m.default.initialize({
1409
1457
  startOnLoad: false,
1410
1458
  securityLevel: "strict",
@@ -1468,7 +1516,9 @@ var init_MermaidDiagram = __esm({
1468
1516
  return mermaidPromise;
1469
1517
  };
1470
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);
1471
1520
  tryFastRender = (code) => {
1521
+ if (hasIconSyntax(code)) return null;
1472
1522
  try {
1473
1523
  return stripFontImports(
1474
1524
  beautifulMermaid.renderMermaidSVG(code, {
@@ -1478,27 +1528,11 @@ var init_MermaidDiagram = __esm({
1478
1528
  font: "Inter, system-ui, sans-serif"
1479
1529
  })
1480
1530
  );
1481
- } catch {
1531
+ } catch (err) {
1532
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1482
1533
  return null;
1483
1534
  }
1484
1535
  };
1485
- makeResponsive = (svgString) => {
1486
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1487
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1488
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1489
- if (!vbWidth) return result;
1490
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1491
- if (hasStyle) {
1492
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1493
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1494
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1495
- return `${pre} style="${combined}"`;
1496
- });
1497
- } else {
1498
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1499
- }
1500
- return result;
1501
- };
1502
1536
  RENDER_DEBOUNCE_MS = 300;
1503
1537
  svgCache = /* @__PURE__ */ new Map();
1504
1538
  resolveSyncSvg = (code) => {
@@ -1539,8 +1573,9 @@ var init_MermaidDiagram = __esm({
1539
1573
  try {
1540
1574
  const result = await mermaidModule.default.render(rendererId, code, container);
1541
1575
  if (renderIdRef.current === currentRenderId && result) {
1542
- svgCache.set(code, result.svg);
1543
- setSvg(result.svg);
1576
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1577
+ svgCache.set(code, svgOutput);
1578
+ setSvg(svgOutput);
1544
1579
  setRenderFailed(false);
1545
1580
  }
1546
1581
  } finally {
@@ -1587,7 +1622,8 @@ var init_MermaidDiagram = __esm({
1587
1622
  copyText: `\`\`\`mermaid
1588
1623
  ${code}
1589
1624
  \`\`\``,
1590
- className: "tw-my-3"
1625
+ className: "tw-my-3",
1626
+ allowForeignObject: true
1591
1627
  },
1592
1628
  code
1593
1629
  );
@@ -1597,7 +1633,7 @@ ${code}
1597
1633
  }
1598
1634
  });
1599
1635
 
1600
- // src/components/MarkdownEditor/MarkdownEditor.tsx
1636
+ // src/blocks/MarkdownEditor/MarkdownEditor.tsx
1601
1637
  init_utils2();
1602
1638
  var ImageRendererContext = react.createContext(null);
1603
1639
  var ImageRendererProvider = ImageRendererContext;
@@ -1693,7 +1729,7 @@ var $isImageNode = (node) => {
1693
1729
  return node instanceof ImageNode;
1694
1730
  };
1695
1731
 
1696
- // src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1732
+ // src/blocks/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1697
1733
  init_Skeleton();
1698
1734
  var MermaidDiagram2 = react.lazy(
1699
1735
  () => Promise.resolve().then(() => (init_MermaidDiagram(), MermaidDiagram_exports)).then(
@@ -1776,11 +1812,7 @@ init_context();
1776
1812
 
1777
1813
  // src/components/Toast/ToastAction.tsx
1778
1814
  init_utils2();
1779
- var ToastAction = ({
1780
- ref,
1781
- className,
1782
- ...rest
1783
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1815
+ var ToastAction = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1784
1816
  "button",
1785
1817
  {
1786
1818
  ...rest,
@@ -1811,12 +1843,7 @@ var ToastAction = ({
1811
1843
 
1812
1844
  // src/components/Toast/ToastDescription.tsx
1813
1845
  init_utils2();
1814
- var ToastDescription = ({
1815
- ref,
1816
- className,
1817
- children,
1818
- ...rest
1819
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1846
+ var ToastDescription = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1820
1847
  "div",
1821
1848
  {
1822
1849
  ref,
@@ -1837,11 +1864,7 @@ var ToastDescription = ({
1837
1864
  // src/components/Toast/ToastDismiss.tsx
1838
1865
  init_icons();
1839
1866
  init_utils2();
1840
- var ToastDismiss = ({
1841
- ref,
1842
- className,
1843
- ...rest
1844
- }) => /* @__PURE__ */ jsxRuntime.jsxs(
1867
+ var ToastDismiss = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxRuntime.jsxs(
1845
1868
  "button",
1846
1869
  {
1847
1870
  ref,
@@ -1871,13 +1894,7 @@ var ToastDismiss = ({
1871
1894
 
1872
1895
  // src/components/Toast/ToastDuration.tsx
1873
1896
  init_utils2();
1874
- var ToastDuration = ({
1875
- ref,
1876
- duration,
1877
- className,
1878
- style,
1879
- ...rest
1880
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1897
+ var ToastDuration = ({ ref, duration, className, style, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1881
1898
  "span",
1882
1899
  {
1883
1900
  ...rest,
@@ -1908,12 +1925,7 @@ var ToastDuration = ({
1908
1925
 
1909
1926
  // src/components/Toast/ToastTitle.tsx
1910
1927
  init_utils2();
1911
- var ToastTitle = ({
1912
- ref,
1913
- className,
1914
- children,
1915
- ...rest
1916
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1928
+ var ToastTitle = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsxRuntime.jsx(
1917
1929
  "div",
1918
1930
  {
1919
1931
  ref,
@@ -2098,7 +2110,7 @@ toast.info = (title, options) => toast({
2098
2110
  toast.dismiss = (toastId) => sonner.toast.dismiss(toastId);
2099
2111
  toast.dismissAll = () => sonner.toast.dismiss();
2100
2112
 
2101
- // src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx
2113
+ // src/blocks/MarkdownEditor/plugins/ImagePastePlugin.tsx
2102
2114
  var ACCEPTED_IMAGE_TYPES = [
2103
2115
  "image/png",
2104
2116
  "image/jpeg",
@@ -2376,7 +2388,7 @@ var postprocessMarkdown = (markdown) => {
2376
2388
  };
2377
2389
  var unescapeMarkdownText = (markdown) => markdown.replace(/\\([*_`~\\])/g, "$1");
2378
2390
 
2379
- // src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2391
+ // src/blocks/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2380
2392
  var IMPORT_TAG = "markdown-import";
2381
2393
  var MarkdownSyncPlugin = ({
2382
2394
  value,
@@ -2422,13 +2434,9 @@ var MarkdownSyncPlugin = ({
2422
2434
  return null;
2423
2435
  };
2424
2436
 
2425
- // src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx
2437
+ // src/blocks/MarkdownEditor/plugins/ToolbarPlugin.tsx
2426
2438
  init_icons();
2427
2439
 
2428
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2429
- init_icons();
2430
- init_utils2();
2431
-
2432
2440
  // src/components/DropdownMenu/DropdownMenu.tsx
2433
2441
  init_context();
2434
2442
 
@@ -2987,11 +2995,7 @@ var DropdownMenuSubTrigger = ({ className, children, ...props }) => {
2987
2995
 
2988
2996
  // src/components/DropdownMenu/DropdownMenuTrigger.tsx
2989
2997
  init_utils2();
2990
- var DropdownMenuTrigger = ({
2991
- ref,
2992
- className,
2993
- ...props
2994
- }) => /* @__PURE__ */ jsxRuntime.jsx(
2998
+ var DropdownMenuTrigger = ({ ref, className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2995
2999
  DropdownMenuPrimitive3.Trigger,
2996
3000
  {
2997
3001
  ...props,
@@ -3023,8 +3027,10 @@ DropdownMenu.RadioGroup = DropdownMenuRadioGroup;
3023
3027
  DropdownMenu.RadioItem = DropdownMenuRadioItem;
3024
3028
  DropdownMenu.ItemDescription = DropdownMenuItemDescription;
3025
3029
 
3026
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
3030
+ // src/blocks/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
3027
3031
  init_Tooltip2();
3032
+ init_icons();
3033
+ init_utils2();
3028
3034
  var ALIGNMENT_OPTIONS = [
3029
3035
  { value: "left", label: "Left", icon: icons_exports.AlignLeft },
3030
3036
  { value: "center", label: "Center", icon: icons_exports.AlignCenter },
@@ -3088,11 +3094,9 @@ var AlignmentDropdown = ({
3088
3094
  )) })
3089
3095
  ] });
3090
3096
  };
3091
-
3092
- // src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx
3097
+ init_Tooltip2();
3093
3098
  init_icons();
3094
3099
  init_utils2();
3095
- init_Tooltip2();
3096
3100
  var BLOCK_TYPE_META = {
3097
3101
  paragraph: { label: "Normal", icon: icons_exports.Type, selectable: true },
3098
3102
  h1: { label: "Heading 1", icon: icons_exports.Heading1, selectable: true },
@@ -3176,76 +3180,7 @@ var BlockTypeDropdown = ({
3176
3180
  ] });
3177
3181
  };
3178
3182
 
3179
- // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
3180
- init_icons();
3181
- init_Button2();
3182
- var buttonGroupVariant = classVarianceAuthority.cva(
3183
- ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
3184
- {
3185
- defaultVariants: {
3186
- variant: "inline",
3187
- space: "small"
3188
- },
3189
- variants: {
3190
- variant: {
3191
- inline: [],
3192
- block: [
3193
- "tw-w-full",
3194
- "tw-flex-col",
3195
- "sm:tw-flex-row",
3196
- "[&_a]:tw-flex-1",
3197
- "[&>button:not([data-icon-only=true])]:tw-flex-1"
3198
- ]
3199
- },
3200
- space: {
3201
- "extra-small": "tw-gap-1",
3202
- "little-small": "tw-gap-2",
3203
- small: "tw-gap-3",
3204
- medium: "tw-gap-4",
3205
- large: "tw-gap-6",
3206
- compact: [
3207
- "tw-border-collapse",
3208
- "!tw-gap-0",
3209
- // ensure that focus visible outline is at the top
3210
- "[&>*:focus-visible]:!tw-z-10",
3211
- "[&>*:not(:first-child)]:tw-rounded-l-none",
3212
- "[&>*:not(:last-child)]:tw-rounded-r-none",
3213
- "[&>*:not(:last-child)]:tw-border-r-0",
3214
- "[&>*:not(:first-child)]:tw-border-l-0",
3215
- // separator
3216
- "[&>*:not(:first-child)]:before:tw-content",
3217
- "[&>*:not(:first-child)]:before:tw-absolute",
3218
- "[&>*:not(:first-child)]:before:tw-left-0",
3219
- "[&>*:not(:first-child)]:before:tw-h-full",
3220
- "[&>*:not(:first-child)]:before:tw-w-px",
3221
- "[&>*:not(:first-child)]:before:tw-bg-black/10"
3222
- ]
3223
- }
3224
- }
3225
- }
3226
- );
3227
- var ButtonGroup = ({
3228
- ref,
3229
- children,
3230
- space = "small",
3231
- className,
3232
- variant,
3233
- ...rest
3234
- }) => {
3235
- return /* @__PURE__ */ jsxRuntime.jsx(
3236
- "div",
3237
- {
3238
- ref,
3239
- ...rest,
3240
- role: "group",
3241
- "data-variant": variant,
3242
- className: buttonGroupVariant({ variant, className, space }),
3243
- children
3244
- }
3245
- );
3246
- };
3247
-
3248
- // src/components/FormGroup/FormGroup.tsx
3183
+ // src/blocks/FormGroup/FormGroup.tsx
3249
3184
  init_utils2();
3250
3185
  var FormGroupContext = react.createContext({
3251
3186
  state: "default"
@@ -3305,12 +3240,7 @@ var InputGroupAddon = ({
3305
3240
  // src/components/InputGroup/InputGroupButton.tsx
3306
3241
  init_utils2();
3307
3242
  init_Button2();
3308
- var InputGroupButton = ({
3309
- ref,
3310
- className,
3311
- tabIndex = -1,
3312
- ...props
3313
- }) => /* @__PURE__ */ jsxRuntime.jsx(
3243
+ var InputGroupButton = ({ ref, className, tabIndex = -1, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
3314
3244
  Button,
3315
3245
  {
3316
3246
  ...props,
@@ -3324,11 +3254,7 @@ var InputGroupButton = ({
3324
3254
 
3325
3255
  // src/components/InputGroup/InputGroupInput.tsx
3326
3256
  init_utils2();
3327
- var InputGroupInput = ({
3328
- ref,
3329
- className,
3330
- ...inputProps
3331
- }) => /* @__PURE__ */ jsxRuntime.jsx(
3257
+ var InputGroupInput = ({ ref, className, ...inputProps }) => /* @__PURE__ */ jsxRuntime.jsx(
3332
3258
  "input",
3333
3259
  {
3334
3260
  ...inputProps,
@@ -3662,6 +3588,29 @@ InputGroup.Addon = InputGroupAddon;
3662
3588
  InputGroup.Button = InputGroupButton;
3663
3589
  InputGroup.TextArea = InputGroupTextArea;
3664
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
+ };
3665
3614
 
3666
3615
  // src/blocks/ColorInput/ColorInput.tsx
3667
3616
  init_icons();
@@ -3758,13 +3707,13 @@ var ColorInput = ({
3758
3707
  ...restInputProps
3759
3708
  }) => {
3760
3709
  const inputRef = react.useRef(null);
3761
- 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
+ });
3762
3716
  const isControlled = valueProp !== void 0;
3763
- const value = isControlled ? valueProp ?? "" : internalValue;
3764
- const setValue = (nextValue) => {
3765
- if (!isControlled) setInternalValue(nextValue);
3766
- onValueChange?.(nextValue);
3767
- };
3768
3717
  const canClear = allowClear && !!value && !disabled && !readOnly;
3769
3718
  const swatchColor = coerceHexInputValue(value);
3770
3719
  const isValidSwatch = isCompleteHexColor(swatchColor);
@@ -3867,15 +3816,12 @@ var ColorInput = ({
3867
3816
  }
3868
3817
  );
3869
3818
  };
3870
- var FormGroupColorInput = ({
3871
- ref,
3872
- ...props
3873
- }) => {
3819
+ var FormGroupColorInput = ({ ref, ...props }) => {
3874
3820
  const { state } = useFormGroupContext();
3875
3821
  return /* @__PURE__ */ jsxRuntime.jsx(ColorInput, { state, ...props, ref });
3876
3822
  };
3877
3823
 
3878
- // src/components/FormGroup/FormGroupError.tsx
3824
+ // src/blocks/FormGroup/FormGroupError.tsx
3879
3825
  init_utils2();
3880
3826
  var toMessage = (entry) => typeof entry === "string" ? entry : entry?.message;
3881
3827
  var FormGroupError = ({ children, className, errors, ...rest }) => {
@@ -3962,10 +3908,7 @@ var NumberInput = ({
3962
3908
  }
3963
3909
  );
3964
3910
  };
3965
- var FormGroupNumberInput = ({
3966
- ref,
3967
- ...props
3968
- }) => {
3911
+ var FormGroupNumberInput = ({ ref, ...props }) => {
3969
3912
  const { state } = useFormGroupContext();
3970
3913
  return /* @__PURE__ */ jsxRuntime.jsx(NumberInput, { ...props, ref, state });
3971
3914
  };
@@ -3977,8 +3920,18 @@ var Textarea = ({
3977
3920
  variant,
3978
3921
  sizing,
3979
3922
  focusVariant,
3923
+ // value handling
3924
+ value: valueProp,
3925
+ defaultValue,
3926
+ onValueChange,
3980
3927
  ...rest
3981
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
+ });
3982
3935
  return /* @__PURE__ */ jsxRuntime.jsx(
3983
3936
  InputGroup,
3984
3937
  {
@@ -3987,7 +3940,7 @@ var Textarea = ({
3987
3940
  focusVariant,
3988
3941
  variant,
3989
3942
  className: containerClassName,
3990
- children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup.TextArea, { ...rest, ref })
3943
+ children: /* @__PURE__ */ jsxRuntime.jsx(InputGroup.TextArea, { ...rest, ref, value, onValueChange: setValue })
3991
3944
  }
3992
3945
  );
3993
3946
  };
@@ -3995,12 +3948,10 @@ var FormGroupTextarea = (props) => {
3995
3948
  const { state } = useFormGroupContext();
3996
3949
  return /* @__PURE__ */ jsxRuntime.jsx(Textarea, { state, ...props });
3997
3950
  };
3998
-
3999
- // src/components/Input/Input.tsx
4000
3951
  init_icons();
4001
3952
  init_utils2();
4002
3953
 
4003
- // src/components/Input/utils.ts
3954
+ // src/blocks/TextInput/utils.ts
4004
3955
  init_utils2();
4005
3956
  var genInputTestId = (prefix = "") => {
4006
3957
  const ps = createPrefixedString(prefix);
@@ -4011,7 +3962,11 @@ var genInputTestId = (prefix = "") => {
4011
3962
  clearButton: ps`clear-button`
4012
3963
  };
4013
3964
  };
4014
- var Input = ({
3965
+ var sanitizeTextInputValue = (value) => {
3966
+ if (typeof value === "string" && value.trim() === "") return "";
3967
+ return value;
3968
+ };
3969
+ var TextInput = ({
4015
3970
  ref: forwardedRef,
4016
3971
  state = "default",
4017
3972
  sizing = "default",
@@ -4033,23 +3988,28 @@ var Input = ({
4033
3988
  focusVariant = "default",
4034
3989
  onChange,
4035
3990
  onBlur,
4036
- value,
3991
+ onValueChange,
3992
+ onValueBlur,
3993
+ value: valueProp,
4037
3994
  defaultValue,
4038
3995
  ...inputProps
4039
3996
  }) => {
4040
- const [hasUncontrolledValue, setHasUncontrolledValue] = react.useState(() => !!defaultValue);
4041
- const hasValue = !!value || hasUncontrolledValue;
4042
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
+ });
4043
4005
  const testId = genInputTestId(prefixTestId);
4044
- const isClearButtonVisible = hasValue && !disabled && !readOnly || !!onClear;
4006
+ const isClearButtonVisible = !!value && !disabled && !readOnly || !!onClear;
4045
4007
  const handleChange = (event) => {
4046
- const val = event.target.value;
4047
- setHasUncontrolledValue(val !== "");
4008
+ setValue(event.target.value);
4048
4009
  onChange?.(event);
4049
4010
  };
4050
4011
  const handleBlur = (event) => {
4051
- const val = event.target.value;
4052
- setHasUncontrolledValue(val !== "");
4012
+ onValueBlur?.(event.target.value);
4053
4013
  onBlur?.(event);
4054
4014
  };
4055
4015
  const handleClear = () => {
@@ -4057,11 +4017,8 @@ var Input = ({
4057
4017
  inputRef.current.value = "";
4058
4018
  inputRef.current.focus();
4059
4019
  onClear?.();
4060
- setHasUncontrolledValue(false);
4061
- onChange?.(createChangeInputEvent(inputRef.current));
4020
+ handleChange(createChangeInputEvent(inputRef.current));
4062
4021
  };
4063
- const isControlled = value !== void 0;
4064
- const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
4065
4022
  return /* @__PURE__ */ jsxRuntime.jsxs(
4066
4023
  InputGroup,
4067
4024
  {
@@ -4077,7 +4034,7 @@ var Input = ({
4077
4034
  InputGroup.Input,
4078
4035
  {
4079
4036
  ...inputProps,
4080
- ...valueProp,
4037
+ value,
4081
4038
  autoFocus,
4082
4039
  type,
4083
4040
  onChange: handleChange,
@@ -4116,48 +4073,7 @@ var Input = ({
4116
4073
  }
4117
4074
  );
4118
4075
  };
4119
- var sanitizeTextInputValue = (value) => {
4120
- if (typeof value === "string" && value.trim() === "") return "";
4121
- return value;
4122
- };
4123
- var TextInput = ({
4124
- ref,
4125
- value,
4126
- defaultValue,
4127
- type = "text",
4128
- variant,
4129
- onValueChange,
4130
- onChange,
4131
- onValueBlur,
4132
- onBlur,
4133
- ...props
4134
- }) => {
4135
- const handleChange = (event) => {
4136
- onValueChange?.(event.target.value);
4137
- onChange?.(event);
4138
- };
4139
- const handleBlur = (event) => {
4140
- onValueBlur?.(event.target.value);
4141
- onBlur?.(event);
4142
- };
4143
- return /* @__PURE__ */ jsxRuntime.jsx(
4144
- Input,
4145
- {
4146
- ...props,
4147
- ref,
4148
- onChange: handleChange,
4149
- onBlur: handleBlur,
4150
- type,
4151
- variant,
4152
- value: sanitizeTextInputValue(value),
4153
- defaultValue: sanitizeTextInputValue(defaultValue)
4154
- }
4155
- );
4156
- };
4157
- var FormGroupTextInput = ({
4158
- ref,
4159
- ...props
4160
- }) => {
4076
+ var FormGroupTextInput = ({ ref, ...props }) => {
4161
4077
  const { state } = useFormGroupContext();
4162
4078
  return /* @__PURE__ */ jsxRuntime.jsx(TextInput, { state, ...props, ref });
4163
4079
  };
@@ -4171,6 +4087,74 @@ FormGroup.NumberInput = FormGroupNumberInput;
4171
4087
  FormGroup.ColorInput = FormGroupColorInput;
4172
4088
  FormGroup.Textarea = FormGroupTextarea;
4173
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
+
4174
4158
  // src/components/Label/Label.tsx
4175
4159
  init_utils2();
4176
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)" });
@@ -4191,9 +4175,12 @@ var Label2 = ({ className, children, id, htmlFor, ...rest }) => /* @__PURE__ */
4191
4175
  Label2.Optional = Optional;
4192
4176
  Label2.Required = Required;
4193
4177
 
4194
- // src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4195
- init_utils2();
4178
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4179
+ init_icons();
4180
+
4181
+ // src/blocks/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4196
4182
  init_Tooltip2();
4183
+ init_utils2();
4197
4184
  var ToolbarButton = ({
4198
4185
  active,
4199
4186
  disabled,
@@ -4571,7 +4558,7 @@ var ToolbarPlugin = () => {
4571
4558
  );
4572
4559
  };
4573
4560
 
4574
- // src/components/MarkdownEditor/theme.ts
4561
+ // src/blocks/MarkdownEditor/theme.ts
4575
4562
  var editorTheme = {
4576
4563
  link: "tw-cursor-pointer !tw-text-primary tw-underline",
4577
4564
  text: {