pixelon 0.3.84 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/molecules/chat/StructuredContent/components/index.d.ts +0 -1
- package/dist/components/molecules/chat/StructuredContent/helpers/componentRegistry.d.ts +13 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.esm.js +34 -192
- package/dist/index.js +41 -191
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +1 -1
- package/src/styles/index.scss +0 -1
|
@@ -13,7 +13,6 @@ export { ActionMenu } from './ActionMenu/ActionMenu';
|
|
|
13
13
|
export { ReactiveCrud } from './ReactiveCrud/ReactiveCrud';
|
|
14
14
|
export { ReactiveCrudChat } from './ReactiveCrud/ReactiveCrudChat';
|
|
15
15
|
export { ReactiveCrudItemChat } from './ReactiveCrud/ReactiveCrudItemChat';
|
|
16
|
-
export { PriceNegotiationChat } from './ReactiveCrud/PriceNegotiationChat';
|
|
17
16
|
export { MapView } from './MapView/MapView';
|
|
18
17
|
export { MapViewChat } from './MapView/MapViewChat';
|
|
19
18
|
export type { MapPoint, MapViewProps, MapViewLabels } from './MapView/types';
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ChatComponentProps } from './types';
|
|
3
|
+
export interface HostChatComponent {
|
|
4
|
+
render: React.FC<ChatComponentProps>;
|
|
5
|
+
/** No se oculta al llegar a un estado terminal (paneles y navegación, no acciones de un uso). */
|
|
6
|
+
persistent?: boolean;
|
|
7
|
+
/** Contenido del autor, sin interacción: nunca se oculta al re-hidratar el historial. */
|
|
8
|
+
pureDisplay?: boolean;
|
|
9
|
+
}
|
|
10
|
+
type EntradaHost = React.FC<ChatComponentProps> | HostChatComponent;
|
|
11
|
+
/** Registra componentes del consumidor. Se llama una vez, al arrancar la app. */
|
|
12
|
+
export declare function registerChatComponents(comps: Record<string, EntradaHost>): void;
|
|
13
|
+
/** Vacía el registro del host. Para tests: sin esto un caso contamina al siguiente. */
|
|
14
|
+
export declare function clearChatComponents(): void;
|
|
3
15
|
export declare function renderComponent(props: ChatComponentProps): React.ReactNode;
|
|
16
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,11 @@ export { default as ChatModal } from './components/molecules/chat/Modal/Modal';
|
|
|
25
25
|
export { default as ChatUserAttachments } from './components/molecules/chat/UserAttachments/UserAttachments';
|
|
26
26
|
export { default as ChatUserMessage } from './components/molecules/chat/UserMessage/UserMessage';
|
|
27
27
|
export { StructuredContent as ChatStructuredContent, type StructuredContentProps as ChatStructuredContentProps } from './components/molecules/chat/StructuredContent';
|
|
28
|
+
export { useReactiveCrud } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/useReactiveCrud';
|
|
29
|
+
export { ActionFormDrawer } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/ActionFormDrawer';
|
|
30
|
+
export { matchesVisibleWhen, matchesDisabledWhen, matchesDoneWhen, disabledReasonFor, } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/ReactiveCrud';
|
|
31
|
+
export { registerChatComponents, clearChatComponents, type HostChatComponent, } from './components/molecules/chat/StructuredContent/helpers/componentRegistry';
|
|
32
|
+
export type { ChatComponentProps as ChatHostComponentProps } from './components/molecules/chat/StructuredContent/helpers/types';
|
|
28
33
|
export { ServiceShortcuts } from './components/molecules/chat/StructuredContent/components/ServiceShortcuts/ServiceShortcuts';
|
|
29
34
|
export type { ServiceShortcut, ServiceShortcutsProps } from './components/molecules/chat/StructuredContent/components/ServiceShortcuts/ServiceShortcuts';
|
|
30
35
|
export { ServicesMap } from './components/molecules/chat/StructuredContent/components/ServicesMap/ServicesMap';
|
package/dist/index.esm.js
CHANGED
|
@@ -1651,7 +1651,7 @@ function getSubmitActionId(component) {
|
|
|
1651
1651
|
}
|
|
1652
1652
|
const TERMINAL_STATUS = /* @__PURE__ */ new Set(["answered", "cancelled", "expired"]);
|
|
1653
1653
|
const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge", "reactive_form", "carousel"]);
|
|
1654
|
-
const PERSISTENT_COMPONENTS = /* @__PURE__ */ new Set(["reactive_crud", "reactive_crud_item", "
|
|
1654
|
+
const PERSISTENT_COMPONENTS = /* @__PURE__ */ new Set(["reactive_crud", "reactive_crud_item", "chat_navigator", "map_view", "user_tools"]);
|
|
1655
1655
|
const PURE_DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge"]);
|
|
1656
1656
|
|
|
1657
1657
|
const AnsweredSummary = ({ component }) => {
|
|
@@ -16311,7 +16311,8 @@ function ReactiveCrudItemChat({ component, eventBus }) {
|
|
|
16311
16311
|
const moduleKey = pick("module");
|
|
16312
16312
|
const recordId = pick("record_id") ?? pick("recordId") ?? pick("id") ?? pick("service_id");
|
|
16313
16313
|
const recordLabel = pick("record_label") ?? pick("label");
|
|
16314
|
-
const
|
|
16314
|
+
const allowedRaw = pick("actions");
|
|
16315
|
+
const allowed = Array.isArray(allowedRaw) && allowedRaw.length > 0 ? allowedRaw : void 0;
|
|
16315
16316
|
const config = typeof moduleKey === "string" && resolveModuleConfig ? resolveModuleConfig(moduleKey) : void 0;
|
|
16316
16317
|
if (!config || recordId == null || recordId === "") return null;
|
|
16317
16318
|
return /* @__PURE__ */ jsx(
|
|
@@ -16440,108 +16441,6 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16440
16441
|
] });
|
|
16441
16442
|
}
|
|
16442
16443
|
|
|
16443
|
-
const ACTOR_LABEL = { COLLA: "la empresa aliada", ADMIN: "la operadora" };
|
|
16444
|
-
const TURN_GATED = /* @__PURE__ */ new Set(["accept_price", "propose_price"]);
|
|
16445
|
-
function PriceNegotiationChat({ component, eventBus }) {
|
|
16446
|
-
const { resolveModuleConfig } = useChatConfig();
|
|
16447
|
-
const props = component.props ?? {};
|
|
16448
|
-
const top = component;
|
|
16449
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16450
|
-
const moduleKey = pick("module");
|
|
16451
|
-
const recordId = pick("record_id") ?? pick("service_id") ?? pick("id");
|
|
16452
|
-
const recordLabel = pick("record_label") ?? pick("label");
|
|
16453
|
-
const allowed = pick("actions");
|
|
16454
|
-
const config = typeof moduleKey === "string" && resolveModuleConfig ? resolveModuleConfig(moduleKey) : void 0;
|
|
16455
|
-
if (!config || recordId == null || recordId === "") return null;
|
|
16456
|
-
return /* @__PURE__ */ jsx(
|
|
16457
|
-
NegotiationPanel,
|
|
16458
|
-
{
|
|
16459
|
-
config,
|
|
16460
|
-
recordId: String(recordId),
|
|
16461
|
-
recordLabel,
|
|
16462
|
-
allowed: Array.isArray(allowed) ? allowed.map(String) : void 0,
|
|
16463
|
-
eventBus
|
|
16464
|
-
}
|
|
16465
|
-
);
|
|
16466
|
-
}
|
|
16467
|
-
function NegotiationPanel({ config, recordId, recordLabel, allowed, eventBus }) {
|
|
16468
|
-
const { chatIsForeign } = useChatConfig();
|
|
16469
|
-
const crud = useReactiveCrud(config, eventBus);
|
|
16470
|
-
const [activeAction, setActiveAction] = useState(null);
|
|
16471
|
-
const row = useMemo(
|
|
16472
|
-
() => crud.rows.find((r) => String(r[config.idField]) === recordId),
|
|
16473
|
-
[crud.rows, config.idField, recordId]
|
|
16474
|
-
);
|
|
16475
|
-
const actions = useMemo(() => {
|
|
16476
|
-
if (!row) return [];
|
|
16477
|
-
return (config.rowActions ?? []).filter((a) => !allowed || allowed.includes(a.key)).filter((a) => matchesVisibleWhen(a, row));
|
|
16478
|
-
}, [config.rowActions, row, allowed]);
|
|
16479
|
-
const title = recordLabel ?? config.title ?? "Servicio";
|
|
16480
|
-
const proposed = row?.proposed_price;
|
|
16481
|
-
const proposer = row?.price_proposed_by;
|
|
16482
|
-
const myTurn = row?.my_turn === true || String(row?.my_turn) === "true";
|
|
16483
|
-
const hasOffer = proposed != null && proposed !== "";
|
|
16484
|
-
const canPropose = !allowed || allowed.includes("propose_price");
|
|
16485
|
-
const agreed = row?.price_amount;
|
|
16486
|
-
const esperandoRespuesta = ["QUOTED", "PRE_ASSIGNED"].includes(String(row?.status ?? ""));
|
|
16487
|
-
const cerrada = !esperandoRespuesta && agreed != null && agreed !== "";
|
|
16488
|
-
const ofertaMia = hasOffer && !myTurn;
|
|
16489
|
-
const quienOfrece = ofertaMia ? "tu oferta" : `oferta de ${ACTOR_LABEL[proposer ?? ""] ?? "la otra parte"}`;
|
|
16490
|
-
return /* @__PURE__ */ jsxs("div", { className: "px-chat-price-neg", children: [
|
|
16491
|
-
/* @__PURE__ */ jsxs("div", { className: "px-chat-price-neg__header", children: [
|
|
16492
|
-
/* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__title", children: title }),
|
|
16493
|
-
/* @__PURE__ */ jsx("span", { className: `px-chat-price-neg__badge${cerrada ? " is-closed" : ""}`, children: cerrada ? "Precio acordado" : canPropose ? "Negociaci\xF3n de precio" : "Cotizaci\xF3n" })
|
|
16494
|
-
] }),
|
|
16495
|
-
crud.actionError && /* @__PURE__ */ jsxs("div", { className: "px-chat-price-neg__error", role: "alert", children: [
|
|
16496
|
-
/* @__PURE__ */ jsx("span", { children: crud.actionError }),
|
|
16497
|
-
/* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Cerrar", onClick: crud.clearActionError, children: "\u2715" })
|
|
16498
|
-
] }),
|
|
16499
|
-
crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-price-neg__hint", children: "Cargando\u2026" }),
|
|
16500
|
-
!crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-price-neg__hint", children: "No se encontr\xF3 el servicio." }),
|
|
16501
|
-
row && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16502
|
-
/* @__PURE__ */ jsx("div", { className: "px-chat-price-neg__offer", children: cerrada ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16503
|
-
/* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__amount", children: /* @__PURE__ */ jsx(CurrencyDisplay, { value: agreed }) }),
|
|
16504
|
-
/* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__by", children: "precio acordado" })
|
|
16505
|
-
] }) : hasOffer ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16506
|
-
/* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__amount", children: /* @__PURE__ */ jsx(CurrencyDisplay, { value: proposed }) }),
|
|
16507
|
-
/* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__by", children: canPropose ? quienOfrece : "costo del servicio" })
|
|
16508
|
-
] }) : /* @__PURE__ */ jsx("span", { className: "px-chat-price-neg__by", children: "A\xFAn no hay una oferta. Prop\xF3n un valor." }) }),
|
|
16509
|
-
!cerrada && /* @__PURE__ */ jsx("div", { className: `px-chat-price-neg__turn${myTurn ? " is-mine" : ""}`, children: myTurn ? canPropose ? "Es tu turno: acepta o contraprop\xF3n." : "Es tu turno: acepta o rechaza." : "Esperando la respuesta de la otra parte\u2026" }),
|
|
16510
|
-
!cerrada && /* @__PURE__ */ jsxs("div", { className: "px-chat-price-neg__actions", children: [
|
|
16511
|
-
actions.map((a) => {
|
|
16512
|
-
const gated = TURN_GATED.has(a.key) && !myTurn;
|
|
16513
|
-
const noOffer = a.key === "accept_price" && !hasOffer;
|
|
16514
|
-
const disabled = gated || noOffer || Boolean(chatIsForeign);
|
|
16515
|
-
return /* @__PURE__ */ jsx(
|
|
16516
|
-
"button",
|
|
16517
|
-
{
|
|
16518
|
-
type: "button",
|
|
16519
|
-
className: `px-chat-price-neg__action${a.intent === "danger" ? " is-danger" : a.key === "accept_price" ? " is-primary" : ""}`,
|
|
16520
|
-
disabled,
|
|
16521
|
-
title: gated ? "Esperando la respuesta de la otra parte" : void 0,
|
|
16522
|
-
onClick: () => a.form ? setActiveAction({ action: a, row }) : crud.runEndpoints(a.endpoints ?? [a.endpoint], { ...row, id: row[config.idField] }),
|
|
16523
|
-
children: a.label
|
|
16524
|
-
},
|
|
16525
|
-
a.key
|
|
16526
|
-
);
|
|
16527
|
-
}),
|
|
16528
|
-
actions.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-chat-price-neg__hint", children: "Sin acciones disponibles." })
|
|
16529
|
-
] })
|
|
16530
|
-
] }),
|
|
16531
|
-
activeAction && /* @__PURE__ */ jsx(
|
|
16532
|
-
ActionFormDrawer,
|
|
16533
|
-
{
|
|
16534
|
-
action: activeAction.action,
|
|
16535
|
-
row: activeAction.row,
|
|
16536
|
-
idField: config.idField,
|
|
16537
|
-
eventBus,
|
|
16538
|
-
onExecute: (ctx) => crud.runEndpoints(activeAction.action.endpoints ?? [activeAction.action.endpoint], ctx),
|
|
16539
|
-
onClose: () => setActiveAction(null)
|
|
16540
|
-
}
|
|
16541
|
-
)
|
|
16542
|
-
] });
|
|
16543
|
-
}
|
|
16544
|
-
|
|
16545
16444
|
function MapViewChat({ component, eventBus }) {
|
|
16546
16445
|
const { googleMapsApiKey } = useChatConfig();
|
|
16547
16446
|
const props = component.props ?? {};
|
|
@@ -16756,30 +16655,6 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
|
|
|
16756
16655
|
};
|
|
16757
16656
|
ServicesMap.displayName = "ServicesMap";
|
|
16758
16657
|
|
|
16759
|
-
function ServicesMapChat({ component, eventBus }) {
|
|
16760
|
-
const { resolveModuleConfig, googleMapsApiKey } = useChatConfig();
|
|
16761
|
-
const props = component.props ?? {};
|
|
16762
|
-
const top = component;
|
|
16763
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16764
|
-
const moduleKey = pick("module");
|
|
16765
|
-
let config;
|
|
16766
|
-
if (typeof moduleKey === "string" && resolveModuleConfig) {
|
|
16767
|
-
config = resolveModuleConfig(moduleKey);
|
|
16768
|
-
} else if (pick("data")) {
|
|
16769
|
-
config = component.props ? props : top;
|
|
16770
|
-
}
|
|
16771
|
-
if (!config?.data?.list) return null;
|
|
16772
|
-
return /* @__PURE__ */ jsx(
|
|
16773
|
-
ServicesMap,
|
|
16774
|
-
{
|
|
16775
|
-
config,
|
|
16776
|
-
eventBus,
|
|
16777
|
-
apiKey: googleMapsApiKey,
|
|
16778
|
-
filter: pick("filter")
|
|
16779
|
-
}
|
|
16780
|
-
);
|
|
16781
|
-
}
|
|
16782
|
-
|
|
16783
16658
|
const CLASS$5 = `${COMPONENT_PREFIX$1}service-shortcuts`;
|
|
16784
16659
|
const ICONS = {
|
|
16785
16660
|
map: /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
@@ -16856,62 +16731,6 @@ const ServiceShortcuts = ({
|
|
|
16856
16731
|
};
|
|
16857
16732
|
ServiceShortcuts.displayName = "ServiceShortcuts";
|
|
16858
16733
|
|
|
16859
|
-
const USED_KEY = (messageId) => `px:service_shortcuts:used:${messageId}`;
|
|
16860
|
-
function readUsed(messageId) {
|
|
16861
|
-
if (!messageId) return void 0;
|
|
16862
|
-
try {
|
|
16863
|
-
return localStorage.getItem(USED_KEY(messageId)) ?? void 0;
|
|
16864
|
-
} catch {
|
|
16865
|
-
return void 0;
|
|
16866
|
-
}
|
|
16867
|
-
}
|
|
16868
|
-
const DEFAULTS = {
|
|
16869
|
-
map: { id: "map", label: "Ver en el mapa", hint: "D\xF3nde est\xE1n ubicados", route: "/mapa", icon: "map" },
|
|
16870
|
-
list: { id: "list", label: "Ver la lista", hint: "Gestionar y filtrar", route: "/servicios", icon: "list" },
|
|
16871
|
-
// SPEC-030 — las dos puertas de quien llega por el enlace público y no sabe qué escribir.
|
|
16872
|
-
// No navegan: dicen por él lo que tendría que teclear, y el agente responde con el formulario
|
|
16873
|
-
// que toque. Así el componente no necesita saber qué formulario es cada cosa.
|
|
16874
|
-
request: {
|
|
16875
|
-
id: "request",
|
|
16876
|
-
label: "Solicitar una gr\xFAa",
|
|
16877
|
-
hint: "Pedir el servicio ahora",
|
|
16878
|
-
prompt: "Quiero solicitar una gr\xFAa",
|
|
16879
|
-
icon: "tow"
|
|
16880
|
-
},
|
|
16881
|
-
check: {
|
|
16882
|
-
id: "check",
|
|
16883
|
-
label: "Consultar mi servicio",
|
|
16884
|
-
hint: "Ya ped\xED una gr\xFAa antes",
|
|
16885
|
-
prompt: "Quiero consultar el servicio que ya ped\xED",
|
|
16886
|
-
icon: "search"
|
|
16887
|
-
}
|
|
16888
|
-
};
|
|
16889
|
-
function ServiceShortcutsChat({ component, eventBus, assistantMessageId }) {
|
|
16890
|
-
const [elegido, setElegido] = useState(() => readUsed(assistantMessageId));
|
|
16891
|
-
const props = component.props ?? {};
|
|
16892
|
-
const top = component;
|
|
16893
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16894
|
-
const recordar = (id) => {
|
|
16895
|
-
setElegido(id);
|
|
16896
|
-
if (!assistantMessageId) return;
|
|
16897
|
-
try {
|
|
16898
|
-
localStorage.setItem(USED_KEY(assistantMessageId), id);
|
|
16899
|
-
} catch {
|
|
16900
|
-
}
|
|
16901
|
-
};
|
|
16902
|
-
const custom = pick("options");
|
|
16903
|
-
const options = custom?.length ? custom : (pick("show") ?? ["map", "list"]).map((k) => DEFAULTS[k]).filter(Boolean);
|
|
16904
|
-
return /* @__PURE__ */ jsx(
|
|
16905
|
-
ServiceShortcuts,
|
|
16906
|
-
{
|
|
16907
|
-
options,
|
|
16908
|
-
eventBus,
|
|
16909
|
-
selectedId: elegido,
|
|
16910
|
-
onSelect: recordar
|
|
16911
|
-
}
|
|
16912
|
-
);
|
|
16913
|
-
}
|
|
16914
|
-
|
|
16915
16734
|
const DATE_CHIPS = [
|
|
16916
16735
|
{ key: "todo", label: "Todo" },
|
|
16917
16736
|
{ key: "hoy", label: "Hoy" },
|
|
@@ -17575,16 +17394,39 @@ const COMPONENT_MAP = {
|
|
|
17575
17394
|
action_menu: ActionMenu,
|
|
17576
17395
|
reactive_crud: ReactiveCrudChat,
|
|
17577
17396
|
reactive_crud_item: ReactiveCrudItemChat,
|
|
17578
|
-
price_negotiation: PriceNegotiationChat,
|
|
17579
17397
|
chat_navigator: ChatNavigatorChat,
|
|
17580
17398
|
user_tools: UserToolsChat,
|
|
17581
|
-
map_view: MapViewChat
|
|
17582
|
-
services_map
|
|
17583
|
-
|
|
17584
|
-
|
|
17399
|
+
map_view: MapViewChat
|
|
17400
|
+
// SPEC-115 — `price_negotiation`, `services_map` y `service_shortcuts` salieron de aquí: son del flujo del
|
|
17401
|
+
// solicitante de grúas, no primitivos de diseño. Los registra el host (towing-web) con
|
|
17402
|
+
// `registerChatComponents`. Los componentes de presentación (ServicesMap, ServiceShortcuts)
|
|
17403
|
+
// SÍ se quedan y siguen exportándose: lo que se fue es su adaptador al chat.
|
|
17404
|
+
};
|
|
17405
|
+
const HOST_COMPONENTS = {};
|
|
17406
|
+
function normalizar(e) {
|
|
17407
|
+
return typeof e === "function" ? { render: e } : e;
|
|
17408
|
+
}
|
|
17409
|
+
function registerChatComponents(comps) {
|
|
17410
|
+
for (const [tipo, entrada] of Object.entries(comps)) {
|
|
17411
|
+
HOST_COMPONENTS[tipo] = normalizar(entrada);
|
|
17412
|
+
}
|
|
17413
|
+
}
|
|
17414
|
+
function clearChatComponents() {
|
|
17415
|
+
for (const tipo of Object.keys(HOST_COMPONENTS)) delete HOST_COMPONENTS[tipo];
|
|
17416
|
+
}
|
|
17417
|
+
function esPersistente(tipo) {
|
|
17418
|
+
const h = HOST_COMPONENTS[tipo];
|
|
17419
|
+
if (h) return h.persistent === true;
|
|
17420
|
+
return PERSISTENT_COMPONENTS.has(tipo);
|
|
17421
|
+
}
|
|
17422
|
+
function esDisplayPuro(tipo) {
|
|
17423
|
+
const h = HOST_COMPONENTS[tipo];
|
|
17424
|
+
if (h) return h.pureDisplay === true;
|
|
17425
|
+
return PURE_DISPLAY_COMPONENTS.has(tipo);
|
|
17426
|
+
}
|
|
17585
17427
|
function renderComponent(props) {
|
|
17586
17428
|
const { component } = props;
|
|
17587
|
-
if (!
|
|
17429
|
+
if (!esPersistente(component.type) && !esDisplayPuro(component.type)) {
|
|
17588
17430
|
if (component.status) {
|
|
17589
17431
|
if (TERMINAL_STATUS.has(component.status)) {
|
|
17590
17432
|
const policy = component.visibility_policy ?? "hide_on_terminal";
|
|
@@ -17597,7 +17439,7 @@ function renderComponent(props) {
|
|
|
17597
17439
|
return null;
|
|
17598
17440
|
}
|
|
17599
17441
|
}
|
|
17600
|
-
const Component = COMPONENT_MAP[component.type];
|
|
17442
|
+
const Component = HOST_COMPONENTS[component.type]?.render ?? COMPONENT_MAP[component.type];
|
|
17601
17443
|
if (!Component) return null;
|
|
17602
17444
|
return /* @__PURE__ */ jsx(Component, { ...props });
|
|
17603
17445
|
}
|
|
@@ -24735,4 +24577,4 @@ function buildBreadcrumbPath(items, targetKey, currentPath = []) {
|
|
|
24735
24577
|
return [];
|
|
24736
24578
|
}
|
|
24737
24579
|
|
|
24738
|
-
export { BottomSheet, CHAT_CONFIG_DEFAULTS, CHAT_EVENT, ICON_TYPES as CHAT_ICON_TYPES, Chat, AssistantMessage as ChatAssistantMessage, AssistantThinkingIndicator as ChatAssistantThinkingIndicator, AttachmentPreview as ChatAttachmentPreview, Avatar as ChatAvatar, Button$1 as ChatButton, ChatConfigProvider, DateDivider as ChatDateDivider, FileViewer as ChatFileViewer, ChatFloatingActions, FullscreenViewer as ChatFullscreenViewer, ChatHeader as ChatHeaderComponent, Icon$1 as ChatIcon, Input$2 as ChatInput, ChatInput as ChatInputComponent, Link as ChatLink, Loader$1 as ChatLoader, Logo as ChatLogo, MessageStatus as ChatMessageStatus, Modal as ChatModal, ChatNavigator, Select$2 as ChatSelect, SelectMenu as ChatSelectMenu, StructuredContent as ChatStructuredContent, Text as ChatText, Textarea as ChatTextarea, UserAttachments as ChatUserAttachments, UserMessage as ChatUserMessage, ChatWidget, FileField, BADGE_VARIANTS as LUMI_BADGE_VARIANTS, DEFAULT_TITLES as LUMI_DEFAULT_TITLES, LUMI_ICON_TYPES, LiveIndicator, LocationField, ActionBar as LumiActionBar, Badge as LumiBadge, Base as LumiBase, BaseNavbar as LumiBaseNavbar, BaseWorkspace as LumiBaseWorkspace, Breadcrumb as LumiBreadcrumb, BreadcrumbItem as LumiBreadcrumbItem, BreadcrumbSeparator as LumiBreadcrumbSeparator, Button as LumiButton, Calendar as LumiCalendar, Card as LumiCard, Checkbox$1 as LumiCheckbox, Crud as LumiCrud, CurrencyDisplay as LumiCurrencyDisplay, Dashboard as LumiDashboard, DashboardNavbar as LumiDashboardNavbar, DashboardSidebar as LumiDashboardSidebar, DashboardWorkspace as LumiDashboardWorkspace, DateDisplay as LumiDateDisplay, DateInput$1 as LumiDateInput, Drawer as LumiDrawer, DropdownMenu as LumiDropdownMenu, DynamicForm as LumiDynamicForm, FieldValue as LumiFieldValue, Filter as LumiFilter, FilterRow as LumiFilterRow, Checkbox as LumiFormCheckbox, DateInput as LumiFormDateInput, FormDrawer as LumiFormDrawer, Input as LumiFormInput, Select as LumiFormSelect, TimeInput as LumiFormTimeInput, Icon as LumiIcon, Input$1 as LumiInput, Loader as LumiLoader, Menu as LumiMenu, MenuItem as LumiMenuItem, MenuItemGroup as LumiMenuItemGroup, Notification as LumiNotification, Pagination as LumiPagination, Popover as LumiPopover, QRCode as LumiQRCode, RecordCard as LumiRecordCard, Select$1 as LumiSelect, StepIndicator as LumiStepIndicator, Stepper as LumiStepper, SubMenu as LumiSubMenu, Table as LumiTable, Tabs as LumiTabs, TextArea as LumiTextArea, TimeInput$1 as LumiTimeInput, Tooltip as LumiTooltip, MapView, ReactiveCrud, ServiceShortcuts, ServicesMap, SessionExpiryPrompt, UserTools, chatEventBus, createDeepPropertySubscriber, createEventBus, createStore, createStoreMerger, deepMerge, getLastFleetSnapshot, setLastFleetSnapshot, useChatConfig };
|
|
24580
|
+
export { ActionFormDrawer, BottomSheet, CHAT_CONFIG_DEFAULTS, CHAT_EVENT, ICON_TYPES as CHAT_ICON_TYPES, Chat, AssistantMessage as ChatAssistantMessage, AssistantThinkingIndicator as ChatAssistantThinkingIndicator, AttachmentPreview as ChatAttachmentPreview, Avatar as ChatAvatar, Button$1 as ChatButton, ChatConfigProvider, DateDivider as ChatDateDivider, FileViewer as ChatFileViewer, ChatFloatingActions, FullscreenViewer as ChatFullscreenViewer, ChatHeader as ChatHeaderComponent, Icon$1 as ChatIcon, Input$2 as ChatInput, ChatInput as ChatInputComponent, Link as ChatLink, Loader$1 as ChatLoader, Logo as ChatLogo, MessageStatus as ChatMessageStatus, Modal as ChatModal, ChatNavigator, Select$2 as ChatSelect, SelectMenu as ChatSelectMenu, StructuredContent as ChatStructuredContent, Text as ChatText, Textarea as ChatTextarea, UserAttachments as ChatUserAttachments, UserMessage as ChatUserMessage, ChatWidget, FileField, BADGE_VARIANTS as LUMI_BADGE_VARIANTS, DEFAULT_TITLES as LUMI_DEFAULT_TITLES, LUMI_ICON_TYPES, LiveIndicator, LocationField, ActionBar as LumiActionBar, Badge as LumiBadge, Base as LumiBase, BaseNavbar as LumiBaseNavbar, BaseWorkspace as LumiBaseWorkspace, Breadcrumb as LumiBreadcrumb, BreadcrumbItem as LumiBreadcrumbItem, BreadcrumbSeparator as LumiBreadcrumbSeparator, Button as LumiButton, Calendar as LumiCalendar, Card as LumiCard, Checkbox$1 as LumiCheckbox, Crud as LumiCrud, CurrencyDisplay as LumiCurrencyDisplay, Dashboard as LumiDashboard, DashboardNavbar as LumiDashboardNavbar, DashboardSidebar as LumiDashboardSidebar, DashboardWorkspace as LumiDashboardWorkspace, DateDisplay as LumiDateDisplay, DateInput$1 as LumiDateInput, Drawer as LumiDrawer, DropdownMenu as LumiDropdownMenu, DynamicForm as LumiDynamicForm, FieldValue as LumiFieldValue, Filter as LumiFilter, FilterRow as LumiFilterRow, Checkbox as LumiFormCheckbox, DateInput as LumiFormDateInput, FormDrawer as LumiFormDrawer, Input as LumiFormInput, Select as LumiFormSelect, TimeInput as LumiFormTimeInput, Icon as LumiIcon, Input$1 as LumiInput, Loader as LumiLoader, Menu as LumiMenu, MenuItem as LumiMenuItem, MenuItemGroup as LumiMenuItemGroup, Notification as LumiNotification, Pagination as LumiPagination, Popover as LumiPopover, QRCode as LumiQRCode, RecordCard as LumiRecordCard, Select$1 as LumiSelect, StepIndicator as LumiStepIndicator, Stepper as LumiStepper, SubMenu as LumiSubMenu, Table as LumiTable, Tabs as LumiTabs, TextArea as LumiTextArea, TimeInput$1 as LumiTimeInput, Tooltip as LumiTooltip, MapView, ReactiveCrud, ServiceShortcuts, ServicesMap, SessionExpiryPrompt, UserTools, chatEventBus, clearChatComponents, createDeepPropertySubscriber, createEventBus, createStore, createStoreMerger, deepMerge, disabledReasonFor, getLastFleetSnapshot, matchesDisabledWhen, matchesDoneWhen, matchesVisibleWhen, registerChatComponents, setLastFleetSnapshot, useChatConfig, useReactiveCrud };
|
package/dist/index.js
CHANGED
|
@@ -1672,7 +1672,7 @@ function getSubmitActionId(component) {
|
|
|
1672
1672
|
}
|
|
1673
1673
|
const TERMINAL_STATUS = /* @__PURE__ */ new Set(["answered", "cancelled", "expired"]);
|
|
1674
1674
|
const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge", "reactive_form", "carousel"]);
|
|
1675
|
-
const PERSISTENT_COMPONENTS = /* @__PURE__ */ new Set(["reactive_crud", "reactive_crud_item", "
|
|
1675
|
+
const PERSISTENT_COMPONENTS = /* @__PURE__ */ new Set(["reactive_crud", "reactive_crud_item", "chat_navigator", "map_view", "user_tools"]);
|
|
1676
1676
|
const PURE_DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge"]);
|
|
1677
1677
|
|
|
1678
1678
|
const AnsweredSummary = ({ component }) => {
|
|
@@ -16332,7 +16332,8 @@ function ReactiveCrudItemChat({ component, eventBus }) {
|
|
|
16332
16332
|
const moduleKey = pick("module");
|
|
16333
16333
|
const recordId = pick("record_id") ?? pick("recordId") ?? pick("id") ?? pick("service_id");
|
|
16334
16334
|
const recordLabel = pick("record_label") ?? pick("label");
|
|
16335
|
-
const
|
|
16335
|
+
const allowedRaw = pick("actions");
|
|
16336
|
+
const allowed = Array.isArray(allowedRaw) && allowedRaw.length > 0 ? allowedRaw : void 0;
|
|
16336
16337
|
const config = typeof moduleKey === "string" && resolveModuleConfig ? resolveModuleConfig(moduleKey) : void 0;
|
|
16337
16338
|
if (!config || recordId == null || recordId === "") return null;
|
|
16338
16339
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -16461,108 +16462,6 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
|
|
|
16461
16462
|
] });
|
|
16462
16463
|
}
|
|
16463
16464
|
|
|
16464
|
-
const ACTOR_LABEL = { COLLA: "la empresa aliada", ADMIN: "la operadora" };
|
|
16465
|
-
const TURN_GATED = /* @__PURE__ */ new Set(["accept_price", "propose_price"]);
|
|
16466
|
-
function PriceNegotiationChat({ component, eventBus }) {
|
|
16467
|
-
const { resolveModuleConfig } = useChatConfig();
|
|
16468
|
-
const props = component.props ?? {};
|
|
16469
|
-
const top = component;
|
|
16470
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16471
|
-
const moduleKey = pick("module");
|
|
16472
|
-
const recordId = pick("record_id") ?? pick("service_id") ?? pick("id");
|
|
16473
|
-
const recordLabel = pick("record_label") ?? pick("label");
|
|
16474
|
-
const allowed = pick("actions");
|
|
16475
|
-
const config = typeof moduleKey === "string" && resolveModuleConfig ? resolveModuleConfig(moduleKey) : void 0;
|
|
16476
|
-
if (!config || recordId == null || recordId === "") return null;
|
|
16477
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16478
|
-
NegotiationPanel,
|
|
16479
|
-
{
|
|
16480
|
-
config,
|
|
16481
|
-
recordId: String(recordId),
|
|
16482
|
-
recordLabel,
|
|
16483
|
-
allowed: Array.isArray(allowed) ? allowed.map(String) : void 0,
|
|
16484
|
-
eventBus
|
|
16485
|
-
}
|
|
16486
|
-
);
|
|
16487
|
-
}
|
|
16488
|
-
function NegotiationPanel({ config, recordId, recordLabel, allowed, eventBus }) {
|
|
16489
|
-
const { chatIsForeign } = useChatConfig();
|
|
16490
|
-
const crud = useReactiveCrud(config, eventBus);
|
|
16491
|
-
const [activeAction, setActiveAction] = React.useState(null);
|
|
16492
|
-
const row = React.useMemo(
|
|
16493
|
-
() => crud.rows.find((r) => String(r[config.idField]) === recordId),
|
|
16494
|
-
[crud.rows, config.idField, recordId]
|
|
16495
|
-
);
|
|
16496
|
-
const actions = React.useMemo(() => {
|
|
16497
|
-
if (!row) return [];
|
|
16498
|
-
return (config.rowActions ?? []).filter((a) => !allowed || allowed.includes(a.key)).filter((a) => matchesVisibleWhen(a, row));
|
|
16499
|
-
}, [config.rowActions, row, allowed]);
|
|
16500
|
-
const title = recordLabel ?? config.title ?? "Servicio";
|
|
16501
|
-
const proposed = row?.proposed_price;
|
|
16502
|
-
const proposer = row?.price_proposed_by;
|
|
16503
|
-
const myTurn = row?.my_turn === true || String(row?.my_turn) === "true";
|
|
16504
|
-
const hasOffer = proposed != null && proposed !== "";
|
|
16505
|
-
const canPropose = !allowed || allowed.includes("propose_price");
|
|
16506
|
-
const agreed = row?.price_amount;
|
|
16507
|
-
const esperandoRespuesta = ["QUOTED", "PRE_ASSIGNED"].includes(String(row?.status ?? ""));
|
|
16508
|
-
const cerrada = !esperandoRespuesta && agreed != null && agreed !== "";
|
|
16509
|
-
const ofertaMia = hasOffer && !myTurn;
|
|
16510
|
-
const quienOfrece = ofertaMia ? "tu oferta" : `oferta de ${ACTOR_LABEL[proposer ?? ""] ?? "la otra parte"}`;
|
|
16511
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-price-neg", children: [
|
|
16512
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-price-neg__header", children: [
|
|
16513
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__title", children: title }),
|
|
16514
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-chat-price-neg__badge${cerrada ? " is-closed" : ""}`, children: cerrada ? "Precio acordado" : canPropose ? "Negociaci\xF3n de precio" : "Cotizaci\xF3n" })
|
|
16515
|
-
] }),
|
|
16516
|
-
crud.actionError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-price-neg__error", role: "alert", children: [
|
|
16517
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: crud.actionError }),
|
|
16518
|
-
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Cerrar", onClick: crud.clearActionError, children: "\u2715" })
|
|
16519
|
-
] }),
|
|
16520
|
-
crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-price-neg__hint", children: "Cargando\u2026" }),
|
|
16521
|
-
!crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-price-neg__hint", children: "No se encontr\xF3 el servicio." }),
|
|
16522
|
-
row && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
16523
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-price-neg__offer", children: cerrada ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
16524
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__amount", children: /* @__PURE__ */ jsxRuntime.jsx(CurrencyDisplay, { value: agreed }) }),
|
|
16525
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__by", children: "precio acordado" })
|
|
16526
|
-
] }) : hasOffer ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
16527
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__amount", children: /* @__PURE__ */ jsxRuntime.jsx(CurrencyDisplay, { value: proposed }) }),
|
|
16528
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__by", children: canPropose ? quienOfrece : "costo del servicio" })
|
|
16529
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-price-neg__by", children: "A\xFAn no hay una oferta. Prop\xF3n un valor." }) }),
|
|
16530
|
-
!cerrada && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `px-chat-price-neg__turn${myTurn ? " is-mine" : ""}`, children: myTurn ? canPropose ? "Es tu turno: acepta o contraprop\xF3n." : "Es tu turno: acepta o rechaza." : "Esperando la respuesta de la otra parte\u2026" }),
|
|
16531
|
-
!cerrada && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-price-neg__actions", children: [
|
|
16532
|
-
actions.map((a) => {
|
|
16533
|
-
const gated = TURN_GATED.has(a.key) && !myTurn;
|
|
16534
|
-
const noOffer = a.key === "accept_price" && !hasOffer;
|
|
16535
|
-
const disabled = gated || noOffer || Boolean(chatIsForeign);
|
|
16536
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16537
|
-
"button",
|
|
16538
|
-
{
|
|
16539
|
-
type: "button",
|
|
16540
|
-
className: `px-chat-price-neg__action${a.intent === "danger" ? " is-danger" : a.key === "accept_price" ? " is-primary" : ""}`,
|
|
16541
|
-
disabled,
|
|
16542
|
-
title: gated ? "Esperando la respuesta de la otra parte" : void 0,
|
|
16543
|
-
onClick: () => a.form ? setActiveAction({ action: a, row }) : crud.runEndpoints(a.endpoints ?? [a.endpoint], { ...row, id: row[config.idField] }),
|
|
16544
|
-
children: a.label
|
|
16545
|
-
},
|
|
16546
|
-
a.key
|
|
16547
|
-
);
|
|
16548
|
-
}),
|
|
16549
|
-
actions.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-price-neg__hint", children: "Sin acciones disponibles." })
|
|
16550
|
-
] })
|
|
16551
|
-
] }),
|
|
16552
|
-
activeAction && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16553
|
-
ActionFormDrawer,
|
|
16554
|
-
{
|
|
16555
|
-
action: activeAction.action,
|
|
16556
|
-
row: activeAction.row,
|
|
16557
|
-
idField: config.idField,
|
|
16558
|
-
eventBus,
|
|
16559
|
-
onExecute: (ctx) => crud.runEndpoints(activeAction.action.endpoints ?? [activeAction.action.endpoint], ctx),
|
|
16560
|
-
onClose: () => setActiveAction(null)
|
|
16561
|
-
}
|
|
16562
|
-
)
|
|
16563
|
-
] });
|
|
16564
|
-
}
|
|
16565
|
-
|
|
16566
16465
|
function MapViewChat({ component, eventBus }) {
|
|
16567
16466
|
const { googleMapsApiKey } = useChatConfig();
|
|
16568
16467
|
const props = component.props ?? {};
|
|
@@ -16777,30 +16676,6 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
|
|
|
16777
16676
|
};
|
|
16778
16677
|
ServicesMap.displayName = "ServicesMap";
|
|
16779
16678
|
|
|
16780
|
-
function ServicesMapChat({ component, eventBus }) {
|
|
16781
|
-
const { resolveModuleConfig, googleMapsApiKey } = useChatConfig();
|
|
16782
|
-
const props = component.props ?? {};
|
|
16783
|
-
const top = component;
|
|
16784
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16785
|
-
const moduleKey = pick("module");
|
|
16786
|
-
let config;
|
|
16787
|
-
if (typeof moduleKey === "string" && resolveModuleConfig) {
|
|
16788
|
-
config = resolveModuleConfig(moduleKey);
|
|
16789
|
-
} else if (pick("data")) {
|
|
16790
|
-
config = component.props ? props : top;
|
|
16791
|
-
}
|
|
16792
|
-
if (!config?.data?.list) return null;
|
|
16793
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16794
|
-
ServicesMap,
|
|
16795
|
-
{
|
|
16796
|
-
config,
|
|
16797
|
-
eventBus,
|
|
16798
|
-
apiKey: googleMapsApiKey,
|
|
16799
|
-
filter: pick("filter")
|
|
16800
|
-
}
|
|
16801
|
-
);
|
|
16802
|
-
}
|
|
16803
|
-
|
|
16804
16679
|
const CLASS$5 = `${COMPONENT_PREFIX$1}service-shortcuts`;
|
|
16805
16680
|
const ICONS = {
|
|
16806
16681
|
map: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
@@ -16877,62 +16752,6 @@ const ServiceShortcuts = ({
|
|
|
16877
16752
|
};
|
|
16878
16753
|
ServiceShortcuts.displayName = "ServiceShortcuts";
|
|
16879
16754
|
|
|
16880
|
-
const USED_KEY = (messageId) => `px:service_shortcuts:used:${messageId}`;
|
|
16881
|
-
function readUsed(messageId) {
|
|
16882
|
-
if (!messageId) return void 0;
|
|
16883
|
-
try {
|
|
16884
|
-
return localStorage.getItem(USED_KEY(messageId)) ?? void 0;
|
|
16885
|
-
} catch {
|
|
16886
|
-
return void 0;
|
|
16887
|
-
}
|
|
16888
|
-
}
|
|
16889
|
-
const DEFAULTS = {
|
|
16890
|
-
map: { id: "map", label: "Ver en el mapa", hint: "D\xF3nde est\xE1n ubicados", route: "/mapa", icon: "map" },
|
|
16891
|
-
list: { id: "list", label: "Ver la lista", hint: "Gestionar y filtrar", route: "/servicios", icon: "list" },
|
|
16892
|
-
// SPEC-030 — las dos puertas de quien llega por el enlace público y no sabe qué escribir.
|
|
16893
|
-
// No navegan: dicen por él lo que tendría que teclear, y el agente responde con el formulario
|
|
16894
|
-
// que toque. Así el componente no necesita saber qué formulario es cada cosa.
|
|
16895
|
-
request: {
|
|
16896
|
-
id: "request",
|
|
16897
|
-
label: "Solicitar una gr\xFAa",
|
|
16898
|
-
hint: "Pedir el servicio ahora",
|
|
16899
|
-
prompt: "Quiero solicitar una gr\xFAa",
|
|
16900
|
-
icon: "tow"
|
|
16901
|
-
},
|
|
16902
|
-
check: {
|
|
16903
|
-
id: "check",
|
|
16904
|
-
label: "Consultar mi servicio",
|
|
16905
|
-
hint: "Ya ped\xED una gr\xFAa antes",
|
|
16906
|
-
prompt: "Quiero consultar el servicio que ya ped\xED",
|
|
16907
|
-
icon: "search"
|
|
16908
|
-
}
|
|
16909
|
-
};
|
|
16910
|
-
function ServiceShortcutsChat({ component, eventBus, assistantMessageId }) {
|
|
16911
|
-
const [elegido, setElegido] = React.useState(() => readUsed(assistantMessageId));
|
|
16912
|
-
const props = component.props ?? {};
|
|
16913
|
-
const top = component;
|
|
16914
|
-
const pick = (key) => props[key] !== void 0 ? props[key] : top[key];
|
|
16915
|
-
const recordar = (id) => {
|
|
16916
|
-
setElegido(id);
|
|
16917
|
-
if (!assistantMessageId) return;
|
|
16918
|
-
try {
|
|
16919
|
-
localStorage.setItem(USED_KEY(assistantMessageId), id);
|
|
16920
|
-
} catch {
|
|
16921
|
-
}
|
|
16922
|
-
};
|
|
16923
|
-
const custom = pick("options");
|
|
16924
|
-
const options = custom?.length ? custom : (pick("show") ?? ["map", "list"]).map((k) => DEFAULTS[k]).filter(Boolean);
|
|
16925
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16926
|
-
ServiceShortcuts,
|
|
16927
|
-
{
|
|
16928
|
-
options,
|
|
16929
|
-
eventBus,
|
|
16930
|
-
selectedId: elegido,
|
|
16931
|
-
onSelect: recordar
|
|
16932
|
-
}
|
|
16933
|
-
);
|
|
16934
|
-
}
|
|
16935
|
-
|
|
16936
16755
|
const DATE_CHIPS = [
|
|
16937
16756
|
{ key: "todo", label: "Todo" },
|
|
16938
16757
|
{ key: "hoy", label: "Hoy" },
|
|
@@ -17596,16 +17415,39 @@ const COMPONENT_MAP = {
|
|
|
17596
17415
|
action_menu: ActionMenu,
|
|
17597
17416
|
reactive_crud: ReactiveCrudChat,
|
|
17598
17417
|
reactive_crud_item: ReactiveCrudItemChat,
|
|
17599
|
-
price_negotiation: PriceNegotiationChat,
|
|
17600
17418
|
chat_navigator: ChatNavigatorChat,
|
|
17601
17419
|
user_tools: UserToolsChat,
|
|
17602
|
-
map_view: MapViewChat
|
|
17603
|
-
services_map
|
|
17604
|
-
|
|
17605
|
-
|
|
17420
|
+
map_view: MapViewChat
|
|
17421
|
+
// SPEC-115 — `price_negotiation`, `services_map` y `service_shortcuts` salieron de aquí: son del flujo del
|
|
17422
|
+
// solicitante de grúas, no primitivos de diseño. Los registra el host (towing-web) con
|
|
17423
|
+
// `registerChatComponents`. Los componentes de presentación (ServicesMap, ServiceShortcuts)
|
|
17424
|
+
// SÍ se quedan y siguen exportándose: lo que se fue es su adaptador al chat.
|
|
17425
|
+
};
|
|
17426
|
+
const HOST_COMPONENTS = {};
|
|
17427
|
+
function normalizar(e) {
|
|
17428
|
+
return typeof e === "function" ? { render: e } : e;
|
|
17429
|
+
}
|
|
17430
|
+
function registerChatComponents(comps) {
|
|
17431
|
+
for (const [tipo, entrada] of Object.entries(comps)) {
|
|
17432
|
+
HOST_COMPONENTS[tipo] = normalizar(entrada);
|
|
17433
|
+
}
|
|
17434
|
+
}
|
|
17435
|
+
function clearChatComponents() {
|
|
17436
|
+
for (const tipo of Object.keys(HOST_COMPONENTS)) delete HOST_COMPONENTS[tipo];
|
|
17437
|
+
}
|
|
17438
|
+
function esPersistente(tipo) {
|
|
17439
|
+
const h = HOST_COMPONENTS[tipo];
|
|
17440
|
+
if (h) return h.persistent === true;
|
|
17441
|
+
return PERSISTENT_COMPONENTS.has(tipo);
|
|
17442
|
+
}
|
|
17443
|
+
function esDisplayPuro(tipo) {
|
|
17444
|
+
const h = HOST_COMPONENTS[tipo];
|
|
17445
|
+
if (h) return h.pureDisplay === true;
|
|
17446
|
+
return PURE_DISPLAY_COMPONENTS.has(tipo);
|
|
17447
|
+
}
|
|
17606
17448
|
function renderComponent(props) {
|
|
17607
17449
|
const { component } = props;
|
|
17608
|
-
if (!
|
|
17450
|
+
if (!esPersistente(component.type) && !esDisplayPuro(component.type)) {
|
|
17609
17451
|
if (component.status) {
|
|
17610
17452
|
if (TERMINAL_STATUS.has(component.status)) {
|
|
17611
17453
|
const policy = component.visibility_policy ?? "hide_on_terminal";
|
|
@@ -17618,7 +17460,7 @@ function renderComponent(props) {
|
|
|
17618
17460
|
return null;
|
|
17619
17461
|
}
|
|
17620
17462
|
}
|
|
17621
|
-
const Component = COMPONENT_MAP[component.type];
|
|
17463
|
+
const Component = HOST_COMPONENTS[component.type]?.render ?? COMPONENT_MAP[component.type];
|
|
17622
17464
|
if (!Component) return null;
|
|
17623
17465
|
return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
|
|
17624
17466
|
}
|
|
@@ -24756,6 +24598,7 @@ function buildBreadcrumbPath(items, targetKey, currentPath = []) {
|
|
|
24756
24598
|
return [];
|
|
24757
24599
|
}
|
|
24758
24600
|
|
|
24601
|
+
exports.ActionFormDrawer = ActionFormDrawer;
|
|
24759
24602
|
exports.BottomSheet = BottomSheet;
|
|
24760
24603
|
exports.CHAT_CONFIG_DEFAULTS = CHAT_CONFIG_DEFAULTS;
|
|
24761
24604
|
exports.CHAT_EVENT = CHAT_EVENT;
|
|
@@ -24854,11 +24697,18 @@ exports.ServicesMap = ServicesMap;
|
|
|
24854
24697
|
exports.SessionExpiryPrompt = SessionExpiryPrompt;
|
|
24855
24698
|
exports.UserTools = UserTools;
|
|
24856
24699
|
exports.chatEventBus = chatEventBus;
|
|
24700
|
+
exports.clearChatComponents = clearChatComponents;
|
|
24857
24701
|
exports.createDeepPropertySubscriber = createDeepPropertySubscriber;
|
|
24858
24702
|
exports.createEventBus = createEventBus;
|
|
24859
24703
|
exports.createStore = createStore;
|
|
24860
24704
|
exports.createStoreMerger = createStoreMerger;
|
|
24861
24705
|
exports.deepMerge = deepMerge;
|
|
24706
|
+
exports.disabledReasonFor = disabledReasonFor;
|
|
24862
24707
|
exports.getLastFleetSnapshot = getLastFleetSnapshot;
|
|
24708
|
+
exports.matchesDisabledWhen = matchesDisabledWhen;
|
|
24709
|
+
exports.matchesDoneWhen = matchesDoneWhen;
|
|
24710
|
+
exports.matchesVisibleWhen = matchesVisibleWhen;
|
|
24711
|
+
exports.registerChatComponents = registerChatComponents;
|
|
24863
24712
|
exports.setLastFleetSnapshot = setLastFleetSnapshot;
|
|
24864
24713
|
exports.useChatConfig = useChatConfig;
|
|
24714
|
+
exports.useReactiveCrud = useReactiveCrud;
|