goblin-magic 1.6.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/test/navigation.spec.js +11 -17
- package/widgets/calendar-menu/styles.js +3 -0
- package/widgets/calendar-menu/widget.js +42 -0
- package/widgets/calendar-menu-content/widget.js +1 -0
- package/widgets/checkbox-menu-items/styles.js +28 -0
- package/widgets/checkbox-menu-items/widget.js +122 -0
- package/widgets/listener-stack/listener-stack.js +1 -1
- package/widgets/magic-button/widget.js +2 -16
- package/widgets/magic-date-field/widget.js +15 -21
- package/widgets/magic-datetime-field/widget.js +0 -1
- package/widgets/magic-div/styles.js +8 -0
- package/widgets/magic-navigation/service.js +104 -60
- package/widgets/magic-navigation/widget.js +10 -6
- package/widgets/magic-table/widget.js +2 -5
- package/widgets/magic-wave/styles.js +57 -0
- package/widgets/magic-wave/widget.js +36 -0
- package/widgets/main-tabs/styles.js +19 -2
- package/widgets/main-tabs/widget.js +1 -0
- package/widgets/menu/styles.js +19 -8
- package/widgets/menu/widget.js +8 -8
- package/widgets/small-calendar-grid/styles.js +19 -12
- package/widgets/small-calendar-grid/widget.js +8 -6
- package/widgets/tab-layout/styles.js +3 -15
- package/widgets/tab-layout/widget.js +304 -45
- package/widgets/year-month/styles.js +63 -0
- package/widgets/year-month/widget.js +163 -0
- package/widgets/year-month-grid/styles.js +57 -0
- package/widgets/year-month-grid/widget.js +63 -0
- package/widgets/year-month-menu/styles.js +22 -0
- package/widgets/year-month-menu/widget.js +117 -0
package/package.json
CHANGED
package/test/navigation.spec.js
CHANGED
|
@@ -44,37 +44,31 @@ describe('goblin.magic.navigation', function () {
|
|
|
44
44
|
|
|
45
45
|
/* 1,2,3 → 2,3,1 */
|
|
46
46
|
restore(navLogic);
|
|
47
|
-
navLogic.moveTab('
|
|
47
|
+
navLogic.moveTab('tab@1', 'panel@1', 'panel@1', 2);
|
|
48
48
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
49
49
|
.to.be.eql(['tab@2', 'tab@3', 'tab@1']);
|
|
50
50
|
|
|
51
51
|
/* 1,2,3 → 2,1,3 */
|
|
52
52
|
restore(navLogic);
|
|
53
|
-
navLogic.moveTab('
|
|
54
|
-
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
55
|
-
.to.be.eql(['tab@2', 'tab@1', 'tab@3']);
|
|
56
|
-
|
|
57
|
-
/* 1,2,3 → 2,1,3 */
|
|
58
|
-
restore(navLogic);
|
|
59
|
-
navLogic.moveTab('panel@1', 'tab@1', 'panel@1', 'tab@2', 'right');
|
|
53
|
+
navLogic.moveTab('tab@1', 'panel@1', 'panel@1', 1);
|
|
60
54
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
61
55
|
.to.be.eql(['tab@2', 'tab@1', 'tab@3']);
|
|
62
56
|
|
|
63
57
|
/* 1,2,3 → 1,2,3 */
|
|
64
58
|
restore(navLogic);
|
|
65
|
-
navLogic.moveTab('
|
|
59
|
+
navLogic.moveTab('tab@1', 'panel@1', 'panel@1', 0);
|
|
66
60
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
67
61
|
.to.be.eql(['tab@1', 'tab@2', 'tab@3']);
|
|
68
62
|
|
|
69
63
|
/* 1,2,3 → 3,1,2 */
|
|
70
64
|
restore(navLogic);
|
|
71
|
-
navLogic.moveTab('
|
|
65
|
+
navLogic.moveTab('tab@3', 'panel@1', 'panel@1', 0);
|
|
72
66
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
73
67
|
.to.be.eql(['tab@3', 'tab@1', 'tab@2']);
|
|
74
68
|
|
|
75
69
|
/* 1,2,3 → 1,3,2 */
|
|
76
70
|
restore(navLogic);
|
|
77
|
-
navLogic.moveTab('
|
|
71
|
+
navLogic.moveTab('tab@3', 'panel@1', 'panel@1', 1);
|
|
78
72
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
79
73
|
.to.be.eql(['tab@1', 'tab@3', 'tab@2']);
|
|
80
74
|
|
|
@@ -82,7 +76,7 @@ describe('goblin.magic.navigation', function () {
|
|
|
82
76
|
|
|
83
77
|
/* 2,3 → 4,5,6,1 */
|
|
84
78
|
restore(navLogic);
|
|
85
|
-
navLogic.moveTab('
|
|
79
|
+
navLogic.moveTab('tab@1', 'panel@1', 'panel@2', 3);
|
|
86
80
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
87
81
|
.to.be.eql(['tab@2', 'tab@3']);
|
|
88
82
|
expect(navLogic.state.panels['panel@2'].tabIds.toJS()) //
|
|
@@ -90,7 +84,7 @@ describe('goblin.magic.navigation', function () {
|
|
|
90
84
|
|
|
91
85
|
/* 1,3 → 2,4,5,6 */
|
|
92
86
|
restore(navLogic);
|
|
93
|
-
navLogic.moveTab('
|
|
87
|
+
navLogic.moveTab('tab@2', 'panel@1', 'panel@2', 0);
|
|
94
88
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
95
89
|
.to.be.eql(['tab@1', 'tab@3']);
|
|
96
90
|
expect(navLogic.state.panels['panel@2'].tabIds.toJS()) //
|
|
@@ -98,7 +92,7 @@ describe('goblin.magic.navigation', function () {
|
|
|
98
92
|
|
|
99
93
|
/* 1,2 → 4,5,3,6 */
|
|
100
94
|
restore(navLogic);
|
|
101
|
-
navLogic.moveTab('
|
|
95
|
+
navLogic.moveTab('tab@3', 'panel@1', 'panel@2', 2);
|
|
102
96
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
103
97
|
.to.be.eql(['tab@1', 'tab@2']);
|
|
104
98
|
expect(navLogic.state.panels['panel@2'].tabIds.toJS()) //
|
|
@@ -106,9 +100,9 @@ describe('goblin.magic.navigation', function () {
|
|
|
106
100
|
|
|
107
101
|
/* . → 2,4,1,5,6,3 */
|
|
108
102
|
restore(navLogic);
|
|
109
|
-
navLogic.moveTab('
|
|
110
|
-
navLogic.moveTab('
|
|
111
|
-
navLogic.moveTab('
|
|
103
|
+
navLogic.moveTab('tab@2', 'panel@1', 'panel@2', 0);
|
|
104
|
+
navLogic.moveTab('tab@1', 'panel@1', 'panel@2', 2);
|
|
105
|
+
navLogic.moveTab('tab@3', 'panel@1', 'panel@2', 5);
|
|
112
106
|
expect(navLogic.state.panels['panel@1'].tabIds.toJS()) //
|
|
113
107
|
.to.be.eql([]);
|
|
114
108
|
expect(navLogic.state.panels['panel@2'].tabIds.toJS()) //
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Widget from 'goblin-laboratory/widgets/widget';
|
|
3
|
+
import * as styles from './styles.js';
|
|
4
|
+
import Menu from '../menu/widget.js';
|
|
5
|
+
import CalendarMenuContent from '../calendar-menu-content/widget.js';
|
|
6
|
+
import {date as DateConverters} from 'xcraft-core-converters';
|
|
7
|
+
|
|
8
|
+
class CalendarMenu extends Widget {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.styles = styles;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
handleCalendarChange = (date, menu) => {
|
|
15
|
+
menu.close();
|
|
16
|
+
this.props.onChange(date);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
render() {
|
|
20
|
+
const {allowEmpty, selectWeek, value, onChange, children} = this.props;
|
|
21
|
+
return (
|
|
22
|
+
<Menu>
|
|
23
|
+
{children}
|
|
24
|
+
<Menu.Content position="bottom center" addTabIndex={false}>
|
|
25
|
+
<Menu.Context.Consumer>
|
|
26
|
+
{(menu) => (
|
|
27
|
+
<CalendarMenuContent
|
|
28
|
+
allowEmpty={allowEmpty}
|
|
29
|
+
selectWeek={selectWeek}
|
|
30
|
+
value={value || DateConverters.getNowCanonical()}
|
|
31
|
+
onChange={(date) => this.handleCalendarChange(date, menu)}
|
|
32
|
+
onCancel={menu.close}
|
|
33
|
+
/>
|
|
34
|
+
)}
|
|
35
|
+
</Menu.Context.Consumer>
|
|
36
|
+
</Menu.Content>
|
|
37
|
+
</Menu>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default CalendarMenu;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export default function styles() {
|
|
2
|
+
const items = {
|
|
3
|
+
padding: '3px 3px 2px 3px',
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
const item = {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
flexDirection: 'row',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const hr = {
|
|
12
|
+
width: '100%',
|
|
13
|
+
margin: 0,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const buttons = {
|
|
17
|
+
display: 'flex',
|
|
18
|
+
flexDirection: 'row',
|
|
19
|
+
padding: '1px',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
items,
|
|
24
|
+
item,
|
|
25
|
+
hr,
|
|
26
|
+
buttons,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Widget from 'goblin-laboratory/widgets/widget';
|
|
3
|
+
import * as styles from './styles.js';
|
|
4
|
+
import MagicButton from '../magic-button/widget.js';
|
|
5
|
+
import Icon from '@mdi/react';
|
|
6
|
+
import {
|
|
7
|
+
mdiCheckboxBlankOutline,
|
|
8
|
+
mdiCheckboxIntermediateVariant,
|
|
9
|
+
mdiCheckboxMarked,
|
|
10
|
+
} from '@mdi/js';
|
|
11
|
+
import MagicCheckbox from '../magic-checkbox/widget.js';
|
|
12
|
+
import Menu from '../menu/widget.js';
|
|
13
|
+
import withC from 'goblin-laboratory/widgets/connect-helpers/with-c.js';
|
|
14
|
+
|
|
15
|
+
class CheckboxMenuItemsNC extends Widget {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.styles = styles;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
toggle = (value) => {
|
|
22
|
+
const {checkedValues} = this.props;
|
|
23
|
+
if (!checkedValues) {
|
|
24
|
+
this.props.onChange(this.values.filter((v) => v !== value));
|
|
25
|
+
} else if (checkedValues.includes(value)) {
|
|
26
|
+
this.props.onChange([...checkedValues].filter((v) => v !== value));
|
|
27
|
+
} else {
|
|
28
|
+
this.props.onChange([...checkedValues, value]);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
set = (value, event) => {
|
|
33
|
+
const {checkedValues} = this.props;
|
|
34
|
+
if (event.ctrlKey) {
|
|
35
|
+
this.toggle(value);
|
|
36
|
+
} else if (checkedValues?.length === 1 && checkedValues.includes(value)) {
|
|
37
|
+
this.all();
|
|
38
|
+
} else {
|
|
39
|
+
this.props.onChange([value]);
|
|
40
|
+
}
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
all = () => {
|
|
45
|
+
this.props.onChange(null);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
empty = () => {
|
|
49
|
+
this.props.onChange([]);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
invert = () => {
|
|
53
|
+
const {checkedValues} = this.props;
|
|
54
|
+
if (checkedValues) {
|
|
55
|
+
if (checkedValues.length === 0) {
|
|
56
|
+
this.all();
|
|
57
|
+
} else {
|
|
58
|
+
this.props.onChange(
|
|
59
|
+
this.values.filter((value) => !checkedValues.includes(value))
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
this.empty();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
renderItem(value, text) {
|
|
68
|
+
const {checkedValues} = this.props;
|
|
69
|
+
return (
|
|
70
|
+
<div key={value} className={this.styles.classNames.item}>
|
|
71
|
+
<MagicCheckbox
|
|
72
|
+
value={!checkedValues || checkedValues.includes(value)}
|
|
73
|
+
onChange={() => this.toggle(value)}
|
|
74
|
+
// disabled
|
|
75
|
+
/>
|
|
76
|
+
<Menu.Item onPointerUp={(event) => this.set(value, event)}>
|
|
77
|
+
{typeof text === 'string' ? <span>{text}</span> : text}
|
|
78
|
+
</Menu.Item>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
render() {
|
|
84
|
+
const {values, checkedValues, renderValue, children} = this.props;
|
|
85
|
+
this.values = values ? [...values] : [];
|
|
86
|
+
const renderedChildren = React.Children.map(children, (child) => {
|
|
87
|
+
if (React.isValidElement(child) && child.type === 'option') {
|
|
88
|
+
const {value, children} = child.props;
|
|
89
|
+
this.values.push(value);
|
|
90
|
+
return this.renderItem(value, children);
|
|
91
|
+
}
|
|
92
|
+
return child;
|
|
93
|
+
});
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
<div className={this.styles.classNames.items}>
|
|
97
|
+
{values?.map((value) => this.renderItem(value, renderValue(value)))}
|
|
98
|
+
{renderedChildren}
|
|
99
|
+
</div>
|
|
100
|
+
<Menu.Hr className={this.styles.classNames.hr} />
|
|
101
|
+
<div className={this.styles.classNames.buttons}>
|
|
102
|
+
<MagicButton simple onPointerUp={this.all}>
|
|
103
|
+
<Icon path={mdiCheckboxMarked} size="1.2em" />
|
|
104
|
+
Tout
|
|
105
|
+
</MagicButton>
|
|
106
|
+
<MagicButton simple onPointerUp={this.empty}>
|
|
107
|
+
<Icon path={mdiCheckboxBlankOutline} size="1.2em" />
|
|
108
|
+
Aucun
|
|
109
|
+
</MagicButton>
|
|
110
|
+
<MagicButton simple onPointerUp={this.invert}>
|
|
111
|
+
<Icon path={mdiCheckboxIntermediateVariant} size="1.2em" />
|
|
112
|
+
Inverser
|
|
113
|
+
</MagicButton>
|
|
114
|
+
</div>
|
|
115
|
+
</>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const CheckboxMenuItems = withC(CheckboxMenuItemsNC);
|
|
121
|
+
|
|
122
|
+
export default CheckboxMenuItems;
|
|
@@ -51,7 +51,7 @@ export default class ListenerStack {
|
|
|
51
51
|
const stack = this.getStack(type);
|
|
52
52
|
const index = stack.indexOf(listener);
|
|
53
53
|
if (index === -1) {
|
|
54
|
-
console.error(`Unknown listener for type ${type}`);
|
|
54
|
+
// console.error(`Unknown listener for type ${type}`);
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
57
|
stack.splice(index, 1);
|
|
@@ -2,7 +2,6 @@ import * as styles from './styles.js';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import Widget from 'goblin-laboratory/widgets/widget';
|
|
4
4
|
import withC from 'goblin-laboratory/widgets/connect-helpers/with-c';
|
|
5
|
-
import {TranslatableButton} from 'goblin-nabu/widgets/helpers/element-helpers.js';
|
|
6
5
|
|
|
7
6
|
class MagicButtonNC extends Widget {
|
|
8
7
|
constructor() {
|
|
@@ -56,21 +55,7 @@ class MagicButtonNC extends Widget {
|
|
|
56
55
|
typeof this.props.children === 'string' &&
|
|
57
56
|
this.props.children.length === 1;
|
|
58
57
|
|
|
59
|
-
return
|
|
60
|
-
<TranslatableButton
|
|
61
|
-
{...props}
|
|
62
|
-
className={this.styles.classNames.button + ' button ' + className}
|
|
63
|
-
data-enabled={enabled}
|
|
64
|
-
data-underlined={underlined}
|
|
65
|
-
data-big={big}
|
|
66
|
-
data-simple={simple}
|
|
67
|
-
data-len1={len1}
|
|
68
|
-
onPointerDown={onPointerDown && this.handlePointerDown}
|
|
69
|
-
title={title}
|
|
70
|
-
>
|
|
71
|
-
{this.renderChildren(spinner, len1)}
|
|
72
|
-
</TranslatableButton>
|
|
73
|
-
) : (
|
|
58
|
+
return (
|
|
74
59
|
<button
|
|
75
60
|
{...props}
|
|
76
61
|
className={this.styles.classNames.button + ' button ' + className}
|
|
@@ -80,6 +65,7 @@ class MagicButtonNC extends Widget {
|
|
|
80
65
|
data-simple={simple}
|
|
81
66
|
data-len1={len1}
|
|
82
67
|
onPointerDown={onPointerDown && this.handlePointerDown}
|
|
68
|
+
title={title}
|
|
83
69
|
>
|
|
84
70
|
{this.renderChildren(spinner, len1)}
|
|
85
71
|
</button>
|
|
@@ -10,6 +10,7 @@ import {mdiCalendarMonth} from '@mdi/js';
|
|
|
10
10
|
import Menu from '../menu/widget.js';
|
|
11
11
|
import CalendarMenuContent from '../calendar-menu-content/widget.js';
|
|
12
12
|
import CalendarHelpers from '../calendar-helpers.js';
|
|
13
|
+
import CalendarMenu from '../calendar-menu/widget.js';
|
|
13
14
|
|
|
14
15
|
class MagicDateFieldNC extends Widget {
|
|
15
16
|
constructor() {
|
|
@@ -150,41 +151,34 @@ class MagicDateFieldNC extends Widget {
|
|
|
150
151
|
this.dateBeforeMonthChange = null;
|
|
151
152
|
};
|
|
152
153
|
|
|
153
|
-
handleCalendarChange = (date, menu) => {
|
|
154
|
-
menu.close();
|
|
155
|
-
this.props.onChange(date);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
154
|
render() {
|
|
159
|
-
const {
|
|
155
|
+
const {
|
|
156
|
+
value,
|
|
157
|
+
onChange,
|
|
158
|
+
className = '',
|
|
159
|
+
required,
|
|
160
|
+
disabled,
|
|
161
|
+
...props
|
|
162
|
+
} = this.props;
|
|
160
163
|
return (
|
|
161
164
|
<InputGroup>
|
|
162
165
|
<MagicTextField
|
|
163
166
|
inputRef={this.inputRef}
|
|
167
|
+
value={value}
|
|
168
|
+
onChange={onChange}
|
|
164
169
|
format={this.format}
|
|
165
170
|
parse={this.parse}
|
|
171
|
+
disabled={disabled}
|
|
166
172
|
{...props}
|
|
167
173
|
onKeyDown={this.handleKeyDown}
|
|
168
174
|
onBlur={this.handleBlur}
|
|
169
175
|
className={this.styles.classNames.dateField + ' ' + className}
|
|
170
176
|
/>
|
|
171
|
-
<
|
|
172
|
-
<Menu.Button>
|
|
177
|
+
<CalendarMenu allowEmpty={!required} value={value} onChange={onChange}>
|
|
178
|
+
<Menu.Button disabled={disabled}>
|
|
173
179
|
<Icon path={mdiCalendarMonth} size={0.8} />
|
|
174
180
|
</Menu.Button>
|
|
175
|
-
|
|
176
|
-
<Menu.Context.Consumer>
|
|
177
|
-
{(menu) => (
|
|
178
|
-
<CalendarMenuContent
|
|
179
|
-
allowEmpty={!required}
|
|
180
|
-
value={this.props.value || DateConverters.getNowCanonical()}
|
|
181
|
-
onChange={(date) => this.handleCalendarChange(date, menu)}
|
|
182
|
-
onCancel={menu.close}
|
|
183
|
-
/>
|
|
184
|
-
)}
|
|
185
|
-
</Menu.Context.Consumer>
|
|
186
|
-
</Menu.Content>
|
|
187
|
-
</Menu>
|
|
181
|
+
</CalendarMenu>
|
|
188
182
|
</InputGroup>
|
|
189
183
|
);
|
|
190
184
|
}
|
|
@@ -12,6 +12,14 @@ export default function styles() {
|
|
|
12
12
|
'@media (prefers-color-scheme: light)': {
|
|
13
13
|
background: 'rgba(248, 241, 248, 0.85)',
|
|
14
14
|
},
|
|
15
|
+
|
|
16
|
+
'.prefers-reduced-transparency &': {
|
|
17
|
+
'background': 'rgba(41, 51, 77, 1)',
|
|
18
|
+
'backdropFilter': 'none',
|
|
19
|
+
'@media (prefers-color-scheme: light)': {
|
|
20
|
+
background: 'rgba(241, 237, 244, 1)',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
15
23
|
};
|
|
16
24
|
|
|
17
25
|
return {
|