summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/export-button.tsx
diff options
context:
space:
mode:
authorMaze <167211895+mazeincoding@users.noreply.github.com>2026-02-23 03:24:02 +0100
committerGitHub <noreply@github.com>2026-02-23 03:24:02 +0100
commit93d1e3383ce47e45157d70f9ba6251239dae6bc2 (patch)
tree1e33a2d7533b65f0e7c8927f03905a1a99937bd1 /apps/web/src/components/editor/export-button.tsx
parentfca99d6126c31fbb18ed9f1034cee6f940b040e8 (diff)
downloadopencut-93d1e3383ce47e45157d70f9ba6251239dae6bc2.tar.gz
feat: major editor overhaul (assets, properties, timeline, fonts) (#709)
* feat: major editor overhaul (assets, properties, timeline, fonts) Refactor editor core systems to standardize UI architecture and improve performance. Assets & Properties: - Replace monolithic property items with composable `Section` architecture. - Add specialized sections for Transform, Blending, and Text. - Implement `NumberField` with scrubbing and math evaluation. - Add new ColorPicker with EyeDropper and multiple format support. - Standardize asset panels using new `PanelView` layout. Fonts & Stickers: - Implement custom font atlas/sprite system for high-performance previews. - Add virtualized FontPicker with search and favorites. - Refactor stickers to use a provider-based architecture (icons, emoji, flags, shapes). - Standardize sticker IDs to `provider:value` format. Timeline & Interaction: - Convert bookmarks to rich objects with notes, colors, and duration. - Refactor drag-and-drop to use Command pattern (enabling proper undo/redo). - Add Shift modifier to disable snapping during moves/resizes. - Add new overlays for layout guides and text editing. Renderer: - Add support for multi-line text, custom line-height, and letter-spacing. - Implement global composite operation (blend modes). - Update sticker node to resolve dynamic provider IDs. Infrastructure: - Add storage migrations (v3->v6) for text weights, sticker IDs, and bookmarks. - Update global styles and core UI components (Button, Input, Popover). * add ts-nocheck directive to settings-legacy.tsx to suppress TypeScript errors * fix: correct global composite operation assignment in TextNode to ensure proper blend mode handling * deleted shadcn components with errors * formatting * fix linter issues * migrate from next middleware to proxy * add missing component back * add breadcrumb back * chore: add @radix-ui/react-primitive deps * chore: more deps * chore: add missing env vars to bun-ci * next env
Diffstat (limited to 'apps/web/src/components/editor/export-button.tsx')
-rw-r--r--apps/web/src/components/editor/export-button.tsx147
1 files changed, 78 insertions, 69 deletions
diff --git a/apps/web/src/components/editor/export-button.tsx b/apps/web/src/components/editor/export-button.tsx
index f39c18e2..bc44e650 100644
--- a/apps/web/src/components/editor/export-button.tsx
+++ b/apps/web/src/components/editor/export-button.tsx
@@ -23,7 +23,11 @@ import {
type ExportQuality,
type ExportResult,
} from "@/types/export";
-import { PropertyGroup } from "@/components/editor/panels/properties/property-item";
+import {
+ Section,
+ SectionContent,
+ SectionHeader,
+} from "@/components/editor/panels/properties/section";
import { useEditor } from "@/hooks/use-editor";
import { DEFAULT_EXPORT_OPTIONS } from "@/constants/export-constants";
@@ -162,78 +166,83 @@ function ExportPopover({
{!isExporting && (
<>
<div className="flex flex-col">
- <PropertyGroup
- title="Format"
- defaultExpanded={false}
- hasBorderTop={false}
- >
- <RadioGroup
- value={format}
- onValueChange={(value) => {
- if (isExportFormat(value)) {
- setFormat(value);
- }
- }}
- >
- <div className="flex items-center space-x-2">
- <RadioGroupItem value="mp4" id="mp4" />
- <Label htmlFor="mp4">
- MP4 (H.264) - Better compatibility
- </Label>
- </div>
- <div className="flex items-center space-x-2">
- <RadioGroupItem value="webm" id="webm" />
- <Label htmlFor="webm">
- WebM (VP9) - Smaller file size
- </Label>
- </div>
- </RadioGroup>
- </PropertyGroup>
+ <Section collapsible defaultOpen={false} hasBorderTop={false}>
+ <SectionHeader title="Format" />
+ <SectionContent>
+ <RadioGroup
+ value={format}
+ onValueChange={(value) => {
+ if (isExportFormat(value)) {
+ setFormat(value);
+ }
+ }}
+ >
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="mp4" id="mp4" />
+ <Label htmlFor="mp4">
+ MP4 (H.264) - Better compatibility
+ </Label>
+ </div>
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="webm" id="webm" />
+ <Label htmlFor="webm">
+ WebM (VP9) - Smaller file size
+ </Label>
+ </div>
+ </RadioGroup>
+ </SectionContent>
+ </Section>
- <PropertyGroup title="Quality" defaultExpanded={false}>
- <RadioGroup
- value={quality}
- onValueChange={(value) => {
- if (isExportQuality(value)) {
- setQuality(value);
- }
- }}
- >
- <div className="flex items-center space-x-2">
- <RadioGroupItem value="low" id="low" />
- <Label htmlFor="low">Low - Smallest file size</Label>
- </div>
- <div className="flex items-center space-x-2">
- <RadioGroupItem value="medium" id="medium" />
- <Label htmlFor="medium">Medium - Balanced</Label>
- </div>
- <div className="flex items-center space-x-2">
- <RadioGroupItem value="high" id="high" />
- <Label htmlFor="high">High - Recommended</Label>
- </div>
+ <Section collapsible defaultOpen={false}>
+ <SectionHeader title="Quality" />
+ <SectionContent>
+ <RadioGroup
+ value={quality}
+ onValueChange={(value) => {
+ if (isExportQuality(value)) {
+ setQuality(value);
+ }
+ }}
+ >
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="low" id="low" />
+ <Label htmlFor="low">Low - Smallest file size</Label>
+ </div>
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="medium" id="medium" />
+ <Label htmlFor="medium">Medium - Balanced</Label>
+ </div>
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="high" id="high" />
+ <Label htmlFor="high">High - Recommended</Label>
+ </div>
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="very_high" id="very_high" />
+ <Label htmlFor="very_high">
+ Very High - Largest file size
+ </Label>
+ </div>
+ </RadioGroup>
+ </SectionContent>
+ </Section>
+
+ <Section collapsible defaultOpen={false}>
+ <SectionHeader title="Audio" />
+ <SectionContent>
<div className="flex items-center space-x-2">
- <RadioGroupItem value="very_high" id="very_high" />
- <Label htmlFor="very_high">
- Very High - Largest file size
+ <Checkbox
+ id="include-audio"
+ checked={includeAudio}
+ onCheckedChange={(checked) =>
+ setIncludeAudio(!!checked)
+ }
+ />
+ <Label htmlFor="include-audio">
+ Include audio in export
</Label>
</div>
- </RadioGroup>
- </PropertyGroup>
-
- <PropertyGroup title="Audio" defaultExpanded={false}>
- <div className="flex items-center space-x-2">
- <Checkbox
- id="include-audio"
- checked={includeAudio}
- onCheckedChange={(checked) =>
- setIncludeAudio(!!checked)
- }
- />
- <Label htmlFor="include-audio">
- Include audio in export
- </Label>
- </div>
- </PropertyGroup>
+ </SectionContent>
+ </Section>
</div>
<div className="p-3 pt-0">