diff --git a/docs/.vuepress/override.styl b/docs/.vuepress/override.styl index 158ca7411..498992d75 100644 --- a/docs/.vuepress/override.styl +++ b/docs/.vuepress/override.styl @@ -4,6 +4,11 @@ $navBarColor = white $scrollBarSize = 8px $pageWidth = 900px +.img-ctr { + margin: 0 auto; + display: block; +} + .navbar { background-color: rgb(111, 41, 67); background-image: linear-gradient(120deg, rgb(217, 131, 166), rgb(77, 17, 79)); diff --git a/docs/.vuepress/public/component-type-stack.svg b/docs/.vuepress/public/component-type-stack.svg new file mode 100644 index 000000000..f77e6a374 --- /dev/null +++ b/docs/.vuepress/public/component-type-stack.svg @@ -0,0 +1,68 @@ + + + + Artboard + Created with Sketch. + + + + + + + type: image + + + + + + + + type: new-type + + + + + + + + type: text + + + + + + + + type: default + + + + + Component Type Stack + + + + + + New Component Type + goes on top + + + The + default + is the last + available type + + + Each parsed element goes + through the stack from TOP + to BOTTOM + + + + <span> + New element + </span> + + + \ No newline at end of file diff --git a/docs/getting-started.md b/docs/getting-started.md index 05baa3291..82805e51f 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -597,7 +597,7 @@ editor.setDevice('Mobile'); ``` ::: tip -Check out the [Device Manager API](api/panels.html) to see all the available methods +Check out the [Device Manager API](api/device_manager.html) to see all the available methods ::: ## Store & load data diff --git a/docs/modules/Components-new.md b/docs/modules/Components-new.md index aef30ba45..da0341e5d 100644 --- a/docs/modules/Components-new.md +++ b/docs/modules/Components-new.md @@ -4,7 +4,7 @@ title: Component Manager # Component Manager -The Component is the base element for template composition. It is atomic, so elements like images, text boxes, maps, etc. fit the definition of a Component. The concept of the component was made to allow the developer to bind different behaviors to different elements. Like for example, opening the Asset Manager on double click of the image. +The Component is a base element of the template. It might be something simple and atomic like an image or a text box, but also complex structures, more probably composed by other components, like sections or pages. The concept of the component was made to allow the developer to bind different behaviors to different elements. For example, opening the Asset Manager on double click of the image is a custom behavior binded to that particular type of element. ::: warning This guide is referring to GrapesJS v0.14.67 or higher @@ -18,7 +18,11 @@ This guide is referring to GrapesJS v0.14.67 or higher ## How Components work? -Let's see in detail how components work by looking at all steps from adding an HTML string to the editor. +Let's see in detail how components work by looking at all the steps from adding an HTML string to the editor. + +::: tip +All the following snippets can be run directly in console from the [main demo](https://grapesjs.com/demo.html) +::: This is how we can add new components to the canvas: @@ -38,7 +42,7 @@ editor.getWrapper().append(`
...`); ``` ::: tip -If you need to append a component in a specific position, you can use `at` option. To add a component on top of all others (in the same collection) you would use +If you need to append a component in at a specific position, you can use `at` option. So, to add a component on top of all others (in the same collection) you would use ```js component.append('
...', { at: 0 }) ``` @@ -53,7 +57,7 @@ component.append('
...', { at: parseInt(length / 2, 10) }) ### Component Definition -In the first step the HTML string is parsed and trasformed to what is called **Component Definition**, so the result of the input would be: +In the first step, the HTML string is parsed and transformed to what is called **Component Definition**, so the result of the input above would be: ```js { @@ -75,29 +79,30 @@ In the first step the HTML string is parsed and trasformed to what is called **C } ``` -The real **Component Definition** would be a little bit bigger so we reduced the JSON for the sake of simplicity. +The real **Component Definition** would be a little bit bigger so so we'd reduced the JSON for the sake of simplicity. -You can notice the result is similar to what is generally called a **Virtual DOM**, a lightweight rappresentation of the DOM element. This actually helps the editor to keep track of the state of our elements and make performance-friendly changes/updates. -The meaning of properties like `tagName`, `attributes` and `components` are quite obvious, but what about `type`?! This particular property specifies the actual **Component** of our **Component Definition** (you check the list of default components [below](#built-in-components)) and if it's omitted, the default one will be used `type: 'default'`. -At this point, a good question would be, how the editor assignes those types by starting from a simple HTML string? This step is identified as **Component Recognition** and it's explained in detail in the next paragraph. +You might notice the result is similar to what is generally called a **Virtual DOM**, a lightweight representation of the DOM element. This actually helps the editor to keep track of the state of our elements and make performance-friendly changes/updates. +The meaning of properties like `tagName`, `attributes` and `components` are quite obvious, but what about `type`?! This particular property specifies the **Component Type** of our **Component Definition** (you check the list of default components [below](#built-in-component-types)) and if it's omitted, the default one will be used `type: 'default'`. +At this point, a good question would be, how the editor assigns those types by starting from a simple HTML string? This step is identified as **Component Recognition** and it's explained in detail in the next paragraph. ### Component Recognition and Component Type Stack -As we said before, when you pass an HTML string as a component to the editor, that string is parsed and compiled to the [Component Definition](#component-definition) with a new `type` property. To understand what `type` should be assigned, for each parsed HTML Element, the editor iterates over all the defined components, called **Component Type Stack**, and checks via `isComponent` method (we will see it later) if that component type is appropriate for that element. The Component Type Stack is just a simple array of component types but what is matter is the order of those types. Any new added custom **Component Type** (we'll see later how to create them) goes on top of the Component Type Stack and each element returned from the parser iterates the stack from top to bottom (the last element of the stack is the `default` one), the iteration stops once one of the component returns a truthy value from the `isComponent` method. +As we mentioned before, when you pass an HTML string as a component to the editor, that string is parsed and compiled to the [Component Definition] with a new `type` property. To understand what `type` should be assigned, for each parsed HTML Element, the editor iterates over all the defined components, called **Component Type Stack**, and checks via `isComponent` method (we will see it later) if that component type is appropriate for that element. The Component Type Stack is just a simple array of component types but what is matter is the order of those types. Any new added custom **Component Type** (we'll see later how to create them) goes on top of the Component Type Stack and each element returned from the parser iterates the stack from top to bottom (the last element of the stack is the `default` one), the iteration stops once one of the component returns a truthy value from the `isComponent` method. -SVG - ComponentTypeStack + ::: tip -If you're importing big chunks of HTML code you might want to improve the performances by skipping the parsing and the component recognition steps by passing directly Component Definiton objects or using the JSX syntax. Read more about it here...TODO +If you're importing big string chunks of HTML code you might want to improve the performances by skipping the parsing and the component recognition steps by passing directly Component Definition objects or using the JSX syntax. +Read [here](#setup-jsx-syntax) about how to setup JSX syntax parser ::: ### Component instance -Once the **Component Definition** is ready and the type is assigned, the [Component](api/component) instance can be created (known also as the **Model**). Let's step back to our previous example with the HTML string, the result of the `append` method is an array of added components. +Once the **Component Definition** is ready and the type is assigned, the [Component] instance can be created (known also as the **Model**). Let's step back to our previous example with the HTML string, the result of the `append` method is an array of added components. ```js const component = editor.addComponents(`
@@ -120,11 +125,12 @@ You can also use methods like `getAttributes`, `setAttributes`, `components`, et ```js const innerComponents = component.components(); +innerComponents.forEach(comp => console.log(comp.toHTML())); // Update component content component.components(`
Component 1
Component 2
`); ``` -Each component can define its own properties and methods but all of them will always extend, at least, the `default` one (then you will see how to create new custom components and how to extend the already defined) so it's good to check the [Component API](api/component) to see all available properties and methods. +Each component can define its own properties and methods but all of them will always extend, at least, the `default` one (then you will see how to create new custom components and how to extend the already defined) so it's good to check the [Component API] to see all available properties and methods. The **main purpose of the Component** is to keep track of its data and to return them when necessary. One common thing you might need to ask from the component is to show its current HTML @@ -140,21 +146,21 @@ JSON.stringify(component) ``` ::: tip -For storing/loading all the components you should rely on the [Storage Manager](modules/storage) +For storing/loading all the components you should rely on the [Storage Manager](/modules/storage.html) ::: -So, the **Component instance** is responable for the **final data** (eg. HTML, JSON) of your templates. If you need, for example, to update/add some attribute in the HTML you need to update its component (eg. `component.addAttributes({ title: 'Title added' })`), so the Component/Model is your **Source of Truth**. +So, the **Component instance** is responsible for the **final data** (eg. HTML, JSON) of your templates. If you need, for example, to update/add some attribute in the HTML you need to update its component (eg. `component.addAttributes({ title: 'Title added' })`), so the Component/Model is your **Source of Truth**. ### Component rendering -Another important part of components is how they are rendered in the **canvas**, this aspect is handled by the **View** of the component. It has nothing to do with the **final data**, you can return a big `
...
` string as HTML of your component but render it as a simple image in the canvas (think about placeholders for complex/dynamic data). +Another important part of components is how they are rendered in the **canvas**, this aspect is handled by its **View**. It has nothing to do with the **final HTML data**, you can return a big `
...
` string as HTML of your component but render it as a simple image in the canvas (think about placeholders for complex/dynamic data). -So, by default, the view of components is automatically synced with the data of its models (you can't have a View without a Model). If you update the attribute of the component or append a new one as a child, the view will render it in the canvas. +By default, the view of components is automatically synced with the data of its models (you can't have a View without a Model). If you update the attribute of the component or append a new one as a child, the view will render it in the canvas. -Unfotunatelly, sometimes, you might need some additional logic to handle better the component result. Think about allowing a user build its `` element, for this specific case you might want to add custom buttons in the canvas, so it'd be easier adding/removing columns/rows. To handle those cases you can rely on the View, where you can add additional DOM component, attach events, etc. All of this will be completely unrelated with the final HTML of the `
` (the result the user would expect) as it handled by the Model. -Once the component is rendered (when you actually see it in the canvas) you can always access its View and the DOM element. +Unfortunately, sometimes, you might need some additional logic to handle better the component result. Think about allowing a user build its `
` element, for this specific case you might want to add custom buttons in the canvas, so it'd be easier adding/removing columns/rows. To handle those cases you can rely on the View, where you can add additional DOM component, attach events, etc. All of this will be completely unrelated with the final HTML of the `
` (the result the user would expect) as it handled by the Model. +Once the component is rendered you can always access its View and the DOM element. ```js const component = editor.getSelected(); @@ -164,10 +170,10 @@ const view = component.getView(); const el = component.getEl(); ``` -So, generally, the View is something you wouldn't need to change as the default one handles already the sync with the Model but in case you'd need more control over elements (eg. custom UI in canvas) you'll probably need to create a custom component type and extend the default View with your logic. We'll see later how to create custom Component Types. +Generally, the View is something you wouldn't need to change as the default one handles already the sync with the Model but in case you'd need more control over elements (eg. custom UI in canvas) you'll probably need to create a custom component type and extend the default View with your logic. We'll see later how to create custom Component Types. -So far we have seen the core concept behind Components and how they work. The **Model/Component** is the **source of truth** for the final code of templates (eg. the HTML export relies on it) and the *View/ComponentView* is what is used by the editor to **preview our components** to users in the canvas. +So far we have seen the core concept behind Components and how they work. The **Model/Component** is the **source of truth** for the final code of templates (eg. the HTML export relies on it) and the **View/ComponentView** is what is used by the editor to **preview our components** to users in the canvas.