@cnamts/synapse 1.0.1 → 1.0.2
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/README.md +1 -1
- package/dist/{DateFilter-BmRuzQ9Z.js → DateFilter-YWOTbfeL.js} +1 -1
- package/dist/{NumberFilter-CnIPDHqx.js → NumberFilter-DMmMgALM.js} +1 -1
- package/dist/{PeriodFilter-CZwZ8CnQ.js → PeriodFilter-Bok5BHcn.js} +1 -1
- package/dist/SelectFilter-BKud2WhN.js +136 -0
- package/dist/{TextFilter-DTxZHJwX.js → TextFilter-DvMf2thH.js} +1 -1
- package/dist/components/Accordion/Accordion.d.ts +2 -1
- package/dist/components/Accordion/composables/useAccordionGroupCommunication.d.ts +5 -0
- package/dist/components/Accordion/composables/useAccordionKeyboardNavigation.d.ts +12 -0
- package/dist/components/Accordion/composables/useAccordionState.d.ts +13 -0
- package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +85 -0
- package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +2 -0
- package/dist/components/Customs/SySelect/SySelect.d.ts +33 -13
- package/dist/components/Customs/SyTextField/SyTextField.d.ts +2 -2
- package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +1585 -1452
- package/dist/components/DatePicker/DatePicker/DatePicker.d.ts +16 -2
- package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +3 -1
- package/dist/components/DatePicker/composables/index.d.ts +2 -0
- package/dist/components/DatePicker/composables/useAsteriskDisplay.d.ts +14 -0
- package/dist/components/DatePicker/composables/useDateAutoClamp.d.ts +16 -0
- package/dist/components/DatePicker/composables/useDateRangeInput.d.ts +1 -1
- package/dist/components/DatePicker/composables/useDisplayedDateString.d.ts +3 -0
- package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +1 -0
- package/dist/components/DatePicker/composables/useMonthButtonCustomization.d.ts +5 -2
- package/dist/components/NirField/NirField.d.ts +7 -3
- package/dist/components/NirField/nirValidation.d.ts +1 -1
- package/dist/components/PasswordField/PasswordField.d.ts +2 -0
- package/dist/components/PeriodField/PeriodField.d.ts +52 -8
- package/dist/components/PhoneField/PhoneField.d.ts +2 -2
- package/dist/components/RangeField/RangeField.d.ts +2 -0
- package/dist/components/SearchListField/SearchListField.d.ts +9 -0
- package/dist/components/SyTextArea/SyTextArea.d.ts +2 -0
- package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +14 -9
- package/dist/components/Tables/SyTable/SyTable.d.ts +12 -7
- package/dist/components/Tables/common/SyTablePagination.d.ts +1636 -0
- package/dist/components/Tables/common/TableHeader.d.ts +2 -20
- package/dist/components/Tables/common/filters/SelectFilter.d.ts +5 -5
- package/dist/components/Tables/common/filters/getFilterComponent.d.ts +1 -0
- package/dist/components/Tables/common/filters/locales.d.ts +4 -0
- package/dist/components/Tables/common/filters/logics/date.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/number.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/period.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/select.d.ts +1 -0
- package/dist/components/Tables/common/filters/logics/text.d.ts +1 -0
- package/dist/components/Tables/common/locales.d.ts +21 -0
- package/dist/components/Tables/common/organizeColumns/OrganizeColumns.d.ts +267 -0
- package/dist/components/Tables/common/organizeColumns/sortHeaders.d.ts +2 -0
- package/dist/components/Tables/common/tableFilterUtils.d.ts +1 -0
- package/dist/components/Tables/common/tableStorageUtils.d.ts +41 -1
- package/dist/components/Tables/common/tableUtils.d.ts +42 -5
- package/dist/components/Tables/common/types.d.ts +19 -8
- package/dist/components/Tables/common/usePagination.d.ts +22 -0
- package/dist/components/Tables/common/useTableCheckbox.d.ts +20 -0
- package/dist/components/Tables/common/useTableHeaders.d.ts +76 -0
- package/dist/components/Tables/common/useTableItems.d.ts +24 -0
- package/dist/components/Tables/common/useTableOptions.d.ts +18 -0
- package/dist/components/ToolbarContainer/ToolbarContainer.d.ts +11 -0
- package/dist/components/UserMenuBtn/UserMenuBtn.d.ts +9 -2
- package/dist/components/index.d.ts +8 -6
- package/dist/design-system-v3.js +58 -56
- package/dist/design-system-v3.umd.cjs +22 -22
- package/dist/main-Cx8qG7YR.js +16344 -0
- package/dist/stories/Accessibilite/Vuetify/VuetifyItems.d.ts +14 -2
- package/dist/stories/DesignTokens/StylesTypographiques.stories.new.d.ts +8 -0
- package/dist/stories/DesignTokens/TypographyDisplay.d.ts +28 -0
- package/dist/stories/DesignTokens/vue-shims.d.ts +6 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/common/imgs/accessibility-svgrepo-com.svg +4 -0
- package/src/components/Accordion/Accessibilite/AccessibilityGuide.mdx +249 -0
- package/src/components/Accordion/Accordion.vue +48 -76
- package/src/components/Accordion/composables/__tests__/useAccordionGroupCommunication.spec.ts +146 -0
- package/src/components/Accordion/composables/__tests__/useAccordionKeyboardNavigation.spec.ts +209 -0
- package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +144 -0
- package/src/components/Accordion/composables/useAccordionGroupCommunication.ts +52 -0
- package/src/components/Accordion/composables/useAccordionKeyboardNavigation.ts +111 -0
- package/src/components/Accordion/composables/useAccordionState.ts +59 -0
- package/src/components/Accordion/tests/__snapshots__/accordion.spec.ts.snap +3 -0
- package/src/components/Customs/SyCheckbox/Accessibilite.mdx +303 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +50 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +630 -0
- package/src/components/Customs/SyCheckbox/SyCheckbox.vue +326 -0
- package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +201 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +1 -0
- package/src/components/Customs/SyInputSelect/SyInputSelect.vue +8 -1
- package/src/components/Customs/SySelect/SySelect.stories.ts +160 -0
- package/src/components/Customs/SySelect/SySelect.vue +291 -32
- package/src/components/Customs/SySelect/tests/SySelect.spec.ts +230 -0
- package/src/components/Customs/SyTextField/SyTextField.stories.ts +3 -2
- package/src/components/Customs/SyTextField/SyTextField.vue +19 -8
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +241 -31
- package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +305 -57
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.events.spec.ts +161 -0
- package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +4 -2
- package/src/components/DatePicker/DatePicker/DatePicker.stories.ts +259 -137
- package/src/components/DatePicker/DatePicker/DatePicker.vue +153 -25
- package/src/components/DatePicker/DatePicker/tests/DatePicker.events.spec.ts +189 -0
- package/src/components/DatePicker/DatePicker/{DatePicker.spec.ts → tests/DatePicker.spec.ts} +1 -15
- package/src/components/DatePicker/DateTextInput/DateRange.stories.ts +24 -14
- package/src/components/DatePicker/DateTextInput/DateTextInput.events.spec.ts +148 -0
- package/src/components/DatePicker/DateTextInput/DateTextInput.spec.ts +3 -1
- package/src/components/DatePicker/DateTextInput/DateTextInput.vue +200 -5
- package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +241 -31
- package/src/components/DatePicker/composables/index.ts +2 -0
- package/src/components/DatePicker/composables/tests/useDateAutoClamp.spec.ts +190 -0
- package/src/components/DatePicker/composables/tests/useInputBlurHandler.spec.ts +182 -4
- package/src/components/DatePicker/composables/tests/useMonthButtonCustomization.spec.ts +105 -80
- package/src/components/DatePicker/composables/useAsteriskDisplay.ts +31 -0
- package/src/components/DatePicker/composables/useDateAutoClamp.ts +136 -0
- package/src/components/DatePicker/composables/useDateRangeInput.ts +21 -18
- package/src/components/DatePicker/composables/useDisplayedDateString.ts +13 -1
- package/src/components/DatePicker/composables/useInputBlurHandler.ts +84 -20
- package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +149 -51
- package/src/components/DiacriticPicker/DiacriticPicker.stories.ts +10 -0
- package/src/components/ErrorPage/Accessibilite.stories.ts +8 -0
- package/src/components/ErrorPage/ErrorPage.vue +12 -6
- package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +4 -4
- package/src/components/NirField/NirField.mdx +22 -9
- package/src/components/NirField/NirField.stories.ts +26 -2
- package/src/components/NirField/NirField.vue +209 -22
- package/src/components/NirField/nirValidation.ts +17 -3
- package/src/components/NirField/tests/NirField.spec.ts +2 -2
- package/src/components/NotFoundPage/Accessibilite.stories.ts +8 -0
- package/src/components/NotFoundPage/NotFoundPage.vue +2 -1
- package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +8 -6
- package/src/components/PaginatedTable/PaginatedTable.mdx +2 -0
- package/src/components/PasswordField/PasswordField.stories.ts +4 -0
- package/src/components/PasswordField/PasswordField.vue +3 -0
- package/src/components/PeriodField/PeriodField.vue +2 -0
- package/src/components/PhoneField/PhoneField.stories.ts +15 -15
- package/src/components/PhoneField/PhoneField.vue +1 -1
- package/src/components/RangeField/RangeField.stories.ts +9 -0
- package/src/components/RangeField/RangeField.vue +4 -0
- package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +12 -0
- package/src/components/SearchListField/SearchListField.vue +5 -0
- package/src/components/SyTextArea/SyTextArea.vue +3 -0
- package/src/components/SyTextArea/tests/SyTextArea.spec.ts +0 -1
- package/src/components/Tables/SyServerTable/FilterRules.stories.ts +632 -15
- package/src/components/Tables/SyServerTable/SyServerTable.mdx +15 -5
- package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +2844 -1377
- package/src/components/Tables/SyServerTable/SyServerTable.vue +155 -66
- package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +256 -4
- package/src/components/Tables/SyTable/FilterRules.stories.ts +183 -0
- package/src/components/Tables/SyTable/SyTable.mdx +14 -4
- package/src/components/Tables/SyTable/SyTable.stories.ts +1265 -477
- package/src/components/Tables/SyTable/SyTable.vue +152 -72
- package/src/components/Tables/SyTable/tests/SyTable.spec.ts +366 -4
- package/src/components/Tables/common/SyTableFilter.vue +3 -56
- package/src/components/Tables/common/SyTablePagination.vue +375 -0
- package/src/components/Tables/common/TableHeader.vue +10 -26
- package/src/components/Tables/common/filters/SelectFilter.vue +131 -22
- package/src/components/Tables/common/filters/getFilterComponent.ts +54 -0
- package/src/components/Tables/common/filters/locales.ts +4 -0
- package/src/components/Tables/common/filters/logics/date.ts +12 -0
- package/src/components/Tables/common/filters/logics/number.ts +48 -0
- package/src/components/Tables/common/filters/logics/period.ts +25 -0
- package/src/components/Tables/common/filters/logics/select.ts +27 -0
- package/src/components/Tables/common/filters/logics/tests/TextFilterLogic.spec.ts +177 -0
- package/src/components/Tables/common/filters/logics/text.ts +62 -0
- package/src/components/Tables/common/filters/tests/TextFilter.spec.ts +11 -11
- package/src/components/Tables/common/locales.ts +24 -0
- package/src/components/Tables/common/organizeColumns/OrganizeColumns.vue +269 -0
- package/src/components/Tables/common/organizeColumns/sortHeaders.ts +9 -0
- package/src/components/Tables/common/tableFilterUtils.ts +43 -295
- package/src/components/Tables/common/tableStorageUtils.ts +27 -2
- package/src/components/Tables/common/tableStyles.scss +26 -0
- package/src/components/Tables/common/tableUtils.ts +3 -16
- package/src/components/Tables/common/tests/SyTablePagination.spec.ts +170 -0
- package/src/components/Tables/common/tests/filterByRange.spec.ts +215 -0
- package/src/components/Tables/common/tests/tableFilterUtils.spec.ts +0 -14
- package/src/components/Tables/common/tests/tableUtils.spec.ts +7 -51
- package/src/components/Tables/common/types.ts +17 -6
- package/src/components/Tables/common/usePagination.ts +83 -0
- package/src/components/Tables/common/useTableCheckbox.ts +58 -0
- package/src/components/Tables/common/useTableHeaders.ts +88 -0
- package/src/components/Tables/common/useTableItems.ts +87 -0
- package/src/components/Tables/common/useTableOptions.ts +93 -0
- package/src/components/ToolbarContainer/ToolbarContainer.mdx +16 -0
- package/src/components/ToolbarContainer/ToolbarContainer.stories.ts +675 -0
- package/src/components/ToolbarContainer/ToolbarContainer.vue +128 -0
- package/src/components/ToolbarContainer/tests/ToolbarContainer.spec.ts +156 -0
- package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +74 -0
- package/src/components/UserMenuBtn/UserMenuBtn.vue +19 -17
- package/src/components/index.ts +8 -6
- package/src/stories/Accessibilite/Aculturation/AuditDesignSystem.mdx +293 -20
- package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +448 -54
- package/src/stories/Accessibilite/Audit/RGAA.mdx +231 -23
- package/src/stories/Accessibilite/Avancement/Avancement.mdx +591 -7
- package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +139 -38
- package/src/stories/Accessibilite/Introduction.mdx +258 -18
- package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +221 -31
- package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +204 -22
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +537 -24
- package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +577 -70
- package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru.mdx +382 -31
- package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +419 -81
- package/src/stories/Accessibilite/Vuetify/Vuetify.mdx +132 -6
- package/src/stories/Accessibilite/Vuetify/Vuetify.stories.ts +370 -146
- package/src/stories/Accessibilite/Vuetify/VuetifyItems.ts +35 -57
- package/src/stories/Demarrer/Accueil.stories.ts +20 -5
- package/src/stories/DesignTokens/StylesTypographiques.mdx +10 -9
- package/src/stories/DesignTokens/StylesTypographiques.stories.new.ts +397 -0
- package/src/stories/DesignTokens/StylesTypographiques.stories.ts +397 -0
- package/src/stories/DesignTokens/TypographyDisplay.vue +155 -0
- package/src/stories/DesignTokens/vue-shims.d.ts +6 -0
- package/src/stories/GuideDuDev/LesBreackingChanges.mdx +0 -2
- package/src/stories/GuideDuDev/MigrationDepuisBridge.mdx +1 -1
- package/src/stories/GuideDuDev/MigrationDepuisVue2.mdx +1 -1
- package/src/stories/GuideDuDev/PortailAgent.mdx +10 -0
- package/src/stories/GuideDuDev/PortailAgent.stories.ts +506 -0
- package/src/stories/GuideDuDev/Theme.mdx +41 -0
- package/dist/SelectFilter-Cj-GW2Cc.js +0 -97
- package/dist/main-WDqeoGM-.js +0 -14788
- package/src/components/PaginatedTable/tests/__snapshots__/PaginatedTable.spec.ts.snap +0 -886
- package/src/components/Tables/SyServerTable/tests/__snapshots__/SyServerTable.spec.ts.snap +0 -521
- package/src/components/Tables/SyTable/tests/__snapshots__/SyTable.spec.ts.snap +0 -521
- package/src/stories/DesignTokens/ThemePA.mdx +0 -35
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { parseDate } from '../../tableFilterUtils'
|
|
2
|
+
|
|
3
|
+
export default function filter(itemValue: unknown, filterValue: unknown): boolean {
|
|
4
|
+
const itemDate = parseDate(itemValue)
|
|
5
|
+
const targetDate = parseDate(filterValue)
|
|
6
|
+
if (!itemDate || !targetDate) return false
|
|
7
|
+
return (
|
|
8
|
+
itemDate.getDate() === targetDate.getDate()
|
|
9
|
+
&& itemDate.getMonth() === targetDate.getMonth()
|
|
10
|
+
&& itemDate.getFullYear() === targetDate.getFullYear()
|
|
11
|
+
)
|
|
12
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export default function filter(itemValue: unknown, filterValue: unknown): boolean {
|
|
2
|
+
if (typeof itemValue === 'number') {
|
|
3
|
+
// Handle string filter values that may contain operators
|
|
4
|
+
if (typeof filterValue === 'string') {
|
|
5
|
+
// Check for operators at the beginning of the string
|
|
6
|
+
const operatorMatch = /^([=<>]{1,2})(.+)$/.exec(filterValue)
|
|
7
|
+
if (operatorMatch) {
|
|
8
|
+
const operator = operatorMatch[1]
|
|
9
|
+
const valueStr = operatorMatch[2].trim()
|
|
10
|
+
const numValue = parseFloat(valueStr.replace(',', '.'))
|
|
11
|
+
|
|
12
|
+
if (isNaN(numValue)) return false
|
|
13
|
+
|
|
14
|
+
switch (operator) {
|
|
15
|
+
case '=':
|
|
16
|
+
return itemValue === numValue
|
|
17
|
+
case '<>':
|
|
18
|
+
return itemValue !== numValue
|
|
19
|
+
case '<':
|
|
20
|
+
return itemValue < numValue
|
|
21
|
+
case '<=':
|
|
22
|
+
return itemValue <= numValue
|
|
23
|
+
case '>':
|
|
24
|
+
return itemValue > numValue
|
|
25
|
+
case '>=':
|
|
26
|
+
return itemValue >= numValue
|
|
27
|
+
default:
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// No operator, try to parse the value and do exact match
|
|
33
|
+
const numValue = parseFloat(filterValue.replace(',', '.'))
|
|
34
|
+
if (!isNaN(numValue)) {
|
|
35
|
+
return itemValue === numValue
|
|
36
|
+
}
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Handle numeric filter values (exact match)
|
|
41
|
+
if (typeof filterValue === 'number') {
|
|
42
|
+
return itemValue === filterValue
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return String(itemValue).includes(String(filterValue))
|
|
46
|
+
}
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { parseDate } from '../../tableFilterUtils'
|
|
2
|
+
|
|
3
|
+
export default function filter(itemValue: unknown, filterValue: unknown): boolean {
|
|
4
|
+
const itemDate = parseDate(itemValue)
|
|
5
|
+
if (
|
|
6
|
+
typeof filterValue !== 'object'
|
|
7
|
+
|| filterValue === null
|
|
8
|
+
|| 'from' in filterValue === false
|
|
9
|
+
|| 'to' in filterValue === false
|
|
10
|
+
) throw new Error('Invalid filter value for period type')
|
|
11
|
+
|
|
12
|
+
const min = parseDate(filterValue.from)
|
|
13
|
+
const max = parseDate(filterValue.to)
|
|
14
|
+
|
|
15
|
+
if (itemDate) {
|
|
16
|
+
if (min && itemDate < min) {
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
if (max && itemDate > max) {
|
|
20
|
+
return false
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default function filter(itemValue: unknown, filterValue: unknown): boolean {
|
|
2
|
+
// Handle multiple selection (filterValue is array)
|
|
3
|
+
if (Array.isArray(filterValue)) {
|
|
4
|
+
// If itemValue is also an array (e.g., item.skills = ['JavaScript', 'Vue'])
|
|
5
|
+
if (Array.isArray(itemValue)) {
|
|
6
|
+
// Check if any value in filterValue matches any value in itemValue
|
|
7
|
+
return filterValue.some(fv =>
|
|
8
|
+
itemValue.some(iv =>
|
|
9
|
+
// Handle both primitive values and objects
|
|
10
|
+
typeof fv === 'object' && fv !== null && typeof iv === 'object' && iv !== null
|
|
11
|
+
? JSON.stringify(fv) === JSON.stringify(iv)
|
|
12
|
+
: fv === iv,
|
|
13
|
+
),
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// If itemValue is a single value, check if it's included in filterValue
|
|
18
|
+
return filterValue.includes(itemValue as unknown as typeof filterValue[0])
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Handle object comparison
|
|
22
|
+
if (typeof filterValue === 'object' && filterValue !== null) {
|
|
23
|
+
return JSON.stringify(filterValue) === JSON.stringify(itemValue)
|
|
24
|
+
}
|
|
25
|
+
// Handle single value comparison
|
|
26
|
+
return itemValue === filterValue
|
|
27
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { it, expect, describe } from 'vitest'
|
|
2
|
+
import filter from '../text'
|
|
3
|
+
|
|
4
|
+
describe('Text filter logic', () => {
|
|
5
|
+
it('should return true for empty string and empty filter', () => {
|
|
6
|
+
expect(filter('', '')).toBe(true)
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('should return true for null item value and empty filter', () => {
|
|
10
|
+
expect(filter(null, '')).toBe(true)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should return false for null item value and non-empty filter', () => {
|
|
14
|
+
expect(filter(null, 'test')).toBe(false)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should return true for exact match', () => {
|
|
18
|
+
expect(filter('test', 'test')).toBe(true)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('should return false for non-matching strings', () => {
|
|
22
|
+
expect(filter('test', 'example')).toBe(false)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should perform case-insensitive search by default', () => {
|
|
26
|
+
expect(filter('Test', 'test')).toBe(true)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should handle special characters in filter', () => {
|
|
30
|
+
expect(filter('hello world!', 'world')).toBe(true)
|
|
31
|
+
expect(filter('hello world!', 'WORLD')).toBe(true)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should handle empty filter string', () => {
|
|
35
|
+
expect(filter('any text', '')).toBe(true)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('should not take accents into account', () => {
|
|
39
|
+
expect(filter('café', 'cafe')).toBe(true)
|
|
40
|
+
expect(filter('café', 'Café')).toBe(true)
|
|
41
|
+
expect(filter('café', 'CAFE')).toBe(true)
|
|
42
|
+
expect(filter('éèêëùûüîïñ', 'eeeuuuiin')).toBe(true)
|
|
43
|
+
expect(filter('éèêëùûüîïñ', 'ÉÈÊËÙÛÜÎÏÑ')).toBe(true)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('return true for a sequence found in the middle of a string or a word', () => {
|
|
47
|
+
expect(filter('hello world', 'lo wo')).toBe(true)
|
|
48
|
+
expect(filter('hello world', 'lo W')).toBe(true)
|
|
49
|
+
expect(filter('hello world', 'loW')).toBe(false)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('handles guillemets to case-sensitive search', () => {
|
|
53
|
+
expect(filter('Hello World', '"Hello"')).toBe(true)
|
|
54
|
+
expect(filter('Hello World', '"hello"')).toBe(false)
|
|
55
|
+
expect(filter('Hello World', '"WORLD"')).toBe(false)
|
|
56
|
+
expect(filter('Hello World', '"world"')).toBe(false)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('handles guillemets to accents sensitive search', () => {
|
|
60
|
+
expect(filter('café', '"cafe"')).toBe(false)
|
|
61
|
+
expect(filter('éèêëùûüîïñ', '"éèêëùûüîïñ"')).toBe(true)
|
|
62
|
+
expect(filter('éèêëùûüîïñ', '"eeeuuuiin"')).toBe(false)
|
|
63
|
+
expect(filter('éèêëùûüîïñ', '"ÉÈÊËÙÛÜÎÏÑ"')).toBe(false)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('perform a scrict comparaison when the search string begin by a =', () => {
|
|
67
|
+
expect(filter('lorem ipsum', '=lorem ipsum')).toBe(true)
|
|
68
|
+
expect(filter('lorem ipsum', '=lorem Ipsum')).toBe(false)
|
|
69
|
+
expect(filter('lorem ipsum', '=lorem ipsum ')).toBe(false)
|
|
70
|
+
expect(filter('lorem ipsum', '=ipsum')).toBe(false)
|
|
71
|
+
expect(filter('lorem ipsum', '=lorem')).toBe(false)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('permorm a non equal comparaison when the search string begin by <>', () => {
|
|
75
|
+
expect(filter('lorem ipsum', '<>lorem ipsum')).toBe(false)
|
|
76
|
+
expect(filter('lorem ipsum', '<>lorem Ipsum')).toBe(true)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('accepts the wildcard ? in the search string', () => {
|
|
80
|
+
expect(filter('lorem ipsum', 'lorem ?psum')).toBe(true)
|
|
81
|
+
expect(filter('lorem ipsum', 'lorem ?psu?')).toBe(true)
|
|
82
|
+
expect(filter('lorem ipsum', '???????????')).toBe(true)
|
|
83
|
+
expect(filter('lorem ipsum', 'lorem ?psu?m')).toBe(false)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('accepts the wildcard * in the search string', () => {
|
|
87
|
+
expect(filter('lorem ipsum', 'lorem *um')).toBe(true)
|
|
88
|
+
expect(filter('lorem ipsum', 'lorem*psu*')).toBe(true)
|
|
89
|
+
expect(filter('lorem ipsum', '*ipsum')).toBe(true)
|
|
90
|
+
expect(filter('lorem ipsum', 'lorem*')).toBe(true)
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('accepts the mixed use of the secials caracters in the search string', () => {
|
|
94
|
+
expect(filter('lorem ipsum', '=l?rem ip*')).toBe(true)
|
|
95
|
+
expect(filter('lorem ipsum', '=l?rEm ip*')).toBe(false)
|
|
96
|
+
expect(filter('lorem ipsum', '<>l?rem ip*')).toBe(false)
|
|
97
|
+
expect(filter('lorem ipsum', '<>l?rem ipsul')).toBe(true)
|
|
98
|
+
expect(filter('lorem ipsum', '"lorem*psum"')).toBe(true)
|
|
99
|
+
expect(filter('lorem ipsum', '"lorém*psum"')).toBe(false)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('returns true when a next letter is found and the superior than operator is used', () => {
|
|
103
|
+
expect(filter('b', '>a')).toBe(true)
|
|
104
|
+
expect(filter('b', '>b')).toBe(false)
|
|
105
|
+
expect(filter('b', '>c')).toBe(false)
|
|
106
|
+
expect(filter('café', '>b')).toBe(true)
|
|
107
|
+
expect(filter('café', '>c')).toBe(true)
|
|
108
|
+
expect(filter('café', '>cd')).toBe(false)
|
|
109
|
+
expect(filter('café', '>d')).toBe(false)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('returns true when a next letter is found and the inferior than operator is used', () => {
|
|
113
|
+
expect(filter('b', '<c')).toBe(true)
|
|
114
|
+
expect(filter('b', '<b')).toBe(false)
|
|
115
|
+
expect(filter('b', '<a')).toBe(false)
|
|
116
|
+
expect(filter('café', '<d')).toBe(true)
|
|
117
|
+
expect(filter('café', '<c')).toBe(false)
|
|
118
|
+
expect(filter('café', '<ca')).toBe(false)
|
|
119
|
+
expect(filter('café', '<e')).toBe(true)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('returns true when a next letter is found and the superior or equal than operator is used', () => {
|
|
123
|
+
expect(filter('b', '>=a')).toBe(true)
|
|
124
|
+
expect(filter('b', '>=b')).toBe(true)
|
|
125
|
+
expect(filter('b', '>=c')).toBe(false)
|
|
126
|
+
expect(filter('café', '>=b')).toBe(true)
|
|
127
|
+
expect(filter('café', '>=c')).toBe(true)
|
|
128
|
+
expect(filter('café', '>=cd')).toBe(false)
|
|
129
|
+
expect(filter('café', '>=d')).toBe(false)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('returns true when a next letter is found and the inferior or equal than operator is used', () => {
|
|
133
|
+
expect(filter('b', '<=c')).toBe(true)
|
|
134
|
+
expect(filter('b', '<=b')).toBe(true)
|
|
135
|
+
expect(filter('b', '<=a')).toBe(false)
|
|
136
|
+
expect(filter('café', '<=d')).toBe(true)
|
|
137
|
+
expect(filter('café', '<=c')).toBe(false)
|
|
138
|
+
expect(filter('café', '<=ca')).toBe(false)
|
|
139
|
+
expect(filter('café', '<=e')).toBe(true)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
describe('specs specifics tests', () => {
|
|
143
|
+
it('matches all words starting with "p" regardless of case', () => {
|
|
144
|
+
expect(filter('pomme', 'p*')).toBe(true)
|
|
145
|
+
expect(filter('Pomme', 'p*')).toBe(true)
|
|
146
|
+
expect(filter('banane', 'p*')).toBe(false)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('matches all words of exactly 4 letters', () => {
|
|
150
|
+
expect(filter('test', '=????')).toBe(true)
|
|
151
|
+
expect(filter('test', '=????')).toBe(true)
|
|
152
|
+
expect(filter('tests', '=????')).toBe(false)
|
|
153
|
+
expect(filter('tes', '=????')).toBe(false)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('matches all empty values', () => {
|
|
157
|
+
expect(filter('', '<>?*')).toBe(true)
|
|
158
|
+
expect(filter(null, '<>?*')).toBe(true)
|
|
159
|
+
expect(filter('test', '<>?*')).toBe(false)
|
|
160
|
+
expect(filter(' ', '<>?*')).toBe(false)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('matches all words containing a capital "W"', () => {
|
|
164
|
+
expect(filter('Hello World', '"W"')).toBe(true)
|
|
165
|
+
expect(filter('hello world', '"W"')).toBe(false)
|
|
166
|
+
expect(filter('World', '"W"')).toBe(true)
|
|
167
|
+
expect(filter('world', '"W"')).toBe(false)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('matches all words alphabetically after "zu"', () => {
|
|
171
|
+
expect(filter('zucchini', '>zu')).toBe(true)
|
|
172
|
+
expect(filter('zu', '>zu')).toBe(false)
|
|
173
|
+
expect(filter('zebra', '>zu')).toBe(false)
|
|
174
|
+
expect(filter('apple', '>zu')).toBe(false)
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export default function filter(itemValue: unknown, filterValue: unknown): boolean {
|
|
2
|
+
const str = String(itemValue ?? '')
|
|
3
|
+
const search = String(filterValue ?? '')
|
|
4
|
+
|
|
5
|
+
if (search.startsWith('"') && search.endsWith('"')) {
|
|
6
|
+
const regex = generateRegex(search.slice(1, -1), true)
|
|
7
|
+
return regex.test(str)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
else if (search.startsWith('=')) {
|
|
11
|
+
const regex = generateRegex(search.slice(1), true, true)
|
|
12
|
+
return regex.test(str)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
else if (search.startsWith('<>')) {
|
|
16
|
+
const regex = generateRegex(search.slice(2), true, true)
|
|
17
|
+
return !regex.test(str)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
else if (search.startsWith('<=')) {
|
|
21
|
+
const cleanedSearch = search.slice(2).trim()
|
|
22
|
+
return str.localeCompare(cleanedSearch) <= 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
else if (search.startsWith('>=')) {
|
|
26
|
+
const cleanedSearch = search.slice(2).trim()
|
|
27
|
+
return str.localeCompare(cleanedSearch) >= 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
else if (search.startsWith('>')) {
|
|
31
|
+
const cleanedSearch = search.slice(1).trim()
|
|
32
|
+
return str.localeCompare(cleanedSearch) > 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
else if (search.startsWith('<')) {
|
|
36
|
+
const cleanedSearch = search.slice(1).trim()
|
|
37
|
+
return str.localeCompare(cleanedSearch) < 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
else {
|
|
41
|
+
const regex = generateRegex(removeAccents(search))
|
|
42
|
+
return regex.test(removeAccents(str))
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function generateRegex(search: string, caseSensitive = false, strict = false): RegExp {
|
|
47
|
+
const escapedSearch = search.replace(/[-[\]{}()+.,\\^$|#\s]/g, '\\$&')
|
|
48
|
+
const regexSequenceWithWildcards = escapedSearch.replace(/\?/g, '.')
|
|
49
|
+
let regex = regexSequenceWithWildcards.replace(/\*/g, '.*')
|
|
50
|
+
if (strict) {
|
|
51
|
+
regex = '^' + regex + '$'
|
|
52
|
+
}
|
|
53
|
+
else if (regex !== escapedSearch) {
|
|
54
|
+
regex = '^' + regex
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return new RegExp(regex, caseSensitive ? 'g' : 'gi')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function removeAccents(str: string): string {
|
|
61
|
+
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
|
|
62
|
+
}
|
|
@@ -117,7 +117,7 @@ describe('TextFilter.vue', () => {
|
|
|
117
117
|
|
|
118
118
|
// Émettre une valeur pour déclencher la mise à jour du filtre
|
|
119
119
|
const syTextField = newWrapper.findComponent(SyTextField)
|
|
120
|
-
|
|
120
|
+
syTextField.vm.$emit('update:modelValue', 'test value')
|
|
121
121
|
|
|
122
122
|
// Vérifier que l'événement a été émis avec une clé générée basée sur le titre
|
|
123
123
|
expect(newWrapper.emitted('update:filters')).toBeTruthy()
|
|
@@ -193,15 +193,15 @@ describe('TextFilter.vue', () => {
|
|
|
193
193
|
it('supports wildcard * for any string of characters', () => {
|
|
194
194
|
const filters = [{ key: 'text', value: 'a*', type: 'text' as FilterType }]
|
|
195
195
|
const result = filterItems(testItems, filters)
|
|
196
|
-
expect(result).toHaveLength(
|
|
197
|
-
expect(result.map(item => item.id)).toEqual([1
|
|
196
|
+
expect(result).toHaveLength(1)
|
|
197
|
+
expect(result.map(item => item.id)).toEqual([1])
|
|
198
198
|
})
|
|
199
199
|
|
|
200
200
|
it('supports wildcard ? for any single character', () => {
|
|
201
201
|
const filters = [{ key: 'text', value: '????', type: 'text' as FilterType }]
|
|
202
202
|
const result = filterItems(testItems, filters)
|
|
203
|
-
expect(result).toHaveLength(
|
|
204
|
-
expect(result.map(item => item.id)).toEqual([1, 4,
|
|
203
|
+
expect(result).toHaveLength(6) // the word should have at least 4 characterss
|
|
204
|
+
expect(result.map(item => item.id)).toEqual([1, 2, 3, 4, 5, 7])
|
|
205
205
|
})
|
|
206
206
|
|
|
207
207
|
it('supports case-sensitive search with double quotes', () => {
|
|
@@ -223,27 +223,27 @@ describe('TextFilter.vue', () => {
|
|
|
223
223
|
expect(result[0].id).toBe(5)
|
|
224
224
|
})
|
|
225
225
|
|
|
226
|
-
it('supports exact length search
|
|
226
|
+
it('supports exact length search equal and question marks', () => {
|
|
227
227
|
const filters = [{ key: 'text', value: '=????', type: 'text' as FilterType }]
|
|
228
228
|
const result = filterItems(testItems, filters)
|
|
229
|
-
expect(result).toHaveLength(
|
|
230
|
-
expect(result.map(item => item.id)).toEqual([
|
|
229
|
+
expect(result).toHaveLength(1)
|
|
230
|
+
expect(result.map(item => item.id)).toEqual([4])
|
|
231
231
|
|
|
232
232
|
// Test with different length
|
|
233
233
|
const filters2 = [{ key: 'text', value: '=?????', type: 'text' as FilterType }]
|
|
234
234
|
const result2 = filterItems(testItems, filters2)
|
|
235
235
|
expect(result2).toHaveLength(2)
|
|
236
|
-
expect(result2.map(item => item.id)).toEqual([
|
|
236
|
+
expect(result2.map(item => item.id)).toEqual([1, 7])
|
|
237
237
|
})
|
|
238
238
|
|
|
239
|
-
it('supports empty or null value search with
|
|
239
|
+
it('supports empty or null value search with not equal operator', () => {
|
|
240
240
|
const filters = [{ key: 'text', value: '<>?*', type: 'text' as FilterType }]
|
|
241
241
|
const result = filterItems(testItems, filters)
|
|
242
242
|
expect(result).toHaveLength(2)
|
|
243
243
|
expect(result.map(item => item.id)).toEqual([8, 9])
|
|
244
244
|
})
|
|
245
245
|
|
|
246
|
-
it('supports alphabetical comparison with
|
|
246
|
+
it('supports alphabetical comparison with superior operator', () => {
|
|
247
247
|
const filters = [{ key: 'text', value: '>f', type: 'text' as FilterType }]
|
|
248
248
|
const result = filterItems(testItems, filters)
|
|
249
249
|
expect(result).toHaveLength(2)
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
export const locales = {
|
|
2
|
+
// Table locales
|
|
2
3
|
resetFilters: 'Réinitialiser les filtres',
|
|
3
4
|
noData: 'Aucune donnée disponible',
|
|
4
5
|
columnOrder: (columnTitle: string) => `Ordonner par ${columnTitle}`,
|
|
5
6
|
ResizableColumn: 'Redimensionner la colonne',
|
|
6
7
|
resizeColumn: (columnTitle: string) => `Redimensionner la colonne ${columnTitle}`,
|
|
8
|
+
selectAllRows: 'Sélectionner toutes les lignes',
|
|
9
|
+
selectRow: 'Sélectionner la ligne',
|
|
10
|
+
|
|
11
|
+
// Pagination locales
|
|
12
|
+
pagination: {
|
|
13
|
+
itemsPerPageText: 'Lignes par page:',
|
|
14
|
+
previous: 'Précédent',
|
|
15
|
+
next: 'Suivant',
|
|
16
|
+
all: 'Tous',
|
|
17
|
+
showingItems: (start: number, end: number, total: number) => `${start}-${end} sur ${total} éléments`,
|
|
18
|
+
pageText: (page: number) => `${page}`,
|
|
19
|
+
pageAriaLabel: (page: number) => `Page ${page}`,
|
|
20
|
+
currentPageAriaLabel: (page: number) => `Page courante, Page ${page}`,
|
|
21
|
+
paginationNavAriaLabel: 'Navigation de pagination',
|
|
22
|
+
},
|
|
23
|
+
reorganizeColumns: 'Gestion des colonnes',
|
|
24
|
+
close: 'Fermer',
|
|
25
|
+
apply: 'Appliquer',
|
|
26
|
+
reorganizeColumnsTitle: 'Gestion des colonnes',
|
|
27
|
+
hideColumn: (columnTitle: string) => `Masquer la colonne ${columnTitle}`,
|
|
28
|
+
showColumn: (columnTitle: string) => `Afficher la colonne ${columnTitle}`,
|
|
29
|
+
moveColumnLeft: (columnTitle: string) => `Déplacer la colonne ${columnTitle} vers la gauche`,
|
|
30
|
+
moveColumnRight: (columnTitle: string) => `Déplacer la colonne ${columnTitle} vers la droite`,
|
|
7
31
|
}
|