@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.
Files changed (90) hide show
  1. package/components/Alert/Alert.tsx +1 -1
  2. package/components/Breadcrumb/Breadcrumb.meta.ts +1 -1
  3. package/components/Breadcrumb/Breadcrumb.tsx +4 -4
  4. package/components/Browser/Browser.tsx +6 -2
  5. package/components/Button/Button.tsx +175 -173
  6. package/components/ButtonGroup/ButtonGroup.tsx +2 -4
  7. package/components/Checkbox/Checkbox.tsx +61 -55
  8. package/components/Clock/Clock.module.css +1 -1
  9. package/components/Clock/Clock.tsx +1 -1
  10. package/components/Column/Column.tsx +2 -2
  11. package/components/Confirm/Confirm.tsx +1 -1
  12. package/components/DatePicker/DatePicker.tsx +6 -2
  13. package/components/Debug/Debug.tsx +2 -2
  14. package/components/Details/Details.tsx +1 -1
  15. package/components/Dialog/Dialog.tsx +32 -5
  16. package/components/Donut/Donut.module.css +1 -1
  17. package/components/Donut/Donut.tsx +8 -1
  18. package/components/Dot/Dot.tsx +1 -1
  19. package/components/Dropdown/Dropdown.tsx +46 -19
  20. package/components/Fieldset/Fieldset.tsx +1 -1
  21. package/components/Flex/Flex.tsx +12 -10
  22. package/components/Grid/Grid.tsx +7 -3
  23. package/components/Heading/Heading.tsx +15 -10
  24. package/components/Heading/components/H0/H0.tsx +1 -1
  25. package/components/Icon/Icon.tsx +1 -1
  26. package/components/Input/Input.tsx +13 -3
  27. package/components/Layout/components/LayoutAside/LayoutAside.tsx +1 -1
  28. package/components/Layout/components/LayoutAside/components/LayoutAsideContent/LayoutAsideContent.tsx +1 -1
  29. package/components/Layout/components/LayoutAside/components/LayoutAsideFooter/LayoutAsideFooter.tsx +1 -1
  30. package/components/Layout/components/LayoutAside/components/LayoutAsideToggle/LayoutAsideToggle.tsx +1 -1
  31. package/components/Layout/components/LayoutMain/LayoutMain.tsx +1 -1
  32. package/components/Layout/components/LayoutMain/components/LayoutMainContent/LayoutMainContent.tsx +1 -1
  33. package/components/Layout/components/LayoutNavigation/LayoutNavigation.tsx +1 -1
  34. package/components/Loading/Loading.tsx +10 -2
  35. package/components/Markdown/Markdown.meta.ts +7 -0
  36. package/components/Markdown/Markdown.tsx +15 -6
  37. package/components/Markdown/Markdown.types.ts +4 -1
  38. package/components/Markdown/Markdown.utils.spec.ts +3 -3
  39. package/components/Markdown/Markdown.utils.ts +9 -7
  40. package/components/Masonry/Masonry.meta.ts +1 -1
  41. package/components/Masonry/Masonry.tsx +2 -2
  42. package/components/Masonry/Masonry.types.ts +1 -1
  43. package/components/Menu/Menu.tsx +1 -3
  44. package/components/Menu/components/MenuCategory/MenuCategory.tsx +13 -2
  45. package/components/Menu/components/MenuFilter/MenuFilter.tsx +1 -1
  46. package/components/Menu/components/MenuItem/MenuItem.tsx +14 -1
  47. package/components/Overlay/Overlay.tsx +1 -1
  48. package/components/Pie/Pie.tsx +7 -4
  49. package/components/Pill/Pill.tsx +1 -1
  50. package/components/Placeholder/Placeholder.tsx +1 -0
  51. package/components/Progress/Progress.tsx +9 -1
  52. package/components/Radio/Radio.tsx +64 -58
  53. package/components/Segments/Segments.tsx +6 -6
  54. package/components/Select/Select.tsx +5 -4
  55. package/components/Separator/components/HorizontalSeparator/HorizontalSeparator.tsx +1 -1
  56. package/components/Separator/components/VerticalSeparator/VerticalSeparator.tsx +1 -1
  57. package/{components.css → components/Setup/Setup.components.css} +2 -2
  58. package/components/Setup/Setup.meta.ts +2 -2
  59. package/components/Setup/Setup.tsx +10 -7
  60. package/components/Setup/Setup.types.ts +1 -0
  61. package/components/Shimmer/Shimmer.tsx +3 -2
  62. package/components/Slider/Slider.tsx +4 -4
  63. package/components/Spacer/Spacer.tsx +1 -1
  64. package/components/Table/Table.tsx +1 -1
  65. package/components/Tabs/Tabs.tsx +36 -12
  66. package/components/Text/Text.tsx +5 -2
  67. package/components/Textarea/Textarea.tsx +10 -5
  68. package/components/Tile/Tile.tsx +2 -9
  69. package/components/Tile/Tile.types.ts +1 -1
  70. package/components/Timestamp/Timestamp.meta.ts +5 -1
  71. package/components/Timestamp/Timestamp.tsx +3 -3
  72. package/components/Timestamp/Timestamp.types.ts +1 -1
  73. package/components/Toggle/Toggle.tsx +2 -2
  74. package/components/Tooltip/Tooltip.module.css +32 -0
  75. package/components/Tooltip/Tooltip.tsx +36 -72
  76. package/components/Tooltip/Tooltip.types.ts +1 -0
  77. package/components/Tooltip/components/TooltipContent/TooltipContent.tsx +5 -3
  78. package/components/Tooltip/components/TooltipTrigger/TooltipTrigger.tsx +10 -4
  79. package/components/shared/InputLabel/InputLabel.tsx +1 -1
  80. package/components/shared/ResultList/ResultList.tsx +6 -7
  81. package/constants/hooks.ts +1 -1
  82. package/contexts/LayoutContext/LayoutContext.tsx +30 -20
  83. package/contexts/LayoutContext/LayoutContext.types.ts +1 -0
  84. package/hooks/useDebounce.tsx +2 -2
  85. package/hooks/useLayoutContext.tsx +1 -0
  86. package/hooks/usePrint.tsx +31 -0
  87. package/index.ts +4 -0
  88. package/package.json +20 -12
  89. package/utils/date.ts +54 -0
  90. package/utils/dayjs.ts +0 -21
