@stack-spot/citric-react 0.35.1 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/dist/citric.css +2844 -2832
  2. package/dist/components/Accordion.d.ts +1 -1
  3. package/dist/components/Accordion.js +1 -1
  4. package/dist/components/Alert.d.ts +1 -1
  5. package/dist/components/Alert.js +1 -1
  6. package/dist/components/AsyncContent.d.ts +1 -1
  7. package/dist/components/AsyncContent.js +1 -1
  8. package/dist/components/Avatar.d.ts +1 -1
  9. package/dist/components/Avatar.js +1 -1
  10. package/dist/components/AvatarGroup.d.ts +1 -1
  11. package/dist/components/AvatarGroup.js +1 -1
  12. package/dist/components/Badge.d.ts +1 -1
  13. package/dist/components/Badge.js +1 -1
  14. package/dist/components/Blockquote.d.ts +1 -1
  15. package/dist/components/Blockquote.js +1 -1
  16. package/dist/components/Breadcrumb.d.ts +1 -1
  17. package/dist/components/Breadcrumb.js +1 -1
  18. package/dist/components/Button.d.ts +1 -1
  19. package/dist/components/Button.js +1 -1
  20. package/dist/components/ButtonLink.d.ts +1 -1
  21. package/dist/components/ButtonLink.js +1 -1
  22. package/dist/components/Card.d.ts +1 -1
  23. package/dist/components/Card.js +1 -1
  24. package/dist/components/Checkbox.d.ts +1 -1
  25. package/dist/components/Checkbox.js +1 -1
  26. package/dist/components/CheckboxGroup.d.ts +1 -1
  27. package/dist/components/CheckboxGroup.js +1 -1
  28. package/dist/components/Circle.d.ts +1 -1
  29. package/dist/components/Circle.js +1 -1
  30. package/dist/components/Divider.d.ts +1 -1
  31. package/dist/components/Divider.js +1 -1
  32. package/dist/components/ErrorBoundary.d.ts +1 -1
  33. package/dist/components/ErrorBoundary.js +1 -1
  34. package/dist/components/ErrorMessage.d.ts +1 -1
  35. package/dist/components/ErrorMessage.js +1 -1
  36. package/dist/components/FallbackBoundary.d.ts +1 -1
  37. package/dist/components/FallbackBoundary.js +1 -1
  38. package/dist/components/Favorite.d.ts +1 -1
  39. package/dist/components/Favorite.js +1 -1
  40. package/dist/components/FieldGroup.d.ts +1 -1
  41. package/dist/components/FieldGroup.js +1 -1
  42. package/dist/components/Form.d.ts +2 -2
  43. package/dist/components/Form.js +1 -1
  44. package/dist/components/FormGroup.d.ts +1 -1
  45. package/dist/components/FormGroup.js +1 -1
  46. package/dist/components/Icon.d.ts +1 -1
  47. package/dist/components/Icon.js +1 -1
  48. package/dist/components/IconBox.d.ts +3 -3
  49. package/dist/components/IconBox.js +1 -1
  50. package/dist/components/ImageBox.d.ts +3 -3
  51. package/dist/components/ImageBox.js +1 -1
  52. package/dist/components/ImageWithFallback.d.ts +1 -1
  53. package/dist/components/ImageWithFallback.js +1 -1
  54. package/dist/components/Input.d.ts +1 -1
  55. package/dist/components/Input.js +1 -1
  56. package/dist/components/Link.d.ts +1 -1
  57. package/dist/components/Link.js +1 -1
  58. package/dist/components/LoadingPanel.d.ts +1 -1
  59. package/dist/components/LoadingPanel.js +1 -1
  60. package/dist/components/MenuOverlay/Menu.d.ts +1 -1
  61. package/dist/components/MenuOverlay/Menu.js +1 -1
  62. package/dist/components/MenuOverlay/index.d.ts +1 -1
  63. package/dist/components/MenuOverlay/index.js +1 -1
  64. package/dist/components/Overlay/index.d.ts +1 -1
  65. package/dist/components/Overlay/index.js +1 -1
  66. package/dist/components/Pagination.d.ts +1 -1
  67. package/dist/components/Pagination.js +1 -1
  68. package/dist/components/ProgressBar.d.ts +1 -1
  69. package/dist/components/ProgressBar.js +1 -1
  70. package/dist/components/ProgressCircular.d.ts +1 -1
  71. package/dist/components/ProgressCircular.js +1 -1
  72. package/dist/components/RadioGroup.d.ts +1 -1
  73. package/dist/components/RadioGroup.js +1 -1
  74. package/dist/components/Rating.d.ts +17 -3
  75. package/dist/components/Rating.d.ts.map +1 -1
  76. package/dist/components/Rating.js +11 -3
  77. package/dist/components/Rating.js.map +1 -1
  78. package/dist/components/Select/MultiSelect.d.ts +1 -1
  79. package/dist/components/Select/MultiSelect.js +1 -1
  80. package/dist/components/Select/RichSelect.d.ts +1 -1
  81. package/dist/components/Select/RichSelect.js +1 -1
  82. package/dist/components/Select/SimpleSelect.d.ts +1 -1
  83. package/dist/components/Select/SimpleSelect.js +1 -1
  84. package/dist/components/Select/index.d.ts +1 -1
  85. package/dist/components/Select/index.js +1 -1
  86. package/dist/components/SelectBox.d.ts +1 -1
  87. package/dist/components/SelectBox.js +1 -1
  88. package/dist/components/Skeleton.d.ts +1 -1
  89. package/dist/components/Skeleton.js +1 -1
  90. package/dist/components/Slider.d.ts +1 -1
  91. package/dist/components/Slider.js +1 -1
  92. package/dist/components/SmartTable.d.ts +1 -1
  93. package/dist/components/SmartTable.js +1 -1
  94. package/dist/components/Stepper.d.ts +1 -1
  95. package/dist/components/Stepper.js +1 -1
  96. package/dist/components/Table.d.ts +3 -3
  97. package/dist/components/Table.js +1 -1
  98. package/dist/components/Tabs/index.d.ts +1 -1
  99. package/dist/components/Tabs/index.js +1 -1
  100. package/dist/components/Textarea.d.ts +1 -1
  101. package/dist/components/Textarea.js +1 -1
  102. package/dist/components/Tooltip.d.ts +1 -1
  103. package/dist/components/Tooltip.js +1 -1
  104. package/dist/context/CitricProvider.d.ts +1 -1
  105. package/dist/context/CitricProvider.js +1 -1
  106. package/dist/overlay.js +1 -1
  107. package/dist/theme.css +415 -415
  108. package/package.json +7 -6
  109. package/scripts/build-css.ts +49 -49
  110. package/src/components/Accordion.tsx +130 -130
  111. package/src/components/Alert.tsx +24 -24
  112. package/src/components/AsyncContent.tsx +70 -70
  113. package/src/components/Avatar.tsx +45 -45
  114. package/src/components/AvatarGroup.tsx +49 -49
  115. package/src/components/Badge.tsx +47 -47
  116. package/src/components/Blockquote.tsx +18 -18
  117. package/src/components/Breadcrumb.tsx +33 -33
  118. package/src/components/Button.tsx +105 -105
  119. package/src/components/ButtonLink.tsx +45 -45
  120. package/src/components/Card.tsx +68 -68
  121. package/src/components/Checkbox.tsx +51 -51
  122. package/src/components/CheckboxGroup.tsx +152 -152
  123. package/src/components/Circle.tsx +43 -43
  124. package/src/components/CitricComponent.ts +47 -47
  125. package/src/components/Divider.tsx +24 -24
  126. package/src/components/ErrorBoundary.tsx +75 -75
  127. package/src/components/ErrorMessage.tsx +11 -11
  128. package/src/components/FallbackBoundary.tsx +40 -40
  129. package/src/components/Favorite.tsx +57 -57
  130. package/src/components/FieldGroup.tsx +46 -46
  131. package/src/components/Form.tsx +36 -36
  132. package/src/components/FormGroup.tsx +57 -57
  133. package/src/components/Icon.tsx +35 -35
  134. package/src/components/IconBox.tsx +134 -134
  135. package/src/components/ImageBox.tsx +125 -125
  136. package/src/components/ImageWithFallback.tsx +65 -65
  137. package/src/components/Input.tsx +49 -49
  138. package/src/components/Link.tsx +55 -55
  139. package/src/components/LoadingPanel.tsx +8 -8
  140. package/src/components/MenuOverlay/Menu.tsx +158 -158
  141. package/src/components/MenuOverlay/context.ts +20 -20
  142. package/src/components/MenuOverlay/index.tsx +55 -55
  143. package/src/components/MenuOverlay/keyboard.ts +60 -60
  144. package/src/components/MenuOverlay/types.ts +171 -171
  145. package/src/components/Overlay/context.ts +10 -10
  146. package/src/components/Overlay/index.tsx +164 -164
  147. package/src/components/Overlay/types.ts +70 -70
  148. package/src/components/Pagination.tsx +113 -113
  149. package/src/components/ProgressBar.tsx +45 -45
  150. package/src/components/ProgressCircular.tsx +45 -45
  151. package/src/components/RadioGroup.tsx +146 -146
  152. package/src/components/Rating.tsx +98 -35
  153. package/src/components/Select/MultiSelect.tsx +217 -217
  154. package/src/components/Select/RichSelect.tsx +128 -128
  155. package/src/components/Select/SimpleSelect.tsx +73 -73
  156. package/src/components/Select/hooks.ts +133 -133
  157. package/src/components/Select/index.tsx +35 -35
  158. package/src/components/Select/types.ts +134 -134
  159. package/src/components/SelectBox.tsx +167 -167
  160. package/src/components/Skeleton.tsx +53 -53
  161. package/src/components/Slider.tsx +89 -89
  162. package/src/components/SmartTable.tsx +227 -227
  163. package/src/components/Stepper.tsx +163 -163
  164. package/src/components/Table.tsx +234 -234
  165. package/src/components/Tabs/TabController.ts +54 -54
  166. package/src/components/Tabs/index.tsx +87 -87
  167. package/src/components/Tabs/types.ts +54 -54
  168. package/src/components/Tabs/utils.ts +6 -6
  169. package/src/components/Text.ts +111 -111
  170. package/src/components/Textarea.tsx +27 -27
  171. package/src/components/Tooltip.tsx +72 -72
  172. package/src/components/layout.tsx +101 -101
  173. package/src/context/CitricContext.tsx +4 -4
  174. package/src/context/CitricProvider.tsx +14 -14
  175. package/src/context/hooks.ts +6 -6
  176. package/src/index.ts +58 -58
  177. package/src/overlay.ts +341 -341
  178. package/src/types.ts +216 -216
  179. package/src/utils/ValueController.ts +28 -28
  180. package/src/utils/acessibility.ts +92 -92
  181. package/src/utils/checkbox.ts +121 -121
  182. package/src/utils/css.ts +119 -119
  183. package/src/utils/options.ts +9 -9
  184. package/src/utils/radio.ts +93 -93
  185. package/src/utils/react.ts +6 -6
  186. package/tsconfig.json +10 -10
