@bronzelabs/oakma-ui 0.0.1 → 0.0.2

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 (123) hide show
  1. package/dist/index.d.ts +345 -0
  2. package/dist/index.js +1 -0
  3. package/dist/oakma-ui.css +2 -0
  4. package/package.json +6 -2
  5. package/.prettierrc.cjs +0 -25
  6. package/.storybook/components/ActionButton.tsx +0 -44
  7. package/.storybook/components/DummyIcons.tsx +0 -47
  8. package/.storybook/components/index.ts +0 -2
  9. package/.storybook/docs/blocks/ImportStatement.tsx +0 -52
  10. package/.storybook/docs/blocks/index.ts +0 -1
  11. package/.storybook/docs/page.tsx +0 -41
  12. package/.storybook/main.ts +0 -21
  13. package/.storybook/postcss.config.cjs +0 -8
  14. package/.storybook/preview-body.html +0 -20
  15. package/.storybook/preview-head.html +0 -6
  16. package/.storybook/preview.tsx +0 -30
  17. package/.storybook/tailwind.css +0 -6
  18. package/.storybook/utils/index.ts +0 -2
  19. package/.storybook/utils/renderAsReact.tsx +0 -30
  20. package/.storybook/utils/renderDocsWithProps.tsx +0 -22
  21. package/@types/markdown.d.ts +0 -4
  22. package/eslint.config.js +0 -91
  23. package/postcss.config.cjs +0 -8
  24. package/scripts/release.sh +0 -76
  25. package/src/components/Button/Button.stories.tsx +0 -314
  26. package/src/components/Button/Button.tsx +0 -132
  27. package/src/components/Button/index.ts +0 -2
  28. package/src/components/Button/types.ts +0 -19
  29. package/src/components/Checkbox/Checkbox.stories.tsx +0 -152
  30. package/src/components/Checkbox/Checkbox.tsx +0 -90
  31. package/src/components/Checkbox/index.ts +0 -2
  32. package/src/components/Checkbox/types.ts +0 -6
  33. package/src/components/Chip/Chip.stories.tsx +0 -146
  34. package/src/components/Chip/Chip.tsx +0 -59
  35. package/src/components/Chip/index.ts +0 -2
  36. package/src/components/Chip/types.ts +0 -6
  37. package/src/components/Drawer/Drawer.docs.md +0 -88
  38. package/src/components/Drawer/Drawer.stories.tsx +0 -239
  39. package/src/components/Drawer/Drawer.tsx +0 -194
  40. package/src/components/Drawer/index.ts +0 -3
  41. package/src/components/Drawer/types.ts +0 -3
  42. package/src/components/Dropdown/AsyncDropdown.tsx +0 -105
  43. package/src/components/Dropdown/Dropdown.docs.md +0 -33
  44. package/src/components/Dropdown/Dropdown.stories.tsx +0 -419
  45. package/src/components/Dropdown/Dropdown.tsx +0 -104
  46. package/src/components/Dropdown/MultiValue.tsx +0 -19
  47. package/src/components/Dropdown/ValueContainer.tsx +0 -114
  48. package/src/components/Dropdown/index.ts +0 -4
  49. package/src/components/Dropdown/types.ts +0 -29
  50. package/src/components/Dropdown/useDropdown.tsx +0 -257
  51. package/src/components/Logo/Logo.stories.tsx +0 -130
  52. package/src/components/Logo/Logo.tsx +0 -80
  53. package/src/components/Logo/index.ts +0 -2
  54. package/src/components/Modal/Modal.docs.md +0 -94
  55. package/src/components/Modal/Modal.stories.tsx +0 -318
  56. package/src/components/Modal/Modal.tsx +0 -217
  57. package/src/components/Modal/index.ts +0 -1
  58. package/src/components/MultiSelect/AsyncMultiSelect.tsx +0 -47
  59. package/src/components/MultiSelect/MultiSelect.docs.md +0 -37
  60. package/src/components/MultiSelect/MultiSelect.stories.tsx +0 -493
  61. package/src/components/MultiSelect/MultiSelect.tsx +0 -81
  62. package/src/components/MultiSelect/index.ts +0 -2
  63. package/src/components/Notification/Notification.stories.tsx +0 -158
  64. package/src/components/Notification/Notification.tsx +0 -110
  65. package/src/components/Notification/index.ts +0 -1
  66. package/src/components/Notification/types.ts +0 -11
  67. package/src/components/Notifications/Notifications.docs.md +0 -103
  68. package/src/components/Notifications/Notifications.stories.tsx +0 -159
  69. package/src/components/Notifications/Notifications.tsx +0 -90
  70. package/src/components/Notifications/NotificationsContext.tsx +0 -90
  71. package/src/components/Notifications/index.ts +0 -7
  72. package/src/components/Select/Select.stories.tsx +0 -234
  73. package/src/components/Select/Select.tsx +0 -129
  74. package/src/components/Select/index.ts +0 -2
  75. package/src/components/Select/types.ts +0 -1
  76. package/src/components/Spinner/Spinner.stories.tsx +0 -55
  77. package/src/components/Spinner/Spinner.tsx +0 -48
  78. package/src/components/Spinner/index.ts +0 -2
  79. package/src/components/Spinner/types.ts +0 -8
  80. package/src/components/TextArea/TextArea.stories.tsx +0 -243
  81. package/src/components/TextArea/TextArea.tsx +0 -133
  82. package/src/components/TextArea/index.ts +0 -2
  83. package/src/components/TextArea/types.ts +0 -4
  84. package/src/components/TextField/Container.tsx +0 -68
  85. package/src/components/TextField/ErrorMessage.tsx +0 -37
  86. package/src/components/TextField/Icon.tsx +0 -77
  87. package/src/components/TextField/Label.tsx +0 -56
  88. package/src/components/TextField/NotchBorder.tsx +0 -67
  89. package/src/components/TextField/index.ts +0 -14
  90. package/src/components/TextField/types.ts +0 -15
  91. package/src/components/TextField/useInputKeyboardFocus.tsx +0 -63
  92. package/src/components/TextInput/TextInput.stories.tsx +0 -384
  93. package/src/components/TextInput/TextInput.tsx +0 -255
  94. package/src/components/TextInput/index.ts +0 -2
  95. package/src/components/TextInput/types.ts +0 -4
  96. package/src/components/Toggle/Toggle.stories.tsx +0 -142
  97. package/src/components/Toggle/Toggle.tsx +0 -69
  98. package/src/components/Toggle/index.ts +0 -1
  99. package/src/hooks/index.ts +0 -6
  100. package/src/hooks/useCombinedRefs.ts +0 -37
  101. package/src/hooks/useEventListener.ts +0 -87
  102. package/src/hooks/useFocusTrap/createAriaHider.ts +0 -62
  103. package/src/hooks/useFocusTrap/index.ts +0 -1
  104. package/src/hooks/useFocusTrap/scopeTab.ts +0 -46
  105. package/src/hooks/useFocusTrap/tabbable.ts +0 -107
  106. package/src/hooks/useFocusTrap/useFocusTrap.ts +0 -97
  107. package/src/hooks/useIsomorphicLayoutEffect.ts +0 -14
  108. package/src/hooks/useLockBodyScroll.ts +0 -24
  109. package/src/hooks/useOnClickOutside.ts +0 -53
  110. package/src/index.ts +0 -22
  111. package/src/tailwind.css +0 -4
  112. package/src/types/helpers.ts +0 -11
  113. package/src/types/polymorphic.ts +0 -39
  114. package/src/utils/animation/variants.ts +0 -21
  115. package/src/utils/array/index.ts +0 -1
  116. package/src/utils/array/uniqBy.ts +0 -12
  117. package/src/utils/common/index.ts +0 -1
  118. package/src/utils/common/isFunction.ts +0 -17
  119. package/src/utils/react/extractDisplayName.ts +0 -15
  120. package/src/utils/react/index.ts +0 -1
  121. package/tsconfig.json +0 -16
  122. package/tsconfig.production.json +0 -19
  123. package/tsup.config.ts +0 -16
