grainjs 0.1.0 → 1.0.2

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 (164) hide show
  1. package/README.md +54 -9
  2. package/dist/cjs/index.d.ts +6 -2
  3. package/dist/cjs/index.js +24 -17
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/lib/PriorityQueue.d.ts +1 -1
  6. package/dist/cjs/lib/PriorityQueue.js +1 -0
  7. package/dist/cjs/lib/PriorityQueue.js.map +1 -1
  8. package/dist/cjs/lib/_computed_queue.d.ts +18 -0
  9. package/dist/cjs/lib/_computed_queue.js +6 -1
  10. package/dist/cjs/lib/_computed_queue.js.map +1 -1
  11. package/dist/cjs/lib/binding.d.ts +16 -10
  12. package/dist/cjs/lib/binding.js +22 -27
  13. package/dist/cjs/lib/binding.js.map +1 -1
  14. package/dist/cjs/lib/browserGlobals.d.ts +4 -1
  15. package/dist/cjs/lib/browserGlobals.js +2 -0
  16. package/dist/cjs/lib/browserGlobals.js.map +1 -1
  17. package/dist/cjs/lib/computed.d.ts +11 -7
  18. package/dist/cjs/lib/computed.js +16 -0
  19. package/dist/cjs/lib/computed.js.map +1 -1
  20. package/dist/cjs/lib/dispose.d.ts +106 -14
  21. package/dist/cjs/lib/dispose.js +76 -11
  22. package/dist/cjs/lib/dispose.js.map +1 -1
  23. package/dist/cjs/lib/dom.d.ts +21 -17
  24. package/dist/cjs/lib/dom.js +33 -26
  25. package/dist/cjs/lib/dom.js.map +1 -1
  26. package/dist/cjs/lib/domComponent.d.ts +71 -0
  27. package/dist/cjs/lib/domComponent.js +15 -0
  28. package/dist/cjs/lib/domComponent.js.map +1 -0
  29. package/dist/cjs/lib/domComputed.d.ts +89 -0
  30. package/dist/cjs/lib/domComputed.js +92 -0
  31. package/dist/cjs/lib/domComputed.js.map +1 -0
  32. package/dist/cjs/lib/{_domDispose.d.ts → domDispose.d.ts} +12 -2
  33. package/dist/cjs/lib/{_domDispose.js → domDispose.js} +21 -8
  34. package/dist/cjs/lib/domDispose.js.map +1 -0
  35. package/dist/cjs/lib/{_domForEach.d.ts → domForEach.d.ts} +2 -2
  36. package/dist/cjs/lib/domForEach.js +72 -0
  37. package/dist/cjs/lib/domForEach.js.map +1 -0
  38. package/dist/cjs/lib/{_domImpl.d.ts → domImpl.d.ts} +15 -12
  39. package/dist/cjs/lib/{_domImpl.js → domImpl.js} +23 -6
  40. package/dist/cjs/lib/domImpl.js.map +1 -0
  41. package/dist/cjs/lib/{_domMethods.d.ts → domMethods.d.ts} +27 -62
  42. package/dist/cjs/lib/{_domMethods.js → domMethods.js} +21 -76
  43. package/dist/cjs/lib/domMethods.js.map +1 -0
  44. package/dist/cjs/lib/domevent.d.ts +32 -21
  45. package/dist/cjs/lib/domevent.js +33 -12
  46. package/dist/cjs/lib/domevent.js.map +1 -1
  47. package/dist/cjs/lib/emit.d.ts +25 -2
  48. package/dist/cjs/lib/emit.js +3 -1
  49. package/dist/cjs/lib/emit.js.map +1 -1
  50. package/dist/cjs/lib/kowrap.d.ts +45 -3
  51. package/dist/cjs/lib/kowrap.js +93 -10
  52. package/dist/cjs/lib/kowrap.js.map +1 -1
  53. package/dist/cjs/lib/obsArray.d.ts +8 -8
  54. package/dist/cjs/lib/obsArray.js +1 -0
  55. package/dist/cjs/lib/obsArray.js.map +1 -1
  56. package/dist/cjs/lib/observable.d.ts +6 -1
  57. package/dist/cjs/lib/observable.js +11 -2
  58. package/dist/cjs/lib/observable.js.map +1 -1
  59. package/dist/cjs/lib/pureComputed.d.ts +3 -3
  60. package/dist/cjs/lib/pureComputed.js +2 -1
  61. package/dist/cjs/lib/pureComputed.js.map +1 -1
  62. package/dist/cjs/lib/styled.d.ts +76 -11
  63. package/dist/cjs/lib/styled.js +55 -23
  64. package/dist/cjs/lib/styled.js.map +1 -1
  65. package/dist/cjs/lib/subscribe.d.ts +15 -6
  66. package/dist/cjs/lib/subscribe.js +6 -2
  67. package/dist/cjs/lib/subscribe.js.map +1 -1
  68. package/dist/cjs/lib/util.js +1 -0
  69. package/dist/cjs/lib/util.js.map +1 -1
  70. package/dist/cjs/lib/widgets/input.d.ts +2 -2
  71. package/dist/cjs/lib/widgets/input.js +2 -2
  72. package/dist/cjs/lib/widgets/input.js.map +1 -1
  73. package/dist/cjs/lib/widgets/select.d.ts +1 -1
  74. package/dist/cjs/lib/widgets/select.js +1 -0
  75. package/dist/cjs/lib/widgets/select.js.map +1 -1
  76. package/dist/esm/index.js +6 -2
  77. package/dist/esm/index.js.map +1 -1
  78. package/dist/esm/lib/PriorityQueue.js.map +1 -1
  79. package/dist/esm/lib/_computed_queue.js +5 -1
  80. package/dist/esm/lib/_computed_queue.js.map +1 -1
  81. package/dist/esm/lib/binding.js +20 -27
  82. package/dist/esm/lib/binding.js.map +1 -1
  83. package/dist/esm/lib/browserGlobals.js +1 -0
  84. package/dist/esm/lib/browserGlobals.js.map +1 -1
  85. package/dist/esm/lib/computed.js +15 -0
  86. package/dist/esm/lib/computed.js.map +1 -1
  87. package/dist/esm/lib/dispose.js +74 -11
  88. package/dist/esm/lib/dispose.js.map +1 -1
  89. package/dist/esm/lib/dom.js +21 -17
  90. package/dist/esm/lib/dom.js.map +1 -1
  91. package/dist/esm/lib/domComponent.js +11 -0
  92. package/dist/esm/lib/domComponent.js.map +1 -0
  93. package/dist/esm/lib/domComputed.js +84 -0
  94. package/dist/esm/lib/domComputed.js.map +1 -0
  95. package/dist/esm/lib/{_domDispose.js → domDispose.js} +19 -8
  96. package/dist/esm/lib/domDispose.js.map +1 -0
  97. package/dist/esm/lib/domForEach.js +68 -0
  98. package/dist/esm/lib/domForEach.js.map +1 -0
  99. package/dist/esm/lib/{_domImpl.js → domImpl.js} +20 -4
  100. package/dist/esm/lib/domImpl.js.map +1 -0
  101. package/dist/esm/lib/{_domMethods.js → domMethods.js} +8 -63
  102. package/dist/esm/lib/domMethods.js.map +1 -0
  103. package/dist/esm/lib/domevent.js +30 -11
  104. package/dist/esm/lib/domevent.js.map +1 -1
  105. package/dist/esm/lib/emit.js +2 -1
  106. package/dist/esm/lib/emit.js.map +1 -1
  107. package/dist/esm/lib/kowrap.js +90 -10
  108. package/dist/esm/lib/kowrap.js.map +1 -1
  109. package/dist/esm/lib/obsArray.js.map +1 -1
  110. package/dist/esm/lib/observable.js +9 -1
  111. package/dist/esm/lib/observable.js.map +1 -1
  112. package/dist/esm/lib/pureComputed.js +1 -1
  113. package/dist/esm/lib/pureComputed.js.map +1 -1
  114. package/dist/esm/lib/styled.js +52 -22
  115. package/dist/esm/lib/styled.js.map +1 -1
  116. package/dist/esm/lib/subscribe.js +5 -2
  117. package/dist/esm/lib/subscribe.js.map +1 -1
  118. package/dist/esm/lib/util.js.map +1 -1
  119. package/dist/esm/lib/widgets/input.js +1 -2
  120. package/dist/esm/lib/widgets/input.js.map +1 -1
  121. package/dist/esm/lib/widgets/select.js.map +1 -1
  122. package/dist/grain-full.debug.js +1627 -1222
  123. package/dist/grain-full.min.js +1 -1
  124. package/dist/grain-full.min.js.map +1 -1
  125. package/index.ts +6 -2
  126. package/lib/_computed_queue.ts +7 -1
  127. package/lib/binding.ts +33 -28
  128. package/lib/browserGlobals.ts +3 -1
  129. package/lib/computed.ts +37 -7
  130. package/lib/dispose.ts +81 -33
  131. package/lib/dom.ts +24 -18
  132. package/lib/domComponent.ts +89 -0
  133. package/lib/domComputed.ts +146 -0
  134. package/lib/{_domDispose.ts → domDispose.ts} +26 -8
  135. package/lib/{_domForEach.ts → domForEach.ts} +12 -11
  136. package/lib/{_domImpl.ts → domImpl.ts} +36 -30
  137. package/lib/{_domMethods.ts → domMethods.ts} +33 -103
  138. package/lib/domevent.ts +59 -22
  139. package/lib/emit.ts +2 -1
  140. package/lib/kowrap.ts +109 -11
  141. package/lib/obsArray.ts +2 -2
  142. package/lib/observable.ts +10 -2
  143. package/lib/pureComputed.ts +7 -6
  144. package/lib/styled.ts +65 -39
  145. package/lib/subscribe.ts +24 -8
  146. package/lib/widgets/input.ts +9 -7
  147. package/lib/widgets/select.ts +3 -3
  148. package/package.json +41 -42
  149. package/dist/cjs/lib/_domComponent.d.ts +0 -84
  150. package/dist/cjs/lib/_domComponent.js +0 -160
  151. package/dist/cjs/lib/_domComponent.js.map +0 -1
  152. package/dist/cjs/lib/_domDispose.js.map +0 -1
  153. package/dist/cjs/lib/_domForEach.js +0 -71
  154. package/dist/cjs/lib/_domForEach.js.map +0 -1
  155. package/dist/cjs/lib/_domImpl.js.map +0 -1
  156. package/dist/cjs/lib/_domMethods.js.map +0 -1
  157. package/dist/esm/lib/_domComponent.js +0 -155
  158. package/dist/esm/lib/_domComponent.js.map +0 -1
  159. package/dist/esm/lib/_domDispose.js.map +0 -1
  160. package/dist/esm/lib/_domForEach.js +0 -68
  161. package/dist/esm/lib/_domForEach.js.map +0 -1
  162. package/dist/esm/lib/_domImpl.js.map +0 -1
  163. package/dist/esm/lib/_domMethods.js.map +0 -1
  164. package/lib/_domComponent.ts +0 -167
