astryx-dracula 0.1.5 → 0.2.1

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 (90) hide show
  1. package/README.md +8 -0
  2. package/USAGE.md +13 -0
  3. package/astryx.integration.mjs +3 -0
  4. package/package.json +4 -2
  5. package/templates/ai-chat-landing.template.mjs +6 -0
  6. package/templates/ai-chat-landing.tsx +478 -0
  7. package/templates/ai-chat.template.mjs +6 -0
  8. package/templates/ai-chat.tsx +766 -0
  9. package/templates/blank.template.mjs +6 -0
  10. package/templates/blank.tsx +18 -0
  11. package/templates/centered-hero.template.mjs +6 -0
  12. package/templates/centered-hero.tsx +190 -0
  13. package/templates/classic-gallery.template.mjs +6 -0
  14. package/templates/classic-gallery.tsx +183 -0
  15. package/templates/contact-form.template.mjs +6 -0
  16. package/templates/contact-form.tsx +294 -0
  17. package/templates/dashboard-portfolio.template.mjs +6 -0
  18. package/templates/dashboard-portfolio.tsx +802 -0
  19. package/templates/dashboard.template.mjs +6 -0
  20. package/templates/dashboard.tsx +776 -0
  21. package/templates/detail-page.template.mjs +6 -0
  22. package/templates/detail-page.tsx +697 -0
  23. package/templates/documentation-design.template.mjs +6 -0
  24. package/templates/documentation-design.tsx +753 -0
  25. package/templates/documentation-technical.template.mjs +6 -0
  26. package/templates/documentation-technical.tsx +294 -0
  27. package/templates/documentation.template.mjs +6 -0
  28. package/templates/documentation.tsx +349 -0
  29. package/templates/editor.template.mjs +6 -0
  30. package/templates/editor.tsx +961 -0
  31. package/templates/file-explorer.template.mjs +6 -0
  32. package/templates/file-explorer.tsx +579 -0
  33. package/templates/form-two-column.template.mjs +6 -0
  34. package/templates/form-two-column.tsx +316 -0
  35. package/templates/gallery-hero.template.mjs +6 -0
  36. package/templates/gallery-hero.tsx +289 -0
  37. package/templates/ide.template.mjs +6 -0
  38. package/templates/ide.tsx +537 -0
  39. package/templates/incident-console.template.mjs +6 -0
  40. package/templates/incident-console.tsx +586 -0
  41. package/templates/kanban-board.template.mjs +6 -0
  42. package/templates/kanban-board.tsx +748 -0
  43. package/templates/library.template.mjs +6 -0
  44. package/templates/library.tsx +491 -0
  45. package/templates/login-card.template.mjs +6 -0
  46. package/templates/login-card.tsx +202 -0
  47. package/templates/login-split.template.mjs +6 -0
  48. package/templates/login-split.tsx +316 -0
  49. package/templates/login-sso.template.mjs +6 -0
  50. package/templates/login-sso.tsx +275 -0
  51. package/templates/login.template.mjs +6 -0
  52. package/templates/login.tsx +100 -0
  53. package/templates/messaging-shell.template.mjs +6 -0
  54. package/templates/messaging-shell.tsx +677 -0
  55. package/templates/mixed-gallery.template.mjs +6 -0
  56. package/templates/mixed-gallery.tsx +192 -0
  57. package/templates/payment-form.template.mjs +6 -0
  58. package/templates/payment-form.tsx +992 -0
  59. package/templates/product-detail.template.mjs +6 -0
  60. package/templates/product-detail.tsx +368 -0
  61. package/templates/product-gallery.template.mjs +6 -0
  62. package/templates/product-gallery.tsx +175 -0
  63. package/templates/settings-dialog.template.mjs +6 -0
  64. package/templates/settings-dialog.tsx +926 -0
  65. package/templates/settings-sidebar.template.mjs +6 -0
  66. package/templates/settings-sidebar.tsx +954 -0
  67. package/templates/settings.template.mjs +6 -0
  68. package/templates/settings.tsx +237 -0
  69. package/templates/shell-nav.template.mjs +6 -0
  70. package/templates/shell-nav.tsx +308 -0
  71. package/templates/shell-side-nav.template.mjs +6 -0
  72. package/templates/shell-side-nav.tsx +240 -0
  73. package/templates/shell-top-nav.template.mjs +6 -0
  74. package/templates/shell-top-nav.tsx +245 -0
  75. package/templates/side-gallery.template.mjs +6 -0
  76. package/templates/side-gallery.tsx +181 -0
  77. package/templates/table-grouped.template.mjs +6 -0
  78. package/templates/table-grouped.tsx +1176 -0
  79. package/templates/table-page-chart.template.mjs +6 -0
  80. package/templates/table-page-chart.tsx +699 -0
  81. package/templates/table-page-heatmap-status.template.mjs +6 -0
  82. package/templates/table-page-heatmap-status.tsx +549 -0
  83. package/templates/table-page-shoe-store-heatmap.template.mjs +6 -0
  84. package/templates/table-page-shoe-store-heatmap.tsx +1044 -0
  85. package/templates/table-page.template.mjs +6 -0
  86. package/templates/table-page.tsx +447 -0
  87. package/templates/table.template.mjs +6 -0
  88. package/templates/table.tsx +86 -0
  89. package/templates/theme-showcase.template.mjs +6 -0
  90. package/templates/theme-showcase.tsx +1284 -0
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Blank',
4
+ description: 'Empty layout shell for a new page',
5
+ category: 'tooling',
6
+ };
@@ -0,0 +1,18 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > Tx.lg"A blank crypt awaits its story"
4
+
5
+ import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
6
+ import {Text} from '@astryxdesign/core/Text';
7
+
8
+ export default function BlankPage() {
9
+ return (
10
+ <Layout
11
+ content={
12
+ <LayoutContent>
13
+ <Text type="large">A blank crypt awaits its story</Text>
14
+ </LayoutContent>
15
+ }
16
+ />
17
+ );
18
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Centered Hero',
4
+ description: 'Headline, CTAs, and hero visual',
5
+ category: 'marketing',
6
+ };
@@ -0,0 +1,190 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC > (V[g6 a=center] > Hd"Hero"[level=1] + Tx"Remit"[t=body] + (H[j=center g3] > B.primary"CTA" + B"Secondary"))
4
+
5
+ import type {CSSProperties} from 'react';
6
+ import {VStack, HStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
7
+ import {Text, Heading} from '@astryxdesign/core/Text';
8
+ import {Button} from '@astryxdesign/core/Button';
9
+ import {Icon} from '@astryxdesign/core/Icon';
10
+ import {AspectRatio} from '@astryxdesign/core/AspectRatio';
11
+ import {Section} from '@astryxdesign/core/Section';
12
+ import {ArrowRight} from 'lucide-react';
13
+
14
+ const heroImage: CSSProperties = {
15
+ width: '100%',
16
+ height: '100%',
17
+ display: 'block',
18
+ };
19
+ const heroFrame: CSSProperties = {
20
+ maxWidth: 1200,
21
+ marginInline: 'auto',
22
+ borderRadius: 'var(--radius-page)',
23
+ border: 'var(--border-width) solid var(--color-separator)',
24
+ overflow: 'clip',
25
+ };
26
+
27
+ function NightCastleScene() {
28
+ return (
29
+ <svg
30
+ style={heroImage}
31
+ viewBox="0 0 800 450"
32
+ role="img"
33
+ aria-label="Moonlit castle on a hill in Dracula theme colors">
34
+ <title>Castle under a harvest moon</title>
35
+ <rect width="800" height="450" fill="var(--dracula-bg-dark)" />
36
+ {/* Stars */}
37
+ <g fill="var(--dracula-purple)">
38
+ <circle cx="60" cy="60" r="2.5" />
39
+ <circle cx="180" cy="120" r="2" />
40
+ <circle cx="330" cy="50" r="2.5" />
41
+ <circle cx="470" cy="90" r="2" />
42
+ <circle cx="700" cy="200" r="2.5" />
43
+ <circle cx="750" cy="80" r="2" />
44
+ </g>
45
+ <g fill="var(--dracula-cyan)">
46
+ <circle cx="120" cy="90" r="2" />
47
+ <circle cx="270" cy="70" r="2.5" />
48
+ <circle cx="540" cy="50" r="2" />
49
+ <circle cx="660" cy="160" r="2" />
50
+ </g>
51
+ <g fill="var(--dracula-pink)">
52
+ <circle cx="90" cy="170" r="2" />
53
+ <circle cx="400" cy="130" r="2.5" />
54
+ <circle cx="590" cy="200" r="2" />
55
+ <circle cx="730" cy="260" r="2" />
56
+ </g>
57
+ {/* Harvest moon */}
58
+ <circle cx="620" cy="110" r="56" fill="var(--dracula-yellow)" />
59
+ <circle
60
+ cx="600"
61
+ cy="95"
62
+ r="10"
63
+ fill="var(--dracula-orange)"
64
+ opacity={0.5}
65
+ />
66
+ <circle
67
+ cx="638"
68
+ cy="125"
69
+ r="7"
70
+ fill="var(--dracula-orange)"
71
+ opacity={0.5}
72
+ />
73
+ {/* Bats */}
74
+ <g
75
+ fill="none"
76
+ stroke="var(--dracula-purple)"
77
+ strokeWidth={4}
78
+ strokeLinecap="round">
79
+ <path d="M120 130 q12 -12 24 0 q12 -12 24 0" />
80
+ <path d="M210 90 q9 -9 18 0 q9 -9 18 0" />
81
+ <path d="M470 160 q9 -9 18 0 q9 -9 18 0" />
82
+ </g>
83
+ {/* Hills */}
84
+ <path
85
+ d="M0 330 Q200 260 400 320 T800 300 V450 H0 Z"
86
+ fill="var(--dracula-selection)"
87
+ />
88
+ <path
89
+ d="M0 385 Q240 320 480 375 T800 360 V450 H0 Z"
90
+ fill="var(--dracula-bg-light)"
91
+ />
92
+ {/* Castle */}
93
+ <g>
94
+ <rect
95
+ x="150"
96
+ y="225"
97
+ width="120"
98
+ height="120"
99
+ rx={4}
100
+ fill="var(--dracula-bg-lighter)"
101
+ />
102
+ <rect
103
+ x="130"
104
+ y="185"
105
+ width="44"
106
+ height="160"
107
+ rx={4}
108
+ fill="var(--dracula-bg-lighter)"
109
+ />
110
+ <rect
111
+ x="246"
112
+ y="185"
113
+ width="44"
114
+ height="160"
115
+ rx={4}
116
+ fill="var(--dracula-bg-lighter)"
117
+ />
118
+ <g fill="var(--dracula-bg-lighter)">
119
+ <rect x="130" y="175" width="12" height="14" rx={2} />
120
+ <rect x="149" y="175" width="12" height="14" rx={2} />
121
+ <rect x="246" y="175" width="12" height="14" rx={2} />
122
+ <rect x="265" y="175" width="12" height="14" rx={2} />
123
+ <rect x="150" y="215" width="14" height="16" rx={2} />
124
+ <rect x="173" y="215" width="14" height="16" rx={2} />
125
+ <rect x="196" y="215" width="14" height="16" rx={2} />
126
+ <rect x="219" y="215" width="14" height="16" rx={2} />
127
+ <rect x="242" y="215" width="14" height="16" rx={2} />
128
+ </g>
129
+ <g fill="var(--dracula-yellow)">
130
+ <rect x="168" y="255" width="14" height="20" rx={2} />
131
+ <rect x="203" y="255" width="14" height="20" rx={2} />
132
+ <rect x="238" y="255" width="14" height="20" rx={2} />
133
+ <rect x="143" y="215" width="10" height="14" rx={2} />
134
+ <rect x="259" y="215" width="10" height="14" rx={2} />
135
+ </g>
136
+ <path
137
+ d="M195 345 v-30 a15 15 0 0 1 30 0 v30 Z"
138
+ fill="var(--dracula-bg-dark)"
139
+ />
140
+ </g>
141
+ </svg>
142
+ );
143
+ }
144
+
145
+ export default function CenteredHero() {
146
+ return (
147
+ <Layout
148
+ content={
149
+ <LayoutContent padding={6}>
150
+ <VStack gap={10}>
151
+ <VStack gap={6} hAlign="center">
152
+ <VStack gap={3} hAlign="center">
153
+ <Heading
154
+ level={1}
155
+ type="display-2"
156
+ justify="center"
157
+ textWrap="balance">
158
+ Small joys for creatures of the night
159
+ </Heading>
160
+ <Text
161
+ type="body"
162
+ color="secondary"
163
+ justify="center"
164
+ textWrap="balance">
165
+ Sometimes all it takes is one small ritual to turn the whole
166
+ night around.
167
+ </Text>
168
+ </VStack>
169
+ <HStack gap={3} wrap="wrap" justify="center">
170
+ <Button
171
+ label="Embrace the night"
172
+ variant="primary"
173
+ endContent={
174
+ <Icon icon={ArrowRight} size="sm" color="inherit" />
175
+ }
176
+ />
177
+ <Button label="Read the lore" variant="secondary" />
178
+ </HStack>
179
+ </VStack>
180
+ <Section variant="transparent" padding={0}>
181
+ <AspectRatio ratio={16 / 9} style={heroFrame}>
182
+ <NightCastleScene />
183
+ </AspectRatio>
184
+ </Section>
185
+ </VStack>
186
+ </LayoutContent>
187
+ }
188
+ />
189
+ );
190
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Classic Gallery',
4
+ description: 'Filterable image wall with category tabs',
5
+ category: 'marketing',
6
+ };
@@ -0,0 +1,183 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ // XLE (canonical structure, validated with `bunx astryx layout check`):
3
+ // L > LC[p=0] > Ctr > V[g=8] > (V[g=4 a=center] > (V[g=2 a=center] > Hd"Hung after dark"[level=1] + Tx"A coven-curated wall"[t=body]) + (TL > Tab"All"! + Tab"Lifestyle" + Tab"Scenery" + Tab"Home") + Tx"10 pieces on the wall"[t=supporting]) + (G[g=4] > (C[p=0] > AR)*6)
4
+
5
+ import {useState, type CSSProperties} from 'react';
6
+ import {VStack, Layout, LayoutContent} from '@astryxdesign/core/Layout';
7
+ import {Center} from '@astryxdesign/core/Center';
8
+ import {Card} from '@astryxdesign/core/Card';
9
+ import {AspectRatio} from '@astryxdesign/core/AspectRatio';
10
+ import {Text, Heading} from '@astryxdesign/core/Text';
11
+ import {Grid} from '@astryxdesign/core/Grid';
12
+ import {Section} from '@astryxdesign/core/Section';
13
+ import {TabList, Tab} from '@astryxdesign/core/TabList';
14
+
15
+ // ─── Styles ─────────────────────────────────────────────────────────────────
16
+
17
+ const outer: CSSProperties = {
18
+ maxWidth: 1200,
19
+ width: '100%',
20
+ paddingInline: 'var(--space-viewport)',
21
+ paddingBlock: 'var(--space-viewport)',
22
+ };
23
+ const frameClip: CSSProperties = {
24
+ overflow: 'clip',
25
+ };
26
+ const artImage: CSSProperties = {
27
+ width: '100%',
28
+ height: '100%',
29
+ display: 'block',
30
+ };
31
+ const textCenter: CSSProperties = {
32
+ textAlign: 'center',
33
+ };
34
+
35
+ // ─── Gallery Data ───────────────────────────────────────────────────────────
36
+
37
+ type Category = 'all' | 'lifestyle' | 'scene' | 'home';
38
+
39
+ interface GalleryImage {
40
+ alt: string;
41
+ category: Exclude<Category, 'all'>;
42
+ }
43
+
44
+ // Dracula accent per gallery shelf.
45
+ const CATEGORY_HUES: Record<Exclude<Category, 'all'>, string> = {
46
+ scene: 'var(--dracula-cyan)',
47
+ lifestyle: 'var(--dracula-pink)',
48
+ home: 'var(--dracula-yellow)',
49
+ };
50
+
51
+ const GALLERY_IMAGES: GalleryImage[] = [
52
+ {alt: 'Moonlit ridge trail under a harvest moon', category: 'scene'},
53
+ {alt: 'Late portrait in violet lamplight', category: 'lifestyle'},
54
+ {alt: 'Lamplit reading nook after midnight', category: 'home'},
55
+ {alt: 'Fog rolling over the night pines', category: 'scene'},
56
+ {alt: 'Dancer caught mid-step in stage pink', category: 'lifestyle'},
57
+ {alt: 'Kitchen table set for a midnight feast', category: 'lifestyle'},
58
+ {alt: 'Castle silhouette over sleeping hills', category: 'scene'},
59
+ {alt: 'Attic window glowing amber at 2am', category: 'home'},
60
+ {alt: 'Cellar shelves lined with bottled dusk', category: 'home'},
61
+ {alt: 'Bats crossing a violet harvest moon', category: 'scene'},
62
+ ];
63
+
64
+ // ─── Gallery Art ────────────────────────────────────────────────────────────
65
+
66
+ function GalleryArt({image, index}: {image: GalleryImage; index: number}) {
67
+ const hue = CATEGORY_HUES[image.category];
68
+ const moonX = 90 + ((index * 53) % 220);
69
+ const moonY = 62 + ((index * 29) % 60);
70
+ const hillA = 190 + ((index * 13) % 40);
71
+ const hillB = 215 + ((index * 17) % 40);
72
+ return (
73
+ <svg
74
+ viewBox="0 0 400 300"
75
+ preserveAspectRatio="xMidYMid slice"
76
+ style={artImage}
77
+ role="img"
78
+ aria-label={image.alt}>
79
+ <rect width="400" height="300" fill="var(--dracula-bg-light)" />
80
+ <g fill="var(--dracula-purple)" opacity={0.55}>
81
+ <circle cx={40 + ((index * 37) % 320)} cy={30} r={2} />
82
+ <circle cx={120 + ((index * 23) % 200)} cy={52} r={1.6} />
83
+ <circle cx={260 + ((index * 11) % 110)} cy={26} r={2.2} />
84
+ <circle cx={330} cy={70 + ((index * 7) % 30)} r={1.6} />
85
+ </g>
86
+ <circle cx={moonX} cy={moonY} r={34} fill={hue} opacity={0.9} />
87
+ <circle
88
+ cx={moonX - 12}
89
+ cy={moonY - 8}
90
+ r={28}
91
+ fill="var(--dracula-bg-light)"
92
+ opacity={0.55}
93
+ />
94
+ <path
95
+ d={`M0 ${hillA} Q100 ${hillA - 50} 200 ${hillA - 10} T400 ${hillA - 30} V300 H0 Z`}
96
+ fill="var(--dracula-current-line)"
97
+ />
98
+ <path
99
+ d={`M0 ${hillB} Q120 ${hillB - 40} 240 ${hillB} T400 ${hillB - 20} V300 H0 Z`}
100
+ fill="var(--dracula-bg)"
101
+ />
102
+ <g
103
+ transform={`translate(${60 + ((index * 41) % 280)} ${hillB - 34})`}
104
+ fill="none"
105
+ stroke={hue}
106
+ strokeWidth="4"
107
+ strokeLinecap="round"
108
+ strokeLinejoin="round">
109
+ <rect x="-22" y="-22" width="44" height="44" rx="5" />
110
+ <circle cx="9" cy="-9" r="2" fill={hue} stroke="none" />
111
+ <path d="M-17 15 L-4 0 L5 9 L10 4 L17 12" />
112
+ </g>
113
+ </svg>
114
+ );
115
+ }
116
+
117
+ // ─── Main Page ──────────────────────────────────────────────────────────────
118
+
119
+ export default function ClassicGallery() {
120
+ const [filter, setFilter] = useState<Category>('all');
121
+
122
+ const filteredImages =
123
+ filter === 'all'
124
+ ? GALLERY_IMAGES
125
+ : GALLERY_IMAGES.filter(img => img.category === filter);
126
+
127
+ return (
128
+ <Layout
129
+ height="fill"
130
+ content={
131
+ <LayoutContent padding={0}>
132
+ <Center axis="horizontal">
133
+ <VStack gap={8} style={outer}>
134
+ {/* Header */}
135
+ <Center axis="horizontal">
136
+ <Section variant="transparent" maxWidth={680} padding={0}>
137
+ <VStack gap={4} hAlign="center" style={textCenter}>
138
+ <VStack gap={2} hAlign="center">
139
+ <Heading level={1}>Hung after dark</Heading>
140
+ <Text type="body" color="secondary">
141
+ A coven-curated wall of moonlit ridges, late portraits,
142
+ and lamplit rooms. Filter by haunt and stay a while —
143
+ the gallery never sleeps.
144
+ </Text>
145
+ </VStack>
146
+
147
+ <TabList
148
+ value={filter}
149
+ onChange={v => setFilter(v as Category)}>
150
+ <Tab value="all" label="All" />
151
+ <Tab value="lifestyle" label="Lifestyle" />
152
+ <Tab value="scene" label="Scenery" />
153
+ <Tab value="home" label="Home" />
154
+ </TabList>
155
+ <Text
156
+ type="supporting"
157
+ color="secondary"
158
+ hasTabularNumbers>
159
+ {filteredImages.length}{' '}
160
+ {filteredImages.length === 1 ? 'piece' : 'pieces'} on the
161
+ wall
162
+ </Text>
163
+ </VStack>
164
+ </Section>
165
+ </Center>
166
+
167
+ {/* Gallery Grid */}
168
+ <Grid columns={{minWidth: 260, repeat: 'fit'}} gap={4}>
169
+ {filteredImages.map((image, i) => (
170
+ <Card key={image.alt} padding={0} style={frameClip}>
171
+ <AspectRatio ratio={3 / 2}>
172
+ <GalleryArt image={image} index={i} />
173
+ </AspectRatio>
174
+ </Card>
175
+ ))}
176
+ </Grid>
177
+ </VStack>
178
+ </Center>
179
+ </LayoutContent>
180
+ }
181
+ />
182
+ );
183
+ }
@@ -0,0 +1,6 @@
1
+ export default {
2
+ type: 'page',
3
+ name: 'Contact Form',
4
+ description: 'Lead capture form with goals and budget',
5
+ category: 'forms',
6
+ };