@frontlit/page-builder 0.1.0-alpha.1 → 0.1.0-alpha.3

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 (116) hide show
  1. package/README.md +38 -2
  2. package/dist/blocks/index.d.ts +35 -21
  3. package/dist/blocks/index.js +4 -3
  4. package/dist/builder/index.d.ts +8 -11
  5. package/dist/builder/index.js +7 -5
  6. package/dist/{button-C3VrMJkr.d.ts → button-OLKN3wPf.d.ts} +3 -3
  7. package/dist/{chunk-7W6Q4WA7.js → chunk-36QHCIPM.js} +252 -282
  8. package/dist/chunk-36QHCIPM.js.map +1 -0
  9. package/dist/{chunk-GTY75HW2.js → chunk-ATNM5JHI.js} +2 -2
  10. package/dist/chunk-ATNM5JHI.js.map +1 -0
  11. package/dist/chunk-BBI7UHOA.js +56 -0
  12. package/dist/chunk-BBI7UHOA.js.map +1 -0
  13. package/dist/{chunk-MO76KZY2.js → chunk-GIKTOAQS.js} +661 -423
  14. package/dist/chunk-GIKTOAQS.js.map +1 -0
  15. package/dist/chunk-HWOVSHIW.js +4 -0
  16. package/dist/{chunk-RUYOL7JZ.js.map → chunk-HWOVSHIW.js.map} +1 -1
  17. package/dist/{chunk-SSQWYMQR.js → chunk-IU4KATI2.js} +74 -129
  18. package/dist/chunk-IU4KATI2.js.map +1 -0
  19. package/dist/chunk-J7Z4UW45.js +3418 -0
  20. package/dist/chunk-J7Z4UW45.js.map +1 -0
  21. package/dist/{chunk-7KIX4WAO.js → chunk-K4WCLHMS.js} +1435 -1382
  22. package/dist/chunk-K4WCLHMS.js.map +1 -0
  23. package/dist/chunk-XU7ALPGQ.js +22 -0
  24. package/dist/chunk-XU7ALPGQ.js.map +1 -0
  25. package/dist/components/index.d.ts +33 -8
  26. package/dist/components/index.js +43 -2
  27. package/dist/components/index.js.map +1 -1
  28. package/dist/data-slots.d.ts +3 -3
  29. package/dist/data-slots.js +1 -1
  30. package/dist/fonts/archivo/archivo-latin-variable.woff2 +0 -0
  31. package/dist/fonts/hanken-grotesk/hanken-grotesk-latin-variable.woff2 +0 -0
  32. package/dist/fonts/jetbrains-mono/jetbrains-mono-latin-variable.woff2 +0 -0
  33. package/dist/fonts/spline-sans-mono/spline-sans-mono-latin-variable.woff2 +0 -0
  34. package/dist/heading-DQCxQt38.d.ts +20 -0
  35. package/dist/image-Bk8kPXwP.d.ts +52 -0
  36. package/dist/index.d.ts +18 -11
  37. package/dist/index.js +9 -7
  38. package/dist/media-CnLImjVC.d.ts +21 -0
  39. package/dist/models/index.d.ts +6 -6
  40. package/dist/models/index.js +2 -1
  41. package/dist/{page-DfVl_aHX.d.ts → page-B5Gmm-Ys.d.ts} +2 -3
  42. package/dist/primitives/index.d.ts +287 -61
  43. package/dist/primitives/index.js +2 -1
  44. package/dist/renderer/index.d.ts +12 -8
  45. package/dist/renderer/index.js +6 -4
  46. package/dist/{section-background-BgOCp5l3.d.ts → section-background-6V_LCi5e.d.ts} +1 -1
  47. package/dist/server/index.d.ts +103 -0
  48. package/dist/server/index.js +2649 -0
  49. package/dist/server/index.js.map +1 -0
  50. package/dist/server/islands/code-snippet.d.ts +17 -0
  51. package/dist/server/islands/code-snippet.js +72 -0
  52. package/dist/server/islands/code-snippet.js.map +1 -0
  53. package/dist/server/islands/email-form.d.ts +50 -0
  54. package/dist/server/islands/email-form.js +406 -0
  55. package/dist/server/islands/email-form.js.map +1 -0
  56. package/dist/server/islands/header-mobile-menu.d.ts +22 -0
  57. package/dist/server/islands/header-mobile-menu.js +422 -0
  58. package/dist/server/islands/header-mobile-menu.js.map +1 -0
  59. package/dist/server/islands/inline-embed.d.ts +28 -0
  60. package/dist/server/islands/inline-embed.js +84 -0
  61. package/dist/server/islands/inline-embed.js.map +1 -0
  62. package/dist/server/islands/marquee-track.d.ts +18 -0
  63. package/dist/server/islands/marquee-track.js +67 -0
  64. package/dist/server/islands/marquee-track.js.map +1 -0
  65. package/dist/server/islands/nav-link.d.ts +37 -0
  66. package/dist/server/islands/nav-link.js +67 -0
  67. package/dist/server/islands/nav-link.js.map +1 -0
  68. package/dist/server/islands/support-form.d.ts +17 -0
  69. package/dist/server/islands/support-form.js +469 -0
  70. package/dist/server/islands/support-form.js.map +1 -0
  71. package/dist/server/islands/theme-mode-switcher.d.ts +38 -0
  72. package/dist/server/islands/theme-mode-switcher.js +169 -0
  73. package/dist/server/islands/theme-mode-switcher.js.map +1 -0
  74. package/dist/server/islands/video-with-preview.d.ts +13 -0
  75. package/dist/server/islands/video-with-preview.js +269 -0
  76. package/dist/server/islands/video-with-preview.js.map +1 -0
  77. package/dist/server/primitives.d.ts +200 -0
  78. package/dist/server/primitives.js +888 -0
  79. package/dist/server/primitives.js.map +1 -0
  80. package/dist/server/schema.d.ts +11308 -0
  81. package/dist/server/schema.js +6179 -0
  82. package/dist/server/schema.js.map +1 -0
  83. package/dist/server/theme-CF3fIKvw.d.ts +9 -0
  84. package/dist/{theme-style-39nxXQy0.d.ts → server/theme-style-5_AGy-4V.d.ts} +43 -1
  85. package/dist/server/theme-style-BPaMwk88.d.ts +183 -0
  86. package/dist/server/theme.d.ts +28 -0
  87. package/dist/{chunk-RBJBODQP.js → server/theme.js} +903 -1243
  88. package/dist/server/theme.js.map +1 -0
  89. package/dist/server/widget-YH9BrOwY.d.ts +77 -0
  90. package/dist/styles.css +4016 -8317
  91. package/dist/theme-style-BVd5tOsc.d.ts +183 -0
  92. package/dist/theme.css +186 -191
  93. package/dist/{widget--uEOpdq3.d.ts → widget-CpE2HdgU.d.ts} +25 -18
  94. package/package.json +71 -11
  95. package/schema/page.v1.json +3855 -0
  96. package/schema/site.v1.json +3811 -0
  97. package/dist/alignment-dZDzN96G.d.ts +0 -5
  98. package/dist/chunk-7KIX4WAO.js.map +0 -1
  99. package/dist/chunk-7W6Q4WA7.js.map +0 -1
  100. package/dist/chunk-GTY75HW2.js.map +0 -1
  101. package/dist/chunk-MO76KZY2.js.map +0 -1
  102. package/dist/chunk-RBJBODQP.js.map +0 -1
  103. package/dist/chunk-RUYOL7JZ.js +0 -4
  104. package/dist/chunk-SSQWYMQR.js.map +0 -1
  105. package/dist/fonts/montserrat/montserrat-latin-100-normal.woff2 +0 -0
  106. package/dist/fonts/montserrat/montserrat-latin-200-normal.woff2 +0 -0
  107. package/dist/fonts/montserrat/montserrat-latin-300-normal.woff2 +0 -0
  108. package/dist/fonts/montserrat/montserrat-latin-400-normal.woff2 +0 -0
  109. package/dist/fonts/montserrat/montserrat-latin-500-normal.woff2 +0 -0
  110. package/dist/fonts/montserrat/montserrat-latin-600-normal.woff2 +0 -0
  111. package/dist/fonts/montserrat/montserrat-latin-700-normal.woff2 +0 -0
  112. package/dist/fonts/montserrat/montserrat-latin-800-normal.woff2 +0 -0
  113. package/dist/fonts/montserrat/montserrat-latin-900-normal.woff2 +0 -0
  114. package/dist/fonts/source-sans-3/source-sans-3-latin-400-normal.woff2 +0 -0
  115. package/dist/image-D7GlnOio.d.ts +0 -30
  116. package/dist/media-Njv378j7.d.ts +0 -13
@@ -1,11 +1,13 @@
1
1
  "use client";
2
- import { NavLink, VideoWithPreview, Image, TextRenderer, SandboxedEmbed, ThemeModeSwitcher } from './chunk-7W6Q4WA7.js';
3
- import { Button2, Drawer, Section, cn, Preheader, Header1, Subheader1, PageCard, PageCardContent, Header2, Header4, Text2, Badge, PageCardHeader, Text1, Input, Label, Link, Caption, Header3 } from './chunk-RBJBODQP.js';
4
- import React7, { useState, useId, useRef, useEffect } from 'react';
2
+ import { NavLink, VideoWithPreview, Image, TextRenderer, InlineEmbed } from './chunk-36QHCIPM.js';
3
+ import { Button2, Section, cn, Preheader, Display, Subheader1, CodeSnippet, Caption, PageCard, PageCardContent, Header2, Header1, Header4, Text2, Badge, PageCardHeader, Text1, Link, Header3, Drawer, Input, Label } from './chunk-J7Z4UW45.js';
4
+ import { getMediaUrl, getMediaAlt } from './chunk-XU7ALPGQ.js';
5
5
  import clsx3 from 'clsx';
6
- import * as Icons from 'lucide-react';
7
- import { MenuIcon, Code2, LockKeyhole, ChevronDown, Plus } from 'lucide-react';
8
6
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
7
+ import React2, { useId, useState, useRef, useEffect } from 'react';
8
+ import * as Icons from 'lucide-react';
9
+ import { Code2, LockKeyhole, ChevronDown, MenuIcon, Plus, ImageIcon } from 'lucide-react';
10
+ import { ImageUploadDialog } from '@frontlit/media-uploader';
9
11
  import { Editor, emptyDoc } from '@frontlit/text-editor';
10
12
 
11
13
  // src/blocks/header/metadata.ts
@@ -15,60 +17,88 @@ var headerMetadata = {
15
17
  description: "The site navigation bar, pinned to the top of every page.",
16
18
  compatibleWith: ["site", "landing", "blog", "post", "custom"]
17
19
  };
18
-
19
- // src/utils/is-video.ts
20
- function isVideo(youtubeLink, media) {
21
- return Boolean(
22
- youtubeLink || media && RegExp("video/").test(media?.mimeType || "")
23
- );
24
- }
25
-
26
- // src/utils/generate-unique-id.ts
27
- function generateUniqueId() {
28
- return Math.random().toString(36).slice(2) + Date.now().toString(36);
29
- }
30
20
  function HeaderLink({
31
21
  link,
32
22
  theme,
33
- onClick
23
+ onClick,
24
+ fullWidth = false
34
25
  }) {
35
26
  if (link.isButton) {
36
- return /* @__PURE__ */ jsx(NavLink, { href: link.href, onClick, children: /* @__PURE__ */ jsx(Button2, { size: "sm", theme, children: link.label }) });
27
+ return /* @__PURE__ */ jsx(NavLink, { href: link.href, onClick, children: /* @__PURE__ */ jsx(
28
+ Button2,
29
+ {
30
+ size: fullWidth ? void 0 : "sm",
31
+ theme,
32
+ className: fullWidth ? "w-full" : void 0,
33
+ children: link.label
34
+ }
35
+ ) });
37
36
  }
38
37
  return /* @__PURE__ */ jsx(NavLink, { href: link.href, onClick, className: "no-underline", children: /* @__PURE__ */ jsx(Link, { theme, className: "no-underline", children: link.label }) });
39
38
  }
39
+ function HeaderMobileMenu({
40
+ links,
41
+ ctaLabel,
42
+ ctaHref,
43
+ theme
44
+ }) {
45
+ const [open, setOpen] = useState(false);
46
+ return /* @__PURE__ */ jsx(
47
+ Drawer,
48
+ {
49
+ open,
50
+ setOpen,
51
+ side: "right",
52
+ theme,
53
+ trigger: /* @__PURE__ */ jsxs(Button2, { variant: "outline", size: "sm", theme, children: [
54
+ /* @__PURE__ */ jsx(MenuIcon, { className: "h-4 w-4" }),
55
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle menu" })
56
+ ] }),
57
+ children: /* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col gap-4", children: [
58
+ links.map((link) => /* @__PURE__ */ jsx(
59
+ HeaderLink,
60
+ {
61
+ link,
62
+ theme,
63
+ onClick: () => setOpen(false),
64
+ fullWidth: true
65
+ },
66
+ link.id
67
+ )),
68
+ ctaLabel && ctaHref && /* @__PURE__ */ jsx(NavLink, { href: ctaHref, onClick: () => setOpen(false), children: /* @__PURE__ */ jsx(Button2, { theme, className: "w-full", children: ctaLabel }) })
69
+ ] })
70
+ }
71
+ );
72
+ }
40
73
  function HeaderWidget({
41
74
  settings: {
42
- logoText,
43
- logoImage,
75
+ logoCorners,
44
76
  links = [],
45
77
  ctaLabel,
46
78
  ctaHref,
47
79
  linkAlignment = "left",
48
80
  layout = "fixed",
49
81
  backdropBlur = false,
50
- showThemeSwitcher = true,
51
82
  cssId,
52
83
  maxWidth,
53
84
  verticalPadding,
54
85
  background
55
86
  },
56
87
  state: { theme },
57
- pageData,
58
- nextTheme,
59
- toggleTheme
88
+ pageData
60
89
  }) {
61
90
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
62
91
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
63
92
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
64
- const [mobileNavOpen, setMobileNavOpen] = useState(false);
65
93
  const isFloating = layout === "floating";
66
94
  const isCentered = layout === "centered";
67
95
  const isFixed = !isFloating;
68
96
  const primaryLinks = links.filter((link) => !link.isButton);
69
97
  const buttonLinks = links.filter((link) => link.isButton);
70
- const resolvedLogoImage = pageData.siteLogoUrl || logoImage;
71
- const resolvedLogoAlt = pageData.siteLogoAlt || logoText || "";
98
+ const resolvedLogoImage = pageData.siteLogoUrl;
99
+ const resolvedLogoText = pageData.siteTitle;
100
+ const resolvedLogoAlt = pageData.siteLogoAlt || resolvedLogoText || "";
101
+ const effectiveLogoCorners = logoCorners ?? 2;
72
102
  const logo = /* @__PURE__ */ jsx(NavLink, { href: "/", className: "no-underline", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
73
103
  resolvedLogoImage && /* @__PURE__ */ jsx(
74
104
  Image,
@@ -77,70 +107,23 @@ function HeaderWidget({
77
107
  alt: resolvedLogoAlt,
78
108
  width: "w-8",
79
109
  height: "h-8",
80
- borderRadius: 2
110
+ sizes: "32px",
111
+ className: "aspect-square shrink-0",
112
+ borderRadius: effectiveLogoCorners
81
113
  }
82
114
  ),
83
- logoText && /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: logoText })
115
+ resolvedLogoText && /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, as: "span", children: resolvedLogoText })
84
116
  ] }) });
85
- const colorModeControl = showThemeSwitcher && toggleTheme ? /* @__PURE__ */ jsx(
86
- ThemeModeSwitcher,
87
- {
88
- resolved: nextTheme ?? "light",
89
- onToggle: toggleTheme,
90
- theme: overriddenTheme,
91
- size: "sm",
92
- variant: "outline"
93
- }
94
- ) : null;
95
117
  const ctaAndMenu = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
96
- colorModeControl,
97
118
  buttonLinks.map((link) => /* @__PURE__ */ jsx("div", { className: "hidden lg:!block", children: /* @__PURE__ */ jsx(HeaderLink, { link, theme: overriddenTheme }) }, link.id)),
98
119
  ctaLabel && ctaHref && /* @__PURE__ */ jsx("div", { className: "hidden lg:!block", children: /* @__PURE__ */ jsx(NavLink, { href: ctaHref, children: /* @__PURE__ */ jsx(Button2, { theme: overriddenTheme, size: "sm", children: ctaLabel }) }) }),
99
120
  /* @__PURE__ */ jsx("div", { className: "lg:hidden", children: /* @__PURE__ */ jsx(
100
- Drawer,
121
+ HeaderMobileMenu,
101
122
  {
102
- open: mobileNavOpen,
103
- setOpen: setMobileNavOpen,
104
- side: "right",
105
- theme: overriddenTheme,
106
- trigger: /* @__PURE__ */ jsxs(
107
- Button2,
108
- {
109
- variant: "outline",
110
- size: "sm",
111
- theme: overriddenTheme,
112
- children: [
113
- /* @__PURE__ */ jsx(MenuIcon, { className: "h-4 w-4" }),
114
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle menu" })
115
- ]
116
- }
117
- ),
118
- children: /* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col gap-4", children: [
119
- links.map((link) => /* @__PURE__ */ jsx(
120
- HeaderLink,
121
- {
122
- link,
123
- theme: overriddenTheme,
124
- onClick: () => setMobileNavOpen(false)
125
- },
126
- link.id
127
- )),
128
- ctaLabel && ctaHref && /* @__PURE__ */ jsx(
129
- NavLink,
130
- {
131
- href: ctaHref,
132
- onClick: () => setMobileNavOpen(false),
133
- children: /* @__PURE__ */ jsx(
134
- Button2,
135
- {
136
- theme: overriddenTheme,
137
- className: "w-full",
138
- children: ctaLabel
139
- }
140
- )
141
- }
142
- )
143
- ] })
123
+ links,
124
+ ctaLabel,
125
+ ctaHref,
126
+ theme: overriddenTheme
144
127
  }
145
128
  ) })
146
129
  ] });
@@ -150,24 +133,10 @@ function HeaderWidget({
150
133
  const leftLinks = primaryLinks.slice(0, half);
151
134
  const rightLinks = primaryLinks.slice(half);
152
135
  mainContent = /* @__PURE__ */ jsxs("div", { className: "grid w-full grid-cols-[1fr_auto_1fr] items-center gap-4", children: [
153
- /* @__PURE__ */ jsx("div", { className: "hidden items-center justify-end gap-6 lg:!flex", children: leftLinks.map((link) => /* @__PURE__ */ jsx(
154
- HeaderLink,
155
- {
156
- link,
157
- theme: overriddenTheme
158
- },
159
- link.id
160
- )) }),
136
+ /* @__PURE__ */ jsx("div", { className: "hidden items-center justify-end gap-6 lg:!flex", children: leftLinks.map((link) => /* @__PURE__ */ jsx(HeaderLink, { link, theme: overriddenTheme }, link.id)) }),
161
137
  /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: logo }),
162
138
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3", children: [
163
- /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-6 lg:!flex", children: rightLinks.map((link) => /* @__PURE__ */ jsx(
164
- HeaderLink,
165
- {
166
- link,
167
- theme: overriddenTheme
168
- },
169
- link.id
170
- )) }),
139
+ /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-6 lg:!flex", children: rightLinks.map((link) => /* @__PURE__ */ jsx(HeaderLink, { link, theme: overriddenTheme }, link.id)) }),
171
140
  ctaAndMenu
