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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goblin-magic",
3
- "version": "1.6.1",
3
+ "version": "1.8.0",
4
4
  "description": "goblin-magic",
5
5
  "author": "Epsitec SA",
6
6
  "contributors": [
@@ -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('panel@1', 'tab@1', 'panel@1', 'tab@3', 'right');
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('panel@1', 'tab@1', 'panel@1', 'tab@3', 'left');
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('panel@1', 'tab@1', 'panel@1', 'tab@2', 'left');
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('panel@1', 'tab@3', 'panel@1', 'tab@1', 'left');
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('panel@1', 'tab@3', 'panel@1', 'tab@1', 'right');
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('panel@1', 'tab@1', 'panel@2', 'tab@6', 'right');
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('panel@1', 'tab@2', 'panel@2', 'tab@4', 'left');
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('panel@1', 'tab@3', 'panel@2', 'tab@5', 'right');
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('panel@1', 'tab@2', 'panel@2', 'tab@4', 'left');
110
- navLogic.moveTab('panel@1', 'tab@1', 'panel@2', 'tab@5', 'left');
111
- navLogic.moveTab('panel@1', 'tab@3', 'panel@2', 'tab@6', 'right');
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,3 @@
1
+ export default function styles() {
2
+ return {};
3
+ }
@@ -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;
@@ -52,6 +52,7 @@ class CalendarMenuContent extends Widget {
52
52
  >
53
53
  <SmallCalendar
54
54
  ref={this.calendarRef}
55
+ selectWeek={this.props.selectWeek}
55
56
  date={this.state.date}
56
57
  onDateChange={this.handleDateChange}
57
58
  onDayClick={this.handleDayClick}
@@ -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 title ? (
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 {className = '', required, ...props} = this.props;
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
- <Menu>
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
- <Menu.Content position="bottom center" addTabIndex={false}>
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
  }
@@ -68,7 +68,6 @@ class MagicDatetimeFieldNC extends Widget {
68
68
  requiredDate,
69
69
  requiredTime,
70
70
  isEndTime,
71
- dispatch,
72
71
  ...props
73
72
  } = this.props;
74
73
  const {date, time} = value ? parseZonedDateTime(value) : {};
@@ -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 {