@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.
package/dist/mermaid.js CHANGED
@@ -7,6 +7,7 @@ import { Root as Root$1, Trigger, Portal, Content } from '@radix-ui/react-toolti
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { keboolaLegacySidebar, keboolaLegacyTopnav } from '@keboola/brand-registry';
9
9
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
+ import { createPortal } from 'react-dom';
10
11
  import DOMPurify from 'dompurify';
11
12
  import { Root, Slottable } from '@radix-ui/react-slot';
12
13
  import * as lucide_react_star from 'lucide-react';
@@ -225,6 +226,7 @@ var Tooltip = ({
225
226
  placement = "right",
226
227
  forceHide = false,
227
228
  forceShow = false,
229
+ delayDuration,
228
230
  // trigger props
229
231
  triggerAsChild = false
230
232
  }) => {
@@ -244,6 +246,7 @@ var Tooltip = ({
244
246
  {
245
247
  open: !!tooltip && (open || forceShow) && !forceHide,
246
248
  onOpenChange: setOpen,
249
+ delayDuration,
247
250
  disableHoverableContent: isActionVariant,
248
251
  children: [
249
252
  /* @__PURE__ */ jsx(
@@ -376,6 +379,7 @@ var Keboola = forwardRef(
376
379
  width: size,
377
380
  height: size,
378
381
  viewBox: "0 0 300 512",
382
+ overflow: "visible",
379
383
  fill: color,
380
384
  className: cn("lucide", className),
381
385
  ...rest,
@@ -834,10 +838,13 @@ var ClipboardButton = ({
834
838
  var MIN_SCALE = 0.5;
835
839
  var MAX_SCALE = 3;
836
840
  var ZOOM_STEP = 0.1;
837
- var ZoomableSvg = ({ html, copyText, className }) => {
841
+ var ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
838
842
  const safeHtml = useMemo(
839
- () => DOMPurify.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
840
- [html]
843
+ () => DOMPurify.sanitize(html, {
844
+ USE_PROFILES: { svg: true, svgFilters: true },
845
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
846
+ }),
847
+ [html, allowForeignObject]
841
848
  );
842
849
  const containerRef = useRef(null);
843
850
  const [scale, setScale] = useState(1);
@@ -866,7 +873,7 @@ var ZoomableSvg = ({ html, copyText, className }) => {
866
873
  };
867
874
  el.addEventListener("wheel", onWheel, { passive: false });
868
875
  return () => el.removeEventListener("wheel", onWheel);
869
- }, []);
876
+ }, [isFullscreen]);
870
877
  const didDragRef = useRef(false);
871
878
  const handleMouseDown = useCallback(
872
879
  (e) => {
@@ -973,14 +980,18 @@ var ZoomableSvg = ({ html, copyText, className }) => {
973
980
  }
974
981
  );
975
982
  if (isFullscreen) {
976
- return /* @__PURE__ */ jsx(
977
- "div",
978
- {
979
- role: "presentation",
980
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
981
- onClick: stopPropagation,
982
- children: diagramContent
983
- }
983
+ return createPortal(
984
+ /* @__PURE__ */ jsx(
985
+ "div",
986
+ {
987
+ role: "presentation",
988
+ "data-testid": "zoomable-svg-fullscreen",
989
+ className: "tailwindcss-preflight tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
990
+ onClick: stopPropagation,
991
+ children: diagramContent
992
+ }
993
+ ),
994
+ document.body
984
995
  );
985
996
  }
986
997
  return /* @__PURE__ */ jsx(
@@ -994,15 +1005,47 @@ var ZoomableSvg = ({ html, copyText, className }) => {
994
1005
  }
995
1006
  );
996
1007
  };
1008
+
1009
+ // src/blocks/MermaidDiagram/svgTransforms.ts
1010
+ var HTML_TAG = /<[^>]+>/g;
1011
+ var FOREIGN_OBJECT = /(<foreignObject\b[^>]*>)([\s\S]*?)(<\/foreignObject>)/g;
1012
+ var ROOT_SVG_TAG = /^(\s*<svg\b)([^>]*)(>)/i;
1013
+ var flattenForeignObjectLabels = (svg) => svg.replace(FOREIGN_OBJECT, (_match, open, inner, close) => {
1014
+ const text = inner.replace(HTML_TAG, " ").replace(/\s+/g, " ").trim();
1015
+ return `${open}${text}${close}`;
1016
+ });
1017
+ var STYLE_ATTR = /\s+style="([^"]*)"/i;
1018
+ var makeResponsive = (svgString) => {
1019
+ const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1020
+ const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1021
+ return svgString.replace(ROOT_SVG_TAG, (_match, open, attrs, close) => {
1022
+ const existingStyle = attrs.match(STYLE_ATTR)?.[1] ?? "";
1023
+ const styleDecls = existingStyle.replace(/max-width:\s*[^;"]*;?\s*/gi, "").replace(/\s+/g, " ").trim().replace(/;$/, "");
1024
+ let nextAttrs = attrs.replace(/\s+width="[^"]*"/i, "").replace(/\s+height="[^"]*"/i, "").replace(STYLE_ATTR, "");
1025
+ nextAttrs += ' width="100%"';
1026
+ const styleParts = [styleDecls, vbWidth ? `max-width: ${vbWidth}px` : ""].filter(Boolean).join("; ");
1027
+ if (styleParts) nextAttrs += ` style="${styleParts}"`;
1028
+ return `${open}${nextAttrs}${close}`;
1029
+ });
1030
+ };
997
1031
  var PRIMARY_FALLBACK_CHANNELS = "31 143 255";
998
1032
  var resolvePrimary = () => {
999
1033
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1000
1034
  return `rgb(${channels})`;
1001
1035
  };
1002
1036
  var mermaidPromise = null;
1037
+ var registerLucideIconPack = (m) => {
1038
+ m.registerIconPacks([
1039
+ {
1040
+ name: "lucide",
1041
+ loader: () => import('@iconify-json/lucide/icons.json').then((mod) => mod.default)
1042
+ }
1043
+ ]);
1044
+ };
1003
1045
  var getMermaid = () => {
1004
1046
  if (!mermaidPromise) {
1005
1047
  mermaidPromise = import('mermaid').then((m) => {
1048
+ registerLucideIconPack(m.default);
1006
1049
  m.default.initialize({
1007
1050
  startOnLoad: false,
1008
1051
  securityLevel: "strict",
@@ -1066,7 +1109,9 @@ var getMermaid = () => {
1066
1109
  return mermaidPromise;
1067
1110
  };
1068
1111
  var stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1112
+ var hasIconSyntax = (code) => /@\{[^}]*\bicon\s*:/.test(code) || /\b(?:icon|service|group)\b[^\n(]*\(\s*[\w-]+:/.test(code) || /\bfa[bslr]?:fa-/.test(code);
1069
1113
  var tryFastRender = (code) => {
1114
+ if (hasIconSyntax(code)) return null;
1070
1115
  try {
1071
1116
  return stripFontImports(
1072
1117
  renderMermaidSVG(code, {
@@ -1076,27 +1121,11 @@ var tryFastRender = (code) => {
1076
1121
  font: "Inter, system-ui, sans-serif"
1077
1122
  })
1078
1123
  );
1079
- } catch {
1124
+ } catch (err) {
1125
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1080
1126
  return null;
1081
1127
  }
1082
1128
  };
1083
- var makeResponsive = (svgString) => {
1084
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1085
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1086
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1087
- if (!vbWidth) return result;
1088
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1089
- if (hasStyle) {
1090
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1091
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1092
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1093
- return `${pre} style="${combined}"`;
1094
- });
1095
- } else {
1096
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1097
- }
1098
- return result;
1099
- };
1100
1129
  var RENDER_DEBOUNCE_MS = 300;
1101
1130
  var svgCache = /* @__PURE__ */ new Map();
1102
1131
  var resolveSyncSvg = (code) => {
@@ -1137,8 +1166,9 @@ var MermaidDiagram = ({ code }) => {
1137
1166
  try {
1138
1167
  const result = await mermaidModule.default.render(rendererId, code, container);
1139
1168
  if (renderIdRef.current === currentRenderId && result) {
1140
- svgCache.set(code, result.svg);
1141
- setSvg(result.svg);
1169
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1170
+ svgCache.set(code, svgOutput);
1171
+ setSvg(svgOutput);
1142
1172
  setRenderFailed(false);
1143
1173
  }
1144
1174
  } finally {
@@ -1185,7 +1215,8 @@ var MermaidDiagram = ({ code }) => {
1185
1215
  copyText: `\`\`\`mermaid
1186
1216
  ${code}
1187
1217
  \`\`\``,
1188
- className: "tw-my-3"
1218
+ className: "tw-my-3",
1219
+ allowForeignObject: true
1189
1220
  },
1190
1221
  code
1191
1222
  );