@asteby/metacore-runtime-react 27.2.0 → 27.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 27.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - ccfb7b0: Empty state del Tablero: el mockup animado ahora es full-bleed, se mueve más y
8
+ va sin texto. Antes se percibía como una ilustración centrada casi estática con
9
+ un caption en inglés. Ahora los tiles skeleton llenan todo el área del
10
+ dashboard en una grilla 4×4 y se reacomodan de forma visible —pares que se
11
+ intercambian de lugar (horizontal, vertical y diagonal) con translate suave,
12
+ escalonados para que siempre haya 2-3 piezas en movimiento— como si el tablero
13
+ se estuviera armando solo. Se eliminó el caption ("Your dashboard is taking
14
+ shape"): la animación habla sola y así no se envía copy sin localizar. Se
15
+ mantiene el loop lento (~13s), tokens de tema y `prefers-reduced-motion: reduce`
16
+ (congela todo). El mock sigue decorativo (`aria-hidden`).
17
+
18
+ ## 27.3.0
19
+
20
+ ### Minor Changes
21
+
22
+ - 8b46e55: El empty state del Tablero ahora muestra un mockup animado en vez de un ícono
23
+ estático. Cuando no hay widgets (o ninguno visible tras el gating de permisos),
24
+ `DashboardGrid` pinta una silueta del propio dashboard —tiles skeleton (un
25
+ gráfico grande, un par de stat cards, una barra de progreso y una lista)— que
26
+ se desplazan y reacomodan suavemente entre sí, como piezas encajando en su
27
+ lugar. El mensaje pasa de "no hay nada" a "acá va a vivir tu tablero".
28
+
29
+ Detalles: animación CSS pura (un loop lento de ~11s, translate+scale sutil, sin
30
+ dependencias nuevas), tokens de tema (`bg-muted`) para light/dark automáticos,
31
+ `prefers-reduced-motion: reduce` congela todo, y el mock es decorativo
32
+ (`aria-hidden`). Se exporta el componente `DashboardEmptyMockup` por si un host
33
+ quiere reutilizarlo. Copy por defecto del empty ajustado al nuevo framing
34
+ (override vía `strings`).
35
+
3
36
  ## 27.2.0
4
37
 
5
38
  ### Minor Changes
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Full-bleed animated skeleton of a dashboard whose tiles slide and swap places,
4
+ * as if the layout were assembling itself. Purely decorative — always
5
+ * `aria-hidden`, no text.
6
+ */
7
+ export declare function DashboardEmptyMockup({ className }: {
8
+ className?: string;
9
+ }): React.JSX.Element;
10
+ //# sourceMappingURL=dashboard-empty-mockup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-empty-mockup.d.ts","sourceRoot":"","sources":["../src/dashboard-empty-mockup.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2I9B;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBAuBzE"}
@@ -0,0 +1,136 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // DashboardEmptyMockup — the animated empty state for the modular dashboard.
3
+ //
4
+ // Instead of a static "nothing here" card, we paint a silhouette of the
5
+ // dashboard itself and let it BUILD ITSELF: skeleton tiles (a big chart, stat
6
+ // cards, a bar, lists) that live in a full-bleed grid and visibly slide past
7
+ // each other, swapping places like pieces reorganizing into a layout. The
8
+ // metaphor is "your board is assembling", not "empty".
9
+ //
10
+ // Design constraints (kept simple so it ships from a package):
11
+ // - Full-bleed: fills the whole dashboard area (100% w/h), NOT a centered
12
+ // illustration. A responsive grid so it reads like the real dashboard.
13
+ // - Pure CSS keyframes, no dependencies. One slow loop (~13s). Motion is
14
+ // PERCEPTIBLE — tiles translate a real distance and swap in pairs — but
15
+ // never opacity-strobing, and eased so it feels like settling.
16
+ // - Theme tokens only (bg-muted / border tokens) → light & dark for free.
17
+ // - `prefers-reduced-motion: reduce` freezes everything (tiles rest in place).
18
+ // - No caption text — the animation carries the meaning, and shipping copy
19
+ // from the package risks un-localized strings. The whole mock is
20
+ // decorative → aria-hidden.
21
+ //
22
+ // Keyframes ship inline in a <style> tag rather than as Tailwind utilities:
23
+ // consumer apps scan only their OWN source for Tailwind classes, so arbitrary
24
+ // animation utilities declared here would never be generated in their build.
25
+ // Static tokens (bg-muted, rounded-lg…) are standard classes the host emits
26
+ // anyway, so those stay as className.
27
+ import * as React from 'react';
28
+ import { cn } from '@asteby/metacore-ui/lib';
29
+ // Scoped, collision-proof keyframe + class names (prefixed, unlikely to clash).
30
+ const STYLE_ID = 'mc-dashboard-empty-mockup-style';
31
+ // Each tile lives in a grid cell and animates on a shared ~13s loop. Pairs move
32
+ // in opposite directions at the same phase so it reads as a SWAP, and the phases
33
+ // are staggered (via negative delays) so 2-3 tiles are always in motion at
34
+ // different moments of the cycle — never a frozen frame.
35
+ const MOCKUP_CSS = `
36
+ .mc-demock{--mc-demock-dur:13s}
37
+ .mc-demock-tile{will-change:transform;transform-origin:center;
38
+ animation-duration:var(--mc-demock-dur);animation-timing-function:cubic-bezier(.65,0,.35,1);
39
+ animation-iteration-count:infinite}
40
+ /* Horizontal swap pair (col A <-> col B) */
41
+ .mc-demock-swapL{animation-name:mc-demock-swap-left}
42
+ .mc-demock-swapR{animation-name:mc-demock-swap-right;animation-delay:-.2s}
43
+ /* Vertical swap pair */
44
+ .mc-demock-swapU{animation-name:mc-demock-swap-up;animation-delay:-4.3s}
45
+ .mc-demock-swapD{animation-name:mc-demock-swap-down;animation-delay:-4.5s}
46
+ /* Diagonal reshuffle pair */
47
+ .mc-demock-shuffleA{animation-name:mc-demock-shuffle-a;animation-delay:-8.1s}
48
+ .mc-demock-shuffleB{animation-name:mc-demock-shuffle-b;animation-delay:-8.3s}
49
+ /* Gentle drifters filling the rhythm between swaps */
50
+ .mc-demock-driftA{animation-name:mc-demock-drift-a;animation-delay:-2.4s}
51
+ .mc-demock-driftB{animation-name:mc-demock-drift-b;animation-delay:-6.7s}
52
+ .mc-demock-shimmer{position:relative;overflow:hidden}
53
+ .mc-demock-shimmer::after{content:"";position:absolute;inset:0;
54
+ background:linear-gradient(105deg,transparent 35%,currentColor 50%,transparent 65%);
55
+ opacity:.05;transform:translateX(-120%);
56
+ animation:mc-demock-sheen var(--mc-demock-dur) ease-in-out infinite}
57
+ /* Swaps: hold home -> travel a full cell (+gap) to the partner's slot -> hold
58
+ -> travel back. ~108% of own size clears the tile plus the grid gap. */
59
+ @keyframes mc-demock-swap-left{
60
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(108%,0)}88%,100%{transform:translate(0,0)}}
61
+ @keyframes mc-demock-swap-right{
62
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(-108%,0)}88%,100%{transform:translate(0,0)}}
63
+ @keyframes mc-demock-swap-up{
64
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(0,112%)}88%,100%{transform:translate(0,0)}}
65
+ @keyframes mc-demock-swap-down{
66
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(0,-112%)}88%,100%{transform:translate(0,0)}}
67
+ @keyframes mc-demock-shuffle-a{
68
+ 0%,15%{transform:translate(0,0) scale(1)}45%,60%{transform:translate(106%,110%) scale(.96)}90%,100%{transform:translate(0,0) scale(1)}}
69
+ @keyframes mc-demock-shuffle-b{
70
+ 0%,15%{transform:translate(0,0) scale(1)}45%,60%{transform:translate(-106%,-110%) scale(1.04)}90%,100%{transform:translate(0,0) scale(1)}}
71
+ @keyframes mc-demock-drift-a{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(4%,-5%) scale(1.02)}}
72
+ @keyframes mc-demock-drift-b{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-5%,4%) scale(.98)}}
73
+ @keyframes mc-demock-sheen{0%,100%{transform:translateX(-120%)}55%,72%{transform:translateX(120%)}}
74
+ @media (prefers-reduced-motion:reduce){
75
+ .mc-demock-tile{animation:none!important}
76
+ .mc-demock-shimmer::after{animation:none!important;opacity:0}
77
+ }
78
+ `;
79
+ /** Injects the keyframes once per document (idempotent, SSR-safe). */
80
+ function useMockupStyles() {
81
+ React.useInsertionEffect(() => {
82
+ if (typeof document === 'undefined')
83
+ return;
84
+ if (document.getElementById(STYLE_ID))
85
+ return;
86
+ const el = document.createElement('style');
87
+ el.id = STYLE_ID;
88
+ el.textContent = MOCKUP_CSS;
89
+ document.head.appendChild(el);
90
+ }, []);
91
+ }
92
+ const tileBase = 'rounded-lg bg-muted mc-demock-tile mc-demock-shimmer text-foreground overflow-hidden';
93
+ /** A skeleton "chart" tile: a row of bars. */
94
+ function ChartGlyph() {
95
+ return (_jsx("div", { className: "flex h-full items-end gap-1.5 p-3", children: [6, 10, 7, 12, 9, 11, 8].map((h, i) => (_jsx("div", { className: "w-full rounded-sm bg-foreground/10", style: { height: `${h * 8}%` } }, i))) }));
96
+ }
97
+ /** A skeleton "stat card": label + big number. */
98
+ function StatGlyph() {
99
+ return (_jsxs("div", { className: "flex h-full flex-col justify-center gap-2 p-3", children: [_jsx("div", { className: "h-2 w-1/2 rounded-full bg-foreground/15" }), _jsx("div", { className: "h-4 w-2/3 rounded bg-foreground/15" })] }));
100
+ }
101
+ /** A skeleton "list" tile: stacked rows. */
102
+ function ListGlyph() {
103
+ return (_jsxs("div", { className: "flex h-full flex-col justify-center gap-2 p-3", children: [_jsx("div", { className: "h-2 w-full rounded-full bg-foreground/12" }), _jsx("div", { className: "h-2 w-4/5 rounded-full bg-foreground/12" }), _jsx("div", { className: "h-2 w-2/3 rounded-full bg-foreground/12" })] }));
104
+ }
105
+ /** A skeleton "progress bar" tile. */
106
+ function BarGlyph() {
107
+ return (_jsx("div", { className: "flex h-full items-center px-3", children: _jsx("div", { className: "h-2.5 w-full rounded-full bg-foreground/10", children: _jsx("div", { className: "h-full w-2/5 rounded-full bg-foreground/20" }) }) }));
108
+ }
109
+ const TILES = [
110
+ // Big chart (top-left 2x2) — diagonal shuffle with the bottom stat.
111
+ { area: { gridColumn: '1 / 3', gridRow: '1 / 3' }, motion: 'mc-demock-shuffleA', glyph: _jsx(ChartGlyph, {}) },
112
+ // Horizontal swap pair, top-right.
113
+ { area: { gridColumn: '3 / 4', gridRow: '1 / 2' }, motion: 'mc-demock-swapL', glyph: _jsx(StatGlyph, {}) },
114
+ { area: { gridColumn: '4 / 5', gridRow: '1 / 2' }, motion: 'mc-demock-swapR', glyph: _jsx(StatGlyph, {}) },
115
+ // Vertical swap pair, right column.
116
+ { area: { gridColumn: '3 / 5', gridRow: '2 / 3' }, motion: 'mc-demock-swapU', glyph: _jsx(ListGlyph, {}) },
117
+ { area: { gridColumn: '3 / 5', gridRow: '3 / 4' }, motion: 'mc-demock-swapD', glyph: _jsx(BarGlyph, {}) },
118
+ // Bottom-left cluster: shuffle partner + drifter.
119
+ { area: { gridColumn: '1 / 2', gridRow: '3 / 4' }, motion: 'mc-demock-shuffleB', glyph: _jsx(StatGlyph, {}) },
120
+ { area: { gridColumn: '2 / 3', gridRow: '3 / 4' }, motion: 'mc-demock-driftA', glyph: _jsx(StatGlyph, {}) },
121
+ // Full-width footer bar + trailing stat.
122
+ { area: { gridColumn: '1 / 4', gridRow: '4 / 5' }, motion: 'mc-demock-driftB', glyph: _jsx(BarGlyph, {}) },
123
+ { area: { gridColumn: '4 / 5', gridRow: '4 / 5' }, motion: 'mc-demock-driftA', glyph: _jsx(StatGlyph, {}) },
124
+ ];
125
+ /**
126
+ * Full-bleed animated skeleton of a dashboard whose tiles slide and swap places,
127
+ * as if the layout were assembling itself. Purely decorative — always
128
+ * `aria-hidden`, no text.
129
+ */
130
+ export function DashboardEmptyMockup({ className }) {
131
+ useMockupStyles();
132
+ return (_jsx("div", { "aria-hidden": "true", "data-testid": "dashboard-empty-mockup", className: cn('mc-demock pointer-events-none h-full w-full select-none', className), children: _jsx("div", { className: "grid h-full w-full gap-3", style: {
133
+ gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
134
+ gridTemplateRows: 'repeat(4, minmax(0, 1fr))',
135
+ }, children: TILES.map((t, i) => (_jsx("div", { style: t.area, className: cn(tileBase, t.motion), children: t.glyph }, i))) }) }));
136
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-grid.d.ts","sourceRoot":"","sources":["../src/dashboard-grid.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAK9B,OAAO,KAAK,EACR,kBAAkB,EAElB,oBAAoB,EACpB,mBAAmB,EACtB,MAAM,mBAAmB,CAAA;AAW1B,uEAAuE;AACvE,wBAAgB,eAAe,CAC3B,MAAM,CAAC,EAAE,oBAAoB,EAAE,EAC/B,OAAO,CAAC,EAAE,mBAAmB,EAAE,GAChC,oBAAoB,EAAE,CAgBxB;AASD,wBAAgB,aAAa,CAAC,EAC1B,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,SAAS,EACT,OAAO,GACV,EAAE,kBAAkB,qBAiJpB"}
1
+ {"version":3,"file":"dashboard-grid.d.ts","sourceRoot":"","sources":["../src/dashboard-grid.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EACR,kBAAkB,EAElB,oBAAoB,EACpB,mBAAmB,EACtB,MAAM,mBAAmB,CAAA;AAY1B,uEAAuE;AACvE,wBAAgB,eAAe,CAC3B,MAAM,CAAC,EAAE,oBAAoB,EAAE,EAC/B,OAAO,CAAC,EAAE,mBAAmB,EAAE,GAChC,oBAAoB,EAAE,CAgBxB;AASD,wBAAgB,aAAa,CAAC,EAC1B,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,MAAM,EACN,QAAQ,EACR,SAAS,EACT,OAAO,GACV,EAAE,kBAAkB,qBA4IpB"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // DashboardGrid — the modular dashboard surface. Renders the union of
3
3
  // declarative + federated widgets in a responsive 4-column grid, grouped with
4
4
  // headings, honouring per-widget size, permission gating (useCan), batch data
@@ -8,11 +8,11 @@ import * as React from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import { cn } from '@asteby/metacore-ui/lib';
10
10
  import { useCan, usePermissionsActive } from './permissions-context';
11
- import { DynamicIcon } from './dynamic-icon';
12
11
  import { WidgetRenderer, WidgetSkeleton, isTallWidget } from './widgets/widget-renderer';
12
+ import { DashboardEmptyMockup } from './dashboard-empty-mockup';
13
13
  const DEFAULT_STRINGS = {
14
- emptyTitle: 'Your dashboard is empty',
15
- emptyDescription: 'Install an addon with dashboard widgets to start seeing metrics here.',
14
+ emptyTitle: 'Your dashboard is taking shape',
15
+ emptyDescription: 'Install an addon with dashboard widgets and your metrics will start living here.',
16
16
  widgetError: 'Could not load this widget.',
17
17
  widgetEmpty: 'No data yet.',
18
18
  };
@@ -120,7 +120,11 @@ export function DashboardGrid({ groups, widgets, loadData, isAdmin, locale, curr
120
120
  }, [visibleGroups]);
121
121
  // Global empty state (no widgets at all / none visible after gating).
122
122
  if (visibleGroups.length === 0) {
123
- return (_jsxs("div", { "data-testid": "dashboard-empty", className: cn('flex min-h-[40vh] flex-col items-center justify-center rounded-xl border border-dashed border-border/60 p-10 text-center', className), children: [_jsx("div", { className: "mb-4 flex size-14 items-center justify-center rounded-2xl bg-muted text-muted-foreground", children: _jsx(DynamicIcon, { name: "LayoutDashboard", className: "size-7" }) }), _jsx("h3", { className: "text-base font-semibold text-foreground", children: tr(undefined, s.emptyTitle) || s.emptyTitle }), _jsx("p", { className: "mt-1 max-w-sm text-sm text-muted-foreground", children: s.emptyDescription })] }));
123
+ return (_jsx("div", { "data-testid": "dashboard-empty", className: cn(
124
+ // Full-bleed: the mockup fills the whole dashboard area, not a
125
+ // centered illustration. No caption — the animation speaks for
126
+ // itself (and dodges shipping un-localized copy).
127
+ 'min-h-[60vh] w-full rounded-xl border border-dashed border-border/60 p-4', className), children: _jsx(DashboardEmptyMockup, { className: "h-full min-h-[inherit]" }) }));
124
128
  }
125
129
  return (_jsx("div", { "data-testid": "dashboard-grid", className: cn(
126
130
  // Masonry: balanced CSS columns. Cards take their natural height
package/dist/index.d.ts CHANGED
@@ -58,6 +58,7 @@ export { ActivityDiff, type ActivityEvent, type ActivityDiffProps, } from './act
58
58
  export { RecordHistory, type RecordHistoryProps, } from './record-history';
59
59
  export { ActivityTimeline, type ActivityTimelineProps, } from './activity-timeline';
60
60
  export { DashboardGrid, normalizeGroups, } from './dashboard-grid';
61
+ export { DashboardEmptyMockup } from './dashboard-empty-mockup';
61
62
  export type { WidgetKind, WidgetSize, WidgetFormat, WidgetAccent, WidgetAggregate, WidgetWhereOp, DashboardWidgetQuery, DashboardWidgetCompare, DashboardWidgetSpec, WidgetSeriesPoint, WidgetData, DashboardWidgetGroup, LoadWidgetData, DashboardGridProps, DashboardGridStrings, } from './dashboard-types';
62
63
  export { StatWidget, BarWidget, LineWidget, AreaWidget, PieWidget, DonutWidget, ListWidget, ProgressWidget, type WidgetRenderProps, } from './widgets/renderers';
63
64
  export { WidgetRenderer, WidgetSkeleton, SIZE_SPAN, SIZE_CLASS, type WidgetRendererProps, } from './widgets/widget-renderer';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -60,6 +60,7 @@ export { ActivityDiff, } from './activity-diff';
60
60
  export { RecordHistory, } from './record-history';
61
61
  export { ActivityTimeline, } from './activity-timeline';
62
62
  export { DashboardGrid, normalizeGroups, } from './dashboard-grid';
63
+ export { DashboardEmptyMockup } from './dashboard-empty-mockup';
63
64
  export { StatWidget, BarWidget, LineWidget, AreaWidget, PieWidget, DonutWidget, ListWidget, ProgressWidget, } from './widgets/renderers';
64
65
  export { WidgetRenderer, WidgetSkeleton, SIZE_SPAN, SIZE_CLASS, } from './widgets/widget-renderer';
65
66
  export { WidgetCard, DeltaChip, WidgetEmpty, WidgetError, } from './widgets/widget-card';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "27.2.0",
3
+ "version": "27.3.1",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -156,6 +156,19 @@ describe('DashboardGrid render', () => {
156
156
  expect(screen.getByTestId('dashboard-empty')).toBeTruthy()
157
157
  })
158
158
 
159
+ it('renders the animated mockup (decorative) in the empty state', () => {
160
+ render(<DashboardGrid widgets={[]} loadData={loaderOf({})} />)
161
+ const mock = screen.getByTestId('dashboard-empty-mockup')
162
+ expect(mock).toBeTruthy()
163
+ // Purely decorative → hidden from the a11y tree.
164
+ expect(mock.getAttribute('aria-hidden')).toBe('true')
165
+ // Keyframes are injected once into the document head.
166
+ expect(document.getElementById('mc-dashboard-empty-mockup-style')).toBeTruthy()
167
+ // No caption text — the animation carries the meaning (and avoids
168
+ // shipping un-localized copy from the package).
169
+ expect(screen.queryByText(/dashboard/i)).toBeNull()
170
+ })
171
+
159
172
  it('survives an empty → populated transition (React #310 regression)', async () => {
160
173
  // The flatten/order useMemo must run BEFORE the empty-state early return.
161
174
  // When it sat after the return, an empty render called one fewer hook
@@ -0,0 +1,194 @@
1
+ // DashboardEmptyMockup — the animated empty state for the modular dashboard.
2
+ //
3
+ // Instead of a static "nothing here" card, we paint a silhouette of the
4
+ // dashboard itself and let it BUILD ITSELF: skeleton tiles (a big chart, stat
5
+ // cards, a bar, lists) that live in a full-bleed grid and visibly slide past
6
+ // each other, swapping places like pieces reorganizing into a layout. The
7
+ // metaphor is "your board is assembling", not "empty".
8
+ //
9
+ // Design constraints (kept simple so it ships from a package):
10
+ // - Full-bleed: fills the whole dashboard area (100% w/h), NOT a centered
11
+ // illustration. A responsive grid so it reads like the real dashboard.
12
+ // - Pure CSS keyframes, no dependencies. One slow loop (~13s). Motion is
13
+ // PERCEPTIBLE — tiles translate a real distance and swap in pairs — but
14
+ // never opacity-strobing, and eased so it feels like settling.
15
+ // - Theme tokens only (bg-muted / border tokens) → light & dark for free.
16
+ // - `prefers-reduced-motion: reduce` freezes everything (tiles rest in place).
17
+ // - No caption text — the animation carries the meaning, and shipping copy
18
+ // from the package risks un-localized strings. The whole mock is
19
+ // decorative → aria-hidden.
20
+ //
21
+ // Keyframes ship inline in a <style> tag rather than as Tailwind utilities:
22
+ // consumer apps scan only their OWN source for Tailwind classes, so arbitrary
23
+ // animation utilities declared here would never be generated in their build.
24
+ // Static tokens (bg-muted, rounded-lg…) are standard classes the host emits
25
+ // anyway, so those stay as className.
26
+
27
+ import * as React from 'react'
28
+ import { cn } from '@asteby/metacore-ui/lib'
29
+
30
+ // Scoped, collision-proof keyframe + class names (prefixed, unlikely to clash).
31
+ const STYLE_ID = 'mc-dashboard-empty-mockup-style'
32
+
33
+ // Each tile lives in a grid cell and animates on a shared ~13s loop. Pairs move
34
+ // in opposite directions at the same phase so it reads as a SWAP, and the phases
35
+ // are staggered (via negative delays) so 2-3 tiles are always in motion at
36
+ // different moments of the cycle — never a frozen frame.
37
+ const MOCKUP_CSS = `
38
+ .mc-demock{--mc-demock-dur:13s}
39
+ .mc-demock-tile{will-change:transform;transform-origin:center;
40
+ animation-duration:var(--mc-demock-dur);animation-timing-function:cubic-bezier(.65,0,.35,1);
41
+ animation-iteration-count:infinite}
42
+ /* Horizontal swap pair (col A <-> col B) */
43
+ .mc-demock-swapL{animation-name:mc-demock-swap-left}
44
+ .mc-demock-swapR{animation-name:mc-demock-swap-right;animation-delay:-.2s}
45
+ /* Vertical swap pair */
46
+ .mc-demock-swapU{animation-name:mc-demock-swap-up;animation-delay:-4.3s}
47
+ .mc-demock-swapD{animation-name:mc-demock-swap-down;animation-delay:-4.5s}
48
+ /* Diagonal reshuffle pair */
49
+ .mc-demock-shuffleA{animation-name:mc-demock-shuffle-a;animation-delay:-8.1s}
50
+ .mc-demock-shuffleB{animation-name:mc-demock-shuffle-b;animation-delay:-8.3s}
51
+ /* Gentle drifters filling the rhythm between swaps */
52
+ .mc-demock-driftA{animation-name:mc-demock-drift-a;animation-delay:-2.4s}
53
+ .mc-demock-driftB{animation-name:mc-demock-drift-b;animation-delay:-6.7s}
54
+ .mc-demock-shimmer{position:relative;overflow:hidden}
55
+ .mc-demock-shimmer::after{content:"";position:absolute;inset:0;
56
+ background:linear-gradient(105deg,transparent 35%,currentColor 50%,transparent 65%);
57
+ opacity:.05;transform:translateX(-120%);
58
+ animation:mc-demock-sheen var(--mc-demock-dur) ease-in-out infinite}
59
+ /* Swaps: hold home -> travel a full cell (+gap) to the partner's slot -> hold
60
+ -> travel back. ~108% of own size clears the tile plus the grid gap. */
61
+ @keyframes mc-demock-swap-left{
62
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(108%,0)}88%,100%{transform:translate(0,0)}}
63
+ @keyframes mc-demock-swap-right{
64
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(-108%,0)}88%,100%{transform:translate(0,0)}}
65
+ @keyframes mc-demock-swap-up{
66
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(0,112%)}88%,100%{transform:translate(0,0)}}
67
+ @keyframes mc-demock-swap-down{
68
+ 0%,12%{transform:translate(0,0)}38%,62%{transform:translate(0,-112%)}88%,100%{transform:translate(0,0)}}
69
+ @keyframes mc-demock-shuffle-a{
70
+ 0%,15%{transform:translate(0,0) scale(1)}45%,60%{transform:translate(106%,110%) scale(.96)}90%,100%{transform:translate(0,0) scale(1)}}
71
+ @keyframes mc-demock-shuffle-b{
72
+ 0%,15%{transform:translate(0,0) scale(1)}45%,60%{transform:translate(-106%,-110%) scale(1.04)}90%,100%{transform:translate(0,0) scale(1)}}
73
+ @keyframes mc-demock-drift-a{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(4%,-5%) scale(1.02)}}
74
+ @keyframes mc-demock-drift-b{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(-5%,4%) scale(.98)}}
75
+ @keyframes mc-demock-sheen{0%,100%{transform:translateX(-120%)}55%,72%{transform:translateX(120%)}}
76
+ @media (prefers-reduced-motion:reduce){
77
+ .mc-demock-tile{animation:none!important}
78
+ .mc-demock-shimmer::after{animation:none!important;opacity:0}
79
+ }
80
+ `
81
+
82
+ /** Injects the keyframes once per document (idempotent, SSR-safe). */
83
+ function useMockupStyles() {
84
+ React.useInsertionEffect(() => {
85
+ if (typeof document === 'undefined') return
86
+ if (document.getElementById(STYLE_ID)) return
87
+ const el = document.createElement('style')
88
+ el.id = STYLE_ID
89
+ el.textContent = MOCKUP_CSS
90
+ document.head.appendChild(el)
91
+ }, [])
92
+ }
93
+
94
+ const tileBase =
95
+ 'rounded-lg bg-muted mc-demock-tile mc-demock-shimmer text-foreground overflow-hidden'
96
+
97
+ /** A skeleton "chart" tile: a row of bars. */
98
+ function ChartGlyph() {
99
+ return (
100
+ <div className="flex h-full items-end gap-1.5 p-3">
101
+ {[6, 10, 7, 12, 9, 11, 8].map((h, i) => (
102
+ <div
103
+ key={i}
104
+ className="w-full rounded-sm bg-foreground/10"
105
+ style={{ height: `${h * 8}%` }}
106
+ />
107
+ ))}
108
+ </div>
109
+ )
110
+ }
111
+
112
+ /** A skeleton "stat card": label + big number. */
113
+ function StatGlyph() {
114
+ return (
115
+ <div className="flex h-full flex-col justify-center gap-2 p-3">
116
+ <div className="h-2 w-1/2 rounded-full bg-foreground/15" />
117
+ <div className="h-4 w-2/3 rounded bg-foreground/15" />
118
+ </div>
119
+ )
120
+ }
121
+
122
+ /** A skeleton "list" tile: stacked rows. */
123
+ function ListGlyph() {
124
+ return (
125
+ <div className="flex h-full flex-col justify-center gap-2 p-3">
126
+ <div className="h-2 w-full rounded-full bg-foreground/12" />
127
+ <div className="h-2 w-4/5 rounded-full bg-foreground/12" />
128
+ <div className="h-2 w-2/3 rounded-full bg-foreground/12" />
129
+ </div>
130
+ )
131
+ }
132
+
133
+ /** A skeleton "progress bar" tile. */
134
+ function BarGlyph() {
135
+ return (
136
+ <div className="flex h-full items-center px-3">
137
+ <div className="h-2.5 w-full rounded-full bg-foreground/10">
138
+ <div className="h-full w-2/5 rounded-full bg-foreground/20" />
139
+ </div>
140
+ </div>
141
+ )
142
+ }
143
+
144
+ // The board: a 4-col x 4-row grid that fills the container. Each tile declares
145
+ // its cell (via inline gridColumn/gridRow) and a motion class. Swap pairs sit in
146
+ // adjacent cells and move toward each other, so the eye reads a reshuffle.
147
+ type Tile = { area: React.CSSProperties; motion: string; glyph: React.ReactNode }
148
+
149
+ const TILES: Tile[] = [
150
+ // Big chart (top-left 2x2) — diagonal shuffle with the bottom stat.
151
+ { area: { gridColumn: '1 / 3', gridRow: '1 / 3' }, motion: 'mc-demock-shuffleA', glyph: <ChartGlyph /> },
152
+ // Horizontal swap pair, top-right.
153
+ { area: { gridColumn: '3 / 4', gridRow: '1 / 2' }, motion: 'mc-demock-swapL', glyph: <StatGlyph /> },
154
+ { area: { gridColumn: '4 / 5', gridRow: '1 / 2' }, motion: 'mc-demock-swapR', glyph: <StatGlyph /> },
155
+ // Vertical swap pair, right column.
156
+ { area: { gridColumn: '3 / 5', gridRow: '2 / 3' }, motion: 'mc-demock-swapU', glyph: <ListGlyph /> },
157
+ { area: { gridColumn: '3 / 5', gridRow: '3 / 4' }, motion: 'mc-demock-swapD', glyph: <BarGlyph /> },
158
+ // Bottom-left cluster: shuffle partner + drifter.
159
+ { area: { gridColumn: '1 / 2', gridRow: '3 / 4' }, motion: 'mc-demock-shuffleB', glyph: <StatGlyph /> },
160
+ { area: { gridColumn: '2 / 3', gridRow: '3 / 4' }, motion: 'mc-demock-driftA', glyph: <StatGlyph /> },
161
+ // Full-width footer bar + trailing stat.
162
+ { area: { gridColumn: '1 / 4', gridRow: '4 / 5' }, motion: 'mc-demock-driftB', glyph: <BarGlyph /> },
163
+ { area: { gridColumn: '4 / 5', gridRow: '4 / 5' }, motion: 'mc-demock-driftA', glyph: <StatGlyph /> },
164
+ ]
165
+
166
+ /**
167
+ * Full-bleed animated skeleton of a dashboard whose tiles slide and swap places,
168
+ * as if the layout were assembling itself. Purely decorative — always
169
+ * `aria-hidden`, no text.
170
+ */
171
+ export function DashboardEmptyMockup({ className }: { className?: string }) {
172
+ useMockupStyles()
173
+ return (
174
+ <div
175
+ aria-hidden="true"
176
+ data-testid="dashboard-empty-mockup"
177
+ className={cn('mc-demock pointer-events-none h-full w-full select-none', className)}
178
+ >
179
+ <div
180
+ className="grid h-full w-full gap-3"
181
+ style={{
182
+ gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
183
+ gridTemplateRows: 'repeat(4, minmax(0, 1fr))',
184
+ }}
185
+ >
186
+ {TILES.map((t, i) => (
187
+ <div key={i} style={t.area} className={cn(tileBase, t.motion)}>
188
+ {t.glyph}
189
+ </div>
190
+ ))}
191
+ </div>
192
+ </div>
193
+ )
194
+ }
@@ -8,7 +8,6 @@ import * as React from 'react'
8
8
  import { useTranslation } from 'react-i18next'
9
9
  import { cn } from '@asteby/metacore-ui/lib'
10
10
  import { useCan, usePermissionsActive } from './permissions-context'
11
- import { DynamicIcon } from './dynamic-icon'
12
11
  import type {
13
12
  DashboardGridProps,
14
13
  DashboardGridStrings,
@@ -16,11 +15,12 @@ import type {
16
15
  DashboardWidgetSpec,
17
16
  } from './dashboard-types'
18
17
  import { WidgetRenderer, WidgetSkeleton, isTallWidget } from './widgets/widget-renderer'
18
+ import { DashboardEmptyMockup } from './dashboard-empty-mockup'
19
19
 
20
20
  const DEFAULT_STRINGS: DashboardGridStrings = {
21
- emptyTitle: 'Your dashboard is empty',
21
+ emptyTitle: 'Your dashboard is taking shape',
22
22
  emptyDescription:
23
- 'Install an addon with dashboard widgets to start seeing metrics here.',
23
+ 'Install an addon with dashboard widgets and your metrics will start living here.',
24
24
  widgetError: 'Could not load this widget.',
25
25
  widgetEmpty: 'No data yet.',
26
26
  }
@@ -154,19 +154,14 @@ export function DashboardGrid({
154
154
  <div
155
155
  data-testid="dashboard-empty"
156
156
  className={cn(
157
- 'flex min-h-[40vh] flex-col items-center justify-center rounded-xl border border-dashed border-border/60 p-10 text-center',
157
+ // Full-bleed: the mockup fills the whole dashboard area, not a
158
+ // centered illustration. No caption — the animation speaks for
159
+ // itself (and dodges shipping un-localized copy).
160
+ 'min-h-[60vh] w-full rounded-xl border border-dashed border-border/60 p-4',
158
161
  className,
159
162
  )}
160
163
  >
161
- <div className="mb-4 flex size-14 items-center justify-center rounded-2xl bg-muted text-muted-foreground">
162
- <DynamicIcon name="LayoutDashboard" className="size-7" />
163
- </div>
164
- <h3 className="text-base font-semibold text-foreground">
165
- {tr(undefined, s.emptyTitle) || s.emptyTitle}
166
- </h3>
167
- <p className="mt-1 max-w-sm text-sm text-muted-foreground">
168
- {s.emptyDescription}
169
- </p>
164
+ <DashboardEmptyMockup className="h-full min-h-[inherit]" />
170
165
  </div>
171
166
  )
172
167
  }
package/src/index.ts CHANGED
@@ -325,6 +325,7 @@ export {
325
325
  DashboardGrid,
326
326
  normalizeGroups,
327
327
  } from './dashboard-grid'
328
+ export { DashboardEmptyMockup } from './dashboard-empty-mockup'
328
329
  export type {
329
330
  WidgetKind,
330
331
  WidgetSize,