@vuetify/nightly 3.7.12-master.2025-02-14 → 3.7.12-master.2025-02-17

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 (41) hide show
  1. package/CHANGELOG.md +12 -3
  2. package/dist/json/attributes.json +2936 -2924
  3. package/dist/json/importMap-labs.json +16 -16
  4. package/dist/json/importMap.json +174 -174
  5. package/dist/json/tags.json +3 -0
  6. package/dist/json/web-types.json +5456 -5428
  7. package/dist/vuetify-labs.css +3803 -3795
  8. package/dist/vuetify-labs.d.ts +80 -29
  9. package/dist/vuetify-labs.esm.js +109 -46
  10. package/dist/vuetify-labs.esm.js.map +1 -1
  11. package/dist/vuetify-labs.js +109 -46
  12. package/dist/vuetify-labs.min.css +2 -2
  13. package/dist/vuetify.css +3706 -3706
  14. package/dist/vuetify.d.ts +86 -74
  15. package/dist/vuetify.esm.js +20 -13
  16. package/dist/vuetify.esm.js.map +1 -1
  17. package/dist/vuetify.js +20 -13
  18. package/dist/vuetify.js.map +1 -1
  19. package/dist/vuetify.min.css +2 -2
  20. package/dist/vuetify.min.js +6 -6
  21. package/dist/vuetify.min.js.map +1 -1
  22. package/lib/components/VDataTable/composables/sort.mjs +12 -8
  23. package/lib/components/VDataTable/composables/sort.mjs.map +1 -1
  24. package/lib/components/VDatePicker/VDatePickerControls.mjs +1 -1
  25. package/lib/components/VDatePicker/VDatePickerControls.mjs.map +1 -1
  26. package/lib/components/VDatePicker/index.d.mts +27 -15
  27. package/lib/components/index.d.mts +27 -15
  28. package/lib/composables/calendar.mjs +4 -1
  29. package/lib/composables/calendar.mjs.map +1 -1
  30. package/lib/entry-bundler.mjs +1 -1
  31. package/lib/framework.mjs +1 -1
  32. package/lib/index.d.mts +59 -59
  33. package/lib/labs/VCalendar/index.d.mts +8 -2
  34. package/lib/labs/VDateInput/index.d.mts +8 -2
  35. package/lib/labs/VNumberInput/VNumberInput.css +10 -2
  36. package/lib/labs/VNumberInput/VNumberInput.mjs +93 -35
  37. package/lib/labs/VNumberInput/VNumberInput.mjs.map +1 -1
  38. package/lib/labs/VNumberInput/VNumberInput.sass +12 -2
  39. package/lib/labs/VNumberInput/index.d.mts +37 -10
  40. package/lib/labs/components.d.mts +53 -14
  41. package/package.json +1 -1
package/lib/index.d.mts CHANGED
@@ -486,77 +486,80 @@ declare module 'vue' {
486
486
  $children?: VNodeChild
487
487
  }
