@deckspec/theme-noir-display 0.1.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.
@@ -0,0 +1,115 @@
1
+ import { z } from "zod";
2
+
3
+ const columnSchema = z.object({
4
+ name: z.string().min(1).describe("Column header"),
5
+ items: z.array(z.string().min(1)).min(1).max(6).describe("Feature items"),
6
+ highlighted: z.boolean().optional().describe("Highlight this column"),
7
+ });
8
+
9
+ export const schema = z.object({
10
+ heading: z.string().min(1).max(60).describe("Section heading"),
11
+ columns: z.array(columnSchema).min(2).max(3).describe("Comparison columns"),
12
+ });
13
+
14
+ type Props = z.infer<typeof schema>;
15
+
16
+ export default function ComparisonColumns({ heading, columns }: Props) {
17
+ return (
18
+ <div className="slide-stack" style={{ justifyContent: "center", gap: 44 }}>
19
+ <h2
20
+ style={{
21
+ fontSize: 48,
22
+ fontWeight: 600,
23
+ lineHeight: 1.08,
24
+ letterSpacing: "-0.003em",
25
+ textAlign: "center",
26
+ }}
27
+ >
28
+ {heading}
29
+ </h2>
30
+
31
+ <div
32
+ style={{
33
+ display: "grid",
34
+ gridTemplateColumns: `repeat(${columns.length}, 1fr)`,
35
+ gap: 20,
36
+ }}
37
+ >
38
+ {columns.map((col, ci) => (
39
+ <div
40
+ key={ci}
41
+ style={{
42
+ backgroundColor: "#ffffff",
43
+ borderRadius: 18,
44
+ border: col.highlighted
45
+ ? "1.5px solid var(--color-primary)"
46
+ : "none",
47
+ padding: "36px 32px",
48
+ display: "flex",
49
+ flexDirection: "column",
50
+ gap: 24,
51
+ boxShadow: col.highlighted
52
+ ? "0 2px 12px rgba(0,113,227,0.08)"
53
+ : "4px 4px 12px rgba(0,0,0,0.06)",
54
+ }}
55
+ >
56
+ <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
57
+ <span
58
+ style={{
59
+ fontSize: 24,
60
+ fontWeight: 600,
61
+ fontFamily: "var(--font-heading)",
62
+ letterSpacing: "0.009em",
63
+ color: "var(--color-foreground)",
64
+ }}
65
+ >
66
+ {col.name}
67
+ </span>
68
+ {col.highlighted && (
69
+ <span
70
+ style={{
71
+ fontSize: 12,
72
+ fontWeight: 600,
73
+ padding: "3px 10px",
74
+ borderRadius: 980,
75
+ backgroundColor: "var(--color-primary)",
76
+ color: "#fff",
77
+ }}
78
+ >
79
+ Recommended
80
+ </span>
81
+ )}
82
+ </div>
83
+
84
+ <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
85
+ {col.items.map((item, ii) => (
86
+ <div key={ii} style={{ display: "flex", alignItems: "center", gap: 10 }}>
87
+ <svg width={16} height={16} viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0 }}>
88
+ <path
89
+ d="M3 8.5L6.5 12L13 4"
90
+ stroke={col.highlighted ? "var(--color-primary)" : "var(--color-muted-foreground)"}
91
+ strokeWidth="2"
92
+ strokeLinecap="round"
93
+ strokeLinejoin="round"
94
+ />
95
+ </svg>
96
+ <span
97
+ style={{
98
+ fontSize: 17,
99
+ fontWeight: 400,
100
+ letterSpacing: "-0.022em",
101
+ color: "var(--color-foreground)",
102
+ lineHeight: 1.47,
103
+ }}
104
+ >
105
+ {item}
106
+ </span>
107
+ </div>
108
+ ))}
109
+ </div>
110
+ </div>
111
+ ))}
112
+ </div>
113
+ </div>
114
+ );
115
+ }
@@ -0,0 +1,94 @@
1
+ import { z } from "zod";
2
+
3
+ const metricSchema = z.object({
4
+ label: z.string().min(1).describe("Metric label"),
5
+ value: z.string().min(1).describe("Display value"),
6
+ });
7
+
8
+ export const schema = z.object({
9
+ headline: z.string().min(1).max(60).describe("Section heading"),
10
+ description: z.string().max(200).optional().describe("Optional body text"),
11
+ metrics: z.array(metricSchema).min(2).max(4).describe("Key metrics"),
12
+ });
13
+
14
+ type Props = z.infer<typeof schema>;
15
+
16
+ export default function FeatureMetrics({ headline, description, metrics }: Props) {
17
+ return (
18
+ <div
19
+ className="slide"
20
+ style={{
21
+ display: "flex",
22
+ flexDirection: "column",
23
+ alignItems: "center",
24
+ justifyContent: "center",
25
+ gap: 48,
26
+ background: "#ffffff",
27
+ padding: "40px 80px 60px",
28
+ }}
29
+ >
30
+ <div style={{ textAlign: "center", marginBottom: 16 }}>
31
+ <h2
32
+ style={{
33
+ fontSize: 48,
34
+ fontWeight: 600,
35
+ lineHeight: 1.08,
36
+ letterSpacing: "-0.003em",
37
+ }}
38
+ >
39
+ {headline}
40
+ </h2>
41
+ {description && (
42
+ <p
43
+ style={{
44
+ fontSize: 21,
45
+ fontWeight: 400,
46
+ lineHeight: 1.38,
47
+ color: "var(--color-muted-foreground)",
48
+ marginTop: 12,
49
+ }}
50
+ >
51
+ {description}
52
+ </p>
53
+ )}
54
+ </div>
55
+
56
+ <div style={{ display: "flex", justifyContent: "center", gap: 64 }}>
57
+ {metrics.map((m, i) => (
58
+ <div
59
+ key={i}
60
+ style={{
61
+ display: "flex",
62
+ flexDirection: "column",
63
+ alignItems: "center",
64
+ gap: 8,
65
+ }}
66
+ >
67
+ <span
68
+ style={{
69
+ fontSize: 56,
70
+ fontWeight: 600,
71
+ fontFamily: "var(--font-heading)",
72
+ lineHeight: 1,
73
+ letterSpacing: "-0.015em",
74
+ color: "var(--color-foreground)",
75
+ }}
76
+ >
77
+ {m.value}
78
+ </span>
79
+ <span
80
+ style={{
81
+ fontSize: 17,
82
+ fontWeight: 400,
83
+ letterSpacing: "-0.022em",
84
+ color: "var(--color-muted-foreground)",
85
+ }}
86
+ >
87
+ {m.label}
88
+ </span>
89
+ </div>
90
+ ))}
91
+ </div>
92
+ </div>
93
+ );
94
+ }
@@ -0,0 +1,151 @@
1
+ import { z } from "zod";
2
+
3
+ const stepSchema = z.object({
4
+ title: z.string().min(1).describe("Step title"),
5
+ description: z.string().optional().describe("Step description"),
6
+ });
7
+
8
+ export const schema = z.object({
9
+ label: z.string().min(1).max(30).optional().describe("Accent eyebrow"),
10
+ heading: z.string().min(1).max(60).describe("Diagram heading"),
11
+ steps: z.array(stepSchema).min(3).max(5).describe("Flow steps"),
12
+ });
13
+
14
+ type Props = z.infer<typeof schema>;
15
+
16
+ function Arrow() {
17
+ return (
18
+ <svg width={32} height={32} viewBox="0 0 32 32" fill="none" style={{ flexShrink: 0 }}>
19
+ <path
20
+ d="M8 16H24M24 16L18 10M24 16L18 22"
21
+ stroke="#0071e3"
22
+ strokeWidth="2"
23
+ strokeLinecap="round"
24
+ strokeLinejoin="round"
25
+ />
26
+ </svg>
27
+ );
28
+ }
29
+
30
+ export default function FlowDiagram({ label, heading, steps }: Props) {
31
+ return (
32
+ <div
33
+ className="slide"
34
+ style={{
35
+ display: "flex",
36
+ flexDirection: "column",
37
+ alignItems: "center",
38
+ justifyContent: "center",
39
+ gap: 48,
40
+ background: "#ffffff",
41
+ padding: "48px 60px",
42
+ }}
43
+ >
44
+ {/* Header */}
45
+ <div style={{ textAlign: "center" }}>
46
+ {label && (
47
+ <span
48
+ style={{
49
+ fontSize: 17,
50
+ fontWeight: 600,
51
+ letterSpacing: "-0.022em",
52
+ color: "var(--color-primary)",
53
+ display: "block",
54
+ marginBottom: 8,
55
+ }}
56
+ >
57
+ {label}
58
+ </span>
59
+ )}
60
+ <h2
61
+ style={{
62
+ fontSize: 44,
63
+ fontWeight: 600,
64
+ lineHeight: 1.08,
65
+ letterSpacing: "-0.003em",
66
+ }}
67
+ >
68
+ {heading}
69
+ </h2>
70
+ </div>
71
+
72
+ {/* Flow */}
73
+ <div
74
+ style={{
75
+ display: "flex",
76
+ alignItems: "center",
77
+ gap: 8,
78
+ width: "100%",
79
+ justifyContent: "center",
80
+ }}
81
+ >
82
+ {steps.map((step, i) => (
83
+ <div key={i} style={{ display: "flex", alignItems: "center", gap: 8 }}>
84
+ {/* Step card */}
85
+ <div
86
+ style={{
87
+ display: "flex",
88
+ flexDirection: "column",
89
+ alignItems: "center",
90
+ textAlign: "center",
91
+ gap: 12,
92
+ padding: "28px 20px",
93
+ backgroundColor: "#f5f5f7",
94
+ borderRadius: 16,
95
+ minWidth: 160,
96
+ maxWidth: 200,
97
+ }}
98
+ >
99
+ {/* Step number */}
100
+ <div
101
+ style={{
102
+ width: 36,
103
+ height: 36,
104
+ borderRadius: "50%",
105
+ backgroundColor: i === 0 ? "#0071e3" : "#1d1d1f",
106
+ color: "#fff",
107
+ display: "flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ fontSize: 15,
111
+ fontWeight: 600,
112
+ fontFamily: "var(--font-heading)",
113
+ }}
114
+ >
115
+ {i + 1}
116
+ </div>
117
+ <span
118
+ style={{
119
+ fontSize: 17,
120
+ fontWeight: 600,
121
+ fontFamily: "var(--font-heading)",
122
+ letterSpacing: "-0.022em",
123
+ color: "#1d1d1f",
124
+ lineHeight: 1.3,
125
+ }}
126
+ >
127
+ {step.title}
128
+ </span>
129
+ {step.description && (
130
+ <span
131
+ style={{
132
+ fontSize: 13,
133
+ fontWeight: 400,
134
+ letterSpacing: "-0.016em",
135
+ color: "#6e6e73",
136
+ lineHeight: 1.38,
137
+ }}
138
+ >
139
+ {step.description}
140
+ </span>
141
+ )}
142
+ </div>
143
+
144
+ {/* Arrow between steps */}
145
+ {i < steps.length - 1 && <Arrow />}
146
+ </div>
147
+ ))}
148
+ </div>
149
+ </div>
150
+ );
151
+ }
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+
3
+ export const schema = z.object({
4
+ eyebrow: z.string().min(1).max(30).describe("Small accent label above headline"),
5
+ headline: z.string().min(1).max(60).describe("Massive display headline (supports \\n)"),
6
+ body: z.string().min(1).max(200).describe("Supporting body text"),
7
+ });
8
+
9
+ type Props = z.infer<typeof schema>;
10
+
11
+ export default function HeroStatement({ eyebrow, headline, body }: Props) {
12
+ const lines = headline.split("\\n");
13
+
14
+ return (
15
+ <div
16
+ className="slide"
17
+ style={{
18
+ display: "flex",
19
+ alignItems: "center",
20
+ justifyContent: "center",
21
+ background: "#ffffff",
22
+ }}
23
+ >
24
+ <div
25
+ className="stack-center"
26
+ style={{ gap: 20, maxWidth: 900, padding: "0 80px", marginBottom: 32 }}
27
+ >
28
+ <span
29
+ style={{
30
+ fontSize: 17,
31
+ fontWeight: 600,
32
+ letterSpacing: "-0.022em",
33
+ color: "var(--color-primary)",
34
+ }}
35
+ >
36
+ {eyebrow}
37
+ </span>
38
+
39
+ <h1
40
+ style={{
41
+ fontSize: 80,
42
+ fontWeight: 600,
43
+ lineHeight: 1.05,
44
+ letterSpacing: "-0.015em",
45
+ textAlign: "center",
46
+ }}
47
+ >
48
+ {lines.map((line, i) => (
49
+ <span key={i}>
50
+ {i > 0 && <br />}
51
+ {line}
52
+ </span>
53
+ ))}
54
+ </h1>
55
+
56
+ <p
57
+ style={{
58
+ fontSize: 21,
59
+ fontWeight: 400,
60
+ lineHeight: 1.38,
61
+ letterSpacing: "0.011em",
62
+ color: "var(--color-muted-foreground)",
63
+ maxWidth: 700,
64
+ textAlign: "center",
65
+ }}
66
+ >
67
+ {body}
68
+ </p>
69
+ </div>
70
+ </div>
71
+ );
72
+ }
@@ -0,0 +1,126 @@
1
+ import { z } from "zod";
2
+ import { Icon } from "../_lib/icon.js";
3
+
4
+ const itemSchema = z.object({
5
+ icon: z.string().min(1).describe("Icon name (lucide)"),
6
+ title: z.string().min(1).describe("Feature title"),
7
+ description: z.string().optional().describe("Short description"),
8
+ });
9
+
10
+ export const schema = z.object({
11
+ label: z.string().min(1).max(30).optional().describe("Accent eyebrow"),
12
+ heading: z.string().min(1).max(60).describe("Section heading"),
13
+ items: z.array(itemSchema).min(3).max(6).describe("Icon feature items"),
14
+ });
15
+
16
+ type Props = z.infer<typeof schema>;
17
+
18
+ export default function IconGrid({ label, heading, items }: Props) {
19
+ const cols = items.length <= 3 ? items.length : items.length <= 4 ? 2 : 3;
20
+
21
+ return (
22
+ <div
23
+ className="slide"
24
+ style={{
25
+ display: "flex",
26
+ flexDirection: "column",
27
+ alignItems: "center",
28
+ justifyContent: "center",
29
+ gap: 40,
30
+ background: "#ffffff",
31
+ padding: "48px 80px",
32
+ }}
33
+ >
34
+ <div style={{ textAlign: "center" }}>
35
+ {label && (
36
+ <span
37
+ style={{
38
+ fontSize: 17,
39
+ fontWeight: 600,
40
+ letterSpacing: "-0.022em",
41
+ color: "var(--color-primary)",
42
+ display: "block",
43
+ marginBottom: 8,
44
+ }}
45
+ >
46
+ {label}
47
+ </span>
48
+ )}
49
+ <h2
50
+ style={{
51
+ fontSize: 44,
52
+ fontWeight: 600,
53
+ lineHeight: 1.08,
54
+ letterSpacing: "-0.003em",
55
+ }}
56
+ >
57
+ {heading}
58
+ </h2>
59
+ </div>
60
+
61
+ <div
62
+ style={{
63
+ display: "grid",
64
+ gridTemplateColumns: `repeat(${cols}, 1fr)`,
65
+ gap: 24,
66
+ width: "100%",
67
+ maxWidth: 900,
68
+ }}
69
+ >
70
+ {items.map((item, i) => (
71
+ <div
72
+ key={i}
73
+ style={{
74
+ display: "flex",
75
+ flexDirection: "column",
76
+ alignItems: "center",
77
+ textAlign: "center",
78
+ gap: 12,
79
+ padding: "24px 16px",
80
+ }}
81
+ >
82
+ <div
83
+ style={{
84
+ width: 48,
85
+ height: 48,
86
+ borderRadius: 12,
87
+ backgroundColor: "#f5f5f7",
88
+ display: "flex",
89
+ alignItems: "center",
90
+ justifyContent: "center",
91
+ color: "var(--color-primary)",
92
+ }}
93
+ >
94
+ <Icon name={item.icon} size={24} />
95
+ </div>
96
+ <span
97
+ style={{
98
+ fontSize: 17,
99
+ fontWeight: 600,
100
+ fontFamily: "var(--font-heading)",
101
+ letterSpacing: "-0.022em",
102
+ color: "var(--color-foreground)",
103
+ lineHeight: 1.3,
104
+ }}
105
+ >
106
+ {item.title}
107
+ </span>
108
+ {item.description && (
109
+ <span
110
+ style={{
111
+ fontSize: 14,
112
+ fontWeight: 400,
113
+ letterSpacing: "-0.016em",
114
+ color: "var(--color-muted-foreground)",
115
+ lineHeight: 1.43,
116
+ }}
117
+ >
118
+ {item.description}
119
+ </span>
120
+ )}
121
+ </div>
122
+ ))}
123
+ </div>
124
+ </div>
125
+ );
126
+ }
@@ -0,0 +1,17 @@
1
+ export { default as TitleCenter, schema as titleCenterSchema } from "./title-center/index.js";
2
+ export { default as HeroStatement, schema as heroStatementSchema } from "./hero-statement/index.js";
3
+ export { default as FeatureMetrics, schema as featureMetricsSchema } from "./feature-metrics/index.js";
4
+ export { default as BulletList, schema as bulletListSchema } from "./bullet-list/index.js";
5
+ export { default as ThreePillars, schema as threePillarsSchema } from "./three-pillars/index.js";
6
+ export { default as BigNumber, schema as bigNumberSchema } from "./big-number/index.js";
7
+ export { default as ComparisonColumns, schema as comparisonColumnsSchema } from "./comparison-columns/index.js";
8
+ export { default as PricingTiers, schema as pricingTiersSchema } from "./pricing-tiers/index.js";
9
+ export { default as ThankYou, schema as thankYouSchema } from "./thank-you/index.js";
10
+ export { default as IconGrid, schema as iconGridSchema } from "./icon-grid/index.js";
11
+ export { default as ChartBar, schema as chartBarSchema } from "./chart-bar/index.js";
12
+ export { default as FlowDiagram, schema as flowDiagramSchema } from "./flow-diagram/index.js";
13
+ export { default as PhotoSplit, schema as photoSplitSchema } from "./photo-split/index.js";
14
+ export { default as ChallengeCards, schema as challengeCardsSchema } from "./challenge-cards/index.js";
15
+ export { default as PhasedRoadmap, schema as phasedRoadmapSchema } from "./phased-roadmap/index.js";
16
+ export { default as ShowcaseGrid, schema as showcaseGridSchema } from "./showcase-grid/index.js";
17
+ export { default as BodyMessage, schema as bodyMessageSchema } from "./body-message/index.js";