Skip to content

Commit

Permalink
refactor: more cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
QuiiBz committed Dec 27, 2023
1 parent a26d13b commit 6677ebc
Show file tree
Hide file tree
Showing 24 changed files with 149 additions and 96 deletions.
13 changes: 10 additions & 3 deletions apps/dashboard/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
'use client'
import { OgPlayground } from "../components/OgPlayground";
import { OgEditor } from "../components/OgEditor";
import { createElementId } from "../lib/elements";
import type { OGElement } from "../lib/types";

/**
* The initial elements to render in the editor.
*
* It only contains a single element, a white background that
* takes the entire width and height of the editor.
*/
const initialElements: OGElement[] = [
{
id: Math.random().toString(),
id: createElementId(),
tag: 'div',
x: 0,
y: 0,
Expand All @@ -19,6 +26,6 @@ const initialElements: OGElement[] = [

export default function Home() {
return (
<OgPlayground height={630} initialElements={initialElements} width={1200} />
<OgEditor height={630} initialElements={initialElements} width={1200} />
)
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
import type { ReactElement } from "react"
import type { OGElement } from "../lib/types"
import { createElement } from "../lib/elements"
import { TextIcon } from "./icons/TextIcon"
import { CircleIcon } from "./icons/CircleIcon"
import { ImageIcon } from "./icons/ImageIcon"
import { useOg } from "./OgPlayground"
import { useOg } from "./OgEditor"
import { BoxIcon } from "./icons/BoxIcon"
import { MagicWandIcon } from "./icons/MagicWandIcon"

interface ToolbarButtonProps {
element: OGElement
element: Partial<OGElement>
children: ReactElement
}

function ToolbarButton({ element, children }: ToolbarButtonProps) {
const { addElement } = useOg()

return (
<button className="p-2 text-gray-600 hover:text-gray-900" onClick={() => { addElement(element); }} type="button">
<button className="p-2 text-gray-600 hover:text-gray-900" onClick={() => { addElement(createElement(element)); }} type="button">
{children}
</button>
)
}

export function PlaygroundToolbar() {
export function EditorToolbar() {
return (
<div className="rounded-md border border-gray-100 bg-white z-10 flex flex-row items-center">
<ToolbarButton element={{
tag: 'p',
id: String(Math.random()),
x: (1200 - 100) / 2,
y: (630 - 50) / 2,
width: 100,
height: 50,
visible: true,
Expand All @@ -48,9 +46,6 @@ export function PlaygroundToolbar() {
<div className="w-[1px] h-4 bg-gray-100" />
<ToolbarButton element={{
tag: 'div',
id: String(Math.random()),
x: (1200 - 200) / 2,
y: (630 - 200) / 2,
width: 200,
height: 200,
visible: true,
Expand All @@ -63,9 +58,6 @@ export function PlaygroundToolbar() {
<div className="w-[1px] h-4 bg-gray-100" />
<ToolbarButton element={{
tag: 'div',
id: String(Math.random()),
x: (1200 - 150) / 2,
y: (630 - 150) / 2,
width: 150,
height: 150,
visible: true,
Expand All @@ -79,9 +71,6 @@ export function PlaygroundToolbar() {
<div className="w-[1px] h-4 bg-gray-100" />
<ToolbarButton element={{
tag: 'div',
id: String(Math.random()),
x: (1200 - 200) / 2,
y: (630 - 150) / 2,
width: 200,
height: 150,
visible: true,
Expand All @@ -96,9 +85,6 @@ export function PlaygroundToolbar() {
<div className="w-[1px] h-4 bg-gray-100" />
<ToolbarButton element={{
tag: 'span',
id: String(Math.random()),
x: (1200 - 312) / 2,
y: (630 - 50) / 2,
width: 312,
height: 50,
visible: true,
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/Element.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { CSSProperties } from "react";
import { useEffect, useMemo, useRef, useState } from "react"
import type { OGElement } from "../lib/types";
import { hexToRgba } from "../lib/colors";
import { useOg } from "./OgPlayground"
import { useOg } from "./OgEditor"

interface ElementProps {
element: OGElement
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/ElementTab.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSortable } from "@dnd-kit/sortable"
import { CSS } from '@dnd-kit/utilities';
import type { OGElement } from "../lib/types";
import { useOg } from "./OgPlayground"
import { useOg } from "./OgEditor"
import { BoxIcon } from "./icons/BoxIcon"
import { CircleIcon } from "./icons/CircleIcon"
import { ImageIcon } from "./icons/ImageIcon"
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/LeftPanel/ElementRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { OGElement } from "../../lib/types";
import { NotVisibleIcon } from "../icons/NotVisibleIcon"
import { TextIcon } from "../icons/TextIcon"
import { VisibleIcon } from "../icons/VisibleIcon"
import { useOg } from "../OgPlayground"
import { useOg } from "../OgEditor"
import { BoxIcon } from "../icons/BoxIcon"
import { CircleIcon } from "../icons/CircleIcon"
import { ImageIcon } from "../icons/ImageIcon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { DragEndEvent } from "@dnd-kit/core";
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
import { SortableContext, arrayMove, sortableKeyboardCoordinates, verticalListSortingStrategy } from "@dnd-kit/sortable";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import { ElementRow } from "./ElementRow";

export function ElementsSection() {
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/LeftPanel/ExportSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { flushSync } from "react-dom";
import { Button } from "../Button";
import { PngIcon } from "../icons/PngIcon";
import { SvgIcon } from "../icons/SvgIcon";
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import { domToReactLike, exportToPng, exportToSvg } from "../../lib/export";

export function ExportSection() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Button } from "../Button";
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import { RedoIcon } from "../icons/RedoIcon";
import { UndoIcon } from "../icons/UndoIcon";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import type { RefObject } from "react";
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import type { OGElement } from "../lib/types";
import { createElementId } from "../lib/elements";
import { maybeLoadFont } from "../lib/fonts";
import { Element } from './Element'
import { RightPanel } from "./RightPanel";
import { LeftPanel } from "./LeftPanel";
import { PlaygroundToolbar } from "./PlaygroundToolbar";

function maybeLoadFont(font: string, weight: number) {
const id = `font-${font}-${weight}`

if (document.getElementById(id)) {
return
}

const link = document.createElement('link')
link.id = id
link.rel = 'stylesheet'
link.href = `https://fonts.bunny.net/css?family=${font.toLowerCase().replace(' ', '-')}:${weight}`
document.head.appendChild(link)
}
import { EditorToolbar } from "./EditorToolbar";

interface OgContextType {
elements: OGElement[]
Expand Down Expand Up @@ -55,7 +43,7 @@ let editIndex = -1

let elementToCopy: OGElement | undefined

export function OgPlayground({ initialElements, width, height }: OgProviderProps) {
export function OgEditor({ initialElements, width, height }: OgProviderProps) {
const [selectedElement, setRealSelectedElement] = useState<string | null>(null)
const [elements, setRealElements] = useState<OGElement[]>(() => {
const item = typeof localStorage !== 'undefined' ? localStorage.getItem('elements') : undefined
Expand Down Expand Up @@ -209,7 +197,7 @@ export function OgPlayground({ initialElements, width, height }: OgProviderProps
...elementToCopy,
x: elementToCopy.x + 10,
y: elementToCopy.y + 10,
id: String(Math.random()),
id: createElementId(),
})
}
}
Expand Down Expand Up @@ -258,7 +246,7 @@ export function OgPlayground({ initialElements, width, height }: OgProviderProps
</div>
</div>
<div className="border border-gray-100 absolute pointer-events-none transform translate-y-[32px]" style={{ width, height }} />
<PlaygroundToolbar />
<EditorToolbar />
</div>
<div className="w-[300px] h-screen flex flex-col border-l border-gray-100 shadow-lg shadow-gray-100 bg-white z-10">
<RightPanel />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useOg } from "../OgPlayground";
import { Input, Select } from '../Labels'
import { useOg } from "../OgEditor";
import { Input } from '../forms/Input'
import { Select } from '../forms/Select'
import type { OGElement } from "../../lib/types";
import { ColorIcon } from "../icons/ColorIcon";
import { DeleteIcon } from "../icons/DeleteIcon";
Expand Down
5 changes: 3 additions & 2 deletions apps/dashboard/src/components/RightPanel/BorderSection.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import type { OGElement } from "../../lib/types";
import { DeleteIcon } from "../icons/DeleteIcon";
import { AddIcon } from "../icons/AddIcon";
import { ColorIcon } from "../icons/ColorIcon";
import { Input, Select } from "../Labels";
import { Input } from '../forms/Input'
import { Select } from '../forms/Select'
import { WidthIcon } from "../icons/WidthIcon";
import { BorderStyleIcon } from "../icons/BorderStyleIcon";

Expand Down
16 changes: 10 additions & 6 deletions apps/dashboard/src/components/RightPanel/FontSection.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useOg } from "../OgPlayground";
import { Input, Select } from '../Labels'
import { useOg } from "../OgEditor";
import { Input } from '../forms/Input'
import { Select } from '../forms/Select'
import type { OGElement } from "../../lib/types";
import { TextIcon } from "../icons/TextIcon";
import { FONTS, WEIGHTS } from "../../lib/fonts";
import type { Font } from "../../lib/fonts";
import { FONTS, FONT_WEIGHTS } from "../../lib/fonts";
import { BoldIcon } from "../icons/BoldIcon";
import { FontSizeIcon } from "../icons/FontSizeIcon";
import { ColorIcon } from "../icons/ColorIcon";
Expand All @@ -26,10 +28,12 @@ export function FontSection({ selectedElement }: FontSectionProps) {
<p className="text-xs text-gray-600">Font</p>
<div className="grid grid-cols-2 gap-2">
<Select onChange={value => {
const font = value as unknown as Font

updateElement({
...selectedElement,
fontFamily: value as unknown as typeof FONTS[number],
fontWeight: WEIGHTS[value as unknown as typeof FONTS[number]].includes(selectedElement.fontWeight) ? selectedElement.fontWeight : 400,
fontFamily: font,
fontWeight: FONT_WEIGHTS[font].includes(selectedElement.fontWeight) ? selectedElement.fontWeight : 400,
});
}} value={selectedElement.fontFamily} values={[...FONTS]}>
<TextIcon />
Expand All @@ -39,7 +43,7 @@ export function FontSection({ selectedElement }: FontSectionProps) {
...selectedElement,
fontWeight: Number(value),
});
}} value={String(selectedElement.fontWeight)} values={WEIGHTS[selectedElement.fontFamily].map(String)}>
}} value={String(selectedElement.fontWeight)} values={FONT_WEIGHTS[selectedElement.fontFamily].map(String)}>
<BoldIcon />
</Select>
<Input onChange={value => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { OGElement } from "../../lib/types";
import { Input } from "../Labels";
import { useOg } from "../OgPlayground";
import { Input } from '../forms/Input'
import { useOg } from "../OgEditor";
import { CornerIcon } from "../icons/CornerIcon";
import { OpacityIcon } from "../icons/OpacityIcon";
import { RotateIcon } from "../icons/RotateIcon";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { OGElement } from "../../lib/types";
import { Button } from "../Button";
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import { DeleteIcon } from "../icons/DeleteIcon";

interface ModificationsSectionProps {
Expand Down
4 changes: 2 additions & 2 deletions apps/dashboard/src/components/RightPanel/ShadowSection.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import type { OGElement } from "../../lib/types";
import { DeleteIcon } from "../icons/DeleteIcon";
import { AddIcon } from "../icons/AddIcon";
import { ColorIcon } from "../icons/ColorIcon";
import { Input } from "../Labels";
import { Input } from '../forms/Input'
import { WidthIcon } from "../icons/WidthIcon";
import { GradientIcon } from "../icons/GradientIcon";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useOg } from "../OgPlayground";
import { Input } from '../Labels'
import { useOg } from "../OgEditor";
import { Input } from '../forms/Input'
import type { OGElement } from "../../lib/types";

interface SizePositionSectionProps {
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/RightPanel/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useOg } from "../OgPlayground";
import { useOg } from "../OgEditor";
import { BackgroundSection } from "./BackgroundSection";
import { BorderSection } from "./BorderSection";
import { FontSection } from "./FontSection";
Expand Down
19 changes: 19 additions & 0 deletions apps/dashboard/src/components/forms/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ReactNode } from "react"

interface ButtonProps {
icon?: ReactNode
variant?: 'danger'
onClick: () => void
isLoading?: boolean
className?: string
children: ReactNode
}

export function Button({ icon, variant, onClick, isLoading, className, children }: ButtonProps) {
return (
<button className={`flex gap-3 items-center px-3 py-1 border rounded ${variant === 'danger' ? 'text-red-900 bg-red-50 border-red-200 hover:border-red-300' : 'text-gray-900 bg-gray-50 border-gray-200 hover:border-gray-300'} ${isLoading ? 'cursor-not-allowed opacity-60' : ''} ${className}`} onClick={isLoading ? undefined : onClick} type="button">
{icon}
{children}
</button>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,3 @@ export function Input<Type extends InputType>({ type, value, min, max, suffix, o
)
}

interface SelectProps {
value: string
values: string[]
onChange: (value: string) => void
children: ReactNode
}

export function Select({ value, values, onChange, children }: SelectProps) {
const id = useId()

return (
<div className="border border-gray-100 rounded pl-1.5 bg-gray-100 flex items-center gap-1 hover:border-gray-300">
<label className="text-gray-700 text-sm whitespace-nowrap" htmlFor={id}>
{children}
</label>
<select
className="px-1 py-0.5 text-gray-900 rounded w-full h-full focus:outline-blue-500"
defaultValue={value}
id={id}
onChange={event => { onChange(event.target.value); }}
>
{values.map(currentValue => (
<option key={currentValue} value={currentValue}>{currentValue}</option>
))}
</select>
</div>
)
}
Loading

0 comments on commit 6677ebc

Please sign in to comment.