@teammodlr/ui-kit 2.3.1 → 2.3.3

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 (34) hide show
  1. package/lib/components/cardcontextmenu/CardContextMenu.vue.d.ts +129 -0
  2. package/lib/components/cardcontextmenu/CardContextMenuItem.vue.d.ts +88 -0
  3. package/lib/components/cardcontextmenu/CardContextMenuList.vue.d.ts +5 -0
  4. package/lib/components/cardcontextmenu/CardContextMenuSeperator.vue.d.ts +4 -0
  5. package/lib/components/cardcontextmenu/CardContextMenuWrapper.vue.d.ts +2 -0
  6. package/lib/components/cardcontextmenu/hooks.d.ts +2 -0
  7. package/lib/components/cardcontextmenu/style/Dropdown.css.d.ts +9 -0
  8. package/lib/components/cardcontextmenu/style/index.d.ts +1 -0
  9. package/lib/components/cardcontextmenu/symbol.d.ts +6 -0
  10. package/lib/components/dialog/Dialog.vue.d.ts +1 -1
  11. package/lib/components/index.d.ts +4 -0
  12. package/lib/index.cjs.js +8 -8
  13. package/lib/index.es.js +4175 -3806
  14. package/lib/style.css +1 -1
  15. package/package.json +1 -1
  16. package/src/components/cardcontextmenu/CardContextMenu.vue +276 -0
  17. package/src/components/cardcontextmenu/CardContextMenuItem.vue +151 -0
  18. package/src/components/cardcontextmenu/CardContextMenuList.vue +20 -0
  19. package/src/components/cardcontextmenu/CardContextMenuSeperator.vue +23 -0
  20. package/src/components/cardcontextmenu/CardContextMenuWrapper.vue +18 -0
  21. package/src/components/cardcontextmenu/examples/basic.vue +71 -0
  22. package/src/components/cardcontextmenu/examples/index.stories.ts +22 -0
  23. package/src/components/cardcontextmenu/examples/index.ts +1 -0
  24. package/src/components/cardcontextmenu/hooks.ts +30 -0
  25. package/src/components/cardcontextmenu/style/Dropdown.css.ts +158 -0
  26. package/src/components/cardcontextmenu/style/index.ts +1 -0
  27. package/src/components/cardcontextmenu/symbol.ts +9 -0
  28. package/src/components/dialog/Dialog.vue +33 -47
  29. package/src/components/dialogprovider/DialogProvider.vue +14 -20
  30. package/src/components/dialogprovider/examples/basic.vue +55 -54
  31. package/src/components/dropdown/Dropdown.vue +2 -2
  32. package/src/components/dropdown/examples/context.vue +3 -1
  33. package/src/components/index.ts +5 -0
  34. package/src/styles/transitions.css.ts +98 -97
