@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.
@@ -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,
@@ -1186,10 +1189,13 @@ var init_ZoomableSvg = __esm({
1186
1189
  MIN_SCALE = 0.5;
1187
1190
  MAX_SCALE = 3;
1188
1191
  ZOOM_STEP = 0.1;
1189
- ZoomableSvg = ({ html, copyText, className }) => {
1192
+ ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
1190
1193
  const safeHtml = useMemo(
1191
- () => DOMPurify.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
1192
- [html]
1194
+ () => DOMPurify.sanitize(html, {
1195
+ USE_PROFILES: { svg: true, svgFilters: true },
1196
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
1197
+ }),
1198
+ [html, allowForeignObject]
1193
1199
  );
1194
1200
  const containerRef = useRef(null);
1195
1201
  const [scale, setScale] = useState(1);
@@ -1218,7 +1224,7 @@ var init_ZoomableSvg = __esm({
1218
1224
  };
1219
1225
  el.addEventListener("wheel", onWheel, { passive: false });
1220
1226
  return () => el.removeEventListener("wheel", onWheel);
1221
- }, []);
1227
+ }, [isFullscreen]);
1222
1228
  const didDragRef = useRef(false);
1223
1229
  const handleMouseDown = useCallback(
1224
1230
  (e) => {
@@ -1325,14 +1331,18 @@ var init_ZoomableSvg = __esm({
1325
1331
  }
1326
1332
  );
1327
1333
  if (isFullscreen) {
1328
- return /* @__PURE__ */ jsx(
1329
- "div",
1330
- {
1331
- role: "presentation",
1332
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1333
- onClick: stopPropagation,
1334
- children: diagramContent
1335
- }
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
1336
1346
  );
1337
1347
  }
1338
1348
  return /* @__PURE__ */ jsx(
@@ -1356,26 +1366,64 @@ var init_ZoomableSvg2 = __esm({
1356
1366
  }
1357
1367
  });
1358
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
+
1359
1397
  // src/blocks/MermaidDiagram/MermaidDiagram.tsx
1360
1398
  var MermaidDiagram_exports = {};
1361
1399
  __export(MermaidDiagram_exports, {
1362
1400
  MermaidDiagram: () => MermaidDiagram
1363
1401
  });
1364
- 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;
1365
1403
  var init_MermaidDiagram = __esm({
1366
1404
  "src/blocks/MermaidDiagram/MermaidDiagram.tsx"() {
1367
1405
  init_Skeleton();
1368
1406
  init_ZoomableSvg2();
1369
1407
  init_utils2();
1408
+ init_svgTransforms();
1370
1409
  PRIMARY_FALLBACK_CHANNELS = "31 143 255";
1371
1410
  resolvePrimary = () => {
1372
1411
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1373
1412
  return `rgb(${channels})`;
1374
1413
  };
1375
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
+ };
1376
1423
  getMermaid = () => {
1377
1424
  if (!mermaidPromise) {
1378
1425
  mermaidPromise = import('mermaid').then((m) => {
1426
+ registerLucideIconPack(m.default);
1379
1427
  m.default.initialize({
1380
1428
  startOnLoad: false,
1381
1429
  securityLevel: "strict",
@@ -1439,7 +1487,9 @@ var init_MermaidDiagram = __esm({
1439
1487
  return mermaidPromise;
1440
1488
  };
1441
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);
1442
1491
  tryFastRender = (code) => {
1492
+ if (hasIconSyntax(code)) return null;
1443
1493
  try {
1444
1494
  return stripFontImports(
1445
1495
  renderMermaidSVG(code, {
@@ -1449,27 +1499,11 @@ var init_MermaidDiagram = __esm({
1449
1499
  font: "Inter, system-ui, sans-serif"
1450
1500
  })
1451
1501
  );
1452
- } catch {
1502
+ } catch (err) {
1503
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1453
1504
  return null;
1454
1505
  }
1455
1506
  };
1456
- makeResponsive = (svgString) => {
1457
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1458
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1459
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1460
- if (!vbWidth) return result;
1461
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1462
- if (hasStyle) {
1463
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1464
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1465
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1466
- return `${pre} style="${combined}"`;
1467
- });
1468
- } else {
1469
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1470
- }
1471
- return result;
1472
- };
1473
1507
  RENDER_DEBOUNCE_MS = 300;
1474
1508
  svgCache = /* @__PURE__ */ new Map();
1475
1509
  resolveSyncSvg = (code) => {
@@ -1510,8 +1544,9 @@ var init_MermaidDiagram = __esm({
1510
1544
  try {
1511
1545
  const result = await mermaidModule.default.render(rendererId, code, container);
1512
1546
  if (renderIdRef.current === currentRenderId && result) {
1513
- svgCache.set(code, result.svg);
1514
- setSvg(result.svg);
1547
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1548
+ svgCache.set(code, svgOutput);
1549
+ setSvg(svgOutput);
1515
1550
  setRenderFailed(false);
1516
1551
  }
1517
1552
  } finally {
@@ -1558,7 +1593,8 @@ var init_MermaidDiagram = __esm({
1558
1593
  copyText: `\`\`\`mermaid
1559
1594
  ${code}
1560
1595
  \`\`\``,
1561
- className: "tw-my-3"
1596
+ className: "tw-my-3",
1597
+ allowForeignObject: true
1562
1598
  },
1563
1599
  code
1564
1600
  );
@@ -1568,7 +1604,7 @@ ${code}
1568
1604
  }
1569
1605
  });
1570
1606
 
1571
- // src/components/MarkdownEditor/MarkdownEditor.tsx
1607
+ // src/blocks/MarkdownEditor/MarkdownEditor.tsx
1572
1608
  init_utils2();
1573
1609
  var ImageRendererContext = createContext(null);
1574
1610
  var ImageRendererProvider = ImageRendererContext;
@@ -1664,7 +1700,7 @@ var $isImageNode = (node) => {
1664
1700
  return node instanceof ImageNode;
1665
1701
  };
1666
1702
 
1667
- // src/components/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1703
+ // src/blocks/MarkdownEditor/nodes/MermaidNodeComponent.tsx
1668
1704
  init_Skeleton();
1669
1705
  var MermaidDiagram2 = lazy(
1670
1706
  () => Promise.resolve().then(() => (init_MermaidDiagram(), MermaidDiagram_exports)).then(
@@ -1747,11 +1783,7 @@ init_context();
1747
1783
 
1748
1784
  // src/components/Toast/ToastAction.tsx
1749
1785
  init_utils2();
1750
- var ToastAction = ({
1751
- ref,
1752
- className,
1753
- ...rest
1754
- }) => /* @__PURE__ */ jsx(
1786
+ var ToastAction = ({ ref, className, ...rest }) => /* @__PURE__ */ jsx(
1755
1787
  "button",
1756
1788
  {
1757
1789
  ...rest,
@@ -1782,12 +1814,7 @@ var ToastAction = ({
1782
1814
 
1783
1815
  // src/components/Toast/ToastDescription.tsx
1784
1816
  init_utils2();
1785
- var ToastDescription = ({
1786
- ref,
1787
- className,
1788
- children,
1789
- ...rest
1790
- }) => /* @__PURE__ */ jsx(
1817
+ var ToastDescription = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsx(
1791
1818
  "div",
1792
1819
  {
1793
1820
  ref,
@@ -1808,11 +1835,7 @@ var ToastDescription = ({
1808
1835
  // src/components/Toast/ToastDismiss.tsx
1809
1836
  init_icons();
1810
1837
  init_utils2();
1811
- var ToastDismiss = ({
1812
- ref,
1813
- className,
1814
- ...rest
1815
- }) => /* @__PURE__ */ jsxs(
1838
+ var ToastDismiss = ({ ref, className, ...rest }) => /* @__PURE__ */ jsxs(
1816
1839
  "button",
1817
1840
  {
1818
1841
  ref,
@@ -1842,13 +1865,7 @@ var ToastDismiss = ({
1842
1865
 
1843
1866
  // src/components/Toast/ToastDuration.tsx
1844
1867
  init_utils2();
1845
- var ToastDuration = ({
1846
- ref,
1847
- duration,
1848
- className,
1849
- style,
1850
- ...rest
1851
- }) => /* @__PURE__ */ jsx(
1868
+ var ToastDuration = ({ ref, duration, className, style, ...rest }) => /* @__PURE__ */ jsx(
1852
1869
  "span",
1853
1870
  {
1854
1871
  ...rest,
@@ -1879,12 +1896,7 @@ var ToastDuration = ({
1879
1896
 
1880
1897
  // src/components/Toast/ToastTitle.tsx
1881
1898
  init_utils2();
1882
- var ToastTitle = ({
1883
- ref,
1884
- className,
1885
- children,
1886
- ...rest
1887
- }) => /* @__PURE__ */ jsx(
1899
+ var ToastTitle = ({ ref, className, children, ...rest }) => /* @__PURE__ */ jsx(
1888
1900
  "div",
1889
1901
  {
1890
1902
  ref,
@@ -2069,7 +2081,7 @@ toast.info = (title, options) => toast({
2069
2081
  toast.dismiss = (toastId) => toast$1.dismiss(toastId);
2070
2082
  toast.dismissAll = () => toast$1.dismiss();
2071
2083
 
2072
- // src/components/MarkdownEditor/plugins/ImagePastePlugin.tsx
2084
+ // src/blocks/MarkdownEditor/plugins/ImagePastePlugin.tsx
2073
2085
  var ACCEPTED_IMAGE_TYPES = [
2074
2086
  "image/png",
2075
2087
  "image/jpeg",
@@ -2347,7 +2359,7 @@ var postprocessMarkdown = (markdown) => {
2347
2359
  };
2348
2360
  var unescapeMarkdownText = (markdown) => markdown.replace(/\\([*_`~\\])/g, "$1");
2349
2361
 
2350
- // src/components/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2362
+ // src/blocks/MarkdownEditor/plugins/MarkdownSyncPlugin.tsx
2351
2363
  var IMPORT_TAG = "markdown-import";
2352
2364
  var MarkdownSyncPlugin = ({
2353
2365
  value,
@@ -2393,13 +2405,9 @@ var MarkdownSyncPlugin = ({
2393
2405
  return null;
2394
2406
  };
2395
2407
 
2396
- // src/components/MarkdownEditor/plugins/ToolbarPlugin.tsx
2408
+ // src/blocks/MarkdownEditor/plugins/ToolbarPlugin.tsx
2397
2409
  init_icons();
2398
2410
 
2399
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2400
- init_icons();
2401
- init_utils2();
2402
-
2403
2411
  // src/components/DropdownMenu/DropdownMenu.tsx
2404
2412
  init_context();
2405
2413
 
@@ -2958,11 +2966,7 @@ var DropdownMenuSubTrigger = ({ className, children, ...props }) => {
2958
2966
 
2959
2967
  // src/components/DropdownMenu/DropdownMenuTrigger.tsx
2960
2968
  init_utils2();
2961
- var DropdownMenuTrigger = ({
2962
- ref,
2963
- className,
2964
- ...props
2965
- }) => /* @__PURE__ */ jsx(
2969
+ var DropdownMenuTrigger = ({ ref, className, ...props }) => /* @__PURE__ */ jsx(
2966
2970
  Trigger$1,
2967
2971
  {
2968
2972
  ...props,
@@ -2994,8 +2998,10 @@ DropdownMenu.RadioGroup = DropdownMenuRadioGroup;
2994
2998
  DropdownMenu.RadioItem = DropdownMenuRadioItem;
2995
2999
  DropdownMenu.ItemDescription = DropdownMenuItemDescription;
2996
3000
 
2997
- // src/components/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
3001
+ // src/blocks/MarkdownEditor/plugins/toolbar/AlignmentDropdown.tsx
2998
3002
  init_Tooltip2();
3003
+ init_icons();
3004
+ init_utils2();
2999
3005
  var ALIGNMENT_OPTIONS = [
3000
3006
  { value: "left", label: "Left", icon: icons_exports.AlignLeft },
3001
3007
  { value: "center", label: "Center", icon: icons_exports.AlignCenter },
@@ -3059,11 +3065,9 @@ var AlignmentDropdown = ({
3059
3065
  )) })
3060
3066
  ] });
3061
3067
  };
3062
-
3063
- // src/components/MarkdownEditor/plugins/toolbar/BlockTypeDropdown.tsx
3068
+ init_Tooltip2();
3064
3069
  init_icons();
3065
3070
  init_utils2();
3066
- init_Tooltip2();
3067
3071
  var BLOCK_TYPE_META = {
3068
3072
  paragraph: { label: "Normal", icon: icons_exports.Type, selectable: true },
3069
3073
  h1: { label: "Heading 1", icon: icons_exports.Heading1, selectable: true },
@@ -3147,76 +3151,7 @@ var BlockTypeDropdown = ({
3147
3151
  ] });
3148
3152
  };
3149
3153
 
3150
- // src/components/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
3151
- init_icons();
3152
- init_Button2();
3153
- var buttonGroupVariant = cva(
3154
- ["tailwindcss-preflight", "tw-inline-flex", "tw-items-center", "tw-group/button-group"],
3155
- {
3156
- defaultVariants: {
3157
- variant: "inline",
3158
- space: "small"
3159
- },
3160
- variants: {
3161
- variant: {
3162
- inline: [],
3163
- block: [
3164
- "tw-w-full",
3165
- "tw-flex-col",
3166
- "sm:tw-flex-row",
3167
- "[&_a]:tw-flex-1",
3168
- "[&>button:not([data-icon-only=true])]:tw-flex-1"
3169
- ]
3170
- },
3171
- space: {
3172
- "extra-small": "tw-gap-1",
3173
- "little-small": "tw-gap-2",
3174
- small: "tw-gap-3",
3175
- medium: "tw-gap-4",
3176
- large: "tw-gap-6",
3177
- compact: [
3178
- "tw-border-collapse",
3179
- "!tw-gap-0",
3180
- // ensure that focus visible outline is at the top
3181
- "[&>*:focus-visible]:!tw-z-10",
3182
- "[&>*:not(:first-child)]:tw-rounded-l-none",
3183
- "[&>*:not(:last-child)]:tw-rounded-r-none",
3184
- "[&>*:not(:last-child)]:tw-border-r-0",
3185
- "[&>*:not(:first-child)]:tw-border-l-0",
3186
- // separator
3187
- "[&>*:not(:first-child)]:before:tw-content",
3188
- "[&>*:not(:first-child)]:before:tw-absolute",
3189
- "[&>*:not(:first-child)]:before:tw-left-0",
3190
- "[&>*:not(:first-child)]:before:tw-h-full",
3191
- "[&>*:not(:first-child)]:before:tw-w-px",
3192
- "[&>*:not(:first-child)]:before:tw-bg-black/10"
3193
- ]
3194
- }
3195
- }
3196
- }
3197
- );
3198
- var ButtonGroup = ({
3199
- ref,
3200
- children,
3201
- space = "small",
3202
- className,
3203
- variant,
3204
- ...rest
3205
- }) => {
3206
- return /* @__PURE__ */ jsx(
3207
- "div",
3208
- {
3209
- ref,
3210
- ...rest,
3211
- role: "group",
3212
- "data-variant": variant,
3213
- className: buttonGroupVariant({ variant, className, space }),
3214
- children
3215
- }
3216
- );
3217
- };
3218
-
3219
- // src/components/FormGroup/FormGroup.tsx
3154
+ // src/blocks/FormGroup/FormGroup.tsx
3220
3155
  init_utils2();
3221
3156
  var FormGroupContext = createContext({
3222
3157
  state: "default"
@@ -3276,12 +3211,7 @@ var InputGroupAddon = ({
3276
3211
  // src/components/InputGroup/InputGroupButton.tsx
3277
3212
  init_utils2();
3278
3213
  init_Button2();
3279
- var InputGroupButton = ({
3280
- ref,
3281
- className,
3282
- tabIndex = -1,
3283
- ...props
3284
- }) => /* @__PURE__ */ jsx(
3214
+ var InputGroupButton = ({ ref, className, tabIndex = -1, ...props }) => /* @__PURE__ */ jsx(
3285
3215
  Button,
3286
3216
  {
3287
3217
  ...props,
@@ -3295,11 +3225,7 @@ var InputGroupButton = ({
3295
3225
 
3296
3226
  // src/components/InputGroup/InputGroupInput.tsx
3297
3227
  init_utils2();
3298
- var InputGroupInput = ({
3299
- ref,
3300
- className,
3301
- ...inputProps
3302
- }) => /* @__PURE__ */ jsx(
3228
+ var InputGroupInput = ({ ref, className, ...inputProps }) => /* @__PURE__ */ jsx(
3303
3229
  "input",
3304
3230
  {
3305
3231
  ...inputProps,
@@ -3633,6 +3559,29 @@ InputGroup.Addon = InputGroupAddon;
3633
3559
  InputGroup.Button = InputGroupButton;
3634
3560
  InputGroup.TextArea = InputGroupTextArea;
3635
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
+ };
3636
3585
 
3637
3586
  // src/blocks/ColorInput/ColorInput.tsx
3638
3587
  init_icons();
@@ -3729,13 +3678,13 @@ var ColorInput = ({
3729
3678
  ...restInputProps
3730
3679
  }) => {
3731
3680
  const inputRef = useRef(null);
3732
- 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
+ });
3733
3687
  const isControlled = valueProp !== void 0;
3734
- const value = isControlled ? valueProp ?? "" : internalValue;
3735
- const setValue = (nextValue) => {
3736
- if (!isControlled) setInternalValue(nextValue);
3737
- onValueChange?.(nextValue);
3738
- };
3739
3688
  const canClear = allowClear && !!value && !disabled && !readOnly;
3740
3689
  const swatchColor = coerceHexInputValue(value);
3741
3690
  const isValidSwatch = isCompleteHexColor(swatchColor);
@@ -3838,15 +3787,12 @@ var ColorInput = ({
3838
3787
  }
3839
3788
  );
3840
3789
  };
3841
- var FormGroupColorInput = ({
3842
- ref,
3843
- ...props
3844
- }) => {
3790
+ var FormGroupColorInput = ({ ref, ...props }) => {
3845
3791
  const { state } = useFormGroupContext();
3846
3792
  return /* @__PURE__ */ jsx(ColorInput, { state, ...props, ref });
3847
3793
  };
3848
3794
 
3849
- // src/components/FormGroup/FormGroupError.tsx
3795
+ // src/blocks/FormGroup/FormGroupError.tsx
3850
3796
  init_utils2();
3851
3797
  var toMessage = (entry) => typeof entry === "string" ? entry : entry?.message;
3852
3798
  var FormGroupError = ({ children, className, errors, ...rest }) => {
@@ -3933,10 +3879,7 @@ var NumberInput = ({
3933
3879
  }
3934
3880
  );
3935
3881
  };
3936
- var FormGroupNumberInput = ({
3937
- ref,
3938
- ...props
3939
- }) => {
3882
+ var FormGroupNumberInput = ({ ref, ...props }) => {
3940
3883
  const { state } = useFormGroupContext();
3941
3884
  return /* @__PURE__ */ jsx(NumberInput, { ...props, ref, state });
3942
3885
  };
@@ -3948,8 +3891,18 @@ var Textarea = ({
3948
3891
  variant,
3949
3892
  sizing,
3950
3893
  focusVariant,
3894
+ // value handling
3895
+ value: valueProp,
3896
+ defaultValue,
3897
+ onValueChange,
3951
3898
  ...rest
3952
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
+ });
3953
3906
  return /* @__PURE__ */ jsx(
3954
3907
  InputGroup,
3955
3908
  {
@@ -3958,7 +3911,7 @@ var Textarea = ({
3958
3911
  focusVariant,
3959
3912
  variant,
3960
3913
  className: containerClassName,
3961
- children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref })
3914
+ children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref, value, onValueChange: setValue })
3962
3915
  }
3963
3916
  );
3964
3917
  };
@@ -3966,12 +3919,10 @@ var FormGroupTextarea = (props) => {
3966
3919
  const { state } = useFormGroupContext();
3967
3920
  return /* @__PURE__ */ jsx(Textarea, { state, ...props });
3968
3921
  };
3969
-
3970
- // src/components/Input/Input.tsx
3971
3922
  init_icons();
3972
3923
  init_utils2();
3973
3924
 
3974
- // src/components/Input/utils.ts
3925
+ // src/blocks/TextInput/utils.ts
3975
3926
  init_utils2();
3976
3927
  var genInputTestId = (prefix = "") => {
3977
3928
  const ps = createPrefixedString(prefix);
@@ -3982,7 +3933,11 @@ var genInputTestId = (prefix = "") => {
3982
3933
  clearButton: ps`clear-button`
3983
3934
  };
3984
3935
  };
3985
- var Input = ({
3936
+ var sanitizeTextInputValue = (value) => {
3937
+ if (typeof value === "string" && value.trim() === "") return "";
3938
+ return value;
3939
+ };
3940
+ var TextInput = ({
3986
3941
  ref: forwardedRef,
3987
3942
  state = "default",
3988
3943
  sizing = "default",
@@ -4004,23 +3959,28 @@ var Input = ({
4004
3959
  focusVariant = "default",
4005
3960
  onChange,
4006
3961
  onBlur,
4007
- value,
3962
+ onValueChange,
3963
+ onValueBlur,
3964
+ value: valueProp,
4008
3965
  defaultValue,
4009
3966
  ...inputProps
4010
3967
  }) => {
4011
- const [hasUncontrolledValue, setHasUncontrolledValue] = useState(() => !!defaultValue);
4012
- const hasValue = !!value || hasUncontrolledValue;
4013
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
+ });
4014
3976
  const testId = genInputTestId(prefixTestId);
4015
- const isClearButtonVisible = hasValue && !disabled && !readOnly || !!onClear;
3977
+ const isClearButtonVisible = !!value && !disabled && !readOnly || !!onClear;
4016
3978
  const handleChange = (event) => {
4017
- const val = event.target.value;
4018
- setHasUncontrolledValue(val !== "");
3979
+ setValue(event.target.value);
4019
3980
  onChange?.(event);
4020
3981
  };
4021
3982
  const handleBlur = (event) => {
4022
- const val = event.target.value;
4023
- setHasUncontrolledValue(val !== "");
3983
+ onValueBlur?.(event.target.value);
4024
3984
  onBlur?.(event);
4025
3985
  };
4026
3986
  const handleClear = () => {
@@ -4028,11 +3988,8 @@ var Input = ({
4028
3988
  inputRef.current.value = "";
4029
3989
  inputRef.current.focus();
4030
3990
  onClear?.();
4031
- setHasUncontrolledValue(false);
4032
- onChange?.(createChangeInputEvent(inputRef.current));
3991
+ handleChange(createChangeInputEvent(inputRef.current));
4033
3992
  };
4034
- const isControlled = value !== void 0;
4035
- const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
4036
3993
  return /* @__PURE__ */ jsxs(
4037
3994
  InputGroup,
4038
3995
  {
@@ -4048,7 +4005,7 @@ var Input = ({
4048
4005
  InputGroup.Input,
4049
4006
  {
4050
4007
  ...inputProps,
4051
- ...valueProp,
4008
+ value,
4052
4009
  autoFocus,
4053
4010
  type,
4054
4011
  onChange: handleChange,
@@ -4087,48 +4044,7 @@ var Input = ({
4087
4044
  }
4088
4045
  );
4089
4046
  };
4090
- var sanitizeTextInputValue = (value) => {
4091
- if (typeof value === "string" && value.trim() === "") return "";
4092
- return value;
4093
- };
4094
- var TextInput = ({
4095
- ref,
4096
- value,
4097
- defaultValue,
4098
- type = "text",
4099
- variant,
4100
- onValueChange,
4101
- onChange,
4102
- onValueBlur,
4103
- onBlur,
4104
- ...props
4105
- }) => {
4106
- const handleChange = (event) => {
4107
- onValueChange?.(event.target.value);
4108
- onChange?.(event);
4109
- };
4110
- const handleBlur = (event) => {
4111
- onValueBlur?.(event.target.value);
4112
- onBlur?.(event);
4113
- };
4114
- return /* @__PURE__ */ jsx(
4115
- Input,
4116
- {
4117
- ...props,
4118
- ref,
4119
- onChange: handleChange,
4120
- onBlur: handleBlur,
4121
- type,
4122
- variant,
4123
- value: sanitizeTextInputValue(value),
4124
- defaultValue: sanitizeTextInputValue(defaultValue)
4125
- }
4126
- );
4127
- };
4128
- var FormGroupTextInput = ({
4129
- ref,
4130
- ...props
4131
- }) => {
4047
+ var FormGroupTextInput = ({ ref, ...props }) => {
4132
4048
  const { state } = useFormGroupContext();
4133
4049
  return /* @__PURE__ */ jsx(TextInput, { state, ...props, ref });
4134
4050
  };
@@ -4142,6 +4058,74 @@ FormGroup.NumberInput = FormGroupNumberInput;
4142
4058
  FormGroup.ColorInput = FormGroupColorInput;
4143
4059
  FormGroup.Textarea = FormGroupTextarea;
4144
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
+
4145
4129
  // src/components/Label/Label.tsx
4146
4130
  init_utils2();
4147
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)" });
@@ -4162,9 +4146,12 @@ var Label2 = ({ className, children, id, htmlFor, ...rest }) => /* @__PURE__ */
4162
4146
  Label2.Optional = Optional;
4163
4147
  Label2.Required = Required;
4164
4148
 
4165
- // src/components/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4166
- init_utils2();
4149
+ // src/blocks/MarkdownEditor/plugins/toolbar/LinkPanel.tsx
4150
+ init_icons();
4151
+
4152
+ // src/blocks/MarkdownEditor/plugins/toolbar/ToolbarButton.tsx
4167
4153
  init_Tooltip2();
4154
+ init_utils2();
4168
4155
  var ToolbarButton = ({
4169
4156
  active,
4170
4157
  disabled,
@@ -4542,7 +4529,7 @@ var ToolbarPlugin = () => {
4542
4529
  );
4543
4530
  };
4544
4531
 
4545
- // src/components/MarkdownEditor/theme.ts
4532
+ // src/blocks/MarkdownEditor/theme.ts
4546
4533
  var editorTheme = {
4547
4534
  link: "tw-cursor-pointer !tw-text-primary tw-underline",
4548
4535
  text: {