@htmlplus/element 2.2.0 → 2.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.
package/README.md CHANGED
@@ -475,7 +475,7 @@ Parameters:
475
475
  <br />
476
476
  - `type` (Optional)
477
477
  <br />
478
- Do not set the value to this property. This value is automatically set during transpiling.
478
+ Do not set the value to this property. This value is automatically set during transforming.
479
479
  <br />
480
480
  <br />
481
481
 
@@ -1,6 +1,6 @@
1
- import { camelCase, kebabCase } from 'change-case';
1
+ import { camelCase } from 'change-case';
2
2
  import * as CONSTANTS from '../../constants/index.js';
3
- import { call, getConfig, getMembers, getTag, isServer, request, toProperty } from '../utils/index.js';
3
+ import { call, getConfig, getTag, isServer, request } from '../utils/index.js';
4
4
  /**
5
5
  * The class marked with this decorator is considered a
6
6
  * [Custom Element](https://mdn.io/using-custom-elements),
@@ -13,17 +13,11 @@ export function Element() {
13
13
  const tag = getTag(constructor);
14
14
  if (customElements.get(tag))
15
15
  return;
16
- const members = getMembers(constructor);
17
16
  class Plus extends HTMLElement {
18
17
  constructor() {
19
18
  super();
20
19
  this.attachShadow({ mode: 'open' });
21
20
  const instance = (this[CONSTANTS.API_INSTANCE] = new constructor());
22
- Object.keys(members).forEach((key) => {
23
- if (members[key].type != CONSTANTS.TYPE_FUNCTION) {
24
- members[key].default = instance[key];
25
- }
26
- });
27
21
  instance[CONSTANTS.API_HOST] = () => this;
28
22
  // TODO
29
23
  call(instance, CONSTANTS.LIFECYCLE_CONSTRUCTED);
@@ -32,25 +26,23 @@ export function Element() {
32
26
  static get formAssociated() {
33
27
  return constructor['formAssociated'];
34
28
  }
29
+ // TODO
35
30
  static get observedAttributes() {
36
- return Object.keys(members)
37
- .filter((key) => members[key].type != CONSTANTS.TYPE_FUNCTION)
38
- .map((key) => kebabCase(key));
31
+ return constructor['observedAttributes'];
39
32
  }
40
33
  adoptedCallback() {
41
34
  call(this[CONSTANTS.API_INSTANCE], CONSTANTS.LIFECYCLE_ADOPTED);
42
35
  }
43
36
  attributeChangedCallback(attribute, prev, next) {
44
- var _a;
45
37
  const instance = this[CONSTANTS.API_INSTANCE];
46
38
  if (instance[CONSTANTS.API_LOCKED])
47
39
  return;
48
40
  const name = camelCase(attribute);
49
- const type = (_a = members[name]) === null || _a === void 0 ? void 0 : _a.type;
50
- const value = toProperty(next, type);
51
- if (instance[name] === value)
52
- return;
53
- instance[name] = value;
41
+ // ensures the integrity of readonly properties to prevent potential errors.
42
+ try {
43
+ this[name] = next;
44
+ }
45
+ catch (_a) { }
54
46
  }
55
47
  connectedCallback() {
56
48
  const instance = this[CONSTANTS.API_INSTANCE];
@@ -6,7 +6,7 @@ import { appendToMethod, defineProperty, host } from '../utils/index.js';
6
6
  */