@@ -0,0 +1,151 @@
1
+ <template>
2
+ <component
3
+ :is="computedType"
4
+ :href="href"
5
+ ref="wrapper"
6
+ :class="computedWrapperClasses"
7
+ role="menuitem"
8
+ tabindex="0"
9
+ @click="handleSelect"
10
+ v-bind="$attrs">
11
+ <div v-if="hasIconLeft" :class="style.menuItemIcon">
12
+ <slot name="icon-left" />
13
+ </div>
14
+ <div :class="style.menuItemTextContainer">
15
+ <span :class="style.menuItemText"><slot /></span>
16
+ </div>
17
+ <!-- <div v-if="hotkey" class="m-dropdown__hotkeys">
18
+ <template v-for="key in hotkey.split('+')">
19
+ <kbd>{{ key }}</kbd>
20
+ </template>
21
+ </div> -->
22
+ <div v-if="hasIconRight" :class="style.menuItemIcon">
23
+ <slot name="icon-right" />
24
+ </div>
25
+ </component>
26
+ </template>
27
+
28
+ <script lang="ts">
29
+ import {
30
+ computed,
31
+ defineComponent,
32
+ inject,
33
+ type PropType,
34
+ ref,
35
+ toRef
36
+ } from 'vue';
37
+ import { useLabel } from './hooks';
38
+ import * as style from './style';
39
+ import type { Variant } from '../../types/props';
40
+
41
+ export default defineComponent({
42
+ name: 'CardContextMenuItem',
43
+ props: {
44
+ label: {
45
+ type: [String, Number],
46
+ default: null
47
+ },
48
+ disabled: {
49
+ type: Boolean,
50
+ default: false
51
+ },
52
+ reference: {
53
+ type: Boolean,
54
+ default: false
55
+ },
56
+ onSelect: {
57
+ type: Function as PropType<(label: string | number) => void>,
58
+ default: () => {}
59
+ },
60
+ hotkey: {
61
+ type: String,
62
+ default: null
63
+ },
64
+ description: {
65
+ type: String,
66
+ default: null
67
+ },
68
+ href: {
69
+ type: String,
70
+ default: null
71
+ },
72
+ variant: {
73
+ type: String as PropType<Variant>,
74
+ default: 'default'
75
+ }
76
+ },
77
+ emits: [],
78
+ setup(props, { slots }) {
79
+ const parentSelect = inject('dropdown-select', null);
80
+ // const state = inject(DROPDOWN_STATE, null);
81
+ // const keys = useMagicKeys({
82
+ // passive: false,
83
+ // onEventFired: (event) => {
84
+
85
+ // // only fire when the dropdown is open
86
+ // if (state?.isOpen.value) {
87
+ // event.preventDefault();
88
+ // }
89
+ // }
90
+ // });
91
+
92
+ const hasIconLeft = computed(() => !!slots['icon-left']);
93
+ const hasIconRight = computed(() => !!slots['icon-right']);
94
+
95
+ const wrapper = ref(null);
96
+ const label = toRef(props, 'label');
97
+ const isReference = ref(props.reference);
98
+ const currentLabel = useLabel(label, wrapper);
99
+ function handleSelect() {
100
+ if (props.disabled || isReference.value) {
101
+ return;
102
+ }
103
+
104
+ if (typeof parentSelect === 'function') {
105
+ // @ts-ignore
106
+ parentSelect([currentLabel.value!]);
107
+ }
108
+
109
+ props.onSelect(currentLabel.value!);
110
+ }
111
+
112
+ // const isOpen = computed(() => {
113
+ // return state?.isOpen.value;
114
+ // });
115
+
116
+ const computedWrapperClasses = computed(() => {
117
+ return [style.menuItem, style.variant[props.variant]];
118
+ });
119
+
120
+ const computedType = computed(() => {
121
+ if (props.href) {
122
+ return 'a';
123
+ }
124
+
125
+ return 'li';
126
+ });
127
+
128
+ // onMounted(() => {
129
+ // if (props.hotkey) {
130
+ // const combination = keys[props.hotkey];
131
+
132
+ // whenever(combination, (v) => {
133
+ // if (v && isOpen.value) {
134
+ // handleSelect();
135
+ // }
136
+ // })
137
+ // }
138
+ // })
139
+
140
+ return {
141
+ wrapper,
142
+ hasIconLeft,
143
+ hasIconRight,
144
+ handleSelect,
145
+ computedWrapperClasses,
146
+ style,
147
+ computedType
148
+ };
149
+ }
150
+ });
151
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <ul :class="style.menuItems">
3
+ <slot />
4
+ </ul>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { defineComponent } from 'vue';
9
+ import * as style from "./style";
10
+
11
+ export default defineComponent({
12
+ name: "CardContextMenuList",
13
+ setup() {
14
+
15
+ return {
16
+ style
17
+ }
18
+ }
19
+ })
20
+ </script>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <li :class="computedClasses"></li>
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import {computed, defineComponent} from "vue";
7
+ import * as style from "./style";
8
+
9
+ export default defineComponent({
10
+ name: "CardContextMenuSeperator",
11
+ setup() {
12
+ const computedClasses = computed(() => {
13
+ return [
14
+ style.menuSeperator
15
+ ]
16
+ });
17
+
18
+ return {
19
+ computedClasses
20
+ }
21
+ }
22
+ })
23
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { defineComponent, inject, provide } from 'vue';
7
+ import {CARDCONTEXTMENU_STATE} from "./symbol";
8
+
9
+ export default defineComponent({
10
+ name: 'CardContextMenuWrapper',
11
+ setup() {
12
+ const state = inject(CARDCONTEXTMENU_STATE, null);
13
+
14
+ // @ts-ignore
15
+ provide('dropdown-select', state?.handleSelect);
16
+ }
17
+ })
18
+ </script>
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <div>
3
+ <div style="background: #eee; width: 500px; height: 500px;" @contextmenu="handleContextMenu">
4
+
5
+ </div>
6
+
7
+ <MCardContextMenu :virtual="position" :open="showing">
8
+ <template #menu>
9
+ <MCardContextMenuList>
10
+ <MCardContextMenuItem>
11
+ Item One
12
+ </MCardContextMenuItem>
13
+ <MCardContextMenuItem>
14
+ Item Two
15
+ </MCardContextMenuItem>
16
+
17
+ <MCardContextMenu>
18
+ <MCardContextMenuItem>
19
+ <template #icon-right>
20
+ <svg style="width: 16px; height: 16px;" xmlns="http://www.w3.org/2000/svg"
21
+ viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
22
+ <path fill-rule="evenodd"
23
+ d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
24
+ clip-rule="evenodd" />
25
+ </svg>
26
+
27
+ </template>
28
+ Item Three (Parent)
29
+ </MCardContextMenuItem>
30
+
31
+ <template #menu>
32
+ <MCardContextMenuList>
33
+ <MCardContextMenuItem @click="handleClick">
34
+ Child One
35
+ </MCardContextMenuItem>
36
+ <MCardContextMenuItem>
37
+ Child Two
38
+ </MCardContextMenuItem>
39
+ </MCardContextMenuList>
40
+ </template>
41
+ </MCardContextMenu>
42
+ </MCardContextMenuList>
43
+ </template>
44
+ </MCardContextMenu>
45
+ </div>
46
+ </template>
47
+
48
+ <script lang="ts" setup>
49
+ import { nextTick, ref, reactive } from 'vue';
50
+
51
+ const showing = ref(false);
52
+ const position = reactive({
53
+ x: 0,
54
+ y: 0
55
+ })
56
+
57
+ const handleContextMenu = (e: MouseEvent) => {
58
+ e.preventDefault();
59
+ showing.value = false;
60
+ nextTick().then(() => {
61
+ showing.value = true;
62
+
63
+ position.x = e.clientX;
64
+ position.y = e.clientY;
65
+ })
66
+ }
67
+
68
+ const handleClick = () => {
69
+ alert('hi');
70
+ }
71
+ </script>
@@ -0,0 +1,22 @@
1
+ import MCardContextMenu from '../CardContextMenu.vue';
2
+ import MCardContextMenuList from '../CardContextMenuList.vue';
3
+ import MCardContextMenuItem from '../CardContextMenuItem.vue';
4
+ import MButton from '../../button/Button.vue';
5
+
6
+ import { MCardContextMenuBasic } from './index';
7
+ import { createStory, popperPositionArgType } from '../../../__storybook__';
8
+
9
+ export default {
10
+ component: MCardContextMenu,
11
+ subcomponents: {
12
+ MCardContextMenuList,
13
+ MCardContextMenuItem,
14
+ MButton
15
+ },
16
+ title: 'Components/Card Context Menu',
17
+ argTypes: {
18
+ ...popperPositionArgType()
19
+ }
20
+ };
21
+
22
+ export const Basic = createStory(MCardContextMenuBasic);
@@ -0,0 +1 @@
1
+ export { default as MCardContextMenuBasic } from './basic.vue';
@@ -0,0 +1,30 @@
1
+ import { ref, watch, onMounted, nextTick } from 'vue';
2
+
3
+ import type { Ref } from 'vue';
4
+
5
+ export function useLabel(
6
+ rawLabel: Ref<string | number | null>,
7
+ element: Ref<HTMLElement | null | undefined>
8
+ ) {
9
+ const label = ref(rawLabel.value);
10
+
11
+ function setLabel(value: string | number | null) {
12
+ if (element.value) {
13
+ label.value = value ?? element.value.textContent?.trim() ?? null;
14
+ } else {
15
+ label.value = value;
16
+ }
17
+ }
18
+
19
+ watch(rawLabel, value => {
20
+ setLabel(value);
21
+ });
22
+
23
+ onMounted(() => {
24
+ nextTick(() => {
25
+ setLabel(rawLabel.value);
26
+ });
27
+ });
28
+
29
+ return label;
30
+ }
@@ -0,0 +1,158 @@
1
+ import { createVar, style, styleVariants } from '@vanilla-extract/css';
2
+ import { themeVars } from '../../../styles/theme.css';
3
+
4
+ export const menu = style({
5
+ backgroundColor: '#ffffff',
6
+ borderRadius: '5px',
7
+ padding: '5px',
8
+ zIndex: 4000,
9
+ boxSizing: 'border-box',
10
+ position: 'relative',
11
+ minWidth: '130px',
12
+ maxWidth: '350px',
13
+ border: `1px solid ${themeVars.color.gray[300]}`,
14
+ boxShadow: themeVars.shadow.md,
15
+ overflow: 'auto'
16
+ });
17
+
18
+ export const menuItems = style({
19
+ listStyle: 'none',
20
+ margin: 0,
21
+ padding: 0
22
+ });
23
+
24
+ const vars = {
25
+ backgroundColor: createVar(),
26
+ color: createVar()
27
+ };
28
+
29
+ export const menuItem = style({
30
+ vars: {
31
+ [vars.backgroundColor]: 'transparent',
32
+ [vars.color]: themeVars.color.font.text
33
+ },
34
+ display: 'grid',
35
+ alignItems: 'center',
36
+ gridTemplateAreas: '"icon name kbd decoration"',
37
+ gridTemplateColumns: '16px 1fr auto minmax(8px, auto)',
38
+ gridTemplateRows: '16px',
39
+ columnGap: themeVars.space['1.5'],
40
+ rowGap: themeVars.space['0.5'],
41
+ borderRadius: themeVars.rounded.default,
42
+ padding: `${themeVars.space['2']} ${themeVars.space['1.5']}`,
43
+ fontSize: themeVars.fontSize.base,
44
+ color: themeVars.color.font.text,
45
+ cursor: 'pointer',
46
+ transition: 'background-color 0.14s ease',
47
+ textDecoration: 'none',
48
+ ':hover': {
49
+ vars: {
50
+ [vars.backgroundColor]: themeVars.color.gray[100],
51
+ [vars.color]: themeVars.color.font.text
52
+ },
53
+ backgroundColor: vars.backgroundColor,
54
+ color: vars.color
55
+ }
56
+ });
57
+
58
+ export const variant = styleVariants({
59
+ primary: {
60
+ color: themeVars.color.blue[500],
61
+ ':hover': {
62
+ vars: {
63
+ [vars.backgroundColor]: themeVars.color.blue[50],
64
+ [vars.color]: themeVars.color.blue[500]
65
+ }
66
+ }
67
+ },
68
+ dark: {
69
+ ':hover': {
70
+ vars: {
71
+ [vars.backgroundColor]: themeVars.color.gray[100],
72
+ [vars.color]: themeVars.color.font.text
73
+ }
74
+ }
75
+ },
76
+ default: {
77
+ ':hover': {
78
+ vars: {
79
+ [vars.backgroundColor]: themeVars.color.gray[100],
80
+ [vars.color]: themeVars.color.font.text
81
+ }
82
+ }
83
+ },
84
+ tertiary: {
85
+ ':hover': {
86
+ vars: {
87
+ [vars.backgroundColor]: themeVars.color.gray[100],
88
+ [vars.color]: themeVars.color.font.text
89
+ }
90
+ }
91
+ },
92
+ success: {
93
+ color: themeVars.color.green[600],
94
+ ':hover': {
95
+ vars: {
96
+ [vars.backgroundColor]: themeVars.color.green[50],
97
+ [vars.color]: themeVars.color.green[600]
98
+ }
99
+ }
100
+ },
101
+ warning: {
102
+ color: themeVars.color.amber[600],
103
+ ':hover': {
104
+ vars: {
105
+ [vars.backgroundColor]: themeVars.color.amber[50],
106
+ [vars.color]: themeVars.color.amber[600]
107
+ }
108
+ }
109
+ },
110
+ error: {
111
+ color: themeVars.color.red[600],
112
+ ':hover': {
113
+ vars: {
114
+ [vars.backgroundColor]: themeVars.color.red[50],
115
+ [vars.color]: themeVars.color.red[500]
116
+ }
117
+ }
118
+ }
119
+ });
120
+
121
+ export const menuItemTextContainer = style({
122
+ margin: `0 ${themeVars.space[0.5]}`,
123
+ gridArea: 'name',
124
+ overflow: 'hidden',
125
+ display: 'flex',
126
+ alignItems: 'center',
127
+ gap: themeVars.space[2]
128
+ });
129
+
130
+ export const menuItemText = style({
131
+ flex: `0 1 auto`,
132
+ overflow: 'hidden',
133
+ whiteSpace: 'nowrap',
134
+ textOverflow: 'ellipsis'
135
+ });
136
+
137
+ export const menuItemIcon = style({
138
+ gridArea: 'icon',
139
+ flexShrink: 0,
140
+ display: 'flex',
141
+ position: 'relative',
142
+ top: '1px',
143
+ opacity: 0.8
144
+ });
145
+
146
+ export const menuSeperator = style({
147
+ height: '1px',
148
+ backgroundColor: themeVars.color.gray[200],
149
+ width: `calc(100% + 10px)`,
150
+ margin: `5px -5px`
151
+ });
152
+
153
+ export const heading = style({
154
+ padding: `${themeVars.space[2]} ${themeVars.space[2.5]}`,
155
+ fontWeight: 500,
156
+ fontSize: themeVars.fontSize.small,
157
+ color: themeVars.color.gray[600]
158
+ });
@@ -0,0 +1 @@
1
+ export * from './Dropdown.css';
@@ -0,0 +1,9 @@
1
+ import type { InjectionKey } from 'vue';
2
+
3
+ export interface CardContextMenuState {
4
+ handleSelect: (labels: string[]) => void;
5
+ isOpen: boolean;
6
+ }
7
+
8
+ export const CARDCONTEXTMENU_STATE: InjectionKey<CardContextMenuState> =
9
+ Symbol('CARDCONTEXTMENU_STATE');
@@ -1,52 +1,41 @@
1
1
  <template>
