@teammodlr/ui-kit 2.2.1 → 2.3.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.
@@ -1,329 +1,203 @@
1
- <template>
2
- <Primitive
3
- as-child
4
- ref="wrapper">
5
-
6
- <DropdownTrigger
7
- ref="referenceRef"
8
- :class="computedReferenceClasses"
9
- @click="toggleDropdown">
10
- <slot />
11
- </DropdownTrigger>
12
-
13
- <DropdownWrapper>
14
- <Teleport :disabled="isNested" to="body">
15
- <transition
16
- :enter-active-class="scale.enterActive"
17
- :leave-active-class="scale.leaveActive"
18
- :enter-from-class="scale.enterFrom"
19
- :leave-to-class="scale.leaveTo">
20
- <div
21
- v-if="isOpen"
22
- ref="popper"
23
- :class="menuClasses"
24
- :style="{ zIndex: zIndex, maxHeight: maxHeight }">
25
- <slot name="menu" />
26
- </div>
27
- </transition>
28
- </Teleport>
29
- </DropdownWrapper>
30
- </Primitive>
31
- </template>
32
-
33
- <script lang="ts">
34
- import { usePopper } from '../../composables/usePopper';
35
- import type { Placement, VirtualElement } from '@popperjs/core';
36
- import { scale } from '../../styles/transitions.css';
37
- import {Primitive} from "../primative/primitive";
38
- import {
39
- defineComponent,
40
- inject,
41
- ref,
42
- type PropType,
43
- provide,
44
- watch,
45
- onMounted,
46
- nextTick,
47
- computed,
48
- toRef,
49
- reactive,
50
- watchEffect, type Ref
51
- } from 'vue';
52
- import { onClickOutside, useEventListener } from '@vueuse/core';
53
- import DropdownWrapper from './DropdownWrapper.vue';
54
- import { useLabel } from './hooks';
55
- import { useZIndex } from '../../composables/useZIndex';
56
- import type { DropdownState } from './symbol';
57
- import { DROPDOWN_STATE } from './symbol';
58
- import * as style from './style';
59
- import {createContext} from "../../utils/injection";
60
- import DropdownTrigger from "./DropdownTrigger.vue";
61
-
62
- interface DropdownContext {
63
- reference: Ref<HTMLElement | undefined>
64
- onReferenceChange: (element: HTMLElement | undefined) => void
65
- }
66
-
67
- export const [injectDropdownContext, provideDropdownContext] = createContext<DropdownContext>('Dropdown');
68
-
69
-
70
- export default defineComponent({
71
- name: 'Dropdown',
72
- components: {
73
- DropdownTrigger,
74
- DropdownWrapper,
75
- Primitive
76
- },
77
- props: {
78
- open: {
79
- type: Boolean,
80
- default: false
81
- },
82
- placement: {
83
- type: String as PropType<Placement>,
84
- default: 'bottom-start'
85
- },
86
- transfer: {
87
- type: Boolean,
88
- default: false
89
- },
90
- trigger: {
91
- type: String as PropType<'click' | 'hover'>,
92
- default: 'click'
93
- },
94
- virtual: {
95
- type: [Object],
96
- default: null
97
- },
98
- x: {
99
- type: Number,
100
- default: 0
101
- },
102
- y: {
103
- type: Number,
104
- default: 0
105
- },
106
- label: {
107
- default: null,
108
- static: true
109
- },
110
- transitionName: {
111
- type: String,
112
- default: 'fade'
113
- },
114
- onSelect: {
115
- type: Function as PropType<(labels: any) => void>,
116
- default: () => {}
117
- },
118
- zIndex: {
119
- type: Number
120
- }
121
- },
122
- emits: ['update:open'],
123
- setup(props, { emit }) {
124
- const parentState = inject(DROPDOWN_STATE, null);
125
- const { nextZIndex } = useZIndex();
126
- const isNested = !!parentState;
127
- const label = toRef(props, 'label');
128
- const isOpen = ref(props.open);
129
- const placement = ref(props.placement);
130
- const transfer = toRef(props, 'transfer');
131
- const wrapper = ref(null);
132
- const referenceRef = ref<HTMLElement>();
133
- const zIndex = ref(props.zIndex ?? nextZIndex());
134
- const reference = computed(() => {
135
- if (props.virtual !== null) {
136
- const virtual = (props.virtual as any).$el ?? props.virtual;
137
- if (virtual) {
138
- if ('getBoundingClientRect' in virtual) {
139
- return virtual as VirtualElement;
140
- }
141
-
142
- if ('x' in virtual && 'y' in virtual) {
143
- return {
144
- getBoundingClientRect: () => ({
145
- x: virtual.x,
146
- y: virtual.y,
147
- left: virtual.x,
148
- top: virtual.y,
149
- width: 0,
150
- height: 0
151
- })
152
- } as VirtualElement;
153
- }
154
- }
155
- }
156
-
157
- return referenceRef.value;
158
- });
159
-
160
- provideDropdownContext({
161
- reference: referenceRef,
162
- onReferenceChange: element => referenceRef.value = element
163
- });
164
-
165
- const { popper, transferTo, updatePopper } = usePopper({
166
- reference: reference,
167
- placement,
168
- transfer,
169
- wrapper,
170
- isDrop: true,
171
- offset: isNested ? [-2, 2] : [0, 14]
172
- });
173
-
174
- const currentLabel = useLabel(label, referenceRef);
175
-
176
- provide('dropdown-select', null);
177
-
178
- const startState: DropdownState = reactive({
179
- handleSelect: handleSelect,
180
- isOpen: isOpen
181
- });
182
-
183
- provide(DROPDOWN_STATE, startState);
184
-
185
- watch(
186
- () => props.open,
187
- value => {
188
- isOpen.value = value;
189
- }
190
- );
191
-
192
- watch(
193
- () => props.placement,
194
- value => {
195
- setPlacement(value);
196
- }
197
- );
198
-
199
- watch(isOpen, value => {
200
- if (value) {
201
- updatePopper();
202
- }
203
-
204
- emit('update:open', value);
205
- });
206
-
207
- onMounted(() => {
208
- nextTick(() => {
209
- setPlacement(props.placement);
210
- });
211
- });
212
-
213
- useEventListener('resize', () => {
214
- updatePopper();
215
- });
216
-
217
- onClickOutside(wrapper, e => {
218
- let parent = e.target as HTMLElement;
219
-
220
- let i = 0;
221
- while (parent) {
222
- if (parent.classList.contains('m-dropdown-menu')) {
223
- return;
224
- }
225
- parent = parent.parentElement as HTMLElement;
226
-
227
- if (i > 10) {
228
- break;
229
- }
230
- i++;
231
- }
232
-
233
- isOpen.value = false;
234
- });
235
-
236
- function setPlacement(value: Placement) {
237
- const [xPlacement] = value.split('-');
238
-
239
- if (isNested && xPlacement !== 'right' && xPlacement !== 'left') {
240
- placement.value = 'right-start';
241
- } else {
242
- placement.value = value;
243
- }
244
- }
245
-
246
- function toggleDropdown() {
247
- isOpen.value = !isOpen.value;
248
- }
249
-
250
- function handleSelect(labels: string[]) {
251
- isOpen.value = false;
252
- props.onSelect(labels);
253
- if (typeof parentState?.handleSelect === 'function') {
254
- // @ts-ignore
255
- parentState.handleSelect([currentLabel.value!, ...labels]);
256
- }
257
- }
258
-
259
- const computedWrapperClasses = computed(() => {
260
- return [
261
- 'm-dropdown',
262
- {
263
- 'm-dropdown--open': isOpen.value,
264
- 'm-dropdown--nested': isNested
265
- }
266
- ];
267
- });
268
-
269
- const computedReferenceClasses = computed(() => {});
270
-
271
- const menuClasses = computed(() => {
272
- return ['m-dropdown-menu', style.menu];
273
- });
274
-
275
- const transitionName = computed(() => {
276
- return `m-transition__${props.transitionName}`;
277
- });
278
-
279
- const maxHeight = ref('auto');
280
- useEventListener(window, 'resize', () => {
281
- if (isOpen.value) {
282
- resize();
283
- updatePopper();
284
- }
285
- });
286
-
287
- watchEffect(() => {
288
- resize();
289
- });
290
-
291
- function resize() {
292
- if (!isOpen.value || !reference.value) {
293
- maxHeight.value = 'auto';
294
- return;
295
- }
296
- let referenceHeight =
297
- reference.value?.getBoundingClientRect().height;
298
-
299
- let referenceTop = reference.value?.getBoundingClientRect().top;
300
- if (!referenceHeight || !referenceTop) {
301
- return;
302
- }
303
- let windowHeight = window.innerHeight;
304
-
305
- maxHeight.value = `${
306
- windowHeight - referenceHeight - referenceTop - 30
307
- }px`;
308
- }
309
-
310
- return {
311
- wrapper,
312
- referenceRef,
313
- popper,
314
- transferTo,
315
- isOpen,
316
- isNested,
317
- placement,
318
- menuClasses,
319
- computedWrapperClasses,
320
- computedReferenceClasses,
321
- transitionName,
322
- toggleDropdown,
323
- zIndex,
324
- scale,
325
- maxHeight
326
- };
327
- }
328
- });
329
- </script>
1
+ <template>
2
+ <ContextMenuRoot v-if="contextMenu">
3
+ <ContextMenuTrigger as-child>
4
+ <slot />
5
+ </ContextMenuTrigger>
6
+ <ContextMenuPortal>
7
+ <ContextMenuContent :align="placement" :class="menuClasses" :side-offset="5">
8
+ <slot name="menu" />
9
+ </ContextMenuContent>
10
+ </ContextMenuPortal>
11
+ </ContextMenuRoot>
12
+ <DropdownMenuRoot v-model:open="isOpen" v-else>
13
+ <DropdownMenuTrigger as-child>
14
+ <slot />
15
+ </DropdownMenuTrigger>
16
+ <DropdownMenuPortal>
17
+ <DropdownMenuContent :align="placement" :class="menuClasses" :side-offset="5">
18
+ <slot name="menu" />
19
+ </DropdownMenuContent>
20
+ </DropdownMenuPortal>
21
+ </DropdownMenuRoot>
22
+ </template>
23
+
24
+ <script lang="ts">
25
+ import {
26
+ DropdownMenuArrow,
27
+ DropdownMenuCheckboxItem,
28
+ DropdownMenuContent,
29
+ DropdownMenuItem,
30
+ DropdownMenuItemIndicator,
31
+ DropdownMenuLabel,
32
+ DropdownMenuPortal,
33
+ DropdownMenuRadioGroup,
34
+ DropdownMenuRadioItem,
35
+ DropdownMenuRoot,
36
+ DropdownMenuSeparator,
37
+ DropdownMenuSub,
38
+ DropdownMenuSubContent,
39
+ DropdownMenuSubTrigger,
40
+ DropdownMenuTrigger,
41
+
42
+ ContextMenuCheckboxItem,
43
+ ContextMenuContent,
44
+ ContextMenuItem,
45
+ ContextMenuItemIndicator,
46
+ ContextMenuLabel,
47
+ ContextMenuPortal,
48
+ ContextMenuRadioGroup,
49
+ ContextMenuRadioItem,
50
+ ContextMenuRoot,
51
+ ContextMenuSeparator,
52
+ ContextMenuSub,
53
+ ContextMenuSubContent,
54
+ ContextMenuSubTrigger,
55
+ ContextMenuTrigger,
56
+ } from 'radix-vue';
57
+ import {
58
+ computed,
59
+ defineComponent,
60
+ ref,
61
+ watch,
62
+ type PropType
63
+ } from 'vue';
64
+ import { useZIndex } from '../../composables/useZIndex';
65
+ import { scale } from '../../styles/transitions.css';
66
+ import * as style from './style';
67
+ import { DROPDOWN_STATE } from './symbol';
68
+
69
+ export default defineComponent({
70
+ name: 'Dropdown',
71
+ components: {
72
+ DropdownMenuArrow,
73
+ DropdownMenuCheckboxItem,
74
+ DropdownMenuContent,
75
+ DropdownMenuItem,
76
+ DropdownMenuItemIndicator,
77
+ DropdownMenuLabel,
78
+ DropdownMenuPortal,
79
+ DropdownMenuRadioGroup,
80
+ DropdownMenuRadioItem,
81
+ DropdownMenuRoot,
82
+ DropdownMenuSeparator,
83
+ DropdownMenuSub,
84
+ DropdownMenuSubContent,
85
+ DropdownMenuSubTrigger,
86
+ DropdownMenuTrigger,
87
+
88
+ ContextMenuCheckboxItem,
89
+ ContextMenuContent,
90
+ ContextMenuItem,
91
+ ContextMenuItemIndicator,
92
+ ContextMenuLabel,
93
+ ContextMenuPortal,
94
+ ContextMenuRadioGroup,
95
+ ContextMenuRadioItem,
96
+ ContextMenuRoot,
97
+ ContextMenuSeparator,
98
+ ContextMenuSub,
99
+ ContextMenuSubContent,
100
+ ContextMenuSubTrigger,
101
+ ContextMenuTrigger,
102
+ },
103
+ props: {
104
+ open: {
105
+ type: Boolean,
106
+ default: false
107
+ },
108
+ placement: {
109
+ type: String as PropType<"start" | "center" | "end">,
110
+ default: 'start'
111
+ },
112
+ transfer: {
113
+ type: Boolean,
114
+ default: false
115
+ },
116
+ trigger: {
117
+ type: String as PropType<'click' | 'hover'>,
118
+ default: 'click'
119
+ },
120
+ contextMenu: {
121
+ type: Boolean,
122
+ default: false
123
+ },
124
+ x: {
125
+ type: Number,
126
+ default: 0
127
+ },
128
+ y: {
129
+ type: Number,
130
+ default: 0
131
+ },
132
+ label: {
133
+ default: null,
134
+ static: true
135
+ },
136
+ transitionName: {
137
+ type: String,
138
+ default: 'fade'
139
+ },
140
+ onSelect: {
141
+ type: Function as PropType<(labels: any) => void>,
142
+ default: () => {}
143
+ },
144
+ zIndex: {
145
+ type: Number
146
+ }
147
+ },
148
+ emits: ['update:open'],
149
+ setup(props, { emit }) {
150
+ const { nextZIndex } = useZIndex();
151
+ const isOpen = ref(props.open);
152
+ const placement = ref(props.placement);
153
+ const wrapper = ref(null);
154
+ const referenceRef = ref<HTMLElement>();
155
+ const zIndex = ref(props.zIndex ?? nextZIndex());
156
+
157
+ watch(
158
+ () => props.open,
159
+ value => {
160
+ isOpen.value = value;
161
+ }
162
+ );
163
+
164
+ function toggleDropdown() {
165
+ isOpen.value = !isOpen.value;
166
+ }
167
+
168
+
169
+ const computedWrapperClasses = computed(() => {
170
+ return [
171
+ 'm-dropdown',
172
+ {
173
+ 'm-dropdown--open': isOpen.value
174
+ }
175
+ ];
176
+ });
177
+
178
+ const computedReferenceClasses = computed(() => {});
179
+
180
+ const menuClasses = computed(() => {
181
+ return ['m-dropdown-menu', style.menu];
182
+ });
183
+
184
+ const transitionName = computed(() => {
185
+ return `m-transition__${props.transitionName}`;
186
+ });
187
+
188
+ return {
189
+ wrapper,
190
+ referenceRef,
191
+ isOpen,
192
+ placement,
193
+ menuClasses,
194
+ computedWrapperClasses,
195
+ computedReferenceClasses,
196
+ transitionName,
197
+ toggleDropdown,
198
+ zIndex,
199
+ scale
200
+ };
201
+ }
202
+ });
203
+ </script>
@@ -1,23 +1,23 @@
1
- <template>
2
- <li :class="computedClasses">
3
- <slot />
4
- </li>
5
- </template>
6
-
7
- <script lang="ts">
8
- import { computed, defineComponent } from 'vue';
9
- import * as style from './style';
10
-
11
- export default defineComponent({
12
- name: 'DropdownHeading',
13
- setup() {
14
- const computedClasses = computed(() => {
15
- return [style.heading];
16
- });
17
-
18
- return {
19
- computedClasses
20
- };
21
- }
22
- });
23
- </script>
1
+ <template>
2
+ <div :class="computedClasses">
3
+ <slot />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { computed, defineComponent } from 'vue';
9
+ import * as style from './style';
10
+
11
+ export default defineComponent({
12
+ name: 'DropdownHeading',
13
+ setup() {
14
+ const computedClasses = computed(() => {
15
+ return [style.heading];
16
+ });
17
+
18
+ return {
19
+ computedClasses
20
+ };
21
+ }
22
+ });
23
+ </script>