-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
solid-template-helper.js
86 lines (75 loc) · 2.84 KB
/
solid-template-helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// This code is based on react-template-helper:
// https://github.com/meteor/react-packages/blob/master/packages/react-template-helper/react-template-helper.js
// which is licensed under the same MIT License (but with different authors)
import {checkNpmVersions} from 'meteor/tmeasday:check-npm-versions';
checkNpmVersions({
'solid-js': '>=1',
}, 'solid-template-helper');
const {createStore, reconcile} = require('solid-js/store');
const SolidWeb = require('solid-js/web');
// Empty template; logic in `onRendered` below
Template.Solid = new Template("Template.Solid", () => []);
Template.Solid.onRendered(function () {
const parentTemplate = parentTemplateName();
const template = this;
const container = this.firstNode.parentNode;
let lastComponent, setRenderProps;
this.autorun(function (c) {
const data = Blaze.getData();
const component = data && data.component;
if (!component) {
throw new Error(
`In template "${parentTemplate}", call to \`{{> Solid ... }}\` ` +
"missing `component` argument.");
}
if (typeof component !== 'function') {
throw new Error(
`In template "${parentTemplate}", call to \`{{> Solid ... }}\` ` +
"passed non-function for `component` argument.");
}
const props = Object.assign({}, data);
delete props.component;
if (component !== lastComponent) {
// Initial render or changed component
if (template.dispose) template.dispose();
template.dispose = SolidWeb.render(
() => {
let renderProps;
[renderProps, setRenderProps] = createStore(props);
return SolidWeb.createComponent(component, renderProps);
}, container);
} else {
// Same component; just update changed props reactively
setRenderProps(reconcile(props));
}
lastComponent = component;
});
});
Template.Solid.onDestroyed(function () {
if (this.dispose) this.dispose();
});
// Gets the name of the template inside of which this instance of `{{>
// Solid ...}}` is being used. Used to print more explicit error messages.
// Roughly identical to react-template-helper.js's `parentTemplateName`.
function parentTemplateName() {
let view = Blaze.getView();
if (!view || view.name !== "Template.Solid")
throw new Error("Unexpected: called outside of Template.Solid");
// find the first parent view which is a template or body
view = view.parentView;
while (view) {
// check `view.name.match(/^Template\./)` because iron-router (and
// maybe other packages) create a view named "yield" that has the
// `template` property set
let m;
if (view.template && view.name &&
(m = view.name.match(/^Template\.(.*)/))) {
return m[1];
} else if (view.name === "body") {
return "<body>";
}
view = view.parentView;
}
// not sure when this could happen
return "<unknown>";
};