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.
Files changed (129) hide show
  1. package/BRAND.md +3 -3
  2. package/README.md +7 -4
  3. package/USAGE.md +49 -49
  4. package/astryx-dracula.d.ts +2 -2
  5. package/astryx-dracula.js +25 -9
  6. package/astryx-dracula.variants.d.ts +2 -2
  7. package/astryx.integration.mjs +1 -1
  8. package/icons.mjs +21 -17
  9. package/icons.tsx +69 -62
  10. package/package.json +125 -120
  11. package/shared/auth-chrome-config.ts +6 -6
  12. package/shared/auth-chrome.tsx +143 -144
  13. package/shared/auth-copy.ts +14 -14
  14. package/shared/chaptered-doc-config.ts +48 -51
  15. package/shared/chaptered-doc.tsx +267 -289
  16. package/shared/chart-hues.ts +25 -10
  17. package/shared/chart-labels.tsx +31 -30
  18. package/shared/chart-legend.tsx +55 -56
  19. package/shared/chart-panel-style.ts +3 -3
  20. package/shared/data-bar.tsx +97 -102
  21. package/shared/format-money.ts +1 -1
  22. package/shared/gallery-image.ts +6 -6
  23. package/shared/login-demo.ts +1 -1
  24. package/shared/metric-card.tsx +101 -105
  25. package/shared/metric-delta.tsx +28 -27
  26. package/shared/order-desk.tsx +205 -216
  27. package/shared/revenue-chart.tsx +145 -165
  28. package/shared/scene-castle.tsx +206 -291
  29. package/shared/scene-frame.tsx +33 -32
  30. package/shared/scene-hues.ts +17 -17
  31. package/shared/scene-tile.tsx +88 -92
  32. package/shared/settings-data.ts +119 -125
  33. package/shared/settings-rows.tsx +122 -159
  34. package/shared/sparkline.tsx +75 -88
  35. package/shared/sso-icons.tsx +10 -22
  36. package/shared/stars.tsx +16 -25
  37. package/templates/ai-chat-landing.template.mjs +5 -4
  38. package/templates/ai-chat-landing.tsx +473 -460
  39. package/templates/ai-chat.template.mjs +5 -4
  40. package/templates/ai-chat.tsx +543 -612
  41. package/templates/blank.template.mjs +5 -4
  42. package/templates/blank.tsx +18 -14
  43. package/templates/centered-hero.template.mjs +5 -4
  44. package/templates/centered-hero.tsx +55 -68
  45. package/templates/classic-gallery.template.mjs +5 -4
  46. package/templates/classic-gallery.tsx +97 -104
  47. package/templates/contact-form.template.mjs +5 -4
  48. package/templates/contact-form.tsx +247 -282
  49. package/templates/dashboard-portfolio.template.mjs +5 -4
  50. package/templates/dashboard-portfolio.tsx +717 -548
  51. package/templates/dashboard.template.mjs +5 -4
  52. package/templates/dashboard.tsx +596 -567
  53. package/templates/detail-page.template.mjs +5 -4
  54. package/templates/detail-page.tsx +546 -603
  55. package/templates/documentation-design.template.mjs +5 -4
  56. package/templates/documentation-design.tsx +231 -243
  57. package/templates/documentation-technical.template.mjs +5 -4
  58. package/templates/documentation-technical.tsx +236 -239
  59. package/templates/documentation.template.mjs +5 -4
  60. package/templates/documentation.tsx +267 -279
  61. package/templates/editor.template.mjs +5 -4
  62. package/templates/editor.tsx +844 -877
  63. package/templates/file-explorer.template.mjs +5 -4
  64. package/templates/file-explorer.tsx +566 -590
  65. package/templates/form-two-column.template.mjs +5 -4
  66. package/templates/form-two-column.tsx +195 -210
  67. package/templates/gallery-hero.template.mjs +5 -4
  68. package/templates/gallery-hero.tsx +93 -114
  69. package/templates/ide.template.mjs +5 -4
  70. package/templates/ide.tsx +407 -453
  71. package/templates/incident-console.template.mjs +5 -4
  72. package/templates/incident-console.tsx +593 -575
  73. package/templates/kanban-board.template.mjs +5 -4
  74. package/templates/kanban-board.tsx +665 -683
  75. package/templates/library.template.mjs +5 -4
  76. package/templates/library.tsx +409 -430
  77. package/templates/login-card.template.mjs +5 -4
  78. package/templates/login-card.tsx +63 -72
  79. package/templates/login-split.template.mjs +5 -4
  80. package/templates/login-split.tsx +192 -193
  81. package/templates/login-sso.template.mjs +5 -4
  82. package/templates/login-sso.tsx +257 -258
  83. package/templates/login.template.mjs +5 -4
  84. package/templates/login.tsx +53 -49
  85. package/templates/messaging-shell.template.mjs +5 -4
  86. package/templates/messaging-shell.tsx +556 -574
  87. package/templates/mixed-gallery.template.mjs +5 -4
  88. package/templates/mixed-gallery.tsx +60 -58
  89. package/templates/payment-form.template.mjs +5 -4
  90. package/templates/payment-form.tsx +882 -991
  91. package/templates/product-detail.template.mjs +5 -4
  92. package/templates/product-detail.tsx +261 -272
  93. package/templates/product-gallery.template.mjs +5 -4
  94. package/templates/product-gallery.tsx +126 -137
  95. package/templates/product-tour.template.mjs +5 -4
  96. package/templates/product-tour.tsx +741 -773
  97. package/templates/settings-dialog.template.mjs +5 -4
  98. package/templates/settings-dialog.tsx +688 -717
  99. package/templates/settings-sidebar.template.mjs +5 -4
  100. package/templates/settings-sidebar.tsx +762 -807
  101. package/templates/settings.template.mjs +5 -4
  102. package/templates/settings.tsx +289 -304
  103. package/templates/shell-nav.template.mjs +5 -4
  104. package/templates/shell-nav.tsx +212 -219
  105. package/templates/shell-side-nav.template.mjs +5 -4
  106. package/templates/shell-side-nav.tsx +135 -157
  107. package/templates/shell-top-nav.template.mjs +5 -4
  108. package/templates/shell-top-nav.tsx +182 -203
  109. package/templates/side-gallery.template.mjs +5 -4
  110. package/templates/side-gallery.tsx +85 -90
  111. package/templates/table-grouped.template.mjs +5 -4
  112. package/templates/table-grouped.tsx +1000 -1053
  113. package/templates/table-page-chart.template.mjs +5 -4
  114. package/templates/table-page-chart.tsx +400 -398
  115. package/templates/table-page-heatmap-status.template.mjs +5 -4
  116. package/templates/table-page-heatmap-status.tsx +483 -512
  117. package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
  118. package/templates/table-page-shoe-store-heatmap.tsx +748 -746
  119. package/templates/table-page.template.mjs +5 -4
  120. package/templates/table-page.tsx +396 -405
  121. package/templates/table.template.mjs +5 -4
  122. package/templates/table.tsx +92 -93
  123. package/templates/tech-report.template.mjs +5 -4
  124. package/templates/tech-report.tsx +1316 -1304
  125. package/templates/theme-showcase.template.mjs +5 -4
  126. package/templates/theme-showcase.tsx +871 -951
  127. package/theme.css +35 -77
  128. package/theme.css.d.ts +9 -0
  129. package/tokens.css +373 -380
