@aspprev/versi-ds 0.2.0 → 0.4.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,9 +1,11 @@
1
- # Versi Design System
1
+ # VERSI Design System
2
2
 
3
- Biblioteca React de componentes, tokens, temas e utilitários para padronizar as interfaces dos produtos ASPPrev.
3
+ Biblioteca React de componentes, tokens, temas e utilitários para padronizar as interfaces dos produtos VERSI.
4
4
 
5
5
  O [Storybook](#storybook) é a documentação visual oficial: nele você pode explorar componentes, foundations, temas, padrões de composição e estados acessíveis.
6
6
 
7
+ Site oficial: [versitec.com.br](https://versitec.com.br/) · [Storybook online](https://versi-design-system.vercel.app/)
8
+
7
9
  ## Instalação
8
10
 
9
11
  ```bash
@@ -16,6 +18,9 @@ Requisitos do pacote:
16
18
  - React `>=18.2.0 <20`;
17
19
  - React DOM `>=18.2.0 <20`.
18
20
 
21
+ O identificador npm `@aspprev/versi-ds` é mantido por compatibilidade com as
22
+ aplicações consumidoras e não representa o nome visual atual da marca.
23
+
19
24
  As integrações abaixo são opcionais e só precisam ser instaladas pelas entradas que as utilizam: `@headlessui/react`, `apexcharts`, `date-fns`, `formik`, `jsbarcode`, `react-apexcharts` e `react-number-format`.
20
25
 
21
26
  ## Uso
@@ -60,8 +65,38 @@ export function Resumo() {
60
65
  | `/styles.css` | estilos e tokens base |
61
66
  | `/themes.css` | presets de tema |
62
67
 
68
+ Na linha 0.4.x, todos os nove caminhos acima fazem parte do contrato público,
69
+ incluindo `@aspprev/versi-ds/charts`, `@aspprev/versi-ds/countries`, os cinco
70
+ entrypoints de componentes e os dois entrypoints CSS. Eles são definidos no
71
+ campo `exports` do `package.json`; arquivos internos de `src` não fazem parte
72
+ do contrato.
73
+
63
74
  Evite deep imports. Use somente os entrypoints públicos documentados no `package.json`.
64
75
 
76
+ ### APIs desta versão
77
+
78
+ ```tsx
79
+ import { DatePicker, DomainStatusBadge, Table } from "@aspprev/versi-ds";
80
+ import { OtpCodeInput } from "@aspprev/versi-ds/forms";
81
+ import {
82
+ FileDropzone,
83
+ FileList,
84
+ FileUploadProgress,
85
+ FileViewer,
86
+ QRCode,
87
+ validateFiles,
88
+ } from "@aspprev/versi-ds/documents";
89
+ ```
90
+
91
+ - `OtpCodeInput` suporta `onComplete`, colagem de código, máscara, erro e controle por `value`/`values`.
92
+ - `QRCode` suporta `description`, `ariaLabel`, `loading`, `error`, `size` e nível de correção.
93
+ - Upload e `FileViewer` são controlados pelo consumidor; transporte, autenticação, persistência e download não fazem parte do pacote.
94
+ - `DatePicker` aceita `selectionMode="year"` e mantém `selectionMode="day"` como padrão.
95
+ - `DomainStatusBadge` aceita `statusMap` para vocabulário específico do produto.
96
+ - `Table` preserva os modos `fit`, `adaptive` e `scroll`; filtros e paginação respondem ao espaço do container.
97
+
98
+ 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.
99
+
65
100
  ## Organização do Design System
66
101
 
67
102
  - **Components**: controles de ação, formulários, feedback, navegação, dados, documentos, overlays e layout.
@@ -143,7 +178,7 @@ npm run check:package
143
178
  npm run prepack
144
179
  ```
145
180
 
146
- O script `prepack` valida tokens, governança, segurança, TypeScript, build, tamanho e conteúdo do pacote. O projeto não possui um script `lint` separado.
181
+ O script `prepack` valida tokens, governança, segurança, lint, TypeScript, build, tamanho e conteúdo do pacote.
147
182
 
148
183
  Para testar o exemplo integrado:
149
184
 
@@ -45,24 +45,61 @@ function BoletoBarCode({ linhaDigitavel }) {
45
45
  ] });
46
46
  }
47
47
 
