diff --git a/docs/documentation/state/index.md b/docs/documentation/state/index.md index 3960d14a..3b65e0ad 100644 --- a/docs/documentation/state/index.md +++ b/docs/documentation/state/index.md @@ -15,6 +15,10 @@ state: (initialValue: T, sub?: StateSubscriber) => readonly[(StateGetter, StateSetter, StateUnSubscriber)] ``` +State, when used in templates allow the DOM to only update where needed. + +Markup templates do no traverse the DOM to check for updates and the state itself will only notify the template after verifying that the data has changed with a shallow comparison. That allows the DOM to only update when and where necessary. + ### Input You can provide an `initialValue` to start the state as well as a `StateSubscriber` which is function that will get called every time the state changes. diff --git a/docs/documentation/templating/values.md b/docs/documentation/templating/values.md index df08ad76..19231f76 100644 --- a/docs/documentation/templating/values.md +++ b/docs/documentation/templating/values.md @@ -51,6 +51,34 @@ const type = 'button' html`` ``` +### Node + +Markup templates work seamlessly with DOM nodes and this ability allows you to migrate any vanilla JavaScript solution easily to Markup templates. + +You can inject any Node directly in the template and they will be rendered just fine. + +```javascript +const button = document.createElement('button') +button.textContent = 'click me' +button.type = 'button' + +html`${button}`.render(document.body) +``` + +### HTMLTemplate + +Another thing you can inject in the templates for powerful compositions are the template instances themselves. + +```javascript +const button = html`` + +html`${button}`.render(document.body) +``` + +This simple capability allows you to declare, store, and move around templates like you would with any data. This behavior resembles working with nodes in vanilla JavaScript and makes it easier to share and compose templates to build complex views. + +Another benefits of composing templates is the fact that each template are tracked separately allowing only the part of the DOM to update when needed. + ### Arrays Injected arrays will have their items rendered as they are. This makes it super easy to render lists in general and comes handy with data handling. diff --git a/docs/documentation/utilities/element.md b/docs/documentation/utilities/element.md index cdd1249f..517e8b1a 100644 --- a/docs/documentation/utilities/element.md +++ b/docs/documentation/utilities/element.md @@ -7,3 +7,77 @@ layout: document --- ## Element Utility + +```typescript +interface ElementOptions { + attributes?: A + textContent?: string + htmlContent?: string + ns?: 'http://www.w3.org/1999/xhtml' | 'http://www.w3.org/2000/svg' +} + +type element = (tagName: string, options?: ElementOptions) => Element +``` + +The `element` attribute is simply a function that allows you to create DOM elements in one call. + +Normally, when working with DOM elements we create and piece them together after. + +```javascript +const button = document.createElement('button') +button.type = 'button' +button.textContent = 'click me' + +button.addEventListener('click', () => { + console.log('clicked') +}) +``` + +This is a lot of steps to create a simple button. Here is the same thing using `element`: + +```javascript +const button = element('button', { + textContent: 'click me', + attributes: { + type: 'button', + onclick: () => { + console.log('clicked') + }, + }, +}) +``` + +The `element` uses `addEventListener` behind the scenes and handles non-primitive values for you by easily detecting web component elements. + +### Web components + +The best part of working with `element` is with web components. It will handle all non-primitive props to ensure the web components get data as they should. + +```javascript +const item = element('todo-item', { + attributes: { + data: { + id: crypto.randomUUID(), + name: 'buy groceries', + status: 'pending', + dateCreated: new Date(), + }, + }, +}) +``` + +### SVG elements + +To create SVG elements you can specify the `ns` option with the value of `http://www.w3.org/2000/svg` and that will give you any SVG element. + +```javascript +const rect = element('rect', { + ns: 'http://www.w3.org/2000/svg', + attributes: { + x: 10, + y: 10, + width: 100, + height: 100, + }, +}) +``` diff --git a/docs/documentation/utilities/index.md b/docs/documentation/utilities/index.md index 34758d26..be22aae8 100644 --- a/docs/documentation/utilities/index.md +++ b/docs/documentation/utilities/index.md @@ -38,7 +38,7 @@ Utilities are just functions that rendered in template and that need to be calle The power with working with states and template comes when you start defining your own utilities. Let's look at a quick example: -We have a common scenario where we have a input value that uses state and we need to display a certain message whether the value is valid or not. +We have a common scenario where we have a input field that uses state and we need to display a certain message whether the value is valid or not. ```javascript const [value, updateValue] = state(null) @@ -67,7 +67,9 @@ html` `.render(document.body) ``` -Now I also realize that i want to mark the field red when the input is bad and that relies on the same logic. So, i can extract that logic into a function for reusability: +This is not bad but logic in the template takes space and lots of them makes template hard to read. + +I realized that i want to mark the field red when the input is invalid and that relies on the same logic we have in the function. So, i can extract that logic into a function for reusability: ```javascript const [value, updateValue] = state(null) @@ -117,9 +119,11 @@ html` `.render(document.body) ``` -This ability to just create and compose functions to handle everything is what further makes templating easy and fun to do. +You can see that we have functions that handle different logic composing them for even more complex logic dependent on the state. + +This ability to just create and compose functions to handle everything is what further makes templating easy and fun in Markup. -We can further things up by introducing a utility for handling form values that we can use with multiple form fields at once. +We can further things up by wrapping everything in a reusable utility for handling form input values of any kind that we can use with multiple form fields. ```javascript const formFieldValue = (pattern) => { @@ -163,7 +167,7 @@ html` style="color: ${name.color}" /> ${when( - name.pristineOrValid, + name.isPristineOrValid, html`

Your name

`, html`

Name must be at least 3 characters @@ -177,11 +181,11 @@ html` style="color: ${email.color}" /> ${when( - email.pristineOrValid, + email.isPristineOrValid, html`

Your email

`, html`

Email is not valid

` )} `.render(document.body) ``` -As you can see, when it comes to reactivity, Markup relies heavily and solely on functions to get the job done. This function oriented nature makes templating simple and somehow familiar to anyone. +As you can see, when it comes to reactivity, Markup relies heavily and solely on functions to get the job done. This function oriented nature makes templating simple and somehow familiar to anyone. Give it a try!