@windrun-huaiin/third-ui 15.1.0 → 16.0.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.
Files changed (133) hide show
  1. package/LICENSE +1 -1
  2. package/dist/ai/ai-chat-composer.d.ts +2 -0
  3. package/dist/ai/ai-chat-composer.js +47 -0
  4. package/dist/ai/ai-chat-composer.mjs +45 -0
  5. package/dist/ai/ai-markdown.d.ts +2 -0
  6. package/dist/ai/ai-markdown.js +36 -0
  7. package/dist/ai/ai-markdown.mjs +34 -0
  8. package/dist/ai/ai-message-actions.d.ts +2 -0
  9. package/dist/ai/ai-message-actions.js +14 -0
  10. package/dist/ai/ai-message-actions.mjs +12 -0
  11. package/dist/ai/ai-message-bubble.d.ts +2 -0
  12. package/dist/ai/ai-message-bubble.js +66 -0
  13. package/dist/ai/ai-message-bubble.mjs +64 -0
  14. package/dist/ai/ai-message-content.d.ts +2 -0
  15. package/dist/ai/ai-message-content.js +63 -0
  16. package/dist/ai/ai-message-content.mjs +61 -0
  17. package/dist/ai/ai-message-list.d.ts +2 -0
  18. package/dist/ai/ai-message-list.js +24 -0
  19. package/dist/ai/ai-message-list.mjs +22 -0
  20. package/dist/ai/ai-message-meta.d.ts +2 -0
  21. package/dist/ai/ai-message-meta.js +38 -0
  22. package/dist/ai/ai-message-meta.mjs +36 -0
  23. package/dist/ai/ai-status-indicator.d.ts +2 -0
  24. package/dist/ai/ai-status-indicator.js +51 -0
  25. package/dist/ai/ai-status-indicator.mjs +49 -0
  26. package/dist/ai/index.d.ts +11 -0
  27. package/dist/ai/index.js +33 -0
  28. package/dist/ai/index.mjs +11 -0
  29. package/dist/ai/types.d.ts +110 -0
  30. package/dist/ai/use-ai-conversation.d.ts +13 -0
  31. package/dist/ai/use-ai-conversation.js +276 -0
  32. package/dist/ai/use-ai-conversation.mjs +274 -0
  33. package/dist/clerk/clerk-organization-client.js +2 -2
  34. package/dist/clerk/clerk-organization-client.mjs +2 -2
  35. package/dist/clerk/clerk-page-generator.d.ts +1 -1
  36. package/dist/clerk/clerk-user-client.js +2 -2
  37. package/dist/clerk/clerk-user-client.mjs +2 -2
  38. package/dist/clerk/fingerprint/fingerprint-provider.js +9 -9
  39. package/dist/clerk/fingerprint/fingerprint-provider.mjs +9 -9
  40. package/dist/fuma/base/custom-header.js +4 -4
  41. package/dist/fuma/base/custom-header.mjs +4 -4
  42. package/dist/fuma/mdx/banner.js +3 -3
  43. package/dist/fuma/mdx/banner.mjs +3 -3
  44. package/dist/fuma/mdx/fuma-github-info.js +3 -3
  45. package/dist/fuma/mdx/fuma-github-info.mjs +3 -3
  46. package/dist/fuma/mdx/gradient-button.js +3 -3
  47. package/dist/fuma/mdx/gradient-button.mjs +3 -3
  48. package/dist/fuma/mdx/index.d.ts +1 -0
  49. package/dist/fuma/mdx/index.js +2 -0
  50. package/dist/fuma/mdx/index.mjs +1 -0
  51. package/dist/fuma/mdx/markdown-component-map.d.ts +3 -0
  52. package/dist/fuma/mdx/markdown-component-map.js +73 -0
  53. package/dist/fuma/mdx/markdown-component-map.mjs +71 -0
  54. package/dist/fuma/mdx/mermaid.d.ts +2 -1
  55. package/dist/fuma/mdx/mermaid.js +130 -6
  56. package/dist/fuma/mdx/mermaid.mjs +130 -6
  57. package/dist/fuma/mdx/toc-base.js +4 -4
  58. package/dist/fuma/mdx/toc-base.mjs +4 -4
  59. package/dist/fuma/mdx/trophy-card.js +2 -2
  60. package/dist/fuma/mdx/trophy-card.mjs +2 -2
  61. package/dist/fuma/mdx/zia-card.js +3 -3
  62. package/dist/fuma/mdx/zia-card.mjs +3 -3
  63. package/dist/fuma/mdx/zia-file.js +3 -3
  64. package/dist/fuma/mdx/zia-file.mjs +3 -3
  65. package/dist/main/ads-alert-dialog.js +2 -2
  66. package/dist/main/ads-alert-dialog.mjs +2 -2
  67. package/dist/main/credit/credit-nav-button.js +2 -2
  68. package/dist/main/credit/credit-nav-button.mjs +2 -2
  69. package/dist/main/credit/credit-overview-client.js +4 -4
  70. package/dist/main/credit/credit-overview-client.mjs +4 -4
  71. package/dist/main/footer.js +2 -2
  72. package/dist/main/footer.mjs +2 -2
  73. package/dist/main/go-to-top.js +2 -2
  74. package/dist/main/go-to-top.mjs +2 -2
  75. package/dist/main/hero-media.d.ts +14 -0
  76. package/dist/main/hero-media.js +12 -0
  77. package/dist/main/hero-media.mjs +10 -0
  78. package/dist/main/hero-section.d.ts +10 -0
  79. package/dist/main/hero-section.js +11 -0
  80. package/dist/main/hero-section.mjs +9 -0
  81. package/dist/main/index.d.ts +3 -0
  82. package/dist/main/index.js +6 -0
  83. package/dist/main/index.mjs +3 -0
  84. package/dist/main/info-tooltip.d.ts +8 -0
  85. package/dist/main/info-tooltip.js +48 -0
  86. package/dist/main/info-tooltip.mjs +46 -0
  87. package/dist/main/pill-select/x-pill-select.js +2 -2
  88. package/dist/main/pill-select/x-pill-select.mjs +2 -2
  89. package/dist/main/pill-select/x-token-input.js +2 -2
  90. package/dist/main/pill-select/x-token-input.mjs +2 -2
  91. package/dist/main/x-button.js +3 -3
  92. package/dist/main/x-button.mjs +3 -3
  93. package/package.json +16 -3
  94. package/src/ai/ai-chat-composer.tsx +187 -0
  95. package/src/ai/ai-markdown.tsx +45 -0
  96. package/src/ai/ai-message-actions.tsx +16 -0
  97. package/src/ai/ai-message-bubble.tsx +138 -0
  98. package/src/ai/ai-message-content.tsx +149 -0
  99. package/src/ai/ai-message-list.tsx +59 -0
  100. package/src/ai/ai-message-meta.tsx +56 -0
  101. package/src/ai/ai-status-indicator.tsx +61 -0
  102. package/src/ai/index.ts +13 -0
  103. package/src/ai/types.ts +131 -0
  104. package/src/ai/use-ai-conversation.ts +422 -0
  105. package/src/clerk/clerk-organization-client.tsx +5 -5
  106. package/src/clerk/clerk-page-generator.tsx +1 -1
  107. package/src/clerk/clerk-user-client.tsx +4 -4
  108. package/src/clerk/fingerprint/fingerprint-provider.tsx +34 -22
  109. package/src/fuma/base/custom-header.tsx +5 -5
  110. package/src/fuma/mdx/banner.tsx +3 -3
  111. package/src/fuma/mdx/fuma-github-info.tsx +4 -4
  112. package/src/fuma/mdx/gradient-button.tsx +3 -3
  113. package/src/fuma/mdx/index.ts +2 -1
  114. package/src/fuma/mdx/markdown-component-map.tsx +174 -0
  115. package/src/fuma/mdx/mermaid.tsx +145 -10
  116. package/src/fuma/mdx/toc-base.tsx +5 -5
  117. package/src/fuma/mdx/trophy-card.tsx +2 -2
  118. package/src/fuma/mdx/zia-card.tsx +3 -3
  119. package/src/fuma/mdx/zia-file.tsx +3 -3
  120. package/src/main/ads-alert-dialog.tsx +5 -5
  121. package/src/main/credit/credit-nav-button.tsx +3 -3
  122. package/src/main/credit/credit-overview-client.tsx +15 -7
  123. package/src/main/features.tsx +5 -3
  124. package/src/main/footer.tsx +4 -5
  125. package/src/main/go-to-top.tsx +2 -2
  126. package/src/main/hero-media.tsx +53 -0
  127. package/src/main/hero-section.tsx +36 -0
  128. package/src/main/index.ts +5 -0
  129. package/src/main/info-tooltip.tsx +99 -0
  130. package/src/main/language-detector.tsx +4 -4
  131. package/src/main/pill-select/x-pill-select.tsx +2 -2
  132. package/src/main/pill-select/x-token-input.tsx +2 -2
  133. package/src/main/x-button.tsx +4 -4
