astryx-dracula 0.4.0 → 0.5.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 (121) hide show
  1. package/astryx.integration.mjs +1 -1
  2. package/icons.mjs +17 -17
  3. package/icons.tsx +61 -62
  4. package/package.json +120 -116
  5. package/shared/auth-chrome-config.ts +6 -6
  6. package/shared/auth-chrome.tsx +168 -19
  7. package/shared/auth-copy.ts +14 -14
  8. package/shared/chaptered-doc-config.ts +48 -51
  9. package/shared/chaptered-doc.tsx +270 -292
  10. package/shared/chart-hues.ts +10 -15
  11. package/shared/chart-labels.tsx +31 -30
  12. package/shared/chart-legend.tsx +55 -57
  13. package/shared/chart-panel-style.ts +3 -3
  14. package/shared/data-bar.tsx +97 -102
  15. package/shared/format-money.ts +3 -0
  16. package/shared/gallery-image.ts +6 -6
  17. package/shared/login-demo.ts +1 -1
  18. package/shared/metric-card.tsx +123 -0
  19. package/shared/metric-delta.tsx +28 -27
  20. package/shared/order-desk.tsx +205 -216
  21. package/shared/revenue-chart.tsx +145 -165
  22. package/shared/scene-castle.tsx +206 -291
  23. package/shared/scene-frame.tsx +33 -32
  24. package/shared/scene-hues.ts +17 -25
  25. package/shared/scene-tile.tsx +88 -100
  26. package/shared/settings-data.ts +132 -104
  27. package/shared/settings-rows.tsx +143 -163
  28. package/shared/sparkline.tsx +75 -88
  29. package/shared/sso-icons.tsx +10 -22
  30. package/shared/stars.tsx +19 -0
  31. package/templates/ai-chat-landing.template.mjs +4 -4
  32. package/templates/ai-chat-landing.tsx +468 -447
  33. package/templates/ai-chat.template.mjs +4 -4
  34. package/templates/ai-chat.tsx +561 -645
  35. package/templates/blank.template.mjs +4 -4
  36. package/templates/blank.tsx +14 -12
  37. package/templates/centered-hero.template.mjs +4 -4
  38. package/templates/centered-hero.tsx +52 -67
  39. package/templates/classic-gallery.template.mjs +4 -4
  40. package/templates/classic-gallery.tsx +92 -101
  41. package/templates/contact-form.template.mjs +4 -4
  42. package/templates/contact-form.tsx +243 -280
  43. package/templates/dashboard-portfolio.template.mjs +4 -4
  44. package/templates/dashboard-portfolio.tsx +723 -634
  45. package/templates/dashboard.template.mjs +4 -4
  46. package/templates/dashboard.tsx +592 -682
  47. package/templates/detail-page.template.mjs +4 -4
  48. package/templates/detail-page.tsx +537 -598
  49. package/templates/documentation-design.template.mjs +4 -4
  50. package/templates/documentation-design.tsx +242 -709
  51. package/templates/documentation-technical.template.mjs +4 -4
  52. package/templates/documentation-technical.tsx +233 -258
  53. package/templates/documentation.template.mjs +4 -4
  54. package/templates/documentation.tsx +263 -277
  55. package/templates/editor.template.mjs +4 -4
  56. package/templates/editor.tsx +847 -899
  57. package/templates/file-explorer.template.mjs +4 -4
  58. package/templates/file-explorer.tsx +562 -602
  59. package/templates/form-two-column.template.mjs +4 -4
  60. package/templates/form-two-column.tsx +187 -208
  61. package/templates/gallery-hero.template.mjs +4 -4
  62. package/templates/gallery-hero.tsx +89 -112
  63. package/templates/ide.template.mjs +4 -4
  64. package/templates/ide.tsx +405 -462
  65. package/templates/incident-console.template.mjs +4 -4
  66. package/templates/incident-console.tsx +559 -581
  67. package/templates/kanban-board.template.mjs +4 -4
  68. package/templates/kanban-board.tsx +660 -729
  69. package/templates/library.template.mjs +4 -4
  70. package/templates/library.tsx +405 -452
  71. package/templates/login-card.template.mjs +4 -4
  72. package/templates/login-card.tsx +59 -163
  73. package/templates/login-split.template.mjs +4 -4
  74. package/templates/login-split.tsx +196 -232
  75. package/templates/login-sso.template.mjs +4 -4
  76. package/templates/login-sso.tsx +253 -277
  77. package/templates/login.template.mjs +4 -4
  78. package/templates/login.tsx +51 -149
  79. package/templates/messaging-shell.template.mjs +4 -4
  80. package/templates/messaging-shell.tsx +596 -624
  81. package/templates/mixed-gallery.template.mjs +4 -4
  82. package/templates/mixed-gallery.tsx +56 -56
  83. package/templates/payment-form.template.mjs +4 -4
  84. package/templates/payment-form.tsx +877 -990
  85. package/templates/product-detail.template.mjs +4 -4
  86. package/templates/product-detail.tsx +251 -302
  87. package/templates/product-gallery.template.mjs +4 -4
  88. package/templates/product-gallery.tsx +122 -135
  89. package/templates/product-tour.template.mjs +4 -4
  90. package/templates/product-tour.tsx +737 -794
  91. package/templates/settings-dialog.template.mjs +4 -4
  92. package/templates/settings-dialog.tsx +694 -747
  93. package/templates/settings-sidebar.template.mjs +4 -4
  94. package/templates/settings-sidebar.tsx +768 -848
  95. package/templates/settings.template.mjs +4 -4
  96. package/templates/settings.tsx +306 -230
  97. package/templates/shell-nav.template.mjs +4 -4
  98. package/templates/shell-nav.tsx +217 -277
  99. package/templates/shell-side-nav.template.mjs +4 -4
  100. package/templates/shell-side-nav.tsx +130 -231
  101. package/templates/shell-top-nav.template.mjs +4 -4
  102. package/templates/shell-top-nav.tsx +192 -248
  103. package/templates/side-gallery.template.mjs +4 -4
  104. package/templates/side-gallery.tsx +87 -94
  105. package/templates/table-grouped.template.mjs +4 -4
  106. package/templates/table-grouped.tsx +999 -1201
  107. package/templates/table-page-chart.template.mjs +4 -4
  108. package/templates/table-page-chart.tsx +398 -397
  109. package/templates/table-page-heatmap-status.template.mjs +4 -4
  110. package/templates/table-page-heatmap-status.tsx +479 -527
  111. package/templates/table-page-shoe-store-heatmap.template.mjs +4 -4
  112. package/templates/table-page-shoe-store-heatmap.tsx +746 -746
  113. package/templates/table-page.template.mjs +4 -4
  114. package/templates/table-page.tsx +393 -431
  115. package/templates/table.template.mjs +4 -4
  116. package/templates/table.tsx +93 -99
  117. package/templates/tech-report.template.mjs +4 -4
  118. package/templates/tech-report.tsx +1320 -1324
  119. package/templates/theme-showcase.template.mjs +4 -4
  120. package/templates/theme-showcase.tsx +869 -1246
  121. package/tokens.css +340 -343
