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
@@ -7,7 +7,7 @@
7
7
  // which the chart vocabulary already uses, so the kit has one shape rather than
8
8
  // one precedent and one exception.
9
9
 
10
- export type SceneTileSize = 'lg' | 'sm';
10
+ export type SceneTileSize = "lg" | "sm";
11
11
 
12
12
  /**
13
13
  * Art-treatment hues for scene tiles. Purple-free by this module's remit.
@@ -15,13 +15,13 @@ export type SceneTileSize = 'lg' | 'sm';
15
15
  * on both dark surfaces at the disc's 0.9 opacity, including purple.
16
16
  */
17
17
  export const SCENE_HUES = {
18
- muted: 'var(--dracula-comment)',
19
- cyan: 'var(--dracula-cyan)',
20
- green: 'var(--dracula-green)',
21
- yellow: 'var(--dracula-yellow)',
22
- orange: 'var(--dracula-orange)',
23
- pink: 'var(--dracula-pink)',
24
- red: 'var(--dracula-red)',
18
+ muted: "var(--dracula-comment)",
19
+ cyan: "var(--dracula-cyan)",
20
+ green: "var(--dracula-green)",
21
+ yellow: "var(--dracula-yellow)",
22
+ orange: "var(--dracula-orange)",
23
+ pink: "var(--dracula-pink)",
24
+ red: "var(--dracula-red)",
25
25
  } as const;
26
26
 
27
27
  export type SceneHue = (typeof SCENE_HUES)[keyof typeof SCENE_HUES];
@@ -29,13 +29,13 @@ export type SceneHue = (typeof SCENE_HUES)[keyof typeof SCENE_HUES];
29
29
  // Shared alt list for the nine-tile side/classic wall (folded into one
30
30
  // module so the two surfaces cannot drift apart again).
31
31
  export const SCENE_TILE_ALTS = [
32
- 'Moonlit ridge trail under a harvest moon',
33
- 'Late portrait in violet lamplight',
34
- 'Lamplit reading nook after midnight',
35
- 'Fog rolling over the night pines',
36
- 'Dancer caught mid-step in stage pink',
37
- 'Kitchen table set for a midnight feast',
38
- 'Castle silhouette over sleeping hills',
39
- 'Attic window glowing amber at 2am',
40
- 'Cellar shelves lined with bottled dusk',
32
+ "Moonlit ridge trail under a harvest moon",
33
+ "Late portrait in violet lamplight",
34
+ "Lamplit reading nook after midnight",
35
+ "Fog rolling over the night pines",
36
+ "Dancer caught mid-step in stage pink",
37
+ "Kitchen table set for a midnight feast",
38
+ "Castle silhouette over sleeping hills",
39
+ "Attic window glowing amber at 2am",
40
+ "Cellar shelves lined with bottled dusk",
41
41
  ] as const;
@@ -21,100 +21,96 @@
21
21
  // reached a 34px disc. The union turns that into a compile error at the call
22
22
  // site with the exact offending value named.
23
23
 
24
- import {galleryImage} from 'astryx-dracula/shared/gallery-image';
25
- import type {SceneHue, SceneTileSize} from 'astryx-dracula/shared/scene-hues';
26
-
24
+ import { galleryImage } from "astryx-dracula/shared/gallery-image";
25
+ import type { SceneHue, SceneTileSize } from "astryx-dracula/shared/scene-hues";
27
26
 
28
27
  interface SceneTileProps {
29
- /**
30
- * Per-tile accent: the sm fork paints it as the moon disc (`:70`, a 34px
31
- * radius at 0.9 opacity) and as glyph dots; the lg fork paints the glyph.
32
- * One prop, three areas of very different size — the split by role is a
33
- * deliberate follow-up, not an oversight. Both areas clear 1.4.11 at the
34
- * same `SceneHue`, so the split is about which role may take which subset,
35
- * not about a second contrast axis.
36
- */
37
- hue: SceneHue;
38
- /** Accessible name for the tile art. */
39
- label: string;
40
- /** `lg` for grid thumbs, `sm` for the classic/side landscape tiles. */
41
- size?: SceneTileSize;
42
- /** Positional seed so repeated sm tiles vary moon, hills, and star field.
43
- * Ignored by the lg fork (one centered glyph, no variance). */
44
- index?: number;
28
+ /**
29
+ * Per-tile accent: the sm fork paints it as the moon disc (`:70`, a 34px
30
+ * radius at 0.9 opacity) and as glyph dots; the lg fork paints the glyph.
31
+ * One prop, three areas of very different size — the split by role is a
32
+ * deliberate follow-up, not an oversight. Both areas clear 1.4.11 at the
33
+ * same `SceneHue`, so the split is about which role may take which subset,
34
+ * not about a second contrast axis.
35
+ */
36
+ hue: SceneHue;
37
+ /** Accessible name for the tile art. */
38
+ label: string;
39
+ /** `lg` for grid thumbs, `sm` for the classic/side landscape tiles. */
40
+ size?: SceneTileSize;
41
+ /** Positional seed so repeated sm tiles vary moon, hills, and star field.
42
+ * Ignored by the lg fork (one centered glyph, no variance). */
43
+ index?: number;
45
44
  }
