@joist/element 3.9.1 → 4.0.0-next.10

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 (81) hide show
  1. package/README.md +67 -29
  2. package/package.json +5 -4
  3. package/src/lib/attr.test.ts +122 -48
  4. package/src/lib/attr.ts +61 -34
  5. package/src/lib/element.test.ts +89 -16
  6. package/src/lib/element.ts +74 -38
  7. package/src/lib/lifecycle.test.ts +31 -0
  8. package/src/lib/lifecycle.ts +9 -0
  9. package/src/lib/listen.test.ts +88 -0
  10. package/src/lib/listen.ts +27 -4
  11. package/src/lib/metadata.ts +17 -3
  12. package/src/lib/query.test.ts +53 -0
  13. package/src/lib/query.ts +37 -0
  14. package/src/lib/result.ts +2 -26
  15. package/src/lib/tags.ts +22 -64
  16. package/src/lib/template.test.ts +95 -0
  17. package/src/lib/template.ts +115 -0
  18. package/src/lib.ts +3 -3
  19. package/target/lib/attr.d.ts +4 -1
  20. package/target/lib/attr.js +49 -28
  21. package/target/lib/attr.js.map +1 -1
  22. package/target/lib/attr.test.js +277 -147
  23. package/target/lib/attr.test.js.map +1 -1
  24. package/target/lib/element.d.ts +6 -1
  25. package/target/lib/element.js +58 -29
  26. package/target/lib/element.js.map +1 -1
  27. package/target/lib/element.test.js +186 -64
  28. package/target/lib/element.test.js.map +1 -1
  29. package/target/lib/lifecycle.d.ts +1 -0
  30. package/target/lib/lifecycle.js +8 -0
  31. package/target/lib/lifecycle.js.map +1 -0
  32. package/target/lib/lifecycle.test.js +48 -0
  33. package/target/lib/lifecycle.test.js.map +1 -0
  34. package/target/lib/listen.d.ts +2 -1
  35. package/target/lib/listen.js +21 -3
  36. package/target/lib/listen.js.map +1 -1
  37. package/target/lib/listen.test.js +159 -0
  38. package/target/lib/listen.test.js.map +1 -0
  39. package/target/lib/metadata.d.ts +14 -3
  40. package/target/lib/metadata.js +2 -2
  41. package/target/lib/metadata.js.map +1 -1
  42. package/target/lib/query.d.ts +9 -0
  43. package/target/lib/query.js +24 -0
  44. package/target/lib/query.js.map +1 -0
  45. package/target/lib/query.test.js +78 -0
  46. package/target/lib/query.test.js.map +1 -0
  47. package/target/lib/result.d.ts +2 -8
  48. package/target/lib/result.js +1 -19
  49. package/target/lib/result.js.map +1 -1
  50. package/target/lib/tags.d.ts +10 -20
  51. package/target/lib/tags.js +17 -29
  52. package/target/lib/tags.js.map +1 -1
  53. package/target/lib/template.d.ts +9 -0
  54. package/target/lib/template.js +83 -0
  55. package/target/lib/template.js.map +1 -0
  56. package/target/lib/template.test.d.ts +1 -0
  57. package/target/lib/template.test.js +70 -0
  58. package/target/lib/template.test.js.map +1 -0
  59. package/target/lib.d.ts +3 -3
  60. package/target/lib.js +3 -3
  61. package/target/lib.js.map +1 -1
  62. package/src/lib/shadow.test.ts +0 -40
  63. package/src/lib/shadow.ts +0 -16
  64. package/src/lib/tag-name.test.ts +0 -13
  65. package/src/lib/tag-name.ts +0 -10
  66. package/src/lib/tags.test.ts +0 -28
  67. package/target/lib/shadow.d.ts +0 -2
  68. package/target/lib/shadow.js +0 -10
  69. package/target/lib/shadow.js.map +0 -1
  70. package/target/lib/shadow.test.js +0 -69
  71. package/target/lib/shadow.test.js.map +0 -1
  72. package/target/lib/tag-name.d.ts +0 -1
  73. package/target/lib/tag-name.js +0 -6
  74. package/target/lib/tag-name.js.map +0 -1
  75. package/target/lib/tag-name.test.js +0 -36
  76. package/target/lib/tag-name.test.js.map +0 -1
  77. package/target/lib/tags.test.js +0 -23
  78. package/target/lib/tags.test.js.map +0 -1
  79. /package/target/lib/{shadow.test.d.ts → lifecycle.test.d.ts} +0 -0
  80. /package/target/lib/{tag-name.test.d.ts → listen.test.d.ts} +0 -0
  81. /package/target/lib/{tags.test.d.ts → query.test.d.ts} +0 -0
