@stack-spot/portal-layout 0.0.3 → 0.0.4

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 (56) hide show
  1. package/dist/Layout.d.ts +17 -3
  2. package/dist/Layout.d.ts.map +1 -1
  3. package/dist/Layout.js +8 -4
  4. package/dist/Layout.js.map +1 -1
  5. package/dist/LayoutOverlayManager.d.ts.map +1 -1
  6. package/dist/LayoutOverlayManager.js +10 -7
  7. package/dist/LayoutOverlayManager.js.map +1 -1
  8. package/dist/components/Dialog.d.ts.map +1 -1
  9. package/dist/components/Dialog.js +4 -1
  10. package/dist/components/Dialog.js.map +1 -1
  11. package/dist/components/Header.d.ts +2 -1
  12. package/dist/components/Header.d.ts.map +1 -1
  13. package/dist/components/Header.js +1 -1
  14. package/dist/components/Header.js.map +1 -1
  15. package/dist/components/Menu/MenuContent.d.ts.map +1 -1
  16. package/dist/components/Menu/MenuContent.js +12 -5
  17. package/dist/components/Menu/MenuContent.js.map +1 -1
  18. package/dist/components/Menu/MenuSections.d.ts +1 -0
  19. package/dist/components/Menu/MenuSections.d.ts.map +1 -1
  20. package/dist/components/Menu/MenuSections.js +12 -5
  21. package/dist/components/Menu/MenuSections.js.map +1 -1
  22. package/dist/components/Menu/PageSelector.d.ts.map +1 -1
  23. package/dist/components/Menu/PageSelector.js +1 -1
  24. package/dist/components/Menu/PageSelector.js.map +1 -1
  25. package/dist/components/Menu/types.d.ts +7 -0
  26. package/dist/components/Menu/types.d.ts.map +1 -1
  27. package/dist/components/OverlayContent.d.ts.map +1 -1
  28. package/dist/components/OverlayContent.js +5 -1
  29. package/dist/components/OverlayContent.js.map +1 -1
  30. package/dist/components/SelectionList.d.ts +2 -1
  31. package/dist/components/SelectionList.d.ts.map +1 -1
  32. package/dist/components/SelectionList.js +3 -3
  33. package/dist/components/SelectionList.js.map +1 -1
  34. package/dist/components/Toaster.d.ts.map +1 -1
  35. package/dist/components/Toaster.js +5 -1
  36. package/dist/components/Toaster.js.map +1 -1
  37. package/dist/dictionary.d.ts +15 -0
  38. package/dist/dictionary.d.ts.map +1 -0
  39. package/dist/dictionary.js +23 -0
  40. package/dist/dictionary.js.map +1 -0
  41. package/dist/layout.css +22 -8
  42. package/package.json +4 -3
  43. package/src/Layout.tsx +34 -12
  44. package/src/LayoutOverlayManager.tsx +15 -10
  45. package/src/components/Dialog.tsx +4 -1
  46. package/src/components/Header.tsx +3 -2
  47. package/src/components/Menu/MenuContent.tsx +12 -4
  48. package/src/components/Menu/MenuSections.tsx +14 -6
  49. package/src/components/Menu/PageSelector.tsx +1 -0
  50. package/src/components/Menu/types.ts +7 -0
  51. package/src/components/OverlayContent.tsx +16 -12
  52. package/src/components/SelectionList.tsx +5 -3
  53. package/src/components/Toaster.tsx +9 -5
  54. package/src/dictionary.ts +25 -0
  55. package/src/layout.css +22 -8
  56. package/src/citric.fix.d.ts +0 -7
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionList.js","sourceRoot":"","sources":["../../src/components/SelectionList.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SelectionList.js","sourceRoot":"","sources":["../../src/components/SelectionList.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../src/components/Toaster.tsx"],"names":[],"mappings":"AAGA,OAAO,uCAAuC,CAAA;AAQ9C,eAAO,MAAM,OAAO,+CAAqD,CAAA"}
1
+ {"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../src/components/Toaster.tsx"],"names":[],"mappings":"AAGA,OAAO,uCAAuC,CAAA;AAY9C,eAAO,MAAM,OAAO,+CAAqD,CAAA"}
@@ -3,6 +3,10 @@ import { TimesMini } from '@citric/icons';
3
3
  import { IconButton } from '@citric/ui';