@@ -3,9 +3,10 @@
3
3
 
4
4
  var tslib = require('tslib');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
- var server = require('@windrun-huaiin/base-ui/components/server');
6
+ var icons = require('@windrun-huaiin/base-ui/icons');
7
7
  var utils = require('@windrun-huaiin/lib/utils');
8
8
  var nextThemes = require('next-themes');
9
+ var rough = require('roughjs');
9
10
  var React = require('react');
10
11
  var lib = require('@windrun-huaiin/base-ui/lib');
11
12
 
@@ -15,7 +16,7 @@ function sanitizeFilename(name) {
15
16
  .replace(/\s+/g, '_')
16
17
  .slice(0, 120);
17
18
  }
18
- function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview = true }) {
19
+ function Mermaid({ chart, title, watermarkEnabled, watermarkText, handDrawn = true, enablePreview = true }) {
19
20
  const id = React.useId();
20
21
  const [svg, setSvg] = React.useState('');
21
22
  const { resolvedTheme } = nextThemes.useTheme();
@@ -45,9 +46,9 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
45
46
  try {
46
47
  mermaid.initialize(mermaidConfig);
47
48
  const { svg } = yield mermaid.render(id.replaceAll(':', ''), chart.replaceAll('\\n', '\n'));
48
- let svgWithWatermark = svg;
49
+ let svgWithWatermark = handDrawn ? applyHandDrawnStyle(svg) : svg;
49
50
  if (watermarkEnabled && watermarkText) {
50
- svgWithWatermark = addWatermarkToSvg(svg, watermarkText, lib.themeSvgIconColor);
51
+ svgWithWatermark = addWatermarkToSvg(svgWithWatermark, watermarkText, lib.themeSvgIconColor);
51
52
  }
52
53
  if (isMounted)
53
54
  setSvg(svgWithWatermark);
@@ -61,7 +62,7 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
61
62
  isMounted = false;
62
63
  setSvg('');
63
64
  };
64
- }, [chart, id, resolvedTheme, watermarkEnabled, watermarkText]);
65
+ }, [chart, id, resolvedTheme, watermarkEnabled, watermarkText, handDrawn]);
65
66
  // helpers for preview zoom
66
67
  const clamp = (v, min, max) => Math.min(Math.max(v, min), max);
67
68
  const resetTransform = React.useCallback(() => {
@@ -213,7 +214,7 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
213
214
  window.scrollTo(0, scrollY);
214
215
  };
215
216
  }, [open]);
