@bronzelabs/oakma-ui 0.0.1

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 (121) hide show
  1. package/.prettierrc.cjs +25 -0
  2. package/.storybook/components/ActionButton.tsx +44 -0
  3. package/.storybook/components/DummyIcons.tsx +47 -0
  4. package/.storybook/components/index.ts +2 -0
  5. package/.storybook/docs/blocks/ImportStatement.tsx +52 -0
  6. package/.storybook/docs/blocks/index.ts +1 -0
  7. package/.storybook/docs/page.tsx +41 -0
  8. package/.storybook/main.ts +21 -0
  9. package/.storybook/postcss.config.cjs +8 -0
  10. package/.storybook/preview-body.html +20 -0
  11. package/.storybook/preview-head.html +6 -0
  12. package/.storybook/preview.tsx +30 -0
  13. package/.storybook/tailwind.css +6 -0
  14. package/.storybook/utils/index.ts +2 -0
  15. package/.storybook/utils/renderAsReact.tsx +30 -0
  16. package/.storybook/utils/renderDocsWithProps.tsx +22 -0
  17. package/@types/markdown.d.ts +4 -0
  18. package/README.md +3 -0
  19. package/eslint.config.js +91 -0
  20. package/package.json +63 -0
  21. package/postcss.config.cjs +8 -0
  22. package/scripts/release.sh +76 -0
  23. package/src/components/Button/Button.stories.tsx +314 -0
  24. package/src/components/Button/Button.tsx +132 -0
  25. package/src/components/Button/index.ts +2 -0
  26. package/src/components/Button/types.ts +19 -0
  27. package/src/components/Checkbox/Checkbox.stories.tsx +152 -0
  28. package/src/components/Checkbox/Checkbox.tsx +90 -0
  29. package/src/components/Checkbox/index.ts +2 -0
  30. package/src/components/Checkbox/types.ts +6 -0
  31. package/src/components/Chip/Chip.stories.tsx +146 -0
  32. package/src/components/Chip/Chip.tsx +59 -0
  33. package/src/components/Chip/index.ts +2 -0
  34. package/src/components/Chip/types.ts +6 -0
  35. package/src/components/Drawer/Drawer.docs.md +88 -0
  36. package/src/components/Drawer/Drawer.stories.tsx +239 -0
  37. package/src/components/Drawer/Drawer.tsx +194 -0
  38. package/src/components/Drawer/index.ts +3 -0
  39. package/src/components/Drawer/types.ts +3 -0
  40. package/src/components/Dropdown/AsyncDropdown.tsx +105 -0
  41. package/src/components/Dropdown/Dropdown.docs.md +33 -0
  42. package/src/components/Dropdown/Dropdown.stories.tsx +419 -0
  43. package/src/components/Dropdown/Dropdown.tsx +104 -0
  44. package/src/components/Dropdown/MultiValue.tsx +19 -0
  45. package/src/components/Dropdown/ValueContainer.tsx +114 -0
  46. package/src/components/Dropdown/index.ts +4 -0
  47. package/src/components/Dropdown/types.ts +29 -0
  48. package/src/components/Dropdown/useDropdown.tsx +257 -0
  49. package/src/components/Logo/Logo.stories.tsx +130 -0
  50. package/src/components/Logo/Logo.tsx +80 -0
  51. package/src/components/Logo/index.ts +2 -0
  52. package/src/components/Modal/Modal.docs.md +94 -0
  53. package/src/components/Modal/Modal.stories.tsx +318 -0
  54. package/src/components/Modal/Modal.tsx +217 -0
  55. package/src/components/Modal/index.ts +1 -0
  56. package/src/components/MultiSelect/AsyncMultiSelect.tsx +47 -0
  57. package/src/components/MultiSelect/MultiSelect.docs.md +37 -0
  58. package/src/components/MultiSelect/MultiSelect.stories.tsx +493 -0
  59. package/src/components/MultiSelect/MultiSelect.tsx +81 -0
  60. package/src/components/MultiSelect/index.ts +2 -0
  61. package/src/components/Notification/Notification.stories.tsx +158 -0
  62. package/src/components/Notification/Notification.tsx +110 -0
  63. package/src/components/Notification/index.ts +1 -0
  64. package/src/components/Notification/types.ts +11 -0
  65. package/src/components/Notifications/Notifications.docs.md +103 -0
  66. package/src/components/Notifications/Notifications.stories.tsx +159 -0
  67. package/src/components/Notifications/Notifications.tsx +90 -0
  68. package/src/components/Notifications/NotificationsContext.tsx +90 -0
  69. package/src/components/Notifications/index.ts +7 -0
  70. package/src/components/Select/Select.stories.tsx +234 -0
  71. package/src/components/Select/Select.tsx +129 -0
  72. package/src/components/Select/index.ts +2 -0
  73. package/src/components/Select/types.ts +1 -0
  74. package/src/components/Spinner/Spinner.stories.tsx +55 -0
  75. package/src/components/Spinner/Spinner.tsx +48 -0
  76. package/src/components/Spinner/index.ts +2 -0
  77. package/src/components/Spinner/types.ts +8 -0
  78. package/src/components/TextArea/TextArea.stories.tsx +243 -0
  79. package/src/components/TextArea/TextArea.tsx +133 -0
  80. package/src/components/TextArea/index.ts +2 -0
  81. package/src/components/TextArea/types.ts +4 -0
  82. package/src/components/TextField/Container.tsx +68 -0
  83. package/src/components/TextField/ErrorMessage.tsx +37 -0
  84. package/src/components/TextField/Icon.tsx +77 -0
  85. package/src/components/TextField/Label.tsx +56 -0
  86. package/src/components/TextField/NotchBorder.tsx +67 -0
  87. package/src/components/TextField/index.ts +14 -0
  88. package/src/components/TextField/types.ts +15 -0
  89. package/src/components/TextField/useInputKeyboardFocus.tsx +63 -0
  90. package/src/components/TextInput/TextInput.stories.tsx +384 -0
  91. package/src/components/TextInput/TextInput.tsx +255 -0
  92. package/src/components/TextInput/index.ts +2 -0
  93. package/src/components/TextInput/types.ts +4 -0
  94. package/src/components/Toggle/Toggle.stories.tsx +142 -0
  95. package/src/components/Toggle/Toggle.tsx +69 -0
  96. package/src/components/Toggle/index.ts +1 -0
  97. package/src/hooks/index.ts +6 -0
  98. package/src/hooks/useCombinedRefs.ts +37 -0
  99. package/src/hooks/useEventListener.ts +87 -0
  100. package/src/hooks/useFocusTrap/createAriaHider.ts +62 -0
  101. package/src/hooks/useFocusTrap/index.ts +1 -0
  102. package/src/hooks/useFocusTrap/scopeTab.ts +46 -0
  103. package/src/hooks/useFocusTrap/tabbable.ts +107 -0
  104. package/src/hooks/useFocusTrap/useFocusTrap.ts +97 -0
  105. package/src/hooks/useIsomorphicLayoutEffect.ts +14 -0
  106. package/src/hooks/useLockBodyScroll.ts +24 -0
  107. package/src/hooks/useOnClickOutside.ts +53 -0
  108. package/src/index.ts +22 -0
  109. package/src/tailwind.css +4 -0
  110. package/src/types/helpers.ts +11 -0
  111. package/src/types/polymorphic.ts +39 -0
  112. package/src/utils/animation/variants.ts +21 -0
  113. package/src/utils/array/index.ts +1 -0
  114. package/src/utils/array/uniqBy.ts +12 -0
  115. package/src/utils/common/index.ts +1 -0
  116. package/src/utils/common/isFunction.ts +17 -0
  117. package/src/utils/react/extractDisplayName.ts +15 -0
  118. package/src/utils/react/index.ts +1 -0
  119. package/tsconfig.json +16 -0
  120. package/tsconfig.production.json +19 -0
  121. package/tsup.config.ts +16 -0
