pixelon 0.3.75 → 0.3.76

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,9 @@
1
+ import './DeadlineCountdown.scss';
2
+ interface Props {
3
+ /** Hora límite en ISO. */
4
+ deadline: string;
5
+ label?: string;
6
+ expiredLabel?: string;
7
+ }
8
+ export declare function DeadlineCountdown({ deadline, label, expiredLabel }: Props): import("react/jsx-runtime").JSX.Element | null;
9
+ export default DeadlineCountdown;
@@ -144,5 +144,22 @@ export interface ReactiveCrudConfig {
144
144
  x?: number | string;
145
145
  y?: number | string;
146
146
  };
147
+ /** SPEC-087 — cuenta atrás en el panel de un registro. Ver `DeadlineConfig`. */
148
+ deadline?: DeadlineConfig;
149
+ }
150
+ /** SPEC-087 — fecha límite de un registro, pintada como cuenta atrás junto a sus acciones.
151
+ *
152
+ * Es deliberadamente genérico: dice «esta tarjeta tiene una fecha límite», no de qué es el plazo.
153
+ * El campo apunta a un dato de la fila con un INSTANTE en ISO, nunca a una duración: una duración
154
+ * se queda vieja en cuanto se guarda, y estas cards viven para siempre en el chat.
155
+ *
156
+ * Si el campo viene vacío no se pinta nada — no hay plazo que enseñar. */
157
+ export interface DeadlineConfig {
158
+ /** Campo de la fila con la hora límite en ISO. */
159
+ field: string;
160
+ /** Texto sobre el contador. Ej: 'Para que salga la grúa'. */
161
+ label?: string;
162
+ /** Qué decir cuando ya venció. Se sigue mostrando: desaparecer sería volver al silencio. */
163
+ expiredLabel?: string;
147
164
  }
148
165
  export type { FilterManager };
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ export type { ChatNavigatorConfig, ChatNavigatorItem, ChatNavigatorEndpoint } fr
40
40
  export { UserTools } from './components/molecules/chat/StructuredContent/components/UserTools/UserTools';
41
41
  export type { UserToolsConfig, UserToolItem } from './components/molecules/chat/StructuredContent/components/UserTools/types';
42
42
  export { ReactiveCrud } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/ReactiveCrud';
43
- export type { ReactiveCrudConfig, ReactiveCrudField, RowActionDef, EndpointRef, CrudMolecule, CrudFieldOptionsEndpoint, RowActionVisibleWhen, } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/types';
43
+ export type { ReactiveCrudConfig, ReactiveCrudField, DeadlineConfig, RowActionDef, EndpointRef, CrudMolecule, CrudFieldOptionsEndpoint, RowActionVisibleWhen, } from './components/molecules/chat/StructuredContent/components/ReactiveCrud/types';
44
44
  export { Chat } from './components/organisms/chat/Chat';
45
45
  export type { ChatProps } from './components/organisms/chat/Chat';
46
46
  export type { ChatMessage } from './core/chat';
package/dist/index.esm.js CHANGED
@@ -15871,6 +15871,41 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
15871
15871
  ] });
15872
15872
  }
15873
15873
 
15874
+ function restante(hasta) {
15875
+ return Math.max(0, hasta - Date.now());
15876
+ }
15877
+ function formatear(ms) {
15878
+ const total = Math.floor(ms / 1e3);
15879
+ const min = Math.floor(total / 60);
15880
+ const seg = total % 60;
15881
+ return `${String(min).padStart(2, "0")}:${String(seg).padStart(2, "0")}`;
15882
+ }
15883
+ function DeadlineCountdown({ deadline, label, expiredLabel }) {
15884
+ const hasta = new Date(deadline).getTime();
15885
+ const valida = !Number.isNaN(hasta);
15886
+ const [ms, setMs] = useState(() => valida ? restante(hasta) : 0);
15887
+ useEffect(() => {
15888
+ if (!valida) return;
15889
+ setMs(restante(hasta));
15890
+ const id = setInterval(() => setMs(restante(hasta)), 1e3);
15891
+ return () => clearInterval(id);
15892
+ }, [hasta, valida]);
15893
+ if (!valida) return null;
15894
+ const vencido = ms <= 0;
15895
+ const apurado = !vencido && ms <= 6e4;
15896
+ return /* @__PURE__ */ jsx(
15897
+ "div",
15898
+ {
15899
+ className: `px-deadline${vencido ? " is-expired" : ""}${apurado ? " is-urgent" : ""}`,
15900
+ role: "status",
15901
+ children: vencido ? /* @__PURE__ */ jsx("span", { className: "px-deadline__expired", children: expiredLabel ?? "El plazo venci\xF3" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
15902
+ label && /* @__PURE__ */ jsx("span", { className: "px-deadline__label", children: label }),
15903
+ /* @__PURE__ */ jsx("span", { className: "px-deadline__time", children: formatear(ms) })
15904
+ ] })
15905
+ }
15906
+ );
15907
+ }
15908
+
15874
15909
  function ReactiveCrudItemChat({ component, eventBus }) {
15875
15910
  const { resolveModuleConfig } = useChatConfig();
15876
15911
  const props = component.props ?? {};
@@ -15938,6 +15973,14 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
15938
15973
  ] }),
