@teammodlr/ui-kit 3.0.0-beta.9 → 3.0.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.
Files changed (87) hide show
  1. package/lib/components/checkbox/Checkbox.vue.d.ts +4 -4
  2. package/lib/components/clearbutton/ClearButton.vue.d.ts +7 -0
  3. package/lib/components/clearbutton/style/ClearButton.css.d.ts +2 -0
  4. package/lib/components/clearbutton/style/index.d.ts +1 -0
  5. package/lib/components/colorpicker/ColorPicker.vue.d.ts +0 -1
  6. package/lib/components/colorpicker/style/ColorPicker.css.d.ts +1 -0
  7. package/lib/components/dialog/style/Dialog.css.d.ts +2 -0
  8. package/lib/components/drawer/Drawer.vue.d.ts +142 -0
  9. package/lib/components/drawer/style/Drawer.css.d.ts +33 -0
  10. package/lib/components/drawer/style/index.d.ts +1 -0
  11. package/lib/components/hovercard/HoverCard.vue.d.ts +122 -0
  12. package/lib/components/hovercard/style/HoverCard.css.d.ts +3 -0
  13. package/lib/components/hovercard/style/index.d.ts +1 -0
  14. package/lib/components/index.d.ts +3 -0
  15. package/lib/components/input/Input.vue.d.ts +20 -5
  16. package/lib/components/input/style/Input.css.d.ts +4 -0
  17. package/lib/components/paneldialog/PanelDialog.vue.d.ts +167 -0
  18. package/lib/components/paneldialog/style/PanelDialog.css.d.ts +8 -0
  19. package/lib/components/paneldialog/style/index.d.ts +1 -0
  20. package/lib/components/popover/Popover.vue.d.ts +24 -0
  21. package/lib/components/radio/Radio.vue.d.ts +5 -5
  22. package/lib/components/radiobutton/RadioButton.vue.d.ts +4 -4
  23. package/lib/components/select/Select.vue.d.ts +72 -91
  24. package/lib/components/select/style/Select.css.d.ts +9 -1
  25. package/lib/components/switch/Switch.vue.d.ts +4 -4
  26. package/lib/components/textarea/Textarea.vue.d.ts +16 -5
  27. package/lib/components/textarea/style/Textarea.css.d.ts +2 -0
  28. package/lib/composables/useInput.d.ts +9 -2
  29. package/lib/index.cjs.js +3 -3
  30. package/lib/index.es.js +8491 -6431
  31. package/lib/style.css +1 -1
  32. package/lib/tsconfig.app.tsbuildinfo +1 -0
  33. package/package.json +7 -4
  34. package/src/components/cardcontextmenu/style/Dropdown.css.ts +7 -0
  35. package/src/components/clearbutton/ClearButton.vue +39 -0
  36. package/src/components/clearbutton/style/ClearButton.css.ts +37 -0
  37. package/src/components/clearbutton/style/index.ts +1 -0
  38. package/src/components/colorpicker/ColorPicker.vue +8 -11
  39. package/src/components/colorpicker/examples/basic.vue +8 -17
  40. package/src/components/colorpicker/style/ColorPicker.css.ts +6 -1
  41. package/src/components/dialog/Dialog.vue +2 -5
  42. package/src/components/dialog/style/Dialog.css.ts +30 -0
  43. package/src/components/drawer/Drawer.vue +276 -0
  44. package/src/components/drawer/examples/basic.vue +15 -0
  45. package/src/components/drawer/examples/custom-title.vue +21 -0
  46. package/src/components/drawer/examples/index.stories.ts +24 -0
  47. package/src/components/drawer/examples/index.ts +7 -0
  48. package/src/components/drawer/examples/no-mask.vue +15 -0
  49. package/src/components/drawer/examples/no-outside-close.vue +15 -0
  50. package/src/components/drawer/examples/placements.vue +28 -0
  51. package/src/components/drawer/examples/with-footer.vue +21 -0
  52. package/src/components/drawer/examples/with-trigger.vue +13 -0
  53. package/src/components/drawer/style/Drawer.css.ts +208 -0
  54. package/src/components/drawer/style/index.ts +1 -0
  55. package/src/components/dropdown/Dropdown.vue +1 -1
  56. package/src/components/hovercard/HoverCard.vue +163 -0
  57. package/src/components/hovercard/style/HoverCard.css.ts +175 -0
  58. package/src/components/hovercard/style/index.ts +1 -0
  59. package/src/components/index.ts +3 -0
  60. package/src/components/input/Input.vue +52 -4
  61. package/src/components/input/examples/clearable.vue +18 -0
  62. package/src/components/input/examples/index.stories.ts +3 -1
  63. package/src/components/input/examples/index.ts +1 -0
  64. package/src/components/input/style/Input.css.ts +19 -0
  65. package/src/components/messageprovider/MessageProvider.vue +33 -7
  66. package/src/components/paneldialog/PanelDialog.vue +500 -0
  67. package/src/components/paneldialog/examples/basic.vue +36 -0
  68. package/src/components/paneldialog/examples/index.stories.ts +22 -0
  69. package/src/components/paneldialog/examples/index.ts +2 -0
  70. package/src/components/paneldialog/examples/modal.vue +31 -0
  71. package/src/components/paneldialog/style/PanelDialog.css.ts +90 -0
  72. package/src/components/paneldialog/style/index.ts +1 -0
  73. package/src/components/popover/Popover.vue +6 -1
  74. package/src/components/select/Select.vue +122 -42
  75. package/src/components/select/examples/clearable.vue +18 -0
  76. package/src/components/select/examples/fill.vue +52 -0
  77. package/src/components/select/examples/index.stories.ts +3 -1
  78. package/src/components/select/examples/index.ts +2 -0
  79. package/src/components/select/style/Select.css.ts +140 -24
  80. package/src/components/tab/Tab.vue +1 -1
  81. package/src/components/tab/style/Tab.css.ts +6 -0
  82. package/src/components/textarea/Textarea.vue +40 -4
  83. package/src/components/textarea/examples/clearable.vue +16 -0
  84. package/src/components/textarea/examples/index.stories.ts +2 -1
  85. package/src/components/textarea/examples/index.ts +1 -0
  86. package/src/components/textarea/style/Textarea.css.ts +10 -0
  87. package/src/composables/useInput.ts +10 -2