@@ -0,0 +1,46 @@
1
+ // Utils
2
+ import { findTabbableDescendants } from "./tabbable"
3
+
4
+ /*
5
+
6
+
7
+
8
+
9
+ */
10
+
11
+ const scopeTab = (node: HTMLElement, event: KeyboardEvent): void => {
12
+ const tabbable = findTabbableDescendants(node)
13
+ if (!tabbable.length) {
14
+ event.preventDefault()
15
+ return
16
+ }
17
+ const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1]
18
+ const root = node.getRootNode() as unknown as DocumentOrShadowRoot
19
+ let leavingFinalTabbable = finalTabbable === root.activeElement || node === root.activeElement
20
+
21
+ const activeElement = root.activeElement as Element
22
+ const activeElementIsRadio =
23
+ activeElement.tagName === "INPUT" && activeElement.getAttribute("type") === "radio"
24
+ if (activeElementIsRadio) {
25
+ const activeRadioGroup = tabbable.filter(
26
+ element =>
27
+ element.getAttribute("type") === "radio" &&
28
+ element.getAttribute("name") === activeElement.getAttribute("name"),
29
+ )
30
+ leavingFinalTabbable = activeRadioGroup.includes(finalTabbable)
31
+ }
32
+
33
+ if (!leavingFinalTabbable) {
34
+ return
35
+ }
36
+
37
+ event.preventDefault()
38
+
39
+ const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0]
40
+
41
+ if (target) {
42
+ target.focus()
43
+ }
44
+ }
45
+
46
+ export { scopeTab }
@@ -0,0 +1,107 @@
1
+ // Constants
2
+ const TABBABLE_NODES = /input|select|textarea|button|object/
3
+ const FOCUS_SELECTOR = "a, input, select, textarea, button, object, [tabindex]"
4
+
5
+ /*
6
+
7
+
8
+
9
+
10
+ */
11
+
12
+ /**
13
+ * Retruns true if the given element is hidden (has `display: none;`).
14
+ *
15
+ * @param {HTMLElement} element
16
+ * @returns {boolean}
17
+ */
18
+ const hidden = (element: HTMLElement): boolean => {
19
+ return element.style.display === "none"
20
+ }
21
+
22
+ /**
23
+ * Returns true if the given element is visible.
24
+ *
25
+ * @param {HTMLElement} element
26
+ * @returns {boolean}
27
+ */
28
+ const visible = (element: HTMLElement): boolean => {
29
+ const isHidden =
30
+ element.getAttribute("aria-hidden") ||
31
+ element.getAttribute("hidden") ||
32
+ element.getAttribute("type") === "hidden"
33
+
34
+ if (isHidden) {
35
+ return false
36
+ }
37
+
38
+ let parentElement: HTMLElement = element
39
+ while (parentElement) {
40
+ if (parentElement === document.body || parentElement.nodeType === 11) {
41
+ break
42
+ }
43
+
44
+ if (hidden(parentElement)) {
45
+ return false
46
+ }
47
+
48
+ parentElement = parentElement.parentNode as HTMLElement
49
+ }
50
+
51
+ return true
52
+ }
53
+
54
+ /**
55
+ * Gets the tab index of the given element.
56
+ *
57
+ * @param {HTMLElement} element
58
+ * @returns {number}
59
+ */
60
+ const getElementTabIndex = (element: HTMLElement): number => {
61
+ let tabIndex: string | null | undefined = element.getAttribute("tabindex")
62
+ if (tabIndex === null) {
63
+ tabIndex = undefined
64
+ }
65
+ return parseInt(tabIndex as string, 10)
66
+ }
67
+
68
+ /**
69
+ * Returns true of the given element is able to receive focus.
70
+ *
71
+ * @param {HTMLElement} element
72
+ * @returns {boolean}
73
+ */
74
+ const focusable = (element: HTMLElement): boolean => {
75
+ const nodeName = element.nodeName.toLowerCase()
76
+ const isTabIndexNotNaN = !Number.isNaN(getElementTabIndex(element))
77
+ const res =
78
+ // @ts-ignore
79
+ (TABBABLE_NODES.test(nodeName) && !element.disabled) ||
80
+ (element instanceof HTMLAnchorElement ? element.href || isTabIndexNotNaN : isTabIndexNotNaN)
81
+
82
+ return !!(res && visible(element))
83
+ }
84
+
85
+ /**
86
+ * Returns true of the given element is able to be tabbed.
87
+ *
88
+ * @param {HTMLElement} element
89
+ * @returns {boolean}
90
+ */
91
+ const tabbable = (element: HTMLElement): boolean => {
92
+ const tabIndex = getElementTabIndex(element)
93
+ const isTabIndexNaN = Number.isNaN(tabIndex)
94
+ return (isTabIndexNaN || tabIndex >= 0) && focusable(element)
95
+ }
96
+
97
+ /**
98
+ * Retreives an array of tabbable HTMLElements that are children of the given element.
99
+ *
100
+ * @param {HTMLElement} element
101
+ * @returns {HTMLElement[]}
102
+ */
103
+ const findTabbableDescendants = (element: HTMLElement): HTMLElement[] => {
104
+ return Array.from(element.querySelectorAll<HTMLElement>(FOCUS_SELECTOR)).filter(tabbable)
105
+ }
106
+
107
+ export { FOCUS_SELECTOR, focusable, tabbable, findTabbableDescendants }
@@ -0,0 +1,97 @@
1
+ import { useCallback, useEffect, useRef } from "react"
2
+ import { FOCUS_SELECTOR, focusable, tabbable } from "./tabbable"
3
+ import { scopeTab } from "./scopeTab"
4
+ import { createAriaHider } from "./createAriaHider"
5
+
6
+ /*
7
+
8
+
9
+
10
+
11
+ */
12
+
13
+ const useFocusTrap = <T extends HTMLElement = HTMLElement>(
14
+ isActive = true,
15
+ ): ((instance: T | null) => void) => {
16
+ const ref = useRef<T | null>(null)
17
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
18
+ const restoreAria = useRef<Function | null>(null)
19
+
20
+ const focusNode = (node: HTMLElement): void => {
21
+ let focusElement: HTMLElement | null = node.querySelector("[data-autofocus]")
22
+
23
+ if (!focusElement) {
24
+ const children = Array.from<HTMLElement>(node.querySelectorAll(FOCUS_SELECTOR))
25
+ focusElement = children.find(tabbable) || children.find(focusable) || null
26
+ if (!focusElement && focusable(node)) focusElement = node
27
+ }
28
+
29
+ if (focusElement) {
30
+ focusElement.focus({ preventScroll: true })
31
+ }
32
+ }
33
+
34
+ const setRef = useCallback(
35
+ (node: T | null) => {
36
+ if (!isActive) {
37
+ return
38
+ }
39
+
40
+ if (node === null) {
41
+ if (restoreAria.current) {
42
+ restoreAria.current()
43
+ restoreAria.current = null
44
+ }
45
+ return
46
+ }
47
+
48
+ restoreAria.current = createAriaHider(node)
49
+ if (ref.current === node) {
50
+ return
51
+ }
52
+
53
+ if (node) {
54
+ // Delay processing the HTML node by a frame. This ensures focus is assigned correctly.
55
+ setTimeout(() => {
56
+ if (node.getRootNode()) {
57
+ focusNode(node)
58
+ }
59
+ })
60
+
61
+ ref.current = node
62
+ } else {
63
+ ref.current = null
64
+ }
65
+ },
66
+ [isActive],
67
+ )
68
+
69
+ useEffect(() => {
70
+ if (!isActive) {
71
+ return undefined
72
+ }
73
+
74
+ if (ref.current) {
75
+ setTimeout(() => focusNode(ref.current!))
76
+ }
77
+
78
+ const handleKeyDown = (event: KeyboardEvent): void => {
79
+ if (event.key === "Tab" && ref.current) {
80
+ scopeTab(ref.current, event)
81
+ }
82
+ }
83
+
84
+ document.addEventListener("keydown", handleKeyDown)
85
+ return () => {
86
+ document.removeEventListener("keydown", handleKeyDown)
87
+
88
+ if (restoreAria.current) {
89
+ restoreAria.current()
90
+ }
91
+ }
92
+ }, [isActive])
93
+
94
+ return setRef
95
+ }
96
+
97
+ export { useFocusTrap }
@@ -0,0 +1,14 @@
1
+ "use client"
2
+
3
+ import { useEffect, useLayoutEffect } from "react"
4
+
5
+ /*
6
+
7
+
8
+
9
+
10
+ */
11
+
12
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect
13
+
14
+ export { useIsomorphicLayoutEffect }
@@ -0,0 +1,24 @@
1
+ "use client"
2
+
3
+ // Utils
4
+ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect"
5
+
6
+ /*
7
+
8
+
9
+
10
+
11
+
12
+ */
13
+
14
+ export function useLockBodyScroll(lock: boolean = true): void {
15
+ useIsomorphicLayoutEffect(() => {
16
+ if (!lock) return
17
+
18
+ const previousValue = document.body.style.overflow
19
+ document.body.style.overflow = "hidden"
20
+ return () => {
21
+ document.body.style.overflow = previousValue
22
+ }
23
+ }, [lock])
24
+ }
@@ -0,0 +1,53 @@
1
+ import { RefObject } from "react"
2
+
3
+ // Utils
4
+ import { useEventListener } from "./useEventListener"
5
+
6
+ // Types
7
+ type Handler = (event: MouseEvent) => void
8
+
9
+ /*
10
+
11
+
12
+
13
+
14
+ */
15
+
16
+ export function useOnClickOutside<T extends HTMLElement | null = HTMLElement>(
17
+ ref: RefObject<T>,
18
+ handler: Handler,
19
+ mouseEvent: "mousedown" | "mouseup" = "mousedown",
20
+ ): void {
21
+ useEventListener(mouseEvent, event => {
22
+ const el = ref?.current
23
+
24
+ // Do nothing if clicking ref's element or descendent elements
25
+ if (!el || el.contains(event.target as Node)) {
26
+ return
27
+ }
28
+
29
+ /**
30
+ * 26/05/25 - not sure if we still need this in Oakma, but leaving it in for now just in case.
31
+ * ---
32
+ *
33
+ * We have to do an annoying dance here to check if the click was on a the
34
+ * clear indicator of a dropdown or multiselect.
35
+ *
36
+ * This is because when one of these components is used within a modal,
37
+ * clicking the clear indicator will close the modal.
38
+ */
39
+ const isDropdownIndicator = (el: any): boolean => {
40
+ if (!(el instanceof HTMLElement)) return false
41
+ return Array.from(el?.classList).some(className => className?.endsWith("-indicatorContainer"))
42
+ }
43
+
44
+ if (
45
+ isDropdownIndicator((event.target as HTMLElement)?.parentNode) ||
46
+ isDropdownIndicator((event.target as HTMLElement)?.parentNode?.parentNode)
47
+ ) {
48
+ return
49
+ }
50
+
51
+ handler(event)
52
+ })
53
+ }
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ export { default as Button, type ButtonProps, BUTTON_VARIANTS, type ButtonVariant, BUTTON_SIZES, type ButtonSize } from "./components/Button"
2
+ export { default as Checkbox, type CheckboxProps, CHECKBOX_SIZES, type CheckboxSize } from "./components/Checkbox"
3
+ export { default as Chip, type ChipProps, CHIP_SIZES, type ChipSize } from "./components/Chip"
4
+ export { default as Drawer, type DrawerProps, DRAWER_POSITIONS, type DrawerPosition } from "./components/Drawer"
5
+ export { default as Dropdown, type DropdownProps, AsyncDropdown, type AsyncDropdownProps, type DropdownSize } from "./components/Dropdown"
6
+ export { default as Logo, type LogoProps } from "./components/Logo"
7
+ export { default as Modal, type ModalProps } from "./components/Modal"
8
+ export { default as MultiSelect, type MultiSelectProps, AsyncMultiSelect, type AsyncMultiSelectProps } from "./components/MultiSelect"
9
+ export { default as Notification, type NotificationProps } from "./components/Notification"
10
+ export {
11
+ default as Notifications,
12
+ NotificationsProvider,
13
+ NotificationsContext,
14
+ useNotifications,
15
+ type NotificationsProps,
16
+ type NotificationsContextType,
17
+ } from "./components/Notifications"
18
+ export { default as Select, type SelectProps, type SelectSize } from "./components/Select"
19
+ export { default as Spinner, type SpinnerProps } from "./components/Spinner"
20
+ export { default as TextArea, type TextAreaProps, type TextAreaSize } from "./components/TextArea"
21
+ export { default as TextInput, type TextInputProps, type TextInputSize } from "./components/TextInput"
22
+ export { default as Toggle, type ToggleProps } from "./components/Toggle"
@@ -0,0 +1,4 @@
1
+ @import "tailwindcss";
2
+ @import "@bronzelabs/oakma-tailwind-preset";
3
+
4
+ @source not "./**/*.stories.tsx";
@@ -0,0 +1,11 @@
1
+ /*
2
+
3
+
4
+
5
+
6
+
7
+ */
8
+
9
+ export type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
10
+
11
+ export type SingleOrArray<T> = T | T[]
@@ -0,0 +1,39 @@
1
+ import React from "react"
2
+
3
+ /*
4
+
5
+
6
+
7
+
8
+ */
9
+
10
+ type AsProp<C extends React.ElementType> = {
11
+ /** The type of element to render the component as. */
12
+ as?: C
13
+ }
14
+
15
+ type PropsToOmit<C extends React.ElementType, P> = keyof (AsProp<C> & P)
16
+
17
+ /**
18
+ * @template {React.ElementType} C Component
19
+ * @template {object} P Props
20
+ */
21
+ export type PolymorphicComponentProps<
22
+ C extends React.ElementType,
23
+ P = object,
24
+ > = React.PropsWithChildren<P & AsProp<C>> &
25
+ Omit<React.ComponentPropsWithoutRef<C>, PropsToOmit<C, P>>
26
+
27
+ /**
28
+ * @template {React.ElementType} C Components
29
+ * @template {object} P Props
30
+ */
31
+ export type PolymorphicComponentPropsWithRef<
32
+ C extends React.ElementType,
33
+ P = object,
34
+ > = PolymorphicComponentProps<C, P> & { ref?: PolymorphicRef<C> }
35
+
36
+ /**
37
+ * @template {React.ElementType} C Component
38
+ */
39
+ export type PolymorphicRef<C extends React.ElementType> = React.ComponentPropsWithRef<C>["ref"]
@@ -0,0 +1,21 @@
1
+ import type { Variants } from "motion"
2
+
3
+ /*
4
+
5
+
6
+
7
+
8
+
9
+ */
10
+
11
+ export const backdropVariants: Variants = {
12
+ hidden: {
13
+ opacity: 0,
14
+ transition: {
15
+ duration: 0.1,
16
+ },
17
+ },
18
+ visible: {
19
+ opacity: 1,
20
+ },
21
+ }
@@ -0,0 +1 @@
1
+ export { uniqBy } from "./uniqBy"
@@ -0,0 +1,12 @@
1
+ const uniqBy = <T>(array: T[], iteratee: ((item: T) => unknown) | keyof T): T[] => {
2
+ const getKey = typeof iteratee === "function" ? iteratee : (item: T) => item[iteratee]
3
+ const seen = new Set()
4
+ return array.filter(item => {
5
+ const key = getKey(item)
6
+ if (seen.has(key)) return false
7
+ seen.add(key)
8
+ return true
9
+ })
10
+ }
11
+
12
+ export { uniqBy }
@@ -0,0 +1 @@
1
+ export { isFunction } from "./isFunction"
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Type guard that checks if a given value is a function
3
+ *
4
+ * @param {any} value
5
+ * @returns {boolean}
6
+ */
7
+
8
+ /*
9
+
10
+
11
+
12
+
13
+ */
14
+
15
+ const isFunction = (value: any): value is (...args: any[]) => any => typeof value === "function"
16
+
17
+ export { isFunction }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * extractDisplayName
3
+ *
4
+ * @param {React.FC} type
5
+ * @returns {string}
6
+ */
7
+
8
+ /*
9
+ */
10
+
11
+ const extractDisplayName = (type: any): string => {
12
+ return type.displayName || type.name || "unknown"
13
+ }
14
+
15
+ export { extractDisplayName }
@@ -0,0 +1 @@
1
+ export { extractDisplayName } from "./extractDisplayName"
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true
13
+ },
14
+ "include": ["src", "@types"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
5
+ "module": "esnext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "declaration": true,
9
+ "declarationDir": "dist",
10
+ "emitDeclarationOnly": true,
11
+ "isolatedModules": true,
12
+ "strict": true,
13
+ "skipLibCheck": true,
14
+ "esModuleInterop": true,
15
+ "ignoreDeprecations": "6.0" // tsup injects baseUrl:"." internally — remove when tsup fixes it
16
+ },
17
+ "include": ["src"],
18
+ "exclude": ["dist", "node_modules", "**/*.spec.tsx", "**/*.stories.tsx"]
19
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from "tsup"
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ splitting: false,
6
+ sourcemap: false,
7
+ minify: true,
8
+ clean: true,
9
+ external: ["react", "react-dom"],
10
+ format: ["esm"],
11
+ dts: {
12
+ resolve: true,
13
+ },
14
+ tsconfig: "./tsconfig.production.json",
15
+ // banner: { js: `"use client";` },
16
+ })