@teammodlr/ui-kit 2.3.23 → 3.0.0-beta.2

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 (93) hide show
  1. package/lib/components/avatar/Avatar.vue.d.ts +2 -2
  2. package/lib/components/badge/style/Badge.css.d.ts +2 -2
  3. package/lib/components/button/Button.vue.d.ts +7 -4
  4. package/lib/components/button/style/Button.css.d.ts +3 -3
  5. package/lib/components/cardcontextmenu/CardContextMenu.vue.d.ts +5 -8
  6. package/lib/components/cardcontextmenu/CardContextMenuItem.vue.d.ts +11 -2
  7. package/lib/components/cardcontextmenu/CardContextMenuTriggerProvider.vue.d.ts +2 -0
  8. package/lib/components/cardcontextmenu/style/Dropdown.css.d.ts +2 -1
  9. package/lib/components/cardcontextmenu/symbol.d.ts +1 -0
  10. package/lib/components/checkbox/Checkbox.vue.d.ts +15 -4
  11. package/lib/components/collapse/CollapseItem.vue.d.ts +3 -2
  12. package/lib/components/colorpicker/ColorPicker.vue.d.ts +8 -9
  13. package/lib/components/confirm/Confirm.vue.d.ts +9 -0
  14. package/lib/components/confirm/props.d.ts +4 -0
  15. package/lib/components/dialog/Dialog.vue.d.ts +9 -4
  16. package/lib/components/dialogprovider/DialogProvider.vue.d.ts +1 -0
  17. package/lib/components/dialogprovider/types.d.ts +1 -0
  18. package/lib/components/dropdown/Dropdown.vue.d.ts +3 -1
  19. package/lib/components/dropdown/DropdownItem.vue.d.ts +11 -1
  20. package/lib/components/dropdown/DropdownSeperator.vue.d.ts +1 -0
  21. package/lib/components/dropdown/DropdownTriggerProvider.vue.d.ts +2 -0
  22. package/lib/components/dropdown/style/Dropdown.css.d.ts +2 -1
  23. package/lib/components/dropdown/symbol.d.ts +2 -0
  24. package/lib/components/image/Image.vue.d.ts +1 -1
  25. package/lib/components/messageprovider/Message.vue.d.ts +1 -1
  26. package/lib/components/messageprovider/MessageProvider.vue.d.ts +22 -24
  27. package/lib/components/messageprovider/style/Message.css.d.ts +1 -1
  28. package/lib/components/messageprovider/types.d.ts +5 -0
  29. package/lib/components/modal/Modal.vue.d.ts +18 -6
  30. package/lib/components/radio/Radio.vue.d.ts +2 -0
  31. package/lib/components/radiobuttongroup/RadioButtonGroup.vue.d.ts +1 -0
  32. package/lib/components/select/Select.vue.d.ts +20 -11
  33. package/lib/components/switch/Switch.vue.d.ts +2 -0
  34. package/lib/components/tab/Tab.vue.d.ts +5 -2
  35. package/lib/components/tab/TabGroup.vue.d.ts +8 -3
  36. package/lib/components/textarea/Textarea.vue.d.ts +2 -1
  37. package/lib/components/tooltip/Tooltip.vue.d.ts +5 -20
  38. package/lib/components/tooltip/TooltipTrigger.vue.d.ts +1 -10
  39. package/lib/components/tree/Tree.vue.d.ts +3 -3
  40. package/lib/components/tree/TreeNode.vue.d.ts +26 -12
  41. package/lib/components/tree/types.d.ts +5 -5
  42. package/lib/index.cjs.js +5 -14
  43. package/lib/index.es.js +15429 -10907
  44. package/lib/style.css +1 -1
  45. package/package.json +12 -6
  46. package/src/components/avatar/Avatar.vue +32 -24
  47. package/src/components/button/Button.vue +24 -5
  48. package/src/components/cardcontextmenu/CardContextMenu.vue +68 -95
  49. package/src/components/cardcontextmenu/CardContextMenuItem.vue +40 -50
  50. package/src/components/cardcontextmenu/CardContextMenuSeperator.vue +9 -7
  51. package/src/components/cardcontextmenu/CardContextMenuTriggerProvider.vue +15 -0
  52. package/src/components/cardcontextmenu/style/Dropdown.css.ts +155 -2
  53. package/src/components/cardcontextmenu/symbol.ts +3 -0
  54. package/src/components/checkbox/Checkbox.vue +37 -12
  55. package/src/components/checkbox/style/Checkbox.css.ts +6 -6
  56. package/src/components/collapse/CollapseItem.vue +46 -21
  57. package/src/components/collapse/style/Collapse.css.ts +5 -1
  58. package/src/components/colorpicker/ColorPicker.vue +76 -45
  59. package/src/components/confirm/Confirm.vue +15 -8
  60. package/src/components/confirm/props.ts +4 -0
  61. package/src/components/dialog/Dialog.vue +169 -36
  62. package/src/components/dialogprovider/types.ts +1 -0
  63. package/src/components/dropdown/Dropdown.vue +46 -3
  64. package/src/components/dropdown/DropdownItem.vue +55 -25
  65. package/src/components/dropdown/DropdownSeperator.vue +19 -11
  66. package/src/components/dropdown/DropdownTriggerProvider.vue +15 -0
  67. package/src/components/dropdown/examples/context.vue +2 -2
  68. package/src/components/dropdown/style/Dropdown.css.ts +157 -4
  69. package/src/components/dropdown/symbol.ts +4 -0
  70. package/src/components/form/examples/basic.vue +19 -8
  71. package/src/components/messageprovider/MessageProvider.vue +136 -90
  72. package/src/components/messageprovider/examples/basic.vue +3 -1
  73. package/src/components/messageprovider/examples/index.stories.ts +37 -1
  74. package/src/components/messageprovider/types.ts +10 -0
  75. package/src/components/modal/Modal.vue +142 -67
  76. package/src/components/radio/Radio.vue +31 -17
  77. package/src/components/radiobutton/RadioButton.vue +15 -2
  78. package/src/components/radiobuttongroup/RadioButtonGroup.vue +11 -4
  79. package/src/components/select/Select.vue +301 -153
  80. package/src/components/select/examples/basic.vue +1 -1
  81. package/src/components/slider/Slider.vue +1 -1
  82. package/src/components/switch/Switch.vue +30 -10
  83. package/src/components/switch/style/Switch.css.ts +3 -5
  84. package/src/components/tab/Tab.vue +29 -20
  85. package/src/components/tab/TabGroup.vue +29 -38
  86. package/src/components/textarea/Textarea.vue +8 -4
  87. package/src/components/tooltip/Tooltip.vue +52 -141
  88. package/src/components/tooltip/TooltipTrigger.vue +14 -17
  89. package/src/components/tooltip/style/Tooltip.css.ts +148 -29
  90. package/src/components/tree/Tree.vue +138 -100
  91. package/src/components/tree/TreeNode.vue +105 -98
  92. package/src/components/tree/types.ts +4 -4
  93. package/src/styles/transitions.css.ts +36 -16