172
141
  ] })
173
142
  ] });
@@ -181,14 +150,7 @@ function HeaderWidget({
181
150
  "hidden items-center gap-6 lg:!flex lg:!grow",
182
151
  linkAlignment === "right" ? "justify-end" : linkAlignment === "center" ? "justify-center" : "justify-start"
183
152
  ),
184
- children: primaryLinks.map((link) => /* @__PURE__ */ jsx(
185
- HeaderLink,
186
- {
187
- link,
188
- theme: overriddenTheme
189
- },
190
- link.id
191
- ))
153
+ children: primaryLinks.map((link) => /* @__PURE__ */ jsx(HeaderLink, { link, theme: overriddenTheme }, link.id))
192
154
  }
193
155
  ),
194
156
  ctaAndMenu
@@ -201,7 +163,6 @@ function HeaderWidget({
201
163
  component: "header",
202
164
  id: cssId,
203
165
  background,
204
- nextTheme,
205
166
  className: clsx3(
206
167
  "sticky top-0 z-20",
207
168
  isFixed && "border-b",
@@ -226,6 +187,18 @@ function HeaderWidget({
226
187
  }
227
188
  );
228
189
  }
190
+
191
+ // src/utils/is-video.ts
192
+ function isVideo(youtubeLink, media) {
193
+ return Boolean(
194
+ youtubeLink || media && RegExp("video/").test(media?.mimeType || "")
195
+ );
196
+ }
197
+
198
+ // src/utils/generate-unique-id.ts
199
+ function generateUniqueId() {
200
+ return Math.random().toString(36).slice(2) + Date.now().toString(36);
201
+ }
229
202
  function FieldGroup({
230
203
  title,
231
204
  children
@@ -243,7 +216,8 @@ function TextField({
243
216
  value,
244
217
  onChange,
245
218
  placeholder,
246
- multiline
219
+ multiline,
220
+ hint
247
221
  }) {
248
222
  const generatedId = useId();
249
223
  const inputId = `field-${generatedId.replace(/:/g, "")}`;
@@ -267,9 +241,90 @@ function TextField({
267
241
  placeholder,
268
242
  onChange: (e) => onChange(e.target.value)
269
243
  }
244
+ ),
245
+ hint && /* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: hint })
246
+ ] });
247
+ }
248
+ var RICH_TEXT_MIN_HEIGHT = {
249
+ 80: "min-h-[80px]",
250
+ 100: "min-h-[100px]",
251
+ 160: "min-h-[160px]"
252
+ };
253
+ function RichTextField({
254
+ label,
255
+ value,
256
+ onChange,
257
+ showToolbar = true,
258
+ minHeight = 80
259
+ }) {
260
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
261
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: label }),
262
+ /* @__PURE__ */ jsx(
263
+ Editor,
264
+ {
265
+ profile: "documentation",
266
+ initialContent: value ?? emptyDoc,
267
+ onChange,
268
+ debounceMs: 150,
269
+ showToolbar,
270
+ editorClassName: RICH_TEXT_MIN_HEIGHT[minHeight]
271
+ }
270
272
  )
271
273
  ] });
272
274
  }
275
+ var TITLE_SIZE_FIELDS = [
276
+ { key: "mobile", label: "Phone" },
277
+ { key: "tablet", label: "Tablet" },
278
+ { key: "desktop", label: "Desktop" }
279
+ ];
280
+ function TitleLevelField({
281
+ settings,
282
+ defaultLevel = "h2",
283
+ onChange
284
+ }) {
285
+ return /* @__PURE__ */ jsx(
286
+ SelectField,
287
+ {
288
+ label: "Title heading level",
289
+ value: settings.titleLevel ?? defaultLevel,
290
+ onChange: (titleLevel) => onChange({ titleLevel }),
291
+ options: [
292
+ { label: "H1 \u2014 the page's main heading", value: "h1" },
293
+ { label: "H2 \u2014 section heading", value: "h2" },
294
+ { label: "H3 \u2014 sub-section heading", value: "h3" }
295
+ ]
296
+ }
297
+ );
298
+ }
299
+ function TitleSizeField({
300
+ settings,
301
+ onChange
302
+ }) {
303
+ const size = settings.titleSize ?? {};
304
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 text-sm", children: [
305
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-foreground", children: "Title size (px)" }),
306
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2", children: TITLE_SIZE_FIELDS.map(({ key, label }) => /* @__PURE__ */ jsxs("label", { className: "flex min-w-0 flex-col gap-1", children: [
307
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] text-muted-foreground", children: label }),
308
+ /* @__PURE__ */ jsx(
309
+ "input",
310
+ {
311
+ type: "number",
312
+ min: 8,
313
+ max: 200,
314
+ placeholder: "Theme",
315
+ className: "h-9 min-w-0 rounded-lg border border-input bg-muted/20 px-2 py-2 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground/70 focus:border-ring focus:bg-background focus:ring-2 focus:ring-ring/20",
316
+ value: size[key] ?? "",
317
+ onChange: (e) => onChange({
318
+ titleSize: {
319
+ ...size,
320
+ [key]: e.target.value ? Number(e.target.value) : void 0
321
+ }
322
+ })
323
+ }
324
+ )
325
+ ] }, key)) })
326
+ ] });
327
+ }
273
328
  function NumberField({
274
329
  label,
275
330
  value,
@@ -295,6 +350,66 @@ function NumberField({
295
350
  )
296
351
  ] });
297
352
  }
353
+ function SliderField({
354
+ label,
355
+ value = 0,
356
+ onChange,
357
+ min = 0,
358
+ max = 8,
359
+ step = 1,
360
+ unit = "",
361
+ displayValue,
362
+ minLabel,
363
+ maxLabel
364
+ }) {
365
+ const generatedId = useId();
366
+ const inputId = `field-${generatedId.replace(/:/g, "")}`;
367
+ const numValue = Number.isFinite(value) ? value : min;
368
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
369
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
370
+ /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "text-xs font-semibold text-foreground", children: label }),
371
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
372
+ displayValue && /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-muted-foreground", children: displayValue }),
373
+ /* @__PURE__ */ jsx(
374
+ "input",
375
+ {
376
+ id: inputId,
377
+ type: "number",
378
+ inputMode: "numeric",
379
+ min,
380
+ max,
381
+ step,
382
+ value: numValue,
383
+ onChange: (e) => {
384
+ const parsed = Number(e.currentTarget.value);
385
+ if (Number.isNaN(parsed)) return;
386
+ onChange(Math.min(Math.max(parsed, min), max));
387
+ },
388
+ className: "h-7 w-12 rounded-md border border-input bg-muted/20 px-1.5 py-1 text-center text-xs font-semibold text-foreground outline-none transition-colors focus:border-ring focus:bg-background focus:ring-2 focus:ring-ring/20"
389
+ }
390
+ ),
391
+ unit && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium text-muted-foreground", children: unit })
392
+ ] })
393
+ ] }),
394
+ /* @__PURE__ */ jsx(
395
+ "input",
396
+ {
397
+ type: "range",
398
+ min,
399
+ max,
400
+ step,
401
+ value: numValue,
402
+ onChange: (e) => onChange(Number(e.currentTarget.value)),
403
+ "aria-label": label,
404
+ className: "h-1.5 w-full cursor-pointer accent-primary"
405
+ }
406
+ ),
407
+ (minLabel || maxLabel) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-[10px] font-medium text-muted-foreground", children: [
408
+ /* @__PURE__ */ jsx("span", { children: minLabel }),
409
+ /* @__PURE__ */ jsx("span", { children: maxLabel })
410
+ ] })
411
+ ] });
412
+ }
298
413
  function SelectField({
299
414
  label,
300
415
  value,
@@ -322,28 +437,33 @@ function ToggleField({
322
437
  value,
323
438
  onChange
324
439
  }) {
325
- return /* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-border/80 bg-muted/20 px-3 py-2.5 text-sm transition-colors hover:bg-muted/50", children: [
326
- /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-foreground", children: label }),
327
- /* @__PURE__ */ jsx(
328
- "input",
329
- {
330
- type: "checkbox",
331
- className: "peer sr-only",
332
- checked: Boolean(value),
333
- onChange: (e) => onChange(e.target.checked)
334
- }
335
- ),
336
- /* @__PURE__ */ jsx(
337
- "span",
338
- {
339
- "aria-hidden": "true",
340
- className: cn(
341
- "relative h-5 w-9 shrink-0 rounded-full bg-muted-foreground/25 transition-colors after:absolute after:left-0.5 after:top-0.5 after:h-4 after:w-4 after:rounded-full after:bg-background after:shadow-sm after:transition-transform peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2",
342
- value && "bg-primary after:translate-x-4"
343
- )
344
- }
345
- )
346
- ] });
440
+ return (
441
+ // `relative` anchors the sr-only checkbox here. Without it the checkbox
442
+ // is positioned against an ancestor outside the settings panel, and
443
+ // focusing it scrolls the whole builder out of place.
444
+ /* @__PURE__ */ jsxs("label", { className: "relative flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-border/80 bg-muted/20 px-3 py-2.5 text-sm transition-colors hover:bg-muted/50", children: [
445
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-foreground", children: label }),
446
+ /* @__PURE__ */ jsx(
447
+ "input",
448
+ {
449
+ type: "checkbox",
450
+ className: "peer sr-only",
451
+ checked: Boolean(value),
452
+ onChange: (e) => onChange(e.target.checked)
453
+ }
454
+ ),
455
+ /* @__PURE__ */ jsx(
456
+ "span",
457
+ {
458
+ "aria-hidden": "true",
459
+ className: cn(
460
+ "relative h-5 w-9 shrink-0 rounded-full bg-muted-foreground/25 transition-colors after:absolute after:left-0.5 after:top-0.5 after:h-4 after:w-4 after:rounded-full after:bg-background after:shadow-sm after:transition-transform peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-2",
461
+ value && "bg-primary after:translate-x-4"
462
+ )
463
+ }
464
+ )
465
+ ] })
466
+ );
347
467
  }
348
468
  function ListField({
349
469
  label,
@@ -401,31 +521,119 @@ function ListField({
401
521
  )
402
522
  ] });
403
523
  }
524
+ function ImageField({
525
+ label,
526
+ value,
527
+ onChange,
528
+ placeholder = "https://..."
529
+ }) {
530
+ const imageUrl = getMediaUrl(value);
531
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 text-sm", children: [
532
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-foreground", children: label }),
533
+ imageUrl ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
534
+ /* @__PURE__ */ jsx("div", { className: "relative aspect-video w-full overflow-hidden rounded-lg border border-border bg-muted/40", children: /* @__PURE__ */ jsx("img", { src: imageUrl, alt: "Preview", className: "h-full w-full object-cover" }) }),
535
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
536
+ /* @__PURE__ */ jsx(
537
+ ImageUploadDialog,
538
+ {
539
+ title: `Choose ${label.toLowerCase()}`,
540
+ description: "Upload an image or select one from your library.",
541
+ onSelect: (selected) => {
542
+ const selMedia = selected.media;
543
+ const mediaLitId = selMedia?.mediaLitId ?? selMedia?.mediaId ?? void 0;
544
+ onChange({
545
+ ...mediaLitId ? { mediaId: mediaLitId, mediaLitId } : {},
546
+ url: selected.src,
547
+ file: selected.src,
548
+ thumbnailUrl: selMedia?.thumbnailUrl ?? selected.src,
549
+ thumbnail: selMedia?.thumbnailUrl ?? selected.src,
550
+ alt: selected.alt
551
+ });
552
+ },
553
+ children: /* @__PURE__ */ jsxs(
554
+ "button",
555
+ {
556
+ type: "button",
557
+ className: "inline-flex h-8 items-center justify-center rounded-lg border border-input bg-background px-3 text-xs font-medium text-foreground hover:bg-muted",
558
+ children: [
559
+ /* @__PURE__ */ jsx(ImageIcon, { className: "mr-1.5 h-3.5 w-3.5" }),
560
+ "Change image"
561
+ ]
562
+ }
563
+ )
564
+ }
565
+ ),
566
+ /* @__PURE__ */ jsx(
567
+ "button",
568
+ {
569
+ type: "button",
570
+ className: "inline-flex h-8 items-center justify-center rounded-lg border border-destructive/30 bg-background px-3 text-xs font-medium text-destructive hover:bg-destructive/10",
571
+ onClick: () => onChange(void 0),
572
+ children: "Remove"
573
+ }
574
+ )
575
+ ] })
576
+ ] }) : /* @__PURE__ */ jsx(
577
+ ImageUploadDialog,
578
+ {
579
+ title: `Choose ${label.toLowerCase()}`,
580
+ description: "Upload an image or select one from your library.",
581
+ onSelect: (selected) => {
582
+ const selMedia = selected.media;
583
+ const mediaLitId = selMedia?.mediaLitId ?? selMedia?.mediaId ?? void 0;
584
+ onChange({
585
+ ...mediaLitId ? { mediaId: mediaLitId, mediaLitId } : {},
586
+ url: selected.src,
587
+ file: selected.src,
588
+ thumbnailUrl: selMedia?.thumbnailUrl ?? selected.src,
589
+ thumbnail: selMedia?.thumbnailUrl ?? selected.src,
590
+ alt: selected.alt
591
+ });
592
+ },
593
+ children: /* @__PURE__ */ jsxs(
594
+ "button",
595
+ {
596
+ type: "button",
597
+ className: "flex w-full items-center justify-center gap-2 rounded-lg border border-dashed border-border bg-muted/20 py-3 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:bg-muted/40 hover:text-foreground",
598
+ children: [
599
+ /* @__PURE__ */ jsx(ImageIcon, { className: "h-4 w-4" }),
600
+ "Upload or choose image"
601
+ ]
602
+ }
603
+ )
604
+ }
605
+ ),
606
+ /* @__PURE__ */ jsx(
607
+ "input",
608
+ {
609
+ type: "text",
610
+ className: "h-9 rounded-lg border border-input bg-muted/20 px-3 py-2 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground/70 focus:border-ring focus:bg-background focus:ring-2 focus:ring-ring/20",
611
+ value: imageUrl ?? "",
612
+ placeholder,
613
+ onChange: (e) => onChange(
614
+ e.target.value ? { url: e.target.value, file: e.target.value } : void 0
615
+ )
616
+ }
617
+ )
618
+ ] });
619
+ }
620
+ var CORNER_LABELS = {
621
+ 0: "Square",
622
+ 1: "Small",
623
+ 2: "Default",
624
+ 3: "Medium",
625
+ 4: "Large",
626
+ 5: "XL",
627
+ 6: "2XL",
628
+ 7: "3XL",
629
+ 8: "Full"
630
+ };
404
631
  function HeaderEditor({
405
632
  settings,
406
633
  onChange
407
634
  }) {
408
635
  const update = (partial) => onChange({ ...settings, ...partial });
409
636
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
410
- /* @__PURE__ */ jsxs(FieldGroup, { title: "Logo", children: [
411
- /* @__PURE__ */ jsx(
412
- TextField,
413
- {
414
- label: "Logo text",
415
- value: settings.logoText,
416
- onChange: (logoText) => update({ logoText })
417
- }
418
- ),
419
- /* @__PURE__ */ jsx(
420
- TextField,
421
- {
422
- label: "Logo image URL",
423
- value: settings.logoImage,
424
- placeholder: "https://...",
425
- onChange: (logoImage) => update({ logoImage })
426
- }
427
- )
428
- ] }),
429
637
  /* @__PURE__ */ jsx(FieldGroup, { title: "Navigation links", children: /* @__PURE__ */ jsx(
430
638
  ListField,
431
639
  {
@@ -514,22 +722,35 @@ function HeaderEditor({
514
722
  value: settings.backdropBlur,
515
723
  onChange: (backdropBlur) => update({ backdropBlur })
516
724
  }
517
- ),
518
- /* @__PURE__ */ jsx(
519
- ToggleField,
520
- {
521
- label: "Color mode switcher",
522
- value: settings.showThemeSwitcher !== false,
523
- onChange: (showThemeSwitcher) => update({ showThemeSwitcher })
524
- }
525
725
  )
526
726
  ] })
527
727
  ] });
528
728
  }
729
+ function HeaderDesignEditor({
730
+ settings,
731
+ onChange
732
+ }) {
733
+ const update = (partial) => onChange({ ...settings, ...partial });
734
+ const logoCorners = settings.logoCorners ?? 2;
735
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: /* @__PURE__ */ jsx(FieldGroup, { title: "Logo styling", children: /* @__PURE__ */ jsx(
736
+ SliderField,
737
+ {
738
+ label: "Logo corners",
739
+ value: logoCorners,
740
+ min: 0,
741
+ max: 8,
742
+ step: 1,
743
+ minLabel: "0 (Square)",
744
+ maxLabel: "Full",
745
+ displayValue: CORNER_LABELS[logoCorners] ?? `${logoCorners}`,
746
+ onChange: (val) => update({ logoCorners: val })
747
+ }
748
+ ) }) });
749
+ }
529
750
 
530
751
  // src/blocks/header/defaults.ts