15939
15974
  crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-crud-item__hint", children: "Cargando\u2026" }),
15940
15975
  !crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-crud-item__hint", children: "No se encontr\xF3 el servicio." }),
15976
+ row && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsx(
15977
+ DeadlineCountdown,
15978
+ {
15979
+ deadline: row[config.deadline.field],
15980
+ label: config.deadline.label,
15981
+ expiredLabel: config.deadline.expiredLabel
15982
+ }
15983
+ ),
15941
15984
  row && /* @__PURE__ */ jsxs("div", { className: "px-chat-crud-item__actions", children: [
15942
15985
  config.detail && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-crud-item__action", onClick: () => setDetailRow(row), children: "Ver" }),
15943
15986
  actions.map((a) => {
package/dist/index.js CHANGED
@@ -15892,6 +15892,41 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
15892
15892
  ] });
15893
15893
  }
15894
15894
 
15895
+ function restante(hasta) {
15896
+ return Math.max(0, hasta - Date.now());
15897
+ }
15898
+ function formatear(ms) {
15899
+ const total = Math.floor(ms / 1e3);
15900
+ const min = Math.floor(total / 60);
15901
+ const seg = total % 60;
15902
+ return `${String(min).padStart(2, "0")}:${String(seg).padStart(2, "0")}`;
15903
+ }
15904
+ function DeadlineCountdown({ deadline, label, expiredLabel }) {
15905
+ const hasta = new Date(deadline).getTime();
15906
+ const valida = !Number.isNaN(hasta);
15907
+ const [ms, setMs] = React.useState(() => valida ? restante(hasta) : 0);
15908
+ React.useEffect(() => {
15909
+ if (!valida) return;
15910
+ setMs(restante(hasta));
15911
+ const id = setInterval(() => setMs(restante(hasta)), 1e3);
15912
+ return () => clearInterval(id);
15913
+ }, [hasta, valida]);
15914
+ if (!valida) return null;
15915
+ const vencido = ms <= 0;
15916
+ const apurado = !vencido && ms <= 6e4;
15917
+ return /* @__PURE__ */ jsxRuntime.jsx(
15918
+ "div",
15919
+ {
15920
+ className: `px-deadline${vencido ? " is-expired" : ""}${apurado ? " is-urgent" : ""}`,
15921
+ role: "status",
15922
+ children: vencido ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-deadline__expired", children: expiredLabel ?? "El plazo venci\xF3" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15923
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-deadline__label", children: label }),
15924
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-deadline__time", children: formatear(ms) })
15925
+ ] })
15926
+ }
15927
+ );
15928
+ }
15929
+
15895
15930
  function ReactiveCrudItemChat({ component, eventBus }) {
15896
15931
  const { resolveModuleConfig } = useChatConfig();
15897
15932
  const props = component.props ?? {};
@@ -15959,6 +15994,14 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, eventBus
15959
15994
  ] }),
15960
15995
  crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Cargando\u2026" }),
15961
15996
  !crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "No se encontr\xF3 el servicio." }),
15997
+ row && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsxRuntime.jsx(
15998
+ DeadlineCountdown,
15999
+ {
16000
+ deadline: row[config.deadline.field],
16001
+ label: config.deadline.label,
16002
+ expiredLabel: config.deadline.expiredLabel
16003
+ }
16004
+ ),
15962
16005
  row && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-item__actions", children: [
15963
16006
  config.detail && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-crud-item__action", onClick: () => setDetailRow(row), children: "Ver" }),
15964
16007
  actions.map((a) => {