@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.
Files changed (217) hide show
  1. package/README.md +1 -1
  2. package/dist/{DateFilter-BmRuzQ9Z.js → DateFilter-YWOTbfeL.js} +1 -1
  3. package/dist/{NumberFilter-CnIPDHqx.js → NumberFilter-DMmMgALM.js} +1 -1
  4. package/dist/{PeriodFilter-CZwZ8CnQ.js → PeriodFilter-Bok5BHcn.js} +1 -1
  5. package/dist/SelectFilter-BKud2WhN.js +136 -0
  6. package/dist/{TextFilter-DTxZHJwX.js → TextFilter-DvMf2thH.js} +1 -1
  7. package/dist/components/Accordion/Accordion.d.ts +2 -1
  8. package/dist/components/Accordion/composables/useAccordionGroupCommunication.d.ts +5 -0
  9. package/dist/components/Accordion/composables/useAccordionKeyboardNavigation.d.ts +12 -0
  10. package/dist/components/Accordion/composables/useAccordionState.d.ts +13 -0
  11. package/dist/components/Customs/SyCheckbox/SyCheckbox.d.ts +85 -0
  12. package/dist/components/Customs/SyInputSelect/SyInputSelect.d.ts +2 -0
  13. package/dist/components/Customs/SySelect/SySelect.d.ts +33 -13
  14. package/dist/components/Customs/SyTextField/SyTextField.d.ts +2 -2
  15. package/dist/components/DatePicker/ComplexDatePicker/ComplexDatePicker.d.ts +1585 -1452
  16. package/dist/components/DatePicker/DatePicker/DatePicker.d.ts +16 -2
  17. package/dist/components/DatePicker/DateTextInput/DateTextInput.d.ts +3 -1
  18. package/dist/components/DatePicker/composables/index.d.ts +2 -0
  19. package/dist/components/DatePicker/composables/useAsteriskDisplay.d.ts +14 -0
  20. package/dist/components/DatePicker/composables/useDateAutoClamp.d.ts +16 -0
  21. package/dist/components/DatePicker/composables/useDateRangeInput.d.ts +1 -1
  22. package/dist/components/DatePicker/composables/useDisplayedDateString.d.ts +3 -0
  23. package/dist/components/DatePicker/composables/useInputBlurHandler.d.ts +1 -0
  24. package/dist/components/DatePicker/composables/useMonthButtonCustomization.d.ts +5 -2
  25. package/dist/components/NirField/NirField.d.ts +7 -3
  26. package/dist/components/NirField/nirValidation.d.ts +1 -1
  27. package/dist/components/PasswordField/PasswordField.d.ts +2 -0
  28. package/dist/components/PeriodField/PeriodField.d.ts +52 -8
  29. package/dist/components/PhoneField/PhoneField.d.ts +2 -2
  30. package/dist/components/RangeField/RangeField.d.ts +2 -0
  31. package/dist/components/SearchListField/SearchListField.d.ts +9 -0
  32. package/dist/components/SyTextArea/SyTextArea.d.ts +2 -0
  33. package/dist/components/Tables/SyServerTable/SyServerTable.d.ts +14 -9
  34. package/dist/components/Tables/SyTable/SyTable.d.ts +12 -7
  35. package/dist/components/Tables/common/SyTablePagination.d.ts +1636 -0
  36. package/dist/components/Tables/common/TableHeader.d.ts +2 -20
  37. package/dist/components/Tables/common/filters/SelectFilter.d.ts +5 -5
  38. package/dist/components/Tables/common/filters/getFilterComponent.d.ts +1 -0
  39. package/dist/components/Tables/common/filters/locales.d.ts +4 -0
  40. package/dist/components/Tables/common/filters/logics/date.d.ts +1 -0
  41. package/dist/components/Tables/common/filters/logics/number.d.ts +1 -0
  42. package/dist/components/Tables/common/filters/logics/period.d.ts +1 -0
  43. package/dist/components/Tables/common/filters/logics/select.d.ts +1 -0
  44. package/dist/components/Tables/common/filters/logics/text.d.ts +1 -0
  45. package/dist/components/Tables/common/locales.d.ts +21 -0
  46. package/dist/components/Tables/common/organizeColumns/OrganizeColumns.d.ts +267 -0
  47. package/dist/components/Tables/common/organizeColumns/sortHeaders.d.ts +2 -0
  48. package/dist/components/Tables/common/tableFilterUtils.d.ts +1 -0
  49. package/dist/components/Tables/common/tableStorageUtils.d.ts +41 -1
  50. package/dist/components/Tables/common/tableUtils.d.ts +42 -5
  51. package/dist/components/Tables/common/types.d.ts +19 -8
  52. package/dist/components/Tables/common/usePagination.d.ts +22 -0
  53. package/dist/components/Tables/common/useTableCheckbox.d.ts +20 -0
  54. package/dist/components/Tables/common/useTableHeaders.d.ts +76 -0
  55. package/dist/components/Tables/common/useTableItems.d.ts +24 -0
  56. package/dist/components/Tables/common/useTableOptions.d.ts +18 -0
  57. package/dist/components/ToolbarContainer/ToolbarContainer.d.ts +11 -0
  58. package/dist/components/UserMenuBtn/UserMenuBtn.d.ts +9 -2
  59. package/dist/components/index.d.ts +8 -6
  60. package/dist/design-system-v3.js +58 -56
  61. package/dist/design-system-v3.umd.cjs +22 -22
  62. package/dist/main-Cx8qG7YR.js +16344 -0
  63. package/dist/stories/Accessibilite/Vuetify/VuetifyItems.d.ts +14 -2
  64. package/dist/stories/DesignTokens/StylesTypographiques.stories.new.d.ts +8 -0
  65. package/dist/stories/DesignTokens/TypographyDisplay.d.ts +28 -0
  66. package/dist/stories/DesignTokens/vue-shims.d.ts +6 -0
  67. package/dist/style.css +1 -1
  68. package/package.json +1 -1
  69. package/src/common/imgs/accessibility-svgrepo-com.svg +4 -0
  70. package/src/components/Accordion/Accessibilite/AccessibilityGuide.mdx +249 -0
  71. package/src/components/Accordion/Accordion.vue +48 -76
  72. package/src/components/Accordion/composables/__tests__/useAccordionGroupCommunication.spec.ts +146 -0
  73. package/src/components/Accordion/composables/__tests__/useAccordionKeyboardNavigation.spec.ts +209 -0
  74. package/src/components/Accordion/composables/__tests__/useAccordionState.spec.ts +144 -0
  75. package/src/components/Accordion/composables/useAccordionGroupCommunication.ts +52 -0
  76. package/src/components/Accordion/composables/useAccordionKeyboardNavigation.ts +111 -0
  77. package/src/components/Accordion/composables/useAccordionState.ts +59 -0
  78. package/src/components/Accordion/tests/__snapshots__/accordion.spec.ts.snap +3 -0
  79. package/src/components/Customs/SyCheckbox/Accessibilite.mdx +303 -0
  80. package/src/components/Customs/SyCheckbox/SyCheckbox.mdx +50 -0
  81. package/src/components/Customs/SyCheckbox/SyCheckbox.stories.ts +630 -0
  82. package/src/components/Customs/SyCheckbox/SyCheckbox.vue +326 -0
  83. package/src/components/Customs/SyCheckbox/tests/SyCheckbox.spec.ts +201 -0
  84. package/src/components/Customs/SyInputSelect/SyInputSelect.stories.ts +1 -0
  85. package/src/components/Customs/SyInputSelect/SyInputSelect.vue +8 -1
  86. package/src/components/Customs/SySelect/SySelect.stories.ts +160 -0
  87. package/src/components/Customs/SySelect/SySelect.vue +291 -32
  88. package/src/components/Customs/SySelect/tests/SySelect.spec.ts +230 -0
  89. package/src/components/Customs/SyTextField/SyTextField.stories.ts +3 -2
  90. package/src/components/Customs/SyTextField/SyTextField.vue +19 -8
  91. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.stories.ts +241 -31
  92. package/src/components/DatePicker/ComplexDatePicker/ComplexDatePicker.vue +305 -57
  93. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.events.spec.ts +161 -0
  94. package/src/components/DatePicker/ComplexDatePicker/tests/ComplexDatePicker.spec.ts +4 -2
  95. package/src/components/DatePicker/DatePicker/DatePicker.stories.ts +259 -137
  96. package/src/components/DatePicker/DatePicker/DatePicker.vue +153 -25
  97. package/src/components/DatePicker/DatePicker/tests/DatePicker.events.spec.ts +189 -0
  98. package/src/components/DatePicker/DatePicker/{DatePicker.spec.ts → tests/DatePicker.spec.ts} +1 -15
  99. package/src/components/DatePicker/DateTextInput/DateRange.stories.ts +24 -14
  100. package/src/components/DatePicker/DateTextInput/DateTextInput.events.spec.ts +148 -0
  101. package/src/components/DatePicker/DateTextInput/DateTextInput.spec.ts +3 -1
  102. package/src/components/DatePicker/DateTextInput/DateTextInput.vue +200 -5
  103. package/src/components/DatePicker/DateTextInput/NoCalendar.stories.ts +241 -31
  104. package/src/components/DatePicker/composables/index.ts +2 -0
  105. package/src/components/DatePicker/composables/tests/useDateAutoClamp.spec.ts +190 -0
  106. package/src/components/DatePicker/composables/tests/useInputBlurHandler.spec.ts +182 -4
  107. package/src/components/DatePicker/composables/tests/useMonthButtonCustomization.spec.ts +105 -80
  108. package/src/components/DatePicker/composables/useAsteriskDisplay.ts +31 -0
  109. package/src/components/DatePicker/composables/useDateAutoClamp.ts +136 -0
  110. package/src/components/DatePicker/composables/useDateRangeInput.ts +21 -18
  111. package/src/components/DatePicker/composables/useDisplayedDateString.ts +13 -1
  112. package/src/components/DatePicker/composables/useInputBlurHandler.ts +84 -20
  113. package/src/components/DatePicker/composables/useMonthButtonCustomization.ts +149 -51
  114. package/src/components/DiacriticPicker/DiacriticPicker.stories.ts +10 -0
  115. package/src/components/ErrorPage/Accessibilite.stories.ts +8 -0
  116. package/src/components/ErrorPage/ErrorPage.vue +12 -6
  117. package/src/components/ErrorPage/tests/__snapshots__/ErrorPage.spec.ts.snap +4 -4
  118. package/src/components/NirField/NirField.mdx +22 -9
  119. package/src/components/NirField/NirField.stories.ts +26 -2
  120. package/src/components/NirField/NirField.vue +209 -22
  121. package/src/components/NirField/nirValidation.ts +17 -3
  122. package/src/components/NirField/tests/NirField.spec.ts +2 -2
  123. package/src/components/NotFoundPage/Accessibilite.stories.ts +8 -0
  124. package/src/components/NotFoundPage/NotFoundPage.vue +2 -1
  125. package/src/components/NotFoundPage/tests/__snapshots__/NotFoundPage.spec.ts.snap +8 -6
  126. package/src/components/PaginatedTable/PaginatedTable.mdx +2 -0
  127. package/src/components/PasswordField/PasswordField.stories.ts +4 -0
  128. package/src/components/PasswordField/PasswordField.vue +3 -0
  129. package/src/components/PeriodField/PeriodField.vue +2 -0
  130. package/src/components/PhoneField/PhoneField.stories.ts +15 -15
  131. package/src/components/PhoneField/PhoneField.vue +1 -1
  132. package/src/components/RangeField/RangeField.stories.ts +9 -0
  133. package/src/components/RangeField/RangeField.vue +4 -0
  134. package/src/components/RangeField/tests/__snapshots__/RangeField.spec.ts.snap +12 -0
  135. package/src/components/SearchListField/SearchListField.vue +5 -0
  136. package/src/components/SyTextArea/SyTextArea.vue +3 -0
  137. package/src/components/SyTextArea/tests/SyTextArea.spec.ts +0 -1
  138. package/src/components/Tables/SyServerTable/FilterRules.stories.ts +632 -15
  139. package/src/components/Tables/SyServerTable/SyServerTable.mdx +15 -5
  140. package/src/components/Tables/SyServerTable/SyServerTable.stories.ts +2844 -1377
  141. package/src/components/Tables/SyServerTable/SyServerTable.vue +155 -66
  142. package/src/components/Tables/SyServerTable/tests/SyServerTable.spec.ts +256 -4
  143. package/src/components/Tables/SyTable/FilterRules.stories.ts +183 -0
  144. package/src/components/Tables/SyTable/SyTable.mdx +14 -4
  145. package/src/components/Tables/SyTable/SyTable.stories.ts +1265 -477
  146. package/src/components/Tables/SyTable/SyTable.vue +152 -72
  147. package/src/components/Tables/SyTable/tests/SyTable.spec.ts +366 -4
  148. package/src/components/Tables/common/SyTableFilter.vue +3 -56
  149. package/src/components/Tables/common/SyTablePagination.vue +375 -0
  150. package/src/components/Tables/common/TableHeader.vue +10 -26
  151. package/src/components/Tables/common/filters/SelectFilter.vue +131 -22
  152. package/src/components/Tables/common/filters/getFilterComponent.ts +54 -0
  153. package/src/components/Tables/common/filters/locales.ts +4 -0
  154. package/src/components/Tables/common/filters/logics/date.ts +12 -0
  155. package/src/components/Tables/common/filters/logics/number.ts +48 -0
  156. package/src/components/Tables/common/filters/logics/period.ts +25 -0
  157. package/src/components/Tables/common/filters/logics/select.ts +27 -0
  158. package/src/components/Tables/common/filters/logics/tests/TextFilterLogic.spec.ts +177 -0
  159. package/src/components/Tables/common/filters/logics/text.ts +62 -0
  160. package/src/components/Tables/common/filters/tests/TextFilter.spec.ts +11 -11
  161. package/src/components/Tables/common/locales.ts +24 -0
  162. package/src/components/Tables/common/organizeColumns/OrganizeColumns.vue +269 -0
  163. package/src/components/Tables/common/organizeColumns/sortHeaders.ts +9 -0
  164. package/src/components/Tables/common/tableFilterUtils.ts +43 -295
  165. package/src/components/Tables/common/tableStorageUtils.ts +27 -2
  166. package/src/components/Tables/common/tableStyles.scss +26 -0
  167. package/src/components/Tables/common/tableUtils.ts +3 -16
  168. package/src/components/Tables/common/tests/SyTablePagination.spec.ts +170 -0
  169. package/src/components/Tables/common/tests/filterByRange.spec.ts +215 -0
  170. package/src/components/Tables/common/tests/tableFilterUtils.spec.ts +0 -14
  171. package/src/components/Tables/common/tests/tableUtils.spec.ts +7 -51
  172. package/src/components/Tables/common/types.ts +17 -6
  173. package/src/components/Tables/common/usePagination.ts +83 -0
  174. package/src/components/Tables/common/useTableCheckbox.ts +58 -0
  175. package/src/components/Tables/common/useTableHeaders.ts +88 -0
  176. package/src/components/Tables/common/useTableItems.ts +87 -0
  177. package/src/components/Tables/common/useTableOptions.ts +93 -0
  178. package/src/components/ToolbarContainer/ToolbarContainer.mdx +16 -0
  179. package/src/components/ToolbarContainer/ToolbarContainer.stories.ts +675 -0
  180. package/src/components/ToolbarContainer/ToolbarContainer.vue +128 -0
  181. package/src/components/ToolbarContainer/tests/ToolbarContainer.spec.ts +156 -0
  182. package/src/components/UserMenuBtn/UserMenuBtn.stories.ts +74 -0
  183. package/src/components/UserMenuBtn/UserMenuBtn.vue +19 -17
  184. package/src/components/index.ts +8 -6
  185. package/src/stories/Accessibilite/Aculturation/AuditDesignSystem.mdx +293 -20
  186. package/src/stories/Accessibilite/Aculturation/SensibilisationAccessibilite.mdx +448 -54
  187. package/src/stories/Accessibilite/Audit/RGAA.mdx +231 -23
  188. package/src/stories/Accessibilite/Avancement/Avancement.mdx +591 -7
  189. package/src/stories/Accessibilite/Avancement/Avancement.stories.ts +139 -38
  190. package/src/stories/Accessibilite/Introduction.mdx +258 -18
  191. package/src/stories/Accessibilite/KitDePreAudit/Echantillonnage.mdx +221 -31
  192. package/src/stories/Accessibilite/KitDePreAudit/Introduction.mdx +204 -22
  193. package/src/stories/Accessibilite/KitDePreAudit/Outils/Introduction.mdx +537 -24
  194. package/src/stories/Accessibilite/KitDePreAudit/Outils/LecteursDEcran.mdx +577 -70
  195. package/src/stories/Accessibilite/KitDePreAudit/Outils/Tanaguru.mdx +382 -31
  196. package/src/stories/Accessibilite/KitDePreAudit/Preaudit.mdx +419 -81
  197. package/src/stories/Accessibilite/Vuetify/Vuetify.mdx +132 -6
  198. package/src/stories/Accessibilite/Vuetify/Vuetify.stories.ts +370 -146
  199. package/src/stories/Accessibilite/Vuetify/VuetifyItems.ts +35 -57
  200. package/src/stories/Demarrer/Accueil.stories.ts +20 -5
  201. package/src/stories/DesignTokens/StylesTypographiques.mdx +10 -9
  202. package/src/stories/DesignTokens/StylesTypographiques.stories.new.ts +397 -0
  203. package/src/stories/DesignTokens/StylesTypographiques.stories.ts +397 -0
  204. package/src/stories/DesignTokens/TypographyDisplay.vue +155 -0
  205. package/src/stories/DesignTokens/vue-shims.d.ts +6 -0
  206. package/src/stories/GuideDuDev/LesBreackingChanges.mdx +0 -2
  207. package/src/stories/GuideDuDev/MigrationDepuisBridge.mdx +1 -1
  208. package/src/stories/GuideDuDev/MigrationDepuisVue2.mdx +1 -1
  209. package/src/stories/GuideDuDev/PortailAgent.mdx +10 -0
  210. package/src/stories/GuideDuDev/PortailAgent.stories.ts +506 -0
  211. package/src/stories/GuideDuDev/Theme.mdx +41 -0
  212. package/dist/SelectFilter-Cj-GW2Cc.js +0 -97
  213. package/dist/main-WDqeoGM-.js +0 -14788
  214. package/src/components/PaginatedTable/tests/__snapshots__/PaginatedTable.spec.ts.snap +0 -886
  215. package/src/components/Tables/SyServerTable/tests/__snapshots__/SyServerTable.spec.ts.snap +0 -521
  216. package/src/components/Tables/SyTable/tests/__snapshots__/SyTable.spec.ts.snap +0 -521
  217. 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
- await syTextField.vm.$emit('update:modelValue', 'test value')
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(2)
197
- expect(result.map(item => item.id)).toEqual([1, 2])
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(3)
204
- expect(result.map(item => item.id)).toEqual([1, 4, 6])
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 with =????', () => {
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(3)
230
- expect(result.map(item => item.id)).toEqual([1, 4, 6])
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([2, 5])
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
  }