@nuxt/ui 2.18.7 → 2.19.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/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +3 -3
- package/dist/runtime/components/data/Table.vue +82 -27
- package/dist/runtime/components/data/Table.vue.d.ts +45 -37
- package/dist/runtime/components/elements/AvatarGroup.js +2 -2
- package/dist/runtime/components/elements/Carousel.vue +1 -1
- package/dist/runtime/components/elements/Dropdown.vue +6 -2
- package/dist/runtime/components/elements/MeterGroup.d.ts +1 -1
- package/dist/runtime/components/elements/Progress.vue +1 -1
- package/dist/runtime/components/forms/Checkbox.vue.d.ts +1 -1
- package/dist/runtime/components/forms/Form.vue +104 -43
- package/dist/runtime/components/forms/Form.vue.d.ts +5 -3
- package/dist/runtime/components/forms/Input.vue +5 -2
- package/dist/runtime/components/forms/Input.vue.d.ts +3 -0
- package/dist/runtime/components/forms/InputMenu.vue +419 -8
- package/dist/runtime/components/forms/InputMenu.vue.d.ts +19 -0
- package/dist/runtime/components/forms/Radio.vue.d.ts +1 -1
- package/dist/runtime/components/forms/RadioGroup.vue +3 -4
- package/dist/runtime/components/forms/RadioGroup.vue.d.ts +1 -1
- package/dist/runtime/components/forms/SelectMenu.vue +501 -11
- package/dist/runtime/components/forms/SelectMenu.vue.d.ts +30 -2
- package/dist/runtime/components/forms/Textarea.vue +7 -4
- package/dist/runtime/components/forms/Textarea.vue.d.ts +3 -0
- package/dist/runtime/components/layout/Divider.vue +1 -1
- package/dist/runtime/components/layout/Divider.vue.d.ts +5 -2
- package/dist/runtime/components/navigation/CommandPalette.vue +1 -1
- package/dist/runtime/components/navigation/CommandPalette.vue.d.ts +1 -1
- package/dist/runtime/components/navigation/CommandPaletteGroup.vue.d.ts +1 -1
- package/dist/runtime/components/navigation/Pagination.vue +4 -4
- package/dist/runtime/components/navigation/Pagination.vue.d.ts +1 -1
- package/dist/runtime/components/navigation/Tabs.vue +1 -1
- package/dist/runtime/components/navigation/VerticalNavigation.vue.d.ts +6 -2
- package/dist/runtime/components/overlays/Modal.vue +1 -1
- package/dist/runtime/components/overlays/Notifications.vue +1 -1
- package/dist/runtime/components/overlays/Popover.vue +6 -2
- package/dist/runtime/composables/defineShortcuts.js +1 -1
- package/dist/runtime/composables/useButtonGroup.d.ts +1 -1
- package/dist/runtime/composables/useUI.js +1 -1
- package/dist/runtime/plugins/modals.js +1 -1
- package/dist/runtime/plugins/slideovers.js +1 -1
- package/dist/runtime/types/accordion.d.ts +1 -1
- package/dist/runtime/types/alert.d.ts +4 -4
- package/dist/runtime/types/avatar.d.ts +3 -3
- package/dist/runtime/types/badge.d.ts +3 -3
- package/dist/runtime/types/button.d.ts +3 -5
- package/dist/runtime/types/chip.d.ts +2 -2
- package/dist/runtime/types/command-palette.d.ts +2 -2
- package/dist/runtime/types/component.d.ts +3 -3
- package/dist/runtime/types/divider.d.ts +3 -3
- package/dist/runtime/types/dropdown.d.ts +1 -1
- package/dist/runtime/types/form-group.d.ts +2 -2
- package/dist/runtime/types/form.d.ts +7 -2
- package/dist/runtime/types/index.d.ts +1 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/input.d.ts +3 -3
- package/dist/runtime/types/kbd.d.ts +2 -2
- package/dist/runtime/types/meter.d.ts +2 -2
- package/dist/runtime/types/modal.d.ts +2 -2
- package/dist/runtime/types/notification.d.ts +1 -1
- package/dist/runtime/types/progress.d.ts +2 -2
- package/dist/runtime/types/range.d.ts +3 -3
- package/dist/runtime/types/select.d.ts +3 -3
- package/dist/runtime/types/table.d.ts +18 -0
- package/dist/runtime/types/textarea.d.ts +3 -3
- package/dist/runtime/types/toggle.d.ts +3 -3
- package/dist/runtime/types/utils.d.ts +2 -2
- package/dist/runtime/ui.config/data/table.d.ts +1 -0
- package/dist/runtime/ui.config/data/table.js +1 -0
- package/dist/runtime/ui.config/elements/avatar.js +15 -15
- package/dist/runtime/ui.config/elements/button.js +25 -25
- package/dist/runtime/ui.config/elements/buttonGroup.js +1 -1
- package/dist/runtime/ui.config/elements/chip.js +5 -5
- package/dist/runtime/ui.config/elements/meter.js +20 -20
- package/dist/runtime/ui.config/elements/meterGroup.js +1 -1
- package/dist/runtime/ui.config/elements/progress.js +18 -18
- package/dist/runtime/ui.config/forms/formGroup.js +5 -6
- package/dist/runtime/ui.config/forms/input.js +40 -40
- package/dist/runtime/ui.config/forms/inputMenu.d.ts +6 -0
- package/dist/runtime/ui.config/forms/inputMenu.js +7 -1
- package/dist/runtime/ui.config/forms/range.js +20 -20
- package/dist/runtime/ui.config/forms/selectMenu.d.ts +9 -0
- package/dist/runtime/ui.config/forms/selectMenu.js +10 -1
- package/dist/runtime/ui.config/forms/toggle.js +20 -20
- package/dist/runtime/ui.config/layout/divider.d.ts +1 -0
- package/dist/runtime/ui.config/layout/divider.js +12 -11
- package/dist/runtime/ui.config/navigation/horizontalNavigation.js +1 -1
- package/dist/runtime/ui.config/navigation/verticalNavigation.js +1 -1
- package/dist/runtime/ui.config/popper.js +0 -1
- package/dist/runtime/utils/colors.js +7 -7
- package/dist/runtime/utils/index.js +4 -4
- package/dist/runtime/utils/lodash.js +1 -1
- package/package.json +21 -19
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
/>
|
|
64
64
|
<span v-else-if="option.chip" :class="uiMenu.option.chip.base" :style="{ background: `#${option.chip}` }" />
|
|
65
65
|
|
|
66
|
-
<span class="truncate">{{ ['string', 'number'].includes(typeof option) ? option : option
|
|
66
|
+
<span class="truncate">{{ ['string', 'number'].includes(typeof option) ? option : accessor(option, optionAttribute) }}</span>
|
|
67
67
|
</slot>
|
|
68
68
|
</div>
|
|
69
69
|
|
|
@@ -75,12 +75,12 @@
|
|
|
75
75
|
|
|
76
76
|
<p v-if="query && !filteredOptions.length" :class="uiMenu.option.empty">
|
|
77
77
|
<slot name="option-empty" :query="query">
|
|
78
|
-
|
|
78
|
+
{{ uiMenu.default.optionEmpty.label.replace('{query}', query) }}
|
|
79
79
|
</slot>
|
|
80
80
|
</p>
|
|
81
81
|
<p v-else-if="!filteredOptions.length" :class="uiMenu.empty">
|
|
82
82
|
<slot name="empty" :query="query">
|
|
83
|
-
|
|
83
|
+
{{ uiMenu.default.empty.label }}
|
|
84
84
|
</slot>
|
|
85
85
|
</p>
|
|
86
86
|
</HComboboxOptions>
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
</template>
|
|
92
92
|
|
|
93
93
|
<script>
|
|
94
|
-
import { ref, computed, toRef, watch, defineComponent } from "vue";
|
|
94
|
+
import { ref, computed, toRef, watch, defineComponent, toRaw } from "vue";
|
|
95
95
|
import {
|
|
96
96
|
Combobox as HCombobox,
|
|
97
97
|
ComboboxButton as HComboboxButton,
|
|
@@ -297,9 +297,9 @@ export default defineComponent({
|
|
|
297
297
|
}
|
|
298
298
|
if (props.valueAttribute) {
|
|
299
299
|
const option = options.value.find((option2) => option2[props.valueAttribute] === props.modelValue);
|
|
300
|
-
return option ? option
|
|
300
|
+
return option ? accessor(option, props.optionAttribute) : null;
|
|
301
301
|
} else {
|
|
302
|
-
return ["string", "number"].includes(typeof props.modelValue) ? props.modelValue : props.modelValue
|
|
302
|
+
return ["string", "number"].includes(typeof props.modelValue) ? props.modelValue : accessor(props.modelValue, props.optionAttribute);
|
|
303
303
|
}
|
|
304
304
|
});
|
|
305
305
|
const inputClass = computed(() => {
|
|
@@ -372,17 +372,421 @@ export default defineComponent({
|
|
|
372
372
|
}, [], {
|
|
373
373
|
lazy: props.searchLazy
|
|
374
374
|
});
|
|
375
|
+
function escapeRegExp(string) {
|
|
376
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\<script lang="ts">
|
|
377
|
+
import { ref, computed, toRef, watch, defineComponent, toRaw } from 'vue'
|
|
378
|
+
import type { PropType } from 'vue'
|
|
379
|
+
import {
|
|
380
|
+
Combobox as HCombobox,
|
|
381
|
+
ComboboxButton as HComboboxButton,
|
|
382
|
+
ComboboxOptions as HComboboxOptions,
|
|
383
|
+
ComboboxOption as HComboboxOption,
|
|
384
|
+
ComboboxInput as HComboboxInput,
|
|
385
|
+
provideUseId
|
|
386
|
+
} from '@headlessui/vue'
|
|
387
|
+
import { computedAsync, useDebounceFn } from '@vueuse/core'
|
|
388
|
+
import { defu } from 'defu'
|
|
389
|
+
import { twMerge, twJoin } from 'tailwind-merge'
|
|
390
|
+
import UIcon from '../elements/Icon.vue'
|
|
391
|
+
import UAvatar from '../elements/Avatar.vue'
|
|
392
|
+
import { useUI } from '../../composables/useUI'
|
|
393
|
+
import { usePopper } from '../../composables/usePopper'
|
|
394
|
+
import { useFormGroup } from '../../composables/useFormGroup'
|
|
395
|
+
import { get, mergeConfig } from '../../utils'
|
|
396
|
+
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
|
|
397
|
+
import type { InputSize, InputColor, InputVariant, PopperOptions, Strategy, DeepPartial } from '../../types/index'
|
|
398
|
+
// @ts-expect-error
|
|
399
|
+
import appConfig from '#build/app.config'
|
|
400
|
+
import { input, inputMenu } from '#ui/ui.config'
|
|
401
|
+
import { useId } from '#imports'
|
|
402
|
+
|
|
403
|
+
const config = mergeConfig<typeof input>(appConfig.ui.strategy, appConfig.ui.input, input)
|
|
404
|
+
|
|
405
|
+
const configMenu = mergeConfig<typeof inputMenu>(appConfig.ui.strategy, appConfig.ui.inputMenu, inputMenu)
|
|
406
|
+
|
|
407
|
+
export default defineComponent({
|
|
408
|
+
components: {
|
|
409
|
+
HCombobox,
|
|
410
|
+
HComboboxButton,
|
|
411
|
+
HComboboxOptions,
|
|
412
|
+
HComboboxOption,
|
|
413
|
+
HComboboxInput,
|
|
414
|
+
UIcon,
|
|
415
|
+
UAvatar
|
|
416
|
+
},
|
|
417
|
+
inheritAttrs: false,
|
|
418
|
+
props: {
|
|
419
|
+
modelValue: {
|
|
420
|
+
type: [String, Number, Object, Array] as PropType<string | number | object | Array<any> | null>,
|
|
421
|
+
default: ''
|
|
422
|
+
},
|
|
423
|
+
query: {
|
|
424
|
+
type: String,
|
|
425
|
+
default: null
|
|
426
|
+
},
|
|
427
|
+
by: {
|
|
428
|
+
type: String,
|
|
429
|
+
default: undefined
|
|
430
|
+
},
|
|
431
|
+
options: {
|
|
432
|
+
type: Array as PropType<{ [key: string]: any, disabled?: boolean }[] | string[]>,
|
|
433
|
+
default: () => []
|
|
434
|
+
},
|
|
435
|
+
id: {
|
|
436
|
+
type: String,
|
|
437
|
+
default: null
|
|
438
|
+
},
|
|
439
|
+
name: {
|
|
440
|
+
type: String,
|
|
441
|
+
default: null
|
|
442
|
+
},
|
|
443
|
+
required: {
|
|
444
|
+
type: Boolean,
|
|
445
|
+
default: false
|
|
446
|
+
},
|
|
447
|
+
icon: {
|
|
448
|
+
type: String,
|
|
449
|
+
default: null
|
|
450
|
+
},
|
|
451
|
+
loadingIcon: {
|
|
452
|
+
type: String,
|
|
453
|
+
default: () => config.default.loadingIcon
|
|
454
|
+
},
|
|
455
|
+
leadingIcon: {
|
|
456
|
+
type: String,
|
|
457
|
+
default: null
|
|
458
|
+
},
|
|
459
|
+
trailingIcon: {
|
|
460
|
+
type: String,
|
|
461
|
+
default: () => configMenu.default.trailingIcon
|
|
462
|
+
},
|
|
463
|
+
trailing: {
|
|
464
|
+
type: Boolean,
|
|
465
|
+
default: false
|
|
466
|
+
},
|
|
467
|
+
leading: {
|
|
468
|
+
type: Boolean,
|
|
469
|
+
default: false
|
|
470
|
+
},
|
|
471
|
+
loading: {
|
|
472
|
+
type: Boolean,
|
|
473
|
+
default: false
|
|
474
|
+
},
|
|
475
|
+
selectedIcon: {
|
|
476
|
+
type: String,
|
|
477
|
+
default: () => configMenu.default.selectedIcon
|
|
478
|
+
},
|
|
479
|
+
disabled: {
|
|
480
|
+
type: Boolean,
|
|
481
|
+
default: false
|
|
482
|
+
},
|
|
483
|
+
nullable: {
|
|
484
|
+
type: Boolean,
|
|
485
|
+
default: false
|
|
486
|
+
},
|
|
487
|
+
placeholder: {
|
|
488
|
+
type: String,
|
|
489
|
+
default: null
|
|
490
|
+
},
|
|
491
|
+
padded: {
|
|
492
|
+
type: Boolean,
|
|
493
|
+
default: true
|
|
494
|
+
},
|
|
495
|
+
size: {
|
|
496
|
+
type: String as PropType<InputSize>,
|
|
497
|
+
default: null,
|
|
498
|
+
validator(value: string) {
|
|
499
|
+
return Object.keys(config.size).includes(value)
|
|
500
|
+
}
|
|
501
|
+
},
|
|
502
|
+
color: {
|
|
503
|
+
type: String as PropType<InputColor>,
|
|
504
|
+
default: () => config.default.color,
|
|
505
|
+
validator(value: string) {
|
|
506
|
+
return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
variant: {
|
|
510
|
+
type: String as PropType<InputVariant>,
|
|
511
|
+
default: () => config.default.variant,
|
|
512
|
+
validator(value: string) {
|
|
513
|
+
return [
|
|
514
|
+
...Object.keys(config.variant),
|
|
515
|
+
...Object.values(config.color).flatMap(value => Object.keys(value))
|
|
516
|
+
].includes(value)
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
optionAttribute: {
|
|
520
|
+
type: String,
|
|
521
|
+
default: 'label'
|
|
522
|
+
},
|
|
523
|
+
valueAttribute: {
|
|
524
|
+
type: String,
|
|
525
|
+
default: null
|
|
526
|
+
},
|
|
527
|
+
search: {
|
|
528
|
+
type: Function as PropType<((query: string) => Promise<any[]> | any[])>,
|
|
529
|
+
default: undefined
|
|
530
|
+
},
|
|
531
|
+
searchAttributes: {
|
|
532
|
+
type: Array,
|
|
533
|
+
default: null
|
|
534
|
+
},
|
|
535
|
+
searchLazy: {
|
|
536
|
+
type: Boolean,
|
|
537
|
+
default: false
|
|
538
|
+
},
|
|
539
|
+
debounce: {
|
|
540
|
+
type: Number,
|
|
541
|
+
default: 200
|
|
542
|
+
},
|
|
543
|
+
popper: {
|
|
544
|
+
type: Object as PropType<PopperOptions>,
|
|
545
|
+
default: () => ({})
|
|
546
|
+
},
|
|
547
|
+
inputClass: {
|
|
548
|
+
type: String,
|
|
549
|
+
default: null
|
|
550
|
+
},
|
|
551
|
+
class: {
|
|
552
|
+
type: [String, Object, Array] as PropType<any>,
|
|
553
|
+
default: () => ''
|
|
554
|
+
},
|
|
555
|
+
ui: {
|
|
556
|
+
type: Object as PropType<DeepPartial<typeof config> & { strategy?: Strategy }>,
|
|
557
|
+
default: () => ({})
|
|
558
|
+
},
|
|
559
|
+
uiMenu: {
|
|
560
|
+
type: Object as PropType<DeepPartial<typeof configMenu> & { strategy?: Strategy }>,
|
|
561
|
+
default: () => ({})
|
|
562
|
+
}
|
|
563
|
+
},
|
|
564
|
+
emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],
|
|
565
|
+
setup(props, { emit, slots }) {
|
|
566
|
+
const { ui, attrs } = useUI('input', toRef(props, 'ui'), config, toRef(props, 'class'))
|
|
567
|
+
const { ui: uiMenu } = useUI('inputMenu', toRef(props, 'uiMenu'), configMenu)
|
|
568
|
+
|
|
569
|
+
const popper = computed<PopperOptions>(() => defu({}, props.popper, uiMenu.value.popper as PopperOptions))
|
|
570
|
+
|
|
571
|
+
const [trigger, container] = usePopper(popper.value)
|
|
572
|
+
|
|
573
|
+
const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props })
|
|
574
|
+
const { emitFormBlur, emitFormChange, inputId, color, size: sizeFormGroup, name } = useFormGroup(props, config)
|
|
575
|
+
|
|
576
|
+
const size = computed(() => sizeButtonGroup.value ?? sizeFormGroup.value)
|
|
577
|
+
|
|
578
|
+
const internalQuery = ref('')
|
|
579
|
+
const query = computed({
|
|
580
|
+
get() {
|
|
581
|
+
return props.query ?? internalQuery.value
|
|
582
|
+
},
|
|
583
|
+
set(value) {
|
|
584
|
+
internalQuery.value = value
|
|
585
|
+
emit('update:query', value)
|
|
586
|
+
}
|
|
587
|
+
})
|
|
588
|
+
|
|
589
|
+
const label = computed(() => {
|
|
590
|
+
if (!props.modelValue) {
|
|
591
|
+
return
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (props.valueAttribute) {
|
|
595
|
+
const option = options.value.find(option => option[props.valueAttribute] === props.modelValue)
|
|
596
|
+
return option ? accessor(option, props.optionAttribute) : null
|
|
597
|
+
} else {
|
|
598
|
+
return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : accessor(props.modelValue as Record<string, any>, props.optionAttribute)
|
|
599
|
+
}
|
|
600
|
+
})
|
|
601
|
+
|
|
602
|
+
const inputClass = computed(() => {
|
|
603
|
+
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
|
|
604
|
+
|
|
605
|
+
return twMerge(twJoin(
|
|
606
|
+
ui.value.base,
|
|
607
|
+
ui.value.form,
|
|
608
|
+
rounded.value,
|
|
609
|
+
ui.value.placeholder,
|
|
610
|
+
ui.value.size[size.value],
|
|
611
|
+
props.padded ? ui.value.padding[size.value] : 'p-0',
|
|
612
|
+
variant?.replaceAll('{color}', color.value),
|
|
613
|
+
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
|
|
614
|
+
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
|
|
615
|
+
), props.inputClass)
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
const isLeading = computed(() => {
|
|
619
|
+
return (props.icon && props.leading) || (props.icon && !props.trailing) || (props.loading && !props.trailing) || props.leadingIcon
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
const isTrailing = computed(() => {
|
|
623
|
+
return (props.icon && props.trailing) || (props.loading && props.trailing) || props.trailingIcon
|
|
624
|
+
})
|
|
625
|
+
|
|
626
|
+
const leadingIconName = computed(() => {
|
|
627
|
+
if (props.loading) {
|
|
628
|
+
return props.loadingIcon
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return props.leadingIcon || props.icon
|
|
632
|
+
})
|
|
633
|
+
|
|
634
|
+
const trailingIconName = computed(() => {
|
|
635
|
+
if (props.loading && !isLeading.value) {
|
|
636
|
+
return props.loadingIcon
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
return props.trailingIcon || props.icon
|
|
640
|
+
})
|
|
641
|
+
|
|
642
|
+
const leadingWrapperIconClass = computed(() => {
|
|
643
|
+
return twJoin(
|
|
644
|
+
ui.value.icon.leading.wrapper,
|
|
645
|
+
ui.value.icon.leading.pointer,
|
|
646
|
+
ui.value.icon.leading.padding[size.value]
|
|
647
|
+
)
|
|
648
|
+
})
|
|
649
|
+
|
|
650
|
+
const leadingIconClass = computed(() => {
|
|
651
|
+
return twJoin(
|
|
652
|
+
ui.value.icon.base,
|
|
653
|
+
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
|
|
654
|
+
ui.value.icon.size[size.value],
|
|
655
|
+
props.loading && ui.value.icon.loading
|
|
656
|
+
)
|
|
657
|
+
})
|
|
658
|
+
|
|
659
|
+
const trailingWrapperIconClass = computed(() => {
|
|
660
|
+
return twJoin(
|
|
661
|
+
ui.value.icon.trailing.wrapper,
|
|
662
|
+
ui.value.icon.trailing.padding[size.value]
|
|
663
|
+
)
|
|
664
|
+
})
|
|
665
|
+
|
|
666
|
+
const trailingIconClass = computed(() => {
|
|
667
|
+
return twJoin(
|
|
668
|
+
ui.value.icon.base,
|
|
669
|
+
color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
|
|
670
|
+
ui.value.icon.size[size.value],
|
|
671
|
+
props.loading && !isLeading.value && ui.value.icon.loading
|
|
672
|
+
)
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
const debouncedSearch = props.search && typeof props.search === 'function' ? useDebounceFn(props.search, props.debounce) : undefined
|
|
676
|
+
|
|
677
|
+
const options = computedAsync(async () => {
|
|
678
|
+
if (debouncedSearch) {
|
|
679
|
+
return await debouncedSearch(query.value)
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
return props.options || []
|
|
683
|
+
}, [], {
|
|
684
|
+
lazy: props.searchLazy
|
|
685
|
+
})
|
|
686
|
+
|
|
687
|
+
function escapeRegExp(string: string) {
|
|
688
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const filteredOptions = computed(() => {
|
|
692
|
+
if (!query.value || debouncedSearch) {
|
|
693
|
+
return options.value
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const escapedQuery = escapeRegExp(query.value)
|
|
697
|
+
|
|
698
|
+
return options.value.filter((option: any) => {
|
|
699
|
+
return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute: any) => {
|
|
700
|
+
if (['string', 'number'].includes(typeof option)) {
|
|
701
|
+
return String(option).search(new RegExp(escapedQuery, 'i')) !== -1
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const child = get(option, searchAttribute)
|
|
705
|
+
|
|
706
|
+
return child !== null && child !== undefined && String(child).search(new RegExp(escapedQuery, 'i')) !== -1
|
|
707
|
+
})
|
|
708
|
+
})
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
watch(container, (value) => {
|
|
712
|
+
if (value) {
|
|
713
|
+
emit('open')
|
|
714
|
+
} else {
|
|
715
|
+
emit('close')
|
|
716
|
+
emitFormBlur()
|
|
717
|
+
}
|
|
718
|
+
})
|
|
719
|
+
|
|
720
|
+
function onUpdate(value: any) {
|
|
721
|
+
query.value = ''
|
|
722
|
+
|
|
723
|
+
if (toRaw(props.modelValue) === toRaw(value)) {
|
|
724
|
+
return
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
emit('update:modelValue', value)
|
|
728
|
+
emit('change', value)
|
|
729
|
+
|
|
730
|
+
emitFormChange()
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function accessor<T extends Record<string, any>>(obj: T, key: string) {
|
|
734
|
+
return get(obj, key)
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function onQueryChange(event: any) {
|
|
738
|
+
query.value = event.target.value
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
provideUseId(() => useId())
|
|
742
|
+
|
|
743
|
+
return {
|
|
744
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
745
|
+
ui,
|
|
746
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
747
|
+
uiMenu,
|
|
748
|
+
attrs,
|
|
749
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
750
|
+
name,
|
|
751
|
+
inputId,
|
|
752
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
753
|
+
popper,
|
|
754
|
+
trigger,
|
|
755
|
+
container,
|
|
756
|
+
label,
|
|
757
|
+
isLeading,
|
|
758
|
+
isTrailing,
|
|
759
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
760
|
+
inputClass,
|
|
761
|
+
leadingIconName,
|
|
762
|
+
leadingIconClass,
|
|
763
|
+
leadingWrapperIconClass,
|
|
764
|
+
trailingIconName,
|
|
765
|
+
trailingIconClass,
|
|
766
|
+
trailingWrapperIconClass,
|
|
767
|
+
filteredOptions,
|
|
768
|
+
// eslint-disable-next-line vue/no-dupe-keys
|
|
769
|
+
query,
|
|
770
|
+
accessor,
|
|
771
|
+
onUpdate,
|
|
772
|
+
onQueryChange
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
})
|
|
776
|
+
</script>");
|
|
777
|
+
}
|
|
375
778
|
const filteredOptions = computed(() => {
|
|
376
779
|
if (!query.value || debouncedSearch) {
|
|
377
780
|
return options.value;
|
|
378
781
|
}
|
|
782
|
+
const escapedQuery = escapeRegExp(query.value);
|
|
379
783
|
return options.value.filter((option) => {
|
|
380
784
|
return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute) => {
|
|
381
785
|
if (["string", "number"].includes(typeof option)) {
|
|
382
|
-
return String(option).search(new RegExp(
|
|
786
|
+
return String(option).search(new RegExp(escapedQuery, "i")) !== -1;
|
|
383
787
|
}
|
|
384
788
|
const child = get(option, searchAttribute);
|
|
385
|
-
return child !== null && child !== void 0 && String(child).search(new RegExp(
|
|
789
|
+
return child !== null && child !== void 0 && String(child).search(new RegExp(escapedQuery, "i")) !== -1;
|
|
386
790
|
});
|
|
387
791
|
});
|
|
388
792
|
});
|
|
@@ -396,10 +800,16 @@ export default defineComponent({
|
|
|
396
800
|
});
|
|
397
801
|
function onUpdate(value) {
|
|
398
802
|
query.value = "";
|
|
803
|
+
if (toRaw(props.modelValue) === toRaw(value)) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
399
806
|
emit("update:modelValue", value);
|
|
400
807
|
emit("change", value);
|
|
401
808
|
emitFormChange();
|
|
402
809
|
}
|
|
810
|
+
function accessor(obj, key) {
|
|
811
|
+
return get(obj, key);
|
|
812
|
+
}
|
|
403
813
|
function onQueryChange(event) {
|
|
404
814
|
query.value = event.target.value;
|
|
405
815
|
}
|
|
@@ -431,6 +841,7 @@ export default defineComponent({
|
|
|
431
841
|
filteredOptions,
|
|
432
842
|
// eslint-disable-next-line vue/no-dupe-keys
|
|
433
843
|
query,
|
|
844
|
+
accessor,
|
|
434
845
|
onUpdate,
|
|
435
846
|
onQueryChange
|
|
436
847
|
};
|
|
@@ -162,6 +162,12 @@ declare const configMenu: {
|
|
|
162
162
|
default: {
|
|
163
163
|
selectedIcon: string;
|
|
164
164
|
trailingIcon: string;
|
|
165
|
+
empty: {
|
|
166
|
+
label: string;
|
|
167
|
+
};
|
|
168
|
+
optionEmpty: {
|
|
169
|
+
label: string;
|
|
170
|
+
};
|
|
165
171
|
};
|
|
166
172
|
arrow: {
|
|
167
173
|
ring: string;
|
|
@@ -478,6 +484,12 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
478
484
|
default: {
|
|
479
485
|
selectedIcon: string;
|
|
480
486
|
trailingIcon: string;
|
|
487
|
+
empty: {
|
|
488
|
+
label: string;
|
|
489
|
+
};
|
|
490
|
+
optionEmpty: {
|
|
491
|
+
label: string;
|
|
492
|
+
};
|
|
481
493
|
};
|
|
482
494
|
arrow: {
|
|
483
495
|
ring: string;
|
|
@@ -508,6 +520,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
508
520
|
trailingWrapperIconClass: import("vue").ComputedRef<string>;
|
|
509
521
|
filteredOptions: import("vue").ComputedRef<any[]>;
|
|
510
522
|
query: import("vue").WritableComputedRef<string, string>;
|
|
523
|
+
accessor: <T extends Record<string, any>>(obj: T, key: string) => any;
|
|
511
524
|
onUpdate: (value: any) => void;
|
|
512
525
|
onQueryChange: (event: any) => void;
|
|
513
526
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("change" | "close" | "update:modelValue" | "open" | "update:query")[], "change" | "close" | "update:modelValue" | "open" | "update:query", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
@@ -860,6 +873,12 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
|
|
|
860
873
|
default?: DeepPartial<{
|
|
861
874
|
selectedIcon: string;
|
|
862
875
|
trailingIcon: string;
|
|
876
|
+
empty: {
|
|
877
|
+
label: string;
|
|
878
|
+
};
|
|
879
|
+
optionEmpty: {
|
|
880
|
+
label: string;
|
|
881
|
+
};
|
|
863
882
|
}, any>;
|
|
864
883
|
arrow?: DeepPartial<{
|
|
865
884
|
ring: string;
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
:ui="uiRadio"
|
|
18
18
|
@change="onUpdate(option.value)"
|
|
19
19
|
>
|
|
20
|
-
<template #label>
|
|
20
|
+
<template v-if="$slots.label" #label>
|
|
21
21
|
<slot name="label" v-bind="{ option, selected: option.selected }" />
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
|
-
<template #help>
|
|
24
|
+
<template v-if="$slots.help" #help>
|
|
25
25
|
<slot name="help" v-bind="{ option, selected: option.selected }" />
|
|
26
26
|
</template>
|
|
27
27
|
</URadio>
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
</template>
|
|
31
31
|
|
|
32
32
|
<script>
|
|
33
|
-
import URadio from "./Radio.vue";
|
|
34
33
|
import { computed, defineComponent, provide, toRef } from "vue";
|
|
35
34
|
import { useUI } from "../../composables/useUI";
|
|
36
35
|
import { useFormGroup } from "../../composables/useFormGroup";
|
|
37
36
|
import { mergeConfig, get } from "../../utils";
|
|
37
|
+
import URadio from "./Radio.vue";
|
|
38
38
|
import appConfig from "#build/app.config";
|
|
39
39
|
import { radioGroup, radio } from "#ui/ui.config";
|
|
40
40
|
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.radioGroup, radioGroup);
|
|
@@ -137,7 +137,6 @@ export default defineComponent({
|
|
|
137
137
|
uiRadio,
|
|
138
138
|
attrs,
|
|
139
139
|
normalizedOptions,
|
|
140
|
-
// eslint-disable-next-line vue/no-dupe-keys
|
|
141
140
|
onUpdate
|
|
142
141
|
};
|
|
143
142
|
}
|