@agility/plenum-ui 2.0.0-rc2 → 2.0.0-rc21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -11
- package/build.js +30 -25
- package/dist/index.d.ts +279 -93
- package/dist/index.js +1 -5935
- package/dist/index.js.map +4 -4
- package/dist/tailwind.css +63516 -0
- package/dist/types/stories/atoms/buttons/Button/Alternative/Alternative.stories.d.ts +1 -0
- package/dist/types/stories/atoms/buttons/Button/Button.d.ts +7 -9
- package/dist/types/stories/atoms/buttons/Button/Danger/Danger.stories.d.ts +1 -0
- package/dist/types/stories/atoms/buttons/Button/Primary/Primary.stories.d.ts +1 -0
- package/dist/types/stories/atoms/buttons/Button/Secondary/Secondary.stories.d.ts +1 -0
- package/dist/types/stories/atoms/buttons/Capsule/Capsule.d.ts +1 -1
- package/dist/types/stories/atoms/icons/DynamicIcon.d.ts +1 -1
- package/dist/types/stories/atoms/icons/TablerIcon.d.ts +1 -1
- package/dist/types/stories/index.d.ts +4 -4
- package/dist/types/stories/molecules/index.d.ts +3 -3
- package/dist/types/stories/molecules/inputs/InputCounter/InputCounter.d.ts +10 -0
- package/dist/types/stories/molecules/inputs/InputCounter/index.d.ts +2 -0
- package/dist/types/stories/molecules/inputs/InputField/InputField.d.ts +8 -4
- package/dist/types/stories/molecules/inputs/TextInput/TextInput.d.ts +39 -0
- package/dist/types/stories/molecules/inputs/TextInput/index.d.ts +4 -0
- package/dist/types/stories/molecules/inputs/index.d.ts +5 -4
- package/dist/types/stories/molecules/inputs/select/Select.d.ts +2 -2
- package/dist/types/stories/molecules/inputs/textArea/TextArea.d.ts +34 -21
- package/dist/types/stories/molecules/inputs/textArea/TextArea.stories.d.ts +4 -4
- package/dist/types/stories/molecules/inputs/textArea/index.d.ts +3 -3
- package/dist/types/stories/molecules/inputs/toggleSwitch/ToggleSwitch.d.ts +9 -7
- package/dist/types/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.d.ts +3 -5
- package/dist/types/stories/organisms/AnimatedLabelInput/index.d.ts +1 -1
- package/dist/types/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.d.ts +12 -0
- package/dist/types/stories/organisms/AnimatedLabelTextArea/index.d.ts +3 -0
- package/dist/types/stories/organisms/DropdownComponent/DropdownComponent.d.ts +18 -15
- package/dist/types/stories/organisms/DropdownComponent/index.d.ts +2 -2
- package/dist/types/stories/organisms/EmptySectionPlaceholder/index.d.ts +1 -1
- package/dist/types/stories/organisms/TextInputSelect/InputSelect.d.ts +16 -0
- package/dist/types/stories/organisms/TextInputSelect/TextInputSelect.d.ts +48 -0
- package/dist/types/stories/organisms/TextInputSelect/index.d.ts +3 -0
- package/dist/types/stories/organisms/index.d.ts +5 -3
- package/local.sh +100 -0
- package/package.json +35 -18
- package/rollup.config.mjs +42 -0
- package/stories/Introduction.mdx +1 -1
- package/stories/atoms/buttons/Button/Alternative/Alternative.stories.ts +7 -0
- package/stories/atoms/buttons/Button/Button.tsx +45 -17
- package/stories/atoms/buttons/Button/Danger/Danger.stories.ts +7 -0
- package/stories/atoms/buttons/Button/Primary/Primary.stories.ts +7 -0
- package/stories/atoms/buttons/Button/Secondary/Secondary.stories.ts +7 -0
- package/stories/atoms/buttons/Capsule/Capsule.tsx +2 -1
- package/stories/atoms/icons/DynamicIcon.tsx +3 -2
- package/stories/atoms/icons/TablerIcon.tsx +1 -1
- package/stories/atoms/loaders/Loader.tsx +12 -6
- package/stories/index.ts +22 -10
- package/stories/molecules/index.ts +22 -6
- package/stories/molecules/inputs/InputCounter/InputCounter.stories.tsx +18 -0
- package/stories/molecules/inputs/InputCounter/InputCounter.tsx +24 -0
- package/stories/molecules/inputs/InputCounter/index.tsx +3 -0
- package/stories/molecules/inputs/InputField/InputField.tsx +13 -7
- package/stories/molecules/inputs/TextInput/TextInput.stories.tsx +32 -0
- package/stories/molecules/inputs/TextInput/TextInput.tsx +165 -0
- package/stories/molecules/inputs/TextInput/index.tsx +5 -0
- package/stories/molecules/inputs/checkbox/Checkbox.tsx +1 -1
- package/stories/molecules/inputs/index.ts +18 -4
- package/stories/molecules/inputs/select/Select.tsx +1 -1
- package/stories/molecules/inputs/textArea/TextArea.stories.ts +7 -5
- package/stories/molecules/inputs/textArea/TextArea.tsx +139 -48
- package/stories/molecules/inputs/textArea/index.ts +3 -3
- package/stories/molecules/inputs/toggleSwitch/ToggleSwitch.tsx +61 -57
- package/stories/molecules/tabs/index.tsx +2 -3
- package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.stories.tsx +10 -1
- package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.tsx +43 -37
- package/stories/organisms/AnimatedLabelInput/index.tsx +1 -1
- package/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.stories.tsx +26 -0
- package/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.tsx +61 -0
- package/stories/organisms/AnimatedLabelTextArea/index.tsx +3 -0
- package/stories/organisms/ButtonDropdown/ButtonDropdown.stories.tsx +59 -58
- package/stories/organisms/ButtonDropdown/ButtonDropdown.tsx +13 -16
- package/stories/organisms/DropdownComponent/Dropdown.stories.tsx +1 -1
- package/stories/organisms/DropdownComponent/DropdownComponent.tsx +155 -131
- package/stories/organisms/DropdownComponent/dropdownItems.ts +32 -8
- package/stories/organisms/DropdownComponent/index.ts +2 -2
- package/stories/organisms/EmptySectionPlaceholder/index.tsx +2 -1
- package/stories/organisms/FormInputWithAddons/FormInputWithAddons.tsx +7 -2
- package/stories/organisms/TextInputSelect/InputSelect.tsx +59 -0
- package/stories/organisms/TextInputSelect/TextInputSelect.stories.tsx +33 -0
- package/stories/organisms/TextInputSelect/TextInputSelect.tsx +186 -0
- package/stories/organisms/TextInputSelect/index.tsx +3 -0
- package/stories/organisms/index.ts +15 -4
- package/tsconfig.lib.json +13 -6
- package/watch.js +50 -0
- package/.yarnrc.yml +0 -1
- package/dist/types/stories/layouts/index.d.ts +0 -0
- package/stories/layouts/CardLayout/CardLayout.stories.tsx +0 -18
- package/stories/layouts/CardLayout/CardLayout.tsx +0 -22
- package/stories/layouts/CardLayout/index.tsx +0 -3
- package/stories/layouts/ModalLayout/ModalLayout.stories.tsx +0 -18
- package/stories/layouts/ModalLayout/ModalLayout.tsx +0 -22
- package/stories/layouts/ModalLayout/index.tsx +0 -3
- package/stories/layouts/index.ts +0 -0
- package/stories/organisms/DropdownComponent/Dropdown.test.tsx +0 -0
|
@@ -13,14 +13,15 @@ export type AcceptedInputTypes =
|
|
|
13
13
|
| "tel"
|
|
14
14
|
| "text"
|
|
15
15
|
| "url"
|
|
16
|
+
| "currency"
|
|
16
17
|
|
|
17
|
-
export interface IInputFieldProps extends React.
|
|
18
|
+
export interface IInputFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
|
|
18
19
|
/** Callback on change */
|
|
19
20
|
handleChange: (value: string) => void
|
|
20
21
|
/** Input ID*/
|
|
21
|
-
id
|
|
22
|
+
id?: string
|
|
22
23
|
/** Input Name */
|
|
23
|
-
name
|
|
24
|
+
name?: string
|
|
24
25
|
/** Force the focus state on the input */
|
|
25
26
|
isFocused?: boolean
|
|
26
27
|
/** Error condition */
|
|
@@ -37,7 +38,10 @@ export interface IInputFieldProps extends React.ComponentPropsWithoutRef<"input"
|
|
|
37
38
|
required?: boolean
|
|
38
39
|
/** use input psuedo classes for :valid and :invalid styles. on by default */
|
|
39
40
|
clientSideCheck?: boolean
|
|
40
|
-
/**
|
|
41
|
+
/** Placeholder text */
|
|
42
|
+
placeholder?: string
|
|
43
|
+
/**ref for input */
|
|
44
|
+
ref?: React.Ref<HTMLInputElement>
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
const InputField: React.FC<IInputFieldProps> = ({
|
|
@@ -52,24 +56,26 @@ const InputField: React.FC<IInputFieldProps> = ({
|
|
|
52
56
|
handleChange,
|
|
53
57
|
required,
|
|
54
58
|
clientSideCheck = true,
|
|
55
|
-
placeholder,
|
|
56
59
|
className,
|
|
60
|
+
placeholder,
|
|
61
|
+
ref,
|
|
57
62
|
...rest
|
|
58
63
|
}) => {
|
|
59
64
|
return (
|
|
60
65
|
<input
|
|
61
66
|
{...{
|
|
67
|
+
ref,
|
|
62
68
|
type,
|
|
63
69
|
id,
|
|
64
70
|
name,
|
|
65
71
|
value,
|
|
66
72
|
onChange: (e) => {
|
|
67
|
-
handleChange(e.target.value)
|
|
73
|
+
if (handleChange) handleChange(e.target.value)
|
|
68
74
|
},
|
|
69
75
|
autoFocus: isFocused,
|
|
70
76
|
readOnly: isReadonly,
|
|
71
77
|
disabled: isDisabled,
|
|
72
|
-
placeholder: placeholder ||
|
|
78
|
+
placeholder: placeholder || undefined,
|
|
73
79
|
required,
|
|
74
80
|
"aria-invalid": isError,
|
|
75
81
|
"aria-disabled": isDisabled,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import TextInput, { ITextInputProps } from "./TextInput"
|
|
3
|
+
import React from "react"
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof TextInput> = {
|
|
6
|
+
title: "Design System/molecules/inputs/TextInput",
|
|
7
|
+
component: TextInput,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
argTypes: {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default meta
|
|
13
|
+
type Story = StoryObj<typeof TextInput>
|
|
14
|
+
|
|
15
|
+
export const DefaultTextInputStory: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
type: "text",
|
|
18
|
+
label: "Label",
|
|
19
|
+
isFocused: true,
|
|
20
|
+
isError: false,
|
|
21
|
+
id: "id",
|
|
22
|
+
name: "name",
|
|
23
|
+
isRequired: true,
|
|
24
|
+
|
|
25
|
+
isDisabled: false,
|
|
26
|
+
isReadonly: false,
|
|
27
|
+
message: "message",
|
|
28
|
+
isShowCounter: true,
|
|
29
|
+
maxLength: 100,
|
|
30
|
+
placeholder: "placeholder"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { forwardRef, useEffect, useId, useRef, useState } from "react"
|
|
2
|
+
import { default as cn } from "classnames"
|
|
3
|
+
import InputLabel from "../InputLabel"
|
|
4
|
+
import InputField, { AcceptedInputTypes } from "../InputField"
|
|
5
|
+
import InputCounter from "../InputCounter"
|
|
6
|
+
|
|
7
|
+
export interface ITextInputProps {
|
|
8
|
+
/** Input type*/
|
|
9
|
+
type: AcceptedInputTypes
|
|
10
|
+
/** Input ID */
|
|
11
|
+
id?: string
|
|
12
|
+
/** Input Name */
|
|
13
|
+
name?: string
|
|
14
|
+
/** Label for the input */
|
|
15
|
+
label?: string
|
|
16
|
+
/** Force the focus state on the input */
|
|
17
|
+
isFocused?: boolean
|
|
18
|
+
/** Error state */
|
|
19
|
+
isError?: boolean
|
|
20
|
+
/** If field is required */
|
|
21
|
+
isRequired?: boolean
|
|
22
|
+
/** Disabled state */
|
|
23
|
+
isDisabled?: boolean
|
|
24
|
+
/** Readonly state */
|
|
25
|
+
isReadonly?: boolean
|
|
26
|
+
/** Set default value */
|
|
27
|
+
defaultValue?: string
|
|
28
|
+
/** Message shown under the text field */
|
|
29
|
+
message?: string
|
|
30
|
+
/** Input character counter */
|
|
31
|
+
isShowCounter?: boolean
|
|
32
|
+
/** Max length of input character */
|
|
33
|
+
maxLength?: number
|
|
34
|
+
/** Callback on change */
|
|
35
|
+
handleChange(value: string): void
|
|
36
|
+
/** input value */
|
|
37
|
+
value: string
|
|
38
|
+
/**Placeholder input text*/
|
|
39
|
+
placeholder?: string
|
|
40
|
+
|
|
41
|
+
className?: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const TextInput = (
|
|
45
|
+
{
|
|
46
|
+
label,
|
|
47
|
+
isFocused,
|
|
48
|
+
isError,
|
|
49
|
+
id,
|
|
50
|
+
name,
|
|
51
|
+
isRequired,
|
|
52
|
+
type,
|
|
53
|
+
defaultValue,
|
|
54
|
+
isDisabled,
|
|
55
|
+
isReadonly,
|
|
56
|
+
message,
|
|
57
|
+
isShowCounter,
|
|
58
|
+
maxLength,
|
|
59
|
+
handleChange,
|
|
60
|
+
placeholder,
|
|
61
|
+
value: externalValue,
|
|
62
|
+
className,
|
|
63
|
+
...props
|
|
64
|
+
}: ITextInputProps,
|
|
65
|
+
ref: React.Ref<HTMLInputElement>
|
|
66
|
+
) => {
|
|
67
|
+
const uniqueID = useId()
|
|
68
|
+
const [isFocus, setIsFocus] = useState<boolean>(Boolean(isFocused))
|
|
69
|
+
|
|
70
|
+
const [value, setValue] = useState<string>(externalValue || defaultValue || "")
|
|
71
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
//if the external value is updated by the parent component, reset the value in here...
|
|
75
|
+
if (externalValue !== undefined && externalValue !== null) {
|
|
76
|
+
setValue(externalValue)
|
|
77
|
+
}
|
|
78
|
+
}, [externalValue])
|
|
79
|
+
|
|
80
|
+
// set force focus
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const input = inputRef.current
|
|
83
|
+
if (!input || isFocus === undefined || isDisabled) return
|
|
84
|
+
if (isFocus) {
|
|
85
|
+
input.focus()
|
|
86
|
+
} else {
|
|
87
|
+
input.blur()
|
|
88
|
+
}
|
|
89
|
+
}, [isFocus])
|
|
90
|
+
|
|
91
|
+
// set label as active if default value is set
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
const input = inputRef.current
|
|
94
|
+
if (!input || defaultValue === undefined || defaultValue === "") return
|
|
95
|
+
}, [defaultValue])
|
|
96
|
+
|
|
97
|
+
const handleInputFocus = () => setIsFocus(true)
|
|
98
|
+
// add other focus effects here
|
|
99
|
+
|
|
100
|
+
const handleInputBlur = () => setIsFocus(false)
|
|
101
|
+
|
|
102
|
+
if (!id) id = `input-${uniqueID}`
|
|
103
|
+
if (!name) name = id
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div className="relative">
|
|
107
|
+
<InputLabel
|
|
108
|
+
isPlaceholder={true}
|
|
109
|
+
label={label}
|
|
110
|
+
isRequired={isRequired}
|
|
111
|
+
id={id}
|
|
112
|
+
isError={isError}
|
|
113
|
+
isActive={true}
|
|
114
|
+
isDisabled={isDisabled}
|
|
115
|
+
/>
|
|
116
|
+
<InputField
|
|
117
|
+
onFocus={handleInputFocus}
|
|
118
|
+
onBlur={handleInputBlur}
|
|
119
|
+
handleChange={(v: string) => {
|
|
120
|
+
setValue(v)
|
|
121
|
+
handleChange(v)
|
|
122
|
+
}}
|
|
123
|
+
ref={ref}
|
|
124
|
+
type={type}
|
|
125
|
+
name={name}
|
|
126
|
+
id={id}
|
|
127
|
+
className={cn(
|
|
128
|
+
"w-full rounded border py-2 px-3 text-sm font-normal leading-5",
|
|
129
|
+
{ "border-gray-300": !isFocus && !isError },
|
|
130
|
+
{
|
|
131
|
+
"!border-purple-500 shadow-none outline-purple-500 focus:!ring-purple-500": isFocus && !isError
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"!border-red-500 shadow-none focus:ring-red-500": isError
|
|
135
|
+
},
|
|
136
|
+
className
|
|
137
|
+
)}
|
|
138
|
+
isDisabled={isDisabled}
|
|
139
|
+
isReadonly={isReadonly}
|
|
140
|
+
value={value}
|
|
141
|
+
defaultValue={defaultValue}
|
|
142
|
+
maxLength={maxLength}
|
|
143
|
+
placeholder={placeholder}
|
|
144
|
+
{...props}
|
|
145
|
+
/>
|
|
146
|
+
<div className="flex flex-row space-x-3">
|
|
147
|
+
<div className="grow">
|
|
148
|
+
{message && (
|
|
149
|
+
<span className={cn("mt-1 block text-sm", isError ? "text-red-500" : "text-gray-500")}>
|
|
150
|
+
{message}
|
|
151
|
+
</span>
|
|
152
|
+
)}
|
|
153
|
+
</div>
|
|
154
|
+
{isShowCounter && (
|
|
155
|
+
<div className="shrink-0">
|
|
156
|
+
<InputCounter current={Number(value?.length)} limit={maxLength} />
|
|
157
|
+
</div>
|
|
158
|
+
)}
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const _TextInput = forwardRef<HTMLInputElement, ITextInputProps>(TextInput)
|
|
165
|
+
export default _TextInput
|
|
@@ -53,7 +53,7 @@ const Checkbox: FC<ICheckboxProps> = ({
|
|
|
53
53
|
const wrapperStyles = cn(
|
|
54
54
|
"relative flex items-center min-h-[38px]",
|
|
55
55
|
{ "opacity-50": isDisabled },
|
|
56
|
-
{ "rounded-sm
|
|
56
|
+
{ "rounded-sm border border-1 px-3 border-gray-200": hasBorder },
|
|
57
57
|
{ "py-3": hasBorder && message },
|
|
58
58
|
className
|
|
59
59
|
)
|
|
@@ -4,8 +4,9 @@ import InputField, { AcceptedInputTypes, IInputFieldProps } from "./InputField"
|
|
|
4
4
|
import InputLabel, { IInputLabelProps } from "./InputLabel"
|
|
5
5
|
import NestedInputButton, { INestedInputButtonProps } from "./NestedInputButton"
|
|
6
6
|
import Radio, { IRadioProps } from "./radio"
|
|
7
|
-
import Select, { ISelectProps } from "./select"
|
|
8
|
-
import
|
|
7
|
+
import Select, { ISelectProps, ISimpleSelectOptions } from "./select"
|
|
8
|
+
import Textarea, { ITextareaProps } from "./textArea"
|
|
9
|
+
import TextInput, { ITextInputProps } from "./TextInput"
|
|
9
10
|
import ToggleSwitch, { IToggleSwitchProps } from "./toggleSwitch"
|
|
10
11
|
|
|
11
12
|
export type {
|
|
@@ -16,9 +17,22 @@ export type {
|
|
|
16
17
|
INestedInputButtonProps,
|
|
17
18
|
IRadioProps,
|
|
18
19
|
ISelectProps,
|
|
19
|
-
|
|
20
|
+
ISimpleSelectOptions,
|
|
21
|
+
ITextareaProps,
|
|
22
|
+
ITextInputProps,
|
|
20
23
|
IToggleSwitchProps,
|
|
21
24
|
AcceptedInputTypes
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
export {
|
|
27
|
+
export {
|
|
28
|
+
Checkbox,
|
|
29
|
+
Combobox,
|
|
30
|
+
InputField,
|
|
31
|
+
InputLabel,
|
|
32
|
+
NestedInputButton,
|
|
33
|
+
Radio,
|
|
34
|
+
Select,
|
|
35
|
+
Textarea,
|
|
36
|
+
ToggleSwitch,
|
|
37
|
+
TextInput
|
|
38
|
+
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
-
import
|
|
3
|
-
const meta: Meta<typeof
|
|
2
|
+
import Textarea from "./TextArea"
|
|
3
|
+
const meta: Meta<typeof Textarea> = {
|
|
4
4
|
title: "Design System/Molecules/Inputs/TextArea",
|
|
5
|
-
component:
|
|
5
|
+
component: Textarea,
|
|
6
6
|
tags: ["autodocs"]
|
|
7
7
|
}
|
|
8
8
|
const dummyText: string = `Checkmate... Life finds a way. Is this my espresso machine? Wh-what is-h-how did you get my espresso machine? You're a very talented young man, with your own clever thoughts and ideas. Do you need a manager? Is this my espresso machine? Wh-what is-h-how did you get my espresso machine?
|
|
9
9
|
|
|
10
10
|
I was part of something special. Just my luck, no ice. You really think you can fly that thing? Must go faster... go, go, go, go, go! God creates dinosaurs. God destroys dinosaurs. God creates Man. Man destroys God. Man creates Dinosaurs. Yeah, but your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should.`
|
|
11
|
-
type Story = StoryObj<typeof
|
|
12
|
-
export const
|
|
11
|
+
type Story = StoryObj<typeof Textarea>
|
|
12
|
+
export const DefaultTextarea: Story = {
|
|
13
13
|
args: {
|
|
14
14
|
id: "appDescription",
|
|
15
15
|
name: "description",
|
|
16
16
|
rows: 12,
|
|
17
|
+
cols: 18,
|
|
18
|
+
label: { display: "Description" },
|
|
17
19
|
placeholder: dummyText
|
|
18
20
|
}
|
|
19
21
|
}
|
|
@@ -1,67 +1,158 @@
|
|
|
1
|
+
import React, { forwardRef, useEffect, useId, useState } from "react"
|
|
1
2
|
import { default as cn } from "classnames"
|
|
3
|
+
import InputLabel from "../InputLabel"
|
|
4
|
+
import InputCounter from "../InputCounter"
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
interface ILabelProps extends React.DetailedHTMLProps<React.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement> {
|
|
7
|
+
display: string
|
|
8
|
+
htmlFor?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ITextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> {
|
|
12
|
+
/** Input ID */
|
|
13
|
+
id?: string
|
|
14
|
+
/** Input Name */
|
|
15
|
+
name?: string
|
|
16
|
+
/** Label for the input */
|
|
17
|
+
label?: ILabelProps
|
|
18
|
+
/** Error state */
|
|
13
19
|
isError?: boolean
|
|
20
|
+
/** If field is required */
|
|
21
|
+
isRequired?: boolean
|
|
14
22
|
/** Disabled state */
|
|
15
23
|
isDisabled?: boolean
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
value
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
/** Set default value */
|
|
25
|
+
defaultValue?: string
|
|
26
|
+
|
|
27
|
+
value?: string
|
|
28
|
+
|
|
29
|
+
/** Message shown under the text field */
|
|
30
|
+
message?: string
|
|
31
|
+
/** Input character counter */
|
|
32
|
+
isShowCounter?: boolean
|
|
33
|
+
/** Max length of input character */
|
|
34
|
+
maxLength?: number
|
|
35
|
+
/** Callback on change */
|
|
36
|
+
onChange?(value: string): void
|
|
37
|
+
/** Number of rows */
|
|
38
|
+
rows?: number
|
|
39
|
+
/** Number of cols */
|
|
40
|
+
cols?: number
|
|
41
|
+
placeholder?: string
|
|
24
42
|
className?: string
|
|
43
|
+
ref?: React.LegacyRef<HTMLTextAreaElement>
|
|
25
44
|
}
|
|
26
|
-
|
|
45
|
+
|
|
46
|
+
const Textarea: React.FC<ITextareaProps> = ({
|
|
27
47
|
id,
|
|
28
48
|
name,
|
|
29
|
-
|
|
30
|
-
isFocused,
|
|
49
|
+
label,
|
|
31
50
|
isError,
|
|
32
|
-
|
|
51
|
+
isRequired,
|
|
33
52
|
isDisabled,
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
defaultValue,
|
|
54
|
+
message,
|
|
55
|
+
isShowCounter,
|
|
56
|
+
maxLength,
|
|
57
|
+
rows = 12,
|
|
58
|
+
cols = 48,
|
|
59
|
+
onChange,
|
|
60
|
+
value,
|
|
36
61
|
placeholder,
|
|
37
62
|
className,
|
|
63
|
+
ref,
|
|
38
64
|
...rest
|
|
39
65
|
}) => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
const uniqueID = useId()
|
|
67
|
+
|
|
68
|
+
const discriptionStyles = cn("text-sm mt-1 block", { "text-gray-500": !isError }, { "text-red-500": isError })
|
|
69
|
+
|
|
70
|
+
if (!id) id = `ta-${uniqueID}`
|
|
71
|
+
|
|
72
|
+
if (!label) {
|
|
73
|
+
return (
|
|
74
|
+
<textarea
|
|
75
|
+
ref={ref}
|
|
76
|
+
maxLength={maxLength}
|
|
77
|
+
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
78
|
+
const targetValue = e.target.value
|
|
79
|
+
if (onChange) {
|
|
80
|
+
onChange(targetValue)
|
|
81
|
+
}
|
|
82
|
+
}}
|
|
83
|
+
rows={rows}
|
|
84
|
+
name={name}
|
|
85
|
+
id={id}
|
|
86
|
+
cols={cols}
|
|
87
|
+
className={cn(
|
|
88
|
+
"peer block w-full rounded focus:border-purple-500 focus:ring-purple-500 sm:text-sm",
|
|
89
|
+
{ "border-gray-300 ": !isError },
|
|
90
|
+
{
|
|
91
|
+
"border-red-500 outline-red-500 focus:ring-red-500": isError
|
|
92
|
+
},
|
|
59
93
|
className
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
94
|
+
)}
|
|
95
|
+
disabled={isDisabled}
|
|
96
|
+
defaultValue={defaultValue}
|
|
97
|
+
value={value}
|
|
98
|
+
placeholder={placeholder}
|
|
99
|
+
{...rest}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//with label
|
|
105
|
+
return (
|
|
106
|
+
<div>
|
|
107
|
+
<InputLabel
|
|
108
|
+
isPlaceholder
|
|
109
|
+
isActive
|
|
110
|
+
label={label.display}
|
|
111
|
+
isRequired={isRequired}
|
|
112
|
+
id={id}
|
|
113
|
+
isError={isError}
|
|
114
|
+
isDisabled={isDisabled}
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<div>
|
|
118
|
+
<textarea
|
|
119
|
+
ref={ref}
|
|
120
|
+
maxLength={maxLength}
|
|
121
|
+
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
122
|
+
const targetValue = e.target.value
|
|
123
|
+
if (onChange) {
|
|
124
|
+
onChange(targetValue)
|
|
125
|
+
}
|
|
126
|
+
}}
|
|
127
|
+
rows={rows}
|
|
128
|
+
name={name}
|
|
129
|
+
id={id}
|
|
130
|
+
cols={cols}
|
|
131
|
+
className={cn(
|
|
132
|
+
"block w-full rounded focus:border-purple-500 focus:ring-purple-500 sm:text-sm",
|
|
133
|
+
{ "border-gray-300 ": !isError },
|
|
134
|
+
{
|
|
135
|
+
"border-red-500 outline-red-500 focus:ring-red-500": isError
|
|
136
|
+
},
|
|
137
|
+
className
|
|
138
|
+
)}
|
|
139
|
+
disabled={isDisabled}
|
|
140
|
+
defaultValue={defaultValue}
|
|
141
|
+
value={value}
|
|
142
|
+
placeholder={placeholder}
|
|
143
|
+
{...rest}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
<div className="flex flex-row space-x-3">
|
|
147
|
+
<div className="grow">{message && <span className={discriptionStyles}>{message}</span>}</div>
|
|
148
|
+
{isShowCounter && (
|
|
149
|
+
<div className="shrink-0">
|
|
150
|
+
<InputCounter current={Number(value?.length)} limit={maxLength} />
|
|
151
|
+
</div>
|
|
152
|
+
)}
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
64
155
|
)
|
|
65
156
|
}
|
|
66
157
|
|
|
67
|
-
export default
|
|
158
|
+
export default Textarea
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
export type {
|
|
3
|
-
export default
|
|
1
|
+
import TextArea, { ITextareaProps } from "./TextArea"
|
|
2
|
+
export type { ITextareaProps }
|
|
3
|
+
export default TextArea
|