@@ -1,164 +1,164 @@
1
- import { useEffect, useRef } from 'react'
2
- import { showOverlay } from '../../overlay'
3
- import { HTMLTag } from '../../types'
4
- import { focusFirstChild } from '../../utils/acessibility'
5
- import { OverlayProvider } from './context'
6
- import { OverlayController, OverlayProps } from './types'
7
-
8
- /**
9
- * An arbitrary time to wait for the next React render to be performed
10
- */
11
- const arbitraryRenderTime = 20
12
-
13
- /**
14
- * These todos are in order of priority.
15
- *
16
- * TODO: update position when the size changes. Currently, the top position seems out of place whenever the height changes. The same is
17
- * probably true for the left position if the width changes.
18
- * TODO: hoverDelayMS
19
- * TODO: reposition the overlay when it's under a scrollable element other then the body and this element is scrolled.
20
- * TODO: close the overlay when it's under a scrollable element other then the body and the element that triggered the tooltip becomes
21
- * hidden by the scroll.
22
- * TODO: use React Portal to implement overlays. The current implementation will lose every React context in the tree.
23
- */
24
-
25
- /**
26
- * Creates an overlay for the child component. The overlay can be any React element. The overlay can be triggered by "click" or "hover"
27
- * (default).
28
- *
29
- * @example
30
- *
31
- * ```
32
- * const overlay = <Card>Hey, this is my overlay!</Card>
33
- *
34
- * return (
35
- * <Overlay content={overlay} attributes={{ style: { margin: '20px' } }}>
36
- * <Button>Hover to see the overlay</Button>
37
- * </Overlay>
38
- * )
39
- * ```
40
- */
41
- export function Overlay<T extends keyof HTMLTag>({
42
- tag,
43
- children,
44
- content,
45
- position = 'top',
46
- triggerOn = 'hover',
47
- alignment = 'center',
48
- attributes,
49
- onRenderChild,
50
- autoFocusBehavior = 'keyboard',
51
- ...props
52
- }: OverlayProps<T>,
53
- ) {
54
- const controller = useRef<OverlayController>({ close: () => Promise.resolve() })
55
- const wrapper = useRef<HTMLDivElement | null>(null)
56
- // props that don't require removing and reattaching the event listeners
57
- const dynamic = useRef({ tag, content, position, alignment, attributes })
58
-
59
- useEffect(() => {
60
- dynamic.current = { tag, content, position, alignment, attributes }
61
- }, [tag, content, position, alignment, attributes])
62
-
63
- useEffect(() => {
64
- let visible = false
65
- let hideOnClickOutside: ((event: Event) => void) | undefined
66
- let hideOnEsc: ((event: Event) => void) | undefined
67
- let hideOverlay: (() => Promise<void>) | undefined
68
- let removeRefocusTargetListener: (() => void) | undefined
69
-
70
- function getTarget() {
71
- const target = wrapper.current?.firstChild
72
- return target instanceof HTMLElement ? target : undefined
73
- }
74
-
75
- if (onRenderChild) {
76
- const target = getTarget()
77
- if (target) onRenderChild(target)
78
- }
79
-
80
- async function show(event: Event) {
81
- if (visible) return
82
- visible = true
83
- const target = getTarget()
84
- if (!target) return
85
- const { overlay, hide: hideFn } = showOverlay({
86
- tag: dynamic.current.tag,
87
- content: ['string', 'number', 'boolean'].includes(typeof dynamic.current.content)
88
- ? dynamic.current.content
89
- : <OverlayProvider value={controller.current}>{dynamic.current.content}</OverlayProvider>,
90
- target,
91
- position: dynamic.current.position,
92
- alignment: dynamic.current.alignment,
93
- attributes: dynamic.current.attributes,
94
- })
95
- hideOverlay = hideFn
96
-
97
- function onHide(condition: (event: Event) => boolean) {
98
- return (event: Event) => {
99
- if (condition(event)) controller.current.close()
100
- }
101
- }
102
-
103
- if (event.type === 'click') {
104
- hideOnEsc = onHide(e => e instanceof KeyboardEvent && e.key === 'Escape')
105
- setTimeout(() => {
106
- hideOnClickOutside = onHide(e => e instanceof MouseEvent && e.button === 0 && !overlay.contains(e.target as HTMLElement))
107
- document.addEventListener('click', hideOnClickOutside)
108
- }, arbitraryRenderTime)
109
- document.addEventListener('keydown', hideOnEsc)
110
- }
111
-
112
- //focus target when the last overlay element loses focus
113
- function refocusTarget(e: KeyboardEvent) {
114
- if (e.key === 'Tab' && e.target instanceof HTMLElement) {
115
- const allItems = Array.from(e.target.closest('[data-citric="menu"]')?.querySelectorAll('a, button') ?? [])
116
- if (e.target === allItems[allItems.length - 1]) {
117
- getTarget()?.focus()
118
- e.preventDefault()
119
- }
120
- }
121
- }
122
- overlay.addEventListener('keydown', refocusTarget)
123
- removeRefocusTargetListener = () => overlay.removeEventListener('keydown', refocusTarget)
124
-
125
- // auto-focus
126
- const openedWithMouse = event instanceof MouseEvent && event.detail > 0
127
- if (autoFocusBehavior === 'always' || (autoFocusBehavior === 'keyboard' && !openedWithMouse)) {
128
- setTimeout(() => focusFirstChild(overlay), arbitraryRenderTime)
129
- }
130
- }
131
-
132
- controller.current.close = async () => {
133
- visible = false
134
- if (hideOnClickOutside) document.removeEventListener('click', hideOnClickOutside)
135
- if (hideOnEsc) document.removeEventListener('keydown', hideOnEsc)
136
- removeRefocusTargetListener?.()
137
- await hideOverlay?.()
138
- }
139
-
140
- if (triggerOn === 'hover') {
141
- getTarget()?.addEventListener('mouseenter', show)
142
- getTarget()?.addEventListener('mouseleave', controller.current.close)
143
- getTarget()?.addEventListener('focus', show)
144
- getTarget()?.addEventListener('blur', controller.current.close)
145
- return () => {
146
- getTarget()?.removeEventListener('mouseenter', show)
147
- getTarget()?.removeEventListener('mouseleave', controller.current.close)
148
- getTarget()?.removeEventListener('focus', show)
149
- getTarget()?.removeEventListener('blur', controller.current.close)
150
- }
151
- }
152
-
153
- if (triggerOn === 'click') {
154
- getTarget()?.addEventListener('click', show)
155
- return () => {
156
- controller.current.close()
157
- getTarget()?.removeEventListener('click', show)
158
- if (hideOnClickOutside) document.removeEventListener('click', hideOnClickOutside)
159
- }
160
- }
161
- }, [wrapper.current, triggerOn])
162
-
163
- return <div ref={wrapper} {...props}>{children}</div>
164
- }
1
+ import { useEffect, useRef } from 'react'
2
+ import { showOverlay } from '../../overlay'
3
+ import { HTMLTag } from '../../types'
4
+ import { focusFirstChild } from '../../utils/acessibility'
5
+ import { OverlayProvider } from './context'
6
+ import { OverlayController, OverlayProps } from './types'
7
+
8
+ /**
9
+ * An arbitrary time to wait for the next React render to be performed
10
+ */
11
+ const arbitraryRenderTime = 20
12
+
13
+ /**
14
+ * These todos are in order of priority.
15
+ *
16
+ * TODO: update position when the size changes. Currently, the top position seems out of place whenever the height changes. The same is
17
+ * probably true for the left position if the width changes.
18
+ * TODO: hoverDelayMS
19
+ * TODO: reposition the overlay when it's under a scrollable element other then the body and this element is scrolled.
20
+ * TODO: close the overlay when it's under a scrollable element other then the body and the element that triggered the tooltip becomes
21
+ * hidden by the scroll.
22
+ * TODO: use React Portal to implement overlays. The current implementation will lose every React context in the tree.
23
+ */
24
+
25
+ /**
26
+ * Creates an overlay for the child component. The overlay can be any React element. The overlay can be triggered by "click" or "hover"
27
+ * (default).
28
+ *
29
+ * @example
30
+ *
31
+ * ```
32
+ * const overlay = <Card>Hey, this is my overlay!</Card>
33
+ *
34
+ * return (
35
+ * <Overlay content={overlay} attributes={{ style: { margin: '20px' } }}>
36
+ * <Button>Hover to see the overlay</Button>
37
+ * </Overlay>
38
+ * )
39
+ * ```
40
+ */
41
+ export function Overlay<T extends keyof HTMLTag>({
42
+ tag,
43
+ children,
44
+ content,
45
+ position = 'top',
46
+ triggerOn = 'hover',
47
+ alignment = 'center',
48
+ attributes,
49
+ onRenderChild,
50
+ autoFocusBehavior = 'keyboard',
51
+ ...props
52
+ }: OverlayProps<T>,
53
+ ) {
54
+ const controller = useRef<OverlayController>({ close: () => Promise.resolve() })
55
+ const wrapper = useRef<HTMLDivElement | null>(null)
56
+ // props that don't require removing and reattaching the event listeners
57
+ const dynamic = useRef({ tag, content, position, alignment, attributes })
58
+
59
+ useEffect(() => {
60
+ dynamic.current = { tag, content, position, alignment, attributes }
61
+ }, [tag, content, position, alignment, attributes])
62
+
63
+ useEffect(() => {
64
+ let visible = false
65
+ let hideOnClickOutside: ((event: Event) => void) | undefined
66
+ let hideOnEsc: ((event: Event) => void) | undefined
67
+ let hideOverlay: (() => Promise<void>) | undefined
68
+ let removeRefocusTargetListener: (() => void) | undefined
69
+
70
+ function getTarget() {
71
+ const target = wrapper.current?.firstChild
72
+ return target instanceof HTMLElement ? target : undefined
73
+ }
74
+
75
+ if (onRenderChild) {
76
+ const target = getTarget()
77
+ if (target) onRenderChild(target)
78
+ }
79
+
80
+ async function show(event: Event) {
81
+ if (visible) return
82
+ visible = true
83
+ const target = getTarget()
84
+ if (!target) return
85
+ const { overlay, hide: hideFn } = showOverlay({
86
+ tag: dynamic.current.tag,
87
+ content: ['string', 'number', 'boolean'].includes(typeof dynamic.current.content)
88
+ ? dynamic.current.content
89
+ : <OverlayProvider value={controller.current}>{dynamic.current.content}</OverlayProvider>,
90
+ target,
91
+ position: dynamic.current.position,
92
+ alignment: dynamic.current.alignment,
93
+ attributes: dynamic.current.attributes,
94
+ })
95
+ hideOverlay = hideFn
96
+
97
+ function onHide(condition: (event: Event) => boolean) {
98
+ return (event: Event) => {
99
+ if (condition(event)) controller.current.close()
100
+ }
101
+ }
102
+
103
+ if (event.type === 'click') {
104
+ hideOnEsc = onHide(e => e instanceof KeyboardEvent && e.key === 'Escape')
105
+ setTimeout(() => {
106
+ hideOnClickOutside = onHide(e => e instanceof MouseEvent && e.button === 0 && !overlay.contains(e.target as HTMLElement))
107
+ document.addEventListener('click', hideOnClickOutside)
108
+ }, arbitraryRenderTime)
109
+ document.addEventListener('keydown', hideOnEsc)
110
+ }
111
+
112
+ //focus target when the last overlay element loses focus
113
+ function refocusTarget(e: KeyboardEvent) {
114
+ if (e.key === 'Tab' && e.target instanceof HTMLElement) {
115
+ const allItems = Array.from(e.target.closest('[data-citric="menu"]')?.querySelectorAll('a, button') ?? [])
116
+ if (e.target === allItems[allItems.length - 1]) {
117
+ getTarget()?.focus()
118
+ e.preventDefault()
119
+ }
120
+ }
121
+ }
122
+ overlay.addEventListener('keydown', refocusTarget)
123
+ removeRefocusTargetListener = () => overlay.removeEventListener('keydown', refocusTarget)
124
+
125
+ // auto-focus
126
+ const openedWithMouse = event instanceof MouseEvent && event.detail > 0
127
+ if (autoFocusBehavior === 'always' || (autoFocusBehavior === 'keyboard' && !openedWithMouse)) {
128
+ setTimeout(() => focusFirstChild(overlay), arbitraryRenderTime)
129
+ }
130
+ }
131
+
132
+ controller.current.close = async () => {
133
+ visible = false
134
+ if (hideOnClickOutside) document.removeEventListener('click', hideOnClickOutside)
135
+ if (hideOnEsc) document.removeEventListener('keydown', hideOnEsc)
136
+ removeRefocusTargetListener?.()
137
+ await hideOverlay?.()
138
+ }
139
+
140
+ if (triggerOn === 'hover') {
141
+ getTarget()?.addEventListener('mouseenter', show)
142
+ getTarget()?.addEventListener('mouseleave', controller.current.close)
143
+ getTarget()?.addEventListener('focus', show)
144
+ getTarget()?.addEventListener('blur', controller.current.close)
145
+ return () => {
146
+ getTarget()?.removeEventListener('mouseenter', show)
147
+ getTarget()?.removeEventListener('mouseleave', controller.current.close)
148
+ getTarget()?.removeEventListener('focus', show)
149
+ getTarget()?.removeEventListener('blur', controller.current.close)
150
+ }
151
+ }
152
+
153
+ if (triggerOn === 'click') {
154
+ getTarget()?.addEventListener('click', show)
155
+ return () => {
156
+ controller.current.close()
157
+ getTarget()?.removeEventListener('click', show)
158
+ if (hideOnClickOutside) document.removeEventListener('click', hideOnClickOutside)
159
+ }
160
+ }
161
+ }, [wrapper.current, triggerOn])
162
+
163
+ return <div ref={wrapper} {...props}>{children}</div>
164
+ }
@@ -1,70 +1,70 @@
1
- import { OverlayOptions } from '../../overlay'
2
- import { HTMLTag } from '../../types'
3
-
4
- export type TriggerOn = 'hover' | 'click'
5
-
6
- export interface BaseOverlayProps<T extends keyof HTMLTag> extends Omit<OverlayOptions<T>, 'target'> {
7
- /**
8
- * When should the overlay element be created? When the child is clicked or when the child is hovered?
9
- *
10
- * Accessibility:
11
- * Click = focus + press enter to open; focus + enter to close OR esc.
12
- * Hover = focus to open; blur to close.
13
- *
14
- * @default 'hover'
15
- */
16
- triggerOn?: TriggerOn,
17
- /**
18
- * TODO: not implemented yet.
19
- *
20
- * Only valid if `triggerOn` is "hover".
21
- *
22
- * If the overlay is hidden right after the mouse leaves the element, then it becomes impossible to interact with anything inside the
23
- * tooltip. This sets a delay for the overlay to disappear, giving it time for the user to hover the overlay or gocus one of its children,
24
- * which will prevent it from closing.
25
- *
26
- * When `hoverDelayMS` is greater then zero, the hover effect is also applied to the overlay itself instead of just the child element.
27
- *
28
- * When set to "auto", a hover delay of 1 second will be used if the overlay contains any focusable element.
29
- *
30
- * @default 'auto'
31
- */
32
- hoverDelayMS?: number | 'auto',
33
- /**
34
- * TODO: not implemented yet.
35
- *
36
- * - Never: the focus won't changes when the overlay opens.
37
- * - All: the focus always changes when the overlay opens (given there's a focusable element in the overlay).
38
- * - Keyboard (default): the focus only changes when the overlay is opened via the keyboard.
39
- *
40
- * The first focusable element in the overlay will be focused as soon as it's rendered. When it's closed, the child element
41
- * (`children`) regains focus.
42
- *
43
- * The focus control will be such that, after the last element in the overlay is focused, the next focus will move to the child element
44
- * (`children`).
45
- *
46
- * If the overlay has no focusable element, this properties makes no difference.
47
- *
48
- * Attention: focusable elements inside the overlay can be ignored by setting `auto-focus` to false.
49
- *
50
- * @default 'keyboard'
51
- */
52
- autoFocusBehavior?: 'never' | 'always' | 'keyboard',
53
- /**
54
- * The element to receive the overlay.
55
- */
56
- children: React.ReactElement,
57
- /**
58
- * Function to run when the child is rendered. It receives the child element as a parameter.
59
- *
60
- * This is useful for easily adding attributes to the element (mainly accessibility ones).
61
- * @param element the child element, the one that receives the overlay.
62
- */
63
- onRenderChild?: (element: HTMLElement) => void,
64
- }
65
-
66
- export type OverlayProps<T extends keyof HTMLTag> = Omit<React.JSX.IntrinsicElements['div'], 'content'> & BaseOverlayProps<T>
67
-
68
- export interface OverlayController {
69
- close: () => Promise<void>,
70
- }
1
+ import { OverlayOptions } from '../../overlay'
2
+ import { HTMLTag } from '../../types'
3
+
4
+ export type TriggerOn = 'hover' | 'click'
5
+
6
+ export interface BaseOverlayProps<T extends keyof HTMLTag> extends Omit<OverlayOptions<T>, 'target'> {
7
+ /**
8
+ * When should the overlay element be created? When the child is clicked or when the child is hovered?
9
+ *
10
+ * Accessibility:
11
+ * Click = focus + press enter to open; focus + enter to close OR esc.
12
+ * Hover = focus to open; blur to close.
13
+ *
14
+ * @default 'hover'
15
+ */
16
+ triggerOn?: TriggerOn,
17
+ /**
18
+ * TODO: not implemented yet.
19
+ *
20
+ * Only valid if `triggerOn` is "hover".
21
+ *
22
+ * If the overlay is hidden right after the mouse leaves the element, then it becomes impossible to interact with anything inside the
23
+ * tooltip. This sets a delay for the overlay to disappear, giving it time for the user to hover the overlay or gocus one of its children,
24
+ * which will prevent it from closing.
25
+ *
26
+ * When `hoverDelayMS` is greater then zero, the hover effect is also applied to the overlay itself instead of just the child element.
27
+ *
28
+ * When set to "auto", a hover delay of 1 second will be used if the overlay contains any focusable element.
29
+ *
30
+ * @default 'auto'
31
+ */
32
+ hoverDelayMS?: number | 'auto',
33
+ /**
34
+ * TODO: not implemented yet.
35
+ *
36
+ * - Never: the focus won't changes when the overlay opens.
37
+ * - All: the focus always changes when the overlay opens (given there's a focusable element in the overlay).
38
+ * - Keyboard (default): the focus only changes when the overlay is opened via the keyboard.
39
+ *
40
+ * The first focusable element in the overlay will be focused as soon as it's rendered. When it's closed, the child element
41
+ * (`children`) regains focus.
42
+ *
43
+ * The focus control will be such that, after the last element in the overlay is focused, the next focus will move to the child element
44
+ * (`children`).
45
+ *
46
+ * If the overlay has no focusable element, this properties makes no difference.
47
+ *
48
+ * Attention: focusable elements inside the overlay can be ignored by setting `auto-focus` to false.
49
+ *
50
+ * @default 'keyboard'
51
+ */
52
+ autoFocusBehavior?: 'never' | 'always' | 'keyboard',
53
+ /**
54
+ * The element to receive the overlay.
55
+ */
56
+ children: React.ReactElement,
57
+ /**
58
+ * Function to run when the child is rendered. It receives the child element as a parameter.
59
+ *
60
+ * This is useful for easily adding attributes to the element (mainly accessibility ones).
61
+ * @param element the child element, the one that receives the overlay.
62
+ */
63
+ onRenderChild?: (element: HTMLElement) => void,
64
+ }
65
+
66
+ export type OverlayProps<T extends keyof HTMLTag> = Omit<React.JSX.IntrinsicElements['div'], 'content'> & BaseOverlayProps<T>
67
+
68
+ export interface OverlayController {
69
+ close: () => Promise<void>,
70
+ }