@@ -0,0 +1,89 @@
1
+ import { BindableValue } from './binding';
2
+ import { MultiHolder } from './dispose';
3
+ import { DomArg, DomMethod } from './domImpl';
4
+ export declare type DomComputed = [Node, Node, DomMethod];
5
+ export declare type DomContents = Node | string | DomComputed | void | null | undefined | IDomContentsArray;
6
+ export interface IDomContentsArray extends Array<DomContents> {
7
+ }
8
+ /**
9
+ * Replaces the content between nodeBefore and nodeAfter, which should be two siblings within the
10
+ * same parent node. New content may be anything allowed as an argument to dom(), including null
11
+ * to insert nothing. Runs disposers, if any, on all removed content.
12
+ */
13
+ export declare function replaceContent(nodeBefore: Node, nodeAfter: Node, content: DomContents): void;
14
+ /**
15
+ * Appends dynamic DOM content to an element. The value may be an observable or function (from
16
+ * which a computed is created), whose value will be passed to `contentFunc` which should return
17
+ * DOM content. If the contentFunc is omitted, it defaults to identity, i.e. it's OK for the
18
+ * observable or function to return DOM directly.
19
+ *
20
+ * The DOM content returned may be an element, string, array, or null. Whenever the observable
21
+ * changes, previous content is disposed and removed, and new content added in its place.
22
+ *
23
+ * The following are roughly equivalent:
24
+ * (A) domComputed(nlinesObs, nlines => nlines > 1 ? dom('textarea') : dom('input'));
25
+ * (B) domComputed(use => use(nlinesObs) > 1 ? dom('textarea') : dom('input'));
26
+ * (C) domComputed(use => use(nlinesObs) > 1, isTall => isTall ? dom('textarea') : dom('input'));
27
+ *
28
+ * Here, (C) is best. Both (A) and (B) would rebuild DOM for any change in nlinesObs, but (C)
29
+ * encapsulates meaningful changes in the observable, and only recreates DOM when necessary.
30
+ *
31
+ * Syntax (B), without the second argument, may be useful in cases of DOM depending on several
32
+ * observables, e.g.
33
+ *
34
+ * domComputed(use => use(readonlyObs) ? dom('div') :
35
+ * (use(nlinesObs) > 1 ? dom('textarea') : dom('input')));
36
+ *
37
+ * If the argument is not an observable, domComputed() may but should not be used. The following
38
+ * are equivalent:
39
+ *
40
+ * dom(..., domComputed(listValue, list => `Have ${list.length} items`), ...)
41
+ * dom(..., `Have ${listValue.length} items`, ...)
42
+ *
43
+ * In this case, the latter is preferred as the clearly simpler one.
44
+ *
45
+ * @param valueObs: Observable or function for a computed.
46
+ * @param contentFunc: Function called with the result of valueObs as the input, and
47
+ * returning DOM as output. If omitted, defaults to the identity function.
48
+ */
49
+ export declare function domComputed(valueObs: BindableValue<Exclude<DomArg, DomMethod>>): DomComputed;
50
+ export declare function domComputed<T>(valueObs: BindableValue<T>, contentFunc: (val: T) => DomContents): DomComputed;
51
+ /**
52
+ * Like domComputed(), but the callback gets an additional first argument, owner, which may be
53
+ * used to take ownership of objects created by the callback. These will be disposed before each
54
+ * new call to the callback, and when the containing DOM is disposed.
55
+ *
56
+ * domComputedOwned(valueObs, (owner, value) => Editor.create(owner, value).renderSomething());
57
+ */
58
+ export declare function domComputedOwned<T>(valueObs: BindableValue<T>, contentFunc: (owner: MultiHolder, val: T) => DomContents): DomComputed;
59
+ /**
60
+ * Conditionally appends DOM to an element. The value may be an observable or function (from which
61
+ * a computed is created), whose value -- if truthy -- will be passed to `contentFunc` which
62
+ * should return DOM content. If the value is falsy, DOM content is removed.
63
+ *
64
+ * Note that if the observable changes between different truthy values, contentFunc gets called
65
+ * for each value, and previous content gets destroyed. To consider all truthy values the same,
66
+ * use an observable that returns a proper boolean, e.g.
67
+ *
68
+ * dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
69
+ *
70
+ * As with domComputed(), dom.maybe() may but should not be used when the argument is not an
71
+ * observable or function. The following are equivalent:
72
+ *
73
+ * dom(..., dom.maybe(myValue, () => dom(...)));
74
+ * dom(..., myValue ? dom(...) : null);
75
+ *
76
+ * The latter is preferred for being simpler.
77
+ *
78
+ * @param boolValueObs: Observable or function for a computed.
79
+ * @param contentFunc: Called with the result of boolValueObs when it is truthy. Should return DOM.
80
+ */
81
+ export declare function maybe<T>(boolValueObs: BindableValue<T>, contentFunc: (val: NonNullable<T>) => DomContents): DomComputed;
82
+ /**
83
+ * Like maybe(), but the callback gets an additional first argument, owner, which may be used to
84
+ * take ownership of objects created by the callback. These will be disposed before each new call
85
+ * to the callback, and when the condition becomes false or the containing DOM gets disposed.
86
+ *
87
+ * maybeOwned(showEditor, (owner) => Editor.create(owner).renderSomething());
88
+ */
89
+ export declare function maybeOwned<T>(boolValueObs: BindableValue<T>, contentFunc: (owner: MultiHolder, val: NonNullable<T>) => DomContents): DomComputed;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maybeOwned = exports.maybe = exports.domComputedOwned = exports.domComputed = exports.replaceContent = void 0;
4
+ const binding_1 = require("./binding");
5
+ const dispose_1 = require("./dispose");
6
+ const domDispose_1 = require("./domDispose");
7
+ const domImpl_1 = require("./domImpl");
8
+ // Use the browser globals in a way that allows replacing them with mocks in tests.
9
+ const browserGlobals_1 = require("./browserGlobals");
10
+ /**
11
+ * Replaces the content between nodeBefore and nodeAfter, which should be two siblings within the
12
+ * same parent node. New content may be anything allowed as an argument to dom(), including null
13
+ * to insert nothing. Runs disposers, if any, on all removed content.
14
+ */
15
+ function replaceContent(nodeBefore, nodeAfter, content) {
16
+ const elem = nodeBefore.parentNode;
17
+ if (elem) {
18
+ let next;
19
+ for (let n = nodeBefore.nextSibling; n && n !== nodeAfter; n = next) {
20
+ next = n.nextSibling;
21
+ domDispose_1.domDispose(n);
22
+ elem.removeChild(n);
23
+ }
24
+ if (content) {
25
+ elem.insertBefore(content instanceof browserGlobals_1.G.Node ? content : domImpl_1.frag(content), nodeAfter);
26
+ }
27
+ }
28
+ }
29
+ exports.replaceContent = replaceContent;
30
+ function domComputed(valueObs, contentFunc = identity) {
31
+ const markerPre = browserGlobals_1.G.document.createComment('a');
32
+ const markerPost = browserGlobals_1.G.document.createComment('b');
33
+ // Function is added after markerPre and markerPost, so that it runs once they have already been
34
+ // attached to elem (the parent element).
35
+ return [markerPre, markerPost, (elem) => {
36
+ binding_1.subscribeElem(markerPost, valueObs, (value) => replaceContent(markerPre, markerPost, contentFunc(value)));
37
+ }];
38
+ }
39
+ exports.domComputed = domComputed;
40
+ /**
41
+ * Like domComputed(), but the callback gets an additional first argument, owner, which may be
42
+ * used to take ownership of objects created by the callback. These will be disposed before each
43
+ * new call to the callback, and when the containing DOM is disposed.
44
+ *
45
+ * domComputedOwned(valueObs, (owner, value) => Editor.create(owner, value).renderSomething());
46
+ */
47
+ function domComputedOwned(valueObs, contentFunc) {
48
+ const holder = dispose_1.Holder.create(null);
49
+ const [markerPre, markerPost, func] = domComputed(valueObs, (val) => contentFunc(dispose_1.MultiHolder.create(holder), val));
50
+ domDispose_1.autoDisposeElem(markerPost, holder);
51
+ return [markerPre, markerPost, func];
52
+ }
53
+ exports.domComputedOwned = domComputedOwned;
54
+ function identity(arg) { return arg; }
55
+ /**
56
+ * Conditionally appends DOM to an element. The value may be an observable or function (from which
57
+ * a computed is created), whose value -- if truthy -- will be passed to `contentFunc` which
58
+ * should return DOM content. If the value is falsy, DOM content is removed.
59
+ *
60
+ * Note that if the observable changes between different truthy values, contentFunc gets called
61
+ * for each value, and previous content gets destroyed. To consider all truthy values the same,
62
+ * use an observable that returns a proper boolean, e.g.
63
+ *
64
+ * dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
65
+ *
66
+ * As with domComputed(), dom.maybe() may but should not be used when the argument is not an
67
+ * observable or function. The following are equivalent:
68
+ *
69
+ * dom(..., dom.maybe(myValue, () => dom(...)));
70
+ * dom(..., myValue ? dom(...) : null);
71
+ *
72
+ * The latter is preferred for being simpler.
73
+ *
74
+ * @param boolValueObs: Observable or function for a computed.
75
+ * @param contentFunc: Called with the result of boolValueObs when it is truthy. Should return DOM.
76
+ */
77
+ function maybe(boolValueObs, contentFunc) {
78
+ return domComputed(boolValueObs, (value) => value ? contentFunc(value) : null);
79
+ }
80
+ exports.maybe = maybe;
81
+ /**
82
+ * Like maybe(), but the callback gets an additional first argument, owner, which may be used to
83
+ * take ownership of objects created by the callback. These will be disposed before each new call
84
+ * to the callback, and when the condition becomes false or the containing DOM gets disposed.
85
+ *
86
+ * maybeOwned(showEditor, (owner) => Editor.create(owner).renderSomething());
87
+ */
88
+ function maybeOwned(boolValueObs, contentFunc) {
89
+ return domComputedOwned(boolValueObs, (owner, value) => value ? contentFunc(owner, value) : null);
90
+ }
91
+ exports.maybeOwned = maybeOwned;
92
+ //# sourceMappingURL=domComputed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domComputed.js","sourceRoot":"","sources":["../../../lib/domComputed.ts"],"names":[],"mappings":";;;AAAA,uCAAuD;AACvD,uCAA8C;AAC9C,6CAAyD;AACzD,uCAAkD;AAElD,mFAAmF;AACnF,qDAAmC;AAUnC;;;;GAIG;AACH,SAAgB,cAAc,CAAC,UAAgB,EAAE,SAAe,EAAE,OAAoB;IACpF,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC;IACnC,IAAI,IAAI,EAAE;QACR,IAAI,IAAI,CAAC;QACT,KAAK,IAAI,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC,GAAG,IAAI,EAAE;YACnE,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC;YACrB,uBAAU,CAAC,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;SACrB;QACD,IAAI,OAAO,EAAE;YACX,IAAI,CAAC,YAAY,CAAC,OAAO,YAAY,kBAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAI,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;SACnF;KACF;AACH,CAAC;AAbD,wCAaC;AAyCD,SAAgB,WAAW,CACzB,QAA0B,EAAE,cAAuC,QAAe;IAElF,MAAM,SAAS,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAEjD,gGAAgG;IAChG,yCAAyC;IACzC,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;YAC5C,uBAAa,CAAC,UAAU,EAAE,QAAQ,EAChC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAZD,kCAYC;AAED;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAC9B,QAA0B,EAAE,WAAwD;IAEpF,MAAM,MAAM,GAAG,gBAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,QAAQ,EACxD,CAAC,GAAM,EAAE,EAAE,CAAC,WAAW,CAAC,qBAAW,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5D,4BAAe,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AARD,4CAQC;AAED,SAAS,QAAQ,CAAI,GAAM,IAAO,OAAO,GAAG,CAAC,CAAC,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,KAAK,CAAI,YAA8B,EACnD,WAAiD;IACnD,OAAO,WAAW,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAClF,CAAC;AAHD,sBAGC;AAED;;;;;;GAMG;AACH,SAAgB,UAAU,CAAI,YAA8B,EACxD,WAAqE;IACvE,OAAO,gBAAgB,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,KAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC;AAHD,gCAGC"}
@@ -1,5 +1,15 @@
1
1
  import { IDisposable } from './dispose';
