dxd-style-code 0.1.11 → 0.1.13
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/dist/dxd-style-code.js +7470 -6336
- package/dist/dxd-style-code.umd.cjs +3 -3
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/components/atoms/DX/DX.stories.js +265 -0
- package/src/components/atoms/DX/DX.vue +80 -0
- package/src/components/atoms/DX/index.js +2 -0
- package/src/components/atoms/DXAvatar/DXAvatar.stories.js +1 -2
- package/src/components/atoms/DXBackdrop/DXBackdrop.stories.js +77 -1
- package/src/components/atoms/DXBadge/DXBadge.stories.js +83 -1
- package/src/components/atoms/DXBlockquote/DXBlockquote.stories.js +67 -1
- package/src/components/atoms/DXBox/DXBox.stories.js +1 -1
- package/src/components/atoms/DXBox/DXBox.vue +69 -2
- package/src/components/atoms/DXButton/DXButton.stories.js +94 -1
- package/src/components/atoms/DXButton/DXButton.vue +145 -11
- package/src/components/atoms/DXCard/DXCard.stories.js +72 -14
- package/src/components/atoms/DXCard/DXCard.vue +3 -4
- package/src/components/atoms/DXCheckbox/DXCheckbox.stories.js +85 -1
- package/src/components/atoms/DXCode/DXCode.stories.js +67 -1
- package/src/components/atoms/DXContainer/DXContainer.stories.js +1 -1
- package/src/components/atoms/DXContainer/DXContainer.vue +28 -1
- package/src/components/atoms/DXDivider/DXDivider.stories.js +84 -1
- package/src/components/atoms/DXFlex/DXFlex.stories.js +1 -1
- package/src/components/atoms/DXFlex/DXFlex.vue +57 -3
- package/src/components/atoms/DXFormLabel/DXFormLabel.stories.js +70 -1
- package/src/components/atoms/DXGrid/DXGrid.stories.js +1 -1
- package/src/components/atoms/DXHeading/DXHeading.stories.js +90 -1
- package/src/components/atoms/DXIcon/DXIcon.stories.js +74 -0
- package/src/components/atoms/DXIconWrapper/DXIconWrapper.stories.js +69 -0
- package/src/components/atoms/DXImage/DXImage.stories.js +483 -0
- package/src/components/atoms/DXImage/DXImage.vue +294 -0
- package/src/components/atoms/DXImage/index.js +2 -0
- package/src/components/atoms/DXInputAddon/DXInputAddon.stories.js +86 -1
- package/src/components/atoms/DXLabel/DXLabel.stories.js +62 -1
- package/src/components/atoms/DXLink/DXLink.stories.js +75 -10
- package/src/components/atoms/DXLink/DXLink.vue +59 -3
- package/src/components/atoms/DXList/DXList.stories.js +76 -1
- package/src/components/atoms/DXLoader/DXLoader.stories.js +75 -1
- package/src/components/atoms/DXNav/DXNav.stories.js +236 -0
- package/src/components/atoms/DXNav/DXNav.vue +114 -0
- package/src/components/atoms/DXNav/index.js +2 -0
- package/src/components/atoms/DXProgress/DXProgress.stories.js +76 -1
- package/src/components/atoms/DXRadio/DXRadio.stories.js +85 -1
- package/src/components/atoms/DXSkeleton/DXSkeleton.stories.js +59 -1
- package/src/components/atoms/DXSlider/DXSlider.stories.js +89 -0
- package/src/components/atoms/DXSpacer/DXSpacer.stories.js +1 -1
- package/src/components/atoms/DXStack/DXStack.stories.js +1 -1
- package/src/components/atoms/DXStack/DXStack.vue +5 -2
- package/src/components/atoms/DXTags/DXTags.stories.js +77 -0
- package/src/components/atoms/DXText/DXText.stories.js +83 -1
- package/src/components/atoms/DXToast/DXToast.stories.js +64 -1
- package/src/components/atoms/DXToggle/DXToggle.stories.js +84 -1
- package/src/components/atoms/DXToggleButton/DXToggleButton.stories.js +78 -1
- package/src/components/atoms/DXTooltip/DXTooltip.stories.js +98 -1
- package/src/components/atoms/index.js +3 -0
- package/src/components/molecules/DXActionButtons/DXActionButtons.stories.js +280 -77
- package/src/components/molecules/DXActionButtons/DXActionButtons.vue +31 -31
- package/src/components/molecules/DXAlert/DXAlert.stories.js +199 -1
- package/src/components/molecules/DXAlert/DXAlert.vue +35 -13
- package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.stories.js +125 -1
- package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.vue +22 -18
- package/src/components/molecules/DXButtonGroup/DXButtonGroup.stories.js +193 -6
- package/src/components/molecules/DXButtonGroup/DXButtonGroup.vue +39 -3
- package/src/components/molecules/DXCloseButton/DXCloseButton.stories.js +64 -1
- package/src/components/molecules/DXComboBox/DXComboBox.stories.js +66 -0
- package/src/components/molecules/DXCopyField/DXCopyField.stories.js +128 -1
- package/src/components/molecules/DXCopyField/DXCopyField.vue +60 -7
- package/src/components/molecules/DXDataFilter/DXDataFilter.vue +8 -6
- package/src/components/molecules/DXDatePicker/DXDatePicker.stories.js +58 -0
- package/src/components/molecules/DXFileUpload/DXFileUpload.stories.js +66 -0
- package/src/components/molecules/DXFilterGroup/DXFilterGroup.stories.js +61 -0
- package/src/components/molecules/DXFormControl/DXFormControl.stories.js +76 -0
- package/src/components/molecules/DXFormControl/DXFormControl.vue +9 -8
- package/src/components/molecules/DXInput/DXInput.stories.js +100 -1
- package/src/components/molecules/DXInputGroup/DXInputGroup.stories.js +89 -1
- package/src/components/molecules/DXInputMask/DXInputMask.stories.js +67 -0
- package/src/components/molecules/DXMenu/DXMenu.stories.js +111 -4
- package/src/components/molecules/DXMenu/DXMenu.vue +18 -5
- package/src/components/molecules/DXMenu/README.md +1 -1
- package/src/components/molecules/DXPagination/DXPagination.stories.js +105 -2
- package/src/components/molecules/DXPagination/DXPagination.vue +18 -33
- package/src/components/molecules/DXPasswordInput/DXPasswordInput.stories.js +67 -1
- package/src/components/molecules/DXRadioCard/DXRadioCard.stories.js +64 -0
- package/src/components/molecules/DXRadioGroup/DXRadioGroup.stories.js +84 -0
- package/src/components/molecules/DXRating/DXRating.stories.js +3 -2
- package/src/components/molecules/DXSearchBar/DXSearchBar.stories.js +1 -1
- package/src/components/molecules/DXSearchBar/DXSearchBar.vue +16 -12
- package/src/components/molecules/DXSearchSelect/DXSearchSelect.stories.js +71 -0
- package/src/components/molecules/DXSegmentedControl/DXSegmentedControl.stories.js +74 -0
- package/src/components/molecules/DXSelect/DXSelect.stories.js +92 -1
- package/src/components/molecules/DXStatCard/DXStatCard.stories.js +1 -1
- package/src/components/molecules/DXStatCard/DXStatCard.vue +30 -26
- package/src/components/molecules/DXTableFiltersPanel/index.js +3 -0
- package/src/components/molecules/DXTablePagination/DXTablePagination.stories.js +67 -0
- package/src/components/molecules/DXTableToolbar/DXTableToolbar.stories.js +71 -0
- package/src/components/molecules/DXTextarea/DXTextarea.stories.js +87 -1
- package/src/components/molecules/DXTimePicker/DXTimePicker.stories.js +1 -1
- package/src/components/molecules/DXValidationIcon/DXValidationIcon.stories.js +59 -1
- package/src/components/molecules/index.js +0 -1
- package/src/components/organisms/DXAccordion/DXAccordion.stories.js +75 -0
- package/src/components/organisms/DXAppLayout/DXAppLayout.stories.js +27 -25
- package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.stories.js +0 -2
- package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.vue +5 -8
- package/src/components/{molecules → organisms}/DXBaseTable/DXBaseTable.stories.js +78 -1
- package/src/components/{molecules → organisms}/DXBaseTable/DXBaseTable.vue +2 -2
- package/src/components/organisms/DXChartContainer/DXChartContainer.stories.js +1 -1
- package/src/components/organisms/DXChartContainer/DXChartContainer.vue +10 -6
- package/src/components/organisms/DXChatInterface/DXChatInterface.stories.js +1 -1
- package/src/components/organisms/DXChatInterface/DXChatInterface.vue +6 -4
- package/src/components/organisms/DXCommentSection/DXCommentSection.stories.js +1 -1
- package/src/components/organisms/DXCommentSection/DXCommentSection.vue +7 -6
- package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.stories.js +1 -1
- package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.vue +4 -2
- package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.stories.js +1 -1
- package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.vue +3 -2
- package/src/components/organisms/DXDataTable/DXDataTable.stories.js +1 -1
- package/src/components/organisms/DXDropdown/DXDropdown.stories.js +84 -1
- package/src/components/organisms/DXEmptyState/DXEmptyState.stories.js +64 -0
- package/src/components/organisms/DXEmptyState/DXEmptyState.vue +4 -2
- package/src/components/organisms/DXHeaderBar/DXHeaderBar.stories.js +409 -3
- package/src/components/organisms/DXHeaderBar/DXHeaderBar.vue +261 -52
- package/src/components/organisms/DXMediaGallery/DXMediaGallery.stories.js +1 -1
- package/src/components/organisms/DXMediaGallery/DXMediaGallery.vue +6 -4
- package/src/components/organisms/DXModal/DXModal.stories.js +93 -1
- package/src/components/organisms/DXModal/DXModal.vue +3 -2
- package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.stories.js +1 -1
- package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.vue +2 -1
- package/src/components/organisms/DXReportGenerator/DXReportGenerator.vue +4 -3
- package/src/components/organisms/DXSettingsPanel/DXSettingsPanel.vue +11 -8
- package/src/components/organisms/DXSidebar/DXSidebar.stories.js +1 -1
- package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.stories.js +104 -1
- package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.vue +14 -4
- package/src/components/organisms/DXSidebarMenu/README.md +3 -3
- package/src/components/organisms/DXTable/DXTable.stories.js +138 -11
- package/src/components/organisms/DXTable/DXTable.vue +1 -1
- package/src/components/organisms/DXTabs/DXTabs.stories.js +91 -1
- package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.stories.js +1 -1
- package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.vue +20 -18
- package/src/components/organisms/index.js +1 -0
- package/src/components/utilities/DXAnimatePresence/DXAnimatePresence.stories.js +1 -1
- package/src/components/utilities/DXBreakpointProvider/DXBreakpointProvider.stories.js +1 -1
- package/src/components/utilities/DXObserver/DXObserver.stories.js +1 -1
- package/src/components/utilities/DXPortal/DXPortal.stories.js +1 -1
- package/src/components/utilities/DXStaggeredAnimation/DXStaggeredAnimation.stories.js +2 -2
- package/src/components/utilities/DXThemeProvider/DXThemeProvider.stories.js +1 -1
- package/src/components/utilities/DXTransitionGroup/DXTransitionGroup.stories.js +1 -1
- package/src/composables/useSize.js +8 -1
- /package/src/components/{molecules → organisms}/DXBaseTable/index.js +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<component
|
|
3
3
|
:is="componentTag"
|
|
4
4
|
:type="componentTag === 'button' ? type : undefined"
|
|
5
|
-
:disabled="
|
|
5
|
+
:disabled="effectiveDisabled"
|
|
6
6
|
:to="to"
|
|
7
7
|
:href="href"
|
|
8
8
|
:target="target"
|
|
@@ -10,17 +10,19 @@
|
|
|
10
10
|
:class="allClasses"
|
|
11
11
|
data-component="DXButton"
|
|
12
12
|
:data-variant="variant"
|
|
13
|
-
:data-size="
|
|
14
|
-
:data-disabled="
|
|
13
|
+
:data-size="effectiveSize"
|
|
14
|
+
:data-disabled="effectiveDisabled"
|
|
15
15
|
:data-icon-only="iconOnly"
|
|
16
16
|
:data-block="block"
|
|
17
|
+
:data-in-group="!!buttonGroup"
|
|
18
|
+
@click="handleClick"
|
|
17
19
|
>
|
|
18
20
|
<slot />
|
|
19
21
|
</component>
|
|
20
22
|
</template>
|
|
21
23
|
|
|
22
24
|
<script setup>
|
|
23
|
-
import { computed } from "vue";
|
|
25
|
+
import { computed, inject, onMounted, onUnmounted } from "vue";
|
|
24
26
|
import { useSize } from "../../../composables/useSize";
|
|
25
27
|
import { useVariantButton } from "../../../composables/useVariant";
|
|
26
28
|
import { useClassComposition } from "../../../composables/useClassComposition";
|
|
@@ -46,6 +48,60 @@ const props = defineProps({
|
|
|
46
48
|
target: { type: String, default: null },
|
|
47
49
|
/** Rel для ссылки */
|
|
48
50
|
rel: { type: String, default: null },
|
|
51
|
+
/** Значение для использования в DXButtonGroup */
|
|
52
|
+
value: { type: [String, Number], default: null },
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const buttonGroup = inject("buttonGroup", null);
|
|
56
|
+
|
|
57
|
+
// Генерируем уникальный ID для регистрации
|
|
58
|
+
const componentId = Date.now() + Math.random();
|
|
59
|
+
|
|
60
|
+
onMounted(() => {
|
|
61
|
+
if (buttonGroup?.registerComponent) {
|
|
62
|
+
buttonGroup.registerComponent('button', componentId);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
onUnmounted(() => {
|
|
67
|
+
if (buttonGroup?.unregisterComponent) {
|
|
68
|
+
buttonGroup.unregisterComponent(componentId);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Получаем информацию о позиции кнопки в группе
|
|
73
|
+
const buttonPosition = computed(() => {
|
|
74
|
+
if (!buttonGroup?.getComponentPosition) {
|
|
75
|
+
return { isFirst: false, isLast: false, isMiddle: false };
|
|
76
|
+
}
|
|
77
|
+
return buttonGroup.getComponentPosition(componentId);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Эффективный размер: используем размер группы, если кнопка в группе
|
|
81
|
+
const effectiveSize = computed(() => {
|
|
82
|
+
if (buttonGroup) {
|
|
83
|
+
// Маппинг размеров группы на размеры кнопки
|
|
84
|
+
const sizeMap = {
|
|
85
|
+
sm: 'sm',
|
|
86
|
+
md: 'md',
|
|
87
|
+
lg: 'lg',
|
|
88
|
+
};
|
|
89
|
+
return sizeMap[buttonGroup.size] || 'md';
|
|
90
|
+
}
|
|
91
|
+
return props.size;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Эффективное состояние disabled: учитываем состояние группы
|
|
95
|
+
const effectiveDisabled = computed(() => {
|
|
96
|
+
return props.disabled || (buttonGroup?.disabled ?? false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Проверяем, выбрана ли кнопка
|
|
100
|
+
const isSelected = computed(() => {
|
|
101
|
+
if (!buttonGroup || props.value === null || props.value === undefined) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return buttonGroup.isSelected(props.value);
|
|
49
105
|
});
|
|
50
106
|
|
|
51
107
|
const BASE_CLASSES = "btn group inline-flex items-center justify-center gap-2 rounded-xl font-semibold transition focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-60";
|
|
@@ -63,22 +119,100 @@ const componentTag = computed(() => {
|
|
|
63
119
|
* Классы размера
|
|
64
120
|
*/
|
|
65
121
|
const sizeClass = computed(() => {
|
|
66
|
-
|
|
122
|
+
if (buttonGroup && !props.iconOnly) {
|
|
123
|
+
// В группе используем только padding и размер текста, высоту контролирует группа
|
|
124
|
+
const fullSizeClass = useSize(effectiveSize.value, 'button');
|
|
125
|
+
// Извлекаем только padding и text размер, убираем height
|
|
126
|
+
return fullSizeClass.replace(/\bh-\d+\b/g, '').trim();
|
|
127
|
+
}
|
|
128
|
+
return useSize(effectiveSize.value, props.iconOnly ? 'buttonIcon' : 'button');
|
|
67
129
|
});
|
|
68
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Классы border-radius для кнопки в группе
|
|
133
|
+
*/
|
|
134
|
+
const getBorderRadiusClasses = () => {
|
|
135
|
+
if (!buttonGroup) {
|
|
136
|
+
return 'rounded-xl';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (buttonPosition.value.isFirst) {
|
|
140
|
+
return 'rounded-l-xl rounded-r-none';
|
|
141
|
+
} else if (buttonPosition.value.isLast) {
|
|
142
|
+
return 'rounded-l-none rounded-r-xl';
|
|
143
|
+
} else {
|
|
144
|
+
return 'rounded-none';
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Обработчик клика
|
|
150
|
+
*/
|
|
151
|
+
const handleClick = (event) => {
|
|
152
|
+
// Если кнопка в группе и имеет value, обрабатываем через группу
|
|
153
|
+
if (buttonGroup && props.value !== null && props.value !== undefined) {
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
event.stopPropagation();
|
|
156
|
+
buttonGroup.handleSelect(props.value);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Если это router-link или обычная ссылка, не предотвращаем стандартное поведение
|
|
161
|
+
if (props.to || props.href) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Для обычной кнопки стандартное поведение
|
|
166
|
+
};
|
|
167
|
+
|
|
69
168
|
/**
|
|
70
169
|
* Все классы для кнопки
|
|
71
170
|
*/
|
|
72
|
-
const allClasses = computed(() =>
|
|
73
|
-
|
|
74
|
-
BASE_CLASSES,
|
|
75
|
-
|
|
171
|
+
const allClasses = computed(() => {
|
|
172
|
+
const baseClasses = buttonGroup
|
|
173
|
+
? BASE_CLASSES.replace('rounded-xl', getBorderRadiusClasses())
|
|
174
|
+
: BASE_CLASSES;
|
|
175
|
+
|
|
176
|
+
// В группе: выбранная кнопка - темная, невыбранная - светлая
|
|
177
|
+
// Вне группы: используем стандартные варианты
|
|
178
|
+
let variantClasses;
|
|
179
|
+
if (buttonGroup) {
|
|
180
|
+
if (isSelected.value) {
|
|
181
|
+
variantClasses = 'bg-slate-900 text-white hover:bg-slate-800';
|
|
182
|
+
} else {
|
|
183
|
+
variantClasses = 'bg-white text-slate-700 hover:bg-slate-50';
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
variantClasses = useVariantButton(props.variant);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Классы для разделителей в группе
|
|
190
|
+
const dividerClasses = computed(() => {
|
|
191
|
+
if (!buttonGroup) return {};
|
|
192
|
+
// divide-x добавляет border-left ко всем элементам кроме первого
|
|
193
|
+
// Но для надежности добавляем явно
|
|
194
|
+
return {
|
|
195
|
+
'border-l border-slate-200': !buttonPosition.value.isFirst,
|
|
196
|
+
};
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return useClassComposition(
|
|
200
|
+
baseClasses,
|
|
201
|
+
variantClasses,
|
|
76
202
|
sizeClass.value,
|
|
77
203
|
{
|
|
78
204
|
'w-full': props.block,
|
|
79
205
|
'px-0 py-0': props.iconOnly,
|
|
206
|
+
// В группе не применяем border-0, чтобы divide-x мог добавить разделители
|
|
207
|
+
// Варианты кнопок в группе уже не содержат границ (переопределены выше)
|
|
208
|
+
// В группе высота контролируется группой
|
|
209
|
+
'h-full': buttonGroup && !props.iconOnly,
|
|
210
|
+
// В группе используем flex-1 для равномерного распределения
|
|
211
|
+
'flex-1': buttonGroup && !props.iconOnly,
|
|
212
|
+
// Явно добавляем разделители
|
|
213
|
+
...dividerClasses.value,
|
|
80
214
|
}
|
|
81
|
-
)
|
|
82
|
-
);
|
|
215
|
+
);
|
|
216
|
+
});
|
|
83
217
|
</script>
|
|
84
218
|
|
|
@@ -3,11 +3,79 @@ import DXCard from './DXCard.vue';
|
|
|
3
3
|
export default {
|
|
4
4
|
title: 'Atoms/DXCard',
|
|
5
5
|
component: DXCard,
|
|
6
|
-
tags: ['autodocs'],
|
|
6
|
+
tags: ['autodocs', 'category:data-display'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
# DXCard
|
|
12
|
+
|
|
13
|
+
Универсальный компонент карточки с различными вариантами оформления и настраиваемым padding.
|
|
14
|
+
|
|
15
|
+
## Назначение
|
|
16
|
+
|
|
17
|
+
DXCard предоставляет стандартизированный контейнер для группировки контента. Компонент поддерживает
|
|
18
|
+
различные варианты визуального оформления (bordered, elevated, flat) и гибкую систему padding для
|
|
19
|
+
создания карточек с различной плотностью контента.
|
|
20
|
+
|
|
21
|
+
## Архитектура
|
|
22
|
+
|
|
23
|
+
### Использует
|
|
24
|
+
- \`useSpacing\` composable - для унификации padding (none, xs, sm, md, lg, xl)
|
|
25
|
+
|
|
26
|
+
### Используется в
|
|
27
|
+
- \`DXStatCard\` - карточки статистики
|
|
28
|
+
- \`DXDashboardWidget\` - виджеты дашборда
|
|
29
|
+
- \`DXUserProfileCard\` - карточки профиля
|
|
30
|
+
- \`DXMenu\` - контейнеры меню
|
|
31
|
+
- Любые места, где требуется визуальное выделение контента
|
|
32
|
+
|
|
33
|
+
## Внутренняя логика
|
|
34
|
+
|
|
35
|
+
### Варианты оформления
|
|
36
|
+
- **bordered** (по умолчанию): Карточка с рамкой 2px (\`border-1 border-slate-200\`), без тени
|
|
37
|
+
- **elevated**: Карточка с большой тенью (\`shadow-lg\`) и тонкой рамкой для эффекта "плавающей" карточки
|
|
38
|
+
- **flat**: Минимальное оформление, только фон и скругление, без рамки и тени
|
|
39
|
+
|
|
40
|
+
### Система padding
|
|
41
|
+
Поддерживает 6 уровней padding через \`useSpacing\` composable:
|
|
42
|
+
- **none** - без отступов
|
|
43
|
+
- **xs** - минимальные отступы
|
|
44
|
+
- **sm** - маленькие отступы (p-3)
|
|
45
|
+
- **md** - средние отступы (p-5, по умолчанию)
|
|
46
|
+
- **lg** - большие отступы (p-8)
|
|
47
|
+
- **xl** - очень большие отступы
|
|
48
|
+
|
|
49
|
+
### Скругление
|
|
50
|
+
Все карточки имеют скругление \`rounded-2xl\` для единообразного внешнего вида.
|
|
51
|
+
|
|
52
|
+
## Особенности
|
|
53
|
+
|
|
54
|
+
### Базовые стили
|
|
55
|
+
- Белый фон (\`bg-white\`)
|
|
56
|
+
- Скругление углов (\`rounded-2xl\`)
|
|
57
|
+
- Варианты оформления через \`variant\` prop
|
|
58
|
+
|
|
59
|
+
### Гибкость контента
|
|
60
|
+
Компонент использует slot для контента, что позволяет размещать внутри любые элементы:
|
|
61
|
+
- Заголовки и текст
|
|
62
|
+
- Изображения
|
|
63
|
+
- Формы и интерактивные элементы
|
|
64
|
+
- Другие компоненты
|
|
65
|
+
|
|
66
|
+
### Использование в композиции
|
|
67
|
+
DXCard часто используется как базовый контейнер для более сложных компонентов:
|
|
68
|
+
- Карточки статистики с иконками и метриками
|
|
69
|
+
- Виджеты дашборда с графиками
|
|
70
|
+
- Карточки профиля с аватарами и информацией
|
|
71
|
+
`,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
7
75
|
argTypes: {
|
|
8
76
|
variant: {
|
|
9
77
|
control: 'select',
|
|
10
|
-
options: ['
|
|
78
|
+
options: ['bordered', 'elevated', 'flat'],
|
|
11
79
|
description: 'Card variant style'
|
|
12
80
|
},
|
|
13
81
|
padding: {
|
|
@@ -20,7 +88,7 @@ export default {
|
|
|
20
88
|
|
|
21
89
|
export const Default = {
|
|
22
90
|
args: {
|
|
23
|
-
variant: '
|
|
91
|
+
variant: 'bordered',
|
|
24
92
|
padding: 'md',
|
|
25
93
|
},
|
|
26
94
|
render: (args) => ({
|
|
@@ -46,17 +114,7 @@ export const Variants = {
|
|
|
46
114
|
template: `
|
|
47
115
|
<div class="space-y-4">
|
|
48
116
|
<div>
|
|
49
|
-
<p class="text-sm font-medium text-slate-700 mb-2">
|
|
50
|
-
<DXCard variant="default">
|
|
51
|
-
<h3 class="text-lg font-semibold text-slate-900 mb-2">Default Card</h3>
|
|
52
|
-
<p class="text-sm text-slate-600">
|
|
53
|
-
Subtle border and shadow for a clean, modern look.
|
|
54
|
-
</p>
|
|
55
|
-
</DXCard>
|
|
56
|
-
</div>
|
|
57
|
-
|
|
58
|
-
<div>
|
|
59
|
-
<p class="text-sm font-medium text-slate-700 mb-2">Bordered (2px border, no shadow)</p>
|
|
117
|
+
<p class="text-sm font-medium text-slate-700 mb-2">Bordered (2px border, no shadow) - Default</p>
|
|
60
118
|
<DXCard variant="bordered">
|
|
61
119
|
<h3 class="text-lg font-semibold text-slate-900 mb-2">Bordered Card</h3>
|
|
62
120
|
<p class="text-sm text-slate-600">
|
|
@@ -14,11 +14,11 @@ import { computed } from "vue";
|
|
|
14
14
|
import { useSpacing } from "../../../composables/useSpacing";
|
|
15
15
|
|
|
16
16
|
const props = defineProps({
|
|
17
|
-
/** Вариант:
|
|
17
|
+
/** Вариант: bordered | elevated | flat */
|
|
18
18
|
variant: {
|
|
19
19
|
type: String,
|
|
20
|
-
default: "
|
|
21
|
-
validator: (value) => ['
|
|
20
|
+
default: "bordered",
|
|
21
|
+
validator: (value) => ['bordered', 'elevated', 'flat'].includes(value)
|
|
22
22
|
},
|
|
23
23
|
/** Padding: none | xs | sm | md | lg | xl */
|
|
24
24
|
padding: {
|
|
@@ -31,7 +31,6 @@ const props = defineProps({
|
|
|
31
31
|
const BASE_CLASSES = "bg-white rounded-2xl";
|
|
32
32
|
|
|
33
33
|
const VARIANT_CLASSES = {
|
|
34
|
-
default: "border border-slate-100 shadow-sm",
|
|
35
34
|
bordered: "border-1 border-slate-200",
|
|
36
35
|
elevated: "shadow-lg border border-slate-50",
|
|
37
36
|
flat: "border-0",
|
|
@@ -12,7 +12,91 @@ import {
|
|
|
12
12
|
export default {
|
|
13
13
|
title: 'Atoms/DXCheckbox',
|
|
14
14
|
component: DXCheckbox,
|
|
15
|
-
tags: ['autodocs'],
|
|
15
|
+
tags: ['autodocs', 'category:form'],
|
|
16
|
+
parameters: {
|
|
17
|
+
docs: {
|
|
18
|
+
description: {
|
|
19
|
+
component: `
|
|
20
|
+
# DXCheckbox
|
|
21
|
+
|
|
22
|
+
Компонент чекбокса с поддержкой двух вариантов (нативный и кастомный), различных размеров, цветов и иконок.
|
|
23
|
+
|
|
24
|
+
## Назначение
|
|
25
|
+
|
|
26
|
+
DXCheckbox предоставляет стандартизированный чекбокс для выбора одного или нескольких значений.
|
|
27
|
+
Компонент поддерживает два варианта оформления (нативный и кастомный), различные размеры, цвета,
|
|
28
|
+
иконки и работу как с boolean значениями, так и с массивами.
|
|
29
|
+
|
|
30
|
+
## Архитектура
|
|
31
|
+
|
|
32
|
+
### Использует
|
|
33
|
+
- \`DXIcon\` - для отображения иконок в кастомном варианте
|
|
34
|
+
- \`useSize\` composable - для унификации размеров (xs, sm, md, lg, xl)
|
|
35
|
+
- \`useVariantCheckbox\` composable - для вариантов оформления кастомного чекбокса
|
|
36
|
+
- \`Transition\` - для анимации иконок
|
|
37
|
+
|
|
38
|
+
### Используется в
|
|
39
|
+
- Формы с выбором опций
|
|
40
|
+
- Списки с множественным выбором
|
|
41
|
+
- Согласия и подтверждения
|
|
42
|
+
- Фильтры и настройки
|
|
43
|
+
- Любые места, требующие выбора true/false или множественного выбора
|
|
44
|
+
|
|
45
|
+
## Внутренняя логика
|
|
46
|
+
|
|
47
|
+
### Варианты
|
|
48
|
+
- **default** (по умолчанию): Нативный HTML checkbox с кастомной стилизацией
|
|
49
|
+
- **custom**: Кастомный чекбокс с иконками и настраиваемыми цветами
|
|
50
|
+
|
|
51
|
+
### Режимы работы
|
|
52
|
+
- **Boolean режим**: При \`modelValue\` - Boolean, чекбокс работает как переключатель
|
|
53
|
+
- **Array режим**: При \`modelValue\` - Array и указан \`value\`, чекбокс добавляет/удаляет значение из массива
|
|
54
|
+
|
|
55
|
+
### Кастомный вариант
|
|
56
|
+
При \`variant="custom"\`:
|
|
57
|
+
- Поддерживает различные формы: \`square\` (квадрат), \`circle\` (круг)
|
|
58
|
+
- Поддерживает различные цвета: \`slate\`, \`primary\`, \`success\`, \`danger\`, \`warning\`, \`info\`
|
|
59
|
+
- Иконки для checked/unchecked состояний (по умолчанию CheckIcon для checked)
|
|
60
|
+
- Анимации иконок: \`none\`, \`scale\`, \`wiggle\`
|
|
61
|
+
|
|
62
|
+
### Размеры
|
|
63
|
+
Поддерживает 5 размеров:
|
|
64
|
+
- **xs** - очень маленький
|
|
65
|
+
- **sm** - маленький
|
|
66
|
+
- **md** - средний (по умолчанию)
|
|
67
|
+
- **lg** - большой
|
|
68
|
+
- **xl** - очень большой
|
|
69
|
+
|
|
70
|
+
## Особенности
|
|
71
|
+
|
|
72
|
+
### v-model
|
|
73
|
+
Полностью поддерживает двустороннее связывание через \`v-model\`:
|
|
74
|
+
- Для boolean: \`v-model="checked"\` где checked - Boolean
|
|
75
|
+
- Для массива: \`v-model="selected"\` где selected - Array, и указан \`value\` prop
|
|
76
|
+
|
|
77
|
+
### Лейбл
|
|
78
|
+
- Текст лейбла через \`label\` prop
|
|
79
|
+
- Лейбл кликабелен и переключает чекбокс
|
|
80
|
+
|
|
81
|
+
### Состояния
|
|
82
|
+
- **disabled** - отключает чекбокс
|
|
83
|
+
- **checked** - отмеченное состояние
|
|
84
|
+
- **unchecked** - неотмеченное состояние
|
|
85
|
+
|
|
86
|
+
### Доступность
|
|
87
|
+
- Нативный checkbox: полная поддержка нативной доступности
|
|
88
|
+
- Кастомный checkbox: использует \`role="checkbox"\`, \`aria-checked\`, \`aria-disabled\`
|
|
89
|
+
- Поддержка клавиатурной навигации (Space для переключения)
|
|
90
|
+
|
|
91
|
+
### Иконки
|
|
92
|
+
В кастомном варианте:
|
|
93
|
+
- **checkedIcon**: Иконка для отмеченного состояния (по умолчанию CheckIcon)
|
|
94
|
+
- **uncheckedIcon**: Иконка для неотмеченного состояния (опционально)
|
|
95
|
+
- Размер иконки автоматически адаптируется к размеру чекбокса
|
|
96
|
+
`,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
16
100
|
argTypes: {
|
|
17
101
|
variant: {
|
|
18
102
|
control: 'select',
|
|
@@ -3,7 +3,73 @@ import DXCode from './DXCode.vue';
|
|
|
3
3
|
export default {
|
|
4
4
|
title: 'Atoms/DXCode',
|
|
5
5
|
component: DXCode,
|
|
6
|
-
tags: ['autodocs'],
|
|
6
|
+
tags: ['autodocs', 'category:typography'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
# DXCode
|
|
12
|
+
|
|
13
|
+
Компонент для отображения кода с поддержкой inline и block режимов.
|
|
14
|
+
|
|
15
|
+
## Назначение
|
|
16
|
+
|
|
17
|
+
DXCode предоставляет стандартизированный способ отображения кода в документации, статьях и интерфейсах.
|
|
18
|
+
Компонент поддерживает два режима: inline (для кода внутри текста) и block (для блоков кода).
|
|
19
|
+
|
|
20
|
+
## Архитектура
|
|
21
|
+
|
|
22
|
+
### Использует
|
|
23
|
+
- Динамический рендеринг HTML тегов - для семантической правильности
|
|
24
|
+
|
|
25
|
+
### Используется в
|
|
26
|
+
- Документация и статьи
|
|
27
|
+
- Примеры кода
|
|
28
|
+
- Технические описания
|
|
29
|
+
- Любые места, требующие отображения кода
|
|
30
|
+
|
|
31
|
+
## Внутренняя логика
|
|
32
|
+
|
|
33
|
+
### Режимы
|
|
34
|
+
- **inline** (по умолчанию): Код внутри текста, использует \`<code>\` тег
|
|
35
|
+
- **block**: Блок кода, использует \`<pre><code>\` теги
|
|
36
|
+
|
|
37
|
+
### Размеры
|
|
38
|
+
Поддерживает 3 размера:
|
|
39
|
+
- **xs** - очень маленький текст
|
|
40
|
+
- **sm** - маленький текст (по умолчанию)
|
|
41
|
+
- **md** - средний текст
|
|
42
|
+
|
|
43
|
+
### Визуальное оформление
|
|
44
|
+
- **inline**: Светлый фон (bg-slate-100), темный текст, небольшой padding
|
|
45
|
+
- **block**: Темный фон (bg-slate-900), светлый текст, padding, скругление, прокрутка при переполнении
|
|
46
|
+
|
|
47
|
+
## Особенности
|
|
48
|
+
|
|
49
|
+
### Inline режим
|
|
50
|
+
Используется для кода внутри текста:
|
|
51
|
+
\`\`\`vue
|
|
52
|
+
<DXCode>npm install</DXCode>
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
### Block режим
|
|
56
|
+
Используется для блоков кода:
|
|
57
|
+
\`\`\`vue
|
|
58
|
+
<DXCode block>
|
|
59
|
+
const greeting = "Hello World";
|
|
60
|
+
console.log(greeting);
|
|
61
|
+
</DXCode>
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
### Моноширинный шрифт
|
|
65
|
+
Всегда использует моноширинный шрифт (\`font-mono\`) для правильного отображения кода.
|
|
66
|
+
|
|
67
|
+
### Прокрутка
|
|
68
|
+
В block режиме при переполнении появляется горизонтальная прокрутка (\`overflow-x-auto\`).
|
|
69
|
+
`,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
7
73
|
};
|
|
8
74
|
|
|
9
75
|
export const Inline = {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
:data-size="size"
|
|
6
6
|
:data-padding="padding"
|
|
7
7
|
:data-center="center"
|
|
8
|
+
:data-position="position"
|
|
8
9
|
>
|
|
9
10
|
<slot />
|
|
10
11
|
</div>
|
|
@@ -22,6 +23,8 @@ const props = defineProps({
|
|
|
22
23
|
center: { type: Boolean, default: true },
|
|
23
24
|
/** Горизонтальные отступы: none | xs | sm | md | lg | xl */
|
|
24
25
|
padding: { type: String, default: "md" },
|
|
26
|
+
/** Позиционирование: static | relative | absolute | fixed | sticky */
|
|
27
|
+
position: { type: String, default: null },
|
|
25
28
|
});
|
|
26
29
|
|
|
27
30
|
const BASE_CLASSES = "w-full";
|
|
@@ -60,11 +63,34 @@ const paddingClass = computed(() => {
|
|
|
60
63
|
return useSpacing(props.padding, 'paddingX');
|
|
61
64
|
});
|
|
62
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Классы позиционирования
|
|
68
|
+
*
|
|
69
|
+
* @description
|
|
70
|
+
* Определяет CSS position для контейнера.
|
|
71
|
+
* Используется для создания контекста позиционирования для абсолютно позиционированных дочерних элементов.
|
|
72
|
+
*
|
|
73
|
+
* @returns {string|null} Tailwind CSS класс для позиционирования или null
|
|
74
|
+
*/
|
|
75
|
+
const positionClass = computed(() => {
|
|
76
|
+
if (!props.position) return null;
|
|
77
|
+
|
|
78
|
+
const positionClasses = {
|
|
79
|
+
static: "static",
|
|
80
|
+
relative: "relative",
|
|
81
|
+
absolute: "absolute",
|
|
82
|
+
fixed: "fixed",
|
|
83
|
+
sticky: "sticky",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return positionClasses[props.position] || null;
|
|
87
|
+
});
|
|
88
|
+
|
|
63
89
|
/**
|
|
64
90
|
* Все классы для контейнера
|
|
65
91
|
*
|
|
66
92
|
* @description
|
|
67
|
-
* Объединяет базовые классы, размер,
|
|
93
|
+
* Объединяет базовые классы, размер, отступы, центрирование и позиционирование
|
|
68
94
|
* с использованием useClassComposition для единообразного подхода.
|
|
69
95
|
*
|
|
70
96
|
* @returns {Array} Массив классов для применения к элементу
|
|
@@ -74,6 +100,7 @@ const containerClasses = computed(() =>
|
|
|
74
100
|
BASE_CLASSES,
|
|
75
101
|
sizeClass.value,
|
|
76
102
|
paddingClass.value,
|
|
103
|
+
positionClass.value,
|
|
77
104
|
{
|
|
78
105
|
"mx-auto": props.center,
|
|
79
106
|
}
|
|
@@ -3,7 +3,90 @@ import DXDivider from './DXDivider.vue';
|
|
|
3
3
|
export default {
|
|
4
4
|
title: 'Atoms/DXDivider',
|
|
5
5
|
component: DXDivider,
|
|
6
|
-
tags: ['autodocs'],
|
|
6
|
+
tags: ['autodocs', 'category:feedback'],
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: `
|
|
11
|
+
# DXDivider
|
|
12
|
+
|
|
13
|
+
Компонент разделителя для визуального разделения контента с поддержкой горизонтальной и вертикальной ориентации.
|
|
14
|
+
|
|
15
|
+
## Назначение
|
|
16
|
+
|
|
17
|
+
DXDivider предоставляет стандартизированный способ визуального разделения контента на странице.
|
|
18
|
+
Компонент поддерживает горизонтальную и вертикальную ориентацию, различные цвета, толщины и отступы.
|
|
19
|
+
|
|
20
|
+
## Архитектура
|
|
21
|
+
|
|
22
|
+
### Использует
|
|
23
|
+
- \`useSpacing\` composable - для унификации отступов
|
|
24
|
+
- \`useVariantDividerBorder\` composable - для вариантов границ
|
|
25
|
+
|
|
26
|
+
### Используется в
|
|
27
|
+
- Разделение секций контента
|
|
28
|
+
- Разделение элементов в списках
|
|
29
|
+
- Разделение групп в формах
|
|
30
|
+
- Любые места, требующие визуального разделения
|
|
31
|
+
|
|
32
|
+
## Внутренняя логика
|
|
33
|
+
|
|
34
|
+
### Ориентация
|
|
35
|
+
- **horizontal** (по умолчанию): Горизонтальный разделитель
|
|
36
|
+
- **vertical**: Вертикальный разделитель
|
|
37
|
+
|
|
38
|
+
### Цвета
|
|
39
|
+
Поддерживает 3 цветовых варианта:
|
|
40
|
+
- **light** - светлый цвет (для темных фонов)
|
|
41
|
+
- **default** - стандартный цвет (по умолчанию)
|
|
42
|
+
- **dark** - темный цвет (для светлых фонов)
|
|
43
|
+
|
|
44
|
+
### Толщина
|
|
45
|
+
Поддерживает 3 варианта толщины:
|
|
46
|
+
- **thin** - тонкая линия
|
|
47
|
+
- **default** - стандартная толщина (по умолчанию)
|
|
48
|
+
- **thick** - толстая линия
|
|
49
|
+
|
|
50
|
+
### Отступы
|
|
51
|
+
Поддерживает отступы через \`spacing\` prop:
|
|
52
|
+
- **none** - без отступов
|
|
53
|
+
- **xs**, **sm**, **md**, **lg**, **xl** - различные размеры отступов
|
|
54
|
+
|
|
55
|
+
### Текст в разделителе
|
|
56
|
+
Можно добавить текст в горизонтальный разделитель через default slot:
|
|
57
|
+
- Текст отображается по центру
|
|
58
|
+
- Линии автоматически размещаются по бокам
|
|
59
|
+
|
|
60
|
+
## Особенности
|
|
61
|
+
|
|
62
|
+
### Горизонтальный разделитель
|
|
63
|
+
Используется для разделения контента по вертикали:
|
|
64
|
+
\`\`\`vue
|
|
65
|
+
<div>
|
|
66
|
+
<p>Content above</p>
|
|
67
|
+
<DXDivider />
|
|
68
|
+
<p>Content below</p>
|
|
69
|
+
</div>
|
|
70
|
+
\`\`\`
|
|
71
|
+
|
|
72
|
+
### Вертикальный разделитель
|
|
73
|
+
Используется для разделения контента по горизонтали:
|
|
74
|
+
\`\`\`vue
|
|
75
|
+
<div class="flex">
|
|
76
|
+
<div>Left content</div>
|
|
77
|
+
<DXDivider orientation="vertical" />
|
|
78
|
+
<div>Right content</div>
|
|
79
|
+
</div>
|
|
80
|
+
\`\`\`
|
|
81
|
+
|
|
82
|
+
### С текстом
|
|
83
|
+
\`\`\`vue
|
|
84
|
+
<DXDivider>OR</DXDivider>
|
|
85
|
+
\`\`\`
|
|
86
|
+
`,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
7
90
|
argTypes: {
|
|
8
91
|
orientation: {
|
|
9
92
|
control: { type: 'select' },
|