@luanlu/mk-motion 1.2.0 → 1.2.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/package.json +2 -4
- package/src/a11y/focus-trap.ts +64 -0
- package/src/a11y/keyboard.ts +43 -0
- package/src/components/alert/alert.css +111 -0
- package/src/components/alert/alert.ts +107 -0
- package/src/components/avatar/avatar.css +112 -0
- package/src/components/avatar/avatar.ts +175 -0
- package/src/components/breadcrumb/breadcrumb.css +31 -0
- package/src/components/breadcrumb/breadcrumb.ts +71 -0
- package/src/components/button/button.css +108 -0
- package/src/components/button/button.ts +140 -0
- package/src/components/card/card.css +52 -0
- package/src/components/card/card.ts +87 -0
- package/src/components/collapse/collapse.css +76 -0
- package/src/components/collapse/collapse.ts +168 -0
- package/src/components/dialog/dialog.css +78 -0
- package/src/components/dialog/dialog.ts +164 -0
- package/src/components/drawer/drawer.css +73 -0
- package/src/components/drawer/drawer.ts +131 -0
- package/src/components/empty/empty.css +36 -0
- package/src/components/empty/empty.ts +85 -0
- package/src/components/form/checkbox.css +56 -0
- package/src/components/form/checkbox.ts +119 -0
- package/src/components/form/radio.css +57 -0
- package/src/components/form/radio.ts +153 -0
- package/src/components/form/select.css +91 -0
- package/src/components/form/select.ts +174 -0
- package/src/components/form/slider.css +56 -0
- package/src/components/form/slider.ts +148 -0
- package/src/components/input/input.css +92 -0
- package/src/components/input/input.ts +162 -0
- package/src/components/layout/divider.css +32 -0
- package/src/components/layout/divider.ts +42 -0
- package/src/components/layout/row.css +64 -0
- package/src/components/layout/row.ts +57 -0
- package/src/components/layout/space.css +14 -0
- package/src/components/layout/space.ts +48 -0
- package/src/components/loading/loading.css +37 -0
- package/src/components/loading/loading.ts +46 -0
- package/src/components/menu/menu.css +121 -0
- package/src/components/menu/menu.ts +187 -0
- package/src/components/message/message.css +64 -0
- package/src/components/message/message.ts +96 -0
- package/src/components/popover/popover.css +73 -0
- package/src/components/popover/popover.ts +279 -0
- package/src/components/progress/progress.css +112 -0
- package/src/components/progress/progress.ts +171 -0
- package/src/components/steps/steps.css +127 -0
- package/src/components/steps/steps.ts +102 -0
- package/src/components/styles/components.css +28 -0
- package/src/components/styles/reset.css +24 -0
- package/src/components/styles/tokens.css +248 -0
- package/src/components/styles/variables.css +24 -0
- package/src/components/switch/switch.css +53 -0
- package/src/components/switch/switch.ts +103 -0
- package/src/components/table/table.css +192 -0
- package/src/components/table/table.ts +370 -0
- package/src/components/tabs/tabs.css +138 -0
- package/src/components/tabs/tabs.ts +211 -0
- package/src/components/tag/tag.css +123 -0
- package/src/components/tag/tag.ts +112 -0
- package/src/components/tooltip/tooltip.css +66 -0
- package/src/components/tooltip/tooltip.ts +185 -0
- package/src/core/animator.ts +124 -0
- package/src/core/timeline.ts +128 -0
- package/src/core/utils.ts +47 -0
- package/src/effects/glitch.ts +99 -0
- package/src/effects/particle.ts +134 -0
- package/src/effects/text-split.ts +95 -0
- package/src/effects/wave-text.ts +88 -0
- package/src/gesture/draggable.ts +130 -0
- package/src/gesture/spring.ts +152 -0
- package/src/index.ts +162 -0
- package/src/interactive/coverflow.ts +100 -0
- package/src/interactive/cursor-trail.ts +113 -0
- package/src/interactive/flip-card.ts +114 -0
- package/src/interactive/magnetic.ts +121 -0
- package/src/micro/hover-lift.ts +94 -0
- package/src/micro/ripple.ts +130 -0
- package/src/motion/component-motion.ts +177 -0
- package/src/presets/index.ts +69 -0
- package/src/scroll/scroll-trigger.ts +104 -0
- package/src/styles/animations.css +135 -0
- package/src/styles/element-plus.css +174 -0
- package/src/text/count-up.ts +108 -0
- package/src/text/typewriter.ts +109 -0
- package/src/theme/dark.css +19 -0
- package/src/theme/light.css +19 -0
- package/src/theme/theme.ts +65 -0
- package/src/transitions/blur-reveal.ts +92 -0
- package/src/transitions/collapse.ts +112 -0
- package/src/transitions/lazy-image.ts +87 -0
- package/src/transitions/list.ts +75 -0
- package/src/transitions/loading.ts +95 -0
- package/src/transitions/parallax.ts +60 -0
- package/src/transitions/shimmer.ts +105 -0
- package/src/transitions/toast.ts +151 -0
- package/src/types.d.ts +4 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import './steps.css'
|
|
2
|
+
|
|
3
|
+
export interface StepItem {
|
|
4
|
+
title: string
|
|
5
|
+
description?: string
|
|
6
|
+
icon?: string
|
|
7
|
+
status?: 'wait' | 'process' | 'finish' | 'error'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface StepsOptions {
|
|
11
|
+
direction?: 'horizontal' | 'vertical'
|
|
12
|
+
current?: number
|
|
13
|
+
items: StepItem[]
|
|
14
|
+
size?: 'small' | 'default'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class MkSteps {
|
|
18
|
+
el: HTMLElement
|
|
19
|
+
private options: StepsOptions
|
|
20
|
+
|
|
21
|
+
constructor(container: HTMLElement | string, options: StepsOptions) {
|
|
22
|
+
const parent = typeof container === 'string' ? document.querySelector(container)! : container
|
|
23
|
+
this.options = { direction: 'horizontal', current: 0, size: 'default', ...options }
|
|
24
|
+
|
|
25
|
+
this.el = document.createElement('div')
|
|
26
|
+
this.el.className = `mk-steps mk-steps--${this.options.direction}`
|
|
27
|
+
if (this.options.size === 'small') this.el.classList.add('mk-steps--small')
|
|
28
|
+
|
|
29
|
+
this.render()
|
|
30
|
+
parent.appendChild(this.el)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private render(): void {
|
|
34
|
+
this.el.innerHTML = ''
|
|
35
|
+
const { items, current = 0, direction } = this.options
|
|
36
|
+
|
|
37
|
+
items.forEach((item, index) => {
|
|
38
|
+
const step = document.createElement('div')
|
|
39
|
+
step.className = 'mk-step'
|
|
40
|
+
|
|
41
|
+
const status = item.status ?? (index < current ? 'finish' : index === current ? 'process' : 'wait')
|
|
42
|
+
step.classList.add(`is-${status}`)
|
|
43
|
+
if (index === items.length - 1) step.classList.add('is-last')
|
|
44
|
+
|
|
45
|
+
const head = document.createElement('div')
|
|
46
|
+
head.className = 'mk-step__head'
|
|
47
|
+
|
|
48
|
+
const line = document.createElement('div')
|
|
49
|
+
line.className = 'mk-step__line'
|
|
50
|
+
if (direction === 'vertical') {
|
|
51
|
+
line.style.width = '1px'
|
|
52
|
+
line.style.height = '100%'
|
|
53
|
+
line.style.left = '15px'
|
|
54
|
+
line.style.top = '30px'
|
|
55
|
+
}
|
|
56
|
+
head.appendChild(line)
|
|
57
|
+
|
|
58
|
+
const icon = document.createElement('div')
|
|
59
|
+
icon.className = 'mk-step__icon'
|
|
60
|
+
if (status === 'finish') {
|
|
61
|
+
icon.textContent = item.icon || '✓'
|
|
62
|
+
} else if (status === 'error') {
|
|
63
|
+
icon.textContent = item.icon || '✕'
|
|
64
|
+
} else {
|
|
65
|
+
icon.textContent = item.icon || String(index + 1)
|
|
66
|
+
}
|
|
67
|
+
head.appendChild(icon)
|
|
68
|
+
|
|
69
|
+
const main = document.createElement('div')
|
|
70
|
+
main.className = 'mk-step__main'
|
|
71
|
+
|
|
72
|
+
const title = document.createElement('div')
|
|
73
|
+
title.className = 'mk-step__title'
|
|
74
|
+
title.textContent = item.title
|
|
75
|
+
main.appendChild(title)
|
|
76
|
+
|
|
77
|
+
if (item.description) {
|
|
78
|
+
const desc = document.createElement('div')
|
|
79
|
+
desc.className = 'mk-step__description'
|
|
80
|
+
desc.textContent = item.description
|
|
81
|
+
main.appendChild(desc)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
step.appendChild(head)
|
|
85
|
+
step.appendChild(main)
|
|
86
|
+
this.el.appendChild(step)
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
setCurrent(current: number): void {
|
|
91
|
+
this.options.current = current
|
|
92
|
+
this.render()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
destroy(): void {
|
|
96
|
+
this.el.remove()
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createSteps(container: HTMLElement | string, options: StepsOptions): MkSteps {
|
|
101
|
+
return new MkSteps(container, options)
|
|
102
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* MotionKit UI Components - Unified Styles */
|
|
2
|
+
@import '../button/button.css';
|
|
3
|
+
@import '../input/input.css';
|
|
4
|
+
@import '../card/card.css';
|
|
5
|
+
@import '../dialog/dialog.css';
|
|
6
|
+
@import '../drawer/drawer.css';
|
|
7
|
+
@import '../message/message.css';
|
|
8
|
+
@import '../switch/switch.css';
|
|
9
|
+
@import '../loading/loading.css';
|
|
10
|
+
@import '../tag/tag.css';
|
|
11
|
+
@import '../tabs/tabs.css';
|
|
12
|
+
@import '../table/table.css';
|
|
13
|
+
@import '../avatar/avatar.css';
|
|
14
|
+
@import '../alert/alert.css';
|
|
15
|
+
@import '../progress/progress.css';
|
|
16
|
+
@import '../collapse/collapse.css';
|
|
17
|
+
@import '../empty/empty.css';
|
|
18
|
+
@import '../popover/popover.css';
|
|
19
|
+
@import '../menu/menu.css';
|
|
20
|
+
@import '../breadcrumb/breadcrumb.css';
|
|
21
|
+
@import '../steps/steps.css';
|
|
22
|
+
@import '../layout/row.css';
|
|
23
|
+
@import '../layout/space.css';
|
|
24
|
+
@import '../layout/divider.css';
|
|
25
|
+
@import '../form/select.css';
|
|
26
|
+
@import '../form/checkbox.css';
|
|
27
|
+
@import '../form/radio.css';
|
|
28
|
+
@import '../form/slider.css';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.mk-ui *, .mk-ui *::before, .mk-ui *::after { box-sizing: border-box; }
|
|
2
|
+
.mk-ui {
|
|
3
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
4
|
+
font-size: 14px;
|
|
5
|
+
color: var(--mk-text-muted);
|
|
6
|
+
line-height: 1.6;
|
|
7
|
+
-webkit-font-smoothing: antialiased;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* Modern glass overlay */
|
|
11
|
+
.mk-glass {
|
|
12
|
+
background: rgba(19, 19, 30, 0.75);
|
|
13
|
+
backdrop-filter: blur(20px) saturate(1.5);
|
|
14
|
+
-webkit-backdrop-filter: blur(20px) saturate(1.5);
|
|
15
|
+
}
|
|
16
|
+
[data-mk-theme="light"] .mk-glass {
|
|
17
|
+
background: rgba(241, 245, 249, 0.75);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* Animated gradient border */
|
|
21
|
+
@keyframes mk-gradient-shift {
|
|
22
|
+
0%, 100% { background-position: 0% 50%; }
|
|
23
|
+
50% { background-position: 100% 50%; }
|
|
24
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/* ==========================================================
|
|
2
|
+
MotionKit Design Tokens v2.0
|
|
3
|
+
==========================================================
|
|
4
|
+
A comprehensive design system powering all MotionKit
|
|
5
|
+
components with consistent colors, typography, spacing,
|
|
6
|
+
shadows, borders, and motion.
|
|
7
|
+
========================================================== */
|
|
8
|
+
|
|
9
|
+
/* ----- Core Color Scale (each color: 50-950) ----- */
|
|
10
|
+
:root {
|
|
11
|
+
/* Indigo - Primary */
|
|
12
|
+
--mk-indigo-50: #eef2ff;
|
|
13
|
+
--mk-indigo-100: #e0e7ff;
|
|
14
|
+
--mk-indigo-200: #c7d2fe;
|
|
15
|
+
--mk-indigo-300: #a5b4fc;
|
|
16
|
+
--mk-indigo-400: #818cf8;
|
|
17
|
+
--mk-indigo-500: #6366f1;
|
|
18
|
+
--mk-indigo-600: #4f46e5;
|
|
19
|
+
--mk-indigo-700: #4338ca;
|
|
20
|
+
--mk-indigo-800: #3730a3;
|
|
21
|
+
--mk-indigo-900: #312e81;
|
|
22
|
+
--mk-indigo-950: #1e1b4b;
|
|
23
|
+
|
|
24
|
+
/* Green - Success */
|
|
25
|
+
--mk-green-50: #f0fdf4;
|
|
26
|
+
--mk-green-100: #dcfce7;
|
|
27
|
+
--mk-green-200: #bbf7d0;
|
|
28
|
+
--mk-green-300: #86efac;
|
|
29
|
+
--mk-green-400: #4ade80;
|
|
30
|
+
--mk-green-500: #22c55e;
|
|
31
|
+
--mk-green-600: #16a34a;
|
|
32
|
+
--mk-green-700: #15803d;
|
|
33
|
+
--mk-green-800: #166534;
|
|
34
|
+
--mk-green-900: #14532d;
|
|
35
|
+
--mk-green-950: #052e16;
|
|
36
|
+
|
|
37
|
+
/* Amber - Warning */
|
|
38
|
+
--mk-amber-50: #fffbeb;
|
|
39
|
+
--mk-amber-100: #fef3c7;
|
|
40
|
+
--mk-amber-200: #fde68a;
|
|
41
|
+
--mk-amber-300: #fcd34d;
|
|
42
|
+
--mk-amber-400: #fbbf24;
|
|
43
|
+
--mk-amber-500: #f59e0b;
|
|
44
|
+
--mk-amber-600: #d97706;
|
|
45
|
+
--mk-amber-700: #b45309;
|
|
46
|
+
--mk-amber-800: #92400e;
|
|
47
|
+
--mk-amber-900: #78350f;
|
|
48
|
+
--mk-amber-950: #451a03;
|
|
49
|
+
|
|
50
|
+
/* Red - Danger */
|
|
51
|
+
--mk-red-50: #fef2f2;
|
|
52
|
+
--mk-red-100: #fee2e2;
|
|
53
|
+
--mk-red-200: #fecaca;
|
|
54
|
+
--mk-red-300: #fca5a5;
|
|
55
|
+
--mk-red-400: #f87171;
|
|
56
|
+
--mk-red-500: #ef4444;
|
|
57
|
+
--mk-red-600: #dc2626;
|
|
58
|
+
--mk-red-700: #b91c1c;
|
|
59
|
+
--mk-red-800: #991b1b;
|
|
60
|
+
--mk-red-900: #7f1d1d;
|
|
61
|
+
--mk-red-950: #450a0a;
|
|
62
|
+
|
|
63
|
+
/* Slate - Neutral / Gray */
|
|
64
|
+
--mk-slate-50: #f8fafc;
|
|
65
|
+
--mk-slate-100: #f1f5f9;
|
|
66
|
+
--mk-slate-200: #e2e8f0;
|
|
67
|
+
--mk-slate-300: #cbd5e1;
|
|
68
|
+
--mk-slate-400: #94a3b8;
|
|
69
|
+
--mk-slate-500: #64748b;
|
|
70
|
+
--mk-slate-600: #475569;
|
|
71
|
+
--mk-slate-700: #334155;
|
|
72
|
+
--mk-slate-800: #1e293b;
|
|
73
|
+
--mk-slate-900: #0f172a;
|
|
74
|
+
--mk-slate-950: #020617;
|
|
75
|
+
|
|
76
|
+
/* Sky - Info */
|
|
77
|
+
--mk-sky-50: #f0f9ff;
|
|
78
|
+
--mk-sky-100: #e0f2fe;
|
|
79
|
+
--mk-sky-200: #bae6fd;
|
|
80
|
+
--mk-sky-300: #7dd3fc;
|
|
81
|
+
--mk-sky-400: #38bdf8;
|
|
82
|
+
--mk-sky-500: #0ea5e9;
|
|
83
|
+
--mk-sky-600: #0284c7;
|
|
84
|
+
--mk-sky-700: #0369a1;
|
|
85
|
+
--mk-sky-800: #075985;
|
|
86
|
+
--mk-sky-900: #0c4a6e;
|
|
87
|
+
--mk-sky-950: #082f49;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* ----- Semantic Tokens (dark-first) ----- */
|
|
91
|
+
:root {
|
|
92
|
+
/* Surfaces */
|
|
93
|
+
--mk-bg: #09090b;
|
|
94
|
+
--mk-bg-elevated: #0c0c14;
|
|
95
|
+
--mk-surface: #12121a;
|
|
96
|
+
--mk-surface-hover:#1a1a25;
|
|
97
|
+
--mk-surface-active:#22222e;
|
|
98
|
+
--mk-surface-raised:#1e1e2a;
|
|
99
|
+
|
|
100
|
+
/* Borders */
|
|
101
|
+
--mk-border: #1e1e2e;
|
|
102
|
+
--mk-border-hover: #27273a;
|
|
103
|
+
--mk-border-active: #3a3a55;
|
|
104
|
+
--mk-divider: rgba(255,255,255,0.06);
|
|
105
|
+
|
|
106
|
+
/* Primary */
|
|
107
|
+
--mk-primary: var(--mk-indigo-500);
|
|
108
|
+
--mk-primary-hover: var(--mk-indigo-400);
|
|
109
|
+
--mk-primary-active: var(--mk-indigo-600);
|
|
110
|
+
--mk-primary-soft: rgba(99,102,241,0.12);
|
|
111
|
+
--mk-primary-muted: rgba(99,102,241,0.06);
|
|
112
|
+
|
|
113
|
+
/* Semantic */
|
|
114
|
+
--mk-success: var(--mk-green-500);
|
|
115
|
+
--mk-success-soft: rgba(34,197,94,0.12);
|
|
116
|
+
--mk-warning: var(--mk-amber-500);
|
|
117
|
+
--mk-warning-soft: rgba(245,158,11,0.12);
|
|
118
|
+
--mk-danger: var(--mk-red-500);
|
|
119
|
+
--mk-danger-soft: rgba(239,68,68,0.12);
|
|
120
|
+
--mk-info: var(--mk-sky-500);
|
|
121
|
+
--mk-info-soft: rgba(14,165,233,0.12);
|
|
122
|
+
|
|
123
|
+
/* Text */
|
|
124
|
+
--mk-text: #f8fafc;
|
|
125
|
+
--mk-text-primary: #f1f5f9;
|
|
126
|
+
--mk-text-secondary: #94a3b8;
|
|
127
|
+
--mk-text-tertiary: #64748b;
|
|
128
|
+
--mk-text-disabled: #475569;
|
|
129
|
+
--mk-text-inverse: #0f172a;
|
|
130
|
+
|
|
131
|
+
/* Typography */
|
|
132
|
+
--mk-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
133
|
+
--mk-font-mono: 'SF Mono', SFMono-Regular, ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;
|
|
134
|
+
|
|
135
|
+
--mk-text-xs: 0.75rem; /* 12px */
|
|
136
|
+
--mk-text-sm: 0.8125rem; /* 13px */
|
|
137
|
+
--mk-text-base: 0.875rem; /* 14px */
|
|
138
|
+
--mk-text-md: 1rem; /* 16px */
|
|
139
|
+
--mk-text-lg: 1.125rem; /* 18px */
|
|
140
|
+
--mk-text-xl: 1.25rem; /* 20px */
|
|
141
|
+
--mk-text-2xl: 1.5rem; /* 24px */
|
|
142
|
+
--mk-text-3xl: 1.875rem; /* 30px */
|
|
143
|
+
--mk-text-4xl: 2.25rem; /* 36px */
|
|
144
|
+
|
|
145
|
+
--mk-font-normal: 400;
|
|
146
|
+
--mk-font-medium: 500;
|
|
147
|
+
--mk-font-semibold: 600;
|
|
148
|
+
--mk-font-bold: 700;
|
|
149
|
+
|
|
150
|
+
--mk-leading-none: 1;
|
|
151
|
+
--mk-leading-tight: 1.25;
|
|
152
|
+
--mk-leading-snug: 1.375;
|
|
153
|
+
--mk-leading-normal: 1.5;
|
|
154
|
+
--mk-leading-relaxed:1.625;
|
|
155
|
+
|
|
156
|
+
/* Spacing */
|
|
157
|
+
--mk-space-0: 0px;
|
|
158
|
+
--mk-space-1: 4px;
|
|
159
|
+
--mk-space-2: 8px;
|
|
160
|
+
--mk-space-3: 12px;
|
|
161
|
+
--mk-space-4: 16px;
|
|
162
|
+
--mk-space-5: 20px;
|
|
163
|
+
--mk-space-6: 24px;
|
|
164
|
+
--mk-space-8: 32px;
|
|
165
|
+
--mk-space-10: 40px;
|
|
166
|
+
--mk-space-12: 48px;
|
|
167
|
+
--mk-space-16: 64px;
|
|
168
|
+
--mk-space-20: 80px;
|
|
169
|
+
--mk-space-24: 96px;
|
|
170
|
+
|
|
171
|
+
/* Radius */
|
|
172
|
+
--mk-radius-none: 0px;
|
|
173
|
+
--mk-radius-sm: 4px;
|
|
174
|
+
--mk-radius: 8px;
|
|
175
|
+
--mk-radius-md: 10px;
|
|
176
|
+
--mk-radius-lg: 12px;
|
|
177
|
+
--mk-radius-xl: 16px;
|
|
178
|
+
--mk-radius-2xl: 20px;
|
|
179
|
+
--mk-radius-full: 9999px;
|
|
180
|
+
|
|
181
|
+
/* Shadows */
|
|
182
|
+
--mk-shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
|
|
183
|
+
--mk-shadow: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2);
|
|
184
|
+
--mk-shadow-md: 0 4px 6px -1px rgba(0,0,0,0.3), 0 2px 4px -2px rgba(0,0,0,0.2);
|
|
185
|
+
--mk-shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.35), 0 4px 6px -4px rgba(0,0,0,0.2);
|
|
186
|
+
--mk-shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.4), 0 8px 10px -6px rgba(0,0,0,0.2);
|
|
187
|
+
--mk-shadow-glow: 0 0 20px rgba(99,102,241,0.15);
|
|
188
|
+
|
|
189
|
+
/* Motion */
|
|
190
|
+
--mk-duration-fast: 150ms;
|
|
191
|
+
--mk-duration-normal: 250ms;
|
|
192
|
+
--mk-duration-slow: 400ms;
|
|
193
|
+
--mk-duration-slower: 600ms;
|
|
194
|
+
|
|
195
|
+
--mk-ease-default: cubic-bezier(0.4, 0, 0.2, 1);
|
|
196
|
+
--mk-ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
197
|
+
--mk-ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
198
|
+
--mk-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
199
|
+
--mk-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
200
|
+
--mk-ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
201
|
+
|
|
202
|
+
--mk-transition-colors: color var(--mk-duration-fast) var(--mk-ease-default), background-color var(--mk-duration-fast) var(--mk-ease-default), border-color var(--mk-duration-fast) var(--mk-ease-default);
|
|
203
|
+
--mk-transition-transform: transform var(--mk-duration-normal) var(--mk-ease-out-expo);
|
|
204
|
+
--mk-transition-shadow: box-shadow var(--mk-duration-normal) var(--mk-ease-default);
|
|
205
|
+
--mk-transition-opacity: opacity var(--mk-duration-fast) var(--mk-ease-default);
|
|
206
|
+
--mk-transition-all: all var(--mk-duration-fast) var(--mk-ease-default);
|
|
207
|
+
|
|
208
|
+
/* Z-Index Scale */
|
|
209
|
+
--mk-z-base: 0;
|
|
210
|
+
--mk-z-dropdown: 100;
|
|
211
|
+
--mk-z-sticky: 200;
|
|
212
|
+
--mk-z-fixed: 300;
|
|
213
|
+
--mk-z-modal-backdrop: 400;
|
|
214
|
+
--mk-z-modal: 500;
|
|
215
|
+
--mk-z-popover: 600;
|
|
216
|
+
--mk-z-tooltip: 700;
|
|
217
|
+
--mk-z-toast: 800;
|
|
218
|
+
--mk-z-top: 9999;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* ----- Light Theme Override ----- */
|
|
222
|
+
[data-mk-theme="light"] {
|
|
223
|
+
--mk-bg: #ffffff;
|
|
224
|
+
--mk-bg-elevated: #f8fafc;
|
|
225
|
+
--mk-surface: #f1f5f9;
|
|
226
|
+
--mk-surface-hover:#e2e8f0;
|
|
227
|
+
--mk-surface-active:#cbd5e1;
|
|
228
|
+
--mk-surface-raised:#ffffff;
|
|
229
|
+
|
|
230
|
+
--mk-border: #e2e8f0;
|
|
231
|
+
--mk-border-hover: #cbd5e1;
|
|
232
|
+
--mk-border-active: #94a3b8;
|
|
233
|
+
--mk-divider: rgba(0,0,0,0.06);
|
|
234
|
+
|
|
235
|
+
--mk-text: #0f172a;
|
|
236
|
+
--mk-text-primary: #1e293b;
|
|
237
|
+
--mk-text-secondary: #475569;
|
|
238
|
+
--mk-text-tertiary: #94a3b8;
|
|
239
|
+
--mk-text-disabled: #cbd5e1;
|
|
240
|
+
--mk-text-inverse: #f8fafc;
|
|
241
|
+
|
|
242
|
+
--mk-shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
|
|
243
|
+
--mk-shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
|
|
244
|
+
--mk-shadow-md: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04);
|
|
245
|
+
--mk-shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.03);
|
|
246
|
+
--mk-shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.08), 0 8px 10px -6px rgba(0,0,0,0.02);
|
|
247
|
+
--mk-shadow-glow: 0 0 20px rgba(99,102,241,0.12);
|
|
248
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--mk-bg: #09090b;
|
|
3
|
+
--mk-surface: #12121a;
|
|
4
|
+
--mk-surface-hover: #1a1a25;
|
|
5
|
+
--mk-border: #1f1f2e;
|
|
6
|
+
--mk-border-hover: #2e2e42;
|
|
7
|
+
|
|
8
|
+
--mk-primary: #6366f1;
|
|
9
|
+
--mk-primary-hover: #818cf8;
|
|
10
|
+
--mk-primary-active: #4f46e5;
|
|
11
|
+
|
|
12
|
+
--mk-success: #22c55e;
|
|
13
|
+
--mk-warning: #f59e0b;
|
|
14
|
+
--mk-danger: #ef4444;
|
|
15
|
+
|
|
16
|
+
--mk-text: #f8fafc;
|
|
17
|
+
--mk-text-secondary: #94a3b8;
|
|
18
|
+
--mk-text-tertiary: #64748b;
|
|
19
|
+
|
|
20
|
+
--mk-radius: 8px;
|
|
21
|
+
--mk-radius-lg: 12px;
|
|
22
|
+
|
|
23
|
+
--mk-transition: 0.15s ease;
|
|
24
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
.mk-switch {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: 10px;
|
|
5
|
+
cursor: pointer;
|
|
6
|
+
user-select: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.mk-switch__core {
|
|
10
|
+
position: relative;
|
|
11
|
+
width: 40px;
|
|
12
|
+
height: 22px;
|
|
13
|
+
background: var(--mk-surface-hover);
|
|
14
|
+
border: 1px solid var(--mk-border);
|
|
15
|
+
border-radius: 11px;
|
|
16
|
+
transition: var(--mk-transition);
|
|
17
|
+
flex-shrink: 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.mk-switch__core::after {
|
|
21
|
+
content: '';
|
|
22
|
+
position: absolute;
|
|
23
|
+
top: 2px;
|
|
24
|
+
left: 2px;
|
|
25
|
+
width: 16px;
|
|
26
|
+
height: 16px;
|
|
27
|
+
background: var(--mk-text-secondary);
|
|
28
|
+
border-radius: 50%;
|
|
29
|
+
transition: var(--mk-transition);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.mk-switch.is-checked .mk-switch__core {
|
|
33
|
+
background: var(--mk-primary);
|
|
34
|
+
border-color: var(--mk-primary);
|
|
35
|
+
}
|
|
36
|
+
.mk-switch.is-checked .mk-switch__core::after {
|
|
37
|
+
transform: translateX(18px);
|
|
38
|
+
background: #fff;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.mk-switch__label {
|
|
42
|
+
font-size: 13px;
|
|
43
|
+
color: var(--mk-text-secondary);
|
|
44
|
+
transition: color 0.2s;
|
|
45
|
+
}
|
|
46
|
+
.mk-switch.is-checked .mk-switch__label--active {
|
|
47
|
+
color: var(--mk-text);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.mk-switch.is-disabled {
|
|
51
|
+
opacity: 0.4;
|
|
52
|
+
cursor: not-allowed;
|
|
53
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import './switch.css'
|
|
2
|
+
import { onKey, Keys } from '../../a11y/keyboard.ts'
|
|
3
|
+
|
|
4
|
+
export interface SwitchOptions {
|
|
5
|
+
value?: boolean
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
activeText?: string
|
|
8
|
+
inactiveText?: string
|
|
9
|
+
onChange?: (value: boolean) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class MkSwitch {
|
|
13
|
+
el: HTMLLabelElement
|
|
14
|
+
private core: HTMLDivElement
|
|
15
|
+
private options: SwitchOptions
|
|
16
|
+
private _value: boolean
|
|
17
|
+
private activeLabel?: HTMLSpanElement
|
|
18
|
+
private _cleanupKey?: () => void
|
|
19
|
+
private inactiveLabel?: HTMLSpanElement
|
|
20
|
+
|
|
21
|
+
constructor(container: HTMLElement | string, options: SwitchOptions = {}) {
|
|
22
|
+
const parent =
|
|
23
|
+
typeof container === 'string'
|
|
24
|
+
? document.querySelector(container)!
|
|
25
|
+
: container
|
|
26
|
+
|
|
27
|
+
this.options = { value: false, ...options }
|
|
28
|
+
this._value = this.options.value!
|
|
29
|
+
|
|
30
|
+
this.el = document.createElement('label')
|
|
31
|
+
this.el.className = 'mk-switch'
|
|
32
|
+
if (this._value) this.el.classList.add('is-checked')
|
|
33
|
+
if (this.options.disabled) this.el.classList.add('is-disabled')
|
|
34
|
+
this.el.setAttribute('role', 'switch')
|
|
35
|
+
this.el.setAttribute('aria-checked', String(this._value))
|
|
36
|
+
if (!this.options.disabled) {
|
|
37
|
+
this.el.setAttribute('tabindex', '0')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (this.options.inactiveText) {
|
|
41
|
+
this.inactiveLabel = document.createElement('span')
|
|
42
|
+
this.inactiveLabel.className = 'mk-switch__label'
|
|
43
|
+
this.inactiveLabel.textContent = this.options.inactiveText
|
|
44
|
+
if (!this._value) this.inactiveLabel.classList.add('mk-switch__label--active')
|
|
45
|
+
this.el.appendChild(this.inactiveLabel)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.core = document.createElement('div')
|
|
49
|
+
this.core.className = 'mk-switch__core'
|
|
50
|
+
this.el.appendChild(this.core)
|
|
51
|
+
|
|
52
|
+
if (this.options.activeText) {
|
|
53
|
+
this.activeLabel = document.createElement('span')
|
|
54
|
+
this.activeLabel.className = 'mk-switch__label'
|
|
55
|
+
this.activeLabel.textContent = this.options.activeText
|
|
56
|
+
if (this._value) this.activeLabel.classList.add('mk-switch__label--active')
|
|
57
|
+
this.el.appendChild(this.activeLabel)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.el.addEventListener('click', () => {
|
|
61
|
+
if (this.options.disabled) return
|
|
62
|
+
this.toggle()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
this._cleanupKey = onKey(this.el, [
|
|
66
|
+
{ key: Keys.Enter, handler: () => this.toggle() },
|
|
67
|
+
{ key: Keys.Space, handler: () => this.toggle() },
|
|
68
|
+
])
|
|
69
|
+
|
|
70
|
+
parent.appendChild(this.el)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get value(): boolean {
|
|
74
|
+
return this._value
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
set value(v: boolean) {
|
|
78
|
+
if (this._value !== v) {
|
|
79
|
+
this._value = v
|
|
80
|
+
this.el.classList.toggle('is-checked', v)
|
|
81
|
+
this.el.setAttribute('aria-checked', String(v))
|
|
82
|
+
this.activeLabel?.classList.toggle('mk-switch__label--active', v)
|
|
83
|
+
this.inactiveLabel?.classList.toggle('mk-switch__label--active', !v)
|
|
84
|
+
this.options.onChange?.(v)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
toggle(): void {
|
|
89
|
+
this.value = !this._value
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
destroy(): void {
|
|
93
|
+
this._cleanupKey?.()
|
|
94
|
+
this.el.remove()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createSwitch(
|
|
99
|
+
container: HTMLElement | string,
|
|
100
|
+
options?: SwitchOptions
|
|
101
|
+
): MkSwitch {
|
|
102
|
+
return new MkSwitch(container, options)
|
|
103
|
+
}
|