@asteby/metacore-runtime-react 18.13.2 → 18.13.3

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 18.13.3
4
+
5
+ ### Patch Changes
6
+
7
+ - b45b5b1: ActivityDiff: created/deleted events render as a true two-column grid (Campo + Valor) — the old layout emitted a placeholder cell plus a col-span-2 value into a 3-column grid, overflowing the row so the value wrapped below its label. RecordHistory gains `moduleLabel` so the event-header badge can show the localized model title (e.g. "Clientes") instead of the raw addon_key.
8
+
3
9
  ## 18.13.2
4
10
 
5
11
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"activity-diff.d.ts","sourceRoot":"","sources":["../src/activity-diff.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAO/C;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI,CAAA;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,iBAAiB;IAC9B,oCAAoC;IACpC,KAAK,EAAE,aAAa,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AAuGD;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAmJpD,CAAA"}
1
+ {"version":3,"file":"activity-diff.d.ts","sourceRoot":"","sources":["../src/activity-diff.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAO/C;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,IAAI,CAAA;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,iBAAiB;IAC9B,oCAAoC;IACpC,KAAK,EAAE,aAAa,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AAuGD;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA4KpD,CAAA"}
@@ -137,7 +137,7 @@ export const ActivityDiff = ({ event, columns, timeZone, currency, locale = 'es'
137
137
  if (allKeys.length === 0 && !event.summary) {
138
138
  return (_jsx("div", { className: cn('text-sm text-muted-foreground italic py-1', className), children: "Sin campos registrados." }));
139
139
  }
140
- return (_jsxs("div", { className: cn('space-y-2', className), children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Badge, { variant: "outline", className: cn('text-xs font-medium px-2 py-0.5', variantBadge.className), children: variantBadge.label || event.action }), changed.size > 0 && variant === 'updated' && (_jsxs("span", { className: "text-xs text-muted-foreground", children: [changed.size, " campo", changed.size !== 1 ? 's' : '', " modificado", changed.size !== 1 ? 's' : ''] })), allKeys.length > 0 && variant === 'updated' && (_jsx("button", { type: "button", onClick: () => setShowOnlyChanged((v) => !v), className: "ml-auto text-xs text-primary hover:underline", children: showOnlyChanged ? `Ver todos (${allKeys.length})` : 'Solo cambios' }))] }), event.summary && (_jsx("p", { className: "text-sm text-muted-foreground italic", children: event.summary })), displayedKeys.length > 0 && (_jsxs("div", { className: "rounded-lg border border-border/60 overflow-hidden text-sm", children: [_jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [_jsx("span", { children: "Campo" }), !isCreated && _jsx("span", { children: isDeleted ? 'Valor' : 'Antes' }), isCreated && _jsx("span", {}), !isDeleted && _jsx("span", { children: isCreated ? 'Valor' : 'Después' }), isDeleted && _jsx("span", {})] }), displayedKeys.map((key, idx) => {
140
+ return (_jsxs("div", { className: cn('space-y-2', className), children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx(Badge, { variant: "outline", className: cn('text-xs font-medium px-2 py-0.5', variantBadge.className), children: variantBadge.label || event.action }), changed.size > 0 && variant === 'updated' && (_jsxs("span", { className: "text-xs text-muted-foreground", children: [changed.size, " campo", changed.size !== 1 ? 's' : '', " modificado", changed.size !== 1 ? 's' : ''] })), allKeys.length > 0 && variant === 'updated' && (_jsx("button", { type: "button", onClick: () => setShowOnlyChanged((v) => !v), className: "ml-auto text-xs text-primary hover:underline", children: showOnlyChanged ? `Ver todos (${allKeys.length})` : 'Solo cambios' }))] }), event.summary && (_jsx("p", { className: "text-sm text-muted-foreground italic", children: event.summary })), displayedKeys.length > 0 && (_jsxs("div", { className: "rounded-lg border border-border/60 overflow-hidden text-sm", children: [isCreated || isDeleted ? (_jsxs("div", { className: "grid grid-cols-[1fr_2fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground gap-x-2", children: [_jsx("span", { children: "Campo" }), _jsx("span", { children: isDeleted ? 'Valor anterior' : 'Valor' })] })) : (_jsxs("div", { className: "grid grid-cols-[1fr_1fr_1fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground gap-x-2", children: [_jsx("span", { children: "Campo" }), _jsx("span", { children: "Antes" }), _jsx("span", { children: "Despu\u00E9s" })] })), displayedKeys.map((key, idx) => {
141
141
  const col = resolveColumn(key, columns);
142
142
  const label = resolveLabel(key, columns);
143
143
  const isChanged = changed.has(key);
@@ -155,9 +155,12 @@ export const ActivityDiff = ({ event, columns, timeZone, currency, locale = 'es'
155
155
  ? ROW_STYLE.created
156
156
  : isDeleted
157
157
  ? ROW_STYLE.deleted
158
- : isChanged
159
- ? {}
160
- : {};
161
- return (_jsxs("div", { style: rowStyle, className: cn('grid grid-cols-[1fr_1fr_1fr] items-start px-3 py-2 gap-x-2', idx !== displayedKeys.length - 1 && 'border-b border-border/30', isChanged && variant === 'updated' && 'bg-yellow-50/40 dark:bg-yellow-950/10'), children: [_jsx("span", { className: "text-xs font-medium text-foreground/70 pt-0.5 truncate", title: label, children: label }), !isCreated ? (_jsx("span", { className: cn(isDeleted ? 'col-span-2' : ''), children: _jsx(ActivityValueRenderer, { value: isDeleted ? fromVal : fromVal, col: col, timeZone: timeZone, currency: currency, locale: locale }) })) : (_jsx("span", {})), !isDeleted ? (_jsxs("span", { className: cn(isCreated ? 'col-span-2' : ''), children: [isChanged && variant === 'updated' && (_jsx("span", { className: "inline-flex items-center gap-1 align-middle mr-1", children: _jsx(ArrowRight, { className: "h-3 w-3 text-muted-foreground/50 shrink-0" }) })), _jsx(ActivityValueRenderer, { value: isCreated ? toVal : toVal, col: col, timeZone: timeZone, currency: currency, locale: locale })] })) : (_jsx("span", {}))] }, key));
158
+ : {};
159
+ // Single-snapshot row: label + one value cell, aligned
160
+ // with the two-column header above.
161
+ if (isCreated || isDeleted) {
162
+ return (_jsxs("div", { style: rowStyle, className: cn('grid grid-cols-[1fr_2fr] items-start px-3 py-2 gap-x-2', idx !== displayedKeys.length - 1 && 'border-b border-border/30'), children: [_jsx("span", { className: "text-xs font-medium text-foreground/70 pt-0.5 truncate", title: label, children: label }), _jsx("span", { className: "min-w-0", children: _jsx(ActivityValueRenderer, { value: isDeleted ? fromVal : toVal, col: col, timeZone: timeZone, currency: currency, locale: locale }) })] }, key));
163
+ }
164
+ return (_jsxs("div", { className: cn('grid grid-cols-[1fr_1fr_1fr] items-start px-3 py-2 gap-x-2', idx !== displayedKeys.length - 1 && 'border-b border-border/30', isChanged && variant === 'updated' && 'bg-yellow-50/40 dark:bg-yellow-950/10'), children: [_jsx("span", { className: "text-xs font-medium text-foreground/70 pt-0.5 truncate", title: label, children: label }), _jsx("span", { className: "min-w-0", children: _jsx(ActivityValueRenderer, { value: fromVal, col: col, timeZone: timeZone, currency: currency, locale: locale }) }), _jsxs("span", { className: "min-w-0", children: [isChanged && variant === 'updated' && (_jsx("span", { className: "inline-flex items-center gap-1 align-middle mr-1", children: _jsx(ArrowRight, { className: "h-3 w-3 text-muted-foreground/50 shrink-0" }) })), _jsx(ActivityValueRenderer, { value: toVal, col: col, timeZone: timeZone, currency: currency, locale: locale })] })] }, key));
162
165
  })] }))] }));
163
166
  };
@@ -43,6 +43,11 @@ export interface RecordHistoryProps {
43
43
  * fine for absolute same-origin paths.
44
44
  */
45
45
  resolveAvatarUrl?: (path: string) => string;
46
+ /**
47
+ * Localized label for the badge on each event header (e.g. "Clientes").
48
+ * Falls back to the event's raw `addon_key` when omitted.
49
+ */
50
+ moduleLabel?: string;
46
51
  }
47
52
  /**
48
53
  * Shows the full activity history of a single record as a vertical timeline.
@@ -1 +1 @@
1
- {"version":3,"file":"record-history.d.ts","sourceRoot":"","sources":["../src/record-history.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAOpD,MAAM,WAAW,kBAAkB;IAC/B;;;OAGG;IACH,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAC9C;AAoCD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqLtD,CAAA"}
1
+ {"version":3,"file":"record-history.d.ts","sourceRoot":"","sources":["../src/record-history.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAOpD,MAAM,WAAW,kBAAkB;IAC/B;;;OAGG;IACH,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IAC3C;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAoCD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsLtD,CAAA"}
@@ -51,7 +51,7 @@ function actionDotColor(action) {
51
51
  * Each event is collapsible — the header shows actor + time; expanding reveals
52
52
  * the <ActivityDiff> with field-level changes.
53
53
  */
54
- export const RecordHistory = ({ events, columns, timeZone, currency, locale = 'es', className, onOpenEvent, resolveAvatarUrl, }) => {
54
+ export const RecordHistory = ({ events, columns, timeZone, currency, locale = 'es', className, onOpenEvent, resolveAvatarUrl, moduleLabel, }) => {
55
55
  const dateLocale = locale === 'en' ? enUS : es;
56
56
  // Sort: most recent first
57
57
  const sorted = React.useMemo(() => [...events].sort((a, b) => new Date(b.occurred_at).getTime() - new Date(a.occurred_at).getTime()), [events]);
@@ -94,7 +94,7 @@ export const RecordHistory = ({ events, columns, timeZone, currency, locale = 'e
94
94
  return event.occurred_at;
95
95
  }
96
96
  })();
97
- return (_jsx(Collapsible, { open: isOpen, onOpenChange: () => toggle(event.id), children: _jsxs("div", { className: "relative", children: [_jsx("span", { className: "absolute -left-5 top-3.5 h-2.5 w-2.5 rounded-full border-2 border-background -translate-x-[4px]", style: { background: dotColor }, "aria-hidden": "true" }), _jsxs("div", { className: "rounded-lg border border-border/60 bg-card overflow-hidden", children: [_jsx(CollapsibleTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "w-full flex items-center gap-3 px-4 py-3 text-left hover:bg-muted/30 transition-colors", children: [_jsxs(Avatar, { className: "h-7 w-7 rounded-full shrink-0", children: [event.actor_avatar ? (_jsx(AvatarImage, { src: resolveAvatarUrl ? resolveAvatarUrl(event.actor_avatar) : event.actor_avatar, alt: actor })) : null, _jsx(AvatarFallback, { className: "text-[9px] font-bold bg-primary/10 text-primary", children: getInitials(actor) })] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("span", { className: "text-sm font-semibold text-foreground truncate", children: actor }), _jsx("span", { className: "text-sm text-muted-foreground", children: actionLabel(event.action) })] }), _jsxs("div", { className: "flex items-center gap-1.5 mt-0.5", children: [_jsx(Clock, { className: "h-3 w-3 text-muted-foreground/60 shrink-0" }), _jsx("span", { className: "text-xs text-muted-foreground", title: fullDate, children: timeAgo }), event.addon_key && (_jsx(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0 h-4 ml-1", children: event.addon_key }))] })] }), onOpenEvent && (_jsx("span", { role: "button", tabIndex: 0, "aria-label": "Ver en registro de actividad", title: "Ver en registro de actividad", className: "shrink-0 rounded-md p-1.5 text-muted-foreground hover:text-foreground hover:bg-muted/60 transition-colors cursor-pointer", onClick: (e) => {
97
+ return (_jsx(Collapsible, { open: isOpen, onOpenChange: () => toggle(event.id), children: _jsxs("div", { className: "relative", children: [_jsx("span", { className: "absolute -left-5 top-3.5 h-2.5 w-2.5 rounded-full border-2 border-background -translate-x-[4px]", style: { background: dotColor }, "aria-hidden": "true" }), _jsxs("div", { className: "rounded-lg border border-border/60 bg-card overflow-hidden", children: [_jsx(CollapsibleTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: "w-full flex items-center gap-3 px-4 py-3 text-left hover:bg-muted/30 transition-colors", children: [_jsxs(Avatar, { className: "h-7 w-7 rounded-full shrink-0", children: [event.actor_avatar ? (_jsx(AvatarImage, { src: resolveAvatarUrl ? resolveAvatarUrl(event.actor_avatar) : event.actor_avatar, alt: actor })) : null, _jsx(AvatarFallback, { className: "text-[9px] font-bold bg-primary/10 text-primary", children: getInitials(actor) })] }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsx("span", { className: "text-sm font-semibold text-foreground truncate", children: actor }), _jsx("span", { className: "text-sm text-muted-foreground", children: actionLabel(event.action) })] }), _jsxs("div", { className: "flex items-center gap-1.5 mt-0.5", children: [_jsx(Clock, { className: "h-3 w-3 text-muted-foreground/60 shrink-0" }), _jsx("span", { className: "text-xs text-muted-foreground", title: fullDate, children: timeAgo }), (moduleLabel || event.addon_key) && (_jsx(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0 h-4 ml-1", children: moduleLabel || event.addon_key }))] })] }), onOpenEvent && (_jsx("span", { role: "button", tabIndex: 0, "aria-label": "Ver en registro de actividad", title: "Ver en registro de actividad", className: "shrink-0 rounded-md p-1.5 text-muted-foreground hover:text-foreground hover:bg-muted/60 transition-colors cursor-pointer", onClick: (e) => {
98
98
  e.stopPropagation();
99
99
  onOpenEvent(event);
100
100
  }, onKeyDown: (e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "18.13.2",
3
+ "version": "18.13.3",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,8 +61,8 @@
61
61
  "typescript": "^6.0.0",
62
62
  "vitest": "^4.0.0",
63
63
  "zustand": "^5.0.0",
64
- "@asteby/metacore-sdk": "3.2.0",
65
- "@asteby/metacore-ui": "2.5.1"
64
+ "@asteby/metacore-ui": "2.5.1",
65
+ "@asteby/metacore-sdk": "3.2.0"
66
66
  },
67
67
  "scripts": {
68
68
  "build": "tsc -p tsconfig.json",
@@ -233,17 +233,25 @@ export const ActivityDiff: React.FC<ActivityDiffProps> = ({
233
233
  <p className="text-sm text-muted-foreground italic">{event.summary}</p>
234
234
  )}
235
235
 
236
- {/* Diff table */}
236
+ {/* Diff table. Created/deleted events carry a single snapshot — no
237
+ before/after pair — so they collapse to two columns (Campo +
238
+ Valor); a third placeholder column would force the value cell
239
+ to wrap onto its own row. Updated keeps Campo/Antes/Después. */}
237
240
  {displayedKeys.length > 0 && (
238
241
  <div className="rounded-lg border border-border/60 overflow-hidden text-sm">
239
242
  {/* Column headers */}
240
- <div className="grid grid-cols-[1fr_1fr_1fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground">
241
- <span>Campo</span>
242
- {!isCreated && <span>{isDeleted ? 'Valor' : 'Antes'}</span>}
243
- {isCreated && <span></span>}
244
- {!isDeleted && <span>{isCreated ? 'Valor' : 'Después'}</span>}
245
- {isDeleted && <span></span>}
246
- </div>
243
+ {isCreated || isDeleted ? (
244
+ <div className="grid grid-cols-[1fr_2fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground gap-x-2">
245
+ <span>Campo</span>
246
+ <span>{isDeleted ? 'Valor anterior' : 'Valor'}</span>
247
+ </div>
248
+ ) : (
249
+ <div className="grid grid-cols-[1fr_1fr_1fr] border-b border-border/40 bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground gap-x-2">
250
+ <span>Campo</span>
251
+ <span>Antes</span>
252
+ <span>Después</span>
253
+ </div>
254
+ )}
247
255
 
248
256
  {displayedKeys.map((key, idx) => {
249
257
  const col = resolveColumn(key, columns)
@@ -265,14 +273,39 @@ export const ActivityDiff: React.FC<ActivityDiffProps> = ({
265
273
  ? ROW_STYLE.created
266
274
  : isDeleted
267
275
  ? ROW_STYLE.deleted
268
- : isChanged
269
- ? {}
270
- : {}
276
+ : {}
277
+
278
+ // Single-snapshot row: label + one value cell, aligned
279
+ // with the two-column header above.
280
+ if (isCreated || isDeleted) {
281
+ return (
282
+ <div
283
+ key={key}
284
+ style={rowStyle}
285
+ className={cn(
286
+ 'grid grid-cols-[1fr_2fr] items-start px-3 py-2 gap-x-2',
287
+ idx !== displayedKeys.length - 1 && 'border-b border-border/30',
288
+ )}
289
+ >
290
+ <span className="text-xs font-medium text-foreground/70 pt-0.5 truncate" title={label}>
291
+ {label}
292
+ </span>
293
+ <span className="min-w-0">
294
+ <ActivityValueRenderer
295
+ value={isDeleted ? fromVal : toVal}
296
+ col={col}
297
+ timeZone={timeZone}
298
+ currency={currency}
299
+ locale={locale}
300
+ />
301
+ </span>
302
+ </div>
303
+ )
304
+ }
271
305
 
272
306
  return (
273
307
  <div
274
308
  key={key}
275
- style={rowStyle}
276
309
  className={cn(
277
310
  'grid grid-cols-[1fr_1fr_1fr] items-start px-3 py-2 gap-x-2',
278
311
  idx !== displayedKeys.length - 1 && 'border-b border-border/30',
@@ -284,40 +317,32 @@ export const ActivityDiff: React.FC<ActivityDiffProps> = ({
284
317
  {label}
285
318
  </span>
286
319
 
287
- {/* Before value (or value for deleted/created) */}
288
- {!isCreated ? (
289
- <span className={cn(isDeleted ? 'col-span-2' : '')}>
290
- <ActivityValueRenderer
291
- value={isDeleted ? fromVal : fromVal}
292
- col={col}
293
- timeZone={timeZone}
294
- currency={currency}
295
- locale={locale}
296
- />
297
- </span>
298
- ) : (
299
- <span />
300
- )}
320
+ {/* Before value */}
321
+ <span className="min-w-0">
322
+ <ActivityValueRenderer
323
+ value={fromVal}
324
+ col={col}
325
+ timeZone={timeZone}
326
+ currency={currency}
327
+ locale={locale}
328
+ />
329
+ </span>
301
330
 
302
331
  {/* After value */}
303
- {!isDeleted ? (
304
- <span className={cn(isCreated ? 'col-span-2' : '')}>
305
- {isChanged && variant === 'updated' && (
306
- <span className="inline-flex items-center gap-1 align-middle mr-1">
307
- <ArrowRight className="h-3 w-3 text-muted-foreground/50 shrink-0" />
308
- </span>
309
- )}
310
- <ActivityValueRenderer
311
- value={isCreated ? toVal : toVal}
312
- col={col}
313
- timeZone={timeZone}
314
- currency={currency}
315
- locale={locale}
316
- />
317
- </span>
318
- ) : (
319
- <span />
320
- )}
332
+ <span className="min-w-0">
333
+ {isChanged && variant === 'updated' && (
334
+ <span className="inline-flex items-center gap-1 align-middle mr-1">
335
+ <ArrowRight className="h-3 w-3 text-muted-foreground/50 shrink-0" />
336
+ </span>
337
+ )}
338
+ <ActivityValueRenderer
339
+ value={toVal}
340
+ col={col}
341
+ timeZone={timeZone}
342
+ currency={currency}
343
+ locale={locale}
344
+ />
345
+ </span>
321
346
  </div>
322
347
  )
323
348
  })}
@@ -64,6 +64,11 @@ export interface RecordHistoryProps {
64
64
  * fine for absolute same-origin paths.
65
65
  */
66
66
  resolveAvatarUrl?: (path: string) => string
67
+ /**
68
+ * Localized label for the badge on each event header (e.g. "Clientes").
69
+ * Falls back to the event's raw `addon_key` when omitted.
70
+ */
71
+ moduleLabel?: string
67
72
  }
68
73
 
69
74
  // ---------------------------------------------------------------------------
@@ -114,6 +119,7 @@ export const RecordHistory: React.FC<RecordHistoryProps> = ({
114
119
  className,
115
120
  onOpenEvent,
116
121
  resolveAvatarUrl,
122
+ moduleLabel,
117
123
  }) => {
118
124
  const dateLocale = locale === 'en' ? enUS : es
119
125
 
@@ -223,9 +229,9 @@ export const RecordHistory: React.FC<RecordHistoryProps> = ({
223
229
  <span className="text-xs text-muted-foreground" title={fullDate}>
224
230
  {timeAgo}
225
231
  </span>
226
- {event.addon_key && (
232
+ {(moduleLabel || event.addon_key) && (
227
233
  <Badge variant="outline" className="text-[10px] px-1.5 py-0 h-4 ml-1">
228
- {event.addon_key}
234
+ {moduleLabel || event.addon_key}
229
235
  </Badge>
230
236
  )}
231
237
  </div>