@@ -0,0 +1,208 @@
1
+ import {
2
+ globalKeyframes,
3
+ style,
4
+ styleVariants
5
+ } from '@vanilla-extract/css';
6
+ import { themeVars } from '../../../styles/theme.css';
7
+
8
+ export const mask = style({
9
+ position: 'fixed',
10
+ top: 0,
11
+ insetInlineEnd: 0,
12
+ bottom: 0,
13
+ insetInlineStart: 0,
14
+ height: '100%',
15
+ backgroundColor: 'hsla(0,0%,45.1%,0.7)'
16
+ });
17
+
18
+ const drawerBase = {
19
+ position: 'fixed' as const,
20
+ backgroundColor: '#fff',
21
+ display: 'flex',
22
+ flexDirection: 'column' as const,
23
+ boxShadow:
24
+ '0 6px 16px 0 rgba(0,0,0,0.08), 0 3px 6px -4px rgba(0,0,0,0.12), 0 9px 28px 8px rgba(0,0,0,0.05)',
25
+ selectors: {
26
+ '&:focus': { outline: 'none' },
27
+ '&:focus-visible': { outline: 'none' }
28
+ }
29
+ };
30
+
31
+ export const placement = styleVariants({
32
+ left: {
33
+ ...drawerBase,
34
+ top: 0,
35
+ left: 0,
36
+ bottom: 0,
37
+ height: '100%'
38
+ },
39
+ right: {
40
+ ...drawerBase,
41
+ top: 0,
42
+ right: 0,
43
+ bottom: 0,
44
+ height: '100%'
45
+ },
46
+ top: {
47
+ ...drawerBase,
48
+ top: 0,
49
+ left: 0,
50
+ right: 0,
51
+ width: '100%'
52
+ },
53
+ bottom: {
54
+ ...drawerBase,
55
+ bottom: 0,
56
+ left: 0,
57
+ right: 0,
58
+ width: '100%'
59
+ }
60
+ });
61
+
62
+ const DURATION = '0.28s';
63
+ const TIMING = 'cubic-bezier(0.16, 1, 0.3, 1)';
64
+
65
+ const SLIDE_LEFT_IN = 'drawer-slide-left-in';
66
+ const SLIDE_LEFT_OUT = 'drawer-slide-left-out';
67
+ const SLIDE_RIGHT_IN = 'drawer-slide-right-in';
68
+ const SLIDE_RIGHT_OUT = 'drawer-slide-right-out';
69
+ const SLIDE_TOP_IN = 'drawer-slide-top-in';
70
+ const SLIDE_TOP_OUT = 'drawer-slide-top-out';
71
+ const SLIDE_BOTTOM_IN = 'drawer-slide-bottom-in';
72
+ const SLIDE_BOTTOM_OUT = 'drawer-slide-bottom-out';
73
+
74
+ globalKeyframes(SLIDE_LEFT_IN, {
75
+ from: { transform: 'translateX(-100%)' },
76
+ to: { transform: 'translateX(0)' }
77
+ });
78
+ globalKeyframes(SLIDE_LEFT_OUT, {
79
+ from: { transform: 'translateX(0)' },
80
+ to: { transform: 'translateX(-100%)' }
81
+ });
82
+ globalKeyframes(SLIDE_RIGHT_IN, {
83
+ from: { transform: 'translateX(100%)' },
84
+ to: { transform: 'translateX(0)' }
85
+ });
86
+ globalKeyframes(SLIDE_RIGHT_OUT, {
87
+ from: { transform: 'translateX(0)' },
88
+ to: { transform: 'translateX(100%)' }
89
+ });
90
+ globalKeyframes(SLIDE_TOP_IN, {
91
+ from: { transform: 'translateY(-100%)' },
92
+ to: { transform: 'translateY(0)' }
93
+ });
94
+ globalKeyframes(SLIDE_TOP_OUT, {
95
+ from: { transform: 'translateY(0)' },
96
+ to: { transform: 'translateY(-100%)' }
97
+ });
98
+ globalKeyframes(SLIDE_BOTTOM_IN, {
99
+ from: { transform: 'translateY(100%)' },
100
+ to: { transform: 'translateY(0)' }
101
+ });
102
+ globalKeyframes(SLIDE_BOTTOM_OUT, {
103
+ from: { transform: 'translateY(0)' },
104
+ to: { transform: 'translateY(100%)' }
105
+ });
106
+
107
+ export const slideTransition = {
108
+ left: {
109
+ enterActive: style({ animation: `${DURATION} ${SLIDE_LEFT_IN} ${TIMING}`, willChange: 'transform' }),
110
+ leaveActive: style({ animation: `${DURATION} ${SLIDE_LEFT_OUT} ${TIMING}`, willChange: 'transform' }),
111
+ enterFrom: style({ transform: 'translateX(-100%)' }),
112
+ leaveTo: style({ transform: 'translateX(-100%)' })
113
+ },
114
+ right: {
115
+ enterActive: style({ animation: `${DURATION} ${SLIDE_RIGHT_IN} ${TIMING}`, willChange: 'transform' }),
116
+ leaveActive: style({ animation: `${DURATION} ${SLIDE_RIGHT_OUT} ${TIMING}`, willChange: 'transform' }),
117
+ enterFrom: style({ transform: 'translateX(100%)' }),
118
+ leaveTo: style({ transform: 'translateX(100%)' })
119
+ },
120
+ top: {
121
+ enterActive: style({ animation: `${DURATION} ${SLIDE_TOP_IN} ${TIMING}`, willChange: 'transform' }),
122
+ leaveActive: style({ animation: `${DURATION} ${SLIDE_TOP_OUT} ${TIMING}`, willChange: 'transform' }),
123
+ enterFrom: style({ transform: 'translateY(-100%)' }),
124
+ leaveTo: style({ transform: 'translateY(-100%)' })
125
+ },
126
+ bottom: {
127
+ enterActive: style({ animation: `${DURATION} ${SLIDE_BOTTOM_IN} ${TIMING}`, willChange: 'transform' }),
128
+ leaveActive: style({ animation: `${DURATION} ${SLIDE_BOTTOM_OUT} ${TIMING}`, willChange: 'transform' }),
129
+ enterFrom: style({ transform: 'translateY(100%)' }),
130
+ leaveTo: style({ transform: 'translateY(100%)' })
131
+ }
132
+ };
133
+
134
+ export const header = style({
135
+ display: 'flex',
136
+ justifyContent: 'space-between',
137
+ alignItems: 'center',
138
+ padding: `${themeVars.space[4]} ${themeVars.space[4]} 0 ${themeVars.space[4]}`,
139
+ flexShrink: '0'
140
+ });
141
+
142
+ export const title = style({
143
+ margin: 0,
144
+ fontSize: `${themeVars.fontSize.xlarge}`,
145
+ fontWeight: '500',
146
+ color: themeVars.color.font.default
147
+ });
148
+
149
+ export const close = style({
150
+ outline: 'none',
151
+ display: 'inline-flex',
152
+ alignItems: 'center',
153
+ justifyContent: 'center',
154
+ width: '1.5rem',
155
+ height: '1.5rem',
156
+ backgroundColor: 'transparent',
157
+ border: 'none',
158
+ padding: 0,
159
+ cursor: 'pointer',
160
+ borderRadius: themeVars.rounded.full,
161
+ position: 'relative',
162
+ transition: 'background-color 0.2s',
163
+ ':hover': {
164
+ backgroundColor: themeVars.color.gray[150]
165
+ },
166
+ ':focus-visible': {
167
+ outline: 'none',
168
+ backgroundColor: themeVars.color.gray[150]
169
+ },
170
+ '::before': {
171
+ content: '""',
172
+ position: 'absolute',
173
+ top: '50%',
174
+ left: '50%',
175
+ transform: 'translate(-50%, -50%) rotate(45deg)',
176
+ width: '0.8rem',
177
+ height: '2px',
178
+ backgroundColor: themeVars.color.gray[500],
179
+ transformOrigin: 'center'
180
+ },
181
+ '::after': {
182
+ content: '""',
183
+ position: 'absolute',
184
+ top: '50%',
185
+ left: '50%',
186
+ transform: 'translate(-50%, -50%) rotate(-45deg)',
187
+ width: '0.8rem',
188
+ height: '2px',
189
+ backgroundColor: themeVars.color.gray[500],
190
+ transformOrigin: 'center'
191
+ }
192
+ });
193
+
194
+ export const body = style({
195
+ padding: themeVars.space[4],
196
+ display: 'flex',
197
+ flexDirection: 'column',
198
+ flexGrow: '1',
199
+ overflowY: 'auto',
200
+ color: themeVars.color.font.text
201
+ });
202
+
203
+ export const footer = style({
204
+ display: 'flex',
205
+ alignItems: 'center',
206
+ padding: `0 ${themeVars.space[4]} ${themeVars.space[4]} ${themeVars.space[4]}`,
207
+ flexShrink: '0'
208
+ });
@@ -0,0 +1 @@
1
+ export * from './Drawer.css';
@@ -9,7 +9,7 @@
9
9
  </ContextMenuSubContent>
