@krometra/ui-kit 0.5.0 → 0.6.1
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 +15 -3
- package/dist/ui-kit.css +1 -1
- package/dist/ui-kit.js +1441 -1349
- package/dist/ui-kit.umd.cjs +3 -3
- package/package.json +1 -1
- package/src/components/KChip.vue +102 -0
- package/src/components/KInput.vue +11 -1
- package/src/index.js +3 -2
package/package.json
CHANGED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
/**
|
|
3
|
+
* KChip — кнопка-признак в виде таблетки: выбор вариантов, фильтры, теги.
|
|
4
|
+
*
|
|
5
|
+
* v-model:pressed — нажата ли; без него чип — обычная кнопка (событие click)
|
|
6
|
+
* tone — цвет нажатого: 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | 'info'
|
|
7
|
+
* soft — подкрашен тоном и без нажатия (кнопка меню, акцент)
|
|
8
|
+
* dashed — пунктирная рамка (вторичный вариант)
|
|
9
|
+
* expanded — true/false рисует стрелку и ставит aria-expanded (чип открывает панель)
|
|
10
|
+
* marked — точка перед подписью: внутри что-то выбрано
|
|
11
|
+
* size — 'md' (по умолчанию) | 'sm'
|
|
12
|
+
* icon — семантическое имя KIcon перед подписью
|
|
13
|
+
*/
|
|
14
|
+
import { computed } from 'vue'
|
|
15
|
+
import KIcon from './KIcon.vue'
|
|
16
|
+
|
|
17
|
+
const props = defineProps({
|
|
18
|
+
pressed: { type: Boolean, default: undefined },
|
|
19
|
+
tone: { type: String, default: 'primary' },
|
|
20
|
+
soft: { type: Boolean, default: false },
|
|
21
|
+
dashed: { type: Boolean, default: false },
|
|
22
|
+
expanded: { type: Boolean, default: undefined },
|
|
23
|
+
marked: { type: Boolean, default: false },
|
|
24
|
+
size: { type: String, default: 'md' },
|
|
25
|
+
icon: { type: String, default: '' },
|
|
26
|
+
disabled: { type: Boolean, default: false },
|
|
27
|
+
})
|
|
28
|
+
const emit = defineEmits(['update:pressed', 'click'])
|
|
29
|
+
|
|
30
|
+
const toggle = computed(() => props.pressed !== undefined)
|
|
31
|
+
const menu = computed(() => props.expanded !== undefined)
|
|
32
|
+
|
|
33
|
+
function click(event) {
|
|
34
|
+
if (toggle.value) emit('update:pressed', !props.pressed)
|
|
35
|
+
emit('click', event)
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<button
|
|
41
|
+
type="button"
|
|
42
|
+
class="k-chip"
|
|
43
|
+
:class="[
|
|
44
|
+
`k-chip--${tone}`,
|
|
45
|
+
`k-chip--${size}`,
|
|
46
|
+
{ 'k-chip--on': pressed, 'k-chip--soft': soft, 'k-chip--dashed': dashed },
|
|
47
|
+
]"
|
|
48
|
+
:aria-pressed="toggle ? String(!!pressed) : undefined"
|
|
49
|
+
:aria-expanded="menu ? String(!!expanded) : undefined"
|
|
50
|
+
:disabled="disabled"
|
|
51
|
+
@click="click"
|
|
52
|
+
>
|
|
53
|
+
<span v-if="marked" class="k-chip__mark" />
|
|
54
|
+
<KIcon v-if="icon" :name="icon" :size="size === 'sm' ? 13 : 15" />
|
|
55
|
+
<span class="k-chip__label"><slot /></span>
|
|
56
|
+
<KIcon v-if="menu" :name="expanded ? 'chevron-up' : 'chevron-down'" :size="size === 'sm' ? 13 : 14" />
|
|
57
|
+
</button>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<style scoped>
|
|
61
|
+
.k-chip {
|
|
62
|
+
--tone: var(--k-primary);
|
|
63
|
+
--tone-soft: var(--k-primary-soft);
|
|
64
|
+
--tone-strong: var(--k-primary);
|
|
65
|
+
display: inline-flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: 0.35rem;
|
|
68
|
+
max-width: 100%;
|
|
69
|
+
padding: 0.25rem 0.75rem;
|
|
70
|
+
border: 1px solid var(--k-border);
|
|
71
|
+
border-radius: 999px;
|
|
72
|
+
background: transparent;
|
|
73
|
+
color: var(--k-text);
|
|
74
|
+
font: inherit;
|
|
75
|
+
font-size: 0.875rem;
|
|
76
|
+
line-height: 1.35;
|
|
77
|
+
text-align: left;
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
transition: background-color 0.12s, border-color 0.12s, color 0.12s;
|
|
80
|
+
}
|
|
81
|
+
.k-chip--sm { padding: 0.15rem 0.6rem; font-size: 0.8125rem; }
|
|
82
|
+
.k-chip__label { min-width: 0; overflow-wrap: anywhere; }
|
|
83
|
+
.k-chip__mark { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
|
|
84
|
+
.k-chip:hover:not(:disabled) { border-color: var(--k-border-strong); }
|
|
85
|
+
.k-chip:focus-visible { outline: 2px solid var(--k-primary); outline-offset: 2px; }
|
|
86
|
+
.k-chip:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
87
|
+
.k-chip--dashed { border-style: dashed; }
|
|
88
|
+
.k-chip--on,
|
|
89
|
+
.k-chip--soft { background: var(--tone-soft); border-color: var(--tone); color: var(--tone-strong); font-weight: 500; }
|
|
90
|
+
.k-chip--on:hover:not(:disabled),
|
|
91
|
+
.k-chip--soft:hover:not(:disabled) { border-color: var(--tone-strong); }
|
|
92
|
+
|
|
93
|
+
.k-chip--neutral { --tone: var(--k-border-strong); --tone-soft: var(--k-surface-muted); --tone-strong: var(--k-text); }
|
|
94
|
+
.k-chip--success { --tone: var(--k-success); --tone-soft: var(--k-success-soft); --tone-strong: var(--k-success-strong); }
|
|
95
|
+
.k-chip--warning { --tone: var(--k-warning); --tone-soft: var(--k-warning-soft); --tone-strong: var(--k-warning-strong); }
|
|
96
|
+
.k-chip--danger { --tone: var(--k-danger); --tone-soft: var(--k-danger-soft); --tone-strong: var(--k-danger-strong); }
|
|
97
|
+
.k-chip--info { --tone: var(--k-info); --tone-soft: var(--k-info-soft); --tone-strong: var(--k-info-strong); }
|
|
98
|
+
|
|
99
|
+
@media (prefers-reduced-motion: reduce) {
|
|
100
|
+
.k-chip { transition: none; }
|
|
101
|
+
}
|
|
102
|
+
</style>
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
* inputmode, min, @blur, …) прокидываются на <input>.
|
|
8
8
|
*
|
|
9
9
|
* <KInput v-model="query" label="Поиск" prefix-icon="search" :error="err" />
|
|
10
|
+
*
|
|
11
|
+
* size — 'md' (по умолчанию) | 'sm' — компактное поле внутри строки текста или таблицы
|
|
12
|
+
* inline — подпись слева от поля, а не над ним
|
|
10
13
|
*/
|
|
11
14
|
import { computed, useAttrs } from 'vue'
|
|
12
15
|
import KIcon from './KIcon.vue'
|
|
@@ -37,13 +40,15 @@ defineProps({
|
|
|
37
40
|
required: { type: Boolean, default: false },
|
|
38
41
|
disabled: { type: Boolean, default: false },
|
|
39
42
|
readonly: { type: Boolean, default: false },
|
|
43
|
+
size: { type: String, default: 'md' },
|
|
44
|
+
inline: { type: Boolean, default: false },
|
|
40
45
|
})
|
|
41
46
|
|
|
42
47
|
defineEmits(['update:modelValue'])
|
|
43
48
|
</script>
|
|
44
49
|
|
|
45
50
|
<template>
|
|
46
|
-
<label class="k-input" v-bind="rootAttrs">
|
|
51
|
+
<label class="k-input" :class="[`k-input--${size}`, { 'k-input--inline': inline }]" v-bind="rootAttrs">
|
|
47
52
|
<span v-if="label" class="k-input__label">
|
|
48
53
|
{{ label }}<span v-if="required" class="k-input__req">*</span>
|
|
49
54
|
</span>
|
|
@@ -105,4 +110,9 @@ defineEmits(['update:modelValue'])
|
|
|
105
110
|
.k-input__suffix { font-size: 0.875rem; color: var(--k-text-muted); white-space: nowrap; }
|
|
106
111
|
.k-input__hint { font-size: 0.75rem; color: var(--k-text-muted); }
|
|
107
112
|
.k-input__error { font-size: 0.75rem; color: var(--k-danger); }
|
|
113
|
+
.k-input--inline { flex-direction: row; align-items: center; gap: 0.4rem; }
|
|
114
|
+
.k-input--inline .k-input__label { white-space: nowrap; }
|
|
115
|
+
.k-input--sm .k-input__box { height: var(--k-control-h-sm); padding: 0 0.5rem; gap: 0.35rem; }
|
|
116
|
+
.k-input--sm .k-input__field { font-size: 0.8125rem; }
|
|
117
|
+
.k-input--sm .k-input__suffix { font-size: 0.8125rem; }
|
|
108
118
|
</style>
|
package/src/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import KBadge from './components/KBadge.vue'
|
|
|
22
22
|
import KButton from './components/KButton.vue'
|
|
23
23
|
import KCard from './components/KCard.vue'
|
|
24
24
|
import KCheckbox from './components/KCheckbox.vue'
|
|
25
|
+
import KChip from './components/KChip.vue'
|
|
25
26
|
import KCombobox from './components/KCombobox.vue'
|
|
26
27
|
import KCountdown from './components/KCountdown.vue'
|
|
27
28
|
import KDescriptions from './components/KDescriptions.vue'
|
|
@@ -54,7 +55,7 @@ import KToast from './components/KToast.vue'
|
|
|
54
55
|
import KTooltip from './components/KTooltip.vue'
|
|
55
56
|
|
|
56
57
|
export {
|
|
57
|
-
KAlert, KAvatar, KBadge, KButton, KCard, KCheckbox, KCombobox, KCountdown,
|
|
58
|
+
KAlert, KAvatar, KBadge, KButton, KCard, KCheckbox, KChip, KCombobox, KCountdown,
|
|
58
59
|
KDescriptions, KDrawer, KDropdown, KEmpty, KFileUpload, KFilterBar, KGantt, KIcon,
|
|
59
60
|
KInput, KMenuItem, KModal, KMoney, KPage, KPagination, KProgress,
|
|
60
61
|
KRadioGroup, KSegmented, KSelect, KShell, KStat, KSteps, KSwitch, KTable,
|
|
@@ -70,7 +71,7 @@ export { useToast, pushToast, dismissToast, toastStore } from './composables/use
|
|
|
70
71
|
export * from './format.js'
|
|
71
72
|
|
|
72
73
|
const components = {
|
|
73
|
-
KAlert, KAvatar, KBadge, KButton, KCard, KCheckbox, KCombobox, KCountdown,
|
|
74
|
+
KAlert, KAvatar, KBadge, KButton, KCard, KCheckbox, KChip, KCombobox, KCountdown,
|
|
74
75
|
KDescriptions, KDrawer, KDropdown, KEmpty, KFileUpload, KFilterBar, KGantt, KIcon,
|
|
75
76
|
KInput, KMenuItem, KModal, KMoney, KPage, KPagination, KProgress,
|
|
76
77
|
KRadioGroup, KSegmented, KSelect, KShell, KStat, KSteps, KSwitch, KTable,
|