@teammodlr/ui-kit 1.0.4 → 1.0.6

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 (147) hide show
  1. package/package.json +2 -1
  2. package/src/__storybook__/argTypes.ts +42 -0
  3. package/src/__storybook__/createStory.ts +15 -0
  4. package/src/__storybook__/index.ts +2 -0
  5. package/src/components/avatar/Avatar.css +69 -0
  6. package/src/components/avatar/Avatar.vue +102 -0
  7. package/src/components/avatar/examples/basic.vue +6 -0
  8. package/src/components/avatar/examples/custom-size.vue +7 -0
  9. package/src/components/avatar/examples/index.stories.ts +28 -0
  10. package/src/components/avatar/examples/index.ts +5 -0
  11. package/src/components/avatar/examples/sizes.vue +33 -0
  12. package/src/components/avatar/examples/slots.vue +7 -0
  13. package/src/components/avatar/examples/variants.vue +18 -0
  14. package/src/components/avatargroup/AvatarGroup.css +8 -0
  15. package/src/components/avatargroup/AvatarGroup.vue +32 -0
  16. package/src/components/avatargroup/examples/basic.vue +11 -0
  17. package/src/components/avatargroup/examples/index.stories.ts +28 -0
  18. package/src/components/avatargroup/examples/index.ts +1 -0
  19. package/src/components/breadcrumb/Breadcrumb.css +46 -0
  20. package/src/components/breadcrumb/Breadcrumb.vue +51 -0
  21. package/src/components/breadcrumb/examples/basic.vue +9 -0
  22. package/src/components/breadcrumb/examples/index.stories.ts +20 -0
  23. package/src/components/breadcrumb/examples/index.ts +1 -0
  24. package/src/components/breadcrumbitem/BreadcrumbItem.vue +66 -0
  25. package/src/components/breadcrumbitem/index.ts +1 -0
  26. package/src/components/button/Button.css +378 -0
  27. package/src/components/button/Button.vue +108 -0
  28. package/src/components/button/examples/basic.vue +3 -0
  29. package/src/components/button/examples/colors-secondary.vue +8 -0
  30. package/src/components/button/examples/colors.vue +8 -0
  31. package/src/components/button/examples/disabled.vue +3 -0
  32. package/src/components/button/examples/icon.vue +10 -0
  33. package/src/components/button/examples/index.stories.ts +33 -0
  34. package/src/components/button/examples/index.ts +7 -0
  35. package/src/components/button/examples/rounded.vue +7 -0
  36. package/src/components/button/examples/size.vue +7 -0
  37. package/src/components/buttongroup/ButtonGroup.vue +47 -0
  38. package/src/components/buttongroup/examples/basic.vue +9 -0
  39. package/src/components/buttongroup/examples/index.stories.ts +21 -0
  40. package/src/components/buttongroup/examples/index.ts +1 -0
  41. package/src/components/checkbox/Checkbox.css +185 -0
  42. package/src/components/checkbox/Checkbox.vue +140 -0
  43. package/src/components/checkbox/examples/basic.vue +9 -0
  44. package/src/components/checkbox/examples/index.stories.ts +21 -0
  45. package/src/components/checkbox/examples/index.ts +3 -0
  46. package/src/components/checkbox/examples/slot.vue +11 -0
  47. package/src/components/dropdown/Dropdown.css +68 -0
  48. package/src/components/dropdown/Dropdown.vue +237 -0
  49. package/src/components/dropdown/DropdownItem.vue +118 -0
  50. package/src/components/dropdown/DropdownList.vue +20 -0
  51. package/src/components/dropdown/DropdownWrapper.vue +17 -0
  52. package/src/components/dropdown/examples/basic.vue +73 -0
  53. package/src/components/dropdown/examples/context.vue +71 -0
  54. package/src/components/dropdown/examples/index.stories.ts +23 -0
  55. package/src/components/dropdown/examples/index.ts +2 -0
  56. package/src/components/dropdown/hooks.ts +30 -0
  57. package/src/components/form/Form.vue +141 -0
  58. package/src/components/form/examples/basic.vue +73 -0
  59. package/src/components/form/examples/index.stories.ts +23 -0
  60. package/src/components/form/examples/index.ts +1 -0
  61. package/src/components/image/Image.vue +71 -0
  62. package/src/components/image/examples/basic.vue +5 -0
  63. package/src/components/image/examples/index.stories.ts +12 -0
  64. package/src/components/image/examples/index.ts +1 -0
  65. package/src/components/index.ts +27 -0
  66. package/src/components/input/Input.css +173 -0
  67. package/src/components/input/Input.vue +176 -0
  68. package/src/components/input/examples/basic.vue +7 -0
  69. package/src/components/input/examples/index.stories.ts +24 -0
  70. package/src/components/input/examples/index.ts +4 -0
  71. package/src/components/input/examples/prefix.vue +7 -0
  72. package/src/components/input/examples/sizes.vue +9 -0
  73. package/src/components/input/examples/suffix.vue +7 -0
  74. package/src/components/link/Link.css +147 -0
  75. package/src/components/link/Link.vue +54 -0
  76. package/src/components/link/examples/basic.vue +3 -0
  77. package/src/components/link/examples/index.stories.ts +20 -0
  78. package/src/components/link/examples/index.ts +1 -0
  79. package/src/components/messageprovider/Message.vue +76 -0
  80. package/src/components/messageprovider/MessageProvider.css +36 -0
  81. package/src/components/messageprovider/MessageProvider.vue +142 -0
  82. package/src/components/messageprovider/examples/basic.vue +19 -0
  83. package/src/components/messageprovider/examples/index.stories.ts +30 -0
  84. package/src/components/messageprovider/examples/index.ts +1 -0
  85. package/src/components/messageprovider/examples/wrapper.vue +9 -0
  86. package/src/components/messageprovider/types.ts +39 -0
  87. package/src/components/messageprovider/useMessage.ts +12 -0
  88. package/src/components/select/Select.css +226 -0
  89. package/src/components/select/Select.vue +474 -0
  90. package/src/components/select/examples/basic.vue +20 -0
  91. package/src/components/select/examples/index.stories.ts +22 -0
  92. package/src/components/select/examples/index.ts +3 -0
  93. package/src/components/select/examples/multiple.vue +22 -0
  94. package/src/components/select/examples/searchable.vue +20 -0
  95. package/src/components/skeleton/Skeleton.css +73 -0
  96. package/src/components/skeleton/Skeleton.vue +47 -0
  97. package/src/components/skeleton/examples/basic.vue +3 -0
  98. package/src/components/skeleton/examples/index.stories.ts +24 -0
  99. package/src/components/skeleton/examples/index.ts +2 -0
  100. package/src/components/skeleton/examples/post.vue +8 -0
  101. package/src/components/tab/Tab.css +113 -0
  102. package/src/components/tab/Tab.vue +98 -0
  103. package/src/components/tab/TabGroup.vue +90 -0
  104. package/src/components/tab/examples/basic.vue +19 -0
  105. package/src/components/tab/examples/index.stories.ts +25 -0
  106. package/src/components/tab/examples/index.ts +2 -0
  107. package/src/components/tab/examples/vertical.vue +19 -0
  108. package/src/components/table/Table.css +45 -0
  109. package/src/components/table/Table.vue +108 -0
  110. package/src/components/table/TableBody.vue +13 -0
  111. package/src/components/table/TableCell.vue +13 -0
  112. package/src/components/table/TableHead.vue +22 -0
  113. package/src/components/table/TableHeadRow.vue +15 -0
  114. package/src/components/table/TableRow.vue +13 -0
  115. package/src/components/table/examples/basic.vue +46 -0
  116. package/src/components/table/examples/index.stories.ts +19 -0
  117. package/src/components/table/examples/index.ts +1 -0
  118. package/src/components/table/types/index.ts +5 -0
  119. package/src/components/tooltip/Tooltip.css +49 -0
  120. package/src/components/tooltip/Tooltip.vue +85 -0
  121. package/src/components/tooltip/examples/basic.vue +8 -0
  122. package/src/components/tooltip/examples/index.stories.ts +21 -0
  123. package/src/components/tooltip/examples/index.ts +1 -0
  124. package/src/components/virtualscroll/VirtualScroll.css +13 -0
  125. package/src/components/virtualscroll/VirtualScroll.vue +61 -0
  126. package/src/components/virtualscroll/examples/basic.vue +37 -0
  127. package/src/components/virtualscroll/examples/index.stories.ts +31 -0
  128. package/src/components/virtualscroll/examples/index.ts +1 -0
  129. package/src/composables/element.ts +13 -0
  130. package/src/composables/useCachedUid.ts +48 -0
  131. package/src/composables/useEventListener.ts +14 -0
  132. package/src/composables/useInput.ts +134 -0
  133. package/src/composables/useIsServer.ts +7 -0
  134. package/src/composables/useMount.ts +43 -0
  135. package/src/composables/usePopper.ts +194 -0
  136. package/src/create.ts +34 -0
  137. package/src/css/components.css +14 -0
  138. package/src/css/index.css +4 -0
  139. package/src/css/normalize.css +379 -0
  140. package/src/css/transitions.css +40 -0
  141. package/src/css/variables.css +80 -0
  142. package/src/exports/nuxt.js +33 -0
  143. package/src/exports/nuxt.plugin.js +8 -0
  144. package/src/index.ts +5 -0
  145. package/src/install.ts +8 -0
  146. package/src/shims-vue.d.ts +6 -0
  147. package/src/types/props.ts +3 -0
