@axinom/mosaic-ui 0.67.0-rc.0 → 0.67.0-rc.2

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.67.0-rc.0",
3
+ "version": "0.67.0-rc.2",
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": "70d5670035f6c7b78dcea00a0b5e082bef45afe3"
115
+ "gitHead": "2364d1ad780b65c4974987c3f3ac30e09dfe850e"
116
116
  }
@@ -109,7 +109,7 @@ $input-inactive: 1px solid var(--input-border-color, $input-border-color);
109
109
  }
110
110
  }
111
111
 
112
- .content {
112
+ .contentContainer {
113
113
  display: grid;
114
114
  grid-template-rows: 0fr;
115
115
  transition: grid-template-rows 200ms cubic-bezier(0.4, 0, 0.2, 1);
@@ -118,6 +118,12 @@ $input-inactive: 1px solid var(--input-border-color, $input-border-color);
118
118
  grid-template-rows: 1fr;
119
119
  }
120
120
 
121
+ .content {
122
+ border-left: 1px solid transparent;
123
+ border-right: 1px solid transparent;
124
+ border-bottom: 1px solid transparent;
125
+ }
126
+
121
127
  .active {
122
128
  display: grid;
123
129
  overflow: hidden;
@@ -274,7 +274,9 @@ export const Filter = <T extends Data>({
274
274
  />
275
275
  </div>
276
276
  <div
277
- className={clsx(classes.content, { [classes.expanded]: isExpanded })}
277
+ className={clsx(classes.contentContainer, {
278
+ [classes.expanded]: isExpanded,
279
+ })}
278
280
  >
279
281
  {hasValue && !isExpanded && (
280
282
  <div
@@ -299,7 +301,7 @@ export const Filter = <T extends Data>({
299
301
  {isExpanded && (
300
302
  <div
301
303
  data-test-id="filter-content"
302
- className={clsx({ [classes.active]: isActive })}
304
+ className={clsx({ [classes.active]: isActive }, classes.content)}
303
305
  >
304
306
  {renderFilterContent()}
305
307
  </div>
@@ -4,13 +4,24 @@
4
4
  .container {
5
5
  display: grid;
6
6
 
7
+ .dateTimeInputWrapper {
8
+ border: $input-inactive;
9
+
10
+ &:focus-within {
11
+ border: $input-active;
12
+ }
13
+ }
7
14
  .dateTimeInput {
8
15
  display: grid;
9
16
  grid-template-rows: 1fr;
10
17
  grid-template-columns: 1fr min-content;
11
18
 
12
19
  place-items: center;
13
- border: $input-inactive;
20
+ border: 2px solid transparent;
21
+
22
+ &:focus-within {
23
+ border: none;
24
+ }
14
25
 
15
26
  .inputValue {
16
27
  &:focus {
@@ -40,10 +51,6 @@
40
51
  }
41
52
  }
42
53
 
43
- &:focus-within {
44
- border: $input-active;
45
- }
46
-
47
54
  &.hasError {
48
55
  border: 3px solid
49
56
  var(--input-invalid-border-color, $input-invalid-border-color);
@@ -106,32 +106,34 @@ export const DateTimeFilter: React.FC<DateTimeFilterProps> = ({
106
106
  className,
107
107
  )}
108
108
  >
109
- <div
110
- className={clsx(
111
- classes.dateTimeInput,
112
- 'datetime-border-wrapper',
113
- errorMsg && classes.hasError,
114
- )}
115
- ref={container}
116
- >
117
- <input
118
- id={inputId}
119
- autoFocus
120
- className={clsx(classes.inputValue)}
121
- onKeyDown={handleKeyDown}
122
- onChange={(e) => setValue(e.target.value)}
123
- value={value}
124
- />
125
- <Button
126
- className={clsx(classes.button)}
127
- buttonContext={ButtonContext.None}
128
- icon={IconName.Calendar}
129
- onButtonClicked={(e) => {
130
- e.persist();
131
- e.preventDefault();
132
- setShowPicker(!showPicker);
133
- }}
134
- />
109
+ <div className={clsx(classes.dateTimeInputWrapper)}>
110
+ <div
111
+ className={clsx(
112
+ classes.dateTimeInput,
113
+ 'datetime-border-wrapper',
114
+ errorMsg && classes.hasError,
115
+ )}
116
+ ref={container}
117
+ >
118
+ <input
119
+ id={inputId}
120
+ autoFocus
121
+ className={clsx(classes.inputValue)}
122
+ onKeyDown={handleKeyDown}
123
+ onChange={(e) => setValue(e.target.value)}
124
+ value={value}
125
+ />
126
+ <Button
127
+ className={clsx(classes.button)}
128
+ buttonContext={ButtonContext.None}
129
+ icon={IconName.Calendar}
130
+ onButtonClicked={(e) => {
131
+ e.persist();
132
+ e.preventDefault();
133
+ setShowPicker(!showPicker);
134
+ }}
135
+ />
136
+ </div>
135
137
  </div>
136
138
  {errorMsg !== undefined && <small>{errorMsg}</small>}
137
139
  </div>
@@ -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
- };