fds-vue-core 6.2.6 → 6.2.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fds-vue-core",
3
- "version": "6.2.6",
3
+ "version": "6.2.7",
4
4
  "description": "FDS Vue Core Component Library",
5
5
  "type": "module",
6
6
  "main": "./dist/fds-vue-core.cjs.js",
@@ -39,23 +39,6 @@
39
39
  "engines": {
40
40
  "node": "^20.19.0 || >=22.12.0"
41
41
  },
42
- "scripts": {
43
- "serve": "vite",
44
- "build": "vite build && pnpm build:types && cp ./src/tokens.css ./dist/tokens.css && cp ./src/slot-styles.css ./dist/slot-styles.css && cp ./src/apply.css ./dist/apply.css && cp ./src/fonts.css ./dist/fonts.css && cp -r ./public/assets ./dist/assets && mkdir -p ./dist/assets/img/logos && cp -r ./src/assets/img/logos/* ./dist/assets/img/logos/",
45
- "build:types": "pnpm exec fgd typecheck --project tsconfig.build.json",
46
- "preview": "vite preview",
47
- "lint": "pnpm exec fgd lint --fix .",
48
- "lint:ts": "pnpm exec fgd typecheck --noEmit -p tsconfig.app.json",
49
- "lint:all": "pnpm lint && pnpm lint:ts",
50
- "format": "prettier --write src/",
51
- "prepublishOnly": "pnpm build",
52
- "storybook": "STORYBOOK=true storybook dev -p 6006",
53
- "build-storybook": "STORYBOOK=true storybook build",
54
- "yalc:publish": "pnpm build && yalc publish",
55
- "yalc:push": "pnpm build && yalc push",
56
- "serve:playground": "pnpm --dir playground-consumer dev",
57
- "lint-check": "pnpm exec fgd lint ."
58
- },
59
42
  "config": {
60
43
  "commitizen": {
61
44
  "path": "./scripts/cz/cz-adapter.cjs"
@@ -65,7 +48,7 @@
65
48
  "vue": "^3.5.25"
66
49
  },
67
50
  "dependencies": {
68
- "axios": "1.15.1",
51
+ "axios": "1.15.2",
69
52
  "date-fns": "4.1.0",
70
53
  "imask": "7.6.1",
71
54
  "tailwindcss": "4.2.4"
@@ -82,13 +65,13 @@
82
65
  "@vitejs/plugin-vue": "6.0.6",
83
66
  "@vitest/browser": "3.2.4",
84
67
  "eslint-plugin-storybook": "10.1.10",
85
- "fg-devkit": "1.5.1",
68
+ "fg-devkit": "1.6.1",
86
69
  "storybook": "10.2.12",
87
70
  "vite": "7.3.2",
88
71
  "vite-plugin-dts": "4.5.4",
89
72
  "vite-plugin-vue-devtools": "8.1.1",
90
73
  "vitest": "3.2.4",
91
- "vue": "3.5.32"
74
+ "vue": "3.5.33"
92
75
  },
93
76
  "knip": {
94
77
  "ignoreBinaries": [
@@ -101,22 +84,20 @@
101
84
  "src/apply.css"
102
85
  ]
103
86
  },
104
- "pnpm": {
105
- "overrides": {
106
- "follow-redirects@<=1.15.11": ">=1.16.0",
107
- "lodash@<=4.17.23": ">=4.18.0",
108
- "lodash@>=4.0.0 <=4.17.22": ">=4.17.23",
109
- "lodash@>=4.0.0 <=4.17.23": ">=4.18.0",
110
- "tmp@<=0.2.3": ">=0.2.4",
111
- "minimatch@>=10.0.0 <10.2.3": ">=10.2.3"
112
- },
113
- "onlyBuiltDependencies": [
114
- "@parcel/watcher",
115
- "core-js-pure",
116
- "esbuild",
117
- "lefthook",
118
- "vue-demi"
119
- ]
120
- },
121
- "packageManager": "pnpm@10.17.1"
122
- }
87
+ "scripts": {
88
+ "serve": "vite",
89
+ "build": "vite build && pnpm build:types && cp ./src/tokens.css ./dist/tokens.css && cp ./src/slot-styles.css ./dist/slot-styles.css && cp ./src/apply.css ./dist/apply.css && cp ./src/fonts.css ./dist/fonts.css && cp -r ./public/assets ./dist/assets && mkdir -p ./dist/assets/img/logos && cp -r ./src/assets/img/logos/* ./dist/assets/img/logos/",
90
+ "build:types": "pnpm exec fgd typecheck --project tsconfig.build.json",
91
+ "preview": "vite preview",
92
+ "lint": "pnpm exec fgd lint --fix .",
93
+ "lint:ts": "pnpm exec fgd typecheck --noEmit -p tsconfig.app.json",
94
+ "lint:all": "pnpm lint && pnpm lint:ts",
95
+ "format": "prettier --write src/",
96
+ "storybook": "STORYBOOK=true storybook dev -p 6006",
97
+ "build-storybook": "STORYBOOK=true storybook build",
98
+ "yalc:publish": "pnpm build && yalc publish",
99
+ "yalc:push": "pnpm build && yalc push",
100
+ "serve:playground": "pnpm --dir playground-consumer dev",
101
+ "lint-check": "pnpm exec fgd lint ."
102
+ }
103
+ }
@@ -71,6 +71,7 @@ const emit = defineEmits<{
71
71
 
72
72
  const dropdownVisible = ref(false)
73
73
  const searchTerm = ref('')
74
+ const bypassSearchFilter = ref(false)
74
75
  const selectedItem = ref<Record<string, unknown> | null>(null)
75
76
  const selectedItems = ref<Array<Record<string, unknown>>>([...(props.initialSelectedItems ?? [])])
76
77
  const showSelectedOnly = ref(false)
@@ -105,6 +106,7 @@ const {
105
106
  props,
106
107
  searchFields,
107
108
  searchTerm,
109
+ bypassSearchFilter,
108
110
  showSelectedOnly,
109
111
  selectedItems,
110
112
  isMultiple,
@@ -240,6 +242,7 @@ const listWrapperStyle = computed(() => {
240
242
  })
241
243
 
242
244
  const handleClear = () => {
245
+ bypassSearchFilter.value = false
243
246
  searchTerm.value = ''
244
247
  selectedItem.value = null
245
248
  selectedItems.value = []
@@ -350,6 +353,7 @@ const handleInput = (e: Event) => {
350
353
  const target = e.target as HTMLInputElement
351
354
  const { value } = target
352
355
 
356
+ bypassSearchFilter.value = false
353
357
  searchTerm.value = value
354
358
  dropdownVisible.value = true
355
359
  if (!isMultiple.value) {
@@ -532,9 +536,9 @@ const handleSingleSelection = (item: Record<string, unknown>) => {
532
536
  selectItem(item)
533
537
  dropdownVisible.value = false
534
538
 
535
- // Focus input after a short delay to prevent dropdown from reopening
539
+ // Blur input after selection so next interaction starts from a clean focus state.
536
540
  setTimeout(() => {
537
- focusInput()
541
+ handleBlurInput()
538
542
  }, 100)
539
543
  }
540
544
 
@@ -591,14 +595,19 @@ const handleDropdownScroll = (event: Event) => {
591
595
 
592
596
  const handleInputFocus = () => {
593
597
  inputHasFocus.value = true
594
- // Only open dropdown if an item hasn't been selected and there are items to show
595
- if ((isMultiple.value || !selectedItem.value) && displayedItems.value.length > 0) {
598
+ if (!isMultiple.value && !!selectedItem.value) {
599
+ bypassSearchFilter.value = true
600
+ filterAndPaginate()
601
+ }
602
+ // Open dropdown on focus whenever there are items to show.
603
+ if (displayedItems.value.length > 0) {
596
604
  dropdownVisible.value = true
597
605
  }
598
606
  }
599
607
 
600
608
  const handleInputBlur = () => {
601
609
  inputHasFocus.value = false
610
+ bypassSearchFilter.value = false
602
611
  }
603
612
 
604
613
  const handleListKeyDown = (e: KeyboardEvent) => {
@@ -831,7 +840,7 @@ defineExpose<{
831
840
  v-if="multiple && showSelectedToggle && selectedItems.length > 0"
832
841
  :label="`${selectedToggleLabel} (${selectedItems.length})`"
833
842
  :checked="showSelectedOnly"
834
- :disableFocusOutline="true"
843
+ :disablePseudoStates="true"
835
844
  @change="handleToggleSelectedOnly"
836
845
  />
837
846
  </div>
@@ -855,14 +864,19 @@ defineExpose<{
855
864
  :style="optionPaddingStyle(item)"
856
865
  v-html="handleMatchingString(item)"
857
866
  ></div>
858
- <div v-else :class="[labelClasses, listItemClasses]" :style="optionPaddingStyle(item)">
867
+ <div
868
+ v-else
869
+ @click="() => handleMultipleSelectionChange(item)"
870
+ :class="[labelClasses, listItemClasses]"
871
+ :style="optionPaddingStyle(item)"
872
+ >
859
873
  <FdsCheckbox
860
874
  v-if="multiple"
861
875
  :id="`search-select-radio-${index}`"
862
876
  :name="`search-select-checkbox-group-${inputId}`"
863
877
  :checked="isItemSelected(item)"
864
878
  :tabindex="-1"
865
- :disableFocusOutline="true"
879
+ :disablePseudoStates="true"
866
880
  class="mb-0!"
867
881
  @change="() => handleMultipleSelectionChange(item)"
868
882
  >
@@ -875,7 +889,7 @@ defineExpose<{
875
889
  :value="index"
876
890
  :checked="!!selectedItem && getItemIdentifier(selectedItem) === getItemIdentifier(item)"
877
891
  :tabindex="-1"
878
- :disableFocusOutline="true"
892
+ :disablePseudoStates="true"
879
893
  class="mb-0!"
880
894
  @change="() => handleSingleSelection(item)"
881
895
  @keydown.enter="(e) => handleClick(e, item)"
@@ -7,6 +7,7 @@ interface UseSearchSelectProItemsArgs {
7
7
  props: FdsSearchSelectProProps
8
8
  searchFields: ComputedRef<string[]>
9
9
  searchTerm: Ref<string>
10
+ bypassSearchFilter: Ref<boolean>
10
11
  showSelectedOnly: Ref<boolean>
11
12
  selectedItems: Ref<SearchSelectItem[]>
12
13
  isMultiple: ComputedRef<boolean>
@@ -17,6 +18,7 @@ export const useSearchSelectProItems = ({
17
18
  props,
18
19
  searchFields,
19
20
  searchTerm,
21
+ bypassSearchFilter,
20
22
  showSelectedOnly,
21
23
  selectedItems,
22
24
  isMultiple,
@@ -255,6 +257,7 @@ export const useSearchSelectProItems = ({
255
257
  }
256
258
 
257
259
  const matchesSearchTerm = (item: SearchSelectItem): boolean => {
260
+ if (bypassSearchFilter.value) return true
258
261
  if (!searchTerm.value) return true
259
262
 
260
263
  const searchValue = isPid.value ? searchTerm.value.replace(/\D/g, '') : searchTerm.value
@@ -274,6 +277,7 @@ export const useSearchSelectProItems = ({
274
277
  }
275
278
 
276
279
  const matchesDividerSearchTerm = (item: SearchSelectItem): boolean => {
280
+ if (bypassSearchFilter.value) return false
277
281
  if (!isDividerItem(item) || !searchTerm.value) return false
278
282
 
279
283
  const searchValue = isPid.value ? searchTerm.value.replace(/\D/g, '') : searchTerm.value
@@ -288,7 +292,7 @@ export const useSearchSelectProItems = ({
288
292
  }
289
293
 
290
294
  const filterWithDividerGroups = (sourceData: SearchSelectItem[]): SearchSelectItem[] => {
291
- if (!searchTerm.value) return sourceData
295
+ if (bypassSearchFilter.value || !searchTerm.value) return sourceData
292
296
 
293
297
  const matched: SearchSelectItem[] = []
294
298
  let currentDivider: SearchSelectItem | null = null
@@ -360,7 +364,10 @@ export const useSearchSelectProItems = ({
360
364
  displayedItems.value = effectiveLimit !== null ? matchedArray.slice(0, effectiveLimit) : matchedArray
361
365
  }
362
366
 
363
- onTotal(matchingItems.value.length)
367
+ const totalMatchingCount = matchingItems.value.filter(
368
+ (item) => props.dividerSelectable || !isDividerItem(item),
369
+ ).length
370
+ onTotal(totalMatchingCount)
364
371
  }
365
372
 
366
373
  const resetVisibleItemsLimit = () => {
@@ -25,7 +25,7 @@ const props = withDefaults(defineProps<FdsCheckboxProps>(), {
25
25
  class: undefined,
26
26
  dataTestid: undefined,
27
27
  inputClass: undefined,
28
- disableFocusOutline: false,
28
+ disablePseudoStates: false,
29
29
  })
30
30
 
31
31
  const emit = defineEmits<{
@@ -71,15 +71,19 @@ const externalClass = computed(() => props.class ?? attrs.class)
71
71
  const wrapperClasses = computed(() => ['block relative flex items-center mb-2 last:mb-0'])
72
72
  const innerWrapperClasses = computed(() => [
73
73
  'flex p-0.5 items-start rounded-md',
74
- 'hover:bg-blue_t-100 active:bg-blue_t-200',
75
- !props.disableFocusOutline &&
76
- '[&:has(:focus-visible)]:outline-2 [&:has(:focus-visible)]:outline-dashed [&:has(:focus-visible)]:-outline-offset-2 [&:has(:focus-visible)]:outline-blue-500',
74
+ !props.disablePseudoStates && 'hover:bg-blue_t-100 active:bg-blue_t-200',
75
+ props.disablePseudoStates
76
+ ? '[&:has(:focus)]:outline-none [&:has(:focus-visible)]:outline-none'
77
+ : '[&:has(:focus-visible)]:outline-2 [&:has(:focus-visible)]:outline-dashed [&:has(:focus-visible)]:-outline-offset-2 [&:has(:focus-visible)]:outline-blue-500',
77
78
  props.disabled && 'hover:bg-transparent active:bg-transparent',
78
79
  ])
79
80
 
80
81
  const inputClasses = computed(() => [
81
82
  'rounded-md transition-colors duration-200 accent-blue-500 m-[3px]',
82
- 'peer z-2 bg-white min-w-[18px] min-h-[18px] focus-visible:outline-none',
83
+ 'peer z-2 bg-white min-w-[18px] min-h-[18px]',
84
+ props.disablePseudoStates
85
+ ? 'focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0'
86
+ : 'focus-visible:outline-none',
83
87
  props.disabled && 'cursor-not-allowed',
84
88
  props.inputClass,
85
89
  ])
@@ -15,8 +15,8 @@ export interface FdsCheckboxProps {
15
15
  name?: string
16
16
  dataTestid?: string
17
17
  inputClass?: string | Record<string, boolean> | Array<string | Record<string, boolean>>
18
- // Disable focus outline - Example: Use when checkbox is inside a list that has a focus outline
19
- disableFocusOutline?: boolean
18
+ // Disable pseudo states (hover, active, focus, focus-visible)
19
+ disablePseudoStates?: boolean
20
20
  // Override event handlers with correct types
21
21
  onInput?: ((value: boolean) => void) | Array<(value: boolean) => void>
22
22
  onChange?: ((value: boolean) => void) | Array<(value: boolean) => void>
@@ -20,7 +20,7 @@ const props = withDefaults(defineProps<FdsRadioProps>(), {
20
20
  class: undefined,
21
21
  dataTestid: undefined,
22
22
  inputClass: undefined,
23
- disableFocusOutline: false,
23
+ disablePseudoStates: false,
24
24
  })
25
25
 
26
26
  const emit = defineEmits<{
@@ -104,14 +104,18 @@ function handleChange(e: Event) {
104
104
  const wrapperClasses = computed(() => ['block relative flex items-center mb-2 last:mb-0'])
105
105
  const innerWrapperClasses = computed(() => [
106
106
  'flex p-0.5 items-start rounded-l-xl rounded-r-md',
107
- 'hover:bg-blue_t-100 active:bg-blue_t-200',
108
- !props.disableFocusOutline &&
109
- '[&:has(:focus-visible)]:outline-2 [&:has(:focus-visible)]:outline-dashed [&:has(:focus-visible)]:-outline-offset-2 [&:has(:focus-visible)]:outline-blue-500',
107
+ !props.disablePseudoStates && 'hover:bg-blue_t-100 active:bg-blue_t-200',
108
+ props.disablePseudoStates
109
+ ? '[&:has(:focus)]:outline-none [&:has(:focus-visible)]:outline-none'
110
+ : '[&:has(:focus-visible)]:outline-2 [&:has(:focus-visible)]:outline-dashed [&:has(:focus-visible)]:-outline-offset-2 [&:has(:focus-visible)]:outline-blue-500',
110
111
  props.disabled && 'hover:bg-transparent active:bg-transparent',
111
112
  ])
112
113
 
113
114
  const inputClasses = computed(() => [
114
- 'peer z-2 bg-white min-w-[20px] min-h-[20px] focus-visible:outline-none rounded-full accent-blue-500',
115
+ 'peer z-2 bg-white min-w-[20px] min-h-[20px] rounded-full accent-blue-500',
116
+ props.disablePseudoStates
117
+ ? 'focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0'
118
+ : 'focus-visible:outline-none',
115
119
  props.disabled && 'cursor-not-allowed',
116
120
  props.inputClass,
117
121
  ])
@@ -14,8 +14,8 @@ export interface FdsRadioProps {
14
14
  tabindex?: number | string
15
15
  autofocus?: boolean
16
16
  inputClass?: string | Record<string, boolean> | Array<string | Record<string, boolean>>
17
- // Disable focus outline - Example: Use when radio is inside a list that has a focus outline
18
- disableFocusOutline?: boolean
17
+ // Disable pseudo states (hover, active, focus, focus-visible)
18
+ disablePseudoStates?: boolean
19
19
  // Override event handlers with correct types
20
20
  onInput?:
21
21
  | ((value: string | number | boolean | null) => void)