@@ -3,7 +3,7 @@ import { ButtonGroup } from "../ButtonGroup"
3
3
  import { Flex } from "../Flex"
4
4
  import { Text } from "../Text"
5
5
  import { Icon } from "../Icon"
6
- import { getClasses } from "@heliosgraphics/utils/classnames"
6
+ import { getClasses } from "@heliosgraphics/utils"
7
7
  import { getColorClasses } from "../../utils/colors"
8
8
  import { INTENTION_COLOR_MAP } from "../../constants/intentions"
9
9
  import styles from "./Alert.module.css"
@@ -12,6 +12,6 @@ export const meta: HeliosAttributeMeta<BreadcrumbProps> = {
12
12
  _status: "nominal",
13
13
  _category: "content",
14
14
  items: {
15
- type: "Array<BreadCrumbItem>",
15
+ type: "Array<BreadcrumbItem>",
16
16
  },
17
17
  }
@@ -8,13 +8,13 @@ export const Breadcrumb: FC<BreadcrumbProps> = ({ items }) => {
8
8
  if (!items?.length) return null
9
9
 
10
10
  return (
11
- <Flex isYCentered={true} gap={2} isWrapped={true}>
12
- {items?.map((item, key) => {
13
- const isLast: boolean = Boolean(key + 1 === items?.length)
11
+ <Flex isYCentered={true} gap={2} isWrapped={true} data-ui-component="Breadcrumb">
12
+ {items?.map((item, index) => {
13
+ const isLast: boolean = Boolean(index + 1 === items?.length)
14
14
  const AComponent: ElementType = item.as || "a"
15
15
 
16
16
  return (
17
- <Fragment key={key}>
17
+ <Fragment key={item.href ?? item.name}>
18
18
  <AComponent
19
19
  href={item.href}
20
20
  onClick={item.onClick}
@@ -1,4 +1,4 @@
1
- import { getClasses } from "@heliosgraphics/utils/classnames"
1
+ import { getClasses } from "@heliosgraphics/utils"
2
2
  import styles from "./Browser.module.css"
3
3
  import type { BrowserProps } from "./Browser.types"
4
4
  import type { FC } from "react"
@@ -6,5 +6,9 @@ import type { FC } from "react"
6
6
  export const Browser: FC<BrowserProps> = ({ children }) => {
7
7
  const browserClasses: string = getClasses(styles.browser)
8
8
 
9
- return <div className={browserClasses}>{children}</div>
9
+ return (
10
+ <div className={browserClasses} data-ui-component="Browser">
11
+ {children}
12
+ </div>
13
+ )
10
14
  }
@@ -1,12 +1,12 @@
1
1
  "use client"
2
2
 
3
3
  import styles from "./Button.module.css"
4
- import { getClasses } from "@heliosgraphics/utils/classnames"
4
+ import { getClasses } from "@heliosgraphics/utils"
5
5
  import { Flex } from "../Flex"
6
6
  import { Icon } from "../Icon"
7
7
  import { Loading } from "../Loading"
8
8
  import { Text } from "../Text"
9
- import { useState, useId, type KeyboardEvent, type MouseEvent, type FC, useMemo } from "react"
9
+ import { useState, useId, memo, type KeyboardEvent, type MouseEvent, type FC, useMemo } from "react"
10
10
  import { getColorClasses } from "../../utils/colors"
11
11
  import { INTENTION_COLOR_MAP } from "../../constants/intentions"
12
12
  import type { HeliosIconType } from "../../types/icons"
@@ -25,179 +25,181 @@ const BUTTON_ICON_LABEL_SIZE: Record<string, number> = {
25
25
  normal: 16,
26
26
  }
27
27
 
28
- export const Button: FC<ButtonProps> = ({
29
- accept,
30
- appearance,
31
- badge,
32
- badgeIcon,
33
- color,
34
- flair,
35
- icon,
36
- iconLeft,
37
- iconRight,
38
- intent = "neutral",
39
- isDisabled,
40
- isIconOnly,
41
- isLoading,
42
- isRounded,
43
- multiple,
44
- onChange,
45
- onClick,
46
- role = "button",
47
- size = "normal",
48
- tabIndex,
49
- type = "button",
50
- value,
51
- ...restProps
52
- }) => {
53
- const [isActive, setIsActive] = useState<boolean>(false)
54
-
55
- const buttonId = useId()
56
- const isIconOnlyLoading: boolean = !!isIconOnly && !!isLoading
57
-
58
- const localIconLeft: HeliosIconType | undefined = icon || iconLeft
59
- const localIconRight: HeliosIconType | undefined = iconRight
60
-
61
- const consideredColor: HeliosColorType = color ? color : INTENTION_COLOR_MAP[intent]
62
- const consideredAppearance: HeliosAppearanceType = useMemo(
63
- () => (appearance ? appearance : consideredColor === "gray" ? "light" : "dark"),
64
- [appearance, consideredColor],
65
- )
66
-
67
- const colorClasses = getColorClasses(consideredColor, consideredAppearance)
68
- const buttonClasses = getClasses(styles.button, "relative cursor-pointer", ...colorClasses, {
69
- [styles.buttonLight]: consideredAppearance === "light",
70
-
71
- [styles.buttonActive]: isActive,
72
- [styles.buttonDisabled]: isDisabled,
73
- [styles.buttonLoading]: isLoading,
74
-
75
- [styles.buttonRounded]: isRounded,
76
- [styles.buttonRound]: !isRounded && size !== "tiny",
77
- [styles.buttonRoundTiny]: !isRounded && size === "tiny",
78
-
79
- [styles.buttonSizeNormal]: !size || size === "normal",
80
- [styles.buttonSizeSmall]: size === "small",
81
- [styles.buttonSizeTiny]: size === "tiny",
82
-
83
- [styles.buttonWithIconLeft]: localIconLeft,
84
- [styles.buttonWithIconRight]: localIconRight,
85
- [styles.buttonIconOnly]: isIconOnly,
86
- [styles.buttonIconOnlyLoading]: isIconOnlyLoading,
87
- })
88
-
89
- const buttonIconLeftClasses = getClasses("relative", styles.button__icon, {
90
- [styles.button__iconLeft]: localIconLeft,
91
- })
92
-
93
- const buttonIconRightClasses = getClasses("relative", styles.button__icon, {
94
- [styles.button__iconRight]: localIconRight,
95
- [styles.button__iconRightLoading]: isLoading,
96
- })
97
-
98
- const buttonLoadingSize: 10 | 20 = size && size !== "normal" ? 10 : 20
99
- const isFileType: boolean = type === "file"
100
- const showFileLabel: boolean = isFileType && !isIconOnly
101
-
102
- const baseInputClasses = getClasses(styles.button__baseElement, "sans fw-medium", {
103
- tiny: size === "tiny" || size === "small",
104
- "small ": size === "normal",
105
- "radius-max": isRounded,
106
- [styles.button__baseElementNormal]: size === "normal" && !isIconOnly,
107
- [styles.button__baseElementSmall]: size === "small" && !isIconOnly,
108
- [styles.button__baseElementTiny]: size === "tiny" && !isIconOnly,
109
- })
110
-
111
- const buttonLabelClasses: string = getClasses(baseInputClasses, styles.button__label)
112
- const buttonInputClasses: string = getClasses(baseInputClasses, styles.button__input, {
113
- [styles.button__inputFile]: isFileType,
114
- })
115
-
116
- const handleClick = (event: MouseEvent<HTMLDivElement>): void => {
117
- if (isDisabled || isLoading) {
28
+ export const Button: FC<ButtonProps> = memo(
29
+ ({
30
+ accept,
31
+ appearance,
32
+ badge,
33
+ badgeIcon,
34
+ color,
35
+ flair,
36
+ icon,
37
+ iconLeft,
38
+ iconRight,
39
+ intent = "neutral",
40
+ isDisabled,
41
+ isIconOnly,
42
+ isLoading,
43
+ isRounded,
44
+ multiple,
45
+ onChange,
46
+ onClick,
47
+ role = "button",
48
+ size = "normal",
49
+ tabIndex,
50
+ type = "button",
51
+ value,
52
+ ...restProps
53
+ }) => {
54
+ const [isActive, setIsActive] = useState<boolean>(false)
55
+
56
+ const buttonId = useId()
57
+ const isIconOnlyLoading: boolean = !!isIconOnly && !!isLoading
58
+
59
+ const localIconLeft: HeliosIconType | undefined = icon || iconLeft
60
+ const localIconRight: HeliosIconType | undefined = iconRight
61
+
62
+ const consideredColor: HeliosColorType = color ? color : INTENTION_COLOR_MAP[intent]
63
+ const consideredAppearance: HeliosAppearanceType = useMemo(
64
+ () => (appearance ? appearance : consideredColor === "gray" ? "light" : "dark"),
65
+ [appearance, consideredColor],
66
+ )
67
+
68
+ const colorClasses = getColorClasses(consideredColor, consideredAppearance)
69
+ const buttonClasses = getClasses(styles.button, "relative cursor-pointer", ...colorClasses, {
70
+ [styles.buttonLight]: consideredAppearance === "light",
71
+
72
+ [styles.buttonActive]: isActive,
73
+ [styles.buttonDisabled]: isDisabled,
74
+ [styles.buttonLoading]: isLoading,
75
+
76
+ [styles.buttonRounded]: isRounded,
77
+ [styles.buttonRound]: !isRounded && size !== "tiny",
78
+ [styles.buttonRoundTiny]: !isRounded && size === "tiny",
79
+
80
+ [styles.buttonSizeNormal]: !size || size === "normal",
81
+ [styles.buttonSizeSmall]: size === "small",
82
+ [styles.buttonSizeTiny]: size === "tiny",
83
+
84
+ [styles.buttonWithIconLeft]: localIconLeft,
85
+ [styles.buttonWithIconRight]: localIconRight,
86
+ [styles.buttonIconOnly]: isIconOnly,
87
+ [styles.buttonIconOnlyLoading]: isIconOnlyLoading,
88
+ })
89
+
90
+ const buttonIconLeftClasses = getClasses("relative", styles.button__icon, {
91
+ [styles.button__iconLeft]: localIconLeft,
92
+ })
93
+
94
+ const buttonIconRightClasses = getClasses("relative", styles.button__icon, {
95
+ [styles.button__iconRight]: localIconRight,
96
+ [styles.button__iconRightLoading]: isLoading,
97
+ })
98
+
99
+ const buttonLoadingSize: 10 | 20 = size && size !== "normal" ? 10 : 20
100
+ const isFileType: boolean = type === "file"
101
+ const showFileLabel: boolean = isFileType && !isIconOnly
102
+
103
+ const baseInputClasses = getClasses(styles.button__baseElement, "sans fw-medium", {
104
+ tiny: size === "tiny" || size === "small",
105
+ "small ": size === "normal",
106
+ "radius-max": isRounded,
107
+ [styles.button__baseElementNormal]: size === "normal" && !isIconOnly,
108
+ [styles.button__baseElementSmall]: size === "small" && !isIconOnly,
109
+ [styles.button__baseElementTiny]: size === "tiny" && !isIconOnly,
110
+ })
111
+
112
+ const buttonLabelClasses: string = getClasses(baseInputClasses, styles.button__label)
113
+ const buttonInputClasses: string = getClasses(baseInputClasses, styles.button__input, {
114
+ [styles.button__inputFile]: isFileType,
115
+ })
116
+
117
+ const handleClick = (event: MouseEvent<HTMLDivElement>): void => {
118
+ if (isDisabled || isLoading) {
119
+ event.preventDefault()
120
+ return
121
+ }
122
+
123
+ onClick?.(event)
124
+ }
125
+
126
+ const handleKeyUp = (): void => {
127
+ setIsActive(false)
128
+ }
129
+
130
+ const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
131
+ if (event.key !== "Enter" && event.key !== " ") return
118
132
  event.preventDefault()
119
- return
133
+
134
+ if (isDisabled || isLoading || !buttonId) return
135
+
136
+ setIsActive(true)
137
+ document.getElementById(buttonId)?.click()
120
138
  }
121
139
 
122
- onClick?.(event)
123
- }
124
-
125
- const handleKeyUp = (): void => {
126
- setIsActive(false)
127
- }
128
-
129
- const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
130
- if (event.key !== "Enter" && event.key !== " ") return
131
- event.preventDefault()
132
-
133
- if (isDisabled || isLoading || !buttonId) return
134
-
135
- setIsActive(true)
136
- document.getElementById(buttonId)?.click()
137
- }
138
-
139
- return (
140
- <Flex
141
- className={buttonClasses}
142
- isInline={true}
143
- isCentered={true}
144
- onKeyDown={handleKeyDown}
145
- onKeyUp={handleKeyUp}
146
- data-ui-component="Button"
147
- data-ui-size={size}
148
- aria-disabled={isDisabled || isLoading}
149
- aria-busy={isLoading}
150
- aria-label={isIconOnly ? value : undefined}
151
- tabIndex={isDisabled ? -1 : (tabIndex ?? 0)}
152
- role={role}
153
- {...(onClick && { onClick: handleClick })}
154
- {...restProps}
155
- >
156
- {localIconLeft && !isIconOnlyLoading && (
157
- <Flex className={buttonIconLeftClasses}>
158
- <Icon icon={localIconLeft} size={BUTTON_ICON_SIZE[size] || 24} />
159
- </Flex>
160
- )}
161
- <input
162
- id={buttonId}
140
+ return (
141
+ <Flex
142
+ className={buttonClasses}
143
+ isInline={true}
144
+ isCentered={true}
145
+ onKeyDown={handleKeyDown}
146
+ onKeyUp={handleKeyUp}
147
+ data-ui-component="Button"
148
+ data-ui-size={size}
163
149
  aria-disabled={isDisabled || isLoading}
164
- disabled={isDisabled || isLoading}
165
- type={type}
166
- className={buttonInputClasses}
167
- accept={accept}
168
- multiple={multiple}
169
- tabIndex={-1}
170
- onChange={onChange}
171
- defaultValue={isIconOnly || isFileType ? "" : value}
172
- />
173
- {showFileLabel && (
174
- <label htmlFor={buttonId} className={buttonLabelClasses}>
175
- {value}
176
- </label>
177
- )}
178
- {isLoading && <Loading size={buttonLoadingSize} className={styles.button__loading} />}
179
- {localIconRight && !isIconOnlyLoading && (
180
- <Flex className={buttonIconRightClasses}>
181
- <Icon icon={localIconRight} size={BUTTON_ICON_SIZE[size] || 24} />
182
- </Flex>
183
- )}
184
- {!!flair && (
185
- <Flex className={styles.button__flair} isCentered={true}>
186
- <Text type={size !== "normal" ? "micro" : "tiny"} fontFamily="mono">
187
- {flair}
188
- </Text>
189
- </Flex>
190
- )}
191
- {(!!badge || !!badgeIcon) && (
192
- <Flex className={styles.button__badge} isCentered={true} gap={2}>
193
- {badgeIcon && <Icon icon={badgeIcon} size={BUTTON_ICON_LABEL_SIZE[size] || 16} />}
194
- {badge && (
195
- <Text type={size !== "normal" ? "tiny" : "tiny"} fontFamily="mono" emphasis="inherit">
196
- {badge}
150
+ aria-busy={isLoading}
151
+ aria-label={isIconOnly ? value : undefined}
152
+ tabIndex={isDisabled ? -1 : (tabIndex ?? 0)}
153
+ role={role}
154
+ {...(onClick && { onClick: handleClick })}
155
+ {...restProps}
156
+ >
157
+ {localIconLeft && !isIconOnlyLoading && (
158
+ <Flex className={buttonIconLeftClasses}>
159
+ <Icon icon={localIconLeft} size={BUTTON_ICON_SIZE[size] || 24} />
160
+ </Flex>
161
+ )}
162
+ <input
163
+ id={buttonId}
164
+ aria-disabled={isDisabled || isLoading}
165
+ disabled={isDisabled || isLoading}
166
+ type={type}
167
+ className={buttonInputClasses}
168
+ accept={accept}
169
+ multiple={multiple}
170
+ tabIndex={-1}
171
+ onChange={onChange}
172
+ defaultValue={isIconOnly || isFileType ? "" : value}
173
+ />
174
+ {showFileLabel && (
175
+ <label htmlFor={buttonId} className={buttonLabelClasses}>
176
+ {value}
177
+ </label>
178
+ )}
179
+ {isLoading && <Loading size={buttonLoadingSize} className={styles.button__loading} />}
180
+ {localIconRight && !isIconOnlyLoading && (
181
+ <Flex className={buttonIconRightClasses}>
182
+ <Icon icon={localIconRight} size={BUTTON_ICON_SIZE[size] || 24} />
183
+ </Flex>
184
+ )}
185
+ {!!flair && (
186
+ <Flex className={styles.button__flair} isCentered={true}>
187
+ <Text type={size !== "normal" ? "micro" : "tiny"} fontFamily="mono">
188
+ {flair}
197
189
  </Text>
198
- )}
199
- </Flex>
200
- )}
201
- </Flex>
202
- )
203
- }
190
+ </Flex>
191
+ )}
192
+ {(!!badge || !!badgeIcon) && (
193
+ <Flex className={styles.button__badge} isCentered={true} gap={2}>
194
+ {badgeIcon && <Icon icon={badgeIcon} size={BUTTON_ICON_LABEL_SIZE[size] || 16} />}
195
+ {badge && (
196
+ <Text type="tiny" fontFamily="mono" emphasis="inherit">
197
+ {badge}
198
+ </Text>
199
+ )}
200
+ </Flex>
201
+ )}
202
+ </Flex>
203
+ )
204
+ },
205
+ )
@@ -1,7 +1,5 @@
1
- "use client"
2
-
3
- import { ButtonGroupProps } from "./ButtonGroup.types"
4
- import { getClasses } from "@heliosgraphics/utils/classnames"
1
+ import type { ButtonGroupProps } from "./ButtonGroup.types"
2
+ import { getClasses } from "@heliosgraphics/utils"
5
3
  import { Flex } from "../Flex"
6
4
  import styles from "./ButtonGroup.module.css"
7
5
  import type { FC } from "react"
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
- import { useId } from "react"
4
- import { getClasses } from "@heliosgraphics/utils/classnames"
3
+ import { useId, memo } from "react"
4
+ import { getClasses } from "@heliosgraphics/utils"
5
5
  import { getColorClasses } from "../../utils/colors"
6
6
  import { Flex } from "../Flex"
7
7
  import { Icon } from "../Icon"
@@ -10,60 +10,66 @@ import styles from "./Checkbox.module.css"
10
10
  import type { FC } from "react"
11
11
  import type { CheckboxProps } from "./Checkbox.types"
12
12
 
13
- export const Checkbox: FC<CheckboxProps> = ({
14
- color = "gray",
15
- isChecked,
16
- isVertical,
17
- isLabelHidden = false,
18
- isSmall,
19
- description,
20
- isDisabled,
21
- isRequired,
22
- onChange,
23
- label,
24
- }) => {
25
- const checkboxId: string = useId()
13
+ export const Checkbox: FC<CheckboxProps> = memo(
14
+ ({
15
+ color = "gray",
16
+ isChecked,
17
+ isVertical,
18
+ isLabelHidden = false,
19
+ isSmall,
20
+ description,
21
+ isDisabled,
22
+ isRequired,
23
+ onChange,
24
+ label,
25
+ }) => {
26
+ const checkboxId: string = useId()
26
27
 
27
- const colorClasses = getColorClasses(color, "dark")
28
- const checkboxClasses = getClasses(styles.checkbox, ...colorClasses, {
29
- [styles.checkboxDisabled]: isDisabled,
30
- [styles.checkboxSmall]: isSmall,
31
- })
28
+ const colorClasses = getColorClasses(color, "dark")
29
+ const checkboxClasses = getClasses(styles.checkbox, ...colorClasses, {
30
+ [styles.checkboxDisabled]: isDisabled,
31
+ [styles.checkboxSmall]: isSmall,
32
+ })
32
33
 
33
- const checkboxLabelClasses = getClasses(styles.checkbox__checkboxLabel, "flex gap-4", {
34
- "flex-x-center flex-column": isVertical,
35
- "flex-y-center": !isVertical,
36
- })
34
+ const checkboxLabelClasses = getClasses(styles.checkbox__checkboxLabel, "flex gap-4", {
35
+ "flex-x-center flex-column": isVertical,
36
+ "flex-y-center": !isVertical,
37
+ })
37
38
 
38
- return (
39
- <div className={checkboxClasses}>
40
- <label className={checkboxLabelClasses} htmlFor={checkboxId}>
41
- <span className={styles.checkbox__mark}>
42
- <input
43
- type="checkbox"
44
- checked={isChecked}
45
- onChange={onChange}
46
- disabled={isDisabled}
47
- required={isRequired}
48
- aria-label={isLabelHidden ? label : undefined}
49
- id={checkboxId}
50
- />
51
- <Icon icon="check" size={isSmall ? 14 : 18} className={styles.checkbox__checkboxIcon} />
52
- <div className={styles.checkbox__checkboxMark} />
53
- </span>
54
- {!isLabelHidden && (
55
- <Flex isColumn={true}>
56
- <Text type={isSmall ? "tiny" : "small"} fontWeight="medium" emphasis={isDisabled ? "tertiary" : "inherit"}>
57
- {label}
58
- </Text>
59
- {description && (
60
- <Text type="tiny" emphasis="secondary">
61
- {description}
39
+ return (
40
+ <div className={checkboxClasses} data-ui-component="Checkbox">
41
+ <label className={checkboxLabelClasses} htmlFor={checkboxId}>
42
+ <span className={styles.checkbox__mark}>
43
+ <input
44
+ type="checkbox"
45
+ checked={isChecked}
46
+ onChange={onChange}
47
+ disabled={isDisabled}
48
+ required={isRequired}
49
+ aria-label={isLabelHidden ? label : undefined}
50
+ id={checkboxId}
51
+ />
52
+ <Icon icon="check" size={isSmall ? 14 : 18} className={styles.checkbox__checkboxIcon} />
53
+ <div className={styles.checkbox__checkboxMark} />
54
+ </span>
55
+ {!isLabelHidden && (
56
+ <Flex isColumn={true}>
57
+ <Text
58
+ type={isSmall ? "tiny" : "small"}
59
+ fontWeight="medium"
60
+ emphasis={isDisabled ? "tertiary" : "inherit"}
61
+ >
62
+ {label}
62
63
  </Text>
63
- )}
64
- </Flex>
65
- )}
66
- </label>
67
- </div>
68
- )
69
- }
64
+ {description && (
65
+ <Text type="tiny" emphasis="secondary">
66
+ {description}
67
+ </Text>
68
+ )}
69
+ </Flex>
70
+ )}
71
+ </label>
72
+ </div>
73
+ )
74
+ },
75
+ )
@@ -23,5 +23,5 @@
23
23
 
24
24
  .clock__second {
25
25
  stroke: var(--ui-text-primary);
26
- transform: all 100ms linear;
26
+ transition: transform 100ms linear;
27
27
  }
@@ -34,7 +34,7 @@ export const Clock: FC<ClockProps> = () => {
34
34
  }
35
35
 
36
36
  return (
37
- <div className={styles.clock}>
37
+ <div className={styles.clock} data-ui-component="Clock">
38
38
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
39
39
  <g transform="translate(128,128)">
40
40
  <circle r="124" fill="none" strokeWidth="8" className={styles.clock__border} />
@@ -1,5 +1,5 @@
1
1
  import { getFlexUtility, getSafeFlexProps } from "../Flex/Flex.utils"
2
- import { getClasses } from "@heliosgraphics/utils/classnames"
2
+ import { getClasses } from "@heliosgraphics/utils"
3
3
  import type { ColumnProps } from "./Column.types"
4
4
  import type { FC } from "react"
5
5
 
@@ -15,5 +15,5 @@ export const Column: FC<ColumnProps> = (props) => {
15
15
  width: `${props.width ?? 960}px`,
16
16
  }
17
17
 
18
- return <div {...safeProps} style={columnStyle} className={columnClasses} />
18
+ return <div {...safeProps} style={columnStyle} className={columnClasses} data-ui-component="Column" />
19
19
  }
@@ -25,7 +25,7 @@ export const Confirm: FC<ConfirmProps> = ({
25
25
 
26
26
  return (
27
27
  <Dialog title={title} onClose={onCancel} isOpen={isOpen} isCentered={true}>
28
- <Flex gap={12} isColumn={true}>
28
+ <Flex gap={12} isColumn={true} data-ui-component="Confirm">
29
29
  {!!description && <Text type="paragraph">{description}</Text>}
30
30
  <ButtonGroup align={buttonGroupAlign}>
31
31
  {confirmOrder === "left" && confirmButton}
@@ -1,4 +1,4 @@
1
- import { getClasses } from "@heliosgraphics/utils/classnames"
1
+ import { getClasses } from "@heliosgraphics/utils"
2
2
  import styles from "./DatePicker.module.css"
3
3
  import type { DatePickerProps } from "./DatePicker.types"
4
4
  import type { FC } from "react"
@@ -6,5 +6,9 @@ import type { FC } from "react"
6
6
  export const DatePicker: FC<DatePickerProps> = ({ date }) => {
7
7
  const datePickerClasses: string = getClasses(styles.datePicker)
8
8
 
9
- return <div className={datePickerClasses}>{date}</div>
9
+ return (
10
+ <div className={datePickerClasses} data-ui-component="DatePicker">
11
+ {date}
12
+ </div>
13
+ )
10
14
  }
@@ -5,7 +5,7 @@ import { ButtonGroup } from "../ButtonGroup"
5
5
  import { Text } from "../Text"
6
6
  import { Flex } from "../Flex"
7
7
  import { Separator } from "../Separator"
8
- import { DebugProps } from "./Debug.types"
8
+ import type { DebugProps } from "./Debug.types"
9
9
  import styles from "./Debug.module.css"
10
10
  import { useState } from "react"
11
11
  import type { FC } from "react"
@@ -19,7 +19,7 @@ export const Debug: FC<DebugProps> = ({ color = "gray", appearance = "dark" }) =
19
19
  const [isClosed, setIsClosed] = useState(false)
20
20
 
21
21
  return (
22
- <Flex className={debugClasses}>
22
+ <Flex className={debugClasses} data-ui-component="Debug">
23
23
  <Flex isColumn={true} gap={4}>
24
24
  <Text type="micro" fontFamily="mono" emphasis="secondary">
25
25
  color: {color}, appearance: {appearance}