Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
1a67bca
Support negative values in position x and y for image and text layer
SwarnimDoegar Jan 16, 2026
560cdba
Add support for duplicate and rename in L1 sidebar
SwarnimDoegar Jan 19, 2026
5ad6ab7
feat: add trim transformation support
piyushryn Jan 20, 2026
645fd1d
Add advanced padding input support
SwarnimDoegar Jan 20, 2026
117c4a7
Remove unwanted console logs
SwarnimDoegar Jan 20, 2026
5a13741
Fix Icon Button in padding input
SwarnimDoegar Jan 21, 2026
7663b96
Add focus support in image overlay
SwarnimDoegar Jan 21, 2026
6293e83
fix: update trim transformation schema and default values for improve…
piyushryn Jan 21, 2026
d7fdd83
feat: add color replace transformation with validation and integratio…
piyushryn Jan 22, 2026
937b21d
Add tooltip and better UX in padding input
SwarnimDoegar Jan 22, 2026
c36c4dd
Add zoom support with fo face and object in base image and image overlay
SwarnimDoegar Jan 22, 2026
56834fe
Fix zoom input step size and default value
SwarnimDoegar Jan 23, 2026
90c2b1b
Fix padding toggle button style
SwarnimDoegar Jan 23, 2026
bc2da35
feat: add border and sharpen transformations to image processing sche…
piyushryn Jan 27, 2026
0cac58c
refactor: improve transformation schema for border, trim, and sharpen…
piyushryn Jan 27, 2026
a5e7fef
Update packages/imagekit-editor-dev/src/schema/index.ts
piyushryn Jan 27, 2026
cc2aeb3
Initial plan
Copilot Jan 27, 2026
87a681a
Update packages/imagekit-editor-dev/src/components/common/ColorPicker…
piyushryn Jan 27, 2026
d04269d
fix: correct formatting for items array opening bracket at line 1855
Copilot Jan 27, 2026
6996dd3
Merge pull request #7 from imagekit-developer/copilot/sub-pr-6
piyushryn Jan 27, 2026
85364a6
Remove unused imports in PaddingInput component
SwarnimDoegar Jan 28, 2026
2054687
Add gradient effect support in base and overlay images
SwarnimDoegar Jan 28, 2026
9ce5aa2
Improve renaming mode UX
SwarnimDoegar Jan 28, 2026
f439563
Improve Gradient Picker implementation
SwarnimDoegar Jan 28, 2026
e00059e
Add shadow and grayscale support in image layer
SwarnimDoegar Jan 28, 2026
16ec40a
refactor: update borderWidth validation in transformation schema to u…
piyushryn Jan 28, 2026
825b3c4
feat: add unsharpen mask transformation to image processing schema wi…
piyushryn Jan 28, 2026
c0fa40b
feat: integrate unsharpen mask transformation into overlay processing…
piyushryn Jan 29, 2026
a132fb9
feat: enhance transformation schema with new lineHeight and dpr optio…
piyushryn Jan 30, 2026
a878f98
Retain Padding Input Value
SwarnimDoegar Jan 30, 2026
7d21805
Retain Zoom Input Value
SwarnimDoegar Jan 30, 2026
8839de5
fix: update trimEnabled transformation property to disable trimming a…
piyushryn Jan 30, 2026
415b18a
Add Distortion support in base and overlay image
SwarnimDoegar Jan 30, 2026
7e3c44f
Refactor padding input
SwarnimDoegar Jan 30, 2026
3fb5b78
Add per corner radius support in base and overlay image
SwarnimDoegar Jan 30, 2026
06dee02
fix: color picker alpha behavior consistent with the downstream service
hrhv Feb 2, 2026
9ebb3ab
chore: added .cursor to gitignore
hrhv Feb 2, 2026
df03ba3
Merge pull request #5 from SwarnimDoegar/IK-2461-improvements
hrhv Feb 2, 2026
cea4543
Merge remote-tracking branch 'origin/IK-2461/enhancements' into harsh…
hrhv Feb 2, 2026
4f3c7ed
Merge branch 'IK-2461/enhancements' of github.com:imagekit-developer/…
piyushryn Feb 3, 2026
5508601
Merge pull request #6 from imagekit-developer/piyush/enhancements
hrhv Feb 3, 2026
db20f7e
Merge remote-tracking branch 'origin/IK-2461/enhancements' into harsh…
hrhv Feb 3, 2026
4014c00
Improved distort perspective implementation
SwarnimDoegar Feb 4, 2026
151e4f8
Merge branch 'IK-2461/enhancements' into IK-2461-improvements
SwarnimDoegar Feb 5, 2026
63b7d03
chore: Add VSCode extension recommendations for TypeScript and Biome
ahnv Feb 6, 2026
a25aae4
chore(workflows): Add lint step to CI and publish
ahnv Feb 6, 2026
50b44b5
Fix linting issues
SwarnimDoegar Feb 6, 2026
199d437
Fix type and linting issues
SwarnimDoegar Feb 9, 2026
6f761cd
Fix more linting errors
SwarnimDoegar Feb 9, 2026
9e33b57
Fixed formatting issues
SwarnimDoegar Feb 9, 2026
ae16d31
Do not use structured clone
SwarnimDoegar Feb 11, 2026
b99e7c9
Fix formatting
SwarnimDoegar Feb 11, 2026
2deab3d
Move to strict type
SwarnimDoegar Feb 11, 2026
0e59f47
Merge pull request #8 from SwarnimDoegar/IK-2461-improvements
hrhv Feb 13, 2026
ccb8520
feat: complete ux revamp for backgrounds
hrhv Feb 16, 2026
85a2d14
feat: resize and crop mode revamp ux
hrhv Feb 16, 2026
bee43f2
Merge branch 'harshit/enhancements' into IK-2461/enhancements
hrhv Feb 16, 2026
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 .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
- name: 📦 Install deps, build, pack
run: |
yarn install --frozen-lockfile
yarn lint
yarn package
env:
CI: true
Expand All @@ -33,4 +34,4 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: imagekit-editor-package
path: builds/imagekit-editor-*.tgz
path: builds/imagekit-editor-*.tgz
6 changes: 4 additions & 2 deletions .github/workflows/node-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ jobs:
with:
node-version: 20.x
cache: yarn
registry-url: 'https://registry.npmjs.org'
registry-url: "https://registry.npmjs.org"

- name: Build and Publish
run: |
yarn install --frozen-lockfile

yarn lint

yarn build

npm whoami
Expand All @@ -48,4 +50,4 @@ jobs:

env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
CI: true
CI: true
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ packages/imagekit-editor/*.tgz
.turbo
.yarn
builds
packages/imagekit-editor/README.md
packages/imagekit-editor/README.md
.cursor
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["ms-vscode.vscode-typescript-next", "biomejs.biome"]
}
10 changes: 7 additions & 3 deletions packages/imagekit-editor-dev/src/components/RetryableImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ 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 @@ -105,11 +104,12 @@ export default function RetryableImage(props: RetryableImageProps) {
setProbing(true)
}, [currentSrcBase, src])

// biome-ignore lint/correctness/useExhaustiveDependencies: <not needed>
useEffect(() => {
if (!src) return
if (lazy && !visible) return
setAttempt(0)
beginLoad(0)
beginLoad()
}, [src, visible, lazy])

const scheduleRetry = useCallback(() => {
Expand Down Expand Up @@ -156,7 +156,11 @@ export default function RetryableImage(props: RetryableImageProps) {
}

return (
<Box ref={rootRef as any} position="relative" display="inline-block">
<Box
ref={rootRef as React.RefObject<HTMLDivElement>}
position="relative"
display="inline-block"
>
{error ? (
<Center
w={imgProps.width || "full"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ const AnchorField: React.FC<AnchorFieldProps> = ({
minWidth="0"
p="0"
isDisabled={!positions.includes(position.value)}
onClick={() => onChange(position.value)}
onClick={() => {
if (value === position.value) {
return onChange("")
}
onChange(position.value)
}}
borderRadius="md"
border={
value === position.value
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
type As,
Box,
Flex,
HStack,
Expand Down Expand Up @@ -67,6 +68,7 @@ export const CheckboxCardField: React.FC<CheckboxCardFieldProps> = ({
}

return (
// biome-ignore lint/a11y/useSemanticElements: <role used to concur to chakra standard>
<HStack
as="fieldset"
id={id}
Expand All @@ -85,6 +87,7 @@ export const CheckboxCardField: React.FC<CheckboxCardFieldProps> = ({
const isChecked = value.includes(opt.value)
const disabled = opt.isDisabled || (!isChecked && isMaxed)
return (
// biome-ignore lint/a11y/useSemanticElements: <role used to concur to chakra standard>
<Box
key={opt.value}
data-checkbox-card
Expand Down Expand Up @@ -114,7 +117,7 @@ export const CheckboxCardField: React.FC<CheckboxCardFieldProps> = ({
}}
>
<Flex align="center" gap="2">
{opt.icon ? <Icon as={opt.icon as any} boxSize="16px" /> : null}
{opt.icon ? <Icon as={opt.icon as As} boxSize="16px" /> : null}
<Text fontSize="sm" noOfLines={1}>
{opt.label}
</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,79 @@ import {
PopoverTrigger,
} from "@chakra-ui/react"
import { memo, useEffect, useState } from "react"
import ColorPicker from "react-best-gradient-color-picker"
import ColorPicker, {
type ColorPickerProps,
} from "react-best-gradient-color-picker"
import { useDebounce } from "../../hooks/useDebounce"

const ColorPickerField = ({
fieldName,
value,
setValue,
fieldProps,
}: {
fieldName: string
value: string
setValue: (name: string, value: string) => void
fieldProps?: ColorPickerProps
}) => {
const [localValue, setLocalValue] = useState<string>(value)

/**
* @note: This parsing behavior is not a bug, it has been mimicked to match the downstream service
* logic i.e. parseInt(hexAlpha, 10) / 100, which parses the hex digits as decimal, stopping at
* non-digit characters.
*/
const parseAlphaLikeDownstream = (hexAlpha: string): number => {
const parsed = parseInt(hexAlpha, 10)
return isNaN(parsed) ? 0 : parsed / 100
}

/**
* Helper function to convert alpha back to hex format that will parse correctly downstream.
* We need to find a hex value that, when parsed as decimal by downstream, gives us the desired alpha.
*
* For example:
* - If alpha is 0.99, we want downstream to get 99, so we need "99" in hex
* - If alpha is 0.5, we want downstream to get 50, so we need "50" in hex
*/
const alphaToHexForDownstream = (alpha: number): string => {
const targetDecimal = Math.round(alpha * 100)
const clampedDecimal = Math.max(0, Math.min(99, targetDecimal))
return clampedDecimal.toString().padStart(2, "0")
}

// Convert a color from downstream format to standard format for the color picker
const convertDownstreamToStandard = (color: string): string => {
if (!color || !color.startsWith('#') || color.length !== 9) {
return color
}

const rgb = color.slice(1, 7)
const alphaHex = color.slice(7, 9)
const parsedAlpha = parseAlphaLikeDownstream(alphaHex)

// Convert to standard 0-255 range
const standardAlphaInt = Math.round(parsedAlpha * 255)
const standardAlphaHex = standardAlphaInt.toString(16).padStart(2, "0")

return `#${rgb}${standardAlphaHex}`
}

// Get the preview color that shows what downstream will actually render
const getPreviewColor = (color: string): string => {
if (!color || !color.startsWith('#')) {
return color
}

if (color.length === 9) {
// Has alpha channel - convert using downstream logic
return convertDownstreamToStandard(color)
}

return color
}

const handleColorChange = (color: string) => {
const parts = color.match(/[\d.]+/g)?.map(Number) ?? []

Expand All @@ -35,12 +94,12 @@ const ColorPickerField = ({
.map((v) => v.toString(16).padStart(2, "0"))
.join("")

if (a === undefined) {
if (fieldProps?.hideOpacity === true || a === undefined) {
setLocalValue(`#${rgbHex}`)
} else {
const alphaDec = a > 1 ? a / 100 : a
const alphaInt = clamp8(Math.round(alphaDec * 255))
setLocalValue(`#${rgbHex}${alphaInt.toString(16).padStart(2, "0")}`)
const alphaHex = alphaToHexForDownstream(alphaDec)
setLocalValue(`#${rgbHex}${alphaHex}`)
}
}

Expand All @@ -50,6 +109,10 @@ const ColorPickerField = ({
setValue(fieldName, debouncedValue)
}, [debouncedValue, fieldName, setValue])

useEffect(() => {
setLocalValue(value)
}, [value])

return (
<Flex direction="column" gap="2">
<Flex>
Expand Down Expand Up @@ -84,7 +147,7 @@ const ColorPickerField = ({
height="10"
align="center"
justify="center"
bg={localValue}
bg={getPreviewColor(localValue)}
borderWidth="1px"
borderColor="gray.200"
borderLeft="0"
Expand All @@ -95,7 +158,7 @@ const ColorPickerField = ({
<PopoverContent p="2" width="auto" zIndex={1400}>
<PopoverBody p="0">
<ColorPicker
value={localValue}
value={convertDownstreamToStandard(localValue)}
onChange={handleColorChange}
disableDarkMode
hideGradientType
Expand All @@ -107,6 +170,8 @@ const ColorPickerField = ({
hideInputs
hideAdvancedSliders
hideColorGuide
// @ts-expect-error - fieldProps may include props not declared in ColorPickerProps, but they are intentionally forwarded
{...fieldProps}
/>
</PopoverBody>
</PopoverContent>
Expand Down
Loading
Loading