488
488
  export interface GlobalComponents {
489
- VApp: typeof import('vuetify/components')['VApp']
490
489
  VAppBar: typeof import('vuetify/components')['VAppBar']
491
490
  VAppBarNavIcon: typeof import('vuetify/components')['VAppBarNavIcon']
492
491
  VAppBarTitle: typeof import('vuetify/components')['VAppBarTitle']
492
+ VAutocomplete: typeof import('vuetify/components')['VAutocomplete']
493
+ VApp: typeof import('vuetify/components')['VApp']
493
494
  VAlert: typeof import('vuetify/components')['VAlert']
494
495
  VAlertTitle: typeof import('vuetify/components')['VAlertTitle']
495
- VBadge: typeof import('vuetify/components')['VBadge']
496
496
  VAvatar: typeof import('vuetify/components')['VAvatar']
497
+ VBtnGroup: typeof import('vuetify/components')['VBtnGroup']
498
+ VBottomSheet: typeof import('vuetify/components')['VBottomSheet']
499
+ VBadge: typeof import('vuetify/components')['VBadge']
500
+ VBottomNavigation: typeof import('vuetify/components')['VBottomNavigation']
497
501
  VBanner: typeof import('vuetify/components')['VBanner']
498
502
  VBannerActions: typeof import('vuetify/components')['VBannerActions']
499
503
  VBannerText: typeof import('vuetify/components')['VBannerText']
500
- VBreadcrumbs: typeof import('vuetify/components')['VBreadcrumbs']
501
- VBreadcrumbsItem: typeof import('vuetify/components')['VBreadcrumbsItem']
502
- VBreadcrumbsDivider: typeof import('vuetify/components')['VBreadcrumbsDivider']
503
504
  VBtn: typeof import('vuetify/components')['VBtn']
504
- VBottomNavigation: typeof import('vuetify/components')['VBottomNavigation']
505
- VBtnGroup: typeof import('vuetify/components')['VBtnGroup']
506
- VBtnToggle: typeof import('vuetify/components')['VBtnToggle']
507
- VBottomSheet: typeof import('vuetify/components')['VBottomSheet']
508
505
  VCarousel: typeof import('vuetify/components')['VCarousel']
509
506
  VCarouselItem: typeof import('vuetify/components')['VCarouselItem']
510
- VChip: typeof import('vuetify/components')['VChip']
511
507
  VCard: typeof import('vuetify/components')['VCard']
512
508
  VCardActions: typeof import('vuetify/components')['VCardActions']
513
509
  VCardItem: typeof import('vuetify/components')['VCardItem']
514
510
  VCardSubtitle: typeof import('vuetify/components')['VCardSubtitle']
515
511
  VCardText: typeof import('vuetify/components')['VCardText']
516
512
  VCardTitle: typeof import('vuetify/components')['VCardTitle']
517
- VCheckbox: typeof import('vuetify/components')['VCheckbox']
518
- VCheckboxBtn: typeof import('vuetify/components')['VCheckboxBtn']
519
- VColorPicker: typeof import('vuetify/components')['VColorPicker']
513
+ VChip: typeof import('vuetify/components')['VChip']
514
+ VBreadcrumbs: typeof import('vuetify/components')['VBreadcrumbs']
515
+ VBreadcrumbsItem: typeof import('vuetify/components')['VBreadcrumbsItem']
516
+ VBreadcrumbsDivider: typeof import('vuetify/components')['VBreadcrumbsDivider']
517
+ VBtnToggle: typeof import('vuetify/components')['VBtnToggle']
520
518
  VChipGroup: typeof import('vuetify/components')['VChipGroup']
521
519
  VCode: typeof import('vuetify/components')['VCode']
522
- VDataTable: typeof import('vuetify/components')['VDataTable']
523
- VDataTableHeaders: typeof import('vuetify/components')['VDataTableHeaders']
524
- VDataTableFooter: typeof import('vuetify/components')['VDataTableFooter']
525
- VDataTableRows: typeof import('vuetify/components')['VDataTableRows']
526
- VDataTableRow: typeof import('vuetify/components')['VDataTableRow']
527
- VDataTableVirtual: typeof import('vuetify/components')['VDataTableVirtual']
528
- VDataTableServer: typeof import('vuetify/components')['VDataTableServer']
520
+ VCheckbox: typeof import('vuetify/components')['VCheckbox']
521
+ VCheckboxBtn: typeof import('vuetify/components')['VCheckboxBtn']
529
522
  VCombobox: typeof import('vuetify/components')['VCombobox']
523
+ VColorPicker: typeof import('vuetify/components')['VColorPicker']
530
524
  VCounter: typeof import('vuetify/components')['VCounter']
531
- VEmptyState: typeof import('vuetify/components')['VEmptyState']
532
525
  VDatePicker: typeof import('vuetify/components')['VDatePicker']
533
526
  VDatePickerControls: typeof import('vuetify/components')['VDatePickerControls']
534
527
  VDatePickerHeader: typeof import('vuetify/components')['VDatePickerHeader']
535
528
  VDatePickerMonth: typeof import('vuetify/components')['VDatePickerMonth']
536
529
  VDatePickerMonths: typeof import('vuetify/components')['VDatePickerMonths']
537
530
  VDatePickerYears: typeof import('vuetify/components')['VDatePickerYears']
538
- VDialog: typeof import('vuetify/components')['VDialog']
531
+ VDataTable: typeof import('vuetify/components')['VDataTable']
532
+ VDataTableHeaders: typeof import('vuetify/components')['VDataTableHeaders']
533
+ VDataTableFooter: typeof import('vuetify/components')['VDataTableFooter']
534
+ VDataTableRows: typeof import('vuetify/components')['VDataTableRows']
535
+ VDataTableRow: typeof import('vuetify/components')['VDataTableRow']
536
+ VDataTableVirtual: typeof import('vuetify/components')['VDataTableVirtual']
537
+ VDataTableServer: typeof import('vuetify/components')['VDataTableServer']
539
538
  VDivider: typeof import('vuetify/components')['VDivider']
539
+ VDialog: typeof import('vuetify/components')['VDialog']
540
+ VFab: typeof import('vuetify/components')['VFab']
541
+ VEmptyState: typeof import('vuetify/components')['VEmptyState']
540
542
  VExpansionPanels: typeof import('vuetify/components')['VExpansionPanels']
541
543
  VExpansionPanel: typeof import('vuetify/components')['VExpansionPanel']
542
544
  VExpansionPanelText: typeof import('vuetify/components')['VExpansionPanelText']
543
545
  VExpansionPanelTitle: typeof import('vuetify/components')['VExpansionPanelTitle']
544
- VFab: typeof import('vuetify/components')['VFab']
545
- VFileInput: typeof import('vuetify/components')['VFileInput']
546
- VFooter: typeof import('vuetify/components')['VFooter']
547
546
  VField: typeof import('vuetify/components')['VField']
548
547
  VFieldLabel: typeof import('vuetify/components')['VFieldLabel']
548
+ VFooter: typeof import('vuetify/components')['VFooter']
549
+ VFileInput: typeof import('vuetify/components')['VFileInput']
549
550
  VIcon: typeof import('vuetify/components')['VIcon']
550
551
  VComponentIcon: typeof import('vuetify/components')['VComponentIcon']
551
552
  VSvgIcon: typeof import('vuetify/components')['VSvgIcon']
552
553
  VLigatureIcon: typeof import('vuetify/components')['VLigatureIcon']
553
554
  VClassIcon: typeof import('vuetify/components')['VClassIcon']
554
- VInput: typeof import('vuetify/components')['VInput']
555
555
  VImg: typeof import('vuetify/components')['VImg']
556
- VKbd: typeof import('vuetify/components')['VKbd']
556
+ VInfiniteScroll: typeof import('vuetify/components')['VInfiniteScroll']
557
+ VInput: typeof import('vuetify/components')['VInput']
558
+ VLabel: typeof import('vuetify/components')['VLabel']
557
559
  VItemGroup: typeof import('vuetify/components')['VItemGroup']
558
560
  VItem: typeof import('vuetify/components')['VItem']
559
- VInfiniteScroll: typeof import('vuetify/components')['VInfiniteScroll']
561
+ VKbd: typeof import('vuetify/components')['VKbd']
562
+ VMenu: typeof import('vuetify/components')['VMenu']
560
563
  VList: typeof import('vuetify/components')['VList']
561
564
  VListGroup: typeof import('vuetify/components')['VListGroup']
562
565
  VListImg: typeof import('vuetify/components')['VListImg']
@@ -566,67 +569,66 @@ declare module 'vue' {
566
569
  VListItemSubtitle: typeof import('vuetify/components')['VListItemSubtitle']
567
570
  VListItemTitle: typeof import('vuetify/components')['VListItemTitle']
568
571
  VListSubheader: typeof import('vuetify/components')['VListSubheader']
569
- VNavigationDrawer: typeof import('vuetify/components')['VNavigationDrawer']
570
- VMenu: typeof import('vuetify/components')['VMenu']
571
- VLabel: typeof import('vuetify/components')['VLabel']
572
- VMain: typeof import('vuetify/components')['VMain']
573
572
  VMessages: typeof import('vuetify/components')['VMessages']
573
+ VMain: typeof import('vuetify/components')['VMain']
574
+ VNavigationDrawer: typeof import('vuetify/components')['VNavigationDrawer']
574
575
  VOtpInput: typeof import('vuetify/components')['VOtpInput']
575
576
  VOverlay: typeof import('vuetify/components')['VOverlay']
576
577
  VPagination: typeof import('vuetify/components')['VPagination']
578
+ VProgressLinear: typeof import('vuetify/components')['VProgressLinear']
579
+ VRadioGroup: typeof import('vuetify/components')['VRadioGroup']
577
580
  VProgressCircular: typeof import('vuetify/components')['VProgressCircular']
578
581
  VRating: typeof import('vuetify/components')['VRating']
579
- VRadioGroup: typeof import('vuetify/components')['VRadioGroup']
580
- VSheet: typeof import('vuetify/components')['VSheet']
581
- VProgressLinear: typeof import('vuetify/components')['VProgressLinear']
582
- VSlider: typeof import('vuetify/components')['VSlider']
583
- VSelectionControlGroup: typeof import('vuetify/components')['VSelectionControlGroup']
584
582
  VSelect: typeof import('vuetify/components')['VSelect']
583
+ VSkeletonLoader: typeof import('vuetify/components')['VSkeletonLoader']
584
+ VSlideGroup: typeof import('vuetify/components')['VSlideGroup']
585
+ VSlideGroupItem: typeof import('vuetify/components')['VSlideGroupItem']
586
+ VSlider: typeof import('vuetify/components')['VSlider']
587
+ VSheet: typeof import('vuetify/components')['VSheet']
588
+ VSnackbar: typeof import('vuetify/components')['VSnackbar']
589
+ VSystemBar: typeof import('vuetify/components')['VSystemBar']
585
590
  VStepper: typeof import('vuetify/components')['VStepper']
586
591
  VStepperActions: typeof import('vuetify/components')['VStepperActions']
587
592
  VStepperHeader: typeof import('vuetify/components')['VStepperHeader']
588
593
  VStepperItem: typeof import('vuetify/components')['VStepperItem']
589
594
  VStepperWindow: typeof import('vuetify/components')['VStepperWindow']
590
595
  VStepperWindowItem: typeof import('vuetify/components')['VStepperWindowItem']
591
- VSlideGroup: typeof import('vuetify/components')['VSlideGroup']
592
- VSlideGroupItem: typeof import('vuetify/components')['VSlideGroupItem']
593
- VSnackbar: typeof import('vuetify/components')['VSnackbar']
594
- VSwitch: typeof import('vuetify/components')['VSwitch']
596
+ VSelectionControlGroup: typeof import('vuetify/components')['VSelectionControlGroup']
595
597
  VSelectionControl: typeof import('vuetify/components')['VSelectionControl']
596
- VSystemBar: typeof import('vuetify/components')['VSystemBar']
597
598
  VTab: typeof import('vuetify/components')['VTab']
598
599
  VTabs: typeof import('vuetify/components')['VTabs']
599
600
  VTabsWindow: typeof import('vuetify/components')['VTabsWindow']
600
601
  VTabsWindowItem: typeof import('vuetify/components')['VTabsWindowItem']
601
- VTable: typeof import('vuetify/components')['VTable']
602
- VTextField: typeof import('vuetify/components')['VTextField']
603
602
  VTextarea: typeof import('vuetify/components')['VTextarea']
604
- VTimeline: typeof import('vuetify/components')['VTimeline']
605
- VTimelineItem: typeof import('vuetify/components')['VTimelineItem']
606
- VTooltip: typeof import('vuetify/components')['VTooltip']
603
+ VSwitch: typeof import('vuetify/components')['VSwitch']
604
+ VTextField: typeof import('vuetify/components')['VTextField']
607
605
  VToolbar: typeof import('vuetify/components')['VToolbar']
608
606
  VToolbarTitle: typeof import('vuetify/components')['VToolbarTitle']
609
607
  VToolbarItems: typeof import('vuetify/components')['VToolbarItems']
610
- VSkeletonLoader: typeof import('vuetify/components')['VSkeletonLoader']
611
- VAutocomplete: typeof import('vuetify/components')['VAutocomplete']
608
+ VTable: typeof import('vuetify/components')['VTable']
609
+ VWindow: typeof import('vuetify/components')['VWindow']
610
+ VWindowItem: typeof import('vuetify/components')['VWindowItem']
611
+ VTimeline: typeof import('vuetify/components')['VTimeline']
612
+ VTimelineItem: typeof import('vuetify/components')['VTimelineItem']
613
+ VTooltip: typeof import('vuetify/components')['VTooltip']
612
614
  VConfirmEdit: typeof import('vuetify/components')['VConfirmEdit']
613
615
  VDataIterator: typeof import('vuetify/components')['VDataIterator']
614
616
  VDefaultsProvider: typeof import('vuetify/components')['VDefaultsProvider']
617
+ VForm: typeof import('vuetify/components')['VForm']
615
618
  VContainer: typeof import('vuetify/components')['VContainer']
616
619
  VCol: typeof import('vuetify/components')['VCol']
617
620
  VRow: typeof import('vuetify/components')['VRow']
618
621
  VSpacer: typeof import('vuetify/components')['VSpacer']
619
- VForm: typeof import('vuetify/components')['VForm']
620
622
  VHover: typeof import('vuetify/components')['VHover']
621
- VLazy: typeof import('vuetify/components')['VLazy']
622
623
  VLayout: typeof import('vuetify/components')['VLayout']
623
624
  VLayoutItem: typeof import('vuetify/components')['VLayoutItem']
625
+ VLazy: typeof import('vuetify/components')['VLazy']
624
626
  VLocaleProvider: typeof import('vuetify/components')['VLocaleProvider']
625
627
  VNoSsr: typeof import('vuetify/components')['VNoSsr']
626
- VParallax: typeof import('vuetify/components')['VParallax']
627
628
  VRadio: typeof import('vuetify/components')['VRadio']
628
- VResponsive: typeof import('vuetify/components')['VResponsive']
629
+ VParallax: typeof import('vuetify/components')['VParallax']
629
630
  VRangeSlider: typeof import('vuetify/components')['VRangeSlider']
631
+ VResponsive: typeof import('vuetify/components')['VResponsive']
630
632
  VSparkline: typeof import('vuetify/components')['VSparkline']
631
633
  VSpeedDial: typeof import('vuetify/components')['VSpeedDial']
632
634
  VThemeProvider: typeof import('vuetify/components')['VThemeProvider']
@@ -648,8 +650,6 @@ declare module 'vue' {
648
650
  VExpandTransition: typeof import('vuetify/components')['VExpandTransition']
649
651
  VExpandXTransition: typeof import('vuetify/components')['VExpandXTransition']
650
652
  VDialogTransition: typeof import('vuetify/components')['VDialogTransition']
651
- VWindow: typeof import('vuetify/components')['VWindow']
652
- VWindowItem: typeof import('vuetify/components')['VWindowItem']
653
653
  VCalendar: typeof import('vuetify/labs/components')['VCalendar']
654
654
  VCalendarDay: typeof import('vuetify/labs/components')['VCalendarDay']
655
655
  VCalendarHeader: typeof import('vuetify/labs/components')['VCalendarHeader']
@@ -659,19 +659,19 @@ declare module 'vue' {
659
659
  VStepperVertical: typeof import('vuetify/labs/components')['VStepperVertical']
660
660
  VStepperVerticalItem: typeof import('vuetify/labs/components')['VStepperVerticalItem']
661
661
  VStepperVerticalActions: typeof import('vuetify/labs/components')['VStepperVerticalActions']
662
+ VPicker: typeof import('vuetify/labs/components')['VPicker']
663
+ VPickerTitle: typeof import('vuetify/labs/components')['VPickerTitle']
664
+ VNumberInput: typeof import('vuetify/labs/components')['VNumberInput']
662
665
  VFileUpload: typeof import('vuetify/labs/components')['VFileUpload']
663
666
  VFileUploadItem: typeof import('vuetify/labs/components')['VFileUploadItem']
664
- VNumberInput: typeof import('vuetify/labs/components')['VNumberInput']
665
667
  VTimePicker: typeof import('vuetify/labs/components')['VTimePicker']
666
668
  VTimePickerClock: typeof import('vuetify/labs/components')['VTimePickerClock']
667
669
  VTimePickerControls: typeof import('vuetify/labs/components')['VTimePickerControls']
668
- VPicker: typeof import('vuetify/labs/components')['VPicker']
669
- VPickerTitle: typeof import('vuetify/labs/components')['VPickerTitle']
670
670
  VTreeview: typeof import('vuetify/labs/components')['VTreeview']
671
671
  VTreeviewItem: typeof import('vuetify/labs/components')['VTreeviewItem']
672
672
  VTreeviewGroup: typeof import('vuetify/labs/components')['VTreeviewGroup']
673
673
  VDateInput: typeof import('vuetify/labs/components')['VDateInput']
674
- VPullToRefresh: typeof import('vuetify/labs/components')['VPullToRefresh']
675
674
  VSnackbarQueue: typeof import('vuetify/labs/components')['VSnackbarQueue']
675
+ VPullToRefresh: typeof import('vuetify/labs/components')['VPullToRefresh']
676
676
  }
677
677
  }
@@ -590,7 +590,10 @@ declare const VCalendar: {
590
590
  default: number;
591
591
  };
592
592
  allowedDates: vue.PropType<unknown[] | ((date: unknown) => boolean)>;
593
- disabled: BooleanConstructor;
593
+ disabled: {
594
+ type: BooleanConstructor;
595
+ default: null;
596
+ };
594
597
  displayValue: vue.PropType<unknown>;
595
598
  modelValue: vue.PropType<unknown[]>;
596
599
  month: (StringConstructor | NumberConstructor)[];
@@ -689,7 +692,10 @@ declare const VCalendar: {
689
692
  default: number;
690
693
  };
691
694
  allowedDates: vue.PropType<unknown[] | ((date: unknown) => boolean)>;
692
- disabled: BooleanConstructor;
695
+ disabled: {
696
+ type: BooleanConstructor;
697
+ default: null;
698
+ };
693
699
  displayValue: vue.PropType<unknown>;
694
700
  modelValue: vue.PropType<unknown[]>;
695
701
  month: (StringConstructor | NumberConstructor)[];
@@ -762,7 +762,10 @@ declare const VDateInput: {
762
762
  default: string;
763
763
  };
764
764
  text: StringConstructor;
765
- disabled: BooleanConstructor;
765
+ disabled: {
766
+ type: BooleanConstructor;
767
+ default: null;
768
+ };
766
769
  multiple: PropType<boolean | "range" | number | (string & {})>;
767
770
  month: (StringConstructor | NumberConstructor)[];
768
771
  year: NumberConstructor;
@@ -980,7 +983,10 @@ declare const VDateInput: {
980
983
  default: string;
981
984
  };
982
985
  text: StringConstructor;
983
- disabled: BooleanConstructor;
986
+ disabled: {
987
+ type: BooleanConstructor;
988
+ default: null;
989
+ };
984
990
  multiple: PropType<boolean | "range" | number | (string & {})>;
985
991
  month: (StringConstructor | NumberConstructor)[];
986
992
  year: NumberConstructor;
@@ -4,10 +4,18 @@
4
4
  .v-number-input input[type=number]::-webkit-outer-spin-button, .v-number-input input[type=number]::-webkit-inner-spin-button {
5
5
  -webkit-appearance: none;
6
6
  }
7
- .v-number-input .v-field {
8
- padding-inline-end: 0;
7
+ .v-number-input .v-field:not(:has(.v-field__prepend-inner > .v-icon)) {
9
8
  padding-inline-start: 0;
10
9
  }
10
+ .v-number-input .v-field:not(:has(.v-field__append-inner > .v-icon)) {
11
+ padding-inline-end: 0;
12
+ }
13
+ .v-number-input .v-field__prepend-inner:has(.v-number-input__control) > .v-icon {
14
+ margin-inline-end: 12px;
15
+ }
16
+ .v-number-input .v-field__append-inner:has(.v-number-input__control) > .v-icon {
17
+ margin-inline-start: 12px;
18
+ }
11
19
  .v-number-input--inset .v-divider {
12
20
  height: 55%;
13
21
  width: 55%;
@@ -10,8 +10,8 @@ import { makeVTextFieldProps, VTextField } from "../../components/VTextField/VTe
10
10
  import { useForm } from "../../composables/form.mjs";
11
11
  import { forwardRefs } from "../../composables/forwardRefs.mjs";
12
12
  import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utilities
13
- import { computed, nextTick, onMounted, ref } from 'vue';
14
- import { clamp, genericComponent, getDecimals, omit, propsFactory, useRender } from "../../util/index.mjs"; // Types
13
+ import { computed, nextTick, onMounted, ref, shallowRef, watch, watchEffect } from 'vue';
14
+ import { clamp, genericComponent, omit, propsFactory, useRender } from "../../util/index.mjs"; // Types
15
15
  const makeVNumberInputProps = propsFactory({
16
16
  controlVariant: {
17
17
  type: String,
@@ -35,7 +35,11 @@ const makeVNumberInputProps = propsFactory({
35
35
  type: Number,
36
36
  default: 1
37
37
  },
38
- ...omit(makeVTextFieldProps({}), ['appendInnerIcon', 'modelValue', 'prependInnerIcon'])
38
+ precision: {
39
+ type: Number,
40
+ default: 0
41
+ },
42
+ ...omit(makeVTextFieldProps({}), ['modelValue'])
39
43
  }, 'VNumberInput');
40
44
  export const VNumberInput = genericComponent()({
41
45
  name: 'VNumberInput',
@@ -49,27 +53,39 @@ export const VNumberInput = genericComponent()({
49
53
  let {
50
54
  slots
51
55
  } = _ref;
52
- const _model = useProxiedModel(props, 'modelValue');
53
- const model = computed({
54
- get: () => _model.value,
55
- // model.value could be empty string from VTextField
56
- // but _model.value should be eventually kept in type Number | null
56
+ const vTextFieldRef = ref();
57
+ const form = useForm(props);
58
+ const controlsDisabled = computed(() => form.isDisabled.value || form.isReadonly.value);
59
+ const isFocused = ref(false);
60
+ function correctPrecision(val) {
61
+ let precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : props.precision;
62
+ const fixed = precision == null ? String(val) : val.toFixed(precision);
63
+ return isFocused.value ? Number(fixed).toString() // trim zeros
64
+ : fixed;
65
+ }
66
+ const model = useProxiedModel(props, 'modelValue', null, val => val ?? null, val => val == null ? val ?? null : clamp(+val, props.min, props.max));
67
+ const _inputText = shallowRef(null);
68
+ watchEffect(() => {
69
+ if (isFocused.value && !controlsDisabled.value) {
70
+ // ignore external changes
71
+ } else if (model.value == null || controlsDisabled.value) {
72
+ _inputText.value = model.value && !isNaN(model.value) ? String(model.value) : null;
73
+ } else if (!isNaN(model.value)) {
74
+ _inputText.value = correctPrecision(model.value);
75
+ }
76
+ });
77
+ const inputText = computed({
78
+ get: () => _inputText.value,
57
79
  set(val) {
58
80
  if (val === null || val === '') {
59
- _model.value = null;
60
- return;
61
- }
62
- const value = Number(val);
63
- if (!isNaN(value) && value <= props.max && value >= props.min) {
64
- _model.value = value;
81
+ model.value = null;
82
+ _inputText.value = null;
83
+ } else if (!isNaN(+val) && +val <= props.max && +val >= props.min) {
84
+ model.value = +val;
85
+ _inputText.value = val;
65
86
  }
66
87
  }
67
88
  });
68
- const vTextFieldRef = ref();
69
- const stepDecimals = computed(() => getDecimals(props.step));
70
- const modelDecimals = computed(() => typeof model.value === 'number' ? getDecimals(model.value) : 0);
71
- const form = useForm(props);
72
- const controlsDisabled = computed(() => form.isDisabled.value || form.isReadonly.value);
73
89
  const canIncrease = computed(() => {
74
90
  if (controlsDisabled.value) return false;
75
91
  return (model.value ?? 0) + props.step <= props.max;
@@ -91,23 +107,29 @@ export const VNumberInput = genericComponent()({
91
107
  const decrementSlotProps = computed(() => ({
92
108
  click: onClickDown
93
109
  }));
110
+ watch(() => props.precision, () => formatInputValue());
94
111
  onMounted(() => {
95
- if (!controlsDisabled.value) {
96
- clampModel();
97
- }
112
+ clampModel();
98
113
  });
114
+ function inferPrecision(value) {
115
+ if (value == null) return 0;
116
+ const str = value.toString();
117
+ const idx = str.indexOf('.');
118
+ return ~idx ? str.length - idx : 0;
119
+ }
99
120
  function toggleUpDown() {
100
121
  let increment = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
101
122
  if (controlsDisabled.value) return;
102
123
  if (model.value == null) {
103
- model.value = clamp(0, props.min, props.max);
124
+ inputText.value = correctPrecision(clamp(0, props.min, props.max));
104
125
  return;
105
126
  }
106
- const decimals = Math.max(modelDecimals.value, stepDecimals.value);
127
+ let inferredPrecision = Math.max(inferPrecision(model.value), inferPrecision(props.step));
128
+ if (props.precision != null) inferredPrecision = Math.max(inferredPrecision, props.precision);
107
129
  if (increment) {
108
- if (canIncrease.value) model.value = +(model.value + props.step).toFixed(decimals);
130
+ if (canIncrease.value) inputText.value = correctPrecision(model.value + props.step, inferredPrecision);
109
131
  } else {
110
- if (canDecrease.value) model.value = +(model.value - props.step).toFixed(decimals);
132
+ if (canDecrease.value) inputText.value = correctPrecision(model.value - props.step, inferredPrecision);
111
133
  }
112
134
  }
113
135
  function onClickUp(e) {
@@ -130,6 +152,16 @@ export const VNumberInput = genericComponent()({
130
152
  if (!/^-?(\d+(\.\d*)?|(\.\d+)|\d*|\.)$/.test(potentialNewInputVal)) {
131
153
  e.preventDefault();
132
154
  }
155
+ if (props.precision == null) return;
156
+
157
+ // Ignore decimal digits above precision limit
158
+ if (potentialNewInputVal.split('.')[1]?.length > props.precision) {
159
+ e.preventDefault();
160
+ }
161
+ // Ignore decimal separator when precision = 0
162
+ if (props.precision === 0 && potentialNewInputVal.includes('.')) {
163
+ e.preventDefault();
164
+ }
133
165
  }
134
166
  async function onKeydown(e) {
135
167
  if (['Enter', 'ArrowLeft', 'ArrowRight', 'Backspace', 'Delete', 'Tab'].includes(e.key) || e.ctrlKey) return;
@@ -149,14 +181,39 @@ export const VNumberInput = genericComponent()({
149
181
  e.stopPropagation();
150
182
  }
151
183
  function clampModel() {
184
+ if (controlsDisabled.value) return;
152
185
  if (!vTextFieldRef.value) return;
153
- const inputText = vTextFieldRef.value.value;
154
- if (inputText && !isNaN(+inputText)) {
155
- model.value = clamp(+inputText, props.min, props.max);
186
+ const actualText = vTextFieldRef.value.value;
187
+ if (actualText && !isNaN(+actualText)) {
188
+ inputText.value = correctPrecision(clamp(+actualText, props.min, props.max));
156
189
  } else {
157
- model.value = null;
190
+ inputText.value = null;
158
191
  }
159
192
  }
193
+ function formatInputValue() {
194
+ if (controlsDisabled.value) return;
195
+ if (model.value === null || isNaN(model.value)) {
196
+ inputText.value = null;
197
+ return;
198
+ }
199
+ inputText.value = props.precision == null ? String(model.value) : model.value.toFixed(props.precision);
200
+ }
201
+ function trimDecimalZeros() {
202
+ if (controlsDisabled.value) return;
203
+ if (model.value === null || isNaN(model.value)) {
204
+ inputText.value = null;
205
+ return;
206
+ }
207
+ inputText.value = model.value.toString();
208
+ }
209
+ function onFocus() {
210
+ isFocused.value = true;
211
+ trimDecimalZeros();
212
+ }
213
+ function onBlur() {
214
+ isFocused.value = false;
215
+ clampModel();
216
+ }
160
217
  useRender(() => {
161
218
  const {
162
219
  modelValue: _,
@@ -234,20 +291,21 @@ export const VNumberInput = genericComponent()({
234
291
  "class": "v-number-input__control"
235
292
  }, [_createVNode(VDivider, {
236
293
  "vertical": true
237
- }, null), incrementControlNode()]) : props.reverse ? undefined : _createVNode(_Fragment, null, [dividerNode(), controlNode()]);
294
+ }, null), incrementControlNode()]) : props.reverse || controlVariant.value === 'hidden' ? undefined : _createVNode(_Fragment, null, [dividerNode(), controlNode()]);
238
295
  const hasAppendInner = slots['append-inner'] || appendInnerControl;
239
296
  const prependInnerControl = controlVariant.value === 'split' ? _createVNode("div", {
240
297
  "class": "v-number-input__control"
241
298
  }, [decrementControlNode(), _createVNode(VDivider, {
242
299
  "vertical": true
243
- }, null)]) : props.reverse ? _createVNode(_Fragment, null, [controlNode(), dividerNode()]) : undefined;
300
+ }, null)]) : props.reverse && controlVariant.value !== 'hidden' ? _createVNode(_Fragment, null, [controlNode(), dividerNode()]) : undefined;
244
301
  const hasPrependInner = slots['prepend-inner'] || prependInnerControl;
245
302
  return _createVNode(VTextField, _mergeProps({
246
303
  "ref": vTextFieldRef,
247
- "modelValue": model.value,
248
- "onUpdate:modelValue": $event => model.value = $event,
304
+ "modelValue": inputText.value,
305
+ "onUpdate:modelValue": $event => inputText.value = $event,
249
306
  "onBeforeinput": onBeforeinput,
250
- "onChange": clampModel,
307
+ "onFocus": onFocus,
308
+ "onBlur": onBlur,
251
309
  "onKeydown": onKeydown,
252
310
  "class": ['v-number-input', {
253
311
  'v-number-input--default': controlVariant.value === 'default',