@oondemand/oon-core-front 0.5.6 → 0.6.1

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.
@@ -0,0 +1,71 @@
1
+ import {
2
+ LoadingScreen
3
+ } from "./chunk-ALZCHGGI.js";
4
+
5
+ // src/routing.tsx
6
+ import { lazy, Suspense } from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var OON_RESERVED_ROUTES = Object.freeze([
9
+ "/login",
10
+ "/accept-invite",
11
+ "/first-access",
12
+ "/ativacao",
13
+ "/instancia-suspensa",
14
+ "/instancia-revogada",
15
+ "/acesso-negado"
16
+ ]);
17
+ function normalizedPath(path) {
18
+ const value = String(path || "").trim();
19
+ if (!value.startsWith("/")) throw new Error(`Rota Oon inv\xE1lida "${path}": use caminho absoluto iniciado por /.`);
20
+ return value.length > 1 ? value.replace(/\/+$/, "") : value;
21
+ }
22
+ function defineOonRoutes(routes) {
23
+ const seen = /* @__PURE__ */ new Set();
24
+ for (const route of routes) {
25
+ const path = normalizedPath(route.path);
26
+ if (OON_RESERVED_ROUTES.includes(path)) throw new Error(`Rota reservada pelo OonCore: ${path}.`);
27
+ if (seen.has(path)) throw new Error(`Rota duplicada: ${path}.`);
28
+ seen.add(path);
29
+ const sources = [route.element !== void 0, Boolean(route.component), Boolean(route.lazy)].filter(Boolean).length;
30
+ if (sources !== 1) throw new Error(`Rota ${path} deve declarar exatamente um de: element, component ou lazy.`);
31
+ }
32
+ return routes;
33
+ }
34
+ function defineOonNavigation(items) {
35
+ const seen = /* @__PURE__ */ new Set();
36
+ const visit = (item) => {
37
+ if (!item.label?.trim()) throw new Error("Item de navega\xE7\xE3o sem label.");
38
+ if (!item.href && !item.action && !item.children?.length) {
39
+ throw new Error(`Item de navega\xE7\xE3o ${item.label} deve declarar href, action ou children.`);
40
+ }
41
+ if (item.href && !item.external && !item.href.startsWith("/")) {
42
+ throw new Error(`Item de navega\xE7\xE3o ${item.label} deve usar href absoluto iniciado por /.`);
43
+ }
44
+ const key = `${item.href ?? item.action ?? "group"}:${item.label}`;
45
+ if (seen.has(key)) throw new Error(`Item de navega\xE7\xE3o duplicado: ${item.label}.`);
46
+ seen.add(key);
47
+ for (const child of item.children ?? []) visit(child);
48
+ };
49
+ for (const item of items) visit(item);
50
+ return items;
51
+ }
52
+ function routeElement(route) {
53
+ let Component = route.component;
54
+ if (route.lazy) Component = lazy(route.lazy);
55
+ const content = Component ? /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingScreen, {}), children: /* @__PURE__ */ jsx(Component, {}) }) : route.element;
56
+ if (!route.layout) return content;
57
+ const Layout = route.layout;
58
+ return /* @__PURE__ */ jsx(Layout, { children: content });
59
+ }
60
+ function navigation(config) {
61
+ return { mode: config.mode ?? "manual", items: [...defineOonNavigation(config.items ?? [])] };
62
+ }
63
+
64
+ export {
65
+ OON_RESERVED_ROUTES,
66
+ defineOonRoutes,
67
+ defineOonNavigation,
68
+ routeElement,
69
+ navigation
70
+ };
71
+ //# sourceMappingURL=chunk-32GGDIWB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/routing.tsx"],"sourcesContent":["import { lazy, Suspense } from \"react\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport type { OonMenuItem, OonNavigationConfig, OonRoute } from \"./types\";\nimport { LoadingScreen } from \"./shell/LoadingScreen\";\n\nexport const OON_RESERVED_ROUTES = Object.freeze([\n \"/login\",\n \"/accept-invite\",\n \"/first-access\",\n \"/ativacao\",\n \"/instancia-suspensa\",\n \"/instancia-revogada\",\n \"/acesso-negado\",\n]);\n\nfunction normalizedPath(path: string): string {\n const value = String(path || \"\").trim();\n if (!value.startsWith(\"/\")) throw new Error(`Rota Oon inválida \"${path}\": use caminho absoluto iniciado por /.`);\n return value.length > 1 ? value.replace(/\\/+$/, \"\") : value;\n}\n\nexport function defineOonRoutes<const T extends readonly OonRoute[]>(routes: T): T {\n const seen = new Set<string>();\n for (const route of routes) {\n const path = normalizedPath(route.path);\n if (OON_RESERVED_ROUTES.includes(path)) throw new Error(`Rota reservada pelo OonCore: ${path}.`);\n if (seen.has(path)) throw new Error(`Rota duplicada: ${path}.`);\n seen.add(path);\n const sources = [route.element !== undefined, Boolean(route.component), Boolean(route.lazy)].filter(Boolean).length;\n if (sources !== 1) throw new Error(`Rota ${path} deve declarar exatamente um de: element, component ou lazy.`);\n }\n return routes;\n}\n\nexport function defineOonNavigation<const T extends readonly OonMenuItem[]>(items: T): T {\n const seen = new Set<string>();\n const visit = (item: OonMenuItem) => {\n if (!item.label?.trim()) throw new Error(\"Item de navegação sem label.\");\n if (!item.href && !item.action && !item.children?.length) {\n throw new Error(`Item de navegação ${item.label} deve declarar href, action ou children.`);\n }\n if (item.href && !item.external && !item.href.startsWith(\"/\")) {\n throw new Error(`Item de navegação ${item.label} deve usar href absoluto iniciado por /.`);\n }\n const key = `${item.href ?? item.action ?? \"group\"}:${item.label}`;\n if (seen.has(key)) throw new Error(`Item de navegação duplicado: ${item.label}.`);\n seen.add(key);\n for (const child of item.children ?? []) visit(child);\n };\n for (const item of items) visit(item);\n return items;\n}\n\nexport function routeElement(route: OonRoute): ReactNode {\n let Component: ComponentType | undefined = route.component;\n if (route.lazy) Component = lazy(route.lazy);\n const content = Component ? <Suspense fallback={<LoadingScreen />}><Component /></Suspense> : route.element;\n if (!route.layout) return content;\n const Layout = route.layout;\n return <Layout>{content}</Layout>;\n}\n\nexport function navigation(config: OonNavigationConfig): OonNavigationConfig {\n return { mode: config.mode ?? \"manual\", items: [...defineOonNavigation(config.items ?? [])] };\n}\n"],"mappings":";;;;;AAAA,SAAS,MAAM,gBAAgB;AAwDmB;AAnD3C,IAAM,sBAAsB,OAAO,OAAO;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,eAAe,MAAsB;AAC5C,QAAM,QAAQ,OAAO,QAAQ,EAAE,EAAE,KAAK;AACtC,MAAI,CAAC,MAAM,WAAW,GAAG,EAAG,OAAM,IAAI,MAAM,yBAAsB,IAAI,yCAAyC;AAC/G,SAAO,MAAM,SAAS,IAAI,MAAM,QAAQ,QAAQ,EAAE,IAAI;AACxD;AAEO,SAAS,gBAAqD,QAAc;AACjF,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,eAAe,MAAM,IAAI;AACtC,QAAI,oBAAoB,SAAS,IAAI,EAAG,OAAM,IAAI,MAAM,gCAAgC,IAAI,GAAG;AAC/F,QAAI,KAAK,IAAI,IAAI,EAAG,OAAM,IAAI,MAAM,mBAAmB,IAAI,GAAG;AAC9D,SAAK,IAAI,IAAI;AACb,UAAM,UAAU,CAAC,MAAM,YAAY,QAAW,QAAQ,MAAM,SAAS,GAAG,QAAQ,MAAM,IAAI,CAAC,EAAE,OAAO,OAAO,EAAE;AAC7G,QAAI,YAAY,EAAG,OAAM,IAAI,MAAM,QAAQ,IAAI,8DAA8D;AAAA,EAC/G;AACA,SAAO;AACT;AAEO,SAAS,oBAA4D,OAAa;AACvF,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAQ,CAAC,SAAsB;AACnC,QAAI,CAAC,KAAK,OAAO,KAAK,EAAG,OAAM,IAAI,MAAM,oCAA8B;AACvE,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU,QAAQ;AACxD,YAAM,IAAI,MAAM,2BAAqB,KAAK,KAAK,0CAA0C;AAAA,IAC3F;AACA,QAAI,KAAK,QAAQ,CAAC,KAAK,YAAY,CAAC,KAAK,KAAK,WAAW,GAAG,GAAG;AAC7D,YAAM,IAAI,MAAM,2BAAqB,KAAK,KAAK,0CAA0C;AAAA,IAC3F;AACA,UAAM,MAAM,GAAG,KAAK,QAAQ,KAAK,UAAU,OAAO,IAAI,KAAK,KAAK;AAChE,QAAI,KAAK,IAAI,GAAG,EAAG,OAAM,IAAI,MAAM,sCAAgC,KAAK,KAAK,GAAG;AAChF,SAAK,IAAI,GAAG;AACZ,eAAW,SAAS,KAAK,YAAY,CAAC,EAAG,OAAM,KAAK;AAAA,EACtD;AACA,aAAW,QAAQ,MAAO,OAAM,IAAI;AACpC,SAAO;AACT;AAEO,SAAS,aAAa,OAA4B;AACvD,MAAI,YAAuC,MAAM;AACjD,MAAI,MAAM,KAAM,aAAY,KAAK,MAAM,IAAI;AAC3C,QAAM,UAAU,YAAY,oBAAC,YAAS,UAAU,oBAAC,iBAAc,GAAI,8BAAC,aAAU,GAAE,IAAc,MAAM;AACpG,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,QAAM,SAAS,MAAM;AACrB,SAAO,oBAAC,UAAQ,mBAAQ;AAC1B;AAEO,SAAS,WAAW,QAAkD;AAC3E,SAAO,EAAE,MAAM,OAAO,QAAQ,UAAU,OAAO,CAAC,GAAG,oBAAoB,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE;AAC9F;","names":[]}
@@ -0,0 +1,19 @@
1
+ // src/shell/LoadingScreen.tsx
2
+ import { Button, Flex, Spinner, Text } from "@chakra-ui/react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ function LoadingScreen({
5
+ message,
6
+ actionLabel,
7
+ onAction
8
+ }) {
9
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", align: "center", justify: "center", minH: "60vh", gap: 4, children: [
10
+ /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
11
+ message ? /* @__PURE__ */ jsx(Text, { color: "gray.500", fontSize: "sm", textAlign: "center", children: message }) : null,
12
+ actionLabel && onAction ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: onAction, children: actionLabel }) : null
13
+ ] });
14
+ }
15
+
16
+ export {
17
+ LoadingScreen
18
+ };
19
+ //# sourceMappingURL=chunk-ALZCHGGI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shell/LoadingScreen.tsx"],"sourcesContent":["import { Button, Flex, Spinner, Text } from \"@chakra-ui/react\";\n\ninterface LoadingScreenProps {\n message?: string;\n actionLabel?: string;\n onAction?: () => void;\n}\n\n/** Tela de carregamento/estado neutro reutilizada por guards e Suspense. */\nexport function LoadingScreen({\n message,\n actionLabel,\n onAction,\n}: LoadingScreenProps) {\n return (\n <Flex direction=\"column\" align=\"center\" justify=\"center\" minH=\"60vh\" gap={4}>\n <Spinner size=\"lg\" />\n {message ? (\n <Text color=\"gray.500\" fontSize=\"sm\" textAlign=\"center\">\n {message}\n </Text>\n ) : null}\n {actionLabel && onAction ? (\n <Button size=\"sm\" variant=\"outline\" onClick={onAction}>\n {actionLabel}\n </Button>\n ) : null}\n </Flex>\n );\n}\n"],"mappings":";AAAA,SAAS,QAAQ,MAAM,SAAS,YAAY;AAexC,SACE,KADF;AANG,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,SACE,qBAAC,QAAK,WAAU,UAAS,OAAM,UAAS,SAAQ,UAAS,MAAK,QAAO,KAAK,GACxE;AAAA,wBAAC,WAAQ,MAAK,MAAK;AAAA,IAClB,UACC,oBAAC,QAAK,OAAM,YAAW,UAAS,MAAK,WAAU,UAC5C,mBACH,IACE;AAAA,IACH,eAAe,WACd,oBAAC,UAAO,MAAK,MAAK,SAAQ,WAAU,SAAS,UAC1C,uBACH,IACE;AAAA,KACN;AAEJ;","names":[]}
@@ -0,0 +1,103 @@
1
+ import {
2
+ CoreCollection
3
+ } from "./chunk-R7ZBLDC2.js";
4
+ import {
5
+ useOonApi
6
+ } from "./chunk-VJ7YNFF7.js";
7
+
8
+ // src/components/CoreCurrency.tsx
9
+ import { Button, Flex, Heading, Stack, Text } from "@chakra-ui/react";
10
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ function CoreCurrency({ model = "Moeda", label = "Multi-moedas", endpoint = "/moedas", columns }) {
13
+ const { http } = useOonApi();
14
+ const queryClient = useQueryClient();
15
+ const updateRates = useMutation({
16
+ mutationFn: () => http.post(`${endpoint}/actions/update-rates`, {}, { headers: { "x-oon-origin": "integration" } }),
17
+ onSuccess: () => queryClient.invalidateQueries({ queryKey: ["oon", "list", endpoint] })
18
+ });
19
+ return /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
20
+ /* @__PURE__ */ jsxs(Flex, { align: "center", justify: "space-between", children: [
21
+ /* @__PURE__ */ jsx(Heading, { size: "lg", children: label }),
22
+ /* @__PURE__ */ jsx(Button, { size: "sm", colorPalette: "blue", loading: updateRates.isPending, onClick: () => updateRates.mutate(), children: "Atualizar cota\xE7\xF5es" })
23
+ ] }),
24
+ updateRates.isError ? /* @__PURE__ */ jsx(Text, { fontSize: "sm", color: "red.600", children: updateRates.error?.message }) : null,
25
+ /* @__PURE__ */ jsx(CoreCollection, { model, label: "", mode: columns ? "full" : "dynamic", endpoint, columns })
26
+ ] });
27
+ }
28
+
29
+ // src/components/CoreAssistant.tsx
30
+ import { useState } from "react";
31
+ import { Box, Button as Button2, Flex as Flex2, Heading as Heading2, Input, Stack as Stack2, Text as Text2 } from "@chakra-ui/react";
32
+ import { useMutation as useMutation2 } from "@tanstack/react-query";
33
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
34
+ function CoreAssistant({ assistantCode, label = "Assistente", entity, endpoint = "/assistant-runs" }) {
35
+ const { http } = useOonApi();
36
+ const [messages, setMessages] = useState([]);
37
+ const [input, setInput] = useState("");
38
+ const ask = useMutation2({
39
+ mutationFn: async (message) => {
40
+ const { data } = await http.post(
41
+ endpoint,
42
+ {
43
+ assistantCode,
44
+ entity,
45
+ message,
46
+ // Contexto redigido: a Central pode enriquecer, mas o Core não envia PII por padrão.
47
+ context: { redactionPolicy: "default" }
48
+ },
49
+ { headers: { "x-oon-origin": "assistant" } }
50
+ );
51
+ return data.reply ?? data.message ?? "";
52
+ },
53
+ onSuccess: (reply) => setMessages((prev) => [...prev, { role: "assistant", content: reply }])
54
+ });
55
+ const send = () => {
56
+ const text = input.trim();
57
+ if (!text) return;
58
+ setMessages((prev) => [...prev, { role: "user", content: text }]);
59
+ setInput("");
60
+ ask.mutate(text);
61
+ };
62
+ return /* @__PURE__ */ jsxs2(Stack2, { gap: 4, maxW: "560px", children: [
63
+ /* @__PURE__ */ jsx2(Heading2, { size: "md", children: label }),
64
+ /* @__PURE__ */ jsx2(Box, { borderWidth: "1px", borderColor: "gray.200", borderRadius: "md", bg: "white", p: 4, minH: "240px", children: /* @__PURE__ */ jsxs2(Stack2, { gap: 3, children: [
65
+ messages.length === 0 ? /* @__PURE__ */ jsx2(Text2, { color: "gray.400", fontSize: "sm", children: "Fa\xE7a uma pergunta ao assistente." }) : messages.map((m, idx) => /* @__PURE__ */ jsx2(Flex2, { justify: m.role === "user" ? "flex-end" : "flex-start", children: /* @__PURE__ */ jsx2(
66
+ Box,
67
+ {
68
+ bg: m.role === "user" ? "brand.500" : "gray.100",
69
+ color: m.role === "user" ? "white" : "gray.800",
70
+ px: 3,
71
+ py: 2,
72
+ borderRadius: "md",
73
+ maxW: "80%",
74
+ fontSize: "sm",
75
+ children: m.content
76
+ }
77
+ ) }, idx)),
78
+ ask.isPending ? /* @__PURE__ */ jsx2(Text2, { color: "gray.400", fontSize: "sm", children: "Pensando\u2026" }) : null,
79
+ ask.isError ? /* @__PURE__ */ jsx2(Text2, { color: "red.600", fontSize: "sm", children: ask.error?.message }) : null
80
+ ] }) }),
81
+ /* @__PURE__ */ jsxs2(Flex2, { gap: 2, children: [
82
+ /* @__PURE__ */ jsx2(
83
+ Input,
84
+ {
85
+ size: "sm",
86
+ value: input,
87
+ placeholder: "Digite sua mensagem...",
88
+ onChange: (e) => setInput(e.currentTarget.value),
89
+ onKeyDown: (e) => {
90
+ if (e.key === "Enter") send();
91
+ }
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsx2(Button2, { size: "sm", colorPalette: "blue", onClick: send, loading: ask.isPending, children: "Enviar" })
95
+ ] })
96
+ ] });
97
+ }
98
+
99
+ export {
100
+ CoreCurrency,
101
+ CoreAssistant
102
+ };
103
+ //# sourceMappingURL=chunk-KD7UQF5E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/CoreCurrency.tsx","../src/components/CoreAssistant.tsx"],"sourcesContent":["import { Button, Flex, Heading, Stack, Text } from \"@chakra-ui/react\";\nimport { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { OonColumnDef } from \"../types\";\nimport { useOonApi } from \"../api/ApiProvider\";\nimport { CoreCollection } from \"./CoreCollection\";\n\nexport interface CoreCurrencyProps {\n /** model das moedas. Default: \"Moeda\". */\n model?: string;\n label?: string;\n endpoint?: string;\n columns?: OonColumnDef[];\n}\n\n/**\n * Multi-moedas (módulo de domínio, Seção 4.6/2.11). Lista as moedas e expõe a\n * ação RESTful de atualizar cotações (POST /<endpoint>/actions/update-rates).\n */\nexport function CoreCurrency({ model = \"Moeda\", label = \"Multi-moedas\", endpoint = \"/moedas\", columns }: CoreCurrencyProps) {\n const { http } = useOonApi();\n const queryClient = useQueryClient();\n\n const updateRates = useMutation({\n mutationFn: () => http.post(`${endpoint}/actions/update-rates`, {}, { headers: { \"x-oon-origin\": \"integration\" } }),\n onSuccess: () => queryClient.invalidateQueries({ queryKey: [\"oon\", \"list\", endpoint] }),\n });\n\n return (\n <Stack gap={6}>\n <Flex align=\"center\" justify=\"space-between\">\n <Heading size=\"lg\">{label}</Heading>\n <Button size=\"sm\" colorPalette=\"blue\" loading={updateRates.isPending} onClick={() => updateRates.mutate()}>\n Atualizar cotações\n </Button>\n </Flex>\n {updateRates.isError ? (\n <Text fontSize=\"sm\" color=\"red.600\">\n {updateRates.error?.message}\n </Text>\n ) : null}\n <CoreCollection model={model} label=\"\" mode={columns ? \"full\" : \"dynamic\"} endpoint={endpoint} columns={columns} />\n </Stack>\n );\n}\n","import { useState } from \"react\";\nimport { Box, Button, Flex, Heading, Input, Stack, Text } from \"@chakra-ui/react\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useOonApi } from \"../api/ApiProvider\";\n\nexport interface AssistantMessage {\n role: \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface CoreAssistantProps {\n /** code do assistente registrado no back (ex.: \"servicos-tomados.revisao\"). */\n assistantCode: string;\n label?: string;\n /** entidade de contexto (apenas tipo + id; nada sensível). */\n entity?: { type: string; id: string };\n /** base de assistentes; default usa o mesmo client REST do Core. */\n endpoint?: string;\n}\n\n/**\n * Assistente IA do Core (Seção 2.12 / 6.2). Envia ao back apenas\n * assistantCode + entity + message — NUNCA chave de IA, modelo ou prompt.\n * O back resolve modelo, prompt, chave e políticas.\n */\nexport function CoreAssistant({ assistantCode, label = \"Assistente\", entity, endpoint = \"/assistant-runs\" }: CoreAssistantProps) {\n const { http } = useOonApi();\n const [messages, setMessages] = useState<AssistantMessage[]>([]);\n const [input, setInput] = useState(\"\");\n\n const ask = useMutation({\n mutationFn: async (message: string) => {\n const { data } = await http.post<{ reply?: string; message?: string }>(\n endpoint,\n {\n assistantCode,\n entity,\n message,\n // Contexto redigido: a Central pode enriquecer, mas o Core não envia PII por padrão.\n context: { redactionPolicy: \"default\" },\n },\n { headers: { \"x-oon-origin\": \"assistant\" } }\n );\n return data.reply ?? data.message ?? \"\";\n },\n onSuccess: (reply) => setMessages((prev) => [...prev, { role: \"assistant\", content: reply }]),\n });\n\n const send = () => {\n const text = input.trim();\n if (!text) return;\n setMessages((prev) => [...prev, { role: \"user\", content: text }]);\n setInput(\"\");\n ask.mutate(text);\n };\n\n return (\n <Stack gap={4} maxW=\"560px\">\n <Heading size=\"md\">{label}</Heading>\n <Box borderWidth=\"1px\" borderColor=\"gray.200\" borderRadius=\"md\" bg=\"white\" p={4} minH=\"240px\">\n <Stack gap={3}>\n {messages.length === 0 ? (\n <Text color=\"gray.400\" fontSize=\"sm\">\n Faça uma pergunta ao assistente.\n </Text>\n ) : (\n messages.map((m, idx) => (\n <Flex key={idx} justify={m.role === \"user\" ? \"flex-end\" : \"flex-start\"}>\n <Box\n bg={m.role === \"user\" ? \"brand.500\" : \"gray.100\"}\n color={m.role === \"user\" ? \"white\" : \"gray.800\"}\n px={3}\n py={2}\n borderRadius=\"md\"\n maxW=\"80%\"\n fontSize=\"sm\"\n >\n {m.content}\n </Box>\n </Flex>\n ))\n )}\n {ask.isPending ? (\n <Text color=\"gray.400\" fontSize=\"sm\">\n Pensando…\n </Text>\n ) : null}\n {ask.isError ? (\n <Text color=\"red.600\" fontSize=\"sm\">\n {ask.error?.message}\n </Text>\n ) : null}\n </Stack>\n </Box>\n <Flex gap={2}>\n <Input\n size=\"sm\"\n value={input}\n placeholder=\"Digite sua mensagem...\"\n onChange={(e) => setInput(e.currentTarget.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") send();\n }}\n />\n <Button size=\"sm\" colorPalette=\"blue\" onClick={send} loading={ask.isPending}>\n Enviar\n </Button>\n </Flex>\n </Stack>\n );\n}\n"],"mappings":"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","names":["Button","Flex","Heading","Stack","Text","useMutation","jsx","jsxs","useMutation","Stack","Heading","Text","Flex","Button"]}