Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

alit-element

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

alit-element - npm Package Compare versions

Comparing version 0.1.1 to 0.2.0

dist/alit-element-decorators.d.ts

26

dist/alit-element.d.ts

@@ -5,6 +5,21 @@ import 'reflect-metadata';

export { TemplateResult } from 'lit-html/lit-html.js';
export interface EventListenerDeclaration {
eventName: string;
target: string | EventTarget;
handler: (event?: Event) => void;
}
export interface ChangeRecord {
path: string;
value: any;
oldValue: any;
}
export declare type ObserveHandler = (changeRecords: ChangeRecord[]) => void;
export declare class AlitElement extends LitElement {
static readonly __listeners: EventListenerDeclaration[];
static readonly __observers: {
[name: string]: ObserveHandler[];
};
private _$;
/**
* Get element with specified if in the element's shadow root
* Get element with specified ID in the element's shadow root
* @param id Id of element

@@ -22,3 +37,3 @@ */

*/
$$All(selector: string): any;
$$All(selector: string): NodeList;
/**

@@ -37,7 +52,4 @@ * Fires a custom event with the specified name

readonly node: HTMLElement;
connectedCallback(): void;
_propertiesChanged(currentProps: object, changedProps: object, oldProps: object): void;
}
/***********************************
* Functions to support decorators
***********************************/
export declare function element(name: string): (c: any) => void;
export declare function property(): (prototype: any, propertyName: string) => void;

@@ -10,4 +10,6 @@ import 'reflect-metadata';

}
static get __listeners() { return []; }
static get __observers() { return {}; }
/**
* Get element with specified if in the element's shadow root
* Get element with specified ID in the element's shadow root
* @param id Id of element

@@ -64,29 +66,47 @@ */

}
}
/***********************************
* Functions to support decorators
***********************************/
export function element(name) {
return (c) => {
if (name) {
window.customElements.define(name, c);
connectedCallback() {
super.connectedCallback();
const listeners = this.constructor.__listeners;
for (const listener of listeners) {
if (listener.eventName && listener.handler) {
const target = (typeof listener.target === 'string') ? this.$$(listener.target) : listener.target;
if (target && target.addEventListener) {
target.addEventListener(listener.eventName, (e) => {
listener.handler.call(this, e);
});
}
}
}
};
}
export function property() {
return (prototype, propertyName) => {
const constructor = prototype.constructor;
if (!constructor.hasOwnProperty('properties')) {
Object.defineProperty(constructor, 'properties', { value: {} });
}
_propertiesChanged(currentProps, changedProps, oldProps) {
const observers = this.constructor.__observers;
const map = new Map();
for (const propName in changedProps) {
const handlers = observers[propName];
if (handlers && handlers.length) {
const changeRecord = {
path: propName,
value: changedProps[propName],
oldValue: oldProps[propName]
};
for (const handler of handlers) {
if (!map.has(handler)) {
map.set(handler, [changeRecord]);
}
else {
map.get(handler).push(changeRecord);
}
}
}
}
constructor.properties[propertyName] = { type: getType(prototype, propertyName) || String };
};
}
function getType(prototype, propertyName) {
if (Reflect.hasMetadata) {
if (Reflect.hasMetadata('design:type', prototype, propertyName)) {
return Reflect.getMetadata('design:type', prototype, propertyName);
for (const handler of map.keys()) {
try {
handler.call(this, map.get(handler));
}
catch (err) {
console.warn(err);
}
}
super._propertiesChanged(currentProps, changedProps, oldProps);
}
return null;
}

@@ -1,2 +0,2 @@

import { AlitElement, TemplateResult } from '../alit-element';
import { AlitElement, TemplateResult, ChangeRecord } from '../alit-element';
export declare class AlitCard extends AlitElement {

@@ -8,3 +8,9 @@ name?: string;

description: string;
card?: HTMLDivElement;
toggleBorder(): void;
randomizeAge(): void;
ageChanged(records: ChangeRecord[]): void;
documentClick(): void;
private borderShowing;
_render(): TemplateResult;
}

@@ -10,3 +10,4 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {

};
import { AlitElement, html, element, property } from '../alit-element';
import { AlitElement, html } from '../alit-element';
import { element, property, query, listen, observe } from '../alit-element-decorators';
let AlitCard = class AlitCard extends AlitElement {

@@ -17,5 +18,21 @@ constructor() {

this.description = 'This is the default description';
this.borderShowing = false;
}
toggleBorder() {
this.borderShowing = !this.borderShowing;
this.card.style.border = this.borderShowing ? '2px solid' : 'none';
}
randomizeAge() {
this.age = Math.round(Math.random() * 60 + 20);
this.description = `This guy is aged ${this.age}`;
}
ageChanged(records) {
for (const r of records) {
console.log(`${r.path} changed from '${r.oldValue}' to '${r.value}'`);
}
}
documentClick() {
console.log('document clicked');
}
_render() {
console.log(this.constructor.properties);
return html `

@@ -32,3 +49,2 @@ <style>

display: inline-block;
box-shadow: 0px 0px 11px 0px rgba(0, 0, 0, 0.3);
}

@@ -56,2 +72,6 @@

<p>${this.description}</p>
<p>
<button id="toggleButton">Toggle border</button>
<button id="randomizeButton">Randomize age</button>
</p>
</div>

@@ -81,2 +101,30 @@ `;

], AlitCard.prototype, "description", void 0);
__decorate([
query('.card'),
__metadata("design:type", HTMLDivElement)
], AlitCard.prototype, "card", void 0);
__decorate([
listen('click', '#toggleButton'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], AlitCard.prototype, "toggleBorder", null);
__decorate([
listen('click', '#randomizeButton'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], AlitCard.prototype, "randomizeAge", null);
__decorate([
observe('age', 'description'),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", void 0)
], AlitCard.prototype, "ageChanged", null);
__decorate([
listen('click', document),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], AlitCard.prototype, "documentClick", null);
AlitCard = __decorate([

@@ -86,4 +134,1 @@ element('alit-card')

export { AlitCard };
// export function as<T extends GuildElement>(node: HTMLElement): T {
// return (node as any) as T;
// }
{
"name": "alit-element",
"version": "0.1.1",
"version": "0.2.0",
"description": "A simple wrapper for lit-element with some enhanced functions",

@@ -5,0 +5,0 @@ "main": "dist/alit-element.js",

@@ -1,2 +0,146 @@

# alit-element
A simple extension for lit-element
# AlitElement
A simple base class that extends [lit-element](https://github.com/Polymer/lit-element) with some utility functions.
It also defines decorators, similar to [polymer-decorators](https://github.com/Polymer/polymer-decorators#observetargets-string), which makes development of web components in typescript super easy.
## Sample Code
Here's some sample code that showcases decorators. ([full code](https://github.com/pshihn/alit-element/blob/master/src/example/card.ts))
```javascript
@element('alit-card')
export class AlitCard extends AlitElement {
@property() name?: string;
@property() age: number = 30;
@property() image?: string;
@property() description: string = 'This is the default description';
@query('.card')
card?: HTMLDivElement;
@listen('click', '#toggleButton')
toggleBorder() {
this.borderShowing = !this.borderShowing;
this.card!.style.border = this.borderShowing ? '2px solid' : 'none';
}
@observe('age', 'description')
ageChanged(records: ChangeRecord[]) {
for (const r of records) {
console.log(`${r.path} changed from '${r.oldValue}' to '${r.value}'`);
}
}
_render(): TemplateResult {
return html`
...
...
<div class="card">
...
</div>
...
`;
}
```
## Methods
#### $(id: string): HTMLElement
Get element with specified ID in the element's shadow root.
```javascript
const button = this.$('toggleButton');
```
#### $$(selector: string): HTMLElement
Find first element macthing the slector in the element's shadow root.
```javascript
const card = this.$$('.card');
```
#### $$All(selector: string): NodeList
Find all elements matching the selector in the element's shadow root.
```javascript
const allCards = this.$$All('.card');
```
#### fireEvent(name: string, detail?: any, bubbles: boolean = true, composed: boolean = true)
Utility method to fire custom events
```javascript
this.fireEvent('selected');
this.fireEvent('selected', {selection: this.currentSelection});
```
## Decorators
#### @element(tagname?: string)
Defines a custom element with the associated class
```javascript
@element('hello-world')
export class HelloWorld extends AlitElement {
_render() {
return html`
<div>Hello World</div>
`;
}
}
```
#### @property()
Declared a property to be used by LitElement.
The type is infered using reflected metadata.
```javascript
@element('hello-world')
export class HelloWorld extends AlitElement {
@property() name?: string;
@property() job?: string;
@property() age: number = 30;
}
```
#### @query(selector: string)
Replace this property with a getter that returns the element matching the specified selector.
```javascript
@query('.card')
card?: HTMLDivElement;
```
#### @queryAll(selector: string)
Replace this property with a getter that returns the NodeList of all elements matching the specified selector.
```javascript
@queryAll('my-widget')
widgets: NodeListOf<MyWidgetElement>;
```
#### @listen(eventName: string, target: string | EventTarget)
Add an event listener for `eventName` on `target`.
`target` can be an object reference, or the selector string to find the element in the shadow root.
```javascript
@listen('click', '#toggleButton')
toggleBorder() {
this.borderShowing = !this.borderShowing;
}
```
```javascript
@listen('click', document)
documentClick() {
console.log('document clicked');
}
```
#### observe(...properties: string[])
Add observers to the specified set of properties. This does not support children of properties or wildcards.
```javascript
@observe('age', 'description')
ageChanged(records: ChangeRecord[]) {
// do stuff when age or description changes
}
```
A `ChangeRecord` is defined as follows:
```javascript
interface ChangeRecord {
path: string; // property name
value: any;
oldValue: any;
}
```

@@ -6,7 +6,23 @@ import 'reflect-metadata';

export interface EventListenerDeclaration {
eventName: string;
target: string | EventTarget;
handler: (event?: Event) => void;
}
export interface ChangeRecord {
path: string;
value: any;
oldValue: any;
}
export type ObserveHandler = (changeRecords: ChangeRecord[]) => void;
export class AlitElement extends LitElement {
static get __listeners(): EventListenerDeclaration[] { return []; }
static get __observers(): { [name: string]: ObserveHandler[] } { return {}; }
private _$: { [id: string]: HTMLElement } = {};
/**
* Get element with specified if in the element's shadow root
* Get element with specified ID in the element's shadow root
* @param id Id of element

@@ -36,3 +52,3 @@ */

*/
$$All(selector: string) {
$$All(selector: string): NodeList {
return this.shadowRoot.querySelectorAll(selector);

@@ -68,33 +84,47 @@ }

}
}
/***********************************
* Functions to support decorators
***********************************/
export function element(name: string) {
return (c: any) => {
if (name) {
window.customElements.define(name, c);
connectedCallback() {
super.connectedCallback();
const listeners = (<typeof AlitElement>this.constructor).__listeners;
for (const listener of listeners) {
if (listener.eventName && listener.handler) {
const target = (typeof listener.target === 'string') ? this.$$(listener.target) : listener.target;
if (target && target.addEventListener) {
target.addEventListener(listener.eventName, (e) => {
listener.handler.call(this, e);
});
}
}
}
};
}
}
export function property() {
return (prototype: any, propertyName: string) => {
const constructor = prototype.constructor;
if (!constructor.hasOwnProperty('properties')) {
Object.defineProperty(constructor, 'properties', { value: {} });
_propertiesChanged(currentProps: object, changedProps: object, oldProps: object): void {
const observers = (<typeof AlitElement>this.constructor).__observers;
const map = new Map<ObserveHandler, ChangeRecord[]>();
for (const propName in changedProps) {
const handlers = observers[propName];
if (handlers && handlers.length) {
const changeRecord: ChangeRecord = {
path: propName,
value: changedProps[propName],
oldValue: oldProps[propName]
};
for (const handler of handlers) {
if (!map.has(handler)) {
map.set(handler, [changeRecord]);
} else {
map.get(handler)!.push(changeRecord);
}
}
}
}
constructor.properties[propertyName] = { type: getType(prototype, propertyName) || String };
};
}
function getType(prototype: any, propertyName: string): any {
if (Reflect.hasMetadata) {
if (Reflect.hasMetadata('design:type', prototype, propertyName)) {
return Reflect.getMetadata('design:type', prototype, propertyName);
for (const handler of map.keys()) {
try {
handler.call(this, map.get(handler));
} catch (err) {
console.warn(err);
}
}
super._propertiesChanged(currentProps, changedProps, oldProps);
}
return null;
}

@@ -1,2 +0,3 @@

import { AlitElement, html, TemplateResult, element, property } from '../alit-element';
import { AlitElement, html, TemplateResult, ChangeRecord } from '../alit-element';
import { element, property, query, listen, observe } from '../alit-element-decorators';

@@ -11,5 +12,32 @@ @element('alit-card')

@query('.card')
card?: HTMLDivElement;
@listen('click', '#toggleButton')
toggleBorder() {
this.borderShowing = !this.borderShowing;
this.card!.style.border = this.borderShowing ? '2px solid' : 'none';
}
@listen('click', '#randomizeButton')
randomizeAge() {
this.age = Math.round(Math.random() * 60 + 20);
this.description = `This guy is aged ${this.age}`;
}
@observe('age', 'description')
ageChanged(records: ChangeRecord[]) {
for (const r of records) {
console.log(`${r.path} changed from '${r.oldValue}' to '${r.value}'`);
}
}
@listen('click', document)
documentClick() {
console.log('document clicked');
}
private borderShowing = false;
_render(): TemplateResult {
console.log((this.constructor as any).properties);
return html`

@@ -26,3 +54,2 @@ <style>

display: inline-block;
box-shadow: 0px 0px 11px 0px rgba(0, 0, 0, 0.3);
}

@@ -50,9 +77,9 @@

<p>${this.description}</p>
<p>
<button id="toggleButton">Toggle border</button>
<button id="randomizeButton">Randomize age</button>
</p>
</div>
`;
}
}
// export function as<T extends GuildElement>(node: HTMLElement): T {
// return (node as any) as T;
// }
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc