ketekny-ui-kit 1.0.128 → 1.0.130
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/README.md +1 -1
- package/index.js +4 -2
- package/package.json +1 -1
- package/src/layout/kFormSection.vue +55 -0
- package/src/layout/kSingleColPage.vue +31 -7
- package/src/layout/kTwoColPage.vue +56 -10
- package/src/ui/kCard.vue +51 -0
package/README.md
CHANGED
|
@@ -205,7 +205,7 @@ Components:
|
|
|
205
205
|
- `kSelectButton`, `kTags`, `kSearch`, `kArrayList`, `kList`, `kTextArea`
|
|
206
206
|
- `kDialog`, `kDrawer`
|
|
207
207
|
- `kAppHeader`, `kAppFooter`, `kAppMain`, `kHero`
|
|
208
|
-
- `kSingleColPage`, `kMultiColPage`, `
|
|
208
|
+
- `kSingleColPage`, `kMultiColPage`, `twoColLayout`, `legacyTwoColLayout`
|
|
209
209
|
|
|
210
210
|
Other exports:
|
|
211
211
|
|
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
|
@@ -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
|
|
9
|
-
<
|
|
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
|
|
53
|
-
<
|
|
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
|
|
55
|
-
<
|
|
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
|
|
|
@@ -97,11 +105,11 @@
|
|
|
97
105
|
<div class="mx-auto flex min-h-0 w-full max-w-none flex-1 gap-2">
|
|
98
106
|
<aside
|
|
99
107
|
v-if="showLeftSidebar"
|
|
100
|
-
class="min-h-0 shrink-0 overflow-y-auto bg-slate-100
|
|
101
|
-
:class="mobileSidebarClass('left')"
|
|
108
|
+
class="min-h-0 shrink-0 overflow-y-auto bg-slate-100"
|
|
109
|
+
:class="[mobileSidebarClass('left'), sidebarSurfaceClass('left')]"
|
|
102
110
|
:style="mobileSidebarStyle('left')"
|
|
103
111
|
>
|
|
104
|
-
<div v-if="effectiveSidebarLeftTitle" class="
|
|
112
|
+
<div v-if="effectiveSidebarLeftTitle" :class="sidebarTitleWrapClass('left')">
|
|
105
113
|
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-500">
|
|
106
114
|
{{ effectiveSidebarLeftTitle }}
|
|
107
115
|
</p>
|
|
@@ -115,11 +123,11 @@
|
|
|
115
123
|
</section>
|
|
116
124
|
<aside
|
|
117
125
|
v-if="showRightSidebar"
|
|
118
|
-
class="min-h-0 shrink-0 overflow-y-auto bg-slate-100
|
|
119
|
-
:class="mobileSidebarClass('right')"
|
|
126
|
+
class="min-h-0 shrink-0 overflow-y-auto bg-slate-100"
|
|
127
|
+
:class="[mobileSidebarClass('right'), sidebarSurfaceClass('right')]"
|
|
120
128
|
:style="mobileSidebarStyle('right')"
|
|
121
129
|
>
|
|
122
|
-
<div v-if="sidebarRightTitle" class="
|
|
130
|
+
<div v-if="sidebarRightTitle" :class="sidebarTitleWrapClass('right')">
|
|
123
131
|
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-500">
|
|
124
132
|
{{ sidebarRightTitle }}
|
|
125
133
|
</p>
|
|
@@ -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',
|
|
@@ -170,6 +183,14 @@ export default {
|
|
|
170
183
|
type: String,
|
|
171
184
|
default: '',
|
|
172
185
|
},
|
|
186
|
+
sidebarDense: {
|
|
187
|
+
type: Boolean,
|
|
188
|
+
default: false,
|
|
189
|
+
},
|
|
190
|
+
sidebarLeftDense: {
|
|
191
|
+
type: Boolean,
|
|
192
|
+
default: false,
|
|
193
|
+
},
|
|
173
194
|
sidebarTitle: {
|
|
174
195
|
type: String,
|
|
175
196
|
default: '',
|
|
@@ -182,6 +203,10 @@ export default {
|
|
|
182
203
|
type: String,
|
|
183
204
|
default: '',
|
|
184
205
|
},
|
|
206
|
+
sidebarRightDense: {
|
|
207
|
+
type: Boolean,
|
|
208
|
+
default: false,
|
|
209
|
+
},
|
|
185
210
|
sidebarRightTitle: {
|
|
186
211
|
type: String,
|
|
187
212
|
default: '',
|
|
@@ -222,12 +247,18 @@ export default {
|
|
|
222
247
|
hasRightSidebar() {
|
|
223
248
|
return Boolean(this.$slots['sidebar-right'])
|
|
224
249
|
},
|
|
250
|
+
hasActions() {
|
|
251
|
+
return Array.isArray(this.actions) && this.actions.length > 0
|
|
252
|
+
},
|
|
225
253
|
effectiveSidebarLeftWidth() {
|
|
226
254
|
return this.sidebarLeftWidth || this.sidebarWidth || '300px'
|
|
227
255
|
},
|
|
228
256
|
effectiveSidebarLeftTitle() {
|
|
229
257
|
return this.sidebarLeftTitle || this.sidebarTitle
|
|
230
258
|
},
|
|
259
|
+
effectiveSidebarLeftDense() {
|
|
260
|
+
return this.sidebarLeftDense || this.sidebarDense
|
|
261
|
+
},
|
|
231
262
|
effectiveSidebarRightWidth() {
|
|
232
263
|
return this.sidebarRightWidth || this.effectiveSidebarLeftWidth
|
|
233
264
|
},
|
|
@@ -286,6 +317,7 @@ export default {
|
|
|
286
317
|
return {
|
|
287
318
|
side,
|
|
288
319
|
title: side === 'right' ? this.sidebarRightTitle : this.effectiveSidebarLeftTitle,
|
|
320
|
+
dense: side === 'right' ? this.sidebarRightDense : this.effectiveSidebarLeftDense,
|
|
289
321
|
isDesktopViewport: this.isDesktopViewport,
|
|
290
322
|
mobileSidebarOpen: this.mobileSidebarOpen,
|
|
291
323
|
mobileSidebarSide: this.mobileSidebarSide,
|
|
@@ -349,6 +381,20 @@ export default {
|
|
|
349
381
|
sidebarTitleForSide(side) {
|
|
350
382
|
return side === 'right' ? this.sidebarRightTitle : this.effectiveSidebarLeftTitle
|
|
351
383
|
},
|
|
384
|
+
sidebarDenseForSide(side) {
|
|
385
|
+
return side === 'right' ? this.sidebarRightDense : this.effectiveSidebarLeftDense
|
|
386
|
+
},
|
|
387
|
+
sidebarSurfaceClass(side) {
|
|
388
|
+
if (this.sidebarDenseForSide(side)) {
|
|
389
|
+
return ''
|
|
390
|
+
}
|
|
391
|
+
return side === 'right'
|
|
392
|
+
? 'px-4 sm:px-6 lg:mr-8 lg:pl-4 lg:pr-0'
|
|
393
|
+
: 'px-4 sm:px-6 lg:ml-8 lg:pr-4 lg:pl-0'
|
|
394
|
+
},
|
|
395
|
+
sidebarTitleWrapClass(side) {
|
|
396
|
+
return this.sidebarDenseForSide(side) ? '' : 'pb-3'
|
|
397
|
+
},
|
|
352
398
|
mobileSidebarButtonLabel(side) {
|
|
353
399
|
if (this.mobileSidebarOpen && this.mobileSidebarSide === side) {
|
|
354
400
|
return 'Hide sidebar'
|
package/src/ui/kCard.vue
ADDED
|
@@ -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>
|