531
752
  var headerDefaults = {
532
- logoText: "FrontLit",
753
+ logoCorners: 2,
533
754
  links: [
534
755
  { id: generateUniqueId(), label: "Features", href: "/#features" },
535
756
  { id: generateUniqueId(), label: "Pricing", href: "/#pricing" },
@@ -541,7 +762,6 @@ var headerDefaults = {
541
762
  linkAlignment: "left",
542
763
  layout: "fixed",
543
764
  backdropBlur: false,
544
- showThemeSwitcher: true,
545
765
  // Slider value 1. Keeps a new header compact instead of inheriting the
546
766
  // theme's content-section padding (`py-12` / slider 5 on most themes).
547
767
  verticalPadding: "py-4"
@@ -552,6 +772,7 @@ var Header = {
552
772
  metadata: headerMetadata,
553
773
  widget: HeaderWidget,
554
774
  editor: HeaderEditor,
775
+ designEditor: HeaderDesignEditor,
555
776
  getDefaultSettings: () => headerDefaults,
556
777
  layouts: [
557
778
  { id: "fixed", name: "Fixed" },
@@ -567,6 +788,38 @@ var heroMetadata = {
567
788
  description: "A large introductory section with a title, copy and CTAs.",
568
789
  compatibleWith: ["site", "landing", "blog", "post", "custom"]
569
790
  };
791
+ function titleProps({
792
+ titleLevel,
793
+ titleSize
794
+ }, defaultLevel = "h2", baseSizeClassName) {
795
+ const { mobile, tablet, desktop } = titleSize ?? {};
796
+ const size = (value) => value ? `${value}px` : "var(--pb-theme-size, 1em)";
797
+ return {
798
+ as: titleLevel ?? defaultLevel,
799
+ sizeClassName: cn(
800
+ baseSizeClassName,
801
+ mobile && "text-[length:var(--pb-title-mobile)]",
802
+ (mobile || tablet) && "md:text-[length:var(--pb-title-tablet)]",
803
+ (tablet || desktop) && "lg:text-[length:var(--pb-title-desktop)]"
804
+ ),
805
+ style: {
806
+ "--pb-title-mobile": mobile ? size(mobile) : void 0,
807
+ "--pb-title-tablet": mobile || tablet ? size(tablet) : void 0,
808
+ "--pb-title-desktop": tablet || desktop ? size(desktop) : void 0
809
+ }
810
+ };
811
+ }
812
+ var HIGHLIGHT_CLASSES = {
813
+ color: "text-primary",
814
+ marker: "bg-primary px-[0.15em] text-primary-foreground [box-decoration-break:clone]"
815
+ };
816
+ function renderTitle(title, theme) {
817
+ if (!title?.includes("*")) return title;
818
+ const className = HIGHLIGHT_CLASSES[theme?.highlight ?? "color"];
819
+ return title.split(/(\*[^*]+\*)/).map(
820
+ (part, index) => /^\*[^*]+\*$/.test(part) ? React2.createElement("span", { key: index, className }, part.slice(1, -1)) : part
821
+ );
822
+ }
570
823
  var roundedMap = {
571
824
  0: "rounded-none",
572
825
  1: "rounded-sm",
@@ -592,19 +845,23 @@ function HeroWidget({
592
845
  contentAlignment = "left",
593
846
  secondaryButtonAction,
594
847
  secondaryButtonCaption,
848
+ smallPrint,
849
+ command,
850
+ titleLevel,
851
+ titleSize,
595
852
  cssId,
596
853
  maxWidth,
597
854
  verticalPadding,
598
855
  background,
599
856
  layout = "normal"
600
857
  },
601
- state: { theme },
602
- nextTheme
858
+ state: { theme }
603
859
  }) {
604
860
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
605
861
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
606
862
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
607
- const hasHeroGraphic = youtubeLink || media && media.mediaId;
863
+ const mediaUrl = getMediaUrl(media);
864
+ const hasHeroGraphic = Boolean(youtubeLink || mediaUrl);
608
865
  const direction = alignment === "right" ? "md:!flex-row-reverse" : "md:!flex-row";
609
866
  const isCentered = layout === "centered" || layout === "media-below";
610
867
  const graphic = hasHeroGraphic && /* @__PURE__ */ jsx(
@@ -614,16 +871,17 @@ function HeroWidget({
614
871
  children: isVideo(youtubeLink, media) ? /* @__PURE__ */ jsx(
615
872
  VideoWithPreview,
616
873
  {
617
- videoUrl: youtubeLink || media?.file || "",
618
- title: media?.caption || "",
619
- thumbnailUrl: media?.thumbnail || ""
874
+ videoUrl: youtubeLink || mediaUrl || "",
875
+ title: getMediaAlt(media) || media?.caption || "",
876
+ thumbnailUrl: media?.thumbnail || media?.thumbnailUrl || ""
620
877
  }
621
878
  ) : /* @__PURE__ */ jsx(
622
879
  Image,
623
880
  {
624
- src: media?.file || "",
625
- alt: media?.caption || "",
626
- borderRadius: mediaRadius
881
+ src: mediaUrl || "",
882
+ alt: getMediaAlt(media),
883
+ borderRadius: mediaRadius,
884
+ priority: true
627
885
  }
628
886
  )
629
887
  }
@@ -636,15 +894,8 @@ function HeroWidget({
636
894
  isCentered || contentAlignment === "center" ? "items-center text-center" : "items-start justify-center h-full"
637
895
  ),
638
896
  children: [
639
- preTitle && /* @__PURE__ */ jsx(
640
- Preheader,
641
- {
642
- theme: overriddenTheme,
643
- className: "text-muted-foreground",
644
- children: preTitle
645
- }
646
- ),
647
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
897
+ preTitle && /* @__PURE__ */ jsx(Preheader, { theme: overriddenTheme, className: "text-muted-foreground", children: preTitle }),
898
+ /* @__PURE__ */ jsx(Display, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }, "h1"), children: renderTitle(title, overriddenTheme) }),
648
899
  description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) }),
649
900
  /* @__PURE__ */ jsxs(
650
901
  "div",
@@ -654,14 +905,7 @@ function HeroWidget({
654
905
  (isCentered || contentAlignment === "center") && "md:!justify-center"
655
906
  ),
656
907
  children: [
657
- buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, children: /* @__PURE__ */ jsx(
658
- Button2,
659
- {
660
- theme: overriddenTheme,
661
- className: "w-full md:min-w-[150px]",
662
- children: buttonCaption
663
- }
664
- ) }),
908
+ buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, children: /* @__PURE__ */ jsx(Button2, { theme: overriddenTheme, className: "w-full md:min-w-[150px]", children: buttonCaption }) }),
665
909
  secondaryButtonAction && secondaryButtonCaption && /* @__PURE__ */ jsx(NavLink, { href: secondaryButtonAction, children: /* @__PURE__ */ jsx(
666
910
  Button2,
667
911
  {
@@ -673,7 +917,17 @@ function HeroWidget({
673
917
  ) })
674
918
  ]
675
919
  }
676
- )
920
+ ),
921
+ command && /* @__PURE__ */ jsx(
922
+ CodeSnippet,
923
+ {
924
+ code: command,
925
+ prompt: "$",
926
+ theme: overriddenTheme,
927
+ className: "max-w-xl"
928
+ }
929
+ ),
930
+ smallPrint && /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: smallPrint })
677
931
  ]
678
932
  }
679
933
  );
@@ -691,21 +945,9 @@ function HeroWidget({
691
945
  /* @__PURE__ */ jsx("div", { className: `w-full ${hasHeroGraphic ? "md:w-1/2" : ""}`, children: textContent })
692
946
  ] });
693
947
  }
694
- return /* @__PURE__ */ jsx(
695
- Section,
696
- {
697
- theme: overriddenTheme,
698
- id: cssId,
699
- background,
700
- nextTheme,
701
- children: layout === "card" ? /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, children: /* @__PURE__ */ jsx(PageCardContent, { theme: overriddenTheme, children: mainContent }) }) : mainContent
702
- }
703
- );
948
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: layout === "card" ? /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, children: /* @__PURE__ */ jsx(PageCardContent, { theme: overriddenTheme, children: mainContent }) }) : mainContent });
704
949
  }
705
- function HeroEditor({
706
- settings,
707
- onChange
708
- }) {
950
+ function HeroEditor({ settings, onChange }) {
709
951
  const update = (partial) => onChange({ ...settings, ...partial });
710
952
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
711
953
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Content", children: [
@@ -722,33 +964,30 @@ function HeroEditor({
722
964
  TextField,
723
965
  {
724
966
  label: "Title",
967
+ hint: "Wrap words in *asterisks* to highlight them.",
725
968
  value: settings.title,
726
969
  onChange: (title) => update({ title })
727
970
  }
728
971
  ),
729
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
730
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
731
- /* @__PURE__ */ jsx(
732
- Editor,
733
- {
734
- initialContent: settings.description ?? emptyDoc,
735
- onChange: (description) => update({ description }),
736
- showToolbar: false,
737
- editorClassName: "min-h-[100px]"
738
- }
739
- )
740
- ] })
972
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, defaultLevel: "h1", onChange: update }),
973
+ /* @__PURE__ */ jsx(
974
+ RichTextField,
975
+ {
976
+ label: "Description",
977
+ value: settings.description,
978
+ onChange: (description) => update({ description }),
979
+ showToolbar: false,
980
+ minHeight: 100
981
+ }
982
+ )
741
983
  ] }),
742
984
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Media", children: [
743
985
  /* @__PURE__ */ jsx(
744
- TextField,
986
+ ImageField,
745
987
  {
746
- label: "Image URL",
747
- value: settings.media?.file,
748
- placeholder: "https://...",
749
- onChange: (file) => update({
750
- media: file ? { mediaId: file, file } : void 0
751
- })
988
+ label: "Image",
989
+ value: settings.media,
990
+ onChange: (media) => update({ media })
752
991
  }
753
992
  ),
754
993
  /* @__PURE__ */ jsx(
@@ -793,6 +1032,24 @@ function HeroEditor({
793
1032
  value: settings.secondaryButtonAction,
794
1033
  onChange: (secondaryButtonAction) => update({ secondaryButtonAction })
795
1034
  }
1035
+ ),
1036
+ /* @__PURE__ */ jsx(
1037
+ TextField,
1038
+ {
1039
+ label: "Install command",
1040
+ value: settings.command,
1041
+ placeholder: "e.g. curl -fsSL https://example.com/install.sh | sh",
1042
+ onChange: (command) => update({ command })
1043
+ }
1044
+ ),
1045
+ /* @__PURE__ */ jsx(
1046
+ TextField,
1047
+ {
1048
+ label: "Small print",
1049
+ value: settings.smallPrint,
1050
+ placeholder: "e.g. No credit card required",
1051
+ onChange: (smallPrint) => update({ smallPrint })
1052
+ }
796
1053
  )
797
1054
  ] }),
798
1055
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Layout", children: [
@@ -842,6 +1099,7 @@ var Hero = {
842
1099
  metadata: heroMetadata,
843
1100
  widget: HeroWidget,
844
1101
  editor: HeroEditor,
1102
+ titleSize: true,
845
1103
  getDefaultSettings: () => heroDefaults,
846
1104
  layouts: [
847
1105
  { id: "normal", name: "Standard" },
@@ -872,6 +1130,8 @@ var roundedMap2 = {
872
1130
  function ContentWidget({
873
1131
  settings: {
874
1132
  title,
1133
+ titleLevel,
1134
+ titleSize,
875
1135
  body,
876
1136
  media,
877
1137
  alignment = "left",
@@ -883,122 +1143,82 @@ function ContentWidget({
883
1143
  verticalPadding,
884
1144
  background
885
1145
  },
886
- state: { theme },
887
- nextTheme
1146
+ state: { theme }
888
1147
  }) {
889
1148
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
890
1149
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
891
1150
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
892
- const hasMedia = Boolean(media && media.file);
1151
+ const mediaUrl = getMediaUrl(media);
1152
+ const mediaAlt = getMediaAlt(media);
1153
+ const hasMedia = Boolean(mediaUrl);
893
1154
  const sideBySide = layout !== "stacked" && layout !== "overlay";
894
1155
  const direction = alignment === "right" ? "md:!flex-row-reverse" : "md:!flex-row";
895
1156
  if (layout === "overlay") {
896
1157
  const textPosition = alignment === "right" ? "items-end text-right" : "items-start text-left";
897
- return /* @__PURE__ */ jsx(
898
- Section,
899
- {
900
- theme: overriddenTheme,
901
- id: cssId,
902
- background,
903
- nextTheme,
904
- children: /* @__PURE__ */ jsxs("div", { className: "relative min-h-[420px] w-full overflow-hidden rounded-xl", children: [
905
- hasMedia && /* @__PURE__ */ jsx(
906
- Image,
907
- {
908
- src: media?.file || "",
909
- alt: media?.caption || "",
910
- width: "w-full",
911
- height: "h-full",
912
- className: "absolute inset-0",
913
- borderRadius: 0
914
- }
915
- ),
916
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent" }),
917
- /* @__PURE__ */ jsx(
918
- "div",
919
- {
920
- className: clsx3(
921
- "relative flex h-full flex-col justify-end gap-4 p-6 md:p-10",
922
- textPosition
923
- ),
924
- children: /* @__PURE__ */ jsxs("div", { className: "max-w-lg text-white", children: [
925
- title && /* @__PURE__ */ jsx(Header2, { theme: overriddenTheme, children: title }),
926
- body && /* @__PURE__ */ jsx(
927
- TextRenderer,
928
- {
929
- json: body,
930
- theme: overriddenTheme
931
- }
932
- )
933
- ] })
934
- }
935
- )
936
- ] })
937
- }
938
- );
939
- }
940
- return /* @__PURE__ */ jsx(
941
- Section,
942
- {
943
- theme: overriddenTheme,
944
- id: cssId,
945
- background,
946
- nextTheme,
947
- children: /* @__PURE__ */ jsxs(
1158
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "relative min-h-[420px] w-full overflow-hidden rounded-xl", children: [
1159
+ hasMedia && /* @__PURE__ */ jsx(
1160
+ Image,
1161
+ {
1162
+ src: mediaUrl || "",
1163
+ alt: mediaAlt,
1164
+ width: "w-full",
1165
+ height: "h-full",
1166
+ className: "absolute inset-0",
1167
+ borderRadius: 0
1168
+ }
1169
+ ),
1170
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-t from-black/70 via-black/20 to-transparent" }),
1171
+ /* @__PURE__ */ jsx(
948
1172
  "div",
949
1173
  {
950
- className: clsx3("flex flex-col gap-8", sideBySide && direction),
951
- children: [
952
- hasMedia && /* @__PURE__ */ jsx(
953
- "div",
1174
+ className: clsx3(
1175
+ "relative flex h-full flex-col justify-end gap-4 p-6 md:p-10",
1176
+ textPosition
1177
+ ),
1178
+ children: /* @__PURE__ */ jsxs("div", { className: "max-w-lg text-white", children: [
1179
+ title && /* @__PURE__ */ jsx(
1180
+ Header2,
954
1181
  {
955
- className: clsx3(
956
- "flex w-full items-center",
957
- sideBySide && "md:w-1/2"
958
- ),
959
- children: /* @__PURE__ */ jsx(
960
- "div",
961
- {
962
- className: `w-full overflow-hidden ${roundedMap2[mediaRadius] ?? "rounded-md"}`,
963
- children: /* @__PURE__ */ jsx(
964
- Image,
965
- {
966
- src: media?.file || "",
967
- alt: media?.caption || "",
968
- borderRadius: mediaRadius
969
- }
970
- )
971
- }
972
- )
1182
+ theme: overriddenTheme,
1183
+ ...titleProps({ titleLevel, titleSize }),
1184
+ children: renderTitle(title, overriddenTheme)
973
1185
  }
974
1186
  ),
975
- /* @__PURE__ */ jsx(
976
- "div",
977
- {
978
- className: clsx3(
979
- "w-full",
980
- hasMedia && sideBySide && "md:w-1/2"
981
- ),
982
- children: /* @__PURE__ */ jsxs(
983
- "div",
984
- {
985
- className: clsx3(
986
- "flex h-full flex-col justify-center gap-4",
987
- headerAlignment === "center" ? "items-center text-center" : "items-start"
988
- ),
989
- children: [
990
- title && /* @__PURE__ */ jsx(Header2, { theme: overriddenTheme, children: title }),
991
- body && /* @__PURE__ */ jsx(TextRenderer, { json: body, theme: overriddenTheme })
992
- ]
993
- }
994
- )
995
- }
996
- )
997
- ]
1187
+ body && /* @__PURE__ */ jsx(TextRenderer, { json: body, theme: overriddenTheme })
1188
+ ] })
998
1189
  }
999
1190
  )
1000
- }
1001
- );
1191
+ ] }) });
1192
+ }
1193
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: clsx3("flex flex-col gap-8", sideBySide && direction), children: [
1194
+ hasMedia && /* @__PURE__ */ jsx("div", { className: clsx3("flex w-full items-center", sideBySide && "md:w-1/2"), children: /* @__PURE__ */ jsx(
1195
+ "div",
1196
+ {
1197
+ className: `w-full overflow-hidden ${roundedMap2[mediaRadius] ?? "rounded-md"}`,
1198
+ children: /* @__PURE__ */ jsx(Image, { src: mediaUrl || "", alt: mediaAlt, borderRadius: mediaRadius })
1199
+ }
1200
+ ) }),
1201
+ /* @__PURE__ */ jsx("div", { className: clsx3("w-full", hasMedia && sideBySide && "md:w-1/2"), children: /* @__PURE__ */ jsxs(
1202
+ "div",
1203
+ {
1204
+ className: clsx3(
1205
+ "flex h-full flex-col justify-center gap-4",
1206
+ headerAlignment === "center" ? "items-center text-center" : "items-start"
1207
+ ),
1208
+ children: [
1209
+ title && /* @__PURE__ */ jsx(
1210
+ Header2,
1211
+ {
1212
+ theme: overriddenTheme,
1213
+ ...titleProps({ titleLevel, titleSize }),
1214
+ children: renderTitle(title, overriddenTheme)
1215
+ }
1216
+ ),
1217
+ body && /* @__PURE__ */ jsx(TextRenderer, { json: body, theme: overriddenTheme })
1218
+ ]
1219
+ }
1220
+ ) })
1221
+ ] }) });
1002
1222
  }
1003
1223
  function ContentEditor({
1004
1224
  settings,
@@ -1011,32 +1231,29 @@ function ContentEditor({
1011
1231
  TextField,
1012
1232
  {
1013
1233
  label: "Title",
1234
+ hint: "Wrap words in *asterisks* to highlight them.",
1014
1235
  value: settings.title,
1015
1236
  onChange: (title) => update({ title })
1016
1237
  }
1017
1238
  ),
1018
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
1019
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Body" }),
1020
- /* @__PURE__ */ jsx(
1021
- Editor,
1022
- {
1023
- initialContent: settings.body ?? emptyDoc,
1024
- onChange: (body) => update({ body }),
1025
- editorClassName: "min-h-[160px]"
1026
- }
1027
- )
1028
- ] })
1239
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
1240
+ /* @__PURE__ */ jsx(
1241
+ RichTextField,
1242
+ {
1243
+ label: "Body",
1244
+ value: settings.body,
1245
+ onChange: (body) => update({ body }),
1246
+ minHeight: 160
1247
+ }
1248
+ )
1029
1249
  ] }),
1030
1250
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Media", children: [
1031
1251
  /* @__PURE__ */ jsx(
1032
- TextField,
1252
+ ImageField,
1033
1253
  {
1034
- label: "Image URL",
1035
- value: settings.media?.file,
1036
- placeholder: "https://...",
1037
- onChange: (file) => update({
1038
- media: file ? { mediaId: file, file } : void 0
1039
- })
1254
+ label: "Image",
1255
+ value: settings.media,
1256
+ onChange: (media) => update({ media })
1040
1257
  }
1041
1258
  ),
