@heliosgraphics/ui 2.0.1-alpha.8 → 2.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,7 +49,6 @@
49
49
  box-shadow: inset 0 0 0 1px var(--border-active);
50
50
  }
51
51
 
52
- /* Reset */
53
52
  .button .button__baseElement {
54
53
  display: inline-flex;
55
54
 
@@ -68,7 +67,6 @@
68
67
  pointer-events: none;
69
68
  }
70
69
 
71
- /* Sizes */
72
70
  .buttonSizeNormal {
73
71
  --button-badge-size: 24px;
74
72
  --button-badge-margin: 8px;
@@ -136,7 +134,6 @@
136
134
  padding-inline: 7px;
137
135
  }
138
136
 
139
- /* Loading */
140
137
  .buttonLoading,
141
138
  .buttonDisabled {
142
139
  pointer-events: none;
@@ -174,7 +171,6 @@
174
171
  right: 6px;
175
172
  }
176
173
 
177
- /* Badge */
178
174
  .button__badge {
179
175
  z-index: 2;
180
176
 
@@ -187,7 +183,6 @@
187
183
  border-radius: var(--button-badge-radius);
188
184
  }
189
185
 
190
- /* Flair */
191
186
  .button__flair {
192
187
  position: absolute;
193
188
  top: var(--button-flair-offset);
@@ -203,7 +198,6 @@
203
198
  color: var(--text);
204
199
  }
205
200
 
206
- /* Icon */
207
201
  .buttonSizeNormal .button__iconLeft,
208
202
  .buttonSizeNormal .button__iconRight {
209
203
  padding-left: 8px;
@@ -235,7 +229,6 @@
235
229
  padding-right: 5px;
236
230
  }
237
231
 
238
- /* IconRight */
239
232
  .buttonSizeNormal:not(.buttonIconOnly) .button__iconRight {
240
233
  margin-left: -12px;
241
234
  }
@@ -253,7 +246,6 @@
253
246
  opacity: 0;
254
247
  }
255
248
 
