-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
182 lines (156 loc) · 7.89 KB
/
index.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
// Peforms: (de)serialization, observed properties and automatic rendering (in animationframe)
/* Attributes to properties */
// Assumes property names as fooBar and attribute names as foo-bar and maps them accordingly
// Inspired by: https://github.com/elix/elix/blob/master/mixins/AttributeMarshallingMixin.js
var deserialize = {
bool: function bool(val) {
if (val === true || val == 'true') return true;
if (val === false || val == 'false') return false;
return null;
},
string: function string(val) {
return val + "";
},
func: function func(val) {
if (typeof val === 'function') return val;
if (typeof val === 'string') {
if (window[val]) return window[val];
return new Function(val);
}
return null;
},
object: function object(val) {
if ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object') return val;
return null; // TODO try JSON.deserialize
},
array: function array(val) {
if (Array.isArray(val)) return val;
throw 'not implemented';
},
date: function date(val) {
if (val instanceof window.Date) return val;
throw 'not implemented';
},
number: function number(val) {
var val = Number(val);
if (isNaN(val)) return null;
return val;
},
any: function any(val) {
return val;
}
};
var defaultValues = {
bool: true,
string: '',
func: function func() {},
object: {},
array: [],
date: null,
number: 0,
any: ''
};
var RenderComponent = function (_HTMLElement) {
_inherits(RenderComponent, _HTMLElement);
function RenderComponent() {
_classCallCheck(this, RenderComponent);
// Create a (private) properties object with custom getter/setter
var _this = _possibleConstructorReturn(this, (RenderComponent.__proto__ || Object.getPrototypeOf(RenderComponent)).call(this));
var observedAttributes = [];
Object.keys(_this.constructor.properties).forEach(function (key) {
var backingProperty = Symbol(key);
Object.defineProperty(_this, key, {
get: function get() {
return this[backingProperty];
},
set: function set(val) {
if (deserialize[this.constructor.properties[key].type]) {
val = deserialize[this.constructor.properties[key].type](val);
if (val === null) return;
}
//if(this[backingProperty] === val) return; // breaks referential types (objects)
this[backingProperty] = val;
// Schedule a render
this._scheduleRender();
if (this.constructor.properties[key].attribute) {
// TODO map prop name to attr name
this.setAttribute(key, val); // Sync attribute
}
}
});
if (_this.constructor.properties[key].attribute) {
observedAttributes.push(key); // TODO map prop name to attr name
}
// Set default val based on type
_this[backingProperty] = defaultValues[_this.constructor.properties[key].type];
});
return _this;
}
_createClass(RenderComponent, [{
key: 'connectedCallback',
// Element appended to the DOM
value: function connectedCallback() {
var _this2 = this;
this._scheduleRender();
Object.keys(this.constructor.properties).forEach(function (key) {
// Set default property values (if defined)
if ('value' in _this2.constructor.properties[key]) {
_this2[key] = _this2.constructor.properties[key].value;
}
});
}
}, {
key: '_scheduleRender',
value: function _scheduleRender() {
var _this3 = this;
if (this._renderScheduled) return;
this._renderScheduled = true;
requestAnimationFrame(function () {
_this3._renderScheduled = false;
_this3.render();
});
}
}, {
key: 'attributeChangedCallback',
value: function attributeChangedCallback(attributeName, oldValue, newValue) {
if (_get(RenderComponent.prototype.__proto__ || Object.getPrototypeOf(RenderComponent.prototype), 'attributeChangedCallback', this)) {
_get(RenderComponent.prototype.__proto__ || Object.getPrototypeOf(RenderComponent.prototype), 'attributeChangedCallback', this).call(this);
}
if (oldValue === newValue) return;
var propertyName = attributeToPropertyName(attributeName);
if (propertyName in this) {
this[propertyName] = newValue;
}
}
}]);
return RenderComponent;
}(HTMLElement);
// Memoized maps of attribute to property names and vice versa.
var attributeToPropertyNames = {};
var propertyNamesToAttributes = {};
/**
* Convert hyphenated foo-bar attribute name to camel case fooBar property name.
*/
function attributeToPropertyName(attributeName) {
var propertyName = attributeToPropertyNames[attributeName];
if (!propertyName) {
// Convert and memoize.
var hyphenRegEx = /-([a-z])/g;
propertyName = attributeName.replace(hyphenRegEx, function (match) {
return match[1].toUpperCase();
});
attributeToPropertyNames[attributeName] = propertyName;
}
return propertyName;
}
exports.RenderComponent = RenderComponent;