@@ -0,0 +1,115 @@
1
+ const TOKEN_PREFIX = '#:';
2
+
3
+ type Updater = () => void;
4
+ class Updates extends Set<Updater> {}
5
+ type TemplateValueGetter = (key: string) => string;
6
+
7
+ export interface TemplateOpts {
8
+ value?: TemplateValueGetter;
9
+ }
10
+
11
+ export interface RenderOpts {}
12
+
13
+ export function template(templateOpts?: TemplateOpts) {
14
+ // Track all nodes that can be updated and their associated property
15
+ let updates: Updates | null = null;
16
+
17
+ return function render<T extends HTMLElement>(this: T) {
18
+ if (!updates) {
19
+ updates = findUpdates(
20
+ this,
21
+ templateOpts?.value ?? ((key: string) => getTemplateValue(this, key))
22
+ );
23
+ } else {
24
+ for (let update of updates) {
25
+ update();
26
+ }
27
+ }
28
+ };
29
+ }
30
+
31
+ function findUpdates(el: HTMLElement, getter: TemplateValueGetter): Updates {
32
+ const iterator = document.createTreeWalker(el.shadowRoot ?? el, NodeFilter.SHOW_ELEMENT);
33
+ const updates = new Updates();
34
+
35
+ while (iterator.nextNode()) {
36
+ const res = trackElement(iterator.currentNode, updates, getter);
37
+
38
+ if (res !== null) {
39
+ iterator.currentNode = res;
40
+ }
41
+ }
42
+
43
+ return updates;
44
+ }
45
+
46
+ /**
47
+ * configures and tracks a given Node so that it can be updated in place later.
48
+ */
49
+ function trackElement(node: Node, updates: Updates, getter: TemplateValueGetter): Node | null {
50
+ const element = node as Element;
51
+
52
+ for (let attr of element.attributes) {
53
+ const nodeValue = attr.value.trim();
54
+ const realAttributeName = attr.name.replace(TOKEN_PREFIX, '');
55
+
56
+ let update: Updater | null = null;
57
+
58
+ if (attr.name.startsWith(`${TOKEN_PREFIX}bind`)) {
59
+ update = () => {
60
+ const value = getter(attr.value);
61
+
62
+ if (element.textContent !== value) {
63
+ element.textContent = getter(attr.value);
64
+ }
65
+ };
66
+ } else if (attr.name.startsWith(TOKEN_PREFIX)) {
67
+ const isBooleanAttr = nodeValue.startsWith('!');
68
+ const isPositive = nodeValue.startsWith('!!');
69
+ const propertyKey = nodeValue.replaceAll('!', '');
70
+
71
+ if (isBooleanAttr) {
72
+ update = () => {
73
+ let value = isPositive ? !!getter(propertyKey) : !getter(propertyKey);
74
+
75
+ if (value) {
76
+ element.setAttribute(realAttributeName, '');
77
+ } else {
78
+ element.removeAttribute(realAttributeName);
79
+ }
80
+ };
81
+ } else {
82
+ const realAttribute = document.createAttribute(realAttributeName);
83
+ element.setAttributeNode(realAttribute);
84
+
85
+ update = () => {
86
+ const value = getter(nodeValue);
87
+
88
+ if (realAttribute.value !== value) {
89
+ realAttribute.value = value;
90
+ }
91
+ };
92
+ }
93
+ }
94
+
95
+ if (update) {
96
+ updates.add(update);
97
+
98
+ update();
99
+ }
100
+ }
101
+
102
+ return null;
103
+ }
104
+
105
+ export function getTemplateValue(obj: object, key: string) {
106
+ const parsed = key.split('.');
107
+
108
+ let pointer: any = obj;
109
+
110
+ for (let part of parsed) {
111
+ pointer = pointer[part];
112
+ }
113
+
114
+ return pointer;
115
+ }
package/src/lib.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { ShadowResult as TemplateResult } from './lib/result.js';
2
1
  export { css, html, HTMLResult, CSSResult } from './lib/tags.js';
3
- export { shadow } from './lib/shadow.js';
4
2
  export { attr } from './lib/attr.js';
5
3
  export { listen } from './lib/listen.js';
6
- export { tagName } from './lib/tag-name.js';
7
4
  export { element } from './lib/element.js';
