@eturnity/eturnity_reusable_components 9.37.0 → 9.37.1-ATE-87.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/dist/index.es3.js +3 -3
- package/package.json +1 -1
- package/src/assets/theme.js +3 -3
- package/src/components/inputs/select/option/index.vue +6 -9
- package/src/components/inputs/select/option/option.spec.js +39 -0
- package/src/components/selectedOptions/index.vue +67 -100
- package/src/components/selectedOptions/selectedOptions.spec.js +242 -6
- package/src/components/selectedOptions/selectedOptions.stories.js +5 -5
- package/src/components/tableDropdown/index.vue +2 -2
- package/src/components/tables/mainTable/index.vue +7 -5
- package/src/components/threeDots/index.vue +5 -5
- package/src/components/threeDots/threeDots.spec.js +25 -0
package/dist/index.es3.js
CHANGED
|
@@ -815,8 +815,8 @@ const theme = (() => {
|
|
|
815
815
|
iconBackgroundColor: semanticColors.buttonIcon.overlayWhite10
|
|
816
816
|
},
|
|
817
817
|
disabled: {
|
|
818
|
-
textColor: semanticColors.
|
|
819
|
-
backgroundColor:
|
|
818
|
+
textColor: semanticColors.transparentWhite[400],
|
|
819
|
+
backgroundColor: "transparent",
|
|
820
820
|
borderColor: "",
|
|
821
821
|
iconBackgroundColor: semanticColors.buttonIcon.none
|
|
822
822
|
}
|
|
@@ -843,7 +843,7 @@ const theme = (() => {
|
|
|
843
843
|
},
|
|
844
844
|
disabled: {
|
|
845
845
|
backgroundColor: "transparent",
|
|
846
|
-
textColor: semanticColors.
|
|
846
|
+
textColor: semanticColors.transparentWhite[400],
|
|
847
847
|
borderColor: "",
|
|
848
848
|
iconBackgroundColor: semanticColors.buttonIcon.none
|
|
849
849
|
}
|
package/package.json
CHANGED
package/src/assets/theme.js
CHANGED
|
@@ -816,8 +816,8 @@ const theme = (() => {
|
|
|
816
816
|
iconBackgroundColor: semanticColors.buttonIcon.overlayWhite10,
|
|
817
817
|
},
|
|
818
818
|
disabled: {
|
|
819
|
-
textColor: semanticColors.
|
|
820
|
-
backgroundColor:
|
|
819
|
+
textColor: semanticColors.transparentWhite[400],
|
|
820
|
+
backgroundColor: 'transparent',
|
|
821
821
|
borderColor: '',
|
|
822
822
|
iconBackgroundColor: semanticColors.buttonIcon.none,
|
|
823
823
|
},
|
|
@@ -844,7 +844,7 @@ const theme = (() => {
|
|
|
844
844
|
},
|
|
845
845
|
disabled: {
|
|
846
846
|
backgroundColor: 'transparent',
|
|
847
|
-
textColor: semanticColors.
|
|
847
|
+
textColor: semanticColors.transparentWhite[400],
|
|
848
848
|
borderColor: '',
|
|
849
849
|
iconBackgroundColor: semanticColors.buttonIcon.none,
|
|
850
850
|
},
|
|
@@ -14,15 +14,7 @@
|
|
|
14
14
|
:data-value="domDataValue"
|
|
15
15
|
:disabled-bg-color="disabledBgColor"
|
|
16
16
|
:disabled-text-color="disabledTextColor"
|
|
17
|
-
:hovered-bg-color="
|
|
18
|
-
colorMode == 'dark'
|
|
19
|
-
? theme.semanticColors.teal[800]
|
|
20
|
-
: colorMode == 'transparent'
|
|
21
|
-
? 'grey6'
|
|
22
|
-
: hoveredBgColor
|
|
23
|
-
? hoveredBgColor
|
|
24
|
-
: 'grey5'
|
|
25
|
-
"
|
|
17
|
+
:hovered-bg-color="hoveredBackgroundColor"
|
|
26
18
|
:is-disabled="isDisabled"
|
|
27
19
|
:min-width="minWidth"
|
|
28
20
|
:padding="padding"
|
|
@@ -172,6 +164,11 @@
|
|
|
172
164
|
}
|
|
173
165
|
},
|
|
174
166
|
computed: {
|
|
167
|
+
hoveredBackgroundColor() {
|
|
168
|
+
if (this.colorMode == 'dark') return theme.semanticColors.teal[800]
|
|
169
|
+
if (this.colorMode == 'transparent') return 'grey6'
|
|
170
|
+
return this.hoveredBgColor || theme.semanticColors.grey[300]
|
|
171
|
+
},
|
|
175
172
|
/** Vue omits `data-value` when bound to null, so the parent select cannot find this row for search filtering. */
|
|
176
173
|
domDataValue() {
|
|
177
174
|
const v = this.value
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import Option from '@/components/inputs/select/option'
|
|
4
|
+
import theme from '@/assets/theme'
|
|
5
|
+
|
|
6
|
+
// jsdom never receives the stylesheet vue3-styled-components generates, so the
|
|
7
|
+
// hashed class on the rendered option is the observable: two mounts share a
|
|
8
|
+
// class only when they resolve to the same styles.
|
|
9
|
+
describe('RCoption', () => {
|
|
10
|
+
const styleClass = (props = {}) =>
|
|
11
|
+
mount(Option, {
|
|
12
|
+
props: { value: 'a', ...props },
|
|
13
|
+
slots: { default: 'Option A' },
|
|
14
|
+
})
|
|
15
|
+
.classes()
|
|
16
|
+
.join(' ')
|
|
17
|
+
|
|
18
|
+
it('hovers on grey 300 by default', () => {
|
|
19
|
+
expect(styleClass()).toBe(
|
|
20
|
+
styleClass({ hoveredBgColor: theme.semanticColors.grey[300] })
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('lets an explicit hoveredBgColor win over the default', () => {
|
|
25
|
+
expect(styleClass({ hoveredBgColor: 'grey4' })).not.toBe(styleClass())
|
|
26
|
+
expect(styleClass({ hoveredBgColor: 'grey4' })).toBe(
|
|
27
|
+
styleClass({ hoveredBgColor: theme.colors.grey4 })
|
|
28
|
+
)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('keeps its own hover colours in dark and transparent colour modes', () => {
|
|
32
|
+
expect(styleClass({ colorMode: 'dark', hoveredBgColor: 'grey4' })).toBe(
|
|
33
|
+
styleClass({ colorMode: 'dark' })
|
|
34
|
+
)
|
|
35
|
+
expect(
|
|
36
|
+
styleClass({ colorMode: 'transparent', hoveredBgColor: 'grey4' })
|
|
37
|
+
).toBe(styleClass({ colorMode: 'transparent' }))
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
<TitleContainer>
|
|
6
6
|
<BoxTitle> {{ numberSelected }} {{ selectedText }} </BoxTitle>
|
|
7
7
|
<IconContainer @click="$emit('on-close')">
|
|
8
|
-
<Icon
|
|
8
|
+
<Icon
|
|
9
|
+
:color="theme.semanticColors.red[500]"
|
|
10
|
+
cursor="pointer"
|
|
11
|
+
name="close"
|
|
12
|
+
size="14px"
|
|
13
|
+
/>
|
|
9
14
|
</IconContainer>
|
|
10
15
|
</TitleContainer>
|
|
11
16
|
<DividerContainer>
|
|
@@ -15,17 +20,18 @@
|
|
|
15
20
|
<ExpandedListItem
|
|
16
21
|
v-for="item in expandedOptions"
|
|
17
22
|
:key="item.type"
|
|
23
|
+
data-test-id="expanded_option"
|
|
18
24
|
:disabled="item.disabled || false"
|
|
19
25
|
:has-component="!!item?.component"
|
|
20
|
-
:
|
|
26
|
+
:text-color="expandedItemColor(item)"
|
|
21
27
|
@click="
|
|
22
28
|
!item?.component && !item.disabled && $emit('on-' + item.type)
|
|
23
29
|
"
|
|
24
30
|
>
|
|
25
31
|
<ListItemWrapper
|
|
26
32
|
v-if="item?.component"
|
|
33
|
+
data-test-id="expanded_list_item"
|
|
27
34
|
:has-component="!!item?.component"
|
|
28
|
-
test-data-id="expanded_list_item"
|
|
29
35
|
@click="!item.disabled && toggleElement(item.type)"
|
|
30
36
|
>
|
|
31
37
|
<ListItemTitle>
|
|
@@ -38,7 +44,6 @@
|
|
|
38
44
|
<Icon
|
|
39
45
|
:color="theme.colors.white"
|
|
40
46
|
:cursor="item.disabled ? 'not-allowed' : 'pointer'"
|
|
41
|
-
:hovered-color="theme.colors.white"
|
|
42
47
|
name="arrow_right"
|
|
43
48
|
size="20px"
|
|
44
49
|
/>
|
|
@@ -60,42 +65,43 @@
|
|
|
60
65
|
<SelectedContainer>
|
|
61
66
|
{{ numberSelected }} {{ selectedText }}
|
|
62
67
|
</SelectedContainer>
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
68
|
+
<ActionsContainer>
|
|
69
|
+
<template v-if="optionsList.length">
|
|
70
|
+
<RCMainButton
|
|
71
|
+
v-for="item in limitedOptions"
|
|
72
|
+
:key="item.type"
|
|
73
|
+
app-theme="dark"
|
|
74
|
+
:is-disabled="item.disabled"
|
|
75
|
+
no-wrap
|
|
76
|
+
:text="item.name"
|
|
77
|
+
type="ghost"
|
|
78
|
+
:variant="item.variant"
|
|
79
|
+
@click="!item.disabled && $emit('on-' + item.type)"
|
|
80
|
+
/>
|
|
81
|
+
<IconContainer
|
|
82
|
+
v-if="optionsList.length > optionLimit || hasComponent"
|
|
83
|
+
data-test-id="more_actions_button_wrapper"
|
|
84
|
+
@click="expandOptions"
|
|
85
|
+
>
|
|
86
|
+
<ButtonContainer name="more_options,_tool_tips">
|
|
87
|
+
<DotItem />
|
|
88
|
+
<DotItem />
|
|
89
|
+
<DotItem />
|
|
90
|
+
</ButtonContainer>
|
|
91
|
+
</IconContainer>
|
|
92
|
+
</template>
|
|
93
|
+
<EmptyText v-else data-test-id="no_bulk_actions">
|
|
94
|
+
{{ noBulkActionsText }}
|
|
95
|
+
</EmptyText>
|
|
96
|
+
<IconContainer data-test-id="close_button" @click="$emit('on-close')">
|
|
90
97
|
<Icon
|
|
91
|
-
:color="theme.
|
|
98
|
+
:color="theme.semanticColors.red[500]"
|
|
92
99
|
cursor="pointer"
|
|
93
|
-
:hovered-color="theme.colors.white"
|
|
94
100
|
name="close"
|
|
95
101
|
size="14px"
|
|
96
102
|
/>
|
|
97
103
|
</IconContainer>
|
|
98
|
-
</
|
|
104
|
+
</ActionsContainer>
|
|
99
105
|
</BoxContainer>
|
|
100
106
|
</PageContainer>
|
|
101
107
|
</PageWrapper>
|
|
@@ -118,7 +124,7 @@
|
|
|
118
124
|
// {
|
|
119
125
|
// type: 'delete',
|
|
120
126
|
// name: 'Delete',
|
|
121
|
-
//
|
|
127
|
+
// variant: 'cancel' // default is 'main'
|
|
122
128
|
// }
|
|
123
129
|
// ]
|
|
124
130
|
// @on-${type}="function" should $emit the callback for the 'type' in the optionsList
|
|
@@ -137,6 +143,7 @@
|
|
|
137
143
|
// </SelectedOptions>
|
|
138
144
|
import styled from 'vue3-styled-components'
|
|
139
145
|
import InfoText from '../infoText'
|
|
146
|
+
import RCMainButton from '../buttons/mainButton'
|
|
140
147
|
import Icon from '../icon'
|
|
141
148
|
import theme from '../../assets/theme'
|
|
142
149
|
|
|
@@ -149,7 +156,7 @@
|
|
|
149
156
|
`
|
|
150
157
|
|
|
151
158
|
const Divider = styled.div`
|
|
152
|
-
border-bottom: 1px solid
|
|
159
|
+
border-bottom: 1px solid ${(props) => props.theme.semanticColors.teal[600]};
|
|
153
160
|
width: 95%;
|
|
154
161
|
margin: 0 auto;
|
|
155
162
|
`
|
|
@@ -159,7 +166,6 @@
|
|
|
159
166
|
bottom: 30px;
|
|
160
167
|
left: 50%;
|
|
161
168
|
width: auto;
|
|
162
|
-
max-width: 70%;
|
|
163
169
|
transform: translateX(-50%);
|
|
164
170
|
z-index: 999;
|
|
165
171
|
`
|
|
@@ -170,13 +176,12 @@
|
|
|
170
176
|
left: 50%;
|
|
171
177
|
transform: translate(-50%, -50%);
|
|
172
178
|
border-radius: 4px;
|
|
173
|
-
background-color: rgba(0, 0, 0, 0.4);
|
|
174
179
|
`
|
|
175
180
|
|
|
176
181
|
const OptionsContainer = styled.div`
|
|
177
182
|
position: absolute;
|
|
178
183
|
left: 101%;
|
|
179
|
-
background-color: ${(props) => props.theme.colors.
|
|
184
|
+
background-color: ${(props) => props.theme.colors.transparentBlack2};
|
|
180
185
|
border-radius: 4px;
|
|
181
186
|
padding: 15px;
|
|
182
187
|
`
|
|
@@ -185,9 +190,9 @@
|
|
|
185
190
|
display: grid;
|
|
186
191
|
align-items: center;
|
|
187
192
|
height: 100%;
|
|
188
|
-
padding
|
|
193
|
+
padding: 0 24px;
|
|
189
194
|
white-space: nowrap;
|
|
190
|
-
border-right: 1px solid
|
|
195
|
+
border-right: 1px solid ${(props) => props.theme.semanticColors.teal[600]};
|
|
191
196
|
`
|
|
192
197
|
|
|
193
198
|
const TitleContainer = styled.div`
|
|
@@ -210,13 +215,11 @@
|
|
|
210
215
|
const BoxContainer = styled.div`
|
|
211
216
|
display: flex;
|
|
212
217
|
align-items: center;
|
|
213
|
-
background-color: ${(props) => props.theme.colors.
|
|
214
|
-
opacity: 90%;
|
|
218
|
+
background-color: ${(props) => props.theme.colors.transparentBlack2};
|
|
215
219
|
color: ${(props) => props.theme.colors.white};
|
|
216
220
|
border-radius: 4px;
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
height: 45px;
|
|
221
|
+
font-size: 14px;
|
|
222
|
+
height: 62px;
|
|
220
223
|
`
|
|
221
224
|
|
|
222
225
|
const CenterBox = styled(BoxContainer)`
|
|
@@ -239,14 +242,10 @@
|
|
|
239
242
|
|
|
240
243
|
div {
|
|
241
244
|
// This is the dot color
|
|
242
|
-
background: ${(props) => props.theme.
|
|
245
|
+
background: ${(props) => props.theme.semanticColors.grey[600]};
|
|
243
246
|
}
|
|
244
247
|
`
|
|
245
248
|
|
|
246
|
-
const CloseContainer = styled.div`
|
|
247
|
-
margin-left: 20px;
|
|
248
|
-
`
|
|
249
|
-
|
|
250
249
|
const DotItem = styled.div`
|
|
251
250
|
width: 4px;
|
|
252
251
|
height: 4px;
|
|
@@ -254,38 +253,15 @@
|
|
|
254
253
|
border-radius: 50%;
|
|
255
254
|
`
|
|
256
255
|
|
|
257
|
-
const
|
|
256
|
+
const ActionsContainer = styled.div`
|
|
258
257
|
height: 100%;
|
|
259
258
|
display: flex;
|
|
260
259
|
align-items: center;
|
|
260
|
+
gap: 8px;
|
|
261
|
+
padding: 0 24px;
|
|
261
262
|
color: ${(props) => props.theme.colors.white};
|
|
262
263
|
`
|
|
263
264
|
|
|
264
|
-
const ListAttrs = {
|
|
265
|
-
disabled: Boolean,
|
|
266
|
-
hoverColor: String,
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const ListItem = styled('div', ListAttrs)`
|
|
270
|
-
width: max-content;
|
|
271
|
-
height: 100%;
|
|
272
|
-
display: flex;
|
|
273
|
-
align-items: center;
|
|
274
|
-
padding: 0 10px;
|
|
275
|
-
cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
|
|
276
|
-
color: ${(props) => props.disabled && props.theme.colors.grey3};
|
|
277
|
-
|
|
278
|
-
&:hover {
|
|
279
|
-
background: rgba(255, 255, 255, 0.1);
|
|
280
|
-
color: ${(props) =>
|
|
281
|
-
props.disabled
|
|
282
|
-
? props.theme.colors.grey3
|
|
283
|
-
: props.hoverColor
|
|
284
|
-
? props.theme.colors[props.hoverColor]
|
|
285
|
-
: props.theme.colors.white};
|
|
286
|
-
}
|
|
287
|
-
`
|
|
288
|
-
|
|
289
265
|
const IconContainer = styled.div`
|
|
290
266
|
display: grid;
|
|
291
267
|
align-items: center;
|
|
@@ -293,10 +269,9 @@
|
|
|
293
269
|
height: 30px;
|
|
294
270
|
width: 30px;
|
|
295
271
|
cursor: pointer;
|
|
296
|
-
margin-left: 8px;
|
|
297
272
|
|
|
298
273
|
&:hover {
|
|
299
|
-
background:
|
|
274
|
+
background: ${(props) => props.theme.semanticColors.transparentTeal[400]};
|
|
300
275
|
border-radius: 4px;
|
|
301
276
|
}
|
|
302
277
|
`
|
|
@@ -309,8 +284,8 @@
|
|
|
309
284
|
|
|
310
285
|
const ExpandedListItem = styled('div', {
|
|
311
286
|
disabled: Boolean,
|
|
312
|
-
hoverColor: String,
|
|
313
287
|
hasComponent: Boolean,
|
|
288
|
+
textColor: String,
|
|
314
289
|
})`
|
|
315
290
|
width: 100%;
|
|
316
291
|
display: flex;
|
|
@@ -318,12 +293,10 @@
|
|
|
318
293
|
align-items: center;
|
|
319
294
|
padding: ${(props) => (props.hasComponent ? '0' : '13px 15px')};
|
|
320
295
|
cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
|
|
321
|
-
color: ${(props) => props.
|
|
296
|
+
color: ${(props) => props.textColor};
|
|
322
297
|
|
|
323
298
|
&:hover {
|
|
324
|
-
background:
|
|
325
|
-
color: ${(props) =>
|
|
326
|
-
props.disabled ? props.theme.colors.grey3 : props.theme.colors.white};
|
|
299
|
+
background: ${(props) => props.theme.semanticColors.transparentTeal[400]};
|
|
327
300
|
}
|
|
328
301
|
`
|
|
329
302
|
|
|
@@ -343,8 +316,7 @@
|
|
|
343
316
|
|
|
344
317
|
const EmptyText = styled.div`
|
|
345
318
|
color: ${(props) => props.theme.colors.white};
|
|
346
|
-
font-size:
|
|
347
|
-
padding-left: 16px;
|
|
319
|
+
font-size: 14px;
|
|
348
320
|
`
|
|
349
321
|
|
|
350
322
|
export default {
|
|
@@ -353,10 +325,10 @@
|
|
|
353
325
|
PageContainer,
|
|
354
326
|
BoxContainer,
|
|
355
327
|
SelectedContainer,
|
|
356
|
-
|
|
328
|
+
ActionsContainer,
|
|
357
329
|
ButtonContainer,
|
|
358
330
|
DotItem,
|
|
359
|
-
|
|
331
|
+
RCMainButton,
|
|
360
332
|
InfoText,
|
|
361
333
|
CenterBox,
|
|
362
334
|
Icon,
|
|
@@ -373,7 +345,6 @@
|
|
|
373
345
|
Divider,
|
|
374
346
|
DividerContainer,
|
|
375
347
|
ExpandedList,
|
|
376
|
-
CloseContainer,
|
|
377
348
|
},
|
|
378
349
|
props: {
|
|
379
350
|
optionsList: {
|
|
@@ -434,6 +405,13 @@
|
|
|
434
405
|
this.initializeOptions()
|
|
435
406
|
},
|
|
436
407
|
methods: {
|
|
408
|
+
expandedItemColor(item) {
|
|
409
|
+
const ghost = this.theme.mainButton.dark.ghost
|
|
410
|
+
const variant = ghost[item.variant] ?? ghost.main
|
|
411
|
+
const state = item.disabled ? 'disabled' : 'default'
|
|
412
|
+
|
|
413
|
+
return variant[state].textColor
|
|
414
|
+
},
|
|
437
415
|
initializeOptions() {
|
|
438
416
|
this.expandedOptions = [...this.optionsList]
|
|
439
417
|
.map((option, index) => {
|
|
@@ -457,17 +435,6 @@
|
|
|
457
435
|
this.expanded = !this.expanded
|
|
458
436
|
this.expandedOptions = this.optionsList
|
|
459
437
|
},
|
|
460
|
-
handleExpandedOptionClick(item) {
|
|
461
|
-
if (item.disabled) return
|
|
462
|
-
|
|
463
|
-
if (!item.component) {
|
|
464
|
-
this.$emit('on-' + item.type)
|
|
465
|
-
|
|
466
|
-
return
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
this.toggleElement(item.type)
|
|
470
|
-
},
|
|
471
438
|
},
|
|
472
439
|
}
|
|
473
440
|
</script>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import { mount } from '@vue/test-utils'
|
|
3
3
|
import RCSelectedOptions from '@/components/selectedOptions'
|
|
4
|
+
import RCMainButton from '@/components/buttons/mainButton'
|
|
5
|
+
import RCIcon from '@/components/icon/Icon.vue'
|
|
4
6
|
import theme from '@/assets/theme'
|
|
5
7
|
|
|
6
8
|
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
@@ -22,7 +24,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
22
24
|
{
|
|
23
25
|
type: 'delete',
|
|
24
26
|
name: 'Delete',
|
|
25
|
-
|
|
27
|
+
variant: 'cancel',
|
|
26
28
|
},
|
|
27
29
|
],
|
|
28
30
|
}
|
|
@@ -58,7 +60,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
58
60
|
expect(selectedOptions.exists()).toBe(true)
|
|
59
61
|
|
|
60
62
|
const noBulkActions = selectedOptions.find(
|
|
61
|
-
'[test-
|
|
63
|
+
'[data-test-id="no_bulk_actions"]'
|
|
62
64
|
)
|
|
63
65
|
expect(noBulkActions.exists()).toBe(true)
|
|
64
66
|
})
|
|
@@ -78,7 +80,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
78
80
|
|
|
79
81
|
//since we have 2 options, and the limit is 4, we should not see "•••" button
|
|
80
82
|
const moreActionsButton = selectedOptions.find(
|
|
81
|
-
'[test-
|
|
83
|
+
'[data-test-id="more_actions_button_wrapper"]'
|
|
82
84
|
)
|
|
83
85
|
expect(moreActionsButton.exists()).toBe(false)
|
|
84
86
|
})
|
|
@@ -111,7 +113,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
111
113
|
|
|
112
114
|
//since we a component parameter, we should see "•••" button
|
|
113
115
|
const moreActionsButton = selectedOptions.find(
|
|
114
|
-
'[test-
|
|
116
|
+
'[data-test-id="more_actions_button_wrapper"]'
|
|
115
117
|
)
|
|
116
118
|
expect(moreActionsButton.exists()).toBe(true)
|
|
117
119
|
})
|
|
@@ -146,7 +148,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
146
148
|
|
|
147
149
|
//since we a component parameter, we should see "•••" button
|
|
148
150
|
const moreActionsButton = selectedOptions.find(
|
|
149
|
-
'[test-
|
|
151
|
+
'[data-test-id="more_actions_button_wrapper"]'
|
|
150
152
|
)
|
|
151
153
|
expect(moreActionsButton.exists()).toBe(true)
|
|
152
154
|
|
|
@@ -160,7 +162,7 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
160
162
|
|
|
161
163
|
//toggle the element with the component parameter
|
|
162
164
|
const expandedListItems = selectedOptions.findAll(
|
|
163
|
-
'[test-
|
|
165
|
+
'[data-test-id="expanded_list_item"]'
|
|
164
166
|
)
|
|
165
167
|
|
|
166
168
|
//there should be only one since we have only one option with the component parameter
|
|
@@ -173,4 +175,238 @@ describe('RCSelectedOptions.vue', () => {
|
|
|
173
175
|
const setSupplierSlot = wrapper.find('[data-id="set_supplier"]')
|
|
174
176
|
expect(setSupplierSlot.exists()).toBe(true)
|
|
175
177
|
})
|
|
178
|
+
it('renders each collapsed option as a main button', async () => {
|
|
179
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
180
|
+
props: simpleOptionsProps,
|
|
181
|
+
global: {
|
|
182
|
+
provide: {
|
|
183
|
+
theme,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
await wrapper.vm.$nextTick()
|
|
189
|
+
|
|
190
|
+
const optionButtons = wrapper.findAllComponents(RCMainButton)
|
|
191
|
+
expect(optionButtons).toHaveLength(2)
|
|
192
|
+
expect(optionButtons[0].props('text')).toBe('Close')
|
|
193
|
+
expect(optionButtons[1].props('text')).toBe('Delete')
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('passes the option variant straight through to the button', async () => {
|
|
197
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
198
|
+
props: simpleOptionsProps,
|
|
199
|
+
global: {
|
|
200
|
+
provide: {
|
|
201
|
+
theme,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
await wrapper.vm.$nextTick()
|
|
207
|
+
|
|
208
|
+
const optionButtons = wrapper.findAllComponents(RCMainButton)
|
|
209
|
+
expect(optionButtons[0].props('variant')).toBe('main')
|
|
210
|
+
expect(optionButtons[1].props('variant')).toBe('cancel')
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('marks a disabled option as a disabled button and does not emit on click', async () => {
|
|
214
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
215
|
+
props: {
|
|
216
|
+
...simpleOptionsProps,
|
|
217
|
+
optionsList: [
|
|
218
|
+
{
|
|
219
|
+
type: 'delete',
|
|
220
|
+
name: 'Delete',
|
|
221
|
+
disabled: true,
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
global: {
|
|
226
|
+
provide: {
|
|
227
|
+
theme,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
await wrapper.vm.$nextTick()
|
|
233
|
+
|
|
234
|
+
const deleteButton = wrapper.findComponent(RCMainButton)
|
|
235
|
+
expect(deleteButton.props('isDisabled')).toBe(true)
|
|
236
|
+
|
|
237
|
+
await deleteButton.trigger('click')
|
|
238
|
+
expect(wrapper.emitted('on-delete')).toBeUndefined()
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('emits the option event when an enabled option is clicked', async () => {
|
|
242
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
243
|
+
props: simpleOptionsProps,
|
|
244
|
+
global: {
|
|
245
|
+
provide: {
|
|
246
|
+
theme,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
await wrapper.vm.$nextTick()
|
|
252
|
+
|
|
253
|
+
await wrapper.findAllComponents(RCMainButton)[1].trigger('click')
|
|
254
|
+
expect(wrapper.emitted('on-delete')).toHaveLength(1)
|
|
255
|
+
})
|
|
256
|
+
it('renders the close button and emits on-close even when there are no options', async () => {
|
|
257
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
258
|
+
props: {
|
|
259
|
+
...simpleOptionsProps,
|
|
260
|
+
optionsList: [],
|
|
261
|
+
},
|
|
262
|
+
global: {
|
|
263
|
+
provide: {
|
|
264
|
+
theme,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
await wrapper.vm.$nextTick()
|
|
270
|
+
|
|
271
|
+
const closeButton = wrapper.find('[data-test-id="close_button"]')
|
|
272
|
+
expect(closeButton.exists()).toBe(true)
|
|
273
|
+
|
|
274
|
+
await closeButton.trigger('click')
|
|
275
|
+
expect(wrapper.emitted('on-close')).toHaveLength(1)
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
const mountExpanded = async (optionsList) => {
|
|
279
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
280
|
+
props: {
|
|
281
|
+
...simpleOptionsProps,
|
|
282
|
+
optionsList,
|
|
283
|
+
},
|
|
284
|
+
global: {
|
|
285
|
+
provide: {
|
|
286
|
+
theme,
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
await wrapper
|
|
292
|
+
.find('[data-test-id="more_actions_button_wrapper"]')
|
|
293
|
+
.trigger('click')
|
|
294
|
+
await wrapper.vm.$nextTick()
|
|
295
|
+
|
|
296
|
+
return wrapper
|
|
297
|
+
.findAll('[data-test-id="expanded_option"]')
|
|
298
|
+
.map((option) => option.classes().join(' '))
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const expandedItemColors = async (optionsList) => {
|
|
302
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
303
|
+
props: {
|
|
304
|
+
...simpleOptionsProps,
|
|
305
|
+
optionsList,
|
|
306
|
+
},
|
|
307
|
+
global: {
|
|
308
|
+
provide: {
|
|
309
|
+
theme,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
await wrapper
|
|
315
|
+
.find('[data-test-id="more_actions_button_wrapper"]')
|
|
316
|
+
.trigger('click')
|
|
317
|
+
await wrapper.vm.$nextTick()
|
|
318
|
+
|
|
319
|
+
return wrapper
|
|
320
|
+
.findAllComponents('[data-test-id="expanded_option"]')
|
|
321
|
+
.map((option) => option.props('textColor'))
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
it('styles a cancel option differently from the default options in the expanded list', async () => {
|
|
325
|
+
const [close, archive, remove] = await mountExpanded([
|
|
326
|
+
{ type: 'close', name: 'Close' },
|
|
327
|
+
{ type: 'archive', name: 'Archive' },
|
|
328
|
+
{ type: 'delete', name: 'Delete', variant: 'cancel' },
|
|
329
|
+
{ type: 'supplier', name: 'Supplier', component: 'set_supplier' },
|
|
330
|
+
])
|
|
331
|
+
|
|
332
|
+
expect(archive).toBe(close)
|
|
333
|
+
expect(remove).not.toBe(close)
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
it('styles disabled options alike whatever the variant in the expanded list', async () => {
|
|
337
|
+
const [close, remove] = await mountExpanded([
|
|
338
|
+
{ type: 'close', name: 'Close', disabled: true },
|
|
339
|
+
{ type: 'delete', name: 'Delete', variant: 'cancel', disabled: true },
|
|
340
|
+
{ type: 'supplier', name: 'Supplier', component: 'set_supplier' },
|
|
341
|
+
])
|
|
342
|
+
|
|
343
|
+
expect(remove).toBe(close)
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
it('takes expanded option colours from the ghost button theme', async () => {
|
|
347
|
+
const [close, remove, archive, purge] = await expandedItemColors([
|
|
348
|
+
{ type: 'close', name: 'Close' },
|
|
349
|
+
{ type: 'delete', name: 'Delete', variant: 'cancel' },
|
|
350
|
+
{ type: 'archive', name: 'Archive', disabled: true },
|
|
351
|
+
{ type: 'purge', name: 'Purge', variant: 'cancel', disabled: true },
|
|
352
|
+
{ type: 'supplier', name: 'Supplier', component: 'set_supplier' },
|
|
353
|
+
])
|
|
354
|
+
|
|
355
|
+
const ghost = theme.mainButton.dark.ghost
|
|
356
|
+
|
|
357
|
+
expect(close).toBe(ghost.main.default.textColor)
|
|
358
|
+
expect(remove).toBe(ghost.cancel.default.textColor)
|
|
359
|
+
expect(archive).toBe(ghost.main.disabled.textColor)
|
|
360
|
+
expect(purge).toBe(ghost.cancel.disabled.textColor)
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('uses the same close colour in the expanded modal as in the collapsed bar', async () => {
|
|
364
|
+
const wrapper = mount(RCSelectedOptions, {
|
|
365
|
+
props: {
|
|
366
|
+
...simpleOptionsProps,
|
|
367
|
+
optionsList: [
|
|
368
|
+
{ type: 'close', name: 'Close' },
|
|
369
|
+
{ type: 'supplier', name: 'Supplier', component: 'set_supplier' },
|
|
370
|
+
],
|
|
371
|
+
},
|
|
372
|
+
global: {
|
|
373
|
+
provide: {
|
|
374
|
+
theme,
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
await wrapper
|
|
380
|
+
.find('[data-test-id="more_actions_button_wrapper"]')
|
|
381
|
+
.trigger('click')
|
|
382
|
+
await wrapper.vm.$nextTick()
|
|
383
|
+
|
|
384
|
+
const closeIcon = wrapper
|
|
385
|
+
.findAllComponents(RCIcon)
|
|
386
|
+
.find((icon) => icon.props('name') === 'close')
|
|
387
|
+
|
|
388
|
+
expect(closeIcon.props('color')).toBe(theme.semanticColors.red[500])
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('falls back to the main variant when an option has an unknown variant', async () => {
|
|
392
|
+
const [mystery] = await expandedItemColors([
|
|
393
|
+
{ type: 'mystery', name: 'Mystery', variant: 'not_a_variant' },
|
|
394
|
+
{ type: 'supplier', name: 'Supplier', component: 'set_supplier' },
|
|
395
|
+
])
|
|
396
|
+
|
|
397
|
+
expect(mystery).toBe(theme.mainButton.dark.ghost.main.default.textColor)
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
it('gives every disabled option the same background whatever its variant', () => {
|
|
401
|
+
const ghost = theme.mainButton.dark.ghost
|
|
402
|
+
|
|
403
|
+
expect(ghost.main.disabled.backgroundColor).toBe('transparent')
|
|
404
|
+
expect(ghost.cancel.disabled.backgroundColor).toBe('transparent')
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
it('gives every disabled option the same text colour whatever its variant', () => {
|
|
408
|
+
const ghost = theme.mainButton.dark.ghost
|
|
409
|
+
|
|
410
|
+
expect(ghost.cancel.disabled.textColor).toBe(ghost.main.disabled.textColor)
|
|
411
|
+
})
|
|
176
412
|
})
|
|
@@ -9,7 +9,7 @@ export default {
|
|
|
9
9
|
optionsList: {
|
|
10
10
|
control: 'object',
|
|
11
11
|
description:
|
|
12
|
-
'Array of options to display. Each option should have a type and name, and can optionally have a component, disabled state,
|
|
12
|
+
'Array of options to display. Each option should have a type and name, and can optionally have a component, disabled state, variant, and disabledInfo.',
|
|
13
13
|
},
|
|
14
14
|
numberSelected: {
|
|
15
15
|
control: 'number',
|
|
@@ -49,7 +49,7 @@ Default.args = {
|
|
|
49
49
|
{
|
|
50
50
|
type: 'delete',
|
|
51
51
|
name: 'Delete',
|
|
52
|
-
|
|
52
|
+
variant: 'cancel',
|
|
53
53
|
},
|
|
54
54
|
],
|
|
55
55
|
numberSelected: 5,
|
|
@@ -98,7 +98,7 @@ ManyOptions.args = {
|
|
|
98
98
|
{
|
|
99
99
|
type: 'delete',
|
|
100
100
|
name: 'Delete',
|
|
101
|
-
|
|
101
|
+
variant: 'cancel',
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
type: 'archive',
|
|
@@ -132,7 +132,7 @@ CustomLabels.args = {
|
|
|
132
132
|
{
|
|
133
133
|
type: 'delete',
|
|
134
134
|
name: 'Delete',
|
|
135
|
-
|
|
135
|
+
variant: 'cancel',
|
|
136
136
|
},
|
|
137
137
|
],
|
|
138
138
|
numberSelected: 1,
|
|
@@ -158,7 +158,7 @@ CustomLabels.args = {
|
|
|
158
158
|
// {
|
|
159
159
|
// type: 'delete',
|
|
160
160
|
// name: 'Delete',
|
|
161
|
-
//
|
|
161
|
+
// variant: 'cancel' // default is 'main'
|
|
162
162
|
// }
|
|
163
163
|
// ]
|
|
164
164
|
//
|
|
@@ -365,7 +365,7 @@
|
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
&:hover {
|
|
368
|
-
background-color: ${(props) => props.theme.
|
|
368
|
+
background-color: ${(props) => props.theme.semanticColors.grey[300]};
|
|
369
369
|
}
|
|
370
370
|
`
|
|
371
371
|
|
|
@@ -420,7 +420,7 @@
|
|
|
420
420
|
height: 37px;
|
|
421
421
|
|
|
422
422
|
&:hover {
|
|
423
|
-
background-color: ${(props) => props.theme.
|
|
423
|
+
background-color: ${(props) => props.theme.semanticColors.grey[300]};
|
|
424
424
|
}
|
|
425
425
|
`
|
|
426
426
|
|
|
@@ -143,11 +143,13 @@
|
|
|
143
143
|
.arrow-container,
|
|
144
144
|
.input-placeholder,
|
|
145
145
|
.table-dropdown-item {
|
|
146
|
-
background-color: ${(props) =>
|
|
146
|
+
background-color: ${(props) =>
|
|
147
|
+
props.theme.semanticColors.grey[300]};
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
input {
|
|
150
|
-
background-color: ${(props) =>
|
|
151
|
+
background-color: ${(props) =>
|
|
152
|
+
props.theme.semanticColors.grey[300]};
|
|
151
153
|
}
|
|
152
154
|
}
|
|
153
155
|
|
|
@@ -337,7 +339,7 @@
|
|
|
337
339
|
&:hover {
|
|
338
340
|
input:disabled {
|
|
339
341
|
background-color: ${(props) =>
|
|
340
|
-
props.theme.
|
|
342
|
+
props.theme.semanticColors.grey[300] + '!important'};
|
|
341
343
|
}
|
|
342
344
|
|
|
343
345
|
.drag-icon {
|
|
@@ -345,7 +347,7 @@
|
|
|
345
347
|
}
|
|
346
348
|
|
|
347
349
|
.drag-wrapper {
|
|
348
|
-
background-color: ${(props) => props.theme.
|
|
350
|
+
background-color: ${(props) => props.theme.semanticColors.grey[300]};
|
|
349
351
|
}
|
|
350
352
|
|
|
351
353
|
.arrow-dropdown {
|
|
@@ -416,7 +418,7 @@
|
|
|
416
418
|
height: unset;
|
|
417
419
|
|
|
418
420
|
&:focus {
|
|
419
|
-
background: ${(props) => props.theme.
|
|
421
|
+
background: ${(props) => props.theme.semanticColors.grey[300]};
|
|
420
422
|
}
|
|
421
423
|
}
|
|
422
424
|
|
|
@@ -254,12 +254,12 @@
|
|
|
254
254
|
background-color: ${(props) =>
|
|
255
255
|
props.colorTheme == 'dark'
|
|
256
256
|
? theme.semanticColors.teal[700]
|
|
257
|
-
:
|
|
257
|
+
: theme.semanticColors.grey[300]};
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
&:focus-visible {
|
|
261
261
|
outline: none;
|
|
262
|
-
background-color:
|
|
262
|
+
background-color: ${theme.semanticColors.grey[300]};
|
|
263
263
|
}
|
|
264
264
|
`
|
|
265
265
|
const OptionChild = styled('div', { colorTheme: String })`
|
|
@@ -272,12 +272,12 @@
|
|
|
272
272
|
background-color: ${(props) =>
|
|
273
273
|
props.colorTheme == 'dark'
|
|
274
274
|
? theme.semanticColors.teal[600]
|
|
275
|
-
:
|
|
275
|
+
: theme.semanticColors.grey[300]};
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
&:focus-visible {
|
|
279
279
|
outline: none;
|
|
280
|
-
background-color:
|
|
280
|
+
background-color: ${theme.semanticColors.grey[300]};
|
|
281
281
|
}
|
|
282
282
|
`
|
|
283
283
|
|
|
@@ -358,7 +358,7 @@
|
|
|
358
358
|
},
|
|
359
359
|
hoveredBackgroundColor: {
|
|
360
360
|
type: String,
|
|
361
|
-
default: theme.
|
|
361
|
+
default: theme.semanticColors.grey[300],
|
|
362
362
|
},
|
|
363
363
|
dataId: {
|
|
364
364
|
required: false,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import { mount, DOMWrapper } from '@vue/test-utils'
|
|
3
3
|
import ThreeDots from './index.vue'
|
|
4
|
+
import theme from '@/assets/theme'
|
|
4
5
|
|
|
5
6
|
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
|
6
7
|
fetchIcon: jest.fn(() => Promise.resolve('')),
|
|
@@ -118,4 +119,28 @@ describe('ThreeDots', () => {
|
|
|
118
119
|
expect(w.emitted('on-select')).toHaveLength(1)
|
|
119
120
|
expect(w.emitted('on-select')[0][0]).toMatchObject({ value: 'c1' })
|
|
120
121
|
})
|
|
122
|
+
|
|
123
|
+
// jsdom never receives the stylesheet vue3-styled-components generates, so the
|
|
124
|
+
// hashed class on the trigger is the observable: two mounts share a class only
|
|
125
|
+
// when they resolve to the same styles.
|
|
126
|
+
describe('hovered background colour', () => {
|
|
127
|
+
const styleClass = (props = {}) => {
|
|
128
|
+
const w = mount(ThreeDots, { props: { options, ...props } })
|
|
129
|
+
const classes = w.classes().join(' ')
|
|
130
|
+
w.unmount()
|
|
131
|
+
return classes
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
it('hovers on grey 300 by default', () => {
|
|
135
|
+
expect(styleClass()).toBe(
|
|
136
|
+
styleClass({ hoveredBackgroundColor: theme.semanticColors.grey[300] })
|
|
137
|
+
)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('lets an explicit hoveredBackgroundColor win over the default', () => {
|
|
141
|
+
expect(
|
|
142
|
+
styleClass({ hoveredBackgroundColor: theme.colors.grey5 })
|
|
143
|
+
).not.toBe(styleClass())
|
|
144
|
+
})
|
|
145
|
+
})
|
|
121
146
|
})
|