superdesk-ui-framework 3.0.1-beta.25 → 3.0.1-beta.26
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 +36 -1
- package/app/styles/_table-list.scss +1 -0
- package/app/styles/primereact/_pr-dialog.scss +4 -0
- package/app-typescript/components/Label.tsx +10 -6
- package/app-typescript/components/Layouts/AuthoringFrame.tsx +2 -1
- package/app-typescript/components/Layouts/AuthoringFrameRightBar.tsx +21 -2
- package/app-typescript/components/Lists/TableList.tsx +62 -2
- package/app-typescript/components/Menu.tsx +2 -2
- package/app-typescript/components/Spacer.tsx +1 -1
- package/app-typescript/components/TreeSelect.tsx +85 -33
- package/dist/examples.bundle.js +1549 -1184
- package/dist/playgrounds/react-playgrounds/Index.tsx +1 -0
- package/dist/playgrounds/react-playgrounds/Multiedit.tsx +321 -0
- package/dist/react/TableList.tsx +2 -0
- package/dist/react/TreeSelect.tsx +100 -78
- package/dist/superdesk-ui.bundle.css +34 -2
- package/dist/superdesk-ui.bundle.js +1132 -1059
- package/dist/vendor.bundle.js +4 -4
- package/examples/index.js +4 -0
- package/examples/pages/playgrounds/react-playgrounds/Index.tsx +1 -0
- package/examples/pages/playgrounds/react-playgrounds/Multiedit.tsx +321 -0
- package/examples/pages/react/TableList.tsx +2 -0
- package/examples/pages/react/TreeSelect.tsx +100 -78
- package/package.json +1 -1
- package/react/components/Label.d.ts +1 -1
- package/react/components/Label.js +10 -5
- package/react/components/Layouts/AuthoringFrame.d.ts +1 -0
- package/react/components/Layouts/AuthoringFrame.js +1 -1
- package/react/components/Layouts/AuthoringFrameRightBar.d.ts +9 -2
- package/react/components/Layouts/AuthoringFrameRightBar.js +14 -3
- package/react/components/Lists/TableList.d.ts +1 -0
- package/react/components/Lists/TableList.js +34 -6
- package/react/components/Menu.js +1 -1
- package/react/components/TreeSelect.d.ts +3 -1
- package/react/components/TreeSelect.js +50 -23
@@ -276,6 +276,7 @@ tags-input,
|
|
276
276
|
}
|
277
277
|
}
|
278
278
|
.suggestion-item {
|
279
|
+
position: relative;
|
279
280
|
padding: 0.5rem 1rem;
|
280
281
|
cursor: pointer;
|
281
282
|
white-space: nowrap;
|
@@ -312,6 +313,20 @@ tags-input,
|
|
312
313
|
justify-content: space-between;
|
313
314
|
align-items: center;
|
314
315
|
}
|
316
|
+
.suggestion-item--bgcolor {
|
317
|
+
min-height: 1.5em;
|
318
|
+
min-width: 1.5em;
|
319
|
+
padding: 4px 0;
|
320
|
+
display: inline-flex;
|
321
|
+
justify-content: center;
|
322
|
+
align-items: center;
|
323
|
+
border-radius: 99px;
|
324
|
+
white-space: nowrap;
|
325
|
+
|
326
|
+
&[style] {
|
327
|
+
padding-inline: 8px;
|
328
|
+
}
|
329
|
+
}
|
315
330
|
.suggestion-item--disabled {
|
316
331
|
opacity: 0.5;
|
317
332
|
}
|
@@ -493,6 +508,11 @@ tags-input,
|
|
493
508
|
}
|
494
509
|
}
|
495
510
|
|
511
|
+
.tags-input--single-select {
|
512
|
+
display: grid !important;
|
513
|
+
align-items: center !important;
|
514
|
+
}
|
515
|
+
|
496
516
|
.tags-input--multi-select,
|
497
517
|
.tags-input--single-select {
|
498
518
|
position: relative;
|
@@ -546,7 +566,7 @@ tags-input,
|
|
546
566
|
.tags-input__remove-button {
|
547
567
|
display: flex;
|
548
568
|
align-items: center;
|
549
|
-
align-self:
|
569
|
+
align-self: center;
|
550
570
|
margin-inline-start: auto;
|
551
571
|
z-index: 2;
|
552
572
|
cursor: pointer;
|
@@ -561,3 +581,18 @@ tags-input,
|
|
561
581
|
font-weight: 300;
|
562
582
|
}
|
563
583
|
}
|
584
|
+
|
585
|
+
.item-border {
|
586
|
+
width: 5px;
|
587
|
+
z-index: 2;
|
588
|
+
position: absolute;
|
589
|
+
inset-block: 7px;
|
590
|
+
inset-inline-start: 3px;
|
591
|
+
border-radius: 2px;
|
592
|
+
|
593
|
+
&-selected {
|
594
|
+
inset-block: 5px;
|
595
|
+
}
|
596
|
+
}
|
597
|
+
|
598
|
+
|
@@ -78,11 +78,15 @@ export class Label extends React.PureComponent<IProps> {
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
-
export function getTextColor(backgroundColor: string): 'black' | 'white' {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
81
|
+
export function getTextColor(backgroundColor: string): 'black' | 'white' | undefined {
|
82
|
+
if (backgroundColor) {
|
83
|
+
const r = parseInt(backgroundColor.substr(1, 2), 16);
|
84
|
+
const g = parseInt(backgroundColor.substr(3, 2), 16);
|
85
|
+
const b = parseInt(backgroundColor.substr(5, 2), 16);
|
86
|
+
const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
86
87
|
|
87
|
-
|
88
|
+
return (yiq >= 128) ? 'black' : 'white';
|
89
|
+
} else {
|
90
|
+
return;
|
91
|
+
}
|
88
92
|
}
|
@@ -16,6 +16,7 @@ interface IProps {
|
|
16
16
|
header?: React.ReactNode;
|
17
17
|
main?: React.ReactNode;
|
18
18
|
sideBar?: React.ReactNode;
|
19
|
+
sideBarClosed?: boolean;
|
19
20
|
sidePanel?: React.ReactNode;
|
20
21
|
sideOverlay?: React.ReactNode;
|
21
22
|
sideOverlayOpen?: boolean;
|
@@ -56,7 +57,7 @@ export class AuthoringFrame extends React.PureComponent<IProps> {
|
|
56
57
|
</AuthoringFrameSidePanelOverlay>
|
57
58
|
)}
|
58
59
|
{this.props.sideBar && (
|
59
|
-
<AuthoringFrameRightBar>
|
60
|
+
<AuthoringFrameRightBar closed={this.props.sideBarClosed}>
|
60
61
|
{this.props.sideBar}
|
61
62
|
</AuthoringFrameRightBar>
|
62
63
|
)}
|
@@ -2,12 +2,31 @@ import * as React from 'react';
|
|
2
2
|
|
3
3
|
interface IProps {
|
4
4
|
children?: React.ReactNode;
|
5
|
+
closed?: boolean;
|
5
6
|
}
|
6
7
|
|
7
|
-
|
8
|
+
interface IState {
|
9
|
+
children?: React.ReactNode;
|
10
|
+
closed?: boolean;
|
11
|
+
}
|
12
|
+
|
13
|
+
export class AuthoringFrameRightBar extends React.PureComponent<IProps, IState> {
|
14
|
+
constructor(props: IProps) {
|
15
|
+
super(props);
|
16
|
+
this.state = {
|
17
|
+
closed: this.props.closed ? this.props.closed : false,
|
18
|
+
};
|
19
|
+
}
|
20
|
+
componentDidUpdate(prevProps: Readonly<IProps>): void {
|
21
|
+
if (prevProps.closed !== this.props.closed) {
|
22
|
+
this.setState({
|
23
|
+
closed: this.props.closed,
|
24
|
+
});
|
25
|
+
}
|
26
|
+
}
|
8
27
|
render() {
|
9
28
|
return (
|
10
|
-
<div className="sd-editor-grid__sidetabs-bar">
|
29
|
+
!this.state.closed && <div className="sd-editor-grid__sidetabs-bar">
|
11
30
|
{this.props.children}
|
12
31
|
</div>
|
13
32
|
);
|
@@ -4,6 +4,7 @@ import { DragDropContext, Droppable, Draggable, DropResult } from "react-beautif
|
|
4
4
|
import { Tooltip } from '../Tooltip';
|
5
5
|
import { Button } from '../Button';
|
6
6
|
import { Dropdown, IMenuItem, ISubmenu, IMenuGroup } from '../Dropdown';
|
7
|
+
import ReactDOM from 'react-dom';
|
7
8
|
|
8
9
|
export interface IProps {
|
9
10
|
array: Array<IPropsArrayItem>;
|
@@ -12,6 +13,7 @@ export interface IProps {
|
|
12
13
|
className?: string;
|
13
14
|
readOnly?: boolean;
|
14
15
|
showDragHandle?: 'always' | 'onHover' | 'none'; // always default
|
16
|
+
append?: boolean;
|
15
17
|
onDrag?(start: number, end: number): void;
|
16
18
|
onAddItem?(index: number, item?: IPropsArrayItem ): void;
|
17
19
|
itemsDropdown?(index?: number): Array<IMenuItem | ISubmenu | IMenuGroup | 'divider'>;
|
@@ -122,8 +124,23 @@ class TableList extends React.PureComponent<IProps, IState> {
|
|
122
124
|
{...provided.droppableProps} >
|
123
125
|
{this.state.items.map((item: IPropsArrayItem, index: number) => (
|
124
126
|
<Draggable key={index} draggableId={`${index}`} index={index}>
|
125
|
-
{(provided2,
|
126
|
-
|
127
|
+
{(provided2, snapshot) => (
|
128
|
+
this.props.append
|
129
|
+
? <PortalItem
|
130
|
+
provided={provided2}
|
131
|
+
snapshot={snapshot}
|
132
|
+
item={item}
|
133
|
+
index={index}
|
134
|
+
dragAndDrop={this.props.dragAndDrop}
|
135
|
+
showDragHandle={this.props.showDragHandle}
|
136
|
+
addItem={this.props.addItem}
|
137
|
+
onAddItem={() => this.props.onAddItem
|
138
|
+
&& this.props.onAddItem(index, item)}
|
139
|
+
itemsDropdown={() => this.props.itemsDropdown
|
140
|
+
? this.props.itemsDropdown(index)
|
141
|
+
: []}
|
142
|
+
/>
|
143
|
+
: <div
|
127
144
|
ref={provided2.innerRef}
|
128
145
|
{...provided2.draggableProps}
|
129
146
|
{...provided2.dragHandleProps} >
|
@@ -335,6 +352,49 @@ class TableListItem extends React.PureComponent<IPropsItem> {
|
|
335
352
|
}
|
336
353
|
}
|
337
354
|
|
355
|
+
class PortalItem extends React.PureComponent {
|
356
|
+
props: any;
|
357
|
+
render() {
|
358
|
+
const provided = this.props.provided;
|
359
|
+
const snapshot = this.props.snapshot;
|
360
|
+
|
361
|
+
const usePortal: boolean = snapshot.isDragging;
|
362
|
+
|
363
|
+
const child = (
|
364
|
+
<div
|
365
|
+
ref={provided.innerRef}
|
366
|
+
{...provided.draggableProps}
|
367
|
+
{...provided.dragHandleProps}>
|
368
|
+
<TableListItem
|
369
|
+
dragAndDrop={this.props.dragAndDrop}
|
370
|
+
start={this.props.item.start}
|
371
|
+
center={this.props.item.center}
|
372
|
+
end={this.props.item.end}
|
373
|
+
action={this.props.item.action}
|
374
|
+
onClick={this.props.item.onClick ? this.props.item.onClick : undefined}
|
375
|
+
onDoubleClick={this.props.item.onDoubleClick
|
376
|
+
? this.props.item.onDoubleClick
|
377
|
+
: undefined}
|
378
|
+
addItem={this.props.addItem}
|
379
|
+
itemsDropdown={this.props.itemsDropdown}
|
380
|
+
hexColor={this.props.item.hexColor}
|
381
|
+
locked={this.props.item.locked}
|
382
|
+
positionLocked={this.props.item.positionLocked}
|
383
|
+
onAddItem={() => this.props.onAddItem}
|
384
|
+
showDragHandle={this.props.showDragHandle}
|
385
|
+
/>
|
386
|
+
</div>
|
387
|
+
);
|
388
|
+
|
389
|
+
if (!usePortal) {
|
390
|
+
return child;
|
391
|
+
}
|
392
|
+
|
393
|
+
// if dragging - put the item in a portal
|
394
|
+
return ReactDOM.createPortal(child, document.body);
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
338
398
|
export {
|
339
399
|
TableList, TableListItem
|
340
400
|
};
|
@@ -131,7 +131,7 @@ export class Menu extends React.Component<IProps, {}> {
|
|
131
131
|
|
132
132
|
render() {
|
133
133
|
return (
|
134
|
-
<
|
134
|
+
<React.Fragment>
|
135
135
|
{
|
136
136
|
this.props.children(this.toggle)
|
137
137
|
}
|
@@ -167,7 +167,7 @@ export class Menu extends React.Component<IProps, {}> {
|
|
167
167
|
baseZIndex={this.props.zIndex ?? superdeskTopBarZIndex}
|
168
168
|
/>
|
169
169
|
</div>
|
170
|
-
</
|
170
|
+
</React.Fragment>
|
171
171
|
);
|
172
172
|
}
|
173
173
|
}
|
@@ -4,7 +4,7 @@ import classNames from 'classnames';
|
|
4
4
|
export interface IPropsSpacer {
|
5
5
|
h?: boolean; // horizontal
|
6
6
|
v?: boolean; // vertical
|
7
|
-
gap: '4' | '8' | '16' | '32' | '64';
|
7
|
+
gap: '0' | '4' | '8' | '16' | '32' | '64';
|
8
8
|
justifyContent?: 'start' | 'end' | 'center' | 'space-around' | 'space-between' | 'space-evenly' | 'stretch';
|
9
9
|
alignItems?: 'start' | 'end' | 'center' | 'stretch';
|
10
10
|
noGrow?: boolean;
|
@@ -6,6 +6,7 @@ import _debounce from 'lodash/debounce';
|
|
6
6
|
import { InputWrapper } from "./Form";
|
7
7
|
import { createPopper } from '@popperjs/core';
|
8
8
|
import {isEqual} from 'lodash';
|
9
|
+
import {getTextColor} from './Label';
|
9
10
|
|
10
11
|
interface IState<T> {
|
11
12
|
value: Array<T>;
|
@@ -44,8 +45,10 @@ interface IPropsBase<T> {
|
|
44
45
|
disabled?: boolean;
|
45
46
|
getLabel(item: T): string;
|
46
47
|
getId(item: T): string;
|
48
|
+
getBackgroundColor?(item: T): string;
|
49
|
+
getBorderColor?(item: T): string;
|
47
50
|
optionTemplate?(item: T): React.ComponentType<T> | JSX.Element;
|
48
|
-
valueTemplate?(item: T): React.ComponentType<T> | JSX.Element;
|
51
|
+
valueTemplate?(item: T, Wrapper: any): React.ComponentType<T> | JSX.Element;
|
49
52
|
onChange(e: Array<T>): void;
|
50
53
|
}
|
51
54
|
|
@@ -102,7 +105,6 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
102
105
|
this.toggleMenu = this.toggleMenu.bind(this);
|
103
106
|
this.dropdownRef = React.createRef();
|
104
107
|
this.openDropdownRef = React.createRef();
|
105
|
-
|
106
108
|
}
|
107
109
|
|
108
110
|
componentDidMount = () => {
|
@@ -339,17 +341,24 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
339
341
|
event.stopPropagation();
|
340
342
|
this.handleTree(event, option);
|
341
343
|
}}>
|
342
|
-
{this.props.
|
344
|
+
{this.props.getBorderColor
|
345
|
+
&& <div className="item-border"
|
346
|
+
style={{backgroundColor: this.props.getBorderColor(option.value)}}></div>}
|
347
|
+
<span
|
348
|
+
style={this.props.getBackgroundColor
|
349
|
+
? {backgroundColor: this.props.getBackgroundColor(option.value),
|
350
|
+
color: getTextColor(this.props.getBackgroundColor(option.value))}
|
351
|
+
: undefined}
|
352
|
+
className={'suggestion-item--bgcolor'
|
353
|
+
+ (selectedItem ? ' suggestion-item--disabled' : '')}
|
354
|
+
>
|
355
|
+
{this.props.optionTemplate
|
343
356
|
? this.props.optionTemplate(option.value)
|
344
|
-
:
|
345
|
-
|
346
|
-
|
347
|
-
>
|
348
|
-
|
349
|
-
</span>}
|
350
|
-
{option.children && <span className="suggestion-item__icon">
|
351
|
-
<Icon name="chevron-right-thin"></Icon>
|
352
|
-
</span>}
|
357
|
+
: this.props.getLabel(option.value)}
|
358
|
+
</span>
|
359
|
+
{option.children && <span className="suggestion-item__icon">
|
360
|
+
<Icon name="chevron-right-thin"></Icon>
|
361
|
+
</span>}
|
353
362
|
</li>;
|
354
363
|
});
|
355
364
|
}
|
@@ -451,27 +460,46 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
451
460
|
</button>}
|
452
461
|
<ul className="tags-input__tag-list">
|
453
462
|
{this.state.value.map((item, i: number) => {
|
454
|
-
|
463
|
+
const Wrapper: React.ComponentType<{backgroundColor?: string}>
|
464
|
+
= ({backgroundColor, children}) => (
|
455
465
|
<li
|
456
466
|
className={"tags-input__tag-item tags-input__tag-item--multi-select"
|
457
467
|
+ (this.props.readOnly ? ' tags-input__tag-item--readonly' : '')}
|
458
|
-
onClick={() => this.props.readOnly
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
468
|
+
onClick={() => !this.props.readOnly && this.removeClick(i)}
|
469
|
+
style={this.props.valueTemplate
|
470
|
+
? {backgroundColor}
|
471
|
+
: this.props.getBackgroundColor
|
472
|
+
&& {backgroundColor: this.props.getBackgroundColor(item)}}>
|
473
|
+
<span
|
474
|
+
style={{color: backgroundColor
|
475
|
+
? getTextColor(backgroundColor)
|
476
|
+
: this.props.getBackgroundColor
|
477
|
+
&& getTextColor(this.props.getBackgroundColor(item))}}
|
478
|
+
className="tags-input__helper-box">
|
479
|
+
{children}
|
480
|
+
{!this.props.readOnly && <span className="tags-input__remove-button">
|
465
481
|
<Icon name="close-small"></Icon>
|
466
482
|
</span>}
|
467
483
|
</span>
|
468
484
|
</li>
|
469
|
-
|
485
|
+
);
|
486
|
+
|
487
|
+
return (
|
488
|
+
<React.Fragment key={i}>
|
489
|
+
{this.props.valueTemplate
|
490
|
+
? this.props.valueTemplate(item, Wrapper)
|
491
|
+
: <Wrapper>
|
492
|
+
<span>{this.props.getLabel(item)}</span>
|
493
|
+
</Wrapper>
|
494
|
+
}
|
495
|
+
</React.Fragment>
|
496
|
+
);
|
470
497
|
})}
|
471
498
|
</ul>
|
472
499
|
{this.state.value.length > 0
|
473
500
|
? this.props.readOnly
|
474
501
|
|| <button className="tags-input__remove-value"
|
502
|
+
style={{position: 'relative', bottom: '2px'}}
|
475
503
|
onClick={() => this.setState({value: []})}>
|
476
504
|
<Icon name='remove-sign'></Icon>
|
477
505
|
</button> : null}
|
@@ -490,21 +518,40 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
490
518
|
</span>
|
491
519
|
</span>}
|
492
520
|
{this.state.value.map((item, i: number) => {
|
493
|
-
|
521
|
+
const Wrapper: React.ComponentType<{backgroundColor?: string, borderColor?: string}>
|
522
|
+
= ({backgroundColor, borderColor, children}) => (
|
494
523
|
<span
|
495
524
|
className={ 'tags-input__single-item'
|
496
525
|
+ (this.props.readOnly ? ' tags-input__tag-item--readonly' : '')}
|
497
526
|
onClick={() => this.props.readOnly || this.removeClick(i)}>
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
527
|
+
{this.props.getBorderColor
|
528
|
+
&& <div className="item-border item-border-selected"
|
529
|
+
style={borderColor
|
530
|
+
? {backgroundColor: borderColor}
|
531
|
+
: {backgroundColor: this.props.getBorderColor(item)}}></div>}
|
532
|
+
<span
|
533
|
+
style={{color: backgroundColor && getTextColor(backgroundColor)}}
|
534
|
+
className="tags-input__helper-box">
|
535
|
+
<span
|
536
|
+
className={backgroundColor && `tags-input__tag-item`}
|
537
|
+
style={{backgroundColor, margin: 0}}>
|
538
|
+
{children}
|
539
|
+
</span>
|
502
540
|
{this.props.readOnly
|
503
541
|
|| <span className="tags-input__remove-button">
|
504
542
|
<Icon name='remove-sign'></Icon>
|
505
543
|
</span>}
|
506
544
|
</span>
|
507
545
|
</span>
|
546
|
+
);
|
547
|
+
|
548
|
+
return <React.Fragment key={i}>
|
549
|
+
{this.props.valueTemplate
|
550
|
+
? this.props.valueTemplate(item, Wrapper)
|
551
|
+
: <Wrapper>
|
552
|
+
<span>{this.props.getLabel(item)}</span>
|
553
|
+
</Wrapper>
|
554
|
+
}
|
508
555
|
</React.Fragment>;
|
509
556
|
})}
|
510
557
|
</div>
|
@@ -583,14 +630,19 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
583
630
|
event.stopPropagation();
|
584
631
|
this.handleTree(event, option);
|
585
632
|
}}>
|
586
|
-
{this.props.
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
633
|
+
{(this.props.getBorderColor && !this.props.allowMultiple) && <div className="item-border" style={{backgroundColor: this.props.getBorderColor(option.value)}}></div>}
|
634
|
+
<span
|
635
|
+
style={(this.props.getBackgroundColor && option.value)
|
636
|
+
? {backgroundColor: this.props.getBackgroundColor(option.value),
|
637
|
+
color: getTextColor(this.props.getBackgroundColor(option.value))}
|
638
|
+
: undefined}
|
639
|
+
className={'suggestion-item--bgcolor'
|
640
|
+
+ (selectedItem ? ' suggestion-item--disabled' : '')}
|
591
641
|
>
|
592
|
-
{this.props.
|
593
|
-
|
642
|
+
{this.props.optionTemplate
|
643
|
+
? this.props.optionTemplate(option.value)
|
644
|
+
: this.props.getLabel(option.value)}
|
645
|
+
</span>
|
594
646
|
{option.children && <span className="suggestion-item__icon">
|
595
647
|
<Icon name="chevron-right-thin"></Icon>
|
596
648
|
</span>}
|