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.
Files changed (83) hide show
  1. package/BRAND.md +30 -18
  2. package/README.md +22 -11
  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 +67 -32
  31. package/templates/ai-chat.tsx +41 -20
  32. package/templates/blank.tsx +5 -2
  33. package/templates/centered-hero.tsx +15 -124
  34. package/templates/classic-gallery.tsx +21 -65
  35. package/templates/contact-form.tsx +62 -40
  36. package/templates/dashboard-portfolio.tsx +146 -227
  37. package/templates/dashboard.tsx +123 -121
  38. package/templates/detail-page.tsx +101 -95
  39. package/templates/documentation-design.template.mjs +1 -1
  40. package/templates/documentation-design.tsx +85 -96
  41. package/templates/documentation-technical.template.mjs +1 -1
  42. package/templates/documentation-technical.tsx +33 -21
  43. package/templates/documentation.template.mjs +1 -1
  44. package/templates/documentation.tsx +54 -74
  45. package/templates/editor.tsx +119 -89
  46. package/templates/file-explorer.tsx +133 -84
  47. package/templates/form-two-column.tsx +62 -124
  48. package/templates/gallery-hero.tsx +17 -171
  49. package/templates/ide.tsx +27 -21
  50. package/templates/incident-console.tsx +105 -69
  51. package/templates/kanban-board.tsx +100 -41
  52. package/templates/library.template.mjs +2 -2
  53. package/templates/library.tsx +38 -41
  54. package/templates/login-card.tsx +59 -86
  55. package/templates/login-split.tsx +88 -128
  56. package/templates/login-sso.tsx +107 -68
  57. package/templates/login.tsx +108 -52
  58. package/templates/messaging-shell.tsx +172 -143
  59. package/templates/mixed-gallery.tsx +31 -130
  60. package/templates/payment-form.tsx +369 -289
  61. package/templates/product-detail.tsx +40 -57
  62. package/templates/product-gallery.tsx +31 -40
  63. package/templates/product-tour.template.mjs +6 -0
  64. package/templates/product-tour.tsx +916 -0
  65. package/templates/settings-dialog.tsx +145 -286
  66. package/templates/settings-sidebar.tsx +179 -267
  67. package/templates/settings.tsx +42 -13
  68. package/templates/shell-nav.tsx +32 -23
  69. package/templates/shell-side-nav.tsx +30 -19
  70. package/templates/shell-top-nav.tsx +81 -43
  71. package/templates/side-gallery.tsx +39 -93
  72. package/templates/table-grouped.tsx +63 -33
  73. package/templates/table-page-chart.tsx +24 -297
  74. package/templates/table-page-heatmap-status.tsx +157 -91
  75. package/templates/table-page-shoe-store-heatmap.tsx +19 -288
  76. package/templates/table-page.tsx +24 -6
  77. package/templates/table.tsx +24 -7
  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 +313 -249
  82. package/theme.css +76 -14
  83. 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
- import type {CSSProperties} from 'react';
4
- import {
5
- VStack,
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
- // ============= ICONS (verified lucide-react exports) =============
24
- // Filter ← FunnelIcon, Download ← ArrowDownTrayIcon, Plus ← PlusIcon.
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
- interface OrderRow extends Record<string, unknown> {
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: OrderRow[] = [
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
- const statusColor: Record<string, 'green' | 'blue' | 'orange' | 'red'> = {
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
- <Layout
652
- height="fill"
653
- header={
654
- <LayoutHeader hasDivider>
655
- <HStack gap={2} vAlign="center">
656
- <StackItem size="fill">
657
- <Heading level={1}>Matcha Bar</Heading>
658
- </StackItem>
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
  }