@oondemand/oon-core-front 0.3.10 → 0.3.12

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
@@ -3,7 +3,7 @@ import { StrictMode } from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
 
5
5
  // src/app/OonApp.tsx
6
- import { useMemo as useMemo4 } from "react";
6
+ import { useMemo as useMemo6 } from "react";
7
7
  import { RouterProvider } from "react-router-dom";
8
8
 
9
9
  // src/api/createRestClient.ts
@@ -15,6 +15,18 @@ function normalizeError(err) {
15
15
  if (axios.isAxiosError(err)) {
16
16
  const status = err.response?.status;
17
17
  const data = err.response?.data;
18
+ const contentType = String(err.response?.headers?.["content-type"] || "");
19
+ const isTextPayload = typeof data === "string";
20
+ const isProbablyHtml = isTextPayload && /<html|<!doctype/i.test(data);
21
+ if (isTextPayload || contentType && !contentType.includes("json")) {
22
+ return {
23
+ code: codeFromStatus(status),
24
+ message: nonJsonMessage(status, err.config?.url, isProbablyHtml),
25
+ status,
26
+ details: isProbablyHtml ? void 0 : data,
27
+ requestId: err.response?.headers?.["x-request-id"]
28
+ };
29
+ }
18
30
  const envelope = data?.error;
19
31
  return {
20
32
  code: envelope?.code || codeFromStatus(status),
@@ -29,6 +41,16 @@ function normalizeError(err) {
29
41
  }
30
42
  return { code: "UNKNOWN", message: "Erro inesperado." };
31
43
  }
44
+ function nonJsonMessage(status, url, html) {
45
+ const path = url ? ` (${url})` : "";
46
+ if (status === 404) {
47
+ return `Rota da API n\xE3o encontrada${path}. Verifique VITE_API_URL, porta do backend e modo da Central.`;
48
+ }
49
+ if (html) {
50
+ return `Backend retornou HTML em vez de JSON${path}. Verifique se o frontend est\xE1 apontando para a API correta.`;
51
+ }
52
+ return `Backend retornou resposta n\xE3o JSON${path}. Verifique a configura\xE7\xE3o da API.`;
53
+ }
32
54
  function codeFromStatus(status) {
33
55
  switch (status) {
34
56
  case 400:
@@ -433,6 +455,20 @@ function encodeBasicCredentials(email, password) {
433
455
  for (const byte of bytes) binary += String.fromCharCode(byte);
434
456
  return window.btoa(binary);
435
457
  }
458
+ function normalizeList(value) {
459
+ if (Array.isArray(value)) return value.map(String).filter(Boolean);
460
+ if (typeof value === "string") return value.split(/[\s,;]+/).map((item) => item.trim()).filter(Boolean);
461
+ return [];
462
+ }
463
+ function extractCapabilities(user) {
464
+ if (!user) return [];
465
+ return [
466
+ ...normalizeList(user.capabilities),
467
+ ...normalizeList(user.permissoes?.capabilities),
468
+ ...normalizeList(user.aplicativo?.capabilities),
469
+ ...normalizeList(user.aplicativo?.permissoes?.capabilities)
470
+ ].filter((item, index, all) => all.indexOf(item) === index);
471
+ }
436
472
  function AuthProvider({
437
473
  http,
438
474
  storage,
@@ -558,6 +594,7 @@ function AuthProvider({
558
594
  activation?.status
559
595
  ]);
560
596
  const roles = user?.tipo ? [user.tipo] : [];
597
+ const capabilities = extractCapabilities(user);
561
598
  const hasPermission = useCallback2(
562
599
  (permission) => {
563
600
  if (!permission) return true;
@@ -565,14 +602,15 @@ function AuthProvider({
565
602
  if (required.length === 0) return true;
566
603
  if (roles.includes("admin") || roles.includes("master")) return true;
567
604
  return required.some(
568
- (value2) => roles.includes(value2) || roles.some((role) => value2.startsWith(`${role}.`))
605
+ (value2) => roles.includes(value2) || capabilities.includes(value2) || roles.some((role) => value2.startsWith(`${role}.`))
569
606
  );
570
607
  },
571
- [roles]
608
+ [roles, capabilities]
572
609
  );
573
610
  const value = {
574
611
  user,
575
612
  roles,
613
+ capabilities,
576
614
  status,
577
615
  isAuthenticated: status === "authenticated",
578
616
  hasPermission,
@@ -602,9 +640,9 @@ function OonProviders({ config, http, storage, children }) {
602
640
  }
603
641
 
604
642
  // src/components/CoreCollection.tsx
605
- import { useState as useState6 } from "react";
606
- import { Box as Box5, Heading as Heading3, Stack as Stack3, Text as Text6 } from "@chakra-ui/react";
607
- import { useMutation, useQueryClient } from "@tanstack/react-query";
643
+ import { useState as useState10 } from "react";
644
+ import { Box as Box9, Heading as Heading4, Stack as Stack4, Text as Text11 } from "@chakra-ui/react";
645
+ import { useMutation as useMutation2, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
608
646
 
609
647
  // src/components/internal/fieldUtils.ts
610
648
  var HIDDEN_FIELDS = /* @__PURE__ */ new Set(["__v", "_id", "createdAt", "updatedAt", "criadoEm", "atualizadoEm"]);
@@ -757,16 +795,21 @@ function DataGrid({
757
795
  onCreate,
758
796
  onEdit,
759
797
  onDelete,
760
- toolbarExtra
798
+ toolbarExtra,
799
+ filters = [],
800
+ queryExtra,
801
+ renderRowActions
761
802
  }) {
762
803
  const [pageIndex, setPageIndex] = useState3(0);
763
804
  const [pageSize, setPageSize] = useState3(20);
764
805
  const [searchTerm, setSearchTerm] = useState3("");
765
806
  const deferredSearch = useDeferredValue(searchTerm);
766
807
  const [sort, setSort] = useState3(void 0);
808
+ const [filterValues, setFilterValues] = useState3(() => Object.fromEntries(filters.map((filter) => [filter.field, filter.defaultValue ?? ""])));
809
+ const effectiveFilters = Object.fromEntries(Object.entries({ ...queryExtra, ...filterValues }).filter(([, value]) => value !== "" && value != null));
767
810
  const query = useQuery2({
768
- queryKey: ["oon", "list", resourceKey, { pageIndex, pageSize, searchTerm: deferredSearch, sort }],
769
- queryFn: () => resource.list({ pageIndex, pageSize, searchTerm: deferredSearch || void 0, sort }),
811
+ queryKey: ["oon", "list", resourceKey, { pageIndex, pageSize, searchTerm: deferredSearch, sort, filters: effectiveFilters }],
812
+ queryFn: () => resource.list({ pageIndex, pageSize, searchTerm: deferredSearch || void 0, sort, ...effectiveFilters }),
770
813
  placeholderData: keepPreviousData
771
814
  });
772
815
  const toggleSort = (field) => {
@@ -782,7 +825,7 @@ function DataGrid({
782
825
  const totalItems = pagination?.totalItems ?? rows.length;
783
826
  const totalPages = Math.max(1, pagination?.totalPages ?? 1);
784
827
  const currentPage = Math.min(pageIndex + 1, totalPages);
785
- const actionCount = onEdit || onDelete ? 1 : 0;
828
+ const actionCount = onEdit || onDelete || renderRowActions ? 1 : 0;
786
829
  return /* @__PURE__ */ jsxs3(Box2, { bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", boxShadow: "0 1px 2px rgba(15,23,42,.06)", overflow: "hidden", children: [
787
830
  /* @__PURE__ */ jsxs3(Flex2, { minH: "60px", px: "14px", py: "12px", align: "center", gap: 4, borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
788
831
  search ? /* @__PURE__ */ jsxs3(Flex2, { minW: { base: "100%", md: "min(420px, 55vw)" }, maxW: "420px", h: "35px", px: "10px", align: "center", gap: 2, color: "#98A2B3", bg: "white", borderWidth: "1px", borderColor: "#D5DDE3", borderRadius: "6px", _focusWithin: { borderColor: "#0F8DD0", boxShadow: "0 0 0 3px rgba(15,141,208,.10)" }, children: [
@@ -809,6 +852,16 @@ function DataGrid({
809
852
  )
810
853
  ] }) : null,
811
854
  /* @__PURE__ */ jsx7(Spacer, {}),
855
+ filters.map((filter) => filter.type === "select" ? /* @__PURE__ */ jsxs3(NativeSelect.Root, { size: "xs", w: "180px", children: [
856
+ /* @__PURE__ */ jsx7(NativeSelect.Field, { value: String(filterValues[filter.field] ?? ""), onChange: (event) => {
857
+ setFilterValues((current) => ({ ...current, [filter.field]: event.currentTarget.value }));
858
+ setPageIndex(0);
859
+ }, children: (filter.options ?? []).map((option) => /* @__PURE__ */ jsx7("option", { value: String(option.value ?? ""), children: option.label }, String(option.value ?? ""))) }),
860
+ /* @__PURE__ */ jsx7(NativeSelect.Indicator, {})
861
+ ] }, filter.field) : /* @__PURE__ */ jsx7(Input, { w: "180px", h: "35px", fontSize: "11px", placeholder: filter.placeholder ?? filter.label ?? filter.field, type: filter.type === "date" ? "date" : filter.type === "boolean" ? "text" : "text", value: String(filterValues[filter.field] ?? ""), onChange: (event) => {
862
+ setFilterValues((current) => ({ ...current, [filter.field]: event.currentTarget.value }));
863
+ setPageIndex(0);
864
+ } }, filter.field)),
812
865
  /* @__PURE__ */ jsxs3(Flex2, { align: "center", gap: 3, color: "#98A2B3", fontSize: "10px", children: [
813
866
  query.isFetching ? /* @__PURE__ */ jsx7(Text3, { children: "Atualizando..." }) : null,
814
867
  /* @__PURE__ */ jsxs3(Text3, { as: "strong", color: "#667085", fontWeight: "600", children: [
@@ -854,7 +907,8 @@ function DataGrid({
854
907
  columns.map((column) => /* @__PURE__ */ jsx7(Table.Cell, { maxW: "250px", h: "42px", px: "10px", py: "8px", overflow: "hidden", color: "#52606D", borderBottomWidth: "1px", borderColor: "#EEF1F3", fontSize: "11px", textOverflow: "ellipsis", whiteSpace: "nowrap", children: renderCell(row[column.field], column.kind) }, column.field)),
855
908
  actionCount ? /* @__PURE__ */ jsx7(Table.Cell, { h: "42px", px: "10px", py: "5px", borderBottomWidth: "1px", borderColor: "#EEF1F3", textAlign: "center", children: /* @__PURE__ */ jsxs3(Flex2, { justify: "center", gap: "5px", children: [
856
909
  onEdit ? /* @__PURE__ */ jsx7(Button2, { type: "button", "aria-label": "Editar", w: "31px", minW: "31px", h: "31px", p: 0, color: "#667085", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "6px", onClick: () => onEdit(row), _hover: { color: "#036491", bg: "#F0F7FF", borderColor: "#B8D9EB" }, children: /* @__PURE__ */ jsx7(EditIcon, {}) }) : null,
857
- onDelete ? /* @__PURE__ */ jsx7(Button2, { type: "button", "aria-label": "Excluir", w: "31px", minW: "31px", h: "31px", p: 0, color: "#667085", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "6px", onClick: () => onDelete(row), _hover: { color: "#B42318", bg: "#FFF5F5", borderColor: "#FECACA" }, children: /* @__PURE__ */ jsx7(TrashIcon, {}) }) : null
910
+ onDelete ? /* @__PURE__ */ jsx7(Button2, { type: "button", "aria-label": "Excluir", w: "31px", minW: "31px", h: "31px", p: 0, color: "#667085", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "6px", onClick: () => onDelete(row), _hover: { color: "#B42318", bg: "#FFF5F5", borderColor: "#FECACA" }, children: /* @__PURE__ */ jsx7(TrashIcon, {}) }) : null,
911
+ renderRowActions?.(row)
858
912
  ] }) }) : null
859
913
  ] }, row._id ?? index)) })
860
914
  ] }) }),
@@ -1516,21 +1570,362 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
1516
1570
  ] }) });
1517
1571
  }
1518
1572
 
1573
+ // src/components/internal/CoreDetailModal.tsx
1574
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState9 } from "react";
1575
+ import { Box as Box8, Button as Button8, Flex as Flex7, Heading as Heading3, Text as Text10 } from "@chakra-ui/react";
1576
+ import { useQuery as useQuery6, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1577
+
1578
+ // src/components/internal/CoreTabbedDetail.tsx
1579
+ import { useEffect as useEffect5, useState as useState8 } from "react";
1580
+ import { Box as Box7, Button as Button7, Flex as Flex6, Input as Input5, NativeSelect as NativeSelect4, SimpleGrid as SimpleGrid3, Stack as Stack3, Text as Text9 } from "@chakra-ui/react";
1581
+
1582
+ // src/components/internal/CoreSummaryCards.tsx
1583
+ import { SimpleGrid as SimpleGrid2, Box as Box5, Text as Text6, Badge as Badge2 } from "@chakra-ui/react";
1584
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
1585
+
1586
+ // src/components/internal/manifestUtils.ts
1587
+ function normalizeColumn(column, schema) {
1588
+ if (typeof column !== "string") {
1589
+ const meta2 = schema?.fields.find((field) => field.name === column.field);
1590
+ return { label: meta2 ? fieldLabel(meta2) : column.field, kind: meta2?.kind, ...column };
1591
+ }
1592
+ const meta = schema?.fields.find((field) => field.name === column);
1593
+ return { field: column, label: meta ? fieldLabel(meta) : fieldLabel({ name: column }), kind: meta?.kind, sortable: true };
1594
+ }
1595
+ function fieldsForTab(fields, selected) {
1596
+ if (!selected?.length) return fields;
1597
+ const wanted = new Set(selected);
1598
+ return fields.filter((field) => wanted.has(field.field));
1599
+ }
1600
+ function relationFrom(input, relations) {
1601
+ return typeof input === "string" ? relations?.[input] : input;
1602
+ }
1603
+
1604
+ // src/components/internal/CoreSummaryCards.tsx
1605
+ import { Fragment, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1606
+ function format(value, format2) {
1607
+ if (format2 === "currency") return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(Number(value ?? 0));
1608
+ if (format2 === "percent") return `${Number(value ?? 0).toLocaleString("pt-BR")}%`;
1609
+ if (format2 === "date") return formatCell(value, "date");
1610
+ return value == null || value === "" ? "\u2014" : String(value);
1611
+ }
1612
+ function RelatedMetric({ card, relation, parent }) {
1613
+ const schema = useModelSchema(relation.model).data;
1614
+ const resource = useOonResource(schema?.basePath ?? `/${relation.model.toLowerCase()}s`);
1615
+ const parentValue = parent[relation.parentKey ?? "_id"];
1616
+ const query = useQuery4({ queryKey: ["oon", "summary", relation.model, relation.foreignKey, parentValue, card.source, card.field], queryFn: () => resource.list({ [relation.foreignKey]: parentValue, pageSize: 1e3 }) });
1617
+ const rows = query.data?.results ?? [];
1618
+ let value = rows.length;
1619
+ if (card.source === "relatedSum") value = rows.reduce((sum, row) => sum + Number(row[card.field ?? ""] ?? 0), 0);
1620
+ if (card.source === "relatedAvg") value = rows.length ? rows.reduce((sum, row) => sum + Number(row[card.field ?? ""] ?? 0), 0) / rows.length : 0;
1621
+ return /* @__PURE__ */ jsx10(Fragment, { children: query.isLoading ? "..." : format(value, card.format) });
1622
+ }
1623
+ function CoreSummaryCards({ cards = [], parent, relations }) {
1624
+ return /* @__PURE__ */ jsx10(SimpleGrid2, { columns: { base: 1, md: 3 }, gap: 3, children: cards.map((card, index) => {
1625
+ const relation = card.relation ? relationFrom(card.relation, relations) : void 0;
1626
+ const content = relation && card.source?.startsWith("related") ? /* @__PURE__ */ jsx10(RelatedMetric, { card, relation, parent }) : format(parent[card.field ?? ""], card.format);
1627
+ return /* @__PURE__ */ jsxs6(Box5, { p: "14px", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: [
1628
+ /* @__PURE__ */ jsx10(Text6, { color: "#667085", fontSize: "10px", fontWeight: "600", children: card.label }),
1629
+ /* @__PURE__ */ jsx10(Text6, { mt: "6px", color: "#24323A", fontSize: "20px", fontWeight: "700", children: card.format === "badge" ? /* @__PURE__ */ jsx10(Badge2, { children: content }) : content })
1630
+ ] }, `${card.label}-${index}`);
1631
+ }) });
1632
+ }
1633
+
1634
+ // src/components/internal/CoreRelatedGrid.tsx
1635
+ import { useMemo as useMemo4, useState as useState7 } from "react";
1636
+ import { Badge as Badge3, Box as Box6, Button as Button6, Flex as Flex5, Table as Table2, Text as Text8 } from "@chakra-ui/react";
1637
+ import { useMutation, useQuery as useQuery5, useQueryClient } from "@tanstack/react-query";
1638
+
1639
+ // src/components/internal/CoreInlineEditableCell.tsx
1640
+ import { Input as Input4, NativeSelect as NativeSelect3, Textarea as Textarea2 } from "@chakra-ui/react";
1641
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1642
+ function CoreInlineEditableCell({ column, meta, value, onChange }) {
1643
+ const kind = column.editor ?? meta?.kind ?? column.kind ?? "string";
1644
+ const common = { size: "xs", fontSize: "11px", value: value == null ? "" : String(value), onChange: (event) => onChange(event.currentTarget.value) };
1645
+ if (kind === "boolean") return /* @__PURE__ */ jsxs7(NativeSelect3.Root, { size: "xs", children: [
1646
+ /* @__PURE__ */ jsxs7(NativeSelect3.Field, { ...common, children: [
1647
+ /* @__PURE__ */ jsx11("option", { value: "", children: "\u2014" }),
1648
+ /* @__PURE__ */ jsx11("option", { value: "true", children: "Sim" }),
1649
+ /* @__PURE__ */ jsx11("option", { value: "false", children: "N\xE3o" })
1650
+ ] }),
1651
+ /* @__PURE__ */ jsx11(NativeSelect3.Indicator, {})
1652
+ ] });
1653
+ if ((kind === "enum" || kind === "select") && meta?.options?.length) return /* @__PURE__ */ jsxs7(NativeSelect3.Root, { size: "xs", children: [
1654
+ /* @__PURE__ */ jsxs7(NativeSelect3.Field, { ...common, children: [
1655
+ /* @__PURE__ */ jsx11("option", { value: "", children: "\u2014" }),
1656
+ meta.options.map((option) => /* @__PURE__ */ jsx11("option", { value: option, children: option }, option))
1657
+ ] }),
1658
+ /* @__PURE__ */ jsx11(NativeSelect3.Indicator, {})
1659
+ ] });
1660
+ if (kind === "textarea") return /* @__PURE__ */ jsx11(Textarea2, { ...common, rows: 2 });
1661
+ const type = kind === "date" ? "date" : ["number", "currency"].includes(kind) ? "number" : "text";
1662
+ return /* @__PURE__ */ jsx11(Input4, { ...common, type, step: type === "number" ? "any" : void 0 });
1663
+ }
1664
+
1665
+ // src/components/internal/CoreRowAction.tsx
1666
+ import { useState as useState6 } from "react";
1667
+ import { Button as Button5, Text as Text7 } from "@chakra-ui/react";
1668
+
1669
+ // src/components/internal/conditions.ts
1670
+ function valueAt(source, path) {
1671
+ if (!source) return void 0;
1672
+ return path.split(".").reduce((current, part) => {
1673
+ if (current && typeof current === "object") return current[part];
1674
+ return void 0;
1675
+ }, source);
1676
+ }
1677
+ function evaluateCondition(condition, row) {
1678
+ if (!condition) return false;
1679
+ const value = valueAt(row, condition.field);
1680
+ if ("exists" in condition) return condition.exists ? value != null && value !== "" : value == null || value === "";
1681
+ if ("equals" in condition) return value === condition.equals;
1682
+ if ("notEquals" in condition) return value !== condition.notEquals;
1683
+ if ("in" in condition) return condition.in.includes(value);
1684
+ const numeric = Number(value);
1685
+ if (Number.isNaN(numeric)) return false;
1686
+ if ("gt" in condition) return numeric > condition.gt;
1687
+ if ("gte" in condition) return numeric >= condition.gte;
1688
+ if ("lt" in condition) return numeric < condition.lt;
1689
+ if ("lte" in condition) return numeric <= condition.lte;
1690
+ return false;
1691
+ }
1692
+ function interpolateEndpoint(endpoint, row, parent) {
1693
+ return endpoint.replace(/:([A-Za-z0-9_.]+)/g, (_, token) => {
1694
+ if (token === "id") return encodeURIComponent(String(row._id ?? row.id ?? ""));
1695
+ if (token === "parentId") return encodeURIComponent(String(parent?._id ?? parent?.id ?? ""));
1696
+ if (token.startsWith("parent.")) return encodeURIComponent(String(valueAt(parent, token.slice(7)) ?? ""));
1697
+ return encodeURIComponent(String(valueAt(row, token) ?? ""));
1698
+ });
1699
+ }
1700
+
1701
+ // src/components/internal/CoreRowAction.tsx
1702
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1703
+ function messageOf2(error) {
1704
+ return error instanceof Error ? error.message : typeof error === "string" ? error : "N\xE3o foi poss\xEDvel executar a a\xE7\xE3o.";
1705
+ }
1706
+ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh }) {
1707
+ const { http } = useOonApi();
1708
+ const [loading, setLoading] = useState6(false);
1709
+ const [error, setError] = useState6(null);
1710
+ if (evaluateCondition(action.hiddenWhen, row)) return null;
1711
+ const disabled = evaluateCondition(action.disabledWhen, row) || loading;
1712
+ const run = async () => {
1713
+ setError(null);
1714
+ if (action.type === "openDetailModal") return onOpenDetail?.(row, action.initialTab);
1715
+ if (action.type === "navigate") {
1716
+ const href = action.href ?? action.endpoint;
1717
+ if (href) window.location.assign(interpolateEndpoint(href, row, parent));
1718
+ return;
1719
+ }
1720
+ if (action.type !== "apiAction" || !action.endpoint) return;
1721
+ const ok = action.confirm ? window.confirm(action.confirm.description ?? action.confirm.title ?? `Executar ${action.label}?`) : true;
1722
+ if (!ok) return;
1723
+ setLoading(true);
1724
+ try {
1725
+ const url = interpolateEndpoint(action.endpoint, row, parent);
1726
+ await http.request({ url, method: action.method ?? "POST" });
1727
+ onRefresh?.(action.refresh);
1728
+ } catch (err) {
1729
+ setError(err);
1730
+ } finally {
1731
+ setLoading(false);
1732
+ }
1733
+ };
1734
+ return /* @__PURE__ */ jsxs8("span", { children: [
1735
+ /* @__PURE__ */ jsx12(Button5, { type: "button", size: "xs", minH: "28px", px: "9px", borderRadius: "6px", fontSize: "10px", loading, disabled, onClick: run, children: action.label }),
1736
+ error ? /* @__PURE__ */ jsx12(Text7, { mt: "3px", color: "#B42318", fontSize: "9px", children: messageOf2(error) }) : null
1737
+ ] });
1738
+ }
1739
+
1740
+ // src/components/internal/CoreRelatedGrid.tsx
1741
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1742
+ function CoreRelatedGrid({ tab, parent, relations, refreshToken, onRefresh }) {
1743
+ const relation = relationFrom(tab.relation, relations);
1744
+ const schemaQuery = useModelSchema(relation?.model ?? "");
1745
+ const schema = schemaQuery.data;
1746
+ const resource = useOonResource(schema?.basePath ?? `/${relation?.model?.toLowerCase() ?? "related"}s`);
1747
+ const queryClient = useQueryClient();
1748
+ const parentValue = relation ? parent[relation.parentKey ?? "_id"] : void 0;
1749
+ const key = ["oon", "related", relation?.model, relation?.foreignKey, parentValue, refreshToken];
1750
+ const query = useQuery5({ queryKey: key, enabled: !!relation && parentValue != null, queryFn: () => resource.list({ [relation.foreignKey]: parentValue, pageSize: 1e3 }) });
1751
+ const columns = useMemo4(() => (tab.columns?.length ? tab.columns : schema?.fields.slice(0, 8).map((f) => f.name) ?? []).map((column) => normalizeColumn(column, schema)).filter((column) => !column.hidden), [tab.columns, schema]);
1752
+ const [drafts, setDrafts] = useState7({});
1753
+ const [errors, setErrors] = useState7({});
1754
+ const editable = tab.type === "relatedGrid" && tab.editable && tab.editMode === "inline";
1755
+ const mutation = useMutation({ mutationFn: ({ id, values }) => resource.update(id, values), onSuccess: () => {
1756
+ queryClient.invalidateQueries({ queryKey: key });
1757
+ onRefresh?.(["self"]);
1758
+ } });
1759
+ if (!relation) return /* @__PURE__ */ jsx13(Text8, { color: "#B42318", children: "Rela\xE7\xE3o n\xE3o encontrada." });
1760
+ if (query.isLoading) return /* @__PURE__ */ jsx13(Text8, { color: "#667085", children: "Carregando..." });
1761
+ const rows = query.data?.results ?? [];
1762
+ const setDraft = (id, field, value) => setDrafts((current) => ({ ...current, [id]: { ...current[id] ?? {}, [field]: value } }));
1763
+ return /* @__PURE__ */ jsx13(Box6, { overflowX: "auto", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: /* @__PURE__ */ jsxs9(Table2.Root, { size: "sm", minW: "760px", children: [
1764
+ /* @__PURE__ */ jsx13(Table2.Header, { children: /* @__PURE__ */ jsxs9(Table2.Row, { bg: "#F4F7F9", children: [
1765
+ columns.map((c) => /* @__PURE__ */ jsx13(Table2.ColumnHeader, { fontSize: "10px", children: c.label ?? c.field }, c.field)),
1766
+ editable || tab.rowActions?.length ? /* @__PURE__ */ jsx13(Table2.ColumnHeader, { children: "A\xE7\xF5es" }) : null
1767
+ ] }) }),
1768
+ /* @__PURE__ */ jsxs9(Table2.Body, { children: [
1769
+ rows.map((row, index) => {
1770
+ const id = String(row._id ?? row.id ?? index);
1771
+ const draft = drafts[id] ?? {};
1772
+ const dirty = Object.keys(draft).length > 0;
1773
+ return /* @__PURE__ */ jsxs9(Table2.Row, { bg: dirty ? "#FFFBEB" : index % 2 ? "#FBFCFD" : "white", children: [
1774
+ columns.map((column) => {
1775
+ const value = column.field in draft ? draft[column.field] : row[column.field];
1776
+ const meta = schema?.fields.find((f) => f.name === column.field);
1777
+ const canEdit = editable && column.readonly !== true && (column.editable === true || !column.readonly);
1778
+ return /* @__PURE__ */ jsx13(Table2.Cell, { fontSize: "11px", children: canEdit ? /* @__PURE__ */ jsx13(CoreInlineEditableCell, { column, meta, value, onChange: (next) => setDraft(id, column.field, next) }) : column.display === "badgeExists" ? /* @__PURE__ */ jsx13(Badge3, { colorPalette: value ? "green" : "gray", children: value ? "Sim" : "N\xE3o" }) : formatCell(value, column.kind) }, column.field);
1779
+ }),
1780
+ editable || tab.rowActions?.length ? /* @__PURE__ */ jsx13(Table2.Cell, { children: /* @__PURE__ */ jsxs9(Flex5, { gap: "5px", align: "center", wrap: "wrap", children: [
1781
+ dirty ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
1782
+ /* @__PURE__ */ jsx13(Button6, { size: "xs", loading: mutation.isPending, onClick: () => {
1783
+ setErrors((e) => ({ ...e, [id]: void 0 }));
1784
+ mutation.mutate({ id, values: draft }, { onSuccess: () => setDrafts((d) => {
1785
+ const n = { ...d };
1786
+ delete n[id];
1787
+ return n;
1788
+ }), onError: (err) => setErrors((e) => ({ ...e, [id]: err })) });
1789
+ }, children: "Salvar" }),
1790
+ /* @__PURE__ */ jsx13(Button6, { size: "xs", variant: "outline", onClick: () => setDrafts((d) => {
1791
+ const n = { ...d };
1792
+ delete n[id];
1793
+ return n;
1794
+ }), children: "Cancelar" })
1795
+ ] }) : null,
1796
+ tab.rowActions?.map((action) => /* @__PURE__ */ jsx13(CoreRowAction, { action, row, parent, onRefresh }, action.id ?? action.label)),
1797
+ errors[id] ? /* @__PURE__ */ jsx13(Text8, { color: "#B42318", fontSize: "9px", children: "Erro ao salvar." }) : null
1798
+ ] }) }) : null
1799
+ ] }, id);
1800
+ }),
1801
+ rows.length === 0 ? /* @__PURE__ */ jsx13(Table2.Row, { children: /* @__PURE__ */ jsx13(Table2.Cell, { colSpan: columns.length + 1, children: /* @__PURE__ */ jsx13(Text8, { p: "8", textAlign: "center", color: "#98A2B3", children: "Nenhum registro relacionado." }) }) }) : null
1802
+ ] })
1803
+ ] }) });
1804
+ }
1805
+
1806
+ // src/components/internal/CoreTabbedDetail.tsx
1807
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1808
+ function coerce2(value, kind) {
1809
+ if (value === "") return void 0;
1810
+ if (["number", "currency", "currencyConverted"].includes(kind ?? "")) return Number(value);
1811
+ if (kind === "boolean") return value === "true";
1812
+ return value;
1813
+ }
1814
+ function toValue2(value) {
1815
+ return value == null ? "" : String(typeof value === "object" ? value._id ?? "" : value);
1816
+ }
1817
+ function InlineParentForm({ fields, parent, resource, onSaved }) {
1818
+ const [values, setValues] = useState8({});
1819
+ const [saving, setSaving] = useState8(false);
1820
+ const [error, setError] = useState8(null);
1821
+ useEffect5(() => setValues(Object.fromEntries(fields.map((f) => [f.field, toValue2(parent[f.field])]))), [parent, fields]);
1822
+ return /* @__PURE__ */ jsx14("form", { onSubmit: async (event) => {
1823
+ event.preventDefault();
1824
+ setSaving(true);
1825
+ setError(null);
1826
+ try {
1827
+ const payload = Object.fromEntries(fields.map((f) => [f.field, coerce2(values[f.field] ?? "", f.kind)]).filter(([, v]) => v !== void 0));
1828
+ const saved = parent._id ? await resource.update(String(parent._id), payload) : await resource.create(payload);
1829
+ onSaved(saved);
1830
+ } catch (err) {
1831
+ setError(err);
1832
+ } finally {
1833
+ setSaving(false);
1834
+ }
1835
+ }, children: /* @__PURE__ */ jsxs10(Stack3, { gap: 4, children: [
1836
+ error ? /* @__PURE__ */ jsx14(Text9, { color: "#B42318", fontSize: "11px", children: "N\xE3o foi poss\xEDvel salvar." }) : null,
1837
+ /* @__PURE__ */ jsx14(SimpleGrid3, { columns: { base: 1, md: 2 }, gap: 3, children: fields.map((field) => /* @__PURE__ */ jsxs10(Box7, { children: [
1838
+ /* @__PURE__ */ jsx14(Text9, { as: "label", display: "block", mb: "5px", fontSize: "11px", fontWeight: "600", children: fieldLabel({ name: field.field, label: field.label }) }),
1839
+ field.kind === "boolean" ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
1840
+ /* @__PURE__ */ jsxs10(NativeSelect4.Field, { value: values[field.field] ?? "", onChange: (e) => setValues((v) => ({ ...v, [field.field]: e.currentTarget.value })), children: [
1841
+ /* @__PURE__ */ jsx14("option", { value: "", children: "\u2014" }),
1842
+ /* @__PURE__ */ jsx14("option", { value: "true", children: "Sim" }),
1843
+ /* @__PURE__ */ jsx14("option", { value: "false", children: "N\xE3o" })
1844
+ ] }),
1845
+ /* @__PURE__ */ jsx14(NativeSelect4.Indicator, {})
1846
+ ] }) : /* @__PURE__ */ jsx14(Input5, { size: "sm", type: field.kind === "date" ? "date" : ["number", "currency"].includes(field.kind ?? "") ? "number" : "text", value: values[field.field] ?? "", onChange: (e) => setValues((v) => ({ ...v, [field.field]: e.currentTarget.value })) })
1847
+ ] }, field.field)) }),
1848
+ /* @__PURE__ */ jsx14(Flex6, { justify: "flex-end", children: /* @__PURE__ */ jsx14(Button7, { type: "submit", colorPalette: "brand", loading: saving, children: "Salvar dados principais" }) })
1849
+ ] }) });
1850
+ }
1851
+ function CoreTabbedDetail({ tabs, activeTab, onTabChange, parent, formFields, resource, relations, refreshTokens, onRefresh, onParentSaved }) {
1852
+ const active = tabs.find((tab) => tab.id === activeTab) ?? tabs[0];
1853
+ return /* @__PURE__ */ jsxs10(Stack3, { gap: 4, children: [
1854
+ /* @__PURE__ */ jsx14(Flex6, { gap: 2, borderBottomWidth: "1px", borderColor: "#E5E9ED", overflowX: "auto", children: tabs.map((tab) => {
1855
+ const disabled = !parent?._id && (tab.type === "relatedGrid" || tab.type === "readonlyGrid" || tab.type === "summary");
1856
+ return /* @__PURE__ */ jsx14(Button7, { type: "button", variant: active?.id === tab.id ? "solid" : "ghost", colorPalette: active?.id === tab.id ? "brand" : void 0, disabled, onClick: () => onTabChange(tab.id), children: tab.label }, tab.id);
1857
+ }) }),
1858
+ /* @__PURE__ */ jsx14(Box7, { children: !active ? null : active.type === "summary" && parent ? /* @__PURE__ */ jsx14(CoreSummaryCards, { cards: active.cards, parent, relations }) : active.type === "form" ? /* @__PURE__ */ jsx14(InlineParentForm, { fields: fieldsForTab(formFields, active.fields ?? active.groups?.flatMap((g) => g.fields)), parent: parent ?? {}, resource, onSaved: onParentSaved }) : (active.type === "relatedGrid" || active.type === "readonlyGrid") && parent ? /* @__PURE__ */ jsx14(CoreRelatedGrid, { tab: active, parent, relations, refreshToken: refreshTokens[active.id], onRefresh }) : active.type === "customComponent" ? /* @__PURE__ */ jsxs10(Text9, { color: "#667085", children: [
1859
+ "Componente customizado: ",
1860
+ active.component
1861
+ ] }) : /* @__PURE__ */ jsx14(Text9, { color: "#667085", children: "Salve o registro principal para liberar esta aba." }) })
1862
+ ] });
1863
+ }
1864
+
1865
+ // src/components/internal/CoreDetailModal.tsx
1866
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1867
+ function CoreDetailModal({ model, title, config, recordId, initialRecord, initialTab, relations, onClose, onSaved }) {
1868
+ const schemaQuery = useModelSchema(model);
1869
+ const schema = schemaQuery.data;
1870
+ const resource = useOonResource(schema?.basePath ?? `/${model.toLowerCase()}s`);
1871
+ const queryClient = useQueryClient2();
1872
+ const [parent, setParent] = useState9(initialRecord);
1873
+ const [activeTab, setActiveTab] = useState9(initialTab ?? config.defaultTab ?? config.tabs[0]?.id ?? "dados");
1874
+ const [refreshTokens, setRefreshTokens] = useState9({});
1875
+ const parentQuery = useQuery6({ queryKey: ["oon", "detail", model, recordId], enabled: !!recordId, queryFn: () => resource.get(recordId) });
1876
+ useEffect6(() => {
1877
+ if (parentQuery.data) setParent(parentQuery.data);
1878
+ }, [parentQuery.data]);
1879
+ const formFields = useMemo5(() => schema ? formFieldsFromMeta(schema.fields) : [], [schema]);
1880
+ const refresh = (targets) => {
1881
+ const list = targets?.length ? targets : ["self"];
1882
+ if (list.includes("parent") || list.includes("all")) {
1883
+ if (recordId) queryClient.invalidateQueries({ queryKey: ["oon", "detail", model, recordId] });
1884
+ onSaved?.();
1885
+ }
1886
+ setRefreshTokens((current) => {
1887
+ const next = { ...current };
1888
+ for (const target of list) {
1889
+ if (target === "all") config.tabs.forEach((tab) => next[tab.id] = (next[tab.id] ?? 0) + 1);
1890
+ else if (target !== "parent") next[target === "self" ? activeTab : target] = (next[target === "self" ? activeTab : target] ?? 0) + 1;
1891
+ }
1892
+ return next;
1893
+ });
1894
+ };
1895
+ const width = config.size === "full" ? "98vw" : config.size === "md" ? "760px" : config.size === "lg" ? "980px" : "1180px";
1896
+ const displayTitle = parent?.[config.titleField ?? ""] ? String(parent[config.titleField ?? ""]) : title;
1897
+ return /* @__PURE__ */ jsx15(Flex7, { position: "fixed", inset: 0, zIndex: 1e3, align: "center", justify: "center", p: 4, bg: "rgba(15,23,42,.48)", children: /* @__PURE__ */ jsxs11(Box8, { role: "dialog", "aria-modal": "true", w: `min(${width}, 98vw)`, maxH: "94vh", overflow: "hidden", bg: "white", borderRadius: "14px", boxShadow: "0 24px 70px rgba(15,23,42,.24)", children: [
1898
+ /* @__PURE__ */ jsxs11(Flex7, { minH: "72px", px: "20px", align: "center", justify: "space-between", borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
1899
+ /* @__PURE__ */ jsxs11(Box8, { children: [
1900
+ /* @__PURE__ */ jsx15(Text10, { color: "#0474AF", fontSize: "10px", fontWeight: "700", textTransform: "uppercase", children: "Detalhe" }),
1901
+ /* @__PURE__ */ jsx15(Heading3, { size: "md", children: recordId ? displayTitle : `Novo ${title}` })
1902
+ ] }),
1903
+ /* @__PURE__ */ jsx15(Button8, { onClick: onClose, children: "Fechar" })
1904
+ ] }),
1905
+ /* @__PURE__ */ jsx15(Box8, { maxH: "calc(94vh - 73px)", p: "20px", overflowY: "auto", children: schemaQuery.isLoading || parentQuery.isLoading ? /* @__PURE__ */ jsx15(Text10, { children: "Carregando..." }) : /* @__PURE__ */ jsx15(CoreTabbedDetail, { tabs: config.tabs, activeTab, onTabChange: setActiveTab, parent, formFields, resource, relations, refreshTokens, onRefresh: refresh, onParentSaved: (saved) => {
1906
+ setParent(saved);
1907
+ onSaved?.();
1908
+ refresh(["parent"]);
1909
+ } }) })
1910
+ ] }) });
1911
+ }
1912
+
1519
1913
  // src/components/CoreCollection.tsx
1520
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1521
- function CoreCollection({ model, label, section = "Cole\xE7\xE3o", mode = "dynamic", endpoint, columns, form, importExport }) {
1914
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1915
+ function CoreCollection({ model, label, section = "Cole\xE7\xE3o", mode = "dynamic", endpoint, columns, form, importExport, list, relations, detailModal }) {
1522
1916
  const needsSchema = mode !== "full" || !columns || !form || !endpoint;
1523
1917
  const schemaQuery = useModelSchema(needsSchema ? model : "");
1524
1918
  const schema = schemaQuery.data;
1525
1919
  const basePath = endpoint ?? schema?.basePath ?? `/${model.toLowerCase()}s`;
1526
- const resolvedColumns = columns ?? (schema ? columnsFromMeta(schema.fields) : []);
1920
+ const resolvedColumns = (list?.columns?.length ? list.columns.map((column) => normalizeColumn(column, schema)) : columns) ?? (schema ? columnsFromMeta(schema.fields) : []);
1527
1921
  const resolvedForm = form ?? (schema ? formFieldsFromMeta(schema.fields) : []);
1528
1922
  const resource = useOonResource(basePath);
1529
- const queryClient = useQueryClient();
1530
- const [formState, setFormState] = useState6({ open: false });
1531
- const [formError, setFormError] = useState6(null);
1923
+ const queryClient = useQueryClient3();
1924
+ const [formState, setFormState] = useState10({ open: false });
1925
+ const [detailState, setDetailState] = useState10({ open: false });
1926
+ const [formError, setFormError] = useState10(null);
1532
1927
  const invalidate = () => queryClient.invalidateQueries({ queryKey: ["oon", "list", basePath] });
1533
- const saveMutation = useMutation({
1928
+ const saveMutation = useMutation2({
1534
1929
  mutationFn: (values) => {
1535
1930
  const editingRow = formState.open ? formState.row : void 0;
1536
1931
  const id = editingRow?._id;
@@ -1543,39 +1938,52 @@ function CoreCollection({ model, label, section = "Cole\xE7\xE3o", mode = "dynam
1543
1938
  },
1544
1939
  onError: (error) => setFormError(error)
1545
1940
  });
1546
- const deleteMutation = useMutation({
1941
+ const deleteMutation = useMutation2({
1547
1942
  mutationFn: (row) => resource.delete(row._id),
1548
1943
  onSuccess: invalidate
1549
1944
  });
1550
- if (needsSchema && schemaQuery.isLoading) return /* @__PURE__ */ jsx10(LoadingScreen, {});
1551
- if (needsSchema && schemaQuery.isError) return /* @__PURE__ */ jsx10(ErrorState, { error: schemaQuery.error });
1945
+ if (needsSchema && schemaQuery.isLoading) return /* @__PURE__ */ jsx16(LoadingScreen, {});
1946
+ if (needsSchema && schemaQuery.isError) return /* @__PURE__ */ jsx16(ErrorState, { error: schemaQuery.error });
1552
1947
  const title = label ?? schema?.name ?? model;
1553
- return /* @__PURE__ */ jsxs6(Stack3, { gap: 5, children: [
1554
- /* @__PURE__ */ jsxs6(Box5, { children: [
1555
- /* @__PURE__ */ jsx10(Text6, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: section }),
1556
- /* @__PURE__ */ jsx10(Heading3, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: title }),
1557
- /* @__PURE__ */ jsx10(Text6, { mt: 1, fontSize: "13px", color: "gray.500", children: "Consulte, filtre e mantenha os registros desta opera\xE7\xE3o." })
1948
+ return /* @__PURE__ */ jsxs12(Stack4, { gap: 5, children: [
1949
+ /* @__PURE__ */ jsxs12(Box9, { children: [
1950
+ /* @__PURE__ */ jsx16(Text11, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: section }),
1951
+ /* @__PURE__ */ jsx16(Heading4, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: title }),
1952
+ /* @__PURE__ */ jsx16(Text11, { mt: 1, fontSize: "13px", color: "gray.500", children: "Consulte, filtre e mantenha os registros desta opera\xE7\xE3o." })
1558
1953
  ] }),
1559
- /* @__PURE__ */ jsx10(
1954
+ /* @__PURE__ */ jsx16(
1560
1955
  DataGrid,
1561
1956
  {
1562
1957
  resource,
1563
1958
  resourceKey: basePath,
1564
1959
  columns: resolvedColumns,
1960
+ filters: list?.filters,
1565
1961
  onCreate: () => {
1566
1962
  setFormError(null);
1567
- setFormState({ open: true });
1963
+ if (detailModal?.enabled) setDetailState({ open: true });
1964
+ else setFormState({ open: true });
1568
1965
  },
1569
1966
  onEdit: (row) => {
1570
1967
  setFormError(null);
1571
- setFormState({ open: true, row });
1968
+ if (detailModal?.enabled) setDetailState({ open: true, row });
1969
+ else setFormState({ open: true, row });
1572
1970
  },
1573
1971
  onDelete: (row) => {
1574
1972
  if (window.confirm("Excluir este registro?")) deleteMutation.mutate(row);
1575
- }
1973
+ },
1974
+ renderRowActions: list?.rowActions?.length ? (row) => list.rowActions?.map((action) => /* @__PURE__ */ jsx16(
1975
+ CoreRowAction,
1976
+ {
1977
+ action,
1978
+ row,
1979
+ onOpenDetail: (selected, initialTab) => setDetailState({ open: true, row: selected, initialTab }),
1980
+ onRefresh: invalidate
1981
+ },
1982
+ action.id ?? action.label
1983
+ )) : void 0
1576
1984
  }
1577
1985
  ),
1578
- formState.open ? /* @__PURE__ */ jsx10(
1986
+ formState.open ? /* @__PURE__ */ jsx16(
1579
1987
  DynamicForm,
1580
1988
  {
1581
1989
  title: formState.row ? `Editar ${title}` : `Novo ${title}`,
@@ -1595,14 +2003,28 @@ function CoreCollection({ model, label, section = "Cole\xE7\xE3o", mode = "dynam
1595
2003
  }
1596
2004
  }
1597
2005
  ) : null,
1598
- importExport ? null : null
2006
+ importExport ? null : null,
2007
+ detailState.open && detailModal?.enabled ? /* @__PURE__ */ jsx16(
2008
+ CoreDetailModal,
2009
+ {
2010
+ model,
2011
+ title,
2012
+ config: detailModal,
2013
+ recordId: detailState.row?._id,
2014
+ initialRecord: detailState.row,
2015
+ initialTab: detailState.initialTab,
2016
+ relations,
2017
+ onClose: () => setDetailState({ open: false }),
2018
+ onSaved: invalidate
2019
+ }
2020
+ ) : null
1599
2021
  ] });
1600
2022
  }
1601
2023
 
1602
2024
  // src/components/CoreDocument.tsx
1603
- import { jsx as jsx11 } from "react/jsx-runtime";
2025
+ import { jsx as jsx17 } from "react/jsx-runtime";
1604
2026
  function CoreDocument({ model, label, endpoint, columns, form }) {
1605
- return /* @__PURE__ */ jsx11(
2027
+ return /* @__PURE__ */ jsx17(
1606
2028
  CoreCollection,
1607
2029
  {
1608
2030
  model,
@@ -1616,10 +2038,10 @@ function CoreDocument({ model, label, endpoint, columns, form }) {
1616
2038
  }
1617
2039
 
1618
2040
  // src/components/CorePipeline.tsx
1619
- import { useState as useState7 } from "react";
1620
- import { Badge as Badge2, Box as Box6, Button as Button5, Flex as Flex5, Heading as Heading4, Stack as Stack4, Text as Text7 } from "@chakra-ui/react";
1621
- import { useMutation as useMutation2, useQuery as useQuery4, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1622
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
2041
+ import { useState as useState11 } from "react";
2042
+ import { Badge as Badge4, Box as Box10, Button as Button9, Flex as Flex8, Heading as Heading5, Stack as Stack5, Text as Text12 } from "@chakra-ui/react";
2043
+ import { useMutation as useMutation3, useQuery as useQuery7, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2044
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1623
2045
  function ticketId(row) {
1624
2046
  const id = row._id ?? row.id;
1625
2047
  return id == null ? void 0 : String(id);
@@ -1629,15 +2051,15 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1629
2051
  const schema = schemaQuery.data;
1630
2052
  const basePath = endpoint ?? schema?.basePath ?? `/${model.toLowerCase()}s`;
1631
2053
  const resource = useOonResource(basePath);
1632
- const queryClient = useQueryClient2();
1633
- const [selectedTicket, setSelectedTicket] = useState7(null);
1634
- const [formError, setFormError] = useState7(null);
1635
- const listQuery = useQuery4({
2054
+ const queryClient = useQueryClient4();
2055
+ const [selectedTicket, setSelectedTicket] = useState11(null);
2056
+ const [formError, setFormError] = useState11(null);
2057
+ const listQuery = useQuery7({
1636
2058
  queryKey: ["oon", "pipeline", basePath],
1637
2059
  queryFn: () => resource.list({ pageSize: 200 }),
1638
2060
  enabled: !!schema
1639
2061
  });
1640
- const saveMutation = useMutation2({
2062
+ const saveMutation = useMutation3({
1641
2063
  mutationFn: (values) => {
1642
2064
  const id = selectedTicket ? ticketId(selectedTicket) : void 0;
1643
2065
  if (!id) throw new Error("N\xE3o foi poss\xEDvel identificar o ticket selecionado.");
@@ -1650,9 +2072,9 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1650
2072
  },
1651
2073
  onError: (error) => setFormError(error)
1652
2074
  });
1653
- if (schemaQuery.isLoading || listQuery.isLoading) return /* @__PURE__ */ jsx12(LoadingScreen, {});
1654
- if (schemaQuery.isError) return /* @__PURE__ */ jsx12(ErrorState, { error: schemaQuery.error });
1655
- if (listQuery.isError) return /* @__PURE__ */ jsx12(ErrorState, { error: listQuery.error });
2075
+ if (schemaQuery.isLoading || listQuery.isLoading) return /* @__PURE__ */ jsx18(LoadingScreen, {});
2076
+ if (schemaQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: schemaQuery.error });
2077
+ if (listQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: listQuery.error });
1656
2078
  const stageFieldMeta = schema?.fields.find((field) => field.name === stageField);
1657
2079
  const resolvedStages = stages ?? (stageFieldMeta?.options ?? []).map((option) => ({ id: option, label: option }));
1658
2080
  const title = titleField ?? schema?.fields.find((field) => field.kind === "string")?.name ?? schema?.searchable[0] ?? "_id";
@@ -1666,16 +2088,16 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1666
2088
  if (!byStage.has(key)) byStage.set(key, []);
1667
2089
  byStage.get(key).push(row);
1668
2090
  }
1669
- return /* @__PURE__ */ jsxs7(Stack4, { gap: 5, children: [
1670
- /* @__PURE__ */ jsxs7(Box6, { children: [
1671
- /* @__PURE__ */ jsx12(Text7, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: "Esteira de processo" }),
1672
- /* @__PURE__ */ jsx12(Heading4, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: label ?? schema?.name ?? model }),
1673
- /* @__PURE__ */ jsx12(Text7, { mt: 1, fontSize: "13px", color: "gray.500", children: "Acompanhe os tickets por etapa e visualize os principais dados de cada item." })
2091
+ return /* @__PURE__ */ jsxs13(Stack5, { gap: 5, children: [
2092
+ /* @__PURE__ */ jsxs13(Box10, { children: [
2093
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", fontWeight: "700", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", mb: 1, children: "Esteira de processo" }),
2094
+ /* @__PURE__ */ jsx18(Heading5, { size: "lg", color: "#24323A", letterSpacing: "-0.02em", children: label ?? schema?.name ?? model }),
2095
+ /* @__PURE__ */ jsx18(Text12, { mt: 1, fontSize: "13px", color: "gray.500", children: "Acompanhe os tickets por etapa e visualize os principais dados de cada item." })
1674
2096
  ] }),
1675
- /* @__PURE__ */ jsx12(Flex5, { gap: 4, align: "stretch", overflowX: "auto", pb: 3, minH: "420px", children: Array.from(byStage.entries()).map(([stageId, items]) => {
2097
+ /* @__PURE__ */ jsx18(Flex8, { gap: 4, align: "stretch", overflowX: "auto", pb: 3, minH: "420px", children: Array.from(byStage.entries()).map(([stageId, items]) => {
1676
2098
  const stageLabel = resolvedStages.find((stage) => stage.id === stageId)?.label ?? (stageId || "Sem etapa");
1677
- return /* @__PURE__ */ jsxs7(
1678
- Box6,
2099
+ return /* @__PURE__ */ jsxs13(
2100
+ Box10,
1679
2101
  {
1680
2102
  minW: "300px",
1681
2103
  maxW: "340px",
@@ -1686,14 +2108,14 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1686
2108
  borderWidth: "1px",
1687
2109
  borderColor: "#DDE3E7",
1688
2110
  children: [
1689
- /* @__PURE__ */ jsxs7(Flex5, { align: "center", justify: "space-between", mb: 3, px: 1, children: [
1690
- /* @__PURE__ */ jsx12(Text7, { fontWeight: "700", fontSize: "12px", color: "#33434C", textTransform: "uppercase", letterSpacing: "0.03em", children: stageLabel }),
1691
- /* @__PURE__ */ jsx12(Badge2, { colorPalette: "brand", variant: "solid", borderRadius: "full", minW: "24px", justifyContent: "center", children: items.length })
2111
+ /* @__PURE__ */ jsxs13(Flex8, { align: "center", justify: "space-between", mb: 3, px: 1, children: [
2112
+ /* @__PURE__ */ jsx18(Text12, { fontWeight: "700", fontSize: "12px", color: "#33434C", textTransform: "uppercase", letterSpacing: "0.03em", children: stageLabel }),
2113
+ /* @__PURE__ */ jsx18(Badge4, { colorPalette: "brand", variant: "solid", borderRadius: "full", minW: "24px", justifyContent: "center", children: items.length })
1692
2114
  ] }),
1693
- /* @__PURE__ */ jsx12(Stack4, { gap: 2, children: items.length === 0 ? /* @__PURE__ */ jsx12(Box6, { borderWidth: "1px", borderStyle: "dashed", borderColor: "#C8D0D5", borderRadius: "10px", p: 5, textAlign: "center", children: /* @__PURE__ */ jsx12(Text7, { fontSize: "12px", color: "gray.500", children: "Nenhum ticket nesta etapa." }) }) : items.map((row, index) => {
2115
+ /* @__PURE__ */ jsx18(Stack5, { gap: 2, children: items.length === 0 ? /* @__PURE__ */ jsx18(Box10, { borderWidth: "1px", borderStyle: "dashed", borderColor: "#C8D0D5", borderRadius: "10px", p: 5, textAlign: "center", children: /* @__PURE__ */ jsx18(Text12, { fontSize: "12px", color: "gray.500", children: "Nenhum ticket nesta etapa." }) }) : items.map((row, index) => {
1694
2116
  const ticketTitle = formatCell(row[title], "string");
1695
- return /* @__PURE__ */ jsxs7(
1696
- Button5,
2117
+ return /* @__PURE__ */ jsxs13(
2118
+ Button9,
1697
2119
  {
1698
2120
  type: "button",
1699
2121
  variant: "plain",
@@ -1718,10 +2140,10 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1718
2140
  _hover: { borderColor: "brand.300", transform: "translateY(-1px)", boxShadow: "0 7px 18px rgba(7, 38, 46, 0.09)" },
1719
2141
  _focusVisible: { borderColor: "brand.500", boxShadow: "0 0 0 3px rgba(4, 116, 175, 0.16)" },
1720
2142
  children: [
1721
- /* @__PURE__ */ jsx12(Text7, { fontSize: "13px", fontWeight: "700", color: "#24323A", mb: 2, lineClamp: 2, children: ticketTitle }),
1722
- /* @__PURE__ */ jsx12(Stack4, { gap: 1, children: detailFields.map((field) => /* @__PURE__ */ jsxs7(Flex5, { gap: 2, align: "baseline", justify: "space-between", children: [
1723
- /* @__PURE__ */ jsx12(Text7, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.03em", children: fieldLabel(field) }),
1724
- /* @__PURE__ */ jsx12(Text7, { fontSize: "11px", color: "#46545C", fontWeight: "500", textAlign: "right", lineClamp: 1, children: formatCell(row[field.name], field.kind) })
2143
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "13px", fontWeight: "700", color: "#24323A", mb: 2, lineClamp: 2, children: ticketTitle }),
2144
+ /* @__PURE__ */ jsx18(Stack5, { gap: 1, children: detailFields.map((field) => /* @__PURE__ */ jsxs13(Flex8, { gap: 2, align: "baseline", justify: "space-between", children: [
2145
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.03em", children: fieldLabel(field) }),
2146
+ /* @__PURE__ */ jsx18(Text12, { fontSize: "11px", color: "#46545C", fontWeight: "500", textAlign: "right", lineClamp: 1, children: formatCell(row[field.name], field.kind) })
1725
2147
  ] }, field.name)) })
1726
2148
  ]
1727
2149
  },
@@ -1733,7 +2155,7 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1733
2155
  stageId
1734
2156
  );
1735
2157
  }) }),
1736
- selectedTicket ? /* @__PURE__ */ jsx12(
2158
+ selectedTicket ? /* @__PURE__ */ jsx18(
1737
2159
  DynamicForm,
1738
2160
  {
1739
2161
  title: `Editar ${schema?.singular ?? label ?? model}`,
@@ -1758,9 +2180,9 @@ function CorePipeline({ model, label, endpoint, stageField = "status", stages, t
1758
2180
  }
1759
2181
 
1760
2182
  // src/components/CoreDashboard.tsx
1761
- import { Box as Box7, Heading as Heading5, SimpleGrid as SimpleGrid2, Stack as Stack5, Text as Text8 } from "@chakra-ui/react";
2183
+ import { Box as Box11, Heading as Heading6, SimpleGrid as SimpleGrid4, Stack as Stack6, Text as Text13 } from "@chakra-ui/react";
1762
2184
  import { useQueries } from "@tanstack/react-query";
1763
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2185
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
1764
2186
  function CoreDashboard({ label = "Dashboard", widgets = [] }) {
1765
2187
  const { resource } = useOonApi();
1766
2188
  const queries = useQueries({
@@ -1777,17 +2199,17 @@ function CoreDashboard({ label = "Dashboard", widgets = [] }) {
1777
2199
  }))
1778
2200
  });
1779
2201
  let queryIdx = 0;
1780
- return /* @__PURE__ */ jsxs8(Stack5, { gap: 6, children: [
1781
- /* @__PURE__ */ jsx13(Heading5, { size: "lg", children: label }),
1782
- /* @__PURE__ */ jsx13(SimpleGrid2, { columns: { base: 1, md: 2, lg: 3 }, gap: 4, children: widgets.map((w) => {
2202
+ return /* @__PURE__ */ jsxs14(Stack6, { gap: 6, children: [
2203
+ /* @__PURE__ */ jsx19(Heading6, { size: "lg", children: label }),
2204
+ /* @__PURE__ */ jsx19(SimpleGrid4, { columns: { base: 1, md: 2, lg: 3 }, gap: 4, children: widgets.map((w) => {
1783
2205
  if (w.kind === "custom" && w.render) {
1784
- return /* @__PURE__ */ jsx13(Box7, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 5, children: w.render() }, w.id);
2206
+ return /* @__PURE__ */ jsx19(Box11, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 5, children: w.render() }, w.id);
1785
2207
  }
1786
2208
  const q = queries[queryIdx++];
1787
2209
  const value = q?.isLoading ? "\u2026" : q?.isError ? "\u2014" : formatWidget(q?.data, w.kind, w.field);
1788
- return /* @__PURE__ */ jsxs8(Box7, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 5, children: [
1789
- /* @__PURE__ */ jsx13(Text8, { fontSize: "sm", color: "gray.500", children: w.label }),
1790
- /* @__PURE__ */ jsx13(Heading5, { size: "xl", mt: 1, children: value })
2210
+ return /* @__PURE__ */ jsxs14(Box11, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 5, children: [
2211
+ /* @__PURE__ */ jsx19(Text13, { fontSize: "sm", color: "gray.500", children: w.label }),
2212
+ /* @__PURE__ */ jsx19(Heading6, { size: "xl", mt: 1, children: value })
1791
2213
  ] }, w.id);
1792
2214
  }) })
1793
2215
  ] });
@@ -1801,22 +2223,22 @@ function formatWidget(value, kind, field) {
1801
2223
  }
1802
2224
 
1803
2225
  // src/components/ui-v2/CorePage.tsx
1804
- import { Box as Box10, Heading as Heading7, Stack as Stack6, Text as Text11 } from "@chakra-ui/react";
2226
+ import { Box as Box14, Heading as Heading8, Stack as Stack7, Text as Text16 } from "@chakra-ui/react";
1805
2227
 
1806
2228
  // src/security/PermissionGate.tsx
1807
- import { Fragment, jsx as jsx14 } from "react/jsx-runtime";
2229
+ import { Fragment as Fragment3, jsx as jsx20 } from "react/jsx-runtime";
1808
2230
  function PermissionGate({
1809
2231
  permission,
1810
2232
  fallback = null,
1811
2233
  children
1812
2234
  }) {
1813
2235
  const { hasPermission } = useOonAuth();
1814
- return /* @__PURE__ */ jsx14(Fragment, { children: hasPermission(permission) ? children : fallback });
2236
+ return /* @__PURE__ */ jsx20(Fragment3, { children: hasPermission(permission) ? children : fallback });
1815
2237
  }
1816
2238
 
1817
2239
  // src/app/componentRegistry.tsx
1818
- import { Box as Box8, Text as Text9 } from "@chakra-ui/react";
1819
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2240
+ import { Box as Box12, Text as Text14 } from "@chakra-ui/react";
2241
+ import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1820
2242
  var PREFIX_BUCKETS = {
1821
2243
  "custom": "pageComponents",
1822
2244
  "fields": "fieldRenderers",
@@ -1836,12 +2258,12 @@ function resolveComponent(registry, key, bucket) {
1836
2258
  return registry?.[targetBucket]?.[normalized] ?? registry?.[targetBucket]?.[key] ?? null;
1837
2259
  }
1838
2260
  function MissingRenderer({ renderer, children }) {
1839
- if (import.meta.env?.MODE === "production") return /* @__PURE__ */ jsx15(Fragment2, { children: children ?? null });
1840
- return /* @__PURE__ */ jsxs9(Box8, { borderWidth: "1px", borderStyle: "dashed", borderColor: "orange.300", bg: "orange.50", color: "orange.900", borderRadius: "md", p: 3, children: [
1841
- /* @__PURE__ */ jsx15(Text9, { fontSize: "sm", fontWeight: "600", children: "Renderer n\xE3o encontrado" }),
1842
- /* @__PURE__ */ jsxs9(Text9, { fontSize: "xs", children: [
2261
+ if (import.meta.env?.MODE === "production") return /* @__PURE__ */ jsx21(Fragment4, { children: children ?? null });
2262
+ return /* @__PURE__ */ jsxs15(Box12, { borderWidth: "1px", borderStyle: "dashed", borderColor: "orange.300", bg: "orange.50", color: "orange.900", borderRadius: "md", p: 3, children: [
2263
+ /* @__PURE__ */ jsx21(Text14, { fontSize: "sm", fontWeight: "600", children: "Renderer n\xE3o encontrado" }),
2264
+ /* @__PURE__ */ jsxs15(Text14, { fontSize: "xs", children: [
1843
2265
  "Registre a chave ",
1844
- renderer ? /* @__PURE__ */ jsx15("code", { children: renderer }) : "solicitada",
2266
+ renderer ? /* @__PURE__ */ jsx21("code", { children: renderer }) : "solicitada",
1845
2267
  " no registry da UI."
1846
2268
  ] }),
1847
2269
  children
@@ -1849,61 +2271,65 @@ function MissingRenderer({ renderer, children }) {
1849
2271
  }
1850
2272
 
1851
2273
  // src/components/ui-v2/CorePrimitives.tsx
1852
- import { Box as Box9, Button as Button6, Flex as Flex6, Heading as Heading6, Spinner as Spinner3, Text as Text10 } from "@chakra-ui/react";
1853
- import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2274
+ import { Box as Box13, Button as Button10, Flex as Flex9, Heading as Heading7, Spinner as Spinner3, Text as Text15 } from "@chakra-ui/react";
2275
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
1854
2276
  function CorePage({ children }) {
1855
- return /* @__PURE__ */ jsx16(Box9, { children });
2277
+ return /* @__PURE__ */ jsx22(Box13, { children });
1856
2278
  }
1857
2279
  function CorePageHeader({ title, description, actions }) {
1858
- return /* @__PURE__ */ jsxs10(Flex6, { align: "start", justify: "space-between", gap: 4, mb: 6, children: [
1859
- /* @__PURE__ */ jsxs10(Box9, { children: [
1860
- title ? /* @__PURE__ */ jsx16(Heading6, { size: "lg", children: title }) : null,
1861
- description ? /* @__PURE__ */ jsx16(Text10, { color: "gray.600", mt: 1, children: description }) : null
2280
+ return /* @__PURE__ */ jsxs16(Flex9, { align: "start", justify: "space-between", gap: 4, mb: 6, children: [
2281
+ /* @__PURE__ */ jsxs16(Box13, { children: [
2282
+ title ? /* @__PURE__ */ jsx22(Heading7, { size: "lg", children: title }) : null,
2283
+ description ? /* @__PURE__ */ jsx22(Text15, { color: "gray.600", mt: 1, children: description }) : null
1862
2284
  ] }),
1863
2285
  actions
1864
2286
  ] });
1865
2287
  }
1866
2288
  function CoreToolbar({ children }) {
1867
- return /* @__PURE__ */ jsx16(Flex6, { align: "center", gap: 2, mb: 4, children });
2289
+ return /* @__PURE__ */ jsx22(Flex9, { align: "center", gap: 2, mb: 4, children });
1868
2290
  }
1869
2291
  function CoreDataGrid(props) {
1870
- return /* @__PURE__ */ jsx16(CoreCollection, { ...props });
2292
+ return /* @__PURE__ */ jsx22(CoreCollection, { ...props });
1871
2293
  }
1872
2294
  function CoreCards(props) {
1873
- return /* @__PURE__ */ jsx16(CoreCollection, { model: props.model, mode: "minimal", label: props.model });
2295
+ return /* @__PURE__ */ jsx22(CoreCollection, { model: props.model, mode: "minimal", label: props.model });
1874
2296
  }
1875
2297
  function CoreForm(props) {
1876
- return /* @__PURE__ */ jsx16(Box9, { children: props.children });
2298
+ return /* @__PURE__ */ jsx22(Box13, { children: props.children });
1877
2299
  }
1878
2300
  function CoreField({ label, children }) {
1879
- return /* @__PURE__ */ jsxs10(Box9, { children: [
1880
- /* @__PURE__ */ jsx16(Text10, { fontSize: "sm", fontWeight: "600", children: label }),
2301
+ return /* @__PURE__ */ jsxs16(Box13, { children: [
2302
+ /* @__PURE__ */ jsx22(Text15, { fontSize: "sm", fontWeight: "600", children: label }),
1881
2303
  children
1882
2304
  ] });
1883
2305
  }
1884
2306
  function CoreRelationField(props) {
1885
- return /* @__PURE__ */ jsx16(CoreField, { ...props });
2307
+ return /* @__PURE__ */ jsx22(CoreField, { ...props });
1886
2308
  }
1887
2309
  function CoreActions({ children }) {
1888
- return /* @__PURE__ */ jsx16(Flex6, { gap: 2, children });
2310
+ return /* @__PURE__ */ jsx22(Flex9, { gap: 2, children });
1889
2311
  }
1890
2312
  function CoreEmptyState({ title = "Nenhum dado encontrado", actionLabel, onAction }) {
1891
- return /* @__PURE__ */ jsxs10(Box9, { textAlign: "center", py: 10, children: [
1892
- /* @__PURE__ */ jsx16(Text10, { children: title }),
1893
- actionLabel ? /* @__PURE__ */ jsx16(Button6, { mt: 3, onClick: onAction, children: actionLabel }) : null
2313
+ return /* @__PURE__ */ jsxs16(Box13, { textAlign: "center", py: 10, children: [
2314
+ /* @__PURE__ */ jsx22(Text15, { children: title }),
2315
+ actionLabel ? /* @__PURE__ */ jsx22(Button10, { mt: 3, onClick: onAction, children: actionLabel }) : null
1894
2316
  ] });
1895
2317
  }
1896
2318
  function CoreLoadingState({ label = "Carregando..." }) {
1897
- return /* @__PURE__ */ jsxs10(Flex6, { align: "center", gap: 3, children: [
1898
- /* @__PURE__ */ jsx16(Spinner3, { size: "sm" }),
1899
- /* @__PURE__ */ jsx16(Text10, { children: label })
2319
+ return /* @__PURE__ */ jsxs16(Flex9, { align: "center", gap: 3, children: [
2320
+ /* @__PURE__ */ jsx22(Spinner3, { size: "sm" }),
2321
+ /* @__PURE__ */ jsx22(Text15, { children: label })
1900
2322
  ] });
1901
2323
  }
1902
2324
 
1903
2325
  // src/components/ui-v2/CorePage.tsx
1904
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2326
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
1905
2327
  function renderMarkdown(content) {
1906
- return content.split(/\n{2,}/).map((paragraph, index) => /* @__PURE__ */ jsx17(Text11, { whiteSpace: "pre-wrap", children: paragraph }, index));
2328
+ return content.split(/\n{2,}/).map((paragraph, index) => /* @__PURE__ */ jsx23(Text16, { whiteSpace: "pre-wrap", children: paragraph }, index));
2329
+ }
2330
+ function requiredAccess(source) {
2331
+ const values = [...source.permissions ?? [], ...source.capabilities ?? []].filter(Boolean);
2332
+ return values.length ? values : void 0;
1907
2333
  }
1908
2334
  function CoreBlock({ block, registry }) {
1909
2335
  if (block.hidden) return null;
@@ -1911,41 +2337,45 @@ function CoreBlock({ block, registry }) {
1911
2337
  switch (block.type) {
1912
2338
  case "custom": {
1913
2339
  const Component = resolveComponent(registry, block.component, "pageComponents");
1914
- return Component ? /* @__PURE__ */ jsx17(Component, { block, ...block.props }) : /* @__PURE__ */ jsx17(MissingRenderer, { renderer: block.component });
2340
+ return Component ? /* @__PURE__ */ jsx23(Component, { block, ...block.props }) : /* @__PURE__ */ jsx23(MissingRenderer, { renderer: block.component });
1915
2341
  }
1916
2342
  case "collection.datagrid":
1917
- return /* @__PURE__ */ jsx17(CoreDataGrid, { model: block.model, mode: block.mode, columns: block.columns, form: block.form, label: block.title ?? block.model });
2343
+ return /* @__PURE__ */ jsx23(CoreDataGrid, { model: block.model, mode: block.mode, columns: block.columns, form: block.form, label: block.title ?? block.model });
1918
2344
  case "collection.cards": {
1919
2345
  const Component = resolveComponent(registry, block.renderer, "cardRenderers");
1920
- return Component ? /* @__PURE__ */ jsx17(Component, { block, model: block.model }) : /* @__PURE__ */ jsx17(CoreCards, { model: block.model, renderer: block.renderer });
2346
+ return Component ? /* @__PURE__ */ jsx23(Component, { block, model: block.model }) : /* @__PURE__ */ jsx23(CoreCards, { model: block.model, renderer: block.renderer });
1921
2347
  }
1922
2348
  case "section":
1923
- return /* @__PURE__ */ jsxs11(Box10, { children: [
1924
- /* @__PURE__ */ jsx17(Heading7, { size: "md", mb: block.description ? 1 : 4, children: block.title }),
1925
- block.description ? /* @__PURE__ */ jsx17(Text11, { color: "gray.600", mb: 4, children: block.description }) : null,
1926
- /* @__PURE__ */ jsx17(Stack6, { gap: 4, children: block.blocks?.map((child, index) => /* @__PURE__ */ jsx17(CoreBlock, { block: child, registry }, child.id ?? index)) })
2349
+ return /* @__PURE__ */ jsxs17(Box14, { children: [
2350
+ /* @__PURE__ */ jsx23(Heading8, { size: "md", mb: block.description ? 1 : 4, children: block.title }),
2351
+ block.description ? /* @__PURE__ */ jsx23(Text16, { color: "gray.600", mb: 4, children: block.description }) : null,
2352
+ /* @__PURE__ */ jsx23(Stack7, { gap: 4, children: block.blocks?.map((child, index) => /* @__PURE__ */ jsx23(CoreBlock, { block: child, registry }, child.id ?? index)) })
1927
2353
  ] });
1928
2354
  case "markdown":
1929
- return /* @__PURE__ */ jsx17(Stack6, { gap: 2, children: renderMarkdown(block.content) });
2355
+ return /* @__PURE__ */ jsx23(Stack7, { gap: 2, children: renderMarkdown(block.content) });
1930
2356
  default:
1931
- return /* @__PURE__ */ jsx17(MissingRenderer, { renderer: block.type });
2357
+ return /* @__PURE__ */ jsx23(MissingRenderer, { renderer: block.type });
1932
2358
  }
1933
2359
  })();
1934
- return /* @__PURE__ */ jsx17(PermissionGate, { permission: block.permissions, children: content });
2360
+ return /* @__PURE__ */ jsx23(PermissionGate, { permission: requiredAccess(block), children: content });
1935
2361
  }
1936
2362
  function CorePage2({ page, registry }) {
1937
2363
  const Component = resolveComponent(registry, page.component, "pageComponents");
1938
- return /* @__PURE__ */ jsx17(PermissionGate, { permission: page.permissions, children: Component ? /* @__PURE__ */ jsx17(Component, { page }) : /* @__PURE__ */ jsxs11(CorePage, { children: [
1939
- /* @__PURE__ */ jsx17(CorePageHeader, { title: page.title ?? page.label }),
1940
- /* @__PURE__ */ jsx17(Stack6, { gap: 6, children: page.blocks?.map((block, index) => /* @__PURE__ */ jsx17(CoreBlock, { block, registry }, block.id ?? index)) })
2364
+ return /* @__PURE__ */ jsx23(PermissionGate, { permission: requiredAccess(page), children: Component ? /* @__PURE__ */ jsx23(Component, { page }) : /* @__PURE__ */ jsxs17(CorePage, { children: [
2365
+ /* @__PURE__ */ jsx23(CorePageHeader, { title: page.title ?? page.label }),
2366
+ /* @__PURE__ */ jsx23(Stack7, { gap: 6, children: page.blocks?.map((block, index) => /* @__PURE__ */ jsx23(CoreBlock, { block, registry }, block.id ?? index)) })
1941
2367
  ] }) });
1942
2368
  }
1943
2369
 
1944
2370
  // src/app/moduleRegistry.tsx
1945
- import { jsx as jsx18 } from "react/jsx-runtime";
2371
+ import { jsx as jsx24 } from "react/jsx-runtime";
1946
2372
  function slug(value) {
1947
2373
  return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1948
2374
  }
2375
+ function requiredAccess2(source) {
2376
+ const values = [...source.permissions ?? [], ...source.capabilities ?? []].filter(Boolean);
2377
+ return values.length ? values : void 0;
2378
+ }
1949
2379
  function viewId(view) {
1950
2380
  if (view.id) return view.id;
1951
2381
  if (view.type === "dashboard") return "dashboard";
@@ -1965,7 +2395,7 @@ function renderView(view) {
1965
2395
  switch (view.type) {
1966
2396
  case "collection": {
1967
2397
  const v = view;
1968
- return /* @__PURE__ */ jsx18(
2398
+ return /* @__PURE__ */ jsx24(
1969
2399
  CoreCollection,
1970
2400
  {
1971
2401
  model: v.model,
@@ -1973,17 +2403,21 @@ function renderView(view) {
1973
2403
  columns: v.columns,
1974
2404
  form: v.form,
1975
2405
  label: viewLabel(v),
1976
- importExport: v.importExport
2406
+ section: v.section,
2407
+ importExport: v.importExport,
2408
+ list: v.list,
2409
+ relations: v.relations,
2410
+ detailModal: v.detailModal
1977
2411
  }
1978
2412
  );
1979
2413
  }
1980
2414
  case "document": {
1981
2415
  const v = view;
1982
- return /* @__PURE__ */ jsx18(CoreDocument, { model: v.model, label: viewLabel(v), approval: v.approval, attachments: v.attachments });
2416
+ return /* @__PURE__ */ jsx24(CoreDocument, { model: v.model, label: viewLabel(v), approval: v.approval, attachments: v.attachments });
1983
2417
  }
1984
2418
  case "pipeline": {
1985
2419
  const v = view;
1986
- return /* @__PURE__ */ jsx18(
2420
+ return /* @__PURE__ */ jsx24(
1987
2421
  CorePipeline,
1988
2422
  {
1989
2423
  model: v.model,
@@ -1995,7 +2429,7 @@ function renderView(view) {
1995
2429
  }
1996
2430
  case "dashboard": {
1997
2431
  const v = view;
1998
- return /* @__PURE__ */ jsx18(CoreDashboard, { label: viewLabel(v), widgets: v.widgets });
2432
+ return /* @__PURE__ */ jsx24(CoreDashboard, { label: viewLabel(v), widgets: v.widgets });
1999
2433
  }
2000
2434
  default:
2001
2435
  return null;
@@ -2005,15 +2439,15 @@ function viewToRoute(view) {
2005
2439
  return {
2006
2440
  path: viewPath(view),
2007
2441
  element: renderView(view),
2008
- permissions: "permissions" in view ? view.permissions : void 0
2442
+ permissions: requiredAccess2(view)
2009
2443
  };
2010
2444
  }
2011
2445
  function pageToRoute(page, registry) {
2012
- return { path: page.path, element: /* @__PURE__ */ jsx18(CorePage2, { page, registry }), permissions: page.permissions };
2446
+ return { path: page.path, element: /* @__PURE__ */ jsx24(CorePage2, { page, registry }), permissions: requiredAccess2(page) };
2013
2447
  }
2014
2448
  function pageToMenu(page) {
2015
2449
  if (page.hidden || !page.label) return null;
2016
- return { label: page.label, href: page.path, icon: page.icon, section: page.section, permissions: page.permissions, order: page.order };
2450
+ return { label: page.label, href: page.path, icon: page.icon, section: page.section, permissions: requiredAccess2(page), capabilities: page.capabilities, order: page.order };
2017
2451
  }
2018
2452
  function viewToMenu(view) {
2019
2453
  return {
@@ -2021,7 +2455,8 @@ function viewToMenu(view) {
2021
2455
  href: viewPath(view),
2022
2456
  icon: view.icon,
2023
2457
  section: view.section,
2024
- permissions: "permissions" in view ? view.permissions : void 0
2458
+ permissions: requiredAccess2(view),
2459
+ capabilities: "capabilities" in view ? view.capabilities : void 0
2025
2460
  };
2026
2461
  }
2027
2462
  function resolveRegistry(config) {
@@ -2034,8 +2469,8 @@ function resolveRegistry(config) {
2034
2469
  routes.push(route);
2035
2470
  };
2036
2471
  for (const mod of config.modules ?? []) {
2037
- for (const route of mod.routes ?? []) pushRoute(route);
2038
- for (const item of mod.menu ?? []) menu.push(item);
2472
+ for (const route of mod.routes ?? []) pushRoute({ ...route, permissions: requiredAccess2(route) });
2473
+ for (const item of mod.menu ?? []) menu.push({ ...item, permissions: requiredAccess2(item) });
2039
2474
  for (const view of mod.views ?? []) {
2040
2475
  pushRoute(viewToRoute(view));
2041
2476
  menu.push(viewToMenu(view));
@@ -2056,7 +2491,7 @@ function resolveRegistry(config) {
2056
2491
  }
2057
2492
  }
2058
2493
  if (includeManual) {
2059
- for (const item of config.ui?.navigation?.items ?? []) menu.push(item);
2494
+ for (const item of config.ui?.navigation?.items ?? []) menu.push({ ...item, permissions: requiredAccess2(item) });
2060
2495
  }
2061
2496
  menu.sort((a, b) => (a.order ?? 100) - (b.order ?? 100));
2062
2497
  return { routes, menu };
@@ -2069,13 +2504,13 @@ import {
2069
2504
  } from "react-router-dom";
2070
2505
 
2071
2506
  // src/shell/DefaultShell.tsx
2072
- import { Box as Box12, Button as Button7, Flex as Flex8, Spacer as Spacer2, Text as Text13 } from "@chakra-ui/react";
2507
+ import { Box as Box16, Button as Button11, Flex as Flex11, Spacer as Spacer2, Text as Text18 } from "@chakra-ui/react";
2073
2508
  import { Outlet } from "react-router-dom";
2074
2509
 
2075
2510
  // src/shell/Sidebar.tsx
2076
- import { Box as Box11, Flex as Flex7, Image, Stack as Stack7, Text as Text12 } from "@chakra-ui/react";
2511
+ import { Box as Box15, Flex as Flex10, Image, Stack as Stack8, Text as Text17 } from "@chakra-ui/react";
2077
2512
  import { NavLink } from "react-router-dom";
2078
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
2513
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
2079
2514
  function groupBySection(items) {
2080
2515
  const groups = /* @__PURE__ */ new Map();
2081
2516
  for (const item of items) {
@@ -2088,8 +2523,8 @@ function groupBySection(items) {
2088
2523
  function Sidebar({ app, menu, registry }) {
2089
2524
  const { hasPermission } = useOonAuth();
2090
2525
  const visible = menu.filter((item) => !item.hidden && hasPermission(item.permissions));
2091
- return /* @__PURE__ */ jsxs12(
2092
- Box11,
2526
+ return /* @__PURE__ */ jsxs18(
2527
+ Box15,
2093
2528
  {
2094
2529
  as: "nav",
2095
2530
  w: { base: "76px", lg: "248px" },
@@ -2104,9 +2539,9 @@ function Sidebar({ app, menu, registry }) {
2104
2539
  alignSelf: "flex-start",
2105
2540
  overflowY: "auto",
2106
2541
  children: [
2107
- /* @__PURE__ */ jsxs12(Flex7, { align: "center", gap: 3, mb: 6, px: { base: 1, lg: 2 }, minH: "42px", children: [
2108
- app.logo ? /* @__PURE__ */ jsx19(Image, { src: app.logo, alt: app.name, maxH: "36px", maxW: { base: "44px", lg: "150px" }, objectFit: "contain" }) : /* @__PURE__ */ jsx19(
2109
- Flex7,
2542
+ /* @__PURE__ */ jsxs18(Flex10, { align: "center", gap: 3, mb: 6, px: { base: 1, lg: 2 }, minH: "42px", children: [
2543
+ app.logo ? /* @__PURE__ */ jsx25(Image, { src: app.logo, alt: app.name, maxH: "36px", maxW: { base: "44px", lg: "150px" }, objectFit: "contain" }) : /* @__PURE__ */ jsx25(
2544
+ Flex10,
2110
2545
  {
2111
2546
  w: "38px",
2112
2547
  h: "38px",
@@ -2121,14 +2556,14 @@ function Sidebar({ app, menu, registry }) {
2121
2556
  children: "O"
2122
2557
  }
2123
2558
  ),
2124
- /* @__PURE__ */ jsxs12(Box11, { display: { base: "none", lg: "block" }, minW: 0, children: [
2125
- /* @__PURE__ */ jsx19(Text12, { fontWeight: "700", fontSize: "sm", color: "#07262E", lineClamp: 1, children: app.name }),
2126
- /* @__PURE__ */ jsx19(Text12, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.08em", children: "Opera\xE7\xE3o digital" })
2559
+ /* @__PURE__ */ jsxs18(Box15, { display: { base: "none", lg: "block" }, minW: 0, children: [
2560
+ /* @__PURE__ */ jsx25(Text17, { fontWeight: "700", fontSize: "sm", color: "#07262E", lineClamp: 1, children: app.name }),
2561
+ /* @__PURE__ */ jsx25(Text17, { fontSize: "10px", color: "gray.500", textTransform: "uppercase", letterSpacing: "0.08em", children: "Opera\xE7\xE3o digital" })
2127
2562
  ] })
2128
2563
  ] }),
2129
- /* @__PURE__ */ jsx19(Stack7, { gap: 5, children: groupBySection(visible).map(([section, items]) => /* @__PURE__ */ jsxs12(Stack7, { gap: 1, children: [
2130
- /* @__PURE__ */ jsx19(
2131
- Text12,
2564
+ /* @__PURE__ */ jsx25(Stack8, { gap: 5, children: groupBySection(visible).map(([section, items]) => /* @__PURE__ */ jsxs18(Stack8, { gap: 1, children: [
2565
+ /* @__PURE__ */ jsx25(
2566
+ Text17,
2132
2567
  {
2133
2568
  display: { base: "none", lg: "block" },
2134
2569
  fontSize: "10px",
@@ -2143,9 +2578,9 @@ function Sidebar({ app, menu, registry }) {
2143
2578
  ),
2144
2579
  items.map((item) => {
2145
2580
  const CustomMenuItem = resolveComponent(registry, item.renderer, "menuRenderers");
2146
- if (CustomMenuItem) return /* @__PURE__ */ jsx19(CustomMenuItem, { item }, item.href);
2147
- return /* @__PURE__ */ jsx19(NavLink, { to: item.href, end: item.href === "/", title: item.label, children: ({ isActive }) => /* @__PURE__ */ jsxs12(
2148
- Flex7,
2581
+ if (CustomMenuItem) return /* @__PURE__ */ jsx25(CustomMenuItem, { item }, item.href);
2582
+ return /* @__PURE__ */ jsx25(NavLink, { to: item.href, end: item.href === "/", title: item.label, children: ({ isActive }) => /* @__PURE__ */ jsxs18(
2583
+ Flex10,
2149
2584
  {
2150
2585
  align: "center",
2151
2586
  justify: { base: "center", lg: "flex-start" },
@@ -2162,8 +2597,8 @@ function Sidebar({ app, menu, registry }) {
2162
2597
  transition: "all 0.15s ease",
2163
2598
  _hover: { bg: isActive ? "brand.50" : "#F8F9FA", color: "brand.700" },
2164
2599
  children: [
2165
- item.icon ? /* @__PURE__ */ jsx19(Box11, { flex: "0 0 auto", children: item.icon }) : /* @__PURE__ */ jsx19(Box11, { w: "7px", h: "7px", borderRadius: "full", bg: isActive ? "brand.500" : "gray.300" }),
2166
- /* @__PURE__ */ jsx19(Text12, { display: { base: "none", lg: "block" }, lineClamp: 1, children: item.label })
2600
+ item.icon ? /* @__PURE__ */ jsx25(Box15, { flex: "0 0 auto", children: item.icon }) : /* @__PURE__ */ jsx25(Box15, { w: "7px", h: "7px", borderRadius: "full", bg: isActive ? "brand.500" : "gray.300" }),
2601
+ /* @__PURE__ */ jsx25(Text17, { display: { base: "none", lg: "block" }, lineClamp: 1, children: item.label })
2167
2602
  ]
2168
2603
  }
2169
2604
  ) }, item.href);
@@ -2175,21 +2610,21 @@ function Sidebar({ app, menu, registry }) {
2175
2610
  }
2176
2611
 
2177
2612
  // src/shell/DefaultShell.tsx
2178
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
2613
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
2179
2614
  function CoreTopbar({ app }) {
2180
2615
  const { user, logout } = useOonAuth();
2181
- return /* @__PURE__ */ jsxs13(Flex8, { as: "header", align: "center", minH: "64px", px: { base: 4, lg: 6 }, py: 3, borderBottomWidth: "1px", borderColor: "#E8ECEF", bg: "rgba(255, 255, 255, 0.96)", backdropFilter: "blur(10px)", position: "sticky", top: 0, zIndex: 10, children: [
2182
- /* @__PURE__ */ jsxs13(Box12, { children: [
2183
- /* @__PURE__ */ jsx20(Text13, { fontSize: "xs", fontWeight: "600", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", children: "Central Oon" }),
2184
- /* @__PURE__ */ jsx20(Text13, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: app.title ?? app.name })
2616
+ return /* @__PURE__ */ jsxs19(Flex11, { as: "header", align: "center", minH: "64px", px: { base: 4, lg: 6 }, py: 3, borderBottomWidth: "1px", borderColor: "#E8ECEF", bg: "rgba(255, 255, 255, 0.96)", backdropFilter: "blur(10px)", position: "sticky", top: 0, zIndex: 10, children: [
2617
+ /* @__PURE__ */ jsxs19(Box16, { children: [
2618
+ /* @__PURE__ */ jsx26(Text18, { fontSize: "xs", fontWeight: "600", color: "brand.500", textTransform: "uppercase", letterSpacing: "0.08em", children: "Central Oon" }),
2619
+ /* @__PURE__ */ jsx26(Text18, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: app.title ?? app.name })
2185
2620
  ] }),
2186
- /* @__PURE__ */ jsx20(Spacer2, {}),
2187
- user ? /* @__PURE__ */ jsxs13(Flex8, { align: "center", gap: 3, children: [
2188
- /* @__PURE__ */ jsxs13(Box12, { textAlign: "right", display: { base: "none", md: "block" }, children: [
2189
- /* @__PURE__ */ jsx20(Text13, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: user.nome }),
2190
- user.email ? /* @__PURE__ */ jsx20(Text13, { fontSize: "xs", color: "gray.500", children: user.email }) : null
2621
+ /* @__PURE__ */ jsx26(Spacer2, {}),
2622
+ user ? /* @__PURE__ */ jsxs19(Flex11, { align: "center", gap: 3, children: [
2623
+ /* @__PURE__ */ jsxs19(Box16, { textAlign: "right", display: { base: "none", md: "block" }, children: [
2624
+ /* @__PURE__ */ jsx26(Text18, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: user.nome }),
2625
+ user.email ? /* @__PURE__ */ jsx26(Text18, { fontSize: "xs", color: "gray.500", children: user.email }) : null
2191
2626
  ] }),
2192
- /* @__PURE__ */ jsx20(Button7, { size: "sm", variant: "outline", colorPalette: "brand", borderRadius: "8px", onClick: logout, children: "Sair" })
2627
+ /* @__PURE__ */ jsx26(Button11, { size: "sm", variant: "outline", colorPalette: "brand", borderRadius: "8px", onClick: logout, children: "Sair" })
2193
2628
  ] }) : null
2194
2629
  ] });
2195
2630
  }
@@ -2197,45 +2632,45 @@ function Slot({ name, slot, registry, app, menu }) {
2197
2632
  if (slot === "none") return null;
2198
2633
  if (slot?.startsWith("custom:")) {
2199
2634
  const C = resolveComponent(registry, slot, "layoutSlots");
2200
- return C ? /* @__PURE__ */ jsx20(C, { app, menu }) : /* @__PURE__ */ jsx20(MissingRenderer, { renderer: slot });
2635
+ return C ? /* @__PURE__ */ jsx26(C, { app, menu }) : /* @__PURE__ */ jsx26(MissingRenderer, { renderer: slot });
2201
2636
  }
2202
- if (name === "sidebar") return /* @__PURE__ */ jsx20(Sidebar, { app, menu, registry });
2203
- if (name === "topbar") return /* @__PURE__ */ jsx20(CoreTopbar, { app });
2204
- if (name === "footer" && slot === "core") return /* @__PURE__ */ jsx20(Box12, { as: "footer", px: 6, py: 4, color: "gray.500", fontSize: "xs", borderTopWidth: "1px", children: "OonCore" });
2637
+ if (name === "sidebar") return /* @__PURE__ */ jsx26(Sidebar, { app, menu, registry });
2638
+ if (name === "topbar") return /* @__PURE__ */ jsx26(CoreTopbar, { app });
2639
+ if (name === "footer" && slot === "core") return /* @__PURE__ */ jsx26(Box16, { as: "footer", px: 6, py: 4, color: "gray.500", fontSize: "xs", borderTopWidth: "1px", children: "OonCore" });
2205
2640
  return null;
2206
2641
  }
2207
2642
  function DefaultShell({ app, menu, layout, registry }) {
2208
2643
  const portal = layout?.shell === "portal" || layout?.shell === "content-only";
2209
2644
  const mainPadding = portal ? { base: 4, lg: 10 } : { base: 4, lg: 6 };
2210
- return /* @__PURE__ */ jsxs13(Flex8, { align: "stretch", minH: "100vh", bg: portal ? "white" : "#F8F9FA", children: [
2211
- /* @__PURE__ */ jsx20(Slot, { name: "sidebar", slot: layout?.sidebar ?? "core", registry, app, menu }),
2212
- /* @__PURE__ */ jsxs13(Flex8, { direction: "column", flex: "1", minW: 0, children: [
2213
- /* @__PURE__ */ jsx20(Slot, { name: "topbar", slot: layout?.topbar ?? "core", registry, app, menu }),
2214
- /* @__PURE__ */ jsx20(Slot, { name: "header", slot: layout?.header, registry, app, menu }),
2215
- /* @__PURE__ */ jsx20(Box12, { as: "main", flex: "1", p: mainPadding, minW: 0, children: /* @__PURE__ */ jsx20(Box12, { maxW: portal ? "1180px" : "1680px", mx: "auto", children: /* @__PURE__ */ jsx20(Outlet, {}) }) }),
2216
- /* @__PURE__ */ jsx20(Slot, { name: "footer", slot: layout?.footer ?? "none", registry, app, menu })
2645
+ return /* @__PURE__ */ jsxs19(Flex11, { align: "stretch", minH: "100vh", bg: portal ? "white" : "#F8F9FA", children: [
2646
+ /* @__PURE__ */ jsx26(Slot, { name: "sidebar", slot: layout?.sidebar ?? "core", registry, app, menu }),
2647
+ /* @__PURE__ */ jsxs19(Flex11, { direction: "column", flex: "1", minW: 0, children: [
2648
+ /* @__PURE__ */ jsx26(Slot, { name: "topbar", slot: layout?.topbar ?? "core", registry, app, menu }),
2649
+ /* @__PURE__ */ jsx26(Slot, { name: "header", slot: layout?.header, registry, app, menu }),
2650
+ /* @__PURE__ */ jsx26(Box16, { as: "main", flex: "1", p: mainPadding, minW: 0, children: /* @__PURE__ */ jsx26(Box16, { maxW: portal ? "1180px" : "1680px", mx: "auto", children: /* @__PURE__ */ jsx26(Outlet, {}) }) }),
2651
+ /* @__PURE__ */ jsx26(Slot, { name: "footer", slot: layout?.footer ?? "none", registry, app, menu })
2217
2652
  ] })
2218
2653
  ] });
2219
2654
  }
2220
2655
  function PortalShell(props) {
2221
- return /* @__PURE__ */ jsx20(DefaultShell, { ...props, layout: { ...props.layout, shell: "portal" } });
2656
+ return /* @__PURE__ */ jsx26(DefaultShell, { ...props, layout: { ...props.layout, shell: "portal" } });
2222
2657
  }
2223
2658
 
2224
2659
  // src/shell/AuthenticatedLayout.tsx
2225
- import { jsx as jsx21 } from "react/jsx-runtime";
2660
+ import { jsx as jsx27 } from "react/jsx-runtime";
2226
2661
  function AuthenticatedLayout({ app, menu, layout, registry }) {
2227
2662
  if (layout?.shell?.startsWith("custom:")) {
2228
2663
  const CustomShell = resolveComponent(registry, layout.shell, "layoutSlots");
2229
- return CustomShell ? /* @__PURE__ */ jsx21(CustomShell, { app, menu, layout }) : /* @__PURE__ */ jsx21(MissingRenderer, { renderer: layout.shell });
2664
+ return CustomShell ? /* @__PURE__ */ jsx27(CustomShell, { app, menu, layout }) : /* @__PURE__ */ jsx27(MissingRenderer, { renderer: layout.shell });
2230
2665
  }
2231
- if (layout?.shell === "portal") return /* @__PURE__ */ jsx21(PortalShell, { app, menu, layout, registry });
2232
- return /* @__PURE__ */ jsx21(DefaultShell, { app, menu, layout, registry });
2666
+ if (layout?.shell === "portal") return /* @__PURE__ */ jsx27(PortalShell, { app, menu, layout, registry });
2667
+ return /* @__PURE__ */ jsx27(DefaultShell, { app, menu, layout, registry });
2233
2668
  }
2234
2669
 
2235
2670
  // src/security/AccessDeniedPage.tsx
2236
- import { Box as Box13, Button as Button8, Flex as Flex9, Heading as Heading8, Text as Text14, VStack } from "@chakra-ui/react";
2671
+ import { Box as Box17, Button as Button12, Flex as Flex12, Heading as Heading9, Text as Text19, VStack } from "@chakra-ui/react";
2237
2672
  import { useNavigate } from "react-router-dom";
2238
- import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
2673
+ import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
2239
2674
  function AccessDeniedPage({ app }) {
2240
2675
  const { logout } = useOonAuth();
2241
2676
  const navigate = useNavigate();
@@ -2243,8 +2678,8 @@ function AccessDeniedPage({ app }) {
2243
2678
  logout();
2244
2679
  navigate("/login", { replace: true });
2245
2680
  }
2246
- return /* @__PURE__ */ jsx22(Flex9, { minH: "100vh", align: "center", justify: "center", bg: "#F5F8FA", px: 4, children: /* @__PURE__ */ jsx22(
2247
- Box13,
2681
+ return /* @__PURE__ */ jsx28(Flex12, { minH: "100vh", align: "center", justify: "center", bg: "#F5F8FA", px: 4, children: /* @__PURE__ */ jsx28(
2682
+ Box17,
2248
2683
  {
2249
2684
  width: "100%",
2250
2685
  maxW: "560px",
@@ -2254,9 +2689,9 @@ function AccessDeniedPage({ app }) {
2254
2689
  borderRadius: "18px",
2255
2690
  boxShadow: "0 24px 70px rgba(7, 38, 46, 0.10)",
2256
2691
  p: { base: 6, md: 10 },
2257
- children: /* @__PURE__ */ jsxs14(VStack, { align: "stretch", gap: 6, children: [
2258
- /* @__PURE__ */ jsx22(
2259
- Box13,
2692
+ children: /* @__PURE__ */ jsxs20(VStack, { align: "stretch", gap: 6, children: [
2693
+ /* @__PURE__ */ jsx28(
2694
+ Box17,
2260
2695
  {
2261
2696
  width: "56px",
2262
2697
  height: "56px",
@@ -2272,9 +2707,9 @@ function AccessDeniedPage({ app }) {
2272
2707
  children: "!"
2273
2708
  }
2274
2709
  ),
2275
- /* @__PURE__ */ jsxs14(Box13, { children: [
2276
- /* @__PURE__ */ jsx22(
2277
- Text14,
2710
+ /* @__PURE__ */ jsxs20(Box17, { children: [
2711
+ /* @__PURE__ */ jsx28(
2712
+ Text19,
2278
2713
  {
2279
2714
  color: "#39BFED",
2280
2715
  fontSize: "xs",
@@ -2284,15 +2719,15 @@ function AccessDeniedPage({ app }) {
2284
2719
  children: "Acesso negado"
2285
2720
  }
2286
2721
  ),
2287
- /* @__PURE__ */ jsx22(Heading8, { mt: 2, size: "lg", color: "#07262E", children: "Voc\xEA n\xE3o possui permiss\xE3o para este aplicativo" }),
2288
- /* @__PURE__ */ jsxs14(Text14, { mt: 3, color: "gray.600", children: [
2722
+ /* @__PURE__ */ jsx28(Heading9, { mt: 2, size: "lg", color: "#07262E", children: "Voc\xEA n\xE3o possui permiss\xE3o para este aplicativo" }),
2723
+ /* @__PURE__ */ jsxs20(Text19, { mt: 3, color: "gray.600", children: [
2289
2724
  "Seu usu\xE1rio foi autenticado, mas n\xE3o existe uma permiss\xE3o ativa para acessar ",
2290
2725
  app.title ?? app.name,
2291
2726
  ". Solicite o acesso ao administrador da sua organiza\xE7\xE3o."
2292
2727
  ] })
2293
2728
  ] }),
2294
- /* @__PURE__ */ jsx22(
2295
- Button8,
2729
+ /* @__PURE__ */ jsx28(
2730
+ Button12,
2296
2731
  {
2297
2732
  alignSelf: "flex-start",
2298
2733
  bg: "#07262E",
@@ -2309,7 +2744,7 @@ function AccessDeniedPage({ app }) {
2309
2744
 
2310
2745
  // src/security/AppAccessGuard.tsx
2311
2746
  import { Navigate, useLocation } from "react-router-dom";
2312
- import { Fragment as Fragment3, jsx as jsx23 } from "react/jsx-runtime";
2747
+ import { Fragment as Fragment5, jsx as jsx29 } from "react/jsx-runtime";
2313
2748
  function loginRedirect(pathname, search) {
2314
2749
  const destination = `${pathname}${search}`;
2315
2750
  return `/login?redirect=${encodeURIComponent(destination)}`;
@@ -2317,9 +2752,9 @@ function loginRedirect(pathname, search) {
2317
2752
  function AppAccessGuard({ children }) {
2318
2753
  const { status, retry } = useOonAuth();
2319
2754
  const location = useLocation();
2320
- if (status === "loading") return /* @__PURE__ */ jsx23(LoadingScreen, {});
2755
+ if (status === "loading") return /* @__PURE__ */ jsx29(LoadingScreen, {});
2321
2756
  if (status === "unauthenticated") {
2322
- return /* @__PURE__ */ jsx23(
2757
+ return /* @__PURE__ */ jsx29(
2323
2758
  Navigate,
2324
2759
  {
2325
2760
  to: loginRedirect(location.pathname, location.search),
@@ -2328,10 +2763,10 @@ function AppAccessGuard({ children }) {
2328
2763
  );
2329
2764
  }
2330
2765
  if (status === "forbidden") {
2331
- return /* @__PURE__ */ jsx23(Navigate, { to: "/acesso-negado", replace: true });
2766
+ return /* @__PURE__ */ jsx29(Navigate, { to: "/acesso-negado", replace: true });
2332
2767
  }
2333
2768
  if (status === "error") {
2334
- return /* @__PURE__ */ jsx23(
2769
+ return /* @__PURE__ */ jsx29(
2335
2770
  LoadingScreen,
2336
2771
  {
2337
2772
  message: "N\xE3o foi poss\xEDvel validar seu acesso. Tente novamente.",
@@ -2342,22 +2777,22 @@ function AppAccessGuard({ children }) {
2342
2777
  }
2343
2778
  );
2344
2779
  }
2345
- return /* @__PURE__ */ jsx23(Fragment3, { children });
2780
+ return /* @__PURE__ */ jsx29(Fragment5, { children });
2346
2781
  }
2347
2782
 
2348
2783
  // src/security/LoginPage.tsx
2349
- import { useState as useState8 } from "react";
2784
+ import { useState as useState12 } from "react";
2350
2785
  import {
2351
- Box as Box14,
2352
- Button as Button9,
2353
- Flex as Flex10,
2354
- Heading as Heading9,
2355
- Input as Input4,
2356
- Text as Text15,
2786
+ Box as Box18,
2787
+ Button as Button13,
2788
+ Flex as Flex13,
2789
+ Heading as Heading10,
2790
+ Input as Input6,
2791
+ Text as Text20,
2357
2792
  VStack as VStack2
2358
2793
  } from "@chakra-ui/react";
2359
2794
  import { Navigate as Navigate2, useLocation as useLocation2 } from "react-router-dom";
2360
- import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
2795
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
2361
2796
  function safeRedirect(search) {
2362
2797
  const value = new URLSearchParams(search).get("redirect") || "/";
2363
2798
  if (!value.startsWith("/") || value.startsWith("//")) return "/";
@@ -2369,16 +2804,16 @@ function safeRedirect(search) {
2369
2804
  function LoginPage({ app }) {
2370
2805
  const { status, login } = useOonAuth();
2371
2806
  const location = useLocation2();
2372
- const [email, setEmail] = useState8("");
2373
- const [password, setPassword] = useState8("");
2374
- const [submitting, setSubmitting] = useState8(false);
2375
- const [message, setMessage] = useState8(null);
2807
+ const [email, setEmail] = useState12("");
2808
+ const [password, setPassword] = useState12("");
2809
+ const [submitting, setSubmitting] = useState12(false);
2810
+ const [message, setMessage] = useState12(null);
2376
2811
  const redirect = safeRedirect(location.search);
2377
2812
  if (status === "authenticated") {
2378
- return /* @__PURE__ */ jsx24(Navigate2, { to: redirect, replace: true });
2813
+ return /* @__PURE__ */ jsx30(Navigate2, { to: redirect, replace: true });
2379
2814
  }
2380
2815
  if (status === "forbidden") {
2381
- return /* @__PURE__ */ jsx24(Navigate2, { to: "/acesso-negado", replace: true });
2816
+ return /* @__PURE__ */ jsx30(Navigate2, { to: "/acesso-negado", replace: true });
2382
2817
  }
2383
2818
  async function handleSubmit(event) {
2384
2819
  event.preventDefault();
@@ -2396,8 +2831,8 @@ function LoginPage({ app }) {
2396
2831
  setSubmitting(false);
2397
2832
  }
2398
2833
  }
2399
- return /* @__PURE__ */ jsx24(Flex10, { minH: "100vh", align: "center", justify: "center", bg: "#F5F8FA", px: 4, children: /* @__PURE__ */ jsx24(
2400
- Box14,
2834
+ return /* @__PURE__ */ jsx30(Flex13, { minH: "100vh", align: "center", justify: "center", bg: "#F5F8FA", px: 4, children: /* @__PURE__ */ jsx30(
2835
+ Box18,
2401
2836
  {
2402
2837
  width: "100%",
2403
2838
  maxW: "440px",
@@ -2407,10 +2842,10 @@ function LoginPage({ app }) {
2407
2842
  borderRadius: "18px",
2408
2843
  boxShadow: "0 24px 70px rgba(7, 38, 46, 0.10)",
2409
2844
  p: { base: 6, md: 9 },
2410
- children: /* @__PURE__ */ jsx24("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs15(VStack2, { align: "stretch", gap: 6, children: [
2411
- /* @__PURE__ */ jsxs15(Box14, { children: [
2412
- /* @__PURE__ */ jsx24(
2413
- Text15,
2845
+ children: /* @__PURE__ */ jsx30("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs21(VStack2, { align: "stretch", gap: 6, children: [
2846
+ /* @__PURE__ */ jsxs21(Box18, { children: [
2847
+ /* @__PURE__ */ jsx30(
2848
+ Text20,
2414
2849
  {
2415
2850
  color: "#39BFED",
2416
2851
  fontSize: "xs",
@@ -2420,14 +2855,14 @@ function LoginPage({ app }) {
2420
2855
  children: "Central Oon"
2421
2856
  }
2422
2857
  ),
2423
- /* @__PURE__ */ jsx24(Heading9, { mt: 2, size: "lg", color: "#07262E", children: app.title ?? app.name }),
2424
- /* @__PURE__ */ jsx24(Text15, { mt: 2, color: "gray.600", fontSize: "sm", children: "Entre com seu usu\xE1rio autorizado para acessar este aplicativo." })
2858
+ /* @__PURE__ */ jsx30(Heading10, { mt: 2, size: "lg", color: "#07262E", children: app.title ?? app.name }),
2859
+ /* @__PURE__ */ jsx30(Text20, { mt: 2, color: "gray.600", fontSize: "sm", children: "Entre com seu usu\xE1rio autorizado para acessar este aplicativo." })
2425
2860
  ] }),
2426
- /* @__PURE__ */ jsxs15(VStack2, { align: "stretch", gap: 4, children: [
2427
- /* @__PURE__ */ jsxs15(Box14, { children: [
2428
- /* @__PURE__ */ jsx24(Text15, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "E-mail" }),
2429
- /* @__PURE__ */ jsx24(
2430
- Input4,
2861
+ /* @__PURE__ */ jsxs21(VStack2, { align: "stretch", gap: 4, children: [
2862
+ /* @__PURE__ */ jsxs21(Box18, { children: [
2863
+ /* @__PURE__ */ jsx30(Text20, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "E-mail" }),
2864
+ /* @__PURE__ */ jsx30(
2865
+ Input6,
2431
2866
  {
2432
2867
  type: "email",
2433
2868
  value: email,
@@ -2438,10 +2873,10 @@ function LoginPage({ app }) {
2438
2873
  }
2439
2874
  )
2440
2875
  ] }),
2441
- /* @__PURE__ */ jsxs15(Box14, { children: [
2442
- /* @__PURE__ */ jsx24(Text15, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "Senha" }),
2443
- /* @__PURE__ */ jsx24(
2444
- Input4,
2876
+ /* @__PURE__ */ jsxs21(Box18, { children: [
2877
+ /* @__PURE__ */ jsx30(Text20, { mb: 2, fontSize: "sm", fontWeight: "600", color: "#24323A", children: "Senha" }),
2878
+ /* @__PURE__ */ jsx30(
2879
+ Input6,
2445
2880
  {
2446
2881
  type: "password",
2447
2882
  value: password,
@@ -2453,8 +2888,8 @@ function LoginPage({ app }) {
2453
2888
  )
2454
2889
  ] })
2455
2890
  ] }),
2456
- message ? /* @__PURE__ */ jsx24(
2457
- Box14,
2891
+ message ? /* @__PURE__ */ jsx30(
2892
+ Box18,
2458
2893
  {
2459
2894
  role: "alert",
2460
2895
  borderRadius: "10px",
@@ -2466,8 +2901,8 @@ function LoginPage({ app }) {
2466
2901
  children: message
2467
2902
  }
2468
2903
  ) : null,
2469
- /* @__PURE__ */ jsx24(
2470
- Button9,
2904
+ /* @__PURE__ */ jsx30(
2905
+ Button13,
2471
2906
  {
2472
2907
  type: "submit",
2473
2908
  bg: "#07262E",
@@ -2483,9 +2918,9 @@ function LoginPage({ app }) {
2483
2918
  }
2484
2919
 
2485
2920
  // src/security/ActivationPage.tsx
2486
- import { useEffect as useEffect5, useState as useState9 } from "react";
2487
- import { Box as Box15, Button as Button10, Heading as Heading10, Input as Input5, Text as Text16, VStack as VStack3 } from "@chakra-ui/react";
2488
- import { Fragment as Fragment4, jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
2921
+ import { useEffect as useEffect7, useState as useState13 } from "react";
2922
+ import { Box as Box19, Button as Button14, Heading as Heading11, Input as Input7, Text as Text21, VStack as VStack3 } from "@chakra-ui/react";
2923
+ import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
2489
2924
  function encodeBasicCredentials2(email, password) {
2490
2925
  const bytes = new TextEncoder().encode(`${email}:${password}`);
2491
2926
  let binary = "";
@@ -2495,22 +2930,22 @@ function encodeBasicCredentials2(email, password) {
2495
2930
  function ActivationPage() {
2496
2931
  const { http } = useOonApi();
2497
2932
  const activation = useActivation();
2498
- const [step, setStep] = useState9(1);
2499
- const [config, setConfig] = useState9(null);
2500
- const [code, setCode] = useState9("");
2501
- const [preview, setPreview] = useState9(null);
2502
- const [global, setGlobal] = useState9({});
2503
- const [app, setApp] = useState9({});
2504
- const [rootEmail, setRootEmail] = useState9("");
2505
- const [rootPassword, setRootPassword] = useState9("");
2506
- const [devName, setDevName] = useState9("");
2507
- const [devEmail, setDevEmail] = useState9("");
2508
- const [devPassword, setDevPassword] = useState9("");
2509
- const [showCodeFlow, setShowCodeFlow] = useState9(false);
2510
- const [devResult, setDevResult] = useState9(null);
2511
- const [error, setError] = useState9(null);
2512
- const [submitting, setSubmitting] = useState9(false);
2513
- useEffect5(() => {
2933
+ const [step, setStep] = useState13(1);
2934
+ const [config, setConfig] = useState13(null);
2935
+ const [code, setCode] = useState13("");
2936
+ const [preview, setPreview] = useState13(null);
2937
+ const [global, setGlobal] = useState13({});
2938
+ const [app, setApp] = useState13({});
2939
+ const [rootEmail, setRootEmail] = useState13("");
2940
+ const [rootPassword, setRootPassword] = useState13("");
2941
+ const [devName, setDevName] = useState13("");
2942
+ const [devEmail, setDevEmail] = useState13("");
2943
+ const [devPassword, setDevPassword] = useState13("");
2944
+ const [showCodeFlow, setShowCodeFlow] = useState13(false);
2945
+ const [devResult, setDevResult] = useState13(null);
2946
+ const [error, setError] = useState13(null);
2947
+ const [submitting, setSubmitting] = useState13(false);
2948
+ useEffect7(() => {
2514
2949
  http.get("/ativacao/configuracao").then((response) => {
2515
2950
  setConfig(response.data);
2516
2951
  setGlobal(response.data.defaults || {});
@@ -2518,7 +2953,7 @@ function ActivationPage() {
2518
2953
  () => setError("N\xE3o foi poss\xEDvel carregar a configura\xE7\xE3o de ativa\xE7\xE3o.")
2519
2954
  );
2520
2955
  }, [http]);
2521
- useEffect5(() => {
2956
+ useEffect7(() => {
2522
2957
  if (activation.status === "active") {
2523
2958
  window.location.replace("/login");
2524
2959
  }
@@ -2619,13 +3054,13 @@ function ActivationPage() {
2619
3054
  }
2620
3055
  }
2621
3056
  function renderField(field, values, setValues) {
2622
- return /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2623
- /* @__PURE__ */ jsxs16(Text16, { fontWeight: "medium", children: [
3057
+ return /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3058
+ /* @__PURE__ */ jsxs22(Text21, { fontWeight: "medium", children: [
2624
3059
  field.label,
2625
3060
  field.required ? " *" : ""
2626
3061
  ] }),
2627
- /* @__PURE__ */ jsx25(
2628
- Input5,
3062
+ /* @__PURE__ */ jsx31(
3063
+ Input7,
2629
3064
  {
2630
3065
  type: field.type === "password" || field.type === "secret" ? "password" : field.type === "email" ? "email" : field.type === "url" ? "url" : field.type === "number" || field.type === "integer" ? "number" : "text",
2631
3066
  value: String(values[field.name] ?? field.defaultValue ?? ""),
@@ -2636,16 +3071,16 @@ function ActivationPage() {
2636
3071
  onChange: (event) => setValues({ ...values, [field.name]: event.target.value })
2637
3072
  }
2638
3073
  ),
2639
- field.helpText ? /* @__PURE__ */ jsx25(Text16, { fontSize: "sm", color: "gray.500", children: field.helpText }) : null
3074
+ field.helpText ? /* @__PURE__ */ jsx31(Text21, { fontSize: "sm", color: "gray.500", children: field.helpText }) : null
2640
3075
  ] }, field.name);
2641
3076
  }
2642
3077
  function renderDevLocalActivation() {
2643
- return /* @__PURE__ */ jsxs16(Fragment4, { children: [
2644
- /* @__PURE__ */ jsx25(Text16, { color: "gray.700", children: "Entre com seu e-mail e senha para ativar esta Central em ambiente de desenvolvimento. Se o e-mail ainda n\xE3o existir na Central de Ativa\xE7\xF5es, o usu\xE1rio ser\xE1 criado automaticamente com perfil de desenvolvedor." }),
2645
- /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2646
- /* @__PURE__ */ jsx25(Text16, { fontWeight: "medium", children: "Nome do usu\xE1rio" }),
2647
- /* @__PURE__ */ jsx25(
2648
- Input5,
3078
+ return /* @__PURE__ */ jsxs22(Fragment6, { children: [
3079
+ /* @__PURE__ */ jsx31(Text21, { color: "gray.700", children: "Entre com seu e-mail e senha para ativar esta Central em ambiente de desenvolvimento. Se o e-mail ainda n\xE3o existir na Central de Ativa\xE7\xF5es, o usu\xE1rio ser\xE1 criado automaticamente com perfil de desenvolvedor." }),
3080
+ /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3081
+ /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Nome do usu\xE1rio" }),
3082
+ /* @__PURE__ */ jsx31(
3083
+ Input7,
2649
3084
  {
2650
3085
  value: devName,
2651
3086
  onChange: (event) => setDevName(event.target.value),
@@ -2654,10 +3089,10 @@ function ActivationPage() {
2654
3089
  }
2655
3090
  )
2656
3091
  ] }),
2657
- /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2658
- /* @__PURE__ */ jsx25(Text16, { fontWeight: "medium", children: "E-mail *" }),
2659
- /* @__PURE__ */ jsx25(
2660
- Input5,
3092
+ /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3093
+ /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "E-mail *" }),
3094
+ /* @__PURE__ */ jsx31(
3095
+ Input7,
2661
3096
  {
2662
3097
  type: "email",
2663
3098
  value: devEmail,
@@ -2667,10 +3102,10 @@ function ActivationPage() {
2667
3102
  }
2668
3103
  )
2669
3104
  ] }),
2670
- /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2671
- /* @__PURE__ */ jsx25(Text16, { fontWeight: "medium", children: "Senha *" }),
2672
- /* @__PURE__ */ jsx25(
2673
- Input5,
3105
+ /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3106
+ /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Senha *" }),
3107
+ /* @__PURE__ */ jsx31(
3108
+ Input7,
2674
3109
  {
2675
3110
  type: "password",
2676
3111
  value: devPassword,
@@ -2681,8 +3116,8 @@ function ActivationPage() {
2681
3116
  }
2682
3117
  )
2683
3118
  ] }),
2684
- /* @__PURE__ */ jsx25(
2685
- Button10,
3119
+ /* @__PURE__ */ jsx31(
3120
+ Button14,
2686
3121
  {
2687
3122
  colorPalette: "blue",
2688
3123
  onClick: activateDevLocal,
@@ -2691,8 +3126,8 @@ function ActivationPage() {
2691
3126
  children: "Ativar ambiente de desenvolvimento"
2692
3127
  }
2693
3128
  ),
2694
- /* @__PURE__ */ jsx25(
2695
- Button10,
3129
+ /* @__PURE__ */ jsx31(
3130
+ Button14,
2696
3131
  {
2697
3132
  variant: "outline",
2698
3133
  onClick: () => setShowCodeFlow(true),
@@ -2705,7 +3140,7 @@ function ActivationPage() {
2705
3140
  const rootMode = config?.mode === "root-bootstrap" || activation.details?.role === "root";
2706
3141
  const isDevelopmentMember = !rootMode && config?.technical?.ambiente === "desenvolvimento";
2707
3142
  if (activation.status === "loading" || !config) {
2708
- return /* @__PURE__ */ jsx25(Box15, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs16(
3143
+ return /* @__PURE__ */ jsx31(Box19, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs22(
2709
3144
  VStack3,
2710
3145
  {
2711
3146
  maxW: "760px",
@@ -2716,14 +3151,14 @@ function ActivationPage() {
2716
3151
  align: "stretch",
2717
3152
  gap: 5,
2718
3153
  children: [
2719
- /* @__PURE__ */ jsx25(Heading10, { children: "Preparando ativa\xE7\xE3o..." }),
2720
- error ? /* @__PURE__ */ jsx25(Text16, { color: "red.600", children: error }) : null
3154
+ /* @__PURE__ */ jsx31(Heading11, { children: "Preparando ativa\xE7\xE3o..." }),
3155
+ error ? /* @__PURE__ */ jsx31(Text21, { color: "red.600", children: error }) : null
2721
3156
  ]
2722
3157
  }
2723
3158
  ) });
2724
3159
  }
2725
3160
  if (rootMode) {
2726
- return /* @__PURE__ */ jsx25(Box15, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs16(
3161
+ return /* @__PURE__ */ jsx31(Box19, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs22(
2727
3162
  VStack3,
2728
3163
  {
2729
3164
  maxW: "560px",
@@ -2734,21 +3169,21 @@ function ActivationPage() {
2734
3169
  align: "stretch",
2735
3170
  gap: 5,
2736
3171
  children: [
2737
- /* @__PURE__ */ jsx25(Heading10, { children: "Ativa\xE7\xE3o inicial do Ecossistema Oon" }),
2738
- /* @__PURE__ */ jsx25(Text16, { color: "gray.600", children: "Esta \xE9 a aplica\xE7\xE3o root do ecossistema. Informe somente o e-mail e a senha do primeiro administrador. O Core criar\xE1 a estrutura m\xEDnima necess\xE1ria para liberar o primeiro login." }),
2739
- /* @__PURE__ */ jsxs16(Text16, { fontSize: "sm", color: "gray.500", children: [
3172
+ /* @__PURE__ */ jsx31(Heading11, { children: "Ativa\xE7\xE3o inicial do Ecossistema Oon" }),
3173
+ /* @__PURE__ */ jsx31(Text21, { color: "gray.600", children: "Esta \xE9 a aplica\xE7\xE3o root do ecossistema. Informe somente o e-mail e a senha do primeiro administrador. O Core criar\xE1 a estrutura m\xEDnima necess\xE1ria para liberar o primeiro login." }),
3174
+ /* @__PURE__ */ jsxs22(Text21, { fontSize: "sm", color: "gray.500", children: [
2740
3175
  "App: ",
2741
3176
  config.technical.appCode,
2742
3177
  " \xB7 Ambiente:",
2743
3178
  " ",
2744
3179
  config.technical.ambiente
2745
3180
  ] }),
2746
- error ? /* @__PURE__ */ jsx25(Text16, { color: "red.600", children: error }) : null,
2747
- step !== 6 ? /* @__PURE__ */ jsxs16(Fragment4, { children: [
2748
- /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2749
- /* @__PURE__ */ jsx25(Text16, { fontWeight: "medium", children: "E-mail do administrador *" }),
2750
- /* @__PURE__ */ jsx25(
2751
- Input5,
3181
+ error ? /* @__PURE__ */ jsx31(Text21, { color: "red.600", children: error }) : null,
3182
+ step !== 6 ? /* @__PURE__ */ jsxs22(Fragment6, { children: [
3183
+ /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3184
+ /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "E-mail do administrador *" }),
3185
+ /* @__PURE__ */ jsx31(
3186
+ Input7,
2752
3187
  {
2753
3188
  type: "email",
2754
3189
  autoComplete: "email",
@@ -2758,10 +3193,10 @@ function ActivationPage() {
2758
3193
  }
2759
3194
  )
2760
3195
  ] }),
2761
- /* @__PURE__ */ jsxs16(Box15, { w: "100%", children: [
2762
- /* @__PURE__ */ jsx25(Text16, { fontWeight: "medium", children: "Senha *" }),
2763
- /* @__PURE__ */ jsx25(
2764
- Input5,
3196
+ /* @__PURE__ */ jsxs22(Box19, { w: "100%", children: [
3197
+ /* @__PURE__ */ jsx31(Text21, { fontWeight: "medium", children: "Senha *" }),
3198
+ /* @__PURE__ */ jsx31(
3199
+ Input7,
2765
3200
  {
2766
3201
  type: "password",
2767
3202
  minLength: 8,
@@ -2772,8 +3207,8 @@ function ActivationPage() {
2772
3207
  }
2773
3208
  )
2774
3209
  ] }),
2775
- /* @__PURE__ */ jsx25(
2776
- Button10,
3210
+ /* @__PURE__ */ jsx31(
3211
+ Button14,
2777
3212
  {
2778
3213
  colorPalette: "blue",
2779
3214
  onClick: activateRoot,
@@ -2782,15 +3217,15 @@ function ActivationPage() {
2782
3217
  children: "Criar ecossistema e ativar"
2783
3218
  }
2784
3219
  )
2785
- ] }) : /* @__PURE__ */ jsxs16(Fragment4, { children: [
2786
- /* @__PURE__ */ jsx25(Heading10, { size: "md", children: "Ativa\xE7\xE3o conclu\xEDda" }),
2787
- /* @__PURE__ */ jsx25(Text16, { children: "Usu\xE1rio, tenant, aplicativo, licen\xE7a e permiss\xF5es foram preparados. Redirecionando para o primeiro login..." })
3220
+ ] }) : /* @__PURE__ */ jsxs22(Fragment6, { children: [
3221
+ /* @__PURE__ */ jsx31(Heading11, { size: "md", children: "Ativa\xE7\xE3o conclu\xEDda" }),
3222
+ /* @__PURE__ */ jsx31(Text21, { children: "Usu\xE1rio, tenant, aplicativo, licen\xE7a e permiss\xF5es foram preparados. Redirecionando para o primeiro login..." })
2788
3223
  ] })
2789
3224
  ]
2790
3225
  }
2791
3226
  ) });
2792
3227
  }
2793
- return /* @__PURE__ */ jsx25(Box15, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs16(
3228
+ return /* @__PURE__ */ jsx31(Box19, { minH: "100vh", bg: "gray.50", p: 8, children: /* @__PURE__ */ jsxs22(
2794
3229
  VStack3,
2795
3230
  {
2796
3231
  maxW: "760px",
@@ -2801,8 +3236,8 @@ function ActivationPage() {
2801
3236
  align: "stretch",
2802
3237
  gap: 5,
2803
3238
  children: [
2804
- /* @__PURE__ */ jsx25(Heading10, { children: "Ativa\xE7\xE3o da Central Oon" }),
2805
- /* @__PURE__ */ jsxs16(Text16, { children: [
3239
+ /* @__PURE__ */ jsx31(Heading11, { children: "Ativa\xE7\xE3o da Central Oon" }),
3240
+ /* @__PURE__ */ jsxs22(Text21, { children: [
2806
3241
  "App: ",
2807
3242
  config.technical.appCode,
2808
3243
  " \xB7 Ambiente:",
@@ -2812,12 +3247,12 @@ function ActivationPage() {
2812
3247
  " ",
2813
3248
  config.technical.centralAtivacaoUrl || config.technical.centralAtivacaoHost
2814
3249
  ] }),
2815
- error ? /* @__PURE__ */ jsx25(Text16, { color: "red.600", children: error }) : null,
3250
+ error ? /* @__PURE__ */ jsx31(Text21, { color: "red.600", children: error }) : null,
2816
3251
  step === 1 && isDevelopmentMember && !showCodeFlow ? renderDevLocalActivation() : null,
2817
- step === 1 && (!isDevelopmentMember || showCodeFlow) && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2818
- /* @__PURE__ */ jsx25(Text16, { children: "Informe o c\xF3digo de ativa\xE7\xE3o para validar tenant, aplicativo e licen\xE7a antes de consumir o c\xF3digo." }),
2819
- /* @__PURE__ */ jsx25(
2820
- Input5,
3252
+ step === 1 && (!isDevelopmentMember || showCodeFlow) && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3253
+ /* @__PURE__ */ jsx31(Text21, { children: "Informe o c\xF3digo de ativa\xE7\xE3o para validar tenant, aplicativo e licen\xE7a antes de consumir o c\xF3digo." }),
3254
+ /* @__PURE__ */ jsx31(
3255
+ Input7,
2821
3256
  {
2822
3257
  "aria-label": "C\xF3digo de ativa\xE7\xE3o",
2823
3258
  value: code,
@@ -2825,8 +3260,8 @@ function ActivationPage() {
2825
3260
  placeholder: "OON-XXXX"
2826
3261
  }
2827
3262
  ),
2828
- /* @__PURE__ */ jsx25(
2829
- Button10,
3263
+ /* @__PURE__ */ jsx31(
3264
+ Button14,
2830
3265
  {
2831
3266
  onClick: validateCode,
2832
3267
  loading: submitting,
@@ -2834,8 +3269,8 @@ function ActivationPage() {
2834
3269
  children: "Validar c\xF3digo"
2835
3270
  }
2836
3271
  ),
2837
- isDevelopmentMember ? /* @__PURE__ */ jsx25(
2838
- Button10,
3272
+ isDevelopmentMember ? /* @__PURE__ */ jsx31(
3273
+ Button14,
2839
3274
  {
2840
3275
  variant: "outline",
2841
3276
  onClick: () => setShowCodeFlow(false),
@@ -2844,25 +3279,25 @@ function ActivationPage() {
2844
3279
  }
2845
3280
  ) : null
2846
3281
  ] }),
2847
- step === 2 && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2848
- /* @__PURE__ */ jsx25(Heading10, { size: "md", children: "Confirma\xE7\xE3o" }),
2849
- /* @__PURE__ */ jsx25("pre", { children: JSON.stringify(preview, null, 2) }),
2850
- /* @__PURE__ */ jsx25(Button10, { onClick: () => setStep(3), children: "Continuar" })
3282
+ step === 2 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3283
+ /* @__PURE__ */ jsx31(Heading11, { size: "md", children: "Confirma\xE7\xE3o" }),
3284
+ /* @__PURE__ */ jsx31("pre", { children: JSON.stringify(preview, null, 2) }),
3285
+ /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(3), children: "Continuar" })
2851
3286
  ] }),
2852
- step === 3 && /* @__PURE__ */ jsxs16(Fragment4, { children: [
3287
+ step === 3 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
2853
3288
  config.globalFields.map(
2854
3289
  (field) => renderField(field, global, setGlobal)
2855
3290
  ),
2856
- /* @__PURE__ */ jsx25(Button10, { onClick: () => setStep(4), children: "Continuar" })
3291
+ /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(4), children: "Continuar" })
2857
3292
  ] }),
2858
- step === 4 && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2859
- config.appFields.length ? config.appFields.map((field) => renderField(field, app, setApp)) : /* @__PURE__ */ jsx25(Text16, { children: "Nenhum par\xE2metro adicional declarado." }),
2860
- /* @__PURE__ */ jsx25(Button10, { onClick: () => setStep(5), children: "Revisar" })
3293
+ step === 4 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3294
+ config.appFields.length ? config.appFields.map((field) => renderField(field, app, setApp)) : /* @__PURE__ */ jsx31(Text21, { children: "Nenhum par\xE2metro adicional declarado." }),
3295
+ /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(5), children: "Revisar" })
2861
3296
  ] }),
2862
- step === 5 && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2863
- /* @__PURE__ */ jsx25(Text16, { children: "Ao confirmar, o c\xF3digo ser\xE1 consumido e a inst\xE2ncia ser\xE1 registrada no Ecossistema Oon." }),
2864
- /* @__PURE__ */ jsx25(
2865
- Button10,
3297
+ step === 5 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3298
+ /* @__PURE__ */ jsx31(Text21, { children: "Ao confirmar, o c\xF3digo ser\xE1 consumido e a inst\xE2ncia ser\xE1 registrada no Ecossistema Oon." }),
3299
+ /* @__PURE__ */ jsx31(
3300
+ Button14,
2866
3301
  {
2867
3302
  colorPalette: "blue",
2868
3303
  onClick: completeMemberActivation,
@@ -2872,14 +3307,14 @@ function ActivationPage() {
2872
3307
  }
2873
3308
  )
2874
3309
  ] }),
2875
- step === 6 && /* @__PURE__ */ jsxs16(Fragment4, { children: [
2876
- /* @__PURE__ */ jsx25(Heading10, { size: "md", children: "Ativa\xE7\xE3o conclu\xEDda" }),
2877
- devResult?.appCode ? /* @__PURE__ */ jsxs16(Text16, { children: [
3310
+ step === 6 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
3311
+ /* @__PURE__ */ jsx31(Heading11, { size: "md", children: "Ativa\xE7\xE3o conclu\xEDda" }),
3312
+ devResult?.appCode ? /* @__PURE__ */ jsxs22(Text21, { children: [
2878
3313
  "C\xF3digo do app: ",
2879
3314
  devResult.appCode,
2880
3315
  ". Redirecionando para a Central em desenvolvimento..."
2881
- ] }) : /* @__PURE__ */ jsx25(Text16, { children: "Redirecionando para o login..." }),
2882
- devResult?.instrucoes?.env ? /* @__PURE__ */ jsx25(Text16, { fontSize: "sm", color: "gray.500", children: devResult.instrucoes.env }) : null
3316
+ ] }) : /* @__PURE__ */ jsx31(Text21, { children: "Redirecionando para o login..." }),
3317
+ devResult?.instrucoes?.env ? /* @__PURE__ */ jsx31(Text21, { fontSize: "sm", color: "gray.500", children: devResult.instrucoes.env }) : null
2883
3318
  ] })
2884
3319
  ]
2885
3320
  }
@@ -2889,47 +3324,47 @@ function InstanceBlockedPage({
2889
3324
  title,
2890
3325
  message
2891
3326
  }) {
2892
- return /* @__PURE__ */ jsxs16(Box15, { p: 8, children: [
2893
- /* @__PURE__ */ jsx25(Heading10, { children: title }),
2894
- /* @__PURE__ */ jsx25(Text16, { children: message })
3327
+ return /* @__PURE__ */ jsxs22(Box19, { p: 8, children: [
3328
+ /* @__PURE__ */ jsx31(Heading11, { children: title }),
3329
+ /* @__PURE__ */ jsx31(Text21, { children: message })
2895
3330
  ] });
2896
3331
  }
2897
3332
 
2898
3333
  // src/security/RouteGuard.tsx
2899
- import { Fragment as Fragment5, jsx as jsx26 } from "react/jsx-runtime";
3334
+ import { Fragment as Fragment7, jsx as jsx32 } from "react/jsx-runtime";
2900
3335
  function RouteGuard({
2901
3336
  permission,
2902
3337
  children
2903
3338
  }) {
2904
3339
  const { status, hasPermission } = useOonAuth();
2905
- if (status === "loading") return /* @__PURE__ */ jsx26(LoadingScreen, {});
2906
- if (status === "unauthenticated") return /* @__PURE__ */ jsx26(LoadingScreen, { message: "Redirecionando para o login..." });
3340
+ if (status === "loading") return /* @__PURE__ */ jsx32(LoadingScreen, {});
3341
+ if (status === "unauthenticated") return /* @__PURE__ */ jsx32(LoadingScreen, { message: "Redirecionando para o login..." });
2907
3342
  if (!hasPermission(permission)) {
2908
- return /* @__PURE__ */ jsx26(LoadingScreen, { message: "Voc\xEA n\xE3o tem acesso a esta tela." });
3343
+ return /* @__PURE__ */ jsx32(LoadingScreen, { message: "Voc\xEA n\xE3o tem acesso a esta tela." });
2909
3344
  }
2910
- return /* @__PURE__ */ jsx26(Fragment5, { children });
3345
+ return /* @__PURE__ */ jsx32(Fragment7, { children });
2911
3346
  }
2912
3347
 
2913
3348
  // src/security/ActivationGuard.tsx
2914
3349
  import { Navigate as Navigate3 } from "react-router-dom";
2915
- import { jsx as jsx27 } from "react/jsx-runtime";
3350
+ import { jsx as jsx33 } from "react/jsx-runtime";
2916
3351
  function ActivationGuard({ children }) {
2917
3352
  const { status } = useActivation();
2918
3353
  if (status === "loading") return null;
2919
- if (status === "suspended") return /* @__PURE__ */ jsx27(Navigate3, { to: "/instancia-suspensa", replace: true });
2920
- if (status === "revoked") return /* @__PURE__ */ jsx27(Navigate3, { to: "/instancia-revogada", replace: true });
2921
- if (status !== "active" && window.location.pathname !== "/ativacao") return /* @__PURE__ */ jsx27(Navigate3, { to: "/ativacao", replace: true });
3354
+ if (status === "suspended") return /* @__PURE__ */ jsx33(Navigate3, { to: "/instancia-suspensa", replace: true });
3355
+ if (status === "revoked") return /* @__PURE__ */ jsx33(Navigate3, { to: "/instancia-revogada", replace: true });
3356
+ if (status !== "active" && window.location.pathname !== "/ativacao") return /* @__PURE__ */ jsx33(Navigate3, { to: "/ativacao", replace: true });
2922
3357
  return children;
2923
3358
  }
2924
3359
 
2925
3360
  // src/app/createOonRouter.tsx
2926
- import { jsx as jsx28 } from "react/jsx-runtime";
3361
+ import { jsx as jsx34 } from "react/jsx-runtime";
2927
3362
  function createOonRouter({ app, menu, routes, security, layout, registry }) {
2928
3363
  const guardEnabled = security?.enableRouteGuard !== false;
2929
3364
  const publicRoutes = routes.filter((route) => route.public).map((route) => ({ path: route.path, element: route.element }));
2930
3365
  const privateSource = routes.filter((route) => !route.public);
2931
3366
  const privateRoutes = privateSource.map((route) => {
2932
- const element = guardEnabled ? /* @__PURE__ */ jsx28(RouteGuard, { permission: route.permissions, children: route.element }) : route.element;
3367
+ const element = guardEnabled ? /* @__PURE__ */ jsx34(RouteGuard, { permission: route.permissions, children: route.element }) : route.element;
2933
3368
  return route.path === "/" ? { index: true, element } : { path: route.path.replace(/^\//, ""), element };
2934
3369
  });
2935
3370
  const hasIndexRoute = privateSource.some((route) => route.path === "/");
@@ -2937,7 +3372,7 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2937
3372
  if (!hasIndexRoute && firstRoute) {
2938
3373
  privateRoutes.unshift({
2939
3374
  index: true,
2940
- element: /* @__PURE__ */ jsx28(Navigate4, { to: firstRoute.path, replace: true })
3375
+ element: /* @__PURE__ */ jsx34(Navigate4, { to: firstRoute.path, replace: true })
2941
3376
  });
2942
3377
  }
2943
3378
  const customPaths = new Set(publicRoutes.map((route) => route.path));
@@ -2945,19 +3380,19 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2945
3380
  if (!customPaths.has("/login")) {
2946
3381
  builtInPublicRoutes.push({
2947
3382
  path: "/login",
2948
- element: /* @__PURE__ */ jsx28(ActivationGuard, { children: /* @__PURE__ */ jsx28(LoginPage, { app }) })
3383
+ element: /* @__PURE__ */ jsx34(ActivationGuard, { children: /* @__PURE__ */ jsx34(LoginPage, { app }) })
2949
3384
  });
2950
3385
  }
2951
3386
  if (!customPaths.has("/ativacao")) {
2952
3387
  builtInPublicRoutes.push({
2953
3388
  path: "/ativacao",
2954
- element: /* @__PURE__ */ jsx28(ActivationPage, {})
3389
+ element: /* @__PURE__ */ jsx34(ActivationPage, {})
2955
3390
  });
2956
3391
  }
2957
3392
  if (!customPaths.has("/instancia-suspensa")) {
2958
3393
  builtInPublicRoutes.push({
2959
3394
  path: "/instancia-suspensa",
2960
- element: /* @__PURE__ */ jsx28(
3395
+ element: /* @__PURE__ */ jsx34(
2961
3396
  InstanceBlockedPage,
2962
3397
  {
2963
3398
  title: "Inst\xE2ncia suspensa",
@@ -2969,7 +3404,7 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2969
3404
  if (!customPaths.has("/instancia-revogada")) {
2970
3405
  builtInPublicRoutes.push({
2971
3406
  path: "/instancia-revogada",
2972
- element: /* @__PURE__ */ jsx28(
3407
+ element: /* @__PURE__ */ jsx34(
2973
3408
  InstanceBlockedPage,
2974
3409
  {
2975
3410
  title: "Inst\xE2ncia revogada",
@@ -2981,7 +3416,7 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2981
3416
  if (!customPaths.has("/acesso-negado")) {
2982
3417
  builtInPublicRoutes.push({
2983
3418
  path: "/acesso-negado",
2984
- element: /* @__PURE__ */ jsx28(AccessDeniedPage, { app })
3419
+ element: /* @__PURE__ */ jsx34(AccessDeniedPage, { app })
2985
3420
  });
2986
3421
  }
2987
3422
  const tree = [
@@ -2989,7 +3424,7 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2989
3424
  ...publicRoutes,
2990
3425
  {
2991
3426
  path: "/",
2992
- element: /* @__PURE__ */ jsx28(ActivationGuard, { children: /* @__PURE__ */ jsx28(AppAccessGuard, { children: /* @__PURE__ */ jsx28(AuthenticatedLayout, { app, menu, layout, registry }) }) }),
3427
+ element: /* @__PURE__ */ jsx34(ActivationGuard, { children: /* @__PURE__ */ jsx34(AppAccessGuard, { children: /* @__PURE__ */ jsx34(AuthenticatedLayout, { app, menu, layout, registry }) }) }),
2993
3428
  children: privateRoutes
2994
3429
  }
2995
3430
  ];
@@ -2997,13 +3432,13 @@ function createOonRouter({ app, menu, routes, security, layout, registry }) {
2997
3432
  }
2998
3433
 
2999
3434
  // src/app/OonApp.tsx
3000
- import { jsx as jsx29 } from "react/jsx-runtime";
3435
+ import { jsx as jsx35 } from "react/jsx-runtime";
3001
3436
  function localLoginUrl() {
3002
3437
  const current = `${window.location.pathname}${window.location.search}`;
3003
3438
  return `/login?redirect=${encodeURIComponent(current)}`;
3004
3439
  }
3005
3440
  function OonApp({ config }) {
3006
- const { http, storage, router } = useMemo4(() => {
3441
+ const { http, storage, router } = useMemo6(() => {
3007
3442
  const storage2 = createTokenStorage(config.app.id);
3008
3443
  const externalLoginUrl = config.auth?.loginUrl ?? config.api.meusAppsUrl;
3009
3444
  const http2 = createRestClient({
@@ -3032,11 +3467,11 @@ function OonApp({ config }) {
3032
3467
  });
3033
3468
  return { http: http2, storage: storage2, router: router2 };
3034
3469
  }, [config]);
3035
- return /* @__PURE__ */ jsx29(OonProviders, { config, http, storage, children: /* @__PURE__ */ jsx29(RouterProvider, { router }) });
3470
+ return /* @__PURE__ */ jsx35(OonProviders, { config, http, storage, children: /* @__PURE__ */ jsx35(RouterProvider, { router }) });
3036
3471
  }
3037
3472
 
3038
3473
  // src/start.tsx
3039
- import { jsx as jsx30 } from "react/jsx-runtime";
3474
+ import { jsx as jsx36 } from "react/jsx-runtime";
3040
3475
  function validateConfig(config) {
3041
3476
  if (!config?.app?.id) throw new Error("oonCoreFront.start: config.app.id \xE9 obrigat\xF3rio.");
3042
3477
  if (!config?.api?.baseUrl) throw new Error("oonCoreFront.start: config.api.baseUrl \xE9 obrigat\xF3rio.");
@@ -3070,12 +3505,24 @@ function start(config) {
3070
3505
  const el = document.getElementById(rootId);
3071
3506
  if (!el) throw new Error(`oonCoreFront.start: elemento #${rootId} n\xE3o encontrado no DOM.`);
3072
3507
  createRoot(el).render(
3073
- /* @__PURE__ */ jsx30(StrictMode, { children: /* @__PURE__ */ jsx30(OonApp, { config }) })
3508
+ /* @__PURE__ */ jsx36(StrictMode, { children: /* @__PURE__ */ jsx36(OonApp, { config }) })
3074
3509
  );
3075
3510
  }
3076
3511
  var oonCoreFront = { start };
3077
3512
 
3078
3513
  // src/manifest.ts
3514
+ function mergeRegistry(manifestRegistry, runtimeRegistry, customComponents) {
3515
+ if (!manifestRegistry && !runtimeRegistry && !customComponents) return void 0;
3516
+ return {
3517
+ layoutSlots: { ...manifestRegistry?.layoutSlots, ...runtimeRegistry?.layoutSlots },
3518
+ fieldRenderers: { ...manifestRegistry?.fieldRenderers, ...runtimeRegistry?.fieldRenderers },
3519
+ cellRenderers: { ...manifestRegistry?.cellRenderers, ...runtimeRegistry?.cellRenderers },
3520
+ cardRenderers: { ...manifestRegistry?.cardRenderers, ...runtimeRegistry?.cardRenderers },
3521
+ actionRenderers: { ...manifestRegistry?.actionRenderers, ...runtimeRegistry?.actionRenderers },
3522
+ pageComponents: { ...manifestRegistry?.pageComponents, ...runtimeRegistry?.pageComponents, ...customComponents },
3523
+ menuRenderers: { ...manifestRegistry?.menuRenderers, ...runtimeRegistry?.menuRenderers }
3524
+ };
3525
+ }
3079
3526
  function manifestToConfig(manifest, runtime) {
3080
3527
  const views = [];
3081
3528
  for (const c of manifest.collections ?? []) {
@@ -3085,7 +3532,10 @@ function manifestToConfig(manifest, runtime) {
3085
3532
  mode: c.mode ?? "dynamic",
3086
3533
  path: c.path,
3087
3534
  label: c.label,
3088
- section: c.section
3535
+ section: c.section,
3536
+ list: c.list,
3537
+ relations: c.relations,
3538
+ detailModal: c.detailModal
3089
3539
  };
3090
3540
  views.push(view);
3091
3541
  }
@@ -3114,11 +3564,19 @@ function manifestToConfig(manifest, runtime) {
3114
3564
  };
3115
3565
  views.push(view);
3116
3566
  }
3567
+ const registry = mergeRegistry(manifest.registry, runtime.registry, runtime.customComponents);
3568
+ const auth = {
3569
+ mode: runtime.auth?.mode ?? manifest.auth?.mode ?? "bearer",
3570
+ loginUrl: runtime.auth?.loginUrl ?? manifest.auth?.loginUrl,
3571
+ tokenParam: runtime.auth?.tokenParam ?? manifest.auth?.tokenParam ?? "code",
3572
+ devToken: runtime.auth?.devToken ?? runtime.devToken
3573
+ };
3117
3574
  return {
3118
3575
  app: {
3119
3576
  id: manifest.slug,
3120
3577
  name: manifest.name,
3121
- title: manifest.name
3578
+ title: manifest.name,
3579
+ kind: runtime.appKind ?? manifest.appKind
3122
3580
  },
3123
3581
  api: {
3124
3582
  baseUrl: runtime.apiBaseUrl,
@@ -3126,7 +3584,7 @@ function manifestToConfig(manifest, runtime) {
3126
3584
  assistantBaseUrl: runtime.assistantBaseUrl,
3127
3585
  versionPrefix: runtime.versionPrefix ?? ""
3128
3586
  },
3129
- auth: { mode: "bearer", tokenParam: "code", devToken: runtime.devToken },
3587
+ auth,
3130
3588
  security: {
3131
3589
  enableRouteGuard: true,
3132
3590
  enablePermissionGate: true,
@@ -3134,8 +3592,15 @@ function manifestToConfig(manifest, runtime) {
3134
3592
  disableConsoleInProduction: true
3135
3593
  },
3136
3594
  layout: manifest.layout,
3137
- registry: manifest.registry,
3138
- ui: { schemaVersion: manifest.schemaVersion, layout: manifest.layout, registry: manifest.registry, navigation: manifest.navigation, views, pages: manifest.pages }
3595
+ registry,
3596
+ ui: {
3597
+ schemaVersion: manifest.schemaVersion,
3598
+ layout: manifest.layout,
3599
+ registry,
3600
+ navigation: manifest.navigation,
3601
+ views,
3602
+ pages: manifest.pages
3603
+ }
3139
3604
  };
3140
3605
  }
3141
3606
  function startFromManifest(manifest, runtime) {
@@ -3160,34 +3625,34 @@ function defineOonModule(mod) {
3160
3625
  }
3161
3626
 
3162
3627
  // src/components/CoreIntegration.tsx
3163
- import { Badge as Badge3, Box as Box16, Button as Button11, Flex as Flex11, Heading as Heading11, Stack as Stack8, Text as Text17 } from "@chakra-ui/react";
3164
- import { useMutation as useMutation3 } from "@tanstack/react-query";
3165
- import { jsx as jsx31, jsxs as jsxs17 } from "react/jsx-runtime";
3628
+ import { Badge as Badge5, Box as Box20, Button as Button15, Flex as Flex14, Heading as Heading12, Stack as Stack9, Text as Text22 } from "@chakra-ui/react";
3629
+ import { useMutation as useMutation4 } from "@tanstack/react-query";
3630
+ import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
3166
3631
  function CoreIntegration({ label = "Integra\xE7\xF5es" }) {
3167
3632
  const { http } = useOonApi();
3168
3633
  const metadata = useCoreMetadata();
3169
- const reprocess = useMutation3({
3634
+ const reprocess = useMutation4({
3170
3635
  mutationFn: () => http.post("/integrations/actions/process-active", {}, { headers: { "x-oon-origin": "integration" } })
3171
3636
  });
3172
- if (metadata.isLoading) return /* @__PURE__ */ jsx31(LoadingScreen, {});
3173
- if (metadata.isError) return /* @__PURE__ */ jsx31(ErrorState, { error: metadata.error });
3637
+ if (metadata.isLoading) return /* @__PURE__ */ jsx37(LoadingScreen, {});
3638
+ if (metadata.isError) return /* @__PURE__ */ jsx37(ErrorState, { error: metadata.error });
3174
3639
  const integrations = metadata.data?.integrations ?? [];
3175
- return /* @__PURE__ */ jsxs17(Stack8, { gap: 6, children: [
3176
- /* @__PURE__ */ jsxs17(Flex11, { align: "center", justify: "space-between", children: [
3177
- /* @__PURE__ */ jsx31(Heading11, { size: "lg", children: label }),
3178
- /* @__PURE__ */ jsx31(Button11, { size: "sm", variant: "outline", loading: reprocess.isPending, onClick: () => reprocess.mutate(), children: "Reprocessar ativos" })
3640
+ return /* @__PURE__ */ jsxs23(Stack9, { gap: 6, children: [
3641
+ /* @__PURE__ */ jsxs23(Flex14, { align: "center", justify: "space-between", children: [
3642
+ /* @__PURE__ */ jsx37(Heading12, { size: "lg", children: label }),
3643
+ /* @__PURE__ */ jsx37(Button15, { size: "sm", variant: "outline", loading: reprocess.isPending, onClick: () => reprocess.mutate(), children: "Reprocessar ativos" })
3179
3644
  ] }),
3180
- /* @__PURE__ */ jsx31(Stack8, { gap: 3, children: integrations.length === 0 ? /* @__PURE__ */ jsx31(Text17, { color: "gray.400", children: "Nenhuma integra\xE7\xE3o declarada." }) : integrations.map((it, idx) => /* @__PURE__ */ jsx31(
3181
- Box16,
3645
+ /* @__PURE__ */ jsx37(Stack9, { gap: 3, children: integrations.length === 0 ? /* @__PURE__ */ jsx37(Text22, { color: "gray.400", children: "Nenhuma integra\xE7\xE3o declarada." }) : integrations.map((it, idx) => /* @__PURE__ */ jsx37(
3646
+ Box20,
3182
3647
  {
3183
3648
  borderWidth: "1px",
3184
3649
  borderColor: "gray.200",
3185
3650
  borderRadius: "md",
3186
3651
  bg: "white",
3187
3652
  p: 4,
3188
- children: /* @__PURE__ */ jsxs17(Flex11, { align: "center", justify: "space-between", children: [
3189
- /* @__PURE__ */ jsx31(Text17, { fontWeight: "medium", children: it.label ?? it.name ?? "Integra\xE7\xE3o" }),
3190
- /* @__PURE__ */ jsx31(Badge3, { colorPalette: it.status === "erro" ? "red" : it.status === "ativo" ? "green" : "gray", children: it.status ?? "\u2014" })
3653
+ children: /* @__PURE__ */ jsxs23(Flex14, { align: "center", justify: "space-between", children: [
3654
+ /* @__PURE__ */ jsx37(Text22, { fontWeight: "medium", children: it.label ?? it.name ?? "Integra\xE7\xE3o" }),
3655
+ /* @__PURE__ */ jsx37(Badge5, { colorPalette: it.status === "erro" ? "red" : it.status === "ativo" ? "green" : "gray", children: it.status ?? "\u2014" })
3191
3656
  ] })
3192
3657
  },
3193
3658
  it.id ?? it.name ?? idx
@@ -3196,36 +3661,36 @@ function CoreIntegration({ label = "Integra\xE7\xF5es" }) {
3196
3661
  }
3197
3662
 
3198
3663
  // src/components/CoreCurrency.tsx
3199
- import { Button as Button12, Flex as Flex12, Heading as Heading12, Stack as Stack9, Text as Text18 } from "@chakra-ui/react";
3200
- import { useMutation as useMutation4, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
3201
- import { jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
3664
+ import { Button as Button16, Flex as Flex15, Heading as Heading13, Stack as Stack10, Text as Text23 } from "@chakra-ui/react";
3665
+ import { useMutation as useMutation5, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
3666
+ import { jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
3202
3667
  function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/moedas", columns }) {
3203
3668
  const { http } = useOonApi();
3204
- const queryClient = useQueryClient3();
3205
- const updateRates = useMutation4({
3669
+ const queryClient = useQueryClient5();
3670
+ const updateRates = useMutation5({
3206
3671
  mutationFn: () => http.post(`${endpoint}/actions/update-rates`, {}, { headers: { "x-oon-origin": "integration" } }),
3207
3672
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ["oon", "list", endpoint] })
3208
3673
  });
3209
- return /* @__PURE__ */ jsxs18(Stack9, { gap: 6, children: [
3210
- /* @__PURE__ */ jsxs18(Flex12, { align: "center", justify: "space-between", children: [
3211
- /* @__PURE__ */ jsx32(Heading12, { size: "lg", children: label }),
3212
- /* @__PURE__ */ jsx32(Button12, { size: "sm", colorPalette: "blue", loading: updateRates.isPending, onClick: () => updateRates.mutate(), children: "Atualizar cota\xE7\xF5es" })
3674
+ return /* @__PURE__ */ jsxs24(Stack10, { gap: 6, children: [
3675
+ /* @__PURE__ */ jsxs24(Flex15, { align: "center", justify: "space-between", children: [
3676
+ /* @__PURE__ */ jsx38(Heading13, { size: "lg", children: label }),
3677
+ /* @__PURE__ */ jsx38(Button16, { size: "sm", colorPalette: "blue", loading: updateRates.isPending, onClick: () => updateRates.mutate(), children: "Atualizar cota\xE7\xF5es" })
3213
3678
  ] }),
3214
- updateRates.isError ? /* @__PURE__ */ jsx32(Text18, { fontSize: "sm", color: "red.600", children: updateRates.error?.message }) : null,
3215
- /* @__PURE__ */ jsx32(CoreCollection, { model, label: "", mode: columns ? "full" : "dynamic", endpoint, columns })
3679
+ updateRates.isError ? /* @__PURE__ */ jsx38(Text23, { fontSize: "sm", color: "red.600", children: updateRates.error?.message }) : null,
3680
+ /* @__PURE__ */ jsx38(CoreCollection, { model, label: "", mode: columns ? "full" : "dynamic", endpoint, columns })
3216
3681
  ] });
3217
3682
  }
3218
3683
 
3219
3684
  // src/components/CoreAssistant.tsx
3220
- import { useState as useState10 } from "react";
3221
- import { Box as Box17, Button as Button13, Flex as Flex13, Heading as Heading13, Input as Input6, Stack as Stack10, Text as Text19 } from "@chakra-ui/react";
3222
- import { useMutation as useMutation5 } from "@tanstack/react-query";
3223
- import { jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
3685
+ import { useState as useState14 } from "react";
3686
+ import { Box as Box21, Button as Button17, Flex as Flex16, Heading as Heading14, Input as Input8, Stack as Stack11, Text as Text24 } from "@chakra-ui/react";
3687
+ import { useMutation as useMutation6 } from "@tanstack/react-query";
3688
+ import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
3224
3689
  function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint = "/assistant-runs" }) {
3225
3690
  const { http } = useOonApi();
3226
- const [messages, setMessages] = useState10([]);
3227
- const [input, setInput] = useState10("");
3228
- const ask = useMutation5({
3691
+ const [messages, setMessages] = useState14([]);
3692
+ const [input, setInput] = useState14("");
3693
+ const ask = useMutation6({
3229
3694
  mutationFn: async (message) => {
3230
3695
  const { data } = await http.post(
3231
3696
  endpoint,
@@ -3249,11 +3714,11 @@ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint =
3249
3714
  setInput("");
3250
3715
  ask.mutate(text);
3251
3716
  };
3252
- return /* @__PURE__ */ jsxs19(Stack10, { gap: 4, maxW: "560px", children: [
3253
- /* @__PURE__ */ jsx33(Heading13, { size: "md", children: label }),
3254
- /* @__PURE__ */ jsx33(Box17, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 4, minH: "240px", children: /* @__PURE__ */ jsxs19(Stack10, { gap: 3, children: [
3255
- messages.length === 0 ? /* @__PURE__ */ jsx33(Text19, { color: "gray.400", fontSize: "sm", children: "Fa\xE7a uma pergunta ao assistente." }) : messages.map((m, idx) => /* @__PURE__ */ jsx33(Flex13, { justify: m.role === "user" ? "flex-end" : "flex-start", children: /* @__PURE__ */ jsx33(
3256
- Box17,
3717
+ return /* @__PURE__ */ jsxs25(Stack11, { gap: 4, maxW: "560px", children: [
3718
+ /* @__PURE__ */ jsx39(Heading14, { size: "md", children: label }),
3719
+ /* @__PURE__ */ jsx39(Box21, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 4, minH: "240px", children: /* @__PURE__ */ jsxs25(Stack11, { gap: 3, children: [
3720
+ messages.length === 0 ? /* @__PURE__ */ jsx39(Text24, { color: "gray.400", fontSize: "sm", children: "Fa\xE7a uma pergunta ao assistente." }) : messages.map((m, idx) => /* @__PURE__ */ jsx39(Flex16, { justify: m.role === "user" ? "flex-end" : "flex-start", children: /* @__PURE__ */ jsx39(
3721
+ Box21,
3257
3722
  {
3258
3723
  bg: m.role === "user" ? "brand.500" : "gray.100",
3259
3724
  color: m.role === "user" ? "white" : "gray.800",
@@ -3265,12 +3730,12 @@ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint =
3265
3730
  children: m.content
3266
3731
  }
3267
3732
  ) }, idx)),
3268
- ask.isPending ? /* @__PURE__ */ jsx33(Text19, { color: "gray.400", fontSize: "sm", children: "Pensando\u2026" }) : null,
3269
- ask.isError ? /* @__PURE__ */ jsx33(Text19, { color: "red.600", fontSize: "sm", children: ask.error?.message }) : null
3733
+ ask.isPending ? /* @__PURE__ */ jsx39(Text24, { color: "gray.400", fontSize: "sm", children: "Pensando\u2026" }) : null,
3734
+ ask.isError ? /* @__PURE__ */ jsx39(Text24, { color: "red.600", fontSize: "sm", children: ask.error?.message }) : null
3270
3735
  ] }) }),
3271
- /* @__PURE__ */ jsxs19(Flex13, { gap: 2, children: [
3272
- /* @__PURE__ */ jsx33(
3273
- Input6,
3736
+ /* @__PURE__ */ jsxs25(Flex16, { gap: 2, children: [
3737
+ /* @__PURE__ */ jsx39(
3738
+ Input8,
3274
3739
  {
3275
3740
  size: "sm",
3276
3741
  value: input,
@@ -3281,7 +3746,7 @@ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint =
3281
3746
  }
3282
3747
  }
3283
3748
  ),
3284
- /* @__PURE__ */ jsx33(Button13, { size: "sm", colorPalette: "blue", onClick: send, loading: ask.isPending, children: "Enviar" })
3749
+ /* @__PURE__ */ jsx39(Button17, { size: "sm", colorPalette: "blue", onClick: send, loading: ask.isPending, children: "Enviar" })
3285
3750
  ] })
3286
3751
  ] });
3287
3752
  }