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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.92",
4
+ "version": "1.0.94",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -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: 'dashboard',
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
- {{ collapsedTitle }}
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 py-2 rounded-md hover:bg-sidebar-accent"
303
- :class="collapsed ? 'justify-center px-0' : 'gap-2.5 px-2'"
304
- >
305
- <CircleUser class="size-8 shrink-0 text-sidebar-muted" :stroke-width="1.75" />
306
- <div v-if="!collapsed" class="flex-1 min-w-0">
307
- <p class="text-sm font-medium truncate text-sidebar-foreground">{{ accountDisplayName }}</p>
308
- <p class="text-xs truncate text-sidebar-muted">{{ accountEmail }}</p>
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 footerLinks"
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-lg font-semibold cp-text">{{ componentName }} Description</h2>
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-sm font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
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-sm">
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-sm font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ prop.name }}</code>
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-sm text-blue-600">{{ prop.type }}</span></td>
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-sm text-slate-700">{{ prop.default }}</code>
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-sm">
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-sm font-mono px-1.5 py-0.5 rounded cp-chip cp-chip-text">{{ slot.name }}</code>
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-sm font-medium', slot.scoped ? 'bg-emerald-100 text-emerald-700' : 'cp-badge-muted']">
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-lg font-semibold cp-text">{{ componentName }} Preview</h2>
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-sm font-medium rounded-md transition-colors', activeTab === tab.id ? 'cp-tab-active' : 'cp-tab']">
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-sm font-semibold rounded-md transition-colors', activeViewport === vp.id ? 'cp-tab-active' : 'cp-tab']">
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-sm font-medium rounded-md transition-colors cp-chip cp-chip-hover cp-chip-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-sm" v-html="highlightedCode"></code>
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-10 px-4 text-base",
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-10 px-4 text-base",
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",