@teammodlr/ui-kit 2.0.39 → 2.1.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.
- package/lib/components/avatar/Avatar.vue.d.ts +1 -1
- package/lib/components/avatargroup/AvatarGroup.vue.d.ts +1 -1
- package/lib/components/badge/Badge.vue.d.ts +1 -1
- package/lib/components/breadcrumb/Breadcrumb.vue.d.ts +1 -10
- package/lib/components/breadcrumb/BreadcrumbItem.vue.d.ts +1 -1
- package/lib/components/button/Button.vue.d.ts +2 -2
- package/lib/components/buttongroup/ButtonGroup.vue.d.ts +1 -1
- package/lib/components/checkbox/Checkbox.vue.d.ts +1 -1
- package/lib/components/colorpicker/ColorPicker.vue.d.ts +1 -1
- package/lib/components/dialog/Dialog.vue.d.ts +46 -0
- package/lib/components/dialog/DialogProvider.vue.d.ts +37 -0
- package/lib/components/dialog/props.d.ts +22 -0
- package/lib/components/dialog/providerProps.d.ts +8 -0
- package/lib/components/dialog/types.d.ts +27 -0
- package/lib/components/dialog/useDialog.d.ts +2 -0
- package/lib/components/dropdown/Dropdown.vue.d.ts +1 -1
- package/lib/components/dropdown/DropdownItem.vue.d.ts +1 -1
- package/lib/components/dropdown/DropdownList.vue.d.ts +1 -1
- package/lib/components/dropdown/DropdownSeperator.vue.d.ts +1 -1
- package/lib/components/dropdown/DropdownWrapper.vue.d.ts +1 -1
- package/lib/components/form/Form.vue.d.ts +1 -1
- package/lib/components/image/Image.vue.d.ts +1 -1
- package/lib/components/index.d.ts +3 -0
- package/lib/components/input/Input.vue.d.ts +3 -3
- package/lib/components/link/Link.vue.d.ts +1 -1
- package/lib/components/messageprovider/Message.vue.d.ts +2 -2
- package/lib/components/messageprovider/MessageProvider.vue.d.ts +3 -3
- package/lib/components/modal/Modal.vue.d.ts +10 -1
- package/lib/components/pagination/Pagination.vue.d.ts +1 -1
- package/lib/components/radio/Radio.vue.d.ts +13 -4
- package/lib/components/radiobutton/RadioButton.vue.d.ts +1 -1
- package/lib/components/radiobuttongroup/RadioButtonGroup.vue.d.ts +1 -1
- package/lib/components/renderer/examlpes/basic.vue.d.ts +2 -0
- package/lib/components/renderer/examlpes/index.d.ts +1 -0
- package/lib/components/renderer/props.d.ts +12 -0
- package/lib/components/renderer/renderer.d.ts +23 -0
- package/lib/components/select/Select.vue.d.ts +2 -2
- package/lib/components/select/style/Select.css.d.ts +2 -0
- package/lib/components/skeleton/Skeleton.vue.d.ts +1 -1
- package/lib/components/slider/Slider.vue.d.ts +1 -1
- package/lib/components/switch/Switch.vue.d.ts +1 -1
- package/lib/components/tab/Tab.vue.d.ts +1 -1
- package/lib/components/tab/TabGroup.vue.d.ts +1 -1
- package/lib/components/table/Table.vue.d.ts +1 -1
- package/lib/components/table/TableBody.vue.d.ts +1 -1
- package/lib/components/table/TableCell.vue.d.ts +1 -1
- package/lib/components/table/TableHead.vue.d.ts +1 -1
- package/lib/components/table/TableHeadRow.vue.d.ts +1 -1
- package/lib/components/table/TableRow.vue.d.ts +1 -1
- package/lib/components/tag/Tag.vue.d.ts +2 -2
- package/lib/components/textarea/Textarea.vue.d.ts +3 -3
- package/lib/components/tooltip/Tooltip.vue.d.ts +1 -1
- package/lib/components/transfer/Transfer.vue.d.ts +1 -1
- package/lib/components/virtualscroll/VirtualScroll.vue.d.ts +1 -1
- package/lib/composables/index.d.ts +1 -0
- package/lib/index.cjs.js +2 -8
- package/lib/index.es.js +2873 -3245
- package/lib/nuxt.plugin.js +1 -1
- package/lib/style.css +1 -1
- package/lib/styles/theme.css.d.ts +10 -10
- package/package.json +24 -27
- package/src/components/breadcrumb/Breadcrumb.vue +4 -8
- package/src/components/dialog/Dialog.vue +60 -0
- package/src/components/dialog/DialogProvider.vue +81 -0
- package/src/components/dialog/examples/basic.vue +48 -0
- package/src/components/dialog/examples/index.stories.ts +29 -0
- package/src/components/dialog/examples/index.ts +1 -0
- package/src/components/dialog/examples/wrapper.vue +9 -0
- package/src/components/dialog/props.ts +24 -0
- package/src/components/dialog/providerProps.ts +11 -0
- package/src/components/dialog/types.ts +34 -0
- package/src/components/dialog/useDialog.ts +12 -0
- package/src/components/index.ts +3 -0
- package/src/components/input/Input.vue +1 -1
- package/src/components/input/examples/basic.vue +0 -1
- package/src/components/input/style/Input.css.ts +1 -1
- package/src/components/messageprovider/MessageProvider.vue +7 -7
- package/src/components/messageprovider/style/Message.css.ts +2 -1
- package/src/components/modal/Modal.vue +14 -7
- package/src/components/radio/Radio.vue +32 -33
- package/src/components/radio/examples/basic.vue +2 -3
- package/src/components/radio/examples/group.vue +15 -0
- package/src/components/radio/examples/index.stories.ts +2 -0
- package/src/components/radio/examples/index.ts +1 -0
- package/src/components/renderer/examlpes/basic.vue +23 -0
- package/src/components/renderer/examlpes/index.stories.ts +18 -0
- package/src/components/renderer/examlpes/index.ts +1 -0
- package/src/components/renderer/props.ts +15 -0
- package/src/components/renderer/renderer.ts +16 -0
- package/src/components/select/Select.vue +7 -1
- package/src/components/select/style/Select.css.ts +25 -1
- package/src/composables/index.ts +2 -1
- package/src/composables/useZIndex.ts +5 -3
- package/src/examples/modal/modal.stories.ts +9 -0
- package/src/examples/modal/modal.vue +52 -0
- package/src/exports/nuxt.plugin.js +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Variant } from '../../types/props';
|
|
2
|
+
import type { VNodeChild } from 'vue';
|
|
3
|
+
|
|
4
|
+
export type DialogContentType = string;
|
|
5
|
+
|
|
6
|
+
export type DialogContentRender = (props: any) => VNodeChild;
|
|
7
|
+
|
|
8
|
+
export interface DialogOptions {
|
|
9
|
+
title?: string,
|
|
10
|
+
render?: DialogContentRender,
|
|
11
|
+
content: DialogContentType,
|
|
12
|
+
onClose?: () => void,
|
|
13
|
+
onOpen?: () => void,
|
|
14
|
+
onOk?: () => void,
|
|
15
|
+
onCancel?: () => void,
|
|
16
|
+
okVariant?: Variant,
|
|
17
|
+
okText?: DialogContentType,
|
|
18
|
+
cancelText?: DialogContentType,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface DialogResponse {
|
|
22
|
+
result: boolean,
|
|
23
|
+
data: any
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DialogApiInjection {
|
|
27
|
+
create: (options: DialogOptions) => Dialog
|
|
28
|
+
destroyAll: () => void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export interface Dialog extends DialogOptions {
|
|
33
|
+
destroy: () => void
|
|
34
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { inject } from 'vue';
|
|
2
|
+
import type { DialogApiInjection } from './types';
|
|
3
|
+
|
|
4
|
+
export function useDialog(): DialogApiInjection {
|
|
5
|
+
const api = inject('m-dialog', null);
|
|
6
|
+
|
|
7
|
+
if (api === null) {
|
|
8
|
+
throw new Error('m-dialog api is not provided, ensure the component is wrapped in <m-dialog-provider />.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return api;
|
|
12
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { default as MRenderer } from './renderer/renderer';
|
|
1
2
|
export { default as MAvatar } from './avatar/Avatar.vue';
|
|
2
3
|
export { default as MAvatarGroup } from './avatargroup/AvatarGroup.vue';
|
|
3
4
|
export { default as MBadge } from './badge/Badge.vue';
|
|
@@ -39,3 +40,5 @@ export { default as MTextarea } from './textarea/Textarea.vue';
|
|
|
39
40
|
export { default as MTooltip } from './tooltip/Tooltip.vue';
|
|
40
41
|
export { default as MTransfer } from './transfer/Transfer.vue';
|
|
41
42
|
export { default as MVirtualScroll } from './virtualscroll/VirtualScroll.vue';
|
|
43
|
+
export { default as MDialog } from './dialog/Dialog.vue';
|
|
44
|
+
export { default as MDialogProvider } from './dialog/DialogProvider.vue';
|
|
@@ -158,6 +158,7 @@ export default defineComponent({
|
|
|
158
158
|
style.size[props.size],
|
|
159
159
|
{
|
|
160
160
|
[style.block]: props.block,
|
|
161
|
+
[style.error]: inputError.value,
|
|
161
162
|
}
|
|
162
163
|
]
|
|
163
164
|
});
|
|
@@ -168,7 +169,6 @@ export default defineComponent({
|
|
|
168
169
|
{
|
|
169
170
|
[style.block]: props.block,
|
|
170
171
|
[style.disabled]: disabled.value || loading.value,
|
|
171
|
-
[style.error]: inputError.value,
|
|
172
172
|
[style.hasLeftIcon]: hasLeftIcon.value,
|
|
173
173
|
[style.hasRightIcon]: hasRightIcon.value,
|
|
174
174
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<slot />
|
|
3
|
-
<template
|
|
3
|
+
<template>
|
|
4
4
|
<Teleport :to="teleportTo ?? 'body'">
|
|
5
5
|
<transition
|
|
6
6
|
type="animation"
|
|
7
|
-
:enter-active-class="
|
|
8
|
-
:leave-active-class="
|
|
9
|
-
:enter-from-class="
|
|
10
|
-
:leave-to-class="
|
|
7
|
+
:enter-active-class="modalScale.enterActive"
|
|
8
|
+
:leave-active-class="modalScale.leaveActive"
|
|
9
|
+
:enter-from-class="modalScale.enterFrom"
|
|
10
|
+
:leave-to-class="modalScale.leaveTo"
|
|
11
11
|
>
|
|
12
12
|
<div :class="classes">
|
|
13
13
|
<MMessage v-for="message in messageList"
|
|
@@ -39,7 +39,7 @@ import type { PropType } from 'vue';
|
|
|
39
39
|
import MMessage from './Message.vue';
|
|
40
40
|
import { useCachedUid } from '../../composables/useCachedUid';
|
|
41
41
|
import * as style from './style';
|
|
42
|
-
import {
|
|
42
|
+
import { modalScale } from '../../styles/transitions.css';
|
|
43
43
|
export type MessageProviderInst = MessageApiInjection;
|
|
44
44
|
|
|
45
45
|
interface PrivateMessageReactive extends MessageReactive {
|
|
@@ -144,7 +144,7 @@ export default defineComponent({
|
|
|
144
144
|
messageList: messageListRef,
|
|
145
145
|
onInternalAfterLeave,
|
|
146
146
|
classes,
|
|
147
|
-
|
|
147
|
+
modalScale
|
|
148
148
|
},
|
|
149
149
|
api,
|
|
150
150
|
)
|
|
@@ -35,7 +35,8 @@ export const base = style({
|
|
|
35
35
|
fontSize: themeVars.fontSize.base,
|
|
36
36
|
color: themeVars.color.font.text,
|
|
37
37
|
alignItems: "center",
|
|
38
|
-
|
|
38
|
+
willChange: "top, bottom, width",
|
|
39
|
+
transition: "top 0.3s ease-out 0.5s, bottom 0.3s ease-out 0.5s, width 0.3s ease-out 0.5s",
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
export const placement = styleVariants({
|
|
@@ -67,6 +67,10 @@ export default defineComponent({
|
|
|
67
67
|
type: Boolean,
|
|
68
68
|
default: true
|
|
69
69
|
},
|
|
70
|
+
onClose: {
|
|
71
|
+
type: Function as PropType<() => void>,
|
|
72
|
+
default: () => {}
|
|
73
|
+
},
|
|
70
74
|
zIndex: {
|
|
71
75
|
type: Number
|
|
72
76
|
}
|
|
@@ -77,11 +81,11 @@ export default defineComponent({
|
|
|
77
81
|
const isOpen = ref(false);
|
|
78
82
|
const target = ref();
|
|
79
83
|
const zIndex = ref(props.zIndex ?? nextZIndex());
|
|
80
|
-
const {hasFocus, activate, deactivate} = useFocusTrap(target, {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
});
|
|
84
|
+
// const {hasFocus, activate, deactivate} = useFocusTrap(target, {
|
|
85
|
+
// immediate: true,
|
|
86
|
+
// escapeDeactivates: false,
|
|
87
|
+
// allowOutsideClick: true
|
|
88
|
+
// });
|
|
85
89
|
|
|
86
90
|
const { escape } = useMagicKeys()
|
|
87
91
|
|
|
@@ -105,6 +109,9 @@ export default defineComponent({
|
|
|
105
109
|
};
|
|
106
110
|
|
|
107
111
|
const close = () => {
|
|
112
|
+
if (props.onClose) {
|
|
113
|
+
props.onClose();
|
|
114
|
+
}
|
|
108
115
|
ownerScrollbarClose();
|
|
109
116
|
isOpen.value = false;
|
|
110
117
|
};
|
|
@@ -144,10 +151,10 @@ export default defineComponent({
|
|
|
144
151
|
zIndex.value = props.zIndex ? zIndex.value++ : nextZIndex();
|
|
145
152
|
emit('open');
|
|
146
153
|
nextTick(() => {
|
|
147
|
-
activate()
|
|
154
|
+
// activate()
|
|
148
155
|
})
|
|
149
156
|
} else {
|
|
150
|
-
deactivate()
|
|
157
|
+
// deactivate()
|
|
151
158
|
}
|
|
152
159
|
});
|
|
153
160
|
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<label :class="style.base"
|
|
2
|
+
<label :class="style.base">
|
|
3
3
|
<input
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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"
|
|
15
16
|
/>
|
|
16
17
|
<span :class="classes"></span>
|
|
17
18
|
<span :class="style.label" :id="`${id}-label`">
|
|
@@ -27,10 +28,11 @@
|
|
|
27
28
|
</template>
|
|
28
29
|
|
|
29
30
|
<script lang="ts">
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import
|
|
31
|
+
import type { PropType } from 'vue';
|
|
32
|
+
import { computed, defineComponent, defineExpose, ref, toRef } from 'vue';
|
|
33
|
+
import { useInput } from '../../composables/useInput';
|
|
34
|
+
import { useInteractive } from "../../composables/useInteractive";
|
|
35
|
+
import type { Size } from '../../types/props';
|
|
34
36
|
import * as style from './style';
|
|
35
37
|
|
|
36
38
|
export default defineComponent({
|
|
@@ -53,6 +55,10 @@ export default defineComponent({
|
|
|
53
55
|
loading: {
|
|
54
56
|
type: Boolean,
|
|
55
57
|
default: false
|
|
58
|
+
},
|
|
59
|
+
value: {
|
|
60
|
+
type: [String, Number, Boolean],
|
|
61
|
+
default: null
|
|
56
62
|
}
|
|
57
63
|
},
|
|
58
64
|
setup(props, {slots, emit}) {
|
|
@@ -74,8 +80,16 @@ export default defineComponent({
|
|
|
74
80
|
|
|
75
81
|
const disabled = computed(() => formDisabled || formLoading || props.disabled || props.loading);
|
|
76
82
|
const name = toRef(props, 'name');
|
|
77
|
-
const checked =
|
|
83
|
+
const checked = computed(() => props.modelValue === props.value);
|
|
78
84
|
const hasSlot = computed(() => !!(slots.default));
|
|
85
|
+
const pick = computed({
|
|
86
|
+
get() {
|
|
87
|
+
return props.modelValue;
|
|
88
|
+
},
|
|
89
|
+
set(value) {
|
|
90
|
+
emit('update:modelValue', value);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
79
93
|
|
|
80
94
|
const classes = computed(() => {
|
|
81
95
|
return [
|
|
@@ -92,21 +106,6 @@ export default defineComponent({
|
|
|
92
106
|
return formError.value || props.error;
|
|
93
107
|
});
|
|
94
108
|
|
|
95
|
-
watch(() => props.modelValue, (value) => {
|
|
96
|
-
checked.value = !!value;
|
|
97
|
-
}, {immediate: true});
|
|
98
|
-
|
|
99
|
-
watch(() => checked.value, (value) => {
|
|
100
|
-
emit('update:modelValue', value);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
function toggle() {
|
|
104
|
-
if (disabled.value) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
checked.value = !checked.value;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
109
|
defineExpose({
|
|
111
110
|
focus,
|
|
112
111
|
blur,
|
|
@@ -122,9 +121,9 @@ export default defineComponent({
|
|
|
122
121
|
disabled,
|
|
123
122
|
name,
|
|
124
123
|
checked,
|
|
124
|
+
pick,
|
|
125
125
|
radioRef,
|
|
126
126
|
inputError,
|
|
127
|
-
toggle,
|
|
128
127
|
style,
|
|
129
128
|
classes,
|
|
130
129
|
hasSlot,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<MRadio
|
|
2
|
+
<MRadio label="Test" name="item" value="sms" v-model="selected" />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script lang="ts" setup>
|
|
6
6
|
import { ref } from 'vue'
|
|
7
|
-
|
|
8
|
-
const checked = ref(false);
|
|
7
|
+
const selected = ref('');
|
|
9
8
|
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<MRadio label="SMS" name="item" value="sms" v-model="selected" /><br />
|
|
4
|
+
<MRadio label="Email" name="item" value="email" v-model="selected" />
|
|
5
|
+
<div>
|
|
6
|
+
Selected: {{ selected }}
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script lang="ts" setup>
|
|
12
|
+
import { ref } from 'vue'
|
|
13
|
+
|
|
14
|
+
const selected = ref('sms');
|
|
15
|
+
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<MRenderer :h="renderMessage" :props="{ message: msg }">
|
|
3
|
+
</MRenderer>
|
|
4
|
+
</template>
|
|
5
|
+
|
|
6
|
+
<script setup lang="ts">
|
|
7
|
+
import { h, ref } from 'vue'
|
|
8
|
+
const msg = ref('some content')
|
|
9
|
+
|
|
10
|
+
function renderMessage({ message }: { message: string }) {
|
|
11
|
+
return h('p', [
|
|
12
|
+
'Here are ',
|
|
13
|
+
h(
|
|
14
|
+
'span',
|
|
15
|
+
{
|
|
16
|
+
style: 'color: red'
|
|
17
|
+
},
|
|
18
|
+
[message]
|
|
19
|
+
),
|
|
20
|
+
' that using render function',
|
|
21
|
+
])
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import MRenderer from "../renderer";
|
|
2
|
+
import {
|
|
3
|
+
MRendererBasic,
|
|
4
|
+
} from "./index";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
createStory, sizeArgType
|
|
8
|
+
} from "../../../__storybook__";
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
component: MRenderer,
|
|
12
|
+
title: 'Components/Renderer',
|
|
13
|
+
argTypes: {
|
|
14
|
+
...sizeArgType()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Basic = createStory(MRendererBasic);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as MRendererBasic } from './basic.vue';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ExtractPropTypes, PropType } from 'vue';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const rendererProps = {
|
|
5
|
+
h: {
|
|
6
|
+
type: Function,
|
|
7
|
+
default: null
|
|
8
|
+
},
|
|
9
|
+
props: {
|
|
10
|
+
type: Object as PropType<Record<string, any>>,
|
|
11
|
+
default: undefined
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type RendererProps = ExtractPropTypes<typeof rendererProps>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineComponent, renderSlot } from 'vue';
|
|
2
|
+
import { rendererProps } from './props';
|
|
3
|
+
|
|
4
|
+
export default defineComponent({
|
|
5
|
+
name: "Renderer",
|
|
6
|
+
props: rendererProps,
|
|
7
|
+
setup(props, { slots }) {
|
|
8
|
+
return () => {
|
|
9
|
+
if (typeof props.h !== 'function') {
|
|
10
|
+
return renderSlot(slots, 'default', props.props);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return props.h(props.props);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
})
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
<div :class="style.menu" v-if="isOpen" ref="popper" :style="computedConsistentWidth"
|
|
42
42
|
:aria-hidden="isOpen ? 'false' : 'true'">
|
|
43
43
|
<div v-if="searchable" :class="style.search">
|
|
44
|
-
<MInput v-model="search" placeholder="Search" size="sm" ref="searchRef"/>
|
|
44
|
+
<!-- <MInput v-model="search" placeholder="Search" size="sm" ref="searchRef"/> -->
|
|
45
|
+
<input type="text" ref="searchRef" v-model="search" placeholder="Search" :class="style.searchInput" />
|
|
45
46
|
</div>
|
|
46
47
|
<div :class="style.options">
|
|
47
48
|
<div v-for="(option, index) in computedOptions" :key="index" ref="optionsRef"
|
|
@@ -54,6 +55,11 @@
|
|
|
54
55
|
@hover="selectedIndex = index">
|
|
55
56
|
{{ option.label }}
|
|
56
57
|
</div>
|
|
58
|
+
<template v-if="computedOptions.length === 0">
|
|
59
|
+
<div :class="style.noResults">
|
|
60
|
+
No results
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
57
63
|
</div>
|
|
58
64
|
</div>
|
|
59
65
|
</Transition>
|
|
@@ -63,6 +63,7 @@ export const base = style({
|
|
|
63
63
|
lineHeight: vars.height,
|
|
64
64
|
boxSizing: 'border-box',
|
|
65
65
|
resize: 'none',
|
|
66
|
+
cursor: 'pointer',
|
|
66
67
|
boxShadow: 'none',
|
|
67
68
|
transition: `color .3s ${themeVars.transition.default},
|
|
68
69
|
background-color .3s ${themeVars.transition.default},
|
|
@@ -194,13 +195,23 @@ export const placeholder = style({
|
|
|
194
195
|
})
|
|
195
196
|
|
|
196
197
|
export const search = style({
|
|
197
|
-
padding: `${themeVars.space[1]} ${themeVars.space[1]} 0`,
|
|
198
|
+
// padding: `${themeVars.space[1]} ${themeVars.space[1]} 0`,
|
|
198
199
|
backgroundColor: '#FFFFFF',
|
|
199
200
|
position: 'sticky',
|
|
200
201
|
top: 0,
|
|
201
202
|
zIndex: 1,
|
|
202
203
|
});
|
|
203
204
|
|
|
205
|
+
export const searchInput = style({
|
|
206
|
+
padding: `${themeVars.space[2.5]} ${themeVars.space[2.5]}`,
|
|
207
|
+
border: 'none',
|
|
208
|
+
outline: 'none',
|
|
209
|
+
width: '100%',
|
|
210
|
+
fontSize: themeVars.fontSize.base,
|
|
211
|
+
borderBottom: `1px solid ${themeVars.color.gray[200]}`,
|
|
212
|
+
color: themeVars.color.gray[800],
|
|
213
|
+
});
|
|
214
|
+
|
|
204
215
|
export const options = style({
|
|
205
216
|
padding: themeVars.space[1],
|
|
206
217
|
display: 'flex',
|
|
@@ -259,3 +270,16 @@ export const optionSelected = style({
|
|
|
259
270
|
},
|
|
260
271
|
}
|
|
261
272
|
});
|
|
273
|
+
|
|
274
|
+
export const noResults = style({
|
|
275
|
+
padding: `${themeVars.space[2]} 0`,
|
|
276
|
+
display: 'flex',
|
|
277
|
+
// flexDirection: 'column',
|
|
278
|
+
alignItems: 'center',
|
|
279
|
+
textAlign: 'center',
|
|
280
|
+
justifyContent: 'center',
|
|
281
|
+
gap: themeVars.space[0.5],
|
|
282
|
+
width: '100%',
|
|
283
|
+
color: themeVars.color.gray[500],
|
|
284
|
+
fontSize: themeVars.fontSize.small,
|
|
285
|
+
});
|
package/src/composables/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type {InjectionKey, Ref} from "vue";
|
|
2
2
|
import {computed, inject, ref, unref} from "vue";
|
|
3
|
-
import {isNumber} from "@vueuse/core";
|
|
4
3
|
|
|
5
4
|
const zIndex = ref(0);
|
|
6
5
|
export const initialZIndex = 1000;
|
|
@@ -11,7 +10,10 @@ export const useZIndex = (override?: Ref<number>) => {
|
|
|
11
10
|
|
|
12
11
|
const initial = computed(() => {
|
|
13
12
|
const fromInjection = unref(injection);
|
|
14
|
-
|
|
13
|
+
if (fromInjection === undefined || isNaN(fromInjection)) {
|
|
14
|
+
return initialZIndex;
|
|
15
|
+
}
|
|
16
|
+
return fromInjection;
|
|
15
17
|
});
|
|
16
18
|
|
|
17
19
|
const current = computed(() => {
|
|
@@ -28,4 +30,4 @@ export const useZIndex = (override?: Ref<number>) => {
|
|
|
28
30
|
current,
|
|
29
31
|
nextZIndex
|
|
30
32
|
}
|
|
31
|
-
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<MModal ref="modal" title="I am a modal" size="md" :canClickOutside="true" :canBounceOnOpen="false" :canSlideIn="true">
|
|
3
|
+
<template #body>
|
|
4
|
+
<div>
|
|
5
|
+
<MSelect
|
|
6
|
+
v-model="value"
|
|
7
|
+
:options="options"
|
|
8
|
+
:option-value="'id'"
|
|
9
|
+
:option-label="'name'"
|
|
10
|
+
blank
|
|
11
|
+
searchable
|
|
12
|
+
/>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
<template #footer>
|
|
16
|
+
<div style="display: flex; flex-grow: 1; justify-content: end;">
|
|
17
|
+
<MButton variant="primary" @click="modal?.close()">
|
|
18
|
+
Okay
|
|
19
|
+
</MButton>
|
|
20
|
+
<MButton style="margin-left: 8px;" @click="modal?.close()">
|
|
21
|
+
Cancel
|
|
22
|
+
</MButton>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
</MModal>
|
|
26
|
+
|
|
27
|
+
<div style="position: relative; width: 100%; height: 1000px;">
|
|
28
|
+
<button @click="open" style="position: absolute; width: 100px; height: 50px; top: 0; left: 0;">Top Left</button>
|
|
29
|
+
<button @click="open" style="position: absolute; width: 100px; height: 50px; top: 0; right: 0;">Top Right</button>
|
|
30
|
+
<button @click="open" style="position: absolute; width: 100px; height: 50px; bottom: 0; left: 0;">Bottom
|
|
31
|
+
Left</button>
|
|
32
|
+
<button @click="open" style="position: absolute; width: 100px; height: 50px; bottom: 0; right: 0;">Bottom
|
|
33
|
+
Right</button>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<script lang="ts" setup>
|
|
38
|
+
import { ref } from 'vue'
|
|
39
|
+
|
|
40
|
+
const modal = ref<any>(null);
|
|
41
|
+
// make list of options with 1000 items
|
|
42
|
+
const options = Array.from({ length: 50 }, (_, i) => ({
|
|
43
|
+
id: i,
|
|
44
|
+
name: `Option ${i+1}`
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
const value = ref();
|
|
48
|
+
const open = (event: MouseEvent) => {
|
|
49
|
+
modal.value.open(event.target);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
</script>
|