2
2
  export declare type INodeFunc = (node: Node) => void;
3
+ export declare function _disposeNode(node: Node): void;
4
+ export interface IDomDisposeHooks {
5
+ disposeRecursive: (node: Node) => void;
6
+ disposeNode: (node: Node) => void;
7
+ }
8
+ /**
9
+ * Support for extending dom disposal. This is very low-level, and needs utmost care. Any
10
+ * disposers set should take care of calling the original versions of the disposers.
11
+ */
12
+ export declare const domDisposeHooks: IDomDisposeHooks;
3
13
  /**
4
14
  * Run disposers associated with any descendant of elem or with elem itself. Disposers get
5
15
  * associated with elements using dom.onDispose(). Descendants are processed first.
@@ -7,9 +17,9 @@ export declare type INodeFunc = (node: Node) => void;
7
17
  * It is automatically called if one of the function arguments to dom() throws an exception during
8
18
  * element creation. This way any onDispose() handlers set on the unfinished element get called.
9
19
  *
10
- * @param {Element} elem: The element to run disposers on.
20
+ * @param {Node} node: The element to run disposers on.
11
21
  */
12
- export declare function domDispose(elem: Node): void;
22
+ export declare function domDispose(node: Node): void;
13
23
  /**
14
24
  * Associate a disposerFunc with a DOM element. It will be called when the element is disposed
15
25
  * using domDispose() on it or any of its parents. If onDispose is called multiple times, all
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.autoDispose = exports.autoDisposeElem = exports.onDispose = exports.onDisposeElem = exports.domDispose = exports.domDisposeHooks = exports._disposeNode = void 0;
3
4
  /**
4
5
  * Private global disposal map. It maintains the association between DOM nodes and cleanup
5
6
  * functions added with dom.onDispose(). To support multiple disposers on one element, we use a
@@ -25,19 +26,31 @@ function _walkDom(elem, visitFunc) {
25
26
  visitFunc(elem);
26
27
  }
27
28
  // Internal helper to run all disposers for a single element.
28
- function _disposeElem(elem) {
29
- let disposer = _disposeMap.get(elem);
29
+ function _disposeNode(node) {
30
+ let disposer = _disposeMap.get(node);
30
31
  if (disposer) {
31
- let key = elem;
32
+ let key = node;
32
33
  do {
33
34
  _disposeMap.delete(key);
34
- disposer(elem);
35
+ disposer(node);
35
36
  // Find the next disposer; these are chained when there are multiple.
36
37
  key = disposer;
37
38
  disposer = _disposeMap.get(key);
38
39
  } while (disposer);
39
40
  }
40
41
  }
42
+ exports._disposeNode = _disposeNode;
43
+ function _disposeNodeRecursive(node) {
44
+ _walkDom(node, exports.domDisposeHooks.disposeNode);
45
+ }
46
+ /**
47
+ * Support for extending dom disposal. This is very low-level, and needs utmost care. Any
48
+ * disposers set should take care of calling the original versions of the disposers.
49
+ */
50
+ exports.domDisposeHooks = {
51
+ disposeNode: _disposeNode,
52
+ disposeRecursive: _disposeNodeRecursive,
53
+ };
41
54
  /**
42
55
  * Run disposers associated with any descendant of elem or with elem itself. Disposers get
43
56
  * associated with elements using dom.onDispose(). Descendants are processed first.
@@ -45,10 +58,10 @@ function _disposeElem(elem) {
45
58
  * It is automatically called if one of the function arguments to dom() throws an exception during
46
59
  * element creation. This way any onDispose() handlers set on the unfinished element get called.
47
60
  *
48
- * @param {Element} elem: The element to run disposers on.
61
+ * @param {Node} node: The element to run disposers on.
49
62
  */
