@veritree/ui 0.27.0 → 0.28.0-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.
Files changed (116) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/index.js +105 -75
  3. package/mixins/floating-ui-content.js +17 -4
  4. package/mixins/floating-ui-item.js +31 -15
  5. package/mixins/floating-ui.js +142 -24
  6. package/mixins/form-control-icon.js +3 -3
  7. package/mixins/form-control.js +45 -20
  8. package/nuxt.js +38 -26
  9. package/package.json +17 -6
  10. package/src/components/Alert/VTAlert.vue +55 -14
  11. package/src/components/Avatar/VTAvatarImage.vue +6 -26
  12. package/src/components/Badge/VTBadge.vue +60 -0
  13. package/src/components/Badge/VTBadgeNew.vue +60 -0
  14. package/src/components/Breadcrumb/VTBreadcrumbItem.vue +11 -0
  15. package/src/components/Breadcrumb/VTBreadcrumbLink.vue +40 -0
  16. package/src/components/Breadcrumb/VTBreadcrumbList.vue +11 -0
  17. package/src/components/Breadcrumb/VTBreadcrumbRoot.vue +11 -0
  18. package/src/components/Breadcrumb/VTBreadcrumbSeparator.vue +19 -0
  19. package/src/components/Button/VTButton.vue +104 -56
  20. package/src/components/Carousel/VTCarousel.vue +69 -0
  21. package/src/components/Carousel/VTCarouselBackward.vue +36 -0
  22. package/src/components/Carousel/VTCarouselForward.vue +38 -0
  23. package/src/components/Carousel/VTCarouselTracker.vue +80 -0
  24. package/src/components/Checkbox/VTCheckbox.vue +134 -0
  25. package/src/components/Checkbox/VTCheckboxLabel.vue +3 -0
  26. package/src/components/Checkbox/VTCheckboxText.vue +20 -0
  27. package/src/components/Chip/VTChip.vue +29 -0
  28. package/src/components/Dialog/VTDialog.vue +59 -25
  29. package/src/components/Dialog/VTDialogClose.vue +3 -2
  30. package/src/components/Dialog/VTDialogContent.vue +29 -7
  31. package/src/components/Dialog/VTDialogFooter.vue +17 -2
  32. package/src/components/Dialog/VTDialogHeader.vue +2 -1
  33. package/src/components/Dialog/VTDialogMain.vue +5 -1
  34. package/src/components/Dialog/VTDialogOverlay.vue +5 -1
  35. package/src/components/Dialog/VTDialogTitle.vue +1 -1
  36. package/src/components/Disclosure/VTDisclosure.vue +2 -11
  37. package/src/components/Disclosure/VTDisclosureContent.vue +26 -52
  38. package/src/components/Disclosure/VTDisclosureDetails.vue +27 -2
  39. package/src/components/Disclosure/VTDisclosureHeader.vue +56 -89
  40. package/src/components/Disclosure/VTDisclosureIcon.vue +42 -31
  41. package/src/components/Divider/VTDivider.vue +9 -0
  42. package/src/components/Drawer/VTDrawer.vue +6 -15
  43. package/src/components/Drawer/VTDrawerClose.vue +5 -5
  44. package/src/components/Drawer/VTDrawerContent.vue +10 -10
  45. package/src/components/Drawer/VTDrawerFooter.vue +4 -4
  46. package/src/components/Drawer/VTDrawerHeader.vue +4 -4
  47. package/src/components/Drawer/VTDrawerMain.vue +5 -5
  48. package/src/components/Drawer/VTDrawerOverlay.vue +6 -6
  49. package/src/components/Drawer/VTDrawerTitle.vue +5 -5
  50. package/src/components/DropdownMenu/VTDropdownMenu.vue +0 -6
  51. package/src/components/DropdownMenu/VTDropdownMenuContent.vue +10 -1
  52. package/src/components/DropdownMenu/VTDropdownMenuDivider.vue +7 -16
  53. package/src/components/DropdownMenu/VTDropdownMenuItem.vue +5 -1
  54. package/src/components/DropdownMenu/VTDropdownMenuLabel.vue +1 -10
  55. package/src/components/DropdownMenu/VTDropdownMenuTrigger.vue +2 -4
  56. package/src/components/Form/VTFieldset.vue +5 -0
  57. package/src/components/Form/VTForm.vue +11 -0
  58. package/src/components/Form/VTFormCol.vue +20 -0
  59. package/src/components/Form/VTFormFeedback.vue +7 -1
  60. package/src/components/Form/VTFormGroup.vue +5 -7
  61. package/src/components/Form/VTFormLabel.vue +22 -0
  62. package/src/components/Form/VTFormLabelHelper.vue +22 -0
  63. package/src/components/Form/VTFormRow.vue +5 -0
  64. package/src/components/Form/VTInput.vue +2 -5
  65. package/src/components/Form/VTInputDate.vue +602 -0
  66. package/src/components/Form/VTInputIcon.vue +3 -9
  67. package/src/components/Form/VTInputNumber.vue +198 -0
  68. package/src/components/Form/VTInputPassword.vue +14 -5
  69. package/src/components/Form/VTInputRange.vue +92 -0
  70. package/src/components/Form/VTLegend.vue +24 -0
  71. package/src/components/Form/VTTextarea.vue +2 -2
  72. package/src/components/Image/VTImage.vue +10 -10
  73. package/src/components/Listbox/VTListbox.vue +128 -9
  74. package/src/components/Listbox/VTListboxContent.vue +14 -1
  75. package/src/components/Listbox/VTListboxDivider.vue +21 -0
  76. package/src/components/Listbox/VTListboxGroup.vue +9 -0
  77. package/src/components/Listbox/VTListboxItem.vue +57 -15
  78. package/src/components/Listbox/VTListboxLabel.vue +5 -4
  79. package/src/components/Listbox/VTListboxList.vue +1 -6
  80. package/src/components/Listbox/VTListboxPlaceholder.vue +25 -0
  81. package/src/components/Listbox/VTListboxSearch.vue +12 -8
  82. package/src/components/Listbox/VTListboxTrigger.vue +87 -6
  83. package/src/components/Listbox/VTListboxTriggerHighlight.vue +204 -0
  84. package/src/components/Listbox/VTListboxViewport.vue +33 -0
  85. package/src/components/Popover/VTPopoverContent.vue +3 -3
  86. package/src/components/Popover/VTPopoverDivider.vue +1 -1
  87. package/src/components/Popover/VTPopoverItem.vue +6 -2
  88. package/src/components/ProgressBar/VTProgressBar.vue +35 -10
  89. package/src/components/ProgressBar/VTProgressBarIndicator.vue +53 -0
  90. package/src/components/ScrollShadows/VTScrollShadows.vue +76 -0
  91. package/src/components/Separator/VTSeparator.vue +13 -0
  92. package/src/components/Switch/VTSwitch.vue +61 -0
  93. package/src/components/Tabs/VTTab.vue +6 -5
  94. package/src/components/Tabs/VTTabGroup.vue +88 -9
  95. package/src/components/Tabs/VTTabPanel.vue +4 -5
  96. package/src/components/Toast/README.md +263 -0
  97. package/src/components/Toast/VTToast.vue +145 -0
  98. package/src/components/Toast/VTToastAction.vue +25 -0
  99. package/src/components/Toast/VTToastClose.vue +52 -0
  100. package/src/components/Toast/VTToastContent.vue +25 -0
  101. package/src/components/Toast/VTToastDescription.vue +36 -0
  102. package/src/components/Toast/VTToastIcon.vue +72 -0
  103. package/src/components/Toast/VTToastItem.vue +180 -0
  104. package/src/components/Toast/VTToastTitle.vue +34 -0
  105. package/src/components/Tooltip/VTTooltipTrigger.vue +3 -5
  106. package/src/components/Transitions/FadeInOut.vue +2 -2
  107. package/src/components/Utils/FloatingUi.vue +31 -13
  108. package/src/helpers/currency.js +21 -0
  109. package/src/utils/components.js +18 -0
  110. package/src/utils/images.js +31 -12
  111. package/src/components/Input/VTInput.vue +0 -82
  112. package/src/components/Input/VTInputDate.vue +0 -36
  113. package/src/components/Input/VTInputFile.vue +0 -60
  114. package/src/components/Input/VTInputUpload.vue +0 -54
  115. package/src/components/Modal/VTModal.vue +0 -69
  116. package/src/utils/genId.js +0 -13
