@agility/plenum-ui 2.0.0-rc9 → 2.0.0
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 +104 -31
- package/build.js +30 -25
- package/dist/index.d.ts +101 -61
- package/dist/index.js +1 -6295
- package/dist/index.js.map +4 -4
- package/dist/{lib/tailwind.css → tailwind.css} +3729 -8120
- package/dist/types/stories/atoms/buttons/Button/Alternative/Alternative.stories.d.ts +1 -0
- package/dist/types/stories/atoms/buttons/Button/Button.d.ts +3 -7
- 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 +2 -2
- 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/inputs/InputField/InputField.d.ts +7 -7
- package/dist/types/stories/molecules/inputs/TextInput/TextInput.d.ts +1 -1
- package/dist/types/stories/molecules/inputs/select/Select.d.ts +4 -2
- package/dist/types/stories/molecules/inputs/textArea/TextArea.d.ts +5 -1
- package/dist/types/stories/molecules/inputs/toggleSwitch/ToggleSwitch.d.ts +10 -7
- package/dist/types/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.d.ts +5 -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/ButtonDropdown/ButtonDropdown.d.ts +1 -0
- package/dist/types/stories/organisms/DropdownComponent/DropdownComponent.d.ts +24 -13
- 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/index.d.ts +4 -3
- package/local.sh +100 -0
- package/package.json +36 -19
- package/rollup.config.mjs +42 -0
- package/stories/atoms/badges/Badge.tsx +1 -1
- package/stories/atoms/buttons/Button/Alternative/Alternative.stories.ts +10 -0
- package/stories/atoms/buttons/Button/Button.tsx +111 -25
- package/stories/atoms/buttons/Button/Danger/Danger.stories.ts +14 -2
- package/stories/atoms/buttons/Button/Primary/Primary.stories.ts +14 -2
- package/stories/atoms/buttons/Button/Secondary/Secondary.stories.ts +13 -1
- package/stories/atoms/buttons/Button/defaultArgs.ts +1 -1
- package/stories/atoms/buttons/Capsule/Capsule.tsx +2 -1
- package/stories/atoms/icons/DynamicIcon.stories.ts +1 -1
- package/stories/atoms/icons/DynamicIcon.tsx +7 -7
- package/stories/atoms/icons/IconWithShadow.stories.ts +3 -3
- package/stories/atoms/icons/TablerIcon.tsx +1 -1
- package/stories/atoms/loaders/Loader.tsx +12 -6
- package/stories/atoms/loaders/NProgress/RadialProgress.tsx +0 -2
- package/stories/index.ts +8 -4
- package/stories/molecules/inputs/InputCounter/InputCounter.tsx +2 -2
- package/stories/molecules/inputs/InputField/InputField.tsx +31 -29
- package/stories/molecules/inputs/InputLabel/InputLabel.tsx +1 -1
- package/stories/molecules/inputs/TextInput/TextInput.tsx +12 -6
- package/stories/molecules/inputs/checkbox/Checkbox.stories.ts +1 -1
- package/stories/molecules/inputs/checkbox/Checkbox.tsx +1 -2
- package/stories/molecules/inputs/combobox/ComboBox.tsx +126 -135
- package/stories/molecules/inputs/radio/Radio.stories.ts +2 -2
- package/stories/molecules/inputs/select/Select.tsx +10 -2
- package/stories/molecules/inputs/textArea/TextArea.stories.ts +1 -1
- package/stories/molecules/inputs/textArea/TextArea.tsx +57 -27
- package/stories/molecules/inputs/toggleSwitch/ToggleSwitch.stories.tsx +15 -16
- package/stories/molecules/inputs/toggleSwitch/ToggleSwitch.tsx +63 -57
- package/stories/molecules/tabs/index.tsx +2 -3
- package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.stories.tsx +10 -1
- package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.tsx +53 -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 -59
- package/stories/organisms/ButtonDropdown/ButtonDropdown.tsx +42 -30
- package/stories/organisms/DropdownComponent/Dropdown.stories.tsx +26 -2
- package/stories/organisms/DropdownComponent/DropdownComponent.tsx +232 -180
- package/stories/organisms/DropdownComponent/dropdownItems.ts +30 -9
- package/stories/organisms/DropdownComponent/index.ts +2 -2
- package/stories/organisms/EmptySectionPlaceholder/EmptySectionPlaceholder.stories.tsx +3 -3
- package/stories/organisms/EmptySectionPlaceholder/index.tsx +2 -1
- package/stories/organisms/FormInputWithAddons/FormInputWithAddons.stories.tsx +1 -1
- package/stories/organisms/FormInputWithAddons/FormInputWithAddons.tsx +7 -2
- package/stories/organisms/index.ts +12 -3
- package/tailwind.config.js +81 -37
- package/tsconfig.lib.json +13 -6
- package/watch.js +49 -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
|
@@ -53,13 +53,12 @@ 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
|
)
|
|
60
60
|
|
|
61
61
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
62
|
-
console.log(e)
|
|
63
62
|
const targetValue = e.target.value
|
|
64
63
|
const targetChecked = e.target.checked
|
|
65
64
|
typeof onChange === "function" && onChange(targetValue, targetChecked)
|
|
@@ -44,151 +44,142 @@ function classNames(...classes: string[]) {
|
|
|
44
44
|
return classes.filter(Boolean).join(" ")
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
const Combobox = <T extends Record<string, unknown>>({
|
|
48
|
+
label,
|
|
49
|
+
items,
|
|
50
|
+
displayProperty,
|
|
51
|
+
displayValue,
|
|
52
|
+
keyProperty,
|
|
53
|
+
onChange,
|
|
54
|
+
placeholder,
|
|
55
|
+
message,
|
|
56
|
+
isDisabled,
|
|
57
|
+
isError,
|
|
58
|
+
isRequired,
|
|
59
|
+
id,
|
|
60
|
+
nullable
|
|
61
|
+
}: IComboboxProps<T>) => {
|
|
62
|
+
const [query, setQuery] = useState<string>("")
|
|
63
|
+
const [selectedItem, setSelectedItem] = useState<T | undefined>()
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
65
|
+
const onChangeValue = (value: T | undefined) => {
|
|
66
|
+
if (value && selectedItem && value[keyProperty] === selectedItem[keyProperty]) {
|
|
67
|
+
setSelectedItem(undefined)
|
|
68
|
+
} else {
|
|
69
|
+
setSelectedItem(value)
|
|
71
70
|
}
|
|
71
|
+
}
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (displayValue) {
|
|
75
|
+
const dv = items.find((i) => i[displayProperty] === displayValue)
|
|
76
|
+
setSelectedItem(dv)
|
|
77
|
+
}
|
|
78
|
+
}, [displayValue])
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
typeof onChange === "function" && onChange(selectedItem)
|
|
82
|
+
}, [selectedItem])
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
84
|
+
const filteredItems =
|
|
85
|
+
query === ""
|
|
86
|
+
? items
|
|
87
|
+
: items.filter((item) => {
|
|
88
|
+
return `${item[displayProperty]}`.toLowerCase().includes(query.toLowerCase())
|
|
89
|
+
})
|
|
90
|
+
const labelStyles = cn("block text-sm font-medium text-gray-700")
|
|
91
|
+
const buttonStyles = cn("absolute inset-y-0 right-0 flex items-center rounded-r px-2 focus:outline-none")
|
|
92
|
+
const optionStyles = cn(
|
|
93
|
+
"absolute z-30 mt-1 max-h-60 w-full overflow-auto rounded bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
|
|
94
|
+
)
|
|
95
|
+
return (
|
|
96
|
+
<HeadlessUICombobox
|
|
97
|
+
as="div"
|
|
98
|
+
value={selectedItem}
|
|
99
|
+
onChange={(e: T | undefined) => onChangeValue(e)}
|
|
100
|
+
disabled={isDisabled}
|
|
101
|
+
nullable={nullable ? undefined : false}
|
|
102
|
+
>
|
|
103
|
+
{label && (
|
|
104
|
+
<HeadlessUICombobox.Label className={labelStyles}>
|
|
105
|
+
<InputLabel
|
|
106
|
+
isPlaceholder
|
|
107
|
+
isActive
|
|
108
|
+
label={label}
|
|
109
|
+
isRequired={isRequired}
|
|
110
|
+
id={id}
|
|
111
|
+
isError={isError}
|
|
112
|
+
isDisabled={isDisabled}
|
|
113
|
+
/>
|
|
114
|
+
</HeadlessUICombobox.Label>
|
|
115
|
+
)}
|
|
116
|
+
<div className="relative">
|
|
116
117
|
<div className="relative">
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
<HeadlessUICombobox.Input
|
|
119
|
+
className={`w-full rounded border border-gray-300 focus:border-purple-500 focus:outline-none focus:ring-1 focus:ring-purple-500 sm:text-sm ${
|
|
120
|
+
isError ? "border-red-500" : ""
|
|
121
|
+
}`}
|
|
122
|
+
onChange={(event) => setQuery(event.target.value)}
|
|
123
|
+
displayValue={(item: Record<string, unknown>) => `${item ? item[displayProperty] : ""}`}
|
|
124
|
+
placeholder={placeholder}
|
|
125
|
+
/>
|
|
126
|
+
{selectedItem && nullable && (
|
|
127
|
+
<button
|
|
128
|
+
className="absolute right-8 top-[1px] h-9 w-5 text-gray-400 hover:text-gray-500"
|
|
129
|
+
onClick={() => setSelectedItem(undefined)}
|
|
130
|
+
>
|
|
131
|
+
<DynamicIcon icon="IconX" className="h-4 w-4 " aria-hidden="true" />
|
|
132
|
+
</button>
|
|
133
|
+
)}
|
|
134
|
+
</div>
|
|
135
|
+
<HeadlessUICombobox.Button className={buttonStyles}>
|
|
136
|
+
<DynamicIcon icon="IconSelector" className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
|
137
|
+
</HeadlessUICombobox.Button>
|
|
138
|
+
|
|
139
|
+
{filteredItems.length > 0 && (
|
|
140
|
+
<HeadlessUICombobox.Options className={optionStyles}>
|
|
141
|
+
{filteredItems.map((item, index) => (
|
|
142
|
+
<HeadlessUICombobox.Option
|
|
143
|
+
key={`${item[keyProperty]}-${index}`}
|
|
144
|
+
value={item}
|
|
145
|
+
className={({ active }) =>
|
|
146
|
+
classNames(
|
|
147
|
+
"relative cursor-default select-none py-2 pl-3 pr-9",
|
|
148
|
+
active ? "bg-purple-600 text-white" : "text-gray-900"
|
|
149
|
+
)
|
|
150
|
+
}
|
|
130
151
|
>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
<DynamicIcon icon="SelectorIcon" className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
|
137
|
-
</HeadlessUICombobox.Button>
|
|
152
|
+
{({ active, selected }) => (
|
|
153
|
+
<>
|
|
154
|
+
<span className={classNames("block truncate", selected ? "font-semibold" : "")}>
|
|
155
|
+
{`${item[displayProperty]}`}
|
|
156
|
+
</span>
|
|
138
157
|
|
|
139
|
-
|
|
140
|
-
<HeadlessUICombobox.Options className={optionStyles}>
|
|
141
|
-
{filteredItems.map((item, index) => (
|
|
142
|
-
<HeadlessUICombobox.Option
|
|
143
|
-
key={`${item[keyProperty]}-${index}`}
|
|
144
|
-
value={item}
|
|
145
|
-
className={({ active }) =>
|
|
146
|
-
classNames(
|
|
147
|
-
"relative cursor-default select-none py-2 pl-3 pr-9",
|
|
148
|
-
active ? "bg-purple-600 text-white" : "text-gray-900"
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
>
|
|
152
|
-
{({ active, selected }) => (
|
|
153
|
-
<>
|
|
158
|
+
{selected && (
|
|
154
159
|
<span
|
|
155
160
|
className={classNames(
|
|
156
|
-
"
|
|
157
|
-
|
|
161
|
+
"absolute inset-y-0 right-0 flex items-center pr-4",
|
|
162
|
+
active ? "text-white" : "text-purple-600"
|
|
158
163
|
)}
|
|
159
164
|
>
|
|
160
|
-
|
|
165
|
+
<DynamicIcon icon="IconCheck" className="h-5 w-5" aria-hidden="true" />
|
|
161
166
|
</span>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
</HeadlessUICombobox.Options>
|
|
182
|
-
)}
|
|
183
|
-
</div>
|
|
184
|
-
<div className="grow">
|
|
185
|
-
{message && (
|
|
186
|
-
<span className={`mt-1 block text-sm ${isError ? `text-red-500` : `text-gray-500`}`}>
|
|
187
|
-
{message}
|
|
188
|
-
</span>
|
|
189
|
-
)}
|
|
190
|
-
</div>
|
|
191
|
-
</HeadlessUICombobox>
|
|
192
|
-
)
|
|
193
|
-
}
|
|
194
|
-
export default Combobox
|
|
167
|
+
)}
|
|
168
|
+
</>
|
|
169
|
+
)}
|
|
170
|
+
</HeadlessUICombobox.Option>
|
|
171
|
+
))}
|
|
172
|
+
</HeadlessUICombobox.Options>
|
|
173
|
+
)}
|
|
174
|
+
</div>
|
|
175
|
+
<div className="grow">
|
|
176
|
+
{message && (
|
|
177
|
+
<span className={`mt-1 block text-sm ${isError ? `text-red-500` : `text-gray-500`}`}>
|
|
178
|
+
{message}
|
|
179
|
+
</span>
|
|
180
|
+
)}
|
|
181
|
+
</div>
|
|
182
|
+
</HeadlessUICombobox>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
export default Combobox
|
|
@@ -17,10 +17,10 @@ export const DefaultRadio: Story = {
|
|
|
17
17
|
message: "",
|
|
18
18
|
name: "radio-group",
|
|
19
19
|
onChange: (value: string, checked: boolean) => {
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
},
|
|
22
22
|
onClick: (value: string, checked: boolean) => {
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -3,7 +3,7 @@ import InputLabel from "@/stories/molecules/inputs/InputLabel"
|
|
|
3
3
|
import { useId } from "@/utils/useId"
|
|
4
4
|
import { default as cn } from "classnames"
|
|
5
5
|
|
|
6
|
-
export
|
|
6
|
+
export interface ISimpleSelectOptions {
|
|
7
7
|
label: string
|
|
8
8
|
value: string
|
|
9
9
|
}
|
|
@@ -28,6 +28,10 @@ export interface ISelectProps {
|
|
|
28
28
|
value?: string
|
|
29
29
|
|
|
30
30
|
className?: string
|
|
31
|
+
|
|
32
|
+
onFocus?: () => void
|
|
33
|
+
|
|
34
|
+
onBlur?: () => void
|
|
31
35
|
}
|
|
32
36
|
const Select: React.FC<ISelectProps> = ({
|
|
33
37
|
label,
|
|
@@ -39,7 +43,9 @@ const Select: React.FC<ISelectProps> = ({
|
|
|
39
43
|
isError,
|
|
40
44
|
isRequired,
|
|
41
45
|
value,
|
|
42
|
-
className
|
|
46
|
+
className,
|
|
47
|
+
onFocus,
|
|
48
|
+
onBlur
|
|
43
49
|
}) => {
|
|
44
50
|
const [selectedOption, setSelectedOption] = useState<string>(value || options[0].value)
|
|
45
51
|
const uniqueID = useId()
|
|
@@ -84,6 +90,8 @@ const Select: React.FC<ISelectProps> = ({
|
|
|
84
90
|
onChange={handleChange}
|
|
85
91
|
disabled={isDisabled}
|
|
86
92
|
value={selectedOption}
|
|
93
|
+
onFocus={onFocus}
|
|
94
|
+
onBlur={onBlur}
|
|
87
95
|
>
|
|
88
96
|
{options.map(({ value, label }) => {
|
|
89
97
|
return (
|
|
@@ -2,13 +2,19 @@ import React, { forwardRef, useEffect, useId, useState } from "react"
|
|
|
2
2
|
import { default as cn } from "classnames"
|
|
3
3
|
import InputLabel from "../InputLabel"
|
|
4
4
|
import InputCounter from "../InputCounter"
|
|
5
|
+
|
|
6
|
+
interface ILabelProps extends React.DetailedHTMLProps<React.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement> {
|
|
7
|
+
display: string
|
|
8
|
+
htmlFor?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
export interface ITextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> {
|
|
6
12
|
/** Input ID */
|
|
7
13
|
id?: string
|
|
8
14
|
/** Input Name */
|
|
9
15
|
name?: string
|
|
10
16
|
/** Label for the input */
|
|
11
|
-
label?:
|
|
17
|
+
label?: ILabelProps
|
|
12
18
|
/** Error state */
|
|
13
19
|
isError?: boolean
|
|
14
20
|
/** If field is required */
|
|
@@ -51,49 +57,73 @@ const Textarea: React.FC<ITextareaProps> = ({
|
|
|
51
57
|
rows = 12,
|
|
52
58
|
cols = 48,
|
|
53
59
|
onChange,
|
|
54
|
-
value
|
|
60
|
+
value,
|
|
55
61
|
placeholder,
|
|
56
62
|
className,
|
|
57
63
|
ref,
|
|
58
64
|
...rest
|
|
59
65
|
}) => {
|
|
60
66
|
const uniqueID = useId()
|
|
61
|
-
const [value, setValue] = useState<string | undefined>(externalValue || defaultValue || "")
|
|
62
|
-
const handleOnchange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
63
|
-
const targetValue = e.currentTarget.value
|
|
64
|
-
typeof onChange === "function" && onChange(targetValue)
|
|
65
|
-
setValue(targetValue)
|
|
66
|
-
}
|
|
67
67
|
|
|
68
68
|
const discriptionStyles = cn("text-sm mt-1 block", { "text-gray-500": !isError }, { "text-red-500": isError })
|
|
69
69
|
|
|
70
|
-
useEffect(() => {
|
|
71
|
-
//if the external value is updated by the parent component, reset the value in here...
|
|
72
|
-
if (externalValue !== undefined && externalValue !== null) {
|
|
73
|
-
setValue(externalValue)
|
|
74
|
-
}
|
|
75
|
-
}, [externalValue])
|
|
76
|
-
|
|
77
70
|
if (!id) id = `ta-${uniqueID}`
|
|
78
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
|
+
},
|
|
93
|
+
className
|
|
94
|
+
)}
|
|
95
|
+
disabled={isDisabled}
|
|
96
|
+
defaultValue={defaultValue}
|
|
97
|
+
value={value}
|
|
98
|
+
placeholder={placeholder}
|
|
99
|
+
{...rest}
|
|
100
|
+
/>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//with label
|
|
79
105
|
return (
|
|
80
106
|
<div>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
)}
|
|
107
|
+
<InputLabel
|
|
108
|
+
isPlaceholder
|
|
109
|
+
isActive
|
|
110
|
+
label={label.display}
|
|
111
|
+
isRequired={isRequired}
|
|
112
|
+
id={id}
|
|
113
|
+
isError={isError}
|
|
114
|
+
isDisabled={isDisabled}
|
|
115
|
+
/>
|
|
116
|
+
|
|
92
117
|
<div>
|
|
93
118
|
<textarea
|
|
94
119
|
ref={ref}
|
|
95
120
|
maxLength={maxLength}
|
|
96
|
-
onChange={
|
|
121
|
+
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
122
|
+
const targetValue = e.target.value
|
|
123
|
+
if (onChange) {
|
|
124
|
+
onChange(targetValue)
|
|
125
|
+
}
|
|
126
|
+
}}
|
|
97
127
|
rows={rows}
|
|
98
128
|
name={name}
|
|
99
129
|
id={id}
|
|
@@ -13,7 +13,7 @@ export const DefaultToggleSwitch: Story = {
|
|
|
13
13
|
args: {
|
|
14
14
|
isChecked: false,
|
|
15
15
|
onChange: (v: boolean) => {
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
},
|
|
18
18
|
label: {
|
|
19
19
|
text: "label me",
|
|
@@ -53,21 +53,20 @@ export const Checked: Story = {
|
|
|
53
53
|
},
|
|
54
54
|
}
|
|
55
55
|
export const WithIcon: Story = {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
56
|
+
args: {
|
|
57
|
+
...DefaultToggleSwitch.args,
|
|
58
|
+
label: {
|
|
59
|
+
text: "label me three",
|
|
60
|
+
className: "text-lg text-gray-400",
|
|
61
|
+
xPosition: "left"
|
|
62
|
+
},
|
|
63
|
+
withIcon: {
|
|
64
|
+
icon: "IconCheck"
|
|
65
|
+
},
|
|
66
|
+
variant: "base",
|
|
67
|
+
id: "toggle-switch-4",
|
|
68
|
+
name: "toggle four"
|
|
69
|
+
}
|
|
71
70
|
}
|
|
72
71
|
export const NoLabel: Story = {
|
|
73
72
|
args: {
|
|
@@ -2,74 +2,80 @@ import React, { useEffect, useState } from "react"
|
|
|
2
2
|
import { default as cn } from "classnames"
|
|
3
3
|
import { Switch } from "@headlessui/react"
|
|
4
4
|
import { DynamicIcon, IDynamicIconProps } from "@/stories/atoms"
|
|
5
|
+
|
|
6
|
+
interface ToggleSwitchLabel {
|
|
7
|
+
text: string | JSX.Element
|
|
8
|
+
className?: string
|
|
9
|
+
xPosition?: "left" | "right"
|
|
10
|
+
}
|
|
11
|
+
|
|
5
12
|
export interface IToggleSwitchProps {
|
|
6
13
|
isChecked: boolean
|
|
7
14
|
onChange: (isChecked: boolean) => void
|
|
8
|
-
label?:
|
|
9
|
-
|
|
10
|
-
className?: string
|
|
11
|
-
xPosition?: "left" | "right"
|
|
12
|
-
}
|
|
13
|
-
screenReaderLabel: string
|
|
15
|
+
label?: ToggleSwitchLabel
|
|
16
|
+
screenReaderLabel?: string
|
|
14
17
|
name: string
|
|
15
18
|
id: string
|
|
16
|
-
variant
|
|
19
|
+
variant?: "base" | "short"
|
|
17
20
|
withIcon?: IDynamicIconProps
|
|
21
|
+
disabled?: boolean,
|
|
22
|
+
groupClassName?: string
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
const ToggleSwitch: React.FC<IToggleSwitchProps> = ({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
isChecked,
|
|
27
|
+
onChange,
|
|
28
|
+
label,
|
|
29
|
+
screenReaderLabel,
|
|
30
|
+
name,
|
|
31
|
+
id,
|
|
32
|
+
variant = "base",
|
|
33
|
+
withIcon,
|
|
34
|
+
disabled,
|
|
35
|
+
groupClassName,
|
|
29
36
|
}) => {
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
const [checked, setChecked] = useState<boolean>(isChecked)
|
|
38
|
+
useEffect(() => setChecked(isChecked), [isChecked])
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
)
|
|
40
|
+
return (
|
|
41
|
+
<Switch.Group as={"div"} className={cn("flex items-center gap-2", groupClassName)}>
|
|
42
|
+
{label && (label.xPosition === "left" || !label?.xPosition) && (
|
|
43
|
+
<Switch.Label className={label.className}>{label.text}</Switch.Label>
|
|
44
|
+
)}
|
|
45
|
+
<Switch
|
|
46
|
+
name={name}
|
|
47
|
+
id={id}
|
|
48
|
+
checked={checked}
|
|
49
|
+
onChange={(v: boolean) => {
|
|
50
|
+
onChange(v)
|
|
51
|
+
setChecked(v)
|
|
52
|
+
}}
|
|
53
|
+
className={cn(
|
|
54
|
+
{ "w-9 h-4 transition-all": variant === "short", " h-6 w-11": variant === "base" },
|
|
55
|
+
checked && disabled ? "bg-purple-200" : checked ? "bg-purple-600" : "bg-gray-200",
|
|
56
|
+
"relative inline-flex items-center rounded-full focus-visible:ring-2 focus-visible:ring-purple-600 focus-visible:ring-offset-2 focus-within:ring-2 focus-within:ring-purple-600 focus-within:ring-offset-2 focus:ring-2 focus:ring-purple-600 focus:ring-offset-2 active:ring-2 active:ring-purple-600 active:ring-offset-2"
|
|
57
|
+
)}
|
|
58
|
+
disabled={disabled}
|
|
59
|
+
>
|
|
60
|
+
{screenReaderLabel && <span className="sr-only">{screenReaderLabel}</span>}
|
|
61
|
+
<span
|
|
62
|
+
className={cn(
|
|
63
|
+
checked ? "translate-x-[22px]" : "translate-x-[2px]",
|
|
64
|
+
{
|
|
65
|
+
"border border-gray-200 translate-x-0": variant === "short",
|
|
66
|
+
"!translate-x-[22px]": checked && variant === "short"
|
|
67
|
+
},
|
|
68
|
+
" h-5 w-5 transform rounded-full bg-white transition shadow-sm drop-shadow flex items-center justify-center"
|
|
69
|
+
)}
|
|
70
|
+
>
|
|
71
|
+
{withIcon && <DynamicIcon {...withIcon} className={"text-gray-400 m-[2px]"} />}
|
|
72
|
+
</span>
|
|
73
|
+
</Switch>
|
|
74
|
+
{label && label.xPosition === "right" && (
|
|
75
|
+
<Switch.Label className={label.className}>{label.text}</Switch.Label>
|
|
76
|
+
)}
|
|
77
|
+
</Switch.Group>
|
|
78
|
+
)
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
export default ToggleSwitch
|