@typed/template 0.2.0 → 0.3.0

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 (213) hide show
  1. package/dist/cjs/Directive.js +1 -1
  2. package/dist/cjs/Directive.js.map +1 -1
  3. package/dist/cjs/ElementRef.js +23 -13
  4. package/dist/cjs/ElementRef.js.map +1 -1
  5. package/dist/cjs/ElementSource.js +16 -18
  6. package/dist/cjs/ElementSource.js.map +1 -1
  7. package/dist/cjs/EventHandler.js +1 -1
  8. package/dist/cjs/EventHandler.js.map +1 -1
  9. package/dist/cjs/Html.js +31 -32
  10. package/dist/cjs/Html.js.map +1 -1
  11. package/dist/cjs/HtmlChunk.js +4 -1
  12. package/dist/cjs/HtmlChunk.js.map +1 -1
  13. package/dist/cjs/Hydrate.js +1 -1
  14. package/dist/cjs/Hydrate.js.map +1 -1
  15. package/dist/cjs/Many.js +14 -13
  16. package/dist/cjs/Many.js.map +1 -1
  17. package/dist/cjs/Parser.js +11 -323
  18. package/dist/cjs/Parser.js.map +1 -1
  19. package/dist/cjs/Placeholder.js +3 -3
  20. package/dist/cjs/Placeholder.js.map +1 -1
  21. package/dist/cjs/Platform.js +4 -4
  22. package/dist/cjs/Platform.js.map +1 -1
  23. package/dist/cjs/Render.js +1 -1
  24. package/dist/cjs/Render.js.map +1 -1
  25. package/dist/cjs/RenderContext.js +48 -27
  26. package/dist/cjs/RenderContext.js.map +1 -1
  27. package/dist/cjs/RenderTemplate.js +2 -17
  28. package/dist/cjs/RenderTemplate.js.map +1 -1
  29. package/dist/cjs/Template.js +27 -1
  30. package/dist/cjs/Template.js.map +1 -1
  31. package/dist/cjs/TemplateInstance.js +2 -2
  32. package/dist/cjs/TemplateInstance.js.map +1 -1
  33. package/dist/cjs/Test.js +20 -7
  34. package/dist/cjs/Test.js.map +1 -1
  35. package/dist/cjs/index.js +0 -12
  36. package/dist/cjs/index.js.map +1 -1
  37. package/dist/cjs/internal/EventSource.js +95 -0
  38. package/dist/cjs/internal/EventSource.js.map +1 -0
  39. package/dist/cjs/internal/browser.js +11 -11
  40. package/dist/cjs/internal/browser.js.map +1 -1
  41. package/dist/cjs/internal/hydrate.js +49 -50
  42. package/dist/cjs/internal/hydrate.js.map +1 -1
  43. package/dist/cjs/internal/indexRefCounter.js +49 -2
  44. package/dist/cjs/internal/indexRefCounter.js.map +1 -1
  45. package/dist/cjs/internal/parser.js +60 -17
  46. package/dist/cjs/internal/parser.js.map +1 -1
  47. package/dist/cjs/internal/parts.js +128 -28
  48. package/dist/cjs/internal/parts.js.map +1 -1
  49. package/dist/cjs/internal/render.js +486 -53
  50. package/dist/cjs/internal/render.js.map +1 -1
  51. package/dist/cjs/internal/server.js +5 -2
  52. package/dist/cjs/internal/server.js.map +1 -1
  53. package/dist/dts/Directive.d.ts.map +1 -1
  54. package/dist/dts/ElementRef.d.ts +4 -2
  55. package/dist/dts/ElementRef.d.ts.map +1 -1
  56. package/dist/dts/ElementSource.d.ts +10 -5
  57. package/dist/dts/ElementSource.d.ts.map +1 -1
  58. package/dist/dts/EventHandler.d.ts.map +1 -1
  59. package/dist/dts/Html.d.ts +1 -1
  60. package/dist/dts/Html.d.ts.map +1 -1
  61. package/dist/dts/HtmlChunk.d.ts.map +1 -1
  62. package/dist/dts/Many.d.ts +13 -11
  63. package/dist/dts/Many.d.ts.map +1 -1
  64. package/dist/dts/Parser.d.ts +3 -6
  65. package/dist/dts/Parser.d.ts.map +1 -1
  66. package/dist/dts/Part.d.ts +13 -3
  67. package/dist/dts/Part.d.ts.map +1 -1
  68. package/dist/dts/Placeholder.d.ts +2 -2
  69. package/dist/dts/Placeholder.d.ts.map +1 -1
  70. package/dist/dts/Render.d.ts +2 -1
  71. package/dist/dts/Render.d.ts.map +1 -1
  72. package/dist/dts/RenderContext.d.ts +5 -4
  73. package/dist/dts/RenderContext.d.ts.map +1 -1
  74. package/dist/dts/RenderTemplate.d.ts +2 -16
  75. package/dist/dts/RenderTemplate.d.ts.map +1 -1
  76. package/dist/dts/Renderable.d.ts +2 -2
  77. package/dist/dts/Renderable.d.ts.map +1 -1
  78. package/dist/dts/Template.d.ts +21 -3
  79. package/dist/dts/Template.d.ts.map +1 -1
  80. package/dist/dts/TemplateInstance.d.ts +3 -2
  81. package/dist/dts/TemplateInstance.d.ts.map +1 -1
  82. package/dist/dts/Test.d.ts +4 -6
  83. package/dist/dts/Test.d.ts.map +1 -1
  84. package/dist/dts/index.d.ts +0 -4
  85. package/dist/dts/index.d.ts.map +1 -1
  86. package/dist/dts/internal/EventSource.d.ts +12 -0
  87. package/dist/dts/internal/EventSource.d.ts.map +1 -0
  88. package/dist/dts/internal/browser.d.ts.map +1 -1
  89. package/dist/dts/internal/hydrate.d.ts +5 -5
  90. package/dist/dts/internal/hydrate.d.ts.map +1 -1
  91. package/dist/dts/internal/indexRefCounter.d.ts +5 -0
  92. package/dist/dts/internal/indexRefCounter.d.ts.map +1 -1
  93. package/dist/dts/internal/module-augmentation.d.ts +0 -4
  94. package/dist/dts/internal/module-augmentation.d.ts.map +1 -1
  95. package/dist/dts/internal/parser.d.ts +8 -0
  96. package/dist/dts/internal/parser.d.ts.map +1 -1
  97. package/dist/dts/internal/parts.d.ts +66 -56
  98. package/dist/dts/internal/parts.d.ts.map +1 -1
  99. package/dist/dts/internal/render.d.ts +7 -7
  100. package/dist/dts/internal/render.d.ts.map +1 -1
  101. package/dist/dts/internal/server.d.ts.map +1 -1
  102. package/dist/esm/Directive.js +1 -1
  103. package/dist/esm/Directive.js.map +1 -1
  104. package/dist/esm/ElementRef.js +12 -7
  105. package/dist/esm/ElementRef.js.map +1 -1
  106. package/dist/esm/ElementSource.js +16 -13
  107. package/dist/esm/ElementSource.js.map +1 -1
  108. package/dist/esm/EventHandler.js +1 -1
  109. package/dist/esm/EventHandler.js.map +1 -1
  110. package/dist/esm/Html.js +29 -24
  111. package/dist/esm/Html.js.map +1 -1
  112. package/dist/esm/HtmlChunk.js +6 -1
  113. package/dist/esm/HtmlChunk.js.map +1 -1
  114. package/dist/esm/Hydrate.js +1 -1
  115. package/dist/esm/Hydrate.js.map +1 -1
  116. package/dist/esm/Many.js +14 -10
  117. package/dist/esm/Many.js.map +1 -1
  118. package/dist/esm/Parser.js +6 -335
  119. package/dist/esm/Parser.js.map +1 -1
  120. package/dist/esm/Placeholder.js +2 -2
  121. package/dist/esm/Placeholder.js.map +1 -1
  122. package/dist/esm/Platform.js +2 -2
  123. package/dist/esm/Platform.js.map +1 -1
  124. package/dist/esm/Render.js +1 -1
  125. package/dist/esm/Render.js.map +1 -1
  126. package/dist/esm/RenderContext.js +38 -17
  127. package/dist/esm/RenderContext.js.map +1 -1
  128. package/dist/esm/RenderTemplate.js +2 -12
  129. package/dist/esm/RenderTemplate.js.map +1 -1
  130. package/dist/esm/Template.js +24 -0
  131. package/dist/esm/Template.js.map +1 -1
  132. package/dist/esm/TemplateInstance.js +2 -2
  133. package/dist/esm/TemplateInstance.js.map +1 -1
  134. package/dist/esm/Test.js +20 -7
  135. package/dist/esm/Test.js.map +1 -1
  136. package/dist/esm/index.js +0 -4
  137. package/dist/esm/index.js.map +1 -1
  138. package/dist/esm/internal/EventSource.js +91 -0
  139. package/dist/esm/internal/EventSource.js.map +1 -0
  140. package/dist/esm/internal/browser.js +12 -12
  141. package/dist/esm/internal/browser.js.map +1 -1
  142. package/dist/esm/internal/hydrate.js +45 -46
  143. package/dist/esm/internal/hydrate.js.map +1 -1
  144. package/dist/esm/internal/indexRefCounter.js +50 -2
  145. package/dist/esm/internal/indexRefCounter.js.map +1 -1
  146. package/dist/esm/internal/parser.js +84 -17
  147. package/dist/esm/internal/parser.js.map +1 -1
  148. package/dist/esm/internal/parts.js +110 -27
  149. package/dist/esm/internal/parts.js.map +1 -1
  150. package/dist/esm/internal/render.js +476 -58
  151. package/dist/esm/internal/render.js.map +1 -1
  152. package/dist/esm/internal/server.js +5 -4
  153. package/dist/esm/internal/server.js.map +1 -1
  154. package/package.json +10 -26
  155. package/src/Directive.ts +1 -1
  156. package/src/ElementRef.ts +18 -14
  157. package/src/ElementSource.ts +62 -47
  158. package/src/EventHandler.ts +1 -1
  159. package/src/Html.ts +58 -57
  160. package/src/HtmlChunk.ts +15 -1
  161. package/src/Hydrate.ts +1 -1
  162. package/src/Many.ts +53 -43
  163. package/src/Parser.ts +10 -453
  164. package/src/Part.ts +15 -3
  165. package/src/Placeholder.ts +4 -4
  166. package/src/Platform.ts +2 -2
  167. package/src/Render.ts +7 -2
  168. package/src/RenderContext.ts +47 -19
  169. package/src/RenderTemplate.ts +9 -54
  170. package/src/Renderable.ts +2 -1
  171. package/src/Template.ts +26 -0
  172. package/src/TemplateInstance.ts +9 -9
  173. package/src/Test.ts +40 -21
  174. package/src/index.ts +0 -4
  175. package/src/internal/EventSource.ts +153 -0
  176. package/src/internal/browser.ts +26 -25
  177. package/src/internal/hydrate.ts +68 -61
  178. package/src/internal/indexRefCounter.ts +63 -2
  179. package/src/internal/module-augmentation.ts +0 -4
  180. package/src/internal/parser.ts +92 -19
  181. package/src/internal/parts.ts +158 -73
  182. package/src/internal/render.ts +701 -89
  183. package/src/internal/server.ts +5 -3
  184. package/Token/package.json +0 -6
  185. package/Tokenizer/package.json +0 -6
  186. package/dist/cjs/Token.js +0 -270
  187. package/dist/cjs/Token.js.map +0 -1
  188. package/dist/cjs/Tokenizer.js +0 -18
  189. package/dist/cjs/Tokenizer.js.map +0 -1
  190. package/dist/cjs/internal/readAttribute.js +0 -34
  191. package/dist/cjs/internal/readAttribute.js.map +0 -1
  192. package/dist/cjs/internal/tokenizer.js +0 -264
  193. package/dist/cjs/internal/tokenizer.js.map +0 -1
  194. package/dist/dts/Token.d.ts +0 -202
  195. package/dist/dts/Token.d.ts.map +0 -1
  196. package/dist/dts/Tokenizer.d.ts +0 -6
  197. package/dist/dts/Tokenizer.d.ts.map +0 -1
  198. package/dist/dts/internal/readAttribute.d.ts +0 -9
  199. package/dist/dts/internal/readAttribute.d.ts.map +0 -1
  200. package/dist/dts/internal/tokenizer.d.ts +0 -3
  201. package/dist/dts/internal/tokenizer.d.ts.map +0 -1
  202. package/dist/esm/Token.js +0 -264
  203. package/dist/esm/Token.js.map +0 -1
  204. package/dist/esm/Tokenizer.js +0 -9
  205. package/dist/esm/Tokenizer.js.map +0 -1
  206. package/dist/esm/internal/readAttribute.js +0 -24
  207. package/dist/esm/internal/readAttribute.js.map +0 -1
  208. package/dist/esm/internal/tokenizer.js +0 -296
  209. package/dist/esm/internal/tokenizer.js.map +0 -1
  210. package/src/Token.ts +0 -269
  211. package/src/Tokenizer.ts +0 -10
  212. package/src/internal/readAttribute.ts +0 -28
  213. package/src/internal/tokenizer.ts +0 -338