46
45
 
47
-
48
- export function SceneTile({
49
- hue,
50
- label,
51
- size = 'lg',
52
- index = 0,
53
- }: SceneTileProps) {
54
- const moonX = 90 + ((index * 53) % 220);
55
- const moonY = 62 + ((index * 29) % 60);
56
- const hillA = 190 + ((index * 13) % 40);
57
- const hillB = 215 + ((index * 17) % 40);
58
- return (
59
- <svg
60
- viewBox="0 0 400 300"
61
- preserveAspectRatio="xMidYMid slice"
62
- style={galleryImage}
63
- role="img"
64
- aria-label={label}>
65
- <rect width="400" height="300" fill="var(--dracula-bg-light)" />
66
- {size === 'sm' && (
67
- <>
68
- {/* Stars: decorative wash, comment so purple stays reserved for tappables. */}
69
- <g fill="var(--dracula-comment)" opacity={0.55}>
70
- <circle cx={40 + ((index * 37) % 320)} cy={30} r={2} />
71
- <circle cx={120 + ((index * 23) % 200)} cy={52} r={1.6} />
72
- <circle cx={260 + ((index * 11) % 110)} cy={26} r={2.2} />
73
- <circle cx={330} cy={70 + ((index * 7) % 30)} r={1.6} />
74
- </g>
75
- <circle cx={moonX} cy={moonY} r={34} fill={hue} opacity={0.9} />
76
- <circle
77
- cx={moonX - 12}
78
- cy={moonY - 8}
79
- r={28}
80
- fill="var(--dracula-bg-light)"
81
- opacity={0.55}
82
- />
83
- <path
84
- d={`M0 ${hillA} Q100 ${hillA - 50} 200 ${hillA - 10} T400 ${hillA - 30} V300 H0 Z`}
85
- fill="var(--dracula-current-line)"
86
- />
87
- <path
88
- d={`M0 ${hillB} Q120 ${hillB - 40} 240 ${hillB} T400 ${hillB - 20} V300 H0 Z`}
89
- fill="var(--dracula-bg)"
90
- />
91
- </>
92
- )}
93
- {size === 'sm' ? (
94
- <g
95
- transform={`translate(${60 + ((index * 41) % 280)} ${hillB - 34})`}
96
- fill="none"
97
- stroke={hue}
98
- strokeWidth="4"
99
- strokeLinecap="round"
100
- strokeLinejoin="round">
101
- <rect x="-22" y="-22" width="44" height="44" rx={4} />
102
- <circle cx="9" cy="-9" r="2" fill={hue} stroke="none" />
103
- <path d="M-17 15 L-4 0 L5 9 L10 4 L17 12" />
104
- </g>
105
- ) : (
106
- <g
107
- transform="translate(200 150)"
108
- fill="none"
109
- stroke="var(--dracula-comment)"
110
- strokeWidth="5"
111
- strokeLinecap="round"
112
- strokeLinejoin="round">
113
- <rect x="-44" y="-44" width="88" height="88" rx="5" />
114
- <circle cx="18" cy="-18" r="2.5" fill={hue} stroke="none" />
115
- <path d="M-34 30 L-8 0 L10 18 L20 8 L34 24" />
116
- </g>
117
- )}
118
- </svg>
119
- );
46
+ export function SceneTile({ hue, label, size = "lg", index = 0 }: SceneTileProps) {
47
+ const moonX = 90 + ((index * 53) % 220);
48
+ const moonY = 62 + ((index * 29) % 60);
49
+ const hillA = 190 + ((index * 13) % 40);
50
+ const hillB = 215 + ((index * 17) % 40);
51
+ return (
52
+ <svg
53
+ viewBox="0 0 400 300"
54
+ preserveAspectRatio="xMidYMid slice"
55
+ style={galleryImage}
56
+ role="img"
57
+ aria-label={label}
58
+ >
59
+ <rect width="400" height="300" fill="var(--dracula-bg-light)" />
60
+ {size === "sm" && (
61
+ <>
62
+ {/* Stars: decorative wash, comment so purple stays reserved for tappables. */}
63
+ <g fill="var(--dracula-comment)" opacity={0.55}>
64
+ <circle cx={40 + ((index * 37) % 320)} cy={30} r={2} />
65
+ <circle cx={120 + ((index * 23) % 200)} cy={52} r={1.6} />
66
+ <circle cx={260 + ((index * 11) % 110)} cy={26} r={2.2} />
67
+ <circle cx={330} cy={70 + ((index * 7) % 30)} r={1.6} />
68
+ </g>
69
+ <circle cx={moonX} cy={moonY} r={34} fill={hue} opacity={0.9} />
70
+ <circle
71
+ cx={moonX - 12}
72
+ cy={moonY - 8}
73
+ r={28}
74
+ fill="var(--dracula-bg-light)"
75
+ opacity={0.55}
76
+ />
77
+ <path
78
+ d={`M0 ${hillA} Q100 ${hillA - 50} 200 ${hillA - 10} T400 ${hillA - 30} V300 H0 Z`}
79
+ fill="var(--dracula-current-line)"
80
+ />
81
+ <path
82
+ d={`M0 ${hillB} Q120 ${hillB - 40} 240 ${hillB} T400 ${hillB - 20} V300 H0 Z`}
83
+ fill="var(--dracula-bg)"
84
+ />
85
+ </>
86
+ )}
87
+ {size === "sm" ? (
88
+ <g
89
+ transform={`translate(${60 + ((index * 41) % 280)} ${hillB - 34})`}
90
+ fill="none"
91
+ stroke={hue}
92
+ strokeWidth="4"
93
+ strokeLinecap="round"
94
+ strokeLinejoin="round"
95
+ >
96
+ <rect x="-22" y="-22" width="44" height="44" rx={4} />
97
+ <circle cx="9" cy="-9" r="2" fill={hue} stroke="none" />
98
+ <path d="M-17 15 L-4 0 L5 9 L10 4 L17 12" />
99
+ </g>
100
+ ) : (
101
+ <g
102
+ transform="translate(200 150)"
103
+ fill="none"
104
+ stroke="var(--dracula-comment)"
105
+ strokeWidth="5"
106
+ strokeLinecap="round"
107
+ strokeLinejoin="round"
108
+ >
109
+ <rect x="-44" y="-44" width="88" height="88" rx="5" />
110
+ <circle cx="18" cy="-18" r="2.5" fill={hue} stroke="none" />
111
+ <path d="M-34 30 L-8 0 L10 18 L20 8 L34 24" />
112
+ </g>
113
+ )}
114
+ </svg>
115
+ );
120
116
  }
@@ -5,41 +5,36 @@
5
5
  // row instead of hot-updating. `react-doctor/only-export-components` catches it.
6
6
  // Three templates (settings, settings-sidebar, settings-dialog) read from here,
7
7
  // so this data is genuinely shared rather than co-located by accident.
8
- import type {CSSProperties} from 'react';
9
- import type {LucideIcon} from 'lucide-react';
8
+
9
+ import type { LucideIcon } from "lucide-react";
10
10
  import {
11
- Bell,
12
- Briefcase,
13
- CreditCard,
14
- FileText,
15
- Fingerprint,
16
- Globe,
17
- KeyRound,
18
- Laptop,
19
- Lock,
20
- Share2,
21
- ShieldCheck,
22
- Smartphone,
23
- SquarePen,
24
- Tablet,
25
- User,
26
- UserCog,
27
- } from 'lucide-react';
11
+ Bell,
12
+ Briefcase,
13
+ CreditCard,
14
+ FileText,
15
+ Globe,
16
+ Lock,
17
+ Share2,
18
+ ShieldCheck,
19
+ SquarePen,
20
+ User,
21
+ } from "lucide-react";
22
+ import type { CSSProperties } from "react";
28
23
 
