@eturnity/eturnity_reusable_components 8.10.3-EPDM-14085.2 → 8.10.3-EPDM-11600.4
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 +1 -1
- package/src/assets/svgIcons/erase.svg +2 -3
- package/src/assets/theme.js +0 -1
- package/src/components/infoCard/index.vue +3 -3
- package/src/components/inputs/checkbox/index.vue +2 -2
- package/src/components/inputs/inputNumber/InputNumber.stories.js +19 -5
- package/src/components/inputs/inputNumber/index.vue +15 -3
- package/src/components/pageSubtitle/index.vue +7 -1
- package/src/components/draggableCard/defaultProps.js +0 -16
- package/src/components/draggableCard/draggableCard.spec.js +0 -99
- package/src/components/draggableCard/draggableCard.stories.js +0 -79
- package/src/components/draggableCard/index.vue +0 -354
package/package.json
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
<svg
|
2
|
-
<
|
3
|
-
<path d="M24.9592 15.0408C22.2382 12.3197 17.7618 12.3197 15.0408 15.0408C12.3197 17.7618 12.3197 22.2382 15.0408 24.9592C17.7618 27.6803 22.2382 27.6803 24.9592 24.9592C27.6803 22.2382 27.6803 17.8495 24.9592 15.0408ZM23.6426 22.5016L22.4138 23.7304L19.9561 21.2727L17.4984 23.7304L16.2696 22.5016L18.7273 20.0439L16.2696 17.5862L17.4984 16.3574L19.9561 18.815L22.4138 16.3574L23.6426 17.5862L21.185 20.0439L23.6426 22.5016Z" fill="#FF5656"></path>
|
1
|
+
<svg width="22" height="21" viewBox="0 0 22 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M18.4389 3.06113C14.3574 -1.02038 7.64263 -1.02038 3.56113 3.06113C-0.520376 7.14263 -0.520376 13.8574 3.56113 17.9389C7.64263 22.0204 14.3574 22.0204 18.4389 17.9389C22.5204 13.8574 22.5204 7.2743 18.4389 3.06113ZM16.464 14.2524L14.6207 16.0956L10.9342 12.4091L7.24765 16.0956L5.40439 14.2524L9.09091 10.5658L5.40439 6.87931L7.24765 5.03605L10.9342 8.72257L14.6207 5.03605L16.464 6.87931L12.7774 10.5658L16.464 14.2524Z" fill="#FF5656"/>
|
4
3
|
</svg>
|
package/src/assets/theme.js
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
<RCIcon
|
13
13
|
:color="iconColor ? iconColor : presetStyles.iconColor"
|
14
14
|
data-test-id="info_card_icon"
|
15
|
-
name="info"
|
15
|
+
:name="isErrorMinor ? 'erase' : 'info'"
|
16
16
|
size="24px"
|
17
17
|
/>
|
18
18
|
<TextContainer data-test-id="info_card_text_container">
|
@@ -138,8 +138,8 @@
|
|
138
138
|
stylesCollection.iconColor = theme.colors.white
|
139
139
|
} else if (this.isErrorMinor) {
|
140
140
|
stylesCollection.borderStyle = 'dashed'
|
141
|
-
stylesCollection.borderColor = theme.colors.
|
142
|
-
stylesCollection.iconColor = theme.colors.
|
141
|
+
stylesCollection.borderColor = theme.colors.grey4
|
142
|
+
stylesCollection.iconColor = theme.colors.red
|
143
143
|
} else {
|
144
144
|
stylesCollection.borderStyle = 'dashed'
|
145
145
|
stylesCollection.borderColor = theme.colors.grey4
|
@@ -44,7 +44,7 @@
|
|
44
44
|
import styled from 'vue3-styled-components'
|
45
45
|
|
46
46
|
const ComponentWrapper = styled.div`
|
47
|
-
min-height:
|
47
|
+
min-height: 18px;
|
48
48
|
`
|
49
49
|
|
50
50
|
const CheckWrapper = styled('div', { hasLabel: Boolean })`
|
@@ -179,7 +179,7 @@
|
|
179
179
|
font-size: 13px;
|
180
180
|
display: grid;
|
181
181
|
align-items: center;
|
182
|
-
min-height:
|
182
|
+
min-height: 18px;
|
183
183
|
color: ${(props) =>
|
184
184
|
props.isDisabled ? props.theme.colors.grey2 : 'unset'};
|
185
185
|
`
|
@@ -3,15 +3,15 @@ import InputNumber from './index.vue'
|
|
3
3
|
export default {
|
4
4
|
title: 'InputNumber',
|
5
5
|
component: InputNumber,
|
6
|
-
// argTypes: {},
|
7
6
|
}
|
8
7
|
|
9
|
-
const Template = (args
|
8
|
+
const Template = (args) => ({
|
10
9
|
// Components used in your story `template` are defined in the `components` object
|
11
10
|
components: { InputNumber },
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
setup() {
|
12
|
+
return { args: args }
|
13
|
+
},
|
14
|
+
template: `<InputNumber v-bind="args" />`,
|
15
15
|
|
16
16
|
// import InputNumber from "@eturnity/eturnity_reusable_components/src/components/inputs/inputNumber"
|
17
17
|
// How to use:
|
@@ -73,6 +73,20 @@ Disabled.args = {
|
|
73
73
|
showLinearUnitName: false,
|
74
74
|
}
|
75
75
|
|
76
|
+
export const DisabledAndPreDefined = Template.bind({})
|
77
|
+
DisabledAndPreDefined.args = {
|
78
|
+
placeholder: 'Enter Value',
|
79
|
+
disabled: true,
|
80
|
+
isPreDefined: true,
|
81
|
+
value: '',
|
82
|
+
inputWidth: '200px',
|
83
|
+
isError: false,
|
84
|
+
numberPrecision: 0,
|
85
|
+
noBorder: false,
|
86
|
+
textAlign: 'left',
|
87
|
+
showLinearUnitName: false,
|
88
|
+
}
|
89
|
+
|
76
90
|
export const LinearUnit = Template.bind({})
|
77
91
|
LinearUnit.args = {
|
78
92
|
placeholder: 'Enter Value',
|
@@ -42,7 +42,6 @@
|
|
42
42
|
:color-mode="colorMode"
|
43
43
|
:data-id="inputDataId"
|
44
44
|
:data-qa-id="dataQaId"
|
45
|
-
:disabled="disabled"
|
46
45
|
:font-color="colorMode === 'transparent' ? 'white' : fontColor"
|
47
46
|
:font-size="fontSize"
|
48
47
|
:has-label-slot="hasLabelSlot"
|
@@ -52,6 +51,7 @@
|
|
52
51
|
:is-disabled="disabled"
|
53
52
|
:is-error="isError"
|
54
53
|
:is-interactive="isInteractive"
|
54
|
+
:is-pre-defined="isPreDefined"
|
55
55
|
:min-width="minWidth"
|
56
56
|
:no-border="noBorder"
|
57
57
|
:placeholder="displayedPlaceholder"
|
@@ -132,7 +132,7 @@
|
|
132
132
|
</ArrowButton>
|
133
133
|
</ArrowControls>
|
134
134
|
</InputWrapper>
|
135
|
-
<ErrorMessage v-if="isError">{{ errorMessage }}</ErrorMessage>
|
135
|
+
<ErrorMessage v-if="isError && errorMessage">{{ errorMessage }}</ErrorMessage>
|
136
136
|
</Container>
|
137
137
|
</template>
|
138
138
|
|
@@ -194,6 +194,7 @@
|
|
194
194
|
slotSize: String,
|
195
195
|
inputHeight: String,
|
196
196
|
isInteractive: Boolean,
|
197
|
+
isPreDefined: Boolean,
|
197
198
|
alignItems: String,
|
198
199
|
labelFontColor: String,
|
199
200
|
labelFontWeight: String,
|
@@ -254,7 +255,7 @@
|
|
254
255
|
color: ${(props) =>
|
255
256
|
props.isError
|
256
257
|
? props.theme.colors.grey6
|
257
|
-
: props.isDisabled
|
258
|
+
: props.isDisabled && !props.isPreDefined
|
258
259
|
? props.colorMode === 'transparent'
|
259
260
|
? props.theme.colors.white
|
260
261
|
: props.theme.colors.grey2
|
@@ -524,6 +525,11 @@
|
|
524
525
|
required: false,
|
525
526
|
default: 0,
|
526
527
|
},
|
528
|
+
isPreDefined: {
|
529
|
+
type: Boolean,
|
530
|
+
required: false,
|
531
|
+
default: false,
|
532
|
+
},
|
527
533
|
minDecimals: {
|
528
534
|
type: Number,
|
529
535
|
required: false,
|
@@ -644,12 +650,18 @@
|
|
644
650
|
required: false,
|
645
651
|
default: '',
|
646
652
|
},
|
653
|
+
labelDataTestId: {
|
654
|
+
type: String,
|
655
|
+
required: false,
|
656
|
+
default: '',
|
657
|
+
},
|
647
658
|
inputDataId: {
|
648
659
|
type: String,
|
649
660
|
required: false,
|
650
661
|
default: '',
|
651
662
|
},
|
652
663
|
dataQaId: {
|
664
|
+
type: String,
|
653
665
|
required: false,
|
654
666
|
default: '',
|
655
667
|
},
|
@@ -5,7 +5,8 @@
|
|
5
5
|
:has-info-text="!!infoText"
|
6
6
|
:margin-bottom="marginBottom"
|
7
7
|
>
|
8
|
-
<span data-test-id="page_subtitle_text">
|
8
|
+
<span v-if="containsHtml" data-test-id="page_subtitle_text" v-html="text"></span>
|
9
|
+
<span v-else data-test-id="page_subtitle_text">
|
9
10
|
{{ text }}
|
10
11
|
</span>
|
11
12
|
<InfoText
|
@@ -58,6 +59,11 @@
|
|
58
59
|
required: true,
|
59
60
|
type: String,
|
60
61
|
},
|
62
|
+
containsHtml: {
|
63
|
+
required: false,
|
64
|
+
type: Boolean,
|
65
|
+
default: false,
|
66
|
+
},
|
61
67
|
color: {
|
62
68
|
required: false,
|
63
69
|
type: String,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
const defaultProps = {
|
2
|
-
title: 'Sample Title',
|
3
|
-
infoText: 'Sample Info Text',
|
4
|
-
initialPosition: { top: '0px', left: '0px' },
|
5
|
-
minWidth: '284px',
|
6
|
-
maxWidth: '284px',
|
7
|
-
dragTargets: ['document'],
|
8
|
-
dragBounds: {},
|
9
|
-
sampleBody1:
|
10
|
-
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
|
11
|
-
sampleBody2:
|
12
|
-
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
|
13
|
-
sampleFooter: 'Sample footer',
|
14
|
-
}
|
15
|
-
|
16
|
-
export default defaultProps
|
@@ -1,99 +0,0 @@
|
|
1
|
-
import { mount } from '@vue/test-utils'
|
2
|
-
import DraggableCard from '@/components/draggableCard'
|
3
|
-
import defaultProps from './defaultProps'
|
4
|
-
|
5
|
-
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
6
|
-
// need to mock this due to how jest handles import.meta
|
7
|
-
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
8
|
-
}))
|
9
|
-
|
10
|
-
describe('DraggableCard.vue', () => {
|
11
|
-
it('renders properly with required props', () => {
|
12
|
-
const wrapper = mount(DraggableCard, { props: defaultProps })
|
13
|
-
expect(
|
14
|
-
wrapper.find('[data-test-id="draggable_card_header"]').text()
|
15
|
-
).toContain(defaultProps.title)
|
16
|
-
|
17
|
-
// Expect no footer rendered if not provided
|
18
|
-
const footerElement = wrapper.find('[data-test-id="draggable_card_footer"]')
|
19
|
-
expect(footerElement.exists()).toBe(false)
|
20
|
-
})
|
21
|
-
|
22
|
-
it('renders body slot content correctly', () => {
|
23
|
-
const wrapper = mount(DraggableCard, {
|
24
|
-
props: defaultProps,
|
25
|
-
slots: {
|
26
|
-
body: `
|
27
|
-
<div class="custom_body1">${defaultProps.sampleBody1}</div>
|
28
|
-
<div class="custom_body2">${defaultProps.sampleBody2}</div>
|
29
|
-
`,
|
30
|
-
},
|
31
|
-
})
|
32
|
-
expect(wrapper.find('.custom_body1').exists()).toBe(true)
|
33
|
-
expect(wrapper.text()).toContain(defaultProps.sampleBody1)
|
34
|
-
expect(wrapper.find('.custom_body2').exists()).toBe(true)
|
35
|
-
expect(wrapper.text()).toContain(defaultProps.sampleBody2)
|
36
|
-
})
|
37
|
-
|
38
|
-
it('renders footer slot content correctly', () => {
|
39
|
-
const wrapper = mount(DraggableCard, {
|
40
|
-
props: defaultProps,
|
41
|
-
slots: {
|
42
|
-
footer: `<div class="custom_footer">${defaultProps.sampleFooter}</div>`,
|
43
|
-
},
|
44
|
-
})
|
45
|
-
expect(
|
46
|
-
wrapper.find('[data-test-id="draggable_card_footer"]').exists()
|
47
|
-
).toBe(true)
|
48
|
-
expect(wrapper.find('.custom_footer').exists()).toBe(true)
|
49
|
-
expect(wrapper.text()).toContain(defaultProps.sampleFooter)
|
50
|
-
})
|
51
|
-
|
52
|
-
it('emits "on-close" when close button is clicked', async () => {
|
53
|
-
const wrapper = mount(DraggableCard, { props: defaultProps })
|
54
|
-
await wrapper
|
55
|
-
.find('[data-test-id="draggable_card_close_button"]')
|
56
|
-
.trigger('click')
|
57
|
-
expect(wrapper.emitted('on-close')).toBeTruthy()
|
58
|
-
})
|
59
|
-
|
60
|
-
it('toggles collapse state when arrow icon is clicked', async () => {
|
61
|
-
const wrapper = mount(DraggableCard, {
|
62
|
-
props: { ...defaultProps, isCollapsible: true },
|
63
|
-
})
|
64
|
-
expect(wrapper.vm.isCollapsed).toBe(false)
|
65
|
-
await wrapper
|
66
|
-
.find('[data-test-id="draggable_card_collapse_button"]')
|
67
|
-
.trigger('click')
|
68
|
-
expect(wrapper.vm.isCollapsed).toBe(true)
|
69
|
-
})
|
70
|
-
|
71
|
-
it('handles drag start event', async () => {
|
72
|
-
const wrapper = mount(DraggableCard, { props: defaultProps })
|
73
|
-
await wrapper
|
74
|
-
.find('[data-test-id="draggable_card_drag_icon"]')
|
75
|
-
.trigger('mousedown', { clientX: 100, clientY: 100 })
|
76
|
-
expect(wrapper.vm.isDragging).toBe(true)
|
77
|
-
})
|
78
|
-
|
79
|
-
it('handles drag move event', async () => {
|
80
|
-
const wrapper = mount(DraggableCard, { props: defaultProps })
|
81
|
-
wrapper.vm.onDragStart(
|
82
|
-
{ preventDefault: () => {}, clientX: 100, clientY: 100 },
|
83
|
-
false
|
84
|
-
)
|
85
|
-
wrapper.vm.onDrag({ preventDefault: () => {}, clientX: 120, clientY: 120 })
|
86
|
-
expect(wrapper.vm.eventCoordinates.x).toBe(120)
|
87
|
-
expect(wrapper.vm.eventCoordinates.y).toBe(120)
|
88
|
-
})
|
89
|
-
|
90
|
-
it('handles drag end event', async () => {
|
91
|
-
const wrapper = mount(DraggableCard, { props: defaultProps })
|
92
|
-
wrapper.vm.onDragStart(
|
93
|
-
{ preventDefault: () => {}, clientX: 100, clientY: 100 },
|
94
|
-
false
|
95
|
-
)
|
96
|
-
wrapper.vm.onDragEnd()
|
97
|
-
expect(wrapper.vm.isDragging).toBe(false)
|
98
|
-
})
|
99
|
-
})
|
@@ -1,79 +0,0 @@
|
|
1
|
-
import defaultProps from './defaultProps'
|
2
|
-
import DraggableCard from './index.vue'
|
3
|
-
import styled from 'vue3-styled-components'
|
4
|
-
import theme from '@/assets/theme'
|
5
|
-
|
6
|
-
export default {
|
7
|
-
title: 'DraggableCard',
|
8
|
-
component: DraggableCard,
|
9
|
-
tags: ['autodocs'],
|
10
|
-
}
|
11
|
-
|
12
|
-
const TextContainer = styled.div`
|
13
|
-
font-family: ${theme.fonts.mainFont};
|
14
|
-
color: ${theme.colors.white};
|
15
|
-
font-weight: 400;
|
16
|
-
font-size: 14px;
|
17
|
-
line-height: 21px;
|
18
|
-
letter-spacing: 0%;
|
19
|
-
`
|
20
|
-
|
21
|
-
const CompleteTemplate = (args) => {
|
22
|
-
return {
|
23
|
-
components: { DraggableCard, TextContainer },
|
24
|
-
setup() {
|
25
|
-
return { args }
|
26
|
-
},
|
27
|
-
template: `
|
28
|
-
<DraggableCard v-bind="args">
|
29
|
-
<template #body>
|
30
|
-
<TextContainer>{{ args.sampleBody1 }}</TextContainer>
|
31
|
-
<TextContainer>{{ args.sampleBody2 }}</TextContainer>
|
32
|
-
</template>
|
33
|
-
<template #footer>
|
34
|
-
<TextContainer>{{ args.sampleFooter }}</TextContainer>
|
35
|
-
</template>
|
36
|
-
</DraggableCard>
|
37
|
-
`,
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
export const Default = CompleteTemplate.bind({})
|
42
|
-
Default.args = {
|
43
|
-
...defaultProps,
|
44
|
-
}
|
45
|
-
|
46
|
-
export const NotCollapsible = CompleteTemplate.bind({})
|
47
|
-
NotCollapsible.args = {
|
48
|
-
...defaultProps,
|
49
|
-
isCollapsible: false,
|
50
|
-
}
|
51
|
-
|
52
|
-
export const AdjustWidth = CompleteTemplate.bind({})
|
53
|
-
AdjustWidth.args = {
|
54
|
-
...defaultProps,
|
55
|
-
minWidth: '100px',
|
56
|
-
maxWidth: '500px',
|
57
|
-
}
|
58
|
-
|
59
|
-
const NoFooterTemplate = (args) => {
|
60
|
-
return {
|
61
|
-
components: { DraggableCard, TextContainer },
|
62
|
-
setup() {
|
63
|
-
return { args }
|
64
|
-
},
|
65
|
-
template: `
|
66
|
-
<DraggableCard v-bind="args">
|
67
|
-
<template #body>
|
68
|
-
<TextContainer>{{ args.sampleBody1 }}</TextContainer>
|
69
|
-
<TextContainer>{{ args.sampleBody2 }}</TextContainer>
|
70
|
-
</template>
|
71
|
-
</DraggableCard>
|
72
|
-
`,
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
export const NoFooter = NoFooterTemplate.bind({})
|
77
|
-
NoFooter.args = {
|
78
|
-
...defaultProps,
|
79
|
-
}
|
@@ -1,354 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<CardContainer
|
3
|
-
data-test-id="draggable_card_container"
|
4
|
-
:initial-position="initialPosition"
|
5
|
-
:max-width="maxWidth"
|
6
|
-
:min-width="minWidth"
|
7
|
-
>
|
8
|
-
<HeaderContainer data-test-id="draggable_card_header">
|
9
|
-
<SubHeaderWrapper>
|
10
|
-
<LeftIconsContainer>
|
11
|
-
<DragHandleWrapper :class="{ dragging: isDragging }">
|
12
|
-
<RCIcon
|
13
|
-
:color="theme.colors.grey3"
|
14
|
-
data-test-id="draggable_card_drag_icon"
|
15
|
-
name="drag_icon"
|
16
|
-
size="14px"
|
17
|
-
:title="$gettext('drag_drop')"
|
18
|
-
@mousedown="(event) => onDragStart(event, false)"
|
19
|
-
@touchstart="
|
20
|
-
(event) => {
|
21
|
-
onDragStart(event, true)
|
22
|
-
}
|
23
|
-
"
|
24
|
-
/>
|
25
|
-
</DragHandleWrapper>
|
26
|
-
<ArrowIconWrapper
|
27
|
-
v-if="isCollapsible"
|
28
|
-
data-test-id="draggable_card_collapse_button"
|
29
|
-
:is-collapsed="isCollapsed"
|
30
|
-
@click="toggleCollapse"
|
31
|
-
>
|
32
|
-
<CollapseArrowIcon />
|
33
|
-
</ArrowIconWrapper>
|
34
|
-
</LeftIconsContainer>
|
35
|
-
<TitleContainer :data-id="titleDataId">
|
36
|
-
<TextContainer>{{ title }}</TextContainer>
|
37
|
-
<InfoText v-if="infoText?.length" :text="infoText" />
|
38
|
-
</TitleContainer>
|
39
|
-
</SubHeaderWrapper>
|
40
|
-
<CloseButton
|
41
|
-
class="close"
|
42
|
-
data-test-id="draggable_card_close_button"
|
43
|
-
@click="$emit('on-close')"
|
44
|
-
/>
|
45
|
-
</HeaderContainer>
|
46
|
-
<BodyContainer v-if="!isCollapsed" data-test-id="draggable_card_body">
|
47
|
-
<slot name="body"></slot>
|
48
|
-
</BodyContainer>
|
49
|
-
<FooterContainer v-if="$slots.footer" data-test-id="draggable_card_footer">
|
50
|
-
<slot name="footer"></slot>
|
51
|
-
</FooterContainer>
|
52
|
-
</CardContainer>
|
53
|
-
</template>
|
54
|
-
|
55
|
-
<script>
|
56
|
-
import styled from 'vue3-styled-components'
|
57
|
-
import theme from '../../assets/theme.js'
|
58
|
-
import RCIcon from '../icon'
|
59
|
-
import CloseButton from '../buttons/closeButton'
|
60
|
-
import InfoText from '../infoText'
|
61
|
-
import CollapseArrowIcon from '../../assets/icons/collapse_arrow_icon.svg'
|
62
|
-
|
63
|
-
const CardContainerAttr = {
|
64
|
-
initialPosition: Object,
|
65
|
-
minWidth: String,
|
66
|
-
maxWidth: String,
|
67
|
-
}
|
68
|
-
const CardContainer = styled('div', CardContainerAttr)`
|
69
|
-
position: absolute;
|
70
|
-
display: flex;
|
71
|
-
flex-direction: column;
|
72
|
-
border-radius: 4px;
|
73
|
-
min-width: ${(props) => props.minWidth};
|
74
|
-
max-width: ${(props) => props.maxWidth};
|
75
|
-
background: ${theme.colors.transparentBlack2};
|
76
|
-
z-index: 5;
|
77
|
-
${(props) =>
|
78
|
-
props.initialPosition?.top && `top: ${props.initialPosition.top};`}
|
79
|
-
${(props) =>
|
80
|
-
props.initialPosition?.right && `right: ${props.initialPosition.right};`}
|
81
|
-
${(props) =>
|
82
|
-
props.initialPosition?.left && `left: ${props.initialPosition.left};`}
|
83
|
-
${(props) =>
|
84
|
-
props.initialPosition?.bottom &&
|
85
|
-
`bottom: ${props.initialPosition.bottom};`}
|
86
|
-
`
|
87
|
-
|
88
|
-
const HeaderContainer = styled.div`
|
89
|
-
display: flex;
|
90
|
-
align-items: center;
|
91
|
-
justify-content: space-between;
|
92
|
-
padding: 8px;
|
93
|
-
`
|
94
|
-
|
95
|
-
const SubHeaderWrapper = styled.div`
|
96
|
-
display: flex;
|
97
|
-
min-width: 180px;
|
98
|
-
align-items: center;
|
99
|
-
justify-content: space-between;
|
100
|
-
height: fit-content;
|
101
|
-
margin-right: 14px;
|
102
|
-
`
|
103
|
-
|
104
|
-
const LeftIconsContainer = styled.div`
|
105
|
-
display: flex;
|
106
|
-
align-items: center;
|
107
|
-
gap: 4px;
|
108
|
-
margin-right: 14px;
|
109
|
-
`
|
110
|
-
|
111
|
-
const TitleContainer = styled.div`
|
112
|
-
display: flex;
|
113
|
-
align-items: center;
|
114
|
-
gap: 8px;
|
115
|
-
`
|
116
|
-
|
117
|
-
const TextContainer = styled.div`
|
118
|
-
font-family: ${theme.fonts.mainFont};
|
119
|
-
font-weight: 600;
|
120
|
-
font-size: 14px;
|
121
|
-
line-height: 19.6px;
|
122
|
-
letter-spacing: -1%;
|
123
|
-
color: ${theme.colors.white};
|
124
|
-
word-break: break-word;
|
125
|
-
overflow-wrap: break-word;
|
126
|
-
white-space: normal;
|
127
|
-
`
|
128
|
-
|
129
|
-
const DragHandleWrapper = styled.div`
|
130
|
-
display: grid;
|
131
|
-
align-items: center;
|
132
|
-
justify-items: center;
|
133
|
-
width: 26px;
|
134
|
-
height: 26px;
|
135
|
-
cursor: grab;
|
136
|
-
&.dragging {
|
137
|
-
cursor: grabbing;
|
138
|
-
}
|
139
|
-
`
|
140
|
-
|
141
|
-
const collapsedAttrs = {
|
142
|
-
isCollapsed: Boolean,
|
143
|
-
}
|
144
|
-
const ArrowIconWrapper = styled('div', collapsedAttrs)`
|
145
|
-
display: flex;
|
146
|
-
align-items: center;
|
147
|
-
justify-content: center;
|
148
|
-
width: 8px;
|
149
|
-
height: 26px;
|
150
|
-
cursor: pointer;
|
151
|
-
transition: transform 0.3s ease;
|
152
|
-
path {
|
153
|
-
fill: ${theme.colors.white};
|
154
|
-
}
|
155
|
-
|
156
|
-
${(props) => props.isCollapsed && 'transform: rotate(-180deg);'}
|
157
|
-
`
|
158
|
-
|
159
|
-
const BodyContainer = styled.div`
|
160
|
-
display: flex;
|
161
|
-
flex-direction: column;
|
162
|
-
gap: 16px;
|
163
|
-
padding-top: 8px;
|
164
|
-
padding-right: 16px;
|
165
|
-
padding-bottom: 8px;
|
166
|
-
padding-left: 16px;
|
167
|
-
word-break: break-word;
|
168
|
-
overflow-wrap: break-word;
|
169
|
-
white-space: normal;
|
170
|
-
`
|
171
|
-
|
172
|
-
const FooterContainer = styled.div`
|
173
|
-
display: flex;
|
174
|
-
border-radius: 4px;
|
175
|
-
align-items: center;
|
176
|
-
justify-content: space-between;
|
177
|
-
padding: 8px;
|
178
|
-
background: ${theme.colors.eturnityGrey};
|
179
|
-
word-break: break-word;
|
180
|
-
overflow-wrap: break-word;
|
181
|
-
white-space: normal;
|
182
|
-
`
|
183
|
-
|
184
|
-
export default {
|
185
|
-
name: 'DraggableCard',
|
186
|
-
components: {
|
187
|
-
CardContainer,
|
188
|
-
HeaderContainer,
|
189
|
-
SubHeaderWrapper,
|
190
|
-
LeftIconsContainer,
|
191
|
-
TextContainer,
|
192
|
-
DragHandleWrapper,
|
193
|
-
ArrowIconWrapper,
|
194
|
-
CollapseArrowIcon,
|
195
|
-
RCIcon,
|
196
|
-
CloseButton,
|
197
|
-
InfoText,
|
198
|
-
TitleContainer,
|
199
|
-
BodyContainer,
|
200
|
-
FooterContainer,
|
201
|
-
},
|
202
|
-
props: {
|
203
|
-
minWidth: {
|
204
|
-
required: true,
|
205
|
-
type: String,
|
206
|
-
},
|
207
|
-
maxWidth: {
|
208
|
-
required: true,
|
209
|
-
type: String,
|
210
|
-
},
|
211
|
-
initialPosition: {
|
212
|
-
required: true,
|
213
|
-
type: Object,
|
214
|
-
},
|
215
|
-
title: {
|
216
|
-
required: true,
|
217
|
-
type: String,
|
218
|
-
},
|
219
|
-
titleDataId: {
|
220
|
-
required: false,
|
221
|
-
type: String,
|
222
|
-
default: '',
|
223
|
-
},
|
224
|
-
isCollapsible: {
|
225
|
-
required: false,
|
226
|
-
type: Boolean,
|
227
|
-
default: true,
|
228
|
-
},
|
229
|
-
infoText: {
|
230
|
-
required: false,
|
231
|
-
type: String,
|
232
|
-
default: '',
|
233
|
-
},
|
234
|
-
dragTargets: {
|
235
|
-
required: false,
|
236
|
-
type: Array,
|
237
|
-
default: () => ['document'],
|
238
|
-
},
|
239
|
-
dragBounds: {
|
240
|
-
required: false,
|
241
|
-
type: Object,
|
242
|
-
default: () => {},
|
243
|
-
},
|
244
|
-
},
|
245
|
-
emits: ['on-close'],
|
246
|
-
data() {
|
247
|
-
return {
|
248
|
-
isCollapsed: false,
|
249
|
-
isDragging: false,
|
250
|
-
isTouchStart: false,
|
251
|
-
eventCoordinates: {
|
252
|
-
x: 0,
|
253
|
-
y: 0,
|
254
|
-
},
|
255
|
-
}
|
256
|
-
},
|
257
|
-
computed: {
|
258
|
-
dragBoundsEnabled() {
|
259
|
-
const minPosition = this.dragBounds?.min
|
260
|
-
const maxPosition = this.dragBounds?.max
|
261
|
-
return (
|
262
|
-
minPosition?.top &&
|
263
|
-
minPosition?.left &&
|
264
|
-
maxPosition?.top &&
|
265
|
-
maxPosition?.left
|
266
|
-
)
|
267
|
-
},
|
268
|
-
theme() {
|
269
|
-
return theme
|
270
|
-
},
|
271
|
-
},
|
272
|
-
beforeUnmount() {
|
273
|
-
this.removeEvents()
|
274
|
-
},
|
275
|
-
methods: {
|
276
|
-
toggleCollapse() {
|
277
|
-
this.isCollapsed = !this.isCollapsed
|
278
|
-
},
|
279
|
-
onDragStart(e, isTouchStart) {
|
280
|
-
e.preventDefault()
|
281
|
-
this.isDragging = true
|
282
|
-
this.isTouchStart = isTouchStart
|
283
|
-
this.eventCoordinates.x = isTouchStart
|
284
|
-
? e.touches[0].clientX
|
285
|
-
: e.clientX
|
286
|
-
this.eventCoordinates.y = isTouchStart
|
287
|
-
? e.touches[0].clientY
|
288
|
-
: e.clientY
|
289
|
-
this.dragTargets.forEach((id) => {
|
290
|
-
const target =
|
291
|
-
id === 'document' ? document : document.getElementById(id)
|
292
|
-
if (target && target.addEventListener) {
|
293
|
-
target.addEventListener(
|
294
|
-
isTouchStart ? 'touchend' : 'mouseup',
|
295
|
-
this.onDragEnd
|
296
|
-
)
|
297
|
-
target.addEventListener(
|
298
|
-
isTouchStart ? 'touchmove' : 'mousemove',
|
299
|
-
this.onDrag
|
300
|
-
)
|
301
|
-
}
|
302
|
-
})
|
303
|
-
document.addEventListener(
|
304
|
-
isTouchStart ? 'touchend' : 'mouseup',
|
305
|
-
this.onDragEnd
|
306
|
-
)
|
307
|
-
},
|
308
|
-
onDrag(e) {
|
309
|
-
e.preventDefault()
|
310
|
-
const eventX = this.isTouchStart ? e.touches[0].clientX : e.clientX
|
311
|
-
const eventY = this.isTouchStart ? e.touches[0].clientY : e.clientY
|
312
|
-
const deltaX = this.eventCoordinates.x - eventX
|
313
|
-
const deltaY = this.eventCoordinates.y - eventY
|
314
|
-
this.eventCoordinates.x = eventX
|
315
|
-
this.eventCoordinates.y = eventY
|
316
|
-
const element = this.$el
|
317
|
-
let positionY = element.offsetTop - deltaY
|
318
|
-
let positionX = element.offsetLeft - deltaX
|
319
|
-
if (this.dragBoundsEnabled) {
|
320
|
-
const minPosition = this.dragBounds.min
|
321
|
-
const maxPosition = this.dragBounds.max
|
322
|
-
positionY = Math.min(
|
323
|
-
Math.max(positionY, minPosition.top),
|
324
|
-
maxPosition.top
|
325
|
-
)
|
326
|
-
positionX = Math.min(
|
327
|
-
Math.max(positionX, minPosition.left),
|
328
|
-
maxPosition.left
|
329
|
-
)
|
330
|
-
}
|
331
|
-
element.style.top = positionY + 'px'
|
332
|
-
element.style.left = positionX + 'px'
|
333
|
-
},
|
334
|
-
onDragEnd() {
|
335
|
-
this.isDragging = false
|
336
|
-
this.removeEvents()
|
337
|
-
},
|
338
|
-
removeEvents() {
|
339
|
-
this.dragTargets.forEach((id) => {
|
340
|
-
const target =
|
341
|
-
id === 'document' ? document : document.getElementById(id)
|
342
|
-
if (target && target.removeEventListener) {
|
343
|
-
target.removeEventListener('mouseup', this.onDragEnd)
|
344
|
-
target.removeEventListener('touchend', this.onDragEnd)
|
345
|
-
target.removeEventListener('mousemove', this.onDrag)
|
346
|
-
target.removeEventListener('touchmove', this.onDrag)
|
347
|
-
}
|
348
|
-
})
|
349
|
-
document.removeEventListener('mouseup', this.onDragEnd)
|
350
|
-
document.removeEventListener('touchend', this.onDragEnd)
|
351
|
-
},
|
352
|
-
},
|
353
|
-
}
|
354
|
-
</script>
|