@ouestfrance/sipa-bms-ui 8.24.1 → 8.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/form/BmsAutocomplete.vue.d.ts +219 -2
- package/dist/components/navigation/UiTab.vue.d.ts +5 -1
- package/dist/components/navigation/UiTabs.vue.d.ts +1 -1
- package/dist/helpers/tab.helper.d.ts +3 -0
- package/dist/helpers/tab.helper.spec.d.ts +1 -0
- package/dist/models/tab.model.d.ts +1 -1
- package/dist/sipa-bms-ui.css +13 -17
- package/dist/sipa-bms-ui.es.js +3954 -3795
- package/dist/sipa-bms-ui.es.js.map +1 -1
- package/dist/sipa-bms-ui.umd.js +3953 -3794
- package/dist/sipa-bms-ui.umd.js.map +1 -1
- package/package.json +13 -13
- package/src/components/form/BmsAutocomplete.vue +8 -1
- package/src/components/navigation/BmsTabs.stories.js +11 -1
- package/src/components/navigation/BmsTabs.vue +50 -21
- package/src/components/navigation/UiTab.vue +25 -16
- package/src/components/navigation/UiTabs.stories.js +7 -3
- package/src/components/navigation/UiTabs.vue +3 -19
- package/src/helpers/tab.helper.spec.ts +87 -0
- package/src/helpers/tab.helper.ts +19 -1
- package/src/models/tab.model.ts +1 -1
- package/src/showroom/pages/autocomplete.vue +7 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouestfrance/sipa-bms-ui",
|
|
3
|
-
"version": "8.24.
|
|
3
|
+
"version": "8.24.3",
|
|
4
4
|
"author": "Ouest-France BMS",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"scripts": {
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
"@commitlint/cli": "20.3.1",
|
|
37
37
|
"@commitlint/config-conventional": "20.3.1",
|
|
38
38
|
"@mdx-js/react": "3.1.1",
|
|
39
|
-
"@storybook/addon-docs": "10.
|
|
40
|
-
"@storybook/addon-links": "10.
|
|
41
|
-
"@storybook/vue3-vite": "10.
|
|
39
|
+
"@storybook/addon-docs": "10.2.0",
|
|
40
|
+
"@storybook/addon-links": "10.2.0",
|
|
41
|
+
"@storybook/vue3-vite": "10.2.0",
|
|
42
42
|
"@types/lodash": "4.17.23",
|
|
43
43
|
"@types/uuid": "11.0.0",
|
|
44
44
|
"@vitejs/plugin-vue": "6.0.3",
|
|
45
45
|
"@vue/test-utils": "2.4.6",
|
|
46
46
|
"@vueuse/core": "13.9.0",
|
|
47
47
|
"@vueuse/motion": "^3.0.0",
|
|
48
|
-
"axios": "1.13.
|
|
48
|
+
"axios": "1.13.3",
|
|
49
49
|
"blob-util": "^2.0.2",
|
|
50
50
|
"chromatic": "13.3.5",
|
|
51
51
|
"codemirror": "6.0.2",
|
|
@@ -58,19 +58,19 @@
|
|
|
58
58
|
"jsdom": "27.4.0",
|
|
59
59
|
"keycloak-js": "26.1.2",
|
|
60
60
|
"lint-staged": "16.2.7",
|
|
61
|
-
"lodash": "4.17.
|
|
62
|
-
"lucide-vue-next": "0.
|
|
61
|
+
"lodash": "4.17.23",
|
|
62
|
+
"lucide-vue-next": "0.563.0",
|
|
63
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
|
-
"prettier": "3.8.
|
|
67
|
+
"prettier": "3.8.1",
|
|
68
68
|
"remark-gfm": "^4.0.1",
|
|
69
|
-
"sass": "1.97.
|
|
69
|
+
"sass": "1.97.3",
|
|
70
70
|
"semantic-release": "25.0.2",
|
|
71
71
|
"start-server-and-test": "2.1.3",
|
|
72
|
-
"storybook": "10.
|
|
73
|
-
"storybook-addon-pseudo-states": "10.
|
|
72
|
+
"storybook": "10.2.0",
|
|
73
|
+
"storybook-addon-pseudo-states": "10.2.0",
|
|
74
74
|
"storybook-addon-tag-badges": "^3.0.2",
|
|
75
75
|
"storybook-vue3-router": "^7.0.0",
|
|
76
76
|
"typescript": "5.2.2",
|
|
@@ -81,11 +81,11 @@
|
|
|
81
81
|
"vite-plugin-pages": "0.33.2",
|
|
82
82
|
"vite-svg-loader": "5.1.0",
|
|
83
83
|
"vitest": "3.2.4",
|
|
84
|
-
"vue": "3.5.
|
|
84
|
+
"vue": "3.5.27",
|
|
85
85
|
"vue-codemirror": "6.1.1",
|
|
86
86
|
"vue-loader": "17.4.2",
|
|
87
87
|
"vue-router": "4.6.4",
|
|
88
|
-
"vue-tsc": "3.2.
|
|
88
|
+
"vue-tsc": "3.2.3"
|
|
89
89
|
},
|
|
90
90
|
"files": [
|
|
91
91
|
"dist",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<RawAutocomplete
|
|
3
3
|
v-model="modelValue"
|
|
4
|
+
ref="autocompleteElement"
|
|
4
5
|
:options="optionsLabelValue"
|
|
5
6
|
:open="open"
|
|
6
7
|
:label="label"
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
</template>
|
|
43
44
|
|
|
44
45
|
<script setup lang="ts">
|
|
45
|
-
import { computed } from 'vue';
|
|
46
|
+
import { computed, useTemplateRef } from 'vue';
|
|
46
47
|
import RawAutocomplete from './RawAutocomplete.vue';
|
|
47
48
|
import { InputOption } from '@/models';
|
|
48
49
|
import { FieldComponentProps } from '@/plugins/field/field-component.model';
|
|
@@ -69,6 +70,8 @@ const emits = defineEmits<{
|
|
|
69
70
|
input: [e: InputEvent];
|
|
70
71
|
}>();
|
|
71
72
|
|
|
73
|
+
const autocompleteElement = useTemplateRef('autocompleteElement');
|
|
74
|
+
|
|
72
75
|
const currentOptionIcon = computed(() => {
|
|
73
76
|
const option = props.options.find(
|
|
74
77
|
(o) => typeof o !== 'string' && o.value === modelValue.value,
|
|
@@ -84,6 +87,10 @@ const optionsLabelValue = computed(() =>
|
|
|
84
87
|
? props.options.map((o) => ({ label: o, value: o }) as InputOption)
|
|
85
88
|
: (props.options as InputOption[]),
|
|
86
89
|
);
|
|
90
|
+
|
|
91
|
+
defineExpose({
|
|
92
|
+
setFocus: () => autocompleteElement.value?.setFocus(),
|
|
93
|
+
});
|
|
87
94
|
</script>
|
|
88
95
|
|
|
89
96
|
<style scoped lang="scss">
|
|
@@ -39,8 +39,18 @@ const Template = (args) => ({
|
|
|
39
39
|
export const Default = Template.bind({});
|
|
40
40
|
Default.args = {
|
|
41
41
|
title: 'Title',
|
|
42
|
-
tabs: [
|
|
42
|
+
tabs: [
|
|
43
|
+
{ name: 'Titi', id: 'titi' },
|
|
44
|
+
{ name: 'Toto', id: 'toto' },
|
|
45
|
+
],
|
|
43
46
|
};
|
|
47
|
+
|
|
48
|
+
export const DefaultWithoutId = Template.bind({});
|
|
49
|
+
DefaultWithoutId.args = {
|
|
50
|
+
title: 'Title',
|
|
51
|
+
tabs: [{ name: 'Titi' }, { name: 'Toto' }],
|
|
52
|
+
};
|
|
53
|
+
|
|
44
54
|
export const WithSelectedTabId = Template.bind({});
|
|
45
55
|
WithSelectedTabId.args = {
|
|
46
56
|
title: 'Title',
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<UiTabs
|
|
3
3
|
:title="title"
|
|
4
|
-
:tabs="
|
|
5
|
-
:
|
|
6
|
-
@click="
|
|
4
|
+
:tabs="computedTabs"
|
|
5
|
+
:selected-tab-id="selectedTabId"
|
|
6
|
+
@click="onClick"
|
|
7
7
|
>
|
|
8
8
|
<template v-if="needRouterEngine" #router="{ tab }">
|
|
9
|
-
<router-link
|
|
10
|
-
tab
|
|
11
|
-
|
|
9
|
+
<router-link
|
|
10
|
+
class="tab"
|
|
11
|
+
:to="getTabTarget(tab)"
|
|
12
|
+
:class="{
|
|
13
|
+
active: isTabSelected(tab, selectedTabId),
|
|
14
|
+
error: tab.error,
|
|
15
|
+
disabled: tab.disabled,
|
|
16
|
+
}"
|
|
17
|
+
@click="onClick(tab)"
|
|
18
|
+
>{{ tab.name }}</router-link
|
|
19
|
+
>
|
|
12
20
|
</template>
|
|
13
21
|
</UiTabs>
|
|
14
22
|
</template>
|
|
@@ -16,9 +24,13 @@
|
|
|
16
24
|
<script setup lang="ts">
|
|
17
25
|
import { Tab } from '@/models/tab.model';
|
|
18
26
|
import UiTabs from './UiTabs.vue';
|
|
19
|
-
import { computed,
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
27
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
|
28
|
+
import { useRouter } from 'vue-router';
|
|
29
|
+
import {
|
|
30
|
+
getTabId,
|
|
31
|
+
isTabSelected,
|
|
32
|
+
isTabSelectedByRoute,
|
|
33
|
+
} from '@/helpers/tab.helper';
|
|
22
34
|
|
|
23
35
|
const { currentRoute } = useRouter();
|
|
24
36
|
|
|
@@ -28,6 +40,8 @@ const props = defineProps<{
|
|
|
28
40
|
initialTabId?: string;
|
|
29
41
|
}>();
|
|
30
42
|
|
|
43
|
+
const selectedTabId = ref<string | null>(null);
|
|
44
|
+
|
|
31
45
|
const getTabTarget = (tab: Tab) => {
|
|
32
46
|
return tab.routePath ? { path: tab.routePath } : { name: tab.routeName };
|
|
33
47
|
};
|
|
@@ -44,23 +58,38 @@ const needRouterEngine = computed(() => {
|
|
|
44
58
|
);
|
|
45
59
|
});
|
|
46
60
|
|
|
47
|
-
const
|
|
61
|
+
const onClick = (tab: Tab) => {
|
|
62
|
+
selectedTabId.value = tab.id;
|
|
63
|
+
$emits('click', tab);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const computedTabs = computed(() => {
|
|
67
|
+
return props.tabs.map((tab) => {
|
|
68
|
+
return { ...tab, id: getTabId(tab) }; // retro compatibility for id
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const computedInitialTabId = () => {
|
|
48
73
|
if (needRouterEngine.value) {
|
|
49
74
|
const selectedTab =
|
|
50
|
-
props.tabs.find((t) =>
|
|
51
|
-
|
|
75
|
+
props.tabs.find((t) => isTabSelectedByRoute(t, currentRoute.value)) ||
|
|
76
|
+
null;
|
|
77
|
+
selectedTabId.value = selectedTab ? selectedTab.id : null;
|
|
52
78
|
} else if (props.initialTabId) {
|
|
53
|
-
|
|
79
|
+
selectedTabId.value = props.initialTabId;
|
|
54
80
|
} else {
|
|
55
|
-
|
|
81
|
+
selectedTabId.value = null;
|
|
56
82
|
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
onMounted(() => {
|
|
86
|
+
computedInitialTabId();
|
|
57
87
|
});
|
|
58
88
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
: false;
|
|
89
|
+
watch(
|
|
90
|
+
() => props.initialTabId,
|
|
91
|
+
() => {
|
|
92
|
+
computedInitialTabId();
|
|
93
|
+
},
|
|
94
|
+
);
|
|
66
95
|
</script>
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
<slot name="router" :tab="tab">
|
|
3
|
+
<span
|
|
4
|
+
data-testid="tab"
|
|
5
|
+
class="tab"
|
|
6
|
+
:class="{
|
|
7
|
+
active: isActive,
|
|
8
|
+
error: tab.error,
|
|
9
|
+
disabled: tab.disabled,
|
|
10
|
+
}"
|
|
11
|
+
@click="emits('click', $event)"
|
|
12
|
+
>
|
|
13
|
+
{{ tab.name }}
|
|
14
|
+
</span>
|
|
15
|
+
</slot>
|
|
9
16
|
</template>
|
|
10
17
|
|
|
11
18
|
<script lang="ts" setup>
|
|
12
19
|
import { Tab } from '@/models/tab.model';
|
|
13
20
|
import { computed, ComputedRef } from 'vue';
|
|
14
|
-
import {
|
|
21
|
+
import { isTabSelected } from '@/helpers/tab.helper';
|
|
15
22
|
|
|
16
23
|
const props = withDefaults(
|
|
17
24
|
defineProps<{
|
|
@@ -21,14 +28,16 @@ const props = withDefaults(
|
|
|
21
28
|
{},
|
|
22
29
|
);
|
|
23
30
|
|
|
24
|
-
const
|
|
31
|
+
const emits = defineEmits<{
|
|
32
|
+
(e: 'click', event: MouseEvent): void;
|
|
33
|
+
}>();
|
|
25
34
|
|
|
26
|
-
const
|
|
27
|
-
(
|
|
35
|
+
const isActive: ComputedRef<boolean> = computed(() =>
|
|
36
|
+
isTabSelected(props.tab, props.selectedTabId),
|
|
28
37
|
);
|
|
29
38
|
</script>
|
|
30
39
|
|
|
31
|
-
<style lang="scss"
|
|
40
|
+
<style lang="scss">
|
|
32
41
|
.tab {
|
|
33
42
|
--tab-border-color: transparent;
|
|
34
43
|
--tab-color: var(--bms-font-color);
|
|
@@ -38,10 +47,10 @@ const isTabSelected: ComputedRef<boolean> = computed(
|
|
|
38
47
|
border-bottom: 4px solid var(--tab-border-color);
|
|
39
48
|
padding: 0 8px 16px 8px;
|
|
40
49
|
cursor: pointer;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
50
|
+
//:deep(a) {
|
|
51
|
+
// color: var(--tab-color);
|
|
52
|
+
// text-decoration: none;
|
|
53
|
+
//}
|
|
45
54
|
&:hover,
|
|
46
55
|
&__hover {
|
|
47
56
|
--tab-border-color: var(--bms-main-50);
|
|
@@ -27,8 +27,12 @@ const Template = (args) => ({
|
|
|
27
27
|
`,
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
export const
|
|
31
|
-
|
|
30
|
+
export const Default = Template.bind({});
|
|
31
|
+
Default.args = {
|
|
32
32
|
title: 'Title',
|
|
33
|
-
tabs: [
|
|
33
|
+
tabs: [
|
|
34
|
+
{ name: 'Titi', id: 'titi' },
|
|
35
|
+
{ name: 'Toto', id: 'toto' },
|
|
36
|
+
],
|
|
37
|
+
selectedTabId: null,
|
|
34
38
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
</div>
|
|
6
6
|
<UiTab
|
|
7
7
|
v-for="tab in tabs"
|
|
8
|
-
:key="
|
|
8
|
+
:key="tab.id"
|
|
9
9
|
:selectedTabId="selectedTabId"
|
|
10
10
|
:tab="tab"
|
|
11
11
|
@click="onTabClick(tab)"
|
|
@@ -18,36 +18,20 @@
|
|
|
18
18
|
<script setup lang="ts">
|
|
19
19
|
import { Tab } from '@/models/tab.model';
|
|
20
20
|
import UiTab from './UiTab.vue';
|
|
21
|
-
import { computed, ComputedRef, onMounted, ref, watch } from 'vue';
|
|
22
|
-
import { getTabId } from '@/helpers/tab.helper';
|
|
23
21
|
|
|
24
22
|
const props = defineProps<{
|
|
25
23
|
title: string;
|
|
26
24
|
tabs: Tab[];
|
|
27
|
-
|
|
25
|
+
selectedTabId: string | null;
|
|
28
26
|
}>();
|
|
29
27
|
|
|
30
|
-
const selectedTabId = ref<string | null>(null);
|
|
31
|
-
|
|
32
|
-
onMounted(() => {
|
|
33
|
-
selectedTabId.value = props.initialTabId || null;
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
watch(
|
|
37
|
-
() => props.initialTabId,
|
|
38
|
-
() => {
|
|
39
|
-
selectedTabId.value = props.initialTabId || null;
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
|
|
43
28
|
const $emits = defineEmits<{
|
|
44
29
|
(e: 'click', value: any): void;
|
|
45
30
|
}>();
|
|
46
31
|
|
|
47
32
|
const onTabClick = (tab: Tab) => {
|
|
48
|
-
if (
|
|
33
|
+
if (tab.id !== props.selectedTabId) {
|
|
49
34
|
$emits('click', tab);
|
|
50
|
-
selectedTabId.value = getTabId(tab);
|
|
51
35
|
}
|
|
52
36
|
};
|
|
53
37
|
</script>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { isTabSelectedByRoute } from '@/helpers/tab.helper';
|
|
2
|
+
import { Tab } from '@/models/tab.model';
|
|
3
|
+
import { RouteLocation } from 'vue-router';
|
|
4
|
+
import { test } from 'vitest';
|
|
5
|
+
|
|
6
|
+
const createTab = (overrides: Partial<Tab> = {}): Tab => ({
|
|
7
|
+
id: 'tab-1',
|
|
8
|
+
name: 'Tab 1',
|
|
9
|
+
...overrides,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const createRoute = (overrides: Partial<RouteLocation> = {}): RouteLocation =>
|
|
13
|
+
({
|
|
14
|
+
path: '/default',
|
|
15
|
+
name: 'default',
|
|
16
|
+
...overrides,
|
|
17
|
+
}) as RouteLocation;
|
|
18
|
+
|
|
19
|
+
describe('tab.helper', () => {
|
|
20
|
+
describe('isTabSelectedByRoute', () => {
|
|
21
|
+
describe('with routePath', () => {
|
|
22
|
+
test.each([
|
|
23
|
+
['/users', '/users', true],
|
|
24
|
+
['/users', '/users/123', true],
|
|
25
|
+
['/users', '/admin', false],
|
|
26
|
+
['/users', '/admin/users', true],
|
|
27
|
+
])(
|
|
28
|
+
'tab with routePath "%s" and currentRoute.path "%s" should return %s',
|
|
29
|
+
(routePath, path, expected) => {
|
|
30
|
+
const tab = createTab({ routePath });
|
|
31
|
+
const route = createRoute({ path });
|
|
32
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(expected);
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('with routeName (no routePath)', () => {
|
|
38
|
+
test.each([
|
|
39
|
+
['users', 'users', true],
|
|
40
|
+
['users', 'users-list', true],
|
|
41
|
+
['users', 'admin', false],
|
|
42
|
+
['users', 'admin-users', true],
|
|
43
|
+
])(
|
|
44
|
+
'tab with routeName "%s" and currentRoute.name "%s" should return %s',
|
|
45
|
+
(routeName, name, expected) => {
|
|
46
|
+
const tab = createTab({ routeName });
|
|
47
|
+
const route = createRoute({ name });
|
|
48
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(expected);
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
test('should return false when currentRoute.name is undefined', () => {
|
|
53
|
+
const tab = createTab({ routeName: 'users' });
|
|
54
|
+
const route = createRoute({ name: undefined });
|
|
55
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('should return false when currentRoute.name is null', () => {
|
|
59
|
+
const tab = createTab({ routeName: 'users' });
|
|
60
|
+
const route = createRoute({ name: null as unknown as string });
|
|
61
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe('without routePath and routeName', () => {
|
|
66
|
+
test('should return false', () => {
|
|
67
|
+
const tab = createTab();
|
|
68
|
+
const route = createRoute({ path: '/users', name: 'users' });
|
|
69
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('routePath takes priority over routeName', () => {
|
|
74
|
+
test('should use routePath when both are defined', () => {
|
|
75
|
+
const tab = createTab({ routePath: '/admin', routeName: 'users' });
|
|
76
|
+
const route = createRoute({ path: '/admin', name: 'other' });
|
|
77
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('should not match routeName when routePath is defined but does not match', () => {
|
|
81
|
+
const tab = createTab({ routePath: '/admin', routeName: 'users' });
|
|
82
|
+
const route = createRoute({ path: '/other', name: 'users' });
|
|
83
|
+
expect(isTabSelectedByRoute(tab, route)).toBe(false);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
import { Tab } from '@/models';
|
|
2
|
+
import { sanitizeString } from '@/helpers/string.helper';
|
|
3
|
+
import { RouteLocation } from 'vue-router';
|
|
2
4
|
|
|
3
|
-
export const getTabId = (tab: Tab) => tab.id || tab.name;
|
|
5
|
+
export const getTabId = (tab: Tab) => tab.id || sanitizeString(tab.name);
|
|
6
|
+
|
|
7
|
+
export const isTabSelectedByRoute = (
|
|
8
|
+
tab: Tab,
|
|
9
|
+
currentRoute: RouteLocation,
|
|
10
|
+
): boolean =>
|
|
11
|
+
tab.routePath
|
|
12
|
+
? currentRoute.path.includes(tab.routePath)
|
|
13
|
+
: tab.routeName
|
|
14
|
+
? !!currentRoute.name &&
|
|
15
|
+
(currentRoute.name as string).includes(tab.routeName)
|
|
16
|
+
: false;
|
|
17
|
+
|
|
18
|
+
export const isTabSelected = (
|
|
19
|
+
tab: Tab,
|
|
20
|
+
selectedTabId: string | null,
|
|
21
|
+
): boolean => (tab && tab.id === selectedTabId) || false;
|
package/src/models/tab.model.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<br />
|
|
6
6
|
Valeur: {{ inputLabelValue }}
|
|
7
7
|
<BmsAutocomplete
|
|
8
|
+
ref="autocompleteElement"
|
|
8
9
|
label="Autocomplete avec label/value"
|
|
9
10
|
:options="optionsLabelValue"
|
|
10
11
|
v-model="inputLabelValue"
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
import { BmsAutocomplete, BmsBackButton } from '@/index';
|
|
61
62
|
import { Heart, Cat } from 'lucide-vue-next';
|
|
62
63
|
import { range } from 'lodash';
|
|
63
|
-
import { ref } from 'vue';
|
|
64
|
+
import { onMounted, ref, useTemplateRef } from 'vue';
|
|
64
65
|
import BmsButton from '@/components/button/BmsButton.vue';
|
|
65
66
|
import BmsSelect from '@/components/form/BmsSelect.vue';
|
|
66
67
|
import BmsMultiSelect from '@/components/form/BmsMultiSelect.vue';
|
|
@@ -69,6 +70,11 @@ import BmsServerAutocomplete from '@/components/form/BmsServerAutocomplete.vue';
|
|
|
69
70
|
const select = ref('');
|
|
70
71
|
const multiSelect = ref(null);
|
|
71
72
|
const multiSelectText = ref(null);
|
|
73
|
+
const autocompleteElement = useTemplateRef('autocompleteElement');
|
|
74
|
+
|
|
75
|
+
onMounted(() => {
|
|
76
|
+
(autocompleteElement.value as any)?.setFocus();
|
|
77
|
+
});
|
|
72
78
|
|
|
73
79
|
const optionsLabelValue = ref(
|
|
74
80
|
range(0, 30).map((i) =>
|