7
7
  export function Method() {
8
8
  return function (target, propertyKey) {
9
- appendToMethod(target, CONSTANTS.LIFECYCLE_CONNECTED, function () {
9
+ appendToMethod(target, CONSTANTS.LIFECYCLE_CONSTRUCTED, function () {
10
10
  defineProperty(host(this), propertyKey, {
11
11
  get: () => this[propertyKey].bind(this)
12
12
  });
@@ -8,7 +8,7 @@ export interface PropertyOptions {
8
8
  */
9
9
  reflect?: boolean;
10
10
  /**
11
- * Do not set the value to this property. This value is automatically set during transpiling.
11
+ * Do not set the value to this property. This value is automatically set during transforming.
12
12
  */
13
13
  type?: number;
14
14
  }
@@ -16,4 +16,4 @@ export interface PropertyOptions {
16
16
  * Creates a reactive property, reflecting a corresponding attribute value,
17
17
  * and updates the element when the property is set.
18
18
  */
19
- export declare function Property(options?: PropertyOptions): (target: PlusElement, propertyKey: PropertyKey) => void;
19
+ export declare function Property(options?: PropertyOptions): (target: PlusElement, propertyKey: PropertyKey, descriptor?: PropertyDescriptor) => void;
@@ -1,44 +1,80 @@
1
+ import { kebabCase } from 'change-case';
1
2
  import * as CONSTANTS from '../../constants/index.js';
2
- import { addMember, appendToMethod, defineProperty, host, request, toProperty, updateAttribute } from '../utils/index.js';
3
+ import { appendToMethod, defineProperty, host, request, toProperty, updateAttribute } from '../utils/index.js';
3
4
  /**
4
5
  * Creates a reactive property, reflecting a corresponding attribute value,
5
6
  * and updates the element when the property is set.
6
7
  */
7
8
  export function Property(options) {
8
- return function (target, propertyKey) {
9
+ return function (target, propertyKey, descriptor) {
10
+ var _a;
11
+ // Converts property name to string.
9
12
  const name = String(propertyKey);
10
- const symbol = Symbol();
11
- addMember(target.constructor, name, options);
12
- function get() {
13
- return this[symbol];
13
+ // Registers an attribute that is intricately linked to the property.
14
+ ((_a = target.constructor)['observedAttributes'] || (_a['observedAttributes'] = [])).push(kebabCase(name));
15
+ // TODO: This feature is an experimental
16
+ // When the property is a getter function.
17
+ if (descriptor) {
18
+ // Checks the reflection.
19
+ if (options === null || options === void 0 ? void 0 : options.reflect) {
20
+ // Stores the original getter function.
21
+ const getter = descriptor.get;
22
+ // Defines a new getter function.
23
+ descriptor.get = function () {
24
+ const value = getter === null || getter === void 0 ? void 0 : getter.apply(this);
25
+ target[CONSTANTS.API_LOCKED] = true;
26
+ updateAttribute(host(this), name, value);
27
+ target[CONSTANTS.API_LOCKED] = false;
28
+ return value;
29
+ };
30
+ // TODO: Check the lifecycle
31
+ appendToMethod(target, CONSTANTS.LIFECYCLE_UPDATED, function () {
32
+ // Calls the getter function to update the related attribute.
33
+ this[name];
34
+ });
35
+ }
14
36
  }
15
- function set(next) {
16
- const previous = this[symbol];
17
- if (next === previous)
18
- return;
19
- this[symbol] = next;
20
- request(this, name, previous, (skipped) => {
21
- if (!(options === null || options === void 0 ? void 0 : options.reflect) || skipped)
37
+ // When the property is normal.
38
+ else {
39
+ // Creates a unique symbol.
40
+ const symbol = Symbol();
41
+ // Defines a getter function to use in the target class.
42
+ function get() {
43
+ return this[symbol];
44
+ }
45
+ // Defines a setter function to use in the target class.
46
+ function set(next) {
47
+ const previous = this[symbol];
48
+ if (next === previous)
22
49
  return;
23
- target[CONSTANTS.API_LOCKED] = true;
24
- updateAttribute(host(this), name, next);
25
- target[CONSTANTS.API_LOCKED] = false;
26
- });
50
+ this[symbol] = next;
51
+ request(this, name, previous, (skipped) => {
52
+ if (!(options === null || options === void 0 ? void 0 : options.reflect) || skipped)
53
+ return;
54
+ target[CONSTANTS.API_LOCKED] = true;
55
+ updateAttribute(host(this), name, next);
56
+ target[CONSTANTS.API_LOCKED] = false;
57
+ });
58
+ }
59
+ // Attaches the getter and setter functions to the current property of the target class.
60
+ defineProperty(target, propertyKey, { get, set });
27
61
  }
28
- defineProperty(target, propertyKey, { get, set });
29
- // TODO: check the lifecycle
62
+ // TODO: Check the lifecycle
30
63
  appendToMethod(target, CONSTANTS.LIFECYCLE_CONSTRUCTED, function () {
64
+ // Gets the host element from the target class.
31
65
  const element = host(this);
32
- // TODO: experimental for isolated options
33
- if (element === this)
34
- return;
66
+ // Defines a getter function to use in the host element.
35
67
  const get = () => {
36
68
  return this[propertyKey];
37
69
  };
38
- const set = (input) => {
39
- this[propertyKey] = toProperty(input, options === null || options === void 0 ? void 0 : options.type);
40
- };
41
- // TODO: configurable
70
+ // Defines a setter function to use in the host element.
71
+ const set = descriptor
72
+ ? undefined
73
+ : (input) => {
74
+ this[propertyKey] = toProperty(input, options === null || options === void 0 ? void 0 : options.type);
75
+ };
76
+ // TODO: Check the configuration.
77
+ // Attaches the getter and setter functions to the current property of the host element.
42
78
  defineProperty(element, propertyKey, { get, set, configurable: true });
43
79
  });
44
80
  };
@@ -1,5 +1,5 @@
1
1
  import * as CONSTANTS from '../../constants/index.js';
2
2
  export const getStyles = (target) => {
3
3
  var _a;
4
- return (_a = target.constructor[CONSTANTS.STATIC_STYLES]) !== null && _a !== void 0 ? _a : target[CONSTANTS.STATIC_STYLES];
4
+ return (_a = target.constructor[CONSTANTS.STATIC_STYLE]) !== null && _a !== void 0 ? _a : target[CONSTANTS.STATIC_STYLE];
5
5
  };
@@ -1,4 +1,3 @@
1
- export * from './addMember.js';
2
1
  export * from './appendToMethod.js';
3
2
  export * from './attributes.js';
4
3
  export * from './call.js';
@@ -8,7 +7,6 @@ export * from './defineProperty.js';
8
7
  export * from './direction.js';
9
8
  export * from './event.js';
10
9
  export * from './getFramework.js';
11
- export * from './getMembers.js';
12
10
  export * from './getStyles.js';
13
11
  export * from './getTag.js';
14
12
  export * from './host.js';
@@ -1,4 +1,3 @@
1
- export * from './addMember.js';
2
1
  export * from './appendToMethod.js';
3
2
  export * from './attributes.js';
4
3
  export * from './call.js';
@@ -8,7 +7,6 @@ export * from './defineProperty.js';
8
7
  export * from './direction.js';
9
8
  export * from './event.js';
10
9
  export * from './getFramework.js';
11
- export * from './getMembers.js';
12
10
  export * from './getStyles.js';
13
11
  export * from './getTag.js';
14
12
  export * from './host.js';
@@ -7,10 +7,10 @@ export const toProperty = (input, type) => {
7
7
  if (CONSTANTS.TYPE_BOOLEAN & type) {
8
8
  if (string === '')
9
9
  return true;
10
- if (string === 'false')
11
- return false;
12
10
  if (string === 'true')
13
11
  return true;
12
+ if (string === 'false')
13
+ return false;
14
14
  }
15
15
  if (CONSTANTS.TYPE_NUMBER & type) {
16
16
  if (string != '' && !isNaN(input)) {
@@ -11,6 +11,7 @@ export declare const DECORATOR_CSS_VARIABLE = "@Property()";
11
11
  export declare const DECORATOR_ELEMENT = "Element";
12
12
  export declare const DECORATOR_EVENT = "Event";
13
13
  export declare const DECORATOR_PROPERTY = "Property";
14
+ export declare const DECORATOR_PROPERTY_TYPE = "type";
14
15
  export declare const DECORATOR_STATE = "State";
15
16
  export declare const DECORATOR_METHOD = "Method";
16
17
  export declare const ELEMENT_HOST_NAME = "host";
@@ -23,11 +24,8 @@ export declare const LIFECYCLE_LOADED = "loadedCallback";
23
24
  export declare const LIFECYCLE_UPDATE = "updateCallback";
24
25
  export declare const LIFECYCLE_UPDATED = "updatedCallback";
25
26
  export declare const METHOD_RENDER = "render";
26
- export declare const STATIC_MEMBERS = "MEMBERS";
27
- export declare const STATIC_MEMBERS_INITIALIZER = "default";
28
- export declare const STATIC_MEMBERS_TYPE = "type";
29
- export declare const STATIC_STYLES = "STYLES";
30
- export declare const STATIC_TAG = "TAG";
27
+ export declare const STATIC_STYLE = "style";
28
+ export declare const STATIC_TAG = "tag";
31
29
  export declare const STYLE_IMPORTED = "STYLE_IMPORTED";
32
30
  export declare const TYPE_ARRAY: number;
33
31
  export declare const TYPE_BOOLEAN: number;
@@ -15,6 +15,7 @@ export const DECORATOR_CSS_VARIABLE = '@Property()';
15
15
  export const DECORATOR_ELEMENT = 'Element';
16
16
  export const DECORATOR_EVENT = 'Event';
17
17
  export const DECORATOR_PROPERTY = 'Property';
18
+ export const DECORATOR_PROPERTY_TYPE = 'type';
18
19
  export const DECORATOR_STATE = 'State';
19
20
  export const DECORATOR_METHOD = 'Method';
20
21
  // element
@@ -31,11 +32,8 @@ export const LIFECYCLE_UPDATED = 'updatedCallback';
31
32
  // methods
32
33
  export const METHOD_RENDER = 'render';
33
34
  // statics
34
- export const STATIC_MEMBERS = 'MEMBERS';
35
- export const STATIC_MEMBERS_INITIALIZER = 'default';
36
- export const STATIC_MEMBERS_TYPE = 'type';
37
- export const STATIC_STYLES = 'STYLES';
38
- export const STATIC_TAG = 'TAG';
35
+ export const STATIC_STYLE = 'style';
36
+ export const STATIC_TAG = 'tag';
39
37
  // style
40
38
  export const STYLE_IMPORTED = 'STYLE_IMPORTED';
41
39
  // types
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlplus/element",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "author": "Masood Abdolian <m.abdolian@gmail.com>",
@@ -273,9 +273,9 @@ export const customElement = (options) => {
273
273
  }
274
274
  const [argument] = expression.arguments;
275
275
  argument.properties = argument.properties.filter((property) => {
276
- return property.key.name != CONSTANTS.STATIC_MEMBERS_TYPE;
276
+ return property.key.name != CONSTANTS.DECORATOR_PROPERTY_TYPE;
277
277
  });
278
- argument.properties.push(t.objectProperty(t.identifier(CONSTANTS.STATIC_MEMBERS_TYPE), t.numericLiteral(type)));
278
+ argument.properties.push(t.objectProperty(t.identifier(CONSTANTS.DECORATOR_PROPERTY_TYPE), t.numericLiteral(type)));
279
279
  }
280
280
  });
281
281
  // attach typings
@@ -116,11 +116,12 @@ export const document = (options) => {
116
116
  });
117
117
  });
118
118
  const properties = context.classProperties.map((property) => {
119
- var _a, _b;
119
+ var _a, _b, _c;
120
120
  const attribute = kebabCase(property.key['name']);
121
121
  // TODO
122
122
  const initializer = getInitializer(property.value);
123
123
  const name = property.key['name'];
124
+ const readonly = property['kind'] == 'get';
124
125
  // TODO
125
126
  const reflects = (() => {
126
127
  if (!property.decorators)
@@ -143,13 +144,17 @@ export const document = (options) => {
143
144
  catch (_a) { }
144
145
  return false;
145
146
  })();
146
- const required = !property.optional;
147
- const type = print((_a = property.typeAnnotation) === null || _a === void 0 ? void 0 : _a['typeAnnotation']);
148
- const typeReference = getTypeReference(context.fileAST, (_b = property.typeAnnotation) === null || _b === void 0 ? void 0 : _b['typeAnnotation']);
147
+ const required = 'optional' in property && !property.optional;
148
+ // TODO
149
+ const type = property['returnType']
150
+ ? print((_a = property['returnType']) === null || _a === void 0 ? void 0 : _a['typeAnnotation'])
151
+ : print((_b = property.typeAnnotation) === null || _b === void 0 ? void 0 : _b['typeAnnotation']);
152
+ const typeReference = getTypeReference(context.fileAST, (_c = property.typeAnnotation) === null || _c === void 0 ? void 0 : _c['typeAnnotation']);
149
153
  return Object.assign({
150
154
  attribute,
151
155
  initializer,
152
156
  name,
157
+ readonly,
153
158
  reflects,
154
159
  required,
155
160
  type,
@@ -34,7 +34,7 @@ export const style = (options) => {
34
34
  context.styleName = path.basename(context.stylePath, context.styleExtension);
35
35
  const { local } = addDependency(context.fileAST, context.stylePath, CONSTANTS.STYLE_IMPORTED, undefined, true);
36
36
  // TODO: remove 'local!'
37
- const property = t.classProperty(t.identifier(CONSTANTS.STATIC_STYLES), t.identifier(local), undefined, null, undefined, true);
37
+ const property = t.classProperty(t.identifier(CONSTANTS.STATIC_STYLE), t.identifier(local), undefined, null, undefined, true);
38
38
  t.addComment(property, 'leading', CONSTANTS.COMMENT_AUTO_ADDED, true);
39
39
  context.class.body.body.unshift(property);
40
40
  };
@@ -1,2 +0,0 @@
1
- import { PlusElement } from '../../types';
2
- export declare const addMember: (target: PlusElement, key: string, data: any) => void;
@@ -1,6 +0,0 @@
1
- import * as CONSTANTS from '../../constants/index.js';
2
- export const addMember = (target, key, data) => {
3
- var _a;
4
- target[_a = CONSTANTS.STATIC_MEMBERS] || (target[_a] = {});
5
- target[CONSTANTS.STATIC_MEMBERS][key] = data;
6
- };
@@ -1,8 +0,0 @@
1
- import * as CONSTANTS from '../../constants/index.js';
2
- import { PlusElement } from '../../types';
3
- export declare const getMembers: (target: PlusElement) => {
4
- [member: string]: {
5
- default?: any;
6
- type?: any;
7
- };
8
- };
@@ -1,5 +0,0 @@
1
- import * as CONSTANTS from '../../constants/index.js';
2
- // TODO
3
- export const getMembers = (target) => {
4
- return target[CONSTANTS.STATIC_MEMBERS] || {};
5
- };