@heliosgraphics/ui 2.0.0-alpha.98 → 2.0.0-alpha.99

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 (33) hide show
  1. package/components/Button/Button.spec.tsx +1 -1
  2. package/components/ButtonGroup/ButtonGroup.spec.tsx +1 -1
  3. package/components/Clock/Clock.tsx +1 -17
  4. package/components/Clock/Clock.utils.ts +16 -0
  5. package/components/Debug/Debug.tsx +1 -1
  6. package/components/Dialog/Dialog.meta.ts +2 -2
  7. package/components/Dialog/Dialog.tsx +3 -2
  8. package/components/Dialog/Dialog.types.ts +1 -1
  9. package/components/Dot/Dot.spec.tsx +1 -1
  10. package/components/Flex/Flex.tsx +6 -1
  11. package/components/Flex/Flex.utils.spec.ts +3 -3
  12. package/components/Input/Input.meta.ts +1 -1
  13. package/components/Input/Input.tsx +2 -2
  14. package/components/Input/Input.types.ts +1 -1
  15. package/components/Layout/components/LayoutAside/components/LayoutAsideToggle/LayoutAsideToggle.tsx +2 -0
  16. package/components/Layout/components/LayoutMain/components/LayoutMainContent/LayoutMainContent.tsx +7 -1
  17. package/components/Markdown/Markdown.utils.spec.ts +1 -1
  18. package/components/Menu/components/MenuFilter/MenuFilter.tsx +1 -1
  19. package/components/Segments/Segments.tsx +1 -1
  20. package/components/Segments/components/SegmentButton/SegmentButton.tsx +10 -2
  21. package/components/Separator/Separator.spec.tsx +1 -1
  22. package/components/Setup/Setup.tsx +1 -1
  23. package/components/Tabs/Tabs.tsx +0 -2
  24. package/components/Text/Text.utils.spec.ts +1 -1
  25. package/components/Timestamp/Timestamp.meta.ts +2 -2
  26. package/components/Timestamp/Timestamp.tsx +2 -2
  27. package/components/Timestamp/Timestamp.types.ts +1 -1
  28. package/contexts/LayoutContext/LayoutContext.tsx +3 -3
  29. package/contexts/LayoutContext/LayoutContext.types.ts +1 -1
  30. package/hooks/useLayoutContext.tsx +1 -1
  31. package/package.json +4 -10
  32. /package/components/Segments/{Segments.context.ts → Segments.utils.ts} +0 -0
  33. /package/components/Setup/{Setup.components.css → Setup.global.css} +0 -0
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest"
1
+ import { describe, expect, it } from "bun:test"
2
2
  import { Button } from "./Button"
3
3
 