48
- // src/components/file-upload/FileDropzone.tsx
49
- import classNames from "classnames";
50
- import { useId, useRef as useRef2, useState } from "react";
51
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
52
- var acceptsFile = (file, accept) => {
48
+ // src/components/file-upload/validation.ts
49
+ function acceptsFile(file, accept) {
53
50
  if (!(accept == null ? void 0 : accept.trim())) return true;
54
51
  return accept.split(",").map((item) => item.trim().toLowerCase()).some((rule) => {
55
52
  if (rule.endsWith("/*")) return file.type.toLowerCase().startsWith(rule.slice(0, -1));
56
53
  if (rule.startsWith(".")) return file.name.toLowerCase().endsWith(rule);
57
54
  return file.type.toLowerCase() === rule;
58
55
  });
59
- };
56
+ }
57
+ function rejectionMessage(reason) {
58
+ if (reason === "type") return "Tipo de arquivo n\xE3o permitido.";
59
+ if (reason === "size") return "O arquivo excede o tamanho m\xE1ximo permitido.";
60
+ return "Quantidade m\xE1xima de arquivos excedida.";
61
+ }
62
+ function normalizeMaxFiles(options) {
63
+ if (options.multiple === false) return 1;
64
+ if (options.maxFiles === void 0 || !Number.isFinite(options.maxFiles)) {
65
+ return Number.POSITIVE_INFINITY;
66
+ }
67
+ return Math.max(1, Math.floor(options.maxFiles));
68
+ }
69
+ function normalizeMaxSize(maxSize) {
70
+ if (maxSize === void 0 || !Number.isFinite(maxSize)) return void 0;
71
+ return Math.max(0, maxSize);
72
+ }
73
+ function validateFiles(files, options = {}) {
74
+ const selected = Array.from(files);
75
+ const maxFiles = normalizeMaxFiles(options);
76
+ const maxSize = normalizeMaxSize(options.maxSize);
77
+ const accepted = [];
78
+ const rejected = [];
79
+ selected.forEach((file, index) => {
80
+ const reason = !acceptsFile(file, options.accept) ? "type" : maxSize !== void 0 && file.size > maxSize ? "size" : index >= maxFiles ? "count" : void 0;
81
+ if (reason) {
82
+ rejected.push({ file, reason, message: rejectionMessage(reason) });
83
+ } else {
84
+ accepted.push(file);
85
+ }
86
+ });
87
+ return { accepted, rejected };
88
+ }
89
+
90
+ // src/components/file-upload/FileDropzone.tsx
91
+ import classNames from "classnames";
92
+ import { useId, useRef as useRef2, useState } from "react";
93
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
60
94
  function FileDropzone({
61
95
  accept,
62
96
  multiple = false,
63
97
  maxFiles = multiple ? Number.POSITIVE_INFINITY : 1,
64
98
  maxSize,
65
99
  disabled = false,
100
+ id,
101
+ name,
102
+ required = false,
66
103
  label = "Selecionar arquivos",
67
104
  hint = "Arraste e solte os arquivos aqui ou use o teclado para selecionar.",
68
105
  error,
@@ -70,24 +107,21 @@ function FileDropzone({
70
107
  onFilesAccepted,
71
108
  onFilesRejected
72
109
  }) {
73
- const inputId = useId();
110
+ const generatedInputId = useId();
111
+ const inputId = id != null ? id : generatedInputId;
74
112
  const messageId = `${inputId}-message`;
75
113
  const inputRef = useRef2(null);
76
114
  const [isDragging, setIsDragging] = useState(false);
115
+ const [rejectionMessage2, setRejectionMessage] = useState();
77
116
  const processFiles = (fileList) => {
78
117
  if (disabled) return;
79
- const selected = Array.from(fileList);
80
- const accepted = [];
81
- const rejected = [];
82
- selected.forEach((file, index) => {
83
- const reason = !acceptsFile(file, accept) ? "type" : maxSize !== void 0 && file.size > maxSize ? "size" : index >= maxFiles ? "count" : void 0;
84
- if (!reason) accepted.push(file);
85
- else {
86
- const message2 = reason === "type" ? "Tipo de arquivo n\xE3o permitido." : reason === "size" ? "O arquivo excede o tamanho m\xE1ximo permitido." : "Quantidade m\xE1xima de arquivos excedida.";
87
- rejected.push({ file, reason, message: message2 });
88
- }
118
+ const { accepted, rejected } = validateFiles(fileList, {
119
+ accept,
120
+ maxFiles,
121
+ maxSize,
122
+ multiple
89
123
  });
90
- if (!multiple && accepted.length > 1) accepted.splice(1);
124
+ setRejectionMessage(rejected.length ? rejected.map((item) => item.message).join(" ") : void 0);
91
125
  if (accepted.length) onFilesAccepted == null ? void 0 : onFilesAccepted(accepted);
92
126
  if (rejected.length) onFilesRejected == null ? void 0 : onFilesRejected(rejected);
93
127
  };
@@ -100,7 +134,8 @@ function FileDropzone({
100
134
  setIsDragging(false);
101
135
  processFiles(event.dataTransfer.files);
102
136
  };
103
- const message = error || hint;
137
+ const hasError = Boolean(error || rejectionMessage2);
138
+ const message = error || rejectionMessage2 || hint;
104
139
  return /* @__PURE__ */ jsxs2(
105
140
  "div",
106
141
  {
@@ -117,7 +152,7 @@ function FileDropzone({
117
152
  "flex min-h-32 w-full cursor-pointer flex-col items-center justify-center rounded-sm border-2 border-dashed p-6 text-center transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring",
118
153
  isDragging ? "border-action-primary bg-primary-1/10" : "border-border-default bg-surface-card hover:border-border-strong",
119
154
  disabled && "cursor-not-allowed opacity-60",
120
- Boolean(error) && "border-field-border-error",
155
+ hasError && "border-field-border-error",
121
156
  className
122
157
  ),
123
158
  children: [
@@ -129,16 +164,19 @@ function FileDropzone({
129
164
  ref: inputRef,
130
165
  id: inputId,
131
166
  type: "file",
167
+ name,
132
168
  accept,
133
169
  multiple,
134
170
  disabled,
171
+ required,
135
172
  onChange: handleInputChange,
136
173
  "aria-describedby": message ? messageId : void 0,
174
+ "aria-invalid": hasError ? true : void 0,
137
175
  className: "sr-only"
138
176
  }
139
177
  )
140
178
  ] }),
141
- message && /* @__PURE__ */ jsx2("span", { id: messageId, className: classNames("mt-1 text-sm", error ? "text-field-assistive-error" : "text-content-secondary"), children: message })
179
+ message && /* @__PURE__ */ jsx2("span", { id: messageId, role: hasError ? "alert" : void 0, className: classNames("mt-1 text-sm", hasError ? "text-field-assistive-error" : "text-content-secondary"), children: message })
142
180
  ]
143
181
  }
144
182
  );
@@ -198,18 +236,28 @@ var fileId = (item, index) => {
198
236
  var _a;
199
237
  return (_a = item.id) != null ? _a : `${item.file.name}-${item.file.size}-${item.file.lastModified}-${index}`;
200
238
  };
239
+ var statusDescription = (status) => {
240
+ if (status === "uploading") return "Enviando";
241
+ if (status === "success") return "Enviado";
242
+ if (status === "error") return "Erro no envio";
243
+ return "Aguardando envio";
244
+ };
201
245
  function FileList({ files, accessibleName = "Arquivos selecionados", onRemove, onRetry, className }) {
202
246
  return /* @__PURE__ */ jsx4("ul", { "aria-label": accessibleName, className: classNames3("w-full space-y-2", className), children: files.map((item, index) => {
203
247
  var _a;
204
248
  const status = (_a = item.status) != null ? _a : "pending";
205
249
  const progressStatus = status === "pending" ? "idle" : status;
206
- return /* @__PURE__ */ jsxs4("li", { className: "flex min-w-0 flex-wrap items-center gap-3 rounded-sm border border-border-default bg-surface-card p-3", children: [
250
+ return /* @__PURE__ */ jsxs4("li", { "aria-busy": status === "uploading" || void 0, className: "flex min-w-0 flex-wrap items-center gap-3 rounded-sm border border-border-default bg-surface-card p-3", children: [
207
251
  /* @__PURE__ */ jsxs4("div", { className: "min-w-0 flex-1", children: [
208
252
  /* @__PURE__ */ jsx4("p", { className: "truncate font-semibold text-content-primary", title: item.file.name, children: item.file.name }),
209
253
  /* @__PURE__ */ jsxs4("p", { className: "text-xs text-content-secondary", children: [
210
254
  Math.ceil(item.file.size / 1024),
211
255
  " KB"
212
256
  ] }),
257
+ /* @__PURE__ */ jsxs4("span", { className: "sr-only", children: [
258
+ "Status: ",
259
+ statusDescription(status)
260
+ ] }),
213
261
  (status === "uploading" || status === "success" || status === "error") && /* @__PURE__ */ jsx4(FileUploadProgress_default, { value: item.progress, status: progressStatus, label: `Progresso de ${item.file.name}` }),
214
262
  item.error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "mt-1 text-sm text-field-assistive-error", children: item.error })
215
263
  ] }),
@@ -224,65 +272,153 @@ var FileList_default = FileList;
224
272
 
225
273
  // src/components/file-upload/FileViewer.tsx
226
274
  import classNames4 from "classnames";
227
- import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
275
+ import { useEffect as useEffect2, useRef as useRef3, useState as useState2 } from "react";
228
276
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
229
277
  var extensionType = (fileName) => {
230
278
  var _a;
231
279
  const extension = (_a = fileName == null ? void 0 : fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase();
232
280
  if (extension === "pdf") return "application/pdf";
233
- if (["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension != null ? extension : "")) return `image/${extension === "jpg" ? "jpeg" : extension}`;
281
+ if (["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension != null ? extension : "")) {
282
+ return `image/${extension === "jpg" ? "jpeg" : extension}`;
283
+ }
234
284
  if (["txt", "csv", "json", "xml", "md"].includes(extension != null ? extension : "")) return "text/plain";
235
285
  return "application/octet-stream";
236
286
  };
237
- function FileViewer({ source, fileName, contentType, loading = false, error, onDownload, fallback, title = fileName != null ? fileName : "Visualiza\xE7\xE3o do arquivo", className }) {
238
- var _a, _b;
287
+ var normalizeContentType = (contentType) => contentType.split(";", 1)[0].trim().toLowerCase();
288
+ var toError = (cause) => cause instanceof Error ? cause : new Error("N\xE3o foi poss\xEDvel ler o arquivo.");
289
+ function FileViewer({
290
+ source,
291
+ fileName,
292
+ contentType,
293
+ loading = false,
294
+ error,
295
+ onLoad,
296
+ onError,
297
+ onDownload,
298
+ fallback,
299
+ title = fileName != null ? fileName : "Visualiza\xE7\xE3o do arquivo",
300
+ className
301
+ }) {
239
302
  const [objectUrl, setObjectUrl] = useState2();
240
303
  const [textContent, setTextContent] = useState2();
304
+ const [readError, setReadError] = useState2(null);
305
+ const onLoadRef = useRef3(onLoad);
306
+ const onErrorRef = useRef3(onError);
241
307
  const resolved = typeof source === "object" && source !== null && !(source instanceof Blob) ? source : void 0;
242
308
  const blob = source instanceof Blob ? source : resolved == null ? void 0 : resolved.blob;
243
309
  const url = typeof source === "string" ? source : resolved == null ? void 0 : resolved.url;
244
310
  const resolvedName = fileName != null ? fileName : resolved == null ? void 0 : resolved.fileName;
245
- const resolvedType = (_b = (_a = contentType != null ? contentType : resolved == null ? void 0 : resolved.contentType) != null ? _a : blob == null ? void 0 : blob.type) != null ? _b : extensionType(resolvedName);
311
+ const rawType = (contentType == null ? void 0 : contentType.trim()) || (resolved == null ? void 0 : resolved.contentType) || (blob == null ? void 0 : blob.type) || extensionType(resolvedName);
312
+ const resolvedType = normalizeContentType(rawType);
313
+ const isText = resolvedType.startsWith("text/") || resolvedType === "application/json";
314
+ const displayError = error != null ? error : readError == null ? void 0 : readError.message;
246
315
  useEffect2(() => {
316
+ onLoadRef.current = onLoad;
317
+ }, [onLoad]);
318
+ useEffect2(() => {
319
+ onErrorRef.current = onError;
320
+ }, [onError]);
321
+ useEffect2(() => {
322
+ var _a;
323
+ let active = true;
324
+ setReadError(null);
325
+ setTextContent(void 0);
247
326
  if (!blob) {
248
327
  setObjectUrl(void 0);
249
- setTextContent(void 0);
250
- return;
328
+ return () => {
329
+ active = false;
330
+ };
251
331
  }
252
- const nextUrl = URL.createObjectURL(blob);
253
- setObjectUrl(nextUrl);
254
- let active = true;
255
- if (resolvedType.startsWith("text/") || resolvedType === "application/json") {
332
+ let nextUrl;
333
+ try {
334
+ nextUrl = URL.createObjectURL(blob);
335
+ setObjectUrl(nextUrl);
336
+ } catch (cause) {
337
+ const nextError = toError(cause);
338
+ setReadError(nextError);
339
+ (_a = onErrorRef.current) == null ? void 0 : _a.call(onErrorRef, nextError);
340
+ return () => {
341
+ active = false;
342
+ };
343
+ }
344
+ if (isText) {
256
345
  blob.text().then((text) => {
257
- if (active) setTextContent(text);
346
+ var _a2;
347
+ if (!active) return;
348
+ setTextContent(text);
349
+ (_a2 = onLoadRef.current) == null ? void 0 : _a2.call(onLoadRef);
350
+ }).catch((cause) => {
351
+ var _a2;
352
+ if (!active) return;
353
+ const nextError = toError(cause);
354
+ setReadError(nextError);
355
+ (_a2 = onErrorRef.current) == null ? void 0 : _a2.call(onErrorRef, nextError);
258
356
  });
259
- } else {
260
- setTextContent(void 0);
261
357
  }
262
358
  return () => {
263
359
  active = false;
264
360
  URL.revokeObjectURL(nextUrl);
265
361
  };
266
- }, [blob, resolvedType]);
362
+ }, [blob, isText]);
363
+ const handleMediaError = () => {
364
+ var _a;
365
+ const nextError = new Error("N\xE3o foi poss\xEDvel carregar a visualiza\xE7\xE3o do arquivo.");
366
+ setReadError(nextError);
367
+ (_a = onErrorRef.current) == null ? void 0 : _a.call(onErrorRef, nextError);
368
+ };
369
+ const handleLoad = () => {
370
+ var _a;
371
+ return (_a = onLoadRef.current) == null ? void 0 : _a.call(onLoadRef);
372
+ };
373
+ if (loading) {
374
+ return /* @__PURE__ */ jsx5(
375
+ "div",
376
+ {
377
+ className: classNames4("flex min-h-32 items-center justify-center rounded-sm border border-border-default bg-surface-card p-6 text-content-secondary", className),
378
+ role: "status",
379
+ "aria-busy": "true",
380
+ "aria-live": "polite",
381
+ children: "Carregando arquivo\u2026"
382
+ }
383
+ );
384
+ }
385
+ if (displayError) {
386
+ return /* @__PURE__ */ jsx5("div", { className: classNames4("rounded-sm border border-field-border-error bg-surface-card p-4 text-field-assistive-error", className), role: "alert", children: displayError });
387
+ }
267
388
  const displayUrl = objectUrl != null ? objectUrl : url;
268
- const downloadUrl = useMemo(() => displayUrl, [displayUrl]);
269
- if (loading) return /* @__PURE__ */ jsx5("div", { className: classNames4("flex min-h-32 items-center justify-center rounded-sm border border-border-default bg-surface-card p-6 text-content-secondary", className), role: "status", "aria-live": "polite", children: "Carregando arquivo\u2026" });
270
- if (error) return /* @__PURE__ */ jsx5("div", { className: classNames4("rounded-sm border border-field-border-error bg-surface-card p-4 text-field-assistive-error", className), role: "alert", children: error });
271
- if (!displayUrl && !textContent) return /* @__PURE__ */ jsx5("div", { className: classNames4("rounded-sm border border-border-default bg-surface-card p-4 text-content-secondary", className), children: fallback != null ? fallback : "Arquivo indispon\xEDvel." });
272
- const download = onDownload ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: onDownload, className: "min-h-11 rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-focus-ring", children: "Baixar arquivo" }) : downloadUrl ? /* @__PURE__ */ jsx5("a", { href: downloadUrl, download: resolvedName, className: "inline-flex min-h-11 items-center rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-focus-ring", children: "Baixar arquivo" }) : null;
273
- return /* @__PURE__ */ jsxs5("div", { className: classNames4("flex min-w-0 flex-col gap-3 rounded-sm border border-border-default bg-surface-card p-3", className), children: [
274
- resolvedType.startsWith("image/") && displayUrl && /* @__PURE__ */ jsx5("img", { src: displayUrl, alt: title, className: "max-h-[70vh] max-w-full object-contain" }),
275
- resolvedType === "application/pdf" && displayUrl && /* @__PURE__ */ jsx5("iframe", { src: displayUrl, title, className: "min-h-[32rem] w-full border-0" }),
276
- (resolvedType.startsWith("text/") || resolvedType === "application/json") && (textContent !== void 0 ? /* @__PURE__ */ jsx5("pre", { className: "max-h-[70vh] overflow-auto whitespace-pre-wrap break-words text-sm text-content-primary", children: textContent }) : displayUrl && /* @__PURE__ */ jsx5("iframe", { src: displayUrl, title, sandbox: "", className: "min-h-64 w-full border-0" })),
277
- !resolvedType.startsWith("image/") && resolvedType !== "application/pdf" && !resolvedType.startsWith("text/") && resolvedType !== "application/json" && (fallback != null ? fallback : /* @__PURE__ */ jsx5("p", { className: "text-content-secondary", children: "Este tipo de arquivo n\xE3o possui visualiza\xE7\xE3o dispon\xEDvel." })),
278
- download && /* @__PURE__ */ jsx5("div", { className: "flex justify-end", children: download })
279
- ] });
389
+ if (!displayUrl && !textContent) {
390
+ return /* @__PURE__ */ jsx5(
391
+ "div",
392
+ {
393
+ className: classNames4("rounded-sm border border-border-default bg-surface-card p-4 text-content-secondary", className),
394
+ role: "region",
395
+ "aria-label": title,
396
+ children: fallback != null ? fallback : "Arquivo indispon\xEDvel."
397
+ }
398
+ );
399
+ }
400
+ const download = onDownload ? /* @__PURE__ */ jsx5("button", { type: "button", onClick: onDownload, className: "min-h-11 rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring", children: "Baixar arquivo" }) : displayUrl ? /* @__PURE__ */ jsx5("a", { href: displayUrl, download: resolvedName, className: "inline-flex min-h-11 items-center rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring", children: "Baixar arquivo" }) : null;
401
+ return /* @__PURE__ */ jsxs5(
402
+ "div",
403
+ {
404
+ className: classNames4("flex min-w-0 flex-col gap-3 rounded-sm border border-border-default bg-surface-card p-3", className),
405
+ role: "region",
406
+ "aria-label": title,
407
+ children: [
408
+ resolvedType.startsWith("image/") && displayUrl && /* @__PURE__ */ jsx5("img", { src: displayUrl, alt: title, onLoad: handleLoad, onError: handleMediaError, className: "max-h-[70vh] max-w-full object-contain" }),
409
+ resolvedType === "application/pdf" && displayUrl && /* @__PURE__ */ jsx5("iframe", { src: displayUrl, title, onLoad: handleLoad, onError: handleMediaError, sandbox: "", className: "min-h-[32rem] w-full border-0" }),
410
+ isText && (textContent !== void 0 ? /* @__PURE__ */ jsx5("pre", { className: "max-h-[70vh] overflow-auto whitespace-pre-wrap break-words text-sm text-content-primary", children: textContent }) : displayUrl && /* @__PURE__ */ jsx5("iframe", { src: displayUrl, title, onLoad: handleLoad, onError: handleMediaError, sandbox: "", className: "min-h-64 w-full border-0" })),
411
+ !resolvedType.startsWith("image/") && resolvedType !== "application/pdf" && !isText && (fallback != null ? fallback : /* @__PURE__ */ jsx5("p", { className: "text-content-secondary", children: "Este tipo de arquivo n\xE3o possui visualiza\xE7\xE3o dispon\xEDvel." })),
412
+ download && /* @__PURE__ */ jsx5("div", { className: "flex justify-end", children: download })
413
+ ]
414
+ }
415
+ );
280
416
  }
281
417
  var FileViewer_default = FileViewer;
282
418
 
283
419
  // src/components/qr-code/QRCode.tsx
284
420
  import QRCodeGenerator from "qrcode";
285
- import { useEffect as useEffect3, useState as useState3 } from "react";
421
+ import { useEffect as useEffect3, useId as useId2, useMemo, useRef as useRef4, useState as useState3 } from "react";
286
422
  import classNames5 from "classnames";
287
423
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
288
424
  function getRelativeLuminance(color) {
@@ -313,6 +449,9 @@ function QRCode(_a) {
313
449
  bgColor = "#FFFFFF",
314
450
  ariaLabel = "C\xF3digo QR",
315
451
  description,
452
+ loading = false,
453
+ error,
454
+ onError,
316
455
  className
317
456
  } = _b, rest = __objRest(_b, [
318
457
  "value",
@@ -323,43 +462,74 @@ function QRCode(_a) {
323
462
  "bgColor",
324
463
  "ariaLabel",
325
464
  "description",
465
+ "loading",
466
+ "error",
467
+ "onError",
326
468
  "className"
327
469
  ]);
328
470
  var _a2;
329
471
  const [dataUrl, setDataUrl] = useState3(null);
330
- const descriptionId = description ? `${(_a2 = rest.id) != null ? _a2 : "qr-code"}-description` : void 0;
331
- const colors = resolveAccessibleColors(fgColor, bgColor);
472
+ const [generationError, setGenerationError] = useState3(null);
473
+ const onErrorRef = useRef4(onError);
474
+ const generatedId = useId2();
475
+ const resolvedSize = Math.max(1, Number.isFinite(size) ? Math.floor(size) : 192);
476
+ const descriptionId = description ? `${(_a2 = rest.id) != null ? _a2 : generatedId}-description` : void 0;
477
+ const colors = useMemo(
478
+ () => resolveAccessibleColors(fgColor, bgColor),
479
+ [bgColor, fgColor]
480
+ );
481
+ const describedBy = [rest["aria-describedby"], descriptionId].filter(Boolean).join(" ") || void 0;
482
+ const displayError = error != null ? error : generationError == null ? void 0 : generationError.message;
483
+ const isLoading = loading || !dataUrl && !displayError;
484
+ useEffect3(() => {
485
+ onErrorRef.current = onError;
486
+ }, [onError]);
332
487
  useEffect3(() => {
333
488
  let active = true;
489
+ if (error) {
490
+ setDataUrl(null);
491
+ setGenerationError(null);
492
+ return () => {
493
+ active = false;
494
+ };
495
+ }
334
496
  setDataUrl(null);
497
+ setGenerationError(null);
335
498
  QRCodeGenerator.toDataURL(value, {
336
- width: size,
499
+ width: resolvedSize,
337
500
  margin: includeMargin ? 4 : 0,
338
501
  errorCorrectionLevel: level,
339
502
  color: colors
340
503
  }).then((url) => {
341
504
  if (active) setDataUrl(url);
342
- }).catch(() => {
343
- if (active) setDataUrl(null);
505
+ }).catch((cause) => {
506
+ var _a3;
507
+ if (!active) return;
508
+ const nextError = cause instanceof Error ? cause : new Error("N\xE3o foi poss\xEDvel gerar o c\xF3digo QR.");
509
+ setDataUrl(null);
510
+ setGenerationError(nextError);
511
+ (_a3 = onErrorRef.current) == null ? void 0 : _a3.call(onErrorRef, nextError);
344
512
  });
345
513
  return () => {
346
514
  active = false;
347
515
  };
348
- }, [bgColor, fgColor, includeMargin, level, size, value]);
516
+ }, [colors, error, includeMargin, level, resolvedSize, value]);
349
517
  return /* @__PURE__ */ jsxs6(
350
518
  "div",
351
519
  __spreadProps(__spreadValues({}, rest), {
352
520
  role: "img",
353
521
  "aria-label": ariaLabel,
354
- "aria-describedby": descriptionId,
522
+ "aria-describedby": describedBy,
523
+ "aria-busy": isLoading || void 0,
524
+ "aria-invalid": displayError ? true : void 0,
355
525
  className: classNames5("inline-flex max-w-full flex-col items-center gap-2", className),
356
526
  children: [
357
- dataUrl ? /* @__PURE__ */ jsx6("img", { src: dataUrl, alt: "", width: size, height: size, className: "h-auto max-w-full" }) : /* @__PURE__ */ jsx6(
527
+ displayError ? /* @__PURE__ */ jsx6("span", { role: "alert", className: "rounded-sm border border-field-border-error p-3 text-sm text-field-assistive-error", children: displayError }) : dataUrl ? /* @__PURE__ */ jsx6("img", { src: dataUrl, alt: "", width: resolvedSize, height: resolvedSize, className: "h-auto max-w-full" }) : /* @__PURE__ */ jsx6(
358
528
  "span",
359
529
  {
360
530
  "aria-hidden": "true",
361
531
  className: "inline-block animate-pulse rounded-sm bg-surface-muted",
362
- style: { width: size, height: size, maxWidth: "100%" }
532
+ style: { width: resolvedSize, height: resolvedSize, maxWidth: "100%" }
363
533
  }
364
534
  ),
365
535
  description && /* @__PURE__ */ jsx6("span", { id: descriptionId, className: "sr-only", children: description })
@@ -371,10 +541,11 @@ var QRCode_default = QRCode;
371
541
 
372
542
  export {
373
543
  BoletoBarCode,
544
+ validateFiles,
374
545
  FileDropzone_default,
375
546
  FileUploadProgress_default,
376
547
  FileList_default,
377
548
  FileViewer_default,
378
549
  QRCode_default
379
550
  };
380
- //# sourceMappingURL=chunk-H4BBKKRZ.js.map
551
+ //# sourceMappingURL=chunk-7JI5637G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/barcode/barcode.tsx","../src/components/file-upload/validation.ts","../src/components/file-upload/FileDropzone.tsx","../src/components/file-upload/FileUploadProgress.tsx","../src/components/file-upload/FileList.tsx","../src/components/file-upload/FileViewer.tsx","../src/components/qr-code/QRCode.tsx"],"sourcesContent":["\"use client\";\n\nimport JsBarcode from \"jsbarcode\";\nimport { useEffect, useRef } from \"react\";\n\nconst linhaDigitavelParaCodigoBarras = (linha: string): string => {\n const d = linha.replace(/\\D/g, \"\");\n\n const banco = d.substring(0, 3);\n const moeda = d.substring(3, 4);\n const campo1 = d.substring(4, 9);\n const campo2 = d.substring(10, 20);\n const campo3 = d.substring(21, 31);\n const digitoGeral = d.substring(32, 33);\n const vencimento = d.substring(33, 37);\n const valor = d.substring(37, 47);\n\n return (\n banco + moeda + digitoGeral + vencimento + valor + campo1 + campo2 + campo3\n );\n};\n\nexport interface BoletoBarCodeProps {\n linhaDigitavel: string;\n}\n\nexport function BoletoBarCode({ linhaDigitavel }: BoletoBarCodeProps) {\n const svgRef = useRef<SVGSVGElement>(null);\n\n useEffect(() => {\n if (!svgRef.current) return;\n\n try {\n const codigoBarras = linhaDigitavelParaCodigoBarras(linhaDigitavel);\n\n JsBarcode(svgRef.current, codigoBarras, {\n format: \"ITF\",\n lineColor: \"#000000\",\n background: \"#FFFFFF\",\n displayValue: false,\n width: 2,\n height: 80,\n margin: 0,\n });\n } catch (error) {\n console.error(\"Erro ao gerar código de barras:\", error);\n }\n }, [linhaDigitavel]);\n\n return (\n <div className=\"w-full space-y-3 bg-surface-card\">\n <svg ref={svgRef} className=\"w-full\" />\n <p className=\"text-center font-mono text-sm tracking-widest text-content-primary\">\n {linhaDigitavel}\n </p>\n </div>\n );\n}\n\n","export type FileValidationReason = \"type\" | \"size\" | \"count\";\n\nexport interface FileRejection {\n file: File;\n reason: FileValidationReason;\n message: string;\n}\n\nexport interface FileValidationOptions {\n accept?: string;\n multiple?: boolean;\n maxFiles?: number;\n maxSize?: number;\n}\n\nexport interface FileValidationResult {\n accepted: File[];\n rejected: FileRejection[];\n}\n\nfunction acceptsFile(file: File, accept?: string) {\n if (!accept?.trim()) return true;\n\n return accept.split(\",\").map((item) => item.trim().toLowerCase()).some((rule) => {\n if (rule.endsWith(\"/*\")) return file.type.toLowerCase().startsWith(rule.slice(0, -1));\n if (rule.startsWith(\".\")) return file.name.toLowerCase().endsWith(rule);\n return file.type.toLowerCase() === rule;\n });\n}\n\nfunction rejectionMessage(reason: FileValidationReason) {\n if (reason === \"type\") return \"Tipo de arquivo não permitido.\";\n if (reason === \"size\") return \"O arquivo excede o tamanho máximo permitido.\";\n return \"Quantidade máxima de arquivos excedida.\";\n}\n\nfunction normalizeMaxFiles(options: FileValidationOptions) {\n if (options.multiple === false) return 1;\n if (options.maxFiles === undefined || !Number.isFinite(options.maxFiles)) {\n return Number.POSITIVE_INFINITY;\n }\n return Math.max(1, Math.floor(options.maxFiles));\n}\n\nfunction normalizeMaxSize(maxSize?: number) {\n if (maxSize === undefined || !Number.isFinite(maxSize)) return undefined;\n return Math.max(0, maxSize);\n}\n\nexport function validateFiles(\n files: readonly File[] | FileList,\n options: FileValidationOptions = {},\n): FileValidationResult {\n const selected = Array.from(files);\n const maxFiles = normalizeMaxFiles(options);\n const maxSize = normalizeMaxSize(options.maxSize);\n const accepted: File[] = [];\n const rejected: FileRejection[] = [];\n\n selected.forEach((file, index) => {\n const reason: FileValidationReason | undefined = !acceptsFile(file, options.accept)\n ? \"type\"\n : maxSize !== undefined && file.size > maxSize\n ? \"size\"\n : index >= maxFiles\n ? \"count\"\n : undefined;\n\n if (reason) {\n rejected.push({ file, reason, message: rejectionMessage(reason) });\n } else {\n accepted.push(file);\n }\n });\n\n return { accepted, rejected };\n}\n","\"use client\";\n\nimport classNames from \"classnames\";\nimport { useId, useRef, useState, type ChangeEvent, type DragEvent, type ReactNode } from \"react\";\nimport { validateFiles, type FileRejection } from \"./validation\";\n\nexport type { FileRejection } from \"./validation\";\n\nexport interface FileDropzoneProps {\n accept?: string;\n multiple?: boolean;\n maxFiles?: number;\n maxSize?: number;\n disabled?: boolean;\n id?: string;\n name?: string;\n required?: boolean;\n label?: ReactNode;\n hint?: ReactNode;\n error?: ReactNode;\n className?: string;\n onFilesAccepted?: (files: File[]) => void;\n onFilesRejected?: (rejections: FileRejection[]) => void;\n}\n\nexport function FileDropzone({\n accept,\n multiple = false,\n maxFiles = multiple ? Number.POSITIVE_INFINITY : 1,\n maxSize,\n disabled = false,\n id,\n name,\n required = false,\n label = \"Selecionar arquivos\",\n hint = \"Arraste e solte os arquivos aqui ou use o teclado para selecionar.\",\n error,\n className,\n onFilesAccepted,\n onFilesRejected,\n}: FileDropzoneProps) {\n const generatedInputId = useId();\n const inputId = id ?? generatedInputId;\n const messageId = `${inputId}-message`;\n const inputRef = useRef<HTMLInputElement>(null);\n const [isDragging, setIsDragging] = useState(false);\n const [rejectionMessage, setRejectionMessage] = useState<string>();\n\n const processFiles = (fileList: FileList | File[]) => {\n if (disabled) return;\n const { accepted, rejected } = validateFiles(fileList, {\n accept,\n maxFiles,\n maxSize,\n multiple,\n });\n setRejectionMessage(rejected.length ? rejected.map((item) => item.message).join(\" \") : undefined);\n if (accepted.length) onFilesAccepted?.(accepted);\n if (rejected.length) onFilesRejected?.(rejected);\n };\n\n const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) processFiles(event.target.files);\n event.target.value = \"\";\n };\n const handleDrop = (event: DragEvent<HTMLDivElement>) => {\n event.preventDefault();\n setIsDragging(false);\n processFiles(event.dataTransfer.files);\n };\n const hasError = Boolean(error || rejectionMessage);\n const message = error || rejectionMessage || hint;\n\n return (\n <div\n onDragEnter={(event) => { event.preventDefault(); if (!disabled) setIsDragging(true); }}\n onDragOver={(event) => event.preventDefault()}\n onDragLeave={(event) => { if (event.currentTarget === event.target) setIsDragging(false); }}\n onDrop={handleDrop}\n className={classNames(\n \"flex min-h-32 w-full cursor-pointer flex-col items-center justify-center rounded-sm border-2 border-dashed p-6 text-center transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring\",\n isDragging ? \"border-action-primary bg-primary-1/10\" : \"border-border-default bg-surface-card hover:border-border-strong\",\n disabled && \"cursor-not-allowed opacity-60\",\n hasError && \"border-field-border-error\",\n className,\n )}\n >\n <label htmlFor={inputId} className=\"flex cursor-pointer flex-col items-center focus-within:outline focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-focus-ring\">\n <span className=\"font-semibold text-content-primary\">{label}</span>\n <input\n ref={inputRef}\n id={inputId}\n type=\"file\"\n name={name}\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n required={required}\n onChange={handleInputChange}\n aria-describedby={message ? messageId : undefined}\n aria-invalid={hasError ? true : undefined}\n className=\"sr-only\"\n />\n </label>\n {message && <span id={messageId} role={hasError ? \"alert\" : undefined} className={classNames(\"mt-1 text-sm\", hasError ? \"text-field-assistive-error\" : \"text-content-secondary\")}>{message}</span>}\n </div>\n );\n}\n\nexport default FileDropzone;\n","\"use client\";\n\nimport classNames from \"classnames\";\n\nexport type FileUploadProgressStatus = \"idle\" | \"uploading\" | \"success\" | \"error\";\n\nexport interface FileUploadProgressProps {\n value?: number | null;\n label?: string;\n status?: FileUploadProgressStatus;\n showValue?: boolean;\n className?: string;\n}\n\nexport function FileUploadProgress({\n value,\n label = \"Progresso do upload\",\n status = \"uploading\",\n showValue = true,\n className,\n}: FileUploadProgressProps) {\n const resolvedValue = typeof value === \"number\"\n ? Math.min(100, Math.max(0, value))\n : undefined;\n const statusText = status === \"success\"\n ? \"Concluído\"\n : status === \"error\"\n ? \"Erro\"\n : resolvedValue === undefined\n ? \"Em andamento\"\n : `${Math.round(resolvedValue)}%`;\n\n return (\n <div className={classNames(\"w-full\", className)}>\n <div className=\"mb-1 flex items-center justify-between gap-2 text-xs text-content-secondary\">\n <span>{label}</span>\n {showValue && <span aria-hidden=\"true\">{statusText}</span>}\n </div>\n <div\n role=\"progressbar\"\n aria-label={label}\n aria-valuemin={resolvedValue === undefined ? undefined : 0}\n aria-valuemax={resolvedValue === undefined ? undefined : 100}\n aria-valuenow={resolvedValue}\n aria-valuetext={statusText}\n className=\"h-2 w-full overflow-hidden rounded-full bg-surface-muted\"\n >\n <div\n className={classNames(\n \"h-full rounded-full transition-[width] duration-200\",\n status === \"error\" ? \"bg-feedback-danger-strong\" : \"bg-action-primary\",\n resolvedValue === undefined ? \"w-1/2 animate-pulse\" : undefined,\n )}\n style={resolvedValue === undefined ? undefined : { width: `${resolvedValue}%` }}\n />\n </div>\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\">{statusText}</span>\n </div>\n );\n}\n\nexport default FileUploadProgress;\n","\"use client\";\n\nimport classNames from \"classnames\";\nimport { MdClose, MdRefresh } from \"react-icons/md\";\nimport FileUploadProgress, { type FileUploadProgressStatus } from \"./FileUploadProgress\";\n\nexport type FileUploadItemStatus = FileUploadProgressStatus | \"pending\";\n\nexport interface FileUploadItem {\n id?: string;\n file: File;\n progress?: number | null;\n status?: FileUploadItemStatus;\n error?: string;\n}\n\nexport interface FileListProps {\n files: FileUploadItem[];\n accessibleName?: string;\n onRemove?: (item: FileUploadItem, index: number) => void;\n onRetry?: (item: FileUploadItem, index: number) => void;\n className?: string;\n}\n\nconst fileId = (item: FileUploadItem, index: number) => item.id ?? `${item.file.name}-${item.file.size}-${item.file.lastModified}-${index}`;\n\nconst statusDescription = (status: FileUploadItemStatus) => {\n if (status === \"uploading\") return \"Enviando\";\n if (status === \"success\") return \"Enviado\";\n if (status === \"error\") return \"Erro no envio\";\n return \"Aguardando envio\";\n};\n\nexport function FileList({ files, accessibleName = \"Arquivos selecionados\", onRemove, onRetry, className }: FileListProps) {\n return (\n <ul aria-label={accessibleName} className={classNames(\"w-full space-y-2\", className)}>\n {files.map((item, index) => {\n const status = item.status ?? \"pending\";\n const progressStatus: FileUploadProgressStatus = status === \"pending\" ? \"idle\" : status;\n return (\n <li key={fileId(item, index)} aria-busy={status === \"uploading\" || undefined} className=\"flex min-w-0 flex-wrap items-center gap-3 rounded-sm border border-border-default bg-surface-card p-3\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate font-semibold text-content-primary\" title={item.file.name}>{item.file.name}</p>\n <p className=\"text-xs text-content-secondary\">{Math.ceil(item.file.size / 1024)} KB</p>\n <span className=\"sr-only\">Status: {statusDescription(status)}</span>\n {(status === \"uploading\" || status === \"success\" || status === \"error\") && (\n <FileUploadProgress value={item.progress} status={progressStatus} label={`Progresso de ${item.file.name}`} />\n )}\n {item.error && <p role=\"alert\" className=\"mt-1 text-sm text-field-assistive-error\">{item.error}</p>}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {status === \"error\" && onRetry && <button type=\"button\" onClick={() => onRetry(item, index)} aria-label={`Tentar novamente ${item.file.name}`} className=\"flex h-11 w-11 items-center justify-center rounded-sm text-content-secondary hover:bg-surface-muted focus-visible:outline focus-visible:outline-2 focus-visible:outline-focus-ring\"><MdRefresh aria-hidden=\"true\" className=\"h-5 w-5\" /></button>}\n {onRemove && <button type=\"button\" onClick={() => onRemove(item, index)} aria-label={`Remover ${item.file.name}`} className=\"flex h-11 w-11 items-center justify-center rounded-sm text-content-secondary hover:bg-surface-muted focus-visible:outline focus-visible:outline-2 focus-visible:outline-focus-ring\"><MdClose aria-hidden=\"true\" className=\"h-5 w-5\" /></button>}\n </div>\n </li>\n );\n })}\n </ul>\n );\n}\n\nexport default FileList;\n","\"use client\";\n\nimport classNames from \"classnames\";\nimport { useEffect, useRef, useState, type ReactNode } from \"react\";\n\nexport type FileViewerSource = string | Blob | {\n url?: string;\n blob?: Blob;\n contentType?: string;\n fileName?: string;\n};\n\nexport interface FileViewerProps {\n source?: FileViewerSource;\n fileName?: string;\n contentType?: string;\n loading?: boolean;\n error?: ReactNode;\n onLoad?: () => void;\n onError?: (error: Error) => void;\n onDownload?: () => void;\n fallback?: ReactNode;\n title?: string;\n className?: string;\n}\n\nconst extensionType = (fileName?: string) => {\n const extension = fileName?.split(\".\").pop()?.toLowerCase();\n if (extension === \"pdf\") return \"application/pdf\";\n if ([\"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"svg\"].includes(extension ?? \"\")) {\n return `image/${extension === \"jpg\" ? \"jpeg\" : extension}`;\n }\n if ([\"txt\", \"csv\", \"json\", \"xml\", \"md\"].includes(extension ?? \"\")) return \"text/plain\";\n return \"application/octet-stream\";\n};\n\nconst normalizeContentType = (contentType: string) => contentType.split(\";\", 1)[0].trim().toLowerCase();\n\nconst toError = (cause: unknown) => (\n cause instanceof Error ? cause : new Error(\"Não foi possível ler o arquivo.\")\n);\n\nexport function FileViewer({\n source,\n fileName,\n contentType,\n loading = false,\n error,\n onLoad,\n onError,\n onDownload,\n fallback,\n title = fileName ?? \"Visualização do arquivo\",\n className,\n}: FileViewerProps) {\n const [objectUrl, setObjectUrl] = useState<string>();\n const [textContent, setTextContent] = useState<string>();\n const [readError, setReadError] = useState<Error | null>(null);\n const onLoadRef = useRef(onLoad);\n const onErrorRef = useRef(onError);\n const resolved = typeof source === \"object\" && source !== null && !(source instanceof Blob) ? source : undefined;\n const blob = source instanceof Blob ? source : resolved?.blob;\n const url = typeof source === \"string\" ? source : resolved?.url;\n const resolvedName = fileName ?? resolved?.fileName;\n const rawType = contentType?.trim() || resolved?.contentType || blob?.type || extensionType(resolvedName);\n const resolvedType = normalizeContentType(rawType);\n const isText = resolvedType.startsWith(\"text/\") || resolvedType === \"application/json\";\n const displayError = error ?? readError?.message;\n\n useEffect(() => {\n onLoadRef.current = onLoad;\n }, [onLoad]);\n\n useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n useEffect(() => {\n let active = true;\n setReadError(null);\n setTextContent(undefined);\n\n if (!blob) {\n setObjectUrl(undefined);\n return () => { active = false; };\n }\n\n let nextUrl: string;\n try {\n nextUrl = URL.createObjectURL(blob);\n setObjectUrl(nextUrl);\n } catch (cause) {\n const nextError = toError(cause);\n setReadError(nextError);\n onErrorRef.current?.(nextError);\n return () => { active = false; };\n }\n\n if (isText) {\n blob.text()\n .then((text) => {\n if (!active) return;\n setTextContent(text);\n onLoadRef.current?.();\n })\n .catch((cause: unknown) => {\n if (!active) return;\n const nextError = toError(cause);\n setReadError(nextError);\n onErrorRef.current?.(nextError);\n });\n }\n\n return () => {\n active = false;\n URL.revokeObjectURL(nextUrl);\n };\n }, [blob, isText]);\n\n const handleMediaError = () => {\n const nextError = new Error(\"Não foi possível carregar a visualização do arquivo.\");\n setReadError(nextError);\n onErrorRef.current?.(nextError);\n };\n const handleLoad = () => onLoadRef.current?.();\n\n if (loading) {\n return (\n <div\n className={classNames(\"flex min-h-32 items-center justify-center rounded-sm border border-border-default bg-surface-card p-6 text-content-secondary\", className)}\n role=\"status\"\n aria-busy=\"true\"\n aria-live=\"polite\"\n >\n Carregando arquivo…\n </div>\n );\n }\n\n if (displayError) {\n return (\n <div className={classNames(\"rounded-sm border border-field-border-error bg-surface-card p-4 text-field-assistive-error\", className)} role=\"alert\">\n {displayError}\n </div>\n );\n }\n\n const displayUrl = objectUrl ?? url;\n if (!displayUrl && !textContent) {\n return (\n <div\n className={classNames(\"rounded-sm border border-border-default bg-surface-card p-4 text-content-secondary\", className)}\n role=\"region\"\n aria-label={title}\n >\n {fallback ?? \"Arquivo indisponível.\"}\n </div>\n );\n }\n\n const download = onDownload\n ? <button type=\"button\" onClick={onDownload} className=\"min-h-11 rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring\">Baixar arquivo</button>\n : displayUrl\n ? <a href={displayUrl} download={resolvedName} className=\"inline-flex min-h-11 items-center rounded-sm border border-border-default px-3 text-sm font-semibold text-content-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring\">Baixar arquivo</a>\n : null;\n\n return (\n <div\n className={classNames(\"flex min-w-0 flex-col gap-3 rounded-sm border border-border-default bg-surface-card p-3\", className)}\n role=\"region\"\n aria-label={title}\n >\n {resolvedType.startsWith(\"image/\") && displayUrl && (\n <img src={displayUrl} alt={title} onLoad={handleLoad} onError={handleMediaError} className=\"max-h-[70vh] max-w-full object-contain\" />\n )}\n {resolvedType === \"application/pdf\" && displayUrl && (\n <iframe src={displayUrl} title={title} onLoad={handleLoad} onError={handleMediaError} sandbox=\"\" className=\"min-h-[32rem] w-full border-0\" />\n )}\n {isText && (textContent !== undefined\n ? <pre className=\"max-h-[70vh] overflow-auto whitespace-pre-wrap break-words text-sm text-content-primary\">{textContent}</pre>\n : displayUrl && <iframe src={displayUrl} title={title} onLoad={handleLoad} onError={handleMediaError} sandbox=\"\" className=\"min-h-64 w-full border-0\" />)}\n {!resolvedType.startsWith(\"image/\") && resolvedType !== \"application/pdf\" && !isText && (\n fallback ?? <p className=\"text-content-secondary\">Este tipo de arquivo não possui visualização disponível.</p>\n )}\n {download && <div className=\"flex justify-end\">{download}</div>}\n </div>\n );\n}\n\nexport default FileViewer;\n","\"use client\";\n\nimport QRCodeGenerator from \"qrcode\";\nimport { useEffect, useId, useMemo, useRef, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport classNames from \"classnames\";\n\nexport type QRCodeErrorCorrectionLevel = \"L\" | \"M\" | \"Q\" | \"H\";\n\nexport interface QRCodeProps extends Omit<HTMLAttributes<HTMLDivElement>, \"color\" | \"onError\"> {\n value: string;\n size?: number;\n level?: QRCodeErrorCorrectionLevel;\n includeMargin?: boolean;\n fgColor?: string;\n bgColor?: string;\n ariaLabel?: string;\n description?: string;\n loading?: boolean;\n error?: ReactNode;\n onError?: (error: Error) => void;\n}\n\nfunction getRelativeLuminance(color: string) {\n const match = color.trim().match(/^#([\\da-f]{6})$/i);\n if (!match) return null;\n\n const channels = [0, 2, 4].map((offset) => Number.parseInt(match[1].slice(offset, offset + 2), 16) / 255);\n const linear = channels.map((channel) => (\n channel <= 0.03928 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4\n ));\n\n return 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];\n}\n\nfunction resolveAccessibleColors(fgColor: string, bgColor: string) {\n const foregroundLuminance = getRelativeLuminance(fgColor);\n const backgroundLuminance = getRelativeLuminance(bgColor);\n\n if (foregroundLuminance === null || backgroundLuminance === null) {\n return { dark: fgColor, light: bgColor };\n }\n\n const lighter = Math.max(foregroundLuminance, backgroundLuminance);\n const darker = Math.min(foregroundLuminance, backgroundLuminance);\n const contrastRatio = (lighter + 0.05) / (darker + 0.05);\n\n return contrastRatio >= 3\n ? { dark: fgColor, light: bgColor }\n : { dark: \"#000000\", light: \"#FFFFFF\" };\n}\n\nexport function QRCode({\n value,\n size = 192,\n level = \"M\",\n includeMargin = true,\n fgColor = \"#000000\",\n bgColor = \"#FFFFFF\",\n ariaLabel = \"Código QR\",\n description,\n loading = false,\n error,\n onError,\n className,\n ...rest\n}: QRCodeProps) {\n const [dataUrl, setDataUrl] = useState<string | null>(null);\n const [generationError, setGenerationError] = useState<Error | null>(null);\n const onErrorRef = useRef(onError);\n const generatedId = useId();\n const resolvedSize = Math.max(1, Number.isFinite(size) ? Math.floor(size) : 192);\n const descriptionId = description\n ? `${rest.id ?? generatedId}-description`\n : undefined;\n const colors = useMemo(\n () => resolveAccessibleColors(fgColor, bgColor),\n [bgColor, fgColor],\n );\n const describedBy = [rest[\"aria-describedby\"], descriptionId].filter(Boolean).join(\" \") || undefined;\n const displayError = error ?? generationError?.message;\n const isLoading = loading || (!dataUrl && !displayError);\n\n useEffect(() => {\n onErrorRef.current = onError;\n }, [onError]);\n\n useEffect(() => {\n let active = true;\n if (error) {\n setDataUrl(null);\n setGenerationError(null);\n return () => { active = false; };\n }\n setDataUrl(null);\n setGenerationError(null);\n QRCodeGenerator.toDataURL(value, {\n width: resolvedSize,\n margin: includeMargin ? 4 : 0,\n errorCorrectionLevel: level,\n color: colors,\n })\n .then((url) => { if (active) setDataUrl(url); })\n .catch((cause: unknown) => {\n if (!active) return;\n const nextError = cause instanceof Error\n ? cause\n : new Error(\"Não foi possível gerar o código QR.\");\n setDataUrl(null);\n setGenerationError(nextError);\n onErrorRef.current?.(nextError);\n });\n return () => { active = false; };\n }, [colors, error, includeMargin, level, resolvedSize, value]);\n\n return (\n <div\n {...rest}\n role=\"img\"\n aria-label={ariaLabel}\n aria-describedby={describedBy}\n aria-busy={isLoading || undefined}\n aria-invalid={displayError ? true : undefined}\n className={classNames(\"inline-flex max-w-full flex-col items-center gap-2\", className)}\n >\n {displayError ? (\n <span role=\"alert\" className=\"rounded-sm border border-field-border-error p-3 text-sm text-field-assistive-error\">\n {displayError}\n </span>\n ) : dataUrl ? (\n <img src={dataUrl} alt=\"\" width={resolvedSize} height={resolvedSize} className=\"h-auto max-w-full\" />\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"inline-block animate-pulse rounded-sm bg-surface-muted\"\n style={{ width: resolvedSize, height: resolvedSize, maxWidth: \"100%\" }}\n />\n )}\n {description && <span id={descriptionId} className=\"sr-only\">{description}</span>}\n </div>\n );\n}\n\nexport default QRCode;\n"],"mappings":"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","names":["useRef","jsx","jsxs","useRef","rejectionMessage","classNames","jsx","jsxs","classNames","jsx","jsxs","classNames","classNames","useEffect","useRef","useState","jsx","jsxs","_a","useEffect","useId","useRef","useState","classNames","jsx","jsxs","_a","useState","useRef","useId","useEffect","classNames"]}