react-ui-basics 0.0.189 → 0.0.191

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": "react-ui-basics",
3
- "version": "0.0.189",
3
+ "version": "0.0.191",
4
4
  "description": "",
5
5
  "module": "index.js",
6
6
  "_main": "index.cjs.js",
@@ -22,6 +22,7 @@ import {
22
22
  import Button from "./Button";
23
23
  import MaterialIcon from "./MaterialIcon";
24
24
  import {PureComponent} from "./ReactConstants";
25
+ import ReactDOM from "react-dom";
25
26
 
26
27
  export const MODE_DEFAULT = 'default';
27
28
  export const MODE_INLINE = 'inline';
@@ -99,7 +100,9 @@ class AutocompleteSelect extends PureComponent {
99
100
  componentDidMount() {
100
101
  addEventListener(DOCUMENT, 'mousedown', this.listener = (e) => {
101
102
  if (__state(this).isActive && this.el && !this.el.contains(__target(e))) {
102
- this.onClickOutside()
103
+ if(!__props(this).listPortal || !this.list?.el?.el || !this.list.el.el.contains(__target(e))){
104
+ this.onClickOutside()
105
+ }
103
106
  }
104
107
  })
105
108
  if (__props(this).required) {
@@ -112,11 +115,29 @@ class AutocompleteSelect extends PureComponent {
112
115
  }
113
116
  }
114
117
  this.initSelected(__props(this), __state(this))
118
+ this.updateListPosition()
119
+ }
120
+
121
+ updateListPosition = () => {
122
+ if (__props(this).listPortal && __state(this).isActive) {
123
+ var rect = this.el.getBoundingClientRect();
124
+ this.setState({
125
+ listStyles: {
126
+ position: 'absolute',
127
+ top: rect.bottom + 'px',
128
+ left: __left(rect) + 'px',
129
+ minWidth: __width(rect) + 'px',
130
+ maxHeight: '300px',
131
+ }
132
+ })
133
+ }
115
134
  }
116
135
 
117
136
  componentDidUpdate(prevProps, prevState, snapshot) {
118
137
  if (__props(this).value !== __value(prevProps))
119
138
  this.initSelected(__props(this), __state(this))
139
+ if (__state(this).isActive && !prevState.isActive)
140
+ this.updateListPosition()
120
141
  }
121
142
 
122
143
  initSelected = ({value, mode, allowCustom}, {filterValue = ''}) => {
@@ -174,11 +195,12 @@ class AutocompleteSelect extends PureComponent {
174
195
  allowCustom,
175
196
  inlineSelected,
176
197
  removeIcon,
198
+ listPortal,
177
199
  } = __props(this);
178
200
  const id = __props(this).id || this.randomId;
179
201
  const selectedComponent = __props(this).selectedComponent || childComponent;
180
202
  const {selected = {}, filterValue = '', errored} = __state(this);
181
- let {isActive} = __state(this);
203
+ let {isActive, listStyles} = __state(this);
182
204
  if (__props(this).isActive !== UNDEFINED) {
183
205
  isActive = __props(this).isActive
184
206
  }
@@ -209,6 +231,26 @@ class AutocompleteSelect extends PureComponent {
209
231
  const dataFiltered = allowCustom ? [filterValueTrimmed, ...data.filter(suggestion => suggestion !== filterValueTrimmed)] : data;
210
232
 
211
233
  const filterFunction = this.createFilter(prefilter, filterValue, filterValueTrimmed.toLowerCase(), filter)
234
+ let filteredList = <FilteredList className={classNames(isActive && 'visible', listPortal && 'portal')}
235
+ style={listStyles}
236
+ ref={ref('list', this)}
237
+ filter={filterFunction}
238
+ selectSingle={!allowCustom}
239
+ scroll={scroll}
240
+ inline={isInline}
241
+ nextProvider={ref('next', this)}
242
+ prevProvider={ref('prev', this)}
243
+ selectedProvider={ref('getSelected', this)}
244
+ resetProvider={ref('reset', this)}
245
+ onSelect={this.onSelect}
246
+ selected={selected}
247
+ childComponent={childComponent}
248
+ childProps={childProps}
249
+ data={dataFiltered}
250
+ labels={labels}
251
+ />;
252
+ filteredList = listPortal ? ReactDOM.createPortal(filteredList, listPortal) : filteredList
253
+
212
254
  return (
213
255
  <div id={id}
214
256
  className={classNames(
@@ -333,23 +375,7 @@ class AutocompleteSelect extends PureComponent {
333
375
  </div>
334
376
  )}
335
377
 
336
- <FilteredList className={classNames(isActive && 'visible')}
337
- ref={ref('list', this)}
338
- filter={filterFunction}
339
- selectSingle={!allowCustom}
340
- scroll={scroll}
341
- inline={isInline}
342
- nextProvider={ref('next', this)}
343
- prevProvider={ref('prev', this)}
344
- selectedProvider={ref('getSelected', this)}
345
- resetProvider={ref('reset', this)}
346
- onSelect={this.onSelect}
347
- selected={selected}
348
- childComponent={childComponent}
349
- childProps={childProps}
350
- data={dataFiltered}
351
- labels={labels}
352
- />
378
+ {filteredList}
353
379
  </div>
354
380
  )
355
381
  }
@@ -8,21 +8,25 @@
8
8
  .DatePicker > .TextField input {
9
9
  text-align: center;
10
10
  }
11
- .DatePicker .calendar {
11
+
12
+ .calendar {
12
13
  user-select: none;
13
14
  position: absolute;
14
15
  top: 33px;
15
16
  z-index: 10;
16
17
  box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
18
+ border-radius: 4px;
19
+ overflow: hidden;
17
20
  transition: 0.2s all ease;
18
21
  opacity: 0;
19
22
  visibility: hidden;
20
23
  }
21
- .DatePicker .calendar.focused {
24
+ .calendar.focused {
22
25
  opacity: 1;
23
26
  visibility: visible;
24
27
  }
25
- .DatePicker .monthSelect {
28
+ .calendar .monthSelect {
29
+ align-items: center;
26
30
  margin-bottom: 0;
27
31
  background: white;
28
32
  font-size: 12px;
@@ -31,39 +35,39 @@
31
35
  padding-left: 16px;
32
36
  height: 40px;
33
37
  }
34
- .DatePicker .monthSelect span {
38
+ .calendar .monthSelect span {
35
39
  margin-right: auto;
36
40
  }
37
- .DatePicker .monthSelect .Button {
41
+ .calendar .monthSelect .Button {
38
42
  min-width: 25px;
39
43
  min-height: 25px;
40
44
  }
41
- .DatePicker .monthSelect .Button .material-icons {
45
+ .calendar .monthSelect .Button .material-icons {
42
46
  font-size: 16px;
43
47
  }
44
- .DatePicker .monthSelect .Button.disabled {
48
+ .calendar .monthSelect .Button.disabled {
45
49
  background: transparent;
46
50
  }
47
- .DatePicker .CalendarMonthView {
51
+ .calendar .CalendarMonthView {
48
52
  background: white;
49
53
  }
50
- .DatePicker .CalendarMonthView .headers, .DatePicker .CalendarMonthView .days {
54
+ .calendar .CalendarMonthView .headers, .calendar .CalendarMonthView .days {
51
55
  margin-bottom: 0;
52
56
  }
53
- .DatePicker .CalendarMonthView .header {
57
+ .calendar .CalendarMonthView .header {
54
58
  font-size: 12px;
55
59
  font-weight: bold;
56
60
  text-align: center;
57
61
  text-transform: uppercase;
58
62
  margin: 5px;
59
63
  }
60
- .DatePicker .CalendarMonthView .day {
64
+ .calendar .CalendarMonthView .day {
61
65
  font-size: 10px;
62
66
  }
63
- .DatePicker .CalendarMonthView .day.notSelectedMonth {
67
+ .calendar .CalendarMonthView .day.notSelectedMonth {
64
68
  color: #969696;
65
69
  }
66
- .DatePicker .CalendarMonthView .day span {
70
+ .calendar .CalendarMonthView .day span {
67
71
  display: inline-flex;
68
72
  justify-content: center;
69
73
  align-items: center;
@@ -74,20 +78,20 @@
74
78
  transition: 0.2s all ease;
75
79
  cursor: pointer;
76
80
  }
77
- .DatePicker .CalendarMonthView .day span:hover {
81
+ .calendar .CalendarMonthView .day span:hover {
78
82
  background-color: #e6e6e6;
79
83
  }
80
- .DatePicker .CalendarMonthView .day span.inactive {
84
+ .calendar .CalendarMonthView .day span.inactive {
81
85
  color: lightgray;
82
86
  cursor: unset;
83
87
  }
84
- .DatePicker .CalendarMonthView .day span.inactive:hover {
88
+ .calendar .CalendarMonthView .day span.inactive:hover {
85
89
  background: unset;
86
90
  }
87
- .DatePicker .CalendarMonthView .day span.selected {
91
+ .calendar .CalendarMonthView .day span.selected {
88
92
  color: white;
89
93
  background-color: #2196F3;
90
94
  }
91
- .DatePicker .CalendarMonthView .day span.selected:hover {
95
+ .calendar .CalendarMonthView .day span.selected:hover {
92
96
  background-color: #51adf6;
93
97
  }
@@ -11,26 +11,28 @@
11
11
  text-align: center;
12
12
  }
13
13
  }
14
-
15
- .calendar {
16
- user-select: none;
17
- position: absolute;
18
- top: 33px;
19
- z-index: 10;
20
- box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
21
-
22
- transition: 0.2s all ease;
23
- opacity: 0;
24
- visibility: hidden;
25
-
26
- &.focused {
27
- opacity: 1;
28
- visibility: visible;
29
- }
14
+ }
15
+
16
+ .calendar {
17
+ user-select: none;
18
+ position: absolute;
19
+ top: 33px;
20
+ z-index: 10;
21
+ box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
22
+ border-radius: 4px;
23
+ overflow: hidden;
24
+
25
+ transition: 0.2s all ease;
26
+ opacity: 0;
27
+ visibility: hidden;
28
+
29
+ &.focused {
30
+ opacity: 1;
31
+ visibility: visible;
30
32
  }
31
33
 
32
-
33
34
  .monthSelect {
35
+ align-items: center;
34
36
  margin-bottom: 0;
35
37
  background: white;
36
38
  font-size: 12px;
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
+ import ReactDOM from "react-dom";
2
3
  import './DatePicker.css'
3
4
  import TextField from "./TextField";
4
5
  import * as DateTools from "./DateTools";
5
- import {orNoop, classNames, preventDefault} from "./Tools";
6
+ import {orNoop, classNames, preventDefault, ref} from "./Tools";
6
7
  import Button from './Button'
7
8
  import CalendarMonthView from "./CalendarMonthView";
8
9
  import MaterialIcon from "./MaterialIcon";
@@ -41,7 +42,8 @@ export interface DatePickerProps {
41
42
  parser: (input: string) => Date
42
43
  onChange: (e) => void
43
44
  dayOfWeekToString: (day: number) => string | JSX.Element
44
- monthToString: (day: number) => string | JSX.Element
45
+ monthToString: (day: number) => string | JSX.Element,
46
+ portal?: Element | DocumentFragment
45
47
  }
46
48
 
47
49
  interface DatePickerState {
@@ -49,10 +51,12 @@ interface DatePickerState {
49
51
  value: Date,
50
52
  selectedMonth: DateExtended,
51
53
  text: string,
54
+ popupStyles?: any,
52
55
  }
53
56
 
54
57
  class DatePicker extends React.Component<DatePickerProps, DatePickerState> {
55
58
  private el: HTMLDivElement;
59
+ private popup: HTMLDivElement;
56
60
  private listener: (e) => void;
57
61
 
58
62
  constructor(props: DatePickerProps) {
@@ -78,7 +82,8 @@ class DatePicker extends React.Component<DatePickerProps, DatePickerState> {
78
82
  if (this.props.open !== prevProps.open) {
79
83
  const open = !!this.props.open
80
84
  this.setState({
81
- focused: open
85
+ focused: open,
86
+ popupStyles: this.getPopupStyles()
82
87
  })
83
88
  }
84
89
  if (!this.state.focused && !!prevState.focused) {
@@ -86,10 +91,24 @@ class DatePicker extends React.Component<DatePickerProps, DatePickerState> {
86
91
  }
87
92
  };
88
93
 
94
+ private getPopupStyles = () => {
95
+ const boundingClientRect = this.el.getBoundingClientRect();
96
+ return {
97
+ left: boundingClientRect.left + 'px',
98
+ top: boundingClientRect.bottom + 'px',
99
+ }
100
+ };
101
+
89
102
  componentDidMount() {
90
103
  document.addEventListener('mousedown', this.listener = (e) => {
91
- if (this.state.focused && !this.el.contains(e.target))
92
- this.setState({focused: false});
104
+ if (this.state.focused && !this.el.contains(e.target)) {
105
+ if (!this.props.portal || !this.popup.contains(e.target)) {
106
+ this.setState({focused: false});
107
+ }
108
+ }
109
+ })
110
+ this.setState({
111
+ popupStyles: this.getPopupStyles()
93
112
  })
94
113
  };
95
114
 
@@ -98,35 +117,76 @@ class DatePicker extends React.Component<DatePickerProps, DatePickerState> {
98
117
  };
99
118
 
100
119
  shouldComponentUpdate(nextProps, nextState, nextContext) {
101
- if (!DateTools.equals(this.props.value, nextProps.value))
120
+ if (!DateTools.equals(this.props.value, nextProps.value)) {
102
121
  return true;
122
+ }
103
123
 
104
- if (!DateTools.equals(this.state.value, nextState.value))
124
+ if (!DateTools.equals(this.state.value, nextState.value)) {
105
125
  return true;
126
+ }
106
127
 
107
- if (this.props.open !== nextProps.open)
128
+ if (this.props.open !== nextProps.open) {
108
129
  return true;
130
+ }
109
131
 
110
- if (this.state.text !== nextState.text)
132
+ if (this.state.text !== nextState.text) {
111
133
  return true;
134
+ }
112
135
 
113
- if (this.state.focused !== nextState.focused)
136
+ if (this.state.focused !== nextState.focused) {
114
137
  return true;
138
+ }
115
139
 
116
- if (this.state.selectedMonth !== nextState.selectedMonth)
140
+ if (this.state.selectedMonth !== nextState.selectedMonth) {
117
141
  return true;
142
+ }
118
143
 
119
- if (!DateTools.equals(this.props.minDate, nextProps.minDate))
144
+ if (!DateTools.equals(this.props.minDate, nextProps.minDate)) {
120
145
  return true;
146
+ }
121
147
 
122
148
  return false;
123
149
  };
124
150
 
125
151
  render() {
126
- const {minDate, formatter, parser, dayOfWeekToString, monthToString, renderInput} = this.props;
127
- const {value, text, focused, selectedMonth} = this.state;
128
-
129
- return <div className={`DatePicker`} ref={el => this.el = el}>
152
+ const {minDate, formatter, parser, dayOfWeekToString, monthToString, renderInput, portal} = this.props;
153
+ const {value, text, focused, selectedMonth, popupStyles } = this.state;
154
+
155
+ let popup = <div className={classNames('calendar', focused && 'focused', portal && 'portal')}
156
+ ref={ref('popup', this)}
157
+ style={popupStyles}>
158
+ <div className={'row monthSelect'}>
159
+ <span>
160
+ {monthToString(selectedMonth.get(DateTools.TimeUnit.MONTH))}
161
+ &nbsp;{selectedMonth.get(DateTools.TimeUnit.YEAR)}
162
+ </span>
163
+ <Button flat={true} round={true} disabled={minDate && DateTools.dateOf(selectedMonth).isBefore(minDate)} onClick={() => {
164
+ this.setState({selectedMonth: DateTools.dateOf(selectedMonth).subtract(1, DateTools.TimeUnit.MONTH)})
165
+ }}>
166
+ <MaterialIcon icon={'chevron_left'}/>
167
+ </Button>
168
+ <Button flat={true} round={true} onClick={() => {
169
+ this.setState({selectedMonth: DateTools.dateOf(selectedMonth).add(1, DateTools.TimeUnit.MONTH)})
170
+ }}>
171
+ <MaterialIcon icon={'chevron_right'}/>
172
+ </Button>
173
+ </div>
174
+ <CalendarMonthView monthOf={selectedMonth}
175
+ dayOfWeekToString={dayOfWeekToString}
176
+ dayRenderer={(date) => <DayRenderer
177
+ day={DateTools.dateOf(date)}
178
+ selected={value}
179
+ minDate={minDate}
180
+ onClick={value => {
181
+ this.onChange(value)
182
+ this.setState({focused: false, text: formatter(value)});
183
+ }}
184
+ />}/>
185
+ </div>;
186
+
187
+ popup = portal ? ReactDOM.createPortal(popup, portal) : popup
188
+
189
+ return <div className={`DatePicker`} ref={ref('el', this)}>
130
190
  {!!renderInput && renderInput()}
131
191
  {!renderInput && <TextField id={'value'} value={text}
132
192
  autoComplete="off"
@@ -150,35 +210,7 @@ class DatePicker extends React.Component<DatePickerProps, DatePickerState> {
150
210
  }
151
211
  }}
152
212
  />}
153
- <div className={`calendar ${focused && 'focused'}`}>
154
- <div className={'row monthSelect'}>
155
- <span>
156
- {monthToString(selectedMonth.get(DateTools.TimeUnit.MONTH))}
157
- &nbsp;{selectedMonth.get(DateTools.TimeUnit.YEAR)}
158
- </span>
159
- <Button flat={true} round={true} disabled={minDate && DateTools.dateOf(selectedMonth).isBefore(minDate)} onClick={() => {
160
- this.setState({selectedMonth: DateTools.dateOf(selectedMonth).subtract(1, DateTools.TimeUnit.MONTH)})
161
- }}>
162
- <MaterialIcon icon={'chevron_left'}/>
163
- </Button>
164
- <Button flat={true} round={true} onClick={() => {
165
- this.setState({selectedMonth: DateTools.dateOf(selectedMonth).add(1, DateTools.TimeUnit.MONTH)})
166
- }}>
167
- <MaterialIcon icon={'chevron_right'}/>
168
- </Button>
169
- </div>
170
- <CalendarMonthView monthOf={selectedMonth}
171
- dayOfWeekToString={dayOfWeekToString}
172
- dayRenderer={(date) => <DayRenderer
173
- day={DateTools.dateOf(date)}
174
- selected={value}
175
- minDate={minDate}
176
- onClick={value => {
177
- this.onChange(value)
178
- this.setState({focused: false, text: formatter(value)});
179
- }}
180
- />}/>
181
- </div>
213
+ {popup}
182
214
  </div>
183
215
  };
184
216
 
package/src/DateTools.ts CHANGED
@@ -3,7 +3,7 @@ export const resetTime = (date: Date) => {
3
3
  return date
4
4
  };
5
5
  export const timeOf = (date: Date) => date.getTime();
6
- export const equals = (a: Date, b: Date) => a && b && timeOf(a) === timeOf(b);
6
+ export const equals = (a: Date, b: Date) => (a === b) || (a && b && timeOf(a) === timeOf(b));
7
7
  export const isBefore = (a: Date, b: Date) => a && b && timeOf(a) < timeOf(b);
8
8
  export const isAfter = (a: Date, b: Date) => a && b && timeOf(a) > timeOf(b);
9
9
  export const max = (a: Date, b: Date) => {
@@ -18,6 +18,9 @@
18
18
  opacity: 1;
19
19
  visibility: visible;
20
20
  }
21
+ .FilteredList.portal {
22
+ transition: opacity 0.2s ease-out;
23
+ }
21
24
  .FilteredList.inline {
22
25
  max-height: 225px;
23
26
  margin-top: 5px;
@@ -22,6 +22,10 @@
22
22
  }
23
23
  }
24
24
 
25
+ &.portal {
26
+ transition: opacity 0.2s ease-out;
27
+ }
28
+
25
29
  &.inline {
26
30
  max-height: 225px;
27
31
  margin-top: 5px;
package/src/Scrollable.js CHANGED
@@ -2,7 +2,21 @@ import ReactConstants from "./../ReactConstants"; import {clientHeight as __clie
2
2
  import {toConsumableArray as __toConsumableArray} from "./../_virtual/_rollupPluginBabelHelpers"; import {extends as __extends} from "./../_virtual/_rollupPluginBabelHelpers"; import {inherits as __inherits} from "./../_virtual/_rollupPluginBabelHelpers"; import './Scrollable.css'; import ReactCreateElement from './ReactCreateElement';
3
3
  import PropTypes from 'prop-types';
4
4
  import './Scrollable.css'
5
- import {classNames, preventDefault, WINDOW, addEventListener, removeEventListener, setTimeout, clearTimeout, setInterval, clearInterval, createRef, orNoop, NOOP} from "./Tools";
5
+ import {
6
+ classNames,
7
+ preventDefault,
8
+ WINDOW,
9
+ addEventListener,
10
+ removeEventListener,
11
+ setTimeout,
12
+ clearTimeout,
13
+ setInterval,
14
+ clearInterval,
15
+ createRef,
16
+ orNoop,
17
+ NOOP,
18
+ ref
19
+ } from "./Tools";
6
20
  import {propsGetter, stateGS, PureComponent, render, componentDidMount, componentDidUpdate, componentWillUnmount} from "./ReactConstants";
7
21
 
8
22
  export const SCROLLBAR_MODE_HIDDEN = 'hidden';
@@ -36,7 +50,6 @@ class Scrollable extends PureComponent {
36
50
  const status = stateGS(that);
37
51
  const statusH = stateGS(that);
38
52
 
39
- const containerRef = createRef();
40
53
  const viewportRef = createRef();
41
54
  const scrollbarRef = createRef();
42
55
  const horizontalScrollbarRef = createRef();
@@ -63,7 +76,7 @@ class Scrollable extends PureComponent {
63
76
  const viewport = viewportRef();
64
77
  const scrollbar = scrollbarRef();
65
78
  const scrollbarH = horizontalScrollbarRef();
66
- const container = containerRef();
79
+ const container = that.el;
67
80
  const thumb = thumbRef();
68
81
  const thumbH = horizontalThumbRef();
69
82
 
@@ -340,13 +353,13 @@ class Scrollable extends PureComponent {
340
353
  };
341
354
  that.getScroll = () => __scrollTop(viewportRef());
342
355
  that.getScrollHeight = () => scrollHeightOf(viewportRef());
343
- that.getHeight = () => __clientHeight(containerRef());
356
+ that.getHeight = () => that.el.clientHeight;
344
357
 
345
358
  that[ReactConstants[3]] = () => {
346
359
  const _props = props();
347
360
  const {className, children} = _props;
348
361
  return (
349
- <div className={classNames('Scrollable', className, status() || WITH_SCROLL, statusH() + '-horizontal')} style={styleOf(_props)} ref={containerRef}>
362
+ <div className={classNames('Scrollable', className, status() || WITH_SCROLL, statusH() + '-horizontal')} style={styleOf(_props)} ref={ref('el', this)}>
350
363
  <div className="viewport" ref={viewportRef}>
351
364
  {children}
352
365
  </div>
package/src/Table.css CHANGED
@@ -92,3 +92,9 @@
92
92
  padding: 0px;
93
93
  background-color: rgb(240, 240, 240);
94
94
  }
95
+ .Table .editable > .AutocompleteSelect {
96
+ min-width: unset;
97
+ }
98
+ .Table .editable > .AutocompleteSelect > .selected > .DummyChild {
99
+ margin: 0;
100
+ }
package/src/Table.scss CHANGED
@@ -116,6 +116,14 @@
116
116
  background-color: rgb(240, 240, 240);
117
117
  }
118
118
  }
119
+
120
+ > .AutocompleteSelect{
121
+ min-width: unset;
122
+
123
+ > .selected > .DummyChild {
124
+ margin: 0;
125
+ }
126
+ }
119
127
  }
120
128
 
121
129
  }
package/src/Table.tsx CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  createRef,
16
16
  setInterval,
17
17
  createAccessor,
18
- UNDEFINED
18
+ UNDEFINED, DOCUMENT
19
19
  } from "./Tools";
20
20
  import MaterialIcon from "./MaterialIcon";
21
21
  import {componentDidUpdate, componentWillUnmount, render, PureComponent, propsGetter, componentDidMount, stateGSs, stateGS} from "./ReactConstants";
@@ -61,6 +61,7 @@ export interface TableColumn<T> {
61
61
  onClick?: (e: SyntheticEvent, startEditing: () => void, item: T, field: keyof T, row: number, column: number) => void,
62
62
  comparator?: Comparator,
63
63
  header?: string | ReactElement,
64
+ headerColspan?: number,
64
65
  sortable?: boolean,
65
66
  displayEditor?: boolean,
66
67
  formatter?: Formatter<T, T[keyof T]>,
@@ -234,8 +235,11 @@ class Table<T> extends Component<TableProps<T>, TableState<T>> {
234
235
  <tr ref={headers}>
235
236
  {columns.filter(it => !!it).map((column, i) => {
236
237
  const sortable = column.sortable || column.sortable == null;
238
+ if (column.headerColspan === 0)
239
+ return null
240
+
237
241
  return (
238
- <th key={i} onClick={e => sortable && sort(e, column.field, comparatorGetter(column))}>
242
+ <th key={i} colSpan={column.headerColspan} onClick={e => sortable && sort(e, column.field, comparatorGetter(column))}>
239
243
  <div className={classNames('hidden', sortable && 'sortable', sortBy === column.field && 'active')}>
240
244
  {column.header}
241
245
  {column.header && sortBy === column.field && sortOrder === SORT_ASC && (<MaterialIcon icon={'keyboard_arrow_up'}/>)}
@@ -296,6 +300,7 @@ export interface TableColumnSelect<T> extends TableColumn<T> {
296
300
  editorSelectedComponent?: any,
297
301
  editorChildComponent?: any,
298
302
  prefilter?: any,
303
+ filter?: (value: any, filterValue: string) => boolean,
299
304
  }
300
305
 
301
306
  class Row<T> extends PureComponent<RowProps<T>> {
@@ -358,7 +363,7 @@ class Row<T> extends PureComponent<RowProps<T>> {
358
363
  data={(column as TableColumnSelect<T>).editorData}
359
364
  focused={true}
360
365
  withArrow={false}
361
- withFilter={false}
366
+ withFilter={true}
362
367
  selectedMode={'inline'}
363
368
  selectedComponent={(column as TableColumnSelect<T>).editorSelectedComponent}
364
369
  mode={(column as TableColumnSelect<T>).multiSelect ? MODE_MULTIPLE_MINI : MODE_DEFAULT}
@@ -371,6 +376,8 @@ class Row<T> extends PureComponent<RowProps<T>> {
371
376
  childComponent={(column as TableColumnSelect<T>).editorChildComponent}
372
377
  onCancel={cancelEditing}
373
378
  prefilter={(column as TableColumnSelect<T>).prefilter}
379
+ filter={(column as TableColumnSelect<T>).filter}
380
+ listPortal={DOCUMENT.body}
374
381
  />
375
382
  )}
376
383
  {displayEditor && column.editor === editorSwitch && (