@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.cjs CHANGED
@@ -9,6 +9,7 @@ var reactTooltip = require('@radix-ui/react-tooltip');
9
9
  var classVarianceAuthority = require('class-variance-authority');
10
10
  var brandRegistry = require('@keboola/brand-registry');
11
11
  var jsxRuntime = require('react/jsx-runtime');
12
+ var reactDom = require('react-dom');
12
13
  var DOMPurify = require('dompurify');
13
14
  var reactSlot = require('@radix-ui/react-slot');
14
15
  var lucide_react_star = require('lucide-react');
@@ -251,6 +252,7 @@ var Tooltip = ({
251
252
  placement = "right",
252
253
  forceHide = false,
253
254
  forceShow = false,
255
+ delayDuration,
254
256
  // trigger props
255
257
  triggerAsChild = false
256
258
  }) => {
@@ -270,6 +272,7 @@ var Tooltip = ({
270
272
  {
271
273
  open: !!tooltip && (open || forceShow) && !forceHide,
272
274
  onOpenChange: setOpen,
275
+ delayDuration,
273
276
  disableHoverableContent: isActionVariant,
274
277
  children: [
275
278
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -402,6 +405,7 @@ var Keboola = react.forwardRef(
402
405
  width: size,
403
406
  height: size,
404
407
  viewBox: "0 0 300 512",
408
+ overflow: "visible",
405
409
  fill: color,
406
410
  className: cn("lucide", className),
407
411
  ...rest,
@@ -860,10 +864,13 @@ var ClipboardButton = ({
860
864
  var MIN_SCALE = 0.5;
861
865
  var MAX_SCALE = 3;
862
866
  var ZOOM_STEP = 0.1;
863
- var ZoomableSvg = ({ html, copyText, className }) => {
867
+ var ZoomableSvg = ({ html, copyText, className, allowForeignObject }) => {
864
868
  const safeHtml = react.useMemo(
865
- () => DOMPurify__default.default.sanitize(html, { USE_PROFILES: { svg: true, svgFilters: true } }),
866
- [html]
869
+ () => DOMPurify__default.default.sanitize(html, {
870
+ USE_PROFILES: { svg: true, svgFilters: true },
871
+ ...allowForeignObject ? { ADD_TAGS: ["foreignObject"] } : {}
872
+ }),
873
+ [html, allowForeignObject]
867
874
  );
868
875
  const containerRef = react.useRef(null);
869
876
  const [scale, setScale] = react.useState(1);
@@ -892,7 +899,7 @@ var ZoomableSvg = ({ html, copyText, className }) => {
892
899
  };
893
900
  el.addEventListener("wheel", onWheel, { passive: false });
894
901
  return () => el.removeEventListener("wheel", onWheel);
895
- }, []);
902
+ }, [isFullscreen]);
896
903
  const didDragRef = react.useRef(false);
897
904
  const handleMouseDown = react.useCallback(
898
905
  (e) => {
@@ -999,14 +1006,18 @@ var ZoomableSvg = ({ html, copyText, className }) => {
999
1006
  }
1000
1007
  );
1001
1008
  if (isFullscreen) {
1002
- return /* @__PURE__ */ jsxRuntime.jsx(
1003
- "div",
1004
- {
1005
- role: "presentation",
1006
- className: "tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1007
- onClick: stopPropagation,
1008
- children: diagramContent
1009
- }
1009
+ return reactDom.createPortal(
1010
+ /* @__PURE__ */ jsxRuntime.jsx(
1011
+ "div",
1012
+ {
1013
+ role: "presentation",
1014
+ "data-testid": "zoomable-svg-fullscreen",
1015
+ className: "tailwindcss-preflight tw-fixed tw-inset-0 tw-z-[1060] tw-bg-muted tw-p-4",
1016
+ onClick: stopPropagation,
1017
+ children: diagramContent
1018
+ }
1019
+ ),
1020
+ document.body
1010
1021
  );
1011
1022
  }
1012
1023
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -1020,15 +1031,47 @@ var ZoomableSvg = ({ html, copyText, className }) => {
1020
1031
  }
1021
1032
  );
1022
1033
  };
1034
+
1035
+ // src/blocks/MermaidDiagram/svgTransforms.ts
1036
+ var HTML_TAG = /<[^>]+>/g;
1037
+ var FOREIGN_OBJECT = /(<foreignObject\b[^>]*>)([\s\S]*?)(<\/foreignObject>)/g;
1038
+ var ROOT_SVG_TAG = /^(\s*<svg\b)([^>]*)(>)/i;
1039
+ var flattenForeignObjectLabels = (svg) => svg.replace(FOREIGN_OBJECT, (_match, open, inner, close) => {
1040
+ const text = inner.replace(HTML_TAG, " ").replace(/\s+/g, " ").trim();
1041
+ return `${open}${text}${close}`;
1042
+ });
1043
+ var STYLE_ATTR = /\s+style="([^"]*)"/i;
1044
+ var makeResponsive = (svgString) => {
1045
+ const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1046
+ const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1047
+ return svgString.replace(ROOT_SVG_TAG, (_match, open, attrs, close) => {
1048
+ const existingStyle = attrs.match(STYLE_ATTR)?.[1] ?? "";
1049
+ const styleDecls = existingStyle.replace(/max-width:\s*[^;"]*;?\s*/gi, "").replace(/\s+/g, " ").trim().replace(/;$/, "");
1050
+ let nextAttrs = attrs.replace(/\s+width="[^"]*"/i, "").replace(/\s+height="[^"]*"/i, "").replace(STYLE_ATTR, "");
1051
+ nextAttrs += ' width="100%"';
1052
+ const styleParts = [styleDecls, vbWidth ? `max-width: ${vbWidth}px` : ""].filter(Boolean).join("; ");
1053
+ if (styleParts) nextAttrs += ` style="${styleParts}"`;
1054
+ return `${open}${nextAttrs}${close}`;
1055
+ });
1056
+ };
1023
1057
  var PRIMARY_FALLBACK_CHANNELS = "31 143 255";
1024
1058
  var resolvePrimary = () => {
1025
1059
  const channels = typeof document === "undefined" ? PRIMARY_FALLBACK_CHANNELS : getComputedStyle(document.documentElement).getPropertyValue("--color-primary").trim() || PRIMARY_FALLBACK_CHANNELS;
1026
1060
  return `rgb(${channels})`;
1027
1061
  };
1028
1062
  var mermaidPromise = null;
1063
+ var registerLucideIconPack = (m) => {
1064
+ m.registerIconPacks([
1065
+ {
1066
+ name: "lucide",
1067
+ loader: () => import('@iconify-json/lucide/icons.json').then((mod) => mod.default)
1068
+ }
1069
+ ]);
1070
+ };
1029
1071
  var getMermaid = () => {
1030
1072
  if (!mermaidPromise) {
1031
1073
  mermaidPromise = import('mermaid').then((m) => {
1074
+ registerLucideIconPack(m.default);
1032
1075
  m.default.initialize({
1033
1076
  startOnLoad: false,
1034
1077
  securityLevel: "strict",
@@ -1092,7 +1135,9 @@ var getMermaid = () => {
1092
1135
  return mermaidPromise;
1093
1136
  };
1094
1137
  var stripFontImports = (svg) => svg.replace(/@import\s+url\([^)]*fonts\.googleapis\.com[^)]*\);?\s*/g, "");
1138
+ var hasIconSyntax = (code) => /@\{[^}]*\bicon\s*:/.test(code) || /\b(?:icon|service|group)\b[^\n(]*\(\s*[\w-]+:/.test(code) || /\bfa[bslr]?:fa-/.test(code);
1095
1139
  var tryFastRender = (code) => {
1140
+ if (hasIconSyntax(code)) return null;
1096
1141
  try {
1097
1142
  return stripFontImports(
1098
1143
  beautifulMermaid.renderMermaidSVG(code, {
@@ -1102,27 +1147,11 @@ var tryFastRender = (code) => {
1102
1147
  font: "Inter, system-ui, sans-serif"
1103
1148
  })
1104
1149
  );
1105
- } catch {
1150
+ } catch (err) {
1151
+ console.debug("[MermaidDiagram] fast render unavailable, using async fallback:", err);
1106
1152
  return null;
1107
1153
  }
1108
1154
  };
1109
- var makeResponsive = (svgString) => {
1110
- const viewBoxMatch = svgString.match(/viewBox="[^"]*\s([\d.]+)\s[\d.]+"/);
1111
- const vbWidth = viewBoxMatch ? Math.round(Number(viewBoxMatch[1])) : void 0;
1112
- let result = svgString.replace(/(<svg[^>]*?)\s+width="[^"]*"/i, '$1 width="100%"').replace(/(<svg[^>]*?)\s+height="[^"]*"/i, "$1");
1113
- if (!vbWidth) return result;
1114
- const hasStyle = /(<svg[^>]*?)\s+style="([^"]*)"/i.test(result);
1115
- if (hasStyle) {
1116
- result = result.replace(/(<svg[^>]*?)\s+style="([^"]*)"/i, (_m, pre, styles) => {
1117
- const cleaned = styles.replace(/max-width:\s*[^;"]*;?\s*/g, "").trim();
1118
- const combined = [cleaned, `max-width: ${vbWidth}px`].filter(Boolean).join("; ");
1119
- return `${pre} style="${combined}"`;
1120
- });
1121
- } else {
1122
- result = result.replace(/<svg/, `<svg style="max-width: ${vbWidth}px"`);
1123
- }
1124
- return result;
1125
- };
1126
1155
  var RENDER_DEBOUNCE_MS = 300;
1127
1156
  var svgCache = /* @__PURE__ */ new Map();
1128
1157
  var resolveSyncSvg = (code) => {
@@ -1163,8 +1192,9 @@ var MermaidDiagram = ({ code }) => {
1163
1192
  try {
1164
1193
  const result = await mermaidModule.default.render(rendererId, code, container);
1165
1194
  if (renderIdRef.current === currentRenderId && result) {
1166
- svgCache.set(code, result.svg);
1167
- setSvg(result.svg);
1195
+ const svgOutput = flattenForeignObjectLabels(result.svg);
1196
+ svgCache.set(code, svgOutput);
1197
+ setSvg(svgOutput);
1168
1198
  setRenderFailed(false);
1169
1199
  }
1170
1200
  } finally {
@@ -1211,7 +1241,8 @@ var MermaidDiagram = ({ code }) => {
1211
1241
  copyText: `\`\`\`mermaid
1212
1242
  ${code}
1213
1243
  \`\`\``,
1214
- className: "tw-my-3"
1244
+ className: "tw-my-3",
1245
+ allowForeignObject: true
1215
1246
  },
1216
1247
  code
1217
1248
  );