Skip to content

Commit

Permalink
feat: add form component with input support
Browse files Browse the repository at this point in the history
  • Loading branch information
ryo-manba committed May 21, 2024
1 parent c337b95 commit e025943
Show file tree
Hide file tree
Showing 10 changed files with 1,672 additions and 10 deletions.
24 changes: 24 additions & 0 deletions packages/components/form/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# @nextui-org/form

A Quick description of the component

> This is an internal utility, not intended for public usage.
## Installation

```sh
yarn add @nextui-org/form
# or
npm i @nextui-org/form
```

## Contribution

Yes please! See the
[contributing guidelines](https://github.com/nextui-org/nextui/blob/master/CONTRIBUTING.md)
for details.

## License

This project is licensed under the terms of the
[MIT license](https://github.com/nextui-org/nextui/blob/master/LICENSE).
56 changes: 56 additions & 0 deletions packages/components/form/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "@nextui-org/form",
"version": "2.0.0",
"description": "A form is a group of inputs that allows users submit data to a server and supports field validation errors.",
"keywords": [
"form"
],
"author": "Junior Garcia <jrgarciadev@gmail.com>",
"homepage": "https://nextui.org",
"license": "MIT",
"main": "src/index.ts",
"sideEffects": false,
"files": [
"dist"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nextui-org/nextui.git",
"directory": "packages/components/form"
},
"bugs": {
"url": "https://github.com/nextui-org/nextui/issues"
},
"scripts": {
"build": "tsup src --dts",
"build:fast": "tsup src",
"dev": "pnpm build:fast --watch",
"clean": "rimraf dist .turbo",
"typecheck": "tsc --noEmit",
"prepack": "clean-package",
"postpack": "clean-package restore"
},
"peerDependencies": {
"@nextui-org/system": ">=2.0.0",
"@nextui-org/theme": ">=2.0.0",
"react": ">=18",
"react-dom": ">=18"
},
"dependencies": {
"@nextui-org/react-utils": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/input": "workspace:*",
"react-aria-components": "^1.2.1"
},
"devDependencies": {
"@nextui-org/system": "workspace:*",
"@nextui-org/theme": "workspace:*",
"clean-package": "2.2.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"clean-package": "../../../clean-package.config.json"
}
3 changes: 3 additions & 0 deletions packages/components/form/src/form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export {Form} from "react-aria-components";
export {FormContext} from "react-aria-components";
export {useSlottedContext} from "react-aria-components";
11 changes: 11 additions & 0 deletions packages/components/form/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// export types
export type {FormProps} from "react-aria-components";

// export hooks
export {useSlottedContext} from "react-aria-components";

// export context
export {FormContext} from "react-aria-components";

// export component
export {Form} from "react-aria-components";
65 changes: 65 additions & 0 deletions packages/components/form/stories/form.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
import {Meta} from "@storybook/react";
import {Input} from "@nextui-org/input";
import {button} from "@nextui-org/theme";

import {Form, FormProps} from "../src";

export default {
title: "Components/Form",
component: Form,
argTypes: {
isDisabled: {
control: {
type: "boolean",
},
},
validationBehavior: {
control: {
type: "select",
},
options: ["aria", "native"],
},
},
} as Meta<typeof Form>;

const defaultProps = {};

const Template = (args: FormProps) => (
<Form
{...args}
className="flex flex-col gap-4"
onSubmit={(e) => {
e.preventDefault();
alert(`Submitted value: ${e.target["input"].value}`);
}}
>
<Input isRequired label="Name (required)" name="input" />
<button className={button({className: "max-w-fit"})} type="submit">
Submit
</button>
</Form>
);

export const Default = {
render: Template,
args: {
...defaultProps,
},
};

export const NativeValidation = {
render: Template,
args: {
...defaultProps,
validationBehavior: "native",
},
};

export const AriaValidation = {
render: Template,
args: {
...defaultProps,
validationBehavior: "aria",
},
};
10 changes: 10 additions & 0 deletions packages/components/form/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"tailwind-variants": ["../../../node_modules/tailwind-variants"]
},
},
"include": ["src", "index.ts"]
}
8 changes: 8 additions & 0 deletions packages/components/form/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {defineConfig} from "tsup";

export default defineConfig({
clean: true,
target: "es2019",
format: ["cjs", "esm"],
banner: {js: '"use client";'},
});
9 changes: 5 additions & 4 deletions packages/components/input/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@
"postpack": "clean-package restore"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18",
"@nextui-org/system": ">=2.0.0",
"@nextui-org/theme": ">=2.1.0",
"@nextui-org/system": ">=2.0.0"
"react": ">=18",
"react-dom": ">=18"
},
"dependencies": {
"@nextui-org/form": "workspace:*",
"@nextui-org/react-utils": "workspace:*",
"@nextui-org/shared-icons": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
Expand All @@ -54,8 +55,8 @@
"react-textarea-autosize": "^8.5.3"
},
"devDependencies": {
"@nextui-org/theme": "workspace:*",
"@nextui-org/system": "workspace:*",
"@nextui-org/theme": "workspace:*",
"clean-package": "2.2.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/components/input/src/use-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {useControlledState} from "@react-stately/utils";
import {useMemo, Ref, useCallback, useState} from "react";
import {chain, mergeProps} from "@react-aria/utils";
import {useTextField} from "@react-aria/textfield";
import {FormContext, useSlottedContext} from "@nextui-org/form";

export interface Props<T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement>
extends Omit<HTMLNextUIProps<"input">, keyof InputVariantProps> {
Expand Down Expand Up @@ -92,6 +93,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
originalProps: UseInputProps<T>,
) {
const globalContext = useProviderContext();
const {validationBehavior: formValidationBehavior} = useSlottedContext(FormContext) || {};

const [props, variantProps] = mapPropsVariants(originalProps, input.variantKeys);

Expand All @@ -111,7 +113,7 @@ export function useInput<T extends HTMLInputElement | HTMLTextAreaElement = HTML
onClear,
onChange,
validationState,
validationBehavior = globalContext?.validationBehavior ?? "aria",
validationBehavior = formValidationBehavior ?? globalContext?.validationBehavior ?? "aria",
innerWrapperRef: innerWrapperRefProp,
onValueChange = () => {},
...otherProps
Expand Down
Loading

0 comments on commit e025943

Please sign in to comment.