1042
1259
  /* @__PURE__ */ jsx(
@@ -1106,6 +1323,7 @@ var Content = {
1106
1323
  metadata: contentMetadata,
1107
1324
  widget: ContentWidget,
1108
1325
  editor: ContentEditor,
1326
+ titleSize: true,
1109
1327
  getDefaultSettings: () => contentDefaults,
1110
1328
  layouts: [
1111
1329
  { id: "side", name: "Media beside" },
@@ -1129,6 +1347,8 @@ function resolveIcon(name) {
1129
1347
  function FeaturedWidget({
1130
1348
  settings: {
1131
1349
  title,
1350
+ titleLevel,
1351
+ titleSize,
1132
1352
  description,
1133
1353
  headerAlignment = "center",
1134
1354
  items,
@@ -1138,102 +1358,80 @@ function FeaturedWidget({
1138
1358
  verticalPadding,
1139
1359
  background
1140
1360
  },
1141
- state: { theme },
1142
- nextTheme
1361
+ state: { theme }
1143
1362
  }) {
1144
1363
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
1145
1364
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
1146
1365
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
1147
- return /* @__PURE__ */ jsx(
1148
- Section,
1149
- {
1150
- theme: overriddenTheme,
1151
- id: cssId,
1152
- background,
1153
- nextTheme,
1154
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
1155
- /* @__PURE__ */ jsxs(
1156
- "div",
1157
- {
1158
- className: clsx3(
1159
- "flex flex-col gap-4",
1160
- headerAlignment === "center" ? "items-center text-center" : "items-start"
1161
- ),
1162
- children: [
1163
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
1164
- description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(
1165
- TextRenderer,
1166
- {
1167
- json: description,
1168
- theme: overriddenTheme
1169
- }
1170
- ) })
1171
- ]
1172
- }
1366
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
1367
+ /* @__PURE__ */ jsxs(
1368
+ "div",
1369
+ {
1370
+ className: clsx3(
1371
+ "flex flex-col gap-4",
1372
+ headerAlignment === "center" ? "items-center text-center" : "items-start"
1173
1373
  ),
1174
- items && items.length > 0 && layout === "numbered" && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8", children: items.map((item, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
1175
- /* @__PURE__ */ jsx("span", { className: "text-3xl font-bold text-primary/30", children: String(index + 1).padStart(2, "0") }),
1176
- /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: item.title }),
1177
- item.description && /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: item.description })
1178
- ] }, index)) }),
1179
- items && items.length > 0 && layout !== "numbered" && /* @__PURE__ */ jsx(
1180
- "div",
1181
- {
1182
- className: clsx3(
1183
- layout === "list" && "flex flex-col gap-4",
1184
- layout === "compact" && "grid grid-cols-2 md:grid-cols-4 gap-4 items-stretch",
1185
- layout !== "list" && layout !== "compact" && "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-stretch"
1186
- ),
1187
- children: items.map((item, index) => {
1188
- const Icon = resolveIcon(item.icon);
1189
- return /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, children: /* @__PURE__ */ jsxs(
1190
- PageCardContent,
1191
- {
1192
- theme: overriddenTheme,
1193
- className: clsx3(
1194
- "h-full flex gap-3",
1195
- layout === "list" ? "flex-row items-start" : "flex-col",
1196
- layout === "compact" && "items-center text-center gap-2"
1197
- ),
1198
- children: [
1199
- /* @__PURE__ */ jsx(
1200
- "div",
1201
- {
1202
- className: clsx3(
1203
- "flex shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary",
1204
- layout === "compact" ? "h-8 w-8" : "h-10 w-10"
1205
- ),
1206
- children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
1207
- }
1374
+ children: [
1375
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
1376
+ description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) })
1377
+ ]
1378
+ }
1379
+ ),
1380
+ items && items.length > 0 && layout === "numbered" && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8", children: items.map((item, index) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
1381
+ /* @__PURE__ */ jsx("span", { className: "text-3xl font-bold text-primary/30", children: String(index + 1).padStart(2, "0") }),
1382
+ /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: item.title }),
1383
+ item.description && /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: item.description })
1384
+ ] }, index)) }),
1385
+ items && items.length > 0 && layout !== "numbered" && /* @__PURE__ */ jsx(
1386
+ "div",
1387
+ {
1388
+ className: clsx3(
1389
+ layout === "list" && "flex flex-col gap-4",
1390
+ layout === "compact" && "grid grid-cols-2 md:grid-cols-4 gap-4 items-stretch",
1391
+ layout !== "list" && layout !== "compact" && "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-stretch"
1392
+ ),
1393
+ children: items.map((item, index) => {
1394
+ const Icon = resolveIcon(item.icon);
1395
+ return /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, children: /* @__PURE__ */ jsxs(
1396
+ PageCardContent,
1397
+ {
1398
+ theme: overriddenTheme,
1399
+ className: clsx3(
1400
+ "h-full flex gap-3",
1401
+ layout === "list" ? "flex-row items-start" : "flex-col",
1402
+ layout === "compact" && "items-center text-center gap-2"
1403
+ ),
1404
+ children: [
1405
+ /* @__PURE__ */ jsx(
1406
+ "div",
1407
+ {
1408
+ className: clsx3(
1409
+ "flex shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary",
1410
+ layout === "compact" ? "h-8 w-8" : "h-10 w-10"
1208
1411
  ),
1209
- /* @__PURE__ */ jsxs(
1210
- "div",
1211
- {
1212
- className: clsx3(
1213
- "flex flex-col gap-2",
1214
- layout === "compact" && "items-center gap-1"
1215
- ),
1216
- children: [
1217
- /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: item.title }),
1218
- item.description && layout !== "compact" && /* @__PURE__ */ jsx(
1219
- Text2,
1220
- {
1221
- theme: overriddenTheme,
1222
- children: item.description
1223
- }
1224
- )
1225
- ]
1226
- }
1227
- )
1228
- ]
1229
- }
1230
- ) }, index);
1231
- })
1232
- }
1233
- )
1234
- ] })
1235
- }
1236
- );
1412
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsxs(
1416
+ "div",
1417
+ {
1418
+ className: clsx3(
1419
+ "flex flex-col gap-2",
1420
+ layout === "compact" && "items-center gap-1"
1421
+ ),
1422
+ children: [
1423
+ /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: item.title }),
1424
+ item.description && layout !== "compact" && /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: item.description })
1425
+ ]
1426
+ }
1427
+ )
1428
+ ]
1429
+ }
1430
+ ) }, index);
1431
+ })
1432
+ }
1433
+ )
1434
+ ] }) });
1237
1435
  }
1238
1436
  var createItem = () => ({
1239
1437
  title: "New feature",
@@ -1251,22 +1449,22 @@ function FeaturedEditor({
1251
1449
  TextField,
1252
1450
  {
1253
1451
  label: "Title",
1452
+ hint: "Wrap words in *asterisks* to highlight them.",
1254
1453
  value: settings.title,
1255
1454
  onChange: (title) => update({ title })
1256
1455
  }
1257
1456
  ),
1258
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
1259
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
1260
- /* @__PURE__ */ jsx(
1261
- Editor,
1262
- {
1263
- initialContent: settings.description ?? emptyDoc,
1264
- onChange: (description) => update({ description }),
1265
- showToolbar: false,
1266
- editorClassName: "min-h-[80px]"
1267
- }
1268
- )
1269
- ] }),
1457
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
1458
+ /* @__PURE__ */ jsx(
1459
+ RichTextField,
1460
+ {
1461
+ label: "Description",
1462
+ value: settings.description,
1463
+ onChange: (description) => update({ description }),
1464
+ showToolbar: false,
1465
+ minHeight: 80
1466
+ }
1467
+ ),
1270
1468
  /* @__PURE__ */ jsx(
1271
1469
  SelectField,
1272
1470
  {
@@ -1363,6 +1561,7 @@ var Featured = {
1363
1561
  metadata: featuredMetadata,
1364
1562
  widget: FeaturedWidget,
1365
1563
  editor: FeaturedEditor,
1564
+ titleSize: true,
1366
1565
  getDefaultSettings: () => featuredDefaults,
1367
1566
  layouts: [
1368
1567
  { id: "grid", name: "Grid" },
@@ -1382,6 +1581,8 @@ var faqMetadata = {
1382
1581
  function FaqWidget({
1383
1582
  settings: {
1384
1583
  title,
1584
+ titleLevel,
1585
+ titleSize,
1385
1586
  headerAlignment = "left",
1386
1587
  items = [],
1387
1588
  layout = "list",
@@ -1390,115 +1591,63 @@ function FaqWidget({
1390
1591
  verticalPadding,
1391
1592
  background
1392
1593
  },
1393
- state: { theme },
1394
- nextTheme
1594
+ state: { theme }
1395
1595
  }) {
1396
1596
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
1397
1597
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
1398
1598
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
1399
- const [expandedIndex, setExpandedIndex] = useState(
1400
- items.length > 0 ? 0 : null
1401
- );
1402
- return /* @__PURE__ */ jsx(
1403
- Section,
1404
- {
1405
- theme: overriddenTheme,
1406
- id: cssId,
1407
- background,
1408
- nextTheme,
1409
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
1410
- title && /* @__PURE__ */ jsx(
1411
- "div",
1412
- {
1413
- className: clsx3(
1414
- "flex flex-col",
1415
- headerAlignment === "center" ? "items-center text-center" : "items-start"
1416
- ),
1417
- children: /* @__PURE__ */ jsx(Header2, { theme: overriddenTheme, children: title })
1418
- }
1599
+ const groupName = useId();
1600
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
1601
+ title && /* @__PURE__ */ jsx(
1602
+ "div",
1603
+ {
1604
+ className: clsx3(
1605
+ "flex flex-col",
1606
+ headerAlignment === "center" ? "items-center text-center" : "items-start"
1419
1607
  ),
1420
- items.length > 0 && (() => {
1421
- const renderItem = (item, index) => {
1422
- const isOpen = expandedIndex === index;
1423
- return /* @__PURE__ */ jsxs(
1424
- "div",
1425
- {
1426
- className: layout === "cards" ? "rounded-lg border border-border bg-card px-4 py-4" : layout === "columns" ? "border-b border-border py-4" : "py-4",
1427
- children: [
1428
- /* @__PURE__ */ jsxs(
1429
- "button",
1430
- {
1431
- type: "button",
1432
- className: "flex w-full items-center justify-between gap-4 text-left",
1433
- onClick: () => setExpandedIndex(
1434
- isOpen ? null : index
1435
- ),
1436
- "aria-expanded": isOpen,
1437
- children: [
1438
- /* @__PURE__ */ jsx(
1439
- Text1,
1440
- {
1441
- theme: overriddenTheme,
1442
- className: "font-medium",
1443
- children: item.question
1444
- }
1445
- ),
1446
- /* @__PURE__ */ jsx(
1447
- ChevronDown,
1448
- {
1449
- className: clsx3(
1450
- "h-4 w-4 shrink-0 transition-transform",
1451
- isOpen && "rotate-180"
1452
- )
1453
- }
1454
- )
1455
- ]
1456
- }
1457
- ),
1458
- isOpen && /* @__PURE__ */ jsx("div", { className: "pt-3", children: /* @__PURE__ */ jsx(
1459
- Text1,
1460
- {
1461
- theme: overriddenTheme,
1462
- className: "text-muted-foreground",
1463
- children: item.answer
1464
- }
1465
- ) })
1466
- ]
1467
- },
1468
- item.id
1469
- );
1470
- };
1471
- if (layout === "columns") {
1472
- const half = Math.ceil(items.length / 2);
1473
- const left = items.slice(0, half);
1474
- const right = items.slice(half);
1475
- return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-x-10 md:grid-cols-2", children: [
1476
- /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: left.map(
1477
- (item, i) => renderItem(item, i)
1478
- ) }),
1479
- /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: right.map(
1480
- (item, i) => renderItem(item, half + i)
1481
- ) })
1482
- ] });
1483
- }
1484
- return /* @__PURE__ */ jsx(
1485
- "div",
1486
- {
1487
- className: layout === "cards" ? "flex flex-col gap-3" : "flex flex-col divide-y divide-border border-b border-t border-border",
1488
- children: items.map(
1489
- (item, index) => renderItem(item, index)
1490
- )
1491
- }
1492
- );
1493
- })()
1494
- ] })
1495
- }
1496
- );
1608
+ children: /* @__PURE__ */ jsx(Header2, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) })
1609
+ }
1610
+ ),
1611
+ items.length > 0 && (() => {
1612
+ const renderItem = (item, index) => /* @__PURE__ */ jsxs(
1613
+ "details",
1614
+ {
1615
+ name: groupName,
1616
+ open: index === 0,
1617
+ className: clsx3(
1618
+ "group",
1619
+ layout === "cards" ? "rounded-lg border border-border bg-card px-4 py-4" : layout === "columns" ? "border-b border-border py-4" : "py-4"
1620
+ ),
1621
+ children: [
1622
+ /* @__PURE__ */ jsxs("summary", { className: "flex w-full cursor-pointer list-none items-center justify-between gap-4 text-left [&::-webkit-details-marker]:hidden", children: [
1623
+ /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, className: "font-medium", children: item.question }),
1624
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 transition-transform group-open:rotate-180" })
1625
+ ] }),
1626
+ /* @__PURE__ */ jsx("div", { className: "pt-3", children: /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, className: "text-muted-foreground", children: item.answer }) })
1627
+ ]
1628
+ },
1629
+ item.id
1630
+ );
1631
+ if (layout === "columns") {
1632
+ const half = Math.ceil(items.length / 2);
1633
+ const left = items.slice(0, half);
1634
+ const right = items.slice(half);
1635
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-x-10 md:grid-cols-2", children: [
1636
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: left.map((item, i) => renderItem(item, i)) }),
1637
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: right.map((item, i) => renderItem(item, half + i)) })
1638
+ ] });
1639
+ }
1640
+ return /* @__PURE__ */ jsx(
1641
+ "div",
1642
+ {
1643
+ className: layout === "cards" ? "flex flex-col gap-3" : "flex flex-col divide-y divide-border border-b border-t border-border",
1644
+ children: items.map((item, index) => renderItem(item, index))
1645
+ }
1646
+ );
1647
+ })()
1648
+ ] }) });
1497
1649
  }
1498
- function FaqEditor({
1499
- settings,
1500
- onChange
1501
- }) {
1650
+ function FaqEditor({ settings, onChange }) {
1502
1651
  const update = (partial) => onChange({ ...settings, ...partial });
1503
1652
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
1504
1653
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Header", children: [
@@ -1506,10 +1655,12 @@ function FaqEditor({
1506
1655
  TextField,
1507
1656
  {
1508
1657
  label: "Title",
1658
+ hint: "Wrap words in *asterisks* to highlight them.",
1509
1659
  value: settings.title,
1510
1660
  onChange: (title) => update({ title })
1511
1661
  }
1512
1662
  ),
1663
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
1513
1664
  /* @__PURE__ */ jsx(
1514
1665
  SelectField,
1515
1666
  {
@@ -1601,6 +1752,7 @@ var Faq = {
1601
1752
  metadata: faqMetadata,
1602
1753
  widget: FaqWidget,
1603
1754
  editor: FaqEditor,
1755
+ titleSize: true,
1604
1756
  getDefaultSettings: () => faqDefaults,
1605
1757
  layouts: [
1606
1758
  { id: "list", name: "List" },
@@ -1619,6 +1771,8 @@ var pricingMetadata = {
1619
1771
  function PricingWidget({
1620
1772
  settings: {
1621
1773
  title,
1774
+ titleLevel,
1775
+ titleSize,
1622
1776
  description,
1623
1777
  headerAlignment = "center",
1624
1778
  tiers,
@@ -1628,100 +1782,68 @@ function PricingWidget({
1628
1782
  verticalPadding,
1629
1783
  background
1630
1784
  },
1631
- state: { theme },
1632
- nextTheme
1785
+ state: { theme }
1633
1786
  }) {
1634
1787
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
1635
1788
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
1636
1789
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
1637
- return /* @__PURE__ */ jsx(
1638
- Section,
1639
- {
1640
- theme: overriddenTheme,
1641
- id: cssId,
1642
- background,
1643
- nextTheme,
1644
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
1645
- /* @__PURE__ */ jsxs(
1646
- "div",
1790
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
1791
+ /* @__PURE__ */ jsxs(
1792
+ "div",
1793
+ {
1794
+ className: clsx3(
1795
+ "flex flex-col gap-4",
1796
+ headerAlignment === "center" ? "items-center text-center" : "items-start"
1797
+ ),
1798
+ children: [
1799
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
1800
+ description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) })
1801
+ ]
1802
+ }
1803
+ ),
1804
+ tiers && tiers.length > 0 && /* @__PURE__ */ jsx(
1805
+ "div",
1806
+ {
1807
+ className: layout === "stacked" ? "mx-auto flex w-full max-w-xl flex-col gap-6" : "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-stretch",
1808
+ children: tiers.map((tier, index) => /* @__PURE__ */ jsx(
1809
+ PageCard,
1647
1810
  {
1811
+ theme: overriddenTheme,
1648
1812
  className: clsx3(
1649
- "flex flex-col gap-4",
1650
- headerAlignment === "center" ? "items-center text-center" : "items-start"
1813
+ tier.highlighted && "ring-2 ring-primary",
1814
+ layout === "highlight" && tier.highlighted && "relative z-10 shadow-xl md:-translate-y-3"
1651
1815
  ),
1652
- children: [
1653
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
1654
- description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(
1655
- TextRenderer,
1656
- {
1657
- json: description,
1658
- theme: overriddenTheme
1659
- }
1660
- ) })
1661
- ]
1662
- }
1663
- ),
1664
- tiers && tiers.length > 0 && /* @__PURE__ */ jsx(
1665
- "div",
1666
- {
1667
- className: layout === "stacked" ? "mx-auto flex w-full max-w-xl flex-col gap-6" : "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 items-stretch",
1668
- children: tiers.map((tier, index) => /* @__PURE__ */ jsx(
1669
- PageCard,
1816
+ children: /* @__PURE__ */ jsxs(
1817
+ PageCardContent,
1670
1818
  {
1671
1819
  theme: overriddenTheme,
1672
- className: clsx3(
1673
- tier.highlighted && "ring-2 ring-primary",
1674
- layout === "highlight" && tier.highlighted && "relative z-10 shadow-xl md:-translate-y-3"
1675
- ),
1676
- children: /* @__PURE__ */ jsxs(
1677
- PageCardContent,
1678
- {
1679
- theme: overriddenTheme,
1680
- className: "h-full flex flex-col gap-4",
1681
- children: [
1682
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1683
- /* @__PURE__ */ jsx(Preheader, { theme: overriddenTheme, children: tier.name }),
1684
- tier.highlighted && /* @__PURE__ */ jsx(Badge, { theme: overriddenTheme, children: "Most popular" })
1685
- ] }),
1686
- /* @__PURE__ */ jsx(PageCardHeader, { theme: overriddenTheme, children: tier.price }),
1687
- tier.description && /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, children: tier.description }),
1688
- tier.features && tier.features.length > 0 && /* @__PURE__ */ jsx("div", { className: "grow flex flex-col gap-2", children: tier.features.map(
1689
- (feature, i) => /* @__PURE__ */ jsx(
1690
- Text2,
1691
- {
1692
- theme: overriddenTheme,
1693
- children: feature
1694
- },
1695
- i
1696
- )
1697
- ) }),
1698
- tier.buttonAction && tier.buttonCaption && /* @__PURE__ */ jsx(
1699
- NavLink,
1700
- {
1701
- href: tier.buttonAction,
1702
- className: "w-full mt-auto",
1703
- children: /* @__PURE__ */ jsx(
1704
- Button2,
1705
- {
1706
- theme: overriddenTheme,
1707
- variant: tier.highlighted ? "default" : "secondary",
1708
- className: "w-full",
1709
- children: tier.buttonCaption
1710
- }
1711
- )
1712
- }
1713
- )
1714
- ]
1715
- }
1716
- )
1717
- },
1718
- index
1719
- ))
1720
- }
1721
- )
1722
- ] })
1723
- }
1724
- );
1820
+ className: "h-full flex flex-col gap-4",
1821
+ children: [
1822
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1823
+ /* @__PURE__ */ jsx(Preheader, { theme: overriddenTheme, children: tier.name }),
1824
+ tier.highlighted && /* @__PURE__ */ jsx(Badge, { theme: overriddenTheme, children: "Most popular" })
1825
+ ] }),
1826
+ /* @__PURE__ */ jsx(PageCardHeader, { theme: overriddenTheme, children: tier.price }),
1827
+ tier.description && /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, children: tier.description }),
1828
+ tier.features && tier.features.length > 0 && /* @__PURE__ */ jsx("div", { className: "grow flex flex-col gap-2", children: tier.features.map((feature, i) => /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: feature }, i)) }),
1829
+ tier.buttonAction && tier.buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: tier.buttonAction, className: "w-full mt-auto", children: /* @__PURE__ */ jsx(
1830
+ Button2,
1831
+ {
1832
+ theme: overriddenTheme,
1833
+ variant: tier.highlighted ? "default" : "secondary",
1834
+ className: "w-full",
1835
+ children: tier.buttonCaption
1836
+ }
1837
+ ) })
1838
+ ]
1839
+ }
1840
+ )
1841
+ },
1842
+ index
1843
+ ))
1844
+ }
1845
+ )
1846
+ ] }) });
1725
1847
  }