@@ -1,66 +1,98 @@
1
1
  <template>
2
- <Teleport :to="'body'">
3
- <TransitionGroup type="animation" :enter-active-class="fade.enterActive" :leave-active-class="fade.leaveActive"
4
- :enter-from-class="fade.enterFrom" :leave-to-class="fade.leaveTo">
5
- <div :class="style.mask" :style="{ zIndex: zIndex }" v-if="isOpen"></div>
6
- <div tabIndex="-1" v-if="isOpen" @keydown="onWrapperKeyDown" ref="wrapperRef" role="dialog"
7
- :class="computedWrapperClasses" :style="computedWrapperStyles" @click="onOutsideClick">
8
- <!-- <Transition-->
9
- <!-- type="animation"-->
10
- <!-- :enter-active-class="modalScale.enterActive"-->
11
- <!-- :leave-active-class="modalScale.leaveActive"-->
12
- <!-- :enter-from-class="modalScale.enterFrom"-->
13
- <!-- :leave-to-class="modalScale.leaveTo">-->
14
- <div :class="computedModalClasses" role="document" v-bind="$attrs" :style="contentStyleRef">
15
- <div :class="computedContainerClasses" @mousedown="onContentMouseDown" @mouseup="onContentMouseUp"
16
- ref="target">
17
- <template v-if="loading">
18
- <slot name="loading"> Loading...</slot>
19
- </template>
20
- <template v-else>
21
- <div :class="style.sidebar" v-if="hasSidebar">
22
- <slot name="sidebar"></slot>
23
- </div>
24
- <div :class="style.content">
25
- <div v-if="title || showClose" :class="style.header">
26
- <div :class="style.title" v-if="title">
27
- <div>{{ title }}</div>
2
+ <DialogRoot :open="isOpen" modal @update:open="handleOpenChange">
3
+ <DialogPortal to="body">
4
+ <Transition appear type="animation" :enter-active-class="fade.enterActive" :leave-active-class="fade.leaveActive"
5
+ :enter-from-class="fade.enterFrom" :leave-to-class="fade.leaveTo">
6
+ <DialogOverlay v-if="isOpen" force-mount :class="style.mask" :style="{ zIndex }" />
7
+ </Transition>
8
+ <Transition appear type="animation" :enter-active-class="modalScale.enterActive" :leave-active-class="modalScale.leaveActive"
9
+ :enter-from-class="modalScale.enterFrom" :leave-to-class="modalScale.leaveTo">
10
+ <div tabIndex="-1" v-if="isOpen" ref="wrapperRef"
11
+ :class="computedWrapperClasses" :style="computedWrapperStyles">
12
+ <DialogContent
13
+ force-mount
14
+ :class="computedModalClasses"
15
+ v-bind="$attrs"
16
+ :style="contentStyleRef"
17
+ :disable-outside-pointer-events="true"
18
+ @open-auto-focus="handleOpenAutoFocus"
19
+ @escape-key-down="onEscapeKeyDown"
20
+ @pointer-down-outside="onPointerDownOutside"
21
+ @interact-outside="onInteractOutside"
22
+ >
23
+ <FocusScope :trapped="focusTrap" :loop="focusTrap">
24
+ <div :class="computedContainerClasses" ref="target">
25
+ <template v-if="loading">
26
+ <slot name="loading"> Loading...</slot>
27
+ </template>
28
+ <template v-else>
29
+ <div :class="style.sidebar" v-if="hasSidebar">
30
+ <slot name="sidebar"></slot>
31
+ </div>
32
+ <div :class="style.content">
33
+ <div v-if="title || showClose" :class="style.header">
34
+ <DialogTitle as-child v-if="title">
35
+ <div :class="style.title">
36
+ <div>{{ title }}</div>
37
+ </div>
38
+ </DialogTitle>
39
+ </div>
40
+ <DialogClose as-child v-if="showClose">
41
+ <button :class="style.close"></button>
42
+ </DialogClose>
43
+ <div :class="style.body" ref="bodyRef">
44
+ <slot name="body"></slot>
45
+ <slot></slot>
46
+ </div>
47
+ <div :class="style.footer" v-if="hasFooter">
48
+ <slot name="footer"></slot>
49
+ </div>
28
50
  </div>