@@ -2,26 +2,27 @@
2
2
  // table-page-shoe-store-heatmap (Midnight Kicks) templates. The two pages are
3
3
  // one archetype — revenue line over the order log — differing only in catalogue,
4
4
  // rows, and chart scale, so the frame/columns live here once.
5
- import type {CSSProperties} from 'react';
5
+
6
+ import { Button } from "@astryxdesign/core/Button";
7
+ import { Icon } from "@astryxdesign/core/Icon";
8
+ import { IconButton } from "@astryxdesign/core/IconButton";
6
9
  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 {Token} from '@astryxdesign/core/Token';
19
- import {Link} from '@astryxdesign/core/Link';
20
- import {Table, proportional, pixel} from '@astryxdesign/core/Table';
21
- import type {TableColumn} from '@astryxdesign/core/Table';
22
- import {Filter, Download, Plus} from 'lucide-react';
23
- import {RevenueChart, ProductSwatch} from 'astryx-dracula/shared/revenue-chart';
24
- import type {SceneHue} from 'astryx-dracula/shared/scene-hues';
10
+ HStack,
11
+ Layout,
12
+ LayoutContent,
13
+ LayoutHeader,
14
+ StackItem,
15
+ VStack,
16
+ } from "@astryxdesign/core/Layout";
17
+ import { Link } from "@astryxdesign/core/Link";
18
+ import type { TableColumn } from "@astryxdesign/core/Table";
19
+ import { pixel, proportional, Table } from "@astryxdesign/core/Table";
20
+ import { Heading, Text } from "@astryxdesign/core/Text";
21
+ import { Token } from "@astryxdesign/core/Token";
22
+ import { ProductSwatch, RevenueChart } from "astryx-dracula/shared/revenue-chart";
23
+ import type { SceneHue } from "astryx-dracula/shared/scene-hues";
24
+ import { Download, Filter, Plus } from "lucide-react";
25
+ import type { CSSProperties } from "react";
25
26
 
