@aspprev/versi-ds 0.5.0 → 0.5.4

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
@@ -32,6 +32,42 @@ import "@aspprev/versi-ds/styles.css";
32
32
  import "@aspprev/versi-ds/themes.css";
33
33
  ```
34
34
 
35
+ ### InfoGrid em aplicações com Tailwind
36
+
37
+ O layout de `InfoGrid` vem pronto em `@aspprev/versi-ds/styles.css`. Não é
38
+ necessário incluir o pacote no `content` do Tailwind, usar `safelist` ou repetir
39
+ classes responsivas no consumidor. Os breakpoints do componente são fixos:
40
+
41
+ | `columns` | abaixo de 640px | a partir de 640px | a partir de 1024px | a partir de 1440px |
42
+ | --- | --- | --- | --- | --- |
43
+ | 1 | 1 | 1 | 1 | 1 |
44
+ | 2 | 1 | 2 | 2 | 2 |
45
+ | 3 (padrão) | 1 | 2 | 3 | 3 |
46
+ | 4 | 1 | 2 | 2 | 4 |
47
+ | 6 | 1 | 2 | 3 | 6 |
48
+
49
+ As regras próprias `versi-info-grid*` usam `:where()` para permitir customização
50
+ por `className`, inclusive `grid-cols-*` e variantes responsivas, independentemente
51
+ da ordem entre o CSS do DS e as utilities do Tailwind 3 do consumidor. Para usar
52
+ nomes como `mobile:`, `tablet:` e `desktop:` nas suas customizações, configure
53
+ esses nomes no Tailwind da aplicação (640px, 1024px e 1440px, respectivamente).
54
+ Classes personalizadas devem estar nos arquivos cobertos pelo `content` do consumidor.
55
+
56
+ A implementação anterior compartilhava classes de colunas com o consumidor.
57
+ Quando o CSS do consumidor vinha depois e gerava `tablet:grid-cols-3`, mas não
58
+ `desktop:grid-cols-6`, a regra de tablet também se aplicava em desktop e vencia
59
+ pela ordem de declaração e mesma especificidade. A geração da regra de desktop
60
+ no pacote estava correta. Agora o layout usa seletores próprios, sem depender
61
+ da geração parcial de utilities. Após atualizar o JS **e** o CSS do pacote,
62
+ o contorno `className="tablet:grid-cols-3 desktop:grid-cols-6"` pode ser removido
63
+ do portal: `<InfoGrid columns={6}>` é suficiente.
64
+
65
+ Validação de navegador do artefato npm: `npm run test:info-grid-consumer`
66
+ (requer Chromium instalado com `npx playwright install chromium`). O teste
67
+ empacota e extrai o DS em um consumidor, gera Tailwind somente a partir do
68
+ `src` desse consumidor e verifica `grid-template-columns` nas duas ordens de CSS,
69
+ sem Tailwind adicional e com customização explícita por `className`.
70
+
35
71
  Use componentes pela raiz ou por um entrypoint público:
36
72
 
37
73
  ```tsx