1726
1848
  var createTier = () => ({
1727
1849
  name: "New plan",
@@ -1742,22 +1864,22 @@ function PricingEditor({
1742
1864
  TextField,
1743
1865
  {
1744
1866
  label: "Title",
1867
+ hint: "Wrap words in *asterisks* to highlight them.",
1745
1868
  value: settings.title,
1746
1869
  onChange: (title) => update({ title })
1747
1870
  }
1748
1871
  ),
1749
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
1750
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
1751
- /* @__PURE__ */ jsx(
1752
- Editor,
1753
- {
1754
- initialContent: settings.description ?? emptyDoc,
1755
- onChange: (description) => update({ description }),
1756
- showToolbar: false,
1757
- editorClassName: "min-h-[80px]"
1758
- }
1759
- )
1760
- ] }),
1872
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
1873
+ /* @__PURE__ */ jsx(
1874
+ RichTextField,
1875
+ {
1876
+ label: "Description",
1877
+ value: settings.description,
1878
+ onChange: (description) => update({ description }),
1879
+ showToolbar: false,
1880
+ minHeight: 80
1881
+ }
1882
+ ),
1761
1883
  /* @__PURE__ */ jsx(
1762
1884
  SelectField,
1763
1885
  {
@@ -1873,12 +1995,7 @@ var pricingDefaults = {
1873
1995
  name: "Pro",
1874
1996
  price: "$29/mo",
1875
1997
  description: "For growing businesses that need more.",
1876
- features: [
1877
- "5 websites",
1878
- "Custom domain",
1879
- "Blog + Email",
1880
- "Priority support"
1881
- ],
1998
+ features: ["5 websites", "Custom domain", "Blog + Email", "Priority support"],
1882
1999
  buttonCaption: "Talk to us",
1883
2000
  buttonAction: "/help",
1884
2001
  highlighted: true
@@ -1904,6 +2021,7 @@ var Pricing = {
1904
2021
  metadata: pricingMetadata,
1905
2022
  widget: PricingWidget,
1906
2023
  editor: PricingEditor,
2024
+ titleSize: true,
1907
2025
  getDefaultSettings: () => pricingDefaults,
1908
2026
  layouts: [
1909
2027
  { id: "grid", name: "Grid" },
@@ -1922,6 +2040,8 @@ var bannerMetadata = {
1922
2040
  function BannerWidget({
1923
2041
  settings: {
1924
2042
  title,
2043
+ titleLevel,
2044
+ titleSize,
1925
2045
  description,
1926
2046
  buttonCaption,
1927
2047
  buttonAction,
@@ -1934,8 +2054,7 @@ function BannerWidget({
1934
2054
  verticalPadding,
1935
2055
  background
1936
2056
  },
1937
- state: { theme },
1938
- nextTheme
2057
+ state: { theme }
1939
2058
  }) {
1940
2059
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
1941
2060
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
@@ -1944,7 +2063,7 @@ function BannerWidget({
1944
2063
  const isSplit = layout === "split";
1945
2064
  const isBoxed = layout === "boxed";
1946
2065
  const heading = /* @__PURE__ */ jsxs(Fragment, { children: [
1947
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
2066
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
1948
2067
  description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) })
1949
2068
  ] });
1950
2069
  const buttons = (buttonAction || secondaryButtonAction) && /* @__PURE__ */ jsxs(
@@ -1956,14 +2075,7 @@ function BannerWidget({
1956
2075
  !isSplit && isCentered ? "md:!justify-center" : ""
1957
2076
  ),
1958
2077
  children: [
1959
- buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, children: /* @__PURE__ */ jsx(
1960
- Button2,
1961
- {
1962
- theme: overriddenTheme,
1963
- className: "w-full md:min-w-[150px]",
1964
- children: buttonCaption
1965
- }
1966
- ) }),
2078
+ buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, children: /* @__PURE__ */ jsx(Button2, { theme: overriddenTheme, className: "w-full md:min-w-[150px]", children: buttonCaption }) }),
1967
2079
  secondaryButtonAction && secondaryButtonCaption && /* @__PURE__ */ jsx(NavLink, { href: secondaryButtonAction, children: /* @__PURE__ */ jsx(
1968
2080
  Button2,
1969
2081
  {
@@ -1992,23 +2104,14 @@ function BannerWidget({
1992
2104
  ]
1993
2105
  }
1994
2106
  );
1995
- return /* @__PURE__ */ jsx(
1996
- Section,
2107
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: isBoxed ? /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, className: "mx-auto max-w-3xl", children: /* @__PURE__ */ jsx(
2108
+ PageCardContent,
1997
2109
  {
1998
2110
  theme: overriddenTheme,
1999
- id: cssId,
2000
- background,
2001
- nextTheme,
2002
- children: isBoxed ? /* @__PURE__ */ jsx(PageCard, { theme: overriddenTheme, className: "mx-auto max-w-3xl", children: /* @__PURE__ */ jsx(
2003
- PageCardContent,
2004
- {
2005
- theme: overriddenTheme,
2006
- className: "items-center p-8 text-center md:p-12",
2007
- children: content
2008
- }
2009
- ) }) : content
2111
+ className: "items-center p-8 text-center md:p-12",
2112
+ children: content
2010
2113
  }
2011
- );
2114
+ ) }) : content });
2012
2115
  }
2013
2116
  function BannerEditor({
2014
2117
  settings,
@@ -2021,22 +2124,22 @@ function BannerEditor({
2021
2124
  TextField,
2022
2125
  {
2023
2126
  label: "Title",
2127
+ hint: "Wrap words in *asterisks* to highlight them.",
2024
2128
  value: settings.title,
2025
2129
  onChange: (title) => update({ title })
2026
2130
  }
2027
2131
  ),
2028
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
2029
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
2030
- /* @__PURE__ */ jsx(
2031
- Editor,
2032
- {
2033
- initialContent: settings.description ?? emptyDoc,
2034
- onChange: (description) => update({ description }),
2035
- showToolbar: false,
2036
- editorClassName: "min-h-[80px]"
2037
- }
2038
- )
2039
- ] })
2132
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
2133
+ /* @__PURE__ */ jsx(
2134
+ RichTextField,
2135
+ {
2136
+ label: "Description",
2137
+ value: settings.description,
2138
+ onChange: (description) => update({ description }),
2139
+ showToolbar: false,
2140
+ minHeight: 80
2141
+ }
2142
+ )
2040
2143
  ] }),
2041
2144
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Calls to action", children: [
2042
2145
  /* @__PURE__ */ jsx(
@@ -2102,6 +2205,7 @@ var Banner = {
2102
2205
  metadata: bannerMetadata,
2103
2206
  widget: BannerWidget,
2104
2207
  editor: BannerEditor,
2208
+ titleSize: true,
2105
2209
  getDefaultSettings: () => bannerDefaults,
2106
2210
  layouts: [
2107
2211
  { id: "stacked", name: "Stacked" },
@@ -2141,27 +2245,16 @@ async function subscribeEmail(email, pageData) {
2141
2245
  return { success: false };
2142
2246
  }
2143
2247
  }
2144
- function EmailFormWidget({
2145
- settings: {
2146
- title,
2147
- description,
2148
- buttonCaption = "Subscribe",
2149
- successMessage = "Thanks for subscribing!",
2150
- alignment = "left",
2151
- layout = "stacked",
2152
- cssId,
2153
- maxWidth,
2154
- verticalPadding,
2155
- background
2156
- },
2157
- state: { theme },
2248
+ function EmailForm({
2249
+ theme: overriddenTheme,
2250
+ layout,
2251
+ alignment,
2252
+ buttonCaption,
2253
+ successMessage,
2158
2254
  pageData,
2159
2255
  editing,
2160
- nextTheme
2256
+ heading
2161
2257
  }) {
2162
- const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
2163
- overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
2164
- overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
2165
2258
  const [email, setEmail] = useState("");
2166
2259
  const [isSubmitting, setIsSubmitting] = useState(false);
2167
2260
  const [success, setSuccess] = useState(false);
@@ -2181,37 +2274,62 @@ function EmailFormWidget({
2181
2274
  }
2182
2275
  };
2183
2276
  if (layout === "inline") {
2184
- return /* @__PURE__ */ jsx(
2185
- Section,
2277
+ return /* @__PURE__ */ jsxs(
2278
+ "form",
2186
2279
  {
2187
- theme: overriddenTheme,
2188
- id: cssId,
2189
- background,
2190
- nextTheme,
2191
- children: /* @__PURE__ */ jsxs(
2192
- "form",
2280
+ onSubmit,
2281
+ className: "flex flex-col items-start gap-4 md:!flex-row md:items-center md:justify-between",
2282
+ children: [
2283
+ heading,
2284
+ success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: successMessage }) : /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-2 sm:!flex-row md:w-auto md:shrink-0", children: [
2285
+ /* @__PURE__ */ jsx(
2286
+ Input,
2287
+ {
2288
+ theme: overriddenTheme,
2289
+ id: "email",
2290
+ value: email,
2291
+ onChange: (e) => setEmail(e.target.value),
2292
+ placeholder: "Enter your email",
2293
+ type: "email",
2294
+ required: true,
2295
+ className: "md:w-64"
2296
+ }
2297
+ ),
2298
+ /* @__PURE__ */ jsx(
2299
+ Button2,
2300
+ {
2301
+ theme: overriddenTheme,
2302
+ type: "submit",
2303
+ disabled: !editing && (isSubmitting || !email),
2304
+ children: buttonCaption
2305
+ }
2306
+ )
2307
+ ] })
2308
+ ]
2309
+ }
2310
+ );
2311
+ }
2312
+ return /* @__PURE__ */ jsxs(
2313
+ "form",
2314
+ {
2315
+ onSubmit,
2316
+ className: clsx3(
2317
+ "flex gap-4",
2318
+ layout === "split" ? "flex-col md:!flex-row md:items-center md:justify-between md:gap-10" : clsx3("flex-col", isCentered ? "items-center text-center" : "items-start")
2319
+ ),
2320
+ children: [
2321
+ heading,
2322
+ success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: successMessage }) : /* @__PURE__ */ jsxs(
2323
+ "div",
2193
2324
  {
2194
- onSubmit,
2195
- className: "flex flex-col items-start gap-4 md:!flex-row md:items-center md:justify-between",
2325
+ className: clsx3(
2326
+ "flex flex-col md:!flex-row md:!items-end gap-2",
2327
+ layout === "split" ? "md:shrink-0" : "w-full",
2328
+ layout !== "split" && isCentered ? "md:!justify-center" : ""
2329
+ ),
2196
2330
  children: [
2197
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
2198
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, className: "text-xl", children: title }),
2199
- description && /* @__PURE__ */ jsx(
2200
- Subheader1,
2201
- {
2202
- theme: overriddenTheme,
2203
- component: "span",
2204
- children: /* @__PURE__ */ jsx(
2205
- TextRenderer,
2206
- {
2207
- json: description,
2208
- theme: overriddenTheme
2209
- }
2210
- )
2211
- }
2212
- )
2213
- ] }),
2214
- success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: successMessage }) : /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-2 sm:!flex-row md:w-auto md:shrink-0", children: [
2331
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2332
+ /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "email", children: "Email" }),
2215
2333
  /* @__PURE__ */ jsx(
2216
2334
  Input,
2217
2335
  {
@@ -2221,105 +2339,85 @@ function EmailFormWidget({
2221
2339
  onChange: (e) => setEmail(e.target.value),
2222
2340
  placeholder: "Enter your email",
2223
2341
  type: "email",
2224
- required: true,
2225
- className: "md:w-64"
2226
- }
2227
- ),
2228
- /* @__PURE__ */ jsx(
2229
- Button2,
2230
- {
2231
- theme: overriddenTheme,
2232
- type: "submit",
2233
- disabled: !editing && (isSubmitting || !email),
2234
- children: buttonCaption
2342
+ required: true
2235
2343
  }
2236
2344
  )
2237
- ] })
2345
+ ] }),
2346
+ /* @__PURE__ */ jsx(
2347
+ Button2,
2348
+ {
2349
+ theme: overriddenTheme,
2350
+ type: "submit",
2351
+ disabled: !editing && (isSubmitting || !email),
2352
+ children: buttonCaption
2353
+ }
2354
+ )
2238
2355
  ]
2239
2356
  }
2240
2357
  )
2358
+ ]
2359
+ }
2360
+ );
2361
+ }
2362
+ function EmailFormWidget({
2363
+ settings: {
2364
+ title,
2365
+ titleLevel,
2366
+ titleSize,
2367
+ description,
2368
+ buttonCaption = "Subscribe",
2369
+ successMessage = "Thanks for subscribing!",
2370
+ alignment = "left",
2371
+ layout = "stacked",
2372
+ cssId,
2373
+ maxWidth,
2374
+ verticalPadding,
2375
+ background
2376
+ },
2377
+ state: { theme },
2378
+ pageData,
2379
+ editing
2380
+ }) {
2381
+ const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
2382
+ overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
2383
+ overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
2384
+ const descriptionNode = description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) });
2385
+ const heading = layout === "inline" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
2386
+ /* @__PURE__ */ jsx(
2387
+ Header1,
2388
+ {
2389
+ theme: overriddenTheme,
2390
+ ...titleProps({ titleLevel, titleSize }, "h2", "text-xl"),
2391
+ children: renderTitle(title, overriddenTheme)
2241
2392
  }
2242
- );
2243
- }
2244
- return /* @__PURE__ */ jsx(
2245
- Section,
2393
+ ),
2394
+ descriptionNode
2395
+ ] }) : /* @__PURE__ */ jsxs(
2396
+ "div",
2246
2397
  {
2247
- theme: overriddenTheme,
2248
- id: cssId,
2249
- background,
2250
- nextTheme,
2251
- children: /* @__PURE__ */ jsxs(
2252
- "form",
2253
- {
2254
- onSubmit,
2255
- className: clsx3(
2256
- "flex gap-4",
2257
- layout === "split" ? "flex-col md:!flex-row md:items-center md:justify-between md:gap-10" : clsx3(
2258
- "flex-col",
2259
- isCentered ? "items-center text-center" : "items-start"
2260
- )
2261
- ),
2262
- children: [
2263
- /* @__PURE__ */ jsxs(
2264
- "div",
2265
- {
2266
- className: clsx3(
2267
- "flex flex-col gap-4",
2268
- layout === "split" ? "items-start" : "contents"
2269
- ),
2270
- children: [
2271
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
2272
- description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(
2273
- TextRenderer,
2274
- {
2275
- json: description,
2276
- theme: overriddenTheme
2277
- }
2278
- ) })
2279
- ]
2280
- }
2281
- ),
2282
- success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: successMessage }) : /* @__PURE__ */ jsxs(
2283
- "div",
2284
- {
2285
- className: clsx3(
2286
- "flex flex-col md:!flex-row md:!items-end gap-2",
2287
- layout === "split" ? "md:shrink-0" : "w-full",
2288
- layout !== "split" && isCentered ? "md:!justify-center" : ""
2289
- ),
2290
- children: [
2291
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2292
- /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "email", children: "Email" }),
2293
- /* @__PURE__ */ jsx(
2294
- Input,
2295
- {
2296
- theme: overriddenTheme,
2297
- id: "email",
2298
- value: email,
2299
- onChange: (e) => setEmail(e.target.value),
2300
- placeholder: "Enter your email",
2301
- type: "email",
2302
- required: true
2303
- }
2304
- )
2305
- ] }),
2306
- /* @__PURE__ */ jsx(
2307
- Button2,
2308
- {
2309
- theme: overriddenTheme,
2310
- type: "submit",
2311
- disabled: !editing && (isSubmitting || !email),
2312
- children: buttonCaption
2313
- }
2314
- )
2315
- ]
2316
- }
2317
- )
2318
- ]
2319
- }
2320
- )
2398
+ className: clsx3(
2399
+ "flex flex-col gap-4",
2400
+ layout === "split" ? "items-start" : "contents"
2401
+ ),
2402
+ children: [
2403
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
2404
+ descriptionNode
2405
+ ]
2321
2406
  }
2322
2407
  );
2408
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsx(
2409
+ EmailForm,
2410
+ {
2411
+ theme: overriddenTheme,
2412
+ layout,
2413
+ alignment,
2414
+ buttonCaption,
2415
+ successMessage,
2416
+ pageData,
2417
+ editing,
2418
+ heading
2419
+ }
2420
+ ) });
2323
2421
  }
