fds-vue-core 8.1.0 → 8.2.0
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/fds-vue-core.cjs.js +56 -51
- package/dist/fds-vue-core.cjs.js.map +1 -1
- package/dist/fds-vue-core.css +1 -1
- package/dist/fds-vue-core.es.js +56 -51
- package/dist/fds-vue-core.es.js.map +1 -1
- package/dist/helpers/debounce.d.ts +8 -0
- package/dist/index.d.ts +3 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/components/Buttons/FdsButtonMinor/FdsButtonMinor.vue +6 -3
- package/src/components/FdsModal/FdsModal.vue +1 -1
- package/src/components/FdsPagination/FdsPagination.vue +2 -11
- package/src/components/FdsSearchSelect/FdsSearchSelect.vue +1 -8
- package/src/components/FdsSearchSelectPro/FdsSearchSelectPro.vue +20 -22
- package/src/helpers/debounce.ts +35 -0
- package/src/index.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fds-vue-core",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "FDS Vue Core Component Library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/fds-vue-core.cjs.js",
|
|
@@ -57,19 +57,19 @@
|
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@chromatic-com/storybook": "5.2.1",
|
|
59
59
|
"@intlify/unplugin-vue-i18n": "11.2.3",
|
|
60
|
-
"@storybook/addon-a11y": "10.4.
|
|
61
|
-
"@storybook/addon-docs": "10.4.
|
|
62
|
-
"@storybook/addon-vitest": "10.4.
|
|
63
|
-
"@storybook/vue3": "10.4.
|
|
64
|
-
"@storybook/vue3-vite": "10.4.
|
|
60
|
+
"@storybook/addon-a11y": "10.4.6",
|
|
61
|
+
"@storybook/addon-docs": "10.4.6",
|
|
62
|
+
"@storybook/addon-vitest": "10.4.6",
|
|
63
|
+
"@storybook/vue3": "10.4.6",
|
|
64
|
+
"@storybook/vue3-vite": "10.4.6",
|
|
65
65
|
"@tailwindcss/vite": "4.3.1",
|
|
66
66
|
"@types/node": "22.16.5",
|
|
67
67
|
"@vitejs/plugin-vue": "6.0.7",
|
|
68
|
-
"@vitest/browser": "
|
|
69
|
-
"fg-devkit": "1.9.
|
|
70
|
-
"storybook": "10.4.
|
|
68
|
+
"@vitest/browser": "4.1.9",
|
|
69
|
+
"fg-devkit": "1.9.1",
|
|
70
|
+
"storybook": "10.4.6",
|
|
71
71
|
"tsx": "4.22.4",
|
|
72
|
-
"vite": "7.3.
|
|
72
|
+
"vite": "7.3.5",
|
|
73
73
|
"vite-plugin-dts": "4.5.4",
|
|
74
74
|
"vite-plugin-vue-devtools": "8.1.3",
|
|
75
75
|
"vitest": "4.1.9",
|
|
@@ -29,12 +29,15 @@ const emit = defineEmits<{
|
|
|
29
29
|
|
|
30
30
|
const { disabled, href, target, rel, attrs } = useAttrsWithDefaults(props)
|
|
31
31
|
|
|
32
|
-
const rootClasses = computed(() => [
|
|
32
|
+
const rootClasses = computed(() => [
|
|
33
|
+
props.block ? 'flex w-full' : 'inline-flex shrink-0 self-center',
|
|
34
|
+
'transition-opacity duration-200',
|
|
35
|
+
])
|
|
33
36
|
|
|
34
37
|
const externalClass = computed(() => attrs.class)
|
|
35
38
|
|
|
36
39
|
const elBase =
|
|
37
|
-
'box-border appearance-none inline-flex items-
|
|
40
|
+
'box-border appearance-none inline-flex items-center justify-center w-fit min-h-0 shadow-none p-0.5 text-base select-none m-0 rounded-md text-left align-middle no-underline transition-[box-shadow,border-color,background-color] duration-200 font-main font-bold text-base leading-5 tracking-normal focus-visible:outline-dashed focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-blue-500'
|
|
38
41
|
|
|
39
42
|
const variantClasses = computed(() =>
|
|
40
43
|
props.invert
|
|
@@ -105,7 +108,7 @@ const componentAttrs = computed(() => {
|
|
|
105
108
|
<FdsIcon :class="iconFillClass" :name="icon" :size="iconSize" />
|
|
106
109
|
</span>
|
|
107
110
|
</template>
|
|
108
|
-
<span
|
|
111
|
+
<span>
|
|
109
112
|
{{ text }}
|
|
110
113
|
</span>
|
|
111
114
|
</component>
|
|
@@ -102,7 +102,7 @@ const footerClasses = computed(() => [
|
|
|
102
102
|
{
|
|
103
103
|
'sm:flex-row sm:justify-end': !props.alignLeftFooter,
|
|
104
104
|
'sm:flex-row sm:justify-start': props.alignLeftFooter,
|
|
105
|
-
'sticky bg-white bottom-0 shadow-[0px_-8px_16px_0px_rgba(255,255,255,0.59)] z-[2] -mx-6
|
|
105
|
+
'sticky bg-white bottom-0 shadow-[0px_-8px_16px_0px_rgba(255,255,255,0.59)] z-[2] -mx-6 p-6 mt-0!':
|
|
106
106
|
props.stickyFooter,
|
|
107
107
|
},
|
|
108
108
|
])
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref, watch } from 'vue'
|
|
3
3
|
import { useAttrsWithDefaults } from '../../composables/useAttrsWithDefaults'
|
|
4
|
+
import { debounce } from '../../helpers/debounce'
|
|
4
5
|
import { useFdsI18n } from '../../plugin/useFdsI18n'
|
|
5
6
|
import FdsButtonIcon from '../Buttons/FdsButtonIcon/FdsButtonIcon.vue'
|
|
6
7
|
import FdsSpinner from '../FdsSpinner/FdsSpinner.vue'
|
|
@@ -49,16 +50,6 @@ watch(
|
|
|
49
50
|
},
|
|
50
51
|
)
|
|
51
52
|
|
|
52
|
-
const debounce = <T extends (...args: any[]) => void>(fn: T, delay = 300) => {
|
|
53
|
-
let timer: ReturnType<typeof setTimeout>
|
|
54
|
-
return (...args: Parameters<T>) => {
|
|
55
|
-
clearTimeout(timer)
|
|
56
|
-
timer = setTimeout(() => {
|
|
57
|
-
fn(...args)
|
|
58
|
-
}, delay)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
53
|
const handlePageChange = debounce((event: Event) => {
|
|
63
54
|
const target = event.target as HTMLInputElement
|
|
64
55
|
const incomingPage = Number.parseInt(target.value)
|
|
@@ -81,7 +72,7 @@ const handlePageChange = debounce((event: Event) => {
|
|
|
81
72
|
|
|
82
73
|
internalValue.value = page
|
|
83
74
|
emit('paginate', { target: { id: inputId.value }, detail: page })
|
|
84
|
-
},
|
|
75
|
+
}, 300)
|
|
85
76
|
|
|
86
77
|
const handlePagination = (action: 'start' | 'prev' | 'next' | 'end') => {
|
|
87
78
|
let page = 0
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
PID_MASK_OPTIONS,
|
|
9
9
|
useIsPid,
|
|
10
10
|
} from '../../composables/useIsPid'
|
|
11
|
+
import { debounce } from '../../helpers/debounce'
|
|
11
12
|
import FdsPagination from '../FdsPagination/FdsPagination.vue'
|
|
12
13
|
import FdsSpinner from '../FdsSpinner/FdsSpinner.vue'
|
|
13
14
|
import FdsInput from '../Form/FdsInput/FdsInput.vue'
|
|
@@ -258,14 +259,6 @@ watch(
|
|
|
258
259
|
{ immediate: true },
|
|
259
260
|
)
|
|
260
261
|
|
|
261
|
-
const debounce = <T extends (...args: any[]) => void>(fn: T, delay: number) => {
|
|
262
|
-
let timeout: ReturnType<typeof setTimeout>
|
|
263
|
-
return (...args: Parameters<T>) => {
|
|
264
|
-
clearTimeout(timeout)
|
|
265
|
-
timeout = setTimeout(() => fn(...args), delay)
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
262
|
const debouncedEmitChange = debounce((value: string) => {
|
|
270
263
|
const formattedValue = formatPidWithDash(value)
|
|
271
264
|
emit('change', formattedValue)
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
PID_MASK_OPTIONS,
|
|
10
10
|
useIsPid,
|
|
11
11
|
} from '../../composables/useIsPid'
|
|
12
|
+
import { debounce } from '../../helpers/debounce'
|
|
12
13
|
import { useFdsI18n } from '../../plugin/useFdsI18n'
|
|
13
14
|
import FdsButtonIcon from '../Buttons/FdsButtonIcon/FdsButtonIcon.vue'
|
|
14
15
|
import FdsSpinner from '../FdsSpinner/FdsSpinner.vue'
|
|
@@ -286,28 +287,27 @@ watch(
|
|
|
286
287
|
{ immediate: true },
|
|
287
288
|
)
|
|
288
289
|
|
|
289
|
-
let changeTimeout: ReturnType<typeof setTimeout> | null = null
|
|
290
|
-
let inputTimeout: ReturnType<typeof setTimeout> | null = null
|
|
291
290
|
const isDebouncingChange = ref(false)
|
|
292
291
|
const isSearching = computed(() => isDebouncingChange.value || props.loading)
|
|
293
292
|
|
|
294
|
-
const debouncedEmitChange = (
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
isDebouncingChange.value = true
|
|
298
|
-
changeTimeout = setTimeout(() => {
|
|
299
|
-
const formattedValue = formatPidWithDash(value)
|
|
300
|
-
emit('change', formattedValue)
|
|
293
|
+
const debouncedEmitChange = debounce(
|
|
294
|
+
(value: string) => {
|
|
295
|
+
emit('change', formatPidWithDash(value))
|
|
301
296
|
isDebouncingChange.value = false
|
|
302
|
-
},
|
|
303
|
-
|
|
297
|
+
},
|
|
298
|
+
() => Math.max(0, props.debounceMs ?? 500),
|
|
299
|
+
)
|
|
304
300
|
|
|
305
|
-
const debouncedEmitInput = (
|
|
306
|
-
|
|
307
|
-
const delay = Math.max(0, props.debounceMs ?? 500)
|
|
308
|
-
inputTimeout = setTimeout(() => {
|
|
301
|
+
const debouncedEmitInput = debounce(
|
|
302
|
+
(ev: Event) => {
|
|
309
303
|
emit('input', ev)
|
|
310
|
-
},
|
|
304
|
+
},
|
|
305
|
+
() => Math.max(0, props.debounceMs ?? 500),
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
const scheduleDebouncedEmitChange = (value: string) => {
|
|
309
|
+
isDebouncingChange.value = true
|
|
310
|
+
debouncedEmitChange(value)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
watch(
|
|
@@ -318,7 +318,7 @@ watch(
|
|
|
318
318
|
}
|
|
319
319
|
filterAndPaginate()
|
|
320
320
|
if (isMultiple.value || selectedItem.value === null) {
|
|
321
|
-
|
|
321
|
+
scheduleDebouncedEmitChange(newValue)
|
|
322
322
|
}
|
|
323
323
|
},
|
|
324
324
|
)
|
|
@@ -443,9 +443,7 @@ function getCandidateMatchValues(item: Record<string, unknown>): string[] {
|
|
|
443
443
|
if (isDividerItem(item) && !props.dividerSelectable) return []
|
|
444
444
|
|
|
445
445
|
if (searchFields.value.length > 0) {
|
|
446
|
-
return searchFields.value
|
|
447
|
-
.map((key) => String(item[key] ?? '').trim())
|
|
448
|
-
.filter((value) => value.length > 0)
|
|
446
|
+
return searchFields.value.map((key) => String(item[key] ?? '').trim()).filter((value) => value.length > 0)
|
|
449
447
|
}
|
|
450
448
|
|
|
451
449
|
return [String(item.label ?? item.name ?? '').trim()].filter((value) => value.length > 0)
|
|
@@ -757,8 +755,8 @@ onMounted(() => {
|
|
|
757
755
|
|
|
758
756
|
onBeforeUnmount(() => {
|
|
759
757
|
window.removeEventListener('mouseup', onClickOutside as EventListener)
|
|
760
|
-
|
|
761
|
-
|
|
758
|
+
debouncedEmitChange.cancel()
|
|
759
|
+
debouncedEmitInput.cancel()
|
|
762
760
|
isDebouncingChange.value = false
|
|
763
761
|
const input = getInputElement()
|
|
764
762
|
if (input) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type DebouncedFunction<T extends (...args: never[]) => void> = ((...args: Parameters<T>) => void) & {
|
|
2
|
+
cancel: () => void
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a debounced function that delays invoking `fn` until after `delayMs` has elapsed
|
|
7
|
+
* since the last call. The returned function has a `cancel()` method to clear pending invocations.
|
|
8
|
+
*/
|
|
9
|
+
export function debounce<T extends (...args: never[]) => void>(
|
|
10
|
+
fn: T,
|
|
11
|
+
delayMs: number | (() => number),
|
|
12
|
+
): DebouncedFunction<T> {
|
|
13
|
+
let timeoutId: ReturnType<typeof setTimeout> | undefined
|
|
14
|
+
|
|
15
|
+
const debounced = (...args: Parameters<T>) => {
|
|
16
|
+
if (timeoutId !== undefined) {
|
|
17
|
+
clearTimeout(timeoutId)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const delay = typeof delayMs === 'function' ? delayMs() : delayMs
|
|
21
|
+
timeoutId = setTimeout(() => {
|
|
22
|
+
timeoutId = undefined
|
|
23
|
+
fn(...args)
|
|
24
|
+
}, delay)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
debounced.cancel = () => {
|
|
28
|
+
if (timeoutId !== undefined) {
|
|
29
|
+
clearTimeout(timeoutId)
|
|
30
|
+
timeoutId = undefined
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return debounced
|
|
35
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
import { useRouteScrollPositions } from './composables/useRouteScrollPositions'
|
|
75
75
|
import { useViewportBreakpoint } from './composables/useViewportBreakpoint'
|
|
76
76
|
import { capitalizeFirstLetter } from './helpers/capitalizeFirstLetter'
|
|
77
|
+
import { debounce } from './helpers/debounce'
|
|
77
78
|
import { useFileSizeValidation, useFileValidation } from './helpers/fileValidation'
|
|
78
79
|
import { FDS_VUE_CORE_I18N_KEY, type FdsI18nLike } from './plugin/i18n'
|
|
79
80
|
|
|
@@ -128,6 +129,7 @@ export {
|
|
|
128
129
|
export {
|
|
129
130
|
capitalizeFirstLetter,
|
|
130
131
|
clearUnsavedChanges,
|
|
132
|
+
debounce,
|
|
131
133
|
formatPidWithDash,
|
|
132
134
|
getExitGuardWizardId,
|
|
133
135
|
isPidString,
|
|
@@ -222,6 +224,8 @@ export default FdsVueCorePlugin
|
|
|
222
224
|
export type { FdsNodeShape, FdsTreeNode, FdsTreeViewProps, FdsTreeViewStyles } from './components/FdsTreeView/types'
|
|
223
225
|
|
|
224
226
|
// Export helper types
|
|
227
|
+
export type { DebouncedFunction } from './helpers/debounce'
|
|
228
|
+
|
|
225
229
|
export type { FileSizeValidationResult, FileValidationOptions, FileValidationResult } from './helpers/fileValidation'
|
|
226
230
|
|
|
227
231
|
// Button component types
|