@@ -1,25 +1,174 @@
1
1
  // Shared login chrome: page wash + 400px column + Moon brand row + the
2
2
  // autocomplete widen-record TextInput needs (prop type omits input attrs).
3
- import type {CSSProperties} from 'react';
4
- import {Moon} from 'lucide-react';
5
- import {VStack} from '@astryxdesign/core/Layout';
6
- import {Text} from '@astryxdesign/core/Text';
7
- import {Icon} from '@astryxdesign/core/Icon';
8
- import {AUTH_BRAND_NAME} from 'astryx-dracula/shared/auth-copy';
9
- import {
10
- authContentStyle,
11
- authPageStyle,
12
- inputAutoComplete,
13
- } from 'astryx-dracula/shared/auth-chrome-config';
14
3
 
4
+ import { Button } from "@astryxdesign/core/Button";
5
+ import { Card } from "@astryxdesign/core/Card";
6
+ import { Icon } from "@astryxdesign/core/Icon";
7
+ import { VStack } from "@astryxdesign/core/Layout";
8
+ import { Link } from "@astryxdesign/core/Link";
9
+ import { Heading, Text } from "@astryxdesign/core/Text";
10
+ import { TextInput } from "@astryxdesign/core/TextInput";
11
+ import { inputAutoComplete } from "astryx-dracula/shared/auth-chrome-config";
12
+ import {
13
+ AUTH_BRAND_NAME,
14
+ AUTH_EMAIL_PLACEHOLDER,
15
+ AUTH_FORGOT_PASSWORD,
16
+ AUTH_HEADING,
17
+ AUTH_PASSWORD_PLACEHOLDER,
18
+ AUTH_PRIMARY_CTA,
19
+ AUTH_SIGNUP_LINK,
20
+ AUTH_SIGNUP_PROMPT,
21
+ AUTH_SUBTITLE,
22
+ AUTH_TERMS_PREFIX,
23
+ AUTH_TERMS_PRIVACY,
24
+ AUTH_TERMS_SERVICE,
25
+ } from "astryx-dracula/shared/auth-copy";
26
+ import { Moon } from "lucide-react";
27
+ import type { ReactNode } from "react";
15
28
 