@@ -12,17 +12,19 @@ exports.renderSparsePart = renderSparsePart;
12
12
  exports.renderTemplate = void 0;
13
13
  exports.renderValues = renderValues;
14
14
  var Fx = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@typed/fx/Fx"));
15
- var Subject = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("@typed/fx/Subject"));
16
15
  var _TypeId = /*#__PURE__*/require("@typed/fx/TypeId");
17
16
  var _wire = /*#__PURE__*/require("@typed/wire");
18
17
  var _effect = /*#__PURE__*/require("effect");
18
+ var Context = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("effect/Context"));
19
19
  var _ReadonlyArray = /*#__PURE__*/require("effect/ReadonlyArray");
20
+ var _Scope = /*#__PURE__*/require("effect/Scope");
20
21
  var _Directive = /*#__PURE__*/require("../Directive.js");
21
22
  var ElementRef = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../ElementRef.js"));
23
+ var ElementSource = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../ElementSource.js"));
22
24
  var EventHandler = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../EventHandler.js"));
23
25
  var _RenderEvent = /*#__PURE__*/require("../RenderEvent.js");
24
- var _TemplateInstance = /*#__PURE__*/require("../TemplateInstance.js");
25
26
  var _browser = /*#__PURE__*/require("./browser.js");
27
+ var _EventSource = /*#__PURE__*/require("./EventSource.js");
26
28
  var _HydrateContext = /*#__PURE__*/require("./HydrateContext.js");
