structured-fw 0.9.3 → 0.9.5
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 +1 -0
- package/build/system/EventEmitter.d.ts +1 -1
- package/build/system/EventEmitter.js +1 -1
- package/build/system/Types.d.ts +7 -1
- package/build/system/client/ClientComponent.d.ts +4 -2
- package/build/system/client/ClientComponent.js +41 -8
- package/build/system/client/DataStore.d.ts +2 -2
- package/build/system/client/DataStoreView.d.ts +2 -2
- package/build/system/server/dom/DOMNode.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -644,6 +644,7 @@ Methods:
|
|
|
644
644
|
- `find(componentName: string, recursive: boolean = true): ClientComponent | null` - find a child component
|
|
645
645
|
- `findParent(componentName: string): ClientComponent | null` - find the first parent with given name
|
|
646
646
|
- `query(componentName: string, recursive: boolean = true): Array<ClientComponent>` - return all components with given name found within this component, if `recursive = false`, only direct children are considered
|
|
647
|
+
- `bind<T extends LooseObject | undefined = undefined>(element: HTMLElement, eventName: string | Array<string>, callback: (e: Event, data: T) => void): void` - adds event listener(s) to given element. This is preferred over addEventListener because when the component is redrawn/removed, the event listeners added using bind method are automatically restored/removed. Callback receives event as the first argument. Any "data-" prefixed attributes found on `element` are parsed into an object and provided as second argument to callback (you can specify data using attr helper if you want to pass in something other than a string). The method is generic, allowing you to specify expected data type
|
|
647
648
|
- `ref<T>(refName: string): T` - get a HTMLElement or ClientComponent that has attribute `ref="[refName]"`
|
|
648
649
|
- `arrayRef<T>(refName: string): Array<T>` - get an array of HTMLElement or ClientComponent that have attribute `array:ref="[refName]"`
|
|
649
650
|
- `add(appendTo: HTMLElement, componentName: string, data?: LooseObject): Promise<ClientComponent | null>` - add `componentName` component to `appendTo` element, optionally passing `data` to the component when it's being rendered. Returns a promise that resolves with added ClientComponent or null if something went wrong
|
|
@@ -3,5 +3,5 @@ export declare class EventEmitter<T extends Record<string, any> = Record<string,
|
|
|
3
3
|
protected listeners: Partial<Record<keyof T, Array<EventEmitterCallback<any>>>>;
|
|
4
4
|
on<K extends keyof T>(eventName: K, callback: EventEmitterCallback<T[K]>): void;
|
|
5
5
|
emit(eventName: keyof T, payload?: any): void;
|
|
6
|
-
|
|
6
|
+
off(eventName: keyof T, callback: EventEmitterCallback<any>): void;
|
|
7
7
|
}
|
package/build/system/Types.d.ts
CHANGED
|
@@ -159,7 +159,13 @@ export type InitializerFunctionContext = {
|
|
|
159
159
|
isRedraw: boolean;
|
|
160
160
|
};
|
|
161
161
|
export type StoreChangeCallback = (key: string, value: any, oldValue: any, componentId: string) => void;
|
|
162
|
-
export type
|
|
162
|
+
export type ClientComponentEventCallback<T> = T extends undefined ? (e: Event) => void : (e: Event, data: T) => void;
|
|
163
|
+
export type ClientComponentBoundEvent<T extends LooseObject | undefined = undefined> = {
|
|
164
|
+
element: HTMLElement;
|
|
165
|
+
event: keyof HTMLElementEventMap;
|
|
166
|
+
callback: (e: Event) => void;
|
|
167
|
+
callbackOriginal: ClientComponentEventCallback<T>;
|
|
168
|
+
};
|
|
163
169
|
export type ClientComponentTransition = {
|
|
164
170
|
fade: false | number;
|
|
165
171
|
slide: false | number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LooseObject } from '../Types.js';
|
|
1
|
+
import { ClientComponentEventCallback, LooseObject } from '../Types.js';
|
|
2
2
|
import { DataStoreView } from './DataStoreView.js';
|
|
3
3
|
import { DataStore } from './DataStore.js';
|
|
4
4
|
import { Net } from './Net.js';
|
|
@@ -29,6 +29,7 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
29
29
|
private init;
|
|
30
30
|
private runInitializer;
|
|
31
31
|
private initData;
|
|
32
|
+
private attributeData;
|
|
32
33
|
pathData(): Array<{
|
|
33
34
|
[key: string]: string;
|
|
34
35
|
}>;
|
|
@@ -55,6 +56,7 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
55
56
|
private transitionAttributes;
|
|
56
57
|
private transitionAxis;
|
|
57
58
|
private destroy;
|
|
58
|
-
bind(element: HTMLElement, event:
|
|
59
|
+
bind<T extends LooseObject | undefined = undefined>(element: HTMLElement, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: ClientComponentEventCallback<T>): void;
|
|
60
|
+
unbind<T extends LooseObject | undefined = undefined>(element: HTMLElement, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: ClientComponentEventCallback<T>): void;
|
|
59
61
|
private unbindAll;
|
|
60
62
|
}
|
|
@@ -90,19 +90,26 @@ export class ClientComponent extends EventEmitter {
|
|
|
90
90
|
this.initializerExecuted = true;
|
|
91
91
|
}
|
|
92
92
|
initData() {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
objectEach(this.attributeData(this.domNode), (key, val) => {
|
|
94
|
+
this.setData(key, val, false);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
attributeData(node) {
|
|
98
|
+
const data = {};
|
|
99
|
+
for (let i = 0; i < node.attributes.length; i++) {
|
|
100
|
+
if (/^((number|string|boolean|object|any):)?data-[^\s]+/.test(node.attributes[i].name)) {
|
|
101
|
+
const value = node.attributes[i].value;
|
|
96
102
|
const attrData = attributeValueFromString(value);
|
|
97
103
|
if (typeof attrData === 'object') {
|
|
98
|
-
|
|
104
|
+
data[attrData.key] = attrData.value;
|
|
99
105
|
}
|
|
100
106
|
else {
|
|
101
|
-
const key = toCamelCase(
|
|
102
|
-
|
|
107
|
+
const key = toCamelCase(node.attributes[i].name.substring(5));
|
|
108
|
+
data[key] = attrData;
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
}
|
|
112
|
+
return data;
|
|
106
113
|
}
|
|
107
114
|
pathData() {
|
|
108
115
|
let current = this;
|
|
@@ -714,13 +721,39 @@ export class ClientComponent extends EventEmitter {
|
|
|
714
721
|
this.emit('afterDestroy');
|
|
715
722
|
}
|
|
716
723
|
bind(element, event, callback) {
|
|
724
|
+
if (Array.isArray(event)) {
|
|
725
|
+
event.forEach((eventName) => {
|
|
726
|
+
this.bind(element, eventName, callback);
|
|
727
|
+
});
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
717
730
|
if (element instanceof HTMLElement) {
|
|
731
|
+
const callbackWrapper = (e) => {
|
|
732
|
+
callback.apply(this, [e, this.attributeData(element)]);
|
|
733
|
+
};
|
|
718
734
|
this.bound.push({
|
|
719
735
|
element,
|
|
720
736
|
event,
|
|
721
|
-
callback
|
|
737
|
+
callback: callbackWrapper,
|
|
738
|
+
callbackOriginal: callback
|
|
722
739
|
});
|
|
723
|
-
element.addEventListener(event,
|
|
740
|
+
element.addEventListener(event, callbackWrapper);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
unbind(element, event, callback) {
|
|
744
|
+
if (Array.isArray(event)) {
|
|
745
|
+
event.forEach((eventName) => {
|
|
746
|
+
this.unbind(element, eventName, callback);
|
|
747
|
+
});
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
const boundIndex = this.bound.findIndex((bound) => {
|
|
751
|
+
return bound.event === event && bound.element === element && bound.callbackOriginal === callback;
|
|
752
|
+
});
|
|
753
|
+
if (boundIndex > -1) {
|
|
754
|
+
const bound = this.bound[boundIndex];
|
|
755
|
+
bound.element.removeEventListener(bound.event, bound.callback);
|
|
756
|
+
this.bound.splice(boundIndex, 1);
|
|
724
757
|
}
|
|
725
758
|
}
|
|
726
759
|
unbindAll() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StoreChangeCallback } from '../Types.js';
|
|
2
2
|
import { ClientComponent } from './ClientComponent.js';
|
|
3
3
|
export declare class DataStore {
|
|
4
4
|
protected data: {
|
|
@@ -16,7 +16,7 @@ export declare class DataStore {
|
|
|
16
16
|
hasKey(componentId: string, key: string): boolean;
|
|
17
17
|
clear(componentId: string): void;
|
|
18
18
|
destroy(componentId: string): void;
|
|
19
|
-
onChange(componentId: string, key: string
|
|
19
|
+
onChange(componentId: string, key: string, callback: StoreChangeCallback): DataStore;
|
|
20
20
|
onChangeCallbacks(componentId: string): Record<string, Array<StoreChangeCallback>>;
|
|
21
21
|
private unbindAll;
|
|
22
22
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StoreChangeCallback } from '../Types.js';
|
|
2
2
|
import { ClientComponent } from './ClientComponent.js';
|
|
3
3
|
import { DataStore } from './DataStore.js';
|
|
4
4
|
export declare class DataStoreView {
|
|
@@ -14,6 +14,6 @@ export declare class DataStoreView {
|
|
|
14
14
|
clear(): void;
|
|
15
15
|
destroy(): void;
|
|
16
16
|
private componentId;
|
|
17
|
-
onChange(key: string
|
|
17
|
+
onChange(key: string, callback: StoreChangeCallback): DataStoreView;
|
|
18
18
|
onChangeCallbacks(): Record<string, Array<StoreChangeCallback>>;
|
|
19
19
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HTMLParser } from "./HTMLParser.js";
|
|
2
|
-
export const selfClosingTags = ['br', 'hr', 'input', 'img', 'link', 'meta', 'source', 'embed', 'path', 'area'];
|
|
3
|
-
export const recognizedHTMLTags = ['body', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'b', 'i', 'a', 'em', 'strong', 'br', 'hr', 'abbr', 'bdi', 'bdo', 'blockquote', 'cite', 'code', 'del', 'dfn', 'ins', 'kbd', 'mark', 'pre', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'small', 'span', 'sub', 'sup', 'time', 'u', 'var', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'img', 'area', 'map', 'object', 'param', 'table', 'tr', 'td', 'th', 'caption', 'colgroup', 'col', 'form', 'input', 'label', 'select', 'option', 'textarea', 'button', 'fieldset', 'datalist', 'iframe', 'audio', 'video', 'source', 'track', 'script', 'noscript', 'div', 'nav', 'aside', 'canvas', 'embed', 'template'];
|
|
2
|
+
export const selfClosingTags = ['br', 'wbr', 'hr', 'input', 'img', 'link', 'meta', 'source', 'embed', 'path', 'area'];
|
|
3
|
+
export const recognizedHTMLTags = ['body', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'b', 'i', 'a', 'em', 'strong', 'br', 'wbr', 'hr', 'abbr', 'bdi', 'bdo', 'blockquote', 'cite', 'code', 'del', 'dfn', 'ins', 'kbd', 'mark', 'pre', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'small', 'span', 'sub', 'sup', 'time', 'u', 'var', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'img', 'area', 'map', 'object', 'param', 'table', 'tr', 'td', 'th', 'caption', 'colgroup', 'col', 'form', 'input', 'label', 'select', 'option', 'textarea', 'button', 'fieldset', 'datalist', 'iframe', 'audio', 'video', 'source', 'track', 'script', 'noscript', 'div', 'nav', 'aside', 'canvas', 'embed', 'template'];
|
|
4
4
|
export class DOMNode {
|
|
5
5
|
constructor(root, parentNode, tagName) {
|
|
6
6
|
this.parentNode = null;
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"type": "module",
|
|
16
16
|
"main": "build/index",
|
|
17
|
-
"version": "0.9.
|
|
17
|
+
"version": "0.9.5",
|
|
18
18
|
"scripts": {
|
|
19
19
|
"develop": "tsc --watch",
|
|
20
20
|
"startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
|