@bobbykim/manguito-theme 0.4.0 → 0.6.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/README.md +1 -3
- package/index.ts +14 -2
- package/lib/collapse/Collapse.vue +45 -41
- package/lib/directives/index.ts +135 -4
- package/lib/directives/index.types.ts +15 -0
- package/lib/modal/Modal.vue +188 -0
- package/lib/nav/HamburgerMenu.vue +121 -0
- package/lib/sidebar/Sidebar.vue +213 -0
- package/lib/tooltip/index.ts +75 -0
- package/package.json +2 -2
- package/theme/index.ts +3 -3
- package/theme/theme.ts +1 -1
- package/theme/theme.types.ts +6 -4
- package/themeVariables.cjs +112 -1
package/README.md
CHANGED
|
@@ -19,9 +19,7 @@ npx tailwindcss init -p
|
|
|
19
19
|
tailwind.config.cjs
|
|
20
20
|
|
|
21
21
|
```cjs
|
|
22
|
-
const {
|
|
23
|
-
mclTheme,
|
|
24
|
-
} = require('./src/components/manguito-theme/themeVariables.cjs')
|
|
22
|
+
const { mclTheme } = require('@bobbykim/manguito-theme/themeVariables.cjs')
|
|
25
23
|
module.exports = {
|
|
26
24
|
content: [
|
|
27
25
|
'./src/**/*.{vue,ts,js,cjs}',
|
package/index.ts
CHANGED
|
@@ -9,7 +9,10 @@ import type { ClassType, InputType } from './theme/index.js'
|
|
|
9
9
|
import DropdownContainer from './lib/dropdown/DropdownContainer.vue'
|
|
10
10
|
import DropdownContent from './lib/dropdown/DropdownContent.vue'
|
|
11
11
|
import Collapse from './lib/collapse/Collapse.vue'
|
|
12
|
-
import
|
|
12
|
+
import Sidebar from './lib/sidebar/Sidebar.vue'
|
|
13
|
+
import Modal from './lib/modal/Modal.vue'
|
|
14
|
+
|
|
15
|
+
import HamburgerMenu from './lib/nav/HamburgerMenu.vue'
|
|
13
16
|
|
|
14
17
|
const generateClass = (type: ClassType, value: InputType): string => {
|
|
15
18
|
const mclGenerate = new GenerateMCLClass(type, value)
|
|
@@ -31,5 +34,14 @@ const generateClass = (type: ClassType, value: InputType): string => {
|
|
|
31
34
|
|
|
32
35
|
export default generateClass
|
|
33
36
|
|
|
34
|
-
export {
|
|
37
|
+
export {
|
|
38
|
+
DropdownContainer,
|
|
39
|
+
DropdownContent,
|
|
40
|
+
Collapse,
|
|
41
|
+
HamburgerMenu,
|
|
42
|
+
Sidebar,
|
|
43
|
+
Modal,
|
|
44
|
+
}
|
|
35
45
|
export * from './lib/directives'
|
|
46
|
+
export * from './theme/theme.types'
|
|
47
|
+
export * from './lib/collapse/index.types'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref,
|
|
2
|
+
import { ref, watch, Transition } from 'vue'
|
|
3
3
|
import type { CollapseEvent } from './index.types'
|
|
4
4
|
const props = withDefaults(
|
|
5
5
|
defineProps<{
|
|
@@ -15,43 +15,42 @@ const props = withDefaults(
|
|
|
15
15
|
)
|
|
16
16
|
const emit = defineEmits(['toggle'])
|
|
17
17
|
const toggle = ref<boolean>(props.visible)
|
|
18
|
-
const contentRef = ref<HTMLAreaElement>()
|
|
19
|
-
const slotHeight = ref<number>()
|
|
20
18
|
|
|
21
19
|
const handleToggleEvent = (e: Event): void => {
|
|
22
20
|
toggle.value = !toggle.value
|
|
23
21
|
emit('toggle', { ...e, visible: toggle.value } as CollapseEvent)
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @TransitionFunctions
|
|
26
|
+
* @param {HTMLElement} el - passed any since transition handlers don't accept HTMLElement (accepts Element)
|
|
27
|
+
*/
|
|
28
|
+
const onEnter = (el: any) => {
|
|
29
|
+
el.style.height = 'auto'
|
|
30
|
+
el.style.opacity = '0'
|
|
31
|
+
const endWidth = getComputedStyle(el).height
|
|
32
|
+
el.style.height = '0px'
|
|
33
|
+
el.offsetHeight // force repaint
|
|
34
|
+
el.style.height = endWidth
|
|
35
|
+
el.style.opacity = '1'
|
|
34
36
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const onAfterEnter = (el: any) => {
|
|
38
|
+
el.style.height = 'auto'
|
|
39
|
+
el.style.opacity = '1'
|
|
40
|
+
}
|
|
41
|
+
const onLeave = (el: any) => {
|
|
42
|
+
el.style.height = getComputedStyle(el).height
|
|
43
|
+
el.offsetHeight // force repaint
|
|
44
|
+
el.style.height = '0px'
|
|
45
|
+
el.style.opacity = '0'
|
|
46
|
+
}
|
|
47
|
+
|
|
40
48
|
watch(
|
|
41
49
|
() => props.visible,
|
|
42
50
|
(newValue) => {
|
|
43
51
|
toggle.value = newValue
|
|
44
52
|
}
|
|
45
53
|
)
|
|
46
|
-
// lifecycle hooks
|
|
47
|
-
onMounted(() => {
|
|
48
|
-
if (typeof window !== undefined) {
|
|
49
|
-
initObserver().observe(contentRef.value as Element)
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
onBeforeUnmount(() => {
|
|
53
|
-
initObserver().disconnect()
|
|
54
|
-
})
|
|
55
54
|
</script>
|
|
56
55
|
|
|
57
56
|
<template>
|
|
@@ -63,23 +62,28 @@ onBeforeUnmount(() => {
|
|
|
63
62
|
:accordion="accordion"
|
|
64
63
|
:visible="toggle"
|
|
65
64
|
></button>
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
<transition
|
|
66
|
+
name="collapse"
|
|
67
|
+
tag="div"
|
|
68
|
+
@enter="onEnter"
|
|
69
|
+
@after-enter="onAfterEnter"
|
|
70
|
+
@leave="onLeave"
|
|
71
|
+
class="overflow-hidden"
|
|
70
72
|
>
|
|
71
|
-
<div
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
toggle ? 'opacity-100 ease-in' : 'opacity-0 ease-out',
|
|
76
|
-
className,
|
|
77
|
-
]"
|
|
78
|
-
>
|
|
79
|
-
<slot />
|
|
73
|
+
<div v-show="toggle">
|
|
74
|
+
<div :class="[className]">
|
|
75
|
+
<slot />
|
|
76
|
+
</div>
|
|
80
77
|
</div>
|
|
81
|
-
</
|
|
78
|
+
</transition>
|
|
82
79
|
</div>
|
|
83
80
|
</template>
|
|
84
81
|
|
|
85
|
-
<style scoped
|
|
82
|
+
<style scoped lang="scss">
|
|
83
|
+
.collapse-enter-active,
|
|
84
|
+
.collapse-leave-active {
|
|
85
|
+
transition-property: height, opacity;
|
|
86
|
+
transition-duration: 500ms;
|
|
87
|
+
transition-timing-function: ease;
|
|
88
|
+
}
|
|
89
|
+
</style>
|
package/lib/directives/index.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { Directive } from 'vue'
|
|
1
|
+
import { Directive, DirectiveBinding, h, render, createVNode } from 'vue'
|
|
2
|
+
import generateClass from '../..'
|
|
3
|
+
import type { Direction } from '../..'
|
|
4
|
+
import tooltip from '../tooltip'
|
|
5
|
+
import type { TooltipElementType, TooltipValueType } from './index.types'
|
|
2
6
|
|
|
3
7
|
export const vClickOutside: Directive = {
|
|
4
8
|
mounted(el, binding) {
|
|
@@ -14,6 +18,29 @@ export const vClickOutside: Directive = {
|
|
|
14
18
|
},
|
|
15
19
|
}
|
|
16
20
|
|
|
21
|
+
export const vToggle: Directive = {
|
|
22
|
+
mounted(el, binding) {
|
|
23
|
+
el.__ClickToggleHandler = (e: Event): void => {
|
|
24
|
+
const eTarget = e.target as HTMLElement
|
|
25
|
+
let target: HTMLElement
|
|
26
|
+
if (eTarget.tagName === 'A') {
|
|
27
|
+
const targetId = eTarget.getAttribute('href')
|
|
28
|
+
const formattedTargetId =
|
|
29
|
+
targetId?.charAt(0) === '#' ? targetId.substring(1) : targetId
|
|
30
|
+
target = document.getElementById(formattedTargetId as string)!
|
|
31
|
+
} else {
|
|
32
|
+
target = document.getElementById(binding.arg as string)!
|
|
33
|
+
}
|
|
34
|
+
target.click()
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
el.addEventListener('click', el.__ClickToggleHandler)
|
|
38
|
+
},
|
|
39
|
+
unmounted(el) {
|
|
40
|
+
el.removeEventListener('click', el.__ClickToggleHandler)
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
|
|
17
44
|
export const vCollapse: Directive = {
|
|
18
45
|
mounted(el, binding) {
|
|
19
46
|
el.__HandleToggler = (event: Event): void => {
|
|
@@ -23,9 +50,7 @@ export const vCollapse: Directive = {
|
|
|
23
50
|
const targetId = eTarget.getAttribute('href')
|
|
24
51
|
const formattedTargetId =
|
|
25
52
|
targetId?.charAt(0) === '#' ? targetId.substring(1) : targetId
|
|
26
|
-
target = document.getElementById(
|
|
27
|
-
formattedTargetId as string
|
|
28
|
-
) as HTMLElement
|
|
53
|
+
target = document.getElementById(formattedTargetId as string)!
|
|
29
54
|
} else {
|
|
30
55
|
target = document.getElementById(binding.arg as string) as HTMLElement
|
|
31
56
|
}
|
|
@@ -55,3 +80,109 @@ export const vCollapse: Directive = {
|
|
|
55
80
|
el.removeEventListener('click', el.__HandleToggler)
|
|
56
81
|
},
|
|
57
82
|
}
|
|
83
|
+
|
|
84
|
+
export const vTooltip: Directive<TooltipElementType, TooltipValueType> = {
|
|
85
|
+
mounted(el, binding) {
|
|
86
|
+
el.__HandleTooltip = (
|
|
87
|
+
el: HTMLElement,
|
|
88
|
+
binding: DirectiveBinding<TooltipValueType>
|
|
89
|
+
) => {
|
|
90
|
+
// parent element class
|
|
91
|
+
el.classList.add('relative', 'group', 'overflow-visible')
|
|
92
|
+
|
|
93
|
+
// handle tooltip text
|
|
94
|
+
let tooltipText: string | null | undefined
|
|
95
|
+
if (el.hasAttribute('title')) {
|
|
96
|
+
tooltipText = el.getAttribute('title')
|
|
97
|
+
}
|
|
98
|
+
if (
|
|
99
|
+
!el.hasAttribute('title') &&
|
|
100
|
+
typeof binding.value !== 'undefined' &&
|
|
101
|
+
typeof binding.value === 'string'
|
|
102
|
+
) {
|
|
103
|
+
tooltipText = binding.value
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
!el.hasAttribute('title') &&
|
|
107
|
+
typeof binding.value !== 'undefined' &&
|
|
108
|
+
typeof binding.value !== 'string' &&
|
|
109
|
+
typeof binding.value.title === 'string'
|
|
110
|
+
) {
|
|
111
|
+
tooltipText = binding.value.title
|
|
112
|
+
}
|
|
113
|
+
// handle tooltip color
|
|
114
|
+
let tooltipColor: string | null | undefined
|
|
115
|
+
if (el.hasAttribute('color')) {
|
|
116
|
+
tooltipColor = el.getAttribute('color')
|
|
117
|
+
}
|
|
118
|
+
if (
|
|
119
|
+
!el.hasAttribute('color') &&
|
|
120
|
+
typeof binding.value !== 'undefined' &&
|
|
121
|
+
typeof binding.value !== 'string' &&
|
|
122
|
+
typeof binding.value.color === 'string'
|
|
123
|
+
) {
|
|
124
|
+
tooltipColor = binding.value.color
|
|
125
|
+
}
|
|
126
|
+
// handle tooltip text color
|
|
127
|
+
let tooltipTextColor: string | null | undefined
|
|
128
|
+
if (el.hasAttribute('text-color')) {
|
|
129
|
+
tooltipTextColor = el.getAttribute('text-color')
|
|
130
|
+
}
|
|
131
|
+
if (
|
|
132
|
+
!el.hasAttribute('text-color') &&
|
|
133
|
+
typeof binding.value !== 'undefined' &&
|
|
134
|
+
typeof binding.value !== 'string' &&
|
|
135
|
+
typeof binding.value.textColor === 'string'
|
|
136
|
+
) {
|
|
137
|
+
tooltipTextColor = binding.value.textColor
|
|
138
|
+
}
|
|
139
|
+
// handle tooltip width
|
|
140
|
+
let tooltipWidth: string | number | null | undefined
|
|
141
|
+
if (el.hasAttribute('width')) {
|
|
142
|
+
tooltipWidth = el.getAttribute('width')
|
|
143
|
+
}
|
|
144
|
+
if (
|
|
145
|
+
!el.hasAttribute('width') &&
|
|
146
|
+
typeof binding.value !== 'undefined' &&
|
|
147
|
+
typeof binding.value !== 'string' &&
|
|
148
|
+
typeof binding.value.width === ('number' || 'string')
|
|
149
|
+
) {
|
|
150
|
+
tooltipWidth = binding.value.width
|
|
151
|
+
}
|
|
152
|
+
// handle custom class names
|
|
153
|
+
let tooltipClassName: string | undefined
|
|
154
|
+
if (
|
|
155
|
+
typeof binding.value !== 'undefined' &&
|
|
156
|
+
typeof binding.value !== 'string' &&
|
|
157
|
+
typeof binding.value.className === 'string'
|
|
158
|
+
) {
|
|
159
|
+
tooltipClassName = binding.value.className
|
|
160
|
+
}
|
|
161
|
+
let tooltipDirection: Direction | undefined
|
|
162
|
+
const modifierArray: string[] = Object.keys(binding.modifiers)
|
|
163
|
+
// handle direction
|
|
164
|
+
if (modifierArray.length > 0) {
|
|
165
|
+
tooltipDirection = modifierArray[0] as Direction
|
|
166
|
+
}
|
|
167
|
+
const vnode = createVNode(tooltip, {
|
|
168
|
+
direction: tooltipDirection,
|
|
169
|
+
title: tooltipText,
|
|
170
|
+
color: tooltipColor,
|
|
171
|
+
textColor: tooltipTextColor,
|
|
172
|
+
width: tooltipWidth,
|
|
173
|
+
customClass: tooltipClassName,
|
|
174
|
+
})
|
|
175
|
+
render(vnode, el)
|
|
176
|
+
}
|
|
177
|
+
el.__UnmountTooltip = (el: Element) => {
|
|
178
|
+
render(null, el)
|
|
179
|
+
}
|
|
180
|
+
el.__HandleTooltip(el, binding)
|
|
181
|
+
},
|
|
182
|
+
updated(el, binding) {
|
|
183
|
+
el.__HandleTooltip(el, binding)
|
|
184
|
+
},
|
|
185
|
+
unmounted(el) {
|
|
186
|
+
el.__UnmountTooltip(el)
|
|
187
|
+
},
|
|
188
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ColorPalette } from '../..'
|
|
2
|
+
|
|
3
|
+
export interface TooltipElementType extends HTMLElement {
|
|
4
|
+
__HandleTooltip: Function
|
|
5
|
+
__UnmountTooltip: Function
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TooltipValueObjectType {
|
|
9
|
+
title?: string
|
|
10
|
+
color?: ColorPalette
|
|
11
|
+
textColor?: ColorPalette
|
|
12
|
+
width?: number | string
|
|
13
|
+
className?: string
|
|
14
|
+
}
|
|
15
|
+
export type TooltipValueType = TooltipValueObjectType | string
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed, watch, Transition } from 'vue'
|
|
3
|
+
import generateClass, {
|
|
4
|
+
ColorPalette,
|
|
5
|
+
vClickOutside,
|
|
6
|
+
VerticalAlignment,
|
|
7
|
+
} from '../../'
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(
|
|
10
|
+
defineProps<{
|
|
11
|
+
modalId: string
|
|
12
|
+
title?: string
|
|
13
|
+
titleColor?: ColorPalette
|
|
14
|
+
className?: string
|
|
15
|
+
visible?: boolean
|
|
16
|
+
noBackdrop?: boolean
|
|
17
|
+
noHeader?: boolean
|
|
18
|
+
color?: ColorPalette
|
|
19
|
+
backdropColor?: ColorPalette
|
|
20
|
+
placement?: VerticalAlignment
|
|
21
|
+
}>(),
|
|
22
|
+
{
|
|
23
|
+
titleColor: 'dark-3',
|
|
24
|
+
className: '',
|
|
25
|
+
visible: false,
|
|
26
|
+
noBackdrop: false,
|
|
27
|
+
noHeader: false,
|
|
28
|
+
color: 'light-1',
|
|
29
|
+
backdropColor: 'dark-4',
|
|
30
|
+
placement: 'center',
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const emit = defineEmits(['toggle', 'close'])
|
|
35
|
+
const toggle = ref<boolean>(props.visible)
|
|
36
|
+
const toggleComplete = ref<boolean>(false)
|
|
37
|
+
|
|
38
|
+
const handleToggleEvent = (e: Event): void => {
|
|
39
|
+
toggle.value = !toggle.value
|
|
40
|
+
emit('toggle', e)
|
|
41
|
+
}
|
|
42
|
+
const openModal = (): void => {
|
|
43
|
+
toggle.value = true
|
|
44
|
+
}
|
|
45
|
+
const closeModal = (e: Event): void => {
|
|
46
|
+
if (toggleComplete.value === true) {
|
|
47
|
+
toggle.value = false
|
|
48
|
+
emit('close', e)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const handlePlacementVar = computed(() => {
|
|
52
|
+
let placementVariable: number
|
|
53
|
+
if (props.placement === 'top') {
|
|
54
|
+
placementVariable = 25
|
|
55
|
+
} else if (props.placement === 'bottom') {
|
|
56
|
+
placementVariable = 75
|
|
57
|
+
} else {
|
|
58
|
+
placementVariable = 50
|
|
59
|
+
}
|
|
60
|
+
return { '--vertical-placement': placementVariable + '%' }
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @TransitionFunctions
|
|
65
|
+
* Handle toggleComplete value after completion of animation
|
|
66
|
+
*/
|
|
67
|
+
const onAfterEnter = () => {
|
|
68
|
+
toggleComplete.value = true
|
|
69
|
+
}
|
|
70
|
+
const onAfterLeave = () => {
|
|
71
|
+
toggleComplete.value = false
|
|
72
|
+
}
|
|
73
|
+
watch(
|
|
74
|
+
() => props.visible,
|
|
75
|
+
(newValue) => {
|
|
76
|
+
toggle.value = newValue
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
defineExpose({
|
|
80
|
+
toggle: handleToggleEvent,
|
|
81
|
+
close: closeModal,
|
|
82
|
+
open: openModal,
|
|
83
|
+
})
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<template>
|
|
87
|
+
<div :style="handlePlacementVar">
|
|
88
|
+
<button :id="modalId" @click="handleToggleEvent" class="hidden"></button>
|
|
89
|
+
<Transition name="fade" appear tag="div" v-if="!noBackdrop">
|
|
90
|
+
<section
|
|
91
|
+
v-if="toggle"
|
|
92
|
+
@click="closeModal"
|
|
93
|
+
class="fixed inset-0 overflow-y-auto bg-opacity-70 backdrop-blur z-[100]"
|
|
94
|
+
:class="generateClass('BGCOLOR', backdropColor)"
|
|
95
|
+
></section>
|
|
96
|
+
</Transition>
|
|
97
|
+
<Transition
|
|
98
|
+
name="slide-down"
|
|
99
|
+
tag="div"
|
|
100
|
+
@after-enter="onAfterEnter"
|
|
101
|
+
@after-leave="onAfterLeave"
|
|
102
|
+
appear
|
|
103
|
+
>
|
|
104
|
+
<div
|
|
105
|
+
v-if="toggle"
|
|
106
|
+
class="vertical-placement fixed w-full max-w-md z-[110] px-xs"
|
|
107
|
+
>
|
|
108
|
+
<div
|
|
109
|
+
v-click-outside="closeModal"
|
|
110
|
+
:class="[generateClass('BGCOLOR', color), className]"
|
|
111
|
+
class="relative overscroll-contain overflow-y-scroll max-h-[80vh] md:max-h-[60vh]"
|
|
112
|
+
>
|
|
113
|
+
<div v-if="!noHeader" class="sticky top-0">
|
|
114
|
+
<slot name="header" :close="closeModal" :status="toggle">
|
|
115
|
+
<div
|
|
116
|
+
class="flex justify-between items-center p-xs border-b-2"
|
|
117
|
+
:class="generateClass('BGCOLOR', color)"
|
|
118
|
+
>
|
|
119
|
+
<h3
|
|
120
|
+
v-if="title"
|
|
121
|
+
class="h3-md"
|
|
122
|
+
:class="generateClass('TEXTCOLOR', titleColor)"
|
|
123
|
+
>
|
|
124
|
+
{{ title }}
|
|
125
|
+
</h3>
|
|
126
|
+
<button @click="closeModal">
|
|
127
|
+
<svg
|
|
128
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
129
|
+
height="1em"
|
|
130
|
+
viewBox="0 0 384 512"
|
|
131
|
+
class="hover:opacity-75 focus:opacity-75 transition-opacity duration-300 ease-in h-sm"
|
|
132
|
+
:class="[generateClass('SVGFILL', titleColor)]"
|
|
133
|
+
>
|
|
134
|
+
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
|
135
|
+
<path
|
|
136
|
+
d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
|
|
137
|
+
/>
|
|
138
|
+
</svg>
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
</slot>
|
|
142
|
+
</div>
|
|
143
|
+
<slot name="body" :close="closeModal" :status="toggle" />
|
|
144
|
+
<div class="sticky bottom-0">
|
|
145
|
+
<slot name="footer" :close="closeModal" :status="toggle" />
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</Transition>
|
|
150
|
+
</div>
|
|
151
|
+
</template>
|
|
152
|
+
|
|
153
|
+
<style scoped lang="scss">
|
|
154
|
+
.vertical-placement {
|
|
155
|
+
top: var(--vertical-placement);
|
|
156
|
+
left: 50%;
|
|
157
|
+
transform: translateY(calc(-1 * var(--vertical-placement))) translateX(-50%);
|
|
158
|
+
}
|
|
159
|
+
.fade-enter-active,
|
|
160
|
+
.fade-leave-active {
|
|
161
|
+
transition-property: opacity;
|
|
162
|
+
transition-duration: 300ms;
|
|
163
|
+
transition-timing-function: linear;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.fade-enter-from,
|
|
167
|
+
.fade-leave-to {
|
|
168
|
+
opacity: 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.slide-down-enter-active {
|
|
172
|
+
animation: slide-down 300ms ease;
|
|
173
|
+
}
|
|
174
|
+
.slide-down-leave-active {
|
|
175
|
+
animation: slide-down reverse 300ms ease;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@keyframes slide-down {
|
|
179
|
+
0% {
|
|
180
|
+
opacity: 0;
|
|
181
|
+
transform: translateY(-100%) translateX(-50%);
|
|
182
|
+
}
|
|
183
|
+
100% {
|
|
184
|
+
opacity: 1;
|
|
185
|
+
transform: translateY(calc(-1 * var(--vertical-placement))) translateX(-50%);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import type { ColorPalette } from '@bobbykim/manguito-theme'
|
|
4
|
+
import generateClass from '../../index'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(
|
|
7
|
+
defineProps<{
|
|
8
|
+
color?: ColorPalette
|
|
9
|
+
displayBorder?: boolean
|
|
10
|
+
toggle: boolean
|
|
11
|
+
navColor: ColorPalette
|
|
12
|
+
}>(),
|
|
13
|
+
{
|
|
14
|
+
color: 'dark-2',
|
|
15
|
+
displayBorder: true,
|
|
16
|
+
}
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits(['hbg-click'])
|
|
20
|
+
|
|
21
|
+
const handleButtonToggle = (e: Event): void => {
|
|
22
|
+
emit('hbg-click', e)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const hamburgetButtonState = computed({
|
|
26
|
+
get() {
|
|
27
|
+
return props.toggle
|
|
28
|
+
},
|
|
29
|
+
set(value) {
|
|
30
|
+
return value
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const getBorderClass = (
|
|
35
|
+
bColor: ColorPalette,
|
|
36
|
+
border: boolean,
|
|
37
|
+
nColor: ColorPalette
|
|
38
|
+
): string => {
|
|
39
|
+
/**
|
|
40
|
+
* @bColor - color
|
|
41
|
+
* @border - displayBorder
|
|
42
|
+
* @nColor - navColor
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
const classArray: string[] = [
|
|
46
|
+
generateClass('RINGCOLOR', bColor),
|
|
47
|
+
generateClass('OFFSETRING', nColor),
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
if (border) {
|
|
51
|
+
classArray.push(generateClass('BORDER', bColor))
|
|
52
|
+
classArray.push('border')
|
|
53
|
+
}
|
|
54
|
+
return classArray.join(' ')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const getHamburgerButtonClass = (color: ColorPalette): string => {
|
|
58
|
+
/**
|
|
59
|
+
* @color - color
|
|
60
|
+
*/
|
|
61
|
+
const classArray: string[] = [
|
|
62
|
+
generateClass('BGCOLOR', color),
|
|
63
|
+
generateClass('BEFOREBG', color),
|
|
64
|
+
generateClass('AFTERBG', color),
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
return classArray.join(' ')
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<button
|
|
73
|
+
class="p-3xs rounded-md aspect-square outline-none focus:ring-4 ring-offset-2 transition-all duration-300 ease-linear hover:opacity-70 focus:opacity-70 hamburger__button"
|
|
74
|
+
:class="getBorderClass(color, displayBorder, navColor)"
|
|
75
|
+
@click="handleButtonToggle"
|
|
76
|
+
>
|
|
77
|
+
<input
|
|
78
|
+
type="checkbox"
|
|
79
|
+
v-model="hamburgetButtonState"
|
|
80
|
+
class="hidden hamburger__checkbox"
|
|
81
|
+
/>
|
|
82
|
+
<div
|
|
83
|
+
class="relative h-[3px] w-sm hamburger__icon before:w-sm after:w-sm before:h-[3px] after:h-[3px] transition-all duration-300 ease-linear"
|
|
84
|
+
:class="getHamburgerButtonClass(color)"
|
|
85
|
+
></div>
|
|
86
|
+
</button>
|
|
87
|
+
</template>
|
|
88
|
+
|
|
89
|
+
<style lang="scss" scoped>
|
|
90
|
+
.hamburger__icon {
|
|
91
|
+
&::before,
|
|
92
|
+
&::after {
|
|
93
|
+
position: absolute;
|
|
94
|
+
left: 0;
|
|
95
|
+
transition: all 0.3s linear;
|
|
96
|
+
}
|
|
97
|
+
&::before {
|
|
98
|
+
top: -0.5rem;
|
|
99
|
+
}
|
|
100
|
+
&::after {
|
|
101
|
+
top: 0.5rem;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
.hamburger__button {
|
|
105
|
+
&:focus .hamburger__icon,
|
|
106
|
+
&:hover .hamburger__icon {
|
|
107
|
+
scale: 1.05;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
.hamburger__checkbox:checked + .hamburger__icon {
|
|
111
|
+
background-color: transparent;
|
|
112
|
+
}
|
|
113
|
+
.hamburger__checkbox:checked + .hamburger__icon::before {
|
|
114
|
+
top: 0;
|
|
115
|
+
transform: rotate(135deg);
|
|
116
|
+
}
|
|
117
|
+
.hamburger__checkbox:checked + .hamburger__icon::after {
|
|
118
|
+
top: 0;
|
|
119
|
+
transform: rotate(-135deg);
|
|
120
|
+
}
|
|
121
|
+
</style>
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref, computed, watch, Transition } from 'vue'
|
|
3
|
+
import generateClass, { ColorPalette, vClickOutside, DirectionX } from '../../'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(
|
|
6
|
+
defineProps<{
|
|
7
|
+
sidebarId: string
|
|
8
|
+
title?: string
|
|
9
|
+
titleColor?: ColorPalette
|
|
10
|
+
className?: string
|
|
11
|
+
visible?: boolean
|
|
12
|
+
noBackdrop?: boolean
|
|
13
|
+
noHeader?: boolean
|
|
14
|
+
color?: ColorPalette
|
|
15
|
+
backdropColor?: ColorPalette
|
|
16
|
+
placement?: DirectionX
|
|
17
|
+
width?: string | number
|
|
18
|
+
}>(),
|
|
19
|
+
{
|
|
20
|
+
titleColor: 'dark-3',
|
|
21
|
+
className: '',
|
|
22
|
+
visible: false,
|
|
23
|
+
noBackdrop: false,
|
|
24
|
+
noHeader: false,
|
|
25
|
+
color: 'light-1',
|
|
26
|
+
backdropColor: 'dark-4',
|
|
27
|
+
placement: 'left',
|
|
28
|
+
width: 300,
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const emit = defineEmits(['toggle', 'close'])
|
|
33
|
+
const toggle = ref<boolean>(props.visible)
|
|
34
|
+
const toggleComplete = ref<boolean>(false)
|
|
35
|
+
const headerRef = ref<HTMLElement>()
|
|
36
|
+
const footerRef = ref<HTMLElement>()
|
|
37
|
+
|
|
38
|
+
const handleToggleEvent = (e: Event): void => {
|
|
39
|
+
toggle.value = !toggle.value
|
|
40
|
+
emit('toggle', e)
|
|
41
|
+
}
|
|
42
|
+
const openSidebar = (): void => {
|
|
43
|
+
toggle.value = true
|
|
44
|
+
}
|
|
45
|
+
const closeSidebar = (e: Event): void => {
|
|
46
|
+
if (toggleComplete.value === true) {
|
|
47
|
+
toggle.value = false
|
|
48
|
+
emit('close', e)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const handleStyleVariables = computed(() => {
|
|
52
|
+
return {
|
|
53
|
+
'--sidebar-width': `${props.width}px`,
|
|
54
|
+
'--header-height':
|
|
55
|
+
headerRef.value && toggle.value
|
|
56
|
+
? headerRef.value.scrollHeight + 'px'
|
|
57
|
+
: '0px',
|
|
58
|
+
'--footer-height':
|
|
59
|
+
footerRef.value && toggle.value
|
|
60
|
+
? footerRef.value.scrollHeight + 'px'
|
|
61
|
+
: '0px',
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
const sidebarClass = computed(() => {
|
|
65
|
+
return props.placement === 'left' ? 'sidebar-left' : 'sidebar-right'
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @TransitionFunctions
|
|
70
|
+
* Handle toggleComplete value after completion of animation
|
|
71
|
+
*/
|
|
72
|
+
const onAfterEnter = () => {
|
|
73
|
+
toggleComplete.value = true
|
|
74
|
+
}
|
|
75
|
+
const onAfterLeave = () => {
|
|
76
|
+
toggleComplete.value = false
|
|
77
|
+
}
|
|
78
|
+
watch(
|
|
79
|
+
() => props.visible,
|
|
80
|
+
(newValue) => {
|
|
81
|
+
toggle.value = newValue
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
defineExpose({
|
|
85
|
+
toggle: handleToggleEvent,
|
|
86
|
+
open: openSidebar,
|
|
87
|
+
close: closeSidebar,
|
|
88
|
+
})
|
|
89
|
+
</script>
|
|
90
|
+
|
|
91
|
+
<template>
|
|
92
|
+
<div :style="handleStyleVariables">
|
|
93
|
+
<button :id="sidebarId" @click="handleToggleEvent" class="hidden"></button>
|
|
94
|
+
<Transition name="fade" appear tag="div" v-if="!noBackdrop">
|
|
95
|
+
<section
|
|
96
|
+
v-if="toggle"
|
|
97
|
+
@click="closeSidebar"
|
|
98
|
+
class="fixed inset-0 overflow-y-auto bg-opacity-70 backdrop-blur z-[100]"
|
|
99
|
+
:class="generateClass('BGCOLOR', backdropColor)"
|
|
100
|
+
></section>
|
|
101
|
+
</Transition>
|
|
102
|
+
<Transition
|
|
103
|
+
:name="sidebarClass"
|
|
104
|
+
@after-enter="onAfterEnter"
|
|
105
|
+
@after-leave="onAfterLeave"
|
|
106
|
+
appear
|
|
107
|
+
>
|
|
108
|
+
<div
|
|
109
|
+
v-if="toggle"
|
|
110
|
+
v-click-outside="closeSidebar"
|
|
111
|
+
class="sidebar-body fixed h-full overflow-hidden inset-y-0 shadow z-[110]"
|
|
112
|
+
:class="[placement === 'left' ? 'left-0' : 'right-0']"
|
|
113
|
+
>
|
|
114
|
+
<div
|
|
115
|
+
class="relative h-full overscroll-contain overflow-y-scroll"
|
|
116
|
+
:class="[generateClass('BGCOLOR', color), className]"
|
|
117
|
+
>
|
|
118
|
+
<div v-if="!noHeader" class="sticky top-0" ref="headerRef">
|
|
119
|
+
<slot name="header" :close="closeSidebar" :status="toggle">
|
|
120
|
+
<div
|
|
121
|
+
class="flex justify-between items-center p-xs"
|
|
122
|
+
:class="generateClass('BGCOLOR', color)"
|
|
123
|
+
>
|
|
124
|
+
<h3
|
|
125
|
+
v-if="title"
|
|
126
|
+
class="h3-md"
|
|
127
|
+
:class="generateClass('TEXTCOLOR', titleColor)"
|
|
128
|
+
>
|
|
129
|
+
{{ title }}
|
|
130
|
+
</h3>
|
|
131
|
+
<button @click="closeSidebar">
|
|
132
|
+
<svg
|
|
133
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
134
|
+
height="1em"
|
|
135
|
+
viewBox="0 0 384 512"
|
|
136
|
+
class="hover:opacity-75 focus:opacity-75 transition-opacity duration-300 ease-in h-sm"
|
|
137
|
+
:class="[generateClass('SVGFILL', titleColor)]"
|
|
138
|
+
>
|
|
139
|
+
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
|
140
|
+
<path
|
|
141
|
+
d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
|
|
142
|
+
/>
|
|
143
|
+
</svg>
|
|
144
|
+
</button>
|
|
145
|
+
</div>
|
|
146
|
+
</slot>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div class="sidebar-body-height">
|
|
150
|
+
<slot name="body" :close="closeSidebar" :status="toggle" />
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="sticky bottom-0" ref="footerRef">
|
|
154
|
+
<slot name="footer" :close="closeSidebar" :status="toggle" />
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</Transition>
|
|
159
|
+
</div>
|
|
160
|
+
</template>
|
|
161
|
+
|
|
162
|
+
<style scoped lang="scss">
|
|
163
|
+
.sidebar-body {
|
|
164
|
+
width: 100%;
|
|
165
|
+
}
|
|
166
|
+
.sidebar-body-height {
|
|
167
|
+
min-height: calc(100vh - var(--header-height) - var(--footer-height));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.fade-enter-active,
|
|
171
|
+
.fade-leave-active {
|
|
172
|
+
transition-property: opacity;
|
|
173
|
+
transition-duration: 300ms;
|
|
174
|
+
transition-timing-function: linear;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.fade-enter-from,
|
|
178
|
+
.fade-leave-to {
|
|
179
|
+
opacity: 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.sidebar-left-enter-active,
|
|
183
|
+
.sidebar-left-leave-active,
|
|
184
|
+
.sidebar-right-enter-active,
|
|
185
|
+
.sidebar-right-leave-active {
|
|
186
|
+
transition-property: transform, opacity;
|
|
187
|
+
transition-duration: 300ms;
|
|
188
|
+
transition-timing-function: linear;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.sidebar-left-enter-from,
|
|
192
|
+
.sidebar-left-leave-to {
|
|
193
|
+
transform: translateX(-100%);
|
|
194
|
+
}
|
|
195
|
+
.sidebar-right-enter-from,
|
|
196
|
+
.sidebar-right-leave-to {
|
|
197
|
+
transform: translateX(100%);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@media screen and (min-width: 768px) {
|
|
201
|
+
.sidebar-body {
|
|
202
|
+
width: var(--sidebar-width);
|
|
203
|
+
}
|
|
204
|
+
.sidebar-left-enter-from,
|
|
205
|
+
.sidebar-left-leave-to {
|
|
206
|
+
transform: translateX(calc(-1 * var(--sidebar-width)));
|
|
207
|
+
}
|
|
208
|
+
.sidebar-right-enter-from,
|
|
209
|
+
.sidebar-right-leave-to {
|
|
210
|
+
transform: translateX(var(--sidebar-width));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
</style>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { PropType, defineComponent, h, computed } from 'vue'
|
|
2
|
+
import type { Direction, ColorPalette } from '../../'
|
|
3
|
+
import generateClass from '../../'
|
|
4
|
+
|
|
5
|
+
export default defineComponent({
|
|
6
|
+
props: {
|
|
7
|
+
direction: {
|
|
8
|
+
type: String as PropType<Direction>,
|
|
9
|
+
default: 'right',
|
|
10
|
+
},
|
|
11
|
+
color: {
|
|
12
|
+
type: String as PropType<ColorPalette>,
|
|
13
|
+
default: 'dark-3',
|
|
14
|
+
},
|
|
15
|
+
textColor: {
|
|
16
|
+
type: String as PropType<ColorPalette>,
|
|
17
|
+
default: 'white',
|
|
18
|
+
},
|
|
19
|
+
width: {
|
|
20
|
+
type: [Number, String],
|
|
21
|
+
default: 80,
|
|
22
|
+
},
|
|
23
|
+
customClass: {
|
|
24
|
+
type: String,
|
|
25
|
+
default: '',
|
|
26
|
+
},
|
|
27
|
+
title: {
|
|
28
|
+
type: String,
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
setup(props) {
|
|
33
|
+
const defaultClassList: string =
|
|
34
|
+
'invisible opacity-0 group-hover:visible group-hover:opacity-100 z-[100] tooltip'
|
|
35
|
+
const colorClass = computed<string>(() => {
|
|
36
|
+
/**
|
|
37
|
+
* @param {ColorPalette} color - props
|
|
38
|
+
* @param {ColorPalette} textolor - props
|
|
39
|
+
*/
|
|
40
|
+
const { color, textColor } = props
|
|
41
|
+
const classArray: string[] = [
|
|
42
|
+
generateClass('BGCOLOR', color),
|
|
43
|
+
generateClass('TEXTCOLOR', textColor),
|
|
44
|
+
]
|
|
45
|
+
return classArray.join(' ')
|
|
46
|
+
})
|
|
47
|
+
const tooltipWidth = computed(() => {
|
|
48
|
+
return { width: `${props.width}px` }
|
|
49
|
+
})
|
|
50
|
+
const tooltipDirection = computed<string>(() => {
|
|
51
|
+
switch (props.direction) {
|
|
52
|
+
case 'left':
|
|
53
|
+
return 'tooltip-left'
|
|
54
|
+
case 'top':
|
|
55
|
+
return 'tooltip-top'
|
|
56
|
+
case 'bottom':
|
|
57
|
+
return 'tooltip-bottom'
|
|
58
|
+
default:
|
|
59
|
+
return 'tooltip-right'
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
return () =>
|
|
63
|
+
h('div', {
|
|
64
|
+
class: [
|
|
65
|
+
defaultClassList,
|
|
66
|
+
props.customClass,
|
|
67
|
+
tooltipDirection.value,
|
|
68
|
+
colorClass.value,
|
|
69
|
+
],
|
|
70
|
+
role: 'tooltip',
|
|
71
|
+
innerHTML: props.title,
|
|
72
|
+
style: [tooltipWidth.value],
|
|
73
|
+
})
|
|
74
|
+
},
|
|
75
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobbykim/manguito-theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "main theme file for manguito components library. Other MCL components will need to import this file to run.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
"url": "https://github.com/bobbykim89/manguito-component-library.git"
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
|
-
"gitHead": "
|
|
20
|
+
"gitHead": "eb0833dd47a9dd0bb326bee28daf2bee4e421279"
|
|
21
21
|
}
|
package/theme/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
Range,
|
|
8
8
|
OpacityRange,
|
|
9
9
|
SpacingLevel,
|
|
10
|
-
|
|
10
|
+
Alignment,
|
|
11
11
|
} from './theme.types'
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -102,7 +102,7 @@ export type InputType =
|
|
|
102
102
|
| Range<1, 12>
|
|
103
103
|
| OpacityRange
|
|
104
104
|
| SpacingLevel
|
|
105
|
-
|
|
|
105
|
+
| Alignment
|
|
106
106
|
|
|
107
107
|
class GenerateMCLClass extends MCLTheme {
|
|
108
108
|
classType: ClassType
|
|
@@ -449,7 +449,7 @@ class GenerateMCLClass extends MCLTheme {
|
|
|
449
449
|
}
|
|
450
450
|
// handle text align classes
|
|
451
451
|
getTextAlignClass(): string {
|
|
452
|
-
return MCLTheme.textAlign[this.classValue as
|
|
452
|
+
return MCLTheme.textAlign[this.classValue as Alignment]
|
|
453
453
|
}
|
|
454
454
|
// handle border width classes
|
|
455
455
|
getBorderWidthClass(): string {
|
package/theme/theme.ts
CHANGED
package/theme/theme.types.ts
CHANGED
|
@@ -37,12 +37,15 @@ export type HeadingSize = 'sm' | 'md' | 'lg' | 'xl'
|
|
|
37
37
|
export type BodyText = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
38
38
|
// Font weight
|
|
39
39
|
export type FontWeight = 'light' | 'normal' | 'bold'
|
|
40
|
-
//
|
|
41
|
-
export type
|
|
40
|
+
// alignment
|
|
41
|
+
export type Alignment = 'left' | 'center' | 'right'
|
|
42
|
+
export type VerticalAlignment = 'top' | 'center' | 'bottom'
|
|
42
43
|
// link targets
|
|
43
44
|
export type CtaTarget = '_self' | '_blank'
|
|
44
45
|
// Highlight positions
|
|
45
|
-
export type
|
|
46
|
+
export type Direction = 'left' | 'right' | 'top' | 'bottom'
|
|
47
|
+
export type DirectionY = 'top' | 'bottom'
|
|
48
|
+
export type DirectionX = 'left' | 'right'
|
|
46
49
|
// available ranges
|
|
47
50
|
type _RangeArray<
|
|
48
51
|
T extends number,
|
|
@@ -60,7 +63,6 @@ export type Range<T extends number, R extends number> = IntRange<
|
|
|
60
63
|
|
|
61
64
|
export type ButtonSize = 'small' | 'medium' | 'large'
|
|
62
65
|
export type OpacityRange = 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100
|
|
63
|
-
export type Directions = 'left' | 'right'
|
|
64
66
|
export type ColumnWidth = 25 | 50 | 75 | 100
|
|
65
67
|
export type CrossOrigin = 'use-credentials' | 'anonymous'
|
|
66
68
|
export type InputType = 'text' | 'email' | 'password'
|
package/themeVariables.cjs
CHANGED
|
@@ -70,7 +70,7 @@ const mclTheme = plugin.withOptions(
|
|
|
70
70
|
},
|
|
71
71
|
},
|
|
72
72
|
[`.btn.btn-invert.btn-${e(key)}`]: {
|
|
73
|
-
[`@apply border-2 bg-
|
|
73
|
+
[`@apply border-2 bg-transparent border-${key} text-${key}`]: {},
|
|
74
74
|
'&:hover': {
|
|
75
75
|
[`@apply bg-${key} text-white bg-opacity-100`]: {},
|
|
76
76
|
},
|
|
@@ -141,6 +141,48 @@ const mclTheme = plugin.withOptions(
|
|
|
141
141
|
),
|
|
142
142
|
}
|
|
143
143
|
}, {})
|
|
144
|
+
const tooltipColors = Object.keys(colors).reduce((accumulator, key) => {
|
|
145
|
+
// const invalidKeys = ['current', 'transparent', 'inherit']
|
|
146
|
+
// if (invalidKeys.includes(key)) {
|
|
147
|
+
// return
|
|
148
|
+
// }
|
|
149
|
+
if (typeof colors[key] === 'string') {
|
|
150
|
+
return {
|
|
151
|
+
...accumulator,
|
|
152
|
+
[`.tooltip.tooltip-top.bg-${e(key)}`]: {
|
|
153
|
+
[`@apply after:border-t-${key}`]: {},
|
|
154
|
+
},
|
|
155
|
+
[`.tooltip.tooltip-bottom.bg-${e(key)}`]: {
|
|
156
|
+
[`@apply after:border-b-${key}`]: {},
|
|
157
|
+
},
|
|
158
|
+
[`.tooltip.tooltip-right.bg-${e(key)}`]: {
|
|
159
|
+
[`@apply after:border-r-${key}`]: {},
|
|
160
|
+
},
|
|
161
|
+
[`.tooltip.tooltip-left.bg-${e(key)}`]: {
|
|
162
|
+
[`@apply after:border-l-${key}`]: {},
|
|
163
|
+
},
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const colorShades = Object.keys(colors[key])
|
|
167
|
+
return {
|
|
168
|
+
...accumulator,
|
|
169
|
+
...colorShades.reduce((acc, level) => ({
|
|
170
|
+
...acc,
|
|
171
|
+
[`.tooltip.tooltip-top.bg-${e(key)}-${level}`]: {
|
|
172
|
+
[`@apply after:border-t-${key}-${level}`]: {},
|
|
173
|
+
},
|
|
174
|
+
[`.tooltip.tooltip-bottom.bg-${e(key)}-${level}`]: {
|
|
175
|
+
[`@apply after:border-b-${key}-${level}`]: {},
|
|
176
|
+
},
|
|
177
|
+
[`.tooltip.tooltip-right.bg-${e(key)}-${level}`]: {
|
|
178
|
+
[`@apply after:border-r-${key}-${level}`]: {},
|
|
179
|
+
},
|
|
180
|
+
[`.tooltip.tooltip-left.bg-${e(key)}-${level}`]: {
|
|
181
|
+
[`@apply after:border-l-${key}-${level}`]: {},
|
|
182
|
+
},
|
|
183
|
+
})),
|
|
184
|
+
}
|
|
185
|
+
}, {})
|
|
144
186
|
|
|
145
187
|
addBase({
|
|
146
188
|
body: {
|
|
@@ -417,11 +459,80 @@ const mclTheme = plugin.withOptions(
|
|
|
417
459
|
left: '0',
|
|
418
460
|
},
|
|
419
461
|
},
|
|
462
|
+
'.tooltip': {
|
|
463
|
+
'@apply font-normal text-sm transition-opacity duration-200 p-2xs absolute rounded text-center drop-shadow-md':
|
|
464
|
+
{},
|
|
465
|
+
},
|
|
466
|
+
'.tooltip.tooltip-top': {
|
|
467
|
+
left: '50%',
|
|
468
|
+
bottom: '110%',
|
|
469
|
+
transform: 'translateX(-50%)',
|
|
470
|
+
'&::after': {
|
|
471
|
+
content: '" "',
|
|
472
|
+
position: 'absolute',
|
|
473
|
+
top: '100%',
|
|
474
|
+
left: '50%',
|
|
475
|
+
'margin-left': '-5px',
|
|
476
|
+
'border-width': '5px',
|
|
477
|
+
'border-style': 'solid',
|
|
478
|
+
},
|
|
479
|
+
'@apply after:border-t-dark-3 after:border-x-transparent after:border-b-transparent':
|
|
480
|
+
{},
|
|
481
|
+
},
|
|
482
|
+
'.tooltip.tooltip-bottom': {
|
|
483
|
+
left: '50%',
|
|
484
|
+
top: '110%',
|
|
485
|
+
transform: 'translateX(-50%)',
|
|
486
|
+
'&::after': {
|
|
487
|
+
content: '" "',
|
|
488
|
+
position: 'absolute',
|
|
489
|
+
bottom: '100%',
|
|
490
|
+
left: '50%',
|
|
491
|
+
'margin-left': '-5px',
|
|
492
|
+
'border-width': '5px',
|
|
493
|
+
'border-style': 'solid',
|
|
494
|
+
},
|
|
495
|
+
'@apply after:border-t-transparent after:border-x-transparent after:border-b-dark-3':
|
|
496
|
+
{},
|
|
497
|
+
},
|
|
498
|
+
'.tooltip.tooltip-left': {
|
|
499
|
+
top: '50%',
|
|
500
|
+
right: '110%',
|
|
501
|
+
transform: 'translateY(-50%)',
|
|
502
|
+
'&::after': {
|
|
503
|
+
content: '" "',
|
|
504
|
+
position: 'absolute',
|
|
505
|
+
top: '50%',
|
|
506
|
+
left: '100%',
|
|
507
|
+
'margin-top': '-5px',
|
|
508
|
+
'border-width': '5px',
|
|
509
|
+
'border-style': 'solid',
|
|
510
|
+
},
|
|
511
|
+
'@apply after:border-y-transparent after:border-r-transparent after:border-l-dark-3':
|
|
512
|
+
{},
|
|
513
|
+
},
|
|
514
|
+
'.tooltip.tooltip-right': {
|
|
515
|
+
top: '50%',
|
|
516
|
+
left: '110%',
|
|
517
|
+
transform: 'translateY(-50%)',
|
|
518
|
+
'&::after': {
|
|
519
|
+
content: '" "',
|
|
520
|
+
position: 'absolute',
|
|
521
|
+
top: '50%',
|
|
522
|
+
right: '100%',
|
|
523
|
+
'margin-top': '-5px',
|
|
524
|
+
'border-width': '5px',
|
|
525
|
+
'border-style': 'solid',
|
|
526
|
+
},
|
|
527
|
+
'@apply after:border-y-transparent after:border-l-transparent after:border-r-dark-3':
|
|
528
|
+
{},
|
|
529
|
+
},
|
|
420
530
|
})
|
|
421
531
|
|
|
422
532
|
addUtilities(listColors)
|
|
423
533
|
addUtilities(btnColors)
|
|
424
534
|
addUtilities(linkColors)
|
|
535
|
+
addUtilities(tooltipColors)
|
|
425
536
|
}
|
|
426
537
|
},
|
|
427
538
|
(options = {}) => {
|