@indielayer/ui 1.0.0-alpha.0 → 1.0.0-alpha.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 (103) hide show
  1. package/README.md +26 -10
  2. package/lib/components/avatar/Avatar.vue.d.ts +2 -2
  3. package/lib/components/badge/Badge.vue.d.ts +2 -2
  4. package/lib/components/button/Button.vue.d.ts +2 -2
  5. package/lib/components/button/ButtonGroup.vue.d.ts +2 -2
  6. package/lib/components/checkbox/Checkbox.vue.d.ts +5 -4
  7. package/lib/components/drawer/Drawer.vue.d.ts +1 -1
  8. package/lib/components/icon/Icon.vue.d.ts +2 -2
  9. package/lib/components/index.d.ts +2 -2
  10. package/lib/components/input/Input.vue.d.ts +4 -3
  11. package/lib/components/menu/Menu.vue.d.ts +2 -2
  12. package/lib/components/menu/MenuItem.vue.d.ts +3 -3
  13. package/lib/components/notifications/Notifications.vue.d.ts +2 -2
  14. package/lib/components/pagination/Pagination.vue.d.ts +3 -2
  15. package/lib/components/pagination/PaginationItem.vue.d.ts +2 -2
  16. package/lib/components/radio/Radio.vue.d.ts +3 -3
  17. package/lib/components/select/Select.vue.d.ts +4 -3
  18. package/lib/components/slider/Slider.vue.d.ts +3 -3
  19. package/lib/components/spacer/Spacer.vue.d.ts +1 -1
  20. package/lib/components/spinner/Spinner.vue.d.ts +2 -2
  21. package/lib/components/{tabs → tab}/Tab.vue.d.ts +2 -2
  22. package/lib/components/{tabs/Tabs.vue.d.ts → tab/TabGroup.vue.d.ts} +0 -0
  23. package/lib/components/table/TableBody.vue.d.ts +1 -1
  24. package/lib/components/table/TableHead.vue.d.ts +1 -1
  25. package/lib/components/tag/Tag.vue.d.ts +2 -2
  26. package/lib/components/textarea/Textarea.vue.d.ts +4 -12
  27. package/lib/components/toggle/Toggle.vue.d.ts +3 -3
  28. package/lib/composables/colors.d.ts +1 -1
  29. package/lib/composables/css.d.ts +4 -4
  30. package/lib/composables/keys.d.ts +1 -0
  31. package/lib/create.d.ts +11 -0
  32. package/lib/index.cjs.js +2 -2
  33. package/lib/index.d.ts +2 -0
  34. package/lib/index.es.js +183 -107
  35. package/lib/install.d.ts +4 -6
  36. package/lib/nuxt.js +15 -16
  37. package/lib/nuxt.plugin.js +8 -0
  38. package/lib/style.css +1 -1
  39. package/lib/version.d.ts +1 -1
  40. package/package.json +19 -15
  41. package/src/components/alert/Alert.vue +164 -0
  42. package/src/components/avatar/Avatar.vue +137 -0
  43. package/src/components/badge/Badge.vue +107 -0
  44. package/src/components/breadcrumbs/Breadcrumbs.vue +60 -0
  45. package/src/components/button/Button.vue +433 -0
  46. package/src/components/button/ButtonGroup.vue +73 -0
  47. package/src/components/card/Card.vue +25 -0
  48. package/src/components/checkbox/Checkbox.vue +205 -0
  49. package/src/components/collapse/Collapse.vue +181 -0
  50. package/src/components/container/Container.vue +23 -0
  51. package/src/components/divider/Divider.vue +52 -0
  52. package/src/components/drawer/Drawer.vue +244 -0
  53. package/src/components/form/Form.vue +111 -0
  54. package/src/components/icon/Icon.vue +56 -0
  55. package/src/components/image/Image.vue +36 -0
  56. package/src/components/index.ts +45 -0
  57. package/src/components/input/Input.vue +198 -0
  58. package/src/components/link/Link.vue +110 -0
  59. package/src/components/menu/Menu.vue +118 -0
  60. package/src/components/menu/MenuItem.vue +277 -0
  61. package/src/components/modal/Modal.vue +175 -0
  62. package/src/components/notifications/Notifications.vue +318 -0
  63. package/src/components/pagination/Pagination.vue +181 -0
  64. package/src/components/pagination/PaginationItem.vue +58 -0
  65. package/src/components/popover/Popover.vue +194 -0
  66. package/src/components/popover/PopoverContainer.vue +23 -0
  67. package/src/components/progress/Progress.vue +86 -0
  68. package/src/components/radio/Radio.vue +220 -0
  69. package/src/components/scroll/Scroll.vue +143 -0
  70. package/src/components/select/Select.vue +408 -0
  71. package/src/components/skeleton/Skeleton.vue +23 -0
  72. package/src/components/slider/Slider.vue +240 -0
  73. package/src/components/spacer/Spacer.vue +11 -0
  74. package/src/components/spinner/Spinner.vue +45 -0
  75. package/src/components/tab/Tab.vue +100 -0
  76. package/src/components/tab/TabGroup.vue +151 -0
  77. package/src/components/table/Table.vue +172 -0
  78. package/src/components/table/TableBody.vue +13 -0
  79. package/src/components/table/TableCell.vue +78 -0
  80. package/src/components/table/TableHead.vue +15 -0
  81. package/src/components/table/TableHeader.vue +94 -0
  82. package/src/components/table/TableRow.vue +43 -0
  83. package/src/components/tag/Tag.vue +98 -0
  84. package/src/components/textarea/Textarea.vue +156 -0
  85. package/src/components/toggle/Toggle.vue +144 -0
  86. package/src/components/tooltip/Tooltip.vue +26 -0
  87. package/src/composables/colors-utils.ts +378 -0
  88. package/src/composables/colors.ts +82 -0
  89. package/src/composables/common.ts +20 -0
  90. package/src/composables/css.ts +45 -0
  91. package/src/composables/index.ts +7 -0
  92. package/src/composables/inputtable.ts +128 -0
  93. package/src/composables/interactive.ts +16 -0
  94. package/src/composables/keys.ts +8 -0
  95. package/src/composables/notification.ts +10 -0
  96. package/src/create.ts +36 -0
  97. package/src/exports/nuxt.js +32 -0
  98. package/src/exports/nuxt.plugin.js +8 -0
  99. package/src/exports/tailwind.preset.js +55 -0
  100. package/src/index.ts +8 -0
  101. package/src/install.ts +8 -0
  102. package/src/shims-vue.d.ts +6 -0
  103. package/src/version.ts +1 -0