4
4
  import { ToastContainer } from 'react-toastify';
5
5
  import 'react-toastify/dist/ReactToastify.css';
6
- const CloseButton = ({ closeToast }) => (_jsx(IconButton, { onClick: () => closeToast(null), title: "Dismiss", children: _jsx(TimesMini, {}) }));
6
+ import { useDictionary } from '../dictionary';
7
+ const CloseButton = ({ closeToast }) => {
8
+ const t = useDictionary();
9
+ return (_jsx(IconButton, { onClick: () => closeToast(null), title: t.dismiss, children: _jsx(TimesMini, {}) }));
10
+ };
7
11
  export const Toaster = () => _jsx(ToastContainer, { closeButton: CloseButton });
8
12
  //# sourceMappingURL=Toaster.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Toaster.js","sourceRoot":"","sources":["../../src/components/Toaster.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAoB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACjE,OAAO,uCAAuC,CAAA;AAE9C,MAAM,WAAW,GAAG,CAAC,EAAE,UAAU,EAAoB,EAAE,EAAE,CAAC,CACxD,KAAC,UAAU,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAW,CAAC,EAAE,KAAK,EAAC,SAAS,YACjE,KAAC,SAAS,KAAG,GACF,CACd,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,KAAC,cAAc,IAAC,WAAW,EAAE,WAAW,GAAI,CAAA"}
1
+ {"version":3,"file":"Toaster.js","sourceRoot":"","sources":["../../src/components/Toaster.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAoB,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACjE,OAAO,uCAAuC,CAAA;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,MAAM,WAAW,GAAG,CAAC,EAAE,UAAU,EAAoB,EAAE,EAAE;IACvD,MAAM,CAAC,GAAG,aAAa,EAAE,CAAA;IACzB,OAAO,CACL,KAAC,UAAU,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,IAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,YAClE,KAAC,SAAS,KAAG,GACF,CACd,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,KAAC,cAAc,IAAC,WAAW,EAAE,WAAW,GAAI,CAAA"}
@@ -0,0 +1,15 @@
1
+ export declare const useDictionary: () => Record<"cancel" | "close" | "validationLabel" | "dismiss" | "confirm", string>;
2
+ export declare function getDictionary(): {
3
+ close: string;
4
+ validationLabel: string;
5
+ dismiss: string;
6
+ confirm: string;
7
+ cancel: string;
8
+ } | {
9
+ close: string;
10
+ validationLabel: string;
11
+ dismiss: string;
12
+ confirm: string;
13
+ cancel: string;
14
+ };
15
+ //# sourceMappingURL=dictionary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dictionary.d.ts","sourceRoot":"","sources":["../src/dictionary.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,aAAa,sFAAiC,CAAA;AAE3D,wBAAgB,aAAa;;;;;;;;;;;;EAG5B"}
@@ -0,0 +1,23 @@
1
+ import { getLanguage, useTranslate } from '@stack-spot/portal-translate';
2
+ const dictionary = {
3
+ en: {
4
+ close: 'Close',
5
+ validationLabel: 'Please, confirm the action by typing "$0" below:',
6
+ dismiss: 'Dismiss',
7
+ confirm: 'OK',
8
+ cancel: 'Cancel',
9
+ },
10
+ pt: {
11
+ close: 'Fechar',
12
+ validationLabel: 'Por favor, confirme a ação digitando "$0" no campo abaixo:',
13
+ dismiss: 'Dispensar',
14
+ confirm: 'OK',
15
+ cancel: 'Cancelar',
16
+ },
17
+ };
18
+ export const useDictionary = () => useTranslate(dictionary);
19
+ export function getDictionary() {
20
+ const language = getLanguage();
21
+ return dictionary[language];
22
+ }
23
+ //# sourceMappingURL=dictionary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dictionary.js","sourceRoot":"","sources":["../src/dictionary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,WAAW,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAEpF,MAAM,UAAU,GAAG;IACjB,EAAE,EAAE;QACF,KAAK,EAAE,OAAO;QACd,eAAe,EAAE,kDAAkD;QACnE,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,QAAQ;KACjB;IACD,EAAE,EAAE;QACF,KAAK,EAAE,QAAQ;QACf,eAAe,EAAE,4DAA4D;QAC7E,OAAO,EAAE,WAAW;QACpB,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,UAAU;KACnB;CACmB,CAAA;AAEtB,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;AAE3D,MAAM,UAAU,aAAa;IAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAA;AAC7B,CAAC"}
package/dist/layout.css CHANGED
@@ -68,20 +68,23 @@ body {
68
68
  }
69
69
 
70
70
  #page {
71
- flex: 1;
71
+ position: absolute;
72
+ top: var(--header-height);
73
+ left: var(--menu-sections-width);
74
+ right: 0;
75
+ bottom: 0;
76
+ overflow-y: auto;
72
77
  display: flex;
73
78
  flex-direction: column;
74
79
  background-color: var(--light-300);
75
80
  border-top-left-radius: 0.5rem;
76
81
  align-items: center;
77
82
  padding: 24px;
78
- margin-top: var(--header-height);
79
- margin-left: var(--menu-sections-width);
80
- transition: margin ease-in-out var(--menu-animation-duration);
83
+ transition: left ease-in-out var(--menu-animation-duration);
81
84
  }