10
10
  </ContextMenuPortal>
11
11
  </ContextMenuSub>
12
- <ContextMenuRoot v-else-if="isContextMenu" v-model:open="isOpen" v-bind="$attrs">
12
+ <ContextMenuRoot v-else-if="isContextMenu" v-model:open="isOpen" :modal="modal" v-bind="$attrs">
13
13
  <ContextMenuTrigger as-child>
14
14
  <slot />
15
15
  </ContextMenuTrigger>
@@ -0,0 +1,163 @@
1
+ <template>
2
+ <HoverCardRoot
3
+ v-model:open="isOpen"
4
+ :open-delay="openDelay"
5
+ :close-delay="closeDelay"
6
+ >
7
+ <HoverCardTrigger as-child>
8
+ <slot />
9
+ </HoverCardTrigger>
10
+ <HoverCardPortal :disabled="!transfer">
11
+ <HoverCardContent
12
+ :class="contentClasses"
13
+ :side="resolvedSide"
14
+ :align="resolvedAlign"
15
+ :side-offset="sideOffset"
16
+ :collision-padding="collisionPadding"
17
+ :style="{ zIndex: zIndex }"
18
+ >
19
+ <slot name="content" />
20
+ <HoverCardArrow v-if="showArrow" :class="style.arrow" :width="12" :height="6" />
21
+ </HoverCardContent>
22
+ </HoverCardPortal>
23
+ </HoverCardRoot>
24
+ </template>
25
+
26
+ <script lang="ts">
27
+ import {
28
+ HoverCardArrow,
29
+ HoverCardContent,
30
+ HoverCardPortal,
31
+ HoverCardRoot,
32
+ HoverCardTrigger,
33
+ type HoverCardContentProps
34
+ } from 'reka-ui';
35
+ import {
36
+ computed,
37
+ defineComponent,
38
+ ref,
39
+ useAttrs,
40
+ watch,
41
+ type PropType
42
+ } from 'vue';
43
+ import {
44
+ type Placement,
45
+ placementWhileList
46
+ } from '../../composables/usePopper';
47
+ import { useZIndex } from '../../composables/useZIndex';
48
+ import * as style from './style';
49
+
50
+ export default defineComponent({
51
+ name: 'MHoverCard',
52
+ inheritAttrs: false,
53
+ components: {
54
+ HoverCardArrow,
55
+ HoverCardContent,
56
+ HoverCardPortal,
57
+ HoverCardRoot,
58
+ HoverCardTrigger
59
+ },
60
+ props: {
61
+ open: {
62
+ type: Boolean,
63
+ default: false
64
+ },
65
+ placement: {
66
+ type: String as PropType<Placement>,
67
+ default: 'bottom',
68
+ validator: (value: Placement) => placementWhileList.includes(value)
69
+ },
70
+ transfer: {
71
+ type: Boolean,
72
+ default: true
73
+ },
74
+ sideOffset: {
75
+ type: Number,
76
+ default: 5
77
+ },
78
+ collisionPadding: {
79
+ type: [Number, Object] as PropType<number | { top?: number; right?: number; bottom?: number; left?: number }>,
80
+ default: 10
81
+ },
82
+ arrow: {
83
+ type: Boolean,
84
+ default: false
85
+ },
86
+ variant: {
87
+ type: String as PropType<'light' | 'dark'>,
88
+ default: 'light'
89
+ },
90
+ openDelay: {
91
+ type: Number,
92
+ default: 700
93
+ },
94
+ closeDelay: {
95
+ type: Number,
96
+ default: 300
97
+ },
98
+ zIndex: {
99
+ type: Number
100
+ }
101
+ },
102
+ emits: ['update:open'],
103
+ setup(props, { emit }) {
104
+ const attrs = useAttrs();
105
+ const { nextZIndex } = useZIndex();
106
+ const isOpen = ref(props.open);
107
+ const zIndex = ref(props.zIndex ?? nextZIndex());
108
+
109
+ const resolvedPlacement = computed(() => {
110
+ const [side, align] = props.placement.split('-');
111
+
112
+ return {
113
+ side: side === 'top' || side === 'right' || side === 'bottom' || side === 'left'
114
+ ? side
115
+ : undefined,
116
+ align: align === 'start' || align === 'center' || align === 'end'
117
+ ? align
118
+ : undefined
119
+ } as {
120
+ side?: HoverCardContentProps['side'];
121
+ align?: HoverCardContentProps['align'];
122
+ };
123
+ });
124
+
125
+ const showArrow = computed(() => {
126
+ const { align } = resolvedPlacement.value;
127
+ return props.arrow && (!align || align === 'center');
128
+ });
129
+
130
+ const contentClasses = computed(() => {
131
+ return [
132
+ 'm-hover-card-content',
133
+ style.content,
134
+ {
135
+ [style.dark]: props.variant === 'dark'
136
+ },
137
+ attrs.class
138
+ ];
139
+ });
140
+
141
+ watch(
142
+ () => props.open,
143
+ value => {
144
+ isOpen.value = value;
145
+ }
146
+ );
147
+
148
+ watch(isOpen, value => {
149
+ emit('update:open', value);
150
+ });
151
+
152
+ return {
153
+ isOpen,
154
+ zIndex,
155
+ showArrow,
156
+ contentClasses,
157
+ resolvedSide: computed(() => resolvedPlacement.value.side),
158
+ resolvedAlign: computed(() => resolvedPlacement.value.align),
159
+ style
160
+ };
161
+ }
162
+ });
163
+ </script>
@@ -0,0 +1,175 @@
1
+ import { globalKeyframes, globalStyle, style } from '@vanilla-extract/css';
2
+ import { themeVars } from '../../../styles/theme.css';
3
+
4
+ const slideFadeOutTopAnimation = 'hover-card-slide-fade-out-top';
5
+ globalKeyframes(slideFadeOutTopAnimation, {
6
+ from: {
7
+ opacity: 1,
8
+ transform: 'translateY(0) scale(1)'
9
+ },
10
+ to: {
11
+ opacity: 0,
12
+ transform: 'translateY(6px) scale(0.98)'
13
+ }
14
+ });
15
+
16
+ const slideFadeOutBottomAnimation = 'hover-card-slide-fade-out-bottom';
17
+ globalKeyframes(slideFadeOutBottomAnimation, {
18
+ from: {
19
+ opacity: 1,
20
+ transform: 'translateY(0) scale(1)'
21
+ },
22
+ to: {
23
+ opacity: 0,
24
+ transform: 'translateY(-6px) scale(0.98)'
25
+ }
26
+ });
27
+
28
+ const slideFadeOutLeftAnimation = 'hover-card-slide-fade-out-left';
29
+ globalKeyframes(slideFadeOutLeftAnimation, {
30
+ from: {
31
+ opacity: 1,
32
+ transform: 'translateX(0) scale(1)'
33
+ },
34
+ to: {
35
+ opacity: 0,
36
+ transform: 'translateX(6px) scale(0.98)'
37
+ }
38
+ });
39
+
40
+ const slideFadeOutRightAnimation = 'hover-card-slide-fade-out-right';
41
+ globalKeyframes(slideFadeOutRightAnimation, {
42
+ from: {
43
+ opacity: 1,
44
+ transform: 'translateX(0) scale(1)'
45
+ },
46
+ to: {
47
+ opacity: 0,
48
+ transform: 'translateX(-6px) scale(0.98)'
49
+ }
50
+ });
51
+
52
+ const slideFadeTopAnimation = 'hover-card-slide-fade-top';
53
+ globalKeyframes(slideFadeTopAnimation, {
54
+ from: {
55
+ opacity: 0,
56
+ transform: 'translateY(6px) scale(0.98)'
57
+ },
58
+ to: {
59
+ opacity: 1,
60
+ transform: 'translateY(0) scale(1)'
61
+ }
62
+ });
63
+
64
+ const slideFadeBottomAnimation = 'hover-card-slide-fade-bottom';
65
+ globalKeyframes(slideFadeBottomAnimation, {
66
+ from: {
67
+ opacity: 0,
68
+ transform: 'translateY(-6px) scale(0.98)'
69
+ },
70
+ to: {
71
+ opacity: 1,
72
+ transform: 'translateY(0) scale(1)'
73
+ }
74
+ });
75
+
76
+ const slideFadeLeftAnimation = 'hover-card-slide-fade-left';
77
+ globalKeyframes(slideFadeLeftAnimation, {
78
+ from: {
79
+ opacity: 0,
80
+ transform: 'translateX(6px) scale(0.98)'
81
+ },
82
+ to: {
83
+ opacity: 1,
84
+ transform: 'translateX(0) scale(1)'
85
+ }
86
+ });
87
+
88
+ const slideFadeRightAnimation = 'hover-card-slide-fade-right';
89
+ globalKeyframes(slideFadeRightAnimation, {
90
+ from: {
91
+ opacity: 0,
92
+ transform: 'translateX(-6px) scale(0.98)'
93
+ },
94
+ to: {
95
+ opacity: 1,
96
+ transform: 'translateX(0) scale(1)'
97
+ }
98
+ });
99
+
100
+ export const content = style({
101
+ backgroundColor: '#ffffff',
102
+ borderRadius: '5px',
103
+ padding: '5px',
104
+ zIndex: 4000,
105
+ boxSizing: 'border-box',
106
+ position: 'relative',
107
+ minWidth: '130px',
108
+ maxWidth: '350px',
109
+ border: `1px solid ${themeVars.color.gray[300]}`,
110
+ boxShadow: themeVars.shadow.md,
111
+ transformOrigin: 'var(--reka-hover-card-content-transform-origin)',
112
+ willChange: 'transform, opacity',
113
+ outline: 'none',
114
+ selectors: {
115
+ '&[data-state="open"]': {
116
+ animationDuration: '0.16s',
117
+ animationTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)',
118
+ animationFillMode: 'both'
119
+ },
120
+ '&[data-state="closed"]': {
121
+ animationDuration: '0.12s',
122
+ animationTimingFunction: 'ease-out',
123
+ animationFillMode: 'both'
124
+ },
125
+ '&[data-state="closed"][data-side="top"]': {
126
+ animationName: slideFadeOutTopAnimation
127
+ },
128
+ '&[data-state="closed"][data-side="bottom"]': {
129
+ animationName: slideFadeOutBottomAnimation
130
+ },
131
+ '&[data-state="closed"][data-side="left"]': {
132
+ animationName: slideFadeOutLeftAnimation
133
+ },
134
+ '&[data-state="closed"][data-side="right"]': {
135
+ animationName: slideFadeOutRightAnimation
136
+ },
137
+ '&[data-state="open"][data-side="top"]': {
138
+ animationName: slideFadeTopAnimation
139
+ },
140
+ '&[data-state="open"][data-side="bottom"]': {
141
+ animationName: slideFadeBottomAnimation
142
+ },
143
+ '&[data-state="open"][data-side="left"]': {
144
+ animationName: slideFadeLeftAnimation
145
+ },
146
+ '&[data-state="open"][data-side="right"]': {
147
+ animationName: slideFadeRightAnimation
148
+ }
149
+ }
150
+ });
151
+
152
+ export const arrow = style({
153
+ fill: '#ffffff'
154
+ });
155
+
156
+ globalStyle(`${arrow} path`, {
157
+ fill: '#ffffff',
158
+ stroke: themeVars.color.gray[300],
159
+ strokeWidth: '1px'
160
+ });
161
+
162
+ export const dark = style({
163
+ backgroundColor: themeVars.color.gray[900],
164
+ border: `1px solid ${themeVars.color.gray[800]}`,
165
+ color: themeVars.color.gray[100]
166
+ });
167
+
168
+ globalStyle(`${dark} ${arrow}`, {
169
+ fill: themeVars.color.gray[900]
170
+ });
171
+
172
+ globalStyle(`${dark} ${arrow} path`, {
173
+ fill: themeVars.color.gray[900],
174
+ stroke: themeVars.color.gray[800]
175
+ });
@@ -0,0 +1 @@
1
+ export * from './HoverCard.css';
@@ -54,6 +54,9 @@ export { default as MVirtualScroll } from './virtualscroll/VirtualScroll.vue';
54
54
  export { default as MConfirm } from './confirm/Confirm.vue';