29
- </div>
30
- <button v-if="showClose" :class="style.close" @click="close"></button>
31
- <div :class="style.body">
32
- <slot name="body"></slot>
33
- <slot></slot>
34
- </div>
35
- <div :class="style.footer" v-if="hasFooter">
36
- <slot name="footer"></slot>
37
- </div>
51
+ </template>
38
52
  </div>
39
- </template>
40
- </div>
53
+ </FocusScope>
54
+ </DialogContent>
41
55
  </div>
42
- <!-- </Transition>-->
43
- </div>
44
- </TransitionGroup>
45
- </Teleport>
56
+ </Transition>
57
+ </DialogPortal>
58
+ </DialogRoot>
46
59
  </template>
47
60
 
48
61
  <script lang="ts">
49
62
  import type { CSSProperties, PropType } from 'vue';
63
+ import {
64
+ DialogClose,
65
+ DialogContent,
66
+ DialogOverlay,
67
+ DialogPortal,
68
+ DialogRoot,
69
+ DialogTitle,
70
+ FocusScope,
71
+ } from 'reka-ui';
50
72
  import {
51
73
  computed,
52
74
  defineComponent,
53
75
  nextTick,
76
+ provide,
54
77
  ref,
55
78
  shallowRef,
56
79
  watch
57
80
  } from 'vue';
