@htmlplus/element 0.1.0 → 0.1.1

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
@@ -1,17 +1,29 @@
1
1
  # Create Custom HTML Element
2
2
 
3
- TODO
3
+ [![Version](https://img.shields.io/npm/v/@htmlplus/element.svg)](https://www.npmjs.com/package/@htmlplus/element)
4
+ [![GitHub forks](https://img.shields.io/github/forks/htmlplus/element)](https://github.com/htmlplus/element/network/members)
5
+ [![GitHub stars](https://img.shields.io/github/stars/htmlplus/element)](https://github.com/htmlplus/element/stargazers)
6
+ [![GitHub license](https://img.shields.io/github/license/htmlplus/element)](https://github.com/htmlplus/core/blob/main/LICENSE)
7
+ [![Linkedin](https://img.shields.io/badge/Follow%20us-white?logo=linkedIn&color=0077B5&logoColor=white)](https://www.linkedin.com/company/htmlplus)
8
+ [![code coverage](https://img.shields.io/coveralls//htmlplus/element/.svg?style=flat-square)](https://coveralls.io/r/htmlplus/element/)
9
+ [![install size](https://packagephobia.now.sh/badge?p=element)](https://packagephobia.now.sh/result?p=element)
10
+
11
+ Element is powerful library for building scalable, reusable design system for any technology.
12
+ It is one of the fastest and most testable libraries for building web components on the web.
13
+ Completely compatible for Typescript and tsx.
4
14
 
5
15
  ## Table of content
6
16
 
7
17
  - [Install](#install)
8
18
  - [Start](#start)
9
- - [First element](#Firstelement)
19
+ - [First Element](#FirstElement)
20
+ - [Styles](#Styles)
21
+ - [Development Environment](#DevelopmentEnvironment)
10
22
  - [Decorators](#decorators)
11
23
  - [Helpers](#helpers)
12
24
  - [Lifecycles](#lifecycles)
13
25
  - [Services](#services)
14
- - [Tag name configuration](#TagNameConfiguration)
26
+ - [Tag Name Configuration](#TagNameConfiguration)
15
27
  - [Compiler](#compiler)
16
28
 
17
29
  ## Install
@@ -31,19 +43,34 @@ pnpm create @htmlplus/element
31
43
 
32
44
  ## Start
33
45
 
34
- TODO
35
-
36
46
  ```bash
37
47
  cd htmlplus-project
48
+ ```
49
+
50
+ To start your Element project, run:
51
+
52
+ ```bash
53
+ # with npm
38
54
  npm i
39
55
  npm start
56
+
57
+ # with yarn
58
+ yarn install
59
+ yarn start
60
+
61
+ # with pnpm
62
+ pnpm install
63
+ pnpm start
40
64
  ```
41
65
 
42
- ## First element
66
+ ## First Element
43
67
 
44
- TODO
68
+ Element is based on classes, so all components are based on `decorator`.
69
+ The decorator converts the next component code based on it's properties during the build.
45
70
 
46
71
  ```tsx
72
+ // my-element/my-element.tsx
73
+
47
74
  import { Element } from '@htmlplus/element';
48
75
 
49
76
  @Element('my-element')
@@ -54,23 +81,55 @@ export class MyElement {
54
81
  }
55
82
  ```
56
83
 
84
+ The result of this component after build is provide `my-element` web component.
85
+
57
86
  ```html
58
87
  <my-element></my-element>
59
88
  ```
60
89
 
90
+ ## Styles
91
+
92
+ The element automatically adds a same name style file to this component. Create `my-element.scss` file for style.
93
+
94
+ ```scss
95
+ // my-element/my-element.scss
96
+
97
+ :host {
98
+ display: block;
99
+ background-color: red;
100
+ font-size: 2rem;
101
+ }
102
+ ```
103
+
104
+ ## Development Environment
105
+
106
+ For run any of the component, you must write element name tag into the `public/index.html`
107
+
108
+ ```html
109
+ <!-- public/index.html -->
110
+
111
+ <body>
112
+ <my-element></my-element>
113
+ </body>
114
+ ```
115
+
61
116
  ## Decorators
62
117
 
63
- TODO
118
+ With the introduction of Classes in TypeScript and ES6, there now exist certain scenarios that require additional features to support annotating or modifying classes and class members. Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members [More information](https://www.typescriptlang.org/docs/handbook/decorators.html).
64
119
 
65
120
  <details>
66
121
  <summary>Element</summary>
67
122
 
68
- TODO
123
+ Any component must be decorated with `@Element()` decorator. It also makes your web component tag name.
124
+
125
+ Options:
126
+
127
+ - **name**: `String` tag name
69
128
 
70
129
  ```tsx
71
130
  import { Element } from '@htmlplus/element';
72
131
 
73
- @Element()
132
+ @Element('my-element')
74
133
  export class MyElement {
75
134
  render() {
76
135
  return <h1>Hi Everybody</h1>
@@ -87,12 +146,12 @@ export class MyElement {
87
146
  <details>
88
147
  <summary>Property</summary>
89
148
 
90
- TODO
149
+ Property is decorated all the component properties for exposed attributes.
91
150
 
92
151
  Options:
93
152
 
94
153
  - **attribute**: TODO
95
- - **reflect**: TODO
154
+ - **reflect**: `Boolean` For watch mode, when you want to be notified of the attribute change.
96
155
 
97
156
  ```tsx
98
157
  import { Element, Property } from '@htmlplus/element';
@@ -122,14 +181,14 @@ export class SayGreeting {
122
181
  <details>
123
182
  <summary>Event</summary>
124
183
 
125
- TODO
184
+ Components can emit data and events using the Event decorator.
126
185
 
127
186
  Options:
128
187
 
129
- - **name**: A string custom event name to override the default.
130
- - **bubbles**: A Boolean indicating whether the event bubbles up through the DOM or not. default is `false`.
131
- - **cancelable**: A Boolean indicating whether the event is cancelable. default is `false`.
132
- - **composed**: A Boolean value indicating whether or not the event can bubble across the boundary between the shadow DOM and the regular DOM. The default is false.
188
+ - **name**: A `String` custom event name to override the default.
189
+ - **bubbles**: A `Boolean` indicating whether the event bubbles up through the DOM or not. default is `false`.
190
+ - **cancelable**: A `Boolean` indicating whether the event is cancelable. default is `false`.
191
+ - **composed**: A `Boolean` value indicating whether or not the event can bubble across the boundary between the shadow DOM and the regular DOM. The default is `false`.
133
192
 
134
193
  ```tsx
135
194
  import { Element, Event, EventEmitter } from '@htmlplus/element';
@@ -163,25 +222,37 @@ export class MyButton {
163
222
  <details>
164
223
  <summary>Method</summary>
165
224
 
166
- TODO
225
+ Ths `@Method` decorator can be called directly from the element. It can be called from the outside.
167
226
 
168
227
  ```tsx
169
- import { Element, Method } from '@htmlplus/element';
228
+ import { Element, Method, State } from '@htmlplus/element';
170
229
 
171
230
  @Element()
172
- export class MyDialog {
231
+ export class MyCounter {
232
+
233
+ @State()
234
+ counter?: number;
235
+
173
236
  @Method()
174
- open() {
175
- /* TODO */
237
+ increase() {
238
+ this.counter++;
239
+ }
240
+
241
+ render() {
242
+ return (
243
+ <button>
244
+ {this.counter}
245
+ </button>
246
+ )
176
247
  }
177
248
  }
178
249
  ```
179
250
 
180
251
  ```html
181
- <my-dialog id="dialog"></my-dialog>
252
+ <my-counter id="counter"></my-counter>
182
253
 
183
254
  <script>
184
- document.getElementById('dialog').open();
255
+ document.getElementById('counter').increase();
185
256
  </script>
186
257
  ```
187
258
 
@@ -190,11 +261,14 @@ export class MyDialog {
190
261
  <details>
191
262
  <summary>Watch</summary>
192
263
 
193
- TODO
264
+ `@Watch` take the name of the `@Property` and `@State` variable to monitor as a parameter. Any time the value of that property changes the function decorated by `@Watch` will be invoked with the `key`, `newValue` and `oldValue` as parameters. This is called first out of the lifecycle callbacks after a property changes.
265
+
266
+ - **name**: `String` property name
194
267
 
195
268
  ```tsx
196
269
  import { Element, Property, Watch } from '@htmlplus/element';
197
270
 
271
+
198
272
  @Element()
199
273
  export class MyElement {
200
274
 
@@ -211,17 +285,16 @@ export class MyElement {
211
285
  <details>
212
286
  <summary>Listen</summary>
213
287
 
214
- ### Listen
215
-
216
- TODO
288
+ The `@Listen` decorates a function that will handle the event.
289
+ It takes two parameter, event name and event config.
217
290
 
218
291
  Options:
219
292
 
220
- - **target**: TODO
221
- - **once**: TODO
222
- - **passive**: TODO
293
+ - **target**: `body | document | window | host` This option allows us to set where we will listen for the event.
294
+ - **once**: `Boolean` Listen just for one time.
295
+ - **passive**: `Boolean` This will guarantee to the DOM that the event being fired will not `.stopPropagation()`.
223
296
  - **signal**: TODO
224
- - **capture**: TODO
297
+ - **capture**: `Boolean` This option is about when during the event lifecycle the handler will be called.
225
298
 
226
299
  ```tsx
227
300
  import { Element, Listen } from '@htmlplus/element';
@@ -229,25 +302,19 @@ import { Element, Listen } from '@htmlplus/element';
229
302
  @Element()
230
303
  export class MyButton {
231
304
  @Listen('click')
232
- onClick(event) {
233
- /* TODO */
234
- }
305
+ onClick(event) {}
235
306
  }
236
307
  ```
237
308
 
238
- </details>
239
-
240
- <details>
241
- <summary>ListenOptions</summary>
242
-
243
- TODO
244
-
245
- Options:
309
+ ```tsx
310
+ import { Element, Listen } from '@htmlplus/element';
246
311
 
247
- - **once**: TODO
248
- - **passive**: TODO
249
- - **signal**: TODO
250
- - **capture**: TODO
312
+ @Element()
313
+ export class MyContainer {
314
+ @Listen('scroll', { target: 'window' })
315
+ onScroll(event) {}
316
+ }
317
+ ```
251
318
 
252
319
  ```tsx
253
320
  import { Element, ListenOptions } from '@htmlplus/element';
@@ -256,9 +323,7 @@ import { Element, ListenOptions } from '@htmlplus/element';
256
323
  export class MyButton {
257
324
 
258
325
  @ListenOptions({ once: true })
259
- onClick(event) {
260
- /* TODO */
261
- }
326
+ onClick(event) {}
262
327
 
263
328
  render() {
264
329
  return (
@@ -275,7 +340,8 @@ export class MyButton {
275
340
  <details>
276
341
  <summary>State</summary>
277
342
 
278
- TODO
343
+ The `@State` decorator is for manage data inside the component.
344
+ Any changes of `@State` will cause the render function to called again.
279
345
 
280
346
  ```tsx
281
347
  import { Element, Listen, State } from '@htmlplus/element';
@@ -306,9 +372,7 @@ export class MySwitch {
306
372
  <details>
307
373
  <summary>Bind</summary>
308
374
 
309
- ### Bind
310
-
311
- TODO
375
+ The `@Bind` for decorating methods only, by binding them to the current context.
312
376
 
313
377
  ```tsx
314
378
  import { Bind, Element } from '@htmlplus/element';
@@ -669,7 +733,7 @@ TODO
669
733
 
670
734
  </details>
671
735
 
672
- ## Tag name configuration
736
+ ## Tag Name Configuration
673
737
 
674
738
  All examples below produce output `<plus-button></plus-button>`
675
739
 
@@ -1,13 +1,14 @@
1
1
  import * as CONSTANTS from '../../configs/constants.js';
2
+ import { host } from '../helpers/index.js';
2
3
  import { defineMethod, sync } from '../utils/index.js';
3
4
  export function Attributes() {
4
5
  return function (target, propertyKey) {
5
6
  let update;
6
7
  defineMethod(target, CONSTANTS.TOKEN_LIFECYCLE_CONNECTED, function (instance, callback, args) {
7
- update = sync(instance);
8
+ update = sync(host(instance));
8
9
  return callback === null || callback === void 0 ? void 0 : callback(...args);
9
10
  });
10
- defineMethod(target, CONSTANTS.TOKEN_LIFECYCLE_UPDATE, function (instance, callback, args) {
11
+ defineMethod(target, CONSTANTS.TOKEN_LIFECYCLE_UPDATED, function (instance, callback, args) {
11
12
  update(instance[propertyKey]);
12
13
  return callback === null || callback === void 0 ? void 0 : callback(...args);
13
14
  });
@@ -1 +1 @@
1
- export declare function Bind(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
1
+ export declare function Bind(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -1,3 +1,3 @@
1
1
  import { EventOptions } from '../../types/index.js';
2
2
  export declare type EventEmitter<T = any> = (data?: T) => CustomEvent<T>;
3
- export declare function Event<T = any>(options?: EventOptions): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
3
+ export declare function Event<T = any>(options?: EventOptions): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -1,2 +1,2 @@
1
1
  import { ListenOptions, PlusElement } from '../../types/index.js';
2
- export declare function Listen(name: string, options?: ListenOptions): (target: PlusElement, propertyKey: PropertyKey) => void;
2
+ export declare function Listen(name: string, options?: ListenOptions): (target: PlusElement, propertyKey: PropertyKey, descriptor: PropertyDescriptor) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -1,11 +1,12 @@
1
1
  import * as CONSTANTS from '../../configs/constants.js';
2
2
  import { host } from '../helpers/index.js';
3
3
  import { defineMethod } from '../utils/index.js';
4
+ import { Bind } from './bind.js';
4
5
  const defaults = {
5
6
  target: 'host'
6
7
  };
7
8
  export function Listen(name, options = defaults) {
8
- return function (target, propertyKey) {
9
+ return function (target, propertyKey, descriptor) {
9
10
  // TODO: types
10
11
  const element = (instance) => {
11
12
  switch (options.target) {
@@ -21,13 +22,14 @@ export function Listen(name, options = defaults) {
21
22
  };
22
23
  defineMethod(target, CONSTANTS.TOKEN_LIFECYCLE_CONNECTED, function (instance, callback, args) {
23
24
  var _a;
24
- (_a = element(instance)) === null || _a === void 0 ? void 0 : _a.addEventListener(name, target[propertyKey], options);
25
+ (_a = element(instance)) === null || _a === void 0 ? void 0 : _a.addEventListener(name, instance[propertyKey], options);
25
26
  return callback === null || callback === void 0 ? void 0 : callback(...args);
26
27
  });
27
28
  defineMethod(target, CONSTANTS.TOKEN_LIFECYCLE_DISCONNECTED, function (instance, callback, args) {
28
29
  var _a;
29
- (_a = element(instance)) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, target[propertyKey], options);
30
+ (_a = element(instance)) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, instance[propertyKey], options);
30
31
  return callback === null || callback === void 0 ? void 0 : callback(...args);
31
32
  });
33
+ return Bind()(target, propertyKey, descriptor);
32
34
  };
33
35
  }
@@ -1 +1 @@
1
- export declare function Method(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
1
+ export declare function Method(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -1,2 +1,2 @@
1
1
  import { PropertyOptions } from '../../types/index.js';
2
- export declare function Property(options?: PropertyOptions): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
2
+ export declare function Property(options?: PropertyOptions): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -1 +1 @@
1
- export declare function State(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
1
+ export declare function State(): (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => import("../utils/decorator.js").DecoratorSetupReturn | undefined;
@@ -2,4 +2,4 @@ export declare type DecoratorSetup = (target: Object, propertyKey: PropertyKey,
2
2
  export declare type DecoratorSetupReturn = PropertyDescriptor & {
3
3
  onReady?(): void;
4
4
  };
5
- export declare const decorator: (setup: DecoratorSetup) => (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => void;
5
+ export declare const decorator: (setup: DecoratorSetup) => (target: Object, propertyKey: PropertyKey, descriptor?: PropertyDescriptor | undefined) => DecoratorSetupReturn | undefined;
@@ -3,10 +3,12 @@ export const decorator = (setup) => {
3
3
  return function (target, propertyKey, descriptor) {
4
4
  var _a;
5
5
  const options = setup(target, propertyKey, descriptor);
6
- if (Object.keys(options).some((key) => ['configurable', 'enumerable', 'value', 'writable', 'get', 'set'].includes(key)))
7
- defineProperty(target, propertyKey, options);
8
6
  // TODO
9
7
  if (options.onReady)
10
8
  ((_a = target['setup']) !== null && _a !== void 0 ? _a : (target['setup'] = [])).push(options.onReady);
9
+ if (descriptor)
10
+ return options;
11
+ if (Object.keys(options).some((key) => ['configurable', 'enumerable', 'value', 'writable', 'get', 'set'].includes(key)))
12
+ defineProperty(target, propertyKey, options);
11
13
  };
12
14
  };
@@ -2,6 +2,6 @@
2
2
  export const defineMethod = (target, propertyKey, handler) => {
3
3
  const callback = target[propertyKey];
4
4
  target[propertyKey] = function (...args) {
5
- handler(this, callback, args);
5
+ return handler(this, callback === null || callback === void 0 ? void 0 : callback.bind(this), args);
6
6
  };
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlplus/element",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Masood Abdolian <m.abdolian@gmail.com>",
6
6
  "description": "Compiler of HTMLPlus",