@@ -1,58 +1,21 @@
1
1
  <template>
2
- <!-- :href="href" -->
3
2
  <component
4
3
  :is="tag"
5
4
  :to="to"
6
5
  :href="href || to"
7
6
  :type="type"
8
7
  :disabled="isDisabled"
9
- :class="[
10
- // default styles
11
- headless
12
- ? 'button'
13
- : isIcon
14
- ? 'inline-flex items-center justify-center rounded-full [&_svg]:max-h-full [&_svg]:max-w-full'
15
- : 'relative inline-flex rounded border border-solid px-4 text-sm font-semibold leading-none no-underline transition-all',
16
- // variant styles
17
- headless
18
- ? `button--${variant}`
19
- : isPrimary
20
- ? 'bg-secondary-400 hover:bg-secondary-500 focus:bg-secondary-600 active:bg-secondary-600 border-transparent text-white disabled:bg-gray-200 disabled:text-gray-400'
21
- : isSecondary
22
- ? 'border-gray-400 bg-white text-gray-700 hover:bg-gray-100 hover:bg-gray-200 active:bg-gray-200 disabled:border-gray-300 disabled:text-gray-400'
23
- : isTertiary
24
- ? 'text-secondary-400 hover:text-secondary-500 focus:text-secondary-600 active:text-secondary-600 border-transparent disabled:text-gray-400'
25
- : isIcon
26
- ? 'text-primary-100 focus-within:bg-gray-200 hover:bg-gray-200 active:bg-gray-300'
27
- : null,
28
- // sizes styles
29
- headless
30
- ? `button--${size}`
31
- : isLarge
32
- ? isIcon
33
- ? 'h-8 w-8'
34
- : 'h-10'
35
- : isSmall
36
- ? isIcon
37
- ? 'h-6 w-6 p-1'
38
- : 'h-8'
39
- : null,
40
- ]"
41
- v-on="$listeners"
8
+ :class="buttonClasses"
42
9
  >