55
55
  export { default as MConfirmProvider } from './confirm/ConfirmProvider.vue';
56
56
  export { default as MDialog } from './dialog/Dialog.vue';
57
+ export { default as MPanelDialog } from './paneldialog/PanelDialog.vue';
57
58
  export { default as MDialogProvider } from './dialogprovider/DialogProvider.vue';
59
+ export { default as MDrawer } from './drawer/Drawer.vue';
58
60
  export { default as MTree } from './tree/Tree.vue';
59
61
  export { default as MPopover } from './popover/Popover.vue';
62
+ export { default as MHoverCard } from './hovercard/HoverCard.vue';
@@ -20,9 +20,10 @@
20
20
  :type="inputType"
21
21
  :placeholder="placeholder"
22
22
  :name="name"
23
- :value="modelValue || ''"
23
+ :value="currentValue"
24
24
  :readonly="readonly"
25
25
  v-on="inputListeners"
26
+ @input="onNativeInput"
26
27
  :class="inputComputedClasses"
27
28
  v-bind="$attrs"
28
29
  :disabled="disabled || loading"
@@ -32,6 +33,7 @@
32
33
  <div v-if="hasSuffix" :class="style.suffix">
33
34
  <slot name="suffix" />
34
35
  </div>
36
+ <MClearButton v-if="showClear" :class="clearClasses" @clear="onClear" />
35
37
  <div v-if="hasRightIcon" :class="style.rightIcon">
