superdesk-ui-framework 3.1.18 → 3.1.20

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.
@@ -24,7 +24,7 @@
24
24
  padding: 1rem;
25
25
  position: relative;
26
26
  display: grid;
27
- grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
27
+ grid-template-columns: repeat(3, minmax(9rem, 1fr));
28
28
  }
29
29
 
30
30
  .select-grid__item {
@@ -76,4 +76,4 @@
76
76
  margin-block-start: 0;
77
77
  }
78
78
  }
79
- }
79
+ }
@@ -52,25 +52,29 @@ export class IconPicker extends React.PureComponent<IProps, IState> {
52
52
  this.props.onChange(item.value);
53
53
  }
54
54
 
55
- triggerTemplate = (props: any) => <Button
56
- icon={this.props.value}
57
- text={this.props.value}
58
- onClick={(e) => { props.onClick(e); }}
59
- iconOnly={true} />
55
+ triggerTemplate = (props: {onClick: (e: React.SyntheticEvent) => void; }) => (
56
+ <Button
57
+ icon={this.props.value}
58
+ text={this.props.value}
59
+ onClick={(e) => { props.onClick(e); }}
60
+ iconOnly={true}
61
+ />
62
+ )
60
63
 
61
- itemTemplate = ({ item }: { item: IItem | null }) => item ?
62
- (<>
64
+ itemTemplate = ({ item }: { item: IItem | null }) => item && (
65
+ <>
63
66
  <Icon name={item.value} />
64
67
  <span className="sd-text--normal sd-padding-t--1">
65
68
  {item.label}
66
69
  </span>
67
- </>) : null
70
+ </>
71
+ )
68
72
 
