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.
Files changed (148) hide show
  1. package/dist/dxd-style-code.js +7470 -6336
  2. package/dist/dxd-style-code.umd.cjs +3 -3
  3. package/dist/style.css +1 -1
  4. package/package.json +2 -2
  5. package/src/components/atoms/DX/DX.stories.js +265 -0
  6. package/src/components/atoms/DX/DX.vue +80 -0
  7. package/src/components/atoms/DX/index.js +2 -0
  8. package/src/components/atoms/DXAvatar/DXAvatar.stories.js +1 -2
  9. package/src/components/atoms/DXBackdrop/DXBackdrop.stories.js +77 -1
  10. package/src/components/atoms/DXBadge/DXBadge.stories.js +83 -1
  11. package/src/components/atoms/DXBlockquote/DXBlockquote.stories.js +67 -1
  12. package/src/components/atoms/DXBox/DXBox.stories.js +1 -1
  13. package/src/components/atoms/DXBox/DXBox.vue +69 -2
  14. package/src/components/atoms/DXButton/DXButton.stories.js +94 -1
  15. package/src/components/atoms/DXButton/DXButton.vue +145 -11
  16. package/src/components/atoms/DXCard/DXCard.stories.js +72 -14
  17. package/src/components/atoms/DXCard/DXCard.vue +3 -4
  18. package/src/components/atoms/DXCheckbox/DXCheckbox.stories.js +85 -1
  19. package/src/components/atoms/DXCode/DXCode.stories.js +67 -1
  20. package/src/components/atoms/DXContainer/DXContainer.stories.js +1 -1
  21. package/src/components/atoms/DXContainer/DXContainer.vue +28 -1
  22. package/src/components/atoms/DXDivider/DXDivider.stories.js +84 -1
  23. package/src/components/atoms/DXFlex/DXFlex.stories.js +1 -1
  24. package/src/components/atoms/DXFlex/DXFlex.vue +57 -3
  25. package/src/components/atoms/DXFormLabel/DXFormLabel.stories.js +70 -1
  26. package/src/components/atoms/DXGrid/DXGrid.stories.js +1 -1
  27. package/src/components/atoms/DXHeading/DXHeading.stories.js +90 -1
  28. package/src/components/atoms/DXIcon/DXIcon.stories.js +74 -0
  29. package/src/components/atoms/DXIconWrapper/DXIconWrapper.stories.js +69 -0
  30. package/src/components/atoms/DXImage/DXImage.stories.js +483 -0
  31. package/src/components/atoms/DXImage/DXImage.vue +294 -0
  32. package/src/components/atoms/DXImage/index.js +2 -0
  33. package/src/components/atoms/DXInputAddon/DXInputAddon.stories.js +86 -1
  34. package/src/components/atoms/DXLabel/DXLabel.stories.js +62 -1
  35. package/src/components/atoms/DXLink/DXLink.stories.js +75 -10
  36. package/src/components/atoms/DXLink/DXLink.vue +59 -3
  37. package/src/components/atoms/DXList/DXList.stories.js +76 -1
  38. package/src/components/atoms/DXLoader/DXLoader.stories.js +75 -1
  39. package/src/components/atoms/DXNav/DXNav.stories.js +236 -0
  40. package/src/components/atoms/DXNav/DXNav.vue +114 -0
  41. package/src/components/atoms/DXNav/index.js +2 -0
  42. package/src/components/atoms/DXProgress/DXProgress.stories.js +76 -1
  43. package/src/components/atoms/DXRadio/DXRadio.stories.js +85 -1
  44. package/src/components/atoms/DXSkeleton/DXSkeleton.stories.js +59 -1
  45. package/src/components/atoms/DXSlider/DXSlider.stories.js +89 -0
  46. package/src/components/atoms/DXSpacer/DXSpacer.stories.js +1 -1
  47. package/src/components/atoms/DXStack/DXStack.stories.js +1 -1
  48. package/src/components/atoms/DXStack/DXStack.vue +5 -2
  49. package/src/components/atoms/DXTags/DXTags.stories.js +77 -0
  50. package/src/components/atoms/DXText/DXText.stories.js +83 -1
  51. package/src/components/atoms/DXToast/DXToast.stories.js +64 -1
  52. package/src/components/atoms/DXToggle/DXToggle.stories.js +84 -1
  53. package/src/components/atoms/DXToggleButton/DXToggleButton.stories.js +78 -1
  54. package/src/components/atoms/DXTooltip/DXTooltip.stories.js +98 -1
  55. package/src/components/atoms/index.js +3 -0
  56. package/src/components/molecules/DXActionButtons/DXActionButtons.stories.js +280 -77
  57. package/src/components/molecules/DXActionButtons/DXActionButtons.vue +31 -31
  58. package/src/components/molecules/DXAlert/DXAlert.stories.js +199 -1
  59. package/src/components/molecules/DXAlert/DXAlert.vue +35 -13
  60. package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.stories.js +125 -1
  61. package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.vue +22 -18
  62. package/src/components/molecules/DXButtonGroup/DXButtonGroup.stories.js +193 -6
  63. package/src/components/molecules/DXButtonGroup/DXButtonGroup.vue +39 -3
  64. package/src/components/molecules/DXCloseButton/DXCloseButton.stories.js +64 -1
  65. package/src/components/molecules/DXComboBox/DXComboBox.stories.js +66 -0
  66. package/src/components/molecules/DXCopyField/DXCopyField.stories.js +128 -1
  67. package/src/components/molecules/DXCopyField/DXCopyField.vue +60 -7
  68. package/src/components/molecules/DXDataFilter/DXDataFilter.vue +8 -6
  69. package/src/components/molecules/DXDatePicker/DXDatePicker.stories.js +58 -0
  70. package/src/components/molecules/DXFileUpload/DXFileUpload.stories.js +66 -0
  71. package/src/components/molecules/DXFilterGroup/DXFilterGroup.stories.js +61 -0
  72. package/src/components/molecules/DXFormControl/DXFormControl.stories.js +76 -0
  73. package/src/components/molecules/DXFormControl/DXFormControl.vue +9 -8
  74. package/src/components/molecules/DXInput/DXInput.stories.js +100 -1
  75. package/src/components/molecules/DXInputGroup/DXInputGroup.stories.js +89 -1
  76. package/src/components/molecules/DXInputMask/DXInputMask.stories.js +67 -0
  77. package/src/components/molecules/DXMenu/DXMenu.stories.js +111 -4
  78. package/src/components/molecules/DXMenu/DXMenu.vue +18 -5
  79. package/src/components/molecules/DXMenu/README.md +1 -1
  80. package/src/components/molecules/DXPagination/DXPagination.stories.js +105 -2
  81. package/src/components/molecules/DXPagination/DXPagination.vue +18 -33
  82. package/src/components/molecules/DXPasswordInput/DXPasswordInput.stories.js +67 -1
  83. package/src/components/molecules/DXRadioCard/DXRadioCard.stories.js +64 -0
  84. package/src/components/molecules/DXRadioGroup/DXRadioGroup.stories.js +84 -0
  85. package/src/components/molecules/DXRating/DXRating.stories.js +3 -2
  86. package/src/components/molecules/DXSearchBar/DXSearchBar.stories.js +1 -1
  87. package/src/components/molecules/DXSearchBar/DXSearchBar.vue +16 -12
  88. package/src/components/molecules/DXSearchSelect/DXSearchSelect.stories.js +71 -0
  89. package/src/components/molecules/DXSegmentedControl/DXSegmentedControl.stories.js +74 -0
  90. package/src/components/molecules/DXSelect/DXSelect.stories.js +92 -1
  91. package/src/components/molecules/DXStatCard/DXStatCard.stories.js +1 -1
  92. package/src/components/molecules/DXStatCard/DXStatCard.vue +30 -26
  93. package/src/components/molecules/DXTableFiltersPanel/index.js +3 -0
  94. package/src/components/molecules/DXTablePagination/DXTablePagination.stories.js +67 -0
  95. package/src/components/molecules/DXTableToolbar/DXTableToolbar.stories.js +71 -0
  96. package/src/components/molecules/DXTextarea/DXTextarea.stories.js +87 -1
  97. package/src/components/molecules/DXTimePicker/DXTimePicker.stories.js +1 -1
  98. package/src/components/molecules/DXValidationIcon/DXValidationIcon.stories.js +59 -1
  99. package/src/components/molecules/index.js +0 -1
  100. package/src/components/organisms/DXAccordion/DXAccordion.stories.js +75 -0
  101. package/src/components/organisms/DXAppLayout/DXAppLayout.stories.js +27 -25
  102. package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.stories.js +0 -2
  103. package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.vue +5 -8
  104. package/src/components/{molecules → organisms}/DXBaseTable/DXBaseTable.stories.js +78 -1
  105. package/src/components/{molecules → organisms}/DXBaseTable/DXBaseTable.vue +2 -2
  106. package/src/components/organisms/DXChartContainer/DXChartContainer.stories.js +1 -1
  107. package/src/components/organisms/DXChartContainer/DXChartContainer.vue +10 -6
  108. package/src/components/organisms/DXChatInterface/DXChatInterface.stories.js +1 -1
  109. package/src/components/organisms/DXChatInterface/DXChatInterface.vue +6 -4
  110. package/src/components/organisms/DXCommentSection/DXCommentSection.stories.js +1 -1
  111. package/src/components/organisms/DXCommentSection/DXCommentSection.vue +7 -6
  112. package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.stories.js +1 -1
  113. package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.vue +4 -2
  114. package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.stories.js +1 -1
  115. package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.vue +3 -2
  116. package/src/components/organisms/DXDataTable/DXDataTable.stories.js +1 -1
  117. package/src/components/organisms/DXDropdown/DXDropdown.stories.js +84 -1
  118. package/src/components/organisms/DXEmptyState/DXEmptyState.stories.js +64 -0
  119. package/src/components/organisms/DXEmptyState/DXEmptyState.vue +4 -2
  120. package/src/components/organisms/DXHeaderBar/DXHeaderBar.stories.js +409 -3
  121. package/src/components/organisms/DXHeaderBar/DXHeaderBar.vue +261 -52
  122. package/src/components/organisms/DXMediaGallery/DXMediaGallery.stories.js +1 -1
  123. package/src/components/organisms/DXMediaGallery/DXMediaGallery.vue +6 -4
  124. package/src/components/organisms/DXModal/DXModal.stories.js +93 -1
  125. package/src/components/organisms/DXModal/DXModal.vue +3 -2
  126. package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.stories.js +1 -1
  127. package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.vue +2 -1
  128. package/src/components/organisms/DXReportGenerator/DXReportGenerator.vue +4 -3
  129. package/src/components/organisms/DXSettingsPanel/DXSettingsPanel.vue +11 -8
  130. package/src/components/organisms/DXSidebar/DXSidebar.stories.js +1 -1
  131. package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.stories.js +104 -1
  132. package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.vue +14 -4
  133. package/src/components/organisms/DXSidebarMenu/README.md +3 -3
  134. package/src/components/organisms/DXTable/DXTable.stories.js +138 -11
  135. package/src/components/organisms/DXTable/DXTable.vue +1 -1
  136. package/src/components/organisms/DXTabs/DXTabs.stories.js +91 -1
  137. package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.stories.js +1 -1
  138. package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.vue +20 -18
  139. package/src/components/organisms/index.js +1 -0
  140. package/src/components/utilities/DXAnimatePresence/DXAnimatePresence.stories.js +1 -1
  141. package/src/components/utilities/DXBreakpointProvider/DXBreakpointProvider.stories.js +1 -1
  142. package/src/components/utilities/DXObserver/DXObserver.stories.js +1 -1
  143. package/src/components/utilities/DXPortal/DXPortal.stories.js +1 -1
  144. package/src/components/utilities/DXStaggeredAnimation/DXStaggeredAnimation.stories.js +2 -2
  145. package/src/components/utilities/DXThemeProvider/DXThemeProvider.stories.js +1 -1
  146. package/src/components/utilities/DXTransitionGroup/DXTransitionGroup.stories.js +1 -1
  147. package/src/composables/useSize.js +8 -1
  148. /package/src/components/{molecules → organisms}/DXBaseTable/index.js +0 -0