36
38
  <slot name="icon-right" />
37
39
  </div>
@@ -52,14 +54,17 @@ import {
52
54
  defineComponent,
53
55
  ref,
54
56
  computed,
55
- toRef
57
+ toRef,
58
+ watch
56
59
  } from "vue";
57
60
  import { useInput } from "../../composables/useInput";
58
61
  import { useInteractive } from "../../composables/useInteractive";
62
+ import MClearButton from '../clearbutton/ClearButton.vue';
59
63
  import * as style from './style';
60
64
 
61
65
  export default defineComponent({
62
66
  name: 'MInput',
67
+ components: { MClearButton },
63
68
  props: {
64
69
  ...useInput.props(),
65
70
  ...useInteractive.props(),
@@ -100,11 +105,15 @@ export default defineComponent({
100
105
  default: false
101
106
  },
102
107
  error: {
103
- type: String,
108
+ type: String as PropType<string | null>,
104
109
  default: ''
105
110
  },
111
+ clearable: {
112
+ type: Boolean,
113
+ default: false
114
+ },
106
115
  },
107
- emits: useInput.emits(),
116
+ emits: [...useInput.emits(), 'clear'],
108
117
  setup(props, { slots, emit, expose }) {
109
118
  const element = ref<HTMLInputElement|null>(null);
110
119
  const { focus, blur } = useInteractive(element);
@@ -170,6 +179,8 @@ export default defineComponent({
170
179
  [style.disabled]: disabled.value || loading.value,
171
180
  [style.hasLeftIcon]: hasLeftIcon.value,
172
181
  [style.hasRightIcon]: hasRightIcon.value,
182
+ [style.hasClear]: props.clearable,
183
+ [style.hasClearAndRightIcon]: props.clearable && hasRightIcon.value,
173
184
  }
174
185
  ];
175
186
 
@@ -193,8 +204,41 @@ export default defineComponent({
193
204
  return formError.value || props.error;
194
205
  });
195
206
 
207
+ // Tracks typed text so clearable works without v-model
208
+ const internalValue = ref<any>(props.modelValue ?? '');
209
+ watch(() => props.modelValue, value => {
210
+ internalValue.value = value ?? '';
211
+ });
212
+
213
+ const currentValue = computed(() => {
214
+ const value = props.modelValue !== undefined ? props.modelValue : internalValue.value;
215
+ return value || '';
216
+ });
217
+
218
+ const onNativeInput = (event: Event) => {
219
+ internalValue.value = (event.target as HTMLInputElement).value;
220
+ };
221
+
222
+ const showClear = computed(() => {
223
+ return props.clearable
224
+ && !disabled.value
225
+ && !loading.value
226
+ && !props.readonly
227
+ && currentValue.value !== '';
228
+ });
229
+
230
+ const clearClasses = computed(() => {
231
+ return [
232
+ style.clear,
233
+ { [style.clearWithRightIcon]: hasRightIcon.value }
234
+ ];
235
+ });
236
+
196
237
  const onClear = () => {
238
+ internalValue.value = '';
197
239
  emit('update:modelValue', '');
240
+ emit('clear');
241
+ focus();
198
242
  };
199
243
 
200
244
  expose({
@@ -220,6 +264,10 @@ export default defineComponent({
220
264
  hasHelpMessage,
221
265
  inputError,
222
266
  style,
267
+ showClear,
268
+ clearClasses,
269
+ currentValue,
270
+ onNativeInput,
223
271
 
224
272
  onClear,
225
273
  validate,