16
29
  export function LoginBrand() {
17
- return (
18
- <VStack gap={2} hAlign="center">
19
- <Icon icon={Moon} size="lg" color="secondary" />
20
- <Text type="body" weight="semibold" size="lg">
21
- {AUTH_BRAND_NAME}
22
- </Text>
23
- </VStack>
24
- );
30
+ return (
31
+ <VStack gap={2} hAlign="center">
32
+ <Icon icon={Moon} size="lg" color="secondary" />
33
+ <Text type="body" weight="semibold" size="lg">
34
+ {AUTH_BRAND_NAME}
35
+ </Text>
36
+ </VStack>
37
+ );
38
+ }
39
+
40
+ // Shared password-login core: the centered header, credential fields, primary
41
+ // CTA, signup line and terms line every password page in the family carries.
42
+ // The three pages differed only in what sits between the CTA and the signup
43
+ // line (nothing, or the SSO divider + provider buttons) and in their outer
44
+ // shell — login-split's two-column grid and login-sso's step machine keep
45
+ // their own markup and take the pieces below instead of this whole card.
46
+ export function AuthCard({
47
+ selfHash,
48
+ signupLink = AUTH_SIGNUP_LINK,
49
+ children,
50
+ }: {
51
+ selfHash: string;
52
+ signupLink?: string;
53
+ children: ReactNode;
54
+ }) {
55
+ return (
56
+ <>
57
+ <Card padding={4} width="100%">
58
+ <VStack gap={4} hAlign="stretch">
59
+ <VStack gap={1} hAlign="center">
60
+ <Heading level={1} type="display-2" justify="center">
61
+ {AUTH_HEADING}
62
+ </Heading>
63
+ <Text type="body" color="secondary">
64
+ {AUTH_SUBTITLE}
65
+ </Text>
66
+ </VStack>
67
+ {children}
68
+ {/* Prose link: colour alone is not a cue inside a sentence
69
+ (WCAG 1.4.1 / F73), so it asks for the underline the kit
70
+ only gives on hover. */}
71
+ <VStack hAlign="center">
72
+ <Text type="supporting" color="secondary">
73
+ {AUTH_SIGNUP_PROMPT}{" "}
74
+ <Link href={selfHash} type="supporting" hasUnderline>
75
+ {signupLink}
76
+ </Link>
77
+ </Text>
78
+ </VStack>
79
+ </VStack>
80
+ </Card>
81
+ <AuthTerms selfHash={selfHash} />
82
+ </>
83
+ );
84
+ }
85
+
86
+ // Email + password fields with the shared error/forgot-password rhythm, plus
87
+ // the primary CTA that always follows them. The field gap is 8px (gap={2}),
88
+ // not the outer 16px: without the group the two inputs sat twice as far
89
+ // apart as the fields below them.
90
+ export function AuthLoginFields({
91
+ email,
92
+ password,
93
+ error,
94
+ selfHash,
95
+ isLoading,
96
+ onEmailChange,
97
+ onPasswordChange,
98
+ onSubmit,
99
+ }: {
100
+ email: string;
101
+ password: string;
102
+ error: string | null;
103
+ selfHash: string;
104
+ isLoading: boolean;
105
+ onEmailChange: (value: string) => void;
106
+ onPasswordChange: (value: string) => void;
107
+ onSubmit: () => void;
108
+ }) {
109
+ return (
110
+ <>
111
+ <VStack gap={2}>
112
+ <TextInput
113
+ label="Email"
114
+ isLabelHidden
115
+ value={email}
116
+ onChange={onEmailChange}
117
+ placeholder={AUTH_EMAIL_PLACEHOLDER}
118
+ type="email"
119
+ {...inputAutoComplete("email")}
120
+ size="lg"
121
+ onEnter={onSubmit}
122
+ status={error ? { type: "error", message: error } : undefined}
123
+ />
124
+ <VStack gap={1}>
125
+ <TextInput
126
+ label="Password"
127
+ isLabelHidden
128
+ value={password}
129
+ onChange={onPasswordChange}
130
+ placeholder={AUTH_PASSWORD_PLACEHOLDER}
131
+ type="password"
132
+ {...inputAutoComplete("current-password")}
133
+ size="lg"
134
+ onEnter={onSubmit}
135
+ status={error ? { type: "error", message: error } : undefined}
136
+ />
137
+ {error && (
138
+ <VStack hAlign="end">
139
+ <Link href={selfHash} color="secondary" isStandalone>
140
+ {AUTH_FORGOT_PASSWORD}
141
+ </Link>
142
+ </VStack>
143
+ )}
144
+ </VStack>
145
+ </VStack>
146
+ <Button
147
+ label={AUTH_PRIMARY_CTA}
148
+ variant="primary"
149
+ size="lg"
150
+ isLoading={isLoading}
151
+ onClick={onSubmit}
152
+ />
153
+ </>
154
+ );
155
+ }
156
+
157
+ // The family terms line, rendered below the card in the page column.
158
+ export function AuthTerms({ selfHash }: { selfHash: string }) {
159
+ return (
160
+ <VStack hAlign="center" width="100%">
161
+ <Text type="supporting" color="secondary" justify="center">
162
+ {AUTH_TERMS_PREFIX}{" "}
163
+ <Link href={selfHash} type="supporting" hasUnderline>
164
+ {AUTH_TERMS_SERVICE}
165
+ </Link>{" "}
166
+ and{" "}
167
+ <Link href={selfHash} type="supporting" hasUnderline>
168
+ {AUTH_TERMS_PRIVACY}
169
+ </Link>
170
+ .
171
+ </Text>
172
+ </VStack>
173
+ );
25
174
  }