82
85
 
83
86
  #layout.menu-content-visible #page {
84
- margin-left: calc(var(--menu-sections-width) + var(--menu-content-width));
87
+ left: calc(var(--menu-sections-width) + var(--menu-content-width));
85
88
  }
86
89
 
87
90
  #content {
@@ -330,7 +333,7 @@ body {
330
333
  bottom: -420px;
331
334
  left: 20px;
332
335
  height: 400px;
333
- transition: transform bottom 0.3s;
336
+ transition: bottom 0.3s;
334
337
  }
335
338
 
336
339
  #bottomPanel.visible {
@@ -340,12 +343,23 @@ body {
340
343
  #bottomDialog {
341
344
  position: fixed;
342
345
  display: flex;
343
- flex-direction: column;
346
+ flex-direction: row;
344
347
  bottom: -80px;
345
348
  left: 0;
346
349
  right: 0;
347
350
  height: 80px;
348
- transition: transform bottom 0.3s;
351
+ transition: bottom 0.3s;
352
+ background-color: var(--inverse-500);
353
+ color: var(--inverse-contrastText);
354
+ justify-content: center;
355
+ align-items: center;
356
+ gap: 16px;
357
+ }
358
+
359
+ #bottomDialog .btn-group {
360
+ display: flex;
361
+ flex-direction: row;
362
+ gap: 8px;
349
363
  }
350
364
 
351
365
  #bottomDialog.visible {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stack-spot/portal-layout",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,10 +8,11 @@
8
8
  "@citric/core": "^5.3.1",
9
9
  "@citric/icons": "^5.3.1",
10
10
  "@citric/ui": "^5.3.1",
11
- "@stack-spot/portal-theme": "0.0.3",
11
+ "@stack-spot/portal-theme": "^0.0.3",
12
+ "@stack-spot/portal-translate": "^0.0.4",
12
13
  "react": "^18.2.0",
13
14
  "react-dom": "^18.2.0",
14
- "styled-components": "6.1.1"
15
+ "styled-components": "^6.1.1"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@types/react": "^18.2.37",
package/src/Layout.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CSSToCitricAdapter, listToClass, WithStyle } from '@stack-spot/portal-theme'
2
2
  import '@stack-spot/portal-theme/dist/theme.css'
3
- import { ReactElement, ReactNode } from 'react'
3
+ import { ComponentClass, ReactElement, ReactNode } from 'react'
4
4
  import { Header, HeaderProps } from './components/Header'
5
5
  import { MenuContent } from './components/Menu/MenuContent'
6
6
  import { MenuSections } from './components/Menu/MenuSections'
@@ -9,10 +9,23 @@ import { Toaster } from './components/Toaster'
9
9
  import './layout.css'
10
10
  import { overlay } from './LayoutOverlayManager'
11
11
 
12
+ type ErrorBoundaryComponent = ComponentClass<{ children: ReactNode }>
13
+
14
+ interface ErrorBoundaries {
15
+ page?: ErrorBoundaryComponent,
16
+ menuSections?: ErrorBoundaryComponent,
17
+ menuContent?: ErrorBoundaryComponent,
18
+ modal?: ErrorBoundaryComponent,
19
+ rightPanel?: ErrorBoundaryComponent,
20
+ header?: ErrorBoundaryComponent,
21
+ bottomDialog?: ErrorBoundaryComponent,
22
+ }
23
+
12
24
  interface Props extends WithStyle {
13
25
  menu: MenuProps,
14
26
  header: HeaderProps,
15
27
  children: ReactNode,
28
+ errorBoundaries?: ErrorBoundaries,
16
29
  }
