├── .nvmrc ├── .husky ├── commit-msg └── pre-commit ├── packages ├── icons │ ├── src │ │ ├── index.ts │ │ ├── components │ │ │ ├── utils │ │ │ │ └── index.ts │ │ │ ├── filled │ │ │ │ ├── MoonFilled.tsx │ │ │ │ ├── HeartFilled.tsx │ │ │ │ ├── SkipBackwardFilled.tsx │ │ │ │ ├── SkipForwardFilled.tsx │ │ │ │ ├── ExclamationCircleFilled.tsx │ │ │ │ ├── CheckCircleFilled.tsx │ │ │ │ ├── CloseCircleFilled.tsx │ │ │ │ ├── ExclamationSquareFilled.tsx │ │ │ │ └── ExclamationShieldFilled.tsx │ │ │ └── outlined │ │ │ │ ├── CheckOutlined.tsx │ │ │ │ ├── ChevronUpOutlined.tsx │ │ │ │ ├── ChevronDownOutlined.tsx │ │ │ │ ├── ChevronLeftOutlined.tsx │ │ │ │ ├── ChevronRightOutlined.tsx │ │ │ │ ├── SearchOutlined.tsx │ │ │ │ ├── CloseOutlined.tsx │ │ │ │ ├── ExclamationCircleOutlined.tsx │ │ │ │ ├── CopyOutlined.tsx │ │ │ │ ├── MoonOutlined.tsx │ │ │ │ ├── CheckCircleOutlined.tsx │ │ │ │ └── RepeatOutlined.tsx │ │ └── svg │ │ │ ├── outlined │ │ │ ├── check.svg │ │ │ ├── chevron-up.svg │ │ │ ├── chevron-down.svg │ │ │ ├── chevron-left.svg │ │ │ ├── chevron-right.svg │ │ │ ├── search.svg │ │ │ ├── close.svg │ │ │ ├── exclamation-circle.svg │ │ │ ├── copy.svg │ │ │ ├── check-circle.svg │ │ │ ├── moon.svg │ │ │ ├── repeat.svg │ │ │ ├── github.svg │ │ │ ├── skip-backward.svg │ │ │ └── skip-forward.svg │ │ │ └── filled │ │ │ ├── moon.svg │ │ │ ├── heart.svg │ │ │ ├── skip-backward.svg │ │ │ ├── skip-forward.svg │ │ │ ├── exclamation-circle.svg │ │ │ ├── check-circle.svg │ │ │ ├── close-circle.svg │ │ │ ├── exclamation-square.svg │ │ │ ├── exclamation-shield.svg │ │ │ ├── like.svg │ │ │ └── dislike.svg │ ├── types.d.ts │ ├── README.md │ └── tsconfig.json ├── cli │ ├── src │ │ └── actions │ │ │ └── index.ts │ ├── bin │ │ └── index.js │ └── tsconfig.json ├── react │ ├── src │ │ ├── components │ │ │ ├── utils │ │ │ │ ├── ripple │ │ │ │ │ └── index.ts │ │ │ │ ├── portal │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── motionFeatures │ │ │ │ │ ├── features.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── computePosition │ │ │ │ │ ├── middleware │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── generateSlotClass.ts │ │ │ │ ├── isFocusVisible.ts │ │ │ │ ├── generateSlotClasses.ts │ │ │ │ └── useDefaultProps.ts │ │ │ ├── modal │ │ │ │ ├── constants.ts │ │ │ │ └── index.ts │ │ │ ├── icon │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── box │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ └── Box.test.tsx │ │ │ │ ├── Box.tsx │ │ │ │ └── types.ts │ │ │ ├── dialog │ │ │ │ ├── DialogClose.tsx │ │ │ │ ├── DialogTrigger.tsx │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ └── index.ts │ │ │ ├── drawer │ │ │ │ ├── DrawerClose.tsx │ │ │ │ ├── DrawerTrigger.tsx │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ ├── index.ts │ │ │ │ └── DrawerContext.tsx │ │ │ ├── flex │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── classes.ts │ │ │ │ │ └── __snapshots__ │ │ │ │ │ └── Flex.test.tsx.snap │ │ │ ├── buttonBase │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── __snapshots__ │ │ │ │ │ └── ButtonBase.test.tsx.snap │ │ │ ├── focusTrap │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── input │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── inputBase │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── popover │ │ │ │ ├── PopoverClose.tsx │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ ├── index.ts │ │ │ │ └── PopoverContext.tsx │ │ │ ├── alert │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── badge │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── switch │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── button │ │ │ │ ├── index.tsx │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── divider │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ ├── classes.ts │ │ │ │ │ └── __snapshots__ │ │ │ │ │ │ └── Divider.test.tsx.snap │ │ │ │ └── __stories__ │ │ │ │ │ └── Divider.stories.tsx │ │ │ ├── tooltip │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ └── classes.ts │ │ │ ├── initColorSchemeScript │ │ │ │ └── index.ts │ │ │ ├── provider │ │ │ │ ├── index.ts │ │ │ │ └── Context.ts │ │ │ ├── radioGroup │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ └── RadioGroupContext.tsx │ │ │ ├── avatar │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ └── AvatarGroupContext.ts │ │ │ ├── accordion │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ └── AccordionContext.tsx │ │ │ ├── checkbox │ │ │ │ ├── index.ts │ │ │ │ ├── __tests__ │ │ │ │ │ └── classes.ts │ │ │ │ ├── IndeterminateIcon.tsx │ │ │ │ └── CheckboxGroupContext.ts │ │ │ ├── popper │ │ │ │ ├── index.ts │ │ │ │ ├── PopperManager.ts │ │ │ │ └── PopperContext.ts │ │ │ ├── card │ │ │ │ ├── index.ts │ │ │ │ └── __tests__ │ │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── CardHeader.test.tsx.snap │ │ │ │ │ ├── classes.ts │ │ │ │ │ ├── CardBody.test.tsx │ │ │ │ │ └── CardFooter.test.tsx │ │ │ └── index.ts │ │ ├── theme │ │ │ ├── shared │ │ │ │ ├── index.ts │ │ │ │ └── toSlots.ts │ │ │ ├── defineTheme.ts │ │ │ ├── index.ts │ │ │ ├── system │ │ │ │ ├── tokens │ │ │ │ │ ├── zIndices.ts │ │ │ │ │ ├── borderWidths.ts │ │ │ │ │ ├── borders.ts │ │ │ │ │ ├── radii.ts │ │ │ │ │ ├── shadows.ts │ │ │ │ │ ├── transitions.ts │ │ │ │ │ ├── spaces.ts │ │ │ │ │ └── sizes.ts │ │ │ │ ├── index.ts │ │ │ │ ├── semanticTokens │ │ │ │ │ ├── borders.ts │ │ │ │ │ └── index.ts │ │ │ │ └── breakpoints.ts │ │ │ ├── defineColorScheme.ts │ │ │ ├── __tests__ │ │ │ │ ├── defineTheme.test.ts │ │ │ │ └── defineColorScheme.test.ts │ │ │ ├── preset.ts │ │ │ └── recipes │ │ │ │ ├── flex.ts │ │ │ │ ├── index.ts │ │ │ │ └── divider.ts │ │ └── types │ │ │ └── generated │ │ │ └── breakpoints.ts │ └── tsconfig.json ├── system │ ├── src │ │ ├── layers │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── tokens │ │ │ └── index.ts │ │ ├── systemProvider │ │ │ ├── index.tsx │ │ │ ├── types.ts │ │ │ └── SystemContext.ts │ │ ├── recipes │ │ │ └── index.ts │ │ └── colorScheme │ │ │ ├── index.ts │ │ │ └── ColorSchemeContex.ts │ └── tsconfig.json ├── utils │ ├── src │ │ ├── dom │ │ │ ├── index.ts │ │ │ ├── ownerDocument.ts │ │ │ ├── ownerWindow.ts │ │ │ └── addEventListener.ts │ │ ├── shared │ │ │ ├── env.ts │ │ │ ├── upperFirst.ts │ │ │ ├── index.ts │ │ │ ├── chain.ts │ │ │ ├── kebabCase.ts │ │ │ ├── camelCase.ts │ │ │ └── is.ts │ │ ├── react │ │ │ ├── index.ts │ │ │ └── mergeRefs.ts │ │ ├── index.ts │ │ └── __tests__ │ │ │ └── addEventListener.test.ts │ ├── tsconfig.json │ └── README.md ├── hooks │ ├── tsconfig.json │ ├── README.md │ └── src │ │ ├── index.ts │ │ ├── useUnmount.ts │ │ ├── useMergeRefs.ts │ │ ├── __tests__ │ │ ├── useUnmount.test.ts │ │ ├── useLatest.test.tsx │ │ └── useMergeRefs.test.ts │ │ ├── useLatest.ts │ │ └── useEvent.ts └── styled │ ├── README.md │ ├── src │ └── index.ts │ └── tsconfig.json ├── examples ├── .gitignore ├── nex-ui-vite │ ├── src │ │ ├── vite-env.d.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── App.tsx │ ├── tsconfig.json │ ├── vite.config.ts │ ├── .gitignore │ ├── index.html │ └── tsconfig.node.json ├── nex-ui-vite-swc │ ├── src │ │ ├── vite-env.d.ts │ │ ├── index.css │ │ ├── main.tsx │ │ └── App.tsx │ ├── tsconfig.json │ ├── vite.config.ts │ ├── .gitignore │ ├── index.html │ └── tsconfig.node.json ├── nex-ui-nextjs-app │ ├── app │ │ ├── favicon.ico │ │ ├── globals.css │ │ └── layout.tsx │ ├── next.config.ts │ ├── next-env.d.ts │ ├── eslint.config.mjs │ ├── .gitignore │ ├── package.json │ └── tsconfig.json └── nex-ui-nextjs-pages │ ├── public │ └── favicon.ico │ ├── next.config.ts │ ├── next-env.d.ts │ ├── styles │ └── globals.css │ ├── pages │ ├── api │ │ └── hello.ts │ ├── _app.tsx │ └── _document.tsx │ ├── eslint.config.mjs │ ├── tsconfig.json │ └── package.json ├── docs ├── components │ ├── sandpack │ │ ├── index.ts │ │ ├── IconButton.tsx │ │ ├── BugReportButton.tsx │ │ └── CodeSandboxButton.tsx │ ├── docs │ │ ├── homepage │ │ │ ├── features │ │ │ │ ├── index.ts │ │ │ │ ├── demos │ │ │ │ │ └── index.ts │ │ │ │ └── Styling.tsx │ │ │ └── Gallery.tsx │ │ ├── index.ts │ │ ├── TokensTable.tsx │ │ ├── ScaleTable.tsx │ │ ├── SelectorTable.tsx │ │ ├── BreakpointTable.tsx │ │ └── AliasTable.tsx │ ├── table │ │ ├── Td.tsx │ │ ├── Th.tsx │ │ ├── index.ts │ │ ├── Thead.tsx │ │ ├── Table.tsx │ │ ├── Tr.tsx │ │ ├── Tbody.tsx │ │ ├── DefaultItem.tsx │ │ └── HighlightItem.tsx │ ├── index.ts │ └── FlexCenter.tsx ├── app │ ├── [lang] │ │ └── not-found.ts │ ├── env.d.ts │ ├── _dictionaries │ │ ├── zh.ts │ │ ├── i18nConfig.ts │ │ ├── en.ts │ │ └── getDictionary.ts │ └── manifest.ts ├── public │ ├── favicon.ico │ ├── images │ │ ├── logo.png │ │ ├── fruit-1.jpeg │ │ ├── fruit-2.jpeg │ │ ├── fruit-3.jpeg │ │ ├── fruit-4.jpeg │ │ ├── album-cover.png │ │ ├── card-cover.jpeg │ │ ├── playlist-cover-1.jpg │ │ ├── playlist-cover-2.jpg │ │ ├── playlist-cover-3.jpg │ │ ├── playlist-cover-4.jpg │ │ ├── playlist-cover-5.jpg │ │ ├── playlist-cover-6.jpg │ │ ├── playlist-cover-7.jpg │ │ └── playlist-cover-8.jpg │ ├── avatars │ │ ├── avatar-1.jpg │ │ ├── avatar-2.jpg │ │ ├── avatar-4.jpg │ │ └── avatar-3.webp │ ├── sitemap.xml │ └── robots.txt ├── content │ ├── en │ │ ├── docs │ │ │ ├── getting-started │ │ │ │ └── _meta.ts │ │ │ ├── _meta.ts │ │ │ ├── styling │ │ │ │ └── _meta.ts │ │ │ └── components │ │ │ │ └── _meta.ts │ │ └── _meta.ts │ ├── zh │ │ ├── docs │ │ │ ├── getting-started │ │ │ │ └── _meta.ts │ │ │ ├── _meta.ts │ │ │ ├── styling │ │ │ │ └── _meta.ts │ │ │ ├── components │ │ │ │ └── _meta.ts │ │ │ └── customization │ │ │ │ ├── colors.mdx │ │ │ │ └── _meta.ts │ │ └── _meta.ts │ └── _demo │ │ ├── badge │ │ ├── Usage.demo.tsx │ │ ├── Disabled.demo.tsx │ │ ├── WithCloseButton.demo.tsx │ │ ├── WithIcons.demo.tsx │ │ ├── Sizes.demo.tsx │ │ ├── Variants.demo.tsx │ │ ├── Colors.demo.tsx │ │ └── Radii.demo.tsx │ │ ├── button │ │ ├── Usage.demo.tsx │ │ ├── Loading.demo.tsx │ │ ├── Disabled.demo.tsx │ │ ├── Sizes.demo.tsx │ │ ├── Radii.demo.tsx │ │ ├── Variants.demo.tsx │ │ └── Colors.demo.tsx │ │ ├── switch │ │ ├── Disabled.demo.tsx │ │ ├── Usage.demo.tsx │ │ ├── Sizes.demo.tsx │ │ ├── WithIcons.demo.tsx │ │ ├── WithThumbIcon.demo.tsx │ │ ├── Controlled.demo.tsx │ │ └── Colors.demo.tsx │ │ ├── checkbox │ │ ├── Usage.demo.tsx │ │ ├── Indeterminate.demo.tsx │ │ ├── Disabled.demo.tsx │ │ ├── Sizes.demo.tsx │ │ ├── GroupDisabled.demo.tsx │ │ ├── GroupVertical.demo.tsx │ │ ├── Controlled.demo.tsx │ │ └── GroupUseage.demo.tsx │ │ ├── divider │ │ └── index.tsx │ │ ├── alert │ │ ├── Usage.demo.tsx │ │ ├── HideIcon.demo.tsx │ │ ├── WithAction.demo.tsx │ │ └── Closable.demo.tsx │ │ ├── tooltip │ │ ├── Usage.demo.tsx │ │ ├── Delay.demo.tsx │ │ ├── Offset.demo.tsx │ │ ├── Interactive.demo.tsx │ │ └── Controlled.demo.tsx │ │ ├── input │ │ ├── Clearable.demo.tsx │ │ ├── Invalid.demo.tsx │ │ ├── Disabled.demo.tsx │ │ ├── ReadOnly.demo.tsx │ │ ├── Usage.demo.tsx │ │ ├── LabelPlacements.demo.tsx │ │ └── Adornment.demo.tsx │ │ ├── avatar │ │ ├── Outlined.demo.tsx │ │ ├── Fallback.demo.tsx │ │ ├── Usage.demo.tsx │ │ ├── Sizes.demo.tsx │ │ ├── GroupMaxCount.demo.tsx │ │ ├── GroupSpacing.demo.tsx │ │ ├── GroupTotalCount.demo.tsx │ │ ├── Radii.demo.tsx │ │ └── GroupCustomSurplus.demo.tsx │ │ ├── flex │ │ ├── Gap.demo.tsx │ │ ├── Direction.demo.tsx │ │ ├── Usage.demo.tsx │ │ ├── Justify.demo.tsx │ │ └── Align.demo.tsx │ │ ├── card │ │ └── Usage.demo.tsx │ │ ├── radioGroup │ │ ├── Usage.demo.tsx │ │ ├── Disabled.demo.tsx │ │ ├── DefaultValue.demo.tsx │ │ ├── Vertical.demo.tsx │ │ └── Controlled.demo.tsx │ │ ├── index.ts │ │ └── popover │ │ └── Usage.demo.tsx ├── types.d.ts ├── nextraTheme │ ├── README.md │ ├── utils │ │ ├── index.ts │ │ └── git-url-parse.ts │ ├── stores │ │ ├── index.ts │ │ ├── toc.ts │ │ ├── focused-route.ts │ │ ├── active-anchor.ts │ │ ├── theme-config.ts │ │ └── menu.ts │ ├── index.ts │ ├── components │ │ ├── index.ts │ │ └── footer.tsx │ └── css │ │ └── typesetting-article.css ├── postcss.config.mjs ├── next-sitemap.config.mjs ├── next-env.d.ts ├── middleware.ts ├── eslint.config.mjs ├── icons │ ├── pnpm.svg │ ├── accessibility.svg │ └── npm.svg ├── tsconfig.json └── mdx-components.tsx ├── assets ├── logo.png └── construction.png ├── sb ├── utils │ ├── index.ts │ ├── constants.ts │ └── normalize.ts ├── .storybook │ ├── logo.png │ ├── manager.ts │ ├── modes.ts │ ├── manager-head.html │ ├── preview-head.html │ ├── theme.ts │ └── main.ts ├── tsconfig.json ├── chromatic.config.json └── vite.config.ts ├── .npmrc ├── pnpm-workspace.yaml ├── codecov.yml ├── scripts └── utils │ ├── index.ts │ ├── pretty.ts │ └── rollup.ts ├── .prettierignore ├── .github └── CODEOWNERS ├── .vscode ├── settings.json └── launch.json ├── .prettierrc.mjs ├── tests └── shared │ └── utils.ts ├── .editorconfig ├── .changeset ├── config.json └── README.md ├── .lintstagedrc.json ├── .commitlintrc.json ├── notes ├── 解决图标文本对齐.md └── gitflow.md ├── clean-package.config.json ├── turbo.json └── .gitignore /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.16.0 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | pnpm dlx commitlint --edit $1 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm lint-staged -c .lintstagedrc.json -------------------------------------------------------------------------------- /packages/icons/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components' 2 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | pnpm-lock.yaml 3 | yarn.lock -------------------------------------------------------------------------------- /packages/cli/src/actions/index.ts: -------------------------------------------------------------------------------- 1 | export { initAction } from './init' 2 | -------------------------------------------------------------------------------- /docs/components/sandpack/index.ts: -------------------------------------------------------------------------------- 1 | export { Sandpack } from './Sandpack' 2 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/assets/logo.png -------------------------------------------------------------------------------- /examples/nex-ui-vite/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/ripple/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Ripple' 2 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/cli/bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import '../dist/index.js' 4 | -------------------------------------------------------------------------------- /sb/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './constants' 2 | 3 | export * from './normalize' 4 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | prefer-workspace-packages=true 2 | save-prefix='' 3 | enable-pre-post-scripts=true 4 | -------------------------------------------------------------------------------- /docs/app/[lang]/not-found.ts: -------------------------------------------------------------------------------- 1 | export { NotFoundPage as default } from '../../nextraTheme' 2 | -------------------------------------------------------------------------------- /packages/icons/src/components/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { createIcon } from './createIcon' 2 | -------------------------------------------------------------------------------- /sb/.storybook/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/sb/.storybook/logo.png -------------------------------------------------------------------------------- /assets/construction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/assets/construction.png -------------------------------------------------------------------------------- /docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/logo.png -------------------------------------------------------------------------------- /packages/react/src/theme/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './toSlots' 2 | export * from './variants' 3 | -------------------------------------------------------------------------------- /packages/system/src/layers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createLayers' 2 | 3 | export * from './types' 4 | -------------------------------------------------------------------------------- /docs/content/en/docs/getting-started/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | introduction: 'Introduction', 3 | } 4 | -------------------------------------------------------------------------------- /packages/react/src/components/modal/constants.ts: -------------------------------------------------------------------------------- 1 | export const MODAL_INTERNAL_ID_PREFIX = 'nui-modal-' 2 | -------------------------------------------------------------------------------- /docs/public/avatars/avatar-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/avatars/avatar-1.jpg -------------------------------------------------------------------------------- /docs/public/avatars/avatar-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/avatars/avatar-2.jpg -------------------------------------------------------------------------------- /docs/public/avatars/avatar-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/avatars/avatar-4.jpg -------------------------------------------------------------------------------- /docs/public/images/fruit-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/fruit-1.jpeg -------------------------------------------------------------------------------- /docs/public/images/fruit-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/fruit-2.jpeg -------------------------------------------------------------------------------- /docs/public/images/fruit-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/fruit-3.jpeg -------------------------------------------------------------------------------- /docs/public/images/fruit-4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/fruit-4.jpeg -------------------------------------------------------------------------------- /docs/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.demo?raw' { 2 | const content: string 3 | export default content 4 | } 5 | -------------------------------------------------------------------------------- /docs/public/avatars/avatar-3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/avatars/avatar-3.webp -------------------------------------------------------------------------------- /docs/public/images/album-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/album-cover.png -------------------------------------------------------------------------------- /docs/public/images/card-cover.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/card-cover.jpeg -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'docs' 3 | - 'packages/**/**' 4 | - '!packages/cli/dist/**' 5 | - 'sb' 6 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | patch: 4 | default: 5 | target: 100% 6 | threshold: 0% 7 | -------------------------------------------------------------------------------- /docs/content/zh/docs/getting-started/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | introduction: '介绍', 3 | installation: '安装', 4 | } 5 | -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-1.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-2.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-3.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-4.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-5.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-6.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-7.jpg -------------------------------------------------------------------------------- /docs/public/images/playlist-cover-8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/docs/public/images/playlist-cover-8.jpg -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/examples/nex-ui-nextjs-app/app/favicon.ico -------------------------------------------------------------------------------- /docs/nextraTheme/README.md: -------------------------------------------------------------------------------- 1 | #### fork from https://github.com/shuding/nextra/tree/nextra-theme-docs%404.2.3/packages/nextra-theme-docs 2 | -------------------------------------------------------------------------------- /docs/nextraTheme/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getGitIssueUrl } from './get-git-issue-url' 2 | export { gitUrlParse } from './git-url-parse' 3 | -------------------------------------------------------------------------------- /docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | '@tailwindcss/postcss': {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/icon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Icon' 2 | export type { IconProps, IconPropsOverrides } from './types' 3 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/portal/index.ts: -------------------------------------------------------------------------------- 1 | export { Portal } from './Portal' 2 | export type { PortalProps } from './types' 3 | -------------------------------------------------------------------------------- /packages/system/src/tokens/index.ts: -------------------------------------------------------------------------------- 1 | export { createTokens, type Tokens } from './createTokens' 2 | 3 | export type * from './types' 4 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rxy001/nex-ui/HEAD/examples/nex-ui-nextjs-pages/public/favicon.ico -------------------------------------------------------------------------------- /packages/react/src/components/box/index.ts: -------------------------------------------------------------------------------- 1 | export { Box } from './Box' 2 | 3 | export type { BoxProps, BoxPropsOverrides } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/dialog/DialogClose.tsx: -------------------------------------------------------------------------------- 1 | import { ModalClose } from '../modal' 2 | 3 | export const DialogClose = ModalClose 4 | -------------------------------------------------------------------------------- /packages/react/src/components/drawer/DrawerClose.tsx: -------------------------------------------------------------------------------- 1 | import { ModalClose } from '../modal' 2 | 3 | export const DrawerClose = ModalClose 4 | -------------------------------------------------------------------------------- /packages/react/src/components/flex/index.ts: -------------------------------------------------------------------------------- 1 | export { Flex } from './Flex' 2 | export type { FlexProps, FlexPropsOverrides } from './types' 3 | -------------------------------------------------------------------------------- /packages/utils/src/dom/index.ts: -------------------------------------------------------------------------------- 1 | export * from './addEventListener' 2 | export * from './ownerDocument' 3 | export * from './ownerWindow' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/buttonBase/index.ts: -------------------------------------------------------------------------------- 1 | export { ButtonBase } from './ButtonBase' 2 | export type { ButtonBaseProps } from './types' 3 | -------------------------------------------------------------------------------- /packages/react/src/components/focusTrap/index.ts: -------------------------------------------------------------------------------- 1 | export { FocusTrap } from './FocusTrap' 2 | 3 | export type { FocusTrapProps } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/input/index.ts: -------------------------------------------------------------------------------- 1 | export { Input } from './Input' 2 | export type { InputProps, InputPropsOverrides } from './types' 3 | -------------------------------------------------------------------------------- /packages/react/src/components/inputBase/index.ts: -------------------------------------------------------------------------------- 1 | export { InputBase } from './InputBase' 2 | 3 | export type { InputBaseProps } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/popover/PopoverClose.tsx: -------------------------------------------------------------------------------- 1 | import { PopperClose } from '../popper' 2 | 3 | export const PopoverClose = PopperClose 4 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/motionFeatures/features.ts: -------------------------------------------------------------------------------- 1 | import { domAnimation } from 'motion/react' 2 | 3 | export default domAnimation 4 | -------------------------------------------------------------------------------- /scripts/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { pretty } from './pretty' 2 | export { rollup } from './rollup' 3 | export { copy } from './rollup-plugin-copy' 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | */.next/* 2 | dist 3 | public/* 4 | node_modules 5 | assets 6 | notes 7 | coverage 8 | .husky 9 | *.yaml 10 | build 11 | .turbo -------------------------------------------------------------------------------- /packages/react/src/components/alert/index.ts: -------------------------------------------------------------------------------- 1 | export { Alert } from './Alert' 2 | 3 | export type { AlertProps, AlertPropsOverrides } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/badge/index.ts: -------------------------------------------------------------------------------- 1 | export { Badge } from './Badge' 2 | 3 | export type { BadgeProps, BadgePropsOverrides } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/dialog/DialogTrigger.tsx: -------------------------------------------------------------------------------- 1 | import { ModalTrigger } from '../modal' 2 | 3 | export const DialogTrigger = ModalTrigger 4 | -------------------------------------------------------------------------------- /packages/react/src/components/drawer/DrawerTrigger.tsx: -------------------------------------------------------------------------------- 1 | import { ModalTrigger } from '../modal' 2 | 3 | export const DrawerTrigger = ModalTrigger 4 | -------------------------------------------------------------------------------- /packages/react/src/components/switch/index.ts: -------------------------------------------------------------------------------- 1 | export { Switch } from './Switch' 2 | export type { SwitchProps, SwitchPropsOverrides } from './types' 3 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/motionFeatures/index.ts: -------------------------------------------------------------------------------- 1 | export const motionFeatures = () => 2 | import('./features').then((res) => res.default) 3 | -------------------------------------------------------------------------------- /packages/react/src/components/button/index.tsx: -------------------------------------------------------------------------------- 1 | export { Button } from './Button' 2 | 3 | export type { ButtonProps, ButtonPropsOverrides } from './types' 4 | -------------------------------------------------------------------------------- /packages/react/src/components/divider/index.ts: -------------------------------------------------------------------------------- 1 | export { Divider } from './Divider' 2 | export type { DividerProps, DividerPropsOverrides } from './types' 3 | -------------------------------------------------------------------------------- /sb/.storybook/manager.ts: -------------------------------------------------------------------------------- 1 | import { addons } from 'storybook/manager-api' 2 | import theme from './theme' 3 | 4 | addons.setConfig({ 5 | theme, 6 | }) 7 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return Badge 5 | } 6 | -------------------------------------------------------------------------------- /packages/react/src/components/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | export { Tooltip } from './Tooltip' 2 | 3 | export type { TooltipProps, TooltipPropsOverrides } from './types' 4 | -------------------------------------------------------------------------------- /packages/utils/src/shared/env.ts: -------------------------------------------------------------------------------- 1 | export const __DEV__ = process.env.NODE_ENV !== 'production' 2 | 3 | export const __TEST__ = process.env.NODE_ENV === 'test' 4 | -------------------------------------------------------------------------------- /sb/.storybook/modes.ts: -------------------------------------------------------------------------------- 1 | export const allModes = { 2 | dark: { 3 | theme: 'dark', 4 | }, 5 | light: { 6 | theme: 'light', 7 | }, 8 | } as const 9 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Switch } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Switch } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return Switch 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/zh/docs/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'getting-started': '快速开始', 3 | styling: 'Styling', 4 | customization: '定制', 5 | components: '组件', 6 | } 7 | -------------------------------------------------------------------------------- /packages/hooks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/utils/src/react/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mergeRefs' 2 | export * from './supportRef' 3 | export * from './createContext' 4 | export * from './mergeProps' 5 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/icons/types.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | const content: React.ForwardRefExoticComponent> 3 | export default content 4 | } 5 | -------------------------------------------------------------------------------- /packages/react/src/theme/defineTheme.ts: -------------------------------------------------------------------------------- 1 | import type { Theme } from '../types/theme' 2 | 3 | export function defineTheme(theme: Theme): Theme { 4 | return theme 5 | } 6 | -------------------------------------------------------------------------------- /sb/.storybook/manager-head.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | 3 | # These owners will be the default owners for everything in the repo. 4 | * @rxy001 5 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return Badge 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Loading.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return Option 5 | } 6 | -------------------------------------------------------------------------------- /packages/icons/README.md: -------------------------------------------------------------------------------- 1 | # @nex-ui/icons 2 | 3 | Shared icons used by NexUI packages. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm i @nex-ui/icons 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/react/src/components/initColorSchemeScript/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | InitColorSchemeScript, 3 | type InitColorSchemeScriptProps, 4 | } from './InitColorSchemeScript' 5 | -------------------------------------------------------------------------------- /packages/utils/README.md: -------------------------------------------------------------------------------- 1 | # @nex-ui/utils 2 | 3 | Shared utilities used by NexUI packages. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm i @nex-ui/utils 9 | ``` 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "files.associations": { 4 | "*.css": "tailwindcss" 5 | }, 6 | "files.eol": "\n" 7 | } 8 | -------------------------------------------------------------------------------- /docs/components/docs/homepage/features/index.ts: -------------------------------------------------------------------------------- 1 | export { Styling } from './Styling' 2 | export { Theme, type ThemeProps } from './Theme' 3 | export { DarkMode } from './DarkMode' 4 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/react/src/components/provider/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Provider' 2 | 3 | export type { NexUIProviderProps } from './types' 4 | 5 | export { useNexUI } from './Context' 6 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /packages/hooks/README.md: -------------------------------------------------------------------------------- 1 | # @nex-ui/hooks 2 | 3 | A collection of React Hooks for Nex UI components. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm i @nex-ui/hooks 9 | ``` 10 | -------------------------------------------------------------------------------- /packages/react/src/components/flex/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const flexClasses = generateSlotClasses('nui-flex', ['root']) 4 | -------------------------------------------------------------------------------- /packages/react/src/components/icon/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const iconClasses = generateSlotClasses('nui-icon', ['root']) 4 | -------------------------------------------------------------------------------- /docs/content/zh/docs/styling/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'sx-prop': 'sx 属性', 3 | 'responsive-design': '响应式设计', 4 | recipes: 'Recipes', 5 | 'slot-recipes': 'Slot Recipes', 6 | } 7 | -------------------------------------------------------------------------------- /packages/utils/src/shared/upperFirst.ts: -------------------------------------------------------------------------------- 1 | export const upperFirst = (str: string) => { 2 | if (str.length === 0) return str 3 | return str.charAt(0).toUpperCase() + str.slice(1) 4 | } 5 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/Indeterminate.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return Option 5 | } 6 | -------------------------------------------------------------------------------- /docs/content/en/docs/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'getting-started': 'Getting Started', 3 | styling: 'Styling', 4 | customization: 'Customization', 5 | components: 'Components', 6 | } 7 | -------------------------------------------------------------------------------- /packages/react/src/components/divider/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const dividerClasses = generateSlotClasses('nui-divider', ['root']) 4 | -------------------------------------------------------------------------------- /packages/react/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | export { defineTheme } from './defineTheme' 2 | 3 | export { defineColorScheme } from './defineColorScheme' 4 | 5 | export { defaultConfig } from './preset' 6 | -------------------------------------------------------------------------------- /docs/app/env.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import type { FC, SVGProps } from 'react' 3 | 4 | const ReactComponent: FC> 5 | 6 | export default ReactComponent 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "moduleResolution": "Node", 6 | "baseUrl": "./" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/styled/README.md: -------------------------------------------------------------------------------- 1 | # @nex-ui/styled 2 | 3 | Styled API for creating atomic, theme-aware component styling. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm i @nex-ui/styled 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/content/en/docs/styling/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | 'sx-prop': 'The sx Prop', 3 | 'responsive-design': 'Responsive Design', 4 | recipes: 'Recipes', 5 | 'slot-recipes': 'Slot Recipes', 6 | } 7 | -------------------------------------------------------------------------------- /sb/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": [ 4 | ".storybook/*.ts", 5 | ".storybook/*.tsx", 6 | "./vite.config.ts", 7 | "./utils/*.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/src/dom/ownerDocument.ts: -------------------------------------------------------------------------------- 1 | // istanbul ignore file 2 | 3 | export function ownerDocument(node: Node | null | undefined): Document { 4 | return (node && node.ownerDocument) || document 5 | } 6 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/computePosition/middleware/index.ts: -------------------------------------------------------------------------------- 1 | export { flip } from './flip' 2 | export { offset } from './offset' 3 | export { shift } from './shift' 4 | export { arrow } from './arrow' 5 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/generateSlotClass.ts: -------------------------------------------------------------------------------- 1 | export function generateSlotClass( 2 | componentName: string, 3 | slotClass: string, 4 | ): string { 5 | return `${componentName}-${slotClass}` 6 | } 7 | -------------------------------------------------------------------------------- /docs/next-sitemap.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | 3 | const config = { 4 | siteUrl: 'https://nex-ui-docs.vercel.app', 5 | generateRobotsTxt: true, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react({})], 7 | }) 8 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/zIndices.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const zIndices = defineTokens.zIndices({ 4 | modal: 1000, 5 | popover: 2000, 6 | tooltip: 3000, 7 | }) 8 | -------------------------------------------------------------------------------- /docs/public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://nex-ui-docs.vercel.app/sitemap-0.xml 4 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from 'next' 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | reactStrictMode: true, 6 | } 7 | 8 | export default nextConfig 9 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react-swc' 3 | 4 | // https://vite.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /packages/react/src/components/badge/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const badgeSlotClasses = generateSlotClasses('nui-badge', [ 4 | 'root', 5 | 'close-button', 6 | ]) 7 | -------------------------------------------------------------------------------- /packages/react/src/components/tooltip/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const tooltipSlotClasses = generateSlotClasses('nui-tooltip', [ 4 | 'root', 5 | 'content', 6 | ]) 7 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/index.ts: -------------------------------------------------------------------------------- 1 | export * from './scales' 2 | export * from './aliases' 3 | export * from './breakpoints' 4 | export * from './tokens' 5 | export * from './semanticTokens' 6 | export * from './selectors' 7 | -------------------------------------------------------------------------------- /packages/styled/src/index.ts: -------------------------------------------------------------------------------- 1 | // export * from './styled' 2 | 3 | export * from './nex' 4 | 5 | export type { 6 | // NexStyled, 7 | NexFactory, 8 | NexComponent, 9 | CreateNexComponent, 10 | } from './types' 11 | -------------------------------------------------------------------------------- /packages/react/src/components/popover/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const popoverSlotClasses = generateSlotClasses('nui-popover', [ 4 | 'root', 5 | 'content-root', 6 | ]) 7 | -------------------------------------------------------------------------------- /packages/styled/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "paths": { 7 | "~/*": ["../../*"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/system/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "paths": { 6 | "~/*": ["../../*"] 7 | }, 8 | "baseUrl": "./" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /sb/chromatic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "onlyChanged": true, 3 | "projectId": "Project:68511fa4aae3e68f491ff937", 4 | "storybookBaseDir": "sb", 5 | "zip": true, 6 | "exitZeroOnChanges": false, 7 | "buildScriptName": "build" 8 | } 9 | -------------------------------------------------------------------------------- /packages/utils/src/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './kebabCase' 2 | export * from './camelCase' 3 | export * from './chain' 4 | export * from './env' 5 | export * from './is' 6 | export * from './walkObject' 7 | export * from './upperFirst' 8 | -------------------------------------------------------------------------------- /packages/react/src/components/button/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const buttonSlotClasses = generateSlotClasses('nui-button', [ 4 | 'root', 5 | 'start-icon', 6 | 'end-icon', 7 | ]) 8 | -------------------------------------------------------------------------------- /docs/content/_demo/divider/index.tsx: -------------------------------------------------------------------------------- 1 | import usageCode from './Usage.demo?raw' 2 | import UsageDemo from './Usage.demo' 3 | 4 | export const divider = { 5 | usage: { 6 | code: usageCode, 7 | demo: , 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /docs/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/react/src/theme/defineColorScheme.ts: -------------------------------------------------------------------------------- 1 | import type { ColorSchemeProviderProps } from '@nex-ui/system' 2 | 3 | export const defineColorScheme = ( 4 | props: Omit, 5 | ) => { 6 | return props 7 | } 8 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/semanticTokens/borders.ts: -------------------------------------------------------------------------------- 1 | import { defineSemanticTokens } from '@nex-ui/system' 2 | 3 | export const borders = defineSemanticTokens.borders({ 4 | focusVisibleOutline: '{borders.md} {colors.blue.primary}', 5 | }) 6 | -------------------------------------------------------------------------------- /sb/.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /packages/system/src/systemProvider/index.tsx: -------------------------------------------------------------------------------- 1 | export { useSystem } from './SystemContext' 2 | 3 | export * from './SystemProvider' 4 | 5 | export type { SystemContext } from './SystemContext' 6 | 7 | export type { SystemProviderProps } from './types' 8 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/next.config.ts: -------------------------------------------------------------------------------- 1 | import type { NextConfig } from 'next' 2 | 3 | const nextConfig: NextConfig = { 4 | /* config options here */ 5 | compiler: { 6 | emotion: true, 7 | }, 8 | } 9 | 10 | export default nextConfig 11 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/borderWidths.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const borderWidths = defineTokens.borderWidths({ 4 | xs: '0.5px', 5 | sm: '1px', 6 | md: '2px', 7 | lg: '4px', 8 | xl: '8px', 9 | }) 10 | -------------------------------------------------------------------------------- /packages/system/src/systemProvider/types.ts: -------------------------------------------------------------------------------- 1 | import type { ColorSchemeProviderProps } from '../colorScheme' 2 | import type { SystemConfig } from '../system' 3 | 4 | export interface SystemProviderProps 5 | extends ColorSchemeProviderProps, 6 | SystemConfig {} 7 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/breakpoints.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@nex-ui/system' 2 | 3 | export const breakpoints = defineConfig.breakpoints({ 4 | sm: '640px', 5 | md: '768px', 6 | lg: '1024px', 7 | xl: '1280px', 8 | '2xl': '1536px', 9 | }) 10 | -------------------------------------------------------------------------------- /docs/content/_demo/alert/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Alert } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/src/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | padding: 0; 10 | margin: 0; 11 | } 12 | 13 | a { 14 | color: inherit; 15 | text-decoration: none; 16 | } 17 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/check.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/portal/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | 3 | export interface PortalProps { 4 | container?: Element | (() => Element | null) | null 5 | children?: ReactNode 6 | onMount?: () => void 7 | onUnmount?: () => void 8 | } 9 | -------------------------------------------------------------------------------- /packages/utils/src/dom/ownerWindow.ts: -------------------------------------------------------------------------------- 1 | // istanbul ignore file 2 | 3 | import { ownerDocument } from './ownerDocument' 4 | 5 | export function ownerWindow(node: Node | undefined | null): Window { 6 | const doc = ownerDocument(node) 7 | return doc.defaultView || window 8 | } 9 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/src/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | padding: 0; 10 | margin: 0; 11 | } 12 | 13 | a { 14 | color: inherit; 15 | text-decoration: none; 16 | } 17 | -------------------------------------------------------------------------------- /packages/react/src/components/radioGroup/index.ts: -------------------------------------------------------------------------------- 1 | export { Radio } from './Radio' 2 | export { RadioGroup } from './RadioGroup' 3 | 4 | export type { 5 | RadioProps, 6 | RadioGroupProps, 7 | RadioPropsOverrides, 8 | RadioGroupPropsOverrides, 9 | } from './types' 10 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/borders.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const borders = defineTokens.borders({ 4 | xs: '0.5px solid', 5 | sm: '1px solid', 6 | md: '2px solid', 7 | lg: '4px solid', 8 | xl: '8px solid', 9 | }) 10 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | padding: 0; 10 | margin: 0; 11 | } 12 | 13 | a { 14 | color: inherit; 15 | text-decoration: none; 16 | } 17 | -------------------------------------------------------------------------------- /packages/icons/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src"], 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "paths": { 7 | "@storybook/react-vite": ["../../sb/node_modules/@storybook/react-vite"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/semanticTokens/index.ts: -------------------------------------------------------------------------------- 1 | import { defineSemanticTokens } from '@nex-ui/system' 2 | import { colors } from './colors' 3 | import { borders } from './borders' 4 | 5 | export const semanticTokens = defineSemanticTokens({ 6 | colors, 7 | borders, 8 | }) 9 | -------------------------------------------------------------------------------- /docs/content/_demo/tooltip/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip, Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /docs/nextraTheme/utils/git-url-parse.ts: -------------------------------------------------------------------------------- 1 | export function gitUrlParse(url: string) { 2 | const { href, origin, pathname } = new URL(url) 3 | 4 | const [, owner, name] = pathname.split('/', 3) 5 | return { 6 | href, 7 | origin, 8 | owner, 9 | name, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | max-width: 100vw; 4 | overflow-x: hidden; 5 | } 6 | 7 | * { 8 | box-sizing: border-box; 9 | padding: 0; 10 | margin: 0; 11 | } 12 | 13 | a { 14 | color: inherit; 15 | text-decoration: none; 16 | } 17 | -------------------------------------------------------------------------------- /packages/react/src/components/avatar/index.ts: -------------------------------------------------------------------------------- 1 | export { Avatar } from './Avatar' 2 | 3 | export { AvatarGroup } from './AvatarGroup' 4 | 5 | export type { 6 | AvatarProps, 7 | AvatarPropsOverrides, 8 | AvatarGroupProps, 9 | AvatarGroupPropsOverrides, 10 | } from './types' 11 | -------------------------------------------------------------------------------- /packages/react/src/components/input/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const inputClasses = generateSlotClasses('nui-input', [ 4 | 'root', 5 | 'input', 6 | 'clear-button', 7 | 'suffix', 8 | 'prefix', 9 | 'label', 10 | ]) 11 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/isFocusVisible.ts: -------------------------------------------------------------------------------- 1 | export const isFocusVisible = (element: Element): boolean => { 2 | try { 3 | return element.matches(':focus-visible') 4 | } catch { 5 | /* empty */ 6 | } 7 | 8 | // istanbul ignore next 9 | return false 10 | } 11 | -------------------------------------------------------------------------------- /sb/.storybook/theme.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'storybook/theming' 2 | // @ts-ignore 3 | import logo from './logo.png' 4 | 5 | export default create({ 6 | base: 'dark', 7 | brandTitle: 'Nex UI', 8 | brandUrl: 'https://github.com/rxy001/nex-ui', 9 | brandImage: logo, 10 | }) 11 | -------------------------------------------------------------------------------- /docs/components/docs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './homepage' 2 | export * from './AliasTable' 3 | export * from './BreakpointTable' 4 | export * from './ScaleTable' 5 | export * from './SelectorTable' 6 | export * from './ColorsSet' 7 | export * from './AvailableProps' 8 | export * from './TokensTable' 9 | -------------------------------------------------------------------------------- /docs/content/_demo/alert/HideIcon.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Alert } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/input/Clearable.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/Sizes.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Switch } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/hooks/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useEvent' 2 | export * from './useClipboard' 3 | export * from './useFocusRing' 4 | export * from './useControlledState' 5 | export * from './useLatest' 6 | export * from './useDebounce' 7 | export * from './useUnmount' 8 | export * from './useMergeRefs' 9 | -------------------------------------------------------------------------------- /.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://prettier.io/docs/configuration 3 | * @type {import("prettier").Config} 4 | */ 5 | 6 | export default { 7 | semi: false, 8 | singleQuote: true, 9 | tabWidth: 2, 10 | useTabs: false, 11 | jsxSingleQuote: true, 12 | endOfLine: 'lf', 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/Outlined.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/content/_demo/flex/Gap.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/alert/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const alertSlotClasses = generateSlotClasses('nui-alert', [ 4 | 'root', 5 | 'icon', 6 | 'content', 7 | 'title', 8 | 'description', 9 | 'close-button', 10 | ]) 11 | -------------------------------------------------------------------------------- /packages/react/src/theme/__tests__/defineTheme.test.ts: -------------------------------------------------------------------------------- 1 | import { defineTheme } from '../index' 2 | 3 | describe('defineTheme', () => { 4 | it('should return configuration as-is', () => { 5 | const config = {} as const 6 | 7 | expect(defineTheme(config)).toBe(config) 8 | }) 9 | }) 10 | -------------------------------------------------------------------------------- /docs/components/docs/homepage/features/demos/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Playlist } from './Playlist.demo' 2 | export { default as MusicPlayer } from './MusicPlayer.demo' 3 | export { default as playlistCode } from './Playlist.demo?raw' 4 | export { default as musicPlayerCode } from './MusicPlayer.demo?raw' 5 | -------------------------------------------------------------------------------- /docs/content/_demo/card/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Card, CardBody } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | Beautiful, modern and reliable React component library. 8 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/react/src/components/accordion/index.ts: -------------------------------------------------------------------------------- 1 | export { Accordion } from './Accordion' 2 | export { AccordionItem } from './AccordionItem' 3 | 4 | export type { 5 | AccordionProps, 6 | AccordionPropsOverrides, 7 | AccordionItemProps, 8 | AccordionItemPropsOverrides, 9 | } from './types' 10 | -------------------------------------------------------------------------------- /packages/react/src/components/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | export { Checkbox } from './Checkbox' 2 | 3 | export { CheckboxGroup } from './CheckboxGroup' 4 | 5 | export type { 6 | CheckboxPropsOverrides, 7 | CheckboxProps, 8 | CheckboxGroupProps, 9 | CheckboxGroupPropsOverrides, 10 | } from './types' 11 | -------------------------------------------------------------------------------- /tests/shared/utils.ts: -------------------------------------------------------------------------------- 1 | export type KebabCase = S extends `${infer S1}${infer S2}` 2 | ? S2 extends Uncapitalize 3 | ? `${Uncapitalize}${KebabCase}` 4 | : `${Uncapitalize}-${KebabCase}` 5 | : S 6 | 7 | export { kebabCase } from '../../packages/utils/src/index' 8 | -------------------------------------------------------------------------------- /docs/components/table/Td.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type TdProps = ComponentPropsWithoutRef<'td'> 5 | 6 | export const Td = ({ className, ...props }: TdProps) => ( 7 | 8 | ) 9 | -------------------------------------------------------------------------------- /docs/components/table/Th.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type ThProps = ComponentPropsWithoutRef<'th'> 5 | 6 | export const Th = ({ className, ...props }: ThProps) => ( 7 | 8 | ) 9 | -------------------------------------------------------------------------------- /packages/hooks/src/useUnmount.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { __DEV__ } from '@nex-ui/utils' 3 | import { useLatest } from './useLatest' 4 | 5 | export const useUnmount = (fn: () => void) => { 6 | const fnRef = useLatest(fn) 7 | 8 | useEffect(() => fnRef.current, [fnRef]) 9 | } 10 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/react/src/components/switch/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const switchClasses = generateSlotClasses('nui-switch', [ 4 | 'root', 5 | 'input', 6 | 'track', 7 | 'thumb', 8 | 'start-icon', 9 | 'end-icon', 10 | 'label', 11 | ]) 12 | -------------------------------------------------------------------------------- /packages/utils/src/shared/chain.ts: -------------------------------------------------------------------------------- 1 | export const chain = ( 2 | ...callbacks: Array<((...args: TArgs) => void) | null | undefined | false> 3 | ) => { 4 | return (...args: TArgs) => { 5 | for (const cb of callbacks) { 6 | if (cb) cb(...args) 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FlexCenter' 2 | export * from './docs' 3 | export * from './Example' 4 | export * from './CodeBlock' 5 | export * from './sandpack' 6 | export * from './ComponentLinks' 7 | export * from './PropsTable' 8 | export * from './SlotsTable' 9 | export * from './GradientText' 10 | -------------------------------------------------------------------------------- /docs/components/table/index.ts: -------------------------------------------------------------------------------- 1 | export { Thead } from './Thead' 2 | export { Tbody } from './Tbody' 3 | export { Th } from './Th' 4 | export { Td } from './Td' 5 | export { Tr } from './Tr' 6 | export { Table } from './Table' 7 | export { DefaultItem } from './DefaultItem' 8 | export { HighlightItem } from './HighlightItem' 9 | -------------------------------------------------------------------------------- /docs/content/_demo/input/Invalid.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/components/table/Thead.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type TheadProps = ComponentPropsWithoutRef<'thead'> 5 | 6 | export const Thead = ({ className, ...props }: TheadProps) => ( 7 | 8 | ) 9 | -------------------------------------------------------------------------------- /docs/content/_demo/input/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/input/ReadOnly.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /docs/middleware.ts: -------------------------------------------------------------------------------- 1 | export { middleware } from 'nextra/locales' 2 | 3 | export const config = { 4 | // Matcher ignoring `/_next/` and `/api/` 5 | matcher: [ 6 | '/((?!api|_next/static|_next/image|avatars|images|favicon.ico|icon.svg|apple-icon.png|og-image.svg|robots.txt|sitemap|manifest|_pagefind).*)', 7 | ], 8 | } 9 | -------------------------------------------------------------------------------- /docs/public/robots.txt: -------------------------------------------------------------------------------- 1 | # * 2 | User-agent: * 3 | Allow: / 4 | 5 | # Host 6 | Host: https://nex-ui-docs.vercel.app 7 | 8 | # Disallow sensitive paths 9 | Disallow: /api/ 10 | Disallow: /_next/ 11 | Disallow: /admin/ 12 | Disallow: /private/ 13 | 14 | # Sitemaps 15 | Sitemap: https://nex-ui-docs.vercel.app/sitemap.xml 16 | -------------------------------------------------------------------------------- /packages/system/src/recipes/index.ts: -------------------------------------------------------------------------------- 1 | export { defineRecipe } from './defineRecipe' 2 | export { defineSlotRecipe } from './defineSlotRecipe' 3 | 4 | export type { 5 | RecipeConfig, 6 | RecipeRuntimeFn, 7 | SlotRecipeConfig, 8 | SlotRecipeRuntimeFn, 9 | RecipeVariants, 10 | RecipeSlots, 11 | } from './types' 12 | -------------------------------------------------------------------------------- /packages/utils/src/shared/kebabCase.ts: -------------------------------------------------------------------------------- 1 | export function kebabCase(str: string): string { 2 | if (typeof str !== 'string' || str.trim() === '') { 3 | return str 4 | } 5 | 6 | return str 7 | .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2') 8 | .replace(/([a-z\d])([A-Z])/g, '$1-$2') 9 | .toLowerCase() 10 | } 11 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/radii.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const radii = defineTokens.radii({ 4 | xs: '4px', 5 | sm: '6px', 6 | md: '8px', 7 | lg: '12px', 8 | xl: '14px', 9 | '2xl': '16px', 10 | '3xl': '18px', 11 | full: '9999px', 12 | none: '0px', 13 | }) 14 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src", "../../sb/utils"], 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "paths": { 7 | "~/*": ["../../*"], 8 | "@storybook/react-vite": ["../../sb/node_modules/@storybook/react-vite"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/WithCloseButton.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { Badge } from '@nex-ui/react' 4 | 5 | export default function App() { 6 | return ( 7 | { 10 | alert('Close') 11 | }} 12 | > 13 | Badge 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /docs/content/_demo/flex/Direction.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Checkbox } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Item 1 7 | Item 2 8 | Item 3 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /sb/utils/constants.ts: -------------------------------------------------------------------------------- 1 | export const RADII = ['none', 'sm', 'md', 'lg', 'full'] as const 2 | 3 | export const COLORS = [ 4 | 'blue', 5 | 'orange', 6 | 'cyan', 7 | 'gray', 8 | 'red', 9 | 'green', 10 | 'pink', 11 | 'purple', 12 | 'yellow', 13 | ] as const 14 | 15 | export const SIZES = ['sm', 'md', 'lg'] as const 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{bat,cmd}] 15 | end_of_line = crlf 16 | 17 | [*.sh] 18 | end_of_line = lf 19 | -------------------------------------------------------------------------------- /docs/app/_dictionaries/zh.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dark: '深色', 3 | light: '浅色', 4 | system: '系统', 5 | backToTop: '滚动到顶部', 6 | lastUpdated: '最后更新时间', 7 | logo: { 8 | title: 'React 组件库', 9 | }, 10 | editPage: '在 Github 编辑此页', 11 | tocTitle: '在此页面', 12 | feedback: { 13 | content: '有问题吗?反馈给我们', 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Option 7 | 8 | Option 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/content/_demo/tooltip/Delay.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip, Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /docs/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'eslint/config' 2 | import config from '../eslint.config.mjs' 3 | 4 | export default defineConfig([ 5 | { 6 | extends: [config], 7 | }, 8 | { 9 | files: ['**/*.{ts,tsx}'], 10 | rules: { 11 | 'react/require-default-props': 'off', 12 | }, 13 | }, 14 | ]) 15 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/skip-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/skip-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Sizes.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/icons/pnpm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /scripts/utils/pretty.ts: -------------------------------------------------------------------------------- 1 | import { format } from 'prettier' 2 | // @ts-ignore 3 | import config from '../../.prettierrc.mjs' 4 | import type { Options } from 'prettier' 5 | 6 | export function pretty(value: any, options: Options = {}) { 7 | return format(value, { 8 | parser: 'typescript', 9 | ...config, 10 | ...options, 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/Sizes.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Small 7 | Medium 8 | Large 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/react/src/components/box/__tests__/Box.test.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | testComponentStability, 3 | testRefForwarding, 4 | testRootClassName, 5 | } from '~/tests/shared' 6 | import { Box } from '../index' 7 | 8 | describe('Box', () => { 9 | testComponentStability() 10 | 11 | testRefForwarding() 12 | 13 | testRootClassName() 14 | }) 15 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": "@changesets/changelog-git", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["@nex-ui/storybook", "@nex-ui/docs"] 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/WithIcons.demo.tsx: -------------------------------------------------------------------------------- 1 | import { GithubOutlined } from '@nex-ui/icons' 2 | import { Badge, Flex } from '@nex-ui/react' 3 | 4 | export default function App() { 5 | return ( 6 | 7 | }>Github 8 | }>Github 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/radioGroup/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { RadioGroup, Radio } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Banana 8 | Cherry 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Radii.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/index.ts: -------------------------------------------------------------------------------- 1 | export { useActiveAnchor, setActiveSlug } from './active-anchor' 2 | export { useConfig, ConfigProvider } from './config' 3 | export { useFocusedRoute, setFocusedRoute } from './focused-route' 4 | export { useMenu, setMenu } from './menu' 5 | export { ThemeConfigProvider, useThemeConfig } from './theme-config' 6 | export { useToc, setToc } from './toc' 7 | -------------------------------------------------------------------------------- /packages/react/src/components/avatar/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const avatarSlotClasses = generateSlotClasses('nui-avatar', [ 4 | 'root', 5 | 6 | 'outlined', 7 | 8 | 'img', 9 | ]) 10 | 11 | export const avatarGroupSlotClasses = generateSlotClasses('nui-avatar-group', [ 12 | 'root', 13 | 'surplus', 14 | ]) 15 | -------------------------------------------------------------------------------- /packages/react/src/types/generated/breakpoints.ts: -------------------------------------------------------------------------------- 1 | import type { Overwrite } from '../utils' 2 | 3 | export interface BreakpointsOverrides {} 4 | 5 | export type Breakpoints = Overwrite 6 | 7 | export interface DefaultBreakpoints { 8 | sm?: string 9 | md?: string 10 | lg?: string 11 | xl?: string 12 | '2xl'?: string 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Sizes.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Extra Small 7 | Small 8 | Medium 9 | Large 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/content/_demo/radioGroup/Disabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { RadioGroup, Radio } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Banana 8 | Cherry 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/WithIcons.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Switch } from '@nex-ui/react' 2 | import { SunFilled, MoonFilled } from '@nex-ui/icons' 3 | 4 | export default function App() { 5 | return ( 6 | } 8 | endIcon={} 9 | size='lg' 10 | color='green' 11 | defaultChecked 12 | /> 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/react/src/components/accordion/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const accordionSlotClasses = generateSlotClasses('nui-accordion', [ 4 | 'root', 5 | ]) 6 | 7 | export const accordionItemSlotClasses = generateSlotClasses( 8 | 'nui-accordion-item', 9 | ['root', 'heading', 'trigger', 'content', 'indicator'], 10 | ) 11 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/GroupDisabled.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox, CheckboxGroup } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Pear 8 | Orange 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/nextraTheme/index.ts: -------------------------------------------------------------------------------- 1 | export { useThemeConfig, useConfig, useMenu, setMenu } from './stores' 2 | export { useMDXComponents } from './mdx-components' 3 | export { Link } from './mdx-components/link' 4 | export { Layout } from './layout' 5 | export { 6 | NotFoundPage, 7 | Navbar, 8 | ThemeSwitch, 9 | LocaleSwitch, 10 | LastUpdated, 11 | Footer, 12 | } from './components' 13 | -------------------------------------------------------------------------------- /packages/react/src/components/radioGroup/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const radioClasses = generateSlotClasses('nui-radio', [ 4 | 'root', 5 | 'input', 6 | 'label', 7 | 'dot', 8 | ]) 9 | 10 | export const radioGroupClasses = generateSlotClasses('nui-radio-group', [ 11 | 'root', 12 | 'label', 13 | 'wrapper', 14 | ]) 15 | -------------------------------------------------------------------------------- /packages/react/src/theme/preset.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@nex-ui/system' 2 | import { 3 | scales, 4 | aliases, 5 | breakpoints, 6 | tokens, 7 | semanticTokens, 8 | selectors, 9 | } from './system' 10 | 11 | export const defaultConfig = defineConfig({ 12 | aliases, 13 | scales, 14 | breakpoints, 15 | selectors, 16 | tokens, 17 | semanticTokens, 18 | }) 19 | -------------------------------------------------------------------------------- /docs/components/table/Table.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type TableProps = ComponentPropsWithoutRef<'table'> 5 | 6 | export const Table = ({ className, ...props }: TableProps) => ( 7 |
8 | 9 | 10 | ) 11 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/Fallback.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | X 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/MoonFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const MoonFilled = createIcon( 6 | , 10 | 'MoonFilled', 11 | ) 12 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/exclamation-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/system/src/layers/types.ts: -------------------------------------------------------------------------------- 1 | import type { Interpolation } from '../types' 2 | 3 | export type CascadeLayer = 'global' | 'css' 4 | 5 | export type CreateLayersConfig = { 6 | cssCascadeLayersDisabled?: boolean 7 | prefix?: string 8 | } 9 | 10 | export type Layers = { 11 | atRules: string 12 | wrapWithLayer: (layer: CascadeLayer, styles: Interpolation) => Interpolation 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/radioGroup/DefaultValue.demo.tsx: -------------------------------------------------------------------------------- 1 | import { RadioGroup, Radio } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Banana 8 | Cherry 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/content/_demo/radioGroup/Vertical.demo.tsx: -------------------------------------------------------------------------------- 1 | import { RadioGroup, Radio } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Banana 8 | Cherry 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/CheckOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CheckOutlined = createIcon( 6 | , 14 | 'CheckOutlined', 15 | ) 16 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/exclamation-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/react/src/components/checkbox/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const checkboxClasses = generateSlotClasses('nui-checkbox', [ 4 | 'root', 5 | 'input', 6 | 'label', 7 | 'icon', 8 | ]) 9 | 10 | export const checkboxGroupClasses = generateSlotClasses('nui-checkbox-group', [ 11 | 'root', 12 | 'label', 13 | 'wrapper', 14 | ]) 15 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Variants.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /docs/icons/accessibility.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import { NexUIProvider } from '@nex-ui/react' 4 | import App from './App.tsx' 5 | import './index.css' 6 | 7 | createRoot(document.getElementById('root')!).render( 8 | 9 | 10 | 11 | 12 | , 13 | ) 14 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/HeartFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const HeartFilled = createIcon( 6 | , 10 | 'HeartFilled', 11 | ) 12 | -------------------------------------------------------------------------------- /packages/system/src/colorScheme/index.ts: -------------------------------------------------------------------------------- 1 | export { useColorScheme } from './ColorSchemeContex' 2 | export { 3 | ColorSchemeProvider, 4 | createGetColorSchemeSelector, 5 | } from './ColorSchemeProvider' 6 | 7 | export { InitColorSchemeScript } from './InitColorSchemeScript' 8 | 9 | export type { 10 | ColorSchemeProviderProps, 11 | InitColorSchemeScriptProps, 12 | Mode, 13 | } from './types' 14 | -------------------------------------------------------------------------------- /docs/app/_dictionaries/i18nConfig.ts: -------------------------------------------------------------------------------- 1 | import type EnglishLocale from './en' 2 | 3 | export const i18n = { 4 | defaultLocale: 'zh', 5 | locales: ['en', 'zh'], 6 | } as const 7 | 8 | export type Locale = (typeof i18n)['locales'][number] 9 | 10 | export type Dictionary = typeof EnglishLocale 11 | 12 | export type Dictionaries = Record< 13 | Locale, 14 | () => Promise<{ default: Dictionary }> 15 | > 16 | -------------------------------------------------------------------------------- /docs/content/_demo/alert/WithAction.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Alert, Button } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 10 | Action 11 | 12 | } 13 | /> 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Variants.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Solid 7 | Outlined 8 | Faded 9 | Subtle 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from 'next' 3 | 4 | type Data = { 5 | name: string 6 | } 7 | 8 | export default function handler( 9 | req: NextApiRequest, 10 | res: NextApiResponse, 11 | ) { 12 | res.status(200).json({ name: 'John Doe' }) 13 | } 14 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react' 2 | import { createRoot } from 'react-dom/client' 3 | import { NexUIProvider } from '@nex-ui/react' 4 | import App from './App.tsx' 5 | import './index.css' 6 | 7 | createRoot(document.getElementById('root')!).render( 8 | 9 | 10 | 11 | 12 | , 13 | ) 14 | -------------------------------------------------------------------------------- /docs/app/_dictionaries/en.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dark: 'Dark', 3 | light: 'Light', 4 | system: 'System', 5 | backToTop: 'Scroll to top', 6 | lastUpdated: 'Last updated on', 7 | logo: { 8 | title: 'React Component Library', 9 | }, 10 | editPage: 'Edit this page on GitHub', 11 | tocTitle: 'On This Page', 12 | feedback: { 13 | content: 'Question? Give us feedback', 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /packages/hooks/src/useMergeRefs.ts: -------------------------------------------------------------------------------- 1 | import { mergeRefs } from '@nex-ui/utils' 2 | import { useMemo } from 'react' 3 | import { useLatest } from './useLatest' 4 | import type { Ref } from 'react' 5 | 6 | export const useMergeRefs = (...refs: Array | undefined>) => { 7 | const latest = useLatest(refs) 8 | 9 | return useMemo(() => { 10 | return mergeRefs(...latest.current) 11 | }, [latest]) 12 | } 13 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/check-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "**/*.{cjs,mjs,js,jsx,ts,tsx,css,json,md,mdx}": "prettier --write . --config .prettierrc.mjs", 3 | "packages/**/*.{cjs,mjs,js,jsx,ts,tsx}": "eslint -c eslint.config.mjs --max-warnings=0 --fix", 4 | "scripts/**/*.{cjs,mjs,js,jsx,ts,tsx}": "eslint -c eslint.config.mjs --max-warnings=0 --fix", 5 | "docs/**/*.{cjs,mjs,js,jsx,ts,tsx}": "eslint -c ./docs/eslint.config.mjs --max-warnings=0 --fix" 6 | } 7 | -------------------------------------------------------------------------------- /packages/hooks/src/__tests__/useUnmount.test.ts: -------------------------------------------------------------------------------- 1 | import { renderHook } from '@testing-library/react' 2 | import { useUnmount } from '../index' 3 | 4 | describe('useUnmount', () => { 5 | it('should call the cleanup function on unmount', () => { 6 | const cleanup = jest.fn() 7 | const { unmount } = renderHook(() => useUnmount(cleanup)) 8 | unmount() 9 | expect(cleanup).toHaveBeenCalled() 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /packages/react/src/components/checkbox/IndeterminateIcon.tsx: -------------------------------------------------------------------------------- 1 | export const IndeterminateIcon = () => { 2 | return ( 3 | 10 | 11 | 12 | ) 13 | } 14 | 15 | IndeterminateIcon.displayName = 'IndeterminateIcon' 16 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/toc.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand' 2 | import type { Heading } from 'nextra' 3 | import type { Dispatch } from 'react' 4 | 5 | const useTocStore = create<{ 6 | toc: Heading[] 7 | }>(() => ({ 8 | toc: [], 9 | })) 10 | 11 | export const useToc = () => useTocStore((state) => state.toc) 12 | 13 | export const setToc: Dispatch = (toc) => { 14 | useTocStore.setState({ toc }) 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/computePosition/index.ts: -------------------------------------------------------------------------------- 1 | export { computePosition } from './computePosition' 2 | export { getOverflowAncestors } from './getOverflowAncestors' 3 | 4 | export type { 5 | Placement, 6 | FlipOptions, 7 | ArrowOptions, 8 | Middleware, 9 | MiddlewareData, 10 | ComputePositionOptions, 11 | MiddlewareState, 12 | Alignment, 13 | Side, 14 | OffsetOptions, 15 | } from './types' 16 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/ChevronUpOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ChevronUpOutlined = createIcon( 6 | , 12 | 'ChevronUpOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /docs/components/table/Tr.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type TrProps = ComponentPropsWithoutRef<'tr'> 5 | 6 | export const Tr = ({ className, ...props }: TrProps) => ( 7 | 14 | ) 15 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/GroupVertical.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox, CheckboxGroup } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Apple 7 | Pear 8 | Orange 9 | 10 | ) 11 | } 12 | -------------------------------------------------------------------------------- /docs/components/sandpack/IconButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from '@nex-ui/react' 2 | import type { ButtonProps } from '@nex-ui/react' 3 | import type { ElementType } from 'react' 4 | 5 | const sx = { 6 | color: 'white', 7 | _hover: { 8 | bg: '#6d6d6f', 9 | }, 10 | } 11 | 12 | export const IconButton = (props: ButtonProps) => ( 13 | 14 | ) 15 | -------------------------------------------------------------------------------- /docs/content/_demo/input/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 13 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/SkipBackwardFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const SkipBackwardFilled = createIcon( 6 | , 10 | 'SkipBackwardFilled', 11 | ) 12 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/SkipForwardFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const SkipForwardFilled = createIcon( 6 | , 10 | 'SkipForwardFilled', 11 | ) 12 | -------------------------------------------------------------------------------- /packages/react/src/theme/__tests__/defineColorScheme.test.ts: -------------------------------------------------------------------------------- 1 | import { defineColorScheme } from '../index' 2 | 3 | describe('defineColorScheme', () => { 4 | it('should return configuration as-is', () => { 5 | const config = { 6 | colorSchemeSelector: 'data', 7 | defaultMode: 'light', 8 | modeStorageKey: 'color-scheme', 9 | } as const 10 | 11 | expect(defineColorScheme(config)).toBe(config) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/app/_dictionaries/getDictionary.ts: -------------------------------------------------------------------------------- 1 | import type { Dictionaries, Dictionary, Locale } from './i18nConfig' 2 | 3 | const dictionaries: Dictionaries = { 4 | en: () => import('./en'), 5 | zh: () => import('./zh'), 6 | } 7 | 8 | export async function getDictionary(locale: Locale): Promise { 9 | const { default: dictionary } = await ( 10 | dictionaries[locale] || dictionaries.en 11 | )() 12 | 13 | return dictionary 14 | } 15 | -------------------------------------------------------------------------------- /docs/components/docs/homepage/features/Styling.tsx: -------------------------------------------------------------------------------- 1 | import { CodeWindow } from '../CodeWindow' 2 | import { Playlist, playlistCode } from './demos' 3 | 4 | export const Styling = () => { 5 | return ( 6 |
7 | 8 | 9 | {playlistCode} 10 | 11 |
12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '@/styles/globals.css' 2 | import { NexUIProvider } from '@nex-ui/react' 3 | import type { AppProps } from 'next/app' 4 | 5 | const colorScheme = { colorSchemeSelector: 'class' } 6 | 7 | export default function App({ Component, pageProps }: AppProps) { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /packages/react/src/components/popover/index.ts: -------------------------------------------------------------------------------- 1 | export { Popover } from './Popover' 2 | export { PopoverTrigger } from './PopoverTrigger' 3 | export { PopoverContent } from './PopoverContent' 4 | export { PopoverClose } from './PopoverClose' 5 | 6 | export type { 7 | PopoverProps, 8 | PopoverPropsOverrides, 9 | PopoverContentProps, 10 | PopoverContentPropsOverrides, 11 | PopoverTriggerProps, 12 | PopoverCloseProps, 13 | } from './types' 14 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from 'next/document' 2 | import { InitColorSchemeScript } from '@nex-ui/react' 3 | 4 | export default function Document() { 5 | return ( 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-conventional"], 3 | 4 | "rules": { 5 | "type-enum": [ 6 | 2, 7 | "always", 8 | [ 9 | "build", 10 | "chore", 11 | "ci", 12 | "docs", 13 | "feat", 14 | "fix", 15 | "perf", 16 | "refactor", 17 | "revert", 18 | "style", 19 | "test", 20 | "story" 21 | ] 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/focused-route.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand' 2 | import type { Dispatch } from 'react' 3 | 4 | const useFocusedRouteStore = create<{ 5 | focused: string 6 | }>(() => ({ 7 | focused: '', 8 | })) 9 | 10 | export const useFocusedRoute = () => 11 | useFocusedRouteStore((state) => state.focused) 12 | 13 | export const setFocusedRoute: Dispatch = (focused) => { 14 | useFocusedRouteStore.setState({ focused }) 15 | } 16 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/content/en/docs/components/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | accordion: 'Accordion', 3 | alert: 'Alert', 4 | avatar: 'Avatar', 5 | badge: 'Badge', 6 | button: 'Button', 7 | card: 'Card', 8 | checkbox: 'Checkbox', 9 | dialog: 'Dialog', 10 | divider: 'Divider', 11 | drawer: 'Drawer', 12 | flex: 'Flex', 13 | input: 'Input', 14 | popover: 'Popover', 15 | radioGroup: 'RadioGroup', 16 | switch: 'Switch', 17 | tooltip: 'Tooltip', 18 | } 19 | -------------------------------------------------------------------------------- /docs/content/zh/docs/components/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | accordion: 'Accordion', 3 | alert: 'Alert', 4 | avatar: 'Avatar', 5 | badge: 'Badge', 6 | button: 'Button', 7 | card: 'Card', 8 | checkbox: 'Checkbox', 9 | dialog: 'Dialog', 10 | divider: 'Divider', 11 | drawer: 'Drawer', 12 | flex: 'Flex', 13 | input: 'Input', 14 | popover: 'Popover', 15 | radioGroup: 'RadioGroup', 16 | switch: 'Switch', 17 | tooltip: 'Tooltip', 18 | } 19 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/ChevronDownOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ChevronDownOutlined = createIcon( 6 | , 12 | 'ChevronDownOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/ChevronLeftOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ChevronLeftOutlined = createIcon( 6 | , 12 | 'ChevronLeftOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/ChevronRightOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ChevronRightOutlined = createIcon( 6 | , 12 | 'ChevronRightOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './dom' 2 | export * from './react' 3 | export * from './shared' 4 | 5 | export { default as merge } from 'lodash.merge' 6 | 7 | export { default as memoize } from 'lodash.memoize' 8 | 9 | export { default as mergeWith } from 'lodash.mergewith' 10 | 11 | export { default as get } from 'lodash.get' 12 | 13 | export { default as clamp } from 'lodash.clamp' 14 | 15 | export { default as debounce } from 'lodash.debounce' 16 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug Tests", 6 | "type": "node", 7 | "request": "launch", 8 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/jest", 9 | "args": ["--runInBand", "--no-cache", "--watchAll=false"], 10 | "cwd": "${workspaceRoot}", 11 | "console": "integratedTerminal", 12 | "internalConsoleOptions": "neverOpen" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/active-anchor.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand' 2 | import type { Dispatch } from 'react' 3 | 4 | const useActiveAnchorStore = create<{ 5 | activeSlug: string 6 | }>(() => ({ 7 | activeSlug: '', 8 | })) 9 | 10 | export const useActiveAnchor = () => 11 | useActiveAnchorStore((state) => state.activeSlug) 12 | 13 | export const setActiveSlug: Dispatch = (activeSlug) => { 14 | useActiveAnchorStore.setState({ activeSlug }) 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/generateSlotClasses.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClass } from './generateSlotClass' 2 | 3 | export function generateSlotClasses( 4 | componentName: string, 5 | classNames: T[], 6 | ): Record { 7 | const result: Record = {} 8 | 9 | classNames.forEach((className: T) => { 10 | result[className] = generateSlotClass(componentName, className) 11 | }) 12 | 13 | return result 14 | } 15 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Flex } from '@nex-ui/react' 2 | import { UserOutlined } from '@nex-ui/icons' 3 | 4 | export default function App() { 5 | return ( 6 | 7 | 11 | XY 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/close-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/nextraTheme/components/index.ts: -------------------------------------------------------------------------------- 1 | export { Breadcrumb } from './breadcrumb' 2 | export { Footer } from './footer' 3 | export { LastUpdated } from './last-updated' 4 | export { LocaleSwitch } from './locale-switch' 5 | export { Pagination } from './pagination' 6 | export { Navbar } from './navbar' 7 | export { NotFoundPage } from './404/index' 8 | export { Sidebar, MobileNav } from './sidebar' 9 | export { ThemeSwitch } from './theme-switch' 10 | export { TOC } from './toc' 11 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/SearchOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const SearchOutlined = createIcon( 6 | , 12 | 'SearchOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/react/src/components/flex/__tests__/__snapshots__/Flex.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Flex should render with default props 1`] = ` 4 | .emotion-0 { 5 | display: -webkit-box; 6 | display: -webkit-flex; 7 | display: -ms-flexbox; 8 | display: flex; 9 | -webkit-flex-direction: row; 10 | -ms-flex-direction: row; 11 | flex-direction: row; 12 | } 13 | 14 |
17 | `; 18 | -------------------------------------------------------------------------------- /packages/react/src/components/radioGroup/RadioGroupContext.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { RadioGroupContextValue } from './types' 5 | 6 | export const [RadioGroupProvider, useRadioGroup] = 7 | createContext({ 8 | strict: false, 9 | contextName: 'RadioGroupContext', 10 | hookName: 'useRadioGroup', 11 | providerName: 'RadioGroupProvider', 12 | defaultValue: null, 13 | }) 14 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/Sizes.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/CloseOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CloseOutlined = createIcon( 6 | , 10 | 'CloseOutlined', 11 | ) 12 | -------------------------------------------------------------------------------- /packages/react/src/theme/recipes/flex.ts: -------------------------------------------------------------------------------- 1 | import { defineRecipe } from '@nex-ui/system' 2 | import type { RecipeVariants } from '@nex-ui/system' 3 | 4 | export const flexRecipe = defineRecipe({ 5 | base: { 6 | display: 'flex', 7 | }, 8 | variants: { 9 | inline: { 10 | true: { 11 | display: 'inline-flex', 12 | }, 13 | }, 14 | }, 15 | }) 16 | 17 | export type FlexRecipe = typeof flexRecipe 18 | export type FlexVariants = RecipeVariants 19 | -------------------------------------------------------------------------------- /docs/components/FlexCenter.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@nex-ui/react' 2 | import type { InterpolationPrimitive } from '@nex-ui/system' 3 | import type { FlexProps } from '@nex-ui/react' 4 | 5 | type ExampleProps = Omit & { sx: InterpolationPrimitive } 6 | 7 | export function FlexCenter({ children, sx, ...props }: ExampleProps) { 8 | return ( 9 | 10 | {children} 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /docs/components/docs/TokensTable.tsx: -------------------------------------------------------------------------------- 1 | import { TwoColumnTable } from './TwoColumnTable' 2 | 3 | const columns = [ 4 | { 5 | title: 'Token', 6 | dataIndex: 'token', 7 | }, 8 | { title: 'Value', dataIndex: 'value' }, 9 | ] as const 10 | 11 | type TokensTableProps = { 12 | dataSource: { token: string; value: string }[] 13 | } 14 | 15 | export function TokensTable({ dataSource }: TokensTableProps) { 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /docs/content/_demo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './button' 2 | export * from './avatar' 3 | export * from './checkbox' 4 | export * from './flex' 5 | export * from './divider' 6 | export * from './switch' 7 | export * from './accordion' 8 | export * from './input' 9 | export * from './dialog' 10 | export * from './drawer' 11 | export * from './radioGroup' 12 | export * from './alert' 13 | export * from './card' 14 | export * from './tooltip' 15 | export * from './popover' 16 | export * from './badge' 17 | -------------------------------------------------------------------------------- /docs/content/_demo/tooltip/Offset.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip, Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { FlatCompat } from '@eslint/eslintrc' 4 | 5 | const __filename = fileURLToPath(import.meta.url) 6 | const __dirname = dirname(__filename) 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }) 11 | 12 | const eslintConfig = [ 13 | ...compat.extends('next/core-web-vitals', 'next/typescript'), 14 | ] 15 | 16 | export default eslintConfig 17 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { dirname } from 'path' 2 | import { fileURLToPath } from 'url' 3 | import { FlatCompat } from '@eslint/eslintrc' 4 | 5 | const __filename = fileURLToPath(import.meta.url) 6 | const __dirname = dirname(__filename) 7 | 8 | const compat = new FlatCompat({ 9 | baseDirectory: __dirname, 10 | }) 11 | 12 | const eslintConfig = [ 13 | ...compat.extends('next/core-web-vitals', 'next/typescript'), 14 | ] 15 | 16 | export default eslintConfig 17 | -------------------------------------------------------------------------------- /packages/react/src/components/avatar/AvatarGroupContext.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | 5 | import type { AvatarGroupContextValue } from './types' 6 | 7 | export const [AvatarGroupProvider, useAvatarGroup] = 8 | createContext({ 9 | contextName: 'AvatarGroupContext', 10 | providerName: 'AvatarGroupProvider', 11 | hookName: 'useAvatarGroup', 12 | strict: false, 13 | defaultValue: null, 14 | }) 15 | -------------------------------------------------------------------------------- /packages/react/src/components/popper/index.ts: -------------------------------------------------------------------------------- 1 | export { Popper } from './Popper' 2 | export { PopperTrigger } from './PopperTrigger' 3 | export { PopperRoot } from './PopperRoot' 4 | export { PopperContent } from './PopperContent' 5 | export { PopperClose } from './PopperClose' 6 | 7 | export { usePopper } from './PopperContext' 8 | 9 | export type { 10 | PopperProps, 11 | PopperTriggerProps, 12 | PopperRootProps, 13 | PopperContentProps, 14 | PopperCloseProps, 15 | } from './types' 16 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/exclamation-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/react/src/components/buttonBase/types.ts: -------------------------------------------------------------------------------- 1 | import type { Interpolation } from '@nex-ui/system' 2 | import type { ComponentProps, ElementType } from 'react' 3 | import type { Overwrite } from '../../types/utils' 4 | 5 | export type ButtonBaseProps = 6 | Overwrite< 7 | ComponentProps, 8 | { 9 | as?: RootComponent 10 | sx?: Interpolation 11 | href?: string 12 | disabled?: boolean 13 | } 14 | > 15 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/Controlled.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { Checkbox, Flex } from '@nex-ui/react' 4 | import { useState } from 'react' 5 | 6 | export default function App() { 7 | const [checked, setChecked] = useState(true) 8 | 9 | return ( 10 | 11 | 12 | Option 13 | 14 |

Checked: {checked ? 'Yes' : 'No'}

15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/check-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/react/src/components/checkbox/CheckboxGroupContext.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { CheckboxGroupContextValue } from './types' 5 | 6 | export const [CheckboxGroupProvider, useCheckboxGroup] = 7 | createContext({ 8 | contextName: 'CheckboxGroupContext', 9 | providerName: 'CheckboxGroupProvider', 10 | hookName: 'useCheckboxGroup', 11 | strict: false, 12 | defaultValue: null, 13 | }) 14 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/shadows.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const shadows = defineTokens.shadows({ 4 | xs: '0 1px 2px 0 rgb(0 0 0 / 0.1)', 5 | sm: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)', 6 | md: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)', 7 | lg: '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)', 8 | xl: '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)', 9 | }) 10 | -------------------------------------------------------------------------------- /docs/icons/npm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/content/_demo/tooltip/Interactive.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip, Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/ExclamationCircleFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ExclamationCircleFilled = createIcon( 6 | , 12 | 'ExclamationCircleFilled', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/transitions.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const transitions = defineTokens.transitions({ 4 | all: 'all 0.2s', 5 | colors: 6 | 'color 0.2s, background-color 0.2s, border-color 0.2s, text-decoration-color 0.2s, fill 0.2s, stroke 0.2s, opacity 0.2s', 7 | opacity: 'opacity 0.2s', 8 | shadow: 'box-shadow 0.2s', 9 | transform: 'transform 0.2s, opacity 0.2s', 10 | margin: 'margin 0.2s', 11 | scale: 'scale 0.2s, opacity 0.2s', 12 | }) 13 | -------------------------------------------------------------------------------- /packages/react/src/components/inputBase/types.ts: -------------------------------------------------------------------------------- 1 | import type { Interpolation } from '@nex-ui/system' 2 | import type { ElementType, InputHTMLAttributes, DetailedHTMLProps } from 'react' 3 | import type { Overwrite } from '../../types/utils' 4 | 5 | export type InputBaseProps = Overwrite< 6 | DetailedHTMLProps, HTMLInputElement>, 7 | { 8 | as?: ElementType 9 | sx?: Interpolation 10 | invalid?: boolean 11 | onCheckedChange?: (checked: boolean) => void 12 | } 13 | > 14 | -------------------------------------------------------------------------------- /packages/utils/src/shared/camelCase.ts: -------------------------------------------------------------------------------- 1 | export function camelCase(str: string): string { 2 | if (typeof str !== 'string' || str.trim() === '') { 3 | return str 4 | } 5 | 6 | const processed = str.replace(/^-+/, '') 7 | 8 | if (!str.includes('-')) { 9 | return str 10 | } 11 | 12 | if (processed === '') { 13 | return '' 14 | } 15 | 16 | return processed.replace(/-([a-zA-Z0-9]+)/g, (_, letters) => { 17 | return letters.charAt(0).toUpperCase() + letters.slice(1).toLowerCase() 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/CheckCircleFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CheckCircleFilled = createIcon( 6 | , 12 | 'CheckCircleFilled', 13 | ) 14 | -------------------------------------------------------------------------------- /docs/content/_demo/alert/Closable.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { Alert, Button } from '@nex-ui/react' 4 | import { useState } from 'react' 5 | 6 | export default function App() { 7 | const [open, setOpen] = useState(true) 8 | 9 | return open ? ( 10 | setOpen(false)} 15 | /> 16 | ) : ( 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/WithThumbIcon.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { SunFilled, MoonFilled } from '@nex-ui/icons' 4 | import { Switch } from '@nex-ui/react' 5 | import type { SwitchProps } from '@nex-ui/react' 6 | 7 | export default function App() { 8 | const renderThumbIcon = (e: SwitchProps) => 9 | e.checked ? : 10 | 11 | return ( 12 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /packages/react/src/theme/recipes/index.ts: -------------------------------------------------------------------------------- 1 | export * from './divider' 2 | export * from './flex' 3 | export * from './icon' 4 | export * from './button' 5 | export * from './input' 6 | export * from './avatar' 7 | export * from './checkbox' 8 | export * from './switch' 9 | export * from './accordion' 10 | export * from './dialog' 11 | export * from './drawer' 12 | export * from './radioGroup' 13 | export * from './alert' 14 | export * from './card' 15 | export * from './tooltip' 16 | export * from './popover' 17 | export * from './badge' 18 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /packages/react/src/components/accordion/AccordionContext.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { AccordionGroupContextValue } from './types' 5 | 6 | export const [AccordionGroupProvider, useAccordionGroup] = 7 | createContext({ 8 | contextName: 'AccordionGroupContext', 9 | hookName: 'useAccordionGroup', 10 | providerName: 'AccordionGroupProvider', 11 | defaultValue: null as unknown as AccordionGroupContextValue, 12 | strict: true, 13 | }) 14 | -------------------------------------------------------------------------------- /packages/react/src/components/box/Box.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useSlot } from '../utils' 4 | import type { ElementType } from 'react' 5 | import type { BoxProps } from './types' 6 | 7 | export const Box = ( 8 | props: BoxProps, 9 | ) => { 10 | const [BoxRoot, getBoxRootProps] = useSlot({ 11 | elementType: 'div', 12 | externalForwardedProps: props as BoxProps, 13 | }) 14 | 15 | return 16 | } 17 | 18 | Box.displayName = 'Box' 19 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/GroupMaxCount.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, AvatarGroup } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /notes/解决图标文本对齐.md: -------------------------------------------------------------------------------- 1 | #### 父元素高度超过图片高度本身 2 | 3 | 浏览器默认情况下(`vertical-align: baseline`)会将图片底部与 x 底部对齐,因此导致图片的父元素的高度会比图片本身高度多一些. (当没有文本时也是如此,why ? MDN 中指出 baseline 使元素的基线与父元素的基线对齐) 4 | 5 | 解决方法: 6 | 7 | 1. vertical-align 只对行内元素生效,因此让 img 成为块元素. 8 | 2. 在未明确具体高度时,元素的高度是由子元素的高度及 line-height 和 font-size 共同决定. 减小 line-height 和 font-size 的值 9 | 10 | #### 图标与文本居中对齐 11 | 12 | 1. 设置图标和文本 `vertical-aligh: middle` 13 | 2. 使用 flex 布局 (mui 方案) 14 | 3. `vertical-aligh` 支持数值,设置具体的偏移量 (ant-design 方案) 15 | 16 | MUI 方案兼容性更强,可以使用其他 icon. antd 只有使用组件库内的 Icon , 才能与文本居中. 17 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/GroupSpacing.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, AvatarGroup } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/GroupTotalCount.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, AvatarGroup } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/ExclamationCircleOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ExclamationCircleOutlined = createIcon( 6 | 7 | 8 | 14 | 15 | , 16 | 'ExclamationCircleOutlined', 17 | ) 18 | -------------------------------------------------------------------------------- /sb/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import type { StorybookConfig } from '@storybook/react-vite' 2 | 3 | export default { 4 | framework: { 5 | name: '@storybook/react-vite', 6 | options: {}, 7 | }, 8 | stories: [ 9 | '../../packages/*/src/**/__stories__/**/*.stories.@(js|jsx|ts|tsx)', 10 | ], 11 | addons: [ 12 | '@storybook/addon-themes', 13 | '@storybook/addon-a11y', 14 | '@chromatic-com/storybook', 15 | '@storybook/addon-docs', 16 | ], 17 | features: { 18 | backgrounds: false, 19 | }, 20 | } satisfies StorybookConfig 21 | -------------------------------------------------------------------------------- /notes/gitflow.md: -------------------------------------------------------------------------------- 1 | Gitflow@v0.0.0 2 | 3 | ### Branches 4 | 5 | - `dev` 分支. 功能开发. 6 | - `main` 分支. 与已发布代码一致. 7 | 8 | ### PR 合并策略 9 | 10 | 使用 **Rebase** 保证线性历史. 11 | 12 | ### 功能开发 13 | - 基于 `dev` 分支,创建 `feat/foo`. 14 | - 完成后,向 `dev` 分支提交 PR. 15 | - 检查 QA、Visual Tests 的 workflows 状态. 16 | 17 | ### 紧急修复 18 | - 基于 `main` 分支,创建 `fix/boo`, 19 | - 完成后,向 `main` 分支提交 PR. 20 | - 检查 QA、Visual Tests 的 workflows 状态. 21 | 22 | ### 发布 23 | - 本地 run changesets 后 push 到 `main` 分支,触发 Release workflow. 合并由 changesets 提交的 PR 后自动部署到 NPM. 24 | - 自动 rebase origin/main 同步到 `dev` 分支. -------------------------------------------------------------------------------- /packages/system/src/colorScheme/ColorSchemeContex.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { ColorSchemeContext } from './types' 5 | 6 | const [InnerColorSchemeProvider, useColorScheme] = 7 | createContext({ 8 | contextName: 'ColorSchemeContext', 9 | providerName: 'InnerColorSchemeProvider', 10 | hookName: 'useColorScheme', 11 | strict: true, 12 | defaultValue: null as unknown as ColorSchemeContext, 13 | }) 14 | 15 | export { InnerColorSchemeProvider, useColorScheme } 16 | -------------------------------------------------------------------------------- /packages/react/src/components/divider/__tests__/__snapshots__/Divider.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Divider should render with default props 1`] = ` 4 | .emotion-0 { 5 | margin: 0; 6 | border: none; 7 | background-color: var(--nui-colors-gray-highlight); 8 | height: var(--nui-sizes-px); 9 | margin-block-start: var(--nui-spaces-6); 10 | margin-block-end: var(--nui-spaces-6); 11 | } 12 | 13 | 18 | `; 19 | -------------------------------------------------------------------------------- /packages/react/src/components/focusTrap/types.ts: -------------------------------------------------------------------------------- 1 | import type { ReactElement, Ref, FocusEventHandler } from 'react' 2 | 3 | export interface FocusTrapProps { 4 | children: ReactElement<{ ref?: Ref; onFocus?: FocusEventHandler }> 5 | 6 | active?: boolean 7 | 8 | /** 9 | * To pause or unpause the trap while it's `active`. 10 | */ 11 | paused?: boolean 12 | 13 | /** 14 | * If true, the modal will restore focus to previously focused element once the modal is hidden or unmounted. 15 | * @default true 16 | */ 17 | restoreFocus?: boolean 18 | } 19 | -------------------------------------------------------------------------------- /packages/utils/src/__tests__/addEventListener.test.ts: -------------------------------------------------------------------------------- 1 | import { fireEvent } from '@testing-library/dom' 2 | import { addEventListener } from '../dom/index' 3 | 4 | describe('addEventListener', () => { 5 | it('should add event listener to body', () => { 6 | const cb = jest.fn() 7 | const removeEventListener = addEventListener(document.body, 'click', cb) 8 | fireEvent.click(document.body) 9 | expect(cb).toHaveBeenCalled() 10 | removeEventListener() 11 | fireEvent.click(document.body) 12 | expect(cb).toHaveBeenCalledTimes(1) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/utils/src/react/mergeRefs.ts: -------------------------------------------------------------------------------- 1 | import type { RefObject, Ref } from 'react' 2 | 3 | export function mergeRefs(...refs: (Ref | undefined | null)[]) { 4 | const list = refs.filter((ref) => ref) 5 | 6 | if (list.length === 1) { 7 | return list[0] 8 | } 9 | 10 | return (node: T) => { 11 | list.forEach((ref) => { 12 | if (typeof ref === 'function') { 13 | ref(node) 14 | } else if (ref && typeof ref === 'object' && 'current' in ref) { 15 | ;(ref as RefObject).current = node 16 | } 17 | }) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/hooks/src/__tests__/useLatest.test.tsx: -------------------------------------------------------------------------------- 1 | import { renderHook } from '@testing-library/react' 2 | import { useLatest } from '../index' 3 | 4 | describe('useLatest', () => { 5 | it('should return a ref with the latest value', () => { 6 | const { result, rerender } = renderHook((value) => useLatest(value), { 7 | initialProps: 42, 8 | }) 9 | expect(result.current.current).toBe(42) 10 | 11 | rerender(100) 12 | expect(result.current.current).toBe(100) 13 | 14 | rerender(200) 15 | expect(result.current.current).toBe(200) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /packages/react/src/components/card/index.ts: -------------------------------------------------------------------------------- 1 | export { Card } from './Card' 2 | export { CardHeader } from './CardHeader' 3 | export { CardBody } from './CardBody' 4 | export { CardFooter } from './CardFooter' 5 | export { CardActionArea } from './CardActionArea' 6 | 7 | export type { 8 | CardProps, 9 | CardPropsOverrides, 10 | CardHeaderProps, 11 | CardHeaderPropsOverrides, 12 | CardBodyProps, 13 | CardBodyPropsOverrides, 14 | CardFooterProps, 15 | CardFooterPropsOverrides, 16 | CardActionAreaProps, 17 | CardActionAreaPropsOverrides, 18 | } from './types' 19 | -------------------------------------------------------------------------------- /docs/components/docs/homepage/Gallery.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import dynamic from 'next/dynamic' 4 | import { preload } from 'react-dom' 5 | 6 | const ClientGallery = dynamic( 7 | () => import('./Gallery.client').then((m) => m.ClientGallery), 8 | { ssr: false }, 9 | ) 10 | 11 | export const Gallery = () => { 12 | preload('/avatars/avatar-1.jpg', { as: 'image' }) 13 | preload('/avatars/avatar-2.jpg', { as: 'image' }) 14 | preload('/avatars/avatar-3.webp', { as: 'image' }) 15 | preload('/avatars/avatar-4.jpg', { as: 'image' }) 16 | 17 | return 18 | } 19 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/CloseCircleFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CloseCircleFilled = createIcon( 6 | , 12 | 'CloseCircleFilled', 13 | ) 14 | -------------------------------------------------------------------------------- /scripts/utils/rollup.ts: -------------------------------------------------------------------------------- 1 | import { rollup as r } from 'rollup' 2 | 3 | import type { RollupOptions, RollupBuild } from 'rollup' 4 | 5 | export async function rollup(config: RollupOptions) { 6 | let bundle: RollupBuild 7 | try { 8 | bundle = await r(config) 9 | 10 | const output = Array.isArray(config.output) 11 | ? config.output 12 | : [config.output] 13 | 14 | await Promise.all(output.map((o) => bundle.write(o!))) 15 | } catch (error: any) { 16 | throw new Error(error) 17 | } 18 | 19 | if (bundle) { 20 | await bundle.close() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/components/sandpack/BugReportButton.tsx: -------------------------------------------------------------------------------- 1 | import { useEvent } from '@nex-ui/hooks' 2 | import { BugOutlined } from '@nex-ui/icons' 3 | import { IconButton } from './IconButton' 4 | 5 | export const BugReportButton = () => { 6 | const handlePress = useEvent(() => { 7 | window.open('https://github.com/rxy001/nex-ui/issues', '_blank') 8 | }) 9 | 10 | return ( 11 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/CopyOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CopyOutlined = createIcon( 6 | , 15 | 'CopyOutlined', 16 | ) 17 | -------------------------------------------------------------------------------- /packages/react/src/components/card/__tests__/__snapshots__/CardHeader.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`CardHeader should render with default props 1`] = ` 4 | .emotion-0 { 5 | padding: var(--nui-spaces-3); 6 | display: -webkit-box; 7 | display: -webkit-flex; 8 | display: -ms-flexbox; 9 | display: flex; 10 | -webkit-align-items: center; 11 | -webkit-box-align: center; 12 | -ms-flex-align: center; 13 | align-items: center; 14 | gap: var(--nui-spaces-3); 15 | } 16 | 17 |
20 | `; 21 | -------------------------------------------------------------------------------- /clean-package.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "remove": ["devDependencies"], 3 | "replace": { 4 | "main": "dist/cjs/index.cjs", 5 | "module": "dist/esm/index.mjs", 6 | "types": "dist/types/index.d.ts", 7 | "exports": { 8 | ".": { 9 | "import": { 10 | "types": "./dist/types/index.d.ts", 11 | "default": "./dist/esm/index.mjs" 12 | }, 13 | "require": { 14 | "types": "./dist/types/index.d.ts", 15 | "default": "./dist/cjs/index.cjs" 16 | } 17 | }, 18 | "./package.json": "./package.json" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/components/docs/ScaleTable.tsx: -------------------------------------------------------------------------------- 1 | import { defaultConfig } from '@nex-ui/react' 2 | import { TwoColumnTable } from './TwoColumnTable' 3 | 4 | const dataSource = Object.entries(defaultConfig.scales ?? {}).map( 5 | ([prop, token]) => ({ 6 | prop, 7 | token, 8 | }), 9 | ) 10 | 11 | const columns = [ 12 | { 13 | title: 'CSS Property', 14 | dataIndex: 'prop', 15 | }, 16 | { 17 | title: 'Token Category', 18 | dataIndex: 'token', 19 | }, 20 | ] as const 21 | 22 | export function ScaleTable() { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Colors.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | Blue 7 | Cyan 8 | Gray 9 | Orange 10 | Red 11 | Green 12 | Pink 13 | Purple 14 | Yellow 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/Controlled.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useState } from 'react' 4 | import { Flex, Switch } from '@nex-ui/react' 5 | import type { ChangeEvent } from 'react' 6 | 7 | export default function App() { 8 | const [checked, setChecked] = useState(true) 9 | 10 | const onChange = (e: ChangeEvent) => 11 | setChecked(e.target.checked) 12 | 13 | return ( 14 | 15 | 16 |

Checked: {checked ? 'Yes' : 'No'}

17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /packages/hooks/src/useLatest.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useRef } from 'react' 4 | 5 | /** 6 | * A custom hook that returns a ref to the latest value. 7 | * This is useful to avoid stale closures in event handlers or effects. 8 | * 9 | * @param value - The value to keep track of. 10 | * @returns A ref object containing the latest value. 11 | * 12 | * @example 13 | * ```tsx 14 | * const latestValue = useLatest(someValue); 15 | * ``` 16 | */ 17 | export const useLatest = (value: T) => { 18 | const ref = useRef(value) 19 | 20 | ref.current = value 21 | 22 | return ref 23 | } 24 | -------------------------------------------------------------------------------- /packages/react/src/components/provider/Context.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { NexContextValue } from './types' 5 | 6 | const DEFAULT_CONTEXT_VALUE = '__nex-react-default-context-value__' 7 | 8 | const [NexContextProvider, useNexUI] = createContext({ 9 | contextName: 'NexContextValue', 10 | providerName: 'NexContextProvider', 11 | hookName: 'useNexUI', 12 | strict: false, 13 | defaultValue: DEFAULT_CONTEXT_VALUE as unknown as NexContextValue, 14 | }) 15 | 16 | export { NexContextProvider, useNexUI, DEFAULT_CONTEXT_VALUE } 17 | -------------------------------------------------------------------------------- /sb/vite.config.ts: -------------------------------------------------------------------------------- 1 | import react from '@vitejs/plugin-react-swc' 2 | import { defineConfig } from 'vite' 3 | 4 | export default defineConfig(() => { 5 | return { 6 | plugins: [react()], 7 | resolve: { 8 | extensions: [ 9 | '.mjs', 10 | '.js', 11 | '.mts', 12 | '.ts', 13 | '.jsx', 14 | '.tsx', 15 | '.json', 16 | '.css', 17 | ], 18 | alias: [ 19 | { 20 | find: '~/sb/utils', 21 | replacement: `${import.meta.dirname}/utils/index.ts`, 22 | }, 23 | ], 24 | }, 25 | } 26 | }) 27 | -------------------------------------------------------------------------------- /docs/content/_demo/checkbox/GroupUseage.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useState } from 'react' 4 | import { Checkbox, CheckboxGroup } from '@nex-ui/react' 5 | 6 | export default function App() { 7 | const [value, setValue] = useState(['pear']) 8 | 9 | return ( 10 | 15 | Apple 16 | Pear 17 | Orange 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /docs/content/_demo/tooltip/Controlled.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useState } from 'react' 4 | import { Tooltip, Button, Box } from '@nex-ui/react' 5 | 6 | export default function App() { 7 | const [open, setOpen] = useState(false) 8 | 9 | return ( 10 | <> 11 | 17 | 18 | 19 | Open: {open ? 'Yes' : 'No'} 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /docs/components/table/DefaultItem.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type DefaultItemProps = ComponentPropsWithoutRef<'span'> 5 | 6 | export const DefaultItem = ({ 7 | className, 8 | children, 9 | ...props 10 | }: DefaultItemProps) => ( 11 | 18 | {children} 19 | 20 | ) 21 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/theme-config.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext, createElement, useContext } from 'react' 4 | import type { ComponentProps } from 'react' 5 | import type { ThemeConfigProps } from '../layout' 6 | 7 | const ThemeConfigContext = createContext< 8 | Omit 9 | >(null!) 10 | 11 | export const useThemeConfig = () => useContext(ThemeConfigContext) 12 | 13 | export const ThemeConfigProvider = ( 14 | props: ComponentProps, 15 | ) => createElement(ThemeConfigContext.Provider, props) 16 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/MoonOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const MoonOutlined = createIcon( 6 | , 12 | 'MoonOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /docs/content/_demo/input/LabelPlacements.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["tsconfig.json"], 4 | "tasks": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "outputs": ["dist/**", ".next/**", "!.next/cache/**"] 8 | }, 9 | "build:fast": { 10 | "dependsOn": ["^build:fast"], 11 | "outputs": ["dist/**"] 12 | }, 13 | "dev": { 14 | "cache": false, 15 | "persistent": true 16 | }, 17 | "test": { 18 | "outputs": [] 19 | }, 20 | "typecheck": { 21 | "cache": false, 22 | "dependsOn": ["^typecheck"] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/components/docs/SelectorTable.tsx: -------------------------------------------------------------------------------- 1 | import { defaultConfig } from '@nex-ui/react' 2 | import { TwoColumnTable } from './TwoColumnTable' 3 | 4 | const dataSource = Object.entries(defaultConfig.selectors ?? {}).map( 5 | ([selector, value]) => ({ 6 | selector, 7 | value, 8 | }), 9 | ) 10 | 11 | const columns = [ 12 | { 13 | title: 'Selector', 14 | dataIndex: 'selector', 15 | className: 'x:w-[25%]!', 16 | }, 17 | { title: 'Value', dataIndex: 'value' }, 18 | ] as const 19 | 20 | export function SelectorTable() { 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /docs/components/table/HighlightItem.tsx: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx' 2 | import type { ComponentPropsWithoutRef } from 'react' 3 | 4 | type HighlightItemProps = ComponentPropsWithoutRef<'span'> 5 | 6 | export const HighlightItem = ({ 7 | className, 8 | children, 9 | ...props 10 | }: HighlightItemProps) => ( 11 | 18 | {children} 19 | 20 | ) 21 | -------------------------------------------------------------------------------- /docs/content/_demo/button/Colors.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/ExclamationSquareFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ExclamationSquareFilled = createIcon( 6 | , 12 | 'ExclamationSquareFilled', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/exclamation-shield.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/content/zh/_meta.ts: -------------------------------------------------------------------------------- 1 | import meta from './docs/components/_meta' 2 | 3 | export default { 4 | index: { 5 | type: 'page', 6 | title: '首页', 7 | display: 'hidden', 8 | theme: { 9 | layout: 'full', 10 | toc: false, 11 | timestamp: false, 12 | }, 13 | }, 14 | docs: { 15 | type: 'page', 16 | title: '文档', 17 | }, 18 | components: { 19 | type: 'page', 20 | href: `/docs/components/${Object.keys(meta).sort().shift()}`, 21 | title: '组件', 22 | }, 23 | theming: { 24 | type: 'page', 25 | href: '/docs/customization/theming', 26 | title: '定制', 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/spaces.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const spaces = defineTokens.spaces({ 4 | px: '1px', 5 | 0.5: '2px', 6 | 1: '4px', 7 | 1.5: '6px', 8 | 2: '8px', 9 | 2.5: '10px', 10 | 3: '12px', 11 | 3.5: '14px', 12 | 4: '16px', 13 | 4.5: '18px', 14 | 5: '20px', 15 | 5.5: '22px', 16 | 6: '24px', 17 | 6.5: '26px', 18 | 7: '28px', 19 | 7.5: '30px', 20 | 8: '32px', 21 | 8.5: '34px', 22 | 9: '36px', 23 | 9.5: '38px', 24 | 10: '40px', 25 | 11: '44px', 26 | 12: '48px', 27 | 13: '52px', 28 | 14: '56px', 29 | 15: '60px', 30 | }) 31 | -------------------------------------------------------------------------------- /docs/components/docs/BreakpointTable.tsx: -------------------------------------------------------------------------------- 1 | import { defaultConfig } from '@nex-ui/react' 2 | import { TwoColumnTable } from './TwoColumnTable' 3 | 4 | const dataSource = Object.entries(defaultConfig.breakpoints ?? {}).map( 5 | ([breakpoint, width]) => ({ 6 | breakpoint, 7 | width, 8 | }), 9 | ) 10 | 11 | const columns = [ 12 | { 13 | title: 'Breakpoint', 14 | dataIndex: 'breakpoint', 15 | }, 16 | { 17 | title: 'Screen Width', 18 | dataIndex: 'width', 19 | }, 20 | ] as const 21 | 22 | export function BreakpointTable() { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /docs/components/sandpack/CodeSandboxButton.tsx: -------------------------------------------------------------------------------- 1 | import { UnstyledOpenInCodeSandboxButton } from '@codesandbox/sandpack-react' 2 | import { CodeSandboxOutlined } from '@nex-ui/icons' 3 | import { IconButton } from './IconButton' 4 | 5 | export const CodeSandboxButton = () => { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /docs/content/_demo/flex/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Box } from '@nex-ui/react' 2 | import type { ReactNode } from 'react' 3 | 4 | function Item({ children }: { children: ReactNode }) { 5 | return ( 6 | 15 | {children} 16 | 17 | ) 18 | } 19 | 20 | export default function App() { 21 | return ( 22 | 23 | Item 1 24 | Item 2 25 | Item 3 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /docs/content/_demo/radioGroup/Controlled.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { RadioGroup, Radio, Flex } from '@nex-ui/react' 4 | import { useState } from 'react' 5 | 6 | export default function App() { 7 | const [value, setValue] = useState('apple') 8 | 9 | return ( 10 | 11 | 12 | Apple 13 | Banana 14 | Cherry 15 | 16 |

Selected: {value}

17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /packages/react/src/components/utils/useDefaultProps.ts: -------------------------------------------------------------------------------- 1 | import { mergeProps } from '@nex-ui/utils' 2 | import { useNexUI } from '../provider/Context' 3 | import type { ComponentNames } from '../../types/componentThemes' 4 | 5 | type UseDefaultPropsArgs = { 6 | name: ComponentNames 7 | props: Record 8 | } 9 | 10 | export const useDefaultProps = ({ name, props }: UseDefaultPropsArgs): T => { 11 | const { components } = useNexUI() 12 | const defaultProps = components?.[name]?.defaultProps 13 | 14 | if (defaultProps) { 15 | return mergeProps(defaultProps, props) as T 16 | } 17 | 18 | return props as T 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | *.log 30 | 31 | 32 | # Debug 33 | npm-debug.log* 34 | yarn-debug.log* 35 | yarn-error.log* 36 | 37 | # Misc 38 | .DS_Store 39 | *.pem 40 | _pagefind 41 | *.backup 42 | 43 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /docs/components/docs/AliasTable.tsx: -------------------------------------------------------------------------------- 1 | import { defaultConfig } from '@nex-ui/react' 2 | import { TwoColumnTable } from './TwoColumnTable' 3 | 4 | const dataSource = Object.entries(defaultConfig.aliases ?? {}).map( 5 | ([alias, prop]) => ({ 6 | alias, 7 | prop: Array.isArray(prop) ? prop.join('、') : prop, 8 | }), 9 | ) 10 | 11 | const columns = [ 12 | { 13 | title: 'Alias', 14 | dataIndex: 'alias', 15 | }, 16 | { 17 | title: 'CSS Property', 18 | dataIndex: 'prop', 19 | }, 20 | ] as const 21 | 22 | export function AliasTable() { 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "paths": { 17 | "@/*": ["./*"] 18 | } 19 | }, 20 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 21 | "exclude": ["node_modules"] 22 | } 23 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/repeat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/nextraTheme/css/typesetting-article.css: -------------------------------------------------------------------------------- 1 | article.nextra-body-typesetting-article { 2 | font-size: 17px; 3 | font-feature-settings: 4 | 'rlig' 1, 5 | 'calt' 1; 6 | h1 { 7 | @apply x:mt-6 x:mb-4 x:text-center; 8 | font-size: 2.5rem; 9 | } 10 | h2 { 11 | @apply x:border-none; 12 | } 13 | a { 14 | @apply x:no-underline x:hover:underline; 15 | } 16 | p { 17 | @apply x:leading-8; 18 | } 19 | code { 20 | @apply x:border-none x:dark:bg-neutral-700; 21 | } 22 | pre code { 23 | @apply x:dark:bg-transparent; 24 | } 25 | .subheading-anchor { 26 | @apply x:hover:no-underline; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/react/src/components/card/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const cardClasses = generateSlotClasses('nui-card', ['root']) 4 | 5 | export const cardHeaderClasses = generateSlotClasses('nui-card-header', [ 6 | 'root', 7 | 'content', 8 | 'title', 9 | 'subtitle', 10 | ]) 11 | 12 | export const cardBodyClasses = generateSlotClasses('nui-card-body', ['root']) 13 | 14 | export const cardFooterClasses = generateSlotClasses('nui-card-footer', [ 15 | 'root', 16 | ]) 17 | 18 | export const cardActionAreaClasses = generateSlotClasses( 19 | 'nui-card-action-area', 20 | ['root'], 21 | ) 22 | -------------------------------------------------------------------------------- /packages/react/src/components/popper/PopperManager.ts: -------------------------------------------------------------------------------- 1 | export class PopperManager { 2 | private poppers: Map void> = new Map() 3 | 4 | register(popperId: string, flush: () => void) { 5 | if (this.poppers.has(popperId)) { 6 | return 7 | } 8 | 9 | this.poppers.set(popperId, flush) 10 | } 11 | 12 | flush(popperId: string) { 13 | this.poppers.forEach((flush, key) => { 14 | if (popperId !== key) { 15 | flush() 16 | } 17 | }) 18 | } 19 | 20 | unregister(popperId: string) { 21 | if (this.poppers.has(popperId)) { 22 | this.poppers.delete(popperId) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/react/src/theme/shared/toSlots.ts: -------------------------------------------------------------------------------- 1 | type Result = { 2 | [P in keyof T]: { 3 | [L in K[number]]: T[P] 4 | } 5 | } 6 | 7 | export function toSlots, K extends string[]>( 8 | object: T, 9 | ...slotNames: K 10 | ) { 11 | const result = {} as Result 12 | 13 | for (const key in object) { 14 | // @ts-ignore 15 | result[key] = {} 16 | if (Object.prototype.hasOwnProperty.call(object, key)) { 17 | slotNames.forEach((slot) => { 18 | // @ts-ignore 19 | result[key][slot] = object[key] 20 | }) 21 | } 22 | } 23 | return result 24 | } 25 | -------------------------------------------------------------------------------- /docs/content/_demo/flex/Justify.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Box } from '@nex-ui/react' 2 | import type { ReactNode } from 'react' 3 | 4 | function Item({ children }: { children: ReactNode }) { 5 | return ( 6 | 15 | {children} 16 | 17 | ) 18 | } 19 | 20 | export default function App() { 21 | return ( 22 | 23 | Item 1 24 | Item 2 25 | Item 3 26 | 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /packages/react/src/components/popover/PopoverContext.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { PopperRootProps } from '../popper' 5 | import type { PopoverProps } from './types' 6 | 7 | export type PopoverContextValue = PopperRootProps & 8 | Pick 9 | 10 | export const [PopoverProvider, usePopover] = createContext( 11 | { 12 | contextName: 'PopoverContext', 13 | hookName: 'usePopover', 14 | providerName: 'PopoverProvider', 15 | strict: true, 16 | defaultValue: null as unknown as PopoverContextValue, 17 | }, 18 | ) 19 | -------------------------------------------------------------------------------- /packages/utils/src/dom/addEventListener.ts: -------------------------------------------------------------------------------- 1 | type EventMapFor = N extends Window 2 | ? WindowEventMap 3 | : N extends HTMLElement 4 | ? HTMLElementEventMap 5 | : never 6 | 7 | export function addEventListener< 8 | N extends Window | HTMLElement, 9 | K extends keyof EventMapFor, 10 | >( 11 | node: N, 12 | event: K, 13 | cb: (this: N, ev: EventMapFor[K]) => any, 14 | options?: AddEventListenerOptions | boolean, 15 | ): () => void { 16 | node.addEventListener(event as string, cb as EventListener, options) 17 | return () => { 18 | node.removeEventListener(event as string, cb as EventListener, options) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/content/en/_meta.ts: -------------------------------------------------------------------------------- 1 | import meta from './docs/components/_meta' 2 | 3 | export default { 4 | index: { 5 | type: 'page', 6 | title: 'Home', 7 | display: 'hidden', 8 | theme: { 9 | layout: 'full', 10 | toc: false, 11 | timestamp: false, 12 | }, 13 | }, 14 | docs: { 15 | type: 'page', 16 | title: 'Documentation', 17 | }, 18 | components: { 19 | type: 'page', 20 | href: `/docs/components/${Object.keys(meta).sort().shift()}`, 21 | title: 'Components', 22 | }, 23 | theming: { 24 | type: 'page', 25 | href: '/docs/customization/theming', 26 | title: 'Customization', 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /packages/react/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './button' 2 | export * from './icon' 3 | export * from './box' 4 | export * from './provider' 5 | export * from './flex' 6 | export * from './input' 7 | export * from './divider' 8 | export * from './avatar' 9 | export * from './checkbox' 10 | export * from './switch' 11 | export * from './accordion' 12 | export * from './initColorSchemeScript' 13 | export * from './dialog' 14 | export * from './drawer' 15 | export * from './radioGroup' 16 | export * from './alert' 17 | export * from './card' 18 | export * from './popper' 19 | export * from './tooltip' 20 | export * from './popover' 21 | export * from './badge' 22 | -------------------------------------------------------------------------------- /packages/react/src/components/modal/index.ts: -------------------------------------------------------------------------------- 1 | export { ModalContent } from './ModalContent' 2 | export { ModalTrigger } from './ModalTrigger' 3 | export { Modal } from './Modal' 4 | export { ModalHeader } from './ModalHeader' 5 | export { ModalBody } from './ModalBody' 6 | export { ModalFooter } from './ModalFooter' 7 | export { ModalClose } from './ModalClose' 8 | export { ModalPanel } from './ModalPanel' 9 | export { ModalBackdrop } from './ModalBackdrop' 10 | export { ModalRoot } from './ModalRoot' 11 | 12 | export type { 13 | ModalProps, 14 | ModalBackdropProps, 15 | ModalBodyProps, 16 | ModalCloseProps, 17 | ModalContentProps, 18 | } from './types' 19 | -------------------------------------------------------------------------------- /packages/hooks/src/useEvent.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useCallback, useRef } from 'react' 4 | 5 | /** 6 | * A custom React hook that returns a stable function reference. 7 | * This is useful to avoid unnecessary re-renders when passing functions as props. 8 | * 9 | * @param fn - The function to wrap. 10 | * @returns A stable function reference that always points to the latest version of `fn`. 11 | */ 12 | export const useEvent = (fn: T) => { 13 | const latest = useRef(fn) 14 | 15 | latest.current = fn 16 | 17 | return useCallback((...args: any[]) => { 18 | return latest.current(...args) 19 | }, []) as unknown as T 20 | } 21 | -------------------------------------------------------------------------------- /docs/content/_demo/input/Adornment.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Input, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 12 | 18 | 25 | 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /docs/nextraTheme/stores/menu.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'zustand' 2 | import type { Dispatch, SetStateAction } from 'react' 3 | 4 | const useMenuStore = create<{ 5 | hasMenu: boolean 6 | }>(() => ({ 7 | hasMenu: false, 8 | })) 9 | 10 | export const useMenu = () => useMenuStore((state) => state.hasMenu) 11 | 12 | export const setMenu: Dispatch> = (fn) => { 13 | useMenuStore.setState((state) => { 14 | const hasMenu = typeof fn === 'function' ? fn(state.hasMenu) : fn 15 | // Lock background scroll when menu is opened 16 | document.body.classList.toggle('x:max-md:overflow-hidden', hasMenu) 17 | return { hasMenu } 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /packages/utils/src/shared/is.ts: -------------------------------------------------------------------------------- 1 | export const isNumber = (value?: any): value is number => 2 | typeof value === 'number' 3 | 4 | export const isFunction = (value?: any): value is (...args: any[]) => any => 5 | typeof value === 'function' && 6 | !/^class\s/.test(Function.prototype.toString.call(value)) 7 | 8 | export const isPlainObject = (value: any): boolean => 9 | typeof value === 'object' && 10 | Object.prototype.toString.call(value) === '[object Object]' 11 | 12 | export const isString = (value?: any): value is string => 13 | typeof value === 'string' 14 | 15 | export const isUndefined = (value?: any): value is undefined => 16 | typeof value === 'undefined' 17 | -------------------------------------------------------------------------------- /docs/content/_demo/badge/Radii.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Badge, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | Extra Small 8 | 9 | 10 | Small 11 | 12 | 13 | Medium 14 | 15 | 16 | Large 17 | 18 | 19 | Full 20 | 21 | 22 | None 23 | 24 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.* 7 | .yarn/* 8 | !.yarn/patches 9 | !.yarn/plugins 10 | !.yarn/releases 11 | !.yarn/versions 12 | 13 | # testing 14 | /coverage 15 | 16 | # next.js 17 | /.next/ 18 | /out/ 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | *.pem 26 | 27 | # debug 28 | npm-debug.log* 29 | yarn-debug.log* 30 | yarn-error.log* 31 | .pnpm-debug.log* 32 | 33 | # env files (can opt-in for committing if needed) 34 | .env* 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | -------------------------------------------------------------------------------- /packages/react/src/theme/system/tokens/sizes.ts: -------------------------------------------------------------------------------- 1 | import { defineTokens } from '@nex-ui/system' 2 | 3 | export const sizes = defineTokens.sizes({ 4 | max: 'max-content', 5 | min: 'min-content', 6 | full: '100%', 7 | px: '1px', 8 | 1: '4px', 9 | 1.5: '6px', 10 | 2: '8px', 11 | 2.5: '10px', 12 | 3: '12px', 13 | 3.5: '14px', 14 | 4: '16px', 15 | 4.5: '18px', 16 | 5: '20px', 17 | 5.5: '22px', 18 | 6: '24px', 19 | 6.5: '26px', 20 | 7: '28px', 21 | 7.5: '30px', 22 | 8: '32px', 23 | 8.5: '34px', 24 | 9: '36px', 25 | 9.5: '38px', 26 | 10: '40px', 27 | 11: '44px', 28 | 12: '48px', 29 | 13: '52px', 30 | 14: '56px', 31 | 15: '60px', 32 | }) 33 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/Radii.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Avatar, Flex } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /packages/react/src/components/dialog/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const dialogClasses = generateSlotClasses('nui-dialog', [ 4 | 'root', 5 | 'backdrop', 6 | ]) 7 | 8 | export const dialogContentClasses = generateSlotClasses('nui-dialog-content', [ 9 | 'root', 10 | 'paper', 11 | 'close-button', 12 | ]) 13 | 14 | export const dialogHeaderClasses = generateSlotClasses('nui-dialog-header', [ 15 | 'root', 16 | ]) 17 | 18 | export const dialogFooterClasses = generateSlotClasses('nui-dialog-footer', [ 19 | 'root', 20 | ]) 21 | 22 | export const dialogBodyClasses = generateSlotClasses('nui-dialog-body', [ 23 | 'root', 24 | ]) 25 | -------------------------------------------------------------------------------- /packages/react/src/components/drawer/__tests__/classes.ts: -------------------------------------------------------------------------------- 1 | import { generateSlotClasses } from '../../utils' 2 | 3 | export const drawerClasses = generateSlotClasses('nui-drawer', [ 4 | 'root', 5 | 'backdrop', 6 | ]) 7 | 8 | export const drawerContentClasses = generateSlotClasses('nui-drawer-content', [ 9 | 'root', 10 | 'paper', 11 | 'close-button', 12 | ]) 13 | 14 | export const drawerHeaderClasses = generateSlotClasses('nui-drawer-header', [ 15 | 'root', 16 | ]) 17 | 18 | export const drawerFooterClasses = generateSlotClasses('nui-drawer-footer', [ 19 | 'root', 20 | ]) 21 | 22 | export const drawerBodyClasses = generateSlotClasses('nui-drawer-body', [ 23 | 'root', 24 | ]) 25 | -------------------------------------------------------------------------------- /sb/utils/normalize.ts: -------------------------------------------------------------------------------- 1 | const createReadableMapper = () => { 2 | return (abbreviation: string) => { 3 | switch (abbreviation) { 4 | case 'xs': 5 | return 'Extra Small' 6 | case 'sm': 7 | return 'Small' 8 | case 'md': 9 | return 'Medium' 10 | case 'lg': 11 | return 'Large' 12 | case 'xl': 13 | return 'Extra Large' 14 | case 'full': 15 | return 'Full' 16 | case 'none': 17 | return 'None' 18 | default: 19 | return abbreviation 20 | } 21 | } 22 | } 23 | 24 | export const toReadableSize = createReadableMapper() 25 | 26 | export const toReadableRadius = createReadableMapper() 27 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/nextraTheme/components/footer.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import type { ComponentProps, FC } from 'react' 3 | 4 | export const Footer: FC> = ({ 5 | className, 6 | children, 7 | ...props 8 | }) => { 9 | return ( 10 | children && ( 11 |
19 | {children} 20 |
21 | ) 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /packages/react/src/components/drawer/index.ts: -------------------------------------------------------------------------------- 1 | export { Drawer } from './Drawer' 2 | export { DrawerContent } from './DrawerContent' 3 | export { DrawerHeader } from './DrawerHeader' 4 | export { DrawerBody } from './DrawerBody' 5 | export { DrawerFooter } from './DrawerFooter' 6 | export { DrawerClose } from './DrawerClose' 7 | export { DrawerTrigger } from './DrawerTrigger' 8 | 9 | export type { 10 | DrawerProps, 11 | DrawerContentProps, 12 | DrawerHeaderProps, 13 | DrawerBodyProps, 14 | DrawerFooterProps, 15 | DrawerPropsOverrides, 16 | DrawerBodyPropsOverrides, 17 | DrawerFooterPropsOverrides, 18 | DrawerHeaderPropsOverrides, 19 | DrawerContentPropsOverrides, 20 | } from './types' 21 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "paths": { 6 | "@/*": ["./*"] 7 | }, 8 | "allowJs": true, 9 | "noEmit": true, 10 | "strict": true, 11 | "incremental": true, 12 | "jsx": "preserve", 13 | "plugins": [ 14 | { 15 | "name": "next" 16 | } 17 | ] 18 | }, 19 | "include": [ 20 | "./types.d.ts", 21 | "./app", 22 | "./mdx-components.tsx", 23 | "./middleware.ts", 24 | "./next-env.d.ts", 25 | ".next/types/**/*.ts", 26 | "./next.config.ts", 27 | "./content", 28 | "./nextraTheme", 29 | "./components" 30 | ], 31 | "exclude": [] 32 | } 33 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/skip-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /packages/system/src/systemProvider/SystemContext.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { CssFn } from '../css' 5 | import type { Layers } from '../layers' 6 | 7 | const DEFAULT_CONTEXT_VALUE = '__nex-system-default-context-value__' 8 | 9 | export type SystemContext = { 10 | css: CssFn 11 | layers: Layers 12 | } 13 | 14 | const [InnerSystemProvider, useSystem] = createContext({ 15 | contextName: 'SystemContext', 16 | providerName: 'InnerSystemProvider', 17 | hookName: 'useSystem', 18 | strict: false, 19 | defaultValue: DEFAULT_CONTEXT_VALUE as unknown as SystemContext, 20 | }) 21 | 22 | export { InnerSystemProvider, useSystem } 23 | -------------------------------------------------------------------------------- /packages/icons/src/svg/outlined/skip-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/content/zh/docs/customization/colors.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Colors 3 | description: 掌握在 Nex UI 中如何使用以及自定义 Colors Tokens。 4 | --- 5 | 6 | import { Callout } from 'nextra/components' 7 | import { CommonColors, SemanticColors, AvailableProps } from '@/components/docs' 8 | 9 | # Colors 10 | 11 | Nex UI 开箱即提供一套默认的调色板,非常适合当您还未确定具体的品牌配色方案时使用。 12 | 13 | 这些颜色被分为‌通用型颜色和语义化颜色。 14 | 15 | - 通用型颜色:跨主题一致性。 16 | - 语义化主题:根据所选的主题进行调整。 17 | 18 | 19 | 20 | 默认情况下,Color Tokens 可直接应用于以下属性  21 | 22 | 23 | 24 | 25 | 26 | ## ‌通用型颜色 27 | 28 | 29 | 30 | ## 语义化颜色 31 | 32 | 33 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/like.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/react/src/components/popper/PopperContext.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { RefObject } from 'react' 5 | 6 | export type PopperContextValue = { 7 | setOpen: (open: boolean) => void 8 | open: boolean 9 | referenceRef: RefObject 10 | popperRootRef: RefObject 11 | handleOpen: () => void 12 | handleClose: () => void 13 | } 14 | 15 | export const [PopperProvider, usePopper] = createContext({ 16 | contextName: 'PopperPropsContext', 17 | hookName: 'usePopper', 18 | providerName: 'PopperProvider', 19 | strict: true, 20 | defaultValue: null as unknown as PopperContextValue, 21 | }) 22 | -------------------------------------------------------------------------------- /docs/app/manifest.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from 'next' 2 | 3 | export default function manifest(): MetadataRoute.Manifest { 4 | return { 5 | name: 'Nex UI - React Component Library', 6 | short_name: 'Nex UI', 7 | description: 8 | 'Beautiful, modern and reliable React component library with TypeScript support, dark mode, and theme customization.', 9 | start_url: '/', 10 | display: 'standalone', 11 | theme_color: '#ffffff', 12 | background_color: '#ffffff', 13 | orientation: 'portrait', 14 | scope: '/', 15 | screenshots: [ 16 | { 17 | src: '/favicon.ico', 18 | sizes: '1200x630', 19 | type: 'image/x-icon', 20 | }, 21 | ], 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Box, Flex } from '@nex-ui/react' 2 | 3 | function App() { 4 | return ( 5 | 12 | 13 | Nex UI - Vite example in TypeScript 14 | 15 | 16 | 19 | 22 | 23 | 24 | ) 25 | } 26 | 27 | export default App 28 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/CheckCircleOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const CheckCircleOutlined = createIcon( 6 | [ 7 | , 12 | , 19 | ], 20 | 'CheckCircleOutlined', 21 | ) 22 | -------------------------------------------------------------------------------- /docs/mdx-components.tsx: -------------------------------------------------------------------------------- 1 | import { Pre, withIcons } from 'nextra/components' 2 | import { GithubOutlined } from '@nex-ui/icons' 3 | import { 4 | Example, 5 | ComponentLinks, 6 | PropsTable, 7 | SlotsTable, 8 | FlexCenter, 9 | } from '@/components' 10 | import { useMDXComponents as getDocsMDXComponents } from './nextraTheme' 11 | 12 | const docsComponents = getDocsMDXComponents({ 13 | // @ts-ignore 14 | pre: withIcons(Pre, { js: GithubOutlined }), 15 | Example, 16 | ComponentLinks, 17 | PropsTable, 18 | SlotsTable, 19 | FlexCenter, 20 | }) 21 | 22 | export const useMDXComponents: typeof getDocsMDXComponents = (components) => { 23 | return { 24 | ...docsComponents, 25 | ...components, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nex-ui-nextjs-app", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11", 13 | "@nex-ui/react": "latest", 14 | "next": "^15", 15 | "react": "^19", 16 | "react-dom": "^19" 17 | }, 18 | "devDependencies": { 19 | "@eslint/eslintrc": "latest", 20 | "@types/node": "latest", 21 | "@types/react": "^19", 22 | "@types/react-dom": "^19", 23 | "eslint": "latest", 24 | "eslint-config-next": "latest", 25 | "typescript": "latest" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-pages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nex-ui-nextjs-pages", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11", 13 | "@nex-ui/react": "latest", 14 | "next": "^15", 15 | "react": "^19", 16 | "react-dom": "^19" 17 | }, 18 | "devDependencies": { 19 | "@eslint/eslintrc": "latest", 20 | "@types/node": "latest", 21 | "@types/react": "^19", 22 | "@types/react-dom": "^19", 23 | "eslint": "latest", 24 | "eslint-config-next": "latest", 25 | "typescript": "latest" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Button, Box, Flex } from '@nex-ui/react' 2 | 3 | function App() { 4 | return ( 5 | 12 | 13 | Nex UI - Vite example in TypeScript 14 | 15 | 16 | 19 | 22 | 23 | 24 | ) 25 | } 26 | 27 | export default App 28 | -------------------------------------------------------------------------------- /packages/icons/src/svg/filled/dislike.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/content/_demo/avatar/GroupCustomSurplus.demo.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { Avatar, AvatarGroup } from '@nex-ui/react' 4 | 5 | export default function App() { 6 | return ( 7 | { 12 | return
+{surplus}
13 | }} 14 | > 15 | 16 | 17 | 18 | 19 | 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /docs/content/_demo/popover/Usage.demo.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | Popover, 3 | Button, 4 | PopoverContent, 5 | PopoverTrigger, 6 | Box, 7 | } from '@nex-ui/react' 8 | 9 | export default function App() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 21 | Popover Content 22 | 23 | 28 | This is the popover content 29 | 30 | 31 | 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /packages/react/src/components/buttonBase/__tests__/__snapshots__/ButtonBase.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`ButtonBase should render with default props 1`] = ` 4 | .emotion-0 { 5 | padding: 0; 6 | margin: 0; 7 | outline: none; 8 | background: none; 9 | border: none; 10 | -webkit-text-decoration: none; 11 | text-decoration: none; 12 | -webkit-user-select: none; 13 | -moz-user-select: none; 14 | -ms-user-select: none; 15 | user-select: none; 16 | cursor: pointer; 17 | box-sizing: border-box; 18 | -webkit-tap-highlight-color: transparent; 19 | } 20 | 21 | 28 | `; 29 | -------------------------------------------------------------------------------- /packages/react/src/components/card/__tests__/CardBody.test.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | renderWithNexUIProvider, 3 | testComponentStability, 4 | testRefForwarding, 5 | testRootClassName, 6 | } from '~/tests/shared' 7 | import { CardBody } from '../index' 8 | import { cardBodyClasses } from './classes' 9 | 10 | describe('CardBody', () => { 11 | testComponentStability() 12 | 13 | testRefForwarding() 14 | 15 | testRootClassName() 16 | 17 | it('should render with default props', () => { 18 | const { container } = renderWithNexUIProvider() 19 | 20 | const cardBodyRoot = container.firstElementChild 21 | expect(cardBodyRoot).toHaveClass(cardBodyClasses.root) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /docs/content/_demo/switch/Colors.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Switch } from '@nex-ui/react' 2 | 3 | export default function App() { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { NexUIProvider, InitColorSchemeScript } from '@nex-ui/react' 2 | import type { Metadata } from 'next' 3 | import './globals.css' 4 | 5 | export const metadata: Metadata = { 6 | title: 'Next App', 7 | description: 'Generated by nex ui cli', 8 | } 9 | 10 | const colorScheme = { colorSchemeSelector: 'class' } 11 | 12 | export default function RootLayout({ 13 | children, 14 | }: Readonly<{ 15 | children: React.ReactNode 16 | }>) { 17 | return ( 18 | 19 | 20 | 21 | {children} 22 | 23 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /packages/react/src/components/divider/__stories__/Divider.stories.tsx: -------------------------------------------------------------------------------- 1 | import { Divider } from '../Divider' 2 | import type { Meta, StoryObj } from '@storybook/react-vite' 3 | 4 | const meta = { 5 | title: 'Components/Divider', 6 | component: Divider<'hr'>, 7 | argTypes: { 8 | orientation: { 9 | control: 'select', 10 | options: ['vertical', 'horizontal'], 11 | }, 12 | }, 13 | args: { 14 | orientation: 'horizontal', 15 | }, 16 | } satisfies Meta> 17 | 18 | export default meta 19 | 20 | type Story = StoryObj 21 | 22 | export const Default: Story = { 23 | render: (args) => ( 24 |
25 | 26 |
27 | ), 28 | } 29 | -------------------------------------------------------------------------------- /docs/content/_demo/flex/Align.demo.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Box } from '@nex-ui/react' 2 | import type { ReactNode } from 'react' 3 | 4 | function Item({ children }: { children: ReactNode }) { 5 | return ( 6 | 15 | {children} 16 | 17 | ) 18 | } 19 | 20 | export default function App() { 21 | return ( 22 | 29 | Item 1 30 | Item 2 31 | Item 3 32 | 33 | ) 34 | } 35 | -------------------------------------------------------------------------------- /examples/nex-ui-nextjs-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "noEmit": true, 9 | "esModuleInterop": true, 10 | "module": "esnext", 11 | "moduleResolution": "bundler", 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "jsx": "preserve", 15 | "incremental": true, 16 | "plugins": [ 17 | { 18 | "name": "next" 19 | } 20 | ], 21 | "paths": { 22 | "@/*": ["./*"] 23 | } 24 | }, 25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 26 | "exclude": ["node_modules"] 27 | } 28 | -------------------------------------------------------------------------------- /packages/icons/src/components/filled/ExclamationShieldFilled.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const ExclamationShieldFilled = createIcon( 6 | , 12 | 'ExclamationShieldFilled', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/react/src/theme/recipes/divider.ts: -------------------------------------------------------------------------------- 1 | import { defineRecipe } from '@nex-ui/system' 2 | import type { RecipeVariants } from '@nex-ui/system' 3 | 4 | export const dividerRecipe = defineRecipe({ 5 | base: { 6 | m: 0, 7 | border: 'none', 8 | bg: 'gray.highlight', 9 | }, 10 | variants: { 11 | orientation: { 12 | vertical: { 13 | mx: '6', 14 | width: 'px', 15 | height: '100%', 16 | }, 17 | horizontal: { 18 | height: 'px', 19 | my: '6', 20 | }, 21 | }, 22 | }, 23 | defaultVariants: { 24 | orientation: 'horizontal', 25 | }, 26 | }) 27 | 28 | export type DividerRecipe = typeof dividerRecipe 29 | export type DividerVariants = RecipeVariants 30 | -------------------------------------------------------------------------------- /packages/react/src/components/card/__tests__/CardFooter.test.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | renderWithNexUIProvider, 3 | testComponentStability, 4 | testRefForwarding, 5 | testRootClassName, 6 | } from '~/tests/shared' 7 | import { CardFooter } from '../index' 8 | import { cardFooterClasses } from './classes' 9 | 10 | describe('CardFooter', () => { 11 | testComponentStability() 12 | 13 | testRefForwarding() 14 | 15 | testRootClassName() 16 | 17 | it('should render with default props', () => { 18 | const { container } = renderWithNexUIProvider() 19 | 20 | const cardFooterRoot = container.firstElementChild 21 | expect(cardFooterRoot).toHaveClass(cardFooterClasses.root) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /packages/react/src/components/dialog/index.ts: -------------------------------------------------------------------------------- 1 | export { DialogContent } from './DialogContent' 2 | export { DialogTrigger } from './DialogTrigger' 3 | export { Dialog } from './Dialog' 4 | export { DialogHeader } from './DialogHeader' 5 | export { DialogBody } from './DialogBody' 6 | export { DialogFooter } from './DialogFooter' 7 | export { DialogClose } from './DialogClose' 8 | 9 | export type { 10 | DialogProps, 11 | DialogContentProps, 12 | DialogTriggerProps, 13 | DialogHeaderProps, 14 | DialogBodyProps, 15 | DialogFooterProps, 16 | DialogCloseProps, 17 | DialogPropsOverrides, 18 | DialogBodyPropsOverrides, 19 | DialogFooterPropsOverrides, 20 | DialogHeaderPropsOverrides, 21 | DialogContentPropsOverrides, 22 | } from './types' 23 | -------------------------------------------------------------------------------- /packages/hooks/src/__tests__/useMergeRefs.test.ts: -------------------------------------------------------------------------------- 1 | import { renderHook } from '@testing-library/react' 2 | import { useRef } from 'react' 3 | import { useMergeRefs } from '../index' 4 | import type { RefCallback } from 'react' 5 | 6 | describe('useMergeRefs', () => { 7 | it('should merge refs correctly', () => { 8 | const { result } = renderHook(() => { 9 | const ref1 = useRef(null) 10 | const ref2 = useRef(null) 11 | const mergedRef = useMergeRefs(ref1, ref2) 12 | return { ref1, ref2, mergedRef } 13 | }) 14 | 15 | const { ref1, ref2, mergedRef } = result.current 16 | 17 | ;(mergedRef as RefCallback)(1) 18 | expect(ref1.current).toBe(1) 19 | expect(ref2.current).toBe(1) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /packages/icons/src/components/outlined/RepeatOutlined.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createIcon } from '../utils' 4 | 5 | export const RepeatOutlined = createIcon( 6 | , 12 | 'RepeatOutlined', 13 | ) 14 | -------------------------------------------------------------------------------- /packages/react/src/components/drawer/DrawerContext.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { createContext } from '@nex-ui/utils' 4 | import type { DrawerProps } from './types' 5 | 6 | type DrawerContextValue = Omit< 7 | DrawerProps, 8 | | 'open' 9 | | 'children' 10 | | 'restoreFocus' 11 | | 'container' 12 | | 'onOpenChange' 13 | | 'defaultOpen' 14 | | 'keepMounted' 15 | | 'preventScroll' 16 | | 'closeOnEscape' 17 | | 'onClose' 18 | | 'closeOnInteractBackdrop' 19 | > 20 | 21 | export const [DrawerProvider, useDrawer] = createContext({ 22 | contextName: 'DrawerContext', 23 | hookName: 'useDrawer', 24 | providerName: 'DrawerProvider', 25 | strict: true, 26 | defaultValue: null as unknown as DrawerContextValue, 27 | }) 28 | -------------------------------------------------------------------------------- /packages/react/src/components/box/types.ts: -------------------------------------------------------------------------------- 1 | import type { ElementType } from 'react' 2 | import type { OverrideProps } from '../../types/utils' 3 | import type { Interpolation } from '@nex-ui/system' 4 | 5 | export interface BoxPropsOverrides {} 6 | 7 | type BoxOwnProps = { 8 | /** 9 | * The component or element to render as the root. 10 | * @default 'div' 11 | */ 12 | as?: RootComponent 13 | 14 | /** 15 | * The system prop that allows defining system overrides as well as additional CSS styles. 16 | */ 17 | sx?: Interpolation 18 | } 19 | 20 | export type BoxProps = OverrideProps< 21 | RootComponent, 22 | BoxOwnProps, 23 | BoxPropsOverrides 24 | > 25 | -------------------------------------------------------------------------------- /examples/nex-ui-vite/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "verbatimModuleSyntax": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "erasableSyntaxOnly": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedSideEffectImports": true 23 | }, 24 | "include": ["vite.config.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /docs/content/zh/docs/customization/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | '#': { 3 | type: 'separator', 4 | title: 'THEME', 5 | }, 6 | theming: '定制主题', 7 | 'dark-mode': '深色模式', 8 | scales: 'Scales', 9 | tokens: 'Tokens', 10 | 'semantic-tokens': 'Semantic Tokens', 11 | components: 'Components', 12 | aliases: 'Aliases', 13 | breakpoints: 'Breakpoints', 14 | selectors: 'Selectors', 15 | '##': { 16 | type: 'separator', 17 | title: 'DESIGN TOKENS', 18 | }, 19 | colors: 'Colors', 20 | sizes: 'Sizes', 21 | spaces: 'Spaces', 22 | radii: 'Radii', 23 | shadows: 'Shadows', 24 | borders: 'Borders', 25 | 'border-widths': 'BorderWidths', 26 | transitions: 'Transitions', 27 | typography: 'Typography', 28 | 'z-indices': 'Z-Indices', 29 | } 30 | -------------------------------------------------------------------------------- /examples/nex-ui-vite-swc/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "verbatimModuleSyntax": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "erasableSyntaxOnly": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedSideEffectImports": true 23 | }, 24 | "include": ["vite.config.ts"] 25 | } 26 | --------------------------------------------------------------------------------