ketekny-ui-kit 1.0.119 → 1.0.121
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/index.js +2 -1
- package/package.json +1 -1
- package/src/twoColLayout/components/MultilevelSidebar.vue +58 -44
- package/src/twoColLayout/components/SidebarMenuItem.vue +0 -3
- package/src/twoColLayout/components/TwoColLayout.vue +3 -6
- package/src/ui/kClipboard.vue +77 -0
- package/src/ui/kToggle.vue +6 -6
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import kMessage from './src/ui/kMessage.vue'
|
|
|
3
3
|
import kButton from './src/ui/kButton.vue'
|
|
4
4
|
import kCheckbox from './src/ui/kCheckbox.vue'
|
|
5
5
|
import kChip from './src/ui/kChip.vue'
|
|
6
|
+
import kClipboard from './src/ui/kClipboard.vue'
|
|
6
7
|
import kCode from './src/ui/kCode.vue'
|
|
7
8
|
import kDialog from './src/ui/kDialog.vue'
|
|
8
9
|
import kDrawer from './src/ui/kDrawer.vue'
|
|
@@ -56,7 +57,7 @@ import tailwindPreset from './tailwind-preset.js'
|
|
|
56
57
|
// Named exports (tree-shaking friendly)
|
|
57
58
|
export {
|
|
58
59
|
// UI Components
|
|
59
|
-
kMessage, kCode, kToolbar, kTooltip, kTable, kTabs, kChip, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kPagination, kTree,
|
|
60
|
+
kMessage, kCode, kToolbar, kTooltip, kTable, kTabs, kChip, kClipboard, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kPagination, kTree,
|
|
60
61
|
|
|
61
62
|
// Form Components
|
|
62
63
|
kButton, kCheckbox, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea, kForm, kOptionGroup,
|
package/package.json
CHANGED
|
@@ -75,14 +75,15 @@ export default {
|
|
|
75
75
|
},
|
|
76
76
|
theme: {
|
|
77
77
|
type: String,
|
|
78
|
-
default:
|
|
79
|
-
validator: value => ['dark', 'light'].includes(value),
|
|
78
|
+
default: null,
|
|
79
|
+
validator: value => value === null || ['dark', 'light'].includes(value),
|
|
80
80
|
},
|
|
81
81
|
},
|
|
82
82
|
emits: ['select', 'logo-click', 'signin', 'signup', 'signout', 'edit-profile', 'item-click'],
|
|
83
83
|
data() {
|
|
84
84
|
return {
|
|
85
85
|
demoAvatarUrl,
|
|
86
|
+
logoBaseUrl: LOGO_BASE_URL,
|
|
86
87
|
activeId: '',
|
|
87
88
|
activeMenuTab: 'all',
|
|
88
89
|
query: '',
|
|
@@ -105,15 +106,7 @@ export default {
|
|
|
105
106
|
}
|
|
106
107
|
},
|
|
107
108
|
themeClass() {
|
|
108
|
-
return this.theme
|
|
109
|
-
},
|
|
110
|
-
activeExpandedLogoSrc() {
|
|
111
|
-
if (this.theme === 'light') return `${LOGO_BASE_URL}/logo-light.png`
|
|
112
|
-
return `${LOGO_BASE_URL}/logo-dark.png`
|
|
113
|
-
},
|
|
114
|
-
activeCollapsedLogoSrc() {
|
|
115
|
-
if (this.theme === 'light') return `${LOGO_BASE_URL}/logo_icon.jpg`
|
|
116
|
-
return `${LOGO_BASE_URL}/logo-icon-dark.png`
|
|
109
|
+
return this.theme ? `sidebar-force-${this.theme}` : ''
|
|
117
110
|
},
|
|
118
111
|
collapsedTitle() {
|
|
119
112
|
if (!this.title) return ''
|
|
@@ -469,7 +462,7 @@ export default {
|
|
|
469
462
|
|
|
470
463
|
<template>
|
|
471
464
|
<aside
|
|
472
|
-
class="group/sidebar fixed inset-y-0 left-0 z-40 flex h-full shrink-0 flex-col border-r border-[var(--sidebar-border)] bg-[var(--sidebar-bg)] text-[var(--sidebar-text)] transition-[width,transform] duration-200 ease-out lg:static lg:translate-x-0"
|
|
465
|
+
class="group/sidebar sidebar-root fixed inset-y-0 left-0 z-40 flex h-full shrink-0 flex-col border-r border-[var(--sidebar-border)] bg-[var(--sidebar-bg)] text-[var(--sidebar-text)] transition-[width,transform] duration-200 ease-out lg:static lg:translate-x-0"
|
|
473
466
|
:style="sidebarWidthStyle"
|
|
474
467
|
:class="[
|
|
475
468
|
themeClass,
|
|
@@ -488,20 +481,34 @@ export default {
|
|
|
488
481
|
</button>
|
|
489
482
|
|
|
490
483
|
<div class="relative flex items-center px-4 py-4" :class="collapsed ? 'justify-center' : 'gap-2.5'">
|
|
491
|
-
<
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
484
|
+
<template v-if="collapsed">
|
|
485
|
+
<img
|
|
486
|
+
:src="`${logoBaseUrl}/logo_icon.jpg`"
|
|
487
|
+
alt="Ketekny logo"
|
|
488
|
+
class="sidebar-logo-light size-9 shrink-0 rounded-lg object-contain cursor-pointer"
|
|
489
|
+
@click="handleLogoClick"
|
|
490
|
+
/>
|
|
491
|
+
<img
|
|
492
|
+
:src="`${logoBaseUrl}/logo-icon-dark.png`"
|
|
493
|
+
alt="Ketekny logo"
|
|
494
|
+
class="sidebar-logo-dark size-9 shrink-0 rounded-lg object-contain cursor-pointer"
|
|
495
|
+
@click="handleLogoClick"
|
|
496
|
+
/>
|
|
497
|
+
</template>
|
|
498
|
+
<template v-else>
|
|
499
|
+
<img
|
|
500
|
+
:src="`${logoBaseUrl}/logo-light.png`"
|
|
501
|
+
alt="Ketekny logo"
|
|
502
|
+
class="sidebar-logo-light min-w-0 flex-1 object-contain cursor-pointer"
|
|
503
|
+
@click="handleLogoClick"
|
|
504
|
+
/>
|
|
505
|
+
<img
|
|
506
|
+
:src="`${logoBaseUrl}/logo-dark.png`"
|
|
507
|
+
alt="Ketekny logo"
|
|
508
|
+
class="sidebar-logo-dark min-w-0 flex-1 object-contain cursor-pointer"
|
|
509
|
+
@click="handleLogoClick"
|
|
510
|
+
/>
|
|
511
|
+
</template>
|
|
505
512
|
</div>
|
|
506
513
|
|
|
507
514
|
<div v-if="title && !collapsed" class="px-4 pb-2">
|
|
@@ -596,7 +603,6 @@ export default {
|
|
|
596
603
|
:open-ids="effectiveOpenIds"
|
|
597
604
|
:collapsed="collapsed"
|
|
598
605
|
:favorites="favoriteIds"
|
|
599
|
-
:theme="theme"
|
|
600
606
|
@select="handleMenuSelect"
|
|
601
607
|
@toggle="toggle"
|
|
602
608
|
@toggle-favorite="toggleFavorite"
|
|
@@ -741,7 +747,27 @@ export default {
|
|
|
741
747
|
</template>
|
|
742
748
|
|
|
743
749
|
<style scoped>
|
|
744
|
-
.sidebar-
|
|
750
|
+
.sidebar-root {
|
|
751
|
+
--sidebar-bg: #f9f9f9;
|
|
752
|
+
--sidebar-surface: #ffffff;
|
|
753
|
+
--sidebar-surface-muted: #eef4fb;
|
|
754
|
+
--sidebar-text: #0f172a;
|
|
755
|
+
--sidebar-text-soft: rgba(15, 23, 42, 0.8);
|
|
756
|
+
--sidebar-text-strong: rgba(15, 23, 42, 0.9);
|
|
757
|
+
--sidebar-text-muted: #64748b;
|
|
758
|
+
--sidebar-border: rgba(148, 163, 184, 0.28);
|
|
759
|
+
--sidebar-border-strong: rgba(100, 116, 139, 0.4);
|
|
760
|
+
--sidebar-hover: #e2e8f0;
|
|
761
|
+
--sidebar-shadow: rgba(15, 23, 42, 0.12);
|
|
762
|
+
--sidebar-danger: #ea580c;
|
|
763
|
+
--sidebar-danger-hover: #c2410c;
|
|
764
|
+
--sidebar-danger-bg: #ffedd5;
|
|
765
|
+
--sidebar-logo-light-display: block;
|
|
766
|
+
--sidebar-logo-dark-display: none;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
html.dark .sidebar-root:not(.sidebar-force-light),
|
|
770
|
+
.sidebar-root.sidebar-force-dark {
|
|
745
771
|
--sidebar-bg: #0b0c0f;
|
|
746
772
|
--sidebar-surface: #161a22;
|
|
747
773
|
--sidebar-surface-muted: rgba(255, 255, 255, 0.06);
|
|
@@ -756,22 +782,10 @@ export default {
|
|
|
756
782
|
--sidebar-danger: #f59e0b;
|
|
757
783
|
--sidebar-danger-hover: #fbbf24;
|
|
758
784
|
--sidebar-danger-bg: rgba(245, 158, 11, 0.12);
|
|
785
|
+
--sidebar-logo-light-display: none;
|
|
786
|
+
--sidebar-logo-dark-display: block;
|
|
759
787
|
}
|
|
760
788
|
|
|
761
|
-
.sidebar-
|
|
762
|
-
--sidebar-
|
|
763
|
-
--sidebar-surface: #ffffff;
|
|
764
|
-
--sidebar-surface-muted: #eef4fb;
|
|
765
|
-
--sidebar-text: #0f172a;
|
|
766
|
-
--sidebar-text-soft: rgba(15, 23, 42, 0.8);
|
|
767
|
-
--sidebar-text-strong: rgba(15, 23, 42, 0.9);
|
|
768
|
-
--sidebar-text-muted: #64748b;
|
|
769
|
-
--sidebar-border: rgba(148, 163, 184, 0.28);
|
|
770
|
-
--sidebar-border-strong: rgba(100, 116, 139, 0.4);
|
|
771
|
-
--sidebar-hover: #e2e8f0;
|
|
772
|
-
--sidebar-shadow: rgba(15, 23, 42, 0.12);
|
|
773
|
-
--sidebar-danger: #ea580c;
|
|
774
|
-
--sidebar-danger-hover: #c2410c;
|
|
775
|
-
--sidebar-danger-bg: #ffedd5;
|
|
776
|
-
}
|
|
789
|
+
.sidebar-logo-light { display: var(--sidebar-logo-light-display); }
|
|
790
|
+
.sidebar-logo-dark { display: var(--sidebar-logo-dark-display); }
|
|
777
791
|
</style>
|
|
@@ -18,7 +18,6 @@ export default {
|
|
|
18
18
|
openIds: { type: Object, required: true },
|
|
19
19
|
collapsed: { type: Boolean, default: false },
|
|
20
20
|
favorites: { type: Object, default: null },
|
|
21
|
-
theme: { type: String, default: 'dark' },
|
|
22
21
|
},
|
|
23
22
|
emits: ['select', 'toggle', 'toggle-favorite'],
|
|
24
23
|
data() {
|
|
@@ -245,7 +244,6 @@ export default {
|
|
|
245
244
|
:open-ids="openIds"
|
|
246
245
|
:collapsed="collapsed"
|
|
247
246
|
:favorites="favorites"
|
|
248
|
-
:theme="theme"
|
|
249
247
|
@select="$emit('select', $event)"
|
|
250
248
|
@toggle="$emit('toggle', $event)"
|
|
251
249
|
@toggle-favorite="$emit('toggle-favorite', $event)"
|
|
@@ -292,7 +290,6 @@ export default {
|
|
|
292
290
|
:open-ids="openIds"
|
|
293
291
|
:collapsed="false"
|
|
294
292
|
:favorites="favorites"
|
|
295
|
-
:theme="theme"
|
|
296
293
|
@select="$emit('select', $event)"
|
|
297
294
|
@toggle="$emit('toggle', $event)"
|
|
298
295
|
@toggle-favorite="$emit('toggle-favorite', $event)"
|
|
@@ -41,10 +41,7 @@
|
|
|
41
41
|
<button
|
|
42
42
|
v-if="!mobileMenuOpen && showMobileMenuButton"
|
|
43
43
|
type="button"
|
|
44
|
-
class="fixed bottom-0 left-0 z-50 inline-flex size-14 items-center justify-center rounded-tr-2xl transition-colors lg:hidden"
|
|
45
|
-
:class="theme === 'light'
|
|
46
|
-
? 'border border-rose-200 bg-rose-100 text-rose-900 shadow-lg shadow-slate-900/10 hover:bg-rose-200'
|
|
47
|
-
: ' bg-[#e63933] text-white shadow-lg shadow-black/25'"
|
|
44
|
+
class="fixed bottom-0 left-0 z-50 inline-flex size-14 items-center justify-center rounded-tr-2xl transition-colors lg:hidden bg-brand text-brand-foreground shadow-lg shadow-black/25"
|
|
48
45
|
aria-label="Open menu"
|
|
49
46
|
@click="toggleMenu">
|
|
50
47
|
<Menu class="size-6" :stroke-width="2.25" />
|
|
@@ -99,8 +96,8 @@ export default {
|
|
|
99
96
|
},
|
|
100
97
|
theme: {
|
|
101
98
|
type: String,
|
|
102
|
-
default:
|
|
103
|
-
validator: value => ["dark", "light"].includes(value),
|
|
99
|
+
default: null,
|
|
100
|
+
validator: value => value === null || ["dark", "light"].includes(value),
|
|
104
101
|
},
|
|
105
102
|
},
|
|
106
103
|
emits: ["select-menu", "logo-click", "signin", "signup", "signout", "edit-profile", "item-click"],
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button
|
|
3
|
+
type="button"
|
|
4
|
+
class="inline-flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-slate-900 transition hover:bg-slate-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-60"
|
|
5
|
+
:aria-label="ariaLabel || `Copy ${text}`"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
@click="copyToClipboard"
|
|
8
|
+
>
|
|
9
|
+
<slot>
|
|
10
|
+
<span class="truncate max-w-[240px]">{{ text }}</span>
|
|
11
|
+
<component :is="copied ? Check : Copy" :class="copied ? 'text-emerald-600' : ''" :size="16" />
|
|
12
|
+
</slot>
|
|
13
|
+
</button>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup>
|
|
17
|
+
import { Check, Copy } from "@lucide/vue";
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<script>
|
|
21
|
+
export default {
|
|
22
|
+
name: "kClipboard",
|
|
23
|
+
emits: ["copied", "error"],
|
|
24
|
+
props: {
|
|
25
|
+
text: {
|
|
26
|
+
type: String,
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
ariaLabel: {
|
|
30
|
+
type: String,
|
|
31
|
+
default: null,
|
|
32
|
+
},
|
|
33
|
+
disabled: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false,
|
|
36
|
+
},
|
|
37
|
+
resetAfter: {
|
|
38
|
+
type: Number,
|
|
39
|
+
default: 2000,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
data() {
|
|
43
|
+
return {
|
|
44
|
+
copied: false,
|
|
45
|
+
copiedTimeout: null,
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
beforeUnmount() {
|
|
49
|
+
if (this.copiedTimeout) {
|
|
50
|
+
clearTimeout(this.copiedTimeout);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
methods: {
|
|
54
|
+
async copyToClipboard() {
|
|
55
|
+
if (this.disabled) return;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
await navigator.clipboard.writeText(this.text);
|
|
59
|
+
this.copied = true;
|
|
60
|
+
this.$emit("copied", this.text);
|
|
61
|
+
|
|
62
|
+
if (this.copiedTimeout) {
|
|
63
|
+
clearTimeout(this.copiedTimeout);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.copiedTimeout = window.setTimeout(() => {
|
|
67
|
+
this.copied = false;
|
|
68
|
+
this.copiedTimeout = null;
|
|
69
|
+
}, this.resetAfter);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
this.$emit("error", error);
|
|
72
|
+
console.error("kClipboard: failed to copy text.", error);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
</script>
|
package/src/ui/kToggle.vue
CHANGED
|
@@ -148,29 +148,29 @@ export default {
|
|
|
148
148
|
border: 1px solid #cbd5e1;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
html.dark .k-toggle-track--on {
|
|
152
152
|
background: #0369A1;
|
|
153
153
|
border-color: #0369A1;
|
|
154
154
|
box-shadow: 0 2px 8px rgb(2 6 23 / 0.45);
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
html.dark .k-toggle-track--off {
|
|
158
158
|
background: #475569;
|
|
159
159
|
border-color: #475569;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
html.dark .k-toggle-track--disabled {
|
|
163
163
|
background: #334155;
|
|
164
164
|
border-color: #334155;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
html.dark .k-toggle-thumb--on,
|
|
168
|
+
html.dark .k-toggle-thumb--off {
|
|
169
169
|
background: #f8fafc;
|
|
170
170
|
border-color: #cbd5e1;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
html.dark .k-toggle-thumb--disabled {
|
|
174
174
|
background: #94a3b8;
|
|
175
175
|
border-color: #64748b;
|
|
176
176
|
}
|