50
- function domDispose(elem) {
51
- _walkDom(elem, _disposeElem);
63
+ function domDispose(node) {
64
+ exports.domDisposeHooks.disposeRecursive(node);
52
65
  }
53
66
  exports.domDispose = domDispose;
54
67
  /**
@@ -91,4 +104,4 @@ function autoDispose(disposable) {
91
104
  }
92
105
  }
93
106
  exports.autoDispose = autoDispose;
94
- //# sourceMappingURL=_domDispose.js.map
107
+ //# sourceMappingURL=domDispose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domDispose.js","sourceRoot":"","sources":["../../../lib/domDispose.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,GAAuC,IAAI,OAAO,EAAE,CAAC;AAItE,4FAA4F;AAC5F,mCAAmC;AACnC,SAAS,QAAQ,CAAC,IAAU,EAAE,SAAoB;IAChD,IAAI,CAAC,GAAc,IAAI,CAAC,UAAU,CAAC;IACnC,OAAO,CAAC,EAAE;QACR,4FAA4F;QAC5F,gCAAgC;QAChC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACvB,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;KACnB;IACD,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED,6DAA6D;AAC7D,SAAgB,YAAY,CAAC,IAAU;IACrC,IAAI,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,QAAQ,EAAE;QACZ,IAAI,GAAG,GAAmB,IAAI,CAAC;QAC/B,GAAG;YACD,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,qEAAqE;YACrE,GAAG,GAAG,QAAQ,CAAC;YACf,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;SACjC,QAAQ,QAAQ,EAAE;KACpB;AACH,CAAC;AAZD,oCAYC;AAED,SAAS,qBAAqB,CAAC,IAAU;IACvC,QAAQ,CAAC,IAAI,EAAE,uBAAe,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC;AAOD;;;GAGG;AACU,QAAA,eAAe,GAAqB;IAC/C,WAAW,EAAE,YAAY;IACzB,gBAAgB,EAAE,qBAAqB;CACxC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,UAAU,CAAC,IAAU;IACnC,uBAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAFD,gCAEC;AAED;;;;;;;;;GASG;AACH,SAAgB,aAAa,CAAC,IAAU,EAAE,YAAuB;IAC/D,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACpC,IAAI,YAAY,EAAE;QAChB,WAAW,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;KAC7C;AACH,CAAC;AAND,sCAMC;AACD,SAAgB,SAAS,CAAC,YAAuB;IAC/C,OAAO,CAAC,IAAU,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC;AAFD,8BAEC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,IAAU,EAAE,UAA4B;IACtE,IAAI,UAAU,EAAE;QACd,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;KACjD;AACH,CAAC;AAJD,0CAIC;AACD,SAAgB,WAAW,CAAC,UAA4B;IACtD,IAAI,UAAU,EAAE;QACd,OAAO,CAAC,IAAU,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;KAC1D;AACH,CAAC;AAJD,kCAIC"}
@@ -1,4 +1,4 @@
1
- import { DomMethod } from './_domImpl';
1
+ import { DomContents } from './domComputed';
2
2
  import { MaybeObsArray } from './obsArray';
3
3
  /**
4
4
  * Creates DOM elements for each element of an observable array. As the array is changed, children
@@ -18,4 +18,4 @@ import { MaybeObsArray } from './obsArray';
18
18
  * If you'd like to map the DOM node back to its source item, use dom.data() and dom.getData() in
19
19
  * itemCreateFunc().
20
20
  */
21
- export declare function forEach<T>(obsArray: MaybeObsArray<T>, itemCreateFunc: (item: T) => Node | null): DomMethod;
21
+ export declare function forEach<T>(obsArray: MaybeObsArray<T>, itemCreateFunc: (item: T) => Node | null): DomContents;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.forEach = void 0;
4
+ const domComputed_1 = require("./domComputed");
5
+ const domDispose_1 = require("./domDispose");
6
+ const domImpl_1 = require("./domImpl");
7
+ const obsArray_1 = require("./obsArray");
8
+ // Use the browser globals in a way that allows replacing them with mocks in tests.
9
+ const browserGlobals_1 = require("./browserGlobals");
10
+ /**
11
+ * Creates DOM elements for each element of an observable array. As the array is changed, children
12
+ * are added or removed. This works for any array-valued observable, and for obsArray() and
13
+ * computedArray() it works more efficiently for simple changes.
14
+ *
15
+ * The given itemCreateFunc() should return a single DOM node for each item, or null to skip that
16
+ * item. It is called for new items whenever they are spliced in, or the array replaced. The
17
+ * forEach() owns the created nodes, and runs domDispose() on them when they are spliced out.
18
+ *
19
+ * If the created nodes are removed from their parent externally, forEach() will cope with it, but
20
+ * will consider these elements as no longer owned, and will not run domDispose() on them.
21
+ *
22
+ * Note that itemCreateFunc() does not receive an index: an index would only be correct at the
23
+ * time the item is created, and would not reflect further changes to the array.
24
+ *
25
+ * If you'd like to map the DOM node back to its source item, use dom.data() and dom.getData() in
26
+ * itemCreateFunc().
27
+ */
28
+ function forEach(obsArray, itemCreateFunc) {
29
+ const markerPre = browserGlobals_1.G.document.createComment('a');
30
+ const markerPost = browserGlobals_1.G.document.createComment('b');
31
+ return [markerPre, markerPost, (elem) => {
32
+ if (Array.isArray(obsArray)) {
33
+ domComputed_1.replaceContent(markerPre, markerPost, obsArray.map(itemCreateFunc));
34
+ return;
35
+ }
36
+ const nodes = obsArray_1.computedArray(obsArray, itemCreateFunc);
37
+ // Be sure to dispose the newly-created array when the DOM it's associated with is gone.
38
+ domDispose_1.autoDisposeElem(markerPost, nodes);
39
+ nodes.addListener((newArr, oldArr, splice) => {
40
+ if (splice) {
41
+ // Remove the elements that are gone.
42
+ for (const node of splice.deleted) {
43
+ if (node && node.parentNode === elem) {
44
+ domDispose_1.domDispose(node);
45
+ elem.removeChild(node);
46
+ }
47
+ }
48
+ if (splice.numAdded > 0) {
49
+ // Find a valid child immediately following the spliced out portion, for DOM insertion.
50
+ const endIndex = splice.start + splice.numAdded;
51
+ let nextElem = markerPost;
52
+ for (let i = endIndex; i < newArr.length; i++) {
53
+ const node = newArr[i];
54
+ if (node && node.parentNode === elem) {
55
+ nextElem = node;
56
+ break;
57
+ }
58
+ }
59
+ // Insert the new elements.
60
+ const content = domImpl_1.frag(newArr.slice(splice.start, endIndex));
61
+ elem.insertBefore(content, nextElem);
62
+ }
63
+ }
64
+ else {
65
+ domComputed_1.replaceContent(markerPre, markerPost, newArr);
66
+ }
67
+ });
68
+ domComputed_1.replaceContent(markerPre, markerPost, nodes.get());
69
+ }];
70
+ }
71
+ exports.forEach = forEach;
72
+ //# sourceMappingURL=domForEach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domForEach.js","sourceRoot":"","sources":["../../../lib/domForEach.ts"],"names":[],"mappings":";;;AAAA,+CAA0D;AAC1D,6CAAyD;AACzD,uCAA+B;AAC/B,yCAAkE;AAElE,mFAAmF;AACnF,qDAAmC;AAEnC;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,OAAO,CAAI,QAA0B,EAAE,cAAsC;IAC3F,MAAM,SAAS,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,kBAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACjD,OAAO,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;YAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAC3B,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;gBACpE,OAAO;aACR;YAED,MAAM,KAAK,GAAwB,wBAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAE3E,wFAAwF;YACxF,4BAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAEnC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAwB,EAAE,MAAwB,EAAE,MAAO,EAAE,EAAE;gBAChF,IAAI,MAAM,EAAE;oBACV,qCAAqC;oBACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE;wBACjC,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;4BACpC,uBAAU,CAAC,IAAI,CAAC,CAAC;4BACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;yBACxB;qBACF;oBAED,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,EAAE;wBACvB,uFAAuF;wBACvF,MAAM,QAAQ,GAAW,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC;wBACxD,IAAI,QAAQ,GAAS,UAAU,CAAC;wBAChC,KAAK,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;4BAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;4BACvB,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE;gCACpC,QAAQ,GAAG,IAAI,CAAC;gCAChB,MAAM;6BACP;yBACF;wBAED,2BAA2B;wBAC3B,MAAM,OAAO,GAAG,cAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;wBAC3D,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;qBACtC;iBACF;qBAAM;oBACL,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;iBAC/C;YACH,CAAC,CAAC,CAAC;YACH,4BAAc,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;AACL,CAAC;AA9CD,0BA8CC"}
@@ -1,19 +1,21 @@
1
- export declare type DomMethod = (elem: Node) => DomArg | void;
2
- export declare type DomElementMethod = (elem: Element) => DomElementArg | void;
1
+ export declare type DomMethod<T = Node> = (elem: T) => DomArg<T> | void;
2
+ export declare type DomElementMethod = DomMethod<HTMLElement>;
3
3
  export interface IAttrObj {
4
4
  [attrName: string]: string | boolean | null | undefined;
5
5
  }
6
- export declare type DomArg = Node | string | IDomArgArray | DomMethod | void | null | undefined;
7
- export interface IDomArgArray extends Array<DomArg> {
8
- }
9
- export declare type DomElementArg = DomArg | IAttrObj | IDomElementArgArray | DomElementMethod;
10
- export interface IDomElementArgArray extends Array<DomElementArg> {
6
+ export declare type DomArg<T = Node> = Node | string | void | null | undefined | IDomArgs<T> | DomMethod<T> | (T extends Element ? IAttrObj : never);
7
+ export interface IDomArgs<T = Node> extends Array<DomArg<T>> {
11
8
  }
9
+ export declare type DomElementArg = DomArg<HTMLElement>;
12
10
  /**
13
11
  * dom('tag#id.class1.class2', ...args)
14
12
  * The first argument is a string consisting of a tag name, with optional #foo suffix
15
13
  * to add the ID 'foo', and zero or more .bar suffixes to add a CSS class 'bar'.
16
14
  *
15
+ * NOTE that better typings are available when a tag is used directly, e.g.
16
+ * dom('input', {id: 'foo'}, (elem) => ...) --> elem has type HTMLInputElement
17
+ * dom('input#foo', (elem) => ...) --> elem has type HTMLElement
18
+ *
17
19
  * The rest of the arguments are optional and may be:
18
20
  *
19
21
  * Nodes - which become children of the created element;
@@ -25,21 +27,22 @@ export interface IDomElementArgArray extends Array<DomElementArg> {
25
27
  * "dom methods" - expressions such as `dom.attr('href', url)` or `dom.hide(obs)`, which
26
28
  * are actually special cases of the "functions" category.
27
29
  */
28
- export declare function dom(tagString: string, ...args: DomElementArg[]): HTMLElement;
30
+ export declare function dom<Tag extends TagName>(tagString: Tag, ...args: IDomArgs<TagElem<Tag>>): TagElem<Tag>;
31
+ export declare type TagName = keyof HTMLElementTagNameMap | string;
32
+ export declare type TagElem<T extends TagName> = T extends keyof HTMLElementTagNameMap ? HTMLElementTagNameMap[T] : HTMLElement;
29
33
  /**
30
34
  * svg('tag#id.class1.class2', ...args)
31
35
  * Same as dom(...), but creates an SVG element.
32
36
  */
33
- export declare function svg(tagString: string, ...args: DomElementArg[]): SVGElement;
37
+ export declare function svg(tagString: string, ...args: IDomArgs<SVGElement>): SVGElement;
34
38
  /**
35
39
  * Update an element with any number of arguments, as documented in dom().
36
40
  */
37
- export declare function update<E extends Element>(elem: E, ...args: DomElementArg[]): E;
38
- export declare function update<E extends Node>(elem: E, ...args: DomArg[]): E;
41
+ export declare function update<T extends Node, Args extends IDomArgs<T>>(elem: T, ...args: Args): T;
39
42
  /**
40
43
  * Creates a DocumentFragment processing arguments the same way as the dom() function.
41
44
  */
42
- export declare function frag(...args: DomArg[]): DocumentFragment;
45
+ export declare function frag(...args: IDomArgs<DocumentFragment>): DocumentFragment;
43
46
  /**
44
47
  * Find the first element matching a selector; just an abbreviation for document.querySelector().
45
48
  */
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const _domDispose_1 = require("./_domDispose");
4
- const _domMethods_1 = require("./_domMethods");
3
+ exports.findAll = exports.find = exports.frag = exports.update = exports.svg = exports.dom = void 0;
4
+ const domDispose_1 = require("./domDispose");
5
+ const domMethods_1 = require("./domMethods");
5
6
  // Use the browser globals in a way that allows replacing them with mocks in tests.
6
7
  const browserGlobals_1 = require("./browserGlobals");
7
8
  // The goal of the above declarations is to get help from TypeScript in detecting incorrect usage:
8
- // import {text, hide} from './_domMethods';
9
+ // (See test/types/dom.ts for a test of this.)
10
+ // import {text, hide} from './domMethods';
9
11
  // dom('div', text('hello')); // OK
10
12
  // dom('div', hide(true)); // OK
11
13
  // dom('div', {title: 'hello'}); // OK
@@ -17,6 +19,10 @@ const browserGlobals_1 = require("./browserGlobals");
17
19
  * The first argument is a string consisting of a tag name, with optional #foo suffix
18
20
  * to add the ID 'foo', and zero or more .bar suffixes to add a CSS class 'bar'.
19
21
  *
22
+ * NOTE that better typings are available when a tag is used directly, e.g.
23
+ * dom('input', {id: 'foo'}, (elem) => ...) --> elem has type HTMLInputElement
24
+ * dom('input#foo', (elem) => ...) --> elem has type HTMLElement
25
+ *
20
26
  * The rest of the arguments are optional and may be:
21
27
  *
22
28
  * Nodes - which become children of the created element;
@@ -90,22 +96,33 @@ function _createFromTagString(createFunc, tagString) {
90
96
  }
91
97
  return elem;
92
98
  }
99
+ /**
100
+ * Update an element with any number of arguments, as documented in dom().
101
+ */
93
102
  function update(elem, ...args) {
94
103
  return _updateWithArgs(elem, args);
95
104
  }
96
105
  exports.update = update;
106
+ /**
107
+ * Update an element with an array of arguments.
108
+ */
97
109
  function _updateWithArgs(elem, args) {
98
110
  for (const arg of args) {
99
111
  _updateWithArg(elem, arg);
100
112
  }
101
113
  return elem;
102
114
  }
115
+ /**
116
+ * Update an element with an array of arguments, calling disposers in case of an exception. It is
117
+ * an internal helper to be used whenever elem is a newly-created element. If elem is an existing
118
+ * element which the user already knows about, then _updateWithArgs should be called.
119
+ */
103
120
  function _updateWithArgsOrDispose(elem, args) {
104
121
  try {
105
122
  return _updateWithArgs(elem, args);
106
123
  }
107
124
  catch (e) {
108
- _domDispose_1.domDispose(elem);
125
+ domDispose_1.domDispose(elem);
109
126
  throw e;
110
127
  }
111
128
  }
@@ -127,7 +144,7 @@ function _updateWithArg(elem, arg) {
127
144
  elem.appendChild(arg);
128
145
  }
129
146
  else if (typeof arg === 'object') {
130
- _domMethods_1.attrsElem(elem, arg);
147
+ domMethods_1.attrsElem(elem, arg);
131
148
  }
132
149
  else {
133
150
  elem.appendChild(browserGlobals_1.G.document.createTextNode(arg));
@@ -151,4 +168,4 @@ exports.find = find;
151
168
  */
152
169
  function findAll(selector) { return browserGlobals_1.G.document.querySelectorAll(selector); }
153
170
  exports.findAll = findAll;
154
- //# sourceMappingURL=_domImpl.js.map
171
+ //# sourceMappingURL=domImpl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domImpl.js","sourceRoot":"","sources":["../../../lib/domImpl.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { DomArg, DomElementMethod, DomMethod, IAttrObj } from './_domImpl';
2
1
  import { BindableValue } from './binding';
2
+ import { DomElementMethod, DomMethod, IAttrObj } from './domImpl';
3
3
  /**
4
4
  * Sets multiple attributes of a DOM element. The `attrs()` variant takes no `elem` argument.
5
5
  * Null and undefined values are omitted, and booleans are either omitted or set to empty string.
@@ -60,7 +60,7 @@ export declare function prop<T>(property: string, valueObs: BindableValue<T>): D
60
60
  * @param {Element} elem: The element to update.
61
61
  * @param {Boolean} boolValue: True to show the element, false to hide it.
62
62
  */
63
- export declare function showElem(elem: Element, boolValue: boolean): void;
63
+ export declare function showElem(elem: HTMLElement, boolValue: boolean): void;
64
64
  export declare function show(boolValueObs: BindableValue<boolean>): DomElementMethod;
65
65
  /**
66
66
  * The opposite of show, hiding the element when boolValue is true.
@@ -68,7 +68,7 @@ export declare function show(boolValueObs: BindableValue<boolean>): DomElementMe
68
68
  * @param {Element} elem: The element to update.
69
69
  * @param {Boolean} boolValue: True to hide the element, false to show it.
70
70
  */
71
- export declare function hideElem(elem: Element, boolValue: boolean): void;
71
+ export declare function hideElem(elem: HTMLElement, boolValue: boolean): void;
72
72
  export declare function hide(boolValueObs: BindableValue<boolean>): DomElementMethod;
73
73
  /**
74
74
  * Sets or toggles the given css class className.
@@ -103,73 +103,38 @@ export declare function dataElem(elem: Node, key: string, value: any): void;
103
103
  export declare function data(key: string, valueObs: BindableValue<any>): DomMethod;
104
104
  export declare function getData(elem: Node, key: string): any;
105
105
  /**
106
- * Replaces the content between nodeBefore and nodeAfter, which should be two siblings within the
107
- * same parent node. New content may be anything allowed as an argument to dom(), including null
108
- * to insert nothing. Runs disposers, if any, on all removed content.
109
- */
110
- export declare function replaceContent(nodeBefore: Node, nodeAfter: Node, content: DomArg): void;
111
- /**
112
- * Appends dynamic DOM content to an element. The value may be an observable or function (from
113
- * which a computed is created), whose value will be passed to `contentFunc` which should return
114
- * DOM content. If the contentFunc is omitted, it defaults to identity, i.e. it's OK for the
115
- * observable or function to return DOM directly.
116
- *
117
- * The DOM content returned may be an element, string, array, or null. Whenever the observable
118
- * changes, previous content is disposed and removed, and new content added in its place.
106
+ * A very simple setup to identify DOM elements for testing purposes. Here's the recommended
107
+ * usage.
119
108
  *
120
- * These are roughly equivalent:
121
- * (A) domComputed(nlinesObs, nlines => nlines > 1 ? dom('textarea') : dom('input'));
122
- * (B) domComputed(use => use(nlinesObs) > 1, isTall => isTall ? dom('textarea') : dom('input'));
123
- * (C) domComputed(use => use(nlinesObs) > 1 ? dom('textarea') : dom('input'));
109
+ * // In the component to be tested.
110
+ * import {noTestId, TestId} from 'grainjs';
124
111
  *
125
- * Here, (B) is best. It encapsulates meaningful changes in the observable, and separates DOM
126
- * creation, so that DOM is only recreated when necessary. Between (A) and (C), (A) should be
127
- * preferred. Both (A) and (C) would rebuild DOM for any change in nlinesObs, but in (C), it's too
128
- * easy to use `use` more than necessary and cause inadvertent rebuilding of DOM.
112
+ * function myComponent(myArgs, testId: TestId = noTestId) {
113
+ * return dom(..., testId("some-name"),
114
+ * dom(..., testId("another-name"), ...),
115
+ * );
116
+ * }
129
117
  *
130
- * Syntax (C), without the last argument, may be useful in cases of DOM depending on several
131
- * observables, e.g.
118
+ * In the fixture code using this component:
132
119
  *
133
- * domComputed(use => use(readonlyObs) ? dom('div') :
134
- * (use(nlinesObs) > 1 ? dom('textarea') : dom('input')));
120
+ * import {makeTestId} from 'grainjs';
135
121
  *
136
- * If the argument is not an observable, domComputed() may but should not be used. The following
137
- * are equivalent:
122
+ * dom(..., myComponent(myArgs, makeTestId('test-mycomp-'), ...)
138
123
  *
139
- * dom(..., domComputed(listValue, list => list.map(x => dom('div', x))), ...)
140
- * dom(..., listValue.map(x => dom('div', x)), ...)
124
+ * In the webdriver test code:
141
125
  *
142
- * In this case, the latter is preferred as the clearly simpler one.
126
+ * driver.find('.test-my-comp-some-name')
127
+ * driver.find('.test-my-comp-another-name')
143
128
  *
144
- * @param {Element} elem: The element to which to append the DOM content.
145
- * @param {Object} valueObs: Observable or function for a computed.
146
- * @param [Function] contentFunc: Function called with the result of valueObs as the input, and
147
- * returning DOM as output. If omitted, defaults to the identity function.
129
+ * When myComponent() is created with testId argument omitted, the testId() calls are no-ops. When
130
+ * makeTestId('test-foo-') is passed in, testId() calls simply add a css class with that prefix.
148
131
  */
149
- export declare function domComputed<T extends DomArg>(valueObs: BindableValue<T>): DomMethod;
150
- export declare function domComputed<T>(valueObs: BindableValue<T>, contentFunc: (val: T) => DomArg): DomMethod;
132
+ export declare type TestId = (name: string) => DomElementMethod | null;
151
133
  /**
152
- * Conditionally appends DOM to an element. The value may be an observable or function (from which
153
- * a computed is created), whose value -- if truthy -- will be passed to `contentFunc` which
154
- * should return DOM content. If the value is falsy, DOM content is removed.
155
- *
156
- * Note that if the observable changes between different truthy values, contentFunc gets called
157
- * for each value, and previous content gets destroyed. To consider all truthy values the same,
158
- * use an observable that returns a proper boolean, e.g.
159
- *
160
- * dom.maybe(use => Boolean(use(fooObs)), () => dom(...));
161
- *
162
- * As with domComputed(), dom.maybe() may but should not be used when the argument is not an
163
- * observable or function. The following are equivalent:
164
- *
165
- * dom(..., dom.maybe(myValue, () => dom(...)));
166
- * dom(..., myValue ? dom(...) : null);
167
- *
168
- * The latter is preferred for being simpler.
169
- *
170
- * @param {Element} elem: The element to which to append the DOM content.
171
- * @param {Object} boolValueObs: Observable or function for a computed.
172
- * @param [Function] contentFunc: Function called with the result of boolValueObs when it is
173
- * truthy. Should returning DOM as output.
134
+ * See documentation for TestId above.
135
+ */
136
+ export declare function makeTestId(prefix: string): TestId;
137
+ /**
138
+ * See documentation for TestId above.
174
139
  */
175
- export declare function maybe<T>(boolValueObs: BindableValue<T>, contentFunc: (val: T) => DomArg): DomMethod;
140
+ export declare const noTestId: TestId;