@nadicodeai/ui 12.1.115 → 12.1.117
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/dist/components/chart-bar-stacked.d.ts +2 -2
- package/dist/components/chart-bar-stacked.d.ts.map +1 -1
- package/dist/components/chart-bar-stacked.js +4 -6
- package/dist/components/chart-card.d.ts +10 -6
- package/dist/components/chart-card.d.ts.map +1 -1
- package/dist/components/chart-card.js +12 -12
- package/dist/components/chart-ranking.d.ts +35 -0
- package/dist/components/chart-ranking.d.ts.map +1 -0
- package/dist/components/chart-ranking.js +27 -0
- package/dist/components/collection-page.d.ts +3 -1
- package/dist/components/collection-page.d.ts.map +1 -1
- package/dist/components/collection-page.js +3 -3
- package/dist/components/resizable.d.ts +1 -1
- package/dist/components/resizable.js +1 -1
- package/dist/eslint/index.js +2 -0
- package/dist/eslint/rules/disabled-control-appearance.js +75 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/internal/assistant-ui/markdown-text.js +1 -1
- package/dist/showcase/specimens/charts.d.ts +1 -0
- package/dist/showcase/specimens/charts.d.ts.map +1 -1
- package/dist/showcase/specimens/charts.js +10 -0
- package/dist/showcase/specimens/feedback.d.ts +0 -2
- package/dist/showcase/specimens/feedback.d.ts.map +1 -1
- package/dist/showcase/specimens/feedback.js +0 -6
- package/dist/showcase/specimens/index.d.ts +1 -2
- package/dist/showcase/specimens/index.d.ts.map +1 -1
- package/dist/showcase/specimens/navigation.d.ts +0 -1
- package/dist/showcase/specimens/navigation.d.ts.map +1 -1
- package/dist/showcase/specimens/navigation.js +0 -2
- package/dist/showcase/usage.generated.d.ts +1 -1
- package/dist/showcase/usage.generated.d.ts.map +1 -1
- package/dist/showcase/usage.generated.js +15 -26
- package/package.json +13 -10
- package/dist/components/desktop-shell.d.ts +0 -45
- package/dist/components/desktop-shell.d.ts.map +0 -1
- package/dist/components/desktop-shell.js +0 -23
- package/dist/components/picture-label.d.ts +0 -30
- package/dist/components/picture-label.d.ts.map +0 -1
- package/dist/components/picture-label.js +0 -26
|
@@ -5,11 +5,11 @@ import { type ChartCardProps } from "./chart-card.js";
|
|
|
5
5
|
* @family Charts
|
|
6
6
|
* @when How a total moved over time split by Customer, member account or model; with `share`, what part of one total each holds, with no time axis.
|
|
7
7
|
* @instead For a continuous volume in three series or fewer use `ChartAreaStacked`. Two measures side by side use `ChartBarMultiple`. Exact lookup is a table.
|
|
8
|
-
* @behaviour Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.
|
|
8
|
+
* @behaviour Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The summary variant has square bars and no dot legend: its adjacent ChartRanking identifies the series with share bars. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.
|
|
9
9
|
* @words Entity names as the reader knows them, never ids. The neutral remainder is "Everything else". Values through the page's shared money formatter.
|
|
10
10
|
* @access The plot is an image named by the card title; the tooltip and legend are read with it. The share bar sits above the full-width table that carries each figure.
|
|
11
11
|
*/
|
|
12
|
-
declare function ChartBarStacked({ title, period, controls, link, summary, aside, footer, headingLevel, data, xKey, series, entityColorMap, valueFormatter, axisFormatter, otherLabel, emptyState, size, share, className, }: ChartCardProps & {
|
|
12
|
+
declare function ChartBarStacked({ variant, title, period, controls, link, summary, aside, footer, headingLevel, data, xKey, series, entityColorMap, valueFormatter, axisFormatter, otherLabel, emptyState, size, share, className, }: ChartCardProps & {
|
|
13
13
|
/**
|
|
14
14
|
* One bar across the card, each entity a segment of 100%: the share of a
|
|
15
15
|
* total with no time axis. `data` is then a single row keyed by series id.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-bar-stacked.d.ts","sourceRoot":"","sources":["../../src/components/chart-bar-stacked.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"chart-bar-stacked.d.ts","sourceRoot":"","sources":["../../src/components/chart-bar-stacked.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAiBjC;;;;;;;;;GASG;AACH,iBAAS,eAAe,CAAC,EACvB,OAAmB,EACnB,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,OAAO,EACP,KAAK,EACL,MAAM,EACN,YAAY,EACZ,IAAI,EACJ,IAAI,EACJ,MAAM,EACN,cAAc,EACd,cAAsC,EACtC,aAAa,EACb,UAAU,EACV,UAAU,EACV,IAAgB,EAChB,KAAa,EACb,SAAS,GACV,EAAE,cAAc,GAAG;IAClB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,+BA4GA;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -7,7 +7,6 @@ import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartToo
|
|
|
7
7
|
import { CHART_X_AXIS_TICKS, CHART_Y_AXIS_TICK_COUNT, niceAxisTicks, stackedAxisMax, } from "./chart-axis.js";
|
|
8
8
|
import { CHART_LEGEND_CLASS, ChartCard, chartPlotClassName, chartSeriesConfig, defaultValueFormatter, foldOtherSeries, } from "./chart-card.js";
|
|
9
9
|
import { entityColor } from "./chart-entity-colors.js";
|
|
10
|
-
/** Stock stacked-bar corner radius: the bottom bar rounds down, the top bar up. */
|
|
11
10
|
function stackRadius(index, count) {
|
|
12
11
|
if (count === 1)
|
|
13
12
|
return [4, 4, 4, 4];
|
|
@@ -17,7 +16,6 @@ function stackRadius(index, count) {
|
|
|
17
16
|
return [4, 4, 0, 0];
|
|
18
17
|
return [0, 0, 0, 0];
|
|
19
18
|
}
|
|
20
|
-
/** The same stock rounding, turned on its side: the first segment rounds left, the last right. */
|
|
21
19
|
function shareRadius(index, count) {
|
|
22
20
|
if (count === 1)
|
|
23
21
|
return [4, 4, 4, 4];
|
|
@@ -33,19 +31,19 @@ function shareRadius(index, count) {
|
|
|
33
31
|
* @family Charts
|
|
34
32
|
* @when How a total moved over time split by Customer, member account or model; with `share`, what part of one total each holds, with no time axis.
|
|
35
33
|
* @instead For a continuous volume in three series or fewer use `ChartAreaStacked`. Two measures side by side use `ChartBarMultiple`. Exact lookup is a table.
|
|
36
|
-
* @behaviour Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.
|
|
34
|
+
* @behaviour Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The summary variant has square bars and no dot legend: its adjacent ChartRanking identifies the series with share bars. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.
|
|
37
35
|
* @words Entity names as the reader knows them, never ids. The neutral remainder is "Everything else". Values through the page's shared money formatter.
|
|
38
36
|
* @access The plot is an image named by the card title; the tooltip and legend are read with it. The share bar sits above the full-width table that carries each figure.
|
|
39
37
|
*/
|
|
40
|
-
function ChartBarStacked({ title, period, controls, link, summary, aside, footer, headingLevel, data, xKey, series, entityColorMap, valueFormatter = defaultValueFormatter, axisFormatter, otherLabel, emptyState, size = "default", share = false, className, }) {
|
|
38
|
+
function ChartBarStacked({ variant = "default", title, period, controls, link, summary, aside, footer, headingLevel, data, xKey, series, entityColorMap, valueFormatter = defaultValueFormatter, axisFormatter, otherLabel, emptyState, size = "default", share = false, className, }) {
|
|
41
39
|
const folded = foldOtherSeries(series, data, entityColorMap, otherLabel);
|
|
42
40
|
const chartConfig = chartSeriesConfig(folded.series, entityColorMap);
|
|
43
41
|
const domainMax = stackedAxisMax(folded.data, folded.series.map((entry) => entry.id));
|
|
44
|
-
return (_jsx(ChartCard, { title: title, period: period, controls: controls, ...(link ? { link } : {}), summary: summary, aside: aside, ...(footer ? { footer } : {}), ...(headingLevel ? { headingLevel } : {}), className: className, children: (titleId) => emptyState && data.length === 0 ? (emptyState) : share ? (_jsx(ChartContainer, { config: chartConfig, className: "aspect-auto h-16 w-full", children: _jsxs(BarChart, { accessibilityLayer: true, "aria-labelledby": titleId, data: folded.data, layout: "vertical", stackOffset: "expand", children: [_jsx(XAxis, { type: "number", hide: true }), _jsx(YAxis, { type: "category", dataKey: xKey, hide: true }), _jsx(ChartTooltip, { cursor: false, content: _jsx(ChartTooltipContent, { hideLabel: true, indicator: "line", valueFormatter: valueFormatter }) }), _jsx(ChartLegend, { itemSorter: null, content: _jsx(ChartLegendContent, { className: CHART_LEGEND_CLASS }) }), folded.series.map((entry, index) => (_jsx(Bar, { dataKey: entry.id, stackId: "a", fill: entityColor(entityColorMap, entry.id), radius: shareRadius(index, folded.series.length) }, entry.id)))] }) })) : (_jsx(ChartContainer, { config: chartConfig, className: chartPlotClassName(size), children: _jsxs(BarChart, { accessibilityLayer: true, "aria-labelledby": titleId, data: folded.data, children: [_jsx(CartesianGrid, { strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: xKey, tickLine: false, tickMargin: 10, axisLine: false, ...CHART_X_AXIS_TICKS }), _jsx(YAxis, { width: "auto", tickLine: false, axisLine: false, tickMargin: 8, tickCount: CHART_Y_AXIS_TICK_COUNT, ...(domainMax === undefined
|
|
42
|
+
return (_jsx(ChartCard, { variant: variant, title: title, period: period, controls: controls, ...(link ? { link } : {}), summary: summary, aside: aside, ...(footer ? { footer } : {}), ...(headingLevel ? { headingLevel } : {}), className: className, children: (titleId) => emptyState && data.length === 0 ? (emptyState) : share ? (_jsx(ChartContainer, { config: chartConfig, className: "aspect-auto h-16 w-full", children: _jsxs(BarChart, { accessibilityLayer: true, "aria-labelledby": titleId, data: folded.data, layout: "vertical", stackOffset: "expand", children: [_jsx(XAxis, { type: "number", hide: true }), _jsx(YAxis, { type: "category", dataKey: xKey, hide: true }), _jsx(ChartTooltip, { cursor: false, content: _jsx(ChartTooltipContent, { hideLabel: true, indicator: "line", valueFormatter: valueFormatter }) }), variant === "summary" ? null : (_jsx(ChartLegend, { itemSorter: null, content: _jsx(ChartLegendContent, { className: CHART_LEGEND_CLASS }) })), folded.series.map((entry, index) => (_jsx(Bar, { dataKey: entry.id, stackId: "a", fill: entityColor(entityColorMap, entry.id), radius: shareRadius(index, folded.series.length) }, entry.id)))] }) })) : (_jsx(ChartContainer, { config: chartConfig, className: chartPlotClassName(size), children: _jsxs(BarChart, { accessibilityLayer: true, "aria-labelledby": titleId, data: folded.data, children: [_jsx(CartesianGrid, { strokeDasharray: "3 3" }), _jsx(XAxis, { dataKey: xKey, tickLine: false, tickMargin: 10, axisLine: false, ...CHART_X_AXIS_TICKS }), _jsx(YAxis, { width: "auto", tickLine: false, axisLine: false, tickMargin: 8, tickCount: CHART_Y_AXIS_TICK_COUNT, ...(domainMax === undefined
|
|
45
43
|
? {}
|
|
46
44
|
: {
|
|
47
45
|
domain: [0, domainMax],
|
|
48
46
|
ticks: niceAxisTicks(domainMax),
|
|
49
|
-
}), tickFormatter: (value) => (axisFormatter ?? valueFormatter)(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { indicator: "line", valueFormatter: valueFormatter }) }), _jsx(ChartLegend, { itemSorter: null, content: _jsx(ChartLegendContent, { className: CHART_LEGEND_CLASS }) }), folded.series.map((entry, index) => (_jsx(Bar, { dataKey: entry.id, stackId: "a", fill: entityColor(entityColorMap, entry.id), radius: stackRadius(index, folded.series.length), maxBarSize: 48 }, entry.id)))] }) })) }));
|
|
47
|
+
}), tickFormatter: (value) => (axisFormatter ?? valueFormatter)(Number(value)) }), _jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { indicator: "line", valueFormatter: valueFormatter }) }), variant === "summary" ? null : (_jsx(ChartLegend, { itemSorter: null, content: _jsx(ChartLegendContent, { className: CHART_LEGEND_CLASS }) })), folded.series.map((entry, index) => (_jsx(Bar, { dataKey: entry.id, stackId: "a", fill: entityColor(entityColorMap, entry.id), radius: variant === "summary" ? 0 : stackRadius(index, folded.series.length), maxBarSize: 48 }, entry.id)))] }) })) }));
|
|
50
48
|
}
|
|
51
49
|
export { ChartBarStacked };
|
|
@@ -10,6 +10,7 @@ type ChartSeries = {
|
|
|
10
10
|
};
|
|
11
11
|
type ChartDatum = Record<string, number | string>;
|
|
12
12
|
type ChartCardSize = "default" | "lg";
|
|
13
|
+
type ChartCardVariant = "default" | "summary";
|
|
13
14
|
type ChartSummaryTrend = {
|
|
14
15
|
value: React.ReactNode;
|
|
15
16
|
direction: TrendDirection;
|
|
@@ -24,6 +25,7 @@ type ChartSummaryProps = {
|
|
|
24
25
|
valueSize?: ChartCardSize;
|
|
25
26
|
trend?: ChartSummaryTrend;
|
|
26
27
|
status?: React.ReactNode;
|
|
28
|
+
variant?: ChartCardVariant;
|
|
27
29
|
};
|
|
28
30
|
/** The footer strip: when the reading was taken, left; a command on the reading itself, right. */
|
|
29
31
|
type ChartCardFooter = {
|
|
@@ -42,15 +44,17 @@ type ChartCardLink = {
|
|
|
42
44
|
link: React.ReactElement;
|
|
43
45
|
};
|
|
44
46
|
type ChartCardProps = {
|
|
47
|
+
/** Summary places controls beside the title and the total above the plot, alongside its ranking. */
|
|
48
|
+
variant?: ChartCardVariant;
|
|
45
49
|
/** Names the measure and its split: "Model spend by Customer". */
|
|
46
50
|
title: React.ReactNode;
|
|
47
|
-
/**
|
|
51
|
+
/** Bucket or date context under the title by default, beside the total in the summary variant. */
|
|
48
52
|
period?: React.ReactNode;
|
|
49
53
|
/** The title's heading level in the page outline. Defaults to 2. */
|
|
50
54
|
headingLevel?: 2 | 3 | 4;
|
|
51
|
-
/**
|
|
55
|
+
/** Metric and period controls: at the trailing edge by default, immediately after the summary title. */
|
|
52
56
|
controls?: React.ReactNode;
|
|
53
|
-
/**
|
|
57
|
+
/** The way to the reading's owner, at the header's trailing edge. */
|
|
54
58
|
link?: ChartCardLink;
|
|
55
59
|
/** A `ChartSummary` between the header and the plot. */
|
|
56
60
|
summary?: React.ReactNode;
|
|
@@ -97,15 +101,15 @@ declare function foldOtherSeries(series: readonly ChartSeries[], data: readonly
|
|
|
97
101
|
* @family Charts
|
|
98
102
|
* @when Every chart and every reading built around one: the frame a page never builds by hand. A chart is a named section of its page.
|
|
99
103
|
* @instead A single figure is a `KpiCard`, never nested inside a chart. A ranking beside the plot goes in the card's `aside`, not a second card.
|
|
100
|
-
* @behaviour
|
|
104
|
+
* @behaviour The default header puts controls at the trailing edge on wide cards, below the title on narrow cards. The summary variant keeps controls immediately after the title, the owner link at the trailing edge, and the total and period above the plot. The ranking sits beside the plot only when the card itself reaches 48 rem; narrower cards keep a full-width plot and put the ranking below it. Controls wrap on narrow cards. An empty dataset shows its `emptyState` in the plot's place. The footer carries the reading time and at most one command on that reading.
|
|
101
105
|
* @words Title names the measure and its split: "Model spend by Customer". Period as dates. The link: "Explore", or "Open in Analytics" where the owner is another page. Footer: the reading's time, "Updated 4 minutes ago" or "Read at 12:42". Sentence case throughout.
|
|
102
106
|
* @access The title is a heading at the page's level (default 2) and labels the plot. The plot is focusable and shows the 2 px focus outline only on keyboard focus.
|
|
103
107
|
*/
|
|
104
|
-
declare function ChartCard({ title, period, controls, link, summary, aside, footer, headingLevel, className, children, }: Pick<ChartCardProps, "title" | "period" | "controls" | "link" | "summary" | "aside" | "footer" | "headingLevel" | "className"> & {
|
|
108
|
+
declare function ChartCard({ variant, title, period, controls, link, summary, aside, footer, headingLevel, className, children, }: Pick<ChartCardProps, "title" | "variant" | "period" | "controls" | "link" | "summary" | "aside" | "footer" | "headingLevel" | "className"> & {
|
|
105
109
|
/** Receives the title's id, which the plot takes as `aria-labelledby`. */
|
|
106
110
|
children: (titleId: string) => React.ReactNode;
|
|
107
111
|
}): React.JSX.Element;
|
|
108
|
-
declare function ChartSummary({ label, value, valueTitle, valueSize, trend, status, }: ChartSummaryProps): React.JSX.Element;
|
|
112
|
+
declare function ChartSummary({ variant, label, value, valueTitle, valueSize, trend, status, }: ChartSummaryProps): React.JSX.Element;
|
|
109
113
|
/** The plot frame class: fixed height, no aspect ratio, full width. */
|
|
110
114
|
declare function chartPlotClassName(size: ChartCardSize): string;
|
|
111
115
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-card.d.ts","sourceRoot":"","sources":["../../src/components/chart-card.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAa/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAG3F,KAAK,WAAW,GAAG;IACjB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAElD,KAAK,aAAa,GAAG,SAAS,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"chart-card.d.ts","sourceRoot":"","sources":["../../src/components/chart-card.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,17 +9,11 @@ import { CHART_ENTITY_OTHER_COLOR, entityColor, } from "./chart-entity-colors.js
|
|
|
9
9
|
import { PageCommandButton } from "./page-actions.js";
|
|
10
10
|
import { TrendBadge } from "./trend-badge.js";
|
|
11
11
|
import { FooterStrip } from "../internal/footer-strip.js";
|
|
12
|
-
/** Fixed plot heights, so charts on a page share one register. */
|
|
13
12
|
const chartSizes = {
|
|
14
13
|
default: "h-64",
|
|
15
14
|
lg: "h-80",
|
|
16
15
|
};
|
|
17
|
-
/**
|
|
18
|
-
* Below a 28 rem card the controls drop under the title; a lone link stays at the
|
|
19
|
-
* header's trailing edge, as the ranking cards beside it keep theirs.
|
|
20
|
-
*/
|
|
21
16
|
const CONTROLS_UNDER_TITLE_WHEN_NARROW = "has-data-[slot=card-action]:grid-cols-1 [&>[data-slot=card-action]]:col-start-1 [&>[data-slot=card-action]]:row-span-1 [&>[data-slot=card-action]]:row-start-3 [&>[data-slot=card-action]]:justify-self-start @md/chart-card:has-data-[slot=card-action]:grid-cols-[1fr_auto] @md/chart-card:[&>[data-slot=card-action]]:col-start-2 @md/chart-card:[&>[data-slot=card-action]]:row-span-2 @md/chart-card:[&>[data-slot=card-action]]:row-start-1 @md/chart-card:[&>[data-slot=card-action]]:justify-self-end";
|
|
22
|
-
/** Synthetic key for the aggregated neutral series. */
|
|
23
17
|
const OTHER_SERIES_ID = "__nc-other-series__";
|
|
24
18
|
function defaultValueFormatter(value) {
|
|
25
19
|
return value.toLocaleString();
|
|
@@ -69,17 +63,23 @@ function foldOtherSeries(series, data, entityColorMap, otherLabel) {
|
|
|
69
63
|
* @family Charts
|
|
70
64
|
* @when Every chart and every reading built around one: the frame a page never builds by hand. A chart is a named section of its page.
|
|
71
65
|
* @instead A single figure is a `KpiCard`, never nested inside a chart. A ranking beside the plot goes in the card's `aside`, not a second card.
|
|
72
|
-
* @behaviour
|
|
66
|
+
* @behaviour The default header puts controls at the trailing edge on wide cards, below the title on narrow cards. The summary variant keeps controls immediately after the title, the owner link at the trailing edge, and the total and period above the plot. The ranking sits beside the plot only when the card itself reaches 48 rem; narrower cards keep a full-width plot and put the ranking below it. Controls wrap on narrow cards. An empty dataset shows its `emptyState` in the plot's place. The footer carries the reading time and at most one command on that reading.
|
|
73
67
|
* @words Title names the measure and its split: "Model spend by Customer". Period as dates. The link: "Explore", or "Open in Analytics" where the owner is another page. Footer: the reading's time, "Updated 4 minutes ago" or "Read at 12:42". Sentence case throughout.
|
|
74
68
|
* @access The title is a heading at the page's level (default 2) and labels the plot. The plot is focusable and shows the 2 px focus outline only on keyboard focus.
|
|
75
69
|
*/
|
|
76
|
-
function ChartCard({ title, period, controls, link, summary, aside, footer, headingLevel = 2, className, children, }) {
|
|
70
|
+
function ChartCard({ variant = "default", title, period, controls, link, summary, aside, footer, headingLevel = 2, className, children, }) {
|
|
77
71
|
const titleId = React.useId();
|
|
78
|
-
return (_jsxs(Card, { "data-slot": "chart-card", className: cn("@container/chart-card", className), children: [_jsxs(CardHeader, { className: cn(
|
|
79
|
-
|
|
72
|
+
return (_jsxs(Card, { "data-slot": "chart-card", className: cn("@container/chart-card", className), children: [_jsxs(CardHeader, { className: cn(variant === "summary"
|
|
73
|
+
? "flex flex-wrap items-center gap-3"
|
|
74
|
+
: controls && CONTROLS_UNDER_TITLE_WHEN_NARROW), children: [_jsx(CardTitle, { id: titleId, role: "heading", "aria-level": headingLevel, className: variant === "summary" ? "text-heading-xs" : undefined, children: title }), variant === "summary" ? controls : null, period && variant !== "summary" ? _jsx(CardDescription, { children: period }) : null, (variant === "summary" ? link : controls || link) ? (_jsxs(CardAction, { className: cn("flex flex-wrap items-center gap-2", variant === "summary" && "ml-auto"), children: [variant === "summary" ? null : controls, link ? (_jsx(ButtonLink, { variant: "ghost", size: "sm", suffix: _jsx(ChevronRight, { "aria-hidden": "true" }), "aria-label": link.accessibleName, render: link.link, children: link.label })) : null] })) : null] }), summary && variant !== "summary" ? (_jsx("div", { "data-slot": "chart-card-summary", className: "px-(--card-spacing)", children: summary })) : null, _jsxs(CardContent, { className: cn(aside &&
|
|
75
|
+
"grid min-w-0 gap-(--card-spacing) @3xl/chart-card:grid-cols-[minmax(0,2fr)_minmax(16rem,1fr)]"), children: [_jsxs("div", { className: "flex min-w-0 flex-col gap-4", children: [variant === "summary" && (summary || period) ? (_jsxs("div", { "data-slot": "chart-card-summary", className: "flex flex-wrap items-start justify-between gap-3", children: [summary, period ? _jsx(CardDescription, { children: period }) : null] })) : null, children(titleId)] }), aside ? (_jsx("aside", { "data-slot": "chart-card-aside", className: "min-w-0 border-t border-border pt-(--card-spacing) @3xl/chart-card:border-t-0 @3xl/chart-card:border-l @3xl/chart-card:pt-0 @3xl/chart-card:pl-(--card-spacing)", children: aside })) : null] }), footer ? (_jsx(FooterStrip, { hint: footer.reading, hintSlot: "chart-card-reading", children: footer.link ? _jsx(PageCommandButton, { command: footer.link, variant: "ghost" }) : null })) : null] }));
|
|
80
76
|
}
|
|
81
|
-
function ChartSummary({ label, value, valueTitle, valueSize = "default", trend, status, }) {
|
|
82
|
-
return (_jsxs("div", { "data-slot": "chart-summary", className: "flex flex-col items-start gap-2", children: [_jsx("div", { className: "text-muted-foreground text-sm", children: label }), _jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-3", children: [_jsx("div", { "data-slot": "chart-summary-value", className: cn("truncate tabular-nums",
|
|
77
|
+
function ChartSummary({ variant = "default", label, value, valueTitle, valueSize = "default", trend, status, }) {
|
|
78
|
+
return (_jsxs("div", { "data-slot": "chart-summary", className: "flex flex-col items-start gap-2", children: [_jsx("div", { className: cn(variant === "summary" ? "sr-only" : "text-muted-foreground text-sm"), children: label }), _jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-3", children: [_jsx("div", { "data-slot": "chart-summary-value", className: cn("truncate tabular-nums", variant === "summary"
|
|
79
|
+
? "text-display-md"
|
|
80
|
+
: valueSize === "lg"
|
|
81
|
+
? "text-heading-lg"
|
|
82
|
+
: "text-heading-md"), title: valueTitle, children: value }), trend && variant !== "summary" ? (_jsx(TrendBadge, { direction: trend.direction, directionLabel: trend.directionLabel, tone: trend.tone, value: trend.value })) : null, status] }), trend ? (_jsxs("div", { "data-slot": "chart-summary-comparison", className: "flex flex-wrap items-center gap-2 text-muted-foreground text-sm", children: [variant === "summary" ? (_jsx(TrendBadge, { direction: trend.direction, directionLabel: trend.directionLabel, tone: trend.tone, value: trend.value })) : null, trend.comparison] })) : null] }));
|
|
83
83
|
}
|
|
84
84
|
/** The plot frame class: fixed height, no aspect ratio, full width. */
|
|
85
85
|
function chartPlotClassName(size) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type EntityColorMap } from "./chart-entity-colors.js";
|
|
3
|
+
type ChartRankingRow = {
|
|
4
|
+
id: string;
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
display: string;
|
|
7
|
+
exactDisplay?: string;
|
|
8
|
+
value: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The leading entities beside a usage chart, with the complete ranking one step away.
|
|
12
|
+
*
|
|
13
|
+
* @family Charts
|
|
14
|
+
* @when A chart summary needs a ranking beside its plot.
|
|
15
|
+
* @instead Exact breakdown columns belong in a DataTable. This list compares shares of one nonnegative total.
|
|
16
|
+
* @behaviour Shows the first five rows and an optional aggregate remainder, each identity and figure above its coloured share bar. The remainder identifies the neutral plot segment; View all expands the named entities rather than repeating their aggregate. View all opens the complete supplied ranking in a dialog. Rows arrive already sorted and share one total and colour map with the chart.
|
|
17
|
+
* @words The product supplies the title, metric description, View all count, dialog description and close label.
|
|
18
|
+
* @access Each share bar is named by its entity. The dialog is named by the ranking title and retains the selected period and metric.
|
|
19
|
+
*/
|
|
20
|
+
declare function ChartRanking({ title, description, rows, remainder, total, entityColorMap, disclosure, }: {
|
|
21
|
+
title: string;
|
|
22
|
+
description?: ReactNode;
|
|
23
|
+
rows: readonly ChartRankingRow[];
|
|
24
|
+
remainder?: ChartRankingRow;
|
|
25
|
+
total: number;
|
|
26
|
+
entityColorMap: EntityColorMap;
|
|
27
|
+
disclosure: {
|
|
28
|
+
label: string;
|
|
29
|
+
description: string;
|
|
30
|
+
closeLabel: string;
|
|
31
|
+
};
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
|
+
export { ChartRanking };
|
|
34
|
+
export type { ChartRankingRow };
|
|
35
|
+
//# sourceMappingURL=chart-ranking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chart-ranking.d.ts","sourceRoot":"","sources":["../../src/components/chart-ranking.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI9C,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAYpF,KAAK,eAAe,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAsCF;;;;;;;;;GASG;AACH,iBAAS,YAAY,CAAC,EACpB,KAAK,EACL,WAAW,EACX,IAAI,EACJ,SAAS,EACT,KAAK,EACL,cAAc,EACd,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,IAAI,EAAE,SAAS,eAAe,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACxE,+BAuCA;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { Button } from "./button.js";
|
|
6
|
+
import { entityColor } from "./chart-entity-colors.js";
|
|
7
|
+
import { Dialog, DialogBody, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "./dialog.js";
|
|
8
|
+
import { Progress } from "./progress.js";
|
|
9
|
+
function RankingRows({ rows, title, total, entityColorMap, }) {
|
|
10
|
+
const id = useId();
|
|
11
|
+
return (_jsx("ol", { "aria-label": title, className: "flex min-w-0 flex-col gap-4", children: rows.map((row, index) => (_jsxs("li", { className: "flex min-w-0 flex-col gap-2", children: [_jsxs("div", { className: "flex min-w-0 items-center justify-between gap-3 text-sm", children: [_jsx("span", { id: `${id}-${index}`, className: "min-w-0 truncate", children: row.label }), _jsx("span", { className: "shrink-0 tabular-nums", title: row.exactDisplay, children: row.display })] }), _jsx(Progress, { "aria-labelledby": `${id}-${index}`, value: total > 0 ? (row.value / total) * 100 : 0, indicatorColor: entityColor(entityColorMap, row.id), size: "sm" })] }, row.id))) }));
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The leading entities beside a usage chart, with the complete ranking one step away.
|
|
15
|
+
*
|
|
16
|
+
* @family Charts
|
|
17
|
+
* @when A chart summary needs a ranking beside its plot.
|
|
18
|
+
* @instead Exact breakdown columns belong in a DataTable. This list compares shares of one nonnegative total.
|
|
19
|
+
* @behaviour Shows the first five rows and an optional aggregate remainder, each identity and figure above its coloured share bar. The remainder identifies the neutral plot segment; View all expands the named entities rather than repeating their aggregate. View all opens the complete supplied ranking in a dialog. Rows arrive already sorted and share one total and colour map with the chart.
|
|
20
|
+
* @words The product supplies the title, metric description, View all count, dialog description and close label.
|
|
21
|
+
* @access Each share bar is named by its entity. The dialog is named by the ranking title and retains the selected period and metric.
|
|
22
|
+
*/
|
|
23
|
+
function ChartRanking({ title, description, rows, remainder, total, entityColorMap, disclosure, }) {
|
|
24
|
+
const list = { title, total, entityColorMap };
|
|
25
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-col gap-4", children: [_jsxs("div", { className: "flex flex-wrap items-baseline gap-x-2 gap-y-1", children: [_jsx("h3", { className: "text-heading-xs", children: title }), description ? _jsx("span", { className: "text-muted-foreground text-sm", children: description }) : null] }), _jsx(RankingRows, { ...list, rows: remainder ? [...rows.slice(0, 5), remainder] : rows.slice(0, 5) }), rows.length > 0 ? (_jsxs(Dialog, { children: [_jsx(DialogTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm", className: "self-end", suffix: _jsx(ChevronRight, { "aria-hidden": "true" }) }), children: disclosure.label }), _jsxs(DialogContent, { closeLabel: disclosure.closeLabel, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: disclosure.description })] }), _jsx(DialogBody, { children: _jsx(RankingRows, { ...list, rows: rows }) })] })] })) : null] }));
|
|
26
|
+
}
|
|
27
|
+
export { ChartRanking };
|
|
@@ -23,6 +23,8 @@ export type CollectionPageProps<TRecord extends RowData> = RecordListWithout<TRe
|
|
|
23
23
|
actions?: Omit<PageActionsProps, "period">;
|
|
24
24
|
/** The page's sibling collections, under the title row: `TabsNav variant="line"`. */
|
|
25
25
|
tabs?: ReactElement;
|
|
26
|
+
/** Actionable conditions above the toolbar, independent of sibling navigation. */
|
|
27
|
+
attention?: ReactNode;
|
|
26
28
|
search?: CollectionSearchProps;
|
|
27
29
|
filters?: CollectionFiltersProps;
|
|
28
30
|
sort?: CollectionSortProps;
|
|
@@ -47,7 +49,7 @@ export type CollectionPageProps<TRecord extends RowData> = RecordListWithout<TRe
|
|
|
47
49
|
* @when “Use `<Entity>` for a row of descriptive content paired with one or two controls (member rows, integration rows, domain rows).” (https://vercel.com/geist/entity)
|
|
48
50
|
* Ours: a list of entity rows a person finds one of, opens and acts on: Customers, Agents, Skills, Apps, MCP servers, Mailboxes, domains, environment variables (a row with an `editor` expands into its form). Its rows are a `RecordList`'s, so a row has a mark, a name over a muted line and at most three facts; anything wider is not this page.
|
|
49
51
|
* “Projects”: Vercel's Projects page stands a column of titled cards (Usage, Alerts, Recent Previews) at the left of its list. (https://vercel.com/dashboard)
|
|
50
|
-
* Ours:
|
|
52
|
+
* Ours: Customers and Partners use the full-width list, with actionable attention above the toolbar when present. Business summaries belong on Dashboard and Analytics. A rail remains available for context that belongs to the collection itself, such as the selected Library hub.
|
|
51
53
|
* @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
|
|
52
54
|
* Ours: records compared across columns, read by their headings, are a `DataTable` under the page's own title and toolbar. A list inside another page's section is a `RecordList` with its `heading`.
|
|
53
55
|
* @behaviour With a `rail`, the toolbar spans the page and under it stand two columns from 1280 px: the rail, 300 px, then the records' card, its top level with the rail's first title and named by the page's title alone, never a second heading, and the records' rows are `RecordList`'s `line` rows; below 1280 px the records come first and the rail follows them. Each rail card has its title above it at 16 px, an optional 44 px muted summary row with its one outline button at its end (a button never stands in a row of its own, so a card with an `action` has a `summary`), then its items: a figure is one 36 px row, its title and its number at the trailing edge; a record is its 24 px mark, a title over a muted line that wraps to a second before it is cut, and a figure or a status at its end, the whole item opening its record; a card with no items draws its `empty` inside it as one 44 px row like an item. While the rail's read is in flight a card's `items` are undefined and it holds its place with three placeholder lines, so the two columns stand from the first frame; a rail whose read `failed` is one card saying so, and the records beside it stay. Under the title sits only the `description`, when the collection's kind needs explaining; otherwise nothing. The title row holds at most one secondary, the primary, then the three dots, which open only for two commands or more. The primary stays in the title row whether the collection is empty or not, filled, as Vercel's Flags keeps Create Flag; a first use repeats it as the filled button in its card. One toolbar holds the search, which grows, then the filters, then the sort; it shows while there are records or a search or filter is set, and is glass only where the rows scroll under it. While a new search, filter or sort is read, the toolbar is busy and, after a second, shows the one waiting line, while the last rows stay. The rows, their states and their loading are the RecordList's; no match is offered only while a search or filter is set.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collection-page.d.ts","sourceRoot":"","sources":["../../src/components/collection-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC9F,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,4BAA4B,CAAC;AAEvF,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AAEpC,KAAK,eAAe,GAChB;IACE,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,GACD;IAAE,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,OAAO,IAAI,iBAAiB,CAC1E,OAAO,EACP,SAAS,GAAG,SAAS,GAAG,QAAQ,CACjC,GACC,eAAe,GAAG;IAChB,6HAA6H;IAC7H,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC3C,qFAAqF;IACrF,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACnC,iDAAiD;IACjD,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACpD,oGAAoG;IACpG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEJ;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAS,OAAO,EAAE,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,+
|
|
1
|
+
{"version":3,"file":"collection-page.d.ts","sourceRoot":"","sources":["../../src/components/collection-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC9F,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,4BAA4B,CAAC;AAEvF,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AAEpC,KAAK,eAAe,GAChB;IACE,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,GACD;IAAE,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,mBAAmB,CAAC,OAAO,SAAS,OAAO,IAAI,iBAAiB,CAC1E,OAAO,EACP,SAAS,GAAG,SAAS,GAAG,QAAQ,CACjC,GACC,eAAe,GAAG;IAChB,6HAA6H;IAC7H,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;IAC3C,qFAAqF;IACrF,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,kFAAkF;IAClF,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACnC,iDAAiD;IACjD,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACpD,oGAAoG;IACpG,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,CAAC;AAEJ;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAS,OAAO,EAAE,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,+BA2D1F"}
|
|
@@ -17,7 +17,7 @@ import { CollectionRailColumn } from "../internal/collection-rail.js";
|
|
|
17
17
|
* @when “Use `<Entity>` for a row of descriptive content paired with one or two controls (member rows, integration rows, domain rows).” (https://vercel.com/geist/entity)
|
|
18
18
|
* Ours: a list of entity rows a person finds one of, opens and acts on: Customers, Agents, Skills, Apps, MCP servers, Mailboxes, domains, environment variables (a row with an `editor` expands into its form). Its rows are a `RecordList`'s, so a row has a mark, a name over a muted line and at most three facts; anything wider is not this page.
|
|
19
19
|
* “Projects”: Vercel's Projects page stands a column of titled cards (Usage, Alerts, Recent Previews) at the left of its list. (https://vercel.com/dashboard)
|
|
20
|
-
* Ours:
|
|
20
|
+
* Ours: Customers and Partners use the full-width list, with actionable attention above the toolbar when present. Business summaries belong on Dashboard and Analytics. A rail remains available for context that belongs to the collection itself, such as the selected Library hub.
|
|
21
21
|
* @instead “For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity)
|
|
22
22
|
* Ours: records compared across columns, read by their headings, are a `DataTable` under the page's own title and toolbar. A list inside another page's section is a `RecordList` with its `heading`.
|
|
23
23
|
* @behaviour With a `rail`, the toolbar spans the page and under it stand two columns from 1280 px: the rail, 300 px, then the records' card, its top level with the rail's first title and named by the page's title alone, never a second heading, and the records' rows are `RecordList`'s `line` rows; below 1280 px the records come first and the rail follows them. Each rail card has its title above it at 16 px, an optional 44 px muted summary row with its one outline button at its end (a button never stands in a row of its own, so a card with an `action` has a `summary`), then its items: a figure is one 36 px row, its title and its number at the trailing edge; a record is its 24 px mark, a title over a muted line that wraps to a second before it is cut, and a figure or a status at its end, the whole item opening its record; a card with no items draws its `empty` inside it as one 44 px row like an item. While the rail's read is in flight a card's `items` are undefined and it holds its place with three placeholder lines, so the two columns stand from the first frame; a rail whose read `failed` is one card saying so, and the records beside it stay. Under the title sits only the `description`, when the collection's kind needs explaining; otherwise nothing. The title row holds at most one secondary, the primary, then the three dots, which open only for two commands or more. The primary stays in the title row whether the collection is empty or not, filled, as Vercel's Flags keeps Create Flag; a first use repeats it as the filled button in its card. One toolbar holds the search, which grows, then the filters, then the sort; it shows while there are records or a search or filter is set, and is glass only where the rows scroll under it. While a new search, filter or sort is read, the toolbar is busy and, after a second, shows the one waiting line, while the last rows stay. The rows, their states and their loading are the RecordList's; no match is offered only while a search or filter is set.
|
|
@@ -27,9 +27,9 @@ import { CollectionRailColumn } from "../internal/collection-rail.js";
|
|
|
27
27
|
* Ours: the rows' region is the RecordList's, which holds it. The title is the page's h1 when the composition draws it. The toolbar is named by `label` and busy while `pending`; the rows are the RecordList's table, named by `label`.
|
|
28
28
|
*/
|
|
29
29
|
export function CollectionPage(props) {
|
|
30
|
-
const { title, description, actions, tabs, search, filters, sort, toolbarSurface, noMatch, pending, rail, ...list } = props;
|
|
30
|
+
const { title, description, actions, tabs, attention, search, filters, sort, toolbarSurface, noMatch, pending, rail, ...list } = props;
|
|
31
31
|
const hasRecords = list.records !== undefined && list.records.length > 0;
|
|
32
32
|
const narrowed = Boolean(search?.value) || (filters?.facets.some((facet) => facet.value) ?? false);
|
|
33
|
-
const page = (_jsxs("div", { className: "grid min-w-0 gap-4", "data-slot": "collection-page", children: [title ? _jsx(PageHeader, { description: description, title: title }) : null, actions ? _jsx(PageActions, { ...actions }) : null, tabs, (search || filters || sort) && (hasRecords || narrowed) ? (_jsx(CollectionToolbar, { actions: filters || sort ? (_jsxs(_Fragment, { children: [filters ? _jsx(CollectionFilters, { ...filters }) : null, sort ? _jsx(CollectionSort, { ...sort }) : null] })) : undefined, "aria-busy": pending || undefined, label: list.label, search: search ? _jsx(CollectionSearch, { ...search }) : undefined, status: pending ? _jsx(WaitingLine, { className: "w-24", decorative: true }) : null, surface: toolbarSurface ?? "plain" })) : null, rail ? (_jsxs("div", { className: "grid min-w-0 gap-6 xl:grid-cols-[18.75rem_minmax(0,1fr)] xl:items-start", "data-slot": "collection-columns", children: [_jsx("div", { className: "min-w-0 xl:col-start-2 xl:row-start-1", children: _jsx(RecordList, { ...list, layout: "line", noMatch: narrowed ? noMatch : undefined }) }), _jsx(CollectionRailColumn, { className: "xl:col-start-1 xl:row-start-1", rail: rail })] })) : (_jsx(RecordList, { ...list, noMatch: narrowed ? noMatch : undefined }))] }));
|
|
33
|
+
const page = (_jsxs("div", { className: "grid min-w-0 gap-4", "data-slot": "collection-page", children: [title ? _jsx(PageHeader, { description: description, title: title }) : null, actions ? _jsx(PageActions, { ...actions }) : null, tabs, attention, (search || filters || sort) && (hasRecords || narrowed) ? (_jsx(CollectionToolbar, { actions: filters || sort ? (_jsxs(_Fragment, { children: [filters ? _jsx(CollectionFilters, { ...filters }) : null, sort ? _jsx(CollectionSort, { ...sort }) : null] })) : undefined, "aria-busy": pending || undefined, label: list.label, search: search ? _jsx(CollectionSearch, { ...search }) : undefined, status: pending ? _jsx(WaitingLine, { className: "w-24", decorative: true }) : null, surface: toolbarSurface ?? "plain" })) : null, rail ? (_jsxs("div", { className: "grid min-w-0 gap-6 xl:grid-cols-[18.75rem_minmax(0,1fr)] xl:items-start", "data-slot": "collection-columns", children: [_jsx("div", { className: "min-w-0 xl:col-start-2 xl:row-start-1", children: _jsx(RecordList, { ...list, layout: "line", noMatch: narrowed ? noMatch : undefined }) }), _jsx(CollectionRailColumn, { className: "xl:col-start-1 xl:row-start-1", rail: rail })] })) : (_jsx(RecordList, { ...list, noMatch: narrowed ? noMatch : undefined }))] }));
|
|
34
34
|
return title ? _jsx(PageActionsHostProvider, { children: page }) : page;
|
|
35
35
|
}
|
|
@@ -4,7 +4,7 @@ import * as ResizablePrimitive from "react-resizable-panels";
|
|
|
4
4
|
*
|
|
5
5
|
* @family Other
|
|
6
6
|
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
7
|
-
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle
|
|
7
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle. A width a person never changes is a plain grid column. A window too narrow for the panes side by side gets a compact alternative, one pane at a time, instead of squeezed panes.
|
|
8
8
|
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum, set where its content still reads, and its maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px wide hit area centred on it; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else. The group holds sizes only while it is mounted; the product owns persisting them.
|
|
9
9
|
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
10
10
|
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
|
@@ -7,7 +7,7 @@ import { cn } from "../lib/utils.js";
|
|
|
7
7
|
*
|
|
8
8
|
* @family Other
|
|
9
9
|
* @when Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.
|
|
10
|
-
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle
|
|
10
|
+
* @instead The product frame's sidebar resizes through `Sidebar`'s `resize` handle. A width a person never changes is a plain grid column. A window too narrow for the panes side by side gets a compact alternative, one pane at a time, instead of squeezed panes.
|
|
11
11
|
* @behaviour The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum, set where its content still reads, and its maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px wide hit area centred on it; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else. The group holds sizes only while it is mounted; the product owns persisting them.
|
|
12
12
|
* @words Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.
|
|
13
13
|
* @access The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.
|
package/dist/eslint/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { confirmDialogWords } from "./rules/confirm-dialog-words.js";
|
|
|
15
15
|
import { dataTableOneUnsizedColumn } from "./rules/data-table-one-unsized-column.js";
|
|
16
16
|
import { destructiveActionPlacement } from "./rules/destructive-action-placement.js";
|
|
17
17
|
import { disabledChoiceSaysWhy } from "./rules/disabled-choice-says-why.js";
|
|
18
|
+
import { disabledControlAppearance } from "./rules/disabled-control-appearance.js";
|
|
18
19
|
import { settingsLimitInFooter } from "./rules/settings-limit-in-footer.js";
|
|
19
20
|
import { ellipsisOpensADialog } from "./rules/ellipsis-opens-a-dialog.js";
|
|
20
21
|
import { emptyStateOwner } from "./rules/empty-state-owner.js";
|
|
@@ -160,6 +161,7 @@ const plugin = {
|
|
|
160
161
|
"data-table-one-unsized-column": dataTableOneUnsizedColumn,
|
|
161
162
|
"destructive-action-placement": destructiveActionPlacement,
|
|
162
163
|
"disabled-choice-says-why": disabledChoiceSaysWhy,
|
|
164
|
+
"disabled-control-appearance": disabledControlAppearance,
|
|
163
165
|
"settings-limit-in-footer": settingsLimitInFooter,
|
|
164
166
|
"ellipsis-opens-a-dialog": ellipsisOpensADialog,
|
|
165
167
|
"empty-state-owner": emptyStateOwner,
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Standard tool checked first: a `no-restricted-syntax` selector can match a
|
|
3
|
+
* conditional `variant`, but not that its condition reads a value the same
|
|
4
|
+
* element's `disabled` reads. That needs the two expressions compared.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { walk } from "./rendered-import.js";
|
|
8
|
+
|
|
9
|
+
const APPEARANCE_ATTRIBUTES = ["variant", "triggerVariant", "size"];
|
|
10
|
+
|
|
11
|
+
function valuePathsAndPrefixes(root, sourceCode) {
|
|
12
|
+
const names = new Set();
|
|
13
|
+
const collect = (node) => {
|
|
14
|
+
const pathTail = node.parent?.type === "MemberExpression" && !node.parent.computed;
|
|
15
|
+
if (node.type === "Identifier" && !pathTail) names.add(node.name);
|
|
16
|
+
if (node.type === "MemberExpression" && !node.computed) names.add(sourceCode.getText(node));
|
|
17
|
+
};
|
|
18
|
+
collect(root);
|
|
19
|
+
walk(root, sourceCode.visitorKeys, collect);
|
|
20
|
+
return names;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const attribute = (openingElement, name) =>
|
|
24
|
+
openingElement.attributes.find(
|
|
25
|
+
(candidate) => candidate.type === "JSXAttribute" && candidate.name.name === name,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const disabledControlAppearance = {
|
|
29
|
+
meta: {
|
|
30
|
+
type: "problem",
|
|
31
|
+
docs: {
|
|
32
|
+
description:
|
|
33
|
+
"A control never chooses its variant from the condition that disables it, so a disabled control has one appearance.",
|
|
34
|
+
},
|
|
35
|
+
schema: [
|
|
36
|
+
{
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
controls: { type: "array", items: { type: "string" }, uniqueItems: true },
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
defaultOptions: [{ controls: ["Button"] }],
|
|
45
|
+
messages: {
|
|
46
|
+
"variant-follows-disabled":
|
|
47
|
+
"{{control}} turns its {{attribute}} on `{{condition}}`, which also disables it, so its disabled state looks unlike every other disabled {{control}}. Keep one {{attribute}} and let `disabled` draw the state.",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
create(context) {
|
|
51
|
+
const [{ controls }] = context.options;
|
|
52
|
+
const { sourceCode } = context;
|
|
53
|
+
return {
|
|
54
|
+
JSXOpeningElement(node) {
|
|
55
|
+
if (node.name.type !== "JSXIdentifier" || !controls.includes(node.name.name)) return;
|
|
56
|
+
const disabled = attribute(node, "disabled")?.value;
|
|
57
|
+
if (disabled?.type !== "JSXExpressionContainer") return;
|
|
58
|
+
const disabling = valuePathsAndPrefixes(disabled.expression, sourceCode);
|
|
59
|
+
for (const name of APPEARANCE_ATTRIBUTES) {
|
|
60
|
+
const chosen = attribute(node, name)?.value;
|
|
61
|
+
if (chosen?.type !== "JSXExpressionContainer") continue;
|
|
62
|
+
if (chosen.expression.type !== "ConditionalExpression") continue;
|
|
63
|
+
const { test } = chosen.expression;
|
|
64
|
+
if (![...valuePathsAndPrefixes(test, sourceCode)].some((read) => disabling.has(read)))
|
|
65
|
+
continue;
|
|
66
|
+
context.report({
|
|
67
|
+
node: chosen,
|
|
68
|
+
messageId: "variant-follows-disabled",
|
|
69
|
+
data: { control: node.name.name, attribute: name, condition: sourceCode.getText(test) },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export * from "./components/chart-bar-stacked.js";
|
|
|
32
32
|
export * from "./components/chart-card.js";
|
|
33
33
|
export * from "./components/chart-date-range-control.js";
|
|
34
34
|
export * from "./components/chart-entity-colors.js";
|
|
35
|
+
export * from "./components/chart-ranking.js";
|
|
35
36
|
export * from "./components/chart-sparkline.js";
|
|
36
37
|
export * from "./components/check-counts.js";
|
|
37
38
|
export * from "./components/checkbox.js";
|
|
@@ -51,7 +52,6 @@ export * from "./components/confirm-dialog.js";
|
|
|
51
52
|
export * from "./components/context-menu.js";
|
|
52
53
|
export * from "./components/copy-button.js";
|
|
53
54
|
export * from "./components/data-table.js";
|
|
54
|
-
export * from "./components/desktop-shell.js";
|
|
55
55
|
export * from "./components/dialog.js";
|
|
56
56
|
export * from "./components/diff-count.js";
|
|
57
57
|
export * from "./components/disclosure.js";
|
|
@@ -98,7 +98,6 @@ export * from "./components/page-actions.js";
|
|
|
98
98
|
export * from "./components/page-header.js";
|
|
99
99
|
export * from "./components/pairing-code.js";
|
|
100
100
|
export * from "./components/pending-label.js";
|
|
101
|
-
export * from "./components/picture-label.js";
|
|
102
101
|
export * from "./components/platform-mark.js";
|
|
103
102
|
export * from "./components/popover.js";
|
|
104
103
|
export * from "./components/portal-sidebar-frame.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,uCAAuC,CAAC;AACtD,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ export * from "./components/chart-bar-stacked.js";
|
|
|
32
32
|
export * from "./components/chart-card.js";
|
|
33
33
|
export * from "./components/chart-date-range-control.js";
|
|
34
34
|
export * from "./components/chart-entity-colors.js";
|
|
35
|
+
export * from "./components/chart-ranking.js";
|
|
35
36
|
export * from "./components/chart-sparkline.js";
|
|
36
37
|
export * from "./components/check-counts.js";
|
|
37
38
|
export * from "./components/checkbox.js";
|
|
@@ -51,7 +52,6 @@ export * from "./components/confirm-dialog.js";
|
|
|
51
52
|
export * from "./components/context-menu.js";
|
|
52
53
|
export * from "./components/copy-button.js";
|
|
53
54
|
export * from "./components/data-table.js";
|
|
54
|
-
export * from "./components/desktop-shell.js";
|
|
55
55
|
export * from "./components/dialog.js";
|
|
56
56
|
export * from "./components/diff-count.js";
|
|
57
57
|
export * from "./components/disclosure.js";
|
|
@@ -98,7 +98,6 @@ export * from "./components/page-actions.js";
|
|
|
98
98
|
export * from "./components/page-header.js";
|
|
99
99
|
export * from "./components/pairing-code.js";
|
|
100
100
|
export * from "./components/pending-label.js";
|
|
101
|
-
export * from "./components/picture-label.js";
|
|
102
101
|
export * from "./components/platform-mark.js";
|
|
103
102
|
export * from "./components/popover.js";
|
|
104
103
|
export * from "./components/portal-sidebar-frame.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { MarkdownTextPrimitive,
|
|
3
|
+
import { MarkdownTextPrimitive, memoizeMarkdownComponents, useIsMarkdownCodeBlock, } from "@assistant-ui/react-markdown";
|
|
4
4
|
import remarkGfm from "remark-gfm";
|
|
5
5
|
import { memo } from "react";
|
|
6
6
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
declare function DateRangeControlSpecimen(): import("react").JSX.Element;
|
|
2
2
|
export declare const CHARTS: {
|
|
3
|
+
ChartRanking: () => import("react").JSX.Element;
|
|
3
4
|
ActivityCalendar: () => import("react").JSX.Element;
|
|
4
5
|
ChartAreaStacked: () => import("react").JSX.Element;
|
|
5
6
|
ChartBarHorizontal: () => import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/charts.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"charts.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/charts.tsx"],"names":[],"mappings":"AAoFA,iBAAS,wBAAwB,gCA0BhC;AAED,eAAO,MAAM,MAAM;;;;;;;;;;;;;;CA4MQ,CAAC"}
|
|
@@ -12,6 +12,7 @@ import { ChartCard, ChartSummary } from "../../components/chart-card.js";
|
|
|
12
12
|
import { DateRangeControl } from "../../components/chart-date-range-control.js";
|
|
13
13
|
import { createEntityColorMap } from "../../components/chart-entity-colors.js";
|
|
14
14
|
import { ChartSparkline } from "../../components/chart-sparkline.js";
|
|
15
|
+
import { ChartRanking } from "../../components/chart-ranking.js";
|
|
15
16
|
import { KpiCard } from "../../components/kpi-card.js";
|
|
16
17
|
import { TrendBadge, trendTone } from "../../components/trend-badge.js";
|
|
17
18
|
const euro = (value) => new Intl.NumberFormat("en", { style: "currency", currency: "EUR" }).format(value);
|
|
@@ -69,6 +70,15 @@ function DateRangeControlSpecimen() {
|
|
|
69
70
|
return (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx(DateRangeControl, { formatCustomValue: ({ from, to }) => `${from} – ${to}`, label: "Date range", maxValue: RETENTION_TO, minValue: RETENTION_FROM, onChange: setRange, presetLabels: RANGE_PRESET_LABELS, value: range }), _jsx(DateRangeControl, { formatCustomValue: ({ from, to }) => `${from} – ${to}`, label: "Date range, small", maxValue: RETENTION_TO, minValue: RETENTION_FROM, onChange: setSmallRange, presetLabels: RANGE_PRESET_LABELS, size: "sm", value: smallRange })] }));
|
|
70
71
|
}
|
|
71
72
|
export const CHARTS = {
|
|
73
|
+
ChartRanking: () => (_jsx(ChartRanking, { title: "Top customers", description: "by spend", total: 356, rows: SPEND.slice(-1).flatMap((reading) => CUSTOMERS.map((customer) => ({
|
|
74
|
+
...customer,
|
|
75
|
+
value: reading[customer.id],
|
|
76
|
+
display: euro(reading[customer.id]),
|
|
77
|
+
}))), entityColorMap: CUSTOMER_COLORS, disclosure: {
|
|
78
|
+
label: "View all (3)",
|
|
79
|
+
description: "Ranked by spend over the selected period",
|
|
80
|
+
closeLabel: "Close",
|
|
81
|
+
} })),
|
|
72
82
|
ActivityCalendar: () => (_jsx(ActivityCalendar, { data: ACTIVITY, from: "2026-08-16", labels: {
|
|
73
83
|
ariaLabel: "Requests per day",
|
|
74
84
|
unavailable: "Not measured",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
declare function EmptyStateSpecimen(): import("react").JSX.Element;
|
|
2
|
-
declare function LabelledPictureSpecimen(): import("react").JSX.Element;
|
|
3
2
|
declare function PendingLabelSpecimen(): import("react").JSX.Element;
|
|
4
3
|
declare function ToasterSpecimen(): import("react").JSX.Element;
|
|
5
4
|
declare function UpdateCardSpecimen(): import("react").JSX.Element;
|
|
@@ -10,7 +9,6 @@ export declare const FEEDBACK: {
|
|
|
10
9
|
EntryProgress: () => import("react").JSX.Element;
|
|
11
10
|
EntryStageList: () => import("react").JSX.Element;
|
|
12
11
|
HoverCard: () => import("react").JSX.Element;
|
|
13
|
-
LabelledPicture: typeof LabelledPictureSpecimen;
|
|
14
12
|
MessageNotice: () => import("react").JSX.Element;
|
|
15
13
|
NoticeBanner: () => import("react").JSX.Element;
|
|
16
14
|
PendingLabel: typeof PendingLabelSpecimen;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/feedback.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feedback.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/feedback.tsx"],"names":[],"mappings":"AA6CA,iBAAS,kBAAkB,gCAoE1B;AAED,iBAAS,oBAAoB,gCAkB5B;AAED,iBAAS,eAAe,gCAyBvB;AAED,iBAAS,kBAAkB,gCA8B1B;AAED,iBAAS,sBAAsB,gCAwB9B;AAED,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;CA6LM,CAAC"}
|
|
@@ -11,7 +11,6 @@ import { HoverCard, HoverCardContent, HoverCardSummary, HoverCardTrigger, } from
|
|
|
11
11
|
import { Kbd } from "../../components/kbd.js";
|
|
12
12
|
import { MessageNotice } from "../../components/message-notice.js";
|
|
13
13
|
import { NoticeBanner } from "../../components/notice-banner.js";
|
|
14
|
-
import { LabelledPicture, PictureLabel } from "../../components/picture-label.js";
|
|
15
14
|
import { RecordTime } from "../../components/record-time.js";
|
|
16
15
|
import { Skeleton, SkeletonRegion } from "../../components/skeleton.js";
|
|
17
16
|
import { Toaster } from "../../components/sonner.js";
|
|
@@ -38,10 +37,6 @@ function EmptyStateSpecimen() {
|
|
|
38
37
|
copyFailedLabel: "Couldn't copy",
|
|
39
38
|
}, scope: "region" }) }), _jsx(Captioned, { caption: "Failed, in a card: the answer of an ErrorCard", children: _jsx(EmptyState, { kind: "failed", message: FAILED_READ, scope: "card" }) })] }));
|
|
40
39
|
}
|
|
41
|
-
function LabelledPictureSpecimen() {
|
|
42
|
-
const art = useEmptyArt();
|
|
43
|
-
return (_jsx(LabelledPicture, { label: _jsx(PictureLabel, { details: "Ink and watercolour, 2026", title: "A letter that lost its address" }), children: _jsx("img", { alt: "", className: "size-64 object-contain", src: art.mail }) }));
|
|
44
|
-
}
|
|
45
40
|
function PendingLabelSpecimen() {
|
|
46
41
|
const [pending, setPending] = useState(false);
|
|
47
42
|
return (_jsxs(DropdownMenu, { onOpenChange: (open) => (open ? undefined : setPending(false)), children: [_jsx(DropdownMenuTrigger, { render: _jsx(Button, { variant: "outline" }), children: "Account" }), _jsx(DropdownMenuContent, { align: "start", children: _jsx(DropdownMenuCommand, { closeOnClick: false, icon: _jsx(LogOut, {}), loading: pending, loadingLabel: "Signing out", onClick: () => setPending(true), children: "Sign out" }) })] }));
|
|
@@ -71,7 +66,6 @@ export const FEEDBACK = {
|
|
|
71
66
|
{ label: "Region", value: "Frankfurt" },
|
|
72
67
|
{ label: "Last active", value: null },
|
|
73
68
|
], missingLabel: "Not reported", name: "Portal" }) })] })] })),
|
|
74
|
-
LabelledPicture: LabelledPictureSpecimen,
|
|
75
69
|
MessageNotice: () => (_jsxs("div", { className: "grid max-w-lg gap-4", children: [_jsx(MessageNotice, { message: sampleMessage("Couldn't remove pec@acme.it", "The mailbox is still connected.", [
|
|
76
70
|
{ label: "Try again", onClick: nothing },
|
|
77
71
|
]), placement: "action" }), _jsx(MessageNotice, { message: sampleMessage("Billing is paused", "Agents stop at the end of the cycle.", [
|
|
@@ -15,6 +15,7 @@ export declare const SPECIMENS: {
|
|
|
15
15
|
ScrollArea: () => import("react").JSX.Element;
|
|
16
16
|
Separator: () => import("react").JSX.Element;
|
|
17
17
|
ToolIcon: () => import("react").JSX.Element;
|
|
18
|
+
ChartRanking: () => import("react").JSX.Element;
|
|
18
19
|
ActivityCalendar: () => import("react").JSX.Element;
|
|
19
20
|
ChartAreaStacked: () => import("react").JSX.Element;
|
|
20
21
|
ChartBarHorizontal: () => import("react").JSX.Element;
|
|
@@ -45,7 +46,6 @@ export declare const SPECIMENS: {
|
|
|
45
46
|
EntryProgress: () => import("react").JSX.Element;
|
|
46
47
|
EntryStageList: () => import("react").JSX.Element;
|
|
47
48
|
HoverCard: () => import("react").JSX.Element;
|
|
48
|
-
LabelledPicture: () => import("react").JSX.Element;
|
|
49
49
|
MessageNotice: () => import("react").JSX.Element;
|
|
50
50
|
NoticeBanner: () => import("react").JSX.Element;
|
|
51
51
|
PendingLabel: () => import("react").JSX.Element;
|
|
@@ -82,7 +82,6 @@ export declare const SPECIMENS: {
|
|
|
82
82
|
AgentListRow: () => import("react").JSX.Element;
|
|
83
83
|
Breadcrumb: () => import("react").JSX.Element;
|
|
84
84
|
CommandDialog: () => import("react").JSX.Element;
|
|
85
|
-
DesktopAppShell: () => import("react").JSX.Element;
|
|
86
85
|
Footer: () => import("react").JSX.Element;
|
|
87
86
|
PortalSidebarFrame: () => import("react").JSX.Element;
|
|
88
87
|
ScopeSwitcher: () => import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/index.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/index.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYiB,CAAC"}
|
|
@@ -6,7 +6,6 @@ export declare const NAVIGATION: {
|
|
|
6
6
|
AgentListRow: () => import("react").JSX.Element;
|
|
7
7
|
Breadcrumb: () => import("react").JSX.Element;
|
|
8
8
|
CommandDialog: typeof CommandDialogSpecimen;
|
|
9
|
-
DesktopAppShell: () => import("react").JSX.Element;
|
|
10
9
|
Footer: () => import("react").JSX.Element;
|
|
11
10
|
PortalSidebarFrame: () => import("react").JSX.Element;
|
|
12
11
|
ScopeSwitcher: typeof ScopeSwitcherSpecimen;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/navigation.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/showcase/specimens/navigation.tsx"],"names":[],"mappings":"AAoEA,iBAAS,qBAAqB,gCAoC7B;AAED,iBAAS,qBAAqB,gCAmB7B;AAED,iBAAS,uBAAuB,gCAiE/B;AAED,iBAAS,YAAY,gCAqCpB;AAED,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;CAmRI,CAAC"}
|
|
@@ -8,7 +8,6 @@ import { BrandWordmark } from "../../components/brand.js";
|
|
|
8
8
|
import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "../../components/breadcrumb.js";
|
|
9
9
|
import { Button } from "../../components/button.js";
|
|
10
10
|
import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut, } from "../../components/command.js";
|
|
11
|
-
import { DesktopAppShell } from "../../components/desktop-shell.js";
|
|
12
11
|
import { Footer, FooterBrand, FooterIdentity, FooterInner, FooterMeta, FooterNav, } from "../../components/footer.js";
|
|
13
12
|
import { AgentIcon, ApprovalsIcon } from "../../components/house-icons.js";
|
|
14
13
|
import { Kbd } from "../../components/kbd.js";
|
|
@@ -90,7 +89,6 @@ export const NAVIGATION = {
|
|
|
90
89
|
AgentListRow: () => (_jsxs("ul", { className: "grid max-w-xs gap-1", children: [_jsx("li", { children: _jsx(AgentListRow, { color: COBALTO, current: true, form: "orbit", name: "Invoices", state: "working", stateLine: "Drafting October's invoices" }) }), _jsx("li", { children: _jsx(AgentListRow, { color: VERDE, form: "lattice", name: "Orders", state: "waiting", stateLine: "Waiting for you", stateTone: "warn" }) })] })),
|
|
91
90
|
Breadcrumb: () => (_jsxs("div", { className: "grid gap-4", children: [_jsx(Breadcrumb, { "aria-label": "Path", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica" }) })] }) }), _jsx(Breadcrumb, { "aria-label": "Path with a closed ancestor", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { disabled: true, children: "Partners" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica" }) })] }) }), _jsx(Breadcrumb, { "aria-label": "Long path", children: _jsxs(BreadcrumbList, { children: [_jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#customers", children: "Customers" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbEllipsis, { label: "More" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbLink, { href: "#installations", children: "Installations" }) }), _jsx(BreadcrumbSeparator, {}), _jsx(BreadcrumbItem, { children: _jsx(BreadcrumbPage, { children: "Rossi Ottica, Milano" }) })] }) })] })),
|
|
92
91
|
CommandDialog: CommandDialogSpecimen,
|
|
93
|
-
DesktopAppShell: () => (_jsx("div", { className: "h-96 overflow-hidden rounded-md border border-border", children: _jsx(DesktopAppShell, { activityRail: _jsx(Navigation, { children: _jsx(SidebarMenu, { className: "p-2", children: _jsx(SidebarMenuItem, { children: _jsx(SidebarMenuButton, { isActive: true, children: _jsx(AgentListRow, { color: COBALTO, form: "orbit", name: "Invoices", size: 24 }) }) }) }) }), activityRailLabel: "Agents", className: "h-full", primaryPaneLabel: "Conversation", title: "Invoices", children: _jsx("p", { className: "p-4 text-sm text-muted-foreground", children: "The Agent's conversation." }) }) })),
|
|
94
92
|
Footer: () => (_jsx(Footer, { children: _jsxs(FooterInner, { children: [_jsx(FooterBrand, { "aria-label": "nadicode", href: "#top", children: _jsx(BrandWordmark, { alt: "" }) }), _jsx(FooterIdentity, { children: "Agents that do the work, for Italian companies." }), _jsxs(FooterNav, { "aria-label": "Company", children: [_jsx("a", { href: "#privacy", children: "Privacy" }), _jsx("a", { href: "#terms", children: "Terms" })] }), _jsx(FooterMeta, { children: "\u00A9 2026 nadicode" })] }) })),
|
|
95
93
|
PortalSidebarFrame: () => (_jsx(Navigation, { children: _jsx(PortalSidebarFrame, { account: { name: "Ada Rossi", initials: "AR", lines: ["Acme S.r.l."] }, bands: [
|
|
96
94
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type UsageName = "ActivityFeed" | "AgentProfileCard" | "CatalogDrawer" | "CollectionFilters" | "CollectionPage" | "CollectionToolbar" | "ConfirmDialog" | "EntryScene" | "FormDialog" | "FormDrawer" | "LibraryShelf" | "ObjectPage" | "ObjectSection" | "OverviewPage" | "PageHeader" | "RecordList" | "RecordSheet" | "RowEditForm" | "SettingsPage" | "SettingsSection" | "Button" | "ButtonGroup" | "ButtonLink" | "CopyButton" | "LoadMoreButton" | "PageActions" | "Calendar" | "ClearableInput" | "CollectionSearch" | "Field" | "Input" | "InputGroup" | "InputOTP" | "Label" | "NativeSelect" | "SettingsField" | "SettingsRows" | "Slider" | "Textarea" | "Checkbox" | "ChoiceboxGroup" | "CollectionSort" | "Combobox" | "ModelSelect" | "MultiSelect" | "RadioGroup" | "SegmentedChoice" | "SegmentedControl" | "Select" | "Switch" | "ThemeModeSegments" | "ThemeModeSwitcher" | "Toggle" | "ToggleGroup" | "ActionStatus" | "AgentOrb" | "AppMark" | "ArchIcon" | "Avatar" | "Badge" | "BrandWordmark" | "CheckCounts" | "FileTypeIcon" | "IdentityMark" | "ModelIdentity" | "ModelMark" | "PlatformMark" | "ProgressChecklist" | "RecordIdentity" | "StatusBadge" | "StatusDot" | "Tag" | "AgentListRow" | "Breadcrumb" | "CommandDialog" | "
|
|
1
|
+
export type UsageName = "ActivityFeed" | "AgentProfileCard" | "CatalogDrawer" | "CollectionFilters" | "CollectionPage" | "CollectionToolbar" | "ConfirmDialog" | "EntryScene" | "FormDialog" | "FormDrawer" | "LibraryShelf" | "ObjectPage" | "ObjectSection" | "OverviewPage" | "PageHeader" | "RecordList" | "RecordSheet" | "RowEditForm" | "SettingsPage" | "SettingsSection" | "Button" | "ButtonGroup" | "ButtonLink" | "CopyButton" | "LoadMoreButton" | "PageActions" | "Calendar" | "ClearableInput" | "CollectionSearch" | "Field" | "Input" | "InputGroup" | "InputOTP" | "Label" | "NativeSelect" | "SettingsField" | "SettingsRows" | "Slider" | "Textarea" | "Checkbox" | "ChoiceboxGroup" | "CollectionSort" | "Combobox" | "ModelSelect" | "MultiSelect" | "RadioGroup" | "SegmentedChoice" | "SegmentedControl" | "Select" | "Switch" | "ThemeModeSegments" | "ThemeModeSwitcher" | "Toggle" | "ToggleGroup" | "ActionStatus" | "AgentOrb" | "AppMark" | "ArchIcon" | "Avatar" | "Badge" | "BrandWordmark" | "CheckCounts" | "FileTypeIcon" | "IdentityMark" | "ModelIdentity" | "ModelMark" | "PlatformMark" | "ProgressChecklist" | "RecordIdentity" | "StatusBadge" | "StatusDot" | "Tag" | "AgentListRow" | "Breadcrumb" | "CommandDialog" | "Footer" | "PortalSidebarFrame" | "ScopeSwitcher" | "Sidebar" | "SidebarBrand" | "SidebarFind" | "SidebarFrame" | "SidebarMenuChevron" | "SidebarSections" | "Tabs" | "TabsNav" | "textLinkVariants" | "AgentCard" | "Card" | "CardRow" | "CodeBlock" | "DataTable" | "DiffCount" | "DisclosureRow" | "FileDiff" | "Gauge" | "Item" | "Kbd" | "MiddleTruncate" | "ObjectFacts" | "PairingCode" | "Progress" | "QrCode" | "RecordTime" | "RunTimeline" | "SettingsFactsSection" | "Snippet" | "Table" | "TableCard" | "TableValue" | "TextWithCopyButton" | "UsageMeter" | "Alert" | "EmptyState" | "EntryProgress" | "EntryStageList" | "HoverCard" | "MessageNotice" | "NoticeBanner" | "PendingLabel" | "Skeleton" | "SkeletonRegion" | "Toaster" | "Tooltip" | "UpdateCard" | "WaitingLine" | "AccountMenu" | "ActionContextMenu" | "ActionMenu" | "AlertDialog" | "ContextMenu" | "Dialog" | "Drawer" | "DropdownMenu" | "GlassControl" | "MenuChoiceRow" | "Popover" | "Sheet" | "ThemeModeMenu" | "ActivityCalendar" | "ChartAreaStacked" | "ChartBarHorizontal" | "ChartBarMultiple" | "ChartBarStacked" | "ChartCard" | "ChartContainer" | "ChartRanking" | "ChartSparkline" | "DateRangeControl" | "KpiCard" | "TrendBadge" | "createEntityColorMap" | "Accordion" | "AspectRatio" | "BrandField" | "Carousel" | "Collapsible" | "CompanyCard" | "Disclosure" | "HiveScene" | "NadiaPresence" | "NumberedSteps" | "Prose" | "ReadingColumn" | "ResizablePanelGroup" | "ScrollArea" | "Separator" | "ToolIcon";
|
|
2
2
|
export type UsageFamily = "Compositions" | "Actions" | "Inputs" | "Choices" | "Status" | "Navigation" | "Data" | "Feedback" | "Menus" | "Charts" | "Other";
|
|
3
3
|
export type ComponentUsage = {
|
|
4
4
|
name: UsageName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.generated.d.ts","sourceRoot":"","sources":["../../src/showcase/usage.generated.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GACjB,cAAc,GACd,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,gBAAgB,GAChB,mBAAmB,GACnB,eAAe,GACf,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,YAAY,GACZ,eAAe,GACf,cAAc,GACd,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,QAAQ,GACR,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,gBAAgB,GAChB,aAAa,GACb,UAAU,GACV,gBAAgB,GAChB,kBAAkB,GAClB,OAAO,GACP,OAAO,GACP,YAAY,GACZ,UAAU,GACV,OAAO,GACP,cAAc,GACd,eAAe,GACf,cAAc,GACd,QAAQ,GACR,UAAU,GACV,UAAU,GACV,gBAAgB,GAChB,gBAAgB,GAChB,UAAU,GACV,aAAa,GACb,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,kBAAkB,GAClB,QAAQ,GACR,QAAQ,GACR,mBAAmB,GACnB,mBAAmB,GACnB,QAAQ,GACR,aAAa,GACb,cAAc,GACd,UAAU,GACV,SAAS,GACT,UAAU,GACV,QAAQ,GACR,OAAO,GACP,eAAe,GACf,aAAa,GACb,cAAc,GACd,cAAc,GACd,eAAe,GACf,WAAW,GACX,cAAc,GACd,mBAAmB,GACnB,gBAAgB,GAChB,aAAa,GACb,WAAW,GACX,KAAK,GACL,cAAc,GACd,YAAY,GACZ,eAAe,GACf,
|
|
1
|
+
{"version":3,"file":"usage.generated.d.ts","sourceRoot":"","sources":["../../src/showcase/usage.generated.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,7 +63,7 @@ export const USAGE = [
|
|
|
63
63
|
module: "collection-page",
|
|
64
64
|
family: "Compositions",
|
|
65
65
|
summary: "A page whose job is a list of records: its title with the page's actions on one row, its sibling collections, one toolbar, then one line per record.",
|
|
66
|
-
when: "“Use `<Entity>` for a row of descriptive content paired with one or two controls (member rows, integration rows, domain rows).” (https://vercel.com/geist/entity) Ours: a list of entity rows a person finds one of, opens and acts on: Customers, Agents, Skills, Apps, MCP servers, Mailboxes, domains, environment variables (a row with an `editor` expands into its form). Its rows are a `RecordList`'s, so a row has a mark, a name over a muted line and at most three facts; anything wider is not this page. “Projects”: Vercel's Projects page stands a column of titled cards (Usage, Alerts, Recent Previews) at the left of its list. (https://vercel.com/dashboard) Ours:
|
|
66
|
+
when: "“Use `<Entity>` for a row of descriptive content paired with one or two controls (member rows, integration rows, domain rows).” (https://vercel.com/geist/entity) Ours: a list of entity rows a person finds one of, opens and acts on: Customers, Agents, Skills, Apps, MCP servers, Mailboxes, domains, environment variables (a row with an `editor` expands into its form). Its rows are a `RecordList`'s, so a row has a mark, a name over a muted line and at most three facts; anything wider is not this page. “Projects”: Vercel's Projects page stands a column of titled cards (Usage, Alerts, Recent Previews) at the left of its list. (https://vercel.com/dashboard) Ours: Customers and Partners use the full-width list, with actionable attention above the toolbar when present. Business summaries belong on Dashboard and Analytics. A rail remains available for context that belongs to the collection itself, such as the selected Library hub.",
|
|
67
67
|
instead: "“For tabular data with sortable columns and shared row shape, use `Table` instead.” (https://vercel.com/geist/entity) Ours: records compared across columns, read by their headings, are a `DataTable` under the page's own title and toolbar. A list inside another page's section is a `RecordList` with its `heading`.",
|
|
68
68
|
behaviour: "With a `rail`, the toolbar spans the page and under it stand two columns from 1280 px: the rail, 300 px, then the records' card, its top level with the rail's first title and named by the page's title alone, never a second heading, and the records' rows are `RecordList`'s `line` rows; below 1280 px the records come first and the rail follows them. Each rail card has its title above it at 16 px, an optional 44 px muted summary row with its one outline button at its end (a button never stands in a row of its own, so a card with an `action` has a `summary`), then its items: a figure is one 36 px row, its title and its number at the trailing edge; a record is its 24 px mark, a title over a muted line that wraps to a second before it is cut, and a figure or a status at its end, the whole item opening its record; a card with no items draws its `empty` inside it as one 44 px row like an item. While the rail's read is in flight a card's `items` are undefined and it holds its place with three placeholder lines, so the two columns stand from the first frame; a rail whose read `failed` is one card saying so, and the records beside it stay. Under the title sits only the `description`, when the collection's kind needs explaining; otherwise nothing. The title row holds at most one secondary, the primary, then the three dots, which open only for two commands or more. The primary stays in the title row whether the collection is empty or not, filled, as Vercel's Flags keeps Create Flag; a first use repeats it as the filled button in its card. One toolbar holds the search, which grows, then the filters, then the sort; it shows while there are records or a search or filter is set, and is glass only where the rows scroll under it. While a new search, filter or sort is read, the toolbar is busy and, after a second, shows the one waiting line, while the last rows stay. The rows, their states and their loading are the RecordList's; no match is offered only while a search or filter is set.",
|
|
69
69
|
words: '“For multi-facet filters use the plural template `No {Items} Match Your Filters` and suggest widening or clearing.” (https://vercel.com/geist/empty-state) Ours: every string is the product\'s, in sentence case. The title names the collection in the plural ("Agents"); the search says what it finds ("Find a skill"); no match says what found nothing and offers to clear it ("Clear search", "Clear filters").',
|
|
@@ -839,17 +839,6 @@ export const USAGE = [
|
|
|
839
839
|
words: '"`<CommandMenu.Item>` children are Title Case verb phrases (`Deploy Project`, `Invite Team Member`). Avoid navigation phrasing like `Go to project page`; CommandMenu commands act, not browse." (https://vercel.com/geist/command-menu) "`CommandMenuPage.label` is Title Case and names the scope (`Projects`, `Team Settings`)." (https://vercel.com/geist/command-menu) "`CommandMenuPage.placeholder` is sentence case, action-oriented, and ends with `…` (`Search projects…`, `Type a command or search…`). Bare `Search…` is wrong because it doesn’t name the scope." (https://vercel.com/geist/command-menu) "`<CommandMenu.Group heading>` is Title Case, 1–2 words (`Actions`, `Recent`)." (https://vercel.com/geist/command-menu) Ours: groups are plural nouns in sentence case (*Agents*, *Go to*), one or two words. Items are names, or verb and noun for a creation page (*New Agent*), because the dialog goes to places. The placeholder names what is searched, never a bare "Search". No match quotes the query.',
|
|
840
840
|
access: '"Use `aria-live="polite"` on the result count so screen readers hear how the list narrows as the user types." (https://vercel.com/geist/command-menu) "Up/Down arrows move highlight, Enter activates, Escape closes. Backspace at an empty input pops the page stack." (https://vercel.com/geist/command-menu) "Display each item’s `keybind` as a `Kbd` slot so the shortcut is discoverable to sighted users and announced as a label to screen readers." (https://vercel.com/geist/command-menu) Ours: a dialog with a screen-reader `title` and `description`, both required; the *Esc* key is a button named by `closeLabel`, which is required; the field is a combobox over a listbox; the highlighted item is `aria-selected`. A polite live region reads `resultCount` as the list narrows, and it is required. `CommandInput` requires its `placeholder`, `CommandGroup` its `heading` and `CommandItem` its `onSelect`, so no field, group or row is left unnamed or inert; a row with no group stands outside a `CommandGroup`. A shortcut is a `CommandShortcut`, drawn as `kbd` elements. With no pages there is no stack for Backspace to pop.',
|
|
841
841
|
},
|
|
842
|
-
{
|
|
843
|
-
name: "DesktopAppShell",
|
|
844
|
-
module: "desktop-shell",
|
|
845
|
-
family: "Navigation",
|
|
846
|
-
summary: "A desktop window's frame: title bar, rails, resizable panes and status bar.",
|
|
847
|
-
when: "A desktop product's whole window: Nadia's left column (the Agents list, then an Agent's sections behind *‹ Agents*), its workspace and its side panes.",
|
|
848
|
-
instead: "The Portal's column is `PortalSidebarFrame` inside its `Sidebar`. Both draw their rows with the same `SidebarMenuButton` and end with the same `AccountMenu`.",
|
|
849
|
-
behaviour: "One 44 px band shares the window buttons and the window's commands. The workspace splits into resizable panes; the secondary pane and the inspector rail appear only when given. Each Agent row is her orb, name and one line.",
|
|
850
|
-
words: "Every pane label is the product's word for what it holds. An Agent's line says her job in under six words: *Writes quotes from the price list*.",
|
|
851
|
-
access: "Each pane and rail is a labelled region; the orb beside a name is decorative.",
|
|
852
|
-
},
|
|
853
842
|
{
|
|
854
843
|
name: "Footer",
|
|
855
844
|
module: "footer",
|
|
@@ -1312,17 +1301,6 @@ export const USAGE = [
|
|
|
1312
1301
|
words: '"Lead with the entity name as a Title Case heading and one identifying line in sentence case underneath (team slug, owner, deployment URL)." "Follow with 2–4 metadata rows of `Label: value`." "Keys are Title Case noun phrases (`Last Active`, `Created`, `Plan`); values follow the same formatting rules as table cells." "Use the em-dash character `—` for unknown values, never `N/A` or `null`." "Don’t restate what the trigger already showed." "If the row already renders the deployment URL, don’t repeat it as the first card line." (https://vercel.com/geist/context-card) Ours: the name and the keys are in sentence case (*Last active*). A time\'s card leads with the relative label, and its trigger keeps its verb sentence: *Updated 3 hours ago*.',
|
|
1313
1302
|
access: '"The trigger keeps its own accessible name; the card is supplementary and shouldn’t replace it." "Card content is reachable by keyboard once the trigger has focus; Escape closes the card and returns focus to the trigger." (https://vercel.com/geist/context-card) Ours: the trigger is a real element (a `time` with its `datetime` for a moment), so the facts never depend on hover. Keyboard opening is tested, not assumed.',
|
|
1314
1303
|
},
|
|
1315
|
-
{
|
|
1316
|
-
name: "LabelledPicture",
|
|
1317
|
-
module: "picture-label",
|
|
1318
|
-
family: "Feedback",
|
|
1319
|
-
summary: "A failure page's picture with its label, the way a museum labels a work.",
|
|
1320
|
-
when: "A page that cannot show what was asked for: an address or record that is not there (absence), or a request the product stopped (fault). `PictureLabel` is its label.",
|
|
1321
|
-
instead: "For one region that failed inside a working page use `EmptyState failed`; the rest of the page stays. Never turn the whole page into an error because one card failed.",
|
|
1322
|
-
behaviour: "Picture 256 px, 320 from sm, 384 from lg. The label stands centred under the picture at every width, on the same centre line as the words below. Still.",
|
|
1323
|
-
words: "Never apologise, never name the mechanism. The label's title says what the figure in the picture is doing, which is the page's one joke; the second line, in mono, gives its materials and year.",
|
|
1324
|
-
access: "The picture is decorative; the label is a `figcaption`, read once. The page's heading is its `h1`; its actions are real links.",
|
|
1325
|
-
},
|
|
1326
1304
|
{
|
|
1327
1305
|
name: "MessageNotice",
|
|
1328
1306
|
module: "message-notice",
|
|
@@ -1616,7 +1594,7 @@ export const USAGE = [
|
|
|
1616
1594
|
summary: "One total over time, each bar split by entity; with `share`, one bar split to 100%.",
|
|
1617
1595
|
when: "How a total moved over time split by Customer, member account or model; with `share`, what part of one total each holds, with no time axis.",
|
|
1618
1596
|
instead: "For a continuous volume in three series or fewer use `ChartAreaStacked`. Two measures side by side use `ChartBarMultiple`. Exact lookup is a table.",
|
|
1619
|
-
behaviour: 'Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.',
|
|
1597
|
+
behaviour: 'Stacked in series order, bottom segment rounded below and top above at 4 px, bars at most 48 px. The summary variant has square bars and no dot legend: its adjacent ChartRanking identifies the series with share bars. The Portal names five entities and folds the rest into "Everything else". The share plot is 64 px, legend included.',
|
|
1620
1598
|
words: 'Entity names as the reader knows them, never ids. The neutral remainder is "Everything else". Values through the page\'s shared money formatter.',
|
|
1621
1599
|
access: "The plot is an image named by the card title; the tooltip and legend are read with it. The share bar sits above the full-width table that carries each figure.",
|
|
1622
1600
|
},
|
|
@@ -1627,7 +1605,7 @@ export const USAGE = [
|
|
|
1627
1605
|
summary: "The card every chart in the kit renders: one header, the summary, the plot, its legend and the reading's time. The plots (`ChartBarStacked`, `ChartAreaStacked`, `ChartBarMultiple`, `ChartBarHorizontal`) hold only their own plot; a page never builds a chart card frame by hand.",
|
|
1628
1606
|
when: "Every chart and every reading built around one: the frame a page never builds by hand. A chart is a named section of its page.",
|
|
1629
1607
|
instead: "A single figure is a `KpiCard`, never nested inside a chart. A ranking beside the plot goes in the card's `aside`, not a second card.",
|
|
1630
|
-
behaviour: "
|
|
1608
|
+
behaviour: "The default header puts controls at the trailing edge on wide cards, below the title on narrow cards. The summary variant keeps controls immediately after the title, the owner link at the trailing edge, and the total and period above the plot. The ranking sits beside the plot only when the card itself reaches 48 rem; narrower cards keep a full-width plot and put the ranking below it. Controls wrap on narrow cards. An empty dataset shows its `emptyState` in the plot's place. The footer carries the reading time and at most one command on that reading.",
|
|
1631
1609
|
words: 'Title names the measure and its split: "Model spend by Customer". Period as dates. The link: "Explore", or "Open in Analytics" where the owner is another page. Footer: the reading\'s time, "Updated 4 minutes ago" or "Read at 12:42". Sentence case throughout.',
|
|
1632
1610
|
access: "The title is a heading at the page's level (default 2) and labels the plot. The plot is focusable and shows the 2 px focus outline only on keyboard focus.",
|
|
1633
1611
|
},
|
|
@@ -1642,6 +1620,17 @@ export const USAGE = [
|
|
|
1642
1620
|
words: "None of its own: series labels come from the config the plot builds from the page's words.",
|
|
1643
1621
|
access: "The plot it holds is named by the card title through `aria-labelledby`; Recharts' accessibility layer makes it keyboard focusable.",
|
|
1644
1622
|
},
|
|
1623
|
+
{
|
|
1624
|
+
name: "ChartRanking",
|
|
1625
|
+
module: "chart-ranking",
|
|
1626
|
+
family: "Charts",
|
|
1627
|
+
summary: "The leading entities beside a usage chart, with the complete ranking one step away.",
|
|
1628
|
+
when: "A chart summary needs a ranking beside its plot.",
|
|
1629
|
+
instead: "Exact breakdown columns belong in a DataTable. This list compares shares of one nonnegative total.",
|
|
1630
|
+
behaviour: "Shows the first five rows and an optional aggregate remainder, each identity and figure above its coloured share bar. The remainder identifies the neutral plot segment; View all expands the named entities rather than repeating their aggregate. View all opens the complete supplied ranking in a dialog. Rows arrive already sorted and share one total and colour map with the chart.",
|
|
1631
|
+
words: "The product supplies the title, metric description, View all count, dialog description and close label.",
|
|
1632
|
+
access: "Each share bar is named by its entity. The dialog is named by the ranking title and retains the selected period and metric.",
|
|
1633
|
+
},
|
|
1645
1634
|
{
|
|
1646
1635
|
name: "ChartSparkline",
|
|
1647
1636
|
module: "chart-sparkline",
|
|
@@ -1835,7 +1824,7 @@ export const USAGE = [
|
|
|
1835
1824
|
family: "Other",
|
|
1836
1825
|
summary: "Panels a person resizes by dragging the handle between them.",
|
|
1837
1826
|
when: "Side-by-side panes whose balance a person sets: a conversation and its side panel. Nadia's side panel is this, with the window's grid column as the group; it is not a hand-made separator.",
|
|
1838
|
-
instead: "The product frame's sidebar resizes through `Sidebar`'s `resize` handle
|
|
1827
|
+
instead: "The product frame's sidebar resizes through `Sidebar`'s `resize` handle. A width a person never changes is a plain grid column. A window too narrow for the panes side by side gets a compact alternative, one pane at a time, instead of squeezed panes.",
|
|
1839
1828
|
behaviour: 'The handle moves on drag and on arrow keys, and returns the panels to their default size on a double click; each panel keeps its minimum, set where its content still reads, and its maximum. A number is pixels (`minSize={352}`), a string without a unit is a percentage (`defaultSize="60"`), and `"20rem"` and `"40vw"` are read as written, so a panel that must keep a readable width is set in pixels and the pane beside it takes the rest. The handle is a 1 px line with a 4 px wide hit area centred on it; it takes the ring colour while hovered, dragged or focused, and `withHandle` adds a grip for a handle that must be found. Colour: neutral until it is touched, then the ring colour, and nothing else. The group holds sizes only while it is mounted; the product owns persisting them.',
|
|
1840
1829
|
words: "Required: the handle's name, a verb phrase from the product's catalogue: *Resize the side panel*. A panel has none of its own.",
|
|
1841
1830
|
access: "The handle is the resizable library's focusable `separator` with its value, named by the `aria-label` the type requires; the arrow keys move it and Home and End take it to the ends of its range.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nadicodeai/ui",
|
|
3
|
-
"version": "12.1.
|
|
3
|
+
"version": "12.1.117",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -77,13 +77,13 @@
|
|
|
77
77
|
"test:distribution": "node ../../tools/release/package-smoke-test.mjs"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@assistant-ui/react": "0.15.
|
|
81
|
-
"@assistant-ui/react-markdown": "0.14.
|
|
80
|
+
"@assistant-ui/react": "0.15.28",
|
|
81
|
+
"@assistant-ui/react-markdown": "0.14.22",
|
|
82
82
|
"@base-ui/react": "^1.9.0",
|
|
83
|
-
"@iconify-icons/logos": "^2.0.
|
|
83
|
+
"@iconify-icons/logos": "^2.0.3",
|
|
84
84
|
"@iconify/react": "^6.0.2",
|
|
85
|
-
"@nadicodeai/design-system": "12.1.
|
|
86
|
-
"@tanstack/react-table": "^9.
|
|
85
|
+
"@nadicodeai/design-system": "12.1.117",
|
|
86
|
+
"@tanstack/react-table": "^9.3.1",
|
|
87
87
|
"@vgpu/wgsl": "0.6.0",
|
|
88
88
|
"class-variance-authority": "^0.7.1",
|
|
89
89
|
"clsx": "^2.1.1",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"next-themes": "^0.4.6",
|
|
97
97
|
"qrcode": "^1.5.4",
|
|
98
98
|
"react-day-picker": "^10.0.2",
|
|
99
|
-
"react-resizable-panels": "^4.14.
|
|
99
|
+
"react-resizable-panels": "^4.14.5",
|
|
100
100
|
"recharts": "^3.10.1",
|
|
101
101
|
"remark-gfm": "^4.0.1",
|
|
102
102
|
"sonner": "^2.0.8",
|
|
@@ -113,25 +113,28 @@
|
|
|
113
113
|
"tailwindcss": "^4.3.3"
|
|
114
114
|
},
|
|
115
115
|
"devDependencies": {
|
|
116
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
116
117
|
"@lobehub/icons-static-svg": "^1.95.1",
|
|
117
118
|
"@nadicodeai/eslint-plugin": "*",
|
|
118
119
|
"@stryker-mutator/core": "10.0.0",
|
|
119
120
|
"@stryker-mutator/vitest-runner": "10.0.0",
|
|
120
121
|
"@tailwindcss/postcss": "^4.3.3",
|
|
121
122
|
"@testing-library/react": "^16.3.3",
|
|
122
|
-
"@testing-library/user-event": "^14.6.
|
|
123
|
+
"@testing-library/user-event": "^14.6.8",
|
|
123
124
|
"@types/react": "19.3.0",
|
|
124
125
|
"@types/react-dom": "19.3.0",
|
|
125
126
|
"axe-core": "^4.14.0",
|
|
126
127
|
"esbuild": "^0.28.2",
|
|
127
128
|
"eslint": "^9.39.4",
|
|
128
|
-
"jsdom": "^30.1.
|
|
129
|
-
"postcss": "^8.5.
|
|
129
|
+
"jsdom": "^30.1.3",
|
|
130
|
+
"postcss": "^8.5.30",
|
|
131
|
+
"publint": "^0.3.25",
|
|
130
132
|
"react": "19.3.1",
|
|
131
133
|
"react-dom": "19.3.1",
|
|
132
134
|
"shadcn": "4.21.5",
|
|
133
135
|
"tailwindcss": "^4.3.3",
|
|
134
136
|
"typescript": "^6",
|
|
137
|
+
"typescript-native": "npm:typescript@7.0.2",
|
|
135
138
|
"vitest": "^5.0.0"
|
|
136
139
|
}
|
|
137
140
|
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
type DesktopAppShellProps = Omit<React.ComponentProps<"section">, "title"> & {
|
|
3
|
-
title?: React.ReactNode;
|
|
4
|
-
titlebar?: React.ReactNode;
|
|
5
|
-
titlebarActions?: React.ReactNode;
|
|
6
|
-
activityRail?: React.ReactNode;
|
|
7
|
-
inspectorRail?: React.ReactNode;
|
|
8
|
-
secondaryPane?: React.ReactNode;
|
|
9
|
-
statusbar?: React.ReactNode;
|
|
10
|
-
children: React.ReactNode;
|
|
11
|
-
activityRailLabel?: string;
|
|
12
|
-
primaryPaneLabel?: string;
|
|
13
|
-
secondaryPaneLabel?: string;
|
|
14
|
-
inspectorRailLabel?: string;
|
|
15
|
-
secondaryResizeLabel?: string;
|
|
16
|
-
inspectorResizeLabel?: string;
|
|
17
|
-
primaryPaneSize?: number;
|
|
18
|
-
secondaryPaneSize?: number;
|
|
19
|
-
inspectorPaneSize?: number;
|
|
20
|
-
titlebarClassName?: string;
|
|
21
|
-
bodyClassName?: string;
|
|
22
|
-
primaryPaneClassName?: string;
|
|
23
|
-
secondaryPaneClassName?: string;
|
|
24
|
-
inspectorRailClassName?: string;
|
|
25
|
-
statusbarClassName?: string;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* A desktop window's frame: title bar, rails, resizable panes and status bar.
|
|
29
|
-
*
|
|
30
|
-
* @family Navigation
|
|
31
|
-
* @when A desktop product's whole window: Nadia's left column (the Agents list, then an Agent's
|
|
32
|
-
* sections behind *‹ Agents*), its workspace and its side panes.
|
|
33
|
-
* @instead The Portal's column is `PortalSidebarFrame` inside its `Sidebar`. Both draw their
|
|
34
|
-
* rows with the same `SidebarMenuButton` and end with the same `AccountMenu`.
|
|
35
|
-
* @behaviour One 44 px band shares the window buttons and the window's commands. The workspace
|
|
36
|
-
* splits into resizable panes; the secondary pane and the inspector rail appear only when given.
|
|
37
|
-
* Each Agent row is her orb, name and one line.
|
|
38
|
-
* @words Every pane label is the product's word for what it holds. An Agent's line says her job in
|
|
39
|
-
* under six words: *Writes quotes from the price list*.
|
|
40
|
-
* @access Each pane and rail is a labelled region; the orb beside a name is decorative.
|
|
41
|
-
*/
|
|
42
|
-
declare function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel, primaryPaneLabel, secondaryPaneLabel, inspectorRailLabel, secondaryResizeLabel, inspectorResizeLabel, primaryPaneSize, secondaryPaneSize, inspectorPaneSize, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }: DesktopAppShellProps): React.JSX.Element;
|
|
43
|
-
export { DesktopAppShell };
|
|
44
|
-
export type { DesktopAppShellProps };
|
|
45
|
-
//# sourceMappingURL=desktop-shell.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"desktop-shell.d.ts","sourceRoot":"","sources":["../../src/components/desktop-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,KAAK,oBAAoB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,iBAAS,eAAe,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,EACb,SAAS,EACT,QAAQ,EACR,iBAA8B,EAC9B,gBAAsC,EACtC,kBAA0C,EAC1C,kBAAgC,EAChC,oBAAuD,EACvD,oBAA6C,EAC7C,eAA2D,EAC3D,iBAA2C,EAC3C,iBAAsB,EACtB,SAAS,EACT,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyGtB;AAED,OAAO,EAAE,eAAe,EAAE,CAAC;AAC3B,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { cn } from "../lib/utils.js";
|
|
4
|
-
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./resizable.js";
|
|
5
|
-
/**
|
|
6
|
-
* A desktop window's frame: title bar, rails, resizable panes and status bar.
|
|
7
|
-
*
|
|
8
|
-
* @family Navigation
|
|
9
|
-
* @when A desktop product's whole window: Nadia's left column (the Agents list, then an Agent's
|
|
10
|
-
* sections behind *‹ Agents*), its workspace and its side panes.
|
|
11
|
-
* @instead The Portal's column is `PortalSidebarFrame` inside its `Sidebar`. Both draw their
|
|
12
|
-
* rows with the same `SidebarMenuButton` and end with the same `AccountMenu`.
|
|
13
|
-
* @behaviour One 44 px band shares the window buttons and the window's commands. The workspace
|
|
14
|
-
* splits into resizable panes; the secondary pane and the inspector rail appear only when given.
|
|
15
|
-
* Each Agent row is her orb, name and one line.
|
|
16
|
-
* @words Every pane label is the product's word for what it holds. An Agent's line says her job in
|
|
17
|
-
* under six words: *Writes quotes from the price list*.
|
|
18
|
-
* @access Each pane and rail is a labelled region; the orb beside a name is decorative.
|
|
19
|
-
*/
|
|
20
|
-
function DesktopAppShell({ title, titlebar, titlebarActions, activityRail, inspectorRail, secondaryPane, statusbar, children, activityRailLabel = "Activity", primaryPaneLabel = "Primary workspace", secondaryPaneLabel = "Secondary workspace", inspectorRailLabel = "Inspector", secondaryResizeLabel = "Resize the secondary workspace", inspectorResizeLabel = "Resize the inspector", primaryPaneSize = secondaryPane || inspectorRail ? 58 : 100, secondaryPaneSize = inspectorRail ? 24 : 36, inspectorPaneSize = 18, className, titlebarClassName, bodyClassName, primaryPaneClassName, secondaryPaneClassName, inspectorRailClassName, statusbarClassName, ...props }) {
|
|
21
|
-
return (_jsxs("section", { "data-slot": "desktop-app-shell", className: cn("flex h-svh min-h-0 flex-col overflow-hidden border bg-background text-foreground", className), ...props, children: [_jsxs("header", { "data-slot": "desktop-app-titlebar", className: cn("flex h-11 shrink-0 items-center justify-between gap-3 border-b bg-background px-3", titlebarClassName), children: [titlebar ?? (_jsx("div", { "data-slot": "desktop-app-titlebar-content", className: "flex min-w-0 flex-1 items-center gap-2", children: title && _jsx("p", { className: "m-0 truncate text-sm font-medium", children: title }) })), titlebarActions && (_jsx("div", { "data-slot": "desktop-app-titlebar-actions", className: "flex shrink-0 items-center gap-2", children: titlebarActions }))] }), _jsxs("div", { "data-slot": "desktop-app-body", className: cn("flex min-h-0 flex-1", bodyClassName), children: [activityRail && (_jsx("nav", { "data-slot": "desktop-app-activity-rail", "aria-label": activityRailLabel, className: "flex w-14 shrink-0 flex-col items-center gap-2 border-r bg-sidebar p-2 text-sidebar-foreground", children: activityRail })), _jsx("div", { "data-slot": "desktop-app-panes", className: "min-w-0 flex-1", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", className: "min-w-0 flex-1", children: [_jsx(ResizablePanel, { defaultSize: `${primaryPaneSize}%`, minSize: "30%", children: _jsx("section", { "data-slot": "desktop-app-primary-pane", "aria-label": primaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", primaryPaneClassName), children: children }) }), secondaryPane && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { "aria-label": secondaryResizeLabel, withHandle: true }), _jsx(ResizablePanel, { defaultSize: `${secondaryPaneSize}%`, minSize: "18%", children: _jsx("section", { "data-slot": "desktop-app-secondary-pane", "aria-label": secondaryPaneLabel, className: cn("h-full min-w-0 overflow-auto bg-background", secondaryPaneClassName), children: secondaryPane }) })] })), inspectorRail && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { "aria-label": inspectorResizeLabel, withHandle: true }), _jsx(ResizablePanel, { defaultSize: `${inspectorPaneSize}%`, minSize: "16%", maxSize: "36%", children: _jsx("aside", { "data-slot": "desktop-app-inspector-rail", "aria-label": inspectorRailLabel, className: cn("h-full min-w-0 overflow-auto bg-background", inspectorRailClassName), children: inspectorRail }) })] }))] }) })] }), statusbar && (_jsx("footer", { "data-slot": "desktop-app-statusbar", className: cn("flex min-h-8 shrink-0 items-center justify-between gap-3 border-t bg-background px-3 text-xs text-muted-foreground", statusbarClassName), children: statusbar }))] }));
|
|
22
|
-
}
|
|
23
|
-
export { DesktopAppShell };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* A failure page's picture with its label, the way a museum labels a work.
|
|
4
|
-
*
|
|
5
|
-
* DESIGN.md: [Failure surfaces](../../../design-system/DESIGN.md#failure-surfaces).
|
|
6
|
-
*
|
|
7
|
-
* @family Feedback
|
|
8
|
-
* @when A page that cannot show what was asked for: an address or record that is not there
|
|
9
|
-
* (absence), or a request the product stopped (fault). `PictureLabel` is its label.
|
|
10
|
-
* @instead For one region that failed inside a working page use `EmptyState failed`; the rest of
|
|
11
|
-
* the page stays. Never turn the whole page into an error because one card failed.
|
|
12
|
-
* @behaviour Picture 256 px, 320 from sm, 384 from lg. The label stands centred under the picture at
|
|
13
|
-
* every width, on the same centre line as the words below. Still.
|
|
14
|
-
* @words Never apologise, never name the mechanism. The label's title says what the figure in the
|
|
15
|
-
* picture is doing, which is the page's one joke; the second line, in mono, gives its materials and
|
|
16
|
-
* year.
|
|
17
|
-
* @access The picture is decorative; the label is a `figcaption`, read once. The page's heading is
|
|
18
|
-
* its `h1`; its actions are real links.
|
|
19
|
-
*/
|
|
20
|
-
export declare function LabelledPicture({ children, label, className, }: {
|
|
21
|
-
children: ReactNode;
|
|
22
|
-
/** The `PictureLabel`, or a boundary that streams it in. */
|
|
23
|
-
label: ReactNode;
|
|
24
|
-
className?: string;
|
|
25
|
-
}): import("react").JSX.Element;
|
|
26
|
-
export declare function PictureLabel({ title, details }: {
|
|
27
|
-
title: string;
|
|
28
|
-
details: string;
|
|
29
|
-
}): import("react").JSX.Element;
|
|
30
|
-
//# sourceMappingURL=picture-label.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"picture-label.d.ts","sourceRoot":"","sources":["../../src/components/picture-label.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,KAAK,EACL,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,4DAA4D;IAC5D,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAUA;AAED,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,+BASlF"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from "../lib/utils.js";
|
|
3
|
-
/**
|
|
4
|
-
* A failure page's picture with its label, the way a museum labels a work.
|
|
5
|
-
*
|
|
6
|
-
* DESIGN.md: [Failure surfaces](../../../design-system/DESIGN.md#failure-surfaces).
|
|
7
|
-
*
|
|
8
|
-
* @family Feedback
|
|
9
|
-
* @when A page that cannot show what was asked for: an address or record that is not there
|
|
10
|
-
* (absence), or a request the product stopped (fault). `PictureLabel` is its label.
|
|
11
|
-
* @instead For one region that failed inside a working page use `EmptyState failed`; the rest of
|
|
12
|
-
* the page stays. Never turn the whole page into an error because one card failed.
|
|
13
|
-
* @behaviour Picture 256 px, 320 from sm, 384 from lg. The label stands centred under the picture at
|
|
14
|
-
* every width, on the same centre line as the words below. Still.
|
|
15
|
-
* @words Never apologise, never name the mechanism. The label's title says what the figure in the
|
|
16
|
-
* picture is doing, which is the page's one joke; the second line, in mono, gives its materials and
|
|
17
|
-
* year.
|
|
18
|
-
* @access The picture is decorative; the label is a `figcaption`, read once. The page's heading is
|
|
19
|
-
* its `h1`; its actions are real links.
|
|
20
|
-
*/
|
|
21
|
-
export function LabelledPicture({ children, label, className, }) {
|
|
22
|
-
return (_jsxs("figure", { className: cn("m-0 grid w-full max-w-4xl justify-items-center gap-4", className), "data-slot": "labelled-picture", children: [_jsx("div", { children: children }), _jsx("figcaption", { className: "max-w-72 text-center", children: label })] }));
|
|
23
|
-
}
|
|
24
|
-
export function PictureLabel({ title, details }) {
|
|
25
|
-
return (_jsxs("span", { className: "grid gap-1", children: [_jsx("span", { className: "text-body-sm text-balance font-medium", children: title }), _jsx("span", { className: "font-label-mono text-label-mono text-balance text-muted-foreground", children: details })] }));
|
|
26
|
-
}
|