4
4
  describe("Button", () => {
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest"
1
+ import { describe, expect, it } from "bun:test"
2
2
  import { ButtonGroup } from "./ButtonGroup"
3
3
 
4
4
  describe("ButtonGroup", () => {
@@ -2,26 +2,10 @@
2
2
 
3
3
  import { useId, useState, useEffect } from "react"
4
4
  import styles from "./Clock.module.css"
5
+ import { getRotation } from "./Clock.utils"
5
6
  import type { FC } from "react"
6
7
  import type { ClockProps } from "./Clock.types"
7
8
 
8
- const getRotation = (time: Date, type: "hours" | "minutes" | "seconds"): string => {
9
- const hours = time.getHours() % 12
10
- const minutes = time.getMinutes()
11
- const seconds = time.getSeconds()
12
-
13
- switch (type) {
14
- case "hours":
15
- return `rotate(${(hours + minutes / 60) * 30 - 180}, 0, 0)`
16
- case "minutes":
17
- return `rotate(${minutes * 6 - 180}, 0, 0)`
18
- case "seconds":
19
- return `rotate(${seconds * 6 - 180}, 0, 0)`
20
- default:
21
- return ""
22
- }
23
- }
24
-
25
9
  export const Clock: FC<ClockProps> = () => {
26
10
  const titleId: string = useId()
27
11
  const [time, setTime] = useState(() => new Date())
@@ -0,0 +1,16 @@
1
+ export const getRotation = (time: Date, type: "hours" | "minutes" | "seconds"): string => {
2
+ const hours = time.getHours() % 12
3
+ const minutes = time.getMinutes()
4
+ const seconds = time.getSeconds()
5
+
6
+ switch (type) {
7
+ case "hours":
8
+ return `rotate(${(hours + minutes / 60) * 30 - 180}, 0, 0)`
9
+ case "minutes":
10
+ return `rotate(${minutes * 6 - 180}, 0, 0)`
11
+ case "seconds":
12
+ return `rotate(${seconds * 6 - 180}, 0, 0)`
13
+ default:
14
+ return ""
15
+ }
16
+ }
@@ -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} data-ui-component="Debug">
22
+ <Flex className={debugClasses} role="status" 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}
@@ -12,7 +12,7 @@ export const meta: HeliosAttributeMeta<DialogBaseProps> = {
12
12
  {
13
13
  id: "ui-dialog-no-padding",
14
14
  description: "default dialog without content padding",
15
- content: `<Dialog isOpen={IS_OPEN} onClose={ON_TOGGLE_OPEN} title="Hello World" isNarrow={IS_NARROW} isCentered={IS_CENTERED} noPadding={true}>{CHILDREN}</Dialog>`,
15
+ content: `<Dialog isOpen={IS_OPEN} onClose={ON_TOGGLE_OPEN} title="Hello World" isNarrow={IS_NARROW} isCentered={IS_CENTERED} hasNoPadding={true}>{CHILDREN}</Dialog>`,
16
16
  },
17
17
  ],
18
18
  _status: "nominal",
@@ -29,7 +29,7 @@ export const meta: HeliosAttributeMeta<DialogBaseProps> = {
29
29
  type: "boolean",
30
30
  isOptional: true,
31
31
  },
32
- noPadding: {
32
+ hasNoPadding: {
33
33
  type: "boolean",
34
34
  description: "Removes padding from the Dialog content.",
35
35
  isOptional: true,
@@ -16,7 +16,7 @@ export const Dialog: FC<DialogProps> = ({
16
16
  isOpen,
17
17
  isCentered,
18
18
  onClose,
19
- noPadding,
19
+ hasNoPadding,
20
20
  role,
21
21
  }) => {
22
22
  const dialogRef = useRef<HTMLDialogElement | null>(null)
@@ -69,7 +69,7 @@ export const Dialog: FC<DialogProps> = ({
69
69
  })
70
70
  const dialogFlexClasses: string = getClasses(styles.dialog__header, "sticky top-0 z-50 ui-bg-glass")
71
71
  const dialogContentClasses: string = getClasses(styles.dialog__content, {
72
- [styles.dialog__contentNoPadding]: noPadding,
72
+ [styles.dialog__contentNoPadding]: hasNoPadding,
73
73
  })
74
74
 
75
75
  return (
@@ -79,6 +79,7 @@ export const Dialog: FC<DialogProps> = ({
79
79
  onClick={onDialogClose}
80
80
  onCancel={onCancel}
81
81
  role={role}
82
+ aria-modal="true"
82
83
  data-ui-component="Dialog"
83
84
  >
84
85
  {!!title && (
@@ -4,7 +4,7 @@ export interface DialogBaseProps {
4
4
  isCentered?: boolean
5
5
  isNarrow?: boolean
6
6
  isOpen?: boolean
7
- noPadding?: boolean
7
+ hasNoPadding?: boolean
8
8
  onClose: (_?: unknown) => Promise<void> | void
9
9
  role?: "dialog" | "alertdialog"
10
10
  title?: string
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest"
1
+ import { describe, expect, it } from "bun:test"
2
2
  import { Dot } from "./Dot"
3
3
 
4
4
  describe("Dot", () => {
@@ -15,7 +15,12 @@ export const Flex: FC<FlexProps> = (props) => {
15
15
  }
16
16
 
17
17
  const a11yProps = restProps.onClick
18
- ? { role: (restProps.role ?? "button") as string, tabIndex: restProps.tabIndex ?? 0, onKeyDown: handleKeyDown }
18
+ ? {
19
+ role: (restProps.role ?? "button") as string,
20
+ tabIndex: restProps.tabIndex ?? 0,
21
+ onKeyDown: handleKeyDown,
22
+ "aria-label": restProps["aria-label"],
23
+ }
19
24
  : {}
20
25
 
21
26
  return (
@@ -1,4 +1,4 @@
1
- import { it, describe, expect } from "vitest"
1
+ import { it, describe, expect } from "bun:test"
2
2
  import { getFlexUtility, getSafeFlexProps } from "./Flex.utils"
3
3
  import type { FlexProps } from "./Flex.types"
4
4
 
@@ -86,11 +86,11 @@ describe("getSafeFlexProps", () => {
86
86
  xAlign: "start",
87
87
  yAlign: "start",
88
88
  }
89
- const MOCK_FLEX_ATTRIBUTES_SAFE: FlexProps = {
89
+ const MOCK_FLEX_ATTRIBUTES_SAFE = {
90
90
  children: null,
91
91
  className: "xo",
92
92
  draggable: true,
93
- }
93
+ } as Record<string, unknown>
94
94
 
95
95
  it("Generates without invalid attributes", () =>
96
96
  expect(getSafeFlexProps(MOCK_FLEX_ATTRIBUTES)).toEqual(MOCK_FLEX_ATTRIBUTES_SAFE))
@@ -43,7 +43,7 @@ export const meta: HeliosAttributeMeta<InputProps> = {
43
43
  onKeyUp: { type: "string", isOptional: true },
44
44
  placeholder: { type: "string", isOptional: true },
45
45
  results: { type: "Array<ResultItem>", isOptional: true },
46
- showResults: { type: "boolean", isOptional: true },
46
+ isResultsVisible: { type: "boolean", isOptional: true },
47
47
  type: {
48
48
  type: '"text" | "email" | "date" | "time" | "password"',
49
49
  isOptional: true,
@@ -36,7 +36,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
36
36
  onKeyUp,
37
37
  placeholder,
38
38
  results,
39
- showResults,
39
+ isResultsVisible,
40
40
  type = "text",
41
41
  value,
42
42
  },
@@ -56,7 +56,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
56
56
  })
57
57
  .filter(Boolean) || []
58
58
 
59
- const showingResults: boolean = Boolean(!!filteredItems?.length && showResults)
59
+ const showingResults: boolean = Boolean(!!filteredItems?.length && isResultsVisible)
60
60
 
61
61
  const inputClasses: string = getClasses(styles.input, "relative flex flex-column", className, {
62
62
  [styles.inputDisabled]: isDisabled,
@@ -22,7 +22,7 @@ export interface InputProps {
22
22
  onKeyUp?: KeyboardEventHandler
23
23
  placeholder?: string
24
24
  results?: Array<ResultItem>
25
- showResults?: boolean
25
+ isResultsVisible?: boolean
26
26
  type?: "text" | "email" | "date" | "time" | "password"
27
27
  value?: string
28
28
  }
@@ -21,6 +21,8 @@ export const LayoutAsideToggle: FC<LayoutAsideToggleProps> = () => {
21
21
  data-ui-layout-ignore="true"
22
22
  onClick={isMenuVisible ? onAsideClose : onNavigationToggle}
23
23
  size="small"
24
+ aria-expanded={isMenuVisible}
25
+ aria-label={isMenuVisible ? "Close navigation" : "Open navigation"}
24
26
  />
25
27
  </ButtonGroup>
26
28
  )
@@ -34,7 +34,13 @@ export const LayoutMainContent: FC<LayoutMainContentProps> = (props) => {
34
34
  })
35
35
 
36
36
  return (
37
- <section {...safeProps} ref={contentRef} className={mainContentClasses} data-ui-component="Main.Content">
37
+ <section
38
+ {...safeProps}
39
+ ref={contentRef}
40
+ className={mainContentClasses}
41
+ role="main"
42
+ data-ui-component="Main.Content"
43
+ >
38
44
  {props.children}
39
45
  </section>
40
46
  )
@@ -1,4 +1,4 @@
1
- import { it, describe, expect } from "vitest"
1
+ import { it, describe, expect } from "bun:test"
2
2
  import { renderMarkdown } from "./Markdown.utils"
3
3
 
4
4
  describe("markdown", () => {
@@ -8,7 +8,7 @@ export const MenuFilter: FC<MenuFilterProps> = ({ value, onClear, onChange }) =>
8
8
  const menuFilterClasses: string = getClasses(styles.menuFilter, "ui-bg-glass")
9
9
 
10
10
  return (
11
- <div className={menuFilterClasses} data-ui-component="Menu.Filter">
11
+ <div className={menuFilterClasses} role="search" data-ui-component="Menu.Filter">
12
12
  <Input
13
13
  {...(onClear && { onClear })}
14
14
  placeholder="Search"
@@ -4,7 +4,7 @@ import { type FC, useState, useRef, useEffect, useCallback } from "react"
4
4
  import { Flex } from "../Flex"
5
5
  import styles from "./Segments.module.css"
6
6
  import { getClasses } from "@heliosgraphics/utils"
7
- import { SegmentsContext } from "./Segments.context"
7
+ import { SegmentsContext } from "./Segments.utils"
8
8
  import type { SegmentsProps } from "./Segments.types"
9
9
 
10
10
  export const Segments: FC<SegmentsProps> = ({ children, isFullWidth, isSmall, defaultValue }) => {
@@ -1,7 +1,9 @@
1
+ "use client"
2
+
1
3
  import styles from "./SegmentButton.module.css"
2
4
  import { getClasses } from "@heliosgraphics/utils"
3
5
  import { Icon } from "../../../Icon"
4
- import { useSegments } from "../../Segments.context"
6
+ import { useSegments } from "../../Segments.utils"
5
7
  import { useCallback, type FC } from "react"
6
8
  import type { HeliosIconType } from "../../../../types/icons"
7
9
  import type { SegmentButtonProps } from "./SegmentButton.types"
@@ -36,7 +38,13 @@ export const SegmentButton: FC<SegmentButtonProps> = ({
36
38
  )
37
39
 
38
40
  return (
39
- <button ref={handleRef} className={segmentButtonClasses} onClick={handleClick} data-ui-component="SegmentButton">
41
+ <button
42
+ ref={handleRef}
43
+ className={segmentButtonClasses}
44
+ onClick={handleClick}
45
+ aria-pressed={isActive}
46
+ data-ui-component="SegmentButton"
47
+ >
40
48
  {iconL && <Icon icon={iconL} size={16} />}
41
49
  {value}
42
50
  {iconRight && <Icon icon={iconRight} size={16} />}
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from "vitest"
1
+ import { describe, expect, it } from "bun:test"
2
2
  import { Separator } from "./Separator"
3
3
 
4
4
  describe("Separator", () => {
@@ -1,4 +1,4 @@
1
- import "./Setup.components.css"
1
+ import "./Setup.global.css"
2
2
 
3
3
  import type { FC } from "react"
4
4
  import type { SetupLinkProps, SetupProps } from "./Setup.types"
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import { getClasses } from "@heliosgraphics/utils"
4
2
  import { Text } from "../Text"
5
3
  import styles from "./Tabs.module.css"
@@ -1,4 +1,4 @@
1
- import { it, describe, expect } from "vitest"
1
+ import { it, describe, expect } from "bun:test"
2
2
  import { _getFontWeight } from "./Text.utils"
3
3
  import type { TextProps } from "./Text.types"
4
4
 
@@ -6,7 +6,7 @@ export const meta: HeliosAttributeMeta<TimestampProps> = {
6
6
  {
7
7
  id: "ui-timestamp-default",
8
8
  description: "default",
9
- content: `<Timestamp date={DATE} fromNow={false} format={DATE_FORMAT}/>`,
9
+ content: `<Timestamp date={DATE} isRelative={false} format={DATE_FORMAT}/>`,
10
10
  },
11
11
  ],
12
12
  _status: "nominal",
@@ -17,6 +17,6 @@ export const meta: HeliosAttributeMeta<TimestampProps> = {
17
17
  isOptional: true,
18
18
  default: "{ year: numeric, month: long, day: numeric }",
19
19
  },
20
- fromNow: { type: "boolean", isOptional: true },
20
+ isRelative: { type: "boolean", isOptional: true },
21
21
  text: { type: "string", isOptional: true },
22
22
  }
@@ -2,13 +2,13 @@ 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, isRelative, 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() : ""
9
9
 
10
10
  const timestampDate: string = isValid ? parsedIsoString : ""
11
- const formattedDate: string = fromNow ? fromNowDate : formatDate(date, format)
11
+ const formattedDate: string = isRelative ? fromNowDate : formatDate(date, format)
12
12
 
13
13
  return (
14
14
  <time dateTime={timestampDate} suppressHydrationWarning={true} data-ui-component="Timestamp">
@@ -1,6 +1,6 @@
1
1
  export interface TimestampProps {
2
2
  date?: string
3
3
  format?: Intl.DateTimeFormatOptions
4
- fromNow?: boolean
4
+ isRelative?: boolean
5
5
  text?: string
6
6
  }
@@ -69,7 +69,7 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
69
69
  }
70
70
  }, [breakpoint])
71
71
 
72
- const shouldShowNavigation: boolean = isWideEnough || isMenuVisible
72
+ const isNavigationVisible: boolean = isWideEnough || isMenuVisible
73
73
 
74
74
  const onNavigationToggle = useCallback((): void => setIsMenuVisible((prev) => !prev), [])
75
75
  const onAsideClose = useCallback((): void => setIsMenuVisible(false), [])
@@ -82,9 +82,9 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
82
82
  isWideEnough,
83
83
  onAsideClose,
84
84
  onNavigationToggle,
85
- shouldShowNavigation,
85
+ isNavigationVisible,
86
86
  }),
87
- [hasMounted, isMenuVisible, isWideEnough, shouldShowNavigation, onAsideClose, onNavigationToggle],
87
+ [hasMounted, isMenuVisible, isWideEnough, isNavigationVisible, onAsideClose, onNavigationToggle],
88
88
  )
89
89
 
90
90
  return <LayoutContext.Provider value={contextValue}>{children}</LayoutContext.Provider>
@@ -7,5 +7,5 @@ export interface LayoutContextProps {
7
7
  isWideEnough: boolean
8
8
  onAsideClose: () => void
9
9
  onNavigationToggle: () => void
10
- shouldShowNavigation: boolean
10
+ isNavigationVisible: boolean
11
11
  }
@@ -11,7 +11,7 @@ const DEFAULT_LAYOUT_CONTEXT: LayoutContextProps = {
11
11
  isWideEnough: true,
12
12
  onAsideClose: () => {},
13
13
  onNavigationToggle: () => {},
14
- shouldShowNavigation: true,
14
+ isNavigationVisible: true,
15
15
  }
16
16
 
17
17
  export const useLayoutContext = (): LayoutContextProps => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heliosgraphics/ui",
3
- "version": "2.0.0-alpha.98",
3
+ "version": "2.0.0-alpha.99",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "*.css",
@@ -35,10 +35,8 @@
35
35
  ],
36
36
  "scripts": {
37
37
  "pub:components": "bun publish --access public",
38
- "test": "NODE_ENV=test vitest run",
39
- "test:coverage": "NODE_ENV=test vitest run --coverage",
40
- "test:update": "NODE_ENV=test vitest run --update",
41
- "test:watch": "NODE_ENV=test vitest",
38
+ "test": "bun test",
39
+ "test:watch": "bun test --watch",
42
40
  "ts:watch": "tsc --noEmit --incremental --watch"
43
41
  },
44
42
  "dependencies": {
@@ -52,17 +50,13 @@
52
50
  "devDependencies": {
53
51
  "@testing-library/react": "^16.3.2",
54
52
  "@types/node": "^25",
55
- "@vitejs/plugin-react": "^5.1.4",
56
- "@vitest/coverage-v8": "^4.0.18",
57
53
  "esbuild": "^0.27.3",
58
54
  "esbuild-css-modules-plugin": "^3.1.5",
59
55
  "glob": "^13.0.6",
60
56
  "jsdom": "^28.1.0",
61
57
  "next": "^16.1.6",
62
58
  "prettier": "^3.8.1",
63
- "typescript": "^5.9.3",
64
- "vite": "^7.3.1",
65
- "vitest": "^4.0.18"
59
+ "typescript": "^5.9.3"
66
60
  },
67
61
  "peerDependencies": {
68
62
  "@types/react": "^19",