26
27
  // Anchor for the page wrapper.
27
28
  //
@@ -43,231 +44,219 @@ import type {SceneHue} from 'astryx-dracula/shared/scene-hues';
43
44
  // The wrapper exists to give the Layout's `height: 100%` (Layout.tsx:58-63)
44
45
  // something definite to resolve against when the host is content-sized, which
45
46
  // is the case whenever a template ships standalone.
46
- const pageStyle: CSSProperties = {height: '100dvh'};
47
+ const pageStyle: CSSProperties = { height: "100dvh" };
47
48
 
48
49
  export interface OrderDeskProduct {
49
- name: string;
50
- category: string;
51
- /**
52
- * Per-product art tint, painted by `ProductSwatch`. Same remit as
53
- * `SceneTile.hue` — an art treatment, not a data series — so it takes the
54
- * same `SceneHue` union rather than a free-form string. Typing the boundary
55
- * HERE is what makes the compile-error list the real list: typed only at the
56
- * consumer, a raw string flows through untyped and the error never fires.
57
- */
58
- accent: SceneHue;
59
- price: number;
50
+ name: string;
51
+ category: string;
52
+ /**
53
+ * Per-product art tint, painted by `ProductSwatch`. Same remit as
54
+ * `SceneTile.hue` — an art treatment, not a data series — so it takes the
55
+ * same `SceneHue` union rather than a free-form string. Typing the boundary
56
+ * HERE is what makes the compile-error list the real list: typed only at the
57
+ * consumer, a raw string flows through untyped and the error never fires.
58
+ */
59
+ accent: SceneHue;
60
+ price: number;
60
61
  }
61
62
 
62
63
  export interface OrderDeskRow extends Record<string, unknown> {
63
- id: string;
64
- customer: string;
65
- email: string;
66
- product: string;
67
- category: string;
68
- imageIndex: number;
69
- amount: number;
70
- status: 'completed' | 'processing' | 'shipped' | 'refunded';
71
- date: string;
64
+ id: string;
65
+ customer: string;
66
+ email: string;
67
+ product: string;
68
+ category: string;
69
+ imageIndex: number;
70
+ amount: number;
71
+ status: "completed" | "processing" | "shipped" | "refunded";
72
+ date: string;
72
73
  }
73
74
 
74
75
  export interface RevenueDatum {
75
- date: string;
76
- revenue: number;
76
+ date: string;
77
+ revenue: number;
77
78
  }
78
79
 
79
80
  // Vocabulary, not a hue choice: orange is attention and constants only
80
81
  // (principle 3), and an order being picked is routine in-flight work, not
81
82
  // attention. In-progress/activity is cyan (info). refunded stays red — that
