Skip to content

Commit eb55b39

Browse files
authored
Add css mount events (#6540)
* Add component:input to ComponentsEvents * Add additional `data:path` events * Add CssRule mount event * Switch to a new pathSource event. The `data:path:SOURCE_ID` doesn't work as it triggers rebuilds of symbols in ComponentDataCollection * Up comment * Up data_sources docs * Up data_sources jsdoc * Up Module.events TS * Export types data components * More TS export * Up TS * Up docs API
1 parent 1a498bf commit eb55b39

File tree

20 files changed

+172
-90
lines changed

20 files changed

+172
-90
lines changed

docs/api/datasources.md

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,62 @@
33
## DataSources
44

55
This module manages data sources within the editor.
6-
You can initialize the module with the editor by passing an instance of `EditorModel`.
6+
Once the editor is instantiated, you can use the following API to manage data sources:
77

88
```js
9-
const editor = new EditorModel();
10-
const dsm = new DataSourceManager(editor);
9+
const editor = grapesjs.init({ ... });
10+
const dsm = editor.DataSources;
1111
```
1212

13-
Once the editor is instantiated, you can use the following API to manage data sources:
13+
## Available Events
14+
* `data:add` Added new data source.
1415

15-
```js
16-
const dsm = editor.DataSources;
16+
```javascript
17+
editor.on('data:add', (dataSource) => { ... });
1718
```
1819

19-
* [add][1] - Add a new data source.
20-
* [get][2] - Retrieve a data source by its ID.
21-
* [getAll][3] - Retrieve all data sources.
22-
* [remove][4] - Remove a data source by its ID.
23-
* [clear][5] - Remove all data sources.
20+
* `data:remove` Data source removed.
2421

25-
Example of adding a data source:
22+
```javascript
23+
editor.on('data:remove', (dataSource) => { ... });
24+
```
2625

27-
```js
28-
const ds = dsm.add({
29-
id: 'my_data_source_id',
30-
records: [
31-
{ id: 'id1', name: 'value1' },
32-
{ id: 'id2', name: 'value2' }
33-
]
26+
* `data:update` Data source updated.
27+
28+
```javascript
29+
editor.on('data:update', (dataSource, changes) => { ... });
30+
```
31+
32+
* `data:path` Data record path update.
33+
34+
```javascript
35+
editor.on('data:path:SOURCE_ID.RECORD_ID.PROP_NAME', ({ dataSource, dataRecord, path }) => { ... });
36+
editor.on('data:path', ({ dataSource, dataRecord, path }) => {
37+
console.log('Path update in any data source')
3438
});
3539
```
3640

37-
### Parameters
41+
* `data:pathSource` Data record path update per source.
42+
43+
```javascript
44+
editor.on('data:pathSource:SOURCE_ID', ({ dataSource, dataRecord, path }) => { ... });
45+
```
46+
47+
* `data` Catch-all event for all the events mentioned above.
48+
49+
```javascript
50+
editor.on('data', ({ event, model, ... }) => { ... });
51+
```
52+
53+
## Methods
54+
55+
* [add][1] - Add a new data source.
56+
* [get][2] - Retrieve a data source by its ID.
57+
* [getAll][3] - Retrieve all data sources.
58+
* [remove][4] - Remove a data source by its ID.
59+
* [clear][5] - Remove all data sources.
3860

39-
* `em` **EditorModel** Editor model.
61+
[DataSource]: datasource.html
4062

4163
## add
4264

packages/core/src/abstract/Module.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default abstract class Module<T extends ModuleConfig = ModuleConfig> impl
4444
collections: Collection[] = [];
4545
cls: any[] = [];
4646
state?: Model;
47-
events: any;
47+
events: object = {};
4848
model?: any;
4949
view?: any;
5050

@@ -129,18 +129,19 @@ export abstract class ItemManagerModule<
129129
cls: any[] = [];
130130
all: TCollection;
131131
view?: View;
132+
events!: Record<string, string>;
132133

133134
constructor(
134135
em: EditorModel,
135136
moduleName: string,
136137
all: any,
137-
events?: any,
138+
events?: Record<string, string>,
138139
defaults?: TConf,
139140
opts: { skipListen?: boolean } = {},
140141
) {
141142
super(em, moduleName, defaults);
142143
this.all = all;
143-
this.events = events;
144+
if (events) this.events = events;
144145
!opts.skipListen && this.__initListen();
145146
}
146147

packages/core/src/canvas/model/CanvasSpots.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export default class CanvasSpots extends ModuleCollection<CanvasSpot> {
1717
const { em } = this;
1818
this.refreshDbn = debounce(() => this.refresh(), 0);
1919

20-
const evToRefreshDbn = `${ComponentsEvents.resize} styleable:change component:input ${ComponentsEvents.update} frame:updated undo redo`;
20+
const evToRefreshDbn = `${ComponentsEvents.resize} styleable:change ${ComponentsEvents.input} ${ComponentsEvents.update} frame:updated undo redo`;
2121
this.listenTo(em, evToRefreshDbn, () => this.refreshDbn());
2222
}
2323

packages/core/src/code_manager/model/CssGenerator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export default class CssGenerator extends Model {
172172
});
173173

174174
if ((selectorStrNoAdd && found) || selectorsAdd || singleAtRule || !model) {
175-
const block = rule.getDeclaration({ body: 1 });
175+
const block = rule.getDeclaration();
176176
block && (opts.json ? (result = rule) : (result += block));
177177
} else {
178178
dump.push(rule);

packages/core/src/commands/view/SelectComponent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default {
9696
methods[method](listenToEl, 'scroll', this.onContainerChange);
9797
em[method](`component:toggled ${eventCmpUpdate} undo redo`, this.onSelect, this);
9898
em[method]('change:componentHovered', this.onHovered, this);
99-
em[method](`${ComponentsEvents.resize} styleable:change component:input`, this.updateGlobalPos, this);
99+
em[method](`${ComponentsEvents.resize} styleable:change ${ComponentsEvents.input}`, this.updateGlobalPos, this);
100100
em[method](`${eventCmpUpdate}:toolbar`, this._upToolbar, this);
101101
em[method]('frame:updated', this.onFrameUpdated, this);
102102
em[method]('canvas:updateTools', this.onFrameUpdated, this);

packages/core/src/css_composer/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import EditorModel from '../editor/model/Editor';
4040
import Component from '../dom_components/model/Component';
4141
import { ObjectAny, PrevToNewIdMap } from '../common';
4242
import { UpdateStyleOptions } from '../domain_abstract/model/StyleableModel';
43+
import { CssEvents } from './types';
44+
import CssRuleView from './view/CssRuleView';
4345

4446
/** @private */
4547
interface RuleOptions {
@@ -72,8 +74,15 @@ export interface GetSetRuleOptions extends UpdateStyleOptions {
7274
type CssRuleStyle = Required<CssRuleProperties>['style'];
7375

7476
export default class CssComposer extends ItemManagerModule<CssComposerConfig & { pStylePrefix?: string }> {
77+
classes = {
78+
CssRule,
79+
CssRules,
80+
CssRuleView,
81+
CssRulesView,
82+
};
7583
rules: CssRules;
7684
rulesView?: CssRulesView;
85+
events = CssEvents;
7786

7887
Selectors = Selectors;
7988

@@ -85,7 +94,7 @@ export default class CssComposer extends ItemManagerModule<CssComposerConfig & {
8594
* @private
8695
*/
8796
constructor(em: EditorModel) {
88-
super(em, 'CssComposer', null, {}, defConfig());
97+
super(em, 'CssComposer', null, CssEvents, defConfig());
8998
const { config } = this;
9099

91100
const ppfx = config.pStylePrefix;

packages/core/src/css_composer/model/CssRule.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import { isEmpty, forEach, isString, isArray } from 'underscore';
2-
import { Model, ObjectAny, View } from '../../common';
3-
import StyleableModel from '../../domain_abstract/model/StyleableModel';
2+
import { Model, ObjectAny } from '../../common';
3+
import StyleableModel, { StyleProps } from '../../domain_abstract/model/StyleableModel';
44
import Selectors from '../../selector_manager/model/Selectors';
55
import { getMediaLength } from '../../code_manager/model/CssGenerator';
66
import { isEmptyObj, hasWin } from '../../utils/mixins';
77
import Selector, { SelectorProps } from '../../selector_manager/model/Selector';
88
import EditorModel from '../../editor/model/Editor';
99
import CssRuleView from '../view/CssRuleView';
1010

11+
export interface ToCssOptions {
12+
important?: boolean | string[];
13+
allowEmpty?: boolean;
14+
style?: StyleProps;
15+
inline?: boolean;
16+
}
17+
1118
/** @private */
1219
export interface CssRuleProperties {
1320
/**
@@ -214,7 +221,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
214221
* });
215222
* cssRule.getDeclaration() // ".class1{color:red;}"
216223
*/
217-
getDeclaration(opts: ObjectAny = {}) {
224+
getDeclaration(opts: ToCssOptions = {}) {
218225
let result = '';
219226
const { important } = this.attributes;
220227
const selectors = this.selectorsToString(opts);
@@ -285,7 +292,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
285292
* });
286293
* cssRule.toCSS() // "@media (min-width: 500px){.class1{color:red;}}"
287294
*/
288-
toCSS(opts: ObjectAny = {}) {
295+
toCSS(opts: ToCssOptions = {}) {
289296
let result = '';
290297
const atRule = this.getAtRule();
291298
const block = this.getDeclaration(opts);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export enum CssEvents {
2+
/**
3+
* @event `css:mount` CSS rule is mounted in the canvas.
4+
* @example
5+
* editor.on('css:mount', ({ rule }) => { ... });
6+
*/
7+
mount = 'css:mount',
8+
mountBefore = 'css:mount:before',
9+
}

packages/core/src/css_composer/view/CssRuleView.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import FrameView from '../../canvas/view/FrameView';
22
import { View } from '../../common';
3+
import EditorModel from '../../editor/model/Editor';
34
import CssRule from '../model/CssRule';
5+
import { CssEvents } from '../types';
46

57
export default class CssRuleView extends View<CssRule> {
68
config: any;
@@ -19,6 +21,10 @@ export default class CssRuleView extends View<CssRule> {
1921
return this.config.frameView;
2022
}
2123

24+
get em(): EditorModel {
25+
return this.model.em!;
26+
}
27+
2228
remove() {
2329
super.remove();
2430
this.model.removeView(this);
@@ -35,9 +41,13 @@ export default class CssRuleView extends View<CssRule> {
3541
}
3642

3743
render() {
38-
const { model, el } = this;
44+
const { model, el, em } = this;
3945
const important = model.get('important');
40-
el.innerHTML = model.toCSS({ important });
46+
const css = model.toCSS({ important });
47+
const mountProps = { rule: model, ruleView: this, css };
48+
em?.trigger(CssEvents.mountBefore, mountProps);
49+
el.innerHTML = mountProps.css;
50+
em?.trigger(CssEvents.mount, mountProps);
4151
return this;
4252
}
4353
}

packages/core/src/data_sources/index.ts

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,24 @@
11
/**
22
* This module manages data sources within the editor.
3-
* You can initialize the module with the editor by passing an instance of `EditorModel`.
4-
*
5-
* ```js
6-
* const editor = new EditorModel();
7-
* const dsm = new DataSourceManager(editor);
8-
* ```
9-
*
103
* Once the editor is instantiated, you can use the following API to manage data sources:
114
*
125
* ```js
6+
* const editor = grapesjs.init({ ... });
137
* const dsm = editor.DataSources;
148
* ```
159
*
10+
* {REPLACE_EVENTS}
11+
*
12+
* ## Methods
1613
* * [add](#add) - Add a new data source.
1714
* * [get](#get) - Retrieve a data source by its ID.
1815
* * [getAll](#getall) - Retrieve all data sources.
1916
* * [remove](#remove) - Remove a data source by its ID.
2017
* * [clear](#clear) - Remove all data sources.
2118
*
22-
* Example of adding a data source:
23-
*
24-
* ```js
25-
* const ds = dsm.add({
26-
* id: 'my_data_source_id',
27-
* records: [
28-
* { id: 'id1', name: 'value1' },
29-
* { id: 'id2', name: 'value2' }
30-
* ]
31-
* });
32-
* ```
19+
* [DataSource]: datasource.html
3320
*
3421
* @module DataSources
35-
* @param {EditorModel} em - Editor model.
3622
*/
3723

3824
import { ItemManagerModule, ModuleConfig } from '../abstract/Module';

0 commit comments

Comments
 (0)