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.
Files changed (104) hide show
  1. package/.babelrc +3 -0
  2. package/.editorconfig +12 -0
  3. package/.eslintignore +2 -0
  4. package/.eslintrc +40 -0
  5. package/.github/workflows/ci.yml +39 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.prettierignore +1 -0
  8. package/.prettierrc.json +5 -0
  9. package/.stylelintrc +12 -0
  10. package/LICENSE +21 -0
  11. package/README.md +75 -0
  12. package/assets/gltf.svg +49 -0
  13. package/dist/aframe-inspector.js +106250 -0
  14. package/dist/aframe-inspector.js.map +1 -0
  15. package/dist/aframe-inspector.min.js +29040 -0
  16. package/dist/aframe-inspector.min.js.LICENSE.txt +56 -0
  17. package/dist/aframe-inspector.min.js.map +1 -0
  18. package/examples/360video.html +48 -0
  19. package/examples/colors.html +18 -0
  20. package/examples/controllers.html +60 -0
  21. package/examples/embedded-zoom.html +78 -0
  22. package/examples/embedded.html +79 -0
  23. package/examples/empty.html +13 -0
  24. package/examples/index-aframe.html +66 -0
  25. package/examples/index.html +71 -0
  26. package/examples/supercraft.html +6 -0
  27. package/index.html +8 -0
  28. package/package.json +84 -0
  29. package/senangwebs-webverse-editor.png +0 -0
  30. package/src/components/AwesomeIcon.js +53 -0
  31. package/src/components/Collapsible.js +57 -0
  32. package/src/components/EntityRepresentation.js +83 -0
  33. package/src/components/Main.js +222 -0
  34. package/src/components/__tests__/Collapsible.test.js +30 -0
  35. package/src/components/components/AddComponent.js +104 -0
  36. package/src/components/components/CommonComponents.js +160 -0
  37. package/src/components/components/Component.js +151 -0
  38. package/src/components/components/ComponentsContainer.js +52 -0
  39. package/src/components/components/DefaultComponents.js +1 -0
  40. package/src/components/components/Mixins.js +83 -0
  41. package/src/components/components/PropertyRow.js +145 -0
  42. package/src/components/components/Sidebar.js +51 -0
  43. package/src/components/icons/BackViewIcon.js +27 -0
  44. package/src/components/icons/BottomViewIcon.js +26 -0
  45. package/src/components/icons/FrontViewIcon.js +23 -0
  46. package/src/components/icons/LeftViewIcon.js +24 -0
  47. package/src/components/icons/PerspectiveIcon.js +23 -0
  48. package/src/components/icons/PrimitiveBoxIcon.js +143 -0
  49. package/src/components/icons/PrimitiveConeIcon.js +44 -0
  50. package/src/components/icons/PrimitiveCylinderIcon.js +51 -0
  51. package/src/components/icons/PrimitiveEmptyEntityIcon.js +78 -0
  52. package/src/components/icons/PrimitiveImageIcon.js +86 -0
  53. package/src/components/icons/PrimitiveLightIcon.js +107 -0
  54. package/src/components/icons/PrimitivePlaneIcon.js +87 -0
  55. package/src/components/icons/PrimitiveSphereIcon.js +39 -0
  56. package/src/components/icons/PrimitiveTextIcon.js +89 -0
  57. package/src/components/icons/PrimitiveTorusIcon.js +31 -0
  58. package/src/components/icons/RightViewIcon.js +24 -0
  59. package/src/components/icons/TopViewIcon.js +24 -0
  60. package/src/components/modals/Modal.js +107 -0
  61. package/src/components/modals/ModalHelp.js +97 -0
  62. package/src/components/modals/ModalPrimitive.js +114 -0
  63. package/src/components/modals/ModalTextures.js +430 -0
  64. package/src/components/scenegraph/Entity.js +142 -0
  65. package/src/components/scenegraph/SceneGraph.js +337 -0
  66. package/src/components/scenegraph/Toolbar.js +147 -0
  67. package/src/components/viewport/CameraToolbar.js +122 -0
  68. package/src/components/viewport/TransformToolbar.js +102 -0
  69. package/src/components/viewport/ViewportHUD.js +33 -0
  70. package/src/components/widgets/BooleanWidget.js +49 -0
  71. package/src/components/widgets/ColorWidget.js +89 -0
  72. package/src/components/widgets/InputWidget.js +42 -0
  73. package/src/components/widgets/NumberWidget.js +179 -0
  74. package/src/components/widgets/SelectWidget.js +58 -0
  75. package/src/components/widgets/TextureWidget.js +252 -0
  76. package/src/components/widgets/Vec2Widget.js +55 -0
  77. package/src/components/widgets/Vec3Widget.js +58 -0
  78. package/src/components/widgets/Vec4Widget.js +61 -0
  79. package/src/components/widgets/index.js +9 -0
  80. package/src/index.js +301 -0
  81. package/src/lib/EditorControls.js +336 -0
  82. package/src/lib/Events.js +6 -0
  83. package/src/lib/TransformControls.js +1365 -0
  84. package/src/lib/assetsLoader.js +43 -0
  85. package/src/lib/assetsUtils.js +30 -0
  86. package/src/lib/cameras.js +121 -0
  87. package/src/lib/entity.js +556 -0
  88. package/src/lib/history.js +30 -0
  89. package/src/lib/raycaster.js +129 -0
  90. package/src/lib/shortcuts.js +211 -0
  91. package/src/lib/utils.js +118 -0
  92. package/src/lib/viewport.js +268 -0
  93. package/src/style/components.styl +275 -0
  94. package/src/style/entity.styl +22 -0
  95. package/src/style/help.styl +40 -0
  96. package/src/style/index.styl +358 -0
  97. package/src/style/lib.styl +41 -0
  98. package/src/style/primitiveModal.styl +90 -0
  99. package/src/style/scenegraph.styl +173 -0
  100. package/src/style/select.styl +71 -0
  101. package/src/style/textureModal.styl +220 -0
  102. package/src/style/viewport.styl +168 -0
  103. package/src/style/widgets.styl +71 -0
  104. package/webpack.config.js +65 -0
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ faCamera,
5
+ faCube,
6
+ faFont,
7
+ faLightbulb
8
+ } from '@fortawesome/free-solid-svg-icons';
9
+ import { AwesomeIcon } from './AwesomeIcon';
10
+
11
+ const ICONS = {
12
+ camera: (
13
+ <i title="camera">
14
+ <AwesomeIcon icon={faCamera} />
15
+ </i>
16
+ ),
17
+ mesh: (
18
+ <i title="mesh">
19
+ <AwesomeIcon icon={faCube} />
20
+ </i>
21
+ ),
22
+ light: (
23
+ <i title="light">
24
+ <AwesomeIcon icon={faLightbulb} />
25
+ </i>
26
+ ),
27
+ text: (
28
+ <i title="text">
29
+ <AwesomeIcon icon={faFont} />
30
+ </i>
31
+ )
32
+ };
33
+
34
+ export default class EntityRepresentation extends React.Component {
35
+ static propTypes = {
36
+ entity: PropTypes.object,
37
+ onDoubleClick: PropTypes.func
38
+ };
39
+
40
+ render() {
41
+ const entity = this.props.entity;
42
+ const onDoubleClick = this.props.onDoubleClick;
43
+
44
+ if (!entity) {
45
+ return null;
46
+ }
47
+
48
+ // Icons.
49
+ const icons = [];
50
+ for (let objType in ICONS) {
51
+ if (!entity.getObject3D(objType)) {
52
+ continue;
53
+ }
54
+ icons.push(<span key={objType}>&nbsp;{ICONS[objType]}</span>);
55
+ }
56
+
57
+ // Name.
58
+ let entityName = entity.id;
59
+ let type = 'id';
60
+ if (!entity.isScene && !entityName && entity.getAttribute('class')) {
61
+ entityName = entity.getAttribute('class').split(' ')[0];
62
+ type = 'class';
63
+ } else if (!entity.isScene && !entityName && entity.getAttribute('mixin')) {
64
+ entityName = entity.getAttribute('mixin').split(' ')[0];
65
+ type = 'mixin';
66
+ }
67
+
68
+ return (
69
+ <span className="entityPrint" onDoubleClick={onDoubleClick}>
70
+ <span className="entityTagName">
71
+ {'<' + entity.tagName.toLowerCase()}
72
+ </span>
73
+ {entityName && (
74
+ <span className="entityName" data-entity-name-type={type}>
75
+ &nbsp;{entityName}
76
+ </span>
77
+ )}
78
+ {icons.length > 0 && <span className="entityIcons">{icons}</span>}
79
+ <span className="entityCloseTag">{'>'}</span>
80
+ </span>
81
+ );
82
+ }
83
+ }
@@ -0,0 +1,222 @@
1
+ import React from 'react';
2
+ import {
3
+ faPlus,
4
+ faCog,
5
+ faCode,
6
+ faBars,
7
+ faTimes,
8
+ faEye,
9
+ faCube,
10
+ faCubes,
11
+ faFileUpload,
12
+ faFolderOpen,
13
+ faVrCardboard
14
+ } from '@fortawesome/free-solid-svg-icons';
15
+ import { AwesomeIcon } from './AwesomeIcon';
16
+ import Events from '../lib/Events';
17
+ import ComponentsSidebar from './components/Sidebar';
18
+ import ModalTextures from './modals/ModalTextures';
19
+ import ModalHelp from './modals/ModalHelp';
20
+ import SceneGraph from './scenegraph/SceneGraph';
21
+ import CameraToolbar from './viewport/CameraToolbar';
22
+ import TransformToolbar from './viewport/TransformToolbar';
23
+ import ViewportHUD from './viewport/ViewportHUD';
24
+
25
+ THREE.ImageUtils.crossOrigin = '';
26
+
27
+ export default class Main extends React.Component {
28
+ constructor(props) {
29
+ super(props);
30
+
31
+ this.state = {
32
+ entity: null,
33
+ inspectorEnabled: true,
34
+ isModalTexturesOpen: false,
35
+ sceneEl: AFRAME.scenes[0],
36
+ visible: {
37
+ scenegraph: true,
38
+ attributes: false // Set this to false
39
+ }
40
+ };
41
+
42
+ Events.on('togglesidebar', (event) => {
43
+ if (event.which === 'all') {
44
+ if (this.state.visible.scenegraph || this.state.visible.attributes) {
45
+ this.setState({
46
+ visible: {
47
+ scenegraph: false,
48
+ attributes: false
49
+ }
50
+ });
51
+ } else {
52
+ this.setState({
53
+ visible: {
54
+ scenegraph: true,
55
+ attributes: true
56
+ }
57
+ });
58
+ }
59
+ } else if (event.which === 'attributes') {
60
+ this.setState((prevState) => ({
61
+ visible: {
62
+ ...prevState.visible,
63
+ attributes: !prevState.visible.attributes
64
+ }
65
+ }));
66
+ } else if (event.which === 'scenegraph') {
67
+ this.setState((prevState) => ({
68
+ visible: {
69
+ ...prevState.visible,
70
+ scenegraph: !prevState.visible.scenegraph
71
+ }
72
+ }));
73
+ }
74
+ });
75
+ }
76
+
77
+ componentDidMount() {
78
+ Events.on(
79
+ 'opentexturesmodal',
80
+ function (selectedTexture, textureOnClose) {
81
+ this.setState({
82
+ selectedTexture: selectedTexture,
83
+ isModalTexturesOpen: true,
84
+ textureOnClose: textureOnClose
85
+ });
86
+ }.bind(this)
87
+ );
88
+
89
+ Events.on('entityselect', (entity) => {
90
+ // Set the selected entity and ensure the attributes sidebar is visible
91
+ this.setState({
92
+ entity: entity,
93
+ visible: { ...this.state.visible, attributes: true }
94
+ });
95
+ });
96
+
97
+ Events.on('inspectortoggle', (enabled) => {
98
+ this.setState({ inspectorEnabled: enabled });
99
+ });
100
+
101
+ Events.on('openhelpmodal', () => {
102
+ this.setState({ isHelpOpen: true });
103
+ });
104
+ }
105
+
106
+ handleClose = () => {
107
+ Events.emit('togglesidebar', { which: 'attributes' });
108
+ };
109
+
110
+ onCloseHelpModal = (value) => {
111
+ this.setState({ isHelpOpen: false });
112
+ };
113
+
114
+ onModalTextureOnClose = (value) => {
115
+ this.setState({ isModalTexturesOpen: false });
116
+ if (this.state.textureOnClose) {
117
+ this.state.textureOnClose(value);
118
+ }
119
+ };
120
+
121
+ toggleEdit = () => {
122
+ if (this.state.inspectorEnabled) {
123
+ AFRAME.INSPECTOR.close();
124
+ } else {
125
+ AFRAME.INSPECTOR.open();
126
+ }
127
+ };
128
+
129
+ renderSceneGraphToggle() {
130
+ if (!this.state.inspectorEnabled || this.state.visible.scenegraph) {
131
+ return null;
132
+ }
133
+ return (
134
+ <div className="toggle-sidebar left">
135
+ <a
136
+ onClick={() => {
137
+ Events.emit('togglesidebar', { which: 'scenegraph' });
138
+ }}
139
+ title="Show scenegraph"
140
+ >
141
+ <AwesomeIcon icon={faPlus} />
142
+ </a>
143
+ </div>
144
+ );
145
+ }
146
+
147
+ render() {
148
+ const scene = this.state.sceneEl;
149
+ // Simplified toggle button text logic
150
+ const buttonText = this.state.inspectorEnabled ? 'Show' : 'Edit';
151
+
152
+ return (
153
+ <div>
154
+ <a
155
+ id="previewSceneBtn"
156
+ className="toggle-edit"
157
+ onClick={this.toggleEdit}
158
+ >
159
+ <AwesomeIcon icon={faVrCardboard} />
160
+ </a>
161
+
162
+ {this.renderSceneGraphToggle()}
163
+
164
+ <div
165
+ id="inspectorContainer"
166
+ className={this.state.inspectorEnabled ? '' : 'hidden'}
167
+ >
168
+ <div id="leftPanel">
169
+ <div className="scenegraph-menubar">
170
+ <div id="scenegraph-menu-back"></div>
171
+ <div id="scenegraph-panel-action"></div>
172
+ </div>
173
+ <SceneGraph
174
+ scene={scene}
175
+ selectedEntity={this.state.entity}
176
+ visible={this.state.visible.scenegraph}
177
+ />
178
+ </div>
179
+
180
+ <div id="viewportBar">
181
+ <CameraToolbar />
182
+ <TransformToolbar />
183
+ <div className="viewportHud-menubar">
184
+ <ViewportHUD />
185
+ </div>
186
+ </div>
187
+
188
+ <div
189
+ id="rightPanel"
190
+ className={this.state.visible.attributes ? '' : 'hidden'}
191
+ >
192
+ <div className="componentHeader title">
193
+ {/* <a>
194
+ <AwesomeIcon icon={faBars} />
195
+ </a> */}
196
+ <div id="entity-panel-action"></div>
197
+ <a onClick={this.handleClose}>
198
+ <AwesomeIcon icon={faTimes} />
199
+ </a>
200
+ </div>
201
+ <ComponentsSidebar
202
+ entity={this.state.entity}
203
+ visible={this.state.visible.attributes} // This prop might become redundant depending on CSS, but leave for now
204
+ />
205
+ </div>
206
+
207
+ <div id="actionBar"></div>
208
+ </div>
209
+
210
+ <ModalHelp
211
+ isOpen={this.state.isHelpOpen}
212
+ onClose={this.onCloseHelpModal}
213
+ />
214
+ <ModalTextures
215
+ isOpen={this.state.isModalTexturesOpen}
216
+ selectedTexture={this.state.selectedTexture}
217
+ onClose={this.onModalTextureOnClose}
218
+ />
219
+ </div>
220
+ );
221
+ }
222
+ }
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import renderer from 'react-test-renderer';
3
+
4
+ import Collapsible from '../Collapsible.js';
5
+
6
+ describe('Collapsible', () => {
7
+ it('does not set class when not collapsed', () => {
8
+ const tree = renderer
9
+ .create(
10
+ <Collapsible collapsed={false}>
11
+ <div />
12
+ <div />
13
+ </Collapsible>
14
+ )
15
+ .toJSON();
16
+ expect(tree.children[1].props.className).not.toContain('hide');
17
+ });
18
+
19
+ it('sets class when collapsed', () => {
20
+ const tree = renderer
21
+ .create(
22
+ <Collapsible collapsed={true}>
23
+ <div />
24
+ <div />
25
+ </Collapsible>
26
+ )
27
+ .toJSON();
28
+ expect(tree.children[1].props.className).toContain('hide');
29
+ });
30
+ });
@@ -0,0 +1,104 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Events from '../../lib/Events';
4
+ import Select from 'react-select';
5
+
6
+ export default class AddComponent extends React.Component {
7
+ static propTypes = {
8
+ entity: PropTypes.object
9
+ };
10
+
11
+ /**
12
+ * Add blank component.
13
+ * If component is instanced, generate an ID.
14
+ */
15
+ addComponent = (value) => {
16
+ let componentName = value.value;
17
+
18
+ var entity = this.props.entity;
19
+
20
+ if (AFRAME.components[componentName].multiple) {
21
+ const id = prompt(
22
+ `Provide an ID for this component (e.g., 'foo' for ${componentName}__foo).`
23
+ );
24
+ componentName = id ? `${componentName}__${id}` : componentName;
25
+ }
26
+
27
+ entity.setAttribute(componentName, '');
28
+ Events.emit('componentadd', { entity: entity, component: componentName });
29
+ };
30
+
31
+ /**
32
+ * Component dropdown options.
33
+ */
34
+ getComponentsOptions() {
35
+ const usedComponents = Object.keys(this.props.entity.components);
36
+ var commonOptions = Object.keys(AFRAME.components)
37
+ .filter(function (componentName) {
38
+ return (
39
+ AFRAME.components[componentName].multiple ||
40
+ usedComponents.indexOf(componentName) === -1
41
+ );
42
+ })
43
+ .sort()
44
+ .map(function (value) {
45
+ return { value: value, label: value, origin: 'loaded' };
46
+ });
47
+
48
+ this.options = commonOptions;
49
+ this.options = this.options.sort(function (a, b) {
50
+ return a.label === b.label ? 0 : a.label < b.label ? -1 : 1;
51
+ });
52
+ }
53
+
54
+ renderOption(option) {
55
+ var bullet = (
56
+ <span title="Component already loaded in the scene">&#9679;</span>
57
+ );
58
+ return (
59
+ <strong className="option">
60
+ {option.label} {option.origin === 'loaded' ? bullet : ''}
61
+ </strong>
62
+ );
63
+ }
64
+
65
+ render() {
66
+ const entity = this.props.entity;
67
+ if (!entity) {
68
+ return <div />;
69
+ }
70
+
71
+ this.getComponentsOptions();
72
+
73
+ return (
74
+ <div id="addComponentContainer">
75
+ <p id="addComponentHeader">COMPONENTS</p>
76
+ <Select
77
+ id="addComponent"
78
+ className="addComponent"
79
+ classNamePrefix="select"
80
+ options={this.options}
81
+ simpleValue
82
+ clearable={true}
83
+ placeholder="Add component..."
84
+ noResultsText="No components found"
85
+ onChange={this.addComponent}
86
+ optionRenderer={this.renderOption}
87
+ searchable={true}
88
+ />
89
+ </div>
90
+ );
91
+ }
92
+ }
93
+
94
+ /* eslint-disable no-unused-vars */
95
+ /**
96
+ * Check if component has multiplicity.
97
+ */
98
+ function isComponentInstanced(entity, componentName) {
99
+ for (var component in entity.components) {
100
+ if (component.substring(0, component.indexOf('__')) === componentName) {
101
+ return true;
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,160 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { faClipboard } from '@fortawesome/free-solid-svg-icons';
4
+ import { faTimes, faBars } from '@fortawesome/free-solid-svg-icons';
5
+ import { AwesomeIcon } from '../AwesomeIcon';
6
+ import { InputWidget } from '../widgets';
7
+ import DEFAULT_COMPONENTS from './DefaultComponents';
8
+ import PropertyRow from './PropertyRow';
9
+ import Collapsible from '../Collapsible';
10
+ import Mixins from './Mixins';
11
+ import {
12
+ updateEntity,
13
+ getEntityClipboardRepresentation
14
+ } from '../../lib/entity';
15
+ import EntityRepresentation from '../EntityRepresentation';
16
+ import Events from '../../lib/Events';
17
+ import copy from 'clipboard-copy';
18
+ import { saveBlob } from '../../lib/utils';
19
+ import GLTFIcon from '../../../assets/gltf.svg';
20
+
21
+ // @todo Take this out and use updateEntity?
22
+ function changeId(componentName, value) {
23
+ var entity = AFRAME.INSPECTOR.selectedEntity;
24
+ if (entity.id !== value) {
25
+ entity.id = value;
26
+ Events.emit('entityidchange', entity);
27
+ }
28
+ }
29
+
30
+ export default class CommonComponents extends React.Component {
31
+ static propTypes = {
32
+ entity: PropTypes.object
33
+ };
34
+
35
+ componentDidMount() {
36
+ Events.on('entityupdate', (detail) => {
37
+ if (detail.entity !== this.props.entity) {
38
+ return;
39
+ }
40
+ if (
41
+ DEFAULT_COMPONENTS.indexOf(detail.component) !== -1 ||
42
+ detail.component === 'mixin'
43
+ ) {
44
+ this.forceUpdate();
45
+ }
46
+ });
47
+ }
48
+
49
+ renderCommonAttributes() {
50
+ const entity = this.props.entity;
51
+ return ['position', 'rotation', 'scale', 'visible'].map((componentName) => {
52
+ const schema = AFRAME.components[componentName].schema;
53
+ var data = entity.object3D[componentName];
54
+ if (componentName === 'rotation') {
55
+ data = {
56
+ x: THREE.MathUtils.radToDeg(entity.object3D.rotation.x),
57
+ y: THREE.MathUtils.radToDeg(entity.object3D.rotation.y),
58
+ z: THREE.MathUtils.radToDeg(entity.object3D.rotation.z)
59
+ };
60
+ }
61
+ return (
62
+ <PropertyRow
63
+ onChange={updateEntity}
64
+ key={componentName}
65
+ name={componentName}
66
+ showHelp={true}
67
+ schema={schema}
68
+ data={data}
69
+ isSingle={true}
70
+ componentname={componentName}
71
+ entity={entity}
72
+ />
73
+ );
74
+ });
75
+ }
76
+
77
+ exportToGLTF() {
78
+ const entity = this.props.entity;
79
+ AFRAME.INSPECTOR.exporters.gltf.parse(
80
+ entity.object3D,
81
+ function (buffer) {
82
+ const blob = new Blob([buffer], { type: 'application/octet-stream' });
83
+ saveBlob(blob, (entity.id || 'entity') + '.glb');
84
+ },
85
+ function (error) {
86
+ console.error(error);
87
+ },
88
+ { binary: true }
89
+ );
90
+ }
91
+
92
+ render() {
93
+ const entity = this.props.entity;
94
+ if (!entity) {
95
+ return <div />;
96
+ }
97
+ const entityButtons = (
98
+ <div>
99
+ <a
100
+ title="Close components"
101
+ onClick={(event) => {
102
+ this.handleClose();
103
+ }}
104
+ >
105
+ <AwesomeIcon icon={faTimes} />
106
+ </a>
107
+ {/* <a
108
+ title="Export entity to GLTF"
109
+ className="gltfIcon"
110
+ onClick={(event) => {
111
+ this.exportToGLTF();
112
+ event.preventDefault();
113
+ event.stopPropagation();
114
+ }}
115
+ >
116
+ <img src={GLTFIcon} />
117
+ </a>
118
+ <a
119
+ title="Copy entity HTML to clipboard"
120
+ className="button"
121
+ onClick={(event) => {
122
+ event.preventDefault();
123
+ event.stopPropagation();
124
+ copy(getEntityClipboardRepresentation(this.props.entity));
125
+ }}
126
+ >
127
+ <AwesomeIcon icon={faClipboard} />
128
+ </a> */}
129
+ </div>
130
+ );
131
+
132
+ return (
133
+ <Collapsible id="componentEntityHeader" className="commonComponents">
134
+ <div className="collapsible-header sidebar-header">
135
+ <EntityRepresentation entity={entity} />
136
+ {/* {entityButtons} */}
137
+ </div>
138
+ <div className="collapsible-content">
139
+ <div className="propertyRow">
140
+ <label htmlFor="id" className="text">
141
+ ID
142
+ </label>
143
+ <InputWidget
144
+ onChange={changeId}
145
+ entity={entity}
146
+ name="id"
147
+ value={entity.id}
148
+ />
149
+ </div>
150
+ <div className="propertyRow">
151
+ <label className="text">class</label>
152
+ <span>{entity.getAttribute('class')}</span>
153
+ </div>
154
+ {this.renderCommonAttributes()}
155
+ <Mixins entity={entity} />
156
+ </div>
157
+ </Collapsible>
158
+ );
159
+ }
160
+ }