@@ -0,0 +1,483 @@
1
+ import DXImage from './DXImage.vue';
2
+
3
+ export default {
4
+ title: 'Atoms/DXImage',
5
+ component: DXImage,
6
+ tags: ['autodocs', 'category:data-display'],
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component: `
11
+ # DXImage
12
+
13
+ Универсальный компонент для отображения изображений с поддержкой lazy loading, fallback и обработки ошибок.
14
+
15
+ ## Назначение
16
+
17
+ DXImage предоставляет улучшенную функциональность по сравнению с обычным \`<img>\` тегом:
18
+ - Lazy loading через DXObserver
19
+ - Автоматический fallback при ошибке загрузки
20
+ - Skeleton/placeholder при загрузке
21
+ - Поддержка responsive изображений (srcset)
22
+ - Различные размеры и режимы отображения
23
+
24
+ ## Архитектура
25
+
26
+ ### Использует
27
+ - \`useSize\` composable - для предопределенных размеров
28
+ - \`useClassComposition\` composable - для объединения классов
29
+ - \`DXObserver\` - для lazy loading
30
+ - \`DXIcon\` - для fallback иконки
31
+
32
+ ### Используется в
33
+ - Логотипы и брендинг
34
+ - Галереи изображений
35
+ - Карточки товаров
36
+ - Профили пользователей
37
+ - Любые места, где требуется отображение изображений
38
+
39
+ ## Внутренняя логика
40
+
41
+ ### Обработка ошибок
42
+ При ошибке загрузки основного изображения:
43
+ 1. Если указан \`fallback\` → загружает fallback изображение
44
+ 2. Если есть slot \`fallback\` → показывает кастомный fallback
45
+ 3. Иначе показывает дефолтный placeholder с иконкой
46
+
47
+ ### Lazy Loading
48
+ - Использует \`DXObserver\` для отслеживания видимости
49
+ - Показывает skeleton/placeholder до загрузки
50
+ - Загружает изображение только при появлении в viewport
51
+
52
+ ### Размеры
53
+ - Предопределенные размеры через \`size\` prop (xs, sm, md, lg, xl)
54
+ - Кастомные размеры через \`width\` и \`height\` props
55
+ - Использует \`useSize\` composable для унификации
56
+
57
+ ## Особенности
58
+
59
+ ### Базовое использование
60
+ \`\`\`vue
61
+ <DXImage src="/logo.png" alt="Logo" size="md" />
62
+ \`\`\`
63
+
64
+ ### С lazy loading
65
+ \`\`\`vue
66
+ <DXImage src="/image.jpg" alt="Image" lazy />
67
+ \`\`\`
68
+
69
+ ### С fallback
70
+ \`\`\`vue
71
+ <DXImage src="/image.jpg" fallback="/fallback.jpg" alt="Image" />
72
+ \`\`\`
73
+
74
+ ### Responsive изображения
75
+ \`\`\`vue
76
+ <DXImage
77
+ src="/image.jpg"
78
+ srcset="/image-small.jpg 400w, /image-large.jpg 800w"
79
+ sizes="(max-width: 600px) 400px, 800px"
80
+ alt="Responsive image"
81
+ />
82
+ \`\`\`
83
+
84
+ ### Кастомные размеры
85
+ \`\`\`vue
86
+ <DXImage src="/image.jpg" :width="200" :height="150" alt="Image" />
87
+ \`\`\`
88
+
89
+ ## Ограничения
90
+
91
+ - Lazy loading работает только с DXObserver
92
+ - Fallback изображение также может вызвать ошибку (отслеживается отдельно)
93
+ - Skeleton показывается только при lazy loading
94
+ `,
95
+ },
96
+ },
97
+ },
98
+ argTypes: {
99
+ src: {
100
+ control: 'text',
101
+ description: 'URL изображения. Обязательный параметр.',
102
+ table: {
103
+ type: { summary: 'string' },
104
+ category: 'Image',
105
+ },
106
+ },
107
+ alt: {
108
+ control: 'text',
109
+ description: 'Alt текст для доступности. Важен для SEO и скринридеров.',
110
+ table: {
111
+ type: { summary: 'string' },
112
+ defaultValue: { summary: '""' },
113
+ category: 'Image',
114
+ },
115
+ },
116
+ size: {
117
+ control: 'select',
118
+ options: ['xs', 'sm', 'md', 'lg', 'xl'],
119
+ description: 'Предопределенный размер изображения. Использует useSize composable для унификации размеров.',
120
+ table: {
121
+ type: { summary: 'string' },
122
+ defaultValue: { summary: 'null' },
123
+ category: 'Size',
124
+ },
125
+ },
126
+ width: {
127
+ control: 'text',
128
+ description: 'Кастомная ширина изображения. Может быть числом (пиксели) или строкой (например, "200px", "50%").',
129
+ table: {
130
+ type: { summary: 'string | number' },
131
+ defaultValue: { summary: 'null' },
132
+ category: 'Size',
133
+ },
134
+ },
135
+ height: {
136
+ control: 'text',
137
+ description: 'Кастомная высота изображения. Может быть числом (пиксели) или строкой (например, "200px", "50%").',
138
+ table: {
139
+ type: { summary: 'string | number' },
140
+ defaultValue: { summary: 'null' },
141
+ category: 'Size',
142
+ },
143
+ },
144
+ objectFit: {
145
+ control: 'select',
146
+ options: ['cover', 'contain', 'fill', 'none', 'scale-down'],
147
+ description: 'CSS object-fit свойство. Определяет, как изображение вписывается в контейнер.',
148
+ table: {
149
+ type: { summary: 'string' },
150
+ defaultValue: { summary: '"cover"' },
151
+ category: 'Appearance',
152
+ },
153
+ },
154
+ lazy: {
155
+ control: 'boolean',
156
+ description: 'Включить lazy loading. Изображение загружается только при появлении в viewport через DXObserver.',
157
+ table: {
158
+ type: { summary: 'boolean' },
159
+ defaultValue: { summary: 'false' },
160
+ category: 'Behavior',
161
+ },
162
+ },
163
+ fallback: {
164
+ control: 'text',
165
+ description: 'URL fallback изображения при ошибке загрузки основного изображения.',
166
+ table: {
167
+ type: { summary: 'string' },
168
+ defaultValue: { summary: 'null' },
169
+ category: 'Error Handling',
170
+ },
171
+ },
172
+ placeholder: {
173
+ control: 'text',
174
+ description: 'URL placeholder изображения. Показывается до загрузки основного изображения при lazy loading.',
175
+ table: {
176
+ type: { summary: 'string' },
177
+ defaultValue: { summary: 'null' },
178
+ category: 'Loading',
179
+ },
180
+ },
181
+ showSkeleton: {
182
+ control: 'boolean',
183
+ description: 'Показывать skeleton при загрузке (только для lazy loading).',
184
+ table: {
185
+ type: { summary: 'boolean' },
186
+ defaultValue: { summary: 'true' },
187
+ category: 'Loading',
188
+ },
189
+ },
190
+ rounded: {
191
+ control: 'select',
192
+ options: ['none', 'sm', 'md', 'lg', 'xl', 'full'],
193
+ description: 'Скругление углов изображения.',
194
+ table: {
195
+ type: { summary: 'string' },
196
+ defaultValue: { summary: '"none"' },
197
+ category: 'Appearance',
198
+ },
199
+ },
200
+ srcset: {
201
+ control: 'text',
202
+ description: 'Responsive изображения (srcset атрибут). Позволяет браузеру выбирать оптимальное изображение.',
203
+ table: {
204
+ type: { summary: 'string' },
205
+ defaultValue: { summary: 'null' },
206
+ category: 'Responsive',
207
+ },
208
+ },
209
+ sizes: {
210
+ control: 'text',
211
+ description: 'Sizes атрибут для responsive изображений. Определяет размер изображения в разных условиях.',
212
+ table: {
213
+ type: { summary: 'string' },
214
+ defaultValue: { summary: 'null' },
215
+ category: 'Responsive',
216
+ },
217
+ },
218
+ },
219
+ };
220
+
221
+ export const Default = {
222
+ args: {
223
+ src: 'https://via.placeholder.com/400x300',
224
+ alt: 'Placeholder image',
225
+ },
226
+ parameters: {
227
+ docs: {
228
+ description: {
229
+ story: 'Базовое использование DXImage. Простое отображение изображения с alt текстом.',
230
+ },
231
+ },
232
+ },
233
+ render: (args) => ({
234
+ components: { DXImage },
235
+ setup() { return { args }; },
236
+ template: '<DXImage v-bind="args" />',
237
+ }),
238
+ };
239
+
240
+ export const Sizes = {
241
+ parameters: {
242
+ docs: {
243
+ description: {
244
+ story: 'Предопределенные размеры изображений. Использует useSize composable для унификации размеров.',
245
+ },
246
+ },
247
+ },
248
+ render: () => ({
249
+ components: { DXImage },
250
+ template: `
251
+ <div class="flex items-end gap-4">
252
+ <div class="text-center">
253
+ <DXImage src="https://via.placeholder.com/64x64" alt="XS" size="xs" rounded="md" />
254
+ <p class="text-xs text-slate-500 mt-2">XS</p>
255
+ </div>
256
+ <div class="text-center">
257
+ <DXImage src="https://via.placeholder.com/96x96" alt="SM" size="sm" rounded="md" />
258
+ <p class="text-xs text-slate-500 mt-2">SM</p>
259
+ </div>
260
+ <div class="text-center">
261
+ <DXImage src="https://via.placeholder.com/128x128" alt="MD" size="md" rounded="md" />
262
+ <p class="text-xs text-slate-500 mt-2">MD</p>
263
+ </div>
264
+ <div class="text-center">
265
+ <DXImage src="https://via.placeholder.com/192x192" alt="LG" size="lg" rounded="md" />
266
+ <p class="text-xs text-slate-500 mt-2">LG</p>
267
+ </div>
268
+ <div class="text-center">
269
+ <DXImage src="https://via.placeholder.com/256x256" alt="XL" size="xl" rounded="md" />
270
+ <p class="text-xs text-slate-500 mt-2">XL</p>
271
+ </div>
272
+ </div>
273
+ `,
274
+ }),
275
+ };
276
+
277
+ export const CustomSizes = {
278
+ args: {
279
+ src: 'https://via.placeholder.com/400x300',
280
+ alt: 'Custom size image',
281
+ width: 200,
282
+ height: 150,
283
+ },
284
+ parameters: {
285
+ docs: {
286
+ description: {
287
+ story: 'Кастомные размеры через width и height props. Размеры могут быть числами (пиксели) или строками (например, "200px", "50%").',
288
+ },
289
+ },
290
+ },
291
+ render: (args) => ({
292
+ components: { DXImage },
293
+ setup() { return { args }; },
294
+ template: '<DXImage v-bind="args" rounded="lg" />',
295
+ }),
296
+ };
297
+
298
+ export const ObjectFit = {
299
+ parameters: {
300
+ docs: {
301
+ description: {
302
+ story: 'Различные режимы object-fit. Определяет, как изображение вписывается в контейнер.',
303
+ },
304
+ },
305
+ },
306
+ render: () => ({
307
+ components: { DXImage },
308
+ template: `
309
+ <div class="grid grid-cols-3 gap-4">
310
+ <div class="text-center">
311
+ <DXImage
312
+ src="https://via.placeholder.com/400x300"
313
+ alt="Cover"
314
+ :width="200"
315
+ :height="150"
316
+ object-fit="cover"
317
+ rounded="lg"
318
+ />
319
+ <p class="text-xs text-slate-500 mt-2">Cover</p>
320
+ </div>
321
+ <div class="text-center">
322
+ <DXImage
323
+ src="https://via.placeholder.com/400x300"
324
+ alt="Contain"
325
+ :width="200"
326
+ :height="150"
327
+ object-fit="contain"
328
+ rounded="lg"
329
+ class="bg-slate-100"
330
+ />
331
+ <p class="text-xs text-slate-500 mt-2">Contain</p>
332
+ </div>
333
+ <div class="text-center">
334
+ <DXImage
335
+ src="https://via.placeholder.com/400x300"
336
+ alt="Fill"
337
+ :width="200"
338
+ :height="150"
339
+ object-fit="fill"
340
+ rounded="lg"
341
+ />
342
+ <p class="text-xs text-slate-500 mt-2">Fill</p>
343
+ </div>
344
+ </div>
345
+ `,
346
+ }),
347
+ };
348
+
349
+ export const Rounded = {
350
+ parameters: {
351
+ docs: {
352
+ description: {
353
+ story: 'Различные варианты скругления углов изображения.',
354
+ },
355
+ },
356
+ },
357
+ render: () => ({
358
+ components: { DXImage },
359
+ template: `
360
+ <div class="flex gap-4">
361
+ <div class="text-center">
362
+ <DXImage src="https://via.placeholder.com/100x100" alt="None" rounded="none" />
363
+ <p class="text-xs text-slate-500 mt-2">None</p>
364
+ </div>
365
+ <div class="text-center">
366
+ <DXImage src="https://via.placeholder.com/100x100" alt="SM" rounded="sm" />
367
+ <p class="text-xs text-slate-500 mt-2">SM</p>
368
+ </div>
369
+ <div class="text-center">
370
+ <DXImage src="https://via.placeholder.com/100x100" alt="MD" rounded="md" />
371
+ <p class="text-xs text-slate-500 mt-2">MD</p>
372
+ </div>
373
+ <div class="text-center">
374
+ <DXImage src="https://via.placeholder.com/100x100" alt="LG" rounded="lg" />
375
+ <p class="text-xs text-slate-500 mt-2">LG</p>
376
+ </div>
377
+ <div class="text-center">
378
+ <DXImage src="https://via.placeholder.com/100x100" alt="Full" rounded="full" />
379
+ <p class="text-xs text-slate-500 mt-2">Full</p>
380
+ </div>
381
+ </div>
382
+ `,
383
+ }),
384
+ };
385
+
386
+ export const LazyLoading = {
387
+ args: {
388
+ src: 'https://via.placeholder.com/800x600',
389
+ alt: 'Lazy loaded image',
390
+ lazy: true,
391
+ },
392
+ parameters: {
393
+ docs: {
394
+ description: {
395
+ story: 'Lazy loading изображения. Изображение загружается только при появлении в viewport. Прокрутите вниз, чтобы увидеть загрузку.',
396
+ },
397
+ },
398
+ },
399
+ render: (args) => ({
400
+ components: { DXImage },
401
+ setup() { return { args }; },
402
+ template: `
403
+ <div class="space-y-4">
404
+ <div class="h-screen bg-slate-50 p-4">
405
+ <p class="text-slate-600">Прокрутите вниз для загрузки изображения</p>
406
+ </div>
407
+ <DXImage v-bind="args" :width="800" :height="600" rounded="lg" />
408
+ </div>
409
+ `,
410
+ }),
411
+ };
412
+
413
+ export const WithFallback = {
414
+ args: {
415
+ src: 'https://invalid-url-that-will-fail.com/image.jpg',
416
+ alt: 'Image with fallback',
417
+ fallback: 'https://via.placeholder.com/400x300/ff6b6b/ffffff?text=Fallback',
418
+ },
419
+ parameters: {
420
+ docs: {
421
+ description: {
422
+ story: 'Изображение с fallback. При ошибке загрузки основного изображения автоматически загружается fallback изображение.',
423
+ },
424
+ },
425
+ },
426
+ render: (args) => ({
427
+ components: { DXImage },
428
+ setup() { return { args }; },
429
+ template: '<DXImage v-bind="args" :width="400" :height="300" rounded="lg" />',
430
+ }),
431
+ };
432
+
433
+ export const WithCustomFallback = {
434
+ args: {
435
+ src: 'https://invalid-url-that-will-fail.com/image.jpg',
436
+ alt: 'Image with custom fallback',
437
+ },
438
+ parameters: {
439
+ docs: {
440
+ description: {
441
+ story: 'Кастомный fallback через slot. Позволяет использовать любой контент в качестве fallback.',
442
+ },
443
+ },
444
+ },
445
+ render: (args) => ({
446
+ components: { DXImage },
447
+ setup() { return { args }; },
448
+ template: `
449
+ <DXImage v-bind="args" :width="400" :height="300" rounded="lg">
450
+ <template #fallback>
451
+ <div class="w-full h-full bg-gradient-to-br from-slate-100 to-slate-200 flex items-center justify-center rounded-lg">
452
+ <div class="text-center">
453
+ <p class="text-slate-600 font-medium">Изображение не загружено</p>
454
+ <p class="text-slate-400 text-sm mt-1">Используется кастомный fallback</p>
455
+ </div>
456
+ </div>
457
+ </template>
458
+ </DXImage>
459
+ `,
460
+ }),
461
+ };
462
+
463
+ export const Responsive = {
464
+ args: {
465
+ src: 'https://via.placeholder.com/800x600',
466
+ alt: 'Responsive image',
467
+ srcset: 'https://via.placeholder.com/400x300 400w, https://via.placeholder.com/800x600 800w, https://via.placeholder.com/1200x900 1200w',
468
+ sizes: '(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px',
469
+ },
470
+ parameters: {
471
+ docs: {
472
+ description: {
473
+ story: 'Responsive изображение с srcset и sizes. Браузер автоматически выбирает оптимальное изображение в зависимости от размера экрана и плотности пикселей.',
474
+ },
475
+ },
476
+ },
477
+ render: (args) => ({
478
+ components: { DXImage },
479
+ setup() { return { args }; },
480
+ template: '<DXImage v-bind="args" class="w-full" rounded="lg" />',
481
+ }),
482
+ };
483
+