├── .github ├── config │ └── configuration.json └── workflows │ ├── release.yaml │ └── test.yaml ├── .gitignore ├── .storybook ├── main.js └── preview.tsx ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── rollup.config.ts ├── src ├── clickable │ ├── index.ts │ ├── src │ │ ├── index.ts │ │ ├── use-clickable.ts │ │ └── use-event-listeners.ts │ ├── stories │ │ └── use-clickable.stories.tsx │ └── tests │ │ └── clickable.test.tsx ├── color-mode │ ├── index.ts │ ├── src │ │ ├── color-mode-provider.tsx │ │ ├── color-mode-script.tsx │ │ ├── color-mode.utils.ts │ │ ├── index.ts │ │ └── storage-manager.ts │ └── test │ │ ├── color-mode-provider.test.tsx │ │ ├── color-mode-provider__browser.test.tsx │ │ ├── color-mode-provider__server.test.tsx │ │ ├── dark-mode.test.tsx │ │ ├── light-mode.test.tsx │ │ ├── storage-manager.test.ts │ │ ├── use-color-mode-value.test.tsx │ │ └── utils.tsx ├── components │ ├── Alert │ │ ├── index.ts │ │ ├── src │ │ │ ├── Alert.tsx │ │ │ ├── icons.tsx │ │ │ └── index.ts │ │ └── stories │ │ │ └── Alert.stories.tsx │ ├── Box │ │ ├── index.ts │ │ └── src │ │ │ ├── Box.tsx │ │ │ └── index.ts │ ├── Button │ │ ├── index.ts │ │ ├── src │ │ │ ├── Button.tsx │ │ │ ├── ButtonGroup.tsx │ │ │ ├── IconButton.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ ├── Button.stories.tsx │ │ │ └── IconButton.stories.tsx │ │ └── tests │ │ │ ├── button-group.test.tsx │ │ │ └── button.test.tsx │ ├── Checkbox │ │ ├── index.ts │ │ ├── src │ │ │ ├── Checkbox-group.tsx │ │ │ ├── Checkbox-icon.tsx │ │ │ ├── Checkbox.tsx │ │ │ ├── index.ts │ │ │ ├── use-checkbox-group.ts │ │ │ └── use-checkbox.ts │ │ ├── stories │ │ │ └── Checkbox.stories.tsx │ │ └── tests │ │ │ └── checkbox.test.tsx │ ├── CloseButton │ │ ├── index.ts │ │ ├── src │ │ │ ├── CloseButton.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── CloseButton.stories.tsx │ │ └── tests │ │ │ └── CloseButton.test.tsx │ ├── Conditional │ │ ├── index.ts │ │ └── src │ │ │ ├── Conditional.tsx │ │ │ └── index.ts │ ├── Container │ │ ├── index.ts │ │ └── src │ │ │ ├── Container.tsx │ │ │ └── index.ts │ ├── HorizontalNavigation │ │ ├── index.ts │ │ ├── src │ │ │ ├── HorizontalNavigation.tsx │ │ │ └── index.ts │ │ └── stories │ │ │ └── HorizontalNavigation.stories.tsx │ ├── Input │ │ ├── index.ts │ │ ├── src │ │ │ ├── Input.tsx │ │ │ ├── InputAddon.tsx │ │ │ ├── InputCore.tsx │ │ │ ├── InputElement.tsx │ │ │ ├── InputError.tsx │ │ │ ├── InputGroup.tsx │ │ │ ├── InputLabel.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ ├── Input.stories.tsx │ │ │ └── InputGroup.stories.tsx │ │ └── tests │ │ │ └── Input.test.tsx │ ├── Label │ │ ├── index.ts │ │ ├── src │ │ │ ├── Label.tsx │ │ │ └── index.ts │ │ └── stories │ │ │ └── Label.stories.tsx │ ├── List │ │ ├── index.ts │ │ └── src │ │ │ ├── List.tsx │ │ │ └── index.ts │ ├── Menu │ │ ├── index.ts │ │ ├── src │ │ │ ├── Menu.tsx │ │ │ ├── index.ts │ │ │ └── use-menu.ts │ │ ├── stories │ │ │ ├── index.stories.tsx │ │ │ └── menu.stories.tsx │ │ └── tests │ │ │ └── menu.test.tsx │ ├── Modal │ │ ├── index.ts │ │ ├── src │ │ │ ├── Drawer.tsx │ │ │ ├── Modal.tsx │ │ │ ├── index.ts │ │ │ ├── modal-manager.ts │ │ │ ├── modal-transition.tsx │ │ │ └── use-modal.ts │ │ ├── stories │ │ │ ├── Drawer.stories.tsx │ │ │ ├── Modal.stories.tsx │ │ │ └── index.stories.tsx │ │ └── tests │ │ │ └── modal.test.tsx │ ├── Multiselect │ │ ├── index.ts │ │ ├── src │ │ │ ├── Dropdown.tsx │ │ │ ├── Multiselect.tsx │ │ │ ├── Tags.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── Multiselect.stories.tsx │ │ └── tests │ │ │ └── Multiselect.test.tsx │ ├── Radio │ │ ├── index.ts │ │ ├── src │ │ │ ├── Radio-group.tsx │ │ │ ├── Radio.tsx │ │ │ ├── index.ts │ │ │ ├── use-radio-group.ts │ │ │ └── use-radio.ts │ │ ├── stories │ │ │ ├── Radio-group.stories.tsx │ │ │ └── Radio.stories.tsx │ │ └── tests │ │ │ ├── behavior.test.tsx │ │ │ ├── radio-group.test.tsx │ │ │ └── radio.test.tsx │ ├── Select │ │ ├── index.ts │ │ ├── src │ │ │ ├── ClearIcon.tsx │ │ │ ├── Select.tsx │ │ │ ├── constants │ │ │ │ ├── index.ts │ │ │ │ └── transitions.ts │ │ │ └── index.ts │ │ └── stories │ │ │ └── Select.stories.tsx │ ├── Spinner │ │ ├── index.ts │ │ ├── src │ │ │ ├── Spinner.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── Spinner.stories.tsx │ │ └── tests │ │ │ └── Spinner.test.tsx │ ├── Stack │ │ ├── index.ts │ │ └── src │ │ │ ├── Stack.tsx │ │ │ ├── Stack.utils.tsx │ │ │ └── index.ts │ ├── Switch │ │ ├── index.ts │ │ ├── src │ │ │ ├── Switch.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── Switch.stories.tsx │ │ └── tests │ │ │ └── switch.test.tsx │ ├── Table │ │ ├── index.ts │ │ ├── src │ │ │ ├── Table.tsx │ │ │ └── index.ts │ │ └── stories │ │ │ ├── Simple.tsx │ │ │ └── Table.stories.tsx │ ├── Tag │ │ ├── index.ts │ │ ├── src │ │ │ ├── Tag.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── Tag.stories.tsx │ │ └── tests │ │ │ └── tag.test.tsx │ ├── Text │ │ ├── index.ts │ │ ├── src │ │ │ ├── Text.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── Text.stories.tsx │ │ └── tokens.ts │ ├── Toast │ │ ├── index.ts │ │ ├── src │ │ │ ├── Toast.tsx │ │ │ ├── index.ts │ │ │ └── useToast.ts │ │ └── stories │ │ │ └── Toast.stories.tsx │ ├── VerticalNavigation │ │ ├── index.ts │ │ ├── src │ │ │ ├── VerticalNavigation.tsx │ │ │ └── index.ts │ │ ├── stories │ │ │ └── VerticalNavigation.stories.tsx │ │ └── tests │ │ │ └── VerticalNavigation.test.tsx │ └── index.ts ├── css-reset │ ├── index.ts │ └── src │ │ ├── css-reset.tsx │ │ └── index.ts ├── descendant │ ├── index.ts │ ├── src │ │ ├── index.ts │ │ └── use-descendant.ts │ └── stories │ │ └── use-descendant.stories.tsx ├── env │ ├── index.ts │ ├── src │ │ ├── env.tsx │ │ ├── index.ts │ │ ├── mock-document.ts │ │ └── mock-window.ts │ └── tests │ │ └── env.test.tsx ├── form-control │ ├── index.ts │ └── src │ │ ├── index.ts │ │ └── use-form-control.ts ├── hooks │ ├── index.ts │ ├── src │ │ ├── index.ts │ │ ├── use-boolean.ts │ │ ├── use-callback-ref.ts │ │ ├── use-clipboard.ts │ │ ├── use-const.ts │ │ ├── use-controllable.ts │ │ ├── use-dimensions.ts │ │ ├── use-disclosure.ts │ │ ├── use-event-callback.ts │ │ ├── use-event-listener.ts │ │ ├── use-focus-effect.ts │ │ ├── use-focus-on-hide.ts │ │ ├── use-focus-on-pointerdown.ts │ │ ├── use-focus-on-show.ts │ │ ├── use-force-update.ts │ │ ├── use-id.ts │ │ ├── use-interval.ts │ │ ├── use-latest-ref.ts │ │ ├── use-merge-refs.ts │ │ ├── use-mouse-down-ref.ts │ │ ├── use-outside-click.ts │ │ ├── use-pointer-event.ts │ │ ├── use-previous.ts │ │ ├── use-safe-layout-effect.ts │ │ ├── use-shortcut.ts │ │ ├── use-timeout.ts │ │ ├── use-unmount-effect.ts │ │ ├── use-update-effect.ts │ │ └── use-why-update.ts │ └── tests │ │ ├── use-clipboard.test.tsx │ │ └── use-controllable.test.tsx ├── icon │ ├── index.ts │ ├── src │ │ ├── create-icon.tsx │ │ ├── icon.tsx │ │ └── index.ts │ ├── stories │ │ └── icon.stories.tsx │ └── tests │ │ ├── create-icon.test.tsx │ │ └── icon.test.tsx ├── index.ts ├── media-query │ ├── index.ts │ ├── src │ │ ├── create-media-query.ts │ │ ├── index.ts │ │ ├── media-query.hook.tsx │ │ ├── media-query.tsx │ │ ├── media-query.utils.ts │ │ ├── use-breakpoint-value.ts │ │ ├── use-breakpoint.ts │ │ └── use-media-query.ts │ └── tests │ │ ├── create-media-query.test.ts │ │ ├── test-data.ts │ │ ├── use-breakpoint-value.test.tsx │ │ └── utils.test.ts ├── popper │ ├── index.ts │ ├── src │ │ ├── index.tsx │ │ ├── modifiers.ts │ │ ├── use-popper.ts │ │ └── utils.ts │ ├── stories │ │ ├── popper-v2.stories.tsx │ │ └── popper.stories.tsx │ └── tests │ │ └── popper.utils.test.ts ├── portal │ ├── index.ts │ ├── src │ │ ├── index.tsx │ │ ├── portal-manager.tsx │ │ └── portal.tsx │ └── tests │ │ └── portal.test.tsx ├── react-utils │ ├── index.ts │ └── src │ │ ├── children.ts │ │ ├── context.ts │ │ ├── index.ts │ │ ├── refs.ts │ │ └── types.ts ├── react │ ├── index.ts │ ├── src │ │ ├── chakra-provider.tsx │ │ ├── extend-theme.ts │ │ └── index.tsx │ └── tests │ │ └── extend-theme.test.tsx ├── styled-system │ ├── index.ts │ ├── src │ │ ├── config │ │ │ ├── background.ts │ │ │ ├── border.ts │ │ │ ├── color.ts │ │ │ ├── flexbox.ts │ │ │ ├── grid.ts │ │ │ ├── index.ts │ │ │ ├── layout.ts │ │ │ ├── list.ts │ │ │ ├── others.ts │ │ │ ├── outline.ts │ │ │ ├── position.ts │ │ │ ├── shadow.ts │ │ │ ├── space.ts │ │ │ ├── transform.ts │ │ │ ├── transition.ts │ │ │ └── typography.ts │ │ ├── create-transform.ts │ │ ├── css-var.ts │ │ ├── css.ts │ │ ├── expand-responsive.ts │ │ ├── index.ts │ │ ├── prop-config.ts │ │ ├── pseudos.ts │ │ ├── system.ts │ │ ├── theming.types.ts │ │ ├── types.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ ├── parse-border.ts │ │ │ ├── parse-gradient.ts │ │ │ └── types.ts │ └── tests │ │ ├── css-rtl.test.ts │ │ ├── css-type.test.ts │ │ ├── css-var-token.test.ts │ │ ├── css-var.test.ts │ │ ├── css.test.ts │ │ ├── interpolation.test.ts │ │ ├── parse-gradient.test.ts │ │ ├── sr-only.test.ts │ │ ├── text-styles.test.ts │ │ └── theme.ts ├── system │ ├── index.ts │ ├── src │ │ ├── forward-ref.tsx │ │ ├── hooks.ts │ │ ├── index.ts │ │ ├── providers.tsx │ │ ├── should-forward-prop.ts │ │ ├── system.ts │ │ ├── system.types.tsx │ │ ├── system.utils.ts │ │ └── use-style-config.ts │ └── tests │ │ ├── as-prop.test.tsx │ │ ├── hooks.test.ts │ │ ├── should-forward-prop.test.ts │ │ ├── style-config.test.tsx │ │ ├── style-resolver.test.ts │ │ └── system.test.tsx ├── test-utils │ ├── index.ts │ └── src │ │ ├── index.ts │ │ ├── press.ts │ │ └── test-utils.tsx ├── theme-tools │ ├── index.ts │ └── src │ │ ├── color.ts │ │ ├── component.ts │ │ ├── create-breakpoints.ts │ │ └── index.ts ├── theme │ ├── index.ts │ ├── src │ │ ├── components │ │ │ ├── accordion.ts │ │ │ ├── alert.ts │ │ │ ├── avatar.ts │ │ │ ├── badge.ts │ │ │ ├── breadcrumb.ts │ │ │ ├── button.ts │ │ │ ├── checkbox.ts │ │ │ ├── close-button.ts │ │ │ ├── code.ts │ │ │ ├── container.ts │ │ │ ├── divider.ts │ │ │ ├── drawer.ts │ │ │ ├── editable.ts │ │ │ ├── form-error.ts │ │ │ ├── form-label.ts │ │ │ ├── form.ts │ │ │ ├── heading.ts │ │ │ ├── horizontal-navigation.ts │ │ │ ├── index.ts │ │ │ ├── input.ts │ │ │ ├── kbd.ts │ │ │ ├── label.ts │ │ │ ├── link.ts │ │ │ ├── list.ts │ │ │ ├── menu.ts │ │ │ ├── modal.ts │ │ │ ├── multiselect.ts │ │ │ ├── number-input.ts │ │ │ ├── pin-input.ts │ │ │ ├── popover.ts │ │ │ ├── progress.ts │ │ │ ├── radio.ts │ │ │ ├── select.ts │ │ │ ├── skeleton.ts │ │ │ ├── skip-link.ts │ │ │ ├── slider.ts │ │ │ ├── spinner.ts │ │ │ ├── stat.ts │ │ │ ├── switch.ts │ │ │ ├── table.ts │ │ │ ├── tabs.ts │ │ │ ├── tag.ts │ │ │ ├── text.ts │ │ │ ├── textarea.ts │ │ │ ├── tooltip.ts │ │ │ └── vertical-navigation.ts │ │ ├── foundations │ │ │ ├── borders.ts │ │ │ ├── breakpoints.ts │ │ │ ├── colors.ts │ │ │ ├── index.ts │ │ │ ├── radius.ts │ │ │ ├── shadows.ts │ │ │ ├── sizes.ts │ │ │ ├── spacing.ts │ │ │ ├── transition.ts │ │ │ ├── typography.ts │ │ │ └── z-index.ts │ │ ├── index.ts │ │ ├── styles.ts │ │ └── theme.types.ts │ └── tests │ │ └── theme.test.ts ├── transition │ ├── index.ts │ ├── src │ │ ├── Collapse.tsx │ │ ├── Fade.tsx │ │ ├── ScaleFade.tsx │ │ ├── Slide.tsx │ │ ├── SlideFade.tsx │ │ ├── __utils.ts │ │ └── index.ts │ ├── stories │ │ ├── Collapse.stories.tsx │ │ ├── Fade.stories.tsx │ │ ├── Slide.stories.tsx │ │ └── transition.stories.tsx │ └── tests │ │ └── collapse.test.tsx ├── types │ ├── emotion.d.ts │ ├── static.d.ts │ └── theme.ts ├── utils │ ├── index.ts │ ├── src │ │ ├── array.ts │ │ ├── assertion.ts │ │ ├── docPropConfig.ts │ │ ├── dom-query.ts │ │ ├── dom.ts │ │ ├── focus.ts │ │ ├── function.ts │ │ ├── index.ts │ │ ├── number.ts │ │ ├── object.ts │ │ ├── pointer-event.ts │ │ ├── responsive.ts │ │ ├── tabbable.ts │ │ ├── types.ts │ │ └── user-agent.ts │ └── tests │ │ ├── array.test.ts │ │ ├── assertion.test.ts │ │ ├── dom-query.test.ts │ │ ├── dom.test.ts │ │ ├── function.test.ts │ │ ├── keydown.test.ts │ │ ├── number.test.ts │ │ ├── object.test.ts │ │ ├── responsive.test.ts │ │ └── tabbable.test.ts └── visually-hidden │ ├── index.ts │ ├── src │ ├── index.ts │ └── visually-hidden.tsx │ ├── stories │ └── visually-hidden.stories.tsx │ └── tests │ └── visually-hidden.test.tsx └── tsconfig.json /.github/config/configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "categories": [ 3 | { 4 | "title": "## 🚀 Features", 5 | "labels": ["feature"] 6 | }, 7 | { 8 | "title": "## 🐛 Fixes", 9 | "labels": ["fix"] 10 | }, 11 | { 12 | "title": "## 🧪 Tests", 13 | "labels": ["test"] 14 | }, 15 | { 16 | "title": "## 💬 Other", 17 | "labels": ["other", "chore", "added", "updated", "merge"] 18 | } 19 | ], 20 | "ignore_labels": ["ignore"], 21 | "sort": "ASC", 22 | "template": "${{CHANGELOG}}\n\n
\nUncategorized\n\n${{UNCATEGORIZED}}\n
", 23 | "pr_template": "- ${{TITLE}}\n", 24 | "empty_template": "- no changes", 25 | "label_extractor": [ 26 | { 27 | "pattern": "(.) (.+)", 28 | "target": "$1", 29 | "flags": "gu" 30 | }, 31 | { 32 | "pattern": "(.) (.+)", 33 | "target": "$1", 34 | "on_property": "title" 35 | } 36 | ], 37 | "transformers": [], 38 | "max_tags_to_fetch": 200, 39 | "max_pull_requests": 200, 40 | "max_back_track_time_days": 365, 41 | "tag_resolver": { 42 | "method": "semver" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Create Github Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | 8 | jobs: 9 | release: 10 | if: startsWith(github.ref, 'refs/tags/') 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | 16 | - name: Build Changelog 17 | id: github_release 18 | uses: mikepenz/release-changelog-builder-action@v2.0.0 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | with: 22 | configuration: ".github/config/configuration.json" 23 | commitMode: true 24 | 25 | - name: Create Release 26 | uses: actions/create-release@v1 27 | with: 28 | tag_name: ${{ github.ref }} 29 | release_name: ${{ github.ref }} 30 | body: ${{steps.github_release.outputs.changelog}} 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: "16.x" 19 | - run: npm ci 20 | - run: npm ts 21 | - run: npm test 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .build 2 | build 3 | .idea 4 | web_modules 5 | node_modules 6 | dist 7 | storybook-static -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { TsconfigPathsPlugin } = require("tsconfig-paths-webpack-plugin") 3 | 4 | const toPath = (_path) => path.join(process.cwd(), _path) 5 | 6 | module.exports = { 7 | stories: ["../src/**/stories/*.stories.tsx"], 8 | addons: ["@storybook/addon-docs", "storybook-addon-performance/register", "@storybook/addon-a11y"], 9 | typescript: { 10 | reactDocgen: "react-docgen-typescript", 11 | reactDocgenTypescriptOptions: { 12 | shouldRemoveUndefinedFromOptional: true, 13 | propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true), 14 | }, 15 | }, 16 | babel: async (options) => ({ 17 | ...options, 18 | presets: [ 19 | ...options.presets, 20 | [ 21 | "@babel/preset-react", 22 | { 23 | importSource: "lape", 24 | runtime: "automatic", 25 | }, 26 | "preset-react-jsx-transform", // Can name this anything, just an arbitrary alias to avoid duplicate presets' 27 | ], 28 | ], 29 | }), 30 | webpackFinal: async (config) => { 31 | ;[].push.apply(config.resolve.plugins, [new TsconfigPathsPlugin({ extensions: config.resolve.extensions })]) 32 | config.module.rules.push({ 33 | test: /\.mjs$/, 34 | include: /node_modules/, 35 | type: "javascript/auto", 36 | }) 37 | return { 38 | ...config, 39 | devtool: "inline-source-map", 40 | resolve: { 41 | ...config.resolve, 42 | alias: { 43 | ...config.resolve.alias, 44 | "@emotion/core": toPath("node_modules/@emotion/react"), 45 | "emotion-theming": toPath("node_modules/@emotion/react"), 46 | }, 47 | }, 48 | } 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /.storybook/preview.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | export const globalTypes = { 4 | direction: { 5 | name: "Direction", 6 | description: "Direction for layout", 7 | defaultValue: "LTR", 8 | toolbar: { 9 | icon: "globe", 10 | items: ["LTR", "RTL"], 11 | }, 12 | }, 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Karolis Masiulis, Julita Kriauciunaite, 4 | 5 | Copyright for portions of this project are held by Segun Adebayo as part of Chakra UI (c) MIT 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ugnis 2 | 3 | Ugnis is a Design System builder that exports to React and Figma - keeping your designers and developers in sync. 4 | 5 | ## License: 6 | 7 | MIT 8 | 9 | ## Contributors 10 | 11 | [Karolis Masiulis](https://www.github.com/masiulis) | [Julita Kriaučiūnaitė](https://github.com/JulitorK) | [Jonas Bernotas](https://github.com/Djonix) | [Justinas Petuchovas](https://github.com/jpetuchovas) | [Vytas Butkus](http://vytasbutkus.com/) 12 | 13 | -------------------------------------------------------------------------------- /rollup.config.ts: -------------------------------------------------------------------------------- 1 | import typescript from "rollup-plugin-typescript2" 2 | 3 | export default { 4 | input: `src/index.ts`, 5 | preserveModules: true, 6 | output: { 7 | format: "esm", 8 | dir: "./dist", 9 | }, 10 | external: [], 11 | watch: { 12 | include: "src/**", 13 | }, 14 | plugins: [ 15 | typescript({ 16 | typescript: require("ttypescript"), 17 | tsconfigDefaults: { 18 | exclude: ["**/*.test.ts", "**/*.test.tsx", "**/tests", "**/stories"], 19 | compilerOptions: { 20 | declaration: true, 21 | plugins: [ 22 | { transform: "typescript-transform-paths" }, 23 | { transform: "typescript-transform-paths", afterDeclarations: true }, 24 | ], 25 | }, 26 | }, 27 | }), 28 | ], 29 | } 30 | -------------------------------------------------------------------------------- /src/clickable/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src" 2 | -------------------------------------------------------------------------------- /src/clickable/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./use-clickable" 2 | -------------------------------------------------------------------------------- /src/clickable/src/use-event-listeners.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | interface EventListeners { 4 | add( 5 | el: EventTarget, 6 | type: K, 7 | listener: (this: Document, ev: DocumentEventMap[K]) => any, 8 | options?: boolean | AddEventListenerOptions, 9 | ): void 10 | add( 11 | el: EventTarget, 12 | type: string, 13 | listener: EventListenerOrEventListenerObject, 14 | options?: boolean | AddEventListenerOptions, 15 | ): void 16 | remove( 17 | el: EventTarget, 18 | type: K, 19 | listener: (this: Document, ev: DocumentEventMap[K]) => any, 20 | options?: boolean | EventListenerOptions, 21 | ): void 22 | remove( 23 | el: EventTarget, 24 | type: string, 25 | listener: EventListenerOrEventListenerObject, 26 | options?: boolean | EventListenerOptions, 27 | ): void 28 | } 29 | 30 | export function useEventListeners(): EventListeners { 31 | const listeners = React.useRef(new Map()) 32 | const currentListeners = listeners.current 33 | 34 | const add = React.useCallback((el, type, listener, options) => { 35 | listeners.current.set(listener, { type, el, options }) 36 | el.addEventListener(type, listener, options) 37 | }, []) 38 | 39 | const remove = React.useCallback((el, type, listener, options) => { 40 | el.removeEventListener(type, listener, options) 41 | listeners.current.delete(listener) 42 | }, []) 43 | 44 | React.useEffect( 45 | () => () => { 46 | currentListeners.forEach((value, key) => { 47 | remove(value.el, value.type, key, value.options) 48 | }) 49 | }, 50 | [remove, currentListeners], 51 | ) 52 | 53 | return { add, remove } 54 | } 55 | -------------------------------------------------------------------------------- /src/clickable/stories/use-clickable.stories.tsx: -------------------------------------------------------------------------------- 1 | import type * as React from "react" 2 | import { chakra, forwardRef, HTMLChakraProps } from "~/system" 3 | import type { Merge } from "~/utils" 4 | import { useClickable, UseClickableProps } from "../src" 5 | 6 | export type ClickableProps = Merge> 7 | 8 | const Clickable: React.FC = forwardRef((props, ref) => { 9 | const clickable = useClickable({ ...props, ref } as any) as HTMLChakraProps<"button"> 10 | return 11 | }) 12 | 13 | export default { 14 | title: "Utils/Clickable", 15 | } 16 | 17 | export const button = () => ( 18 | <> 19 | { 22 | alert("clicked") 23 | }} 24 | style={{ 25 | userSelect: "none", 26 | }} 27 | _active={{ bg: "blue.500", color: "white" }} 28 | _disabled={{ opacity: 0.4, pointerEvents: "none" }} 29 | > 30 | Clickable 31 | 32 | 33 | 34 | Clickable 35 | 36 | 37 | 44 | 45 | ) 46 | -------------------------------------------------------------------------------- /src/color-mode/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src" 2 | -------------------------------------------------------------------------------- /src/color-mode/src/color-mode-script.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import type { ColorMode } from "./color-mode.utils" 3 | 4 | type Mode = ColorMode | "system" | undefined 5 | 6 | function setScript(initialValue: Mode) { 7 | const mql = window.matchMedia("(prefers-color-scheme: dark)") 8 | const systemPreference = mql.matches ? "dark" : "light" 9 | 10 | let persistedPreference: Mode 11 | 12 | try { 13 | persistedPreference = localStorage.getItem("chakra-ui-color-mode") as Mode 14 | } catch (error) { 15 | console.log("Chakra UI: localStorage is not available. Color mode persistence might not work as expected") 16 | } 17 | 18 | const isInStorage = typeof persistedPreference === "string" 19 | 20 | let colorMode: Mode 21 | 22 | if (isInStorage) { 23 | colorMode = persistedPreference 24 | } else { 25 | colorMode = initialValue === "system" ? systemPreference : initialValue 26 | } 27 | 28 | if (colorMode) { 29 | const root = document.documentElement 30 | root.style.setProperty("--chakra-ui-color-mode", colorMode) 31 | } 32 | } 33 | 34 | interface ColorModeScriptProps { 35 | initialColorMode?: Mode 36 | /** 37 | * Optional nonce that will be passed to the created `