69
73
  render() {
70
74
  return (
71
75
  <SelectGrid
72
- label={this.props.label || "Icon"}
73
- filterPlaceholder={this.props.filterPlaceholder || "Search..."}
76
+ label={this.props.label ?? "Icon"}
77
+ filterPlaceholder={this.props.filterPlaceholder ?? "Search..."}
74
78
  getItems={this.getItems}
75
79
  onChange={this.onChange}
76
80
  itemTemplate={this.itemTemplate}
@@ -19,7 +19,7 @@ interface IProps {
19
19
  getItems(searchString: string | null): Promise<Array<IItem>>;
20
20
  onChange(value: IItem): void;
21
21
  itemTemplate: React.ComponentType<{ item: IItem | null }>;
22
- triggerTemplate: React.ComponentType<any>;
22
+ triggerTemplate: React.ComponentType<{onClick: (e: React.SyntheticEvent) => void; }>;
23
23
  label: string;
24
24
  filterPlaceholder?: string;
25
25
  }
@@ -27,9 +27,12 @@ interface IProps {
27
27
  interface IState {
28
28
  items: Array<IItem>;
29
29
  loading: boolean;
30
- isOpen: boolean;
31
30
  }
32
31
 
32
+ const GRID_COLS = 3;
33
+ const GRID_ROWS = 5;
34
+ const PAGE_SIZE = GRID_COLS * GRID_ROWS;
35
+
33
36
  export class SelectGrid extends React.PureComponent<IProps, IState> {
34
37
  htmlId = nextId();
35
38
  buttonContainer: React.RefObject<HTMLDivElement>;
@@ -40,7 +43,7 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
40
43
  constructor(props: IProps) {
41
44
  super(props);
42
45
 
43
- this.state = { items: [], loading: true, isOpen: false };
46
+ this.state = { items: [], loading: true };
44
47
 
45
48
  this.buttonContainer = React.createRef();
46
49
  this.overlayPanel = React.createRef();
@@ -58,32 +61,16 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
58
61
  document.removeEventListener('keydown', this.handleKeydown);
59
62
  }
60
63
 
61
- togglePopup = (event?: React.SyntheticEvent) => {
64
+ mountPopup = (event?: React.SyntheticEvent) => {
62
65
  if (!event) {
63
- // @ts-ignore
64
- this.overlayPanel.current.hide();
66
+ this.overlayPanel.current?.hide();
65
67
  } else {
66
- // @ts-ignore
67
- this.overlayPanel.current.toggle(event);
68
+ this.overlayPanel.current?.toggle(event);
68
69
  }
69
70
 
70
- setTimeout(() => {
71
- // Now that the popup has (dis)appeared handle items and events
72
-
73
- if (this.state.isOpen) {
74
- document.removeEventListener('keydown', this.handleKeydown);
75
- // @ts-ignore
76
- this.buttonContainer.current.querySelector('button')?.focus();
77
- } else {
78
- document.addEventListener('keydown', this.handleKeydown);
79
- this.loadItems();
80
- // @ts-ignore
81
- this.searchInput.current.focus();
82
- }
83
-
84
- this.setState({ isOpen: !this.state.isOpen });
85
- });
86
-
71
+ document.addEventListener('keydown', this.handleKeydown);
72
+ setTimeout(() => { this.searchInput.current?.focus(); });
73
+ this.loadItems();
87
74
  }
88
75
 
89
76
  search = (event: React.ChangeEvent<HTMLInputElement>) => {
@@ -98,9 +85,18 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
98
85
  });
99
86
  }
100
87
 
88
+ hidePopupAndRefocus = () => {
89
+ document.removeEventListener('keydown', this.handleKeydown);
90
+ this.overlayPanel.current?.hide();
91
+ this.buttonContainer.current?.querySelector('button')?.focus();
92
+ }
93
+
101
94
  select = (item: IItem) => {
102
95
  this.props.onChange(item);
103
- this.togglePopup();
96
+ this.hidePopupAndRefocus();
97
+
98
+ // trigger component update
99
+ this.forceUpdate();
104
100
  }
105
101
 
106
102
  getItemElement = (index: number): HTMLDivElement | null | undefined => {
@@ -122,7 +118,8 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
122
118
  if (event.code === "Escape") {
123
119
  event.preventDefault();
124
120
  event.stopPropagation();
125
- this.togglePopup();
121
+
122
+ this.hidePopupAndRefocus();
126
123
  } else if (activeElement === this.searchInput?.current) {
127
124
  if (event.code === "ArrowDown") {
128
125
  event.preventDefault();
@@ -131,13 +128,11 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
131
128
  event.preventDefault();
132
129
  this.select(this.state.items[0]);
133
130
  }
134
- // @ts-ignore
135
- } else if (document.activeElement.getAttribute('data-item-index') && navKeys.includes(event.code)) {
136
- // @ts-ignore
137
- let itemIndex = parseInt(activeElement.getAttribute('data-item-index'), 10);
131
+ } else if (document.activeElement?.getAttribute('data-item-index') && navKeys.includes(event.code)) {
132
+ let itemIndex = parseInt(activeElement?.getAttribute('data-item-index') as string, 10);
133
+
134
+ event.preventDefault(); // Prevent scrolling, etc.
138
135
 
139
- // Prevent default behaviour, such as scrolling
140
- event.preventDefault();
141
136
  if (event.code === "Enter") {
142
137
  this.select(this.state.items[itemIndex]);
143
138
  return;
@@ -146,17 +141,18 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
146
141
  } else if (event.code === "ArrowLeft") {
147
142
  itemIndex -= 1;
148
143
  } else if (event.code === "ArrowDown") {
149
- itemIndex += 4;
144
+ itemIndex += GRID_COLS;
150
145
  } else if (event.code === "ArrowUp") {
151
- if (itemIndex === 0) {
146
+ if (itemIndex < GRID_COLS) {
152
147
  this.searchInput?.current?.focus();
153
148
  return;
154
149
  }
155
- itemIndex -= 4;
150
+
151
+ itemIndex -= GRID_COLS;
156
152
  } else if (event.code === "PageDown") {
157
- itemIndex += 16;
153
+ itemIndex += PAGE_SIZE;
158
154
  } else if (event.code === "PageUp") {
159
- itemIndex -= 16;
155
+ itemIndex -= PAGE_SIZE;
160
156
  }
161
157
 
162
158
  if (itemIndex < 0) {
@@ -179,14 +175,18 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
179
175
  className="sd-input sd-input--grid-select"
180
176
  ref={this.buttonContainer}
181
177
  aria-label={this.props.label}
178
+ key={this.props.label}
182
179
  >
183
180
  <label className="sd-input__label">
184
181
  {this.props.label}
185
182
  </label>
186
- <TriggerTemplate onClick={this.togglePopup} />
187
-
183
+ <TriggerTemplate onClick={this.mountPopup} />
188
184
  </div>
189
185
  <OverlayPanel
186
+ onHide={() => {
187
+ document.removeEventListener('keydown', this.handleKeydown);
188
+ this.buttonContainer.current?.querySelector('button')?.focus();
189
+ }}
190
190
  ref={this.overlayPanel}
191
191
  dismissable={true}
192
192
  className="select-grid__overlay-panel"
@@ -205,12 +205,8 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
205
205
  />
206
206
  </div>
207
207
  </div>
208
- <div
209
- className="select-grid__body"
210
- ref={this.gridContainer}
211
-
212
- >
213
- <Loader overlay={this.state.loading} />
208
+ <div className="select-grid__body" ref={this.gridContainer}>
209
+ {this.state.loading && <Loader overlay={this.state.loading} />}
214
210
  {this.state.items.map((item, index) => (
215
211
  <div
216
212
  key={this.htmlId + item.label}
@@ -221,7 +217,7 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
221
217
  aria-label={item.name}
222
218
  onClick={() => this.select(item)}
223
219
  >
224
- <ItemTemplate item={item} />
220
+ <ItemTemplate key={item.value} item={item} />
225
221
  </div>
226
222
  ))}
227
223
  </div>
@@ -64837,36 +64837,25 @@ var React = __importStar(__webpack_require__(0));
64837
64837
  var react_id_generator_1 = __importDefault(__webpack_require__(11));
64838
64838
  var overlaypanel_1 = __webpack_require__(681);
64839
64839
  var Loader_1 = __webpack_require__(107);
64840
+ var GRID_COLS = 3;
64841
+ var GRID_ROWS = 5;
64842
+ var PAGE_SIZE = GRID_COLS * GRID_ROWS;
64840
64843
  var SelectGrid = /** @class */ (function (_super) {
64841
64844
  __extends(SelectGrid, _super);
64842
64845
  function SelectGrid(props) {
64843
64846
  var _this = _super.call(this, props) || this;
64844
64847
  _this.htmlId = (0, react_id_generator_1.default)();
64845
- _this.togglePopup = function (event) {
64848
+ _this.mountPopup = function (event) {
64849
+ var _a, _b;
64846
64850
  if (!event) {
64847
- // @ts-ignore
64848
- _this.overlayPanel.current.hide();
64851
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
64849
64852
  }
64850
64853
  else {
64851
- // @ts-ignore
64852
- _this.overlayPanel.current.toggle(event);
64854
+ (_b = _this.overlayPanel.current) === null || _b === void 0 ? void 0 : _b.toggle(event);
64853
64855
  }
64854
- setTimeout(function () {
64855
- // Now that the popup has (dis)appeared handle items and events
64856
- var _a;
64857
- if (_this.state.isOpen) {
64858
- document.removeEventListener('keydown', _this.handleKeydown);
64859
- // @ts-ignore
64860
- (_a = _this.buttonContainer.current.querySelector('button')) === null || _a === void 0 ? void 0 : _a.focus();
64861
- }
64862
- else {
64863
- document.addEventListener('keydown', _this.handleKeydown);
64864
- _this.loadItems();
64865
- // @ts-ignore
64866
- _this.searchInput.current.focus();
64867
- }
64868
- _this.setState({ isOpen: !_this.state.isOpen });
64869
- });
64856
+ document.addEventListener('keydown', _this.handleKeydown);
64857
+ setTimeout(function () { var _a; (_a = _this.searchInput.current) === null || _a === void 0 ? void 0 : _a.focus(); });
64858
+ _this.loadItems();
64870
64859
  };
64871
64860
  _this.search = function (event) {
64872
64861
  var searchString = event.target.value.toLowerCase();
@@ -64879,16 +64868,24 @@ var SelectGrid = /** @class */ (function (_super) {
64879
64868
  _this.setState({ items: items, loading: false });
64880
64869
  });
64881
64870
  };
64871
+ _this.hidePopupAndRefocus = function () {
64872
+ var _a, _b, _c;
64873
+ document.removeEventListener('keydown', _this.handleKeydown);
64874
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
64875
+ (_c = (_b = _this.buttonContainer.current) === null || _b === void 0 ? void 0 : _b.querySelector('button')) === null || _c === void 0 ? void 0 : _c.focus();
64876
+ };
64882
64877
  _this.select = function (item) {
64883
64878
  _this.props.onChange(item);
64884
- _this.togglePopup();
64879
+ _this.hidePopupAndRefocus();
64880
+ // trigger component update
64881
+ _this.forceUpdate();
64885
64882
  };
64886
64883
  _this.getItemElement = function (index) {
64887
64884
  var _a;
64888
64885
  return (_a = _this.gridContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-item-index=\"".concat(index, "\"]"));
64889
64886
  };
64890
64887
  _this.handleKeydown = function (event) {
64891
- var _a, _b, _c, _d, _e;
64888
+ var _a, _b, _c, _d, _e, _f;
64892
64889
  var navKeys = [
64893
64890
  "Enter",
64894
64891
  "ArrowRight",
@@ -64902,7 +64899,7 @@ var SelectGrid = /** @class */ (function (_super) {
64902
64899
  if (event.code === "Escape") {
64903
64900
  event.preventDefault();
64904
64901
  event.stopPropagation();
64905
- _this.togglePopup();
64902
+ _this.hidePopupAndRefocus();
64906
64903
  }
64907
64904
  else if (activeElement === ((_a = _this.searchInput) === null || _a === void 0 ? void 0 : _a.current)) {
64908
64905
  if (event.code === "ArrowDown") {
@@ -64913,13 +64910,10 @@ var SelectGrid = /** @class */ (function (_super) {
64913
64910
  event.preventDefault();
64914
64911
  _this.select(_this.state.items[0]);
64915
64912
  }
64916
- // @ts-ignore
64917
64913
  }
64918
- else if (document.activeElement.getAttribute('data-item-index') && navKeys.includes(event.code)) {
64919
- // @ts-ignore
64920
- var itemIndex = parseInt(activeElement.getAttribute('data-item-index'), 10);
64921
- // Prevent default behaviour, such as scrolling
64922
- event.preventDefault();
64914
+ else if (((_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.getAttribute('data-item-index')) && navKeys.includes(event.code)) {
64915
+ var itemIndex = parseInt(activeElement === null || activeElement === void 0 ? void 0 : activeElement.getAttribute('data-item-index'), 10);
64916
+ event.preventDefault(); // Prevent scrolling, etc.
64923
64917
  if (event.code === "Enter") {
64924
64918
  _this.select(_this.state.items[itemIndex]);
64925
64919
  return;
@@ -64931,20 +64925,20 @@ var SelectGrid = /** @class */ (function (_super) {
64931
64925
  itemIndex -= 1;
64932
64926
  }
64933
64927
  else if (event.code === "ArrowDown") {
64934
- itemIndex += 4;
64928
+ itemIndex += GRID_COLS;
64935
64929
  }
64936
64930
  else if (event.code === "ArrowUp") {
64937
- if (itemIndex === 0) {
64938
- (_d = (_c = _this.searchInput) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.focus();
64931
+ if (itemIndex < GRID_COLS) {
64932
+ (_e = (_d = _this.searchInput) === null || _d === void 0 ? void 0 : _d.current) === null || _e === void 0 ? void 0 : _e.focus();
64939
64933
  return;
64940
64934
  }
64941
- itemIndex -= 4;
64935
+ itemIndex -= GRID_COLS;
64942
64936
  }
64943
64937
  else if (event.code === "PageDown") {
64944
- itemIndex += 16;
64938
+ itemIndex += PAGE_SIZE;
64945
64939
  }
64946
64940
  else if (event.code === "PageUp") {
64947
- itemIndex -= 16;
64941
+ itemIndex -= PAGE_SIZE;
64948
64942
  }
64949
64943
  if (itemIndex < 0) {
64950
64944
  itemIndex = 0;
@@ -64952,10 +64946,10 @@ var SelectGrid = /** @class */ (function (_super) {
64952
64946
  else if (itemIndex >= _this.state.items.length) {
64953
64947
  itemIndex = _this.state.items.length - 1;
64954
64948
  }
64955
- (_e = _this.getItemElement(itemIndex)) === null || _e === void 0 ? void 0 : _e.focus();
64949
+ (_f = _this.getItemElement(itemIndex)) === null || _f === void 0 ? void 0 : _f.focus();
64956
64950
  }
64957
64951
  };
64958
- _this.state = { items: [], loading: true, isOpen: false };
64952
+ _this.state = { items: [], loading: true };
64959
64953
  _this.buttonContainer = React.createRef();
64960
64954
  _this.overlayPanel = React.createRef();
64961
64955
  _this.searchInput = React.createRef();
@@ -64976,19 +64970,23 @@ var SelectGrid = /** @class */ (function (_super) {
64976
64970
  var ItemTemplate = this.props.itemTemplate;
64977
64971
  var TriggerTemplate = this.props.triggerTemplate;
64978
64972
  return (React.createElement(React.Fragment, null,
64979
- React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label },
64973
+ React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label, key: this.props.label },
64980
64974
  React.createElement("label", { className: "sd-input__label" }, this.props.label),
64981
- React.createElement(TriggerTemplate, { onClick: this.togglePopup })),
64982
- React.createElement(overlaypanel_1.OverlayPanel, { ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
64975
+ React.createElement(TriggerTemplate, { onClick: this.mountPopup })),
64976
+ React.createElement(overlaypanel_1.OverlayPanel, { onHide: function () {
64977
+ var _a, _b;
64978
+ document.removeEventListener('keydown', _this.handleKeydown);
64979
+ (_b = (_a = _this.buttonContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector('button')) === null || _b === void 0 ? void 0 : _b.focus();
64980
+ }, ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
64983
64981
  React.createElement("div", { className: "select-grid__panel" },
64984
64982
  React.createElement("div", { className: "select-grid__header" },
64985
64983
  React.createElement("div", { className: "sd-searchbar sd-searchbar--boxed" },
64986
64984
  React.createElement("label", { className: "sd-searchbar__icon" }),
64987
64985
  React.createElement("input", { className: "sd-searchbar__input", placeholder: this.props.filterPlaceholder || 'Search...', type: "text", onChange: this.search, ref: this.searchInput }))),
64988
64986
  React.createElement("div", { className: "select-grid__body", ref: this.gridContainer },
64989
- React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
64987
+ this.state.loading && React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
64990
64988
  this.state.items.map(function (item, index) { return (React.createElement("div", { key: _this.htmlId + item.label, "data-item-index": index, className: "flex-grid__item select-grid__item sd-padding-y--3", tabIndex: 0, role: "button", "aria-label": item.name, onClick: function () { return _this.select(item); } },
64991
- React.createElement(ItemTemplate, { item: item }))); }))))));
64989
+ React.createElement(ItemTemplate, { key: item.value, item: item }))); }))))));
64992
64990
  };
64993
64991
  return SelectGrid;
64994
64992
  }(React.PureComponent));
@@ -147878,13 +147876,12 @@ var IconPicker = /** @class */ (function (_super) {
147878
147876
  _this.onChange = function (item) {
147879
147877
  _this.props.onChange(item.value);
147880
147878
  };
147881
- _this.triggerTemplate = function (props) { return React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true }); };
147879
+ _this.triggerTemplate = function (props) { return (React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true })); };
147882
147880
  _this.itemTemplate = function (_a) {
147883
147881
  var item = _a.item;
147884
- return item ?
147885
- (React.createElement(React.Fragment, null,
147886
- React.createElement(Icon_1.Icon, { name: item.value }),
147887
- React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label))) : null;
147882
+ return item && (React.createElement(React.Fragment, null,
147883
+ React.createElement(Icon_1.Icon, { name: item.value }),
147884
+ React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label)));
147888
147885
  };
147889
147886
  _this.state = { icons: [] };
147890
147887
  return _this;
@@ -147897,7 +147894,8 @@ var IconPicker = /** @class */ (function (_super) {
147897
147894
  });
147898
147895
  };
147899
147896
  IconPicker.prototype.render = function () {
147900
- return (React.createElement(SelectGrid_1.SelectGrid, { label: this.props.label || "Icon", filterPlaceholder: this.props.filterPlaceholder || "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
147897
+ var _a, _b;
147898
+ return (React.createElement(SelectGrid_1.SelectGrid, { label: (_a = this.props.label) !== null && _a !== void 0 ? _a : "Icon", filterPlaceholder: (_b = this.props.filterPlaceholder) !== null && _b !== void 0 ? _b : "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
147901
147899
  };
147902
147900
  return IconPicker;
147903
147901
  }(React.PureComponent));
@@ -185271,7 +185269,7 @@ exports.ThreePaneLayoutPattern = ThreePaneLayoutPattern;
185271
185269
  /* 935 */
185272
185270
  /***/ (function(module, exports) {
185273
185271
 
185274
- module.exports = {"name":"superdesk-ui-framework","version":"3.1.18","license":"AGPL-3.0","repository":{"type":"git","url":"https://github.com/superdesk/superdesk-ui-framework.git"},"main":"dist/superdesk-ui.bundle.js","types":"react/index.d.ts","contributors":["Nemanja Pavlovic","Vladimir Stefanovic","Darko Tomic","Aleksandar Jelicic","Tomas Kikutis","Dragana Zivkovic"],"scripts":{"start":"webpack-dev-server --config tasks/webpack.dev.js","server":"webpack --watch --config tasks/webpack.prod.js && tsc-watch","build":"webpack --config tasks/webpack.prod.js && tsc","build-ui":"webpack && tsc && npm run lint","playground-lint":"tsc -p examples/pages/playgrounds/react-playgrounds --noEmit","lint":"eslint --parser=@typescript-eslint/parser app && tslint -c tslint.json 'app-typescript/**/*.{ts,tsx}' && npm run playground-lint","lint-fix":"tsc -p tsconfig.json --noEmit && tslint --fix -c tslint.json 'app-typescript/**/*.{ts,tsx}'","prepublishOnly":"npm run build","unit-test":"mocha","debug-unit-tests":"mocha --inspect-brk"},"devDependencies":{"@types/assert":"^1.5.6","@types/chart.js":"^2.9.24","@types/classnames":"^2.2.9","@types/enzyme":"^3.10.12","@types/lodash":"^4.14.161","@types/mocha":"^9.1.1","@types/react":"16.8.23","@types/react-beautiful-dnd":"^13.1.2","@types/react-dom":"16.8.0","@types/react-router-dom":"^5.1.2","@types/react-scrollspy":"^3.3.5","@typescript-eslint/parser":"^5.58.0","angular":"^1.7.9","angular-animate":"^1.7.9","angular-route":"^1.7.9","babel-core":"^6.26.0","babel-loader":"^7.1.2","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-es2015":"^6.24.1","babel-preset-react":"^6.24.1","classnames":"^2.2.5","clean-webpack-plugin":"^1.0.0","code-prettify":"^0.1.0","copy-webpack-plugin":"^4.6.0","css-loader":"^2.1.1","eslint":"^4.6.1","eslint-loader":"^1.9.0","eslint-plugin-angular":"^3.1.1","eslint-plugin-react":"^7.3.0","extract-text-webpack-plugin":"^3.0.2","file-loader":"^0.11.2","html-loader":"^0.5.1","html-webpack-plugin":"^2.30.1","jquery":"^3.1.1","jquery-ui":"^1.12.1","jsdom":"20.0.3","jsdom-global":"3.0.2","lodash":"4.17.21","mocha":"^8.4.0","node-sass":"6.0","prismjs":"^1.28.0","prop-types":"^15.6.0","react":"16.8.6","react-dom":"16.8.6","react-redux":"^5.0.6","react-router-dom":"^5.1.2","redux":"^3.7.2","redux-form":"^7.0.4","sass-loader":"^6.0.6","style-loader":"^0.18.2","superdesk-code-style":"^1.1.2","ts-loader":"^6.0.2","ts-node":"^10.9.1","tslint":"^5.18.0","typescript":"4.9.5","url-loader":"^1.1.2","webpack":"^3.5.5","webpack-cli":"3.3.10","webpack-dev-server":"2.11.1","webpack-merge":"^4.2.1"},"dependencies":{"@popperjs/core":"^2.4.0","@superdesk/common":"0.0.28","@superdesk/primereact":"^5.0.2-12","@superdesk/react-resizable-panels":"0.0.39","@types/enzyme-adapter-react-16":"^1.0.6","@types/node":"^14.10.2","chart.js":"^2.9.3","date-fns":"2.7.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.7","moment":"^2.29.3","popper-max-size-modifier":"^0.2.0","popper.js":"1.14.4","primeicons":"2.0.0","react-beautiful-dnd":"^13.0.0","react-id-generator":"^3.0.0","react-scrollspy":"^3.4.3"}}
185272
+ module.exports = {"name":"superdesk-ui-framework","version":"3.1.20","license":"AGPL-3.0","repository":{"type":"git","url":"https://github.com/superdesk/superdesk-ui-framework.git"},"main":"dist/superdesk-ui.bundle.js","types":"react/index.d.ts","contributors":["Nemanja Pavlovic","Vladimir Stefanovic","Darko Tomic","Aleksandar Jelicic","Tomas Kikutis","Dragana Zivkovic"],"scripts":{"start":"webpack-dev-server --config tasks/webpack.dev.js","server":"webpack --watch --config tasks/webpack.prod.js && tsc-watch","build":"webpack --config tasks/webpack.prod.js && tsc","build-ui":"webpack && tsc && npm run lint","playground-lint":"tsc -p examples/pages/playgrounds/react-playgrounds --noEmit","lint":"eslint --parser=@typescript-eslint/parser app && tslint -c tslint.json 'app-typescript/**/*.{ts,tsx}' && npm run playground-lint","lint-fix":"tsc -p tsconfig.json --noEmit && tslint --fix -c tslint.json 'app-typescript/**/*.{ts,tsx}'","prepublishOnly":"npm run build","unit-test":"mocha","debug-unit-tests":"mocha --inspect-brk"},"devDependencies":{"@types/assert":"^1.5.6","@types/chart.js":"^2.9.24","@types/classnames":"^2.2.9","@types/enzyme":"^3.10.12","@types/lodash":"^4.14.161","@types/mocha":"^9.1.1","@types/react":"16.8.23","@types/react-beautiful-dnd":"^13.1.2","@types/react-dom":"16.8.0","@types/react-router-dom":"^5.1.2","@types/react-scrollspy":"^3.3.5","@typescript-eslint/parser":"^5.58.0","angular":"^1.7.9","angular-animate":"^1.7.9","angular-route":"^1.7.9","babel-core":"^6.26.0","babel-loader":"^7.1.2","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-preset-es2015":"^6.24.1","babel-preset-react":"^6.24.1","classnames":"^2.2.5","clean-webpack-plugin":"^1.0.0","code-prettify":"^0.1.0","copy-webpack-plugin":"^4.6.0","css-loader":"^2.1.1","eslint":"^4.6.1","eslint-loader":"^1.9.0","eslint-plugin-angular":"^3.1.1","eslint-plugin-react":"^7.3.0","extract-text-webpack-plugin":"^3.0.2","file-loader":"^0.11.2","html-loader":"^0.5.1","html-webpack-plugin":"^2.30.1","jquery":"^3.1.1","jquery-ui":"^1.12.1","jsdom":"20.0.3","jsdom-global":"3.0.2","lodash":"4.17.21","mocha":"^8.4.0","node-sass":"6.0","prismjs":"^1.28.0","prop-types":"^15.6.0","react":"16.8.6","react-dom":"16.8.6","react-redux":"^5.0.6","react-router-dom":"^5.1.2","redux":"^3.7.2","redux-form":"^7.0.4","sass-loader":"^6.0.6","style-loader":"^0.18.2","superdesk-code-style":"^1.1.2","ts-loader":"^6.0.2","ts-node":"^10.9.1","tslint":"^5.18.0","typescript":"4.9.5","url-loader":"^1.1.2","webpack":"^3.5.5","webpack-cli":"3.3.10","webpack-dev-server":"2.11.1","webpack-merge":"^4.2.1"},"dependencies":{"@popperjs/core":"^2.4.0","@superdesk/common":"0.0.28","@superdesk/primereact":"^5.0.2-12","@superdesk/react-resizable-panels":"0.0.39","@types/enzyme-adapter-react-16":"^1.0.6","@types/node":"^14.10.2","chart.js":"^2.9.3","date-fns":"2.7.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.7","moment":"^2.29.3","popper-max-size-modifier":"^0.2.0","popper.js":"1.14.4","primeicons":"2.0.0","react-beautiful-dnd":"^13.0.0","react-id-generator":"^3.0.0","react-scrollspy":"^3.4.3"}}
185275
185273
 
185276
185274
  /***/ }),
185277
185275
  /* 936 */
@@ -51937,7 +51937,7 @@ label + .sd-radio {
51937
51937
  padding: 1rem;
51938
51938
  position: relative;
51939
51939
  display: grid;
51940
- grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); }
51940
+ grid-template-columns: repeat(3, minmax(9rem, 1fr)); }
51941
51941
 
51942
51942
  .select-grid__item {
51943
51943
  display: flex;
@@ -64341,36 +64341,25 @@ var React = __importStar(__webpack_require__(0));
64341
64341
  var react_id_generator_1 = __importDefault(__webpack_require__(11));
64342
64342
  var overlaypanel_1 = __webpack_require__(681);
64343
64343
  var Loader_1 = __webpack_require__(107);
64344
+ var GRID_COLS = 3;
64345
+ var GRID_ROWS = 5;
64346
+ var PAGE_SIZE = GRID_COLS * GRID_ROWS;
64344
64347
  var SelectGrid = /** @class */ (function (_super) {
64345
64348
  __extends(SelectGrid, _super);
64346
64349
  function SelectGrid(props) {
64347
64350
  var _this = _super.call(this, props) || this;
64348
64351
  _this.htmlId = (0, react_id_generator_1.default)();
64349
- _this.togglePopup = function (event) {
64352
+ _this.mountPopup = function (event) {
64353
+ var _a, _b;
64350
64354
  if (!event) {
64351
- // @ts-ignore
64352
- _this.overlayPanel.current.hide();
64355
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
64353
64356
  }
64354
64357
  else {
64355
- // @ts-ignore
64356
- _this.overlayPanel.current.toggle(event);
64358
+ (_b = _this.overlayPanel.current) === null || _b === void 0 ? void 0 : _b.toggle(event);
64357
64359
  }
64358
- setTimeout(function () {
64359
- // Now that the popup has (dis)appeared handle items and events
64360
- var _a;
64361
- if (_this.state.isOpen) {
64362
- document.removeEventListener('keydown', _this.handleKeydown);
64363
- // @ts-ignore
64364
- (_a = _this.buttonContainer.current.querySelector('button')) === null || _a === void 0 ? void 0 : _a.focus();
64365
- }
64366
- else {
64367
- document.addEventListener('keydown', _this.handleKeydown);
64368
- _this.loadItems();
64369
- // @ts-ignore
64370
- _this.searchInput.current.focus();
64371
- }
64372
- _this.setState({ isOpen: !_this.state.isOpen });
64373
- });
64360
+ document.addEventListener('keydown', _this.handleKeydown);
64361
+ setTimeout(function () { var _a; (_a = _this.searchInput.current) === null || _a === void 0 ? void 0 : _a.focus(); });
64362
+ _this.loadItems();
64374
64363
  };
64375
64364
  _this.search = function (event) {
64376
64365
  var searchString = event.target.value.toLowerCase();
@@ -64383,16 +64372,24 @@ var SelectGrid = /** @class */ (function (_super) {
64383
64372
  _this.setState({ items: items, loading: false });
64384
64373
  });
64385
64374
  };
64375
+ _this.hidePopupAndRefocus = function () {
64376
+ var _a, _b, _c;
64377
+ document.removeEventListener('keydown', _this.handleKeydown);
64378
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
64379
+ (_c = (_b = _this.buttonContainer.current) === null || _b === void 0 ? void 0 : _b.querySelector('button')) === null || _c === void 0 ? void 0 : _c.focus();
64380
+ };
64386
64381
  _this.select = function (item) {
64387
64382
  _this.props.onChange(item);
64388
- _this.togglePopup();
64383
+ _this.hidePopupAndRefocus();
64384
+ // trigger component update
64385
+ _this.forceUpdate();
64389
64386
  };
64390
64387
  _this.getItemElement = function (index) {
64391
64388
  var _a;
64392
64389
  return (_a = _this.gridContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-item-index=\"".concat(index, "\"]"));
64393
64390
  };
64394
64391
  _this.handleKeydown = function (event) {
64395
- var _a, _b, _c, _d, _e;
64392
+ var _a, _b, _c, _d, _e, _f;
64396
64393
  var navKeys = [
64397
64394
  "Enter",
64398
64395
  "ArrowRight",
@@ -64406,7 +64403,7 @@ var SelectGrid = /** @class */ (function (_super) {
64406
64403
  if (event.code === "Escape") {
64407
64404
  event.preventDefault();
64408
64405
  event.stopPropagation();
64409
- _this.togglePopup();
64406
+ _this.hidePopupAndRefocus();
64410
64407
  }
64411
64408
  else if (activeElement === ((_a = _this.searchInput) === null || _a === void 0 ? void 0 : _a.current)) {
64412
64409
  if (event.code === "ArrowDown") {
@@ -64417,13 +64414,10 @@ var SelectGrid = /** @class */ (function (_super) {
64417
64414
  event.preventDefault();
64418
64415
  _this.select(_this.state.items[0]);
64419
64416
  }
64420
- // @ts-ignore
64421
64417
  }
64422
- else if (document.activeElement.getAttribute('data-item-index') && navKeys.includes(event.code)) {
64423
- // @ts-ignore
64424
- var itemIndex = parseInt(activeElement.getAttribute('data-item-index'), 10);
64425
- // Prevent default behaviour, such as scrolling
64426
- event.preventDefault();
64418
+ else if (((_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.getAttribute('data-item-index')) && navKeys.includes(event.code)) {
64419
+ var itemIndex = parseInt(activeElement === null || activeElement === void 0 ? void 0 : activeElement.getAttribute('data-item-index'), 10);
64420
+ event.preventDefault(); // Prevent scrolling, etc.
64427
64421
  if (event.code === "Enter") {
64428
64422
  _this.select(_this.state.items[itemIndex]);
64429
64423
  return;
@@ -64435,20 +64429,20 @@ var SelectGrid = /** @class */ (function (_super) {
64435
64429
  itemIndex -= 1;
64436
64430
  }
64437
64431
  else if (event.code === "ArrowDown") {
64438
- itemIndex += 4;
64432
+ itemIndex += GRID_COLS;
64439
64433
  }
64440
64434
  else if (event.code === "ArrowUp") {
64441
- if (itemIndex === 0) {
64442
- (_d = (_c = _this.searchInput) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.focus();
64435
+ if (itemIndex < GRID_COLS) {
64436
+ (_e = (_d = _this.searchInput) === null || _d === void 0 ? void 0 : _d.current) === null || _e === void 0 ? void 0 : _e.focus();
64443
64437
  return;
64444
64438
  }
64445
- itemIndex -= 4;
64439
+ itemIndex -= GRID_COLS;
64446
64440
  }
64447
64441
  else if (event.code === "PageDown") {
64448
- itemIndex += 16;
64442
+ itemIndex += PAGE_SIZE;
64449
64443
  }
64450
64444
  else if (event.code === "PageUp") {
64451
- itemIndex -= 16;
64445
+ itemIndex -= PAGE_SIZE;
64452
64446
  }
64453
64447
  if (itemIndex < 0) {
64454
64448
  itemIndex = 0;
@@ -64456,10 +64450,10 @@ var SelectGrid = /** @class */ (function (_super) {
64456
64450
  else if (itemIndex >= _this.state.items.length) {
64457
64451
  itemIndex = _this.state.items.length - 1;
64458
64452
  }
64459
- (_e = _this.getItemElement(itemIndex)) === null || _e === void 0 ? void 0 : _e.focus();
64453
+ (_f = _this.getItemElement(itemIndex)) === null || _f === void 0 ? void 0 : _f.focus();
64460
64454
  }
64461
64455
  };
64462
- _this.state = { items: [], loading: true, isOpen: false };
64456
+ _this.state = { items: [], loading: true };
64463
64457
  _this.buttonContainer = React.createRef();
64464
64458
  _this.overlayPanel = React.createRef();
64465
64459
  _this.searchInput = React.createRef();
@@ -64480,19 +64474,23 @@ var SelectGrid = /** @class */ (function (_super) {
64480
64474
  var ItemTemplate = this.props.itemTemplate;
64481
64475
  var TriggerTemplate = this.props.triggerTemplate;
64482
64476
  return (React.createElement(React.Fragment, null,
64483
- React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label },
64477
+ React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label, key: this.props.label },
64484
64478
  React.createElement("label", { className: "sd-input__label" }, this.props.label),
64485
- React.createElement(TriggerTemplate, { onClick: this.togglePopup })),
64486
- React.createElement(overlaypanel_1.OverlayPanel, { ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
64479
+ React.createElement(TriggerTemplate, { onClick: this.mountPopup })),
64480
+ React.createElement(overlaypanel_1.OverlayPanel, { onHide: function () {
64481
+ var _a, _b;
64482
+ document.removeEventListener('keydown', _this.handleKeydown);
64483
+ (_b = (_a = _this.buttonContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector('button')) === null || _b === void 0 ? void 0 : _b.focus();
64484
+ }, ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
64487
64485
  React.createElement("div", { className: "select-grid__panel" },
64488
64486
  React.createElement("div", { className: "select-grid__header" },
64489
64487
  React.createElement("div", { className: "sd-searchbar sd-searchbar--boxed" },
64490
64488
  React.createElement("label", { className: "sd-searchbar__icon" }),
64491
64489
  React.createElement("input", { className: "sd-searchbar__input", placeholder: this.props.filterPlaceholder || 'Search...', type: "text", onChange: this.search, ref: this.searchInput }))),
64492
64490
  React.createElement("div", { className: "select-grid__body", ref: this.gridContainer },
64493
- React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
64491
+ this.state.loading && React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
64494
64492
  this.state.items.map(function (item, index) { return (React.createElement("div", { key: _this.htmlId + item.label, "data-item-index": index, className: "flex-grid__item select-grid__item sd-padding-y--3", tabIndex: 0, role: "button", "aria-label": item.name, onClick: function () { return _this.select(item); } },
64495
- React.createElement(ItemTemplate, { item: item }))); }))))));
64493
+ React.createElement(ItemTemplate, { key: item.value, item: item }))); }))))));
64496
64494
  };
64497
64495
  return SelectGrid;
64498
64496
  }(React.PureComponent));
@@ -146999,13 +146997,12 @@ var IconPicker = /** @class */ (function (_super) {
146999
146997
  _this.onChange = function (item) {
147000
146998
  _this.props.onChange(item.value);
147001
146999
  };
147002
- _this.triggerTemplate = function (props) { return React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true }); };
147000
+ _this.triggerTemplate = function (props) { return (React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true })); };
147003
147001
  _this.itemTemplate = function (_a) {
147004
147002
  var item = _a.item;
147005
- return item ?
147006
- (React.createElement(React.Fragment, null,
147007
- React.createElement(Icon_1.Icon, { name: item.value }),
147008
- React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label))) : null;
147003
+ return item && (React.createElement(React.Fragment, null,
147004
+ React.createElement(Icon_1.Icon, { name: item.value }),
147005
+ React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label)));
147009
147006
  };
147010
147007
  _this.state = { icons: [] };
147011
147008
  return _this;
@@ -147018,7 +147015,8 @@ var IconPicker = /** @class */ (function (_super) {
147018
147015
  });
147019
147016
  };
147020
147017
  IconPicker.prototype.render = function () {
147021
- return (React.createElement(SelectGrid_1.SelectGrid, { label: this.props.label || "Icon", filterPlaceholder: this.props.filterPlaceholder || "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
147018
+ var _a, _b;
147019
+ return (React.createElement(SelectGrid_1.SelectGrid, { label: (_a = this.props.label) !== null && _a !== void 0 ? _a : "Icon", filterPlaceholder: (_b = this.props.filterPlaceholder) !== null && _b !== void 0 ? _b : "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
147022
147020
  };
147023
147021
  return IconPicker;
147024
147022
  }(React.PureComponent));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superdesk-ui-framework",
3
- "version": "3.1.18",
3
+ "version": "3.1.20",
4
4
  "license": "AGPL-3.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,7 +15,9 @@ export declare class IconPicker extends React.PureComponent<IProps, IState> {
15
15
  componentDidMount(): void;
16
16
  getItems: (searchString: string | null) => Promise<Array<IItem>>;
17
17
  onChange: (item: IItem) => void;
18
- triggerTemplate: (props: any) => JSX.Element;
18
+ triggerTemplate: (props: {
19
+ onClick: (e: React.SyntheticEvent) => void;
20
+ }) => JSX.Element;
19
21
  itemTemplate: ({ item }: {
20
22
  item: IItem | null;
21
23
  }) => JSX.Element | null;
@@ -71,13 +71,12 @@ var IconPicker = /** @class */ (function (_super) {
71
71
  _this.onChange = function (item) {
72
72
  _this.props.onChange(item.value);
73
73
  };
74
- _this.triggerTemplate = function (props) { return React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true }); };
74
+ _this.triggerTemplate = function (props) { return (React.createElement(Button_1.Button, { icon: _this.props.value, text: _this.props.value, onClick: function (e) { props.onClick(e); }, iconOnly: true })); };
75
75
  _this.itemTemplate = function (_a) {
76
76
  var item = _a.item;
77
- return item ?
78
- (React.createElement(React.Fragment, null,
79
- React.createElement(Icon_1.Icon, { name: item.value }),
80
- React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label))) : null;
77
+ return item && (React.createElement(React.Fragment, null,
78
+ React.createElement(Icon_1.Icon, { name: item.value }),
79
+ React.createElement("span", { className: "sd-text--normal sd-padding-t--1" }, item.label)));
81
80
  };
82
81
  _this.state = { icons: [] };
83
82
  return _this;
@@ -90,7 +89,8 @@ var IconPicker = /** @class */ (function (_super) {
90
89
  });
91
90
  };
92
91
  IconPicker.prototype.render = function () {
93
- return (React.createElement(SelectGrid_1.SelectGrid, { label: this.props.label || "Icon", filterPlaceholder: this.props.filterPlaceholder || "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
92
+ var _a, _b;
93
+ return (React.createElement(SelectGrid_1.SelectGrid, { label: (_a = this.props.label) !== null && _a !== void 0 ? _a : "Icon", filterPlaceholder: (_b = this.props.filterPlaceholder) !== null && _b !== void 0 ? _b : "Search...", getItems: this.getItems, onChange: this.onChange, itemTemplate: this.itemTemplate, triggerTemplate: this.triggerTemplate }));
94
94
  };
95
95
  return IconPicker;
96
96
  }(React.PureComponent));
@@ -16,14 +16,15 @@ interface IProps {
16
16
  itemTemplate: React.ComponentType<{
17
17
  item: IItem | null;
18
18
  }>;
19
- triggerTemplate: React.ComponentType<any>;
19
+ triggerTemplate: React.ComponentType<{
20
+ onClick: (e: React.SyntheticEvent) => void;
21
+ }>;
20
22
  label: string;
21
23
  filterPlaceholder?: string;
22
24
  }
23
25
  interface IState {
24
26
  items: Array<IItem>;
25
27
  loading: boolean;
26
- isOpen: boolean;
27
28
  }
28
29
  export declare class SelectGrid extends React.PureComponent<IProps, IState> {
29
30
  htmlId: string;
@@ -34,9 +35,10 @@ export declare class SelectGrid extends React.PureComponent<IProps, IState> {
34
35
  constructor(props: IProps);
35
36
  componentDidMount(): void;
36
37
  componentWillUnmount(): void;
37
- togglePopup: (event?: React.SyntheticEvent) => void;
38
+ mountPopup: (event?: React.SyntheticEvent) => void;
38
39
  search: (event: React.ChangeEvent<HTMLInputElement>) => void;
39
40
  loadItems: (searchString?: string | null) => void;
41
+ hidePopupAndRefocus: () => void;
40
42
  select: (item: IItem) => void;
41
43
  getItemElement: (index: number) => HTMLDivElement | null | undefined;
42
44
  handleKeydown: (event: KeyboardEvent) => void;
@@ -46,36 +46,25 @@ var React = __importStar(require("react"));
46
46
  var react_id_generator_1 = __importDefault(require("react-id-generator"));
47
47
  var overlaypanel_1 = require("@superdesk/primereact/overlaypanel");
48
48
  var Loader_1 = require("./Loader");
49
+ var GRID_COLS = 3;
50
+ var GRID_ROWS = 5;
51
+ var PAGE_SIZE = GRID_COLS * GRID_ROWS;
49
52
  var SelectGrid = /** @class */ (function (_super) {
50
53
  __extends(SelectGrid, _super);
51
54
  function SelectGrid(props) {
52
55
  var _this = _super.call(this, props) || this;
53
56
  _this.htmlId = (0, react_id_generator_1.default)();
54
- _this.togglePopup = function (event) {
57
+ _this.mountPopup = function (event) {
58
+ var _a, _b;
55
59
  if (!event) {
56
- // @ts-ignore
57
- _this.overlayPanel.current.hide();
60
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
58
61
  }
59
62
  else {
60
- // @ts-ignore
61
- _this.overlayPanel.current.toggle(event);
63
+ (_b = _this.overlayPanel.current) === null || _b === void 0 ? void 0 : _b.toggle(event);
62
64
  }
63
- setTimeout(function () {
64
- // Now that the popup has (dis)appeared handle items and events
65
- var _a;
66
- if (_this.state.isOpen) {
67
- document.removeEventListener('keydown', _this.handleKeydown);
68
- // @ts-ignore
69
- (_a = _this.buttonContainer.current.querySelector('button')) === null || _a === void 0 ? void 0 : _a.focus();
70
- }
71
- else {
72
- document.addEventListener('keydown', _this.handleKeydown);
73
- _this.loadItems();
74
- // @ts-ignore
75
- _this.searchInput.current.focus();
76
- }
77
- _this.setState({ isOpen: !_this.state.isOpen });
78
- });
65
+ document.addEventListener('keydown', _this.handleKeydown);
66
+ setTimeout(function () { var _a; (_a = _this.searchInput.current) === null || _a === void 0 ? void 0 : _a.focus(); });
67
+ _this.loadItems();
79
68
  };
80
69
  _this.search = function (event) {
81
70
  var searchString = event.target.value.toLowerCase();
@@ -88,16 +77,24 @@ var SelectGrid = /** @class */ (function (_super) {
88
77
  _this.setState({ items: items, loading: false });
89
78
  });
90
79
  };
80
+ _this.hidePopupAndRefocus = function () {
81
+ var _a, _b, _c;
82
+ document.removeEventListener('keydown', _this.handleKeydown);
83
+ (_a = _this.overlayPanel.current) === null || _a === void 0 ? void 0 : _a.hide();
84
+ (_c = (_b = _this.buttonContainer.current) === null || _b === void 0 ? void 0 : _b.querySelector('button')) === null || _c === void 0 ? void 0 : _c.focus();
85
+ };
91
86
  _this.select = function (item) {
92
87
  _this.props.onChange(item);
93
- _this.togglePopup();
88
+ _this.hidePopupAndRefocus();
89
+ // trigger component update
90
+ _this.forceUpdate();
94
91
  };
95
92
  _this.getItemElement = function (index) {
96
93
  var _a;
97
94
  return (_a = _this.gridContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-item-index=\"".concat(index, "\"]"));
98
95
  };
99
96
  _this.handleKeydown = function (event) {
100
- var _a, _b, _c, _d, _e;
97
+ var _a, _b, _c, _d, _e, _f;
101
98
  var navKeys = [
102
99
  "Enter",
103
100
  "ArrowRight",
@@ -111,7 +108,7 @@ var SelectGrid = /** @class */ (function (_super) {
111
108
  if (event.code === "Escape") {
112
109
  event.preventDefault();
113
110
  event.stopPropagation();
114
- _this.togglePopup();
111
+ _this.hidePopupAndRefocus();
115
112
  }
116
113
  else if (activeElement === ((_a = _this.searchInput) === null || _a === void 0 ? void 0 : _a.current)) {
117
114
  if (event.code === "ArrowDown") {
@@ -122,13 +119,10 @@ var SelectGrid = /** @class */ (function (_super) {
122
119
  event.preventDefault();
123
120
  _this.select(_this.state.items[0]);
124
121
  }
125
- // @ts-ignore
126
122
  }
127
- else if (document.activeElement.getAttribute('data-item-index') && navKeys.includes(event.code)) {
128
- // @ts-ignore
129
- var itemIndex = parseInt(activeElement.getAttribute('data-item-index'), 10);
130
- // Prevent default behaviour, such as scrolling
131
- event.preventDefault();
123
+ else if (((_c = document.activeElement) === null || _c === void 0 ? void 0 : _c.getAttribute('data-item-index')) && navKeys.includes(event.code)) {
124
+ var itemIndex = parseInt(activeElement === null || activeElement === void 0 ? void 0 : activeElement.getAttribute('data-item-index'), 10);
125
+ event.preventDefault(); // Prevent scrolling, etc.
132
126
  if (event.code === "Enter") {
133
127
  _this.select(_this.state.items[itemIndex]);
134
128
  return;
@@ -140,20 +134,20 @@ var SelectGrid = /** @class */ (function (_super) {
140
134
  itemIndex -= 1;
141
135
  }
142
136
  else if (event.code === "ArrowDown") {
143
- itemIndex += 4;
137
+ itemIndex += GRID_COLS;
144
138
  }
145
139
  else if (event.code === "ArrowUp") {
146
- if (itemIndex === 0) {
147
- (_d = (_c = _this.searchInput) === null || _c === void 0 ? void 0 : _c.current) === null || _d === void 0 ? void 0 : _d.focus();
140
+ if (itemIndex < GRID_COLS) {
141
+ (_e = (_d = _this.searchInput) === null || _d === void 0 ? void 0 : _d.current) === null || _e === void 0 ? void 0 : _e.focus();
148
142
  return;
149
143
  }
150
- itemIndex -= 4;
144
+ itemIndex -= GRID_COLS;
151
145
  }
152
146
  else if (event.code === "PageDown") {
153
- itemIndex += 16;
147
+ itemIndex += PAGE_SIZE;
154
148
  }
155
149
  else if (event.code === "PageUp") {
156
- itemIndex -= 16;
150
+ itemIndex -= PAGE_SIZE;
157
151
  }
158
152
  if (itemIndex < 0) {
159
153
  itemIndex = 0;
@@ -161,10 +155,10 @@ var SelectGrid = /** @class */ (function (_super) {
161
155
  else if (itemIndex >= _this.state.items.length) {
162
156
  itemIndex = _this.state.items.length - 1;
163
157
  }
164
- (_e = _this.getItemElement(itemIndex)) === null || _e === void 0 ? void 0 : _e.focus();
158
+ (_f = _this.getItemElement(itemIndex)) === null || _f === void 0 ? void 0 : _f.focus();
165
159
  }
166
160
  };
167
- _this.state = { items: [], loading: true, isOpen: false };
161
+ _this.state = { items: [], loading: true };
168
162
  _this.buttonContainer = React.createRef();
169
163
  _this.overlayPanel = React.createRef();
170
164
  _this.searchInput = React.createRef();
@@ -185,19 +179,23 @@ var SelectGrid = /** @class */ (function (_super) {
185
179
  var ItemTemplate = this.props.itemTemplate;
186
180
  var TriggerTemplate = this.props.triggerTemplate;
187
181
  return (React.createElement(React.Fragment, null,
188
- React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label },
182
+ React.createElement("div", { className: "sd-input sd-input--grid-select", ref: this.buttonContainer, "aria-label": this.props.label, key: this.props.label },
189
183
  React.createElement("label", { className: "sd-input__label" }, this.props.label),
190
- React.createElement(TriggerTemplate, { onClick: this.togglePopup })),
191
- React.createElement(overlaypanel_1.OverlayPanel, { ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
184
+ React.createElement(TriggerTemplate, { onClick: this.mountPopup })),
185
+ React.createElement(overlaypanel_1.OverlayPanel, { onHide: function () {
186
+ var _a, _b;
187
+ document.removeEventListener('keydown', _this.handleKeydown);
188
+ (_b = (_a = _this.buttonContainer.current) === null || _a === void 0 ? void 0 : _a.querySelector('button')) === null || _b === void 0 ? void 0 : _b.focus();
189
+ }, ref: this.overlayPanel, dismissable: true, className: "select-grid__overlay-panel", appendTo: document.body },
192
190
  React.createElement("div", { className: "select-grid__panel" },
193
191
  React.createElement("div", { className: "select-grid__header" },
194
192
  React.createElement("div", { className: "sd-searchbar sd-searchbar--boxed" },
195
193
  React.createElement("label", { className: "sd-searchbar__icon" }),
196
194
  React.createElement("input", { className: "sd-searchbar__input", placeholder: this.props.filterPlaceholder || 'Search...', type: "text", onChange: this.search, ref: this.searchInput }))),
197
195
  React.createElement("div", { className: "select-grid__body", ref: this.gridContainer },
198
- React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
196
+ this.state.loading && React.createElement(Loader_1.Loader, { overlay: this.state.loading }),
199
197
  this.state.items.map(function (item, index) { return (React.createElement("div", { key: _this.htmlId + item.label, "data-item-index": index, className: "flex-grid__item select-grid__item sd-padding-y--3", tabIndex: 0, role: "button", "aria-label": item.name, onClick: function () { return _this.select(item); } },
200
- React.createElement(ItemTemplate, { item: item }))); }))))));
198
+ React.createElement(ItemTemplate, { key: item.value, item: item }))); }))))));
201
199
  };
202
200
  return SelectGrid;
203
201
  }(React.PureComponent));
@@ -11,5 +11,6 @@ module.exports = merge(webpackConfig, {
11
11
  devServer: {
12
12
  open: true,
13
13
  port: 9100,
14
+ host: '127.0.0.1'
14
15
  },
15
16
  });