29
24
  export interface SettingsNavItem {
30
- label: string;
31
- icon: LucideIcon;
25
+ label: string;
26
+ icon: LucideIcon;
32
27
  }
33
28
 
34
29
  export const NAV_ITEMS: SettingsNavItem[] = [
35
- {label: 'Personal information', icon: User},
36
- {label: 'Login & security', icon: Lock},
37
- {label: 'Privacy', icon: ShieldCheck},
38
- {label: 'Notifications', icon: Bell},
39
- {label: 'Taxes', icon: FileText},
40
- {label: 'Payments', icon: CreditCard},
41
- {label: 'Languages & currency', icon: Globe},
42
- {label: 'Travel for work', icon: Briefcase},
30
+ { label: "Personal information", icon: User },
31
+ { label: "Login & security", icon: Lock },
32
+ { label: "Privacy", icon: ShieldCheck },
33
+ { label: "Notifications", icon: Bell },
34
+ { label: "Taxes", icon: FileText },
35
+ { label: "Payments", icon: CreditCard },
36
+ { label: "Languages & currency", icon: Globe },
37
+ { label: "Travel for work", icon: Briefcase },
43
38
  ];
44
39
 
45
40
  /**
@@ -49,45 +44,45 @@ export const NAV_ITEMS: SettingsNavItem[] = [
49
44
  * outrank the panel's own primary, `ghost` would leave an action with no
50
45
  * affordance at all. Only the two that can be are offered.
51
46
  */
