├── .nvmrc ├── logo.png ├── packages ├── css │ ├── src │ │ ├── components │ │ │ ├── Forms │ │ │ │ ├── index.ts │ │ │ │ └── Button │ │ │ │ │ ├── index.story.svelte │ │ │ │ │ ├── index.story.vue │ │ │ │ │ └── index.ts │ │ │ ├── Feedback │ │ │ │ ├── index.ts │ │ │ │ └── Spinner │ │ │ │ │ └── index.ts │ │ │ ├── Utility │ │ │ │ ├── index.ts │ │ │ │ ├── Overlay │ │ │ │ │ └── index.ts │ │ │ │ └── Inputable │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── index.story.svelte │ │ │ │ │ └── index.story.vue │ │ │ ├── index.ts │ │ │ ├── Typography │ │ │ │ ├── index.ts │ │ │ │ ├── Link │ │ │ │ │ └── index.ts │ │ │ │ ├── Text │ │ │ │ │ └── index.ts │ │ │ │ ├── Label │ │ │ │ │ └── index.ts │ │ │ │ ├── Heading │ │ │ │ │ └── index.ts │ │ │ │ └── Content │ │ │ │ │ └── index.ts │ │ │ └── Layout │ │ │ │ ├── index.ts │ │ │ │ ├── Flex │ │ │ │ └── index.ts │ │ │ │ ├── Grid │ │ │ │ └── index.ts │ │ │ │ ├── Box │ │ │ │ └── index.ts │ │ │ │ ├── Stack │ │ │ │ └── index.ts │ │ │ │ ├── Skeleton │ │ │ │ └── index.ts │ │ │ │ └── Card │ │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── index.ts │ │ │ └── animation.ts │ │ ├── index.ts │ │ ├── types.ts │ │ └── theme │ │ │ ├── utils │ │ │ └── index.ts │ │ │ ├── colors │ │ │ └── index.ts │ │ │ └── index.ts │ ├── .svelte-kit │ │ ├── generated │ │ │ └── client │ │ │ │ ├── matchers.js │ │ │ │ ├── nodes │ │ │ │ ├── 0.js │ │ │ │ └── 1.js │ │ │ │ └── app.js │ │ ├── tsconfig.json │ │ └── ambient.d.ts │ ├── env.d.ts │ ├── svelte.config.js │ ├── .npmignore │ ├── histoire.config.ts │ ├── vite.config.js │ ├── tsup.config.ts │ ├── README.md │ └── package.json └── react │ ├── .ladle │ └── config.mjs │ ├── src │ ├── utils │ │ ├── index.ts │ │ ├── useDisclosure │ │ │ ├── index.tsx │ │ │ └── index.test.tsx │ │ ├── date │ │ │ ├── index.ts │ │ │ └── index.test.ts │ │ └── useCalendar │ │ │ └── index.tsx │ ├── components │ │ ├── Utility │ │ │ ├── index.ts │ │ │ ├── Overlay │ │ │ │ └── index.ts │ │ │ └── ShowableContent │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── Layout │ │ │ ├── Flex │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Grid │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── AspectRatio │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Card │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Skeleton │ │ │ │ ├── index.tsx │ │ │ │ └── index.stories.tsx │ │ │ ├── Box │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Container │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ ├── Stack │ │ │ │ ├── index.tsx │ │ │ │ └── index.stories.tsx │ │ │ ├── index.ts │ │ │ ├── SimpleGrid │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ └── Image │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ ├── Typography │ │ │ ├── Link │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Text │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Label │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Heading │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── index.ts │ │ │ └── Content │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ ├── Forms │ │ │ ├── Button │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Input │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Textarea │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── Select │ │ │ │ ├── index.ts │ │ │ │ └── index.stories.tsx │ │ │ ├── index.ts │ │ │ ├── Calendar │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ ├── Switch │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ ├── Checkbox │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ │ └── RadioGroup │ │ │ │ ├── index.stories.tsx │ │ │ │ └── index.tsx │ │ └── Feedback │ │ │ ├── index.ts │ │ │ ├── Spinner │ │ │ ├── index.tsx │ │ │ └── index.stories.tsx │ │ │ ├── Tooltip │ │ │ ├── index.stories.tsx │ │ │ └── index.tsx │ │ │ ├── Popover │ │ │ ├── index.stories.tsx │ │ │ └── index.tsx │ │ │ ├── Modal │ │ │ ├── index.ts │ │ │ └── index.stories.tsx │ │ │ └── Drawer │ │ │ ├── index.ts │ │ │ └── index.stories.tsx │ ├── assets │ │ └── icons │ │ │ └── chevron-down.svg │ ├── types.ts │ ├── theme.stories.tsx │ ├── index.ts │ └── index.stories.tsx │ ├── .babelrc │ ├── e2e │ ├── snapshot.spec.ts-snapshots │ │ ├── exoui--theme-chromium-linux.png │ │ ├── exoui--readme-chromium-linux.png │ │ ├── layout--box--default-chromium-linux.png │ │ ├── forms--button--default-chromium-linux.png │ │ ├── forms--button--loading-chromium-linux.png │ │ ├── forms--input--default-chromium-darwin.png │ │ ├── forms--input--default-chromium-linux.png │ │ ├── forms--select--default-chromium-linux.png │ │ ├── forms--switch--default-chromium-linux.png │ │ ├── layout--box--default-chromium-darwin.png │ │ ├── layout--card--default-chromium-darwin.png │ │ ├── layout--card--default-chromium-linux.png │ │ ├── layout--flex--default-chromium-darwin.png │ │ ├── layout--flex--default-chromium-linux.png │ │ ├── layout--grid--default-chromium-darwin.png │ │ ├── layout--grid--default-chromium-linux.png │ │ ├── layout--image--avatar-chromium-darwin.png │ │ ├── layout--image--avatar-chromium-linux.png │ │ ├── layout--image--default-chromium-linux.png │ │ ├── layout--stack--default-chromium-linux.png │ │ ├── feedback--drawer--default-chromium-linux.png │ │ ├── feedback--modal--default-chromium-darwin.png │ │ ├── feedback--modal--default-chromium-linux.png │ │ ├── forms--button--default-chromium-darwin.png │ │ ├── forms--button--loading-chromium-darwin.png │ │ ├── forms--calendar--default-chromium-darwin.png │ │ ├── forms--calendar--default-chromium-linux.png │ │ ├── forms--checkbox--default-chromium-darwin.png │ │ ├── forms--checkbox--default-chromium-linux.png │ │ ├── forms--select--default-chromium-darwin.png │ │ ├── forms--switch--default-chromium-darwin.png │ │ ├── forms--textarea--default-chromium-darwin.png │ │ ├── forms--textarea--default-chromium-linux.png │ │ ├── layout--image--default-chromium-darwin.png │ │ ├── layout--skeleton--default-chromium-linux.png │ │ ├── layout--stack--default-chromium-darwin.png │ │ ├── layout--stack--horizontal-chromium-linux.png │ │ ├── typography--link--default-chromium-linux.png │ │ ├── typography--text--default-chromium-linux.png │ │ ├── feedback--drawer--default-chromium-darwin.png │ │ ├── feedback--drawer--positions-chromium-linux.png │ │ ├── feedback--popover--default-chromium-darwin.png │ │ ├── feedback--popover--default-chromium-linux.png │ │ ├── feedback--spinner--default-chromium-darwin.png │ │ ├── feedback--spinner--default-chromium-linux.png │ │ ├── feedback--tooltip--default-chromium-darwin.png │ │ ├── feedback--tooltip--default-chromium-linux.png │ │ ├── forms--radio-group--default-chromium-linux.png │ │ ├── layout--container--default-chromium-darwin.png │ │ ├── layout--container--default-chromium-linux.png │ │ ├── layout--skeleton--default-chromium-darwin.png │ │ ├── layout--stack--horizontal-chromium-darwin.png │ │ ├── typography--label--default-chromium-darwin.png │ │ ├── typography--label--default-chromium-linux.png │ │ ├── typography--link--default-chromium-darwin.png │ │ ├── typography--text--default-chromium-darwin.png │ │ ├── feedback--drawer--positions-chromium-darwin.png │ │ ├── forms--button--scheme-variants-chromium-linux.png │ │ ├── forms--button--size-variants-chromium-darwin.png │ │ ├── forms--button--size-variants-chromium-linux.png │ │ ├── forms--radio-group--default-chromium-darwin.png │ │ ├── layout--aspect-ratio--default-chromium-darwin.png │ │ ├── layout--aspect-ratio--default-chromium-linux.png │ │ ├── layout--card--scheme-variants-chromium-darwin.png │ │ ├── layout--card--scheme-variants-chromium-linux.png │ │ ├── layout--image--gradient-avatar-chromium-linux.png │ │ ├── layout--simple-grid--default-chromium-darwin.png │ │ ├── layout--simple-grid--default-chromium-linux.png │ │ ├── typography--content--default-chromium-darwin.png │ │ ├── typography--content--default-chromium-linux.png │ │ ├── typography--heading--default-chromium-darwin.png │ │ ├── typography--heading--default-chromium-linux.png │ │ ├── forms--button--scheme-variants-chromium-darwin.png │ │ └── layout--image--gradient-avatar-chromium-darwin.png │ └── snapshot.spec.ts │ ├── README.md │ ├── .npmignore │ ├── tsup.config.ts │ ├── .gitignore │ ├── playwright.config.ts │ └── package.json ├── .prettierrc ├── .editorconfig ├── README.md ├── .gitignore ├── turbo.json ├── favicon.svg ├── package.json ├── .github └── workflows │ └── ci.yml └── logo.svg /.nvmrc: -------------------------------------------------------------------------------- 1 | v19.1.0 2 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/logo.png -------------------------------------------------------------------------------- /packages/css/src/components/Forms/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Button/index' 2 | -------------------------------------------------------------------------------- /packages/css/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * as animation from './animation' 2 | -------------------------------------------------------------------------------- /packages/css/.svelte-kit/generated/client/matchers.js: -------------------------------------------------------------------------------- 1 | export const matchers = {}; -------------------------------------------------------------------------------- /packages/css/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/css/src/components/Feedback/index.ts: -------------------------------------------------------------------------------- 1 | export { spinnerStyles } from './Spinner/index' 2 | -------------------------------------------------------------------------------- /packages/css/src/components/Utility/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Inputable/index' 2 | export * from './Overlay/index' 3 | -------------------------------------------------------------------------------- /packages/react/.ladle/config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | defaultStory: 'exoui--readme', 3 | base: '/exo-ui/' 4 | } 5 | -------------------------------------------------------------------------------- /packages/css/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components/index' 2 | export * from './utils/index' 3 | export * from './theme' 4 | -------------------------------------------------------------------------------- /packages/react/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { useDisclosure } from './useDisclosure' 2 | export { useCalendar } from './useCalendar' 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "trailingComma": "none", 4 | "singleQuote": true, 5 | "printWidth": 120, 6 | "tabWidth": 2 7 | } 8 | -------------------------------------------------------------------------------- /packages/react/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /packages/css/svelte.config.js: -------------------------------------------------------------------------------- 1 | import { vitePreprocess } from '@sveltejs/kit/vite' 2 | 3 | export default { 4 | preprocess: [vitePreprocess()] 5 | } 6 | -------------------------------------------------------------------------------- /packages/react/src/components/Utility/index.ts: -------------------------------------------------------------------------------- 1 | export { composeOverlay } from './Overlay/index' 2 | export { composeShowableContent } from './ShowableContent/index' 3 | -------------------------------------------------------------------------------- /packages/css/.svelte-kit/generated/client/nodes/0.js: -------------------------------------------------------------------------------- 1 | export { default as component } from "../../../../../../node_modules/@sveltejs/kit/src/runtime/components/layout.svelte"; -------------------------------------------------------------------------------- /packages/css/.svelte-kit/generated/client/nodes/1.js: -------------------------------------------------------------------------------- 1 | export { default as component } from "../../../../../../node_modules/@sveltejs/kit/src/runtime/components/error.svelte"; -------------------------------------------------------------------------------- /packages/css/.npmignore: -------------------------------------------------------------------------------- 1 | !dist 2 | .histoire 3 | .turbo 4 | node_modules 5 | src 6 | vite.config.js 7 | tsconfig.json 8 | svelte.config.js 9 | histoire.config.ts 10 | env.d.ts 11 | -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/exoui--theme-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/exoui--theme-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/exoui--readme-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/exoui--readme-chromium-linux.png -------------------------------------------------------------------------------- /packages/css/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Forms/index' 2 | export * from './Utility/index' 3 | export * from './Layout/index' 4 | export * from './Typography/index' 5 | export * from './Feedback/index' 6 | -------------------------------------------------------------------------------- /packages/react/README.md: -------------------------------------------------------------------------------- 1 | # ExoUI React 2 | 3 | Yet another React UI Library. Under construction. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | $ yarn add @mvr-studio/exo-ui 9 | ✨ Done in 3.52s. 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Heading/index' 2 | export * from './Label/index' 3 | export * from './Link/index' 4 | export * from './Text/index' 5 | export * from './Content/index' 6 | -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--box--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--box--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Forms/index' 2 | export * from './Layout/index' 3 | export * from './Feedback/index' 4 | export * from './Typography/index' 5 | export * from './Utility/index' 6 | -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--loading-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--loading-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--input--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--input--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--input--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--input--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--select--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--select--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--switch--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--switch--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--box--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--box--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--flex--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--flex--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--flex--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--flex--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--grid--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--grid--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--grid--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--grid--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--avatar-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--avatar-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--avatar-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--avatar-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--modal--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--modal--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--modal--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--modal--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--loading-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--loading-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--calendar--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--calendar--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--calendar--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--calendar--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--checkbox--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--checkbox--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--checkbox--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--checkbox--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--select--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--select--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--switch--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--switch--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--textarea--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--textarea--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--textarea--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--textarea--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--skeleton--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--skeleton--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--horizontal-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--horizontal-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--link--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--link--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--text--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--text--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--positions-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--positions-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--popover--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--popover--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--popover--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--popover--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--spinner--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--spinner--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--spinner--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--spinner--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--tooltip--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--tooltip--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--tooltip--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--tooltip--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--radio-group--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--radio-group--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--container--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--container--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--container--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--container--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--skeleton--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--skeleton--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--horizontal-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--stack--horizontal-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--label--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--label--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--label--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--label--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--link--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--link--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--text--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--text--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--positions-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/feedback--drawer--positions-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--scheme-variants-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--scheme-variants-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--size-variants-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--size-variants-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--size-variants-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--size-variants-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--radio-group--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--radio-group--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--aspect-ratio--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--aspect-ratio--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--aspect-ratio--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--aspect-ratio--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--scheme-variants-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--scheme-variants-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--scheme-variants-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--card--scheme-variants-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--gradient-avatar-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--gradient-avatar-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--simple-grid--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--simple-grid--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--simple-grid--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--simple-grid--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--content--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--content--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--content--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--content--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--heading--default-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--heading--default-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/typography--heading--default-chromium-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/typography--heading--default-chromium-linux.png -------------------------------------------------------------------------------- /packages/css/src/components/Layout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Box/index' 2 | export * from './Flex/index' 3 | export * from './Grid/index' 4 | export * from './Stack/index' 5 | export * from './Card/index' 6 | export * from './Skeleton/index' 7 | -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--scheme-variants-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/forms--button--scheme-variants-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--gradient-avatar-chromium-darwin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/berlinbnb/deneme2/HEAD/packages/react/e2e/snapshot.spec.ts-snapshots/layout--image--gradient-avatar-chromium-darwin.png -------------------------------------------------------------------------------- /packages/react/.npmignore: -------------------------------------------------------------------------------- 1 | !/dist 2 | /.ladle 3 | /.github 4 | /.storybook 5 | /build 6 | /coverage 7 | /node_modules 8 | /src 9 | /storybook-static 10 | /e2e 11 | .babelrc 12 | playwright.config.ts 13 | tsconfig.json 14 | /playwright-report 15 | -------------------------------------------------------------------------------- /packages/css/histoire.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'histoire' 2 | import { HstVue } from '@histoire/plugin-vue' 3 | import { HstSvelte } from '@histoire/plugin-svelte' 4 | 5 | export default defineConfig({ 6 | plugins: [HstVue(), HstSvelte()] 7 | }) 8 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Flex/index.ts: -------------------------------------------------------------------------------- 1 | import { flexStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeFlex = ({ styled }: ComponentFactory) => { 5 | return styled('div', flexStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Grid/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { gridStyles } from '@mvr-studio/exo-css' 3 | 4 | export const composeGrid = ({ styled }: ComponentFactory) => { 5 | return styled('div', gridStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Link/index.ts: -------------------------------------------------------------------------------- 1 | import { linkStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeLink = ({ styled }: ComponentFactory) => { 5 | return styled('a', linkStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Text/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { textStyles } from '@mvr-studio/exo-css' 3 | 4 | export const composeText = ({ styled }: ComponentFactory) => { 5 | return styled('p', textStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/css/vite.config.js: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue' 2 | import { svelte } from '@sveltejs/vite-plugin-svelte' 3 | 4 | export default { 5 | plugins: [vue(), svelte()], 6 | server: { 7 | fs: { 8 | allow: ['../../'] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/AspectRatio/index.ts: -------------------------------------------------------------------------------- 1 | import * as AspectRatio from '@radix-ui/react-aspect-ratio' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeAspectRatio = ({ styled }: ComponentFactory) => styled(AspectRatio.Root, {}) 5 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Button/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { buttonStyles } from '@mvr-studio/exo-css' 3 | 4 | export const composeButton = ({ styled }: ComponentFactory) => { 5 | return styled('button', buttonStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Label/index.ts: -------------------------------------------------------------------------------- 1 | import { labelStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeLabel = ({ styled }: ComponentFactory) => { 5 | return styled('label', labelStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Heading/index.ts: -------------------------------------------------------------------------------- 1 | import { headingStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeHeading = ({ styled }: ComponentFactory) => { 5 | return styled('h1', headingStyles) 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/index.ts: -------------------------------------------------------------------------------- 1 | export { composeLabel } from './Label/index' 2 | export { composeHeading } from './Heading/index' 3 | export { composeText } from './Text/index' 4 | export { composeLink } from './Link/index' 5 | export { composeContent } from './Content/index' 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/index.ts: -------------------------------------------------------------------------------- 1 | export { composeModal } from './Modal/index' 2 | export { composeDrawer } from './Drawer/index' 3 | export { composeTooltip } from './Tooltip/index' 4 | export { composePopover } from './Popover/index' 5 | export { composeSpinner } from './Spinner/index' 6 | -------------------------------------------------------------------------------- /packages/react/src/assets/icons/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Flex/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../Box' 3 | 4 | export const flexStyles = { 5 | ...boxStyles, 6 | display: 'flex' 7 | } 8 | 9 | export const composeFlexCss = ({ css }: ComposerFactory) => { 10 | return css(flexStyles) 11 | } 12 | -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Grid/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../Box' 3 | 4 | export const gridStyles = { 5 | ...boxStyles, 6 | display: 'grid' 7 | } 8 | 9 | export const composeGridCss = ({ css }: ComposerFactory) => { 10 | return css(gridStyles) 11 | } 12 | -------------------------------------------------------------------------------- /packages/css/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { css } from '@stitches/core' 2 | 3 | export type Color = string 4 | 5 | export interface CreateExpoThemeProps { 6 | primaryColor?: Color 7 | secondaryColor?: Color 8 | colors?: Record 9 | } 10 | 11 | export interface ComposerFactory { 12 | css: typeof css 13 | } 14 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/Link/index.ts: -------------------------------------------------------------------------------- 1 | import { boxStyles } from '../../' 2 | import { ComposerFactory } from '../../../types' 3 | 4 | export const linkStyles = { 5 | ...boxStyles, 6 | color: 'inherit' 7 | } 8 | 9 | export const composeLinkCss = ({ css }: ComposerFactory) => { 10 | return css(linkStyles) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Card/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { composeBox } from '../Box' 3 | import { cardStyles } from '@mvr-studio/exo-css' 4 | 5 | export const composeCard = ({ styled }: ComponentFactory) => { 6 | const Box = composeBox({ styled }) 7 | return styled(Box, cardStyles) 8 | } 9 | -------------------------------------------------------------------------------- /packages/react/src/components/Utility/Overlay/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import * as Dialog from '@radix-ui/react-dialog' 3 | import { overlayStyles } from '@mvr-studio/exo-css' 4 | 5 | export const composeOverlay = ({ styled }: ComponentFactory) => { 6 | return styled(Dialog.Overlay, overlayStyles) 7 | } 8 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Skeleton/index.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { skeletonStyles } from '@mvr-studio/exo-css' 3 | import { composeBox } from '../Box' 4 | 5 | export const composeSkeleton = ({ styled }: ComponentFactory) => { 6 | const Box = composeBox({ styled }) 7 | return styled(Box, skeletonStyles) 8 | } 9 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Spinner/index.tsx: -------------------------------------------------------------------------------- 1 | import { spinnerStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | import { composeBox } from '../../Layout/Box' 4 | 5 | export const composeSpinner = ({ styled }: ComponentFactory) => { 6 | const Box = composeBox({ styled }) 7 | return styled(Box, spinnerStyles) 8 | } 9 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Content/index.ts: -------------------------------------------------------------------------------- 1 | import { contentStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | import { composeBox } from '../../Layout' 4 | 5 | export const composeContent = ({ styled }: ComponentFactory) => { 6 | const Box = composeBox({ styled }) 7 | return styled(Box, contentStyles) 8 | } 9 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Input/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { inputableStyles } from '@mvr-studio/exo-css' 3 | 4 | interface ComposeInputProps extends ComponentFactory { 5 | type?: string 6 | } 7 | 8 | export const composeInput = ({ styled }: ComposeInputProps) => { 9 | return styled('input', inputableStyles) 10 | } 11 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/Text/index.ts: -------------------------------------------------------------------------------- 1 | import { boxStyles } from '../../' 2 | import { ComposerFactory } from '../../../types' 3 | 4 | export const textStyles = { 5 | ...boxStyles, 6 | color: 'var(--default-text-body-color)', 7 | lineHeight: '$tall' 8 | } 9 | 10 | export const composeTextCss = ({ css }: ComposerFactory) => { 11 | return css(textStyles) 12 | } 13 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Spinner/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Spinner } = createExoUi() 7 | return 8 | } 9 | 10 | export default { 11 | title: 'Feedback / Spinner' 12 | } satisfies StoryDefault 13 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Label/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Label } = createExoUi() 7 | return Email Address 8 | } 9 | 10 | export default { 11 | title: 'Typography / Label' 12 | } satisfies StoryDefault 13 | -------------------------------------------------------------------------------- /packages/css/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig([ 4 | { 5 | name: 'main', 6 | entry: ['./src/index.ts'], 7 | outDir: './dist', 8 | format: ['esm', 'cjs'], 9 | sourcemap: true, 10 | clean: true, 11 | bundle: true, 12 | dts: { 13 | compilerOptions: { 14 | moduleResolution: 'Node' 15 | } 16 | } 17 | } 18 | ]) 19 | -------------------------------------------------------------------------------- /packages/react/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig([ 4 | { 5 | name: 'main', 6 | entry: ['./src/index.ts'], 7 | outDir: './dist', 8 | format: ['esm', 'cjs'], 9 | sourcemap: true, 10 | clean: true, 11 | bundle: true, 12 | dts: { 13 | compilerOptions: { 14 | moduleResolution: 'Node' 15 | } 16 | } 17 | } 18 | ]) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2 | 3 |  4 | 5 | --- 6 | 7 | [](https://codeclimate.com/github/mvr-studio/exo-ui/maintainability) 8 | 9 | > Yet another UI Library. Under construction. 10 | 11 | --- 12 | 13 | [Roadmap](https://github.com/orgs/mvr-studio/projects/1/views/1) | 14 | [Maintained by MVR Studio](https://mvr.studio) 15 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/Label/index.ts: -------------------------------------------------------------------------------- 1 | import { boxStyles } from '../../' 2 | import { ComposerFactory } from '../../../types' 3 | 4 | export const labelStyles = { 5 | ...boxStyles, 6 | fontSize: '14px', 7 | fontWeight: '$semibold', 8 | '&[for]': { 9 | cursor: 'pointer' 10 | } 11 | } 12 | 13 | export const composeLabelCss = ({ css }: ComposerFactory) => { 14 | return css(labelStyles) 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Box/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType } from 'react' 2 | import { ComponentFactory } from '../../../types' 3 | import { boxStyles } from '@mvr-studio/exo-css' 4 | 5 | interface BoxFactory extends ComponentFactory { 6 | type?: string 7 | } 8 | 9 | export const composeBox = ({ styled, type = 'div' }: BoxFactory) => { 10 | return styled(type as unknown as ComponentType, boxStyles) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Textarea/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { inputableStyles } from '@mvr-studio/exo-css' 3 | 4 | interface ComposeTextareaProps extends ComponentFactory { 5 | type?: string 6 | } 7 | 8 | export const composeTextarea = ({ styled }: ComposeTextareaProps) => { 9 | return styled('textarea', { 10 | ...inputableStyles, 11 | resize: 'none' 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Skeleton/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Skeleton } = createExoUi() 7 | return 8 | } 9 | 10 | export default { 11 | title: 'Layout / Skeleton' 12 | } satisfies StoryDefault 13 | -------------------------------------------------------------------------------- /packages/css/.svelte-kit/generated/client/app.js: -------------------------------------------------------------------------------- 1 | export { matchers } from './matchers.js'; 2 | 3 | export const nodes = [ 4 | () => import('./nodes/0'), 5 | () => import('./nodes/1') 6 | ]; 7 | 8 | export const server_loads = []; 9 | 10 | export const dictionary = { 11 | 12 | }; 13 | 14 | export const hooks = { 15 | handleError: (({ error }) => { console.error(error) }), 16 | }; 17 | 18 | export { default as root } from '../root.svelte'; -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Box/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | 3 | export const boxStyles = { 4 | appearance: 'none', 5 | fontFamily: '$body', 6 | fontSize: '$md', 7 | color: 'var(--default-text-color)', 8 | padding: 0, 9 | margin: 0, 10 | boxSizing: 'border-box', 11 | width: '100%' 12 | } 13 | 14 | export const composeBoxCss = ({ css }: ComposerFactory) => { 15 | return css(boxStyles) 16 | } 17 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Container/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Container } = createExoUi() 7 | return Box 8 | } 9 | 10 | export default { 11 | title: 'Layout / Container' 12 | } satisfies StoryDefault 13 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Select/index.ts: -------------------------------------------------------------------------------- 1 | import { inputableStyles } from '@mvr-studio/exo-css' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | export const composeSelect = ({ styled }: ComponentFactory) => { 5 | return styled('select', { 6 | ...inputableStyles, 7 | background: 'var(--select-background)', 8 | backgroundRepeat: 'no-repeat', 9 | backgroundPosition: `calc(100% - 0.75rem) center` 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/index.ts: -------------------------------------------------------------------------------- 1 | export { composeButton } from './Button/index' 2 | export { composeInput } from './Input/index' 3 | export { composeSelect } from './Select/index' 4 | export { composeCheckbox } from './Checkbox/index' 5 | export { composeRadioGroup } from './RadioGroup/index' 6 | export { composeCalendar } from './Calendar/index' 7 | export { composeSwitch } from './Switch/index' 8 | export { composeTextarea } from './Textarea/index' 9 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Stack/index.tsx: -------------------------------------------------------------------------------- 1 | import { ComponentFactory } from '../../../types' 2 | import { stackStyles } from '@mvr-studio/exo-css' 3 | 4 | export const composeStack = ({ styled }: ComponentFactory) => { 5 | return styled('div', stackStyles) 6 | } 7 | 8 | export const composeHStack = ({ styled }: ComponentFactory) => { 9 | const Stack = composeStack({ styled }) 10 | return styled(Stack, { flexDirection: 'row' }) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Box/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Box } = createExoUi() 7 | return Box 8 | } 9 | 10 | export default { 11 | title: 'Layout / Box' 12 | } satisfies StoryDefault 13 | -------------------------------------------------------------------------------- /packages/react/src/utils/useDisclosure/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | export const useDisclosure = (defaultIsOpen = false) => { 4 | const [isOpen, setIsOpen] = useState(defaultIsOpen) 5 | const onClose = () => setIsOpen(false) 6 | const onOpen = () => setIsOpen(true) 7 | const onToggle = () => setIsOpen(!isOpen) 8 | return { 9 | isOpen, 10 | onClose, 11 | onOpen, 12 | onToggle, 13 | setIsOpen 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Calendar/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Calendar, Box } = createExoUi() 7 | return ( 8 | 9 | 10 | 11 | ) 12 | } 13 | 14 | export default { 15 | title: 'Forms / Calendar' 16 | } satisfies StoryDefault 17 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Link/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Link } = createExoUi() 7 | return ( 8 | 9 | Link 10 | 11 | ) 12 | } 13 | 14 | export default { 15 | title: 'Typography / Link' 16 | } satisfies StoryDefault 17 | -------------------------------------------------------------------------------- /packages/react/.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | build 3 | !e2e 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | pnpm-debug.log* 12 | lerna-debug.log* 13 | storybook-static 14 | 15 | node_modules 16 | dist 17 | dist-ssr 18 | *.local 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .DS_Store 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | /test-results/ 31 | /playwright-report/ 32 | /playwright/.cache/ 33 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Tooltip/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Button, Tooltip } = createExoUi() 7 | return ( 8 | 9 | Hover it 10 | 11 | ) 12 | } 13 | 14 | export default { 15 | title: 'Feedback / Tooltip' 16 | } satisfies StoryDefault 17 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Input/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Input, Label, Stack } = createExoUi() 7 | return ( 8 | 9 | Email Address 10 | 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Forms / Input' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Textarea/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Textarea, Label, Stack } = createExoUi() 7 | return ( 8 | 9 | Bio 10 | 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Forms / Textarea' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/css/src/theme/utils/index.ts: -------------------------------------------------------------------------------- 1 | const utils = { 2 | paddingX: (value: string | number) => ({ 3 | paddingLeft: value, 4 | paddingRight: value 5 | }), 6 | paddingY: (value: string | number) => ({ 7 | paddingTop: value, 8 | paddingBottom: value 9 | }), 10 | marginX: (value: string | number) => ({ 11 | marginLeft: value, 12 | marginRight: value 13 | }), 14 | marginY: (value: string | number) => ({ 15 | marginTop: value, 16 | marginBottom: value 17 | }) 18 | } 19 | 20 | export default utils 21 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/Heading/index.ts: -------------------------------------------------------------------------------- 1 | import { boxStyles } from '../../' 2 | import { ComposerFactory } from '../../../types' 3 | 4 | export const headingStyles = { 5 | ...boxStyles, 6 | fontWeight: '$bold', 7 | fontSize: '$2xl', 8 | variants: { 9 | size: { 10 | xl: { 11 | fontSize: '$xl' 12 | }, 13 | lg: { 14 | fontSize: '$lg' 15 | } 16 | } 17 | } 18 | } 19 | 20 | export const composeHeadingCss = ({ css }: ComposerFactory) => { 21 | return css(headingStyles) 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | dist 4 | 5 | # dependencies 6 | node_modules 7 | .pnp 8 | .pnp.js 9 | 10 | # testing 11 | coverage 12 | 13 | # next.js 14 | .next/ 15 | out/ 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 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # turbo 35 | .turbo 36 | -------------------------------------------------------------------------------- /packages/css/src/components/Utility/Overlay/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { animation } from '../../../utils' 3 | import { boxStyles } from '../../Layout' 4 | 5 | export const overlayStyles = { 6 | ...boxStyles, 7 | position: 'fixed', 8 | inset: 0, 9 | backgroundColor: 'rgba(0, 0, 0, 0.1)', 10 | animation: `${animation.fadeIn} 0.2s cubic-bezier(0.16, 1, 0.3, 1)`, 11 | zIndex: 1 12 | } 13 | 14 | export const composeOverlayCss = ({ css }: ComposerFactory) => { 15 | return css(overlayStyles) 16 | } 17 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Content/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Content } = createExoUi() 7 | return ( 8 | 9 | Main header 10 | Some Text 11 | Another header 12 | Some more text 13 | 14 | ) 15 | } 16 | 17 | export default { 18 | title: 'Typography / Content' 19 | } satisfies StoryDefault 20 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/index.ts: -------------------------------------------------------------------------------- 1 | export { composeBox } from './Box/index' 2 | export { composeFlex } from './Flex/index' 3 | export { composeStack, composeHStack } from './Stack/index' 4 | export { composeAspectRatio } from './AspectRatio/index' 5 | export { composeGrid } from './Grid/index' 6 | export { composeSimpleGrid } from './SimpleGrid/index' 7 | export { composeImage } from './Image/index' 8 | export { composeContainer } from './Container/index' 9 | export { composeCard } from './Card/index' 10 | export { composeSkeleton } from './Skeleton/index' 11 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["**/.env.*local"], 4 | "pipeline": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "outputs": ["dist/**", ".next/**", "!.next/cache/**"] 8 | }, 9 | "lint": { 10 | "outputs": [] 11 | }, 12 | "story:dev": { 13 | "cache": false 14 | }, 15 | "story:build": { 16 | "outputs": [] 17 | }, 18 | "test:unit": { 19 | "outputs": [] 20 | }, 21 | "test:e2e": { 22 | "outputs": [] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Stack/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../Box' 3 | 4 | export const stackStyles = { 5 | ...boxStyles, 6 | display: 'flex', 7 | flexDirection: 'column', 8 | justifyContent: 'flex-start', 9 | alignItems: 'flex-start', 10 | gap: '$sm', 11 | variants: { 12 | direction: { 13 | horizontal: { 14 | flexDirection: 'row' 15 | } 16 | } 17 | } 18 | } 19 | 20 | export const composeStackCss = ({ css }: ComposerFactory) => { 21 | return css(stackStyles) 22 | } 23 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Switch/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Switch, Stack, Label } = createExoUi() 7 | return ( 8 | 9 | 10 | Color Mode 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Forms / Switch' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Popover/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Box, Button, Popover, Text } = createExoUi() 7 | return ( 8 | 9 | Hidden content}> 10 | Click it 11 | 12 | 13 | ) 14 | } 15 | 16 | export default { 17 | title: 'Feedback / Popover' 18 | } satisfies StoryDefault 19 | -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Skeleton/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { loading } from '../../../utils/animation' 3 | import { boxStyles } from '../Box' 4 | 5 | export const skeletonStyles = { 6 | ...boxStyles, 7 | borderRadius: '$lg', 8 | background: 9 | 'linear-gradient(90deg, var(--outline-color-light) 40%, var(--skeleton-highlight), var(--outline-color-light) 60%) right / 300% 100%', 10 | animation: `${loading} 1s linear infinite` 11 | } 12 | 13 | export const composeSkeletonCss = ({ css }: ComposerFactory) => { 14 | return css(skeletonStyles) 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Select/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Select, Stack, Label } = createExoUi() 7 | return ( 8 | 9 | Preferred Color 10 | 11 | red 12 | blue 13 | 14 | 15 | ) 16 | } 17 | 18 | export default { 19 | title: 'Forms / Select' 20 | } satisfies StoryDefault 21 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Checkbox/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Checkbox, Stack, Label } = createExoUi() 7 | return ( 8 | 9 | 10 | I accept Terms and Conditions. 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Forms / Checkbox' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Heading/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Heading, Stack } = createExoUi() 7 | return ( 8 | 9 | Test 10 | 11 | Test 12 | 13 | 14 | Test 15 | 16 | 17 | ) 18 | } 19 | 20 | export default { 21 | title: 'Typography / Heading' 22 | } satisfies StoryDefault 23 | -------------------------------------------------------------------------------- /favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Grid/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Grid, Box } = createExoUi() 7 | return ( 8 | 9 | Box 10 | Box 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Layout / Grid' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/css/src/theme/colors/index.ts: -------------------------------------------------------------------------------- 1 | import chroma from 'chroma-js' 2 | import { Color } from '../../types' 3 | 4 | const COLOR_SCALE_BREAKPOINTS = [0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9] 5 | 6 | export const createColorScale = (prefix: string, color: Color): Record => { 7 | const colorScale = {} as Record 8 | const sanitizedColor = chroma(color).hex() 9 | const breakpointToColor = chroma.scale(['#ffffff', sanitizedColor, '#000000']) 10 | COLOR_SCALE_BREAKPOINTS.forEach((value) => { 11 | const index = `${prefix}${value * 1000}` 12 | colorScale[index] = breakpointToColor(value).hex() 13 | }) 14 | return colorScale 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/Utility/ShowableContent/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType } from 'react' 2 | import { ComponentFactory } from '../../../types' 3 | 4 | interface ShowableContentProps extends ComponentFactory { 5 | baseComponent: ComponentType 6 | } 7 | 8 | export const composeShowableContent = ({ styled, baseComponent }: ShowableContentProps) => 9 | styled(baseComponent, { 10 | display: 'flex', 11 | position: 'relative', 12 | justifyContent: 'center', 13 | alignItems: 'center', 14 | backgroundColor: 'var(--background-e2)', 15 | boxShadow: '$tooltip', 16 | paddingX: '$md', 17 | paddingY: '$sm', 18 | borderRadius: '$md' 19 | }) 20 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/SimpleGrid/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { SimpleGrid, Box } = createExoUi() 7 | return ( 8 | 9 | Box 10 | Box 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Layout / Simple Grid' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/css/src/components/Layout/Card/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../Box' 3 | 4 | export const cardStyles = { 5 | ...boxStyles, 6 | border: '1px solid', 7 | borderColor: 'var(--outline-color)', 8 | borderRadius: '$lg', 9 | variants: { 10 | scheme: { 11 | elevated: { 12 | borderColor: 'transparent', 13 | boxShadow: '$elevated' 14 | }, 15 | filled: { 16 | backgroundColor: 'var(--outline-color-light)', 17 | borderColor: 'var(--outline-color-light)' 18 | } 19 | } 20 | } 21 | } 22 | 23 | export const composeCardCss = ({ css }: ComposerFactory) => { 24 | return css(cardStyles) 25 | } 26 | -------------------------------------------------------------------------------- /packages/css/src/components/Feedback/Spinner/index.ts: -------------------------------------------------------------------------------- 1 | import { prixClipFix, rotate } from '../../../utils/animation' 2 | import { boxStyles } from '../../Layout' 3 | 4 | export const spinnerStyles = { 5 | ...boxStyles, 6 | maxWidth: '3rem', 7 | width: '100%', 8 | maxHeight: '3rem', 9 | height: '100%', 10 | borderRadius: '50%', 11 | position: 'relative', 12 | animation: `${rotate} 1s linear infinite`, 13 | '&:before': { 14 | content: '', 15 | boxSizing: 'border-box', 16 | position: 'absolute', 17 | inset: 0, 18 | borderRadius: '50%', 19 | border: '5px solid', 20 | borderColor: 'var(--checkbox-indicator)', 21 | animation: `${prixClipFix} 2s linear infinite` 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/AspectRatio/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Box, AspectRatio } = createExoUi() 7 | return ( 8 | 9 | 18 | Aspect Ratio: 3 19 | 20 | 21 | ) 22 | } 23 | 24 | export default { 25 | title: 'Layout / Aspect Ratio' 26 | } satisfies StoryDefault 27 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Flex/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Box, Flex } = createExoUi() 7 | return ( 8 | 9 | Space 10 | Between 11 | 12 | ) 13 | } 14 | 15 | export default { 16 | title: 'Layout / Flex' 17 | } satisfies StoryDefault 18 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Stack/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Stack } = createExoUi() 7 | return ( 8 | 9 | First element 10 | Second element 11 | 12 | ) 13 | } 14 | 15 | export const Horizontal: Story = () => { 16 | const { HStack } = createExoUi() 17 | return ( 18 | 19 | First element 20 | Second element 21 | 22 | ) 23 | } 24 | 25 | export default { 26 | title: 'Layout / Stack' 27 | } satisfies StoryDefault 28 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Card/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Card } = createExoUi() 7 | return Card 8 | } 9 | 10 | export const SchemeVariants: Story = () => { 11 | const { Card, Stack } = createExoUi() 12 | return ( 13 | 14 | 15 | Elevated 16 | 17 | 18 | Filled 19 | 20 | 21 | ) 22 | } 23 | 24 | export default { 25 | title: 'Layout / Card' 26 | } satisfies StoryDefault 27 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exo-ui", 3 | "version": "0.0.0", 4 | "private": true, 5 | "author": "Tomasz Marciniak ", 6 | "workspaces": [ 7 | "packages/*" 8 | ], 9 | "scripts": { 10 | "build": "turbo run build", 11 | "story:dev": "turbo run story:dev", 12 | "story:build": "turbo run story:build", 13 | "test:unit": "turbo run test:unit", 14 | "test:e2e": "turbo run test:e2e", 15 | "lint": "turbo run lint", 16 | "format": "prettier --write \"**/*.{ts,tsx,md}\"" 17 | }, 18 | "devDependencies": { 19 | "prettier": "^2.8.7", 20 | "tsup": "^6.7.0", 21 | "turbo": "latest", 22 | "typescript": "^5.0.4" 23 | }, 24 | "engines": { 25 | "node": ">=14.0.0" 26 | }, 27 | "dependencies": {}, 28 | "packageManager": "yarn@1.22.19" 29 | } 30 | -------------------------------------------------------------------------------- /packages/react/src/types.ts: -------------------------------------------------------------------------------- 1 | import { css } from '@stitches/react' 2 | import type Stitches from '@stitches/react/types/stitches' 3 | 4 | export enum Month { 5 | JANUARY, 6 | FEBRUARY, 7 | MARCH, 8 | APRIL, 9 | MAY, 10 | JUNE, 11 | JULY, 12 | AUGUST, 13 | SEPTEMBER, 14 | OCTOBER, 15 | NOVEMBER, 16 | DECEMBER 17 | } 18 | 19 | export enum Day { 20 | SUNDAY, 21 | MONDAY, 22 | TUESDAY, 23 | WEDNESDAY, 24 | THURSDAY, 25 | FRIDAY, 26 | SATURDAY 27 | } 28 | 29 | export type Color = string 30 | 31 | export interface CreateExpoThemeProps { 32 | primaryColor?: Color 33 | secondaryColor?: Color 34 | colors?: Record 35 | } 36 | 37 | export type Styled = Stitches['styled'] 38 | export interface ComponentFactory { 39 | styled: Styled 40 | css?: typeof css | any 41 | theme?: any 42 | } 43 | -------------------------------------------------------------------------------- /packages/css/src/components/Utility/Inputable/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../../Layout' 3 | 4 | export const inputableStyles = { 5 | ...boxStyles, 6 | display: 'block', 7 | width: '100%', 8 | borderRadius: '$md', 9 | paddingLeft: '$md', 10 | paddingRight: '$md', 11 | paddingTop: '$sm', 12 | paddingBottom: '$sm', 13 | border: 'none', 14 | boxShadow: '$inputDefault', 15 | outline: 'none', 16 | transition: 'box-shadow 0.3s ease-in-out', 17 | backgroundColor: 'var(--default-input-background)', 18 | '&:hover': { boxShadow: '$inputHover' }, 19 | '&:focus': { boxShadow: '$inputFocus' }, 20 | '&::selection': { backgroundColor: '$gray800', color: 'white' } 21 | } 22 | 23 | export const composeInputableCss = ({ css }: ComposerFactory) => { 24 | return css(inputableStyles) 25 | } 26 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Container/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { ComponentFactory } from '../../../types' 3 | import { composeBox } from '../Box' 4 | import { composeFlex } from '../Flex' 5 | 6 | export const composeContainer = ({ styled }: ComponentFactory) => { 7 | const Box = composeBox({ styled }) 8 | const Flex = composeFlex({ styled }) 9 | type FlexProps = React.ComponentProps 10 | 11 | return ({ children, ...flexProps }: FlexProps) => ( 12 | 23 | {children} 24 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /packages/react/src/components/Typography/Text/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Text, Stack } = createExoUi() 7 | return ( 8 | 9 | 10 | Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem 11 | aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. 12 | 13 | 14 | Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores 15 | eos qui ratione voluptatem sequi nesciunt. 16 | 17 | 18 | ) 19 | } 20 | 21 | export default { 22 | title: 'Typography / Text' 23 | } satisfies StoryDefault 24 | -------------------------------------------------------------------------------- /packages/css/.svelte-kit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": {}, 4 | "rootDirs": [ 5 | "..", 6 | "./types" 7 | ], 8 | "importsNotUsedAsValues": "error", 9 | "isolatedModules": true, 10 | "preserveValueImports": true, 11 | "lib": [ 12 | "esnext", 13 | "DOM", 14 | "DOM.Iterable" 15 | ], 16 | "moduleResolution": "node", 17 | "module": "esnext", 18 | "target": "esnext", 19 | "ignoreDeprecations": "5.0" 20 | }, 21 | "include": [ 22 | "ambient.d.ts", 23 | "./types/**/$types.d.ts", 24 | "../vite.config.ts", 25 | "../src/**/*.js", 26 | "../src/**/*.ts", 27 | "../src/**/*.svelte", 28 | "../tests/**/*.js", 29 | "../tests/**/*.ts", 30 | "../tests/**/*.svelte" 31 | ], 32 | "exclude": [ 33 | "../node_modules/**", 34 | "./[!ambient.d.ts]**", 35 | "../src/service-worker.js", 36 | "../src/service-worker.ts", 37 | "../src/service-worker.d.ts" 38 | ] 39 | } -------------------------------------------------------------------------------- /packages/react/src/components/Forms/RadioGroup/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { RadioGroup, Stack, Label } = createExoUi() 7 | return ( 8 | 9 | 10 | 11 | Default 12 | 13 | 14 | 15 | Comfortable 16 | 17 | 18 | ) 19 | } 20 | 21 | export default { 22 | title: 'Forms / Radio Group' 23 | } satisfies StoryDefault 24 | -------------------------------------------------------------------------------- /packages/css/src/components/Typography/Content/index.ts: -------------------------------------------------------------------------------- 1 | import { headingStyles, labelStyles, linkStyles, textStyles } from '..' 2 | import { ComposerFactory } from '../../../types' 3 | import { boxStyles } from '../../Layout' 4 | 5 | export const contentStyles = { 6 | ...boxStyles, 7 | '*': { 8 | marginTop: '$sm' 9 | }, 10 | h1: { 11 | ...headingStyles, 12 | marginTop: '$sm', 13 | fontSize: '2rem' 14 | }, 15 | h2: { 16 | ...headingStyles, 17 | marginTop: '$sm', 18 | fontSize: '1.5rem' 19 | }, 20 | h3: { 21 | ...headingStyles, 22 | marginTop: '$sm', 23 | fontSize: '1.25rem' 24 | }, 25 | p: { ...textStyles, marginTop: '$sm' }, 26 | a: { 27 | ...linkStyles, 28 | marginTop: '$sm', 29 | color: 'var(--link-color)' 30 | }, 31 | label: { ...labelStyles } 32 | } 33 | 34 | export const composeContentCss = ({ css }: ComposerFactory) => { 35 | return css(contentStyles) 36 | } 37 | -------------------------------------------------------------------------------- /packages/css/src/components/Forms/Button/index.story.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | Send 15 | Send 16 | Send 17 | 18 | 19 | Send 20 | Send 21 | Send 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /packages/react/e2e/snapshot.spec.ts: -------------------------------------------------------------------------------- 1 | import { test, expect } from '@playwright/test' 2 | import fetch from 'sync-fetch' 3 | 4 | const TESTABLE_CATEGORIES = ['Feedback', 'Forms', 'Layout', 'Typography'] 5 | const SKIP_STORIES = ['feedback--spinner--default', 'forms--button--loading'] 6 | 7 | const url = 'http://localhost:61000/exo-ui' 8 | 9 | const stories = fetch(`${url}/meta.json`).json().stories 10 | const testableStories = Object.entries(stories) 11 | .filter(([, meta]: any) => TESTABLE_CATEGORIES.includes(meta?.levels?.[0])) 12 | .map(([name]) => name) 13 | 14 | testableStories.forEach((storyKey) => { 15 | if (SKIP_STORIES.includes(storyKey)) return 16 | test(`${storyKey} - compare snapshots`, async ({ page }) => { 17 | await page.goto(`${url}/?story=${storyKey}&mode=preview`) 18 | await page.waitForSelector('[data-storyloaded]') 19 | await expect(page).toHaveScreenshot(`${storyKey}.png`, { maxDiffPixelRatio: 0.1 }) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /packages/css/src/components/Forms/Button/index.story.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Send 6 | Send 7 | Send 8 | 9 | 10 | Send 11 | Send 12 | Send 13 | 14 | 15 | 16 | 17 | 18 | 30 | -------------------------------------------------------------------------------- /packages/css/src/components/Utility/Inputable/index.story.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Red 26 | Blue 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /packages/react/src/utils/date/index.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs' 2 | import isBetween from 'dayjs/plugin/isBetween.js' 3 | dayjs.extend(isBetween) 4 | 5 | export interface InRangeProps { 6 | date: Date 7 | min: Date 8 | max: Date 9 | } 10 | 11 | export const inRange = ({ date, min, max }: InRangeProps) => { 12 | const selectedDate = dayjs(date) 13 | return selectedDate.isBetween(min, max, 'day', '[]') 14 | } 15 | 16 | export const clearTime = (date: Date) => 17 | dayjs(date).set('hour', 0).set('minute', 0).set('second', 0).set('millisecond', 0) 18 | 19 | export const eachOfInterval = ({ start, end, unit }: { start: Date; end: Date; unit: string }) => { 20 | const clearStart = clearTime(start) 21 | const clearEnd = clearTime(end) 22 | const diffOfUnit = clearEnd.diff(clearStart, unit as any) 23 | const diffSanitized = unit === 'week' ? Math.max(4, diffOfUnit) : diffOfUnit 24 | const diffArray = [...Array(diffSanitized + 1).keys()] 25 | return diffArray.map((diff) => clearStart.add(diff, unit as any).toDate()) 26 | } 27 | -------------------------------------------------------------------------------- /packages/react/src/utils/useDisclosure/index.test.tsx: -------------------------------------------------------------------------------- 1 | import { act } from '@testing-library/react' 2 | import { renderHook } from '@testing-library/react-hooks' 3 | import { useDisclosure } from '.' 4 | 5 | test('initial state', () => { 6 | const { result } = renderHook(() => useDisclosure()) 7 | 8 | expect(result.current.isOpen).toBe(false) 9 | }) 10 | 11 | test('onOpen()', () => { 12 | const { result } = renderHook(() => useDisclosure()) 13 | 14 | act(() => { 15 | result.current.onOpen() 16 | }) 17 | 18 | expect(result.current.isOpen).toBe(true) 19 | }) 20 | 21 | test('onClose()', () => { 22 | const { result } = renderHook(() => useDisclosure()) 23 | 24 | act(() => { 25 | result.current.onOpen() 26 | result.current.onClose() 27 | }) 28 | 29 | expect(result.current.isOpen).toBe(false) 30 | }) 31 | 32 | test('onToggle()', () => { 33 | const { result } = renderHook(() => useDisclosure()) 34 | 35 | act(() => { 36 | result.current.onToggle() 37 | }) 38 | 39 | expect(result.current.isOpen).toBe(true) 40 | }) 41 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Modal/index.ts: -------------------------------------------------------------------------------- 1 | import * as Dialog from '@radix-ui/react-dialog' 2 | import { composeOverlay } from '../../Utility' 3 | import { ComponentFactory } from '../../../types' 4 | import { animation } from '@mvr-studio/exo-css' 5 | 6 | export const composeModal = ({ styled }: ComponentFactory) => { 7 | const Overlay = composeOverlay({ styled }) 8 | const Content = styled(Dialog.Content, { 9 | unset: 'all', 10 | boxSizing: 'border-box', 11 | backgroundColor: 'var(--background-e1)', 12 | position: 'fixed', 13 | top: '50%', 14 | left: '50%', 15 | transform: 'translate(-50%, -50%)', 16 | maxWidth: '32rem', 17 | width: '100%', 18 | borderRadius: 0, 19 | padding: '$lg', 20 | animation: `${animation.fadeAndScale} 0.2s cubic-bezier(0.16, 1, 0.3, 1)`, 21 | zIndex: 2, 22 | boxShadow: '$md', 23 | '@sm': { 24 | borderRadius: '$md' 25 | } 26 | }) 27 | const Close = styled(Dialog.Close, {}) 28 | return { Root: Dialog.Root, Portal: Dialog.Portal, Trigger: Dialog.Trigger, Overlay, Content, Close } 29 | } 30 | -------------------------------------------------------------------------------- /packages/css/src/components/Utility/Inputable/index.story.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Red 17 | Blue 18 | 19 | 20 | 21 | 22 | 23 | 24 | 36 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/SimpleGrid/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { CSS } from '@stitches/react' 3 | import { ComponentFactory } from '../../../types' 4 | import { composeGrid } from '../Grid' 5 | 6 | const columnsToTemplate = (columns: number | Record) => { 7 | if (typeof columns === 'number') return `repeat(${columns}, minmax(0, 1fr))` 8 | const responsiveValues = Object.entries(columns).map(([key, value]) => [ 9 | key, 10 | { gridTemplateColumns: `repeat(${value}, minmax(0, 1fr))` } 11 | ]) 12 | return Object.fromEntries(responsiveValues) 13 | } 14 | 15 | export const composeSimpleGrid = ({ styled, css }: ComponentFactory) => { 16 | const Grid = composeGrid({ styled, css }) 17 | type SimpleGridProps = React.ComponentProps & { 18 | columns: number 19 | children: React.ReactNode 20 | css: CSS 21 | } 22 | return ({ children, columns, css, ...rest }: SimpleGridProps) => { 23 | const gridTemplateColumns = columnsToTemplate(columns) 24 | const simpleGridCss = { ...css, ...gridTemplateColumns } 25 | return ( 26 | 27 | {children} 28 | 29 | ) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/css/README.md: -------------------------------------------------------------------------------- 1 | # ExoUI CSS 2 | 3 | Framework agnostic CSS. 4 | 5 | ## Installation 6 | 7 | ```sh 8 | $ yarn add @mvr-studio/exo-css 9 | ✨ Done in 3.52s. 10 | ``` 11 | 12 | ## Usage 13 | 14 | ### Vue 15 | 16 | ```vue 17 | 18 | 19 | Click me 20 | Click me 21 | 22 | 23 | 35 | ``` 36 | 37 | ### Svelte 38 | 39 | ```svelte 40 | 45 | 46 | 47 | Click me 48 | Click me 49 | 50 | ``` 51 | -------------------------------------------------------------------------------- /packages/css/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mvr-studio/exo-css", 3 | "version": "0.0.9", 4 | "author": "Tomasz Marciniak ", 5 | "license": "MIT", 6 | "type": "module", 7 | "main": "dist/index.cjs", 8 | "module": "dist/index.js", 9 | "types": "dist/index.d.ts", 10 | "exports": { 11 | ".": { 12 | "types": "./dist/index.d.ts", 13 | "require": "./dist/index.cjs", 14 | "default": "./dist/index.js" 15 | } 16 | }, 17 | "scripts": { 18 | "build": "tsup", 19 | "dev": "tsup --watch", 20 | "story:dev": "histoire dev", 21 | "story:build": "histoire build", 22 | "story:preview": "histoire preview" 23 | }, 24 | "devDependencies": { 25 | "@esbuild-kit/esm-loader": "^2.5.5", 26 | "@histoire/plugin-svelte": "^0.15.9", 27 | "@histoire/plugin-vue": "^0.15.8", 28 | "@stitches/core": "^1.2.8", 29 | "@sveltejs/kit": "^1.15.2", 30 | "@sveltejs/vite-plugin-svelte": "^2.0.4", 31 | "@types/chroma-js": "^2.4.0", 32 | "@vitejs/plugin-vue": "^4.1.0", 33 | "cross-env": "^7.0.3", 34 | "histoire": "^0.15.9", 35 | "svelte": "^3.58.0", 36 | "vue": "^3.2.47" 37 | }, 38 | "dependencies": { 39 | "chroma-js": "^2.4.2", 40 | "polished": "^4.2.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Image/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Image } = createExoUi() 7 | return 8 | } 9 | 10 | export const Avatar: Story = () => { 11 | const { Image, Text } = createExoUi() 12 | return ( 13 | TM} 16 | /> 17 | ) 18 | } 19 | 20 | export const GradientAvatar: Story = () => { 21 | const { Image, Text } = createExoUi() 22 | return ( 23 | TM} 26 | gradient="addr_test1qztsw4wqagpn9jqh5wqkhupyx9k6q58k7x0ql8pku63ttdmak7sjf0mypuy30hc5usq657rjk57maxt6h4zcrhghssnscfvqd6" 27 | /> 28 | ) 29 | } 30 | 31 | export default { 32 | title: 'Layout / Image' 33 | } satisfies StoryDefault 34 | -------------------------------------------------------------------------------- /packages/react/src/theme.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { invert } from 'polished' 4 | import { createExoUi } from '../' 5 | 6 | export const Colors: Story = () => { 7 | const { Heading, Stack, Flex, theme, SimpleGrid, Text } = createExoUi() 8 | const colors = theme?.colors && Object.values(theme.colors) 9 | return ( 10 | 11 | Theme 12 | 13 | Colors 14 | 15 | 16 | {colors.map((color: any) => ( 17 | 28 | {color.token} 29 | 30 | ))} 31 | 32 | 33 | ) 34 | } 35 | 36 | export default { 37 | title: 'ExoUI / Theme' 38 | } satisfies StoryDefault 39 | -------------------------------------------------------------------------------- /packages/react/src/utils/date/index.test.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs' 2 | import { inRange, clearTime, eachOfInterval } from './' 3 | 4 | test('inRange()', () => { 5 | const min = dayjs().subtract(1, 'day').toDate() 6 | const max = dayjs().add(1, 'day').toDate() 7 | const dateInsideRange = dayjs().toDate() 8 | const dateOutsideRange = dayjs().subtract(7, 'days').toDate() 9 | expect(inRange({ date: dateInsideRange, min, max })).toBeTruthy() 10 | expect(inRange({ date: dateOutsideRange, min, max })).toBeFalsy() 11 | }) 12 | 13 | test('clearTime()', () => { 14 | const dateNow = new Date() 15 | const cleanDate = clearTime(dateNow) 16 | expect(cleanDate.hour()).toEqual(0) 17 | expect(cleanDate.minute()).toEqual(0) 18 | expect(cleanDate.second()).toEqual(0) 19 | expect(cleanDate.millisecond()).toEqual(0) 20 | }) 21 | 22 | test('eachOfInterval()', () => { 23 | const minDate = dayjs('2023-03-17').toDate() 24 | const maxDate = dayjs('2023-03-19').toDate() 25 | const yesterdayTomorrowTimeSpan = eachOfInterval({ start: minDate, end: maxDate, unit: 'day' }) 26 | expect(yesterdayTomorrowTimeSpan.length).toEqual(3) 27 | expect(yesterdayTomorrowTimeSpan[0]).toBeInstanceOf(Date) 28 | expect(yesterdayTomorrowTimeSpan[1]).toBeInstanceOf(Date) 29 | expect(yesterdayTomorrowTimeSpan[2]).toBeInstanceOf(Date) 30 | }) 31 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Tooltip/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import * as Tooltip from '@radix-ui/react-tooltip' 3 | import { ComponentFactory } from '../../../types' 4 | import { composeText } from '../../Typography' 5 | import { composeShowableContent } from '../../Utility' 6 | 7 | const composeTooltipArrow = ({ styled }: ComponentFactory) => styled(Tooltip.Arrow, { fill: 'var(--background-e2)' }) 8 | 9 | export interface TooltipProps { 10 | children: React.ReactNode 11 | label: string 12 | } 13 | 14 | export const composeTooltip = ({ styled, css }: ComponentFactory) => { 15 | const Text = composeText({ styled, css }) 16 | const TooltipContent = composeShowableContent({ styled, baseComponent: Tooltip.Content, css }) 17 | const TooltipArrow = composeTooltipArrow({ styled, css }) 18 | return ({ children, label }: TooltipProps) => ( 19 | 20 | 21 | {children} 22 | 23 | 24 | 25 | 26 | {label} 27 | 28 | 29 | 30 | 31 | 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /packages/react/playwright.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, devices } from '@playwright/test' 2 | 3 | /** 4 | * Read environment variables from file. 5 | * https://github.com/motdotla/dotenv 6 | */ 7 | // require('dotenv').config(); 8 | 9 | /** 10 | * See https://playwright.dev/docs/test-configuration. 11 | */ 12 | export default defineConfig({ 13 | testDir: './e2e', 14 | /* Run tests in files in parallel */ 15 | fullyParallel: true, 16 | /* Fail the build on CI if you accidentally left test.only in the source code. */ 17 | forbidOnly: !!process.env.CI, 18 | /* Retry on CI only */ 19 | retries: process.env.CI ? 2 : 0, 20 | /* Opt out of parallel tests on CI. */ 21 | workers: process.env.CI ? 1 : undefined, 22 | /* Reporter to use. See https://playwright.dev/docs/test-reporters */ 23 | reporter: 'html', 24 | /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ 25 | use: { 26 | trace: 'on-first-retry' 27 | }, 28 | 29 | /* Configure projects for major browsers */ 30 | projects: [ 31 | { 32 | name: 'chromium', 33 | use: { ...devices['Desktop Chrome'] } 34 | } 35 | ], 36 | /* Run your local dev server before starting the tests */ 37 | webServer: { 38 | command: 'yarn story:dev', 39 | url: 'http://localhost:61000/exo-ui', 40 | reuseExistingServer: !process.env.CI 41 | } 42 | }) 43 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuout Integration 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | pages: write 11 | id-token: write 12 | 13 | jobs: 14 | test_and_deploy_ladle: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v3 19 | - name: Use Node.js 19.1 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: 19.1 23 | - name: Install dependencies 24 | run: yarn install --frozen-lockfile 25 | - name: Build Dist 26 | run: yarn build 27 | - name: Run Unit 28 | run: yarn test:unit -- -- --coverage 29 | - name: Install Playwright Browsers 30 | run: npx playwright install --with-deps chromium 31 | - name: Run Playwright tests 32 | run: yarn test:e2e 33 | - uses: actions/upload-artifact@v3 34 | if: always() 35 | with: 36 | name: test-reports 37 | path: | 38 | packages/react/playwright-report/ 39 | packages/react/coverage/ 40 | - name: Build Ladle 41 | run: yarn story:build 42 | - name: Setup Pages 43 | uses: actions/configure-pages@v3 44 | - name: Upload artifact 45 | uses: actions/upload-pages-artifact@v1 46 | with: 47 | path: packages/react/build/ 48 | - name: Deploy to GitHub Pages 49 | id: deployment 50 | uses: actions/deploy-pages@v1 51 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Checkbox/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import * as Checkbox from '@radix-ui/react-checkbox' 3 | import { IconCheck } from '@tabler/icons-react' 4 | import { ComponentFactory } from '../../../types' 5 | 6 | const composeCheckboxRoot = ({ styled }: ComponentFactory) => { 7 | return styled(Checkbox.Root, { 8 | all: 'unset', 9 | boxSizing: 'border-box', 10 | backgroundColor: 'var(--checkbox-background)', 11 | width: '1.5rem', 12 | height: '1.5rem', 13 | borderRadius: '$md', 14 | display: 'flex', 15 | alignItems: 'center', 16 | justifyContent: 'center', 17 | boxShadow: '$checkable', 18 | cursor: 'pointer' 19 | }) 20 | } 21 | 22 | const composeCheckboxIndicator = ({ styled }: ComponentFactory) => { 23 | return styled(Checkbox.Indicator, { 24 | boxSizing: 'border-box', 25 | display: 'flex', 26 | justifyContent: 'center', 27 | alignItems: 'center', 28 | color: 'var(--checkbox-indicator)', 29 | width: '100%' 30 | }) 31 | } 32 | 33 | export const composeCheckbox = ({ styled }: ComponentFactory) => { 34 | const CheckboxRoot = composeCheckboxRoot({ styled }) 35 | const CheckboxIndicator = composeCheckboxIndicator({ styled }) 36 | type CheckboxRootProps = React.ComponentProps 37 | 38 | return (props: CheckboxRootProps) => ( 39 | 40 | 41 | 42 | 43 | 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Modal/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { IconX } from '@tabler/icons-react' 4 | import { createExoUi } from '../../..' 5 | 6 | export const Default: Story = () => { 7 | const { Box, Modal, Button, Stack, Heading, Text, Input, Label } = createExoUi() 8 | return ( 9 | 10 | 11 | 12 | Edit profile 13 | 14 | 15 | 16 | 17 | 18 | Edit profile 19 | Edit user's profile 20 | 21 | Name 22 | 23 | 24 | 25 | Save changes 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ) 38 | } 39 | 40 | export default { 41 | title: 'Feedback / Modal' 42 | } satisfies StoryDefault 43 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Button/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | 5 | export const Default: Story = () => { 6 | const { Box, Button } = createExoUi() 7 | return ( 8 | 9 | Submit 10 | 11 | ) 12 | } 13 | 14 | export const Loading: Story = () => { 15 | const { Box, Button, Spinner } = createExoUi() 16 | return ( 17 | 18 | 19 | 20 | 21 | 22 | ) 23 | } 24 | 25 | export const SizeVariants: Story = () => { 26 | const { Stack, Button } = createExoUi() 27 | return ( 28 | 29 | SM 30 | MD 31 | LG 32 | 33 | ) 34 | } 35 | 36 | export const SchemeVariants: Story = () => { 37 | const { Stack, Button } = createExoUi() 38 | return ( 39 | 40 | Standard 41 | Primary 42 | Outline 43 | Ghost 44 | 45 | ) 46 | } 47 | 48 | export default { 49 | title: 'Forms / Button' 50 | } satisfies StoryDefault 51 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Switch/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import * as Switch from '@radix-ui/react-switch' 3 | import { ComponentFactory } from '../../../types' 4 | 5 | const composeSwitchRoot = ({ styled }: ComponentFactory) => { 6 | return styled(Switch.Root, { 7 | all: 'unset', 8 | boxSizing: 'border-box', 9 | backgroundColor: 'var(--switch-background)', 10 | width: '3rem', 11 | height: '1.5rem', 12 | borderRadius: '9999px', 13 | cursor: 'pointer', 14 | WebkitTapHighlightColor: '$primary400', 15 | '&[data-state="checked"]': { backgroundColor: '$primary300' }, 16 | boxShadow: '$checkable' 17 | }) 18 | } 19 | 20 | const composeSwitchThumb = ({ styled }: ComponentFactory) => { 21 | return styled(Switch.Thumb, { 22 | boxSizing: 'border-box', 23 | width: '1.125rem', 24 | height: '1.125rem', 25 | display: 'block', 26 | color: '$primary400', 27 | backgroundColor: 'white', 28 | borderRadius: '100%', 29 | transition: 'transform 100ms', 30 | transform: 'translateX(0.25rem)', 31 | willChange: 'transform', 32 | '&[data-state="checked"]': { transform: 'translateX(1.375rem)' } 33 | }) 34 | } 35 | 36 | export const composeSwitch = ({ styled }: ComponentFactory) => { 37 | const SwitchRoot = composeSwitchRoot({ styled }) 38 | const CheckboxSwitchThumb = composeSwitchThumb({ styled }) 39 | type SwitchRootProps = React.ComponentProps 40 | 41 | return (props: SwitchRootProps) => ( 42 | 43 | 44 | 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Popover/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import * as Popover from '@radix-ui/react-popover' 3 | import { IconX } from '@tabler/icons-react' 4 | import { ComponentFactory } from '../../../types' 5 | import { composeButton } from '../../Forms' 6 | import { composeShowableContent } from '../../Utility' 7 | 8 | const composePopoverArrow = ({ styled }: ComponentFactory) => styled(Popover.Arrow, { fill: 'var(--background-e2)' }) 9 | const composePopoverClose = ({ styled }: ComponentFactory) => 10 | styled(Popover.Close, { all: 'unset', top: '0.25rem', right: '0.25rem', position: 'absolute' }) 11 | 12 | export interface PopoverProps { 13 | children: React.ReactNode 14 | content: React.ReactNode 15 | } 16 | 17 | export const composePopover = ({ styled, css }: ComponentFactory) => { 18 | const PopoverContent = composeShowableContent({ styled, baseComponent: Popover.Content }) 19 | const PopoverArrow = composePopoverArrow({ styled }) 20 | const PopoverClose = composePopoverClose({ styled }) 21 | const Button = composeButton({ styled, css }) 22 | return ({ children, content }: PopoverProps) => ( 23 | 24 | {children} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {content} 34 | 35 | 36 | 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /packages/react/src/components/Layout/Image/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react' 2 | import * as AvatarPrimitive from '@radix-ui/react-avatar' 3 | import { ComponentFactory } from '../../../types' 4 | import easyMeshGradient from 'easy-mesh-gradient' 5 | 6 | export const composeImage = ({ styled }: ComponentFactory) => { 7 | const ImageRoot = styled(AvatarPrimitive.Root, { 8 | unset: 'all', 9 | display: 'flex', 10 | alignItems: 'center', 11 | justifyContent: 'center', 12 | verticalAlign: 'middle' 13 | }) 14 | const Image = styled(AvatarPrimitive.Image, { 15 | unset: 'all', 16 | width: '100%', 17 | height: '100%', 18 | objectFit: 'cover', 19 | borderRadius: 'inherit' 20 | }) 21 | const ImageFallback = styled(AvatarPrimitive.Fallback, { 22 | unset: 'all', 23 | width: '100%', 24 | height: '100%', 25 | display: 'flex', 26 | alignItems: 'center', 27 | justifyContent: 'center' 28 | }) 29 | type ImageProps = React.ComponentProps & { 30 | src?: string 31 | fallback?: React.ReactNode 32 | fallbackDelay?: number 33 | // Seed for the gradient generation. 34 | gradient?: string | undefined 35 | } 36 | return ({ src, fallback, fallbackDelay = 600, gradient, ...rest }: ImageProps) => { 37 | const backgroundImage = useMemo(() => gradient && easyMeshGradient({ seed: gradient, pointCount: 3 }), [gradient]) 38 | console.log(backgroundImage) 39 | 40 | return ( 41 | 42 | {src && } 43 | {fallback && {fallback}} 44 | 45 | ) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/RadioGroup/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { ComponentFactory } from '../../../types' 3 | import * as RadioGroup from '@radix-ui/react-radio-group' 4 | import { IconPointFilled } from '@tabler/icons-react' 5 | 6 | const composeGroupRoot = ({ styled }: ComponentFactory) => 7 | styled(RadioGroup.Root, { 8 | display: 'flex', 9 | flexDirection: 'column', 10 | gap: 10 11 | }) 12 | 13 | const composeRadioGroupItem = ({ styled }: ComponentFactory) => 14 | styled(RadioGroup.Item, { 15 | all: 'unset', 16 | backgroundColor: 'var(--checkbox-background)', 17 | width: 25, 18 | height: 25, 19 | borderRadius: '100%', 20 | boxShadow: '$checkable', 21 | cursor: 'pointer' 22 | }) 23 | 24 | const composeRadioGroupIndicator = ({ styled }: ComponentFactory) => 25 | styled(RadioGroup.Indicator, { 26 | display: 'flex', 27 | alignItems: 'center', 28 | justifyContent: 'center', 29 | width: '100%', 30 | height: '100%', 31 | position: 'relative', 32 | color: 'var(--checkbox-indicator)' 33 | }) 34 | 35 | const composeItem = ({ styled }: ComponentFactory) => { 36 | const RadioGroupItemRoot = composeRadioGroupItem({ styled }) 37 | const RadioGroupIndicator = composeRadioGroupIndicator({ styled }) 38 | type RadioGroupItemProps = React.ComponentProps & { 39 | value: string 40 | } 41 | 42 | return (props: RadioGroupItemProps) => ( 43 | 44 | 45 | 46 | 47 | 48 | ) 49 | } 50 | 51 | export const composeRadioGroup = ({ styled }: ComponentFactory) => { 52 | const Root = composeGroupRoot({ styled }) 53 | const Item = composeItem({ styled }) 54 | return { Root, Item } 55 | } 56 | -------------------------------------------------------------------------------- /packages/css/src/utils/animation.ts: -------------------------------------------------------------------------------- 1 | import { keyframes } from '@stitches/core' 2 | 3 | export const fadeAndScale = keyframes({ 4 | from: { 5 | opacity: 0, 6 | transform: 'translate(-50%, -48%) scale(0.96)' 7 | }, 8 | to: { 9 | opacity: 1, 10 | transform: 'translate(-50%, -50%) scale(1)' 11 | } 12 | }) 13 | 14 | export const fadeIn = keyframes({ 15 | from: { 16 | opacity: 0 17 | }, 18 | to: { 19 | opacity: 1 20 | } 21 | }) 22 | 23 | export const fadeInSlideRight = keyframes({ 24 | from: { 25 | opacity: 0, 26 | transform: 'translate(10%, 0) scale(0.96)' 27 | }, 28 | to: { 29 | opacity: 1, 30 | transform: 'translate(0, 0) scale(1)' 31 | } 32 | }) 33 | 34 | export const fadeInSlideTop = keyframes({ 35 | from: { 36 | opacity: 0, 37 | transform: 'translate(0, -10%) scale(0.96)' 38 | }, 39 | to: { 40 | opacity: 1, 41 | transform: 'translate(0, 0) scale(1)' 42 | } 43 | }) 44 | 45 | export const fadeInSlideLeft = keyframes({ 46 | from: { 47 | opacity: 0, 48 | transform: 'translate(-10%, 0) scale(0.96)' 49 | }, 50 | to: { 51 | opacity: 1, 52 | transform: 'translate(0, 0) scale(1)' 53 | } 54 | }) 55 | 56 | export const fadeInSlideBottom = keyframes({ 57 | from: { 58 | opacity: 0, 59 | transform: 'translate(0, 10%) scale(0.96)' 60 | }, 61 | to: { 62 | opacity: 1, 63 | transform: 'translate(0, 0) scale(1)' 64 | } 65 | }) 66 | 67 | export const rotate = keyframes({ 68 | '100%': { 69 | transform: 'rotate(360deg)' 70 | } 71 | }) 72 | 73 | export const prixClipFix = keyframes({ 74 | '0%': { clipPath: 'polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)' }, 75 | '25%': { clipPath: 'polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)' }, 76 | '50%': { clipPath: 'polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)' }, 77 | '75%': { clipPath: 'polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 100%)' }, 78 | '100%': { clipPath: 'polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 0)' } 79 | }) 80 | 81 | export const loading = keyframes({ 82 | to: { 83 | backgroundPosition: 'left' 84 | } 85 | }) 86 | -------------------------------------------------------------------------------- /packages/react/src/index.ts: -------------------------------------------------------------------------------- 1 | import { createStitches } from '@stitches/react' 2 | import { composeExoTheme } from '@mvr-studio/exo-css' 3 | import * as utils from './utils/index' 4 | import * as types from './types' 5 | import * as components from './components/index' 6 | 7 | export const createExoUi = (themeProps?: types.CreateExpoThemeProps) => { 8 | const exoTheme = composeExoTheme(themeProps) 9 | const { styled, css, theme, getCssText } = createStitches(exoTheme) 10 | const styledComponents = { 11 | Box: components.composeBox({ styled, css, theme }), 12 | Flex: components.composeFlex({ styled, css, theme }), 13 | Button: components.composeButton({ styled, css, theme }), 14 | Stack: components.composeStack({ styled, css, theme }), 15 | HStack: components.composeHStack({ styled, css, theme }), 16 | Modal: components.composeModal({ styled, css, theme }), 17 | Input: components.composeInput({ styled, css, theme }), 18 | Select: components.composeSelect({ styled, css, theme }), 19 | Label: components.composeLabel({ styled, css, theme }), 20 | Heading: components.composeHeading({ styled, css, theme }), 21 | Text: components.composeText({ styled, css, theme }), 22 | Checkbox: components.composeCheckbox({ styled, css, theme }), 23 | RadioGroup: components.composeRadioGroup({ styled, css, theme }), 24 | Drawer: components.composeDrawer({ styled, css, theme }), 25 | Calendar: components.composeCalendar({ styled, theme, css }), 26 | AspectRatio: components.composeAspectRatio({ styled, css, theme }), 27 | Tooltip: components.composeTooltip({ styled, css, theme }), 28 | Popover: components.composePopover({ styled, css, theme }), 29 | Grid: components.composeGrid({ styled, css, theme }), 30 | SimpleGrid: components.composeSimpleGrid({ styled, css, theme }), 31 | Image: components.composeImage({ styled, css, theme }), 32 | Link: components.composeLink({ styled, css, theme }), 33 | Switch: components.composeSwitch({ styled, css, theme }), 34 | Textarea: components.composeTextarea({ styled, css, theme }), 35 | Spinner: components.composeSpinner({ styled, css }), 36 | Container: components.composeContainer({ styled, css }), 37 | Content: components.composeContent({ styled }), 38 | Card: components.composeCard({ styled }), 39 | Skeleton: components.composeSkeleton({ styled }) 40 | } 41 | return { 42 | styled, 43 | theme, 44 | css, 45 | getCssText, 46 | ...utils, 47 | ...styledComponents 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/css/src/components/Forms/Button/index.ts: -------------------------------------------------------------------------------- 1 | import { ComposerFactory } from '../../../types' 2 | import { boxStyles } from '../../Layout' 3 | 4 | export const buttonStyles = { 5 | ...boxStyles, 6 | display: 'inline-flex', 7 | color: 'var(--default-button-text-color)', 8 | alignItems: 'center', 9 | justifyContent: 'center', 10 | borderRadius: '$md', 11 | backgroundColor: 'var(--default-button-background)', 12 | paddingLeft: '$md', 13 | paddingRight: '$md', 14 | paddingTop: '$sm', 15 | paddingBottom: '$sm', 16 | cursor: 'pointer', 17 | transition: 'background-color 0.2s ease-out', 18 | border: '1px solid', 19 | borderColor: 'transparent', 20 | '&[disabled]': { 21 | opacity: 0.5, 22 | cursor: 'not-allowed' 23 | }, 24 | '&:hover': { 25 | backgroundColor: 'var(--default-button-background-hover)' 26 | }, 27 | '&:active': { 28 | backgroundColor: 'var(--default-button-background-active)' 29 | }, 30 | variants: { 31 | size: { 32 | sm: { 33 | paddingLeft: '$sm', 34 | paddingRight: '$sm', 35 | paddingTop: '$xs', 36 | paddingBottom: '$xs', 37 | fontSize: '14px' 38 | }, 39 | lg: { 40 | paddingLeft: '$lg', 41 | paddingRight: '$lg', 42 | paddingTop: '$md', 43 | paddingBottom: '$md' 44 | } 45 | }, 46 | scheme: { 47 | primary: { 48 | backgroundColor: 'var(--primary-button-background)', 49 | color: 'var(--primary-button-text-color)', 50 | '&:hover': { 51 | backgroundColor: 'var(--primary-button-background-hover)' 52 | }, 53 | '&:active': { 54 | backgroundColor: 'var(--primary-button-background-active)' 55 | } 56 | }, 57 | outline: { 58 | backgroundColor: 'transparent', 59 | border: '1px solid', 60 | borderColor: 'var(--outline-color)', 61 | '&:hover': { 62 | backgroundColor: 'var(--default-button-background-hover)' 63 | }, 64 | '&:active': { 65 | backgroundColor: 'var(--default-button-background-active)' 66 | } 67 | }, 68 | ghost: { 69 | backgroundColor: 'transparent', 70 | '&:hover': { 71 | backgroundColor: 'var(--default-button-background-hover)' 72 | }, 73 | '&:active': { 74 | backgroundColor: 'var(--default-button-background-active)' 75 | } 76 | } 77 | } 78 | } 79 | } 80 | 81 | export const composeButtonCss = ({ css }: ComposerFactory) => { 82 | return css(buttonStyles) 83 | } 84 | -------------------------------------------------------------------------------- /packages/react/src/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import { Story, StoryDefault } from '@ladle/react' 2 | import { createExoUi } from './' 3 | import { Sandpack } from '@codesandbox/sandpack-react' 4 | import dedent from 'dedent' 5 | 6 | export const Readme: Story = () => { 7 | const { Stack, Text, Heading } = createExoUi() 8 | return ( 9 | 10 | ExoUI 11 | Yes, yet another UI library. 12 | 13 | ) 14 | } 15 | 16 | export const Playground: Story = () => { 17 | const APP_CODE = dedent` 18 | import { useState } from 'react' 19 | import { createExoUi } from '@mvr-studio/exo-ui' 20 | 21 | export default function App() { 22 | const [isSent, setIsSent] = useState() 23 | const { Box, Stack, Heading, Text, Button, Input, Label, Textarea, Checkbox } = createExoUi() 24 | 25 | if (isSent) return ( 26 | 27 | 28 | ☑️ 29 | Message Sent 30 | 31 | setIsSent(false)}>Go Back 32 | 33 | ) 34 | 35 | return ( 36 | 37 | Interactive Playground 38 | Have fun 39 | 40 | Email Address 41 | 42 | Message 43 | 44 | 45 | 46 | I accept Terms of Service 47 | 48 | setIsSent(true)}>Send Message 49 | 50 | 51 | ) 52 | } 53 | ` 54 | 55 | const files = { 56 | '/App.tsx': APP_CODE 57 | } 58 | 59 | return ( 60 | 73 | ) 74 | } 75 | 76 | export default { 77 | title: 'ExoUI' 78 | } satisfies StoryDefault 79 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mvr-studio/exo-ui", 3 | "version": "0.1.8", 4 | "author": "Tomasz Marciniak ", 5 | "type": "module", 6 | "main": "dist/index.cjs", 7 | "module": "dist/index.js", 8 | "types": "dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "types": "./dist/index.d.ts", 12 | "require": "./dist/index.cjs", 13 | "default": "./dist/index.js" 14 | } 15 | }, 16 | "scripts": { 17 | "build": "tsup", 18 | "dev": "tsup --watch", 19 | "test:unit": "yarn jest", 20 | "test:e2e": "playwright test", 21 | "story:dev": "ladle serve", 22 | "story:build": "ladle build -o ./build", 23 | "story:preview": "ladle preview" 24 | }, 25 | "peerDependencies": { 26 | "@stitches/react": "^1.2", 27 | "react": "^18", 28 | "react-dom": "^18" 29 | }, 30 | "dependencies": { 31 | "@mvr-studio/exo-css": "*", 32 | "@radix-ui/react-aspect-ratio": "^1.0.2", 33 | "@radix-ui/react-avatar": "^1.0.2", 34 | "@radix-ui/react-checkbox": "^1.0.3", 35 | "@radix-ui/react-dialog": "^1.0.3", 36 | "@radix-ui/react-popover": "^1.0.5", 37 | "@radix-ui/react-radio-group": "^1.1.2", 38 | "@radix-ui/react-switch": "^1.0.2", 39 | "@radix-ui/react-tooltip": "^1.0.5", 40 | "@stitches/react": "^1.2.8", 41 | "@tabler/icons-react": "^2.10.0", 42 | "chroma-js": "^2.4.2", 43 | "dayjs": "^1.11.7", 44 | "easy-mesh-gradient": "^0.0.5", 45 | "polished": "^4.2.2", 46 | "react": "^18.2.0", 47 | "react-dom": "^18.2.0" 48 | }, 49 | "devDependencies": { 50 | "@babel/core": "^7.17.5", 51 | "@babel/preset-env": "^7.21.4", 52 | "@babel/preset-react": "^7.18.6", 53 | "@babel/preset-typescript": "^7.21.0", 54 | "@codesandbox/sandpack-react": "^2.4.7", 55 | "@fontsource/inter": "^4.5.15", 56 | "@ladle/react": "^2.11.0", 57 | "@playwright/test": "^1.32.2", 58 | "@stitches/core": "^1.2.8", 59 | "@testing-library/react": "^12.1.5", 60 | "@testing-library/react-hooks": "^8.0.1", 61 | "@types/chroma-js": "^2.4.0", 62 | "@types/jest": "^29.5.0", 63 | "@types/react": "^18.0.33", 64 | "@types/react-dom": "^18.0.11", 65 | "babel-loader": "^8.2.3", 66 | "babel-plugin-inline-react-svg": "^2.0.1", 67 | "dedent": "^0.7.0", 68 | "jest": "^29.5.0", 69 | "jest-environment-jsdom": "^29.5.0", 70 | "sync-fetch": "^0.4.2", 71 | "tsx": "^3.12.6", 72 | "vite": "^4.2.1" 73 | }, 74 | "jest": { 75 | "testEnvironment": "jsdom", 76 | "modulePathIgnorePatterns": [ 77 | "/e2e" 78 | ] 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Drawer/index.ts: -------------------------------------------------------------------------------- 1 | import * as Dialog from '@radix-ui/react-dialog' 2 | import { ComponentFactory } from '../../../types' 3 | import { animation } from '@mvr-studio/exo-css' 4 | import { composeOverlay } from '../../Utility/index' 5 | 6 | const commonMobileStyles = { 7 | top: 0, 8 | bottom: 0, 9 | right: 0, 10 | left: 0, 11 | maxHeight: '100%', 12 | maxWidth: '100%', 13 | borderRadius: 0 14 | } 15 | 16 | const commonHorizontalVariantProps = { 17 | ...commonMobileStyles, 18 | '@sm': { 19 | top: '1rem', 20 | bottom: '1rem', 21 | left: 'unset', 22 | right: 'unset', 23 | maxWidth: '32rem', 24 | maxHeight: 'calc(100% - 2rem)', 25 | borderRadius: '$md' 26 | } 27 | } 28 | 29 | const commonVerticalVariantProps = { 30 | ...commonMobileStyles, 31 | '@sm': { 32 | top: 'unset', 33 | bottom: 'unset', 34 | left: '1rem', 35 | right: '1rem', 36 | maxWidth: 'calc(100% - 2rem)', 37 | maxHeight: '32rem', 38 | borderRadius: '$md' 39 | } 40 | } 41 | 42 | export const composeDrawer = ({ styled }: ComponentFactory) => { 43 | const Overlay = composeOverlay({ styled }) 44 | const Content = styled(Dialog.Content, { 45 | unset: 'all', 46 | boxSizing: 'border-box', 47 | backgroundColor: 'var(--background-e1)', 48 | position: 'fixed', 49 | height: '100%', 50 | width: '100%', 51 | padding: '$lg', 52 | zIndex: 2, 53 | boxShadow: '$md', 54 | variants: { 55 | position: { 56 | top: { 57 | ...commonVerticalVariantProps, 58 | '@sm': { ...commonVerticalVariantProps['@sm'], top: '1rem' }, 59 | animation: `${animation.fadeInSlideTop} 0.2s cubic-bezier(0.16, 1, 0.3, 1)` 60 | }, 61 | right: { 62 | ...commonHorizontalVariantProps, 63 | '@sm': { ...commonHorizontalVariantProps['@sm'], right: '1rem' }, 64 | animation: `${animation.fadeInSlideRight} 0.2s cubic-bezier(0.16, 1, 0.3, 1)` 65 | }, 66 | bottom: { 67 | ...commonVerticalVariantProps, 68 | '@sm': { ...commonVerticalVariantProps['@sm'], bottom: '1rem' }, 69 | animation: `${animation.fadeInSlideBottom} 0.2s cubic-bezier(0.16, 1, 0.3, 1)` 70 | }, 71 | left: { 72 | ...commonHorizontalVariantProps, 73 | '@sm': { ...commonHorizontalVariantProps['@sm'], left: '1rem' }, 74 | animation: `${animation.fadeInSlideLeft} 0.2s cubic-bezier(0.16, 1, 0.3, 1)` 75 | } 76 | } 77 | }, 78 | defaultVariants: { 79 | position: 'right' 80 | } 81 | }) 82 | const Close = styled(Dialog.Close, {}) 83 | return { Root: Dialog.Root, Portal: Dialog.Portal, Trigger: Dialog.Trigger, Overlay, Content, Close } 84 | } 85 | -------------------------------------------------------------------------------- /packages/react/src/components/Feedback/Drawer/index.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import type { Story, StoryDefault } from '@ladle/react' 3 | import { createExoUi } from '../../..' 4 | import { IconX } from '@tabler/icons-react' 5 | import { useState } from 'react' 6 | 7 | export const Default: Story = () => { 8 | const { Drawer, Button, Stack, Heading, Text, Input, Label, Box } = createExoUi() 9 | return ( 10 | 11 | 12 | 13 | Edit profile 14 | 15 | 16 | 17 | 18 | 19 | Edit profile 20 | Edit user's profile 21 | 22 | Name 23 | 24 | 25 | 26 | Save changes 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | ) 39 | } 40 | 41 | export const Positions: Story = () => { 42 | const [isOpen, setIsOpen] = useState(false) 43 | const [position, setPosition] = useState('top') 44 | const { Drawer, Button, Stack, Heading, Text, Input, Label, Box } = createExoUi() 45 | const openInPosition = (position: string) => { 46 | setPosition(position) 47 | setIsOpen(true) 48 | } 49 | return ( 50 | 51 | 52 | openInPosition('top')}>Top Position 53 | openInPosition('right')}>Right Position 54 | openInPosition('bottom')}>Bottom Position 55 | openInPosition('left')}>Left Position 56 | 57 | 58 | 59 | 60 | 61 | 62 | Edit profile 63 | Edit user's profile 64 | 65 | Name 66 | 67 | 68 | 69 | Save changes 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | ) 82 | } 83 | 84 | export default { 85 | title: 'Feedback / Drawer' 86 | } satisfies StoryDefault 87 | -------------------------------------------------------------------------------- /packages/react/src/components/Forms/Calendar/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { composeFlex, composeStack } from '../../Layout' 3 | import { composeText } from '../../Typography' 4 | import dayjs from 'dayjs' 5 | import { ComponentFactory } from '../../../types' 6 | import { useCalendar } from '../../../utils' 7 | import { composeButton } from '../Button' 8 | import { rgba } from 'polished' 9 | 10 | export const composeCalendar = ({ styled, theme, css }: ComponentFactory) => { 11 | const Flex = composeFlex({ styled, css }) 12 | const Text = composeText({ styled, css }) 13 | const Stack = composeStack({ styled, css }) 14 | const Button = composeButton({ styled, css }) 15 | 16 | return () => { 17 | const { calendar, inRange, isSelected, toggle, viewing, viewNextMonth, viewPreviousMonth } = useCalendar() 18 | 19 | return ( 20 | 21 | 22 | 23 | ← 24 | 25 | {dayjs(viewing).format('MMM YYYY')} 26 | 27 | → 28 | 29 | 30 | 31 | {calendar[0][0].map((day) => ( 32 | 40 | {['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][dayjs(day).day()]} 41 | 42 | ))} 43 | 44 | {calendar[0].map((week) => ( 45 | 46 | {week.map((day) => ( 47 | toggle(day, true)} 57 | scheme="ghost" 58 | css={{ 59 | width: '3rem', 60 | height: '3rem', 61 | borderRadius: '$full', 62 | color: '$gray300', 63 | '&[data-in-range="true"]': { 64 | color: '$gray600' 65 | }, 66 | '&[data-today="true"]': { 67 | color: '$primary400', 68 | border: '1px solid', 69 | borderColor: 'transparent', 70 | backgroundColor: '$primary50' 71 | }, 72 | '&[data-selected="true"]': { 73 | border: '1px solid', 74 | borderColor: 'transparent', 75 | backgroundColor: '$primary400', 76 | color: 'white', 77 | boxShadow: `0 0.25rem 1rem ${rgba(theme.colors.primary400.value, 0.4)}` 78 | } 79 | }} 80 | > 81 | {dayjs(day).format('DD')} 82 | 83 | ))} 84 | 85 | ))} 86 | 87 | ) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/react/src/utils/useCalendar/index.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useMemo, useState } from 'react' 2 | import dayjs from 'dayjs' 3 | import { clearTime, eachOfInterval, inRange } from '../date' 4 | import { Day, Month } from '../../types' 5 | 6 | export interface Options { 7 | /** 8 | * What day a week starts on within the calendar matrix. 9 | * 10 | * @default Day.SUNDAY 11 | */ 12 | weekStartsOn?: Day 13 | 14 | /** 15 | * The initial viewing date. 16 | * 17 | * @default new Date() 18 | */ 19 | viewing?: Date 20 | 21 | /** 22 | * The initial date(s) selection. 23 | * 24 | * @default [] 25 | */ 26 | selected?: Date[] 27 | 28 | /** 29 | * The number of months in the calendar. 30 | * 31 | * @default 1 32 | */ 33 | numberOfMonths?: number 34 | } 35 | 36 | export interface Returns { 37 | /** 38 | * Returns a copy of the given date with the time set to 00:00:00:00. 39 | */ 40 | clearTime: (date: Date) => Date 41 | 42 | /** 43 | * Returns whether or not a date is between 2 other dates (inclusive). 44 | */ 45 | inRange: (props: { date: Date; min: Date; max: Date }) => boolean 46 | 47 | /** 48 | * The date represented in the calendar matrix. Note that 49 | * the month and year are the only parts used. 50 | */ 51 | viewing: Date 52 | 53 | /** 54 | * Set the date represented in the calendar matrix. Note that 55 | * the month and year are the only parts used. 56 | */ 57 | setViewing: React.Dispatch> 58 | 59 | /** 60 | * Set the viewing date to today. 61 | */ 62 | viewToday: () => void 63 | 64 | /** 65 | * Set the viewing date to the given month. 66 | */ 67 | viewMonth: (month: Month) => void 68 | 69 | /** 70 | * Set the viewing date to the month before the current. 71 | */ 72 | viewPreviousMonth: () => void 73 | 74 | /** 75 | * Set the viewing date to the month after the current. 76 | */ 77 | viewNextMonth: () => void 78 | 79 | /** 80 | * Set the viewing date to the given year. 81 | */ 82 | viewYear: (year: number) => void 83 | 84 | /** 85 | * Set the viewing date to the year before the current. 86 | */ 87 | viewPreviousYear: () => void 88 | 89 | /** 90 | * Set the viewing date to the year after the current. 91 | */ 92 | viewNextYear: () => void 93 | 94 | /** 95 | * The dates currently selected. 96 | */ 97 | selected: Date[] 98 | 99 | /** 100 | * Override the currently selected dates. 101 | */ 102 | setSelected: React.Dispatch> 103 | 104 | /** 105 | * Reset the selected dates to []. 106 | */ 107 | clearSelected: () => void 108 | 109 | /** 110 | * Determine whether or not a date has been selected. 111 | */ 112 | isSelected: (date: Date) => boolean 113 | 114 | /** 115 | * Select one or more dates. 116 | */ 117 | select: (date: Date | Date[], replaceExisting?: boolean) => void 118 | 119 | /** 120 | * Deselect one or more dates. 121 | */ 122 | deselect: (date: Date | Date[]) => void 123 | 124 | /** 125 | * Toggle the selection of a date. 126 | */ 127 | toggle: (date: Date, replaceExisting?: boolean) => void 128 | 129 | /** 130 | * Select a range of dates (inclusive). 131 | */ 132 | selectRange: (start: Date, end: Date, replaceExisting?: boolean) => void 133 | 134 | /** 135 | * Deselect a range of dates (inclusive). 136 | */ 137 | deselectRange: (start: Date, end: Date) => void 138 | 139 | /** 140 | * A matrix of days based on the current viewing date. 141 | */ 142 | calendar: Date[][][] 143 | } 144 | 145 | const clearTimeToDate = (date: Date) => clearTime(date).toDate() 146 | 147 | export const useCalendar = ({ 148 | weekStartsOn = Day.SUNDAY, 149 | viewing: initialViewing = new Date(), 150 | selected: initialSelected = [], 151 | numberOfMonths = 1 152 | }: Options = {}): Returns => { 153 | const [viewing, setViewing] = useState(initialViewing) 154 | const viewToday = useCallback(() => setViewing(dayjs().startOf('day').toDate()), [setViewing]) 155 | const viewMonth = useCallback((month: Month) => setViewing((v) => dayjs(v).set('month', month).toDate()), []) 156 | const viewPreviousMonth = useCallback(() => setViewing((v) => dayjs(v).subtract(1, 'month').toDate()), []) 157 | const viewNextMonth = useCallback(() => setViewing((v) => dayjs(v).add(1, 'month').toDate()), []) 158 | const viewYear = useCallback((year: number) => setViewing((v) => dayjs(v).set('year', year).toDate()), []) 159 | const viewPreviousYear = useCallback(() => setViewing((v) => dayjs(v).subtract(1, 'year').toDate()), []) 160 | const viewNextYear = useCallback(() => setViewing((v) => dayjs(v).add(1, 'year').toDate()), []) 161 | const [selected, setSelected] = useState(initialSelected.map(clearTimeToDate)) 162 | const clearSelected = () => setSelected([]) 163 | const isSelected = useCallback( 164 | (date: Date) => selected.findIndex((s) => dayjs(s).isSame(date, 'day')) > -1, 165 | [selected] 166 | ) 167 | 168 | const select = useCallback((date: Date | Date[], replaceExisting?: boolean) => { 169 | if (replaceExisting) { 170 | setSelected(Array.isArray(date) ? date : [date]) 171 | } else { 172 | setSelected((selectedItems) => selectedItems.concat(Array.isArray(date) ? date : [date])) 173 | } 174 | }, []) 175 | 176 | const deselect = useCallback( 177 | (date: Date | Date[]) => 178 | setSelected((selectedItems) => 179 | Array.isArray(date) 180 | ? selectedItems.filter((s) => !date.map((d) => d.getTime()).includes(s.getTime())) 181 | : selectedItems.filter((s) => !dayjs(s).isSame(date, 'day')) 182 | ), 183 | [] 184 | ) 185 | 186 | const toggle = useCallback( 187 | (date: Date, replaceExisting?: boolean) => (isSelected(date) ? deselect(date) : select(date, replaceExisting)), 188 | [deselect, isSelected, select] 189 | ) 190 | 191 | const selectRange = useCallback((start: Date, end: Date, replaceExisting?: boolean) => { 192 | if (replaceExisting) { 193 | setSelected(eachOfInterval({ start, end, unit: 'day' })) 194 | } else { 195 | setSelected((selectedItems) => selectedItems.concat(eachOfInterval({ start, end, unit: 'day' }))) 196 | } 197 | }, []) 198 | 199 | const deselectRange = useCallback((start: Date, end: Date) => { 200 | setSelected((selectedItems) => 201 | selectedItems.filter( 202 | (s) => 203 | !eachOfInterval({ start, end, unit: 'day' }) 204 | .map((d) => d.getTime()) 205 | .includes(s.getTime()) 206 | ) 207 | ) 208 | }, []) 209 | 210 | const calendar = useMemo( 211 | () => 212 | eachOfInterval({ 213 | start: dayjs(viewing).startOf('month').toDate(), 214 | end: dayjs(viewing) 215 | .add(numberOfMonths - 1, 'months') 216 | .endOf('month') 217 | .toDate(), 218 | unit: 'month' 219 | }).map((month) => 220 | eachOfInterval({ 221 | start: dayjs(month).startOf('month').toDate(), 222 | end: dayjs(month).endOf('month').toDate(), 223 | unit: 'week' 224 | }).map((week) => 225 | eachOfInterval({ 226 | start: dayjs(week).startOf('week').toDate(), 227 | end: dayjs(week).endOf('week').toDate(), 228 | unit: 'day' 229 | }) 230 | ) 231 | ), 232 | [viewing, weekStartsOn, numberOfMonths] 233 | ) 234 | 235 | return { 236 | clearTime: clearTimeToDate, 237 | inRange, 238 | viewing, 239 | setViewing, 240 | viewToday, 241 | viewMonth, 242 | viewPreviousMonth, 243 | viewNextMonth, 244 | viewYear, 245 | viewPreviousYear, 246 | viewNextYear, 247 | selected, 248 | setSelected, 249 | clearSelected, 250 | isSelected, 251 | select, 252 | deselect, 253 | toggle, 254 | selectRange, 255 | deselectRange, 256 | calendar 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /packages/css/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { ConfigType } from '@stitches/react/types/config' 2 | import { type CreateExpoThemeProps } from '../types' 3 | import { createColorScale } from './colors' 4 | import utils from './utils' 5 | import { createStitches, globalCss } from '@stitches/core' 6 | 7 | const FALLBACK_DEFAULT_PRIMARY_COLOR = '#2a26ff' 8 | 9 | type CreateExoThemeReturn = { theme: ConfigType.Theme; media: ConfigType.Media; utils: ConfigType.Utils } 10 | 11 | export const composeExoTheme = (themeProps?: CreateExpoThemeProps): CreateExoThemeReturn => { 12 | const primaryColorScale = createColorScale('primary', themeProps?.primaryColor || FALLBACK_DEFAULT_PRIMARY_COLOR) 13 | const secondaryColorScale = themeProps?.secondaryColor 14 | ? createColorScale('secondary', themeProps?.secondaryColor) 15 | : {} 16 | const grayColorScale = createColorScale('gray', '#454752') 17 | 18 | const colors = { 19 | white: '#ffffff', 20 | black: '#000000', 21 | ...grayColorScale, 22 | ...primaryColorScale, 23 | ...secondaryColorScale, 24 | ...themeProps?.colors 25 | } as Record 26 | 27 | const lightThemeVariables = { 28 | '--skeleton-highlight': colors.white, 29 | '--outline-color': colors.gray200, 30 | '--outline-color-light': colors.gray50, 31 | '--link-color': colors.primary400, 32 | '--default-text-color': colors.gray700, 33 | '--default-text-body-color': colors.gray600, 34 | '--default-button-background': colors.gray100, 35 | '--default-button-background-hover': colors.gray200, 36 | '--default-button-background-active': colors.gray300, 37 | '--default-button-text-color': colors.gray700, 38 | '--primary-button-background': colors.primary400, 39 | '--primary-button-background-hover': colors.primary500, 40 | '--primary-button-background-active': colors.primary600, 41 | '--primary-button-text-color': colors.gray50, 42 | '--default-input-background': colors.white, 43 | '--default-input-border-default': colors.gray300, 44 | '--default-input-border-active': colors.primary400, 45 | '--checkbox-background': colors.white, 46 | '--checkbox-indicator': colors.primary400, 47 | '--switch-background': colors.gray200, 48 | '--background-e0': colors.white, 49 | '--background-e1': colors.white, 50 | '--background-e2': colors.gray50, 51 | '--select-background': `url("data:image/svg+xml,");` 52 | } 53 | 54 | const darkThemeVariables = { 55 | '--skeleton-highlight': colors.gray500, 56 | '--outline-color': colors.gray500, 57 | '--outline-color-light': colors.gray700, 58 | '--link-color': colors.primary200, 59 | '--default-text-color': colors.gray50, 60 | '--default-text-body-color': colors.gray100, 61 | '--default-button-background': colors.gray700, 62 | '--default-button-background-hover': colors.gray600, 63 | '--default-button-background-active': colors.gray500, 64 | '--default-button-text-color': colors.gray100, 65 | '--primary-button-background': colors.primary300, 66 | '--primary-button-background-hover': colors.primary200, 67 | '--primary-button-background-active': colors.primary100, 68 | '--primary-button-text-color': colors.gray700, 69 | '--default-input-background': colors.gray800, 70 | '--default-input-border-default': colors.gray500, 71 | '--default-input-border-active': colors.primary300, 72 | '--checkbox-background': colors.gray600, 73 | '--checkbox-indicator': colors.primary200, 74 | '--switch-background': colors.gray600, 75 | '--background-e0': colors.gray900, 76 | '--background-e1': colors.gray800, 77 | '--background-e2': colors.gray700, 78 | '--select-background': `url("data:image/svg+xml,");` 79 | } 80 | 81 | const globalStyles = globalCss({ 82 | html: { 83 | '@media (prefers-color-scheme: dark)': darkThemeVariables, 84 | ...lightThemeVariables 85 | }, 86 | body: { 87 | color: 'var(--default-text-color)' 88 | }, 89 | 'html.dark': darkThemeVariables, 90 | 'html[data-theme="dark"]': darkThemeVariables 91 | }) 92 | 93 | globalStyles() 94 | 95 | return { 96 | theme: { 97 | colors, 98 | space: { 99 | xs: '0.25rem', 100 | sm: '0.5rem', 101 | md: '1rem', 102 | lg: '1.5rem', 103 | xl: '3rem', 104 | '2xl': '6rem' 105 | }, 106 | fontSizes: { 107 | sm: '0.75rem', 108 | md: '1rem', 109 | lg: '1.25rem', 110 | xl: '1.5rem', 111 | '2xl': '2rem' 112 | }, 113 | fonts: { 114 | body: '"Inter", system-ui, sans-serif', 115 | heading: 'Georgia, serif', 116 | mono: 'Menlo, monospace' 117 | }, 118 | fontWeights: { 119 | hairline: 100, 120 | thin: 200, 121 | light: 300, 122 | normal: 400, 123 | medium: 500, 124 | semibold: 600, 125 | bold: 700, 126 | extrabold: 800, 127 | black: 900 128 | }, 129 | lineHeights: { 130 | normal: 'normal', 131 | none: 1, 132 | shorter: 1.25, 133 | short: 1.375, 134 | base: 1.5, 135 | tall: 1.625, 136 | taller: '2', 137 | '3': '.75rem', 138 | '4': '1rem', 139 | '5': '1.25rem', 140 | '6': '1.5rem', 141 | '7': '1.75rem', 142 | '8': '2rem', 143 | '9': '2.25rem', 144 | '10': '2.5rem' 145 | }, 146 | letterSpacings: { 147 | tighter: '-0.05em', 148 | tight: '-0.025em', 149 | normal: '0', 150 | wide: '0.025em', 151 | wider: '0.05em', 152 | widest: '0.1em' 153 | }, 154 | sizes: { 155 | max: 'max-content', 156 | min: 'min-content', 157 | full: '100%', 158 | '3xs': '14rem', 159 | '2xs': '16rem', 160 | xs: '20rem', 161 | sm: '24rem', 162 | md: '28rem', 163 | lg: '32rem', 164 | xl: '36rem', 165 | '2xl': '42rem', 166 | '3xl': '48rem', 167 | '4xl': '56rem', 168 | '5xl': '64rem', 169 | '6xl': '72rem', 170 | '7xl': '80rem', 171 | '8xl': '90rem', 172 | containerSm: '640px', 173 | containerMd: '768px', 174 | containerLg: '1024px', 175 | containerXl: '1280px' 176 | }, 177 | borderWidths: {}, 178 | borderStyles: {}, 179 | radii: { 180 | none: '0', 181 | sm: '0.125rem', 182 | base: '0.25rem', 183 | md: '0.375rem', 184 | lg: '0.5rem', 185 | xl: '0.75rem', 186 | '2xl': '1rem', 187 | '3xl': '1.5rem', 188 | full: '9999px' 189 | }, 190 | shadows: { 191 | md: '0 0.5rem 0.5rem rgba(0, 0, 0, 0.05)', 192 | checkable: '0 0.125rem 0.25rem rgba(0, 0, 0, 0.2)', 193 | tooltip: '0 0 0.5rem rgba(0, 0, 0, 0.2)', 194 | inputDefault: `0 0 0 1px var(--default-input-border-default)`, 195 | inputHover: `0 0 0 1px var(--default-input-border-active)`, 196 | inputFocus: `0 0 0 2px var(--default-input-border-active)`, 197 | elevated: `0 0.125rem 0.25rem var(--outline-color)` 198 | }, 199 | zIndices: { 200 | hide: -1, 201 | auto: 'auto', 202 | base: 0, 203 | docked: 10, 204 | dropdown: 1000, 205 | sticky: 1100, 206 | banner: 1200, 207 | overlay: 1300, 208 | modal: 1400, 209 | popover: 1500, 210 | skipLink: 1600, 211 | toast: 1700, 212 | tooltip: 1800 213 | } 214 | }, 215 | media: { 216 | base: '(min-width: 0)', 217 | sm: '(min-width: 30em)', 218 | md: '(min-width: 48em)', 219 | lg: '(min-width: 62em)', 220 | xl: '(min-width: 80em)', 221 | '2xl': '(min-width: 96em)' 222 | }, 223 | utils 224 | } 225 | } 226 | 227 | export const createExoCss = (themeProps?: CreateExpoThemeProps) => { 228 | const exoTheme = composeExoTheme(themeProps) 229 | return createStitches(exoTheme) 230 | } 231 | -------------------------------------------------------------------------------- /packages/css/.svelte-kit/ambient.d.ts: -------------------------------------------------------------------------------- 1 | 2 | // this file is generated — do not edit it 3 | 4 | 5 | /// 6 | 7 | /** 8 | * Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env). 9 | * 10 | * _Unlike_ [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination. 11 | * 12 | * ```ts 13 | * import { API_KEY } from '$env/static/private'; 14 | * ``` 15 | * 16 | * Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: 17 | * 18 | * ``` 19 | * MY_FEATURE_FLAG="" 20 | * ``` 21 | * 22 | * You can override `.env` values from the command line like so: 23 | * 24 | * ```bash 25 | * MY_FEATURE_FLAG="enabled" npm run dev 26 | * ``` 27 | */ 28 | declare module '$env/static/private' { 29 | export const NVM_INC: string; 30 | export const MANPATH: string; 31 | export const npm_package_scripts_test_cross_platform_build: string; 32 | export const TERM_PROGRAM: string; 33 | export const npm_package_exports___vite_import: string; 34 | export const npm_package_exports___hooks_import: string; 35 | export const NODE: string; 36 | export const npm_package_dependencies_sade: string; 37 | export const INIT_CWD: string; 38 | export const NVM_CD_FLAGS: string; 39 | export const npm_package_devDependencies_typescript: string; 40 | export const npm_package_devDependencies__types_marked: string; 41 | export const npm_package_homepage: string; 42 | export const npm_config_version_git_tag: string; 43 | export const SHELL: string; 44 | export const TERM: string; 45 | export const npm_package_devDependencies_vite: string; 46 | export const npm_package_dependencies_devalue: string; 47 | export const npm_config_network_timeout: string; 48 | export const TMPDIR: string; 49 | export const HOMEBREW_REPOSITORY: string; 50 | export const npm_package_scripts_lint: string; 51 | export const npm_config_init_license: string; 52 | export const TERM_PROGRAM_VERSION: string; 53 | export const npm_package_dependencies_set_cookie_parser: string; 54 | export const npm_package_dependencies_cookie: string; 55 | export const MallocNanoZone: string; 56 | export const ORIGINAL_XDG_CURRENT_DESKTOP: string; 57 | export const npm_package_devDependencies_svelte_preprocess: string; 58 | export const npm_config_registry: string; 59 | export const ZSH: string; 60 | export const npm_package_repository_url: string; 61 | export const npm_package_readmeFilename: string; 62 | export const USER: string; 63 | export const NVM_DIR: string; 64 | export const npm_package_description: string; 65 | export const npm_package_exports___node_import: string; 66 | export const npm_package_exports___package_json: string; 67 | export const npm_package_dependencies_esm_env: string; 68 | export const npm_package_license: string; 69 | export const COMMAND_MODE: string; 70 | export const npm_package_exports___import: string; 71 | export const npm_package_repository_directory: string; 72 | export const SSH_AUTH_SOCK: string; 73 | export const __CF_USER_TEXT_ENCODING: string; 74 | export const npm_package_bin_svelte_kit: string; 75 | export const npm_execpath: string; 76 | export const npm_package_devDependencies__types_sade: string; 77 | export const PAGER: string; 78 | export const npm_package_devDependencies_svelte: string; 79 | export const npm_package_dependencies__sveltejs_vite_plugin_svelte: string; 80 | export const LSCOLORS: string; 81 | export const PATH: string; 82 | export const npm_config_argv: string; 83 | export const npm_package_scripts_postinstall: string; 84 | export const npm_package_devDependencies_rollup: string; 85 | export const npm_package_dependencies_magic_string: string; 86 | export const _: string; 87 | export const __CFBundleIdentifier: string; 88 | export const PWD: string; 89 | export const npm_package_devDependencies__types_mime: string; 90 | export const npm_package_devDependencies_uvu: string; 91 | export const npm_lifecycle_event: string; 92 | export const LANG: string; 93 | export const npm_package_types: string; 94 | export const npm_package_devDependencies_marked: string; 95 | export const npm_package_repository_type: string; 96 | export const npm_package_name: string; 97 | export const npm_package_scripts_test_integration: string; 98 | export const npm_package_devDependencies__types_connect: string; 99 | export const npm_package_dependencies_mime: string; 100 | export const npm_package_exports___node_polyfills_import: string; 101 | export const npm_package_exports___types: string; 102 | export const npm_config_version_commit_hooks: string; 103 | export const XPC_FLAGS: string; 104 | export const npm_package_scripts_test_cross_platform_dev: string; 105 | export const npm_package_dependencies_tiny_glob: string; 106 | export const npm_config_bin_links: string; 107 | export const npm_package_engines_node: string; 108 | export const npm_package_dependencies_sirv: string; 109 | export const XPC_SERVICE_NAME: string; 110 | export const npm_package_version: string; 111 | export const GPG_TTY: string; 112 | export const HOME: string; 113 | export const SHLVL: string; 114 | export const npm_package_dependencies_undici: string; 115 | export const npm_package_type: string; 116 | export const npm_package_scripts_test: string; 117 | export const npm_package_scripts_check_all: string; 118 | export const npm_config_save_prefix: string; 119 | export const npm_config_strict_ssl: string; 120 | export const HOMEBREW_PREFIX: string; 121 | export const npm_config_version_git_message: string; 122 | export const LOGNAME: string; 123 | export const LESS: string; 124 | export const npm_package_scripts_format: string; 125 | export const npm_package_peerDependencies_vite: string; 126 | export const npm_lifecycle_script: string; 127 | export const npm_package_peerDependencies_svelte: string; 128 | export const npm_package_devDependencies__types_set_cookie_parser: string; 129 | export const NVM_BIN: string; 130 | export const npm_package_files_3: string; 131 | export const npm_package_dependencies__types_cookie: string; 132 | export const npm_config_version_git_sign: string; 133 | export const npm_config_ignore_scripts: string; 134 | export const npm_config_user_agent: string; 135 | export const HOMEBREW_CELLAR: string; 136 | export const INFOPATH: string; 137 | export const npm_package_files_2: string; 138 | export const npm_package_devDependencies__types_node: string; 139 | export const npm_package_devDependencies__playwright_test: string; 140 | export const npm_package_files_1: string; 141 | export const npm_package_files_0: string; 142 | export const npm_package_dependencies_kleur: string; 143 | export const npm_config_init_version: string; 144 | export const npm_config_ignore_optional: string; 145 | export const npm_package_files_6: string; 146 | export const npm_config_init_author_name: string; 147 | export const npm_package_scripts_check: string; 148 | export const npm_package_files_5: string; 149 | export const COLORTERM: string; 150 | export const npm_node_execpath: string; 151 | export const npm_package_scripts_test_unit: string; 152 | export const npm_package_files_4: string; 153 | export const npm_config_version_tag_prefix: string; 154 | } 155 | 156 | /** 157 | * Similar to [`$env/static/private`](https://kit.svelte.dev/docs/modules#$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. 158 | * 159 | * Values are replaced statically at build time. 160 | * 161 | * ```ts 162 | * import { PUBLIC_BASE_URL } from '$env/static/public'; 163 | * ``` 164 | */ 165 | declare module '$env/static/public' { 166 | 167 | } 168 | 169 | /** 170 | * This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node) (or running [`vite preview`](https://kit.svelte.dev/docs/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env). 171 | * 172 | * This module cannot be imported into client-side code. 173 | * 174 | * ```ts 175 | * import { env } from '$env/dynamic/private'; 176 | * console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE); 177 | * ``` 178 | * 179 | * > In `dev`, `$env/dynamic` always includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. 180 | */ 181 | declare module '$env/dynamic/private' { 182 | export const env: { 183 | NVM_INC: string; 184 | MANPATH: string; 185 | npm_package_scripts_test_cross_platform_build: string; 186 | TERM_PROGRAM: string; 187 | npm_package_exports___vite_import: string; 188 | npm_package_exports___hooks_import: string; 189 | NODE: string; 190 | npm_package_dependencies_sade: string; 191 | INIT_CWD: string; 192 | NVM_CD_FLAGS: string; 193 | npm_package_devDependencies_typescript: string; 194 | npm_package_devDependencies__types_marked: string; 195 | npm_package_homepage: string; 196 | npm_config_version_git_tag: string; 197 | SHELL: string; 198 | TERM: string; 199 | npm_package_devDependencies_vite: string; 200 | npm_package_dependencies_devalue: string; 201 | npm_config_network_timeout: string; 202 | TMPDIR: string; 203 | HOMEBREW_REPOSITORY: string; 204 | npm_package_scripts_lint: string; 205 | npm_config_init_license: string; 206 | TERM_PROGRAM_VERSION: string; 207 | npm_package_dependencies_set_cookie_parser: string; 208 | npm_package_dependencies_cookie: string; 209 | MallocNanoZone: string; 210 | ORIGINAL_XDG_CURRENT_DESKTOP: string; 211 | npm_package_devDependencies_svelte_preprocess: string; 212 | npm_config_registry: string; 213 | ZSH: string; 214 | npm_package_repository_url: string; 215 | npm_package_readmeFilename: string; 216 | USER: string; 217 | NVM_DIR: string; 218 | npm_package_description: string; 219 | npm_package_exports___node_import: string; 220 | npm_package_exports___package_json: string; 221 | npm_package_dependencies_esm_env: string; 222 | npm_package_license: string; 223 | COMMAND_MODE: string; 224 | npm_package_exports___import: string; 225 | npm_package_repository_directory: string; 226 | SSH_AUTH_SOCK: string; 227 | __CF_USER_TEXT_ENCODING: string; 228 | npm_package_bin_svelte_kit: string; 229 | npm_execpath: string; 230 | npm_package_devDependencies__types_sade: string; 231 | PAGER: string; 232 | npm_package_devDependencies_svelte: string; 233 | npm_package_dependencies__sveltejs_vite_plugin_svelte: string; 234 | LSCOLORS: string; 235 | PATH: string; 236 | npm_config_argv: string; 237 | npm_package_scripts_postinstall: string; 238 | npm_package_devDependencies_rollup: string; 239 | npm_package_dependencies_magic_string: string; 240 | _: string; 241 | __CFBundleIdentifier: string; 242 | PWD: string; 243 | npm_package_devDependencies__types_mime: string; 244 | npm_package_devDependencies_uvu: string; 245 | npm_lifecycle_event: string; 246 | LANG: string; 247 | npm_package_types: string; 248 | npm_package_devDependencies_marked: string; 249 | npm_package_repository_type: string; 250 | npm_package_name: string; 251 | npm_package_scripts_test_integration: string; 252 | npm_package_devDependencies__types_connect: string; 253 | npm_package_dependencies_mime: string; 254 | npm_package_exports___node_polyfills_import: string; 255 | npm_package_exports___types: string; 256 | npm_config_version_commit_hooks: string; 257 | XPC_FLAGS: string; 258 | npm_package_scripts_test_cross_platform_dev: string; 259 | npm_package_dependencies_tiny_glob: string; 260 | npm_config_bin_links: string; 261 | npm_package_engines_node: string; 262 | npm_package_dependencies_sirv: string; 263 | XPC_SERVICE_NAME: string; 264 | npm_package_version: string; 265 | GPG_TTY: string; 266 | HOME: string; 267 | SHLVL: string; 268 | npm_package_dependencies_undici: string; 269 | npm_package_type: string; 270 | npm_package_scripts_test: string; 271 | npm_package_scripts_check_all: string; 272 | npm_config_save_prefix: string; 273 | npm_config_strict_ssl: string; 274 | HOMEBREW_PREFIX: string; 275 | npm_config_version_git_message: string; 276 | LOGNAME: string; 277 | LESS: string; 278 | npm_package_scripts_format: string; 279 | npm_package_peerDependencies_vite: string; 280 | npm_lifecycle_script: string; 281 | npm_package_peerDependencies_svelte: string; 282 | npm_package_devDependencies__types_set_cookie_parser: string; 283 | NVM_BIN: string; 284 | npm_package_files_3: string; 285 | npm_package_dependencies__types_cookie: string; 286 | npm_config_version_git_sign: string; 287 | npm_config_ignore_scripts: string; 288 | npm_config_user_agent: string; 289 | HOMEBREW_CELLAR: string; 290 | INFOPATH: string; 291 | npm_package_files_2: string; 292 | npm_package_devDependencies__types_node: string; 293 | npm_package_devDependencies__playwright_test: string; 294 | npm_package_files_1: string; 295 | npm_package_files_0: string; 296 | npm_package_dependencies_kleur: string; 297 | npm_config_init_version: string; 298 | npm_config_ignore_optional: string; 299 | npm_package_files_6: string; 300 | npm_config_init_author_name: string; 301 | npm_package_scripts_check: string; 302 | npm_package_files_5: string; 303 | COLORTERM: string; 304 | npm_node_execpath: string; 305 | npm_package_scripts_test_unit: string; 306 | npm_package_files_4: string; 307 | npm_config_version_tag_prefix: string; 308 | [key: `PUBLIC_${string}`]: undefined; 309 | [key: string]: string | undefined; 310 | } 311 | } 312 | 313 | /** 314 | * Similar to [`$env/dynamic/private`](https://kit.svelte.dev/docs/modules#$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://kit.svelte.dev/docs/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. 315 | * 316 | * Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead. 317 | * 318 | * ```ts 319 | * import { env } from '$env/dynamic/public'; 320 | * console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE); 321 | * ``` 322 | */ 323 | declare module '$env/dynamic/public' { 324 | export const env: { 325 | [key: `PUBLIC_${string}`]: string | undefined; 326 | } 327 | } 328 | --------------------------------------------------------------------------------
Some Text
Some more text