superdesk-ui-framework 3.1.4 → 3.1.5

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.
@@ -252,7 +252,7 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
252
252
  label='TreeSelect Label'
253
253
  info='Info Message'
254
254
  searchPlaceholder='Search...'
255
- getBackgroundColor={(item: any) => item.bgColor}
255
+ getBackgroundColor={(item: any) => item.bgColor}
256
256
  valueTemplate={(item, Wrapper) => {
257
257
  return (
258
258
  <Wrapper backgroundColor={item.bgColor}>
@@ -278,7 +278,65 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
278
278
  label='TreeSelect Label'
279
279
  info='Info Message'
280
280
  searchPlaceholder='Search...'
281
- getBackgroundColor={(item: any) => item.bgColor}
281
+ getBackgroundColor={(item: any) => item.bgColor}
282
+ valueTemplate={(item, Wrapper) => {
283
+ return (
284
+ <Wrapper backgroundColor={item.bgColor}>
285
+ <span>{item.name}</span>
286
+ </Wrapper>
287
+ );
288
+ }}
289
+ onChange={(e) => false}
290
+ />
291
+ `}</Markup.ReactMarkupCode>
292
+
293
+ </Markup.ReactMarkup>
294
+
295
+ <p className='docs-page__paragraph'>Sortable mode in TreeSelect.</p>
296
+ <Markup.ReactMarkup>
297
+ <Markup.ReactMarkupPreview>
298
+ <div className='docs-page__content-row docs-page__content-row--no-margin'>
299
+ <div className='form__row'>
300
+ <TreeSelect
301
+ kind='synchronous'
302
+ value={[{name: 'Category1'}, {name: 'Category2'}, {name: 'Category3'}]}
303
+ getOptions={() => options}
304
+ getId={(item) => item.name}
305
+ getLabel={(item) => item.name}
306
+ selectBranchWithChildren
307
+ allowMultiple
308
+ sortable
309
+ label='TreeSelect Label'
310
+ info='Info Message'
311
+ searchPlaceholder='Search...'
312
+ getBackgroundColor={(item: any) => item.bgColor}
313
+ valueTemplate={(item, Wrapper) => {
314
+ return (
315
+ <Wrapper backgroundColor={item.bgColor}>
316
+ <span>{item.name}</span>
317
+ </Wrapper>
318
+ );
319
+ }}
320
+ onChange={(e) => false}
321
+ />
322
+ </div>
323
+ </div>
324
+ </Markup.ReactMarkupPreview>
325
+
326
+ <Markup.ReactMarkupCode>{`
327
+ <TreeSelect
328
+ kind='synchronous'
329
+ value={[{name: 'Category1'}]}
330
+ getOptions={() => options}
331
+ getId={(item) => item.name}
332
+ getLabel={(item) => item.name}
333
+ selectBranchWithChildren
334
+ allowMultiple
335
+ sortable
336
+ label='TreeSelect Label'
337
+ info='Info Message'
338
+ searchPlaceholder='Search...'
339
+ getBackgroundColor={(item: any) => item.bgColor}
282
340
  valueTemplate={(item, Wrapper) => {
283
341
  return (
284
342
  <Wrapper backgroundColor={item.bgColor}>
@@ -401,6 +459,7 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
401
459
  <Prop name='loading' isRequired={false} type='boolean' default='false' description='Adds a loading indicator in dropdown.'/>
402
460
  <Prop name='allowMultiple' isRequired={false} type='boolean' default='/' description='Enable multi-select mode.'/>
403
461
  <Prop name='singleLevelSearch' isRequired={false} type='boolean' default='/' description='Limit search to only the level that is displayed.'/>
462
+ <Prop name='sortable' isRequired={false} type='boolean' default='/' description='Enable drag & drop functionality.'/>
404
463
  <Prop name='placeholder' isRequired={false} type='string' default='/' description='Placeholder of component in single select mode.'/>
405
464
  <Prop name='searchPlaceholder' isRequired={false} type='string' default='/' description='Filter input placeholder.'/>
406
465
  <Prop name='getLabel' isRequired={true} type='Function' default='/' description='Callback to invoke when value changes.'/>
@@ -409,7 +468,6 @@ export class TreeSelectDocs extends React.Component<{}, IState> {
409
468
  <Prop name='getBorderColor' isRequired={true} type='Function' default='/' description='Function to return border color of individual item in options in single-select mode.'/>
410
469
  <Prop name='valueTemplate' isRequired={false} type='Function(item, Wrapper)' default='/' description='Function that gets an item in the value and returns the content for it.'/>
411
470
  <Prop name='optionTemplate' isRequired={false} type='Function(item)' default='/' description='Function that gets the option and returns the content for it.'/>
412
- <Prop name='searchOptions' isRequired={false} type='Function' default='/' description='The function will be called when a search is initiated from UI in asynchronous mode.'/>
413
471
  <Prop name='onChange' isRequired={true} type='Function' default='/' description='Callback to invoke when value changes.'/>
414
472
  <Prop name='label' isRequired={false} type='string' default='/' description='Label of component.' />
415
473
  <Prop name='inlineLabel' isRequired={false} type='boolean' default='false' description='Position labels as inline.' />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superdesk-ui-framework",
3
- "version": "3.1.4",
3
+ "version": "3.1.5",
4
4
  "license": "AGPL-3.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { IInputWrapper } from '../Form/InputWrapper';
3
+ import { DropResult } from "react-beautiful-dnd";
3
4
  interface IState<T> {
4
5
  value: Array<T>;
5
6
  options: Array<ITreeNode<T>>;
@@ -25,7 +26,10 @@ interface IPropsBase<T> extends IInputWrapper {
25
26
  singleLevelSearch?: boolean;
26
27
  placeholder?: string;
27
28
  searchPlaceholder?: string;
29
+ noResultsFoundMessage?: string;
30
+ dropdownInitiallyOpen?: boolean;
28
31
  zIndex?: number;
32
+ sortable?: boolean;
29
33
  'data-test-id'?: string;
30
34
  getLabel(item: T): string;
31
35
  getId(item: T): string;
@@ -83,6 +87,7 @@ export declare class TreeSelect<T> extends React.Component<IProps<T>, IState<T>>
83
87
  private debounceFn;
84
88
  private ICancelFn;
85
89
  handleDebounce(): void;
90
+ onDragEnd(result: DropResult): void;
86
91
  render(): JSX.Element;
87
92
  }
88
93
  export {};
@@ -14,6 +14,17 @@ var __extends = (this && this.__extends) || (function () {
14
14
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
15
  };
16
16
  })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
23
+ }
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
17
28
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
29
  if (k2 === undefined) k2 = k;
19
30
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -65,6 +76,13 @@ var TreeSelectPill_1 = require("./TreeSelectPill");
65
76
  var TreeSelectItem_1 = require("./TreeSelectItem");
66
77
  var KeyboardNavigation_1 = require("./KeyboardNavigation");
67
78
  var WithPortal_1 = require("../WithPortal");
79
+ var react_beautiful_dnd_1 = require("react-beautiful-dnd");
80
+ var reorder = function (list, startIndex, endIndex) {
81
+ var result = Array.from(list);
82
+ var removed = result.splice(startIndex, 1)[0];
83
+ result.splice(endIndex, 0, removed);
84
+ return result;
85
+ };
68
86
  var TreeSelect = /** @class */ (function (_super) {
69
87
  __extends(TreeSelect, _super);
70
88
  function TreeSelect(props) {
@@ -120,6 +138,9 @@ var TreeSelect = /** @class */ (function (_super) {
120
138
  document.addEventListener("mousedown", _this.onMouseDown);
121
139
  document.addEventListener("keydown", _this.onKeyDown);
122
140
  document.addEventListener("keydown", _this.onPressEsc);
141
+ if (_this.props.dropdownInitiallyOpen) {
142
+ _this.setState({ openDropdown: true });
143
+ }
123
144
  };
124
145
  _this.debounceFn = (0, debounce_1.default)(_this.handleDebounce, 500);
125
146
  _this.state = {
@@ -155,6 +176,7 @@ var TreeSelect = /** @class */ (function (_super) {
155
176
  _this.openDropdownRef = React.createRef();
156
177
  _this.treeSelectRef = React.createRef();
157
178
  _this.popperInstance = null;
179
+ _this.onDragEnd = _this.onDragEnd.bind(_this);
158
180
  return _this;
159
181
  }
160
182
  TreeSelect.prototype.componentWillUnmount = function () {
@@ -398,6 +420,7 @@ var TreeSelect = /** @class */ (function (_super) {
398
420
  };
399
421
  TreeSelect.prototype.filteredItem = function (arr) {
400
422
  var _this = this;
423
+ var _a;
401
424
  if (this.props.kind === 'synchronous') {
402
425
  var filteredArr = arr.filter(function (item) {
403
426
  if (_this.state.searchFieldValue) {
@@ -429,17 +452,22 @@ var TreeSelect = /** @class */ (function (_super) {
429
452
  }
430
453
  }
431
454
  else if (this.props.kind === 'asynchronous') {
432
- return this.state.options.map(function (item, i) {
433
- var selectedItem = _this.state.value.some(function (obj) {
434
- return _this.props.getId(obj) === _this.props.getId(item.value);
455
+ if (this.state.options.length > 0) {
456
+ return this.state.options.map(function (item, i) {
457
+ var selectedItem = _this.state.value.some(function (obj) {
458
+ return _this.props.getId(obj) === _this.props.getId(item.value);
459
+ });
460
+ return (React.createElement("li", { key: i, className: 'suggestion-item suggestion-item--multi-select', onClick: function (event) {
461
+ _this.handleValue(event, item);
462
+ } },
463
+ React.createElement("button", { className: "suggestion-item--btn", "data-test-id": "option" }, _this.props.optionTemplate
464
+ ? _this.props.optionTemplate(item.value)
465
+ : (React.createElement("span", { className: selectedItem ? 'suggestion-item--selected' : undefined }, _this.props.getLabel(item.value))))));
435
466
  });
436
- return (React.createElement("li", { key: i, className: 'suggestion-item suggestion-item--multi-select', onClick: function (event) {
437
- _this.handleValue(event, item);
438
- } },
439
- React.createElement("button", { className: "suggestion-item--btn", "data-test-id": "option" }, _this.props.optionTemplate
440
- ? _this.props.optionTemplate(item.value)
441
- : (React.createElement("span", { className: selectedItem ? 'suggestion-item--selected' : undefined }, _this.props.getLabel(item.value))))));
442
- });
467
+ }
468
+ else {
469
+ return React.createElement("li", { className: "suggestion-item--nothing-found" }, (_a = this.props.noResultsFoundMessage) !== null && _a !== void 0 ? _a : 'Nothing found');
470
+ }
443
471
  }
444
472
  else {
445
473
  return;
@@ -481,17 +509,26 @@ var TreeSelect = /** @class */ (function (_super) {
481
509
  this.setState({ options: [] });
482
510
  if (this.props.kind === 'asynchronous') {
483
511
  if (this.state.searchFieldValue) {
484
- this.setState({
485
- loading: true,
486
- });
487
512
  this.ICancelFn = this.props.searchOptions(this.state.searchFieldValue, function (items) {
488
513
  var _a;
489
514
  _this.setState({ options: items, loading: false });
490
515
  (_a = _this.popperInstance) === null || _a === void 0 ? void 0 : _a.update();
491
516
  });
492
517
  }
518
+ else {
519
+ this.setState({ options: this.state.firstBranchOptions, loading: false });
520
+ }
493
521
  }
494
522
  };
523
+ TreeSelect.prototype.onDragEnd = function (result) {
524
+ if (!result.destination) {
525
+ return;
526
+ }
527
+ var value = reorder(this.state.value, result.source.index, result.destination.index);
528
+ this.setState({
529
+ value: value,
530
+ });
531
+ };
495
532
  TreeSelect.prototype.render = function () {
496
533
  var _this = this;
497
534
  var _a, _b;
@@ -506,6 +543,27 @@ var TreeSelect = /** @class */ (function (_super) {
506
543
  getBorderColor: this.props.getBorderColor,
507
544
  }, items: this.state.value, valueTemplate: this.props.valueTemplate, getLabel: this.props.getLabel }));
508
545
  }
546
+ var ListWrapper = this.props.sortable
547
+ ? function (_a) {
548
+ var children = _a.children;
549
+ return (React.createElement(react_beautiful_dnd_1.DragDropContext, { onDragEnd: _this.onDragEnd },
550
+ React.createElement(react_beautiful_dnd_1.Droppable, { droppableId: "droppable", direction: "horizontal" }, function (provided, _snapshot) { return (React.createElement("ul", __assign({ className: "tags-input__tag-list", ref: provided.innerRef }, provided.droppableProps),
551
+ children,
552
+ provided.placeholder)); })));
553
+ }
554
+ : function (_a) {
555
+ var children = _a.children;
556
+ return React.createElement("ul", { className: "tags-input__tag-list" }, children);
557
+ };
558
+ var ItemWrapper = this.props.sortable
559
+ ? function (_a) {
560
+ var children = _a.children, itemId = _a.itemId, i = _a.i;
561
+ return (React.createElement(react_beautiful_dnd_1.Draggable, { draggableId: itemId, index: i }, function (provided2) { return (React.createElement("div", __assign({ ref: provided2.innerRef }, provided2.draggableProps, provided2.dragHandleProps), children)); }));
562
+ }
563
+ : function (_a) {
564
+ var children = _a.children;
565
+ return React.createElement(React.Fragment, null, children);
566
+ };
509
567
  return (React.createElement(Form_1.InputWrapper, { label: this.props.label, error: this.props.error, invalid: this.props.error != null, required: this.props.required, disabled: this.props.disabled, info: this.props.info, inlineLabel: this.props.inlineLabel, labelHidden: this.props.labelHidden, htmlId: this.htmlId, tabindex: this.props.tabindex, fullWidth: (_a = this.props.inputWidth === '100%') !== null && _a !== void 0 ? _a : false, "data-test-id": this.props['data-test-id'] },
510
568
  React.createElement("div", { className: "\n tags-input sd-input__input\n tags-input--".concat(this.props.allowMultiple ? 'multi-select' : 'single-select'), ref: this.treeSelectRef, "data-test-id": this.props.allowMultiple ? undefined : 'open-popover' }, this.props.allowMultiple
511
569
  ? React.createElement("div", { className: "tags-input__tags" },
@@ -520,12 +578,13 @@ var TreeSelect = /** @class */ (function (_super) {
520
578
  }
521
579
  }, "data-test-id": "open-popover" },
522
580
  React.createElement("i", { className: "icon-plus-large" })),
523
- React.createElement("ul", { className: "tags-input__tag-list" }, this.state.value.map(function (item, i) {
581
+ React.createElement(ListWrapper, null, this.state.value.map(function (item, i) {
524
582
  var Wrapper = function (_a) {
525
583
  var backgroundColor = _a.backgroundColor, children = _a.children;
526
- return (React.createElement(TreeSelectPill_1.TreeSelectPill, { item: item, readOnly: _this.props.readOnly, disabled: _this.props.disabled, valueTemplate: _this.props.valueTemplate, backgroundColor: backgroundColor, onRemove: function () { return _this.removeClick(i); }, getBackgroundColor: _this.props.getBackgroundColor }, children));
584
+ return (React.createElement(TreeSelectPill_1.TreeSelectPill, { item: item, readOnly: _this.props.readOnly, disabled: _this.props.disabled, valueTemplate: _this.props.valueTemplate, backgroundColor: backgroundColor, onRemove: function () { return _this.removeClick(i); }, getBackgroundColor: _this.props.getBackgroundColor, draggable: _this.props.sortable }, children));
527
585
  };
528
- return (React.createElement(React.Fragment, { key: i }, _this.props.valueTemplate
586
+ var itemId = _this.props.getId(item);
587
+ return (React.createElement(ItemWrapper, { itemId: itemId, key: itemId, i: i }, _this.props.valueTemplate
529
588
  ? _this.props.valueTemplate(item, Wrapper)
530
589
  : (React.createElement(Wrapper, null,
531
590
  React.createElement("span", null, _this.props.getLabel(item))))));
@@ -588,7 +647,11 @@ var TreeSelect = /** @class */ (function (_super) {
588
647
  if (_this.ICancelFn) {
589
648
  _this.ICancelFn();
590
649
  }
591
- _this.setState({ searchFieldValue: event.target.value, options: [] });
650
+ _this.setState({
651
+ searchFieldValue: event.target.value,
652
+ options: [],
653
+ loading: true,
654
+ });
592
655
  (_b = _this.popperInstance) === null || _b === void 0 ? void 0 : _b.update();
593
656
  _this.debounceFn();
594
657
  }
@@ -7,6 +7,7 @@ interface IProps<T> {
7
7
  onRemove(): void;
8
8
  valueTemplate?(item: T, Wrapper: React.ElementType): React.ComponentType<T> | JSX.Element;
9
9
  getBackgroundColor?(item: T): string;
10
+ draggable?: boolean;
10
11
  }
11
12
  export declare class TreeSelectPill<T> extends React.Component<IProps<T>> {
12
13
  render(): JSX.Element;
@@ -37,9 +37,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
37
37
  __setModuleDefault(result, mod);
38
38
  return result;
39
39
  };
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
40
43
  Object.defineProperty(exports, "__esModule", { value: true });
41
44
  exports.TreeSelectPill = void 0;
45
+ var classnames_1 = __importDefault(require("classnames"));
42
46
  var React = __importStar(require("react"));
47
+ var DragHandle_1 = require("../DragHandle");
43
48
  var Icon_1 = require("../Icon");
44
49
  var Label_1 = require("../Label");
45
50
  var TreeSelectPill = /** @class */ (function (_super) {
@@ -49,12 +54,15 @@ var TreeSelectPill = /** @class */ (function (_super) {
49
54
  }
50
55
  TreeSelectPill.prototype.render = function () {
51
56
  var _this = this;
52
- return (React.createElement("li", { className: "tags-input__tag-item tags-input__tag-item--multi-select"
53
- + (this.props.readOnly ? ' tags-input__tag-item--readonly' : ''), onClick: function () { return (!_this.props.readOnly && !_this.props.disabled)
54
- && _this.props.onRemove(); }, style: this.props.valueTemplate
57
+ var classes = (0, classnames_1.default)('tags-input__tag-item tags-input__tag-item--multi-select', {
58
+ 'tags-input__tag-item--readonly': this.props.readOnly,
59
+ 'tags-input__tag-item--draggable': this.props.draggable,
60
+ });
61
+ return (React.createElement("li", { className: classes, style: this.props.valueTemplate
55
62
  ? { backgroundColor: this.props.backgroundColor }
56
63
  : this.props.getBackgroundColor
57
64
  && { backgroundColor: this.props.getBackgroundColor(this.props.item) }, "data-test-id": "item" },
65
+ this.props.draggable && (React.createElement(DragHandle_1.DragHandle, { blank: true, dotsInRow: '3', dotRows: '4' })),
58
66
  React.createElement("span", { className: "tags-input__helper-box", style: {
59
67
  color: this.props.backgroundColor
60
68
  ? (0, Label_1.getTextColor)(this.props.backgroundColor)
@@ -63,7 +71,8 @@ var TreeSelectPill = /** @class */ (function (_super) {
63
71
  } },
64
72
  this.props.children,
65
73
  !this.props.readOnly
66
- && React.createElement("span", { className: "tags-input__remove-button", "data-test-id": "remove" },
74
+ && React.createElement("button", { className: "tags-input__remove-button", "data-test-id": "remove", onClick: function () { return (!_this.props.readOnly && !_this.props.disabled)
75
+ && _this.props.onRemove(); } },
67
76
  React.createElement(Icon_1.Icon, { name: "close-small" })))));
68
77
  };
69
78
  return TreeSelectPill;