ketekny-ui-kit 1.0.129 → 1.0.131

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 CHANGED
@@ -2,6 +2,7 @@
2
2
  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
+ import kCard from './src/ui/kCard.vue'
5
6
  import kChip from './src/ui/kChip.vue'
6
7
  import kClipboard from './src/ui/kClipboard.vue'
7
8
  import kCode from './src/ui/kCode.vue'
@@ -38,6 +39,7 @@ import kTree from './src/ui/kTree.vue'
38
39
  import kAppHeader from './src/layout/kAppHeader.vue'
39
40
  import kAppFooter from './src/layout/kAppFooter.vue'
40
41
  import kAppMain from './src/layout/kAppMain.vue'
42
+ import kFormSection from './src/layout/kFormSection.vue'
41
43
  import kHero from './src/layout/kHero.vue'
42
44
  import kSingleColPage from './src/layout/kSingleColPage.vue'
43
45
  import kMultiColPage from './src/layout/kMultiColPage.vue'
@@ -58,7 +60,7 @@ import tailwindPreset from './tailwind-preset.js'
58
60
  // Named exports (tree-shaking friendly)
59
61
  export {
60
62
  // UI Components
61
- kMessage, kCode, kToolbar, kTooltip, kTable, kTabs, kChip, kClipboard, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kPagination, kTree,
63
+ kMessage, kCode, kToolbar, kTooltip, kTable, kTabs, kCard, kChip, kClipboard, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar, kPagination, kTree,
62
64
 
63
65
  // Form Components
64
66
  kButton, kCheckbox, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kList, kTextArea, kForm, kOptionGroup,
@@ -67,7 +69,7 @@ export {
67
69
  kDialog, kDrawer,
68
70
 
69
71
  // Layout Components
70
- kAppHeader, kAppFooter, kAppMain, kHero, kSingleColPage, kMultiColPage, kTwoColPage, twoColLayout, legacyTwoColLayout,
72
+ kAppHeader, kAppFooter, kAppMain, kFormSection, kHero, kSingleColPage, kMultiColPage, kTwoColPage, twoColLayout, legacyTwoColLayout,
71
73
 
72
74
  // Plugins
73
75
  toastPlugin, confirmPlugin, alertPlugin, tooltipPlugin, inputDialogPlugin,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.129",
4
+ "version": "1.0.131",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <section :class="sectionClasses">
3
+ <div class="grid gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:items-start">
4
+ <div>
5
+ <h3 class="text-lg font-semibold">
6
+ {{ title }}
7
+ </h3>
8
+ <p v-if="help" class="mt-1 text-sm text-slate-500">
9
+ {{ help }}
10
+ </p>
11
+ <div v-if="$slots.left" class="mt-4">
12
+ <slot name="left" />
13
+ </div>
14
+ </div>
15
+
16
+ <div class="w-full" :style="contentStyles">
17
+ <slot />
18
+ </div>
19
+ </div>
20
+ </section>
21
+ </template>
22
+
23
+ <script>
24
+ export default {
25
+ name: 'kFormSection',
26
+ props: {
27
+ title: {
28
+ type: String,
29
+ required: true,
30
+ },
31
+ help: {
32
+ type: String,
33
+ default: '',
34
+ },
35
+ borderTop: {
36
+ type: Boolean,
37
+ default: false,
38
+ },
39
+ contentMaxWidth: {
40
+ type: String,
41
+ default: '56rem',
42
+ },
43
+ },
44
+ computed: {
45
+ sectionClasses() {
46
+ return this.borderTop ? 'border-t border-slate-200 pt-8' : ''
47
+ },
48
+ contentStyles() {
49
+ return {
50
+ maxWidth: this.contentMaxWidth,
51
+ }
52
+ },
53
+ },
54
+ }
55
+ </script>
@@ -5,8 +5,16 @@
5
5
  class="sticky z-30 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur sm:px-6 lg:px-8"
6
6
  :style="{ top: resolvedHeaderExtraTop }"
7
7
  >
8
- <div class="mx-auto flex w-full max-w-none items-center">
9
- <slot name="header-extra" />
8
+ <div class="mx-auto w-full max-w-none py-1">
9
+ <kToolbar
10
+ v-if="hasActions"
11
+ :actions="actions"
12
+ dense
13
+ variant="plain"
14
+ />
15
+ <div v-if="$slots['header-extra']" class="flex items-center">
16
+ <slot name="header-extra" />
17
+ </div>
10
18
  </div>
11
19
  </div>
12
20
 
@@ -49,8 +57,16 @@
49
57
  class="sticky z-30 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur sm:px-6 lg:px-8"
50
58
  :style="{ top: resolvedHeaderExtraTop }"
51
59
  >
52
- <div class="mx-auto flex w-full max-w-none items-center">
53
- <slot name="header-extra" />
60
+ <div class="mx-auto w-full max-w-none py-1">
61
+ <kToolbar
62
+ v-if="hasActions"
63
+ :actions="actions"
64
+ dense
65
+ variant="plain"
66
+ />
67
+ <div v-if="$slots['header-extra']" class="flex items-center">
68
+ <slot name="header-extra" />
69
+ </div>
54
70
  </div>
55
71
  </div>
56
72
 
@@ -65,10 +81,11 @@
65
81
  <script>
66
82
  import packageJson from '../../package.json'
67
83
  import kButton from '../ui/kButton.vue'
84
+ import kToolbar from '../ui/kToolbar.vue'
68
85
 
69
86
  export default {
70
87
  name: 'PageShell',
71
- components: { kButton },
88
+ components: { kButton, kToolbar },
72
89
  props: {
73
90
  appTitle: {
74
91
  type: String,
@@ -86,6 +103,10 @@ export default {
86
103
  type: String,
87
104
  default: '',
88
105
  },
106
+ actions: {
107
+ type: Array,
108
+ default: () => [],
109
+ },
89
110
  headerExtraTop: {
90
111
  type: String,
91
112
  default: '0px',
@@ -104,11 +125,14 @@ export default {
104
125
  this.$slots['header-actions']
105
126
  )
106
127
  },
128
+ hasActions() {
129
+ return Array.isArray(this.actions) && this.actions.length > 0
130
+ },
107
131
  showHeaderExtraBeforeTitle() {
108
- return this.headerExtraBeforeTitle && Boolean(this.$slots['header-extra'])
132
+ return this.headerExtraBeforeTitle && (Boolean(this.$slots['header-extra']) || this.hasActions)
109
133
  },
110
134
  showHeaderExtraAfterTitle() {
111
- return !this.headerExtraBeforeTitle && Boolean(this.$slots['header-extra'])
135
+ return !this.headerExtraBeforeTitle && (Boolean(this.$slots['header-extra']) || this.hasActions)
112
136
  },
113
137
  resolvedHeaderExtraTop() {
114
138
  return this.hasTopSection ? this.headerExtraTop : '0px'
@@ -48,11 +48,19 @@
48
48
  </section>
49
49
 
50
50
  <div
51
- v-if="$slots['header-extra']"
51
+ v-if="$slots['header-extra'] || hasActions"
52
52
  class="shrink-0 border-b border-t border-slate-200 bg-slate-50 px-4 backdrop-blur"
53
53
  >
54
- <div class="mx-auto flex w-full max-w-none items-center">
55
- <slot name="header-extra" />
54
+ <div class="mx-auto w-full max-w-none py-1">
55
+ <kToolbar
56
+ v-if="hasActions"
57
+ :actions="actions"
58
+ dense
59
+ variant="plain"
60
+ />
61
+ <div v-if="$slots['header-extra']" class="flex items-center">
62
+ <slot name="header-extra" />
63
+ </div>
56
64
  </div>
57
65
  </div>
58
66
 
@@ -135,6 +143,7 @@
135
143
  import packageJson from '../../package.json'
136
144
  import kButton from '../ui/kButton.vue'
137
145
  import kIcon from '../ui/kIcon.vue'
146
+ import kToolbar from '../ui/kToolbar.vue'
138
147
 
139
148
  const LG_VIEWPORT_QUERY = '(min-width: 1024px)'
140
149
  const MAIN_MENU_TOGGLE_EVENT = 'ketekny:two-col-layout-mobile-menu'
@@ -144,7 +153,7 @@ const MOBILE_SWIPE_VERTICAL_TOLERANCE = 48
144
153
 
145
154
  export default {
146
155
  name: 'MultiColPage',
147
- components: { kButton, kIcon },
156
+ components: { kButton, kIcon, kToolbar },
148
157
  props: {
149
158
  appTitle: {
150
159
  type: String,
@@ -162,6 +171,10 @@ export default {
162
171
  type: String,
163
172
  default: '',
164
173
  },
174
+ actions: {
175
+ type: Array,
176
+ default: () => [],
177
+ },
165
178
  sidebarWidth: {
166
179
  type: String,
167
180
  default: '300px',
@@ -234,6 +247,9 @@ export default {
234
247
  hasRightSidebar() {
235
248
  return Boolean(this.$slots['sidebar-right'])
236
249
  },
250
+ hasActions() {
251
+ return Array.isArray(this.actions) && this.actions.length > 0
252
+ },
237
253
  effectiveSidebarLeftWidth() {
238
254
  return this.sidebarLeftWidth || this.sidebarWidth || '300px'
239
255
  },
@@ -487,7 +487,7 @@ export default {
487
487
 
488
488
  <template>
489
489
  <aside
490
- 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"
490
+ 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-transform duration-200 ease-out lg:static lg:translate-x-0"
491
491
  :style="sidebarWidthStyle"
492
492
  :class="[
493
493
  themeClass,
@@ -634,7 +634,7 @@ export default {
634
634
  />
635
635
  </ul>
636
636
  <p
637
- v-if="!collapsed && displayedMenuItems.length === 0"
637
+ v-if="!collapsed && displayedMenuItems.length === 0 && (query.trim() || !$slots['sidebar-panel'])"
638
638
  class="px-3 py-6 text-center text-[var(--sidebar-text-muted)]"
639
639
  >
640
640
  Δεν βρέθηκαν αποτελέσματα.
@@ -77,7 +77,7 @@
77
77
  </div>
78
78
 
79
79
  <pre class="p-4 overflow-x-auto rounded-lg text-[11px] leading-5 cp-pre">
80
- <code class="font-mono text-[11px]" v-html="highlightedCode"></code>
80
+ <code class="font-mono text-[11px]">{{ code.trim() }}</code>
81
81
  </pre>
82
82
  </div>
83
83
  </div>
@@ -85,11 +85,6 @@
85
85
  </template>
86
86
 
87
87
  <script>
88
- import hljs from "highlight.js/lib/core";
89
- import xml from "highlight.js/lib/languages/xml";
90
-
91
- hljs.registerLanguage("xml", xml);
92
-
93
88
  export default {
94
89
  name: "ComponentShowcase",
95
90
  props: {
@@ -113,14 +108,6 @@ export default {
113
108
  };
114
109
  },
115
110
  computed: {
116
- highlightedCode() {
117
- if (!this.code) return "";
118
- try {
119
- return hljs.highlight(this.code.trim(), { language: "xml" }).value;
120
- } catch {
121
- return this.escapeHtml(this.code.trim());
122
- }
123
- },
124
111
  previewViewportClass() {
125
112
  if (this.activeViewport === "mobile") return "max-w-[430px]";
126
113
  if (this.activeViewport === "tablet") return "max-w-[820px]";
@@ -137,11 +124,6 @@ export default {
137
124
  console.error("Failed to copy code:", err);
138
125
  }
139
126
  },
140
- escapeHtml(text) {
141
- const div = document.createElement("div");
142
- div.textContent = text;
143
- return div.innerHTML;
144
- },
145
127
  },
146
128
  };
147
129
  </script>
@@ -0,0 +1,51 @@
1
+ <template>
2
+ <article class="overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm">
3
+ <header
4
+ v-if="hasHeader"
5
+ class="border-b border-slate-200 px-5 py-4"
6
+ >
7
+ <slot name="header">
8
+ <div>
9
+ <p v-if="title" class="text-sm font-semibold text-slate-900">
10
+ {{ title }}
11
+ </p>
12
+ <p v-if="subtitle" :class="title ? 'mt-1 text-sm text-slate-500' : 'text-sm text-slate-500'">
13
+ {{ subtitle }}
14
+ </p>
15
+ </div>
16
+ </slot>
17
+ </header>
18
+
19
+ <div class="px-5 py-4">
20
+ <slot />
21
+ </div>
22
+
23
+ <footer
24
+ v-if="$slots.footer"
25
+ class="border-t border-slate-200 px-5 py-4"
26
+ >
27
+ <slot name="footer" />
28
+ </footer>
29
+ </article>
30
+ </template>
31
+
32
+ <script>
33
+ export default {
34
+ name: 'kCard',
35
+ props: {
36
+ title: {
37
+ type: String,
38
+ default: '',
39
+ },
40
+ subtitle: {
41
+ type: String,
42
+ default: '',
43
+ },
44
+ },
45
+ computed: {
46
+ hasHeader() {
47
+ return Boolean(this.$slots.header || this.title || this.subtitle)
48
+ },
49
+ },
50
+ }
51
+ </script>