5
+ export { query } from './lib/query.js';
6
+ export { template, getTemplateValue } from './lib/template.js';
7
+ export { ready } from './lib/lifecycle.js';
@@ -1 +1,4 @@
1
- export declare function attr<This extends HTMLElement>({ get, set }: ClassAccessorDecoratorTarget<This, unknown>, ctx: ClassAccessorDecoratorContext<This>): ClassAccessorDecoratorResult<This, any>;
1
+ export interface AttrOpts {
2
+ observed?: boolean;
3
+ }
4
+ export declare function attr(opts?: AttrOpts): <This extends HTMLElement>({ get, set }: ClassAccessorDecoratorTarget<This, unknown>, ctx: ClassAccessorDecoratorContext<This>) => ClassAccessorDecoratorResult<This, any>;
@@ -1,35 +1,56 @@
1
1
  import { metadataStore } from './metadata.js';
2
- export function attr({ get, set }, ctx) {
3
- const name = String(ctx.name);
4
- const meta = metadataStore.read(ctx.metadata);
5
- meta.attrs.push(name);
6
- return {
7
- set(value) {
8
- if (value === true) {
9
- this.setAttribute(name, '');
10
- }
11
- else if (value === false) {
12
- this.removeAttribute(name);
13
- }
14
- else {
15
- this.setAttribute(name, String(value));
16
- }
17
- set.call(this, value);
18
- },
19
- get() {
20
- const ogValue = get.call(this);
21
- const attr = this.getAttribute(name);
22
- if (attr !== null) {
23
- if (attr === '') {
24
- return true;
2
+ export function attr(opts) {
3
+ return function attrDecorator({ get, set }, ctx) {
4
+ const attrName = parseAttrName(ctx.name);
5
+ const meta = metadataStore.read(ctx.metadata);
6
+ meta.attrs.push({
7
+ propName: ctx.name,
8
+ attrName,
9
+ observe: opts?.observed ?? true
10
+ });
11
+ return {
12
+ set(value) {
13
+ if (value === true) {
14
+ this.setAttribute(attrName, '');
15
+ }
16
+ else if (value === false) {
17
+ this.removeAttribute(attrName);
18
+ }
19
+ else {
20
+ this.setAttribute(attrName, String(value));
25
21
  }
26
- if (typeof ogValue === 'number') {
27
- return Number(attr);
22
+ set.call(this, value);
23
+ },
24
+ get() {
25
+ const ogValue = get.call(this);
26
+ const attr = this.getAttribute(attrName);
27
+ if (attr !== null) {
28
+ if (attr === '') {
29
+ return true;
30
+ }
31
+ if (typeof ogValue === 'number') {
32
+ return Number(attr);
33
+ }
34
+ return attr;
28
35
  }
29
- return attr;
36
+ return ogValue;
30
37
  }
31
- return ogValue;
32
- }
38
+ };
33
39
  };
34
40
  }
41
+ function parseAttrName(val) {
42
+ let value;
43
+ if (typeof val === 'symbol') {
44
+ if (val.description) {
45
+ value = val.description;
46
+ }
47
+ else {
48
+ throw new Error('Cannot handle Symbol property without description');
49
+ }
50
+ }
51
+ else {
52
+ value = val;
53
+ }
54
+ return value.toLowerCase().replaceAll(' ', '-');
55
+ }
35
56
  //# sourceMappingURL=attr.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attr.js","sourceRoot":"","sources":["../../src/lib/attr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,IAAI,CAClB,EAAE,GAAG,EAAE,GAAG,EAA+C,EACzD,GAAwC;IAExC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEtB,OAAO;QACL,GAAG,CAAC,KAAc;YAChB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACzC,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;QACD,GAAG;YACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAErC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAElB,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;oBAChB,OAAO,IAAI,CAAC;gBACd,CAAC;gBAGD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAChC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;gBACtB,CAAC;gBAGD,OAAO,IAAI,CAAC;YACd,CAAC;YAGD,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"attr.js","sourceRoot":"","sources":["../../src/lib/attr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAM9C,MAAM,UAAU,IAAI,CAAC,IAAe;IAClC,OAAO,SAAS,aAAa,CAC3B,EAAE,GAAG,EAAE,GAAG,EAA+C,EACzD,GAAwC;QAExC,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAE9C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACd,QAAQ,EAAE,GAAG,CAAC,IAAI;YAClB,QAAQ;YACR,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI;SAChC,CAAC,CAAC;QAEH,OAAO;YACL,GAAG,CAAC,KAAc;gBAChB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC;qBAAM,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;oBAC3B,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;gBACjC,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC7C,CAAC;gBAED,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACxB,CAAC;YACD,GAAG;gBACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAEzC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAElB,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;oBAGD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;wBAChC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;oBACtB,CAAC;oBAGD,OAAO,IAAI,CAAC;gBACd,CAAC;gBAGD,OAAO,OAAO,CAAC;YACjB,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,GAAoB;IACzC,IAAI,KAAa,CAAC;IAElB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YACpB,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC"}