@@ -1,22 +1,22 @@
1
1
  // Auth copy shared by the four login templates. Single-sourced so the family
2
2
  // line cannot drift again. SSO-specific strings (Work email, Whisper your
3
3
  // details, Continue with SSO, provider names) stay per-template in login-sso.
4
- export const AUTH_HEADING = 'Welcome back to the night';
5
- export const AUTH_SUBTITLE = 'Sign in to your crypt';
6
- export const AUTH_PRIMARY_CTA = 'Sign in';
7
- export const AUTH_SIGNUP_PROMPT = 'New to the castle?';
8
- export const AUTH_SIGNUP_LINK = 'Sign up';
9
- export const AUTH_SSO_DIVIDER = 'Or continue with';
10
- export const AUTH_FORGOT_PASSWORD = 'Forgot password?';
4
+ export const AUTH_HEADING = "Welcome back to the night";
5
+ export const AUTH_SUBTITLE = "Sign in to your crypt";
6
+ export const AUTH_PRIMARY_CTA = "Sign in";
7
+ export const AUTH_SIGNUP_PROMPT = "New to the castle?";
8
+ export const AUTH_SIGNUP_LINK = "Sign up";
9
+ export const AUTH_SSO_DIVIDER = "Or continue with";
10
+ export const AUTH_FORGOT_PASSWORD = "Forgot password?";
11
11
  // Names the problem without apologising, and does not blame one field: a
