@stack-spot/portal-layout 0.0.52 → 0.0.53

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 (97) hide show
  1. package/dist/Layout.d.ts +2 -2
  2. package/dist/Layout.js +1 -1
  3. package/dist/LayoutOverlayManager.js +6 -6
  4. package/dist/LayoutOverlayManager.js.map +1 -1
  5. package/dist/components/Dialog.d.ts +1 -1
  6. package/dist/components/Dialog.js +1 -1
  7. package/dist/components/Header.d.ts +1 -1
  8. package/dist/components/Header.js +1 -1
  9. package/dist/components/OverlayContent.d.ts +1 -1
  10. package/dist/components/OverlayContent.js +20 -20
  11. package/dist/components/PortalSwitcher.d.ts +1 -1
  12. package/dist/components/PortalSwitcher.js +54 -54
  13. package/dist/components/SelectionList.d.ts +1 -1
  14. package/dist/components/SelectionList.js +54 -54
  15. package/dist/components/SelectionList.js.map +1 -1
  16. package/dist/components/Toaster.d.ts +1 -1
  17. package/dist/components/Toaster.js +1 -1
  18. package/dist/components/UserMenu.d.ts +1 -1
  19. package/dist/components/UserMenu.js +41 -41
  20. package/dist/components/error/ErrorBoundary.d.ts +1 -1
  21. package/dist/components/error/ErrorBoundary.js +1 -1
  22. package/dist/components/error/ErrorFeedback.d.ts +1 -1
  23. package/dist/components/error/ErrorFeedback.js +1 -1
  24. package/dist/components/error/SilentErrorBoundary.d.ts +1 -1
  25. package/dist/components/error/SilentErrorBoundary.js +1 -1
  26. package/dist/components/menu/MenuContent.d.ts +12 -10
  27. package/dist/components/menu/MenuContent.d.ts.map +1 -1
  28. package/dist/components/menu/MenuContent.js +146 -146
  29. package/dist/components/menu/MenuContent.js.map +1 -1
  30. package/dist/components/menu/MenuSections.d.ts +1 -1
  31. package/dist/components/menu/MenuSections.js +1 -1
  32. package/dist/components/menu/MenuSections.js.map +1 -1
  33. package/dist/components/menu/PageSelector.d.ts +1 -1
  34. package/dist/components/menu/PageSelector.js +65 -65
  35. package/dist/components/menu/PageSelector.js.map +1 -1
  36. package/dist/components/menu/use-check-text-overflow.js.map +1 -1
  37. package/dist/layout-context.d.ts +1 -1
  38. package/dist/layout-context.js +1 -1
  39. package/dist/layout.css +466 -466
  40. package/dist/svg/AI.d.ts +1 -1
  41. package/dist/svg/AI.js +1 -1
  42. package/dist/svg/EDP.d.ts +1 -1
  43. package/dist/svg/EDP.js +1 -1
  44. package/dist/svg/Forbidden.d.ts +1 -1
  45. package/dist/svg/Forbidden.js +1 -1
  46. package/dist/svg/HUB.d.ts +1 -1
  47. package/dist/svg/HUB.js +1 -1
  48. package/dist/svg/Logo.d.ts +1 -1
  49. package/dist/svg/Logo.js +1 -1
  50. package/dist/svg/NotFound.d.ts +1 -1
  51. package/dist/svg/NotFound.js +1 -1
  52. package/dist/svg/ServerError.d.ts +1 -1
  53. package/dist/svg/ServerError.js +1 -1
  54. package/dist/svg/Unauthenticated.d.ts +1 -1
  55. package/dist/svg/Unauthenticated.js +1 -1
  56. package/dist/toaster.js +2 -2
  57. package/dist/toaster.js.map +1 -1
  58. package/dist/utils.js.map +1 -1
  59. package/package.json +5 -5
  60. package/src/Layout.tsx +106 -106
  61. package/src/LayoutOverlayManager.tsx +273 -273
  62. package/src/components/Dialog.tsx +93 -93
  63. package/src/components/Header.tsx +34 -34
  64. package/src/components/OverlayContent.tsx +58 -58
  65. package/src/components/PortalSwitcher.tsx +147 -147
  66. package/src/components/SelectionList.tsx +272 -272
  67. package/src/components/Toaster.tsx +16 -16
  68. package/src/components/UserMenu.tsx +111 -111
  69. package/src/components/error/ErrorBoundary.tsx +38 -38
  70. package/src/components/error/ErrorFeedback.tsx +114 -114
  71. package/src/components/error/ErrorManager.ts +31 -31
  72. package/src/components/error/SilentErrorBoundary.tsx +54 -54
  73. package/src/components/menu/MenuContent.tsx +296 -296
  74. package/src/components/menu/MenuSections.tsx +270 -270
  75. package/src/components/menu/PageSelector.tsx +154 -154
  76. package/src/components/menu/constants.ts +2 -2
  77. package/src/components/menu/types.ts +112 -112
  78. package/src/components/menu/use-check-text-overflow.tsx +26 -26
  79. package/src/components/menu/use-keyboard-controls.tsx +70 -70
  80. package/src/components/types.ts +15 -15
  81. package/src/dictionary.ts +25 -25
  82. package/src/elements.ts +24 -24
  83. package/src/errors.ts +11 -11
  84. package/src/index.ts +17 -17
  85. package/src/layout-context.tsx +22 -22
  86. package/src/layout.css +466 -466
  87. package/src/svg/AI.tsx +37 -37
  88. package/src/svg/EDP.tsx +35 -35
  89. package/src/svg/Forbidden.tsx +22 -22
  90. package/src/svg/HUB.tsx +35 -35
  91. package/src/svg/Logo.tsx +35 -35
  92. package/src/svg/NotFound.tsx +16 -16
  93. package/src/svg/ServerError.tsx +33 -33
  94. package/src/svg/Unauthenticated.tsx +16 -16
  95. package/src/toaster.tsx +76 -76
  96. package/src/utils.ts +114 -114
  97. package/tsconfig.json +8 -8
