Skip to content

Commit d388f7d

Browse files
authored
Merge pull request #2 from imagekit-developer/IK-2396
2 parents 13a3202 + 1351eea commit d388f7d

File tree

10 files changed

+346
-47
lines changed

10 files changed

+346
-47
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export default ImageEditor;
130130
| `signer` | `Signer` || Function to generate signed URLs for private images |
131131
| `onAddImage` | `() => void` || Callback function for adding new images |
132132
| `exportOptions` | `ExportOptions` || Configuration for export functionality |
133+
| `focusObjects` | `string[]` || Custom list of selectable focus objects for object-based focus |
133134

134135
### ImageKitEditor Ref Methods
135136

@@ -181,6 +182,19 @@ exportOptions={{
181182
}}
182183
```
183184

185+
### Focus Objects
186+
187+
You can override the list of selectable focus objects used when a transformation's focus is set to "Object" (e.g., Maintain Aspect Ratio, Forced Crop, Extract). If not provided, the editor defaults to ImageKit's supported objects (e.g., person, bicycle, car, dog, etc.).
188+
189+
See the supported object list in the ImageKit docs: https://imagekit.io/docs/image-resize-and-crop#supported-object-list
190+
191+
```tsx
192+
<ImageKitEditor
193+
focusObjects={["person", "cat", "car", "customObject"]}
194+
// ... other props
195+
/>
196+
```
197+
184198
### File Element Interface
185199

186200
For advanced use cases with metadata and signed URLs:

examples/react-example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@imagekit/editor": "1.0.0",
6+
"@imagekit/editor": "1.1.0",
77
"@types/node": "^20.11.24",
88
"@types/react": "^17.0.2",
99
"@types/react-dom": "^17.0.2",

examples/react-example/src/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ function App() {
3636
requireSignedUrl: false,
3737
},
3838
},
39+
{
40+
url: "https://ik.imagekit.io/v3sxk1svj/brown%20bear%20plush%20toy%20on%20whi....jpg?updatedAt=1760432666859",
41+
metadata: {
42+
requireSignedUrl: false,
43+
},
44+
},
3945
// ...Array.from({ length: 10000 }).map((_, i) => ({
4046
// url: `https://ik.imagekit.io/v3sxk1svj/placeholder.jpg?updatedAt=${Date.now()}&v=${i}`,
4147
// metadata: {

packages/imagekit-editor-dev/src/ImageKitEditor.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import merge from "lodash/merge"
44
import React, { forwardRef, useImperativeHandle } from "react"
55
import { EditorLayout, EditorWrapper } from "./components/editor"
66
import type { HeaderProps } from "./components/header"
7+
import type { DEFAULT_FOCUS_OBJECTS } from "./schema"
78
import {
89
type FileElement,
10+
type FocusObjects,
911
type RequiredMetadata,
1012
type Signer,
1113
useEditorStore,
@@ -24,15 +26,15 @@ interface EditorProps<Metadata extends RequiredMetadata = RequiredMetadata> {
2426
signer?: Signer<Metadata>
2527
onAddImage?: () => void
2628
exportOptions?: HeaderProps["exportOptions"]
27-
29+
focusObjects?: ReadonlyArray<FocusObjects>
2830
onClose: (args: { dirty: boolean; destroy: () => void }) => void
2931
}
3032

3133
function ImageKitEditorImpl<M extends RequiredMetadata>(
3234
props: EditorProps<M>,
3335
ref: React.Ref<ImageKitEditorRef>,
3436
) {
35-
const { theme, initialImages, signer } = props
37+
const { theme, initialImages, signer, focusObjects } = props
3638
const {
3739
addImage,
3840
addImages,
@@ -62,8 +64,9 @@ function ImageKitEditorImpl<M extends RequiredMetadata>(
6264
initialize({
6365
imageList: initialImages,
6466
signer,
67+
focusObjects,
6568
})
66-
}, [initialImages, signer, initialize])
69+
}, [initialImages, signer, focusObjects, initialize])
6770

