Skip to content

Commit 94ebde3

Browse files
author
Niklas Kiefer
committed
wip wip
1 parent 20dc130 commit 94ebde3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+825
-343
lines changed

packages/form-js-editor/assets/form-js-editor.css

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
--color-context-pad-item-fill: var(--color-grey-225-10-35);
99
--color-context-pad-item-hover-fill: var(--color-black);
1010

11-
--color-properties-container-background: var(--color-white);
12-
--color-properties-container-border: var(--color-grey-225-10-80);
13-
1411
--color-dragula-background: var(--color-blue-205-100-45);
1512
--color-dragula-border: var(--color-blue-205-100-45);
1613
--color-dragula-mirror-background: var(--color-white);
@@ -27,6 +24,12 @@
2724
--color-palette-field-hover-background: var(--color-grey-225-10-95);
2825
}
2926

27+
.fjs-properties-container {
28+
--color-properties-container-background: var(--color-white);
29+
--color-properties-container-border: var(--color-grey-225-10-80);
30+
--properties-panel-width: 300px;
31+
}
32+
3033
.fjs-editor-container {
3134
height: 100%;
3235
width: 100%;
@@ -188,22 +191,25 @@
188191
* Properties Panel
189192
*/
190193
.fjs-editor-container .fjs-properties-container {
191-
width: 300px;
194+
height: 100%;
195+
}
196+
197+
.fjs-properties-container {
192198
background-color: var(--color-properties-container-background);
199+
width: var(--properties-panel-width);
193200
border-left: solid 1px var(--color-properties-container-border);
194-
height: 100%;
195201
color: var(--color-text);
196202
}
197203

198-
.fjs-editor-container .fjs-properties-panel {
204+
.fjs-properties-panel-container .fjs-properties-panel {
199205
height: 100%;
200206
}
201207

202-
.fjs-editor-container .fjs-properties-panel * {
208+
.fjs-properties-panel-container .fjs-properties-panel * {
203209
box-sizing: border-box;
204210
}
205211

206-
.fjs-editor-container .bio-properties-panel-header-icon svg {
212+
.fjs-properties-panel-container .fjs-properties-panel .bio-properties-panel-header-icon svg {
207213
transform: scale(1.3);
208214
}
209215

packages/form-js-editor/src/FormEditor.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import KeyboardModule from './features/keyboard';
99
import ModelingModule from './features/modeling';
1010
import SelectionModule from './features/selection';
1111
import PaletteModule from './features/palette';
12+
import PropertiesPanelModule from './features/properties-panel';
1213

1314
const ids = new Ids([ 32, 36, 1 ]);
1415

@@ -298,7 +299,8 @@ export default class FormEditor {
298299
EditorActionsModule,
299300
KeyboardModule,
300301
SelectionModule,
301-
PaletteModule
302+
PaletteModule,
303+
PropertiesPanelModule
302304
];
303305
}
304306

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { PropertiesPanel } from '@bpmn-io/properties-panel';
2+
3+
import {
4+
useCallback,
5+
useState,
6+
useLayoutEffect
7+
} from 'preact/hooks';
8+
9+
import { FormPropertiesPanelContext } from './context';
10+
11+
import { PropertiesPanelHeaderProvider } from './PropertiesPanelHeaderProvider';
12+
import { PropertiesPanelPlaceholderProvider } from './PropertiesPanelPlaceholderProvider';
13+
14+
import {
15+
CustomValuesGroup,
16+
GeneralGroup,
17+
ValidationGroup,
18+
ValuesGroups
19+
} from './groups';
20+
21+
function getGroups(field, editField) {
22+
23+
if (!field) {
24+
return [];
25+
}
26+
27+
const groups = [
28+
GeneralGroup(field, editField),
29+
...ValuesGroups(field, editField),
30+
ValidationGroup(field, editField),
31+
CustomValuesGroup(field, editField)
32+
];
33+
34+
// contract: if a group returns null, it should not be displayed at all
35+
return groups.filter(group => group !== null);
36+
}
37+
38+
export default function FormPropertiesPanel(props) {
39+
const {
40+
eventBus,
41+
injector
42+
} = props;
43+
44+
const formEditor = injector.get('formEditor');
45+
const modeling = injector.get('modeling');
46+
const selection = injector.get('selection');
47+
48+
const { schema } = formEditor._getState();
49+
50+
const [ state, setState ] = useState({
51+
selectedFormField: selection.get() || schema
52+
});
53+
54+
const _update = (field) => {
55+
56+
setState({
57+
...state,
58+
selectedFormField: field
59+
});
60+
61+
// notify interested parties on property panel updates
62+
eventBus.fire('propertiesPanel.updated', {
63+
formField: field
64+
});
65+
};
66+
67+
// TODO(pinussilvestrus): it's not working with normal useEffect
68+
useLayoutEffect(() => {
69+
function onSelectionChange(event) {
70+
_update(event.selection || schema);
71+
}
72+
73+
eventBus.on('selection.changed', onSelectionChange);
74+
75+
return () => {
76+
eventBus.off('selection.changed', onSelectionChange);
77+
};
78+
}, []);
79+
80+
useLayoutEffect(() => {
81+
const onFieldChanged = () => {
82+
83+
/**
84+
* TODO(pinussilvestrus): update with actual updated element,
85+
* once we have a proper updater/change support
86+
*/
87+
_update(selection.get() || schema);
88+
};
89+
90+
eventBus.on('changed', onFieldChanged);
91+
92+
return () => {
93+
eventBus.off('changed', onFieldChanged);
94+
};
95+
}, []);
96+
97+
const selectedFormField = state.selectedFormField;
98+
99+
const propertiesPanelContext = {
100+
getService(type, strict = true) {
101+
return injector.get(type, strict);
102+
}
103+
};
104+
105+
const onFocus = () => eventBus.fire('propertiesPanel.focusin');
106+
107+
const onBlur = () => eventBus.fire('propertiesPanel.focusout');
108+
109+
const editField = useCallback((formField, key, value) => modeling.editFormField(formField, key, value), [ modeling ]);
110+
111+
return (
112+
<div
113+
class="fjs-properties-panel"
114+
data-field={ selectedFormField && selectedFormField.id }
115+
onFocusCapture={ onFocus }
116+
onBlurCapture={ onBlur }
117+
>
118+
<FormPropertiesPanelContext.Provider value={ propertiesPanelContext }>
119+
<PropertiesPanel
120+
element={ selectedFormField }
121+
eventBus={ eventBus }
122+
groups={ getGroups(selectedFormField, editField) }
123+
headerProvider={ PropertiesPanelHeaderProvider }
124+
placeholderProvider={ PropertiesPanelPlaceholderProvider }
125+
/>
126+
</FormPropertiesPanelContext.Provider>
127+
</div>
128+
);
129+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
textToLabel
33
} from './Util';
44

5-
import { iconsByType } from '../icons';
5+
import { iconsByType } from '../../render/components/icons';
66

77
const labelsByType = {
88
button: 'BUTTON',
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import PropertiesPanel from './PropertiesPanel';
2+
3+
import {
4+
render
5+
} from 'preact';
6+
7+
import {
8+
domify,
9+
query as domQuery
10+
} from 'min-dom';
11+
12+
/**
13+
* @typedef { { parent: Element } } PropertiesPanelConfig
14+
* @typedef { import('../../core/EventBus').default } EventBus
15+
* @typedef { import('../../types').Injector } Injector
16+
*/
17+
18+
/**
19+
* @param {PropertiesPanelConfig} propertiesPanelConfig
20+
* @param {Injector} injector
21+
* @param {EventBus} eventBus
22+
*/
23+
export default class PropertiesPanelRenderer {
24+
25+
constructor(propertiesPanelConfig, injector, eventBus) {
26+
const {
27+
parent
28+
} = propertiesPanelConfig || {};
29+
30+
this._eventBus = eventBus;
31+
this._injector = injector;
32+
33+
this._container = domify('<div class="fjs-properties-container" input-handle-modified-keys="y,z"></div>');
34+
35+
if (parent) {
36+
this.attachTo(parent);
37+
}
38+
39+
this._eventBus.once('formEditor.rendered', 500, () => {
40+
this._render();
41+
});
42+
}
43+
44+
45+
/**
46+
* Attach the properties panel to a parent node.
47+
*
48+
* @param {HTMLElement} container
49+
*/
50+
attachTo(container) {
51+
if (!container) {
52+
throw new Error('container required');
53+
}
54+
55+
if (typeof container === 'string') {
56+
container = domQuery(container);
57+
}
58+
59+
// (1) detach from old parent
60+
this.detach();
61+
62+
// (2) append to parent container
63+
container.appendChild(this._container);
64+
65+
// (3) notify interested parties
66+
this._eventBus.fire('propertiesPanel.attach');
67+
}
68+
69+
/**
70+
* Detach the properties panel from its parent node.
71+
*/
72+
detach() {
73+
const parentNode = this._container.parentNode;
74+
75+
if (parentNode) {
76+
parentNode.removeChild(this._container);
77+
78+
this._eventBus.fire('propertiesPanel.detach');
79+
}
80+
}
81+
82+
_render() {
83+
render(
84+
<PropertiesPanel
85+
eventBus={ this._eventBus }
86+
injector={ this._injector }
87+
/>,
88+
this._container
89+
);
90+
91+
this._eventBus.fire('propertiesPanel.rendered');
92+
}
93+
94+
_destroy() {
95+
if (this._container) {
96+
render(null, this._container);
97+
98+
this._eventBus.fire('propertiesPanel.destroyed');
99+
}
100+
}
101+
}
102+
103+
PropertiesPanelRenderer.$inject = [ 'config.propertiesPanel', 'injector', 'eventBus' ];
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createContext } from 'preact';
2+
3+
/**
4+
* @param {string} type
5+
* @param {boolean} [strict]
6+
*
7+
* @returns {any}
8+
*/
9+
function getService(type, strict) {}
10+
11+
const PropertiesPanelContext = createContext({
12+
getService
13+
});
14+
15+
export default PropertiesPanelContext;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as FormPropertiesPanelContext } from './FormPropertiesPanelContext';

0 commit comments

Comments
 (0)