2324
2422
  function EmailFormEditor({
2325
2423
  settings,
@@ -2332,22 +2430,22 @@ function EmailFormEditor({
2332
2430
  TextField,
2333
2431
  {
2334
2432
  label: "Title",
2433
+ hint: "Wrap words in *asterisks* to highlight them.",
2335
2434
  value: settings.title,
2336
2435
  onChange: (title) => update({ title })
2337
2436
  }
2338
2437
  ),
2339
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
2340
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
2341
- /* @__PURE__ */ jsx(
2342
- Editor,
2343
- {
2344
- initialContent: settings.description ?? emptyDoc,
2345
- onChange: (description) => update({ description }),
2346
- showToolbar: false,
2347
- editorClassName: "min-h-[80px]"
2348
- }
2349
- )
2350
- ] })
2438
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
2439
+ /* @__PURE__ */ jsx(
2440
+ RichTextField,
2441
+ {
2442
+ label: "Description",
2443
+ value: settings.description,
2444
+ onChange: (description) => update({ description }),
2445
+ showToolbar: false,
2446
+ minHeight: 80
2447
+ }
2448
+ )
2351
2449
  ] }),
2352
2450
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Form", children: [
2353
2451
  /* @__PURE__ */ jsx(
@@ -2391,10 +2489,11 @@ var emailFormDefaults = {
2391
2489
  };
2392
2490
 
2393
2491
  // src/blocks/email-form/index.ts
2394
- var EmailForm = {
2492
+ var EmailForm2 = {
2395
2493
  metadata: emailFormMetadata,
2396
2494
  widget: EmailFormWidget,
2397
2495
  editor: EmailFormEditor,
2496
+ titleSize: true,
2398
2497
  getDefaultSettings: () => emailFormDefaults,
2399
2498
  layouts: [
2400
2499
  { id: "stacked", name: "Stacked" },
@@ -2451,33 +2550,18 @@ async function submitTicket(input, pageData) {
2451
2550
  return { success: false };
2452
2551
  }
2453
2552
  }
2454
- function SupportFormWidget({
2455
- settings: {
2456
- title,
2457
- description,
2458
- buttonCaption = "Submit ticket",
2459
- successMessage = "Thanks \u2014 we've got your ticket and will reply by email soon.",
2460
- alignment = "left",
2461
- cssId,
2462
- maxWidth,
2463
- verticalPadding,
2464
- background
2465
- },
2466
- state: { theme },
2553
+ function SupportForm({
2554
+ theme: overriddenTheme,
2555
+ buttonCaption,
2556
+ successMessage,
2467
2557
  pageData,
2468
- editing,
2469
- nextTheme
2558
+ editing
2470
2559
  }) {
2471
- const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
2472
- overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
2473
- overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
2474
2560
  const [subject, setSubject] = useState("");
2475
2561
  const [message, setMessage] = useState("");
2476
2562
  const [email, setEmail] = useState("");
2477
2563
  const [name, setName] = useState("");
2478
- const [suggestions, setSuggestions] = useState(
2479
- []
2480
- );
2564
+ const [suggestions, setSuggestions] = useState([]);
2481
2565
  const [isSubmitting, setIsSubmitting] = useState(false);
2482
2566
  const [success, setSuccess] = useState(false);
2483
2567
  const debounceRef = useRef(null);
@@ -2512,158 +2596,168 @@ function SupportFormWidget({
2512
2596
  setIsSubmitting(false);
2513
2597
  }
2514
2598
  };
2515
- const isCentered = alignment === "center";
2516
2599
  const inputStyles = overriddenTheme.interactives.input;
2517
2600
  const inputTypography = overriddenTheme.typography.input;
2518
2601
  const cardStyles = overriddenTheme.interactives.card;
2519
- return /* @__PURE__ */ jsxs(
2520
- Section,
2521
- {
2522
- theme: overriddenTheme,
2523
- id: cssId,
2524
- background,
2525
- nextTheme,
2526
- children: [
2527
- /* @__PURE__ */ jsxs(
2528
- "div",
2602
+ return success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, className: "mt-4", children: successMessage }) : /* @__PURE__ */ jsxs("form", { onSubmit, className: "mt-4 flex w-full max-w-lg flex-col gap-3", children: [
2603
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2604
+ /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "subject", children: "Subject" }),
2605
+ /* @__PURE__ */ jsx(
2606
+ Input,
2607
+ {
2608
+ theme: overriddenTheme,
2609
+ id: "subject",
2610
+ value: subject,
2611
+ onChange: (e) => setSubject(e.target.value),
2612
+ placeholder: "What do you need help with?",
2613
+ required: true,
2614
+ className: "w-full"
2615
+ }
2616
+ )
2617
+ ] }),
2618
+ suggestions.length > 0 && /* @__PURE__ */ jsxs(
2619
+ "div",
2620
+ {
2621
+ className: cn(
2622
+ "rounded-lg border border-border bg-card p-3 text-sm text-card-foreground shadow-sm",
2623
+ cardStyles.border?.width,
2624
+ cardStyles.border?.radius,
2625
+ cardStyles.border?.style,
2626
+ cardStyles.shadow
2627
+ ),
2628
+ children: [
2629
+ /* @__PURE__ */ jsx("p", { className: "mb-1 font-medium", children: "This might help:" }),
2630
+ /* @__PURE__ */ jsx("ul", { className: "list-inside list-disc", children: suggestions.map((doc) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
2631
+ "a",
2632
+ {
2633
+ href: suggestionHref(doc),
2634
+ target: "_blank",
2635
+ rel: "noreferrer",
2636
+ className: "underline",
2637
+ children: doc.title ?? doc.slug
2638
+ }
2639
+ ) }, doc.documentId)) })
2640
+ ]
2641
+ }
2642
+ ),
2643
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2644
+ /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "message", children: "Message" }),
2645
+ /* @__PURE__ */ jsx(
2646
+ "textarea",
2647
+ {
2648
+ id: "message",
2649
+ value: message,
2650
+ onChange: (e) => setMessage(e.target.value),
2651
+ placeholder: "Describe the issue\u2026",
2652
+ required: true,
2653
+ rows: 4,
2654
+ className: cn(
2655
+ "w-full border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2656
+ inputTypography.fontFamily,
2657
+ inputTypography.fontSize,
2658
+ inputTypography.fontWeight,
2659
+ inputTypography.lineHeight,
2660
+ inputTypography.letterSpacing,
2661
+ inputStyles.border?.width,
2662
+ inputStyles.border?.style,
2663
+ inputStyles.border?.radius,
2664
+ inputStyles.shadow,
2665
+ inputStyles.custom
2666
+ )
2667
+ }
2668
+ )
2669
+ ] }),
2670
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:!flex-row", children: [
2671
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1 items-start", children: [
2672
+ /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "email", children: "Email" }),
2673
+ /* @__PURE__ */ jsx(
2674
+ Input,
2529
2675
  {
2530
- className: clsx3(
2531
- "flex flex-col gap-4",
2532
- isCentered ? "items-center text-center" : "items-start"
2533
- ),
2534
- children: [
2535
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
2536
- description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(
2537
- TextRenderer,
2538
- {
2539
- json: description,
2540
- theme: overriddenTheme
2541
- }
2542
- ) })
2543
- ]
2676
+ theme: overriddenTheme,
2677
+ id: "email",
2678
+ type: "email",
2679
+ value: email,
2680
+ onChange: (e) => setEmail(e.target.value),
2681
+ placeholder: "you@example.com",
2682
+ required: true,
2683
+ className: "w-full"
2544
2684
  }
2545
- ),
2546
- success ? /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, className: "mt-4", children: successMessage }) : /* @__PURE__ */ jsxs(
2547
- "form",
2685
+ )
2686
+ ] }),
2687
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1 items-start", children: [
2688
+ /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "name", children: "Name (optional)" }),
2689
+ /* @__PURE__ */ jsx(
2690
+ Input,
2548
2691
  {
2549
- onSubmit,
2550
- className: "mt-4 flex w-full max-w-lg flex-col gap-3",
2551
- children: [
2552
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2553
- /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "subject", children: "Subject" }),
2554
- /* @__PURE__ */ jsx(
2555
- Input,
2556
- {
2557
- theme: overriddenTheme,
2558
- id: "subject",
2559
- value: subject,
2560
- onChange: (e) => setSubject(e.target.value),
2561
- placeholder: "What do you need help with?",
2562
- required: true,
2563
- className: "w-full"
2564
- }
2565
- )
2566
- ] }),
2567
- suggestions.length > 0 && /* @__PURE__ */ jsxs(
2568
- "div",
2569
- {
2570
- className: cn(
2571
- "rounded-lg border border-border bg-card p-3 text-sm text-card-foreground shadow-sm",
2572
- cardStyles.border?.width,
2573
- cardStyles.border?.radius,
2574
- cardStyles.border?.style,
2575
- cardStyles.shadow
2576
- ),
2577
- children: [
2578
- /* @__PURE__ */ jsx("p", { className: "mb-1 font-medium", children: "This might help:" }),
2579
- /* @__PURE__ */ jsx("ul", { className: "list-inside list-disc", children: suggestions.map((doc) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
2580
- "a",
2581
- {
2582
- href: suggestionHref(doc),
2583
- target: "_blank",
2584
- rel: "noreferrer",
2585
- className: "underline",
2586
- children: doc.title ?? doc.slug
2587
- }
2588
- ) }, doc.documentId)) })
2589
- ]
2590
- }
2591
- ),
2592
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 items-start", children: [
2593
- /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "message", children: "Message" }),
2594
- /* @__PURE__ */ jsx(
2595
- "textarea",
2596
- {
2597
- id: "message",
2598
- value: message,
2599
- onChange: (e) => setMessage(e.target.value),
2600
- placeholder: "Describe the issue\u2026",
2601
- required: true,
2602
- rows: 4,
2603
- className: cn(
2604
- "w-full border border-input bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2605
- inputTypography.fontFamily,
2606
- inputTypography.fontSize,
2607
- inputTypography.fontWeight,
2608
- inputTypography.lineHeight,
2609
- inputTypography.letterSpacing,
2610
- inputStyles.border?.width,
2611
- inputStyles.border?.style,
2612
- inputStyles.border?.radius,
2613
- inputStyles.shadow,
2614
- inputStyles.custom
2615
- )
2616
- }
2617
- )
2618
- ] }),
2619
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 sm:!flex-row", children: [
2620
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1 items-start", children: [
2621
- /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "email", children: "Email" }),
2622
- /* @__PURE__ */ jsx(
2623
- Input,
2624
- {
2625
- theme: overriddenTheme,
2626
- id: "email",
2627
- type: "email",
2628
- value: email,
2629
- onChange: (e) => setEmail(e.target.value),
2630
- placeholder: "you@example.com",
2631
- required: true,
2632
- className: "w-full"
2633
- }
2634
- )
2635
- ] }),
2636
- /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-1 items-start", children: [
2637
- /* @__PURE__ */ jsx(Label, { theme: overriddenTheme, htmlFor: "name", children: "Name (optional)" }),
2638
- /* @__PURE__ */ jsx(
2639
- Input,
2640
- {
2641
- theme: overriddenTheme,
2642
- id: "name",
2643
- value: name,
2644
- onChange: (e) => setName(e.target.value),
2645
- placeholder: "Your name",
2646
- className: "w-full"
2647
- }
2648
- )
2649
- ] })
2650
- ] }),
2651
- /* @__PURE__ */ jsx(
2652
- Button2,
2653
- {
2654
- theme: overriddenTheme,
2655
- type: "submit",
2656
- disabled: !editing && (isSubmitting || !subject || !message || !email),
2657
- className: "self-start",
2658
- children: buttonCaption
2659
- }
2660
- )
2661
- ]
2692
+ theme: overriddenTheme,
2693
+ id: "name",
2694
+ value: name,
2695
+ onChange: (e) => setName(e.target.value),
2696
+ placeholder: "Your name",
2697
+ className: "w-full"
2662
2698
  }
2663
2699
  )
2664
- ]
2665
- }
2666
- );
2700
+ ] })
2701
+ ] }),
2702
+ /* @__PURE__ */ jsx(
2703
+ Button2,
2704
+ {
2705
+ theme: overriddenTheme,
2706
+ type: "submit",
2707
+ disabled: !editing && (isSubmitting || !subject || !message || !email),
2708
+ className: "self-start",
2709
+ children: buttonCaption
2710
+ }
2711
+ )
2712
+ ] });
2713
+ }
2714
+ function SupportFormWidget({
2715
+ settings: {
2716
+ title,
2717
+ titleLevel,
2718
+ titleSize,
2719
+ description,
2720
+ buttonCaption = "Submit ticket",
2721
+ successMessage = "Thanks \u2014 we've got your ticket and will reply by email soon.",
2722
+ alignment = "left",
2723
+ cssId,
2724
+ maxWidth,
2725
+ verticalPadding,
2726
+ background
2727
+ },
2728
+ state: { theme },
2729
+ pageData,
2730
+ editing
2731
+ }) {
2732
+ const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
2733
+ overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
2734
+ overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
2735
+ const isCentered = alignment === "center";
2736
+ return /* @__PURE__ */ jsxs(Section, { theme: overriddenTheme, id: cssId, background, children: [
2737
+ /* @__PURE__ */ jsxs(
2738
+ "div",
2739
+ {
2740
+ className: clsx3(
2741
+ "flex flex-col gap-4",
2742
+ isCentered ? "items-center text-center" : "items-start"
2743
+ ),
2744
+ children: [
2745
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
2746
+ description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) })
2747
+ ]
2748
+ }
2749
+ ),
2750
+ /* @__PURE__ */ jsx(
2751
+ SupportForm,
2752
+ {
2753
+ theme: overriddenTheme,
2754
+ buttonCaption,
2755
+ successMessage,
2756
+ pageData,
2757
+ editing
2758
+ }
2759
+ )
2760
+ ] });
2667
2761
  }
2668
2762
  function SupportFormEditor({
2669
2763
  settings,
@@ -2676,22 +2770,22 @@ function SupportFormEditor({
2676
2770
  TextField,
2677
2771
  {
2678
2772
  label: "Title",
2773
+ hint: "Wrap words in *asterisks* to highlight them.",
2679
2774
  value: settings.title,
2680
2775
  onChange: (title) => update({ title })
2681
2776
  }
2682
2777
  ),
2683
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
2684
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
2685
- /* @__PURE__ */ jsx(
2686
- Editor,
2687
- {
2688
- initialContent: settings.description ?? emptyDoc,
2689
- onChange: (description) => update({ description }),
2690
- showToolbar: false,
2691
- editorClassName: "min-h-[80px]"
2692
- }
2693
- )
2694
- ] })
2778
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
2779
+ /* @__PURE__ */ jsx(
2780
+ RichTextField,
2781
+ {
2782
+ label: "Description",
2783
+ value: settings.description,
2784
+ onChange: (description) => update({ description }),
2785
+ showToolbar: false,
2786
+ minHeight: 80
2787
+ }
2788
+ )
2695
2789
  ] }),
2696
2790
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Form", children: [
2697
2791
  /* @__PURE__ */ jsx(
@@ -2735,10 +2829,11 @@ var supportFormDefaults = {
2735
2829
  };
2736
2830
 
2737
2831
  // src/blocks/support-form/index.ts
2738
- var SupportForm = {
2832
+ var SupportForm2 = {
2739
2833
  metadata: supportFormMetadata,
2740
2834
  widget: SupportFormWidget,
2741
2835
  editor: SupportFormEditor,
2836
+ titleSize: true,
2742
2837
  getDefaultSettings: () => supportFormDefaults,
2743
2838
  layouts: [{ id: "stacked", name: "Stacked" }]
2744
2839
  };
@@ -2752,22 +2847,26 @@ var footerMetadata = {
2752
2847
  };
2753
2848
  function FooterWidget({
2754
2849
  settings: {
2755
- logoText,
2756
- tagline,
2850
+ tagline: ownTagline,
2757
2851
  columns = [],
2758
2852
  copyrightText,
2759
2853
  layout = "columns",
2854
+ showThemeSwitcher = true,
2760
2855
  cssId,
2761
2856
  maxWidth,
2762
2857
  verticalPadding,
2763
2858
  background
2764
2859
  },
2765
2860
  state: { theme },
2766
- nextTheme
2861
+ pageData,
2862
+ themeSwitcher
2767
2863
  }) {
2864
+ const logoText = pageData.siteTitle;
2865
+ const tagline = ownTagline || pageData.siteSubtitle;
2768
2866
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
2769
2867
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
2770
2868
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
2869
+ const colorModeControl = showThemeSwitcher ? themeSwitcher : null;
2771
2870
  return /* @__PURE__ */ jsxs(
2772
2871
  Section,
2773
2872
  {
@@ -2775,11 +2874,10 @@ function FooterWidget({
2775
2874
  component: "footer",
2776
2875
  id: cssId,
2777
2876
  background,
2778
- nextTheme,
2779
2877
  className: "border-t",
2780
2878
  children: [
2781
2879
  layout === "minimal" ? /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-wrap items-center justify-between gap-4", children: [
2782
- logoText && /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, children: logoText }),
2880
+ logoText && /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, as: "p", children: logoText }),
2783
2881
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2", children: [
2784
2882
  columns.flatMap(
2785
2883
  (column) => column.links.map((link) => /* @__PURE__ */ jsx(
@@ -2787,23 +2885,17 @@ function FooterWidget({
2787
2885
  {
2788
2886
  href: link.href,
2789
2887
  className: "no-underline",
2790
- children: /* @__PURE__ */ jsx(
2791
- Link,
2792
- {
2793
- theme: overriddenTheme,
2794
- className: "text-xs",
2795
- children: link.label
2796
- }
2797
- )
2888
+ children: /* @__PURE__ */ jsx(Link, { theme: overriddenTheme, className: "text-xs", children: link.label })
2798
2889
  },
2799
2890
  `${column.id}-${link.id}`
2800
2891
  ))
2801
2892
  ),
2802
- copyrightText && /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: copyrightText })
2893
+ copyrightText && /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: copyrightText }),
2894
+ colorModeControl
2803
2895
  ] })
2804
2896
  ] }) : layout === "centered" ? /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col items-center gap-6 text-center", children: [
2805
2897
  /* @__PURE__ */ jsxs("div", { className: "flex max-w-sm flex-col items-center gap-3", children: [
2806
- logoText && /* @__PURE__ */ jsx(Header3, { theme: overriddenTheme, children: logoText }),
2898
+ logoText && /* @__PURE__ */ jsx(Header3, { theme: overriddenTheme, as: "p", children: logoText }),
2807
2899
  tagline && /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: tagline })
2808
2900
  ] }),
2809
2901
  /* @__PURE__ */ jsx("div", { className: "flex flex-wrap justify-center gap-x-6 gap-y-2", children: columns.flatMap(
@@ -2812,62 +2904,29 @@ function FooterWidget({
2812
2904
  {
2813
2905
  href: link.href,
2814
2906
  className: "no-underline",
2815
- children: /* @__PURE__ */ jsx(
2816
- Link,
2817
- {
2818
- theme: overriddenTheme,
2819
- className: "text-xs",
2820
- children: link.label
2821
- }
2822
- )
2907
+ children: /* @__PURE__ */ jsx(Link, { theme: overriddenTheme, className: "text-xs", children: link.label })
2823
2908
  },
2824
2909
  `${column.id}-${link.id}`
2825
2910
  ))
2826
2911
  ) })
2827
2912
  ] }) : /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-8 lg:!flex-row lg:justify-between", children: [
