custom-elements-ts 0.0.15 → 0.0.17

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.
@@ -1,259 +1,283 @@
1
- const toKebabCase = str => {
2
- return str
3
- .replace(/([a-z])([A-Z])/g, '$1-$2')
4
- .replace(/[\s_]+/g, '-')
5
- .toLowerCase();
6
- };
7
- const toCamelCase = str => {
8
- return str
9
- .toLowerCase()
10
- .replace(/(\-\w)/g, (m) => m[1].toUpperCase());
11
- };
12
- const toDotCase = (str) => {
13
- return str.replace(/(?!^)([A-Z])/g, ' $1')
14
- .replace(/[_\s]+(?=[a-zA-Z])/g, '.')
15
- .toLowerCase();
16
- };
17
- const tryParseInt = (value) => {
18
- return (parseInt(value) == value && parseFloat(value) !== NaN) ? parseInt(value) : value;
1
+ const toKebabCase = (str) => {
2
+ return str
3
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
4
+ .replace(/[\s_]+/g, '-')
5
+ .toLowerCase();
6
+ };
7
+ const toCamelCase = (str) => {
8
+ return str.toLowerCase().replace(/(-\w)/g, (m) => m[1].toUpperCase());
9
+ };
10
+ const toDotCase = (str) => {
11
+ return str
12
+ .replace(/(?!^)([A-Z])/g, ' $1')
13
+ .replace(/[_\s]+(?=[a-zA-Z])/g, '.')
14
+ .toLowerCase();
15
+ };
16
+ const tryParseInt = (value) => {
17
+ if (typeof value === 'number' && Number.isInteger(value)) {
18
+ return value;
19
+ }
20
+ if (typeof value === 'string') {
21
+ const trimmed = value.trim();
22
+ if (trimmed !== '') {
23
+ const parsed = Number(trimmed);
24
+ if (Number.isInteger(parsed) && String(parsed) === trimmed) {
25
+ return parsed;
26
+ }
27
+ }
28
+ }
29
+ return value;
19
30
  };
20
31
 
21
- const Listen = (eventName, selector) => {
22
- return (target, methodName) => {
23
- if (!target.constructor.listeners) {
24
- target.constructor.listeners = [];
25
- }
26
- target.constructor.listeners.push({ selector: selector, eventName: eventName, handler: target[methodName] });
27
- };
28
- };
29
- const addEventListeners = (target) => {
30
- if (target.constructor.listeners) {
31
- for (const listener of target.constructor.listeners) {
32
- const eventTarget = (listener.selector)
33
- ? target.shadowRoot.querySelector(listener.selector)
34
- ? target.shadowRoot.querySelector(listener.selector) : null
35
- : target;
36
- if (eventTarget) {
37
- eventTarget.addEventListener(listener.eventName, (e) => {
38
- listener.handler.call(target, e);
39
- });
40
- }
41
- }
42
- }
43
- };
44
- const Dispatch = (eventName) => {
45
- return (target, propertyName) => {
46
- function get() {
47
- const self = this;
48
- return {
49
- emit(options) {
50
- const evtName = (eventName) ? eventName : toDotCase(propertyName);
51
- self.dispatchEvent(new CustomEvent(evtName, options));
52
- }
53
- };
54
- }
55
- Object.defineProperty(target, propertyName, { get });
56
- };
32
+ const Listen = (eventName, selector) => {
33
+ return (target, methodName) => {
34
+ if (!target.constructor.listeners) {
35
+ target.constructor.listeners = [];
36
+ }
37
+ target.constructor.listeners.push({
38
+ selector: selector,
39
+ eventName: eventName,
40
+ handler: target[methodName],
41
+ });
42
+ };
43
+ };
44
+ const addEventListeners = (target) => {
45
+ if (target.constructor.listeners) {
46
+ const targetRoot = target.shadowRoot || target;
47
+ for (const listener of target.constructor.listeners) {
48
+ let eventTarget = target;
49
+ if (listener.selector) {
50
+ eventTarget = targetRoot.querySelector(listener.selector);
51
+ }
52
+ if (eventTarget) {
53
+ eventTarget.addEventListener(listener.eventName, (e) => {
54
+ listener.handler.call(target, e);
55
+ });
56
+ }
57
+ }
58
+ }
59
+ };
60
+ const Dispatch = (eventName) => {
61
+ return (target, propertyName) => {
62
+ function get() {
63
+ const self = this;
64
+ return {
65
+ emit(options) {
66
+ const evtName = eventName ? eventName : toDotCase(propertyName);
67
+ self.dispatchEvent(new CustomEvent(evtName, options));
68
+ },
69
+ };
70
+ }
71
+ Object.defineProperty(target, propertyName, { get });
72
+ };
57
73
  };
58
74
 
59
- const Prop = () => {
60
- return (target, propName) => {
61
- const attrName = toKebabCase(propName);
62
- function get() {
63
- if (this.props[propName]) {
64
- return this.props[propName];
65
- }
66
- return this.getAttribute(attrName);
67
- }
68
- function set(value) {
69
- if (this.__connected) {
70
- const oldValue = this.props[propName];
71
- this.props[propName] = tryParseInt(value);
72
- if (typeof value != 'object') {
73
- this.setAttribute(attrName, value);
74
- }
75
- else {
76
- this.onAttributeChange(attrName, oldValue, value, false);
77
- }
78
- }
79
- else {
80
- if (!this.hasAttribute(toKebabCase(propName))) {
81
- this.constructor.propsInit[propName] = value;
82
- }
83
- }
84
- }
85
- if (!target.constructor.propsInit) {
86
- target.constructor.propsInit = {};
87
- }
88
- target.constructor.propsInit[propName] = null;
89
- Object.defineProperty(target, propName, { get, set });
90
- };
91
- };
92
- const getProps = (target) => {
93
- const watchAttributes = target.constructor.watchAttributes;
94
- const plainAttributes = Object.assign({}, watchAttributes);
95
- Object.keys(plainAttributes).forEach(v => plainAttributes[v] = '');
96
- const cycleProps = Object.assign({}, plainAttributes, target.constructor.propsInit);
97
- return Object.keys(cycleProps);
98
- };
99
- const initializeProps = (target) => {
100
- const watchAttributes = target.constructor.watchAttributes;
101
- for (let prop of getProps(target)) {
102
- if (watchAttributes) {
103
- if (watchAttributes[toKebabCase(prop)] == null) {
104
- watchAttributes[toKebabCase(prop)] = '';
105
- }
106
- else {
107
- const attribValue = target.props[prop] || target.getAttribute(toKebabCase(prop));
108
- if (typeof target[watchAttributes[prop]] == 'function') {
109
- target[watchAttributes[prop]]({ new: attribValue });
110
- }
111
- }
112
- }
113
- if (target.constructor.propsInit[prop]) {
114
- if (!target.hasAttribute(toKebabCase(prop))) {
115
- target[prop] = target.constructor.propsInit[prop];
116
- }
117
- }
118
- }
75
+ const Prop = () => {
76
+ return (target, propName) => {
77
+ const attrName = toKebabCase(propName);
78
+ function get() {
79
+ const hasOwn = Object.prototype.hasOwnProperty.call(this.props, propName);
80
+ if (hasOwn) {
81
+ return this.props[propName];
82
+ }
83
+ return this.getAttribute(attrName);
84
+ }
85
+ function set(value) {
86
+ if (this.__connected) {
87
+ const oldValue = this.props[propName];
88
+ this.props[propName] = tryParseInt(value);
89
+ const valueType = typeof value;
90
+ const shouldReflect = valueType === 'string' || valueType === 'number' || valueType === 'boolean';
91
+ if (shouldReflect) {
92
+ this.setAttribute(attrName, value);
93
+ }
94
+ else {
95
+ this.onAttributeChange(attrName, oldValue, value, false);
96
+ }
97
+ }
98
+ else {
99
+ if (!this.hasAttribute(toKebabCase(propName))) {
100
+ this.constructor.propsInit[propName] = value;
101
+ }
102
+ }
103
+ }
104
+ if (!target.constructor.propsInit) {
105
+ target.constructor.propsInit = {};
106
+ }
107
+ target.constructor.propsInit[propName] = null;
108
+ Object.defineProperty(target, propName, { get, set });
109
+ };
110
+ };
111
+ const getProps = (target) => {
112
+ const watchAttributes = target.constructor.watchAttributes;
113
+ const plainAttributes = Object.assign({}, watchAttributes);
114
+ Object.keys(plainAttributes).forEach((v) => (plainAttributes[v] = ''));
115
+ const cycleProps = Object.assign(Object.assign({}, plainAttributes), target.constructor.propsInit);
116
+ return Object.keys(cycleProps);
117
+ };
118
+ const initializeProps = (target) => {
119
+ const watchAttributes = target.constructor.watchAttributes;
120
+ for (const prop of getProps(target)) {
121
+ if (watchAttributes) {
122
+ if (watchAttributes[toKebabCase(prop)] === null ||
123
+ watchAttributes[toKebabCase(prop)] === undefined) {
124
+ watchAttributes[toKebabCase(prop)] = '';
125
+ }
126
+ else {
127
+ const hasOwn = Object.prototype.hasOwnProperty.call(target.props, prop);
128
+ const attribValue = hasOwn ? target.props[prop] : target.getAttribute(toKebabCase(prop));
129
+ if (typeof target[watchAttributes[prop]] === 'function') {
130
+ target[watchAttributes[prop]]({ new: attribValue });
131
+ }
132
+ }
133
+ }
134
+ if (target.constructor.propsInit[prop]) {
135
+ if (!target.hasAttribute(toKebabCase(prop))) {
136
+ target[prop] = target.constructor.propsInit[prop];
137
+ }
138
+ }
139
+ }
119
140
  };
120
141
 
121
- const CustomElement = (args) => {
122
- return (target) => {
123
- var _a;
124
- const tag = args.tag || toKebabCase(target.prototype.constructor.name);
125
- const customElement = (_a = class extends target {
126
- constructor() {
127
- super();
128
- this.props = {};
129
- this.showShadowRoot = args.shadow == null ? true : args.shadow;
130
- if (!this.shadowRoot && this.showShadowRoot) {
131
- this.attachShadow({ mode: 'open' });
132
- }
133
- }
134
- static get observedAttributes() {
135
- return Object.keys(this.propsInit || {}).map(x => toKebabCase(x));
136
- }
137
- attributeChangedCallback(name, oldValue, newValue) {
138
- this.onAttributeChange(name, oldValue, newValue);
139
- }
140
- onAttributeChange(name, oldValue, newValue, set = true) {
141
- if (oldValue != newValue) {
142
- if (set) {
143
- this[toCamelCase(name)] = newValue;
144
- }
145
- const watchAttributes = this.constructor.watchAttributes;
146
- if (watchAttributes && watchAttributes[name]) {
147
- const methodToCall = watchAttributes[name];
148
- if (this.__connected) {
149
- if (typeof this[methodToCall] == 'function') {
150
- this[methodToCall]({ old: oldValue, new: newValue });
151
- }
152
- }
153
- }
154
- }
155
- }
156
- connectedCallback() {
157
- this.__render();
158
- super.connectedCallback && super.connectedCallback();
159
- this.__connected = true;
160
- addEventListeners(this);
161
- initializeProps(this);
162
- }
163
- __render() {
164
- if (this.__connected)
165
- return;
166
- const template = document.createElement('template');
167
- const style = ` <style>${args.style ? args.style : ''}</style>`;
168
- template.innerHTML = `${this.showShadowRoot ? style : ''}${args.template ? args.template : ''}`;
169
- (this.showShadowRoot ? this.shadowRoot : this).appendChild(document.importNode(template.content, true));
170
- }
171
- },
172
- _a.__connected = false,
173
- _a);
174
- if (!customElements.get(tag)) {
175
- customElements.define(tag, customElement);
176
- }
177
- return customElement;
178
- };
142
+ const CustomElement = (args) => {
143
+ return (target) => {
144
+ const tag = args.tag || toKebabCase(target.prototype.constructor.name);
145
+ const customElement = class extends target {
146
+ static get observedAttributes() {
147
+ return Object.keys(this.propsInit || {}).map((x) => toKebabCase(x));
148
+ }
149
+ constructor() {
150
+ super();
151
+ this.__connected = false;
152
+ this.props = {};
153
+ this.showShadowRoot =
154
+ args.shadow === undefined || args.shadow === null ? true : args.shadow;
155
+ if (!this.shadowRoot && this.showShadowRoot) {
156
+ this.attachShadow({ mode: 'open' });
157
+ }
158
+ }
159
+ attributeChangedCallback(name, oldValue, newValue) {
160
+ this.onAttributeChange(name, oldValue, newValue);
161
+ }
162
+ onAttributeChange(name, oldValue, newValue, set = true) {
163
+ if (oldValue !== newValue) {
164
+ if (set) {
165
+ const propName = toCamelCase(name);
166
+ this[propName] = newValue;
167
+ }
168
+ const watchAttributes = this.constructor.watchAttributes;
169
+ if (watchAttributes && watchAttributes[name]) {
170
+ const methodToCall = watchAttributes[name];
171
+ if (this.__connected) {
172
+ if (typeof this[methodToCall] === 'function') {
173
+ this[methodToCall]({ old: oldValue, new: newValue });
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
179
+ connectedCallback() {
180
+ this.__render();
181
+ const parentProto = Object.getPrototypeOf(Object.getPrototypeOf(this)) || null;
182
+ if (parentProto && typeof parentProto.connectedCallback === 'function') {
183
+ parentProto.connectedCallback.call(this);
184
+ }
185
+ this.__connected = true;
186
+ addEventListeners(this);
187
+ initializeProps(this);
188
+ }
189
+ __render() {
190
+ if (this.__connected)
191
+ return;
192
+ const template = document.createElement('template');
193
+ const style = `${args.style ? `<style>${args.style}</style>` : ''}`;
194
+ template.innerHTML = `${style}${args.template ? args.template : ''}`;
195
+ (this.showShadowRoot ? this.shadowRoot : this).appendChild(document.importNode(template.content, true));
196
+ }
197
+ };
198
+ if (!customElements.get(tag)) {
199
+ customElements.define(tag, customElement);
200
+ }
201
+ return customElement;
202
+ };
179
203
  };
180
204
 
181
- const Watch = (attrName) => {
182
- return (target, propertyName) => {
183
- if (!target.constructor.watchAttributes) {
184
- target.constructor.watchAttributes = {};
185
- }
186
- target.constructor.watchAttributes[toKebabCase(attrName)] = propertyName;
187
- if (!target.constructor.propsInit) {
188
- target.constructor.propsInit = {};
189
- }
190
- target.constructor.propsInit[attrName] = null;
191
- };
205
+ const Watch = (attrName) => {
206
+ return (target, propertyName) => {
207
+ if (!target.constructor.watchAttributes) {
208
+ target.constructor.watchAttributes = {};
209
+ }
210
+ target.constructor.watchAttributes[toKebabCase(attrName)] = propertyName;
211
+ if (!target.constructor.propsInit) {
212
+ target.constructor.propsInit = {};
213
+ }
214
+ target.constructor.propsInit[attrName] = null;
215
+ };
192
216
  };
193
217
 
194
- const Toggle = () => {
195
- return (target, propName) => {
196
- function get() {
197
- const getAttribute = (propName) => {
198
- if (this.hasAttribute(propName)) {
199
- const attrValue = this.getAttribute(propName);
200
- if (/^(true|false|^$)$/.test(attrValue)) {
201
- return attrValue == 'true' || attrValue == '';
202
- }
203
- else {
204
- return false;
205
- }
206
- }
207
- return false;
208
- };
209
- return getAttribute(propName);
210
- }
211
- function set(value) {
212
- const oldValue = value;
213
- if (value != undefined) {
214
- switch (typeof value) {
215
- case 'boolean':
216
- break;
217
- case 'string':
218
- if (/^(true|false|^$)$/.test(value)) {
219
- value = oldValue == 'true' || oldValue == '';
220
- }
221
- else {
222
- console.warn(`TypeError: Cannot set boolean toggle property '${propName}' to '${value}'`);
223
- value = false;
224
- }
225
- break;
226
- default:
227
- throw (`TypeError: Cannot set boolean toggle property '${propName}' to '${value}'`);
228
- }
229
- }
230
- if (this.__connected) {
231
- this.props[propName] = value || false;
232
- if (oldValue !== '' && oldValue !== null) {
233
- this.setAttribute(propName, value);
234
- }
235
- else {
236
- if (value) {
237
- this.setAttribute(propName, '');
238
- }
239
- else {
240
- this.removeAttribute(propName);
241
- }
242
- }
243
- }
244
- else {
245
- if (!this.hasAttribute(toKebabCase(propName))) {
246
- this.constructor.propsInit[propName] = value;
247
- }
248
- }
249
- }
250
- if (!target.constructor.propsInit) {
251
- target.constructor.propsInit = {};
252
- }
253
- target.constructor.propsInit[propName] = null;
254
- Object.defineProperty(target, propName, { get, set });
255
- };
218
+ const Toggle = () => {
219
+ return (target, propName) => {
220
+ function get() {
221
+ const getAttribute = (attrName) => {
222
+ if (this.hasAttribute(attrName)) {
223
+ const attrValue = this.getAttribute(attrName);
224
+ if (/^(true|false|^$)$/.test(attrValue)) {
225
+ return attrValue === 'true' || attrValue === '';
226
+ }
227
+ else {
228
+ return false;
229
+ }
230
+ }
231
+ return false;
232
+ };
233
+ return getAttribute(propName);
234
+ }
235
+ function set(value) {
236
+ const oldValue = value;
237
+ if (value !== null && value !== undefined) {
238
+ switch (typeof value) {
239
+ case 'boolean':
240
+ break;
241
+ case 'string':
242
+ if (/^(true|false|^$)$/.test(value)) {
243
+ value = oldValue === 'true' || oldValue === '';
244
+ }
245
+ else {
246
+ console.warn(`TypeError: Cannot set boolean toggle property '${propName}' to '${value}'`);
247
+ value = false;
248
+ }
249
+ break;
250
+ default:
251
+ throw new TypeError(`Cannot set boolean toggle property '${propName}' to '${value}'`);
252
+ }
253
+ }
254
+ if (this.__connected) {
255
+ this.props[propName] = value || false;
256
+ if (oldValue !== '' && oldValue !== null) {
257
+ this.setAttribute(propName, value);
258
+ }
259
+ else {
260
+ if (value) {
261
+ this.setAttribute(propName, '');
262
+ }
263
+ else {
264
+ this.removeAttribute(propName);
265
+ }
266
+ }
267
+ }
268
+ else {
269
+ if (!this.hasAttribute(toKebabCase(propName))) {
270
+ this.constructor.propsInit[propName] = value;
271
+ }
272
+ }
273
+ }
274
+ if (!target.constructor.propsInit) {
275
+ target.constructor.propsInit = {};
276
+ }
277
+ target.constructor.propsInit[propName] = null;
278
+ Object.defineProperty(target, propName, { get, set });
279
+ };
256
280
  };
257
281
 
258
- export { CustomElement, Watch, Prop, initializeProps, Toggle, Listen, addEventListeners, Dispatch };
282
+ export { CustomElement, Dispatch, Listen, Prop, Toggle, Watch, addEventListeners, initializeProps };
259
283
  //# sourceMappingURL=custom-elements-ts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-ts.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"custom-elements-ts.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,12 +1,12 @@
1
- export interface CustomElementMetadata {
2
- tag?: string;
3
- template?: string;
4
- templateUrl?: string;
5
- styleUrl?: string;
6
- style?: string;
7
- shadow?: boolean;
8
- }
9
- export interface KeyValue {
10
- [key: string]: any;
11
- }
12
- export declare const CustomElement: (args: CustomElementMetadata) => (target: any) => any;
1
+ export interface CustomElementMetadata {
2
+ tag?: string;
3
+ template?: string;
4
+ templateUrl?: string;
5
+ styleUrl?: string;
6
+ style?: string;
7
+ shadow?: boolean;
8
+ }
9
+ export interface KeyValue {
10
+ [key: string]: any;
11
+ }
12
+ export declare const CustomElement: (args: CustomElementMetadata) => (target: any) => any;