structured-fw 0.9.2 → 0.9.4
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 +5 -1
- package/build/system/Util.js +3 -2
- package/build/system/client/ClientComponent.d.ts +2 -1
- package/build/system/client/ClientComponent.js +22 -0
- package/build/system/client/DataStore.d.ts +2 -2
- package/build/system/client/DataStoreView.d.ts +2 -2
- package/build/system/server/Component.js +4 -5
- 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(element: HTMLElement, eventName: string | Array<string>, callback: (e: Event) => 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 removed
|
|
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,11 @@ 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 ClientComponentBoundEvent = {
|
|
163
|
+
element: HTMLElement;
|
|
164
|
+
event: keyof HTMLElementEventMap;
|
|
165
|
+
callback: (e: Event) => void;
|
|
166
|
+
};
|
|
163
167
|
export type ClientComponentTransition = {
|
|
164
168
|
fade: false | number;
|
|
165
169
|
slide: false | number;
|
package/build/system/Util.js
CHANGED
|
@@ -215,8 +215,9 @@ function base64ToBytes(base64) {
|
|
|
215
215
|
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
216
216
|
}
|
|
217
217
|
function bytesToBase64(bytes) {
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
return btoa(bytes.reduce((prev, curr) => {
|
|
219
|
+
return prev + String.fromCharCode(curr);
|
|
220
|
+
}, ''));
|
|
220
221
|
}
|
|
221
222
|
export function attributeValueToString(key, value) {
|
|
222
223
|
return 'base64:' + bytesToBase64(new TextEncoder().encode(JSON.stringify({ key, value })));
|
|
@@ -55,6 +55,7 @@ export declare class ClientComponent extends EventEmitter {
|
|
|
55
55
|
private transitionAttributes;
|
|
56
56
|
private transitionAxis;
|
|
57
57
|
private destroy;
|
|
58
|
-
bind(element: HTMLElement, event:
|
|
58
|
+
bind(element: HTMLElement, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: (e: Event) => void): void;
|
|
59
|
+
unbind(element: HTMLElement, event: keyof HTMLElementEventMap | Array<keyof HTMLElementEventMap>, callback: (e: Event) => void): void;
|
|
59
60
|
private unbindAll;
|
|
60
61
|
}
|
|
@@ -714,6 +714,12 @@ export class ClientComponent extends EventEmitter {
|
|
|
714
714
|
this.emit('afterDestroy');
|
|
715
715
|
}
|
|
716
716
|
bind(element, event, callback) {
|
|
717
|
+
if (Array.isArray(event)) {
|
|
718
|
+
event.forEach((eventName) => {
|
|
719
|
+
this.bind(element, eventName, callback);
|
|
720
|
+
});
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
717
723
|
if (element instanceof HTMLElement) {
|
|
718
724
|
this.bound.push({
|
|
719
725
|
element,
|
|
@@ -723,6 +729,22 @@ export class ClientComponent extends EventEmitter {
|
|
|
723
729
|
element.addEventListener(event, callback);
|
|
724
730
|
}
|
|
725
731
|
}
|
|
732
|
+
unbind(element, event, callback) {
|
|
733
|
+
if (Array.isArray(event)) {
|
|
734
|
+
event.forEach((eventName) => {
|
|
735
|
+
this.unbind(element, eventName, callback);
|
|
736
|
+
});
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
const boundIndex = this.bound.findIndex((bound) => {
|
|
740
|
+
return bound.event === event && bound.element === element && callback === callback;
|
|
741
|
+
});
|
|
742
|
+
if (boundIndex > -1) {
|
|
743
|
+
const bound = this.bound[boundIndex];
|
|
744
|
+
bound.element.removeEventListener(bound.event, bound.callback);
|
|
745
|
+
this.bound.splice(boundIndex, 1);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
726
748
|
unbindAll() {
|
|
727
749
|
this.bound.forEach((bound) => {
|
|
728
750
|
bound.element.removeEventListener(bound.event, bound.callback);
|
|
@@ -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
|
}
|
|
@@ -88,19 +88,18 @@ export class Component extends EventEmitter {
|
|
|
88
88
|
this.setAttributes({ deferred: true }, 'data-', true);
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
this.attributes = Object.assign(this.importedParentData(this.parent.data) || {}, this.attributes);
|
|
93
|
-
}
|
|
91
|
+
const importedParentData = this.parent ? this.importedParentData(this.parent.data) : {};
|
|
94
92
|
if (data === undefined) {
|
|
95
93
|
if (this.entry && this.entry.module) {
|
|
96
|
-
this.data = Object.assign(this.data, await this.entry.module.getData(this.attributes, this.document.ctx, this.document.application, this) || {});
|
|
94
|
+
this.data = Object.assign(this.data, await this.entry.module.getData(Object.assign(importedParentData, this.attributes), this.document.ctx, this.document.application, this) || {});
|
|
97
95
|
}
|
|
98
96
|
else {
|
|
97
|
+
this.attributes = Object.assign(importedParentData, this.attributes);
|
|
99
98
|
this.data = Object.assign(exportedContextData, this.attributes);
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
101
|
else {
|
|
103
|
-
this.data = Object.assign(exportedContextData, data, this.attributes);
|
|
102
|
+
this.data = Object.assign(exportedContextData, Object.assign(importedParentData, data), this.attributes);
|
|
104
103
|
}
|
|
105
104
|
this.fillData(this.data);
|
|
106
105
|
if (this.entry === null || this.entry.exportData) {
|
|
@@ -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.4",
|
|
18
18
|
"scripts": {
|
|
19
19
|
"develop": "tsc --watch",
|
|
20
20
|
"startDev": "cd build && nodemon --watch '../app/**/*' --watch '../build/**/*' -e js,html,css index.js",
|