senangwebs-aframe-editor 1.6.5
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/.babelrc +3 -0
- package/.editorconfig +12 -0
- package/.eslintignore +2 -0
- package/.eslintrc +40 -0
- package/.github/workflows/ci.yml +39 -0
- package/.husky/pre-commit +4 -0
- package/.prettierignore +1 -0
- package/.prettierrc.json +5 -0
- package/.stylelintrc +12 -0
- package/LICENSE +21 -0
- package/README.md +75 -0
- package/assets/gltf.svg +49 -0
- package/dist/aframe-inspector.js +106250 -0
- package/dist/aframe-inspector.js.map +1 -0
- package/dist/aframe-inspector.min.js +29040 -0
- package/dist/aframe-inspector.min.js.LICENSE.txt +56 -0
- package/dist/aframe-inspector.min.js.map +1 -0
- package/examples/360video.html +48 -0
- package/examples/colors.html +18 -0
- package/examples/controllers.html +60 -0
- package/examples/embedded-zoom.html +78 -0
- package/examples/embedded.html +79 -0
- package/examples/empty.html +13 -0
- package/examples/index-aframe.html +66 -0
- package/examples/index.html +71 -0
- package/examples/supercraft.html +6 -0
- package/index.html +8 -0
- package/package.json +84 -0
- package/senangwebs-webverse-editor.png +0 -0
- package/src/components/AwesomeIcon.js +53 -0
- package/src/components/Collapsible.js +57 -0
- package/src/components/EntityRepresentation.js +83 -0
- package/src/components/Main.js +222 -0
- package/src/components/__tests__/Collapsible.test.js +30 -0
- package/src/components/components/AddComponent.js +104 -0
- package/src/components/components/CommonComponents.js +160 -0
- package/src/components/components/Component.js +151 -0
- package/src/components/components/ComponentsContainer.js +52 -0
- package/src/components/components/DefaultComponents.js +1 -0
- package/src/components/components/Mixins.js +83 -0
- package/src/components/components/PropertyRow.js +145 -0
- package/src/components/components/Sidebar.js +51 -0
- package/src/components/icons/BackViewIcon.js +27 -0
- package/src/components/icons/BottomViewIcon.js +26 -0
- package/src/components/icons/FrontViewIcon.js +23 -0
- package/src/components/icons/LeftViewIcon.js +24 -0
- package/src/components/icons/PerspectiveIcon.js +23 -0
- package/src/components/icons/PrimitiveBoxIcon.js +143 -0
- package/src/components/icons/PrimitiveConeIcon.js +44 -0
- package/src/components/icons/PrimitiveCylinderIcon.js +51 -0
- package/src/components/icons/PrimitiveEmptyEntityIcon.js +78 -0
- package/src/components/icons/PrimitiveImageIcon.js +86 -0
- package/src/components/icons/PrimitiveLightIcon.js +107 -0
- package/src/components/icons/PrimitivePlaneIcon.js +87 -0
- package/src/components/icons/PrimitiveSphereIcon.js +39 -0
- package/src/components/icons/PrimitiveTextIcon.js +89 -0
- package/src/components/icons/PrimitiveTorusIcon.js +31 -0
- package/src/components/icons/RightViewIcon.js +24 -0
- package/src/components/icons/TopViewIcon.js +24 -0
- package/src/components/modals/Modal.js +107 -0
- package/src/components/modals/ModalHelp.js +97 -0
- package/src/components/modals/ModalPrimitive.js +114 -0
- package/src/components/modals/ModalTextures.js +430 -0
- package/src/components/scenegraph/Entity.js +142 -0
- package/src/components/scenegraph/SceneGraph.js +337 -0
- package/src/components/scenegraph/Toolbar.js +147 -0
- package/src/components/viewport/CameraToolbar.js +122 -0
- package/src/components/viewport/TransformToolbar.js +102 -0
- package/src/components/viewport/ViewportHUD.js +33 -0
- package/src/components/widgets/BooleanWidget.js +49 -0
- package/src/components/widgets/ColorWidget.js +89 -0
- package/src/components/widgets/InputWidget.js +42 -0
- package/src/components/widgets/NumberWidget.js +179 -0
- package/src/components/widgets/SelectWidget.js +58 -0
- package/src/components/widgets/TextureWidget.js +252 -0
- package/src/components/widgets/Vec2Widget.js +55 -0
- package/src/components/widgets/Vec3Widget.js +58 -0
- package/src/components/widgets/Vec4Widget.js +61 -0
- package/src/components/widgets/index.js +9 -0
- package/src/index.js +301 -0
- package/src/lib/EditorControls.js +336 -0
- package/src/lib/Events.js +6 -0
- package/src/lib/TransformControls.js +1365 -0
- package/src/lib/assetsLoader.js +43 -0
- package/src/lib/assetsUtils.js +30 -0
- package/src/lib/cameras.js +121 -0
- package/src/lib/entity.js +556 -0
- package/src/lib/history.js +30 -0
- package/src/lib/raycaster.js +129 -0
- package/src/lib/shortcuts.js +211 -0
- package/src/lib/utils.js +118 -0
- package/src/lib/viewport.js +268 -0
- package/src/style/components.styl +275 -0
- package/src/style/entity.styl +22 -0
- package/src/style/help.styl +40 -0
- package/src/style/index.styl +358 -0
- package/src/style/lib.styl +41 -0
- package/src/style/primitiveModal.styl +90 -0
- package/src/style/scenegraph.styl +173 -0
- package/src/style/select.styl +71 -0
- package/src/style/textureModal.styl +220 -0
- package/src/style/viewport.styl +168 -0
- package/src/style/widgets.styl +71 -0
- package/webpack.config.js +65 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { faClipboard, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
|
4
|
+
import { AwesomeIcon } from '../AwesomeIcon';
|
|
5
|
+
import PropertyRow from './PropertyRow';
|
|
6
|
+
import Collapsible from '../Collapsible';
|
|
7
|
+
import copy from 'clipboard-copy';
|
|
8
|
+
import { getComponentClipboardRepresentation } from '../../lib/entity';
|
|
9
|
+
import Events from '../../lib/Events';
|
|
10
|
+
|
|
11
|
+
const isSingleProperty = AFRAME.schema.isSingleProperty;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Single component.
|
|
15
|
+
*/
|
|
16
|
+
export default class Component extends React.Component {
|
|
17
|
+
static propTypes = {
|
|
18
|
+
component: PropTypes.any,
|
|
19
|
+
entity: PropTypes.object,
|
|
20
|
+
isCollapsed: PropTypes.bool,
|
|
21
|
+
name: PropTypes.string
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
constructor(props) {
|
|
25
|
+
super(props);
|
|
26
|
+
this.state = {
|
|
27
|
+
entity: this.props.entity,
|
|
28
|
+
name: this.props.name
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
componentDidMount() {
|
|
33
|
+
Events.on('entityupdate', (detail) => {
|
|
34
|
+
if (detail.entity !== this.props.entity) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (detail.component === this.props.name) {
|
|
38
|
+
this.forceUpdate();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static getDerivedStateFromProps(props, state) {
|
|
44
|
+
if (state.entity !== props.entity) {
|
|
45
|
+
return { entity: props.entity };
|
|
46
|
+
}
|
|
47
|
+
if (state.name !== props.name) {
|
|
48
|
+
return { name: props.name };
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
removeComponent = (event) => {
|
|
54
|
+
var componentName = this.props.name;
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
if (
|
|
57
|
+
confirm('Do you really want to remove component `' + componentName + '`?')
|
|
58
|
+
) {
|
|
59
|
+
this.props.entity.removeAttribute(componentName);
|
|
60
|
+
Events.emit('componentremove', {
|
|
61
|
+
entity: this.props.entity,
|
|
62
|
+
component: componentName
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Render propert(ies) of the component.
|
|
69
|
+
*/
|
|
70
|
+
renderPropertyRows = () => {
|
|
71
|
+
const componentData = this.props.component;
|
|
72
|
+
|
|
73
|
+
if (isSingleProperty(componentData.schema)) {
|
|
74
|
+
const componentName = this.props.name;
|
|
75
|
+
const schema = AFRAME.components[componentName.split('__')[0]].schema;
|
|
76
|
+
return (
|
|
77
|
+
<PropertyRow
|
|
78
|
+
key={componentName}
|
|
79
|
+
name={componentName}
|
|
80
|
+
schema={schema}
|
|
81
|
+
data={componentData.data}
|
|
82
|
+
componentname={componentName}
|
|
83
|
+
isSingle={true}
|
|
84
|
+
entity={this.props.entity}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return Object.keys(componentData.schema)
|
|
90
|
+
.sort()
|
|
91
|
+
.map((propertyName) => (
|
|
92
|
+
<PropertyRow
|
|
93
|
+
key={propertyName}
|
|
94
|
+
name={propertyName}
|
|
95
|
+
schema={componentData.schema[propertyName]}
|
|
96
|
+
data={componentData.data[propertyName]}
|
|
97
|
+
componentname={this.props.name}
|
|
98
|
+
isSingle={false}
|
|
99
|
+
entity={this.props.entity}
|
|
100
|
+
/>
|
|
101
|
+
));
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
render() {
|
|
105
|
+
let componentName = this.props.name;
|
|
106
|
+
let subComponentName = '';
|
|
107
|
+
if (componentName.indexOf('__') !== -1) {
|
|
108
|
+
subComponentName = componentName;
|
|
109
|
+
componentName = componentName.substr(0, componentName.indexOf('__'));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<Collapsible collapsed={this.props.isCollapsed}>
|
|
114
|
+
<div className="componentHeader collapsible-header">
|
|
115
|
+
<span
|
|
116
|
+
className="componentTitle"
|
|
117
|
+
title={subComponentName || componentName}
|
|
118
|
+
>
|
|
119
|
+
<span>{subComponentName || componentName}</span>
|
|
120
|
+
</span>
|
|
121
|
+
<div className="componentHeaderActions">
|
|
122
|
+
{/* <a
|
|
123
|
+
title="Copy to clipboard"
|
|
124
|
+
className="button"
|
|
125
|
+
onClick={(event) => {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
event.stopPropagation();
|
|
128
|
+
copy(
|
|
129
|
+
getComponentClipboardRepresentation(
|
|
130
|
+
this.state.entity,
|
|
131
|
+
(subComponentName || componentName).toLowerCase()
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
<AwesomeIcon icon={faClipboard} />
|
|
137
|
+
</a> */}
|
|
138
|
+
<a
|
|
139
|
+
title="Remove component"
|
|
140
|
+
className="button"
|
|
141
|
+
onClick={this.removeComponent}
|
|
142
|
+
>
|
|
143
|
+
<AwesomeIcon icon={faTrashAlt} />
|
|
144
|
+
</a>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
<div className="collapsible-content">{this.renderPropertyRows()}</div>
|
|
148
|
+
</Collapsible>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import AddComponent from './AddComponent';
|
|
4
|
+
import Component from './Component';
|
|
5
|
+
import CommonComponents from './CommonComponents';
|
|
6
|
+
import DEFAULT_COMPONENTS from './DefaultComponents';
|
|
7
|
+
import Events from '../../lib/Events';
|
|
8
|
+
|
|
9
|
+
export default class ComponentsContainer extends React.Component {
|
|
10
|
+
static propTypes = {
|
|
11
|
+
entity: PropTypes.object
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
componentDidMount() {
|
|
15
|
+
Events.on('entityupdate', (detail) => {
|
|
16
|
+
if (detail.entity !== this.props.entity) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (detail.component === 'mixin') {
|
|
20
|
+
this.forceUpdate();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
render() {
|
|
26
|
+
const entity = this.props.entity;
|
|
27
|
+
const components = entity ? entity.components : {};
|
|
28
|
+
const definedComponents = Object.keys(components).filter(function (key) {
|
|
29
|
+
return DEFAULT_COMPONENTS.indexOf(key) === -1;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const renderedComponents = definedComponents.sort().map(function (key) {
|
|
33
|
+
return (
|
|
34
|
+
<Component
|
|
35
|
+
isCollapsed={definedComponents.length > 2}
|
|
36
|
+
component={components[key]}
|
|
37
|
+
entity={entity}
|
|
38
|
+
key={key}
|
|
39
|
+
name={key}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className="components">
|
|
46
|
+
<CommonComponents entity={entity} />
|
|
47
|
+
<AddComponent entity={entity} />
|
|
48
|
+
{renderedComponents}
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default ['visible', 'position', 'scale', 'rotation'];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Select from 'react-select';
|
|
4
|
+
import Events from '../../lib/Events';
|
|
5
|
+
|
|
6
|
+
export default class Mixin extends React.Component {
|
|
7
|
+
static propTypes = {
|
|
8
|
+
entity: PropTypes.object.isRequired
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
constructor(props) {
|
|
12
|
+
super(props);
|
|
13
|
+
this.state = { mixins: this.getMixinValue() };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
componentDidUpdate(prevProps, prevState) {
|
|
17
|
+
if (this.props.entity === prevProps.entity) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
this.setState({ mixins: this.getMixinValue() });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
getMixinValue() {
|
|
24
|
+
return (this.props.entity.getAttribute('mixin') || '')
|
|
25
|
+
.split(/\s+/g)
|
|
26
|
+
.filter((v) => !!v)
|
|
27
|
+
.map((v) => ({ label: v, value: v }));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getMixinOptions = () => {
|
|
31
|
+
const mixinIds = this.props.entity.mixinEls.map(function (mixin) {
|
|
32
|
+
return mixin.id;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return Array.prototype.slice
|
|
36
|
+
.call(document.querySelectorAll('a-mixin'))
|
|
37
|
+
.filter(function (mixin) {
|
|
38
|
+
return mixinIds.indexOf(mixin.id) === -1;
|
|
39
|
+
})
|
|
40
|
+
.sort()
|
|
41
|
+
.map(function (mixin) {
|
|
42
|
+
return { value: mixin.id, label: mixin.id };
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
updateMixins = (value) => {
|
|
47
|
+
const entity = this.props.entity;
|
|
48
|
+
|
|
49
|
+
this.setState({ mixins: value });
|
|
50
|
+
const mixinStr = value.map((v) => v.value).join(' ');
|
|
51
|
+
entity.setAttribute('mixin', mixinStr);
|
|
52
|
+
|
|
53
|
+
Events.emit('entityupdate', {
|
|
54
|
+
component: 'mixin',
|
|
55
|
+
entity: entity,
|
|
56
|
+
property: '',
|
|
57
|
+
value: mixinStr
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
render() {
|
|
62
|
+
return (
|
|
63
|
+
<div className="mixinOptions">
|
|
64
|
+
<div className="propertyRow">
|
|
65
|
+
<span className="text">mixins</span>
|
|
66
|
+
<span className="mixinValue">
|
|
67
|
+
<Select
|
|
68
|
+
id="mixinSelect"
|
|
69
|
+
classNamePrefix="select"
|
|
70
|
+
options={this.getMixinOptions()}
|
|
71
|
+
isMulti={true}
|
|
72
|
+
placeholder="Add mixin..."
|
|
73
|
+
noResultsText="No mixins found"
|
|
74
|
+
onChange={this.updateMixins.bind(this)}
|
|
75
|
+
simpleValue
|
|
76
|
+
value={this.state.mixins}
|
|
77
|
+
/>
|
|
78
|
+
</span>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* eslint-disable no-prototype-builtins */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
|
|
6
|
+
import BooleanWidget from '../widgets/BooleanWidget';
|
|
7
|
+
import ColorWidget from '../widgets/ColorWidget';
|
|
8
|
+
import InputWidget from '../widgets/InputWidget';
|
|
9
|
+
import NumberWidget from '../widgets/NumberWidget';
|
|
10
|
+
import SelectWidget from '../widgets/SelectWidget';
|
|
11
|
+
import TextureWidget from '../widgets/TextureWidget';
|
|
12
|
+
import Vec4Widget from '../widgets/Vec4Widget';
|
|
13
|
+
import Vec3Widget from '../widgets/Vec3Widget';
|
|
14
|
+
import Vec2Widget from '../widgets/Vec2Widget';
|
|
15
|
+
import { updateEntity } from '../../lib/entity';
|
|
16
|
+
|
|
17
|
+
export default class PropertyRow extends React.Component {
|
|
18
|
+
static propTypes = {
|
|
19
|
+
componentname: PropTypes.string.isRequired,
|
|
20
|
+
data: PropTypes.oneOfType([
|
|
21
|
+
PropTypes.array.isRequired,
|
|
22
|
+
PropTypes.bool.isRequired,
|
|
23
|
+
PropTypes.number.isRequired,
|
|
24
|
+
PropTypes.object.isRequired,
|
|
25
|
+
PropTypes.string.isRequired
|
|
26
|
+
]),
|
|
27
|
+
entity: PropTypes.object.isRequired,
|
|
28
|
+
isSingle: PropTypes.bool.isRequired,
|
|
29
|
+
name: PropTypes.string.isRequired,
|
|
30
|
+
schema: PropTypes.object.isRequired
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
constructor(props) {
|
|
34
|
+
super(props);
|
|
35
|
+
this.id = props.componentname + ':' + props.name;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getWidget() {
|
|
39
|
+
const props = this.props;
|
|
40
|
+
const isMap =
|
|
41
|
+
props.componentname === 'material' &&
|
|
42
|
+
(props.name === 'envMap' || props.name === 'src');
|
|
43
|
+
let type = props.schema.type;
|
|
44
|
+
if (props.componentname === 'animation' && props.name === 'loop') {
|
|
45
|
+
// fix wrong number type for animation loop property
|
|
46
|
+
type = 'boolean';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const value =
|
|
50
|
+
props.schema.type === 'selector'
|
|
51
|
+
? props.entity.getDOMAttribute(props.componentname)?.[props.name]
|
|
52
|
+
: props.data;
|
|
53
|
+
|
|
54
|
+
const widgetProps = {
|
|
55
|
+
componentname: props.componentname,
|
|
56
|
+
entity: props.entity,
|
|
57
|
+
isSingle: props.isSingle,
|
|
58
|
+
name: props.name,
|
|
59
|
+
onChange: function (name, value) {
|
|
60
|
+
updateEntity(
|
|
61
|
+
props.entity,
|
|
62
|
+
props.componentname,
|
|
63
|
+
!props.isSingle ? props.name : '',
|
|
64
|
+
value
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
value: value
|
|
68
|
+
};
|
|
69
|
+
const numberWidgetProps = {
|
|
70
|
+
min: props.schema.hasOwnProperty('min') ? props.schema.min : -Infinity,
|
|
71
|
+
max: props.schema.hasOwnProperty('max') ? props.schema.max : Infinity
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (props.schema.oneOf && props.schema.oneOf.length > 0) {
|
|
75
|
+
return <SelectWidget {...widgetProps} options={props.schema.oneOf} />;
|
|
76
|
+
}
|
|
77
|
+
if (type === 'map' || isMap) {
|
|
78
|
+
return <TextureWidget {...widgetProps} />;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
switch (type) {
|
|
82
|
+
case 'number': {
|
|
83
|
+
return <NumberWidget {...widgetProps} {...numberWidgetProps} />;
|
|
84
|
+
}
|
|
85
|
+
case 'int': {
|
|
86
|
+
return (
|
|
87
|
+
<NumberWidget {...widgetProps} {...numberWidgetProps} precision={0} />
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
case 'vec2': {
|
|
91
|
+
return <Vec2Widget {...widgetProps} />;
|
|
92
|
+
}
|
|
93
|
+
case 'vec3': {
|
|
94
|
+
return <Vec3Widget {...widgetProps} />;
|
|
95
|
+
}
|
|
96
|
+
case 'vec4': {
|
|
97
|
+
return <Vec4Widget {...widgetProps} />;
|
|
98
|
+
}
|
|
99
|
+
case 'color': {
|
|
100
|
+
return <ColorWidget {...widgetProps} />;
|
|
101
|
+
}
|
|
102
|
+
case 'boolean': {
|
|
103
|
+
return <BooleanWidget {...widgetProps} />;
|
|
104
|
+
}
|
|
105
|
+
default: {
|
|
106
|
+
if (
|
|
107
|
+
props.schema.type === 'string' &&
|
|
108
|
+
widgetProps.value &&
|
|
109
|
+
typeof widgetProps.value !== 'string'
|
|
110
|
+
) {
|
|
111
|
+
// Allow editing a custom type like event-set component schema
|
|
112
|
+
widgetProps.value = props.schema.stringify(widgetProps.value);
|
|
113
|
+
}
|
|
114
|
+
return <InputWidget {...widgetProps} />;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
render() {
|
|
120
|
+
const props = this.props;
|
|
121
|
+
const value =
|
|
122
|
+
props.schema.type === 'selector'
|
|
123
|
+
? props.entity.getDOMAttribute(props.componentname)?.[props.name]
|
|
124
|
+
: JSON.stringify(props.data);
|
|
125
|
+
const title =
|
|
126
|
+
props.name + '\n - type: ' + props.schema.type + '\n - value: ' + value;
|
|
127
|
+
|
|
128
|
+
const className = clsx({
|
|
129
|
+
propertyRow: true,
|
|
130
|
+
propertyRowDefined: props.isSingle
|
|
131
|
+
? !!props.entity.getDOMAttribute(props.componentname)
|
|
132
|
+
: props.name in
|
|
133
|
+
(props.entity.getDOMAttribute(props.componentname) || {})
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div className={className}>
|
|
138
|
+
<label htmlFor={this.id} className="text" title={title}>
|
|
139
|
+
{props.name}
|
|
140
|
+
</label>
|
|
141
|
+
{this.getWidget(props.schema.type)}
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
|
4
|
+
import { AwesomeIcon } from '../AwesomeIcon'; // Assuming AwesomeIcon is in the parent directory
|
|
5
|
+
import ComponentsContainer from './ComponentsContainer';
|
|
6
|
+
import EntityRepresentation from '../EntityRepresentation';
|
|
7
|
+
import Events from '../../lib/Events';
|
|
8
|
+
|
|
9
|
+
export default class Sidebar extends React.Component {
|
|
10
|
+
static propTypes = {
|
|
11
|
+
entity: PropTypes.object,
|
|
12
|
+
visible: PropTypes.bool
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
constructor(props) {
|
|
16
|
+
super(props);
|
|
17
|
+
this.state = { open: false };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
componentDidMount() {
|
|
21
|
+
Events.on('componentremove', (event) => {
|
|
22
|
+
this.forceUpdate();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
Events.on('componentadd', (event) => {
|
|
26
|
+
this.forceUpdate();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
handleToggle = () => {
|
|
31
|
+
this.setState({ open: !this.state.open });
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
handleClose = () => {
|
|
35
|
+
Events.emit('togglesidebar', { which: 'attributes' });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
render() {
|
|
39
|
+
const entity = this.props.entity;
|
|
40
|
+
const visible = this.props.visible;
|
|
41
|
+
if (entity && visible) {
|
|
42
|
+
return (
|
|
43
|
+
<div id="sidebar">
|
|
44
|
+
<ComponentsContainer entity={entity} />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
} else {
|
|
48
|
+
return <div />;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const BackViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline (adjust perspective for back view) */}
|
|
14
|
+
{/* Draw the back face first */}
|
|
15
|
+
<path d="M 10 2 L 24 2 L 24 16 L 10 16 Z" fill="#00ff99" />{' '}
|
|
16
|
+
{/* Back Face Highlighted */}
|
|
17
|
+
{/* Draw visible edges from back view */}
|
|
18
|
+
<path d="M 5 5 L 10 2" /> {/* Top-Left Edge */}
|
|
19
|
+
<path d="M 5 5 L 5 19" /> {/* Front-Left Edge */}
|
|
20
|
+
<path d="M 5 19 L 10 16" /> {/* Bottom-Left Edge */}
|
|
21
|
+
<path d="M 19 5 L 24 2" /> {/* Top-Right Edge */}
|
|
22
|
+
<path d="M 19 5 L 19 19" /> {/* Front-Right Edge */}
|
|
23
|
+
<path d="M 19 19 L 24 16" /> {/* Bottom-Right Edge */}
|
|
24
|
+
</svg>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export default BackViewIcon;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const BottomViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" /> {/* Front Face */}
|
|
15
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Edge */}
|
|
16
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Edge */}
|
|
17
|
+
<path d="M 5 19 L 10 16 L 10 2" /> {/* Left Edge */}
|
|
18
|
+
<path d="M 10 16 L 24 16" /> {/* Bottom Edge */}
|
|
19
|
+
{/* Highlight Bottom Face (approximated) */}
|
|
20
|
+
{/* Since it's a bottom view, we might just show the bottom square or a variation */}
|
|
21
|
+
{/* Let's highlight the bottom part of the front and right faces visible from a low angle */}
|
|
22
|
+
<path d="M 5 19 L 19 19 L 24 16 L 10 16 Z" fill="#00ff99" />
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export default BottomViewIcon;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const FrontViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" fill="#00ff99" />{' '}
|
|
15
|
+
{/* Front Face Highlighted */}
|
|
16
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Edge */}
|
|
17
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Edge */}
|
|
18
|
+
<path d="M 5 19 L 10 16 L 10 2" /> {/* Left Edge */}
|
|
19
|
+
<path d="M 10 16 L 24 16" /> {/* Bottom Edge */}
|
|
20
|
+
</svg>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export default FrontViewIcon;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const LeftViewIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" /> {/* Front Face */}
|
|
15
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Face */}
|
|
16
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Face */}
|
|
17
|
+
<path d="M 5 19 L 10 16 L 10 2" /> {/* Left Edge */}
|
|
18
|
+
<path d="M 10 16 L 24 16" /> {/* Bottom Edge */}
|
|
19
|
+
{/* Highlight Left Face */}
|
|
20
|
+
<path d="M 5 5 L 10 2 L 10 16 L 5 19 Z" fill="#00ff99" />
|
|
21
|
+
</svg>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export default LeftViewIcon;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const PerspectiveIcon = (props) => (
|
|
4
|
+
<svg
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="none"
|
|
7
|
+
stroke="currentColor"
|
|
8
|
+
strokeWidth="1.5"
|
|
9
|
+
strokeLinecap="round"
|
|
10
|
+
strokeLinejoin="round"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
{/* Simple Cube Outline */}
|
|
14
|
+
<path d="M 5 5 L 19 5 L 19 19 L 5 19 Z" /> {/* Front Face */}
|
|
15
|
+
<path d="M 5 5 L 10 2 L 24 2 L 19 5" /> {/* Top Face */}
|
|
16
|
+
<path d="M 19 5 L 24 2 L 24 16 L 19 19" /> {/* Right Face */}
|
|
17
|
+
{/* Optional: Add inner lines for perspective effect if needed */}
|
|
18
|
+
{/* <path d="M 5 19 L 10 16 L 10 2" /> */}
|
|
19
|
+
{/* <path d="M 10 16 L 24 16" /> */}
|
|
20
|
+
</svg>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export default PerspectiveIcon;
|