diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2026-02-23 03:24:02 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-23 03:24:02 +0100 |
| commit | 93d1e3383ce47e45157d70f9ba6251239dae6bc2 (patch) | |
| tree | 1e33a2d7533b65f0e7c8927f03905a1a99937bd1 /apps/web/src/components/ui/input-with-back.tsx | |
| parent | fca99d6126c31fbb18ed9f1034cee6f940b040e8 (diff) | |
| download | opencut-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/ui/input-with-back.tsx')
| -rw-r--r-- | apps/web/src/components/ui/input-with-back.tsx | 173 |
1 files changed, 85 insertions, 88 deletions
diff --git a/apps/web/src/components/ui/input-with-back.tsx b/apps/web/src/components/ui/input-with-back.tsx index f8265779..1c22fd2e 100644 --- a/apps/web/src/components/ui/input-with-back.tsx +++ b/apps/web/src/components/ui/input-with-back.tsx @@ -1,88 +1,85 @@ -"use client";
-
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { ArrowLeft, Search } from "lucide-react";
-import { motion } from "motion/react";
-import { useState, useEffect } from "react";
-
-interface InputWithBackProps {
- isExpanded: boolean;
- setIsExpanded: (isExpanded: boolean) => void;
- placeholder?: string;
- value?: string;
- onChange?: (value: string) => void;
- disableAnimation?: boolean;
-}
-
-export function InputWithBack({
- isExpanded,
- setIsExpanded,
- placeholder = "Search anything",
- value,
- onChange,
- disableAnimation = false,
-}: InputWithBackProps) {
- const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null);
- const [buttonOffset, setButtonOffset] = useState(-60);
-
- const smoothTransition = {
- duration: disableAnimation ? 0 : 0.35,
- ease: [0.25, 0.1, 0.25, 1] as const,
- };
-
- useEffect(() => {
- if (containerRef) {
- const rect = containerRef.getBoundingClientRect();
- setButtonOffset(-rect.left - 48);
- }
- }, [containerRef]);
-
- return (
- <div ref={setContainerRef} className="relative w-full">
- <motion.div
- className="absolute top-1/2 left-0 z-10 -translate-y-1/2 cursor-pointer hover:opacity-75"
- initial={{
- x: isExpanded ? 0 : buttonOffset,
- opacity: isExpanded ? 1 : 0.5,
- }}
- animate={{
- x: isExpanded ? 0 : buttonOffset,
- opacity: isExpanded ? 1 : 0.5,
- }}
- transition={smoothTransition}
- onClick={() => setIsExpanded(!isExpanded)}
- >
- <Button
- variant="outline"
- className="bg-accent !size-9 rounded-full"
- >
- <ArrowLeft />
- </Button>
- </motion.div>
- <div
- className="relative flex-1"
- style={{ marginLeft: "0px", paddingLeft: "0px" }}
- >
- <motion.div
- className="relative"
- initial={{
- marginLeft: isExpanded ? 50 : 0,
- }}
- animate={{
- marginLeft: isExpanded ? 50 : 0,
- }}
- transition={smoothTransition}
- >
- <Search className="text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2" />
- <Input
- placeholder={placeholder}
- className="bg-accent w-full pl-9"
- value={value}
- onChange={(e) => onChange?.(e.target.value)}
- />
- </motion.div>
- </div>
- </div>
- );
-}
+"use client"; + +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { ArrowLeft, Search } from "lucide-react"; +import { motion } from "motion/react"; +import { useState, useEffect } from "react"; + +interface InputWithBackProps { + isExpanded: boolean; + setIsExpanded: (isExpanded: boolean) => void; + placeholder?: string; + value?: string; + onChange?: (value: string) => void; + disableAnimation?: boolean; +} + +export function InputWithBack({ + isExpanded, + setIsExpanded, + placeholder = "Search anything", + value, + onChange, + disableAnimation = false, +}: InputWithBackProps) { + const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null); + const [buttonOffset, setButtonOffset] = useState(-60); + + const smoothTransition = { + duration: disableAnimation ? 0 : 0.35, + ease: [0.25, 0.1, 0.25, 1] as const, + }; + + useEffect(() => { + if (containerRef) { + const rect = containerRef.getBoundingClientRect(); + setButtonOffset(-rect.left - 48); + } + }, [containerRef]); + + return ( + <div ref={setContainerRef} className="relative w-full"> + <motion.div + className="absolute top-1/2 left-0 z-10 -translate-y-1/2 cursor-pointer hover:opacity-75" + initial={{ + x: isExpanded ? 0 : buttonOffset, + opacity: isExpanded ? 1 : 0.5, + }} + animate={{ + x: isExpanded ? 0 : buttonOffset, + opacity: isExpanded ? 1 : 0.5, + }} + transition={smoothTransition} + onClick={() => setIsExpanded(!isExpanded)} + > + <Button variant="outline" className="bg-accent !size-9 rounded-full"> + <ArrowLeft /> + </Button> + </motion.div> + <div + className="relative flex-1" + style={{ marginLeft: "0px", paddingLeft: "0px" }} + > + <motion.div + className="relative" + initial={{ + marginLeft: isExpanded ? 50 : 0, + }} + animate={{ + marginLeft: isExpanded ? 50 : 0, + }} + transition={smoothTransition} + > + <Search className="text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2" /> + <Input + placeholder={placeholder} + className="bg-accent w-full pl-9" + value={value} + onChange={(e) => onChange?.(e.target.value)} + /> + </motion.div> + </div> + </div> + ); +} |