@@ -0,0 +1,118 @@
1
+ <template>
2
+ <li ref="wrapper" :class="computedWrapperClasses" role="menuitem" tabindex="0" @click="handleSelect">
3
+ <div v-if="hasIconLeft" class="m-dropdown__icon-left">
4
+ <slot name="icon-left" />
5
+ </div>
6
+ <div class="m-dropdown__text">
7
+ <slot />
8
+ </div>
9
+ <!-- <div v-if="hotkey" class="m-dropdown__hotkeys">
10
+ <template v-for="key in hotkey.split('+')">
11
+ <kbd>{{ key }}</kbd>
12
+ </template>
13
+ </div> -->
14
+ <div v-if="hasIconRight" class="m-dropdown__icon-right">
15
+ <slot name="icon-right" />
16
+ </div>
17
+ </li>
18
+ </template>
19
+
20
+ <script lang="ts">
21
+ import { defineComponent, inject, ref, type PropType, computed, toRef, onMounted } from 'vue';
22
+ import { useMagicKeys, whenever } from '@vueuse/core';
23
+ import { useLabel } from './hooks';
24
+
25
+ export default defineComponent({
26
+ name: "DropdownItem",
27
+ props: {
28
+ label: {
29
+ type: [String, Number],
30
+ default: null
31
+ },
32
+ disabled: {
33
+ type: Boolean,
34
+ default: false
35
+ },
36
+ reference: {
37
+ type: Boolean,
38
+ default: false
39
+ },
40
+ onSelect: {
41
+ type: Function as PropType<(label: string | number) => void>,
42
+ default: () => { }
43
+ },
44
+ hotkey: {
45
+ type: String,
46
+ default: null
47
+ }
48
+ },
49
+ emits: [],
50
+ setup(props, { slots }) {
51
+ const parentSelect = inject('dropdown-select', null);
52
+ const state = inject("dropdown", null);
53
+ // const keys = useMagicKeys({
54
+ // passive: false,
55
+ // onEventFired: (event) => {
56
+
57
+ // // only fire when the dropdown is open
58
+ // if (state?.isOpen.value) {
59
+ // event.preventDefault();
60
+ // }
61
+ // }
62
+ // });
63
+
64
+ const hasIconLeft = computed(() => !!(slots['icon-left']));
65
+ const hasIconRight = computed(() => !!(slots['icon-right']));
66
+
67
+ const wrapper = ref(null);
68
+ const label = toRef(props, 'label')
69
+ const isReference = ref(props.reference)
70
+ const currentLabel = useLabel(label, wrapper)
71
+ function handleSelect() {
72
+ if (props.disabled || isReference.value) {
73
+ return;
74
+ }
75
+
76
+ if (typeof parentSelect === 'function') {
77
+ // @ts-ignore
78
+ parentSelect([currentLabel.value!]);
79
+ }
80
+
81
+ props.onSelect(currentLabel.value!);
82
+ }
83
+
84
+ // const isOpen = computed(() => {
85
+ // return state?.isOpen.value;
86
+ // });
87
+
88
+ const computedWrapperClasses = computed(() => {
89
+ return {
90
+ 'm-dropdown-item': true,
91
+ 'm-dropdown-item--disabled': props.disabled,
92
+ 'm-dropdown-item--reference': props.reference
93
+ }
94
+ });
95
+
96
+ // onMounted(() => {
97
+ // if (props.hotkey) {
98
+ // const combination = keys[props.hotkey];
99
+
100
+ // whenever(combination, (v) => {
101
+ // if (v && isOpen.value) {
102
+ // handleSelect();
103
+ // }
104
+ // })
105
+ // }
106
+ // })
107
+
108
+
109
+ return {
110
+ wrapper,
111
+ hasIconLeft,
112
+ hasIconRight,
113
+ handleSelect,
114
+ computedWrapperClasses
115
+ }
116
+ }
117
+ })
118
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <ul>
3
+ <slot />
4
+ </ul>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { defineComponent } from 'vue';
9
+
10
+ export default defineComponent({
11
+ name: "DropdownList",
12
+ setup() {
13
+
14
+ // computed classes
15
+ return {
16
+
17
+ }
18
+ }
19
+ })
20
+ </script>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <slot />
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { defineComponent, inject, provide } from 'vue';
7
+
8
+ export default defineComponent({
9
+ name: 'DropdownWrapper',
10
+ setup() {
11
+ const state = inject("dropdown", null);
12
+
13
+ // @ts-ignore
14
+ provide('dropdown-select', state?.handleSelect);
15
+ }
16
+ })
17
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <MDropdown>
3
+ <MButton>
4
+ Menu
5
+ </MButton>
6
+
7
+ <template #menu>
8
+ <MDropdownList>
9
+ <MDropdownItem hotkey="Ctrl+L" @click="handleClick">
10
+ Item One
11
+ </MDropdownItem>
12
+ <MDropdownItem>
13
+ Item Two
14
+ </MDropdownItem>
15
+
16
+ <MDropdown>
17
+ <MDropdownItem>
18
+ <template #icon-right>
19
+ <svg style="width: 16px; height: 16px;" xmlns="http://www.w3.org/2000/svg"
20
+ viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
21
+ <path fill-rule="evenodd"
22
+ 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"
23
+ clip-rule="evenodd" />
24
+ </svg>
25
+
26
+ </template>
27
+ Item Three (Parent)
28
+ </MDropdownItem>
29
+
30
+ <template #menu>
31
+ <MDropdownList>
32
+ <MDropdownItem @click="handleClick">
33
+ Child One
34
+ </MDropdownItem>
35
+ <MDropdown>
36
+ <MDropdownItem>
37
+ <template #icon-right>
38
+ <svg style="width: 16px; height: 16px;" xmlns="http://www.w3.org/2000/svg"
39
+ viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
40
+ <path fill-rule="evenodd"
41
+ 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"
42
+ clip-rule="evenodd" />
43
+ </svg>
44
+
45
+ </template>
46
+ Item Three (Parent)
47
+ </MDropdownItem>
48
+
49
+ <template #menu>
50
+ <MDropdownList>
51
+ <MDropdownItem @click="handleClick">
52
+ Child One
53
+ </MDropdownItem>
54
+ <MDropdownItem>
55
+ Child Two
56
+ </MDropdownItem>
57
+ </MDropdownList>
58
+ </template>
59
+ </MDropdown>
60
+ </MDropdownList>
61
+ </template>
62
+ </MDropdown>
63
+ </MDropdownList>
64
+ </template>
65
+ </MDropdown>
66
+ </template>
67
+
68
+ <script lang="ts" setup>
69
+
70
+ const handleClick = () => {
71
+ alert('hi');
72
+ }
73
+ </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
+ <MDropdown :virtual="position" :open="showing">
8
+ <template #menu>
9
+ <MDropdownList>
10
+ <MDropdownItem>
11
+ Item One
12
+ </MDropdownItem>
13
+ <MDropdownItem>
14
+ Item Two
15
+ </MDropdownItem>
16
+
17
+ <MDropdown>
18
+ <MDropdownItem>
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
+ </MDropdownItem>
30
+
31
+ <template #menu>
32
+ <MDropdownList>
33
+ <MDropdownItem @click="handleClick">
34
+ Child One
35
+ </MDropdownItem>
36
+ <MDropdownItem>
37
+ Child Two
38
+ </MDropdownItem>
39
+ </MDropdownList>
40
+ </template>
41
+ </MDropdown>
42
+ </MDropdownList>
43
+ </template>
44
+ </MDropdown>
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,23 @@
1
+ import MDropdown from '../Dropdown.vue';
2
+ import MDropdownList from '../DropdownList.vue';
3
+ import MDropdownItem from '../DropdownItem.vue';
4
+ import MButton from '../../button/Button.vue';
5
+
6
+ import {
7
+ MDropdownBasic,
8
+ MDropdownContext
9
+ } from './index';
10
+ import { createStory } from '@/__storybook__';
11
+
12
+ export default {
13
+ component: MDropdown,
14
+ subcomponents: {
15
+ MDropdownList,
16
+ MDropdownItem,
17
+ MButton
18
+ },
19
+ title: 'Components/Dropdown'
20
+ }
21
+
22
+ export const Basic = createStory(MDropdownBasic);
23
+ export const Context = createStory(MDropdownContext);
@@ -0,0 +1,2 @@
1
+ export { default as MDropdownBasic } from './basic.vue';
2
+ export { default as MDropdownContext } from './context.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,141 @@
1
+ <template>
2
+ <form :styles="computedStyles" :class="[
3
+ computedClasses
4
+ ]" @submit.prevent="submit">
5
+ <slot />
6
+ </form>
7
+ </template>
8
+
9
+ <script lang="ts">
10
+ import { defineComponent, provide, reactive, computed, onMounted, watch, nextTick, ref } from 'vue';
11
+ import type { PropType } from 'vue';
12
+
13
+ const injectKey = "m-form";
14
+
15
+ export type FormError = {
16
+ field: string;
17
+ message: string;
18
+ };
19
+
20
+ export type Form = {
21
+ name: string;
22
+ focus: () => void;
23
+ validate: () => boolean;
24
+ setError: (error: string) => void;
25
+ };
26
+
27
+ export default defineComponent({
28
+ name: "MForm",
29
+ props: {
30
+ disabled: {
31
+ type: Boolean,
32
+ default: false,
33
+ },
34
+ loading: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+ errors: {
39
+ type: [Array, Object] as PropType<[FormError[], FormError]>,
40
+ default: () => ([]),
41
+ },
42
+ autoValidate: {
43
+ type: Boolean,
44
+ default: true,
45
+ },
46
+ autoFocus: {
47
+ type: Boolean,
48
+ default: false,
49
+ },
50
+ },
51
+ emits: [
52
+ "submit"
53
+ ],
54
+ setup(props, { emit }) {
55
+ const inputs: Form[] = [];
56
+
57
+ provide(injectKey, {
58
+ add: (name: string, focus: () => void, validate: () => boolean, setError: (error: string) => void) => {
59
+ const exists = inputs.find((input) => input.name === name);
60
+
61
+ if (exists) {
62
+ exists.focus = focus;
63
+ exists.validate = validate;
64
+ exists.setError = setError;
65
+ } else {
66
+ inputs.push({
67
+ name,
68
+ focus,
69
+ validate,
70
+ setError,
71
+ });
72
+ }
73
+ },
74
+ remove: (name: string) => {
75
+ const index = inputs.findIndex((input) => input.name === name);
76
+ inputs.splice(index, 1);
77
+ },
78
+ insideForm: true,
79
+ disabled: ref(props.disabled),
80
+ loading: ref(props.loading),
81
+ });
82
+
83
+ onMounted(() => {
84
+ if (props.autoFocus && inputs && inputs.length > 0) {
85
+ inputs[0].focus();
86
+ }
87
+ });
88
+
89
+ watch(() => props.errors, (errors) => {
90
+ if (errors) {
91
+ nextTick(() => {
92
+ if (Array.isArray(errors)) {
93
+ errors.forEach((error: any) => {
94
+ const input = inputs.find((i) => i.name === error.field)
95
+ if (input) input.setError(error.message)
96
+ })
97
+ } else {
98
+ const input = inputs.find((i) => i.name === (errors as FormError).field)
99
+ if (input) input.setError((errors as FormError).message)
100
+ }
101
+ })
102
+ }
103
+ });
104
+
105
+ const validate = () => {
106
+ let isValid = true;
107
+
108
+ inputs.forEach((input) => {
109
+ if (!input.validate()) {
110
+ isValid = false;
111
+ }
112
+ });
113
+
114
+ return isValid;
115
+ };
116
+
117
+ const submit = (e: Event) => {
118
+ e.preventDefault();
119
+ e.stopPropagation();
120
+
121
+ emit("submit", props.autoValidate ? validate() : true);
122
+ };
123
+
124
+ const computedStyles = computed(() => {
125
+ return [];
126
+ });
127
+
128
+ const computedClasses = computed(() => {
129
+ return [
130
+ "m-form"
131
+ ];
132
+ });
133
+
134
+ return {
135
+ submit,
136
+ computedStyles,
137
+ computedClasses
138
+ };
139
+ }
140
+ });
141
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <MForm @submit="onSubmit" :loading="loading">
3
+ <MInput
4
+ label="Email"
5
+ placeholder="Email Address"
6
+ name="email"
7
+ v-model="email"
8
+ :rules="[rules.isRequired, rules.isEmail]"
9
+ />
10
+
11
+ <MInput
12
+ label="Name"
13
+ placeholder="Name"
14
+ name="name"
15
+ v-model="name"
16
+ :rules="[rules.isRequired]"
17
+ />
18
+
19
+ <MSelect
20
+ label="Option"
21
+ v-model="option"
22
+ :options="options"
23
+ :option-value="'id'"
24
+ :option-label="'name'"
25
+ :rules="[rules.isRequired]"
26
+ />
27
+
28
+ <MCheckbox
29
+ label="Agree to terms"
30
+ v-model="agree"
31
+ :rules="[rules.isRequired]"
32
+ >
33
+ Something here!
34
+ </MCheckbox>
35
+
36
+
37
+ <MButton type="submit" color="blue">Submit</MButton>
38
+ </MForm>
39
+ </template>
40
+
41
+ <script lang="ts" setup>
42
+ import { MCheckbox, MSelect } from '@/components';
43
+ import { ref } from 'vue';
44
+
45
+ const rules = {
46
+ isEmail: (v: any) => /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(v) || 'E-mail must be valid',
47
+ isRequired: (v: any) => !!v || 'Field is required',
48
+ }
49
+
50
+ const options = Array.from({ length: 50 }, (_, i) => ({
51
+ id: i+1,
52
+ name: `Option ${i+1}`
53
+ }));
54
+
55
+ const loading = ref(false);
56
+ const email = ref('');
57
+ const name = ref('');
58
+ const option = ref('');
59
+ const agree = ref(false);
60
+
61
+
62
+ function onSubmit(valid: boolean) {
63
+ if (valid) {
64
+ loading.value = true;
65
+ setTimeout(() => {
66
+ console.log('submit', { email: email.value, name: name.value });
67
+ loading.value = false;
68
+ }, 3000);
69
+ } else {
70
+ console.log('invalid');
71
+ }
72
+ }
73
+ </script>
@@ -0,0 +1,23 @@
1
+ import MForm from '../Form.vue';
2
+ import MInput from '../../input/Input.vue';
3
+ import MButton from '../../button/Button.vue';
4
+ import MSelect from '../../select/Select.vue';
5
+ import MCheckbox from '../../checkbox/Checkbox.vue';
6
+
7
+ import {
8
+ MFormBasic
9
+ } from './index';
10
+ import { createStory } from '@/__storybook__';
11
+
12
+ export default {
13
+ component: MForm,
14
+ subcomponents: {
15
+ MInput,
16
+ MButton,
17
+ MSelect,
18
+ MCheckbox
19
+ },
20
+ title: 'Components/Form'
21
+ }
22
+
23
+ export const Basic = createStory(MFormBasic);
@@ -0,0 +1 @@
1
+ export { default as MFormBasic } from './basic.vue';
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <img :class="computedClasses" :style="computedStyles" :src="source" :alt="alt" />
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { defineComponent, watch, ref, computed } from 'vue';
7
+
8
+
9
+ export default defineComponent({
10
+ name: "MImage",
11
+ props: {
12
+ src: {
13
+ type: String,
14
+ required: true,
15
+ },
16
+ scrSet: {
17
+ type: String,
18
+ default: "",
19
+ },
20
+ fit: {
21
+ type: String,
22
+ default: "cover",
23
+ },
24
+ alt: {
25
+ type: String,
26
+ default: "",
27
+ },
28
+ },
29
+ emits: {
30
+ error: (e: Event) => true
31
+ },
32
+ setup(props, { emit }) {
33
+ const source = ref<string | undefined>("");
34
+
35
+ if (typeof window !== 'undefined' && Image) {
36
+ watch(() => props.src, (src) => {
37
+ if(!src) {
38
+ return;
39
+ }
40
+
41
+ const image = new Image();
42
+ image.onload = () => {
43
+ source.value = props.src;
44
+ };
45
+ image.onerror = () => {
46
+ emit('error', new Event('error'));
47
+ };
48
+ image.src = src;
49
+ },
50
+ { immediate: true })
51
+ }
52
+
53
+ const computedClasses = computed(() => {
54
+ return {
55
+ "m-image": true,
56
+ }
57
+ });
58
+
59
+ const computedStyles = computed(() => {
60
+ return {
61
+ }
62
+ });
63
+
64
+ return {
65
+ source,
66
+ computedClasses,
67
+ computedStyles,
68
+ }
69
+ }
70
+ })
71
+ </script>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <MImage
3
+ src="https://images.unsplash.com/photo-1672745256937-4e60a4534413?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=976&q=80"
4
+ />
5
+ </template>
@@ -0,0 +1,12 @@
1
+ import { createStory } from "@/__storybook__";
2
+ import MImage from "../Image.vue";
3
+ import {
4
+ MImageBasic,
5
+ } from "./index";
6
+
7
+ export default {
8
+ component: MImage,
9
+ title: 'Components/Image',
10
+ }
11
+
12
+ export const Basic = createStory(MImageBasic);