@ouestfrance/sipa-bms-ui 8.10.1 → 8.12.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/button/BmsButton.vue.d.ts +2 -1
- package/dist/components/button/BmsIconButton.vue.d.ts +3 -1
- package/dist/components/button/UiButton.vue.d.ts +4 -2
- package/dist/components/button/UiButtonLink.vue.d.ts +1 -0
- package/dist/components/feedback/BmsTooltip.vue.d.ts +1 -1
- package/dist/components/feedback/UiTooltip.vue.d.ts +1 -1
- package/dist/components/form/BmsInputText.vue.d.ts +2 -0
- package/dist/components/form/BmsSearch.vue.d.ts +4 -0
- package/dist/components/form/RawAutocomplete.vue.d.ts +2 -0
- package/dist/components/layout/BmsHeaderTitle.vue.d.ts +1 -1
- package/dist/components/layout/UiPopoverMenu.vue.d.ts +1 -1
- package/dist/components/navigation/BmsBreadcrumb.vue.d.ts +1 -1
- package/dist/components/navigation/BmsShortLinkMenu.vue.d.ts +2 -2
- package/dist/components/navigation/UiTenantSwitcher.vue.d.ts +4 -0
- package/dist/components/table/BmsTableFilters.vue.d.ts +4 -0
- package/dist/components/utils/BmsCocarde.vue.d.ts +1 -1
- package/dist/mockServiceWorker.js +2 -1
- package/dist/plugins/field/FieldComponent.vue.d.ts +3 -0
- package/dist/plugins/field/SkeletonField.vue.d.ts +2 -0
- package/dist/plugins/field/field-component.model.d.ts +2 -0
- package/dist/plugins/router-history/router-history.composable.d.ts +1 -1
- package/dist/sipa-bms-ui.css +95 -100
- package/dist/sipa-bms-ui.es.js +4099 -4009
- package/dist/sipa-bms-ui.es.js.map +1 -1
- package/dist/sipa-bms-ui.umd.js +4106 -4016
- package/dist/sipa-bms-ui.umd.js.map +1 -1
- package/package.json +19 -18
- package/src/components/button/BmsButton.stories.js +26 -0
- package/src/components/button/BmsButton.vue +2 -0
- package/src/components/button/BmsIconButton.stories.js +4 -0
- package/src/components/button/BmsIconButton.vue +10 -1
- package/src/components/button/UiButton.vue +2 -0
- package/src/components/button/UiButtonLink.vue +13 -6
- package/src/components/feedback/UiTooltip.vue +1 -0
- package/src/components/form/BmsAutocomplete.stories.js +12 -0
- package/src/components/form/BmsAutocomplete.vue +1 -0
- package/src/components/form/BmsInputText.stories.js +8 -0
- package/src/components/form/BmsInputToggle.stories.js +27 -0
- package/src/components/form/BmsInputToggle.vue +16 -2
- package/src/components/form/BmsMultiSelect.vue +6 -1
- package/src/components/form/BmsSelect.stories.js +9 -0
- package/src/components/form/BmsSelect.vue +31 -65
- package/src/components/form/BmsServerAutocomplete.stories.js +25 -2
- package/src/components/form/BmsServerAutocomplete.vue +1 -0
- package/src/components/form/RawSelect.vue +1 -18
- package/src/components/layout/BmsModal.stories.js +1 -1
- package/src/components/table/BmsServerTable.vue +2 -4
- package/src/plugins/field/FieldComponent.spec.ts +2 -1
- package/src/plugins/field/FieldComponent.stories.js +18 -1
- package/src/plugins/field/FieldComponent.vue +26 -6
- package/src/plugins/field/SkeletonField.stories.js +21 -0
- package/src/plugins/field/SkeletonField.vue +27 -0
- package/src/plugins/field/field-component.model.ts +2 -0
- package/src/showroom/App.vue +5 -0
- package/src/showroom/pages/loading-form.vue +78 -0
|
@@ -17,6 +17,7 @@ const Template = (args) => ({
|
|
|
17
17
|
Album,
|
|
18
18
|
},
|
|
19
19
|
template: `
|
|
20
|
+
<div style="border:1px solid grey; width: 400px;">
|
|
20
21
|
<field v-bind="args">
|
|
21
22
|
<template #icon-start v-if="args.iconStart">
|
|
22
23
|
<Flashlight/>
|
|
@@ -26,12 +27,28 @@ const Template = (args) => ({
|
|
|
26
27
|
<Album/>
|
|
27
28
|
</template>
|
|
28
29
|
</field>
|
|
29
|
-
|
|
30
|
+
</div>
|
|
31
|
+
`,
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
export const Default = Template.bind({});
|
|
33
35
|
Default.args = {
|
|
34
36
|
label: 'My label',
|
|
37
|
+
ellipsisLabel: true,
|
|
38
|
+
captions: ['Helping text'],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const NoOverflow = Template.bind({});
|
|
42
|
+
NoOverflow.args = {
|
|
43
|
+
label: 'My label looooooooooooooooooooooooooooooooooooooooooooooong',
|
|
44
|
+
ellipsisLabel: false,
|
|
45
|
+
captions: ['Helping text'],
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Overflow = Template.bind({});
|
|
49
|
+
Overflow.args = {
|
|
50
|
+
label: 'My label looooooooooooooooooooooooooooooooooooooooooooooong',
|
|
51
|
+
ellipsisLabel: true,
|
|
35
52
|
captions: ['Helping text'],
|
|
36
53
|
};
|
|
37
54
|
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="classes">
|
|
2
|
+
<div :class="classes" ref="parentElement">
|
|
3
3
|
<div class="field__wrapper">
|
|
4
4
|
<span class="field__label">
|
|
5
|
-
<span
|
|
5
|
+
<span
|
|
6
|
+
class="field__label__title"
|
|
7
|
+
:class="{ ellipsis: ellipsisLabel }"
|
|
8
|
+
:title="ellipsisLabel ? label : undefined"
|
|
9
|
+
>
|
|
10
|
+
{{ label }}
|
|
11
|
+
</span>
|
|
12
|
+
|
|
6
13
|
<span v-if="required" class="field__label-required">*</span>
|
|
7
14
|
<span v-if="optional && !required" class="field__label-optional">
|
|
8
15
|
(Optionnel)
|
|
@@ -15,7 +22,8 @@
|
|
|
15
22
|
</span>
|
|
16
23
|
|
|
17
24
|
<span class="field__input">
|
|
18
|
-
<
|
|
25
|
+
<SkeletonField v-if="loading" />
|
|
26
|
+
<slot v-else></slot>
|
|
19
27
|
</span>
|
|
20
28
|
<span ref="datalist">
|
|
21
29
|
<span class="field__datalist" :class="{ top: openTop }">
|
|
@@ -53,16 +61,20 @@ import { useElementBounding, useWindowSize } from '@vueuse/core';
|
|
|
53
61
|
import { Caption } from '@/models/caption.model';
|
|
54
62
|
import BmsCaption from '@/components/feedback/BmsCaption.vue';
|
|
55
63
|
import { FieldComponentProps } from './field-component.model';
|
|
64
|
+
import SkeletonField from './SkeletonField.vue';
|
|
56
65
|
|
|
57
66
|
const props = withDefaults(defineProps<FieldComponentProps>(), {
|
|
58
67
|
label: '',
|
|
59
68
|
optional: false,
|
|
60
69
|
small: false,
|
|
70
|
+
loading: false,
|
|
71
|
+
ellipsisLabel: false,
|
|
61
72
|
});
|
|
62
73
|
|
|
63
74
|
const datalist: Ref<HTMLSpanElement | null> = ref<HTMLSpanElement | null>(null);
|
|
64
|
-
const { y } = useElementBounding(datalist);
|
|
65
75
|
|
|
76
|
+
const { y } = useElementBounding(datalist);
|
|
77
|
+
const parentElement = ref<HTMLElement | null>(null);
|
|
66
78
|
const { height: windowHeight } = useWindowSize();
|
|
67
79
|
|
|
68
80
|
const classes = computed(() => {
|
|
@@ -140,7 +152,6 @@ const getCaptionIdentifier = (caption: string | Caption): string => {
|
|
|
140
152
|
&__wrapper {
|
|
141
153
|
display: inline-block;
|
|
142
154
|
position: relative;
|
|
143
|
-
min-width: 24rem;
|
|
144
155
|
width: 100%;
|
|
145
156
|
background-color: transparent;
|
|
146
157
|
}
|
|
@@ -150,9 +161,17 @@ const getCaptionIdentifier = (caption: string | Caption): string => {
|
|
|
150
161
|
align-items: center;
|
|
151
162
|
|
|
152
163
|
&__title {
|
|
164
|
+
display: inline-block;
|
|
165
|
+
white-space: nowrap;
|
|
166
|
+
|
|
153
167
|
font-size: 1em;
|
|
154
168
|
font-weight: var(--field-label-font-weight);
|
|
155
169
|
color: var(--field-label-color);
|
|
170
|
+
|
|
171
|
+
&.ellipsis {
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
text-overflow: ellipsis;
|
|
174
|
+
}
|
|
156
175
|
}
|
|
157
176
|
|
|
158
177
|
&-helper--icon {
|
|
@@ -182,10 +201,11 @@ const getCaptionIdentifier = (caption: string | Caption): string => {
|
|
|
182
201
|
}
|
|
183
202
|
|
|
184
203
|
&.is-small {
|
|
185
|
-
--field-height:
|
|
204
|
+
--field-height: 1.5em;
|
|
186
205
|
--field-padding: 0.5em;
|
|
187
206
|
--field-margin: 0;
|
|
188
207
|
--field-label-font-weight: normal;
|
|
208
|
+
|
|
189
209
|
.field__captions {
|
|
190
210
|
margin-top: 0.5rem;
|
|
191
211
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import SkeletonField from './SkeletonField.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Composants/form/SkeletonField',
|
|
5
|
+
component: SkeletonField,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
setup() {
|
|
10
|
+
return { args };
|
|
11
|
+
},
|
|
12
|
+
components: {
|
|
13
|
+
SkeletonField,
|
|
14
|
+
},
|
|
15
|
+
template: `
|
|
16
|
+
<SkeletonField v-bind="args" style="width:200px;height:20px"/>
|
|
17
|
+
`,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const Default = Template.bind({});
|
|
21
|
+
Default.args = {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="skeleton"></div>
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<style lang="css" scoped>
|
|
6
|
+
@keyframes blink-animation {
|
|
7
|
+
0% {
|
|
8
|
+
background-color: var(--bms-main-25);
|
|
9
|
+
}
|
|
10
|
+
50% {
|
|
11
|
+
background-color: var(--bms-main-10);
|
|
12
|
+
}
|
|
13
|
+
100% {
|
|
14
|
+
background-color: var(--bms-main-25);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
.skeleton {
|
|
18
|
+
/* background-color: var(--bms-main-25); */
|
|
19
|
+
min-height: var(--field-height);
|
|
20
|
+
border-radius: var(--bms-border-radius);
|
|
21
|
+
height: 100%;
|
|
22
|
+
width: 100%;
|
|
23
|
+
/* opacity: 0.7; */
|
|
24
|
+
/* transition: background-color 1000ms linear; */
|
|
25
|
+
animation: blink-animation 2s steps(10, start) infinite alternate;
|
|
26
|
+
}
|
|
27
|
+
</style>
|
|
@@ -2,6 +2,7 @@ import { Caption } from '@/models';
|
|
|
2
2
|
|
|
3
3
|
export interface FieldComponentProps {
|
|
4
4
|
label?: string;
|
|
5
|
+
loading?: boolean;
|
|
5
6
|
required?: boolean;
|
|
6
7
|
optional?: boolean;
|
|
7
8
|
helperText?: string;
|
|
@@ -9,4 +10,5 @@ export interface FieldComponentProps {
|
|
|
9
10
|
captions?: (string | Caption)[];
|
|
10
11
|
disabled?: boolean;
|
|
11
12
|
small?: boolean;
|
|
13
|
+
ellipsisLabel?: boolean;
|
|
12
14
|
}
|
package/src/showroom/App.vue
CHANGED
|
@@ -92,6 +92,11 @@ const menuItems: (MenuItem | ParentMenuItem)[] = [
|
|
|
92
92
|
link: '/draggable-list',
|
|
93
93
|
id: 'draggableList',
|
|
94
94
|
},
|
|
95
|
+
{
|
|
96
|
+
label: 'Formulaire asynchrone',
|
|
97
|
+
link: '/loading-form',
|
|
98
|
+
id: 'loadingForm',
|
|
99
|
+
},
|
|
95
100
|
{
|
|
96
101
|
label: 'External Url',
|
|
97
102
|
link: 'https://google.fr',
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<BmsInputToggle label="Loading" name="loading" v-model="loading" />
|
|
3
|
+
<BmsInputToggle label="Small" name="small" v-model="small" />
|
|
4
|
+
<BmsForm>
|
|
5
|
+
<template #section1>
|
|
6
|
+
<h2>Formulaire statique aux options dynamiques</h2>
|
|
7
|
+
<BmsSelect
|
|
8
|
+
label="Select"
|
|
9
|
+
v-model="select"
|
|
10
|
+
:loading="loading"
|
|
11
|
+
:small="small"
|
|
12
|
+
:options="selectOptions"
|
|
13
|
+
/>
|
|
14
|
+
<BmsAutocomplete
|
|
15
|
+
label="Autocomplete"
|
|
16
|
+
v-model="autocomplete"
|
|
17
|
+
:loading="loading"
|
|
18
|
+
:small="small"
|
|
19
|
+
:options="autocompleteOptions"
|
|
20
|
+
/>
|
|
21
|
+
<BmsInputText
|
|
22
|
+
label="Text"
|
|
23
|
+
v-model="autocomplete"
|
|
24
|
+
:loading="loading"
|
|
25
|
+
:small="small"
|
|
26
|
+
/>
|
|
27
|
+
<BmsInputBooleanCheckbox
|
|
28
|
+
:model-value="false"
|
|
29
|
+
:loading="loading"
|
|
30
|
+
:small="small"
|
|
31
|
+
label="boolean"
|
|
32
|
+
name="boolean"
|
|
33
|
+
label-value="oui"
|
|
34
|
+
/>
|
|
35
|
+
<BmsInputRadioCaptionGroup
|
|
36
|
+
:loading="loading"
|
|
37
|
+
:small="small"
|
|
38
|
+
label="Radio Buttons"
|
|
39
|
+
v-model="radio"
|
|
40
|
+
:options="[
|
|
41
|
+
{ value: 'tata', label: 'Tata', captions: ['Caption'] },
|
|
42
|
+
{ value: 'titi', label: 'Titi', captions: ['Caption'] },
|
|
43
|
+
{ value: 'toto', label: 'Toto', captions: ['Caption'] },
|
|
44
|
+
{ value: 'tutu', captions: ['Caption'] },
|
|
45
|
+
]"
|
|
46
|
+
:captions="loading ? [] : ['this is a question']"
|
|
47
|
+
required
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
50
|
+
</BmsForm>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script setup lang="ts">
|
|
54
|
+
import BmsAutocomplete from '@/components/form/BmsAutocomplete.vue';
|
|
55
|
+
import BmsInputBooleanCheckbox from '@/components/form/BmsInputBooleanCheckbox.vue';
|
|
56
|
+
import BmsInputRadioCaptionGroup from '@/components/form/BmsInputRadioCaptionGroup.vue';
|
|
57
|
+
import BmsInputText from '@/components/form/BmsInputText.vue';
|
|
58
|
+
import BmsInputToggle from '@/components/form/BmsInputToggle.vue';
|
|
59
|
+
import BmsSelect from '@/components/form/BmsSelect.vue';
|
|
60
|
+
import BmsForm from '@/components/layout/BmsForm.vue';
|
|
61
|
+
import { InputOption } from '@/models';
|
|
62
|
+
import { ref } from 'vue';
|
|
63
|
+
|
|
64
|
+
const loading = ref(true);
|
|
65
|
+
const small = ref(true);
|
|
66
|
+
const select = ref([]);
|
|
67
|
+
const autocomplete = ref('');
|
|
68
|
+
|
|
69
|
+
const selectOptions = ref<InputOption[]>([
|
|
70
|
+
{ label: 'label 1', value: 1 },
|
|
71
|
+
{ label: 'label 2', value: 2 },
|
|
72
|
+
]);
|
|
73
|
+
const autocompleteOptions = ref<InputOption[]>([
|
|
74
|
+
{ label: 'label 1', value: 1 },
|
|
75
|
+
{ label: 'label 2', value: 2 },
|
|
76
|
+
]);
|
|
77
|
+
const radio = ref('toto');
|
|
78
|
+
</script>
|