2
2
  <Teleport to="body">
3
- <TransitionGroup
4
- type="animation"
5
- :enter-active-class="fade.enterActive"
6
- :leave-active-class="fade.leaveActive"
7
- :enter-from-class="fade.enterFrom"
8
- :leave-to-class="fade.leaveTo"
9
- >
10
- <div :class="style.root" v-if="open" :style="{ zIndex: zIndex, position: 'fixed', inset: '0', pointerEvents: modal ? 'all' : 'none' }">
3
+ <Transition :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.root" v-if="open"
6
+ :style="{ zIndex: zIndex, position: 'fixed', inset: '0', pointerEvents: modal ? 'all' : 'none' }">
11
7
  <div :class="backdropClasses" v-if="modal"></div>
12
8
  <div ref="wrapper" :class="wrapperClasses">
13
- <Transition
14
- type="animation"
15
- :enter-active-class="modalScale.enterActive"
16
- :leave-active-class="modalScale.leaveActive"
17
- :enter-from-class="modalScale.enterFrom"
18
- :leave-to-class="modalScale.leaveTo"
19
- @enter="onEnter"
20
- >
21
- <div ref="dialog" :style="computedStyle">
22
- <div tabindex="0" aria-hidden="true"
23
- style="width: 0px; height: 0px; overflow: hidden; outline: none;"></div>
24
- <slot v-if="$slots.container" name="container" :close="close"></slot>
25
- <template v-else>
26
- <div :class="style.content">
27
- <button role="button" :class="style.close" @click="close"></button>
28
- <div :class="headerClasses" ref="handle">
29
- <div :class="style.title">
30
- <slot name="title">
31
- {{ resolvedTitle }}
32
- </slot>
33
- </div>
34
- </div>
35
- <div>
36
- <slot></slot>
37
- </div>
38
- <div v-if="$slots.footer" :class="style.footer">
39
- <slot name="footer"></slot>
9
+
10
+ <div ref="dialog" :style="computedStyle">
11
+ <div tabindex="0" aria-hidden="true"
12
+ style="width: 0px; height: 0px; overflow: hidden; outline: none;"></div>
13
+ <slot v-if="$slots.container" name="container" :close="close"></slot>
14
+ <template v-else>
15
+ <div :class="style.content">
16
+ <button role="button" :class="style.close" @click="close"></button>
17
+ <div :class="headerClasses" ref="handle">
18
+ <div :class="style.title">
19
+ <slot name="title">
20
+ {{ resolvedTitle }}
21
+ </slot>
40
22
  </div>