@@ -1,318 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import Modal from "./Modal"
5
- import Button from "../Button"
6
- import TextInput from "../TextInput"
7
-
8
- // Types
9
- import type { StoryFn, Meta } from "@storybook/react-webpack5"
10
-
11
- // Utils
12
- import { StorybookActionButton } from "../../../.storybook/components"
13
- import { renderDocsWithProps } from "../../../.storybook/utils"
14
- import extraDocs from "./Modal.docs.md"
15
-
16
- const lorem = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`
17
-
18
- /*
19
-
20
-
21
-
22
-
23
- */
24
-
25
- const meta = {
26
- title: "Components/Modal",
27
- component: Modal,
28
- parameters: {
29
- controls: {
30
- exclude: ["ref", "children"],
31
- },
32
- docs: {
33
- description: {
34
- component: "A component that can be used to display content in a modal.",
35
- },
36
- page: renderDocsWithProps({ extraDocs }),
37
- },
38
- },
39
- argTypes: {
40
- isOpen: {
41
- description: "Controls whether the Modal is visible.",
42
- control: { type: "boolean" },
43
- table: {
44
- type: { summary: "boolean" },
45
- defaultValue: { summary: "false" },
46
- },
47
- },
48
- onClose: {
49
- description:
50
- "Callback fired when the Modal should close (close button, outside click, or Escape key).",
51
- control: false,
52
- table: {
53
- type: { summary: "() => void" },
54
- },
55
- },
56
- withBackdrop: {
57
- description: "Renders a blurred backdrop behind the Modal.",
58
- control: { type: "boolean" },
59
- table: {
60
- type: { summary: "boolean" },
61
- defaultValue: { summary: "true" },
62
- },
63
- },
64
- withCloseButton: {
65
- description: "Renders an X button in the top-right corner of the Modal.",
66
- control: { type: "boolean" },
67
- table: {
68
- type: { summary: "boolean" },
69
- defaultValue: { summary: "true" },
70
- },
71
- },
72
- closeOnClickOutside: {
73
- description: "Calls `onClose` when the user clicks outside the Modal.",
74
- control: { type: "boolean" },
75
- table: {
76
- type: { summary: "boolean" },
77
- defaultValue: { summary: "true" },
78
- },
79
- },
80
- closeOnEscape: {
81
- description: "Calls `onClose` when the user presses the Escape key.",
82
- control: { type: "boolean" },
83
- table: {
84
- type: { summary: "boolean" },
85
- defaultValue: { summary: "true" },
86
- },
87
- },
88
- lockScroll: {
89
- description: "Locks body scroll while the Modal is open.",
90
- control: { type: "boolean" },
91
- table: {
92
- type: { summary: "boolean" },
93
- defaultValue: { summary: "true" },
94
- },
95
- },
96
- trapFocus: {
97
- description: "Traps keyboard focus inside the Modal while it is open.",
98
- control: { type: "boolean" },
99
- table: {
100
- type: { summary: "boolean" },
101
- defaultValue: { summary: "true" },
102
- },
103
- },
104
- portal: {
105
- description:
106
- "DOM element or DocumentFragment to render the Modal portal into. Defaults to `document.body`.",
107
- control: false,
108
- table: {
109
- type: { summary: "Element | DocumentFragment" },
110
- defaultValue: { summary: "document.body" },
111
- },
112
- },
113
- header: {
114
- description: "Replaces the default title/subtitle area with a custom React node.",
115
- control: false,
116
- table: {
117
- type: { summary: "ReactNode" },
118
- defaultValue: { summary: "undefined" },
119
- },
120
- },
121
- footer: {
122
- description: "Renders a sticky footer area at the bottom of the Modal.",
123
- control: false,
124
- table: {
125
- type: { summary: "ReactNode" },
126
- defaultValue: { summary: "undefined" },
127
- },
128
- },
129
- contentClassName: {
130
- description: "Additional CSS class applied to the scrollable content wrapper.",
131
- control: { type: "text" },
132
- table: {
133
- type: { summary: "string" },
134
- defaultValue: { summary: "undefined" },
135
- },
136
- },
137
- title: {
138
- description:
139
- "@deprecated — not currently rendered. Use `header` to display a custom heading.",
140
- control: { type: "text" },
141
- table: {
142
- type: { summary: "string" },
143
- defaultValue: { summary: "undefined" },
144
- category: "Deprecated",
145
- },
146
- },
147
- subTitle: {
148
- description:
149
- "@deprecated — not currently rendered. Use `header` to display a custom subheading.",
150
- control: { type: "text" },
151
- table: {
152
- type: { summary: "string" },
153
- defaultValue: { summary: "undefined" },
154
- category: "Deprecated",
155
- },
156
- },
157
- },
158
- args: {
159
- withBackdrop: true,
160
- withCloseButton: true,
161
- closeOnClickOutside: true,
162
- closeOnEscape: true,
163
- lockScroll: true,
164
- trapFocus: true,
165
- children: <p>{lorem}</p>,
166
- },
167
- decorators: [
168
- (Story, { args: { onClose, ...rest } }) => {
169
- const [isOpen, setIsOpen] = React.useState(false)
170
-
171
- return (
172
- <>
173
- <StorybookActionButton onClick={() => setIsOpen(true)}>Open modal</StorybookActionButton>
174
- {Story({
175
- args: {
176
- isOpen: isOpen,
177
- onClose: () => {
178
- setIsOpen(false)
179
- onClose?.()
180
- },
181
- ...rest,
182
- },
183
- })}
184
- </>
185
- )
186
- },
187
- ],
188
- } satisfies Meta<typeof Modal>
189
-
190
- // Templates
191
- const DummyContent = () => (
192
- <div className="flex flex-col pb-6 text-center">
193
- <h2 className="mb-6 font-lora text-2xl font-medium text-neutral-100">Change account photo</h2>
194
- <div className="mb-3 flex flex-col items-center gap-3 rounded-3xl border border-stroke-dark p-8">
195
- <h3 className="font-inter text-lg font-medium text-neutral-100">Upload your photo</h3>
196
- <Button size="sm" variant="secondary">
197
- Select File
198
- </Button>
199
- </div>
200
- <p className="text-xs text-neutral-50">
201
- It should be smaller than 2MB, and it should show your face.
202
- </p>
203
- </div>
204
- )
205
-
206
- const Template: StoryFn<typeof Modal> = args => <Modal {...args} />
207
-
208
- const CustomFooterTemplate: StoryFn<typeof Modal> = args => (
209
- <Modal
210
- {...args}
211
- footer={
212
- <div className="flex gap-1.5">
213
- <Button className="w-full" size="md" variant="secondary" onClick={args.onClose}>
214
- Accept
215
- </Button>
216
- <Button className="w-full" size="md" variant="danger" onClick={args.onClose} data-autofocus>
217
- Decline
218
- </Button>
219
- </div>
220
- }
221
- />
222
- )
223
-
224
- const WithFormTemplate: StoryFn<typeof Modal> = args => (
225
- <Modal {...args}>
226
- <form
227
- className="grid gap-6"
228
- onSubmit={e => {
229
- e.preventDefault()
230
- args.onClose()
231
- alert("submitted")
232
- }}
233
- >
234
- <TextInput id="example" type="email" label="Email" placeholder="Enter your email" required />
235
- <Button className="w-full">Finish</Button>
236
- </form>
237
- </Modal>
238
- )
239
-
240
- // Stories
241
- const Default = Template.bind({})
242
- const CustomHeader = Template.bind({})
243
- const CustomFooter = CustomFooterTemplate.bind({})
244
- const Wide = Template.bind({})
245
- const Long = Template.bind({})
246
- const WithForm = WithFormTemplate.bind({})
247
-
248
- // Args
249
- Default.args = {
250
- children: <DummyContent />,
251
- }
252
-
253
- CustomHeader.args = {
254
- header: (
255
- <header
256
- style={{
257
- display: "flex",
258
- justifyContent: "center",
259
- padding: 24,
260
- background:
261
- "linear-gradient(90deg, rgb(2 0 36 / 1) 0%, rgb(9 9 121 / 1) 35%, rgb(0 212 255 / 1) 100%)",
262
- }}
263
- >
264
- <h5 style={{ margin: 0, color: "white" }}>This is a custom header</h5>
265
- </header>
266
- ),
267
- }
268
-
269
- Wide.args = {
270
- children: <DummyContent />,
271
- className: "sm:w-[600px]",
272
- }
273
-
274
- Long.args = {
275
- title: "Title",
276
- subTitle: "Subtitle",
277
- children: (
278
- <div className="grid gap-3">
279
- <p>{lorem}</p>
280
- <p>{lorem}</p>
281
- <p>{lorem}</p>
282
- <p>{lorem}</p>
283
- <p>{lorem}</p>
284
- <p>{lorem}</p>
285
- </div>
286
- ),
287
- }
288
-
289
- // Parameters
290
- CustomHeader.parameters = {
291
- docs: {
292
- description: {
293
- story:
294
- "The `header` prop can be used to render a custom header. (e.g. `header={<h1>Custom header</h1>}`)",
295
- },
296
- },
297
- }
298
-
299
- CustomFooter.parameters = {
300
- docs: {
301
- description: {
302
- story:
303
- "The `footer` prop can be used to render a custom footer. (e.g. `footer={<h1>Custom footer</h1>}`)",
304
- },
305
- },
306
- }
307
-
308
- Wide.parameters = {
309
- docs: {
310
- description: {
311
- story:
312
- "To set a custom width for the Modal pass a tailwind width class to the className prop (e.g. `w-96` or `w-[64rem]`).",
313
- },
314
- },
315
- }
316
-
317
- export { Default, CustomHeader, CustomFooter, Wide, Long, WithForm }
318
- export default meta
@@ -1,217 +0,0 @@
1
- "use client"
2
-
3
- import React, { useEffect } from "react"
4
- import { createPortal } from "react-dom"
5
-
6
- // Components
7
- import { XMarkIcon } from "@heroicons/react/20/solid"
8
-
9
- // Utils
10
- import { motion, AnimatePresence, Variants, HTMLMotionProps } from "motion/react"
11
- import clsx from "clsx"
12
- import {
13
- useCombinedRefs,
14
- useEventListener,
15
- useLockBodyScroll,
16
- useOnClickOutside,
17
- useFocusTrap,
18
- } from "../../hooks"
19
- import { backdropVariants } from "../../utils/animation/variants"
20
-
21
- // Variants
22
- const modalVariants: Variants = {
23
- hidden: {
24
- opacity: 0,
25
- x: "-50%",
26
- y: "-45%",
27
- transition: {
28
- duration: 0.15,
29
- ease: [0.4, 0, 0.2, 1],
30
- },
31
- },
32
- visible: {
33
- opacity: 1,
34
- x: "-50%",
35
- y: "-50%",
36
- transition: {
37
- duration: 0.15,
38
- ease: [0.4, 0, 0.2, 1],
39
- },
40
- },
41
- }
42
-
43
- // Params
44
- interface ModalProps extends HTMLMotionProps<"div"> {
45
- /** */
46
- isOpen?: boolean
47
- /** Callback function that's called when the Modal is closed. */
48
- onClose: () => void
49
- /** */
50
- withBackdrop?: boolean
51
- /** */
52
- withCloseButton?: boolean
53
- /** */
54
- closeOnClickOutside?: boolean
55
- /** */
56
- closeOnEscape?: boolean
57
- /** */
58
- lockScroll?: boolean
59
- /** */
60
- trapFocus?: boolean
61
- /** */
62
- portal?: Element | DocumentFragment
63
- /** @deprecated Not currently in use */
64
- /** Title to use at the top of the Modal. */
65
- title?: string
66
- /** @deprecated Not currently in use */
67
- /** Subtitle to use at the top of the Modal. */
68
- subTitle?: string
69
- /** A React Node that's displayed in place of the default `title` and `subTitle`. */
70
- header?: React.ReactNode
71
- /** A React Node that's displayed at the bottom of the Modal. */
72
- footer?: React.ReactNode
73
- /** */
74
- children?: React.ReactNode
75
- /** */
76
- contentClassName?: string
77
- }
78
-
79
- const MODAL_EVENT = "oakma-modal-state"
80
-
81
- /*
82
-
83
-
84
-
85
-
86
-
87
- */
88
-
89
- const Modal: React.FC<ModalProps> = ({
90
- isOpen = false,
91
- withBackdrop = true,
92
- withCloseButton = true,
93
- closeOnClickOutside = true,
94
- closeOnEscape = true,
95
- lockScroll = true,
96
- trapFocus = true,
97
- portal,
98
- onClose,
99
- title, // eslint-disable-line
100
- subTitle, // eslint-disable-line
101
- className,
102
- children,
103
- header,
104
- footer,
105
- contentClassName,
106
- ref,
107
- ...rest
108
- }) => {
109
- // Refs
110
- const focusRef = useFocusTrap(trapFocus && isOpen)
111
- const combinedRefs = useCombinedRefs<HTMLDivElement | null>(ref, focusRef)
112
-
113
- // Events
114
- useOnClickOutside<HTMLDivElement | null>(combinedRefs, () => {
115
- if (closeOnClickOutside) onClose()
116
- })
117
-
118
- useEventListener("keydown", e => {
119
- if (closeOnEscape && e.key === "Escape") onClose()
120
- })
121
-
122
- useLockBodyScroll(lockScroll && isOpen)
123
-
124
- // Effects
125
- useEffect(() => {
126
- if (typeof window !== "undefined") {
127
- window.dispatchEvent(new CustomEvent(MODAL_EVENT, { detail: { open: isOpen } }))
128
- }
129
- return () => {
130
- if (typeof window !== "undefined") {
131
- window.dispatchEvent(new CustomEvent(MODAL_EVENT, { detail: { open: false } }))
132
- }
133
- }
134
- }, [isOpen])
135
-
136
- if (typeof window === "undefined") {
137
- return null
138
- }
139
-
140
- return createPortal(
141
- <AnimatePresence>
142
- {isOpen && (
143
- <div className="fixed inset-0 z-9998">
144
- {withBackdrop && (
145
- <motion.div
146
- className="fixed inset-0 opacity-30 backdrop-blur-xs"
147
- initial="hidden"
148
- animate="visible"
149
- exit="hidden"
150
- variants={backdropVariants}
151
- role="presentation"
152
- style={{ backgroundColor: "rgba(15 41 41 / 0.3)" }}
153
- />
154
- )}
155
-
156
- <motion.div
157
- className={clsx(
158
- "fixed top-1/2 left-1/2 flex max-h-[90vh] w-[calc(100vw-3rem)] shrink-0 flex-col gap-4 overflow-hidden rounded-5xl bg-white shadow-md sm:w-96",
159
- className,
160
- )}
161
- ref={combinedRefs}
162
- role="dialog"
163
- aria-modal
164
- initial="hidden"
165
- animate="visible"
166
- exit="hidden"
167
- variants={modalVariants}
168
- {...rest}
169
- >
170
- <header
171
- className={clsx(
172
- "sticky top-0 grid w-full grid-cols-[auto_min-content] items-start gap-4 bg-transparent pt-4 pl-6",
173
- withCloseButton ? "pr-4" : "p-6",
174
- )}
175
- >
176
- {header && <>{header}</>}
177
-
178
- {/* {!header && !!title && (
179
- <div className="flex flex-col pt-1">
180
- <h2 className="font-lora text-2xl font-medium text-neutral-100">{title}</h2>
181
- {subTitle && <p className="text-neutral-50">{subTitle}</p>}
182
- </div>
183
- )} */}
184
-
185
- {withCloseButton && (
186
- <button
187
- className="col-start-2 -mt-0.5 -mr-0.5 flex size-6 cursor-pointer items-center justify-center justify-self-end rounded-full text-neutral-50 transition-colors hover:bg-neutral-50/10 hover:text-neutral-100 focus-visible:bg-neutral-50/10 focus-visible:text-neutral-100 active:bg-neutral-50/20"
188
- onClick={onClose}
189
- title="Close modal"
190
- >
191
- <XMarkIcon className="size-6" />
192
- </button>
193
- )}
194
- </header>
195
-
196
- <div
197
- className={clsx(
198
- "size-full overflow-scroll px-6",
199
- !footer && "pb-6",
200
- contentClassName,
201
- )}
202
- >
203
- {children}
204
- </div>
205
-
206
- {footer && <footer className="bg-transparent px-6 pb-4">{footer}</footer>}
207
- </motion.div>
208
- </div>
209
- )}
210
- </AnimatePresence>,
211
- portal || document.body,
212
- )
213
- }
214
-
215
- Modal.displayName = "Modal"
216
- export default Modal
217
- export type { ModalProps }
@@ -1 +0,0 @@
1
- export { default, type ModalProps } from "./Modal"
@@ -1,47 +0,0 @@
1
- "use client"
2
-
3
- import React from "react"
4
-
5
- // Components
6
- import { AsyncDropdown, type AsyncDropdownProps } from "../Dropdown"
7
- import { MultiSelectOption } from "./MultiSelect"
8
-
9
- // Props
10
- interface AsyncMultiSelectProps extends Omit<AsyncDropdownProps, "isMulti"> {
11
- cy?: string
12
- }
13
-
14
- const multiSelectComponents = { Option: MultiSelectOption }
15
-
16
- /*
17
-
18
-
19
-
20
-
21
-
22
- */
23
-
24
- const AsyncMultiSelect: React.FC<AsyncMultiSelectProps> = ({
25
- tabSelectsValue = false,
26
- closeMenuOnSelect = false,
27
- hideSelectedOptions = false,
28
- isClearable = false,
29
- ...rest
30
- }) => {
31
- return (
32
- <AsyncDropdown
33
- closeMenuOnSelect={closeMenuOnSelect}
34
- hideSelectedOptions={hideSelectedOptions}
35
- tabSelectsValue={tabSelectsValue}
36
- // @ts-expect-error - The `isMulti` prop is not supported when used by external consumers, however it is required internally to render the correct components and behavior.
37
- isMulti
38
- isClearable={isClearable}
39
- components={multiSelectComponents}
40
- {...rest}
41
- />
42
- )
43
- }
44
-
45
- AsyncMultiSelect.displayName = "AsyncMultiSelect"
46
- export default AsyncMultiSelect
47
- export type { AsyncMultiSelectProps }
@@ -1,37 +0,0 @@
1
- ## Usage with `react-hook-form`
2
-
3
- Due to the nature of the component should, you want to use the MultiSelect within a form managed by `react-hook-form`, you'll need to use their `Controller` component:
4
-
5
- ```tsx
6
- "use client"
7
-
8
- import React from "react"
9
- import { useForm, Controller } from "react-hook-form"
10
-
11
- export default function MyForm() {
12
- const { control, handleSubmit } = useForm()
13
-
14
- return (
15
- <form onSubmit={handleSubmit(data => console.log(data))}>
16
- <Controller
17
- name="controlled-multi-select"
18
- control={control}
19
- render={({ field }) => {
20
- return <MultiSelect {...multiSelectProps} {...field} />
21
- }}
22
- />
23
- </form>
24
- )
25
- }
26
- ```
27
-
28
- Doing this will mean that the result from the component will be correctly passed to `rhf`'s submit handler.
29
-
30
- ```json
31
- // example result from multi select
32
- [
33
- { "label": "Item 1", "value": "item-1" },
34
- { "label": "Item 2", "value": "item-2" },
35
- { "label": "Item 3", "value": "item-3" }
36
- ]
37
- ```