ketekny-ui-kit 1.0.9 → 1.0.11

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
@@ -23,6 +23,8 @@ import kTags from './src/ui/kTags.vue'
23
23
  import kSearch from './src/ui/kSearch.vue'
24
24
  import kArrayList from './src/ui/kArrayList.vue'
25
25
  import kSkeleton from './src/ui/kSkeleton.vue'
26
+ import kProgressBar from './src/ui/kProgressBar.vue'
27
+ import kTextArea from './src/ui/kTextArea.vue'
26
28
 
27
29
  // Layout Components
28
30
  import kAppHeader from './src/layout/kAppHeader.vue'
@@ -43,10 +45,10 @@ import tailwindPreset from './tailwind-preset.js'
43
45
  // Named exports (tree-shaking friendly)
44
46
  export {
45
47
  // UI Components
46
- kMessage, kCode, kToolbar, kTable, kTabs, kChip, kSpinner, kDatatable, kIcon, kMenu, kSkeleton,
48
+ kMessage, kCode, kToolbar, kTable, kTabs, kChip, kSpinner, kDatatable, kIcon, kMenu, kSkeleton, kProgressBar,
47
49
 
48
50
  // Form Components
49
- kButton, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList,
51
+ kButton, kSelect, kUploader, kToggle, kInput, kDateSelector, kEditor, kSelectButton, kTags, kSearch, kArrayList, kTextArea,
50
52
 
51
53
  // Dialogs
52
54
  kDialog, kDrawer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ketekny-ui-kit",
3
3
  "type": "module",
4
- "version": "1.0.9",
4
+ "version": "1.0.11",
5
5
  "description": "A Vue 3 UI component library with Tailwind CSS styling",
6
6
  "main": "index.js",
7
7
  "files": [
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="w-full">
3
+ <div
4
+ class="relative w-full overflow-hidden rounded-full bg-slate-200"
5
+ :style="{ height: resolvedHeight }"
6
+ role="progressbar"
7
+ :aria-valuemin="0"
8
+ :aria-valuemax="max"
9
+ :aria-valuenow="safeValue"
10
+ >
11
+ <div
12
+ class="h-full transition-all duration-300 ease-out"
13
+ :class="barClass"
14
+ :style="{ width: `${percentage}%` }"
15
+ />
16
+ <span
17
+ v-if="showValue"
18
+ class="absolute inset-0 flex items-center justify-center text-xs font-semibold text-slate-700"
19
+ >
20
+ {{ Math.round(percentage) }}%
21
+ </span>
22
+ </div>
23
+ </div>
24
+ </template>
25
+
26
+ <script>
27
+ export default {
28
+ name: 'kProgressBar',
29
+ props: {
30
+ value: { type: Number, default: 0 },
31
+ max: { type: Number, default: 100 },
32
+ height: { type: [String, Number], default: 8 },
33
+ color: {
34
+ type: String,
35
+ default: 'primary',
36
+ validator: (v) => ['primary', 'success', 'warning', 'danger', 'info'].includes(v),
37
+ },
38
+ striped: { type: Boolean, default: false },
39
+ animated: { type: Boolean, default: false },
40
+ showValue: { type: Boolean, default: false },
41
+ },
42
+ computed: {
43
+ safeMax() {
44
+ return Number(this.max) > 0 ? Number(this.max) : 100
45
+ },
46
+ safeValue() {
47
+ const inVal = Number(this.value)
48
+ if (!Number.isFinite(inVal)) return 0
49
+ return Math.min(Math.max(inVal, 0), this.safeMax)
50
+ },
51
+ percentage() {
52
+ return (this.safeValue / this.safeMax) * 100
53
+ },
54
+ resolvedHeight() {
55
+ return typeof this.height === 'number' ? `${this.height}px` : this.height
56
+ },
57
+ barClass() {
58
+ const palette = {
59
+ primary: 'bg-primary',
60
+ success: 'bg-green-600',
61
+ warning: 'bg-amber-500',
62
+ danger: 'bg-red-600',
63
+ info: 'bg-sky-600',
64
+ }
65
+ return [
66
+ palette[this.color] || palette.primary,
67
+ this.striped ? 'k-progress-striped' : '',
68
+ this.animated ? 'k-progress-animated' : '',
69
+ ]
70
+ },
71
+ },
72
+ }
73
+ </script>
74
+
75
+ <style scoped>
76
+ .k-progress-striped {
77
+ background-image: linear-gradient(
78
+ 45deg,
79
+ rgba(255, 255, 255, 0.25) 25%,
80
+ transparent 25%,
81
+ transparent 50%,
82
+ rgba(255, 255, 255, 0.25) 50%,
83
+ rgba(255, 255, 255, 0.25) 75%,
84
+ transparent 75%,
85
+ transparent
86
+ );
87
+ background-size: 1rem 1rem;
88
+ }
89
+
90
+ .k-progress-animated {
91
+ animation: k-progress-bar-stripes 0.9s linear infinite;
92
+ }
93
+
94
+ @keyframes k-progress-bar-stripes {
95
+ from {
96
+ background-position: 1rem 0;
97
+ }
98
+ to {
99
+ background-position: 0 0;
100
+ }
101
+ }
102
+ </style>
package/src/ui/kTable.vue CHANGED
@@ -115,7 +115,7 @@ export default {
115
115
  }
116
116
 
117
117
  .table-custom--card th {
118
- @apply px-6 py-4 text-xl font-semibold text-left text-white bg-primary border-b border-primary;
118
+ @apply px-6 py-4 text-lg font-semibold text-left text-white bg-primary border-b border-primary;
119
119
  }
120
120
 
121
121
  .table-custom--plain th {
@@ -127,7 +127,7 @@ export default {
127
127
  }
128
128
 
129
129
  .table-custom--card td {
130
- @apply h-[4rem] px-6 py-4 text-lg text-slate-800;
130
+ @apply h-[3.2rem] px-6 py-4 text-base text-slate-800;
131
131
  }
132
132
 
133
133
  .table-custom--plain td {
@@ -0,0 +1,116 @@
1
+ <template>
2
+ <div class="w-full">
3
+ <label
4
+ v-if="label != null"
5
+ :for="inputId"
6
+ class="inputLabel"
7
+ :class="hasError ? 'text-red-500' : 'text-gray-700'"
8
+ >
9
+ {{ label }}
10
+ </label>
11
+
12
+ <textarea
13
+ :id="inputId"
14
+ :value="computedModelValue"
15
+ @input="handleInput"
16
+ :rows="rows"
17
+ :disabled="disabled"
18
+ :placeholder="placeholder"
19
+ :autofocus="autofocus"
20
+ :class="textareaClass"
21
+ :aria-invalid="hasError ? 'true' : 'false'"
22
+ :aria-describedby="describedById"
23
+ />
24
+
25
+ <div :id="errorId" class="mt-1 text-red-500" v-if="hasError && error !== true && error !== ''">
26
+ {{ error }}
27
+ </div>
28
+
29
+ <div :id="infoId" class="mt-1 text-gray-500" v-if="info != null">
30
+ {{ info }}
31
+ </div>
32
+ </div>
33
+ </template>
34
+
35
+ <script>
36
+ export default {
37
+ name: 'kTextArea',
38
+ props: {
39
+ modelValue: [String, Number],
40
+ label: { type: String, default: null },
41
+ info: { type: String, default: null },
42
+ error: { type: [String, Boolean], default: null },
43
+ placeholder: { type: String, default: null },
44
+ disabled: { type: Boolean, default: false },
45
+ id: { type: String, default: null },
46
+ autofocus: { type: Boolean, default: false },
47
+ rows: { type: Number, default: 4 },
48
+ capsOnly: { type: Boolean, default: false },
49
+ },
50
+ data() {
51
+ return {
52
+ computedModelValue: '',
53
+ generatedId: `textarea-${Math.random().toString(36).slice(2, 11)}`,
54
+ }
55
+ },
56
+ computed: {
57
+ hasError() {
58
+ return this.error != null && this.error !== false
59
+ },
60
+ inputId() {
61
+ return this.id || this.generatedId
62
+ },
63
+ errorId() {
64
+ return `${this.inputId}-error`
65
+ },
66
+ infoId() {
67
+ return `${this.inputId}-info`
68
+ },
69
+ describedById() {
70
+ const ids = []
71
+ if (this.hasError && this.error !== true && this.error !== '') ids.push(this.errorId)
72
+ if (this.info != null) ids.push(this.infoId)
73
+ return ids.length ? ids.join(' ') : null
74
+ },
75
+ textareaClass() {
76
+ return [
77
+ 'w-full px-3 py-2 border rounded-lg transition shadow-sm focus:outline-none text-gray-700 focus:ring-0 focus:border-green-500 bg-white placeholder-gray-400',
78
+ this.hasError ? 'border-red-500 focus:ring focus:ring-red-300' : '',
79
+ this.disabled ? '!bg-gray-100 !text-gray-400 !cursor-not-allowed' : '',
80
+ ]
81
+ },
82
+ },
83
+ created() {
84
+ this.init(this.modelValue)
85
+ },
86
+ watch: {
87
+ modelValue(val) {
88
+ this.init(val)
89
+ },
90
+ },
91
+ methods: {
92
+ init(val) {
93
+ this.computedModelValue = val ?? ''
94
+ },
95
+ handleInput(event) {
96
+ let val = event.target.value
97
+
98
+ if (typeof val === 'string' && this.capsOnly) {
99
+ val = val.normalize('NFD').replace(/\p{Diacritic}/gu, '')
100
+ val = val
101
+ .replace(/[άαΆΑ]/g, 'Α')
102
+ .replace(/[έεΈΕ]/g, 'Ε')
103
+ .replace(/[ήηΉΗ]/g, 'Η')
104
+ .replace(/[ίιΊΙϊΐ]/g, 'Ι')
105
+ .replace(/[όοΌΟ]/g, 'Ο')
106
+ .replace(/[ύυΎΫΰϋ]/g, 'Υ')
107
+ .replace(/[ώωΏΩ]/g, 'Ω')
108
+ .toUpperCase()
109
+ }
110
+
111
+ this.computedModelValue = val
112
+ this.$emit('update:modelValue', val)
113
+ },
114
+ },
115
+ }
116
+ </script>