256
- /* Icon:focus */
257
249
  .buttonSizeNormal.buttonIconOnly:not(.buttonIconOnlyLoading) .button__baseElement {
258
250
  margin-left: -40px;
259
251
  width: 40px;
@@ -73,7 +73,7 @@ export const getFlexUtility = (props?: FlexProps): string => {
73
73
  export const getResponsiveScale = (value?: ResponsiveScaleType, prefix: string = "p"): string => {
74
74
  if (!value) return ""
75
75
 
76
- const isArray: boolean = Boolean(value && value instanceof Array)
76
+ const isArray: boolean = Array.isArray(value)
77
77
  const classes = new Set<string>()
78
78
 
79
79
  if (!isArray) return `${prefix}-${value}`
@@ -92,7 +92,7 @@ export const getResponsiveScale = (value?: ResponsiveScaleType, prefix: string =
92
92
  export const getPadding = (paddingValue?: ResponsiveScaleType): string => {
93
93
  if (!paddingValue) return ""
94
94
 
95
- const isArray: boolean = Boolean(paddingValue && paddingValue instanceof Array)
95
+ const isArray: boolean = Array.isArray(paddingValue)
96
96
  const paddingClasses = new Set<string>()
97
97
 
98
98
  if (!isArray) return `p-${paddingValue}`
@@ -111,7 +111,7 @@ export const getPadding = (paddingValue?: ResponsiveScaleType): string => {
111
111
  export const getRadius = (radiusValue?: ResponsiveRadiusType): string => {
112
112
  if (!radiusValue) return ""
113
113
 
114
- const isArray: boolean = Boolean(radiusValue && radiusValue instanceof Array)
114
+ const isArray: boolean = Array.isArray(radiusValue)
115
115
  const radiusClasses = new Set<string>()
116
116
 
117
117
  if (!isArray) return `radius-${radiusValue}`
@@ -32,9 +32,7 @@ export const Heading: FC<HeadingProps> = (props) => {
32
32
  const lineHeightStyle: CSSProperties | undefined = lineHeight !== undefined ? { lineHeight } : undefined
33
33
 
34
34
  const mergedStyle: CSSProperties | undefined =
35
- style || lineClampStyle || lineHeightStyle
36
- ? { ...(style || {}), ...(lineClampStyle || {}), ...(lineHeightStyle || {}) }
37
- : undefined
35
+ style || lineClampStyle || lineHeightStyle ? { ...style, ...lineClampStyle, ...lineHeightStyle } : undefined
38
36
  const safeHeadingProps: Omit<HeadingProps, "level" | "lineClamp" | "lineHeight" | "className" | "style"> =
39
37
  stripTypographyProps(rest)
40
38
 
@@ -1,26 +1,25 @@
1
1
  .icon {
2
+ color: currentColor;
2
3
  transition: all var(--speed-sm) var(--ease-in-out-sine);
3
4
  }
4
5
 
5
6
  .icon svg {
6
7
  height: 100%;
7
8
  width: 100%;
9
+ }
8
10
 
9
- fill: currentcolor;
10
- stroke: currentcolor;
11
+ .iconPrimary {
12
+ color: var(--ui-text-primary);
11
13
  }
12
14
 
13
- .iconPrimary svg {
14
- fill: var(--ui-text-primary);
15
- stroke: var(--ui-text-primary);
15
+ .iconSecondary {
16
+ color: var(--ui-text-secondary);
16
17
  }
17
18
 
18
- .iconSecondary svg {
19
- fill: var(--ui-text-secondary);
20
- stroke: var(--ui-text-secondary);
19
+ .iconTertiary {
20
+ color: var(--ui-text-tertiary);
21
21
  }
22
22
 
23
- .iconTertiary svg {
24
- fill: var(--ui-text-tertiary);
25
- stroke: var(--ui-text-tertiary);
23
+ .iconInherit {
24
+ color: inherit;
26
25
  }
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from "bun:test"
2
+ import { icons } from "@heliosgraphics/icons"
3
+ import { readFileSync } from "fs"
4
+ import { dirname, join } from "path"
5
+ import { fileURLToPath } from "url"
6
+ import { getIconIdScope, getScopedIconSvg } from "./Icon.utils"
7
+
8
+ const __filename: string = fileURLToPath(import.meta.url)
9
+ const __dirname: string = dirname(__filename)
10
+
11
+ describe("Icon", () => {
12
+ it("should preserve fill-only, stroke-only, and mixed icon paint modes", () => {
13
+ expect(icons["triangle"]).toContain('fill="currentColor"')
14
+ expect(icons["triangle"]).not.toContain('stroke="currentColor"')
15
+
16
+ expect(icons["arrow-right"]).toContain('stroke="currentColor"')
17
+ expect(icons["arrow-right"]).not.toContain('fill="currentColor"')
18
+
19
+ expect(icons["tag"]).toContain('fill="currentColor"')
20
+ expect(icons["tag"]).toContain('stroke="currentColor"')
21
+ })
22
+
23
+ it("should not force fill or stroke on every svg", () => {
24
+ const iconStyles: string = readFileSync(join(__dirname, "Icon.module.css"), "utf8")
25
+
26
+ expect(iconStyles).toContain(".icon svg")
27
+ expect(iconStyles).not.toContain(".icon svg {\n\theight: 100%;\n\twidth: 100%;\n\n\tfill: currentcolor;")
28
+ expect(iconStyles).not.toContain("stroke: currentcolor;")
29
+ })
30
+
31
+ it("should scope svg definitions per icon instance", () => {
32
+ const scope: string = getIconIdScope(":r1:")
33
+ const actual: string = getScopedIconSvg(icons["layout-aside-right"], scope)
34
+
35
+ expect(actual).toContain(`id="${scope}-a"`)
36
+ expect(actual).toContain(`mask="url(#${scope}-a)"`)
37
+ expect(actual).not.toContain('id="a"')
38
+ expect(actual).not.toContain("url(#a)")
39
+ })
40
+ })
@@ -1,10 +1,15 @@
1
+ "use client"
2
+
1
3
  import { getClasses } from "@heliosgraphics/utils"
2
4
  import { icons } from "@heliosgraphics/icons"
3
5
  import styles from "./Icon.module.css"
4
- import type { FC } from "react"
6
+ import { useId, type FC } from "react"
7
+ import { getIconIdScope, getScopedIconSvg } from "./Icon.utils"
5
8
  import type { IconProps } from "./Icon.types"
6
9
 
7
10
  export const Icon: FC<IconProps> = ({ icon, className, emphasis, size }) => {
11
+ const iconId: string = getIconIdScope(useId())
12
+ const iconSvg: string = getScopedIconSvg(icons[icon] || "", iconId)
8
13
  const iconSizeStyle = {
9
14
  height: size + "px",
10
15
  minHeight: size + "px",
@@ -16,6 +21,7 @@ export const Icon: FC<IconProps> = ({ icon, className, emphasis, size }) => {
16
21
  [styles.iconPrimary]: emphasis === "primary",
17
22
  [styles.iconSecondary]: emphasis === "secondary",
18
23
  [styles.iconTertiary]: emphasis === "tertiary",
24
+ [styles.iconInherit]: emphasis === "inherit",
19
25
  })
20
26
 
21
27
  return (
@@ -25,7 +31,7 @@ export const Icon: FC<IconProps> = ({ icon, className, emphasis, size }) => {
25
31
  aria-hidden={true}
26
32
  data-ui-component="Icon"
27
33
  data-ui-icon={icon}
28
- dangerouslySetInnerHTML={{ __html: icons[icon] || "" }}
34
+ dangerouslySetInnerHTML={{ __html: iconSvg }}
29
35
  />
30
36
  )
31
37
  }
@@ -0,0 +1,11 @@
1
+ const HREF_REFERENCE_REGEX = /\b(href|xlink:href)="#([^"]+)"/g
2
+ const ID_ATTRIBUTE_REGEX = /\bid="([^"]+)"/g
3
+ const URL_REFERENCE_REGEX = /url\(#([^\)]+)\)/g
4
+
5
+ export const getIconIdScope = (id: string): string => `icon-${id.replace(/[^a-zA-Z0-9_-]/g, "")}`
6
+
7
+ export const getScopedIconSvg = (svg: string, scope: string): string =>
8
+ svg
9
+ .replace(ID_ATTRIBUTE_REGEX, `id="${scope}-$1"`)
10
+ .replace(URL_REFERENCE_REGEX, `url(#${scope}-$1)`)
11
+ .replace(HREF_REFERENCE_REGEX, `$1="#${scope}-$2"`)
@@ -1,8 +1,8 @@
1
1
  "use client"
2
2
 
3
3
  import type { FC } from "react"
4
- import { Button } from "../../../../../Button/Button"
5
- import { ButtonGroup } from "../../../../../ButtonGroup/ButtonGroup"
4
+ import { Button } from "../../../../../Button"
5
+ import { ButtonGroup } from "../../../../../ButtonGroup"
6
6
  import { useLayoutContext } from "../../../../../../hooks/useLayoutContext"
7
7
  import type { LayoutAsideToggleProps } from "./LayoutAsideToggle.types"
8
8
 
@@ -3,6 +3,10 @@
3
3
  let lastLocation: string | null = null
4
4
  let isHistoryPatched: boolean = false
5
5
 
6
+ const dispatchLocationChange = (): void => {
7
+ globalThis.dispatchEvent(new Event("locationchange"))
8
+ }
9
+
6
10
  const getLocationKey = (): string | null => {
7
11
  if (!globalThis?.location) return null
8
12
 
@@ -15,9 +19,6 @@ const patchHistory = (): void => {
15
19
  isHistoryPatched = true
16
20
 
17
21
  const { pushState, replaceState } = globalThis.history
18
- const dispatchLocationChange = (): void => {
19
- globalThis.dispatchEvent(new Event("locationchange"))
20
- }
21
22
 
22
23
  const pushStateWrapper = (...args: Parameters<History["pushState"]>): ReturnType<History["pushState"]> => {
23
24
  const result = pushState.apply(globalThis.history, args as Parameters<History["pushState"]>)
@@ -16,7 +16,7 @@ export const meta: HeliosAttributeMeta<MarkdownProps> = {
16
16
  isOptional: true,
17
17
  description: "Children to render inside the markdown wrapper",
18
18
  },
19
- allowLinks: {
19
+ isLinksAllowed: {
20
20
  type: "boolean",
21
21
  isOptional: true,
22
22
  description: "Preserves markdown links and auto-linked URLs in sanitized output",
@@ -67,7 +67,6 @@
67
67
  line-height: normal;
68
68
  }
69
69
 
70
- /* Element: Blockquote */
71
70
  .markdown blockquote {
72
71
  position: relative;
73
72
 
@@ -110,7 +109,6 @@
110
109
  line-height: inherit;
111
110
  }
112
111
 
113
- /* Element: Link */
114
112
  .markdown a {
115
113
  color: oklch(var(--ui-text-soft-l) var(--ui-chroma) var(--ui-blue));
116
114
 
@@ -118,7 +116,6 @@
118
116
  text-decoration: underline;
119
117
  }
120
118
 
121
- /* Element: List */
122
119
  .markdown ul li {
123
120
  list-style-type: disc;
124
121
  }
@@ -140,13 +137,11 @@
140
137
  list-style-type: circle;
141
138
  }
142
139
 
143
- /* Element: Separator */
144
140
  .markdown hr {
145
141
  border: 0;
146
142
  border-top: 1px solid var(--ui-border-secondary);
147
143
  }
148
144
 
149
- /* Element: Table */
150
145
  .markdown table {
151
146
  max-width: 100%;
152
147
 
@@ -181,7 +176,6 @@
181
176
  border-radius: var(--radius-md);
182
177
  }
183
178
 
184
- /* Element: Headings */
185
179
  .markdown h1 {
186
180
  font-size: var(--font-size-h1);
187
181
  line-height: var(--line-height-h1);
@@ -222,24 +216,20 @@
222
216
  line-height: var(--line-height-p);
223
217
  }
224
218
 
225
- /* Element: strong, bold: 700 */
226
219
  .markdown b,
227
220
  .markdown strong {
228
221
  font-weight: var(--font-weight-bold);
229
222
  }
230
223
 
231
- /* Element: Delete */
232
224
  .markdown del {
233
225
  text-decoration: line-through;
234
226
  }
235
227
 
236
- /* Element: Italic */
237
228
  .markdown i,
238
229
  .markdown em {
239
230
  font-style: italic;
240
231
  }
241
232
 
242
- /* Modifier: Code */
243
233
  .markdown *:not(pre) code {
244
234
  display: inline-block;
245
235
  padding: 0 4px;
@@ -4,7 +4,7 @@ import styles from "./Markdown.module.css"
4
4
  import type { FC } from "react"
5
5
  import type { MarkdownProps } from "./Markdown.types"
6
6
 
7
- export const Markdown: FC<MarkdownProps> = ({ text, children, isNonSelectable, allowLinks }) => {
7
+ export const Markdown: FC<MarkdownProps> = ({ text, children, isNonSelectable, isLinksAllowed }) => {
8
8
  if (!text && !children) return null
9
9
 
10
10
  const markdownClasses: string = getClasses(styles.markdown, {
@@ -12,7 +12,7 @@ export const Markdown: FC<MarkdownProps> = ({ text, children, isNonSelectable, a
12
12
  })
13
13
 
14
14
  if (text) {
15
- const innerHTML = { __html: renderMarkdown(text, { allowLinks }) }
15
+ const innerHTML = { __html: renderMarkdown(text, { allowLinks: !!isLinksAllowed }) }
16
16
 
17
17
  return <div className={markdownClasses} dangerouslySetInnerHTML={innerHTML} data-ui-component="Markdown"></div>
18
18
  }
@@ -1,8 +1,8 @@
1
1
  import type { ReactNode } from "react"
2
2
 
3
3
  export interface MarkdownProps {
4
- allowLinks?: boolean
5
4
  children?: ReactNode
5
+ isLinksAllowed?: boolean
6
6
  isNonSelectable?: boolean
7
7
  text?: string
8
8
  }
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from "bun:test"
2
+ import type { HeliosFixedThemeType } from "../../types/themes"
3
+ import { code } from "./Setup.utils"
4
+
5
+ describe("Setup", () => {
6
+ it("should execute when serialized into an inline script", () => {
7
+ const rootDataset: Record<string, string> = {}
8
+ const localStorageValues = new Map<string, string>()
9
+ const listeners: Record<string, (event: { matches: boolean }) => void> = {}
10
+
11
+ globalThis.__theme = "light" as HeliosFixedThemeType
12
+ globalThis.__onThemeChange = undefined
13
+ globalThis.__setPreferredTheme = (): void => {}
14
+ globalThis.document = {
15
+ documentElement: {
16
+ dataset: rootDataset,
17
+ },
18
+ } as Document
19
+ globalThis.localStorage = {
20
+ getItem: (key: string): string | null => localStorageValues.get(key) ?? null,
21
+ setItem: (key: string, value: string): void => {
22
+ localStorageValues.set(key, value)
23
+ },
24
+ } as Storage
25
+ globalThis.matchMedia = ((query: string): MediaQueryList => {
26
+ expect(query).toBe("(prefers-color-scheme: dark)")
27
+ return {
28
+ matches: true,
29
+ addEventListener: (type: string, listener: (event: { matches: boolean }) => void): void => {
30
+ listeners[type] = listener
31
+ },
32
+ } as MediaQueryList
33
+ }) as typeof globalThis.matchMedia
34
+
35
+ new Function(`return (${code.toString()})("system", undefined)`)()
36
+
37
+ expect(globalThis.__theme).toBe("dark")
38
+ expect(rootDataset["theme"]).toBe("dark")
39
+ expect(typeof listeners["change"]).toBe("function")
40
+
41
+ const changeListener = listeners["change"]
42
+ expect(changeListener).toBeDefined()
43
+ if (!changeListener) {
44
+ throw new Error("expected change listener to be registered")
45
+ }
46
+
47
+ changeListener({ matches: false })
48
+
49
+ expect(globalThis.__theme).toBe("light")
50
+ expect(rootDataset["theme"]).toBe("light")
51
+ expect(localStorageValues.get("theme")).toBe("light")
52
+ })
53
+ })
@@ -3,20 +3,18 @@ import type { HeliosFixedThemeType, HeliosThemeType } from "../../types/themes"
3
3
  export const code = (theme: HeliosThemeType = "system", fixedTheme?: HeliosFixedThemeType): void => {
4
4
  globalThis.__onThemeChange = function (_theme: HeliosFixedThemeType): void {}
5
5
 
6
+ /* eslint-disable-next-line unicorn/consistent-function-scoping */
6
7
  const setTheme = (newTheme: HeliosFixedThemeType): void => {
7
8
  globalThis.__theme = newTheme
8
9
  document.documentElement.dataset["theme"] = newTheme
9
10
  globalThis.__onThemeChange?.(newTheme)
10
11
  }
11
12
 
12
- const handleDocumentClick = (event: MouseEvent): void => {
13
- if (event.x > 256 && globalThis.location.hash === "#ui-menu") {
14
- globalThis.location.hash = "#ui"
15
- }
13
+ /* eslint-disable-next-line unicorn/consistent-function-scoping */
14
+ const handleDarkModeChange = (event: MediaQueryListEvent): void => {
15
+ globalThis.__setPreferredTheme(event.matches ? "dark" : "light")
16
16
  }
17
17
 
18
- document.addEventListener("click", handleDocumentClick)
19
-
20
18
  const isLocked: boolean = fixedTheme !== undefined || theme !== "system"
21
19
 
22
20
  if (fixedTheme !== undefined && theme !== "system") {
@@ -51,10 +49,6 @@ export const code = (theme: HeliosThemeType = "system", fixedTheme?: HeliosFixed
51
49
  }
52
50
  }
53
51
 
54
- const handleDarkModeChange = (event: MediaQueryListEvent): void => {
55
- globalThis.__setPreferredTheme(event.matches ? "dark" : "light")
56
- }
57
-
58
52
  darkQuery.addEventListener("change", handleDarkModeChange)
59
53
 
60
54
  setTheme(preferredTheme ?? (darkQuery.matches ? "dark" : "light"))
@@ -1,7 +1,4 @@
1
1
  @layer helios {
2
- /* TODO sync with css */
3
-
4
- /* background */
5
2
  .ui-bg,
6
3
  .ui-bg-primary {
7
4
  background-color: var(--ui-bg-primary);
@@ -20,7 +17,6 @@
20
17
  backdrop-filter: blur(3px);
21
18
  }
22
19
 
23
- /* radius utilities */
24
20
  .radius-none {
25
21
  border-radius: 0;
26
22
  }
@@ -53,7 +49,6 @@
53
49
  border-radius: 9999px;
54
50
  }
55
51
 
56
- /* scrollbar */
57
52
  .ui-scrollbar::-webkit-scrollbar {
58
53
  height: 8px;
59
54
  width: 8px;
@@ -84,7 +79,6 @@
84
79
  background-color: var(--ui-bg-soft-disabled-gray);
85
80
  }
86
81
 
87
- /* elevation */
88
82
  .elevation-sm {
89
83
  box-shadow: var(--ui-elevation-sm);
90
84
  }
@@ -97,7 +91,6 @@
97
91
  box-shadow: var(--ui-elevation-lg);
98
92
  }
99
93
 
100
- /* debug */
101
94
  .debug * {
102
95
  box-shadow: inset 0 0 0 1px var(--ui-bg-red);
103
96
  }
@@ -1,19 +1,13 @@
1
1
  import { getClasses } from "@heliosgraphics/utils"
2
2
  import { Text } from "../Text"
3
+ import { onTabKeyDown } from "./Tabs.utils"
3
4
  import styles from "./Tabs.module.css"
4
- import type { FC, KeyboardEvent } from "react"
5
+ import type { FC } from "react"
5
6
  import type { TabItem, TabsProps } from "./Tabs.types"
6
7
 
7
8
  export const Tabs: FC<TabsProps> = ({ items, children }) => {
8
9
  if (!items?.length) return null
9
10
 
10
- const onKeyDown = (event: KeyboardEvent<HTMLElement>, item: TabItem): void => {
11
- if (event.key === " " || event.key === "Enter") {
12
- event.preventDefault()
13
- item.onClick?.()
14
- }
15
- }
16
-
17
11
  return (
18
12
  <div data-ui-component="Tabs">
19
13
  <div role="tablist" className={styles.tabs__list}>
@@ -46,7 +40,7 @@ export const Tabs: FC<TabsProps> = ({ items, children }) => {
46
40
  <div
47
41
  {...commonProps}
48
42
  onClick={item.isDisabled ? undefined : item.onClick}
49
- onKeyDown={(e) => onKeyDown(e, item)}
43
+ onKeyDown={(event) => onTabKeyDown(event, item)}
50
44
  >
51
45
  <Text type="small" fontWeight="medium">
52
46
  {item.name}
@@ -0,0 +1,9 @@
1
+ import type { KeyboardEvent } from "react"
2
+ import type { TabItem } from "./Tabs.types"
3
+
4
+ export const onTabKeyDown = (event: KeyboardEvent<HTMLElement>, item: TabItem): void => {
5
+ if (event.key === " " || event.key === "Enter") {
6
+ event.preventDefault()
7
+ item.onClick?.()
8
+ }
9
+ }
@@ -28,7 +28,7 @@ export const Text: FC<TextProps> = (props) => {
28
28
  : undefined
29
29
 
30
30
  const mergedStyle: object | undefined =
31
- props.style || lineClampStyle ? { ...(props.style || {}), ...(lineClampStyle || {}) } : undefined
31
+ props.style || lineClampStyle ? { ...props.style, ...lineClampStyle } : undefined
32
32
 
33
33
  const baseTextProps: Omit<TextProps, "type"> = {
34
34
  onClick: props.onClick,
@@ -3,7 +3,6 @@
3
3
 
4
4
  background-color: var(--bg);
5
5
  border: 1px solid var(--border);
6
- border-radius: var(--radius-md);
7
6
  color: var(--text);
8
7
  overflow: hidden;
9
8
  transition: all var(--speed-sm) var(--ease-in-out-sine);
@@ -34,8 +34,8 @@ export const Tile: FC<TileProps> = ({
34
34
  const tileColorClasses: Array<string> = getColorClasses(resolvedColor, appearance)
35
35
  const tileClasses = getClasses(styles.tile, ...tileColorClasses, {
36
36
  [styles.tileLarge]: isLarge,
37
- ["radius-normal"]: isRounded,
38
- ["radius-max"]: isRound,
37
+ ["radius-md"]: isRounded,
38
+ ["radius-100"]: isRound,
39
39
  })
40
40
 
41
41
  return (
@@ -32,9 +32,9 @@ const RESULT_ITEMS: Array<ResultItem> = [
32
32
  onClick: () => null,
33
33
  description: "Nulla ultricies ultrices mauris, sed posuere justo ultrices in.",
34
34
  },
35
- { name: "Random Item", icon: "person" },
35
+ { name: "Random Item", icon: "user" },
36
36
  { name: "Active Item", icon: "bell", isActive: true },
37
- { name: "Lorem Ipsum Dolor Sit Ameta", icon: "x-x" },
37
+ { name: "Lorem Ipsum Dolor Sit Ameta", icon: "brand-x" },
38
38
  ]
39
39
 
40
40
  const MARKDOWN: string = `# Donec vestibulum
@@ -41,7 +41,6 @@ const LayoutProvider: FC<LayoutProviderProps> = ({ children, breakpoint = 960 })
41
41
  }
42
42
  }
43
43
 
44
- // Set initial state
45
44
  handleChange(mql)
46
45
 
47
46
  mql.addEventListener("change", handleChange)
@@ -3,6 +3,8 @@
3
3
  import { useCallback, useEffect, useState } from "react"
4
4
  import type { HeliosFixedThemeType } from "../types/themes"
5
5
 
6
+ const getTheme = (): HeliosFixedThemeType => (typeof globalThis !== "undefined" ? globalThis.__theme : "light")
7
+
6
8
  export const useTheme = (): { theme: HeliosFixedThemeType; isDark: boolean; toggleTheme: () => void } => {
7
9
  const [theme, setTheme] = useState<HeliosFixedThemeType | null>(null)
8
10
 
@@ -10,8 +12,6 @@ export const useTheme = (): { theme: HeliosFixedThemeType; isDark: boolean; togg
10
12
  setTheme(getTheme())
11
13
  }, [])
12
14
 
13
- const getTheme = (): HeliosFixedThemeType => (typeof globalThis !== "undefined" ? globalThis.__theme : "light")
14
-
15
15
  const toggleTheme = useCallback(() => {
16
16
  const currentIsDark: boolean = getTheme() === "dark"
17
17
  globalThis.__setPreferredTheme?.(currentIsDark ? "light" : "dark")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heliosgraphics/ui",
3
- "version": "2.0.1-alpha.8",
3
+ "version": "2.0.1-beta.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "*.css",
@@ -40,12 +40,12 @@
40
40
  "ts:watch": "tsc --noEmit --incremental --watch"
41
41
  },
42
42
  "dependencies": {
43
- "@heliosgraphics/css": "^1.0.0-alpha.9",
44
- "@heliosgraphics/icons": "^1.0.0-alpha.14",
45
- "@heliosgraphics/utils": "^6.0.0-alpha.15",
46
- "marked": "^17.0.5",
47
- "marked-linkify-it": "^3.1.14",
48
- "marked-xhtml": "^1.0.14",
43
+ "@heliosgraphics/css": "^1.0.0-alpha.10",
44
+ "@heliosgraphics/icons": "^1.0.0-beta.0",
45
+ "@heliosgraphics/utils": "^6.0.0-alpha.17",
46
+ "marked": "^18.0.3",
47
+ "marked-linkify-it": "^3.1.15",
48
+ "marked-xhtml": "^1.0.15",
49
49
  "react-plock": "^3.6.1"
50
50
  },
51
51
  "devDependencies": {
@@ -54,10 +54,10 @@
54
54
  "esbuild": "^0.28.0",
55
55
  "esbuild-css-modules-plugin": "^3.1.5",
56
56
  "glob": "^13.0.6",
57
- "jsdom": "^29.0.1",
58
- "next": "^16.2.2",
59
- "prettier": "^3.8.1",
60
- "typescript": "^6.0.2"
57
+ "jsdom": "^29.1.1",
58
+ "next": "^16.2.6",
59
+ "prettier": "^3.8.3",
60
+ "typescript": "^6.0.3"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@types/react": "^19",