2828
2913
  /* @__PURE__ */ jsxs("div", { className: "flex max-w-sm flex-col gap-3", children: [
2829
- logoText && /* @__PURE__ */ jsx(Header3, { theme: overriddenTheme, children: logoText }),
2914
+ logoText && /* @__PURE__ */ jsx(Header3, { theme: overriddenTheme, as: "p", children: logoText }),
2830
2915
  tagline && /* @__PURE__ */ jsx(Text2, { theme: overriddenTheme, children: tagline })
2831
2916
  ] }),
2832
- /* @__PURE__ */ jsx("div", { className: "flex flex-col flex-wrap gap-8 lg:!flex-row", children: columns.map((column) => /* @__PURE__ */ jsxs(
2833
- "div",
2834
- {
2835
- className: "flex flex-col gap-3 lg:min-w-[140px]",
2836
- children: [
2837
- /* @__PURE__ */ jsx(
2838
- Header4,
2839
- {
2840
- theme: overriddenTheme,
2841
- className: "text-sm",
2842
- children: column.title
2843
- }
2844
- ),
2845
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: column.links.map((link) => /* @__PURE__ */ jsx(
2846
- NavLink,
2847
- {
2848
- href: link.href,
2849
- className: "no-underline",
2850
- children: /* @__PURE__ */ jsx(
2851
- Link,
2852
- {
2853
- theme: overriddenTheme,
2854
- className: "text-xs",
2855
- children: link.label
2856
- }
2857
- )
2858
- },
2859
- link.id
2860
- )) })
2861
- ]
2862
- },
2863
- column.id
2864
- )) })
2917
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col flex-wrap gap-8 lg:!flex-row", children: columns.map((column) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 lg:min-w-[140px]", children: [
2918
+ /* @__PURE__ */ jsx(Header4, { theme: overriddenTheme, className: "text-sm", children: column.title }),
2919
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: column.links.map((link) => /* @__PURE__ */ jsx(NavLink, { href: link.href, className: "no-underline", children: /* @__PURE__ */ jsx(Link, { theme: overriddenTheme, className: "text-xs", children: link.label }) }, link.id)) })
2920
+ ] }, column.id)) })
2865
2921
  ] }),
2866
- copyrightText && layout !== "minimal" && /* @__PURE__ */ jsx(
2922
+ (copyrightText || colorModeControl) && layout !== "minimal" && /* @__PURE__ */ jsxs(
2867
2923
  "div",
2868
2924
  {
2869
- className: layout === "centered" ? "mt-8 border-t pt-6 text-center" : "mt-8 border-t pt-6",
2870
- children: /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: copyrightText })
2925
+ className: layout === "centered" ? "mt-8 flex flex-col items-center gap-4 border-t pt-6 text-center" : "mt-8 flex items-center justify-between gap-4 border-t pt-6",
2926
+ children: [
2927
+ copyrightText && /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: copyrightText }),
2928
+ colorModeControl && /* @__PURE__ */ jsx("div", { className: layout === "centered" ? void 0 : "ml-auto", children: colorModeControl })
2929
+ ]
2871
2930
  }
2872
2931
  )
2873
2932
  ]
@@ -2880,25 +2939,16 @@ function FooterEditor({
2880
2939
  }) {
2881
2940
  const update = (partial) => onChange({ ...settings, ...partial });
2882
2941
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
2883
- /* @__PURE__ */ jsxs(FieldGroup, { title: "Brand", children: [
2884
- /* @__PURE__ */ jsx(
2885
- TextField,
2886
- {
2887
- label: "Logo text",
2888
- value: settings.logoText,
2889
- onChange: (logoText) => update({ logoText })
2890
- }
2891
- ),
2892
- /* @__PURE__ */ jsx(
2893
- TextField,
2894
- {
2895
- label: "Tagline",
2896
- value: settings.tagline,
2897
- multiline: true,
2898
- onChange: (tagline) => update({ tagline })
2899
- }
2900
- )
2901
- ] }),
2942
+ /* @__PURE__ */ jsx(FieldGroup, { title: "Brand", children: /* @__PURE__ */ jsx(
2943
+ TextField,
2944
+ {
2945
+ label: "Tagline",
2946
+ value: settings.tagline,
2947
+ multiline: true,
2948
+ hint: "Leave empty to use the subtitle from Branding.",
2949
+ onChange: (tagline) => update({ tagline: tagline || void 0 })
2950
+ }
2951
+ ) }),
2902
2952
  /* @__PURE__ */ jsx(FieldGroup, { title: "Link columns", children: /* @__PURE__ */ jsx(
2903
2953
  ListField,
2904
2954
  {
@@ -2973,21 +3023,30 @@ function FooterEditor({
2973
3023
  ] })
2974
3024
  }
2975
3025
  ) }),
2976
- /* @__PURE__ */ jsx(FieldGroup, { title: "Copyright", children: /* @__PURE__ */ jsx(
2977
- TextField,
2978
- {
2979
- label: "Copyright text",
2980
- value: settings.copyrightText,
2981
- onChange: (copyrightText) => update({ copyrightText })
2982
- }
2983
- ) })
3026
+ /* @__PURE__ */ jsxs(FieldGroup, { title: "Copyright", children: [
3027
+ /* @__PURE__ */ jsx(
3028
+ TextField,
3029
+ {
3030
+ label: "Copyright text",
3031
+ value: settings.copyrightText,
3032
+ onChange: (copyrightText) => update({ copyrightText })
3033
+ }
3034
+ ),
3035
+ /* @__PURE__ */ jsx(
3036
+ ToggleField,
3037
+ {
3038
+ label: "Color mode switcher",
3039
+ value: settings.showThemeSwitcher !== false,
3040
+ onChange: (showThemeSwitcher) => update({ showThemeSwitcher })
3041
+ }
3042
+ )
3043
+ ] })
2984
3044
  ] });
2985
3045
  }
2986
3046
 
2987
3047
  // src/blocks/footer/defaults.ts
2988
3048
  var footerDefaults = {
2989
- logoText: "FrontLit",
2990
- tagline: "Build your website, publish content, support users, and grow your audience from one dashboard.",
3049
+ showThemeSwitcher: true,
2991
3050
  columns: [
2992
3051
  {
2993
3052
  id: generateUniqueId(),
@@ -3054,33 +3113,16 @@ var richTextMetadata = {
3054
3113
  displayName: "Rich text",
3055
3114
  description: "A block of formatted text \u2014 paragraphs, headings, lists and links \u2014 with no title or media.",
3056
3115
  compatibleWith: ["site", "landing", "blog", "post", "custom"]
3057
- };
3058
- function RichTextWidget({
3059
- settings: {
3060
- text,
3061
- alignment = "left",
3062
- cssId,
3063
- maxWidth,
3064
- verticalPadding,
3065
- background
3066
- },
3067
- state: { theme },
3068
- nextTheme
3116
+ };
3117
+ function RichTextWidget({
3118
+ settings: { text, alignment = "left", cssId, maxWidth, verticalPadding, background },
3119
+ state: { theme }
3069
3120
  }) {
3070
3121
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
3071
3122
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
3072
3123
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
3073
3124
  if (!text) return null;
3074
- return /* @__PURE__ */ jsx(
3075
- Section,
3076
- {
3077
- theme: overriddenTheme,
3078
- id: cssId,
3079
- background,
3080
- nextTheme,
3081
- children: /* @__PURE__ */ jsx("div", { style: { textAlign: alignment }, children: /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: text, theme: overriddenTheme }) }) })
3082
- }
3083
- );
3125
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsx("div", { style: { textAlign: alignment }, children: /* @__PURE__ */ jsx(Text1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: text, theme: overriddenTheme }) }) }) });
3084
3126
  }
3085
3127
  function RichTextEditor({
3086
3128
  settings,
@@ -3088,17 +3130,15 @@ function RichTextEditor({
3088
3130
  }) {
3089
3131
  const update = (partial) => onChange({ ...settings, ...partial });
3090
3132
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: /* @__PURE__ */ jsxs(FieldGroup, { title: "Content", children: [
3091
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
3092
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Text" }),
3093
- /* @__PURE__ */ jsx(
3094
- Editor,
3095
- {
3096
- initialContent: settings.text ?? emptyDoc,
3097
- onChange: (text) => update({ text }),
3098
- editorClassName: "min-h-[160px]"
3099
- }
3100
- )
3101
- ] }),
3133
+ /* @__PURE__ */ jsx(
3134
+ RichTextField,
3135
+ {
3136
+ label: "Text",
3137
+ value: settings.text,
3138
+ onChange: (text) => update({ text }),
3139
+ minHeight: 160
3140
+ }
3141
+ ),
3102
3142
  /* @__PURE__ */ jsx(
3103
3143
  SelectField,
3104
3144
  {
@@ -3155,7 +3195,9 @@ function resolveIcon2(name) {
3155
3195
  }
3156
3196
  function GridItemCard({ item, theme }) {
3157
3197
  const Icon = resolveIcon2(item.icon);
3158
- const hasMedia = Boolean(item.media?.file);
3198
+ const mediaUrl = getMediaUrl(item.media);
3199
+ const mediaAlt = getMediaAlt(item.media);
3200
+ const hasMedia = Boolean(mediaUrl);
3159
3201
  const isOverlay = item.mediaAlignment === "overlay";
3160
3202
  const mediaFirst = item.mediaAlignment !== "bottom";
3161
3203
  if (isOverlay) {
@@ -3163,8 +3205,8 @@ function GridItemCard({ item, theme }) {
3163
3205
  hasMedia && /* @__PURE__ */ jsx(
3164
3206
  Image,
3165
3207
  {
3166
- src: item.media?.file || "",
3167
- alt: item.media?.caption || "",
3208
+ src: mediaUrl || "",
3209
+ alt: mediaAlt,
3168
3210
  className: "absolute inset-0",
3169
3211
  width: "w-full",
3170
3212
  height: "h-full",
@@ -3177,36 +3219,25 @@ function GridItemCard({ item, theme }) {
3177
3219
  ] }) });
3178
3220
  return item.buttonAction ? /* @__PURE__ */ jsx(NavLink, { href: item.buttonAction, className: "block", children: card }) : card;
3179
3221
  }
3180
- const media = hasMedia ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-md", children: /* @__PURE__ */ jsx(
3181
- Image,
3182
- {
3183
- src: item.media?.file || "",
3184
- alt: item.media?.caption || ""
3185
- }
3186
- ) }) : Icon ? /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-md bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" }) }) : null;
3222
+ const media = hasMedia ? /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-md", children: /* @__PURE__ */ jsx(Image, { src: mediaUrl || "", alt: mediaAlt }) }) : Icon ? /* @__PURE__ */ jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-md bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" }) }) : null;
3187
3223
  const text = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
3188
3224
  /* @__PURE__ */ jsx(Header4, { theme, children: item.title }),
3189
3225
  item.description && /* @__PURE__ */ jsx(Text2, { theme, children: item.description }),
3190
3226
  item.buttonAction && item.buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: item.buttonAction, className: "mt-2", children: /* @__PURE__ */ jsx(Button2, { theme, variant: "secondary", size: "sm", children: item.buttonCaption }) })
3191
3227
  ] });
3192
- return /* @__PURE__ */ jsx(PageCard, { theme, children: /* @__PURE__ */ jsx(
3193
- PageCardContent,
3194
- {
3195
- theme,
3196
- className: "flex h-full flex-col gap-3",
3197
- children: mediaFirst ? /* @__PURE__ */ jsxs(Fragment, { children: [
3198
- media,
3199
- text
3200
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3201
- text,
3202
- media
3203
- ] })
3204
- }
3205
- ) });
3228
+ return /* @__PURE__ */ jsx(PageCard, { theme, children: /* @__PURE__ */ jsx(PageCardContent, { theme, className: "flex h-full flex-col gap-3", children: mediaFirst ? /* @__PURE__ */ jsxs(Fragment, { children: [
3229
+ media,
3230
+ text
3231
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3232
+ text,
3233
+ media
3234
+ ] }) }) });
3206
3235
  }
3207
3236
  function GridWidget({
3208
3237
  settings: {
3209
3238
  title,
3239
+ titleLevel,
3240
+ titleSize,
3210
3241
  description,
3211
3242
  headerAlignment = "center",
3212
3243
  buttonCaption,
@@ -3218,65 +3249,39 @@ function GridWidget({
3218
3249
  verticalPadding,
3219
3250
  background
3220
3251
  },
3221
- state: { theme },
3222
- nextTheme
3252
+ state: { theme }
3223
3253
  }) {
3224
3254
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
3225
3255
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
3226
3256
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
3227
- return /* @__PURE__ */ jsx(
3228
- Section,
3229
- {
3230
- theme: overriddenTheme,
3231
- id: cssId,
3232
- background,
3233
- nextTheme,
3234
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
3235
- /* @__PURE__ */ jsxs(
3236
- "div",
3237
- {
3238
- className: clsx3(
3239
- "flex flex-col gap-4",
3240
- headerAlignment === "center" ? "items-center text-center" : "items-start"
3241
- ),
3242
- children: [
3243
- /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, children: title }),
3244
- description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(
3245
- TextRenderer,
3246
- {
3247
- json: description,
3248
- theme: overriddenTheme
3249
- }
3250
- ) }),
3251
- buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, className: "mt-2", children: /* @__PURE__ */ jsx(Button2, { theme: overriddenTheme, children: buttonCaption }) })
3252
- ]
3253
- }
3257
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
3258
+ /* @__PURE__ */ jsxs(
3259
+ "div",
3260
+ {
3261
+ className: clsx3(
3262
+ "flex flex-col gap-4",
3263
+ headerAlignment === "center" ? "items-center text-center" : "items-start"
3254
3264
  ),
3255
- items && items.length > 0 && /* @__PURE__ */ jsx(
3256
- "div",
3257
- {
3258
- className: clsx3(
3259
- "grid grid-cols-1 md:grid-cols-2 gap-6 items-stretch",
3260
- columns === 3 ? "lg:grid-cols-3" : "lg:grid-cols-2"
3261
- ),
3262
- children: items.map((item, index) => /* @__PURE__ */ jsx(
3263
- GridItemCard,
3264
- {
3265
- item,
3266
- theme: overriddenTheme
3267
- },
3268
- index
3269
- ))
3270
- }
3271
- )
3272
- ] })
3273
- }
3274
- );
3265
+ children: [
3266
+ /* @__PURE__ */ jsx(Header1, { theme: overriddenTheme, ...titleProps({ titleLevel, titleSize }), children: renderTitle(title, overriddenTheme) }),
3267
+ description && /* @__PURE__ */ jsx(Subheader1, { theme: overriddenTheme, component: "span", children: /* @__PURE__ */ jsx(TextRenderer, { json: description, theme: overriddenTheme }) }),
3268
+ buttonAction && buttonCaption && /* @__PURE__ */ jsx(NavLink, { href: buttonAction, className: "mt-2", children: /* @__PURE__ */ jsx(Button2, { theme: overriddenTheme, children: buttonCaption }) })
3269
+ ]
3270
+ }
3271
+ ),
3272
+ items && items.length > 0 && /* @__PURE__ */ jsx(
3273
+ "div",
3274
+ {
3275
+ className: clsx3(
3276
+ "grid grid-cols-1 md:grid-cols-2 gap-6 items-stretch",
3277
+ columns === 3 ? "lg:grid-cols-3" : "lg:grid-cols-2"
3278
+ ),
3279
+ children: items.map((item, index) => /* @__PURE__ */ jsx(GridItemCard, { item, theme: overriddenTheme }, index))
3280
+ }
3281
+ )
3282
+ ] }) });
3275
3283
  }
