@jimmy_harika/websitekit 0.5.4 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jimmy_harika/websitekit",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "Snow Labs website builder engine. Block-agnostic, curated-section. One shared builder across every Snow Labs app — engine + design-system-agnostic blocks + per-industry catalogs (author, photographer, …). Each app plugs in a catalog + theme + persistence adapter.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -89,7 +89,7 @@ export function Canvas({ catalog }: { catalog: Catalog }) {
89
89
  e.stopPropagation();
90
90
  ui.openLibrary(0);
91
91
  }}
92
- className="flex min-h-[60vh] w-full flex-col items-center justify-center gap-3 text-muted-foreground/70 transition hover:text-sky-500"
92
+ className="flex min-h-[60vh] w-full flex-col items-center justify-center gap-3 text-muted-foreground/70 transition hover:text-primary"
93
93
  >
94
94
  <span className="flex size-12 items-center justify-center rounded-full border-2 border-dashed border-current">
95
95
  <Plus className="size-6" />
@@ -29,7 +29,7 @@ export function EditorDock({
29
29
  <aside
30
30
  data-editor-dock
31
31
  className={cn(
32
- "flex h-full shrink-0 flex-col border-l border-border/50 bg-card/90 text-foreground shadow-[-12px_0_40px_-20px_rgba(0,0,0,0.45)] backdrop-blur-2xl",
32
+ "flex h-full shrink-0 flex-col border-l border-border/50 bg-card/90 text-foreground shadow-none backdrop-blur-2xl",
33
33
  wide ? "w-[min(36rem,100vw)]" : "w-[min(22rem,100vw)]",
34
34
  "max-md:fixed max-md:inset-x-0 max-md:bottom-0 max-md:top-auto max-md:z-50 max-md:h-[min(78vh,100%)] max-md:w-full max-md:rounded-t-2xl max-md:border-l-0 max-md:border-t max-md:shadow-2xl",
35
35
  className,
@@ -79,7 +79,7 @@ export function EditorRail({
79
79
  data-editor-rail
80
80
  aria-label="Editor tools"
81
81
  className={cn(
82
- "z-20 hidden w-[4.25rem] shrink-0 flex-col items-stretch gap-0.5 border-r border-border/40 bg-card/50 py-2 backdrop-blur-xl md:flex",
82
+ "z-20 hidden w-[4.25rem] shrink-0 flex-col items-stretch gap-0.5 border-r border-border bg-card/80 py-2 backdrop-blur-xl md:flex",
83
83
  className,
84
84
  )}
85
85
  >
@@ -92,7 +92,7 @@ export function EditorRail({
92
92
  className={cn(
93
93
  "mx-1 flex flex-col items-center gap-0.5 rounded-xl px-1 py-2 text-[9px] font-medium uppercase tracking-[0.08em] transition",
94
94
  item.active
95
- ? "bg-foreground text-background shadow-sm"
95
+ ? "bg-primary text-primary-foreground shadow-sm"
96
96
  : "text-muted-foreground hover:bg-muted hover:text-foreground",
97
97
  )}
98
98
  >
@@ -12,19 +12,19 @@ export function InsertPoint({ index }: { index: number }) {
12
12
  {/* Always visible on touch/small screens (group-hover doesn't fire on touch);
13
13
  hover-reveal on desktop. Without this a mobile user can't add a 2nd section. */}
14
14
  <div className="pointer-events-none absolute inset-x-0 -top-4 flex h-8 items-center justify-center px-6 opacity-100 transition group-hover/ins:opacity-100 md:opacity-0 md:group-hover/ins:opacity-100">
15
- <div className="h-px flex-1 bg-sky-400/70" />
15
+ <div className="h-px flex-1 bg-primary/70" />
16
16
  <button
17
17
  type="button"
18
18
  onClick={(e) => {
19
19
  e.stopPropagation();
20
20
  ui.openLibrary(index);
21
21
  }}
22
- className="pointer-events-auto mx-2 flex size-7 items-center justify-center rounded-full bg-sky-500 text-white shadow-md transition hover:scale-105 hover:bg-sky-600"
22
+ className="pointer-events-auto mx-2 flex size-7 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-md transition hover:scale-105 hover:bg-primary/90"
23
23
  title="Add section here"
24
24
  >
25
25
  <Plus className="size-4" />
26
26
  </button>
27
- <div className="h-px flex-1 bg-sky-400/70" />
27
+ <div className="h-px flex-1 bg-primary/70" />
28
28
  </div>
29
29
  </div>
30
30
  );
@@ -17,7 +17,14 @@ const BP: { id: Breakpoint; icon: typeof Monitor; label: string }[] = [
17
17
  { id: "desktop", icon: Monitor, label: "Desktop" },
18
18
  ];
19
19
 
20
- export function Inspector({ catalog }: { catalog: Catalog }) {
20
+ export function Inspector({
21
+ catalog,
22
+ /** When true (docked mode), skip the outer chrome — parent dock owns the title bar. */
23
+ embedded,
24
+ }: {
25
+ catalog: Catalog;
26
+ embedded?: boolean;
27
+ }) {
21
28
  const ui = useEditorUi();
22
29
  const selectedId = useBuilder((s) => s.selectedId);
23
30
  const section = useBuilder(
@@ -29,7 +36,9 @@ export function Inspector({ catalog }: { catalog: Catalog }) {
29
36
  const remove = useBuilder((s) => s.removeSection);
30
37
  const duplicate = useBuilder((s) => s.duplicateSection);
31
38
 
32
- if (!ui.inspectorOpen || !section) return null;
39
+ // In embedded/dock mode the parent already decided to show us — don't require inspectorOpen.
40
+ if (!embedded && !ui.inspectorOpen) return null;
41
+ if (!section) return null;
33
42
  const def = getDefinition(catalog, section.type);
34
43
  if (!def) return null;
35
44
 
@@ -43,18 +52,27 @@ export function Inspector({ catalog }: { catalog: Catalog }) {
43
52
 
44
53
  return (
45
54
  <div className="flex h-full min-h-0 flex-col">
46
- <div className="flex items-center justify-between border-b px-4 py-3">
47
- <div>
48
- <p className="text-[11px] uppercase tracking-wider text-muted-foreground/70">Section</p>
49
- <h3 className="text-sm font-semibold">{def.label}</h3>
55
+ {!embedded && (
56
+ <div className="flex items-center justify-between border-b border-border px-4 py-3">
57
+ <div>
58
+ <p className="text-[11px] uppercase tracking-wider text-muted-foreground">
59
+ Section
60
+ </p>
61
+ <h3 className="text-sm font-semibold text-foreground">{def.label}</h3>
62
+ </div>
63
+ <button
64
+ onClick={() => ui.setInspectorOpen(false)}
65
+ className="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
66
+ >
67
+ <X className="size-4" />
68
+ </button>
50
69
  </div>
51
- <button
52
- onClick={() => ui.setInspectorOpen(false)}
53
- className="rounded p-1 hover:bg-accent"
54
- >
55
- <X className="size-4" />
56
- </button>
57
- </div>
70
+ )}
71
+ {embedded && (
72
+ <div className="border-b border-border px-4 py-2.5">
73
+ <p className="text-sm font-semibold text-foreground">{def.label}</p>
74
+ </div>
75
+ )}
58
76
  <div className="flex-1 space-y-5 overflow-auto p-4">
59
77
  <div>
60
78
  <label className="mb-1.5 block text-xs font-medium text-muted-foreground">
@@ -137,7 +155,7 @@ export function Inspector({ catalog }: { catalog: Catalog }) {
137
155
  </button>
138
156
  <button
139
157
  onClick={() => remove(section.id)}
140
- className="flex-1 rounded-md border border-red-200 px-3 py-2 text-xs text-red-600 hover:bg-red-50"
158
+ className="flex-1 rounded-md border border-destructive/30 px-3 py-2 text-xs text-destructive hover:bg-destructive/10"
141
159
  >
142
160
  Delete
143
161
  </button>
@@ -328,7 +346,7 @@ function ImageField({
328
346
  <img
329
347
  src={value}
330
348
  alt={altValue ?? ""}
331
- className={`h-24 w-full rounded-md object-cover ${dragOver ? "ring-2 ring-sky-400" : ""}`}
349
+ className={`h-24 w-full rounded-md object-cover ${dragOver ? "ring-2 ring-primary" : ""}`}
332
350
  onDragOver={(e) => {
333
351
  e.preventDefault();
334
352
  setDragOver(true);
@@ -344,7 +362,7 @@ function ImageField({
344
362
  ) : (
345
363
  <div
346
364
  className={`flex h-24 items-center justify-center rounded-md border border-dashed text-xs text-muted-foreground/70 ${
347
- dragOver ? "border-sky-400 bg-sky-400/10" : ""
365
+ dragOver ? "border-primary bg-primary/10" : ""
348
366
  }`}
349
367
  onDragOver={(e) => {
350
368
  e.preventDefault();
@@ -377,7 +395,7 @@ function ImageField({
377
395
  </button>
378
396
  )}
379
397
  </div>
380
- {err && <p className="text-[10px] text-red-600 dark:text-red-400">{err}</p>}
398
+ {err && <p className="text-[10px] text-destructive">{err}</p>}
381
399
  <input ref={ref} type="file" accept="image/*,.heic,.heif,image/heic,image/heif" hidden onChange={pick} />
382
400
  <input
383
401
  value={value}
@@ -482,7 +500,7 @@ function ImageListField({
482
500
  <div key={`${url}-${i}`} className="group relative">
483
501
  {/* eslint-disable-next-line @next/next/no-img-element */}
484
502
  <img src={url} alt="" className="aspect-square w-full rounded-md object-cover" />
485
- <div className="absolute inset-0 hidden items-end justify-between rounded-md bg-black/40 p-1 group-hover:flex">
503
+ <div className="absolute inset-0 hidden items-end justify-between rounded-md bg-foreground/40 p-1 group-hover:flex">
486
504
  <div className="flex gap-0.5">
487
505
  <button
488
506
  title="Move left"
@@ -515,7 +533,7 @@ function ImageListField({
515
533
  ) : (
516
534
  <div
517
535
  className={`flex h-16 items-center justify-center rounded-md border border-dashed text-xs text-muted-foreground/70 ${
518
- dragOver ? "border-sky-400 bg-sky-400/10" : ""
536
+ dragOver ? "border-primary bg-primary/10" : ""
519
537
  }`}
520
538
  onDragOver={(e) => {
521
539
  e.preventDefault();
@@ -535,7 +553,7 @@ function ImageListField({
535
553
  onClick={() => ref.current?.click()}
536
554
  disabled={busy || room === 0}
537
555
  className={`w-full rounded-md border px-2 py-1.5 text-xs hover:bg-muted disabled:opacity-50 ${
538
- dragOver ? "border-sky-400" : ""
556
+ dragOver ? "border-primary" : ""
539
557
  }`}
540
558
  onDragOver={(e) => {
541
559
  e.preventDefault();
@@ -670,7 +688,7 @@ function ItemListField({
670
688
  <button
671
689
  title="Remove"
672
690
  onClick={() => onChange(value.filter((_, j) => j !== i))}
673
- className="rounded border px-1 text-[10px] leading-4 text-red-600"
691
+ className="rounded border px-1 text-[10px] leading-4 text-destructive"
674
692
  >
675
693
  ×
676
694
  </button>
@@ -306,19 +306,16 @@ function PageBuilderInner({
306
306
  onClose={closeDock}
307
307
  wide={dock === "library"}
308
308
  >
309
- {dock === "sections" && <SectionsPanel catalog={catalog} />}
309
+ {dock === "sections" && <SectionsPanel catalog={catalog} embedded />}
310
310
  {dock === "design" && <ThemePanel />}
311
- {dock === "inspector" && (
312
- <div className="p-1">
313
- {selectedId ? (
314
- <Inspector catalog={catalog} />
315
- ) : (
316
- <p className="p-4 text-sm text-muted-foreground">
317
- Click a section on the page to edit its content and layout.
318
- </p>
319
- )}
320
- </div>
321
- )}
311
+ {dock === "inspector" &&
312
+ (selectedId ? (
313
+ <Inspector catalog={catalog} embedded />
314
+ ) : (
315
+ <p className="p-4 text-sm text-muted-foreground">
316
+ Click a section on the page to edit its content and layout.
317
+ </p>
318
+ ))}
322
319
  {dock === "library" && <BlockLibraryBody catalog={catalog} />}
323
320
  {dock === "host" && hostDock?.body}
324
321
  </EditorDock>
@@ -61,14 +61,14 @@ export function SectionFrame({
61
61
  className={cn(
62
62
  "pointer-events-none absolute inset-0 z-10 ring-inset transition",
63
63
  selected
64
- ? "ring-2 ring-sky-500"
65
- : "ring-1 ring-transparent group-hover/sec:ring-2 group-hover/sec:ring-sky-300",
66
- over && "ring-2 ring-sky-400",
64
+ ? "ring-2 ring-primary"
65
+ : "ring-1 ring-transparent group-hover/sec:ring-2 group-hover/sec:ring-primary/40",
66
+ over && "ring-2 ring-primary",
67
67
  )}
68
68
  />
69
69
  <div
70
70
  className={cn(
71
- "absolute right-3 top-3 z-20 flex items-center gap-0.5 rounded-lg border border-black/10 bg-background/95 p-1 text-foreground shadow-sm backdrop-blur transition",
71
+ "absolute right-3 top-3 z-20 flex items-center gap-0.5 rounded-lg border border-border bg-card/95 p-1 text-foreground shadow-sm backdrop-blur transition",
72
72
  selected
73
73
  ? "opacity-100"
74
74
  : "pointer-events-none opacity-0 group-hover/sec:pointer-events-auto group-hover/sec:opacity-100",
@@ -103,7 +103,7 @@ export function SectionFrame({
103
103
  <button
104
104
  title="Delete"
105
105
  onClick={stop(() => remove(section.id))}
106
- className="rounded p-1.5 text-red-600 hover:bg-red-50"
106
+ className="rounded p-1.5 text-destructive hover:bg-destructive/10"
107
107
  >
108
108
  <Trash2 className="size-4" />
109
109
  </button>
@@ -111,7 +111,7 @@ export function SectionFrame({
111
111
  {section.hideOn && section.hideOn.length > 0 && (
112
112
  <div
113
113
  title={`Hidden on ${section.hideOn.join(", ")}`}
114
- className="absolute left-3 top-3 z-20 flex items-center gap-1 rounded-md border border-black/10 bg-background/95 px-1.5 py-1 text-foreground/70 shadow-sm backdrop-blur"
114
+ className="absolute left-3 top-3 z-20 flex items-center gap-1 rounded-md border border-border bg-background/95 px-1.5 py-1 text-foreground/70 shadow-sm backdrop-blur"
115
115
  >
116
116
  <EyeOff className="size-3.5" />
117
117
  {section.hideOn.map((bp) => {
@@ -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({ catalog }: { catalog: Catalog }) {
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 className="flex items-center justify-between border-b border-border px-3 py-2.5">
24
- <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
25
- Sections
26
- </span>
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-secondary px-2 py-1 text-xs font-medium text-secondary-foreground transition hover:opacity-90"
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-red-500"
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-black/10"
56
+ className="size-4 rounded-full border border-border"
57
57
  style={{ background: c }}
58
58
  />
59
59
  ))}
@@ -62,7 +62,7 @@ function EditableText({
62
62
  Tag,
63
63
  {
64
64
  ref,
65
- className: cn("outline-none focus:ring-2 focus:ring-sky-400/60 rounded-sm", className),
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-sky-400",
179
- dragOver && "outline-sky-400",
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-black/[0.04] text-[11px] uppercase tracking-wider opacity-50 outline-2 outline-dashed outline-black/15 hover:outline-sky-400",
191
- dragOver && "outline-sky-400 opacity-80",
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-red-600 dark:text-red-400" title={err}>
202
+ <p className="mt-1 text-[10px] text-destructive" title={err}>
203
203
  {err}
204
204
  </p>
205
205
  )}