├── .gitignore ├── .npmignore ├── README.md ├── _docs ├── .gitignore ├── .npmrc ├── README.md ├── app.config.ts ├── components │ ├── Logo.vue │ └── content │ │ ├── ColorGuide.vue │ │ ├── Colors.vue │ │ ├── Demo.vue │ │ ├── Pagination │ │ ├── PaginationCompact.vue │ │ ├── PaginationCount.vue │ │ ├── PaginationDemo.vue │ │ └── PaginationRanges.vue │ │ ├── Popup │ │ ├── PopupBeforeClose.vue │ │ ├── PopupDemo.vue │ │ ├── PopupFullWidth.vue │ │ ├── PopupNoClose.vue │ │ └── PopupSlots.vue │ │ ├── Tabs │ │ ├── TabsDefault.vue │ │ ├── TabsDemo.vue │ │ ├── TabsDisabled.vue │ │ ├── TabsIcon.vue │ │ ├── TabsScrollable.vue │ │ └── TabsVModel.vue │ │ ├── button │ │ ├── ButtonColors.vue │ │ ├── ButtonCompact.vue │ │ ├── ButtonDefault.vue │ │ ├── ButtonDemo.vue │ │ ├── ButtonIcon.vue │ │ ├── ButtonLoading.vue │ │ ├── ButtonRouting.vue │ │ └── ButtonTypes.vue │ │ ├── checkbox │ │ ├── CheckboxArray.vue │ │ └── CheckboxDemo.vue │ │ ├── input │ │ ├── InputColor.vue │ │ ├── InputDefault.vue │ │ ├── InputDemo.vue │ │ ├── InputError.vue │ │ ├── InputIcon.vue │ │ ├── InputLabel.vue │ │ ├── InputSlots.vue │ │ ├── InputTagElement.vue │ │ └── InputWithDirective.vue │ │ ├── loading │ │ ├── LoadingDemo.vue │ │ ├── LoadingStyling.vue │ │ └── LoadingTarget.vue │ │ ├── notification │ │ ├── CookieExample.vue │ │ ├── NotificationBefore.vue │ │ ├── NotificationClose.vue │ │ ├── NotificationDemo.vue │ │ ├── NotificationDuration.vue │ │ ├── NotificationExamples.vue │ │ ├── NotificationStyling.vue │ │ └── NotificationWidth.vue │ │ ├── radio │ │ ├── RadioDefault.vue │ │ ├── RadioDemo.vue │ │ └── RadioTag.vue │ │ ├── select │ │ ├── SelectAsync.vue │ │ ├── SelectBase.vue │ │ ├── SelectCustomOption.vue │ │ ├── SelectCustomSearch.vue │ │ ├── SelectCustomSelectedItems.vue │ │ ├── SelectDefault.vue │ │ ├── SelectDemo.vue │ │ ├── SelectDisabled.vue │ │ ├── SelectGroup.vue │ │ ├── SelectMultiple.vue │ │ ├── SelectNewOption.vue │ │ ├── SelectOptimized.vue │ │ └── SelectOptimizedGrouped.vue │ │ ├── slider │ │ ├── SliderCustomTick.vue │ │ ├── SliderDemo.vue │ │ ├── SliderRange.vue │ │ ├── SliderStep.vue │ │ ├── SliderTickSlot.vue │ │ ├── SliderTicks.vue │ │ └── SliderTooltip.vue │ │ └── switch │ │ ├── SwitchAlternative.vue │ │ ├── SwitchArray.vue │ │ ├── SwitchColor.vue │ │ ├── SwitchDefault.vue │ │ └── SwitchSlots.vue ├── content │ ├── 0.index.md │ ├── 1.guide │ │ ├── 0.index.md │ │ ├── 1.customization.md │ │ └── _dir.yml │ ├── 2.components │ │ ├── 0.button.md │ │ ├── 1.input.md │ │ ├── 2.select.md │ │ ├── 3.checkbox.md │ │ ├── 4.tabs.md │ │ ├── 5.popup.md │ │ ├── 6.pagination.md │ │ ├── 7.slider.md │ │ ├── 8.radio.md │ │ ├── 9.switch.md │ │ └── _dir.yml │ └── 3.composables │ │ ├── 1.useNotification.md │ │ ├── 2.useLoading.md │ │ └── _dir.yml ├── nuxt.config.ts ├── package-lock.json ├── package.json ├── plugins │ └── sevue.ts ├── public │ └── favicon.ico ├── renovate.json ├── style │ └── style.scss ├── tokens.config.ts └── tsconfig.json ├── components.d.ts ├── dev ├── App.vue ├── assets │ ├── fonts │ │ ├── Inter-Bold.ttf │ │ ├── Inter-Light.ttf │ │ ├── Inter-Medium.ttf │ │ └── Inter-Regular.ttf │ └── images │ │ └── cookies.svg ├── components │ ├── Cnot.vue │ └── InputWithDirective.vue ├── main.ts ├── mock │ └── index.ts ├── pages │ ├── AlertPage.vue │ ├── ButtonPage.vue │ ├── CheckboxPage.vue │ ├── DropdownPage.vue │ ├── HomePage.vue │ ├── InputPage.vue │ ├── LoadingPage.vue │ ├── NotificationPage.vue │ ├── PaginationPage.vue │ ├── PlaygroundPage.vue │ ├── PopupPage.vue │ ├── RadioPage.vue │ ├── SelectNewPage.vue │ ├── SelectPage.vue │ ├── SliderPage.vue │ ├── SwitchPage.vue │ └── TabsPage.vue ├── router.ts └── style │ └── main.scss ├── dist.zip ├── docs ├── .vitepress │ ├── config.mts │ ├── styles │ │ └── doc-style.scss │ └── theme │ │ └── index.ts ├── components │ ├── Colors.vue │ ├── Demo.vue │ ├── button │ │ ├── ButtonColors.vue │ │ ├── ButtonCompact.vue │ │ ├── ButtonDefault.vue │ │ ├── ButtonDemo.vue │ │ ├── ButtonIcon.vue │ │ ├── ButtonLoading.vue │ │ ├── ButtonRouting.vue │ │ └── ButtonTypes.vue │ ├── checkbox │ │ ├── CheckboxArray.vue │ │ └── CheckboxDemo.vue │ ├── icons │ │ ├── CloseIcon.vue │ │ └── SearchIcon.vue │ ├── input │ │ ├── InputColor.vue │ │ ├── InputDefault.vue │ │ ├── InputDemo.vue │ │ ├── InputError.vue │ │ ├── InputIcon.vue │ │ ├── InputLabel.vue │ │ ├── InputSlots.vue │ │ ├── InputTagElement.vue │ │ └── InputWithDirective.vue │ ├── pagination │ │ ├── PaginationCompact.vue │ │ ├── PaginationCount.vue │ │ ├── PaginationDemo.vue │ │ └── PaginationRanges.vue │ ├── popup │ │ ├── PopupBeforeClose.vue │ │ ├── PopupClose.vue │ │ ├── PopupDemo.vue │ │ ├── PopupFullWidth.vue │ │ └── PopupSlots.vue │ ├── select │ │ ├── SelectAsync.vue │ │ ├── SelectBase.vue │ │ ├── SelectCustomOption.vue │ │ ├── SelectCustomOptionContent.vue │ │ ├── SelectCustomSearch.vue │ │ ├── SelectCustomSelectedItems.vue │ │ ├── SelectDefault.vue │ │ ├── SelectDemo.vue │ │ ├── SelectDisabled.vue │ │ ├── SelectGroup.vue │ │ ├── SelectMultiple.vue │ │ ├── SelectNewOption.vue │ │ ├── SelectOptimized.vue │ │ └── SelectOptimizedGrouped.vue │ └── tabs │ │ ├── TabsDefault.vue │ │ ├── TabsDemo.vue │ │ ├── TabsDisabled.vue │ │ ├── TabsIcon.vue │ │ ├── TabsScrollable.vue │ │ └── TabsVModel.vue ├── package-lock.json ├── package.json └── src │ ├── api-examples.md │ ├── components │ ├── button.md │ ├── checkbox.md │ ├── input.md │ ├── pagination.md │ ├── popup.md │ ├── select.md │ └── tabs.md │ ├── guide │ ├── customization.md │ └── index.md │ ├── index.md │ ├── markdown-examples.md │ └── public │ └── images │ ├── flag-fr.png │ ├── flag-gr.png │ ├── flag-it.png │ └── flag-uk.png ├── env.d.ts ├── index.html ├── package-lock.json ├── package.json ├── src ├── components │ ├── HeightTransition.vue │ ├── LoadingSpinner.vue │ ├── VNodeRenderer.vue │ ├── alert │ │ ├── RAlert.vue │ │ └── index.ts │ ├── button │ │ ├── RButton.vue │ │ └── index.ts │ ├── checkbox │ │ ├── CheckboxRoot.vue │ │ ├── RCheckbox.vue │ │ └── index.ts │ ├── dropdown │ │ ├── DropdownContent.vue │ │ ├── DropdownItem.vue │ │ ├── DropdownRoot.vue │ │ ├── DropdownTrigger.vue │ │ ├── RDropdown.vue │ │ ├── RDropdownItem.vue │ │ └── index.ts │ ├── icons │ │ ├── SevueIcon.vue │ │ └── svgs │ │ │ ├── check.svg │ │ │ ├── chevron-down.svg │ │ │ ├── chevron-left.svg │ │ │ ├── chevron-right.svg │ │ │ └── close.svg │ ├── index.ts │ ├── input │ │ ├── RInput.vue │ │ └── index.ts │ ├── internal │ │ ├── FieldLabel.vue │ │ ├── FieldMessage.vue │ │ ├── InputContainer.vue │ │ ├── Label.vue │ │ └── index.ts │ ├── loading │ │ ├── RLoading.vue │ │ └── index.ts │ ├── notification │ │ ├── Notification.vue │ │ ├── NotificationContainer.vue │ │ └── index.ts │ ├── pagination │ │ ├── RPagination.vue │ │ └── index.ts │ ├── popper │ │ ├── PopperContent.vue │ │ ├── PopperReference.vue │ │ ├── PopperRoot.vue │ │ └── index.ts │ ├── popup │ │ ├── PopupClose.vue │ │ ├── PopupContent.vue │ │ ├── PopupDescription.vue │ │ ├── PopupOverlay.vue │ │ ├── PopupRoot.vue │ │ ├── PopupTitle.vue │ │ ├── RPopup.vue │ │ └── index.ts │ ├── primitive │ │ ├── Primitive.ts │ │ ├── Slot.ts │ │ └── index.ts │ ├── provider │ │ ├── Provider.vue │ │ └── index.ts │ ├── radio │ │ ├── RRadio.vue │ │ ├── RadioRoot.vue │ │ └── index.ts │ ├── roving-focus │ │ ├── RovingFocusItem.vue │ │ ├── RovingFocusRoot.vue │ │ ├── index.ts │ │ └── utils.ts │ ├── select │ │ ├── ROption.vue │ │ ├── RSelect.vue │ │ ├── RSelectGroup.vue │ │ ├── RSelectInput.vue │ │ └── index.ts │ ├── select_prev │ │ ├── ROption.vue │ │ ├── RSelect.vue │ │ ├── RSelectGroup.vue │ │ ├── SelectedItems.vue │ │ └── index.ts │ ├── slider │ │ ├── RSlider.vue │ │ ├── RSliderDot.vue │ │ ├── RSliderTick.vue │ │ └── index.ts │ ├── switch │ │ ├── RSwitch.vue │ │ └── index.ts │ └── tabs │ │ ├── RPanel.vue │ │ ├── RPanelItem.vue │ │ ├── RTab.vue │ │ ├── RTabItem.vue │ │ ├── TabsIndicator.vue │ │ ├── TabsItem.vue │ │ ├── TabsRoot.vue │ │ └── index.ts ├── composables │ ├── useCollection.ts │ ├── useColor.ts │ ├── useContext.ts │ ├── useDirection.ts │ ├── useDynamicSlots.ts │ ├── useEmitsAsProps.ts │ ├── useFloating.ts │ ├── useFocusTrap.ts │ ├── useForwardExpose.ts │ ├── useForwardRef.ts │ ├── useId.ts │ ├── useLoading.ts │ ├── useNotification.ts │ ├── useSevue.ts │ └── useTimer.ts ├── directives │ ├── appendToBody.ts │ ├── clickOutside.ts │ └── ripple.ts ├── injectionKeys.ts ├── main.ts ├── styles │ ├── index.scss │ ├── ripple.scss │ └── variables.scss ├── types │ └── index.ts └── utils │ ├── createContext.ts │ ├── getRelatedChildren.ts │ ├── index.ts │ ├── mountComponent.ts │ ├── popper.ts │ └── renderSlotFragments.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.slns 28 | *.sw? 29 | 30 | docs/.vitepress/dist 31 | docs/.vitepress/cache -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dev 3 | src -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SEVUE 2 | 3 | ## UI components for Vue/Nuxt 3 4 | 5 |
6 | 7 |
8 | 9 | ### 📌 Documentation 10 | [sevue.sedevs.com](https://sevue.sedevs.com) 11 | 12 | ### Components 13 | - button 14 | - input 15 | - select 16 | - checkbox 17 | - tabs 18 | - popup 19 | - pagination 20 | - slider 21 | - radio 22 | - switch 23 | 24 | ### Composables 25 | - useNotification 26 | - useLoading 27 | 28 | > ⚠️ Not all components are ready yet, use at your own risk. -------------------------------------------------------------------------------- /_docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | sw.* 11 | .env 12 | .output 13 | -------------------------------------------------------------------------------- /_docs/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /_docs/README.md: -------------------------------------------------------------------------------- 1 | # Docus Starter 2 | 3 | Starter template for [Docus](https://docus.dev). 4 | 5 | ## Clone 6 | 7 | Clone the repository (using `nuxi`): 8 | 9 | ```bash 10 | npx nuxi init -t themes/docus 11 | ``` 12 | 13 | ## Setup 14 | 15 | Install dependencies: 16 | 17 | ```bash 18 | yarn install 19 | ``` 20 | 21 | ## Development 22 | 23 | ```bash 24 | yarn dev 25 | ``` 26 | 27 | ## Edge Side Rendering 28 | 29 | Can be deployed to Vercel Functions, Netlify Functions, AWS, and most Node-compatible environments. 30 | 31 | Look at all the available presets [here](https://v3.nuxtjs.org/guide/deploy/presets). 32 | 33 | ```bash 34 | yarn build 35 | ``` 36 | 37 | ## Static Generation 38 | 39 | Use the `generate` command to build your application. 40 | 41 | The HTML files will be generated in the .output/public directory and ready to be deployed to any static compatible hosting. 42 | 43 | ```bash 44 | yarn generate 45 | ``` 46 | 47 | ## Preview build 48 | 49 | You might want to preview the result of your build locally, to do so, run the following command: 50 | 51 | ```bash 52 | yarn preview 53 | ``` 54 | 55 | --- 56 | 57 | For a detailed explanation of how things work, check out [Docus](https://docus.dev). 58 | -------------------------------------------------------------------------------- /_docs/app.config.ts: -------------------------------------------------------------------------------- 1 | export default defineAppConfig({ 2 | docus: { 3 | title: "Sevue", 4 | description: "Vue/Nuxt UI Library.", 5 | image: "https://i.imgur.com/fQhpqDY.png", 6 | socials: { 7 | twitter: "saeed8ab", 8 | github: "sa8ab/sevue", 9 | }, 10 | aside: { 11 | level: 0, 12 | exclude: [], 13 | }, 14 | header: { 15 | logo: false, 16 | }, 17 | footer: { 18 | iconLinks: [ 19 | // { 20 | // href: "https://nuxt.com", 21 | // icon: "simple-icons:nuxtdotjs", 22 | // }, 23 | ], 24 | }, 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /_docs/components/Logo.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_docs/components/content/ColorGuide.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /_docs/components/content/Colors.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /_docs/components/content/Demo.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 27 | 28 | 51 | -------------------------------------------------------------------------------- /_docs/components/content/Pagination/PaginationCompact.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/Pagination/PaginationCount.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/Pagination/PaginationDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/Pagination/PaginationRanges.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/Popup/PopupBeforeClose.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/Popup/PopupDemo.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /_docs/components/content/Popup/PopupFullWidth.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /_docs/components/content/Popup/PopupNoClose.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/Popup/PopupSlots.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 20 | 21 | 42 | -------------------------------------------------------------------------------- /_docs/components/content/Tabs/TabsDefault.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /_docs/components/content/Tabs/TabsDisabled.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /_docs/components/content/Tabs/TabsIcon.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 19 | 20 | 28 | -------------------------------------------------------------------------------- /_docs/components/content/Tabs/TabsScrollable.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/Tabs/TabsVModel.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonColors.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonCompact.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonDefault.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonLoading.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 19 | 20 | 32 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonRouting.vue: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/button/ButtonTypes.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/checkbox/CheckboxArray.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /_docs/components/content/checkbox/CheckboxDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputColor.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputDefault.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 13 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputDemo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputError.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputIcon.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputLabel.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputSlots.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 24 | 25 | 38 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputTagElement.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /_docs/components/content/input/InputWithDirective.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /_docs/components/content/loading/LoadingDemo.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 30 | 31 | 60 | -------------------------------------------------------------------------------- /_docs/components/content/loading/LoadingStyling.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | 28 | 57 | -------------------------------------------------------------------------------- /_docs/components/content/loading/LoadingTarget.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 29 | 30 | 60 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationBefore.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 22 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationClose.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 28 | 29 | 36 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationDemo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationDuration.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationExamples.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationStyling.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | 23 | 30 | -------------------------------------------------------------------------------- /_docs/components/content/notification/NotificationWidth.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | -------------------------------------------------------------------------------- /_docs/components/content/radio/RadioDefault.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 26 | -------------------------------------------------------------------------------- /_docs/components/content/radio/RadioDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 27 | -------------------------------------------------------------------------------- /_docs/components/content/radio/RadioTag.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 31 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectBase.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectCustomSearch.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | 36 | 63 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectDefault.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectDemo.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectDisabled.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectGroup.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 31 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectMultiple.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectOptimized.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | -------------------------------------------------------------------------------- /_docs/components/content/select/SelectOptimizedGrouped.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 58 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderCustomTick.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderRange.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderStep.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderTickSlot.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 26 | 27 | 33 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderTicks.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/slider/SliderTooltip.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /_docs/components/content/switch/SwitchAlternative.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | 16 | 34 | -------------------------------------------------------------------------------- /_docs/components/content/switch/SwitchArray.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 31 | 32 | 41 | -------------------------------------------------------------------------------- /_docs/components/content/switch/SwitchColor.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /_docs/components/content/switch/SwitchDefault.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 25 | 26 | 34 | -------------------------------------------------------------------------------- /_docs/components/content/switch/SwitchSlots.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 28 | 29 | 43 | -------------------------------------------------------------------------------- /_docs/content/0.index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | navigation: false 4 | layout: page 5 | --- 6 | 7 | ::block-hero 8 | --- 9 | cta: 10 | - Get Started 11 | - /guide 12 | secondary: 13 | - Open on GitHub → 14 | - https://github.com/sa8ab/sevue 15 | snippet: npm install sevue 16 | --- 17 | 18 | #title 19 | Sevue 20 | 21 | #description 22 | Vue & Nuxt UI library 23 | :: 24 | 25 | ::List{type="success"} 26 | - Light Weight 27 | - Customizable 28 | - Responsive 29 | - Typescript Friendly 30 | - Free and open source 31 | :: 32 | 33 | [] 34 | -------------------------------------------------------------------------------- /_docs/content/1.guide/0.index.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | 1. Add `Sevue` to your project: 4 | 5 | ::CodeGroup 6 | ```bash [NPM] 7 | npm install sevue 8 | ``` 9 | ```bash [Yarn] 10 | yarn add sevue 11 | ``` 12 | :: 13 | 14 | 2. Use `Sevue` in your app: 15 | 16 | ::CodeGroup 17 | ```js [src/main.ts] 18 | import { createApp } from 'vue' 19 | import Sevue from 'sevue' 20 | import 'sevue/dist/style.css' 21 | 22 | const app = createApp() 23 | app.use(Sevue, { 24 | // options 25 | }) 26 | ``` 27 | :: 28 | 29 | For Nuxt JS add Sevue in a plugin 30 | 31 | ::CodeGroup 32 | ```js [plugins/sevue.ts] 33 | import Sevue from 'sevue' 34 | import 'sevue/dist/style.css' 35 | import { NuxtLink } from '#imports' 36 | 37 | export default defineNuxtPlugin((nuxtApp) => { 38 | nuxtApp.vueApp.use(Sevue, { 39 | nuxtOptions: { 40 | isNuxt: true, 41 | // will be used when `RButton` has `to` prop 42 | NuxtLink: NuxtLink 43 | } 44 | // options 45 | }) 46 | }) 47 | ``` 48 | :: -------------------------------------------------------------------------------- /_docs/content/1.guide/_dir.yml: -------------------------------------------------------------------------------- 1 | title: Guide 2 | -------------------------------------------------------------------------------- /_docs/content/2.components/_dir.yml: -------------------------------------------------------------------------------- 1 | title: Components 2 | -------------------------------------------------------------------------------- /_docs/content/3.composables/_dir.yml: -------------------------------------------------------------------------------- 1 | title: Composables 2 | -------------------------------------------------------------------------------- /_docs/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtConfig({ 2 | extends: "@nuxt-themes/docus", 3 | css: ["boxicons/css/boxicons.min.css", "@/style/style.scss"], 4 | }); 5 | -------------------------------------------------------------------------------- /_docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docus-starter", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "nuxi dev", 7 | "build": "nuxi build", 8 | "generate": "nuxi generate", 9 | "preview": "nuxi preview", 10 | "lint": "eslint ." 11 | }, 12 | "devDependencies": { 13 | "eslint": "^8.35.0", 14 | "nuxt": "^3.3.2" 15 | }, 16 | "dependencies": { 17 | "@nuxt-themes/docus": "^1.15.0", 18 | "axios": "^1.3.4", 19 | "boxicons": "^2.1.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /_docs/plugins/sevue.ts: -------------------------------------------------------------------------------- 1 | import Sevue from "sevue"; 2 | import "sevue/dist/style.css"; 3 | export default defineNuxtPlugin((nuxtApp) => { 4 | nuxtApp.vueApp.use(Sevue, { 5 | nuxtOptions: { 6 | isNuxt: true, 7 | }, 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /_docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/_docs/public/favicon.ico -------------------------------------------------------------------------------- /_docs/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ], 5 | "lockFileMaintenance": { 6 | "enabled": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /_docs/style/style.scss: -------------------------------------------------------------------------------- 1 | .r-button { 2 | p { 3 | padding: 0; 4 | margin: 0 !important; 5 | } 6 | } 7 | .doc-input { 8 | width: 100%; 9 | max-width: 320px; 10 | margin: auto; 11 | .r-input { 12 | width: 100%; 13 | } 14 | } 15 | .input-items { 16 | display: grid; 17 | grid-template-columns: 1fr 1fr; 18 | gap: 8px; 19 | } 20 | .doc-items.two { 21 | display: grid; 22 | grid-template-columns: 1fr 1fr; 23 | gap: 8px; 24 | } 25 | .doc-items.three { 26 | display: grid; 27 | grid-template-columns: 1fr 1fr 1fr; 28 | gap: 8px; 29 | } 30 | .doc-items.four { 31 | display: grid; 32 | grid-template-columns: 1fr 1fr 1fr 1fr; 33 | gap: 8px; 34 | } 35 | .doc-item { 36 | width: 100%; 37 | max-width: 320px; 38 | margin: auto; 39 | .r-input { 40 | width: 100%; 41 | } 42 | } 43 | 44 | .alert .prose-code code { 45 | --elements-state-warning-backgroundColor-secondary: transparent; 46 | } 47 | 48 | @media only screen and (max-width: 800px) { 49 | .doc-items, 50 | .input-items { 51 | grid-template-columns: 1fr !important; 52 | } 53 | } 54 | 55 | .table-wrapper th:last-child { 56 | min-width: 280px; 57 | } 58 | 59 | .table-wrapper { 60 | td:nth-child(2), 61 | th:nth-child(2) { 62 | color: rgba(230, 126, 34, 1); 63 | } 64 | } 65 | 66 | .card { 67 | background: rgb(var(--r-b1)); 68 | padding: var(--r-space-2); 69 | border-radius: var(--r-radius); 70 | } 71 | 72 | .r-button { 73 | line-height: 1.2; 74 | } 75 | -------------------------------------------------------------------------------- /_docs/tokens.config.ts: -------------------------------------------------------------------------------- 1 | import { defineTheme } from 'pinceau' 2 | 3 | export default defineTheme({ 4 | color: { 5 | primary: { 6 | 50: "#80d4ff", 7 | 100: "#66cbff", 8 | 200: "#4dc2ff", 9 | 300: "#33b9ff", 10 | 400: "#1ab1ff", 11 | 500: "#00a8ff", 12 | 600: "#0097e6", 13 | 700: "#0086cc", 14 | 800: "#0076b3", 15 | 900: "#006599", 16 | }, 17 | }, 18 | }); 19 | -------------------------------------------------------------------------------- /_docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /dev/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 39 | -------------------------------------------------------------------------------- /dev/assets/fonts/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/dev/assets/fonts/Inter-Bold.ttf -------------------------------------------------------------------------------- /dev/assets/fonts/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/dev/assets/fonts/Inter-Light.ttf -------------------------------------------------------------------------------- /dev/assets/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/dev/assets/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /dev/assets/fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/dev/assets/fonts/Inter-Regular.ttf -------------------------------------------------------------------------------- /dev/components/Cnot.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /dev/components/InputWithDirective.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /dev/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import App from "./App.vue"; 3 | import Sevue from "../src/main"; 4 | import "../src/styles/index.scss"; 5 | import "./style/main.scss"; 6 | import "boxicons/css/boxicons.min.css"; 7 | import router from "./router"; 8 | import { vMaska } from "maska"; 9 | 10 | const app = createApp(App); 11 | app.use(Sevue); 12 | app.use(router); 13 | app.directive("maska", vMaska); 14 | app.mount("#app"); 15 | -------------------------------------------------------------------------------- /dev/mock/index.ts: -------------------------------------------------------------------------------- 1 | export const users = [ 2 | { 3 | id: "f4", 4 | name: "Anna Little", 5 | company: "BIFLEX", 6 | }, 7 | { 8 | id: "46", 9 | name: "Mindy Glass", 10 | company: "HALAP", 11 | }, 12 | { 13 | id: "5e", 14 | name: "Beatrice Montgomery", 15 | company: "KANGLE", 16 | }, 17 | { 18 | id: "b0", 19 | name: "Norman Pollard", 20 | company: "MAINELAND", 21 | }, 22 | { 23 | id: "42", 24 | name: "Wheeler Wallace", 25 | company: "ISOSPHERE", 26 | }, 27 | { 28 | id: "23", 29 | name: "Natasha Scott", 30 | company: "CINASTER", 31 | }, 32 | { 33 | id: "c5", 34 | name: "Kristina Ramirez", 35 | company: "JOVIOLD", 36 | }, 37 | ]; 38 | 39 | export const groupedUsers = [ 40 | { 41 | role: "Admin", 42 | users: [ 43 | { 44 | id: "f4", 45 | name: "Anna Little", 46 | company: "BIFLEX", 47 | }, 48 | { 49 | id: "46", 50 | name: "Mindy Glass", 51 | company: "HALAP", 52 | }, 53 | { 54 | id: "5e", 55 | name: "Beatrice Montgomery", 56 | company: "KANGLE", 57 | }, 58 | ], 59 | }, 60 | { 61 | role: "Agent", 62 | users: [ 63 | { 64 | id: "23", 65 | name: "Natasha Scott Natasha Scott Natasha Scott Natasha Scott Natasha Scott", 66 | company: "CINASTER", 67 | }, 68 | { 69 | id: "c5", 70 | name: "Kristina Ramirez", 71 | company: "JOVIOLD", 72 | }, 73 | ], 74 | }, 75 | ]; 76 | -------------------------------------------------------------------------------- /dev/pages/AlertPage.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /dev/pages/CheckboxPage.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 47 | 48 | 70 | -------------------------------------------------------------------------------- /dev/pages/HomePage.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 41 | -------------------------------------------------------------------------------- /dev/pages/InputPage.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 55 | 56 | 69 | -------------------------------------------------------------------------------- /dev/pages/LoadingPage.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /dev/pages/NotificationPage.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /dev/pages/PaginationPage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /dev/pages/PlaygroundPage.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /dev/pages/RadioPage.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /dev/pages/SelectPage.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 57 | 58 | 81 | -------------------------------------------------------------------------------- /dev/pages/SliderPage.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 66 | 67 | 78 | -------------------------------------------------------------------------------- /dev/pages/SwitchPage.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 35 | 36 | 46 | -------------------------------------------------------------------------------- /dev/style/main.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Inter"; 3 | src: url("../assets/fonts/Inter-Regular.ttf"); 4 | font-size: 400; 5 | } 6 | @font-face { 7 | font-family: "Inter"; 8 | src: url("../assets/fonts/Inter-Bold.ttf"); 9 | font-weight: bold; 10 | } 11 | @font-face { 12 | font-family: "Inter"; 13 | src: url("../assets/fonts/Inter-Light.ttf"); 14 | font-weight: 300; 15 | } 16 | @font-face { 17 | font-family: "Inter"; 18 | src: url("../assets/fonts/Inter-Medium.ttf"); 19 | font-weight: 500; 20 | } 21 | 22 | body { 23 | font-family: Inter; 24 | } 25 | 26 | a { 27 | text-decoration: none; 28 | color: var(--r-text); 29 | } 30 | -------------------------------------------------------------------------------- /dist.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/dist.zip -------------------------------------------------------------------------------- /docs/.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitepress"; 2 | 3 | // https://vitepress.dev/reference/site-config 4 | export default defineConfig({ 5 | title: "Sevue", 6 | description: "Vue / Nuxt 3 UI Library", 7 | srcDir: "./src", 8 | themeConfig: { 9 | // https://vitepress.dev/reference/default-theme-config 10 | nav: [ 11 | { text: "Home", link: "/" }, 12 | { text: "Documentation", link: "/guide/" }, 13 | ], 14 | 15 | sidebar: [ 16 | { 17 | text: "Guide", 18 | items: [ 19 | { text: "Installation", link: "/guide/" }, 20 | { text: "Customization", link: "/guide/customization" }, 21 | ], 22 | }, 23 | { 24 | text: "Components", 25 | items: [ 26 | { text: "Button", link: "/components/button" }, 27 | { text: "Input", link: "/components/input" }, 28 | { text: "Select", link: "/components/select" }, 29 | { text: "Checkbox", link: "/components/checkbox" }, 30 | { text: "Tabs", link: "/components/tabs" }, 31 | { text: "Popup", link: "/components/popup" }, 32 | { text: "Pagination", link: "/components/pagination" }, 33 | ], 34 | }, 35 | ], 36 | 37 | socialLinks: [{ icon: "github", link: "https://github.com/sa8ab/sevue" }], 38 | }, 39 | }); 40 | -------------------------------------------------------------------------------- /docs/.vitepress/styles/doc-style.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --vp-c-brand-1: #00a8ff; 3 | --vp-c-brand-2: #0097e6; 4 | --vp-c-brand-3: #00a8ff; 5 | --vp-c-brand-soft: rgba(#00a8ff, 0.5); 6 | } 7 | 8 | button:focus { 9 | outline: 0; 10 | } 11 | 12 | .button-items { 13 | display: flex; 14 | gap: var(--space-1); 15 | flex-wrap: wrap; 16 | gap: 10px; 17 | } 18 | 19 | .button-loading-container { 20 | display: flex; 21 | flex-direction: column; 22 | gap: 10px; 23 | } 24 | 25 | .input-items { 26 | display: grid; 27 | grid-template-columns: 1fr 1fr; 28 | gap: 10px; 29 | } 30 | 31 | .color-red { 32 | color: var(--vp-c-red-1); 33 | } 34 | .color-yellow { 35 | color: var(--vp-c-yellow-1); 36 | } 37 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import DefaultTheme from "vitepress/theme"; 2 | import type { Theme } from "vitepress"; 3 | import Sevue from "sevue"; 4 | import "sevue/dist/style.css"; 5 | import "../styles/doc-style.scss"; 6 | import Demo from "../../components/Demo.vue"; 7 | 8 | export default { 9 | extends: DefaultTheme, 10 | enhanceApp: ({ app }) => { 11 | app.use(Sevue); 12 | app.component("Demo", Demo); 13 | }, 14 | } satisfies Theme; 15 | -------------------------------------------------------------------------------- /docs/components/Colors.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 31 | -------------------------------------------------------------------------------- /docs/components/Demo.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 36 | 37 | 61 | -------------------------------------------------------------------------------- /docs/components/button/ButtonColors.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | -------------------------------------------------------------------------------- /docs/components/button/ButtonCompact.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /docs/components/button/ButtonDefault.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /docs/components/button/ButtonDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /docs/components/button/ButtonIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /docs/components/button/ButtonLoading.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /docs/components/button/ButtonRouting.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /docs/components/button/ButtonTypes.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /docs/components/checkbox/CheckboxArray.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /docs/components/checkbox/CheckboxDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /docs/components/icons/CloseIcon.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /docs/components/icons/SearchIcon.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /docs/components/input/InputColor.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 14 | -------------------------------------------------------------------------------- /docs/components/input/InputDefault.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /docs/components/input/InputDemo.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /docs/components/input/InputError.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | -------------------------------------------------------------------------------- /docs/components/input/InputIcon.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /docs/components/input/InputLabel.vue: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/components/input/InputSlots.vue: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | 23 | 30 | 31 | 39 | -------------------------------------------------------------------------------- /docs/components/input/InputTagElement.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /docs/components/input/InputWithDirective.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /docs/components/pagination/PaginationCompact.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/components/pagination/PaginationCount.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /docs/components/pagination/PaginationDemo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /docs/components/pagination/PaginationRanges.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/components/popup/PopupBeforeClose.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /docs/components/popup/PopupClose.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/components/popup/PopupDemo.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 17 | -------------------------------------------------------------------------------- /docs/components/popup/PopupFullWidth.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /docs/components/popup/PopupSlots.vue: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 24 | 49 | -------------------------------------------------------------------------------- /docs/components/select/SelectBase.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 20 | 21 | -------------------------------------------------------------------------------- /docs/components/select/SelectCustomOption.vue: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 29 | 30 | 47 | -------------------------------------------------------------------------------- /docs/components/select/SelectCustomOptionContent.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 27 | 28 | 45 | -------------------------------------------------------------------------------- /docs/components/select/SelectCustomSearch.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | 36 | 63 | -------------------------------------------------------------------------------- /docs/components/select/SelectDefault.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 28 | -------------------------------------------------------------------------------- /docs/components/select/SelectDemo.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 36 | -------------------------------------------------------------------------------- /docs/components/select/SelectDisabled.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 45 | -------------------------------------------------------------------------------- /docs/components/select/SelectGroup.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 42 | -------------------------------------------------------------------------------- /docs/components/select/SelectMultiple.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 32 | -------------------------------------------------------------------------------- /docs/components/select/SelectOptimized.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 34 | -------------------------------------------------------------------------------- /docs/components/select/SelectOptimizedGrouped.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 58 | -------------------------------------------------------------------------------- /docs/components/tabs/TabsDefault.vue: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 26 | -------------------------------------------------------------------------------- /docs/components/tabs/TabsDisabled.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 14 | 15 | 20 | -------------------------------------------------------------------------------- /docs/components/tabs/TabsIcon.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 19 | 20 | 28 | -------------------------------------------------------------------------------- /docs/components/tabs/TabsScrollable.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /docs/components/tabs/TabsVModel.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | 16 | 24 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "docs:dev": "vitepress dev", 4 | "docs:build": "vitepress build", 5 | "docs:preview": "vitepress preview" 6 | }, 7 | "dependencies": { 8 | "sevue": "^0.4.0", 9 | "vitepress": "^1.0.0-rc.45" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/src/api-examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # Runtime API Examples 6 | 7 | This page demonstrates usage of some of the runtime APIs provided by VitePress. 8 | 9 | The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: 10 | 11 | ```md 12 | 17 | 18 | ## Results 19 | 20 | ### Theme Data 21 |
{{ theme }}
22 | 23 | ### Page Data 24 |
{{ page }}
25 | 26 | ### Page Frontmatter 27 |
{{ frontmatter }}
28 | ``` 29 | 30 | 35 | 36 | ## Results 37 | 38 | ### Theme Data 39 |
{{ theme }}
40 | 41 | ### Page Data 42 |
{{ page }}
43 | 44 | ### Page Frontmatter 45 |
{{ frontmatter }}
46 | 47 | ## More 48 | 49 | Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata). 50 | -------------------------------------------------------------------------------- /docs/src/components/checkbox.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Checkbox 7 | 8 |

9 | 10 | 11 | 12 | 13 | ## Array Selection 14 | 15 | `RCheckbox` works same as native checkbox. In order to have multiple selected items in an array, set initial value for `v-model` as `array` type. 16 | 17 | 18 | 19 | :::code-group 20 | <<< ../../components/checkbox/CheckboxArray.vue#template [template] 21 | <<< ../../components/checkbox/CheckboxArray.vue#script{ts} [script] 22 | ::: 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /docs/src/components/pagination.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Popup 9 | 10 |

11 | 12 | 13 | 14 | 15 | ## Count 16 | 17 | `count` is a number prop that specifies count of pages. 18 | 19 | 20 | 21 | :::code-group 22 | <<< ../../components/pagination/PaginationCount.vue#template [template] 23 | ::: 24 | 25 | 28 | 29 | 30 | 31 | 32 | ## Ranges 33 | 34 | `mainRange` specifies how many pages to be visible after and before active page. `sideRange` specifies how many pages to be visible from start and end. 35 | 36 | 37 | 38 | 39 | :::code-group 40 | <<< ../../components/pagination/PaginationRanges.vue#template [template] 41 | ::: 42 | 43 | 46 | 47 | 48 | 49 | ## compact 50 | 51 | Puts navigation buttons bellow pages 52 | 53 | 54 | 55 | :::code-group 56 | <<< ../../components/pagination/PaginationCompact.vue#template [template] 57 | ::: 58 | 59 | 62 | 63 | -------------------------------------------------------------------------------- /docs/src/components/popup.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | # Popup 9 | 10 |

11 | 12 | 13 | 14 | 15 | ## No Close 16 | 17 | If `noClose` is true popup won't be closed by clicking the underlay. and if `noCloseButton` is true the close button will not be shown. 18 | 19 | 20 | 21 | 22 | :::code-group 23 | <<< ../../components/popup/PopupClose.vue#template [template] 24 | ::: 25 | 26 | 29 | 30 | 31 | 32 | 33 | ## beforeClose 34 | 35 | `beforeClose` is called when clicking outside of popup (the underlay) or when clicking close button. it recieves the `done` function as it's first parameter and when it's called the popup will close. 36 | 37 | 38 | 39 | 40 | :::code-group 41 | <<< ../../components/popup/PopupBeforeClose.vue#template [template] 42 | <<< ../../components/popup/PopupBeforeClose.vue#script{ts} [script] 43 | ::: 44 | 45 | 48 | 49 | 50 | 51 | 52 | ## Custom Header & Footer 53 | 54 | Header and Footer of the popup is customizable using `header` and `footer` named slot. 55 | 56 | 57 | 58 | :::code-group 59 | <<< ../../components/popup/PopupSlots.vue#template [template] 60 | <<< ../../components/popup/PopupSlots.vue#style{scss} [style] 61 | ::: 62 | 63 | 66 | 67 | -------------------------------------------------------------------------------- /docs/src/components/tabs.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | # Tabs 7 | 8 |

9 | 10 | 11 | 12 | 13 | ## Default 14 | 15 | `RTab` is for Tabbar and `RPanel` is for content of the tabbar. you can use them separately as well. 16 | 17 | 18 | 19 | :::code-group 20 | <<< ../../components/tabs/TabsDefault.vue#template [template] 21 | <<< ../../components/tabs/TabsDefault.vue#script{ts} [script] 22 | ::: 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/src/guide/index.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | 1. Add `Sevue` to your project: 4 | 5 | :::code-group 6 | ```bash [NPM] 7 | npm install sevue 8 | ``` 9 | ```bash [Yarn] 10 | yarn add sevue 11 | ``` 12 | ::: 13 | 14 | 2. Use `Sevue` in your app: 15 | 16 | ```js [src/main.ts] 17 | import { createApp } from 'vue' 18 | import Sevue from 'sevue' 19 | import 'sevue/dist/style.css' 20 | 21 | const app = createApp() 22 | app.use(Sevue, { 23 | // options 24 | }) 25 | ``` 26 | 27 | For Nuxt JS add Sevue in a plugin 28 | 29 | :::code-group 30 | ```js [plugins/sevue.ts] 31 | import Sevue from 'sevue' 32 | import 'sevue/dist/style.css' 33 | import { NuxtLink } from '#imports' 34 | 35 | export default defineNuxtPlugin((nuxtApp) => { 36 | nuxtApp.vueApp.use(Sevue, { 37 | nuxtOptions: { 38 | isNuxt: true, 39 | // will be used when `RButton` has `to` prop 40 | NuxtLink: NuxtLink 41 | } 42 | // options 43 | }) 44 | }) 45 | ``` 46 | ::: -------------------------------------------------------------------------------- /docs/src/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: "Sevue" 7 | text: "Vue / Nuxt 3 UI Library" 8 | tagline: My great project tagline 9 | actions: 10 | - theme: brand 11 | text: Getting Started 12 | link: /markdown-examples 13 | - theme: alt 14 | text: View On Github 15 | link: https://github.com/sa8ab/sevue 16 | 17 | features: 18 | - title: Feature A 19 | details: Lorem ipsum dolor sit amet, consectetur adipiscing elit 20 | - title: Feature B 21 | details: Lorem ipsum dolor sit amet, consectetur adipiscing elit 22 | - title: Feature C 23 | details: Lorem ipsum dolor sit amet, consectetur adipiscing elit 24 | --- 25 | 26 | -------------------------------------------------------------------------------- /docs/src/markdown-examples.md: -------------------------------------------------------------------------------- 1 | # Markdown Extension Examples 2 | 3 | This page demonstrates some of the built-in markdown extensions provided by VitePress. 4 | 5 | ## Syntax Highlighting 6 | 7 | VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting: 8 | 9 | **Input** 10 | 11 | ````md 12 | ```js{4} 13 | export default { 14 | data () { 15 | return { 16 | msg: 'Highlighted!' 17 | } 18 | } 19 | } 20 | ``` 21 | ```` 22 | 23 | **Output** 24 | 25 | ```js{4} 26 | export default { 27 | data () { 28 | return { 29 | msg: 'Highlighted!' 30 | } 31 | } 32 | } 33 | ``` 34 | 35 | ## Custom Containers 36 | 37 | **Input** 38 | 39 | ```md 40 | ::: info 41 | This is an info box. 42 | ::: 43 | 44 | ::: tip 45 | This is a tip. 46 | ::: 47 | 48 | ::: warning 49 | This is a warning. 50 | ::: 51 | 52 | ::: danger 53 | This is a dangerous warning. 54 | ::: 55 | 56 | ::: details 57 | This is a details block. 58 | ::: 59 | ``` 60 | 61 | **Output** 62 | 63 | ::: info 64 | This is an info box. 65 | ::: 66 | 67 | ::: tip 68 | This is a tip. 69 | ::: 70 | 71 | ::: warning 72 | This is a warning. 73 | ::: 74 | 75 | ::: danger 76 | This is a dangerous warning. 77 | ::: 78 | 79 | ::: details 80 | This is a details block. 81 | ::: 82 | 83 | ## More 84 | 85 | Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown). 86 | -------------------------------------------------------------------------------- /docs/src/public/images/flag-fr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/docs/src/public/images/flag-fr.png -------------------------------------------------------------------------------- /docs/src/public/images/flag-gr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/docs/src/public/images/flag-gr.png -------------------------------------------------------------------------------- /docs/src/public/images/flag-it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/docs/src/public/images/flag-it.png -------------------------------------------------------------------------------- /docs/src/public/images/flag-uk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sa8ab/sevue/0dd5a61f60cf5d74ebafb2943d1fd4162fac5ee3/docs/src/public/images/flag-uk.png -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sevue", 3 | "version": "0.4.7", 4 | "private": false, 5 | "files": [ 6 | "dist" 7 | ], 8 | "main": "./dist/sevue.umd.js", 9 | "module": "./dist/sevue.mjs", 10 | "types": "./dist/main.d.ts", 11 | "scripts": { 12 | "dev": "vite", 13 | "build": "run-p type-check build-only", 14 | "preview": "vite preview", 15 | "build-only": "vite build", 16 | "type-check": "vue-tsc --noEmit" 17 | }, 18 | "exports": { 19 | ".": { 20 | "types": "./dist/main.d.ts", 21 | "import": "./dist/sevue.mjs", 22 | "require": "./dist/sevue.umd.js" 23 | }, 24 | "./dist/style.css": { 25 | "import": "./dist/style.css", 26 | "require": "./dist/style.css" 27 | } 28 | }, 29 | "dependencies": { 30 | "@floating-ui/vue": "^1.0.6", 31 | "@popperjs/core": "^2.11.6", 32 | "@vueuse/core": "^10.9.0", 33 | "focus-trap": "^7.5.4" 34 | }, 35 | "peerDependencies": { 36 | "vue": "^3.4.0" 37 | }, 38 | "devDependencies": { 39 | "@rollup/plugin-typescript": "^11.0.0", 40 | "@types/node": "^18.14.2", 41 | "@vitejs/plugin-vue": "^4.0.0", 42 | "@vue-macros/volar": "^0.9.4", 43 | "@vue/tsconfig": "^0.1.3", 44 | "axios": "^1.3.4", 45 | "boxicons": "^2.1.4", 46 | "install": "^0.13.0", 47 | "maska": "^2.1.8", 48 | "npm": "^9.6.3", 49 | "npm-run-all": "^4.1.5", 50 | "rollup-plugin-typescript2": "^0.34.1", 51 | "sass": "^1.58.3", 52 | "typescript": "~4.8.4", 53 | "unplugin-vue-components": "^0.24.1", 54 | "unplugin-vue-define-options": "^1.2.3", 55 | "vite": "^4.1.4", 56 | "vite-plugin-dts": "^3.7.2", 57 | "vite-svg-loader": "^4.0.0", 58 | "vue": "^3.4.21", 59 | "vue-router": "^4.1.6", 60 | "vue-tsc": "^1.8.27" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/components/HeightTransition.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 35 | 36 | 49 | -------------------------------------------------------------------------------- /src/components/LoadingSpinner.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 20 | 21 | -------------------------------------------------------------------------------- /src/components/VNodeRenderer.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/alert/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RAlert, type RAlertProps } from "./RAlert.vue"; 2 | -------------------------------------------------------------------------------- /src/components/button/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RButton, type RButtonProps } from "./RButton.vue"; 2 | -------------------------------------------------------------------------------- /src/components/checkbox/CheckboxRoot.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 60 | -------------------------------------------------------------------------------- /src/components/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CheckboxRoot, type CheckboxRootEmits, type CheckboxRootProps } from "./CheckboxRoot.vue"; 2 | export { default as RCheckbox, type RCheckboxProps } from "./RCheckbox.vue"; 3 | -------------------------------------------------------------------------------- /src/components/dropdown/DropdownRoot.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 65 | 66 | 69 | -------------------------------------------------------------------------------- /src/components/dropdown/DropdownTrigger.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 50 | -------------------------------------------------------------------------------- /src/components/dropdown/RDropdownItem.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 17 | 18 | 35 | -------------------------------------------------------------------------------- /src/components/dropdown/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DropdownRoot, type DropdownRootProps, type DropdownRootEmits } from "./DropdownRoot.vue"; 2 | 3 | export { default as DropdownTrigger, type DropdownTriggerProps } from "./DropdownTrigger.vue"; 4 | 5 | export { default as DropdownContent, type DropdownContentProps } from "./DropdownContent.vue"; 6 | 7 | export { default as DropdownItem, type DropdownItemProps } from "./DropdownItem.vue"; 8 | 9 | export { default as RDropdown } from "./RDropdown.vue"; 10 | 11 | export { default as RDropdownItem } from "./RDropdownItem.vue"; 12 | -------------------------------------------------------------------------------- /src/components/icons/SevueIcon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | -------------------------------------------------------------------------------- /src/components/icons/svgs/check.svg: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/icons/svgs/chevron-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/icons/svgs/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/icons/svgs/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/icons/svgs/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | import { RSelect, ROption, RSelectGroup } from "./select"; 2 | import RLoading, { type Props as RLoadingProps } from "./loading/RLoading.vue"; 3 | 4 | import { Label } from "./internal"; 5 | 6 | export * from "./alert"; 7 | export * from "./button"; 8 | export * from "./checkbox"; 9 | export * from "./roving-focus"; 10 | export * from "./tabs"; 11 | export * from "./dropdown"; 12 | export * from "./input"; 13 | export * from "./pagination"; 14 | export * from "./popup"; 15 | export * from "./primitive"; 16 | export * from "./radio"; 17 | export * from "./slider"; 18 | export * from "./tabs"; 19 | export * from "./switch"; 20 | export * from "./primitive"; 21 | export * from "./provider"; 22 | export { 23 | RSelect, 24 | // RSelectProps, 25 | ROption, 26 | // ROptionProps, 27 | RSelectGroup, 28 | RLoading, 29 | RLoadingProps, 30 | Label, 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/input/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RInput, type RInputProps } from "./RInput.vue"; 2 | -------------------------------------------------------------------------------- /src/components/internal/FieldLabel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 34 | -------------------------------------------------------------------------------- /src/components/internal/FieldMessage.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 32 | -------------------------------------------------------------------------------- /src/components/internal/InputContainer.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 28 | 29 | 47 | -------------------------------------------------------------------------------- /src/components/internal/Label.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /src/components/internal/index.ts: -------------------------------------------------------------------------------- 1 | import Label from "./Label.vue"; 2 | export { Label }; 3 | -------------------------------------------------------------------------------- /src/components/notification/NotificationContainer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | 29 | 73 | -------------------------------------------------------------------------------- /src/components/notification/index.ts: -------------------------------------------------------------------------------- 1 | import Notification from "./Notification.vue"; 2 | import NotificationContainer from "./NotificationContainer.vue"; 3 | import mounter from "@/utils/mountComponent"; 4 | import type { App } from "vue"; 5 | import type { Notification as NotificationType, NotificationOptions } from "@/types"; 6 | 7 | const notificationFactory = (app: App) => { 8 | const defaultProps = { 9 | placement: "bottom-right", 10 | }; 11 | const _app = app; 12 | return (data: NotificationOptions): NotificationType => { 13 | const propsData = { 14 | ...defaultProps, 15 | ...data, 16 | }; 17 | 18 | const appendName = propsData.placement.includes("top") ? "prepend" : "append"; 19 | 20 | const container = document.querySelector(`.r-notifications-container.${propsData.placement}`); 21 | 22 | if (container) { 23 | const { element, vNode } = mounter(Notification, { 24 | props: propsData, 25 | app: _app, 26 | }); 27 | container[appendName](element); 28 | 29 | return { 30 | close: vNode.component?.exposed?.close 31 | } 32 | } else { 33 | const { elementChild } = mounter(NotificationContainer, { 34 | props: propsData, 35 | app: _app, 36 | }); 37 | 38 | document.body.append(elementChild); 39 | 40 | const { element, vNode } = mounter(Notification, { 41 | props: propsData, 42 | app: _app, 43 | }); 44 | 45 | elementChild[appendName](element); 46 | 47 | return { 48 | close: vNode.component?.exposed?.close 49 | } 50 | } 51 | }; 52 | }; 53 | 54 | export default notificationFactory; 55 | -------------------------------------------------------------------------------- /src/components/pagination/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RPagination, type RPaginationProps } from "./RPagination.vue"; 2 | -------------------------------------------------------------------------------- /src/components/popper/PopperContent.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /src/components/popper/PopperReference.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /src/components/popper/PopperRoot.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | 27 | 30 | -------------------------------------------------------------------------------- /src/components/popper/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/components/popup/PopupClose.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /src/components/popup/PopupContent.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 65 | -------------------------------------------------------------------------------- /src/components/popup/PopupDescription.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /src/components/popup/PopupOverlay.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 25 | -------------------------------------------------------------------------------- /src/components/popup/PopupRoot.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 60 | 61 | 64 | -------------------------------------------------------------------------------- /src/components/popup/PopupTitle.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /src/components/popup/index.ts: -------------------------------------------------------------------------------- 1 | export { default as PopupRoot, type PopupRootContext, type PopupRootEmits, type PopupRootProps } from "./PopupRoot.vue"; 2 | 3 | export { default as PopupContent, type PopupContentProps } from "./PopupContent.vue"; 4 | 5 | export { default as PopupOverlay, type PopupOverlayProps } from "./PopupOverlay.vue"; 6 | 7 | export { default as PopupClose, type PopupCloseProps } from "./PopupClose.vue"; 8 | 9 | export { default as PopupTitle, type PopupTitleProps } from "./PopupTitle.vue"; 10 | 11 | export { default as PopupDescription, type PopupDescriptionProps } from "./PopupDescription.vue"; 12 | 13 | export { default as RPopup, type RPopupProps } from "./RPopup.vue"; 14 | -------------------------------------------------------------------------------- /src/components/primitive/Primitive.ts: -------------------------------------------------------------------------------- 1 | import { type Component, type PropType, defineComponent, h } from "vue"; 2 | import { Slot } from "./Slot"; 3 | 4 | export interface PrimitiveProps { 5 | asChild?: boolean; 6 | as?: string | Component; 7 | } 8 | 9 | export const Primitive = defineComponent({ 10 | name: "Primitive", 11 | inheritAttrs: false, 12 | props: { 13 | asChild: { 14 | type: Boolean, 15 | default: false, 16 | }, 17 | as: { 18 | type: [String, Object] as PropType, 19 | default: "div", 20 | }, 21 | }, 22 | setup(props, { attrs, slots }) { 23 | const asTag = props.asChild ? "template" : props.as; 24 | 25 | // For self closing tags, don't provide default slots because of hydration issue 26 | const SELT_CLOSING_TAGS = ["area", "img", "input"]; 27 | if (typeof asTag === "string" && SELT_CLOSING_TAGS.includes(asTag)) return () => h(asTag, attrs); 28 | 29 | if (asTag !== "template") return () => h(props.as, attrs, { default: slots.default }); 30 | 31 | return () => h(Slot, attrs, { default: slots.default }); 32 | }, 33 | }); 34 | -------------------------------------------------------------------------------- /src/components/primitive/Slot.ts: -------------------------------------------------------------------------------- 1 | import { cloneVNode, defineComponent, mergeProps } from "vue"; 2 | import { renderSlotFragments } from "@/utils/renderSlotFragments"; 3 | 4 | export const Slot = defineComponent({ 5 | name: "PrimitiveSlot", 6 | inheritAttrs: false, 7 | setup(_, { attrs, slots }) { 8 | return () => { 9 | if (!slots.default) return null; 10 | const childrens = renderSlotFragments(slots.default()); 11 | 12 | const [firstChildren, ...otherChildren] = childrens; 13 | 14 | if (firstChildren) { 15 | // remove props ref from being inferred 16 | delete firstChildren.props?.ref; 17 | const mergedProps = mergeProps(attrs, firstChildren.props ?? {}); 18 | // remove class to prevent duplicated 19 | if (attrs.class && firstChildren.props?.class) delete firstChildren.props.class; 20 | 21 | const cloned = cloneVNode(firstChildren, mergedProps); 22 | // Explicitly override props starting with `on`. 23 | // It seems cloneVNode from Vue doesn't like overriding `onXXX` props. So 24 | // we have to do it manually. 25 | for (const prop in mergedProps) { 26 | if (prop.startsWith("on")) { 27 | cloned.props ||= {}; 28 | cloned.props[prop] = mergedProps[prop]; 29 | } 30 | } 31 | 32 | return childrens.length === 1 ? cloned : [cloned, ...otherChildren]; 33 | } 34 | 35 | return childrens; 36 | }; 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /src/components/primitive/index.ts: -------------------------------------------------------------------------------- 1 | export { Primitive, type PrimitiveProps } from "./Primitive"; 2 | export { Slot } from "./Slot"; 3 | -------------------------------------------------------------------------------- /src/components/provider/Provider.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /src/components/provider/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Provider, type ProviderProps } from "./Provider.vue"; 2 | -------------------------------------------------------------------------------- /src/components/radio/RadioRoot.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 63 | -------------------------------------------------------------------------------- /src/components/radio/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RRadio, type RRadioProps } from "./RRadio.vue"; 2 | 3 | export { default as RadioRoot, type RadioRootEmits, type RadioRootProps } from "./RadioRoot.vue"; 4 | -------------------------------------------------------------------------------- /src/components/roving-focus/RovingFocusItem.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /src/components/roving-focus/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RovingFocusRoot, type RovingFocusRootProps } from "./RovingFocusRoot.vue"; 2 | export { default as RovingFocusItem, type RovingFocusItemProps } from "./RovingFocusItem.vue"; 3 | -------------------------------------------------------------------------------- /src/components/roving-focus/utils.ts: -------------------------------------------------------------------------------- 1 | import type { Direction, Dir, Orientation } from "../../types"; 2 | 3 | export const MAP_KEY_TO_FOCUS_DIRECTION: Record = { 4 | ArrowLeft: "backward", 5 | ArrowUp: "backward", 6 | ArrowRight: "forward", 7 | ArrowDown: "forward", 8 | }; 9 | 10 | export function getDirectionAwareKey(key: string, dir?: Dir) { 11 | if (dir !== "rtl") return key; 12 | return key === "ArrowLeft" ? "ArrowRight" : key === "ArrowRight" ? "ArrowLeft" : key; 13 | } 14 | 15 | export function getFocusDirection(event: KeyboardEvent, orientation?: Orientation, dir?: Dir) { 16 | const key = getDirectionAwareKey(event.key, dir); 17 | if (orientation === "vertical" && ["ArrowLeft", "ArrowRight"].includes(key)) return undefined; 18 | if (orientation === "horizontal" && ["ArrowUp", "ArrowDown"].includes(key)) return undefined; 19 | return MAP_KEY_TO_FOCUS_DIRECTION[key]; 20 | } 21 | 22 | export function wrapArray(array: T[], startIndex: number) { 23 | return array.map((_, index) => array[(startIndex + index) % array.length]); 24 | } 25 | 26 | export const focusFirst = (list: Array) => { 27 | const currentlyFocuedElement = document.activeElement; 28 | for (const item of list) { 29 | if (item === currentlyFocuedElement) return; 30 | item.focus(); 31 | if (document.activeElement !== currentlyFocuedElement) return; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/components/select/ROption.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 55 | 56 | 80 | -------------------------------------------------------------------------------- /src/components/select/RSelectGroup.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 29 | -------------------------------------------------------------------------------- /src/components/select/RSelectInput.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/components/select/index.ts: -------------------------------------------------------------------------------- 1 | import RSelect from "./RSelect.vue"; 2 | import ROption from "./ROption.vue"; 3 | import RSelectGroup from "./RSelectGroup.vue"; 4 | 5 | export { RSelect, ROption, RSelectGroup }; 6 | -------------------------------------------------------------------------------- /src/components/select_prev/RSelectGroup.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 28 | 29 | 37 | -------------------------------------------------------------------------------- /src/components/select_prev/SelectedItems.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | 30 | 55 | -------------------------------------------------------------------------------- /src/components/select_prev/index.ts: -------------------------------------------------------------------------------- 1 | import RSelect, { type Props as RSelectProps } from "./RSelect.vue"; 2 | import ROption, { type Props as ROptionProps } from "./ROption.vue"; 3 | import RSelectGroup from "./RSelectGroup.vue"; 4 | 5 | export type { RSelectProps, ROptionProps } 6 | export { RSelect, ROption, RSelectGroup }; 7 | -------------------------------------------------------------------------------- /src/components/slider/RSliderTick.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 34 | 35 | 59 | -------------------------------------------------------------------------------- /src/components/slider/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RSlider, type RSliderProps } from "./RSlider.vue"; 2 | -------------------------------------------------------------------------------- /src/components/switch/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RSwitch, type RSwitchProps } from "./RSwitch.vue"; 2 | -------------------------------------------------------------------------------- /src/components/tabs/RPanelItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/components/tabs/RTabItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 44 | -------------------------------------------------------------------------------- /src/components/tabs/TabsIndicator.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 53 | -------------------------------------------------------------------------------- /src/components/tabs/TabsItem.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 63 | -------------------------------------------------------------------------------- /src/components/tabs/index.ts: -------------------------------------------------------------------------------- 1 | import RPanel from "./RPanel.vue"; 2 | import RPanelItem from "./RPanelItem.vue"; 3 | 4 | export { default as TabsRoot, type TabsRootProps, type TabsRootEmits } from "./TabsRoot.vue"; 5 | 6 | export { default as TabsItem, type TabsItemProps } from "./TabsItem.vue"; 7 | 8 | export { default as TabsIndicator } from "./TabsIndicator.vue"; 9 | 10 | export { default as RTab, type RTabEmits, type RTabsProps } from "./RTab.vue"; 11 | export { default as RTabItem, type RTabItemProps } from "./RTabItem.vue"; 12 | export { RPanel, RPanelItem }; 13 | -------------------------------------------------------------------------------- /src/composables/useCollection.ts: -------------------------------------------------------------------------------- 1 | import { unrefElement } from "@vueuse/core"; 2 | import { type Ref, inject, onBeforeUpdate, onMounted, onUpdated, provide, ref, watch } from "vue"; 3 | 4 | type ContextValue = Ref; 5 | 6 | export function useCollection(injectionKey: string, name = "data-sevue-collection-item") { 7 | const COLLECTION_SYMBOL = injectionKey; 8 | 9 | const createCollection = (sourceRef?: Ref) => { 10 | const items = ref([]); 11 | 12 | function updateItems() { 13 | const sourceEl = unrefElement(sourceRef); 14 | if (!sourceEl) { 15 | items.value = []; 16 | return; 17 | } 18 | 19 | items.value = Array.from(sourceEl.querySelectorAll(`[${name}]:not([data-disabled])`)) as HTMLElement[]; 20 | } 21 | 22 | onBeforeUpdate(() => { 23 | items.value = []; 24 | }); 25 | 26 | onMounted(updateItems); 27 | onUpdated(updateItems); 28 | 29 | watch(() => sourceRef?.value, updateItems, { immediate: true }); 30 | 31 | provide(COLLECTION_SYMBOL, items); 32 | 33 | return items; 34 | }; 35 | 36 | const injectCollection = () => { 37 | return inject(COLLECTION_SYMBOL, ref([])); 38 | }; 39 | 40 | return { createCollection, injectCollection }; 41 | } 42 | -------------------------------------------------------------------------------- /src/composables/useColor.ts: -------------------------------------------------------------------------------- 1 | import { getColor, getForegroundColor } from "@/utils"; 2 | import { computed } from "vue"; 3 | import type { Ref } from "vue"; 4 | 5 | const useColor = (color: Ref, foregroundColor?: Ref) => { 6 | const c = computed(() => getColor(color.value)); 7 | 8 | const f = computed(() => { 9 | if (foregroundColor?.value) return getColor(foregroundColor.value); 10 | return getForegroundColor(color.value); 11 | }); 12 | 13 | return { color: c, foreground: f }; 14 | }; 15 | 16 | export default useColor; 17 | -------------------------------------------------------------------------------- /src/composables/useContext.ts: -------------------------------------------------------------------------------- 1 | import { type InjectionKey, provide, inject } from "vue"; 2 | 3 | export const useContext = (name: string) => { 4 | const injectionKey: InjectionKey = Symbol(name); 5 | 6 | const injector = () => { 7 | const injection = inject(injectionKey); 8 | if (injection) return injection; 9 | 10 | throw new Error(`Injection ${injectionKey.toString()} failed, insure component is inside ${name}`); 11 | }; 12 | 13 | const provider = (context: ContextType) => { 14 | provide(injectionKey, context); 15 | return context; 16 | }; 17 | 18 | return [injector, provider] as const; 19 | }; 20 | -------------------------------------------------------------------------------- /src/composables/useDirection.ts: -------------------------------------------------------------------------------- 1 | import type { Dir } from "@/types"; 2 | import { type Ref, computed, ref } from "vue"; 3 | 4 | export function useDirection(dir?: Ref) { 5 | return computed(() => dir?.value || "ltr"); 6 | } 7 | -------------------------------------------------------------------------------- /src/composables/useDynamicSlots.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, useSlots, watch, ref, type VNode } from "vue"; 2 | const useDynamicSlots = () => { 3 | const data = ref([]); 4 | 5 | const { default: defaultSlot } = useSlots(); 6 | 7 | onMounted(() => { 8 | data.value = defaultSlot!(); 9 | }); 10 | 11 | watch( 12 | () => defaultSlot!(), 13 | (defSlot) => (data.value = defSlot), 14 | { immediate: true } 15 | ); 16 | 17 | return data; 18 | }; 19 | export default useDynamicSlots; 20 | -------------------------------------------------------------------------------- /src/composables/useEmitsAsProps.ts: -------------------------------------------------------------------------------- 1 | import { camelize, getCurrentInstance, toHandlerKey } from "vue"; 2 | 3 | // https://github.com/vuejs/core/issues/5917 4 | 5 | export const useEmitsAsProps = (emit: (name: Name, ...args: any[]) => void) => { 6 | const vm = getCurrentInstance(); 7 | 8 | const events = vm?.type.emits as Name[]; 9 | const result: Record = {}; 10 | 11 | if (!events?.length) { 12 | console.warn(`No emitted event found. Please check component: ${vm?.type.__name}`); 13 | } 14 | 15 | events?.forEach((ev) => { 16 | result[toHandlerKey(camelize(ev))] = (...arg: any) => emit(ev, ...arg); 17 | }); 18 | return result; 19 | }; 20 | -------------------------------------------------------------------------------- /src/composables/useFloating.ts: -------------------------------------------------------------------------------- 1 | import { 2 | useFloating as useBaseFloating, 3 | flip, 4 | offset, 5 | shift, 6 | size, 7 | autoUpdate, 8 | type UseFloatingReturn, 9 | type UseFloatingOptions, 10 | type OffsetOptions, 11 | type DetectOverflowOptions, 12 | type Placement, 13 | } from "@floating-ui/vue"; 14 | import { computed, type Ref } from "vue"; 15 | 16 | export { Placement }; 17 | 18 | export interface Options { 19 | offset?: OffsetOptions; 20 | boundry?: DetectOverflowOptions["boundary"]; 21 | rootBoundry?: DetectOverflowOptions["rootBoundary"]; 22 | open?: Ref; 23 | placement?: Placement; 24 | } 25 | 26 | export const useFloating = ( 27 | reference: Parameters[0], 28 | floating: Parameters[1], 29 | options?: Ref 30 | ): UseFloatingReturn => { 31 | const detectOverflowOptions = computed(() => { 32 | return { 33 | boundary: options?.value?.boundry, 34 | rootBoundary: options?.value?.rootBoundry, 35 | }; 36 | }); 37 | 38 | const middleware = computed(() => [ 39 | offset(options?.value?.offset || 4), 40 | flip({ 41 | ...detectOverflowOptions.value, 42 | crossAxis: false, 43 | }), 44 | shift({ 45 | ...detectOverflowOptions.value, 46 | }), 47 | size({ 48 | ...detectOverflowOptions.value, 49 | apply: ({ availableHeight, availableWidth, elements }) => { 50 | Object.assign(elements.floating.style, { maxWidth: `${availableWidth}px`, maxHeight: `${availableHeight}px` }); 51 | }, 52 | }), 53 | ]); 54 | 55 | const result = useBaseFloating(reference, floating, { 56 | whileElementsMounted: autoUpdate, 57 | open: options?.value?.open, 58 | placement: options?.value?.placement, 59 | middleware, 60 | }); 61 | 62 | return result; 63 | }; 64 | 65 | export { autoUpdate }; 66 | -------------------------------------------------------------------------------- /src/composables/useForwardRef.ts: -------------------------------------------------------------------------------- 1 | import { type ComponentPublicInstance, getCurrentInstance, ref, computed } from "vue"; 2 | import { unrefElement } from "@vueuse/core"; 3 | 4 | export function useForwardRef() { 5 | const instance = getCurrentInstance()!; 6 | 7 | const currentRef = ref(); 8 | const currentElement = computed(() => { 9 | // $el could be text/comment for non-single root normal or text root, thus we retrieve the nextElementSibling 10 | // @ts-expect-error ignore ts error 11 | return ["#text", "#comment"].includes(currentRef.value?.$el.nodeName) 12 | ? // @ts-expect-error ignore ts error 13 | currentRef.value?.$el.nextElementSibling 14 | : // @ts-expect-error ignore ts error 15 | unrefElement(currentRef); 16 | }); 17 | 18 | function forwardRef(ref: Element | ComponentPublicInstance | null) { 19 | currentRef.value = ref; 20 | if (typeof ref === "object") { 21 | instance.exposed = ref; 22 | instance.exposeProxy = ref; 23 | } 24 | } 25 | return { forwardRef, currentRef, currentElement }; 26 | } 27 | -------------------------------------------------------------------------------- /src/composables/useId.ts: -------------------------------------------------------------------------------- 1 | import { injectProviderContext } from "@/components/provider/Provider.vue"; 2 | 3 | let count = 0; 4 | 5 | export function useId(manual?: string, prefix = "sevue") { 6 | if (manual) return manual; 7 | 8 | const providerContext = injectProviderContext(); 9 | 10 | if (providerContext.useId) return providerContext.useId(); 11 | return `${prefix}-${++count}`; 12 | } 13 | -------------------------------------------------------------------------------- /src/composables/useLoading.ts: -------------------------------------------------------------------------------- 1 | import { loadingKey } from "@/injectionKeys"; 2 | import type { LoadingInject } from "@/types"; 3 | import { inject } from "vue"; 4 | 5 | const useLoading = () => { 6 | return inject(loadingKey) as LoadingInject; 7 | }; 8 | 9 | export default useLoading; 10 | -------------------------------------------------------------------------------- /src/composables/useNotification.ts: -------------------------------------------------------------------------------- 1 | import { notificationKey } from "@/injectionKeys"; 2 | import { inject } from "vue"; 3 | import type { NotificationInject } from "@/types"; 4 | 5 | const useNotification = () => { 6 | const notification = inject(notificationKey) as NotificationInject; 7 | return notification; 8 | }; 9 | 10 | export default useNotification; 11 | -------------------------------------------------------------------------------- /src/composables/useSevue.ts: -------------------------------------------------------------------------------- 1 | import { sevueKey } from "@/injectionKeys" 2 | import type { Sevue } from "@/types" 3 | import { inject } from "vue" 4 | 5 | const useSevue = () => { 6 | const sevue = inject(sevueKey) as Sevue 7 | return sevue 8 | } 9 | 10 | export default useSevue -------------------------------------------------------------------------------- /src/directives/appendToBody.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | beforeMount(el: HTMLElement) { 3 | document!.querySelector("body")!.appendChild(el); 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /src/injectionKeys.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, Ref, ComputedRef } from "vue"; 2 | import type { 3 | LoadingOptions, 4 | NotificationOptions, 5 | Notification, 6 | LoadingInject, 7 | Sevue, 8 | SelectInject, 9 | NotificationInject, 10 | SliderInject, 11 | TabInject, 12 | PanelInject, 13 | } from "@/types"; 14 | 15 | export const notificationKey = Symbol() as InjectionKey; 16 | 17 | export const sevueKey = Symbol() as InjectionKey; 18 | 19 | export const rSelectKey = Symbol() as InjectionKey; 20 | 21 | export const loadingKey = Symbol() as InjectionKey; 22 | 23 | export const sliderKey = Symbol() as InjectionKey; 24 | 25 | export const tabKey = Symbol() as InjectionKey; 26 | 27 | export const panelKey = Symbol() as InjectionKey; 28 | -------------------------------------------------------------------------------- /src/styles/ripple.scss: -------------------------------------------------------------------------------- 1 | .v-ripple { 2 | &__container { 3 | color: inherit; 4 | 5 | border-radius: inherit; 6 | position: absolute; 7 | width: 100%; 8 | height: 100%; 9 | left: 0; 10 | top: 0; 11 | overflow: hidden; 12 | z-index: 0; 13 | pointer-events: none; 14 | contain: strict; 15 | } 16 | 17 | &__animation { 18 | color: inherit; 19 | 20 | position: absolute; 21 | top: 0; 22 | left: 0; 23 | border-radius: 50%; 24 | background: currentColor; 25 | opacity: 0; 26 | pointer-events: none; 27 | overflow: hidden; 28 | will-change: transform, opacity; 29 | 30 | &--enter { 31 | transition: none; 32 | } 33 | 34 | &--in { 35 | transition: $ripple-animation-transition-in; 36 | } 37 | 38 | &--out { 39 | transition: $ripple-animation-transition-out; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | @function color($color: color, $alpha: 1) { 2 | @return rgba(var(--r-#{$color}), $alpha); 3 | } 4 | @function generateBoxShadow($width: 1px, $color: prm, $alpha: 1) { 5 | @return 0 0 0 $width rgba(var(--r-#{$color}), $alpha); 6 | } 7 | 8 | .flexCenter { 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | } 13 | 14 | .overflow-x-scroll-bar, 15 | .scroll-bar { 16 | &::-webkit-scrollbar { 17 | height: 4px; 18 | width: 4px; 19 | display: block; 20 | } 21 | &::-webkit-scrollbar-thumb { 22 | background: rgba(gray, 0.3); 23 | border-radius: 5px; 24 | } 25 | } 26 | 27 | // ripple 28 | $transition: ( 29 | "fast-out-slow-in": cubic-bezier(0.4, 0, 0.2, 1), 30 | "linear-out-slow-in": cubic-bezier(0, 0, 0.2, 1), 31 | "fast-out-linear-in": cubic-bezier(0.4, 0, 1, 1), 32 | "ease-in-out": cubic-bezier(0.4, 0, 0.6, 1), 33 | "fast-in-fast-out": cubic-bezier(0.25, 0.8, 0.25, 1), 34 | "swing": cubic-bezier(0.25, 0.8, 0.5, 1), 35 | ) !default; 36 | $ripple-animation-transition-in: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.1s cubic-bezier(0.4, 0, 0.2, 1) !default; 37 | $ripple-animation-transition-out: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) !default; 38 | $ripple-animation-visible-opacity: 0.15 !default; 39 | -------------------------------------------------------------------------------- /src/utils/createContext.ts: -------------------------------------------------------------------------------- 1 | import { type InjectionKey, provide, inject } from "vue"; 2 | 3 | export const createContext = (name: string) => { 4 | const injectionKey: InjectionKey = Symbol(name); 5 | 6 | const injector = () => { 7 | const injection = inject(injectionKey); 8 | if (injection) return injection; 9 | 10 | throw new Error(`Injection ${injectionKey.toString()} failed, insure component is inside ${name}`); 11 | }; 12 | 13 | const provider = (context: ContextType) => { 14 | provide(injectionKey, context); 15 | return context; 16 | }; 17 | 18 | return [injector, provider]; 19 | }; 20 | -------------------------------------------------------------------------------- /src/utils/getRelatedChildren.ts: -------------------------------------------------------------------------------- 1 | import type { VNode } from "vue"; 2 | 3 | export default (slot: VNode[], key: string) => { 4 | const items: VNode[] = []; 5 | 6 | const setItems = (unknownNodes: VNode[]) => { 7 | unknownNodes.forEach((unknownNode) => { 8 | if ((unknownNode.type as any)[key]) { 9 | items.push(unknownNode); 10 | } else if (typeof unknownNode.children === "object" && unknownNode.children) { 11 | // @ts-ignore 12 | if (unknownNode.children.default) { 13 | // @ts-ignore 14 | setItems(unknownNode.children.default() as VNode[]); 15 | } else { 16 | setItems(unknownNode.children as VNode[]); 17 | } 18 | } 19 | }); 20 | }; 21 | setItems(slot); 22 | 23 | return items; 24 | }; 25 | -------------------------------------------------------------------------------- /src/utils/mountComponent.ts: -------------------------------------------------------------------------------- 1 | import { createVNode, render } from "vue"; 2 | import type { Component, App } from "vue"; 3 | 4 | type Params = { 5 | props?: Record; 6 | children?: unknown; 7 | element?: HTMLElement; 8 | elementClass?: string; 9 | app?: App; 10 | }; 11 | const mounter = ( 12 | component: Component, // Component to mount 13 | { 14 | props, // props of the component 15 | children, // children of the component 16 | element = document.createElement("div"), // where to mount 17 | elementClass, 18 | app, 19 | }: Params = {} 20 | ) => { 21 | const vNode = createVNode(component, props, children); 22 | 23 | if (app) vNode.appContext = app._context; 24 | 25 | if (elementClass) element.classList.add(elementClass) 26 | render(vNode, element); 27 | 28 | const destroy = () => { 29 | if (element) render(null, element); 30 | }; 31 | const elementChild = element.children[0]; 32 | 33 | return { vNode, destroy, element, elementChild }; 34 | }; 35 | 36 | // export const mounterFactory = (app: App) => { 37 | // return (...args: [component: Component, params: Params]) => 38 | // mounter(...args, app); 39 | // }; 40 | 41 | export default mounter; 42 | -------------------------------------------------------------------------------- /src/utils/popper.ts: -------------------------------------------------------------------------------- 1 | import { createPopper, type ModifierArguments, type Options, type VirtualElement } from "@popperjs/core"; 2 | 3 | const sameWidth = { 4 | name: "sameWidth", 5 | enabled: true, 6 | phase: "beforeWrite", 7 | requires: ["computeStyles"], 8 | fn: ({ state }: ModifierArguments) => { 9 | state.styles.popper.width = `${state.rects.reference.width}px`; 10 | }, 11 | effect: ({ state }: ModifierArguments) => { 12 | state.elements.popper.style.width = `${(state.elements.reference as HTMLElement).offsetWidth}px`; 13 | }, 14 | }; 15 | 16 | export const createSameWidthPopper = ( 17 | el: Element | VirtualElement, 18 | popperEl: HTMLElement, 19 | options: any = {} 20 | ) => { 21 | const optionModifiers = options.modifiers || []; 22 | return createPopper(el, popperEl, { 23 | ...options, 24 | modifiers: [...optionModifiers, sameWidth], 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /src/utils/renderSlotFragments.ts: -------------------------------------------------------------------------------- 1 | import { Fragment, type VNode } from "vue"; 2 | 3 | export function renderSlotFragments(children?: VNode[]): VNode[] { 4 | if (!children) return []; 5 | return children.flatMap((child) => { 6 | if (child.type === Fragment) return renderSlotFragments(child.children as VNode[]); 7 | 8 | return [child]; 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "compilerOptions": { 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | }, 9 | "types": ["unplugin-vue-define-options/macros-global", "vite-svg-loader", "vite/client"] 10 | }, 11 | "references": [ 12 | { 13 | "path": "./tsconfig.node.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from "node:url"; 2 | 3 | import { defineConfig } from "vite"; 4 | // @ts-ignore 5 | import DefineOptions from "unplugin-vue-define-options/vite"; 6 | import Components from "unplugin-vue-components/vite"; 7 | import vue from "@vitejs/plugin-vue"; 8 | import dts from "vite-plugin-dts"; 9 | import ViteSVGLoader from "vite-svg-loader"; 10 | 11 | // https://vitejs.dev/config/ 12 | export default defineConfig({ 13 | plugins: [ 14 | vue(), 15 | DefineOptions(), 16 | ViteSVGLoader({ 17 | defaultImport: "component", 18 | }), 19 | { 20 | ...Components({ 21 | dts: true, 22 | resolvers: [ 23 | (componentName) => { 24 | return { name: componentName, from: "./src/components" }; 25 | }, 26 | ], 27 | }), 28 | name: "build-only", 29 | apply: "build", 30 | }, 31 | { 32 | ...dts({ 33 | skipDiagnostics: false, 34 | entryRoot: "./src", 35 | copyDtsFiles: true, 36 | }), 37 | name: "build-only", 38 | apply: "build", 39 | }, 40 | ], 41 | build: { 42 | lib: { 43 | entry: "src/main.ts", 44 | name: "sevue", 45 | // fileName: (format) => `sevue.${format}.js`, 46 | }, 47 | rollupOptions: { 48 | external: ["vue"], 49 | output: { globals: { vue: "Vue" }, exports: "named" }, 50 | }, 51 | }, 52 | resolve: { 53 | alias: { 54 | "@": fileURLToPath(new URL("./src", import.meta.url)), 55 | }, 56 | }, 57 | css: { 58 | preprocessorOptions: { 59 | scss: { 60 | additionalData: ` 61 | @use "sass:math"; 62 | @import "./src/styles/variables.scss"; 63 | `, 64 | }, 65 | }, 66 | }, 67 | server: { 68 | port: 4000, 69 | }, 70 | }); 71 | --------------------------------------------------------------------------------