@vector-business-services/cristal-ds-web 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -199,8 +199,13 @@ interface ChartProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'chi
199
199
  helpLabel?: string;
200
200
  /** Botões à direita do título (IconButton tertiary xsmall no Figma). */
201
201
  actions?: ReactNode;
202
- /** Altura da área do gráfico, com os eixos. Padrão: 266px, a do Figma. */
203
- height?: number;
202
+ /**
203
+ * Altura da área do gráfico, com os eixos: em px, ou `'100%'` para ocupar a altura do contêiner
204
+ * (que precisa ter altura definida). Padrão: 266px, a do Figma.
205
+ */
206
+ height?: number | '100%';
207
+ /** Legenda abaixo do gráfico. Padrão: com 2 ou mais séries. */
208
+ legend?: boolean;
204
209
  id?: string;
205
210
  className?: string;
206
211
  }
package/dist/index.d.ts CHANGED
@@ -199,8 +199,13 @@ interface ChartProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'chi
199
199
  helpLabel?: string;
200
200
  /** Botões à direita do título (IconButton tertiary xsmall no Figma). */
201
201
  actions?: ReactNode;
202
- /** Altura da área do gráfico, com os eixos. Padrão: 266px, a do Figma. */
203
- height?: number;
202
+ /**
203
+ * Altura da área do gráfico, com os eixos: em px, ou `'100%'` para ocupar a altura do contêiner
204
+ * (que precisa ter altura definida). Padrão: 266px, a do Figma.
205
+ */
206
+ height?: number | '100%';
207
+ /** Legenda abaixo do gráfico. Padrão: com 2 ou mais séries. */
208
+ legend?: boolean;
204
209
  id?: string;
205
210
  className?: string;
206
211
  }
package/dist/index.js CHANGED
@@ -603,6 +603,26 @@ var comAlfa = (cor, alfa) => {
603
603
  const [r = 0, g = 0, b = 0] = normal.match(/[\d.]+/g)?.map(Number) ?? [];
604
604
  return `rgba(${r}, ${g}, ${b}, ${alfa})`;
605
605
  };
