@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,158 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import Notification from "./Notification"
5
-
6
- // Types
7
- import type { Meta, StoryFn } from "@storybook/react-webpack5"
8
- import type { NotificationProps } from "./Notification"
9
- import { NOTIFICATION_VARIANTS } from "./types"
10
-
11
- // Utils
12
- import { DummyPhoneIcon } from "../../../.storybook/components"
13
-
14
- /*
15
-
16
-
17
-
18
-
19
- */
20
-
21
- const meta: Meta<NotificationProps> = {
22
- title: "Components/Notification",
23
- component: Notification,
24
- parameters: {
25
- docs: {
26
- description: {
27
- component:
28
- "A notification banner used to surface messages, alerts, or status updates to the user.",
29
- },
30
- },
31
- controls: {
32
- exclude: ["className", "ref", "leadingIcon"],
33
- },
34
- },
35
- argTypes: {
36
- variant: {
37
- type: "string",
38
- description: "Visual variant of the Notification.",
39
- table: {
40
- type: { summary: NOTIFICATION_VARIANTS.map(v => `"${v}"`).join(" | ") },
41
- defaultValue: { summary: '"default"' },
42
- },
43
- options: NOTIFICATION_VARIANTS,
44
- control: { type: "select" },
45
- },
46
- text: {
47
- type: "string",
48
- description: "The primary message text.",
49
- table: {
50
- type: { summary: "React.ReactNode" },
51
- },
52
- },
53
- subText: {
54
- type: "string",
55
- description: "Optional secondary message displayed below the primary text.",
56
- table: {
57
- type: { summary: "React.ReactNode" },
58
- defaultValue: { summary: "undefined" },
59
- },
60
- },
61
- onClose: {
62
- description: "When provided, renders a dismiss button that calls this handler.",
63
- table: {
64
- type: { summary: "() => void" },
65
- defaultValue: { summary: "undefined" },
66
- },
67
- },
68
- },
69
- args: {
70
- text: "Notification message here",
71
- variant: "default",
72
- },
73
- decorators: [
74
- Story => (
75
- <div style={{ width: 350 }}>
76
- <Story />
77
- </div>
78
- ),
79
- ],
80
- }
81
-
82
- const Template: StoryFn<NotificationProps> = args => <Notification {...args} />
83
-
84
- const Default = Template.bind({})
85
- const Dark = Template.bind({})
86
- const WithLeadingIcon = Template.bind({})
87
- const WithSubText = Template.bind({})
88
- const WithAllFeatures = Template.bind({})
89
-
90
- // Args
91
- Default.args = {
92
- onClose: () => {},
93
- }
94
-
95
- Dark.args = {
96
- variant: "dark",
97
- onClose: () => {},
98
- }
99
-
100
- WithLeadingIcon.args = {
101
- leadingIcon: <DummyPhoneIcon />,
102
- onClose: () => {},
103
- }
104
-
105
- WithSubText.args = {
106
- subText: "Sub-text message here.",
107
- onClose: () => {},
108
- }
109
-
110
- WithAllFeatures.args = {
111
- leadingIcon: <DummyPhoneIcon />,
112
- subText: "Sub-text message here.",
113
- onClose: () => {},
114
- }
115
-
116
- // Parameters
117
- Default.parameters = {
118
- docs: {
119
- description: {
120
- story: "Default light notification with a dismiss button.",
121
- },
122
- },
123
- }
124
-
125
- Dark.parameters = {
126
- docs: {
127
- description: {
128
- story: 'Dark teal variant. Pass `variant="dark"` to enable.',
129
- },
130
- },
131
- }
132
-
133
- WithLeadingIcon.parameters = {
134
- docs: {
135
- description: {
136
- story: "Pass any React node to `leadingIcon` to render an icon before the message.",
137
- },
138
- },
139
- }
140
-
141
- WithSubText.parameters = {
142
- docs: {
143
- description: {
144
- story: "Provide `subText` to render a secondary line of smaller text beneath the message.",
145
- },
146
- },
147
- }
148
-
149
- WithAllFeatures.parameters = {
150
- docs: {
151
- description: {
152
- story: "Leading icon, primary message, sub-text, and dismiss button all together.",
153
- },
154
- },
155
- }
156
-
157
- export { Default, Dark, WithLeadingIcon, WithSubText, WithAllFeatures }
158
- export default meta
@@ -1,110 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import { XMarkIcon } from "@heroicons/react/20/solid"
5
-
6
- // Types
7
- import { NotificationVariant } from "./types"
8
-
9
- // Utils
10
- import clsx from "clsx"
11
-
12
- // Params
13
- interface NotificationProps extends Omit<React.ComponentPropsWithRef<"div">, "children"> {
14
- variant?: NotificationVariant
15
- leadingIcon?: React.ReactNode
16
- text: string
17
- subText?: string | React.ReactNode
18
- onClose?: () => void
19
- }
20
-
21
- interface NotificationData extends Pick<NotificationProps, "variant" | "text" | "subText"> {
22
- /** The id of the Notification. */
23
- id: string
24
- /** Time that the notification was added. */
25
- timestamp: number
26
- }
27
-
28
- /*
29
-
30
-
31
-
32
-
33
- */
34
-
35
- const Notification: React.FC<NotificationProps> = ({
36
- variant = "default",
37
- text,
38
- subText,
39
- leadingIcon,
40
- onClose,
41
- className,
42
- ...rest
43
- }) => {
44
- return (
45
- <div
46
- className={clsx(
47
- "flex w-full items-start gap-2 rounded-2xl border px-4 py-3 shadow-md",
48
- variant === "default" && "border-stroke-dark bg-white",
49
- variant === "dark" && "border-transparent bg-teal-100",
50
- className,
51
- )}
52
- {...rest}
53
- >
54
- {leadingIcon && (
55
- <span
56
- className={clsx(
57
- "mt-0.5 size-5 shrink-0",
58
- variant === "default" && "text-teal-100",
59
- variant === "dark" && "text-white",
60
- )}
61
- >
62
- {leadingIcon}
63
- </span>
64
- )}
65
- <div className="flex min-w-0 flex-1 flex-col gap-1">
66
- <p
67
- className={clsx(
68
- "text-sm font-medium tracking-[-0.14px]",
69
- variant === "default" && "text-neutral-100",
70
- variant === "dark" && "text-white",
71
- )}
72
- >
73
- {text}
74
- </p>
75
- {subText && (
76
- <p
77
- className={clsx(
78
- "text-xs",
79
- variant === "default" && "text-neutral-50",
80
- variant === "dark" && "text-teal-10",
81
- )}
82
- >
83
- {subText}
84
- </p>
85
- )}
86
- </div>
87
-
88
- {onClose && (
89
- <button
90
- type="button"
91
- onClick={onClose}
92
- aria-label="Dismiss notification"
93
- className={clsx(
94
- "flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors ease-out",
95
- variant === "default" &&
96
- "text-neutral-50 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",
97
- variant === "dark" &&
98
- "text-white/70 hover:bg-white/10 hover:text-white focus-visible:bg-white/10 focus-visible:text-white active:bg-white/20",
99
- )}
100
- >
101
- <XMarkIcon className="size-5" />
102
- </button>
103
- )}
104
- </div>
105
- )
106
- }
107
-
108
- Notification.displayName = "Notification"
109
- export default Notification
110
- export type { NotificationProps, NotificationData }
@@ -1 +0,0 @@
1
- export { default, type NotificationProps, type NotificationData } from "./Notification"
@@ -1,11 +0,0 @@
1
- /*
2
-
3
-
4
-
5
-
6
-
7
- */
8
-
9
- export const NOTIFICATION_VARIANTS = ["default", "dark"] as const
10
-
11
- export type NotificationVariant = (typeof NOTIFICATION_VARIANTS)[number]
@@ -1,103 +0,0 @@
1
- ## Usage
2
-
3
- To being, wrap you entire application in `NotificationsProvider`. This will provide the context for the notifications to be displayed and allow the adding and removing of notifications from anywhere in the app:
4
-
5
- ```tsx
6
- import { NotificationsProvider } from "@bronzelabs/oakma-ui"
7
-
8
- export default function RootLayout({ children }: { children: React.ReactNode }) {
9
- return (
10
- <html lang="en">
11
- <body>
12
- <NotificationsProvider>
13
- <main>{children}</main>
14
- </NotificationsProvider>
15
- </body>
16
- </html>
17
- )
18
- }
19
- ```
20
-
21
- In most cases you'll want to display the notifications in their default, fixed position in the viewport. To do this, add the `Notifications` component to the layout of your app:
22
-
23
- ```tsx
24
- import { NotificationsProvider, Notifications } from "@bronzelabs/oakma-ui"
25
-
26
- export default function RootLayout({ children }: { children: React.ReactNode }) {
27
- return (
28
- <html lang="en">
29
- <body>
30
- <NotificationsProvider>
31
- <main>{children}</main>
32
- <Notifications /> { /* <----- */ }
33
- </NotificationsProvider>
34
- </body>
35
- </html>
36
- )
37
- }
38
- ```
39
-
40
- ### Adding a notification
41
-
42
- To add a notification, use the `useNotifications` hook to access the `addNotification` method. This accepts either a single or an array of `Notification` objects as its only argument. The `Notification` object has the following properties:
43
-
44
- | Property | Type | Description |
45
- | --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------- |
46
- | `id` | `string` | A unique identifier for the notification. If not provided, one will be generated. |
47
- | `text` | `string \| React.ReactNode` | Content to display inside the Notification. Can also be a ReactNode to allow passing of jsx with things like links. |
48
- | `subText` | `string \| React.ReactNode` | Optional content to display below the main text. Can also be a ReactNode. |
49
- | `variant` | `"default"` \| `"dark"` | The style variant of the Notification. Currently just controls light/dark. |
50
-
51
- ```tsx
52
- "use client"
53
-
54
- import { useNotifications } from "@bronzelabs/oakma-ui"
55
-
56
- export default function MyComponent() {
57
- const { addNotification } = useNotifications()
58
-
59
- function handleClick() {
60
- addNotification({
61
- text: "This is a success notification",
62
- })
63
- }
64
-
65
- return <button onClick={handleClick}>Add notification</button>
66
- }
67
- ```
68
-
69
- You can also pass an optional second argument to `addNotification` to specify whether the notification should automatically dismiss after a certain amount of time. By default, notifications will automatically dismiss after 5 seconds. To disable this behavior, pass `false` as the second argument:
70
-
71
- ```tsx
72
- export default function MyComponent() {
73
- // {/* ... */}
74
-
75
- function handleClick() {
76
- addNotification({
77
- text: "This notification will not automatically dismiss",
78
- }, false)
79
- }
80
-
81
- // {/* ... */}
82
- }
83
- ```
84
-
85
- ### Removing a notification
86
-
87
- To remove a notification, use the `useNotifications` hook to access the `removeNotification` method. This function accepts the `id` of the notification you want to remove as its only argument.
88
-
89
- ```tsx
90
- "use client"
91
-
92
- import { useNotifications } from "@bronzelabs/oakma-ui"
93
-
94
- export default function MyComponent() {
95
- const { removeNotification } = useNotifications()
96
-
97
- function handleClick() {
98
- removeNotification("1")
99
- }
100
-
101
- return <button onClick={handleClick}>Remove notification</button>
102
- }
103
- ```
@@ -1,159 +0,0 @@
1
- import React, { useEffect } from "react"
2
-
3
- // Components
4
- import Notifications, { type NotificationsProps } from "./Notifications"
5
- import Notification, { type NotificationData } from "../Notification"
6
- import { NotificationsProvider, useNotifications } from "./NotificationsContext"
7
-
8
- // Types
9
- import type { StoryFn, Meta } from "@storybook/react-webpack5"
10
- import type { PickPartial } from "../../types/helpers"
11
-
12
- // Utils
13
- import { StorybookActionButton } from "../../../.storybook/components"
14
- import extraDocs from "./Notifications.docs.md"
15
- import { renderDocsWithProps } from "../../../.storybook/utils"
16
-
17
- // Data
18
- const data: PickPartial<NotificationData, "id" | "timestamp">[] = [
19
- {
20
- text: "This is the first notification",
21
- subText: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
22
- },
23
- {
24
- text: "This is the second notification",
25
- subText: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
26
- },
27
- {
28
- text: "This is the third notification",
29
- subText: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
30
- },
31
- ]
32
-
33
- /*
34
-
35
-
36
-
37
-
38
- */
39
-
40
- const meta = {
41
- title: "Components/Notifications",
42
- component: Notifications,
43
- subcomponents: { Notification },
44
- parameters: {
45
- docs: {
46
- page: renderDocsWithProps({ extraDocs }),
47
- },
48
- controls: {
49
- exclude: ["className", "ref", "children"],
50
- },
51
- },
52
- argTypes: {
53
- isDisismissable: {
54
- type: "boolean",
55
- description: "Whether the notifications can be dismissed by an internal `X` button or not",
56
- table: {
57
- type: { summary: "boolean" },
58
- defaultValue: { summary: "false" },
59
- },
60
- },
61
- },
62
- args: {
63
- isDisismissable: false,
64
- },
65
- decorators: [
66
- Story => (
67
- <div style={{ width: 400 }}>
68
- <Story />
69
- </div>
70
- ),
71
- ],
72
- } satisfies Meta<typeof Notifications>
73
-
74
- // Templates
75
- const Template: StoryFn<NotificationsProps> = args => {
76
- const { addNotification } = useNotifications()
77
-
78
- useEffect(() => addNotification(data, false), [addNotification])
79
-
80
- return (
81
- <Notifications
82
- {...args}
83
- /**
84
- * Position in the main app is fixed to the top right corner, however, in storybook
85
- * this is positioning it outside the relevant container, therefore, its position
86
- * needs to be reset.
87
- */
88
- style={{
89
- position: "relative",
90
- top: "auto",
91
- right: "auto",
92
- bottom: "auto",
93
- left: "auto",
94
- }}
95
- />
96
- )
97
- }
98
-
99
- // Stories
100
- const Default = Template.bind({})
101
- const Dismissable = Template.bind({})
102
- const Playground = Template.bind({})
103
-
104
- // Args
105
- Dismissable.args = {
106
- isDisismissable: true,
107
- }
108
-
109
- Playground.args = {
110
- isDisismissable: true,
111
- }
112
-
113
- // Decorators
114
- Default.decorators = [Story => <NotificationsProvider>{<Story />}</NotificationsProvider>]
115
-
116
- Dismissable.decorators = [Story => <NotificationsProvider>{<Story />}</NotificationsProvider>]
117
-
118
- Playground.decorators = [
119
- Story => {
120
- const { notifications, addNotification, removeNotification } = useNotifications()
121
-
122
- return (
123
- <div>
124
- {<Story />}
125
- <div
126
- style={{
127
- marginTop: 48,
128
- display: "flex",
129
- alignItems: "center",
130
- justifyContent: "center",
131
- gap: 16,
132
- }}
133
- >
134
- <StorybookActionButton
135
- onClick={() =>
136
- addNotification(
137
- {
138
- text: "This is a dummy notification",
139
- subText: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
140
- variant: Math.round(Math.random()) > 0 ? "default" : "dark",
141
- },
142
- false,
143
- )
144
- }
145
- >
146
- Add
147
- </StorybookActionButton>
148
- <StorybookActionButton onClick={() => removeNotification(notifications.at(0)?.id)}>
149
- Remove
150
- </StorybookActionButton>
151
- </div>
152
- </div>
153
- )
154
- },
155
- Story => <NotificationsProvider>{<Story />}</NotificationsProvider>,
156
- ]
157
-
158
- export default meta
159
- export { Default, Dismissable, Playground }
@@ -1,90 +0,0 @@
1
- "use client"
2
-
3
- import React, { useCallback } from "react"
4
-
5
- // Components
6
- import Notification from "../Notification"
7
-
8
- // Types
9
-
10
- // Utils
11
- import clsx from "clsx"
12
- import { useNotifications } from "./NotificationsContext"
13
- import { motion, AnimatePresence, type Variants } from "motion/react"
14
-
15
- // Props
16
- interface NotificationsProps extends React.ComponentProps<"div"> {
17
- isDisismissable?: boolean
18
- children?: never
19
- }
20
-
21
- const notificationVariants: Variants = {
22
- initial: {
23
- opacity: 0,
24
- y: 15,
25
- },
26
- animate: {
27
- opacity: 1,
28
- y: 0,
29
- transition: {
30
- ease: "easeOut",
31
- duration: 0.15,
32
- },
33
- },
34
- exit: {
35
- opacity: 0,
36
- x: "4rem",
37
- transition: {
38
- ease: "easeOut",
39
- duration: 0.15,
40
- },
41
- },
42
- }
43
-
44
- /*
45
-
46
-
47
-
48
-
49
- */
50
-
51
- const Notifications: React.FC<NotificationsProps> = ({ className, isDisismissable, ...rest }) => {
52
- // State
53
- const { notifications: data, removeNotification } = useNotifications()
54
-
55
- // Functions
56
- const handleRemove = useCallback(
57
- (id: string) => () => removeNotification(id),
58
- [removeNotification],
59
- )
60
-
61
- return (
62
- <div
63
- className={clsx(
64
- "w-[min(25rem, 96vw)] fixed inset-x-[2vw] top-0 z-9999 md:top-6 md:right-6 md:left-auto",
65
- className,
66
- )}
67
- {...rest}
68
- >
69
- <AnimatePresence>
70
- {data?.map(item => (
71
- <motion.div
72
- key={item.id}
73
- className="my-3 w-full min-w-82 select-none"
74
- initial="initial"
75
- animate="animate"
76
- exit="exit"
77
- variants={notificationVariants}
78
- layout
79
- >
80
- <Notification {...item} onClose={isDisismissable ? handleRemove(item.id) : undefined} />
81
- </motion.div>
82
- ))}
83
- </AnimatePresence>
84
- </div>
85
- )
86
- }
87
-
88
- Notifications.displayName = "Notifications"
89
- export default Notifications
90
- export type { NotificationsProps }