@aarhus-university/au-lib-react-components 11.5.0 → 11.5.1

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.
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "name": "@aarhus-university/au-lib-react-components",
4
- "version": "11.5.0",
4
+ "version": "11.5.1",
5
5
  "description": "Library for shared React components for various applications on au.dk",
6
6
  "scripts": {
7
7
  "test": "jest",
8
8
  "build": "jest && webpack --config ./webpack.config.js",
9
- "storybook": "start-storybook -p 6006",
9
+ "storybook": "start-storybook -p 6006 -h 127.0.0.1",
10
10
  "build-storybook": "build-storybook",
11
11
  "chromatic": "npx chromatic --project-token=6e78be9148c0"
12
12
  },
@@ -72,9 +72,9 @@
72
72
  "webpack-cli": "^4.9.2"
73
73
  },
74
74
  "dependencies": {
75
- "@aarhus-university/au-designsystem-delphinus": "0.35.2",
75
+ "@aarhus-university/au-designsystem-delphinus": "0.39.3",
76
76
  "@aarhus-university/au-designsystem-delphinus-dev": "0.2.0",
77
- "@aarhus-university/types": "^0.17.14",
77
+ "@aarhus-university/types": "0.20.0",
78
78
  "@reduxjs/toolkit": "^1.8.3",
79
79
  "@types/google.analytics": "^0.0.42",
80
80
  "@types/history": "^5.0.0",
@@ -1,84 +1,94 @@
1
+ /* eslint-disable max-len */
1
2
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
3
  /* eslint-env browser */
3
- import React, { FC, useState } from 'react';
4
- import ReactDOM from 'react-dom';
4
+ import React, {
5
+ FC, useState, useRef, useEffect,
6
+ } from 'react';
7
+ import { hideModal } from '@aarhus-university/au-designsystem-delphinus/source/js/components/modal-view';
5
8
  import AUButtonComponent from './AUButtonComponent';
9
+ import AUModalComponent from './AUModalComponent';
6
10
 
7
- const AUAlertComponent: FC<AUButtonToastComponentUnionProps> = ({
11
+ const AUAlertComponent: FC<AUAlertComponentProps> = ({
12
+ modalId,
8
13
  confirm,
9
- message: pMessage,
10
- buttonText,
14
+ processing,
15
+ done,
16
+ header,
17
+ message,
18
+ okButtonText,
11
19
  cancelButtonText,
12
20
  label,
13
- disabled,
14
21
  size,
15
22
  type,
16
23
  icon,
17
24
  iconPosition,
18
25
  hideLabel,
19
26
  mode,
20
- btnRef,
21
27
  classNames,
22
- ariaExpanded,
23
28
  dataGtm,
24
29
  asSubmit,
25
30
  onClick,
26
- }: AUButtonToastComponentUnionProps) => {
31
+ }: AUAlertComponentProps) => {
27
32
  const [alert, setAlert] = useState<boolean>(false);
28
- const { type: mType, message, header } = pMessage;
33
+ const btnRef = useRef<HTMLButtonElement>(null);
34
+ useEffect(() => {
35
+ if (done) {
36
+ hideModal(modalId, btnRef.current as HTMLButtonElement, () => setAlert(false));
37
+ }
38
+ }, [done]);
29
39
 
30
- let className = 'toast-notification toast-notification--persistent';
31
- if (mType !== 'default') {
32
- className = `${className} toast-notification--${mType}`;
40
+ let okBtnMode = mode;
41
+ if (processing) {
42
+ if (mode === 'confirmable-action') {
43
+ okBtnMode = 'confirmable-action processing';
44
+ } else if (mode === 'ireversable-action') {
45
+ okBtnMode = 'ireversable-action processing';
46
+ }
33
47
  }
34
48
 
35
49
  return (
36
50
  <>
37
- {
38
- alert && (
39
- <>
40
- {
41
- ReactDOM.createPortal(
42
- <div className={className}>
43
- <div className="toast-notification__content">
44
- {
45
- header && (
46
- <h2 className="toast-notification__header">
47
- {header}
48
- </h2>
49
- )
50
- }
51
- <p dangerouslySetInnerHTML={{ __html: message }} />
52
- </div>
51
+ <AUModalComponent
52
+ domId={modalId}
53
+ show={alert}
54
+ sender={btnRef.current}
55
+ onClose={() => setAlert(false)}
56
+ closeButtonDisabled={processing}
57
+ >
58
+ <>
59
+ <h2 className="modal-view__header">{header}</h2>
60
+ <div className="modal-view__content">
61
+ <div className="content-container" dangerouslySetInnerHTML={{ __html: message }} />
62
+ <div className="button-container vertical-spacing-top">
63
+ <AUButtonComponent
64
+ label={okButtonText}
65
+ disabled={processing}
66
+ mode={okBtnMode}
67
+ onClick={(event) => {
68
+ if (typeof onClick === 'function') {
69
+ onClick(event, btnRef);
70
+ }
71
+ }}
72
+ />
73
+ {
74
+ confirm && (
53
75
  <AUButtonComponent
54
- label={buttonText as string}
55
- onClick={(event) => {
56
- if (typeof onClick === 'function') {
57
- onClick(event, btnRef);
58
- }
59
- setAlert(false);
76
+ label={cancelButtonText}
77
+ disabled={processing}
78
+ type="text"
79
+ onClick={() => {
80
+ hideModal(modalId, btnRef.current as HTMLButtonElement, () => setAlert(false));
60
81
  }}
61
82
  />
62
- {
63
- confirm && (
64
- <AUButtonComponent
65
- label={cancelButtonText as string}
66
- onClick={() => {
67
- setAlert(false);
68
- }}
69
- />
70
- )
71
- }
72
- </div>,
73
- document.querySelector('body')!,
74
- )
75
- }
76
- </>
77
- )
78
- }
83
+ )
84
+ }
85
+ </div>
86
+ </div>
87
+ </>
88
+ </AUModalComponent>
79
89
  <AUButtonComponent
80
90
  label={label}
81
- disabled={disabled}
91
+ disabled={alert}
82
92
  size={size}
83
93
  type={type}
84
94
  icon={icon}
@@ -87,7 +97,8 @@ const AUAlertComponent: FC<AUButtonToastComponentUnionProps> = ({
87
97
  mode={mode}
88
98
  btnRef={btnRef}
89
99
  classNames={classNames}
90
- ariaExpanded={ariaExpanded}
100
+ ariaExpanded={alert}
101
+ ariaHasPopup
91
102
  dataGtm={dataGtm}
92
103
  asSubmit={asSubmit}
93
104
  onClick={() => {
@@ -14,6 +14,7 @@ const AUButtonComponent: FC<AUButtonComponentProps> = ({
14
14
  btnRef,
15
15
  classNames,
16
16
  ariaExpanded,
17
+ ariaHasPopup,
17
18
  asSubmit,
18
19
  onClick,
19
20
  }: AUButtonComponentProps) => {
@@ -31,8 +32,8 @@ const AUButtonComponent: FC<AUButtonComponentProps> = ({
31
32
  }
32
33
  }
33
34
  let modeClass = '';
34
- if (mode !== 'none') {
35
- modeClass = `button--${mode}`;
35
+ if (mode && mode !== 'none') {
36
+ modeClass = mode.includes(' ') ? mode.split(' ').map((m) => `button--${m}`).join(' ') : `button--${mode}`;
36
37
  }
37
38
 
38
39
  return (
@@ -46,10 +47,11 @@ const AUButtonComponent: FC<AUButtonComponentProps> = ({
46
47
  typeClass,
47
48
  iconClass,
48
49
  modeClass,
49
- disabled && mode !== 'processing' ? 'visually-disabled' : '',
50
+ disabled && !mode?.includes('processing') ? 'visually-disabled' : '',
50
51
  ].concat(classNames || []).join(' ').replace(/\s+/g, ' ').trim()}
51
52
  title={icon && hideLabel ? label : undefined}
52
53
  aria-expanded={ariaExpanded}
54
+ aria-haspopup={ariaHasPopup}
53
55
  onClick={(event: MouseEvent<HTMLButtonElement>) => {
54
56
  if (typeof onClick !== 'undefined') {
55
57
  onClick(event, btnRef);
@@ -71,6 +73,7 @@ AUButtonComponent.defaultProps = {
71
73
  mode: 'none',
72
74
  classNames: [],
73
75
  ariaExpanded: false,
76
+ ariaHasPopup: undefined,
74
77
  asSubmit: false,
75
78
  // eslint-disable-next-line no-console
76
79
  onClick: (
@@ -0,0 +1,67 @@
1
+ /* eslint-disable jsx-a11y/label-has-associated-control */
2
+ import React, { FC } from 'react';
3
+
4
+ const AUEditFilterComponent: FC = () => (
5
+ <form className="form">
6
+ <h2>Rediger filter</h2>
7
+ <div className="form__field">
8
+ <label htmlFor="title">Titel</label>
9
+ <input type="text" id="title" />
10
+ </div>
11
+ <h3>Kriterier</h3>
12
+ <div>
13
+ <div className="form__field">
14
+ <label htmlFor="orgunit">
15
+ Organisatorisk enhed
16
+ </label>
17
+ <input type="text" id="orgunit" />
18
+ </div>
19
+ <div className="search-filter">
20
+ <h3 className="search-filter__label">Valgte enheder:</h3>
21
+ <div className="search-filter__items">
22
+ <button type="button" className="search-filter__item">
23
+ <span className="search-filter__item__value">
24
+ Arts
25
+ </span>
26
+ </button>
27
+ <button type="button" className="search-filter__item">
28
+ <span className="search-filter__item__value">
29
+ Health
30
+ </span>
31
+ </button>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div>
36
+ <div className="form__field">
37
+ <label htmlFor="orgunit">
38
+ Uddannelser
39
+ </label>
40
+ <input type="text" id="orgunit" />
41
+ </div>
42
+ <div className="search-filter">
43
+ <h3 className="search-filter__label">Valgte uddannelser:</h3>
44
+ <div className="search-filter__items">
45
+ <button type="button" className="search-filter__item">
46
+ <span className="search-filter__item__value">
47
+ Bacheloruddannelsen i Medicin
48
+ </span>
49
+ </button>
50
+ <button type="button" className="search-filter__item">
51
+ <span className="search-filter__item__value">
52
+ Kandidatuddannelsen i Medicin
53
+ </span>
54
+ </button>
55
+ <button type="button" className="search-filter__item">
56
+ <span className="search-filter__item__value">
57
+ Den sundhedsfaglige kandidatuddannelse
58
+ </span>
59
+ </button>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </form>
64
+ );
65
+
66
+ AUEditFilterComponent.displayName = 'AUEditFilterComponent';
67
+ export default AUEditFilterComponent;
@@ -13,6 +13,7 @@ const AUToolbarComponent: FC<AUToolbarComponentProps> = ({
13
13
  title,
14
14
  buttonClass,
15
15
  buttonElements,
16
+ onCloseContentToggles,
16
17
  }: AUToolbarComponentProps) => {
17
18
  const toolbarRef = useRef<HTMLDivElement>(null);
18
19
  useEffect(() => {
@@ -28,6 +29,9 @@ const AUToolbarComponent: FC<AUToolbarComponentProps> = ({
28
29
  // eslint-disable-next-line max-len
29
30
  toolbarCleanUp = setToolbar(toolbarRef.current, (toolbar: HTMLElement) => {
30
31
  closeAllContentTogglesInToolbar(toolbar);
32
+ if (typeof onCloseContentToggles === 'function') {
33
+ onCloseContentToggles();
34
+ }
31
35
  }, false);
32
36
  }
33
37
 
@@ -95,6 +99,7 @@ AUToolbarComponent.defaultProps = {
95
99
  title: undefined,
96
100
  buttonClass: 'toolbar__toggle',
97
101
  buttonElements: [],
102
+ onCloseContentToggles: undefined,
98
103
  };
99
104
 
100
105
  AUToolbarComponent.displayName = 'AUToolbarComponent';
@@ -1,22 +1,88 @@
1
- import React from 'react';
1
+ import React, { FC, useState } from 'react';
2
2
  import { ComponentStory, ComponentMeta } from '@storybook/react';
3
3
  import AUAlertComponent from '../src/components/AUAlertComponent';
4
4
  import { ThemeWrapper } from './lib/helpers';
5
5
 
6
+ const AlertWrapper: FC<AUAlertComponentProps> = ({
7
+ confirm,
8
+ label,
9
+ mode,
10
+ header,
11
+ message,
12
+ okButtonText,
13
+ cancelButtonText,
14
+ }) => {
15
+ const [processing, setProcessing] = useState<boolean>(false);
16
+ const [done, setDone] = useState<boolean>(false);
17
+
18
+ return (
19
+ <AUAlertComponent
20
+ modalId="alertModal"
21
+ confirm={confirm}
22
+ label={label}
23
+ mode={mode}
24
+ header={header}
25
+ message={message}
26
+ okButtonText={okButtonText}
27
+ cancelButtonText={cancelButtonText}
28
+ processing={processing}
29
+ done={done}
30
+ onClick={() => {
31
+ setDone(false);
32
+ setProcessing(true);
33
+ setTimeout(() => {
34
+ setDone(true);
35
+ setProcessing(false);
36
+ }, 2500);
37
+ }}
38
+ />
39
+ );
40
+ };
41
+
6
42
  export default {
7
43
  title: 'Delphinus/Alert and Confirm',
8
44
  component: AUAlertComponent,
9
45
  argTypes: {
10
- children: {
46
+ label: {
47
+ table: {
48
+ disable: true,
49
+ }
50
+ },
51
+ mode: {
52
+ table: {
53
+ disable: true,
54
+ }
55
+ },
56
+ onClick: {
57
+ table: {
58
+ disable: true,
59
+ }
60
+ },
61
+ modalId: {
11
62
  table: {
12
63
  disable: true,
13
64
  }
14
65
  },
15
- buttonChild: {
66
+ confirm: {
16
67
  table: {
17
68
  disable: true,
18
69
  }
19
- }
70
+ },
71
+ processing: {
72
+ table: {
73
+ disable: true,
74
+ }
75
+ },
76
+ done: {
77
+ table: {
78
+ disable: true,
79
+ }
80
+ },
81
+ cancelButtonText: {
82
+ table: {
83
+ disable: true,
84
+ }
85
+ },
20
86
  },
21
87
  decorators: [
22
88
  (Story, context) => (
@@ -27,19 +93,16 @@ export default {
27
93
  ],
28
94
  } as ComponentMeta<typeof AUAlertComponent>;
29
95
 
30
- const Template: ComponentStory<typeof AUAlertComponent> = (args) => <AUAlertComponent {...args} />;
96
+ const Template: ComponentStory<typeof AUAlertComponent> = (args) => <AlertWrapper {...args} />;
31
97
 
32
98
  export const Alert = Template.bind({});
33
99
 
34
100
  Alert.args = {
35
101
  label: 'Slet',
36
102
  mode: 'ireversable-action',
37
- message: {
38
- message: 'Den valgte fil vil blive slettet.',
39
- type: 'attention',
40
- header: 'Advarsel!',
41
- },
42
- buttonText: 'Ok, forstået',
103
+ header: 'Advarsel',
104
+ message: '<p>Den valgte fil vil blive slettet.</p>',
105
+ okButtonText: 'Ok, forstået',
43
106
  onClick: () => console.log('Clicked'),
44
107
  };
45
108
 
@@ -49,12 +112,9 @@ Confirm.args = {
49
112
  confirm: true,
50
113
  label: 'Slet',
51
114
  mode: 'ireversable-action',
52
- message: {
53
- message: 'Er du sikker på, at du vil slette den valgte fil?',
54
- type: 'warning',
55
- header: 'Advarsel!',
56
- },
57
- buttonText: 'Ja',
115
+ header: 'Bekræft',
116
+ message: '<p>Er du sikker på, at du vil slette den valgte fil?</p>',
117
+ okButtonText: 'Ja',
58
118
  cancelButtonText: 'Annuller',
59
119
  onClick: () => console.log('Clicked'),
60
120
  };
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { ComponentStory, ComponentMeta } from '@storybook/react';
3
+ import AUEditFilterComponent from '../src/components/AUEditFilterComponent';
4
+ import { ThemeWrapper } from './lib/helpers';
5
+
6
+ export default {
7
+ title: 'Delphinus/Filters',
8
+ component: AUEditFilterComponent,
9
+ argTypes: {
10
+ },
11
+ decorators: [
12
+ (Story, context) => (
13
+ <ThemeWrapper theme={context.globals.theme}>
14
+ {Story()}
15
+ </ThemeWrapper>
16
+ )
17
+ ],
18
+ } as ComponentMeta<typeof AUEditFilterComponent>;
19
+
20
+ const Template: ComponentStory<typeof AUEditFilterComponent> = (args) => (
21
+ <>
22
+ <AUEditFilterComponent {...args} />
23
+ </>
24
+ );
25
+
26
+ export const Edit = Template.bind({});
27
+ Edit.args = {
28
+ };
29
+
@@ -33,6 +33,7 @@ const Template: ComponentStory<typeof AUModalComponent> = (args) => {
33
33
  <div className="page__content__block">
34
34
  <AUButtonComponent
35
35
  label="Open modal"
36
+ ariaHasPopup
36
37
  onClick={() => updateArgs({ ...args, show: true })}
37
38
  />
38
39
  <AUModalComponent {...args} onClose={() => updateArgs({ ...args, show: false })}>
@@ -323,4 +323,5 @@ Filter.args = {
323
323
  </div>
324
324
  </AUContentToggleComponent>
325
325
  ],
326
+ onCloseContentToggles: () => console.log('luuuuuk?'),
326
327
  };