@heliosgraphics/ui 2.0.0-alpha.94 → 2.0.0-alpha.96
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.
- package/components/Alert/Alert.tsx +2 -0
- package/components/Breadcrumb/Breadcrumb.tsx +17 -1
- package/components/Browser/Browser.tsx +2 -0
- package/components/Button/Button.tsx +11 -7
- package/components/ButtonGroup/ButtonGroup.tsx +2 -0
- package/components/Checkbox/Checkbox.tsx +66 -55
- package/components/Clock/Clock.tsx +23 -19
- package/components/Column/Column.tsx +2 -0
- package/components/Confirm/Confirm.tsx +2 -0
- package/components/DatePicker/DatePicker.meta.ts +12 -5
- package/components/DatePicker/DatePicker.module.css +70 -1
- package/components/DatePicker/DatePicker.tsx +116 -4
- package/components/DatePicker/DatePicker.types.ts +6 -1
- package/components/DatePicker/DatePicker.utils.ts +53 -0
- package/components/Debug/Debug.tsx +2 -0
- package/components/Details/Details.tsx +2 -0
- package/components/Dialog/Dialog.module.css +48 -40
- package/components/Dialog/Dialog.tsx +23 -58
- package/components/Donut/Donut.tsx +5 -6
- package/components/Dot/Dot.tsx +2 -0
- package/components/Dropdown/Dropdown.module.css +25 -10
- package/components/Dropdown/Dropdown.tsx +22 -29
- package/components/Fieldset/Fieldset.tsx +2 -0
- package/components/Flex/Flex.meta.ts +1 -0
- package/components/Flex/Flex.tsx +23 -2
- package/components/Flex/Flex.types.ts +1 -0
- package/components/Flex/Flex.utils.spec.ts +4 -1
- package/components/Flex/Flex.utils.ts +4 -1
- package/components/Grid/Grid.tsx +2 -0
- package/components/Heading/Heading.meta.ts +5 -0
- package/components/Heading/Heading.tsx +15 -9
- package/components/Heading/Heading.types.ts +1 -0
- package/components/Heading/components/H0/H0.tsx +2 -0
- package/components/Heading/components/H1/H1.tsx +4 -1
- package/components/Heading/components/H2/H2.tsx +4 -1
- package/components/Heading/components/H3/H3.tsx +4 -1
- package/components/Heading/components/H4/H4.tsx +4 -1
- package/components/Heading/components/H5/H5.tsx +4 -1
- package/components/Heading/components/H6/H6.tsx +4 -1
- package/components/Icon/Icon.tsx +2 -0
- package/components/Input/Input.tsx +103 -95
- package/components/Layout/Layout.tsx +2 -0
- package/components/Layout/components/LayoutAside/LayoutAside.tsx +2 -0
- package/components/Layout/components/LayoutAside/components/LayoutAsideContent/LayoutAsideContent.tsx +2 -0
- package/components/Layout/components/LayoutAside/components/LayoutAsideFooter/LayoutAsideFooter.tsx +2 -0
- package/components/Layout/components/LayoutAside/components/LayoutAsideToggle/LayoutAsideToggle.tsx +2 -0
- package/components/Layout/components/LayoutMain/LayoutMain.tsx +2 -0
- package/components/Layout/components/LayoutMain/components/LayoutMainContent/LayoutMainContent.tsx +2 -0
- package/components/Layout/components/LayoutNavigation/LayoutNavigation.tsx +2 -0
- package/components/Layout/components/LayoutSubNavigation/LayoutSubNavigation.tsx +2 -0
- package/components/Loading/Loading.tsx +2 -0
- package/components/Markdown/Markdown.tsx +2 -0
- package/components/Masonry/Masonry.tsx +5 -1
- package/components/Menu/Menu.tsx +2 -0
- package/components/Menu/components/MenuCategory/MenuCategory.tsx +2 -0
- package/components/Menu/components/MenuFilter/MenuFilter.tsx +2 -2
- package/components/Menu/components/MenuItem/MenuItem.tsx +2 -0
- package/components/Overlay/Overlay.module.css +42 -18
- package/components/Overlay/Overlay.tsx +26 -5
- package/components/Pie/Pie.tsx +2 -0
- package/components/Pill/Pill.meta.ts +9 -1
- package/components/Pill/Pill.module.css +11 -0
- package/components/Pill/Pill.tsx +30 -5
- package/components/Pill/Pill.types.ts +2 -0
- package/components/Placeholder/Placeholder.tsx +2 -0
- package/components/Progress/Progress.tsx +2 -0
- package/components/Radio/Radio.tsx +2 -0
- package/components/Range/Range.tsx +2 -0
- package/components/Segments/Segments.context.ts +19 -0
- package/components/Segments/Segments.meta.ts +4 -0
- package/components/Segments/Segments.tsx +34 -42
- package/components/Segments/Segments.types.ts +1 -0
- package/components/Segments/components/SegmentButton/SegmentButton.meta.ts +0 -4
- package/components/Segments/components/SegmentButton/SegmentButton.tsx +28 -2
- package/components/Segments/components/SegmentButton/SegmentButton.types.ts +0 -2
- package/components/Select/Select.tsx +40 -43
- package/components/Separator/Separator.tsx +2 -0
- package/components/Separator/components/HRMarkup/HRMarkup.tsx +2 -0
- package/components/Separator/components/HorizontalSeparator/HorizontalSeparator.tsx +2 -0
- package/components/Separator/components/VerticalSeparator/VerticalSeparator.tsx +2 -0
- package/components/Setup/Setup.tsx +3 -0
- package/components/Shimmer/Shimmer.tsx +2 -0
- package/components/Slider/Slider.tsx +2 -0
- package/components/Spacer/Spacer.tsx +2 -0
- package/components/Table/Table.tsx +2 -0
- package/components/Tabs/Tabs.meta.ts +12 -12
- package/components/Tabs/Tabs.module.css +25 -9
- package/components/Tabs/Tabs.tsx +50 -51
- package/components/Tabs/Tabs.types.ts +10 -3
- package/components/Text/Text.tsx +2 -0
- package/components/Text/components/Div/Div.tsx +4 -1
- package/components/Text/components/Micro/Micro.tsx +4 -1
- package/components/Text/components/P/P.tsx +4 -1
- package/components/Text/components/Small/Small.tsx +4 -1
- package/components/Text/components/Tiny/Tiny.tsx +4 -1
- package/components/Textarea/Textarea.tsx +14 -13
- package/components/Tile/Tile.tsx +2 -0
- package/components/Timestamp/Timestamp.tsx +2 -0
- package/components/Toggle/Toggle.tsx +2 -0
- package/components/Tooltip/Tooltip.module.css +13 -0
- package/components/Tooltip/Tooltip.tsx +19 -11
- package/components/Tooltip/Tooltip.types.ts +0 -1
- package/components/Tooltip/components/TooltipContent/TooltipContent.tsx +4 -0
- package/components/Tooltip/components/TooltipTrigger/TooltipTrigger.tsx +6 -2
- package/components/shared/InputLabel/InputLabel.tsx +2 -0
- package/components/shared/ResultList/ResultList.tsx +7 -5
- package/constants/components.ts +2 -2
- package/constants/meta.ts +9 -9
- package/contexts/LayoutContext/LayoutContext.tsx +15 -34
- package/contexts/LayoutContext/LayoutContext.types.ts +0 -1
- package/hooks/useLayoutContext.tsx +0 -1
- package/index.ts +5 -0
- package/package.json +4 -4
|
@@ -12,23 +12,49 @@
|
|
|
12
12
|
border-radius: var(--radius-lg) 0 0 var(--radius-lg);
|
|
13
13
|
touch-action: pan-y;
|
|
14
14
|
transform: translateX(-50%);
|
|
15
|
+
|
|
16
|
+
opacity: 0;
|
|
17
|
+
transition:
|
|
18
|
+
opacity var(--speed-lg) ease-in-out,
|
|
19
|
+
transform var(--speed-lg) ease-in-out,
|
|
20
|
+
overlay var(--speed-lg) ease-in-out allow-discrete,
|
|
21
|
+
display var(--speed-lg) ease-in-out allow-discrete;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
|
-
.
|
|
18
|
-
|
|
24
|
+
.dialog[open] {
|
|
25
|
+
opacity: 1;
|
|
26
|
+
transform: translateX(-50%);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@starting-style {
|
|
30
|
+
.dialog[open] {
|
|
31
|
+
opacity: 0;
|
|
32
|
+
transform: translateX(-50%) translateY(6px);
|
|
33
|
+
}
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
.
|
|
22
|
-
|
|
36
|
+
.dialogNarrow {
|
|
37
|
+
width: 420px;
|
|
23
38
|
}
|
|
24
39
|
|
|
25
40
|
.dialogCentered {
|
|
26
41
|
top: 50%;
|
|
27
42
|
|
|
28
|
-
animation: dialogCenterFadeIn var(--speed-lg) ease-in-out;
|
|
29
43
|
transform: translateX(-50%) translateY(-50%);
|
|
30
44
|
}
|
|
31
45
|
|
|
46
|
+
.dialogCentered[open] {
|
|
47
|
+
opacity: 1;
|
|
48
|
+
transform: translateX(-50%) translateY(-50%);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@starting-style {
|
|
52
|
+
.dialogCentered[open] {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
transform: translateX(-50%) translateY(calc(-50% + 6px));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
.dialog__content {
|
|
33
59
|
position: relative;
|
|
34
60
|
z-index: var(--z-index-1);
|
|
@@ -48,54 +74,36 @@
|
|
|
48
74
|
.dialog::backdrop {
|
|
49
75
|
--ui-bg-backdrop: rgba(80, 80, 80, 0.5);
|
|
50
76
|
|
|
51
|
-
animation: backdropFadeIn var(--speed-sm) ease-in-out;
|
|
52
77
|
background-color: var(--ui-bg-backdrop);
|
|
53
78
|
backdrop-filter: blur(2px);
|
|
54
|
-
}
|
|
55
79
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.dialog__content {
|
|
62
|
-
padding: 12px;
|
|
63
|
-
}
|
|
80
|
+
opacity: 0;
|
|
81
|
+
transition:
|
|
82
|
+
opacity var(--speed-sm) ease-in-out,
|
|
83
|
+
overlay var(--speed-sm) ease-in-out allow-discrete,
|
|
84
|
+
display var(--speed-sm) ease-in-out allow-discrete;
|
|
64
85
|
}
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
width: calc(100% - 16px);
|
|
69
|
-
}
|
|
87
|
+
.dialog[open]::backdrop {
|
|
88
|
+
opacity: 1;
|
|
70
89
|
}
|
|
71
90
|
|
|
72
|
-
@
|
|
73
|
-
|
|
91
|
+
@starting-style {
|
|
92
|
+
.dialog[open]::backdrop {
|
|
74
93
|
opacity: 0;
|
|
75
|
-
transform: translateX(-50%) translateY(6px);
|
|
76
|
-
}
|
|
77
|
-
100% {
|
|
78
|
-
opacity: 1;
|
|
79
|
-
transform: translateX(-50%) translateY(0);
|
|
80
94
|
}
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
@
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
transform: translateX(-50%) translateY(calc(-50% + 6px));
|
|
87
|
-
}
|
|
88
|
-
100% {
|
|
89
|
-
opacity: 1;
|
|
90
|
-
transform: translateX(-50%) translateY(-50%);
|
|
97
|
+
@media (max-width: 576px) {
|
|
98
|
+
.dialog:not(.dialogCentered) {
|
|
99
|
+
width: calc(100% - 16px);
|
|
91
100
|
}
|
|
92
|
-
}
|
|
93
101
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
opacity: 0;
|
|
102
|
+
.dialogCentered {
|
|
103
|
+
width: calc(100% - 16px);
|
|
97
104
|
}
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
|
|
106
|
+
.dialog__content {
|
|
107
|
+
padding: 12px;
|
|
100
108
|
}
|
|
101
109
|
}
|
|
@@ -9,9 +9,6 @@ import { Flex } from "../Flex"
|
|
|
9
9
|
import { getClasses } from "@heliosgraphics/utils"
|
|
10
10
|
import type { DialogProps } from "./Dialog.types"
|
|
11
11
|
|
|
12
|
-
const ATTRIBUTE_SCROLL = "data-scroll" as const
|
|
13
|
-
const POSITION_FIXED_CLASS = "fixed" as const
|
|
14
|
-
|
|
15
12
|
export const Dialog: FC<DialogProps> = ({
|
|
16
13
|
title,
|
|
17
14
|
children,
|
|
@@ -24,60 +21,25 @@ export const Dialog: FC<DialogProps> = ({
|
|
|
24
21
|
}) => {
|
|
25
22
|
const dialogRef = useRef<HTMLDialogElement | null>(null)
|
|
26
23
|
const triggerRef = useRef<Element | null>(null)
|
|
27
|
-
|
|
28
|
-
const resetScroll = (): void => {
|
|
29
|
-
globalThis?.requestAnimationFrame(() => {
|
|
30
|
-
document.body.setAttribute(ATTRIBUTE_SCROLL, "")
|
|
31
|
-
dialogRef?.current?.scrollTo?.(0, 0)
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const resetDocumentStyle = (scrollPosition: number): void => {
|
|
36
|
-
globalThis?.requestAnimationFrame(() => {
|
|
37
|
-
document.body.style.position = ""
|
|
38
|
-
document.body.style.height = ""
|
|
39
|
-
document.body.style.top = ""
|
|
40
|
-
document.body.classList.remove(POSITION_FIXED_CLASS)
|
|
41
|
-
|
|
42
|
-
return globalThis?.scrollTo?.(0, scrollPosition)
|
|
43
|
-
})
|
|
44
|
-
}
|
|
24
|
+
const onCloseRef = useRef<() => void>(onClose)
|
|
45
25
|
|
|
46
26
|
useEffect(() => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const scrollPosition: number = parseInt(localPos) ?? 0
|
|
50
|
-
|
|
51
|
-
resetDocumentStyle(scrollPosition)
|
|
52
|
-
resetScroll()
|
|
53
|
-
}
|
|
54
|
-
}, [title, isOpen])
|
|
27
|
+
onCloseRef.current = onClose
|
|
28
|
+
}, [onClose])
|
|
55
29
|
|
|
56
30
|
useEffect(() => {
|
|
57
31
|
dialogRef?.current?.scrollTo?.(0, 0)
|
|
58
32
|
|
|
59
33
|
if (isOpen) {
|
|
60
34
|
triggerRef.current = document.activeElement
|
|
35
|
+
document.documentElement.style.overflow = "hidden"
|
|
61
36
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
document.body.classList.add(POSITION_FIXED_CLASS)
|
|
65
|
-
document.body.style.top = `-${localPosition}px`
|
|
66
|
-
document.body.setAttribute(ATTRIBUTE_SCROLL, localPosition.toString())
|
|
67
|
-
|
|
68
|
-
dialogRef?.current?.showModal?.()
|
|
69
|
-
|
|
70
|
-
const dialog = dialogRef.current
|
|
71
|
-
|
|
72
|
-
const handleCancel = (event: Event): void => {
|
|
73
|
-
event.preventDefault()
|
|
74
|
-
onClose()
|
|
37
|
+
if (!dialogRef.current?.open) {
|
|
38
|
+
dialogRef?.current?.showModal?.()
|
|
75
39
|
}
|
|
76
40
|
|
|
77
|
-
dialog?.addEventListener("cancel", handleCancel)
|
|
78
|
-
|
|
79
41
|
return (): void => {
|
|
80
|
-
|
|
42
|
+
document.documentElement.style.overflow = ""
|
|
81
43
|
|
|
82
44
|
const trigger = triggerRef.current
|
|
83
45
|
if (trigger && trigger instanceof HTMLElement) {
|
|
@@ -85,20 +47,14 @@ export const Dialog: FC<DialogProps> = ({
|
|
|
85
47
|
}
|
|
86
48
|
triggerRef.current = null
|
|
87
49
|
}
|
|
88
|
-
} else if (!dialogRef?.current) {
|
|
89
|
-
const localPos: string = document?.body?.getAttribute(ATTRIBUTE_SCROLL) ?? "0"
|
|
90
|
-
const scrollPosition: number = parseInt(localPos) ?? 0
|
|
91
|
-
|
|
92
|
-
document.body.classList.remove(POSITION_FIXED_CLASS)
|
|
93
|
-
|
|
94
|
-
resetDocumentStyle(scrollPosition)
|
|
95
|
-
|
|
96
|
-
dialogRef?.current?.close?.()
|
|
97
50
|
}
|
|
98
|
-
|
|
99
|
-
return undefined
|
|
100
51
|
}, [isOpen])
|
|
101
52
|
|
|
53
|
+
const onCancel = (event: React.SyntheticEvent<HTMLDialogElement>): void => {
|
|
54
|
+
event.preventDefault()
|
|
55
|
+
onCloseRef.current()
|
|
56
|
+
}
|
|
57
|
+
|
|
102
58
|
if (!isOpen) return null
|
|
103
59
|
|
|
104
60
|
const onDialogClose = (event: MouseEvent<HTMLDialogElement>): boolean | void | Promise<void> => {
|
|
@@ -117,7 +73,14 @@ export const Dialog: FC<DialogProps> = ({
|
|
|
117
73
|
})
|
|
118
74
|
|
|
119
75
|
return (
|
|
120
|
-
<dialog
|
|
76
|
+
<dialog
|
|
77
|
+
ref={dialogRef}
|
|
78
|
+
className={dialogClasses}
|
|
79
|
+
onClick={onDialogClose}
|
|
80
|
+
onCancel={onCancel}
|
|
81
|
+
role={role}
|
|
82
|
+
data-ui-component="Dialog"
|
|
83
|
+
>
|
|
121
84
|
{!!title && (
|
|
122
85
|
<Flex isBetween={true} isYCentered={true} padding={8} className={dialogFlexClasses}>
|
|
123
86
|
<Heading level={5} fontWeight="medium">
|
|
@@ -128,7 +91,9 @@ export const Dialog: FC<DialogProps> = ({
|
|
|
128
91
|
</ButtonGroup>
|
|
129
92
|
</Flex>
|
|
130
93
|
)}
|
|
131
|
-
|
|
94
|
+
<div className={dialogContentClasses}>{children}</div>
|
|
132
95
|
</dialog>
|
|
133
96
|
)
|
|
134
97
|
}
|
|
98
|
+
|
|
99
|
+
Dialog.displayName = "Dialog"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
1
2
|
import { getDonutBorderSize } from "./Donut.utils"
|
|
2
3
|
import { Flex } from "../Flex"
|
|
3
4
|
import styles from "./Donut.module.css"
|
|
@@ -12,18 +13,14 @@ export const Donut: FC<DonutProps> = ({ children, size, percentage = 0, color })
|
|
|
12
13
|
const dashSize = 100 - percentage
|
|
13
14
|
const donutColor: string = `hsl(var(--${color}-hue), var(--${color}-saturation), 50%)`
|
|
14
15
|
|
|
16
|
+
const donutClasses: string = getClasses(styles.donut, "relative")
|
|
15
17
|
const donutContainerStyle: object = {
|
|
16
18
|
height: size + "px",
|
|
17
19
|
width: size + "px",
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
return (
|
|
21
|
-
<Flex
|
|
22
|
-
style={donutContainerStyle}
|
|
23
|
-
className={`${styles.donut} relative`}
|
|
24
|
-
isCentered={true}
|
|
25
|
-
data-ui-component="Donut"
|
|
26
|
-
>
|
|
23
|
+
<Flex style={donutContainerStyle} className={donutClasses} isCentered={true} data-ui-component="Donut">
|
|
27
24
|
<Flex className="absolute top-0 left-0 z-50" style={donutContainerStyle} isCentered={true}>
|
|
28
25
|
{children}
|
|
29
26
|
</Flex>
|
|
@@ -62,3 +59,5 @@ export const Donut: FC<DonutProps> = ({ children, size, percentage = 0, color })
|
|
|
62
59
|
</Flex>
|
|
63
60
|
)
|
|
64
61
|
}
|
|
62
|
+
|
|
63
|
+
Donut.displayName = "Donut"
|
package/components/Dot/Dot.tsx
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
user-select: none;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
.dropdownOpen [data-ui-component="Icon"] {
|
|
9
|
+
transition: transform 96ms ease-in-out;
|
|
10
|
+
transform: rotate(180deg);
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
.dropdownDisabled {
|
|
9
14
|
cursor: not-allowed;
|
|
10
15
|
pointer-events: none;
|
|
@@ -48,30 +53,40 @@
|
|
|
48
53
|
position: absolute;
|
|
49
54
|
z-index: var(--z-index-8);
|
|
50
55
|
|
|
56
|
+
display: none;
|
|
51
57
|
min-width: 240px;
|
|
52
58
|
opacity: 0;
|
|
53
59
|
|
|
54
60
|
transition:
|
|
61
|
+
display 96ms ease-in-out allow-discrete,
|
|
55
62
|
transform 96ms ease-in-out,
|
|
56
63
|
opacity 96ms ease-in-out;
|
|
57
64
|
pointer-events: none;
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
.
|
|
61
|
-
|
|
67
|
+
.dropdown__navActive {
|
|
68
|
+
display: block;
|
|
69
|
+
opacity: 1;
|
|
62
70
|
|
|
63
|
-
transform: translateY(0)
|
|
71
|
+
transform: translateY(0);
|
|
64
72
|
|
|
65
73
|
pointer-events: all;
|
|
66
|
-
}
|
|
67
74
|
|
|
68
|
-
@
|
|
69
|
-
0% {
|
|
75
|
+
@starting-style {
|
|
70
76
|
opacity: 0;
|
|
71
|
-
/* transform: translateY(-8px); */
|
|
72
77
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.dropdownBottomLeft .dropdown__navActive,
|
|
81
|
+
.dropdownBottomRight .dropdown__navActive {
|
|
82
|
+
@starting-style {
|
|
83
|
+
transform: translateY(-6px);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.dropdownTopLeft .dropdown__navActive,
|
|
88
|
+
.dropdownTopRight .dropdown__navActive {
|
|
89
|
+
@starting-style {
|
|
90
|
+
transform: translateY(6px);
|
|
76
91
|
}
|
|
77
92
|
}
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
useEffect,
|
|
5
|
-
useMemo,
|
|
6
|
-
useState,
|
|
7
|
-
useRef,
|
|
8
|
-
cloneElement,
|
|
9
|
-
Children as ReactChildren,
|
|
10
|
-
type ReactElement,
|
|
11
|
-
type FC,
|
|
12
|
-
} from "react"
|
|
3
|
+
import { useEffect, useMemo, useState, useRef, type FC } from "react"
|
|
13
4
|
import { ANIMATION_FAST } from "../../constants/animations"
|
|
14
5
|
import { getClasses } from "@heliosgraphics/utils"
|
|
15
6
|
import { ResultList } from "../shared/ResultList"
|
|
16
7
|
import styles from "./Dropdown.module.css"
|
|
17
|
-
import type {
|
|
8
|
+
import type { KeyboardEvent, MouseEvent } from "react"
|
|
18
9
|
import type { DropdownProps } from "./Dropdown.types"
|
|
19
|
-
import type { HeliosIconType } from "../../types/icons"
|
|
20
10
|
|
|
21
11
|
export const Dropdown: FC<DropdownProps> = ({ children, items, isDisabled, position = "bottom-left" }) => {
|
|
22
12
|
const hoverStateRef = useRef<boolean>(false)
|
|
@@ -55,6 +45,7 @@ export const Dropdown: FC<DropdownProps> = ({ children, items, isDisabled, posit
|
|
|
55
45
|
[styles.dropdownBottomRight]: position === "bottom-right",
|
|
56
46
|
[styles.dropdownTopLeft]: position === "top-left",
|
|
57
47
|
[styles.dropdownTopRight]: position === "top-right",
|
|
48
|
+
[styles.dropdownOpen]: isVisible,
|
|
58
49
|
})
|
|
59
50
|
|
|
60
51
|
const mouseEnter = (_event: MouseEvent<HTMLDivElement>): void => {
|
|
@@ -72,23 +63,16 @@ export const Dropdown: FC<DropdownProps> = ({ children, items, isDisabled, posit
|
|
|
72
63
|
}, ANIMATION_FAST)
|
|
73
64
|
}
|
|
74
65
|
|
|
75
|
-
const renderChildren = ReactChildren.map(
|
|
76
|
-
children as ReactElement<{ children: ReactNode; icon: HeliosIconType }>,
|
|
77
|
-
(child: ReactElement<{ children: ReactNode; icon: HeliosIconType }>) => {
|
|
78
|
-
const caretProps = {
|
|
79
|
-
...(child?.props?.icon === "caret-down" && isVisible && { icon: "caret-up" as HeliosIconType }),
|
|
80
|
-
...(child?.props?.icon === "chevron-down" && isVisible && { icon: "chevron-up" as HeliosIconType }),
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return cloneElement(child, { ...child.props, ...caretProps })
|
|
84
|
-
},
|
|
85
|
-
)
|
|
86
|
-
|
|
87
66
|
const onSetVisible = (): void => setVisible(!isVisible)
|
|
88
67
|
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
68
|
+
const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
|
|
69
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
70
|
+
event.preventDefault()
|
|
71
|
+
onSetVisible()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const navClasses: string = getClasses(styles.dropdown__nav, isVisible && styles.dropdown__navActive)
|
|
92
76
|
|
|
93
77
|
const itemsWithClose = useMemo(
|
|
94
78
|
() =>
|
|
@@ -108,8 +92,15 @@ export const Dropdown: FC<DropdownProps> = ({ children, items, isDisabled, posit
|
|
|
108
92
|
|
|
109
93
|
return (
|
|
110
94
|
<div className={dropdownClasses} onMouseEnter={mouseEnter} onMouseLeave={mouseLeave} data-ui-component="Dropdown">
|
|
111
|
-
<div
|
|
112
|
-
|
|
95
|
+
<div
|
|
96
|
+
role="button"
|
|
97
|
+
tabIndex={0}
|
|
98
|
+
onClick={onSetVisible}
|
|
99
|
+
onKeyDown={onKeyDown}
|
|
100
|
+
aria-expanded={isVisible}
|
|
101
|
+
aria-haspopup="listbox"
|
|
102
|
+
>
|
|
103
|
+
{children}
|
|
113
104
|
</div>
|
|
114
105
|
<nav
|
|
115
106
|
className={navClasses}
|
|
@@ -122,3 +113,5 @@ export const Dropdown: FC<DropdownProps> = ({ children, items, isDisabled, posit
|
|
|
122
113
|
</div>
|
|
123
114
|
)
|
|
124
115
|
}
|
|
116
|
+
|
|
117
|
+
Dropdown.displayName = "Dropdown"
|
|
@@ -25,6 +25,7 @@ export const meta: HeliosAttributeMeta<FlexBaseProps> = {
|
|
|
25
25
|
isBetween: { type: "boolean", isOptional: true },
|
|
26
26
|
isCentered: { type: "boolean", isOptional: true },
|
|
27
27
|
isColumn: { type: "boolean", isOptional: true },
|
|
28
|
+
isFullHeight: { type: "boolean", isOptional: true },
|
|
28
29
|
isFullWidth: { type: "boolean", isOptional: true },
|
|
29
30
|
isInline: { type: "boolean", isOptional: true },
|
|
30
31
|
isNoWrap: { type: "boolean", isOptional: true },
|
package/components/Flex/Flex.tsx
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
import { getFlexUtility, getSafeFlexProps } from "../Flex/Flex.utils"
|
|
2
2
|
import type { FlexProps } from "./Flex.types"
|
|
3
|
+
import type { FC, KeyboardEvent } from "react"
|
|
3
4
|
|
|
4
|
-
export const Flex = (props
|
|
5
|
+
export const Flex: FC<FlexProps> = (props) => {
|
|
5
6
|
const { ref, ...restProps } = props
|
|
6
7
|
const flexClasses: string = getFlexUtility(restProps)
|
|
7
8
|
const safeProps = getSafeFlexProps(restProps)
|
|
8
9
|
|
|
10
|
+
const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
|
|
11
|
+
if (restProps.onClick && (event.key === "Enter" || event.key === " ")) {
|
|
12
|
+
event.preventDefault()
|
|
13
|
+
restProps.onClick(event as unknown as React.MouseEvent<HTMLDivElement>)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const a11yProps = restProps.onClick
|
|
18
|
+
? { role: (restProps.role ?? "button") as string, tabIndex: restProps.tabIndex ?? 0, onKeyDown: handleKeyDown }
|
|
19
|
+
: {}
|
|
20
|
+
|
|
9
21
|
return (
|
|
10
|
-
<div
|
|
22
|
+
<div
|
|
23
|
+
{...safeProps}
|
|
24
|
+
className={flexClasses}
|
|
25
|
+
onClick={restProps.onClick}
|
|
26
|
+
ref={ref}
|
|
27
|
+
data-ui-component="Flex"
|
|
28
|
+
{...a11yProps}
|
|
29
|
+
>
|
|
11
30
|
{restProps.children}
|
|
12
31
|
</div>
|
|
13
32
|
)
|
|
14
33
|
}
|
|
34
|
+
|
|
35
|
+
Flex.displayName = "Flex"
|
|
@@ -40,6 +40,9 @@ describe("getFlexUtility", () => {
|
|
|
40
40
|
it("Generates without duplicated classes", () =>
|
|
41
41
|
expect(getFlexUtility(MOCK_FLEX_DUPLICATE)).toEqual(MOCK_FLEX_DUPLICATE_CLASSES))
|
|
42
42
|
|
|
43
|
+
it("Generates xAlign center class", () =>
|
|
44
|
+
expect(getFlexUtility({ children: null, xAlign: "center" })).toEqual("flex flex-x-center"))
|
|
45
|
+
|
|
43
46
|
const MOCK_FLEX_RESPONSIVE_CLASSES = `flex mobile:p-0 tablet:p-8 p-16`
|
|
44
47
|
const MOCK_FLEX_RESPONSIVE: FlexProps = {
|
|
45
48
|
children: null,
|
|
@@ -60,7 +63,7 @@ describe("getFlexUtility", () => {
|
|
|
60
63
|
})
|
|
61
64
|
|
|
62
65
|
describe("getSafeFlexProps", () => {
|
|
63
|
-
const MOCK_FLEX_ATTRIBUTES: unknown = {
|
|
66
|
+
const MOCK_FLEX_ATTRIBUTES: Record<string, unknown> = {
|
|
64
67
|
children: null,
|
|
65
68
|
className: "xo",
|
|
66
69
|
draggable: true,
|
|
@@ -21,10 +21,12 @@ export const getFlexUtility = (props?: FlexProps): string => {
|
|
|
21
21
|
if (props.yAlign === "start") flexClasses.add("align-flex-start")
|
|
22
22
|
if (props.yAlign === "end") flexClasses.add("align-flex-end")
|
|
23
23
|
if (props.xAlign === "start") flexClasses.add("justify-flex-start")
|
|
24
|
+
if (props.xAlign === "center") flexClasses.add("flex-x-center")
|
|
24
25
|
if (props.xAlign === "end") flexClasses.add("justify-flex-end")
|
|
25
26
|
if (props.isBetween) flexClasses.add("space-between")
|
|
26
27
|
if (props.isAround) flexClasses.add("space-around")
|
|
27
28
|
if (props.onClick) flexClasses.add("cursor-pointer")
|
|
29
|
+
if (props.isFullHeight) flexClasses.add("hp-100")
|
|
28
30
|
if (props.isFullWidth) flexClasses.add("wp-100")
|
|
29
31
|
if (props.isNoWrap) flexClasses.add("nowrap")
|
|
30
32
|
if (props.elevation === "small") flexClasses.add("elevation-sm")
|
|
@@ -128,7 +130,7 @@ export const getRadius = (radiusValue?: ResponsiveRadiusType): string => {
|
|
|
128
130
|
}
|
|
129
131
|
|
|
130
132
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
131
|
-
export const getSafeFlexProps = (props: any):
|
|
133
|
+
export const getSafeFlexProps = (props: Record<string, any>): Record<string, unknown> => {
|
|
132
134
|
const {
|
|
133
135
|
gap: _gap,
|
|
134
136
|
isAround: _isAround,
|
|
@@ -136,6 +138,7 @@ export const getSafeFlexProps = (props: any): Partial<FlexProps> => {
|
|
|
136
138
|
isCentered: _isCentered,
|
|
137
139
|
isColumn: _isColumn,
|
|
138
140
|
isColumnCentered: _isColumnCentered,
|
|
141
|
+
isFullHeight: _isFullHeight,
|
|
139
142
|
isFullWidth: _isFullWidth,
|
|
140
143
|
isInline: _isInline,
|
|
141
144
|
isStretch: _isStretch,
|
package/components/Grid/Grid.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import type { HeadingProps } from "./Heading.types"
|
|
|
12
12
|
import type { FC, CSSProperties } from "react"
|
|
13
13
|
|
|
14
14
|
export const Heading: FC<HeadingProps> = (props) => {
|
|
15
|
-
const { level, lineClamp, style, className, ...rest } = props
|
|
15
|
+
const { level, lineClamp, lineHeight, style, className, ...rest } = props
|
|
16
16
|
|
|
17
17
|
const headingClasses: string = getClasses(className, styles.heading, {
|
|
18
18
|
[styles.headingPrimary]: props.emphasis === "primary",
|
|
@@ -32,8 +32,12 @@ export const Heading: FC<HeadingProps> = (props) => {
|
|
|
32
32
|
}
|
|
33
33
|
: undefined
|
|
34
34
|
|
|
35
|
+
const lineHeightStyle: CSSProperties | undefined = lineHeight !== undefined ? { lineHeight } : undefined
|
|
36
|
+
|
|
35
37
|
const mergedStyle: CSSProperties | undefined =
|
|
36
|
-
style || lineClampStyle
|
|
38
|
+
style || lineClampStyle || lineHeightStyle
|
|
39
|
+
? { ...(style || {}), ...(lineClampStyle || {}), ...(lineHeightStyle || {}) }
|
|
40
|
+
: undefined
|
|
37
41
|
|
|
38
42
|
const allProps: Omit<HeadingProps, "level"> = {
|
|
39
43
|
...rest,
|
|
@@ -44,20 +48,22 @@ export const Heading: FC<HeadingProps> = (props) => {
|
|
|
44
48
|
|
|
45
49
|
switch (level) {
|
|
46
50
|
case 0:
|
|
47
|
-
return <H0 {...allProps} />
|
|
51
|
+
return <H0 {...allProps} data-ui-component="Heading" />
|
|
48
52
|
case 1:
|
|
49
|
-
return <H1 {...allProps} />
|
|
53
|
+
return <H1 {...allProps} data-ui-component="Heading" />
|
|
50
54
|
case 2:
|
|
51
|
-
return <H2 {...allProps} />
|
|
55
|
+
return <H2 {...allProps} data-ui-component="Heading" />
|
|
52
56
|
case 3:
|
|
53
|
-
return <H3 {...allProps} />
|
|
57
|
+
return <H3 {...allProps} data-ui-component="Heading" />
|
|
54
58
|
case 4:
|
|
55
|
-
return <H4 {...allProps} />
|
|
59
|
+
return <H4 {...allProps} data-ui-component="Heading" />
|
|
56
60
|
case 5:
|
|
57
|
-
return <H5 {...allProps} />
|
|
61
|
+
return <H5 {...allProps} data-ui-component="Heading" />
|
|
58
62
|
case 6:
|
|
59
|
-
return <H6 {...allProps} />
|
|
63
|
+
return <H6 {...allProps} data-ui-component="Heading" />
|
|
60
64
|
default:
|
|
61
65
|
return null
|
|
62
66
|
}
|
|
63
67
|
}
|
|
68
|
+
|
|
69
|
+
Heading.displayName = "Heading"
|
|
@@ -3,6 +3,7 @@ import type { TextBaseProps } from "../Text/Text.types"
|
|
|
3
3
|
|
|
4
4
|
export interface HeadingBaseProps {
|
|
5
5
|
level: 0 | 1 | 2 | 3 | 4 | 5 | 6
|
|
6
|
+
lineHeight?: number
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export type HeadingProps = HeadingBaseProps & Omit<TextBaseProps, "type"> & HTMLAttributes<HTMLHeadingElement>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
1
2
|
import type { FC } from "react"
|
|
2
3
|
import type { H1Props } from "./H1.types"
|
|
3
4
|
|
|
4
5
|
export const H1: FC<H1Props> = (props) => {
|
|
5
|
-
return <h1 {...props} className={
|
|
6
|
+
return <h1 {...props} className={getClasses("h1", props.className)} data-ui-component="Heading.H1" />
|
|
6
7
|
}
|
|
8
|
+
|
|
9
|
+
H1.displayName = "H1"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
1
2
|
import type { FC } from "react"
|
|
2
3
|
import type { H2Props } from "./H2.types"
|
|
3
4
|
|
|
4
5
|
export const H2: FC<H2Props> = (props) => {
|
|
5
|
-
return <h2 {...props} className={
|
|
6
|
+
return <h2 {...props} className={getClasses("h2", props.className)} data-ui-component="Heading.H2" />
|
|
6
7
|
}
|
|
8
|
+
|
|
9
|
+
H2.displayName = "H2"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
1
2
|
import type { FC } from "react"
|
|
2
3
|
import type { H3Props } from "./H3.types"
|
|
3
4
|
|
|
4
5
|
export const H3: FC<H3Props> = (props) => {
|
|
5
|
-
return <h3 {...props} className={
|
|
6
|
+
return <h3 {...props} className={getClasses("h3", props.className)} data-ui-component="Heading.H3" />
|
|
6
7
|
}
|
|
8
|
+
|
|
9
|
+
H3.displayName = "H3"
|