@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.d.cts CHANGED
@@ -430,6 +430,8 @@ interface MenuPrincipalItem {
430
430
  icon: ReactNode;
431
431
  /** Texto da tag no canto (Show Tag no Figma, onde é "Experimente"). */
432
432
  tag?: string;
433
+ /** Ícone da tag. Padrão: DribbbleLogo, o do Figma. */
434
+ tagIcon?: ReactNode;
433
435
  /** Ação do item; o menu popup fecha depois dela. */
434
436
  command?: (event: MenuItemCommandEvent) => void;
435
437
  /** Link do item; sem ele o clique não navega. */
package/dist/index.d.ts CHANGED
@@ -430,6 +430,8 @@ interface MenuPrincipalItem {
430
430
  icon: ReactNode;
431
431
  /** Texto da tag no canto (Show Tag no Figma, onde é "Experimente"). */
432
432
  tag?: string;
433
+ /** Ícone da tag. Padrão: DribbbleLogo, o do Figma. */
434
+ tagIcon?: ReactNode;
433
435
  /** Ação do item; o menu popup fecha depois dela. */
434
436
  command?: (event: MenuItemCommandEvent) => void;
435
437
  /** Link do item; sem ele o clique não navega. */
package/dist/index.js CHANGED
@@ -86,6 +86,23 @@ var Accordion = forwardRef(function Accordion2({ multiple = false, activeIndex,
86
86
  }
87
87
  );
88
88
  });
89
+
90
+ // src/components/popup.ts
91
+ function seguirLado(painel, alvo) {
92
+ if (!(painel instanceof HTMLElement) || !alvo) return;
93
+ const marcar = () => {
94
+ const acima = painel.getBoundingClientRect().top < alvo.getBoundingClientRect().top;
95
+ if (acima) painel.setAttribute("data-cr-lado", "acima");
96
+ else painel.removeAttribute("data-cr-lado");
97
+ };
98
+ marcar();
99
+ new MutationObserver(marcar).observe(painel, { attributes: true, attributeFilter: ["style"] });
100
+ }
101
+ var painelDoCampo = (campo, seletorDoPainel) => {
102
+ const lista = campo?.getAttribute("aria-controls");
103
+ return lista ? document.getElementById(lista)?.closest(seletorDoPainel) : null;
104
+ };
105
+ var aoPosicionar = (onEnter) => ({ onEnter });
89
106
  var AutoComplete = forwardRef(function AutoComplete2({
90
107
  variant = "outline",
91
108
  size = "large",
@@ -137,9 +154,18 @@ var AutoComplete = forwardRef(function AutoComplete2({
137
154
  },
138
155
  // O Prime mostra um spinner próprio enquanto busca; o Figma não define esse estado.
139
156
  loadingIcon: { className: "cr-autocomplete__loader" },
140
- panel: { className: "cr-autocomplete__panel" },
141
- list: { className: "cr-autocomplete__list" },
142
- item: { className: "cr-autocomplete__item" }
157
+ panel: { className: "cr-lista cr-autocomplete__panel" },
158
+ // Lado da lista (acima ou abaixo do campo), medido logo depois de o Prime posicionar.
159
+ transition: aoPosicionar(() => {
160
+ const campo = document.getElementById(id);
161
+ seguirLado(painelDoCampo(campo, ".cr-autocomplete__panel"), campo);
162
+ }),
163
+ // A área que rola (o Prime aceita listWrapper no pt, mas o d.ts não declara).
164
+ ...{ listWrapper: { className: "cr-lista__rolagem" } },
165
+ list: { className: "cr-lista__itens" },
166
+ item: ({ context }) => ({
167
+ className: `cr-lista__item cr-autocomplete__item${context.selected ? " cr-lista__item--selecionado" : ""}`
168
+ })
143
169
  },
144
170
  ...props
145
171
  }
@@ -237,8 +263,17 @@ function Tooltip({
237
263
  useEffect(() => {
238
264
  if (!describe) return;
239
265
  const elements = resolveTargets(target);
240
- elements.forEach((element) => element.setAttribute("aria-describedby", tooltipId));
241
- return () => elements.forEach((element) => element.removeAttribute("aria-describedby"));
266
+ const ids = (element) => (element.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean);
267
+ const gravar = (element, lista) => lista.length ? element.setAttribute("aria-describedby", lista.join(" ")) : element.removeAttribute("aria-describedby");
268
+ elements.forEach((element) => {
269
+ if (!ids(element).includes(tooltipId)) gravar(element, [...ids(element), tooltipId]);
270
+ });
271
+ return () => elements.forEach(
272
+ (element) => gravar(
273
+ element,
274
+ ids(element).filter((idAtual) => idAtual !== tooltipId)
275
+ )
276
+ );
242
277
  }, [target, tooltipId, describe]);
243
278
  const classes = ["cr-tooltip", `cr-tooltip--${type}`, className].filter(Boolean).join(" ");
244
279
  const pt = {
@@ -260,6 +295,7 @@ function Tooltip({
260
295
  showDelay,
261
296
  hideDelay,
262
297
  disabled,
298
+ closeOnEscape: true,
263
299
  onBeforeShow: (e) => e.originalEvent?.type !== "focus" || usandoTeclado,
264
300
  pt,
265
301
  children: content
@@ -505,7 +541,7 @@ function Chart({
505
541
  s.label
506
542
  ] }, s.label)) })
507
543
  ] }),
508
- /* @__PURE__ */ jsxs("table", { className: "cr-chart__table", children: [
544
+ /* @__PURE__ */ jsxs("table", { className: "cr-so-leitor cr-chart__table", children: [
509
545
  title && /* @__PURE__ */ jsx("caption", { children: title }),
510
546
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
511
547
  /* @__PURE__ */ jsx("td", {}),
@@ -575,7 +611,10 @@ var Checkbox = forwardRef(function Checkbox2({
575
611
  value,
576
612
  icon: /* @__PURE__ */ jsx(Check, { size: 16 }),
577
613
  pt: {
578
- root: { className: "cr-checkbox__control" },
614
+ // Marcado pela prop do Cristal, não pelo atributo interno do Prime (data-p-highlight).
615
+ root: {
616
+ className: `cr-checkbox__control${checked ? " cr-checkbox__control--checked" : ""}`
617
+ },
579
618
  input: { className: "cr-checkbox__input" },
580
619
  box: { className: "cr-checkbox__box" },
581
620
  icon: { className: "cr-checkbox__icon", "aria-hidden": true }
@@ -585,7 +624,7 @@ var Checkbox = forwardRef(function Checkbox2({
585
624
  /* @__PURE__ */ jsx(
586
625
  "label",
587
626
  {
588
- className: `cr-checkbox__label${showLabel ? "" : " cr-checkbox__label--hidden"}`,
627
+ className: `cr-checkbox__label${showLabel ? "" : " cr-checkbox__label--hidden cr-so-leitor"}`,
589
628
  htmlFor: inputId,
590
629
  children: label
591
630
  }
@@ -816,7 +855,7 @@ function Drawer({
816
855
  panelRef.current = element;
817
856
  if (behavior === "full") setRolagem(element);
818
857
  },
819
- className: "cr-drawer__panel",
858
+ className: "cr-rolagem-fina cr-drawer__panel",
820
859
  tabIndex: behavior === "full" && rolavel ? 0 : void 0,
821
860
  children: [
822
861
  /* @__PURE__ */ jsxs("div", { className: "cr-drawer__header", children: [
@@ -839,7 +878,7 @@ function Drawer({
839
878
  "div",
840
879
  {
841
880
  ref: behavior === "fixed" ? setRolagem : void 0,
842
- className: "cr-drawer__body",
881
+ className: "cr-rolagem-fina cr-drawer__body",
843
882
  tabIndex: behavior === "fixed" && rolavel ? 0 : void 0,
844
883
  children
845
884
  }
@@ -934,10 +973,17 @@ var Menu = forwardRef(function Menu2({
934
973
  className
935
974
  }, ref) {
936
975
  const primeRef = useRef(null);
976
+ const alvo = useRef(null);
937
977
  const context = useContext(PrimeReactContext);
938
978
  useImperativeHandle(ref, () => ({
939
- toggle: (event) => primeRef.current?.toggle(event),
940
- show: (event) => primeRef.current?.show(event),
979
+ toggle: (event) => {
980
+ alvo.current = event.currentTarget;
981
+ primeRef.current?.toggle(event);
982
+ },
983
+ show: (event) => {
984
+ alvo.current = event.currentTarget;
985
+ primeRef.current?.show(event);
986
+ },
941
987
  hide: (event) => primeRef.current?.hide(event),
942
988
  getElement: () => primeRef.current?.getElement() ?? null
943
989
  }));
@@ -958,7 +1004,7 @@ var Menu = forwardRef(function Menu2({
958
1004
  className: [item.selected && "cr-menu__item--selected", item.className].filter(Boolean).join(" "),
959
1005
  data: { selected: item.selected }
960
1006
  }));
961
- const classes = ["cr-menu", `cr-menu--${density}`, popup && "cr-menu--popup", className].filter(Boolean).join(" ");
1007
+ const classes = ["cr-lista cr-menu", `cr-menu--${density}`, popup && "cr-menu--popup", className].filter(Boolean).join(" ");
962
1008
  const pt = {
963
1009
  // O nome acessível vai na lista (role=menu); o Prime lê `ariaLabel`, mas não o declara no tipo.
964
1010
  menu: {
@@ -975,7 +1021,13 @@ var Menu = forwardRef(function Menu2({
975
1021
  };
976
1022
  },
977
1023
  content: { className: "cr-menu__content" },
978
- action: { className: "cr-menu__action" },
1024
+ // Lado do popup (acima ou abaixo de quem o abriu), medido logo depois de o Prime posicionar.
1025
+ // Numa microtarefa: no onEnter o Prime ainda está religando a ref (getElement vem vazio); ela
1026
+ // roda logo depois, antes de a tela ser pintada.
1027
+ transition: aoPosicionar(
1028
+ () => queueMicrotask(() => seguirLado(primeRef.current?.getElement(), alvo.current))
1029
+ ),
1030
+ action: { className: "cr-lista__item cr-menu__action" },
979
1031
  label: { className: "cr-menu__label" }
980
1032
  };
981
1033
  const menu = /* @__PURE__ */ jsx(
@@ -1232,9 +1284,12 @@ var MenuPrincipal = forwardRef(
1232
1284
  const primeRef = useRef(null);
1233
1285
  const context = useContext(PrimeReactContext);
1234
1286
  const [baseDoAlvo, setBaseDoAlvo] = useState();
1287
+ const alvo = useRef(null);
1235
1288
  const medirAlvo = (event) => {
1236
- const alvo = event.currentTarget;
1237
- if (alvo instanceof Element) setBaseDoAlvo(alvo.getBoundingClientRect().bottom);
1289
+ const elemento = event.currentTarget;
1290
+ if (!(elemento instanceof Element)) return;
1291
+ alvo.current = elemento;
1292
+ setBaseDoAlvo(elemento.getBoundingClientRect().bottom);
1238
1293
  };
1239
1294
  useImperativeHandle(ref, () => ({
1240
1295
  toggle: (event) => {
@@ -1274,7 +1329,15 @@ var MenuPrincipal = forwardRef(
1274
1329
  item.description && /* @__PURE__ */ jsx("span", { className: "cr-menu-principal__description", children: item.description })
1275
1330
  ] }),
1276
1331
  " ",
1277
- item.tag && /* @__PURE__ */ jsx(Tag, { className: "cr-menu-principal__tag", variant: "warning", icon: /* @__PURE__ */ jsx(DribbbleLogo, {}), children: item.tag })
1332
+ item.tag && /* @__PURE__ */ jsx(
1333
+ Tag,
1334
+ {
1335
+ className: "cr-menu-principal__tag",
1336
+ variant: "warning",
1337
+ icon: item.tagIcon ?? /* @__PURE__ */ jsx(DribbbleLogo, {}),
1338
+ children: item.tag
1339
+ }
1340
+ )
1278
1341
  ]
1279
1342
  }
1280
1343
  )
@@ -1292,8 +1355,16 @@ var MenuPrincipal = forwardRef(
1292
1355
  const pt = {
1293
1356
  menu: { className: "cr-menu-principal__list", "aria-label": ariaLabel },
1294
1357
  submenuHeader: { className: "cr-menu-principal__group" },
1295
- separator: { className: "cr-menu-principal__separator" },
1296
- menuitem: { className: "cr-menu-principal__item" }
1358
+ // O divisor tracejado é o Divider do Cristal (dashed).
1359
+ separator: {
1360
+ className: "cr-divider cr-divider--horizontal cr-divider--dashed cr-menu-principal__separator"
1361
+ },
1362
+ menuitem: { className: "cr-menu-principal__item" },
1363
+ // Lado do popup, medido logo depois de o Prime posicionar.
1364
+ // Numa microtarefa: no onEnter o Prime ainda está religando a ref (como no Menu).
1365
+ transition: aoPosicionar(
1366
+ () => queueMicrotask(() => seguirLado(primeRef.current?.getElement(), alvo.current))
1367
+ )
1297
1368
  };
1298
1369
  const menu = /* @__PURE__ */ jsx(
1299
1370
  Menu$1,
@@ -1427,7 +1498,7 @@ function Modal({
1427
1498
  "div",
1428
1499
  {
1429
1500
  ref: setBody,
1430
- className: "cr-modal__body",
1501
+ className: "cr-rolagem-fina cr-modal__body",
1431
1502
  tabIndex: rolavel ? 0 : void 0,
1432
1503
  children
1433
1504
  }
@@ -1524,9 +1595,9 @@ var MultiSelect = forwardRef(function MultiSelect2({
1524
1595
  );
1525
1596
  };
1526
1597
  const checkbox = {
1527
- root: { className: "cr-multiselect__checkbox" },
1528
- box: { className: "cr-multiselect__checkbox-box" },
1529
- input: { className: "cr-multiselect__checkbox-input" }
1598
+ root: { className: "cr-checkbox__control cr-multiselect__checkbox" },
1599
+ box: { className: "cr-checkbox__box cr-multiselect__checkbox-box" },
1600
+ input: { className: "cr-checkbox__input cr-multiselect__checkbox-input" }
1530
1601
  };
1531
1602
  const pt = {
1532
1603
  // Com a lista aberta o foco vai para a busca (no body), fora da caixa: o estado Focused do
@@ -1537,7 +1608,7 @@ var MultiSelect = forwardRef(function MultiSelect2({
1537
1608
  className: `cr-field__control cr-multiselect__control${open ? " cr-multiselect__control--open" : ""}`
1538
1609
  };
1539
1610
  },
1540
- hiddenInputWrapper: { className: "cr-multiselect__hidden" },
1611
+ hiddenInputWrapper: { className: "cr-so-leitor cr-multiselect__hidden" },
1541
1612
  input: {
1542
1613
  "aria-describedby": supportText ? hintId : void 0,
1543
1614
  "aria-invalid": error ? true : void 0,
@@ -1546,7 +1617,7 @@ var MultiSelect = forwardRef(function MultiSelect2({
1546
1617
  labelContainer: { className: "cr-multiselect__value" },
1547
1618
  label: { className: "cr-multiselect__chips" },
1548
1619
  trigger: { className: "cr-field__icon cr-multiselect__trigger" },
1549
- panel: { className: `cr-multiselect__panel cr-multiselect__panel--${density}` },
1620
+ panel: { className: `cr-lista cr-multiselect__panel cr-multiselect__panel--${density}` },
1550
1621
  header: { className: "cr-multiselect__header" },
1551
1622
  headerCheckboxContainer: { className: "cr-multiselect__select-all" },
1552
1623
  // O Prime repete role=checkbox na <div> em volta do <input>: o leitor de tela veria dois.
@@ -1561,13 +1632,13 @@ var MultiSelect = forwardRef(function MultiSelect2({
1561
1632
  root: { className: "cr-multiselect__search-input", "aria-label": filterPlaceholder }
1562
1633
  },
1563
1634
  closeButton: { className: "cr-multiselect__close" },
1564
- wrapper: { className: "cr-multiselect__wrapper" },
1565
- list: { className: "cr-multiselect__list" },
1635
+ wrapper: { className: "cr-lista__rolagem" },
1636
+ list: { className: "cr-lista__itens" },
1566
1637
  item: (options2) => {
1567
1638
  const context = options2?.context;
1568
1639
  const focused = context !== void 0 && context.focusedIndex === context.index;
1569
1640
  return {
1570
- className: `cr-multiselect__item${focused ? " cr-multiselect__item--focused" : ""}`
1641
+ className: `cr-lista__item cr-multiselect__item${focused ? " cr-multiselect__item--focused" : ""}`
1571
1642
  };
1572
1643
  },
1573
1644
  checkboxContainer: { className: "cr-multiselect__item-checkbox" },
@@ -1775,15 +1846,29 @@ var Select = forwardRef(function Select2({
1775
1846
  },
1776
1847
  // O <select> escondido do Prime só existe para formulários: fora da árvore de acessibilidade.
1777
1848
  select: { "aria-hidden": true },
1778
- hiddenSelectedMessage: { className: "cr-select__hidden" },
1849
+ hiddenSelectedMessage: { className: "cr-so-leitor cr-select__hidden" },
1779
1850
  // O Prime usa a mesma chave no texto do campo e no combobox escondido.
1780
1851
  input: { className: "cr-select__value" },
1781
1852
  trigger: { className: "cr-field__icon cr-select__trigger", "aria-hidden": true },
1782
- panel: { className: "cr-select__panel" },
1783
- wrapper: { className: "cr-select__wrapper" },
1784
- list: { className: "cr-select__list", id: listId },
1785
- item: { className: "cr-select__item" },
1786
- emptyMessage: { className: "cr-select__item cr-select__empty" }
1853
+ panel: { className: "cr-lista cr-select__panel" },
1854
+ // Lado da lista (acima ou abaixo do campo), medido logo depois de o Prime posicionar.
1855
+ transition: aoPosicionar(
1856
+ () => seguirLado(
1857
+ document.getElementById(listId)?.closest(".cr-select__panel"),
1858
+ document.getElementById(inputId)?.closest(".cr-select__control")
1859
+ )
1860
+ ),
1861
+ wrapper: { className: "cr-lista__rolagem cr-select__wrapper" },
1862
+ list: { className: "cr-lista__itens cr-select__list", id: listId },
1863
+ // Selecionado e em foco (teclado) pelo contexto do pt, a API pública do Prime (não data-p-*).
1864
+ item: ({ context }) => ({
1865
+ className: [
1866
+ "cr-lista__item cr-select__item",
1867
+ context.selected && "cr-lista__item--selecionado",
1868
+ context.focused && "cr-lista__item--focado"
1869
+ ].filter(Boolean).join(" ")
1870
+ }),
1871
+ emptyMessage: { className: "cr-lista__item cr-select__item cr-select__empty" }
1787
1872
  };
1788
1873
  return /* @__PURE__ */ jsxs("div", { className: classes, children: [
1789
1874
  label && /* @__PURE__ */ jsxs("label", { className: "cr-field__label", htmlFor: inputId, children: [
@@ -1970,7 +2055,8 @@ var Radio = forwardRef(function Radio2({
1970
2055
  disabled,
1971
2056
  required,
1972
2057
  pt: {
1973
- root: { className: "cr-radio__control" },
2058
+ // Marcado pela prop do Cristal, não pelo atributo interno do Prime (data-p-checked).
2059
+ root: { className: `cr-radio__control${checked ? " cr-radio__control--checked" : ""}` },
1974
2060
  input: { className: "cr-radio__input" },
1975
2061
  box: { className: "cr-radio__box" },
1976
2062
  icon: { className: "cr-radio__icon" }
@@ -1980,7 +2066,7 @@ var Radio = forwardRef(function Radio2({
1980
2066
  /* @__PURE__ */ jsx(
1981
2067
  "label",
1982
2068
  {
1983
- className: `cr-radio__label${showLabel ? "" : " cr-radio__label--hidden"}`,
2069
+ className: `cr-radio__label${showLabel ? "" : " cr-radio__label--hidden cr-so-leitor"}`,
1984
2070
  htmlFor: inputId,
1985
2071
  children: label
1986
2072
  }
@@ -2110,7 +2196,12 @@ var Switch = forwardRef(function Switch2({
2110
2196
  disabled,
2111
2197
  name,
2112
2198
  pt: {
2113
- root: { className: "cr-switch__control", role: void 0, "aria-checked": void 0 },
2199
+ // Ligado pela prop do Cristal, não pelo atributo interno do Prime (data-p-highlight).
2200
+ root: {
2201
+ className: `cr-switch__control${checked ? " cr-switch__control--checked" : ""}`,
2202
+ role: void 0,
2203
+ "aria-checked": void 0
2204
+ },
2114
2205
  input: { className: "cr-switch__input" },
2115
2206
  slider: { className: "cr-switch__track" }
2116
2207
  }
@@ -2119,7 +2210,7 @@ var Switch = forwardRef(function Switch2({
2119
2210
  /* @__PURE__ */ jsx(
2120
2211
  "label",
2121
2212
  {
2122
- className: `cr-switch__label${showLabel ? "" : " cr-switch__label--hidden"}`,
2213
+ className: `cr-switch__label${showLabel ? "" : " cr-switch__label--hidden cr-so-leitor"}`,
2123
2214
  htmlFor: inputId,
2124
2215
  children: label
2125
2216
  }