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