@jimmy_harika/websitekit 0.5.3 → 0.5.5
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/package.json +1 -1
- package/src/editor/BlockLibrary.tsx +82 -54
- package/src/editor/Canvas.tsx +1 -1
- package/src/editor/EditorDock.tsx +107 -0
- package/src/editor/InsertPoint.tsx +3 -3
- package/src/editor/Inspector.tsx +39 -21
- package/src/editor/PageBuilder.tsx +238 -276
- package/src/editor/SectionFrame.tsx +6 -6
- package/src/editor/SectionsPanel.tsx +22 -8
- package/src/editor/ThemePanel.tsx +1 -1
- package/src/editor/Toolbar.tsx +33 -82
- package/src/editor/edit-primitives.tsx +6 -6
- package/src/editor/index.tsx +7 -1
|
@@ -14,21 +14,35 @@ import { useEditorUi } from "./ui-context";
|
|
|
14
14
|
import { useDraggable, useDropTarget } from "./dnd";
|
|
15
15
|
import { cn } from "../lib/cn";
|
|
16
16
|
|
|
17
|
-
export function SectionsPanel({
|
|
17
|
+
export function SectionsPanel({
|
|
18
|
+
catalog,
|
|
19
|
+
embedded,
|
|
20
|
+
}: {
|
|
21
|
+
catalog: Catalog;
|
|
22
|
+
/** Dock owns the title — only show the Add control. */
|
|
23
|
+
embedded?: boolean;
|
|
24
|
+
}) {
|
|
18
25
|
const sections = useBuilder((s) => s.doc.sections);
|
|
19
26
|
const ui = useEditorUi();
|
|
20
27
|
|
|
21
28
|
return (
|
|
22
29
|
<div className="flex h-full min-h-0 flex-col">
|
|
23
|
-
<div
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
<div
|
|
31
|
+
className={cn(
|
|
32
|
+
"flex items-center border-b border-border px-3 py-2.5",
|
|
33
|
+
embedded ? "justify-end" : "justify-between",
|
|
34
|
+
)}
|
|
35
|
+
>
|
|
36
|
+
{!embedded && (
|
|
37
|
+
<span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
38
|
+
Sections
|
|
39
|
+
</span>
|
|
40
|
+
)}
|
|
27
41
|
<button
|
|
28
42
|
onClick={() => ui.openLibrary(sections.length)}
|
|
29
|
-
className="flex items-center gap-1 rounded-md bg-
|
|
43
|
+
className="flex items-center gap-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground transition hover:opacity-90"
|
|
30
44
|
>
|
|
31
|
-
<Plus className="size-3.5" /> Add
|
|
45
|
+
<Plus className="size-3.5" /> Add block
|
|
32
46
|
</button>
|
|
33
47
|
</div>
|
|
34
48
|
<div className="min-h-0 flex-1 overflow-auto p-2">
|
|
@@ -139,7 +153,7 @@ function SectionRow({
|
|
|
139
153
|
<button
|
|
140
154
|
title="Delete section"
|
|
141
155
|
onClick={stop(() => remove(id))}
|
|
142
|
-
className="rounded p-0.5 text-muted-foreground hover:text-
|
|
156
|
+
className="rounded p-0.5 text-muted-foreground hover:text-destructive"
|
|
143
157
|
>
|
|
144
158
|
<Trash2 className="size-3.5" />
|
|
145
159
|
</button>
|
|
@@ -53,7 +53,7 @@ export function ThemePanel() {
|
|
|
53
53
|
{[p.colors.bg, p.colors.text, p.colors.accent].map((c, i) => (
|
|
54
54
|
<span
|
|
55
55
|
key={i}
|
|
56
|
-
className="size-4 rounded-full border border-
|
|
56
|
+
className="size-4 rounded-full border border-border"
|
|
57
57
|
style={{ background: c }}
|
|
58
58
|
/>
|
|
59
59
|
))}
|
package/src/editor/Toolbar.tsx
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/** Clean editor header: leading · devices · undo · preview · publish. */
|
|
4
4
|
import type { ReactNode } from "react";
|
|
5
5
|
import {
|
|
6
6
|
ExternalLink,
|
|
7
|
-
LayoutGrid,
|
|
8
|
-
List,
|
|
9
7
|
Monitor,
|
|
10
|
-
|
|
11
|
-
PanelRight,
|
|
8
|
+
Plus,
|
|
12
9
|
Redo2,
|
|
13
10
|
Smartphone,
|
|
14
11
|
Tablet,
|
|
@@ -27,30 +24,29 @@ const DEVICES: { id: Device; icon: typeof Monitor; label: string }[] = [
|
|
|
27
24
|
export function Toolbar({
|
|
28
25
|
onPublish,
|
|
29
26
|
saving = "idle",
|
|
30
|
-
designOpen,
|
|
31
|
-
onToggleDesign,
|
|
32
|
-
hasTemplates,
|
|
27
|
+
designOpen: _designOpen,
|
|
28
|
+
onToggleDesign: _onToggleDesign,
|
|
29
|
+
hasTemplates: _hasTemplates,
|
|
33
30
|
leading,
|
|
34
31
|
viewUrl,
|
|
35
32
|
floating,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
sectionsOpen,
|
|
39
|
-
onToggleSections,
|
|
33
|
+
compact,
|
|
34
|
+
onAddBlock,
|
|
40
35
|
}: {
|
|
41
36
|
onPublish?: () => void;
|
|
42
37
|
saving?: "idle" | "saving" | "saved";
|
|
43
|
-
designOpen
|
|
44
|
-
onToggleDesign
|
|
38
|
+
designOpen?: boolean;
|
|
39
|
+
onToggleDesign?: () => void;
|
|
45
40
|
hasTemplates?: boolean;
|
|
46
41
|
leading?: ReactNode;
|
|
47
42
|
viewUrl?: string;
|
|
48
43
|
floating?: boolean;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
sectionsOpen?: boolean;
|
|
52
|
-
onToggleSections?: () => void;
|
|
44
|
+
compact?: boolean;
|
|
45
|
+
onAddBlock?: () => void;
|
|
53
46
|
}) {
|
|
47
|
+
void _designOpen;
|
|
48
|
+
void _onToggleDesign;
|
|
49
|
+
void _hasTemplates;
|
|
54
50
|
const ui = useEditorUi();
|
|
55
51
|
const undo = useTemporal((s) => s.undo);
|
|
56
52
|
const redo = useTemporal((s) => s.redo);
|
|
@@ -60,45 +56,18 @@ export function Toolbar({
|
|
|
60
56
|
return (
|
|
61
57
|
<header
|
|
62
58
|
className={cn(
|
|
63
|
-
"relative z-40 flex h-12 shrink-0 items-center gap-
|
|
59
|
+
"relative z-40 flex h-12 shrink-0 items-center gap-2 px-2 text-foreground sm:px-3",
|
|
64
60
|
floating
|
|
65
61
|
? "border-b border-border/40 bg-card/50 backdrop-blur-xl"
|
|
66
62
|
: "border-b border-border bg-card",
|
|
67
63
|
)}
|
|
68
64
|
>
|
|
69
65
|
{leading && (
|
|
70
|
-
<div className="flex min-w-0 items-center gap-1.5
|
|
66
|
+
<div className="flex min-w-0 flex-1 items-center gap-1.5 overflow-hidden">
|
|
71
67
|
{leading}
|
|
72
68
|
</div>
|
|
73
69
|
)}
|
|
74
|
-
<div className="flex
|
|
75
|
-
{floating && onToggleSections && (
|
|
76
|
-
<ToolButton active={!!sectionsOpen} onClick={onToggleSections} title="Sections">
|
|
77
|
-
<List className="size-4" />
|
|
78
|
-
<span className="hidden text-xs lg:inline">Sections</span>
|
|
79
|
-
</ToolButton>
|
|
80
|
-
)}
|
|
81
|
-
<ToolButton active={designOpen} onClick={onToggleDesign} title="Design">
|
|
82
|
-
<Palette className="size-4" />
|
|
83
|
-
<span className="hidden text-xs lg:inline">Design</span>
|
|
84
|
-
</ToolButton>
|
|
85
|
-
{hasTemplates && (
|
|
86
|
-
<ToolButton onClick={() => ui.setTemplatesOpen(true)} title="Templates">
|
|
87
|
-
<LayoutGrid className="size-4" />
|
|
88
|
-
<span className="hidden text-xs lg:inline">Templates</span>
|
|
89
|
-
</ToolButton>
|
|
90
|
-
)}
|
|
91
|
-
{floating && onToggleInspector && (
|
|
92
|
-
<ToolButton
|
|
93
|
-
active={!!inspectorOpen}
|
|
94
|
-
onClick={onToggleInspector}
|
|
95
|
-
title="Inspector"
|
|
96
|
-
>
|
|
97
|
-
<PanelRight className="size-4" />
|
|
98
|
-
<span className="hidden text-xs lg:inline">Inspect</span>
|
|
99
|
-
</ToolButton>
|
|
100
|
-
)}
|
|
101
|
-
</div>
|
|
70
|
+
{!leading && <div className="flex-1" />}
|
|
102
71
|
|
|
103
72
|
<div className="absolute left-1/2 flex -translate-x-1/2 items-center rounded-xl border border-border/50 bg-background/70 p-0.5 backdrop-blur-md">
|
|
104
73
|
{DEVICES.map((d) => {
|
|
@@ -121,7 +90,16 @@ export function Toolbar({
|
|
|
121
90
|
})}
|
|
122
91
|
</div>
|
|
123
92
|
|
|
124
|
-
<div className="ml-auto flex items-center gap-0.5">
|
|
93
|
+
<div className="ml-auto flex shrink-0 items-center gap-0.5">
|
|
94
|
+
{onAddBlock && !compact && (
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
onClick={onAddBlock}
|
|
98
|
+
className="mr-1 hidden items-center gap-1 rounded-xl border border-border/50 px-2.5 py-1.5 text-xs font-medium text-foreground hover:bg-muted sm:inline-flex"
|
|
99
|
+
>
|
|
100
|
+
<Plus className="size-3.5" /> Add
|
|
101
|
+
</button>
|
|
102
|
+
)}
|
|
125
103
|
<button
|
|
126
104
|
onClick={() => undo()}
|
|
127
105
|
disabled={!canUndo}
|
|
@@ -143,19 +121,19 @@ export function Toolbar({
|
|
|
143
121
|
href={viewUrl}
|
|
144
122
|
target="_blank"
|
|
145
123
|
rel="noreferrer"
|
|
146
|
-
title="
|
|
147
|
-
className="ml-
|
|
124
|
+
title="Preview live site"
|
|
125
|
+
className="ml-0.5 hidden items-center gap-1 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground sm:flex"
|
|
148
126
|
>
|
|
149
|
-
<ExternalLink className="size-3.5" />
|
|
127
|
+
<ExternalLink className="size-3.5" />
|
|
150
128
|
</a>
|
|
151
129
|
)}
|
|
152
|
-
<span className="mx-1 w-
|
|
153
|
-
{saving === "saving" ? "
|
|
130
|
+
<span className="mx-1 hidden w-10 text-right text-[10px] text-muted-foreground/70 sm:block">
|
|
131
|
+
{saving === "saving" ? "…" : saving === "saved" ? "Saved" : ""}
|
|
154
132
|
</span>
|
|
155
133
|
{onPublish && (
|
|
156
134
|
<button
|
|
157
135
|
onClick={onPublish}
|
|
158
|
-
className="rounded-xl bg-primary px-3.5 py-1.5 text-sm font-semibold text-primary-foreground shadow-sm transition hover:opacity-90
|
|
136
|
+
className="rounded-xl bg-primary px-3.5 py-1.5 text-sm font-semibold text-primary-foreground shadow-sm transition hover:opacity-90"
|
|
159
137
|
>
|
|
160
138
|
Publish
|
|
161
139
|
</button>
|
|
@@ -164,30 +142,3 @@ export function Toolbar({
|
|
|
164
142
|
</header>
|
|
165
143
|
);
|
|
166
144
|
}
|
|
167
|
-
|
|
168
|
-
function ToolButton({
|
|
169
|
-
active,
|
|
170
|
-
onClick,
|
|
171
|
-
title,
|
|
172
|
-
children,
|
|
173
|
-
}: {
|
|
174
|
-
active?: boolean;
|
|
175
|
-
onClick: () => void;
|
|
176
|
-
title: string;
|
|
177
|
-
children: React.ReactNode;
|
|
178
|
-
}) {
|
|
179
|
-
return (
|
|
180
|
-
<button
|
|
181
|
-
onClick={onClick}
|
|
182
|
-
title={title}
|
|
183
|
-
className={cn(
|
|
184
|
-
"flex items-center gap-1.5 rounded-xl px-2 py-1.5 sm:px-2.5",
|
|
185
|
-
active
|
|
186
|
-
? "bg-secondary text-secondary-foreground"
|
|
187
|
-
: "text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
188
|
-
)}
|
|
189
|
-
>
|
|
190
|
-
{children}
|
|
191
|
-
</button>
|
|
192
|
-
);
|
|
193
|
-
}
|
|
@@ -62,7 +62,7 @@ function EditableText({
|
|
|
62
62
|
Tag,
|
|
63
63
|
{
|
|
64
64
|
ref,
|
|
65
|
-
className: cn("outline-none focus:ring-2 focus:ring-
|
|
65
|
+
className: cn("outline-none focus:ring-2 focus:ring-primary/60 rounded-sm", className),
|
|
66
66
|
style,
|
|
67
67
|
contentEditable: true,
|
|
68
68
|
suppressContentEditableWarning: true,
|
|
@@ -175,8 +175,8 @@ function EditableImage({ field, src, alt, className, style, width, height, prior
|
|
|
175
175
|
loading={priority ? "eager" : "lazy"}
|
|
176
176
|
fetchPriority={priority ? "high" : "auto"}
|
|
177
177
|
className={cn(
|
|
178
|
-
"cursor-pointer outline-2 outline-offset-2 outline-transparent hover:outline-
|
|
179
|
-
dragOver && "outline-
|
|
178
|
+
"cursor-pointer outline-2 outline-offset-2 outline-transparent hover:outline-primary",
|
|
179
|
+
dragOver && "outline-primary",
|
|
180
180
|
className,
|
|
181
181
|
)}
|
|
182
182
|
style={style}
|
|
@@ -187,8 +187,8 @@ function EditableImage({ field, src, alt, className, style, width, height, prior
|
|
|
187
187
|
) : (
|
|
188
188
|
<div
|
|
189
189
|
className={cn(
|
|
190
|
-
"flex cursor-pointer items-center justify-center bg-
|
|
191
|
-
dragOver && "outline-
|
|
190
|
+
"flex cursor-pointer items-center justify-center bg-foreground/[0.04] text-[11px] uppercase tracking-wider opacity-50 outline-2 outline-dashed outline-foreground/15 hover:outline-primary",
|
|
191
|
+
dragOver && "outline-primary opacity-80",
|
|
192
192
|
className,
|
|
193
193
|
)}
|
|
194
194
|
style={style}
|
|
@@ -199,7 +199,7 @@ function EditableImage({ field, src, alt, className, style, width, height, prior
|
|
|
199
199
|
</div>
|
|
200
200
|
)}
|
|
201
201
|
{err && (
|
|
202
|
-
<p className="mt-1 text-[10px] text-
|
|
202
|
+
<p className="mt-1 text-[10px] text-destructive" title={err}>
|
|
203
203
|
{err}
|
|
204
204
|
</p>
|
|
205
205
|
)}
|
package/src/editor/index.tsx
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
/** Client editor entry. Production rendering lives at
|
|
4
4
|
* "@jimmy_harika/websitekit/renderer"; the model/registry at the package root. */
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
PageBuilder,
|
|
7
|
+
type PageBuilderProps,
|
|
8
|
+
type HostRailItem,
|
|
9
|
+
type DockMode,
|
|
10
|
+
} from "./PageBuilder";
|
|
11
|
+
export { EditorDock, EditorRail } from "./EditorDock";
|
|
6
12
|
export { type TemplateMeta } from "./TemplateGallery";
|
|
7
13
|
export { type Device } from "./ui-context";
|
|
8
14
|
export { type EditorCapabilities } from "./edit-primitives";
|