58
81
  import * as style from './style';
59
82
  import { fade, modalScale } from '../../styles/transitions.css';
60
- import { useZIndex } from '../../composables/useZIndex';
83
+ import { useZIndex, ZINDEX } from '../../composables/useZIndex';
61
84
 
62
85
  export default defineComponent({
63
86
  name: 'MModal',
87
+ components: {
88
+ DialogClose,
89
+ DialogContent,
90
+ DialogOverlay,
91
+ DialogPortal,
92
+ DialogRoot,
93
+ DialogTitle,
94
+ FocusScope,
95
+ },
64
96
  props: {
65
97
  open: {
66
98
  type: Boolean,
@@ -106,15 +138,21 @@ export default defineComponent({
106
138
  centered: {
107
139
  type: Boolean,
108
140
  default: true
141
+ },
142
+ focusTrap: {
143
+ type: Boolean,
144
+ default: true
109
145
  }
110
146
  },
111
- emits: ['open', 'update:open'],
147
+ emits: ['open', 'close', 'update:open'],
112
148
  setup(props, { emit, slots }) {
113
149
  const { nextZIndex } = useZIndex();
114
150
 
115
151
  const target = ref();
152
+ const bodyRef = ref<HTMLElement | null>(null);
116
153
  const wrapperRef = shallowRef<HTMLDivElement>();
117
154
  const zIndex = ref(props.zIndex ?? nextZIndex());
155
+ provide(ZINDEX, zIndex);
118
156
  const hasSidebar = computed(() => !!slots.sidebar);
119
157
  const hasFooter = computed(() => !!slots.footer);
120
158
  const transformOrigin = ref<string>();
@@ -194,43 +232,78 @@ export default defineComponent({
194
232
  };
195
233
  });
196
234
 
197
- const contentClickRef = shallowRef(false);
198
- const contentTimeoutRef = shallowRef<any>();
235
+ const canCloseOutside = computed(() => props.canClickOutside || props.outsideClose);
236
+
237
+ const focusableBodySelector = [
238
+ '[autofocus]',
239
+ 'input:not([type="hidden"])',
240
+ 'textarea',
241
+ 'select',
242
+ '[contenteditable="true"]',
243
+ 'button',
244
+ 'a[href]',
245
+ '[tabindex]:not([tabindex="-1"])'
246
+ ].join(', ');
247
+
248
+ function getFirstFocusableBodyElement() {
249
+ if (!bodyRef.value) {
250
+ return null;
251
+ }
252
+
253
+ return Array.from(
254
+ bodyRef.value.querySelectorAll<HTMLElement>(focusableBodySelector)
255
+ ).find(element => {
256
+ return !element.matches(':disabled')
257
+ && element.getAttribute('aria-disabled') !== 'true'
258
+ && element.getAttribute('aria-hidden') !== 'true'
259
+ && element.getClientRects().length > 0;
260
+ }) ?? null;
261
+ }
262
+
263
+ const handleOpenAutoFocus = (event: Event) => {
264
+ const firstFocusableBodyElement = getFirstFocusableBodyElement();
265
+
266
+ if (!firstFocusableBodyElement) {
267
+ return;
268
+ }
199
269
 
200
- const onContentMouseDown = () => {
201
- clearTimeout(contentTimeoutRef.value);
202
- contentClickRef.value = true;
270
+ event.preventDefault();
271
+ firstFocusableBodyElement.focus();
203
272
  };
204
273
 
205
- const onContentMouseUp = () => {
206
- contentTimeoutRef.value = setTimeout(() => {
207
- contentClickRef.value = false;
208
- }, 0);
274
+ const onEscapeKeyDown = (e: KeyboardEvent) => {
275
+ e.stopPropagation();
276
+ close(e);
209
277
  };
210
278
 
211
- const onOutsideClick = (e: MouseEvent) => {
212
- if (!(props.canClickOutside || props.outsideClose)) {
213
- return null;
279
+ const onPointerDownOutside = (e: Event) => {
280
+ if (!canCloseOutside.value) {
281
+ e.preventDefault();
214
282
  }
283
+ };
215
284
 
216
- if (contentClickRef.value) {
217
- contentClickRef.value = false;
218
- } else if (wrapperRef.value === e.target) {
219
- close(e);
285
+ const onInteractOutside = (e: Event) => {
286
+ if (!canCloseOutside.value) {
287
+ e.preventDefault();
288
+ return;
220
289
  }
290
+
291
+ close(e as MouseEvent | KeyboardEvent);
221
292
  };
222
293
 
223
- const onWrapperKeyDown = (e: KeyboardEvent) => {
224
- if (e.key === 'Escape') {
225
- e.stopPropagation();
226
- close(e);
294
+ const handleOpenChange = (value: boolean) => {
295
+ if (!value && isOpen.value) {
296
+ close(undefined);
227
297
  return;
228
298
  }
299
+
300
+ isOpen.value = value;
229
301
  };
230
302
 
231
303
  const close = (e: MouseEvent | KeyboardEvent | undefined) => {
232
304
  props.onClose?.(e);
233
305
  ownerScrollbarClose();
306
+ emit('close', e);
234
307
  isOpen.value = false;
235
308
  };
236
309
 
@@ -283,12 +356,14 @@ export default defineComponent({
283
356
 
284
357
  return {
285
358
  close,
286
- onOutsideClick,
287
359
  open,
288
- onContentMouseDown,
289
- onContentMouseUp,
290
- onWrapperKeyDown,
360
+ onEscapeKeyDown,
361
+ onPointerDownOutside,
362
+ onInteractOutside,
363
+ handleOpenChange,
364
+ handleOpenAutoFocus,
291
365
  target,
366
+ bodyRef,
292
367
  style,
293
368
  isOpen,
294
369
  computedWrapperStyles,
@@ -1,20 +1,19 @@
1
1
  <template>
2
2
  <label :class="style.base">
3
- <input
4
- v-model="pick"
5
- :value="value"
6
- type="radio"
7
- :aria-checked="checked ? 'true' : 'false'"
8
- :aria-disabled="(disabled || loading) ? 'true' : 'false'"
9
- :aria-labelledby="`${id}-label`"
10
- :disabled="disabled || loading"
11
- :name="name"
12
- :id="id"
13
- v-bind="$attrs"
14
- v-on="inputListeners"
15
- :class="style.input"
16
- />
17
- <span :class="classes"></span>
3
+ <RadioGroupRoot v-model="pick" :name="name" :disabled="disabled || loading">
4
+ <RadioGroupItem
5
+ :value="value"
6
+ :id="id"
7
+ :disabled="disabled || loading"
8
+ :aria-checked="checked ? 'true' : 'false'"
9
+ :aria-disabled="(disabled || loading) ? 'true' : 'false'"
10
+ :aria-labelledby="`${id}-label`"
11
+ v-bind="$attrs"
12
+ :class="classes"
13
+ @blur="onBlur"
14
+ @focus="onFocus"
15
+ />
16
+ </RadioGroupRoot>
18
17
  <span :class="style.label" :id="`${id}-label`">
19
18
  <template v-if="hasSlot">
20
19
  <slot/>
@@ -29,6 +28,7 @@
29
28
 
30
29
  <script lang="ts">
31
30
  import type {PropType} from 'vue';
31
+ import { RadioGroupItem, RadioGroupRoot } from 'reka-ui';
32
32
  import {computed, defineComponent, ref, toRef} from 'vue';
33
33
  import {useInput} from '../../composables/useInput';
34
34
  import {useInteractive} from "../../composables/useInteractive";
@@ -37,6 +37,10 @@ import * as style from './style';
37
37
 
38
38
  export default defineComponent({
39
39
  name: "Radio",
40
+ components: {
41
+ RadioGroupItem,
42
+ RadioGroupRoot
43
+ },
40
44
  emits: useInput.emits(),
41
45
  props: {
42
46
  ...useInput.props(),
@@ -76,7 +80,7 @@ export default defineComponent({
76
80
  formDisabled,
77
81
  formLoading,
78
82
  inputListeners
79
- } = useInput(props, {focus, emit});
83
+ } = useInput(props, {focus, emit, withListeners: false});
80
84
 
81
85
  const disabled = computed(() => formDisabled || formLoading || props.disabled || props.loading);
82
86
  const name = toRef(props, 'name');
@@ -106,6 +110,14 @@ export default defineComponent({
106
110
  return formError.value || props.error;
107
111
  });
108
112
 
113
+ function onFocus(event: FocusEvent) {
114
+ emit('focus', event);
115
+ }
116
+
117
+ function onBlur(event: FocusEvent) {
118
+ emit('blur', event);
119
+ }
120
+
109
121
  expose({
110
122
  focus,
111
123
  blur,
@@ -129,7 +141,9 @@ export default defineComponent({
129
141
  hasSlot,
130
142
  inputListeners,
131
143
  focus,
132
- blur
144
+ blur,
145
+ onFocus,
146
+ onBlur
133
147
  }
134
148
  }
135
149
  })
@@ -1,14 +1,24 @@
1
1
  <template>
2
- <label :class="computedClasses" :disabled="disabled" @click="handleClick" v-bind="$attrs" :aria-selected="selected" :aria-disabled="disabled">
2
+ <RadioGroupItem
3
+ :class="computedClasses"
4
+ :disabled="disabled"
5
+ :value="id"
6
+ :name="name"
7
+ v-bind="$attrs"
8
+ :aria-selected="selected"
9
+ :aria-disabled="disabled"
10
+ @click="handleClick"
11
+ >
3
12
  <input type="radio" :class="computedRadioClasses" :name="name" :value="id" :disabled="disabled">
4
13
  <span>
5
14
  <slot />
6
15
  </span>
7
- </label>
16
+ </RadioGroupItem>
8
17
  </template>
9
18
 
10
19
  <script lang="ts">
11
20
  import type {PropType} from "vue";
21
+ import { RadioGroupItem } from 'reka-ui';
12
22
  import {computed, defineComponent, inject, ref } from "vue";
13
23
  import type {Size} from "../../types/props";
14
24
  import * as style from "./style";
@@ -18,6 +28,9 @@ import {RADIO_BUTTON_GROUP_STATE} from "../radiobuttongroup/symbol";
18
28
 
19
29
  export default defineComponent({
20
30
  name: "MRadioButton",
31
+ components: {
32
+ RadioGroupItem
33
+ },
21
34
  props: {
22
35
  ...useInput.props(),
23
36
  ...useInteractive.props(),
@@ -1,12 +1,15 @@
1
1
  <template>
2
- <div
2
+ <RadioGroupRoot
3
+ v-model="selectedValue"
4
+ :name="name"
3
5
  :class="computedClasses"
4
6
  >
5
7
  <slot/>
6
- </div>
8
+ </RadioGroupRoot>
7
9
  </template>
8
10
 
9
11
  <script lang="ts">
12
+ import { RadioGroupRoot } from 'reka-ui';
10
13
  import {computed, defineComponent, type PropType, provide, reactive, toRef} from "vue";
11
14
  import type {Size} from '../../types/props';
12
15
  import * as style from "./style";
@@ -15,6 +18,9 @@ import {RADIO_BUTTON_GROUP_STATE} from "./symbol";
15
18
 
16
19
  export default defineComponent({
17
20
  name: "MRadioButtonGroup",
21
+ components: {
22
+ RadioGroupRoot
23
+ },
18
24
  props: {
19
25
  modelValue: {
20
26
  type: [String, Number],
@@ -68,8 +74,9 @@ export default defineComponent({
68
74
  })
69
75
 
70
76
  return {
71
- computedClasses
77
+ computedClasses,
78
+ selectedValue
72
79
  }
73
80
  }
74
81
  });
75
- </script>
82
+ </script>