lost-sia 2.0.1-alpha8 → 3.0.0
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.
- package/README.md +4 -0
- package/dist/Annotation/logic/Annotation.d.ts +17 -0
- package/dist/Annotation/logic/Annotation.js +1 -0
- package/dist/Annotation/ui/AnnotationComponent.d.ts +24 -0
- package/dist/Annotation/ui/AnnotationComponent.js +1 -0
- package/dist/Annotation/ui/atoms/AnnoBar.d.ts +15 -0
- package/dist/Annotation/ui/atoms/AnnoBar.js +1 -0
- package/dist/Annotation/ui/atoms/DaviIcon.d.ts +9 -0
- package/dist/Annotation/ui/atoms/DaviIcon.js +19 -0
- package/dist/Annotation/ui/atoms/Edge.d.ts +17 -0
- package/dist/Annotation/ui/atoms/Edge.js +1 -0
- package/dist/Annotation/ui/atoms/Node.d.ts +17 -0
- package/dist/Annotation/ui/atoms/Node.js +1 -0
- package/dist/Annotation/ui/atoms/PolygonArea.d.ts +16 -0
- package/dist/Annotation/ui/atoms/PolygonArea.js +1 -0
- package/dist/Annotation/ui/tools/BBox.d.ts +21 -0
- package/dist/Annotation/ui/tools/BBox.js +1 -0
- package/dist/Annotation/ui/tools/Line.d.ts +21 -0
- package/dist/Annotation/ui/tools/Line.js +1 -0
- package/dist/Annotation/ui/tools/Point.d.ts +16 -0
- package/dist/Annotation/ui/tools/Point.js +1 -0
- package/dist/Annotation/ui/tools/Polygon.d.ts +23 -0
- package/dist/Annotation/ui/tools/Polygon.js +1 -0
- package/dist/Canvas/Canvas.d.ts +31 -0
- package/dist/Canvas/Canvas.js +1 -0
- package/dist/Canvas/LabelInput.d.ts +11 -0
- package/dist/Canvas/LabelInput.js +1 -0
- package/dist/IconButton.d.ts +25 -0
- package/dist/IconButton.js +1 -0
- package/dist/Sia.d.ts +33 -0
- package/dist/Sia.js +1 -0
- package/dist/Toolbar/Toolbar.d.ts +21 -0
- package/dist/Toolbar/Toolbar.js +1 -0
- package/dist/Toolbar/ToolbarItems/AccessibilityTools.d.ts +7 -0
- package/dist/Toolbar/ToolbarItems/AccessibilityTools.js +1 -0
- package/dist/Toolbar/ToolbarItems/AnnoToolSelector.d.ts +11 -0
- package/dist/Toolbar/ToolbarItems/AnnoToolSelector.js +1 -0
- package/dist/Toolbar/ToolbarItems/ImageToolItems/ImageLabelInput.d.ts +11 -0
- package/dist/Toolbar/ToolbarItems/ImageToolItems/ImageLabelInput.js +1 -0
- package/dist/Toolbar/ToolbarItems/ImageToolItems/TagLabel.d.ts +11 -0
- package/dist/Toolbar/ToolbarItems/ImageToolItems/TagLabel.js +1 -0
- package/dist/Toolbar/ToolbarItems/ImageTools.d.ts +13 -0
- package/dist/Toolbar/ToolbarItems/ImageTools.js +1 -0
- package/dist/Toolbar/ToolbarItems/Instructions.d.ts +2 -0
- package/dist/Toolbar/ToolbarItems/Instructions.js +1 -0
- package/dist/Toolbar/ToolbarItems/InstructionsModal.d.ts +6 -0
- package/dist/Toolbar/ToolbarItems/InstructionsModal.js +1 -0
- package/dist/assets/SIA-BV1tYu3P.css +1 -0
- package/dist/assets/brand-icons-Cu_C0hZ4.svg +1008 -0
- package/dist/assets/brand-icons-F3SPCeH1.woff +0 -0
- package/dist/assets/brand-icons-XL9sxUpA.woff2 +0 -0
- package/dist/assets/brand-icons-sqJ2Pg7a.eot +0 -0
- package/dist/assets/brand-icons-ubhWoxly.ttf +0 -0
- package/dist/assets/flags-DOLqOU7Y.png +0 -0
- package/dist/assets/icons-BOCtAERH.woff +0 -0
- package/dist/assets/icons-CHzK1VD9.eot +0 -0
- package/dist/assets/icons-D29ZQHHw.ttf +0 -0
- package/dist/assets/icons-Du6TOHnR.woff2 +0 -0
- package/dist/assets/icons-RwhydX30.svg +1518 -0
- package/dist/assets/node_modules/semantic-ui-css/semantic.min-Bvulf91l.css +346 -0
- package/dist/assets/outline-icons-BfdLr8tr.svg +366 -0
- package/dist/assets/outline-icons-DD8jm0uy.ttf +0 -0
- package/dist/assets/outline-icons-DInHoiqI.woff2 +0 -0
- package/dist/assets/outline-icons-LX8adJ4n.eot +0 -0
- package/dist/assets/outline-icons-aQ88nltS.woff +0 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -0
- package/dist/models/AnnotationMode.d.ts +11 -0
- package/dist/models/AnnotationMode.js +1 -0
- package/dist/models/AnnotationStatus.d.ts +8 -0
- package/dist/models/AnnotationStatus.js +1 -0
- package/dist/models/AnnotationTool.d.ts +7 -0
- package/dist/models/AnnotationTool.js +1 -0
- package/dist/models/CanvasAction.d.ts +28 -0
- package/dist/models/CanvasAction.js +1 -0
- package/dist/models/Direction.d.ts +7 -0
- package/dist/models/Direction.js +1 -0
- package/dist/models/EditorModes.d.ts +11 -0
- package/dist/models/EditorModes.js +1 -0
- package/dist/models/KeyAction.d.ts +22 -0
- package/dist/models/KeyAction.js +1 -0
- package/dist/models/NotificationType.d.ts +7 -0
- package/dist/models/NotificationType.js +1 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.js +1 -0
- package/dist/stories/AnnotationTools.stories.d.ts +40 -0
- package/dist/stories/Canvas/Canvas.stories.d.ts +50 -0
- package/dist/stories/Canvas/CanvasOffset.d.ts +13 -0
- package/dist/stories/Canvas/CanvasWithOffset.stories.d.ts +36 -0
- package/dist/stories/FilterDropdown.stories.d.ts +19 -0
- package/dist/stories/MinimalSia.stories.d.ts +66 -0
- package/dist/stories/SIA/DemoWrapper.d.ts +8 -0
- package/dist/stories/SIA/DemoWrapper.stories.d.ts +27 -0
- package/dist/stories/SIA/SIA.stories.d.ts +72 -0
- package/dist/stories/Toolbar/ImageTools/TagLabel.stories.d.ts +21 -0
- package/dist/stories/Toolbar/Instructions.stories.d.ts +11 -0
- package/dist/stories/Toolbar/Toolbar.stories.d.ts +37 -0
- package/dist/stories/exampleData/exampleAnnotations.d.ts +8 -0
- package/dist/stories/exampleData/exampleExternalAnnotations.d.ts +8 -0
- package/dist/stories/exampleData/exampleImage.d.ts +2 -0
- package/dist/stories/exampleData/exampleLabels.d.ts +6 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +1 -0
- package/dist/utils/KeyMapper.d.ts +9 -0
- package/dist/utils/KeyMapper.js +1 -0
- package/dist/utils/TimeUtils.d.ts +4 -0
- package/dist/utils/TimeUtils.js +1 -0
- package/dist/utils/color.d.ts +2 -0
- package/dist/utils/color.js +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/mouse.d.ts +6 -0
- package/dist/utils/mouse.js +1 -0
- package/dist/utils/siaIcons.js +12 -0
- package/dist/utils/transform.d.ts +28 -0
- package/dist/utils/transform.js +1 -0
- package/dist/utils/uiConfig.js +1 -0
- package/dist/utils/windowViewport.d.ts +22 -0
- package/dist/utils/windowViewport.js +1 -0
- package/package.json +19 -16
- package/src/AnnoExampleViewer.jsx +18 -18
- package/src/Annotation/logic/Annotation.ts +24 -26
- package/src/Annotation/ui/AnnotationComponent.tsx +115 -86
- package/src/Annotation/ui/atoms/AnnoBar.tsx +51 -53
- package/src/Annotation/ui/atoms/DaviIcon.tsx +12 -22
- package/src/Annotation/ui/atoms/Edge.tsx +25 -22
- package/src/Annotation/ui/atoms/Node.tsx +56 -50
- package/src/Annotation/ui/atoms/PolygonArea.tsx +30 -35
- package/src/Annotation/ui/tools/BBox.tsx +136 -150
- package/src/Annotation/ui/tools/Line.tsx +94 -91
- package/src/Annotation/ui/tools/Point.tsx +19 -17
- package/src/Annotation/ui/tools/Polygon.tsx +126 -95
- package/src/Canvas/Canvas.tsx +748 -594
- package/src/Canvas/LabelInput.tsx +68 -45
- package/src/IconButton.tsx +119 -0
- package/src/InfoBoxes/AnnoDetails.jsx +53 -53
- package/src/InfoBoxes/AnnoStats.jsx +41 -41
- package/src/InfoBoxes/InfoBox.jsx +16 -16
- package/src/InfoBoxes/InfoBoxArea.jsx +32 -34
- package/src/InfoBoxes/LabelInfo.jsx +30 -30
- package/src/SIASettingButton.jsx +25 -25
- package/src/Sia.tsx +484 -0
- package/src/Toolbar/Toolbar.tsx +38 -31
- package/src/Toolbar/ToolbarItems/AccessibilityTools.tsx +26 -46
- package/src/Toolbar/ToolbarItems/AnnoToolSelector.tsx +53 -46
- package/src/Toolbar/ToolbarItems/ImageToolItems/ImageLabelInput.tsx +127 -0
- package/src/Toolbar/ToolbarItems/ImageToolItems/TagLabel.tsx +29 -28
- package/src/Toolbar/ToolbarItems/ImageTools.tsx +43 -40
- package/src/Toolbar/ToolbarItems/Instructions.tsx +47 -50
- package/src/Toolbar/ToolbarItems/InstructionsModal.tsx +8 -8
- package/src/index.ts +9 -13
- package/src/models/{AnnotationMode.tsx → AnnotationMode.ts} +1 -1
- package/src/models/{AnnotationStatus.tsx → AnnotationStatus.ts} +1 -1
- package/src/models/{AnnotationTool.tsx → AnnotationTool.ts} +1 -1
- package/src/models/{CanvasAction.tsx → CanvasAction.ts} +1 -1
- package/src/models/{Direction.tsx → Direction.ts} +1 -1
- package/src/models/{EditorModes.tsx → EditorModes.ts} +1 -1
- package/src/models/{KeyAction.tsx → KeyAction.ts} +3 -1
- package/src/models/NotificationType.ts +8 -0
- package/src/models/index.ts +6 -7
- package/src/siaDummyData.js +71 -71
- package/src/stories/AnnotationTools.mdx +27 -0
- package/src/stories/AnnotationTools.stories.tsx +104 -0
- package/src/stories/Canvas/Canvas.stories.tsx +59 -113
- package/src/stories/Canvas/CanvasOffset.tsx +54 -38
- package/src/stories/Canvas/CanvasWithOffset.stories.tsx +42 -113
- package/src/stories/FilterDropdown.stories.ts +13 -11
- package/src/stories/MinimalSIA.mdx +20 -0
- package/src/stories/MinimalSia.stories.tsx +90 -0
- package/src/stories/SIA/DemoWrapper.stories.tsx +71 -0
- package/src/stories/SIA/DemoWrapper.tsx +55 -0
- package/src/stories/SIA/SIA.stories.tsx +79 -45
- package/src/stories/Toolbar/ImageTools/TagLabel.stories.tsx +11 -12
- package/src/stories/Toolbar/Instructions.stories.tsx +11 -11
- package/src/stories/Toolbar/Toolbar.stories.tsx +32 -47
- package/src/stories/Welcome.mdx +5 -0
- package/src/stories/development/CoordinateSystems.mdx +25 -0
- package/src/stories/exampleData/exampleAnnotations.ts +65 -0
- package/src/stories/exampleData/exampleExternalAnnotations.ts +115 -0
- package/src/stories/{siaDummyData2.ts → exampleData/exampleImage.ts} +3 -264
- package/src/stories/exampleData/exampleLabels.ts +146 -0
- package/src/stories/main.scss +6 -0
- package/src/styles/style.scss +1 -26
- package/src/types.ts +67 -0
- package/src/utils/KeyMapper.ts +76 -74
- package/src/utils/TimeUtils.ts +11 -0
- package/src/utils/color.ts +25 -25
- package/src/utils/hist.js +22 -22
- package/src/utils/index.ts +2 -3
- package/src/utils/mouse.ts +45 -0
- package/src/utils/siaIcons.jsx +5 -7
- package/src/utils/transform.ts +186 -0
- package/src/utils/uiConfig.js +19 -22
- package/src/utils/windowViewport.ts +34 -0
- package/src/AnnoLabelInput.jsx +0 -109
- package/src/AnnoToolBar.jsx +0 -153
- package/src/Annotation/AnnoBar.jsx +0 -154
- package/src/Annotation/Annotation.jsx +0 -395
- package/src/Annotation/Annotation.scss +0 -47
- package/src/Annotation/BBox.jsx +0 -299
- package/src/Annotation/Edge.jsx +0 -92
- package/src/Annotation/InfSelectionArea.jsx +0 -72
- package/src/Annotation/Line.jsx +0 -68
- package/src/Annotation/Node.jsx +0 -282
- package/src/Annotation/Point.jsx +0 -200
- package/src/Annotation/Polygon.jsx +0 -404
- package/src/Annotation/logic/AnnotationUtils.ts +0 -30
- package/src/Canvas.jsx +0 -2194
- package/src/ImgBar.jsx +0 -131
- package/src/LabelInput.jsx +0 -238
- package/src/Prompt.jsx +0 -45
- package/src/SIAFilterButton.jsx +0 -186
- package/src/Sia.jsx +0 -478
- package/src/Sia2.tsx +0 -392
- package/src/SiaPopup.jsx +0 -15
- package/src/ToolBar.jsx +0 -463
- package/src/Toolbar/NavigationButtons.tsx +0 -21
- package/src/Toolbar/ToolbarItem.jsx +0 -30
- package/src/Toolbar/ToolbarItems/ImageToolItems/ImageLabel.tsx +0 -62
- package/src/Toolbar.css +0 -13
- package/src/ToolbarItem.jsx +0 -31
- package/src/filterTools.js +0 -5
- package/src/models/AllowedTools.tsx +0 -9
- package/src/models/AnnotationSettings.tsx +0 -9
- package/src/models/ExternalAnnotation.ts +0 -15
- package/src/models/Label.tsx +0 -8
- package/src/models/UiConfig.tsx +0 -6
- package/src/stories/Button.jsx +0 -54
- package/src/stories/Button.stories.js +0 -48
- package/src/stories/Header.jsx +0 -69
- package/src/stories/Header.stories.js +0 -28
- package/src/stories/Page.jsx +0 -87
- package/src/stories/Page.stories.js +0 -28
- package/src/stories/SIA2/DemoWrapper.stories.tsx +0 -167
- package/src/stories/SIA2/DemoWrapper.tsx +0 -54
- package/src/stories/SIA2/Sia2.stories.tsx +0 -62
- package/src/stories/Toolbar/ImageTools/ImageLabel.stories.tsx +0 -32
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +0 -5
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +0 -15
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +0 -3
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +0 -12
- package/src/stories/assets/youtube.svg +0 -4
- package/src/stories/button.css +0 -30
- package/src/stories/header.css +0 -32
- package/src/stories/lost.js +0 -54
- package/src/stories/page.css +0 -69
- package/src/stories/siaDummyData.js +0 -263
- package/src/stories/store.js +0 -18
- package/src/test.js +0 -7
- package/src/types/annoStatus.js +0 -4
- package/src/types/canvasActions.js +0 -58
- package/src/types/cursorstyles.js +0 -3
- package/src/types/modes.js +0 -9
- package/src/types/notificationType.js +0 -11
- package/src/types/toolbarEvents.js +0 -35
- package/src/types/tools.js +0 -17
- package/src/types.tsx +0 -11
- package/src/utils/annoConversion.js +0 -145
- package/src/utils/annoConversion2.ts +0 -145
- package/src/utils/colorlut.js +0 -68
- package/src/utils/constraints.js +0 -81
- package/src/utils/index.js +0 -1
- package/src/utils/keyActions.js +0 -113
- package/src/utils/mouse.js +0 -14
- package/src/utils/mouse2.ts +0 -35
- package/src/utils/transform.js +0 -336
- package/src/utils/transform2.ts +0 -343
- package/src/utils/windowViewport.js +0 -34
- package/src/utils/windowViewport2.ts +0 -50
package/src/Sia.tsx
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import { useEffect, useState, ReactElement, useRef, CSSProperties } from 'react'
|
|
2
|
+
import { CSpinner } from '@coreui/react'
|
|
3
|
+
import Canvas from './Canvas/Canvas'
|
|
4
|
+
import AnnotationTool from './models/AnnotationTool'
|
|
5
|
+
import Toolbar from './Toolbar/Toolbar'
|
|
6
|
+
import Annotation from './Annotation/logic/Annotation'
|
|
7
|
+
import AnnotationMode from './models/AnnotationMode'
|
|
8
|
+
import AnnotationStatus from './models/AnnotationStatus'
|
|
9
|
+
import {
|
|
10
|
+
AllowedTools,
|
|
11
|
+
AnnotationSettings,
|
|
12
|
+
ExternalAnnotation,
|
|
13
|
+
Label,
|
|
14
|
+
PolygonOperationResult,
|
|
15
|
+
SIANotification,
|
|
16
|
+
UiConfig,
|
|
17
|
+
} from './types'
|
|
18
|
+
|
|
19
|
+
type SiaProps = {
|
|
20
|
+
additionalButtons?: ReactElement
|
|
21
|
+
allowedTools?: AllowedTools
|
|
22
|
+
polygonOperationResult?: PolygonOperationResult
|
|
23
|
+
annotationSettings?: AnnotationSettings
|
|
24
|
+
defaultAnnotationTool?: AnnotationTool
|
|
25
|
+
defaultLabelId?: number
|
|
26
|
+
image?: string
|
|
27
|
+
isLoading?: boolean
|
|
28
|
+
isPolygonSelectionMode?: boolean
|
|
29
|
+
initialAnnotations?: ExternalAnnotation[]
|
|
30
|
+
initialImageLabelIds?: number[]
|
|
31
|
+
initialIsImageJunk?: boolean
|
|
32
|
+
possibleLabels: Label[]
|
|
33
|
+
uiConfig?: UiConfig
|
|
34
|
+
onAnnoCreated?: (createdAnno: Annotation, allAnnos: Annotation[]) => void
|
|
35
|
+
onAnnoCreationFinished?: (createdAnno: Annotation, allAnnos: Annotation[]) => void
|
|
36
|
+
onAnnoChanged?: (changedAnno: Annotation, allAnnos: Annotation[]) => void
|
|
37
|
+
onAnnoDeleted?: (deletedAnno: Annotation, allAnnos: Annotation[]) => void
|
|
38
|
+
onImageLabelsChanged?: (selectedImageIds: number[]) => void
|
|
39
|
+
onIsImageJunk?: (isJunk: boolean) => void
|
|
40
|
+
onNotification?: (notification: SIANotification) => void
|
|
41
|
+
onSelectAnnotation?: (annotation: Annotation) => void
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Main SIA component
|
|
46
|
+
*/
|
|
47
|
+
const Sia2 = ({
|
|
48
|
+
additionalButtons,
|
|
49
|
+
allowedTools: propAllowedTools,
|
|
50
|
+
polygonOperationResult = { annotationsToDelete: [], polygonsToCreate: [] },
|
|
51
|
+
annotationSettings: propAnnotationSettings,
|
|
52
|
+
uiConfig: propUiConfig,
|
|
53
|
+
defaultAnnotationTool,
|
|
54
|
+
defaultLabelId,
|
|
55
|
+
image,
|
|
56
|
+
isLoading = false,
|
|
57
|
+
isPolygonSelectionMode = false,
|
|
58
|
+
initialAnnotations = undefined,
|
|
59
|
+
initialImageLabelIds = undefined,
|
|
60
|
+
initialIsImageJunk = false,
|
|
61
|
+
possibleLabels,
|
|
62
|
+
onAnnoCreated = (_, __) => {},
|
|
63
|
+
onAnnoCreationFinished = (_, __) => {},
|
|
64
|
+
onAnnoChanged = (_, __) => {},
|
|
65
|
+
onAnnoDeleted = (_, __) => {},
|
|
66
|
+
onImageLabelsChanged = () => {},
|
|
67
|
+
onIsImageJunk = () => {},
|
|
68
|
+
onNotification = (_) => {},
|
|
69
|
+
onSelectAnnotation = (_) => {},
|
|
70
|
+
}: SiaProps) => {
|
|
71
|
+
const marginBetweenToolbarAndContainerPixels: number = 10
|
|
72
|
+
|
|
73
|
+
// ref for accessing the toolbar height (adjustable by screen size + custom components)
|
|
74
|
+
const toolbarContainerRef = useRef(null)
|
|
75
|
+
|
|
76
|
+
const [allowedTools, setAllowedTools] = useState<AllowedTools>()
|
|
77
|
+
|
|
78
|
+
const [annotations, setAnnotations] = useState<Annotation[]>([])
|
|
79
|
+
const [annotationSettings, setAnnotationSettings] = useState<AnnotationSettings>()
|
|
80
|
+
|
|
81
|
+
const [uiConfig, setUiConfig] = useState<UiConfig>()
|
|
82
|
+
|
|
83
|
+
const [selectedAnnotation, setSelectedAnnotation] = useState<Annotation>()
|
|
84
|
+
|
|
85
|
+
const [selectedAnnoTool, setSelectedAnnoTool] = useState<AnnotationTool>(
|
|
86
|
+
defaultAnnotationTool ?? AnnotationTool.Point,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// for adjusting the container/canvas size
|
|
90
|
+
// const [toolbarHeight, setToolbarHeight] = useState<number>(-1);
|
|
91
|
+
|
|
92
|
+
// const [outerContainerStyle, setOuterContainerStyle] = useState<CSSProperties>({
|
|
93
|
+
// // use the max available height as a flex child
|
|
94
|
+
// flex: '1 1 auto',
|
|
95
|
+
// minHeight: 0,
|
|
96
|
+
|
|
97
|
+
// // give the max available height to the next child
|
|
98
|
+
// display: 'flex',
|
|
99
|
+
// flexDirection: 'column',
|
|
100
|
+
// })
|
|
101
|
+
|
|
102
|
+
const [imageLabelIds, setImageLabelIds] = useState<number[]>(initialImageLabelIds)
|
|
103
|
+
|
|
104
|
+
const [isImageJunk, setIsImageJunk] = useState<boolean>()
|
|
105
|
+
const [isFullscreen, setIsFullscreen] = useState<boolean>(false)
|
|
106
|
+
|
|
107
|
+
// keep track which numbers are already used for annotation ids - even if they are deleted
|
|
108
|
+
const [usedInternalIds, setUsedInternalIds] = useState<number[]>([])
|
|
109
|
+
|
|
110
|
+
const deleteAnnotationByInternalId = (internalId: number) => {
|
|
111
|
+
// get index of selected annotation
|
|
112
|
+
const annoListIndex: number = annotations.findIndex(
|
|
113
|
+
(anno) => anno.internalId === internalId,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
// dereference list to force state update
|
|
117
|
+
const _annotations: Annotation[] = [...annotations]
|
|
118
|
+
|
|
119
|
+
// remove annotation
|
|
120
|
+
const removedAnno: Annotation = _annotations.splice(annoListIndex, 1)[0]
|
|
121
|
+
|
|
122
|
+
setAnnotations(_annotations)
|
|
123
|
+
setSelectedAnnotation(undefined)
|
|
124
|
+
|
|
125
|
+
// inform the outside world about our changes
|
|
126
|
+
onAnnoDeleted(removedAnno, _annotations)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const deleteSelectedAnnotation = () => {
|
|
130
|
+
if (selectedAnnotation === undefined) return
|
|
131
|
+
|
|
132
|
+
deleteAnnotationByInternalId(selectedAnnotation.internalId)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const createInitialAnnotations = () => {
|
|
136
|
+
// this is only run during initialization, so internal id list is always empty at this point
|
|
137
|
+
// fill this without the dedicated createNewInternalAnnotationId to avoid accessing old state
|
|
138
|
+
// setState in loop thats depending on its value => you are in react hell
|
|
139
|
+
let internalAnnoId: number = 0
|
|
140
|
+
|
|
141
|
+
// create internal annotation object from external annotations
|
|
142
|
+
// assign internal id, add default data if not set from the outside
|
|
143
|
+
const _annotations: Annotation[] = initialAnnotations.map(
|
|
144
|
+
(externalAnno: ExternalAnnotation) => {
|
|
145
|
+
const _anno: Annotation = {
|
|
146
|
+
...externalAnno,
|
|
147
|
+
internalId: internalAnnoId++,
|
|
148
|
+
mode: AnnotationMode.VIEW,
|
|
149
|
+
selectedNode: 1,
|
|
150
|
+
status: externalAnno.status,
|
|
151
|
+
annoTime: externalAnno.annoTime ?? 0,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return _anno
|
|
155
|
+
},
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
// list all used internal ids (from 0 to internalAnnoId)
|
|
159
|
+
setUsedInternalIds([...new Array(internalAnnoId).keys()])
|
|
160
|
+
|
|
161
|
+
setAnnotations(_annotations)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const createNewInternalAnnotationId = (): number => {
|
|
165
|
+
// find the next free number
|
|
166
|
+
let newInternalId: number = 0
|
|
167
|
+
while (usedInternalIds.includes(newInternalId)) newInternalId++
|
|
168
|
+
|
|
169
|
+
// add it to the used numbers (dereference list to trigger react state change)
|
|
170
|
+
const _usedInternalIds = [...usedInternalIds]
|
|
171
|
+
_usedInternalIds.push(newInternalId)
|
|
172
|
+
setUsedInternalIds(_usedInternalIds)
|
|
173
|
+
|
|
174
|
+
return newInternalId
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const handleAnnoEditing = (annotation: Annotation) => {
|
|
178
|
+
const _annotations: Annotation[] = [...annotations]
|
|
179
|
+
|
|
180
|
+
// annotation is being edited - remove it from current annotations for this time
|
|
181
|
+
const selectedAnnotationIndex: number = _annotations.findIndex(
|
|
182
|
+
(annotation: Annotation) =>
|
|
183
|
+
annotation.internalId === selectedAnnotation?.internalId,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
if (selectedAnnotationIndex === -1) return
|
|
187
|
+
|
|
188
|
+
// remove the old anno
|
|
189
|
+
const removedAnno: Annotation = _annotations.splice(selectedAnnotationIndex, 1)[0]
|
|
190
|
+
|
|
191
|
+
// do deletion state update without the new anno!
|
|
192
|
+
onAnnoDeleted(removedAnno, _annotations)
|
|
193
|
+
|
|
194
|
+
// add the new anno
|
|
195
|
+
const newAnnoations: Annotation[] = [..._annotations]
|
|
196
|
+
newAnnoations.push(annotation)
|
|
197
|
+
|
|
198
|
+
// update the list
|
|
199
|
+
setAnnotations(newAnnoations)
|
|
200
|
+
|
|
201
|
+
setSelectedAnnotation(annotation)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const handleImageJunk = (newJunkState: boolean) => {
|
|
205
|
+
setIsImageJunk(newJunkState)
|
|
206
|
+
onIsImageJunk(newJunkState)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
// remove current annotations when the image changes
|
|
211
|
+
if (image === undefined) {
|
|
212
|
+
setAnnotations([])
|
|
213
|
+
setSelectedAnnotation(undefined)
|
|
214
|
+
}
|
|
215
|
+
}, [image])
|
|
216
|
+
|
|
217
|
+
useEffect(() => {
|
|
218
|
+
setIsImageJunk(initialIsImageJunk)
|
|
219
|
+
|
|
220
|
+
// update the initial annotations only when the image is not set
|
|
221
|
+
// (the annotations are always loaded before the image)
|
|
222
|
+
// when we dont have any annos, we dont need to call it (prevents render errors on initialization)
|
|
223
|
+
if (
|
|
224
|
+
image !== undefined ||
|
|
225
|
+
initialAnnotations === undefined ||
|
|
226
|
+
initialAnnotations.length === 0
|
|
227
|
+
)
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
createInitialAnnotations()
|
|
231
|
+
}, [initialAnnotations])
|
|
232
|
+
|
|
233
|
+
useEffect(() => {
|
|
234
|
+
setImageLabelIds(initialImageLabelIds)
|
|
235
|
+
}, [initialImageLabelIds])
|
|
236
|
+
|
|
237
|
+
// update annotation settings if changed in the parent
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
const defaultAnnotationSettigs: AnnotationSettings = {
|
|
240
|
+
canCreate: true,
|
|
241
|
+
canEdit: true,
|
|
242
|
+
canHaveMultipleLabels: false,
|
|
243
|
+
canLabel: true,
|
|
244
|
+
minimalArea: 250,
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// use default values if a key is not set
|
|
248
|
+
const newAnnotationSettings = {
|
|
249
|
+
...defaultAnnotationSettigs,
|
|
250
|
+
...propAnnotationSettings,
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
setAnnotationSettings(newAnnotationSettings)
|
|
254
|
+
}, [propAnnotationSettings])
|
|
255
|
+
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
const defaultUiConfig: UiConfig = {
|
|
258
|
+
nodeRadius: 4,
|
|
259
|
+
strokeWidth: 4,
|
|
260
|
+
imageCentered: false,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// use default values if a key is not set
|
|
264
|
+
const newUiConfig = {
|
|
265
|
+
...defaultUiConfig,
|
|
266
|
+
...propUiConfig,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
setUiConfig(newUiConfig)
|
|
270
|
+
}, [propUiConfig])
|
|
271
|
+
|
|
272
|
+
// set default allowed tools if user has not specified them
|
|
273
|
+
useEffect(() => {
|
|
274
|
+
const defaultAllowedTools: AllowedTools = {
|
|
275
|
+
bbox: true,
|
|
276
|
+
point: true,
|
|
277
|
+
line: true,
|
|
278
|
+
junk: true,
|
|
279
|
+
polygon: true,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (propAllowedTools === undefined) return setAllowedTools(defaultAllowedTools)
|
|
283
|
+
|
|
284
|
+
setAllowedTools(propAllowedTools)
|
|
285
|
+
}, [propAllowedTools])
|
|
286
|
+
|
|
287
|
+
// useEffect(() => {
|
|
288
|
+
// if (toolbarHeight < 0) return;
|
|
289
|
+
|
|
290
|
+
// setOuterContainerStyle({
|
|
291
|
+
// height: `calc(100% - ${toolbarHeight}px)`,
|
|
292
|
+
// });
|
|
293
|
+
// }, [toolbarHeight]);
|
|
294
|
+
|
|
295
|
+
// useEffect(() => {
|
|
296
|
+
// if (toolbarContainerRef.current === null) return;
|
|
297
|
+
// const { width, height } =
|
|
298
|
+
// toolbarContainerRef.current.getBoundingClientRect();
|
|
299
|
+
|
|
300
|
+
// setToolbarHeight(height + marginBetweenToolbarAndContainerPixels);
|
|
301
|
+
// }, [toolbarContainerRef]);
|
|
302
|
+
|
|
303
|
+
const fullscreenStyle: CSSProperties = {
|
|
304
|
+
position: 'fixed',
|
|
305
|
+
top: 0,
|
|
306
|
+
left: 0,
|
|
307
|
+
zIndex: 6000,
|
|
308
|
+
backgroundColor: '#ffff',
|
|
309
|
+
width: '100%',
|
|
310
|
+
height: '100%',
|
|
311
|
+
padding: 15,
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const outerContainerStyle: CSSProperties = {
|
|
315
|
+
// use the max available height as a flex child
|
|
316
|
+
flex: '1 1 auto',
|
|
317
|
+
minHeight: 0,
|
|
318
|
+
|
|
319
|
+
// give the max available height to the next child
|
|
320
|
+
display: 'flex',
|
|
321
|
+
flexDirection: 'column',
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (allowedTools === undefined)
|
|
325
|
+
return (
|
|
326
|
+
<div className="d-flex justify-content-center">
|
|
327
|
+
<CSpinner color="primary" style={{ width: '5rem', height: '5rem' }} />
|
|
328
|
+
</div>
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
return (
|
|
332
|
+
<div
|
|
333
|
+
style={{
|
|
334
|
+
...(isFullscreen ? fullscreenStyle : {}),
|
|
335
|
+
// use the max available height as a flex child
|
|
336
|
+
flex: '1 1 auto',
|
|
337
|
+
minHeight: 0,
|
|
338
|
+
|
|
339
|
+
// give the max available height to the next child
|
|
340
|
+
display: 'flex',
|
|
341
|
+
flexDirection: 'column',
|
|
342
|
+
}}
|
|
343
|
+
>
|
|
344
|
+
<div
|
|
345
|
+
ref={toolbarContainerRef}
|
|
346
|
+
style={{
|
|
347
|
+
marginBottom: marginBetweenToolbarAndContainerPixels,
|
|
348
|
+
}}
|
|
349
|
+
>
|
|
350
|
+
<Toolbar
|
|
351
|
+
annotationSettings={annotationSettings}
|
|
352
|
+
allowedTools={allowedTools}
|
|
353
|
+
additionalButtons={additionalButtons}
|
|
354
|
+
isDisabled={isLoading}
|
|
355
|
+
isFullscreen={isFullscreen}
|
|
356
|
+
isImageJunk={isImageJunk}
|
|
357
|
+
imageLabelIds={imageLabelIds}
|
|
358
|
+
possibleLabels={possibleLabels}
|
|
359
|
+
selectedTool={selectedAnnoTool}
|
|
360
|
+
onImageLabelsChanged={(newImageLabelIds: number[]) => {
|
|
361
|
+
setImageLabelIds(newImageLabelIds)
|
|
362
|
+
onImageLabelsChanged(newImageLabelIds)
|
|
363
|
+
}}
|
|
364
|
+
onSetIsFullscreen={setIsFullscreen}
|
|
365
|
+
onSetIsImageJunk={handleImageJunk}
|
|
366
|
+
onSetSelectedTool={setSelectedAnnoTool}
|
|
367
|
+
onShouldDeleteSelectedAnnotation={deleteSelectedAnnotation}
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
<div style={outerContainerStyle}>
|
|
371
|
+
{isLoading && (
|
|
372
|
+
<div className="d-flex justify-content-center">
|
|
373
|
+
<CSpinner
|
|
374
|
+
color="primary"
|
|
375
|
+
style={{ width: '5rem', height: '5rem', marginTop: 200 }}
|
|
376
|
+
/>
|
|
377
|
+
</div>
|
|
378
|
+
)}
|
|
379
|
+
|
|
380
|
+
{image && annotations && (
|
|
381
|
+
<Canvas
|
|
382
|
+
annotations={annotations}
|
|
383
|
+
annotationSettings={annotationSettings}
|
|
384
|
+
defaultLabelId={defaultLabelId}
|
|
385
|
+
image={image}
|
|
386
|
+
isFullscreen={isFullscreen}
|
|
387
|
+
isImageJunk={isImageJunk}
|
|
388
|
+
isPolygonSelectionMode={isPolygonSelectionMode}
|
|
389
|
+
selectedAnnotation={selectedAnnotation}
|
|
390
|
+
selectedAnnoTool={selectedAnnoTool}
|
|
391
|
+
polygonOperationResult={polygonOperationResult}
|
|
392
|
+
possibleLabels={possibleLabels}
|
|
393
|
+
uiConfig={uiConfig}
|
|
394
|
+
onAnnoCreated={(annotation: Annotation) => {
|
|
395
|
+
const _annotations: Annotation[] = [...annotations]
|
|
396
|
+
_annotations.push(annotation)
|
|
397
|
+
setAnnotations(_annotations)
|
|
398
|
+
setSelectedAnnotation(annotation)
|
|
399
|
+
onAnnoCreated(annotation, _annotations)
|
|
400
|
+
}}
|
|
401
|
+
onAnnoChanged={(changedAnno: Annotation) => {
|
|
402
|
+
// update annotation list
|
|
403
|
+
const annoListIndex: number = annotations.findIndex(
|
|
404
|
+
(anno) => anno.internalId === changedAnno.internalId,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
// only fire event if item found
|
|
408
|
+
if (annoListIndex === -1) return
|
|
409
|
+
|
|
410
|
+
const _annotations: Annotation[] = [...annotations]
|
|
411
|
+
_annotations[annoListIndex] = changedAnno
|
|
412
|
+
setAnnotations(_annotations)
|
|
413
|
+
|
|
414
|
+
// inform the outside world about our change
|
|
415
|
+
onAnnoChanged(changedAnno, _annotations)
|
|
416
|
+
}}
|
|
417
|
+
onAnnoCreationFinished={(
|
|
418
|
+
changedAnno: Annotation,
|
|
419
|
+
hasAnnoJustBeenCreated: boolean,
|
|
420
|
+
) => {
|
|
421
|
+
// update annotation list
|
|
422
|
+
const _annotations: Annotation[] = [...annotations]
|
|
423
|
+
|
|
424
|
+
// remove the previous annotations we used to do the operation with
|
|
425
|
+
if (isPolygonSelectionMode) {
|
|
426
|
+
if (polygonOperationResult?.annotationsToDelete !== undefined) {
|
|
427
|
+
// we also want to remove the current selected annotation
|
|
428
|
+
polygonOperationResult.annotationsToDelete.push(selectedAnnotation)
|
|
429
|
+
|
|
430
|
+
for (const annotation of polygonOperationResult.annotationsToDelete) {
|
|
431
|
+
// polygonOperationResult.annotationsToDelete.forEach((annotation) => {
|
|
432
|
+
// remove annotations "the official way" (inform the server what we did)
|
|
433
|
+
deleteAnnotationByInternalId(annotation.internalId)
|
|
434
|
+
|
|
435
|
+
// since we are updating the annotations list after all the deletions again, their disappearance wouldn't be noticed
|
|
436
|
+
// therefore also manually remove the annotations here
|
|
437
|
+
|
|
438
|
+
// get index of selected annotation
|
|
439
|
+
const annoListIndex: number = _annotations.findIndex(
|
|
440
|
+
(anno) => anno.internalId === annotation.internalId,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
// remove annotation from object
|
|
444
|
+
_annotations.splice(annoListIndex, 1)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// are we just marking an existing annotation as finished or did we created it in the same frame
|
|
450
|
+
if (hasAnnoJustBeenCreated) _annotations.push(changedAnno)
|
|
451
|
+
else {
|
|
452
|
+
// all other annotation types
|
|
453
|
+
const annoListIndex: number = annotations.findIndex(
|
|
454
|
+
(anno) => anno.internalId === changedAnno.internalId,
|
|
455
|
+
)
|
|
456
|
+
_annotations[annoListIndex] = changedAnno
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
setAnnotations(_annotations)
|
|
460
|
+
|
|
461
|
+
// mark annotation as fully created
|
|
462
|
+
changedAnno.status = AnnotationStatus.CREATED
|
|
463
|
+
|
|
464
|
+
// inform the outer world about our changes
|
|
465
|
+
onAnnoCreationFinished(changedAnno, _annotations)
|
|
466
|
+
}}
|
|
467
|
+
onAnnoEditing={handleAnnoEditing}
|
|
468
|
+
onSetIsImageJunk={handleImageJunk}
|
|
469
|
+
onNotification={onNotification}
|
|
470
|
+
onRequestNewAnnoId={createNewInternalAnnotationId}
|
|
471
|
+
onSelectAnnotation={(annotation) => {
|
|
472
|
+
setSelectedAnnotation(annotation)
|
|
473
|
+
onSelectAnnotation(annotation)
|
|
474
|
+
}}
|
|
475
|
+
onSetSelectedTool={setSelectedAnnoTool}
|
|
476
|
+
onShouldDeleteAnno={deleteAnnotationByInternalId}
|
|
477
|
+
/>
|
|
478
|
+
)}
|
|
479
|
+
</div>
|
|
480
|
+
</div>
|
|
481
|
+
)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
export default Sia2
|
package/src/Toolbar/Toolbar.tsx
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { CCol, CRow } from
|
|
1
|
+
import { CCol, CRow } from '@coreui/react'
|
|
2
2
|
|
|
3
|
-
import AnnoToolSelector from
|
|
4
|
-
import ImageTools from
|
|
5
|
-
import AnnotationTool from
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import AnnotationSettings from "../models/AnnotationSettings";
|
|
10
|
-
import Label from "../models/Label";
|
|
3
|
+
import AnnoToolSelector from './ToolbarItems/AnnoToolSelector'
|
|
4
|
+
import ImageTools from './ToolbarItems/ImageTools'
|
|
5
|
+
import AnnotationTool from '../models/AnnotationTool'
|
|
6
|
+
import AccessibilityTools from './ToolbarItems/AccessibilityTools'
|
|
7
|
+
import { ReactElement } from 'react'
|
|
8
|
+
import { AllowedTools, AnnotationSettings, Label } from '../types'
|
|
11
9
|
|
|
12
10
|
type ToolbarProps = {
|
|
13
|
-
annotationSettings: AnnotationSettings
|
|
14
|
-
allowedTools: AllowedTools
|
|
15
|
-
additionalButtons
|
|
16
|
-
isImageJunk?: boolean
|
|
17
|
-
imageLabelIds?: number[]
|
|
18
|
-
isDisabled?: boolean
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
annotationSettings: AnnotationSettings
|
|
12
|
+
allowedTools: AllowedTools
|
|
13
|
+
additionalButtons?: ReactElement
|
|
14
|
+
isImageJunk?: boolean
|
|
15
|
+
imageLabelIds?: number[]
|
|
16
|
+
isDisabled?: boolean
|
|
17
|
+
isFullscreen?: boolean
|
|
18
|
+
possibleLabels: Label[]
|
|
19
|
+
selectedTool: AnnotationTool
|
|
20
|
+
onImageLabelsChanged?: (selectedImageIds: number[]) => void
|
|
21
|
+
onSetIsFullscreen?: (isFullscreen: boolean) => void
|
|
22
|
+
onSetIsImageJunk?: (isImageJunk: boolean) => void
|
|
23
|
+
onSetSelectedTool?: (selectedTool: AnnotationTool) => void
|
|
24
|
+
onShouldDeleteSelectedAnnotation?: () => void
|
|
25
|
+
}
|
|
26
26
|
|
|
27
27
|
const Toolbar = ({
|
|
28
28
|
annotationSettings,
|
|
@@ -31,33 +31,40 @@ const Toolbar = ({
|
|
|
31
31
|
isImageJunk = false,
|
|
32
32
|
imageLabelIds = [],
|
|
33
33
|
isDisabled = false,
|
|
34
|
+
isFullscreen = false,
|
|
34
35
|
possibleLabels,
|
|
35
36
|
selectedTool,
|
|
36
37
|
onImageLabelsChanged = () => {},
|
|
38
|
+
onSetIsFullscreen = () => {},
|
|
37
39
|
onSetIsImageJunk = () => {},
|
|
38
40
|
onSetSelectedTool = () => {},
|
|
39
41
|
onShouldDeleteSelectedAnnotation = () => {},
|
|
40
42
|
}: ToolbarProps) => {
|
|
41
43
|
return (
|
|
42
|
-
<CRow
|
|
43
|
-
<CCol xs=
|
|
44
|
+
<CRow className="d-flex justify-content-center flex-wrap align-items-center gap-0 py-2 px-4">
|
|
45
|
+
<CCol xs="auto">
|
|
44
46
|
<ImageTools
|
|
45
47
|
canJunk={allowedTools.junk}
|
|
46
48
|
isImageJunk={isImageJunk}
|
|
47
49
|
imageLabelIds={imageLabelIds}
|
|
48
50
|
isDisabled={isDisabled}
|
|
51
|
+
isFullscreen={isFullscreen}
|
|
49
52
|
possibleLabels={possibleLabels}
|
|
50
53
|
onImageLabelsChanged={onImageLabelsChanged}
|
|
51
54
|
onSetIsImageJunk={onSetIsImageJunk}
|
|
52
55
|
/>
|
|
53
56
|
</CCol>
|
|
54
57
|
|
|
55
|
-
<CCol xs=
|
|
56
|
-
<AccessibilityTools
|
|
58
|
+
<CCol xs="auto">
|
|
59
|
+
<AccessibilityTools
|
|
60
|
+
isDisabled={isDisabled}
|
|
61
|
+
isFullscreen={isFullscreen}
|
|
62
|
+
onSetIsFullscreen={onSetIsFullscreen}
|
|
63
|
+
/>
|
|
57
64
|
</CCol>
|
|
58
65
|
|
|
59
66
|
{annotationSettings.canCreate && (
|
|
60
|
-
<CCol xs=
|
|
67
|
+
<CCol xs="auto">
|
|
61
68
|
<AnnoToolSelector
|
|
62
69
|
allowedTools={allowedTools}
|
|
63
70
|
isDisabled={isDisabled}
|
|
@@ -68,9 +75,9 @@ const Toolbar = ({
|
|
|
68
75
|
</CCol>
|
|
69
76
|
)}
|
|
70
77
|
|
|
71
|
-
{additionalButtons
|
|
78
|
+
{additionalButtons}
|
|
72
79
|
</CRow>
|
|
73
|
-
)
|
|
74
|
-
}
|
|
80
|
+
)
|
|
81
|
+
}
|
|
75
82
|
|
|
76
|
-
export default Toolbar
|
|
83
|
+
export default Toolbar
|
|
@@ -1,69 +1,49 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
faQuestion,
|
|
7
|
-
} from "@fortawesome/free-solid-svg-icons";
|
|
8
|
-
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
9
|
-
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
|
10
|
-
import { useState } from "react";
|
|
11
|
-
import InstructionsModal from "./InstructionsModal";
|
|
1
|
+
import { CButtonGroup } from '@coreui/react'
|
|
2
|
+
import { faMaximize, faQuestion } from '@fortawesome/free-solid-svg-icons'
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
import InstructionsModal from './InstructionsModal'
|
|
5
|
+
import IconButton from '../../IconButton'
|
|
12
6
|
|
|
13
7
|
type AccessibilityToolsProps = {
|
|
14
|
-
isDisabled?: boolean
|
|
15
|
-
|
|
8
|
+
isDisabled?: boolean
|
|
9
|
+
isFullscreen?: boolean
|
|
10
|
+
onSetIsFullscreen?: (isFullscreen: boolean) => void
|
|
11
|
+
}
|
|
16
12
|
|
|
17
13
|
const AccessibilityTools = ({
|
|
18
14
|
isDisabled = false,
|
|
15
|
+
isFullscreen = false,
|
|
16
|
+
onSetIsFullscreen = () => {},
|
|
19
17
|
}: AccessibilityToolsProps) => {
|
|
20
18
|
const [isInstructionsModalVisible, setIsInstructionsModalVisible] =
|
|
21
|
-
useState<boolean>(false)
|
|
19
|
+
useState<boolean>(false)
|
|
22
20
|
|
|
23
21
|
return (
|
|
24
22
|
<CButtonGroup role="group" aria-label="Basic example">
|
|
25
|
-
|
|
23
|
+
<IconButton
|
|
26
24
|
color="primary"
|
|
25
|
+
icon={faMaximize}
|
|
26
|
+
isOutline={!isFullscreen}
|
|
27
27
|
disabled={isDisabled}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<FontAwesomeIcon icon={faFilter as IconProp} size="lg" />
|
|
32
|
-
</CButton> */}
|
|
33
|
-
|
|
34
|
-
{/* <CButton
|
|
35
|
-
color="primary"
|
|
36
|
-
disabled={isDisabled}
|
|
37
|
-
variant="outline"
|
|
38
|
-
onClick={() => {}}
|
|
39
|
-
>
|
|
40
|
-
<FontAwesomeIcon icon={faMaximize as IconProp} size="lg" />
|
|
41
|
-
</CButton>
|
|
42
|
-
|
|
43
|
-
<CButton
|
|
44
|
-
color="primary"
|
|
45
|
-
disabled={isDisabled}
|
|
46
|
-
variant="outline"
|
|
47
|
-
onClick={() => {}}
|
|
48
|
-
>
|
|
49
|
-
<FontAwesomeIcon icon={faCog as IconProp} size="lg" />
|
|
50
|
-
</CButton> */}
|
|
28
|
+
onClick={() => onSetIsFullscreen(!isFullscreen)}
|
|
29
|
+
tooltip="Toggle fullscreen"
|
|
30
|
+
/>
|
|
51
31
|
|
|
52
|
-
<
|
|
32
|
+
<IconButton
|
|
53
33
|
color="primary"
|
|
34
|
+
icon={faQuestion}
|
|
35
|
+
isOutline={true}
|
|
54
36
|
disabled={isDisabled}
|
|
55
|
-
variant="outline"
|
|
56
37
|
onClick={() => setIsInstructionsModalVisible(true)}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
</CButton>
|
|
38
|
+
tooltip="Open instructions"
|
|
39
|
+
/>
|
|
60
40
|
|
|
61
41
|
<InstructionsModal
|
|
62
42
|
isOpen={isInstructionsModalVisible}
|
|
63
43
|
setIsOpen={setIsInstructionsModalVisible}
|
|
64
44
|
/>
|
|
65
45
|
</CButtonGroup>
|
|
66
|
-
)
|
|
67
|
-
}
|
|
46
|
+
)
|
|
47
|
+
}
|
|
68
48
|
|
|
69
|
-
export default AccessibilityTools
|
|
49
|
+
export default AccessibilityTools
|