@ouestfrance/sipa-bms-ui 8.20.0 → 8.22.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/components/feedback/BmsGhost.vue.d.ts +24 -0
- package/dist/components/form/BmsAutocomplete.vue.d.ts +2 -2
- package/dist/components/form/BmsFilePicker.vue.d.ts +4 -0
- package/dist/components/form/BmsMultiSelect.vue.d.ts +4 -0
- package/dist/components/form/BmsServerAutocomplete.vue.d.ts +2 -2
- package/dist/components/form/RawAutocomplete.vue.d.ts +11 -3
- package/dist/components/layout/BmsFloatingWindow.vue.d.ts +20 -1
- package/dist/index.d.ts +2 -1
- package/dist/mockServiceWorker.js +1 -1
- package/dist/sipa-bms-ui.css +117 -393
- package/dist/sipa-bms-ui.es.js +447 -129
- package/dist/sipa-bms-ui.es.js.map +1 -1
- package/dist/sipa-bms-ui.umd.js +449 -130
- package/dist/sipa-bms-ui.umd.js.map +1 -1
- package/package.json +12 -12
- package/src/assets/scss/_conf.scss +0 -1
- package/src/assets/scss/app.scss +0 -1
- package/src/components/button/BmsAllButtons.stories.js +50 -23
- package/src/components/button/BmsButton.stories.js +153 -59
- package/src/components/feedback/BmsGhost.stories.js +60 -0
- package/src/components/feedback/BmsGhost.vue +82 -0
- package/src/components/feedback/BmsTooltip.vue +15 -1
- package/src/components/feedback/UiTooltip.vue +9 -1
- package/src/components/form/BmsFilePicker.stories.js +6 -1
- package/src/components/form/BmsFilePicker.vue +10 -5
- package/src/components/form/BmsMultiSelect.vue +32 -25
- package/src/components/form/BmsSelect.vue +18 -16
- package/src/components/form/RawAutocomplete.vue +16 -4
- package/src/components/form/RawInputText.vue +1 -0
- package/src/components/layout/BmsFloatingWindow.stories.js +226 -12
- package/src/components/layout/BmsFloatingWindow.vue +286 -13
- package/src/components/layout/BmsModal.stories.js +2 -1
- package/src/components/layout/BmsSplitWindow.vue +0 -1
- package/src/components/table/BmsTableFilters.vue +1 -1
- package/src/documentation/button/primaryButton.mdx +142 -0
- package/src/documentation/{secondaryButton.mdx → button/secondaryButton.mdx} +2 -2
- package/src/documentation/foundation/contributing.mdx +72 -0
- package/src/documentation/foundation/gettingstarted.mdx +7 -0
- package/src/documentation/{principles.mdx → foundation/principles.mdx} +9 -9
- package/src/documentation/icons.mdx +43 -0
- package/src/index.ts +3 -0
- package/src/showroom/pages/forms.vue +10 -1
- package/src/assets/scss/_formkit.scss +0 -353
- package/src/components/form/Form.stories.js +0 -35
- package/src/documentation/primaryButton.mdx +0 -20
- /package/src/documentation/{button.mdx → button/button.mdx} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouestfrance/sipa-bms-ui",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.22.0",
|
|
4
4
|
"author": "Ouest-France BMS",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"scripts": {
|
|
@@ -30,16 +30,15 @@
|
|
|
30
30
|
"url": "https://gitlab.ouest-france.fr/sipa-ouest-france/platform/platform-library-vuejs-bms.git"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@chromatic-com/storybook": "^4.1.
|
|
33
|
+
"@chromatic-com/storybook": "^4.1.3",
|
|
34
34
|
"@codemirror/lang-html": "6.4.11",
|
|
35
35
|
"@codemirror/lang-json": "6.0.2",
|
|
36
36
|
"@commitlint/cli": "20.1.0",
|
|
37
37
|
"@commitlint/config-conventional": "20.0.0",
|
|
38
|
-
"@formkit/vue": "1.6.9",
|
|
39
38
|
"@mdx-js/react": "3.1.1",
|
|
40
|
-
"@storybook/addon-docs": "10.
|
|
41
|
-
"@storybook/addon-links": "10.
|
|
42
|
-
"@storybook/vue3-vite": "10.
|
|
39
|
+
"@storybook/addon-docs": "10.1.6",
|
|
40
|
+
"@storybook/addon-links": "10.1.6",
|
|
41
|
+
"@storybook/vue3-vite": "10.1.6",
|
|
43
42
|
"@types/lodash": "4.17.21",
|
|
44
43
|
"@types/uuid": "11.0.0",
|
|
45
44
|
"@vitejs/plugin-vue": "6.0.2",
|
|
@@ -61,15 +60,17 @@
|
|
|
61
60
|
"lint-staged": "16.2.7",
|
|
62
61
|
"lodash": "4.17.21",
|
|
63
62
|
"lucide-vue-next": "0.554.0",
|
|
63
|
+
"msw": "^2.12.4",
|
|
64
64
|
"msw-storybook-addon": "^2.0.3",
|
|
65
65
|
"normalize.css": "8.0.1",
|
|
66
66
|
"path": "0.12.7",
|
|
67
67
|
"prettier": "3.6.2",
|
|
68
|
+
"remark-gfm": "^4.0.1",
|
|
68
69
|
"sass": "1.94.2",
|
|
69
70
|
"semantic-release": "25.0.2",
|
|
70
71
|
"start-server-and-test": "2.1.3",
|
|
71
|
-
"storybook": "10.
|
|
72
|
-
"storybook-addon-pseudo-states": "10.
|
|
72
|
+
"storybook": "10.1.6",
|
|
73
|
+
"storybook-addon-pseudo-states": "10.1.6",
|
|
73
74
|
"storybook-addon-tag-badges": "^3.0.2",
|
|
74
75
|
"storybook-vue3-router": "^7.0.0",
|
|
75
76
|
"typescript": "5.2.2",
|
|
@@ -118,9 +119,8 @@
|
|
|
118
119
|
]
|
|
119
120
|
},
|
|
120
121
|
"msw": {
|
|
121
|
-
"workerDirectory":
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"msw": "^2.3.1"
|
|
122
|
+
"workerDirectory": [
|
|
123
|
+
"public"
|
|
124
|
+
]
|
|
125
125
|
}
|
|
126
126
|
}
|
package/src/assets/scss/app.scss
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import BmsButton from '@/components/button/BmsButton.vue';
|
|
2
2
|
import BmsIconButton from '@/components/button/BmsIconButton.vue';
|
|
3
|
-
import { Heart } from 'lucide-vue-next';
|
|
3
|
+
import { Heart, ArrowLeft, ArrowRight } from 'lucide-vue-next';
|
|
4
4
|
|
|
5
5
|
const types = ['primary', 'secondary', 'tertiary'];
|
|
6
6
|
const modes = ['default', 'danger'];
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
|
-
title: 'Composants/button',
|
|
9
|
+
title: 'Composants/button/Button',
|
|
10
10
|
component: BmsButton,
|
|
11
11
|
};
|
|
12
12
|
|
|
@@ -14,41 +14,68 @@ const AllButtonsTemplate = () => ({
|
|
|
14
14
|
components: {
|
|
15
15
|
BmsButton,
|
|
16
16
|
BmsIconButton,
|
|
17
|
+
ArrowLeft,
|
|
18
|
+
ArrowRight,
|
|
17
19
|
Heart,
|
|
18
20
|
},
|
|
19
21
|
setup() {
|
|
20
22
|
return { types, modes };
|
|
21
23
|
},
|
|
22
24
|
template: `
|
|
23
|
-
<div style="display:grid;grid-template-columns:repeat(
|
|
25
|
+
<div style="display:grid;grid-template-columns:repeat(4, auto); gap:1em; justify-items: start; align-items: center;">
|
|
24
26
|
<template v-for="mode in modes" :key="mode">
|
|
25
27
|
<template v-for="type in types">
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Button {{ mode }} {{ type }} {{ to ? ' avec une URL ' : '' }}
|
|
28
|
+
<BmsButton :mode="mode" :type="type" small>
|
|
29
|
+
Button {{ mode }} {{ type }} small
|
|
29
30
|
</BmsButton>
|
|
30
|
-
<BmsButton :mode="mode" :type="type"
|
|
31
|
-
Button {{ mode }} {{ type }}
|
|
31
|
+
<BmsButton :mode="mode" :type="type">
|
|
32
|
+
Button {{ mode }} {{ type }}
|
|
32
33
|
</BmsButton>
|
|
33
|
-
<BmsButton :mode="mode" :type="type"
|
|
34
|
-
Button {{ mode }} {{ type }}
|
|
34
|
+
<BmsButton :mode="mode" :type="type" class="_hover">
|
|
35
|
+
Button {{ mode }} {{ type }} hovered
|
|
36
|
+
</BmsButton>
|
|
37
|
+
<BmsButton :mode="mode" :type="type" disabled>
|
|
38
|
+
Button {{ mode }} {{ type }} disabled
|
|
35
39
|
</BmsButton>
|
|
36
|
-
</template>
|
|
37
40
|
</template>
|
|
38
41
|
</template>
|
|
42
|
+
|
|
43
|
+
<BmsButton small>
|
|
44
|
+
<template #start> <ArrowLeft/> </template>
|
|
45
|
+
Button small
|
|
46
|
+
<template #end> <ArrowRight/> </template>
|
|
47
|
+
</BmsButton>
|
|
48
|
+
<BmsButton>
|
|
49
|
+
<template #start> <ArrowLeft/> </template>
|
|
50
|
+
Button
|
|
51
|
+
<template #end> <ArrowRight/> </template>
|
|
52
|
+
</BmsButton>
|
|
53
|
+
<BmsButton class="_hover">
|
|
54
|
+
<template #start> <ArrowLeft/> </template>
|
|
55
|
+
Button hovered
|
|
56
|
+
<template #end> <ArrowRight/> </template>
|
|
57
|
+
</BmsButton>
|
|
58
|
+
<BmsButton disabled>
|
|
59
|
+
<template #start> <ArrowLeft/> </template>
|
|
60
|
+
Button disabled
|
|
61
|
+
<template #end> <ArrowRight/> </template>
|
|
62
|
+
</BmsButton>
|
|
63
|
+
|
|
39
64
|
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
65
|
+
<template v-for="mode in modes" :key="mode">
|
|
66
|
+
<BmsIconButton v-bind="args" :mode="mode" small>
|
|
67
|
+
<Heart />
|
|
68
|
+
</BmsIconButton>
|
|
69
|
+
<BmsIconButton v-bind="args" :mode="mode">
|
|
70
|
+
<Heart />
|
|
71
|
+
</BmsIconButton>
|
|
72
|
+
<BmsIconButton v-bind="args" :mode="mode" class="_hover">
|
|
73
|
+
<Heart />
|
|
74
|
+
</BmsIconButton>
|
|
75
|
+
<BmsIconButton v-bind="args" :mode="mode" disabled>
|
|
76
|
+
<Heart />
|
|
77
|
+
</BmsIconButton>
|
|
78
|
+
</template>
|
|
52
79
|
</div>
|
|
53
80
|
`,
|
|
54
81
|
});
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import BmsButton from '@/components/button/BmsButton.vue';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ArrowLeft,
|
|
4
|
+
ArrowRight,
|
|
5
|
+
Camera,
|
|
6
|
+
Heart,
|
|
7
|
+
Wand,
|
|
8
|
+
Check,
|
|
9
|
+
} from 'lucide-vue-next';
|
|
3
10
|
import { StatusType } from '@/models';
|
|
4
11
|
|
|
5
12
|
export default {
|
|
6
13
|
title: 'Composants/button/Button',
|
|
7
14
|
component: BmsButton,
|
|
8
15
|
tags: ['with_useable_code'],
|
|
16
|
+
parameters: {
|
|
17
|
+
chromatic: { disable: true },
|
|
18
|
+
},
|
|
9
19
|
argTypes: {
|
|
10
20
|
type: {
|
|
11
21
|
control: { type: 'select' },
|
|
@@ -25,78 +35,162 @@ export default {
|
|
|
25
35
|
const Template = (args) => ({
|
|
26
36
|
components: {
|
|
27
37
|
BmsButton,
|
|
28
|
-
ArrowRight,
|
|
29
|
-
ArrowLeft,
|
|
30
|
-
Camera,
|
|
31
|
-
Heart,
|
|
32
|
-
Wand,
|
|
33
38
|
},
|
|
34
39
|
setup() {
|
|
35
40
|
return { args };
|
|
36
41
|
},
|
|
37
42
|
template: `
|
|
38
|
-
<BmsButton v-bind="args">Save me</BmsButton>
|
|
39
|
-
<br>
|
|
40
|
-
<br>
|
|
41
|
-
<BmsButton v-bind="args">
|
|
42
|
-
Next page
|
|
43
|
-
<template #end><ArrowRight /></template>
|
|
44
|
-
</BmsButton>
|
|
45
|
-
<br>
|
|
46
|
-
<br>
|
|
47
|
-
<BmsButton v-bind="args">
|
|
48
|
-
<template #start>
|
|
49
|
-
<Heart/>
|
|
50
|
-
</template>
|
|
51
|
-
Icons left & right
|
|
52
|
-
<template #end>
|
|
53
|
-
<Wand/>
|
|
54
|
-
</template>
|
|
55
|
-
</BmsButton>
|
|
56
|
-
<br>
|
|
57
|
-
<br>
|
|
58
43
|
<BmsButton v-bind="args">
|
|
59
|
-
|
|
60
|
-
Retour
|
|
44
|
+
Save
|
|
61
45
|
</BmsButton>
|
|
62
|
-
|
|
63
|
-
`,
|
|
46
|
+
`,
|
|
64
47
|
});
|
|
65
48
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
default: 'Mon texte',
|
|
69
|
-
end: '<Wand/>',
|
|
70
|
-
};
|
|
49
|
+
export const Playground = Template.bind({});
|
|
50
|
+
Playground.args = {};
|
|
71
51
|
|
|
72
|
-
|
|
73
|
-
|
|
52
|
+
// Stories for documentation examples (Do/Don't)
|
|
53
|
+
export const DoSimple = Template.bind({});
|
|
54
|
+
DoSimple.args = {
|
|
74
55
|
type: 'primary',
|
|
75
|
-
...WITH_DEFAULT_SLOT,
|
|
76
56
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
...WITH_DEFAULT_SLOT,
|
|
81
|
-
type: 'primary',
|
|
82
|
-
mode: StatusType.Danger,
|
|
57
|
+
export const DoDanger = Template.bind({});
|
|
58
|
+
DoDanger.args = {
|
|
59
|
+
mode: 'danger',
|
|
83
60
|
};
|
|
84
61
|
|
|
85
|
-
export const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
type: 'secondary',
|
|
62
|
+
export const DoSmall = Template.bind({});
|
|
63
|
+
DoSmall.args = {
|
|
64
|
+
small: true,
|
|
89
65
|
};
|
|
90
66
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
67
|
+
// Do: Button with icon at start
|
|
68
|
+
export const DoIconStart = () => ({
|
|
69
|
+
components: { BmsButton, Check },
|
|
70
|
+
template: `
|
|
71
|
+
<BmsButton type="primary">
|
|
72
|
+
<template #start><Check /></template>
|
|
73
|
+
Confirm
|
|
74
|
+
</BmsButton>
|
|
75
|
+
`,
|
|
76
|
+
});
|
|
96
77
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
78
|
+
// Do: Button with icon at end
|
|
79
|
+
export const DoIconEnd = () => ({
|
|
80
|
+
components: { BmsButton, ArrowRight },
|
|
81
|
+
template: `
|
|
82
|
+
<BmsButton type="primary">
|
|
83
|
+
Next
|
|
84
|
+
<template #end><ArrowRight /></template>
|
|
85
|
+
</BmsButton>
|
|
86
|
+
`,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Do: Submit button
|
|
90
|
+
export const DoSubmit = () => ({
|
|
91
|
+
components: { BmsButton },
|
|
92
|
+
template: `
|
|
93
|
+
<form>
|
|
94
|
+
<BmsButton type="primary" :submit="true">Submit form</BmsButton>
|
|
95
|
+
</form>
|
|
96
|
+
`,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Don't: Long labels
|
|
100
|
+
export const DontLongLabel = () => ({
|
|
101
|
+
components: { BmsButton },
|
|
102
|
+
template:
|
|
103
|
+
'<BmsButton type="primary">Click here to save your changes to the document</BmsButton>',
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const DoShortLabel = () => ({
|
|
107
|
+
components: { BmsButton },
|
|
108
|
+
template: '<BmsButton type="primary">Save changes</BmsButton>',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Don't: Multiple primary buttons
|
|
112
|
+
export const DontMultiplePrimary = () => ({
|
|
113
|
+
components: { BmsButton },
|
|
114
|
+
template: `
|
|
115
|
+
<div style="display: flex; gap: 8px;">
|
|
116
|
+
<BmsButton type="primary">Save</BmsButton>
|
|
117
|
+
<BmsButton type="primary">Cancel</BmsButton>
|
|
118
|
+
<BmsButton type="primary">Delete</BmsButton>
|
|
119
|
+
</div>
|
|
120
|
+
`,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const DoOnePrimary = () => ({
|
|
124
|
+
components: { BmsButton },
|
|
125
|
+
template: `
|
|
126
|
+
<div style="display: flex; gap: 8px;">
|
|
127
|
+
<BmsButton type="primary">Save</BmsButton>
|
|
128
|
+
<BmsButton type="secondary">Cancel</BmsButton>
|
|
129
|
+
<BmsButton type="secondary">Delete</BmsButton>
|
|
130
|
+
</div>
|
|
131
|
+
`,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Don't: Too many icons
|
|
135
|
+
export const DontTooManyIcons = () => ({
|
|
136
|
+
components: { BmsButton, Heart, Wand, Check, ArrowRight },
|
|
137
|
+
template: `
|
|
138
|
+
<BmsButton type="primary">
|
|
139
|
+
<template #start><Heart /><Wand /></template>
|
|
140
|
+
Save changes
|
|
141
|
+
<template #end><Check /><ArrowRight /></template>
|
|
142
|
+
</BmsButton>
|
|
143
|
+
`,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export const DoOneIcon = () => ({
|
|
147
|
+
components: { BmsButton, ArrowRight },
|
|
148
|
+
template: `
|
|
149
|
+
<BmsButton type="primary">
|
|
150
|
+
<template #end><ArrowRight /></template>
|
|
151
|
+
Next
|
|
152
|
+
</BmsButton>
|
|
153
|
+
`,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Don't: Generic labels
|
|
157
|
+
export const DontGenericLabel = () => ({
|
|
158
|
+
components: { BmsButton },
|
|
159
|
+
template: `
|
|
160
|
+
<div style="display: flex; gap: 8px;">
|
|
161
|
+
<BmsButton type="primary">Click here</BmsButton>
|
|
162
|
+
<BmsButton type="primary">Submit</BmsButton>
|
|
163
|
+
</div>
|
|
164
|
+
`,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
export const DoSpecificLabel = () => ({
|
|
168
|
+
components: { BmsButton },
|
|
169
|
+
template: `
|
|
170
|
+
<div style="display: flex; gap: 8px;">
|
|
171
|
+
<BmsButton type="primary">Save changes</BmsButton>
|
|
172
|
+
<BmsButton type="primary">Confirm order</BmsButton>
|
|
173
|
+
</div>
|
|
174
|
+
`,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Don't: Primary for cancel
|
|
178
|
+
export const DontPrimaryForCancel = () => ({
|
|
179
|
+
components: { BmsButton },
|
|
180
|
+
template: `
|
|
181
|
+
<div style="display: flex; gap: 8px;">
|
|
182
|
+
<BmsButton type="primary">Cancel</BmsButton>
|
|
183
|
+
<BmsButton type="secondary">Save</BmsButton>
|
|
184
|
+
</div>
|
|
185
|
+
`,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export const DoPrimaryForSave = () => ({
|
|
189
|
+
components: { BmsButton },
|
|
190
|
+
template: `
|
|
191
|
+
<div style="display: flex; gap: 8px;">
|
|
192
|
+
<BmsButton type="secondary">Cancel</BmsButton>
|
|
193
|
+
<BmsButton type="primary">Save</BmsButton>
|
|
194
|
+
</div>
|
|
195
|
+
`,
|
|
196
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import BmsGhost from './BmsGhost.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Composants/feedback/Ghost',
|
|
5
|
+
component: BmsGhost,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
components: {
|
|
10
|
+
BmsGhost,
|
|
11
|
+
},
|
|
12
|
+
data() {
|
|
13
|
+
return { args };
|
|
14
|
+
},
|
|
15
|
+
template: `
|
|
16
|
+
<div
|
|
17
|
+
:style="{
|
|
18
|
+
position: 'fixed',
|
|
19
|
+
top: 0,
|
|
20
|
+
left: 0,
|
|
21
|
+
width: '100%',
|
|
22
|
+
height: '100%',
|
|
23
|
+
padding: '1em',
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'center',
|
|
27
|
+
userSelect: 'none',
|
|
28
|
+
cursor: 'pointer'
|
|
29
|
+
}"
|
|
30
|
+
@pointerdown="args.modelValue = !args.modelValue"
|
|
31
|
+
>
|
|
32
|
+
<p>Cliquez pour faire apparaître/Disparaître le fantôme</p>
|
|
33
|
+
</div>
|
|
34
|
+
<BmsGhost
|
|
35
|
+
v-model="args.modelValue"
|
|
36
|
+
:opacity-when-visible="args.opacityWhenVisible"
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
:style="{
|
|
40
|
+
background: 'darkslategray',
|
|
41
|
+
color: 'white',
|
|
42
|
+
padding: '1em',
|
|
43
|
+
borderRadius: '8px',
|
|
44
|
+
}"
|
|
45
|
+
>
|
|
46
|
+
<h3 :style="{
|
|
47
|
+
margin: 0,
|
|
48
|
+
color: 'white',
|
|
49
|
+
}">Bonjour !</h3>
|
|
50
|
+
<p style="margin: 0">Je suis un fantôme</p>
|
|
51
|
+
</div>
|
|
52
|
+
</BmsGhost>
|
|
53
|
+
`,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export const Default = Template.bind({});
|
|
57
|
+
Default.args = {
|
|
58
|
+
modelValue: false,
|
|
59
|
+
opacityWhenVisible: 0.6,
|
|
60
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
opacityWhenVisible?: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const SCREEN_MARGIN = 10;
|
|
7
|
+
|
|
8
|
+
import { onBeforeMount, onBeforeUnmount, ref } from 'vue';
|
|
9
|
+
|
|
10
|
+
const visible = defineModel<boolean>({
|
|
11
|
+
default: false,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
15
|
+
opacityWhenVisible: 0.8,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const ghost = ref<HTMLElement | null>(null);
|
|
19
|
+
const x = ref<number>(0);
|
|
20
|
+
const y = ref<number>(0);
|
|
21
|
+
|
|
22
|
+
onBeforeMount(() => {
|
|
23
|
+
document.addEventListener('pointermove', onPointerMove);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
onBeforeUnmount(() => {
|
|
27
|
+
document.removeEventListener('pointermove', onPointerMove);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const onPointerMove = (e: PointerEvent) => {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
|
|
34
|
+
updateGhost(e.clientX, e.clientY);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const updateGhost = (posX: number, posY: number) => {
|
|
38
|
+
if (!ghost.value) return;
|
|
39
|
+
|
|
40
|
+
const rect = ghost.value.getBoundingClientRect();
|
|
41
|
+
const screenWidth = window.innerWidth;
|
|
42
|
+
const screenHeight = window.innerHeight;
|
|
43
|
+
|
|
44
|
+
//Update position
|
|
45
|
+
x.value = Math.max(
|
|
46
|
+
Math.min(posX, screenWidth - rect.width - SCREEN_MARGIN),
|
|
47
|
+
SCREEN_MARGIN,
|
|
48
|
+
);
|
|
49
|
+
y.value = Math.max(
|
|
50
|
+
Math.min(posY, screenHeight - rect.height - SCREEN_MARGIN),
|
|
51
|
+
SCREEN_MARGIN,
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<template>
|
|
57
|
+
<div
|
|
58
|
+
ref="ghost"
|
|
59
|
+
aria-hidden="true"
|
|
60
|
+
class="bms-ghost"
|
|
61
|
+
:style="{
|
|
62
|
+
'--ghost-x': `${x}px`,
|
|
63
|
+
'--ghost-y': `${y}px`,
|
|
64
|
+
opacity: visible ? props.opacityWhenVisible : 0,
|
|
65
|
+
}"
|
|
66
|
+
>
|
|
67
|
+
<slot />
|
|
68
|
+
</div>
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
<style scoped lang="scss">
|
|
72
|
+
.bms-ghost {
|
|
73
|
+
position: fixed;
|
|
74
|
+
top: var(--ghost-y, 0);
|
|
75
|
+
left: var(--ghost-x, 0);
|
|
76
|
+
z-index: 1000;
|
|
77
|
+
|
|
78
|
+
pointer-events: none;
|
|
79
|
+
user-select: none;
|
|
80
|
+
transition: opacity 0.2s ease-in-out;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
:visible="showToolTip && activated"
|
|
6
6
|
:direction="direction"
|
|
7
7
|
:getAnchorElementValues="getAnchorElementValues"
|
|
8
|
+
:class="classes"
|
|
8
9
|
>
|
|
9
10
|
<slot name="tooltipText">
|
|
10
11
|
{{ tooltipText }}
|
|
@@ -26,9 +27,12 @@ import {
|
|
|
26
27
|
MaybeElementRef,
|
|
27
28
|
useElementVisibility,
|
|
28
29
|
} from '@vueuse/core';
|
|
29
|
-
import { ref, watchEffect } from 'vue';
|
|
30
|
+
import { computed, ref, watchEffect } from 'vue';
|
|
30
31
|
import UiTooltip from './UiTooltip.vue';
|
|
31
32
|
|
|
33
|
+
import { useAttrs } from 'vue';
|
|
34
|
+
const attrs = useAttrs();
|
|
35
|
+
|
|
32
36
|
const tooltip = ref(null);
|
|
33
37
|
const tooltipAnchor = ref<Element>();
|
|
34
38
|
const showToolTip = ref(true);
|
|
@@ -51,6 +55,16 @@ withDefaults(
|
|
|
51
55
|
},
|
|
52
56
|
);
|
|
53
57
|
|
|
58
|
+
const classes = computed(() => {
|
|
59
|
+
const parentClasses = attrs.class as string | undefined;
|
|
60
|
+
return (
|
|
61
|
+
parentClasses
|
|
62
|
+
?.split(' ')
|
|
63
|
+
.map((cls) => `${cls}__bms-tooltip`)
|
|
64
|
+
.join(' ') ?? ''
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
54
68
|
const isUnderOverlay = (): boolean => {
|
|
55
69
|
const overlays = Array.from(document.getElementsByClassName('overlay'));
|
|
56
70
|
if (overlays.length === 0) {
|
|
@@ -25,6 +25,9 @@ const calculatedTooltipTransform: Ref<string> = ref<string>('none');
|
|
|
25
25
|
const windowSize = useWindowSize();
|
|
26
26
|
const { getTooltipTranslatePosition } = useTooltipHelper();
|
|
27
27
|
|
|
28
|
+
import { useAttrs } from 'vue';
|
|
29
|
+
const attrs = useAttrs();
|
|
30
|
+
|
|
28
31
|
const props = withDefaults(
|
|
29
32
|
defineProps<{
|
|
30
33
|
visible?: boolean;
|
|
@@ -61,7 +64,8 @@ const anchorElement = ref<
|
|
|
61
64
|
>(undefined);
|
|
62
65
|
|
|
63
66
|
const classes = computed(
|
|
64
|
-
() =>
|
|
67
|
+
() =>
|
|
68
|
+
`bms-tooltip__text bms-tooltip__text--${props.direction} ${attrs.class ? attrs.class : ''}`,
|
|
65
69
|
);
|
|
66
70
|
|
|
67
71
|
const setTooltipPosition = async () => {
|
|
@@ -136,6 +140,10 @@ const style = computed(() => {
|
|
|
136
140
|
transform: var(--bms-tooltip-transform);
|
|
137
141
|
overflow-wrap: break-word;
|
|
138
142
|
|
|
143
|
+
&.floating-window__expand-btn__bms-tooltip {
|
|
144
|
+
z-index: calc(var(--bms-z-index-modal) + 1);
|
|
145
|
+
}
|
|
146
|
+
|
|
139
147
|
&::before {
|
|
140
148
|
content: '';
|
|
141
149
|
position: absolute;
|
|
@@ -32,7 +32,12 @@ const Template = (args) => ({
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
export const Empty = Template.bind({});
|
|
35
|
-
Empty.args = {
|
|
35
|
+
Empty.args = {
|
|
36
|
+
modelValue: [],
|
|
37
|
+
limit: 5,
|
|
38
|
+
dragOverMessage: 'Déposer vos fichiers ici',
|
|
39
|
+
dragOffMessage: 'Glissez votre fichier ici ou cliquez pour parcourir',
|
|
40
|
+
};
|
|
36
41
|
|
|
37
42
|
export const WithFiles = Template.bind({});
|
|
38
43
|
WithFiles.args = {
|
|
@@ -7,9 +7,16 @@ const files: Ref<File[] | undefined> = ref();
|
|
|
7
7
|
const isDragOver = ref(false);
|
|
8
8
|
|
|
9
9
|
const props = withDefaults(
|
|
10
|
-
defineProps<{
|
|
10
|
+
defineProps<{
|
|
11
|
+
dragOverMessage?: string;
|
|
12
|
+
dragOffMessage?: string;
|
|
13
|
+
modelValue?: File[];
|
|
14
|
+
limit: number;
|
|
15
|
+
}>(),
|
|
11
16
|
{
|
|
12
17
|
limit: 10,
|
|
18
|
+
dragOverMessage: 'Déposer votre image ici',
|
|
19
|
+
dragOffMessage: 'Glissez votre image ici ou cliquez pour parcourir',
|
|
13
20
|
},
|
|
14
21
|
);
|
|
15
22
|
|
|
@@ -101,10 +108,8 @@ function onDeleteFile(file: File) {
|
|
|
101
108
|
@dragover.prevent
|
|
102
109
|
>
|
|
103
110
|
<label class="file-upload__label">
|
|
104
|
-
<template v-if="isDragOver">
|
|
105
|
-
<template v-else
|
|
106
|
-
>Glissez votre image ici ou cliquez pour parcourir</template
|
|
107
|
-
>
|
|
111
|
+
<template v-if="isDragOver">{{ dragOverMessage }}</template>
|
|
112
|
+
<template v-else>{{ dragOffMessage }}</template>
|
|
108
113
|
<input
|
|
109
114
|
data-testid="file-upload-input-file"
|
|
110
115
|
type="file"
|