12
12
  // mistyped email used to be reported as a wrong password, because this string
13
13
  // was attached to the password input only.
14
- export const AUTH_ERROR_MESSAGE = 'Email or password is wrong. Try again.';
15
- export const AUTH_EMAIL_PLACEHOLDER = 'you@castle.dracula';
14
+ export const AUTH_ERROR_MESSAGE = "Email or password is wrong. Try again.";
15
+ export const AUTH_EMAIL_PLACEHOLDER = "you@castle.dracula";
16
16
  // The placeholder is the only visible name on the credential inputs, so it has
17
17
  // to actually name the field. "Whisper your password" named nothing.
18
- export const AUTH_PASSWORD_PLACEHOLDER = 'Your password';
19
- export const AUTH_BRAND_NAME = 'Castle Dracula';
20
- export const AUTH_TERMS_PREFIX = 'By clicking continue, you agree to our';
21
- export const AUTH_TERMS_SERVICE = 'Terms of service';
22
- export const AUTH_TERMS_PRIVACY = 'Privacy policy';
18
+ export const AUTH_PASSWORD_PLACEHOLDER = "Your password";
19
+ export const AUTH_BRAND_NAME = "Castle Dracula";
20
+ export const AUTH_TERMS_PREFIX = "By clicking continue, you agree to our";
21
+ export const AUTH_TERMS_SERVICE = "Terms of service";
22
+ export const AUTH_TERMS_PRIVACY = "Privacy policy";
@@ -9,84 +9,81 @@
9
9
  // documentation-technical, product-tour, tech-report) share lives here; the
10
10
  // outline-building and scroll helpers that only chaptered-doc itself calls stay
11
11
  // unexported in that file.
12
- import type {CSSProperties} from 'react';
13
- import type {IconType} from '@astryxdesign/core/Icon';
14
- import type {OutlineItem} from '@astryxdesign/core/Outline';
12
+
13
+ import type { IconType } from "@astryxdesign/core/Icon";
14
+ import type { OutlineItem } from "@astryxdesign/core/Outline";
15
+ import type { CSSProperties } from "react";
15
16
 
16
17
  // ─── Types ───────────────────────────────────────────────────────────────────
17
18
 
18
19
  export interface DocSection {
19
- // Unique within the chapter; the DOM id is derived from it so the outline
20
- // links and the headings can never drift apart.
21
- key: string;
22
- heading: string;
23
- body: string;
24
- bullets?: string[];
25
- code?: {language: string; title: string; source: string};
20
+ // Unique within the chapter; the DOM id is derived from it so the outline
21
+ // links and the headings can never drift apart.
22
+ key: string;
23
+ heading: string;
24
+ body: string;
25
+ bullets?: string[];
26
+ code?: { language: string; title: string; source: string };
26
27
  }
27
28
 
28
29
  export interface DocChapter {
29
- id: string;
30
- title: string;
31
- icon: IconType;
32
- intro: string;
33
- hasArt?: boolean;
34
- sections: DocSection[];
30
+ id: string;
31
+ title: string;
32
+ icon: IconType;
33
+ intro: string;
34
+ hasArt?: boolean;
35
+ sections: DocSection[];
35
36
  }
