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