@vector-business-services/cristal-ds-web 0.13.0 → 0.14.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.cjs CHANGED
@@ -88,6 +88,23 @@ var Accordion = react.forwardRef(function Accordion2({ multiple = false, activeI
88
88
  }
89
89
  );
90
90
  });
91
+
92
+ // src/components/popup.ts
93
+ function seguirLado(painel, alvo) {
94
+ if (!(painel instanceof HTMLElement) || !alvo) return;
95
+ const marcar = () => {
96
+ const acima = painel.getBoundingClientRect().top < alvo.getBoundingClientRect().top;
97
+ if (acima) painel.setAttribute("data-cr-lado", "acima");
98
+ else painel.removeAttribute("data-cr-lado");
99
+ };
100
+ marcar();
101
+ new MutationObserver(marcar).observe(painel, { attributes: true, attributeFilter: ["style"] });
102
+ }
103
+ var painelDoCampo = (campo, seletorDoPainel) => {
104
+ const lista = campo?.getAttribute("aria-controls");
105
+ return lista ? document.getElementById(lista)?.closest(seletorDoPainel) : null;
106
+ };
107
+ var aoPosicionar = (onEnter) => ({ onEnter });
91
108
  var AutoComplete = react.forwardRef(function AutoComplete2({
92
109
  variant = "outline",
93
110
  size = "large",
@@ -139,9 +156,18 @@ var AutoComplete = react.forwardRef(function AutoComplete2({
139
156
  },
140
157
  // O Prime mostra um spinner próprio enquanto busca; o Figma não define esse estado.
141
158
  loadingIcon: { className: "cr-autocomplete__loader" },
142
- panel: { className: "cr-autocomplete__panel" },
143
- list: { className: "cr-autocomplete__list" },
144
- item: { className: "cr-autocomplete__item" }
159
+ panel: { className: "cr-lista cr-autocomplete__panel" },
160
+ // Lado da lista (acima ou abaixo do campo), medido logo depois de o Prime posicionar.
161
+ transition: aoPosicionar(() => {
162
+ const campo = document.getElementById(id);
163
+ seguirLado(painelDoCampo(campo, ".cr-autocomplete__panel"), campo);
164
+ }),
165
+ // A área que rola (o Prime aceita listWrapper no pt, mas o d.ts não declara).
166
+ ...{ listWrapper: { className: "cr-lista__rolagem" } },
167
+ list: { className: "cr-lista__itens" },
168
+ item: ({ context }) => ({
169
+ className: `cr-lista__item cr-autocomplete__item${context.selected ? " cr-lista__item--selecionado" : ""}`
170
+ })
145
171
  },
146
172
  ...props
147
173
  }
@@ -239,8 +265,17 @@ function Tooltip({
239
265
  react.useEffect(() => {
240
266
  if (!describe) return;
241
267
  const elements = resolveTargets(target);
242
- elements.forEach((element) => element.setAttribute("aria-describedby", tooltipId));
243
- return () => elements.forEach((element) => element.removeAttribute("aria-describedby"));
268
+ const ids = (element) => (element.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean);
269
+ const gravar = (element, lista) => lista.length ? element.setAttribute("aria-describedby", lista.join(" ")) : element.removeAttribute("aria-describedby");
270
+ elements.forEach((element) => {
271
+ if (!ids(element).includes(tooltipId)) gravar(element, [...ids(element), tooltipId]);
272
+ });
273
+ return () => elements.forEach(
274
+ (element) => gravar(
275
+ element,
276
+ ids(element).filter((idAtual) => idAtual !== tooltipId)
277
+ )
278
+ );
244
279
  }, [target, tooltipId, describe]);
245
280
  const classes = ["cr-tooltip", `cr-tooltip--${type}`, className].filter(Boolean).join(" ");
246
281
  const pt = {
@@ -262,6 +297,7 @@ function Tooltip({
262
297
  showDelay,
263
298
  hideDelay,
264
299
  disabled,
300
+ closeOnEscape: true,
265
301
  onBeforeShow: (e) => e.originalEvent?.type !== "focus" || usandoTeclado,
266
302
  pt,
267
303
  children: content
@@ -507,7 +543,7 @@ function Chart({
507
543
  s.label
508
544
  ] }, s.label)) })
509
545
  ] }),
510
- /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "cr-chart__table", children: [
546
+ /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "cr-so-leitor cr-chart__table", children: [
511
547
  title && /* @__PURE__ */ jsxRuntime.jsx("caption", { children: title }),
512
548
  /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
513
549
  /* @__PURE__ */ jsxRuntime.jsx("td", {}),
@@ -577,7 +613,10 @@ var Checkbox = react.forwardRef(function Checkbox2({
577
613
  value,
578
614
  icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.Check, { size: 16 }),
579
615
  pt: {
580
- root: { className: "cr-checkbox__control" },
616
+ // Marcado pela prop do Cristal, não pelo atributo interno do Prime (data-p-highlight).
617
+ root: {
618
+ className: `cr-checkbox__control${checked ? " cr-checkbox__control--checked" : ""}`
619
+ },
581
620
  input: { className: "cr-checkbox__input" },
582
621
  box: { className: "cr-checkbox__box" },
583
622
  icon: { className: "cr-checkbox__icon", "aria-hidden": true }
@@ -587,7 +626,7 @@ var Checkbox = react.forwardRef(function Checkbox2({
587
626
  /* @__PURE__ */ jsxRuntime.jsx(
588
627
  "label",
589
628
  {
590
- className: `cr-checkbox__label${showLabel ? "" : " cr-checkbox__label--hidden"}`,
629
+ className: `cr-checkbox__label${showLabel ? "" : " cr-checkbox__label--hidden cr-so-leitor"}`,
591
630
  htmlFor: inputId,
592
631
  children: label
593
632
  }
@@ -818,7 +857,7 @@ function Drawer({
818
857
  panelRef.current = element;
819
858
  if (behavior === "full") setRolagem(element);
820
859
  },
821
- className: "cr-drawer__panel",
860
+ className: "cr-rolagem-fina cr-drawer__panel",
822
861
  tabIndex: behavior === "full" && rolavel ? 0 : void 0,
823
862
  children: [
824
863
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cr-drawer__header", children: [
@@ -841,7 +880,7 @@ function Drawer({
841
880
  "div",
842
881
  {
843
882
  ref: behavior === "fixed" ? setRolagem : void 0,
844
- className: "cr-drawer__body",
883
+ className: "cr-rolagem-fina cr-drawer__body",
845
884
  tabIndex: behavior === "fixed" && rolavel ? 0 : void 0,
846
885
  children
847
886
  }
@@ -936,10 +975,17 @@ var Menu = react.forwardRef(function Menu2({
936
975
  className
937
976
  }, ref) {
938
977
  const primeRef = react.useRef(null);
978
+ const alvo = react.useRef(null);
939
979
  const context = react.useContext(api.PrimeReactContext);
940
980
  react.useImperativeHandle(ref, () => ({
941
- toggle: (event) => primeRef.current?.toggle(event),
942
- show: (event) => primeRef.current?.show(event),
981
+ toggle: (event) => {
982
+ alvo.current = event.currentTarget;
983
+ primeRef.current?.toggle(event);
984
+ },
985
+ show: (event) => {
986
+ alvo.current = event.currentTarget;
987
+ primeRef.current?.show(event);
988
+ },
943
989
  hide: (event) => primeRef.current?.hide(event),
944
990
  getElement: () => primeRef.current?.getElement() ?? null
945
991
  }));
@@ -960,7 +1006,7 @@ var Menu = react.forwardRef(function Menu2({
960
1006
  className: [item.selected && "cr-menu__item--selected", item.className].filter(Boolean).join(" "),
961
1007
  data: { selected: item.selected }
962
1008
  }));
963
- const classes = ["cr-menu", `cr-menu--${density}`, popup && "cr-menu--popup", className].filter(Boolean).join(" ");
1009
+ const classes = ["cr-lista cr-menu", `cr-menu--${density}`, popup && "cr-menu--popup", className].filter(Boolean).join(" ");
964
1010
  const pt = {
965
1011
  // O nome acessível vai na lista (role=menu); o Prime lê `ariaLabel`, mas não o declara no tipo.
966
1012
  menu: {
@@ -977,7 +1023,13 @@ var Menu = react.forwardRef(function Menu2({
977
1023
  };
978
1024
  },
979
1025
  content: { className: "cr-menu__content" },
980
- action: { className: "cr-menu__action" },
1026
+ // Lado do popup (acima ou abaixo de quem o abriu), medido logo depois de o Prime posicionar.
1027
+ // Numa microtarefa: no onEnter o Prime ainda está religando a ref (getElement vem vazio); ela
1028
+ // roda logo depois, antes de a tela ser pintada.
1029
+ transition: aoPosicionar(
1030
+ () => queueMicrotask(() => seguirLado(primeRef.current?.getElement(), alvo.current))
1031
+ ),
1032
+ action: { className: "cr-lista__item cr-menu__action" },
981
1033
  label: { className: "cr-menu__label" }
982
1034
  };
983
1035
  const menu$1 = /* @__PURE__ */ jsxRuntime.jsx(
@@ -1234,9 +1286,12 @@ var MenuPrincipal = react.forwardRef(
1234
1286
  const primeRef = react.useRef(null);
1235
1287
  const context = react.useContext(api.PrimeReactContext);
1236
1288
  const [baseDoAlvo, setBaseDoAlvo] = react.useState();
1289
+ const alvo = react.useRef(null);
1237
1290
  const medirAlvo = (event) => {
1238
- const alvo = event.currentTarget;
1239
- if (alvo instanceof Element) setBaseDoAlvo(alvo.getBoundingClientRect().bottom);
1291
+ const elemento = event.currentTarget;
1292
+ if (!(elemento instanceof Element)) return;
1293
+ alvo.current = elemento;
1294
+ setBaseDoAlvo(elemento.getBoundingClientRect().bottom);
1240
1295
  };
1241
1296
  react.useImperativeHandle(ref, () => ({
1242
1297
  toggle: (event) => {
@@ -1276,7 +1331,15 @@ var MenuPrincipal = react.forwardRef(
1276
1331
  item.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cr-menu-principal__description", children: item.description })
1277
1332
  ] }),
1278
1333
  " ",
1279
- item.tag && /* @__PURE__ */ jsxRuntime.jsx(Tag, { className: "cr-menu-principal__tag", variant: "warning", icon: /* @__PURE__ */ jsxRuntime.jsx(react$1.DribbbleLogo, {}), children: item.tag })
1334
+ item.tag && /* @__PURE__ */ jsxRuntime.jsx(
1335
+ Tag,
1336
+ {
1337
+ className: "cr-menu-principal__tag",
1338
+ variant: "warning",
1339
+ icon: item.tagIcon ?? /* @__PURE__ */ jsxRuntime.jsx(react$1.DribbbleLogo, {}),
1340
+ children: item.tag
1341
+ }
1342
+ )
1280
1343
  ]
1281
1344
  }
1282
1345
  )
@@ -1294,8 +1357,16 @@ var MenuPrincipal = react.forwardRef(
1294
1357
  const pt = {
1295
1358
  menu: { className: "cr-menu-principal__list", "aria-label": ariaLabel },
1296
1359
  submenuHeader: { className: "cr-menu-principal__group" },
1297
- separator: { className: "cr-menu-principal__separator" },
1298
- menuitem: { className: "cr-menu-principal__item" }
1360
+ // O divisor tracejado é o Divider do Cristal (dashed).
1361
+ separator: {
1362
+ className: "cr-divider cr-divider--horizontal cr-divider--dashed cr-menu-principal__separator"
1363
+ },
1364
+ menuitem: { className: "cr-menu-principal__item" },
1365
+ // Lado do popup, medido logo depois de o Prime posicionar.
1366
+ // Numa microtarefa: no onEnter o Prime ainda está religando a ref (como no Menu).
1367
+ transition: aoPosicionar(
1368
+ () => queueMicrotask(() => seguirLado(primeRef.current?.getElement(), alvo.current))
1369
+ )
1299
1370
  };
1300
1371
  const menu$1 = /* @__PURE__ */ jsxRuntime.jsx(
1301
1372
  menu.Menu,
@@ -1429,7 +1500,7 @@ function Modal({
1429
1500
  "div",
1430
1501
  {
1431
1502
  ref: setBody,
1432
- className: "cr-modal__body",
1503
+ className: "cr-rolagem-fina cr-modal__body",
1433
1504
  tabIndex: rolavel ? 0 : void 0,
1434
1505
  children
1435
1506
  }
@@ -1526,9 +1597,9 @@ var MultiSelect = react.forwardRef(function MultiSelect2({
1526
1597
  );
1527
1598
  };
1528
1599
  const checkbox = {
1529
- root: { className: "cr-multiselect__checkbox" },
1530
- box: { className: "cr-multiselect__checkbox-box" },
1531
- input: { className: "cr-multiselect__checkbox-input" }
1600
+ root: { className: "cr-checkbox__control cr-multiselect__checkbox" },
1601
+ box: { className: "cr-checkbox__box cr-multiselect__checkbox-box" },
1602
+ input: { className: "cr-checkbox__input cr-multiselect__checkbox-input" }
1532
1603
  };
1533
1604
  const pt = {
1534
1605
  // Com a lista aberta o foco vai para a busca (no body), fora da caixa: o estado Focused do
@@ -1539,7 +1610,7 @@ var MultiSelect = react.forwardRef(function MultiSelect2({
1539
1610
  className: `cr-field__control cr-multiselect__control${open ? " cr-multiselect__control--open" : ""}`
1540
1611
  };
1541
1612
  },
1542
- hiddenInputWrapper: { className: "cr-multiselect__hidden" },
1613
+ hiddenInputWrapper: { className: "cr-so-leitor cr-multiselect__hidden" },
1543
1614
  input: {
1544
1615
  "aria-describedby": supportText ? hintId : void 0,
1545
1616
  "aria-invalid": error ? true : void 0,
@@ -1548,7 +1619,7 @@ var MultiSelect = react.forwardRef(function MultiSelect2({
1548
1619
  labelContainer: { className: "cr-multiselect__value" },
1549
1620
  label: { className: "cr-multiselect__chips" },
1550
1621
  trigger: { className: "cr-field__icon cr-multiselect__trigger" },
1551
- panel: { className: `cr-multiselect__panel cr-multiselect__panel--${density}` },
1622
+ panel: { className: `cr-lista cr-multiselect__panel cr-multiselect__panel--${density}` },
1552
1623
  header: { className: "cr-multiselect__header" },
1553
1624
  headerCheckboxContainer: { className: "cr-multiselect__select-all" },
1554
1625
  // O Prime repete role=checkbox na <div> em volta do <input>: o leitor de tela veria dois.
@@ -1563,13 +1634,13 @@ var MultiSelect = react.forwardRef(function MultiSelect2({
1563
1634
  root: { className: "cr-multiselect__search-input", "aria-label": filterPlaceholder }
1564
1635
  },
1565
1636
  closeButton: { className: "cr-multiselect__close" },
1566
- wrapper: { className: "cr-multiselect__wrapper" },
1567
- list: { className: "cr-multiselect__list" },
1637
+ wrapper: { className: "cr-lista__rolagem" },
1638
+ list: { className: "cr-lista__itens" },
1568
1639
  item: (options2) => {
1569
1640
  const context = options2?.context;
1570
1641
  const focused = context !== void 0 && context.focusedIndex === context.index;
1571
1642
  return {
1572
- className: `cr-multiselect__item${focused ? " cr-multiselect__item--focused" : ""}`
1643
+ className: `cr-lista__item cr-multiselect__item${focused ? " cr-multiselect__item--focused" : ""}`
1573
1644
  };
1574
1645
  },
1575
1646
  checkboxContainer: { className: "cr-multiselect__item-checkbox" },
@@ -1777,15 +1848,29 @@ var Select = react.forwardRef(function Select2({
1777
1848
  },
1778
1849
  // O <select> escondido do Prime só existe para formulários: fora da árvore de acessibilidade.
1779
1850
  select: { "aria-hidden": true },
1780
- hiddenSelectedMessage: { className: "cr-select__hidden" },
1851
+ hiddenSelectedMessage: { className: "cr-so-leitor cr-select__hidden" },
1781
1852
  // O Prime usa a mesma chave no texto do campo e no combobox escondido.
1782
1853
  input: { className: "cr-select__value" },
1783
1854
  trigger: { className: "cr-field__icon cr-select__trigger", "aria-hidden": true },
1784
- panel: { className: "cr-select__panel" },
1785
- wrapper: { className: "cr-select__wrapper" },
1786
- list: { className: "cr-select__list", id: listId },
1787
- item: { className: "cr-select__item" },
1788
- emptyMessage: { className: "cr-select__item cr-select__empty" }
1855
+ panel: { className: "cr-lista cr-select__panel" },
1856
+ // Lado da lista (acima ou abaixo do campo), medido logo depois de o Prime posicionar.
1857
+ transition: aoPosicionar(
1858
+ () => seguirLado(
1859
+ document.getElementById(listId)?.closest(".cr-select__panel"),
1860
+ document.getElementById(inputId)?.closest(".cr-select__control")
1861
+ )
1862
+ ),
1863
+ wrapper: { className: "cr-lista__rolagem cr-select__wrapper" },
1864
+ list: { className: "cr-lista__itens cr-select__list", id: listId },
1865
+ // Selecionado e em foco (teclado) pelo contexto do pt, a API pública do Prime (não data-p-*).
1866
+ item: ({ context }) => ({
1867
+ className: [
1868
+ "cr-lista__item cr-select__item",
1869
+ context.selected && "cr-lista__item--selecionado",
1870
+ context.focused && "cr-lista__item--focado"
1871
+ ].filter(Boolean).join(" ")
1872
+ }),
1873
+ emptyMessage: { className: "cr-lista__item cr-select__item cr-select__empty" }
1789
1874
  };
1790
1875
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes, children: [
1791
1876
  label && /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "cr-field__label", htmlFor: inputId, children: [
@@ -1972,7 +2057,8 @@ var Radio = react.forwardRef(function Radio2({
1972
2057
  disabled,
1973
2058
  required,
1974
2059
  pt: {
1975
- root: { className: "cr-radio__control" },
2060
+ // Marcado pela prop do Cristal, não pelo atributo interno do Prime (data-p-checked).
2061
+ root: { className: `cr-radio__control${checked ? " cr-radio__control--checked" : ""}` },
1976
2062
  input: { className: "cr-radio__input" },
1977
2063
  box: { className: "cr-radio__box" },
1978
2064
  icon: { className: "cr-radio__icon" }
@@ -1982,7 +2068,7 @@ var Radio = react.forwardRef(function Radio2({
1982
2068
  /* @__PURE__ */ jsxRuntime.jsx(
1983
2069
  "label",
1984
2070
  {
1985
- className: `cr-radio__label${showLabel ? "" : " cr-radio__label--hidden"}`,
2071
+ className: `cr-radio__label${showLabel ? "" : " cr-radio__label--hidden cr-so-leitor"}`,
1986
2072
  htmlFor: inputId,
1987
2073
  children: label
1988
2074
  }
@@ -2112,7 +2198,12 @@ var Switch = react.forwardRef(function Switch2({
2112
2198
  disabled,
2113
2199
  name,
2114
2200
  pt: {
2115
- root: { className: "cr-switch__control", role: void 0, "aria-checked": void 0 },
2201
+ // Ligado pela prop do Cristal, não pelo atributo interno do Prime (data-p-highlight).
2202
+ root: {
2203
+ className: `cr-switch__control${checked ? " cr-switch__control--checked" : ""}`,
2204
+ role: void 0,
2205
+ "aria-checked": void 0
2206
+ },
2116
2207
  input: { className: "cr-switch__input" },
2117
2208
  slider: { className: "cr-switch__track" }
2118
2209
  }
@@ -2121,7 +2212,7 @@ var Switch = react.forwardRef(function Switch2({
2121
2212
  /* @__PURE__ */ jsxRuntime.jsx(
2122
2213
  "label",
2123
2214
  {
2124
- className: `cr-switch__label${showLabel ? "" : " cr-switch__label--hidden"}`,
2215
+ className: `cr-switch__label${showLabel ? "" : " cr-switch__label--hidden cr-so-leitor"}`,
2125
2216
  htmlFor: inputId,
2126
2217
  children: label
2127
2218
  }