52
- export type RowActionVariant = 'secondary' | 'destructive';
47
+ export type RowActionVariant = "secondary" | "destructive";
53
48
  export interface InfoRow {
54
- label: string;
55
- value: string;
56
- action: string;
57
- /**
58
- * What `action` actually is. 'action' (the default) changes state in place
59
- * and renders a Button; 'destination' navigates and renders a Link. Stated
60
- * in the data rather than inferred from `href` or read off the label, so
61
- * renaming "View" cannot silently turn a destination back into an action.
62
- */
63
- actionKind?: 'action' | 'destination';
64
- /** Where a 'destination' action goes. Read only when actionKind is 'destination'. */
65
- href?: string;
66
- /**
67
- * Visual weight of the trailing Button. `secondary` is the default and the
68
- * right answer for almost every row. `destructive` is for a row whose action
69
- * ends or destroys something — disconnecting an account, deleting data — so
70
- * that control agrees with the templates' inline Deactivate/Delete buttons
71
- * instead of rendering identically to "Create" sitting above it. Stated
72
- * here for the same reason `actionKind` is: the renderer cannot recover it
73
- * from the label without reading the English verb off the row, which is how
74
- * "View" became a button in the first place. Ignored for a `'destination'`
75
- * row, which renders a Link and takes no variant.
76
- */
77
- variant?: RowActionVariant;
78
- /**
79
- * What the Button does, when something wants it to. Optional on purpose: a
80
- * row with no `onAction` renders an inert control, which is the honest
81
- * default for a showcase with no backend — better than a toggle that flips
82
- * "Connected" to "Disconnected" and pretends a call happened. A consumer
83
- * that has a real handler passes one and the row goes live. Nothing here
84
- * simulates a result or invents state to make the button look busy.
85
- */
86
- onAction?: () => void;
49
+ label: string;
50
+ value: string;
51
+ action: string;
52
+ /**
53
+ * What `action` actually is. 'action' (the default) changes state in place
54
+ * and renders a Button; 'destination' navigates and renders a Link. Stated
55
+ * in the data rather than inferred from `href` or read off the label, so
56
+ * renaming "View" cannot silently turn a destination back into an action.
57
+ */
58
+ actionKind?: "action" | "destination";
59
+ /** Where a 'destination' action goes. Read only when actionKind is 'destination'. */
60
+ href?: string;
61
+ /**
62
+ * Visual weight of the trailing Button. `secondary` is the default and the
63
+ * right answer for almost every row. `destructive` is for a row whose action
64
+ * ends or destroys something — disconnecting an account, deleting data — so
65
+ * that control agrees with the templates' inline Deactivate/Delete buttons
66
+ * instead of rendering identically to "Create" sitting above it. Stated
67
+ * here for the same reason `actionKind` is: the renderer cannot recover it
68
+ * from the label without reading the English verb off the row, which is how
69
+ * "View" became a button in the first place. Ignored for a `'destination'`
70
+ * row, which renders a Link and takes no variant.
71
+ */
72
+ variant?: RowActionVariant;
73
+ /**
74
+ * What the Button does, when something wants it to. Optional on purpose: a
75
+ * row with no `onAction` renders an inert control, which is the honest
76
+ * default for a showcase with no backend — better than a toggle that flips
77
+ * "Connected" to "Disconnected" and pretends a call happened. A consumer
78
+ * that has a real handler passes one and the row goes live. Nothing here
79
+ * simulates a result or invents state to make the button look busy.
80
+ */
81
+ onAction?: () => void;
87
82
  }
