@dooboostore/simple-web-component 1.0.19 → 1.0.21
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 +2028 -146
- package/dist/cjs/decorators/addEventListener.js +4 -4
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/appendChild.js +4 -4
- package/dist/cjs/decorators/appendChild.js.map +2 -2
- package/dist/cjs/decorators/attribute.js +141 -0
- package/dist/cjs/decorators/attribute.js.map +7 -0
- package/dist/cjs/decorators/changedAttribute.js +5 -5
- package/dist/cjs/decorators/changedAttribute.js.map +2 -2
- package/dist/cjs/decorators/classList.js +4 -4
- package/dist/cjs/decorators/classList.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +36 -9
- package/dist/cjs/decorators/elementDefine.js.map +3 -3
- package/dist/cjs/decorators/emitCustomEvent.js +4 -4
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/index.js +1 -0
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +4 -4
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/onConnectedInnerHtml.js +4 -4
- package/dist/cjs/decorators/onConnectedInnerHtml.js.map +2 -2
- package/dist/cjs/decorators/query.js +4 -4
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +4 -4
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/decorators/replaceChildren.js +5 -5
- package/dist/cjs/decorators/replaceChildren.js.map +2 -2
- package/dist/cjs/decorators/setAttribute.js +46 -20
- package/dist/cjs/decorators/setAttribute.js.map +2 -2
- package/dist/cjs/decorators/style.js +4 -4
- package/dist/cjs/decorators/style.js.map +2 -2
- package/dist/cjs/elements/SwcAppEngine.js +8 -8
- package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
- package/dist/cjs/elements/SwcAppMixin.js +28 -1
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/elements/SwcAsync.js +4 -4
- package/dist/cjs/elements/SwcAsync.js.map +2 -2
- package/dist/cjs/elements/SwcChoose.js +4 -4
- package/dist/cjs/elements/SwcChoose.js.map +2 -2
- package/dist/cjs/elements/SwcIf.js +4 -4
- package/dist/cjs/elements/SwcIf.js.map +2 -2
- package/dist/cjs/elements/SwcLoop.js +4 -4
- package/dist/cjs/elements/SwcLoop.js.map +2 -2
- package/dist/cjs/elements/register.js +13 -13
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/router/ElementRouter.js +7 -7
- package/dist/cjs/router/ElementRouter.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/esm/decorators/addEventListener.js +1 -1
- package/dist/esm/decorators/addEventListener.js.map +1 -1
- package/dist/esm/decorators/appendChild.js +1 -1
- package/dist/esm/decorators/appendChild.js.map +1 -1
- package/dist/esm/decorators/attribute.js +122 -0
- package/dist/esm/decorators/attribute.js.map +7 -0
- package/dist/esm/decorators/changedAttribute.js +1 -1
- package/dist/esm/decorators/changedAttribute.js.map +1 -1
- package/dist/esm/decorators/classList.js +1 -1
- package/dist/esm/decorators/classList.js.map +1 -1
- package/dist/esm/decorators/elementDefine.js +31 -4
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +1 -1
- package/dist/esm/decorators/emitCustomEvent.js.map +1 -1
- package/dist/esm/decorators/index.js +1 -0
- package/dist/esm/decorators/index.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +1 -1
- package/dist/esm/decorators/lifecycles.js.map +1 -1
- package/dist/esm/decorators/onConnectedInnerHtml.js +1 -1
- package/dist/esm/decorators/onConnectedInnerHtml.js.map +1 -1
- package/dist/esm/decorators/query.js +1 -1
- package/dist/esm/decorators/query.js.map +1 -1
- package/dist/esm/decorators/queryAll.js +1 -1
- package/dist/esm/decorators/queryAll.js.map +1 -1
- package/dist/esm/decorators/replaceChildren.js +1 -1
- package/dist/esm/decorators/replaceChildren.js.map +1 -1
- package/dist/esm/decorators/setAttribute.js +42 -16
- package/dist/esm/decorators/setAttribute.js.map +2 -2
- package/dist/esm/decorators/style.js +1 -1
- package/dist/esm/decorators/style.js.map +1 -1
- package/dist/esm/elements/SwcAppEngine.js +4 -4
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +28 -1
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/elements/SwcAsync.js +1 -1
- package/dist/esm/elements/SwcAsync.js.map +1 -1
- package/dist/esm/elements/SwcChoose.js +1 -1
- package/dist/esm/elements/SwcChoose.js.map +1 -1
- package/dist/esm/elements/SwcIf.js +1 -1
- package/dist/esm/elements/SwcIf.js.map +1 -1
- package/dist/esm/elements/SwcLoop.js +1 -1
- package/dist/esm/elements/SwcLoop.js.map +1 -1
- package/dist/esm/elements/register.js +1 -1
- package/dist/esm/elements/register.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/router/ElementRouter.js +2 -2
- package/dist/esm/router/ElementRouter.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +5910 -3839
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/attribute.d.ts +23 -0
- package/dist/types/decorators/attribute.d.ts.map +1 -0
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +1 -0
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/setAttribute.d.ts +3 -0
- package/dist/types/decorators/setAttribute.d.ts.map +1 -1
- package/dist/types/elements/SwcAppEngine.d.ts +5 -4
- package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/router/ElementRouter.d.ts +1 -1
- package/dist/types/router/ElementRouter.d.ts.map +1 -1
- package/dist/types/types.d.ts +2 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +5910 -3839
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +10 -5
- package/src/decorators/addEventListener.ts +1 -1
- package/src/decorators/appendChild.ts +1 -1
- package/src/decorators/attribute.ts +158 -0
- package/src/decorators/changedAttribute.ts +1 -1
- package/src/decorators/classList.ts +1 -1
- package/src/decorators/elementDefine.ts +38 -5
- package/src/decorators/emitCustomEvent.ts +1 -1
- package/src/decorators/index.ts +1 -0
- package/src/decorators/lifecycles.ts +1 -1
- package/src/decorators/onConnectedInnerHtml.ts +1 -1
- package/src/decorators/query.ts +1 -1
- package/src/decorators/queryAll.ts +1 -1
- package/src/decorators/replaceChildren.ts +1 -1
- package/src/decorators/setAttribute.ts +49 -17
- package/src/decorators/style.ts +1 -1
- package/src/elements/SwcAppEngine.ts +9 -8
- package/src/elements/SwcAppMixin.ts +32 -1
- package/src/elements/SwcAsync.ts +1 -1
- package/src/elements/SwcChoose.ts +1 -1
- package/src/elements/SwcIf.ts +1 -1
- package/src/elements/SwcLoop.ts +1 -1
- package/src/elements/register.ts +1 -1
- package/src/index.ts +3 -2
- package/src/router/ElementRouter.ts +2 -2
- package/src/types.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dooboostore/simple-web-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -54,6 +54,11 @@
|
|
|
54
54
|
"import": "./dist/esm/index.js",
|
|
55
55
|
"require": "./dist/cjs/index.js"
|
|
56
56
|
},
|
|
57
|
+
"./bundle-entry": {
|
|
58
|
+
"types": "./dist/types/bundle-entry.d.ts",
|
|
59
|
+
"import": "./dist/esm/bundle-entry.js",
|
|
60
|
+
"require": "./dist/cjs/bundle-entry.js"
|
|
61
|
+
},
|
|
57
62
|
"./*": {
|
|
58
63
|
"types": "./dist/types/*.d.ts",
|
|
59
64
|
"import": "./dist/esm/*.js",
|
|
@@ -87,10 +92,10 @@
|
|
|
87
92
|
"webpack": "^5.93.0",
|
|
88
93
|
"webpack-cli": "^5.1.4",
|
|
89
94
|
"webpack-dev-server": "^5.2.0",
|
|
90
|
-
"@dooboostore/core": "1.0.
|
|
91
|
-
"@dooboostore/core-node": "1.0.
|
|
92
|
-
"@dooboostore/
|
|
93
|
-
"@dooboostore/
|
|
95
|
+
"@dooboostore/core": "1.0.30",
|
|
96
|
+
"@dooboostore/core-node": "1.0.12",
|
|
97
|
+
"@dooboostore/simple-boot": "1.0.54",
|
|
98
|
+
"@dooboostore/core-web": "1.0.10"
|
|
94
99
|
},
|
|
95
100
|
"scripts": {
|
|
96
101
|
"clean": "rm -rf dist",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { ensureInit, getElementConfig } from './elementDefine';
|
|
3
3
|
|
|
4
4
|
export type AppendChildPosition = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd';
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
+
import { ensureInit, getElementConfig } from './elementDefine';
|
|
3
|
+
import { SwcUtils } from '../utils/Utils';
|
|
4
|
+
import { SpecialSelector, SwcQueryOptions } from '../types';
|
|
5
|
+
|
|
6
|
+
export interface AttributeOptions extends SwcQueryOptions {
|
|
7
|
+
name?: string;
|
|
8
|
+
connectedInitialize?: boolean;
|
|
9
|
+
type?: typeof Number | typeof Boolean | typeof String;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface AttributeMetadata {
|
|
13
|
+
propertyKey: string | symbol;
|
|
14
|
+
selector: string;
|
|
15
|
+
options: AttributeOptions;
|
|
16
|
+
privateKey: symbol; // Added to bypass getter during initialization
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:attribute');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Helper to perform type conversion from string to target type
|
|
23
|
+
*/
|
|
24
|
+
const convertValue = (val: string | null, type: any): any => {
|
|
25
|
+
if (val === null || val === undefined) return val;
|
|
26
|
+
if (type === Number) return Number(val);
|
|
27
|
+
if (type === Boolean) return val === 'false' || val === '0' ? false : true;
|
|
28
|
+
return val;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Helper to resolve target elements based on selector and root options
|
|
33
|
+
*/
|
|
34
|
+
export const resolveTargetEls = (inst: any, selector: string, options: AttributeOptions, currentWin: any): HTMLElement[] => {
|
|
35
|
+
const r = options.root || 'auto';
|
|
36
|
+
const results: HTMLElement[] = [];
|
|
37
|
+
|
|
38
|
+
const applyRoot = (target: any) => {
|
|
39
|
+
if (!target) return;
|
|
40
|
+
if (r === 'auto') {
|
|
41
|
+
// Attributes belong to the ELEMENT, not the ShadowRoot.
|
|
42
|
+
// So for :host and direct attribute sync, we mostly want the element itself.
|
|
43
|
+
results.push(target);
|
|
44
|
+
} else {
|
|
45
|
+
if (r === 'light' || r === 'all') results.push(target);
|
|
46
|
+
if ((r === 'shadow' || r === 'all') && target.shadowRoot) results.push(target.shadowRoot);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (selector === ':host' || !selector) {
|
|
51
|
+
applyRoot(inst);
|
|
52
|
+
} else if (selector === ':window') {
|
|
53
|
+
results.push(currentWin);
|
|
54
|
+
} else if (selector === ':document') {
|
|
55
|
+
results.push(currentWin.document);
|
|
56
|
+
} else {
|
|
57
|
+
const hostSet = SwcUtils.getHostSet(inst);
|
|
58
|
+
if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
|
|
59
|
+
else if (selector === ':appHost') applyRoot(hostSet.$appHost as any);
|
|
60
|
+
else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
|
|
61
|
+
else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
|
|
62
|
+
else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost as any);
|
|
63
|
+
else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost as any);
|
|
64
|
+
else {
|
|
65
|
+
if (r === 'shadow') {
|
|
66
|
+
const found = inst.shadowRoot?.querySelectorAll(selector);
|
|
67
|
+
if (found) results.push(...found);
|
|
68
|
+
} else if (r === 'light') {
|
|
69
|
+
const found = inst.querySelectorAll(selector);
|
|
70
|
+
if (found) results.push(...found);
|
|
71
|
+
} else if (r === 'all') {
|
|
72
|
+
const sMatch = inst.shadowRoot?.querySelectorAll(selector);
|
|
73
|
+
const lMatch = inst.querySelectorAll(selector);
|
|
74
|
+
if (sMatch) results.push(...sMatch);
|
|
75
|
+
if (lMatch) results.push(...lMatch);
|
|
76
|
+
} else {
|
|
77
|
+
const found = (inst.shadowRoot || inst).querySelectorAll(selector);
|
|
78
|
+
if (found) results.push(...found);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return results;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @attribute decorator to sync a field value with an element's attribute.
|
|
87
|
+
*/
|
|
88
|
+
export function attribute(selector: string, options: AttributeOptions = {}): PropertyDecorator {
|
|
89
|
+
return (target: Object, propertyKey: string | symbol) => {
|
|
90
|
+
const constructor = target.constructor;
|
|
91
|
+
const privateKey = Symbol(String(propertyKey));
|
|
92
|
+
|
|
93
|
+
const designType = (Reflect as any).getMetadata('design:type', target, propertyKey);
|
|
94
|
+
|
|
95
|
+
let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_METADATA_KEY, constructor) as AttributeMetadata[];
|
|
96
|
+
if (!metaList) {
|
|
97
|
+
metaList = [];
|
|
98
|
+
ReflectUtils.defineMetadata(ATTRIBUTE_METADATA_KEY, metaList, constructor);
|
|
99
|
+
}
|
|
100
|
+
metaList.push({ propertyKey, selector, options, privateKey });
|
|
101
|
+
|
|
102
|
+
Object.defineProperty(target, propertyKey, {
|
|
103
|
+
get(this: any) {
|
|
104
|
+
const attrName = options.name || String(propertyKey);
|
|
105
|
+
const conf = getElementConfig(this);
|
|
106
|
+
const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
|
|
107
|
+
const targetType = options.type || designType;
|
|
108
|
+
|
|
109
|
+
console.log('type-->', propertyKey, targetType);
|
|
110
|
+
// During early init phase, if syncing memory to DOM, return memory.
|
|
111
|
+
if (this.__swc_syncing_init || (options.connectedInitialize && !this.__swc_connected)) {
|
|
112
|
+
return convertValue(this[privateKey], targetType);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const targets = resolveTargetEls(this, selector, options, currentWin);
|
|
116
|
+
const primaryTarget = targets[0];
|
|
117
|
+
|
|
118
|
+
if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {
|
|
119
|
+
if ((primaryTarget as any).hasAttribute(attrName)) {
|
|
120
|
+
const domVal = (primaryTarget as any).getAttribute(attrName);
|
|
121
|
+
return convertValue(domVal, targetType);
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return convertValue(this[privateKey], targetType);
|
|
127
|
+
},
|
|
128
|
+
set(this: any, nv: any) {
|
|
129
|
+
const targetType = options.type || designType;
|
|
130
|
+
// const convertedValue = convertValue(nv, targetType);
|
|
131
|
+
// console.log('---set', propertyKey, targetType, nv, convertedValue);
|
|
132
|
+
|
|
133
|
+
const attrName = options.name || String(propertyKey);
|
|
134
|
+
const conf = getElementConfig(this);
|
|
135
|
+
const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
|
|
136
|
+
const targets = resolveTargetEls(this, selector, options, currentWin);
|
|
137
|
+
targets.forEach(it => {
|
|
138
|
+
console.log('----->', it)
|
|
139
|
+
if (it && typeof (it as any).setAttribute === 'function') {
|
|
140
|
+
if (nv === null) {
|
|
141
|
+
(it as any).removeAttribute(attrName);
|
|
142
|
+
} else {
|
|
143
|
+
(it as any).setAttribute(attrName, String(nv));
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
this[privateKey] = nv;
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
},
|
|
150
|
+
enumerable: true,
|
|
151
|
+
configurable: true
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const findAllAttributeMetadata = (target: any): AttributeMetadata[] => {
|
|
157
|
+
return ReflectUtils.findAllMetadata<AttributeMetadata[]>(ATTRIBUTE_METADATA_KEY, target).flat();
|
|
158
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
2
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
3
3
|
import { getOnConnectedInnerHtmlMetadata } from './onConnectedInnerHtml';
|
|
4
4
|
import { getAddEventListenerMetadata } from './addEventListener';
|
|
5
5
|
import { ON_BEFORE_CONNECTED_METADATA_KEY, ON_AFTER_CONNECTED_METADATA_KEY, ON_BEFORE_DISCONNECTED_METADATA_KEY, ON_AFTER_DISCONNECTED_METADATA_KEY, ON_BEFORE_ADOPTED_METADATA_KEY, ON_AFTER_ADOPTED_METADATA_KEY, findAllLifecycleMetadata } from './lifecycles';
|
|
@@ -10,12 +10,13 @@ import { findAllReplaceChildrenMetadata } from './replaceChildren';
|
|
|
10
10
|
import { findAllAppendChildMetadata } from './appendChild';
|
|
11
11
|
import { findAllClassListMetadata } from './classList';
|
|
12
12
|
import { findAllStyleMetadata } from './style';
|
|
13
|
+
import { findAllAttributeMetadata } from './attribute';
|
|
13
14
|
import { SwcUtils } from '../utils/Utils';
|
|
14
15
|
import { HTML_TAG_ENTRIES, DOM_EVENT_NAMES } from '../config/config';
|
|
15
16
|
import { SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject';
|
|
16
17
|
import { InjectSituationType, HostSet } from '../types';
|
|
17
18
|
|
|
18
|
-
// --- Core Interfaces & Types
|
|
19
|
+
// --- Core Interfaces & Types ---
|
|
19
20
|
|
|
20
21
|
export const ELEMENT_CONFIG_KEY = Symbol('simple-web-component:element-config');
|
|
21
22
|
|
|
@@ -221,12 +222,13 @@ export const elementDefine =
|
|
|
221
222
|
const emitCustomEventList = getEmitCustomEventMetadataList(constructor) || [];
|
|
222
223
|
const addEventListenerList = getAddEventListenerMetadata(constructor) || [];
|
|
223
224
|
const attrChangeMap = findAllAttributeChangedMetadata(constructor);
|
|
225
|
+
const attributeList = findAllAttributeMetadata(constructor);
|
|
224
226
|
|
|
225
227
|
const swcLifecycleAttributes = ['swc-on-constructor', 'swc-on-connected', 'swc-on-disconnected', 'swc-on-before-connected', 'swc-on-after-connected', 'swc-on-before-disconnected', 'swc-on-after-disconnected', 'swc-on-before-adopted', 'swc-on-after-adopted', 'swc-on-attribute-changed'];
|
|
226
228
|
const swcOnEvents = DOM_EVENT_NAMES.map(e => `swc-on-${e}`);
|
|
227
229
|
|
|
228
230
|
// Collect all observed attributes from all decorators
|
|
229
|
-
const mergedObservedAttributes = [...new Set([...(metadata.observedAttributes ?? []), ...attrChangeMap.keys(), ...Array.from(findAllSetAttributeMetadata(constructor).values()).map(it => it.name), ...emitCustomEventList.map(it => it.options.attributeName!), ...swcLifecycleAttributes, ...swcOnEvents])];
|
|
231
|
+
const mergedObservedAttributes = [...new Set([...(metadata.observedAttributes ?? []), ...attrChangeMap.keys(), ...Array.from(findAllSetAttributeMetadata(constructor).values()).map(it => it.name), ...attributeList.map(it => it.options.name || String(it.propertyKey)), ...emitCustomEventList.map(it => it.options.attributeName!), ...swcLifecycleAttributes, ...swcOnEvents])];
|
|
230
232
|
|
|
231
233
|
const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
|
|
232
234
|
|
|
@@ -251,7 +253,33 @@ export const elementDefine =
|
|
|
251
253
|
for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
|
|
252
254
|
}
|
|
253
255
|
|
|
254
|
-
|
|
256
|
+
// Initialize @attribute fields (DOM <-> JS Sync)
|
|
257
|
+
attributeList.forEach(meta => {
|
|
258
|
+
const attrName = meta.options.name || String(meta.propertyKey);
|
|
259
|
+
if (meta.options.connectedInitialize) {
|
|
260
|
+
// JS -> DOM (FORCE OVERWRITE)
|
|
261
|
+
const memoryVal = (this as any)[meta.privateKey];
|
|
262
|
+
if (memoryVal !== undefined) {
|
|
263
|
+
(this as any).__swc_syncing_init = true;
|
|
264
|
+
try {
|
|
265
|
+
(this as any)[meta.propertyKey] = memoryVal; // Trigger setter to update DOM
|
|
266
|
+
} finally {
|
|
267
|
+
(this as any).__swc_syncing_init = false;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} else if (meta.selector === ':host' || !meta.selector) {
|
|
271
|
+
// DOM -> JS (Pull from HTML)
|
|
272
|
+
const domVal = this.getAttribute(attrName);
|
|
273
|
+
if (domVal !== null) {
|
|
274
|
+
(this as any).__swc_syncing_init = true;
|
|
275
|
+
try {
|
|
276
|
+
(this as any)[meta.propertyKey] = domVal; // Update memory with DOM value
|
|
277
|
+
} finally {
|
|
278
|
+
(this as any).__swc_syncing_init = false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
});
|
|
255
283
|
|
|
256
284
|
if (connectedInnerHtmlList.length > 0) {
|
|
257
285
|
let sContent = '',
|
|
@@ -360,12 +388,14 @@ export const elementDefine =
|
|
|
360
388
|
});
|
|
361
389
|
|
|
362
390
|
if (originalConnected) originalConnected.apply(this);
|
|
391
|
+
|
|
363
392
|
const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
|
|
364
393
|
if (aMethods) {
|
|
365
394
|
for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
|
|
366
395
|
}
|
|
367
396
|
(this as any)._executeSwcScript('swc-on-connected', hostSet);
|
|
368
397
|
(this as any)._executeSwcScript('swc-on-after-connected', hostSet);
|
|
398
|
+
(this as any).__swc_connected = true;
|
|
369
399
|
};
|
|
370
400
|
|
|
371
401
|
const originalDisconnected = proto.disconnectedCallback;
|
|
@@ -390,6 +420,7 @@ export const elementDefine =
|
|
|
390
420
|
}
|
|
391
421
|
(this as any)._executeSwcScript('swc-on-disconnected', hostSet);
|
|
392
422
|
(this as any)._executeSwcScript('swc-on-after-disconnected', hostSet);
|
|
423
|
+
(this as any).__swc_connected = false;
|
|
393
424
|
};
|
|
394
425
|
|
|
395
426
|
const originalAdopted = proto.adoptedCallback;
|
|
@@ -415,6 +446,7 @@ export const elementDefine =
|
|
|
415
446
|
proto.attributeChangedCallback = function (name: string, old: string | null, newVal: string | null) {
|
|
416
447
|
if (originalAttributeChanged) originalAttributeChanged.apply(this, [name, old, newVal]);
|
|
417
448
|
|
|
449
|
+
// Handle swc-on-* events
|
|
418
450
|
if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
|
|
419
451
|
if (newVal !== null) {
|
|
420
452
|
const customEventMeta = emitCustomEventList.find(it => it.options.attributeName === name);
|
|
@@ -423,6 +455,7 @@ export const elementDefine =
|
|
|
423
455
|
}
|
|
424
456
|
}
|
|
425
457
|
|
|
458
|
+
// Handle @changedAttribute callbacks
|
|
426
459
|
const mKeys = attrChangeMap.get(name);
|
|
427
460
|
if (mKeys && Array.isArray(mKeys)) {
|
|
428
461
|
const hSet = SwcUtils.getHostSet(this as any);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { SpecialSelector, SwcQueryOptions } from '../types';
|
|
3
3
|
import { ensureInit, getElementConfig } from './elementDefine';
|
|
4
4
|
import { SwcUtils } from '../utils/Utils';
|
package/src/decorators/index.ts
CHANGED
package/src/decorators/query.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { getElementConfig, ensureInit } from './elementDefine';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
4
|
import { SpecialSelector, SwcQueryOptions } from '../types';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { getElementConfig, ensureInit } from './elementDefine';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
4
|
import { SpecialSelector, SwcQueryOptions } from '../types';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { ensureInit, getElementConfig } from './elementDefine';
|
|
3
3
|
|
|
4
4
|
export const REPLACE_CHILDREN_METADATA_KEY = Symbol('simple-web-component:replace-children');
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { ReflectUtils } from '@dooboostore/core
|
|
1
|
+
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { ensureInit, getElementConfig } from './elementDefine';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
|
+
import { SwcQueryOptions } from '../types';
|
|
4
5
|
|
|
5
6
|
export interface SetAttributeMetadata {
|
|
6
7
|
propertyKey: string | symbol;
|
|
7
8
|
selector: string;
|
|
8
9
|
name: string;
|
|
10
|
+
options: SwcQueryOptions;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export const SET_ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:set-attribute');
|
|
@@ -15,7 +17,9 @@ export const SET_ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:set-attri
|
|
|
15
17
|
* Usage: @setAttribute(':host', 'count')
|
|
16
18
|
* Usage: @setAttribute('#child', 'disabled')
|
|
17
19
|
*/
|
|
18
|
-
export function setAttribute(selector: string, name: string): MethodDecorator
|
|
20
|
+
export function setAttribute(selector: string, name: string): MethodDecorator;
|
|
21
|
+
export function setAttribute(selector: string, name: string, options?: SwcQueryOptions): MethodDecorator;
|
|
22
|
+
export function setAttribute(selector: string, name: string, options: SwcQueryOptions = {}): MethodDecorator {
|
|
19
23
|
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
20
24
|
const constructor = target.constructor;
|
|
21
25
|
let metaList = ReflectUtils.getOwnMetadata(SET_ATTRIBUTE_METADATA_KEY, constructor) as Map<string | symbol, SetAttributeMetadata>;
|
|
@@ -23,7 +27,7 @@ export function setAttribute(selector: string, name: string): MethodDecorator {
|
|
|
23
27
|
metaList = new Map<string | symbol, SetAttributeMetadata>();
|
|
24
28
|
ReflectUtils.defineMetadata(SET_ATTRIBUTE_METADATA_KEY, metaList, constructor);
|
|
25
29
|
}
|
|
26
|
-
metaList.set(propertyKey, { propertyKey, selector, name });
|
|
30
|
+
metaList.set(propertyKey, { propertyKey, selector, name, options });
|
|
27
31
|
|
|
28
32
|
const original = descriptor.value;
|
|
29
33
|
descriptor.value = async function (...args: any[]) {
|
|
@@ -34,22 +38,50 @@ export function setAttribute(selector: string, name: string): MethodDecorator {
|
|
|
34
38
|
const conf = getElementConfig(this);
|
|
35
39
|
const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else if (selector === ':window') targetEl = currentWin as any;
|
|
40
|
-
else if (selector === ':document') targetEl = currentWin.document as any;
|
|
41
|
-
else if (selector === ':parentHost') targetEl = hostSet.$parentHost;
|
|
42
|
-
else if (selector === ':appHost') targetEl = hostSet.$appHost;
|
|
43
|
-
else if (selector === ':firstHost') targetEl = hostSet.$firstHost;
|
|
44
|
-
else if (selector === ':lastHost') targetEl = hostSet.$lastHost;
|
|
45
|
-
else if (selector === ':firstAppHost') targetEl = hostSet.$firstAppHost;
|
|
46
|
-
else if (selector === ':lastAppHost') targetEl = hostSet.$lastAppHost;
|
|
47
|
-
else targetEl = (this.shadowRoot || (this as any)).querySelector(selector);
|
|
41
|
+
const targetEls: any[] = [];
|
|
42
|
+
const r = options.root || 'auto';
|
|
48
43
|
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
|
|
44
|
+
const applyRoot = (t: any) => {
|
|
45
|
+
if (!t) return;
|
|
46
|
+
if (r === 'auto') {
|
|
47
|
+
targetEls.push((t as any).shadowRoot || t);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (r === 'light' || r === 'all') targetEls.push(t);
|
|
51
|
+
if ((r === 'shadow' || r === 'all') && (t as any).shadowRoot) targetEls.push((t as any).shadowRoot);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
if (selector === ':window') targetEls.push(currentWin);
|
|
55
|
+
else if (selector === ':document') targetEls.push(currentWin.document as any);
|
|
56
|
+
else if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
|
|
57
|
+
else if (selector === ':appHost') applyRoot(hostSet.$appHost);
|
|
58
|
+
else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
|
|
59
|
+
else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
|
|
60
|
+
else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost);
|
|
61
|
+
else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost);
|
|
62
|
+
else if (selector === ':hosts') hostSet.$hosts.forEach(applyRoot);
|
|
63
|
+
else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRoot);
|
|
64
|
+
else if (selector === ':host' || !selector) applyRoot(this);
|
|
65
|
+
else {
|
|
66
|
+
const roots: any[] = [];
|
|
67
|
+
if (r === 'shadow') {
|
|
68
|
+
if ((this as any).shadowRoot) roots.push((this as any).shadowRoot);
|
|
69
|
+
} else if (r === 'light') {
|
|
70
|
+
roots.push(this as any);
|
|
71
|
+
} else if (r === 'all') {
|
|
72
|
+
roots.push(this as any);
|
|
73
|
+
if ((this as any).shadowRoot) roots.push((this as any).shadowRoot);
|
|
74
|
+
} else {
|
|
75
|
+
roots.push((this as any).shadowRoot || (this as any));
|
|
76
|
+
}
|
|
77
|
+
roots.forEach(root => targetEls.push(...root.querySelectorAll(selector)));
|
|
52
78
|
}
|
|
79
|
+
|
|
80
|
+
targetEls.forEach(targetEl => {
|
|
81
|
+
if (!targetEl || typeof (targetEl as any).setAttribute !== 'function') return;
|
|
82
|
+
if (res === null) (targetEl as any).removeAttribute(name);
|
|
83
|
+
else (targetEl as any).setAttribute(name, String(res));
|
|
84
|
+
})
|
|
53
85
|
}
|
|
54
86
|
return res;
|
|
55
87
|
};
|
package/src/decorators/style.ts
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { SimpleApplication } from '@dooboostore/simple-boot/SimpleApplication';
|
|
2
|
-
import { PathRouter } from '@dooboostore/core-web
|
|
3
|
-
import { HashRouter } from '@dooboostore/core-web
|
|
2
|
+
import { PathRouter } from '@dooboostore/core-web';
|
|
3
|
+
import { HashRouter } from '@dooboostore/core-web';
|
|
4
4
|
import { ElementRouter } from '../router/ElementRouter';
|
|
5
5
|
import { SimOption } from '@dooboostore/simple-boot/SimOption';
|
|
6
|
-
import { Router, RouterEventType } from '@dooboostore/core-web
|
|
7
|
-
import { Subscription } from '@dooboostore/core
|
|
8
|
-
import { ConstructorType,
|
|
9
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
6
|
+
import { Router, RouterEventType } from '@dooboostore/core-web';
|
|
7
|
+
import { Subscription } from '@dooboostore/core';
|
|
8
|
+
import { ConstructorType, OptionalType } from '@dooboostore/core';
|
|
9
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
10
10
|
import { SwcUtils } from '../utils/Utils';
|
|
11
11
|
|
|
12
12
|
export type SwcConfigType = {
|
|
13
|
-
rootRouter: ConstructorType<any> |
|
|
13
|
+
rootRouter: ConstructorType<any> | symbol;
|
|
14
14
|
routeType: 'path' | 'hash' | 'element';
|
|
15
|
+
connectMode?: 'direct' | 'swap';
|
|
15
16
|
path?: string;
|
|
16
17
|
window: Window;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
export type SwcAttributeConfigType =
|
|
20
|
+
export type SwcAttributeConfigType = OptionalType<SwcConfigType, 'routeType' | 'window'>;
|
|
20
21
|
|
|
21
22
|
export class SwcAppEngine {
|
|
22
23
|
public simpleApplication?: SimpleApplication;
|
|
@@ -12,7 +12,38 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
async connect(config?: SwcAttributeConfigType) {
|
|
15
|
-
|
|
15
|
+
const mode = config?.connectMode || 'direct';
|
|
16
|
+
|
|
17
|
+
if (mode !== 'swap') {
|
|
18
|
+
await this.__swc_engine.connect(config);
|
|
19
|
+
this.setAttribute('swc-connect-mode', 'direct');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parent = this.parentNode;
|
|
24
|
+
if (!parent) {
|
|
25
|
+
await this.__swc_engine.connect(config);
|
|
26
|
+
this.setAttribute('swc-connect-mode', 'direct');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const clonedApp = this.cloneNode(true) as any;
|
|
31
|
+
clonedApp.style.display = 'none';
|
|
32
|
+
parent.insertBefore(clonedApp, this.nextSibling);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
await clonedApp.connect({ ...(config || {}), connectMode: 'direct' });
|
|
36
|
+
if (this.parentNode) {
|
|
37
|
+
this.parentNode.removeChild(this);
|
|
38
|
+
}
|
|
39
|
+
clonedApp.setAttribute('swc-connect-mode', 'swap');
|
|
40
|
+
clonedApp.style.display = '';
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (clonedApp.parentNode) {
|
|
43
|
+
clonedApp.parentNode.removeChild(clonedApp);
|
|
44
|
+
}
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
16
47
|
}
|
|
17
48
|
|
|
18
49
|
connectedCallback() {
|
package/src/elements/SwcAsync.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { changedAttribute } from '../decorators/changedAttribute';
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
3
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
5
|
export class SwcAsync extends HTMLTemplateElement {
|
|
6
6
|
private _nodes: Node[] = [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { changedAttribute } from '../decorators/changedAttribute';
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
3
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
5
|
export class SwcChoose extends HTMLTemplateElement {
|
|
6
6
|
private _nodes: Node[] = [];
|
package/src/elements/SwcIf.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { changedAttribute } from '../decorators/changedAttribute';
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
3
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
5
|
export class SwcIf extends HTMLTemplateElement {
|
|
6
6
|
private _value = false;
|
package/src/elements/SwcLoop.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { changedAttribute } from '../decorators/changedAttribute';
|
|
2
2
|
import { SwcUtils } from '../utils/Utils';
|
|
3
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
3
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
4
4
|
|
|
5
5
|
export class SwcLoop extends HTMLTemplateElement {
|
|
6
6
|
private _value: any[] = [];
|
package/src/elements/register.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { elementDefine } from '../decorators/elementDefine';
|
|
2
2
|
import { SwcAppMixin } from './SwcAppMixin';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
|
-
import { FunctionUtils } from '@dooboostore/core
|
|
4
|
+
import { FunctionUtils } from '@dooboostore/core';
|
|
5
5
|
import { changedAttribute } from '../decorators/changedAttribute';
|
|
6
6
|
|
|
7
7
|
export const registerAllElements = (w: any) => {
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { registerAllElements } from './elements/register';
|
|
|
3
3
|
|
|
4
4
|
// Decorators
|
|
5
5
|
export * from './decorators/elementDefine';
|
|
6
|
+
export * from './decorators/attribute';
|
|
6
7
|
export * from './decorators/setAttribute';
|
|
7
8
|
export * from './decorators/changedAttribute';
|
|
8
9
|
export { onConnectedInnerHtml } from './decorators/onConnectedInnerHtml';
|
|
@@ -27,9 +28,9 @@ export * from './utils/TemplateUtils';
|
|
|
27
28
|
export * from './config/config';
|
|
28
29
|
|
|
29
30
|
// Registration Factory
|
|
30
|
-
export default (w: Window, other?: ((w:Window)=>void)[]): void => {
|
|
31
|
+
export default (w: Window, other?: ((w: Window) => void)[]): void => {
|
|
31
32
|
registerAllElements(w);
|
|
32
33
|
other?.forEach(fn => {
|
|
33
|
-
|
|
34
|
+
fn(w);
|
|
34
35
|
});
|
|
35
36
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ChangeStateConfig, ChangeStateResult, RouteAction, Router, RouterConfig, RouterMethodOptions } from '@dooboostore/core-web
|
|
2
|
-
import { UrlUtils } from '@dooboostore/core
|
|
1
|
+
import { ChangeStateConfig, ChangeStateResult, RouteAction, Router, RouterConfig, RouterMethodOptions } from '@dooboostore/core-web';
|
|
2
|
+
import { UrlUtils } from '@dooboostore/core';
|
|
3
3
|
|
|
4
4
|
export class ElementRouter extends Router {
|
|
5
5
|
private _history: { url: string; data: any; title?: string }[] = [];
|