3276
- function GridEditor({
3277
- settings,
3278
- onChange
3279
- }) {
3284
+ function GridEditor({ settings, onChange }) {
3280
3285
  const update = (partial) => onChange({ ...settings, ...partial });
3281
3286
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
3282
3287
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Header", children: [
@@ -3284,21 +3289,21 @@ function GridEditor({
3284
3289
  TextField,
3285
3290
  {
3286
3291
  label: "Title",
3292
+ hint: "Wrap words in *asterisks* to highlight them.",
3287
3293
  value: settings.title,
3288
3294
  onChange: (title) => update({ title })
3289
3295
  }
3290
3296
  ),
3291
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-sm", children: [
3292
- /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: "Description" }),
3293
- /* @__PURE__ */ jsx(
3294
- Editor,
3295
- {
3296
- initialContent: settings.description ?? emptyDoc,
3297
- onChange: (description) => update({ description }),
3298
- editorClassName: "min-h-[100px]"
3299
- }
3300
- )
3301
- ] }),
3297
+ /* @__PURE__ */ jsx(TitleLevelField, { settings, onChange: update }),
3298
+ /* @__PURE__ */ jsx(
3299
+ RichTextField,
3300
+ {
3301
+ label: "Description",
3302
+ value: settings.description,
3303
+ onChange: (description) => update({ description }),
3304
+ minHeight: 100
3305
+ }
3306
+ ),
3302
3307
  /* @__PURE__ */ jsx(
3303
3308
  SelectField,
3304
3309
  {
@@ -3381,14 +3386,11 @@ function GridEditor({
3381
3386
  }
3382
3387
  ),
3383
3388
  /* @__PURE__ */ jsx(
3384
- TextField,
3389
+ ImageField,
3385
3390
  {
3386
- label: "Image URL (overrides icon)",
3387
- value: item.media?.file,
3388
- placeholder: "https://...",
3389
- onChange: (file) => updateItem({
3390
- media: file ? { mediaId: file, file } : void 0
3391
- })
3391
+ label: "Image (overrides icon)",
3392
+ value: item.media,
3393
+ onChange: (media) => updateItem({ media })
3392
3394
  }
3393
3395
  ),
3394
3396
  /* @__PURE__ */ jsx(
@@ -3478,6 +3480,7 @@ var Grid = {
3478
3480
  metadata: gridMetadata,
3479
3481
  widget: GridWidget,
3480
3482
  editor: GridEditor,
3483
+ titleSize: true,
3481
3484
  getDefaultSettings: () => gridDefaults
3482
3485
  };
3483
3486
 
@@ -3513,68 +3516,52 @@ function MediaWidget({
3513
3516
  verticalPadding,
3514
3517
  background
3515
3518
  },
3516
- state: { theme },
3517
- nextTheme
3519
+ state: { theme }
3518
3520
  }) {
3519
3521
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
3520
3522
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
3521
3523
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
3522
3524
  const isVideoContent = isVideo(youtubeLink, media);
3523
- return /* @__PURE__ */ jsx(
3524
- Section,
3525
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsx(
3526
+ "div",
3525
3527
  {
3526
- theme: overriddenTheme,
3527
- id: cssId,
3528
- background,
3529
- nextTheme,
3530
- children: /* @__PURE__ */ jsx(
3531
- "div",
3528
+ className: cn(
3529
+ "overflow-hidden",
3530
+ roundedMap3[mediaRadius] ?? "rounded",
3531
+ hasBorder && (overriddenTheme.interactives?.card?.border?.width || "border")
3532
+ ),
3533
+ children: isVideoContent ? /* @__PURE__ */ jsx(
3534
+ VideoWithPreview,
3532
3535
  {
3533
- className: cn(
3534
- "overflow-hidden",
3535
- roundedMap3[mediaRadius] ?? "rounded",
3536
- hasBorder && (overriddenTheme.interactives?.card?.border?.width || "border")
3537
- ),
3538
- children: isVideoContent ? /* @__PURE__ */ jsx(
3539
- VideoWithPreview,
3540
- {
3541
- videoUrl: youtubeLink || media?.file || "",
3542
- title: media?.caption || "",
3543
- thumbnailUrl: media?.thumbnail || "",
3544
- aspectRatio,
3545
- modal: playVideoInModal
3546
- }
3547
- ) : /* @__PURE__ */ jsx(
3548
- Image,
3549
- {
3550
- src: media?.file || "",
3551
- alt: media?.caption || "",
3552
- objectFit,
3553
- borderRadius: mediaRadius
3554
- }
3555
- )
3536
+ videoUrl: youtubeLink || getMediaUrl(media) || "",
3537
+ title: getMediaAlt(media) || media?.caption || "",
3538
+ thumbnailUrl: media?.thumbnail || media?.thumbnailUrl || "",
3539
+ aspectRatio,
3540
+ modal: playVideoInModal
3541
+ }
3542
+ ) : /* @__PURE__ */ jsx(
3543
+ Image,
3544
+ {
3545
+ src: getMediaUrl(media) || "",
3546
+ alt: getMediaAlt(media),
3547
+ objectFit,
3548
+ borderRadius: mediaRadius
3556
3549
  }
3557
3550
  )
3558
3551
  }
3559
- );
3552
+ ) });
3560
3553
  }
3561
- function MediaEditor({
3562
- settings,
3563
- onChange
3564
- }) {
3554
+ function MediaEditor({ settings, onChange }) {
3565
3555
  const update = (partial) => onChange({ ...settings, ...partial });
3566
3556
  const isVideoContent = isVideo(settings.youtubeLink, settings.media);
3567
3557
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
3568
3558
  /* @__PURE__ */ jsxs(FieldGroup, { title: "Media", children: [
3569
3559
  /* @__PURE__ */ jsx(
3570
- TextField,
3560
+ ImageField,
3571
3561
  {
3572
- label: "Image URL",
3573
- value: settings.media?.file,
3574
- placeholder: "https://...",
3575
- onChange: (file) => update({
3576
- media: file ? { mediaId: file, file } : void 0
3577
- })
3562
+ label: "Image / poster",
3563
+ value: settings.media,
3564
+ onChange: (media) => update({ media })
3578
3565
  }
3579
3566
  ),
3580
3567
  /* @__PURE__ */ jsx(
@@ -3742,8 +3729,7 @@ function MarqueeWidget({
3742
3729
  verticalPadding,
3743
3730
  background
3744
3731
  },
3745
- state: { theme },
3746
- nextTheme
3732
+ state: { theme }
3747
3733
  }) {
3748
3734
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
3749
3735
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
@@ -3767,50 +3753,33 @@ function MarqueeWidget({
3767
3753
  children: Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-8 w-8" }) : /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap text-sm font-medium", children: item.text })
3768
3754
  }
3769
3755
  );
3770
- return item.href ? /* @__PURE__ */ jsx(NavLink, { href: item.href, openInSameTab: false, children: content }, item.id) : /* @__PURE__ */ jsx(React7.Fragment, { children: content }, item.id);
3756
+ return item.href ? /* @__PURE__ */ jsx(NavLink, { href: item.href, openInSameTab: false, children: content }, item.id) : /* @__PURE__ */ jsx(React2.Fragment, { children: content }, item.id);
3771
3757
  };
3772
- return /* @__PURE__ */ jsx(
3773
- Section,
3774
- {
3775
- theme: overriddenTheme,
3776
- id: cssId,
3777
- background,
3778
- nextTheme,
3779
- children: /* @__PURE__ */ jsxs("div", { className: "relative", "aria-hidden": "true", children: [
3780
- /* @__PURE__ */ jsx(
3781
- MarqueeTrack,
3782
- {
3783
- speed,
3784
- direction,
3785
- pauseOnHover,
3786
- children: items.map(renderItem)
3758
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "relative", "aria-hidden": "true", children: [
3759
+ /* @__PURE__ */ jsx(MarqueeTrack, { speed, direction, pauseOnHover, children: items.map(renderItem) }),
3760
+ fadeWidth > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
3761
+ /* @__PURE__ */ jsx(
3762
+ "div",
3763
+ {
3764
+ className: "pointer-events-none absolute inset-y-0 left-0 z-10",
3765
+ style: {
3766
+ width: fadeWidth,
3767
+ background: "linear-gradient(to right, var(--background), transparent)"
3787
3768
  }
3788
- ),
3789
- fadeWidth > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
3790
- /* @__PURE__ */ jsx(
3791
- "div",
3792
- {
3793
- className: "pointer-events-none absolute inset-y-0 left-0 z-10",
3794
- style: {
3795
- width: fadeWidth,
3796
- background: "linear-gradient(to right, var(--background), transparent)"
3797
- }
3798
- }
3799
- ),
3800
- /* @__PURE__ */ jsx(
3801
- "div",
3802
- {
3803
- className: "pointer-events-none absolute inset-y-0 right-0 z-10",
3804
- style: {
3805
- width: fadeWidth,
3806
- background: "linear-gradient(to left, var(--background), transparent)"
3807
- }
3808
- }
3809
- )
3810
- ] })
3811
- ] })
3812
- }
3813
- );
3769
+ }
3770
+ ),
3771
+ /* @__PURE__ */ jsx(
3772
+ "div",
3773
+ {
3774
+ className: "pointer-events-none absolute inset-y-0 right-0 z-10",
3775
+ style: {
3776
+ width: fadeWidth,
3777
+ background: "linear-gradient(to left, var(--background), transparent)"
3778
+ }
3779
+ }
3780
+ )
3781
+ ] })
3782
+ ] }) });
3814
3783
  }
3815
3784
  function MarqueeEditor({
3816
3785
  settings,
@@ -4029,59 +3998,40 @@ function EmbedWidget({
4029
3998
  background
4030
3999
  },
4031
4000
  state: { theme },
4032
- editing,
4033
- nextTheme
4001
+ editing
4034
4002
  }) {
4035
4003
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
4036
4004
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
4037
4005
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
4038
4006
  if (!content) {
4039
4007
  if (!editing) return null;
4040
- return /* @__PURE__ */ jsx(
4041
- Section,
4042
- {
4043
- theme: overriddenTheme,
4044
- id: cssId,
4045
- background,
4046
- nextTheme,
4047
- children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-48 flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-muted/30 px-6 py-12 text-center", children: [
4048
- /* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-muted-foreground", children: /* @__PURE__ */ jsx(Code2, { className: "h-4 w-4" }) }),
4049
- /* @__PURE__ */ jsxs("div", { children: [
4050
- /* @__PURE__ */ jsx("p", { className: "font-semibold text-foreground", children: "Embed external content" }),
4051
- /* @__PURE__ */ jsx("p", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: "Paste an embed URL or script snippet in the block settings." })
4052
- ] })
4053
- ] })
4054
- }
4055
- );
4008
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-48 flex-col items-center justify-center gap-3 rounded-lg border border-dashed border-border bg-muted/30 px-6 py-12 text-center", children: [
4009
+ /* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-muted-foreground", children: /* @__PURE__ */ jsx(Code2, { className: "h-4 w-4" }) }),
4010
+ /* @__PURE__ */ jsxs("div", { children: [
4011
+ /* @__PURE__ */ jsx("p", { className: "font-semibold text-foreground", children: "Embed external content" }),
4012
+ /* @__PURE__ */ jsx("p", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: "Paste an embed URL or script snippet in the block settings." })
4013
+ ] })
4014
+ ] }) });
4056
4015
  }
4057
4016
  const isScript = contentType === "script";
4058
4017
  const ratio = aspectRatio !== "default" ? aspectRatioMap[aspectRatio] : void 0;
4059
- const containerStyle = ratio ? { position: "relative", paddingTop: `${100 / ratio}%` } : !isScript ? { height } : {};
4060
- const iframeStyle = ratio ? { position: "absolute", inset: 0, width: "100%", height: "100%" } : isScript ? { width: "100%", height } : { width: "100%", height: "100%" };
4061
- return /* @__PURE__ */ jsx(
4062
- Section,
4063
- {
4064
- theme: overriddenTheme,
4065
- id: cssId,
4066
- background,
4067
- nextTheme,
4068
- children: /* @__PURE__ */ jsx("div", { style: containerStyle, children: isScript ? /* @__PURE__ */ jsx(SandboxedEmbed, { content, style: iframeStyle }) : /* @__PURE__ */ jsx(
4069
- "iframe",
4070
- {
4071
- src: content,
4072
- style: iframeStyle,
4073
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
4074
- allowFullScreen: true,
4075
- title: "Embedded content"
4076
- }
4077
- ) })
4078
- }
4079
- );
4018
+ const containerStyle = ratio ? { position: "relative", paddingTop: `${100 / ratio}%` } : { position: "relative", height: isScript ? void 0 : height };
4019
+ const fillStyle = ratio ? { position: "absolute", inset: 0, width: "100%", height: "100%" } : { width: "100%", height: "100%" };
4020
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
4021
+ isScript ? /* @__PURE__ */ jsx(InlineEmbed, { content, style: ratio ? fillStyle : void 0 }) : /* @__PURE__ */ jsx(
4022
+ "iframe",
4023
+ {
4024
+ src: content,
4025
+ style: fillStyle,
4026
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
4027
+ allowFullScreen: true,
4028
+ title: "Embedded content"
4029
+ }
4030
+ ),
4031
+ editing && /* @__PURE__ */ jsx("div", { className: "absolute inset-0" })
4032
+ ] }) });
4080
4033
  }
4081
- function EmbedEditor({
4082
- settings,
4083
- onChange
4084
- }) {
4034
+ function EmbedEditor({ settings, onChange }) {
4085
4035
  const update = (partial) => onChange({ ...settings, ...partial });
4086
4036
  const contentType = settings.contentType ?? "url";
4087
4037
  const aspectRatio = settings.aspectRatio ?? "default";
@@ -4127,14 +4077,17 @@ function EmbedEditor({
4127
4077
  value: aspectRatio,
4128
4078
  onChange: (value) => update({ aspectRatio: value }),
4129
4079
  options: [
4130
- { label: "Default (fixed height)", value: "default" },
4080
+ {
4081
+ label: contentType === "url" ? "Default (fixed height)" : "Default (fit content)",
4082
+ value: "default"
4083
+ },
4131
4084
  { label: "Widescreen (16:9)", value: "16:9" },
4132
4085
  { label: "Standard (4:3)", value: "4:3" },
4133
4086
  { label: "Square (1:1)", value: "1:1" }
4134
4087
  ]
4135
4088
  }
4136
4089
  ),
4137
- aspectRatio === "default" && /* @__PURE__ */ jsx(
4090
+ aspectRatio === "default" && contentType === "url" && /* @__PURE__ */ jsx(
4138
4091
  NumberField,
4139
4092
  {
4140
4093
  label: "Height (px)",
@@ -4164,6 +4117,117 @@ var Embed = {
4164
4117
  getDefaultSettings: () => embedDefaults
4165
4118
  };
4166
4119
 
4120
+ // src/blocks/code-snippet/metadata.ts
4121
+ var codeSnippetMetadata = {
4122
+ name: "code-snippet",
4123
+ displayName: "Code snippet",
4124
+ description: "A command or short code sample with a copy button, like an install command.",
4125
+ compatibleWith: ["site", "landing", "blog", "post", "custom"],
4126
+ icon: "SquareTerminal"
4127
+ };
4128
+ function CodeSnippetWidget({
4129
+ settings: {
4130
+ code,
4131
+ showPrompt = true,
4132
+ caption,
4133
+ contentAlignment = "center",
4134
+ cssId,
4135
+ maxWidth,
4136
+ verticalPadding,
4137
+ background
4138
+ },
4139
+ state: { theme }
4140
+ }) {
4141
+ const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
4142
+ overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
4143
+ overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
4144
+ if (!code) return null;
4145
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: /* @__PURE__ */ jsxs(
4146
+ "div",
4147
+ {
4148
+ className: clsx3(
4149
+ "flex w-full max-w-2xl flex-col gap-3",
4150
+ contentAlignment === "center" ? "mx-auto items-center" : "items-start"
4151
+ ),
4152
+ children: [
4153
+ /* @__PURE__ */ jsx(
4154
+ CodeSnippet,
4155
+ {
4156
+ code,
4157
+ prompt: showPrompt ? "$" : void 0,
4158
+ theme: overriddenTheme
4159
+ }
4160
+ ),
4161
+ caption && /* @__PURE__ */ jsx(Caption, { theme: overriddenTheme, children: caption })
4162
+ ]
4163
+ }
4164
+ ) });
4165
+ }
4166
+ function CodeSnippetEditor({
4167
+ settings,
4168
+ onChange
4169
+ }) {
4170
+ const update = (partial) => onChange({ ...settings, ...partial });
4171
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
4172
+ /* @__PURE__ */ jsxs(FieldGroup, { title: "Content", children: [
4173
+ /* @__PURE__ */ jsx(
4174
+ TextField,
4175
+ {
4176
+ label: "Code",
4177
+ value: settings.code,
4178
+ placeholder: "curl -fsSL https://example.com/install.sh | sh",
4179
+ multiline: true,
4180
+ onChange: (code) => update({ code })
4181
+ }
4182
+ ),
4183
+ /* @__PURE__ */ jsx(
4184
+ ToggleField,
4185
+ {
4186
+ label: "Show $ prompt",
4187
+ value: settings.showPrompt ?? true,
4188
+ onChange: (showPrompt) => update({ showPrompt })
4189
+ }
4190
+ ),
4191
+ /* @__PURE__ */ jsx(
4192
+ TextField,
4193
+ {
4194
+ label: "Caption",
4195
+ value: settings.caption,
4196
+ placeholder: "e.g. macOS \xB7 Linux \xB7 Windows",
4197
+ onChange: (caption) => update({ caption })
4198
+ }
4199
+ )
4200
+ ] }),
4201
+ /* @__PURE__ */ jsx(FieldGroup, { title: "Layout", children: /* @__PURE__ */ jsx(
4202
+ SelectField,
4203
+ {
4204
+ label: "Alignment",
4205
+ value: settings.contentAlignment ?? "center",
4206
+ onChange: (contentAlignment) => update({ contentAlignment }),
4207
+ options: [
4208
+ { label: "Left", value: "left" },
4209
+ { label: "Center", value: "center" }
4210
+ ]
4211
+ }
4212
+ ) })
4213
+ ] });
4214
+ }
4215
+
4216
+ // src/blocks/code-snippet/defaults.ts
4217
+ var codeSnippetDefaults = {
4218
+ code: "curl -fsSL https://example.com/install.sh | sh",
4219
+ showPrompt: true,
4220
+ contentAlignment: "center"
4221
+ };
4222
+
4223
+ // src/blocks/code-snippet/index.ts
4224
+ var CodeSnippetBlock = {
4225
+ metadata: codeSnippetMetadata,
4226
+ widget: CodeSnippetWidget,
4227
+ editor: CodeSnippetEditor,
4228
+ getDefaultSettings: () => codeSnippetDefaults
4229
+ };
4230
+
4167
4231
  // src/blocks/data-slot/metadata.ts
4168
4232
  var dataSlotMetadata = {
4169
4233
  name: "data-slot",
@@ -4175,23 +4239,13 @@ function DataSlotWidget({
4175
4239
  data,
4176
4240
  editing,
4177
4241
  settings: { slot, cssId, maxWidth, verticalPadding, background },
4178
- state: { theme },
4179
- nextTheme
4242
+ state: { theme }
4180
4243
  }) {
4181
4244
  const overriddenTheme = JSON.parse(JSON.stringify(theme.theme));
4182
4245
  overriddenTheme.structure.page.width = maxWidth || theme.theme.structure.page.width;
4183
4246
  overriddenTheme.structure.section.padding.y = verticalPadding || theme.theme.structure.section.padding.y;
4184
4247
  if (data !== void 0) {
4185
- return /* @__PURE__ */ jsx(
4186
- Section,
4187
- {
4188
- theme: overriddenTheme,
4189
- id: cssId,
4190
- background,
4191
- nextTheme,
4192
- children: data
4193
- }
4194
- );
4248
+ return /* @__PURE__ */ jsx(Section, { theme: overriddenTheme, id: cssId, background, children: data });
4195
4249
  }
4196
4250
  if (!editing) return null;
4197
4251
  return /* @__PURE__ */ jsx(
@@ -4200,17 +4254,16 @@ function DataSlotWidget({
4200
4254
  theme: overriddenTheme,
4201
4255
  id: cssId,
4202
4256
  background,
4203
- nextTheme,
4204
4257
  className: "border-y border-dashed border-border bg-muted/30",
4205
4258
  children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [
4206
4259
  /* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-muted-foreground", children: /* @__PURE__ */ jsx(LockKeyhole, { className: "h-4 w-4" }) }),
4207
4260
  /* @__PURE__ */ jsxs("div", { children: [
4208
4261
  /* @__PURE__ */ jsx("p", { className: "font-semibold text-foreground", children: "Data slot" }),
4209
4262
  /* @__PURE__ */ jsxs("p", { className: "mt-1 text-sm text-muted-foreground", children: [
4210
- "The embedding application resolves data for",
4211
- " ",
4263
+ "The embedding application resolves data for ",
4212
4264
  String(slot || "this slot"),
4213
- " here."
4265
+ " ",
4266
+ "here."
4214
4267
  ] })
4215
4268
  ] })
4216
4269
  ] })
@@ -4224,6 +4277,6 @@ var DataSlot = {
4224
4277
  widget: DataSlotWidget
4225
4278
  };
4226
4279
 
4227
- export { Banner, Content, DataSlot, EmailForm, Embed, Faq, Featured, FieldGroup, Footer, Grid, Header, Hero, Marquee, MediaBlock, Pricing, RichText, SupportForm, TextField, ToggleField, generateUniqueId };
4228
- //# sourceMappingURL=chunk-7KIX4WAO.js.map
4229
- //# sourceMappingURL=chunk-7KIX4WAO.js.map
4280
+ export { Banner, CodeSnippetBlock, Content, DataSlot, EmailForm2 as EmailForm, Embed, Faq, Featured, FieldGroup, Footer, Grid, Header, Hero, Marquee, MediaBlock, Pricing, RichText, SupportForm2 as SupportForm, TextField, TitleSizeField, ToggleField, generateUniqueId };
4281
+ //# sourceMappingURL=chunk-K4WCLHMS.js.map
4282
+ //# sourceMappingURL=chunk-K4WCLHMS.js.map