@@ -97,7 +133,7 @@ import {
97
133
  - `DatePicker` aceita `selectionMode="year"` e mantém `selectionMode="day"` como padrão.
98
134
  - `StatusBadge` oferece as cores `primary`, `blue`, `green`, `orange`, `yellow`, `red`, `slate` e `black` nas aparências `solid`, `soft` e `outline`. `DomainStatusBadge` aceita um `statusMap` definido pelo consumidor; o DS não associa nomes de status a cores.
99
135
  - `Table` preserva os modos `fit`, `adaptive` e `scroll`; filtros e paginação respondem ao espaço do container.
100
- - `InputPhone`/`PhoneInput` e `SelectCountry` aceitam `showFlags`; o padrão é `true` e `showFlags={false}` remove a bandeira sem reservar espaço.
136
+ - `InputPhone`/`PhoneInput` e `SelectCountry`/`CountrySelect` aceitam `showFlags` (padrão: `true`); `showFlags={false}` oculta somente a bandeira do campo, sem reservar espaço. A lista de países sempre mantém as bandeiras.
101
137
  - Os controles de formulário ocupam a largura disponível do container; `className="w-full"` pode ser usado em grids, flex containers e colunas responsivas.
102
138
 
103
139
  Consulte [`docs/API-NOVOS-COMPONENTES.md`](docs/API-NOVOS-COMPONENTES.md) e o Storybook para exemplos completos, estados de erro/carregamento e contratos de acessibilidade.
@@ -192,6 +228,14 @@ npm run prepack
192
228
 
193
229
  O script `prepack` valida tokens, governança, segurança, lint, TypeScript, build, tamanho e conteúdo do pacote.
194
230
 
231
+ Os workflows compartilham as validações de segurança, pacote e consumidores.
232
+ Consulte [segurança do build e compatibilidade](docs/SEGURANCA-BUILD-COMPATIBILIDADE.md)
233
+ para a correção local de build que preserva o suporte aos navegadores atuais.
234
+ `npm run check:security` audita DS e piloto nos escopos completo e de produção,
235
+ verifica a mitigação instalada e salva relatórios em `test-results/security`.
236
+ `npm run check:release -- vX.Y.Z` confere a tag candidata contra os manifestos;
237
+ no CI de publicação, a tag é obtida do evento do GitHub.
238
+
195
239
  Para testar o exemplo integrado:
196
240
 
197
241
  ```bash
@@ -289,11 +289,12 @@ var Divider = ({
289
289
  height = "h-[1px]",
290
290
  children,
291
291
  bgColor = "black",
292
+ className,
292
293
  ...rest
293
294
  }) => {
294
295
  const colorClass = colorClassMap[bgColor];
295
296
  const barClass = classNames(children ? "w-1/3" : "w-1/2", height, colorClass);
296
- return /* @__PURE__ */ jsxs3("div", { className: classNames(width, "flex items-center justify-center"), children: [
297
+ return /* @__PURE__ */ jsxs3("div", { ...rest, className: classNames(width, "flex items-center justify-center", className), children: [
297
298
  /* @__PURE__ */ jsx4("div", { className: barClass }),
298
299
  children && /* @__PURE__ */ jsxs3("div", { className: "px-3", children: [
299
300
  children,
@@ -621,7 +622,7 @@ var avatarSizeMap = {
621
622
  };
622
623
  function Inicials(name) {
623
624
  const nome = name;
624
- if (!!nome) {
625
+ if (nome) {
625
626
  const array = nome.split(" ");
626
627
  const primeiraLetra = nome.charAt(0);
627
628
  const posicaoUltimoEspaco = nome.lastIndexOf(" ");
@@ -645,7 +646,7 @@ var Avatar = ({
645
646
  ...rest
646
647
  }) => {
647
648
  const avatarSizeClass = avatarSizeMap[size];
648
- const avatarComponent = image ? /* @__PURE__ */ jsx11(AvatarImage_default, { src: image, altDescription: description }) : !!name ? /* @__PURE__ */ jsx11(
649
+ const avatarComponent = image ? /* @__PURE__ */ jsx11(AvatarImage_default, { src: image, altDescription: description }) : name ? /* @__PURE__ */ jsx11(
649
650
  "span",
650
651
  {
651
652
  className: classNames5(
@@ -888,10 +889,10 @@ function PageButtons(props) {
888
889
  const { currentPage, totalResults, perPage, onClick, size } = props;
889
890
  const pages = Math.max(1, Math.ceil(totalResults / perPage));
890
891
  const sizeClasses = PAGINATION_SIZE_CLASSES[size];
891
- let pagesAfter = pages - currentPage > 2 ? 2 : pages - currentPage;
892
- let pagesBefore = currentPage > 2 ? 2 : currentPage === 2 ? 1 : 0;
892
+ const pagesAfter = pages - currentPage > 2 ? 2 : pages - currentPage;
893
+ const pagesBefore = currentPage > 2 ? 2 : currentPage === 2 ? 1 : 0;
893
894
  let buttonsBefore = [];
894
- let buttonsAfter = [];
895
+ const buttonsAfter = [];
895
896
  for (let i = 1; i <= pagesBefore; i++) {
896
897
  const page = currentPage - i;
897
898
  buttonsBefore = [
@@ -1070,7 +1071,7 @@ function Checkbox({
1070
1071
  layout = "row",
1071
1072
  ...props
1072
1073
  }) {
1073
- let containerClass = "";
1074
+ let containerClass;
1074
1075
  if (layout === "col") {
1075
1076
  containerClass = "flex flex-col gap-y-3 mt-3";
1076
1077
  } else if (layout === "grid-2") {
@@ -1081,7 +1082,7 @@ function Checkbox({
1081
1082
  return /* @__PURE__ */ jsx18("div", { className: containerClass, children: options.map((option) => /* @__PURE__ */ jsxs10(
1082
1083
  "label",
1083
1084
  {
1084
- className: "mr-6 flex min-h-7 cursor-pointer items-center gap-2",
1085
+ className: `mr-6 flex min-h-7 items-center gap-2 ${props.disabled ? "cursor-not-allowed" : "cursor-pointer"}`,
1085
1086
  children: [
1086
1087
  /* @__PURE__ */ jsx18(
1087
1088
  "input",
@@ -1094,7 +1095,7 @@ function Checkbox({
1094
1095
  ...props
1095
1096
  }
1096
1097
  ),
1097
- /* @__PURE__ */ jsx18("span", { className: "text-content-secondary", children: option.label })
1098
+ /* @__PURE__ */ jsx18("span", { className: props.disabled ? "text-field-content-disabled" : "text-content-secondary", children: option.label })
1098
1099
  ]
1099
1100
  },
1100
1101
  option.value
@@ -1402,15 +1403,12 @@ var InputSlider = ({
1402
1403
  prefix,
1403
1404
  suffix,
1404
1405
  sufix,
1405
- marks,
1406
- valueLabelDisplay = "auto",
1407
1406
  showLabel = false,
1408
1407
  disabled = false,
1409
1408
  inputDisabled = false,
1410
1409
  valueFormmated,
1411
1410
  showInput = false,
1412
- ariaLabel,
1413
- ...rest
1411
+ ariaLabel
1414
1412
  }) => {
1415
1413
  const [value, setValue] = useState2(initialValue);
1416
1414
  const resolvedSuffix = suffix ?? sufix;
@@ -1421,7 +1419,7 @@ var InputSlider = ({
1421
1419
  const parsedValue = Number(newValue);
1422
1420
  setValue(parsedValue);
1423
1421
  },
1424
- [functionChange]
1422
+ []
1425
1423
  );
1426
1424
  const handleInputChange = useCallback2(
1427
1425
  (event) => {
@@ -1448,7 +1446,7 @@ var InputSlider = ({
1448
1446
  /* @__PURE__ */ jsx20(
1449
1447
  "input",
1450
1448
  {
1451
- className: "w-full range pr-6 accent-primary-1",
1449
+ className: "w-full range pr-6 accent-primary-1 disabled:cursor-not-allowed disabled:accent-field-content-disabled",
1452
1450
  type: "range",
1453
1451
  name,
1454
1452
  id: name,
@@ -1465,7 +1463,7 @@ var InputSlider = ({
1465
1463
  "input",
1466
1464
  {
1467
1465
  id: valueInputId,
1468
- className: "min-w-0",
1466
+ className: "min-w-0 disabled:cursor-not-allowed disabled:text-field-content-disabled",
1469
1467
  value: inputDisabled ? "-" : value,
1470
1468
  onChange: handleInputChange,
1471
1469
  onBlur: handleBlur,
@@ -1477,7 +1475,7 @@ var InputSlider = ({
1477
1475
  disabled: disabled || inputDisabled
1478
1476
  }
1479
1477
  ),
1480
- (showLabel || prefix || resolvedSuffix || valueFormmated) && /* @__PURE__ */ jsxs12("span", { className: "shrink-0 text-sm text-content-secondary", children: [
1478
+ (showLabel || prefix || resolvedSuffix || valueFormmated) && /* @__PURE__ */ jsxs12("span", { className: `shrink-0 text-sm ${disabled ? "text-field-content-disabled" : "text-content-secondary"}`, children: [
1481
1479
  prefix,
1482
1480
  valueFormmated ?? value,
1483
1481
  resolvedSuffix
@@ -1696,18 +1694,18 @@ function resolveOptionalValue(value, options = {}) {
1696
1694
  // src/components/info-grid/InfoGrid.tsx
1697
1695
  import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
1698
1696
  var COLUMN_STYLES2 = {
1699
- 1: "grid-cols-1",
1700
- 2: "grid-cols-1 mobile:grid-cols-2",
1701
- 3: "grid-cols-1 mobile:grid-cols-2 tablet:grid-cols-3",
1702
- 4: "grid-cols-1 mobile:grid-cols-2 desktop:grid-cols-4",
1703
- 6: "grid-cols-1 mobile:grid-cols-2 tablet:grid-cols-3 desktop:grid-cols-6"
1697
+ 1: "versi-info-grid--1",
1698
+ 2: "versi-info-grid--2",
1699
+ 3: "versi-info-grid--3",
1700
+ 4: "versi-info-grid--4",
1701
+ 6: "versi-info-grid--6"
1704
1702
  };
1705
1703
  function InfoGrid({ columns = 3, className, ...rest }) {
1706
1704
  return /* @__PURE__ */ jsx25(
1707
1705
  "dl",
1708
1706
  {
1709
1707
  className: classNames10(
1710
- "grid gap-x-8 gap-y-5",
1708
+ "versi-info-grid grid gap-x-8 gap-y-5",
1711
1709
  COLUMN_STYLES2[columns],
1712
1710
  className
1713
1711
  ),
@@ -2022,7 +2020,6 @@ function FormErrorNavigation() {
2022
2020
  cleanupPendingNavigation?.();
2023
2021
  const form = event.target;
2024
2022
  let handled = false;
2025
- let observer;
2026
2023
  const timers = [];
2027
2024
  const cleanup = () => {
2028
2025
  observer?.disconnect();
@@ -2036,7 +2033,7 @@ function FormErrorNavigation() {
2036
2033
  cleanup();
2037
2034
  navigateToInvalidField(field);
2038
2035
  };
2039
- observer = new MutationObserver(tryNavigate);
2036
+ const observer = new MutationObserver(tryNavigate);
2040
2037
  observer.observe(form, {
2041
2038
  attributeFilter: ["aria-invalid"],
2042
2039
  attributes: true,
@@ -3214,15 +3211,13 @@ function resolveContainerBreakpoint(width, breakpoints = defaultContainerBreakpo
3214
3211
  );
3215
3212
  }
3216
3213
  function getBreakpointMapKey(breakpoints) {
3217
- return Object.entries(breakpoints).sort(([first], [second]) => first.localeCompare(second)).map(([name, threshold]) => `${name}:${threshold}`).join("|");
3214
+ return JSON.stringify(Object.entries(breakpoints).sort(([, first], [, second]) => first - second));
3218
3215
  }
3219
3216
  function useContainerBreakpoint(ref, options = {}) {
3220
3217
  const thresholds = options.breakpoints ?? defaultContainerBreakpoints;
3221
3218
  const thresholdsKey = getBreakpointMapKey(thresholds);
3222
3219
  const sortedThresholds = useMemo4(
3223
- () => Object.entries(thresholds).sort(
3224
- ([, first], [, second]) => first === second ? 0 : first - second
3225
- ),
3220
+ () => JSON.parse(thresholdsKey),
3226
3221
  [thresholdsKey]
3227
3222
  );
3228
3223
  const [current, setCurrent] = useState6();
@@ -3287,4 +3282,4 @@ export {
3287
3282
  resolveContainerBreakpoint,
3288
3283
  useContainerBreakpoint
3289
3284
  };
3290
- //# sourceMappingURL=chunk-5Q7V22OH.js.map
3285
+ //# sourceMappingURL=chunk-2KJU6VM4.js.map