6871
useImperativeHandle(
6972
ref,

packages/imagekit-editor-dev/src/components/sidebar/transformation-config-sidebar.tsx

Lines changed: 71 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,14 @@ import { PiArrowLeft } from "@react-icons/all-files/pi/PiArrowLeft"
3737
import { PiCaretDown } from "@react-icons/all-files/pi/PiCaretDown"
3838
import { PiInfo } from "@react-icons/all-files/pi/PiInfo"
3939
import { PiX } from "@react-icons/all-files/pi/PiX"
40+
import startCase from "lodash/startCase"
4041
import { useEffect, useMemo } from "react"
4142
import { Controller, type SubmitHandler, useForm } from "react-hook-form"
4243
import Select from "react-select"
4344
import CreateableSelect from "react-select/creatable"
4445
import { z } from "zod/v3"
4546
import type { TransformationField } from "../../schema"
46-
import { transformationSchema } from "../../schema"
47+
import { DEFAULT_FOCUS_OBJECTS, transformationSchema } from "../../schema"
4748
import { useEditorStore } from "../../store"
4849
import { isStepAligned } from "../../utils"
4950
import AnchorField from "../common/AnchorField"
@@ -61,6 +62,7 @@ export const TransformationConfigSidebar: React.FC = () => {
6162
addTransformation,
6263
updateTransformation,
6364
imageList,
65+
focusObjects,
6466
_setSidebarState,
6567
_internalState,
6668
_setTransformationToEdit,
@@ -296,40 +298,74 @@ export const TransformationConfigSidebar: React.FC = () => {
296298
<Controller
297299
name={field.name}
298300
control={control}
299-
render={({ field: controllerField }) => (
300-
<Select
301-
id={field.name}
302-
placeholder="Select"
303-
menuPlacement="auto"
304-
options={field.fieldProps?.options?.map((option) => ({
305-
value: option.value,
306-
label: option.label,
307-
}))}
308-
value={field.fieldProps?.options?.find(
309-
(option) => option.value === controllerField.value,
310-
)}
311-
onChange={(selectedOption) =>
312-
controllerField.onChange(selectedOption?.value)
313-
}
314-
onBlur={controllerField.onBlur}
315-
styles={{
316-
control: (base) => ({
317-
...base,
318-
fontSize: "12px",
319-
minHeight: "32px",
320-
borderColor: "#E2E8F0",
321-
}),
322-
menu: (base) => ({
323-
...base,
324-
zIndex: 10,
325-
}),
326-
option: (base) => ({
327-
...base,
328-
fontSize: "12px",
329-
}),
330-
}}
331-
/>
332-
)}
301+
render={({ field: controllerField }) => {
302+
// For focusObject field, use focusObjects from store or default list
303+
const selectOptions =
304+
field.name === "focusObject"
305+
? (focusObjects || DEFAULT_FOCUS_OBJECTS).map(
306+
(obj) => ({
307+
value: obj,
308+
label: startCase(obj),
309+
}),
310+
)
311+
: field.fieldProps?.options?.map((option) => ({
312+
value: option.value,
313+
label: option.label,
314+
}))
315+
316+
const isCreatable = field.fieldProps?.isCreatable === true
317+
const SelectComponent = isCreatable
318+
? CreateableSelect
319+
: Select
320+
321+
// For creatable selects, find the value in options or create a custom one
322+
const selectedValue = isCreatable
323+
? selectOptions?.find(
324+
(option) => option.value === controllerField.value,
325+
) ||
326+
(controllerField.value
327+
? {
328+
value: controllerField.value as string,
329+
label: startCase(controllerField.value as string),
330+
}
331+
: null)
332+
: selectOptions?.find(
333+
(option) => option.value === controllerField.value,
334+
)
335+
336+
return (
337+
<SelectComponent
338+
id={field.name}
339+
formatCreateLabel={(inputValue) =>
340+
`Use "${inputValue}"`
341+
}
342+
placeholder="Select"
343+
menuPlacement="auto"
344+
options={selectOptions}
345+
value={selectedValue}
346+
onChange={(selectedOption) =>
347+
controllerField.onChange(selectedOption?.value)
348+
}
349+
onBlur={controllerField.onBlur}
350+
styles={{
351+
control: (base) => ({
352+
...base,
353+
fontSize: "12px",
354+
minHeight: "32px",
355+
borderColor: "#E2E8F0",
356+
}),
357+
menu: (base) => ({
358+
...base,
359+
zIndex: 10,
360+
}),
361+
option: (base) => ({
362+
...base,
363+
fontSize: "12px",
364+
}),
365+
}}
366+
/>
367+
)
368+
}}
333369
/>
334370
) : null}
335371
{field.fieldType === "select-creatable" ? (
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export type { ImageKitEditorProps, ImageKitEditorRef } from "./ImageKitEditor"
22
export { ImageKitEditor } from "./ImageKitEditor"
3+
export { DEFAULT_FOCUS_OBJECTS } from "./schema"
34
export type { FileElement, Signer } from "./store"

0 commit comments

Comments
 (0)