@bycrux/editor 0.4.2 → 0.4.4
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
|
@@ -84,7 +84,7 @@ function SlideGrid({
|
|
|
84
84
|
onDrop={() => handleDrop(idx)}
|
|
85
85
|
onDragEnd={handleDragEnd}
|
|
86
86
|
onClick={() => onSelect(slide.id)}
|
|
87
|
-
className={`group relative cursor-pointer rounded overflow-hidden border transition-colors ${
|
|
87
|
+
className={`group relative flex-shrink-0 cursor-pointer rounded overflow-hidden border transition-colors ${
|
|
88
88
|
selectedSlideId === slide.id
|
|
89
89
|
? 'border-[var(--editor-accent)]'
|
|
90
90
|
: dragOverIdx === idx
|
|
@@ -357,16 +357,18 @@ export default function CarouselEditor<P extends Project = Project>({ project: i
|
|
|
357
357
|
obs.observe(el)
|
|
358
358
|
return () => obs.disconnect()
|
|
359
359
|
}, [])
|
|
360
|
-
const PADDING =
|
|
361
|
-
const HINT_RESERVE =
|
|
360
|
+
const PADDING = 32
|
|
361
|
+
const HINT_RESERVE = 28
|
|
362
362
|
const availW = Math.max(0, canvasContainerSize.w - PADDING)
|
|
363
363
|
const availH = Math.max(0, canvasContainerSize.h - PADDING - HINT_RESERVE)
|
|
364
364
|
const canvasScale = Math.min(availW / w, availH / h, 1)
|
|
365
365
|
|
|
366
366
|
return (
|
|
367
|
-
<div ref={containerRef} className="flex flex-col h-full overflow-
|
|
368
|
-
{/* TOP: slide rail
|
|
369
|
-
|
|
367
|
+
<div ref={containerRef} className="flex flex-col h-full overflow-y-auto bg-[var(--editor-bg)]">
|
|
368
|
+
{/* TOP: slide rail | canvas | editing panel (right). Given a generous
|
|
369
|
+
viewport-relative height so the slide renders large; the project-media
|
|
370
|
+
region flows beneath and the whole editor scrolls vertically. */}
|
|
371
|
+
<div className="flex flex-shrink-0 min-h-[62vh] overflow-hidden">
|
|
370
372
|
<SlideGrid
|
|
371
373
|
project={project}
|
|
372
374
|
slides={slides}
|
|
@@ -380,7 +382,7 @@ export default function CarouselEditor<P extends Project = Project>({ project: i
|
|
|
380
382
|
compileOverlay={(t) => adapter.compileOverlay(t)}
|
|
381
383
|
/>
|
|
382
384
|
|
|
383
|
-
<div ref={canvasContainerRef} className="relative flex-1 flex flex-col items-center justify-center gap-4 overflow-hidden p-
|
|
385
|
+
<div ref={canvasContainerRef} className="relative flex-1 flex flex-col items-center justify-center gap-4 overflow-hidden p-4">
|
|
384
386
|
<button
|
|
385
387
|
onClick={handleRefresh}
|
|
386
388
|
disabled={refreshing}
|
|
@@ -491,52 +493,50 @@ export default function CarouselEditor<P extends Project = Project>({ project: i
|
|
|
491
493
|
</div>
|
|
492
494
|
)}
|
|
493
495
|
</div>
|
|
494
|
-
</div>
|
|
495
496
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
</div>
|
|
508
|
-
)}
|
|
509
|
-
<div className="flex flex-1 min-h-0 overflow-hidden">
|
|
510
|
-
<div className="w-80 flex-shrink-0 overflow-y-auto border-r border-[var(--editor-border)]">
|
|
511
|
-
<SlidePropertyPanel
|
|
512
|
-
project={project}
|
|
513
|
-
slide={selectedSlide}
|
|
514
|
-
element={selectedElement}
|
|
515
|
-
adapter={adapter}
|
|
516
|
-
onSlideChange={handleSlideChange}
|
|
517
|
-
onElementChange={handlePanelElementChange}
|
|
518
|
-
onDeleteSlide={handleDeleteSlide}
|
|
519
|
-
onDuplicateSlide={handleDuplicateSlide}
|
|
520
|
-
onDeleteElement={handleDeleteElement}
|
|
521
|
-
onDuplicateElement={handleDuplicateElement}
|
|
522
|
-
onReorderElement={handleReorderElement}
|
|
523
|
-
onEnterCrop={(_slideId, elementId) => { setSelectedElementId(elementId); setCropElementId(elementId) }}
|
|
524
|
-
updateOverlayProp={state.updateOverlayProp}
|
|
525
|
-
hiddenElementIds={hiddenElementIds}
|
|
526
|
-
onToggleElementVisibility={onToggleElementVisibility}
|
|
527
|
-
/>
|
|
528
|
-
</div>
|
|
529
|
-
{slots?.assetsPanel && (
|
|
530
|
-
// Below the canvas the assets slot fills the remaining width (no longer
|
|
531
|
-
// capped to a 320px sidebar) and scrolls vertically within the bounded
|
|
532
|
-
// below-canvas region.
|
|
533
|
-
<div className="flex-1 min-w-0 flex flex-col overflow-y-auto overflow-x-hidden">
|
|
534
|
-
{slots.assetsPanel}
|
|
497
|
+
{/* RIGHT: the slide editor (add-element toolbar + property panel),
|
|
498
|
+
beside the canvas with its own vertical scroll. */}
|
|
499
|
+
<div className="w-[24rem] flex-shrink-0 border-l border-[var(--editor-border)] flex flex-col overflow-y-auto bg-[var(--editor-bg)]">
|
|
500
|
+
{selectedSlide && project.status !== 'pending' && (
|
|
501
|
+
<div className="px-4 py-2 border-b border-[var(--editor-border)]">
|
|
502
|
+
<AddElementMenu
|
|
503
|
+
project={project}
|
|
504
|
+
selectedSlideId={selectedSlideId}
|
|
505
|
+
adapter={adapter}
|
|
506
|
+
onAddElement={handleAddElement}
|
|
507
|
+
/>
|
|
535
508
|
</div>
|
|
536
509
|
)}
|
|
510
|
+
<SlidePropertyPanel
|
|
511
|
+
project={project}
|
|
512
|
+
slide={selectedSlide}
|
|
513
|
+
element={selectedElement}
|
|
514
|
+
adapter={adapter}
|
|
515
|
+
onSlideChange={handleSlideChange}
|
|
516
|
+
onElementChange={handlePanelElementChange}
|
|
517
|
+
onDeleteSlide={handleDeleteSlide}
|
|
518
|
+
onDuplicateSlide={handleDuplicateSlide}
|
|
519
|
+
onDeleteElement={handleDeleteElement}
|
|
520
|
+
onDuplicateElement={handleDuplicateElement}
|
|
521
|
+
onReorderElement={handleReorderElement}
|
|
522
|
+
onEnterCrop={(_slideId, elementId) => { setSelectedElementId(elementId); setCropElementId(elementId) }}
|
|
523
|
+
updateOverlayProp={state.updateOverlayProp}
|
|
524
|
+
hiddenElementIds={hiddenElementIds}
|
|
525
|
+
onToggleElementVisibility={onToggleElementVisibility}
|
|
526
|
+
// Fills the right column (drop the default w-80 width + left border).
|
|
527
|
+
className="w-full border-l-0"
|
|
528
|
+
/>
|
|
537
529
|
</div>
|
|
538
530
|
</div>
|
|
539
531
|
|
|
532
|
+
{/* BELOW: Project media, full width at the bottom. Flows beneath the top
|
|
533
|
+
region and scrolls with the page (the root is overflow-y-auto). */}
|
|
534
|
+
{slots?.assetsPanel && (
|
|
535
|
+
<div className="flex-shrink-0 border-t border-[var(--editor-border)] w-full flex flex-col">
|
|
536
|
+
{slots.assetsPanel}
|
|
537
|
+
</div>
|
|
538
|
+
)}
|
|
539
|
+
|
|
540
540
|
{renderOpen && (
|
|
541
541
|
<CarouselRenderModal
|
|
542
542
|
projectId={project.id}
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
GlobalOverlayProp,
|
|
10
10
|
EditorAdapter,
|
|
11
11
|
} from '../types'
|
|
12
|
-
import { Button } from '../ui'
|
|
12
|
+
import { Button, cn } from '../ui'
|
|
13
13
|
import { TextFormattingToolbar } from '../text/TextFormattingToolbar'
|
|
14
14
|
|
|
15
15
|
function parseNumber(v: string): number | null {
|
|
@@ -39,6 +39,10 @@ interface Props {
|
|
|
39
39
|
// selected element; `hiddenElementIds` reflects the current hidden set.
|
|
40
40
|
hiddenElementIds?: string[]
|
|
41
41
|
onToggleElementVisibility?: (elementId: string) => void
|
|
42
|
+
// Override the panel's root container classes. Hosts that stack the panel
|
|
43
|
+
// full-width (e.g. below the canvas) pass this to drop the default `w-80`
|
|
44
|
+
// sidebar constraint.
|
|
45
|
+
className?: string
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
// Small eye toggle to hide/show the selected element in the editor preview only
|
|
@@ -179,6 +183,7 @@ export default function SlidePropertyPanel({
|
|
|
179
183
|
adapter,
|
|
180
184
|
hiddenElementIds,
|
|
181
185
|
onToggleElementVisibility,
|
|
186
|
+
className,
|
|
182
187
|
}: Props) {
|
|
183
188
|
// Map of jsxPath → GlobalOverlay for overlay prop schemas
|
|
184
189
|
const [overlaySchemas, setOverlaySchemas] = useState<Map<string, GlobalOverlay>>(new Map())
|
|
@@ -206,7 +211,7 @@ export default function SlidePropertyPanel({
|
|
|
206
211
|
|
|
207
212
|
if (!slide) {
|
|
208
213
|
return (
|
|
209
|
-
<div className=
|
|
214
|
+
<div className={cn('w-80 flex-shrink-0 flex items-center justify-center text-[var(--editor-text)]/40 text-xs p-4', className)}>
|
|
210
215
|
Select a slide
|
|
211
216
|
</div>
|
|
212
217
|
)
|
|
@@ -216,7 +221,7 @@ export default function SlidePropertyPanel({
|
|
|
216
221
|
const overlaySchema = overlayEl ? overlaySchemas.get(overlayEl.overlay.template) : null
|
|
217
222
|
|
|
218
223
|
return (
|
|
219
|
-
<div className=
|
|
224
|
+
<div className={cn('w-80 flex-shrink-0 border-l border-[var(--editor-border)] flex flex-col overflow-y-auto bg-[var(--editor-bg)]', className)}>
|
|
220
225
|
{/* Slide header */}
|
|
221
226
|
<div className="px-4 py-3 border-b border-[var(--editor-border)]">
|
|
222
227
|
<div className="text-xs font-semibold text-[var(--editor-text)]/60 uppercase tracking-wider mb-2">Slide</div>
|
|
@@ -97,11 +97,11 @@ describe('CarouselEditor — editor-core integration', () => {
|
|
|
97
97
|
/>,
|
|
98
98
|
)
|
|
99
99
|
await waitFor(() => getByTestId('assets'))
|
|
100
|
-
// The assets slot
|
|
101
|
-
//
|
|
102
|
-
//
|
|
100
|
+
// The assets slot lives in the below-canvas region, full-width at the very
|
|
101
|
+
// bottom (no longer capped to a 320px sidebar) so the host panel spans the
|
|
102
|
+
// editor width beneath the top canvas/editing region.
|
|
103
103
|
const wrapper = getByTestId('assets').parentElement
|
|
104
|
-
expect(wrapper?.className).toContain('
|
|
104
|
+
expect(wrapper?.className).toContain('w-full')
|
|
105
105
|
expect(wrapper?.className).not.toContain('w-80')
|
|
106
106
|
})
|
|
107
107
|
|
package/src/ui/button.tsx
CHANGED
|
@@ -7,10 +7,10 @@ const buttonVariants = cva(
|
|
|
7
7
|
variants: {
|
|
8
8
|
variant: {
|
|
9
9
|
default: 'bg-[var(--editor-accent)] text-[var(--editor-accent-foreground)] hover:opacity-90',
|
|
10
|
-
secondary: 'bg-
|
|
11
|
-
ghost: 'text-
|
|
10
|
+
secondary: 'bg-[var(--editor-surface)] text-[var(--editor-text)] border border-[var(--editor-border)] hover:border-[var(--editor-accent)]',
|
|
11
|
+
ghost: 'text-[var(--editor-text)] hover:bg-[var(--editor-surface)] hover:text-[var(--editor-text)]',
|
|
12
12
|
danger: 'bg-red-600 text-white hover:bg-red-700',
|
|
13
|
-
outline: '
|
|
13
|
+
outline: 'bg-[var(--editor-surface)] text-[var(--editor-text)] border border-[var(--editor-border)] hover:border-[var(--editor-accent)]',
|
|
14
14
|
},
|
|
15
15
|
size: {
|
|
16
16
|
default: 'h-9 px-4 py-2',
|