41
23
  </div>
42
- </template>
43
- <div tabindex="0" aria-hidden="true"
44
- style="width: 0px; height: 0px; overflow: hidden; outline: none;"></div>
45
- </div>
46
- </Transition>
24
+ <div>
25
+ <slot></slot>
26
+ </div>
27
+ <div v-if="$slots.footer" :class="style.footer">
28
+ <slot name="footer"></slot>
29
+ </div>
30
+ </div>
31
+ </template>
32
+ <div tabindex="0" aria-hidden="true"
33
+ style="width: 0px; height: 0px; overflow: hidden; outline: none;"></div>
34
+ </div>
35
+
47
36
  </div>
48
37
  </div>
49
- </TransitionGroup>
38
+ </Transition>
50
39
  </Teleport>
51
40
  </template>
52
41
  <script lang="ts">
@@ -84,7 +73,7 @@ export default defineComponent({
84
73
  },
85
74
  onClose: {
86
75
  type: Function,
87
- default: () => {},
76
+ default: () => { },
88
77
  },
89
78
  zIndex: {
90
79
  type: Number,
@@ -111,7 +100,6 @@ export default defineComponent({
111
100
  const { nextZIndex, current: maxZIndex } = useZIndex();
112
101
  const zIndex = ref(props.zIndex ?? nextZIndex());
113
102
 
114
- const isOpen = ref<boolean>(props.open);
115
103
  const isDragging = ref<boolean>(false);
116
104
 
117
105
  const { x, y } = useDraggable(dialog, {
@@ -156,7 +144,6 @@ export default defineComponent({
156
144
  }));
157
145
 
158
146
  function close() {
159
- isOpen.value = false;
160
147
  emit('update:open', false);
161
148
  onCloseEmit();
162
149
  }
@@ -204,7 +191,7 @@ export default defineComponent({
204
191
  }
205
192
 
206
193
  useEventListener(window, 'resize', () => {
207
- if (isOpen.value) {
194
+ if (props.open) {
208
195
  if (!props.draggable) {
209
196
  nextTick(() => centerDialog())
210
197
  } else {
@@ -216,7 +203,6 @@ export default defineComponent({
216
203
  watch(
217
204
  () => props.open,
218
205
  async (newVal) => {
219
- isOpen.value = newVal;
220
206
  if (newVal) {
221
207
  await nextTick();
222
208
  centerDialog();
@@ -243,9 +229,9 @@ export default defineComponent({
243
229
  backdropClasses,
244
230
  resolvedTitle,
245
231
  wrapperClasses,
246
- isOpen,
247
232
  close,
248
233
  onEnter,
234
+ open: computed(() => props.open)
249
235
  };
250
236
  },
251
237
  });