goblin-magic 1.0.3

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.
Files changed (88) hide show
  1. package/.editorconfig +9 -0
  2. package/.zou-flow +2 -0
  3. package/eslint.config.js +65 -0
  4. package/magicNavigation.js +7 -0
  5. package/package.json +45 -0
  6. package/widgets/dialog/widget.js +78 -0
  7. package/widgets/element-helpers/element-has-direct-text.js +9 -0
  8. package/widgets/element-helpers/is-empty-area-element.js +17 -0
  9. package/widgets/element-helpers/is-flat-element.js +52 -0
  10. package/widgets/get-modifiers/get-modifiers.js +34 -0
  11. package/widgets/input-group/styles.js +74 -0
  12. package/widgets/input-group/widget.js +24 -0
  13. package/widgets/magic-action/styles.js +45 -0
  14. package/widgets/magic-action/widget.js +44 -0
  15. package/widgets/magic-background/bg-alps.jpg +0 -0
  16. package/widgets/magic-background/bg-fur.png +0 -0
  17. package/widgets/magic-background/bg-milkyway.png +0 -0
  18. package/widgets/magic-background/bg-space.jpg +0 -0
  19. package/widgets/magic-background/bg-synth.jpg +0 -0
  20. package/widgets/magic-background/bg-white.png +0 -0
  21. package/widgets/magic-background/styles.js +81 -0
  22. package/widgets/magic-background/widget.js +20 -0
  23. package/widgets/magic-box/styles.js +10 -0
  24. package/widgets/magic-box/widget.js +28 -0
  25. package/widgets/magic-box-old/styles.js +111 -0
  26. package/widgets/magic-box-old/widget.js +30 -0
  27. package/widgets/magic-button/styles.js +156 -0
  28. package/widgets/magic-button/widget.js +89 -0
  29. package/widgets/magic-checkbox/styles.js +116 -0
  30. package/widgets/magic-checkbox/widget.js +68 -0
  31. package/widgets/magic-color-field/styles.js +22 -0
  32. package/widgets/magic-color-field/widget.js +68 -0
  33. package/widgets/magic-date-field/styles.js +9 -0
  34. package/widgets/magic-date-field/widget.js +145 -0
  35. package/widgets/magic-datetime-field/styles.js +11 -0
  36. package/widgets/magic-datetime-field/widget.js +95 -0
  37. package/widgets/magic-dialog/styles.js +39 -0
  38. package/widgets/magic-dialog/widget.js +116 -0
  39. package/widgets/magic-div/styles.js +22 -0
  40. package/widgets/magic-div/widget.js +20 -0
  41. package/widgets/magic-emoji/styles.js +14 -0
  42. package/widgets/magic-emoji/widget.js +33 -0
  43. package/widgets/magic-emoji-picker/styles.js +21 -0
  44. package/widgets/magic-emoji-picker/widget.js +44 -0
  45. package/widgets/magic-inplace-input/styles.js +55 -0
  46. package/widgets/magic-inplace-input/widget.js +26 -0
  47. package/widgets/magic-input/styles.js +50 -0
  48. package/widgets/magic-input/widget.js +397 -0
  49. package/widgets/magic-label/styles.js +20 -0
  50. package/widgets/magic-label/widget.js +24 -0
  51. package/widgets/magic-navigation/service.js +1306 -0
  52. package/widgets/magic-navigation/styles.js +103 -0
  53. package/widgets/magic-navigation/view-context.js +15 -0
  54. package/widgets/magic-navigation/widget.js +540 -0
  55. package/widgets/magic-number-field/styles.js +10 -0
  56. package/widgets/magic-number-field/widget.js +103 -0
  57. package/widgets/magic-panel/styles.js +61 -0
  58. package/widgets/magic-panel/widget.js +63 -0
  59. package/widgets/magic-radio/styles.js +93 -0
  60. package/widgets/magic-radio/widget.js +74 -0
  61. package/widgets/magic-scroll/styles.js +22 -0
  62. package/widgets/magic-scroll/widget.js +20 -0
  63. package/widgets/magic-select/styles.js +16 -0
  64. package/widgets/magic-select/widget.js +134 -0
  65. package/widgets/magic-table/reducer.js +63 -0
  66. package/widgets/magic-table/styles.js +170 -0
  67. package/widgets/magic-table/widget.js +627 -0
  68. package/widgets/magic-tag/styles.js +32 -0
  69. package/widgets/magic-tag/widget.js +32 -0
  70. package/widgets/magic-text-field/styles.js +58 -0
  71. package/widgets/magic-text-field/widget.js +66 -0
  72. package/widgets/magic-time-field/styles.js +8 -0
  73. package/widgets/magic-time-field/widget.js +142 -0
  74. package/widgets/magic-timer/styles.js +30 -0
  75. package/widgets/magic-timer/widget.js +162 -0
  76. package/widgets/magic-zen/styles.js +61 -0
  77. package/widgets/magic-zen/widget.js +42 -0
  78. package/widgets/main-tabs/styles.js +106 -0
  79. package/widgets/main-tabs/widget.js +23 -0
  80. package/widgets/menu/styles.js +156 -0
  81. package/widgets/menu/test-menu.html +154 -0
  82. package/widgets/menu/widget.js +575 -0
  83. package/widgets/movable/widget.js +80 -0
  84. package/widgets/splitter/styles.js +57 -0
  85. package/widgets/splitter/widget.js +40 -0
  86. package/widgets/tab-layout/styles.js +31 -0
  87. package/widgets/tab-layout/widget.js +59 -0
  88. package/widgets/with-computed-size/widget.js +52 -0