88
83
 
89
84
  export const LOGIN_ROWS: InfoRow[] = [
90
- {label: 'Password', value: 'Not created', action: 'Create'},
85
+ { label: "Password", value: "Not created", action: "Create" },
91
86
  ];
92
87
 
93
88
  // Disconnecting ends an account link the user set up on purpose, so it is the
@@ -95,101 +90,100 @@ export const LOGIN_ROWS: InfoRow[] = [
95
90
  // position. LOGIN_ROWS' "Create" is the opposite (it adds a password) and
96
91
  // keeps the default `secondary`.
97
92
  export const SOCIAL_ROWS: InfoRow[] = [
98
- {label: 'Google', value: 'Connected', action: 'Disconnect', variant: 'destructive'},
93
+ { label: "Google", value: "Connected", action: "Disconnect", variant: "destructive" },
99
94
  ];
100
95
 
101
96
  export interface DeviceRow {
102
- label: string;
103
- isCurrent?: boolean;
104
- location: string;
105
- action?: string;
97
+ label: string;
98
+ isCurrent?: boolean;
99
+ location: string;
100
+ action?: string;
106
101
  }
107
102
 
108
103
  export const DEVICE_ROWS: DeviceRow[] = [
109
- {
110
- label: 'OS X 10.15.7 · Chrome',
111
- isCurrent: true,
112
- location: 'Brașov, Transylvania · March 30, 2026 at 19:31',
113
- },
114
- {label: 'Session', location: 'August 9, 2023 at 04:19', action: 'Log out'},
115
- {
116
- label: 'OS X 10.15.7 · unknown',
117
- location: 'Whitby, England · April 14, 2023 at 17:47',
118
- action: 'Log out',
119
- },
104
+ {
105
+ label: "OS X 10.15.7 · Chrome",
106
+ isCurrent: true,
107
+ location: "Brașov, Transylvania · March 30, 2026 at 19:31",
108
+ },
109
+ { label: "Session", location: "August 9, 2023 at 04:19", action: "Log out" },
110
+ {
111
+ label: "OS X 10.15.7 · unknown",
112
+ location: "Whitby, England · April 14, 2023 at 17:47",
113
+ action: "Log out",
114
+ },
120
115
  ];
121
116
 
122
117
  export interface InfoTileData {
123
- icon: LucideIcon;
124
- title: string;
125
- body: string;
118
+ icon: LucideIcon;
119
+ title: string;
120
+ body: string;
126
121
  }
127
122
 
128
123
  export const INFO_TILES: InfoTileData[] = [
129
- {
130
- icon: Lock,
131
- title: "Why isn't my info shown here?",
132
- body: "We're veiling some crypt details to protect your identity.",
133
- },
134
- {
135
- icon: SquarePen,
136
- title: 'Which details can be edited?',
137
- body: "Contact runes and personal details can be edited. If these were used to verify your identity, you'll need to be verified anew before your next stay, or to keep hosting your crypt.",
138
- },
139
- {
140
- icon: Share2,
141
- title: 'What info is shared with others?',
142
- body: 'We only release contact runes after a booking is sealed.',
143
- },
124
+ {
125
+ icon: Lock,
126
+ title: "Why isn't my info shown here?",
127
+ body: "We're veiling some crypt details to protect your identity.",
128
+ },
129
+ {
130
+ icon: SquarePen,
131
+ title: "Which details can be edited?",
132
+ body: "Contact runes and personal details can be edited. If these were used to verify your identity, you'll need to be verified anew before your next stay, or to keep hosting your crypt.",
133
+ },
134
+ {
135
+ icon: Share2,
136
+ title: "What info is shared with others?",
137
+ body: "We only release contact runes after a booking is sealed.",
138
+ },
144
139
  ];
145
140
 
146
141
  // Shared row chrome: the icon chip, nowrap action column, and sidebar heading
147
142
  // offset duplicated across settings-dialog and settings-sidebar. Tokens only,
148
143
  // no layout opinions — templates keep their own padding/dividers.
149
144
  export const iconBox: CSSProperties = {
150
- borderRadius: 'var(--radius-container)',
151
- backgroundColor: 'var(--color-background-surface)',
152
- flexShrink: 0,
145
+ borderRadius: "var(--radius-container)",
146
+ backgroundColor: "var(--color-background-surface)",
147
+ flexShrink: 0,
153
148
  };
154
149
 
155
150
  // Keeps row actions ("Log out", "Deactivate") on one line: without this the
156
151
  // action column wraps mid-phrase at tablet widths while the info column still
157
152
  // has room to wrap instead.
158
153
  export const actionNoWrap: CSSProperties = {
159
- flexShrink: 0,
160
- whiteSpace: 'nowrap',
154
+ flexShrink: 0,
155
+ whiteSpace: "nowrap",
161
156
  };
162
157
 
163
158
  // Aligns the sidebar heading with list-item label text. No heading margin prop.
164
159
  export const sideNavHeading: CSSProperties = {
165
- marginInline: 'var(--spacing-4)',
160
+ marginInline: "var(--spacing-4)",
166
161
  };
167
162
 
168
163
  // Locale pickers shared by the sidebar and dialog templates. The two copies
169
164
  // were byte-identical walls; a single source keeps them in sync.
170
- export const LANGUAGES: {label: string; value: string}[] = [
171
- {label: 'English (Canada)', value: 'en-CA'},
172
- {label: 'English (US)', value: 'en-US'},
173
- {label: 'French', value: 'fr'},
174
- {label: 'Spanish', value: 'es'},
175
- {label: 'German', value: 'de'},
176
- {label: 'Japanese', value: 'ja'},
165
+ export const LANGUAGES: { label: string; value: string }[] = [
166
+ { label: "English (Canada)", value: "en-CA" },
167
+ { label: "English (US)", value: "en-US" },
168
+ { label: "French", value: "fr" },
169
+ { label: "Spanish", value: "es" },
170
+ { label: "German", value: "de" },
171
+ { label: "Japanese", value: "ja" },
177
172
  ];
178
173
 
179
- export const CURRENCIES: {label: string; value: string}[] = [
180
- {label: 'Canadian dollar (CAD)', value: 'CAD'},
181
- {label: 'US dollar (USD)', value: 'USD'},
182
- {label: 'Euro (EUR)', value: 'EUR'},
183
- {label: 'British pound (GBP)', value: 'GBP'},
184
- {label: 'Japanese yen (JPY)', value: 'JPY'},
174
+ export const CURRENCIES: { label: string; value: string }[] = [
175
+ { label: "Canadian dollar (CAD)", value: "CAD" },
176
+ { label: "US dollar (USD)", value: "USD" },
177
+ { label: "Euro (EUR)", value: "EUR" },
178
+ { label: "British pound (GBP)", value: "GBP" },
179
+ { label: "Japanese yen (JPY)", value: "JPY" },
185
180
  ];
186
181
 
187
- export const TIMEZONES: {label: string; value: string}[] = [
188
- {label: '(GMT-05:00) Eastern Time (US & Canada)', value: 'ET'},
189
- {label: '(GMT-06:00) Central Time (US & Canada)', value: 'CT'},
190
- {label: '(GMT-07:00) Mountain Time (US & Canada)', value: 'MT'},
191
- {label: '(GMT-08:00) Pacific Time (US & Canada)', value: 'PT'},
192
- {label: '(GMT+00:00) UTC', value: 'UTC'},
193
- {label: '(GMT+01:00) London', value: 'GMT+1'},
182
+ export const TIMEZONES: { label: string; value: string }[] = [
183
+ { label: "(GMT-05:00) Eastern Time (US & Canada)", value: "ET" },
184
+ { label: "(GMT-06:00) Central Time (US & Canada)", value: "CT" },
185
+ { label: "(GMT-07:00) Mountain Time (US & Canada)", value: "MT" },
186
+ { label: "(GMT-08:00) Pacific Time (US & Canada)", value: "PT" },
187
+ { label: "(GMT+00:00) UTC", value: "UTC" },
188
+ { label: "(GMT+01:00) London", value: "GMT+1" },
194
189
  ];
195
-