@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.
Files changed (91) hide show
  1. package/README.md +104 -31
  2. package/build.js +30 -25
  3. package/dist/index.d.ts +101 -61
  4. package/dist/index.js +1 -6295
  5. package/dist/index.js.map +4 -4
  6. package/dist/{lib/tailwind.css → tailwind.css} +3729 -8120
  7. package/dist/types/stories/atoms/buttons/Button/Alternative/Alternative.stories.d.ts +1 -0
  8. package/dist/types/stories/atoms/buttons/Button/Button.d.ts +3 -7
  9. package/dist/types/stories/atoms/buttons/Button/Danger/Danger.stories.d.ts +1 -0
  10. package/dist/types/stories/atoms/buttons/Button/Primary/Primary.stories.d.ts +1 -0
  11. package/dist/types/stories/atoms/buttons/Button/Secondary/Secondary.stories.d.ts +1 -0
  12. package/dist/types/stories/atoms/buttons/Capsule/Capsule.d.ts +1 -1
  13. package/dist/types/stories/atoms/icons/DynamicIcon.d.ts +2 -2
  14. package/dist/types/stories/atoms/icons/TablerIcon.d.ts +1 -1
  15. package/dist/types/stories/index.d.ts +4 -4
  16. package/dist/types/stories/molecules/inputs/InputField/InputField.d.ts +7 -7
  17. package/dist/types/stories/molecules/inputs/TextInput/TextInput.d.ts +1 -1
  18. package/dist/types/stories/molecules/inputs/select/Select.d.ts +4 -2
  19. package/dist/types/stories/molecules/inputs/textArea/TextArea.d.ts +5 -1
  20. package/dist/types/stories/molecules/inputs/toggleSwitch/ToggleSwitch.d.ts +10 -7
  21. package/dist/types/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.d.ts +5 -5
  22. package/dist/types/stories/organisms/AnimatedLabelInput/index.d.ts +1 -1
  23. package/dist/types/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.d.ts +12 -0
  24. package/dist/types/stories/organisms/AnimatedLabelTextArea/index.d.ts +3 -0
  25. package/dist/types/stories/organisms/ButtonDropdown/ButtonDropdown.d.ts +1 -0
  26. package/dist/types/stories/organisms/DropdownComponent/DropdownComponent.d.ts +24 -13
  27. package/dist/types/stories/organisms/DropdownComponent/index.d.ts +2 -2
  28. package/dist/types/stories/organisms/EmptySectionPlaceholder/index.d.ts +1 -1
  29. package/dist/types/stories/organisms/index.d.ts +4 -3
  30. package/local.sh +100 -0
  31. package/package.json +36 -19
  32. package/rollup.config.mjs +42 -0
  33. package/stories/atoms/badges/Badge.tsx +1 -1
  34. package/stories/atoms/buttons/Button/Alternative/Alternative.stories.ts +10 -0
  35. package/stories/atoms/buttons/Button/Button.tsx +111 -25
  36. package/stories/atoms/buttons/Button/Danger/Danger.stories.ts +14 -2
  37. package/stories/atoms/buttons/Button/Primary/Primary.stories.ts +14 -2
  38. package/stories/atoms/buttons/Button/Secondary/Secondary.stories.ts +13 -1
  39. package/stories/atoms/buttons/Button/defaultArgs.ts +1 -1
  40. package/stories/atoms/buttons/Capsule/Capsule.tsx +2 -1
  41. package/stories/atoms/icons/DynamicIcon.stories.ts +1 -1
  42. package/stories/atoms/icons/DynamicIcon.tsx +7 -7
  43. package/stories/atoms/icons/IconWithShadow.stories.ts +3 -3
  44. package/stories/atoms/icons/TablerIcon.tsx +1 -1
  45. package/stories/atoms/loaders/Loader.tsx +12 -6
  46. package/stories/atoms/loaders/NProgress/RadialProgress.tsx +0 -2
  47. package/stories/index.ts +8 -4
  48. package/stories/molecules/inputs/InputCounter/InputCounter.tsx +2 -2
  49. package/stories/molecules/inputs/InputField/InputField.tsx +31 -29
  50. package/stories/molecules/inputs/InputLabel/InputLabel.tsx +1 -1
  51. package/stories/molecules/inputs/TextInput/TextInput.tsx +12 -6
  52. package/stories/molecules/inputs/checkbox/Checkbox.stories.ts +1 -1
  53. package/stories/molecules/inputs/checkbox/Checkbox.tsx +1 -2
  54. package/stories/molecules/inputs/combobox/ComboBox.tsx +126 -135
  55. package/stories/molecules/inputs/radio/Radio.stories.ts +2 -2
  56. package/stories/molecules/inputs/select/Select.tsx +10 -2
  57. package/stories/molecules/inputs/textArea/TextArea.stories.ts +1 -1
  58. package/stories/molecules/inputs/textArea/TextArea.tsx +57 -27
  59. package/stories/molecules/inputs/toggleSwitch/ToggleSwitch.stories.tsx +15 -16
  60. package/stories/molecules/inputs/toggleSwitch/ToggleSwitch.tsx +63 -57
  61. package/stories/molecules/tabs/index.tsx +2 -3
  62. package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.stories.tsx +10 -1
  63. package/stories/organisms/AnimatedLabelInput/AnimatedLabelInput.tsx +53 -37
  64. package/stories/organisms/AnimatedLabelInput/index.tsx +1 -1
  65. package/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.stories.tsx +26 -0
  66. package/stories/organisms/AnimatedLabelTextArea/AnimatedLabelTextArea.tsx +61 -0
  67. package/stories/organisms/AnimatedLabelTextArea/index.tsx +3 -0
  68. package/stories/organisms/ButtonDropdown/ButtonDropdown.stories.tsx +59 -59
  69. package/stories/organisms/ButtonDropdown/ButtonDropdown.tsx +42 -30
  70. package/stories/organisms/DropdownComponent/Dropdown.stories.tsx +26 -2
  71. package/stories/organisms/DropdownComponent/DropdownComponent.tsx +232 -180
  72. package/stories/organisms/DropdownComponent/dropdownItems.ts +30 -9
  73. package/stories/organisms/DropdownComponent/index.ts +2 -2
  74. package/stories/organisms/EmptySectionPlaceholder/EmptySectionPlaceholder.stories.tsx +3 -3
  75. package/stories/organisms/EmptySectionPlaceholder/index.tsx +2 -1
  76. package/stories/organisms/FormInputWithAddons/FormInputWithAddons.stories.tsx +1 -1
  77. package/stories/organisms/FormInputWithAddons/FormInputWithAddons.tsx +7 -2
  78. package/stories/organisms/index.ts +12 -3
  79. package/tailwind.config.js +81 -37
  80. package/tsconfig.lib.json +13 -6
  81. package/watch.js +49 -0
  82. package/.yarnrc.yml +0 -1
  83. package/dist/types/stories/layouts/index.d.ts +0 -0
  84. package/stories/layouts/CardLayout/CardLayout.stories.tsx +0 -18
  85. package/stories/layouts/CardLayout/CardLayout.tsx +0 -22
  86. package/stories/layouts/CardLayout/index.tsx +0 -3
  87. package/stories/layouts/ModalLayout/ModalLayout.stories.tsx +0 -18
  88. package/stories/layouts/ModalLayout/ModalLayout.tsx +0 -22
  89. package/stories/layouts/ModalLayout/index.tsx +0 -3
  90. package/stories/layouts/index.ts +0 -0
  91. package/stories/organisms/DropdownComponent/Dropdown.test.tsx +0 -0
