jamespot-react-components 1.0.2 → 1.0.16

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 (91) hide show
  1. package/.storybook/StorybookContainer/StorybookContainer.css +1 -0
  2. package/babel.config.js +0 -1
  3. package/build/jamespot-react-components.js +254 -235
  4. package/build/jamespot-react-components.js.LICENSE.txt +19 -13
  5. package/build/jamespot-react-components.js.map +1 -1
  6. package/build/src/components/Common/JRCConditionalWrapper.d.ts +4 -4
  7. package/build/src/components/Form/Input/JRCInputCheckbox/JRCInputCheckbox.d.ts +5 -2
  8. package/build/src/components/Form/Input/JRCInputDate/JRCInputDate.d.ts +11 -0
  9. package/build/src/components/Form/Input/JRCInputDate/JRCInputDate.stories.d.ts +5 -0
  10. package/build/src/components/Form/Input/JRCInputText/JRCInputText.d.ts +1 -1
  11. package/build/src/components/Form/Input/JRCInputTextarea/JRCInputTextarea.d.ts +15 -0
  12. package/build/src/components/Form/Input/JRCInputTextarea/JRCInputTextarea.stories.d.ts +5 -0
  13. package/build/src/components/JRCAppContainer/JRCAppContainer.d.ts +1 -0
  14. package/build/src/components/JRCButton/JRCButton.d.ts +25 -0
  15. package/build/src/components/JRCButton/JRCButtonConfig.d.ts +1 -2
  16. package/build/src/components/JRCEllipsis/JRCEllipsis.d.ts +5 -0
  17. package/build/src/components/JRCEllipsis/JRCEllipsis.stories.d.ts +5 -0
  18. package/build/src/components/JRCHref/JRCHref.d.ts +18 -10
  19. package/build/src/components/JRCImg/url.util.d.ts +3 -3
  20. package/build/src/components/JRCList/JRCList.d.ts +2 -0
  21. package/build/src/components/JRCModal/JRCModal.d.ts +5 -1
  22. package/build/src/components/JRCModal/JRCModal.styles.d.ts +0 -1
  23. package/build/src/components/JRCTag/JRCTag.d.ts +2 -0
  24. package/build/src/components/Templates/JRCBase.template.d.ts +9 -0
  25. package/build/src/components/Templates/JRCTemplate.stories.d.ts +13 -0
  26. package/build/src/components/Templates/JRCTwoColumns.template.d.ts +7 -0
  27. package/build/src/hooks/UseDidMountEffect.d.ts +1 -2
  28. package/build/src/index.d.ts +11 -8
  29. package/build/src/styles/theme.d.ts +4 -1
  30. package/build/src/types.d.ts +6 -2
  31. package/externals.d.ts +0 -1
  32. package/externals.json +3 -1
  33. package/package.json +4 -4
  34. package/src/components/Common/JRCConditionalWrapper.tsx +6 -13
  35. package/src/components/Form/Input/JRCFormColor/JRCFormColor.tsx +12 -12
  36. package/src/components/Form/Input/JRCFormEmail/JRCInputEmail.tsx +4 -8
  37. package/src/components/Form/Input/JRCFormSelect/JRCFormSelect.tsx +5 -1
  38. package/src/components/Form/Input/JRCFormSelect/JRCFormSelectTag.tsx +3 -1
  39. package/src/components/Form/Input/JRCInputCheckbox/JRCInputCheckbox.stories.tsx +1 -4
  40. package/src/components/Form/Input/JRCInputCheckbox/JRCInputCheckbox.tsx +12 -10
  41. package/src/components/Form/Input/JRCInputDate/JRCInputDate.stories.tsx +50 -0
  42. package/src/components/Form/Input/JRCInputDate/JRCInputDate.tsx +26 -0
  43. package/src/components/Form/Input/JRCInputText/JRCInputText.tsx +2 -2
  44. package/src/components/Form/Input/JRCInputTextarea/JRCInputTextarea.stories.tsx +52 -0
  45. package/src/components/Form/Input/JRCInputTextarea/JRCInputTextarea.tsx +36 -0
  46. package/src/components/Form/Input/JRCSelect/JRCInputSelect.tsx +1 -1
  47. package/src/components/JRCAppContainer/JRCAppContainer.tsx +6 -2
  48. package/src/components/JRCAppLeftColumn/JRCAppLeftColumn.styles.tsx +2 -1
  49. package/src/components/JRCAvatar/JRCAvatar.test.tsx +10 -6
  50. package/src/components/JRCAvatar/JRCAvatar.tsx +1 -0
  51. package/src/components/JRCButton/JRCButton.stories.tsx +1 -1
  52. package/src/components/JRCButton/JRCButton.tsx +9 -3
  53. package/src/components/JRCButton/JRCButtonConfig.tsx +1 -1
  54. package/src/components/JRCButton/JRCValidationButton.tsx +10 -4
  55. package/src/components/JRCButton/__snapshots__/JRCButton.test.tsx.snap +1 -2
  56. package/src/components/JRCButtonDropdown/JRCButtonDropdown.tsx +2 -2
  57. package/src/components/JRCEllipsis/JRCEllipsis.stories.tsx +18 -0
  58. package/src/components/JRCEllipsis/JRCEllipsis.tsx +22 -0
  59. package/src/components/JRCHref/JRCHref.stories.tsx +2 -0
  60. package/src/components/JRCHref/JRCHref.tsx +42 -15
  61. package/src/components/JRCIcon/JRCIcon.tsx +1 -1
  62. package/src/components/JRCIconButton/JRCIconButton.tsx +1 -4
  63. package/src/components/JRCImg/JRCImg.tsx +4 -2
  64. package/src/components/JRCImg/url.util.ts +7 -6
  65. package/src/components/JRCImg/url.utils.test.ts +7 -1
  66. package/src/components/JRCList/JRCList.styles.tsx +16 -2
  67. package/src/components/JRCList/JRCList.tsx +5 -5
  68. package/src/components/JRCList/JRCListMockData.stories.tsx +1 -1
  69. package/src/components/JRCModal/JRCModal.styles.tsx +0 -6
  70. package/src/components/JRCModal/JRCModal.tsx +75 -61
  71. package/src/components/JRCTag/JRCTag.tsx +29 -9
  72. package/src/components/JRCThemeProvider/animation.css +19 -0
  73. package/src/components/JRCThemeProvider/font.css +1 -1
  74. package/src/components/JRCThemeProvider/gabarit.css +4 -0
  75. package/src/components/JRCTooltip/JRCTooltip.tsx +5 -2
  76. package/src/components/JRCTypography/__snapshots__/JRCTypography.test.tsx.snap +1 -1
  77. package/src/components/Templates/JRCBase.template.tsx +39 -0
  78. package/src/components/Templates/JRCTemplate.stories.tsx +55 -0
  79. package/src/components/Templates/JRCTwoColumns.template.tsx +20 -0
  80. package/src/hooks/UseDidMountEffect.tsx +1 -3
  81. package/src/index.tsx +17 -10
  82. package/src/styles/theme.tsx +12 -6
  83. package/src/translation/lang.json +3 -2
  84. package/src/types.ts +8 -2
  85. package/build/src/components/Form/Input/JRCFormTextEditor/JRCFormTextEditor.d.ts +0 -10
  86. package/build/src/components/Form/Input/JRCFormTextEditor/JRCFormTextEditor.stories.d.ts +0 -5
  87. package/build/src/components/JRCColumnCenterTitle/JRCColumnCenterTitle.d.ts +0 -12
  88. package/src/components/Form/Input/JRCFormTextEditor/JRCFormTextEditor.stories.tsx +0 -30
  89. package/src/components/Form/Input/JRCFormTextEditor/JRCFormTextEditor.tsx +0 -36
  90. package/src/components/JRCColumnCenterTitle/JRCColumnCenterTitle.tsx +0 -26
  91. package/src/variables.scss +0 -67
