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.
- package/app/styles/_sd-tag-input.scss +1 -1
- package/app-typescript/components/TreeSelect/TreeSelect.tsx +118 -38
- package/app-typescript/components/TreeSelect/TreeSelectPill.tsx +20 -9
- package/dist/examples.bundle.js +78139 -78057
- package/dist/react/TreeSelect.tsx +61 -3
- package/dist/superdesk-ui.bundle.css +1 -1
- package/dist/superdesk-ui.bundle.js +78175 -78103
- package/examples/pages/react/TreeSelect.tsx +61 -3
- package/package.json +1 -1
- package/react/components/TreeSelect/TreeSelect.d.ts +5 -0
- package/react/components/TreeSelect/TreeSelect.js +80 -17
- package/react/components/TreeSelect/TreeSelectPill.d.ts +1 -0
- package/react/components/TreeSelect/TreeSelectPill.js +13 -4
@@ -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,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
|
-
|
433
|
-
|
434
|
-
|
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
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
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(
|
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
|
-
|
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({
|
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
|
-
|
53
|
-
|
54
|
-
|
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("
|
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;
|