216
- return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: enablePreview ? 'group relative cursor-zoom-in' : undefined, onClick: () => enablePreview && svg && setOpen(true), children: [jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: svg } }), enablePreview && svg && (jsxRuntime.jsx("div", { className: "pointer-events-none absolute right-2 top-2 hidden rounded bg-black/50 px-2 py-0.5 text-[12px] text-white group-hover:block", children: "Preview Chart" }))] }), title && (jsxRuntime.jsxs("div", { className: utils.cn("mt-2 flex items-center justify-center text-center text-[13px] font-italic", lib.themeIconColor), children: [jsxRuntime.jsx(server.globalLucideIcons.Mmd, { className: 'mr-1 h-4 w-4' }), jsxRuntime.jsx("span", { children: title })] })), enablePreview && open && (jsxRuntime.jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": typeof title === 'string' ? title : 'Mermaid Preview', className: "fixed inset-0 z-9999 flex items-center justify-center", children: [jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/60", onClick: () => { setOpen(false); resetTransform(); }, onWheel: (e) => { e.preventDefault(); e.stopPropagation(); }, onTouchMove: (e) => { e.preventDefault(); e.stopPropagation(); } }), jsxRuntime.jsxs("div", { className: "relative z-1 max-w-[95vw] w-[95vw] h-[88vh] p-0 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-md shadow-2xl overflow-hidden", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 px-3 py-2 border-b border-neutral-200 dark:border-neutral-700", children: [jsxRuntime.jsxs("div", { className: utils.cn("min-w-0 flex items-center gap-2 text-sm", lib.themeIconColor), children: [jsxRuntime.jsx(server.globalLucideIcons.Mmd, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "truncate max-w-[50vw]", children: title !== null && title !== void 0 ? title : 'Mermaid Preview' })] }), jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [jsxRuntime.jsx("button", { "aria-label": "Zoom out", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(-0.5), children: "\uFF0D" }), jsxRuntime.jsxs("span", { className: "mx-0.5 w-12 text-center text-[12px] select-none", children: [Math.round(scale * 100), "%"] }), jsxRuntime.jsx("button", { "aria-label": "Zoom in", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(0.5), children: "\uFF0B" }), jsxRuntime.jsx("div", { className: "mx-1 hidden h-4 w-px bg-neutral-300 dark:bg-neutral-700 sm:block" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 100%", className: "hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(1), children: "X1" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 200%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(2), children: "X2" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 300%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(3), children: "X3" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 1000%", className: "ml-1 hidden h-6 min-w-10 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(10), children: "X10" }), jsxRuntime.jsx("button", { "aria-label": "Reset", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: resetTransform, children: jsxRuntime.jsx(server.globalLucideIcons.RefreshCcw, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsx("button", { "aria-label": "Download SVG", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: handleDownload, children: jsxRuntime.jsx(server.globalLucideIcons.Download, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsx("button", { "aria-label": "Close", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: () => { setOpen(false); resetTransform(); }, children: jsxRuntime.jsx(server.globalLucideIcons.X, { className: "h-3.5 w-3.5" }) })] })] }), jsxRuntime.jsxs("div", { className: "relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900 overscroll-contain touch-none", onWheel: onWheel, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerCancel, children: [jsxRuntime.jsx("div", { className: "absolute left-1/2 top-1/2", style: { transform: `translate(-50%, -50%) translate(${translate.x}px, ${translate.y}px)` }, children: jsxRuntime.jsx("div", { style: { transform: `scale(${scale})`, transformOrigin: '50% 50%' }, dangerouslySetInnerHTML: { __html: svg } }) }), jsxRuntime.jsxs("div", { className: "absolute inset-x-3 bottom-3 rounded-md bg-white/92 px-3 py-2 shadow-sm backdrop-blur sm:hidden dark:bg-neutral-900/92", children: [jsxRuntime.jsxs("label", { className: "mb-1 flex items-center justify-between text-[11px] text-neutral-600 dark:text-neutral-300", children: [jsxRuntime.jsx("span", { children: "Zoom" }), jsxRuntime.jsxs("span", { children: [Math.round(scale * 100), "%"] })] }), jsxRuntime.jsx("input", { "aria-label": "Zoom slider", className: "block w-full", type: "range", min: "25", max: "1000", step: "5", value: Math.round(scale * 100), style: { accentColor: lib.themeSvgIconColor }, onChange: (e) => setScale(clamp(Number(e.target.value) / 100, 0.25, 10)) })] }), jsxRuntime.jsx("div", { className: "pointer-events-none absolute bottom-2 right-3 hidden rounded bg-black/40 px-2 py-1 text-xs text-white sm:block", children: "Drag to pan, click button to zoom-out or zoom-in" }), jsxRuntime.jsx("div", { className: "pointer-events-none absolute left-3 top-3 rounded bg-black/40 px-2 py-1 text-[11px] text-white sm:hidden", children: "Drag to pan, pinch to zoom-out or zoom-in" })] })] })] }))] }));
217
+ return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsxs("div", { className: enablePreview ? 'group relative cursor-zoom-in' : undefined, onClick: () => enablePreview && svg && setOpen(true), children: [jsxRuntime.jsx("div", { dangerouslySetInnerHTML: { __html: svg } }), enablePreview && svg && (jsxRuntime.jsx("div", { className: "pointer-events-none absolute right-2 top-2 hidden rounded bg-black/50 px-2 py-0.5 text-[12px] text-white group-hover:block", children: "Preview Chart" }))] }), title && (jsxRuntime.jsxs("div", { className: utils.cn("mt-2 flex items-center justify-center text-center text-[13px] font-italic", lib.themeIconColor), children: [jsxRuntime.jsx(icons.MmdIcon, { className: 'mr-1 h-4 w-4' }), jsxRuntime.jsx("span", { children: title })] })), enablePreview && open && (jsxRuntime.jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": typeof title === 'string' ? title : 'Mermaid Preview', className: "fixed inset-0 z-9999 flex items-center justify-center", children: [jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/60", onClick: () => { setOpen(false); resetTransform(); }, onWheel: (e) => { e.preventDefault(); e.stopPropagation(); }, onTouchMove: (e) => { e.preventDefault(); e.stopPropagation(); } }), jsxRuntime.jsxs("div", { className: "relative z-1 max-w-[95vw] w-[95vw] h-[88vh] p-0 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-md shadow-2xl overflow-hidden", children: [jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 px-3 py-2 border-b border-neutral-200 dark:border-neutral-700", children: [jsxRuntime.jsxs("div", { className: utils.cn("min-w-0 flex items-center gap-2 text-sm", lib.themeIconColor), children: [jsxRuntime.jsx(icons.MmdIcon, { className: "h-4 w-4" }), jsxRuntime.jsx("span", { className: "truncate max-w-[50vw]", children: title !== null && title !== void 0 ? title : 'Mermaid Preview' })] }), jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [jsxRuntime.jsx("button", { "aria-label": "Zoom out", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(-0.5), children: "\uFF0D" }), jsxRuntime.jsxs("span", { className: "mx-0.5 w-12 text-center text-[12px] select-none", children: [Math.round(scale * 100), "%"] }), jsxRuntime.jsx("button", { "aria-label": "Zoom in", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(0.5), children: "\uFF0B" }), jsxRuntime.jsx("div", { className: "mx-1 hidden h-4 w-px bg-neutral-300 dark:bg-neutral-700 sm:block" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 100%", className: "hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(1), children: "X1" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 200%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(2), children: "X2" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 300%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(3), children: "X3" }), jsxRuntime.jsx("button", { "aria-label": "Zoom 1000%", className: "ml-1 hidden h-6 min-w-10 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(10), children: "X10" }), jsxRuntime.jsx("button", { "aria-label": "Reset", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: resetTransform, children: jsxRuntime.jsx(icons.RefreshCcwIcon, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsx("button", { "aria-label": "Download SVG", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: handleDownload, children: jsxRuntime.jsx(icons.DownloadIcon, { className: "h-3.5 w-3.5" }) }), jsxRuntime.jsx("button", { "aria-label": "Close", className: utils.cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", lib.themeIconColor), onClick: () => { setOpen(false); resetTransform(); }, children: jsxRuntime.jsx(icons.XIcon, { className: "h-3.5 w-3.5" }) })] })] }), jsxRuntime.jsxs("div", { className: "relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900 overscroll-contain touch-none", onWheel: onWheel, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerCancel, children: [jsxRuntime.jsx("div", { className: "absolute left-1/2 top-1/2", style: { transform: `translate(-50%, -50%) translate(${translate.x}px, ${translate.y}px)` }, children: jsxRuntime.jsx("div", { style: { transform: `scale(${scale})`, transformOrigin: '50% 50%' }, dangerouslySetInnerHTML: { __html: svg } }) }), jsxRuntime.jsxs("div", { className: "absolute inset-x-3 bottom-3 rounded-md bg-white/92 px-3 py-2 shadow-sm backdrop-blur sm:hidden dark:bg-neutral-900/92", children: [jsxRuntime.jsxs("label", { className: "mb-1 flex items-center justify-between text-[11px] text-neutral-600 dark:text-neutral-300", children: [jsxRuntime.jsx("span", { children: "Zoom" }), jsxRuntime.jsxs("span", { children: [Math.round(scale * 100), "%"] })] }), jsxRuntime.jsx("input", { "aria-label": "Zoom slider", className: "block w-full", type: "range", min: "25", max: "1000", step: "5", value: Math.round(scale * 100), style: { accentColor: lib.themeSvgIconColor }, onChange: (e) => setScale(clamp(Number(e.target.value) / 100, 0.25, 10)) })] }), jsxRuntime.jsx("div", { className: "pointer-events-none absolute bottom-2 right-3 hidden rounded bg-black/40 px-2 py-1 text-xs text-white sm:block", children: "Drag to pan, click button to zoom-out or zoom-in" }), jsxRuntime.jsx("div", { className: "pointer-events-none absolute left-3 top-3 rounded bg-black/40 px-2 py-1 text-[11px] text-white sm:hidden", children: "Drag to pan, pinch to zoom-out or zoom-in" })] })] })] }))] }));
217
218
  }
218
219
  function addWatermarkToSvg(svg, watermark, watermarkColor) {
219
220
  const watermarkText = `
@@ -232,5 +233,128 @@ function addWatermarkToSvg(svg, watermark, watermarkColor) {
232
233
  `;
233
234
  return svg.replace('</svg>', `${watermarkText}</svg>`);
234
235
  }
236
+ function applyHandDrawnStyle(svg) {
237
+ if (typeof window === 'undefined')
238
+ return svg;
239
+ try {
240
+ const parser = new DOMParser();
241
+ const doc = parser.parseFromString(svg, 'image/svg+xml');
242
+ const svgElement = doc.documentElement;
243
+ if (!svgElement || svgElement.tagName.toLowerCase() !== 'svg')
244
+ return svg;
245
+ const rc = rough.svg(svgElement);
246
+ const serializer = new XMLSerializer();
247
+ const getNumber = (value) => Number.parseFloat(value !== null && value !== void 0 ? value : '') || 0;
248
+ const getStyleValue = (element, name) => {
249
+ const inlineStyle = element.getAttribute('style');
250
+ if (inlineStyle) {
251
+ const match = inlineStyle.match(new RegExp(`(?:^|;)\\s*${name}\\s*:\\s*([^;]+)`));
252
+ if (match === null || match === void 0 ? void 0 : match[1])
253
+ return match[1].trim();
254
+ }
255
+ return element.getAttribute(name);
256
+ };
257
+ const applyAttributes = (source, target) => {
258
+ var _a;
259
+ for (const attr of source.getAttributeNames()) {
260
+ if (attr === 'x' || attr === 'y' || attr === 'x1' || attr === 'y1' || attr === 'x2' || attr === 'y2' || attr === 'width' || attr === 'height' || attr === 'rx' || attr === 'ry' || attr === 'points' || attr === 'd')
261
+ continue;
262
+ target.setAttribute(attr, (_a = source.getAttribute(attr)) !== null && _a !== void 0 ? _a : '');
263
+ }
264
+ };
265
+ const createOptions = (element) => {
266
+ var _a, _b;
267
+ const stroke = (_a = getStyleValue(element, 'stroke')) !== null && _a !== void 0 ? _a : '#000';
268
+ const fill = (_b = getStyleValue(element, 'fill')) !== null && _b !== void 0 ? _b : 'none';
269
+ const strokeWidth = getNumber(getStyleValue(element, 'stroke-width')) || 1.5;
270
+ return {
271
+ stroke,
272
+ fill: fill === 'none' ? undefined : fill,
273
+ strokeWidth,
274
+ roughness: 1.6,
275
+ bowing: 1.25,
276
+ fillStyle: fill === 'none' ? 'hachure' : 'solid',
277
+ fillWeight: 0.8,
278
+ hachureGap: 10,
279
+ preserveVertices: true,
280
+ seed: 7,
281
+ };
282
+ };
283
+ const replaceShape = (element, node) => {
284
+ var _a, _b;
285
+ if (!node || !element.parentNode)
286
+ return;
287
+ applyAttributes(element, node);
288
+ if (element.getAttribute('class')) {
289
+ node.setAttribute('class', (_a = element.getAttribute('class')) !== null && _a !== void 0 ? _a : '');
290
+ }
291
+ if (element.getAttribute('style')) {
292
+ node.setAttribute('style', (_b = element.getAttribute('style')) !== null && _b !== void 0 ? _b : '');
293
+ }
294
+ element.parentNode.replaceChild(node, element);
295
+ };
296
+ svgElement.querySelectorAll('rect').forEach((element) => {
297
+ const x = getNumber(element.getAttribute('x'));
298
+ const y = getNumber(element.getAttribute('y'));
299
+ const width = getNumber(element.getAttribute('width'));
300
+ const height = getNumber(element.getAttribute('height'));
301
+ const rx = getNumber(element.getAttribute('rx'));
302
+ const ry = getNumber(element.getAttribute('ry'));
303
+ const node = rx > 0 || ry > 0
304
+ ? rc.path(`M ${x + rx} ${y}
305
+ H ${x + width - rx}
306
+ Q ${x + width} ${y} ${x + width} ${y + ry}
307
+ V ${y + height - ry}
308
+ Q ${x + width} ${y + height} ${x + width - rx} ${y + height}
309
+ H ${x + rx}
310
+ Q ${x} ${y + height} ${x} ${y + height - ry}
311
+ V ${y + ry}
312
+ Q ${x} ${y} ${x + rx} ${y}
313
+ Z`, createOptions(element))
314
+ : rc.rectangle(x, y, width, height, createOptions(element));
315
+ replaceShape(element, node);
316
+ });
317
+ svgElement.querySelectorAll('line').forEach((element) => {
318
+ const node = rc.line(getNumber(element.getAttribute('x1')), getNumber(element.getAttribute('y1')), getNumber(element.getAttribute('x2')), getNumber(element.getAttribute('y2')), createOptions(element));
319
+ replaceShape(element, node);
320
+ });
321
+ svgElement.querySelectorAll('polyline').forEach((element) => {
322
+ var _a;
323
+ const points = ((_a = element.getAttribute('points')) !== null && _a !== void 0 ? _a : '')
324
+ .trim()
325
+ .split(/\s+/)
326
+ .map((pair) => pair.split(',').map(Number))
327
+ .filter((point) => point.length === 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]));
328
+ if (points.length < 2)
329
+ return;
330
+ const node = rc.linearPath(points, createOptions(element));
331
+ replaceShape(element, node);
332
+ });
333
+ svgElement.querySelectorAll('polygon').forEach((element) => {
334
+ var _a;
335
+ const points = ((_a = element.getAttribute('points')) !== null && _a !== void 0 ? _a : '')
336
+ .trim()
337
+ .split(/\s+/)
338
+ .map((pair) => pair.split(',').map(Number))
339
+ .filter((point) => point.length === 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]));
340
+ if (points.length < 2)
341
+ return;
342
+ const node = rc.polygon(points, createOptions(element));
343
+ replaceShape(element, node);
344
+ });
345
+ svgElement.querySelectorAll('path').forEach((element) => {
346
+ const d = element.getAttribute('d');
347
+ if (!d)
348
+ return;
349
+ const node = rc.path(d, createOptions(element));
350
+ replaceShape(element, node);
351
+ });
352
+ return serializer.serializeToString(svgElement);
353
+ }
354
+ catch (error) {
355
+ console.error('Error while applying hand-drawn mermaid style', error);
356
+ return svg;
357
+ }
358
+ }
235
359
 
236
360
  exports.Mermaid = Mermaid;
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
  import { __awaiter } from 'tslib';
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
4
+ import { MmdIcon, RefreshCcwIcon, DownloadIcon, XIcon } from '@windrun-huaiin/base-ui/icons';
5
5
  import { cn } from '@windrun-huaiin/lib/utils';
6
6
  import { useTheme } from 'next-themes';
7
+ import rough from 'roughjs';
7
8
  import { useId, useState, useRef, useEffect, useCallback } from 'react';
8
9
  import { themeSvgIconColor, themeIconColor } from '@windrun-huaiin/base-ui/lib';
9
10
 
@@ -13,7 +14,7 @@ function sanitizeFilename(name) {
13
14
  .replace(/\s+/g, '_')
14
15
  .slice(0, 120);
15
16
  }
16
- function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview = true }) {
17
+ function Mermaid({ chart, title, watermarkEnabled, watermarkText, handDrawn = true, enablePreview = true }) {
17
18
  const id = useId();
18
19
  const [svg, setSvg] = useState('');
19
20
  const { resolvedTheme } = useTheme();
@@ -43,9 +44,9 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
43
44
  try {
44
45
  mermaid.initialize(mermaidConfig);
45
46
  const { svg } = yield mermaid.render(id.replaceAll(':', ''), chart.replaceAll('\\n', '\n'));
46
- let svgWithWatermark = svg;
47
+ let svgWithWatermark = handDrawn ? applyHandDrawnStyle(svg) : svg;
47
48
  if (watermarkEnabled && watermarkText) {
48
- svgWithWatermark = addWatermarkToSvg(svg, watermarkText, themeSvgIconColor);
49
+ svgWithWatermark = addWatermarkToSvg(svgWithWatermark, watermarkText, themeSvgIconColor);
49
50
  }
50
51
  if (isMounted)
51
52
  setSvg(svgWithWatermark);
@@ -59,7 +60,7 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
59
60
  isMounted = false;
60
61
  setSvg('');
61
62
  };
62
- }, [chart, id, resolvedTheme, watermarkEnabled, watermarkText]);
63
+ }, [chart, id, resolvedTheme, watermarkEnabled, watermarkText, handDrawn]);
63
64
  // helpers for preview zoom
