dxd-style-code 0.1.7 → 0.1.8
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 +11974 -3725
- package/dist/dxd-style-code.umd.cjs +10 -1
- package/dist/style.css +1 -1
- package/package.json +13 -6
- package/src/components/atoms/DXAvatar/DXAvatar.stories.js +319 -0
- package/src/components/atoms/DXAvatar/DXAvatar.vue +167 -0
- package/src/components/atoms/DXAvatar/index.js +2 -0
- package/src/components/atoms/DXBackdrop/DXBackdrop.stories.js +341 -0
- package/src/components/atoms/DXBackdrop/DXBackdrop.vue +102 -0
- package/src/components/atoms/DXBackdrop/index.js +2 -0
- package/src/components/atoms/DXBadge/DXBadge.stories.js +239 -0
- package/src/components/atoms/DXBadge/DXBadge.vue +45 -0
- package/src/components/atoms/DXBadge/index.js +2 -0
- package/src/components/atoms/DXButton/DXButton.stories.js +178 -0
- package/src/components/atoms/DXButton/DXButton.vue +84 -0
- package/src/components/atoms/DXButton/index.js +2 -0
- package/src/components/atoms/DXCard/DXCard.stories.js +133 -0
- package/src/components/atoms/DXCard/DXCard.vue +46 -0
- package/src/components/atoms/DXCard/index.js +2 -0
- package/src/components/atoms/DXCheckbox/DXCheckbox.stories.js +294 -0
- package/src/components/atoms/DXCheckbox/DXCheckbox.vue +191 -0
- package/src/components/atoms/DXCheckbox/index.js +2 -0
- package/src/components/atoms/DXDivider/DXDivider.stories.js +135 -0
- package/src/components/atoms/DXDivider/DXDivider.vue +74 -0
- package/src/components/atoms/DXDivider/index.js +2 -0
- package/src/components/atoms/DXDropdownItem/DXDropdownItem.vue +116 -0
- package/src/components/atoms/DXDropdownItem/index.js +2 -0
- package/src/components/atoms/DXFormLabel/DXFormLabel.stories.js +194 -0
- package/src/components/atoms/DXFormLabel/DXFormLabel.vue +94 -0
- package/src/components/atoms/DXFormLabel/index.js +2 -0
- package/src/components/atoms/DXIcon/DXIcon.stories.js +156 -0
- package/src/components/atoms/DXIcon/DXIcon.vue +102 -0
- package/src/components/atoms/DXIcon/index.js +3 -0
- package/src/components/atoms/DXIconWrapper/DXIconWrapper.stories.js +237 -0
- package/src/components/atoms/DXIconWrapper/DXIconWrapper.vue +79 -0
- package/src/components/atoms/DXIconWrapper/index.js +2 -0
- package/src/components/atoms/DXInputAddon/DXInputAddon.stories.js +230 -0
- package/src/components/atoms/DXInputAddon/DXInputAddon.vue +64 -0
- package/src/components/atoms/DXInputAddon/index.js +2 -0
- package/src/components/atoms/DXLink/DXLink.stories.js +475 -0
- package/src/components/atoms/DXLink/DXLink.vue +229 -0
- package/src/components/atoms/DXLink/index.js +2 -0
- package/src/components/atoms/DXLoader/DXLoader.stories.js +280 -0
- package/src/components/atoms/DXLoader/DXLoader.vue +78 -0
- package/src/components/atoms/DXLoader/index.js +2 -0
- package/src/components/atoms/DXProgress/DXProgress.stories.js +312 -0
- package/src/components/atoms/DXProgress/DXProgress.vue +85 -0
- package/src/components/atoms/DXProgress/index.js +2 -0
- package/src/components/atoms/DXQuote/DXQuote.stories.js +255 -0
- package/src/components/atoms/DXQuote/DXQuote.vue +97 -0
- package/src/components/atoms/DXQuote/index.js +2 -0
- package/src/components/atoms/DXRadio/DXRadio.stories.js +277 -0
- package/src/components/atoms/DXRadio/DXRadio.vue +144 -0
- package/src/components/atoms/DXRadio/index.js +2 -0
- package/src/components/atoms/DXSkeleton/DXSkeleton.stories.js +50 -0
- package/src/components/atoms/DXSkeleton/DXSkeleton.vue +19 -0
- package/src/components/atoms/DXSkeleton/index.js +2 -0
- package/src/components/atoms/DXSlider/DXSlider.stories.js +522 -0
- package/src/components/atoms/DXSlider/DXSlider.vue +338 -0
- package/src/components/atoms/DXSlider/index.js +2 -0
- package/src/components/atoms/DXTags/DXTags.stories.js +206 -0
- package/src/components/atoms/DXTags/DXTags.vue +111 -0
- package/src/components/atoms/DXTags/index.js +2 -0
- package/src/components/atoms/DXToast/DXToast.stories.js +40 -0
- package/src/components/atoms/DXToast/DXToast.vue +32 -0
- package/src/components/atoms/DXToast/index.js +2 -0
- package/src/components/atoms/DXToggle/DXToggle.stories.js +143 -0
- package/src/components/atoms/DXToggle/DXToggle.vue +142 -0
- package/src/components/atoms/DXToggle/index.js +2 -0
- package/src/components/atoms/DXToggleButton/DXToggleButton.stories.js +513 -0
- package/src/components/atoms/DXToggleButton/DXToggleButton.vue +140 -0
- package/src/components/atoms/DXToggleButton/index.js +2 -0
- package/src/components/atoms/DXTooltip/DXTooltip.stories.js +243 -0
- package/src/components/atoms/DXTooltip/DXTooltip.vue +151 -0
- package/src/components/atoms/DXTooltip/index.js +2 -0
- package/src/components/atoms/index.js +24 -0
- package/src/components/layout/DXBox/DXBox.stories.js +238 -0
- package/src/components/layout/DXBox/DXBox.vue +198 -0
- package/src/components/layout/DXBox/index.js +2 -0
- package/src/components/layout/DXContainer/DXContainer.stories.js +147 -0
- package/src/components/layout/DXContainer/DXContainer.vue +83 -0
- package/src/components/layout/DXContainer/index.js +2 -0
- package/src/components/layout/DXFlex/DXFlex.stories.js +210 -0
- package/src/components/layout/DXFlex/DXFlex.vue +149 -0
- package/src/components/layout/DXFlex/index.js +2 -0
- package/src/components/layout/DXGrid/DXGrid.stories.js +238 -0
- package/src/components/layout/DXGrid/DXGrid.vue +167 -0
- package/src/components/layout/DXGrid/index.js +2 -0
- package/src/components/layout/DXSpacer/DXSpacer.stories.js +187 -0
- package/src/components/layout/DXSpacer/DXSpacer.vue +102 -0
- package/src/components/layout/DXSpacer/index.js +2 -0
- package/src/components/layout/DXStack/DXStack.stories.js +199 -0
- package/src/components/layout/DXStack/DXStack.vue +140 -0
- package/src/components/layout/DXStack/index.js +2 -0
- package/src/components/layout/index.js +8 -0
- package/src/components/molecules/DXActionButtons/DXActionButtons.stories.js +288 -0
- package/src/components/molecules/DXActionButtons/DXActionButtons.vue +106 -0
- package/src/components/molecules/DXActionButtons/index.js +2 -0
- package/src/components/molecules/DXAlert/DXAlert.stories.js +70 -0
- package/src/components/molecules/DXAlert/DXAlert.vue +116 -0
- package/src/components/molecules/DXAlert/index.js +2 -0
- package/src/components/molecules/DXBaseTable/DXBaseTable.stories.js +433 -0
- package/src/components/molecules/DXBaseTable/DXBaseTable.vue +459 -0
- package/src/components/molecules/DXBaseTable/index.js +4 -0
- package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.stories.js +227 -0
- package/src/components/molecules/DXBreadcrumb/DXBreadcrumb.vue +96 -0
- package/src/components/molecules/DXBreadcrumb/index.js +2 -0
- package/src/components/molecules/DXButtonGroup/DXButtonGroup.stories.js +26 -0
- package/src/components/molecules/DXButtonGroup/DXButtonGroup.vue +78 -0
- package/src/components/molecules/DXButtonGroup/index.js +2 -0
- package/src/components/molecules/DXCloseButton/DXCloseButton.stories.js +53 -0
- package/src/components/molecules/DXCloseButton/DXCloseButton.vue +62 -0
- package/src/components/molecules/DXCloseButton/index.js +3 -0
- package/src/components/molecules/DXComboBox/DXComboBox.stories.js +62 -0
- package/src/components/molecules/DXComboBox/DXComboBox.vue +167 -0
- package/src/components/molecules/DXComboBox/index.js +2 -0
- package/src/components/molecules/DXCopyField/DXCopyField.stories.js +231 -0
- package/src/components/molecules/DXCopyField/DXCopyField.vue +75 -0
- package/src/components/molecules/DXCopyField/index.js +2 -0
- package/src/components/molecules/DXDataFilter/DXDataFilter.stories.js +275 -0
- package/src/components/molecules/DXDataFilter/DXDataFilter.vue +385 -0
- package/src/components/molecules/DXDataFilter/index.js +2 -0
- package/src/components/molecules/DXDatePicker/DXDatePicker.stories.js +42 -0
- package/src/components/molecules/DXDatePicker/DXDatePicker.vue +121 -0
- package/src/components/molecules/DXDatePicker/index.js +2 -0
- package/src/components/molecules/DXDropdownDivider/DXDropdownDivider.vue +30 -0
- package/src/components/molecules/DXDropdownDivider/index.js +2 -0
- package/src/components/molecules/DXFileUpload/DXFileUpload.stories.js +53 -0
- package/src/components/molecules/DXFileUpload/DXFileUpload.vue +199 -0
- package/src/components/molecules/DXFileUpload/index.js +2 -0
- package/src/components/molecules/DXFilterGroup/DXFilterGroup.stories.js +43 -0
- package/src/components/molecules/DXFilterGroup/DXFilterGroup.vue +43 -0
- package/src/components/molecules/DXFilterGroup/index.js +2 -0
- package/src/components/molecules/DXFormControl/DXFormControl.stories.js +69 -0
- package/src/components/molecules/DXFormControl/DXFormControl.vue +72 -0
- package/src/components/molecules/DXFormControl/index.js +2 -0
- package/src/components/molecules/DXInput/DXInput.stories.js +291 -0
- package/src/components/molecules/DXInput/DXInput.vue +156 -0
- package/src/components/molecules/DXInput/index.js +3 -0
- package/src/components/molecules/DXInputGroup/DXInputGroup.stories.js +228 -0
- package/src/components/molecules/DXInputGroup/DXInputGroup.vue +64 -0
- package/src/components/molecules/DXInputGroup/index.js +2 -0
- package/src/components/molecules/DXInputMask/DXInputMask.stories.js +53 -0
- package/src/components/molecules/DXInputMask/DXInputMask.vue +89 -0
- package/src/components/molecules/DXInputMask/index.js +2 -0
- package/src/components/molecules/DXMenu/DXMenu.stories.js +379 -0
- package/src/components/molecules/DXMenu/DXMenu.vue +331 -0
- package/src/components/molecules/DXMenu/README.md +479 -0
- package/src/components/molecules/DXMenu/index.js +2 -0
- package/src/components/molecules/DXPagination/DXPagination.stories.js +62 -0
- package/src/components/molecules/DXPagination/DXPagination.vue +123 -0
- package/src/components/molecules/DXPagination/index.js +2 -0
- package/src/components/molecules/DXPasswordInput/DXPasswordInput.stories.js +42 -0
- package/src/components/molecules/DXPasswordInput/DXPasswordInput.vue +74 -0
- package/src/components/molecules/DXPasswordInput/index.js +2 -0
- package/src/components/molecules/DXRadioCard/DXRadioCard.stories.js +60 -0
- package/src/components/molecules/DXRadioCard/DXRadioCard.vue +71 -0
- package/src/components/molecules/DXRadioCard/index.js +2 -0
- package/src/components/molecules/DXRadioGroup/DXRadioGroup.stories.js +297 -0
- package/src/components/molecules/DXRadioGroup/DXRadioGroup.vue +73 -0
- package/src/components/molecules/DXRadioGroup/index.js +2 -0
- package/src/components/molecules/DXRating/DXRating.stories.js +322 -0
- package/src/components/molecules/DXRating/DXRating.vue +402 -0
- package/src/components/molecules/DXRating/index.js +2 -0
- package/src/components/molecules/DXSearchBar/DXSearchBar.stories.js +357 -0
- package/src/components/molecules/DXSearchBar/DXSearchBar.vue +525 -0
- package/src/components/molecules/DXSearchBar/index.js +2 -0
- package/src/components/molecules/DXSearchSelect/DXSearchSelect.stories.js +50 -0
- package/src/components/molecules/DXSearchSelect/DXSearchSelect.vue +207 -0
- package/src/components/molecules/DXSearchSelect/index.js +2 -0
- package/src/components/molecules/DXSegmentedControl/DXSegmentedControl.stories.js +326 -0
- package/src/components/molecules/DXSegmentedControl/DXSegmentedControl.vue +116 -0
- package/src/components/molecules/DXSegmentedControl/index.js +2 -0
- package/src/components/molecules/DXSelect/DXSelect.stories.js +259 -0
- package/src/components/molecules/DXSelect/DXSelect.vue +149 -0
- package/src/components/molecules/DXSelect/index.js +3 -0
- package/src/components/molecules/DXStatCard/DXStatCard.stories.js +335 -0
- package/src/components/molecules/DXStatCard/DXStatCard.vue +309 -0
- package/src/components/molecules/DXStatCard/index.js +2 -0
- package/src/components/molecules/DXTableFiltersPanel/DXTableFiltersPanel.vue +72 -0
- package/src/components/molecules/DXTableFiltersPanel/index.js +7 -0
- package/src/components/molecules/DXTablePagination/DXTablePagination.stories.js +236 -0
- package/src/components/molecules/DXTablePagination/DXTablePagination.vue +93 -0
- package/src/components/molecules/DXTablePagination/index.js +2 -0
- package/src/components/molecules/DXTableToolbar/DXTableToolbar.stories.js +271 -0
- package/src/components/molecules/DXTableToolbar/DXTableToolbar.vue +102 -0
- package/src/components/molecules/DXTableToolbar/index.js +2 -0
- package/src/components/molecules/DXTextarea/DXTextarea.stories.js +239 -0
- package/src/components/molecules/DXTextarea/DXTextarea.vue +158 -0
- package/src/components/molecules/DXTextarea/index.js +3 -0
- package/src/components/molecules/DXTimePicker/DXTimePicker.stories.js +282 -0
- package/src/components/molecules/DXTimePicker/DXTimePicker.vue +640 -0
- package/src/components/molecules/DXTimePicker/index.js +2 -0
- package/src/components/molecules/DXValidationIcon/DXValidationIcon.stories.js +60 -0
- package/src/components/molecules/DXValidationIcon/DXValidationIcon.vue +53 -0
- package/src/components/molecules/DXValidationIcon/index.js +3 -0
- package/src/components/molecules/index.js +34 -0
- package/src/components/organisms/DXAccordion/DXAccordion.stories.js +33 -0
- package/src/components/organisms/DXAccordion/DXAccordion.vue +104 -0
- package/src/components/organisms/DXAccordion/index.js +2 -0
- package/src/components/organisms/DXAppLayout/DXAppLayout.stories.js +689 -0
- package/src/components/organisms/DXAppLayout/DXAppLayout.vue +460 -0
- package/src/components/organisms/DXAppLayout/index.js +2 -0
- package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.stories.js +232 -0
- package/src/components/organisms/DXAuthenticationForm/DXAuthenticationForm.vue +458 -0
- package/src/components/organisms/DXAuthenticationForm/index.js +2 -0
- package/src/components/organisms/DXChartContainer/DXChartContainer.stories.js +286 -0
- package/src/components/organisms/DXChartContainer/DXChartContainer.vue +273 -0
- package/src/components/organisms/DXChartContainer/index.js +2 -0
- package/src/components/organisms/DXChatInterface/DXChatInterface.stories.js +164 -0
- package/src/components/organisms/DXChatInterface/DXChatInterface.vue +583 -0
- package/src/components/organisms/DXChatInterface/index.js +2 -0
- package/src/components/organisms/DXCommentSection/DXCommentSection.stories.js +173 -0
- package/src/components/organisms/DXCommentSection/DXCommentSection.vue +487 -0
- package/src/components/organisms/DXCommentSection/index.js +2 -0
- package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.stories.js +331 -0
- package/src/components/organisms/DXDashboardGrid/DXDashboardGrid.vue +309 -0
- package/src/components/organisms/DXDashboardGrid/index.js +2 -0
- package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.stories.js +271 -0
- package/src/components/organisms/DXDashboardWidget/DXDashboardWidget.vue +260 -0
- package/src/components/organisms/DXDashboardWidget/index.js +2 -0
- package/src/components/organisms/DXDataTable/DXDataTable.stories.js +247 -0
- package/src/components/organisms/DXDataTable/DXDataTable.vue +496 -0
- package/src/components/organisms/DXDataTable/index.js +2 -0
- package/src/components/organisms/DXDropdown/DXDropdown.stories.js +795 -0
- package/src/components/organisms/DXDropdown/DXDropdown.vue +238 -0
- package/src/components/organisms/DXDropdown/index.js +2 -0
- package/src/components/organisms/DXEmptyState/DXEmptyState.stories.js +37 -0
- package/src/components/organisms/DXEmptyState/DXEmptyState.vue +41 -0
- package/src/components/organisms/DXEmptyState/index.js +2 -0
- package/src/components/organisms/DXFormWizard/DXFormWizard.stories.js +378 -0
- package/src/components/organisms/DXFormWizard/DXFormWizard.vue +578 -0
- package/src/components/organisms/DXFormWizard/index.js +2 -0
- package/src/components/organisms/DXHeaderBar/DXHeaderBar.stories.js +448 -0
- package/src/components/organisms/DXHeaderBar/DXHeaderBar.vue +190 -0
- package/src/components/organisms/DXHeaderBar/index.js +2 -0
- package/src/components/organisms/DXMediaGallery/DXMediaGallery.stories.js +347 -0
- package/src/components/organisms/DXMediaGallery/DXMediaGallery.vue +422 -0
- package/src/components/organisms/DXMediaGallery/index.js +2 -0
- package/src/components/organisms/DXModal/DXModal.stories.js +138 -0
- package/src/components/organisms/DXModal/DXModal.vue +213 -0
- package/src/components/organisms/DXModal/index.js +2 -0
- package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.stories.js +183 -0
- package/src/components/organisms/DXNotificationCenter/DXNotificationCenter.vue +566 -0
- package/src/components/organisms/DXNotificationCenter/index.js +2 -0
- package/src/components/organisms/DXReportGenerator/DXReportGenerator.stories.js +199 -0
- package/src/components/organisms/DXReportGenerator/DXReportGenerator.vue +344 -0
- package/src/components/organisms/DXReportGenerator/index.js +2 -0
- package/src/components/organisms/DXSettingsPanel/DXSettingsPanel.stories.js +245 -0
- package/src/components/organisms/DXSettingsPanel/DXSettingsPanel.vue +454 -0
- package/src/components/organisms/DXSettingsPanel/index.js +2 -0
- package/src/components/organisms/DXSidebar/DXSidebar.stories.js +316 -0
- package/src/components/organisms/DXSidebar/DXSidebar.vue +212 -0
- package/src/components/organisms/DXSidebar/index.js +2 -0
- package/src/components/organisms/DXSidebarMenu/DATA_STRUCTURE.md +299 -0
- package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.stories.js +729 -0
- package/src/components/organisms/DXSidebarMenu/DXSidebarMenu.vue +257 -0
- package/src/components/organisms/DXSidebarMenu/DXSidebarMenuItem.vue +249 -0
- package/src/components/organisms/DXSidebarMenu/README.md +333 -0
- package/src/components/organisms/DXSidebarMenu/index.js +3 -0
- package/src/components/organisms/DXTable/DXTable.stories.js +550 -0
- package/src/components/organisms/DXTable/DXTable.vue +324 -0
- package/src/components/organisms/DXTable/index.js +2 -0
- package/src/components/organisms/DXTabs/DXTabs.stories.js +407 -0
- package/src/components/organisms/DXTabs/DXTabs.vue +301 -0
- package/src/components/organisms/DXTabs/index.js +2 -0
- package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.stories.js +194 -0
- package/src/components/organisms/DXUserProfileCard/DXUserProfileCard.vue +403 -0
- package/src/components/organisms/DXUserProfileCard/index.js +2 -0
- package/src/components/organisms/DXWizard/DXWizard.stories.js +212 -0
- package/src/components/organisms/DXWizard/DXWizard.vue +615 -0
- package/src/components/organisms/DXWizard/index.js +2 -0
- package/src/components/organisms/index.js +25 -0
- package/src/components/typography/DXBlockquote/DXBlockquote.stories.js +33 -0
- package/src/components/typography/DXBlockquote/DXBlockquote.vue +44 -0
- package/src/components/typography/DXBlockquote/index.js +2 -0
- package/src/components/typography/DXCode/DXCode.stories.js +29 -0
- package/src/components/typography/DXCode/DXCode.vue +46 -0
- package/src/components/typography/DXCode/index.js +2 -0
- package/src/components/typography/DXHeading/DXHeading.stories.js +54 -0
- package/src/components/typography/DXHeading/DXHeading.vue +68 -0
- package/src/components/typography/DXHeading/index.js +2 -0
- package/src/components/typography/DXLabel/DXLabel.stories.js +40 -0
- package/src/components/typography/DXLabel/DXLabel.vue +49 -0
- package/src/components/typography/DXLabel/index.js +2 -0
- package/src/components/typography/DXList/DXList.stories.js +50 -0
- package/src/components/typography/DXList/DXList.vue +55 -0
- package/src/components/typography/DXList/index.js +2 -0
- package/src/components/typography/DXText/DXText.stories.js +47 -0
- package/src/components/typography/DXText/DXText.vue +67 -0
- package/src/components/typography/DXText/index.js +2 -0
- package/src/components/typography/index.js +8 -0
- package/src/components/utilities/DXAnimatePresence/DXAnimatePresence.stories.js +335 -0
- package/src/components/utilities/DXAnimatePresence/DXAnimatePresence.vue +207 -0
- package/src/components/utilities/DXAnimatePresence/index.js +2 -0
- package/src/components/utilities/DXBreakpointProvider/DXBreakpointProvider.stories.js +321 -0
- package/src/components/utilities/DXBreakpointProvider/DXBreakpointProvider.vue +158 -0
- package/src/components/utilities/DXBreakpointProvider/index.js +2 -0
- package/src/components/utilities/DXObserver/DXObserver.stories.js +324 -0
- package/src/components/utilities/DXObserver/DXObserver.vue +182 -0
- package/src/components/utilities/DXObserver/index.js +2 -0
- package/src/components/utilities/DXPortal/DXPortal.stories.js +267 -0
- package/src/components/utilities/DXPortal/DXPortal.vue +69 -0
- package/src/components/utilities/DXPortal/index.js +2 -0
- package/src/components/utilities/DXStaggeredAnimation/DXStaggeredAnimation.stories.js +339 -0
- package/src/components/utilities/DXStaggeredAnimation/DXStaggeredAnimation.vue +155 -0
- package/src/components/utilities/DXStaggeredAnimation/index.js +2 -0
- package/src/components/utilities/DXThemeProvider/DXThemeProvider.stories.js +327 -0
- package/src/components/utilities/DXThemeProvider/DXThemeProvider.vue +227 -0
- package/src/components/utilities/DXThemeProvider/index.js +2 -0
- package/src/components/utilities/DXTransitionGroup/DXTransitionGroup.stories.js +368 -0
- package/src/components/utilities/DXTransitionGroup/DXTransitionGroup.vue +212 -0
- package/src/components/utilities/DXTransitionGroup/index.js +2 -0
- package/src/components/utilities/index.js +9 -0
- package/src/composables/useAnimation.js +264 -0
- package/src/composables/useClassComposition.js +35 -0
- package/src/composables/useDataAttributes.js +83 -0
- package/src/composables/useMenu.js +88 -0
- package/src/composables/useSize.js +135 -0
- package/src/composables/useSpacing.js +37 -0
- package/src/composables/useTableColumns.js +88 -0
- package/src/composables/useTableData.js +82 -0
- package/src/composables/useTableFilter.js +158 -0
- package/src/composables/useTablePagination.js +89 -0
- package/src/composables/useTableSelection.js +77 -0
- package/src/composables/useTableSort.js +75 -0
- package/src/composables/useTabsScroll.js +88 -0
- package/src/composables/useVariant.js +700 -0
- package/src/index.js +86 -0
- package/src/styles/animations.css +171 -0
- package/src/styles/index.css +99 -0
- package/src/styles/tokens.js +123 -0
- package/src/utils/propTypes.js +77 -0
- package/src/utils/toggleButtonPresets.js +115 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
ref="containerRef"
|
|
4
|
+
:class="containerClasses"
|
|
5
|
+
data-component="DXStaggeredAnimation"
|
|
6
|
+
:data-direction="direction"
|
|
7
|
+
:data-transition="transition"
|
|
8
|
+
>
|
|
9
|
+
<slot />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
import { computed, onMounted, watch, nextTick, ref, onBeforeUnmount } from "vue";
|
|
15
|
+
import { useClassComposition } from "@/composables/useClassComposition";
|
|
16
|
+
|
|
17
|
+
const props = defineProps({
|
|
18
|
+
/**
|
|
19
|
+
* Задержка между элементами в миллисекундах
|
|
20
|
+
* @default 100
|
|
21
|
+
*/
|
|
22
|
+
delay: { type: Number, default: 100 },
|
|
23
|
+
/**
|
|
24
|
+
* Направление анимации: top-to-bottom | left-to-right | right-to-left | bottom-to-top
|
|
25
|
+
* @default 'top-to-bottom'
|
|
26
|
+
*/
|
|
27
|
+
direction: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: "top-to-bottom",
|
|
30
|
+
validator: (v) =>
|
|
31
|
+
[
|
|
32
|
+
"top-to-bottom",
|
|
33
|
+
"left-to-right",
|
|
34
|
+
"right-to-left",
|
|
35
|
+
"bottom-to-top",
|
|
36
|
+
].includes(v),
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Тип transition: fade | fade-slide | scale
|
|
40
|
+
* @default 'fade'
|
|
41
|
+
*/
|
|
42
|
+
transition: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: "fade",
|
|
45
|
+
validator: (v) => ["fade", "fade-slide", "scale"].includes(v),
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Длительность анимации в миллисекундах
|
|
49
|
+
* @default 300
|
|
50
|
+
*/
|
|
51
|
+
duration: { type: Number, default: 300 },
|
|
52
|
+
/**
|
|
53
|
+
* Анимировать при монтировании
|
|
54
|
+
* @default true
|
|
55
|
+
*/
|
|
56
|
+
animateOnMount: { type: Boolean, default: true },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const emit = defineEmits(["animation-complete"]);
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Классы для контейнера
|
|
63
|
+
*
|
|
64
|
+
* @description
|
|
65
|
+
* Базовые классы для контейнера анимации.
|
|
66
|
+
*
|
|
67
|
+
* @returns {Array} Массив классов
|
|
68
|
+
*/
|
|
69
|
+
const containerClasses = computed(() => useClassComposition("w-full"));
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Применение анимации к дочерним элементам
|
|
73
|
+
*
|
|
74
|
+
* @description
|
|
75
|
+
* Применяет анимацию с задержкой к каждому дочернему элементу.
|
|
76
|
+
*/
|
|
77
|
+
function applyStaggeredAnimation() {
|
|
78
|
+
nextTick(() => {
|
|
79
|
+
const container = document.querySelector(
|
|
80
|
+
'[data-component="DXStaggeredAnimation"]'
|
|
81
|
+
);
|
|
82
|
+
if (!container) return;
|
|
83
|
+
|
|
84
|
+
const children = Array.from(container.children);
|
|
85
|
+
let completedCount = 0;
|
|
86
|
+
|
|
87
|
+
children.forEach((child, index) => {
|
|
88
|
+
const delay = index * props.delay;
|
|
89
|
+
const childElement = child;
|
|
90
|
+
|
|
91
|
+
// Устанавливаем начальное состояние
|
|
92
|
+
childElement.style.opacity = "0";
|
|
93
|
+
childElement.style.transition = `all ${props.duration}ms ease-out`;
|
|
94
|
+
|
|
95
|
+
// Применяем начальные стили в зависимости от направления
|
|
96
|
+
switch (props.direction) {
|
|
97
|
+
case "top-to-bottom":
|
|
98
|
+
childElement.style.transform = "translateY(-20px)";
|
|
99
|
+
break;
|
|
100
|
+
case "bottom-to-top":
|
|
101
|
+
childElement.style.transform = "translateY(20px)";
|
|
102
|
+
break;
|
|
103
|
+
case "left-to-right":
|
|
104
|
+
childElement.style.transform = "translateX(-20px)";
|
|
105
|
+
break;
|
|
106
|
+
case "right-to-left":
|
|
107
|
+
childElement.style.transform = "translateX(20px)";
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (props.transition === "scale") {
|
|
112
|
+
childElement.style.transform += " scale(0.95)";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Применяем анимацию с задержкой
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
childElement.style.opacity = "1";
|
|
118
|
+
childElement.style.transform = "translate(0, 0) scale(1)";
|
|
119
|
+
|
|
120
|
+
// Отслеживаем завершение анимации
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
completedCount++;
|
|
123
|
+
if (completedCount === children.length) {
|
|
124
|
+
emit("animation-complete");
|
|
125
|
+
}
|
|
126
|
+
}, props.duration);
|
|
127
|
+
}, delay);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Применение анимации при монтировании
|
|
133
|
+
onMounted(() => {
|
|
134
|
+
if (props.animateOnMount) {
|
|
135
|
+
applyStaggeredAnimation();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Очистка при размонтировании (таймеры очищаются автоматически при размонтировании компонента)
|
|
140
|
+
|
|
141
|
+
// Реакция на изменение delay или direction
|
|
142
|
+
watch(
|
|
143
|
+
[() => props.delay, () => props.direction, () => props.transition],
|
|
144
|
+
() => {
|
|
145
|
+
if (props.animateOnMount) {
|
|
146
|
+
applyStaggeredAnimation();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
<style scoped>
|
|
153
|
+
/* CSS переменные для анимации применяются через inline стили */
|
|
154
|
+
</style>
|
|
155
|
+
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import { ref, inject } from 'vue';
|
|
2
|
+
import DXThemeProvider from './DXThemeProvider.vue';
|
|
3
|
+
import DXCard from '../../atoms/DXCard/DXCard.vue';
|
|
4
|
+
import DXButton from '../../atoms/DXButton/DXButton.vue';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Utilities/DXThemeProvider',
|
|
8
|
+
component: DXThemeProvider,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
parameters: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component: `
|
|
14
|
+
# DXThemeProvider
|
|
15
|
+
|
|
16
|
+
Провайдер для управления темами и цветовыми схемами приложения.
|
|
17
|
+
|
|
18
|
+
## Назначение
|
|
19
|
+
|
|
20
|
+
DXThemeProvider предоставляет систему управления темами через provide/inject и CSS переменные.
|
|
21
|
+
Позволяет переключаться между темами, сохранять выбор пользователя и использовать системную тему.
|
|
22
|
+
|
|
23
|
+
## Архитектура
|
|
24
|
+
|
|
25
|
+
### Использует
|
|
26
|
+
- Vue provide/inject - для доступа к теме в компонентах
|
|
27
|
+
- CSS переменные - для применения цветов темы
|
|
28
|
+
- localStorage - для сохранения выбранной темы (опционально)
|
|
29
|
+
- prefers-color-scheme - для определения системной темы (опционально)
|
|
30
|
+
|
|
31
|
+
### Используется в
|
|
32
|
+
- Корневой компонент приложения
|
|
33
|
+
- Любые компоненты, требующие доступа к теме
|
|
34
|
+
|
|
35
|
+
## Внутренняя логика
|
|
36
|
+
|
|
37
|
+
### CSS переменные
|
|
38
|
+
Цвета темы применяются как CSS переменные с префиксом \`--color-\`:
|
|
39
|
+
- \`--color-primary\`
|
|
40
|
+
- \`--color-background\`
|
|
41
|
+
- \`--color-text\`
|
|
42
|
+
- И другие цвета из объекта темы
|
|
43
|
+
|
|
44
|
+
### Provide/Inject
|
|
45
|
+
Компоненты могут получить доступ к теме через inject:
|
|
46
|
+
\`\`\`javascript
|
|
47
|
+
const theme = inject('theme');
|
|
48
|
+
theme.setTheme('dark');
|
|
49
|
+
\`\`\`
|
|
50
|
+
|
|
51
|
+
### Сохранение темы
|
|
52
|
+
Если \`persist={true}\`, тема сохраняется в localStorage и восстанавливается при загрузке.
|
|
53
|
+
|
|
54
|
+
## Особенности
|
|
55
|
+
|
|
56
|
+
### Системная тема
|
|
57
|
+
При \`useSystemTheme={true}\` автоматически определяется системная тема через \`prefers-color-scheme\`.
|
|
58
|
+
|
|
59
|
+
### Динамическое переключение
|
|
60
|
+
Тема может быть изменена динамически, все CSS переменные обновляются автоматически.
|
|
61
|
+
`,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
argTypes: {
|
|
66
|
+
theme: {
|
|
67
|
+
control: 'text',
|
|
68
|
+
description: 'Текущая тема.',
|
|
69
|
+
table: {
|
|
70
|
+
type: { summary: 'string' },
|
|
71
|
+
defaultValue: { summary: 'light' },
|
|
72
|
+
category: 'Theme',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
persist: {
|
|
76
|
+
control: 'boolean',
|
|
77
|
+
description: 'Сохранять тему в localStorage.',
|
|
78
|
+
table: {
|
|
79
|
+
type: { summary: 'boolean' },
|
|
80
|
+
defaultValue: { summary: 'false' },
|
|
81
|
+
category: 'Behavior',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
useSystemTheme: {
|
|
85
|
+
control: 'boolean',
|
|
86
|
+
description: 'Использовать системную тему (prefers-color-scheme).',
|
|
87
|
+
table: {
|
|
88
|
+
type: { summary: 'boolean' },
|
|
89
|
+
defaultValue: { summary: 'false' },
|
|
90
|
+
category: 'Behavior',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const defaultThemes = {
|
|
97
|
+
light: {
|
|
98
|
+
name: 'Светлая',
|
|
99
|
+
colors: {
|
|
100
|
+
primary: '#007bff',
|
|
101
|
+
background: '#ffffff',
|
|
102
|
+
text: '#000000',
|
|
103
|
+
border: '#e5e7eb',
|
|
104
|
+
surface: '#f9fafb',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
dark: {
|
|
108
|
+
name: 'Темная',
|
|
109
|
+
colors: {
|
|
110
|
+
primary: '#0d6efd',
|
|
111
|
+
background: '#1a1a1a',
|
|
112
|
+
text: '#ffffff',
|
|
113
|
+
border: '#374151',
|
|
114
|
+
surface: '#2d2d2d',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const Default = {
|
|
120
|
+
args: {
|
|
121
|
+
theme: 'light',
|
|
122
|
+
themes: defaultThemes,
|
|
123
|
+
},
|
|
124
|
+
parameters: {
|
|
125
|
+
docs: {
|
|
126
|
+
description: {
|
|
127
|
+
story: 'Базовое использование провайдера тем с переключением между светлой и темной темой.',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
render: (args) => ({
|
|
132
|
+
components: { DXThemeProvider, DXCard, DXButton },
|
|
133
|
+
setup() {
|
|
134
|
+
const theme = ref(args.theme);
|
|
135
|
+
const themes = ref(args.themes);
|
|
136
|
+
|
|
137
|
+
const toggleTheme = () => {
|
|
138
|
+
theme.value = theme.value === 'light' ? 'dark' : 'light';
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return { theme, themes, toggleTheme };
|
|
142
|
+
},
|
|
143
|
+
template: `
|
|
144
|
+
<DXThemeProvider :theme="theme" :themes="themes">
|
|
145
|
+
<div class="min-h-screen p-8" style="background-color: var(--color-background, #ffffff); color: var(--color-text, #000000);">
|
|
146
|
+
<div class="space-y-4">
|
|
147
|
+
<DXButton @click="toggleTheme">
|
|
148
|
+
Переключить тему ({{ theme === 'light' ? 'Темная' : 'Светлая' }})
|
|
149
|
+
</DXButton>
|
|
150
|
+
<DXCard class="p-4" style="background-color: var(--color-surface, #f9fafb); border-color: var(--color-border, #e5e7eb);">
|
|
151
|
+
<h2 class="text-xl font-semibold mb-2">Текущая тема: {{ theme }}</h2>
|
|
152
|
+
<p>Этот контент использует цвета текущей темы через CSS переменные.</p>
|
|
153
|
+
<div class="mt-4 p-3 rounded" style="background-color: var(--color-primary, #007bff); color: white;">
|
|
154
|
+
Primary цвет темы
|
|
155
|
+
</div>
|
|
156
|
+
</DXCard>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</DXThemeProvider>
|
|
160
|
+
`,
|
|
161
|
+
}),
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export const WithPersistence = {
|
|
165
|
+
args: {
|
|
166
|
+
theme: 'light',
|
|
167
|
+
themes: defaultThemes,
|
|
168
|
+
persist: true,
|
|
169
|
+
},
|
|
170
|
+
parameters: {
|
|
171
|
+
docs: {
|
|
172
|
+
description: {
|
|
173
|
+
story: 'Провайдер с сохранением темы в localStorage. Тема сохраняется и восстанавливается при перезагрузке.',
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
render: (args) => ({
|
|
178
|
+
components: { DXThemeProvider, DXCard, DXButton },
|
|
179
|
+
setup() {
|
|
180
|
+
const theme = ref(args.theme);
|
|
181
|
+
const themes = ref(args.themes);
|
|
182
|
+
|
|
183
|
+
const toggleTheme = () => {
|
|
184
|
+
theme.value = theme.value === 'light' ? 'dark' : 'light';
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return { theme, themes, toggleTheme };
|
|
188
|
+
},
|
|
189
|
+
template: `
|
|
190
|
+
<DXThemeProvider :theme="theme" :themes="themes" :persist="true">
|
|
191
|
+
<div class="min-h-screen p-8" style="background-color: var(--color-background, #ffffff); color: var(--color-text, #000000);">
|
|
192
|
+
<div class="space-y-4">
|
|
193
|
+
<DXCard class="p-4" style="background-color: var(--color-surface, #f9fafb);">
|
|
194
|
+
<p class="mb-2">Тема сохраняется в localStorage</p>
|
|
195
|
+
<p class="text-sm text-slate-500">Перезагрузите страницу, чтобы увидеть сохранение</p>
|
|
196
|
+
</DXCard>
|
|
197
|
+
<DXButton @click="toggleTheme">
|
|
198
|
+
Переключить тему ({{ theme === 'light' ? 'Темная' : 'Светлая' }})
|
|
199
|
+
</DXButton>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</DXThemeProvider>
|
|
203
|
+
`,
|
|
204
|
+
}),
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export const WithInject = {
|
|
208
|
+
parameters: {
|
|
209
|
+
docs: {
|
|
210
|
+
description: {
|
|
211
|
+
story: 'Использование темы через inject в дочерних компонентах.',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
render: () => ({
|
|
216
|
+
components: { DXThemeProvider, DXCard, DXButton },
|
|
217
|
+
setup() {
|
|
218
|
+
const themes = ref(defaultThemes);
|
|
219
|
+
|
|
220
|
+
// Компонент, использующий inject
|
|
221
|
+
const ThemedComponent = {
|
|
222
|
+
setup() {
|
|
223
|
+
const theme = inject('theme');
|
|
224
|
+
return { theme };
|
|
225
|
+
},
|
|
226
|
+
template: `
|
|
227
|
+
<DXCard class="p-4" style="background-color: var(--color-surface, #f9fafb);">
|
|
228
|
+
<h3 class="font-semibold mb-2">Доступ к теме через inject</h3>
|
|
229
|
+
<p class="mb-2">Текущая тема: {{ theme.currentTheme.value }}</p>
|
|
230
|
+
<p class="mb-2">Доступные темы: {{ theme.availableThemes.value.join(', ') }}</p>
|
|
231
|
+
<DXButton @click="theme.setTheme()" size="sm">
|
|
232
|
+
Переключить тему
|
|
233
|
+
</DXButton>
|
|
234
|
+
</DXCard>
|
|
235
|
+
`,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
return { themes, ThemedComponent };
|
|
239
|
+
},
|
|
240
|
+
template: `
|
|
241
|
+
<DXThemeProvider :themes="themes">
|
|
242
|
+
<div class="min-h-screen p-8" style="background-color: var(--color-background, #ffffff); color: var(--color-text, #000000);">
|
|
243
|
+
<ThemedComponent />
|
|
244
|
+
</div>
|
|
245
|
+
</DXThemeProvider>
|
|
246
|
+
`,
|
|
247
|
+
}),
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
export const CustomThemes = {
|
|
251
|
+
parameters: {
|
|
252
|
+
docs: {
|
|
253
|
+
description: {
|
|
254
|
+
story: 'Кастомные темы с дополнительными цветами.',
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
render: () => ({
|
|
259
|
+
components: { DXThemeProvider, DXCard, DXButton },
|
|
260
|
+
setup() {
|
|
261
|
+
const theme = ref('blue');
|
|
262
|
+
const themes = ref({
|
|
263
|
+
blue: {
|
|
264
|
+
name: 'Синяя',
|
|
265
|
+
colors: {
|
|
266
|
+
primary: '#3b82f6',
|
|
267
|
+
background: '#eff6ff',
|
|
268
|
+
text: '#1e3a8a',
|
|
269
|
+
border: '#93c5fd',
|
|
270
|
+
surface: '#dbeafe',
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
green: {
|
|
274
|
+
name: 'Зеленая',
|
|
275
|
+
colors: {
|
|
276
|
+
primary: '#10b981',
|
|
277
|
+
background: '#ecfdf5',
|
|
278
|
+
text: '#065f46',
|
|
279
|
+
border: '#6ee7b7',
|
|
280
|
+
surface: '#d1fae5',
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
purple: {
|
|
284
|
+
name: 'Фиолетовая',
|
|
285
|
+
colors: {
|
|
286
|
+
primary: '#8b5cf6',
|
|
287
|
+
background: '#f5f3ff',
|
|
288
|
+
text: '#5b21b6',
|
|
289
|
+
border: '#c4b5fd',
|
|
290
|
+
surface: '#e9d5ff',
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const setTheme = (themeName) => {
|
|
296
|
+
theme.value = themeName;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
return { theme, themes, setTheme };
|
|
300
|
+
},
|
|
301
|
+
template: `
|
|
302
|
+
<DXThemeProvider :theme="theme" :themes="themes">
|
|
303
|
+
<div class="min-h-screen p-8" style="background-color: var(--color-background, #ffffff); color: var(--color-text, #000000);">
|
|
304
|
+
<div class="space-y-4">
|
|
305
|
+
<div class="flex gap-2">
|
|
306
|
+
<DXButton
|
|
307
|
+
v-for="(themeData, themeName) in themes"
|
|
308
|
+
:key="themeName"
|
|
309
|
+
:variant="theme === themeName ? 'primary' : 'ghost'"
|
|
310
|
+
@click="setTheme(themeName)"
|
|
311
|
+
>
|
|
312
|
+
{{ themeData.name }}
|
|
313
|
+
</DXButton>
|
|
314
|
+
</div>
|
|
315
|
+
<DXCard class="p-4" style="background-color: var(--color-surface, #f9fafb); border-color: var(--color-border, #e5e7eb);">
|
|
316
|
+
<h2 class="text-xl font-semibold mb-2">Текущая тема: {{ theme }}</h2>
|
|
317
|
+
<div class="mt-4 p-3 rounded" style="background-color: var(--color-primary, #007bff); color: white;">
|
|
318
|
+
Primary цвет темы
|
|
319
|
+
</div>
|
|
320
|
+
</DXCard>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</DXThemeProvider>
|
|
324
|
+
`,
|
|
325
|
+
}),
|
|
326
|
+
};
|
|
327
|
+
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="providerClasses"
|
|
4
|
+
:data-theme="currentTheme"
|
|
5
|
+
data-component="DXThemeProvider"
|
|
6
|
+
>
|
|
7
|
+
<slot />
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<script setup>
|
|
12
|
+
import { ref, computed, watch, provide, onMounted } from "vue";
|
|
13
|
+
import { useClassComposition } from "@/composables/useClassComposition";
|
|
14
|
+
|
|
15
|
+
const props = defineProps({
|
|
16
|
+
/**
|
|
17
|
+
* Текущая тема
|
|
18
|
+
* @default 'light'
|
|
19
|
+
*/
|
|
20
|
+
theme: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: "light",
|
|
23
|
+
},
|
|
24
|
+
/**
|
|
25
|
+
* Объект с доступными темами
|
|
26
|
+
* Формат: { themeName: { name, colors: { primary, background, text, ... } } }
|
|
27
|
+
* @default {}
|
|
28
|
+
*/
|
|
29
|
+
themes: {
|
|
30
|
+
type: Object,
|
|
31
|
+
default: () => ({}),
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Сохранять тему в localStorage
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
persist: { type: Boolean, default: false },
|
|
38
|
+
/**
|
|
39
|
+
* Ключ для сохранения в localStorage
|
|
40
|
+
* @default 'dx-theme'
|
|
41
|
+
*/
|
|
42
|
+
storageKey: { type: String, default: "dx-theme" },
|
|
43
|
+
/**
|
|
44
|
+
* Использовать системную тему (prefers-color-scheme)
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
47
|
+
useSystemTheme: { type: Boolean, default: false },
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const emit = defineEmits(["theme-change"]);
|
|
51
|
+
|
|
52
|
+
const currentTheme = ref(props.theme);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Классы для провайдера
|
|
56
|
+
*
|
|
57
|
+
* @description
|
|
58
|
+
* Базовые классы для контейнера провайдера тем.
|
|
59
|
+
*
|
|
60
|
+
* @returns {Array} Массив классов
|
|
61
|
+
*/
|
|
62
|
+
const providerClasses = computed(() => useClassComposition("w-full h-full"));
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Текущая тема с учетом системной
|
|
66
|
+
*
|
|
67
|
+
* @description
|
|
68
|
+
* Возвращает текущую тему, учитывая системную тему если useSystemTheme включен.
|
|
69
|
+
*
|
|
70
|
+
* @returns {string} Название текущей темы
|
|
71
|
+
*/
|
|
72
|
+
const effectiveTheme = computed(() => {
|
|
73
|
+
if (props.useSystemTheme) {
|
|
74
|
+
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
75
|
+
? "dark"
|
|
76
|
+
: "light";
|
|
77
|
+
return systemTheme;
|
|
78
|
+
}
|
|
79
|
+
return currentTheme.value;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Цвета текущей темы
|
|
84
|
+
*
|
|
85
|
+
* @description
|
|
86
|
+
* Извлекает цвета из объекта themes для текущей темы.
|
|
87
|
+
*
|
|
88
|
+
* @returns {Object} Объект с цветами темы
|
|
89
|
+
*/
|
|
90
|
+
const themeColors = computed(() => {
|
|
91
|
+
const theme = props.themes[effectiveTheme.value];
|
|
92
|
+
if (!theme || !theme.colors) {
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
return theme.colors;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Применение CSS переменных темы
|
|
100
|
+
*
|
|
101
|
+
* @description
|
|
102
|
+
* Применяет цвета темы как CSS переменные к корневому элементу.
|
|
103
|
+
*/
|
|
104
|
+
function applyTheme() {
|
|
105
|
+
const colors = themeColors.value;
|
|
106
|
+
const root = document.documentElement;
|
|
107
|
+
|
|
108
|
+
Object.keys(colors).forEach((key) => {
|
|
109
|
+
const cssVar = `--color-${key}`;
|
|
110
|
+
root.style.setProperty(cssVar, colors[key]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Применяем класс темы к body для удобства стилизации
|
|
114
|
+
document.body.setAttribute("data-theme", effectiveTheme.value);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Загрузка темы из localStorage
|
|
119
|
+
*
|
|
120
|
+
* @description
|
|
121
|
+
* Загружает сохраненную тему из localStorage если persist включен.
|
|
122
|
+
*/
|
|
123
|
+
function loadThemeFromStorage() {
|
|
124
|
+
if (!props.persist) return;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const savedTheme = localStorage.getItem(props.storageKey);
|
|
128
|
+
if (savedTheme && props.themes[savedTheme]) {
|
|
129
|
+
currentTheme.value = savedTheme;
|
|
130
|
+
emit("theme-change", savedTheme);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.warn("DXThemeProvider: Ошибка загрузки темы из localStorage", error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Сохранение темы в localStorage
|
|
139
|
+
*
|
|
140
|
+
* @description
|
|
141
|
+
* Сохраняет текущую тему в localStorage если persist включен.
|
|
142
|
+
*/
|
|
143
|
+
function saveThemeToStorage() {
|
|
144
|
+
if (!props.persist) return;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
localStorage.setItem(props.storageKey, currentTheme.value);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.warn("DXThemeProvider: Ошибка сохранения темы в localStorage", error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Переключение темы
|
|
155
|
+
*
|
|
156
|
+
* @description
|
|
157
|
+
* Переключает тему на следующую из списка доступных тем.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} themeName - Название темы для переключения (опционально)
|
|
160
|
+
*/
|
|
161
|
+
function setTheme(themeName = null) {
|
|
162
|
+
const availableThemes = Object.keys(props.themes);
|
|
163
|
+
if (availableThemes.length === 0) return;
|
|
164
|
+
|
|
165
|
+
if (themeName && props.themes[themeName]) {
|
|
166
|
+
currentTheme.value = themeName;
|
|
167
|
+
} else {
|
|
168
|
+
// Переключение на следующую тему
|
|
169
|
+
const currentIndex = availableThemes.indexOf(currentTheme.value);
|
|
170
|
+
const nextIndex = (currentIndex + 1) % availableThemes.length;
|
|
171
|
+
currentTheme.value = availableThemes[nextIndex];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
saveThemeToStorage();
|
|
175
|
+
emit("theme-change", currentTheme.value);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Provide темы для дочерних компонентов
|
|
179
|
+
provide("theme", {
|
|
180
|
+
currentTheme: computed(() => currentTheme.value),
|
|
181
|
+
effectiveTheme,
|
|
182
|
+
themeColors,
|
|
183
|
+
setTheme,
|
|
184
|
+
availableThemes: computed(() => Object.keys(props.themes)),
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Применение темы при изменении
|
|
188
|
+
watch(
|
|
189
|
+
[effectiveTheme, () => props.themes],
|
|
190
|
+
() => {
|
|
191
|
+
applyTheme();
|
|
192
|
+
},
|
|
193
|
+
{ immediate: true }
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Отслеживание изменений системной темы
|
|
197
|
+
let systemThemeMediaQuery = null;
|
|
198
|
+
if (props.useSystemTheme) {
|
|
199
|
+
systemThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
200
|
+
systemThemeMediaQuery.addEventListener("change", () => {
|
|
201
|
+
applyTheme();
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Инициализация при монтировании
|
|
206
|
+
onMounted(() => {
|
|
207
|
+
loadThemeFromStorage();
|
|
208
|
+
applyTheme();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Реакция на изменение prop theme
|
|
212
|
+
watch(
|
|
213
|
+
() => props.theme,
|
|
214
|
+
(newTheme) => {
|
|
215
|
+
if (newTheme !== currentTheme.value && props.themes[newTheme]) {
|
|
216
|
+
currentTheme.value = newTheme;
|
|
217
|
+
saveThemeToStorage();
|
|
218
|
+
emit("theme-change", newTheme);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
</script>
|
|
223
|
+
|
|
224
|
+
<style scoped>
|
|
225
|
+
/* CSS переменные применяются динамически через JavaScript */
|
|
226
|
+
</style>
|
|
227
|
+
|