@oondemand/oon-core-front 0.3.33 → 0.3.34

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
@@ -88,11 +88,11 @@ function createRestClient(deps) {
88
88
  instance.interceptors.response.use(
89
89
  (res) => res,
90
90
  (error) => {
91
- const normalized = normalizeError(error);
91
+ const normalized2 = normalizeError(error);
92
92
  const requestPath = String(error.config?.url || "").split("?")[0].replace(/\/$/, "");
93
93
  const isLogin = requestPath.endsWith("/auth/autenticar");
94
- if (normalized.status === 401 && !isLogin) onUnauthorized?.();
95
- return Promise.reject(normalized);
94
+ if (normalized2.status === 401 && !isLogin) onUnauthorized?.();
95
+ return Promise.reject(normalized2);
96
96
  }
97
97
  );
98
98
  return instance;
@@ -778,8 +778,8 @@ function PlusIcon() {
778
778
  function renderCell(value, kind) {
779
779
  const formatted = formatCell(value, kind);
780
780
  if (kind === "enum") {
781
- const normalized = String(value ?? "").toLowerCase();
782
- const palette = /erro|cancel|inativo|recus|critica/.test(normalized) ? "red" : /pendente|aguardando|rascunho/.test(normalized) ? "orange" : /processando|conferencia|integrando|validando/.test(normalized) ? "blue" : /ativo|sucesso|conclu|aplicada|disponivel|aprov/.test(normalized) ? "green" : "gray";
781
+ const normalized2 = String(value ?? "").toLowerCase();
782
+ const palette = /erro|cancel|inativo|recus|critica/.test(normalized2) ? "red" : /pendente|aguardando|rascunho/.test(normalized2) ? "orange" : /processando|conferencia|integrando|validando/.test(normalized2) ? "blue" : /ativo|sucesso|conclu|aplicada|disponivel|aprov/.test(normalized2) ? "green" : "gray";
783
783
  return /* @__PURE__ */ jsx7(Badge, { colorPalette: palette, variant: "subtle", borderRadius: "full", px: "7px", py: "3px", fontSize: "9px", fontWeight: "600", textTransform: "capitalize", children: formatted });
784
784
  }
785
785
  if (kind === "boolean") {
@@ -1424,9 +1424,9 @@ function parseCurrencyInitial(value) {
1424
1424
  return Number.isFinite(parsed) ? String(parsed) : "";
1425
1425
  }
1426
1426
  function formatCurrency(value) {
1427
- const normalized = parseCurrencyInitial(value);
1428
- if (!normalized) return "";
1429
- const numeric = Number(normalized);
1427
+ const normalized2 = parseCurrencyInitial(value);
1428
+ if (!normalized2) return "";
1429
+ const numeric = Number(normalized2);
1430
1430
  if (!Number.isFinite(numeric)) return "";
1431
1431
  return new Intl.NumberFormat("pt-BR", {
1432
1432
  style: "currency",
@@ -1833,7 +1833,7 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
1833
1833
 
1834
1834
  // src/components/internal/CoreDetailModal.tsx
1835
1835
  import { useEffect as useEffect6, useMemo as useMemo7, useState as useState9 } from "react";
1836
- import { Box as Box8, Button as Button8, Flex as Flex7, Heading as Heading3, Text as Text10 } from "@chakra-ui/react";
1836
+ import { Box as Box8, Flex as Flex7, Heading as Heading3, IconButton, Text as Text10 } from "@chakra-ui/react";
1837
1837
  import { useQuery as useQuery6, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1838
1838
 
1839
1839
  // src/components/internal/CoreTabbedDetail.tsx
@@ -1980,6 +1980,13 @@ function interpolateEndpoint(endpoint, row, parent) {
1980
1980
 
1981
1981
  // src/components/internal/CoreRowAction.tsx
1982
1982
  import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1983
+ var ACTION_TONES = {
1984
+ success: { bg: "#DCFCE7", color: "#166534", border: "#BBF7D0", hover: "#D1FAE5" },
1985
+ danger: { bg: "#FEE2E2", color: "#991B1B", border: "#FECACA", hover: "#FDE2E2" },
1986
+ warning: { bg: "#FEF3C7", color: "#92400E", border: "#FDE68A", hover: "#FDEDB3" },
1987
+ neutral: { bg: "#F1F5F9", color: "#334155", border: "#E2E8F0", hover: "#E8EEF5" },
1988
+ brand: { bg: "#E0F2FE", color: "#075985", border: "#BAE6FD", hover: "#D5EEFC" }
1989
+ };
1983
1990
  function messageOf2(error) {
1984
1991
  return error instanceof Error ? error.message : typeof error === "string" ? error : "N\xE3o foi poss\xEDvel executar a a\xE7\xE3o.";
1985
1992
  }
@@ -1990,6 +1997,25 @@ function unwrap2(value) {
1990
1997
  if (data && typeof data === "object") return data;
1991
1998
  return record;
1992
1999
  }
2000
+ function emitOperationalEvent(action, row, changes) {
2001
+ if (typeof window === "undefined" || typeof window.dispatchEvent !== "function") return;
2002
+ if (!action.operationalKind) return;
2003
+ const field = action.field;
2004
+ window.dispatchEvent(new CustomEvent("oon:pipeline-action", {
2005
+ detail: {
2006
+ actionId: action.id,
2007
+ label: action.label,
2008
+ group: action.group,
2009
+ operationalKind: action.operationalKind,
2010
+ recordId: row._id ?? row.id,
2011
+ field,
2012
+ previousValue: field ? row[field] : void 0,
2013
+ nextValue: field ? changes?.[field] ?? action.value : void 0,
2014
+ changes,
2015
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString()
2016
+ }
2017
+ }));
2018
+ }
1993
2019
  function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate }) {
1994
2020
  const { http } = useOonApi();
1995
2021
  const [loading, setLoading] = useState6(false);
@@ -1997,6 +2023,7 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
1997
2023
  const [formOpen, setFormOpen] = useState6(false);
1998
2024
  const [formInitialValues, setFormInitialValues] = useState6({});
1999
2025
  const pipelineAction = action;
2026
+ const tone = pipelineAction.tone ? ACTION_TONES[pipelineAction.tone] : void 0;
2000
2027
  if (evaluateCondition(action.hiddenWhen, row)) return null;
2001
2028
  const disabled = evaluateCondition(action.disabledWhen, row) || loading;
2002
2029
  const confirmAction = () => action.confirm ? window.confirm(action.confirm.description ?? action.confirm.title ?? `Executar ${action.label}?`) : true;
@@ -2030,7 +2057,9 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
2030
2057
  if (!pipelineAction.field || !onUpdate || !confirmAction()) return;
2031
2058
  setLoading(true);
2032
2059
  try {
2033
- await onUpdate({ [pipelineAction.field]: pipelineAction.value });
2060
+ const changes = { [pipelineAction.field]: pipelineAction.value };
2061
+ await onUpdate(changes);
2062
+ emitOperationalEvent(pipelineAction, row, changes);
2034
2063
  onRefresh?.(pipelineAction.refresh);
2035
2064
  } catch (err) {
2036
2065
  setError(err);
@@ -2044,6 +2073,7 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
2044
2073
  try {
2045
2074
  const url = interpolateEndpoint(action.endpoint, row, parent);
2046
2075
  await http.request({ url, method: action.method ?? "POST" });
2076
+ emitOperationalEvent(pipelineAction, row);
2047
2077
  onRefresh?.(action.refresh);
2048
2078
  } catch (err) {
2049
2079
  setError(err);
@@ -2051,8 +2081,30 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
2051
2081
  setLoading(false);
2052
2082
  }
2053
2083
  };
2054
- return /* @__PURE__ */ jsxs8("span", { children: [
2055
- /* @__PURE__ */ jsx12(Button5, { type: "button", size: "xs", minH: "28px", px: "9px", borderRadius: "6px", fontSize: "10px", loading, disabled, onClick: run, children: action.label }),
2084
+ return /* @__PURE__ */ jsxs8("span", { style: { display: "inline-flex", flexDirection: "column" }, children: [
2085
+ /* @__PURE__ */ jsx12(
2086
+ Button5,
2087
+ {
2088
+ type: "button",
2089
+ size: "xs",
2090
+ minH: "28px",
2091
+ px: "9px",
2092
+ borderRadius: "6px",
2093
+ fontSize: "10px",
2094
+ fontWeight: "700",
2095
+ variant: tone ? "outline" : void 0,
2096
+ bg: tone?.bg,
2097
+ color: tone?.color,
2098
+ borderColor: tone?.border,
2099
+ boxShadow: tone ? "none" : void 0,
2100
+ loading,
2101
+ disabled,
2102
+ onClick: run,
2103
+ _hover: tone ? { bg: tone.hover, borderColor: tone.border } : void 0,
2104
+ _disabled: tone ? { opacity: 0.55, cursor: "not-allowed" } : void 0,
2105
+ children: action.label
2106
+ }
2107
+ ),
2056
2108
  error ? /* @__PURE__ */ jsx12(Text7, { mt: "3px", color: "#B42318", fontSize: "9px", children: messageOf2(error) }) : null,
2057
2109
  formOpen && pipelineAction.type === "formAction" ? /* @__PURE__ */ jsx12(
2058
2110
  DynamicForm,
@@ -2070,6 +2122,7 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
2070
2122
  try {
2071
2123
  const url = interpolateEndpoint(pipelineAction.endpoint, row, parent);
2072
2124
  await http.request({ url, method: pipelineAction.method ?? "POST", data: values });
2125
+ emitOperationalEvent(pipelineAction, row, values);
2073
2126
  setFormOpen(false);
2074
2127
  onRefresh?.(pipelineAction.refresh);
2075
2128
  } catch (err) {
@@ -2696,14 +2749,32 @@ function CoreDetailModal({
2696
2749
  const width = config.size === "full" ? "98vw" : config.size === "md" ? "760px" : config.size === "lg" ? "980px" : "1180px";
2697
2750
  const displayTitle = parent?.[config.titleField ?? ""] ? String(parent[config.titleField ?? ""]) : title;
2698
2751
  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: [
2699
- /* @__PURE__ */ jsxs11(Flex7, { minH: "72px", px: "20px", align: "center", justify: "space-between", gap: 4, borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
2700
- /* @__PURE__ */ jsxs11(Box8, { children: [
2752
+ /* @__PURE__ */ jsxs11(Flex7, { minH: "72px", px: "20px", py: "10px", align: "center", justify: "space-between", gap: 4, borderBottomWidth: "1px", borderColor: "#E5E9ED", children: [
2753
+ /* @__PURE__ */ jsxs11(Box8, { minW: "160px", children: [
2701
2754
  /* @__PURE__ */ jsx15(Text10, { color: "#0474AF", fontSize: "10px", fontWeight: "700", textTransform: "uppercase", children: "Detalhe" }),
2702
2755
  /* @__PURE__ */ jsx15(Heading3, { size: "md", children: recordId ? displayTitle : `Novo ${title}` })
2703
2756
  ] }),
2704
- /* @__PURE__ */ jsxs11(Flex7, { align: "center", justify: "flex-end", gap: "6px", wrap: "wrap", children: [
2757
+ /* @__PURE__ */ jsxs11(Flex7, { flex: "1", align: "center", justify: "flex-end", gap: "8px", wrap: "wrap", children: [
2705
2758
  recordId ? actions : null,
2706
- /* @__PURE__ */ jsx15(Button8, { onClick: onClose, children: "Fechar" })
2759
+ /* @__PURE__ */ jsx15(
2760
+ IconButton,
2761
+ {
2762
+ "aria-label": "Fechar",
2763
+ title: "Fechar",
2764
+ size: "sm",
2765
+ minW: "32px",
2766
+ h: "32px",
2767
+ borderRadius: "full",
2768
+ variant: "ghost",
2769
+ color: "#475569",
2770
+ fontSize: "21px",
2771
+ fontWeight: "400",
2772
+ lineHeight: "1",
2773
+ onClick: onClose,
2774
+ _hover: { bg: "#F1F5F9", color: "#0F172A" },
2775
+ children: "\xD7"
2776
+ }
2777
+ )
2707
2778
  ] })
2708
2779
  ] }),
2709
2780
  /* @__PURE__ */ jsx15(Box8, { maxH: "calc(94vh - 73px)", p: "20px", overflowY: "auto", children: schemaQuery.isLoading || parentQuery.isLoading ? /* @__PURE__ */ jsx15(Text10, { children: "Carregando..." }) : /* @__PURE__ */ jsx15(
@@ -2870,8 +2941,135 @@ function CoreDocument({ model, label, endpoint, columns, form }) {
2870
2941
 
2871
2942
  // src/components/CorePipeline.tsx
2872
2943
  import { useState as useState11 } from "react";
2873
- import { Badge as Badge4, Box as Box10, Button as Button9, Flex as Flex8, Heading as Heading5, Input as Input6, NativeSelect as NativeSelect5, Stack as Stack5, Text as Text12 } from "@chakra-ui/react";
2944
+ import { Badge as Badge4, Box as Box10, Button as Button8, Flex as Flex8, Heading as Heading5, Input as Input6, NativeSelect as NativeSelect5, Stack as Stack5, Text as Text12 } from "@chakra-ui/react";
2874
2945
  import { useMutation as useMutation3, useQuery as useQuery7, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
2946
+
2947
+ // src/pipelineTicket.ts
2948
+ var DEFAULT_EXCLUDED_STAGES = [
2949
+ "cancelado",
2950
+ "cancelada",
2951
+ "cancelled",
2952
+ "rejeitado",
2953
+ "rejeitada",
2954
+ "rejected"
2955
+ ];
2956
+ function normalized(value) {
2957
+ return String(value ?? "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").trim().toLowerCase();
2958
+ }
2959
+ function slug(value) {
2960
+ return normalized(value).replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2961
+ }
2962
+ function approvalTone(action) {
2963
+ const key = normalized(`${action.id ?? ""} ${action.label}`);
2964
+ if (/recusar|reprovar|reject/.test(key)) return "danger";
2965
+ if (/aprovar|approve/.test(key)) return "success";
2966
+ return void 0;
2967
+ }
2968
+ function workStatusPresentation(value) {
2969
+ const key = normalized(value);
2970
+ if (/aguardando.*inicio|nao.*iniciado|waiting/.test(key)) {
2971
+ return { order: 0, label: "Aguardando in\xEDcio", tone: "warning" };
2972
+ }
2973
+ if (/trabalhando|em.*andamento|working/.test(key)) {
2974
+ return { order: 1, label: "Trabalhando", tone: "success" };
2975
+ }
2976
+ if (/revisar|revisao|review/.test(key)) {
2977
+ return { order: 2, label: "Revis\xE3o", tone: "danger" };
2978
+ }
2979
+ return void 0;
2980
+ }
2981
+ function decoratePipelineAction(action, stageField, workStatusField) {
2982
+ const approval = action.type === "transition" && action.field === stageField && approvalTone(action);
2983
+ const workStatus = action.type === "setField" && action.field === workStatusField;
2984
+ const group = action.group ?? (approval ? "approval" : workStatus ? "workStatus" : "custom");
2985
+ const tone = action.tone ?? (approval || (workStatus ? workStatusPresentation(action.value)?.tone : void 0)) ?? (group === "custom" ? "neutral" : void 0);
2986
+ const operationalKind = action.operationalKind ?? (group === "approval" ? "approval" : group === "workStatus" ? "work-status" : "business");
2987
+ return { ...action, group, tone, operationalKind };
2988
+ }
2989
+ function resolvePipelineActions({
2990
+ stageField,
2991
+ stages,
2992
+ workStatusValues = [],
2993
+ ticketActions = [],
2994
+ defaultActions
2995
+ }) {
2996
+ const config = defaultActions === false ? void 0 : defaultActions ?? {};
2997
+ const workStatusField = config?.workStatusField ?? "statusTrabalho";
2998
+ const explicit = ticketActions.map((action) => decoratePipelineAction(action, stageField, workStatusField));
2999
+ if (defaultActions === false) return explicit;
3000
+ const resolved = [];
3001
+ const hasExplicitApproval = explicit.some((action) => action.group === "approval");
3002
+ const hasExplicitWorkStatus = explicit.some((action) => action.group === "workStatus");
3003
+ if (config?.approval !== false && !hasExplicitApproval) {
3004
+ const excluded = /* @__PURE__ */ new Set([
3005
+ ...DEFAULT_EXCLUDED_STAGES,
3006
+ ...(config?.excludedStages ?? []).map(normalized)
3007
+ ]);
3008
+ const approvalStages = stages.filter((stage) => !excluded.has(normalized(stage.id)));
3009
+ approvalStages.forEach((stage, index) => {
3010
+ const next = approvalStages[index + 1];
3011
+ if (next) {
3012
+ resolved.push({
3013
+ id: `core-aprovar-${slug(stage.id)}`,
3014
+ label: "Aprovar",
3015
+ type: "transition",
3016
+ field: stageField,
3017
+ value: next.id,
3018
+ hiddenWhen: { field: stageField, notEquals: stage.id },
3019
+ confirm: { description: `Aprovar este ticket e alterar a etapa para ${next.label}?` },
3020
+ refresh: ["all"],
3021
+ group: "approval",
3022
+ tone: "success",
3023
+ operationalKind: "approval"
3024
+ });
3025
+ }
3026
+ });
3027
+ approvalStages.forEach((stage, index) => {
3028
+ const previous = approvalStages[index - 1];
3029
+ if (previous) {
3030
+ resolved.push({
3031
+ id: `core-recusar-${slug(stage.id)}`,
3032
+ label: "Recusar",
3033
+ type: "transition",
3034
+ field: stageField,
3035
+ value: previous.id,
3036
+ hiddenWhen: { field: stageField, notEquals: stage.id },
3037
+ confirm: { description: `Recusar este ticket e retornar a etapa para ${previous.label}?` },
3038
+ refresh: ["all"],
3039
+ group: "approval",
3040
+ tone: "danger",
3041
+ operationalKind: "approval"
3042
+ });
3043
+ }
3044
+ });
3045
+ }
3046
+ if (config?.workStatus !== false && !hasExplicitWorkStatus && workStatusValues.length) {
3047
+ workStatusValues.map((value) => ({ value, presentation: workStatusPresentation(value) })).filter((item) => Boolean(item.presentation)).sort((a, b) => a.presentation.order - b.presentation.order).forEach(({ value, presentation }) => {
3048
+ resolved.push({
3049
+ id: `core-status-trabalho-${slug(value)}`,
3050
+ label: presentation.label,
3051
+ type: "setField",
3052
+ field: workStatusField,
3053
+ value,
3054
+ disabledWhen: { field: workStatusField, equals: value },
3055
+ refresh: ["all"],
3056
+ group: "workStatus",
3057
+ tone: presentation.tone,
3058
+ operationalKind: "work-status"
3059
+ });
3060
+ });
3061
+ }
3062
+ return [...resolved, ...explicit];
3063
+ }
3064
+ function groupPipelineActions(actions) {
3065
+ return {
3066
+ approval: actions.filter((action) => action.group === "approval"),
3067
+ workStatus: actions.filter((action) => action.group === "workStatus"),
3068
+ custom: actions.filter((action) => action.group === "custom")
3069
+ };
3070
+ }
3071
+
3072
+ // src/components/CorePipeline.tsx
2875
3073
  import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2876
3074
  function ticketId(row) {
2877
3075
  const id = row._id ?? row.id;
@@ -2945,6 +3143,7 @@ function CorePipeline({
2945
3143
  viewModes = ["board"],
2946
3144
  defaultView,
2947
3145
  list,
3146
+ defaultActions,
2948
3147
  ticketActions = []
2949
3148
  }) {
2950
3149
  const schemaQuery = useModelSchema(model);
@@ -2993,6 +3192,17 @@ function CorePipeline({
2993
3192
  if (viewMode === "board" && listQuery.isError) return /* @__PURE__ */ jsx18(ErrorState, { error: listQuery.error });
2994
3193
  const stageFieldMeta = schema?.fields.find((field) => field.name === stageField);
2995
3194
  const resolvedStages = stages ?? (stageFieldMeta?.options ?? []).map((option) => ({ id: option, label: option }));
3195
+ const defaultActionsConfig = defaultActions === false ? void 0 : defaultActions;
3196
+ const workStatusField = defaultActionsConfig?.workStatusField ?? "statusTrabalho";
3197
+ const workStatusMeta = schema?.fields.find((field) => field.name === workStatusField);
3198
+ const resolvedTicketActions = resolvePipelineActions({
3199
+ stageField,
3200
+ stages: resolvedStages,
3201
+ workStatusValues: workStatusMeta?.options ?? [],
3202
+ ticketActions,
3203
+ defaultActions
3204
+ });
3205
+ const groupedTicketActions = groupPipelineActions(resolvedTicketActions);
2996
3206
  const resolvedTitleField = titleField ?? ticketModal?.titleField ?? schema?.fields.find((field) => field.kind === "string")?.name ?? schema?.searchable[0] ?? "_id";
2997
3207
  const detailFields = (schema?.fields ?? []).filter((field) => field.name !== stageField && field.name !== resolvedTitleField && field.kind !== "raw").slice(0, 3);
2998
3208
  const formFields = mergeFormFields2(formFieldsFromMeta(schema?.fields ?? []), form);
@@ -3014,7 +3224,7 @@ function CorePipeline({
3014
3224
  ...defaultStage ? { [stageField]: defaultStage } : {}
3015
3225
  });
3016
3226
  };
3017
- const modalActions = selectedTicket && !creating ? /* @__PURE__ */ jsx18(Flex8, { gap: "5px", align: "center", wrap: "wrap", children: ticketActions.map((action, index) => /* @__PURE__ */ jsx18(
3227
+ const renderModalAction = (action, index) => selectedTicket ? /* @__PURE__ */ jsx18(
3018
3228
  CoreRowAction,
3019
3229
  {
3020
3230
  action,
@@ -3032,7 +3242,40 @@ function CorePipeline({
3032
3242
  }
3033
3243
  },
3034
3244
  action.id ?? `${action.label}-${index}`
3035
- )) }) : null;
3245
+ ) : null;
3246
+ const modalActions = selectedTicket && !creating ? /* @__PURE__ */ jsxs13(Flex8, { gap: "8px", align: "center", justify: "flex-end", wrap: "wrap", children: [
3247
+ groupedTicketActions.approval.length ? /* @__PURE__ */ jsx18(
3248
+ Flex8,
3249
+ {
3250
+ role: "group",
3251
+ "aria-label": "Aprova\xE7\xE3o do ticket",
3252
+ gap: "4px",
3253
+ align: "center",
3254
+ p: "3px",
3255
+ bg: "#F8FAFC",
3256
+ borderWidth: "1px",
3257
+ borderColor: "#E2E8F0",
3258
+ borderRadius: "9px",
3259
+ children: groupedTicketActions.approval.map(renderModalAction)
3260
+ }
3261
+ ) : null,
3262
+ groupedTicketActions.workStatus.length ? /* @__PURE__ */ jsx18(
3263
+ Flex8,
3264
+ {
3265
+ role: "group",
3266
+ "aria-label": "Status de trabalho",
3267
+ gap: "4px",
3268
+ align: "center",
3269
+ p: "3px",
3270
+ bg: "#F8FAFC",
3271
+ borderWidth: "1px",
3272
+ borderColor: "#E2E8F0",
3273
+ borderRadius: "9px",
3274
+ children: groupedTicketActions.workStatus.map(renderModalAction)
3275
+ }
3276
+ ) : null,
3277
+ groupedTicketActions.custom.length ? /* @__PURE__ */ jsx18(Flex8, { role: "group", "aria-label": "Outras a\xE7\xF5es", gap: "4px", align: "center", wrap: "wrap", children: groupedTicketActions.custom.map(renderModalAction) }) : null
3278
+ ] }) : null;
3036
3279
  return /* @__PURE__ */ jsxs13(Stack5, { gap: 5, children: [
3037
3280
  /* @__PURE__ */ jsxs13(Flex8, { align: { base: "stretch", md: "flex-end" }, justify: "space-between", gap: 4, direction: { base: "column", md: "row" }, children: [
3038
3281
  /* @__PURE__ */ jsxs13(Box10, { children: [
@@ -3041,8 +3284,8 @@ function CorePipeline({
3041
3284
  /* @__PURE__ */ jsx18(Text12, { mt: 1, fontSize: "13px", color: "gray.500", children: "Acompanhe os tickets por etapa e visualize os principais dados de cada item." })
3042
3285
  ] }),
3043
3286
  /* @__PURE__ */ jsxs13(Flex8, { gap: "8px", align: "center", wrap: "wrap", children: [
3044
- allowedViewModes.length > 1 ? allowedViewModes.map((mode) => /* @__PURE__ */ jsx18(Button9, { size: "sm", variant: viewMode === mode ? "solid" : "outline", colorPalette: "brand", onClick: () => setViewMode(mode), children: mode === "board" ? "Quadro" : "Lista" }, mode)) : null,
3045
- create?.enabled ? /* @__PURE__ */ jsx18(Button9, { size: "sm", colorPalette: "brand", onClick: openCreate, children: create.label ?? "Novo ticket" }) : null
3287
+ allowedViewModes.length > 1 ? allowedViewModes.map((mode) => /* @__PURE__ */ jsx18(Button8, { size: "sm", variant: viewMode === mode ? "solid" : "outline", colorPalette: "brand", onClick: () => setViewMode(mode), children: mode === "board" ? "Quadro" : "Lista" }, mode)) : null,
3288
+ create?.enabled ? /* @__PURE__ */ jsx18(Button8, { size: "sm", colorPalette: "brand", onClick: openCreate, children: create.label ?? "Novo ticket" }) : null
3046
3289
  ] })
3047
3290
  ] }),
3048
3291
  filters.length ? /* @__PURE__ */ jsxs13(Flex8, { p: "12px", gap: "10px", align: "flex-end", wrap: "wrap", bg: "white", borderWidth: "1px", borderColor: "#E5E9ED", borderRadius: "10px", children: [
@@ -3062,7 +3305,7 @@ function CorePipeline({
3062
3305
  ] }, filter.field);
3063
3306
  }),
3064
3307
  /* @__PURE__ */ jsx18(
3065
- Button9,
3308
+ Button8,
3066
3309
  {
3067
3310
  size: "sm",
3068
3311
  variant: "outline",
@@ -3094,7 +3337,7 @@ function CorePipeline({
3094
3337
  /* @__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) => {
3095
3338
  const ticketTitle = formatCell(row[resolvedTitleField], "string");
3096
3339
  return /* @__PURE__ */ jsxs13(
3097
- Button9,
3340
+ Button8,
3098
3341
  {
3099
3342
  type: "button",
3100
3343
  variant: "plain",
@@ -3254,10 +3497,10 @@ function registryKey(key) {
3254
3497
  }
3255
3498
  function resolveComponent(registry, key, bucket) {
3256
3499
  if (!key) return null;
3257
- const normalized = registryKey(key);
3500
+ const normalized2 = registryKey(key);
3258
3501
  const inferred = key.includes(".") ? PREFIX_BUCKETS[key.split(".")[0]] : void 0;
3259
3502
  const targetBucket = bucket ?? inferred ?? "pageComponents";
3260
- return registry?.[targetBucket]?.[normalized] ?? registry?.[targetBucket]?.[key] ?? null;
3503
+ return registry?.[targetBucket]?.[normalized2] ?? registry?.[targetBucket]?.[key] ?? null;
3261
3504
  }
3262
3505
  function MissingRenderer({ renderer, children }) {
3263
3506
  if (import.meta.env?.MODE === "production") return /* @__PURE__ */ jsx21(Fragment4, { children: children ?? null });
@@ -3273,7 +3516,7 @@ function MissingRenderer({ renderer, children }) {
3273
3516
  }
3274
3517
 
3275
3518
  // src/components/ui-v2/CorePrimitives.tsx
3276
- import { Box as Box13, Button as Button10, Flex as Flex9, Heading as Heading7, Spinner as Spinner3, Text as Text15 } from "@chakra-ui/react";
3519
+ import { Box as Box13, Button as Button9, Flex as Flex9, Heading as Heading7, Spinner as Spinner3, Text as Text15 } from "@chakra-ui/react";
3277
3520
  import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
3278
3521
  function CorePage({ children }) {
3279
3522
  return /* @__PURE__ */ jsx22(Box13, { children });
@@ -3314,7 +3557,7 @@ function CoreActions({ children }) {
3314
3557
  function CoreEmptyState({ title = "Nenhum dado encontrado", actionLabel, onAction }) {
3315
3558
  return /* @__PURE__ */ jsxs16(Box13, { textAlign: "center", py: 10, children: [
3316
3559
  /* @__PURE__ */ jsx22(Text15, { children: title }),
3317
- actionLabel ? /* @__PURE__ */ jsx22(Button10, { mt: 3, onClick: onAction, children: actionLabel }) : null
3560
+ actionLabel ? /* @__PURE__ */ jsx22(Button9, { mt: 3, onClick: onAction, children: actionLabel }) : null
3318
3561
  ] });
3319
3562
  }
3320
3563
  function CoreLoadingState({ label = "Carregando..." }) {
@@ -3371,7 +3614,7 @@ function CorePage2({ page, registry }) {
3371
3614
 
3372
3615
  // src/app/moduleRegistry.tsx
3373
3616
  import { jsx as jsx24 } from "react/jsx-runtime";
3374
- function slug(value) {
3617
+ function slug2(value) {
3375
3618
  return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
3376
3619
  }
3377
3620
  function requiredAccess2(source) {
@@ -3381,7 +3624,7 @@ function requiredAccess2(source) {
3381
3624
  function viewId(view) {
3382
3625
  if (view.id) return view.id;
3383
3626
  if (view.type === "dashboard") return "dashboard";
3384
- return slug(view.model);
3627
+ return slug2(view.model);
3385
3628
  }
3386
3629
  function viewPath(view) {
3387
3630
  if (view.path) return view.path;
@@ -3436,6 +3679,7 @@ function renderView(view, registry) {
3436
3679
  viewModes: v.viewModes,
3437
3680
  defaultView: v.defaultView,
3438
3681
  list: v.list,
3682
+ defaultActions: v.defaultActions,
3439
3683
  ticketActions: v.ticketActions
3440
3684
  }
3441
3685
  );
@@ -3518,7 +3762,7 @@ import {
3518
3762
  } from "react-router-dom";
3519
3763
 
3520
3764
  // src/shell/DefaultShell.tsx
3521
- import { Box as Box16, Button as Button11, Flex as Flex11, Spacer as Spacer2, Text as Text18 } from "@chakra-ui/react";
3765
+ import { Box as Box16, Button as Button10, Flex as Flex11, Spacer as Spacer2, Text as Text18 } from "@chakra-ui/react";
3522
3766
  import { Outlet } from "react-router-dom";
3523
3767
 
3524
3768
  // src/shell/Sidebar.tsx
@@ -3638,7 +3882,7 @@ function CoreTopbar({ app }) {
3638
3882
  /* @__PURE__ */ jsx26(Text18, { fontSize: "sm", fontWeight: "600", color: "#24323A", children: user.nome }),
3639
3883
  user.email ? /* @__PURE__ */ jsx26(Text18, { fontSize: "xs", color: "gray.500", children: user.email }) : null
3640
3884
  ] }),
3641
- /* @__PURE__ */ jsx26(Button11, { size: "sm", variant: "outline", colorPalette: "brand", borderRadius: "8px", onClick: logout, children: "Sair" })
3885
+ /* @__PURE__ */ jsx26(Button10, { size: "sm", variant: "outline", colorPalette: "brand", borderRadius: "8px", onClick: logout, children: "Sair" })
3642
3886
  ] }) : null
3643
3887
  ] });
3644
3888
  }
@@ -3682,7 +3926,7 @@ function AuthenticatedLayout({ app, menu, layout, registry }) {
3682
3926
  }
3683
3927
 
3684
3928
  // src/security/AccessDeniedPage.tsx
3685
- import { Box as Box17, Button as Button12, Flex as Flex12, Heading as Heading9, Text as Text19, VStack } from "@chakra-ui/react";
3929
+ import { Box as Box17, Button as Button11, Flex as Flex12, Heading as Heading9, Text as Text19, VStack } from "@chakra-ui/react";
3686
3930
  import { useNavigate } from "react-router-dom";
3687
3931
  import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
3688
3932
  function AccessDeniedPage({ app }) {
@@ -3741,7 +3985,7 @@ function AccessDeniedPage({ app }) {
3741
3985
  ] })
3742
3986
  ] }),
3743
3987
  /* @__PURE__ */ jsx28(
3744
- Button12,
3988
+ Button11,
3745
3989
  {
3746
3990
  alignSelf: "flex-start",
3747
3991
  bg: "#07262E",
@@ -3798,7 +4042,7 @@ function AppAccessGuard({ children }) {
3798
4042
  import { useState as useState12 } from "react";
3799
4043
  import {
3800
4044
  Box as Box18,
3801
- Button as Button13,
4045
+ Button as Button12,
3802
4046
  Flex as Flex13,
3803
4047
  Heading as Heading10,
3804
4048
  Input as Input7,
@@ -3916,7 +4160,7 @@ function LoginPage({ app }) {
3916
4160
  }
3917
4161
  ) : null,
3918
4162
  /* @__PURE__ */ jsx30(
3919
- Button13,
4163
+ Button12,
3920
4164
  {
3921
4165
  type: "submit",
3922
4166
  bg: "#07262E",
@@ -3933,7 +4177,7 @@ function LoginPage({ app }) {
3933
4177
 
3934
4178
  // src/security/ActivationPage.tsx
3935
4179
  import { useEffect as useEffect7, useState as useState13 } from "react";
3936
- import { Box as Box19, Button as Button14, Heading as Heading11, Input as Input8, Text as Text21, VStack as VStack3 } from "@chakra-ui/react";
4180
+ import { Box as Box19, Button as Button13, Heading as Heading11, Input as Input8, Text as Text21, VStack as VStack3 } from "@chakra-ui/react";
3937
4181
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
3938
4182
  function encodeBasicCredentials2(email, password) {
3939
4183
  const bytes = new TextEncoder().encode(`${email}:${password}`);
@@ -4131,7 +4375,7 @@ function ActivationPage() {
4131
4375
  )
4132
4376
  ] }),
4133
4377
  /* @__PURE__ */ jsx31(
4134
- Button14,
4378
+ Button13,
4135
4379
  {
4136
4380
  colorPalette: "blue",
4137
4381
  onClick: activateDevLocal,
@@ -4141,7 +4385,7 @@ function ActivationPage() {
4141
4385
  }
4142
4386
  ),
4143
4387
  /* @__PURE__ */ jsx31(
4144
- Button14,
4388
+ Button13,
4145
4389
  {
4146
4390
  variant: "outline",
4147
4391
  onClick: () => setShowCodeFlow(true),
@@ -4222,7 +4466,7 @@ function ActivationPage() {
4222
4466
  )
4223
4467
  ] }),
4224
4468
  /* @__PURE__ */ jsx31(
4225
- Button14,
4469
+ Button13,
4226
4470
  {
4227
4471
  colorPalette: "blue",
4228
4472
  onClick: activateRoot,
@@ -4275,7 +4519,7 @@ function ActivationPage() {
4275
4519
  }
4276
4520
  ),
4277
4521
  /* @__PURE__ */ jsx31(
4278
- Button14,
4522
+ Button13,
4279
4523
  {
4280
4524
  onClick: validateCode,
4281
4525
  loading: submitting,
@@ -4284,7 +4528,7 @@ function ActivationPage() {
4284
4528
  }
4285
4529
  ),
4286
4530
  isDevelopmentMember ? /* @__PURE__ */ jsx31(
4287
- Button14,
4531
+ Button13,
4288
4532
  {
4289
4533
  variant: "outline",
4290
4534
  onClick: () => setShowCodeFlow(false),
@@ -4296,22 +4540,22 @@ function ActivationPage() {
4296
4540
  step === 2 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
4297
4541
  /* @__PURE__ */ jsx31(Heading11, { size: "md", children: "Confirma\xE7\xE3o" }),
4298
4542
  /* @__PURE__ */ jsx31("pre", { children: JSON.stringify(preview, null, 2) }),
4299
- /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(3), children: "Continuar" })
4543
+ /* @__PURE__ */ jsx31(Button13, { onClick: () => setStep(3), children: "Continuar" })
4300
4544
  ] }),
4301
4545
  step === 3 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
4302
4546
  config.globalFields.map(
4303
4547
  (field) => renderField(field, global, setGlobal)
4304
4548
  ),
4305
- /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(4), children: "Continuar" })
4549
+ /* @__PURE__ */ jsx31(Button13, { onClick: () => setStep(4), children: "Continuar" })
4306
4550
  ] }),
4307
4551
  step === 4 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
4308
4552
  config.appFields.length ? config.appFields.map((field) => renderField(field, app, setApp)) : /* @__PURE__ */ jsx31(Text21, { children: "Nenhum par\xE2metro adicional declarado." }),
4309
- /* @__PURE__ */ jsx31(Button14, { onClick: () => setStep(5), children: "Revisar" })
4553
+ /* @__PURE__ */ jsx31(Button13, { onClick: () => setStep(5), children: "Revisar" })
4310
4554
  ] }),
4311
4555
  step === 5 && /* @__PURE__ */ jsxs22(Fragment6, { children: [
4312
4556
  /* @__PURE__ */ jsx31(Text21, { children: "Ao confirmar, o c\xF3digo ser\xE1 consumido e a inst\xE2ncia ser\xE1 registrada no Ecossistema Oon." }),
4313
4557
  /* @__PURE__ */ jsx31(
4314
- Button14,
4558
+ Button13,
4315
4559
  {
4316
4560
  colorPalette: "blue",
4317
4561
  onClick: completeMemberActivation,
@@ -4574,6 +4818,7 @@ function manifestToConfig(manifest, runtime) {
4574
4818
  viewModes: p.viewModes,
4575
4819
  defaultView: p.defaultView,
4576
4820
  list: p.list,
4821
+ defaultActions: p.defaultActions,
4577
4822
  ticketActions: p.ticketActions
4578
4823
  };
4579
4824
  views.push(view);
@@ -4651,7 +4896,7 @@ function defineOonModule(mod) {
4651
4896
  }
4652
4897
 
4653
4898
  // src/components/CoreIntegration.tsx
4654
- 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";
4899
+ import { Badge as Badge5, Box as Box20, Button as Button14, Flex as Flex14, Heading as Heading12, Stack as Stack9, Text as Text22 } from "@chakra-ui/react";
4655
4900
  import { useMutation as useMutation4 } from "@tanstack/react-query";
4656
4901
  import { jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
4657
4902
  function CoreIntegration({ label = "Integra\xE7\xF5es" }) {
@@ -4666,7 +4911,7 @@ function CoreIntegration({ label = "Integra\xE7\xF5es" }) {
4666
4911
  return /* @__PURE__ */ jsxs23(Stack9, { gap: 6, children: [
4667
4912
  /* @__PURE__ */ jsxs23(Flex14, { align: "center", justify: "space-between", children: [
4668
4913
  /* @__PURE__ */ jsx37(Heading12, { size: "lg", children: label }),
4669
- /* @__PURE__ */ jsx37(Button15, { size: "sm", variant: "outline", loading: reprocess.isPending, onClick: () => reprocess.mutate(), children: "Reprocessar ativos" })
4914
+ /* @__PURE__ */ jsx37(Button14, { size: "sm", variant: "outline", loading: reprocess.isPending, onClick: () => reprocess.mutate(), children: "Reprocessar ativos" })
4670
4915
  ] }),
4671
4916
  /* @__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(
4672
4917
  Box20,
@@ -4687,7 +4932,7 @@ function CoreIntegration({ label = "Integra\xE7\xF5es" }) {
4687
4932
  }
4688
4933
 
4689
4934
  // src/components/CoreCurrency.tsx
4690
- import { Button as Button16, Flex as Flex15, Heading as Heading13, Stack as Stack10, Text as Text23 } from "@chakra-ui/react";
4935
+ import { Button as Button15, Flex as Flex15, Heading as Heading13, Stack as Stack10, Text as Text23 } from "@chakra-ui/react";
4691
4936
  import { useMutation as useMutation5, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
4692
4937
  import { jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
4693
4938
  function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/moedas", columns }) {
@@ -4700,7 +4945,7 @@ function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/mo
4700
4945
  return /* @__PURE__ */ jsxs24(Stack10, { gap: 6, children: [
4701
4946
  /* @__PURE__ */ jsxs24(Flex15, { align: "center", justify: "space-between", children: [
4702
4947
  /* @__PURE__ */ jsx38(Heading13, { size: "lg", children: label }),
4703
- /* @__PURE__ */ jsx38(Button16, { size: "sm", colorPalette: "blue", loading: updateRates.isPending, onClick: () => updateRates.mutate(), children: "Atualizar cota\xE7\xF5es" })
4948
+ /* @__PURE__ */ jsx38(Button15, { size: "sm", colorPalette: "blue", loading: updateRates.isPending, onClick: () => updateRates.mutate(), children: "Atualizar cota\xE7\xF5es" })
4704
4949
  ] }),
4705
4950
  updateRates.isError ? /* @__PURE__ */ jsx38(Text23, { fontSize: "sm", color: "red.600", children: updateRates.error?.message }) : null,
4706
4951
  /* @__PURE__ */ jsx38(CoreCollection, { model, label: "", mode: columns ? "full" : "dynamic", endpoint, columns })
@@ -4709,7 +4954,7 @@ function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/mo
4709
4954
 
4710
4955
  // src/components/CoreAssistant.tsx
4711
4956
  import { useState as useState14 } from "react";
4712
- import { Box as Box21, Button as Button17, Flex as Flex16, Heading as Heading14, Input as Input9, Stack as Stack11, Text as Text24 } from "@chakra-ui/react";
4957
+ import { Box as Box21, Button as Button16, Flex as Flex16, Heading as Heading14, Input as Input9, Stack as Stack11, Text as Text24 } from "@chakra-ui/react";
4713
4958
  import { useMutation as useMutation6 } from "@tanstack/react-query";
4714
4959
  import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
4715
4960
  function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint = "/assistant-runs" }) {
@@ -4772,7 +5017,7 @@ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint =
4772
5017
  }
4773
5018
  }
4774
5019
  ),
4775
- /* @__PURE__ */ jsx39(Button17, { size: "sm", colorPalette: "blue", onClick: send, loading: ask.isPending, children: "Enviar" })
5020
+ /* @__PURE__ */ jsx39(Button16, { size: "sm", colorPalette: "blue", onClick: send, loading: ask.isPending, children: "Enviar" })
4776
5021
  ] })
4777
5022
  ] });
4778
5023
  }