@ayu-sh-kr/dota-ui 0.0.1
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/dist/app.config.d.ts +2 -0
- package/dist/components/accordian/accordion.component.d.ts +16 -0
- package/dist/components/accordian/accordion.config.d.ts +21 -0
- package/dist/components/avatar/avatar.component.d.ts +25 -0
- package/dist/components/badge/badge.component.d.ts +14 -0
- package/dist/components/badge/badge.config.d.ts +75 -0
- package/dist/components/button/button.component.d.ts +23 -0
- package/dist/components/button/button.config.d.ts +9 -0
- package/dist/components/card/card.component.d.ts +33 -0
- package/dist/components/chip/chip.component.d.ts +11 -0
- package/dist/components/chip/chip.config.d.ts +30 -0
- package/dist/components/icon/icons.component.d.ts +15 -0
- package/dist/components/icon/icons.config.d.ts +19 -0
- package/dist/components/index.d.ts +11 -0
- package/dist/components/modal/modal.component.d.ts +16 -0
- package/dist/components/modal/modal.config.d.ts +56 -0
- package/dist/components/placeholder/placeholder.component.d.ts +6 -0
- package/dist/components/popover/popover.component.d.ts +25 -0
- package/dist/components/test/count-button.component.d.ts +9 -0
- package/dist/components/test/counter.component.d.ts +7 -0
- package/dist/components/utils/scaffold.component.d.ts +7 -0
- package/dist/dota-ui.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +3272 -0
- package/dist/main.d.ts +1 -0
- package/dist/style-BbqE44zC.css +222 -0
- package/dist/utils/debounce.d.ts +25 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/position-calculator.utils.d.ts +69 -0
- package/dist/utils/position.utils.d.ts +106 -0
- package/dist/vite.svg +1 -0
- package/index.html +13 -0
- package/package.json +34 -0
- package/postcss.config.js +6 -0
- package/public/vite.svg +1 -0
- package/src/app.config.ts +136 -0
- package/src/app.d.ts +28 -0
- package/src/components/accordian/accordion.component.ts +79 -0
- package/src/components/accordian/accordion.config.ts +27 -0
- package/src/components/accordian/accordion.css +19 -0
- package/src/components/avatar/avatar.component.ts +195 -0
- package/src/components/badge/badge.component.ts +49 -0
- package/src/components/badge/badge.config.ts +85 -0
- package/src/components/button/button.component.ts +118 -0
- package/src/components/button/button.config.ts +66 -0
- package/src/components/button/button.css +96 -0
- package/src/components/card/card.component.ts +145 -0
- package/src/components/chip/chip.component.ts +44 -0
- package/src/components/chip/chip.config.ts +33 -0
- package/src/components/icon/icons.component.ts +83 -0
- package/src/components/icon/icons.config.ts +24 -0
- package/src/components/index.ts +11 -0
- package/src/components/modal/modal.component.ts +67 -0
- package/src/components/modal/modal.config.ts +69 -0
- package/src/components/modal/modal.css +50 -0
- package/src/components/placeholder/placeholder.component.ts +25 -0
- package/src/components/placeholder/placeholder.css +3 -0
- package/src/components/popover/popover.component.ts +127 -0
- package/src/components/popover/popover.css +7 -0
- package/src/components/test/count-button.component.ts +48 -0
- package/src/components/test/counter.component.ts +37 -0
- package/src/components/utils/scaffold.component.ts +27 -0
- package/src/index.ts +2 -0
- package/src/main.ts +2 -0
- package/src/style.css +7 -0
- package/src/typescript.svg +1 -0
- package/src/utils/debounce.ts +37 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/position-calculator.utils.ts +122 -0
- package/src/utils/position.utils.ts +243 -0
- package/src/vite-env.d.ts +1 -0
- package/tailwind.config.ts +13 -0
- package/tsconfig.json +41 -0
- package/vite.config.ts +46 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
.buttonFill{
|
|
2
|
+
letter-spacing: 0.15rem;
|
|
3
|
+
transition: all 0.3s;
|
|
4
|
+
position: relative;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
z-index: 1;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.buttonFill::after {
|
|
10
|
+
content: '';
|
|
11
|
+
position: absolute;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
left: 0;
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
border-radius: inherit;
|
|
17
|
+
z-index: -2;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.buttonFill::before {
|
|
21
|
+
content: '';
|
|
22
|
+
position: absolute;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
left: 0;
|
|
25
|
+
width: 0;
|
|
26
|
+
height: 100%;
|
|
27
|
+
transition: all 0.3s;
|
|
28
|
+
border-radius: inherit;
|
|
29
|
+
z-index: -1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.buttonFill:hover {
|
|
33
|
+
color: #fff;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.buttonFill:hover::before {
|
|
37
|
+
width: 100%;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/*--- Button Fill END ---*/
|
|
41
|
+
|
|
42
|
+
.btn {
|
|
43
|
+
width: 180px;
|
|
44
|
+
height: 60px;
|
|
45
|
+
cursor: pointer;
|
|
46
|
+
background: transparent;
|
|
47
|
+
border: 1px solid #91C9FF;
|
|
48
|
+
outline: none;
|
|
49
|
+
transition: 1s ease-in-out;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
svg {
|
|
53
|
+
position: absolute;
|
|
54
|
+
left: 0;
|
|
55
|
+
top: 0;
|
|
56
|
+
fill: none;
|
|
57
|
+
stroke: #fff;
|
|
58
|
+
stroke-dasharray: 150 480;
|
|
59
|
+
stroke-dashoffset: 150;
|
|
60
|
+
transition: 1s ease-in-out;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.btn:hover {
|
|
64
|
+
transition: 1s ease-in-out;
|
|
65
|
+
background: #9b5bdc;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.btn:hover svg {
|
|
69
|
+
stroke-dashoffset: -480;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.btn span {
|
|
73
|
+
color: white;
|
|
74
|
+
font-size: 18px;
|
|
75
|
+
font-weight: 100;
|
|
76
|
+
}
|
|
77
|
+
.center {
|
|
78
|
+
width: 180px;
|
|
79
|
+
height: 60px;
|
|
80
|
+
position: absolute;
|
|
81
|
+
background: blueviolet;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
span.ripple {
|
|
85
|
+
position: absolute;
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
transform: scale(0);
|
|
88
|
+
animation: ripple 600ms linear;
|
|
89
|
+
background-color: rgba(255, 255, 255, 0.7);
|
|
90
|
+
}
|
|
91
|
+
@keyframes ripple {
|
|
92
|
+
to {
|
|
93
|
+
transform: scale(4);
|
|
94
|
+
opacity: 0;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import {BaseElement, Component, Property, String} from "@ayu-sh-kr/dota-core/dist";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'dota-card',
|
|
7
|
+
shadow: false
|
|
8
|
+
})
|
|
9
|
+
export class CardComponent extends BaseElement {
|
|
10
|
+
|
|
11
|
+
content!: string;
|
|
12
|
+
|
|
13
|
+
@Property({name: 'className', type: String})
|
|
14
|
+
className!: string
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
this.content = this.innerHTML;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
render(): string {
|
|
22
|
+
return `
|
|
23
|
+
<div class="${this.className}">
|
|
24
|
+
${this.content}
|
|
25
|
+
</div>
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Component({
|
|
32
|
+
selector: 'card-title',
|
|
33
|
+
shadow: true
|
|
34
|
+
})
|
|
35
|
+
export class CardTitleComponent extends BaseElement {
|
|
36
|
+
|
|
37
|
+
@Property({name: 'title', type: String})
|
|
38
|
+
title!: string;
|
|
39
|
+
|
|
40
|
+
@Property({name: 'className', type: String})
|
|
41
|
+
className!: string;
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
super();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
template = (title: string) => {
|
|
48
|
+
|
|
49
|
+
let content;
|
|
50
|
+
|
|
51
|
+
content = title || this.innerHTML;
|
|
52
|
+
|
|
53
|
+
return `
|
|
54
|
+
<h1 class="text-3xl font-bold ${this.className ?? ''}">
|
|
55
|
+
${content}
|
|
56
|
+
</h1>
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
render() {
|
|
61
|
+
return this.template(this.title);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Component({
|
|
66
|
+
selector: 'card-header',
|
|
67
|
+
shadow: false
|
|
68
|
+
})
|
|
69
|
+
export class CardHeaderComponent extends BaseElement {
|
|
70
|
+
|
|
71
|
+
@Property({name: '', type: String})
|
|
72
|
+
header!: string;
|
|
73
|
+
|
|
74
|
+
constructor() {
|
|
75
|
+
super();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
template = (header: string) => {
|
|
79
|
+
let content = header || this.innerHTML;
|
|
80
|
+
|
|
81
|
+
return `
|
|
82
|
+
<header class="py-4 text-4xl font-bold">${content}</header>
|
|
83
|
+
`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
render(): string {
|
|
87
|
+
return this.template(this.header)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Component({
|
|
92
|
+
selector: 'card-description',
|
|
93
|
+
shadow: false
|
|
94
|
+
})
|
|
95
|
+
export class CardDescriptionComponent extends BaseElement {
|
|
96
|
+
|
|
97
|
+
@Property({name: 'description', type: String})
|
|
98
|
+
description!: string;
|
|
99
|
+
|
|
100
|
+
@Property({name: 'className', type: String})
|
|
101
|
+
className!: string;
|
|
102
|
+
|
|
103
|
+
constructor() {
|
|
104
|
+
super();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
template = (description: string) => {
|
|
109
|
+
let content = description || this.innerHTML;
|
|
110
|
+
|
|
111
|
+
return `
|
|
112
|
+
<p class="text-lg font-medium ${this.className}">${content}</p>
|
|
113
|
+
`
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render(): string {
|
|
117
|
+
return this.template(this.description)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@Component({
|
|
122
|
+
selector: 'card-footer',
|
|
123
|
+
shadow: false
|
|
124
|
+
})
|
|
125
|
+
export class CardFooterComponent extends BaseElement {
|
|
126
|
+
|
|
127
|
+
content!: string
|
|
128
|
+
|
|
129
|
+
@Property({name: 'className', type: String})
|
|
130
|
+
className!: string;
|
|
131
|
+
|
|
132
|
+
constructor() {
|
|
133
|
+
super();
|
|
134
|
+
this.content = this.innerHTML;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
render(): string {
|
|
138
|
+
return `
|
|
139
|
+
<footer class="flex items-center gap-4 justify-center ${this.className}">
|
|
140
|
+
${this.content}
|
|
141
|
+
</footer>
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {BaseElement, Component, Property, String} from "@ayu-sh-kr/dota-core/dist";
|
|
2
|
+
import type {ChipColor, ChipPosition} from "@dota/components/chip/chip.config.ts";
|
|
3
|
+
import {ChipStyle} from "@dota/components/chip/chip.config.ts";
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'dota-chip',
|
|
7
|
+
shadow: false
|
|
8
|
+
})
|
|
9
|
+
class ChipComponent extends BaseElement{
|
|
10
|
+
|
|
11
|
+
@Property({name: 'text', type: String})
|
|
12
|
+
text!: string;
|
|
13
|
+
|
|
14
|
+
@Property({name: 'position', type: String})
|
|
15
|
+
position!: ChipPosition;
|
|
16
|
+
|
|
17
|
+
@Property({name: 'color', type: String})
|
|
18
|
+
color!: ChipColor
|
|
19
|
+
|
|
20
|
+
content!: string
|
|
21
|
+
|
|
22
|
+
constructor() {
|
|
23
|
+
super();
|
|
24
|
+
this.content = this.innerHTML;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
render(): string {
|
|
28
|
+
return `
|
|
29
|
+
<div class="${ChipStyle.base.parent}">
|
|
30
|
+
<span class="
|
|
31
|
+
${ChipStyle.base.chip} ${ChipStyle.position[this.position] ?? ChipStyle.position["top-right"]}
|
|
32
|
+
${ChipStyle.color[this.color] ?? ChipStyle.color.yellow} text-[10px]
|
|
33
|
+
${this.text ? 'size-4': 'size-2'}">
|
|
34
|
+
${this.text ?? ''}
|
|
35
|
+
</span>
|
|
36
|
+
${this.content}
|
|
37
|
+
</div>
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export {ChipComponent, ChipStyle, type ChipColor, type ChipPosition}
|
|
44
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const ChipStyle = {
|
|
2
|
+
base: {
|
|
3
|
+
parent: 'relative inline-flex items-center justify-center flex-shrink-0',
|
|
4
|
+
chip: 'absolute rounded-full text-center text-white flex item-center justify-center'
|
|
5
|
+
},
|
|
6
|
+
|
|
7
|
+
position: {
|
|
8
|
+
'top-left': 'top-0 left-0 -translate-y-1/2 -translate-x-1/2',
|
|
9
|
+
'top-right': 'top-0 right-0 -translate-y-1/2 translate-x-1/2',
|
|
10
|
+
'bottom-right': 'bottom-0 right-0 translate-y-1/2 translate-x-1/2',
|
|
11
|
+
'bottom-left': 'bottom-0 left-0 translate-y-1/2 -translate-x-1/2',
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
color: {
|
|
15
|
+
red: 'bg-red-500 dark:bg-red-400',
|
|
16
|
+
yellow: 'bg-yellow-500 dark:bg-yellow-400',
|
|
17
|
+
rose: 'bg-rose-500 dark:bg-rose-400',
|
|
18
|
+
emerald: 'bg-emerald-500 dark:bg-emerald-400',
|
|
19
|
+
green: 'bg-green-500 dark:bg-green-400',
|
|
20
|
+
blue: 'bg-blue-500 dark:bg-blue-400',
|
|
21
|
+
cyan: 'bg-cyan-500 dark:bg-cyan-400',
|
|
22
|
+
teal: 'bg-teal-500 dark:bg-teal-400',
|
|
23
|
+
gray: 'bg-gray-500 dark:bg-gray-400',
|
|
24
|
+
orange: 'bg-orange-500 dark:bg-orange-400',
|
|
25
|
+
sky: 'bg-sky-500 dark:bg-sky-400',
|
|
26
|
+
purple: 'bg-purple-500 dark:bg-purple-400',
|
|
27
|
+
violet: 'bg-violet-500 dark:bg-violet-400',
|
|
28
|
+
pink: 'bg-pink-500 dark:bg-pink-400'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ChipPosition = keyof typeof ChipStyle.position;
|
|
33
|
+
export type ChipColor = keyof typeof ChipStyle.color
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {BaseElement, Component, HTML, Property, AfterInit, String} from "@ayu-sh-kr/dota-core/dist";
|
|
2
|
+
import type {IconSize, IconVariant, IconColor} from "@dota/components/icon/icons.config.ts";
|
|
3
|
+
import {IconStyle} from "@dota/components/icon/icons.config.ts";
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'dota-icon',
|
|
7
|
+
shadow: false
|
|
8
|
+
})
|
|
9
|
+
class IconsComponent extends BaseElement {
|
|
10
|
+
|
|
11
|
+
@Property({name: 'name', type: String})
|
|
12
|
+
name!: string;
|
|
13
|
+
|
|
14
|
+
@Property({name: 'classname', type: String})
|
|
15
|
+
className!: string;
|
|
16
|
+
|
|
17
|
+
@Property({name: 'size', type: String})
|
|
18
|
+
size!: IconSize;
|
|
19
|
+
|
|
20
|
+
@Property({name: 'color', type: String})
|
|
21
|
+
color!: IconColor
|
|
22
|
+
|
|
23
|
+
@Property({name: 'variant', type: String})
|
|
24
|
+
variant!: IconVariant
|
|
25
|
+
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@AfterInit()
|
|
32
|
+
afterViewInit() {
|
|
33
|
+
this.getSvg().then();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async getSvg() {
|
|
37
|
+
let url = `https://api.iconify.design/${this.name}.svg?color=%23888888`;
|
|
38
|
+
const response = await fetch(url);
|
|
39
|
+
if(response.status === 200){
|
|
40
|
+
let text = await response.text();
|
|
41
|
+
if(text !== '404' ){
|
|
42
|
+
this.innerHTML = text;
|
|
43
|
+
|
|
44
|
+
const svg = this.querySelector('svg');
|
|
45
|
+
|
|
46
|
+
if(svg) {
|
|
47
|
+
svg.setAttribute('class', IconStyle.size[this.size] || IconStyle.size.sm)
|
|
48
|
+
IconStyle.base.split(" ")
|
|
49
|
+
.forEach(value => svg.classList.add(value))
|
|
50
|
+
|
|
51
|
+
if(this.color) {
|
|
52
|
+
const iconColor = this.variant ? IconStyle.color[this.color][this.variant] : IconStyle.color[this.color].solid
|
|
53
|
+
|
|
54
|
+
iconColor.split(" ")
|
|
55
|
+
.forEach(value => svg.classList.add(value))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const svgPath = this.querySelector('svg path');
|
|
61
|
+
|
|
62
|
+
if(svgPath) {
|
|
63
|
+
svgPath.setAttribute('fill', 'currentColor')
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.warn('Invalid Icon Name')
|
|
69
|
+
this.innerHTML = '';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
render(): string {
|
|
74
|
+
return HTML`
|
|
75
|
+
<div id="svg" class="flex items-center justify-center">
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {IconsComponent, IconStyle}
|
|
83
|
+
export type {IconVariant, IconColor, IconSize}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {UIConfig} from "@dota/app.config.ts";
|
|
2
|
+
|
|
3
|
+
export const IconStyle = {
|
|
4
|
+
shadow: 'shadow-sm',
|
|
5
|
+
base: 'overflow-hidden rounded-md focus:outline-none focus:outline-none disabled:cursor-not-allowed disabled:opacity-75 flex-shrink-0 relative font-medium',
|
|
6
|
+
color: {
|
|
7
|
+
...UIConfig.color
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
size: {
|
|
11
|
+
sm: 'p-0.5 size-4',
|
|
12
|
+
md: 'p-0.5 size-6',
|
|
13
|
+
lg: 'p-1 size-8',
|
|
14
|
+
xl: 'p-1 size-10',
|
|
15
|
+
'2xl': 'p-1.5 size-12',
|
|
16
|
+
'3xl': 'p-1.5 size-14'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type IconSize = keyof typeof IconStyle.size;
|
|
21
|
+
type IconColor = keyof typeof IconStyle.color;
|
|
22
|
+
type IconVariant = keyof ColorVariants
|
|
23
|
+
|
|
24
|
+
export type {IconSize, IconVariant, IconColor}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "@dota/components/modal/modal.component.ts";
|
|
2
|
+
export * from "@dota/components/card/card.component.ts";
|
|
3
|
+
export * from "@dota/components/badge/badge.component.ts";
|
|
4
|
+
export * from "@dota/components/utils/scaffold.component.ts";
|
|
5
|
+
export * from "@dota/components/icon/icons.component.ts";
|
|
6
|
+
export * from "@dota/components/accordian/accordion.component.ts";
|
|
7
|
+
export * from "@dota/components/chip/chip.component.ts";
|
|
8
|
+
export * from "@dota/components/avatar/avatar.component.ts";
|
|
9
|
+
export * from "@dota/components/button/button.component.ts";
|
|
10
|
+
export * from "@dota/components/popover/popover.component.ts";
|
|
11
|
+
export * from "@dota/components/placeholder/placeholder.component.ts";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import './modal.css';
|
|
2
|
+
import {BaseElement, BindEvent, Component, EventEmitter, Property, Emitter, String} from "@ayu-sh-kr/dota-core/dist";
|
|
3
|
+
import type {ModalDirection, ModalDuration, ModalRounded} from "@dota/components/modal/modal.config.ts";
|
|
4
|
+
import {ModalStyle} from "@dota/components/modal/modal.config.ts";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'dota-modal',
|
|
9
|
+
shadow: false
|
|
10
|
+
})
|
|
11
|
+
class ModalComponent extends BaseElement {
|
|
12
|
+
|
|
13
|
+
@Property({name: 'open', type: String})
|
|
14
|
+
isOpen!: boolean;
|
|
15
|
+
|
|
16
|
+
content!: string;
|
|
17
|
+
|
|
18
|
+
@Property({name: 'className', type: String})
|
|
19
|
+
className!: string
|
|
20
|
+
|
|
21
|
+
@Property({name: 'rounded', type: String})
|
|
22
|
+
rounded!: ModalRounded
|
|
23
|
+
|
|
24
|
+
@Property({name: 'duration', type: String})
|
|
25
|
+
duration!: ModalDuration
|
|
26
|
+
|
|
27
|
+
@Property({name: 'direction', type: String})
|
|
28
|
+
direction!: ModalDirection
|
|
29
|
+
|
|
30
|
+
@Emitter()
|
|
31
|
+
modalChange!: EventEmitter<boolean>
|
|
32
|
+
|
|
33
|
+
constructor() {
|
|
34
|
+
super();
|
|
35
|
+
this.content = this.innerHTML;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@BindEvent({event: 'click', id: '#close'})
|
|
39
|
+
handleClose() {
|
|
40
|
+
this.isOpen = false;
|
|
41
|
+
|
|
42
|
+
this.modalChange.emit(false, this);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
template = (open: boolean) => {
|
|
46
|
+
return `
|
|
47
|
+
<div style="
|
|
48
|
+
--start-x: ${ModalStyle.direction[`${this.direction ?? 'up'}`].startX};
|
|
49
|
+
--end-x: ${ModalStyle.direction[`${this.direction ?? 'up'}`].endX};
|
|
50
|
+
--start-y: ${ModalStyle.direction[`${this.direction ?? 'up'}`].startY};
|
|
51
|
+
--end-y: ${ModalStyle.direction[`${this.direction ?? 'up'}`].endY};
|
|
52
|
+
--animation-duration: ${ModalStyle.duration[`${this.duration ?? '1300'}`]};
|
|
53
|
+
" id="model" class="${open ? 'modelOpen' : 'modelClose'} ${ModalStyle.base} ${ModalStyle.rounded[`${this.rounded ?? 'none'}`]}">
|
|
54
|
+
<button type="button" id="close" class="absolute right-4 top-3">X</button>
|
|
55
|
+
${this.content}
|
|
56
|
+
</div>
|
|
57
|
+
`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
render() {
|
|
61
|
+
return this.template(this.isOpen);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export {ModalComponent, ModalStyle as ModalConfig}
|
|
67
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
|
|
2
|
+
export const ModalStyle = {
|
|
3
|
+
|
|
4
|
+
base: "bg-white border border-gray-200 fixed left-1/2 top-1/2 space-y-4 shadow-md p-6 min-w-[320px] z-[999]",
|
|
5
|
+
|
|
6
|
+
duration: {
|
|
7
|
+
"0" : "0s",
|
|
8
|
+
"100": "100ms",
|
|
9
|
+
"150": "150ms",
|
|
10
|
+
"200": "200ms",
|
|
11
|
+
"300": "300ms",
|
|
12
|
+
"500": "500ms",
|
|
13
|
+
"700": "700ms",
|
|
14
|
+
"1000": "1000ms",
|
|
15
|
+
"1200": "1200ms",
|
|
16
|
+
"1300": "1300ms",
|
|
17
|
+
"2000": "2000ms"
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
rounded: {
|
|
21
|
+
'none': '',
|
|
22
|
+
'sm': 'rounded-sm',
|
|
23
|
+
'md': 'rounded-md',
|
|
24
|
+
'lg': 'rounded-lg',
|
|
25
|
+
'xl': 'rounded-xl',
|
|
26
|
+
'2xl': 'rounded-2xl',
|
|
27
|
+
'3xl': 'rounded-3xl',
|
|
28
|
+
'full': 'rounded-full'
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
direction: {
|
|
32
|
+
up: {
|
|
33
|
+
startX: '-50%',
|
|
34
|
+
endX: '-50%',
|
|
35
|
+
startY: '-200%',
|
|
36
|
+
endY: '-50%'
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
down: {
|
|
40
|
+
startX: '-50%',
|
|
41
|
+
endX: '-50%',
|
|
42
|
+
startY: '200%',
|
|
43
|
+
endY: '-50%'
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
left: {
|
|
47
|
+
startX: '-180%',
|
|
48
|
+
endX: '-50%',
|
|
49
|
+
startY: '-50%',
|
|
50
|
+
endY: '-50%'
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
right: {
|
|
54
|
+
startX: '140%',
|
|
55
|
+
endX: '-50%',
|
|
56
|
+
startY: '-50%',
|
|
57
|
+
endY: '-50%'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
type ModalRounded = keyof typeof ModalStyle.rounded
|
|
64
|
+
|
|
65
|
+
type ModalDuration = keyof typeof ModalStyle.duration
|
|
66
|
+
|
|
67
|
+
type ModalDirection = keyof typeof ModalStyle.direction
|
|
68
|
+
|
|
69
|
+
export type {ModalRounded, ModalDuration, ModalDirection}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--start-opacity: 0;
|
|
3
|
+
--end-opacity: 1;
|
|
4
|
+
--start-x: -50%;
|
|
5
|
+
--start-y: -150%;
|
|
6
|
+
--end-x: -50%;
|
|
7
|
+
--end-y: -50%;
|
|
8
|
+
--animation-duration: 0.5s;
|
|
9
|
+
--animation-delay: 0.5s;
|
|
10
|
+
--animation-ease-open: ease-out;
|
|
11
|
+
--animation-ease-close: ease-in;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@keyframes modal-open {
|
|
15
|
+
0% {
|
|
16
|
+
display: none;
|
|
17
|
+
opacity: var(--start-opacity);
|
|
18
|
+
transform: translate(var(--start-x), var(--start-y));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
100% {
|
|
22
|
+
opacity: var(--end-opacity);
|
|
23
|
+
transform: translate(var(--end-x), var(--end-y));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@keyframes modal-close {
|
|
28
|
+
0% {
|
|
29
|
+
opacity: var(--end-opacity);
|
|
30
|
+
transform: translate(var(--end-x), var(--end-y));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
100% {
|
|
34
|
+
display: none;
|
|
35
|
+
opacity: var(--start-opacity);
|
|
36
|
+
transform: translate(var(--start-x), var(--start-y));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
.modelOpen {
|
|
42
|
+
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1);
|
|
43
|
+
animation: modal-open var(--animation-duration) forwards;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.modelClose {
|
|
47
|
+
animation-timing-function: cubic-bezier(0.39, 0.575, 0.565, 1);
|
|
48
|
+
animation: modal-close var(--animation-duration) forwards;
|
|
49
|
+
/* todo : have to delete element on close */
|
|
50
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "./placeholder.css"
|
|
2
|
+
import {BaseElement, Component, Property, String} from "@ayu-sh-kr/dota-core/dist";
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'dota-placeholder',
|
|
6
|
+
shadow: false
|
|
7
|
+
})
|
|
8
|
+
export class PlaceholderComponent extends BaseElement {
|
|
9
|
+
|
|
10
|
+
@Property({name: 'classname', type: String})
|
|
11
|
+
className!: string
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
render(): string {
|
|
19
|
+
return `
|
|
20
|
+
<div class="bg-slate-400 flex justify-center items-center p-1 rounded-lg overflow-hidden ${this.className}">
|
|
21
|
+
<div class="placeholder w-full h-full bg-slate-300 rounded-lg"></div>
|
|
22
|
+
</div>
|
|
23
|
+
`
|
|
24
|
+
}
|
|
25
|
+
}
|