17
30
 
18
31
  interface RawProps extends WithStyle {
@@ -21,9 +34,12 @@ interface RawProps extends WithStyle {
21
34
  header: ReactElement,
22
35
  children: ReactNode,
23
36
  compactMenu?: boolean,
37
+ errorBoundaries?: ErrorBoundaries,
24
38
  }
25
39
 
26
- export const RawLayout = ({ menuSections, menuContent, header, compactMenu = true, children, className, style }: RawProps) => {
40
+ export const RawLayout = (
41
+ { menuSections, menuContent, header, compactMenu = true, children, errorBoundaries = {}, className, style }: RawProps,
42
+ ) => {
27
43
  // @ts-ignore
28
44
  const { bottomDialog, modal, rightPanel } = overlay.useOverlays()
29
45
  const classes = [
@@ -32,21 +48,26 @@ export const RawLayout = ({ menuSections, menuContent, header, compactMenu = tru
32
48
  className,
33
49
  ]
34
50
 
51
+ function includeErrorBoundary(content: ReactNode, section: keyof ErrorBoundaries) {
52
+ const ErrorBoundary = errorBoundaries[section]
53
+ return ErrorBoundary ? <ErrorBoundary>{content}</ErrorBoundary> : content
54
+ }
55
+
35
56
  return (
36
57
  <CSSToCitricAdapter>
37
58
  <div id="layout" className={listToClass(classes)} style={style}>
38
- <header id="header">{header}</header>
39
- <aside id="menu">
40
- <nav id="menuContent">{menuContent}</nav>
41
- <nav id="menuSections">{menuSections}</nav>
42
- </aside>
43
59
  <div id="page">
44
- <article id="content">{children}</article>
60
+ <article id="content">{includeErrorBoundary(children, 'page')}</article>
45
61
  </div>
46
- <div id="rightPanel">{rightPanel}</div>
47
- <div id="bottomDialog">{bottomDialog}</div>
62
+ <header id="header">{includeErrorBoundary(header, 'header')}</header>
63
+ <aside id="menu">
64
+ <nav id="menuContent">{includeErrorBoundary(menuContent, 'menuContent')}</nav>
65
+ <nav id="menuSections">{includeErrorBoundary(menuSections, 'menuSections')}</nav>
66
+ </aside>
67
+ <div id="rightPanel">{includeErrorBoundary(rightPanel, 'rightPanel')}</div>
68
+ <div id="bottomDialog">{includeErrorBoundary(bottomDialog, 'bottomDialog')}</div>
48
69
  <div id="backdrop">
49
- <div id="modal">{modal}</div>
70
+ <div id="modal">{includeErrorBoundary(modal, 'modal')}</div>
50
71
  </div>
51
72
  <Toaster />
52
73
  </div>
@@ -59,7 +80,7 @@ const MenuContentRenderer = ({ content }: Required<Pick<Props['menu'], 'content'
59
80
  return <MenuContent {...menuContent} />
60
81
  }
61
82
 
62
- export const Layout = ({ menu, header, children, className, style }: Props) => (
83
+ export const Layout = ({ menu, header, children, errorBoundaries, className, style }: Props) => (
63
84
  <RawLayout
64
85
  header={<Header {...header} />}
65
86
  menuSections={<MenuSections {...menu} />}
@@ -68,6 +89,7 @@ export const Layout = ({ menu, header, children, className, style }: Props) => (
68
89
  : undefined
69
90
  }
70
91
  compactMenu={menu.compact}
92
+ errorBoundaries={errorBoundaries}
71
93
  className={className}
72
94
  style={style}
73
95
  >
@@ -1,9 +1,10 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
2
 
3
- import { Button, Flex } from '@citric/core'
3
+ import { Button } from '@citric/core'
4
4
  import { ReactElement, useLayoutEffect, useState } from 'react'
5
5
  import { Dialog, DialogOptions } from './components/Dialog'
6
6
  import { OverlayContent, OverlayContentProps } from './components/OverlayContent'
7
+ import { getDictionary } from './dictionary'
7
8
  import { ElementNotFound, LayoutError } from './errors'
8
9
  import { showToaster as showReactToaster } from './toaster'
9
10
  import { valueOfLayoutVar } from './utils'
@@ -115,24 +116,28 @@ class LayoutOverlayManager {
115
116
  })
116
117
  }
117
118
 
118
- confirm({ confirm = 'OK', cancel = 'Cancel', ...options }: DialogOptions): Promise<boolean> {
119
- return this.showDialog({ ...options, confirm, cancel })
119
+ confirm({ confirm, cancel, ...options }: DialogOptions): Promise<boolean> {
120
+ const t = getDictionary()
121
+ return this.showDialog({ ...options, confirm: confirm || t.confirm, cancel: cancel || t.cancel })
120
122
  }
121
123
 
122
- async alert({ confirm = 'OK', showButton = true, ...options }: AlertOptions): Promise<void> {
123
- await this.showDialog({ ...options, confirm: showButton ? confirm : undefined })
124
+ async alert({ confirm, showButton = true, ...options }: AlertOptions): Promise<void> {
125
+ const t = getDictionary()
126
+ await this.showDialog({ ...options, confirm: showButton ? (confirm || t.confirm) : undefined })
124
127
  }
125
128
 
126
129
  showBottomDialog({ message, cancel, confirm }: BottomDialogOptions): Promise<boolean> {
127
130
  if (!this.elements?.bottomDialog) throw new ElementNotFound('bottom dialog', BOTTOM_DIALOG_ID)
128
131
  if (!this.setContent.bottomDialog) throw new LayoutError('unable to show bottom dialog, because it has not been setup yet.')
129
132
  return new Promise((resolve) => {
130
- this.setContent.bottomDialog!(
131
- <Flex gap>
133
+ this.setContent.bottomDialog?.(
134
+ <>
132
135
  {message}
133
- {cancel && <Button onClick={() => resolve(true)} colorScheme="inverse" appearance="outlined">{cancel}</Button>}
134
- {confirm && <Button onClick={() => resolve(false)} colorScheme="inverse">{confirm}</Button>}
135
- </Flex>,
136
+ <div className="btn-group">
137
+ {cancel && <Button onClick={() => resolve(false)} colorScheme="light" appearance="outlined">{cancel}</Button>}
138
+ {confirm && <Button onClick={() => resolve(true)} colorScheme="light">{confirm}</Button>}
139
+ </div>
140
+ </>,
136
141
  )
137
142
  this.elements?.bottomDialog?.setAttribute('class', 'visible')
138
143
  })
@@ -1,5 +1,7 @@
1
1
  import { Button, Flex, Input, Text } from '@citric/core'
2
+ import { interpolate } from '@stack-spot/portal-translate'
2
3
  import { ReactNode, useState } from 'react'
4
+ import { useDictionary } from '../dictionary'
3
5
  import { OverlayContent } from './OverlayContent'
4
6
 
5
7
  interface Validation {
@@ -49,6 +51,7 @@ export const Dialog = ({
49
51
  buttonPlacement = type === 'panel' ? 'left' : 'right',
50
52
  }: Props,
51
53
  ) => {
54
+ const t = useDictionary()
52
55
  const [enabled, setEnabled] = useState(!validation)
53
56
 
54
57
  function renderValidation() {
@@ -56,7 +59,7 @@ export const Dialog = ({
56
59
  const value = typeof validation === 'string' ? validation : validation.value
57
60
  const label = typeof validation === 'object' && validation.label
58
61
  ? validation.label
59
- : `Please, confirm the action by typing "${value}" below:`
62
+ : interpolate(t.validationLabel, value)
60
63
  const placeholder = typeof validation === 'object' ? validation.placeholder : undefined
61
64
  return (
62
65
  <div style={{ margin: '16px 0' }}>
@@ -6,6 +6,7 @@ import { UserMenu } from './UserMenu'
6
6
 
7
7
  export interface HeaderProps {
8
8
  logo?: ReactNode,
9
+ logoHref?: string,
9
10
  userName?: string,
10
11
  email?: string,
11
12
  options?: SelectionListProps['items'],
@@ -13,9 +14,9 @@ export interface HeaderProps {
13
14
  right?: ReactNode,
14
15
  }
15
16
 
16
- export const Header = ({ logo, center, right, userName, email, options }: HeaderProps) => (
17
+ export const Header = ({ logo, logoHref, center, right, userName, email, options }: HeaderProps) => (
17
18
  <>
18
- {logo ?? <StackspotLogo title="stackspot" style={{ width: 130 }} />}
19
+ <a href={logoHref} title="Home">{logo ?? <StackspotLogo style={{ width: 130 }} />}</a>
19
20
  <Flex flex={1}>{center}</Flex>
20
21
  {right}
21
22
  {userName && <UserMenu userName={userName} email={email} options={options} />}
@@ -5,6 +5,7 @@ import { LoadingCircular } from '@citric/ui'
5
5
  import { listToClass, theme } from '@stack-spot/portal-theme'
6
6
  import { useMemo, useState } from 'react'
7
7
  import { styled } from 'styled-components'
8
+ import { hideOverlayImmediately } from './MenuSections'
8
9
  import { PageSelector } from './PageSelector'
9
10
  import { MENU_CONTENT_ITEM_PADDING as ITEM_PADDING, MENU_CONTENT_PADDING as PADDING } from './constants'
10
11
  import { ItemGroup, MenuAction, MenuItem, MenuSectionContent } from './types'
@@ -128,18 +129,23 @@ const Title = styled.header`
128
129
  margin: ${PADDING}px 0 24px ${PADDING}px;
129
130
  `
130
131
 
131
- const ActionItem = ({ label, onClick, href, active, icon, overflow = 'wrap' }: MenuAction) => (
132
+ const ActionItem = ({ label, onClick, href, active, icon, badge, overflow = 'wrap' }: MenuAction) => (
132
133
  <a
133
134
  href={active ? undefined : href}
134
- onClick={active ? onClick : undefined}
135
+ onClick={() => {
136
+ if (active) return
137
+ if (onClick) onClick()
138
+ hideOverlayImmediately()
139
+ }}
135
140
  className={listToClass(['action', 'item-row', active ? 'active' : undefined])}
136
141
  >
137
142
  {icon}
138
143
  <Text appearance="body2" className={`label ${overflow}`}>{label}</Text>
144
+ {badge}
139
145
  </a>
140
146
  )
141
147
 
142
- const CollapsibleGroupItem = ({ label, open: initiallyOpened, children, icon, overflow = 'wrap' }: ItemGroup) => {
148
+ const CollapsibleGroupItem = ({ label, open: initiallyOpened, children, icon, badge, overflow = 'wrap' }: ItemGroup) => {
143
149
  const [open, setOpen] = useState(initiallyOpened ?? children?.some(c => 'active' in c && c.active) ?? false)
144
150
  const items = useMemo(() => children?.map(renderOption), [children])
145
151
 
@@ -148,6 +154,7 @@ const CollapsibleGroupItem = ({ label, open: initiallyOpened, children, icon, ov
148
154
  <a onClick={() => setOpen(!open)} className="item-row">
149
155
  {icon}
150
156
  <Text appearance="body2" className={`label ${overflow}`}>{label}</Text>
157
+ {badge}
151
158
  <IconBox><ChevronDown className={listToClass(['chevron', open ? 'open' : ''])} /></IconBox>
152
159
  </a>
153
160
  <MenuGroup className={open ? 'open' : undefined}>{items}</MenuGroup>
@@ -155,7 +162,7 @@ const CollapsibleGroupItem = ({ label, open: initiallyOpened, children, icon, ov
155
162
  )
156
163
  }
157
164
 
158
- const RootGroupItem = ({ label, children, icon, overflow = 'wrap' }: ItemGroup) => {
165
+ const RootGroupItem = ({ label, children, icon, badge, overflow = 'wrap' }: ItemGroup) => {
159
166
  const items = useMemo(() => children?.filter(i => !i.hidden).map(renderOption), [children])
160
167
 
161
168
  return (
@@ -163,6 +170,7 @@ const RootGroupItem = ({ label, children, icon, overflow = 'wrap' }: ItemGroup)
163
170
  <div className="item-row">
164
171
  {icon}
165
172
  <Text appearance="overheader2" colorScheme="light.700" className={`group-title label ${overflow}`}>{label}</Text>
173
+ {badge}
166
174
  </div>
167
175
  <MenuGroup className="open no-indentation">{items}</MenuGroup>
168
176
  </>
@@ -16,7 +16,8 @@ function hideOverlay() {
16
16
  hideOverlayTask = window.setTimeout(hideOverlayImmediately, HIDE_OVERLAY_DELAY_MS)
17
17
  }
18
18
 
19
- function hideOverlayImmediately() {
19
+ // eslint-disable-next-line react-refresh/only-export-components
20
+ export function hideOverlayImmediately() {
20
21
  document.getElementById(MENU_OVERLAY_ID)?.classList.remove('visible')
21
22
  }
22
23
 
@@ -45,11 +46,18 @@ const Section = ({
45
46
  onOpen,
46
47
  setCurrentOverlay,
47
48
  id,
48
- }: MenuSection & { id: number, setCurrentOverlay: (id: number | undefined) => void }) => {
49
+ hasContent,
50
+ }: MenuSection & { id: number, setCurrentOverlay: (id: number | undefined) => void, hasContent: boolean }) => {
49
51
  const contentToRender = typeof content === 'function' ? content() : content
50
52
 
51
53
  function shouldShowOverlay() {
52
- return !!contentToRender && (!active || !isMenuContentVisible())
54
+ /* The overlay should appear if:
55
+ * 1. The section has some content to render OR:
56
+ * 1.1 The section is active and there is a contextual menu for the active page.
57
+ * 2. The section is inactive OR:
58
+ * 2.1. The contextual menu is hidden.
59
+ */
60
+ return (!!contentToRender || (hasContent && active)) && (!active || !isMenuContentVisible())
53
61
  }
54
62
 
55
63
  function showOverlayAndFixArrowPosition(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
@@ -106,7 +114,7 @@ export const MenuSections = ({ sections, ...props }: MenuProps) => {
106
114
  const [currentOverlay, setCurrentOverlay] = useState<number | undefined>()
107
115
 
108
116
  const sectionItems = useMemo(
109
- () => sections.map((s, i) => <Section key={i} id={i} {...s} setCurrentOverlay={setCurrentOverlay} />),
117
+ () => sections.map((s, i) => <Section key={i} id={i} {...s} setCurrentOverlay={setCurrentOverlay} hasContent={!!props.content} />),
110
118
  [sections],
111
119
  )
112
120
 
@@ -126,12 +134,12 @@ export const MenuSections = ({ sections, ...props }: MenuProps) => {
126
134
  return (
127
135
  <>
128
136
  <ul>{sectionItems}</ul>
129
- <button className="toggle" onClick={toggleMenu} title="Toggle menu panel visibility">
137
+ {!!props.content && <button className="toggle" onClick={toggleMenu} title="Toggle menu panel visibility">
130
138
  <IconBox>
131
139
  <MenuIcon className="expand" />
132
140
  <ChevronLeft className="collapse" />
133
141
  </IconBox>
134
- </button>
142
+ </button>}
135
143
  <div id="menuContentOverlay" onMouseEnter={showOverlay} onMouseLeave={hideOverlay}>
136
144
  {renderMenuOverlay()}
137
145
  <div className="arrow"></div>
@@ -111,6 +111,7 @@ export const PageSelector = ({ options, value, button, loading, title }: Selecto
111
111
  items={optionsWithIcon}
112
112
  onHide={() => setVisible(false)}
113
113
  after={button ? <a className="view-all" href={button.href} onClick={button.onClick}>{button.label}</a> : undefined}
114
+ scroll
114
115
  />
115
116
  </>
116
117
  )
@@ -3,7 +3,14 @@ import { Action } from '../types'
3
3
 
4
4
  interface BaseMenuItem {
5
5
  hidden?: boolean,
6
+ /**
7
+ * React element on the left.
8
+ */
6
9
  icon?: React.ReactElement,
10
+ /**
11
+ * React element on the right.
12
+ */
13
+ badge?: React.ReactElement,
7
14
  /**
8
15
  * Whether to wrap overflowing text, just hide or hide and add an ellipsis (...).
9
16
  * @default 'wrap'
@@ -4,6 +4,7 @@ import { IconButton } from '@citric/ui'
4
4
  import { WithStyle, listToClass, theme } from '@stack-spot/portal-theme'
5
5
  import { ReactNode } from 'react'
6
6
  import { styled } from 'styled-components'
7
+ import { useDictionary } from '../dictionary'
7
8
 
8
9
  export interface OverlayContentProps extends WithStyle {
9
10
  title: string,
@@ -38,15 +39,18 @@ const ContentBox = styled.section`
38
39
  }
39
40
  `
40
41
 
41
- export const OverlayContent = ({ children, title, subtitle, className, style, onClose, type }: Props) => (
42
- <ContentBox style={style} className={listToClass([className, type])}>
43
- <header>
44
- <Flex flexDirection="column" flex={1}>
45
- <Text appearance={type === 'modal' ? 'h3' : 'h4'}>{title}</Text>
46
- {subtitle && <Text appearance="body2" colorScheme="light.700">{subtitle}</Text>}
47
- </Flex>
48
- <IconButton onClick={onClose} title="close" aria-label="close"><TimesMini /></IconButton>
49
- </header>
50
- {children}
51
- </ContentBox>
52
- )
42
+ export const OverlayContent = ({ children, title, subtitle, className, style, onClose, type }: Props) => {
43
+ const t = useDictionary()
44
+ return (
45
+ <ContentBox style={style} className={listToClass([className, type])}>
46
+ <header>
47
+ <Flex flexDirection="column" flex={1}>
48
+ <Text appearance={type === 'modal' ? 'h3' : 'h4'}>{title}</Text>
49
+ {subtitle && <Text appearance="body2" colorScheme="light.700">{subtitle}</Text>}
50
+ </Flex>
51
+ <IconButton onClick={onClose} title={t.close} aria-label={t.close}><TimesMini /></IconButton>
52
+ </header>
53
+ {children}
54
+ </ContentBox>
55
+ )
56
+ }
@@ -47,11 +47,12 @@ export interface SelectionListProps extends WithStyle {
47
47
  maxHeight?: string,
48
48
  before?: ReactElement,
49
49
  after?: ReactElement,
50
+ scroll?: boolean,
50
51
  }
51
52
 
52
- const SelectionBox = styled.div<{ $maxHeight: string }>`
53
+ const SelectionBox = styled.div<{ $maxHeight: string, $scroll?: boolean }>`
53
54
  max-height: 0;
54
- overflow-y: auto;
55
+ overflow-y: ${({ $scroll }) => $scroll ? 'auto' : 'hidden'};
55
56
  overflow-x: hidden;
56
57
  transition: max-height ease-in ${ANIMATION_DURATION_MS / 1000}s;
57
58
  z-index: 1;
@@ -145,7 +146,7 @@ function renderItem(item: ListItem, setCurrent: (current: CurrentItemList) => vo
145
146
  }
146
147
 
147
148
  export const SelectionList = ({
148
- items, className, style, visible = true, maxHeight = '300px', onHide, before, after,
149
+ items, className, style, visible = true, maxHeight = '300px', onHide, before, after, scroll,
149
150
  }: SelectionListProps) => {
150
151
  const wrapper = useRef<HTMLDivElement>(null)
151
152
  const itemsRef = useRef(items)
@@ -182,6 +183,7 @@ export const SelectionList = ({
182
183
  $maxHeight={maxHeight}
183
184
  style={style}
184
185
  className={listToClass(['selection-list', visible ? 'visible' : undefined, className])}
186
+ $scroll={scroll}
185
187
  >
186
188
  <div className="selection-list-content">
187
189
  {before}
@@ -2,11 +2,15 @@ import { TimesMini } from '@citric/icons'
2
2
  import { IconButton } from '@citric/ui'
3
3
  import { CloseButtonProps, ToastContainer } from 'react-toastify'
4
4
  import 'react-toastify/dist/ReactToastify.css'
5
+ import { useDictionary } from '../dictionary'
5
6
 
6
- const CloseButton = ({ closeToast }: CloseButtonProps) => (
7
- <IconButton onClick={() => closeToast(null as any)} title="Dismiss">
8
- <TimesMini />
9
- </IconButton>
10
- )
7
+ const CloseButton = ({ closeToast }: CloseButtonProps) => {
8
+ const t = useDictionary()
9
+ return (
10
+ <IconButton onClick={() => closeToast(null as any)} title={t.dismiss}>
11
+ <TimesMini />
12
+ </IconButton>
13
+ )
14
+ }
11
15
 
12
16
  export const Toaster = () => <ToastContainer closeButton={CloseButton} />
@@ -0,0 +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
+ }