43
10
  <VTSpinner v-if="busy" class="absolute inset-0 m-auto" />
44
- <span
45
- :class="[
46
- headless ? null : 'mx-auto inline-flex items-center gap-2 self-center',
47
- headless && busy ? 'button--busy' : busy ? 'invisible' : null,
48
- ]"
49
- >
11
+ <span :class="spanClasses">
50
12
  <slot></slot>
51
13
  </span>
52
14
  </component>
53
15
  </template>
54
16
 
55
17
  <script>
18
+ import { resolveComponent } from 'vue';
56
19
  import VTSpinner from '../Spinner/VTSpinner.vue';
57
20
 
58
21
  export default {
@@ -64,64 +27,149 @@ export default {
64
27
  variant: {
65
28
  type: String,
66
29
  default: 'primary',
30
+ validator(value) {
31
+ return ['primary', 'secondary', 'tertiary', 'dark', 'icon'].includes(
32
+ value,
33
+ );
34
+ },
67
35
  },
36
+
68
37
  size: {
69
38
  type: String,
70
39
  default: 'large',
40
+ validator(value) {
41
+ return ['small', 'large'].includes(value);
42
+ },
71
43
  },
44
+
72
45
  to: {
73
46
  type: [String, Object],
74
47
  default: null,
75
48
  },
49
+
76
50
  href: {
77
51
  type: [String, Object],
78
52
  default: null,
79
53
  },
54
+
80
55
  headless: {
81
56
  type: Boolean,
82
57
  default: false,
83
58
  },
59
+
84
60
  busy: {
85
61
  type: Boolean,
86
62
  default: false,
87
63
  },
64
+
88
65
  disabled: {
89
66
  type: Boolean,
90
67
  default: false,
91
68
  },
69
+
70
+ appearance: {
71
+ type: String,
72
+ default: 'normal',
73
+ validator(value) {
74
+ return ['normal', 'ghost'].includes(value);
75
+ },
76
+ },
77
+
78
+ version: {
79
+ type: String,
80
+ default: '1',
81
+ },
92
82
  },
93
83
 
94
84
  computed: {
95
- isPrimary() {
96
- return this.variant === 'primary';
97
- },
85
+ buttonClasses() {
86
+ const classes = [];
87
+
88
+ if (this.headless) {
89
+ classes.push('button');
90
+ classes.push(`button--${this.variant}`);
91
+ classes.push(`button--${this.size}`);
92
+ } else {
93
+ if (!this.isIcon) {
94
+ classes.push('button-base');
95
+ }
96
+
97
+ if (this.variant === 'primary') {
98
+ classes.push('button--primary');
99
+ }
98
100
 
99
- isSecondary() {
100
- return this.variant === 'secondary';
101
+ if (this.variant === 'secondary') {
102
+ classes.push('button--secondary');
103
+ }
104
+
105
+ if (this.variant === 'tertiary') {
106
+ classes.push('button--tertiary');
107
+ }
108
+
109
+ if (this.variant === 'dark') {
110
+ classes.push('button--dark');
111
+ }
112
+
113
+ if (this.isIcon) {
114
+ classes.push('button--icon');
115
+ }
116
+
117
+ if (this.isGhost) {
118
+ classes.push('button--ghost');
119
+ }
120
+
121
+ if (this.size === 'large') {
122
+ classes.push(this.isIcon ? 'h-8 w-8' : 'button--large');
123
+ } else if (this.size === 'small') {
124
+ classes.push(this.isIcon ? 'h-6 w-6 p-1' : 'button--small');
125
+ }
126
+
127
+ if (this.version && this.version !== '1') {
128
+ classes.push(`button--version-${this.version}`);
129
+ }
130
+ }
131
+
132
+ if (this.isDisabled && this.isIcon) {
133
+ classes.push('[&_svg]:text-gray-400');
134
+ }
135
+
136
+ return classes.filter(Boolean);
101
137
  },
102
138
 
103
- isTertiary() {
104
- return this.variant === 'tertiary';
139
+ spanClasses() {
140
+ const classes = [];
141
+
142
+ if (!this.headless) {
143
+ classes.push(
144
+ 'mx-auto inline-flex items-center gap-2 self-center pointer-events-none',
145
+ );
146
+ }
147
+
148
+ if (this.headless && this.busy) {
149
+ classes.push('button--busy');
150
+ } else if (this.busy) {
151
+ classes.push('invisible');
152
+ }
153
+
154
+ return classes.filter(Boolean);
105
155
  },
106
156
 
107
157
  isIcon() {
108
158
  return this.variant === 'icon';
109
159
  },
110
160
 
111
- isLarge() {
112
- return this.size === 'large';
113
- },
114
-
115
- isSmall() {
116
- return this.size === 'small';
161
+ isDisabled() {
162
+ return (this.disabled || this.busy) || undefined;
117
163
  },
118
164
 
119
- isDisabled() {
120
- return this.disabled || this.busy;
165
+ isGhost() {
166
+ return this.appearance === 'ghost';
121
167
  },
122
168
 
123
169
  tag() {
124
- return this.href ? 'a' : this.to ? 'NuxtLink' : 'button';
170
+ if (this.href) return 'a';
171
+ if (this.to) return resolveComponent('NuxtLink');
172
+ return 'button';
125
173
  },
126
174
 
127
175
  type() {
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <div class="relative overflow-hidden">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'VTCarousel',
10
+
11
+ provide() {
12
+ return {
13
+ apiCarousel: () => {
14
+ const registerElTracker = (elTracker) => {
15
+ if (!elTracker) return;
16
+ this.elTracker = elTracker;
17
+ };
18
+
19
+ return {
20
+ elTracker: this.elTracker,
21
+ hasContentOverflow: this.hasContentOverflow,
22
+ hasScrolledToLeftEnd: this.hasScrolledToLeftEnd,
23
+ hasScrolledToLeftStart: this.hasScrolledToLeftStart,
24
+ isLeftEndReached: this.isLeftEndReached,
25
+ isLeftStartReached: this.isLeftStartReached,
26
+ onObserveTracker: this.onObserveTracker,
27
+ registerElTracker,
28
+ };
29
+ },
30
+ };
31
+ },
32
+
33
+ data() {
34
+ return {
35
+ elTracker: null,
36
+ hasContentOverflow: false,
37
+ hasScrolledToLeftEnd: false,
38
+ hasScrolledToLeftStart: true,
39
+ };
40
+ },
41
+
42
+ mounted() {
43
+ this.hasContentOverflow = this.isContentOverflowing();
44
+ },
45
+
46
+ methods: {
47
+ onObserveTracker() {
48
+ this.hasContentOverflow = this.isContentOverflowing();
49
+ },
50
+
51
+ isLeftEndReached() {
52
+ const { offsetWidth, scrollLeft, scrollWidth } = this.elTracker;
53
+ const distanceToLeftEnd = Math.abs(
54
+ scrollWidth - offsetWidth - scrollLeft,
55
+ );
56
+ this.hasScrolledToLeftEnd = distanceToLeftEnd <= 10;
57
+ },
58
+
59
+ isLeftStartReached() {
60
+ const { scrollLeft } = this.elTracker;
61
+ this.hasScrolledToLeftStart = scrollLeft === 0;
62
+ },
63
+
64
+ isContentOverflowing() {
65
+ return this.elTracker.offsetWidth !== this.elTracker.scrollWidth;
66
+ },
67
+ },
68
+ };
69
+ </script>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div
3
+ :class="[visible ? 'pointer-events-none opacity-0' : 'opacity-100']"
4
+ class="flex items-center justify-start transition-opacity duration-100"
5
+ >
6
+ <slot :scroll-backward="scrollBackward" />
7
+ </div>
8
+ </template>
9
+
10
+ <script>
11
+ export default {
12
+ name: 'VTCarouselBackward',
13
+
14
+ inject: ['apiCarousel'],
15
+
16
+ computed: {
17
+ carousel() {
18
+ return this.apiCarousel();
19
+ },
20
+
21
+ elTracker() {
22
+ return this.carousel.elTracker;
23
+ },
24
+
25
+ visible() {
26
+ return this.carousel.hasScrolledToLeftStart;
27
+ },
28
+ },
29
+
30
+ methods: {
31
+ scrollBackward() {
32
+ this.elTracker.scrollLeft -= 200;
33
+ },
34
+ },
35
+ };
36
+ </script>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div
3
+ :class="[visible ? 'opacity-100' : 'pointer-events-none opacity-0']"
4
+ class="flex items-center justify-end transition-opacity duration-100"
5
+ >
6
+ <slot :scroll-forward="scrollForward" />
7
+ </div>
8
+ </template>
9
+
10
+ <script>
11
+ export default {
12
+ name: 'VTCarouselForward',
13
+
14
+ inject: ['apiCarousel'],
15
+
16
+ computed: {
17
+ carousel() {
18
+ return this.apiCarousel();
19
+ },
20
+
21
+ elTracker() {
22
+ return this.carousel.elTracker;
23
+ },
24
+
25
+ visible() {
26
+ return (
27
+ this.carousel.hasContentOverflow && !this.carousel.hasScrolledToLeftEnd
28
+ );
29
+ },
30
+ },
31
+
32
+ methods: {
33
+ scrollForward() {
34
+ this.elTracker.scrollLeft += 200;
35
+ },
36
+ },
37
+ };
38
+ </script>
@@ -0,0 +1,80 @@
1
+ <template>
2
+ <div class="relative flex snap-start overflow-x-scroll [&>*]:shrink-0">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ name: 'VTCarouselTracker',
10
+
11
+ inject: ['apiCarousel'],
12
+
13
+ data() {
14
+ return {
15
+ mutationObserver: null,
16
+ resizeObserver: null,
17
+ };
18
+ },
19
+
20
+ beforeUnmount() {
21
+ if (!this.$el) {
22
+ return;
23
+ }
24
+
25
+ this.$el.removeEventListener('scroll', this.onScroll);
26
+ this.mutationObserver?.disconnect();
27
+ this.resizeObserver?.disconnect();
28
+ },
29
+
30
+ mounted() {
31
+ this.registerElTracker();
32
+ this.registerMutationObserver();
33
+ this.registerResizeObserver();
34
+ this.addEventListeners();
35
+ },
36
+
37
+ methods: {
38
+ registerElTracker() {
39
+ this.apiCarousel().registerElTracker(this.$el);
40
+ },
41
+
42
+ registerResizeObserver() {
43
+ this.resizeObserver = new ResizeObserver(() => {
44
+ this.apiCarousel().onObserveTracker();
45
+ });
46
+
47
+ this.resizeObserver.observe(this.$el);
48
+ },
49
+
50
+ registerMutationObserver() {
51
+ this.mutationObserver = new MutationObserver(() => {
52
+ this.apiCarousel().onObserveTracker();
53
+ });
54
+
55
+ this.mutationObserver.observe(this.$el, {
56
+ childList: true,
57
+ });
58
+ },
59
+
60
+ addEventListeners() {
61
+ this.$el.addEventListener('scroll', this.onScroll);
62
+ },
63
+
64
+ onScroll() {
65
+ this.apiCarousel().isLeftEndReached();
66
+ this.apiCarousel().isLeftStartReached();
67
+ },
68
+ },
69
+ };
70
+ </script>
71
+
72
+ <style scoped>
73
+ div {
74
+ scrollbar-width: none;
75
+
76
+ &::-webkit-scrollbar {
77
+ display: none;
78
+ }
79
+ }
80
+ </style>
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <input
3
+ type="checkbox"
4
+ v-model="modelValueComputed"
5
+ :value="value"
6
+ :checked="checked"
7
+ :disabled="disabled"
8
+ :indeterminate="indeterminate"
9
+ :class="[
10
+ headless
11
+ ? 'input-checkbox'
12
+ : 'h-[18px] w-[18px] shrink-0 appearance-none rounded border border-solid bg-no-repeat align-middle focus-visible:ring-2 focus-visible:ring-white',
13
+ headless
14
+ ? `input-checkbox--${variant}`
15
+ : isError
16
+ ? 'border-error-300'
17
+ : 'border-gray-300',
18
+ checked
19
+ ? headless
20
+ ? 'input-checkbox--checked'
21
+ : 'border-secondary-300 bg-secondary-300'
22
+ : null,
23
+ disabled
24
+ ? headless
25
+ ? 'input-checkbox--disabled'
26
+ : 'pointer-events-none bg-gray-100'
27
+ : null,
28
+ indeterminate
29
+ ? headless
30
+ ? 'input-checkbox--indeterminate'
31
+ : 'border-secondary-200 bg-secondary-200'
32
+ : null,
33
+ ]"
34
+ v-bind="$attrs"
35
+ @change="onChange"
36
+ />
37
+ </template>
38
+
39
+ <script>
40
+ /**
41
+ * Notes:
42
+ * - Not tested with an array yet
43
+ */
44
+ export default {
45
+ props: {
46
+ disabled: {
47
+ type: Boolean,
48
+ default: false,
49
+ },
50
+ indeterminate: {
51
+ type: Boolean,
52
+ default: false,
53
+ },
54
+ headless: {
55
+ type: Boolean,
56
+ default: false,
57
+ },
58
+ modelValue: {
59
+ type: [Array, Boolean],
60
+ default: null,
61
+ },
62
+ variant: {
63
+ type: [String, Object, Function],
64
+ default: '',
65
+ },
66
+ value: {
67
+ type: [Boolean, Object],
68
+ default: null,
69
+ },
70
+ },
71
+
72
+ data() {
73
+ return {
74
+ checked: false,
75
+ };
76
+ },
77
+
78
+ computed: {
79
+ modelValueComputed: {
80
+ get() {
81
+ return this.modelValue;
82
+ },
83
+ set(value) {
84
+ this.$emit('update:modelValue', value);
85
+ },
86
+ },
87
+
88
+ isError() {
89
+ return this.variant === 'error';
90
+ },
91
+ },
92
+
93
+ watch: {
94
+ indeterminate(newVal) {
95
+ this.checked = !newVal;
96
+ this.$el.indeterminate = newVal;
97
+ },
98
+
99
+ checked(newVal) {
100
+ if (newVal) {
101
+ this.$el.indeterminate = false;
102
+ this.$emit('update:indeterminate', false);
103
+ }
104
+ },
105
+ },
106
+
107
+ mounted() {
108
+ if (this.indeterminate) {
109
+ this.$el.indeterminate = this.indeterminate;
110
+ }
111
+ },
112
+
113
+ methods: {
114
+ onChange(event) {
115
+ this.checked = event.target.checked;
116
+ },
117
+ },
118
+ };
119
+ </script>
120
+
121
+ <style scoped>
122
+ input:not(.input-checkbox):checked,
123
+ input:not(.input-checkbox):indeterminate {
124
+ background-size: cover;
125
+ }
126
+
127
+ input:not(.input-checkbox):checked {
128
+ background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9.00016 16.17L4.83016 12L3.41016 13.41L9.00016 19L21.0002 7.00003L19.5902 5.59003L9.00016 16.17Z' fill='%23ffffff'/%3E%3Cpath d='M9.00016 16.17L4.83016 12L3.41016 13.41L9.00016 19L21.0002 7.00003L19.5902 5.59003L9.00016 16.17Z' fill='%23ffffff' /%3E%3C/svg%3E%0A");
129
+ }
130
+
131
+ input:not(.input-checkbox):indeterminate {
132
+ background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M19 13H5V11H19V13Z' fill='%23ffffff'/%3E%3Cpath d='M19 13H5V11H19V13Z' fill='%23ffffff'/%3E%3C/svg%3E%0A");
133
+ }
134
+ </style>
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <label class="flex items-start gap-2"><slot /></label>
3
+ </template>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <component :is="as" :class="[headless ? 'input-checkbox-text' : 'text-sm']"
3
+ ><slot />
4
+ </component>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ props: {
10
+ as: {
11
+ type: String,
12
+ default: 'div',
13
+ },
14
+ headless: {
15
+ type: Boolean,
16
+ default: false,
17
+ },
18
+ },
19
+ };
20
+ </script>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <div
3
+ class="Chip flex shrink-0 items-center gap-2 rounded-full bg-gray-200 py-0.5 pl-2 pr-[3px] text-sm text-gray-800"
4
+ >
5
+ <span class="Chip-text truncate whitespace-nowrap"><slot></slot></span>
6
+ <button
7
+ class="Chip-button shrink-0 text-gray-500 hover:text-gray-600"
8
+ @click.stop.prevent="onCancel"
9
+ >
10
+ <IconCancel class="Chip-button__icon h-5 w-5" />
11
+ </button>
12
+ </div>
13
+ </template>
14
+
15
+ <script>
16
+ import { IconCancel } from '@veritree/icons';
17
+
18
+ export default {
19
+ name: 'VTChip',
20
+
21
+ components: { IconCancel },
22
+
23
+ methods: {
24
+ onCancel() {
25
+ this.$emit('cancel');
26
+ },
27
+ },
28
+ };
29
+ </script>