@nuxt/ui 2.19.0 → 2.19.1

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.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/ui",
3
- "version": "2.19.0",
3
+ "version": "2.19.1",
4
4
  "configKey": "ui",
5
5
  "compatibility": {
6
6
  "nuxt": ">=3.10.0"
package/dist/module.mjs CHANGED
@@ -14,7 +14,7 @@ const __filename = __cjs_url__.fileURLToPath(import.meta.url);
14
14
  const __dirname = __cjs_path__.dirname(__filename);
15
15
  const require = __cjs_mod__.createRequire(import.meta.url);
16
16
  const name = "@nuxt/ui";
17
- const version = "2.19.0";
17
+ const version = "2.19.1";
18
18
 
19
19
  function createTemplates(nuxt = useNuxt()) {
20
20
  const template = addTemplate({
@@ -145,8 +145,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
145
145
  default: () => {};
146
146
  };
147
147
  }>> & Readonly<{}>, {
148
- orientation: "horizontal" | "vertical";
149
148
  size: ButtonSize;
149
+ orientation: "horizontal" | "vertical";
150
150
  ui: Partial<{
151
151
  wrapper: {
152
152
  horizontal: string;
@@ -173,8 +173,8 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
173
173
  }> & {
174
174
  strategy?: Strategy;
175
175
  };
176
- class: any;
177
176
  icon: string;
177
+ class: any;
178
178
  max: number;
179
179
  min: number;
180
180
  indicator: boolean;
@@ -373,407 +373,7 @@ export default defineComponent({
373
373
  lazy: props.searchLazy
374
374
  });
375
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>");
376
+ return string.replace(/[.*+?^${}()|[\]\\]/g, (match) => `\\${match}`);
777
377
  }
778
378
  const filteredOptions = computed(() => {
779
379
  if (!query.value || debouncedSearch) {
@@ -453,486 +453,7 @@ export default defineComponent({
453
453
  lazy: props.searchableLazy
454
454
  });
455
455
  function escapeRegExp(string) {
456
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\<script lang="ts">
457
- import { ref, computed, toRef, watch, defineComponent, toRaw } from 'vue'
458
- import type { PropType } from 'vue'
459
- import {
460
- Combobox as HCombobox,
461
- ComboboxButton as HComboboxButton,
462
- ComboboxOptions as HComboboxOptions,
463
- ComboboxOption as HComboboxOption,
464
- ComboboxInput as HComboboxInput,
465
- Listbox as HListbox,
466
- ListboxButton as HListboxButton,
467
- ListboxOptions as HListboxOptions,
468
- ListboxOption as HListboxOption,
469
- provideUseId
470
- } from '@headlessui/vue'
471
- import { computedAsync, useDebounceFn } from '@vueuse/core'
472
- import { defu } from 'defu'
473
- import { twMerge, twJoin } from 'tailwind-merge'
474
- import UIcon from '../elements/Icon.vue'
475
- import UAvatar from '../elements/Avatar.vue'
476
- import { useUI } from '../../composables/useUI'
477
- import { usePopper } from '../../composables/usePopper'
478
- import { useFormGroup } from '../../composables/useFormGroup'
479
- import { get, mergeConfig } from '../../utils'
480
- import { useInjectButtonGroup } from '../../composables/useButtonGroup'
481
- import type { SelectSize, SelectColor, SelectVariant, PopperOptions, Strategy, DeepPartial } from '../../types/index'
482
- // @ts-expect-error
483
- import appConfig from '#build/app.config'
484
- import { select, selectMenu } from '#ui/ui.config'
485
- import { useId } from '#imports'
486
-
487
- const config = mergeConfig<typeof select>(appConfig.ui.strategy, appConfig.ui.select, select)
488
-
489
- const configMenu = mergeConfig<typeof selectMenu>(appConfig.ui.strategy, appConfig.ui.selectMenu, selectMenu)
490
-
491
- export default defineComponent({
492
- components: {
493
- HCombobox,
494
- HComboboxButton,
495
- HComboboxOptions,
496
- HComboboxOption,
497
- HComboboxInput,
498
- HListbox,
499
- HListboxButton,
500
- HListboxOptions,
501
- HListboxOption,
502
- UIcon,
503
- UAvatar
504
- },
505
- inheritAttrs: false,
506
- props: {
507
- modelValue: {
508
- type: [String, Number, Object, Array, Boolean] as PropType<string | number | object | Array<any> | boolean | null>,
509
- default: ''
510
- },
511
- query: {
512
- type: String,
513
- default: null
514
- },
515
- by: {
516
- type: String,
517
- default: undefined
518
- },
519
- options: {
520
- type: Array as PropType<{ [key: string]: any, disabled?: boolean }[] | string[]>,
521
- default: () => []
522
- },
523
- id: {
524
- type: String,
525
- default: null
526
- },
527
- name: {
528
- type: String,
529
- default: null
530
- },
531
- required: {
532
- type: Boolean,
533
- default: false
534
- },
535
- icon: {
536
- type: String,
537
- default: null
538
- },
539
- loadingIcon: {
540
- type: String,
541
- default: () => config.default.loadingIcon
542
- },
543
- leadingIcon: {
544
- type: String,
545
- default: null
546
- },
547
- trailingIcon: {
548
- type: String,
549
- default: () => config.default.trailingIcon
550
- },
551
- trailing: {
552
- type: Boolean,
553
- default: false
554
- },
555
- leading: {
556
- type: Boolean,
557
- default: false
558
- },
559
- loading: {
560
- type: Boolean,
561
- default: false
562
- },
563
- selectedIcon: {
564
- type: String,
565
- default: () => configMenu.default.selectedIcon
566
- },
567
- disabled: {
568
- type: Boolean,
569
- default: false
570
- },
571
- multiple: {
572
- type: Boolean,
573
- default: false
574
- },
575
- searchable: {
576
- type: [Boolean, Function] as PropType<boolean | ((query: string) => Promise<any[]> | any[])>,
577
- default: false
578
- },
579
- searchablePlaceholder: {
580
- type: String,
581
- default: () => configMenu.default.searchablePlaceholder.label
582
- },
583
- searchableLazy: {
584
- type: Boolean,
585
- default: false
586
- },
587
- clearSearchOnClose: {
588
- type: Boolean,
589
- default: () => configMenu.default.clearSearchOnClose
590
- },
591
- debounce: {
592
- type: Number,
593
- default: 200
594
- },
595
- creatable: {
596
- type: Boolean,
597
- default: false
598
- },
599
- showCreateOptionWhen: {
600
- type: [String, Function] as PropType<'always' | 'empty' | ((query: string, results: any[]) => boolean)>,
601
- default: () => configMenu.default.showCreateOptionWhen
602
- },
603
- placeholder: {
604
- type: String,
605
- default: null
606
- },
607
- padded: {
608
- type: Boolean,
609
- default: true
610
- },
611
- size: {
612
- type: String as PropType<SelectSize>,
613
- default: null,
614
- validator(value: string) {
615
- return Object.keys(config.size).includes(value)
616
- }
617
- },
618
- color: {
619
- type: String as PropType<SelectColor>,
620
- default: () => config.default.color,
621
- validator(value: string) {
622
- return [...appConfig.ui.colors, ...Object.keys(config.color)].includes(value)
623
- }
624
- },
625
- variant: {
626
- type: String as PropType<SelectVariant>,
627
- default: () => config.default.variant,
628
- validator(value: string) {
629
- return [
630
- ...Object.keys(config.variant),
631
- ...Object.values(config.color).flatMap(value => Object.keys(value))
632
- ].includes(value)
633
- }
634
- },
635
- optionAttribute: {
636
- type: String,
637
- default: 'label'
638
- },
639
- valueAttribute: {
640
- type: String,
641
- default: null
642
- },
643
- searchAttributes: {
644
- type: Array,
645
- default: null
646
- },
647
- popper: {
648
- type: Object as PropType<PopperOptions>,
649
- default: () => ({})
650
- },
651
- selectClass: {
652
- type: String,
653
- default: null
654
- },
655
- class: {
656
- type: [String, Object, Array] as PropType<any>,
657
- default: () => ''
658
- },
659
- ui: {
660
- type: Object as PropType<DeepPartial<typeof config> & { strategy?: Strategy }>,
661
- default: () => ({})
662
- },
663
- uiMenu: {
664
- type: Object as PropType<DeepPartial<typeof configMenu> & { strategy?: Strategy }>,
665
- default: () => ({})
666
- }
667
- },
668
- emits: ['update:modelValue', 'update:query', 'open', 'close', 'change'],
669
- setup(props, { emit, slots }) {
670
- if (import.meta.dev && props.multiple && !Array.isArray(props.modelValue)) {
671
- console.warn(`[@nuxt/ui] The USelectMenu components needs to have a modelValue of type Array when using the multiple prop. Got '${typeof props.modelValue}' instead.`, props.modelValue)
672
- }
673
-
674
- const { ui, attrs } = useUI('select', toRef(props, 'ui'), config, toRef(props, 'class'))
675
- const { ui: uiMenu } = useUI('selectMenu', toRef(props, 'uiMenu'), configMenu)
676
-
677
- const popper = computed<PopperOptions>(() => defu({}, props.popper, uiMenu.value.popper as PopperOptions))
678
-
679
- const [trigger, container] = usePopper(popper.value)
680
-
681
- const { size: sizeButtonGroup, rounded } = useInjectButtonGroup({ ui, props })
682
- const { emitFormBlur, emitFormChange, inputId, color, size: sizeFormGroup, name } = useFormGroup(props, config)
683
-
684
- const size = computed(() => sizeButtonGroup.value ?? sizeFormGroup.value)
685
-
686
- const internalQuery = ref('')
687
- const query = computed({
688
- get() {
689
- return props.query ?? internalQuery.value
690
- },
691
- set(value) {
692
- internalQuery.value = value
693
- emit('update:query', value)
694
- }
695
- })
696
-
697
- const selected = computed(() => {
698
- if (props.multiple) {
699
- if (!Array.isArray(props.modelValue) || !props.modelValue.length) {
700
- return []
701
- }
702
-
703
- if (props.valueAttribute) {
704
- return options.value.filter(option => (props.modelValue as any[]).includes(option[props.valueAttribute]))
705
- }
706
- return options.value.filter(option => (props.modelValue as any[]).includes(option))
707
- }
708
-
709
- if (props.valueAttribute) {
710
- return options.value.find(option => option[props.valueAttribute] === props.modelValue)
711
- }
712
- return options.value.find(option => option === props.modelValue)
713
- })
714
-
715
- const label = computed(() => {
716
- if (props.multiple) {
717
- if (Array.isArray(props.modelValue) && props.modelValue.length) {
718
- return `${selected.value.length} selected`
719
- } else {
720
- return null
721
- }
722
- } else if (props.modelValue !== undefined && props.modelValue !== null) {
723
- if (props.valueAttribute) {
724
- return accessor(selected.value, props.optionAttribute) ?? null
725
- } else {
726
- return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : accessor(props.modelValue as Record<string, any>, props.optionAttribute)
727
- }
728
- }
729
-
730
- return null
731
- })
732
-
733
- const selectClass = computed(() => {
734
- const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
735
-
736
- return twMerge(twJoin(
737
- ui.value.base,
738
- uiMenu.value.select,
739
- rounded.value,
740
- ui.value.size[size.value],
741
- ui.value.gap[size.value],
742
- props.padded ? ui.value.padding[size.value] : 'p-0',
743
- variant?.replaceAll('{color}', color.value),
744
- (isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
745
- (isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
746
- ), props.placeholder && (!props.modelValue || (Array.isArray(props.modelValue) && !props.modelValue.length)) && ui.value.placeholder, props.selectClass)
747
- })
748
-
749
- const isLeading = computed(() => {
750
- return (props.icon && props.leading) || (props.icon && !props.trailing) || (props.loading && !props.trailing) || props.leadingIcon
751
- })
752
-
753
- const isTrailing = computed(() => {
754
- return (props.icon && props.trailing) || (props.loading && props.trailing) || props.trailingIcon
755
- })
756
-
757
- const leadingIconName = computed(() => {
758
- if (props.loading) {
759
- return props.loadingIcon
760
- }
761
-
762
- return props.leadingIcon || props.icon
763
- })
764
-
765
- const trailingIconName = computed(() => {
766
- if (props.loading && !isLeading.value) {
767
- return props.loadingIcon
768
- }
769
-
770
- return props.trailingIcon || props.icon
771
- })
772
-
773
- const leadingWrapperIconClass = computed(() => {
774
- return twJoin(
775
- ui.value.icon.leading.wrapper,
776
- ui.value.icon.leading.pointer,
777
- ui.value.icon.leading.padding[size.value]
778
- )
779
- })
780
-
781
- const leadingIconClass = computed(() => {
782
- return twJoin(
783
- ui.value.icon.base,
784
- color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
785
- ui.value.icon.size[size.value],
786
- props.loading && ui.value.icon.loading
787
- )
788
- })
789
-
790
- const trailingWrapperIconClass = computed(() => {
791
- return twJoin(
792
- ui.value.icon.trailing.wrapper,
793
- ui.value.icon.trailing.pointer,
794
- ui.value.icon.trailing.padding[size.value]
795
- )
796
- })
797
-
798
- const trailingIconClass = computed(() => {
799
- return twJoin(
800
- ui.value.icon.base,
801
- color.value && appConfig.ui.colors.includes(color.value) && ui.value.icon.color.replaceAll('{color}', color.value),
802
- ui.value.icon.size[size.value],
803
- props.loading && !isLeading.value && ui.value.icon.loading
804
- )
805
- })
806
-
807
- const debouncedSearch = props.searchable && typeof props.searchable === 'function' ? useDebounceFn(props.searchable, props.debounce) : undefined
808
-
809
- const options = computedAsync(async () => {
810
- if (debouncedSearch) {
811
- return await debouncedSearch(query.value)
812
- }
813
-
814
- return props.options || []
815
- }, [], {
816
- lazy: props.searchableLazy
817
- })
818
-
819
- function escapeRegExp(string: string) {
820
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
821
- }
822
-
823
- function accessor<T extends Record<string, any>>(obj: T, key: string) {
824
- return get(obj, key)
825
- }
826
-
827
- const filteredOptions = computed(() => {
828
- if (!query.value || debouncedSearch) {
829
- return options.value
830
- }
831
-
832
- const escapedQuery = escapeRegExp(query.value)
833
-
834
- return options.value.filter((option: any) => {
835
- return (props.searchAttributes?.length ? props.searchAttributes : [props.optionAttribute]).some((searchAttribute: any) => {
836
- if (['string', 'number'].includes(typeof option)) {
837
- return String(option).search(new RegExp(escapedQuery, 'i')) !== -1
838
- }
839
-
840
- const child = get(option, searchAttribute)
841
-
842
- return child !== null && child !== undefined && String(child).search(new RegExp(escapedQuery, 'i')) !== -1
843
- })
844
- })
845
- })
846
-
847
- const createOption = computed(() => {
848
- if (query.value === '') {
849
- return null
850
- }
851
- if (props.showCreateOptionWhen === 'empty' && filteredOptions.value.length) {
852
- return null
853
- }
854
- if (props.showCreateOptionWhen === 'always') {
855
- const existingOption = filteredOptions.value.find(option => ['string', 'number'].includes(typeof option) ? option === query.value : accessor(option, props.optionAttribute) === query.value)
856
- if (existingOption) {
857
- return null
858
- }
859
- }
860
- if (typeof props.showCreateOptionWhen === 'function') {
861
- if (!props.showCreateOptionWhen(query.value, filteredOptions.value)) {
862
- return null
863
- }
864
- }
865
- return ['string', 'number'].includes(typeof props.modelValue) ? query.value : { [props.optionAttribute]: query.value }
866
- })
867
-
868
- function clearOnClose() {
869
- if (props.clearSearchOnClose) {
870
- query.value = ''
871
- }
872
- }
873
-
874
- watch(container, (value) => {
875
- if (value) {
876
- emit('open')
877
- } else {
878
- clearOnClose()
879
- emit('close')
880
- emitFormBlur()
881
- }
882
- })
883
-
884
- function onUpdate(value: any) {
885
- if (toRaw(props.modelValue) === value) {
886
- return
887
- }
888
-
889
- emit('update:modelValue', value)
890
- emit('change', value)
891
- emitFormChange()
892
- }
893
-
894
- function onQueryChange(event: any) {
895
- query.value = event.target.value
896
- }
897
-
898
- provideUseId(() => useId())
899
-
900
- return {
901
- // eslint-disable-next-line vue/no-dupe-keys
902
- ui,
903
- // eslint-disable-next-line vue/no-dupe-keys
904
- uiMenu,
905
- attrs,
906
- // eslint-disable-next-line vue/no-dupe-keys
907
- name,
908
- inputId,
909
- // eslint-disable-next-line vue/no-dupe-keys
910
- popper,
911
- trigger,
912
- container,
913
- selected,
914
- label,
915
- accessor,
916
- isLeading,
917
- isTrailing,
918
- // eslint-disable-next-line vue/no-dupe-keys
919
- selectClass,
920
- leadingIconName,
921
- leadingIconClass,
922
- leadingWrapperIconClass,
923
- trailingIconName,
924
- trailingIconClass,
925
- trailingWrapperIconClass,
926
- filteredOptions,
927
- createOption,
928
- // eslint-disable-next-line vue/no-dupe-keys
929
- query,
930
- onUpdate,
931
- onQueryChange
932
- }
933
- }
934
- })
935
- </script>");
456
+ return string.replace(/[.*+?^${}()|[\]\\]/g, (match) => `\\${match}`);
936
457
  }
937
458
  function accessor(obj, key) {
938
459
  return get(obj, key);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxt/ui",
3
3
  "description": "A UI Library for Modern Web Apps, powered by Vue & Tailwind CSS.",
4
- "version": "2.19.0",
4
+ "version": "2.19.1",
5
5
  "packageManager": "pnpm@9.12.3",
6
6
  "repository": "nuxt/ui",
7
7
  "homepage": "https://ui.nuxt.com",