├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .versionrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── __test__ ├── hexToRgb.test.ts ├── newVariables.test.ts ├── prefix.test.ts ├── safeList.test.ts ├── selectors.prefix.test.ts ├── sortThemes.test.ts └── theme.test.ts ├── components ├── base.css ├── base │ ├── base.css │ └── tailwind.config.js ├── components.css ├── informational │ ├── accordion.css │ ├── alert.css │ ├── avatar.css │ ├── badge.css │ ├── card.css │ ├── divider.css │ ├── dot.css │ ├── form-control.css │ ├── kbd.css │ ├── menu.css │ ├── modal.css │ ├── pagination.css │ ├── popover.css │ ├── progress.css │ ├── sidebar.css │ ├── skeleton.css │ ├── spinner.css │ ├── stepper.css │ ├── table.css │ ├── tabs.css │ └── tooltip.css ├── inputs │ ├── button-group.css │ ├── button.css │ ├── checkbox.css │ ├── dropdown.css │ ├── input-file.css │ ├── input.css │ ├── radio.css │ ├── range.css │ ├── select.css │ ├── switch.css │ └── textarea.css ├── navigation │ ├── breadcrumb.css │ ├── drawer.css │ ├── link.css │ └── navbar.css ├── styles.css ├── utilities.css └── utilities │ ├── tailwind.config.js │ └── utilities.css ├── config ├── colors │ ├── background.ts │ ├── base-colors.ts │ ├── blue.ts │ ├── cyan.ts │ ├── default-schema.ts │ ├── gray.ts │ ├── green.ts │ ├── index.ts │ ├── pink.ts │ ├── purple.ts │ ├── red.ts │ ├── slate.ts │ ├── text.ts │ └── yellow.ts ├── index.ts ├── prefix │ └── prefix.ts ├── theme │ ├── dark-theme.ts │ ├── ligh-theme.ts │ └── var-theme.ts ├── types │ ├── config.types.ts │ ├── theme.types.ts │ └── variables.types.ts └── utils │ ├── applyOpacityValue.ts │ ├── extractNewVariables.ts │ ├── hexToRGB.ts │ ├── isEmpty.ts │ ├── prefix.ts │ ├── safeList.ts │ ├── sortThemes.ts │ └── theme.ts ├── docs ├── .env.local ├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── README.md ├── components │ ├── icons │ │ ├── ArrowRight.tsx │ │ ├── Book.tsx │ │ ├── BookIcon.tsx │ │ ├── ChangelogIcon.tsx │ │ ├── ChevronLeft.tsx │ │ ├── ChevronRight.tsx │ │ ├── ComponentsIcon.tsx │ │ ├── CopyIcon.tsx │ │ ├── DiscordIcon.tsx │ │ ├── GithubIcon.tsx │ │ ├── LogoIcon.tsx │ │ ├── MenuIcon.tsx │ │ ├── Recyle.tsx │ │ ├── SearchIcon.tsx │ │ ├── Tools.tsx │ │ ├── TwitterIcon.tsx │ │ └── XIcon.tsx │ ├── layout │ │ ├── DocsLayout.tsx │ │ └── MainLayout.tsx │ ├── mdx │ │ ├── CDN.tsx │ │ ├── Code.tsx │ │ ├── ExamplesRepositories.tsx │ │ ├── Heading.tsx │ │ ├── Li.tsx │ │ ├── Link.tsx │ │ ├── LinkRedirect.tsx │ │ ├── Paragraph.tsx │ │ ├── Resizable.tsx │ │ ├── attributes │ │ │ ├── attributes-table.tsx │ │ │ ├── attributes-title.tsx │ │ │ ├── attributes.tsx │ │ │ └── index.ts │ │ ├── index.tsx │ │ └── layout │ │ │ └── Meta.tsx │ ├── playground │ │ ├── CodeBlock.tsx │ │ └── title.tsx │ └── styles │ │ ├── Community.tsx │ │ ├── Comparison.tsx │ │ ├── DarkMode.tsx │ │ ├── DarkModeSwitcher.tsx │ │ ├── Footer.tsx │ │ ├── GetStarted.tsx │ │ ├── Hero.tsx │ │ ├── Navbar.tsx │ │ ├── NavbarDocs.tsx │ │ ├── Pallete.tsx │ │ ├── Reusable.tsx │ │ ├── Searcher.tsx │ │ ├── SideNav.tsx │ │ ├── Sidebar.tsx │ │ ├── Statistics.tsx │ │ └── TableOfContents.tsx ├── content │ ├── components │ │ ├── accordion.mdx │ │ ├── alert.mdx │ │ ├── avatar.mdx │ │ ├── badge.mdx │ │ ├── breadcrumb.mdx │ │ ├── button-group.mdx │ │ ├── button.mdx │ │ ├── card.mdx │ │ ├── checkbox.mdx │ │ ├── divider.mdx │ │ ├── dots.mdx │ │ ├── drawer.mdx │ │ ├── dropdown.mdx │ │ ├── forms.mdx │ │ ├── input-file.mdx │ │ ├── input.mdx │ │ ├── kbd.mdx │ │ ├── link.mdx │ │ ├── menu.mdx │ │ ├── modal.mdx │ │ ├── navbar.mdx │ │ ├── pagination.mdx │ │ ├── popover.mdx │ │ ├── progress.mdx │ │ ├── radio.mdx │ │ ├── range.mdx │ │ ├── select.mdx │ │ ├── sidebar.mdx │ │ ├── skeleton.mdx │ │ ├── spinners.mdx │ │ ├── stepper.mdx │ │ ├── switch.mdx │ │ ├── table.mdx │ │ ├── tabs.mdx │ │ ├── textarea.mdx │ │ └── tooltip.mdx │ ├── get-started │ │ ├── customization.mdx │ │ ├── installation.mdx │ │ ├── theme.mdx │ │ └── usage.mdx │ ├── license │ │ └── MIT.mdx │ └── more │ │ └── changelog.mdx ├── hooks │ ├── useCopyToClipboard.ts │ ├── useIsomorphicLayoutEffect.ts │ ├── useMobile.ts │ ├── useOutsideAlerter.ts │ ├── useScroll.ts │ └── useScrollSpy.ts ├── lib │ └── constant.ts ├── next-sitemap.config.js ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.tsx │ ├── _document.tsx │ ├── docs │ │ └── [[...page]].tsx │ └── index.tsx ├── postcss.config.js ├── public │ ├── android-chrome-192x192.png │ ├── android-chrome-384x384.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── card.webp │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── grad.png │ ├── grad2.png │ ├── iframe.js │ ├── logo.png │ ├── mesh.png │ ├── mesh2.png │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ ├── site.webmanifest │ └── vercel.svg ├── styles │ ├── globals.css │ ├── playground.css │ └── searcher.css ├── tailwind.config.js ├── tsconfig.json └── utils │ ├── getRoutes.ts │ ├── getToc.ts │ ├── htmlToJsx.ts │ ├── items.ts │ ├── jsxToHtml.ts │ ├── pallete.ts │ └── titleToSlug.ts ├── examples ├── gastby-example │ ├── .gitignore │ ├── README.md │ ├── gatsby-browser.js │ ├── gatsby-config.ts │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.js │ ├── src │ │ ├── images │ │ │ └── icon.png │ │ ├── pages │ │ │ ├── 404.tsx │ │ │ └── index.tsx │ │ └── styles │ │ │ └── global.css │ ├── tailwind.config.js │ └── tsconfig.json ├── my-angular-project │ ├── .editorconfig │ ├── .gitignore │ ├── .vscode │ │ ├── extensions.json │ │ ├── launch.json │ │ └── tasks.json │ ├── README.md │ ├── angular.json │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ └── app.module.ts │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ └── styles.css │ ├── tailwind.config.js │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── my-react-app │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.js │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── index.css │ │ └── index.js │ └── tailwind.config.js ├── my-remix-app │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── entry.client.tsx │ │ ├── entry.server.tsx │ │ ├── root.tsx │ │ ├── routes │ │ │ └── index.tsx │ │ └── styles │ │ │ └── app.css │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── favicon.ico │ ├── remix.config.js │ ├── remix.env.d.ts │ ├── tailwind.config.js │ └── tsconfig.json ├── my-svelte-app │ ├── .eslintignore │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .npmrc │ ├── .prettierignore │ ├── .prettierrc │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.cjs │ ├── src │ │ ├── app.css │ │ ├── app.d.ts │ │ ├── app.html │ │ ├── lib │ │ │ └── images │ │ │ │ ├── github.svg │ │ │ │ ├── svelte-logo.svg │ │ │ │ ├── svelte-welcome.png │ │ │ │ └── svelte-welcome.webp │ │ └── routes │ │ │ ├── +layout.svelte │ │ │ ├── +page.svelte │ │ │ ├── +page.ts │ │ │ ├── Counter.svelte │ │ │ ├── Header.svelte │ │ │ ├── about │ │ │ ├── +page.svelte │ │ │ └── +page.ts │ │ │ ├── styles.css │ │ │ └── sverdle │ │ │ ├── +page.server.ts │ │ │ ├── +page.svelte │ │ │ ├── game.ts │ │ │ ├── how-to-play │ │ │ ├── +page.svelte │ │ │ └── +page.ts │ │ │ ├── reduced-motion.ts │ │ │ └── words.server.ts │ ├── static │ │ ├── favicon.png │ │ └── robots.txt │ ├── svelte.config.js │ ├── tailwind.config.cjs │ ├── tsconfig.json │ └── vite.config.js ├── nextjs-example │ ├── .eslintrc.json │ ├── .gitignore │ ├── README.md │ ├── next.config.js │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ ├── api │ │ │ └── hello.ts │ │ └── index.tsx │ ├── postcss.config.js │ ├── public │ │ ├── favicon.ico │ │ ├── next.svg │ │ ├── thirteen.svg │ │ └── vercel.svg │ ├── styles │ │ ├── Home.module.css │ │ └── globals.css │ ├── tailwind.config.js │ └── tsconfig.json └── vuejs-example │ ├── .gitignore │ ├── .vscode │ └── extensions.json │ ├── README.md │ ├── env.d.ts │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── postcss.config.js │ ├── public │ └── favicon.ico │ ├── src │ ├── App.vue │ ├── assets │ │ ├── base.css │ │ ├── logo.svg │ │ └── main.css │ ├── components │ │ ├── HelloWorld.vue │ │ ├── TheWelcome.vue │ │ ├── WelcomeItem.vue │ │ └── icons │ │ │ ├── IconCommunity.vue │ │ │ ├── IconDocumentation.vue │ │ │ ├── IconEcosystem.vue │ │ │ ├── IconSupport.vue │ │ │ └── IconTooling.vue │ └── main.ts │ ├── tailwind.config.js │ ├── tsconfig.config.json │ ├── tsconfig.json │ └── vite.config.ts ├── experiments └── rippleui │ ├── base.html │ └── theme-change.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── prettier.config.js ├── scripts └── minify.js ├── standalone-cli ├── .gitignore ├── README.md ├── example │ ├── index.html │ ├── input.css │ ├── output.css │ ├── tailwind.config.js │ └── tailwindcss ├── package-lock.json ├── package.json ├── standalone.js └── tests │ ├── fixtures │ ├── basic.html │ ├── plugins.html │ ├── postcss.config.js │ └── test.config.js │ └── test.js ├── tailwind.config.js └── tsconfig.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | 3 | # These owners will be the default owners for everything in the repo. 4 | * @siumauricio 5 | 6 | # Order is important. The last matching pattern has the most precedence. 7 | # So if a pull request only touches javascript files, only these owners 8 | # will be requested to review. 9 | # *.js @octocat @github/js 10 | 11 | # You can also use email addresses if you prefer. 12 | # docs/* docs@example.com -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | # Description 10 | 11 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 12 | 13 | Closes # 14 | 15 | ## Type of change 16 | 17 | Please delete options that are not relevant. 18 | 19 | - [ ] Bug fix (non-breaking change which fixes an issue) 20 | - [ ] New feature (non-breaking change which adds functionality) 21 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 22 | - [ ] This change requires a documentation update 23 | - [ ] Refactor (implement any different implementation of something) 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules 3 | dist 4 | experiments/* 5 | !experiments/rippleui 6 | experiments/rippleui/* 7 | !experiments/rippleui/base.html 8 | !experiments/rippleui/theme-change.js -------------------------------------------------------------------------------- /.versionrc: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | { 4 | "type": "chore", 5 | "scope": "docs", 6 | "hidden": true 7 | }, 8 | { 9 | "type": "feat", 10 | "scope": "docs", 11 | "hidden": true 12 | }, 13 | { 14 | "type": "refactor", 15 | "scope": "docs", 16 | "hidden": true 17 | }, 18 | { 19 | "type": "fix", 20 | "scope": "docs", 21 | "hidden": true 22 | }, 23 | { 24 | "type": "styles", 25 | "scope": "docs", 26 | "hidden": false 27 | }, 28 | { 29 | "type": "fix", 30 | "section": "Bug Fixes", 31 | "hidden": false 32 | }, 33 | { 34 | "type": "chore", 35 | "section": "Chores", 36 | "hidden": true 37 | }, 38 | { 39 | "type": "feat", 40 | "section": "Features", 41 | "hidden": false 42 | }, 43 | { 44 | "type": "refactor", 45 | "section": "Refactor", 46 | "hidden": false 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mauricio Siu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__test__/hexToRgb.test.ts: -------------------------------------------------------------------------------- 1 | import { hexToRGB } from "./../config/utils/hexToRGB"; 2 | import { expect, test } from "vitest"; 3 | 4 | test("Should recieve a hexa and return a rgb", (t) => { 5 | let hexa = "#ffffff"; 6 | 7 | let result = hexToRGB(hexa); 8 | expect(result).toEqual("255 255 255"); 9 | 10 | hexa = "#000000"; 11 | result = hexToRGB(hexa); 12 | expect(result).toEqual("0 0 0"); 13 | 14 | hexa = "#653463"; 15 | result = hexToRGB(hexa); 16 | expect(result).toEqual("101 52 99"); 17 | }); 18 | 19 | test("Should throw and error if receive a invalid hex", (t) => { 20 | let hexa = "#fff"; 21 | 22 | expect(() => hexToRGB(hexa)).toThrowError(); 23 | 24 | hexa = "#4262"; 25 | expect(() => hexToRGB(hexa)).toThrowError(); 26 | 27 | hexa = "#4262f"; 28 | expect(() => hexToRGB(hexa)).toThrowError(); 29 | 30 | hexa = "#4262ffg"; 31 | expect(() => hexToRGB(hexa)).toThrowError(); 32 | }); 33 | -------------------------------------------------------------------------------- /__test__/newVariables.test.ts: -------------------------------------------------------------------------------- 1 | import { extractNewVariables } from "./../config/utils/extractNewVariables"; 2 | import { expect, test } from "vitest"; 3 | 4 | test("Should return colors with -- in each property", (t) => { 5 | const colorsMap1: any = { 6 | "blue-2": "#fff", 7 | }; 8 | 9 | const colorsMap2: any = { 10 | "blue-3": "#fff", 11 | }; 12 | const result = extractNewVariables(colorsMap1, colorsMap2); 13 | 14 | expect(result).toEqual({ 15 | "blue-3": expect.any(Function), 16 | }); 17 | }); 18 | 19 | test("Should return empty obj is obj1 is empty", (t) => { 20 | const colorsMap1: any = { 21 | "blue-2": "#fff", 22 | }; 23 | 24 | const colorsMap2: any = {}; 25 | const result = extractNewVariables(colorsMap1, colorsMap2); 26 | 27 | expect(result).toEqual({}); 28 | }); 29 | -------------------------------------------------------------------------------- /__test__/prefix.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "vitest"; 2 | import { addPrefix } from "../config/utils/prefix"; 3 | 4 | test("Should return colors with -- in each property", (t) => { 5 | const obj = { 6 | white: "#fff", 7 | "white-invert": "#000", 8 | "white-inverted": "#000", 9 | }; 10 | const result = addPrefix(obj); 11 | expect(result).toEqual({ 12 | "--white": "#fff", 13 | "--white-invert": "#000", 14 | "--white-inverted": "#000", 15 | }); 16 | }); 17 | 18 | test("Should return empty obj if receive empty obj", (t) => { 19 | const obj: any = {}; 20 | const result = addPrefix(obj); 21 | expect(result).toEqual({}); 22 | }); 23 | -------------------------------------------------------------------------------- /__test__/safeList.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test } from "vitest"; 2 | import { safeList } from "../config/utils/safeList"; 3 | 4 | const regex = safeList[0] as { 5 | pattern: RegExp; 6 | variants?: string[] | undefined; 7 | }; 8 | test("should accept the following colors", (t) => { 9 | // This test passes because it does not throw an exception. 10 | 11 | expect(regex.pattern.test("bg-primary")).toBe(true); 12 | expect(regex.pattern.test("bg-secondary")).toBe(true); 13 | expect(regex.pattern.test("bg-backgroundSecondary")).toBe(true); 14 | expect(regex.pattern.test("bg-black")).toBe(true); 15 | expect(regex.pattern.test("bg-blackInverted")).toBe(true); 16 | expect(regex.pattern.test("bg-whiteInverted")).toBe(true); 17 | expect(regex.pattern.test("bg-blue-1")).toBe(true); 18 | expect(regex.pattern.test("bg-blue-2")).toBe(true); 19 | }); 20 | 21 | test("should not accept the following colors", (t) => { 22 | // Missing regex 23 | // This test fails because it throws an exception. 24 | // expect(regex.pattern.test("bg-whiteI")).toBe(false); 25 | // expect(regex.pattern.test("bg-whiteInvert")).toBe(false); 26 | // expect(regex.pattern.test("bg-whiteInvertedd")).toBe(false); 27 | // expect(regex.pattern.test("bg-whiteInverteddd")).toBe(false); 28 | // expect(regex.pattern.test("bg-blue-20")).toBe(false); 29 | }); 30 | -------------------------------------------------------------------------------- /components/base.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | -------------------------------------------------------------------------------- /components/base/base.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/base"; 2 | 3 | html { 4 | -webkit-tap-highlight-color: transparent; 5 | } 6 | -------------------------------------------------------------------------------- /components/base/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | corePlugins: { 4 | preflight: false, 5 | }, 6 | content: [], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | }; 12 | -------------------------------------------------------------------------------- /components/components.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/components"; 2 | @import "./inputs/button.css"; 3 | @import "./inputs/input.css"; 4 | @import "./inputs/textarea.css"; 5 | @import "./inputs/select.css"; 6 | @import "./inputs/checkbox.css"; 7 | @import "./inputs/radio.css"; 8 | @import "./inputs/switch.css"; 9 | @import "./inputs/button-group.css"; 10 | @import "./inputs/dropdown.css"; 11 | @import "./inputs/range.css"; 12 | @import "./inputs/input-file.css"; 13 | @import "./informational/modal.css"; 14 | @import "./informational/badge.css"; 15 | @import "./informational/tooltip.css"; 16 | @import "./informational/avatar.css"; 17 | @import "./informational/alert.css"; 18 | @import "./informational/table.css"; 19 | @import "./informational/card.css"; 20 | @import "./informational/accordion.css"; 21 | @import "./informational/tabs.css"; 22 | @import "./informational/divider.css"; 23 | @import "./informational/pagination.css"; 24 | @import "./informational/skeleton.css"; 25 | @import "./informational/stepper.css"; 26 | @import "./informational/kbd.css"; 27 | @import "./informational/progress.css"; 28 | @import "./informational/dot.css"; 29 | @import "./informational/form-control.css"; 30 | @import "./informational/menu.css"; 31 | @import "./informational/popover.css"; 32 | @import "./informational/sidebar.css"; 33 | @import "./informational/spinner.css"; 34 | @import "./navigation/navbar.css"; 35 | @import "./navigation/breadcrumb.css"; 36 | @import "./navigation/drawer.css"; 37 | @import "./navigation/link.css"; 38 | -------------------------------------------------------------------------------- /components/informational/alert.css: -------------------------------------------------------------------------------- 1 | .alert { 2 | @apply relative flex w-full flex-row items-center gap-3 rounded-xl bg-gray-4 p-4; 3 | } 4 | 5 | .alert-info { 6 | @apply bg-blue-4; 7 | } 8 | 9 | .alert-success { 10 | @apply bg-green-4; 11 | } 12 | 13 | .alert-warning { 14 | @apply bg-yellow-4; 15 | } 16 | 17 | .alert-error { 18 | @apply bg-red-4; 19 | } 20 | 21 | .alert-info { 22 | @apply bg-cyan-4; 23 | } 24 | -------------------------------------------------------------------------------- /components/informational/card.css: -------------------------------------------------------------------------------- 1 | .card { 2 | @apply bg-gray-3 flex w-full max-w-sm flex-col gap-2 rounded-xl shadow-md; 3 | } 4 | 5 | .card.card-image-cover img:first-child { 6 | @apply h-auto max-w-full rounded-t-xl; 7 | } 8 | 9 | .card.card-image-cover img:last-child { 10 | @apply h-auto max-w-full rounded-b-xl; 11 | } 12 | 13 | .card-header { 14 | @apply flex flex-row items-center justify-between text-xl font-semibold; 15 | } 16 | 17 | .card-body { 18 | @apply flex flex-col gap-3 p-8; 19 | } 20 | 21 | .card-footer { 22 | @apply flex flex-row items-center justify-between; 23 | } 24 | 25 | .card.card-image-cover:not( 26 | :has(.card-header), 27 | :has(.card-body), 28 | :has(.card-footer) 29 | ) 30 | img { 31 | @apply rounded-lg; 32 | } 33 | -------------------------------------------------------------------------------- /components/informational/divider.css: -------------------------------------------------------------------------------- 1 | .divider:not(:empty) { 2 | @apply gap-4; 3 | } 4 | 5 | .divider { 6 | @apply my-4 flex h-4 flex-row items-center whitespace-nowrap; 7 | } 8 | 9 | .divider::before, 10 | .divider-horizontal::before { 11 | @apply bg-gray-6 h-px w-full content-[""]; 12 | } 13 | 14 | .divider::after, 15 | .divider-horizontal::after { 16 | @apply bg-gray-6 h-px w-full content-[""]; 17 | } 18 | 19 | .divider-vertical { 20 | @apply my-0 mx-4 h-full w-4 flex-col; 21 | } 22 | 23 | .divider-vertical::before { 24 | @apply bg-gray-6 h-full w-px content-[""]; 25 | } 26 | 27 | .divider-vertical::after { 28 | @apply bg-gray-6 h-full w-px content-[""]; 29 | } 30 | -------------------------------------------------------------------------------- /components/informational/dot.css: -------------------------------------------------------------------------------- 1 | .dot { 2 | @apply inline-flex h-2.5 min-h-[10px] w-2.5 min-w-[10px] select-none rounded-[50%] bg-gray-8 leading-3; 3 | } 4 | 5 | .dot-primary { 6 | @apply bg-primary; 7 | } 8 | 9 | .dot-secondary { 10 | @apply bg-secondary; 11 | } 12 | 13 | .dot-success { 14 | @apply bg-success; 15 | } 16 | 17 | .dot-error { 18 | @apply bg-error; 19 | } 20 | 21 | .dot-warning { 22 | @apply bg-warning; 23 | } 24 | 25 | .dot-info { 26 | @apply bg-info; 27 | } 28 | .dot-xs { 29 | @apply h-1.5 min-h-[7px] w-1.5 min-w-[7px] leading-[8px]; 30 | } 31 | 32 | .dot-sm { 33 | @apply h-2 min-h-[8px] w-2 min-w-[8px] leading-[9px]; 34 | } 35 | 36 | .dot-md { 37 | @apply h-2.5 min-h-[10px] w-2.5 min-w-[10px] leading-[11px]; 38 | } 39 | 40 | .dot-lg { 41 | @apply h-3 min-h-[12px] w-3 min-w-[12px] leading-[13px]; 42 | } 43 | 44 | .dot-xl { 45 | @apply h-3.5 min-h-[14px] w-3.5 min-w-[14px] leading-[15px]; 46 | } 47 | -------------------------------------------------------------------------------- /components/informational/form-control.css: -------------------------------------------------------------------------------- 1 | .form-group { 2 | @apply flex w-full flex-col gap-3; 3 | } 4 | 5 | .form-field { 6 | @apply flex flex-col gap-1.5; 7 | } 8 | 9 | .form-label { 10 | @apply flex flex-row justify-between px-1 text-sm text-content1; 11 | } 12 | 13 | .form-label-alt { 14 | @apply text-xs text-content2; 15 | } 16 | 17 | .form-control { 18 | @apply relative flex flex-row gap-1.5 text-sm; 19 | } 20 | -------------------------------------------------------------------------------- /components/informational/kbd.css: -------------------------------------------------------------------------------- 1 | .kbd { 2 | @apply border-gray-6 bg-gray-3 inline-flex h-fit items-center justify-center whitespace-nowrap rounded-md border py-1.5 px-2.5 text-xs font-semibold shadow-[0px_1.5px_0px_rgba(0,0,0,0.1)]; 3 | } 4 | 5 | .kbd-xs { 6 | @apply py-0.5 px-1.5 text-xs; 7 | } 8 | 9 | .kbd-sm { 10 | @apply py-1 px-2 text-xs; 11 | } 12 | 13 | .kbd-md { 14 | @apply py-1.5 px-2.5 text-xs; 15 | } 16 | 17 | .kbd-lg { 18 | @apply py-2 px-3 text-sm; 19 | } 20 | 21 | .kbd-xl { 22 | @apply py-2 px-3.5 text-base; 23 | } 24 | -------------------------------------------------------------------------------- /components/informational/menu.css: -------------------------------------------------------------------------------- 1 | .menu { 2 | @apply flex w-full flex-col gap-2; 3 | } 4 | 5 | .menu-section { 6 | @apply flex flex-col gap-2; 7 | } 8 | 9 | .menu-title { 10 | @apply text-xs font-normal; 11 | } 12 | 13 | .menu-items { 14 | @apply flex flex-col gap-1.5; 15 | } 16 | 17 | .menu-item { 18 | transition-property: transform, opacity, visibility; 19 | transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 20 | @apply flex cursor-pointer select-none flex-row items-center gap-2 rounded-lg px-4 py-2 text-sm text-content1 duration-150 will-change-transform hover:bg-gray-4 active:scale-[0.97] active:bg-gray-5; 21 | } 22 | 23 | .menu-item-disabled { 24 | @apply pointer-events-none cursor-not-allowed text-content3 active:scale-[1]; 25 | } 26 | 27 | .menu-item-no-animation { 28 | @apply transition-none active:scale-[1]; 29 | } 30 | 31 | .menu-item.menu-active { 32 | @apply bg-gray-5 transition-none active:scale-[1]; 33 | } 34 | 35 | .menu-toggle { 36 | @apply hidden; 37 | } 38 | 39 | .menu-item-collapse { 40 | transition: padding 0.15s, grid-template-rows 0.15s; 41 | @apply grid grid-rows-[0fr] overflow-hidden; 42 | } 43 | 44 | .menu-toggle:checked ~ .menu-item-collapse { 45 | @apply grid-rows-[1fr] border-none; 46 | } 47 | 48 | .menu-item:focus-within ~ .menu-item-collapse { 49 | @apply grid-rows-[1fr] border-none; 50 | } 51 | 52 | .menu-icon { 53 | @apply transition-transform duration-300; 54 | } 55 | 56 | .menu-toggle:checked ~ .menu-item .menu-icon { 57 | @apply rotate-90; 58 | } 59 | -------------------------------------------------------------------------------- /components/informational/modal.css: -------------------------------------------------------------------------------- 1 | .modal { 2 | @apply invisible fixed inset-0 z-[60] flex items-center justify-center overscroll-none bg-black/60 px-4 text-left opacity-0 transition-all; 3 | } 4 | 5 | .modal-overlay { 6 | @apply absolute inset-0; 7 | } 8 | 9 | .modal-state { 10 | @apply hidden; 11 | } 12 | .modal-state:checked + .modal, 13 | .modal-open.modal { 14 | @apply visible translate-y-0 scale-100 opacity-100; 15 | } 16 | 17 | html:has(.modal-state:checked, .modal-open) { 18 | @apply overflow-hidden; 19 | } 20 | 21 | .modal-state:checked + .modal .modal-content, 22 | .modal-open .modal-content { 23 | @apply translate-y-0 scale-100; 24 | } 25 | 26 | .modal-content { 27 | @apply relative h-max max-h-[calc(100%-10%)] max-w-lg scale-90 overflow-auto rounded-xl bg-gray-1 p-6 transition duration-75 ease-in-out; 28 | } 29 | -------------------------------------------------------------------------------- /components/informational/pagination.css: -------------------------------------------------------------------------------- 1 | .pagination { 2 | @apply flex gap-2; 3 | } 4 | 5 | .pagination .btn { 6 | @apply hover:bg-gray-4 min-w-[2.5rem] border border-transparent px-0 py-2; 7 | } 8 | 9 | .pagination .btn.btn-active { 10 | @apply border-primary bg-primary text-white; 11 | } 12 | 13 | .pagination input:checked + .btn { 14 | @apply border-primary bg-primary text-white; 15 | } 16 | 17 | .pagination input:disabled + .btn { 18 | @apply pointer-events-none opacity-50; 19 | } 20 | 21 | .pagination input[type="radio"] { 22 | @apply invisible absolute opacity-0; 23 | } 24 | 25 | .pagination.pagination-compact { 26 | @apply gap-0; 27 | } 28 | 29 | .pagination.pagination-compact .btn { 30 | @apply border-transparent; 31 | } 32 | 33 | .pagination.pagination-bordered .btn { 34 | @apply border-gray-6 border; 35 | } 36 | 37 | .pagination.pagination-bordered .btn.btn-active { 38 | @apply border-primary; 39 | } 40 | 41 | .pagination.pagination-compact :where(.btn:first-of-type) { 42 | @apply rounded-r-none; 43 | } 44 | 45 | .pagination.pagination-compact :where(.btn:last-of-type) { 46 | @apply rounded-l-none; 47 | } 48 | 49 | .pagination.pagination-compact 50 | :where(.btn:not(:first-of-type):not(:last-of-type)) { 51 | @apply rounded-none; 52 | } 53 | 54 | .pagination.pagination-rounded .btn { 55 | @apply rounded-full; 56 | } 57 | -------------------------------------------------------------------------------- /components/informational/sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | @apply top-0 z-[55] flex h-screen w-full max-w-[18rem] translate-x-0 flex-col justify-between bg-gray-2; 3 | } 4 | 5 | .sidebar-sticky { 6 | @apply sticky; 7 | } 8 | 9 | .sidebar-fixed-left { 10 | @apply fixed left-0; 11 | } 12 | 13 | .sidebar-fixed-right { 14 | @apply fixed right-0; 15 | } 16 | 17 | .sidebar-title { 18 | @apply flex w-full items-center font-semibold text-content1; 19 | } 20 | 21 | .sidebar-content { 22 | @apply flex h-full w-full flex-col overflow-y-auto py-6; 23 | } 24 | 25 | .sidebar-footer { 26 | @apply flex w-full flex-col text-content1; 27 | } 28 | 29 | .sidebar-mobile { 30 | @apply transition-transform duration-150; 31 | } 32 | 33 | .sidebar-state { 34 | @apply hidden; 35 | } 36 | 37 | .sidebar-state:checked ~ .sidebar { 38 | @apply ml-0 translate-x-0; 39 | } 40 | 41 | html:has(.sidebar-state:checked) { 42 | @apply overflow-hidden; 43 | } 44 | 45 | .sidebar-state:checked ~ .sidebar-overlay { 46 | @apply fixed inset-0 z-50 bg-black/60 opacity-80 transition-all; 47 | } 48 | -------------------------------------------------------------------------------- /components/informational/skeleton.css: -------------------------------------------------------------------------------- 1 | @keyframes skeletonWave { 2 | 0% { 3 | background-position: 200% 0; 4 | } 5 | to { 6 | background-position: -200% 0; 7 | } 8 | } 9 | 10 | @keyframes skeletonPulse { 11 | 0% { 12 | opacity: 1; 13 | } 14 | 50% { 15 | opacity: 0.4; 16 | } 17 | 100% { 18 | opacity: 1; 19 | } 20 | } 21 | 22 | .skeleton { 23 | animation: skeletonWave 2.5s linear infinite; 24 | background: linear-gradient( 25 | 270deg, 26 | rgb(var(--gray-9)), 27 | rgb(var(--gray-7)), 28 | rgb(var(--gray-7)), 29 | rgb(var(--gray-9)) 30 | ); 31 | background-size: 400% 100%; 32 | transition: opacity 300ms ease-out; 33 | @apply h-full w-full opacity-50; 34 | } 35 | 36 | .skeleton-static { 37 | background: linear-gradient( 38 | 270deg, 39 | rgb(var(--gray-9)), 40 | rgb(var(--gray-7)), 41 | rgb(var(--gray-7)), 42 | rgb(var(--gray-9)) 43 | ); 44 | background-size: 400% 100%; 45 | @apply h-full w-full opacity-40; 46 | } 47 | 48 | .skeleton-pulse { 49 | animation: skeletonPulse 2s linear infinite; 50 | background: no-repeat; 51 | animation-delay: 0.5s; 52 | @apply bg-gray-7 h-full w-full; 53 | } 54 | -------------------------------------------------------------------------------- /components/informational/table.css: -------------------------------------------------------------------------------- 1 | .table { 2 | border-collapse: initial; 3 | @apply w-full border-spacing-0; 4 | } 5 | 6 | .table > thead > tr th:first-child { 7 | @apply border-gray-6 rounded-l-md border-y border-l; 8 | } 9 | 10 | .table > thead > tr th:last-child { 11 | @apply border-gray-6 rounded-r-md border-y border-r; 12 | } 13 | 14 | .table > thead > tr :not(.th:first-child, .th:last-child) { 15 | @apply border-gray-6 border-y; 16 | } 17 | 18 | .table > thead > tr > th { 19 | @apply bg-gray-3 whitespace-nowrap py-4 px-2.5 text-start text-sm font-normal text-content1; 20 | } 21 | 22 | .table > tbody > tr > td, 23 | .table > tbody > tr > th { 24 | @apply border-gray-6 whitespace-nowrap border-b py-4 px-2.5 text-start text-sm text-content2; 25 | } 26 | 27 | /* Compact */ 28 | .table.table-compact > tbody > tr > td, 29 | .table.table-compact > tbody > tr > th { 30 | @apply py-2.5; 31 | } 32 | 33 | .table.table-compact > tbody > tr > td:first-child, 34 | .table.table-compact > tbody > tr > th:first-child { 35 | @apply px-2.5; 36 | } 37 | 38 | .table.table-compact > tbody > tr > td:last-child, 39 | .table.table-compact > tbody > tr > th:last-child { 40 | @apply px-2.5; 41 | } 42 | 43 | .table.table-compact > tbody > tr > td:not(:first-child):not(:last-child), 44 | .table.table-compact > tbody > tr > th:not(:first-child):not(:last-child) { 45 | @apply px-2.5; 46 | } 47 | 48 | .table.table-compact > thead > tr > th { 49 | @apply py-2.5; 50 | } 51 | 52 | .table.table-compact > thead > tr > th:first-child { 53 | @apply px-2.5; 54 | } 55 | 56 | /* Zebra */ 57 | .table.table-zebra > tbody > tr:nth-child(even) > td, 58 | .table.table-zebra > tbody > tr:nth-child(even) > th { 59 | @apply bg-gray-3; 60 | } 61 | 62 | /* Hover */ 63 | .table.table-hover > tbody > tr:hover > td, 64 | .table.table-hover > tbody > tr:hover > th { 65 | @apply bg-gray-3; 66 | } 67 | -------------------------------------------------------------------------------- /components/navigation/breadcrumb.css: -------------------------------------------------------------------------------- 1 | .breadcrumbs { 2 | @apply flex flex-row gap-2 overflow-x-auto px-3 text-sm text-content2 sm:px-0; 3 | } 4 | 5 | .breadcrumbs > ul > li > a { 6 | @apply flex flex-row items-center; 7 | } 8 | 9 | .breadcrumbs > ul { 10 | @apply flex flex-row items-center whitespace-nowrap; 11 | } 12 | 13 | .breadcrumbs > ul > li { 14 | @apply flex cursor-pointer flex-row items-center; 15 | } 16 | 17 | .breadcrumbs > ul > :not(li:last-child) > a { 18 | @apply hover:underline; 19 | } 20 | 21 | .breadcrumbs > ul > li + *:before { 22 | @apply ml-2 mr-3 block opacity-40 content-["/"]; 23 | } 24 | 25 | .breadcrumbs-active { 26 | @apply text-content3; 27 | } 28 | 29 | .breadcrumbs > ul > li:last-child { 30 | @apply cursor-auto text-content3; 31 | } 32 | 33 | .breadcrumbs > ul > li:first-child { 34 | @apply cursor-pointer text-content2 hover:underline; 35 | } 36 | -------------------------------------------------------------------------------- /components/navigation/drawer.css: -------------------------------------------------------------------------------- 1 | .drawer-toggle { 2 | @apply absolute h-0 w-0 appearance-none opacity-0; 3 | } 4 | 5 | html:has(.drawer-toggle:checked) { 6 | @apply overflow-hidden; 7 | } 8 | 9 | .drawer { 10 | @apply bg-gray-1 fixed top-0 left-0 z-[9999] h-screen w-full max-w-xs -translate-x-full overflow-auto transition-transform duration-150 ease-out; 11 | } 12 | 13 | .drawer-right { 14 | @apply right-0 left-auto translate-x-full; 15 | } 16 | 17 | .drawer-top { 18 | transform: translateY(-100%); 19 | @apply top-0 bottom-0 h-fit max-h-screen w-full max-w-full; 20 | } 21 | 22 | .drawer-bottom { 23 | transform: translateY(100%); 24 | @apply top-auto bottom-0 h-fit max-h-screen w-full max-w-full; 25 | } 26 | 27 | .drawer-content { 28 | @apply p-4; 29 | } 30 | 31 | .drawer-toggle:checked ~ .drawer { 32 | transform: translateX(0); 33 | } 34 | 35 | .overlay { 36 | transition: visibility 0.15s ease-out, opacity 0.15s ease-out; 37 | @apply invisible fixed top-0 left-0 z-[9998] h-screen w-full bg-black/60 opacity-0; 38 | } 39 | 40 | .drawer-toggle:checked ~ .overlay { 41 | @apply visible opacity-100; 42 | } 43 | -------------------------------------------------------------------------------- /components/navigation/link.css: -------------------------------------------------------------------------------- 1 | .link { 2 | transition-property: color, background-color, transform, underline; 3 | @apply inline-flex cursor-pointer items-center text-base text-content1 duration-150 hover:text-content2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-6; 4 | } 5 | 6 | .link-primary { 7 | @apply text-primary hover:text-primary/75 focus-visible:outline-primary; 8 | } 9 | 10 | .link-secondary { 11 | @apply text-secondary hover:text-secondary/75 focus-visible:outline-secondary; 12 | } 13 | 14 | .link-success { 15 | @apply text-success hover:text-success/75 focus-visible:outline-success; 16 | } 17 | 18 | .link-error { 19 | @apply text-error hover:text-error/75 focus-visible:outline-error; 20 | } 21 | 22 | .link-warning { 23 | @apply text-warning hover:text-warning/75 focus-visible:outline-warning; 24 | } 25 | 26 | .link-info { 27 | @apply text-info hover:text-info/75 focus-visible:outline-info; 28 | } 29 | 30 | .link-underline { 31 | @apply underline; 32 | } 33 | 34 | .link-underline-hover { 35 | @apply hover:underline; 36 | } 37 | 38 | .link-ghost { 39 | @apply rounded-2xl px-2 py-1 hover:bg-gray-4 hover:text-content1; 40 | } 41 | 42 | .link-ghost-primary { 43 | @apply rounded-2xl px-2 py-1 hover:bg-primary/10 hover:text-primary; 44 | } 45 | 46 | .link-ghost-secondary { 47 | @apply rounded-2xl px-2 py-1 hover:bg-secondary/10 hover:text-secondary; 48 | } 49 | 50 | .link-ghost-success { 51 | @apply rounded-2xl px-2 py-1 hover:bg-success/10 hover:text-success; 52 | } 53 | 54 | .link-ghost-error { 55 | @apply rounded-2xl px-2 py-1 hover:bg-error/10 hover:text-error; 56 | } 57 | 58 | .link-ghost-warning { 59 | @apply rounded-2xl px-2 py-1 hover:bg-warning/10 hover:text-warning; 60 | } 61 | 62 | .link-ghost-info { 63 | @apply hover:bg-info/10 hover:text-info rounded-2xl px-2 py-1; 64 | } 65 | -------------------------------------------------------------------------------- /components/navigation/navbar.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | @apply bg-gray-1 flex w-full items-center px-2 py-2.5 shadow-xl sm:px-4; 3 | } 4 | .navbar-bordered { 5 | @apply border-gray-6 border-b; 6 | } 7 | 8 | .navbar-sticky { 9 | @apply fixed top-0 left-0 right-0 z-50; 10 | } 11 | 12 | .navbar-floating { 13 | @apply fixed top-0 left-0 right-0 z-50 mx-auto mt-5 max-w-7xl rounded-xl; 14 | } 15 | 16 | .navbar-floating.navbar-bordered { 17 | @apply border; 18 | } 19 | 20 | .navbar-glass { 21 | @apply bg-gray-1/70 backdrop-blur-[8px] backdrop-saturate-[50%]; 22 | } 23 | 24 | .navbar-rounded { 25 | @apply rounded-b-xl; 26 | } 27 | 28 | .navbar-no-boxShadow { 29 | @apply shadow-none; 30 | } 31 | 32 | .navbar-start { 33 | @apply flex w-full items-center justify-start gap-1; 34 | } 35 | 36 | .navbar-center { 37 | @apply flex w-full items-center justify-center gap-1; 38 | } 39 | 40 | .navbar-end { 41 | @apply flex w-full items-center justify-end gap-1; 42 | } 43 | 44 | .navbar-brand { 45 | @apply flex items-center gap-1 whitespace-nowrap; 46 | } 47 | 48 | .navbar-item { 49 | @apply cursor-pointer rounded-lg py-2 px-3 text-content1 transition-colors; 50 | } 51 | 52 | .navbar-item:not(.navbar-active):hover { 53 | @apply text-content2; 54 | } 55 | 56 | .navbar-active { 57 | @apply text-primary; 58 | } 59 | 60 | .navbar:not(:has(.navbar-end)) .navbar-center { 61 | @apply items-start justify-start; 62 | } 63 | 64 | .navbar:not(:has(.navbar-start)) .navbar-center { 65 | @apply items-center justify-center; 66 | } 67 | 68 | .navbar:not(:has(.navbar-start)) .navbar-center { 69 | @apply items-end justify-end; 70 | } 71 | 72 | .navbar:not(:has(.navbar-start, .navbar-end)) .navbar-center { 73 | @apply items-center justify-center; 74 | } 75 | -------------------------------------------------------------------------------- /components/styles.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | @import "./base.css"; 4 | @import "./components.css"; 5 | @import "./utilities.css"; 6 | 7 | -------------------------------------------------------------------------------- /components/utilities.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/utilities"; 2 | -------------------------------------------------------------------------------- /components/utilities/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | corePlugins: { 4 | preflight: false, 5 | }, 6 | content: [], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | }; 12 | -------------------------------------------------------------------------------- /components/utilities/utilities.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss/utilities"; 2 | 3 | .hide-scrollbar::-webkit-scrollbar { 4 | display: none; 5 | } 6 | -------------------------------------------------------------------------------- /config/colors/background.ts: -------------------------------------------------------------------------------- 1 | import { BackgroundTheme } from "../types/theme.types"; 2 | 3 | export const background: BackgroundTheme = { 4 | backgroundPrimary: "252 252 252", 5 | backgroundSecondary: "248 248 248", 6 | border: "226 226 226", 7 | }; 8 | 9 | export const backgroundDark: BackgroundTheme = { 10 | backgroundPrimary: "22 22 22", 11 | backgroundSecondary: "28 28 28", 12 | border: "52 52 52", 13 | }; 14 | -------------------------------------------------------------------------------- /config/colors/base-colors.ts: -------------------------------------------------------------------------------- 1 | import { BaseTheme } from "../types/theme.types"; 2 | 3 | export const baseColors: BaseTheme = { 4 | neutral: "105 113 119", 5 | primary: "0 114 245", 6 | secondary: "151 80 221", 7 | success: "23 201 100", 8 | error: "243 18 96", 9 | warning: "255 184 0", 10 | info: "3 183 219", 11 | }; 12 | 13 | export const baseColorsDark: BaseTheme = { 14 | neutral: "105 113 119", 15 | primary: "0 114 245", 16 | secondary: "151 80 221", 17 | success: "23 201 100", 18 | error: "243 18 96", 19 | warning: "255 184 0", 20 | info: "3 183 219", 21 | }; 22 | -------------------------------------------------------------------------------- /config/colors/blue.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | import { hexToRGB } from "../utils/hexToRGB"; 3 | 4 | export const blue: ColorsTheme<"blue"> = { 5 | "blue-1": "251 253 255", 6 | "blue-2": "245 250 255", 7 | "blue-3": "237 246 255", 8 | "blue-4": "225 240 255", 9 | "blue-5": "206 231 254", 10 | "blue-6": "183 217 248", 11 | "blue-7": "150 199 242", 12 | "blue-8": "94 176 239", 13 | "blue-9": "0 145 255", 14 | "blue-10": "0 129 241", 15 | "blue-11": "0 106 220", 16 | "blue-12": "0 37 77", 17 | }; 18 | 19 | export const blueDark: ColorsTheme<"blue"> = { 20 | "blue-1": "15 23 32", 21 | "blue-2": "15 27 45", 22 | "blue-3": "16 36 62", 23 | "blue-4": "16 42 76", 24 | "blue-5": "15 48 88", 25 | "blue-6": "13 56 104", 26 | "blue-7": "10 68 129", 27 | "blue-8": "9 84 165", 28 | "blue-9": "0 145 255", 29 | "blue-10": "54 158 255", 30 | "blue-11": "82 169 255", 31 | "blue-12": "234 246 255", 32 | }; 33 | -------------------------------------------------------------------------------- /config/colors/cyan.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const cyan: ColorsTheme<"cyan"> = { 4 | "cyan-1": "250 253 254", 5 | "cyan-2": "242 252 253", 6 | "cyan-3": "231 249 251", 7 | "cyan-4": "216 243 246", 8 | "cyan-5": "196 234 239", 9 | "cyan-6": "170 222 230", 10 | "cyan-7": "132 205 218", 11 | "cyan-8": "61 185 207", 12 | "cyan-9": "5 162 194", 13 | "cyan-10": "8 148 179", 14 | "cyan-11": "12 119 146", 15 | "cyan-12": "4 49 60", 16 | }; 17 | 18 | export const cyanDark: ColorsTheme<"cyan"> = { 19 | "cyan-1": "7 25 29", 20 | "cyan-2": "6 30 36", 21 | "cyan-3": "7 40 48", 22 | "cyan-4": "7 48 59", 23 | "cyan-5": "7 56 68", 24 | "cyan-6": "6 65 80", 25 | "cyan-7": "4 80 99", 26 | "cyan-8": "0 100 125", 27 | "cyan-9": "5 162 194", 28 | "cyan-10": "0 177 204", 29 | "cyan-11": "0 194 215", 30 | "cyan-12": "225 248 250", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/default-schema.ts: -------------------------------------------------------------------------------- 1 | import { DefaultSchemaColors } from "../types/theme.types"; 2 | 3 | export const defaultSchema: DefaultSchemaColors = { 4 | "background-color": "rgb(var(--backgroundPrimary) / var(--tw-bg-opacity, 1))", 5 | color: "rgb(var(--content1) / var(--tw-text-opacity, 1))", 6 | }; 7 | -------------------------------------------------------------------------------- /config/colors/gray.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const gray: ColorsTheme<"gray"> = { 4 | "gray-1": "252 252 252", 5 | "gray-2": "248 248 248", 6 | "gray-3": "243 243 243", 7 | "gray-4": "237 237 237", 8 | "gray-5": "232 232 232", 9 | "gray-6": "226 226 226", 10 | "gray-7": "219 219 219", 11 | "gray-8": "199 199 199", 12 | "gray-9": "143 143 143", 13 | "gray-10": "133 133 133", 14 | "gray-11": "111 111 111", 15 | "gray-12": "23 23 23", 16 | }; 17 | 18 | export const grayDark: ColorsTheme<"gray"> = { 19 | "gray-1": "22 22 22", 20 | "gray-2": "28 28 28", 21 | "gray-3": "35 35 35", 22 | "gray-4": "40 40 40", 23 | "gray-5": "46 46 46", 24 | "gray-6": "52 52 52", 25 | "gray-7": "62 62 62", 26 | "gray-8": "80 80 80", 27 | "gray-9": "112 112 112", 28 | "gray-10": "126 126 126", 29 | "gray-11": "160 160 160", 30 | "gray-12": "237 237 237", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/green.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const green: ColorsTheme<"green"> = { 4 | "green-1": "251 254 252", 5 | "green-2": "242 252 245", 6 | "green-3": "233 249 238", 7 | "green-4": "221 243 228", 8 | "green-5": "204 235 215", 9 | "green-6": "180 223 196", 10 | "green-7": "146 206 172", 11 | "green-8": "91 185 140", 12 | "green-9": "48 164 108", 13 | "green-10": "41 151 100", 14 | "green-11": "24 121 78", 15 | "green-12": "21 50 38", 16 | }; 17 | 18 | export const greenDark: ColorsTheme<"green"> = { 19 | "green-1": "13 25 18", 20 | "green-2": "12 31 23", 21 | "green-3": "15 41 30", 22 | "green-4": "17 49 35", 23 | "green-5": "19 57 41", 24 | "green-6": "22 68 48", 25 | "green-7": "27 84 58", 26 | "green-8": "35 110 74", 27 | "green-9": "48 164 108", 28 | "green-10": "60 177 121", 29 | "green-11": "76 195 138", 30 | "green-12": "229 251 235", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./blue"; 2 | export * from "./purple"; 3 | export * from "./green"; 4 | export * from "./yellow"; 5 | export * from "./red"; 6 | export * from "./cyan"; 7 | export * from "./pink"; 8 | export * from "./gray"; 9 | export * from './background'; 10 | export * from './base-colors'; 11 | export * from './text'; -------------------------------------------------------------------------------- /config/colors/pink.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const pink: ColorsTheme<"pink"> = { 4 | "pink-1": "255 252 254", 5 | "pink-2": "255 247 252", 6 | "pink-3": "254 238 248", 7 | "pink-4": "252 229 243", 8 | "pink-5": "249 216 236", 9 | "pink-6": "243 198 226", 10 | "pink-7": "236 173 212", 11 | "pink-8": "227 142 195", 12 | "pink-9": "214 64 159", 13 | "pink-10":"210 49 151", 14 | "pink-11": "205 29 141", 15 | "pink-12": "59 10 42", 16 | }; 17 | 18 | export const pinkDark: ColorsTheme<"pink"> = { 19 | "pink-1": "31 18 27", 20 | "pink-2": "39 20 33", 21 | "pink-3": "58 24 47", 22 | "pink-4": "69 26 55", 23 | "pink-5": "80 27 63", 24 | "pink-6": "96 29 72", 25 | "pink-7": "122 29 90", 26 | "pink-8": "167 24 115", 27 | "pink-9": "214 64 159", 28 | "pink-10":"227 75 169", 29 | "pink-11": "246 92 182", 30 | "pink-12": "254 235 247", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/purple.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const purple: ColorsTheme<"purple"> = { 4 | "purple-1": "254 252 254", 5 | "purple-2": "253 250 255", 6 | "purple-3": "249 241 254", 7 | "purple-4": "243 231 252", 8 | "purple-5": "237 219 249", 9 | "purple-6": "227 204 244", 10 | "purple-7": "211 180 237", 11 | "purple-8": "190 147 228", 12 | "purple-9": "142 78 198", 13 | "purple-10": "132 69 188", 14 | "purple-11": "121 58 175", 15 | "purple-12": "43 14 68", 16 | }; 17 | 18 | export const purpleDark: ColorsTheme<"purple"> = { 19 | "purple-1": "27 20 29", 20 | "purple-2": "34 21 39", 21 | "purple-3": "48 26 58", 22 | "purple-4": "58 30 72", 23 | "purple-5": "67 33 85", 24 | "purple-6": "78 38 103", 25 | "purple-7": "95 45 132", 26 | "purple-8": "121 56 178", 27 | "purple-9": "142 78 198", 28 | "purple-10": "157 91 210", 29 | "purple-11": "191 122 240", 30 | "purple-12": "247 236 252", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/red.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const red: ColorsTheme<"red"> = { 4 | "red-1": "255 252 252", 5 | "red-2": "255 248 248", 6 | "red-3": "255 239 239", 7 | "red-4": "255 229 229", 8 | "red-5": "253 216 216", 9 | "red-6": "249 198 198", 10 | "red-7": "243 174 175", 11 | "red-8": "235 144 145", 12 | "red-9": "229 72 77", 13 | "red-10": "220 61 67", 14 | "red-11": "205 43 49", 15 | "red-12": "56 19 22", 16 | }; 17 | 18 | export const redDark: ColorsTheme<"red"> = { 19 | "red-1": "31 19 21", 20 | "red-2": "41 20 21", 21 | "red-3": "60 24 26", 22 | "red-4": "72 26 29", 23 | "red-5": "84 27 31", 24 | "red-6": "103 30 34", 25 | "red-7": "130 32 37", 26 | "red-8": "170 36 41", 27 | "red-9": "229 72 77", 28 | "red-10": "242 85 90", 29 | "red-11": "255 99 105", 30 | "red-12": "254 236 238", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/slate.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const slate: ColorsTheme<"slate"> = { 4 | "slate-1": "251 252 253", 5 | "slate-2": "248 249 250", 6 | "slate-3": "241 243 245", 7 | "slate-4": "236 238 240", 8 | "slate-5": "230 232 235", 9 | "slate-6": "223 227 230", 10 | "slate-7": "215 219 223", 11 | "slate-8": "193 200 205", 12 | "slate-9": "136 144 150", 13 | "slate-10": "126 134 140", 14 | "slate-11": "104 112 118", 15 | "slate-12": "17 24 28", 16 | }; 17 | 18 | export const slateDark: ColorsTheme<"slate"> = { 19 | "slate-1": "21 23 24", 20 | "slate-2": "26 29 30", 21 | "slate-3": "32 36 37", 22 | "slate-4": "38 41 43", 23 | "slate-5": "43 47 49", 24 | "slate-6": "49 53 56", 25 | "slate-7": "58 63 66", 26 | "slate-8": "76 81 85", 27 | "slate-9": "105 113 119", 28 | "slate-10": "120 127 133", 29 | "slate-11": "155 161 166", 30 | "slate-12": "236 237 238", 31 | }; 32 | -------------------------------------------------------------------------------- /config/colors/text.ts: -------------------------------------------------------------------------------- 1 | import { TextTheme } from "../types/theme.types"; 2 | 3 | export const text: TextTheme = { 4 | content1: "28 28 28", 5 | content2: "88 87 87", 6 | content3: "150 150 150", 7 | whiteInverted: "0 0 0", 8 | blackInverted: "255 255 255", 9 | }; 10 | 11 | export const textDark: TextTheme = { 12 | content1: "232 232 232", 13 | content2: "186 186 186", 14 | content3: "118 118 118", 15 | whiteInverted: "255 255 255", 16 | blackInverted: "0 0 0", 17 | }; 18 | -------------------------------------------------------------------------------- /config/colors/yellow.ts: -------------------------------------------------------------------------------- 1 | import { ColorsTheme } from "../types/theme.types"; 2 | 3 | export const yellow: ColorsTheme<"yellow"> = { 4 | "yellow-1": "253 253 249", 5 | "yellow-2": "255 252 232", 6 | "yellow-3": "255 251 209", 7 | "yellow-4": "255 248 187", 8 | "yellow-5": "254 242 164", 9 | "yellow-6": "249 230 140", 10 | "yellow-7": "239 211 108", 11 | "yellow-8": "235 188 0", 12 | "yellow-9": "245 217 10", 13 | "yellow-10": "247 206 0", 14 | "yellow-11": "148 104 0", 15 | "yellow-12": "53 41 15", 16 | }; 17 | 18 | export const yellowDark: ColorsTheme<"yellow"> = { 19 | "yellow-1": "28 21 0", 20 | "yellow-2": "34 26 0", 21 | "yellow-3": "44 33 0", 22 | "yellow-4": "53 40 0", 23 | "yellow-5": "62 48 0", 24 | "yellow-6": "73 60 0", 25 | "yellow-7": "89 74 5", 26 | "yellow-8": "112 94 0", 27 | "yellow-9": "245 217 10", 28 | "yellow-10": "255 239 92", 29 | "yellow-11": "240 192 0", 30 | "yellow-12": "255 250 209", 31 | }; 32 | -------------------------------------------------------------------------------- /config/prefix/prefix.ts: -------------------------------------------------------------------------------- 1 | import postcss, { Declaration, Root, Rule } from "postcss"; 2 | import selectorParser from "postcss-selector-parser"; 3 | 4 | interface CssInJs { 5 | [key: string]: { 6 | [key: string]: string; 7 | }; 8 | } 9 | 10 | const addPrefix = (prefix: string) => { 11 | return (css: Root) => { 12 | css.walkRules((rule: Rule) => { 13 | rule.selector = selectorParser((selectors: selectorParser.Root) => { 14 | selectors.walkClasses((classNode: selectorParser.ClassName) => { 15 | classNode.value = prefix + classNode.value; 16 | }); 17 | }).processSync(rule.selector); 18 | }); 19 | }; 20 | }; 21 | 22 | export const getSelectorsWithPrefix = ( 23 | prefix: string, 24 | cssInJs: CssInJs 25 | ): CssInJs => { 26 | const prefixNoWhiteSpace = prefix.replace(/\s/g, ""); 27 | let cssCode = ""; 28 | for (let key in cssInJs) { 29 | cssCode += `${key}{`; 30 | for (let prop in cssInJs[key]) { 31 | cssCode += `${prop}:${cssInJs[key][prop]};`; 32 | } 33 | cssCode += `}`; 34 | } 35 | const prefixedCSS = postcss([addPrefix(prefixNoWhiteSpace)]).process( 36 | cssCode, 37 | { 38 | from: undefined, 39 | } 40 | ); 41 | const prefixedCSSObject: CssInJs = {}; 42 | prefixedCSS.root.walkRules((rule: Rule) => { 43 | const selector = rule.selector; 44 | let obj: { [key: string]: string } = {}; 45 | rule.walkDecls((decl: Declaration) => { 46 | obj[decl.prop] = decl.value; 47 | }); 48 | prefixedCSSObject[selector] = obj; 49 | }); 50 | return prefixedCSSObject; 51 | }; 52 | -------------------------------------------------------------------------------- /config/theme/dark-theme.ts: -------------------------------------------------------------------------------- 1 | import { addPrefix } from "../utils/prefix"; 2 | import { 3 | blueDark, 4 | greenDark, 5 | purpleDark, 6 | yellowDark, 7 | redDark, 8 | cyanDark, 9 | pinkDark, 10 | grayDark, 11 | backgroundDark, 12 | textDark, 13 | baseColorsDark, 14 | } from "../colors"; 15 | import { PalleteTheme, Theme } from "../types/theme.types"; 16 | import { slateDark } from "../colors/slate"; 17 | 18 | const pallete: PalleteTheme = { 19 | ...blueDark, 20 | ...greenDark, 21 | ...purpleDark, 22 | ...yellowDark, 23 | ...redDark, 24 | ...cyanDark, 25 | ...pinkDark, 26 | ...grayDark, 27 | ...slateDark, 28 | }; 29 | 30 | const colors = { 31 | ...backgroundDark, 32 | ...textDark, 33 | ...baseColorsDark, 34 | ...pallete, 35 | }; 36 | 37 | export const darkTheme: Theme = { 38 | themeName: "dark", 39 | colorScheme: "dark", 40 | prefersColorScheme: true, 41 | colors: { 42 | ...addPrefix({ ...colors }), 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /config/theme/ligh-theme.ts: -------------------------------------------------------------------------------- 1 | import { 2 | blue, 3 | cyan, 4 | gray, 5 | green, 6 | pink, 7 | purple, 8 | red, 9 | yellow, 10 | background, 11 | baseColors, 12 | text, 13 | } from "../colors"; 14 | import { slate } from "../colors/slate"; 15 | import { PalleteTheme, Theme } from "../types/theme.types"; 16 | import { addPrefix } from "../utils/prefix"; 17 | 18 | const pallete: PalleteTheme = { 19 | ...blue, 20 | ...purple, 21 | ...green, 22 | ...yellow, 23 | ...red, 24 | ...cyan, 25 | ...pink, 26 | ...gray, 27 | ...slate, 28 | }; 29 | 30 | const colors = { 31 | ...background, 32 | ...text, 33 | ...baseColors, 34 | ...pallete, 35 | }; 36 | 37 | export const lightTheme: Theme = { 38 | themeName: "light", 39 | colorScheme: "light", 40 | prefersColorScheme: false, 41 | colors: { 42 | ...addPrefix({ ...colors }), 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /config/types/config.types.ts: -------------------------------------------------------------------------------- 1 | import { Theme } from "./theme.types"; 2 | 3 | type MakeOptional = Omit & 4 | Partial>; 5 | 6 | type ThemeExtended = MakeOptional; 7 | 8 | /** 9 | * The @{config} object. 10 | * @typedef {Type} ConfigTheme 11 | * @property {boolean} [defaultStyle] - Will apply by default bg-color and color to the root element. 12 | * @property {string} [prefix] - Will add a prefix to all the variables. 13 | * @property {string[]} [removeThemes] - The list of themes to remove. 14 | * @property {ThemeExtended[]} [themes] - The list of themes to modify, add or remove, you can also add new variables in each theme. 15 | */ 16 | type ConfigTheme = { 17 | /** 18 | * Will apply by default bg-color and color to the root element `(default: true)` 19 | */ 20 | defaultStyle?: boolean; 21 | /** 22 | * Will add a prefix to all the variables `(default: "")` 23 | */ 24 | prefix?: string; 25 | /** 26 | * The list of themes to remove `(default: [])` 27 | */ 28 | removeThemes?: string[]; 29 | /** 30 | * The list of themes to modify, add you can also add new variables in each theme. 31 | */ 32 | themes?: ThemeExtended[]; 33 | }; 34 | 35 | export type Config = ConfigTheme; 36 | -------------------------------------------------------------------------------- /config/types/theme.types.ts: -------------------------------------------------------------------------------- 1 | import { PalleteVariablesScale } from "./variables.types"; 2 | 3 | export type ColorScale = 4 | | "blue" 5 | | "green" 6 | | "yellow" 7 | | "red" 8 | | "cyan" 9 | | "pink" 10 | | "purple" 11 | | "gray" 12 | | "slate"; 13 | 14 | export type PalleteScale = 15 | | "1" 16 | | "2" 17 | | "3" 18 | | "4" 19 | | "5" 20 | | "6" 21 | | "7" 22 | | "8" 23 | | "9" 24 | | "10" 25 | | "11" 26 | | "12"; 27 | 28 | export type BaseScale = 29 | | "primary" 30 | | "secondary" 31 | | "success" 32 | | "error" 33 | | "warning" 34 | | "neutral" 35 | | "info"; 36 | 37 | export type BackgroundScale = 38 | | "backgroundPrimary" 39 | | "backgroundSecondary" 40 | | "border"; 41 | 42 | export type TextScale = 43 | | "content1" 44 | | "content2" 45 | | "content3" 46 | | "whiteInverted" 47 | | "blackInverted"; 48 | 49 | export type DefaultSchemaColors = { 50 | [key in DefaultSchema]: string; 51 | }; 52 | 53 | export type ColorScheme = "light" | "dark"; 54 | 55 | export type DefaultSchema = "background-color" | "color"; 56 | 57 | export type ColorsTheme = { 58 | [key in PalleteVariablesScale]: string; 59 | }; 60 | // We map all the colors combinations 61 | export type PalleteMap = `${ColorScale}-${PalleteScale}`; 62 | 63 | export type PalleteTheme = { 64 | [key in PalleteMap]: string; 65 | }; 66 | 67 | export type BackgroundTheme = { 68 | [key in BackgroundScale]: string; 69 | }; 70 | 71 | export type BaseTheme = { 72 | [key in BaseScale]: string; 73 | }; 74 | 75 | export type TextTheme = { 76 | [key in TextScale]: string; 77 | }; 78 | 79 | export type ColorsMap = PalleteTheme & BackgroundTheme & BaseTheme & TextTheme; 80 | 81 | export type Theme = { 82 | themeName: string; 83 | colorScheme: ColorScheme; 84 | prefersColorScheme: boolean; 85 | colors: ColorsMap; 86 | }; 87 | 88 | export type OptionalTheme = RecursivePartial; 89 | 90 | export type RecursivePartial = { 91 | [P in keyof T]?: RecursivePartial; 92 | }; 93 | -------------------------------------------------------------------------------- /config/types/variables.types.ts: -------------------------------------------------------------------------------- 1 | import { applyOpacityValue } from "../utils/applyOpacityValue"; 2 | import { 3 | BackgroundScale, 4 | BaseScale, 5 | ColorScale, 6 | PalleteScale, 7 | TextScale, 8 | } from "./theme.types"; 9 | 10 | type OpacityFunc = ReturnType; 11 | 12 | export type PalleteVariablesScale = 13 | `${T}-${PalleteScale}`; 14 | 15 | export type ColorsVariables = { 16 | [key in PalleteVariablesScale]: OpacityFunc; 17 | }; 18 | 19 | export type BackgroundVariables = { 20 | [key in BackgroundScale]: OpacityFunc; 21 | }; 22 | 23 | export type TextVariables = { 24 | [key in TextScale]: OpacityFunc; 25 | }; 26 | 27 | export type BaseColorsVariable = { 28 | [key in BaseScale]: OpacityFunc; 29 | }; 30 | 31 | export type PalleteVariablesMap = `${ColorScale}-${PalleteScale}`; 32 | 33 | export type PalleteVariables = { 34 | [key in PalleteVariablesMap]: OpacityFunc; 35 | }; 36 | 37 | export type ColorsVariableMap = BackgroundVariables & 38 | TextVariables & 39 | BaseColorsVariable & 40 | PalleteVariables; 41 | 42 | export type ThemeVariables = { 43 | colors: ColorsVariableMap; 44 | }; 45 | -------------------------------------------------------------------------------- /config/utils/applyOpacityValue.ts: -------------------------------------------------------------------------------- 1 | export const applyOpacityValue = (variable: string) => { 2 | return ({ opacityValue }: { opacityValue?: number }) => { 3 | if (opacityValue === undefined) { 4 | return `rgb(var(${variable}))`; 5 | } 6 | return `rgb(var(${variable}) / ${opacityValue})`; 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /config/utils/extractNewVariables.ts: -------------------------------------------------------------------------------- 1 | import { ColorsVariableMap } from "../types/variables.types"; 2 | import { applyOpacityValue } from "./applyOpacityValue"; 3 | 4 | export const extractNewVariables = ( 5 | obj1: T, 6 | obj2: U 7 | ): Record => { 8 | const keys1 = Object.keys(obj1); 9 | 10 | return Object.keys(obj2) 11 | .filter((key) => !keys1.includes(key)) 12 | .reduce((acc, key) => { 13 | acc[key as keyof ColorsVariableMap] = applyOpacityValue(`--${key}`) as T; 14 | return acc; 15 | }, {} as Record); 16 | }; 17 | -------------------------------------------------------------------------------- /config/utils/hexToRGB.ts: -------------------------------------------------------------------------------- 1 | import { ColorsMap, RecursivePartial } from "../types/theme.types"; 2 | 3 | type Result = `${number} ${number} ${number}`; 4 | 5 | export const hexToRGB = (hex: string): Result => { 6 | // Parse the hexadecimal string to get the red, green, and blue values 7 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 8 | 9 | // Return an object with the red, green, and blue values if the hexadecimal string is valid 10 | if (result) { 11 | const red = parseInt(result[1], 16); 12 | const green = parseInt(result[2], 16); 13 | const blue = parseInt(result[3], 16); 14 | return `${red} ${green} ${blue}`; 15 | } 16 | throw new Error("Invalid hexadecimal string"); 17 | // Return null if the hexadecimal string is invalid 18 | }; 19 | 20 | export const palleteToRGB = >( 21 | pallete: T = {} as T 22 | ): T => { 23 | const transformedPallete: T = {} as T; 24 | Object.keys(pallete).map((key) => { 25 | transformedPallete[key as Extract] = hexToRGB( 26 | pallete[key as Extract] as string 27 | ) as T[Extract]; 28 | }); 29 | return transformedPallete; 30 | }; 31 | -------------------------------------------------------------------------------- /config/utils/isEmpty.ts: -------------------------------------------------------------------------------- 1 | export const isEmpty = (obj: any) => { 2 | return Object.keys(obj).length === 0; 3 | }; 4 | 5 | export const isValid = (obj: object) => { 6 | return obj && !isEmpty(obj); 7 | }; 8 | -------------------------------------------------------------------------------- /config/utils/prefix.ts: -------------------------------------------------------------------------------- 1 | import { ColorsMap, RecursivePartial } from "../types/theme.types"; 2 | 3 | export const addPrefix = >( 4 | obj: T = {} as T 5 | ): T => { 6 | let transformedObj: T = {} as T; 7 | Object.keys(obj).map((key) => { 8 | const newKey = `--${key}` as keyof T; 9 | transformedObj[newKey] = obj[key as keyof T]; 10 | }); 11 | return transformedObj; 12 | }; 13 | -------------------------------------------------------------------------------- /config/utils/safeList.ts: -------------------------------------------------------------------------------- 1 | import { SafelistConfig } from "tailwindcss/types/config"; 2 | 3 | export const safeList: Partial = [ 4 | { 5 | pattern: 6 | /^(bg|to|via|from|text|fill|stroke|border|outline)-((primary|secondary|warning|error|success|content1|content2|content3|backgroundPrimary|backgroundSecondary|border|black|white|whiteInverted|blackInverted)|((blue|red|green|purple|pink|gray|cyan|slate)-(1|2|3|4|5|6|7|8|9|10)\D))/, 7 | variants: [ 8 | // "first", 9 | // "last", 10 | // "odd", 11 | // "even", 12 | // "visited", 13 | // "checked", 14 | // "empty", 15 | // "read-only", 16 | // "group-hover", 17 | // "group-focus", 18 | // "focus-within", 19 | "hover", 20 | "focus", 21 | // "focus-visible", 22 | // "active", 23 | // "disabled", 24 | ], 25 | }, 26 | ]; 27 | -------------------------------------------------------------------------------- /config/utils/sortThemes.ts: -------------------------------------------------------------------------------- 1 | const extractMediaQueries = ( 2 | array: T[] 3 | ): T[] => { 4 | let mediaQueries: T[] = []; 5 | 6 | array.forEach((obj) => { 7 | Object.entries(obj).forEach(([key, value]) => { 8 | if (key.startsWith("@media")) { 9 | mediaQueries.push({ [key]: value } as T); 10 | } 11 | }); 12 | }); 13 | 14 | return mediaQueries; 15 | }; 16 | 17 | const extractRootElement = (array: T[]) => { 18 | const root = array.filter((obj) => obj[":root"] !== undefined)[0]; 19 | if (!root) return; 20 | 21 | return { 22 | ":root": root[":root"], 23 | }; 24 | }; 25 | 26 | const extractDataThemes = (array: T[]) => { 27 | let dataTheme: T[] = []; 28 | 29 | array.forEach((obj) => { 30 | Object.entries(obj).forEach(([key, value]) => { 31 | if (key.match(/\[data-theme=\w+\]/)) { 32 | dataTheme.push({ [key]: value } as T); 33 | } 34 | }); 35 | }); 36 | return dataTheme; 37 | }; 38 | 39 | export const sortThemes = (array: T[]) => { 40 | const root = extractRootElement(array); 41 | const media = extractMediaQueries(array); 42 | const dataTheme = extractDataThemes(array); 43 | if (!root) return [...media, ...dataTheme]; 44 | return [root, ...media, ...dataTheme]; 45 | }; 46 | -------------------------------------------------------------------------------- /docs/.env.local: -------------------------------------------------------------------------------- 1 | SITE_URL=https://www.ripple-ui.com 2 | NEXT_PUBLIC_DOCSEARCH_APP_ID=7MT5F598T9 3 | NEXT_PUBLIC_DOCSEARCH_API_KEY=ff0f013d95467aac5896f71d8372c3fe 4 | NEXT_PUBLIC_DOCSEARCH_INDEX_NAME=ripple-ui -------------------------------------------------------------------------------- /docs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /docs/.prettierignore: -------------------------------------------------------------------------------- 1 | content -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # RippleUI Documentation 2 | 3 | RippleUI uses [Next.js](https://nextjs.org/) for its documentation. Here is how you can run the project locally: 4 | 5 | 1. Clone this repo 6 | 7 | ```sh 8 | git clone https://github.com/Siumauricio/rippleui/tree/main/docs 9 | ``` 10 | 11 | 2. Go into the project root directory 12 | 13 | ```sh 14 | cd docs 15 | ``` 16 | 17 | 3. Install JS dependencies 18 | 19 | ```sh 20 | npm install 21 | ``` 22 | 23 | 4. Start the dev server 24 | 25 | ```sh 26 | npm run dev 27 | ``` -------------------------------------------------------------------------------- /docs/components/icons/ArrowRight.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const ArrowRight = () => { 4 | return ( 5 | 11 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /docs/components/icons/Book.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const BookIcon = () => { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/components/icons/BookIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const BookIcon = () => { 4 | return ( 5 | 6 | 12 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /docs/components/icons/ChangelogIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const ChangelogIcon = () => { 4 | return ( 5 | 11 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/components/icons/ChevronLeft.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const ArrowLeft = () => { 4 | return ( 5 | 12 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /docs/components/icons/ChevronRight.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const ChevronRight = () => { 4 | return ( 5 | 12 | 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /docs/components/icons/ComponentsIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const ComponentsIcon = () => { 4 | return ( 5 | 11 | 15 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /docs/components/icons/CopyIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const CopyIcon = () => { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/components/icons/DiscordIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const DiscordIcon = ({ className = "fill-content3" }: Props) => { 8 | return ( 9 | 16 | 20 | 24 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /docs/components/icons/GithubIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const GithubIcon = ({ className = "fill-content3" }: Props) => { 8 | return ( 9 | 16 | 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /docs/components/icons/MenuIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const MenuIcon = () => { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/components/icons/Recyle.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const RecyleIcon = () => { 4 | return ( 5 | 12 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /docs/components/icons/SearchIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const SearchIcon = ({ className }: Props) => { 8 | return ( 9 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /docs/components/icons/TwitterIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface Props { 4 | className?: string; 5 | } 6 | 7 | export const TwitterIcon = ({ className = "fill-content3" }: Props) => { 8 | return ( 9 | 16 | 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /docs/components/icons/XIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const XIcon = () => { 4 | return ( 5 | 11 | 15 | 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /docs/components/layout/DocsLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Headings } from "../../utils/getToc"; 3 | import { NavbarDocs } from "../styles/NavbarDocs"; 4 | import { SideNav } from "../styles/SideNav"; 5 | import { TableOfContents } from "../styles/TableOfContents"; 6 | 7 | interface Props { 8 | children: React.ReactNode; 9 | headings: Headings[]; 10 | } 11 | 12 | export const DocsLayout = ({ children, headings }: Props) => { 13 | return ( 14 |
15 | 16 | 17 |
18 | 19 |
20 |
21 |
22 |
23 |
{children}
24 |
25 |
26 |
27 |
28 | {headings && headings.length > 0 && ( 29 | 30 | )} 31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | ); 39 | }; 40 | -------------------------------------------------------------------------------- /docs/components/layout/MainLayout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Headings } from "../../utils/getToc"; 3 | import { TableOfContents } from "../styles/TableOfContents"; 4 | 5 | interface Props { 6 | children: React.ReactNode; 7 | headings?: Headings[]; 8 | } 9 | 10 | export const MainLayout = ({ children, headings }: Props) => { 11 | return ( 12 | <> 13 |
14 | 23 | 27 | 28 |
29 |
30 |
31 | {children} 32 |
33 | 34 | {headings && headings.length > 0 && ( 35 |
36 | 37 |
38 | )} 39 |
40 | 41 | ); 42 | }; 43 | -------------------------------------------------------------------------------- /docs/components/mdx/CDN.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { RippleUIVersion } from "../../utils/items"; 3 | import { CodeBlock } from "../playground/CodeBlock"; 4 | 5 | export const CDN = () => { 6 | return ( 7 | 8 | {` 9 | 13 | 14 | 15 | 16 | 17 | 18 | `} 19 | 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /docs/components/mdx/Code.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { CodeBlock } from "../playground/CodeBlock"; 3 | 4 | interface Props { 5 | children: React.ReactNode; 6 | className: string; 7 | } 8 | 9 | export const Code = ({ children, className, ...props }: Props) => { 10 | if (!className) 11 | return {children}; 12 | return ( 13 | 17 | {children} 18 | 19 | ); 20 | }; 21 | -------------------------------------------------------------------------------- /docs/components/mdx/Li.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | interface Props { 4 | children: React.ReactNode; 5 | } 6 | 7 | export const Li = ({ children, ...props }: Props) => { 8 | return
  • {children}
  • ; 9 | }; 10 | -------------------------------------------------------------------------------- /docs/components/mdx/Link.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import NextLink from "next/link"; 3 | import { useRouter } from "next/router"; 4 | 5 | interface Props { 6 | title?: React.ReactNode; 7 | href?: string; 8 | blank?: boolean; 9 | children?: React.ReactNode; 10 | } 11 | 12 | export const Link = ({ href = "/", blank, children }: Props) => { 13 | const isRelativeUrl = !/^([a-z0-9]*:|.{0})\/\/.*$/gim.test(href); 14 | 15 | if (isRelativeUrl) { 16 | return ( 17 | 18 | {children} 19 | 20 | ); 21 | } 22 | 23 | return ( 24 | 30 | {children} 31 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /docs/components/mdx/Paragraph.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | interface Props { 4 | children?: React.ReactNode; 5 | } 6 | 7 | export const Paragraph = ({ children }: Props) => { 8 | return

    {children}

    ; 9 | }; 10 | -------------------------------------------------------------------------------- /docs/components/mdx/attributes/attributes-table.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useLayoutEffect, useState } from "react"; 2 | 3 | interface Props { 4 | children: JSX.Element | JSX.Element[]; 5 | } 6 | 7 | const AttributesTable: React.FC = ({ children }) => { 8 | return ( 9 |
    10 | {React.Children.map(children, (child: JSX.Element) => { 11 | return ( 12 | <> 13 | {child.type == "table" ? ( 14 |
    {child}
    15 | ) : ( 16 |
    17 | {child} 18 |
    19 | )} 20 | 21 | ); 22 | })} 23 |
    24 | ); 25 | }; 26 | 27 | export default AttributesTable; 28 | -------------------------------------------------------------------------------- /docs/components/mdx/attributes/attributes-title.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Link from "next/link"; 3 | import { titleToSlug } from "../../../utils/titleToSlug"; 4 | 5 | export interface AttributesTitleProps { 6 | alias?: string; 7 | } 8 | 9 | const AttributesTitle: React.FC> = 10 | React.memo(({ children, alias }) => { 11 | const titleWithSlug = titleToSlug( 12 | children?.toString().toLowerCase() as string 13 | ); 14 | return ( 15 |
    16 |

    17 | 18 | `{children}` 19 | 20 | 24 |   25 | 26 |

    27 |
    28 | ); 29 | }); 30 | 31 | AttributesTitle.displayName = "AttributesTitle"; 32 | export default AttributesTitle; 33 | -------------------------------------------------------------------------------- /docs/components/mdx/attributes/attributes.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import AttributesTitle from "./attributes-title"; 3 | import AttributesTable from "./attributes-table"; 4 | 5 | export interface AttributesProps { 6 | children: JSX.Element | JSX.Element[]; 7 | } 8 | 9 | const Attributes: React.FC = React.memo(({ children }) => { 10 | const apiTitles = useMemo(() => { 11 | if (React.Children.count(children) === 0) return null; 12 | return {children}; 13 | }, [children]); 14 | 15 | return <>{apiTitles}; 16 | }); 17 | 18 | type AttributesComponent

    = React.FC

    & { 19 | Title: typeof AttributesTitle; 20 | Table: typeof AttributesTable; 21 | }; 22 | Attributes.displayName = "Attributes"; 23 | export default Attributes as AttributesComponent; 24 | -------------------------------------------------------------------------------- /docs/components/mdx/attributes/index.ts: -------------------------------------------------------------------------------- 1 | import Attributes from './attributes'; 2 | import AttributesTitle from './attributes-title'; 3 | import AttributesTable from './attributes-table'; 4 | 5 | Attributes.Title = AttributesTitle; 6 | Attributes.Table = AttributesTable; 7 | 8 | export default Attributes; 9 | -------------------------------------------------------------------------------- /docs/components/mdx/index.tsx: -------------------------------------------------------------------------------- 1 | import { headingDynamic } from "./Heading"; 2 | import { Code } from "./Code"; 3 | import { Paragraph } from "./Paragraph"; 4 | import { Link } from "./Link"; 5 | import { Li } from "./Li"; 6 | import Attributes from "./attributes"; 7 | import LinkRedirect from "./LinkRedirect"; 8 | import { ExamplesRepositories } from "./ExamplesRepositories"; 9 | import { Pallete } from "../styles/Pallete"; 10 | import { CDN } from "./CDN"; 11 | import { CodeBlock } from "../playground/CodeBlock"; 12 | import WindowResizer from "./Resizable"; 13 | export { default as Attributes } from "./attributes"; 14 | 15 | export const MDXcomponents = { 16 | p: Paragraph, 17 | h1: headingDynamic({ level: 1 }), 18 | h2: headingDynamic({ level: 2 }), 19 | h3: headingDynamic({ level: 3 }), 20 | h4: headingDynamic({ level: 4 }), 21 | h5: headingDynamic({ level: 5 }), 22 | WindowResizer: WindowResizer, 23 | a: Link, 24 | li: Li, 25 | pre: CodeBlock, 26 | code: Code, 27 | Attributes: Attributes, 28 | LinkRedirect: LinkRedirect, 29 | ExamplesRepositories: ExamplesRepositories, 30 | Pallete: Pallete, 31 | table: (props: any) => , 32 | CDN: CDN, 33 | }; 34 | -------------------------------------------------------------------------------- /docs/components/playground/title.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export type TitleProps = { 4 | title: React.ReactNode | string; 5 | desc?: React.ReactNode | string; 6 | }; 7 | 8 | const replaceCode = (desc: string): string => { 9 | if (!desc.includes("`")) return desc; 10 | let count = 0; 11 | return desc.replace(/`/g, () => { 12 | const val = count % 2 === 0 ? "" : ""; 13 | count++; 14 | return val; 15 | }); 16 | }; 17 | 18 | const Title: React.FC = React.memo( 19 | ({ title, desc }: TitleProps) => { 20 | const isStringDesc = typeof desc === "string"; 21 | return ( 22 | <> 23 |

    {title}

    24 | {desc && isStringDesc && ( 25 |

    29 | )} 30 | {desc && !isStringDesc &&

    {desc}

    } 31 | 32 | ); 33 | } 34 | ); 35 | 36 | Title.displayName = "PlayGroundTitle"; 37 | export default Title; 38 | -------------------------------------------------------------------------------- /docs/components/styles/TableOfContents.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import NextLink from "next/link"; 3 | import { useRouter } from "next/router"; 4 | import { Headings } from "../../utils/getToc"; 5 | import clsx from "clsx"; 6 | import { useScrollSpy } from "../../hooks/useScrollSpy"; 7 | 8 | interface Props { 9 | toc: Headings[]; 10 | } 11 | 12 | export const TableOfContents = ({ toc }: Props) => { 13 | const router = useRouter(); 14 | const isChangelog = toc[0]?.title === "Changelog"; 15 | const margin = isChangelog ? "0% 0% -80% 0%" : "0% 0% -70% 0%"; 16 | const [routerDefined, setRouterDefined] = useState(""); 17 | const activeId = useScrollSpy( 18 | toc.map(({ id }) => `[id="${id}"]`), 19 | { 20 | rootMargin: margin, 21 | } 22 | ); 23 | 24 | useEffect(() => { 25 | setRouterDefined(router.asPath); 26 | }, []); 27 | 28 | if (toc.length < 1) { 29 | return null; 30 | } 31 | 32 | return ( 33 | 63 | ); 64 | }; 65 | -------------------------------------------------------------------------------- /docs/content/get-started/installation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Install 3 | description: Learn how to add customizable UI components to your project using TailwindCSS. Follow our step-by-step guide to install RippleUI and enhance your website or application's user experience. 4 | --- 5 | import { RippleUIVersion } from "../../utils/items"; 6 | 7 | # Install RippleUI in your project 8 | 9 | How to install Ripple UI in your project 10 | 11 | ## Setup 12 | 13 | You can install RippleUI using npm, yarn or CDN. 14 | 15 | 1. To install RippleUI plugin is required to have [TailwindCSS](https://tailwindcss.com/docs/installation) installed on your machine. 16 | 17 | ```bash disableTabs={true} 18 | npm install rippleui 19 | ``` 20 | 21 | 2. Add plugin to your `tailwind.config.js` file 22 | 23 | ```js disableTabs={true} 24 | module.exports = { 25 | // ... the rest of your config 26 | plugins: [require("rippleui")], 27 | }; 28 | ``` 29 | 30 | 3. CDN 31 | 32 | If you prefer to use CDN, you can add the following link to your HTML file, but consider you can't remove the unused styles. 33 | 34 | 35 | 36 | 37 | Now you are set to use RippleUI components in your project. 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | 44 | 45 | ### RippleUI Examples Repositories 46 | 47 | You can find examples of RippleUI in the following repositories: 48 | 49 | 50 | -------------------------------------------------------------------------------- /docs/content/get-started/usage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Get Started 3 | description: Get started with RippleUI, a collection of customizable UI components. Our step-by-step guide will help you understand the basics and get up and running quickly. 4 | --- 5 | 6 | # Ripple UI - Usage 7 | 8 | RippleUI is a TailwindCSS based UI library for any type application, 9 | you can think RippleUI as Bootstrap or another similar UI library, but with the power of TailwindCSS. 10 | 11 | ## Usage 12 | 13 | For use the components it's very easy to use, just use the `class` prop to add the classes to the HTML element, RippleUI includes a lot of components. 14 | 15 | 1. Button Example 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | 22 | 23 | 2. Input Example 24 | 25 | ```html 26 | 27 | ``` 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/content/license/MIT.mdx: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mauricio Siu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/content/more/changelog.mdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/content/more/changelog.mdx -------------------------------------------------------------------------------- /docs/hooks/useCopyToClipboard.ts: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | type CopiedValue = string | null; 4 | type CopyFn = (text: string) => Promise; // Return success 5 | 6 | function useCopyToClipboard(): [CopiedValue, CopyFn] { 7 | const [copiedText, setCopiedText] = useState(null); 8 | 9 | const copy: CopyFn = async (text) => { 10 | if (!navigator?.clipboard) { 11 | console.warn("Clipboard not supported"); 12 | return false; 13 | } 14 | 15 | // Try to save to clipboard then save it in the state if worked 16 | try { 17 | await navigator.clipboard.writeText(text); 18 | setCopiedText(text); 19 | return true; 20 | } catch (error) { 21 | console.warn("Copy failed", error); 22 | setCopiedText(null); 23 | return false; 24 | } 25 | }; 26 | 27 | return [copiedText, copy]; 28 | } 29 | 30 | export default useCopyToClipboard; 31 | -------------------------------------------------------------------------------- /docs/hooks/useIsomorphicLayoutEffect.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useLayoutEffect } from "react"; 2 | 3 | const useIsomorphicLayoutEffect = 4 | typeof window !== "undefined" ? useLayoutEffect : useEffect; 5 | 6 | export default useIsomorphicLayoutEffect; 7 | -------------------------------------------------------------------------------- /docs/hooks/useMobile.ts: -------------------------------------------------------------------------------- 1 | import { useState, useCallback, useEffect } from "react"; 2 | 3 | export const useMediaQuery = (width: number): boolean => { 4 | const [targetReached, setTargetReached] = useState(false); 5 | 6 | const updateTarget = useCallback((e: any) => { 7 | if (e.matches) { 8 | setTargetReached(true); 9 | } else { 10 | setTargetReached(false); 11 | } 12 | }, []); 13 | 14 | useEffect(() => { 15 | const media = window.matchMedia(`(max-width: ${width}px)`); 16 | 17 | media.addListener(updateTarget); 18 | 19 | // Check on mount (callback is not called until a change occurs) 20 | if (media.matches) { 21 | setTargetReached(true); 22 | } 23 | 24 | return () => media.removeListener(updateTarget); 25 | }, []); 26 | 27 | return targetReached; 28 | }; 29 | 30 | export const useIsMobile = () => { 31 | return useMediaQuery(320); 32 | }; 33 | -------------------------------------------------------------------------------- /docs/hooks/useOutsideAlerter.ts: -------------------------------------------------------------------------------- 1 | import { Ref, RefObject, useEffect } from "react"; 2 | 3 | export const useOutsideAlerter = (ref: RefObject) => { 4 | useEffect(() => { 5 | /** 6 | * Alert if clicked on outside of element 7 | */ 8 | function handleClickOutside(event: MouseEvent) { 9 | if (ref.current && !ref.current.contains(event.target as Node)) { 10 | // 11 | ref.current.style.visibility = "hidden"; 12 | // alert("You clicked outside of me!"); 13 | } 14 | } 15 | // Bind the event listener 16 | document.addEventListener("mousedown", handleClickOutside); 17 | return () => { 18 | // Unbind the event listener on clean up 19 | document.removeEventListener("mousedown", handleClickOutside); 20 | }; 21 | }, [ref]); 22 | }; 23 | -------------------------------------------------------------------------------- /docs/hooks/useScroll.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | type SSRRect = { 4 | bottom: number; 5 | height: number; 6 | left: number; 7 | right: number; 8 | top: number; 9 | width: number; 10 | x: number; 11 | y: number; 12 | }; 13 | const EmptySSRRect: SSRRect = { 14 | bottom: 0, 15 | height: 0, 16 | left: 0, 17 | right: 0, 18 | top: 0, 19 | width: 0, 20 | x: 0, 21 | y: 0, 22 | }; 23 | 24 | const useScroll = () => { 25 | const [lastScrollTop, setLastScrollTop] = useState(0); 26 | const [bodyOffset, setBodyOffset] = useState( 27 | typeof window === "undefined" || !window.document 28 | ? EmptySSRRect 29 | : document.body.getBoundingClientRect() 30 | ); 31 | const [scrollY, setScrollY] = useState(bodyOffset.top); 32 | const [scrollX, setScrollX] = useState(bodyOffset.left); 33 | const [scrollDirection, setScrollDirection] = useState< 34 | "down" | "up" | undefined 35 | >(); 36 | 37 | const listener = () => { 38 | setBodyOffset( 39 | typeof window === "undefined" || !window.document 40 | ? EmptySSRRect 41 | : document.body.getBoundingClientRect() 42 | ); 43 | setScrollY(-bodyOffset.top); 44 | setScrollX(bodyOffset.left); 45 | setScrollDirection(lastScrollTop > -bodyOffset.top ? "down" : "up"); 46 | setLastScrollTop(-bodyOffset.top); 47 | }; 48 | 49 | useEffect(() => { 50 | window.addEventListener("scroll", listener); 51 | return () => { 52 | window.removeEventListener("scroll", listener); 53 | }; 54 | }); 55 | 56 | return { 57 | scrollY, 58 | scrollX, 59 | scrollDirection, 60 | }; 61 | }; 62 | 63 | export { useScroll }; 64 | -------------------------------------------------------------------------------- /docs/hooks/useScrollSpy.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const useScrollSpy = ( 4 | selectors: string[], 5 | options?: IntersectionObserverInit 6 | ) => { 7 | const [activeId, setActiveId] = React.useState(); 8 | const observer = React.useRef(); 9 | 10 | React.useEffect(() => { 11 | const elements = selectors.map((selector) => 12 | document.querySelector(selector) 13 | ); 14 | 15 | if (observer.current) { 16 | observer.current.disconnect(); 17 | } 18 | observer.current = new IntersectionObserver((entries) => { 19 | entries.forEach((entry) => { 20 | if (entry?.isIntersecting) { 21 | setActiveId(entry.target.getAttribute("id")); 22 | } 23 | }); 24 | }, options); 25 | elements.forEach((el) => el && observer.current?.observe(el)); 26 | 27 | return () => observer.current?.disconnect(); 28 | }, [selectors]); 29 | 30 | return activeId; 31 | }; 32 | -------------------------------------------------------------------------------- /docs/lib/constant.ts: -------------------------------------------------------------------------------- 1 | export const URL_WEB = "https://www.ripple-ui.com"; 2 | -------------------------------------------------------------------------------- /docs/next-sitemap.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | module.exports = { 3 | siteUrl: process.env.SITE_URL, 4 | generateRobotsTxt: true, // (optional) 5 | // ...other options 6 | }; 7 | -------------------------------------------------------------------------------- /docs/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | swcMinify: true, 5 | } 6 | 7 | module.exports = nextConfig 8 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rippleui-docs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "css:components": "npx tailwindcss -i styles/globals.css -o public/globals.css -m", 8 | "build": "next build", 9 | "postbuild": "npm run css:components && next-sitemap", 10 | "start": "next start", 11 | "lint": "next lint" 12 | }, 13 | "dependencies": { 14 | "@docsearch/react": "^3.3.2", 15 | "@mdx-js/mdx": "2.1.5", 16 | "@mdx-js/react": "2.1.5", 17 | "@types/node": "18.11.9", 18 | "@types/react": "18.0.25", 19 | "@types/react-dom": "18.0.9", 20 | "clsx": "^1.2.1", 21 | "eslint": "8.28.0", 22 | "eslint-config-next": "13.0.5", 23 | "framer-motion": "^10.6.1", 24 | "hast-util-heading-rank": "^2.1.0", 25 | "hast-util-to-string": "^2.0.0", 26 | "next": "13.0.5", 27 | "next-seo": "^5.15.0", 28 | "next-sitemap": "^3.1.43", 29 | "next-themes": "^0.2.1", 30 | "nextjs-progressbar": "^0.0.16", 31 | "prettier": "^2.8.1", 32 | "prism-react-renderer": "^1.3.5", 33 | "react": "18.2.0", 34 | "react-dom": "18.2.0", 35 | "rehype-slug": "^5.1.0", 36 | "remark-mdx-code-meta": "^2.0.0", 37 | "rippleui": "^1.12.1", 38 | "typescript": "4.9.3" 39 | }, 40 | "devDependencies": { 41 | "@types/prettier": "^2.7.1", 42 | "autoprefixer": "^10.4.13", 43 | "next-mdx-remote": "^4.2.0", 44 | "postcss": "^8.4.19", 45 | "remark-cli": "^11.0.0", 46 | "remark-gfm": "^3.0.1", 47 | "remark-preset-lint-consistent": "^5.1.1", 48 | "remark-preset-lint-recommended": "^6.1.2", 49 | "remark-toc": "^8.0.1", 50 | "tailwindcss": "^3.2.4" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "../styles/globals.css"; 2 | import "../styles/searcher.css"; 3 | import "../styles/playground.css"; 4 | import type { AppProps } from "next/app"; 5 | import { ThemeProvider } from "next-themes"; 6 | import { ReactElement, ReactNode } from "react"; 7 | import { NextPage } from "next"; 8 | import NextNProgress from "nextjs-progressbar"; 9 | 10 | export type NextPageWithLayout

    = NextPage & { 11 | getLayout?: (page: ReactElement) => ReactNode; 12 | }; 13 | 14 | type AppPropsWithLayout = AppProps & { 15 | Component: NextPageWithLayout; 16 | }; 17 | 18 | export default function App({ Component, pageProps }: AppPropsWithLayout) { 19 | const getLayout = Component.getLayout ?? ((page) => page); 20 | 21 | return ( 22 | <> 23 | 24 | {getLayout()} 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /docs/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { 2 | Html, 3 | Head, 4 | Main, 5 | NextScript, 6 | DocumentContext, 7 | } from "next/document"; 8 | 9 | class MyDocument extends Document { 10 | static async getInitialProps(ctx: DocumentContext) { 11 | const initialProps = await Document.getInitialProps(ctx); 12 | return initialProps; 13 | } 14 | render() { 15 | return ( 16 | 17 | 18 | 19 | 20 | 24 | 28 | 29 | 30 |

    31 | 32 | 33 | 34 | ); 35 | } 36 | } 37 | 38 | export default MyDocument; 39 | -------------------------------------------------------------------------------- /docs/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { ReactElement } from "react"; 2 | import { MainLayout } from "../components/layout/MainLayout"; 3 | import Meta from "../components/mdx/layout/Meta"; 4 | import { Community } from "../components/styles/Community"; 5 | import { Comparison } from "../components/styles/Comparison"; 6 | import { DarkMode } from "../components/styles/DarkMode"; 7 | import { Footer } from "../components/styles/Footer"; 8 | import { GetStarted } from "../components/styles/GetStarted"; 9 | import { Hero } from "../components/styles/Hero"; 10 | import { Navbar } from "../components/styles/Navbar"; 11 | import { Reusable } from "../components/styles/Reusable"; 12 | import { Statistics } from "../components/styles/Statistics"; 13 | 14 | export default function Home() { 15 | return ( 16 |
    17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
    25 |
    26 | ); 27 | } 28 | 29 | Home.getLayout = function getLayout(page: ReactElement) { 30 | return ( 31 | 32 | 39 | 40 | {page} 41 | 42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /docs/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /docs/public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/public/android-chrome-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/android-chrome-384x384.png -------------------------------------------------------------------------------- /docs/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/public/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #da532c 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/public/card.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/card.webp -------------------------------------------------------------------------------- /docs/public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/favicon-16x16.png -------------------------------------------------------------------------------- /docs/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/favicon-32x32.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/grad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/grad.png -------------------------------------------------------------------------------- /docs/public/grad2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/grad2.png -------------------------------------------------------------------------------- /docs/public/iframe.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | const iframeLinks = [...document.querySelectorAll("a")]; 3 | const iframeForms = [...document.querySelectorAll("form")]; 4 | 5 | iframeLinks.forEach(function (iframeLink) { 6 | iframeLink.addEventListener("click", (e) => e.preventDefault()); 7 | }); 8 | 9 | iframeForms.forEach(function (iframeForm) { 10 | iframeForm.addEventListener("submit", (e) => e.preventDefault()); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /docs/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/logo.png -------------------------------------------------------------------------------- /docs/public/mesh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/mesh.png -------------------------------------------------------------------------------- /docs/public/mesh2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/mesh2.png -------------------------------------------------------------------------------- /docs/public/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/docs/public/mstile-150x150.png -------------------------------------------------------------------------------- /docs/public/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 19 | 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RippleUI", 3 | "short_name": "RippleUI", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-384x384.png", 12 | "sizes": "384x384", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /docs/public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /docs/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | *, 6 | html { 7 | font-family: "Inter", sans-serif; 8 | } 9 | :root { 10 | --vp-layout-max-width: 1440px; 11 | --vp-sidebar-width: 272px; 12 | } 13 | 14 | pre * { 15 | font-family: "Roboto Mono" !important; 16 | font-size: 14px !important; 17 | line-height: 24px; 18 | } 19 | 20 | .scrollbar-hidden::-webkit-scrollbar { 21 | display: none; 22 | } 23 | 24 | .hide-scrollbar::-webkit-scrollbar { 25 | display: none; 26 | } 27 | 28 | .sidebar { 29 | --vp-layout-max-width: 1440px; 30 | --vp-sidebar-width: 272px; 31 | /* --vp-layout-max-width: 1465px; 32 | padding-left: max( 33 | 32px, 34 | calc((100% - (var(--vp-layout-max-width) - 64px)) / 2) 35 | ); */ 36 | /* width: calc( 37 | (100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 38 | 32px 39 | ); */ 40 | } 41 | 42 | .line-clamp { 43 | display: -webkit-box; 44 | -webkit-line-clamp: 3; 45 | -webkit-box-orient: vertical; 46 | overflow: hidden; 47 | } 48 | 49 | .content { 50 | --vp-layout-max-width: 1440px; 51 | --vp-sidebar-width: 272px; 52 | padding-top: 72px; 53 | } 54 | 55 | ::-webkit-scrollbar { 56 | width: 17px; 57 | @apply bg-gray-3; 58 | } 59 | 60 | *::-webkit-scrollbar-track { 61 | border-radius: 8px; 62 | } 63 | 64 | *::-webkit-scrollbar-thumb { 65 | height: 56px; 66 | border-radius: 8px; 67 | border: 4px solid transparent; 68 | background-clip: content-box; 69 | @apply bg-gray-9; 70 | } 71 | 72 | *::-webkit-scrollbar-thumb:hover { 73 | background-color: #555; 74 | } 75 | -------------------------------------------------------------------------------- /docs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('rippleui').Config} */ 2 | const config = { 3 | themes: [ 4 | { 5 | themeName: "light", 6 | colors: { 7 | discordIcon: "#6b64c3", 8 | }, 9 | }, 10 | { 11 | themeName: "dark", 12 | colors: { 13 | discordIcon: "#5841c3", 14 | }, 15 | }, 16 | ], 17 | }; 18 | 19 | /** @type {import('tailwindcss').Config} */ 20 | module.exports = { 21 | darkMode: "class", 22 | content: [ 23 | "./pages/**/*.{js,ts,jsx,tsx}", 24 | "./components/**/*.{js,ts,jsx,tsx}", 25 | "./content/**/*.{js,ts,md,mdx}", 26 | ], 27 | theme: { 28 | extend: {}, 29 | }, 30 | plugins: [ 31 | require("rippleui")({ 32 | ...config, 33 | }), 34 | ], 35 | }; 36 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /docs/utils/getRoutes.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | type Folder = "get-started" | "components" | "license" | "more"; 5 | 6 | export type Folders = { 7 | [key in Folder]: string; 8 | }; 9 | 10 | export const getRoutes = () => { 11 | const folders: Folders = { 12 | components: path.join(process.cwd(), "content/components"), 13 | "get-started": path.join(process.cwd(), "content/get-started"), 14 | license: path.join(process.cwd(), "content/license"), 15 | more: path.join(process.cwd(), "content/more"), 16 | }; 17 | 18 | const routes = Object.keys(folders).map((folder: string) => { 19 | const files = fs.readdirSync(folders[folder as Folder]); 20 | return files.map((file) => { 21 | const name = file.replace(".mdx", ""); 22 | return `/docs/${folder}/${name}`; 23 | }); 24 | }); 25 | return routes.flat(); 26 | }; 27 | -------------------------------------------------------------------------------- /docs/utils/getToc.ts: -------------------------------------------------------------------------------- 1 | import { headingRank } from "hast-util-heading-rank"; 2 | import { toString } from "hast-util-to-string"; 3 | import { visit } from "unist-util-visit"; 4 | import { Root } from "hast"; 5 | import { titleToSlug } from "./titleToSlug"; 6 | 7 | interface Heading { 8 | id: string; 9 | title: string; 10 | level: number; 11 | } 12 | 13 | type Rank = 1 | 2 | 3 | 4 | 5 | 6; 14 | 15 | interface ExtractHeadingsConfig { 16 | rank: Rank; 17 | headings: Heading[]; 18 | } 19 | 20 | export default function rehypeExtractHeadings({ 21 | rank = 1, 22 | headings, 23 | }: ExtractHeadingsConfig) { 24 | return (tree: Root) => { 25 | visit(tree, "element", (node) => { 26 | const rankNode = headingRank(node); 27 | if ( 28 | (rankNode === 1 || 29 | rankNode === 2 || 30 | rankNode === 3 || 31 | rankNode === 4 || 32 | rankNode === 5) && 33 | node.properties 34 | ) { 35 | headings.push({ 36 | title: toString(node), 37 | //@ts-ignore 38 | id: node.properties.id, 39 | level: parseInt(node.tagName[1]), 40 | }); 41 | } 42 | }); 43 | }; 44 | } 45 | 46 | export interface Headings extends Heading {} 47 | -------------------------------------------------------------------------------- /docs/utils/htmlToJsx.ts: -------------------------------------------------------------------------------- 1 | export const htmlToJsx = (code: string) => { 2 | const regexExpr = 3 | /\b(class|for|tabindex|autofocus|autocomplete|fill-rule|clip-rule|checked|stroke-linecap|stroke-linejoin|stroke-width|enable-background)\b/g; 4 | const replacedProps = code.replace(regexExpr, (match) => { 5 | if (match === "class") { 6 | return "className"; 7 | } else if (match === "for") { 8 | return "htmlFor"; 9 | } else if (match === "tabindex") { 10 | return "tabIndex"; 11 | } else if (match === "autofocus") { 12 | return "autoFocus"; 13 | } else if (match === "autocomplete") { 14 | return "autoComplete"; 15 | } else if (match === "fill-rule") { 16 | return "fillRule"; 17 | } else if (match === "clip-rule") { 18 | return "clipRule"; 19 | } else if (match === "checked") { 20 | return "defaultChecked"; 21 | } else if (match === "stroke-linecap") { 22 | return "strokeLinecap"; 23 | } else if (match === "stroke-linejoin") { 24 | return "strokeLinejoin"; 25 | } else if (match === "stroke-width") { 26 | return "strokeWidth"; 27 | } else if (match === "enable-background") { 28 | return "enableBackground"; 29 | } 30 | return match.toLowerCase(); 31 | }); 32 | return replacedProps; 33 | }; 34 | -------------------------------------------------------------------------------- /docs/utils/jsxToHtml.ts: -------------------------------------------------------------------------------- 1 | export const jsxToHtml = (code: string) => { 2 | const regexExpr = 3 | /className|htmlFor|tabIndex|autoFocus|autoComplete|fillRule|clipRule|defaultChecked|strokeLinecap|strokeLinejoin|strokeWidth|enableBackground/g; 4 | const replacedProps = code.replace(regexExpr, (match) => { 5 | if (match === "className") { 6 | return "class"; 7 | } else if (match === "htmlFor") { 8 | return "for"; 9 | } else if (match === "tabIndex") { 10 | return "tabindex"; 11 | } else if (match === "fillRule") { 12 | return "fill-rule"; 13 | } else if (match === "clipRule") { 14 | return "clip-rule"; 15 | } else if (match === "defaultChecked") { 16 | return "checked"; 17 | } else if (match === "strokeLinecap") { 18 | return "stroke-linecap"; 19 | } else if (match === "strokeLinejoin") { 20 | return "stroke-linejoin"; 21 | } else if (match === "strokeWidth") { 22 | return "stroke-width"; 23 | } else if (match === "enableBackground") { 24 | return "enable-background"; 25 | } 26 | return match.toLowerCase(); 27 | }); 28 | 29 | return replacedProps; 30 | }; 31 | -------------------------------------------------------------------------------- /docs/utils/titleToSlug.ts: -------------------------------------------------------------------------------- 1 | export const titleToSlug = (title: string) => { 2 | return title.replace(/\s/g, '-').toLowerCase(); 3 | }; 4 | -------------------------------------------------------------------------------- /examples/gastby-example/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .cache/ 3 | public 4 | src/gatsby-types.d.ts -------------------------------------------------------------------------------- /examples/gastby-example/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | import "./src/styles/global.css"; 2 | -------------------------------------------------------------------------------- /examples/gastby-example/gatsby-config.ts: -------------------------------------------------------------------------------- 1 | import type { GatsbyConfig } from "gatsby"; 2 | 3 | const config: GatsbyConfig = { 4 | siteMetadata: { 5 | siteUrl: `https://www.yourdomain.tld`, 6 | }, 7 | // More easily incorporate content into your pages through automatic TypeScript type generation and better GraphQL IntelliSense. 8 | // If you use VSCode you can also use the GraphQL plugin 9 | // Learn more at: https://gatsby.dev/graphql-typegen 10 | graphqlTypegen: true, 11 | plugins: [ 12 | "gatsby-plugin-postcss", 13 | // ... 14 | ], 15 | }; 16 | 17 | export default config; 18 | -------------------------------------------------------------------------------- /examples/gastby-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gastby-example", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "gastby-example", 6 | "author": "Mauricio", 7 | "keywords": [ 8 | "gatsby" 9 | ], 10 | "scripts": { 11 | "develop": "gatsby develop", 12 | "start": "gatsby develop", 13 | "build": "gatsby build", 14 | "serve": "gatsby serve", 15 | "clean": "gatsby clean", 16 | "typecheck": "tsc --noEmit" 17 | }, 18 | "dependencies": { 19 | "gatsby": "^5.3.2", 20 | "react": "^18.2.0", 21 | "react-dom": "^18.2.0", 22 | "rippleui": "latest" 23 | }, 24 | "devDependencies": { 25 | "@types/node": "^18.11.10", 26 | "@types/react": "^18.0.26", 27 | "@types/react-dom": "^18.0.9", 28 | "autoprefixer": "^10.4.13", 29 | "gatsby-plugin-postcss": "^6.3.0", 30 | "postcss": "^8.4.20", 31 | "tailwindcss": "^3.2.4", 32 | "typescript": "^4.9.3" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/gastby-example/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/gastby-example/src/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/gastby-example/src/images/icon.png -------------------------------------------------------------------------------- /examples/gastby-example/src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Link, HeadFC, PageProps } from "gatsby" 3 | 4 | const pageStyles = { 5 | color: "#232129", 6 | padding: "96px", 7 | fontFamily: "-apple-system, Roboto, sans-serif, serif", 8 | } 9 | const headingStyles = { 10 | marginTop: 0, 11 | marginBottom: 64, 12 | maxWidth: 320, 13 | } 14 | 15 | const paragraphStyles = { 16 | marginBottom: 48, 17 | } 18 | const codeStyles = { 19 | color: "#8A6534", 20 | padding: 4, 21 | backgroundColor: "#FFF4DB", 22 | fontSize: "1.25rem", 23 | borderRadius: 4, 24 | } 25 | 26 | const NotFoundPage: React.FC = () => { 27 | return ( 28 |
    29 |

    Page not found

    30 |

    31 | Sorry 😔, we couldn’t find what you were looking for. 32 |
    33 | {process.env.NODE_ENV === "development" ? ( 34 | <> 35 |
    36 | Try creating a page in src/pages/. 37 |
    38 | 39 | ) : null} 40 |
    41 | Go home. 42 |

    43 |
    44 | ) 45 | } 46 | 47 | export default NotFoundPage 48 | 49 | export const Head: HeadFC = () => Not found 50 | -------------------------------------------------------------------------------- /examples/gastby-example/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import type { HeadFC, PageProps } from "gatsby"; 3 | 4 | const IndexPage: React.FC = () => { 5 | return ( 6 |
    7 | 8 |
    9 | ); 10 | }; 11 | 12 | export default IndexPage; 13 | 14 | export const Head: HeadFC = () => Home Page; 15 | -------------------------------------------------------------------------------- /examples/gastby-example/src/styles/global.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/gastby-example/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./src/pages/**/*.{js,jsx,ts,tsx}", 5 | "./src/components/**/*.{js,jsx,ts,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [require("rippleui")], 11 | }; 12 | -------------------------------------------------------------------------------- /examples/my-angular-project/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/my-angular-project/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /examples/my-angular-project/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/my-angular-project/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "pwa-chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /examples/my-angular-project/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /examples/my-angular-project/README.md: -------------------------------------------------------------------------------- 1 | # MyAngularProject 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.0.4. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /examples/my-angular-project/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-angular-project", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "^15.0.0", 14 | "@angular/common": "^15.0.0", 15 | "@angular/compiler": "^15.0.0", 16 | "@angular/core": "^15.0.0", 17 | "@angular/forms": "^15.0.0", 18 | "@angular/platform-browser": "^15.0.0", 19 | "@angular/platform-browser-dynamic": "^15.0.0", 20 | "@angular/router": "^15.0.0", 21 | "rxjs": "~7.5.0", 22 | "tslib": "^2.3.0", 23 | "zone.js": "~0.12.0" 24 | }, 25 | "devDependencies": { 26 | "@angular-devkit/build-angular": "^15.0.4", 27 | "@angular/cli": "~15.0.4", 28 | "@angular/compiler-cli": "^15.0.0", 29 | "@types/jasmine": "~4.3.0", 30 | "autoprefixer": "^10.4.13", 31 | "jasmine-core": "~4.5.0", 32 | "karma": "~6.4.0", 33 | "karma-chrome-launcher": "~3.1.0", 34 | "karma-coverage": "~2.2.0", 35 | "karma-jasmine": "~5.1.0", 36 | "karma-jasmine-html-reporter": "~2.0.0", 37 | "postcss": "^8.4.20", 38 | "tailwindcss": "^3.2.4", 39 | "typescript": "~4.8.2", 40 | "rippleui": "latest" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-angular-project/src/app/app.component.css -------------------------------------------------------------------------------- /examples/my-angular-project/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | declarations: [ 8 | AppComponent 9 | ], 10 | }).compileComponents(); 11 | }); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it(`should have as title 'my-angular-project'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('my-angular-project'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement as HTMLElement; 29 | expect(compiled.querySelector('.content span')?.textContent).toContain('my-angular-project app is running!'); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'my-angular-project'; 10 | } 11 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | 4 | import { AppComponent } from './app.component'; 5 | 6 | @NgModule({ 7 | declarations: [ 8 | AppComponent 9 | ], 10 | imports: [ 11 | BrowserModule 12 | ], 13 | providers: [], 14 | bootstrap: [AppComponent] 15 | }) 16 | export class AppModule { } 17 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-angular-project/src/assets/.gitkeep -------------------------------------------------------------------------------- /examples/my-angular-project/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-angular-project/src/favicon.ico -------------------------------------------------------------------------------- /examples/my-angular-project/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MyAngularProject 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | 6 | platformBrowserDynamic().bootstrapModule(AppModule) 7 | .catch(err => console.error(err)); 8 | -------------------------------------------------------------------------------- /examples/my-angular-project/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | @tailwind base; 3 | @tailwind components; 4 | @tailwind utilities; 5 | -------------------------------------------------------------------------------- /examples/my-angular-project/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{html,ts}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("rippleui")], 8 | }; 9 | -------------------------------------------------------------------------------- /examples/my-angular-project/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/my-angular-project/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/my-angular-project/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/my-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/my-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-scripts": "5.0.1", 12 | "rippleui": "latest", 13 | "web-vitals": "^2.1.4" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | }, 39 | "devDependencies": { 40 | "autoprefixer": "^10.4.13", 41 | "postcss": "^8.4.20", 42 | "tailwindcss": "^3.2.4" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/my-react-app/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/my-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-react-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/my-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
    32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/my-react-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-react-app/public/logo192.png -------------------------------------------------------------------------------- /examples/my-react-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-react-app/public/logo512.png -------------------------------------------------------------------------------- /examples/my-react-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/my-react-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/my-react-app/src/App.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/my-react-app/src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ); 9 | } 10 | 11 | export default App; 12 | -------------------------------------------------------------------------------- /examples/my-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/my-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById("root")); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /examples/my-react-app/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("rippleui")], 8 | }; 9 | -------------------------------------------------------------------------------- /examples/my-remix-app/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type {import('eslint').Linter.Config} */ 2 | module.exports = { 3 | extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], 4 | }; 5 | -------------------------------------------------------------------------------- /examples/my-remix-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | /.cache 4 | /build 5 | /public/build 6 | .env 7 | -------------------------------------------------------------------------------- /examples/my-remix-app/README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Remix! 2 | 3 | - [Remix Docs](https://remix.run/docs) 4 | 5 | ## Development 6 | 7 | From your terminal: 8 | 9 | ```sh 10 | npm run dev 11 | ``` 12 | 13 | This starts your app in development mode, rebuilding assets on file changes. 14 | 15 | ## Deployment 16 | 17 | First, build your app for production: 18 | 19 | ```sh 20 | npm run build 21 | ``` 22 | 23 | Then run the app in production mode: 24 | 25 | ```sh 26 | npm start 27 | ``` 28 | 29 | Now you'll need to pick a host to deploy it to. 30 | 31 | ### DIY 32 | 33 | If you're familiar with deploying node applications, the built-in Remix app server is production-ready. 34 | 35 | Make sure to deploy the output of `remix build` 36 | 37 | - `build/` 38 | - `public/build/` 39 | 40 | ### Using a Template 41 | 42 | When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server. 43 | 44 | ```sh 45 | cd .. 46 | # create a new project, and pick a pre-configured host 47 | npx create-remix@latest 48 | cd my-new-remix-app 49 | # remove the new project's app (not the old one!) 50 | rm -rf app 51 | # copy your app over 52 | cp -R ../my-old-remix-app/app app 53 | ``` 54 | -------------------------------------------------------------------------------- /examples/my-remix-app/app/entry.client.tsx: -------------------------------------------------------------------------------- 1 | import { RemixBrowser } from "@remix-run/react"; 2 | import { startTransition, StrictMode } from "react"; 3 | import { hydrateRoot } from "react-dom/client"; 4 | 5 | function hydrate() { 6 | startTransition(() => { 7 | hydrateRoot( 8 | document, 9 | 10 | 11 | 12 | ); 13 | }); 14 | } 15 | 16 | if (window.requestIdleCallback) { 17 | window.requestIdleCallback(hydrate); 18 | } else { 19 | // Safari doesn't support requestIdleCallback 20 | // https://caniuse.com/requestidlecallback 21 | window.setTimeout(hydrate, 1); 22 | } 23 | -------------------------------------------------------------------------------- /examples/my-remix-app/app/root.tsx: -------------------------------------------------------------------------------- 1 | import styles from "./styles/app.css"; 2 | import type { MetaFunction } from "@remix-run/node"; 3 | import { 4 | Links, 5 | LiveReload, 6 | Meta, 7 | Outlet, 8 | Scripts, 9 | ScrollRestoration, 10 | } from "@remix-run/react"; 11 | 12 | export const meta: MetaFunction = () => ({ 13 | charset: "utf-8", 14 | title: "New Remix App", 15 | viewport: "width=device-width,initial-scale=1", 16 | }); 17 | 18 | export function links() { 19 | return [{ rel: "stylesheet", href: styles }]; 20 | } 21 | 22 | export default function App() { 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /examples/my-remix-app/app/routes/index.tsx: -------------------------------------------------------------------------------- 1 | export default function Index() { 2 | return ( 3 |
    4 | 5 |
    6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /examples/my-remix-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "sideEffects": false, 4 | "scripts": { 5 | "build": "npm run build:css && remix build", 6 | "build:css": "tailwindcss -m -i ../app/styles/app.css -o app/styles/app.css", 7 | "dev": "concurrently \"npm run dev:css\" \"remix dev\"", 8 | "dev:css": "tailwindcss -w -i ./app/styles/app.css -o app/styles/app.css" 9 | }, 10 | "dependencies": { 11 | "@remix-run/node": "^1.9.0", 12 | "@remix-run/react": "^1.9.0", 13 | "@remix-run/serve": "^1.9.0", 14 | "isbot": "^3.6.5", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0", 17 | "rippleui": "latest" 18 | }, 19 | "devDependencies": { 20 | "@remix-run/dev": "^1.9.0", 21 | "@remix-run/eslint-config": "^1.9.0", 22 | "@types/react": "^18.0.25", 23 | "@types/react-dom": "^18.0.8", 24 | "autoprefixer": "^10.4.13", 25 | "concurrently": "^7.6.0", 26 | "eslint": "^8.27.0", 27 | "postcss": "^8.4.20", 28 | "tailwindcss": "^3.2.4", 29 | "typescript": "^4.8.4" 30 | }, 31 | "engines": { 32 | "node": ">=14" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/my-remix-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-remix-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/my-remix-app/remix.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@remix-run/dev').AppConfig} */ 2 | module.exports = { 3 | ignoredRouteFiles: ["**/.*"], 4 | // appDirectory: "app", 5 | // assetsBuildDirectory: "public/build", 6 | // serverBuildPath: "build/index.js", 7 | // publicPath: "/build/", 8 | }; 9 | -------------------------------------------------------------------------------- /examples/my-remix-app/remix.env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /examples/my-remix-app/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./app/**/*.{js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("rippleui")], 8 | }; 9 | -------------------------------------------------------------------------------- /examples/my-remix-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], 3 | "compilerOptions": { 4 | "lib": ["DOM", "DOM.Iterable", "ES2019"], 5 | "isolatedModules": true, 6 | "esModuleInterop": true, 7 | "jsx": "react-jsx", 8 | "moduleResolution": "node", 9 | "resolveJsonModule": true, 10 | "target": "ES2019", 11 | "strict": true, 12 | "allowJs": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "baseUrl": ".", 15 | "paths": { 16 | "~/*": ["./app/*"] 17 | }, 18 | 19 | // Remix takes care of building everything in `remix build`. 20 | "noEmit": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], 5 | plugins: ['svelte3', '@typescript-eslint'], 6 | ignorePatterns: ['*.cjs'], 7 | overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], 8 | settings: { 9 | 'svelte3/typescript': () => require('typescript') 10 | }, 11 | parserOptions: { 12 | sourceType: 'module', 13 | ecmaVersion: 2020 14 | }, 15 | env: { 16 | browser: true, 17 | es2017: true, 18 | node: true 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | .vercel 10 | .output 11 | vite.config.js.timestamp-* 12 | vite.config.ts.timestamp-* 13 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | 10 | # Ignore files for PNPM, NPM and YARN 11 | pnpm-lock.yaml 12 | package-lock.json 13 | yarn.lock 14 | -------------------------------------------------------------------------------- /examples/my-svelte-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "pluginSearchDirs": ["."], 8 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }] 9 | } 10 | -------------------------------------------------------------------------------- /examples/my-svelte-app/README.md: -------------------------------------------------------------------------------- 1 | # create-svelte 2 | 3 | Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte). 4 | 5 | ## Creating a project 6 | 7 | If you're seeing this, you've probably already done this step. Congrats! 8 | 9 | ```bash 10 | # create a new project in the current directory 11 | npm create svelte@latest 12 | 13 | # create a new project in my-app 14 | npm create svelte@latest my-app 15 | ``` 16 | 17 | ## Developing 18 | 19 | Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: 20 | 21 | ```bash 22 | npm run dev 23 | 24 | # or start the server and open the app in a new browser tab 25 | npm run dev -- --open 26 | ``` 27 | 28 | ## Building 29 | 30 | To create a production version of your app: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | You can preview the production build with `npm run preview`. 37 | 38 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. 39 | -------------------------------------------------------------------------------- /examples/my-svelte-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myapp", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "dev": "vite dev", 6 | "build": "vite build", 7 | "preview": "vite preview", 8 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 9 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 10 | "lint": "prettier --plugin-search-dir . --check . && eslint .", 11 | "format": "prettier --plugin-search-dir . --write ." 12 | }, 13 | "devDependencies": { 14 | "@fontsource/fira-mono": "^4.5.10", 15 | "@neoconfetti/svelte": "^1.0.0", 16 | "@sveltejs/adapter-auto": "^1.0.0", 17 | "@sveltejs/kit": "^1.0.0", 18 | "@types/cookie": "^0.5.1", 19 | "@typescript-eslint/eslint-plugin": "^5.45.0", 20 | "@typescript-eslint/parser": "^5.45.0", 21 | "autoprefixer": "^10.4.13", 22 | "eslint": "^8.28.0", 23 | "eslint-config-prettier": "^8.5.0", 24 | "eslint-plugin-svelte3": "^4.0.0", 25 | "postcss": "^8.4.20", 26 | "prettier": "^2.8.0", 27 | "prettier-plugin-svelte": "^2.8.1", 28 | "svelte": "^3.54.0", 29 | "svelte-check": "^2.9.2", 30 | "tailwindcss": "^3.2.4", 31 | "tslib": "^2.4.1", 32 | "typescript": "^4.9.3", 33 | "vite": "^4.0.0", 34 | "rippleui": "latest" 35 | }, 36 | "type": "module" 37 | } 38 | -------------------------------------------------------------------------------- /examples/my-svelte-app/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://kit.svelte.dev/docs/types#app 2 | // for information about these interfaces 3 | // and what to do when importing types 4 | declare namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface Platform {} 9 | } 10 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
    %sveltekit.body%
    11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/lib/images/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | 16 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/lib/images/svelte-logo.svg: -------------------------------------------------------------------------------- 1 | svelte-logo -------------------------------------------------------------------------------- /examples/my-svelte-app/src/lib/images/svelte-welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-svelte-app/src/lib/images/svelte-welcome.png -------------------------------------------------------------------------------- /examples/my-svelte-app/src/lib/images/svelte-welcome.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-svelte-app/src/lib/images/svelte-welcome.webp -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 |
    9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | Home 9 | 10 | 11 | 12 |
    13 |

    14 | 15 | 16 | 17 | Welcome 18 | 19 | 20 | 21 | to your new
    SvelteKit app 22 |

    23 | 24 |

    25 | try editing src/routes/+page.svelte 26 |

    27 | 28 | 29 |
    30 | 31 | 60 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/+page.ts: -------------------------------------------------------------------------------- 1 | // since there's no dynamic data here, we can prerender 2 | // it so that it gets served as a static asset in production 3 | export const prerender = true; 4 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/about/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | About 3 | 4 | 5 | 6 |
    7 |

    About this app

    8 | 9 |

    10 | This is a SvelteKit app. You can make your own by typing the 11 | following into your command line and following the prompts: 12 |

    13 | 14 |
    npm create svelte@latest
    15 | 16 |

    17 | The page you're looking at is purely static HTML, with no client-side interactivity needed. 18 | Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening 19 | the devtools network panel and reloading. 20 |

    21 | 22 |

    23 | The Sverdle page illustrates SvelteKit's data loading and form handling. Try 24 | using it with JavaScript disabled! 25 |

    26 |
    27 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/about/+page.ts: -------------------------------------------------------------------------------- 1 | import { dev } from '$app/environment'; 2 | 3 | // we don't need any JS on this page, though we'll load 4 | // it in dev so that we get hot module replacement 5 | export const csr = dev; 6 | 7 | // since there's no dynamic data here, we can prerender 8 | // it so that it gets served as a static asset in production 9 | export const prerender = true; 10 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/sverdle/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { fail } from '@sveltejs/kit'; 2 | import { Game } from './game'; 3 | import type { PageServerLoad, Actions } from './$types'; 4 | 5 | export const load = (({ cookies }) => { 6 | const game = new Game(cookies.get('sverdle')); 7 | 8 | return { 9 | /** 10 | * The player's guessed words so far 11 | */ 12 | guesses: game.guesses, 13 | 14 | /** 15 | * An array of strings like '__x_c' corresponding to the guesses, where 'x' means 16 | * an exact match, and 'c' means a close match (right letter, wrong place) 17 | */ 18 | answers: game.answers, 19 | 20 | /** 21 | * The correct answer, revealed if the game is over 22 | */ 23 | answer: game.answers.length >= 6 ? game.answer : null 24 | }; 25 | }) satisfies PageServerLoad; 26 | 27 | export const actions = { 28 | /** 29 | * Modify game state in reaction to a keypress. If client-side JavaScript 30 | * is available, this will happen in the browser instead of here 31 | */ 32 | update: async ({ request, cookies }) => { 33 | const game = new Game(cookies.get('sverdle')); 34 | 35 | const data = await request.formData(); 36 | const key = data.get('key'); 37 | 38 | const i = game.answers.length; 39 | 40 | if (key === 'backspace') { 41 | game.guesses[i] = game.guesses[i].slice(0, -1); 42 | } else { 43 | game.guesses[i] += key; 44 | } 45 | 46 | cookies.set('sverdle', game.toString()); 47 | }, 48 | 49 | /** 50 | * Modify game state in reaction to a guessed word. This logic always runs on 51 | * the server, so that people can't cheat by peeking at the JavaScript 52 | */ 53 | enter: async ({ request, cookies }) => { 54 | const game = new Game(cookies.get('sverdle')); 55 | 56 | const data = await request.formData(); 57 | const guess = data.getAll('guess') as string[]; 58 | 59 | if (!game.enter(guess)) { 60 | return fail(400, { badGuess: true }); 61 | } 62 | 63 | cookies.set('sverdle', game.toString()); 64 | }, 65 | 66 | restart: async ({ cookies }) => { 67 | cookies.delete('sverdle'); 68 | } 69 | } satisfies Actions; 70 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/sverdle/game.ts: -------------------------------------------------------------------------------- 1 | import { words, allowed } from './words.server'; 2 | 3 | export class Game { 4 | index: number; 5 | guesses: string[]; 6 | answers: string[]; 7 | answer: string; 8 | 9 | /** 10 | * Create a game object from the player's cookie, or initialise a new game 11 | */ 12 | constructor(serialized: string | undefined = undefined) { 13 | if (serialized) { 14 | const [index, guesses, answers] = serialized.split('-'); 15 | 16 | this.index = +index; 17 | this.guesses = guesses ? guesses.split(' ') : []; 18 | this.answers = answers ? answers.split(' ') : []; 19 | } else { 20 | this.index = Math.floor(Math.random() * words.length); 21 | this.guesses = ['', '', '', '', '', '']; 22 | this.answers = [] ; 23 | } 24 | 25 | this.answer = words[this.index]; 26 | } 27 | 28 | /** 29 | * Update game state based on a guess of a five-letter word. Returns 30 | * true if the guess was valid, false otherwise 31 | */ 32 | enter(letters: string[]) { 33 | const word = letters.join(''); 34 | const valid = allowed.has(word); 35 | 36 | if (!valid) return false; 37 | 38 | this.guesses[this.answers.length] = word; 39 | 40 | const available = Array.from(this.answer); 41 | const answer = Array(5).fill('_'); 42 | 43 | // first, find exact matches 44 | for (let i = 0; i < 5; i += 1) { 45 | if (letters[i] === available[i]) { 46 | answer[i] = 'x'; 47 | available[i] = ' '; 48 | } 49 | } 50 | 51 | // then find close matches (this has to happen 52 | // in a second step, otherwise an early close 53 | // match can prevent a later exact match) 54 | for (let i = 0; i < 5; i += 1) { 55 | if (answer[i] === '_') { 56 | const index = available.indexOf(letters[i]); 57 | if (index !== -1) { 58 | answer[i] = 'c'; 59 | available[index] = ' '; 60 | } 61 | } 62 | } 63 | 64 | this.answers.push(answer.join('')); 65 | 66 | return true; 67 | } 68 | 69 | /** 70 | * Serialize game state so it can be set as a cookie 71 | */ 72 | toString() { 73 | return `${this.index}-${this.guesses.join(' ')}-${this.answers.join(' ')}`; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/sverdle/how-to-play/+page.ts: -------------------------------------------------------------------------------- 1 | import { dev } from '$app/environment'; 2 | 3 | // we don't need any JS on this page, though we'll load 4 | // it in dev so that we get hot module replacement 5 | export const csr = dev; 6 | 7 | // since there's no dynamic data here, we can prerender 8 | // it so that it gets served as a static asset in production 9 | export const prerender = true; 10 | -------------------------------------------------------------------------------- /examples/my-svelte-app/src/routes/sverdle/reduced-motion.ts: -------------------------------------------------------------------------------- 1 | import { readable } from 'svelte/store'; 2 | import { browser } from '$app/environment'; 3 | 4 | const reduced_motion_query = '(prefers-reduced-motion: reduce)'; 5 | 6 | const get_initial_motion_preference = () => { 7 | if (!browser) return false; 8 | return window.matchMedia(reduced_motion_query).matches; 9 | }; 10 | 11 | export const reduced_motion = readable(get_initial_motion_preference(), (set) => { 12 | if (browser) { 13 | const set_reduced_motion = (event: MediaQueryListEvent) => { 14 | set(event.matches); 15 | }; 16 | const media_query_list = window.matchMedia(reduced_motion_query); 17 | media_query_list.addEventListener('change', set_reduced_motion); 18 | 19 | return () => { 20 | media_query_list.removeEventListener('change', set_reduced_motion); 21 | }; 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /examples/my-svelte-app/static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/my-svelte-app/static/favicon.png -------------------------------------------------------------------------------- /examples/my-svelte-app/static/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/my-svelte-app/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-auto'; 2 | import { vitePreprocess } from '@sveltejs/kit/vite'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | adapter: adapter() 12 | } 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /examples/my-svelte-app/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,js,svelte,ts}'], 4 | theme: { 5 | extend: {} 6 | }, 7 | plugins: [require('rippleui')] 8 | }; 9 | -------------------------------------------------------------------------------- /examples/my-svelte-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true 12 | } 13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias 14 | // 15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 16 | // from the referenced tsconfig.json - TypeScript does not merge them in 17 | } 18 | -------------------------------------------------------------------------------- /examples/my-svelte-app/vite.config.js: -------------------------------------------------------------------------------- 1 | import { sveltekit } from '@sveltejs/kit/vite'; 2 | 3 | /** @type {import('vite').UserConfig} */ 4 | const config = { 5 | plugins: [sveltekit()] 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /examples/nextjs-example/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/nextjs-example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /examples/nextjs-example/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /examples/nextjs-example/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | } 5 | 6 | module.exports = nextConfig 7 | -------------------------------------------------------------------------------- /examples/nextjs-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@next/font": "13.0.7", 13 | "@types/node": "18.11.17", 14 | "@types/react": "18.0.26", 15 | "@types/react-dom": "18.0.9", 16 | "eslint": "8.30.0", 17 | "eslint-config-next": "13.0.7", 18 | "next": "13.0.7", 19 | "react": "18.2.0", 20 | "react-dom": "18.2.0", 21 | "typescript": "4.9.4", 22 | "rippleui": "latest" 23 | }, 24 | "devDependencies": { 25 | "autoprefixer": "^10.4.13", 26 | "postcss": "^8.4.20", 27 | "tailwindcss": "^3.2.4" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/nextjs-example/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | import type { AppProps } from 'next/app' 3 | 4 | export default function App({ Component, pageProps }: AppProps) { 5 | return 6 | } 7 | -------------------------------------------------------------------------------- /examples/nextjs-example/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from 'next/document' 2 | 3 | export default function Document() { 4 | return ( 5 | 6 | 7 | 8 |
    9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /examples/nextjs-example/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from 'next' 3 | 4 | type Data = { 5 | name: string 6 | } 7 | 8 | export default function handler( 9 | req: NextApiRequest, 10 | res: NextApiResponse 11 | ) { 12 | res.status(200).json({ name: 'John Doe' }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/nextjs-example/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { Inter } from "@next/font/google"; 2 | import styles from "../styles/Home.module.css"; 3 | 4 | const inter = Inter({ subsets: ["latin"] }); 5 | 6 | export default function Home() { 7 | return ( 8 |
    9 | 10 |
    11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /examples/nextjs-example/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/nextjs-example/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/nextjs-example/public/favicon.ico -------------------------------------------------------------------------------- /examples/nextjs-example/public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/nextjs-example/public/thirteen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/nextjs-example/public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/nextjs-example/styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/nextjs-example/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./pages/**/*.{js,ts,jsx,tsx}", 5 | "./components/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [require("rippleui")], 11 | }; 12 | -------------------------------------------------------------------------------- /examples/nextjs-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/vuejs-example/.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 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /examples/vuejs-example/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /examples/vuejs-example/README.md: -------------------------------------------------------------------------------- 1 | # vuejs-example 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Type Support for `.vue` Imports in TS 10 | 11 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. 12 | 13 | If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: 14 | 15 | 1. Disable the built-in TypeScript Extension 16 | 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette 17 | 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` 18 | 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. 19 | 20 | ## Customize configuration 21 | 22 | See [Vite Configuration Reference](https://vitejs.dev/config/). 23 | 24 | ## Project Setup 25 | 26 | ```sh 27 | npm install 28 | ``` 29 | 30 | ### Compile and Hot-Reload for Development 31 | 32 | ```sh 33 | npm run dev 34 | ``` 35 | 36 | ### Type-Check, Compile and Minify for Production 37 | 38 | ```sh 39 | npm run build 40 | ``` 41 | -------------------------------------------------------------------------------- /examples/vuejs-example/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/vuejs-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
    11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/vuejs-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuejs-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "build-only": "vite build", 10 | "type-check": "vue-tsc --noEmit" 11 | }, 12 | "dependencies": { 13 | "vue": "^3.2.45" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^18.11.12", 17 | "@vitejs/plugin-vue": "^4.0.0", 18 | "@vitejs/plugin-vue-jsx": "^3.0.0", 19 | "@vue/tsconfig": "^0.1.3", 20 | "autoprefixer": "^10.4.13", 21 | "npm-run-all": "^4.1.5", 22 | "postcss": "^8.4.20", 23 | "tailwindcss": "^3.2.4", 24 | "typescript": "~4.7.4", 25 | "vite": "^4.0.0", 26 | "vue-tsc": "^1.0.12", 27 | "rippleui": "latest" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/vuejs-example/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /examples/vuejs-example/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/examples/vuejs-example/public/favicon.ico -------------------------------------------------------------------------------- /examples/vuejs-example/src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 37 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/assets/base.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import "./base.css"; 2 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 41 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 87 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /examples/vuejs-example/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | import './assets/main.css' 5 | 6 | createApp(App).mount('#app') 7 | -------------------------------------------------------------------------------- /examples/vuejs-example/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{vue,js,ts,jsx,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("rippleui")], 8 | }; 9 | -------------------------------------------------------------------------------- /examples/vuejs-example/tsconfig.config.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 | -------------------------------------------------------------------------------- /examples/vuejs-example/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 | }, 10 | 11 | "references": [ 12 | { 13 | "path": "./tsconfig.config.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /examples/vuejs-example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [vue(), vueJsx()], 10 | resolve: { 11 | alias: { 12 | '@': fileURLToPath(new URL('./src', import.meta.url)) 13 | } 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /experiments/rippleui/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 37 |
    38 |

    Buttons

    39 | 40 |
    41 | 42 | 43 | -------------------------------------------------------------------------------- /experiments/rippleui/theme-change.js: -------------------------------------------------------------------------------- 1 | var toggle = document.getElementById("theme-toggle"); 2 | 3 | var storedTheme = 4 | localStorage.getItem("theme") || 5 | (window.matchMedia("(prefers-color-scheme: dark)").matches 6 | ? "dark" 7 | : "light"); 8 | if (storedTheme) 9 | document.documentElement.setAttribute("data-theme", storedTheme); 10 | 11 | function toggleDarkmode() { 12 | var currentTheme = document.documentElement.getAttribute("data-theme"); 13 | var targetTheme = "light"; 14 | 15 | if (currentTheme === "light") { 16 | targetTheme = "dark"; 17 | } 18 | console.log(targetTheme); 19 | document.documentElement.setAttribute("data-theme", targetTheme); 20 | localStorage.setItem("theme", targetTheme); 21 | } 22 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | "postcss-import": {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | ...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {}), 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [require('prettier-plugin-tailwindcss')], 3 | } -------------------------------------------------------------------------------- /scripts/minify.js: -------------------------------------------------------------------------------- 1 | const Terser = require('terser'); 2 | var fs = require("fs"); 3 | var path = require("path"); 4 | 5 | 6 | function getAllFiles(dirPath, arrayOfFiles) { 7 | let files = fs.readdirSync(dirPath); 8 | 9 | arrayOfFiles = arrayOfFiles || []; 10 | 11 | files.forEach(function(file) { 12 | if (fs.statSync(dirPath + "/" + file).isDirectory()) { 13 | arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles); 14 | } else { 15 | arrayOfFiles.push(path.join( path.resolve(__dirname, "../"),dirPath, "/", file)); 16 | } 17 | }); 18 | 19 | 20 | return arrayOfFiles.filter(path => path.match(/\.js$/)); 21 | } 22 | 23 | async function minifyFiles(filePaths) { 24 | await Promise.all(filePaths.map(async (filePath) => { 25 | fs.writeFileSync( 26 | filePath, 27 | (await Terser.minify(fs.readFileSync(filePath, "utf8"))).code 28 | ); 29 | })); 30 | } 31 | const files = getAllFiles("./dist/js"); 32 | 33 | minifyFiles(files).then(r => r); -------------------------------------------------------------------------------- /standalone-cli/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | -------------------------------------------------------------------------------- /standalone-cli/README.md: -------------------------------------------------------------------------------- 1 | # Tailwind Standalone CLI 2 | 3 | > Standalone version of [Tailwind CLI](https://tailwindcss.com/docs/installation#using-tailwind-cli) 4 | 5 | ## Installation 6 | 7 | Download the appropriate platform-specific version of the `tailwindcss` with `rippleui` cli from the [latest release](https://github.com/Siumauricio/rippleui/releases). 8 | 9 | ## Usage 10 | 11 | ```bash 12 | # Let's say you have a want to use the executable for new MacOS architecture, with the following command we can rename the executable to tailwindcss 13 | mv tailwindcss-macos-arm64 tailwindcss 14 | 15 | # Then you can use the executable as you would use the Tailwind CLI 16 | 17 | # Create new Tailwind config file 18 | ./tailwindcss init 19 | ``` 20 | 21 | ## Example 22 | 23 | You can see a example of how to use the `tailwindcss` cli with `rippleui` in the `example` folder. 24 | 25 | Check out the [Tailwind CLI documentation](https://tailwindcss.com/docs/installation#using-tailwind-cli) for details on the available options. 26 | -------------------------------------------------------------------------------- /standalone-cli/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 |
    2 222222
    20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /standalone-cli/example/input.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /standalone-cli/example/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["index.html"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("rippleui")], 8 | }; 9 | -------------------------------------------------------------------------------- /standalone-cli/example/tailwindcss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Siumauricio/rippleui/2c240e74445c6ae09dbe4a19ce80c885fbe64d04/standalone-cli/example/tailwindcss -------------------------------------------------------------------------------- /standalone-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailwindcss-standalone", 3 | "version": "0.0.0", 4 | "bin": "standalone.js", 5 | "scripts": { 6 | "build": "pkg . --compress Brotli --no-bytecode --public-packages \"*\" --public", 7 | "prebuild": "rimraf dist", 8 | "postbuild": "move-file dist/tailwindcss-standalone-macos-x64 dist/tailwindcss-macos-x64 && move-file dist/tailwindcss-standalone-macos-arm64 dist/tailwindcss-macos-arm64 && move-file dist/tailwindcss-standalone-win-x64.exe dist/tailwindcss-windows-x64.exe && move-file dist/tailwindcss-standalone-win-arm64.exe dist/tailwindcss-windows-arm64.exe && move-file dist/tailwindcss-standalone-linuxstatic-x64 dist/tailwindcss-linux-x64 && move-file dist/tailwindcss-standalone-linuxstatic-arm64 dist/tailwindcss-linux-arm64 && move-file dist/tailwindcss-standalone-linuxstatic-armv7 dist/tailwindcss-linux-armv7", 9 | "test": "jest" 10 | }, 11 | "devDependencies": { 12 | "@tailwindcss/aspect-ratio": "^0.4.0", 13 | "@tailwindcss/container-queries": "^0.1.0", 14 | "@tailwindcss/forms": "^0.5.2", 15 | "@tailwindcss/line-clamp": "^0.4.0", 16 | "@tailwindcss/typography": "^0.5.4", 17 | "fs-extra": "^10.1.0", 18 | "jest": "^27.2.5", 19 | "move-file-cli": "^3.0.0", 20 | "pkg": "^5.8.0", 21 | "rimraf": "^3.0.2", 22 | "rippleui": "^1.12.1", 23 | "tailwindcss": "^3.3.1" 24 | }, 25 | "pkg": { 26 | "assets": "node_modules/tailwindcss/lib/css/preflight.css", 27 | "targets": [ 28 | "node16-macos-x64", 29 | "node16-macos-arm64", 30 | "node16-win-x64", 31 | "node16-win-arm64", 32 | "node16-linuxstatic-x64", 33 | "node16-linuxstatic-arm64", 34 | "node16-linuxstatic-armv7" 35 | ], 36 | "outputPath": "dist" 37 | }, 38 | "jest": { 39 | "testTimeout": 30000 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /standalone-cli/standalone.js: -------------------------------------------------------------------------------- 1 | let Module = require("module"); 2 | let origRequire = Module.prototype.require; 3 | 4 | let localModules = { 5 | "tailwindcss/colors": require("tailwindcss/colors"), 6 | "tailwindcss/defaultConfig": require("tailwindcss/defaultConfig"), 7 | "tailwindcss/defaultTheme": require("tailwindcss/defaultTheme"), 8 | "tailwindcss/resolveConfig": require("tailwindcss/resolveConfig"), 9 | "tailwindcss/plugin": require("tailwindcss/plugin"), 10 | 11 | "@tailwindcss/aspect-ratio": require("@tailwindcss/aspect-ratio"), 12 | "@tailwindcss/container-queries": require("@tailwindcss/container-queries"), 13 | "@tailwindcss/forms": require("@tailwindcss/forms"), 14 | "@tailwindcss/line-clamp": require("@tailwindcss/line-clamp"), 15 | "@tailwindcss/typography": require("@tailwindcss/typography"), 16 | rippleui: require("rippleui"), 17 | 18 | // These are present to allow them to be specified in the PostCSS config file 19 | autoprefixer: require("autoprefixer"), 20 | tailwindcss: require("tailwindcss"), 21 | }; 22 | 23 | Module.prototype.require = function (id) { 24 | if (localModules.hasOwnProperty(id)) { 25 | return localModules[id]; 26 | } 27 | return origRequire.apply(this, arguments); 28 | }; 29 | 30 | require("tailwindcss/lib/cli"); 31 | -------------------------------------------------------------------------------- /standalone-cli/tests/fixtures/basic.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | -------------------------------------------------------------------------------- /standalone-cli/tests/fixtures/plugins.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |
    5 |
    6 | -------------------------------------------------------------------------------- /standalone-cli/tests/fixtures/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | 'postcss-will-change': {}, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /standalone-cli/tests/fixtures/test.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('@tailwindcss/aspect-ratio'), 4 | require('@tailwindcss/container-queries'), 5 | require('@tailwindcss/forms')({ strategy: 'class' }), 6 | require('@tailwindcss/line-clamp'), 7 | require('@tailwindcss/typography'), 8 | ], 9 | } 10 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | const { safeList } = require("./dist/js/utils/safelist.js"); 2 | 3 | /** @type {import('tailwindcss').Config} */ 4 | module.exports = { 5 | safelist: process.env.NODE_ENV === "production" ? safeList : [], 6 | content: 7 | process.env.NODE_ENV === "production" 8 | ? [{ raw: "" }] 9 | : ["./components/**/*.{html,js}", "./experiments/**/*.{html,js}"], 10 | darkMode: "class", 11 | theme: { 12 | extend: {}, 13 | }, 14 | plugins: [require("./dist/js")], 15 | }; 16 | --------------------------------------------------------------------------------