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
package/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*.{js,jsx,json}]
4
+ indent_style = space
5
+ indent_size = 2
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
8
+ insert_final_newline = true
9
+ max_line_length = 80
package/.zou-flow ADDED
@@ -0,0 +1,2 @@
1
+ [update-version]
2
+ package-json = package.json
@@ -0,0 +1,65 @@
1
+ const js = require('@eslint/js');
2
+ const globals = require('globals');
3
+ const react = require('eslint-plugin-react');
4
+ const jsdoc = require('eslint-plugin-jsdoc');
5
+ const babel = require('@babel/eslint-plugin');
6
+ const prettier = require('eslint-config-prettier');
7
+ const babelParser = require('@babel/eslint-parser');
8
+
9
+ module.exports = [
10
+ js.configs.recommended,
11
+ react.configs.flat.recommended,
12
+ jsdoc.configs['flat/recommended'],
13
+ prettier,
14
+ {
15
+ languageOptions: {
16
+ parser: babelParser,
17
+ parserOptions: {
18
+ requireConfigFile: false, // Évite de devoir spécifier un fichier de configuration Babel
19
+ babelOptions: {
20
+ presets: ['@babel/preset-react'],
21
+ },
22
+ ecmaFeatures: {
23
+ jsx: true,
24
+ },
25
+ },
26
+ globals: {
27
+ ...globals.browser,
28
+ ...globals.node,
29
+ ...globals.es2022,
30
+ ...globals.mocha,
31
+ },
32
+ },
33
+ plugins: {
34
+ 'react': react,
35
+ 'jsdoc': jsdoc,
36
+ '@babel': babel,
37
+ },
38
+ rules: {
39
+ 'eqeqeq': 'error',
40
+ 'no-console': 'off',
41
+ 'react/display-name': 'off',
42
+ '@babel/no-unused-expressions': 'error', // Utilisation de règles spécifiques à Babel
43
+ 'no-unused-vars': [
44
+ 'error',
45
+ {
46
+ vars: 'all',
47
+ args: 'none',
48
+ ignoreRestSiblings: true,
49
+ destructuredArrayIgnorePattern: '^_',
50
+ },
51
+ ],
52
+ 'jsdoc/require-jsdoc': 'off',
53
+ 'jsdoc/require-param-description': 'off',
54
+ 'jsdoc/require-returns-description': 'off',
55
+ },
56
+ settings: {
57
+ react: {
58
+ version: 'detect',
59
+ },
60
+ jsdoc: {
61
+ mode: 'typescript',
62
+ },
63
+ },
64
+ },
65
+ ];
@@ -0,0 +1,7 @@
1
+ const {Elf} = require('xcraft-core-goblin');
2
+ const {
3
+ MagicNavigation,
4
+ MagicNavigationLogic,
5
+ } = require('./widgets/magic-navigation/service.js');
6
+
7
+ exports.xcraftCommands = Elf.birth(MagicNavigation, MagicNavigationLogic);
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "goblin-magic",
3
+ "version": "1.0.3",
4
+ "description": "goblin-magic",
5
+ "author": "",
6
+ "license": "MIT",
7
+ "config": {
8
+ "xcraft": {
9
+ "commands": true
10
+ }
11
+ },
12
+ "scripts": {
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ },
15
+ "dependencies": {
16
+ "lodash": "^4.17.21",
17
+ "xcraft-core-goblin": "^5.34.1",
18
+ "xcraft-core-shredder": "^5.3.2",
19
+ "xcraft-core-stones": "^0.4.13"
20
+ },
21
+ "devDependencies": {
22
+ "emoji-mart": "^5.6.0",
23
+ "@emoji-mart/data": "^1.2.1",
24
+ "@emoji-mart/react": "^1.1.1",
25
+ "@mdi/js": "^7.4.47",
26
+ "@mdi/react": "^1.6.1",
27
+ "goblin-laboratory": "^4.5.0",
28
+ "goblin-nabu": "^2.4.18",
29
+ "mousetrap": "^1.6.5",
30
+ "react": "^17.0.1",
31
+ "react-dom": "^17.0.1",
32
+ "react-splitter-layout": "^4.0.0",
33
+ "xcraft-core-converters": "^4.5.0",
34
+ "xcraft-core-utils": "^4.14.2",
35
+ "xcraft-dev-fontawesome": "^0.1.2",
36
+ "xcraft-dev-prettier": "^2.0.0",
37
+ "xcraft-dev-rules": "^4.4.2"
38
+ },
39
+ "overrides": {
40
+ "react-splitter-layout": {
41
+ "react": "^17.0.1"
42
+ }
43
+ },
44
+ "prettier": "xcraft-dev-prettier"
45
+ }
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import {createPortal} from 'react-dom';
4
+
5
+ export default class Dialog extends Widget {
6
+ constructor() {
7
+ super(...arguments);
8
+
9
+ /** @type {React.RefObject<HTMLDialogElement>} */
10
+ this.dialog = React.createRef();
11
+ }
12
+
13
+ componentDidMount() {
14
+ this.update();
15
+ }
16
+
17
+ componentDidUpdate() {
18
+ this.update();
19
+ }
20
+
21
+ close = () => {
22
+ this.dialog.current?.close();
23
+ };
24
+
25
+ handleClose = (event) => {
26
+ this.props.onClose?.(event);
27
+ event.stopPropagation();
28
+ };
29
+
30
+ handlePointerDown = (event) => {
31
+ this.props.onPointerDown?.(event);
32
+ if (event.target === this.dialog.current) {
33
+ this.closeEnabled = true;
34
+ } else {
35
+ this.closeEnabled = false;
36
+ }
37
+ };
38
+
39
+ handlePointerUp = (event) => {
40
+ this.props.onPointerUp?.(event);
41
+ if (this.closeEnabled && event.target === this.dialog.current) {
42
+ this.dialog.current.close();
43
+ }
44
+ this.closeEnabled = false;
45
+ };
46
+
47
+ update() {
48
+ if (this.props.open) {
49
+ if (!this.dialog.current?.open) {
50
+ if (this.props.modal) {
51
+ this.dialog.current?.showModal();
52
+ } else {
53
+ this.dialog.current?.show();
54
+ }
55
+ }
56
+ } else {
57
+ this.dialog.current?.close();
58
+ }
59
+ }
60
+
61
+ render() {
62
+ const {open, modal, portal = false, ...props} = this.props;
63
+ const dialog = (
64
+ <dialog
65
+ {...props}
66
+ ref={this.dialog}
67
+ onClose={this.handleClose}
68
+ onPointerDown={this.handlePointerDown}
69
+ onPointerUp={this.handlePointerUp}
70
+ />
71
+ );
72
+
73
+ if (portal) {
74
+ return createPortal(dialog, document.getElementById('root'));
75
+ }
76
+ return dialog;
77
+ }
78
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @param {HTMLElement} element
3
+ * @returns {boolean}
4
+ */
5
+ export default function elementHasDirectText(element) {
6
+ return [...element.childNodes].some(
7
+ (node) => node instanceof Text && node.textContent.trim() !== ''
8
+ );
9
+ }
@@ -0,0 +1,17 @@
1
+ import elementHasDirectText from './element-has-direct-text.js';
2
+ import isFlatElement from './is-flat-element.js';
3
+
4
+ /**
5
+ * @param {HTMLElement} element
6
+ * @param {HTMLElement} [stopAtElement]
7
+ * @returns {boolean}
8
+ */
9
+ export default function isEmptyAreaElement(element, stopAtElement) {
10
+ for (let e = element; e && e !== stopAtElement; e = e.parentElement) {
11
+ if (!isFlatElement(e) || elementHasDirectText(e)) {
12
+ // console.log(e);
13
+ return false;
14
+ }
15
+ }
16
+ return true;
17
+ }
@@ -0,0 +1,52 @@
1
+ const nonInteractiveTags = [
2
+ 'ARTICLE',
3
+ 'ASIDE',
4
+ 'BODY',
5
+ 'DIV',
6
+ 'FOOTER',
7
+ 'HEADER',
8
+ 'HGROUP',
9
+ 'HTML',
10
+ 'MAIN',
11
+ 'NAV',
12
+ 'SECTION',
13
+ ];
14
+
15
+ const interactiveRoles = [
16
+ 'button',
17
+ 'checkbox',
18
+ 'grid',
19
+ 'input',
20
+ 'menu',
21
+ 'option',
22
+ 'radio',
23
+ 'slider',
24
+ 'spinbutton',
25
+ 'switch',
26
+ 'table',
27
+ 'tree',
28
+ 'treegrid',
29
+ 'widget',
30
+ // More roles could be added
31
+ // see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles
32
+ ];
33
+
34
+ /**
35
+ * @param {HTMLElement} element
36
+ * @returns {boolean}
37
+ */
38
+ export function hasInteractiveRole(element) {
39
+ return element.role
40
+ ?.split(' ')
41
+ .some((role) => interactiveRoles.includes(role));
42
+ }
43
+
44
+ /**
45
+ * @param {HTMLElement} element
46
+ * @returns {boolean}
47
+ */
48
+ export default function isFlatElement(element) {
49
+ return (
50
+ nonInteractiveTags.includes(element.tagName) && !hasInteractiveRole(element)
51
+ );
52
+ }
@@ -0,0 +1,34 @@
1
+ export function getPlatform(ua) {
2
+ if (!ua) {
3
+ return null;
4
+ }
5
+ ua = ua.toLowerCase();
6
+ if (ua.includes('linux')) {
7
+ return 'linux';
8
+ }
9
+ if (ua.includes('windows')) {
10
+ return 'windows';
11
+ }
12
+ if (ua.includes('mac os')) {
13
+ return 'macos';
14
+ }
15
+ return null;
16
+ }
17
+
18
+ export default function getModifiers(event) {
19
+ const platform = getPlatform(navigator.userAgent);
20
+ if (platform === 'macos') {
21
+ return {
22
+ shiftKey: event.shiftKey,
23
+ ctrlKey: event.metaKey,
24
+ altKey: event.altKey,
25
+ metaKey: event.ctrlKey,
26
+ };
27
+ }
28
+ return {
29
+ shiftKey: event.shiftKey,
30
+ ctrlKey: event.ctrlKey,
31
+ altKey: event.altKey,
32
+ metaKey: event.metaKey,
33
+ };
34
+ }
@@ -0,0 +1,74 @@
1
+ export default function styles() {
2
+ const inputGroup = {
3
+ 'display': 'inline-flex',
4
+ 'flexDirection': 'row',
5
+ 'borderRadius': '5px',
6
+ 'backgroundColor':
7
+ 'color-mix(in srgb, var(--field-background-color), transparent 20%)',
8
+ 'outline':
9
+ '1px solid color-mix(in srgb, var(--text-color), transparent 60%)',
10
+ 'outlineOffset': '-1px',
11
+
12
+ '& > input': {
13
+ backgroundColor: 'transparent',
14
+ paddingRight: '2px',
15
+ border: 'none',
16
+ },
17
+
18
+ '& > :nth-last-child(n + 2 of :not(dialog))': {
19
+ 'borderTopRightRadius': 0,
20
+ 'borderBottomRightRadius': 0,
21
+ '&.button:not(:not(:disabled):hover)': {
22
+ borderRightColor:
23
+ 'color-mix(in srgb, var(--text-color), transparent 70%)',
24
+ },
25
+ },
26
+
27
+ '& > :nth-child(n + 2 of :not(dialog))': {
28
+ 'borderTopLeftRadius': 0,
29
+ 'borderBottomLeftRadius': 0,
30
+ '&.button:not(:not(:disabled):hover)': {
31
+ borderLeftColor:
32
+ 'color-mix(in srgb, var(--text-color), transparent 70%)',
33
+ },
34
+ },
35
+
36
+ '& > :hover': {
37
+ zIndex: 0, // Above other buttons in the group
38
+ },
39
+
40
+ '& > .button': {
41
+ '&:not(:hover)': {
42
+ borderColor: 'transparent',
43
+ },
44
+
45
+ '&:disabled': {
46
+ 'opacity': 1,
47
+ '&:hover': {
48
+ backgroundColor:
49
+ 'color-mix(in srgb, var(--button-background-color), transparent 80%)',
50
+ borderColor: 'transparent',
51
+ },
52
+ },
53
+
54
+ '&[data-simple=true]': {
55
+ 'borderLeft': 'none',
56
+ 'borderRight': 'none',
57
+ 'color': 'color-mix(in srgb, var(--text-color), transparent 60%)',
58
+ '&:hover': {
59
+ color: 'inherit',
60
+ backgroundColor: 'transparent',
61
+ borderColor: 'transparent',
62
+ },
63
+ },
64
+ },
65
+
66
+ '&:focus-within': {
67
+ outlineColor: 'color-mix(in srgb, var(--text-color), transparent 40%)',
68
+ },
69
+ };
70
+
71
+ return {
72
+ inputGroup,
73
+ };
74
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+
5
+ class InputGroup extends Widget {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.styles = styles;
9
+ }
10
+
11
+ render() {
12
+ const {className = '', children, ...props} = this.props;
13
+ return (
14
+ <div
15
+ {...props}
16
+ className={this.styles.classNames.inputGroup + ' ' + className}
17
+ >
18
+ {children}
19
+ </div>
20
+ );
21
+ }
22
+ }
23
+
24
+ export default InputGroup;
@@ -0,0 +1,45 @@
1
+ /******************************************************************************/
2
+ export const propNames = ['selected', 'disabled', 'size'];
3
+ export default function styles(theme, props) {
4
+ let size = 16;
5
+ if (props.size) {
6
+ size = props.size;
7
+ }
8
+ let hoverSize = size + 2;
9
+ const action = {
10
+ display: 'inline-block',
11
+ fontSize: `${size}px`,
12
+ margin: `${size / 4}px`,
13
+ fontWeight: 'bold',
14
+ // textTransform: 'uppercase',
15
+ // color: '#fff',
16
+ textDecoration: 'none',
17
+ transition: 'font-size 0.1s ease-in-out',
18
+ cursor: 'default',
19
+ };
20
+
21
+ const text = {
22
+ ':hover': {
23
+ fontSize: `${hoverSize}px`,
24
+ lineHeight: '1em',
25
+ },
26
+ };
27
+
28
+ if (props.selected) {
29
+ action.textShadow = '0 0 20px var(--text-color)';
30
+ text[':hover'] = null;
31
+ }
32
+
33
+ if (props.disabled) {
34
+ action.color = 'color-mix(in srgb, var(--text-color), transparent 40%)';
35
+ action.userSelect = 'none';
36
+ text[':hover'] = null;
37
+ }
38
+
39
+ return {
40
+ action,
41
+ text,
42
+ };
43
+ }
44
+
45
+ /******************************************************************************/
@@ -0,0 +1,44 @@
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.js';
5
+
6
+ class MagicActionNC extends Widget {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.styles = styles;
10
+ this.doCmd = this.doCmd.bind(this);
11
+ }
12
+
13
+ doCmd() {
14
+ let [serviceId, action] = this.props.cmd.split('.');
15
+ this.doFor(serviceId, action, this.props.arguments || {});
16
+ }
17
+
18
+ togglePanel() {
19
+ this.setState({hidden: !this.state.hidden});
20
+ }
21
+
22
+ render() {
23
+ const {disabled} = this.props;
24
+
25
+ const baseProps = {};
26
+ if (!disabled) {
27
+ baseProps.onClick = this.props.onClick || this.doCmd;
28
+ }
29
+
30
+ return (
31
+ <div>
32
+ <span className={this.styles.classNames.action} {...baseProps}>
33
+ <span className={this.styles.classNames.text}>{this.props.text}</span>
34
+ </span>
35
+ </div>
36
+ );
37
+ }
38
+ }
39
+
40
+ /******************************************************************************/
41
+
42
+ const MagicAction = withC(MagicActionNC);
43
+
44
+ export default MagicAction;
@@ -0,0 +1,81 @@
1
+ import BG_MILK from './bg-milkyway.png';
2
+ import BG_WHITE from './bg-white.png';
3
+
4
+ /******************************************************************************/
5
+
6
+ const images = {
7
+ milk: BG_MILK,
8
+ white: BG_WHITE,
9
+ };
10
+
11
+ window.CSS.registerProperty({
12
+ name: '--aurora-color',
13
+ syntax: '<color>',
14
+ inherits: false,
15
+ initialValue: `transparent`,
16
+ });
17
+
18
+ window.CSS.registerProperty({
19
+ name: '--space-dark',
20
+ inherits: false,
21
+ initialValue: `url(${BG_MILK})`,
22
+ });
23
+
24
+ window.CSS.registerProperty({
25
+ name: '--space-light',
26
+ inherits: false,
27
+ initialValue: `url(${BG_WHITE})`,
28
+ });
29
+
30
+ export const propNames = [
31
+ 'useBackgroundColor',
32
+ 'backgroundColor',
33
+ 'plainColor',
34
+ ];
35
+ export default function styles(theme, props) {
36
+ const {plainColor} = props;
37
+
38
+ const main = {
39
+ '--space-dark': plainColor ? '#0D1D3C' : `url(${images['milk']})`,
40
+ '--space-light': plainColor ? '#CDDFEC' : `url(${images['white']})`,
41
+ '--accent-color': `${props.backgroundColor || 'white'}`,
42
+ '--button-accent-color':
43
+ 'color-mix(in srgb, var(--accent-color), #ccc 40%)',
44
+ '--aurora-color': `transparent`,
45
+ 'height': '100vh',
46
+ 'width': '100vw',
47
+ 'display': 'flex',
48
+ 'flexDirection': 'column',
49
+ 'background': `linear-gradient(to bottom, transparent 40%, var(--aurora-color)), var(--space-dark)`,
50
+ 'backgroundSize': 'cover',
51
+ 'overflow': 'auto',
52
+ 'transition': '--space-dark 3s, --aurora-color 3s',
53
+
54
+ '@media (prefers-color-scheme: light)': {
55
+ // backgroundImage: `linear-gradient(170deg, rgba(207,255,245,1) 0%, rgba(201,216,247,1) 100%)`,
56
+ // backgroundImage: `linear-gradient(to bottom, transparent 40%, var(--aurora-color)), linear-gradient(170deg, rgba(234,255,251,1) 0%, rgba(243,247,255,1) 100%)`,
57
+ background: `linear-gradient(to bottom, transparent 40%, var(--aurora-color)), var(--space-light)`,
58
+ transition: '--space-light 3s, --aurora-color 3s',
59
+ },
60
+ };
61
+
62
+ if (props.useBackgroundColor) {
63
+ main[':hover'] = {
64
+ '--aurora-color': `${props.backgroundColor}42`,
65
+ };
66
+ }
67
+
68
+ const proto = {
69
+ textShadow: 'rgb(179 150 177 / 70%) -2px 0px 40px',
70
+ color: 'rgb(0 0 0)',
71
+ fontSize: '6em',
72
+ textAlign: 'center',
73
+ };
74
+
75
+ return {
76
+ main,
77
+ proto,
78
+ };
79
+ }
80
+
81
+ /******************************************************************************/
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+
5
+ /******************************************************************************/
6
+ export default class MagicBackground extends Widget {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.styles = styles;
10
+ }
11
+
12
+ render() {
13
+ return (
14
+ <div className={this.styles.classNames.main}>
15
+ {/* <div className={this.styles.classNames.proto}></div> */}
16
+ {this.props.children}
17
+ </div>
18
+ );
19
+ }
20
+ }
@@ -0,0 +1,10 @@
1
+ export default function styles() {
2
+ const magicBox = {
3
+ display: 'flex',
4
+ flexDirection: 'column',
5
+ };
6
+
7
+ return {
8
+ magicBox,
9
+ };
10
+ }
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import * as styles from './styles.js';
4
+ import MagicDiv from '../magic-div/widget.js';
5
+ import MagicScroll from '../magic-scroll/widget.js';
6
+
7
+ class MagicBox extends Widget {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.styles = styles;
11
+ }
12
+
13
+ render() {
14
+ const {className = '', children, ...props} = this.props;
15
+ return (
16
+ <MagicDiv
17
+ {...props}
18
+ className={this.styles.classNames.magicBox + ' ' + className}
19
+ >
20
+ <MagicScroll>{children}</MagicScroll>
21
+ </MagicDiv>
22
+ );
23
+ }
24
+ }
25
+
26
+ /******************************************************************************/
27
+
28
+ export default MagicBox;