ketekny-ui-kit 1.0.92 → 1.0.94
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 +1 -1
- package/src/twoColLayout/components/MultilevelSidebar.vue +81 -26
- package/src/twoColLayout/components/TwoColLayout.vue +5 -0
- package/src/ui/componentDescription.vue +10 -10
- package/src/ui/componentShowcase.vue +7 -7
- package/src/ui/kCode.vue +2 -2
- package/src/ui/themes/kButton.theme.js +2 -2
package/package.json
CHANGED
|
@@ -33,6 +33,10 @@ export default {
|
|
|
33
33
|
type: String,
|
|
34
34
|
default: "",
|
|
35
35
|
},
|
|
36
|
+
appIcon: {
|
|
37
|
+
type: String,
|
|
38
|
+
default: "",
|
|
39
|
+
},
|
|
36
40
|
width: {
|
|
37
41
|
type: String,
|
|
38
42
|
default: "360px",
|
|
@@ -65,7 +69,7 @@ export default {
|
|
|
65
69
|
emits: ['select', 'logo-click', 'signin', 'signup', 'signout', 'edit-profile', 'item-click'],
|
|
66
70
|
data() {
|
|
67
71
|
return {
|
|
68
|
-
activeId: '
|
|
72
|
+
activeId: '',
|
|
69
73
|
query: '',
|
|
70
74
|
collapsed: false,
|
|
71
75
|
openIds: new Set(['projects']),
|
|
@@ -114,8 +118,53 @@ export default {
|
|
|
114
118
|
collect(this.filteredMenu)
|
|
115
119
|
return all
|
|
116
120
|
},
|
|
121
|
+
expandedFooterLinks() {
|
|
122
|
+
return this.footerLinks.filter(link => link.id !== 'my-profile')
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
watch: {
|
|
126
|
+
mainMenu: {
|
|
127
|
+
handler() {
|
|
128
|
+
this.syncActiveFromMenu()
|
|
129
|
+
},
|
|
130
|
+
deep: true,
|
|
131
|
+
immediate: true,
|
|
132
|
+
},
|
|
133
|
+
$route() {
|
|
134
|
+
this.syncActiveFromMenu()
|
|
135
|
+
},
|
|
117
136
|
},
|
|
118
137
|
methods: {
|
|
138
|
+
syncActiveFromMenu() {
|
|
139
|
+
const routePath = this.$route?.path
|
|
140
|
+
const findMatch = (items, parentIds = []) => {
|
|
141
|
+
for (const item of items) {
|
|
142
|
+
const itemPath = item?.link?.to ?? item?.to ?? null
|
|
143
|
+
if (routePath && itemPath === routePath) {
|
|
144
|
+
return {
|
|
145
|
+
id: item.id,
|
|
146
|
+
parentIds,
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (item?.children?.length) {
|
|
150
|
+
const childMatch = findMatch(item.children, [...parentIds, item.id])
|
|
151
|
+
if (childMatch) return childMatch
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const matched = findMatch(this.mainMenu)
|
|
158
|
+
if (matched?.id) {
|
|
159
|
+
this.activeId = matched.id
|
|
160
|
+
this.openIds = new Set([...this.openIds, ...matched.parentIds])
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!this.activeId && this.mainMenu[0]?.id) {
|
|
165
|
+
this.activeId = this.mainMenu[0].id
|
|
166
|
+
}
|
|
167
|
+
},
|
|
119
168
|
toggleCollapsed() {
|
|
120
169
|
this.collapsed = !this.collapsed
|
|
121
170
|
},
|
|
@@ -225,12 +274,20 @@ export default {
|
|
|
225
274
|
</p>
|
|
226
275
|
</div>
|
|
227
276
|
|
|
228
|
-
<div v-else-if="title && collapsed" class="px-3 pb-2">
|
|
277
|
+
<div v-else-if="(title || appIcon) && collapsed" class="flex justify-center px-3 pb-2">
|
|
229
278
|
<div
|
|
230
279
|
v-tooltip.right="title"
|
|
231
280
|
class="flex h-10 w-10 items-center justify-center rounded-md border border-sidebar-border/30 bg-sidebar-accent/30 text-[10px] font-bold tracking-[0.18em] text-sidebar-muted"
|
|
232
281
|
>
|
|
233
|
-
|
|
282
|
+
<img
|
|
283
|
+
v-if="appIcon"
|
|
284
|
+
:src="appIcon"
|
|
285
|
+
alt="App icon"
|
|
286
|
+
class="h-6 w-6 object-contain"
|
|
287
|
+
/>
|
|
288
|
+
<template v-else>
|
|
289
|
+
{{ collapsedTitle }}
|
|
290
|
+
</template>
|
|
234
291
|
</div>
|
|
235
292
|
</div>
|
|
236
293
|
|
|
@@ -298,29 +355,27 @@ export default {
|
|
|
298
355
|
</nav>
|
|
299
356
|
|
|
300
357
|
<div class="p-3 mt-auto border-t border-sidebar-border">
|
|
301
|
-
<div
|
|
302
|
-
class="flex items-center
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
358
|
+
<div :class="collapsed ? 'flex flex-col items-center gap-1' : 'space-y-1'">
|
|
359
|
+
<div v-if="!collapsed" class="flex items-center gap-2">
|
|
360
|
+
<button
|
|
361
|
+
type="button"
|
|
362
|
+
class="sidebar-footer-item flex min-h-[38px] flex-1 items-center gap-2.5 rounded-md bg-transparent px-2 py-2 text-left text-sm font-medium text-sidebar-foreground/80 outline-none transition-colors duration-150 hover:bg-sidebar-accent hover:text-sidebar-foreground"
|
|
363
|
+
@click="handleFooterSelect('my-profile')"
|
|
364
|
+
>
|
|
365
|
+
<CircleUser class="sidebar-footer-item-icon size-4 shrink-0" :stroke-width="1.9" />
|
|
366
|
+
<span class="min-w-0 flex-1">
|
|
367
|
+
<span class="block truncate">Το προφίλ μου</span>
|
|
368
|
+
<span class="block truncate text-xs font-normal text-sidebar-muted">{{ accountEmail }}</span>
|
|
369
|
+
</span>
|
|
370
|
+
</button>
|
|
371
|
+
<button
|
|
372
|
+
type="button"
|
|
373
|
+
class="rounded-md p-1.5 text-sidebar-muted hover:bg-sidebar-accent hover:text-sidebar-foreground"
|
|
374
|
+
aria-label="Notifications"
|
|
375
|
+
>
|
|
376
|
+
<Bell class="size-4" :stroke-width="2" />
|
|
377
|
+
</button>
|
|
309
378
|
</div>
|
|
310
|
-
<button
|
|
311
|
-
v-if="!collapsed"
|
|
312
|
-
type="button"
|
|
313
|
-
class="rounded-md p-1.5 text-sidebar-muted hover:bg-sidebar-accent hover:text-sidebar-foreground"
|
|
314
|
-
aria-label="Notifications"
|
|
315
|
-
>
|
|
316
|
-
<Bell class="size-4" :stroke-width="2" />
|
|
317
|
-
</button>
|
|
318
|
-
</div>
|
|
319
|
-
|
|
320
|
-
<div
|
|
321
|
-
class="pt-2 mt-2 border-t border-sidebar-border/70"
|
|
322
|
-
:class="collapsed ? 'flex flex-col items-center gap-1' : 'space-y-1'"
|
|
323
|
-
>
|
|
324
379
|
<button
|
|
325
380
|
v-for="link in footerLinks"
|
|
326
381
|
:key="link.id"
|
|
@@ -353,7 +408,7 @@ export default {
|
|
|
353
408
|
/>
|
|
354
409
|
</button>
|
|
355
410
|
<button
|
|
356
|
-
v-for="link in
|
|
411
|
+
v-for="link in expandedFooterLinks"
|
|
357
412
|
:key="`${link.id}-expanded`"
|
|
358
413
|
v-else
|
|
359
414
|
type="button"
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<MultilevelSidebar
|
|
6
6
|
:title="title"
|
|
7
|
+
:app-icon="appIcon"
|
|
7
8
|
:width="width"
|
|
8
9
|
:collapsed-width="collapsedWidth"
|
|
9
10
|
:main-menu="mainMenu"
|
|
@@ -50,6 +51,10 @@ export default {
|
|
|
50
51
|
type: String,
|
|
51
52
|
default: "",
|
|
52
53
|
},
|
|
54
|
+
appIcon: {
|
|
55
|
+
type: String,
|
|
56
|
+
default: "",
|
|
57
|
+
},
|
|
53
58
|
width: {
|
|
54
59
|
type: String,
|
|
55
60
|
default: "360px",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="overflow-hidden border rounded-lg shadow-sm component-card cp-card cp-border">
|
|
2
|
+
<div class="overflow-hidden border rounded-lg shadow-sm component-card cp-card cp-border text-[14px]">
|
|
3
3
|
<div class="flex items-center justify-between px-4 py-3 border-b cp-border cp-muted-50">
|
|
4
|
-
<h2 class="text-
|
|
4
|
+
<h2 class="text-[15px] font-semibold cp-text">{{ componentName }} Description</h2>
|
|
5
5
|
|
|
6
6
|
<div class="flex items-center gap-1">
|
|
7
7
|
<button
|
|
8
8
|
v-for="tab in tabs"
|
|
9
9
|
:key="tab.id"
|
|
10
10
|
@click="activeTab = tab.id"
|
|
11
|
-
:class="['px-3 py-1.5 text-
|
|
11
|
+
:class="['px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
|
|
12
12
|
{{ tab.label }}
|
|
13
13
|
</button>
|
|
14
14
|
</div>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="p-4">
|
|
18
18
|
<div v-show="activeTab === 'props'">
|
|
19
19
|
<div v-if="props.length > 0" class="overflow-x-auto">
|
|
20
|
-
<table class="w-full text-
|
|
20
|
+
<table class="w-full text-[13px]">
|
|
21
21
|
<thead>
|
|
22
22
|
<tr class="border-b cp-border">
|
|
23
23
|
<th class="px-4 py-3 font-semibold text-left cp-text">Name</th>
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
<tbody>
|
|
31
31
|
<tr v-for="(prop, index) in props" :key="prop.name" :class="index % 2 === 0 ? 'cp-muted-30' : ''">
|
|
32
32
|
<td class="px-4 py-3">
|
|
33
|
-
<code class="text-
|
|
33
|
+
<code class="text-[13px] font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ prop.name }}</code>
|
|
34
34
|
</td>
|
|
35
|
-
<td class="px-4 py-3"><span class="font-mono text-
|
|
35
|
+
<td class="px-4 py-3"><span class="font-mono text-[13px] text-blue-600">{{ prop.type }}</span></td>
|
|
36
36
|
<td class="px-4 py-3">
|
|
37
|
-
<code v-if="prop.default !== undefined" class="font-mono text-
|
|
37
|
+
<code v-if="prop.default !== undefined" class="font-mono text-[13px] text-slate-700">{{ prop.default }}</code>
|
|
38
38
|
<span v-else class="cp-text-muted">-</span>
|
|
39
39
|
</td>
|
|
40
40
|
<td class="px-4 py-3 cp-text-muted">{{ prop.description }}</td>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<div v-show="activeTab === 'slots'">
|
|
52
52
|
<div v-if="slots.length > 0" class="overflow-x-auto">
|
|
53
|
-
<table class="w-full text-
|
|
53
|
+
<table class="w-full text-[13px]">
|
|
54
54
|
<thead>
|
|
55
55
|
<tr class="border-b cp-border">
|
|
56
56
|
<th class="px-4 py-3 font-semibold text-left cp-text">Name</th>
|
|
@@ -62,10 +62,10 @@
|
|
|
62
62
|
<tbody>
|
|
63
63
|
<tr v-for="(slot, index) in slots" :key="slot.name" :class="index % 2 === 0 ? 'cp-muted-30' : ''">
|
|
64
64
|
<td class="px-4 py-3">
|
|
65
|
-
<code class="text-
|
|
65
|
+
<code class="text-[13px] font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ slot.name }}</code>
|
|
66
66
|
</td>
|
|
67
67
|
<td class="px-4 py-3">
|
|
68
|
-
<span :class="['inline-flex items-center px-2 py-0.5 rounded-full text-
|
|
68
|
+
<span :class="['inline-flex items-center px-2 py-0.5 rounded-full text-[13px] font-medium', slot.scoped ? 'bg-emerald-100 text-emerald-700' : 'cp-badge-muted']">
|
|
69
69
|
{{ slot.scoped ? "Yes" : "No" }}
|
|
70
70
|
</span>
|
|
71
71
|
</td>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="overflow-hidden border rounded-lg shadow-sm component-card cp-card cp-border">
|
|
2
|
+
<div class="overflow-hidden border rounded-lg shadow-sm component-card cp-card cp-border text-[14px]">
|
|
3
3
|
<div class="flex items-center justify-between px-4 py-3 border-b cp-border cp-muted-50">
|
|
4
|
-
<h2 class="text-
|
|
4
|
+
<h2 class="text-[15px] font-semibold cp-text">{{ componentName }} Preview</h2>
|
|
5
5
|
|
|
6
6
|
<div class="flex items-center gap-1">
|
|
7
7
|
<button
|
|
8
8
|
v-for="tab in tabs"
|
|
9
9
|
:key="tab.id"
|
|
10
10
|
@click="activeTab = tab.id"
|
|
11
|
-
:class="['px-3 py-1.5 text-
|
|
11
|
+
:class="['px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
|
|
12
12
|
{{ tab.label }}
|
|
13
13
|
</button>
|
|
14
14
|
</div>
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
v-for="vp in previewViewports"
|
|
23
23
|
:key="vp.id"
|
|
24
24
|
@click="activeViewport = vp.id"
|
|
25
|
-
:class="['px-3 py-1.5 text-
|
|
25
|
+
:class="['px-3 py-1.5 text-[13px] font-semibold rounded-md transition-colors', activeViewport === vp.id ? 'cp-tab-active' : 'cp-tab']">
|
|
26
26
|
{{ vp.label }}
|
|
27
27
|
</button>
|
|
28
28
|
</div>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
<div v-show="activeTab === 'code'" class="relative">
|
|
39
39
|
<div class="absolute z-10 top-3 right-3">
|
|
40
|
-
<button @click="copyCode" class="flex items-center gap-1.5 px-3 py-1.5 text-
|
|
40
|
+
<button @click="copyCode" class="flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium rounded-md transition-colors cp-chip cp-chip-hover cp-chip-text">
|
|
41
41
|
<svg
|
|
42
42
|
v-if="!copied"
|
|
43
43
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
</button>
|
|
73
73
|
</div>
|
|
74
74
|
|
|
75
|
-
<pre class="p-4 overflow-x-auto rounded-lg cp-pre">
|
|
76
|
-
<code class="font-mono text-
|
|
75
|
+
<pre class="p-4 overflow-x-auto rounded-lg text-[11px] leading-5 cp-pre">
|
|
76
|
+
<code class="font-mono text-[11px]" v-html="highlightedCode"></code>
|
|
77
77
|
</pre>
|
|
78
78
|
</div>
|
|
79
79
|
</div>
|
package/src/ui/kCode.vue
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<!-- kCode.vue -->
|
|
2
2
|
<template>
|
|
3
|
-
<div class="p-4 mt-3 overflow-hidden text-white whitespace-pre bg-gray-900 border rounded-lg border-primary/30">
|
|
3
|
+
<div class="p-4 mt-3 overflow-hidden text-[11px] leading-5 text-white whitespace-pre bg-gray-900 border rounded-lg border-primary/30">
|
|
4
4
|
<div class="overflow-auto">
|
|
5
|
-
<code>{{ normalizedContent }}</code>
|
|
5
|
+
<code class="font-mono text-[11px]">{{ normalizedContent }}</code>
|
|
6
6
|
</div>
|
|
7
7
|
</div>
|
|
8
8
|
</template>
|
|
@@ -5,7 +5,7 @@ export const K_BUTTON_BASE = "inline-flex flex-row items-center justify-center f
|
|
|
5
5
|
|
|
6
6
|
export const K_BUTTON_SIZE_STYLES = {
|
|
7
7
|
normal: {
|
|
8
|
-
regular: "h-
|
|
8
|
+
regular: "h-9 px-4 text-sm",
|
|
9
9
|
iconOnly: "h-10 w-10 p-0",
|
|
10
10
|
icon: "w-5 h-5",
|
|
11
11
|
loader: "w-5 h-5",
|
|
@@ -27,7 +27,7 @@ export const K_BUTTON_SIZE_STYLES = {
|
|
|
27
27
|
},
|
|
28
28
|
// Backward compatibility aliases
|
|
29
29
|
default: {
|
|
30
|
-
regular: "h-
|
|
30
|
+
regular: "h-9 px-4 text-sm",
|
|
31
31
|
iconOnly: "h-10 w-10 p-0",
|
|
32
32
|
icon: "w-5 h-5",
|
|
33
33
|
loader: "w-5 h-5",
|