diff --git a/.changeset/fix-zenuml-svg-renderer.md b/.changeset/fix-zenuml-svg-renderer.md new file mode 100644 index 00000000000..6dc2bb14226 --- /dev/null +++ b/.changeset/fix-zenuml-svg-renderer.md @@ -0,0 +1,10 @@ +--- +'mermaid': patch +'@mermaid-js/mermaid-zenuml': patch +--- + +fix: update @zenuml/core to v3.46.11 with native SVG renderer + +- Fix vertical lifelines disappearing when printing (#6004) +- Fix SVG dimensions exceeding container boundaries (#7266) +- Fix invalid ZenUML syntax freezing the editor (#7154) diff --git a/packages/mermaid-zenuml/package.json b/packages/mermaid-zenuml/package.json index fd2e58aa37b..f10626f4444 100644 --- a/packages/mermaid-zenuml/package.json +++ b/packages/mermaid-zenuml/package.json @@ -33,7 +33,7 @@ ], "license": "MIT", "dependencies": { - "@zenuml/core": "^3.41.6" + "@zenuml/core": "^3.47.0" }, "devDependencies": { "mermaid": "workspace:^" diff --git a/packages/mermaid-zenuml/src/types/zenuml-core.d.ts b/packages/mermaid-zenuml/src/types/zenuml-core.d.ts new file mode 100644 index 00000000000..bb56cc50710 --- /dev/null +++ b/packages/mermaid-zenuml/src/types/zenuml-core.d.ts @@ -0,0 +1,18 @@ +// Override @zenuml/core types for nodenext module resolution. +// The package lacks "type": "module" so TS treats it as CJS, +// rejecting named imports. This declaration fixes that. +declare module '@zenuml/core' { + export interface RenderOptions { + theme?: 'theme-default' | 'theme-mermaid'; + } + + export interface RenderResult { + svg: string; + innerSvg: string; + width: number; + height: number; + viewBox: string; + } + + export function renderToSvg(code: string, options?: RenderOptions): RenderResult; +} diff --git a/packages/mermaid-zenuml/src/zenumlRenderer.spec.ts b/packages/mermaid-zenuml/src/zenumlRenderer.spec.ts new file mode 100644 index 00000000000..087180db094 --- /dev/null +++ b/packages/mermaid-zenuml/src/zenumlRenderer.spec.ts @@ -0,0 +1,98 @@ +import { vi } from 'vitest'; +import { calculateSvgSizeAttrs } from './zenumlRenderer.js'; + +vi.mock('@zenuml/core', () => ({ + renderToSvg: vi.fn((code: string) => ({ + innerSvg: `${code.trim()}`, + width: 400, + height: 300, + viewBox: '0 0 400 300', + })), +})); + +vi.mock('./mermaidUtils.js', () => ({ + log: { info: vi.fn(), error: vi.fn(), debug: vi.fn(), warn: vi.fn() }, + getConfig: vi.fn(() => ({ + securityLevel: 'loose', + sequence: { useMaxWidth: true }, + })), +})); + +describe('calculateSvgSizeAttrs', function () { + it('should return responsive width when useMaxWidth is true', function () { + const attrs = calculateSvgSizeAttrs(133, 392, true); + + expect(attrs.get('width')).toEqual('100%'); + expect(attrs.get('style')).toEqual('max-width: 133px;'); + expect(attrs.has('height')).toBe(false); + }); + + it('should return absolute dimensions when useMaxWidth is false', function () { + const attrs = calculateSvgSizeAttrs(133, 392, false); + + expect(attrs.get('width')).toEqual('133'); + expect(attrs.get('height')).toEqual('392'); + expect(attrs.has('style')).toBe(false); + }); +}); + +describe('draw', () => { + beforeEach(() => { + vi.clearAllMocks(); + document.body.innerHTML = ''; + }); + + it('should render SVG content into the target element', async () => { + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.id = 'test-id'; + document.body.appendChild(svg); + + const { draw } = await import('./zenumlRenderer.js'); + await draw('zenuml\n Alice->Bob: hello', 'test-id'); + + expect(svg.innerHTML).toContain('Alice-'); + expect(svg.getAttribute('viewBox')).toBe('0 0 400 300'); + expect(svg.getAttribute('width')).toBe('100%'); + expect(svg.getAttribute('style')).toBe('max-width: 400px;'); + }); + + it('should set absolute dimensions when useMaxWidth is false', async () => { + const { getConfig } = await import('./mermaidUtils.js'); + vi.mocked(getConfig).mockReturnValue({ + securityLevel: 'loose', + sequence: { useMaxWidth: false }, + }); + + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.id = 'test-abs'; + document.body.appendChild(svg); + + const { draw } = await import('./zenumlRenderer.js'); + await draw('zenuml\n A->B: msg', 'test-abs'); + + expect(svg.getAttribute('width')).toBe('400'); + expect(svg.getAttribute('height')).toBe('300'); + }); + + it('should handle missing SVG element gracefully', async () => { + const { draw } = await import('./zenumlRenderer.js'); + const { log } = await import('./mermaidUtils.js'); + + await draw('zenuml\n A->B: msg', 'nonexistent'); + + expect(log.error).toHaveBeenCalledWith('Cannot find svg element'); + }); + + it('should strip the zenuml prefix before rendering', async () => { + const { renderToSvg } = await import('@zenuml/core'); + + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.id = 'test-strip'; + document.body.appendChild(svg); + + const { draw } = await import('./zenumlRenderer.js'); + await draw('zenuml\n Alice->Bob: hello', 'test-strip'); + + expect(renderToSvg).toHaveBeenCalledWith('\n Alice->Bob: hello'); + }); +}); diff --git a/packages/mermaid-zenuml/src/zenumlRenderer.ts b/packages/mermaid-zenuml/src/zenumlRenderer.ts index 42ec8fcb404..f1dc2b36a91 100644 --- a/packages/mermaid-zenuml/src/zenumlRenderer.ts +++ b/packages/mermaid-zenuml/src/zenumlRenderer.ts @@ -1,65 +1,86 @@ +import { renderToSvg } from '@zenuml/core'; import { getConfig, log } from './mermaidUtils.js'; -import ZenUml from '@zenuml/core'; const regexp = /^\s*zenuml/; -// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly -function createTemporaryZenumlContainer(id: string) { - const container = document.createElement('div'); - container.id = `container-${id}`; - container.style.display = 'flex'; - container.innerHTML = `
`; - const app = container.querySelector(`#zenUMLApp-${id}`)!; - return { container, app }; -} - -// Create a foreignObject to wrap the Zen UML container in the svg -function createForeignObject(id: string) { - const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'); - foreignObject.setAttribute('x', '0'); - foreignObject.setAttribute('y', '0'); - foreignObject.setAttribute('width', '100%'); - foreignObject.setAttribute('height', '100%'); - const { container, app } = createTemporaryZenumlContainer(id); - foreignObject.appendChild(container); - return { foreignObject, container, app }; -} +export const calculateSvgSizeAttrs = ( + width: number, + height: number, + useMaxWidth: boolean +): Map => { + const attrs = new Map(); + + if (useMaxWidth) { + attrs.set('width', '100%'); + attrs.set('style', `max-width: ${width}px;`); + } else { + attrs.set('width', String(width)); + attrs.set('height', String(height)); + } + + return attrs; +}; /** - * Draws a Zen UML in the tag with id: id based on the graph definition in text. - * - * @param text - The text of the diagram - * @param id - The id of the diagram which will be used as a DOM element id¨ + * Resolves the root document and SVG element, handling sandbox mode. + * Follows the same pattern as mermaid's selectSvgElement utility. */ -export const draw = async function (text: string, id: string) { - log.info('draw with Zen UML renderer', ZenUml); - - text = text.replace(regexp, ''); +const selectSvgElement = (id: string): SVGSVGElement | null => { const { securityLevel } = getConfig(); - // Handle root and Document for when rendering in sandbox mode - let sandboxElement: HTMLIFrameElement | null = null; + let root: Document = document; + if (securityLevel === 'sandbox') { - sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement; + const sandboxElement = document.querySelector(`#i${id}`); + root = sandboxElement?.contentDocument ?? document; } - const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document; + return root.querySelector(`#${id}`); +}; - const svgContainer = root?.querySelector(`svg#${id}`); +const configureSvgSize = ( + svgEl: SVGSVGElement, + width: number, + height: number, + useMaxWidth: boolean +) => { + const attrs = calculateSvgSizeAttrs(width, height, useMaxWidth); - if (!root || !svgContainer) { - log.error('Cannot find root or svgContainer'); - return; + svgEl.removeAttribute('height'); + svgEl.style.removeProperty('max-width'); + + for (const [attr, value] of attrs) { + svgEl.setAttribute(attr, value); } +}; + +/** + * Draws a ZenUML diagram in the SVG element with id: id based on the + * graph definition in text, using native SVG rendering. + * + * @param text - The text of the diagram + * @param id - The id of the diagram which will be used as a DOM element id + */ +export const draw = function (text: string, id: string): Promise { + log.info('draw with ZenUML native SVG renderer'); + + const code = text.replace(regexp, ''); + const config = getConfig(); + const useMaxWidth = config.sequence?.useMaxWidth ?? true; + + const svgEl = selectSvgElement(id); + + if (!svgEl) { + log.error('Cannot find svg element'); + return Promise.resolve(); + } + + const result = renderToSvg(code); - const { foreignObject, container, app } = createForeignObject(id); - svgContainer.appendChild(foreignObject); - const zenuml = new ZenUml(app); - // default is a theme name. More themes to be added and will be configurable in the future - await zenuml.render(text, { theme: 'default', mode: 'static' }); + configureSvgSize(svgEl, result.width, result.height, useMaxWidth); + svgEl.setAttribute('viewBox', result.viewBox); + svgEl.innerHTML = result.innerSvg; - const { width, height } = window.getComputedStyle(container); - log.debug('zenuml diagram size', width, height); - svgContainer.setAttribute('style', `width: ${width}; height: ${height};`); + return Promise.resolve(); }; export default { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad4fee6f4ac..45c0417260c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -474,8 +474,8 @@ importers: packages/mermaid-zenuml: dependencies: '@zenuml/core': - specifier: ^3.41.6 - version: 3.41.6(@babel/core@7.29.0)(@babel/template@7.28.6) + specifier: ^3.47.0 + version: 3.47.2(@babel/core@7.29.0)(@babel/template@7.28.6) devDependencies: mermaid: specifier: workspace:^ @@ -2469,8 +2469,8 @@ packages: '@hapi/topo@6.0.2': resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} - '@headlessui/react@2.2.8': - resolution: {integrity: sha512-vkiZulDC0lFeTrZTbA4tHvhZHvkUb2PFh5xJ1BvWAZdRK0fayMKO1QEO4inWkXxK1i0I1rcwwu1d6mo0K7Pcbw==} + '@headlessui/react@2.2.10': + resolution: {integrity: sha512-5pVLNK9wlpxTUTy9GpgbX/SdcRh+HBnPktjM2wbiLTH4p+2EPHBO1aoSryUCuKUIItdDWO9ITlhUL8UnUN/oIA==} engines: {node: '>=10'} peerDependencies: react: ^18 || ^19 || ^19.0.0-rc @@ -4040,8 +4040,8 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - '@zenuml/core@3.41.6': - resolution: {integrity: sha512-j+yHQb7W9I8ytyvbx+Wht66lsBqcWdbaBpyhOwVsny8m3ohVKNQhayJ7rANHKo6DAtdPnCexzOuttKciySnztA==} + '@zenuml/core@3.47.2': + resolution: {integrity: sha512-aDw1/H06L8HitKYeZoXtw7/HmfVcVHIzdHyoC+6TBYfy6BgfHbfY52a3ONi6/NwMLh6LQZ7IWruWUmlcbi8vNQ==} engines: {node: '>=20'} JSONSelect@0.4.0: @@ -4769,8 +4769,8 @@ packages: resolution: {integrity: sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==} engines: {node: '>=12.20'} - color-string@2.1.2: - resolution: {integrity: sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==} + color-string@2.1.4: + resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} engines: {node: '>=18'} colorette@2.0.20: @@ -6544,8 +6544,8 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - immer@10.1.3: - resolution: {integrity: sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==} + immer@10.2.0: + resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} @@ -7077,8 +7077,8 @@ packages: resolution: {integrity: sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==} engines: {node: '>= 20'} - jotai@2.14.0: - resolution: {integrity: sha512-JQkNkTnqjk1BlSUjHfXi+pGG/573bVN104gp6CymhrWDseZGDReTNniWrLhJ+zXbM6pH+82+UNJ2vwYQUkQMWQ==} + jotai@2.19.1: + resolution: {integrity: sha512-sqm9lVZiqBHZH8aSRk32DSiZDHY3yUIlulXYn9GQj7/LvoUdYXSMti7ZPJGo+6zjzKFt5a25k/I6iBCi43PJcw==} engines: {node: '>=12.20.0'} peerDependencies: '@babel/core': '>=7.0.0' @@ -8456,16 +8456,9 @@ packages: quote-unquote@1.0.0: resolution: {integrity: sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==} - radash@12.1.1: - resolution: {integrity: sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA==} - engines: {node: '>=14.18.0'} - railroad-diagrams@1.0.0: resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} - ramda@0.28.0: - resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} - ramda@0.29.1: resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==} @@ -8488,16 +8481,16 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - react-dom@19.1.1: - resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + react-dom@19.2.5: + resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} peerDependencies: - react: ^19.1.1 + react: ^19.2.5 react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react@19.1.1: - resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + react@19.2.5: + resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -8785,8 +8778,8 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.26.0: - resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} schema-utils@4.3.2: resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} @@ -9255,11 +9248,11 @@ packages: tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - tailwind-merge@3.3.1: - resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwind-merge@3.5.0: + resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} - tailwindcss@3.4.17: - resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + tailwindcss@3.4.19: + resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} engines: {node: '>=14.0.0'} hasBin: true @@ -12097,7 +12090,7 @@ snapshots: babel-loader: 10.0.0(@babel/core@7.29.0)(webpack@5.101.3(esbuild@0.25.12)) bluebird: 3.7.1 debug: 4.4.0 - lodash: 4.17.21 + lodash: 4.18.1 semver: 7.7.3 webpack: 5.101.3(esbuild@0.25.12) transitivePeerDependencies: @@ -12472,26 +12465,26 @@ snapshots: '@floating-ui/core': 1.7.3 '@floating-ui/utils': 0.2.10 - '@floating-ui/react-dom@2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@floating-ui/react-dom@2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@floating-ui/dom': 1.7.4 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) - '@floating-ui/react@0.26.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@floating-ui/react@0.26.28(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@floating-ui/utils': 0.2.10 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) tabbable: 6.2.0 - '@floating-ui/react@0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@floating-ui/react@0.27.16(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@floating-ui/utils': 0.2.10 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) tabbable: 6.2.0 '@floating-ui/utils@0.2.10': {} @@ -12520,19 +12513,19 @@ snapshots: dependencies: '@hapi/hoek': 11.0.7 - '@headlessui/react@2.2.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@headlessui/react@2.2.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@floating-ui/react': 0.26.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@react-aria/focus': 3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@tanstack/react-virtual': 3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - use-sync-external-store: 1.5.0(react@19.1.1) + '@floating-ui/react': 0.26.28(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@react-aria/focus': 3.21.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@react-aria/interactions': 3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@tanstack/react-virtual': 3.13.12(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + use-sync-external-store: 1.5.0(react@19.2.5) - '@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.17)': + '@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.19)': dependencies: - tailwindcss: 3.4.17 + tailwindcss: 3.4.19 '@humanfs/core@0.19.1': {} @@ -12954,54 +12947,54 @@ snapshots: dependencies: quansync: 0.2.11 - '@react-aria/focus@3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@react-aria/focus@3.21.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@react-aria/utils': 3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@react-types/shared': 3.32.0(react@19.1.1) + '@react-aria/interactions': 3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@react-aria/utils': 3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@react-types/shared': 3.32.0(react@19.2.5) '@swc/helpers': 0.5.17 clsx: 2.1.1 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) - '@react-aria/interactions@3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@react-aria/interactions@3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@react-aria/ssr': 3.9.10(react@19.1.1) - '@react-aria/utils': 3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.2.5) + '@react-aria/utils': 3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@react-stately/flags': 3.1.2 - '@react-types/shared': 3.32.0(react@19.1.1) + '@react-types/shared': 3.32.0(react@19.2.5) '@swc/helpers': 0.5.17 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) - '@react-aria/ssr@3.9.10(react@19.1.1)': + '@react-aria/ssr@3.9.10(react@19.2.5)': dependencies: '@swc/helpers': 0.5.17 - react: 19.1.1 + react: 19.2.5 - '@react-aria/utils@3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@react-aria/utils@3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - '@react-aria/ssr': 3.9.10(react@19.1.1) + '@react-aria/ssr': 3.9.10(react@19.2.5) '@react-stately/flags': 3.1.2 - '@react-stately/utils': 3.10.8(react@19.1.1) - '@react-types/shared': 3.32.0(react@19.1.1) + '@react-stately/utils': 3.10.8(react@19.2.5) + '@react-types/shared': 3.32.0(react@19.2.5) '@swc/helpers': 0.5.17 clsx: 2.1.1 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) '@react-stately/flags@3.1.2': dependencies: '@swc/helpers': 0.5.17 - '@react-stately/utils@3.10.8(react@19.1.1)': + '@react-stately/utils@3.10.8(react@19.2.5)': dependencies: '@swc/helpers': 0.5.17 - react: 19.1.1 + react: 19.2.5 - '@react-types/shared@3.32.0(react@19.1.1)': + '@react-types/shared@3.32.0(react@19.2.5)': dependencies: - react: 19.1.1 + react: 19.2.5 '@rolldown/pluginutils@1.0.0-beta.50': {} @@ -13238,11 +13231,11 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tanstack/react-virtual@3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@tanstack/react-virtual@3.13.12(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@tanstack/virtual-core': 3.13.12 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) '@tanstack/virtual-core@3.13.12': {} @@ -14358,30 +14351,28 @@ snapshots: '@xtuc/long@4.2.2': {} - '@zenuml/core@3.41.6(@babel/core@7.29.0)(@babel/template@7.28.6)': + '@zenuml/core@3.47.2(@babel/core@7.29.0)(@babel/template@7.28.6)': dependencies: - '@floating-ui/react': 0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@headlessui/react': 2.2.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1) - '@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.17) + '@floating-ui/react': 0.27.16(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@headlessui/react': 2.2.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.19) antlr4: 4.11.0 class-variance-authority: 0.7.1 clsx: 2.1.1 - color-string: 2.1.2 + color-string: 2.1.4 dompurify: 3.4.0 highlight.js: 10.7.3 html-to-image: 1.11.13 - immer: 10.1.3 - jotai: 2.14.0(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.1.1) - lodash: 4.17.21 + immer: 10.2.0 + jotai: 2.19.1(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.2.5) + lodash: 4.18.1 marked: 4.3.0 pako: 2.1.0 pino: 8.21.0 - radash: 12.1.1 - ramda: 0.28.0 - react: 19.1.1 - react-dom: 19.1.1(react@19.1.1) - tailwind-merge: 3.3.1 - tailwindcss: 3.4.17 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + tailwind-merge: 3.5.0 + tailwindcss: 3.4.19 transitivePeerDependencies: - '@babel/core' - '@babel/template' @@ -15158,7 +15149,7 @@ snapshots: color-name@2.0.2: {} - color-string@2.1.2: + color-string@2.1.4: dependencies: color-name: 2.0.2 @@ -16745,7 +16736,7 @@ snapshots: enhanced-resolve: 5.18.3 module-definition: 6.0.1 module-lookup-amd: 9.0.5 - resolve: 1.22.10 + resolve: 1.22.12 resolve-dependency-path: 4.0.1 sass-lookup: 6.1.0 stylus-lookup: 6.1.0 @@ -17364,7 +17355,7 @@ snapshots: ignore@7.0.5: {} - immer@10.1.3: {} + immer@10.2.0: {} import-fresh@3.3.1: dependencies: @@ -17837,7 +17828,7 @@ snapshots: get-stdin: 5.0.1 glur: 1.1.2 jest: 30.1.3(@types/node@22.19.1) - lodash: 4.17.21 + lodash: 4.18.1 mkdirp: 0.5.6 pixelmatch: 5.3.0 pngjs: 3.4.0 @@ -18068,11 +18059,11 @@ snapshots: '@hapi/topo': 6.0.2 '@standard-schema/spec': 1.0.0 - jotai@2.14.0(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.1.1): + jotai@2.19.1(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.2.5): optionalDependencies: '@babel/core': 7.29.0 '@babel/template': 7.28.6 - react: 19.1.1 + react: 19.2.5 jpeg-js@0.4.4: {} @@ -19465,7 +19456,7 @@ snapshots: postcss: 8.5.8 postcss-value-parser: 4.2.0 read-cache: 1.0.0 - resolve: 1.22.10 + resolve: 1.22.12 postcss-js@4.0.1(postcss@8.5.8): dependencies: @@ -19622,12 +19613,8 @@ snapshots: quote-unquote@1.0.0: {} - radash@12.1.1: {} - railroad-diagrams@1.0.0: {} - ramda@0.28.0: {} - ramda@0.29.1: {} randombytes@2.1.0: @@ -19657,14 +19644,14 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dom@19.1.1(react@19.1.1): + react-dom@19.2.5(react@19.2.5): dependencies: - react: 19.1.1 - scheduler: 0.26.0 + react: 19.2.5 + scheduler: 0.27.0 react-is@18.3.1: {} - react@19.1.1: {} + react@19.2.5: {} read-cache@1.0.0: dependencies: @@ -20022,7 +20009,7 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.26.0: {} + scheduler@0.27.0: {} schema-utils@4.3.2: dependencies: @@ -20612,9 +20599,9 @@ snapshots: tabbable@6.2.0: {} - tailwind-merge@3.3.1: {} + tailwind-merge@3.5.0: {} - tailwindcss@3.4.17: + tailwindcss@3.4.19: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -20636,7 +20623,7 @@ snapshots: postcss-load-config: 4.0.2(postcss@8.5.8) postcss-nested: 6.2.0(postcss@8.5.8) postcss-selector-parser: 6.1.2 - resolve: 1.22.10 + resolve: 1.22.12 sucrase: 3.35.0 transitivePeerDependencies: - ts-node @@ -20662,7 +20649,7 @@ snapshots: dependencies: '@babel/runtime': 7.28.4 bluebird: 3.7.2 - lodash: 4.17.21 + lodash: 4.18.1 shell-quote: 1.8.3 source-map-support: 0.5.21 which: 2.0.2 @@ -21159,9 +21146,9 @@ snapshots: dependencies: punycode: 2.3.1 - use-sync-external-store@1.5.0(react@19.1.1): + use-sync-external-store@1.5.0(react@19.2.5): dependencies: - react: 19.1.1 + react: 19.2.5 util-deprecate@1.0.2: {} @@ -21492,7 +21479,7 @@ snapshots: dependencies: axios: 1.13.2(debug@4.4.3) joi: 18.0.1 - lodash: 4.17.21 + lodash: 4.18.1 minimist: 1.2.8 rxjs: 7.8.2 transitivePeerDependencies: