Skip to content

Commit 8781aa4

Browse files
Merge remote-tracking branch 'origin/feature/typescript'
2 parents aef1c19 + a9ceb31 commit 8781aa4

35 files changed

+1154
-1277
lines changed

package.json

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
"name": "react-image-annotate",
33
"version": "2.0.0",
44
"type": "module",
5+
"main": "dist/main.js",
6+
"types": "dist/main.d.ts",
7+
"files": [
8+
"dist"
9+
],
510
"dependencies": {
611
"@emotion/react": "^11.11.0",
712
"@emotion/styled": "^11.11.0",
@@ -11,11 +16,9 @@
1116
"@mui/icons-material": "^5.2.1",
1217
"@mui/material": "^5.2.3",
1318
"@mui/styles": "^5.2.3",
14-
"@semantic-release/git": "^9.0.0",
1519
"@vitejs/plugin-react": "^4.2.1",
1620
"autoseg": "^0.0.12",
1721
"color-alpha": "^2.0.0",
18-
"get-image-data": "^5.0.0",
1922
"lodash": "^4.17.21",
2023
"material-survey": "^2.1.0",
2124
"moment": "^2.30.0",
@@ -24,7 +27,6 @@
2427
"react-dom": "^18.0.2",
2528
"react-full-screen": "^1.1.1",
2629
"react-hotkeys": "^2.0.0",
27-
"react-json-view": "^1.19.1",
2830
"react-markdown": "^9.0.0",
2931
"react-material-workspace-layout": "^1.0.10",
3032
"react-monaco-editor": "^0.55.0",
@@ -53,9 +55,9 @@
5355
"gh-pages": "^2.0.1",
5456
"prettier": "^2.5.1",
5557
"react-github-btn": "^1.1.1",
56-
"shx": "^0.3.4",
5758
"typescript": "^5.2.2",
5859
"vite": "^5.2.7",
60+
"vite-plugin-dts": "^3.8.1",
5961
"vite-plugin-node-polyfills": "^0.21.0",
6062
"vite-raw-plugin": "^1.0.2",
6163
"vite-tsconfig-paths": "^4.3.2"
@@ -72,7 +74,7 @@
7274
"scripts": {
7375
"start": "vite",
7476
"build": "tsc && vite build",
75-
"dist": "npm run build && cd dist && npm publish",
77+
"publish": "npm run build && cd dist && npm publish",
7678
"prettier": "prettier --write \"src/**/*.js\"",
7779
"prettier:test": "prettier --check \"src/**/*.js\""
7880
},

src/Annotator/index.tsx

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// @flow
22

33
import type { Action, Image, MainLayoutState } from "../MainLayout/types";
4-
import { useEffect, useReducer } from "react";
5-
import Immutable from "seamless-immutable";
4+
import { ComponentType, FunctionComponent, useEffect, useReducer } from "react";
5+
import Immutable, { ImmutableObject } from "seamless-immutable";
66

77
import type { KeypointsDefinition } from "../ImageCanvas/region-tools";
88
import MainLayout from "../MainLayout";
@@ -30,8 +30,8 @@ export type AnnotatorProps = {
3030
images?: Array<Image>;
3131
showPointDistances?: boolean;
3232
pointDistancePrecision?: number;
33-
RegionEditLabel?: Node;
34-
onExit: (state: MainLayoutState) => any;
33+
RegionEditLabel?: ComponentType<any> | FunctionComponent<any> | null;
34+
onExit: (state: MainLayoutState) => void;
3535
videoTime?: number;
3636
videoSrc?: string;
3737
keyframes?: Object;
@@ -102,58 +102,71 @@ export const Annotator = ({
102102
if (selectedImage === -1) selectedImage = undefined;
103103
}
104104
const annotationType = images ? "image" : "video";
105-
const [state, dispatchToReducer] = useReducer(
106-
historyHandler(
107-
combineReducers(
108-
annotationType === "image" ? imageReducer : videoReducer,
109-
generalReducer
110-
)
111-
),
112-
Immutable({
113-
annotationType,
114-
showTags,
115-
allowedArea,
116-
showPointDistances,
117-
pointDistancePrecision,
118-
selectedTool,
119-
fullImageSegmentationMode: fullImageSegmentationMode,
120-
autoSegmentationOptions,
121-
mode: null,
122-
taskDescription,
123-
showMask: true,
124-
labelImages: imageClsList.length > 0 || imageTagList.length > 0,
125-
regionClsList,
126-
regionTagList,
127-
imageClsList,
128-
imageTagList,
129-
currentVideoTime: videoTime,
130-
enabledTools,
131-
history: [],
132-
videoName,
133-
keypointDefinitions,
134-
allowComments,
135-
...(annotationType === "image"
136-
? {
137-
selectedImage,
138-
images,
139-
selectedImageFrameTime:
140-
images && images.length > 0 ? images[0].frameTime : undefined,
141-
}
142-
: {
143-
videoSrc,
144-
keyframes,
145-
}),
146-
})
105+
const combinedReducers = (
106+
annotationType === "image"
107+
? combineReducers(imageReducer, generalReducer)
108+
: combineReducers(videoReducer, generalReducer)
109+
) as (
110+
state: ImmutableObject<MainLayoutState>,
111+
action: Action
112+
) => ImmutableObject<MainLayoutState>;
113+
114+
const immutableState = Immutable({
115+
annotationType,
116+
showTags,
117+
allowedArea,
118+
showPointDistances,
119+
pointDistancePrecision,
120+
selectedTool,
121+
fullImageSegmentationMode: fullImageSegmentationMode,
122+
autoSegmentationOptions,
123+
mode: null,
124+
taskDescription,
125+
showMask: true,
126+
labelImages: imageClsList.length > 0 || imageTagList.length > 0,
127+
regionClsList,
128+
regionTagList,
129+
imageClsList,
130+
imageTagList,
131+
currentVideoTime: videoTime,
132+
enabledTools,
133+
history: [],
134+
videoName,
135+
keypointDefinitions,
136+
allowComments,
137+
...(annotationType === "image"
138+
? {
139+
selectedImage,
140+
images,
141+
selectedImageFrameTime:
142+
images && images.length > 0 ? images[0].frameTime : undefined,
143+
}
144+
: {
145+
videoSrc,
146+
keyframes,
147+
}),
148+
});
149+
const [state, dispatchToReducer] = useReducer<
150+
(state: MainLayoutState, action: Action) => MainLayoutState
151+
>(
152+
historyHandler(combinedReducers) as unknown as (
153+
state: MainLayoutState,
154+
action: Action
155+
) => MainLayoutState,
156+
immutableState as unknown as MainLayoutState
147157
);
148158

149159
const dispatch = useEventCallback((action: Action) => {
150160
if (action.type === "HEADER_BUTTON_CLICKED") {
161+
const value = (Immutable(state) as ImmutableObject<MainLayoutState>)
162+
.without("history")
163+
.asMutable({ deep: true });
151164
if (["Exit", "Done", "Save", "Complete"].includes(action.buttonName)) {
152-
return onExit(Immutable(state).without("history"));
165+
return onExit(value);
153166
} else if (action.buttonName === "Next" && onNextImage) {
154-
return onNextImage(Immutable(state).without("history"));
167+
return onNextImage(value);
155168
} else if (action.buttonName === "Prev" && onPrevImage) {
156-
return onPrevImage(Immutable(state).without("history"));
169+
return onPrevImage(value);
157170
}
158171
}
159172
dispatchToReducer(action);
@@ -167,13 +180,15 @@ export const Annotator = ({
167180
});
168181

169182
useEffect(() => {
170-
if (selectedImage === undefined) return;
183+
if (selectedImage === undefined || state.annotationType !== "image") return;
184+
const image = state.images[selectedImage];
171185
dispatchToReducer({
172186
type: "SELECT_IMAGE",
173187
imageIndex: +selectedImage,
174-
image: state.images[selectedImage],
188+
image,
175189
});
176-
}, [selectedImage, state.images]);
190+
// @ts-ignore
191+
}, [selectedImage, state.annotationType, state.images]);
177192

178193
if (!images && !videoSrc)
179194
return 'Missing required prop "images" or "videoSrc"';
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
export default (...reducers) =>
2-
(state, action) => {
1+
import { Action, MainLayoutStateBase } from "../../MainLayout/types.ts";
2+
import { ImmutableObject } from "seamless-immutable";
3+
4+
export default <T extends ImmutableObject<MainLayoutStateBase>>(
5+
...reducers: ((state: T, action: Action) => T)[]
6+
) =>
7+
(state: T, action: Action) => {
38
for (const reducer of reducers) {
4-
state = reducer(state, action)
9+
state = reducer(state, action);
510
}
6-
return state
7-
}
11+
return state;
12+
};

src/Annotator/reducers/convert-expanding-line-to-polygon.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// @flow
22

33
import { clamp } from "../../utils/clamp";
4+
import { ExpandingLine } from "../../ImageCanvas/region-tools.tsx";
5+
import Immutable from "seamless-immutable";
46

5-
export default (expandingLine) => {
7+
export default (expandingLine: ExpandingLine) => {
68
const expandingWidth = expandingLine.expandingWidth || 0.005;
79
const pointPairs = expandingLine.points.map(({ x, y, angle, width }, i) => {
810
if (!angle) {
@@ -19,8 +21,8 @@ export default (expandingLine) => {
1921
{ x: x - dx, y: y - dy },
2022
];
2123
});
22-
const firstSection = pointPairs.map(([p1, p2]) => p1);
23-
const secondSection = pointPairs.map(([p1, p2]) => p2).asMutable();
24+
const firstSection = pointPairs.map(([p1]) => p1);
25+
const secondSection = Immutable.asMutable(pointPairs.map(([_, p2]) => p2));
2426
secondSection.reverse();
2527

2628
const newPoints = firstSection
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// @flow
22

3-
export default (pointsWithAngles) => {
3+
import { ExpandingLine } from "../../ImageCanvas/region-tools.tsx";
4+
5+
export default (pointsWithAngles: ExpandingLine["points"]) => {
46
// Adjacent angles should not have an angular distance of more than Math.PI
5-
return pointsWithAngles
6-
}
7+
return pointsWithAngles;
8+
};

0 commit comments

Comments
 (0)