36
37
 
37
- export type ChapterGroup = {title: string; chapters: DocChapter[]};
38
+ export type ChapterGroup = { title: string; chapters: DocChapter[] };
38
39
 
39
- export const sectionId = (chapterId: string, key: string) =>
40
- `${chapterId}--${key}`;
40
+ export const sectionId = (chapterId: string, key: string) => `${chapterId}--${key}`;
41
41
 
42
42
  // Astryx has no image primitive: AspectRatio exposes no objectFit or radius
43
43
  // props, so the scene fill and the corner clip live in these two styles.
44
44
  export const sceneFill: CSSProperties = {
45
- width: '100%',
46
- height: '100%',
47
- display: 'block',
45
+ width: "100%",
46
+ height: "100%",
47
+ display: "block",
48
48
  };
49
49
  export const sceneClip: CSSProperties = {
50
- borderRadius: 'var(--radius-container)',
51
- overflow: 'clip',
50
+ borderRadius: "var(--radius-container)",
51
+ overflow: "clip",
52
52
  };
53
53
 
54
54
  // The outline is sticky so it tracks the chapter as the document scrolls.
55
55
  export const outlinePanel: CSSProperties = {
56
- position: 'sticky',
57
- top: 'var(--spacing-6)',
58
- alignSelf: 'start',
59
- // No paddingBlockStart. This object is applied via `style=` to the outline
60
- // LayoutPanels (chaptered-doc.tsx:316, documentation-design.tsx:592,
61
- // documentation-technical.tsx:82), and an inline style prop BEATS the stylex
62
- // class -- so this 8px silently overrode the panel's own 16px block padding
63
- // at the top edge only, leaving every "On this page" rail in the kit
64
- // asymmetric by 8px. The panel already owns its block padding.
56
+ position: "sticky",
57
+ top: "var(--spacing-6)",
58
+ alignSelf: "start",
59
+ // No paddingBlockStart. This object is applied via `style=` to the outline
60
+ // LayoutPanels (chaptered-doc.tsx:316, documentation-design.tsx:592,
61
+ // documentation-technical.tsx:82), and an inline style prop BEATS the stylex
62
+ // class -- so this 8px silently overrode the panel's own 16px block padding
63
+ // at the top edge only, leaving every "On this page" rail in the kit
64
+ // asymmetric by 8px. The panel already owns its block padding.
65
65
  };
66
66
 
67
67
  // Derived once per page so the Outline receives a stable array identity
68
68
  // and does not re-register its scroll spy on every render.
69
- export function buildOutlineByChapter(
70
- chapters: DocChapter[],
71
- ): Record<string, OutlineItem[]> {
72
- return Object.fromEntries(
73
- chapters.map(chapter => [
74
- chapter.id,
75
- chapter.sections.map(section => ({
76
- id: sectionId(chapter.id, section.key),
77
- label: section.heading,
78
- level: 2,
79
- })),
80
- ]),
81
- );
69
+ export function buildOutlineByChapter(chapters: DocChapter[]): Record<string, OutlineItem[]> {
70
+ return Object.fromEntries(
71
+ chapters.map((chapter) => [
72
+ chapter.id,
73
+ chapter.sections.map((section) => ({
74
+ id: sectionId(chapter.id, section.key),
75
+ label: section.heading,
76
+ level: 2,
77
+ })),
78
+ ]),
79
+ );
82
80
  }
83
81
 
84
82
  export function scrollToSection(id: string) {
85
- const target = document.getElementById(id);
86
- if (target != null) {
87
- target.scrollIntoView({behavior: 'smooth', block: 'start'});
88
- }
83
+ const target = document.getElementById(id);
84
+ if (target != null) {
85
+ target.scrollIntoView({ behavior: "smooth", block: "start" });
86
+ }
89
87
  }
90
88
 
91
89
  // ─── Rail ────────────────────────────────────────────────────────────────────
92
-