nbhi 0.6.0 → 0.6.1
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.
- package/README.md +164 -122
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,25 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
**HTML includes and reactive rendering, all without any build tools**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
No-build HTML includes (NBHI) is a simple **3.9KB** library that allows you to include html files into other html files and turns them into [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components). Lazy initialization of content (when entering the viewport) and a one line call to update/hydrate content and attributes in your html pages. No build tools required, no `package.json` needed.
|
|
6
6
|
|
|
7
7
|
# Why?
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
NBHI is developed to create real-time data driven web sites. It has lower complexity than typical SPA applications but still offers more interactivy and flexibility than server side rendered web sites. _It works well with serverless application and a pub/sub data model_.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
NBHI is designed to be composable with other packages to build web sites. It takes the Lego approach, you select the packages for your needs, no lock-in into a single framework with a potential steep learning curve. NBHI is build on standard browser supported technologies which means that you only need to read MDN as the source of knowledge.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
NBHI minimizes abstractions, just standard HTML, CSS and Javascript. Migrating from a SPA to NBHI's multi page application (MPA) approach should mean you can do this one page at the time not having to migrate your whole system at once and pray that everything keeps working.
|
|
14
14
|
|
|
15
15
|
# Benefits
|
|
16
16
|
|
|
17
|
-
-
|
|
18
|
-
- Lightweight: **~
|
|
17
|
+
- No-build web applications (you can still make it a dependency via npm install) 👍
|
|
18
|
+
- Lightweight: **~3.9KB** (minified and bundled) 👍
|
|
19
|
+
- No dependencies 👍
|
|
19
20
|
- Benefit from standard web component encapsulation 👍
|
|
20
21
|
- Lazy load page content, when about to enter the viewport 👍
|
|
21
22
|
- Just standard web technologies, little abstractions 👍
|
|
22
|
-
-
|
|
23
|
-
- Support for
|
|
23
|
+
- Simple single function to hydrate your html (including attributes) 👍
|
|
24
|
+
- Support for form validation for web component based html fields 👍
|
|
25
|
+
- Composable with other packages 👍
|
|
24
26
|
- Multi Page Application (MPA) design
|
|
25
27
|
- The standard method how the web communicates between server and client 👍
|
|
26
28
|
- Normal native routing 👍
|
|
@@ -28,6 +30,23 @@ d--b minimizes abstractions, just standard HTML, CSS and Javascript. Migrating f
|
|
|
28
30
|
- Each page loads what it needs and no more 👍
|
|
29
31
|
- Fast initial draw 👍
|
|
30
32
|
|
|
33
|
+
# Install
|
|
34
|
+
|
|
35
|
+
For no-build solutions:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
<script type="module">
|
|
39
|
+
import { initialize } from 'https://esm.run/nbhi@x.x.x';
|
|
40
|
+
await initialize();
|
|
41
|
+
</script>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For build solutions
|
|
45
|
+
|
|
46
|
+
```cli
|
|
47
|
+
npm install nbhi
|
|
48
|
+
```
|
|
49
|
+
|
|
31
50
|
# Examples
|
|
32
51
|
|
|
33
52
|
Please look in the **examples.html** for working examples.
|
|
@@ -43,30 +62,34 @@ Templates let you build complex systems and reuse components accross multiple pa
|
|
|
43
62
|
index.html
|
|
44
63
|
|
|
45
64
|
```html
|
|
46
|
-
|
|
47
65
|
<html>
|
|
48
66
|
<body>
|
|
49
67
|
<my-component>Overwritten text</my-component>
|
|
50
68
|
|
|
51
69
|
<script type="module">
|
|
52
|
-
import initialize from '/
|
|
53
|
-
await initialize(); // await if
|
|
70
|
+
import initialize from '/NBHI.js';
|
|
71
|
+
await initialize(); // await if external templates
|
|
54
72
|
</script>
|
|
55
73
|
</body>
|
|
56
74
|
</html>
|
|
57
|
-
|
|
58
75
|
```
|
|
59
76
|
|
|
60
|
-
/components/
|
|
77
|
+
/components/component.html
|
|
61
78
|
|
|
62
79
|
```html
|
|
63
|
-
|
|
64
80
|
<div>
|
|
65
81
|
<slot>Default text</slot>
|
|
66
82
|
</div>
|
|
67
83
|
|
|
68
84
|
<style>/* Scoped to the web component */</style>
|
|
69
85
|
|
|
86
|
+
<script>
|
|
87
|
+
// Runs for each instance, fires on the standard connectedCallback
|
|
88
|
+
// element is the web component instance
|
|
89
|
+
export default element => {
|
|
90
|
+
...
|
|
91
|
+
}
|
|
92
|
+
</script>
|
|
70
93
|
```
|
|
71
94
|
|
|
72
95
|
### Internal templates
|
|
@@ -74,9 +97,9 @@ index.html
|
|
|
74
97
|
index.html
|
|
75
98
|
|
|
76
99
|
```html
|
|
77
|
-
|
|
78
100
|
<html>
|
|
79
101
|
<body>
|
|
102
|
+
<!-- id becomes the name of your web component -->
|
|
80
103
|
<template id="my-component">
|
|
81
104
|
<slot>Default</slot>
|
|
82
105
|
<style>/* Scoped to the web component */</style>
|
|
@@ -85,180 +108,199 @@ index.html
|
|
|
85
108
|
<my-component>Overwrite</my-component>
|
|
86
109
|
|
|
87
110
|
<script type="module">
|
|
88
|
-
import initialize from '/
|
|
111
|
+
import initialize from '/NBHI.js';
|
|
89
112
|
initialize(); // No await needed for internal templates
|
|
90
113
|
</script>
|
|
91
114
|
</body>
|
|
92
115
|
</html>
|
|
93
|
-
|
|
94
116
|
```
|
|
95
117
|
|
|
96
|
-
_Note: When you use an internal `<template>` you need to define an id, which will be the name of the tag._
|
|
97
|
-
|
|
98
118
|
## Options
|
|
99
119
|
|
|
100
120
|
```js
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Options for initiating an instance
|
|
104
|
-
* @param {string} [prefix=db]
|
|
105
|
-
* @param {string} [source=/components]
|
|
106
|
-
**/
|
|
107
|
-
|
|
108
|
-
import initialize from 'd--b.js'
|
|
109
|
-
initialize({
|
|
110
|
-
// Prefix to use, ie <db-input> or <db-nav>
|
|
111
|
-
prefix: 'db',
|
|
112
|
-
// Where to find external web components, if string it will be a director
|
|
113
|
-
// when using an object the key is the name (without prefix) of the component
|
|
114
|
-
// and the value the path to the web-component
|
|
115
|
-
directory: '/components',
|
|
116
|
-
});
|
|
117
|
-
|
|
121
|
+
initialize({ prefix = 'my', directory = '/components' }); // Defaults
|
|
118
122
|
```
|
|
119
123
|
|
|
120
|
-
## Methods
|
|
121
|
-
|
|
122
|
-
### .setSlot(value, [slotName], [htmlSelector])
|
|
123
|
-
|
|
124
124
|
```js
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* @param {string} value - What you want to assign to a <slot>
|
|
128
|
-
* @param {string} [slotName] - If not given value is assigned to default <slot>
|
|
129
|
-
* @param {string} [htmlSelector] - Target a html tag in a complex <slot>
|
|
130
|
-
**/
|
|
125
|
+
initialize({ prefix: 'x' }); // Components are now x-component
|
|
126
|
+
```
|
|
131
127
|
|
|
132
|
-
|
|
128
|
+
```js
|
|
129
|
+
initialize({ components: '/abc' }); // Fetches files in /abc/component.html
|
|
130
|
+
```
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
```js
|
|
133
|
+
// key = name of component (no prefix), value is path to file
|
|
134
|
+
initialize({ components: {
|
|
135
|
+
nav: '/shared/nav.html',
|
|
136
|
+
dropdown: '/components/dropdown.html'
|
|
137
|
+
} });
|
|
138
|
+
```
|
|
136
139
|
|
|
137
|
-
|
|
138
|
-
element.setSlot('Some text', 'title');
|
|
140
|
+
## Update a single component (data and attributes)
|
|
139
141
|
|
|
140
|
-
|
|
141
|
-
element.setSlot('Some text', 'title', 'em');
|
|
142
|
+
### Via HTML
|
|
142
143
|
|
|
144
|
+
```html
|
|
145
|
+
<!-- Instance -->
|
|
146
|
+
<my-component checked data-id="1">
|
|
147
|
+
Text here will be assigned to the default slot
|
|
148
|
+
<span slot="title">Will be assigned to the named slot</span>
|
|
149
|
+
</my-component>
|
|
150
|
+
|
|
151
|
+
<!-- Component definition -->
|
|
152
|
+
<section data-id=""> <!-- Data and custom attributes need to be defined so NBHI can resolve them -->
|
|
153
|
+
<input type="checkbox"> <!-- NBHI automatically maps common attributes, checked will be placed on the input -->
|
|
154
|
+
<slot>Default text</slot>
|
|
155
|
+
<slot name="title">Default title</slot>
|
|
156
|
+
</section>
|
|
143
157
|
```
|
|
144
158
|
|
|
145
|
-
###
|
|
159
|
+
### Via JS
|
|
146
160
|
|
|
147
161
|
```js
|
|
148
|
-
|
|
149
|
-
* Updates one or more records in the child template
|
|
150
|
-
* @param {object|object[]} data - The data to use
|
|
151
|
-
**/
|
|
162
|
+
import { update } from 'nbhi';
|
|
152
163
|
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
// Update a single child, with data-slot named "title"
|
|
156
|
-
element.setChildren({ title: 'Some value' });
|
|
164
|
+
const updater = update('my-component');
|
|
157
165
|
|
|
166
|
+
updater('Text here will be assigned to the default slot');
|
|
167
|
+
updater({ title: 'Will be assigned to the named slot' });
|
|
168
|
+
updater({ $checked: true, `$data-id`: 1 }); // Atributes are prefixed with $
|
|
158
169
|
```
|
|
159
170
|
|
|
160
|
-
|
|
171
|
+
## Update a list (data and attributes)
|
|
161
172
|
|
|
162
|
-
###
|
|
173
|
+
### Inline child
|
|
163
174
|
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Runs one time when the web component comes into view
|
|
167
|
-
* @param {function} callback - Callback to run
|
|
168
|
-
**/
|
|
169
|
-
document.querySelector('my-component').onceVisible(element => {
|
|
170
|
-
subscribeToData('someCollection', data => element.setChildren(data));
|
|
171
|
-
});
|
|
175
|
+
/components/component.html
|
|
172
176
|
|
|
177
|
+
```html
|
|
178
|
+
<div>
|
|
179
|
+
<h1><slot>Header</slot></h1>
|
|
180
|
+
<div child> <!-- NBHI uses child attribute to make clones from -->
|
|
181
|
+
<p data-slot="name"></p> <!-- use data-slot for inline children -->
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
173
184
|
```
|
|
174
185
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
```js
|
|
178
|
-
/**
|
|
179
|
-
* Checks if the field is valid
|
|
180
|
-
* @returns boolean
|
|
181
|
-
**/
|
|
182
|
-
document.querySelector('my-form-field').checkValidity();
|
|
186
|
+
index.html
|
|
183
187
|
|
|
188
|
+
```html
|
|
189
|
+
<my-component>Header overwrite</my-component>
|
|
190
|
+
|
|
191
|
+
<script>
|
|
192
|
+
import { initialize, update } from 'nbhi';
|
|
193
|
+
await initialize();
|
|
194
|
+
update('my-component')([
|
|
195
|
+
{ name: 'Record 1' },
|
|
196
|
+
{ name: 'Record 2' },
|
|
197
|
+
]);
|
|
198
|
+
</script>
|
|
184
199
|
```
|
|
185
200
|
|
|
186
|
-
###
|
|
201
|
+
### Child component
|
|
187
202
|
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Get the standard validity object
|
|
191
|
-
* @returns ValidityState
|
|
192
|
-
**/
|
|
193
|
-
document.querySelector('my-form-field').validity;
|
|
203
|
+
/components/component.html
|
|
194
204
|
|
|
205
|
+
```html
|
|
206
|
+
<div>
|
|
207
|
+
<h1><slot>Header</slot></h1>
|
|
208
|
+
<my-child child></my-child> <!-- NBHI uses child attribute to make clones from -->
|
|
209
|
+
</div>
|
|
195
210
|
```
|
|
196
211
|
|
|
197
|
-
|
|
212
|
+
/components/child.html
|
|
198
213
|
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
214
|
+
```html
|
|
215
|
+
<div>
|
|
216
|
+
<p><slot></slot></p> <!-- use regular slot for nested components -->
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
index.html
|
|
205
221
|
|
|
222
|
+
```html
|
|
223
|
+
<my-component>Header overwrite</my-component>
|
|
224
|
+
|
|
225
|
+
<script>
|
|
226
|
+
import { initialize, update } from 'nbhi';
|
|
227
|
+
await initialize();
|
|
228
|
+
update('my-component')(['Record 1', 'Record 2']);
|
|
229
|
+
</script>
|
|
206
230
|
```
|
|
207
231
|
|
|
208
|
-
###
|
|
232
|
+
### List data for `<table>, <ol>, <li> and <option>`
|
|
209
233
|
|
|
210
|
-
|
|
234
|
+
These elements do not support web component children. So for these you can just define the following
|
|
211
235
|
|
|
212
236
|
index.html
|
|
213
237
|
|
|
214
238
|
```html
|
|
239
|
+
<template id="my-table">
|
|
240
|
+
<table>
|
|
241
|
+
<thead>
|
|
242
|
+
<tr>
|
|
243
|
+
<th>Header</th>
|
|
244
|
+
</tr>
|
|
245
|
+
</thead>
|
|
246
|
+
<tbody> <!-- Required -->
|
|
247
|
+
<tr> <!-- No need for child attribute -->
|
|
248
|
+
<td data-slot="name"></td>
|
|
249
|
+
</tr>
|
|
250
|
+
</tbody>
|
|
251
|
+
</table>
|
|
252
|
+
</template>
|
|
253
|
+
|
|
254
|
+
index.html
|
|
215
255
|
|
|
216
|
-
<my-
|
|
256
|
+
<my-table></my-table>
|
|
217
257
|
|
|
258
|
+
<script>
|
|
259
|
+
import { initialize, update } from 'nbhi';
|
|
260
|
+
await initialize();
|
|
261
|
+
update('my-table')([
|
|
262
|
+
{ name: 'Record 1' },
|
|
263
|
+
{ name: 'Record 2' },
|
|
264
|
+
]);
|
|
265
|
+
</script>
|
|
218
266
|
```
|
|
219
267
|
|
|
220
|
-
|
|
268
|
+
Same logic for `<ol>`, `<ul>` and `<option>`
|
|
221
269
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
-->
|
|
227
|
-
<label data-id="">
|
|
228
|
-
<slot></slot>
|
|
229
|
-
<!-- d--b knows to add value and read only to the input field --->
|
|
230
|
-
<input type="email" placeholder="email">
|
|
231
|
-
</div>
|
|
270
|
+
## Lazy loading
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
import { onceVisible } form 'nbhi';
|
|
232
274
|
|
|
275
|
+
onceVisible('my-component', element => ...); // Will run once when it comes into view (200px before)
|
|
233
276
|
```
|
|
234
277
|
|
|
278
|
+
## Validating a form field
|
|
279
|
+
|
|
235
280
|
```js
|
|
281
|
+
import { validate } form 'nbhi';
|
|
236
282
|
|
|
237
|
-
|
|
238
|
-
const element = document.querySelector('my-component')
|
|
239
|
-
element.setAttribute('value', 'Some value');
|
|
240
|
-
element.disabled = true;
|
|
283
|
+
const internals = validate('my-form-field'); // Returns elementInternals
|
|
241
284
|
|
|
285
|
+
// See MDN for details
|
|
286
|
+
internals.checkValidity();
|
|
287
|
+
internals.validity;
|
|
242
288
|
```
|
|
243
289
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
# FAQ
|
|
247
|
-
|
|
248
|
-
### How to pronounce d--b?
|
|
249
|
-
However you like.
|
|
290
|
+
## FAQ
|
|
250
291
|
|
|
251
292
|
### No build steps is nice, but I want to use TypeScript
|
|
293
|
+
|
|
252
294
|
If you want to use TS you have a couple of options. You can either add a build step, nothing is stopping you, the library supports it. If you want to stay buildless but want to add some sort of type checking and hinting you can consider using JSDoc, it is [supported](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#author) in TS as well.
|
|
253
295
|
|
|
254
296
|
### Creating interactivity is verbose with native js DOM manipulation
|
|
255
|
-
d--b is not designed to be a single solution for everything, if you want to make DOM manipulation for interactivity easier I would suggest using dedicated libraries for that. You can consider [Alpine.js](https://alpinejs.dev/) or [Umbrella.js](https://umbrellajs.com/) for example. d--b is designed with composibility in mind so you decide what to add.
|
|
256
297
|
|
|
257
|
-
|
|
258
|
-
You could load them from a CDN if you want to stay 100% buildless, otherwise you could just add a simple minifier and bundler. This will stay very lightweight but probably is more suitable for production environments.
|
|
298
|
+
NBHI is not designed to be a single solution for everything, if you want to make DOM manipulation for interactivity easier I would suggest using dedicated libraries for that. You can consider [Alpine.js](https://alpinejs.dev/) or [Umbrella.js](https://umbrellajs.com/) for example. NBHI is designed with composibility in mind so you decide what to add.
|
|
259
299
|
|
|
260
300
|
### Anybody using web component technology?
|
|
301
|
+
|
|
261
302
|
Just check out the source code of github.com or youtube.com.
|
|
262
303
|
|
|
263
304
|
### We are a team of multiple developers, using a framework ensures we write similar code
|
|
264
|
-
|
|
305
|
+
|
|
306
|
+
You are correct, when you choose a more opinionated framework it will most likely give more cohesive code overall when you work with multiple developers. However it also gives you lock-in. It is a trade-off that you have to make, depending on the team size and how agile your codebase needs to remain.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nbhi",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "No-Build HTML Includes (NBHI) is a simple library that allows you to include html files into other html files and turns them into [web components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components). Lazy initialization of content (when entering the viewport) and a one line call to update/hydrate content in your html pages. No build tools required, no `package.json` needed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components",
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
"multi-page-application",
|
|
14
14
|
"composable"
|
|
15
15
|
],
|
|
16
|
-
"homepage": "https://github.com/royniels/
|
|
16
|
+
"homepage": "https://github.com/royniels/nbhi#readme",
|
|
17
17
|
"bugs": {
|
|
18
|
-
"url": "https://github.com/royniels/
|
|
18
|
+
"url": "https://github.com/royniels/nbhi/issues"
|
|
19
19
|
},
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
|
-
"url": "git+https://github.com/royniels/
|
|
22
|
+
"url": "git+https://github.com/royniels/nbhi.git"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"./index.min.js"
|