64
65
  const clamp = (v, min, max) => Math.min(Math.max(v, min), max);
65
66
  const resetTransform = useCallback(() => {
@@ -211,7 +212,7 @@ function Mermaid({ chart, title, watermarkEnabled, watermarkText, enablePreview
211
212
  window.scrollTo(0, scrollY);
212
213
  };
213
214
  }, [open]);
214
- return (jsxs("div", { children: [jsxs("div", { className: enablePreview ? 'group relative cursor-zoom-in' : undefined, onClick: () => enablePreview && svg && setOpen(true), children: [jsx("div", { dangerouslySetInnerHTML: { __html: svg } }), enablePreview && svg && (jsx("div", { className: "pointer-events-none absolute right-2 top-2 hidden rounded bg-black/50 px-2 py-0.5 text-[12px] text-white group-hover:block", children: "Preview Chart" }))] }), title && (jsxs("div", { className: cn("mt-2 flex items-center justify-center text-center text-[13px] font-italic", themeIconColor), children: [jsx(globalLucideIcons.Mmd, { className: 'mr-1 h-4 w-4' }), jsx("span", { children: title })] })), enablePreview && open && (jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": typeof title === 'string' ? title : 'Mermaid Preview', className: "fixed inset-0 z-9999 flex items-center justify-center", children: [jsx("div", { className: "absolute inset-0 bg-black/60", onClick: () => { setOpen(false); resetTransform(); }, onWheel: (e) => { e.preventDefault(); e.stopPropagation(); }, onTouchMove: (e) => { e.preventDefault(); e.stopPropagation(); } }), jsxs("div", { className: "relative z-1 max-w-[95vw] w-[95vw] h-[88vh] p-0 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-md shadow-2xl overflow-hidden", children: [jsxs("div", { className: "flex items-center justify-between gap-3 px-3 py-2 border-b border-neutral-200 dark:border-neutral-700", children: [jsxs("div", { className: cn("min-w-0 flex items-center gap-2 text-sm", themeIconColor), children: [jsx(globalLucideIcons.Mmd, { className: "h-4 w-4" }), jsx("span", { className: "truncate max-w-[50vw]", children: title !== null && title !== void 0 ? title : 'Mermaid Preview' })] }), jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [jsx("button", { "aria-label": "Zoom out", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(-0.5), children: "\uFF0D" }), jsxs("span", { className: "mx-0.5 w-12 text-center text-[12px] select-none", children: [Math.round(scale * 100), "%"] }), jsx("button", { "aria-label": "Zoom in", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(0.5), children: "\uFF0B" }), jsx("div", { className: "mx-1 hidden h-4 w-px bg-neutral-300 dark:bg-neutral-700 sm:block" }), jsx("button", { "aria-label": "Zoom 100%", className: "hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(1), children: "X1" }), jsx("button", { "aria-label": "Zoom 200%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(2), children: "X2" }), jsx("button", { "aria-label": "Zoom 300%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(3), children: "X3" }), jsx("button", { "aria-label": "Zoom 1000%", className: "ml-1 hidden h-6 min-w-10 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(10), children: "X10" }), jsx("button", { "aria-label": "Reset", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: resetTransform, children: jsx(globalLucideIcons.RefreshCcw, { className: "h-3.5 w-3.5" }) }), jsx("button", { "aria-label": "Download SVG", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: handleDownload, children: jsx(globalLucideIcons.Download, { className: "h-3.5 w-3.5" }) }), jsx("button", { "aria-label": "Close", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: () => { setOpen(false); resetTransform(); }, children: jsx(globalLucideIcons.X, { className: "h-3.5 w-3.5" }) })] })] }), jsxs("div", { className: "relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900 overscroll-contain touch-none", onWheel: onWheel, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerCancel, children: [jsx("div", { className: "absolute left-1/2 top-1/2", style: { transform: `translate(-50%, -50%) translate(${translate.x}px, ${translate.y}px)` }, children: jsx("div", { style: { transform: `scale(${scale})`, transformOrigin: '50% 50%' }, dangerouslySetInnerHTML: { __html: svg } }) }), jsxs("div", { className: "absolute inset-x-3 bottom-3 rounded-md bg-white/92 px-3 py-2 shadow-sm backdrop-blur sm:hidden dark:bg-neutral-900/92", children: [jsxs("label", { className: "mb-1 flex items-center justify-between text-[11px] text-neutral-600 dark:text-neutral-300", children: [jsx("span", { children: "Zoom" }), jsxs("span", { children: [Math.round(scale * 100), "%"] })] }), jsx("input", { "aria-label": "Zoom slider", className: "block w-full", type: "range", min: "25", max: "1000", step: "5", value: Math.round(scale * 100), style: { accentColor: themeSvgIconColor }, onChange: (e) => setScale(clamp(Number(e.target.value) / 100, 0.25, 10)) })] }), jsx("div", { className: "pointer-events-none absolute bottom-2 right-3 hidden rounded bg-black/40 px-2 py-1 text-xs text-white sm:block", children: "Drag to pan, click button to zoom-out or zoom-in" }), jsx("div", { className: "pointer-events-none absolute left-3 top-3 rounded bg-black/40 px-2 py-1 text-[11px] text-white sm:hidden", children: "Drag to pan, pinch to zoom-out or zoom-in" })] })] })] }))] }));
215
+ return (jsxs("div", { children: [jsxs("div", { className: enablePreview ? 'group relative cursor-zoom-in' : undefined, onClick: () => enablePreview && svg && setOpen(true), children: [jsx("div", { dangerouslySetInnerHTML: { __html: svg } }), enablePreview && svg && (jsx("div", { className: "pointer-events-none absolute right-2 top-2 hidden rounded bg-black/50 px-2 py-0.5 text-[12px] text-white group-hover:block", children: "Preview Chart" }))] }), title && (jsxs("div", { className: cn("mt-2 flex items-center justify-center text-center text-[13px] font-italic", themeIconColor), children: [jsx(MmdIcon, { className: 'mr-1 h-4 w-4' }), jsx("span", { children: title })] })), enablePreview && open && (jsxs("div", { role: "dialog", "aria-modal": "true", "aria-label": typeof title === 'string' ? title : 'Mermaid Preview', className: "fixed inset-0 z-9999 flex items-center justify-center", children: [jsx("div", { className: "absolute inset-0 bg-black/60", onClick: () => { setOpen(false); resetTransform(); }, onWheel: (e) => { e.preventDefault(); e.stopPropagation(); }, onTouchMove: (e) => { e.preventDefault(); e.stopPropagation(); } }), jsxs("div", { className: "relative z-1 max-w-[95vw] w-[95vw] h-[88vh] p-0 bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-700 rounded-md shadow-2xl overflow-hidden", children: [jsxs("div", { className: "flex items-center justify-between gap-3 px-3 py-2 border-b border-neutral-200 dark:border-neutral-700", children: [jsxs("div", { className: cn("min-w-0 flex items-center gap-2 text-sm", themeIconColor), children: [jsx(MmdIcon, { className: "h-4 w-4" }), jsx("span", { className: "truncate max-w-[50vw]", children: title !== null && title !== void 0 ? title : 'Mermaid Preview' })] }), jsxs("div", { className: "flex shrink-0 items-center gap-0.5", children: [jsx("button", { "aria-label": "Zoom out", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(-0.5), children: "\uFF0D" }), jsxs("span", { className: "mx-0.5 w-12 text-center text-[12px] select-none", children: [Math.round(scale * 100), "%"] }), jsx("button", { "aria-label": "Zoom in", className: "hidden h-6 w-6 items-center justify-center rounded border border-neutral-300 text-[13px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:flex", onClick: () => zoomBy(0.5), children: "\uFF0B" }), jsx("div", { className: "mx-1 hidden h-4 w-px bg-neutral-300 dark:bg-neutral-700 sm:block" }), jsx("button", { "aria-label": "Zoom 100%", className: "hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(1), children: "X1" }), jsx("button", { "aria-label": "Zoom 200%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(2), children: "X2" }), jsx("button", { "aria-label": "Zoom 300%", className: "ml-1 hidden h-6 min-w-8 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(3), children: "X3" }), jsx("button", { "aria-label": "Zoom 1000%", className: "ml-1 hidden h-6 min-w-10 items-center justify-center rounded border border-neutral-300 px-1.5 text-[12px] transition-colors hover:bg-neutral-100 active:bg-neutral-200 hover:border-neutral-400 active:border-neutral-500 dark:border-neutral-600 dark:hover:bg-neutral-700 dark:active:bg-neutral-600 dark:hover:border-neutral-500 dark:active:border-neutral-400 sm:inline-flex", onClick: () => setScale(10), children: "X10" }), jsx("button", { "aria-label": "Reset", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: resetTransform, children: jsx(RefreshCcwIcon, { className: "h-3.5 w-3.5" }) }), jsx("button", { "aria-label": "Download SVG", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: handleDownload, children: jsx(DownloadIcon, { className: "h-3.5 w-3.5" }) }), jsx("button", { "aria-label": "Close", className: cn("ml-1 flex h-6 w-6 items-center justify-center rounded transition-colors hover:bg-neutral-100 active:bg-neutral-200 dark:hover:bg-neutral-700 dark:active:bg-neutral-600", themeIconColor), onClick: () => { setOpen(false); resetTransform(); }, children: jsx(XIcon, { className: "h-3.5 w-3.5" }) })] })] }), jsxs("div", { className: "relative h-[calc(88vh-40px)] w-full overflow-hidden bg-white dark:bg-neutral-900 overscroll-contain touch-none", onWheel: onWheel, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerCancel, children: [jsx("div", { className: "absolute left-1/2 top-1/2", style: { transform: `translate(-50%, -50%) translate(${translate.x}px, ${translate.y}px)` }, children: jsx("div", { style: { transform: `scale(${scale})`, transformOrigin: '50% 50%' }, dangerouslySetInnerHTML: { __html: svg } }) }), jsxs("div", { className: "absolute inset-x-3 bottom-3 rounded-md bg-white/92 px-3 py-2 shadow-sm backdrop-blur sm:hidden dark:bg-neutral-900/92", children: [jsxs("label", { className: "mb-1 flex items-center justify-between text-[11px] text-neutral-600 dark:text-neutral-300", children: [jsx("span", { children: "Zoom" }), jsxs("span", { children: [Math.round(scale * 100), "%"] })] }), jsx("input", { "aria-label": "Zoom slider", className: "block w-full", type: "range", min: "25", max: "1000", step: "5", value: Math.round(scale * 100), style: { accentColor: themeSvgIconColor }, onChange: (e) => setScale(clamp(Number(e.target.value) / 100, 0.25, 10)) })] }), jsx("div", { className: "pointer-events-none absolute bottom-2 right-3 hidden rounded bg-black/40 px-2 py-1 text-xs text-white sm:block", children: "Drag to pan, click button to zoom-out or zoom-in" }), jsx("div", { className: "pointer-events-none absolute left-3 top-3 rounded bg-black/40 px-2 py-1 text-[11px] text-white sm:hidden", children: "Drag to pan, pinch to zoom-out or zoom-in" })] })] })] }))] }));
215
216
  }
216
217
  function addWatermarkToSvg(svg, watermark, watermarkColor) {
217
218
  const watermarkText = `
@@ -230,5 +231,128 @@ function addWatermarkToSvg(svg, watermark, watermarkColor) {
230
231
  `;
231
232
  return svg.replace('</svg>', `${watermarkText}</svg>`);
232
233
  }
234
+ function applyHandDrawnStyle(svg) {
235
+ if (typeof window === 'undefined')
236
+ return svg;
237
+ try {
238
+ const parser = new DOMParser();
239
+ const doc = parser.parseFromString(svg, 'image/svg+xml');
240
+ const svgElement = doc.documentElement;
241
+ if (!svgElement || svgElement.tagName.toLowerCase() !== 'svg')
242
+ return svg;
243
+ const rc = rough.svg(svgElement);
244
+ const serializer = new XMLSerializer();
245
+ const getNumber = (value) => Number.parseFloat(value !== null && value !== void 0 ? value : '') || 0;
246
+ const getStyleValue = (element, name) => {
247
+ const inlineStyle = element.getAttribute('style');
248
+ if (inlineStyle) {
249
+ const match = inlineStyle.match(new RegExp(`(?:^|;)\\s*${name}\\s*:\\s*([^;]+)`));
250
+ if (match === null || match === void 0 ? void 0 : match[1])
251
+ return match[1].trim();
252
+ }
253
+ return element.getAttribute(name);
254
+ };
255
+ const applyAttributes = (source, target) => {
256
+ var _a;
257
+ for (const attr of source.getAttributeNames()) {
258
+ if (attr === 'x' || attr === 'y' || attr === 'x1' || attr === 'y1' || attr === 'x2' || attr === 'y2' || attr === 'width' || attr === 'height' || attr === 'rx' || attr === 'ry' || attr === 'points' || attr === 'd')
259
+ continue;
260
+ target.setAttribute(attr, (_a = source.getAttribute(attr)) !== null && _a !== void 0 ? _a : '');
261
+ }
262
+ };
263
+ const createOptions = (element) => {
264
+ var _a, _b;
265
+ const stroke = (_a = getStyleValue(element, 'stroke')) !== null && _a !== void 0 ? _a : '#000';
266
+ const fill = (_b = getStyleValue(element, 'fill')) !== null && _b !== void 0 ? _b : 'none';
267
+ const strokeWidth = getNumber(getStyleValue(element, 'stroke-width')) || 1.5;
268
+ return {
269
+ stroke,
270
+ fill: fill === 'none' ? undefined : fill,
271
+ strokeWidth,
272
+ roughness: 1.6,
273
+ bowing: 1.25,
274
+ fillStyle: fill === 'none' ? 'hachure' : 'solid',
275
+ fillWeight: 0.8,
276
+ hachureGap: 10,
277
+ preserveVertices: true,
278
+ seed: 7,
279
+ };
280
+ };
281
+ const replaceShape = (element, node) => {
282
+ var _a, _b;
283
+ if (!node || !element.parentNode)
284
+ return;
285
+ applyAttributes(element, node);
286
+ if (element.getAttribute('class')) {
287
+ node.setAttribute('class', (_a = element.getAttribute('class')) !== null && _a !== void 0 ? _a : '');
288
+ }
289
+ if (element.getAttribute('style')) {
290
+ node.setAttribute('style', (_b = element.getAttribute('style')) !== null && _b !== void 0 ? _b : '');
291
+ }
292
+ element.parentNode.replaceChild(node, element);
293
+ };
294
+ svgElement.querySelectorAll('rect').forEach((element) => {
295
+ const x = getNumber(element.getAttribute('x'));
296
+ const y = getNumber(element.getAttribute('y'));
297
+ const width = getNumber(element.getAttribute('width'));
298
+ const height = getNumber(element.getAttribute('height'));
299
+ const rx = getNumber(element.getAttribute('rx'));
300
+ const ry = getNumber(element.getAttribute('ry'));
301
+ const node = rx > 0 || ry > 0
302
+ ? rc.path(`M ${x + rx} ${y}
303
+ H ${x + width - rx}
304
+ Q ${x + width} ${y} ${x + width} ${y + ry}
305
+ V ${y + height - ry}
306
+ Q ${x + width} ${y + height} ${x + width - rx} ${y + height}
307
+ H ${x + rx}
308
+ Q ${x} ${y + height} ${x} ${y + height - ry}
309
+ V ${y + ry}
310
+ Q ${x} ${y} ${x + rx} ${y}
311
+ Z`, createOptions(element))
312
+ : rc.rectangle(x, y, width, height, createOptions(element));
313
+ replaceShape(element, node);
314
+ });
315
+ svgElement.querySelectorAll('line').forEach((element) => {
316
+ const node = rc.line(getNumber(element.getAttribute('x1')), getNumber(element.getAttribute('y1')), getNumber(element.getAttribute('x2')), getNumber(element.getAttribute('y2')), createOptions(element));
317
+ replaceShape(element, node);
318
+ });
319
+ svgElement.querySelectorAll('polyline').forEach((element) => {
320
+ var _a;
321
+ const points = ((_a = element.getAttribute('points')) !== null && _a !== void 0 ? _a : '')
322
+ .trim()
323
+ .split(/\s+/)
324
+ .map((pair) => pair.split(',').map(Number))
325
+ .filter((point) => point.length === 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]));
326
+ if (points.length < 2)
327
+ return;
328
+ const node = rc.linearPath(points, createOptions(element));
329
+ replaceShape(element, node);
330
+ });
331
+ svgElement.querySelectorAll('polygon').forEach((element) => {
332
+ var _a;
333
+ const points = ((_a = element.getAttribute('points')) !== null && _a !== void 0 ? _a : '')
334
+ .trim()
335
+ .split(/\s+/)
336
+ .map((pair) => pair.split(',').map(Number))
337
+ .filter((point) => point.length === 2 && Number.isFinite(point[0]) && Number.isFinite(point[1]));
338
+ if (points.length < 2)
339
+ return;
340
+ const node = rc.polygon(points, createOptions(element));
341
+ replaceShape(element, node);
342
+ });
343
+ svgElement.querySelectorAll('path').forEach((element) => {
344
+ const d = element.getAttribute('d');
345
+ if (!d)
346
+ return;
347
+ const node = rc.path(d, createOptions(element));
348
+ replaceShape(element, node);
349
+ });
350
+ return serializer.serializeToString(svgElement);
351
+ }
352
+ catch (error) {
353
+ console.error('Error while applying hand-drawn mermaid style', error);
354
+ return svg;
355
+ }
356
+ }
233
357
 
234
358
  export { Mermaid };
@@ -8,7 +8,7 @@ var navigation = require('next/navigation');
8
8
  var nextIntl = require('next-intl');
9
9
  var useCopyButton = require('fumadocs-ui/utils/use-copy-button');
10
10
  var Link = require('fumadocs-core/link');
11
- var server = require('@windrun-huaiin/base-ui/components/server');
11
+ var icons = require('@windrun-huaiin/base-ui/icons');
12
12
  var ui = require('@windrun-huaiin/base-ui/ui');
13
13
 
14
14
  const cache = new Map();
@@ -57,17 +57,17 @@ function LLMCopyButton({ llmApiUrl, sourceKey } = {}) {
57
57
  }));
58
58
  return (jsxRuntime.jsx(ui.Button, { variant: "ghost", size: "sm", loading: isLoading,
59
59
  // force button to left align
60
- className: "justify-start px-0 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300", onClick: onClick, children: checked ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(server.globalLucideIcons.Check, {}), t('copyMarkdownDone')] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(server.globalLucideIcons.Markdown, {}), t('copyMarkdown')] })) }));
60
+ className: "justify-start px-0 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300", onClick: onClick, children: checked ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(icons.CheckIcon, {}), t('copyMarkdownDone')] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(icons.MarkdownIcon, {}), t('copyMarkdown')] })) }));
61
61
  }
62
62
  function EditOnGitHub({ url }) {
63
63
  const t = nextIntl.useTranslations('fuma');
64
- return (jsxRuntime.jsxs(Link, { className: "flex items-center gap-x-2 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300 text-sm", href: url, children: [jsxRuntime.jsx(server.globalLucideIcons.GitHub, {}), t('editOnGithub')] }));
64
+ return (jsxRuntime.jsxs(Link, { className: "flex items-center gap-x-2 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300 text-sm", href: url, children: [jsxRuntime.jsx(icons.GitHubIcon, {}), t('editOnGithub')] }));
65
65
  }
66
66
  // New component for displaying the last updated date with an icon
67
67
  function LastUpdatedDate({ date }) {
68
68
  const t = nextIntl.useTranslations('fuma');
69
69
  const viewDate = date ? `${t('lastUpdate')} ${date}` : `${t('emptyLastUpdate')}`;
70
- return (jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 text-stone-600 dark:text-stone-400 text-sm", children: [jsxRuntime.jsx(server.globalLucideIcons.LastUpdated, {}), viewDate] }));
70
+ return (jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2 text-stone-600 dark:text-stone-400 text-sm", children: [jsxRuntime.jsx(icons.LastUpdatedIcon, {}), viewDate] }));
71
71
  }
72
72
 
73
73
  exports.EditOnGitHub = EditOnGitHub;
@@ -6,7 +6,7 @@ import { useParams } from 'next/navigation';
6
6
  import { useTranslations } from 'next-intl';
7
7
  import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';
8
8
  import Link from 'fumadocs-core/link';
9
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
9
+ import { CheckIcon, MarkdownIcon, GitHubIcon, LastUpdatedIcon } from '@windrun-huaiin/base-ui/icons';
10
10
  import { Button } from '@windrun-huaiin/base-ui/ui';
11
11
 
12
12
  const cache = new Map();
@@ -55,17 +55,17 @@ function LLMCopyButton({ llmApiUrl, sourceKey } = {}) {
55
55
  }));
56
56
  return (jsx(Button, { variant: "ghost", size: "sm", loading: isLoading,
57
57
  // force button to left align
58
- className: "justify-start px-0 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300", onClick: onClick, children: checked ? (jsxs(Fragment, { children: [jsx(globalLucideIcons.Check, {}), t('copyMarkdownDone')] })) : (jsxs(Fragment, { children: [jsx(globalLucideIcons.Markdown, {}), t('copyMarkdown')] })) }));
58
+ className: "justify-start px-0 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300", onClick: onClick, children: checked ? (jsxs(Fragment, { children: [jsx(CheckIcon, {}), t('copyMarkdownDone')] })) : (jsxs(Fragment, { children: [jsx(MarkdownIcon, {}), t('copyMarkdown')] })) }));
59
59
  }
60
60
  function EditOnGitHub({ url }) {
61
61
  const t = useTranslations('fuma');
62
- return (jsxs(Link, { className: "flex items-center gap-x-2 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300 text-sm", href: url, children: [jsx(globalLucideIcons.GitHub, {}), t('editOnGithub')] }));
62
+ return (jsxs(Link, { className: "flex items-center gap-x-2 text-stone-600 hover:text-stone-500 dark:text-stone-400 dark:hover:text-stone-300 text-sm", href: url, children: [jsx(GitHubIcon, {}), t('editOnGithub')] }));
63
63
  }
64
64
  // New component for displaying the last updated date with an icon
65
65
  function LastUpdatedDate({ date }) {
66
66
  const t = useTranslations('fuma');
67
67
  const viewDate = date ? `${t('lastUpdate')} ${date}` : `${t('emptyLastUpdate')}`;
68
- return (jsxs("div", { className: "flex items-center gap-x-2 text-stone-600 dark:text-stone-400 text-sm", children: [jsx(globalLucideIcons.LastUpdated, {}), viewDate] }));
68
+ return (jsxs("div", { className: "flex items-center gap-x-2 text-stone-600 dark:text-stone-400 text-sm", children: [jsx(LastUpdatedIcon, {}), viewDate] }));
69
69
  }
70
70
 
71
71
  export { EditOnGitHub, LLMCopyButton, LastUpdatedDate };
@@ -2,9 +2,9 @@
2
2
  'use strict';
3
3
 
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var server = require('@windrun-huaiin/base-ui/components/server');
5
+ var icons = require('@windrun-huaiin/base-ui/icons');
6
6
 
7
- function TrophyCard({ icon = jsxRuntime.jsx(server.globalLucideIcons.Star, {}), title, children, }) {
7
+ function TrophyCard({ icon = jsxRuntime.jsx(icons.StarIcon, {}), title, children, }) {
8
8
  return (jsxRuntime.jsxs("div", { className: "\n border-2 rounded-xl px-4 py-2\n border-purple-200 dark:border-gray-500\n ", children: [jsxRuntime.jsxs("div", { className: "flex items-center font-bold text-sm", children: [jsxRuntime.jsx("span", { className: "mr-2", children: icon }), jsxRuntime.jsx("span", { children: title })] }), jsxRuntime.jsx("div", { className: "text-sm -mt-1 leading-none", children: children })] }));
9
9
  }
10
10
 
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
3
+ import { StarIcon } from '@windrun-huaiin/base-ui/icons';
4
4
 
5
- function TrophyCard({ icon = jsx(globalLucideIcons.Star, {}), title, children, }) {
5
+ function TrophyCard({ icon = jsx(StarIcon, {}), title, children, }) {
6
6
  return (jsxs("div", { className: "\n border-2 rounded-xl px-4 py-2\n border-purple-200 dark:border-gray-500\n ", children: [jsxs("div", { className: "flex items-center font-bold text-sm", children: [jsx("span", { className: "mr-2", children: icon }), jsx("span", { children: title })] }), jsx("div", { className: "text-sm -mt-1 leading-none", children: children })] }));
7
7
  }
8
8
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  var tslib = require('tslib');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
- var server = require('@windrun-huaiin/base-ui/components/server');
6
+ var icons = require('@windrun-huaiin/base-ui/icons');
7
7
  var utils = require('@windrun-huaiin/lib/utils');
8
8
  var Link = require('next/link');
9
9
 
@@ -12,9 +12,9 @@ function ZiaCard(_a) {
12
12
  const validHref = typeof props.href === 'string' && props.href.trim() !== '';
13
13
  const validDescription = typeof description === 'string' && (description === null || description === void 0 ? void 0 : description.trim()) !== '';
14
14
  if (validHref) {
15
- return (jsxRuntime.jsxs(Link, Object.assign({ href: props.href, "data-card": true, className: utils.cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', 'hover:bg-fd-accent/80', props.className) }, props, { children: [jsxRuntime.jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsxRuntime.jsx(server.globalLucideIcons.CircleSmall, {}) }), jsxRuntime.jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsxRuntime.jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
15
+ return (jsxRuntime.jsxs(Link, Object.assign({ href: props.href, "data-card": true, className: utils.cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', 'hover:bg-fd-accent/80', props.className) }, props, { children: [jsxRuntime.jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsxRuntime.jsx(icons.CircleSmallIcon, {}) }), jsxRuntime.jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsxRuntime.jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
16
16
  }
17
- return (jsxRuntime.jsxs("div", Object.assign({ "data-card": true, className: utils.cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', props.className) }, props, { children: [jsxRuntime.jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsxRuntime.jsx(server.globalLucideIcons.CircleSmall, {}) }), jsxRuntime.jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsxRuntime.jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
17
+ return (jsxRuntime.jsxs("div", Object.assign({ "data-card": true, className: utils.cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', props.className) }, props, { children: [jsxRuntime.jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsxRuntime.jsx(icons.CircleSmallIcon, {}) }), jsxRuntime.jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsxRuntime.jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsxRuntime.jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
18
18
  }
19
19
 
20
20
  exports.ZiaCard = ZiaCard;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { __rest } from 'tslib';
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
- import { globalLucideIcons } from '@windrun-huaiin/base-ui/components/server';
4
+ import { CircleSmallIcon } from '@windrun-huaiin/base-ui/icons';
5
5
  import { cn } from '@windrun-huaiin/lib/utils';
6
6
  import Link from 'next/link';
7
7
 
@@ -10,9 +10,9 @@ function ZiaCard(_a) {
10
10
  const validHref = typeof props.href === 'string' && props.href.trim() !== '';
11
11
  const validDescription = typeof description === 'string' && (description === null || description === void 0 ? void 0 : description.trim()) !== '';
12
12
  if (validHref) {
13
- return (jsxs(Link, Object.assign({ href: props.href, "data-card": true, className: cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', 'hover:bg-fd-accent/80', props.className) }, props, { children: [jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsx(globalLucideIcons.CircleSmall, {}) }), jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
13
+ return (jsxs(Link, Object.assign({ href: props.href, "data-card": true, className: cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', 'hover:bg-fd-accent/80', props.className) }, props, { children: [jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsx(CircleSmallIcon, {}) }), jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
14
14
  }
15
- return (jsxs("div", Object.assign({ "data-card": true, className: cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', props.className) }, props, { children: [jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsx(globalLucideIcons.CircleSmall, {}) }), jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
15
+ return (jsxs("div", Object.assign({ "data-card": true, className: cn('block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors @max-lg:col-span-full', props.className) }, props, { children: [jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon ? icon : jsx(CircleSmallIcon, {}) }), jsx("h3", { className: "not-prose mb-1 text-sm font-medium line-clamp-2 min-h-10", children: title }), validDescription ? (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground", children: description })) : (jsx("p", { className: "my-0! text-sm text-fd-muted-foreground opacity-0 select-none", children: "\u00A0" })), props.children ? (jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children })) : null] })));
16
16
  }
17
17
 
18
18
  export { ZiaCard };
@@ -2,7 +2,7 @@
2
2
 
3
3
  var tslib = require('tslib');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var server = require('@windrun-huaiin/base-ui/components/server');
5
+ var icons = require('@windrun-huaiin/base-ui/icons');
6
6
  var React = require('react');
7
7
  var utils = require('@windrun-huaiin/lib/utils');
8
8
  var collapsible = require('fumadocs-ui/components/ui/collapsible');
@@ -11,7 +11,7 @@ var Link = require('next/link');
11
11
  const itemVariants = 'flex flex-row items-center gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-fd-accent hover:text-fd-accent-foreground [&_svg]:size-4';
12
12
  const anotionClass = 'ms-2 px-2 py-0.5 rounded text-xs font-semibold bg-fd-accent/80 text-fd-accent-foreground dark:bg-white/20 dark:text-white';
13
13
  function ZiaFile(_a) {
14
- var { name, icon = jsxRuntime.jsx(server.globalLucideIcons.File, {}), className, anotion, href } = _a, rest = tslib.__rest(_a, ["name", "icon", "className", "anotion", "href"]);
14
+ var { name, icon = jsxRuntime.jsx(icons.FileIcon, {}), className, anotion, href } = _a, rest = tslib.__rest(_a, ["name", "icon", "className", "anotion", "href"]);
15
15
  const validHref = typeof href === 'string' && href.trim() !== '';
16
16
  const validAnotion = typeof anotion === 'string' && anotion.trim() !== '';
17
17
  if (validHref) {
@@ -23,7 +23,7 @@ function ZiaFolder(_a) {
23
23
  var { name, anotion, defaultOpen = false, className, children } = _a, props = tslib.__rest(_a, ["name", "anotion", "defaultOpen", "className", "children"]);
24
24
  const [open, setOpen] = React.useState(defaultOpen);
25
25
  const validAnotion = typeof anotion === 'string' && anotion.trim() !== '';
26
- return (jsxRuntime.jsxs(collapsible.Collapsible, Object.assign({ open: open, onOpenChange: setOpen }, props, { children: [jsxRuntime.jsxs(collapsible.CollapsibleTrigger, { className: utils.cn(itemVariants, className, 'w-full'), children: [open ? jsxRuntime.jsx(server.globalLucideIcons.FolderOpen, {}) : jsxRuntime.jsx(server.globalLucideIcons.Folder, {}), jsxRuntime.jsx("span", { children: name }), validAnotion && (jsxRuntime.jsx("span", { className: anotionClass, children: anotion }))] }), jsxRuntime.jsx(collapsible.CollapsibleContent, { children: jsxRuntime.jsx("div", { className: "ms-2 flex flex-col border-l ps-2", children: children }) })] })));
26
+ return (jsxRuntime.jsxs(collapsible.Collapsible, Object.assign({ open: open, onOpenChange: setOpen }, props, { children: [jsxRuntime.jsxs(collapsible.CollapsibleTrigger, { className: utils.cn(itemVariants, className, 'w-full'), children: [open ? jsxRuntime.jsx(icons.FolderOpenIcon, {}) : jsxRuntime.jsx(icons.FolderIcon, {}), jsxRuntime.jsx("span", { children: name }), validAnotion && (jsxRuntime.jsx("span", { className: anotionClass, children: anotion }))] }), jsxRuntime.jsx(collapsible.CollapsibleContent, { children: jsxRuntime.jsx("div", { className: "ms-2 flex flex-col border-l ps-2", children: children }) })] })));
27
27
  }
28
28
 
29
29
  exports.ZiaFile = ZiaFile;