@bronzelabs/oakma-ui 0.0.1 → 0.0.3

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 +2 -0
  3. package/dist/oakma-ui.css +2 -0
  4. package/package.json +7 -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,255 +0,0 @@
1
- "use client"
2
-
3
- import React, { useState } from "react"
4
-
5
- // Components
6
- import Button, { ButtonProps } from "../Button"
7
- import { Container, ErrorMessage, Icon, Label, useInputKeyboardFocus } from "../TextField"
8
- import {
9
- EyeSlashIcon,
10
- EyeIcon,
11
- CalendarIcon,
12
- CalendarDaysIcon,
13
- CalendarDateRangeIcon,
14
- ClockIcon,
15
- } from "@heroicons/react/24/solid"
16
-
17
- // Types
18
- import type { TextInputSize, TextInputVariant } from "./types"
19
-
20
- // Utils
21
- import { clsx } from "clsx"
22
-
23
- // Params
24
- const INPUT_TYPES = {
25
- calendar: ["date", "datetime-local", "week", "month", "time"],
26
- text: ["text", "email", "number", "password", "search", "tel", "url"],
27
- }
28
-
29
- interface TextInputProps extends Omit<
30
- React.InputHTMLAttributes<HTMLInputElement>,
31
- "id" | "type" | "size"
32
- > {
33
- id: string
34
- label?: string
35
- size?: TextInputSize
36
- variant?: TextInputVariant
37
- type?: React.HTMLInputTypeAttribute
38
- leadingIcon?: {
39
- icon: React.ReactNode
40
- onClick?: React.MouseEventHandler<HTMLButtonElement>
41
- type?: "button" | "submit" | "reset"
42
- disabled?: boolean
43
- name?: string
44
- }
45
- trailingIcon?: {
46
- icon: React.ReactNode
47
- onClick?: React.MouseEventHandler<HTMLButtonElement>
48
- type?: "button" | "submit" | "reset"
49
- disabled?: boolean
50
- name?: string
51
- }
52
- showOptional?: boolean
53
- error?: {
54
- message: string
55
- }
56
- button?: Omit<ButtonProps, "children"> & { label: string }
57
- }
58
-
59
- /*
60
-
61
-
62
-
63
-
64
-
65
- */
66
-
67
- const TextInput: React.FC<TextInputProps> = ({
68
- id,
69
- label,
70
- size = "md",
71
- variant = "dark",
72
- type = "text",
73
- button,
74
- error,
75
- leadingIcon,
76
- trailingIcon,
77
- showOptional = true,
78
- className,
79
- required,
80
- disabled,
81
- onFocus,
82
- onBlur,
83
- ...rest
84
- }) => {
85
- const { keyboardFocused, handleMouseDown, handleMouseUp, handleFocus, handleBlur } =
86
- useInputKeyboardFocus({ onFocus, onBlur })
87
-
88
- // State
89
- const [dynamicType, setDynamicType] = useState<React.HTMLInputTypeAttribute>(type)
90
-
91
- // Functions
92
- function handleTrailingIconClick(e: React.MouseEvent<HTMLButtonElement>) {
93
- if (type === "password") {
94
- setDynamicType(dynamicType === "password" ? "text" : "password")
95
- }
96
- return trailingIcon?.onClick?.(e)
97
- }
98
-
99
- function handleLeadingIconClick(e: React.MouseEvent<HTMLButtonElement>) {
100
- if (INPUT_TYPES.calendar.includes(dynamicType)) {
101
- return e.currentTarget?.closest("div")?.querySelector("input")?.showPicker()
102
- }
103
- return leadingIcon?.onClick?.(e)
104
- }
105
-
106
- return (
107
- <div className={className}>
108
- <Container
109
- keyboardFocused={keyboardFocused}
110
- onMouseDown={handleMouseDown}
111
- onMouseUp={handleMouseUp}
112
- size={size}
113
- hasButton={!!button?.label}
114
- variant={variant}
115
- label={label}
116
- showOptional={showOptional}
117
- required={required}
118
- >
119
- {label && (
120
- <Label
121
- inputId={id}
122
- label={label}
123
- showOptional={showOptional}
124
- required={required}
125
- variant={variant}
126
- />
127
- )}
128
- {INPUT_TYPES.calendar.includes(dynamicType) && (
129
- <Icon
130
- position="leading"
131
- fieldSize={size}
132
- variant={variant}
133
- disabled={disabled}
134
- onClick={handleLeadingIconClick}
135
- name={leadingIcon?.name}
136
- buttonType={leadingIcon?.type}
137
- >
138
- {dynamicType === "time" && (
139
- <ClockIcon className={clsx(size === "md" && "size-6", size === "sm" && "size-5")} />
140
- )}
141
- {dynamicType === "date" && (
142
- <CalendarIcon
143
- className={clsx(size === "md" && "size-6", size === "sm" && "size-5")}
144
- />
145
- )}
146
- {dynamicType === "datetime-local" && (
147
- <CalendarIcon
148
- className={clsx(size === "md" && "size-6", size === "sm" && "size-5")}
149
- />
150
- )}
151
- {dynamicType === "week" && (
152
- <CalendarDateRangeIcon
153
- className={clsx(size === "md" && "size-6", size === "sm" && "size-5")}
154
- />
155
- )}
156
- {dynamicType === "month" && (
157
- <CalendarDaysIcon
158
- className={clsx(size === "md" && "size-6", size === "sm" && "size-5")}
159
- />
160
- )}
161
- </Icon>
162
- )}
163
- {leadingIcon?.icon && !INPUT_TYPES.calendar.includes(dynamicType) && (
164
- <Icon
165
- position="leading"
166
- fieldSize={size}
167
- variant={variant}
168
- disabled={leadingIcon?.disabled || disabled}
169
- onClick={leadingIcon?.onClick}
170
- name={leadingIcon?.name}
171
- buttonType={leadingIcon?.type}
172
- >
173
- {leadingIcon.icon}
174
- </Icon>
175
- )}
176
-
177
- <input
178
- id={id}
179
- className={clsx(
180
- "size-full min-w-0 placeholder:text-neutral-30 focus:outline-hidden",
181
- variant === "dark" && "text-neutral-100",
182
- variant === "light" && "text-white",
183
- size === "sm" && [
184
- "min-h-6 text-sm",
185
- !!(leadingIcon?.icon || INPUT_TYPES.calendar.includes(dynamicType))
186
- ? "pl-11.5"
187
- : "pl-3",
188
- !!(trailingIcon?.icon || type === "password") ? "pr-10" : "pr-3",
189
- ],
190
- size === "md" && [
191
- "min-h-12 text-base",
192
- !!(leadingIcon?.icon || INPUT_TYPES.calendar.includes(dynamicType))
193
- ? "pl-12.75"
194
- : "pl-5",
195
- !!(trailingIcon?.icon || type === "password") ? "pr-12" : "pr-5",
196
- ],
197
- )}
198
- aria-describedby={error ? `${id}-error` : undefined}
199
- aria-invalid={!!error}
200
- required={required}
201
- onFocus={handleFocus}
202
- onBlur={handleBlur}
203
- disabled={disabled}
204
- type={dynamicType}
205
- {...rest}
206
- />
207
-
208
- {type === "password" && (
209
- <Icon
210
- position="trailing"
211
- onClick={handleTrailingIconClick}
212
- disabled={disabled}
213
- fieldSize={size}
214
- variant={variant}
215
- name="Toggle password visibility"
216
- >
217
- {dynamicType === "password" ? (
218
- <EyeSlashIcon className="size-5" />
219
- ) : (
220
- <EyeIcon className="size-5" />
221
- )}
222
- </Icon>
223
- )}
224
-
225
- {trailingIcon?.icon && dynamicType !== "password" && (
226
- <Icon
227
- position="trailing"
228
- onClick={trailingIcon?.onClick}
229
- disabled={trailingIcon?.disabled || disabled}
230
- fieldSize={size}
231
- variant={variant}
232
- name={trailingIcon?.name}
233
- >
234
- {trailingIcon.icon}
235
- </Icon>
236
- )}
237
-
238
- {button?.label && (
239
- <Button
240
- size={size}
241
- {...button}
242
- disabled={disabled || button.disabled}
243
- className={clsx("shrink-0", size === "sm" && "min-h-7.5!", button.className)}
244
- >
245
- {button.label}
246
- </Button>
247
- )}
248
- </Container>
249
- {error && <ErrorMessage id={id} error={error} />}
250
- </div>
251
- )
252
- }
253
-
254
- export default TextInput
255
- export type { TextInputProps }
@@ -1,2 +0,0 @@
1
- export { default, type TextInputProps } from "./TextInput"
2
- export type { TextInputSize, TextInputVariant } from "./types"
@@ -1,4 +0,0 @@
1
- export type {
2
- TextFieldSize as TextInputSize,
3
- TextFieldVariant as TextInputVariant,
4
- } from "../TextField"
@@ -1,142 +0,0 @@
1
- import React from "react"
2
-
3
- // Components
4
- import Toggle from "./Toggle"
5
-
6
- // Types
7
- import type { Meta, StoryFn } from "@storybook/react-webpack5"
8
- import type { ToggleProps } from "./Toggle"
9
-
10
- /*
11
-
12
-
13
-
14
-
15
- */
16
-
17
- const meta: Meta<ToggleProps> = {
18
- title: "Components/Toggle",
19
- component: Toggle,
20
- parameters: {
21
- docs: {
22
- description: {
23
- component: "A switch control for toggling a boolean setting on or off.",
24
- },
25
- },
26
- controls: {
27
- exclude: ["className", "ref"],
28
- },
29
- },
30
- argTypes: {
31
- label: {
32
- type: "string",
33
- description: "Label text displayed next to the Toggle.",
34
- table: {
35
- type: { summary: "string" },
36
- defaultValue: { summary: "undefined" },
37
- },
38
- },
39
- meta: {
40
- type: "string",
41
- description: "Secondary text displayed below the label.",
42
- table: {
43
- type: { summary: "string" },
44
- defaultValue: { summary: "undefined" },
45
- },
46
- },
47
- activeText: {
48
- type: "string",
49
- description: "Alternate label shown when the toggle is on. Falls back to label if not set.",
50
- table: {
51
- type: { summary: "string" },
52
- defaultValue: { summary: "undefined" },
53
- },
54
- },
55
- disabled: {
56
- description: "Disables the toggle.",
57
- table: {
58
- type: { summary: "boolean" },
59
- defaultValue: { summary: "false" },
60
- },
61
- },
62
- },
63
- args: {},
64
- }
65
-
66
- const Template: StoryFn<ToggleProps> = args => <Toggle {...args} />
67
-
68
- const Default = Template.bind({})
69
- const Checked = Template.bind({})
70
- const WithLabel = Template.bind({})
71
- const WithLabelAndMeta = Template.bind({})
72
- const WithActiveText = Template.bind({})
73
- const Disabled = Template.bind({})
74
- const DisabledChecked = Template.bind({})
75
-
76
- // Args
77
- Checked.args = { defaultChecked: true }
78
- WithLabel.args = { label: "Enable notifications" }
79
- WithLabelAndMeta.args = {
80
- label: "Enable notifications",
81
- meta: "Receive alerts for important account activity.",
82
- }
83
- WithActiveText.args = {
84
- label: "Notifications off",
85
- activeText: "Notifications on",
86
- defaultChecked: true,
87
- }
88
- Disabled.args = { disabled: true, label: "Disabled option" }
89
- DisabledChecked.args = { disabled: true, defaultChecked: true, label: "Disabled on" }
90
-
91
- // Parameters
92
- WithLabel.parameters = {
93
- docs: {
94
- description: {
95
- story: "Pass a `label` prop to display text alongside the toggle.",
96
- },
97
- },
98
- }
99
-
100
- WithLabelAndMeta.parameters = {
101
- docs: {
102
- description: {
103
- story: "The `meta` prop renders secondary descriptive text below the label.",
104
- },
105
- },
106
- }
107
-
108
- WithActiveText.parameters = {
109
- docs: {
110
- description: {
111
- story:
112
- "The `activeText` prop swaps the label when the toggle is on. Useful for showing context-sensitive state.",
113
- },
114
- },
115
- }
116
-
117
- Disabled.parameters = {
118
- docs: {
119
- description: {
120
- story: "Setting `disabled` reduces opacity and prevents interaction.",
121
- },
122
- },
123
- }
124
-
125
- // Decorators
126
- Default.decorators = [
127
- Story => (
128
- <div className="flex flex-wrap items-center gap-4">
129
- <Story />
130
- </div>
131
- ),
132
- ]
133
-
134
- Checked.decorators = [...Default.decorators]
135
- WithLabel.decorators = [...Default.decorators]
136
- WithLabelAndMeta.decorators = [...Default.decorators]
137
- WithActiveText.decorators = [...Default.decorators]
138
- Disabled.decorators = [...Default.decorators]
139
- DisabledChecked.decorators = [...Default.decorators]
140
-
141
- export { Default, Checked, WithLabel, WithLabelAndMeta, WithActiveText, Disabled, DisabledChecked }
142
- export default meta
@@ -1,69 +0,0 @@
1
- import React from "react"
2
-
3
- // Utils
4
- import { clsx } from "clsx"
5
-
6
- // Params
7
- interface ToggleProps extends Omit<React.ComponentPropsWithRef<"input">, "size" | "children"> {
8
- /** Label text displayed next to the Toggle. */
9
- label?: string
10
- /** Secondary text displayed below the label. */
11
- meta?: string
12
- /** Alternate label shown when the toggle is on. Falls back to label if not set. */
13
- activeText?: string
14
- }
15
-
16
- /*
17
-
18
-
19
-
20
-
21
- */
22
-
23
- const Toggle: React.FC<ToggleProps> = ({
24
- className,
25
- label,
26
- meta,
27
- activeText,
28
- disabled,
29
- ref,
30
- ...rest
31
- }) => {
32
- return (
33
- <label
34
- className={clsx(
35
- "group/toggle flex cursor-pointer items-start gap-3",
36
- disabled && "pointer-events-none opacity-40",
37
- className,
38
- )}
39
- >
40
- <input
41
- ref={ref}
42
- type="checkbox"
43
- role="switch"
44
- className="peer absolute opacity-0"
45
- aria-label={label ?? "Toggle"}
46
- disabled={disabled}
47
- {...rest}
48
- />
49
- <div className="relative h-6 w-12 shrink-0 rounded-full bg-neutral-100/20 p-1 transition-colors group-hover/toggle:bg-neutral-100/30 group-has-checked/toggle:bg-lime-180/20 group-has-checked/toggle:group-hover/toggle:bg-lime-180/30 peer-focus-visible:ring-2 peer-focus-visible:ring-teal-100 peer-focus-visible:ring-offset-1">
50
- <div className="absolute left-1 size-4 rounded-full bg-white transition-all group-active/toggle:w-5 group-has-checked/toggle:left-7 group-has-checked/toggle:bg-lime-180 group-has-checked/toggle:group-active/toggle:left-6!" />
51
- </div>
52
- {(activeText || label || meta) && (
53
- <div className="flex flex-1 flex-col gap-0.5 select-none">
54
- {(activeText || label) && (
55
- <span className="text-sm/snug font-medium text-neutral-100">
56
- <span className="hidden group-has-checked/toggle:inline">{activeText || label}</span>
57
- <span className="inline group-has-checked/toggle:hidden">{label}</span>
58
- </span>
59
- )}
60
- {meta && <span className="text-xs/snug text-neutral-50">{meta}</span>}
61
- </div>
62
- )}
63
- </label>
64
- )
65
- }
66
-
67
- Toggle.displayName = "Toggle"
68
- export default Toggle
69
- export type { ToggleProps }
@@ -1 +0,0 @@
1
- export { default, type ToggleProps } from "./Toggle"
@@ -1,6 +0,0 @@
1
- export { useCombinedRefs } from "./useCombinedRefs"
2
- export { useEventListener } from "./useEventListener"
3
- export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"
4
- export { useLockBodyScroll } from "./useLockBodyScroll"
5
- export { useOnClickOutside } from "./useOnClickOutside"
6
- export { useFocusTrap } from "./useFocusTrap"
@@ -1,37 +0,0 @@
1
- "use client"
2
-
3
- import { useRef, useEffect } from "react"
4
-
5
- /**
6
- * useCombinedRefs
7
- *
8
- * @template T
9
- *
10
- * @param {any[]} refs
11
- * @returns {React.RefObject<T>}
12
- */
13
-
14
- /*
15
- */
16
-
17
- const useCombinedRefs = <T>(...refs: any[]): React.RefObject<T | null> => {
18
- // Refs
19
- const targetRef = useRef<T | null>(null)
20
-
21
- // Effects
22
- useEffect(() => {
23
- refs.forEach(ref => {
24
- if (!ref) return
25
-
26
- if (typeof ref === "function") {
27
- ref(targetRef.current)
28
- } else {
29
- ref.current = targetRef.current
30
- }
31
- })
32
- }, [refs])
33
-
34
- return targetRef
35
- }
36
-
37
- export { useCombinedRefs }
@@ -1,87 +0,0 @@
1
- "use client"
2
-
3
- import { RefObject, useEffect, useRef } from "react"
4
-
5
- import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"
6
-
7
- // MediaQueryList Event based useEventListener interface
8
- function useEventListener<K extends keyof MediaQueryListEventMap>(
9
- eventName: K,
10
- handler: (event: MediaQueryListEventMap[K]) => void,
11
- element: RefObject<MediaQueryList>,
12
- options?: boolean | AddEventListenerOptions,
13
- ): void
14
-
15
- // Window Event based useEventListener interface
16
- function useEventListener<K extends keyof WindowEventMap>(
17
- eventName: K,
18
- handler: (event: WindowEventMap[K]) => void,
19
- element?: undefined,
20
- options?: boolean | AddEventListenerOptions,
21
- ): void
22
-
23
- // Element Event based useEventListener interface
24
- function useEventListener<
25
- K extends keyof HTMLElementEventMap,
26
- T extends HTMLElement = HTMLDivElement,
27
- >(
28
- eventName: K,
29
- handler: (event: HTMLElementEventMap[K]) => void,
30
- element: RefObject<T>,
31
- options?: boolean | AddEventListenerOptions,
32
- ): void
33
-
34
- // Document Event based useEventListener interface
35
- function useEventListener<K extends keyof DocumentEventMap>(
36
- eventName: K,
37
- handler: (event: DocumentEventMap[K]) => void,
38
- element: RefObject<Document>,
39
- options?: boolean | AddEventListenerOptions,
40
- ): void
41
-
42
- /*
43
-
44
-
45
-
46
-
47
- */
48
-
49
- function useEventListener<
50
- KW extends keyof WindowEventMap,
51
- KH extends keyof HTMLElementEventMap,
52
- KM extends keyof MediaQueryListEventMap,
53
- T extends HTMLElement | MediaQueryList | void = void,
54
- >(
55
- eventName: KW | KH | KM,
56
- handler: (
57
- event: WindowEventMap[KW] | HTMLElementEventMap[KH] | MediaQueryListEventMap[KM] | Event,
58
- ) => void,
59
- element?: RefObject<T>,
60
- options?: boolean | AddEventListenerOptions,
61
- ): void {
62
- // Create a ref that stores handler
63
- const savedHandler = useRef(handler)
64
-
65
- useIsomorphicLayoutEffect(() => {
66
- savedHandler.current = handler
67
- }, [handler])
68
-
69
- useEffect(() => {
70
- // Define the listening target
71
- const targetElement: T | Window = element?.current ?? window
72
-
73
- if (!(targetElement && targetElement.addEventListener)) return
74
-
75
- // Create event listener that calls handler function stored in ref
76
- const listener: typeof handler = event => savedHandler.current(event)
77
-
78
- targetElement.addEventListener(eventName, listener, options)
79
-
80
- // Remove event listener on cleanup
81
- return () => {
82
- targetElement.removeEventListener(eventName, listener, options)
83
- }
84
- }, [eventName, element, options])
85
- }
86
-
87
- export { useEventListener }
@@ -1,62 +0,0 @@
1
- interface Value {
2
- node: HTMLElement
3
- ariaHidden: string | null
4
- }
5
-
6
- /*
7
-
8
-
9
-
10
-
11
- */
12
-
13
- const createAriaHider = (
14
- containerNode: HTMLElement,
15
- selector: string = "body > :not(script)",
16
- ): (() => void) => {
17
- const id = `tribe-${Math.random().toString(36).slice(2, 11)}`
18
-
19
- const rootNodes: (Value | undefined)[] = Array.from<HTMLElement>(
20
- document?.querySelectorAll(selector),
21
- ).map(node => {
22
- if (node?.shadowRoot?.contains(containerNode) || node.contains(containerNode)) {
23
- return undefined
24
- }
25
-
26
- const ariaHidden = node.getAttribute("aria-hidden")
27
- const prevAriaHidden = node.getAttribute("data-hidden")
28
- const prevFocusId = node.getAttribute("data-focus-id")
29
-
30
- node.setAttribute("data-focus-id", id)
31
-
32
- if (ariaHidden === null || ariaHidden === "false") {
33
- node.setAttribute("aria-hidden", "true")
34
- } else if (!prevAriaHidden && !prevFocusId) {
35
- node.setAttribute("data-hidden", ariaHidden)
36
- }
37
-
38
- return {
39
- node,
40
- ariaHidden: prevAriaHidden || null,
41
- }
42
- })
43
-
44
- return () => {
45
- rootNodes.forEach(item => {
46
- if (!item || id !== item.node.getAttribute("data-focus-id")) {
47
- return
48
- }
49
-
50
- if (item.ariaHidden === null) {
51
- item.node.removeAttribute("aria-hidden")
52
- } else {
53
- item.node.setAttribute("aria-hidden", item.ariaHidden)
54
- }
55
-
56
- item.node.removeAttribute("data-focus-id")
57
- item.node.removeAttribute("data-hidden")
58
- })
59
- }
60
- }
61
-
62
- export { createAriaHider }
@@ -1 +0,0 @@
1
- export { useFocusTrap } from "./useFocusTrap"