@orion-studios/payload-admin-components 0.2.0-beta.0 → 0.2.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js ADDED
@@ -0,0 +1,1165 @@
1
+ 'use client';
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/client.ts
23
+ var client_exports = {};
24
+ __export(client_exports, {
25
+ BlockPicker: () => BlockPicker,
26
+ Dashboard: () => Dashboard,
27
+ EmptyState: () => EmptyState,
28
+ HelpTooltip: () => HelpTooltip,
29
+ Icon: () => Icon,
30
+ Logo: () => Logo,
31
+ SectionTabs: () => SectionTabs,
32
+ StatusBadge: () => StatusBadge,
33
+ ThemeProvider: () => ThemeProvider,
34
+ ThemeSwitcher: () => ThemeSwitcher,
35
+ WelcomeHeader: () => WelcomeHeader,
36
+ useTheme: () => useTheme
37
+ });
38
+ module.exports = __toCommonJS(client_exports);
39
+
40
+ // src/components/Logo.tsx
41
+ var import_jsx_runtime = require("react/jsx-runtime");
42
+ function Logo() {
43
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
44
+ "div",
45
+ {
46
+ style: {
47
+ display: "flex",
48
+ alignItems: "center",
49
+ gap: 10,
50
+ padding: "4px 0",
51
+ textDecoration: "none",
52
+ transition: "opacity 0.2s ease"
53
+ },
54
+ children: [
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
56
+ "div",
57
+ {
58
+ style: {
59
+ width: 32,
60
+ height: 32,
61
+ borderRadius: "var(--admin-radius-sm, 6px)",
62
+ background: "var(--admin-accent, #3b82f6)",
63
+ display: "flex",
64
+ alignItems: "center",
65
+ justifyContent: "center",
66
+ flexShrink: 0
67
+ },
68
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2" }),
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "22", x2: "12", y2: "15.5" }),
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "22 8.5 12 15.5 2 8.5" })
72
+ ] })
73
+ }
74
+ ),
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
76
+ "span",
77
+ {
78
+ style: {
79
+ fontSize: 15,
80
+ fontWeight: 700,
81
+ color: "var(--admin-text, #111827)",
82
+ letterSpacing: "-0.01em"
83
+ },
84
+ children: "Orion CMS"
85
+ }
86
+ )
87
+ ]
88
+ }
89
+ );
90
+ }
91
+
92
+ // src/components/Icon.tsx
93
+ var import_jsx_runtime2 = require("react/jsx-runtime");
94
+ function Icon() {
95
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "32", height: "32", viewBox: "0 0 32 32", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
96
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "32", height: "32", rx: "8", fill: "var(--admin-accent, #3b82f6)" }),
97
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { transform: "translate(4, 4)", children: [
98
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", { points: "12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2", fill: "none", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
99
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", y1: "22", x2: "12", y2: "15.5", stroke: "white", strokeWidth: "1.5" }),
100
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "22 8.5 12 15.5 2 8.5", fill: "none", stroke: "white", strokeWidth: "1.5" })
101
+ ] })
102
+ ] });
103
+ }
104
+
105
+ // src/components/Dashboard.tsx
106
+ var import_react4 = require("react");
107
+
108
+ // src/components/ThemeSwitcher.tsx
109
+ var import_react2 = require("react");
110
+
111
+ // src/hooks/useTheme.ts
112
+ var import_react = require("react");
113
+ var STORAGE_KEY = "orion-admin-theme";
114
+ var DEFAULT_THEME = "light";
115
+ function applyTheme(theme) {
116
+ document.documentElement.setAttribute("data-theme", theme);
117
+ }
118
+ function getCachedTheme() {
119
+ try {
120
+ const stored = localStorage.getItem(STORAGE_KEY);
121
+ if (stored && ["light", "dark", "brand-light", "brand-dark"].includes(stored)) {
122
+ return stored;
123
+ }
124
+ } catch {
125
+ }
126
+ return null;
127
+ }
128
+ function cacheTheme(theme) {
129
+ try {
130
+ localStorage.setItem(STORAGE_KEY, theme);
131
+ } catch {
132
+ }
133
+ }
134
+ function useTheme() {
135
+ const [theme, setThemeState] = (0, import_react.useState)(() => {
136
+ if (typeof window === "undefined") return DEFAULT_THEME;
137
+ return getCachedTheme() || DEFAULT_THEME;
138
+ });
139
+ const [isLoading, setIsLoading] = (0, import_react.useState)(true);
140
+ const debounceRef = (0, import_react.useRef)(null);
141
+ const userIdRef = (0, import_react.useRef)(null);
142
+ (0, import_react.useEffect)(() => {
143
+ const cached = getCachedTheme();
144
+ if (cached) {
145
+ applyTheme(cached);
146
+ setThemeState(cached);
147
+ } else {
148
+ applyTheme(DEFAULT_THEME);
149
+ }
150
+ fetch("/api/users/me", { credentials: "include" }).then((res) => res.json()).then((data) => {
151
+ const user = data?.user || data;
152
+ if (user?.id) {
153
+ userIdRef.current = user.id;
154
+ }
155
+ if (user?.themePreference) {
156
+ const dbTheme = user.themePreference;
157
+ setThemeState(dbTheme);
158
+ applyTheme(dbTheme);
159
+ cacheTheme(dbTheme);
160
+ }
161
+ }).catch(() => {
162
+ }).finally(() => {
163
+ setIsLoading(false);
164
+ });
165
+ }, []);
166
+ const setTheme = (0, import_react.useCallback)((newTheme) => {
167
+ setThemeState(newTheme);
168
+ applyTheme(newTheme);
169
+ cacheTheme(newTheme);
170
+ if (debounceRef.current) {
171
+ clearTimeout(debounceRef.current);
172
+ }
173
+ debounceRef.current = setTimeout(() => {
174
+ const userId = userIdRef.current;
175
+ if (!userId) return;
176
+ fetch(`/api/users/${userId}`, {
177
+ method: "PATCH",
178
+ credentials: "include",
179
+ headers: { "Content-Type": "application/json" },
180
+ body: JSON.stringify({ themePreference: newTheme })
181
+ }).catch(() => {
182
+ });
183
+ }, 300);
184
+ }, []);
185
+ const isDark = theme === "dark" || theme === "brand-dark";
186
+ const isBrand = theme === "brand-light" || theme === "brand-dark";
187
+ const toggleDarkMode = (0, import_react.useCallback)(() => {
188
+ if (isBrand) {
189
+ setTheme(isDark ? "brand-light" : "brand-dark");
190
+ } else {
191
+ setTheme(isDark ? "light" : "dark");
192
+ }
193
+ }, [isDark, isBrand, setTheme]);
194
+ const toggleBrandMode = (0, import_react.useCallback)(() => {
195
+ if (isBrand) {
196
+ setTheme(isDark ? "dark" : "light");
197
+ } else {
198
+ setTheme(isDark ? "brand-dark" : "brand-light");
199
+ }
200
+ }, [isDark, isBrand, setTheme]);
201
+ return {
202
+ theme,
203
+ setTheme,
204
+ isDark,
205
+ isBrand,
206
+ isLoading,
207
+ toggleDarkMode,
208
+ toggleBrandMode
209
+ };
210
+ }
211
+
212
+ // src/components/ThemeSwitcher.tsx
213
+ var import_jsx_runtime3 = require("react/jsx-runtime");
214
+ var iconSize = 16;
215
+ function SunIcon() {
216
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
217
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "5" }),
218
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12", y1: "1", x2: "12", y2: "3" }),
219
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "12", y1: "21", x2: "12", y2: "23" }),
220
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "4.22", y1: "4.22", x2: "5.64", y2: "5.64" }),
221
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "18.36", y1: "18.36", x2: "19.78", y2: "19.78" }),
222
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "1", y1: "12", x2: "3", y2: "12" }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "21", y1: "12", x2: "23", y2: "12" }),
224
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "4.22", y1: "19.78", x2: "5.64", y2: "18.36" }),
225
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "18.36", y1: "5.64", x2: "19.78", y2: "4.22" })
226
+ ] });
227
+ }
228
+ function MoonIcon() {
229
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" }) });
230
+ }
231
+ function PaletteIcon() {
232
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
233
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "13.5", cy: "6.5", r: "0.5", fill: "currentColor" }),
234
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "17.5", cy: "10.5", r: "0.5", fill: "currentColor" }),
235
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8.5", cy: "7.5", r: "0.5", fill: "currentColor" }),
236
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "6.5", cy: "12", r: "0.5", fill: "currentColor" }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" })
238
+ ] });
239
+ }
240
+ var buttonBase = {
241
+ display: "flex",
242
+ alignItems: "center",
243
+ justifyContent: "center",
244
+ width: 32,
245
+ height: 32,
246
+ borderRadius: "var(--admin-radius-sm)",
247
+ border: "1px solid var(--admin-border)",
248
+ background: "var(--admin-surface)",
249
+ color: "var(--admin-text-secondary)",
250
+ cursor: "pointer",
251
+ transition: "all 0.2s ease",
252
+ padding: 0
253
+ };
254
+ var buttonActive = {
255
+ ...buttonBase,
256
+ background: "var(--admin-accent-subtle)",
257
+ borderColor: "var(--admin-accent)",
258
+ color: "var(--admin-accent)"
259
+ };
260
+ function ThemeSwitcher() {
261
+ const { isDark, isBrand, toggleDarkMode, toggleBrandMode } = useTheme();
262
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
263
+ "div",
264
+ {
265
+ style: {
266
+ display: "flex",
267
+ alignItems: "center",
268
+ gap: 6,
269
+ padding: "8px 12px"
270
+ },
271
+ children: [
272
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
273
+ "button",
274
+ {
275
+ type: "button",
276
+ onClick: toggleDarkMode,
277
+ style: isDark ? buttonActive : buttonBase,
278
+ title: isDark ? "Switch to light mode" : "Switch to dark mode",
279
+ "aria-label": isDark ? "Switch to light mode" : "Switch to dark mode",
280
+ children: isDark ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MoonIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SunIcon, {})
281
+ }
282
+ ),
283
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
284
+ "button",
285
+ {
286
+ type: "button",
287
+ onClick: toggleBrandMode,
288
+ style: isBrand ? buttonActive : buttonBase,
289
+ title: isBrand ? "Switch to standard colors" : "Switch to brand colors",
290
+ "aria-label": isBrand ? "Switch to standard colors" : "Switch to brand colors",
291
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaletteIcon, {})
292
+ }
293
+ )
294
+ ]
295
+ }
296
+ );
297
+ }
298
+ function ThemeProvider({ children }) {
299
+ (0, import_react2.useEffect)(() => {
300
+ try {
301
+ const stored = localStorage.getItem("orion-admin-theme");
302
+ if (stored && ["light", "dark", "brand-light", "brand-dark"].includes(stored)) {
303
+ document.documentElement.setAttribute("data-theme", stored);
304
+ } else {
305
+ document.documentElement.setAttribute("data-theme", "light");
306
+ }
307
+ } catch {
308
+ document.documentElement.setAttribute("data-theme", "light");
309
+ }
310
+ }, []);
311
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
312
+ }
313
+
314
+ // src/components/HelpTooltip.tsx
315
+ var import_react3 = require("react");
316
+ var import_jsx_runtime4 = require("react/jsx-runtime");
317
+ function HelpTooltip({
318
+ content,
319
+ position = "top"
320
+ }) {
321
+ const [isVisible, setIsVisible] = (0, import_react3.useState)(false);
322
+ const triggerRef = (0, import_react3.useRef)(null);
323
+ const tooltipRef = (0, import_react3.useRef)(null);
324
+ const tooltipId = (0, import_react3.useRef)(`tooltip-${Math.random().toString(36).slice(2, 9)}`);
325
+ const show = (0, import_react3.useCallback)(() => setIsVisible(true), []);
326
+ const hide = (0, import_react3.useCallback)(() => setIsVisible(false), []);
327
+ const toggle = (0, import_react3.useCallback)(() => setIsVisible((v) => !v), []);
328
+ (0, import_react3.useEffect)(() => {
329
+ if (!isVisible) return;
330
+ const handleKeyDown = (e) => {
331
+ if (e.key === "Escape") setIsVisible(false);
332
+ };
333
+ document.addEventListener("keydown", handleKeyDown);
334
+ return () => document.removeEventListener("keydown", handleKeyDown);
335
+ }, [isVisible]);
336
+ (0, import_react3.useEffect)(() => {
337
+ if (!isVisible) return;
338
+ const handleClick = (e) => {
339
+ if (triggerRef.current && !triggerRef.current.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) {
340
+ setIsVisible(false);
341
+ }
342
+ };
343
+ document.addEventListener("mousedown", handleClick);
344
+ return () => document.removeEventListener("mousedown", handleClick);
345
+ }, [isVisible]);
346
+ const positionStyles = {
347
+ top: { bottom: "100%", left: "50%", transform: "translateX(-50%)", marginBottom: 8 },
348
+ bottom: { top: "100%", left: "50%", transform: "translateX(-50%)", marginTop: 8 },
349
+ left: { right: "100%", top: "50%", transform: "translateY(-50%)", marginRight: 8 },
350
+ right: { left: "100%", top: "50%", transform: "translateY(-50%)", marginLeft: 8 }
351
+ };
352
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { position: "relative", display: "inline-flex", verticalAlign: "middle", marginLeft: 6 }, children: [
353
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
354
+ "button",
355
+ {
356
+ ref: triggerRef,
357
+ type: "button",
358
+ onClick: toggle,
359
+ onMouseEnter: show,
360
+ onMouseLeave: hide,
361
+ onFocus: show,
362
+ onBlur: hide,
363
+ "aria-describedby": isVisible ? tooltipId.current : void 0,
364
+ style: {
365
+ display: "inline-flex",
366
+ alignItems: "center",
367
+ justifyContent: "center",
368
+ width: 18,
369
+ height: 18,
370
+ borderRadius: "50%",
371
+ border: "1.5px solid var(--admin-text-muted)",
372
+ background: "transparent",
373
+ color: "var(--admin-text-muted)",
374
+ fontSize: 11,
375
+ fontWeight: 700,
376
+ cursor: "help",
377
+ padding: 0,
378
+ lineHeight: 1,
379
+ transition: "all 0.15s ease",
380
+ ...isVisible ? {
381
+ borderColor: "var(--admin-accent)",
382
+ color: "var(--admin-accent)",
383
+ background: "var(--admin-accent-subtle)"
384
+ } : {}
385
+ },
386
+ children: "?"
387
+ }
388
+ ),
389
+ isVisible && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
390
+ "div",
391
+ {
392
+ ref: tooltipRef,
393
+ id: tooltipId.current,
394
+ role: "tooltip",
395
+ style: {
396
+ position: "absolute",
397
+ ...positionStyles[position],
398
+ background: "var(--admin-tooltip-bg)",
399
+ color: "var(--admin-tooltip-text)",
400
+ padding: "8px 12px",
401
+ borderRadius: "var(--admin-radius-sm)",
402
+ fontSize: 12,
403
+ lineHeight: 1.5,
404
+ maxWidth: 260,
405
+ minWidth: 160,
406
+ whiteSpace: "normal",
407
+ zIndex: 9999,
408
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
409
+ pointerEvents: "auto",
410
+ animation: "tooltipFadeIn 0.15s ease"
411
+ },
412
+ children: content
413
+ }
414
+ )
415
+ ] });
416
+ }
417
+
418
+ // src/components/StatusBadge.tsx
419
+ var import_jsx_runtime5 = require("react/jsx-runtime");
420
+ var statusConfig = {
421
+ draft: { label: "Draft" },
422
+ published: { label: "Published" },
423
+ changed: { label: "Changed" }
424
+ };
425
+ function StatusBadge({
426
+ status,
427
+ size = "md"
428
+ }) {
429
+ const config = statusConfig[status];
430
+ const isSm = size === "sm";
431
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
432
+ "span",
433
+ {
434
+ style: {
435
+ display: "inline-flex",
436
+ alignItems: "center",
437
+ gap: 4,
438
+ padding: isSm ? "2px 8px" : "3px 10px",
439
+ borderRadius: 20,
440
+ fontSize: isSm ? 11 : 12,
441
+ fontWeight: 600,
442
+ lineHeight: 1.4,
443
+ background: `var(--admin-badge-${status}-bg)`,
444
+ color: `var(--admin-badge-${status}-text)`,
445
+ whiteSpace: "nowrap"
446
+ },
447
+ children: [
448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
449
+ "span",
450
+ {
451
+ style: {
452
+ width: isSm ? 5 : 6,
453
+ height: isSm ? 5 : 6,
454
+ borderRadius: "50%",
455
+ background: "currentColor",
456
+ flexShrink: 0
457
+ }
458
+ }
459
+ ),
460
+ config.label
461
+ ]
462
+ }
463
+ );
464
+ }
465
+
466
+ // src/components/Dashboard.tsx
467
+ var import_jsx_runtime6 = require("react/jsx-runtime");
468
+ function PagesIcon({ size = 24 }) {
469
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
470
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
471
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "14 2 14 8 20 8" }),
472
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
473
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
474
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "10 9 9 9 8 9" })
475
+ ] });
476
+ }
477
+ function MediaIcon({ size = 24 }) {
478
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
479
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
480
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
481
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "21 15 16 10 5 21" })
482
+ ] });
483
+ }
484
+ function SettingsIcon({ size = 24 }) {
485
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
486
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "3" }),
487
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" })
488
+ ] });
489
+ }
490
+ function LayoutIcon({ size = 24 }) {
491
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
492
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
493
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "9", x2: "21", y2: "9" }),
494
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "3", y1: "15", x2: "21", y2: "15" })
495
+ ] });
496
+ }
497
+ function PlusIcon({ size = 16 }) {
498
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
499
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
500
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
501
+ ] });
502
+ }
503
+ function ClockIcon({ size = 14 }) {
504
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
505
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
506
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "12 6 12 12 16 14" })
507
+ ] });
508
+ }
509
+ function getGreeting() {
510
+ const hour = (/* @__PURE__ */ new Date()).getHours();
511
+ if (hour < 12) return "Good morning";
512
+ if (hour < 17) return "Good afternoon";
513
+ return "Good evening";
514
+ }
515
+ function formatRelativeTime(dateStr) {
516
+ const date = new Date(dateStr);
517
+ const now = /* @__PURE__ */ new Date();
518
+ const diffMs = now.getTime() - date.getTime();
519
+ const diffMins = Math.floor(diffMs / 6e4);
520
+ const diffHours = Math.floor(diffMs / 36e5);
521
+ const diffDays = Math.floor(diffMs / 864e5);
522
+ if (diffMins < 1) return "Just now";
523
+ if (diffMins < 60) return `${diffMins}m ago`;
524
+ if (diffHours < 24) return `${diffHours}h ago`;
525
+ if (diffDays < 7) return `${diffDays}d ago`;
526
+ return date.toLocaleDateString();
527
+ }
528
+ function Dashboard() {
529
+ const [userName, setUserName] = (0, import_react4.useState)("");
530
+ const [recentPages, setRecentPages] = (0, import_react4.useState)([]);
531
+ const [pageCount, setPageCount] = (0, import_react4.useState)(null);
532
+ const [mediaCount, setMediaCount] = (0, import_react4.useState)(null);
533
+ (0, import_react4.useEffect)(() => {
534
+ fetch("/api/users/me", { credentials: "include" }).then((res) => res.json()).then((data) => {
535
+ const user = data?.user || data;
536
+ setUserName(user?.fullName || user?.email?.split("@")[0] || "");
537
+ }).catch(() => {
538
+ });
539
+ fetch("/api/pages?limit=5&sort=-updatedAt", { credentials: "include" }).then((res) => res.json()).then((data) => {
540
+ setRecentPages(data?.docs || []);
541
+ setPageCount(data?.totalDocs ?? null);
542
+ }).catch(() => {
543
+ });
544
+ fetch("/api/media?limit=0", { credentials: "include" }).then((res) => res.json()).then((data) => {
545
+ setMediaCount(data?.totalDocs ?? null);
546
+ }).catch(() => {
547
+ });
548
+ }, []);
549
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "32px", maxWidth: 1200, margin: "0 auto" }, children: [
550
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", marginBottom: 32 }, children: [
551
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
552
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h1", { style: { fontSize: 28, fontWeight: 700, color: "var(--admin-text)", margin: "0 0 6px" }, children: [
553
+ getGreeting(),
554
+ userName ? `, ${userName}` : ""
555
+ ] }),
556
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { fontSize: 15, color: "var(--admin-text-muted)", margin: 0 }, children: "Manage your website content and settings from here." })
557
+ ] }),
558
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ThemeSwitcher, {})
559
+ ] }),
560
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: 10, marginBottom: 32, flexWrap: "wrap" }, children: [
561
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuickAction, { href: "/admin/collections/pages/create", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, {}), label: "New Page" }),
562
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuickAction, { href: "/admin/collections/media/create", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon, {}), label: "Upload Media" }),
563
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuickAction, { href: "/admin/globals/header", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LayoutIcon, { size: 16 }), label: "Edit Navigation" }),
564
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuickAction, { href: "/admin/globals/site-settings", icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SettingsIcon, { size: 16 }), label: "Website Settings" })
565
+ ] }),
566
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
567
+ "div",
568
+ {
569
+ style: {
570
+ display: "grid",
571
+ gap: 20,
572
+ gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
573
+ marginBottom: 32
574
+ },
575
+ children: [
576
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
577
+ ContentCard,
578
+ {
579
+ icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PagesIcon, {}),
580
+ title: "Pages",
581
+ description: "Create and manage your website pages",
582
+ count: pageCount,
583
+ countLabel: "pages",
584
+ tooltip: "Pages are the individual sections of your website. Each page has a URL and contains content sections.",
585
+ actions: [
586
+ { label: "View All", href: "/admin/collections/pages" },
587
+ { label: "Create New", href: "/admin/collections/pages/create", primary: true }
588
+ ]
589
+ }
590
+ ),
591
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
592
+ ContentCard,
593
+ {
594
+ icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MediaIcon, {}),
595
+ title: "Media Library",
596
+ description: "Upload and organize images and files",
597
+ count: mediaCount,
598
+ countLabel: "files",
599
+ tooltip: "Your media library stores all images, documents, and files used across your website.",
600
+ actions: [
601
+ { label: "Browse", href: "/admin/collections/media" },
602
+ { label: "Upload", href: "/admin/collections/media/create", primary: true }
603
+ ]
604
+ }
605
+ ),
606
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
607
+ ContentCard,
608
+ {
609
+ icon: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LayoutIcon, {}),
610
+ title: "Site Design",
611
+ description: "Customize your header, footer, and site-wide settings",
612
+ tooltip: "These settings apply to every page on your website \u2014 your navigation menu, footer information, and global SEO settings.",
613
+ actions: [
614
+ { label: "Header & Nav", href: "/admin/globals/header" },
615
+ { label: "Footer", href: "/admin/globals/footer" },
616
+ { label: "Settings", href: "/admin/globals/site-settings", primary: true }
617
+ ]
618
+ }
619
+ )
620
+ ]
621
+ }
622
+ ),
623
+ recentPages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
624
+ "div",
625
+ {
626
+ style: {
627
+ background: "var(--admin-card-bg)",
628
+ border: "1px solid var(--admin-card-border)",
629
+ borderRadius: "var(--admin-radius-lg)",
630
+ overflow: "hidden"
631
+ },
632
+ children: [
633
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
634
+ "div",
635
+ {
636
+ style: {
637
+ padding: "16px 20px",
638
+ borderBottom: "1px solid var(--admin-border-subtle)",
639
+ display: "flex",
640
+ alignItems: "center",
641
+ justifyContent: "space-between"
642
+ },
643
+ children: [
644
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h3", { style: { fontSize: 15, fontWeight: 600, color: "var(--admin-text)", margin: 0, display: "flex", alignItems: "center", gap: 6 }, children: [
645
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ClockIcon, {}),
646
+ " Recently Edited"
647
+ ] }),
648
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
649
+ "a",
650
+ {
651
+ href: "/admin/collections/pages",
652
+ style: { fontSize: 13, color: "var(--admin-accent)", textDecoration: "none", fontWeight: 500 },
653
+ children: "View all"
654
+ }
655
+ )
656
+ ]
657
+ }
658
+ ),
659
+ recentPages.map((page, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
660
+ "a",
661
+ {
662
+ href: `/admin/collections/pages/${page.id}`,
663
+ style: {
664
+ display: "flex",
665
+ alignItems: "center",
666
+ justifyContent: "space-between",
667
+ padding: "12px 20px",
668
+ textDecoration: "none",
669
+ borderBottom: i < recentPages.length - 1 ? "1px solid var(--admin-border-subtle)" : "none",
670
+ transition: "background-color 0.15s ease"
671
+ },
672
+ onMouseEnter: (e) => {
673
+ e.currentTarget.style.backgroundColor = "var(--admin-surface)";
674
+ },
675
+ onMouseLeave: (e) => {
676
+ e.currentTarget.style.backgroundColor = "transparent";
677
+ },
678
+ children: [
679
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12, minWidth: 0 }, children: [
680
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PagesIcon, { size: 16 }),
681
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: 14, fontWeight: 500, color: "var(--admin-text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: page.title || page.slug || "Untitled" })
682
+ ] }),
683
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12, flexShrink: 0 }, children: [
684
+ page._status && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StatusBadge, { status: page._status, size: "sm" }),
685
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { fontSize: 12, color: "var(--admin-text-muted)", whiteSpace: "nowrap" }, children: formatRelativeTime(page.updatedAt) })
686
+ ] })
687
+ ]
688
+ },
689
+ page.id
690
+ ))
691
+ ]
692
+ }
693
+ )
694
+ ] });
695
+ }
696
+ function QuickAction({ href, icon, label }) {
697
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
698
+ "a",
699
+ {
700
+ href,
701
+ style: {
702
+ display: "inline-flex",
703
+ alignItems: "center",
704
+ gap: 6,
705
+ padding: "8px 16px",
706
+ background: "var(--admin-surface)",
707
+ border: "1px solid var(--admin-border)",
708
+ borderRadius: "var(--admin-radius-md)",
709
+ color: "var(--admin-text)",
710
+ textDecoration: "none",
711
+ fontSize: 13,
712
+ fontWeight: 500,
713
+ transition: "all 0.2s ease",
714
+ whiteSpace: "nowrap"
715
+ },
716
+ onMouseEnter: (e) => {
717
+ e.currentTarget.style.borderColor = "var(--admin-accent)";
718
+ e.currentTarget.style.color = "var(--admin-accent)";
719
+ e.currentTarget.style.background = "var(--admin-accent-subtle)";
720
+ },
721
+ onMouseLeave: (e) => {
722
+ e.currentTarget.style.borderColor = "var(--admin-border)";
723
+ e.currentTarget.style.color = "var(--admin-text)";
724
+ e.currentTarget.style.background = "var(--admin-surface)";
725
+ },
726
+ children: [
727
+ icon,
728
+ label
729
+ ]
730
+ }
731
+ );
732
+ }
733
+ function ContentCard({
734
+ icon,
735
+ title,
736
+ description,
737
+ count,
738
+ countLabel,
739
+ tooltip,
740
+ actions
741
+ }) {
742
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
743
+ "div",
744
+ {
745
+ style: {
746
+ background: "var(--admin-card-bg)",
747
+ border: "1px solid var(--admin-card-border)",
748
+ borderRadius: "var(--admin-radius-lg)",
749
+ padding: 24,
750
+ display: "flex",
751
+ flexDirection: "column",
752
+ gap: 16,
753
+ boxShadow: "var(--admin-card-shadow)",
754
+ transition: "all 0.2s ease"
755
+ },
756
+ children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
758
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
759
+ "div",
760
+ {
761
+ style: {
762
+ width: 40,
763
+ height: 40,
764
+ borderRadius: "var(--admin-radius-md)",
765
+ background: "var(--admin-accent-subtle)",
766
+ color: "var(--admin-accent)",
767
+ display: "flex",
768
+ alignItems: "center",
769
+ justifyContent: "center"
770
+ },
771
+ children: icon
772
+ }
773
+ ),
774
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
775
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h3", { style: { fontSize: 16, fontWeight: 600, color: "var(--admin-text)", margin: 0, display: "flex", alignItems: "center" }, children: [
776
+ title,
777
+ tooltip && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HelpTooltip, { content: tooltip, position: "right" })
778
+ ] }),
779
+ count !== void 0 && count !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: { fontSize: 12, color: "var(--admin-text-muted)" }, children: [
780
+ count,
781
+ " ",
782
+ countLabel
783
+ ] })
784
+ ] })
785
+ ] }) }),
786
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { fontSize: 13, color: "var(--admin-text-muted)", margin: 0, lineHeight: 1.5 }, children: description }),
787
+ actions && actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", gap: 8, marginTop: "auto", flexWrap: "wrap" }, children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
788
+ "a",
789
+ {
790
+ href: action.href,
791
+ style: {
792
+ display: "inline-flex",
793
+ alignItems: "center",
794
+ padding: "7px 14px",
795
+ borderRadius: "var(--admin-radius-sm)",
796
+ fontSize: 13,
797
+ fontWeight: 500,
798
+ textDecoration: "none",
799
+ transition: "all 0.15s ease",
800
+ ...action.primary ? {
801
+ background: "var(--admin-accent)",
802
+ color: "var(--admin-text-inverse)"
803
+ } : {
804
+ background: "var(--admin-surface)",
805
+ color: "var(--admin-text-secondary)",
806
+ border: "1px solid var(--admin-border)"
807
+ }
808
+ },
809
+ children: action.label
810
+ },
811
+ action.href
812
+ )) })
813
+ ]
814
+ }
815
+ );
816
+ }
817
+
818
+ // src/components/EmptyState.tsx
819
+ var import_jsx_runtime7 = require("react/jsx-runtime");
820
+ function EmptyState({
821
+ icon,
822
+ title,
823
+ description,
824
+ actionLabel,
825
+ actionHref
826
+ }) {
827
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
828
+ "div",
829
+ {
830
+ style: {
831
+ display: "flex",
832
+ flexDirection: "column",
833
+ alignItems: "center",
834
+ justifyContent: "center",
835
+ padding: "48px 24px",
836
+ textAlign: "center",
837
+ background: "var(--admin-surface)",
838
+ borderRadius: "var(--admin-radius-lg)",
839
+ border: "1px dashed var(--admin-border)"
840
+ },
841
+ children: [
842
+ icon && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
843
+ "div",
844
+ {
845
+ style: {
846
+ marginBottom: 16,
847
+ color: "var(--admin-text-muted)",
848
+ opacity: 0.6
849
+ },
850
+ children: icon
851
+ }
852
+ ),
853
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
854
+ "h3",
855
+ {
856
+ style: {
857
+ fontSize: 18,
858
+ fontWeight: 600,
859
+ color: "var(--admin-text)",
860
+ margin: "0 0 8px"
861
+ },
862
+ children: title
863
+ }
864
+ ),
865
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
866
+ "p",
867
+ {
868
+ style: {
869
+ fontSize: 14,
870
+ color: "var(--admin-text-muted)",
871
+ margin: "0 0 20px",
872
+ maxWidth: 400,
873
+ lineHeight: 1.5
874
+ },
875
+ children: description
876
+ }
877
+ ),
878
+ actionLabel && actionHref && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
879
+ "a",
880
+ {
881
+ href: actionHref,
882
+ style: {
883
+ display: "inline-flex",
884
+ alignItems: "center",
885
+ gap: 6,
886
+ padding: "10px 20px",
887
+ background: "var(--admin-accent)",
888
+ color: "var(--admin-text-inverse)",
889
+ borderRadius: "var(--admin-radius-md)",
890
+ textDecoration: "none",
891
+ fontWeight: 600,
892
+ fontSize: 14,
893
+ transition: "all 0.2s ease"
894
+ },
895
+ children: actionLabel
896
+ }
897
+ )
898
+ ]
899
+ }
900
+ );
901
+ }
902
+
903
+ // src/components/BlockPicker.tsx
904
+ var import_react5 = require("react");
905
+ var import_jsx_runtime8 = require("react/jsx-runtime");
906
+ function BlockPicker({
907
+ blocks,
908
+ onSelect
909
+ }) {
910
+ const [searchQuery, setSearchQuery] = (0, import_react5.useState)("");
911
+ const filtered = blocks.filter(
912
+ (b) => b.label.toLowerCase().includes(searchQuery.toLowerCase()) || b.slug.toLowerCase().includes(searchQuery.toLowerCase()) || b.description && b.description.toLowerCase().includes(searchQuery.toLowerCase())
913
+ );
914
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [
915
+ blocks.length > 4 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
916
+ "input",
917
+ {
918
+ type: "text",
919
+ placeholder: "Search sections...",
920
+ value: searchQuery,
921
+ onChange: (e) => setSearchQuery(e.target.value),
922
+ style: {
923
+ padding: "10px 14px",
924
+ border: "1px solid var(--admin-input-border)",
925
+ borderRadius: "var(--admin-radius-md)",
926
+ background: "var(--admin-input-bg)",
927
+ color: "var(--admin-text)",
928
+ fontSize: 14,
929
+ outline: "none",
930
+ width: "100%",
931
+ boxSizing: "border-box"
932
+ }
933
+ }
934
+ ),
935
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
936
+ "div",
937
+ {
938
+ style: {
939
+ display: "grid",
940
+ gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
941
+ gap: 12
942
+ },
943
+ children: filtered.map((block) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
944
+ "button",
945
+ {
946
+ type: "button",
947
+ onClick: () => onSelect(block.slug),
948
+ style: {
949
+ display: "flex",
950
+ flexDirection: "column",
951
+ alignItems: "center",
952
+ gap: 10,
953
+ padding: 16,
954
+ background: "var(--admin-card-bg)",
955
+ border: "1px solid var(--admin-card-border)",
956
+ borderRadius: "var(--admin-radius-lg)",
957
+ cursor: "pointer",
958
+ transition: "all 0.2s ease",
959
+ textAlign: "center"
960
+ },
961
+ onMouseEnter: (e) => {
962
+ e.currentTarget.style.borderColor = "var(--admin-accent)";
963
+ e.currentTarget.style.boxShadow = "var(--admin-card-shadow-hover)";
964
+ e.currentTarget.style.transform = "translateY(-2px)";
965
+ },
966
+ onMouseLeave: (e) => {
967
+ e.currentTarget.style.borderColor = "var(--admin-card-border)";
968
+ e.currentTarget.style.boxShadow = "none";
969
+ e.currentTarget.style.transform = "translateY(0)";
970
+ },
971
+ children: [
972
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
973
+ "div",
974
+ {
975
+ style: {
976
+ width: 48,
977
+ height: 48,
978
+ borderRadius: "var(--admin-radius-md)",
979
+ background: "var(--admin-accent-subtle)",
980
+ color: "var(--admin-accent)",
981
+ display: "flex",
982
+ alignItems: "center",
983
+ justifyContent: "center",
984
+ fontSize: 24,
985
+ overflow: "hidden"
986
+ },
987
+ children: block.imageURL ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
988
+ "img",
989
+ {
990
+ src: block.imageURL,
991
+ alt: block.label,
992
+ style: { width: "100%", height: "100%", objectFit: "cover" }
993
+ }
994
+ ) : block.icon ? block.icon : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(BlockDefaultIcon, {})
995
+ }
996
+ ),
997
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
998
+ "span",
999
+ {
1000
+ style: {
1001
+ fontSize: 13,
1002
+ fontWeight: 600,
1003
+ color: "var(--admin-text)",
1004
+ lineHeight: 1.3
1005
+ },
1006
+ children: block.label
1007
+ }
1008
+ ),
1009
+ block.description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1010
+ "span",
1011
+ {
1012
+ style: {
1013
+ fontSize: 11,
1014
+ color: "var(--admin-text-muted)",
1015
+ lineHeight: 1.4
1016
+ },
1017
+ children: block.description
1018
+ }
1019
+ )
1020
+ ]
1021
+ },
1022
+ block.slug
1023
+ ))
1024
+ }
1025
+ ),
1026
+ filtered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { textAlign: "center", color: "var(--admin-text-muted)", fontSize: 14, padding: 20 }, children: "No sections match your search." })
1027
+ ] });
1028
+ }
1029
+ function BlockDefaultIcon() {
1030
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
1031
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "3", y: "3", width: "7", height: "7" }),
1032
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "14", y: "3", width: "7", height: "7" }),
1033
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "14", y: "14", width: "7", height: "7" }),
1034
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("rect", { x: "3", y: "14", width: "7", height: "7" })
1035
+ ] });
1036
+ }
1037
+
1038
+ // src/components/SectionTabs.tsx
1039
+ var import_react6 = require("react");
1040
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1041
+ function SectionTabs({
1042
+ tabs,
1043
+ defaultTab = 0
1044
+ }) {
1045
+ const [activeTab, setActiveTab] = (0, import_react6.useState)(defaultTab);
1046
+ if (tabs.length === 0) return null;
1047
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1048
+ "div",
1049
+ {
1050
+ style: {
1051
+ border: "1px solid var(--admin-border)",
1052
+ borderRadius: "var(--admin-radius-lg)",
1053
+ overflow: "hidden",
1054
+ background: "var(--admin-card-bg)"
1055
+ },
1056
+ children: [
1057
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1058
+ "div",
1059
+ {
1060
+ style: {
1061
+ display: "flex",
1062
+ borderBottom: "2px solid var(--admin-border)",
1063
+ background: "var(--admin-surface)",
1064
+ overflowX: "auto",
1065
+ scrollbarWidth: "none"
1066
+ },
1067
+ children: tabs.map((tab, index) => {
1068
+ const isActive = index === activeTab;
1069
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1070
+ "button",
1071
+ {
1072
+ type: "button",
1073
+ onClick: () => setActiveTab(index),
1074
+ style: {
1075
+ display: "flex",
1076
+ alignItems: "center",
1077
+ gap: 6,
1078
+ padding: "12px 18px",
1079
+ border: "none",
1080
+ borderBottom: isActive ? "2px solid var(--admin-accent)" : "2px solid transparent",
1081
+ marginBottom: -2,
1082
+ background: "transparent",
1083
+ color: isActive ? "var(--admin-accent)" : "var(--admin-text-muted)",
1084
+ fontWeight: isActive ? 600 : 500,
1085
+ fontSize: 13,
1086
+ cursor: "pointer",
1087
+ transition: "all 0.15s ease",
1088
+ whiteSpace: "nowrap"
1089
+ },
1090
+ children: [
1091
+ tab.icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { display: "flex", opacity: isActive ? 1 : 0.6 }, children: tab.icon }),
1092
+ tab.label
1093
+ ]
1094
+ },
1095
+ index
1096
+ );
1097
+ })
1098
+ }
1099
+ ),
1100
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { padding: 20 }, children: tabs[activeTab]?.content })
1101
+ ]
1102
+ }
1103
+ );
1104
+ }
1105
+
1106
+ // src/components/WelcomeHeader.tsx
1107
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1108
+ function WelcomeHeader({
1109
+ title,
1110
+ description,
1111
+ tooltip,
1112
+ actions
1113
+ }) {
1114
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1115
+ "div",
1116
+ {
1117
+ style: {
1118
+ display: "flex",
1119
+ alignItems: "flex-start",
1120
+ justifyContent: "space-between",
1121
+ padding: "24px 0",
1122
+ borderBottom: "1px solid var(--admin-border-subtle)",
1123
+ marginBottom: 24
1124
+ },
1125
+ children: [
1126
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1127
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1128
+ "h1",
1129
+ {
1130
+ style: {
1131
+ fontSize: 24,
1132
+ fontWeight: 700,
1133
+ color: "var(--admin-text)",
1134
+ margin: 0,
1135
+ display: "flex",
1136
+ alignItems: "center"
1137
+ },
1138
+ children: [
1139
+ title,
1140
+ tooltip && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(HelpTooltip, { content: tooltip, position: "right" })
1141
+ ]
1142
+ }
1143
+ ),
1144
+ description && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { fontSize: 14, color: "var(--admin-text-muted)", margin: "6px 0 0" }, children: description })
1145
+ ] }),
1146
+ actions && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", gap: 8 }, children: actions })
1147
+ ]
1148
+ }
1149
+ );
1150
+ }
1151
+ // Annotate the CommonJS export names for ESM import in node:
1152
+ 0 && (module.exports = {
1153
+ BlockPicker,
1154
+ Dashboard,
1155
+ EmptyState,
1156
+ HelpTooltip,
1157
+ Icon,
1158
+ Logo,
1159
+ SectionTabs,
1160
+ StatusBadge,
1161
+ ThemeProvider,
1162
+ ThemeSwitcher,
1163
+ WelcomeHeader,
1164
+ useTheme
1165
+ });