@cnamts/synapse 0.0.3-alpha → 0.0.4-alpha
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/design-system-v3.d.ts +712 -27
- package/dist/design-system-v3.js +2715 -1485
- package/dist/design-system-v3.umd.cjs +10 -1
- package/dist/style.css +1 -1
- package/package.json +5 -2
- package/src/components/Alert/Alert.mdx +1 -1
- package/src/components/Alert/Alert.stories.ts +91 -1
- package/src/components/BackBtn/BackBtn.mdx +1 -1
- package/src/components/BackBtn/BackBtn.stories.ts +84 -1
- package/src/components/BackToTopBtn/BackToTopBtn.mdx +3 -3
- package/src/components/BackToTopBtn/BackToTopBtn.stories.ts +172 -11
- package/src/components/CollapsibleList/CollapsibleList.mdx +2 -2
- package/src/components/CollapsibleList/CollapsibleList.stories.ts +37 -1
- package/src/components/CopyBtn/CopyBtn.mdx +1 -1
- package/src/components/CopyBtn/CopyBtn.stories.ts +120 -1
- package/src/components/CopyBtn/CopyBtn.vue +1 -1
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.mdx +6 -8
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.stories.ts +270 -4
- package/src/components/Customs/CustomInputSelect/CustomInputSelect.vue +80 -53
- package/src/components/Customs/CustomInputSelect/config.ts +10 -0
- package/src/components/Customs/CustomSelect/CustomSelect.mdx +3 -3
- package/src/components/Customs/CustomSelect/CustomSelect.stories.ts +158 -2
- package/src/components/Customs/CustomSelect/CustomSelect.vue +25 -6
- package/src/components/Customs/CustomTextField/CustomTextField.mdx +44 -0
- package/src/components/Customs/CustomTextField/CustomTextField.stories.ts +403 -0
- package/src/components/Customs/CustomTextField/CustomTextField.vue +110 -0
- package/src/components/Customs/CustomTextField/tests/CustomTextField.spec.ts +93 -0
- package/src/components/Customs/CustomTextField/tests/__snapshots__/CustomTextField.spec.ts.snap +59 -0
- package/src/components/Customs/CustomTextField/types.d.ts +3 -0
- package/src/components/DataList/DataList.mdx +77 -0
- package/src/components/DataList/DataList.stories.ts +960 -0
- package/src/components/DataList/DataList.vue +140 -0
- package/src/components/DataList/DataListLoading/DataListLoading.vue +56 -0
- package/src/components/DataList/DataListLoading/tests/DataListLoading.spec.ts +23 -0
- package/src/components/DataList/locales.ts +3 -0
- package/src/components/DataList/tests/DataList.spec.ts +194 -0
- package/src/components/DataList/types.d.ts +23 -0
- package/src/components/DataListGroup/DataListGroup.mdx +77 -0
- package/src/components/DataListGroup/DataListGroup.stories.ts +987 -0
- package/src/components/DataListGroup/DataListGroup.vue +59 -0
- package/src/components/DataListGroup/tests/DataListGroup.spec.ts +54 -0
- package/src/components/DataListGroup/tests/data/dataListGroupItems.ts +41 -0
- package/src/components/DataListGroup/types.d.ts +15 -0
- package/src/components/DataListItem/DataListItem.vue +135 -0
- package/src/components/DataListItem/config.ts +17 -0
- package/src/components/DataListItem/locales.ts +3 -0
- package/src/components/DataListItem/tests/DataListItem.spec.ts +156 -0
- package/src/components/DataListItem/types.d.ts +23 -0
- package/src/components/DownloadBtn/Accessibilite.mdx +14 -0
- package/src/components/DownloadBtn/Accessibilite.stories.ts +166 -0
- package/src/components/DownloadBtn/AccessibiliteItems.ts +129 -0
- package/src/components/DownloadBtn/DownloadBtn.mdx +5 -6
- package/src/components/DownloadBtn/DownloadBtn.stories.ts +207 -2
- package/src/components/DownloadBtn/constants/ExpertiseLevelEnum.ts +4 -0
- package/src/components/FooterBar/FooterBar.mdx +2 -2
- package/src/components/FooterBar/FooterBar.stories.ts +1 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.mdx +1 -1
- package/src/components/FranceConnectBtn/FranceConnectBtn.stories.ts +58 -1
- package/src/components/HeaderBar/HeaderBar.mdx +164 -45
- package/src/components/HeaderBar/HeaderBar.stories.ts +559 -15
- package/src/components/HeaderBar/HeaderBar.vue +60 -22
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.mdx +433 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderBurgerMenu.stories.ts +1089 -0
- package/src/components/HeaderBar/{HeaderComplexMenu/HeaderComplexMenu.vue → HeaderBurgerMenu/HeaderBurgerMenu.vue} +74 -45
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.mdx +38 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuItem/HeaderMenuItem.stories.ts +89 -0
- package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderMenuItem/tests/__snapshots__/HeaderMenuItem.spec.ts.snap +1 -1
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.mdx +17 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderMenuSection/HeaderMenuSection.stories.ts +121 -0
- package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderMenuSection/HeaderMenuSection.vue +2 -2
- package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderMenuSection/tests/HeaderMenuSection.spec.ts +1 -3
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.mdx +43 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/HeaderSubMenu/HeaderSubMenu.stories.ts +261 -0
- package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderSubMenu/HeaderSubMenu.vue +17 -3
- package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderSubMenu/tests/HeaderSubMenu.spec.ts +1 -1
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/HeaderBurgerMenu.spec.ts +180 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderBurgerMenu.spec.ts.snap +13 -0
- package/src/components/HeaderBar/HeaderBurgerMenu/tests/__snapshots__/HeaderComplexMenu.spec.ts.snap +13 -0
- package/src/components/HeaderBar/HeaderLogo/HeaderLogo.vue +62 -25
- package/src/components/HeaderBar/HeaderLogo/tests/HeaderLogo.spec.ts +49 -1
- package/src/components/HeaderBar/HeaderMenuBtn/HeaderMenuBtn.vue +19 -23
- package/src/components/HeaderBar/HeaderMenuBtn/tests/HeaderMenuBtn.spec.ts +70 -0
- package/src/components/HeaderBar/Usages.mdx +85 -0
- package/src/components/HeaderBar/consts.scss +0 -1
- package/src/components/HeaderBar/tests/HeaderBar.spec.ts +8 -2
- package/src/components/HeaderBar/tests/__snapshots__/HeaderBar.spec.ts.snap +5 -10
- package/src/components/HeaderLoading/HeaderLoading.mdx +28 -0
- package/src/components/HeaderLoading/HeaderLoading.stories.ts +62 -0
- package/src/components/HeaderLoading/HeaderLoading.vue +45 -0
- package/src/components/HeaderLoading/tests/HeaderLoading.spec.ts +22 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.mdx +128 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.stories.ts +784 -0
- package/src/components/HeaderNavigationBar/HeaderNavigationBar.vue +194 -0
- package/src/components/HeaderNavigationBar/HorizontalNavbar/HorizontalNavbar.vue +74 -0
- package/src/components/HeaderNavigationBar/HorizontalNavbar/config.ts +18 -0
- package/src/components/HeaderNavigationBar/tests/HeaderNavigationBar.spec.ts +127 -0
- package/src/components/HeaderNavigationBar/types.ts +7 -0
- package/src/components/HeaderToolbar/HeaderToolbar.mdx +31 -0
- package/src/components/HeaderToolbar/HeaderToolbar.stories.ts +343 -0
- package/src/components/HeaderToolbar/HeaderToolbar.vue +487 -0
- package/src/components/HeaderToolbar/tests/HeaderToolbar.spec.ts +196 -0
- package/src/components/HeaderToolbar/types.d.ts +20 -0
- package/src/components/LangBtn/LangBtn.mdx +1 -1
- package/src/components/LangBtn/LangBtn.stories.ts +125 -8
- package/src/components/Logo/Logo.mdx +2 -2
- package/src/components/Logo/Logo.stories.ts +147 -1
- package/src/components/LogoBrandSection/LogoBrandSection.mdx +14 -0
- package/src/components/LogoBrandSection/LogoBrandSection.stories.ts +158 -0
- package/src/components/LogoBrandSection/LogoBrandSection.vue +312 -0
- package/src/components/LogoBrandSection/assets/ameli-pro.svg +1 -0
- package/src/components/LogoBrandSection/assets/ameli.svg +1 -0
- package/src/components/LogoBrandSection/assets/cnam.svg +1 -0
- package/src/components/LogoBrandSection/assets/compte-ameli.svg +1 -0
- package/src/components/LogoBrandSection/dividerDimensionsMapping.ts +14 -0
- package/src/components/LogoBrandSection/locales.ts +14 -0
- package/src/components/LogoBrandSection/secondaryLogoMapping.ts +24 -0
- package/src/components/LogoBrandSection/tests/LogoBrandSection.spec.ts +365 -0
- package/src/components/LogoBrandSection/tests/__snapshots__/LogoBrandSection.spec.ts.snap +14 -0
- package/src/components/LogoBrandSection/types.ts +8 -0
- package/src/components/NotificationBar/NotificationBar.mdx +6 -6
- package/src/components/NotificationBar/NotificationBar.stories.ts +1 -1
- package/src/components/NotificationBar/NotificationBar.vue +2 -2
- package/src/components/NotificationBar/tests/NotificationBar.spec.ts +1 -1
- package/src/components/PageContainer/PageContainer.mdx +1 -1
- package/src/components/PageContainer/PageContainer.stories.ts +86 -1
- package/src/components/PhoneField/PhoneField.mdx +49 -0
- package/src/components/PhoneField/PhoneField.stories.ts +869 -0
- package/src/components/PhoneField/PhoneField.vue +230 -0
- package/src/components/PhoneField/indicatifs.ts +104 -0
- package/src/components/PhoneField/locales.ts +4 -0
- package/src/components/PhoneField/tests/PhoneField.spec.ts +179 -0
- package/src/components/SkipLink/SkipLink.stories.ts +50 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.mdx +28 -1
- package/src/components/SocialMediaLinks/SocialMediaLinks.stories.ts +37 -1
- package/src/components/SubHeader/SubHeader.mdx +31 -0
- package/src/components/SubHeader/SubHeader.stories.ts +1032 -0
- package/src/components/SubHeader/SubHeader.vue +185 -0
- package/src/components/SubHeader/config.ts +12 -0
- package/src/components/SubHeader/locales.ts +3 -0
- package/src/components/SubHeader/tests/SubHeader.spec.ts +144 -0
- package/src/components/index.ts +24 -7
- package/src/composables/widthable/index.ts +29 -0
- package/src/composables/widthable/tests/widthable.spec.ts +52 -0
- package/src/designTokens/tokens/cnam/cnamLightTheme.ts +2 -2
- package/src/main.ts +1 -0
- package/src/modules.d.ts +4 -0
- package/src/services/index.ts +1 -0
- package/src/stories/Demarrer/Accueil.mdx +10 -0
- package/src/stories/Demarrer/Accueil.stories.ts +76 -0
- package/src/stories/Demarrer/PolitiqueDeConfidentialite.mdx +9 -0
- package/src/stories/Demarrer/PolitiqueDeConfidentialite.stories.ts +20 -0
- package/src/stories/Fondamentaux/Accessibilite/Accessibilite.mdx +1 -2
- package/src/stories/Fondamentaux/Accessibilite/Accessibilite.stories.ts +1 -1
- package/src/stories/Fondamentaux/EcoConception/Econception.stories.ts +1 -1
- package/src/stories/GuideDuDev/moduleDeNotification.mdx +52 -48
- package/src/stories/GuideDuDev/vuetifyOptions.mdx +31 -28
- package/src/stories/Guidelines/CustomisationEtThemes.mdx +1 -1
- package/src/utils/functions/throttleDisplayFn/tests/throttleDisplayFn.spec.ts +47 -0
- package/src/utils/functions/throttleDisplayFn/throttleDisplayFn.ts +26 -0
- package/src/utils/rules/exactLength/index.ts +33 -0
- package/src/utils/rules/exactLength/locales.ts +6 -0
- package/src/utils/rules/required/index.ts +25 -0
- package/src/utils/rules/required/locales.ts +5 -0
- package/src/utils/rules/required/ruleMessageHelper.ts +14 -0
- package/src/utils/rules/required/tests/index.spec.ts +47 -0
- package/src/utils/rules/required/tests/rulesMessageHelper.spec.ts +22 -0
- package/src/utils/rules/types.d.ts +15 -0
- package/src/components/Beta/beta.mdx +0 -5
- package/src/components/Deprecated/deprecated.mdx +0 -5
- package/src/components/HeaderBar/HeaderComplexMenu/HeaderComplexMenu.stories.ts +0 -272
- package/src/components/HeaderBar/HeaderComplexMenu/HeaderMenuItem/HeaderMenuItem.stories.ts +0 -49
- package/src/components/HeaderBar/HeaderComplexMenu/HeaderMenuSection/HeaderMenuSection.stories.ts +0 -56
- package/src/components/HeaderBar/HeaderComplexMenu/HeaderSubMenu/HeaderSubMenu.stories.ts +0 -137
- package/src/components/HeaderBar/HeaderComplexMenu/tests/HeaderComplexMenu.spec.ts +0 -129
- package/src/components/HeaderBar/HeaderComplexMenu/tests/__snapshots__/HeaderComplexMenu.spec.ts.snap +0 -18
- package/src/stories/Home/Accueil.mdx +0 -7
- package/src/stories/Home/PolitiqueDeConfidentialite.mdx +0 -4
- package/src/stories/Home/synapse.webp +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderMenuItem/HeaderMenuItem.vue +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/HeaderMenuItem/tests/HeaderMenuItem.spec.ts +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/conts.ts +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/locals.ts +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/tests/useHandleSubMenus.spec.ts +0 -0
- /package/src/components/HeaderBar/{HeaderComplexMenu → HeaderBurgerMenu}/useHandleSubMenus.ts +0 -0
- /package/src/components/Logo/{types.d.ts → types.ts} +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { PropType } from 'vue'
|
|
3
|
+
import type { DataListIcons } from '../DataList/types'
|
|
4
|
+
import type { DataListGroupItems, DataListActionEvent } from './types'
|
|
5
|
+
import DataList from '../DataList/DataList.vue'
|
|
6
|
+
|
|
7
|
+
const props = defineProps({
|
|
8
|
+
items: {
|
|
9
|
+
type: Array as PropType<DataListGroupItems>,
|
|
10
|
+
required: true,
|
|
11
|
+
},
|
|
12
|
+
icons: {
|
|
13
|
+
type: Object as PropType<DataListIcons | undefined>,
|
|
14
|
+
default: undefined,
|
|
15
|
+
},
|
|
16
|
+
itemWidth: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: '200px',
|
|
19
|
+
},
|
|
20
|
+
loading: {
|
|
21
|
+
type: Boolean,
|
|
22
|
+
default: false,
|
|
23
|
+
},
|
|
24
|
+
renderHtmlValue: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const emit = defineEmits(['click:list-item'])
|
|
31
|
+
|
|
32
|
+
const emitItemAction = (dataListIndex: number, itemIndex: number): void => {
|
|
33
|
+
const eventValue: DataListActionEvent = {
|
|
34
|
+
dataListIndex,
|
|
35
|
+
itemIndex,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
emit('click:list-item', eventValue)
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<div class="vd-data-list-group d-flex flex-wrap max-width-none ma-n4">
|
|
44
|
+
<DataList
|
|
45
|
+
v-for="(dataList, index) in props.items"
|
|
46
|
+
:key="`vd-data-list-${index}`"
|
|
47
|
+
:loading="props.loading"
|
|
48
|
+
:render-html-value="props.renderHtmlValue"
|
|
49
|
+
:list-title="dataList.title"
|
|
50
|
+
:items="dataList.items"
|
|
51
|
+
:items-number-loading="dataList.itemsNumberLoading"
|
|
52
|
+
:heading-loading="dataList.headingLoading"
|
|
53
|
+
:width="props.itemWidth"
|
|
54
|
+
:icons="props.icons"
|
|
55
|
+
class="ma-4"
|
|
56
|
+
@click:item-action="emitItemAction(index, $event)"
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
|
|
4
|
+
import DataListGroup from '../DataListGroup.vue'
|
|
5
|
+
|
|
6
|
+
import { dataListGroupItems } from './data/dataListGroupItems'
|
|
7
|
+
import { vuetify } from '@tests/unit/setup'
|
|
8
|
+
|
|
9
|
+
describe('DataListGroup', () => {
|
|
10
|
+
it('renders correctly', () => {
|
|
11
|
+
const wrapper = mount(DataListGroup, {
|
|
12
|
+
props: {
|
|
13
|
+
items: dataListGroupItems,
|
|
14
|
+
},
|
|
15
|
+
global: {
|
|
16
|
+
plugins: [vuetify],
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
expect(wrapper.find('h4').text()).toBe('Catégorie 1')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('renders loading state correctly', async () => {
|
|
24
|
+
const wrapper = mount(DataListGroup, {
|
|
25
|
+
props: {
|
|
26
|
+
loading: true,
|
|
27
|
+
items: dataListGroupItems,
|
|
28
|
+
},
|
|
29
|
+
global: {
|
|
30
|
+
plugins: [vuetify],
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
expect(wrapper.find('.vd-data-list-loading').exists()).toBe(true)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('emit the right event when clicking on a item button', async () => {
|
|
38
|
+
const wrapper = mount(DataListGroup, {
|
|
39
|
+
props: {
|
|
40
|
+
items: dataListGroupItems,
|
|
41
|
+
},
|
|
42
|
+
global: {
|
|
43
|
+
plugins: [vuetify],
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const button = wrapper.find('button')
|
|
48
|
+
await button.trigger('click')
|
|
49
|
+
|
|
50
|
+
expect(wrapper.emitted('click:list-item')).toEqual([
|
|
51
|
+
[{ dataListIndex: 1, itemIndex: 0 }],
|
|
52
|
+
])
|
|
53
|
+
})
|
|
54
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { DataList } from '../../../DataList/types'
|
|
2
|
+
import type { DataListGroupItems } from '../../types'
|
|
3
|
+
|
|
4
|
+
export const dataListItems: DataList = [
|
|
5
|
+
{
|
|
6
|
+
key: 'Libellé',
|
|
7
|
+
value: 'Texte saisi',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
key: 'Libellé',
|
|
11
|
+
value: 'Texte saisi',
|
|
12
|
+
},
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
export const dataListItemsActions: DataList = [
|
|
16
|
+
{
|
|
17
|
+
key: 'Libellé',
|
|
18
|
+
value: 'Texte à modifier',
|
|
19
|
+
action: 'Modifier',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: 'Libellé',
|
|
23
|
+
value: 'Texte à modifier',
|
|
24
|
+
action: 'Modifier',
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
export const dataListGroupItems: DataListGroupItems = [
|
|
29
|
+
{
|
|
30
|
+
title: 'Catégorie 1',
|
|
31
|
+
items: dataListItems,
|
|
32
|
+
itemsNumberLoading: 2,
|
|
33
|
+
headingLoading: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: 'Catégorie 2',
|
|
37
|
+
items: dataListItemsActions,
|
|
38
|
+
itemsNumberLoading: 2,
|
|
39
|
+
headingLoading: true,
|
|
40
|
+
},
|
|
41
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DataList } from '../DataList/types'
|
|
2
|
+
|
|
3
|
+
export interface DataListActionEvent {
|
|
4
|
+
dataListIndex: number
|
|
5
|
+
itemIndex: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface DataListGroupItem {
|
|
9
|
+
title?: string
|
|
10
|
+
items: DataList
|
|
11
|
+
headingLoading?: boolean
|
|
12
|
+
itemsNumberLoading?: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type DataListGroupItems = DataListGroupItem[]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { useTheme } from 'vuetify'
|
|
4
|
+
|
|
5
|
+
import useCustomizableOptions, { type CustomizableOptions } from '@/composables/useCustomizableOptions'
|
|
6
|
+
|
|
7
|
+
import { config } from './config'
|
|
8
|
+
import { locales } from './locales'
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<CustomizableOptions & {
|
|
11
|
+
label: string
|
|
12
|
+
value?: string | number
|
|
13
|
+
action?: string
|
|
14
|
+
placeholder?: string
|
|
15
|
+
chip?: boolean
|
|
16
|
+
icon?: string
|
|
17
|
+
row?: boolean
|
|
18
|
+
renderHtmlValue?: boolean
|
|
19
|
+
}>(), {
|
|
20
|
+
label: '',
|
|
21
|
+
value: undefined,
|
|
22
|
+
action: undefined,
|
|
23
|
+
placeholder: locales.placeholder,
|
|
24
|
+
chip: false,
|
|
25
|
+
icon: undefined,
|
|
26
|
+
row: false,
|
|
27
|
+
renderHtmlValue: false,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const emits = defineEmits(['click:action'])
|
|
31
|
+
|
|
32
|
+
const options = useCustomizableOptions(config, props)
|
|
33
|
+
const theme = useTheme()
|
|
34
|
+
|
|
35
|
+
const labelColor = computed(() => {
|
|
36
|
+
return theme.current.value.dark
|
|
37
|
+
? 'rgba(255, 255, 255, .7)'
|
|
38
|
+
: 'rgba(0, 0, 0, .6)'
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const itemValue = computed(() => {
|
|
42
|
+
if (typeof props.value === 'number') {
|
|
43
|
+
return isNaN(props.value)
|
|
44
|
+
? props.placeholder
|
|
45
|
+
: props.value.toString()
|
|
46
|
+
}
|
|
47
|
+
return props.value || props.placeholder
|
|
48
|
+
})
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<template>
|
|
52
|
+
<li class="vd-data-list-item d-flex flex-wrap">
|
|
53
|
+
<slot name="icon">
|
|
54
|
+
<VIcon
|
|
55
|
+
v-if="icon"
|
|
56
|
+
v-bind="options.icon"
|
|
57
|
+
>
|
|
58
|
+
{{ icon }}
|
|
59
|
+
</VIcon>
|
|
60
|
+
</slot>
|
|
61
|
+
|
|
62
|
+
<div class="vd-data-list-item-content">
|
|
63
|
+
<div :class="{ 'vd-row': row }">
|
|
64
|
+
<div
|
|
65
|
+
class="vd-data-list-item-label text-caption"
|
|
66
|
+
:style="{ color: labelColor }"
|
|
67
|
+
>
|
|
68
|
+
{{ label }}
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="vd-data-list-item-value">
|
|
72
|
+
<slot
|
|
73
|
+
name="value"
|
|
74
|
+
v-bind="{ itemValue }"
|
|
75
|
+
>
|
|
76
|
+
<VChip
|
|
77
|
+
v-if="chip"
|
|
78
|
+
v-bind="options.chip"
|
|
79
|
+
>
|
|
80
|
+
{{ itemValue }}
|
|
81
|
+
</VChip>
|
|
82
|
+
|
|
83
|
+
<span
|
|
84
|
+
v-else-if="renderHtmlValue"
|
|
85
|
+
class="text-body-1"
|
|
86
|
+
v-html="itemValue"
|
|
87
|
+
/>
|
|
88
|
+
|
|
89
|
+
<span
|
|
90
|
+
v-else
|
|
91
|
+
class="text-body-1"
|
|
92
|
+
v-text="itemValue"
|
|
93
|
+
/>
|
|
94
|
+
</slot>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<slot name="action">
|
|
99
|
+
<VBtn
|
|
100
|
+
v-if="action"
|
|
101
|
+
v-bind="options.actionBtn"
|
|
102
|
+
class="vd-data-list-item-action-btn"
|
|
103
|
+
@click="emits('click:action')"
|
|
104
|
+
>
|
|
105
|
+
{{ action }}
|
|
106
|
+
</VBtn>
|
|
107
|
+
</slot>
|
|
108
|
+
</div>
|
|
109
|
+
</li>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<style lang="scss" scoped>
|
|
113
|
+
.vd-row {
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-wrap: wrap;
|
|
116
|
+
|
|
117
|
+
.vd-data-list-item-label {
|
|
118
|
+
align-self: center;
|
|
119
|
+
|
|
120
|
+
&::after {
|
|
121
|
+
content: ':';
|
|
122
|
+
margin: 0 4px;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.vd-data-list-item-action-btn.v-btn {
|
|
128
|
+
min-width: 0;
|
|
129
|
+
margin: 0 -1px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.v-icon.v-theme--light {
|
|
133
|
+
color: rgba(0, 0, 0, 0.54);
|
|
134
|
+
}
|
|
135
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { VariantType } from '@/types/vuetifyTypes'
|
|
2
|
+
|
|
3
|
+
export const config = {
|
|
4
|
+
icon: {
|
|
5
|
+
size: 24,
|
|
6
|
+
class: 'mr-4 mt-2',
|
|
7
|
+
},
|
|
8
|
+
chip: {
|
|
9
|
+
class: 'mt-1',
|
|
10
|
+
},
|
|
11
|
+
actionBtn: {
|
|
12
|
+
variant: 'text' as VariantType,
|
|
13
|
+
size: 'small',
|
|
14
|
+
color: 'secondary',
|
|
15
|
+
class: 'text-body-1 pa-0',
|
|
16
|
+
},
|
|
17
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
|
2
|
+
import { describe, it, expect } from 'vitest'
|
|
3
|
+
import { vuetify } from '@tests/unit/setup'
|
|
4
|
+
|
|
5
|
+
import DataListItem from '../DataListItem.vue'
|
|
6
|
+
|
|
7
|
+
describe('DataListItem', () => {
|
|
8
|
+
it('renders correctly', () => {
|
|
9
|
+
const wrapper = mount(DataListItem, {
|
|
10
|
+
global: {
|
|
11
|
+
plugins: [vuetify],
|
|
12
|
+
},
|
|
13
|
+
props: {
|
|
14
|
+
label: 'Test',
|
|
15
|
+
value: 'Sample Value',
|
|
16
|
+
action: 'Click Me',
|
|
17
|
+
chip: false,
|
|
18
|
+
row: true,
|
|
19
|
+
},
|
|
20
|
+
slots: {
|
|
21
|
+
icon: '<VIcon>mdi-home</VIcon>',
|
|
22
|
+
value: '<span>Custom Value</span>',
|
|
23
|
+
action: '<VBtn>Custom Action</VBtn>',
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
expect(wrapper.vm.value).toBe('Sample Value')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('renders correctly with a number value', () => {
|
|
31
|
+
const wrapper = mount(DataListItem, {
|
|
32
|
+
global: {
|
|
33
|
+
plugins: [vuetify],
|
|
34
|
+
},
|
|
35
|
+
props: {
|
|
36
|
+
label: 'Test',
|
|
37
|
+
value: 123,
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
expect(wrapper.vm.value).toBe(123)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('renders correctly with a NaN value', () => {
|
|
45
|
+
const wrapper = mount(DataListItem, {
|
|
46
|
+
global: {
|
|
47
|
+
plugins: [vuetify],
|
|
48
|
+
},
|
|
49
|
+
props: {
|
|
50
|
+
label: 'Test',
|
|
51
|
+
value: parseInt('test', 10),
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
expect(wrapper.vm.value).toBe(NaN)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('renders correctly a value with HTML as text', () => {
|
|
59
|
+
const wrapper = mount(DataListItem, {
|
|
60
|
+
global: {
|
|
61
|
+
plugins: [vuetify],
|
|
62
|
+
},
|
|
63
|
+
props: {
|
|
64
|
+
label: 'Test',
|
|
65
|
+
value: '<span>Custom Value</span>',
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const elValue = wrapper.find('.vd-data-list-item-value span')
|
|
70
|
+
|
|
71
|
+
expect(elValue.text()).toBe('<span>Custom Value</span>')
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('renders correctly a value as plain HTML', () => {
|
|
75
|
+
const wrapper = mount(DataListItem, {
|
|
76
|
+
global: {
|
|
77
|
+
plugins: [vuetify],
|
|
78
|
+
},
|
|
79
|
+
props: {
|
|
80
|
+
label: 'Test',
|
|
81
|
+
value: 'Paul<br> Dupont',
|
|
82
|
+
renderHtmlValue: true,
|
|
83
|
+
},
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const elValue = wrapper.find('.vd-data-list-item-value span')
|
|
87
|
+
|
|
88
|
+
expect(elValue.text()).toBe('Paul Dupont')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('renders correctly value in a chip', () => {
|
|
92
|
+
const wrapper = mount(DataListItem, {
|
|
93
|
+
global: {
|
|
94
|
+
plugins: [vuetify],
|
|
95
|
+
},
|
|
96
|
+
props: {
|
|
97
|
+
label: 'Test',
|
|
98
|
+
value: 'Chip Value',
|
|
99
|
+
chip: true,
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
const elChip = wrapper.find('.v-chip__content')
|
|
104
|
+
expect(elChip.text()).toBe('Chip Value')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('renders correctly with an action', () => {
|
|
108
|
+
const wrapper = mount(DataListItem, {
|
|
109
|
+
global: {
|
|
110
|
+
plugins: [vuetify],
|
|
111
|
+
},
|
|
112
|
+
props: {
|
|
113
|
+
label: 'Test',
|
|
114
|
+
action: 'Click Me',
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const elAction = wrapper.find('.vd-data-list-item-action-btn')
|
|
119
|
+
expect(elAction.text()).toBe('Click Me')
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('emits click:action event on button click', async () => {
|
|
123
|
+
const wrapper = mount(DataListItem, {
|
|
124
|
+
global: {
|
|
125
|
+
plugins: [vuetify],
|
|
126
|
+
},
|
|
127
|
+
props: {
|
|
128
|
+
label: 'Test',
|
|
129
|
+
action: 'Click Me',
|
|
130
|
+
},
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const button = wrapper.find('.vd-data-list-item-action-btn')
|
|
134
|
+
await button.trigger('click')
|
|
135
|
+
|
|
136
|
+
expect(wrapper.emitted('click:action')).toBeTruthy()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('renders correctly in row mode', () => {
|
|
140
|
+
const wrapper = mount(DataListItem, {
|
|
141
|
+
global: {
|
|
142
|
+
plugins: [vuetify],
|
|
143
|
+
},
|
|
144
|
+
props: {
|
|
145
|
+
label: 'Test',
|
|
146
|
+
value: 'Sample Value',
|
|
147
|
+
action: 'Click Me',
|
|
148
|
+
chip: false,
|
|
149
|
+
row: true,
|
|
150
|
+
},
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const elRow = wrapper.find('.vd-row')
|
|
154
|
+
expect(elRow.exists()).toBe(true)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useCustomizableOptions } from '@/composables/useCustomizableOptions'
|
|
2
|
+
|
|
3
|
+
export interface IndexedObject<Type = string> {
|
|
4
|
+
[key: string]: Type
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface DataListItem {
|
|
8
|
+
key: string
|
|
9
|
+
value?: string | number
|
|
10
|
+
action?: string
|
|
11
|
+
chip?: boolean
|
|
12
|
+
icon?: string
|
|
13
|
+
options?: useCustomizableOptions
|
|
14
|
+
class?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type DataList = DataListItem[]
|
|
18
|
+
|
|
19
|
+
export interface DataListIcons {
|
|
20
|
+
[iconName: string]: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type ItemClass = (string | undefined | IndexedObject<boolean>)[]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Meta, Story } from '@storybook/addon-docs';
|
|
2
|
+
import * as AccessStories from './Accessibilite.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={AccessStories} />
|
|
5
|
+
|
|
6
|
+
Accessibilité
|
|
7
|
+
=============
|
|
8
|
+
<Story of={AccessStories.Legende} />
|
|
9
|
+
<br />
|
|
10
|
+
|
|
11
|
+
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
<Story of={AccessStories.AccessibilitePanel} />
|
|
14
|
+
<br />
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VExpansionPanelText, VDataTable, VIcon } from 'vuetify/components'
|
|
2
|
+
import type { StoryObj } from '@storybook/vue3'
|
|
3
|
+
import { AccessibiliteItemsIndeterminate, AccessibiliteItemsValidated } from './AccessibiliteItems'
|
|
4
|
+
import { mdiCheckboxMarkedCircle, mdiLink, mdiEye } from '@mdi/js'
|
|
5
|
+
|
|
6
|
+
const checkIcon = mdiCheckboxMarkedCircle
|
|
7
|
+
const iconEye = mdiEye
|
|
8
|
+
const linkICon = mdiLink
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
title: 'Composants/Boutons/DownloadBtn/Accessibilité',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const AccessibilitePanel: StoryObj = {
|
|
15
|
+
|
|
16
|
+
render: () => {
|
|
17
|
+
return {
|
|
18
|
+
components: { VExpansionPanels, VExpansionPanel, VExpansionPanelTitle, VExpansionPanelText, VDataTable, VIcon },
|
|
19
|
+
|
|
20
|
+
setup() {
|
|
21
|
+
const icon = checkIcon
|
|
22
|
+
|
|
23
|
+
return { AccessibiliteItemsIndeterminate, AccessibiliteItemsValidated, icon, linkICon, iconEye }
|
|
24
|
+
},
|
|
25
|
+
template: `
|
|
26
|
+
<div class="accessibiliteItems" style="display:flex; max-width: none !important;">
|
|
27
|
+
<v-col cols="6">
|
|
28
|
+
<div style="display:flex; margin-bottom: 10px; justify-content: space-between; align-items: center;">
|
|
29
|
+
<h5>{{ AccessibiliteItemsIndeterminate.length }} critères à prendre en charge par le projet</h5>
|
|
30
|
+
<div style="display: flex; align-items: center;">
|
|
31
|
+
<v-btn variant="tonal" color="red" size="x-small" style="margin: 4px;font-size: 8px;"
|
|
32
|
+
rounded>Tanaguru
|
|
33
|
+
</v-btn>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<v-expansion-panels value="opened" multiple>
|
|
38
|
+
<v-expansion-panel v-for="(item, index) in AccessibiliteItemsIndeterminate" :key="index" style="background-color: rgba(42, 96, 158, 0.1); margin-bottom: 10px;">
|
|
39
|
+
<v-expansion-panel-title>
|
|
40
|
+
<VIcon :icon="iconEye" style="margin-right: 5px; color:#5778b7;"/>
|
|
41
|
+
{{ item.title }}
|
|
42
|
+
</v-expansion-panel-title>
|
|
43
|
+
<v-expansion-panel-text>
|
|
44
|
+
<v-expansion-panels>
|
|
45
|
+
<v-expansion-panel>
|
|
46
|
+
<v-expansion-panel-title
|
|
47
|
+
style="font-weight: bold; font-size: 13px; line-height: 16px;">
|
|
48
|
+
{{ item.subtitle }}
|
|
49
|
+
</v-expansion-panel-title>
|
|
50
|
+
<v-expansion-panel-text>
|
|
51
|
+
<div v-for="(value, i) in item.items" :key="i">
|
|
52
|
+
<p style="font-size: 13px;line-height: 16px;">
|
|
53
|
+
{{ value.precision }}
|
|
54
|
+
</p>
|
|
55
|
+
<div v-for="element in value.solution"
|
|
56
|
+
style="margin-top:15px; font-size: 13px;line-height: 16px;">
|
|
57
|
+
<p style="font-weight: bold;">Méthodologie du test : <a
|
|
58
|
+
href="value.link" target="blank">
|
|
59
|
+
<VIcon :icon="linkICon"/>
|
|
60
|
+
</a></p>
|
|
61
|
+
|
|
62
|
+
<p>{{ element.info1 }}</p>
|
|
63
|
+
<p>{{ element.info2 }}</p>
|
|
64
|
+
<p>{{ element.info3 }}</p>
|
|
65
|
+
|
|
66
|
+
</div>
|
|
67
|
+
<span style="display:flex; justify-content:center; margin-bottom:5px;">______</span>
|
|
68
|
+
</div>
|
|
69
|
+
</v-expansion-panel-text>
|
|
70
|
+
</v-expansion-panel>
|
|
71
|
+
</v-expansion-panels>
|
|
72
|
+
</v-expansion-panel-text>
|
|
73
|
+
</v-expansion-panel>
|
|
74
|
+
</v-expansion-panels>
|
|
75
|
+
</v-col>
|
|
76
|
+
<v-col cols="6">
|
|
77
|
+
<div style="display:flex; margin-bottom: 10px; justify-content: space-between; align-items: center;">
|
|
78
|
+
<h5>{{ AccessibiliteItemsValidated.length }} critères pris en charge par l'équipe Design System</h5>
|
|
79
|
+
<div style="display: flex; align-items: center;">
|
|
80
|
+
<v-btn variant="tonal" color="red" size="x-small" style="margin: 4px;font-size: 8px;"
|
|
81
|
+
rounded>Tanaguru
|
|
82
|
+
</v-btn>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<v-expansion-panels value="opened" multiple>
|
|
86
|
+
<v-expansion-panel
|
|
87
|
+
v-for="(item, index) in AccessibiliteItemsValidated"
|
|
88
|
+
:key="index" style="background-color: rgba(53,135,0,0.1); margin-bottom: 10px;">
|
|
89
|
+
<v-expansion-panel-title>
|
|
90
|
+
<VIcon color="green" :icon="icon" style="margin-right: 5px;"/>
|
|
91
|
+
{{ item.title }}
|
|
92
|
+
</v-expansion-panel-title>
|
|
93
|
+
<v-expansion-panel-text>
|
|
94
|
+
<v-expansion-panels>
|
|
95
|
+
<v-expansion-panel>
|
|
96
|
+
<v-expansion-panel-title style="font-weight: bold;font-size: 13px; line-height: 16px;">
|
|
97
|
+
{{ item.subtitle }}
|
|
98
|
+
</v-expansion-panel-title>
|
|
99
|
+
<v-expansion-panel-text>
|
|
100
|
+
<div v-for="(value, i) in item.items" :key="i">
|
|
101
|
+
<p style="font-size: 13px;line-height: 16px;">
|
|
102
|
+
{{ value.precision }}
|
|
103
|
+
</p>
|
|
104
|
+
<div v-for="element in value.solution"
|
|
105
|
+
style="margin-top:15px; font-size: 13px;line-height: 16px;">
|
|
106
|
+
<p style="font-weight: bold;">Méthodologie du test : <a
|
|
107
|
+
href="value.link" target="blank">
|
|
108
|
+
<VIcon :icon="linkICon"/>
|
|
109
|
+
</a></p>
|
|
110
|
+
<p>{{ element.info1 }}</p>
|
|
111
|
+
<p>{{ element.info2 }}</p>
|
|
112
|
+
<p>{{ element.info3 }}</p>
|
|
113
|
+
</div>
|
|
114
|
+
<span style="display:flex; justify-content:center; margin-bottom:5px;">______</span>
|
|
115
|
+
</div>
|
|
116
|
+
</v-expansion-panel-text>
|
|
117
|
+
</v-expansion-panel>
|
|
118
|
+
</v-expansion-panels>
|
|
119
|
+
</v-expansion-panel-text>
|
|
120
|
+
</v-expansion-panel>
|
|
121
|
+
</v-expansion-panels>
|
|
122
|
+
</v-col>
|
|
123
|
+
</div>
|
|
124
|
+
`,
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
tags: ['!dev'],
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export const Legende: StoryObj = {
|
|
131
|
+
args: {
|
|
132
|
+
icon: checkIcon,
|
|
133
|
+
},
|
|
134
|
+
render: (args) => {
|
|
135
|
+
return {
|
|
136
|
+
components: { VIcon },
|
|
137
|
+
setup() {
|
|
138
|
+
return { args }
|
|
139
|
+
},
|
|
140
|
+
template: `
|
|
141
|
+
<p style="color: grey;font-size: 11px; margin-bottom: 12px;">Date de conception: 20/11/2024</p>
|
|
142
|
+
<div>
|
|
143
|
+
<p>Le tableau ci-dessous liste nos recommandations suivant les <a target="blank" style="color:#0C41BD;" href="https://www.numerique.gouv.fr/publications/rgaa-accessibilite/#contenu">catégories du RGAA</a>.</p>
|
|
144
|
+
<p style="margin-bottom: 12px;font-weight:bold;">Pour rappel le composant seul ne garantie pas
|
|
145
|
+
l'accessibilité du site.</p>
|
|
146
|
+
<div style="font-size: 14px">
|
|
147
|
+
<p>Nous avons deux façons de relever les problèmes d'accessibilité des composants :</p>
|
|
148
|
+
<div>
|
|
149
|
+
<v-btn variant="tonal" color="grey" size="x-small" style="margin: 2px;font-size: 8px;" rounded>
|
|
150
|
+
Audit
|
|
151
|
+
</v-btn>
|
|
152
|
+
Problèmes relevés par le projet
|
|
153
|
+
</div>
|
|
154
|
+
<div>
|
|
155
|
+
<v-btn variant="tonal" color="red" size="x-small" style="margin: 2px;font-size: 8px;" rounded>
|
|
156
|
+
Tanaguru
|
|
157
|
+
</v-btn>
|
|
158
|
+
Problèmes relevés par Tanaguru
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
`,
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
tags: ['!dev'],
|
|
166
|
+
}
|