@validationcloud/fractal-ui 1.71.0 → 1.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,71 +1,50 @@
1
- <div align="center">
2
- <img src="./fractal-ui.svg" height="150">
3
- </div>
4
-
5
1
  # @validationcloud/fractal-ui
6
2
 
7
- This is Validation Cloud's component library, providing our web applications with custom React components, design tokens, and Tailwind classes.
8
-
9
- ## Usage
3
+ Validation Cloud's shared React component library with design tokens and Tailwind CSS utilities.
10
4
 
11
- The `@validationcloud/fractal-ui` package requires `react`, `react-dom`, and `tailwindcss` to also be installed as they are peer dependencies.
5
+ ## Install
12
6
 
13
7
  ```sh
14
8
  npm install @validationcloud/fractal-ui react react-dom tailwindcss
15
9
  ```
16
10
 
17
- ### Components
11
+ ## Setup
18
12
 
19
- All components located in `src/components/` are available for use and can be imported as such:
13
+ Import components:
20
14
 
21
- ```sh
22
- import { Button } from '@validationcloud/fractal-ui'
15
+ ```ts
16
+ import { Button } from '@validationcloud/fractal-ui';
23
17
  ```
24
18
 
25
- ### Stylesheet
26
-
27
- This library provides a stylesheet that can be used in projects using the Tailwind CSS styling framework. Currently the consuming project needs to be using Tailwind 4.
19
+ Add styles to your global stylesheet (requires Tailwind 4):
28
20
 
29
- In the consuming application's global stylesheet, import the `tailwind.css` file after the `tailwindcss` import:
30
-
31
- ```sh
21
+ ```css
32
22
  @import 'tailwindcss';
33
23
  @import '@validationcloud/fractal-ui/tailwind.css';
34
24
  ```
35
25
 
36
- ## Local development
37
-
38
- Install packages:
39
-
40
- ```sh
41
- npm install
42
- ```
26
+ ## Development
43
27
 
44
- Start Storybook development server:
28
+ Requires Node.js 22.14.0+ and pnpm.
45
29
 
46
30
  ```sh
47
- npm run storybook
31
+ pnpm install
32
+ pnpm storybook
48
33
  ```
49
34
 
