@searpent/react-image-annotate 2.0.0 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/Annotator/index.js +169 -0
  2. package/Annotator/reducers/combine-reducers.js +14 -0
  3. package/Annotator/reducers/convert-expanding-line-to-polygon.js +73 -0
  4. package/{src/Annotator → Annotator}/reducers/fix-twisted.js +3 -5
  5. package/Annotator/reducers/general-reducer.js +1058 -0
  6. package/Annotator/reducers/get-active-image.js +27 -0
  7. package/Annotator/reducers/get-implied-video-regions.js +180 -0
  8. package/Annotator/reducers/history-handler.js +38 -0
  9. package/Annotator/reducers/image-reducer.js +20 -0
  10. package/Annotator/reducers/video-reducer.js +88 -0
  11. package/ClassSelectionMenu/index.js +135 -0
  12. package/Crosshairs/index.js +53 -0
  13. package/DebugSidebarBox/index.js +20 -0
  14. package/DemoSite/Editor.js +194 -0
  15. package/DemoSite/ErrorBoundaryDialog.js +64 -0
  16. package/DemoSite/index.js +40 -0
  17. package/FullImageSegmentationAnnotator/index.js +7 -0
  18. package/GroupSelectorSidebarBox/index.js +63 -0
  19. package/HighlightBox/index.js +99 -0
  20. package/HistorySidebarBox/index.js +71 -0
  21. package/ImageCanvas/index.js +424 -0
  22. package/ImageCanvas/region-tools.js +165 -0
  23. package/{src/ImageCanvas → ImageCanvas}/styles.js +12 -8
  24. package/ImageCanvas/use-mouse.js +180 -0
  25. package/ImageCanvas/use-project-box.js +27 -0
  26. package/ImageCanvas/use-wasd-mode.js +62 -0
  27. package/ImageMask/index.js +133 -0
  28. package/ImageMask/load-image.js +25 -0
  29. package/ImageSelectorSidebarBox/index.js +60 -0
  30. package/KeyframeTimeline/get-time-string.js +27 -0
  31. package/KeyframeTimeline/index.js +233 -0
  32. package/KeyframesSelectorSidebarBox/index.js +93 -0
  33. package/LandingPage/index.js +159 -0
  34. package/MainLayout/icon-dictionary.js +104 -0
  35. package/MainLayout/index.js +366 -0
  36. package/{src/MainLayout → MainLayout}/styles.js +6 -7
  37. package/MainLayout/types.js +0 -0
  38. package/MainLayout/use-implied-video-regions.js +13 -0
  39. package/PointDistances/index.js +73 -0
  40. package/PreventScrollToParents/index.js +51 -0
  41. package/RegionLabel/index.js +191 -0
  42. package/{src/RegionLabel → RegionLabel}/styles.js +12 -15
  43. package/RegionSelectAndTransformBoxes/index.js +167 -0
  44. package/RegionSelectorSidebarBox/index.js +248 -0
  45. package/{src/RegionSelectorSidebarBox → RegionSelectorSidebarBox}/styles.js +13 -14
  46. package/RegionShapes/index.js +274 -0
  47. package/RegionTags/index.js +138 -0
  48. package/SettingsDialog/index.js +52 -0
  49. package/SettingsProvider/index.js +53 -0
  50. package/Shortcuts/ShortcutField.js +46 -0
  51. package/Shortcuts/index.js +133 -0
  52. package/ShortcutsManager/index.js +155 -0
  53. package/Sidebar/index.js +69 -0
  54. package/SidebarBoxContainer/index.js +93 -0
  55. package/SmallToolButton/index.js +42 -0
  56. package/TagsSidebarBox/index.js +105 -0
  57. package/TaskDescriptionSidebarBox/index.js +58 -0
  58. package/Theme/index.js +30 -0
  59. package/VideoOrImageCanvasBackground/index.js +151 -0
  60. package/colors.js +14 -0
  61. package/hooks/use-event-callback.js +10 -0
  62. package/hooks/use-exclude-pattern.js +24 -0
  63. package/hooks/use-load-image.js +26 -0
  64. package/hooks/use-window-size.js +46 -0
  65. package/{src/hooks → hooks}/xpattern.js +1 -1
  66. package/index.js +3 -0
  67. package/lib.js +3 -0
  68. package/package.json +1 -1
  69. package/stories.js +5 -0
  70. package/utils/get-from-local-storage.js +7 -0
  71. package/utils/get-hotkey-help-text.js +9 -0
  72. package/utils/get-landmarks-with-transform.js +40 -0
  73. package/utils/set-in-local-storage.js +3 -0
  74. package/.babelrc +0 -6
  75. package/.env +0 -1
  76. package/.flowconfig +0 -2
  77. package/.github/workflows/release-on-master.yml +0 -32
  78. package/.github/workflows/test.yml +0 -16
  79. package/.prettierrc +0 -3
  80. package/.releaserc.js +0 -18
  81. package/.storybook/addons.js +0 -2
  82. package/.storybook/config.js +0 -16
  83. package/LICENSE +0 -21
  84. package/public/favicon.ico +0 -0
  85. package/public/index.html +0 -38
  86. package/src/Annotator/bike-pic.png +0 -0
  87. package/src/Annotator/bike-pic2.png +0 -0
  88. package/src/Annotator/dab-keyframes.story.json +0 -1
  89. package/src/Annotator/index.js +0 -206
  90. package/src/Annotator/index.story.js +0 -727
  91. package/src/Annotator/poses.story.js +0 -150
  92. package/src/Annotator/reducers/combine-reducers.js +0 -7
  93. package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -53
  94. package/src/Annotator/reducers/general-reducer.js +0 -914
  95. package/src/Annotator/reducers/get-active-image.js +0 -21
  96. package/src/Annotator/reducers/get-implied-video-regions.js +0 -115
  97. package/src/Annotator/reducers/history-handler.js +0 -60
  98. package/src/Annotator/reducers/image-reducer.js +0 -23
  99. package/src/Annotator/reducers/video-reducer.js +0 -85
  100. package/src/Annotator/video.story.js +0 -51
  101. package/src/ClassSelectionMenu/index.js +0 -108
  102. package/src/Crosshairs/index.js +0 -64
  103. package/src/DebugSidebarBox/index.js +0 -36
  104. package/src/DemoSite/Editor.js +0 -235
  105. package/src/DemoSite/ErrorBoundaryDialog.js +0 -34
  106. package/src/DemoSite/index.js +0 -41
  107. package/src/DemoSite/index.story.js +0 -10
  108. package/src/DemoSite/simple-segmentation-example.json +0 -572
  109. package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
  110. package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
  111. package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
  112. package/src/FullImageSegmentationAnnotator/index.js +0 -7
  113. package/src/FullImageSegmentationAnnotator/index.story.js +0 -177
  114. package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
  115. package/src/HighlightBox/index.js +0 -143
  116. package/src/HistorySidebarBox/index.js +0 -78
  117. package/src/ImageCanvas/dancing-man.story.jpg +0 -0
  118. package/src/ImageCanvas/index.js +0 -488
  119. package/src/ImageCanvas/index.story.js +0 -214
  120. package/src/ImageCanvas/mouse_mask.story.png +0 -0
  121. package/src/ImageCanvas/region-tools.js +0 -171
  122. package/src/ImageCanvas/seves_desk.story.jpg +0 -0
  123. package/src/ImageCanvas/use-mouse.js +0 -168
  124. package/src/ImageCanvas/use-project-box.js +0 -23
  125. package/src/ImageCanvas/use-wasd-mode.js +0 -50
  126. package/src/ImageMask/index.js +0 -127
  127. package/src/ImageMask/load-image.js +0 -32
  128. package/src/ImageSelectorSidebarBox/index.js +0 -54
  129. package/src/KeyframeTimeline/get-time-string.js +0 -25
  130. package/src/KeyframeTimeline/index.js +0 -223
  131. package/src/KeyframesSelectorSidebarBox/index.js +0 -93
  132. package/src/LandingPage/content.md +0 -57
  133. package/src/LandingPage/github-markdown.css +0 -964
  134. package/src/LandingPage/index.js +0 -147
  135. package/src/MainLayout/icon-dictionary.js +0 -79
  136. package/src/MainLayout/index.js +0 -420
  137. package/src/MainLayout/index.story.js +0 -240
  138. package/src/MainLayout/types.js +0 -156
  139. package/src/MainLayout/use-implied-video-regions.js +0 -17
  140. package/src/PointDistances/index.js +0 -90
  141. package/src/PreventScrollToParents/index.js +0 -48
  142. package/src/PreventScrollToParents/index.story.js +0 -23
  143. package/src/RegionLabel/index.js +0 -201
  144. package/src/RegionSelectAndTransformBoxes/index.js +0 -234
  145. package/src/RegionSelectorSidebarBox/index.js +0 -216
  146. package/src/RegionShapes/index.js +0 -236
  147. package/src/RegionTags/index.js +0 -130
  148. package/src/SettingsDialog/index.js +0 -58
  149. package/src/SettingsProvider/index.js +0 -44
  150. package/src/Shortcuts/ShortcutField.js +0 -44
  151. package/src/Shortcuts/index.js +0 -129
  152. package/src/ShortcutsManager/index.js +0 -162
  153. package/src/Sidebar/index.js +0 -117
  154. package/src/SidebarBoxContainer/index.js +0 -93
  155. package/src/SmallToolButton/index.js +0 -57
  156. package/src/TagsSidebarBox/index.js +0 -93
  157. package/src/TaskDescriptionSidebarBox/index.js +0 -43
  158. package/src/Theme/index.js +0 -36
  159. package/src/VideoOrImageCanvasBackground/index.js +0 -170
  160. package/src/colors.js +0 -32
  161. package/src/hooks/use-event-callback.js +0 -11
  162. package/src/hooks/use-exclude-pattern.js +0 -27
  163. package/src/hooks/use-load-image.js +0 -21
  164. package/src/hooks/use-window-size.js +0 -46
  165. package/src/hooks/xpattern.png +0 -0
  166. package/src/index.js +0 -18
  167. package/src/lib.js +0 -7
  168. package/src/screenshot.png +0 -0
  169. package/src/site.css +0 -5
  170. package/src/stories.js +0 -2
  171. package/src/utils/get-from-local-storage.js +0 -7
  172. package/src/utils/get-hotkey-help-text.js +0 -11
  173. package/src/utils/get-landmarks-with-transform.js +0 -23
  174. package/src/utils/set-in-local-storage.js +0 -6
