Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ packages/imagekit-editor/dist/*
packages/imagekit-editor/*.tgz
.turbo
.yarn
builds
builds
packages/imagekit-editor/README.md
2 changes: 1 addition & 1 deletion examples/react-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@imagekit/editor": "1.2.0",
"@imagekit/editor": "2.0.0",
"@types/node": "^20.11.24",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
Expand Down
43 changes: 24 additions & 19 deletions examples/react-example/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import ReactDOM from "react-dom"
function App() {
const [open, setOpen] = React.useState(true)
const [editorProps, setEditorProps] =
React.useState<ImageKitEditorProps<{ requireSignedUrl: boolean }>>()
React.useState<
ImageKitEditorProps<{ requireSignedUrl: boolean; fileName: string }>
>()
const ref = React.useRef<ImageKitEditorRef>(null)

/**
Expand All @@ -28,18 +30,21 @@ function App() {
url: "https://ik.imagekit.io/v3sxk1svj/white%20BMW%20car%20on%20street.jpg",
metadata: {
requireSignedUrl: false,
fileName: "white BMW car on street.jpg",
},
},
{
url: "https://ik.imagekit.io/v3sxk1svj/Young%20Living%20Patchouili%20bot....jpg",
metadata: {
requireSignedUrl: false,
fileName: "Young Living Patchouili bot.jpg",
},
},
{
url: "https://ik.imagekit.io/v3sxk1svj/brown%20bear%20plush%20toy%20on%20whi....jpg?updatedAt=1760432666859",
metadata: {
requireSignedUrl: false,
fileName: "brown bear plush toy on white.jpg",
},
},
// ...Array.from({ length: 10000 }).map((_, i) => ({
Expand All @@ -57,26 +62,26 @@ function App() {
label: "Export",
icon: <Icon boxSize={"5"} as={PiDownload} />,
isVisible: true,
onClick: (images) => {
console.log(images)
onClick: (images, currentImage) => {
console.log(images, currentImage)
},
},
{
type: "menu",
label: "Export",
icon: <Icon boxSize={"5"} as={PiDownload} />,
isVisible: true,
options: [
{
label: "Export",
icon: <Icon boxSize={"5"} as={PiDownload} />,
isVisible: true,
onClick: (images) => {
console.log(images)
},
},
],
},
// {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this commented out menu option?

// type: "menu",
// label: "Export",
// icon: <Icon boxSize={"5"} as={PiDownload} />,
// isVisible: true,
// options: [
// {
// label: "Export",
// icon: <Icon boxSize={"5"} as={PiDownload} />,
// isVisible: true,
// onClick: (images) => {
// console.log(images)
// },
// },
// ],
// },
],
signer: async (request) => {
console.log(request)
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
"start": "turbo run start",
"build": "turbo run build",
"version": "yarn workspace @imagekit/editor version",
"package": "yarn build && yarn workspace @imagekit/editor pack --out ../../builds/imagekit-editor-%v.tgz",
"release": "yarn build && yarn workspace @imagekit/editor pack --out ../../builds/imagekit-editor-%v.tgz && yarn workspace @imagekit/editor publish",
"package": "yarn build && shx cp README.md ./packages/imagekit-editor/ && yarn workspace @imagekit/editor pack --out ../../builds/imagekit-editor-%v.tgz",
"release": "yarn build && shx cp README.md ./packages/imagekit-editor/ && yarn workspace @imagekit/editor pack --out ../../builds/imagekit-editor-%v.tgz && yarn workspace @imagekit/editor publish",
"prepare": "husky",
"lint": "biome ci"
},
"devDependencies": {
"@biomejs/biome": "2.1.1",
"husky": "^9.1.7",
"lint-staged": "^16.1.2",
"shx": "^0.4.0",
"turbo": "^2.0.1"
},
"packageManager": "[email protected]",
Expand Down
11 changes: 5 additions & 6 deletions packages/imagekit-editor-dev/src/ImageKitEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,27 @@ import merge from "lodash/merge"
import React, { forwardRef, useImperativeHandle } from "react"
import { EditorLayout, EditorWrapper } from "./components/editor"
import type { HeaderProps } from "./components/header"
import type { DEFAULT_FOCUS_OBJECTS } from "./schema"
import {
type FileElement,
type FocusObjects,
type InputFileElement,
type RequiredMetadata,
type Signer,
useEditorStore,
} from "./store"
import { themeOverrides } from "./theme"

export interface ImageKitEditorRef {
loadImage: (image: string | FileElement) => void
loadImages: (images: Array<string | FileElement>) => void
loadImage: (image: string | InputFileElement) => void
loadImages: (images: Array<string | InputFileElement>) => void
setCurrentImage: (imageSrc: string) => void
}

interface EditorProps<Metadata extends RequiredMetadata = RequiredMetadata> {
theme?: Dict
initialImages?: Array<string | FileElement<Metadata>>
initialImages?: Array<string | InputFileElement<Metadata>>
signer?: Signer<Metadata>
onAddImage?: () => void
exportOptions?: HeaderProps["exportOptions"]
exportOptions?: HeaderProps<Metadata>["exportOptions"]
focusObjects?: ReadonlyArray<FocusObjects>
onClose: (args: { dirty: boolean; destroy: () => void }) => void
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from "@chakra-ui/react"
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useVisibility } from "../hooks/useVisibility"
import { useEditorStore } from "../store"

export interface RetryableImageProps extends ImageProps {
maxRetries?: number
Expand Down Expand Up @@ -144,7 +145,8 @@ export default function RetryableImage(props: RetryableImageProps) {

const overlayActive = !!externalLoading || loading

const handleVisibleLoad = () => {
const handleVisibleLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
imgProps?.onLoad?.(event)
setLoading(false)
setError(null)
lastSuccessBaseRef.current = currentSrcBase
Expand Down
32 changes: 13 additions & 19 deletions packages/imagekit-editor-dev/src/components/editor/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { PiGridFour } from "@react-icons/all-files/pi/PiGridFour"
import { PiImageSquare } from "@react-icons/all-files/pi/PiImageSquare"
import { PiListBullets } from "@react-icons/all-files/pi/PiListBullets"
import { type FC, useEffect, useState } from "react"
import { type FC, useMemo } from "react"
import { useEditorStore } from "../../store"

interface ActionBarProps {
Expand All @@ -33,25 +33,19 @@ export const ActionBar: FC<ActionBarProps> = ({
gridImageSize,
setGridImageSize,
}) => {
const { currentImage, showOriginal, setShowOriginal } = useEditorStore()
const {
currentImage,
imageList,
originalImageList,
showOriginal,
setShowOriginal,
} = useEditorStore()

const [imageDimensions, setImageDimensions] = useState<{
width: number
height: number
} | null>(null)

useEffect(() => {
if (currentImage) {
const img = new Image()
img.onload = () => {
setImageDimensions({
width: img.naturalWidth,
height: img.naturalHeight,
})
}
img.src = currentImage
}
}, [currentImage])
const imageDimensions = useMemo(() => {
const idx = imageList.findIndex((img) => img === currentImage)
if (idx === -1) return null
return originalImageList[idx].imageDimensions
}, [currentImage, imageList, originalImageList])

return (
<Box
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const GridView: FC<GridViewProps> = ({ imageSize, onAddImage }) => {
originalImageList,
signingImages,
removeImage,
setImageDimensions,
} = useEditorStore()
return (
<Flex
Expand Down Expand Up @@ -157,6 +158,12 @@ export const GridView: FC<GridViewProps> = ({ imageSize, onAddImage }) => {
</Center>
}
isLoading={isSigning}
onLoad={(event) => {
setImageDimensions(originalImageList[index]!.url, {
width: event.currentTarget.naturalWidth,
height: event.currentTarget.naturalHeight,
})
}}
/>
</Box>
)}
Expand Down
11 changes: 11 additions & 0 deletions packages/imagekit-editor-dev/src/components/editor/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const ListView: FC<ListViewProps> = ({ onAddImage }) => {
imageList,
originalImageList,
signingImages,
setImageDimensions,
_internalState,
} = useEditorStore()

Expand Down Expand Up @@ -53,6 +54,16 @@ export const ListView: FC<ListViewProps> = ({ onAddImage }) => {
const originalUrl = originalImageList[idx]?.url
return originalUrl ? signingImages[originalUrl] : false
})()}
onLoad={(event) => {
console.log(event)
if (!currentImage) return
const idx = imageList.findIndex((img) => img === currentImage)
if (idx === -1) return
setImageDimensions(originalImageList[idx]!.url, {
width: event.currentTarget.naturalWidth,
height: event.currentTarget.naturalHeight,
})
}}
/>
</Flex>
</Flex>
Expand Down
59 changes: 49 additions & 10 deletions packages/imagekit-editor-dev/src/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,46 @@ import { PiImageSquare } from "@react-icons/all-files/pi/PiImageSquare"
import { PiImagesSquare } from "@react-icons/all-files/pi/PiImagesSquare"
import { PiX } from "@react-icons/all-files/pi/PiX"
import React, { useMemo } from "react"
import { useEditorStore } from "../../store"
import {
type FileElement,
type RequiredMetadata,
useEditorStore,
} from "../../store"

interface ExportOptionButton {
interface ExportOptionButton<
Metadata extends RequiredMetadata = RequiredMetadata,
> {
type: "button"
label: string
icon?: React.ReactElement
isVisible: boolean | ((images: string[], currentImage?: string) => boolean)
onClick: (images: string[], currentImage?: string) => void
onClick: (
images: { url: string; file: FileElement<Metadata> }[],
currentImage?: { url: string; file: FileElement<Metadata> },
) => void
}

interface ExportOptionMenu {
interface ExportOptionMenu<
Metadata extends RequiredMetadata = RequiredMetadata,
> {
type: "menu"
label: string
icon?: React.ReactElement
isVisible: boolean | ((images: string[], currentImage?: string) => boolean)
options: Array<Omit<ExportOptionButton, "type">>
options: Array<Omit<ExportOptionButton<Metadata>, "type">>
}

export interface HeaderProps {
export interface HeaderProps<
Metadata extends RequiredMetadata = RequiredMetadata,
> {
onClose: () => void
exportOptions?: Array<ExportOptionButton | ExportOptionMenu>
exportOptions?: Array<
ExportOptionButton<Metadata> | ExportOptionMenu<Metadata>
>
}

export const Header = ({ onClose, exportOptions }: HeaderProps) => {
const { imageList, currentImage } = useEditorStore()
const { imageList, originalImageList, currentImage } = useEditorStore()

const headerText = useMemo(() => {
if (imageList.length === 1) {
Expand Down Expand Up @@ -92,7 +107,19 @@ export const Header = ({ onClose, exportOptions }: HeaderProps) => {
borderRadius="0"
px="8"
size="sm"
onClick={() => exportOption.onClick(imageList, currentImage)}
onClick={() => {
const images = imageList.map((image, index) => ({
url: image,
file: originalImageList[index],
}))
const cImage = images.find(
(image) => image.url === currentImage,
)
exportOption.onClick(images, {
url: cImage!.url,
file: cImage!.file,
})
}}
>
{exportOption.label}
</Button>
Expand Down Expand Up @@ -121,7 +148,19 @@ export const Header = ({ onClose, exportOptions }: HeaderProps) => {
.map((option) => (
<MenuItem
key={`export-menu-option-${option.label}`}
onClick={() => option.onClick(imageList, currentImage)}
onClick={() => {
const images = imageList.map((image, index) => ({
url: image,
file: originalImageList[index],
}))
const cImage = images.find(
(image) => image.url === currentImage,
)
option.onClick(images, {
url: cImage!.url,
file: cImage!.file,
})
}}
>
{option.label}
</MenuItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const Toolbar: FC<ToolbarProps> = ({ onAddImage, onSelectImage }) => {
signingImages,
setCurrentImage,
removeImage,
setImageDimensions,
_internalState,
} = useEditorStore()

Expand Down Expand Up @@ -204,6 +205,12 @@ export const Toolbar: FC<ToolbarProps> = ({ onAddImage, onSelectImage }) => {
</Center>
}
isLoading={isSigning}
onLoad={(event) => {
setImageDimensions(originalImageList[index]!.url, {
width: event.currentTarget.naturalWidth,
height: event.currentTarget.naturalHeight,
})
}}
/>
</Box>
)}
Expand Down
Loading