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
|
@@ -4,99 +4,134 @@
|
|
|
4
4
|
data-component="DXHeaderBar"
|
|
5
5
|
:data-sticky="sticky"
|
|
6
6
|
:data-fixed="fixed"
|
|
7
|
+
:data-variant="variant || 'default'"
|
|
8
|
+
:data-breakpoint="currentBreakpoint?.value || null"
|
|
9
|
+
:data-mobile="isMobile"
|
|
7
10
|
>
|
|
8
|
-
<DXContainer :size="containerSize" :padding="containerPadding">
|
|
9
|
-
<
|
|
11
|
+
<DXContainer :size="containerSize" :padding="containerPadding" position="relative">
|
|
12
|
+
<DXFlex justify="between" align="center" gap="md" height="full">
|
|
10
13
|
<!-- Логотип и название -->
|
|
11
|
-
<
|
|
14
|
+
<DXFlex align="center" gap="sm" :shrink="true">
|
|
12
15
|
<DXLink
|
|
13
16
|
v-if="logo || appName"
|
|
14
17
|
:to="logoLink"
|
|
15
18
|
:href="logoHref"
|
|
16
19
|
variant="ghost"
|
|
17
|
-
class="flex items-center gap-3 hover:opacity-80 transition-opacity"
|
|
18
20
|
>
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
<DXFlex align="center" gap="sm">
|
|
22
|
+
<DXImage
|
|
23
|
+
v-if="logo"
|
|
24
|
+
:src="logo"
|
|
25
|
+
:alt="appName || 'Logo'"
|
|
26
|
+
height="32"
|
|
27
|
+
object-fit="contain"
|
|
28
|
+
/>
|
|
29
|
+
<DXHeading v-if="appName" level="1" size="lg" weight="semibold">
|
|
30
|
+
{{ appName }}
|
|
31
|
+
</DXHeading>
|
|
32
|
+
</DXFlex>
|
|
28
33
|
</DXLink>
|
|
29
34
|
<slot name="logo" />
|
|
30
|
-
</
|
|
35
|
+
</DXFlex>
|
|
31
36
|
|
|
32
37
|
<!-- Навигация (desktop) -->
|
|
33
|
-
<
|
|
38
|
+
<DXNav
|
|
34
39
|
v-if="$slots.navigation"
|
|
40
|
+
type="main"
|
|
35
41
|
class="hidden md:flex items-center gap-1 flex-1"
|
|
36
42
|
>
|
|
37
43
|
<slot name="navigation" />
|
|
38
|
-
</
|
|
44
|
+
</DXNav>
|
|
39
45
|
|
|
40
46
|
<!-- Поиск (desktop) -->
|
|
41
|
-
<
|
|
47
|
+
<DXFlex
|
|
42
48
|
v-if="$slots.search"
|
|
43
|
-
|
|
49
|
+
align="center"
|
|
50
|
+
class="hidden md:flex flex-1 max-w-md mx-4"
|
|
44
51
|
>
|
|
45
52
|
<slot name="search" />
|
|
46
|
-
</
|
|
53
|
+
</DXFlex>
|
|
47
54
|
|
|
48
55
|
<!-- Действия (desktop) -->
|
|
49
|
-
<
|
|
56
|
+
<DXFlex
|
|
50
57
|
v-if="$slots.actions"
|
|
51
|
-
|
|
58
|
+
align="center"
|
|
59
|
+
gap="sm"
|
|
60
|
+
:shrink="true"
|
|
61
|
+
class="hidden md:flex"
|
|
52
62
|
>
|
|
53
63
|
<slot name="actions" />
|
|
54
|
-
</
|
|
64
|
+
</DXFlex>
|
|
55
65
|
|
|
56
66
|
<!-- Мобильное меню -->
|
|
57
|
-
<
|
|
67
|
+
<DXFlex align="center" gap="sm" class="md:hidden">
|
|
58
68
|
<slot name="mobile-menu" />
|
|
59
|
-
</
|
|
69
|
+
</DXFlex>
|
|
70
|
+
</DXFlex>
|
|
71
|
+
|
|
72
|
+
<!-- Центральная часть - абсолютное позиционирование -->
|
|
73
|
+
<div
|
|
74
|
+
v-if="$slots.center"
|
|
75
|
+
class="hidden md:block absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
|
|
76
|
+
>
|
|
77
|
+
<slot name="center" />
|
|
60
78
|
</div>
|
|
61
79
|
</DXContainer>
|
|
62
80
|
|
|
63
81
|
<!-- Мобильная навигация (drawer) -->
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
82
|
+
<DXAnimatePresence
|
|
83
|
+
v-if="$slots['mobile-navigation']"
|
|
84
|
+
:show="showMobileMenu"
|
|
85
|
+
type="slide-down"
|
|
86
|
+
mode="default"
|
|
87
|
+
>
|
|
88
|
+
<DXBox
|
|
89
|
+
position="fixed"
|
|
90
|
+
inset
|
|
91
|
+
z-index="50"
|
|
92
|
+
bg="white"
|
|
93
|
+
:class="['md:hidden', mobileMenuClasses]"
|
|
68
94
|
>
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
95
|
+
<DXBox p="md">
|
|
96
|
+
<DXBox my="md">
|
|
97
|
+
<DXFlex justify="between" align="center">
|
|
98
|
+
<DXHeading v-if="appName" level="2" size="lg" weight="semibold">
|
|
99
|
+
{{ appName }}
|
|
100
|
+
</DXHeading>
|
|
101
|
+
<DXButton
|
|
102
|
+
variant="ghost"
|
|
103
|
+
size="sm"
|
|
104
|
+
@click="closeMobileMenu"
|
|
105
|
+
>
|
|
106
|
+
<template #icon>
|
|
107
|
+
<DXIcon :icon="XMarkIcon" size="md" />
|
|
108
|
+
</template>
|
|
109
|
+
</DXButton>
|
|
110
|
+
</DXFlex>
|
|
111
|
+
</DXBox>
|
|
112
|
+
<DXStack tag="nav" gap="sm" direction="vertical">
|
|
85
113
|
<slot name="mobile-navigation" />
|
|
86
|
-
</
|
|
87
|
-
</
|
|
88
|
-
</
|
|
89
|
-
</
|
|
114
|
+
</DXStack>
|
|
115
|
+
</DXBox>
|
|
116
|
+
</DXBox>
|
|
117
|
+
</DXAnimatePresence>
|
|
90
118
|
</header>
|
|
91
119
|
</template>
|
|
92
120
|
|
|
93
121
|
<script setup>
|
|
94
|
-
import { ref, computed } from "vue";
|
|
122
|
+
import { ref, computed, inject } from "vue";
|
|
95
123
|
import { useClassComposition } from "../../../composables/useClassComposition";
|
|
96
124
|
import DXContainer from "../../atoms/DXContainer/DXContainer.vue";
|
|
125
|
+
import DXFlex from "../../atoms/DXFlex/DXFlex.vue";
|
|
126
|
+
import DXBox from "../../atoms/DXBox/DXBox.vue";
|
|
127
|
+
import DXStack from "../../atoms/DXStack/DXStack.vue";
|
|
128
|
+
import DXImage from "../../atoms/DXImage/DXImage.vue";
|
|
129
|
+
import DXHeading from "../../atoms/DXHeading/DXHeading.vue";
|
|
97
130
|
import DXLink from "../../atoms/DXLink/DXLink.vue";
|
|
98
131
|
import DXButton from "../../atoms/DXButton/DXButton.vue";
|
|
99
132
|
import DXIcon from "../../atoms/DXIcon/DXIcon.vue";
|
|
133
|
+
import DXNav from "../../atoms/DXNav/DXNav.vue";
|
|
134
|
+
import DXAnimatePresence from "../../utilities/DXAnimatePresence/DXAnimatePresence.vue";
|
|
100
135
|
import { XMarkIcon } from "@heroicons/vue/24/outline";
|
|
101
136
|
|
|
102
137
|
const props = defineProps({
|
|
@@ -118,24 +153,191 @@ const props = defineProps({
|
|
|
118
153
|
containerPadding: { type: String, default: "md" },
|
|
119
154
|
/** Высота header */
|
|
120
155
|
height: { type: String, default: "auto", validator: (v) => ["auto", "sm", "md", "lg"].includes(v) },
|
|
156
|
+
/** Вариант стилизации: bordered | elevated | flat */
|
|
157
|
+
variant: {
|
|
158
|
+
type: String,
|
|
159
|
+
default: null,
|
|
160
|
+
validator: (value) => value === null || ['bordered', 'elevated', 'flat'].includes(value),
|
|
161
|
+
},
|
|
162
|
+
/** Фон: white | slate | transparent */
|
|
163
|
+
bg: {
|
|
164
|
+
type: String,
|
|
165
|
+
default: "white",
|
|
166
|
+
validator: (value) => ['white', 'slate', 'transparent'].includes(value),
|
|
167
|
+
},
|
|
168
|
+
/** Тень: none | sm | md | lg | xl */
|
|
169
|
+
shadow: {
|
|
170
|
+
type: String,
|
|
171
|
+
default: null,
|
|
172
|
+
validator: (value) => value === null || ['none', 'sm', 'md', 'lg', 'xl'].includes(value),
|
|
173
|
+
},
|
|
174
|
+
/** Рамка: none | bottom | full */
|
|
175
|
+
border: {
|
|
176
|
+
type: String,
|
|
177
|
+
default: "bottom",
|
|
178
|
+
validator: (value) => ['none', 'bottom', 'full'].includes(value),
|
|
179
|
+
},
|
|
121
180
|
});
|
|
122
181
|
|
|
123
182
|
const emit = defineEmits(["mobile-menu-toggle"]);
|
|
124
183
|
|
|
184
|
+
// Получение данных о breakpoint через inject (если DXBreakpointProvider доступен)
|
|
185
|
+
const currentBreakpoint = inject('currentBreakpoint', ref(null));
|
|
186
|
+
const screenWidth = inject('screenWidth', ref(null));
|
|
187
|
+
const screenHeight = inject('screenHeight', ref(null));
|
|
188
|
+
const breakpoints = inject('breakpoints', ref(null));
|
|
189
|
+
|
|
190
|
+
// Состояние мобильного меню
|
|
125
191
|
const showMobileMenu = ref(false);
|
|
126
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Проверка, является ли текущий breakpoint мобильным
|
|
195
|
+
*
|
|
196
|
+
* @description
|
|
197
|
+
* Определяет, находится ли приложение в мобильном режиме на основе breakpoint.
|
|
198
|
+
*
|
|
199
|
+
* @returns {boolean} true если breakpoint меньше md (768px)
|
|
200
|
+
*/
|
|
201
|
+
const isMobile = computed(() => {
|
|
202
|
+
if (!currentBreakpoint?.value) {
|
|
203
|
+
// Fallback: проверка через screenWidth если breakpoint недоступен
|
|
204
|
+
if (screenWidth?.value !== null && screenWidth?.value !== undefined) {
|
|
205
|
+
return screenWidth.value < 768;
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Считаем мобильным если breakpoint меньше md
|
|
211
|
+
const mobileBreakpoints = ['xs', 'sm'];
|
|
212
|
+
return mobileBreakpoints.includes(currentBreakpoint.value);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Проверка, является ли текущий breakpoint десктопным
|
|
217
|
+
*
|
|
218
|
+
* @description
|
|
219
|
+
* Определяет, находится ли приложение в десктопном режиме.
|
|
220
|
+
*
|
|
221
|
+
* @returns {boolean} true если breakpoint >= md (768px)
|
|
222
|
+
*/
|
|
223
|
+
const isDesktop = computed(() => !isMobile.value);
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Классы фона
|
|
227
|
+
*
|
|
228
|
+
* @description
|
|
229
|
+
* Определяет классы для background-color в зависимости от значения bg prop.
|
|
230
|
+
*
|
|
231
|
+
* @returns {string} Tailwind CSS класс для фона
|
|
232
|
+
*/
|
|
233
|
+
const bgClass = computed(() => {
|
|
234
|
+
const bgClasses = {
|
|
235
|
+
white: "bg-white",
|
|
236
|
+
slate: "bg-slate-50",
|
|
237
|
+
transparent: "bg-transparent",
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
return bgClasses[props.bg] || "bg-white";
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Классы тени
|
|
245
|
+
*
|
|
246
|
+
* @description
|
|
247
|
+
* Определяет классы для box-shadow в зависимости от значения shadow prop.
|
|
248
|
+
*
|
|
249
|
+
* @returns {string|null} Tailwind CSS класс для тени или null
|
|
250
|
+
*/
|
|
251
|
+
const shadowClass = computed(() => {
|
|
252
|
+
if (!props.shadow) return null;
|
|
253
|
+
|
|
254
|
+
const shadowClasses = {
|
|
255
|
+
none: "shadow-none",
|
|
256
|
+
sm: "shadow-sm",
|
|
257
|
+
md: "shadow",
|
|
258
|
+
lg: "shadow-lg",
|
|
259
|
+
xl: "shadow-xl",
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return shadowClasses[props.shadow] || null;
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Классы рамки
|
|
267
|
+
*
|
|
268
|
+
* @description
|
|
269
|
+
* Определяет классы для border в зависимости от значения border prop.
|
|
270
|
+
*
|
|
271
|
+
* @returns {string|null} Tailwind CSS класс для рамки или null
|
|
272
|
+
*/
|
|
273
|
+
const borderClass = computed(() => {
|
|
274
|
+
if (props.border === "none") return null;
|
|
275
|
+
|
|
276
|
+
const borderClasses = {
|
|
277
|
+
bottom: "border-b border-slate-200",
|
|
278
|
+
full: "border border-slate-200",
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
return borderClasses[props.border] || "border-b border-slate-200";
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Классы варианта стилизации
|
|
286
|
+
*
|
|
287
|
+
* @description
|
|
288
|
+
* Определяет дополнительные классы в зависимости от варианта стилизации.
|
|
289
|
+
*
|
|
290
|
+
* @returns {string|null} Дополнительные классы или null
|
|
291
|
+
*/
|
|
292
|
+
const variantClass = computed(() => {
|
|
293
|
+
if (!props.variant) return null;
|
|
294
|
+
|
|
295
|
+
const variantClasses = {
|
|
296
|
+
bordered: "border-slate-300",
|
|
297
|
+
elevated: null, // Тень применяется через shadow prop
|
|
298
|
+
flat: "border-0",
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
return variantClasses[props.variant] || null;
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Финальная тень (с учетом variant)
|
|
306
|
+
*
|
|
307
|
+
* @description
|
|
308
|
+
* Если variant="elevated" и shadow не указан, применяется shadow-sm по умолчанию.
|
|
309
|
+
* Иначе используется значение shadow prop.
|
|
310
|
+
*
|
|
311
|
+
* @returns {string|null} Tailwind CSS класс для тени или null
|
|
312
|
+
*/
|
|
313
|
+
const finalShadowClass = computed(() => {
|
|
314
|
+
if (props.shadow) {
|
|
315
|
+
return shadowClass.value;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (props.variant === "elevated") {
|
|
319
|
+
return "shadow-sm";
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return null;
|
|
323
|
+
});
|
|
324
|
+
|
|
127
325
|
/**
|
|
128
326
|
* Классы для header
|
|
129
327
|
*
|
|
130
328
|
* @description
|
|
131
329
|
* Вычисляет классы для header компонента, включая позиционирование (sticky/fixed),
|
|
132
|
-
*
|
|
330
|
+
* высоту, фон, тень, рамку и вариант стилизации.
|
|
133
331
|
*
|
|
134
332
|
* @returns {Array} Массив классов для header
|
|
135
333
|
*/
|
|
136
334
|
const headerClasses = computed(() =>
|
|
137
335
|
useClassComposition(
|
|
138
|
-
"w-full
|
|
336
|
+
"w-full",
|
|
337
|
+
bgClass.value,
|
|
338
|
+
finalShadowClass.value,
|
|
339
|
+
borderClass.value,
|
|
340
|
+
variantClass.value,
|
|
139
341
|
{
|
|
140
342
|
"sticky top-0 z-40": props.sticky && !props.fixed,
|
|
141
343
|
"fixed top-0 left-0 right-0 z-40": props.fixed,
|
|
@@ -180,11 +382,18 @@ function openMobileMenu() {
|
|
|
180
382
|
emit("mobile-menu-toggle", true);
|
|
181
383
|
}
|
|
182
384
|
|
|
183
|
-
// Экспортируем методы для использования в родительском компоненте
|
|
385
|
+
// Экспортируем методы и данные для использования в родительском компоненте
|
|
184
386
|
defineExpose({
|
|
185
387
|
openMobileMenu,
|
|
186
388
|
closeMobileMenu,
|
|
187
389
|
showMobileMenu,
|
|
390
|
+
// Breakpoint данные (если доступны через DXBreakpointProvider)
|
|
391
|
+
currentBreakpoint,
|
|
392
|
+
screenWidth,
|
|
393
|
+
screenHeight,
|
|
394
|
+
breakpoints,
|
|
395
|
+
isMobile,
|
|
396
|
+
isDesktop,
|
|
188
397
|
});
|
|
189
398
|
</script>
|
|
190
399
|
|
|
@@ -128,12 +128,12 @@
|
|
|
128
128
|
autoplay
|
|
129
129
|
/>
|
|
130
130
|
<div v-if="selectedItem.title || selectedItem.description" class="mt-4">
|
|
131
|
-
<
|
|
131
|
+
<DXHeading v-if="selectedItem.title" level="3" size="lg" weight="semibold" color="default">
|
|
132
132
|
{{ selectedItem.title }}
|
|
133
|
-
</
|
|
134
|
-
<
|
|
133
|
+
</DXHeading>
|
|
134
|
+
<DXText v-if="selectedItem.description" tag="p" size="sm" color="muted" class="mt-1">
|
|
135
135
|
{{ selectedItem.description }}
|
|
136
|
-
</
|
|
136
|
+
</DXText>
|
|
137
137
|
</div>
|
|
138
138
|
</div>
|
|
139
139
|
|
|
@@ -175,6 +175,8 @@ import DXModal from "../DXModal/DXModal.vue";
|
|
|
175
175
|
import DXObserver from "../../utilities/DXObserver/DXObserver.vue";
|
|
176
176
|
import DXButton from "../../atoms/DXButton/DXButton.vue";
|
|
177
177
|
import DXIcon from "../../atoms/DXIcon/DXIcon.vue";
|
|
178
|
+
import DXHeading from "../../atoms/DXHeading/DXHeading.vue";
|
|
179
|
+
import DXText from "../../atoms/DXText/DXText.vue";
|
|
178
180
|
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/vue/24/outline";
|
|
179
181
|
|
|
180
182
|
const props = defineProps({
|
|
@@ -5,7 +5,99 @@ import DXButton from '../../atoms/DXButton/DXButton.vue';
|
|
|
5
5
|
export default {
|
|
6
6
|
title: 'Organisms/DXModal',
|
|
7
7
|
component: DXModal,
|
|
8
|
-
tags: ['autodocs'],
|
|
8
|
+
tags: ['autodocs', 'category:overlay'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: `
|
|
13
|
+
# DXModal
|
|
14
|
+
|
|
15
|
+
Универсальный компонент модального окна с поддержкой различных вариантов отображения и режимов.
|
|
16
|
+
|
|
17
|
+
## Назначение
|
|
18
|
+
|
|
19
|
+
DXModal предоставляет полнофункциональное модальное окно с поддержкой различных вариантов отображения
|
|
20
|
+
(модальное окно, полноэкранный режим, боковая панель, половина экрана справа), настраиваемым backdrop,
|
|
21
|
+
переключателем режимов и слотами для кастомизации контента.
|
|
22
|
+
|
|
23
|
+
## Архитектура
|
|
24
|
+
|
|
25
|
+
### Использует
|
|
26
|
+
- \`DXBackdrop\` - фон модального окна с размытием и блокировкой скролла
|
|
27
|
+
- \`DXCloseButton\` - кнопка закрытия
|
|
28
|
+
- \`DXHeading\` - заголовок модального окна
|
|
29
|
+
- \`Transition\` - анимации появления/исчезновения
|
|
30
|
+
|
|
31
|
+
### Используется в
|
|
32
|
+
- Формы редактирования
|
|
33
|
+
- Диалоги подтверждения
|
|
34
|
+
- Детальные просмотры
|
|
35
|
+
- Настройки и конфигурация
|
|
36
|
+
- Любые места, требующие фокусированного взаимодействия
|
|
37
|
+
|
|
38
|
+
## Внутренняя логика
|
|
39
|
+
|
|
40
|
+
### Варианты отображения
|
|
41
|
+
- **modal** (по умолчанию): Классическое модальное окно по центру экрана с настраиваемой шириной
|
|
42
|
+
- **fullscreen**: Полноэкранный режим, занимает весь экран
|
|
43
|
+
- **sidebar-right**: Боковая панель справа, выезжает с правой стороны
|
|
44
|
+
- **half-right**: Половина экрана справа, фиксированная позиция
|
|
45
|
+
|
|
46
|
+
### Анимации
|
|
47
|
+
- **modal/fullscreen**: Использует анимацию \`fade-scale\` (появление с масштабированием)
|
|
48
|
+
- **sidebar-right/half-right**: Использует анимацию \`slide-right\` (выезд справа)
|
|
49
|
+
|
|
50
|
+
### Управление состоянием
|
|
51
|
+
- Управляется через \`open\` prop (Boolean)
|
|
52
|
+
- События: \`close\`, \`opened\`, \`closed\`
|
|
53
|
+
- Поддержка \`update:variant\` для динамического изменения режима
|
|
54
|
+
|
|
55
|
+
### Backdrop
|
|
56
|
+
- Настраиваемое размытие: \`none\`, \`sm\`, \`md\`, \`lg\`, \`xl\`
|
|
57
|
+
- Настраиваемая прозрачность (0-100)
|
|
58
|
+
- Настраиваемый цвет: \`slate-900\`, \`gray-900\`, \`black\`, \`white\`
|
|
59
|
+
- Блокировка скролла body (по умолчанию включена)
|
|
60
|
+
- Возможность закрытия по клику на backdrop (через \`closable\`)
|
|
61
|
+
|
|
62
|
+
### Переключатель режимов
|
|
63
|
+
При \`showModeSwitcher={true}\` отображается переключатель режимов в заголовке:
|
|
64
|
+
- Иконки для каждого режима
|
|
65
|
+
- Визуальное выделение текущего режима
|
|
66
|
+
- Событие \`update:variant\` при смене режима
|
|
67
|
+
|
|
68
|
+
## Особенности
|
|
69
|
+
|
|
70
|
+
### Слоты
|
|
71
|
+
- **default** - основной контент модального окна
|
|
72
|
+
- **title** - заголовок (по умолчанию "Диалог")
|
|
73
|
+
- **actions** - кнопки действий внизу модального окна
|
|
74
|
+
|
|
75
|
+
### Ширина (для modal)
|
|
76
|
+
Поддерживает 4 размера ширины:
|
|
77
|
+
- **sm** - маленькая ширина
|
|
78
|
+
- **md** - средняя ширина (по умолчанию)
|
|
79
|
+
- **lg** - большая ширина
|
|
80
|
+
- **xl** - очень большая ширина
|
|
81
|
+
|
|
82
|
+
### Закрытие
|
|
83
|
+
- Кнопка закрытия в заголовке (если \`closable={true}\`)
|
|
84
|
+
- Закрытие по клику на backdrop (если \`closable={true}\`)
|
|
85
|
+
- Событие \`close\` для программного закрытия
|
|
86
|
+
|
|
87
|
+
### Структура контента
|
|
88
|
+
Модальное окно имеет три секции:
|
|
89
|
+
1. **Заголовок** - заголовок, переключатель режимов (опционально), кнопка закрытия
|
|
90
|
+
2. **Контент** - основной контент с прокруткой
|
|
91
|
+
3. **Действия** - кнопки действий (если используется слот \`actions\`)
|
|
92
|
+
|
|
93
|
+
### Специальные варианты
|
|
94
|
+
- **half-right**: Не использует backdrop, фиксированная позиция справа, z-index 20
|
|
95
|
+
- **sidebar-right**: Backdrop с z-index 50, выезжает справа
|
|
96
|
+
- **fullscreen**: Занимает весь экран, padding 8
|
|
97
|
+
`,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
9
101
|
argTypes: {
|
|
10
102
|
variant: {
|
|
11
103
|
control: 'select',
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
>
|
|
19
19
|
<div :class="containerClass">
|
|
20
20
|
<div class="flex items-center justify-between flex-shrink-0 mb-4 gap-4">
|
|
21
|
-
<
|
|
21
|
+
<DXHeading level="3" size="lg" weight="semibold" color="default" class="flex-1">
|
|
22
22
|
<slot name="title">Диалог</slot>
|
|
23
|
-
</
|
|
23
|
+
</DXHeading>
|
|
24
24
|
|
|
25
25
|
<!-- View Mode Switcher -->
|
|
26
26
|
<div v-if="showModeSwitcher" class="flex items-center gap-1 rounded-xl border border-slate-200 bg-slate-50 p-1">
|
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
} from "@heroicons/vue/24/outline";
|
|
69
69
|
import DXBackdrop from "../../atoms/DXBackdrop/DXBackdrop.vue";
|
|
70
70
|
import DXCloseButton from "../../molecules/DXCloseButton/DXCloseButton.vue";
|
|
71
|
+
import DXHeading from "../../atoms/DXHeading/DXHeading.vue";
|
|
71
72
|
|
|
72
73
|
const props = defineProps({
|
|
73
74
|
/** Открыто/закрыто */
|
|
@@ -4,7 +4,7 @@ import DXNotificationCenter from './DXNotificationCenter.vue';
|
|
|
4
4
|
export default {
|
|
5
5
|
title: 'Organisms/DXNotificationCenter',
|
|
6
6
|
component: DXNotificationCenter,
|
|
7
|
-
tags: ['autodocs'],
|
|
7
|
+
tags: ['autodocs', 'category:feedback'],
|
|
8
8
|
parameters: {
|
|
9
9
|
docs: {
|
|
10
10
|
description: {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<div v-if="showHeader || $slots.header" :class="headerClasses">
|
|
30
30
|
<slot name="header">
|
|
31
31
|
<div class="flex items-center justify-between">
|
|
32
|
-
<
|
|
32
|
+
<DXHeading level="3" size="lg" weight="semibold" color="default">Уведомления</DXHeading>
|
|
33
33
|
<DXButton
|
|
34
34
|
v-if="unreadCount > 0"
|
|
35
35
|
size="sm"
|
|
@@ -144,6 +144,7 @@ import { useSpacing } from "../../../composables/useSpacing";
|
|
|
144
144
|
import DXButton from "../../atoms/DXButton/DXButton.vue";
|
|
145
145
|
import DXIcon from "../../atoms/DXIcon/DXIcon.vue";
|
|
146
146
|
import DXBadge from "../../atoms/DXBadge/DXBadge.vue";
|
|
147
|
+
import DXHeading from "../../atoms/DXHeading/DXHeading.vue";
|
|
147
148
|
import DXDropdown from "../DXDropdown/DXDropdown.vue";
|
|
148
149
|
import {
|
|
149
150
|
BellIcon,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<!-- Header -->
|
|
7
7
|
<div v-if="showHeader || $slots.header" :class="headerClasses">
|
|
8
8
|
<slot name="header">
|
|
9
|
-
<
|
|
9
|
+
<DXHeading level="2" size="2xl" weight="bold" color="default">Генератор отчетов</DXHeading>
|
|
10
10
|
</slot>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<div v-if="$slots.settings || showSettings" :class="settingsClasses">
|
|
27
27
|
<slot name="settings" :settings="reportSettings" :update-setting="updateSetting">
|
|
28
28
|
<DXCard v-if="showSettings" class="p-4">
|
|
29
|
-
<
|
|
29
|
+
<DXHeading level="3" weight="semibold" class="mb-4">Настройки отчета</DXHeading>
|
|
30
30
|
<div class="space-y-4">
|
|
31
31
|
<DXFormControl label="Формат экспорта">
|
|
32
32
|
<DXSelect
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
<div v-if="$slots.preview || showPreview" :class="previewClasses">
|
|
50
50
|
<slot name="preview" :data="previewData" :columns="columns">
|
|
51
51
|
<DXCard v-if="showPreview" class="p-4">
|
|
52
|
-
<
|
|
52
|
+
<DXHeading level="3" weight="semibold" class="mb-4">Предпросмотр</DXHeading>
|
|
53
53
|
<DXTable
|
|
54
54
|
:columns="columns"
|
|
55
55
|
:data="previewData"
|
|
@@ -91,6 +91,7 @@ import { useClassComposition } from "../../../composables/useClassComposition";
|
|
|
91
91
|
import { useSpacing } from "../../../composables/useSpacing";
|
|
92
92
|
import DXCard from "../../atoms/DXCard/DXCard.vue";
|
|
93
93
|
import DXButton from "../../atoms/DXButton/DXButton.vue";
|
|
94
|
+
import DXHeading from "../../atoms/DXHeading/DXHeading.vue";
|
|
94
95
|
import DXTable from "../DXTable/DXTable.vue";
|
|
95
96
|
import DXDataFilter from "../../molecules/DXDataFilter/DXDataFilter.vue";
|
|
96
97
|
import DXSelect from "../../molecules/DXSelect/DXSelect.vue";
|