@@ -1,201 +0,0 @@
1
- // @flow
2
-
3
- import React, { useRef, memo } from "react"
4
- import Paper from "@mui/material/Paper"
5
- import { makeStyles } from "@mui/styles"
6
- import { createTheme, ThemeProvider } from "@mui/material/styles"
7
- import styles from "./styles"
8
- import classnames from "classnames"
9
- import type { Region } from "../ImageCanvas/region-tools.js"
10
- import IconButton from "@mui/material/IconButton"
11
- import Button from "@mui/material/Button"
12
- import TrashIcon from "@mui/icons-material/Delete"
13
- import CheckIcon from "@mui/icons-material/Check"
14
- import TextField from "@mui/material/TextField"
15
- import Select from "react-select"
16
- import CreatableSelect from "react-select/creatable"
17
-
18
- import { asMutable } from "seamless-immutable"
19
-
20
- const theme = createTheme()
21
- const useStyles = makeStyles((theme) => styles)
22
-
23
- type Props = {
24
- region: Region,
25
- editing?: boolean,
26
- allowedClasses?: Array<string>,
27
- allowedTags?: Array<string>,
28
- cls?: string,
29
- tags?: Array<string>,
30
- onDelete: (Region) => null,
31
- onChange: (Region) => null,
32
- onClose: (Region) => null,
33
- onOpen: (Region) => null,
34
- onRegionClassAdded: () => {},
35
- allowComments?: boolean,
36
- }
37
-
38
- export const RegionLabel = ({
39
- region,
40
- editing,
41
- allowedClasses,
42
- allowedTags,
43
- onDelete,
44
- onChange,
45
- onClose,
46
- onOpen,
47
- onRegionClassAdded,
48
- allowComments,
49
- }: Props) => {
50
- const classes = useStyles()
51
- const commentInputRef = useRef(null)
52
- const onCommentInputClick = (_) => {
53
- // The TextField wraps the <input> tag with two divs
54
- const commentInput = commentInputRef.current.children[0].children[0]
55
-
56
- if (commentInput) return commentInput.focus()
57
- }
58
-
59
- return (
60
- <ThemeProvider theme={theme}>
61
- <Paper
62
- onClick={() => (!editing ? onOpen(region) : null)}
63
- className={classnames(classes.regionInfo, {
64
- highlighted: region.highlighted,
65
- })}
66
- >
67
- {!editing ? (
68
- <div>
69
- {region.cls && (
70
- <div className="name">
71
- <div
72
- className="circle"
73
- style={{ backgroundColor: region.color }}
74
- />
75
- {region.cls}
76
- </div>
77
- )}
78
- {region.tags && (
79
- <div className="tags">
80
- {region.tags.map((t) => (
81
- <div key={t} className="tag">
82
- {t}
83
- </div>
84
- ))}
85
- </div>
86
- )}
87
- </div>
88
- ) : (
89
- <div style={{ width: 200 }}>
90
- <div style={{ display: "flex", flexDirection: "row" }}>
91
- <div
92
- style={{
93
- display: "flex",
94
- backgroundColor: region.color || "#888",
95
- color: "#fff",
96
- padding: 4,
97
- paddingLeft: 8,
98
- paddingRight: 8,
99
- borderRadius: 4,
100
- fontWeight: "bold",
101
- textShadow: "0px 0px 5px rgba(0,0,0,0.4)",
102
- }}
103
- >
104
- {region.type}
105
- </div>
106
- <div style={{ flexGrow: 1 }} />
107
- <IconButton
108
- onClick={() => onDelete(region)}
109
- tabIndex={-1}
110
- style={{ width: 22, height: 22 }}
111
- size="small"
112
- variant="outlined"
113
- >
114
- <TrashIcon style={{ marginTop: -8, width: 16, height: 16 }} />
115
- </IconButton>
116
- </div>
117
- {(allowedClasses || []).length > 0 && (
118
- <div style={{ marginTop: 6 }}>
119
- <CreatableSelect
120
- placeholder="Classification"
121
- onChange={(o, actionMeta) => {
122
- if (actionMeta.action == "create-option") {
123
- onRegionClassAdded(o.value)
124
- }
125
- return onChange({
126
- ...(region: any),
127
- cls: o.value,
128
- })
129
- }}
130
- value={
131
- region.cls ? { label: region.cls, value: region.cls } : null
132
- }
133
- options={asMutable(
134
- allowedClasses.map((c) => ({ value: c, label: c }))
135
- )}
136
- />
137
- </div>
138
- )}
139
- {(allowedTags || []).length > 0 && (
140
- <div style={{ marginTop: 4 }}>
141
- <Select
142
- onChange={(newTags) =>
143
- onChange({
144
- ...(region: any),
145
- tags: newTags.map((t) => t.value),
146
- })
147
- }
148
- placeholder="Tags"
149
- value={(region.tags || []).map((c) => ({
150
- label: c,
151
- value: c,
152
- }))}
153
- isMulti
154
- options={asMutable(
155
- allowedTags.map((c) => ({ value: c, label: c }))
156
- )}
157
- />
158
- </div>
159
- )}
160
- {allowComments && (
161
- <TextField
162
- InputProps={{
163
- className: classes.commentBox,
164
- }}
165
- fullWidth
166
- multiline
167
- rows={3}
168
- ref={commentInputRef}
169
- onClick={onCommentInputClick}
170
- value={region.comment || ""}
171
- onChange={(event) =>
172
- onChange({ ...(region: any), comment: event.target.value })
173
- }
174
- />
175
- )}
176
- {onClose && (
177
- <div style={{ marginTop: 4, display: "flex" }}>
178
- <div style={{ flexGrow: 1 }} />
179
- <Button
180
- onClick={() => onClose(region)}
181
- size="small"
182
- variant="contained"
183
- color="primary"
184
- >
185
- <CheckIcon />
186
- </Button>
187
- </div>
188
- )}
189
- </div>
190
- )}
191
- </Paper>
192
- </ThemeProvider>
193
- )
194
- }
195
-
196
- export default memo(
197
- RegionLabel,
198
- (prevProps, nextProps) =>
199
- prevProps.editing === nextProps.editing &&
200
- prevProps.region === nextProps.region
201
- )
@@ -1,234 +0,0 @@
1
- import React, { Fragment, memo } from "react"
2
- import HighlightBox from "../HighlightBox"
3
- import { styled } from "@mui/material/styles"
4
- import { createTheme, ThemeProvider } from "@mui/material/styles"
5
- import PreventScrollToParents from "../PreventScrollToParents"
6
- import Tooltip from "@mui/material/Tooltip"
7
-
8
- const theme = createTheme()
9
- const TransformGrabber = styled("div")(({ theme }) => ({
10
- width: 8,
11
- height: 8,
12
- zIndex: 2,
13
- border: "2px solid #FFF",
14
- position: "absolute",
15
- }))
16
-
17
- const boxCursorMap = [
18
- ["nw-resize", "n-resize", "ne-resize"],
19
- ["w-resize", "grab", "e-resize"],
20
- ["sw-resize", "s-resize", "se-resize"],
21
- ]
22
-
23
- const arePropsEqual = (prev, next) => {
24
- return (
25
- prev.region === next.region &&
26
- prev.dragWithPrimary === next.dragWithPrimary &&
27
- prev.createWithPrimary === next.createWithPrimary &&
28
- prev.zoomWithPrimary === next.zoomWithPrimary &&
29
- prev.mat === next.mat
30
- )
31
- }
32
-
33
- export const RegionSelectAndTransformBox = memo(
34
- ({
35
- region: r,
36
- mouseEvents,
37
- projectRegionBox,
38
- dragWithPrimary,
39
- createWithPrimary,
40
- zoomWithPrimary,
41
- onBeginMovePoint,
42
- onSelectRegion,
43
- layoutParams,
44
- fullImageSegmentationMode = false,
45
- mat,
46
- onBeginBoxTransform,
47
- onBeginMovePolygonPoint,
48
- onBeginMoveKeypoint,
49
- onAddPolygonPoint,
50
- showHighlightBox,
51
- }) => {
52
- const pbox = projectRegionBox(r)
53
- const { iw, ih } = layoutParams.current
54
- return (
55
- <ThemeProvider theme={theme}>
56
- <Fragment>
57
- <PreventScrollToParents>
58
- {showHighlightBox && r.type !== "polygon" && (
59
- <HighlightBox
60
- region={r}
61
- mouseEvents={mouseEvents}
62
- dragWithPrimary={dragWithPrimary}
63
- createWithPrimary={createWithPrimary}
64
- zoomWithPrimary={zoomWithPrimary}
65
- onBeginMovePoint={onBeginMovePoint}
66
- onSelectRegion={onSelectRegion}
67
- pbox={pbox}
68
- />
69
- )}
70
- {r.type === "box" &&
71
- !dragWithPrimary &&
72
- !zoomWithPrimary &&
73
- !r.locked &&
74
- r.highlighted &&
75
- mat.a < 1.2 &&
76
- [
77
- [0, 0],
78
- [0.5, 0],
79
- [1, 0],
80
- [1, 0.5],
81
- [1, 1],
82
- [0.5, 1],
83
- [0, 1],
84
- [0, 0.5],
85
- [0.5, 0.5],
86
- ].map(([px, py], i) => (
87
- <TransformGrabber
88
- key={i}
89
- {...mouseEvents}
90
- onMouseDown={(e) => {
91
- if (e.button === 0)
92
- return onBeginBoxTransform(r, [px * 2 - 1, py * 2 - 1])
93
- mouseEvents.onMouseDown(e)
94
- }}
95
- style={{
96
- left: pbox.x - 4 - 2 + pbox.w * px,
97
- top: pbox.y - 4 - 2 + pbox.h * py,
98
- cursor: boxCursorMap[py * 2][px * 2],
99
- borderRadius: px === 0.5 && py === 0.5 ? 4 : undefined,
100
- }}
101
- />
102
- ))}
103
- {r.type === "polygon" &&
104
- !dragWithPrimary &&
105
- !zoomWithPrimary &&
106
- !r.locked &&
107
- r.highlighted &&
108
- r.points.map(([px, py], i) => {
109
- const proj = mat
110
- .clone()
111
- .inverse()
112
- .applyToPoint(px * iw, py * ih)
113
- return (
114
- <TransformGrabber
115
- key={i}
116
- {...mouseEvents}
117
- onMouseDown={(e) => {
118
- if (e.button === 0 && (!r.open || i === 0))
119
- return onBeginMovePolygonPoint(r, i)
120
- mouseEvents.onMouseDown(e)
121
- }}
122
- style={{
123
- cursor: !r.open
124
- ? "move"
125
- : i === 0
126
- ? "pointer"
127
- : undefined,
128
- zIndex: 10,
129
- pointerEvents:
130
- r.open && i === r.points.length - 1
131
- ? "none"
132
- : undefined,
133
- left: proj.x - 4,
134
- top: proj.y - 4,
135
- }}
136
- />
137
- )
138
- })}
139
- {r.type === "polygon" &&
140
- r.highlighted &&
141
- !dragWithPrimary &&
142
- !zoomWithPrimary &&
143
- !r.locked &&
144
- !r.open &&
145
- r.points.length > 1 &&
146
- r.points
147
- .map((p1, i) => [p1, r.points[(i + 1) % r.points.length]])
148
- .map(([p1, p2]) => [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2])
149
- .map((pa, i) => {
150
- const proj = mat
151
- .clone()
152
- .inverse()
153
- .applyToPoint(pa[0] * iw, pa[1] * ih)
154
- return (
155
- <TransformGrabber
156
- key={i}
157
- {...mouseEvents}
158
- onMouseDown={(e) => {
159
- if (e.button === 0)
160
- return onAddPolygonPoint(r, pa, i + 1)
161
- mouseEvents.onMouseDown(e)
162
- }}
163
- style={{
164
- cursor: "copy",
165
- zIndex: 10,
166
- left: proj.x - 4,
167
- top: proj.y - 4,
168
- border: "2px dotted #fff",
169
- opacity: 0.5,
170
- }}
171
- />
172
- )
173
- })}
174
- {r.type === "keypoints" &&
175
- !dragWithPrimary &&
176
- !zoomWithPrimary &&
177
- !r.locked &&
178
- r.highlighted &&
179
- Object.entries(r.points).map(
180
- ([keypointId, { x: px, y: py }], i) => {
181
- const proj = mat
182
- .clone()
183
- .inverse()
184
- .applyToPoint(px * iw, py * ih)
185
- return (
186
- <Tooltip title={keypointId} key={i}>
187
- <TransformGrabber
188
- key={i}
189
- {...mouseEvents}
190
- onMouseDown={(e) => {
191
- if (e.button === 0 && (!r.open || i === 0))
192
- return onBeginMoveKeypoint(r, keypointId)
193
- mouseEvents.onMouseDown(e)
194
- }}
195
- style={{
196
- cursor: !r.open
197
- ? "move"
198
- : i === 0
199
- ? "pointer"
200
- : undefined,
201
- zIndex: 10,
202
- pointerEvents:
203
- r.open && i === r.points.length - 1
204
- ? "none"
205
- : undefined,
206
- left: proj.x - 4,
207
- top: proj.y - 4,
208
- }}
209
- />
210
- </Tooltip>
211
- )
212
- }
213
- )}
214
- </PreventScrollToParents>
215
- </Fragment>
216
- </ThemeProvider>
217
- )
218
- },
219
- arePropsEqual
220
- )
221
-
222
- export const RegionSelectAndTransformBoxes = memo(
223
- (props) => {
224
- return props.regions
225
- .filter((r) => r.visible || r.visible === undefined)
226
- .filter((r) => !r.locked)
227
- .map((r, i) => {
228
- return <RegionSelectAndTransformBox key={r.id} {...props} region={r} />
229
- })
230
- },
231
- (n, p) => n.regions === p.regions && n.mat === p.mat
232
- )
233
-
234
- export default RegionSelectAndTransformBoxes
@@ -1,216 +0,0 @@
1
- // @flow
2
-
3
- import React, { Fragment, useState, memo } from "react"
4
- import SidebarBoxContainer from "../SidebarBoxContainer"
5
- import { makeStyles } from "@mui/styles"
6
- import { createTheme, ThemeProvider } from "@mui/material/styles"
7
- import { styled } from "@mui/material/styles"
8
- import { grey } from "@mui/material/colors"
9
- import RegionIcon from "@mui/icons-material/PictureInPicture"
10
- import Grid from "@mui/material/Grid"
11
- import ReorderIcon from "@mui/icons-material/SwapVert"
12
- import PieChartIcon from "@mui/icons-material/PieChart"
13
- import TrashIcon from "@mui/icons-material/Delete"
14
- import LockIcon from "@mui/icons-material/Lock"
15
- import UnlockIcon from "@mui/icons-material/LockOpen"
16
- import VisibleIcon from "@mui/icons-material/Visibility"
17
- import VisibleOffIcon from "@mui/icons-material/VisibilityOff"
18
- import styles from "./styles"
19
- import classnames from "classnames"
20
- import isEqual from "lodash/isEqual"
21
-
22
- const theme = createTheme()
23
- const useStyles = makeStyles((theme) => styles)
24
-
25
- const HeaderSep = styled("div")(({ theme }) => ({
26
- borderTop: `1px solid ${grey[200]}`,
27
- marginTop: 2,
28
- marginBottom: 2,
29
- }))
30
-
31
- const Chip = ({ color, text }) => {
32
- const classes = useStyles()
33
- return (
34
- <span className={classes.chip}>
35
- <div className="color" style={{ backgroundColor: color }} />
36
- <div className="text">{text}</div>
37
- </span>
38
- )
39
- }
40
-
41
- const RowLayout = ({
42
- header,
43
- highlighted,
44
- order,
45
- classification,
46
- area,
47
- tags,
48
- trash,
49
- lock,
50
- visible,
51
- onClick,
52
- }) => {
53
- const classes = useStyles()
54
- const [mouseOver, changeMouseOver] = useState(false)
55
- return (
56
- <div
57
- onClick={onClick}
58
- onMouseEnter={() => changeMouseOver(true)}
59
- onMouseLeave={() => changeMouseOver(false)}
60
- className={classnames(classes.row, { header, highlighted })}
61
- >
62
- <Grid container alignItems="center">
63
- <Grid item xs={2}>
64
- <div style={{ textAlign: "right", paddingRight: 10 }}>{order}</div>
65
- </Grid>
66
- <Grid item xs={5}>
67
- {classification}
68
- </Grid>
69
- <Grid item xs={2}>
70
- <div style={{ textAlign: "right", paddingRight: 6 }}>{area}</div>
71
- </Grid>
72
- <Grid item xs={1}>
73
- {trash}
74
- </Grid>
75
- <Grid item xs={1}>
76
- {lock}
77
- </Grid>
78
- <Grid item xs={1}>
79
- {visible}
80
- </Grid>
81
- </Grid>
82
- </div>
83
- )
84
- }
85
-
86
- const RowHeader = () => {
87
- return (
88
- <RowLayout
89
- header
90
- highlighted={false}
91
- order={<ReorderIcon className="icon" />}
92
- classification={<div style={{ paddingLeft: 10 }}>Class</div>}
93
- area={<PieChartIcon className="icon" />}
94
- trash={<TrashIcon className="icon" />}
95
- lock={<LockIcon className="icon" />}
96
- visible={<VisibleIcon className="icon" />}
97
- />
98
- )
99
- }
100
-
101
- const MemoRowHeader = memo(RowHeader)
102
-
103
- const Row = ({
104
- region: r,
105
- highlighted,
106
- onSelectRegion,
107
- onDeleteRegion,
108
- onChangeRegion,
109
- visible,
110
- locked,
111
- color,
112
- cls,
113
- index,
114
- }) => {
115
- return (
116
- <RowLayout
117
- header={false}
118
- highlighted={highlighted}
119
- onClick={() => onSelectRegion(r)}
120
- order={`#${index + 1}`}
121
- classification={<Chip text={cls || ""} color={color || "#ddd"} />}
122
- area=""
123
- trash={<TrashIcon onClick={() => onDeleteRegion(r)} className="icon2" />}
124
- lock={
125
- r.locked ? (
126
- <LockIcon
127
- onClick={() => onChangeRegion({ ...r, locked: false })}
128
- className="icon2"
129
- />
130
- ) : (
131
- <UnlockIcon
132
- onClick={() => onChangeRegion({ ...r, locked: true })}
133
- className="icon2"
134
- />
135
- )
136
- }
137
- visible={
138
- r.visible || r.visible === undefined ? (
139
- <VisibleIcon
140
- onClick={() => onChangeRegion({ ...r, visible: false })}
141
- className="icon2"
142
- />
143
- ) : (
144
- <VisibleOffIcon
145
- onClick={() => onChangeRegion({ ...r, visible: true })}
146
- className="icon2"
147
- />
148
- )
149
- }
150
- />
151
- )
152
- }
153
-
154
- const MemoRow = memo(
155
- Row,
156
- (prevProps, nextProps) =>
157
- prevProps.highlighted === nextProps.highlighted &&
158
- prevProps.visible === nextProps.visible &&
159
- prevProps.locked === nextProps.locked &&
160
- prevProps.id === nextProps.id &&
161
- prevProps.index === nextProps.index &&
162
- prevProps.cls === nextProps.cls &&
163
- prevProps.color === nextProps.color
164
- )
165
-
166
- const emptyArr = []
167
-
168
- export const RegionSelectorSidebarBox = ({
169
- regions = emptyArr,
170
- onDeleteRegion,
171
- onChangeRegion,
172
- onSelectRegion,
173
- }) => {
174
- const classes = useStyles()
175
- return (
176
- <ThemeProvider theme={theme}>
177
- <SidebarBoxContainer
178
- title="Regions"
179
- subTitle=""
180
- icon={<RegionIcon style={{ color: grey[700] }} />}
181
- expandedByDefault
182
- >
183
- <div className={classes.container}>
184
- <MemoRowHeader />
185
- <HeaderSep />
186
- {regions.map((r, i) => (
187
- <MemoRow
188
- key={r.id}
189
- {...r}
190
- region={r}
191
- index={i}
192
- onSelectRegion={onSelectRegion}
193
- onDeleteRegion={onDeleteRegion}
194
- onChangeRegion={onChangeRegion}
195
- />
196
- ))}
197
- </div>
198
- </SidebarBoxContainer>
199
- </ThemeProvider>
200
- )
201
- }
202
-
203
- const mapUsedRegionProperties = (r) => [
204
- r.id,
205
- r.color,
206
- r.locked,
207
- r.visible,
208
- r.highlighted,
209
- ]
210
-
211
- export default memo(RegionSelectorSidebarBox, (prevProps, nextProps) =>
212
- isEqual(
213
- (prevProps.regions || emptyArr).map(mapUsedRegionProperties),
214
- (nextProps.regions || emptyArr).map(mapUsedRegionProperties)
215
- )
216
- )