@@ -16,7 +16,7 @@ export const DefaultCheckbox: Story = {
16
16
  isError: false,
17
17
  message: "",
18
18
  onChange: (value: string) => {
19
- console.log(`onChange ${value}`)
19
+
20
20
  }
21
21
  }
22
22
  }
@@ -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 ring-1 px-3 ring-gray-300": hasBorder },
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
- 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>()
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
- const onChangeValue = (value: T | undefined) => {
66
- if (value && selectedItem && value[keyProperty] === selectedItem[keyProperty]) {
67
- setSelectedItem(undefined)
68
- } else {
69
- setSelectedItem(value)
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
- useEffect(() => {
74
- if (displayValue) {
75
- const dv = items.find((i) => i[displayProperty] === displayValue)
76
- setSelectedItem(dv)
77
- }
78
- }, [displayValue])
73
+ useEffect(() => {
74
+ if (displayValue) {
75
+ const dv = items.find((i) => i[displayProperty] === displayValue)
76
+ setSelectedItem(dv)
77
+ }
78
+ }, [displayValue])
79
79
 
80
- useEffect(() => {
81
- typeof onChange === "function" && onChange(selectedItem)
82
- }, [selectedItem])
80
+ useEffect(() => {
81
+ typeof onChange === "function" && onChange(selectedItem)
82
+ }, [selectedItem])
83
83
 
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
- )}
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
- <div className="relative">
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)}
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
- <DynamicIcon icon="XIcon" className="h-4 w-4 " aria-hidden="true" />
132
- </button>
133
- )}
134
- </div>
135
- <HeadlessUICombobox.Button className={buttonStyles}>
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
- {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
- }
151
- >
152
- {({ active, selected }) => (
153
- <>
158
+ {selected && (
154
159
  <span
155
160
  className={classNames(
156
- "block truncate",
157
- selected ? "font-semibold" : ""
161
+ "absolute inset-y-0 right-0 flex items-center pr-4",
162
+ active ? "text-white" : "text-purple-600"
158
163
  )}
159
164
  >
160
- {`${item[displayProperty]}`}
165
+ <DynamicIcon icon="IconCheck" className="h-5 w-5" aria-hidden="true" />
161
166
  </span>
162
-
163
- {selected && (
164
- <span
165
- className={classNames(
166
- "absolute inset-y-0 right-0 flex items-center pr-4",
167
- active ? "text-white" : "text-purple-600"
168
- )}
169
- >
170
- <DynamicIcon
171
- icon="CheckIcon"
172
- className="h-5 w-5"
173
- aria-hidden="true"
174
- />
175
- </span>
176
- )}
177
- </>
178
- )}
179
- </HeadlessUICombobox.Option>
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
- console.log(`onChange ${value} ${checked}`)
20
+
21
21
  },
22
22
  onClick: (value: string, checked: boolean) => {
23
- console.log(`onClick ${value} ${checked}`)
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 type ISimpleSelectOptions = {
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 (
@@ -15,7 +15,7 @@ export const DefaultTextarea: Story = {
15
15
  name: "description",
16
16
  rows: 12,
17
17
  cols: 18,
18
- label: "Description",
18
+ label: { display: "Description" },
19
19
  placeholder: dummyText
20
20
  }
21
21
  }
@@ -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?: string
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: externalValue,
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
- {label && (
82
- <InputLabel
83
- isPlaceholder
84
- isActive
85
- label={label}
86
- isRequired={isRequired}
87
- id={id}
88
- isError={isError}
89
- isDisabled={isDisabled}
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={handleOnchange}
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
- console.log(v, "v")
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
- 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
- name: "IconCheck",
65
- type: "solid",
66
- },
67
- variant: "base",
68
- id: "toggle-switch-4",
69
- name: "toggle four",
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
- text: string | JSX.Element
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: "base" | "short"
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
- isChecked,
22
- onChange,
23
- label,
24
- screenReaderLabel,
25
- name,
26
- id,
27
- variant = "base",
28
- withIcon,
26
+ isChecked,
27
+ onChange,
28
+ label,
29
+ screenReaderLabel,
30
+ name,
31
+ id,
32
+ variant = "base",
33
+ withIcon,
34
+ disabled,
35
+ groupClassName,
29
36
  }) => {
30
- const [checked, setChecked] = useState<boolean>(isChecked)
31
- useEffect(() => setChecked(isChecked), [isChecked])
37
+ const [checked, setChecked] = useState<boolean>(isChecked)
38
+ useEffect(() => setChecked(isChecked), [isChecked])
32
39
 
33
- return (
34
- <Switch.Group as={"div"} className={"flex items-center gap-2"}>
35
- {label && label.xPosition === "left" && (
36
- <Switch.Label className={label.className}>{label.text}</Switch.Label>
37
- )}
38
- <Switch
39
- name={name}
40
- id={id}
41
- checked={checked}
42
- onChange={(v: boolean) => {
43
- onChange(v)
44
- setChecked(v)
45
- }}
46
- className={cn(
47
- { "w-9 h-4": variant === "short", " h-6 w-11": variant === "base" },
48
- checked ? "bg-purple-600" : "bg-gray-200",
49
- "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"
50
- )}
51
- >
52
- <span className="sr-only">{screenReaderLabel}</span>
53
- <span
54
- className={cn(
55
- checked ? "translate-x-[22px]" : "translate-x-[2px]",
56
- {
57
- "border border-gray-200 translate-x-0": variant === "short",
58
- "!translate-x-[22px]": checked && variant === "short",
59
- },
60
- " h-5 w-5 transform rounded-full bg-white transition shadow-sm drop-shadow flex items-center justify-center"
61
- )}
62
- >
63
- {withIcon && (
64
- <DynamicIcon {...withIcon} className={"text-gray-400 m-[2px]"} />
65
- )}
66
- </span>
67
- </Switch>
68
- {label && label.xPosition === "right" && (
69
- <Switch.Label className={label.className}>{label.text}</Switch.Label>
70
- )}
71
- </Switch.Group>
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