@heliosgraphics/ui 2.0.0-alpha.89 → 2.0.0-alpha.90
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 +1 -1
- package/components/Breadcrumb/Breadcrumb.meta.ts +1 -1
- package/components/Breadcrumb/Breadcrumb.tsx +4 -4
- package/components/Browser/Browser.tsx +6 -2
- package/components/Button/Button.tsx +175 -173
- package/components/ButtonGroup/ButtonGroup.tsx +2 -4
- package/components/Checkbox/Checkbox.tsx +61 -55
- package/components/Clock/Clock.module.css +1 -1
- package/components/Clock/Clock.tsx +1 -1
- package/components/Column/Column.tsx +2 -2
- package/components/Confirm/Confirm.tsx +1 -1
- package/components/DatePicker/DatePicker.tsx +6 -2
- package/components/Debug/Debug.tsx +2 -2
- package/components/Details/Details.tsx +1 -1
- package/components/Dialog/Dialog.tsx +32 -5
- package/components/Donut/Donut.module.css +1 -1
- package/components/Donut/Donut.tsx +8 -1
- package/components/Dot/Dot.tsx +1 -1
- package/components/Dropdown/Dropdown.tsx +46 -19
- package/components/Fieldset/Fieldset.tsx +1 -1
- package/components/Flex/Flex.tsx +12 -10
- package/components/Grid/Grid.tsx +7 -3
- package/components/Heading/Heading.tsx +15 -10
- package/components/Heading/components/H0/H0.tsx +1 -1
- package/components/Icon/Icon.tsx +1 -1
- package/components/Input/Input.tsx +13 -3
- package/components/Layout/components/LayoutAside/LayoutAside.tsx +1 -1
- package/components/Layout/components/LayoutAside/components/LayoutAsideContent/LayoutAsideContent.tsx +1 -1
- package/components/Layout/components/LayoutAside/components/LayoutAsideFooter/LayoutAsideFooter.tsx +1 -1
- package/components/Layout/components/LayoutAside/components/LayoutAsideToggle/LayoutAsideToggle.tsx +1 -1
- package/components/Layout/components/LayoutMain/LayoutMain.tsx +1 -1
- package/components/Layout/components/LayoutMain/components/LayoutMainContent/LayoutMainContent.tsx +1 -1
- package/components/Layout/components/LayoutNavigation/LayoutNavigation.tsx +1 -1
- package/components/Loading/Loading.tsx +10 -2
- package/components/Markdown/Markdown.meta.ts +7 -0
- package/components/Markdown/Markdown.tsx +15 -6
- package/components/Markdown/Markdown.types.ts +4 -1
- package/components/Markdown/Markdown.utils.spec.ts +3 -3
- package/components/Markdown/Markdown.utils.ts +9 -7
- package/components/Masonry/Masonry.meta.ts +1 -1
- package/components/Masonry/Masonry.tsx +2 -2
- package/components/Masonry/Masonry.types.ts +1 -1
- package/components/Menu/Menu.tsx +1 -3
- package/components/Menu/components/MenuCategory/MenuCategory.tsx +13 -2
- package/components/Menu/components/MenuFilter/MenuFilter.tsx +1 -1
- package/components/Menu/components/MenuItem/MenuItem.tsx +14 -1
- package/components/Overlay/Overlay.tsx +1 -1
- package/components/Pie/Pie.tsx +7 -4
- package/components/Pill/Pill.tsx +1 -1
- package/components/Placeholder/Placeholder.tsx +1 -0
- package/components/Progress/Progress.tsx +9 -1
- package/components/Radio/Radio.tsx +64 -58
- package/components/Segments/Segments.tsx +6 -6
- package/components/Select/Select.tsx +5 -4
- package/components/Separator/components/HorizontalSeparator/HorizontalSeparator.tsx +1 -1
- package/components/Separator/components/VerticalSeparator/VerticalSeparator.tsx +1 -1
- package/{components.css → components/Setup/Setup.components.css} +2 -2
- package/components/Setup/Setup.meta.ts +2 -2
- package/components/Setup/Setup.tsx +10 -7
- package/components/Setup/Setup.types.ts +1 -0
- package/components/Shimmer/Shimmer.tsx +3 -2
- package/components/Slider/Slider.tsx +4 -4
- package/components/Spacer/Spacer.tsx +1 -1
- package/components/Table/Table.tsx +1 -1
- package/components/Tabs/Tabs.tsx +36 -12
- package/components/Text/Text.tsx +5 -2
- package/components/Textarea/Textarea.tsx +10 -5
- package/components/Tile/Tile.tsx +2 -9
- package/components/Tile/Tile.types.ts +1 -1
- package/components/Timestamp/Timestamp.meta.ts +5 -1
- package/components/Timestamp/Timestamp.tsx +3 -3
- package/components/Timestamp/Timestamp.types.ts +1 -1
- package/components/Toggle/Toggle.tsx +2 -2
- package/components/Tooltip/Tooltip.module.css +32 -0
- package/components/Tooltip/Tooltip.tsx +36 -72
- package/components/Tooltip/Tooltip.types.ts +1 -0
- package/components/Tooltip/components/TooltipContent/TooltipContent.tsx +5 -3
- package/components/Tooltip/components/TooltipTrigger/TooltipTrigger.tsx +10 -4
- package/components/shared/InputLabel/InputLabel.tsx +1 -1
- package/components/shared/ResultList/ResultList.tsx +6 -7
- package/constants/hooks.ts +1 -1
- package/contexts/LayoutContext/LayoutContext.tsx +30 -20
- package/contexts/LayoutContext/LayoutContext.types.ts +1 -0
- package/hooks/useDebounce.tsx +2 -2
- package/hooks/useLayoutContext.tsx +1 -0
- package/hooks/usePrint.tsx +31 -0
- package/index.ts +4 -0
- package/package.json +20 -12
- package/utils/date.ts +54 -0
- package/utils/dayjs.ts +0 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { getClasses } from "@heliosgraphics/utils
|
|
3
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
4
4
|
import { Text } from "../Text"
|
|
5
5
|
import { useId, useRef, useEffect } from "react"
|
|
6
6
|
import { InputLabel } from "../shared/InputLabel"
|
|
@@ -13,6 +13,7 @@ export const Textarea: FC<TextareaProps> = (props) => {
|
|
|
13
13
|
const { autoComplete: _autoComplete, helperText: _helperText, isDisabled, isLabelHidden, ...goodProps } = props
|
|
14
14
|
|
|
15
15
|
const htmlFor: string = useId()
|
|
16
|
+
const helperId: string = `${htmlFor}-helper`
|
|
16
17
|
const textareaClasses: string = getClasses(styles.textarea, "flex flex-column", {
|
|
17
18
|
[styles.textareaDisabled]: props.isDisabled,
|
|
18
19
|
})
|
|
@@ -24,17 +25,20 @@ export const Textarea: FC<TextareaProps> = (props) => {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
// TODO no longer necessary <3
|
|
28
28
|
useEffect(() => {
|
|
29
29
|
if (textareaRef?.current) {
|
|
30
30
|
onInput()
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
setTimeout(() => onInput(), 100)
|
|
33
|
+
const timer: ReturnType<typeof setTimeout> = setTimeout(() => onInput(), 100)
|
|
34
|
+
|
|
35
|
+
return (): void => {
|
|
36
|
+
globalThis.clearTimeout(timer)
|
|
37
|
+
}
|
|
34
38
|
}, [props.value])
|
|
35
39
|
|
|
36
40
|
return (
|
|
37
|
-
<div className={textareaClasses}>
|
|
41
|
+
<div className={textareaClasses} data-ui-component="Textarea">
|
|
38
42
|
{!props.isLabelHidden && (
|
|
39
43
|
<InputLabel
|
|
40
44
|
id={htmlFor}
|
|
@@ -51,9 +55,10 @@ export const Textarea: FC<TextareaProps> = (props) => {
|
|
|
51
55
|
onInput={onInput}
|
|
52
56
|
onLoad={onInput}
|
|
53
57
|
disabled={isDisabled}
|
|
58
|
+
aria-describedby={props.helperText ? helperId : undefined}
|
|
54
59
|
/>
|
|
55
60
|
{!!props.helperText && (
|
|
56
|
-
<Text type="tiny" emphasis="tertiary" className={styles.input__helper}>
|
|
61
|
+
<Text type="tiny" emphasis="tertiary" className={styles.input__helper} id={helperId}>
|
|
57
62
|
{props.helperText}
|
|
58
63
|
</Text>
|
|
59
64
|
)}
|
package/components/Tile/Tile.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { getClasses } from "@heliosgraphics/utils/classnames"
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
3
2
|
import { getColorClasses } from "../../utils/colors"
|
|
4
3
|
import { Icon } from "../Icon"
|
|
5
4
|
import { Text } from "../Text"
|
|
@@ -35,6 +34,7 @@ export const Tile: FC<TileProps> = ({
|
|
|
35
34
|
<Flex
|
|
36
35
|
{...(onClick && { onClick })}
|
|
37
36
|
className={tileClasses}
|
|
37
|
+
data-ui-component="Tile"
|
|
38
38
|
isCentered={true}
|
|
39
39
|
isColumn={true}
|
|
40
40
|
style={{
|
|
@@ -44,13 +44,6 @@ export const Tile: FC<TileProps> = ({
|
|
|
44
44
|
}}
|
|
45
45
|
>
|
|
46
46
|
<Icon icon={icon} size={size * 0.5} emphasis="inherit" />
|
|
47
|
-
{/*<svg width="100%" height="100%" viewBox={`0 0 ${size} ${size}`} className={styles.tile__background}>
|
|
48
|
-
<linearGradient id={tileId}>
|
|
49
|
-
<stop stopColor={`var(--${resolvedColor})`} offset="0%" />
|
|
50
|
-
{colorAccent && <stop stopColor={`var(--${resolvedColorAccent})`} offset="100%" />}
|
|
51
|
-
</linearGradient>
|
|
52
|
-
<rect fill={`url(#${tileId})`} x={0} y={0} width={size} height={size} rx={isRound ? size : isRounded ? 8 : 0} />
|
|
53
|
-
</svg> */}
|
|
54
47
|
{iconAccent && (
|
|
55
48
|
<Flex isCentered={true}>
|
|
56
49
|
<Icon icon={iconAccent} size={size * 1} className={styles.tile__iconAccent} />
|
|
@@ -12,7 +12,11 @@ export const meta: HeliosAttributeMeta<TimestampProps> = {
|
|
|
12
12
|
_status: "nominal",
|
|
13
13
|
_category: "content",
|
|
14
14
|
date: { type: "string", isOptional: true },
|
|
15
|
-
format: {
|
|
15
|
+
format: {
|
|
16
|
+
type: "Intl.DateTimeFormatOptions",
|
|
17
|
+
isOptional: true,
|
|
18
|
+
default: "{ year: numeric, month: long, day: numeric }",
|
|
19
|
+
},
|
|
16
20
|
fromNow: { type: "boolean", isOptional: true },
|
|
17
21
|
text: { type: "string", isOptional: true },
|
|
18
22
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getIsValid, formatDate, getFromNow } from "../../utils/
|
|
1
|
+
import { getIsValid, formatDate, getFromNow } from "../../utils/date"
|
|
2
2
|
import type { FC } from "react"
|
|
3
3
|
import type { TimestampProps } from "./Timestamp.types"
|
|
4
4
|
|
|
5
|
-
export const Timestamp: FC<TimestampProps> = ({ date, fromNow, text, format
|
|
5
|
+
export const Timestamp: FC<TimestampProps> = ({ date, fromNow, text, format }) => {
|
|
6
6
|
const fromNowDate = getFromNow(date)
|
|
7
7
|
const isValid: boolean = getIsValid(date)
|
|
8
8
|
const parsedIsoString: string = date && isValid ? new Date(Date.parse(date))?.toISOString() : ""
|
|
@@ -11,7 +11,7 @@ export const Timestamp: FC<TimestampProps> = ({ date, fromNow, text, format = "M
|
|
|
11
11
|
const formattedDate: string = fromNow ? fromNowDate : formatDate(date, format)
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
|
-
<time dateTime={timestampDate} suppressHydrationWarning={true}>
|
|
14
|
+
<time dateTime={timestampDate} suppressHydrationWarning={true} data-ui-component="Timestamp">
|
|
15
15
|
{!!text && text}
|
|
16
16
|
{formattedDate}
|
|
17
17
|
</time>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import { useId } from "react"
|
|
4
|
-
import { getClasses } from "@heliosgraphics/utils
|
|
4
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
5
5
|
import { getColorClasses } from "../../utils/colors"
|
|
6
6
|
import { INTENTION_COLOR_MAP } from "../../constants/intentions"
|
|
7
7
|
import { Text } from "../Text"
|
|
@@ -35,7 +35,7 @@ export const Toggle: FC<ToggleProps> = ({
|
|
|
35
35
|
const toggleLabelClasses = getClasses(styles.toggle__toggleLabel, "flex flex-y-center gap-4 flex-wrap")
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
|
-
<div className={toggleClasses}>
|
|
38
|
+
<div className={toggleClasses} data-ui-component="Toggle">
|
|
39
39
|
<label className={toggleLabelClasses} htmlFor={toggleId}>
|
|
40
40
|
<input
|
|
41
41
|
type="checkbox"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
|
|
4
4
|
display: inline-block;
|
|
5
|
+
anchor-scope: --tooltip;
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
.tooltip {
|
|
@@ -9,10 +10,41 @@
|
|
|
9
10
|
z-index: 10;
|
|
10
11
|
|
|
11
12
|
max-width: 320px;
|
|
13
|
+
margin: 8px;
|
|
12
14
|
padding: 8px;
|
|
13
15
|
|
|
14
16
|
background-color: var(--ui-bg-secondary);
|
|
15
17
|
border: 0;
|
|
16
18
|
color: var(--ui-text-primary);
|
|
17
19
|
border-radius: var(--radius-sm);
|
|
20
|
+
|
|
21
|
+
position-area: bottom center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.tooltipBottomLeft {
|
|
25
|
+
position-area: bottom left;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.tooltipBottomRight {
|
|
29
|
+
position-area: bottom right;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.tooltipTopCenter {
|
|
33
|
+
position-area: top center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tooltipTopLeft {
|
|
37
|
+
position-area: top left;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.tooltipTopRight {
|
|
41
|
+
position-area: top right;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.tooltipLeftCenter {
|
|
45
|
+
position-area: left center;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.tooltipRightCenter {
|
|
49
|
+
position-area: right center;
|
|
18
50
|
}
|
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { useRef, useEffect, useMemo, useState, FC } from "react"
|
|
4
|
-
import { getClasses } from "@heliosgraphics/utils
|
|
3
|
+
import { useRef, useEffect, useMemo, useState, useId, type FC } from "react"
|
|
4
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
5
5
|
import styles from "./Tooltip.module.css"
|
|
6
6
|
import type { TooltipProps, TooltipComposition, TooltipContextType } from "./Tooltip.types"
|
|
7
7
|
import { TooltipTrigger } from "./components/TooltipTrigger"
|
|
8
8
|
import { TooltipContent } from "./components/TooltipContent"
|
|
9
9
|
import { TooltipContext } from "./Tooltip.utils"
|
|
10
10
|
|
|
11
|
+
const POSITION_CLASS_MAP: Record<NonNullable<TooltipProps["position"]>, string | undefined> = {
|
|
12
|
+
"bottom-center": undefined,
|
|
13
|
+
"bottom-left": styles.tooltipBottomLeft,
|
|
14
|
+
"bottom-right": styles.tooltipBottomRight,
|
|
15
|
+
"top-center": styles.tooltipTopCenter,
|
|
16
|
+
"top-left": styles.tooltipTopLeft,
|
|
17
|
+
"top-right": styles.tooltipTopRight,
|
|
18
|
+
"left-center": styles.tooltipLeftCenter,
|
|
19
|
+
"right-center": styles.tooltipRightCenter,
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
const TooltipComponent: FC<TooltipProps> = ({ children = null, position = "bottom-center", isVisible = false }) => {
|
|
12
23
|
const [isOpen, setIsOpen] = useState<boolean>(isVisible)
|
|
13
24
|
const triggerRef = useRef<HTMLDivElement | null>(null)
|
|
14
25
|
const popoverRef = useRef<HTMLDivElement | null>(null)
|
|
26
|
+
const id: string = useId()
|
|
27
|
+
const anchorName: string = `--tooltip-${id.replace(/:/g, "")}`
|
|
28
|
+
|
|
29
|
+
const positionClass: string | undefined = POSITION_CLASS_MAP[position]
|
|
15
30
|
|
|
16
|
-
const tooltipClasses: string = useMemo(
|
|
31
|
+
const tooltipClasses: string = useMemo(
|
|
32
|
+
() => getClasses(styles.tooltip, "elevation-md", positionClass),
|
|
33
|
+
[positionClass],
|
|
34
|
+
)
|
|
17
35
|
|
|
18
36
|
useEffect(() => {
|
|
19
37
|
const trigger = triggerRef.current
|
|
@@ -26,69 +44,14 @@ const TooltipComponent: FC<TooltipProps> = ({ children = null, position = "botto
|
|
|
26
44
|
return
|
|
27
45
|
}
|
|
28
46
|
|
|
29
|
-
const positionTooltip = (): void => {
|
|
30
|
-
if (!trigger || !popover) return
|
|
31
|
-
|
|
32
|
-
const triggerRect = trigger.getBoundingClientRect()
|
|
33
|
-
const popoverRect = popover.getBoundingClientRect()
|
|
34
|
-
const viewportWidth = globalThis.innerWidth
|
|
35
|
-
const viewportHeight = globalThis.innerHeight
|
|
36
|
-
|
|
37
|
-
let top = 0
|
|
38
|
-
let left = 0
|
|
39
|
-
|
|
40
|
-
switch (position) {
|
|
41
|
-
case "bottom-center":
|
|
42
|
-
top = triggerRect.bottom + 8
|
|
43
|
-
left = triggerRect.left + triggerRect.width / 2 - popoverRect.width / 2
|
|
44
|
-
break
|
|
45
|
-
case "bottom-left":
|
|
46
|
-
top = triggerRect.bottom + 8
|
|
47
|
-
left = triggerRect.left
|
|
48
|
-
break
|
|
49
|
-
case "bottom-right":
|
|
50
|
-
top = triggerRect.bottom + 8
|
|
51
|
-
left = triggerRect.right - popoverRect.width
|
|
52
|
-
break
|
|
53
|
-
case "top-center":
|
|
54
|
-
top = triggerRect.top - popoverRect.height - 8
|
|
55
|
-
left = triggerRect.left + triggerRect.width / 2 - popoverRect.width / 2
|
|
56
|
-
break
|
|
57
|
-
case "top-left":
|
|
58
|
-
top = triggerRect.top - popoverRect.height - 8
|
|
59
|
-
left = triggerRect.left
|
|
60
|
-
break
|
|
61
|
-
case "top-right":
|
|
62
|
-
top = triggerRect.top - popoverRect.height - 8
|
|
63
|
-
left = triggerRect.right - popoverRect.width
|
|
64
|
-
break
|
|
65
|
-
case "left-center":
|
|
66
|
-
top = triggerRect.top + triggerRect.height / 2 - popoverRect.height / 2
|
|
67
|
-
left = triggerRect.left - popoverRect.width - 8
|
|
68
|
-
break
|
|
69
|
-
case "right-center":
|
|
70
|
-
top = triggerRect.top + triggerRect.height / 2 - popoverRect.height / 2
|
|
71
|
-
left = triggerRect.right + 8
|
|
72
|
-
break
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
left = Math.max(10, Math.min(left, viewportWidth - popoverRect.width - 10))
|
|
76
|
-
top = Math.max(10, Math.min(top, viewportHeight - popoverRect.height - 10))
|
|
77
|
-
|
|
78
|
-
popover.style.top = `${top}px`
|
|
79
|
-
popover.style.left = `${left}px`
|
|
80
|
-
}
|
|
81
|
-
|
|
82
47
|
if (isVisible) {
|
|
83
48
|
popover.showPopover()
|
|
84
49
|
setIsOpen(true)
|
|
85
|
-
setTimeout(positionTooltip, 0)
|
|
86
50
|
}
|
|
87
51
|
|
|
88
52
|
const handleMouseEnter = (): void => {
|
|
89
53
|
popover.showPopover()
|
|
90
54
|
setIsOpen(true)
|
|
91
|
-
setTimeout(positionTooltip, 0)
|
|
92
55
|
}
|
|
93
56
|
|
|
94
57
|
const handleMouseLeave = (): void => {
|
|
@@ -109,28 +72,29 @@ const TooltipComponent: FC<TooltipProps> = ({ children = null, position = "botto
|
|
|
109
72
|
trigger.addEventListener("mouseleave", handleMouseLeave)
|
|
110
73
|
trigger.addEventListener("keydown", handleKeyDown)
|
|
111
74
|
|
|
112
|
-
globalThis.addEventListener("resize", positionTooltip)
|
|
113
|
-
globalThis.addEventListener("scroll", positionTooltip, true)
|
|
114
|
-
|
|
115
75
|
return (): void => {
|
|
116
76
|
trigger.removeEventListener("mouseenter", handleMouseEnter)
|
|
117
77
|
trigger.removeEventListener("mouseleave", handleMouseLeave)
|
|
118
78
|
trigger.removeEventListener("keydown", handleKeyDown)
|
|
119
|
-
globalThis.removeEventListener("resize", positionTooltip)
|
|
120
|
-
globalThis.removeEventListener("scroll", positionTooltip, true)
|
|
121
79
|
}
|
|
122
|
-
}, [isVisible
|
|
123
|
-
|
|
124
|
-
const contextValue: TooltipContextType =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
80
|
+
}, [isVisible])
|
|
81
|
+
|
|
82
|
+
const contextValue: TooltipContextType = useMemo(
|
|
83
|
+
() => ({
|
|
84
|
+
triggerRef,
|
|
85
|
+
popoverRef,
|
|
86
|
+
tooltipClasses,
|
|
87
|
+
anchorName,
|
|
88
|
+
isOpen,
|
|
89
|
+
}),
|
|
90
|
+
[tooltipClasses, anchorName, isOpen],
|
|
91
|
+
)
|
|
130
92
|
|
|
131
93
|
return (
|
|
132
94
|
<TooltipContext.Provider value={contextValue}>
|
|
133
|
-
<div className={styles.tooltipContainer}>
|
|
95
|
+
<div className={styles.tooltipContainer} data-ui-component="Tooltip">
|
|
96
|
+
{children}
|
|
97
|
+
</div>
|
|
134
98
|
</TooltipContext.Provider>
|
|
135
99
|
)
|
|
136
100
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Text } from "../../../Text"
|
|
2
2
|
import { useTooltipContext } from "../../Tooltip.utils"
|
|
3
|
-
import type { FC } from "react"
|
|
3
|
+
import type { CSSProperties, FC } from "react"
|
|
4
4
|
import type { TooltipContentProps } from "./TooltipContent.types"
|
|
5
5
|
|
|
6
6
|
export const TooltipContent: FC<TooltipContentProps> = ({ children }) => {
|
|
7
|
-
const { popoverRef, tooltipClasses } = useTooltipContext()
|
|
7
|
+
const { popoverRef, tooltipClasses, anchorName } = useTooltipContext()
|
|
8
|
+
|
|
9
|
+
const contentStyle: CSSProperties = { positionAnchor: anchorName } as CSSProperties
|
|
8
10
|
|
|
9
11
|
return (
|
|
10
|
-
<div className={tooltipClasses} ref={popoverRef} popover="manual">
|
|
12
|
+
<div className={tooltipClasses} ref={popoverRef} popover="manual" style={contentStyle}>
|
|
11
13
|
<Text type="small">{children}</Text>
|
|
12
14
|
</div>
|
|
13
15
|
)
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { TooltipTriggerProps } from "./TooltipTrigger.types"
|
|
1
|
+
import type { TooltipTriggerProps } from "./TooltipTrigger.types"
|
|
2
2
|
import { useTooltipContext } from "../../Tooltip.utils"
|
|
3
|
-
import type { FC } from "react"
|
|
3
|
+
import type { CSSProperties, FC } from "react"
|
|
4
4
|
|
|
5
5
|
export const TooltipTrigger: FC<TooltipTriggerProps> = ({ children }) => {
|
|
6
|
-
const { triggerRef } = useTooltipContext()
|
|
6
|
+
const { triggerRef, anchorName } = useTooltipContext()
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const triggerStyle: CSSProperties = { anchorName } as CSSProperties
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div ref={triggerRef} style={triggerStyle}>
|
|
12
|
+
{children}
|
|
13
|
+
</div>
|
|
14
|
+
)
|
|
9
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FC } from "react"
|
|
2
2
|
import styles from "./InputLabel.module.css"
|
|
3
|
-
import { getClasses } from "@heliosgraphics/utils
|
|
3
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
4
4
|
import type { InputLabelProps } from "./InputLabel.types"
|
|
5
5
|
|
|
6
6
|
export const InputLabel: FC<InputLabelProps> = ({ id, label, isDisabled, isHidden }) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getClasses } from "@heliosgraphics/utils
|
|
1
|
+
import { getClasses } from "@heliosgraphics/utils"
|
|
2
2
|
import { Checkbox } from "../../Checkbox"
|
|
3
3
|
import { Flex } from "../../Flex"
|
|
4
4
|
import { Icon } from "../../Icon"
|
|
@@ -15,23 +15,22 @@ export const ResultList = forwardRef<HTMLOListElement, ResultListProps>(({ items
|
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
17
|
<ol className={resultListClasses} data-ui-component="ResultList" role="listbox" ref={ref}>
|
|
18
|
-
{items?.map((item,
|
|
18
|
+
{items?.map((item, index) => {
|
|
19
|
+
const itemKey: string = item.name ? `${item.name}-${index}` : `separator-${index}`
|
|
19
20
|
const itemClasses: string = getClasses("flex flex-y-center gap-5", styles.item, {
|
|
20
21
|
[styles.itemActive]: item.isActive && !item.type,
|
|
21
22
|
[styles.itemDisabled]: item.isDisabled,
|
|
22
23
|
})
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
if (item.type === "separator") return <li key={key} className={styles.resultList__separator} />
|
|
25
|
+
if (item.type === "separator") return <li key={itemKey} className={styles.resultList__separator} />
|
|
26
26
|
|
|
27
|
-
// NOTE @03b8 future composit
|
|
28
27
|
if (item.type === "checkbox") {
|
|
29
28
|
const onCheck = (event: ChangeEvent<HTMLInputElement>): void =>
|
|
30
29
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
30
|
item.onClick?.(event as any)
|
|
32
31
|
|
|
33
32
|
return (
|
|
34
|
-
<li key={
|
|
33
|
+
<li key={itemKey} onClick={item.onClick} className={itemClasses}>
|
|
35
34
|
<Checkbox
|
|
36
35
|
label={item.name}
|
|
37
36
|
{...(item.description && { description: item.description })}
|
|
@@ -43,7 +42,7 @@ export const ResultList = forwardRef<HTMLOListElement, ResultListProps>(({ items
|
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
return (
|
|
46
|
-
<li key={
|
|
45
|
+
<li key={itemKey} onClick={item.onClick} className={itemClasses}>
|
|
47
46
|
{item.icon && (
|
|
48
47
|
<Flex isCentered={true}>
|
|
49
48
|
<Icon icon={item.icon} size={18} />
|
package/constants/hooks.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const HOOKS = ["useIntersection", "usePrevious", "
|
|
1
|
+
export const HOOKS = ["useIntersection", "useLayoutContext", "usePrevious", "usePrint", "useTheme"] as const
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { useState, createContext, useRef, useEffect } from "react"
|
|
3
|
+
import { useState, createContext, useRef, useEffect, useMemo, useCallback } from "react"
|
|
4
4
|
import type { FC, PropsWithChildren } from "react"
|
|
5
5
|
import type { LayoutContextProps } from "./LayoutContext.types"
|
|
6
6
|
|
|
@@ -20,6 +20,7 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
|
|
|
20
20
|
const asideRef = useRef<HTMLElement | null>(null)
|
|
21
21
|
const isMenuVisibleRef = useRef<boolean>(false)
|
|
22
22
|
const windowWidthRef = useRef<number>(0)
|
|
23
|
+
const resizeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
23
24
|
|
|
24
25
|
useEffect(() => {
|
|
25
26
|
isMenuVisibleRef.current = isMenuVisible
|
|
@@ -67,11 +68,20 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
const throttledResize = (): void => {
|
|
72
|
+
if (resizeTimerRef.current) return
|
|
73
|
+
resizeTimerRef.current = setTimeout(() => {
|
|
74
|
+
handleResize()
|
|
75
|
+
resizeTimerRef.current = null
|
|
76
|
+
}, 150)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
globalThis.addEventListener("resize", throttledResize)
|
|
71
80
|
globalThis.document.addEventListener("mousedown", handleClickOutside)
|
|
72
81
|
|
|
73
82
|
return (): void => {
|
|
74
|
-
globalThis.
|
|
83
|
+
if (resizeTimerRef.current) globalThis.clearTimeout(resizeTimerRef.current)
|
|
84
|
+
globalThis.removeEventListener("resize", throttledResize)
|
|
75
85
|
globalThis.document.removeEventListener("mousedown", handleClickOutside)
|
|
76
86
|
}
|
|
77
87
|
}, [breakpoint])
|
|
@@ -79,24 +89,24 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
|
|
|
79
89
|
const isWideEnough: boolean = hasMounted ? windowWidth >= breakpoint : false
|
|
80
90
|
const shouldShowNavigation: boolean = isWideEnough || isMenuVisible
|
|
81
91
|
|
|
82
|
-
const onNavigationToggle = (): void => setIsMenuVisible((prev) => !prev)
|
|
83
|
-
const onAsideClose = (): void => setIsMenuVisible(false)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{children}
|
|
98
|
-
</LayoutContext.Provider>
|
|
92
|
+
const onNavigationToggle = useCallback((): void => setIsMenuVisible((prev) => !prev), [])
|
|
93
|
+
const onAsideClose = useCallback((): void => setIsMenuVisible(false), [])
|
|
94
|
+
|
|
95
|
+
const contextValue: LayoutContextProps = useMemo(
|
|
96
|
+
() => ({
|
|
97
|
+
asideRef,
|
|
98
|
+
hasMounted,
|
|
99
|
+
isMenuVisible,
|
|
100
|
+
isWideEnough,
|
|
101
|
+
onAsideClose,
|
|
102
|
+
onNavigationToggle,
|
|
103
|
+
shouldShowNavigation,
|
|
104
|
+
windowWidth,
|
|
105
|
+
}),
|
|
106
|
+
[hasMounted, isMenuVisible, isWideEnough, shouldShowNavigation, onAsideClose, onNavigationToggle, windowWidth],
|
|
99
107
|
)
|
|
108
|
+
|
|
109
|
+
return <LayoutContext.Provider value={contextValue}>{children}</LayoutContext.Provider>
|
|
100
110
|
}
|
|
101
111
|
|
|
102
112
|
export { LayoutContext, LayoutProvider }
|
package/hooks/useDebounce.tsx
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect } from "react"
|
|
4
4
|
|
|
5
|
-
export const useDebounce = (value:
|
|
6
|
-
const [debouncedValue, setDebouncedValue] = useState<
|
|
5
|
+
export const useDebounce = <T,>(value: T, delay: number): T => {
|
|
6
|
+
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
|
7
7
|
|
|
8
8
|
useEffect(() => {
|
|
9
9
|
const handler: ReturnType<typeof setTimeout> = setTimeout(() => {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react"
|
|
4
|
+
|
|
5
|
+
interface UsePrintReturn {
|
|
6
|
+
isPrinting: boolean
|
|
7
|
+
print: () => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const usePrint = (): UsePrintReturn => {
|
|
11
|
+
const [isPrinting, setIsPrinting] = useState<boolean>(false)
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const handleBeforePrint = (): void => setIsPrinting(true)
|
|
15
|
+
const handleAfterPrint = (): void => setIsPrinting(false)
|
|
16
|
+
|
|
17
|
+
globalThis.addEventListener("beforeprint", handleBeforePrint)
|
|
18
|
+
globalThis.addEventListener("afterprint", handleAfterPrint)
|
|
19
|
+
|
|
20
|
+
return (): void => {
|
|
21
|
+
globalThis.removeEventListener("beforeprint", handleBeforePrint)
|
|
22
|
+
globalThis.removeEventListener("afterprint", handleAfterPrint)
|
|
23
|
+
}
|
|
24
|
+
}, [])
|
|
25
|
+
|
|
26
|
+
const print = useCallback((): void => {
|
|
27
|
+
globalThis.print()
|
|
28
|
+
}, [])
|
|
29
|
+
|
|
30
|
+
return { isPrinting, print }
|
|
31
|
+
}
|
package/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// eslint-disable-next-line typescript/triple-slash-reference
|
|
2
|
+
/// <reference path="./globals.d.ts" />
|
|
3
|
+
|
|
1
4
|
export { Alert } from "./components/Alert"
|
|
2
5
|
export { Breadcrumb } from "./components/Breadcrumb"
|
|
3
6
|
export { Browser } from "./components/Browser"
|
|
@@ -64,6 +67,7 @@ export type { TextBaseProps, TextProps } from "./components/Text"
|
|
|
64
67
|
export { useIntersection } from "./hooks/useIntersection"
|
|
65
68
|
export { useLayoutContext } from "./hooks/useLayoutContext"
|
|
66
69
|
export { usePrevious } from "./hooks/usePrevious"
|
|
70
|
+
export { usePrint } from "./hooks/usePrint"
|
|
67
71
|
export { useTheme } from "./hooks/useTheme"
|
|
68
72
|
|
|
69
73
|
export type { HeliosAppearanceType, HeliosColorType } from "./types/colors"
|