27
29
  var _indexRefCounter = /*#__PURE__*/require("./indexRefCounter.js");
28
30
  var _parser = /*#__PURE__*/require("./parser.js");
@@ -30,32 +32,390 @@ var _parts = /*#__PURE__*/require("./parts.js");
30
32
  var _utils = /*#__PURE__*/require("./utils.js");
31
33
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
32
34
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
35
+ const RenderPartMap = {
36
+ "attr": (templatePart, node, ctx) => {
37
+ const {
38
+ document,
39
+ refCounter,
40
+ renderContext,
41
+ values
42
+ } = ctx;
43
+ const element = node;
44
+ const attr = createAttribute(document, element, templatePart.name);
45
+ const renderable = values[templatePart.index];
46
+ let isSet = true;
47
+ const setValue = value => {
48
+ if (isNullOrUndefined(value)) {
49
+ element.removeAttribute(templatePart.name);
50
+ isSet = false;
51
+ } else {
52
+ attr.value = String(value);
53
+ if (isSet === false) {
54
+ element.setAttributeNode(attr);
55
+ isSet = true;
56
+ }
57
+ }
58
+ };
59
+ return matchSettablePart(renderable, setValue, () => _parts.AttributePartImpl.browser(templatePart.index, element, templatePart.name, renderContext), f => _effect.Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
60
+ },
61
+ "boolean-part": (templatePart, node, ctx) => {
62
+ const {
63
+ refCounter,
64
+ renderContext,
65
+ values
66
+ } = ctx;
67
+ const element = node;
68
+ const renderable = values[templatePart.index];
69
+ const setValue = value => {
70
+ element.toggleAttribute(templatePart.name, isNullOrUndefined(value) ? false : Boolean(value));
71
+ };
72
+ return matchSettablePart(renderable, setValue, () => _parts.BooleanPartImpl.browser(templatePart.index, element, templatePart.name, renderContext), f => _effect.Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
73
+ },
74
+ "className-part": (templatePart, node, ctx) => {
75
+ const {
76
+ refCounter,
77
+ renderContext,
78
+ values
79
+ } = ctx;
80
+ const element = node;
81
+ const renderable = values[templatePart.index];
82
+ let classNames = new Set();
83
+ const setValue = value => {
84
+ if (isNullOrUndefined(value)) {
85
+ element.classList.remove(...classNames);
86
+ classNames.clear();
87
+ } else {
88
+ const newClassNames = new Set(Array.isArray(value) ? value : [String(value)]);
89
+ const {
90
+ added,
91
+ removed
92
+ } = diffClassNames(classNames, newClassNames);
93
+ if (removed.length > 0) {
94
+ element.classList.remove(...removed);
95
+ }
96
+ if (added.length > 0) element.classList.add(...added);
97
+ classNames = newClassNames;
98
+ }
99
+ };
100
+ return matchSettablePart(renderable, setValue, () => _parts.ClassNamePartImpl.browser(templatePart.index, element, renderContext), f => _effect.Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
101
+ },
102
+ "comment-part": (templatePart, node, ctx) => {
103
+ const {
104
+ refCounter,
105
+ renderContext,
106
+ values
107
+ } = ctx;
108
+ const comment = (0, _utils.findHoleComment)(node, templatePart.index);
109
+ const renderable = values[templatePart.index];
110
+ const setValue = value => {
111
+ comment.textContent = isNullOrUndefined(value) ? "" : String(value);
112
+ };
113
+ return matchSettablePart(renderable, setValue, () => _parts.CommentPartImpl.browser(templatePart.index, comment, renderContext), f => _effect.Effect.zipRight(renderContext.queue.add(comment, f), refCounter.release(templatePart.index)), () => ctx.expected++);
114
+ },
115
+ "data": (templatePart, node, ctx) => {
116
+ const element = node;
117
+ const renderable = ctx.values[templatePart.index];
118
+ const previousKeys = new Set(Object.keys(element.dataset));
119
+ const setValue = value => {
120
+ if (isNullOrUndefined(value)) {
121
+ for (const key of previousKeys) {
122
+ delete element.dataset[key];
123
+ }
124
+ previousKeys.clear();
125
+ } else {
126
+ for (const key of previousKeys) {
127
+ if (!(key in value)) {
128
+ delete element.dataset[key];
129
+ previousKeys.delete(key);
130
+ }
131
+ }
132
+ for (const key of Object.keys(value)) {
133
+ if (!previousKeys.has(key)) {
134
+ previousKeys.add(key);
135
+ }
136
+ element.dataset[key] = value[key] || "";
137
+ }
138
+ }
139
+ };
140
+ return matchSettablePart(renderable, setValue, () => _parts.DataPartImpl.browser(templatePart.index, element, ctx.renderContext), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(templatePart.index)), () => ctx.expected++);
141
+ },
142
+ "event": (templatePart, node, ctx) => {
143
+ const element = node;
144
+ const renderable = ctx.values[templatePart.index];
145
+ const handler = getEventHandler(renderable, ctx.context, ctx.onCause);
146
+ if (handler) {
147
+ ctx.eventSource.addEventListener(element, templatePart.name, handler);
148
+ }
149
+ return null;
150
+ },
151
+ "node": (templatePart, node, ctx) => {
152
+ const part = (0, _browser.makeRenderNodePart)(templatePart.index, node, ctx.renderContext, ctx.document, false);
153
+ ctx.expected++;
154
+ return handlePart(ctx.values[templatePart.index], value => _effect.Effect.zipRight(part.update(value), ctx.refCounter.release(templatePart.index)));
155
+ },
156
+ "property": (templatePart, node, ctx) => {
157
+ const element = node;
158
+ const renderable = ctx.values[templatePart.index];
159
+ const setValue = value => {
160
+ if (isNullOrUndefined(value)) {
161
+ delete element[templatePart.name];
162
+ } else {
163
+ ;
164
+ element[templatePart.name] = value;
165
+ }
166
+ };
167
+ return matchSettablePart(renderable, setValue, () => _parts.PropertyPartImpl.browser(templatePart.index, element, templatePart.name, ctx.renderContext), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(templatePart.index)), () => ctx.expected++);
168
+ },
169
+ "properties": (templatePart, node, ctx) => {
170
+ const renderable = ctx.values[templatePart.index];
171
+ if (isNullOrUndefined(renderable)) return null;else if (Fx.isFx(renderable) || _effect.Effect.isEffect(renderable)) {
172
+ throw new Error(`Properties Part must utilize an Record of renderable values.`);
173
+ } else if (typeof renderable === "object" && !Array.isArray(renderable)) {
174
+ const element = node;
175
+ const toggleBoolean = (key, value) => {
176
+ element.toggleAttribute(key, isNullOrUndefined(value) ? false : Boolean(value));
177
+ };
178
+ const setAttribute = (key, value) => {
179
+ if (isNullOrUndefined(value)) {
180
+ element.removeAttribute(key);
181
+ } else {
182
+ element.setAttribute(key, String(value));
183
+ }
184
+ };
185
+ const setProperty = (key, value) => {
186
+ if (isNullOrUndefined(value)) {
187
+ delete element[key];
188
+ } else {
189
+ ;
190
+ element[key] = value;
191
+ }
192
+ };
193
+ const effects = [];
194
+ // We need indexes to track async values that won't conflict
195
+ // with any other Parts, we can start end of the current values.length
196
+ // As there should only ever be exactly 1 properties part.
197
+ let i = ctx.values.length;
198
+ loop: for (const [key, value] of Object.entries(renderable)) {
199
+ const index = ++i;
200
+ switch (key[0]) {
201
+ case "?":
202
+ {
203
+ const name = key.slice(1);
204
+ const eff = matchSettablePart(value, value => toggleBoolean(name, value), () => _parts.BooleanPartImpl.browser(index, element, name, ctx.renderContext), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
205
+ if (eff !== null) {
206
+ effects.push(eff);
207
+ }
208
+ continue loop;
209
+ }
210
+ case ".":
211
+ {
212
+ const name = key.slice(1);
213
+ const eff = matchSettablePart(value, value => setProperty(name, value), () => _parts.PropertyPartImpl.browser(index, element, name, ctx.renderContext), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
214
+ if (eff !== null) {
215
+ effects.push(eff);
216
+ }
217
+ continue loop;
218
+ }
219
+ case "@":
220
+ {
221
+ const name = key.slice(1);
222
+ const handler = getEventHandler(value, ctx.context, ctx.onCause);
223
+ if (handler) {
224
+ ctx.eventSource.addEventListener(element, name, handler);
225
+ }
226
+ continue loop;
227
+ }
228
+ case "o":
229
+ {
230
+ if (key[1] === "n") {
231
+ const name = key.slice(2);
232
+ const handler = getEventHandler(value, ctx.context, ctx.onCause);
233
+ if (handler) {
234
+ ctx.eventSource.addEventListener(element, name, handler);
235
+ }
236
+ }
237
+ continue loop;
238
+ }
239
+ }
240
+ const eff = matchSettablePart(value, value => setAttribute(key, value), () => _parts.AttributePartImpl.browser(index, element, key, ctx.renderContext), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
241
+ if (eff !== null) {
242
+ effects.push(eff);
243
+ }
244
+ }
245
+ return effects;
246
+ } else {
247
+ return null;
248
+ }
249
+ },
250
+ "ref": (templatePart, node, ctx) => {
251
+ const element = node;
252
+ const renderable = ctx.values[templatePart.index];
253
+ if ((0, _Directive.isDirective)(renderable)) {
254
+ return renderable(new _parts.RefPartImpl(ElementSource.fromElement(element), templatePart.index));
255
+ } else if (ElementRef.isElementRef(renderable)) {
256
+ return ElementRef.set(renderable, element);
257
+ }
258
+ return null;
259
+ },
260
+ "sparse-attr": (templatePart, node, ctx) => {
261
+ const values = Array.from({
262
+ length: templatePart.nodes.length
263
+ }, () => "");
264
+ const element = node;
265
+ const attr = createAttribute(ctx.document, element, templatePart.name);
266
+ const setValue = (value, index) => _effect.Effect.suspend(() => {
267
+ values[index] = value || "";
268
+ return ctx.renderContext.queue.add(element, () => attr.value = values.join(""));
269
+ });
270
+ const effects = [];
271
+ for (let i = 0; i < templatePart.nodes.length; ++i) {
272
+ const node = templatePart.nodes[i];
273
+ if (node._tag === "text") {
274
+ values[i] = node.value;
275
+ } else {
276
+ const renderable = ctx.values[node.index];
277
+ const index = i;
278
+ const effect = matchSettablePart(renderable, value => setValue(value, index), () => new _parts.AttributePartImpl(templatePart.name, node.index, ({
279
+ value
280
+ }) => setValue(value, index), null), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(node.index)), () => ctx.expected++);
281
+ if (effect !== null) {
282
+ effects.push(effect);
283
+ }
284
+ }
285
+ }
286
+ return effects;
287
+ },
288
+ "sparse-class-name": (templatePart, node, ctx) => {
289
+ const element = node;
290
+ const effects = templatePart.nodes.flatMap(node => {
291
+ if (node._tag === "text") {
292
+ const split = splitClassNames(node.value);
293
+ if (split.length > 0) element.classList.add(...split);
294
+ return [];
295
+ } else {
296
+ const eff = RenderPartMap[node._tag](node, element, ctx);
297
+ if (eff === null) return [];
298
+ return Array.isArray(eff) ? eff : [eff];
299
+ }
300
+ });
301
+ return effects;
302
+ },
303
+ "sparse-comment": (templatePart, node, ctx) => {
304
+ const values = Array.from({
305
+ length: templatePart.nodes.length
306
+ }, () => "");
307
+ const comment = node;
308
+ const setValue = (value, index) => _effect.Effect.suspend(() => {
309
+ values[index] = value || "";
310
+ return ctx.renderContext.queue.add(comment, () => comment.textContent = values.join(""));
311
+ });
312
+ const effects = [];
313
+ for (let i = 0; i < templatePart.nodes.length; ++i) {
314
+ const node = templatePart.nodes[i];
315
+ if (node._tag === "text") {
316
+ values[i] = node.value;
317
+ } else {
318
+ const renderable = ctx.values[node.index];
319
+ const index = i;
320
+ const effect = matchSettablePart(renderable, value => setValue(value, index), () => new _parts.CommentPartImpl(node.index, ({
321
+ value
322
+ }) => setValue(value, index), null), f => _effect.Effect.zipRight(ctx.renderContext.queue.add(comment, f), ctx.refCounter.release(node.index)), () => ctx.expected++);
323
+ if (effect !== null) {
324
+ effects.push(effect);
325
+ }
326
+ }
327
+ }
328
+ return effects;
329
+ },
330
+ "text-part": (templatePart, node, ctx) => {
331
+ const part = _parts.TextPartImpl.browser(ctx.document, templatePart.index, node, ctx.renderContext);
332
+ ctx.expected++;
333
+ return handlePart(ctx.values[templatePart.index], value => _effect.Effect.zipRight(part.update(value), ctx.refCounter.release(templatePart.index)));
334
+ }
335
+ };
336
+ const SPACE_REGEXP = /\s+/g;
337
+ function splitClassNames(value) {
338
+ return value.split(SPACE_REGEXP).flatMap(a => {
339
+ const trimmed = a.trim();
340
+ return trimmed.length > 0 ? [trimmed] : [];
341
+ });
342
+ }
343
+ function isNullOrUndefined(value) {
344
+ return value === null || value === undefined;
345
+ }
346
+ function diffClassNames(oldClassNames, newClassNames) {
347
+ const added = [];
348
+ const removed = [];
349
+ for (const className of oldClassNames) {
350
+ if (!newClassNames.has(className)) {
351
+ removed.push(className);
352
+ }
353
+ }
354
+ for (const className of newClassNames) {
355
+ if (!oldClassNames.has(className) && className.trim()) {
356
+ added.push(className);
357
+ }
358
+ }
359
+ return {
360
+ added,
361
+ removed
362
+ };
363
+ }
33
364
  /**
34
365
  * Here for "standard" browser rendering, a TemplateInstance is effectively a live
35
366
  * view into the contents rendered by the Template.
36
367
  */
37
- const renderTemplate = (document, ctx) => (templateStrings, values, providedRef) => _effect.Effect.gen(function* (_) {
38
- const elementRef = providedRef || (yield* _(ElementRef.make()));
39
- const events = Fx.map(elementRef, _RenderEvent.DomRenderEvent);
40
- const errors = Subject.make();
41
- const entry = getBrowserEntry(document, ctx, templateStrings);
42
- const content = document.importNode(entry.content, true); // Clone our template
43
- const parts = yield* _(buildParts(document, ctx, entry.template, content, elementRef, errors.onFailure, false)); // Build runtime-variant of parts with our content.
44
- // If there are parts we need to render them before constructing our Wire
45
- if (parts.length > 0) {
46
- const refCounter = yield* _((0, _indexRefCounter.indexRefCounter)(parts.length));
47
- // Do the work
48
- yield* _(renderValues(values, parts, refCounter, errors.onFailure));
49
- // Wait for initial work to be completed
50
- yield* _(refCounter.wait);
368
+ const renderTemplate = (document, renderContext) => (templateStrings, values) => {
369
+ const entry = getBrowserEntry(document, renderContext, templateStrings);
370
+ if (values.length === 0) {
371
+ return Fx.sync(() => (0, _RenderEvent.DomRenderEvent)((0, _wire.persistent)(document.importNode(entry.content, true))));
51
372
  }
52
- // Set the element when it is ready
53
- yield* _(ElementRef.set(elementRef, (0, _wire.persistent)(content)));
54
- // Return the Template instance
55
- return (0, _TemplateInstance.TemplateInstance)(Fx.merge([events, errors]), elementRef);
56
- });
373
+ return Fx.make(sink => {
374
+ return _effect.Effect.gen(function* (_) {
375
+ const content = document.importNode(entry.content, true);
376
+ const context = yield* _(_effect.Effect.context());
377
+ const refCounter = yield* _((0, _indexRefCounter.indexRefCounter2)());
378
+ const ctx = {
379
+ context,
380
+ document,
381
+ eventSource: (0, _EventSource.makeEventSource)(),
382
+ expected: 0,
383
+ refCounter,
384
+ renderContext,
385
+ onCause: sink.onFailure,
386
+ values
387
+ };
388
+ // Connect our interpolated values to our template parts
389
+ const effects = [];
390
+ for (const [part, path] of entry.template.parts) {
391
+ const eff = RenderPartMap[part._tag](part, (0, _utils.findPath)(content, path), ctx);
392
+ if (eff !== null) {
393
+ effects.push(...(Array.isArray(eff) ? eff : [eff]));
394
+ }
395
+ }
396
+ // Fork any effects necessary
397
+ if (effects.length > 0) {
398
+ yield* _(_effect.Effect.forkAll(effects));
399
+ }
400
+ // If there's anything to wait on and it's not already done, wait for an initial value
401
+ // for all asynchronous sources.
402
+ if (ctx.expected > 0 && (yield* _(refCounter.expect(ctx.expected)))) {
403
+ yield* _(refCounter.wait);
404
+ }
405
+ // Create a persistent wire from our content
406
+ const wire = (0, _wire.persistent)(content);
407
+ // Set the element when it is ready
408
+ yield* _(ctx.eventSource.setup(wire, Context.get(context, _Scope.Scope)));
409
+ // Emity our DomRenderEvent
410
+ yield* _(sink.onSuccess((0, _RenderEvent.DomRenderEvent)(wire)));
411
+ // Ensure our templates last forever in the DOM environment
412
+ // so event listeners are kept attached to the current Scope.
413
+ yield* _(_effect.Effect.never);
414
+ });
415
+ });
416
+ };
57
417
  exports.renderTemplate = renderTemplate;
58
- function renderValues(values, parts, refCounter, onCause, makeHydrateContext) {
418
+ function renderValues(values, parts, refCounter, ctx, makeHydrateContext) {
59
419
  return _effect.Effect.all(parts.map((part, index) => {
60
420
  switch (part._tag) {
61
421
  case "sparse/attribute":
@@ -65,7 +425,7 @@ function renderValues(values, parts, refCounter, onCause, makeHydrateContext) {
65
425
  return renderSparsePart(values, part, refCounter);
66
426
  }
67
427
  default:
68
- return renderPart(values, part, refCounter, onCause, makeHydrateContext ? () => makeHydrateContext(index) : undefined);
428
+ return renderPart(values, part, refCounter, ctx, makeHydrateContext ? () => makeHydrateContext(index) : undefined);
69
429
  }
70
430
  }));
71
431
  }
@@ -73,30 +433,40 @@ function renderSparsePart(values, part, refCounter) {
73
433
  const indexes = part.parts.flatMap(p => p._tag === "static/text" ? [] : [p.index]);
74
434
  return _effect.Effect.forkScoped(Fx.observe(unwrapSparsePartRenderables(part.parts.map(p => p._tag === "static/text" ? Fx.succeed(p.value) : values[p.index]), part), value => _effect.Effect.tap(part.update(value), () => _effect.Effect.forEach(indexes, a => refCounter.release(a)))));
75
435
  }
76
- function renderPart(values, part, refCounter, onCause, hydrateCtx) {
436
+ function renderPart(values, part, refCounter, ctx, hydrateCtx) {
77
437
  const partIndex = part.index;
78
438
  const renderable = values[partIndex];
439
+ if (renderable === null || renderable === undefined) return refCounter.release(partIndex);
79
440
  if ((0, _Directive.isDirective)(renderable)) {
80
- return renderable(part).pipe(_effect.Effect.tap(() => refCounter.release(partIndex)), _effect.Effect.forkScoped);
441
+ return renderable(part).pipe(_effect.Effect.flatMap(() => refCounter.release(partIndex)), _effect.Effect.forkScoped);
81
442
  } else if (part._tag === "ref") {
82
443
  return refCounter.release(partIndex);
83
444
  } else if (part._tag === "event") {
84
- return _effect.Effect.tap(part.update(getEventHandler(values[partIndex], onCause)), () => refCounter.release(partIndex));
445
+ const handler = getEventHandler(renderable, ctx, part.onCause);
446
+ if (handler) {
447
+ part.addEventListener(handler);
448
+ }
449
+ return refCounter.release(partIndex);
85
450
  } else if (part._tag === "node" && hydrateCtx) {
86
- if (renderable === null || renderable === undefined) return refCounter.release(partIndex);
87
- return handlePart(values[partIndex], value => _effect.Effect.tap(part.update(value), () => refCounter.release(partIndex))).pipe(_HydrateContext.HydrateContext.provide(hydrateCtx()), _effect.Effect.forkScoped);
451
+ return handlePart(renderable, value => _effect.Effect.flatMap(part.update(value), () => refCounter.release(partIndex))).pipe(_HydrateContext.HydrateContext.provide(hydrateCtx()), _effect.Effect.forkScoped);
452
+ } else if (part._tag === "properties") {
453
+ return handlePropertiesPart(renderable, part, refCounter);
88
454
  } else {
89
- const renderable = values[partIndex];
90
- if (renderable === null || renderable === undefined) return refCounter.release(partIndex);
91
- return handlePart(values[partIndex], value => _effect.Effect.tap(part.update(value), () => refCounter.release(partIndex)));
455
+ return handlePart(renderable, value => _effect.Effect.flatMap(part.update(value), () => refCounter.release(partIndex)));
92
456
  }
93
457
  }
94
- function getEventHandler(renderable, onCause) {
458
+ function handlePropertiesPart(renderable, part, refCounter) {
459
+ if (renderable && typeof renderable === "object") {
460
+ return handlePart(Fx.struct(Object.fromEntries(Object.entries(renderable).map(([k, v]) => [k, unwrapRenderable(v)]))), value => _effect.Effect.tap(part.update(value), () => refCounter.release(part.index)));
461
+ }
462
+ return _effect.Effect.succeed(void 0);
463
+ }
464
+ function getEventHandler(renderable, ctx, onCause) {
95
465
  if (renderable && typeof renderable === "object") {
96
466
  if (EventHandler.EventHandlerTypeId in renderable) {
97
- return EventHandler.make(ev => _effect.Effect.catchAllCause(renderable.handler(ev), onCause), renderable.options);
467
+ return EventHandler.make(ev => _effect.Effect.provide(_effect.Effect.catchAllCause(renderable.handler(ev), onCause), ctx), renderable.options);
98
468
  } else if (_effect.Effect.EffectTypeId in renderable) {
99
- return EventHandler.make(() => _effect.Effect.catchAllCause(renderable, onCause));
469
+ return EventHandler.make(() => _effect.Effect.provide(_effect.Effect.catchAllCause(renderable, onCause), ctx));
100
470
  }
101
471
  }
102
472
  return null;
@@ -107,7 +477,7 @@ function handlePart(renderable, update) {
107
477
  case "object":
108
478
  {
109
479
  if (renderable === null || renderable === undefined) return update(null);else if (Array.isArray(renderable)) {
110
- return renderable.length === 0 ? update(null) : _effect.Effect.forkScoped(Fx.observe(Fx.combine(renderable.map(unwrapRenderable)), update));
480
+ return renderable.length === 0 ? update(null) : _effect.Effect.forkScoped(Fx.observe(Fx.tuple(renderable.map(unwrapRenderable)), update));
111
481
  } else if (_TypeId.TypeId in renderable) {
112
482
  return _effect.Effect.forkScoped(Fx.observe(renderable, update));
113
483
  } else if (_effect.Effect.EffectTypeId in renderable) {
@@ -124,7 +494,7 @@ function unwrapRenderable(renderable) {
124
494
  case "object":
125
495
  {
126
496
  if (renderable === null || renderable === undefined) return Fx.succeed(null);else if (Array.isArray(renderable)) {
127
- return renderable.length === 0 ? Fx.succeed(null) : Fx.combine(renderable.map(unwrapRenderable));
497
+ return renderable.length === 0 ? Fx.succeed(null) : Fx.tuple(renderable.map(unwrapRenderable));
128
498
  } else if (_TypeId.TypeId in renderable) {
129
499
  return renderable;
130
500
  } else if (_effect.Effect.EffectTypeId in renderable) {
@@ -136,7 +506,7 @@ function unwrapRenderable(renderable) {
136
506
  }
137
507
  }
138
508
  function unwrapSparsePartRenderables(renderables, part) {
139
- return Fx.combine(
509
+ return Fx.tuple(
140
510
  // @ts-ignore type too deep
141
511
  renderables.map((renderable, i) => {
142
512
  const p = part.parts[i];
@@ -191,29 +561,31 @@ function getBrowserEntry(document, ctx, templateStrings) {
191
561
  return cached;
192
562
  }
193
563
  }
194
- function buildParts(document, ctx, template, content, ref, onCause, isHydrating) {
195
- return _effect.Effect.all(template.parts.map(([part, path]) => buildPartWithNode(document, ctx, part, (0, _utils.findPath)(content, path), ref, onCause, isHydrating)));
564
+ function buildParts(document, ctx, template, content, eventSource, onCause, isHydrating) {
565
+ return template.parts.map(([part, path]) => buildPartWithNode(document, ctx, part, (0, _utils.findPath)(content, path), eventSource, onCause, isHydrating));
196
566
  }
197
- function buildPartWithNode(document, ctx, part, node, ref, onCause, isHydrating) {
567
+ function buildPartWithNode(document, ctx, part, node, eventSource, onCause, isHydrating) {
198
568
  switch (part._tag) {
199
569
  case "attr":
200
- return _effect.Effect.succeed(_parts.AttributePartImpl.browser(part.index, node, part.name, ctx));
570
+ return _parts.AttributePartImpl.browser(part.index, node, part.name, ctx);
201
571
  case "boolean-part":
202
- return _effect.Effect.succeed(_parts.BooleanPartImpl.browser(part.index, node, part.name, ctx));
572
+ return _parts.BooleanPartImpl.browser(part.index, node, part.name, ctx);
203
573
  case "className-part":
204
- return _effect.Effect.succeed(_parts.ClassNamePartImpl.browser(part.index, node, ctx));
574
+ return _parts.ClassNamePartImpl.browser(part.index, node, ctx);
205
575
  case "comment-part":
206
- return _effect.Effect.succeed(_parts.CommentPartImpl.browser(part.index, node, ctx));
576
+ return _parts.CommentPartImpl.browser(part.index, node, ctx);
207
577
  case "data":
208
- return _effect.Effect.succeed(_parts.DataPartImpl.browser(part.index, node, ctx));
578
+ return _parts.DataPartImpl.browser(part.index, node, ctx);
209
579
  case "event":
210
- return _parts.EventPartImpl.browser(part.name, part.index, ref, node, onCause);
580
+ return new _parts.EventPartImpl(part.name, part.index, ElementSource.fromElement(node), onCause, handler => eventSource.addEventListener(node, part.name, handler));
211
581
  case "node":
212
- return _effect.Effect.succeed((0, _browser.makeRenderNodePart)(part.index, node, ctx, document, isHydrating));
582
+ return (0, _browser.makeRenderNodePart)(part.index, node, ctx, document, isHydrating);
213
583
  case "property":
214
- return _effect.Effect.succeed(_parts.PropertyPartImpl.browser(part.index, node, part.name, ctx));
584
+ return _parts.PropertyPartImpl.browser(part.index, node, part.name, ctx);
585
+ case "properties":
586
+ return _parts.PropertiesPartImpl.browser(part.index, node, ctx);
215
587
  case "ref":
216
- return _effect.Effect.succeed(new _parts.RefPartImpl(ref.query(node), part.index));
588
+ return new _parts.RefPartImpl(ElementSource.fromElement(node), part.index);
217
589
  case "sparse-attr":
218
590
  {
219
591
  const parts = Array(part.nodes.length);
@@ -229,7 +601,7 @@ function buildPartWithNode(document, ctx, part, node, ref, onCause, isHydrating)
229
601
  }) => sparse.update((0, _ReadonlyArray.replace)(sparse.value, i, value || "")), sparse.value[i]));
230
602
  }
231
603
  }
232
- return _effect.Effect.succeed(sparse);
604
+ return sparse;
233
605
  }
234
606
  case "sparse-class-name":
235
607
  {
@@ -248,7 +620,7 @@ function buildPartWithNode(document, ctx, part, node, ref, onCause, isHydrating)
248
620
  }) => sparse.update((0, _ReadonlyArray.replace)(sparse.value, i, value || "")), []));
249
621
  }
250
622
  }
251
- return _effect.Effect.succeed(sparse);
623
+ return sparse;
252
624
  }
253
625
  case "sparse-comment":
254
626
  {
@@ -265,10 +637,10 @@ function buildPartWithNode(document, ctx, part, node, ref, onCause, isHydrating)
265
637
  }) => sparse.update((0, _ReadonlyArray.replace)(sparse.value, i, value || "")), sparse.value[i]));
266
638
  }
267
639
  }
268
- return _effect.Effect.succeed(sparse);
640
+ return sparse;
269
641
  }
270
642
  case "text-part":
271
- return _effect.Effect.succeed(_parts.TextPartImpl.browser(document, part.index, node, ctx));
643
+ return _parts.TextPartImpl.browser(document, part.index, node, ctx);
272
644
  }
273
645
  }
274
646
  function buildTemplate(document, {
@@ -296,6 +668,33 @@ function buildNode(document, node, isSvgContext) {
296
668
  case "comment-part":
297
669
  case "node":
298
670
  return document.createComment(`hole${node.index}`);
671
+ case "doctype":
672
+ return document.implementation.createDocumentType(node.name, docTypeNameToPublicId(node.name), docTypeNameToSystemId(node.name));
673
+ }
674
+ }
675
+ function docTypeNameToPublicId(name) {
676
+ switch (name) {
677
+ case "html":
678
+ return "-//W3C//DTD HTML 4.01//EN";
679
+ case "svg":
680
+ return "-//W3C//DTD SVG 1.1//EN";
681
+ case "math":
682
+ return "-//W3C//DTD MathML 2.0//EN";
683
+ default:
684
+ return "";
685
+ }
686
+ }
687
+ function docTypeNameToSystemId(name) {
688
+ switch (name) {
689
+ // HTML5
690
+ case "html":
691
+ return "http://www.w3.org/TR/html4/strict.dtd";
692
+ case "svg":
693
+ return "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";
694
+ case "math":
695
+ return "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd";
696
+ default:
697
+ return "";
299
698
  }
300
699
  }
301
700
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
@@ -329,4 +728,38 @@ function buildTextChild(document, node) {
329
728
  }
330
729
  return document.createComment(`hole${node.index}`);
331
730
  }
731
+ function createAttribute(document, element, name) {
732
+ return element.getAttributeNode(name) ?? document.createAttribute(name);
733
+ }
734
+ function matchSettablePart(renderable, setValue, makePart, schedule, expect) {
735
+ return matchRenderable(renderable, {
736
+ Fx: fx => {
737
+ expect();
738
+ return Fx.observe(fx, a => schedule(() => setValue(a)));
739
+ },
740
+ Effect: effect => {
741
+ expect();
742
+ return _effect.Effect.flatMap(effect, a => schedule(() => setValue(a)));
743
+ },
744
+ Directive: directive => {
745
+ expect();
746
+ return directive(makePart());
747
+ },
748
+ Otherwise: otherwise => {
749
+ setValue(otherwise);
750
+ return null;
751
+ }
752
+ });
753
+ }
754
+ function matchRenderable(renderable, matches) {
755
+ if (Fx.isFx(renderable)) {
756
+ return matches.Fx(renderable);
757
+ } else if (_effect.Effect.isEffect(renderable)) {
758
+ return matches.Effect(renderable);
759
+ } else if ((0, _Directive.isDirective)(renderable)) {
760
+ return matches.Directive(renderable);
761
+ } else {
762
+ return matches.Otherwise(renderable);
763
+ }
764
+ }
332
765
  //# sourceMappingURL=render.js.map