@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 +33 -0
- package/dist/dashboard-empty-mockup.d.ts +10 -0
- package/dist/dashboard-empty-mockup.d.ts.map +1 -0
- package/dist/dashboard-empty-mockup.js +136 -0
- package/dist/dashboard-grid.d.ts.map +1 -1
- package/dist/dashboard-grid.js +9 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/__tests__/dashboard-grid.test.tsx +13 -0
- package/src/dashboard-empty-mockup.tsx +194 -0
- package/src/dashboard-grid.tsx +8 -13
- package/src/index.ts +1 -0
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;
|
|
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"}
|
package/dist/dashboard-grid.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
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
|
|
15
|
-
emptyDescription: 'Install an addon with dashboard widgets
|
|
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 (
|
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
@@ -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
|
+
}
|
package/src/dashboard-grid.tsx
CHANGED
|
@@ -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
|
|
21
|
+
emptyTitle: 'Your dashboard is taking shape',
|
|
22
22
|
emptyDescription:
|
|
23
|
-
'Install an addon with dashboard widgets
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
}
|