@asteby/metacore-runtime-react 42.0.0 → 44.0.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/CHANGELOG.md +44 -0
- package/dist/action-modal-dispatcher.d.ts +2 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +74 -8
- package/dist/api-context.d.ts.map +1 -1
- package/dist/api-context.js +6 -4
- package/dist/dynamic-icon.d.ts.map +1 -1
- package/dist/dynamic-icon.js +9 -13
- package/dist/dynamic-kanban.d.ts +83 -6
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +647 -146
- package/dist/dynamic-row-actions.d.ts.map +1 -1
- package/dist/dynamic-row-actions.js +11 -15
- package/dist/dynamic-table.d.ts +1 -1
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +14 -1
- package/dist/federated-action-loader.d.ts +18 -0
- package/dist/federated-action-loader.d.ts.map +1 -0
- package/dist/federated-action-loader.js +34 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/license/license-gate.d.ts +0 -21
- package/dist/license/license-gate.d.ts.map +1 -1
- package/dist/license/license-gate.js +5 -2
- package/dist/model-action-toolbar.d.ts.map +1 -1
- package/dist/model-action-toolbar.js +3 -12
- package/dist/portal-drag-overlay.d.ts +5 -0
- package/dist/portal-drag-overlay.d.ts.map +1 -0
- package/dist/portal-drag-overlay.js +8 -0
- package/dist/query-batch.d.ts.map +1 -1
- package/dist/query-batch.js +6 -3
- package/dist/sidebar-layout-manager.js +3 -2
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/use-flip-animation.d.ts +6 -0
- package/dist/use-flip-animation.d.ts.map +1 -1
- package/dist/use-flip-animation.js +11 -4
- package/package.json +6 -5
- package/src/__tests__/action-modal-missing-custom.test.tsx +12 -4
- package/src/__tests__/dynamic-icon-slot.test.tsx +50 -0
- package/src/__tests__/dynamic-kanban-lane-reorder.test.tsx +2 -1
- package/src/__tests__/dynamic-kanban-pipelines-pro.test.tsx +388 -0
- package/src/__tests__/dynamic-kanban.test.tsx +15 -2
- package/src/__tests__/federated-action-modal.test.tsx +315 -0
- package/src/__tests__/image-cell-lucide.test.tsx +7 -5
- package/src/action-modal-dispatcher.tsx +102 -10
- package/src/api-context.tsx +7 -5
- package/src/dynamic-icon.tsx +12 -16
- package/src/dynamic-kanban.tsx +950 -262
- package/src/dynamic-row-actions.tsx +11 -15
- package/src/dynamic-table.tsx +16 -2
- package/src/federated-action-loader.ts +40 -0
- package/src/index.ts +8 -0
- package/src/license/license-gate.tsx +6 -2
- package/src/model-action-toolbar.tsx +3 -12
- package/src/portal-drag-overlay.tsx +20 -0
- package/src/query-batch.ts +6 -3
- package/src/sidebar-layout-manager.tsx +3 -3
- package/src/types.ts +4 -0
- package/src/use-flip-animation.ts +16 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 44.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 35f19fd: Los modals federados de acciones abren siempre el componente del addon, nunca un confirmatorio genérico.
|
|
8
|
+
|
|
9
|
+
- sdk: `subscribeActionComponents(listener)` en el registry de acciones; registrar o quitar un componente notifica a los suscriptores.
|
|
10
|
+
- runtime-react: `ActionModalDispatcher` lee el registry de forma reactiva (`useSyncExternalStore`). Una acción con `modal` muestra "Cargando…" mientras el remote carga, pinta el componente en cuanto se registra y, si no llega en 20 s (`FEDERATED_ACTION_MODAL_TIMEOUT_MS`) muestra el error explícito y lo registra con `console.error`. Un slug sin prefijo `addon.nombre` también se pide al host y espera el timeout. `modal` se respeta venga del manifest del addon o de un override inyectado por el host.
|
|
11
|
+
- runtime-react: `setFederatedActionLoader(fn)` / `FederatedActionLoader` para que el host cargue el remote; el dispatcher lo invoca con `{ model, actionKey, modal }` al abrir y cada 2 s mientras espera.
|
|
12
|
+
- runtime-react: `useDynamicRowActions` y `ModelActionToolbar` pasan la definición completa de la acción (antes se perdía `modal`; en la barra, las acciones `placement: "create"` con `modal` abrían el confirmatorio y ejecutaban sin registro) y el menú de fila abre el dispatcher también para acciones que solo declaran `modal`.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Updated dependencies [35f19fd]
|
|
17
|
+
- @asteby/metacore-sdk@3.10.0
|
|
18
|
+
|
|
19
|
+
## 43.0.0
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- afce99b: Kanban de pipelines a nivel pro.
|
|
24
|
+
|
|
25
|
+
- **La tarjeta arrastrada queda bajo el cursor.** El `DragOverlay` de dnd-kit se pinta en `<body>` (`PortalDragOverlay`, exportado). Con el tema glass, el panel de la página tiene `backdrop-filter` y se volvía el bloque contenedor del overlay `fixed`, que aparecía desplazado a la derecha y abajo. Lo mismo para la barra de acciones masivas de las tablas, el modal de instalación del marketplace y el veil de licencia.
|
|
26
|
+
- **Las columnas no permitidas se marcan al levantar la tarjeta y no aceptan el drop.** `isTransitionAllowed` sigue la misma regla que `StageMachine.Allows` del kernel: sin `transitions` en la metadata no hay restricción; una lista vacía no permite movimientos entre etapas; una tarjeta sin etapa (o con una ajena a la máquina) puede ir a cualquier etapa. Soltar en una columna no permitida devuelve la tarjeta a su lugar, sin petición ni toast.
|
|
27
|
+
- **Movimiento optimista con rollback animado.** El movimiento corre sobre `useOptimisticMutation`; si el servidor lo rechaza, la tarjeta vuelve a su columna con `useFlipAnimation` (nueva opción `shouldAnimate`) y un toast con el motivo. El drop anima la tarjeta hasta su nuevo lugar.
|
|
28
|
+
- **Totales por columna.** El encabezado muestra el conteo real del servidor y la suma de cada columna que declara `display_config.aggregate`, en la moneda de la org, y se recalculan en vivo mientras un movimiento está en curso.
|
|
29
|
+
- **Tarjetas sin filas vacías.** Un campo sin valor (o con un uuid sin resolver) no se pinta como "Canal: —"; la tarjeta muestra los siguientes campos que sí tienen valor. La búsqueda por columna encuentra una relación por su nombre.
|
|
30
|
+
- **Auto-scroll horizontal y teclado.** Cerca del borde el tablero se desplaza solo; con teclado, Espacio/Enter levanta la tarjeta, ←/→ cambian de columna y Escape cancela, con anuncios para lector de pantalla.
|
|
31
|
+
- `DynamicKanban` y `DynamicTable` toman la moneda y la zona horaria del `OrgRuntimeProvider` cuando no llegan por prop (antes el dinero caía a USD).
|
|
32
|
+
- `useApi()` reenvía al cliente del host exactamente los argumentos recibidos, sin un `config` `undefined` al final.
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- 80ff0ba: Recargar ya no parpadea ni mueve nada por el tema o los íconos.
|
|
37
|
+
|
|
38
|
+
- theme: `@asteby/metacore-theme/boot` con `themeBootScript()`, un script inline para el inicio de `<head>` que vuelve a pintar, antes del primer frame, el tema que el usuario vio la última vez (claro/oscuro, `data-ui-*`, clases `font-*`, variables de marca y la hoja de superficies). En la primera visita sigue `prefers-color-scheme`. `ThemeProvider` guarda ese estado (`persistBoot`, activo por defecto) y reactiva las transiciones cuando monta; no toca `<html>` si la clase ya es la correcta.
|
|
39
|
+
- ui: registro de glifos compartido en `@asteby/metacore-ui/icons` (`Glyph`, `getGlyph`, `loadGlyph`, `preloadGlyphs`, `registerGlyphs`). Un glifo visto antes se dibuja en el primer render desde localStorage, cada nombre conserva un solo componente y, mientras uno nuevo carga, `<Glyph>` ocupa su tamaño con un `<svg>` vacío. `resolveIconName` usa el mismo registro.
|
|
40
|
+
- runtime-react: `DynamicIcon` dibuja con `Glyph`, así que las acciones de tabla y los menús ya no aparecen sin ícono para después empujar el texto, tampoco al volver a abrir un menú. Los nombres con dígito (`Trash2`, `Building2`) resuelven su glifo. `DynamicTable` precarga los íconos de las acciones al recibir la metadata.
|
|
41
|
+
- app-providers: mientras `/org/branding` responde, `PlatformConfigProvider` usa la marca cacheada, no los defaults, y solo vuelve a pintar los tokens cuando cambia claro/oscuro; aplicar la marca o la fuente no escribe en `<html>` si el valor no cambió.
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [afce99b]
|
|
44
|
+
- Updated dependencies [80ff0ba]
|
|
45
|
+
- @asteby/metacore-ui@2.23.0
|
|
46
|
+
|
|
3
47
|
## 42.0.0
|
|
4
48
|
|
|
5
49
|
### Minor Changes
|
|
@@ -38,4 +38,6 @@ export declare function readRecordPath(record: any, path: string): unknown;
|
|
|
38
38
|
/** Scalar seed for one action field from the row being acted on. */
|
|
39
39
|
export declare function scalarDefaultFromRecord(field: ActionFieldDef, record: any): unknown;
|
|
40
40
|
export declare function ActionModalDispatcher({ open, onOpenChange, action, model, record, endpoint, onSuccess, }: ActionModalProps): import("react").JSX.Element | null;
|
|
41
|
+
/** How long an action with `modal` waits for its federated component. */
|
|
42
|
+
export declare const FEDERATED_ACTION_MODAL_TIMEOUT_MS = 20000;
|
|
41
43
|
//# sourceMappingURL=action-modal-dispatcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"AA4EA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAA;AAE9E,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAGxB,MAAM,sBAAsB,CAAA;AAG7B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;AAiBhD,MAAM,WAAW,WAAW;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAM1D;AAsBD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAStE;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkB3F;AAYD,MAAM,WAAW,sBAAsB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;CAC1C;AAED,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,cAAc,EAAE,GAAG,SAAS,EACpC,MAAM,EAAE,GAAG,EACX,SAAS,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GAC5H,sBAAsB,EAAE,CAyB1B;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAY1D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASjE;AAUD,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAgBnF;AAED,wBAAgB,qBAAqB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,GACZ,EAAE,gBAAgB,sCAmFlB;AAED,yEAAyE;AACzE,eAAO,MAAM,iCAAiC,QAAS,CAAA"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// ActionModalDispatcher — renders the right modal for a custom action:
|
|
3
3
|
// 1) Custom component from the SDK registry → use it
|
|
4
|
-
// 2) action.modal set but no registered component →
|
|
5
|
-
//
|
|
4
|
+
// 2) action.modal set but no registered component → loading state while the
|
|
5
|
+
// host loads the remote (setFederatedActionLoader); the registry is reactive,
|
|
6
|
+
// so the component renders the moment it registers. Timeout →
|
|
7
|
+
// MissingCustomActionModal (a malformed slug still asks the host, then
|
|
8
|
+
// times out). NEVER falls back to confirm/fields — that
|
|
9
|
+
// hides a broken federated UI.
|
|
6
10
|
// 3) action.fields[] / action.steps[] → GenericActionModal / WizardActionModal
|
|
7
11
|
// 4) action.confirm OR action.confirmMessage → ConfirmActionDialog
|
|
8
12
|
// 5) action.executable (host opened the modal; no modal/fields/confirm) →
|
|
@@ -11,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
11
15
|
//
|
|
12
16
|
// The host injects its axios-like client via <ApiProvider>; we no longer
|
|
13
17
|
// depend on a bundler alias to `@/lib/api`.
|
|
14
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
18
|
+
import { useState, useEffect, useMemo, useSyncExternalStore } from 'react';
|
|
15
19
|
import { useTranslation } from 'react-i18next';
|
|
16
20
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, Input, Textarea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, } from '@asteby/metacore-ui/primitives';
|
|
17
21
|
import { Loader2 } from 'lucide-react';
|
|
@@ -35,7 +39,8 @@ import { FieldGrid, FieldCell, FieldLabel } from './field-grid';
|
|
|
35
39
|
import { useMetadataCache } from './metadata-cache';
|
|
36
40
|
import { ViewValue, objectLabel, relationSiblingValue, isLineItemsField as isRecordLineItemsField, } from './dialogs/dynamic-record';
|
|
37
41
|
// Canonical registry lives in @asteby/metacore-sdk
|
|
38
|
-
import { getActionComponent, } from '@asteby/metacore-sdk';
|
|
42
|
+
import { getActionComponent, subscribeActionComponents, } from '@asteby/metacore-sdk';
|
|
43
|
+
import { requestFederatedAction } from './federated-action-loader';
|
|
39
44
|
export function isPrefillSpec(v) {
|
|
40
45
|
return (typeof v === 'object' &&
|
|
41
46
|
v !== null &&
|
|
@@ -188,14 +193,18 @@ export function scalarDefaultFromRecord(field, record) {
|
|
|
188
193
|
return undefined;
|
|
189
194
|
}
|
|
190
195
|
export function ActionModalDispatcher({ open, onOpenChange, action, model, record, endpoint, onSuccess, }) {
|
|
191
|
-
|
|
196
|
+
// Reactive read: a federated remote usually registers AFTER the first
|
|
197
|
+
// render, and a memoized lookup would pin the fallback forever.
|
|
198
|
+
const readComponent = () => getActionComponent(model, action.key);
|
|
199
|
+
const CustomComponent = useSyncExternalStore(subscribeActionComponents, readComponent, readComponent);
|
|
192
200
|
if (CustomComponent) {
|
|
193
201
|
return (_jsx(CustomComponent, { open: open, onOpenChange: onOpenChange, action: action, model: model, record: record, endpoint: endpoint, onSuccess: onSuccess }));
|
|
194
202
|
}
|
|
195
|
-
// Declarative custom slot (`modal: "addon.action"`).
|
|
196
|
-
//
|
|
203
|
+
// Declarative custom slot (`modal: "addon.action"`). Wait for the remote,
|
|
204
|
+
// then a hard error — confirm/fields generics look "fine" and hide a
|
|
205
|
+
// missing remote.
|
|
197
206
|
if (action.modal) {
|
|
198
|
-
return (_jsx(
|
|
207
|
+
return (_jsx(PendingCustomActionModal, { open: open, onOpenChange: onOpenChange, action: action, model: model }));
|
|
199
208
|
}
|
|
200
209
|
if (action.steps && action.steps.length > 0) {
|
|
201
210
|
return (_jsx(WizardActionModal, { open: open, onOpenChange: onOpenChange, action: action, model: model, record: record, endpoint: endpoint, onSuccess: onSuccess }));
|
|
@@ -214,6 +223,63 @@ export function ActionModalDispatcher({ open, onOpenChange, action, model, recor
|
|
|
214
223
|
}
|
|
215
224
|
return null;
|
|
216
225
|
}
|
|
226
|
+
/** How long an action with `modal` waits for its federated component. */
|
|
227
|
+
export const FEDERATED_ACTION_MODAL_TIMEOUT_MS = 20_000;
|
|
228
|
+
/** How often the host loader is re-invoked while waiting. */
|
|
229
|
+
const FEDERATED_ACTION_RETRY_MS = 2_000;
|
|
230
|
+
const MODAL_SLUG_RE = /^[\w-]+(\.[\w-]+)+$/;
|
|
231
|
+
/**
|
|
232
|
+
* `modal` declared, component not registered yet: show a loading dialog, ask
|
|
233
|
+
* the host to load the remote (re-asking periodically), and give up with
|
|
234
|
+
* MissingCustomActionModal after the timeout. The dispatcher swaps this out
|
|
235
|
+
* for the real component as soon as the registry reports it. `modal` is
|
|
236
|
+
* honored wherever it came from — the addon's own manifest or a host-injected
|
|
237
|
+
* override from another addon that registerAction()s over it.
|
|
238
|
+
*/
|
|
239
|
+
function PendingCustomActionModal({ open, onOpenChange, action, model, }) {
|
|
240
|
+
const { t } = useTranslation();
|
|
241
|
+
const slug = action.modal || '';
|
|
242
|
+
const [timedOut, setTimedOut] = useState(false);
|
|
243
|
+
useEffect(() => {
|
|
244
|
+
if (!open)
|
|
245
|
+
return;
|
|
246
|
+
// A slug without a valid `<addon>.<name>` prefix still goes to the
|
|
247
|
+
// host loader (it decides which remote to load) and still times out —
|
|
248
|
+
// the component is looked up by (model, action.key), never by slug.
|
|
249
|
+
// Warn so a malformed manifest is diagnosable before the timeout.
|
|
250
|
+
const validSlug = MODAL_SLUG_RE.test(slug);
|
|
251
|
+
if (!validSlug) {
|
|
252
|
+
console.warn('[metacore] action modal slug has no valid "<addon>.<name>" prefix', {
|
|
253
|
+
model,
|
|
254
|
+
action: action.key,
|
|
255
|
+
modal: slug,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
setTimedOut(false);
|
|
259
|
+
const req = { model, actionKey: action.key, modal: slug };
|
|
260
|
+
requestFederatedAction(req);
|
|
261
|
+
const retry = setInterval(() => requestFederatedAction(req), FEDERATED_ACTION_RETRY_MS);
|
|
262
|
+
const giveUp = setTimeout(() => {
|
|
263
|
+
clearInterval(retry);
|
|
264
|
+
console.error('[metacore] federated action modal did not register in time', {
|
|
265
|
+
model,
|
|
266
|
+
action: action.key,
|
|
267
|
+
modal: slug,
|
|
268
|
+
validSlug,
|
|
269
|
+
timeoutMs: FEDERATED_ACTION_MODAL_TIMEOUT_MS,
|
|
270
|
+
});
|
|
271
|
+
setTimedOut(true);
|
|
272
|
+
}, FEDERATED_ACTION_MODAL_TIMEOUT_MS);
|
|
273
|
+
return () => {
|
|
274
|
+
clearInterval(retry);
|
|
275
|
+
clearTimeout(giveUp);
|
|
276
|
+
};
|
|
277
|
+
}, [open, model, action.key, slug]);
|
|
278
|
+
if (timedOut) {
|
|
279
|
+
return _jsx(MissingCustomActionModal, { open: open, onOpenChange: onOpenChange, action: action, model: model });
|
|
280
|
+
}
|
|
281
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: t(action.label, { defaultValue: action.label }) }), _jsx(DialogDescription, { children: t('dynamic.action_modal_loading', { defaultValue: 'Cargando…' }) })] }), _jsx("div", { className: "flex justify-center py-6", "data-testid": "federated-action-loading", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) })] }) }));
|
|
282
|
+
}
|
|
217
283
|
/** Shown when the action declares `modal` but no federated component registered. */
|
|
218
284
|
function MissingCustomActionModal({ open, onOpenChange, action, model, }) {
|
|
219
285
|
const { t } = useTranslation();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-context.d.ts","sourceRoot":"","sources":["../src/api-context.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAwD,MAAM,OAAO,CAAA;AAI5E,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACtB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACzE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACtF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACrF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;CAC/E;AAID,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B;AAED,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,gBAAgB,qBAuBjE;AAmCD,mFAAmF;AACnF,wBAAgB,MAAM,IAAI,SAAS,
|
|
1
|
+
{"version":3,"file":"api-context.d.ts","sourceRoot":"","sources":["../src/api-context.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAwD,MAAM,OAAO,CAAA;AAI5E,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACtB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACzE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACtF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;IACrF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC,CAAA;CAC/E;AAID,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,SAAS,CAAA;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B;AAED,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,gBAAgB,qBAuBjE;AAmCD,mFAAmF;AACnF,wBAAgB,MAAM,IAAI,SAAS,CAkBlC;AAED;;wEAEwE;AACxE,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;CACzC;AAID,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B;AAED,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,mBAAmB,qBAEvE;AAED,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C"}
|
package/dist/api-context.js
CHANGED
|
@@ -62,10 +62,12 @@ export function useApi() {
|
|
|
62
62
|
// remembered, so the refresh after a save reads the saved row. The
|
|
63
63
|
// wrapper is stable while the host client is.
|
|
64
64
|
return useMemo(() => ({
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
// Each call reaches the host client with the arguments it was given —
|
|
66
|
+
// never a trailing `undefined` it didn't ask for.
|
|
67
|
+
get: (...args) => batchGet(ctx, ...args),
|
|
68
|
+
post: (...args) => isWrite('post', args[0]) ? mutating(ctx.post(...args)) : ctx.post(...args),
|
|
69
|
+
put: (...args) => mutating(ctx.put(...args)),
|
|
70
|
+
delete: (...args) => mutating(ctx.delete(...args)),
|
|
69
71
|
}), [ctx]);
|
|
70
72
|
}
|
|
71
73
|
const BranchContext = createContext({ id: undefined });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-icon.d.ts","sourceRoot":"","sources":["../src/dynamic-icon.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dynamic-icon.d.ts","sourceRoot":"","sources":["../src/dynamic-icon.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AA2BD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,gBAAgB,sCAIhE;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CASnE;AASD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED,wEAAwE;AACxE,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C"}
|
package/dist/dynamic-icon.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
// DynamicIcon resolves a lucide glyph by name without pulling the full icon
|
|
3
|
-
// set into the shared chunk.
|
|
4
|
-
|
|
3
|
+
// set into the shared chunk. It draws through the shared glyph registry of
|
|
4
|
+
// @asteby/metacore-ui: a glyph seen before renders in the first frame, and an
|
|
5
|
+
// unseen one holds its box until it loads, so the label next to it stays put.
|
|
5
6
|
import dynamicIconImports from 'lucide-react/dynamicIconImports';
|
|
7
|
+
import { Glyph } from '@asteby/metacore-ui/icons';
|
|
6
8
|
function pascalToKebab(pascal) {
|
|
7
9
|
return pascal
|
|
8
10
|
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
@@ -17,21 +19,15 @@ function kebabToPascal(kebab) {
|
|
|
17
19
|
}
|
|
18
20
|
function loaderFor(pascal) {
|
|
19
21
|
const kebab = pascalToKebab(pascal);
|
|
20
|
-
|
|
22
|
+
// Lucide keys split digits ("building-2"); "building2" is not one.
|
|
23
|
+
return (dynamicIconImports[kebab] ??
|
|
24
|
+
dynamicIconImports[kebab.replace(/([a-z])(\d)/g, '$1-$2')]);
|
|
21
25
|
}
|
|
22
26
|
export function DynamicIcon({ name, className }) {
|
|
23
27
|
const resolved = resolveLucideIconName(name);
|
|
24
|
-
|
|
25
|
-
if (!resolved)
|
|
26
|
-
return null;
|
|
27
|
-
const loader = loaderFor(resolved);
|
|
28
|
-
if (!loader)
|
|
29
|
-
return null;
|
|
30
|
-
return lazy(loader);
|
|
31
|
-
}, [resolved]);
|
|
32
|
-
if (!Icon)
|
|
28
|
+
if (!resolved)
|
|
33
29
|
return null;
|
|
34
|
-
return
|
|
30
|
+
return _jsx(Glyph, { name: resolved, className: className });
|
|
35
31
|
}
|
|
36
32
|
// resolveLucideIconName — canonical PascalCase lucide name for a value that is
|
|
37
33
|
// either already PascalCase ("CreditCard") or the kebab slug lucide documents
|
package/dist/dynamic-kanban.d.ts
CHANGED
|
@@ -19,12 +19,19 @@ export declare function deriveStages(metadata: TableMetadata): StageMeta[];
|
|
|
19
19
|
export declare const UNASSIGNED_LANE = "__unassigned__";
|
|
20
20
|
export declare function groupByStage(records: any[], groupByKey: string, stages: StageMeta[]): Map<string, any[]>;
|
|
21
21
|
/**
|
|
22
|
-
* Whether a card may move `from → to`
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* Whether a card may move `from → to` — the same rule as the kernel's
|
|
23
|
+
* `StageMachine.Allows`, so a lane the board offers never ends in a 422:
|
|
24
|
+
*
|
|
25
|
+
* - no `transitions` in the metadata → no stage machine, any move;
|
|
26
|
+
* - a move to the same stage is a no-op, always allowed;
|
|
27
|
+
* - a card with no stage yet — or one outside `stageKeys` (a value written
|
|
28
|
+
* before the machine existed) — is being placed, not moved: any stage takes it;
|
|
29
|
+
* - otherwise the move must be declared. An EMPTY list means the machine allows
|
|
30
|
+
* no moves between its stages.
|
|
31
|
+
*
|
|
32
|
+
* `'*'` is a wildcard on either side.
|
|
26
33
|
*/
|
|
27
|
-
export declare function isTransitionAllowed(transitions: StageTransition[] | undefined, from: string, to: string): boolean;
|
|
34
|
+
export declare function isTransitionAllowed(transitions: StageTransition[] | undefined, from: string, to: string, stageKeys?: ReadonlySet<string>): boolean;
|
|
28
35
|
/**
|
|
29
36
|
* Returns a NEW grouping with `cardId` moved from `fromStage` to `toStage`
|
|
30
37
|
* (appended to the destination lane). Pure — does not mutate the input map.
|
|
@@ -70,6 +77,71 @@ export declare function selectCardColumns(metadata: TableMetadata, maxFields?: n
|
|
|
70
77
|
* exported for unit tests.
|
|
71
78
|
*/
|
|
72
79
|
export declare function cardCellValue(card: any, col: ColumnDefinition): unknown;
|
|
80
|
+
/**
|
|
81
|
+
* Plain text of a card cell — what a person reads on the card. A resolved
|
|
82
|
+
* relation reads as its label/name (never the raw FK uuid), so the lane search
|
|
83
|
+
* and the drag announcements match what is on screen. Pure — exported for tests.
|
|
84
|
+
*/
|
|
85
|
+
export declare function cardCellText(card: any, col: ColumnDefinition): string;
|
|
86
|
+
/**
|
|
87
|
+
* Whether a card field has nothing worth a row: unset, blank, an empty list,
|
|
88
|
+
* `false`, or an opaque id that no relation resolved to a name (a soft-ref
|
|
89
|
+
* uuid column). The card hides those rows instead of painting "Campo: —".
|
|
90
|
+
* Pure — exported for unit tests.
|
|
91
|
+
*/
|
|
92
|
+
export declare function isEmptyCardValue(card: any, col: ColumnDefinition): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* The fields a card shows: the first `max` candidates that carry a value for
|
|
95
|
+
* THIS card. Candidates come in metadata order, so a card with an empty
|
|
96
|
+
* "Asignado a" shows the next useful field instead of a dash. Pure.
|
|
97
|
+
*/
|
|
98
|
+
export declare function visibleCardFields(card: any, candidates: ColumnDefinition[], max?: number): ColumnDefinition[];
|
|
99
|
+
/**
|
|
100
|
+
* Records as the board paints them: each card with an unconfirmed move shows in
|
|
101
|
+
* its destination lane. The fetched records stay as the server sent them, so a
|
|
102
|
+
* rejected move just drops its override and the card is back where it was.
|
|
103
|
+
* Pure — exported for unit tests.
|
|
104
|
+
*/
|
|
105
|
+
export declare function applyStageOverrides(records: any[], overrides: Record<string, string> | undefined, groupByKey: string): any[];
|
|
106
|
+
/** Per-lane change an in-flight move makes to the server totals. */
|
|
107
|
+
export interface LaneDelta {
|
|
108
|
+
count: number;
|
|
109
|
+
sums: Record<string, number>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* How the unconfirmed moves shift each lane's server count and aggregate sums:
|
|
113
|
+
* the source lane loses the card (and its values), the destination gains them.
|
|
114
|
+
* Lets the header totals follow the drag live and snap back on a rollback
|
|
115
|
+
* without touching the server figures. Pure — exported for unit tests.
|
|
116
|
+
*/
|
|
117
|
+
export declare function laneDeltasFromOverrides(records: any[], overrides: Record<string, string> | undefined, groupByKey: string, aggregateKeys?: string[]): Record<string, LaneDelta>;
|
|
118
|
+
/**
|
|
119
|
+
* Returns a NEW per-lane aggregate map with a card's numeric values moved from
|
|
120
|
+
* `fromStage` to `toStage`. Lanes with no known sums yet are left alone. Pure.
|
|
121
|
+
*/
|
|
122
|
+
export declare function applyLaneAggregatesOnMove(aggregates: Record<string, Record<string, number>>, card: any, fromStage: string, toStage: string, aggregateKeys: string[]): Record<string, Record<string, number>>;
|
|
123
|
+
/** A lane's on-screen box, as the keyboard navigation reads it. */
|
|
124
|
+
export interface LaneRect {
|
|
125
|
+
id: string;
|
|
126
|
+
left: number;
|
|
127
|
+
top: number;
|
|
128
|
+
width: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Keyboard drag: where the dragged card goes when the user presses ← or →.
|
|
132
|
+
* Picks the nearest lane to the left/right of the card's current center and
|
|
133
|
+
* returns the top-left coordinates that center the card in that lane, just
|
|
134
|
+
* under its header. Undefined when there is no lane further in that direction.
|
|
135
|
+
* Pure — exported for unit tests.
|
|
136
|
+
*/
|
|
137
|
+
export declare function nextLaneCoordinates(direction: 'left' | 'right', current: {
|
|
138
|
+
left: number;
|
|
139
|
+
top: number;
|
|
140
|
+
width: number;
|
|
141
|
+
}, lanes: LaneRect[]): {
|
|
142
|
+
x: number;
|
|
143
|
+
y: number;
|
|
144
|
+
} | undefined;
|
|
73
145
|
/**
|
|
74
146
|
* Whether a card passes a lane funnel. Picked select/facet `values` match by
|
|
75
147
|
* equality (IN — the card's field value must be one of them); a free-text
|
|
@@ -142,5 +214,10 @@ export interface DynamicKanbanProps {
|
|
|
142
214
|
*/
|
|
143
215
|
defaultFilters?: Record<string, any>;
|
|
144
216
|
}
|
|
145
|
-
|
|
217
|
+
/**
|
|
218
|
+
* The optimistic card move runs on TanStack Query (useOptimisticMutation). A
|
|
219
|
+
* host that mounts no QueryClientProvider still gets a working board: the
|
|
220
|
+
* kanban brings its own client in that case.
|
|
221
|
+
*/
|
|
222
|
+
export declare function DynamicKanban(props: DynamicKanbanProps): React.JSX.Element;
|
|
146
223
|
//# sourceMappingURL=dynamic-kanban.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"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"}
|