astryx-dracula 0.5.0 → 0.6.2
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/BRAND.md +3 -3
- package/README.md +7 -4
- package/USAGE.md +49 -49
- package/astryx-dracula.d.ts +2 -2
- package/astryx-dracula.js +25 -9
- package/astryx-dracula.variants.d.ts +2 -2
- package/astryx.integration.mjs +1 -1
- package/icons.mjs +21 -17
- package/icons.tsx +69 -62
- package/package.json +125 -120
- package/shared/auth-chrome-config.ts +6 -6
- package/shared/auth-chrome.tsx +143 -144
- package/shared/auth-copy.ts +14 -14
- package/shared/chaptered-doc-config.ts +48 -51
- package/shared/chaptered-doc.tsx +267 -289
- package/shared/chart-hues.ts +25 -10
- package/shared/chart-labels.tsx +31 -30
- package/shared/chart-legend.tsx +55 -56
- package/shared/chart-panel-style.ts +3 -3
- package/shared/data-bar.tsx +97 -102
- package/shared/format-money.ts +1 -1
- package/shared/gallery-image.ts +6 -6
- package/shared/login-demo.ts +1 -1
- package/shared/metric-card.tsx +101 -105
- package/shared/metric-delta.tsx +28 -27
- package/shared/order-desk.tsx +205 -216
- package/shared/revenue-chart.tsx +145 -165
- package/shared/scene-castle.tsx +206 -291
- package/shared/scene-frame.tsx +33 -32
- package/shared/scene-hues.ts +17 -17
- package/shared/scene-tile.tsx +88 -92
- package/shared/settings-data.ts +119 -125
- package/shared/settings-rows.tsx +122 -159
- package/shared/sparkline.tsx +75 -88
- package/shared/sso-icons.tsx +10 -22
- package/shared/stars.tsx +16 -25
- package/templates/ai-chat-landing.template.mjs +5 -4
- package/templates/ai-chat-landing.tsx +473 -460
- package/templates/ai-chat.template.mjs +5 -4
- package/templates/ai-chat.tsx +543 -612
- package/templates/blank.template.mjs +5 -4
- package/templates/blank.tsx +18 -14
- package/templates/centered-hero.template.mjs +5 -4
- package/templates/centered-hero.tsx +55 -68
- package/templates/classic-gallery.template.mjs +5 -4
- package/templates/classic-gallery.tsx +97 -104
- package/templates/contact-form.template.mjs +5 -4
- package/templates/contact-form.tsx +247 -282
- package/templates/dashboard-portfolio.template.mjs +5 -4
- package/templates/dashboard-portfolio.tsx +717 -548
- package/templates/dashboard.template.mjs +5 -4
- package/templates/dashboard.tsx +596 -567
- package/templates/detail-page.template.mjs +5 -4
- package/templates/detail-page.tsx +546 -603
- package/templates/documentation-design.template.mjs +5 -4
- package/templates/documentation-design.tsx +231 -243
- package/templates/documentation-technical.template.mjs +5 -4
- package/templates/documentation-technical.tsx +236 -239
- package/templates/documentation.template.mjs +5 -4
- package/templates/documentation.tsx +267 -279
- package/templates/editor.template.mjs +5 -4
- package/templates/editor.tsx +844 -877
- package/templates/file-explorer.template.mjs +5 -4
- package/templates/file-explorer.tsx +566 -590
- package/templates/form-two-column.template.mjs +5 -4
- package/templates/form-two-column.tsx +195 -210
- package/templates/gallery-hero.template.mjs +5 -4
- package/templates/gallery-hero.tsx +93 -114
- package/templates/ide.template.mjs +5 -4
- package/templates/ide.tsx +407 -453
- package/templates/incident-console.template.mjs +5 -4
- package/templates/incident-console.tsx +593 -575
- package/templates/kanban-board.template.mjs +5 -4
- package/templates/kanban-board.tsx +665 -683
- package/templates/library.template.mjs +5 -4
- package/templates/library.tsx +409 -430
- package/templates/login-card.template.mjs +5 -4
- package/templates/login-card.tsx +63 -72
- package/templates/login-split.template.mjs +5 -4
- package/templates/login-split.tsx +192 -193
- package/templates/login-sso.template.mjs +5 -4
- package/templates/login-sso.tsx +257 -258
- package/templates/login.template.mjs +5 -4
- package/templates/login.tsx +53 -49
- package/templates/messaging-shell.template.mjs +5 -4
- package/templates/messaging-shell.tsx +556 -574
- package/templates/mixed-gallery.template.mjs +5 -4
- package/templates/mixed-gallery.tsx +60 -58
- package/templates/payment-form.template.mjs +5 -4
- package/templates/payment-form.tsx +882 -991
- package/templates/product-detail.template.mjs +5 -4
- package/templates/product-detail.tsx +261 -272
- package/templates/product-gallery.template.mjs +5 -4
- package/templates/product-gallery.tsx +126 -137
- package/templates/product-tour.template.mjs +5 -4
- package/templates/product-tour.tsx +741 -773
- package/templates/settings-dialog.template.mjs +5 -4
- package/templates/settings-dialog.tsx +688 -717
- package/templates/settings-sidebar.template.mjs +5 -4
- package/templates/settings-sidebar.tsx +762 -807
- package/templates/settings.template.mjs +5 -4
- package/templates/settings.tsx +289 -304
- package/templates/shell-nav.template.mjs +5 -4
- package/templates/shell-nav.tsx +212 -219
- package/templates/shell-side-nav.template.mjs +5 -4
- package/templates/shell-side-nav.tsx +135 -157
- package/templates/shell-top-nav.template.mjs +5 -4
- package/templates/shell-top-nav.tsx +182 -203
- package/templates/side-gallery.template.mjs +5 -4
- package/templates/side-gallery.tsx +85 -90
- package/templates/table-grouped.template.mjs +5 -4
- package/templates/table-grouped.tsx +1000 -1053
- package/templates/table-page-chart.template.mjs +5 -4
- package/templates/table-page-chart.tsx +400 -398
- package/templates/table-page-heatmap-status.template.mjs +5 -4
- package/templates/table-page-heatmap-status.tsx +483 -512
- package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
- package/templates/table-page-shoe-store-heatmap.tsx +748 -746
- package/templates/table-page.template.mjs +5 -4
- package/templates/table-page.tsx +396 -405
- package/templates/table.template.mjs +5 -4
- package/templates/table.tsx +92 -93
- package/templates/tech-report.template.mjs +5 -4
- package/templates/tech-report.tsx +1316 -1304
- package/templates/theme-showcase.template.mjs +5 -4
- package/templates/theme-showcase.tsx +871 -951
- package/theme.css +35 -77
- package/theme.css.d.ts +9 -0
- package/tokens.css +373 -380
package/shared/chart-labels.tsx
CHANGED
|
@@ -3,42 +3,43 @@
|
|
|
3
3
|
// (nothing meaningful below 12px, ever). The mono family resolves from the
|
|
4
4
|
// `--font-family-mono` theme token, single-sourced with the body/code faces.
|
|
5
5
|
|
|
6
|
-
import type {ReactNode} from
|
|
6
|
+
import type { ReactNode } from "react";
|
|
7
7
|
|
|
8
|
-
export const CHART_LABEL_FILL =
|
|
8
|
+
export const CHART_LABEL_FILL = "var(--color-text-paragraph)";
|
|
9
9
|
export const CHART_LABEL_SIZE = 13;
|
|
10
10
|
|
|
11
11
|
interface ChartLabelProps {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
x: number | string;
|
|
13
|
+
y: number | string;
|
|
14
|
+
textAnchor?: "start" | "middle" | "end";
|
|
15
|
+
/** Defaults to the paragraph token; pass an explicit fill for values drawn
|
|
16
|
+
* on colored fills (e.g. in-cell heatmap counts).
|
|
17
|
+
*
|
|
18
|
+
* Deliberately NOT the chart-legend union: this paints TEXT, so its arms
|
|
19
|
+
* are a text role and the on-fill role, and neither is a --color-data-*
|
|
20
|
+
* var. Reusing the legend type here would reject the one use it exists
|
|
21
|
+
* for. */
|
|
22
|
+
fill?: `var(--color-text-${string})` | `var(--color-on-${string})`;
|
|
23
|
+
children: ReactNode;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function ChartLabel({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
x,
|
|
28
|
+
y,
|
|
29
|
+
textAnchor = "middle",
|
|
30
|
+
fill = CHART_LABEL_FILL,
|
|
31
|
+
children,
|
|
32
32
|
}: ChartLabelProps) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
return (
|
|
34
|
+
<text
|
|
35
|
+
x={x}
|
|
36
|
+
y={y}
|
|
37
|
+
textAnchor={textAnchor}
|
|
38
|
+
fontSize={CHART_LABEL_SIZE}
|
|
39
|
+
fill={fill}
|
|
40
|
+
fontFamily="var(--font-family-mono)"
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</text>
|
|
44
|
+
);
|
|
44
45
|
}
|
package/shared/chart-legend.tsx
CHANGED
|
@@ -21,21 +21,21 @@
|
|
|
21
21
|
//
|
|
22
22
|
// Not interactive. A legend is a key, not a control: no hover, no focus ring.
|
|
23
23
|
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import type {
|
|
24
|
+
import { HStack, StackItem, VStack } from "@astryxdesign/core/Stack";
|
|
25
|
+
import { Text } from "@astryxdesign/core/Text";
|
|
26
|
+
import type { ChartHue, DataColor } from "astryx-dracula/shared/chart-hues";
|
|
27
|
+
import type { ReactNode } from "react";
|
|
28
28
|
|
|
29
29
|
export interface ChartLegendEntry {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
/** REQUIRED. The hue never travels alone — this is the 1.4.1 contract. */
|
|
31
|
+
label: string;
|
|
32
|
+
/** A --color-data-* var, or a --color-background-* surface. Never a raw
|
|
33
|
+
* hex, never a --dracula-* primitive.
|
|
34
|
+
*
|
|
35
|
+
* The surface arm is not optional: a legend whose first row is a recessive
|
|
36
|
+
* surface is normal (the heatmap's zero cell), so a data-only type would
|
|
37
|
+
* reject the value the heatmap is supposed to paint. */
|
|
38
|
+
color: ChartHue | DataColor | `var(--color-background-${string})`;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Kept as a string-keyed fall-through on purpose, and DO NOT narrow it: call
|
|
@@ -47,53 +47,52 @@ export interface ChartLegendEntry {
|
|
|
47
47
|
// none does. The behaviour is correct; only the comment was wrong.
|
|
48
48
|
|
|
49
49
|
export interface ChartLegendProps {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
entries: readonly ChartLegendEntry[];
|
|
51
|
+
/** Spacing step between entries. @default 2 */
|
|
52
|
+
gap?: 1 | 2 | 3 | 4 | 6;
|
|
53
|
+
/** Accessible name for the legend as a group. */
|
|
54
|
+
label?: string;
|
|
55
|
+
/** Swatch size in px. @default 10 */
|
|
56
|
+
swatchSize?: number;
|
|
57
|
+
/** Caption under the legend, e.g. "Hourly intervals · trailing 24 hours". */
|
|
58
|
+
caption?: ReactNode;
|
|
59
|
+
/** Orientation. @default 'row' */
|
|
60
|
+
direction?: "row" | "column";
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
64
63
|
export function ChartLegend({
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
entries,
|
|
65
|
+
gap = 2,
|
|
66
|
+
swatchSize = 10,
|
|
67
|
+
label,
|
|
68
|
+
caption,
|
|
69
|
+
direction = "row",
|
|
71
70
|
}: ChartLegendProps) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
71
|
+
const Stack = direction === "row" ? HStack : VStack;
|
|
72
|
+
return (
|
|
73
|
+
<VStack gap={1}>
|
|
74
|
+
<Stack gap={gap} vAlign="center" role="list" aria-label={label}>
|
|
75
|
+
{entries.map((entry) => (
|
|
76
|
+
<HStack key={entry.label} gap={1} vAlign="center" role="listitem">
|
|
77
|
+
<StackItem
|
|
78
|
+
style={{
|
|
79
|
+
width: `${swatchSize}px`,
|
|
80
|
+
height: `${swatchSize}px`,
|
|
81
|
+
flexShrink: 0,
|
|
82
|
+
background: entry.color,
|
|
83
|
+
borderRadius: "var(--radius-inner)",
|
|
84
|
+
}}
|
|
85
|
+
/>
|
|
86
|
+
{/* supporting, not body: a legend label is metadata by the
|
|
88
87
|
typography doctrine, and it never carries a sentence the page
|
|
89
88
|
needs the reader to have. */}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
89
|
+
<Text type="supporting" color="secondary" hasTabularNumbers>
|
|
90
|
+
{entry.label}
|
|
91
|
+
</Text>
|
|
92
|
+
</HStack>
|
|
93
|
+
))}
|
|
94
|
+
</Stack>
|
|
95
|
+
{caption}
|
|
96
|
+
</VStack>
|
|
97
|
+
);
|
|
99
98
|
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// kit (dashboard, portfolio, chart, heatmap-status, shoe-store). Split from
|
|
3
3
|
// shared/revenue-chart.tsx so that file exports only components and React Fast
|
|
4
4
|
// Refresh stays intact; see shared/scene-hues.ts for the same reason.
|
|
5
|
-
import type {CSSProperties} from
|
|
5
|
+
import type { CSSProperties } from "react";
|
|
6
6
|
|
|
7
7
|
// One chart-panel look for every hand-drawn SVG chart panel in this wave's
|
|
8
8
|
// templates (dashboard, portfolio, chart, heatmap-status, shoe-store). Restate
|
|
9
9
|
// nowhere: theme Card variant work lands in wave 2.
|
|
10
10
|
export const CHART_PANEL_STYLE: CSSProperties = {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
backgroundColor: "var(--color-background)",
|
|
12
|
+
border: "var(--border-width) solid var(--color-separator)",
|
|
13
13
|
};
|
package/shared/data-bar.tsx
CHANGED
|
@@ -36,125 +36,120 @@
|
|
|
36
36
|
// Not interactive. A data bar is not a control, so it carries no hover channel
|
|
37
37
|
// and no focus ring; the inset-ring decision belongs to interactive surfaces.
|
|
38
38
|
|
|
39
|
-
import
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import type {ChartHue} from
|
|
39
|
+
import { HStack, StackItem, VStack } from "@astryxdesign/core/Stack";
|
|
40
|
+
import { Text } from "@astryxdesign/core/Text";
|
|
41
|
+
import type { CSSProperties } from "react";
|
|
42
|
+
import type { ChartHue, DataColor } from "./chart-hues";
|
|
43
43
|
|
|
44
44
|
export interface DataBarSegment {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
/** Stable key for the segment. */
|
|
46
|
+
id: string;
|
|
47
|
+
value: number;
|
|
48
|
+
/** MUST be a --color-data-categorical-* or --color-data-<family>-N var.
|
|
49
|
+
* Never a raw hex, never a --dracula-* primitive. Typed rather than
|
|
50
|
+
* documented: `string` made the rule a comment nobody could break. */
|
|
51
|
+
color: ChartHue | DataColor;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/** Minimum segment share, so a tiny non-zero value stays visible. */
|
|
55
55
|
const MIN_SEGMENT_PCT = 2;
|
|
56
56
|
|
|
57
57
|
export interface DataBarProps {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
58
|
+
/** Accessible name. Required — a bar with no name is an unlabelled graphic. */
|
|
59
|
+
label: string;
|
|
60
|
+
segments: readonly DataBarSegment[];
|
|
61
|
+
/** Bar thickness in px. @default 12 */
|
|
62
|
+
height?: number;
|
|
63
|
+
/** Show the summed value under the bar. @default false */
|
|
64
|
+
hasValueLabel?: boolean;
|
|
65
|
+
/** Formats the summed value. @default toLocaleString() */
|
|
66
|
+
formatValue?: (total: number) => string;
|
|
67
|
+
/** Gap between segments as a spacing-scale step. @default 0 */
|
|
68
|
+
gap?: 0 | 0.5 | 1 | 1.5 | 2 | 3;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const segmentStyle: CSSProperties = {
|
|
72
|
-
|
|
72
|
+
borderRadius: "var(--radius-inner)",
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
export function DataBar({
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
label,
|
|
77
|
+
segments,
|
|
78
|
+
height = 12,
|
|
79
|
+
hasValueLabel = false,
|
|
80
|
+
formatValue = (total) => total.toLocaleString(),
|
|
81
|
+
gap = 0,
|
|
82
82
|
}: DataBarProps) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
};
|
|
99
|
-
})
|
|
100
|
-
.filter((segment): segment is NonNullable<typeof segment> => segment !== null);
|
|
83
|
+
// Negative values are not a magnitude and are clamped out before the ratio is
|
|
84
|
+
// taken: summing a negative into `total` inflates every other segment's
|
|
85
|
+
// share and can push the bar past 100%. An empty or all-zero bar falls
|
|
86
|
+
// through to the track fill below.
|
|
87
|
+
const total = segments.reduce((sum, segment) => sum + Math.max(0, segment.value), 0);
|
|
88
|
+
const visible = segments
|
|
89
|
+
.map((segment) => {
|
|
90
|
+
if (segment.value <= 0) return null;
|
|
91
|
+
return {
|
|
92
|
+
id: segment.id,
|
|
93
|
+
color: segment.color,
|
|
94
|
+
share: (segment.value / total) * 100,
|
|
95
|
+
};
|
|
96
|
+
})
|
|
97
|
+
.filter((segment): segment is NonNullable<typeof segment> => segment !== null);
|
|
101
98
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const drawn = visible
|
|
121
|
-
.map((segment, index) => ({...segment, width: widths[index]}))
|
|
122
|
-
.filter(segment => segment.width > 0);
|
|
99
|
+
// A tiny non-zero value must stay visible, so each segment gets a floor —
|
|
100
|
+
// but the floors are taken OUT of the segments that can afford it. Flooring
|
|
101
|
+
// every segment independently overflows the bar (3 tiny + 1 huge measured
|
|
102
|
+
// 106%), and a bar wider than its track is worse than a missing speck.
|
|
103
|
+
const floorTotal = visible.length * MIN_SEGMENT_PCT;
|
|
104
|
+
const surplus = Math.max(0, 100 - floorTotal);
|
|
105
|
+
const slack = Math.max(
|
|
106
|
+
0,
|
|
107
|
+
visible.reduce((sum, segment) => sum + Math.max(0, segment.share - MIN_SEGMENT_PCT), 0),
|
|
108
|
+
);
|
|
109
|
+
const widths = visible.map((segment) => {
|
|
110
|
+
const room = Math.max(0, segment.share - MIN_SEGMENT_PCT);
|
|
111
|
+
const claim = slack > 0 ? (room / slack) * surplus : 0;
|
|
112
|
+
return Math.min(100, MIN_SEGMENT_PCT + claim);
|
|
113
|
+
});
|
|
114
|
+
const drawn = visible
|
|
115
|
+
.map((segment, index) => ({ ...segment, width: widths[index] }))
|
|
116
|
+
.filter((segment) => segment.width > 0);
|
|
123
117
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
118
|
+
const bar = (
|
|
119
|
+
<HStack
|
|
120
|
+
gap={gap}
|
|
121
|
+
height={height}
|
|
122
|
+
width="100%"
|
|
123
|
+
vAlign="stretch"
|
|
124
|
+
role="img"
|
|
125
|
+
aria-label={label}
|
|
126
|
+
style={
|
|
127
|
+
total > 0
|
|
128
|
+
? undefined
|
|
129
|
+
: {
|
|
130
|
+
// Deliberately --color-progress-value, NOT a text token — see the header.
|
|
131
|
+
background: "var(--color-progress-value)",
|
|
132
|
+
borderRadius: "var(--radius-inner)",
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
>
|
|
136
|
+
{drawn.map((segment) => (
|
|
137
|
+
<StackItem
|
|
138
|
+
key={segment.id}
|
|
139
|
+
style={{ ...segmentStyle, flexBasis: `${segment.width}%`, background: segment.color }}
|
|
140
|
+
/>
|
|
141
|
+
))}
|
|
142
|
+
</HStack>
|
|
143
|
+
);
|
|
149
144
|
|
|
150
|
-
|
|
145
|
+
if (!hasValueLabel) return bar;
|
|
151
146
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
147
|
+
return (
|
|
148
|
+
<VStack gap={1}>
|
|
149
|
+
{bar}
|
|
150
|
+
<Text type="supporting" color="secondary" hasTabularNumbers>
|
|
151
|
+
{formatValue(total)}
|
|
152
|
+
</Text>
|
|
153
|
+
</VStack>
|
|
154
|
+
);
|
|
160
155
|
}
|
package/shared/format-money.ts
CHANGED
package/shared/gallery-image.ts
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
// primitive, so gallery SVG scenes fill their box and clip to rounded corners
|
|
4
4
|
// through these two styles. Replace with component props once #2582 lands.
|
|
5
5
|
|
|
6
|
-
import type {CSSProperties} from
|
|
6
|
+
import type { CSSProperties } from "react";
|
|
7
7
|
|
|
8
8
|
// Fills the AspectRatio box. No objectFit prop on AspectRatio (#2582).
|
|
9
9
|
export const galleryImage: CSSProperties = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
width: "100%",
|
|
11
|
+
height: "100%",
|
|
12
|
+
display: "block",
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
// Rounds the gallery corners (element radius; chapter art uses container — see
|
|
16
16
|
// shared/chaptered-doc sceneClip). No radius prop on AspectRatio (#2582);
|
|
17
17
|
export const galleryImageClip: CSSProperties = {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
borderRadius: "var(--radius-element)",
|
|
19
|
+
overflow: "clip",
|
|
20
20
|
};
|
package/shared/login-demo.ts
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
// Promise.withResolvers — the ES2022 target breaks strict consumers), awaited
|
|
4
4
|
// inside each template's own startTransition.
|
|
5
5
|
export function demoLogin(): Promise<void> {
|
|
6
|
-
|
|
6
|
+
return new Promise((resolve) => setTimeout(resolve, 2000));
|
|
7
7
|
}
|