@@ -1,70 +1,70 @@
1
- import { useCallback, useRef } from 'react'
2
-
3
- interface Props {
4
- /**
5
- * A query selector that returns every html element that must be navigable through the keyboard.
6
- */
7
- querySelectors: string,
8
- /**
9
- * Function to call when ESC is pressed. or when TAB is pressed at the last item in the list of items returned by the query selector.
10
- */
11
- onPressEscape?: () => void,
12
- /**
13
- * Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
14
- * onPressEscape if not specified.
15
- */
16
- onPressLastTab?: () => void,
17
- }
18
-
19
- export function useKeyboardControls({ querySelectors, onPressEscape, onPressLastTab = onPressEscape }: Props) {
20
- const keyboardControlledElement = useRef<HTMLDivElement>(null)
21
- const listeners = useRef<Pick<Props, 'onPressEscape' | 'onPressLastTab'>>({})
22
- listeners.current = { onPressEscape, onPressLastTab }
23
-
24
- const keyboardControls = useCallback((event: KeyboardEvent) => {
25
- const target = event?.target as HTMLElement | null
26
-
27
- function getSelectableAnchors() {
28
- return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? []
29
- }
30
-
31
- function handleArrows(key = event.key) {
32
- const anchors = getSelectableAnchors()
33
- let i = 0
34
- while (i < anchors.length && document.activeElement !== anchors[i]) i++
35
- const next: any = key === 'ArrowDown' ? (anchors[i + 1] ?? anchors[0]) : (anchors[i - 1] ?? anchors[anchors.length - 1])
36
- next?.focus?.()
37
- }
38
-
39
- const handlers: Record<string, (() => void) | undefined> = {
40
- Escape: () => {
41
- listeners.current.onPressEscape?.()
42
- event.stopPropagation()
43
- event.preventDefault()
44
- },
45
- Enter: () => {
46
- target?.click()
47
- },
48
- Tab: () => {
49
- const anchors = getSelectableAnchors()
50
- if (document.activeElement === anchors[anchors.length - 1]) listeners.current.onPressLastTab?.()
51
- else handleArrows('ArrowDown')
52
- event.preventDefault()
53
- },
54
- ArrowUp: handleArrows,
55
- ArrowDown: handleArrows,
56
- }
57
-
58
- handlers[event.key]?.()
59
- }, [])
60
-
61
- const attachKeyboardListeners = useCallback(() => {
62
- document.addEventListener('keydown', keyboardControls)
63
- }, [])
64
-
65
- const detachKeyboardListeners = useCallback(() => {
66
- document.removeEventListener('keydown', keyboardControls)
67
- }, [])
68
-
69
- return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners }
70
- }
1
+ import { useCallback, useRef } from 'react'
2
+
3
+ interface Props {
4
+ /**
5
+ * A query selector that returns every html element that must be navigable through the keyboard.
6
+ */
7
+ querySelectors: string,
8
+ /**
9
+ * Function to call when ESC is pressed. or when TAB is pressed at the last item in the list of items returned by the query selector.
10
+ */
11
+ onPressEscape?: () => void,
12
+ /**
13
+ * Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
14
+ * onPressEscape if not specified.
15
+ */
16
+ onPressLastTab?: () => void,
17
+ }
18
+
19
+ export function useKeyboardControls({ querySelectors, onPressEscape, onPressLastTab = onPressEscape }: Props) {
20
+ const keyboardControlledElement = useRef<HTMLDivElement>(null)
21
+ const listeners = useRef<Pick<Props, 'onPressEscape' | 'onPressLastTab'>>({})
22
+ listeners.current = { onPressEscape, onPressLastTab }
23
+
24
+ const keyboardControls = useCallback((event: KeyboardEvent) => {
25
+ const target = event?.target as HTMLElement | null
26
+
27
+ function getSelectableAnchors() {
28
+ return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? []
29
+ }
30
+
31
+ function handleArrows(key = event.key) {
32
+ const anchors = getSelectableAnchors()
33
+ let i = 0
34
+ while (i < anchors.length && document.activeElement !== anchors[i]) i++
35
+ const next: any = key === 'ArrowDown' ? (anchors[i + 1] ?? anchors[0]) : (anchors[i - 1] ?? anchors[anchors.length - 1])
36
+ next?.focus?.()
37
+ }
38
+
39
+ const handlers: Record<string, (() => void) | undefined> = {
40
+ Escape: () => {
41
+ listeners.current.onPressEscape?.()
42
+ event.stopPropagation()
43
+ event.preventDefault()
44
+ },
45
+ Enter: () => {
46
+ target?.click()
47
+ },
48
+ Tab: () => {
49
+ const anchors = getSelectableAnchors()
50
+ if (document.activeElement === anchors[anchors.length - 1]) listeners.current.onPressLastTab?.()
51
+ else handleArrows('ArrowDown')
52
+ event.preventDefault()
53
+ },
54
+ ArrowUp: handleArrows,
55
+ ArrowDown: handleArrows,
56
+ }
57
+
58
+ handlers[event.key]?.()
59
+ }, [])
60
+
61
+ const attachKeyboardListeners = useCallback(() => {
62
+ document.addEventListener('keydown', keyboardControls)
63
+ }, [])
64
+
65
+ const detachKeyboardListeners = useCallback(() => {
66
+ document.removeEventListener('keydown', keyboardControls)
67
+ }, [])
68
+
69
+ return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners }
70
+ }
@@ -1,15 +1,15 @@
1
- import React, { ReactNode } from 'react'
2
-
3
- interface CustomLabel {
4
- id: string,
5
- element: ReactNode,
6
- }
7
- export interface Action {
8
- label: string | CustomLabel,
9
- onClick?: () => void,
10
- href?: string,
11
- target?: React.AnchorHTMLAttributes<HTMLAnchorElement>['target'],
12
- iconActive?: React.ReactElement,
13
- }
14
-
15
- export type PortalAcronym = 'EDP' | 'AI' | 'HUB'
1
+ import React, { ReactNode } from 'react'
2
+
3
+ interface CustomLabel {
4
+ id: string,
5
+ element: ReactNode,
6
+ }
7
+ export interface Action {
8
+ label: string | CustomLabel,
9
+ onClick?: () => void,
10
+ href?: string,
11
+ target?: React.AnchorHTMLAttributes<HTMLAnchorElement>['target'],
12
+ iconActive?: React.ReactElement,
13
+ }
14
+
15
+ export type PortalAcronym = 'EDP' | 'AI' | 'HUB'
package/src/dictionary.ts CHANGED
@@ -1,25 +1,25 @@
1
- import { Dictionary, getLanguage, useTranslate } from '@stack-spot/portal-translate'
2
-
3
- const dictionary = {
4
- en: {
5
- close: 'Close',
6
- validationLabel: 'Please, confirm the action by typing "$0" below:',
7
- dismiss: 'Dismiss',
8
- confirm: 'OK',
9
- cancel: 'Cancel',
10
- },
11
- pt: {
12
- close: 'Fechar',
13
- validationLabel: 'Por favor, confirme a ação digitando "$0" no campo abaixo:',
14
- dismiss: 'Dispensar',
15
- confirm: 'OK',
16
- cancel: 'Cancelar',
17
- },
18
- } satisfies Dictionary
19
-
20
- export const useDictionary = () => useTranslate(dictionary)
21
-
22
- export function getDictionary() {
23
- const language = getLanguage()
24
- return dictionary[language]
25
- }
1
+ import { Dictionary, getLanguage, useTranslate } from '@stack-spot/portal-translate'
2
+
3
+ const dictionary = {
4
+ en: {
5
+ close: 'Close',
6
+ validationLabel: 'Please, confirm the action by typing "$0" below:',
7
+ dismiss: 'Dismiss',
8
+ confirm: 'OK',
9
+ cancel: 'Cancel',
10
+ },
11
+ pt: {
12
+ close: 'Fechar',
13
+ validationLabel: 'Por favor, confirme a ação digitando "$0" no campo abaixo:',
14
+ dismiss: 'Dispensar',
15
+ confirm: 'OK',
16
+ cancel: 'Cancelar',
17
+ },
18
+ } satisfies Dictionary
19
+
20
+ export const useDictionary = () => useTranslate(dictionary)
21
+
22
+ export function getDictionary() {
23
+ const language = getLanguage()
24
+ return dictionary[language]
25
+ }
package/src/elements.ts CHANGED
@@ -1,24 +1,24 @@
1
- export const elementIds = {
2
- layout: 'layout',
3
- backdrop: 'backdrop',
4
- modal: 'modal',
5
- rightPanel: 'rightPanel',
6
- bottomDialog: 'bottomDialog',
7
- page: 'page',
8
- content: 'content',
9
- header: 'header',
10
- menu: 'menu',
11
- menuContent: 'menuContent',
12
- menuSections: 'menuSections',
13
- accessibilityAnnouncer: 'accessibilityAnnouncer',
14
- } as const
15
-
16
- export type LayoutElement = keyof typeof elementIds
17
- export type LayoutElements = Record<LayoutElement, HTMLElement | null>
18
-
19
- export function getLayoutElements() {
20
- return (Object.keys(elementIds) as LayoutElement[]).reduce<LayoutElements>(
21
- (result, id) => ({ ...result, [id]: document.getElementById(id) }),
22
- {} as LayoutElements,
23
- )
24
- }
1
+ export const elementIds = {
2
+ layout: 'layout',
3
+ backdrop: 'backdrop',
4
+ modal: 'modal',
5
+ rightPanel: 'rightPanel',
6
+ bottomDialog: 'bottomDialog',
7
+ page: 'page',
8
+ content: 'content',
9
+ header: 'header',
10
+ menu: 'menu',
11
+ menuContent: 'menuContent',
12
+ menuSections: 'menuSections',
13
+ accessibilityAnnouncer: 'accessibilityAnnouncer',
14
+ } as const
15
+
16
+ export type LayoutElement = keyof typeof elementIds
17
+ export type LayoutElements = Record<LayoutElement, HTMLElement | null>
18
+
19
+ export function getLayoutElements() {
20
+ return (Object.keys(elementIds) as LayoutElement[]).reduce<LayoutElements>(
21
+ (result, id) => ({ ...result, [id]: document.getElementById(id) }),
22
+ {} as LayoutElements,
23
+ )
24
+ }
package/src/errors.ts CHANGED
@@ -1,11 +1,11 @@
1
- export class LayoutError extends Error {
2
- constructor(message: string) {
3
- super(`Layout error: ${message}`)
4
- }
5
- }
6
-
7
- export class ElementNotFound extends LayoutError {
8
- constructor(elementName: string, elementId: string) {
9
- super(`unable to create ${elementName} because no element with id "${elementId}" was found in the view.`)
10
- }
11
- }
1
+ export class LayoutError extends Error {
2
+ constructor(message: string) {
3
+ super(`Layout error: ${message}`)
4
+ }
5
+ }
6
+
7
+ export class ElementNotFound extends LayoutError {
8
+ constructor(elementName: string, elementId: string) {
9
+ super(`unable to create ${elementName} because no element with id "${elementId}" was found in the view.`)
10
+ }
11
+ }
package/src/index.ts CHANGED
@@ -1,17 +1,17 @@
1
- export { Layout, RawLayout } from './Layout'
2
- export { overlay } from './LayoutOverlayManager'
3
- export { Dialog } from './components/Dialog'
4
- export { Toaster } from './components/Toaster'
5
- export { Header, HeaderProps } from './components/Header'
6
- export { OverlayContent } from './components/OverlayContent'
7
- export { PortalSwitcher } from './components/PortalSwitcher'
8
- export { ListAction, SelectionList, SelectionListProps } from './components/SelectionList'
9
- export { MenuContent, Title, MenuGroup, ActionItem } from './components/menu/MenuContent'
10
- export { MenuSections } from './components/menu/MenuSections'
11
- export * from './components/menu/types'
12
- export * from './components/types'
13
- export * from './elements'
14
- export * from './errors'
15
- export { Logo as StackspotLogo } from './svg/Logo'
16
- export * from './utils'
17
-
1
+ export { Layout, RawLayout } from './Layout'
2
+ export { overlay } from './LayoutOverlayManager'
3
+ export { Dialog } from './components/Dialog'
4
+ export { Toaster } from './components/Toaster'
5
+ export { Header, HeaderProps } from './components/Header'
6
+ export { OverlayContent } from './components/OverlayContent'
7
+ export { PortalSwitcher } from './components/PortalSwitcher'
8
+ export { ListAction, SelectionList, SelectionListProps } from './components/SelectionList'
9
+ export { MenuContent, Title, MenuGroup, ActionItem } from './components/menu/MenuContent'
10
+ export { MenuSections } from './components/menu/MenuSections'
11
+ export * from './components/menu/types'
12
+ export * from './components/types'
13
+ export * from './elements'
14
+ export * from './errors'
15
+ export { Logo as StackspotLogo } from './svg/Logo'
16
+ export * from './utils'
17
+
@@ -1,22 +1,22 @@
1
- /* eslint-disable react-refresh/only-export-components */
2
-
3
- import { createContext, useContext } from 'react'
4
-
5
- export type AnchorComponent = (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => React.ReactElement
6
-
7
- export interface LayoutContext {
8
- anchorTag?: AnchorComponent,
9
- }
10
-
11
- const context = createContext<LayoutContext>({})
12
-
13
- const Anchor: AnchorComponent = props => <a {...props} />
14
-
15
- export const LayoutProvider = ({ children, ...props }: LayoutContext & { children: React.ReactNode }) => (
16
- <context.Provider value={props}>{children}</context.Provider>
17
- )
18
-
19
- export function useAnchorTag(): AnchorComponent {
20
- const { anchorTag } = useContext(context)
21
- return anchorTag ?? Anchor
22
- }
1
+ /* eslint-disable react-refresh/only-export-components */
2
+
3
+ import { createContext, useContext } from 'react'
4
+
5
+ export type AnchorComponent = (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => React.ReactElement
6
+
7
+ export interface LayoutContext {
8
+ anchorTag?: AnchorComponent,
9
+ }
10
+
11
+ const context = createContext<LayoutContext>({})
12
+
13
+ const Anchor: AnchorComponent = props => <a {...props} />
14
+
15
+ export const LayoutProvider = ({ children, ...props }: LayoutContext & { children: React.ReactNode }) => (
16
+ <context.Provider value={props}>{children}</context.Provider>
17
+ )
18
+
19
+ export function useAnchorTag(): AnchorComponent {
20
+ const { anchorTag } = useContext(context)
21
+ return anchorTag ?? Anchor
22
+ }