606
+ var senoide = {
607
+ id: "crSenoide",
608
+ beforeDatasetsDraw(chart) {
609
+ chart.data.datasets.forEach((_, indice) => {
610
+ const meta = chart.getDatasetMeta(indice);
611
+ if (meta.type !== "line" || !meta.dataset || !chart.isDatasetVisible(indice)) return;
612
+ const linha = meta.dataset;
613
+ linha.updateControlPoints(chart.chartArea, meta.iScale?.axis);
614
+ const pontos = linha.points;
615
+ pontos.forEach((ponto, i) => {
616
+ const antes = pontos[i - 1];
617
+ const depois = pontos[i + 1];
618
+ ponto.cp1x = antes && !antes.skip ? (antes.x + ponto.x) / 2 : ponto.x;
619
+ ponto.cp1y = ponto.y;
620
+ ponto.cp2x = depois && !depois.skip ? (ponto.x + depois.x) / 2 : ponto.x;
621
+ ponto.cp2y = ponto.y;
622
+ });
623
+ });
624
+ }
625
+ };
606
626
  var cruz = (cor) => ({
607
627
  id: "crCruz",
608
628
  afterDatasetsDraw(chart) {
@@ -619,59 +639,7 @@ var cruz = (cor) => ({
619
639
  ctx.restore();
620
640
  }
621
641
  });
622
- var tracar = (ctx, pontos) => {
623
- pontos.forEach((ponto, i) => {
624
- const antes = pontos[i - 1];
625
- if (!antes) return ctx.moveTo(ponto.x, ponto.y);
626
- const meio = (antes.x + ponto.x) / 2;
627
- ctx.bezierCurveTo(meio, antes.y, meio, ponto.y, ponto.x, ponto.y);
628
- });
629
- };
630
- var trechos = (pontos) => pontos.reduce(
631
- (lista, ponto) => {
632
- if (ponto.skip) lista.push([]);
633
- else lista[lista.length - 1].push(ponto);
634
- return lista;
635
- },
636
- [[]]
637
- ).filter((trecho) => trecho.length > 0);
638
- var curvaDoFigma = {
639
- id: "crCurva",
640
- beforeDatasetsDraw(chart) {
641
- const { ctx, chartArea } = chart;
642
- const series = chart.data.datasets.map((dataset, indice) => ({ dataset, meta: chart.getDatasetMeta(indice), indice })).filter(({ indice }) => chart.isDatasetVisible(indice)).reverse();
643
- ctx.save();
644
- ctx.beginPath();
645
- ctx.rect(chartArea.left, chartArea.top, chartArea.width, chartArea.height);
646
- ctx.clip();
647
- series.forEach(({ dataset, meta }) => {
648
- const cor = String(dataset.borderColor);
649
- const base = Math.min(meta.yScale?.getPixelForValue(0) ?? chartArea.bottom, chartArea.bottom);
650
- const degrade = ctx.createLinearGradient(0, chartArea.top, 0, chartArea.bottom);
651
- degrade.addColorStop(0, comAlfa(cor, 0.1));
652
- degrade.addColorStop(1, comAlfa(cor, 0.02));
653
- trechos(meta.data).forEach((trecho) => {
654
- ctx.beginPath();
655
- tracar(ctx, trecho);
656
- ctx.lineTo(trecho[trecho.length - 1].x, base);
657
- ctx.lineTo(trecho[0].x, base);
658
- ctx.closePath();
659
- ctx.fillStyle = degrade;
660
- ctx.fill();
661
- });
662
- });
663
- series.forEach(({ dataset, meta }) => {
664
- ctx.strokeStyle = String(dataset.borderColor);
665
- ctx.lineWidth = 2;
666
- trechos(meta.data).forEach((trecho) => {
667
- ctx.beginPath();
668
- tracar(ctx, trecho);
669
- ctx.stroke();
670
- });
671
- });
672
- ctx.restore();
673
- }
674
- };
642
+ var semMovimento = () => typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
675
643
  var formatar = (eixo, valor) => eixo?.format ? eixo.format(valor) : String(valor);
676
644
  var Chart = forwardRef(function Chart2({
677
645
  type = "line",
@@ -685,6 +653,7 @@ var Chart = forwardRef(function Chart2({
685
653
  helpLabel = "Ajuda",
686
654
  actions,
687
655
  height = 266,
656
+ legend,
688
657
  id,
689
658
  className,
690
659
  ...props
@@ -723,8 +692,19 @@ var Chart = forwardRef(function Chart2({
723
692
  data: s.data,
724
693
  yAxisID: s.axis === "right" ? "y2" : "y",
725
694
  borderColor: cor,
726
- // A linha e a área são desenhadas pelo plugin curvaDoFigma.
727
- showLine: false,
695
+ borderWidth: 2,
696
+ // Liga a curva (Béziers) do Chart.js; os controles viram os da senoide (plugin senoide).
697
+ cubicInterpolationMode: "monotone",
698
+ // Área até o zero, em degradê da cor da série: 10% em cima e 2% embaixo.
699
+ fill: "origin",
700
+ backgroundColor: ({ chart }) => {
701
+ const area = chart.chartArea;
702
+ if (!area) return comAlfa(cor, 0.1);
703
+ const degrade = chart.ctx.createLinearGradient(0, area.top, 0, area.bottom);
704
+ degrade.addColorStop(0, comAlfa(cor, 0.1));
705
+ degrade.addColorStop(1, comAlfa(cor, 0.02));
706
+ return degrade;
707
+ },
728
708
  pointRadius: 0,
729
709
  pointHoverRadius: 4,
730
710
  pointHoverBorderWidth: 2,
@@ -734,6 +714,18 @@ var Chart = forwardRef(function Chart2({
734
714
  })
735
715
  };
736
716
  }, [tema, labels, series, type, stacked]);
717
+ const ultimoQuadro = useRef(0);
718
+ const marcarAnimando = useCallback(() => {
719
+ ultimoQuadro.current = performance.now();
720
+ raiz.current?.setAttribute("data-cr-animando", "");
721
+ }, []);
722
+ const desmarcarAnimando = useCallback(() => {
723
+ const tentar = () => {
724
+ if (performance.now() - ultimoQuadro.current < 100) setTimeout(tentar, 50);
725
+ else raiz.current?.removeAttribute("data-cr-animando");
726
+ };
727
+ setTimeout(tentar, 50);
728
+ }, []);
737
729
  const options = useMemo(() => {
738
730
  if (!tema) return void 0;
739
731
  const fonte = { ...tema.fonte, weight: tema.fonte.weight };
@@ -756,7 +748,9 @@ var Chart = forwardRef(function Chart2({
756
748
  return {
757
749
  responsive: true,
758
750
  maintainAspectRatio: false,
759
- animation: false,
751
+ // A animação do Chart.js (a do p-chart), sem ela com prefers-reduced-motion. Enquanto anima, a
752
+ // raiz leva data-cr-animando (os testes de imagem esperam o fim).
753
+ animation: semMovimento() ? false : { onProgress: marcarAnimando, onComplete: desmarcarAnimando },
760
754
  interaction: { mode: "index", intersect: false },
761
755
  layout: { padding: { top: 8 } },
762
756
  scales: {
@@ -794,9 +788,14 @@ var Chart = forwardRef(function Chart2({
794
788
  }
795
789
  }
796
790
  };
797
- }, [tema, yAxis, y2Axis, temDireita, series, type, stacked]);
791
+ }, [tema, yAxis, y2Axis, temDireita, series, type, stacked, marcarAnimando, desmarcarAnimando]);
792
+ useLayoutEffect(() => {
793
+ if (data && options && !semMovimento()) raiz.current?.setAttribute("data-cr-animando", "");
794
+ }, [data, options]);
798
795
  const card = Boolean(title || actions);
799
- const classes2 = ["cr-chart", card && "cr-chart--card", className].filter(Boolean).join(" ");
796
+ const preencher = height === "100%";
797
+ const comLegenda = legend ?? series.length > 1;
798
+ const classes2 = ["cr-chart", card && "cr-chart--card", preencher && "cr-chart--fill", className].filter(Boolean).join(" ");
800
799
  return /* @__PURE__ */ jsxs("div", { ...props, ref: raiz, id, className: classes2, children: [
801
800
  card && /* @__PURE__ */ jsxs("div", { className: "cr-chart__header", children: [
802
801
  /* @__PURE__ */ jsxs("div", { className: "cr-chart__title-row", children: [
@@ -809,13 +808,13 @@ var Chart = forwardRef(function Chart2({
809
808
  actions && /* @__PURE__ */ jsx("div", { className: "cr-chart__actions", children: actions })
810
809
  ] }),
811
810
  /* @__PURE__ */ jsxs("div", { className: "cr-chart__body", children: [
812
- /* @__PURE__ */ jsx("div", { className: "cr-chart__plot", style: { height }, children: data && options && /* @__PURE__ */ jsx(
811
+ /* @__PURE__ */ jsx("div", { className: "cr-chart__plot", style: preencher ? void 0 : { height }, children: data && options && /* @__PURE__ */ jsx(
813
812
  Chart$1,
814
813
  {
815
814
  type,
816
815
  data,
817
816
  options,
818
- plugins: type === "line" ? [curvaDoFigma, cruz(tema.cruz)] : [],
817
+ plugins: type === "line" ? [senoide, cruz(tema.cruz)] : [],
819
818
  width: "100%",
820
819
  height: "100%",
821
820
  pt: {
@@ -828,7 +827,7 @@ var Chart = forwardRef(function Chart2({
828
827
  },
829
828
  type
830
829
  ) }),
831
- series.length > 1 && /* @__PURE__ */ jsx("ul", { className: "cr-chart__legend", children: series.map((s, i) => /* @__PURE__ */ jsxs("li", { className: "cr-chart__legend-item", children: [
830
+ comLegenda && /* @__PURE__ */ jsx("ul", { className: "cr-chart__legend", children: series.map((s, i) => /* @__PURE__ */ jsxs("li", { className: "cr-chart__legend-item", children: [
832
831
  /* @__PURE__ */ jsx(
833
832
  "span",
834
833
  {