@@ -45,7 +45,7 @@ const Icon = styled.i<Required<JRCIconProps>>`
45
45
  `;
46
46
 
47
47
  const JRCIcon = ({ color = 'primary', variant = 'default', name, size = 20, className }: JRCIconProps) => (
48
- <Icon className={`react-icon ${name} ${className}`} name={name} size={size} color={color} variant={variant} />
48
+ <Icon className={`react-icon ${name} ${className || ''}`} name={name} size={size} color={color} variant={variant} />
49
49
  );
50
50
 
51
51
  export default JRCIcon;
@@ -81,10 +81,7 @@ const JRCIconButton = (props: JRCIconButtonProps & typeof defaultProps) => {
81
81
  return (
82
82
  <JRCConditionalWrapper
83
83
  condition={!!props.tooltip}
84
- // FIXME TYPESCRIPT-STRICT
85
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
86
- // @ts-ignore
87
- wrapper={(children) => <JRCTooltip {...props.tooltip}>{children}</JRCTooltip>}>
84
+ wrapper={(children) => <JRCTooltip {...(props.tooltip as JRCTooltipProps)}>{children}</JRCTooltip>}>
88
85
  <Button {...props} data-cy={props.dataCy} size={props.size}>
89
86
  <JRCIcon
90
87
  name={props.icon}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- import styled from 'styled-components';
3
+ import styled, { ThemeContext } from 'styled-components';
4
4
  import { formatImgUrl, ImgUrlProps } from './url.util';
5
5
 
6
6
  /**
@@ -43,9 +43,11 @@ const Img = styled.img`
43
43
  `;
44
44
 
45
45
  const JRCImg = (props: JRCImgProps) => {
46
+ const themeContext = React.useContext(ThemeContext);
47
+
46
48
  return (
47
49
  <Img
48
- src={formatImgUrl(props)}
50
+ src={formatImgUrl(props, themeContext.dpr)}
49
51
  loading={props.loading || 'lazy'}
50
52
  alt={props.alt}
51
53
  width={props.width}
@@ -46,7 +46,7 @@ export type ImgUrlProps = {
46
46
  };
47
47
 
48
48
  export function getFrom(arg: Pick<ImgUrlProps, 'from'>) {
49
- return removeIfStartsWith(suffixIfDoesNotExist(arg.from, '/'), '/');
49
+ return removeIfStartsWith(suffixIfDoesNotExist(arg.from, '/'), '/') || '';
50
50
  }
51
51
 
52
52
  export function getTimestamp(arg: Timestamp) {
@@ -58,9 +58,10 @@ export function getUri(arg: UriOrTypeId): string {
58
58
  return `${arg.type}/${arg.recordId}`;
59
59
  }
60
60
 
61
- export function getSize(arg: Size & WidthHeight): string {
61
+ export function getSize(arg: Size & WidthHeight, dpr = 2): string {
62
62
  if ('size' in arg && arg.size) return arg.size;
63
- else if ('width' in arg && arg.width && 'height' in arg && arg.height) return `${arg.width * 2}x${arg.height * 2}`;
63
+ else if ('width' in arg && arg.width && 'height' in arg && arg.height)
64
+ return `${arg.width * dpr}x${arg.height * dpr}`;
64
65
  return '';
65
66
  }
66
67
 
@@ -76,7 +77,7 @@ export function getUrl(url: string): URL | undefined {
76
77
  }
77
78
 
78
79
  try {
79
- return new URL(window.location.origin + url);
80
+ return new URL(window.location.origin + '/' + removeIfStartsWith(url, '/'));
80
81
  } catch (e) {
81
82
  /* silent exception */
82
83
  }
@@ -95,7 +96,7 @@ export function getUrl(url: string): URL | undefined {
95
96
  * The final url is {from}/{size}/{uri}.{format}?_={timestamp}
96
97
  * @param arg
97
98
  */
98
- export function formatImgUrl(arg: ImgUrlProps) {
99
+ export function formatImgUrl(arg: ImgUrlProps, dpr = 2) {
99
100
  if ('url' in arg && arg.url) {
100
101
  const url = getUrl(arg.url);
101
102
  if (url) {
@@ -104,5 +105,5 @@ export function formatImgUrl(arg: ImgUrlProps) {
104
105
  return url.toString();
105
106
  }
106
107
  }
107
- return `/${getFrom(arg)}${getSize(arg)}/${getUri(arg)}.${getFormat(arg)}${getTimestamp(arg)}`;
108
+ return `/${getFrom(arg)}${getSize(arg, dpr)}/${getUri(arg)}.${getFormat(arg)}${getTimestamp(arg)}`;
108
109
  }
@@ -9,6 +9,7 @@ describe('Test utils.url', () => {
9
9
  // @ts-ignore
10
10
  window.location = { origin: 'https://website.com' };
11
11
  });
12
+
12
13
  test('formatImgUrl url', () => {
13
14
  expect(formatImgUrl({ url: '/url/random' })).toStrictEqual('https://website.com/url/random');
14
15
  expect(formatImgUrl({ url: '/url/random?_=12345' })).toStrictEqual('https://website.com/url/random?_=12345');
@@ -24,18 +25,23 @@ describe('Test utils.url', () => {
24
25
  expect(formatImgUrl({ url: 'https://otherwebsite.com/url/random?_=12345', timestamp: 123 })).toStrictEqual(
25
26
  'https://otherwebsite.com/url/random?_=12345',
26
27
  );
28
+ expect(formatImgUrl({ url: 'img/react/bookmark-noresult.png', height: 450 })).toStrictEqual(
29
+ 'https://website.com/img/react/bookmark-noresult.png',
30
+ );
27
31
  });
28
32
 
29
33
  test('getFrom', () => {
30
- expect(getFrom({})).toStrictEqual(undefined);
34
+ expect(getFrom({})).toStrictEqual('');
31
35
  expect(getFrom({ from: 'imagestatic' })).toStrictEqual('imagestatic/');
32
36
  expect(getFrom({ from: 'imagestatic/' })).toStrictEqual('imagestatic/');
33
37
  expect(getFrom({ from: '/imagestatic/' })).toStrictEqual('imagestatic/');
38
+ expect(getFrom({ from: undefined })).toStrictEqual('');
34
39
  });
35
40
 
36
41
  test('getSize', () => {
37
42
  expect(getSize({ size: '32' })).toStrictEqual('32');
38
43
  expect(getSize({ width: 32, height: 32 })).toStrictEqual('64x64');
44
+ expect(getSize({ width: 32, height: 32 }, 3)).toStrictEqual('96x96');
39
45
  });
40
46
 
41
47
  test('getUri', () => {
@@ -4,6 +4,7 @@ import { DndProvider, useDrag, useDrop } from 'react-dnd';
4
4
  import { HTML5Backend } from 'react-dnd-html5-backend';
5
5
  import { JRCIconButton } from '../JRCIconButton/JRCIconButton';
6
6
  import { JRCConditionalWrapper } from '../Common/JRCConditionalWrapper';
7
+ import { useIntl } from 'react-intl';
7
8
  import { DropTargetMonitor } from 'react-dnd/dist/types/types';
8
9
 
9
10
  const TableCss = css`
@@ -19,13 +20,20 @@ export const Table = styled.table`
19
20
  border-collapse: collapse;
20
21
  `;
21
22
 
22
- export const Thead = styled.thead``;
23
+ export const Thead = styled.thead`
24
+ position: sticky;
25
+ top: 0;
26
+ background-color: white;
27
+ border-bottom: 2px solid ${(props) => props.theme.color.grey2};
28
+ z-index: 1;
29
+ `;
23
30
 
24
31
  export const TBody = styled.tbody``;
25
32
 
26
33
  export const Th = styled.th<{ width?: number | string }>`
27
34
  ${TableCss};
28
35
  font-size: 12px;
36
+ padding: 0 4px;
29
37
  font-weight: normal;
30
38
  ${(props) => props.width && props.width > 0 && `width: ${props.width}px`};
31
39
  `;
@@ -75,6 +83,7 @@ export const Tr = styled.tr<{ dragging?: boolean }>`
75
83
 
76
84
  export const Td = styled.td`
77
85
  ${TableCss};
86
+ padding: 0 4px;
78
87
  ${(props) => props.width && `width: ${props.width}`};
79
88
  `;
80
89
 
@@ -137,6 +146,8 @@ export const DraggableTBody = ({ draggable, children }: DraggableTBodyProps) =>
137
146
  const DND_ITEM_TYPE = 'row';
138
147
 
139
148
  export const DraggableTr = ({ index, onDrag, onDrop, draggable, children }: DraggableTrProps) => {
149
+ const intl = useIntl();
150
+
140
151
  const dropRef = React.useRef<HTMLTableRowElement>(null);
141
152
  const dragRef = React.useRef<HTMLTableCellElement>(null);
142
153
  let dragging = false;
@@ -199,7 +210,10 @@ export const DraggableTr = ({ index, onDrag, onDrop, draggable, children }: Drag
199
210
  <Tr ref={dropRef} dragging={dragging}>
200
211
  {draggable && (
201
212
  <DraggableTd ref={dragRef}>
202
- <JRCIconButton icon={'icon-fs-dw'} size="medium" />
213
+ <JRCIconButton
214
+ icon="icon-fs-dw"
215
+ tooltip={{ description: intl.formatMessage({ id: 'GLOBAL_Move' }), position: 'right' }}
216
+ />
203
217
  &nbsp;
204
218
  </DraggableTd>
205
219
  )}
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { useTable, usePagination, useSortBy, UseSortByColumnProps, HeaderGroup, Column, Row, Cell } from 'react-table';
3
3
  import { FormattedMessage } from 'react-intl';
4
4
  import JRCPagination from '../JRCPagination/JRCPagination';
5
- import useDidMountEffect from '../../hooks/UseDidMountEffect';
5
+ import { useDidMountEffect } from '../../hooks/UseDidMountEffect';
6
6
  import JRCIcon from '../JRCIcon/JRCIcon';
7
7
 
8
8
  import {
@@ -25,6 +25,7 @@ import type { Orders } from 'jamespot-user-api';
25
25
  * @member data default react-table data props
26
26
  * @member eventHandlers event handlers: onDrag, onSort and onPage. You Must rearrange the array of data when these events are dispatched
27
27
  * @member config config object. See the Type for use
28
+ * @member className className
28
29
  */
29
30
  export type JRCListProps<T extends Record<string, unknown>> = {
30
31
  columns: Array<Column<T>>;
@@ -45,6 +46,7 @@ export type JRCListProps<T extends Record<string, unknown>> = {
45
46
  nbResults: number;
46
47
  };
47
48
  };
49
+ className?: string;
48
50
  };
49
51
 
50
52
  export const JRCList = <T extends Record<string, unknown>>(props: JRCListProps<T>) => {
@@ -133,7 +135,7 @@ export const JRCList = <T extends Record<string, unknown>>(props: JRCListProps<T
133
135
 
134
136
  return (
135
137
  <React.Fragment>
136
- <Table {...getTableProps()}>
138
+ <Table {...getTableProps()} className={props.className}>
137
139
  <Thead>
138
140
  {headerGroups.map((headerGroup) => (
139
141
  <Tr {...headerGroup.getHeaderGroupProps()}>
@@ -162,9 +164,7 @@ export const JRCList = <T extends Record<string, unknown>>(props: JRCListProps<T
162
164
  <TBody {...getTableBodyProps()}>
163
165
  <DraggableTBody draggable={props.config.draggable}>
164
166
  {rows.map((row: Row<T>, index: number): any => {
165
- if (prepareRow(row) !== undefined) {
166
- prepareRow(row);
167
- }
167
+ prepareRow(row);
168
168
  return (
169
169
  <DraggableTr
170
170
  index={index}
@@ -83,7 +83,7 @@ const Template: Story<never> = (/*args: JRCListProps<MyData>*/) => {
83
83
  limit: config.pagination.perPage,
84
84
  orders,
85
85
  };
86
- jamespot.shortcut.getList(args).then((res: any) => {
86
+ jamespot.bookmark.getList(args).then((res: any) => {
87
87
  setData(res.data);
88
88
  setConfig({
89
89
  ...config,
@@ -63,12 +63,6 @@ export const JRCModalHeader = styled.div`
63
63
  justify-content: space-between;
64
64
  `;
65
65
 
66
- export const JRCModalHeaderTitle = styled.div`
67
- display: flex;
68
- flex-direction: row;
69
- flex: 1;
70
- `;
71
-
72
66
  export const JRCModalFooter = styled.div`
73
67
  flex-shrink: 0;
74
68
  display: flex;
@@ -9,7 +9,6 @@ import {
9
9
  JRCModalContainerFull,
10
10
  JRCModalContent,
11
11
  JRCModalHeader,
12
- JRCModalHeaderTitle,
13
12
  JRCModalFooter,
14
13
  JRCModalClose,
15
14
  } from './JRCModal.styles';
@@ -40,6 +39,8 @@ export interface JRCModalButtonType extends ComponentPropsWithoutRef<'button'> {
40
39
  * @member enableClickAwayCloseModal boolean to enable the close of the Modal by Click Outside of Modal
41
40
  * @member children default ReactNode children in the Modal content
42
41
  * @member portalId id attribute for createPortal
42
+ * @member inPlace if true, does not use a portal
43
+ * @member className use for overriding the styled-components styles
43
44
  */
44
45
  export interface JRCModalProps {
45
46
  open: boolean;
@@ -52,6 +53,8 @@ export interface JRCModalProps {
52
53
  isFull?: boolean;
53
54
  headerButtons?: ReactNode;
54
55
  portalId?: string;
56
+ inPlace?: boolean;
57
+ className?: string;
55
58
  }
56
59
 
57
60
  type MouseEvents = 'click' | 'mousedown' | 'mouseup';
@@ -90,69 +93,67 @@ const JRCModalContainerClickAway = ({
90
93
  return React.createElement(props.isFull ? JRCModalContainerFull : JRCModalContainer, { ref: node, ...props });
91
94
  };
92
95
 
93
- const JRCModal = ({
94
- open,
95
- closeHandler,
96
- buttons,
97
- children,
98
- title,
99
- showIconClose,
100
- enableClickAwayCloseModal,
101
- isFull,
102
- headerButtons,
103
- portalId = 'react-modal',
104
- }: JRCModalProps) => {
105
- const modalRef = React.useRef(null);
106
-
107
- const closeModal = () => {
108
- closeHandler();
109
- };
96
+ const JRCModal = React.forwardRef(
97
+ (
98
+ {
99
+ open,
100
+ closeHandler,
101
+ buttons,
102
+ children,
103
+ title,
104
+ showIconClose,
105
+ enableClickAwayCloseModal,
106
+ isFull,
107
+ headerButtons,
108
+ portalId = 'react-modal',
109
+ inPlace = false,
110
+ className,
111
+ }: JRCModalProps,
112
+ ref: React.ForwardedRef<HTMLDivElement>,
113
+ ) => {
114
+ const closeModal = () => {
115
+ closeHandler();
116
+ };
110
117
 
111
- const escapeHandler = (e: React.KeyboardEvent) => {
112
- if (e.key == 'Escape') closeHandler();
113
- };
114
- const dummyVoid = (): undefined => {
115
- return undefined;
116
- };
118
+ const escapeHandler = (e: React.KeyboardEvent) => {
119
+ if (e.key == 'Escape') closeHandler();
120
+ };
117
121
 
118
- const handleClickAway = (event: any) => {
119
- event.stopPropagation();
120
- closeHandler();
121
- };
122
+ const handleClickAway = (event: any) => {
123
+ event.stopPropagation();
124
+ closeHandler();
125
+ };
122
126
 
123
- const getClickHandlerList = () => {
124
- const handlerList: (() => void)[] = [];
125
- if (buttons != undefined) {
126
- buttons.map((button: JRCModalButtonType) => {
127
- if (button.isClosed == undefined || !button.isClosed)
128
- handlerList.push(() => {
129
- closeHandler();
130
- button.clickHandler != undefined ? button.clickHandler() : dummyVoid();
131
- });
132
- else
133
- handlerList.push(() => {
134
- dummyVoid();
135
- });
136
- });
137
- }
138
- return handlerList;
139
- };
127
+ const getClickHandlerList = () => {
128
+ const handlerList: (() => void)[] = [];
129
+ if (buttons != undefined) {
130
+ buttons.map((button: JRCModalButtonType) => {
131
+ if (button.isClosed == undefined || !button.isClosed)
132
+ handlerList.push(() => {
133
+ closeHandler();
134
+ button.clickHandler != undefined && button.clickHandler();
135
+ });
136
+ else
137
+ handlerList.push(() => {
138
+ /* dummy void */
139
+ });
140
+ });
141
+ }
142
+ return handlerList;
143
+ };
140
144
 
141
- const displayHeaderButtons = headerButtons ? headerButtons : null;
142
- const clickHandlerList = getClickHandlerList();
143
- const portalDiv = document.getElementById(portalId);
145
+ const displayHeaderButtons = headerButtons ? headerButtons : null;
146
+ const clickHandlerList = getClickHandlerList();
147
+ const portalDiv = document.getElementById(portalId);
144
148
 
145
- const ModalBox = open ? (
146
- // FIXME TYPESCRIPT-STRICT
147
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
148
- // @ts-ignore
149
- <JRCThemeProvider>
150
- <JRCModalBox onKeyDown={(e) => escapeHandler(e)} tabIndex={0} ref={modalRef}>
149
+ const ModalBox = () => (
150
+ <JRCModalBox onKeyDown={(e) => escapeHandler(e)} tabIndex={0} ref={ref} className={className}>
151
151
  <JRCModalContainerClickAway
152
+ className="modal-container"
152
153
  onClickAway={enableClickAwayCloseModal ? handleClickAway : undefined}
153
154
  isFull={isFull}>
154
155
  {(title || showIconClose) && (
155
- <JRCModalHeader>
156
+ <JRCModalHeader className={'modal-header'}>
156
157
  {title && <JRCH3>{title}</JRCH3>}
157
158
  {displayHeaderButtons}
158
159
  {showIconClose && (
@@ -163,7 +164,7 @@ const JRCModal = ({
163
164
  </JRCModalHeader>
164
165
  )}
165
166
 
166
- <JRCModalContent>{children}</JRCModalContent>
167
+ <JRCModalContent className="modal-content">{children}</JRCModalContent>
167
168
 
168
169
  {buttons ? (
169
170
  <JRCModalFooter>
@@ -180,10 +181,23 @@ const JRCModal = ({
180
181
  ) : null}
181
182
  </JRCModalContainerClickAway>
182
183
  </JRCModalBox>
183
- </JRCThemeProvider>
184
- ) : null;
185
-
186
- return portalDiv ? ReactDOM.createPortal(ModalBox, portalDiv) : null;
187
- };
184
+ );
185
+
186
+ if (open) {
187
+ if (inPlace) {
188
+ return <ModalBox />;
189
+ } else if (portalDiv) {
190
+ // when using a portal, we need to provide the Theme explicitely
191
+ return ReactDOM.createPortal(
192
+ <JRCThemeProvider>
193
+ <ModalBox />
194
+ </JRCThemeProvider>,
195
+ portalDiv,
196
+ );
197
+ }
198
+ }
199
+ return null;
200
+ },
201
+ );
188
202
 
189
203
  export default JRCModal;
@@ -19,6 +19,7 @@ import JRCTooltip from '../JRCTooltip/JRCTooltip';
19
19
  * @member focusable - whether the element is focusable. Independant of onClick property
20
20
  * @member isFocused - whether the element is focused. Property used with variant for styling the component
21
21
  * @member tooltipDescription - if present, show a tooltip with the description
22
+ * @member clickVariant - whether the hover/focus style is a selectable item or a deletable item
22
23
  */
23
24
  export type JRCTagProps<T> = UriOrTypeId & {
24
25
  collapsed?: boolean;
@@ -31,9 +32,10 @@ export type JRCTagProps<T> = UriOrTypeId & {
31
32
  isFocused?: boolean;
32
33
  tooltipDescription?: string;
33
34
  alt?: string;
35
+ clickVariant?: 'select' | 'delete';
34
36
  };
35
37
 
36
- const TagWrapper = styled.div<{ focusable: boolean; isFocused: boolean }>`
38
+ const TagWrapper = styled.div<{ focusable: boolean; isFocused: boolean; clickVariant: 'select' | 'delete' }>`
37
39
  position: relative;
38
40
  display: inline-flex;
39
41
  align-items: center;
@@ -44,16 +46,16 @@ const TagWrapper = styled.div<{ focusable: boolean; isFocused: boolean }>`
44
46
  cursor: ${(props) => (props.focusable ? 'pointer' : 'default')};
45
47
  background-color: ${(props) => {
46
48
  if (props.focusable && props.isFocused) {
47
- return props.theme.color.orangeL80;
49
+ return props.theme.color[config[props.clickVariant].hoverBGColor];
48
50
  } else {
49
- return props.theme.color.grey0;
51
+ return props.theme.color[config[props.clickVariant].backgroundColor];
50
52
  }
51
53
  }};
52
54
  color: ${(props) => {
53
55
  if (props.focusable && props.isFocused) {
54
- return props.theme.color.grey4;
56
+ return props.theme.color[config[props.clickVariant].hoverColor];
55
57
  } else {
56
- return props.theme.color.grey5;
58
+ return props.theme.color[config[props.clickVariant].color];
57
59
  }
58
60
  }};
59
61
 
@@ -72,14 +74,15 @@ const TagWrapper = styled.div<{ focusable: boolean; isFocused: boolean }>`
72
74
  }
73
75
 
74
76
  :hover {
75
- ${(props) => props.focusable && `background-color: ${props.theme.color.orangeL80}`};
76
- ${(props) => props.focusable && `color: ${props.theme.color.grey4}`};
77
+ ${(props) =>
78
+ props.focusable && `background-color: ${props.theme.color[config[props.clickVariant].hoverBGColor]}`};
79
+ ${(props) => props.focusable && `color: ${props.theme.color[config[props.clickVariant].hoverColor]}`};
77
80
  }
78
81
  :hover i {
79
- ${(props) => props.focusable && `display: block`};
82
+ ${(props) => props.focusable && props.clickVariant === 'delete' && `display: block`};
80
83
  }
81
84
  & i {
82
- ${(props) => props.focusable && props.isFocused && `display: block`};
85
+ ${(props) => props.focusable && props.isFocused && props.clickVariant === 'delete' && `display: block`};
83
86
  }
84
87
  `;
85
88
 
@@ -87,8 +90,24 @@ const TagLabel = styled.div`
87
90
  margin-left: 4px;
88
91
  `;
89
92
 
93
+ const config = {
94
+ select: {
95
+ color: 'grey4',
96
+ backgroundColor: 'white',
97
+ hoverColor: 'grey5',
98
+ hoverBGColor: 'grey0',
99
+ },
100
+ delete: {
101
+ color: 'grey5',
102
+ backgroundColor: 'grey0',
103
+ hoverColor: 'grey4',
104
+ hoverBGColor: 'orangeL80',
105
+ },
106
+ };
107
+
90
108
  export function JRCTag<T>(props: JRCTagProps<T>) {
91
109
  const uri = 'uri' in props ? props.uri : `${props.type}/${props.recordId}`;
110
+ const clickVariant = props.clickVariant || 'delete';
92
111
 
93
112
  const getAvatar = () =>
94
113
  React.createElement(
@@ -104,6 +123,7 @@ export function JRCTag<T>(props: JRCTagProps<T>) {
104
123
  : undefined,
105
124
  focusable: props.focusable,
106
125
  isFocused: props.isFocused,
126
+ clickVariant,
107
127
  },
108
128
  <>
109
129
  <JRCAvatar alt={props.alt} uri={uri} variant={props.variant} focusable={props.focusable} />
@@ -1,3 +1,22 @@
1
+ .wiggle {
2
+ animation: 0.25s ease-in-out 0s 4 wiggle;
3
+ }
4
+
5
+ @keyframes wiggle {
6
+ 0% {
7
+ transform: rotate(0deg);
8
+ }
9
+ 25% {
10
+ transform: rotate(10deg) scale(1.1);
11
+ }
12
+ 75% {
13
+ transform: rotate(-10deg) scale(1.1);
14
+ }
15
+ 100% {
16
+ transform: rotate(0deg);
17
+ }
18
+ }
19
+
1
20
  .scale-left {
2
21
  animation: scale var(--timeout, 1000ms) linear 0s 1;
3
22
  }
@@ -5,7 +5,7 @@
5
5
  .react-reset button,
6
6
  .react-reset select,
7
7
  .react-reset textarea {
8
- font-family: 'Poppins';
8
+ font-family: var(--font-family);
9
9
  font-size: 14px;
10
10
  line-height: 1.5em;
11
11
  font-weight: 400;
@@ -1,3 +1,7 @@
1
+ .react-reset {
2
+ width: 100%;
3
+ }
4
+
1
5
  .r-grid {
2
6
  display: grid;
3
7
  --pageColWidthLeft: 230px;
@@ -71,6 +71,9 @@ const Text = styled(JRCText)<{ sizeTooltip: keyof typeof sizes.padding }>`
71
71
  margin: 0;
72
72
  text-align: ${(props) => (props.sizeTooltip === 'small' ? 'center' : 'initial')};
73
73
  `;
74
+ const InlineBlock = styled.span`
75
+ display: inline-block;
76
+ `;
74
77
 
75
78
  export const JRCTooltip = (props: JRCTooltipProps) => {
76
79
  const id = uuidv4();
@@ -86,14 +89,14 @@ export const JRCTooltip = (props: JRCTooltipProps) => {
86
89
  };
87
90
  return (
88
91
  <>
89
- <span
92
+ <InlineBlock
90
93
  aria-describedby={id}
91
94
  data-event="mouseenter focusin"
92
95
  data-event-off={props.closeButton && props.button ? 'click' : 'mouseleave'}
93
96
  data-tip
94
97
  data-for={id}>
95
98
  {props.children}
96
- </span>
99
+ </InlineBlock>
97
100
  <Tooltip
98
101
  effect="solid"
99
102
  role="tooltip"
@@ -3,7 +3,7 @@
3
3
  exports[`JRCTypography match snapshot 1`] = `
4
4
  <DocumentFragment>
5
5
  <p
6
- class="sc-bdvvtL iOYRhi"
6
+ class="sc-bdvvtL gGmII"
7
7
  >
8
8
  JRCTypography
9
9
  </p>
@@ -0,0 +1,39 @@
1
+ import { JRCAppContainer } from 'components/JRCAppContainer/JRCAppContainer';
2
+ import JRCLoader from 'components/JRCLoader/JRCLoader';
3
+ import { JRCTypography } from 'components/JRCTypography/JRCTypography';
4
+ import * as React from 'react';
5
+ import styled from 'styled-components';
6
+
7
+ export type JRCTemplateBaseProps = {
8
+ children: React.ReactNode;
9
+ isLoading: boolean;
10
+ title?: React.ReactNode;
11
+ };
12
+
13
+ export const ChildrenContainerStyle = styled.div`
14
+ display: block;
15
+ width: 100%;
16
+ `;
17
+
18
+ export const ChildrenContainer = (props: JRCTemplateBaseProps) => {
19
+ return (
20
+ <ChildrenContainerStyle>
21
+ {props.title && (
22
+ <JRCTypography variant="h1" size="xl" weight="medium">
23
+ {props.title}
24
+ </JRCTypography>
25
+ )}
26
+ {props.isLoading ? <JRCLoader variant="skeleton" /> : <>{props.children}</>}
27
+ </ChildrenContainerStyle>
28
+ );
29
+ };
30
+
31
+ export const JRCTemplateBase: React.FC<any> = (props: JRCTemplateBaseProps) => {
32
+ return (
33
+ <JRCAppContainer>
34
+ <ChildrenContainer title={props.title} isLoading={props.isLoading}>
35
+ {props.children}
36
+ </ChildrenContainer>
37
+ </JRCAppContainer>
38
+ );
39
+ };