@webqit/oohtml 3.0.1-12 → 3.0.1-3

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.
Files changed (2) hide show
  1. package/README.md +130 -180
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -375,7 +375,7 @@ setTimeout(() => abortController.abort(), 1000);
375
375
 
376
376
  We can defer module loading until we really need them.
377
377
 
378
- Here, we get the `loading="lazy"` directive for that; and loading is only then triggered on the first attempt to import their contents:
378
+ Here, we get the `loading="lazy"` directive for that; and loading is only then triggered on the first attempt to import its contents:
379
379
 
380
380
  ```html
381
381
  <!-- Loading doesn't happen until the first time this is being accessed -->
@@ -593,42 +593,12 @@ Here, we get a comment-based data-binding tag `<?{ }?>` which works like regular
593
593
  <title><?{ app.title }?></title>
594
594
  </head>
595
595
  <body>
596
- Hi, I'm <?{ name ?? 'Default name' }?>!
597
- and here's another way to write the same comment: <!--?{ cool }?-->
596
+ Hi, I'm <?{ app.name ?? 'Default name' }?>!
597
+ and here's another way to write the same comment: <!--?{ app.cool }?-->
598
598
  </body>
599
599
  </html>
600
600
  ```
601
601
 
602
- <details><summary>Resolution details</summary>
603
-
604
- Here, JavaScript references are resolved from the closest node up the document hierarchy that exposes a corresponding *binding* on its Bindings API ([discussed below](#bindings-api)). Thus, for the above markup, our underlying data structure could be anything like the below:
605
-
606
- ```js
607
- document.bind({ name: 'James Boye', cool: '100%', app: { title: 'Demo App' } });
608
- document.body.bind({ name: 'John Doe' });
609
- ```
610
-
611
- ```js
612
- document: { name: 'James Boye', cool: '100%', app: { title: 'Demo App' } }
613
- └── html
614
- ├── head
615
- └── body: { name: 'John Doe' }
616
- ```
617
-
618
- Now, the `name` reference remains bound to the `name` *binding* on the `<body>` element until the meaning of "closest node" changes again:
619
-
620
- ```js
621
- delete document.body.bindings.name;
622
- ```
623
-
624
- While the `cool` reference remains bound to the `cool` *binding* on the `document` node until the meaning of "closest node" changes again:
625
-
626
- ```js
627
- document.body.bindings.cool = '200%';
628
- ```
629
-
630
- </details>
631
-
632
602
  <details><summary>With SSR Support</summary>
633
603
 
634
604
  On the server, these data-binding tags would retain their place in the DOM while having their output rendered to their right in a text node.
@@ -677,7 +647,7 @@ Here, we get the `binding` attribute for a declarative and neat, key/value data-
677
647
 
678
648
  | Directive | Type | Usage |
679
649
  | :---- | :---- | :---- |
680
- | `&` | CSS Property | `<div binding="& color:someColor; & backgroundColor:someBgColor;"></div>` |
650
+ | `&` | CSS Property | `<div binding="& color:someColor; & backgroundColor:someColor;"></div>` |
681
651
  | `%` | Class Name | `<div binding="% active:app.isActive; % expanded:app.isExpanded;"></div>` |
682
652
  | `~` | Attribute Name | `<a binding="~ href:person.profileUrl+'#bio'; ~ title:'Click me';"></a>` |
683
653
  | | Boolean Attribute | `<a binding="~ ?required:formField.required; ~ ?aria-checked: formField.checked"></a>` |
@@ -706,53 +676,23 @@ Here, we get the `binding` attribute for a declarative and neat, key/value data-
706
676
 
707
677
  </details>
708
678
 
709
- <details><summary>Resolution details</summary>
710
-
711
- Here, JavaScript references are resolved from the closest node up the document hierarchy that exposes a corresponding *binding* on its Bindings API ([discussed below](#bindings-api)). Thus, for the above CSS bindings, our underlying data structure could be anything like the below:
712
-
713
- ```js
714
- document.bind({ someColor: 'green', someBgColor: 'yellow' });
715
- document.body.bind({ someBgColor: 'silver' });
716
- ```
717
-
718
- ```js
719
- document: { someColor: 'green', someBgColor: 'yellow' }
720
- └── html
721
- ├── head
722
- └── body: { someBgColor: 'silver' }
723
- ```
724
-
725
- Now, the `someBgColor` reference remains bound to the `someBgColor` *binding* on the `<body>` element until the meaning of "closest node" changes again:
726
-
727
- ```js
728
- delete document.body.bindings.someBgColor;
729
- ```
730
-
731
- While the `someColor` reference remains bound to the `someColor` *binding* on the `document` node until the meaning of "closest node" changes again:
732
-
733
- ```js
734
- document.body.bindings.someColor = 'brown';
735
- ```
736
-
737
- </details>
738
-
739
679
  <details><summary>All in realtime</summary>
740
680
 
741
- Bindings are resolved in realtime! And in fact, for lists, in-place mutations - additions and removals - on the *iteratee* are automatically reflected on the UI!
681
+ Lists are rendered in realtime, which means that in-place mutations - additions and removals - on the *iteratee* will be automatically reflected on the UI!
742
682
 
743
683
  </details>
744
684
 
745
685
  <details><summary>With SSR Support</summary>
746
686
 
747
- For lists, generated item elements are automatically assigned a corresponding index with a `data-index` attribute! This helps in remapping generated item nodes to their respective entry in *iteratee* - universally.
687
+ Generated item elements are automatically assigned a corresponding index with a `data-index` attribute! This helps in remapping generated item nodes to their respective entry in *iteratee* - universally.
748
688
 
749
689
  </details>
750
690
 
751
691
  ### Quantum Scripts
752
692
 
753
- We often still need to write more serious reactive logic on the UI than a declarative data-binding language can provide for. But we shouldn't need to reach for special tooling or some "serious" programming paradigm on top of JavaScript.
693
+ We often still need to write more serious reactive logic on the UI than a declarative data-binding language can provide. But we shouldn't need to reach for special tooling or some "serious" programming paradigm on top of JavaScript.
754
694
 
755
- Here, from the same `<script>` element we already write, we get a direct upgrade path to reactive programming in just an attribute: `quantum`:
695
+ Here, from the same `<script>` element we write everyday, we get a direct upgrade path to reactive programming in just an attribute: `quantum`:
756
696
 
757
697
  ```html
758
698
  <script quantum>
@@ -849,17 +789,9 @@ It's Imperative Reactive Programming ([IRP](https://en.wikipedia.org/wiki/Reacti
849
789
 
850
790
  Here, the runtime executes your code in a special execution mode that gets literal JavaScript expressions to statically reflect changes. This makes a lot of things possible on the UI! The [Quantum JS](https://github.com/webqit/quantum-js) documentation has a detailed run down.
851
791
 
852
- Now, in each case above, reactivity terminates on script's removal from the DOM. And a programmatic termination is sill possible:
853
-
854
- ```js
855
- const script = document.querySelector('script[quantum]');
856
- // const script = document.querySelector('main').scripts[0];
857
- script.abort();
858
- ```
859
-
860
- But while that is automatic, DOM event handlers bound via `addEventListener()` would still need to be terminated in their own way.
792
+ Now, in each case above, reactivity terminates on script's removal from the DOM. But of course, DOM event handlers bound via `addEventListener()` would still need to be terminated in their own way.
861
793
 
862
- </details>
794
+ <details>
863
795
 
864
796
  ## Data Plumbing
865
797
 
@@ -960,7 +892,7 @@ Observer.set(element, 'liveProperty'); // Live expressions rerun
960
892
 
961
893
  ## Polyfill
962
894
 
963
- OOHTML is being developed as something to be used todayvia a polyfill. This is an active and intentional effort that continues to ensure that the project evolves through a practice-driven process.
895
+ OOHTML is being developed as something to be used today - via a polyfill.
964
896
 
965
897
  <details><summary>Load from a CDN<br>
966
898
  └───────── <a href="https://bundlephobia.com/result?p=@webqit/oohtml"><img align="right" src="https://img.shields.io/bundlephobia/minzip/@webqit/oohtml?label=&style=flat&colorB=black"></a></summary>
@@ -981,8 +913,9 @@ OOHTML is being developed as something to be used today—via a polyfill. This i
981
913
 
982
914
  </details>
983
915
 
984
- <details><summary>Install from NPM<br>
985
- └───────── <a href="https://npmjs.com/package/@webqit/oohtml"><img align="right" src="https://img.shields.io/npm/v/@webqit/oohtml?style=flat&label=&colorB=black"></a></summary>
916
+ <details><summary>Extended usage concepts</summary>
917
+
918
+ To use the polyfill on server-side DOM instances as made possible by libraries like [jsdom](https://github.com/jsdom/jsdom), simply install and initialize the library `@webqit/oohtml` with the DOM instance:
986
919
 
987
920
  ```bash
988
921
  npm i @webqit/oohtml
@@ -996,15 +929,9 @@ import init from '@webqit/oohtml';
996
929
  init.call( window[, options = {} ]);
997
930
  ```
998
931
 
999
- To use the polyfill on server-side DOM instances as made possible by libraries like [jsdom](https://github.com/jsdom/jsdom), simply install and initialize the library `@webqit/oohtml` with the DOM instance as above.
932
+ But all things "SSR" for OOHTML are best left to the [`@webqit/oohtml-ssr`](https://github.com/webqit/oohtml-ssr) package!
1000
933
 
1001
- But all things "SSR" for OOHTML are best left to the [`@webqit/oohtml-ssr`](https://github.com/webqit/oohtml-ssr) package!
1002
-
1003
- </details>
1004
-
1005
- <details><summary>Extended usage concepts</summary>
1006
-
1007
- If you'll be going ahead to build a real app to see OOHTML in action, you may want to consider also using:
934
+ Also, if you'll be going ahead to build a real app to see OOHTML in action, you may want to consider also using:
1008
935
 
1009
936
  + the [`@webqit/oohtml-cli`](https://github.com/webqit/oohtml-cli) package for operating a file-based templating system.
1010
937
 
@@ -1042,7 +969,7 @@ If you'll be going ahead to build a real app to see OOHTML in action, you may wa
1042
969
 
1043
970
  ...still gives the `window` object in the console.
1044
971
 
1045
- + **Scoped/Quantum Scripts**. This feature is an extension of [Quantum JS](https://github.com/webqit/quantum-js) and the default OOHTML build is based on the [Quantum JS Lite APIs](https://github.com/webqit/quantum-js#quantum-js-lite). Now, while Quantum JS Lite yields faster load times, it also means that `<script quantum></script>` and `<script scoped></script>` elements are parsed "asynchronously", in the same timing as `<script type="module"></script>`!
972
+ + **Scoped/Quantum Scripts**. This feature is an extension of [Quantum JS](https://github.com/webqit/quantum-js). The default OOHTML build is based on the [Quantum JS Lite APIs](https://github.com/webqit/quantum-js#quantum-js-lite) and this means that `<script quantum></script>` and `<script scoped></script>` elements are parsed "asynchronously", in the same timing as `<script type="module"></script>`!
1046
973
 
1047
974
  This timing works perfectly generally, but if you have a requirment to have classic scripts follow their [native synchronous timing](https://html.spec.whatwg.org/multipage/parsing.html#scripts-that-modify-the-page-as-it-is-being-parsed), then you'd need to use the *realtime* OOHTML build:
1048
975
 
@@ -1100,72 +1027,84 @@ If you'll be going ahead to build a real app to see OOHTML in action, you may wa
1100
1027
 
1101
1028
  ## Examples
1102
1029
 
1103
- Here are a few examples in the wide range of use cases these features cover. While we'll demonstrate the most basic forms of these scenarios, it takes roughly the same principles to build an intricate form and a highly interactive UI.
1030
+ Here are a few examples in the wide range of use cases these features cover.
1031
+
1032
+ + [Example 1: *Single Page Application*](#example-1-single-page-application)
1033
+ + [Example 2: *Multi-Level Namespacing*](#example-2-multi-level-namespacing)
1034
+ + [Example 3: *Dynamic Shadow DOM*](#example-3-dynamic-shadow-dom)
1035
+ + [Example 4: *Declarative Lists*](#example-4-declarative-lists)
1036
+ + [Example 5: *Imperative Lists*](#example-4-imperative-lists)
1104
1037
 
1105
- <details><summary>Example 1: <i>Single Page Application</i><br>
1106
- └───────── </summary>
1038
+ ### Example 1: *Single Page Application*
1107
1039
 
1108
1040
  The following is how something you could call a Single Page Application ([SPA](https://en.wikipedia.org/wiki/Single-page_application)) could be made - with zero tooling:
1109
1041
 
1110
- **-->** *First, two components that are themselves analogous to a Single File Component ([SFC](https://vuejs.org/guide/scaling-up/sfc.html))*:
1042
+ + *First, two components that are themselves analogous to a Single File Component ([SFC](https://vuejs.org/guide/scaling-up/sfc.html))*:
1111
1043
 
1112
- ```html
1113
- <template def="pages">
1044
+ <details><summary>Code</summary>
1114
1045
 
1115
- <template def="layout">
1116
- <header def="header"></header>
1117
- <footer def="footer"></footer>
1118
- </template>
1046
+ ```html
1047
+ <template def="pages">
1048
+
1049
+ <template def="layout">
1050
+ <header def="header"></header>
1051
+ <footer def="footer"></footer>
1052
+ </template>
1053
+
1054
+ <!-- Home Page -->
1055
+ <template def="home" extends="layout">
1056
+ <main def="main" namespace>
1057
+ <h1 id="banner">Home Page</h1>
1058
+ <a id="cta" href="#/products">Go to Products</a>
1059
+ <template scoped></template>
1060
+ <style scoped></style>
1061
+ <script scoped></script>
1062
+ </main>
1063
+ </template>
1064
+
1065
+ <!-- Products Page -->
1066
+ <template def="products" extends="layout">
1067
+ <main def="main" namespace>
1068
+ <h1 id="banner">Products Page</h1>
1069
+ <a id="cta" href="#/home">Go to Home</a>
1070
+ <template scoped></template>
1071
+ <style scoped></style>
1072
+ <script scoped></script>
1073
+ </main>
1074
+ </template>
1119
1075
 
1120
- <!-- Home Page -->
1121
- <template def="home" extends="layout">
1122
- <main def="main" namespace>
1123
- <h1 id="banner">Home Page</h1>
1124
- <a id="cta" href="#/products">Go to Products</a>
1125
- <template scoped></template>
1126
- <style scoped></style>
1127
- <script scoped></script>
1128
- </main>
1129
- </template>
1076
+ </template>
1077
+ ```
1130
1078
 
1131
- <!-- Products Page -->
1132
- <template def="products" extends="layout">
1133
- <main def="main" namespace>
1134
- <h1 id="banner">Products Page</h1>
1135
- <a id="cta" href="#/home">Go to Home</a>
1136
- <template scoped></template>
1137
- <style scoped></style>
1138
- <script scoped></script>
1139
- </main>
1140
- </template>
1079
+ </details>
1141
1080
 
1142
- </template>
1143
- ```
1081
+ + *Then a 2-line router that alternates the view based on the URL hash*:
1144
1082
 
1145
- **-->** *Then a 2-line router that alternates the view based on the URL hash*:
1083
+ <details><summary>Code</summary>
1146
1084
 
1147
- ```html
1148
- <body importscontext="/pages/home">
1149
-
1150
- <import ref="#header"></import>
1151
- <import ref="#main"></import>
1152
- <import ref="#footer"></import>
1153
-
1154
- <script>
1155
- const route = () => { document.body.setAttribute('importscontext', '/pages' + location.hash.substring(1)); };
1156
- window.addEventListener('hashchange', route);
1157
- </script>
1158
-
1159
- </body>
1160
- ```
1085
+ ```html
1086
+ <body importscontext="/pages/home">
1087
+
1088
+ <import ref="#header"></import>
1089
+ <import ref="#main"></import>
1090
+ <import ref="#footer"></import>
1091
+
1092
+ <script>
1093
+ const route = () => { document.body.setAttribute('importscontext', '/pages' + location.hash.substring(1)); };
1094
+ window.addEventListener('hashchange', route);
1095
+ </script>
1096
+
1097
+ </body>
1098
+ ```
1161
1099
 
1162
- </details>
1100
+ </details>
1163
1101
 
1164
- <details><summary>Example 2: <i>Multi-Level Namespacing</i><br>
1165
- └───────── </summary>
1102
+ ### Example 2: *Multi-Level Namespacing*
1166
1103
 
1167
1104
  The following is a Listbox component lifted directly from the [ARIA Authoring Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/listbox/examples/listbox-grouped/#sc_label) but with IDs effectively "contained" at different levels within the component using the `namespace` attribute.
1168
1105
 
1106
+ <details><summary>Code</summary>
1107
+
1169
1108
  ```html
1170
1109
  <div namespace class="listbox-area">
1171
1110
  <div>
@@ -1231,65 +1170,75 @@ The following is a Listbox component lifted directly from the [ARIA Authoring Pr
1231
1170
 
1232
1171
  </details>
1233
1172
 
1234
- <details><summary>Example 3: <i>Dynamic Shadow DOM</i><br>
1235
- └───────── </summary>
1173
+ ### Example 3: *Dynamic Shadow DOM*
1236
1174
 
1237
1175
  The following is a custom element that derives its Shadow DOM from an imported `<tenplate>` element. The idea is to have different Shadow DOM layouts defined and let the "usage" context decide which variant is imported!
1238
1176
 
1239
- **-->** *First, two layout options defined for the Shadow DOM*:
1177
+ + *First, two layout options defined for the Shadow DOM*:
1240
1178
 
1241
- ```html
1242
- <template def="vendor1">
1179
+ <details><summary>Code</summary>
1243
1180
 
1244
- <template def="components-layout1">
1245
- <template def="magic-button">
1246
- <span id="icon"></span> <span id="text"></span>
1247
- </template>
1248
- </template>
1181
+ ```html
1182
+ <template def="vendor1">
1183
+
1184
+ <template def="components-layout1">
1185
+ <template def="magic-button">
1186
+ <span id="icon"></span> <span id="text"></span>
1187
+ </template>
1188
+ </template>
1189
+
1190
+ <template def="components-layout2">
1191
+ <template def="magic-button">
1192
+ <span id="text"></span> <span id="icon"></span>
1193
+ </template>
1194
+ </template>
1249
1195
 
1250
- <template def="components-layout2">
1251
- <template def="magic-button">
1252
- <span id="text"></span> <span id="icon"></span>
1253
1196
  </template>
1254
- </template>
1197
+ ```
1255
1198
 
1256
- </template>
1257
- ```
1199
+ </details>
1258
1200
 
1259
- **-->** *Next, the Shadow DOM creation that imports its layout from context*:
1201
+ + *Next, the Shadow DOM creation that imports its layout from context*:
1260
1202
 
1261
- ```js
1262
- customElements.define('magic-button', class extends HTMLElement {
1263
- connectedCallback() {
1264
- const shadowRoot = this.attachShadow({ mode: 'open' });
1265
- this.import('@vendor1/magic-button', template => {
1266
- shadowRoot.appendChild( template.content.cloneNode(true) );
1203
+ <details><summary>Code</summary>
1204
+
1205
+ ```js
1206
+ customElements.define('magic-button', class extends HTMLElement {
1207
+ connectedCallback() {
1208
+ const shadowRoot = this.attachShadow({ mode: 'open' });
1209
+ this.import('@vendor1/magic-button', template => {
1210
+ shadowRoot.appendChild( template.content.cloneNode(true) );
1211
+ });
1212
+ }
1267
1213
  });
1268
- }
1269
- });
1270
- ```
1214
+ ```
1271
1215
 
1272
- **-->** *Then, the part where we just drop the component in "layout" contexts*:
1216
+ </details>
1273
1217
 
1274
- ```html
1275
- <div contextname="vendor1" importscontext="/vendor1/components-layout1">
1218
+ + *Then, the part where we just drop the component in "layout" contexts*:
1276
1219
 
1277
- <magic-button></magic-button>
1220
+ <details><summary>Code</summary>
1278
1221
 
1279
- <aside contextname="vendor1" importscontext="/vendor1/components-layout2">
1280
- <magic-button></magic-button>
1281
- </aside>
1222
+ ```html
1223
+ <div contextname="vendor1" importscontext="/vendor1/components-layout1">
1282
1224
 
1283
- </div>
1284
- ```
1225
+ <magic-button></magic-button>
1285
1226
 
1286
- </details>
1227
+ <aside contextname="vendor1" importscontext="/vendor1/components-layout2">
1228
+ <magic-button></magic-button>
1229
+ </aside>
1287
1230
 
1288
- <details><summary>Example 4: <i>Declarative Lists</i><br>
1289
- └───────── </summary>
1231
+ </div>
1232
+ ```
1233
+
1234
+ </details>
1235
+
1236
+ ### Example 4: *Declarative Lists*
1290
1237
 
1291
1238
  The following is a hypothetical list page!
1292
1239
 
1240
+ <details><summary>Code</summary>
1241
+
1293
1242
  ```html
1294
1243
  <section>
1295
1244
 
@@ -1306,11 +1255,12 @@ The following is a hypothetical list page!
1306
1255
 
1307
1256
  </details>
1308
1257
 
1309
- <details><summary>Example 5: <i>Imperative Lists</i><br>
1310
- └───────── </summary>
1258
+ ### Example 4: *Imperative Lists*
1311
1259
 
1312
1260
  The following is much like the above, but imperative. Additions and removals on the data items are also statically reflected!
1313
1261
 
1262
+ <details><summary>Code</summary>
1263
+
1314
1264
  ```html
1315
1265
  <section namespace>
1316
1266
 
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "wicg-proposal"
15
15
  ],
16
16
  "homepage": "https://webqit.io/tooling/oohtml",
17
- "version": "3.0.1-12",
17
+ "version": "3.0.1-3",
18
18
  "license": "MIT",
19
19
  "repository": {
20
20
  "type": "git",