@dhis2-ui/node 10.16.2 → 10.16.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/node",
3
- "version": "10.16.2",
3
+ "version": "10.16.3",
4
4
  "description": "UI Node",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,14 +33,15 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@dhis2/prop-types": "^3.1.2",
36
- "@dhis2-ui/loader": "10.16.2",
37
- "@dhis2/ui-constants": "10.16.2",
36
+ "@dhis2-ui/loader": "10.16.3",
37
+ "@dhis2/ui-constants": "10.16.3",
38
38
  "classnames": "^2.3.1",
39
39
  "prop-types": "^15.7.2"
40
40
  },
41
41
  "files": [
42
42
  "build",
43
- "types"
43
+ "types",
44
+ "src"
44
45
  ],
45
46
  "devDependencies": {
46
47
  "react": "^18.3.1",
@@ -0,0 +1,23 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a closed Node with children is rendered', () => {
4
+ cy.visitStory('Node', 'Closed with children')
5
+ cy.get('[data-test="dhis2-uicore-node"]').should('be.visible')
6
+ })
7
+
8
+ Given('an open Node with children is rendered', () => {
9
+ cy.visitStory('Node', 'Open with children')
10
+ cy.get('[data-test="dhis2-uicore-node"]').should('be.visible')
11
+ })
12
+
13
+ Then('the children are visible', () => {
14
+ cy.get('[data-test="dhis2-uicore-node-leaves"]')
15
+ .contains('I am a child')
16
+ .should('be.visible')
17
+ })
18
+
19
+ Then('the children are not visible', () => {
20
+ cy.get('[data-test="dhis2-uicore-node-leaves"]')
21
+ .contains('I am a child')
22
+ .should('not.be.visible')
23
+ })
@@ -0,0 +1,9 @@
1
+ Feature: The Node renders children
2
+
3
+ Scenario: A closed Node with children
4
+ Given a closed Node with children is rendered
5
+ Then the children are not visible
6
+
7
+ Scenario: An open Node with children
8
+ Given an open Node with children is rendered
9
+ Then the children are visible
@@ -0,0 +1,12 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a Node with component prop is rendered', () => {
4
+ cy.visitStory('Node', 'With component')
5
+ cy.get('[data-test="dhis2-uicore-node"]').should('be.visible')
6
+ })
7
+
8
+ Then('the component is visible', () => {
9
+ cy.get('[data-test="dhis2-uicore-node-label"]')
10
+ .contains('I am a component')
11
+ .should('be.visible')
12
+ })
@@ -0,0 +1,5 @@
1
+ Feature: The Node accepts a component prop
2
+
3
+ Scenario: A Node with component
4
+ Given a Node with component prop is rendered
5
+ Then the component is visible
@@ -0,0 +1,12 @@
1
+ import { Given, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a Node with icon prop is rendered', () => {
4
+ cy.visitStory('Node', 'With icon')
5
+ cy.get('[data-test="dhis2-uicore-node"]').should('be.visible')
6
+ })
7
+
8
+ Then('the icon is visible', () => {
9
+ cy.get('[data-test="dhis2-uicore-node-icon"]')
10
+ .contains('Icon')
11
+ .should('be.visible')
12
+ })
@@ -0,0 +1,5 @@
1
+ Feature: The Node accepts an icon prop
2
+
3
+ Scenario: A Node with icon
4
+ Given a Node with icon prop is rendered
5
+ Then the icon is visible
@@ -0,0 +1,15 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('an open Node with an onClose handler is rendered', () => {
4
+ cy.visitStory('Node', 'Open with on close')
5
+ })
6
+
7
+ When('the arrow is clicked', () => {
8
+ cy.get('[data-test="dhis2-uicore-node-toggle"]').click()
9
+ })
10
+
11
+ Then('the onClose handler is called', () => {
12
+ cy.window().should((win) => {
13
+ expect(win.onClose).to.be.calledWith({ open: false })
14
+ })
15
+ })
@@ -0,0 +1,6 @@
1
+ Feature: The Node has an onClose api
2
+
3
+ Scenario: The user closes the Node
4
+ Given an open Node with an onClose handler is rendered
5
+ When the arrow is clicked
6
+ Then the onClose handler is called
@@ -0,0 +1,15 @@
1
+ import { Given, When, Then } from '@badeball/cypress-cucumber-preprocessor'
2
+
3
+ Given('a closed Node with an onOpen handler is rendered', () => {
4
+ cy.visitStory('Node', 'Closed with on open')
5
+ })
6
+
7
+ When('the arrow is clicked', () => {
8
+ cy.get('[data-test="dhis2-uicore-node-toggle"]').click()
9
+ })
10
+
11
+ Then('the onOpen handler is called', () => {
12
+ cy.window().should((win) => {
13
+ expect(win.onOpen).to.be.calledWith({ open: true })
14
+ })
15
+ })
@@ -0,0 +1,6 @@
1
+ Feature: The Node has an onOpen api
2
+
3
+ Scenario: The user opens the Node
4
+ Given a closed Node with an onOpen handler is rendered
5
+ When the arrow is clicked
6
+ Then the onOpen handler is called
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ export { Node } from './node.js'
package/src/leaves.js ADDED
@@ -0,0 +1,27 @@
1
+ import cx from 'classnames'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ export const Leaves = ({ children, open, dataTest }) => (
6
+ <div className={cx({ open })} data-test={dataTest}>
7
+ {children}
8
+
9
+ <style jsx>{`
10
+ div {
11
+ height: 0;
12
+ overflow: hidden;
13
+ flex-grow: 1;
14
+ }
15
+
16
+ .open {
17
+ height: auto;
18
+ }
19
+ `}</style>
20
+ </div>
21
+ )
22
+
23
+ Leaves.propTypes = {
24
+ children: PropTypes.node,
25
+ dataTest: PropTypes.string,
26
+ open: PropTypes.bool,
27
+ }
@@ -0,0 +1,33 @@
1
+ import React from 'react'
2
+ import { Node } from './node.js'
3
+
4
+ window.onClose = window.Cypress && window.Cypress.cy.stub()
5
+ window.onOpen = window.Cypress && window.Cypress.cy.stub()
6
+
7
+ export default { title: 'Node' }
8
+ export const OpenWithOnClose = () => (
9
+ <Node open onClose={window.onClose} component={<div>Component</div>}>
10
+ Children
11
+ </Node>
12
+ )
13
+ export const ClosedWithOnOpen = () => (
14
+ <Node onOpen={window.onOpen} component={<div>Component</div>}>
15
+ Children
16
+ </Node>
17
+ )
18
+ export const ClosedWithChildren = () => (
19
+ <Node component={<div>Component</div>}>I am a child</Node>
20
+ )
21
+ export const OpenWithChildren = () => (
22
+ <Node open component={<div>Component</div>}>
23
+ I am a child
24
+ </Node>
25
+ )
26
+ export const WithComponent = () => (
27
+ <Node component={<div>I am a component</div>}>Children</Node>
28
+ )
29
+ export const WithIcon = () => (
30
+ <Node component={<div>Component</div>} icon={<div>Icon</div>}>
31
+ Children
32
+ </Node>
33
+ )
package/src/node.js ADDED
@@ -0,0 +1,66 @@
1
+ import cx from 'classnames'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+ import { Leaves } from './leaves.js'
5
+ import { Spacer } from './spacer.js'
6
+ import { Toggle } from './toggle.js'
7
+
8
+ export const Node = ({
9
+ open,
10
+ className,
11
+ component: label,
12
+ children,
13
+ icon,
14
+ onOpen,
15
+ onClose,
16
+ dataTest = 'dhis2-uicore-node',
17
+ }) => {
18
+ const hasLeaves = !!React.Children.toArray(children).filter((i) => i).length
19
+ const showArrow = !icon && hasLeaves
20
+ const showSpacer = !icon && !hasLeaves
21
+
22
+ return (
23
+ <div className={cx('node', className)} data-test={dataTest}>
24
+ {icon && <div data-test={`${dataTest}-icon`}>{icon}</div>}
25
+
26
+ {showArrow && (
27
+ <Toggle
28
+ open={open}
29
+ onOpen={onOpen}
30
+ onClose={onClose}
31
+ dataTest={`${dataTest}-toggle`}
32
+ />
33
+ )}
34
+
35
+ {showSpacer && <Spacer />}
36
+
37
+ <div data-test={`${dataTest}-content`}>
38
+ <div data-test={`${dataTest}-label`}>{label}</div>
39
+
40
+ <Leaves open={open} dataTest={`${dataTest}-leaves`}>
41
+ {children}
42
+ </Leaves>
43
+ </div>
44
+
45
+ <style jsx>{`
46
+ .node {
47
+ display: flex;
48
+ }
49
+ `}</style>
50
+ </div>
51
+ )
52
+ }
53
+
54
+ Node.propTypes = {
55
+ /** Content below this level of the hierarchy; children are revealed when this leaf is 'open' */
56
+ children: PropTypes.node,
57
+ className: PropTypes.string,
58
+ /** Content/label for this leaf, for example a checkbox */
59
+ component: PropTypes.element,
60
+ dataTest: PropTypes.string,
61
+ /** A custom icon to use instead of a toggle arrow */
62
+ icon: PropTypes.node,
63
+ open: PropTypes.bool,
64
+ onClose: PropTypes.func,
65
+ onOpen: PropTypes.func,
66
+ }
@@ -0,0 +1,404 @@
1
+ import { Checkbox } from '@dhis2-ui/checkbox'
2
+ import { CircularLoader } from '@dhis2-ui/loader'
3
+ import React from 'react'
4
+ import { Node } from './node.js'
5
+
6
+ const description = `
7
+ A tool for creating hierarchical, multi-level selectors. Applied in the Organisation Unit Tree component, for example.
8
+
9
+ \`\`\`js
10
+ import { Node } from '@dhis2/ui'
11
+ \`\`\`
12
+ `
13
+
14
+ const say = (something) => () => alert(something)
15
+
16
+ window.onOpen = (payload, event) => {
17
+ console.log('onOpen payload', payload)
18
+ console.log('onOpen event', event)
19
+ }
20
+
21
+ window.onClose = (payload, event) => {
22
+ console.log('onClose payload', payload)
23
+ console.log('onClose event', event)
24
+ }
25
+
26
+ const onOpen = (...args) => window.onOpen(...args)
27
+ const onClose = (...args) => window.onClose(...args)
28
+
29
+ export default {
30
+ title: 'Node',
31
+ component: Node,
32
+ parameters: { docs: { description: { component: description } } },
33
+ }
34
+
35
+ export const CustomIcon = (args) => <Node {...args} />
36
+ CustomIcon.args = {
37
+ icon: <CircularLoader small />,
38
+ open: false,
39
+ onOpen: onOpen,
40
+ onClose: onClose,
41
+ component: (
42
+ <Checkbox
43
+ label="Node label 1.1"
44
+ value="foobar"
45
+ name="l1.1"
46
+ onChange={say('checkbox 1.1 clicked')}
47
+ checked={false}
48
+ />
49
+ ),
50
+ }
51
+ CustomIcon.storyName = 'Custom icon'
52
+
53
+ export const MultipleRoots = (args) => (
54
+ <div>
55
+ <Node
56
+ {...args}
57
+ component={
58
+ <Checkbox
59
+ label="Node label 1.1"
60
+ value="foobar"
61
+ name="l1.1"
62
+ onChange={say('checkbox 1.1 clicked')}
63
+ checked={false}
64
+ />
65
+ }
66
+ >
67
+ <span>Placeholder content</span>
68
+ </Node>
69
+
70
+ <Node
71
+ {...args}
72
+ component={
73
+ <Checkbox
74
+ label="Node label 1.2"
75
+ value="foobar"
76
+ name="l1.2"
77
+ onChange={say('checkbox 1.2 clicked')}
78
+ checked={false}
79
+ />
80
+ }
81
+ >
82
+ <span>Placeholder content</span>
83
+ </Node>
84
+ </div>
85
+ )
86
+ MultipleRoots.args = { open: false, onOpen, onClose }
87
+ MultipleRoots.storyName = 'Multiple roots'
88
+
89
+ export const _2LevelsOpen = () => (
90
+ <Node
91
+ open={true}
92
+ onOpen={onOpen}
93
+ onClose={onClose}
94
+ component={
95
+ <Checkbox
96
+ label="Node label"
97
+ value="foobar"
98
+ name="l1.1"
99
+ onChange={say('Check 1.1')}
100
+ checked={false}
101
+ />
102
+ }
103
+ >
104
+ <Node
105
+ open={true}
106
+ onOpen={onOpen}
107
+ onClose={onClose}
108
+ component={
109
+ <Checkbox
110
+ label="Node label"
111
+ value="foobar"
112
+ name="l2.1"
113
+ onChange={say('Check 2.1')}
114
+ checked={false}
115
+ />
116
+ }
117
+ >
118
+ <Node
119
+ component={
120
+ <Checkbox
121
+ label="Node label"
122
+ name="l3.1"
123
+ value="foobar"
124
+ onChange={say('Check 3.1')}
125
+ checked={false}
126
+ />
127
+ }
128
+ />
129
+ <Node
130
+ component={
131
+ <Checkbox
132
+ label="Node label"
133
+ name="l3.2"
134
+ onChange={say('Check 3.2')}
135
+ value="foobar"
136
+ checked={false}
137
+ />
138
+ }
139
+ />
140
+ <Node
141
+ component={
142
+ <Checkbox
143
+ label="Node label"
144
+ name="l3.3"
145
+ onChange={say('Check 3.3')}
146
+ checked={false}
147
+ value="foobar"
148
+ />
149
+ }
150
+ />
151
+ </Node>
152
+ <Node
153
+ open={false}
154
+ onOpen={onOpen}
155
+ onClose={say('close tree 2.2')}
156
+ component={
157
+ <Checkbox
158
+ label="Node label"
159
+ name="l3.1"
160
+ onChange={say('Check 2.2')}
161
+ value="foobar"
162
+ checked={false}
163
+ />
164
+ }
165
+ >
166
+ <Node
167
+ component={
168
+ <Checkbox
169
+ label="Node label"
170
+ name="l3.4"
171
+ value="foobar"
172
+ onChange={say('Check 3.4')}
173
+ checked={false}
174
+ />
175
+ }
176
+ />
177
+ <Node
178
+ component={
179
+ <Checkbox
180
+ label="Node label"
181
+ name="l3.5"
182
+ onChange={say('Check 3.5')}
183
+ value="foobar"
184
+ checked={false}
185
+ />
186
+ }
187
+ />
188
+ <Node
189
+ component={
190
+ <Checkbox
191
+ label="Node label"
192
+ name="l3.6"
193
+ onChange={say('Check 3.6')}
194
+ value="foobar"
195
+ checked={false}
196
+ />
197
+ }
198
+ />
199
+ </Node>
200
+ <Node
201
+ open={false}
202
+ onOpen={onOpen}
203
+ onClose={onClose}
204
+ component={
205
+ <Checkbox
206
+ label="Node label"
207
+ name="l2.3"
208
+ value="foobar"
209
+ onChange={say('Check 2.3')}
210
+ checked={false}
211
+ />
212
+ }
213
+ />
214
+ <Node
215
+ open={false}
216
+ onOpen={onOpen}
217
+ onClose={onClose}
218
+ component={
219
+ <Checkbox
220
+ label="Node label"
221
+ name="l2.4"
222
+ onChange={say('Check 2.4')}
223
+ value="foobar"
224
+ checked={false}
225
+ />
226
+ }
227
+ />
228
+ <Node
229
+ open={false}
230
+ onOpen={onOpen}
231
+ onClose={onClose}
232
+ component={
233
+ <Checkbox
234
+ label="Node label"
235
+ name="l2.5"
236
+ value="foobar"
237
+ onChange={say('Check 2.5')}
238
+ checked={false}
239
+ />
240
+ }
241
+ />
242
+ <Node
243
+ open={false}
244
+ onOpen={onOpen}
245
+ onClose={onClose}
246
+ component={
247
+ <Checkbox
248
+ label="Node label"
249
+ name="l2.5"
250
+ value="foobar"
251
+ onChange={say('Check 2.5')}
252
+ checked={false}
253
+ />
254
+ }
255
+ >
256
+ {false && 'Foo'}
257
+ </Node>
258
+ </Node>
259
+ )
260
+ _2LevelsOpen.storyName = '2 Levels open'
261
+
262
+ export const TextLeaves = () => (
263
+ <div>
264
+ <Node
265
+ open={true}
266
+ onOpen={onOpen}
267
+ onClose={onClose}
268
+ arrowTopOffset="10px"
269
+ component={
270
+ <h2>Lorem ipsum dolor sit amet, consetetur sadipscing elitr</h2>
271
+ }
272
+ >
273
+ Sed diam nonumy eirmod tempor invidunt ut labore et dolore magna
274
+ aliquyam erat, sed diam voluptua. At vero eos et accusam et justo
275
+ duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata
276
+ sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet,
277
+ consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt
278
+ ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero
279
+ eos et accusam et justo duo dolores et ea rebum. Stet clita kasd
280
+ gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
281
+ <div className="sub-tree sub-tree--open">
282
+ <Node
283
+ open={true}
284
+ onOpen={onOpen}
285
+ onClose={onClose}
286
+ component={
287
+ <h2>
288
+ Lorem ipsum dolor sit amet, consetetur sadipscing
289
+ elitr
290
+ </h2>
291
+ }
292
+ >
293
+ Sed diam nonumy eirmod tempor invidunt ut labore et dolore
294
+ magna aliquyam erat, sed diam voluptua. At vero eos et
295
+ accusam et justo duo dolores et ea rebum. Stet clita kasd
296
+ gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
297
+ amet. Lorem ipsum dolor sit amet, consetetur sadipscing
298
+ elitr, sed diam nonumy eirmod tempor invidunt ut labore et
299
+ dolore magna aliquyam erat, sed diam voluptua. At vero eos
300
+ et accusam et justo duo dolores et ea rebum. Stet clita kasd
301
+ gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
302
+ amet.
303
+ </Node>
304
+ </div>
305
+ <div className="sub-tree">
306
+ <Node
307
+ open={false}
308
+ onOpen={onOpen}
309
+ onClose={onClose}
310
+ component={
311
+ <h2>
312
+ Lorem ipsum dolor sit amet, consetetur sadipscing
313
+ elitr
314
+ </h2>
315
+ }
316
+ >
317
+ <span>Dummy content</span>
318
+ </Node>
319
+ </div>
320
+ <div className="sub-tree">
321
+ <Node
322
+ open={false}
323
+ onOpen={onOpen}
324
+ onClose={onClose}
325
+ component={
326
+ <h2>
327
+ Lorem ipsum dolor sit amet, consetetur sadipscing
328
+ elitr
329
+ </h2>
330
+ }
331
+ >
332
+ <span>Dummy content</span>
333
+ </Node>
334
+ </div>
335
+ <div className="sub-tree">
336
+ <Node
337
+ open={false}
338
+ onOpen={onOpen}
339
+ onClose={onClose}
340
+ component={
341
+ <h2>
342
+ Lorem ipsum dolor sit amet, consetetur sadipscing
343
+ elitr
344
+ </h2>
345
+ }
346
+ >
347
+ <span>Dummy content</span>
348
+ </Node>
349
+ </div>
350
+ <div className="sub-tree">
351
+ <Node
352
+ open={false}
353
+ onOpen={onOpen}
354
+ onClose={onClose}
355
+ component={
356
+ <h2>
357
+ Lorem ipsum dolor sit amet, consetetur sadipscing
358
+ elitr
359
+ </h2>
360
+ }
361
+ >
362
+ <span>Dummy content</span>
363
+ </Node>
364
+ </div>
365
+ </Node>
366
+
367
+ <style jsx>{`
368
+ div {
369
+ font-size: 16px;
370
+ line-height: 24px;
371
+ }
372
+
373
+ h2 {
374
+ font-size: 24px;
375
+ line-height: 32px;
376
+ margin: 0 0 10px;
377
+ }
378
+
379
+ .sub-tree {
380
+ margin-top: 10px;
381
+ }
382
+
383
+ .sub-tree--open {
384
+ margin-bottom: 20px;
385
+ }
386
+
387
+ div :global(.tree__arrow > span) {
388
+ padding-top: 4px;
389
+ }
390
+
391
+ div :global(.tree__arrow.open:after) {
392
+ top: 17px;
393
+ height: calc(100% - 28px);
394
+ }
395
+ `}</style>
396
+ </div>
397
+ )
398
+ TextLeaves.storyName = 'Text leaves'
399
+
400
+ export const RTL = (args) => (
401
+ <div dir="rtl">
402
+ <MultipleRoots {...args} />
403
+ </div>
404
+ )
package/src/spacer.js ADDED
@@ -0,0 +1,11 @@
1
+ import React from 'react'
2
+
3
+ export const Spacer = () => (
4
+ <div>
5
+ <style jsx>{`
6
+ div {
7
+ width: 24px;
8
+ }
9
+ `}</style>
10
+ </div>
11
+ )
package/src/toggle.js ADDED
@@ -0,0 +1,93 @@
1
+ import { colors } from '@dhis2/ui-constants'
2
+ import cx from 'classnames'
3
+ import PropTypes from 'prop-types'
4
+ import React from 'react'
5
+
6
+ const ArrowDown = () => (
7
+ <div className="nodeArrow">
8
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
9
+ <path d="M15.7041 10.3329L12.1495 14.3318C12.0699 14.4213 11.9301 14.4213 11.8505 14.3318L8.29589 10.3329C8.18124 10.2039 8.2728 10 8.44537 10H15.5546C15.7272 10 15.8188 10.2039 15.7041 10.3329Z" />
10
+ <style jsx>{`
11
+ svg {
12
+ fill: inherit;
13
+ height: 24px;
14
+ width: 24px;
15
+ vertical-align: middle;
16
+ pointer-events: none;
17
+ }
18
+ `}</style>
19
+ </svg>
20
+ </div>
21
+ )
22
+
23
+ export const Toggle = ({ open, onOpen, onClose, dataTest }) => {
24
+ const onClick = open ? onClose : onOpen
25
+
26
+ return (
27
+ <div
28
+ className={cx({ open })}
29
+ data-test={dataTest}
30
+ onClick={(event) => onClick && onClick({ open: !open }, event)}
31
+ >
32
+ <span>
33
+ <ArrowDown />
34
+ </span>
35
+
36
+ <style jsx>{`
37
+ div {
38
+ width: 24px;
39
+ position: relative;
40
+ flex-shrink: 0;
41
+ }
42
+ div:after {
43
+ background: ${colors.grey400};
44
+ height: calc(100% - 24px);
45
+ inset-inline-start: 12px;
46
+ position: absolute;
47
+ top: 15px;
48
+ width: 1px;
49
+ z-index: 1;
50
+ }
51
+ .open:after {
52
+ content: '';
53
+ }
54
+ span {
55
+ display: block;
56
+ position: relative;
57
+ z-index: 2;
58
+ fill: ${colors.grey900};
59
+ }
60
+ div :global(.nodeArrow) {
61
+ vertical-align: top;
62
+ transform: rotate(-90deg);
63
+ transition: transform 0.1s ease-out;
64
+ }
65
+ div :global(.nodeArrow:dir(rtl)) {
66
+ transform: rotate(90deg);
67
+ }
68
+ .open :global(.nodeArrow) {
69
+ transform: rotate(0);
70
+ }
71
+ .open :global(.nodeArrow:dir(rtl)) {
72
+ transform: rotate(0);
73
+ }
74
+
75
+ div:hover {
76
+ cursor: pointer;
77
+ border-radius: 3px;
78
+ background: ${colors.grey100};
79
+ }
80
+ div:hover:after {
81
+ background: #bcc8d4;
82
+ }
83
+ `}</style>
84
+ </div>
85
+ )
86
+ }
87
+
88
+ Toggle.propTypes = {
89
+ dataTest: PropTypes.string.isRequired,
90
+ open: PropTypes.bool,
91
+ onClose: PropTypes.func,
92
+ onOpen: PropTypes.func,
93
+ }