@@ -0,0 +1,58 @@
1
+ /******************************************************************************/
2
+
3
+ export default function styles() {
4
+ const disabledStyle = {
5
+ 'backgroundColor': 'color-mix(in srgb, var(--text-color), transparent 95%)',
6
+ 'color': 'color-mix(in srgb, var(--text-color), transparent 30%)',
7
+ '::placeholder': {
8
+ color: 'color-mix(in srgb, var(--text-color), transparent 80%)',
9
+ },
10
+ };
11
+
12
+ const colorPickerStyle = {
13
+ width: '32px',
14
+ height: '20px',
15
+ padding: '0px 2px',
16
+ };
17
+
18
+ const inputEdit = {
19
+ 'display': 'block',
20
+ // 'height': '40px',
21
+ 'width': '100%',
22
+ // 'minHeight': '1em', // For contenteditable
23
+ 'backgroundColor':
24
+ 'color-mix(in srgb, var(--field-background-color), transparent 20%)',
25
+ 'borderRadius': '5px',
26
+ 'border': '1px solid transparent',
27
+ 'padding': '7px 10px',
28
+ // 'fontSize': '14px',
29
+ 'fontSize': 'inherit',
30
+ 'fontWeight': 300,
31
+ 'color': 'var(--text-color)',
32
+ 'resize': 'vertical',
33
+ '::placeholder': {
34
+ color: 'color-mix(in srgb, var(--text-color), transparent 80%)',
35
+ // textTransform: 'uppercase',
36
+ fontWeight: 600,
37
+ },
38
+ ':focus': {
39
+ outline: 'none',
40
+ borderColor: 'color-mix(in srgb, var(--text-color), transparent 60%)',
41
+ // backgroundColor: 'rgba(255,255,255,0.2)',
42
+ fontWeight: 300,
43
+ },
44
+ '&[data-disabled=true]': disabledStyle,
45
+ '&:disabled': disabledStyle,
46
+ '&[type="color"]': colorPickerStyle,
47
+ '&[contenteditable]': {
48
+ minHeight: '54px', // 2 lines
49
+ cursor: 'text',
50
+ },
51
+ };
52
+
53
+ return {
54
+ inputEdit,
55
+ };
56
+ }
57
+
58
+ /******************************************************************************/
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+ import withC from 'goblin-laboratory/widgets/connect-helpers/with-c';
5
+ import MagicInput from '../magic-input/widget.js';
6
+
7
+ let inputCount = 0;
8
+
9
+ class MagicTextFieldNC extends Widget {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.styles = styles;
13
+ this.listId = `input-data-${inputCount++}`;
14
+ }
15
+
16
+ renderDataList() {
17
+ if (!this.props.dataList) {
18
+ return;
19
+ }
20
+ return (
21
+ <datalist id={this.listId}>
22
+ {this.props.dataList.map((value) => (
23
+ <option key={value} value={value} />
24
+ ))}
25
+ </datalist>
26
+ );
27
+ }
28
+
29
+ render() {
30
+ const {className = ''} = this.props;
31
+ return (
32
+ <>
33
+ <MagicInput
34
+ ref={this.props.inputRef}
35
+ className={this.styles.classNames.inputEdit + ' ' + className}
36
+ value={this.props.value}
37
+ onBlur={this.disableEdit}
38
+ onEnterKey={this.props.onEnterKey}
39
+ onKeyDown={this.props.onKeyDown}
40
+ onKeyUp={this.props.onKeyUp}
41
+ placeholder={this.props.placeholder}
42
+ changeMode={this.props.changeMode || 'blur'}
43
+ parse={this.props.parse}
44
+ format={this.props.format}
45
+ onChange={this.props.onChange}
46
+ onValidate={this.props.onValidate}
47
+ type={this.props.type}
48
+ step={this.props.step}
49
+ min={this.props.min}
50
+ max={this.props.max}
51
+ autoFocus={this.props.autoFocus}
52
+ selectAllOnFocus={this.props.selectAllOnFocus}
53
+ rows={this.props.rows}
54
+ autoRows={this.props.autoRows}
55
+ disabled={this.props.disabled}
56
+ emojiPicker={this.props.emojiPicker}
57
+ list={this.props.dataList ? this.listId : undefined}
58
+ />
59
+ {this.renderDataList()}
60
+ </>
61
+ );
62
+ }
63
+ }
64
+ const MagicTextField = withC(MagicTextFieldNC, {value: 'onChange'});
65
+ MagicTextField.displayName = 'MagicTextField';
66
+ export default MagicTextField;
@@ -0,0 +1,8 @@
1
+ export default function styles() {
2
+ const timeField = {
3
+ width: '79px',
4
+ };
5
+ return {
6
+ timeField,
7
+ };
8
+ }
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+ import withC from 'goblin-laboratory/widgets/connect-helpers/with-c';
5
+ import MagicTextField from '../magic-text-field/widget.js';
6
+ import {time as TimeConverters} from 'xcraft-core-converters';
7
+ import InputGroup from '../input-group/widget.js';
8
+ import MagicButton from '../magic-button/widget.js';
9
+ import Icon from '@mdi/react';
10
+ import {mdiClockOutline} from '@mdi/js';
11
+
12
+ class MagicTimeFieldNC extends Widget {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.styles = styles;
16
+ this.inputRef = this.props.inputRef || React.createRef();
17
+ }
18
+
19
+ get input() {
20
+ return this.inputRef.current;
21
+ }
22
+
23
+ static parseEdited(value) {
24
+ if (!value) {
25
+ return null;
26
+ }
27
+ const edited = TimeConverters.parseEdited(value);
28
+ return edited.value;
29
+ }
30
+
31
+ parse = (value) => {
32
+ const newValue = MagicTimeFieldNC.parseEdited(value);
33
+ if (this.props.required && !newValue) {
34
+ return TimeConverters.getNowCanonical();
35
+ }
36
+ return newValue;
37
+ };
38
+
39
+ format = (value) => {
40
+ if (!value) {
41
+ return '';
42
+ }
43
+ return TimeConverters.getDisplayed(value.split(/[.\-+Z]/, 1)[0]);
44
+ };
45
+
46
+ getPositionKind(position) {
47
+ // Value: h h : m m : s s
48
+ // Pos: 0 1 2 3 4 5 6 7 8
49
+ // Kind: 0 | 1 | 2
50
+ if (position <= 2) {
51
+ return 0;
52
+ }
53
+ if (position <= 5) {
54
+ return 1;
55
+ }
56
+ return 2;
57
+ }
58
+
59
+ getSelection(positionKind) {
60
+ // Kind: 0 | 1 | 2
61
+ // Pos: 0 1 2 3 4 5 6 7 8
62
+ // Value: h h : m m : s s
63
+ if (positionKind === 0) {
64
+ return [0, 2];
65
+ }
66
+ if (positionKind === 1) {
67
+ return [3, 5];
68
+ }
69
+ return [6, 8];
70
+ }
71
+
72
+ handleKeyDown = (event) => {
73
+ this.props.onKeyDown?.(event);
74
+
75
+ if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
76
+ const {value, selectionStart, selectionEnd} = event.target;
77
+ const cursorPosition =
78
+ selectionStart < 2
79
+ ? selectionStart
80
+ : (selectionStart + selectionEnd) / 2;
81
+ const step = event.shiftKey ? 10 : 1;
82
+ const direction = event.key === 'ArrowUp' ? 1 : -1;
83
+ const result = TimeConverters.incEdited(
84
+ value,
85
+ cursorPosition,
86
+ direction,
87
+ step
88
+ );
89
+ if (result.edited) {
90
+ this.input.changeAndSelect(
91
+ result.edited,
92
+ result.selectionStart,
93
+ result.selectionEnd
94
+ );
95
+ }
96
+ event.preventDefault();
97
+ }
98
+
99
+ if (event.ctrlKey && event.key === 'ArrowRight') {
100
+ const {value, selectionEnd} = event.target;
101
+ const positionKind = this.getPositionKind(selectionEnd);
102
+ const lastKind = 1;
103
+ const newKind = positionKind < lastKind ? positionKind + 1 : lastKind;
104
+ this.input.htmlInput.setSelectionRange(
105
+ ...this.getSelection(newKind, value.length)
106
+ );
107
+ event.preventDefault();
108
+ }
109
+ if (event.ctrlKey && event.key === 'ArrowLeft') {
110
+ const {value, selectionStart} = event.target;
111
+ const positionKind = this.getPositionKind(selectionStart);
112
+ const newKind = positionKind > 0 ? positionKind - 1 : 0;
113
+ this.input.htmlInput.setSelectionRange(
114
+ ...this.getSelection(newKind, value.length)
115
+ );
116
+ event.preventDefault();
117
+ }
118
+ };
119
+
120
+ render() {
121
+ const {className = '', ...props} = this.props;
122
+ return (
123
+ <InputGroup>
124
+ <MagicTextField
125
+ inputRef={this.inputRef}
126
+ format={this.format}
127
+ parse={this.parse}
128
+ {...props}
129
+ onKeyDown={this.handleKeyDown}
130
+ className={this.styles.classNames.timeField + ' ' + className}
131
+ />
132
+ <MagicButton disabled>
133
+ <Icon path={mdiClockOutline} size={0.8} />
134
+ </MagicButton>
135
+ </InputGroup>
136
+ );
137
+ }
138
+ }
139
+ const MagicTimeField = withC(MagicTimeFieldNC, {value: 'onChange'});
140
+ MagicTimeField.displayName = 'MagicTimeField';
141
+
142
+ export default MagicTimeField;
@@ -0,0 +1,30 @@
1
+ /******************************************************************************/
2
+
3
+ export default function styles() {
4
+ const timer = {
5
+ 'display': 'inline-flex',
6
+ 'flexDirection': 'row',
7
+ 'alignItems': 'center',
8
+
9
+ '& .button': {
10
+ 'lineHeight': '10px',
11
+ 'minHeight': '25px',
12
+ 'minWidth': '24px',
13
+ 'fontSize': '24px',
14
+ 'overflow': 'hidden',
15
+ '& > svg': {
16
+ margin: '-6px',
17
+ },
18
+ },
19
+
20
+ '& .text': {
21
+ marginLeft: '7px',
22
+ },
23
+ };
24
+
25
+ return {
26
+ timer,
27
+ };
28
+ }
29
+
30
+ /******************************************************************************/
@@ -0,0 +1,162 @@
1
+ import * as styles from './styles.js';
2
+ import React from 'react';
3
+ import Widget from 'goblin-laboratory/widgets/widget';
4
+ import withC from 'goblin-laboratory/widgets/connect-helpers/with-c';
5
+ import {datetime as DateTimeConverters} from 'xcraft-core-converters';
6
+ import MagicButton from '../magic-button/widget.js';
7
+ import Icon from '@mdi/react';
8
+ import {mdiPlay, mdiPause} from '@mdi/js';
9
+
10
+ export class TimerUpdater extends Widget {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.state = {
14
+ timerValue: '',
15
+ };
16
+ this.updateTimer = this.updateTimer.bind(this);
17
+ }
18
+
19
+ static getDerivedStateFromProps(props) {
20
+ return {
21
+ timerValue: props.start ? TimerUpdater.getCurrentValue(props.start) : '',
22
+ };
23
+ }
24
+
25
+ componentDidMount() {
26
+ this.startStopTimer();
27
+ }
28
+
29
+ componentDidUpdate() {
30
+ this.startStopTimer();
31
+ }
32
+
33
+ componentWillUnmount() {
34
+ this.stopTimer();
35
+ }
36
+
37
+ static getCurrentValue(start) {
38
+ const now = new Date().toISOString();
39
+ const value = DateTimeConverters.getDisplayedBetweenToDatetimes(start, now);
40
+ return value;
41
+ }
42
+
43
+ updateTimer() {
44
+ this.setState({
45
+ timerValue: TimerUpdater.getCurrentValue(this.props.start),
46
+ });
47
+ }
48
+
49
+ stopTimer() {
50
+ if (this.timer) {
51
+ clearInterval(this.timer);
52
+ this.timer = null;
53
+ }
54
+ }
55
+
56
+ startTimer() {
57
+ if (!this.timer) {
58
+ this.timer = setInterval(this.updateTimer, 1000);
59
+ }
60
+ }
61
+
62
+ startStopTimer() {
63
+ if (this.props.start) {
64
+ this.startTimer();
65
+ } else {
66
+ this.stopTimer();
67
+ }
68
+ }
69
+
70
+ render() {
71
+ return this.props.children(this.state.timerValue);
72
+ }
73
+ }
74
+
75
+ class MagicTimerNC extends Widget {
76
+ constructor() {
77
+ super(...arguments);
78
+ this.styles = styles;
79
+
80
+ this.handleClick = this.handleClick.bind(this);
81
+ }
82
+
83
+ handleClick() {
84
+ if (this.props.start) {
85
+ this.stop();
86
+ } else {
87
+ this.start();
88
+ }
89
+ }
90
+
91
+ start() {
92
+ const now = new Date().toISOString();
93
+ this.props.onStart?.(now);
94
+ }
95
+
96
+ stop() {
97
+ const now = new Date().toISOString();
98
+ this.props.onStop?.(now);
99
+ }
100
+
101
+ render() {
102
+ const {start, onStart, onStop, className = '', ...props} = this.props;
103
+ return (
104
+ <div
105
+ {...props}
106
+ className={this.styles.classNames.timer + ' ' + className}
107
+ >
108
+ <MagicButton
109
+ className="button"
110
+ onClick={this.handleClick}
111
+ enabled={Boolean(start)}
112
+ big
113
+ >
114
+ {start ? (
115
+ <Icon path={mdiPause} size={0.8} />
116
+ ) : (
117
+ <Icon path={mdiPlay} size={0.8} />
118
+ )}
119
+ </MagicButton>
120
+ <TimerUpdater start={this.props.start}>
121
+ {(timerValue) =>
122
+ timerValue && <span className="text">+&nbsp;{timerValue}</span>
123
+ }
124
+ </TimerUpdater>
125
+ </div>
126
+ );
127
+ }
128
+ }
129
+
130
+ // export class MagicTimerTest extends Widget {
131
+ // constructor() {
132
+ // super(...arguments);
133
+ // this.state = {
134
+ // start: null,
135
+ // duration: 0,
136
+ // };
137
+ // this.handleChange = this.handleChange.bind(this);
138
+ // }
139
+
140
+ // handleChange(state) {
141
+ // this.setState(state);
142
+ // }
143
+
144
+ // componentDidUpdate() {
145
+ // console.log(this.state);
146
+ // }
147
+
148
+ // render() {
149
+ // return (
150
+ // <MagicTimerNC
151
+ // onChange={this.handleChange}
152
+ // {...this.state}
153
+ // {...this.props}
154
+ // />
155
+ // );
156
+ // }
157
+ // }
158
+
159
+ const MagicTimer = withC(MagicTimerNC);
160
+ MagicTimer.displayName = 'MagicTimer';
161
+
162
+ export default MagicTimer;
@@ -0,0 +1,61 @@
1
+ export default function styles() {
2
+ const zenDialog = {
3
+ width: '100%',
4
+ height: '100%',
5
+ maxWidth: '100%',
6
+ maxHeight: '100%',
7
+ padding: 0,
8
+ border: 'none',
9
+ };
10
+
11
+ const zen = {
12
+ width: '100%',
13
+ height: '100%',
14
+ padding: '15px',
15
+ // '--border-radius': '8px',
16
+ // 'background': 'transparent',
17
+ // 'borderRadius': '8px',
18
+ // 'boxShadow': '0 4px 30px rgba(0, 0, 0, 0.1)',
19
+ // 'backdropFilter': 'blur(50px) saturate(100%)',
20
+ // 'border':
21
+ // '1px solid color-mix(in srgb, var(--text-color), transparent 78%)',
22
+ };
23
+
24
+ const key = {
25
+ border: '1px solid var(--text-color)',
26
+ padding: '2px',
27
+ };
28
+
29
+ const notice = {
30
+ 'pointerEvents': 'none',
31
+ 'opacity': 0,
32
+ 'zIndex': 2,
33
+ 'borderRadius': '10px',
34
+ 'position': 'fixed',
35
+ 'top': '20px',
36
+ 'left': '50%',
37
+ 'transform': 'translate(-50%, -10%)',
38
+ 'fontSize': '24px',
39
+ 'padding': '15px',
40
+ 'textAlign': 'center',
41
+ 'backgroundColor': 'rgba(0,0,0,0.5)',
42
+ '--text-color': 'white',
43
+ 'color': 'var(--text-color)',
44
+ 'animationDirection': 'forwards',
45
+ 'animationDuration': '3s',
46
+ 'animationName': {
47
+ '0%': {opacity: 1},
48
+ '50%': {opacity: 1},
49
+ '100%': {opacity: 0},
50
+ },
51
+ };
52
+
53
+ return {
54
+ zen,
55
+ zenDialog,
56
+ notice,
57
+ key,
58
+ };
59
+ }
60
+
61
+ /******************************************************************************/
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import {createPortal} from 'react-dom';
3
+ import Widget from 'goblin-laboratory/widgets/widget';
4
+ import * as styles from './styles.js';
5
+ import Dialog from '../dialog/widget.js';
6
+ import MagicBackground from '../magic-background/widget.js';
7
+ import MagicDiv from '../magic-div/widget.js';
8
+
9
+ export default class MagicZen extends Widget {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.styles = styles;
13
+ }
14
+
15
+ render() {
16
+ if (!this.props.active) {
17
+ return this.props.children;
18
+ }
19
+
20
+ const {className = ''} = this.props;
21
+
22
+ return createPortal(
23
+ <Dialog
24
+ className={this.styles.classNames.zenDialog}
25
+ modal={true}
26
+ open
27
+ onClose={this.props.onClose}
28
+ >
29
+ <MagicBackground>
30
+ <div className={this.styles.classNames.notice}>
31
+ Appuyez sur <span className={this.styles.classNames.key}>ESC</span>{' '}
32
+ pour quitter le mode zen
33
+ </div>
34
+ <MagicDiv className={this.styles.classNames.zen + ' ' + className}>
35
+ {this.props.children}
36
+ </MagicDiv>
37
+ </MagicBackground>
38
+ </Dialog>,
39
+ document.getElementById('root')
40
+ );
41
+ }
42
+ }
@@ -0,0 +1,106 @@
1
+ export default function styles() {
2
+ const mainTabs = {
3
+ // 'color': 'white',
4
+ 'padding': '4px 7px',
5
+ 'display': 'flex',
6
+ 'flexDirection': 'row',
7
+ 'flexWrap': 'wrap',
8
+ 'gap': '4px',
9
+
10
+ '&:focus-visible': {
11
+ 'outline': 'none',
12
+
13
+ '& > [data-active=true]': {
14
+ borderColor: 'var(--text-color)',
15
+ boxShadow: '0px 0px 3px var(--text-color)',
16
+ },
17
+ },
18
+
19
+ '& > *': {
20
+ 'padding': '10px 8px 8px 12px',
21
+ 'border':
22
+ '1px solid color-mix(in srgb, var(--text-color), transparent 75%)',
23
+ 'borderRadius': '3px',
24
+ 'backgroundColor':
25
+ 'color-mix(in srgb, var(--text-color), transparent 87.5%)',
26
+ 'backdropFilter': 'blur(10px)',
27
+
28
+ 'display': 'inline-flex',
29
+ 'flexDirection': 'row',
30
+ 'alignItems': 'center',
31
+ 'maxWidth': '300px',
32
+
33
+ '&[data-active=true]': {
34
+ 'backgroundColor': 'rgba(255,255,255,0.25)',
35
+ 'borderColor': 'color-mix(in srgb, var(--text-color), transparent 50%)',
36
+ ':hover': {
37
+ backgroundColor:
38
+ 'color-mix(in srgb, rgba(255,255,255,0.25), var(--accent-color) 15%)',
39
+ },
40
+ '@media (prefers-color-scheme: light)': {
41
+ 'backgroundColor': 'rgba(248, 241, 248, 0.85)',
42
+ 'borderColor':
43
+ 'color-mix(in srgb, var(--text-color), transparent 70%)',
44
+ ':hover': {
45
+ backgroundColor:
46
+ 'color-mix(in srgb, rgba(248, 241, 248, 0.85), var(--accent-color) 15%)',
47
+ },
48
+ },
49
+ },
50
+
51
+ '&[data-highlighted=true]': {
52
+ 'backgroundColor': 'rgba(255,177,60,0.45)',
53
+ 'borderColor': 'rgba(255,153,0,0.7)',
54
+ 'boxShadow': '0px 0px 5px rgba(255,153,0,0.7)',
55
+ ':hover': {
56
+ backgroundColor: 'rgb(255,185,82,0.6)',
57
+ borderColor: 'rgba(255,153,0,0.85)',
58
+ },
59
+ },
60
+
61
+ '&[data-highlighted=true][data-active=true]': {
62
+ 'backgroundColor':
63
+ 'color-mix(in srgb, rgba(255,255,255,0.25), rgba(255,177,60,0.45) 25%)',
64
+ 'borderColor':
65
+ 'color-mix(in srgb, color-mix(in srgb, var(--text-color), transparent 50%), rgba(255,153,0,0.7) 25%)',
66
+ ':hover': {
67
+ backgroundColor:
68
+ 'color-mix(in srgb, color-mix(in srgb, rgba(255,255,255,0.25), rgba(255,177,60,0.45) 25%), var(--accent-color) 15%)',
69
+ borderColor:
70
+ 'color-mix(in srgb, var(--button-accent-color), transparent 10%)',
71
+ },
72
+ '@media (prefers-color-scheme: light)': {
73
+ 'backgroundColor':
74
+ 'color-mix(in srgb, rgba(248, 241, 248, 0.85), rgba(255,177,60,0.45) 25%)',
75
+ 'borderColor':
76
+ 'color-mix(in srgb, color-mix(in srgb, var(--text-color), transparent 70%), rgba(255,153,0,0.7) 25%)',
77
+ ':hover': {
78
+ backgroundColor:
79
+ 'color-mix(in srgb, color-mix(in srgb, rgba(248, 241, 248, 0.85), rgba(255,177,60,0.45) 25%), var(--accent-color) 15%)',
80
+ },
81
+ },
82
+ },
83
+
84
+ ':hover': {
85
+ backgroundColor:
86
+ 'color-mix(in srgb, var(--button-accent-color), transparent 70%)',
87
+ borderColor:
88
+ 'color-mix(in srgb, var(--button-accent-color), transparent 10%)',
89
+ },
90
+
91
+ ':active': {
92
+ opacity: 0.8,
93
+ },
94
+
95
+ '&:focus-visible': {
96
+ borderColor: 'var(--text-color)',
97
+ boxShadow: '0px 0px 3px var(--text-color)',
98
+ outline: 'none',
99
+ },
100
+ },
101
+ };
102
+
103
+ return {
104
+ mainTabs,
105
+ };
106
+ }
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+ import TabLayout from '../tab-layout/widget.js';
5
+
6
+ class MainTabs extends Widget {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.styles = styles;
10
+ }
11
+
12
+ render() {
13
+ const {className = '', ...props} = this.props;
14
+ return (
15
+ <TabLayout.Tabs
16
+ {...props}
17
+ className={this.styles.classNames.mainTabs + ' ' + className}
18
+ ></TabLayout.Tabs>
19
+ );
20
+ }
21
+ }
22
+
23
+ export default MainTabs;