astryx-dracula 0.2.0 → 0.3.0
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 +30 -18
- package/README.md +22 -11
- package/USAGE.md +29 -10
- package/astryx-dracula.js +19 -13
- package/astryx-dracula.variants.d.ts +15 -0
- package/package.json +59 -17
- package/shared/auth-chrome-config.ts +18 -0
- package/shared/auth-chrome.tsx +25 -0
- package/shared/auth-copy.ts +22 -0
- package/shared/chaptered-doc-config.ts +92 -0
- package/shared/chaptered-doc.tsx +332 -0
- package/shared/chart-hues.ts +27 -0
- package/shared/chart-labels.tsx +44 -0
- package/shared/chart-legend.tsx +100 -0
- package/shared/chart-panel-style.ts +13 -0
- package/shared/data-bar.tsx +160 -0
- package/shared/gallery-image.ts +20 -0
- package/shared/login-demo.ts +7 -0
- package/shared/metric-delta.tsx +36 -0
- package/shared/order-desk.tsx +273 -0
- package/shared/revenue-chart.tsx +174 -0
- package/shared/scene-castle.tsx +322 -0
- package/shared/scene-frame.tsx +88 -0
- package/shared/scene-hues.ts +49 -0
- package/shared/scene-tile.tsx +128 -0
- package/shared/settings-data.ts +125 -0
- package/shared/settings-rows.tsx +179 -0
- package/shared/sparkline.tsx +94 -0
- package/shared/sso-icons.tsx +30 -0
- package/templates/ai-chat-landing.tsx +67 -32
- package/templates/ai-chat.tsx +41 -20
- package/templates/blank.tsx +5 -2
- package/templates/centered-hero.tsx +15 -124
- package/templates/classic-gallery.tsx +21 -65
- package/templates/contact-form.tsx +62 -40
- package/templates/dashboard-portfolio.tsx +146 -227
- package/templates/dashboard.tsx +123 -121
- package/templates/detail-page.tsx +101 -95
- package/templates/documentation-design.template.mjs +1 -1
- package/templates/documentation-design.tsx +85 -96
- package/templates/documentation-technical.template.mjs +1 -1
- package/templates/documentation-technical.tsx +33 -21
- package/templates/documentation.template.mjs +1 -1
- package/templates/documentation.tsx +54 -74
- package/templates/editor.tsx +119 -89
- package/templates/file-explorer.tsx +133 -84
- package/templates/form-two-column.tsx +62 -124
- package/templates/gallery-hero.tsx +17 -171
- package/templates/ide.tsx +27 -21
- package/templates/incident-console.tsx +105 -69
- package/templates/kanban-board.tsx +100 -41
- package/templates/library.template.mjs +2 -2
- package/templates/library.tsx +38 -41
- package/templates/login-card.tsx +59 -86
- package/templates/login-split.tsx +88 -128
- package/templates/login-sso.tsx +107 -68
- package/templates/login.tsx +108 -52
- package/templates/messaging-shell.tsx +172 -143
- package/templates/mixed-gallery.tsx +31 -130
- package/templates/payment-form.tsx +369 -289
- package/templates/product-detail.tsx +40 -57
- package/templates/product-gallery.tsx +31 -40
- package/templates/product-tour.template.mjs +6 -0
- package/templates/product-tour.tsx +916 -0
- package/templates/settings-dialog.tsx +145 -286
- package/templates/settings-sidebar.tsx +179 -267
- package/templates/settings.tsx +42 -13
- package/templates/shell-nav.tsx +32 -23
- package/templates/shell-side-nav.tsx +30 -19
- package/templates/shell-top-nav.tsx +81 -43
- package/templates/side-gallery.tsx +39 -93
- package/templates/table-grouped.tsx +63 -33
- package/templates/table-page-chart.tsx +24 -297
- package/templates/table-page-heatmap-status.tsx +157 -91
- package/templates/table-page-shoe-store-heatmap.tsx +19 -288
- package/templates/table-page.tsx +24 -6
- package/templates/table.tsx +24 -7
- package/templates/tech-report.template.mjs +6 -0
- package/templates/tech-report.tsx +1486 -0
- package/templates/theme-showcase.template.mjs +1 -1
- package/templates/theme-showcase.tsx +313 -249
- package/theme.css +76 -14
- package/tokens.css +425 -30
|
@@ -1,116 +1,58 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
// XLE (canonical structure, validated with `bunx astryx layout check`):
|
|
3
|
+
// L > (LH[divider] > H[a=center g=2] > (SI[size=fill] > Hd"Matcha Bar"[level=1]) + IB"Filter"[variant=ghost] + IB"Export"[variant=ghost] + B.primary"New order") + (LC[p=3] > V[g=4] > C[p=4] + (T[hover] > (TR > THC"Order" + THC"Product" + THC"Amount" + THC"Customer" + THC"Email" + THC"Status" + THC"Date") + (TR > TC"ORD-1001" + TC"Ceremonial Matcha Latte" + TC"$6" + TC"Sarah Chen" + TC"sarah.chen@acme.co" + (TC > Tk.green"Completed") + TC"2025-01-15")*6))
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
HStack,
|
|
7
|
-
StackItem,
|
|
8
|
-
Layout,
|
|
9
|
-
LayoutContent,
|
|
10
|
-
LayoutHeader,
|
|
11
|
-
} from '@astryxdesign/core/Layout';
|
|
12
|
-
import {Text, Heading} from '@astryxdesign/core/Text';
|
|
13
|
-
import {Button} from '@astryxdesign/core/Button';
|
|
14
|
-
import {IconButton} from '@astryxdesign/core/IconButton';
|
|
15
|
-
import {Icon} from '@astryxdesign/core/Icon';
|
|
16
|
-
import {Badge} from '@astryxdesign/core/Badge';
|
|
17
|
-
import {Card} from '@astryxdesign/core/Card';
|
|
18
|
-
import {Link} from '@astryxdesign/core/Link';
|
|
19
|
-
import {Table, proportional, pixel} from '@astryxdesign/core/Table';
|
|
20
|
-
import type {TableColumn} from '@astryxdesign/core/Table';
|
|
21
|
-
import {Filter, Download, Plus, Square} from 'lucide-react';
|
|
5
|
+
/**
|
|
6
|
+
* Matcha Bar — order desk: a daily revenue line over the full order log. Frame: page header (title + icon actions) | content column (chart, t (Frame/responsive/container: see XLE header above.)
|
|
7
|
+
*/
|
|
22
8
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Square marks the chart legend swatch.
|
|
26
|
-
|
|
27
|
-
// Per-product Dracula accent for the order thumbnail swatches.
|
|
28
|
-
const PRODUCT_ACCENTS = [
|
|
29
|
-
'var(--dracula-green)',
|
|
30
|
-
'var(--dracula-orange)',
|
|
31
|
-
'var(--dracula-cyan)',
|
|
32
|
-
'var(--dracula-pink)',
|
|
33
|
-
'var(--dracula-purple)',
|
|
34
|
-
'var(--dracula-yellow)',
|
|
35
|
-
] as const;
|
|
36
|
-
|
|
37
|
-
const swatchStyle: CSSProperties = {flexShrink: 0};
|
|
38
|
-
|
|
39
|
-
// Rounded product swatch: Dracula surface with a per-product accent glyph.
|
|
40
|
-
function ProductSwatch({accent, label}: {accent: string; label: string}) {
|
|
41
|
-
return (
|
|
42
|
-
<svg
|
|
43
|
-
viewBox="0 0 36 36"
|
|
44
|
-
width={36}
|
|
45
|
-
height={36}
|
|
46
|
-
style={swatchStyle}
|
|
47
|
-
role="img"
|
|
48
|
-
aria-label={`${label} swatch`}>
|
|
49
|
-
<rect width={36} height={36} rx={5} fill="var(--dracula-bg-light)" />
|
|
50
|
-
<rect
|
|
51
|
-
x={1}
|
|
52
|
-
y={1}
|
|
53
|
-
width={34}
|
|
54
|
-
height={34}
|
|
55
|
-
rx={4}
|
|
56
|
-
fill="none"
|
|
57
|
-
stroke="var(--color-widget-content-border)"
|
|
58
|
-
/>
|
|
59
|
-
<circle cx={18} cy={18} r={7} fill="none" stroke={accent} strokeWidth={3} />
|
|
60
|
-
</svg>
|
|
61
|
-
);
|
|
62
|
-
}
|
|
9
|
+
import {OrderDesk, type OrderDeskRow} from 'astryx-dracula/shared/order-desk';
|
|
10
|
+
import type {SceneHue} from 'astryx-dracula/shared/scene-hues';
|
|
63
11
|
|
|
64
12
|
// ============= DATA =============
|
|
65
13
|
|
|
66
14
|
type ProductCategory = 'Matcha' | 'Coffee' | 'Tea' | 'Smoothie' | 'Specialty';
|
|
67
15
|
|
|
68
|
-
|
|
69
|
-
id: string;
|
|
70
|
-
customer: string;
|
|
71
|
-
email: string;
|
|
72
|
-
product: string;
|
|
73
|
-
category: ProductCategory;
|
|
74
|
-
imageIndex: number;
|
|
75
|
-
amount: number;
|
|
76
|
-
status: 'completed' | 'processing' | 'shipped' | 'refunded';
|
|
77
|
-
date: string;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const PRODUCTS = [
|
|
16
|
+
const PRODUCTS: Array<{name: string; category: string; accent: SceneHue; price: number}> = [
|
|
81
17
|
{
|
|
82
18
|
name: 'Ceremonial Matcha Latte',
|
|
83
19
|
category: 'Matcha' as ProductCategory,
|
|
20
|
+
accent: 'var(--dracula-green)',
|
|
84
21
|
price: 6,
|
|
85
22
|
},
|
|
86
23
|
{
|
|
87
24
|
name: 'Oat Milk Cappuccino',
|
|
88
25
|
category: 'Coffee' as ProductCategory,
|
|
26
|
+
accent: 'var(--dracula-orange)',
|
|
89
27
|
price: 5,
|
|
90
28
|
},
|
|
91
29
|
{
|
|
92
30
|
name: 'Jasmine Green Tea',
|
|
93
31
|
category: 'Tea' as ProductCategory,
|
|
32
|
+
accent: 'var(--dracula-cyan)',
|
|
94
33
|
price: 4,
|
|
95
34
|
},
|
|
96
35
|
{
|
|
97
36
|
name: 'Mango Matcha Smoothie',
|
|
98
37
|
category: 'Smoothie' as ProductCategory,
|
|
38
|
+
accent: 'var(--dracula-pink)',
|
|
99
39
|
price: 8,
|
|
100
40
|
},
|
|
101
41
|
{
|
|
102
42
|
name: 'Hojicha Latte',
|
|
103
43
|
category: 'Specialty' as ProductCategory,
|
|
44
|
+
accent: 'var(--dracula-pink)',
|
|
104
45
|
price: 7,
|
|
105
46
|
},
|
|
106
47
|
{
|
|
107
48
|
name: 'Iced Yuzu Matcha',
|
|
108
49
|
category: 'Matcha' as ProductCategory,
|
|
50
|
+
accent: 'var(--dracula-yellow)',
|
|
109
51
|
price: 7,
|
|
110
52
|
},
|
|
111
53
|
];
|
|
112
54
|
|
|
113
|
-
const orders:
|
|
55
|
+
const orders: OrderDeskRow[] = [
|
|
114
56
|
{
|
|
115
57
|
id: 'ORD-1001',
|
|
116
58
|
customer: 'Sarah Chen',
|
|
@@ -461,233 +403,18 @@ const revenueData = [
|
|
|
461
403
|
{date: 'Jan 15', revenue: 138},
|
|
462
404
|
];
|
|
463
405
|
|
|
464
|
-
|
|
465
|
-
completed: 'green',
|
|
466
|
-
shipped: 'blue',
|
|
467
|
-
processing: 'orange',
|
|
468
|
-
refunded: 'red',
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
const columns: TableColumn<OrderRow>[] = [
|
|
472
|
-
{
|
|
473
|
-
key: 'id',
|
|
474
|
-
header: 'Order',
|
|
475
|
-
width: pixel(110),
|
|
476
|
-
renderCell: (item: OrderRow) => (
|
|
477
|
-
<Link href="#/templates/table-page-chart" isStandalone>
|
|
478
|
-
{item.id}
|
|
479
|
-
</Link>
|
|
480
|
-
),
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
key: 'product',
|
|
484
|
-
header: 'Product',
|
|
485
|
-
width: proportional(3),
|
|
486
|
-
renderCell: (item: OrderRow) => (
|
|
487
|
-
<HStack gap={3} vAlign="center">
|
|
488
|
-
<ProductSwatch
|
|
489
|
-
accent={PRODUCT_ACCENTS[item.imageIndex]}
|
|
490
|
-
label={item.product}
|
|
491
|
-
/>
|
|
492
|
-
<VStack gap={0}>
|
|
493
|
-
<Text type="body">{item.product}</Text>
|
|
494
|
-
<Text type="supporting" color="secondary">
|
|
495
|
-
{item.category}
|
|
496
|
-
</Text>
|
|
497
|
-
</VStack>
|
|
498
|
-
</HStack>
|
|
499
|
-
),
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
key: 'amount',
|
|
503
|
-
header: 'Amount',
|
|
504
|
-
width: pixel(90),
|
|
505
|
-
renderCell: (item: OrderRow) => (
|
|
506
|
-
<Text type="body" hasTabularNumbers>
|
|
507
|
-
${item.amount}
|
|
508
|
-
</Text>
|
|
509
|
-
),
|
|
510
|
-
},
|
|
511
|
-
{
|
|
512
|
-
key: 'customer',
|
|
513
|
-
header: 'Customer',
|
|
514
|
-
width: proportional(2),
|
|
515
|
-
renderCell: (item: OrderRow) => <Text type="body">{item.customer}</Text>,
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
key: 'email',
|
|
519
|
-
header: 'Email',
|
|
520
|
-
width: proportional(2),
|
|
521
|
-
renderCell: (item: OrderRow) => <Text type="body">{item.email}</Text>,
|
|
522
|
-
},
|
|
523
|
-
{
|
|
524
|
-
key: 'status',
|
|
525
|
-
header: 'Status',
|
|
526
|
-
width: pixel(120),
|
|
527
|
-
renderCell: (item: OrderRow) => (
|
|
528
|
-
<Badge
|
|
529
|
-
label={item.status.charAt(0).toUpperCase() + item.status.slice(1)}
|
|
530
|
-
variant={statusColor[item.status]}
|
|
531
|
-
/>
|
|
532
|
-
),
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
key: 'date',
|
|
536
|
-
header: 'Date',
|
|
537
|
-
width: pixel(110),
|
|
538
|
-
renderCell: (item: OrderRow) => (
|
|
539
|
-
<Text type="body" hasTabularNumbers>
|
|
540
|
-
{item.date}
|
|
541
|
-
</Text>
|
|
542
|
-
),
|
|
543
|
-
},
|
|
544
|
-
];
|
|
545
|
-
|
|
546
|
-
// ============= REVENUE CHART (hand SVG, Dracula ramp) =============
|
|
547
|
-
|
|
548
|
-
const revenueLine = 'var(--dracula-purple)';
|
|
549
|
-
|
|
550
|
-
function RevenueChart() {
|
|
551
|
-
const W = 540;
|
|
552
|
-
const H = 200;
|
|
553
|
-
const padLeft = 40;
|
|
554
|
-
const padRight = 12;
|
|
555
|
-
const padTop = 12;
|
|
556
|
-
const baseline = 164;
|
|
557
|
-
const max = 160;
|
|
558
|
-
const plotW = W - padLeft - padRight;
|
|
559
|
-
const plotH = baseline - padTop;
|
|
560
|
-
const points = revenueData.map((d, i) => ({
|
|
561
|
-
...d,
|
|
562
|
-
x: padLeft + (i / (revenueData.length - 1)) * plotW,
|
|
563
|
-
y: baseline - (d.revenue / max) * plotH,
|
|
564
|
-
}));
|
|
565
|
-
const linePath = points
|
|
566
|
-
.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x.toFixed(1)},${p.y.toFixed(1)}`)
|
|
567
|
-
.join(' ');
|
|
568
|
-
const areaPath = `${linePath} L${points[points.length - 1].x.toFixed(1)},${baseline} L${points[0].x.toFixed(1)},${baseline} Z`;
|
|
569
|
-
const gridTicks = [0, 50, 100, 150];
|
|
570
|
-
return (
|
|
571
|
-
<VStack gap={3}>
|
|
572
|
-
<Card
|
|
573
|
-
padding={3}
|
|
574
|
-
style={{
|
|
575
|
-
backgroundColor: 'var(--color-background)',
|
|
576
|
-
border: 'var(--border-width) solid var(--color-separator)',
|
|
577
|
-
}}>
|
|
578
|
-
<svg
|
|
579
|
-
viewBox={`0 0 ${W} ${H}`}
|
|
580
|
-
width="100%"
|
|
581
|
-
role="img"
|
|
582
|
-
aria-label="Daily revenue, January 1 to 15">
|
|
583
|
-
{gridTicks.map(tick => {
|
|
584
|
-
const y = baseline - (tick / max) * plotH;
|
|
585
|
-
return (
|
|
586
|
-
<g key={tick}>
|
|
587
|
-
<line
|
|
588
|
-
x1={padLeft}
|
|
589
|
-
y1={y}
|
|
590
|
-
x2={W - padRight}
|
|
591
|
-
y2={y}
|
|
592
|
-
stroke="var(--color-separator)"
|
|
593
|
-
strokeDasharray={tick === 0 ? undefined : '3 3'}
|
|
594
|
-
opacity={tick === 0 ? 1 : 0.5}
|
|
595
|
-
/>
|
|
596
|
-
<text
|
|
597
|
-
x={padLeft - 6}
|
|
598
|
-
y={y + 3}
|
|
599
|
-
textAnchor="end"
|
|
600
|
-
fontSize={9}
|
|
601
|
-
fill="var(--color-text-paragraph)"
|
|
602
|
-
fontFamily="var(--font-family-mono)">
|
|
603
|
-
${tick}
|
|
604
|
-
</text>
|
|
605
|
-
</g>
|
|
606
|
-
);
|
|
607
|
-
})}
|
|
608
|
-
<path d={areaPath} fill={revenueLine} opacity={0.25} />
|
|
609
|
-
<path
|
|
610
|
-
d={linePath}
|
|
611
|
-
fill="none"
|
|
612
|
-
stroke={revenueLine}
|
|
613
|
-
strokeWidth={2}
|
|
614
|
-
strokeLinejoin="round"
|
|
615
|
-
strokeLinecap="round"
|
|
616
|
-
/>
|
|
617
|
-
{points.map(
|
|
618
|
-
(p, i) =>
|
|
619
|
-
(i % 3 === 0 || i === points.length - 1) && (
|
|
620
|
-
<text
|
|
621
|
-
key={p.date}
|
|
622
|
-
x={i === points.length - 1 ? W - padRight - 2 : p.x}
|
|
623
|
-
y={H - 8}
|
|
624
|
-
textAnchor={i === points.length - 1 ? 'end' : 'middle'}
|
|
625
|
-
fontSize={9}
|
|
626
|
-
fill="var(--color-text-paragraph)"
|
|
627
|
-
fontFamily="var(--font-family-mono)">
|
|
628
|
-
{p.date}
|
|
629
|
-
</text>
|
|
630
|
-
),
|
|
631
|
-
)}
|
|
632
|
-
</svg>
|
|
633
|
-
</Card>
|
|
634
|
-
<Text type="supporting" color="secondary">
|
|
635
|
-
Daily revenue · Jan 1–15
|
|
636
|
-
</Text>
|
|
637
|
-
<HStack gap={2} vAlign="center">
|
|
638
|
-
<Icon icon={Square} size="xsm" style={{color: revenueLine}} />
|
|
639
|
-
<Text type="supporting" color="secondary">
|
|
640
|
-
Revenue
|
|
641
|
-
</Text>
|
|
642
|
-
</HStack>
|
|
643
|
-
</VStack>
|
|
644
|
-
);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// ============= PAGE =============
|
|
406
|
+
// ============= PAGE (parametric OrderDesk; catalogue + rows + scale only) =============
|
|
648
407
|
|
|
649
408
|
export default function ChartTable() {
|
|
650
409
|
return (
|
|
651
|
-
<
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
<IconButton
|
|
660
|
-
label="Filter"
|
|
661
|
-
icon={<Icon icon={Filter} size="sm" />}
|
|
662
|
-
variant="ghost"
|
|
663
|
-
tooltip="Filter"
|
|
664
|
-
/>
|
|
665
|
-
<IconButton
|
|
666
|
-
label="Export"
|
|
667
|
-
icon={<Icon icon={Download} size="sm" />}
|
|
668
|
-
variant="ghost"
|
|
669
|
-
tooltip="Export"
|
|
670
|
-
/>
|
|
671
|
-
<Button label="New order" icon={<Icon icon={Plus} size="sm" />} />
|
|
672
|
-
</HStack>
|
|
673
|
-
</LayoutHeader>
|
|
674
|
-
}
|
|
675
|
-
content={
|
|
676
|
-
<LayoutContent padding={3}>
|
|
677
|
-
<VStack gap={4}>
|
|
678
|
-
<RevenueChart />
|
|
679
|
-
|
|
680
|
-
<Table<OrderRow>
|
|
681
|
-
data={orders}
|
|
682
|
-
columns={columns}
|
|
683
|
-
idKey="id"
|
|
684
|
-
density="balanced"
|
|
685
|
-
dividers="rows"
|
|
686
|
-
hasHover
|
|
687
|
-
/>
|
|
688
|
-
</VStack>
|
|
689
|
-
</LayoutContent>
|
|
690
|
-
}
|
|
410
|
+
<OrderDesk
|
|
411
|
+
title="Matcha Bar"
|
|
412
|
+
selfHash="#/templates/table-page-chart"
|
|
413
|
+
products={PRODUCTS}
|
|
414
|
+
orders={orders}
|
|
415
|
+
revenueData={revenueData}
|
|
416
|
+
chartMax={160}
|
|
417
|
+
gridTicks={[0, 50, 100, 150]}
|
|
691
418
|
/>
|
|
692
419
|
);
|
|
693
420
|
}
|