@@ -0,0 +1,277 @@
1
+ <script lang="ts">
2
+ import { defineComponent, ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
3
+ import { useCSS } from '../../composables/css'
4
+ import { useColors } from '../../composables/colors'
5
+ import { useCommon } from '../../composables/common'
6
+
7
+ import XSpinner from '../../components/spinner/Spinner.vue'
8
+ import XLink from '../../components/link/Link.vue'
9
+
10
+ export default defineComponent({
11
+ name: 'XMenuItem',
12
+
13
+ components: {
14
+ XSpinner,
15
+ XLink,
16
+ },
17
+
18
+ props: {
19
+ ...useCommon.props(),
20
+ ...useColors.props('primary'),
21
+ item: {
22
+ type: Object,
23
+ default: () => {},
24
+ },
25
+ active: Boolean,
26
+ onClick: Function,
27
+ inactive: Boolean,
28
+ value: [Number,String],
29
+ to: String,
30
+ exact: Boolean,
31
+ href: String,
32
+ target: String,
33
+ label: String,
34
+ icon: String,
35
+ iconRight: String,
36
+ loading: Boolean,
37
+ rounded: Boolean,
38
+ filled: Boolean,
39
+ selected: Boolean,
40
+ disabled: Boolean,
41
+ },
42
+
43
+ emits: ['active', 'click'],
44
+
45
+ setup(props, { emit }) {
46
+ const elRef = ref()
47
+ const isActive = ref(false)
48
+
49
+ const filled = computed(() => props.filled || props.item.filled)
50
+ const cItem = computed(() => ({
51
+ ...props,
52
+ ...props.item,
53
+ }))
54
+
55
+ const htmlTag = cItem.value.to || cItem.value.href ? 'x-link' : 'div'
56
+ const isSupported = window && 'MutationObserver' in window
57
+ const classObserver = isSupported ? new MutationObserver(check) : null
58
+
59
+ onMounted(() => {
60
+ if (!elRef.value) return
61
+
62
+ check()
63
+
64
+ if (isSupported && htmlTag === 'x-link') classObserver?.observe(elRef.value.$el, {
65
+ attributes: true,
66
+ attributeFilter: ['class'],
67
+ })
68
+ })
69
+
70
+ onBeforeUnmount(() => {
71
+ if (classObserver) classObserver.disconnect()
72
+ })
73
+
74
+ function onItemClick(e: Event) {
75
+ cItem.value.onClick && cItem.value.onClick(e)
76
+ emit('click', e)
77
+ }
78
+
79
+ function check() {
80
+ if (elRef.value && elRef.value.$el && (cItem.value.href || cItem.value.to)) {
81
+ const active = elRef.value.$el.classList.contains(cItem.value.exact ? 'router-link-exact-active' : 'router-link-active')
82
+
83
+ isActive.value = active
84
+ } else {
85
+ isActive.value = cItem.value.active
86
+ }
87
+ }
88
+
89
+ watch(() => isActive.value, (val) => {
90
+ if (val) emit('active')
91
+ })
92
+
93
+ watch(() => cItem.value.active, (val) => {
94
+ isActive.value = val
95
+ })
96
+
97
+ const css = useCSS()
98
+ const colors = useColors()
99
+ const cssVariables = computed(() => {
100
+ const color = colors.getPalette(cItem.value.color || 'gray')
101
+ const gray = colors.getPalette('gray')
102
+
103
+ if (cItem.value.disabled) return css.get('text', gray[300])
104
+
105
+ if (filled.value) {
106
+ if (isActive.value) {
107
+ return css.variables({
108
+ bg: props.selected ? color[100] : color[50],
109
+ text: color[500],
110
+ hover: {
111
+ bg: props.selected ? color[100] : color[50],
112
+ text: color[500],
113
+ },
114
+ dark: {
115
+ bg: props.selected ? color[800] : color[700],
116
+ text: color[100],
117
+ hover: {
118
+ bg: props.selected ? color[800] : color[700],
119
+ text: color[100],
120
+ },
121
+ },
122
+ })
123
+ }
124
+
125
+ return css.variables({
126
+ bg: props.selected ? gray[50] : 'transparent',
127
+ text: gray[800],
128
+ hover: {
129
+ bg: gray[50],
130
+ text: gray[900],
131
+ },
132
+ dark: {
133
+ bg: props.selected ? gray[800] : 'transparent',
134
+ text: gray[200],
135
+ hover: {
136
+ bg: gray[800],
137
+ text: gray[100],
138
+ },
139
+ },
140
+ })
141
+ }
142
+
143
+ if (isActive.value) {
144
+ return css.variables({
145
+ text: color[500],
146
+ hover: {
147
+ text: color[500],
148
+ border: color[500],
149
+ },
150
+ dark: {
151
+ text: color[500],
152
+ hover: {
153
+ text: color[500],
154
+ border: color[500],
155
+ },
156
+ },
157
+ })
158
+ }
159
+
160
+ return css.variables({
161
+ text: gray[800],
162
+ hover: {
163
+ text: gray[900],
164
+ border: gray[300],
165
+ },
166
+ dark: {
167
+ text: gray[300],
168
+ hover: {
169
+ text: gray[200],
170
+ border: gray[800],
171
+ },
172
+ },
173
+ })
174
+ })
175
+
176
+ return {
177
+ elRef,
178
+ cItem,
179
+ htmlTag,
180
+ isActive,
181
+ cssVariables,
182
+ onItemClick,
183
+ }
184
+ },
185
+ })
186
+ </script>
187
+
188
+ <template>
189
+ <component
190
+ :is="htmlTag"
191
+ ref="elRef"
192
+ :to="cItem.to"
193
+ :href="cItem.href"
194
+ :target="cItem.target"
195
+ :color="cItem.color"
196
+ class="relative flex items-center whitespace-nowrap px-3 mt-1"
197
+ :style="cssVariables"
198
+ :class="[
199
+ $style['menu-item'],
200
+ [isActive ? $style['menu-item--active'] : ''],
201
+ {
202
+ 'font-medium': isActive,
203
+ 'flex items-center': $slots.prefix || $slots.suffix,
204
+ 'cursor-pointer': !cItem.disabled && !inactive,
205
+
206
+ // size
207
+ 'py-1 text-xs': cItem.size === 'xs',
208
+ 'py-2 text-sm': cItem.size === 'sm',
209
+ 'py-1.5': !cItem.size || !['xs', 'sm', 'lg', 'xl'].includes(cItem.size),
210
+ 'py-3': cItem.size === 'lg',
211
+ 'py-4 text-lg': cItem.size === 'xl',
212
+
213
+ 'rounded my-[1px]': rounded
214
+ },
215
+ ]"
216
+ :title="cItem.label"
217
+ :alt="cItem.label"
218
+ @click="onItemClick"
219
+ >
220
+ <span v-if="$slots.prefix" class="mr-2 shrink-0">
221
+ <slot name="prefix"></slot>
222
+ </span>
223
+ <x-icon v-else-if="cItem.icon" :size="cItem.size" :icon="cItem.icon" class="mr-2 shrink-0"/>
224
+
225
+ <span class="flex-1 truncate">
226
+ <slot>{{ cItem.label }}</slot>
227
+ </span>
228
+
229
+ <span class="ml-1 shrink-0">
230
+ <x-spinner v-if="cItem.loading" :size="cItem.size" />
231
+ <template v-else>
232
+ <span v-if="$slots.suffix">
233
+ <slot name="suffix"></slot>
234
+ </span>
235
+ <x-icon v-else-if="cItem.iconRight" :size="cItem.size" :icon="cItem.iconRight"/>
236
+ </template>
237
+ </span>
238
+ </component>
239
+ </template>
240
+
241
+ <style lang="postcss" module scoped>
242
+ .menu-item {
243
+ color: var(--x-text);
244
+ background-color: var(--x-bg);
245
+
246
+ &:before {
247
+ content: '';
248
+ position: absolute;
249
+ left: -1px;
250
+ height: 100%;
251
+ width: 1px;
252
+ background-color: transparent;
253
+ }
254
+
255
+ &:hover {
256
+ color: var(--x-text-hover, var(--x-text));
257
+ background-color: var(--x-bg-hover, var(--x-bg));
258
+ }
259
+
260
+ :global(.dark) & {
261
+ color: var(--x-dark-text);
262
+ background: var(--x-dark-bg);
263
+ &:hover {
264
+ color: var(--x-dark-text-hover, var(--x-dark-text));
265
+ background-color: var(--x-dark-bg-hover, var(--x-dark-bg));
266
+ }
267
+ }
268
+ }
269
+
270
+ :global(.x-menu-inner) {
271
+ .menu-item {
272
+ &:hover:before, &--active:before {
273
+ background-color: var(--x-border-hover);
274
+ }
275
+ }
276
+ }
277
+ </style>
@@ -0,0 +1,175 @@
1
+ <script lang="ts">
2
+ import { computed, defineComponent, ref, watch, type PropType } from 'vue'
3
+
4
+ import { onClickOutside, useEventListener } from '@vueuse/core'
5
+
6
+ import XScroll from '../../components/scroll/Scroll.vue'
7
+
8
+ export default defineComponent({
9
+ name: 'XModal',
10
+
11
+ components: {
12
+ XScroll,
13
+ },
14
+
15
+ props: {
16
+ size: {
17
+ type: String as PropType<'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full'>,
18
+ default: 'md',
19
+ },
20
+ modelValue: Boolean,
21
+ showClose: Boolean,
22
+ backdrop: Boolean,
23
+ },
24
+
25
+ emits: ['update:modelValue'],
26
+
27
+ expose: ['open', 'close'],
28
+
29
+ setup(props, { emit }) {
30
+ const value = ref(props.modelValue)
31
+ const visible = ref(false)
32
+ const modalRef = ref<HTMLElement | null>(null)
33
+
34
+ const classes = computed(() => {
35
+ if (props.size === 'full') return 'w-full'
36
+ else if (props.size === 'xs') return 'sm:max-w-xs w-full'
37
+ else if (props.size === 'sm') return 'sm:max-w-sm w-full'
38
+ else if (props.size === 'lg') return 'sm:max-w-xl w-full'
39
+ else if (props.size === 'xl') return 'sm:max-w-3xl w-full'
40
+
41
+ return 'sm:max-w-lg w-full'
42
+ })
43
+
44
+ let stopClickOutside: undefined | (()=> void) = undefined
45
+
46
+ watch(value, (val) => {
47
+ if (stopClickOutside) {
48
+ stopClickOutside()
49
+ stopClickOutside = undefined
50
+ }
51
+
52
+ if (val) {
53
+ setTimeout(() => {
54
+ stopClickOutside = onClickOutside(modalRef, close)
55
+ })
56
+ }
57
+ })
58
+
59
+ watch(() => props.modelValue, (val) => {
60
+ if (val) {
61
+ value.value = val
62
+
63
+ setTimeout(() => {
64
+ visible.value = val
65
+ })
66
+ } else {
67
+ visible.value = val
68
+
69
+ setTimeout(() => {
70
+ value.value = val
71
+ }, 150)
72
+ }
73
+ })
74
+
75
+ useEventListener(document, 'keydown', onKeyDown)
76
+
77
+ function onKeyDown(event: KeyboardEvent) {
78
+ if (event.key === 'Escape' && value.value) close()
79
+ }
80
+
81
+ function close() {
82
+ visible.value = false
83
+
84
+ setTimeout(() => {
85
+ value.value = false
86
+ emit('update:modelValue', false)
87
+ }, 150)
88
+ }
89
+
90
+ function open() {
91
+ value.value = true
92
+ emit('update:modelValue', true)
93
+
94
+ setTimeout(() => {
95
+ visible.value = true
96
+ })
97
+ }
98
+
99
+ const closeIcon = '<path d="M6 18L18 6M6 6l12 12" />'
100
+
101
+ return {
102
+ closeIcon,
103
+ modalRef,
104
+ classes,
105
+ visible,
106
+ value,
107
+ close,
108
+ open,
109
+ }
110
+ },
111
+ })
112
+ </script>
113
+
114
+ <template>
115
+ <Teleport to="body">
116
+ <div
117
+ v-if="value"
118
+ class="fixed z-40 inset-0 overflow-y-auto transition-all"
119
+ :class="[
120
+ visible ? 'visible' : 'invisible ease-in duration-100'
121
+ ]"
122
+ >
123
+ <div
124
+ v-if="backdrop"
125
+ class="fixed inset-0 bg-gray-500 dark:bg-black transition-opacity"
126
+ :class="[
127
+ visible ? 'ease-out duration-200 opacity-30 dark:opacity-70' : 'ease-in duration-100 opacity-0',
128
+ ]"
129
+ ></div>
130
+
131
+ <div class="flex items-end sm:items-center justify-center p-4 sm:p-6 h-screen">
132
+ <div
133
+ ref="modalRef"
134
+ class="relative flex flex-col z-10 bg-white dark:bg-gray-900 rounded-md shadow-lg transform transition-all overflow-hidden max-h-full"
135
+ :class="[
136
+ classes,
137
+ visible ?
138
+ 'ease-out duration-200 opacity-100 translate-y-0 sm:scale-100'
139
+ : 'ease-in duration-200 opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95',
140
+ ]"
141
+ role="dialog"
142
+ aria-modal="true"
143
+ aria-labelledby="modal-headline"
144
+ >
145
+ <div
146
+ v-if="showClose"
147
+ class="absolute p-1 top-4 right-4 rounded-full bg-opacity-10 hover:bg-opacity-30 cursor-pointer"
148
+ :class="[
149
+ $slots.image ? 'bg-gray-900 text-white' : 'bg-gray-500 text-gray-800 dark:text-gray-300'
150
+ ]"
151
+ @click="close"
152
+ >
153
+ <x-icon :icon="closeIcon"/>
154
+ </div>
155
+ <slot name="image"></slot>
156
+ <div v-if="$slots.header" class="text-lg font-semibold px-6 py-4 border-b">
157
+ <slot name="header"></slot>
158
+ </div>
159
+ <x-scroll
160
+ v-if="$slots.default"
161
+ :scrollbar="false"
162
+ vertical
163
+ >
164
+ <div class="px-6 py-4">
165
+ <slot></slot>
166
+ </div>
167
+ </x-scroll>
168
+ <div v-if="$slots.actions" class="bg-slate-50 dark:bg-gray-800 p-4">
169
+ <slot name="actions"></slot>
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+ </Teleport>
175
+ </template>