@oondemand/oon-core-front 0.3.31 → 0.3.33

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.js CHANGED
@@ -1369,6 +1369,111 @@ function ReferenceSelect({
1369
1369
  ] });
1370
1370
  }
1371
1371
 
1372
+ // src/components/internal/inputMasks.ts
1373
+ var digitsOnly = (value) => String(value ?? "").replace(/\D/g, "");
1374
+ var normalizedName = (value) => String(value ?? "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
1375
+ var hasLetters = (value) => /[a-zA-Z]/.test(String(value ?? ""));
1376
+ function personType(values) {
1377
+ return normalizedName(values?.tipo ?? values?.tipoPessoa ?? values?.pessoaTipo);
1378
+ }
1379
+ function resolveInputMask(field, values) {
1380
+ if (field.mask) return field.mask;
1381
+ if (field.kind === "currency" || field.kind === "currencyConverted") return "currency";
1382
+ if (field.kind && !["string", "number"].includes(field.kind)) return void 0;
1383
+ const name = normalizedName(field.field);
1384
+ if (!name) return void 0;
1385
+ if (name.includes("cnpj")) return "cnpj";
1386
+ if (name.includes("cpf")) return "cpf";
1387
+ if (/documento|document|inscricaofiscal/.test(name)) {
1388
+ const tipo = personType(values);
1389
+ if (tipo === "est" || tipo.includes("estrangeir") || tipo.includes("foreign")) return void 0;
1390
+ if (tipo === "pf" || tipo.includes("fisica")) return "cpf";
1391
+ if (tipo === "pj" || tipo.includes("juridica")) return "cnpj";
1392
+ return "document";
1393
+ }
1394
+ if (/telefone|celular|whatsapp|fone|phone/.test(name)) return "phone";
1395
+ return void 0;
1396
+ }
1397
+ function formatCpf(value) {
1398
+ const digits = digitsOnly(value).slice(0, 11);
1399
+ return digits.replace(/^(\d{3})(\d)/, "$1.$2").replace(/^(\d{3})\.(\d{3})(\d)/, "$1.$2.$3").replace(/\.(\d{3})(\d)/, ".$1-$2");
1400
+ }
1401
+ function formatCnpj(value) {
1402
+ const digits = digitsOnly(value).slice(0, 14);
1403
+ return digits.replace(/^(\d{2})(\d)/, "$1.$2").replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3").replace(/\.(\d{3})(\d)/, ".$1/$2").replace(/(\/\d{4})(\d)/, "$1-$2");
1404
+ }
1405
+ function formatPhone(value) {
1406
+ const digits = digitsOnly(value).slice(0, 11);
1407
+ if (!digits) return "";
1408
+ if (digits.length <= 2) return `(${digits}`;
1409
+ const ddd = digits.slice(0, 2);
1410
+ const number = digits.slice(2);
1411
+ const prefixLength = number.length > 8 ? 5 : 4;
1412
+ const prefix = number.slice(0, prefixLength);
1413
+ const suffix = number.slice(prefixLength);
1414
+ return `(${ddd}) ${prefix}${suffix ? `-${suffix}` : ""}`;
1415
+ }
1416
+ function parseCurrencyInitial(value) {
1417
+ if (value == null || value === "") return "";
1418
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "";
1419
+ const raw = String(value).trim();
1420
+ if (!raw) return "";
1421
+ if (/^-?\d+(?:\.\d+)?$/.test(raw)) return raw;
1422
+ const localized = raw.replace(/[^\d,.-]/g, "").replace(/\.(?=\d{3}(?:\D|$))/g, "").replace(",", ".");
1423
+ const parsed = Number(localized);
1424
+ return Number.isFinite(parsed) ? String(parsed) : "";
1425
+ }
1426
+ function formatCurrency(value) {
1427
+ const normalized = parseCurrencyInitial(value);
1428
+ if (!normalized) return "";
1429
+ const numeric = Number(normalized);
1430
+ if (!Number.isFinite(numeric)) return "";
1431
+ return new Intl.NumberFormat("pt-BR", {
1432
+ style: "currency",
1433
+ currency: "BRL",
1434
+ minimumFractionDigits: 2,
1435
+ maximumFractionDigits: 2
1436
+ }).format(numeric);
1437
+ }
1438
+ function normalizeMaskedValue(value, mask) {
1439
+ if (!mask) return String(value ?? "");
1440
+ if (mask === "currency") return parseCurrencyInitial(value);
1441
+ if (mask === "document" && hasLetters(value)) return String(value ?? "").slice(0, 30);
1442
+ const limit = mask === "cnpj" ? 14 : mask === "cpf" ? 11 : mask === "phone" ? 11 : 14;
1443
+ return digitsOnly(value).slice(0, limit);
1444
+ }
1445
+ function formatMaskedValue(value, mask) {
1446
+ if (!mask) return String(value ?? "");
1447
+ if (mask === "currency") return formatCurrency(value);
1448
+ if (mask === "phone") return formatPhone(value);
1449
+ if (mask === "cpf") return formatCpf(value);
1450
+ if (mask === "cnpj") return formatCnpj(value);
1451
+ if (hasLetters(value)) return String(value ?? "");
1452
+ const digits = digitsOnly(value);
1453
+ return digits.length > 11 ? formatCnpj(digits) : formatCpf(digits);
1454
+ }
1455
+ function parseMaskedInput(value, mask) {
1456
+ if (!mask) return value;
1457
+ if (mask === "currency") {
1458
+ const digits = digitsOnly(value);
1459
+ if (!digits) return "";
1460
+ const amount = Number(digits) / 100;
1461
+ return `${value.includes("-") ? "-" : ""}${amount.toFixed(2)}`;
1462
+ }
1463
+ return normalizeMaskedValue(value, mask);
1464
+ }
1465
+ function inputModeForMask(mask) {
1466
+ if (mask === "document") return "text";
1467
+ return mask ? "numeric" : void 0;
1468
+ }
1469
+ function maxLengthForMask(mask) {
1470
+ if (mask === "cpf") return 14;
1471
+ if (mask === "cnpj") return 18;
1472
+ if (mask === "document") return 30;
1473
+ if (mask === "phone") return 15;
1474
+ return void 0;
1475
+ }
1476
+
1372
1477
  // src/components/internal/DynamicForm.tsx
1373
1478
  import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1374
1479
  var idFor = (field) => `oon-form-field-${field.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
@@ -1404,6 +1509,9 @@ function toValue(value, kind) {
1404
1509
  }
1405
1510
  return String(value);
1406
1511
  }
1512
+ function initialFieldValue(field, value) {
1513
+ return normalizeMaskedValue(toValue(value, field.kind), resolveInputMask(field));
1514
+ }
1407
1515
  function coerce(value, kind) {
1408
1516
  if (value === "") return void 0;
1409
1517
  if (["number", "currency", "currencyConverted"].includes(kind ?? "")) return Number(value);
@@ -1509,7 +1617,7 @@ function resolveReference(field, values) {
1509
1617
  return { filters, disabled: missing.length > 0 };
1510
1618
  }
1511
1619
  function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submitting, error, onSubmit, onCancel, onFieldChange }) {
1512
- const [values, setValues] = useState5(() => Object.fromEntries(fields.map((field) => [field.field, toValue(initialValues?.[field.field], field.kind)])));
1620
+ const [values, setValues] = useState5(() => Object.fromEntries(fields.map((field) => [field.field, initialFieldValue(field, initialValues?.[field.field])])));
1513
1621
  const [errors, setErrors] = useState5({});
1514
1622
  const [dismissed, setDismissed] = useState5(false);
1515
1623
  const items = useMemo4(() => buildItems(fields), [fields]);
@@ -1632,7 +1740,7 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
1632
1740
  }
1633
1741
  if (field.kind === "ref" && field.ref) {
1634
1742
  const reference = resolveReference(field, values);
1635
- return wrap(/* @__PURE__ */ jsx9(ReferenceSelect, { field: field.field, inputId: id, errorId, label, refModel: field.ref, value: values[field.field] ?? "", initialValue: initialValues?.[field.field], required: field.required, invalid: !!message, error: message, filters: reference.filters, emptyFields: field.referenceEmptyFields, disabled: reference.disabled, disabledMessage: field.referenceDisabledMessage, onChange: (value) => change(field.field, value) }));
1743
+ return wrap(/* @__PURE__ */ jsx9(ReferenceSelect, { field: field.field, inputId: id, errorId, label, refModel: field.ref, value: values[field.field] ?? "", initialValue: initialValues?.[field.field], required: field.required, invalid: !!message, error: message, filters: reference.filters, emptyFields: field.referenceEmptyFields, disabled: reference.disabled, disabledMessage: field.referenceDisabledMessage, onChange: (value2) => change(field.field, value2) }));
1636
1744
  }
1637
1745
  if (field.kind === "enum" && field.options?.length) return wrap(/* @__PURE__ */ jsxs5(NativeSelect2.Root, { size: "sm", children: [
1638
1746
  /* @__PURE__ */ jsxs5(NativeSelect2.Field, { id, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), onChange: (event) => change(field.field, event.currentTarget.value), children: [
@@ -1650,8 +1758,27 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
1650
1758
  /* @__PURE__ */ jsx9(NativeSelect2.Indicator, {})
1651
1759
  ] }));
1652
1760
  if (multiline) return wrap(/* @__PURE__ */ jsx9(Textarea, { id, rows: field.rows ?? 4, resize: "vertical", "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), lineHeight: "1.5", onChange: (event) => change(field.field, event.currentTarget.value) }));
1653
- const type = field.kind === "date" ? "date" : ["number", "currency", "currencyConverted"].includes(field.kind ?? "") ? "number" : "text";
1654
- return wrap(/* @__PURE__ */ jsx9(Input3, { id, type, step: type === "number" ? "any" : void 0, autoComplete: "off", "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), onChange: (event) => change(field.field, event.currentTarget.value) }));
1761
+ const mask = resolveInputMask(field);
1762
+ const type = mask ? "text" : field.kind === "date" ? "date" : field.kind === "number" ? "number" : "text";
1763
+ const value = values[field.field] ?? "";
1764
+ return wrap(
1765
+ /* @__PURE__ */ jsx9(
1766
+ Input3,
1767
+ {
1768
+ id,
1769
+ type,
1770
+ step: type === "number" ? "any" : void 0,
1771
+ inputMode: inputModeForMask(mask),
1772
+ maxLength: maxLengthForMask(mask),
1773
+ autoComplete: "off",
1774
+ "aria-invalid": !!message,
1775
+ "aria-describedby": errorId,
1776
+ value: mask ? formatMaskedValue(value, mask) : value,
1777
+ ...controlProps(!!message),
1778
+ onChange: (event) => change(field.field, parseMaskedInput(event.currentTarget.value, mask))
1779
+ }
1780
+ )
1781
+ );
1655
1782
  };
1656
1783
  const invalid = fields.filter((field) => errors[field.field]);
1657
1784
  const generic = dismissed ? null : messageOf(error);
@@ -1775,7 +1902,13 @@ import { Input as Input4, NativeSelect as NativeSelect3, Textarea as Textarea2 }
1775
1902
  import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1776
1903
  function CoreInlineEditableCell({ column, meta, value, onChange }) {
1777
1904
  const kind = column.editor ?? meta?.kind ?? column.kind ?? "string";
1778
- const common = { size: "xs", fontSize: "11px", value: value == null ? "" : String(value), onChange: (event) => onChange(event.currentTarget.value) };
1905
+ const plainValue = value == null ? "" : String(value);
1906
+ const common = {
1907
+ size: "xs",
1908
+ fontSize: "11px",
1909
+ value: plainValue,
1910
+ onChange: (event) => onChange(event.currentTarget.value)
1911
+ };
1779
1912
  if (kind === "boolean") return /* @__PURE__ */ jsxs7(NativeSelect3.Root, { size: "xs", children: [
1780
1913
  /* @__PURE__ */ jsxs7(NativeSelect3.Field, { ...common, children: [
1781
1914
  /* @__PURE__ */ jsx11("option", { value: "", children: "\u2014" }),
@@ -1792,8 +1925,21 @@ function CoreInlineEditableCell({ column, meta, value, onChange }) {
1792
1925
  /* @__PURE__ */ jsx11(NativeSelect3.Indicator, {})
1793
1926
  ] });
1794
1927
  if (kind === "textarea") return /* @__PURE__ */ jsx11(Textarea2, { ...common, rows: 2 });
1795
- const type = kind === "date" ? "date" : ["number", "currency"].includes(kind) ? "number" : "text";
1796
- return /* @__PURE__ */ jsx11(Input4, { ...common, type, step: type === "number" ? "any" : void 0 });
1928
+ const mask = resolveInputMask({ field: column.field, kind });
1929
+ const type = mask ? "text" : kind === "date" ? "date" : kind === "number" ? "number" : "text";
1930
+ return /* @__PURE__ */ jsx11(
1931
+ Input4,
1932
+ {
1933
+ size: "xs",
1934
+ fontSize: "11px",
1935
+ type,
1936
+ step: type === "number" ? "any" : void 0,
1937
+ inputMode: inputModeForMask(mask),
1938
+ maxLength: maxLengthForMask(mask),
1939
+ value: mask ? formatMaskedValue(plainValue, mask) : plainValue,
1940
+ onChange: (event) => onChange(parseMaskedInput(event.currentTarget.value, mask))
1941
+ }
1942
+ );
1797
1943
  }
1798
1944
 
1799
1945
  // src/components/internal/CoreRowAction.tsx
@@ -2120,6 +2266,9 @@ function toValue2(value, kind) {
2120
2266
  }
2121
2267
  return String(value);
2122
2268
  }
2269
+ function initialFieldValue2(field, value) {
2270
+ return normalizeMaskedValue(toValue2(value, field.kind), resolveInputMask(field));
2271
+ }
2123
2272
  function isMultiline2(field) {
2124
2273
  return /observa|descricao|mensagem|detalhe|necessidade/i.test(field.field);
2125
2274
  }
@@ -2273,6 +2422,7 @@ function FieldControl({
2273
2422
  )
2274
2423
  ] });
2275
2424
  }
2425
+ const mask = resolveInputMask(field);
2276
2426
  const control = field.kind === "enum" && field.options?.length ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
2277
2427
  /* @__PURE__ */ jsxs10(NativeSelect4.Field, { id: inputId, value, ...invalidProps, onChange: (event) => onChange(event.currentTarget.value), children: [
2278
2428
  /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014 Selecione \u2014" }),
@@ -2291,10 +2441,13 @@ function FieldControl({
2291
2441
  {
2292
2442
  id: inputId,
2293
2443
  size: "sm",
2294
- type: field.kind === "date" ? "date" : ["number", "currency", "currencyConverted"].includes(field.kind ?? "") ? "number" : "text",
2295
- value,
2444
+ type: mask ? "text" : field.kind === "date" ? "date" : field.kind === "number" ? "number" : "text",
2445
+ step: !mask && field.kind === "number" ? "any" : void 0,
2446
+ inputMode: inputModeForMask(mask),
2447
+ maxLength: maxLengthForMask(mask),
2448
+ value: mask ? formatMaskedValue(value, mask) : value,
2296
2449
  ...invalidProps,
2297
- onChange: (event) => onChange(event.currentTarget.value)
2450
+ onChange: (event) => onChange(parseMaskedInput(event.currentTarget.value, mask))
2298
2451
  }
2299
2452
  );
2300
2453
  return /* @__PURE__ */ jsxs10(Box7, { children: [
@@ -2343,7 +2496,7 @@ function InlineParentForm({
2343
2496
  const [error, setError] = useState8(null);
2344
2497
  const [fieldErrors, setFieldErrors] = useState8({});
2345
2498
  useEffect5(() => {
2346
- setValues(Object.fromEntries(fields.map((field) => [field.field, toValue2(parent[field.field], field.kind)])));
2499
+ setValues(Object.fromEntries(fields.map((field) => [field.field, initialFieldValue2(field, parent[field.field])])));
2347
2500
  setError(null);
2348
2501
  setFieldErrors({});
2349
2502
  }, [parent, rawFields]);