@axinom/mosaic-ui 0.66.0 → 0.67.0-rc.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@axinom/mosaic-ui",
3
- "version": "0.66.0",
3
+ "version": "0.67.0-rc.1",
4
4
  "description": "UI components for building Axinom Mosaic applications",
5
5
  "author": "Axinom",
6
6
  "license": "PROPRIETARY",
@@ -112,5 +112,5 @@
112
112
  "publishConfig": {
113
113
  "access": "public"
114
114
  },
115
- "gitHead": "c484ceff643b3ac656a5a5aebb30394be58ee2e0"
115
+ "gitHead": "05c979ef28af7f6460faba7b3dbd034ffcb7bd38"
116
116
  }
@@ -1,5 +1,11 @@
1
1
  @import '../../styles/common.scss';
2
2
 
3
+ .container {
4
+ div:has(> .selectionHeader) {
5
+ z-index: 12 !important;
6
+ }
7
+ }
8
+
3
9
  .header {
4
10
  display: grid;
5
11
  grid-template-columns: 1fr 50px;
@@ -7,10 +13,6 @@
7
13
  align-items: center;
8
14
  }
9
15
 
10
- .item {
11
- z-index: 0;
12
- }
13
-
14
16
  .selectionHeader {
15
17
  display: grid;
16
18
  grid-template-columns: 1fr;
@@ -1,3 +1,4 @@
1
+ import clsx from 'clsx';
1
2
  import React, { useEffect } from 'react';
2
3
  import { noop } from '../../helpers/utils';
3
4
  import { Accordion, AccordionItem } from '../Accordion';
@@ -57,7 +58,7 @@ export const FieldSelection: React.FC<FieldSelectionProps> = ({
57
58
 
58
59
  return (
59
60
  <Accordion
60
- className={className}
61
+ className={clsx(classes.container, className)}
61
62
  expandedByDefault={true}
62
63
  header={
63
64
  <FieldSelectionHeader
@@ -84,7 +85,6 @@ export const FieldSelection: React.FC<FieldSelectionProps> = ({
84
85
  {selectedFields.map((field) => (
85
86
  <AccordionItem
86
87
  key={field.value}
87
- className={classes.item}
88
88
  header={
89
89
  <FieldSelectionItemHeader
90
90
  label={field.label as string}
@@ -5,7 +5,6 @@
5
5
 
6
6
  display: grid;
7
7
  grid-auto-rows: 40px;
8
- gap: 1px;
9
8
  border-top: unset;
10
9
 
11
10
  .option {
@@ -43,16 +43,15 @@
43
43
  display: grid;
44
44
  grid-template-columns: min-content min-content;
45
45
  }
46
+ }
46
47
 
47
- .picker {
48
- position: absolute;
49
- overflow: visible;
50
- z-index: 99999;
51
- }
48
+ .picker {
49
+ overflow: visible;
50
+ z-index: 99999;
52
51
  }
53
52
 
54
53
  .backdrop {
55
- position: absolute;
54
+ position: fixed;
56
55
  top: 0;
57
56
  left: 0;
58
57
  bottom: 0;
@@ -1,6 +1,8 @@
1
1
  import clsx from 'clsx';
2
2
  import { DateTime } from 'luxon';
3
3
  import React, { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { usePopper } from 'react-popper';
4
6
  import { noop } from '../../../helpers/utils';
5
7
  import { Button, ButtonContext } from '../../Buttons';
6
8
  import { DateTimePicker } from '../../DateTime/DateTimePicker';
@@ -46,6 +48,9 @@ export const DateTimeText: React.FC<DateTimeTextProps> = ({
46
48
  ...rest
47
49
  }) => {
48
50
  const container = useRef<HTMLDivElement>(null);
51
+ const [pickerElement, setPickerElement] = useState<HTMLDivElement | null>(
52
+ null,
53
+ );
49
54
  const errorMsg: string | undefined = error;
50
55
  const [display, setDisplay] = useState<string>(() => {
51
56
  const locale = fromISODate(value, modifyTime);
@@ -54,6 +59,30 @@ export const DateTimeText: React.FC<DateTimeTextProps> = ({
54
59
 
55
60
  const [showPicker, setShowPicker] = useState(false);
56
61
 
62
+ const { styles, attributes } = usePopper(container.current, pickerElement, {
63
+ placement: 'bottom-start',
64
+ modifiers: [
65
+ {
66
+ name: 'flip',
67
+ options: {
68
+ fallbackPlacements: ['top-start', 'bottom-start'],
69
+ },
70
+ },
71
+ {
72
+ name: 'preventOverflow',
73
+ options: {
74
+ padding: 8,
75
+ },
76
+ },
77
+ {
78
+ name: 'offset',
79
+ options: {
80
+ offset: [0, 4],
81
+ },
82
+ },
83
+ ],
84
+ });
85
+
57
86
  useEffect(() => {
58
87
  const locale = fromISODate(value, modifyTime);
59
88
  setDisplay(locale ?? '');
@@ -119,31 +148,36 @@ export const DateTimeText: React.FC<DateTimeTextProps> = ({
119
148
  }}
120
149
  />
121
150
  </div>
122
- {showPicker && (
123
- <>
124
- <div
125
- className={clsx(classes.picker)}
126
- style={calculatePosition(container.current)}
127
- >
128
- <DateTimePicker
129
- value={getValue(value)}
130
- onSelected={(value) => {
131
- if (!modifyTime) {
132
- setShowPicker(false);
133
- }
134
- onChange && onChange(DateTime.fromJSDate(value).toISO(), true);
151
+ {showPicker &&
152
+ createPortal(
153
+ <>
154
+ <div
155
+ ref={setPickerElement}
156
+ className={clsx(classes.picker)}
157
+ style={styles.popper}
158
+ {...attributes.popper}
159
+ >
160
+ <DateTimePicker
161
+ value={getValue(value)}
162
+ onSelected={(value) => {
163
+ if (!modifyTime) {
164
+ setShowPicker(false);
165
+ }
166
+ onChange &&
167
+ onChange(DateTime.fromJSDate(value).toISO(), true);
168
+ }}
169
+ showTimePicker={modifyTime}
170
+ />
171
+ </div>
172
+ <div
173
+ className={clsx(classes.backdrop)}
174
+ onClick={() => {
175
+ setShowPicker(false);
135
176
  }}
136
- showTimePicker={modifyTime}
137
- />
138
- </div>
139
- <div
140
- className={clsx(classes.backdrop)}
141
- onClick={() => {
142
- setShowPicker(false);
143
- }}
144
- ></div>
145
- </>
146
- )}
177
+ ></div>
178
+ </>,
179
+ document.body,
180
+ )}
147
181
  </FormElementContainer>
148
182
  );
149
183
  };
@@ -172,22 +206,3 @@ function fromISODate(ISODateString: string, modifyTime: boolean): string {
172
206
  return ISODateString;
173
207
  }
174
208
  }
175
-
176
- const calculatePosition = (
177
- container: HTMLDivElement | null,
178
- ): React.CSSProperties => {
179
- if (!container) {
180
- return {};
181
- }
182
-
183
- const PICKER_HEIGHT = 280;
184
-
185
- const rect = container.getBoundingClientRect();
186
- const top = rect.bottom;
187
-
188
- if (top + PICKER_HEIGHT > window.innerHeight) {
189
- return { top: rect.top - PICKER_HEIGHT, left: container.offsetLeft };
190
- } else {
191
- return { top, left: container.offsetLeft };
192
- }
193
- };
@@ -112,7 +112,6 @@ describe('SvgElement', () => {
112
112
  it('passes through additional SVG attributes', () => {
113
113
  const customProps: SvgElementProps = {
114
114
  id: 'custom-id',
115
- 'data-testid': 'custom-svg',
116
115
  fill: 'currentColor',
117
116
  stroke: 'red',
118
117
  strokeWidth: '2',
@@ -122,7 +121,6 @@ describe('SvgElement', () => {
122
121
  const svg = wrapper.find('svg');
123
122
 
124
123
  expect(svg.prop('id')).toBe('custom-id');
125
- expect(svg.prop('data-testid')).toBe('custom-svg');
126
124
  expect(svg.prop('fill')).toBe('currentColor');
127
125
  expect(svg.prop('stroke')).toBe('red');
128
126
  expect(svg.prop('strokeWidth')).toBe('2');