82
83
  // is a real negative.
83
- const STATUS_TOKEN_COLOR: Record<
84
- OrderDeskRow['status'],
85
- 'green' | 'cyan' | 'red'
86
- > = {
87
- completed: 'green',
88
- shipped: 'cyan',
89
- processing: 'cyan',
90
- refunded: 'red',
84
+ const STATUS_TOKEN_COLOR: Record<OrderDeskRow["status"], "green" | "cyan" | "red"> = {
85
+ completed: "green",
86
+ shipped: "cyan",
87
+ processing: "cyan",
88
+ refunded: "red",
91
89
  };
92
90
 
93
- const STATUS_LABEL: Record<OrderDeskRow['status'], string> = {
94
- completed: 'Completed',
95
- shipped: 'Shipped',
96
- processing: 'Processing',
97
- refunded: 'Refunded',
91
+ const STATUS_LABEL: Record<OrderDeskRow["status"], string> = {
92
+ completed: "Completed",
93
+ shipped: "Shipped",
94
+ processing: "Processing",
95
+ refunded: "Refunded",
98
96
  };
99
97
 
100
98
  function columnsFor(selfHash: string, products: OrderDeskProduct[]): TableColumn<OrderDeskRow>[] {
101
- return [
102
- {
103
- key: 'id',
104
- header: 'Order',
105
- width: pixel(96),
106
- renderCell: (item: OrderDeskRow) => (
107
- <Link href={selfHash} isStandalone>
108
- {item.id}
109
- </Link>
110
- ),
111
- },
112
- {
113
- key: 'product',
114
- header: 'Product',
115
- width: proportional(3, {minWidth: 160}),
116
- renderCell: (item: OrderDeskRow) => (
117
- <HStack gap={3} vAlign="center">
118
- <ProductSwatch
119
- accent={products[item.imageIndex].accent}
120
- label={item.product}
121
- />
122
- <StackItem size="fill">
123
- <VStack gap={0}>
124
- <Text type="body" maxLines={1}>
125
- {item.product}
126
- </Text>
127
- <Text type="supporting" color="secondary" maxLines={1}>
128
- {item.category}
129
- </Text>
130
- </VStack>
131
- </StackItem>
132
- </HStack>
133
- ),
134
- },
135
- {
136
- key: 'amount',
137
- header: 'Amount',
138
- width: pixel(88),
139
- renderCell: (item: OrderDeskRow) => (
140
- <Text type="body" hasTabularNumbers maxLines={1}>
141
- ${item.amount}
142
- </Text>
143
- ),
144
- },
145
- {
146
- key: 'customer',
147
- header: 'Customer',
148
- width: proportional(2, {minWidth: 120}),
149
- renderCell: (item: OrderDeskRow) => (
150
- <Text type="body" maxLines={1}>
151
- {item.customer}
152
- </Text>
153
- ),
154
- },
155
- {
156
- key: 'email',
157
- header: 'Email',
158
- width: proportional(2, {minWidth: 120}),
159
- renderCell: (item: OrderDeskRow) => (
160
- <Text type="body" maxLines={1}>
161
- {item.email}
162
- </Text>
163
- ),
164
- },
165
- {
166
- key: 'status',
167
- header: 'Status',
168
- width: pixel(120),
169
- renderCell: (item: OrderDeskRow) => (
170
- <Token
171
- size="sm"
172
- color={STATUS_TOKEN_COLOR[item.status]}
173
- label={STATUS_LABEL[item.status]}
174
- />
175
- ),
176
- },
177
- {
178
- key: 'date',
179
- header: 'Date',
180
- width: pixel(112),
181
- renderCell: (item: OrderDeskRow) => (
182
- <Text type="body" hasTabularNumbers maxLines={1}>
183
- {item.date}
184
- </Text>
185
- ),
186
- },
187
- ];
99
+ return [
100
+ {
101
+ key: "id",
102
+ header: "Order",
103
+ width: pixel(96),
104
+ renderCell: (item: OrderDeskRow) => (
105
+ <Link href={selfHash} isStandalone>
106
+ {item.id}
107
+ </Link>
108
+ ),
109
+ },
110
+ {
111
+ key: "product",
112
+ header: "Product",
113
+ width: proportional(3, { minWidth: 160 }),
114
+ renderCell: (item: OrderDeskRow) => (
115
+ <HStack gap={3} vAlign="center">
116
+ <ProductSwatch accent={products[item.imageIndex].accent} label={item.product} />
117
+ <StackItem size="fill">
118
+ <VStack gap={0}>
119
+ <Text type="body" maxLines={1}>
120
+ {item.product}
121
+ </Text>
122
+ <Text type="supporting" color="secondary" maxLines={1}>
123
+ {item.category}
124
+ </Text>
125
+ </VStack>
126
+ </StackItem>
127
+ </HStack>
128
+ ),
129
+ },
130
+ {
131
+ key: "amount",
132
+ header: "Amount",
133
+ width: pixel(88),
134
+ renderCell: (item: OrderDeskRow) => (
135
+ <Text type="body" hasTabularNumbers maxLines={1}>
136
+ ${item.amount}
137
+ </Text>
138
+ ),
139
+ },
140
+ {
141
+ key: "customer",
142
+ header: "Customer",
143
+ width: proportional(2, { minWidth: 120 }),
144
+ renderCell: (item: OrderDeskRow) => (
145
+ <Text type="body" maxLines={1}>
146
+ {item.customer}
147
+ </Text>
148
+ ),
149
+ },
150
+ {
151
+ key: "email",
152
+ header: "Email",
153
+ width: proportional(2, { minWidth: 120 }),
154
+ renderCell: (item: OrderDeskRow) => (
155
+ <Text type="body" maxLines={1}>
156
+ {item.email}
157
+ </Text>
158
+ ),
159
+ },
160
+ {
161
+ key: "status",
162
+ header: "Status",
163
+ width: pixel(120),
164
+ renderCell: (item: OrderDeskRow) => (
165
+ <Token
166
+ size="sm"
167
+ color={STATUS_TOKEN_COLOR[item.status]}
168
+ label={STATUS_LABEL[item.status]}
169
+ />
170
+ ),
171
+ },
172
+ {
173
+ key: "date",
174
+ header: "Date",
175
+ width: pixel(112),
176
+ renderCell: (item: OrderDeskRow) => (
177
+ <Text type="body" hasTabularNumbers maxLines={1}>
178
+ {item.date}
179
+ </Text>
180
+ ),
181
+ },
182
+ ];
188
183
  }
189
184
 
190
185
  export function OrderDesk({
191
- title,
192
- selfHash,
193
- products,
194
- orders,
195
- revenueData,
196
- chartMax,
197
- gridTicks,
186
+ title,
187
+ selfHash,
188
+ products,
189
+ orders,
190
+ revenueData,
191
+ chartMax,
192
+ gridTicks,
198
193
  }: {
199
- title: string;
200
- selfHash: string;
201
- products: OrderDeskProduct[];
202
- orders: OrderDeskRow[];
203
- revenueData: RevenueDatum[];
204
- chartMax: number;
205
- gridTicks: number[];
194
+ title: string;
195
+ selfHash: string;
196
+ products: OrderDeskProduct[];
197
+ orders: OrderDeskRow[];
198
+ revenueData: RevenueDatum[];
199
+ chartMax: number;
200
+ gridTicks: number[];
206
201
  }) {
207
- return (
208
- // The anchor lives on a page-owned wrapper, never on the Layout. A bare
209
- // `height="fill"` resolves against `min-height: 100%`, which collapses when
210
- // the host is content-sized — and templates ship standalone, so that is the
211
- // common case. Putting the height on the Layout instead would trade
212
- // a soft failure (the document scrolls) for a hard one (content clipped,
213
- // because `LayoutContent` is `overflow: auto` with a definite height).
214
- <div style={pageStyle}>
215
- <Layout
216
- height="fill"
217
- header={
218
- <LayoutHeader hasDivider padding={6}>
219
- <HStack gap={2} vAlign="center">
220
- <StackItem size="fill">
221
- {/* maxLines={1}, not wrap="wrap": at 390 the 35px display-2 title
202
+ return (
203
+ // The anchor lives on a page-owned wrapper, never on the Layout. A bare
204
+ // `height="fill"` resolves against `min-height: 100%`, which collapses when
205
+ // the host is content-sized — and templates ship standalone, so that is the
206
+ // common case. Putting the height on the Layout instead would trade
207
+ // a soft failure (the document scrolls) for a hard one (content clipped,
208
+ // because `LayoutContent` is `overflow: auto` with a definite height).
209
+ <div style={pageStyle}>
210
+ <Layout
211
+ height="fill"
212
+ header={
213
+ <LayoutHeader hasDivider padding={6}>
214
+ <HStack gap={2} vAlign="center">
215
+ <StackItem size="fill">
216
+ {/* maxLines={1}, not wrap="wrap": at 390 the 35px display-2 title
222
217
  wraps 2-3 lines in a 342px header (measured: 136px tall for
223
218
  "Midnight Kicks", 180px for an 18-char title). Wrapping the
224
219
  row measured IDENTICAL header heights in both configurations
225
220
  — the controls already fit, the title is what is tall. And
226
221
  maxLines wires core's useTruncation, so the full value stays
227
222
  reachable in a Tooltip (SC 1.4.10, "truncation must reveal"). */}
228
- <Heading level={1} type="display-2" maxLines={1}>{title}</Heading>
229
- </StackItem>
230
- <IconButton
231
- label="Filter"
232
- icon={<Icon icon={Filter} size="sm" />}
233
- variant="ghost"
234
- tooltip="Filter"
235
- />
236
- <IconButton
237
- label="Export"
238
- icon={<Icon icon={Download} size="sm" />}
239
- variant="ghost"
240
- tooltip="Export"
241
- />
242
- <Button
243
- label="New order"
244
- variant="primary"
245
- icon={<Icon icon={Plus} size="sm" />}
246
- />
247
- </HStack>
248
- </LayoutHeader>
249
- }
250
- content={
251
- <LayoutContent padding={3}>
252
- <VStack gap={4}>
253
- <RevenueChart
254
- data={revenueData}
255
- chartMax={chartMax}
256
- gridTicks={gridTicks}
257
- />
258
- <Table<OrderDeskRow>
259
- data={orders}
260
- columns={columnsFor(selfHash, products)}
261
- idKey="id"
262
- density="balanced"
263
- dividers="rows"
264
- textOverflow="truncate"
265
- hasHover
266
- />
267
- </VStack>
268
- </LayoutContent>
269
- }
270
- />
271
- </div>
272
- );
223
+ <Heading level={1} type="display-2" maxLines={1}>
224
+ {title}
225
+ </Heading>
226
+ </StackItem>
227
+ <IconButton
228
+ label="Filter"
229
+ icon={<Icon icon={Filter} size="sm" />}
230
+ variant="ghost"
231
+ tooltip="Filter"
232
+ />
233
+ <IconButton
234
+ label="Export"
235
+ icon={<Icon icon={Download} size="sm" />}
236
+ variant="ghost"
237
+ tooltip="Export"
238
+ />
239
+ <Button label="New order" variant="primary" icon={<Icon icon={Plus} size="sm" />} />
240
+ </HStack>
241
+ </LayoutHeader>
242
+ }
243
+ content={
244
+ <LayoutContent padding={3}>
245
+ <VStack gap={4}>
246
+ <RevenueChart data={revenueData} chartMax={chartMax} gridTicks={gridTicks} />
247
+ <Table<OrderDeskRow>
248
+ data={orders}
249
+ columns={columnsFor(selfHash, products)}
250
+ idKey="id"
251
+ density="balanced"
252
+ dividers="rows"
253
+ textOverflow="truncate"
254
+ hasHover
255
+ />
256
+ </VStack>
257
+ </LayoutContent>
258
+ }
259
+ />
260
+ </div>
261
+ );
273
262
  }