50
- Storybook can be accessed at [http://localhost:6006](http://localhost:6006)
51
-
52
- # (Optional) Set up git hooks for pre-commit checks
53
-
54
- pnpm run setup-hooks
35
+ Open http://localhost:6006
55
36
 
56
- # To disable: git config --unset core.hooksPath
57
-
58
- ## Project structure
59
-
60
- ```
61
- ├── src -> svgs files (e.g: project logo, icons)
62
- │ ├── assets -> serverless functions deployed as API on Vercel
63
- │ ├── components -> publicy exported components
64
- │ ├── internal -> components used internally, not exported
65
- │ ├── lib -> utility function and shared logic
66
- │ └── styles -> stylesheets with design tokens and custom Tailwind classes
67
- ```
37
+ Live docs: https://fractal-ui.vercel.app/
68
38
 
69
- ## Storybook
39
+ ## Tech Stack
70
40
 
71
- A deployed version of the @validationcloud/fractal-ui Storybook docs can be found at [https://fractal-ui.vercel.app/](https://fractal-ui.vercel.app/)
41
+ - React 19
42
+ - TypeScript 5
43
+ - Tailwind CSS 4
44
+ - Radix UI (headless primitives)
45
+ - Zod (schema validation)
46
+ - Vite (build tooling)
47
+ - Storybook (component documentation)
48
+ - Vitest (testing)
49
+ - ESLint + Prettier (code quality)
50
+ - pnpm (package manager)
@@ -0,0 +1,9 @@
1
+ import { CanvasRenderingContext2D } from 'skia-canvas';
2
+ export declare const FOOTER_HEIGHT = 44;
3
+ /**
4
+ * Draws the branded Mavrik footer onto a canvas context.
5
+ *
6
+ * Layout: VC logo on left, "Powered by [Mavrik wordmark] ai.validationcloud.io" on right.
7
+ * Call with the context already scaled for DPR — all coordinates are in logical pixels.
8
+ */
9
+ export declare function drawMavrikFooter(ctx: CanvasRenderingContext2D, width: number, yOffset: number): void;
@@ -0,0 +1,22 @@
1
+ import { Image as v } from "skia-canvas";
2
+ import { vcLogoDataUri as D, mavrikWordmarkDataUri as G } from "./footer-svg-assets.js";
3
+ const p = 44, H = "#1a1d1f", n = "#6f767e", k = "#2e313c", c = 20, d = 8, y = 140, I = 16, f = 72, _ = 12;
4
+ function O(o) {
5
+ const e = new v();
6
+ return e.src = o, e;
7
+ }
8
+ function P(o, e, i) {
9
+ o.fillStyle = H, o.fillRect(0, i, e, p), o.fillStyle = k, o.fillRect(0, i, e, 1);
10
+ const g = O(D(n)), u = O(G(n)), s = i + p / 2;
11
+ o.drawImage(g, c, s - I / 2, y, I);
12
+ const l = "ai.validationcloud.io", a = "Powered by";
13
+ o.font = "500 11px Poppins";
14
+ const T = o.measureText(l);
15
+ o.font = "500 11px Poppins";
16
+ const w = o.measureText(a), t = e - c - T.width, m = t - d - f, R = m - d - w.width, r = s + 4;
17
+ o.fillStyle = n, o.fillText(a, R, r), o.drawImage(u, m, s - _ / 2, f, _), o.font = "500 11px Poppins", o.fillStyle = n, o.fillText(l, t, r), o.strokeStyle = n, o.lineWidth = 1, o.beginPath(), o.moveTo(t, r + 2), o.lineTo(t + T.width, r + 2), o.stroke();
18
+ }
19
+ export {
20
+ p as FOOTER_HEIGHT,
21
+ P as drawMavrikFooter
22
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * SVG brand assets for server-side canvas rendering, embedded as inline strings.
3
+ *
4
+ * Fill color is parameterized so the same paths can be rendered in any color.
5
+ * Paths match src/assets/vc-logo.svg and ai-app/components/mavrik.tsx respectively.
6
+ */
7
+ export declare function vcLogoDataUri(fill: string): string;
8
+ export declare function mavrikWordmarkDataUri(fill: string): string;
@@ -0,0 +1,37 @@
1
+ function q(a) {
2
+ return `data:image/svg+xml;base64,${Buffer.from(a).toString("base64")}`;
3
+ }
4
+ function C(a) {
5
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="210" height="24" fill="none" viewBox="0 0 210 24">
6
+ <g fill="${a}">
7
+ <path fill-rule="evenodd" d="M33.733 1.868h-21.67C6.438 1.868 1.878 6.404 1.878 12s4.56 10.132 10.185 10.132h21.67c5.625 0 10.185-4.536 10.185-10.132S39.358 1.868 33.733 1.868M0 12c0 6.627 5.4 12 12.063 12h21.67c6.662 0 12.063-5.373 12.063-12s-5.4-12-12.063-12h-21.67C5.401 0 0 5.373 0 12" clip-rule="evenodd"/>
8
+ <path fill-rule="evenodd" d="M33.734 5.174h-21.67C8.273 5.174 5.2 8.23 5.2 12s3.073 6.826 6.863 6.826h21.67c3.79 0 6.862-3.056 6.862-6.826s-3.072-6.826-6.862-6.826M3.323 12c0 4.802 3.912 8.695 8.74 8.695h21.67c4.827 0 8.74-3.893 8.74-8.695s-3.913-8.695-8.74-8.695h-21.67c-4.828 0-8.74 3.893-8.74 8.695" clip-rule="evenodd"/>
9
+ <path fill-rule="evenodd" d="M33.733 8.48h-21.67A3.53 3.53 0 0 0 8.523 12a3.53 3.53 0 0 0 3.54 3.521h21.67a3.53 3.53 0 0 0 3.54-3.52 3.53 3.53 0 0 0-3.54-3.522M6.646 12c0 2.976 2.425 5.39 5.417 5.39h21.67c2.992 0 5.418-2.414 5.418-5.39s-2.426-5.39-5.418-5.39h-21.67c-2.992 0-5.417 2.414-5.417 5.39" clip-rule="evenodd"/>
10
+ <path d="M58.45 20.695h-2.77L48.592 3.327h2.7l5.773 14.542 5.773-14.542h2.7zM73.986 20.695h-2.06l-.14-1.482q-.64.81-1.617 1.262-.978.45-2.165.451-1.246 0-2.223-.486a3.86 3.86 0 0 1-1.537-1.332 3.4 3.4 0 0 1-.559-1.922q0-1.134.606-1.991.605-.868 1.653-1.355 1.047-.498 2.386-.498.838 0 1.699.197a6.6 6.6 0 0 1 1.571.556v-.429q0-.844-.442-1.447a2.7 2.7 0 0 0-1.187-.938 4.1 4.1 0 0 0-1.653-.324q-.802 0-1.641.278-.826.277-1.56.857l-.721-1.934a9.3 9.3 0 0 1 2.2-.95 8.3 8.3 0 0 1 2.257-.323q1.583 0 2.724.625a4.35 4.35 0 0 1 1.78 1.783q.63 1.146.63 2.71zm-5.517-1.783q.827 0 1.525-.336a2.93 2.93 0 0 0 1.129-.973q.442-.636.477-1.482v-.162a4.7 4.7 0 0 0-1.338-.683 4.6 4.6 0 0 0-1.502-.255q-1.176 0-1.955.556-.78.555-.78 1.424 0 .544.314.984.326.43.873.683.56.244 1.257.244M77.988 20.695h-2.54V2.864h2.54zM80.666 5.758q-.548 0-.92-.382a1.28 1.28 0 0 1-.373-.926q0-.545.373-.915.372-.382.92-.382.56 0 .932.382.385.37.385.915t-.385.926q-.373.382-.932.382m1.188 14.937h-2.388V9.116h2.388zM95.628 20.695H93.52l-.128-1.656a5.7 5.7 0 0 1-1.909 1.39q-1.106.497-2.432.497-1.677 0-3.003-.787a5.7 5.7 0 0 1-2.095-2.154q-.757-1.365-.757-3.08 0-1.724.757-3.08a5.7 5.7 0 0 1 2.095-2.153q1.326-.787 3.003-.787 1.257 0 2.328.451a5.5 5.5 0 0 1 1.862 1.262V3.327h2.386zm-6.18-1.9q1.059 0 1.908-.486a3.75 3.75 0 0 0 1.374-1.32q.512-.833.512-1.898v-.394q0-1.065-.512-1.899a3.66 3.66 0 0 0-1.374-1.308q-.85-.475-1.908-.475-1.083 0-1.944.51a3.7 3.7 0 0 0-1.362 1.389q-.5.869-.5 1.98t.5 1.991a3.8 3.8 0 0 0 1.362 1.401q.861.51 1.944.51M107.269 20.695h-2.061l-.139-1.482q-.64.81-1.618 1.262-.978.45-2.165.451-1.245 0-2.223-.486a3.86 3.86 0 0 1-1.536-1.332 3.4 3.4 0 0 1-.56-1.922q0-1.134.606-1.991.605-.868 1.653-1.355 1.047-.498 2.386-.498a7.6 7.6 0 0 1 1.699.197 6.6 6.6 0 0 1 1.571.556v-.429q0-.844-.442-1.447a2.7 2.7 0 0 0-1.187-.938 4.1 4.1 0 0 0-1.653-.324 5.166 5.166 0 0 0-3.2 1.135l-.722-1.934a9.3 9.3 0 0 1 2.2-.95 8.3 8.3 0 0 1 2.258-.323q1.583 0 2.723.625a4.35 4.35 0 0 1 1.781 1.783q.629 1.146.629 2.71zm-5.517-1.783q.826 0 1.524-.336a2.9 2.9 0 0 0 1.129-.973q.442-.636.477-1.482v-.162a4.6 4.6 0 0 0-1.338-.683 4.6 4.6 0 0 0-1.502-.255q-1.175 0-1.955.556-.78.555-.78 1.424 0 .544.314.984.327.43.873.683.56.244 1.258.244M116.424 20.405q-1.221.521-2.362.521t-2.002-.486a3.5 3.5 0 0 1-1.339-1.366q-.477-.892-.477-2.05v-5.789h-2.037V9.116h2.153V6.222h2.27v2.894h3.399v2.119h-3.399v5.35q0 1.018.547 1.62.558.59 1.432.59.734 0 1.455-.44zM118.58 5.758q-.548 0-.92-.382a1.28 1.28 0 0 1-.373-.926q0-.545.373-.915.372-.382.92-.382.56 0 .932.382.385.37.385.915t-.385.926a1.25 1.25 0 0 1-.932.382m1.188 14.937h-2.388V9.116h2.388zM127.257 20.926q-1.746 0-3.143-.787a5.85 5.85 0 0 1-2.2-2.142q-.803-1.366-.803-3.092 0-1.713.803-3.068a5.8 5.8 0 0 1 2.2-2.153q1.397-.8 3.143-.8 1.757 0 3.142.8a5.76 5.76 0 0 1 2.177 2.153q.803 1.355.803 3.068 0 1.725-.803 3.092a5.8 5.8 0 0 1-2.177 2.142q-1.385.787-3.142.787m-.012-2.13q1.06 0 1.886-.51a3.7 3.7 0 0 0 1.315-1.39q.489-.88.489-2.002 0-1.1-.489-1.969a3.6 3.6 0 0 0-1.315-1.389q-.827-.52-1.886-.52-1.047 0-1.885.52a3.7 3.7 0 0 0-1.327 1.39q-.477.868-.477 1.968 0 1.123.477 2.003a3.8 3.8 0 0 0 1.327 1.39q.837.509 1.885.509M145.816 20.695h-2.386v-6.287q0-1.54-.849-2.455-.839-.915-2.258-.915-1.466 0-2.363.973-.896.972-.896 2.582v6.102h-2.386V9.116h2.013l.082 1.864a4.25 4.25 0 0 1 1.676-1.551q1.035-.544 2.432-.544 2.294 0 3.609 1.377 1.326 1.379 1.326 3.798zM166.178 18.483a8.7 8.7 0 0 1-2.888 1.887q-1.664.672-3.631.672t-3.632-.672a8.7 8.7 0 0 1-2.898-1.887 8.9 8.9 0 0 1-1.908-2.871q-.676-1.656-.676-3.601 0-1.957.676-3.601a8.7 8.7 0 0 1 1.908-2.872 8.7 8.7 0 0 1 2.898-1.887q1.665-.671 3.632-.671 1.955 0 3.619.683 1.677.671 2.875 1.864l-1.78 1.806a6.2 6.2 0 0 0-2.094-1.54q-1.212-.567-2.654-.567-1.397 0-2.573.51a6 6 0 0 0-2.049 1.423 6.6 6.6 0 0 0-1.361 2.154q-.478 1.239-.478 2.698t.478 2.698a6.7 6.7 0 0 0 1.361 2.165 6.2 6.2 0 0 0 2.049 1.424q1.175.498 2.573.498 1.442 0 2.654-.556a6.2 6.2 0 0 0 2.083-1.552zM170.092 20.695h-2.54V2.864h2.54zM177.534 20.926q-1.745 0-3.143-.787a5.84 5.84 0 0 1-2.199-2.142q-.803-1.366-.803-3.092 0-1.713.803-3.068a5.8 5.8 0 0 1 2.199-2.153q1.398-.8 3.143-.8 1.758 0 3.142.8a5.75 5.75 0 0 1 2.176 2.153q.804 1.355.803 3.068 0 1.725-.803 3.092a5.8 5.8 0 0 1-2.176 2.142q-1.384.787-3.142.787m-.013-2.13q1.06 0 1.887-.51a3.7 3.7 0 0 0 1.315-1.39q.488-.88.488-2.002 0-1.1-.488-1.969a3.6 3.6 0 0 0-1.315-1.389q-.827-.52-1.887-.52a3.5 3.5 0 0 0-1.885.52 3.7 3.7 0 0 0-1.326 1.39q-.477.868-.477 1.968 0 1.123.477 2.003a3.8 3.8 0 0 0 1.326 1.39 3.56 3.56 0 0 0 1.885.509M196.1 20.695h-2.026l-.082-1.864q-.64 1.018-1.676 1.563-1.025.532-2.433.532-2.28 0-3.607-1.378-1.316-1.39-1.316-3.797V9.116h2.387v6.287q0 1.54.837 2.455.84.915 2.258.915 1.468 0 2.364-.973.907-.984.907-2.582V9.116h2.387zM209.84 20.695h-2.106l-.129-1.656a5.7 5.7 0 0 1-1.908 1.39q-1.105.497-2.433.497-1.676 0-3.002-.787a5.7 5.7 0 0 1-2.096-2.154q-.756-1.365-.756-3.08 0-1.724.756-3.08a5.7 5.7 0 0 1 2.096-2.153q1.326-.787 3.002-.787 1.257 0 2.329.451a5.5 5.5 0 0 1 1.862 1.262V3.327h2.385zm-6.18-1.9q1.059 0 1.908-.486a3.74 3.74 0 0 0 1.374-1.32q.512-.833.513-1.898v-.394q0-1.065-.513-1.899a3.65 3.65 0 0 0-1.374-1.308q-.849-.475-1.908-.475-1.082 0-1.943.51a3.7 3.7 0 0 0-1.363 1.389q-.5.869-.499 1.98 0 1.111.499 1.991a3.8 3.8 0 0 0 1.363 1.401q.86.51 1.943.51"/>
11
+ </g>
12
+ </svg>`;
13
+ }
14
+ function t(a) {
15
+ return q(C(a));
16
+ }
17
+ function h(a) {
18
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="97" height="16" viewBox="0 0 97 16" fill="none">
19
+ <g fill="${a}">
20
+ <path d="M12.4686 0.552591C8.01911 0.854828 4.51929 4.0145 4.51929 7.86777C4.51929 11.8828 8.31918 15.1448 13.0339 15.2057C11.967 15.7117 10.7373 16 9.42818 16C9.35273 16 9.27754 15.999 9.20263 15.9971C9.12224 15.999 9.04158 16 8.96067 16C4.01183 16 0 12.4183 0 8C0 3.58172 4.01183 0 8.96067 0C9.04158 0 9.12224 0.000957396 9.20263 0.00286019C9.27754 0.000957945 9.35273 0 9.42818 0C10.5118 0 11.5411 0.197576 12.4686 0.552591Z"/>
21
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M23.4369 14.2503C25.4894 12.7843 26.8041 10.5292 26.8041 8C26.8041 5.47078 25.4894 3.2157 23.4369 1.7497C22.1068 0.666042 20.3005 0 18.3109 0C18.2355 0 18.1603 0.000957939 18.0854 0.00286017C18.005 0.00095739 17.9243 0 17.8434 0C12.8946 0 8.88275 3.58172 8.88275 8C8.88275 12.4183 12.8946 16 17.8434 16C17.9243 16 18.005 15.999 18.0854 15.9971C18.1603 15.999 18.2355 16 18.3109 16C20.3005 16 22.1068 15.334 23.4369 14.2503ZM19.0901 14.0165C22.4037 14.0165 25.0899 11.3228 25.0899 8C25.0899 4.67716 22.4037 1.98347 19.0901 1.98347C15.7765 1.98347 13.0904 4.67716 13.0904 8C13.0904 11.3228 15.7765 14.0165 19.0901 14.0165Z"/>
22
+ <path d="M31.1982 15.7817V0.436563H33.2837L39.475 10.3902H38.2802L44.4498 0.436563H46.5353V15.7817H43.6026V5.52251L44.1674 5.69714L39.866 12.6385H37.8674L33.5661 5.69714L34.1526 5.52251V15.7817H31.1982Z"/>
23
+ <path d="M53.5219 16C52.5661 16 51.7043 15.7599 50.9368 15.2797C50.1692 14.7995 49.5682 14.1446 49.1337 13.3151C48.6992 12.4857 48.482 11.5543 48.482 10.5211C48.482 9.4734 48.6992 8.53479 49.1337 7.70532C49.5682 6.87585 50.1692 6.22101 50.9368 5.74079C51.7043 5.26057 52.5661 5.02046 53.5219 5.02046C54.275 5.02046 54.9485 5.17326 55.5422 5.47885C56.136 5.78445 56.6067 6.21373 56.9543 6.76671C57.3164 7.30514 57.5119 7.91633 57.5408 8.60027V12.3984C57.5119 13.0969 57.3164 13.7153 56.9543 14.2538C56.6067 14.7922 56.136 15.2215 55.5422 15.5416C54.9485 15.8472 54.275 16 53.5219 16ZM54.0433 13.3588C54.8398 13.3588 55.4843 13.0969 55.9767 12.573C56.4691 12.0346 56.7153 11.3433 56.7153 10.4993C56.7153 9.94634 56.5995 9.45885 56.3677 9.03683C56.1505 8.60027 55.8391 8.26558 55.4336 8.03274C55.0426 7.78536 54.5791 7.66166 54.0433 7.66166C53.5219 7.66166 53.0585 7.78536 52.653 8.03274C52.2619 8.26558 51.9506 8.60027 51.7188 9.03683C51.5016 9.45885 51.393 9.94634 51.393 10.4993C51.393 11.0668 51.5016 11.5689 51.7188 12.0055C51.9506 12.4275 52.2619 12.7622 52.653 13.0096C53.0585 13.2424 53.5219 13.3588 54.0433 13.3588ZM56.5633 15.7817V12.9441L57.0195 10.3684L56.5633 7.83629V5.23875H59.3874V15.7817H56.5633Z"/>
24
+ <path d="M65.0984 15.7817L60.4712 5.23875H63.5994L66.9232 13.9263H65.3808L68.7263 5.23875H71.7459L67.1404 15.7817H65.0984Z"/>
25
+ <path d="M72.8416 15.7817V5.23875H75.6875V15.7817H72.8416ZM75.6875 9.95362L74.5795 9.21146C74.7099 7.91633 75.0864 6.89768 75.7092 6.15553C76.3319 5.39882 77.2299 5.02046 78.403 5.02046C78.9098 5.02046 79.3661 5.10778 79.7716 5.2824C80.1771 5.44247 80.5464 5.71169 80.8795 6.09004L79.0981 8.14188C78.9388 7.96726 78.7433 7.83629 78.5116 7.74898C78.2943 7.66166 78.0409 7.61801 77.7512 7.61801C77.143 7.61801 76.6433 7.81446 76.2523 8.20737C75.8757 8.58572 75.6875 9.1678 75.6875 9.95362Z"/>
26
+ <path d="M81.6619 15.7817V5.23875H84.5294V15.7817H81.6619ZM83.0957 3.53615C82.6322 3.53615 82.2484 3.38336 81.9443 3.07776C81.6402 2.75762 81.4881 2.36471 81.4881 1.89905C81.4881 1.44793 81.6402 1.0623 81.9443 0.742156C82.2484 0.422011 82.6322 0.261938 83.0957 0.261938C83.5736 0.261938 83.9574 0.422011 84.247 0.742156C84.5512 1.0623 84.7032 1.44793 84.7032 1.89905C84.7032 2.36471 84.5512 2.75762 84.247 3.07776C83.9574 3.38336 83.5736 3.53615 83.0957 3.53615Z"/>
27
+ <path d="M93.5242 15.7817L89.4618 10.3465L93.5024 5.23875H96.7828L92.0469 11.0014L92.1556 9.60437L97 15.7817H93.5242ZM86.8332 15.7817V0H89.679V15.7817H86.8332Z"/>
28
+ </g>
29
+ </svg>`;
30
+ }
31
+ function l(a) {
32
+ return q(h(a));
33
+ }
34
+ export {
35
+ l as mavrikWordmarkDataUri,
36
+ t as vcLogoDataUri
37
+ };
@@ -1,3 +1,4 @@
1
+ import { Canvas } from 'skia-canvas';
1
2
  import { ChartTheme } from '../components/echarts-renderer/chart-theme';
2
3
  import { EChartsThemeOption } from '../components/echarts-renderer/echarts-theme-option';
3
4
  /** Font family registration for server-side chart rendering */
@@ -19,6 +20,8 @@ export interface RenderChartToImageOptions {
19
20
  height?: number;
20
21
  devicePixelRatio?: number;
21
22
  }
23
+ /** Renders an ECharts chart to a skia-canvas Canvas instance. */
24
+ export declare function renderChartToCanvas({ option, theme, fonts, width, height, devicePixelRatio, }: RenderChartToImageOptions): Canvas;
22
25
  /**
23
26
  * Renders an ECharts chart to a PNG image buffer.
24
27
  *
@@ -39,5 +42,5 @@ export interface RenderChartToImageOptions {
39
42
  * });
40
43
  * ```
41
44
  */
42
- export declare function renderChartToImage({ option, theme, fonts, width, height, devicePixelRatio, }: RenderChartToImageOptions): Buffer;
45
+ export declare function renderChartToImage(options: RenderChartToImageOptions): Buffer;
43
46
  export {};
@@ -1,33 +1,33 @@
1
- import * as h from "echarts";
2
- import { randomUUID as y } from "node:crypto";
1
+ import * as p from "echarts";
2
+ import { randomUUID as C } from "node:crypto";
3
3
  import { writeFileSync as F, mkdtempSync as O } from "node:fs";
4
- import { tmpdir as j } from "node:os";
5
- import T from "node:path";
6
- import { Image as C, Canvas as I, FontLibrary as S } from "skia-canvas";
4
+ import { tmpdir as b } from "node:os";
5
+ import h from "node:path";
6
+ import { Image as I, Canvas as S, FontLibrary as j } from "skia-canvas";
7
7
  import { calculateTitleLayout as w } from "../components/echarts-renderer/calculate-title-layout.js";
8
- import { isChartTheme as $ } from "../components/echarts-renderer/chart-theme.js";
8
+ import { isChartTheme as v } from "../components/echarts-renderer/chart-theme.js";
9
9
  import { replaceFormatterTokens as A } from "../components/echarts-renderer/formatters/replace-formatter-tokens.js";
10
10
  import { mergeThemeGraphicIntoOptions as D } from "../components/echarts-renderer/merge-theme-graphic-into-options.js";
11
- globalThis.Image = C;
12
- const d = /* @__PURE__ */ new Set();
13
- let l;
11
+ globalThis.Image = I;
12
+ const l = /* @__PURE__ */ new Set();
13
+ let m;
14
14
  function E() {
15
- return l || (l = O(T.join(j(), "chart-fonts-"))), l;
15
+ return m || (m = O(h.join(b(), "chart-fonts-"))), m;
16
16
  }
17
- function G(e) {
18
- for (const t of e)
19
- if (!d.has(t.family))
17
+ function N(r) {
18
+ for (const t of r)
19
+ if (!l.has(t.family))
20
20
  try {
21
- const r = E(), n = t.data.map((c, m) => {
22
- const o = T.join(r, `${t.family}-${String(m)}.ttf`);
23
- return F(o, c), o;
21
+ const e = E(), n = t.data.map((i, s) => {
22
+ const o = h.join(e, `${t.family}-${String(s)}.ttf`);
23
+ return F(o, i), o;
24
24
  });
25
- S.use(t.family, n), d.add(t.family);
26
- } catch (r) {
27
- console.warn(`Failed to register ${t.family} fonts, charts will use fallback font:`, r);
25
+ j.use(t.family, n), l.add(t.family);
26
+ } catch (e) {
27
+ console.warn(`Failed to register ${t.family} fonts, charts will use fallback font:`, e);
28
28
  }
29
29
  }
30
- const N = /* @__PURE__ */ new Set([
30
+ const P = /* @__PURE__ */ new Set([
31
31
  "aria",
32
32
  // Tries to set DOM attributes which node-canvas doesn't implement
33
33
  "toolbox",
@@ -39,48 +39,41 @@ const N = /* @__PURE__ */ new Set([
39
39
  "axisPointer"
40
40
  // Crosshair on hover
41
41
  ]);
42
- function P(e) {
43
- if (!e || typeof e != "object" || Array.isArray(e))
42
+ function $(r) {
43
+ if (!r || typeof r != "object" || Array.isArray(r))
44
44
  return { animation: !1 };
45
45
  const t = Object.fromEntries(
46
- Object.entries(e).filter(([r]) => !N.has(r))
46
+ Object.entries(r).filter(([e]) => !P.has(e))
47
47
  );
48
48
  return t.animation = !1, t;
49
49
  }
50
- function V({
51
- option: e,
50
+ function k({
51
+ option: r,
52
52
  theme: t,
53
- fonts: r,
53
+ fonts: e,
54
54
  width: n = 800,
55
- height: c = 600,
56
- devicePixelRatio: m = 2
55
+ height: i = 600,
56
+ devicePixelRatio: s = 2
57
57
  }) {
58
- r?.length && G(r);
59
- let o, i, f;
60
- const a = t;
61
- if (a && typeof a == "object")
62
- if ($(a)) {
63
- o = `theme-${y()}`, i = a.config, f = i.graphic;
64
- const { graphic: p, ...s } = i;
65
- h.registerTheme(o, s);
66
- } else {
67
- o = `theme-${y()}`, i = a, f = i.graphic;
68
- const { graphic: p, ...s } = i;
69
- h.registerTheme(o, s);
70
- }
71
- const g = new I(n, c), u = h.init(g, o, {
58
+ e?.length && N(e);
59
+ let o, a, c;
60
+ if (t) {
61
+ a = v(t) ? t.config : t, c = a.graphic, o = `theme-${C()}`;
62
+ const { graphic: x, ...T } = a;
63
+ p.registerTheme(o, T);
64
+ }
65
+ const f = new S(n, i), u = p.init(f, o, {
72
66
  renderer: "canvas",
73
- devicePixelRatio: m,
67
+ devicePixelRatio: s,
74
68
  width: n,
75
- height: c
76
- });
77
- try {
78
- const p = P(e), s = A(p), b = w(s, n, i);
79
- return u.setOption(D(b, f), { replaceMerge: ["graphic"] }), g.toBufferSync("png");
80
- } finally {
81
- u.dispose();
82
- }
69
+ height: i
70
+ }), g = $(r), d = A(g), y = w(d, n, a);
71
+ return u.setOption(D(y, c), { replaceMerge: ["graphic"] }), f;
72
+ }
73
+ function W(r) {
74
+ return k(r).toBufferSync("png");
83
75
  }
84
76
  export {
85
- V as renderChartToImage
77
+ k as renderChartToCanvas,
78
+ W as renderChartToImage
86
79
  };
@@ -6,28 +6,12 @@ export interface RenderMavrikChartToImageOptions {
6
6
  devicePixelRatio?: number;
7
7
  }
8
8
  /**
9
- * Renders an ECharts chart to a PNG image buffer using the Mavrik theme.
9
+ * Renders an ECharts chart to a PNG image buffer using the Mavrik theme,
10
+ * with a branded footer strip showing the Validation Cloud logo and Mavrik wordmark.
10
11
  *
11
- * Automatically selects the correct theme variant based on chart type:
12
- * - Vertical bars: gradient flows top-to-bottom
13
- * - Horizontal bars: gradient flows left-to-right
12
+ * The chart occupies `height - 44px` and the footer occupies the remaining 44px,
13
+ * so the output PNG matches the requested dimensions exactly.
14
14
  *
15
- * For custom themes, use renderChartToImage directly.
16
- *
17
- * @param options - Chart configuration and rendering options
18
- * @returns PNG image buffer
19
- *
20
- * @example
21
- * ```ts
22
- * const buffer = renderMavrikChartToImage({
23
- * option: {
24
- * xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
25
- * yAxis: { type: 'value' },
26
- * series: [{ data: [120, 200, 150], type: 'bar' }]
27
- * },
28
- * width: 800,
29
- * height: 600
30
- * });
31
- * ```
15
+ * For custom themes or no footer, use {@link renderChartToImage} directly.
32
16
  */
33
17
  export declare function renderMavrikChartToImage({ option, width, height, devicePixelRatio, }: RenderMavrikChartToImageOptions): Buffer;
@@ -1,26 +1,28 @@
1
- import { selectMavrikTheme as t } from "../components/echarts-renderer/mavrik-theme.js";
2
- import { PoppinsRegular as n, PoppinsMedium as p, PoppinsSemiBold as a, PoppinsBold as s } from "./font-data.js";
3
- import { renderChartToImage as P } from "./render-chart-to-image.js";
4
- const f = {
1
+ import { Canvas as f } from "skia-canvas";
2
+ import { selectMavrikTheme as c } from "../components/echarts-renderer/mavrik-theme.js";
3
+ import { drawMavrikFooter as g, FOOTER_HEIGHT as u } from "./draw-mavrik-footer.js";
4
+ import { PoppinsRegular as C, PoppinsMedium as h, PoppinsSemiBold as T, PoppinsBold as i } from "./font-data.js";
5
+ import { renderChartToCanvas as v } from "./render-chart-to-image.js";
6
+ const I = {
5
7
  family: "Poppins",
6
- data: [n, p, a, s]
8
+ data: [C, h, T, i]
7
9
  };
8
- function l({
9
- option: e,
10
- width: o = 800,
11
- height: r = 600,
12
- devicePixelRatio: i = 2
10
+ function k({
11
+ option: n,
12
+ width: t = 800,
13
+ height: a = 600,
14
+ devicePixelRatio: r = 2
13
15
  }) {
14
- const m = t(e);
15
- return P({
16
- option: e,
17
- theme: m.config,
18
- fonts: [f],
19
- width: o,
20
- height: r,
21
- devicePixelRatio: i
22
- });
16
+ const e = c(n), s = a - u, p = v({
17
+ option: n,
18
+ theme: e.config,
19
+ fonts: [I],
20
+ width: t,
21
+ height: s,
22
+ devicePixelRatio: r
23
+ }), m = new f(t * r, a * r), o = m.getContext("2d");
24
+ return o.drawImage(p, 0, 0), o.save(), o.scale(r, r), g(o, t, s), o.restore(), m.toBufferSync("png");
23
25
  }
24
26
  export {
25
- l as renderMavrikChartToImage
27
+ k as renderMavrikChartToImage
26
28
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@validationcloud/fractal-ui",
3
3
  "private": false,
4
- "version": "1.71.0",
4
+ "version": "1.73.0",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",
7
7
  "files": [