@dooboostore/simple-web-component 1.0.24 → 1.0.26
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 +162 -33
- package/dist/cjs/decorators/addEventListener.js +1 -1
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/applyAttribute.js +148 -0
- package/dist/cjs/decorators/applyAttribute.js.map +7 -0
- package/dist/cjs/decorators/applyClass.js +164 -0
- package/dist/cjs/decorators/applyClass.js.map +7 -0
- package/dist/cjs/decorators/applyNode.js +87 -194
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/{style.js → applyStyle.js} +50 -60
- package/dist/cjs/decorators/applyStyle.js.map +7 -0
- package/dist/cjs/decorators/attribute.js +10 -16
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/changedAttributeHost.js +1 -1
- package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +14 -23
- package/dist/cjs/decorators/elementDefine.js.map +2 -2
- package/dist/cjs/decorators/emitCustomEvent.js +5 -2
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/index.js +3 -3
- package/dist/cjs/decorators/index.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +9 -9
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/query.js +1 -1
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +1 -1
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/elements/SwcAppEngine.js +19 -4
- package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +2 -0
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/utils/Utils.js +1 -1
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/addEventListener.js +1 -1
- package/dist/esm/decorators/addEventListener.js.map +2 -2
- package/dist/esm/decorators/applyAttribute.js +129 -0
- package/dist/esm/decorators/applyAttribute.js.map +7 -0
- package/dist/esm/decorators/applyClass.js +145 -0
- package/dist/esm/decorators/applyClass.js.map +7 -0
- package/dist/esm/decorators/applyNode.js +87 -194
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/{style.js → applyStyle.js} +47 -57
- package/dist/esm/decorators/applyStyle.js.map +7 -0
- package/dist/esm/decorators/attribute.js +10 -16
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/changedAttributeHost.js +1 -1
- package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +14 -23
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +5 -2
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/index.js +3 -3
- package/dist/esm/decorators/index.js.map +1 -1
- package/dist/esm/decorators/lifecycles.js +9 -9
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/query.js +1 -1
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/queryAll.js +1 -1
- package/dist/esm/decorators/queryAll.js.map +2 -2
- package/dist/esm/elements/SwcAppEngine.js +19 -4
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +2 -0
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/utils/Utils.js +1 -1
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +2853 -574
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/applyAttribute.d.ts +22 -0
- package/dist/types/decorators/applyAttribute.d.ts.map +1 -0
- package/dist/types/decorators/applyClass.d.ts +65 -0
- package/dist/types/decorators/applyClass.d.ts.map +1 -0
- package/dist/types/decorators/applyNode.d.ts +15 -123
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/applyStyle.d.ts +21 -0
- package/dist/types/decorators/applyStyle.d.ts.map +1 -0
- package/dist/types/decorators/attribute.d.ts +10 -19
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/index.d.ts +3 -3
- package/dist/types/decorators/index.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/queryAll.d.ts.map +1 -1
- package/dist/types/elements/SwcAppEngine.d.ts +7 -0
- 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/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +2853 -574
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +2 -2
- package/src/decorators/addEventListener.ts +1 -1
- package/src/decorators/applyAttribute.ts +147 -0
- package/src/decorators/applyClass.ts +158 -0
- package/src/decorators/applyNode.ts +112 -330
- package/src/decorators/applyStyle.ts +128 -0
- package/src/decorators/attribute.ts +21 -55
- package/src/decorators/changedAttributeHost.ts +1 -1
- package/src/decorators/elementDefine.ts +18 -39
- package/src/decorators/emitCustomEvent.ts +6 -3
- package/src/decorators/index.ts +3 -3
- package/src/decorators/lifecycles.ts +9 -11
- package/src/decorators/query.ts +1 -1
- package/src/decorators/queryAll.ts +1 -1
- package/src/elements/SwcAppEngine.ts +32 -4
- package/src/elements/SwcAppMixin.ts +2 -0
- package/src/utils/Utils.ts +2 -1
- package/dist/cjs/decorators/classList.js +0 -177
- package/dist/cjs/decorators/classList.js.map +0 -7
- package/dist/cjs/decorators/setAttribute.js +0 -111
- package/dist/cjs/decorators/setAttribute.js.map +0 -7
- package/dist/cjs/decorators/style.js.map +0 -7
- package/dist/esm/decorators/classList.js +0 -158
- package/dist/esm/decorators/classList.js.map +0 -7
- package/dist/esm/decorators/setAttribute.js +0 -92
- package/dist/esm/decorators/setAttribute.js.map +0 -7
- package/dist/esm/decorators/style.js.map +0 -7
- package/dist/types/decorators/classList.d.ts +0 -71
- package/dist/types/decorators/classList.d.ts.map +0 -1
- package/dist/types/decorators/setAttribute.d.ts +0 -23
- package/dist/types/decorators/setAttribute.d.ts.map +0 -1
- package/dist/types/decorators/style.d.ts +0 -58
- package/dist/types/decorators/style.d.ts.map +0 -1
- package/src/decorators/classList.ts +0 -234
- package/src/decorators/setAttribute.ts +0 -114
- package/src/decorators/style.ts +0 -185
|
@@ -3,24 +3,21 @@ import {ensureInit, getElementConfig} from './elementDefine';
|
|
|
3
3
|
import {SwcUtils} from '../utils/Utils';
|
|
4
4
|
import {SpecialSelector, SwcQueryOptions} from '../types';
|
|
5
5
|
|
|
6
|
-
export interface
|
|
6
|
+
export interface AttributeFieldOptions extends SwcQueryOptions {
|
|
7
7
|
name?: string;
|
|
8
8
|
connectedInitialize?: boolean;
|
|
9
9
|
type?: typeof Number | typeof Boolean | typeof String;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export interface
|
|
12
|
+
export interface AttributeFieldMetadata {
|
|
13
13
|
propertyKey: string | symbol;
|
|
14
14
|
selector: string;
|
|
15
|
-
options:
|
|
16
|
-
privateKey: symbol;
|
|
15
|
+
options: AttributeFieldOptions;
|
|
16
|
+
privateKey: symbol;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const
|
|
19
|
+
export const ATTRIBUTE_FIELD_METADATA_KEY = Symbol.for('simple-web-component:attribute-field');
|
|
20
20
|
|
|
21
|
-
/**
|
|
22
|
-
* Helper to perform type conversion from string to target type
|
|
23
|
-
*/
|
|
24
21
|
const convertValue = (val: string | null, type: any): any => {
|
|
25
22
|
if (val === null || val === undefined) return val;
|
|
26
23
|
if (type === Number) return Number(val);
|
|
@@ -28,18 +25,13 @@ const convertValue = (val: string | null, type: any): any => {
|
|
|
28
25
|
return val;
|
|
29
26
|
};
|
|
30
27
|
|
|
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[] => {
|
|
28
|
+
export const resolveTargetEls = (inst: any, selector: string, options: AttributeFieldOptions, currentWin: any): HTMLElement[] => {
|
|
35
29
|
const r = options.root || 'auto';
|
|
36
30
|
const results: HTMLElement[] = [];
|
|
37
31
|
|
|
38
32
|
const applyRoot = (target: any) => {
|
|
39
33
|
if (!target) return;
|
|
40
34
|
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
35
|
results.push(target);
|
|
44
36
|
} else {
|
|
45
37
|
if (r === 'light' || r === 'all') results.push(target);
|
|
@@ -85,24 +77,22 @@ export const resolveTargetEls = (inst: any, selector: string, options: Attribute
|
|
|
85
77
|
/**
|
|
86
78
|
* @attribute decorator to sync a field value with an element's attribute.
|
|
87
79
|
*/
|
|
88
|
-
export function attribute(selector: string, options:
|
|
80
|
+
export function attribute(selector: string, options: AttributeFieldOptions = {}): PropertyDecorator {
|
|
89
81
|
return (target: Object, propertyKey: string | symbol) => {
|
|
90
82
|
const constructor = target.constructor;
|
|
91
83
|
const privateKey = Symbol(String(propertyKey));
|
|
92
84
|
|
|
93
85
|
const designType = (Reflect as any).getMetadata('design:type', target, propertyKey);
|
|
94
86
|
|
|
95
|
-
let metaList = ReflectUtils.getOwnMetadata(
|
|
87
|
+
let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_FIELD_METADATA_KEY, constructor) as AttributeFieldMetadata[];
|
|
96
88
|
if (!metaList) {
|
|
97
89
|
metaList = [];
|
|
98
|
-
ReflectUtils.defineMetadata(
|
|
90
|
+
ReflectUtils.defineMetadata(ATTRIBUTE_FIELD_METADATA_KEY, metaList, constructor);
|
|
99
91
|
}
|
|
100
92
|
metaList.push({propertyKey, selector, options, privateKey});
|
|
101
93
|
|
|
102
|
-
// Helper function to apply setAttribute to targets
|
|
103
94
|
const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {
|
|
104
95
|
targets.forEach(it => {
|
|
105
|
-
console.log('----->', it)
|
|
106
96
|
if (it && typeof (it as any).setAttribute === 'function') {
|
|
107
97
|
if (nv === null) {
|
|
108
98
|
(it as any).removeAttribute(attrName);
|
|
@@ -122,8 +112,6 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
|
|
|
122
112
|
const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
|
|
123
113
|
const targetType = options.type || designType;
|
|
124
114
|
|
|
125
|
-
console.log('type-->', propertyKey, targetType);
|
|
126
|
-
// During early init phase, if syncing memory to DOM, return memory.
|
|
127
115
|
if (this.__swc_syncing_init || (options.connectedInitialize && !this.__swc_connected)) {
|
|
128
116
|
return convertValue(this[privateKey], targetType);
|
|
129
117
|
}
|
|
@@ -142,33 +130,25 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
|
|
|
142
130
|
return convertValue(this[privateKey], targetType);
|
|
143
131
|
},
|
|
144
132
|
set(this: any, nv: any) {
|
|
145
|
-
const targetType = options.type || designType;
|
|
146
|
-
// console.log('---set', propertyKey, targetType, nv, this, this.__swc_syncing_init);
|
|
147
|
-
|
|
148
133
|
const attrName = options.name || String(propertyKey);
|
|
149
134
|
const conf = getElementConfig(this);
|
|
150
135
|
const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
|
|
151
136
|
|
|
152
|
-
// During initialization/syncing phase
|
|
153
137
|
if (this.__swc_syncing_init) {
|
|
154
|
-
// If connectedInitialize is enabled, force setAttribute (JS -> DOM)
|
|
155
138
|
if (options.connectedInitialize === true) {
|
|
156
139
|
const targets = resolveTargetEls(this, selector, options, currentWin);
|
|
157
140
|
applySetAttribute(this, targets, attrName, nv);
|
|
158
141
|
} else {
|
|
159
|
-
// Otherwise just update memory
|
|
160
142
|
this[privateKey] = nv;
|
|
161
143
|
}
|
|
162
144
|
return;
|
|
163
145
|
}
|
|
164
146
|
|
|
165
|
-
// Before connected, save to memory only
|
|
166
147
|
if (!this.__swc_connected) {
|
|
167
148
|
this[privateKey] = nv;
|
|
168
149
|
return;
|
|
169
150
|
}
|
|
170
151
|
|
|
171
|
-
// After connected, normal setAttribute
|
|
172
152
|
const targets = resolveTargetEls(this, selector, options, currentWin);
|
|
173
153
|
applySetAttribute(this, targets, attrName, nv);
|
|
174
154
|
},
|
|
@@ -178,48 +158,34 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
|
|
|
178
158
|
};
|
|
179
159
|
}
|
|
180
160
|
|
|
181
|
-
export const findAllAttributeMetadata = (target: any): AttributeMetadata[] => {
|
|
182
|
-
return ReflectUtils.findAllMetadata<AttributeMetadata[]>(ATTRIBUTE_METADATA_KEY, target).flat();
|
|
183
|
-
};
|
|
184
|
-
|
|
185
161
|
/**
|
|
186
|
-
* @attributeHost decorator
|
|
187
|
-
* Usage: @attributeHost - uses field name as attribute name
|
|
188
|
-
* Usage: @attributeHost() - uses field name as attribute name
|
|
189
|
-
* Usage: @attributeHost('data-id') - uses custom attribute name
|
|
190
|
-
* Usage: @attributeHost({ type: Boolean }) - uses field name with options
|
|
191
|
-
* Usage: @attributeHost('data-id', { type: Boolean }) - uses custom name with options
|
|
162
|
+
* @attributeHost decorator to sync a field value with the :host element's attribute.
|
|
192
163
|
*/
|
|
193
164
|
export function attributeHost(target: Object, propertyKey: string | symbol): void;
|
|
194
|
-
export function attributeHost(): PropertyDecorator;
|
|
195
|
-
export function attributeHost(options: AttributeOptions): PropertyDecorator;
|
|
165
|
+
export function attributeHost(options: AttributeFieldOptions): PropertyDecorator;
|
|
196
166
|
export function attributeHost(attrName: string): PropertyDecorator;
|
|
197
|
-
export function attributeHost(attrName: string, options:
|
|
167
|
+
export function attributeHost(attrName: string, options: AttributeFieldOptions): PropertyDecorator;
|
|
198
168
|
export function attributeHost(targetOrAttrOrOptions?: any, propertyKeyOrOptions?: any): any {
|
|
199
|
-
// Direct decorator usage: @attributeHost (no parentheses)
|
|
200
169
|
if (propertyKeyOrOptions !== undefined && (typeof propertyKeyOrOptions === 'string' || typeof propertyKeyOrOptions === 'symbol')) {
|
|
201
|
-
|
|
202
|
-
return attribute(':host', { name: fieldName })(targetOrAttrOrOptions, propertyKeyOrOptions);
|
|
170
|
+
return attribute(':host', { name: String(propertyKeyOrOptions) })(targetOrAttrOrOptions, propertyKeyOrOptions);
|
|
203
171
|
}
|
|
204
172
|
|
|
205
|
-
// @attributeHost() or @attributeHost(options) or @attributeHost('name')
|
|
206
173
|
if (typeof targetOrAttrOrOptions === 'string') {
|
|
207
|
-
// @attributeHost('customName') or @attributeHost('customName', options)
|
|
208
174
|
const attrName = targetOrAttrOrOptions;
|
|
209
|
-
const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as
|
|
175
|
+
const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as AttributeFieldOptions;
|
|
210
176
|
return attribute(':host', { ...options, name: attrName });
|
|
211
177
|
} else if (typeof targetOrAttrOrOptions === 'object') {
|
|
212
|
-
|
|
213
|
-
const options = targetOrAttrOrOptions as AttributeOptions;
|
|
178
|
+
const options = targetOrAttrOrOptions as AttributeFieldOptions;
|
|
214
179
|
return (target: Object, propertyKey: string | symbol) => {
|
|
215
|
-
|
|
216
|
-
return attribute(':host', { ...options, name: fieldName })(target, propertyKey);
|
|
180
|
+
return attribute(':host', { ...options, name: String(propertyKey) })(target, propertyKey);
|
|
217
181
|
};
|
|
218
182
|
} else {
|
|
219
|
-
// @attributeHost() - use field name as attribute name
|
|
220
183
|
return (target: Object, propertyKey: string | symbol) => {
|
|
221
|
-
|
|
222
|
-
return attribute(':host', { name: fieldName })(target, propertyKey);
|
|
184
|
+
return attribute(':host', { name: String(propertyKey) })(target, propertyKey);
|
|
223
185
|
};
|
|
224
186
|
}
|
|
225
187
|
}
|
|
188
|
+
|
|
189
|
+
export const findAllAttributeMetadata = (target: any): AttributeFieldMetadata[] => {
|
|
190
|
+
return ReflectUtils.findAllMetadata<AttributeFieldMetadata[]>(ATTRIBUTE_FIELD_METADATA_KEY, target).flat();
|
|
191
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ReflectUtils} from '@dooboostore/core';
|
|
2
2
|
|
|
3
|
-
export const ON_ATTRIBUTE_CHANGED_METADATA_KEY = Symbol('simple-web-component:on-attribute-changed');
|
|
3
|
+
export const ON_ATTRIBUTE_CHANGED_METADATA_KEY = Symbol.for('simple-web-component:on-attribute-changed');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @changedAttributeHost decorator - fires when any attribute on :host changes
|
|
@@ -4,7 +4,7 @@ import { getAddEventListenerMetadata } from './addEventListener';
|
|
|
4
4
|
import { ON_CONSTRUCTOR_METADATA_KEY, 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, getOnConnectedInnerHtmlMetadata } from './lifecycles';
|
|
5
5
|
import { getEmitCustomEventMetadataList } from './emitCustomEvent';
|
|
6
6
|
import { findAllAttributeChangedMetadata } from './changedAttributeHost';
|
|
7
|
-
import {
|
|
7
|
+
import { findAllAttributeApplyMetadata } from './applyAttribute';
|
|
8
8
|
import { findAllAttributeMetadata } from './attribute';
|
|
9
9
|
import { SwcUtils } from '../utils/Utils';
|
|
10
10
|
import { HTML_TAG_ENTRIES, DOM_EVENT_NAMES } from '../config/config';
|
|
@@ -13,7 +13,7 @@ import { InjectSituationType, HostSet } from '../types';
|
|
|
13
13
|
|
|
14
14
|
// --- Core Interfaces & Types ---
|
|
15
15
|
|
|
16
|
-
export const ELEMENT_CONFIG_KEY = Symbol('simple-web-component:element-config');
|
|
16
|
+
export const ELEMENT_CONFIG_KEY = Symbol.for('simple-web-component:element-config');
|
|
17
17
|
|
|
18
18
|
export interface ElementConfig {
|
|
19
19
|
extends?: string;
|
|
@@ -161,7 +161,6 @@ const setupPrototype = (proto: any) => {
|
|
|
161
161
|
if (oldHandler) el.removeEventListener(eventName, oldHandler);
|
|
162
162
|
|
|
163
163
|
const handler = async (event: any) => {
|
|
164
|
-
console.log('execute handler', event);
|
|
165
164
|
const parent = SwcUtils.findNearestSwcHost(el);
|
|
166
165
|
const hostSet = SwcUtils.getHostSet(parent || el);
|
|
167
166
|
const conf = getElementConfig(this);
|
|
@@ -185,7 +184,6 @@ const setupPrototype = (proto: any) => {
|
|
|
185
184
|
proto.__swc_executeAttributeEvent = async function (el: HTMLElement, attrName: string, script: string, event: Event) {
|
|
186
185
|
ensureInit(this);
|
|
187
186
|
|
|
188
|
-
console.log('execute handler2', event);
|
|
189
187
|
const parent = SwcUtils.findNearestSwcHost(el);
|
|
190
188
|
const hostSet = SwcUtils.getHostSet(parent || el);
|
|
191
189
|
const conf = getElementConfig(this);
|
|
@@ -231,15 +229,26 @@ export const elementDefine =
|
|
|
231
229
|
const emitCustomEventList = getEmitCustomEventMetadataList(constructor) || [];
|
|
232
230
|
const emitHostCustomEventList = emitCustomEventList.filter(meta => meta.selector === ':host' || meta.selector === '');
|
|
233
231
|
const addEventListenerList = getAddEventListenerMetadata(constructor) || [];
|
|
234
|
-
const addHostEventListenerList = addEventListenerList.filter(meta => meta.selector === ':host' || meta.selector === '');
|
|
235
232
|
const attrChangeMap = findAllAttributeChangedMetadata(constructor);
|
|
236
233
|
const attributeList = findAllAttributeMetadata(constructor);
|
|
234
|
+
const applyAttributeMap = findAllAttributeApplyMetadata(constructor);
|
|
237
235
|
|
|
238
236
|
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'];
|
|
239
237
|
const swcOnEvents = DOM_EVENT_NAMES.map(e => `swc-on-${e}`);
|
|
240
238
|
|
|
241
239
|
// Collect all observed attributes from all decorators
|
|
242
|
-
const
|
|
240
|
+
const attributeApplyNames = Array.from(applyAttributeMap.values()).map(it => it.options.name).filter(Boolean) as string[];
|
|
241
|
+
const attributeListNames = attributeList.map(it => it.options.name || String(it.propertyKey));
|
|
242
|
+
|
|
243
|
+
const mergedObservedAttributes = [...new Set([
|
|
244
|
+
...(metadata.observedAttributes ?? []),
|
|
245
|
+
...attrChangeMap.keys(),
|
|
246
|
+
...attributeApplyNames,
|
|
247
|
+
...attributeListNames,
|
|
248
|
+
...emitHostCustomEventList.map(it => (it.options as any).attributeName).filter(Boolean),
|
|
249
|
+
...swcLifecycleAttributes,
|
|
250
|
+
...swcOnEvents
|
|
251
|
+
])];
|
|
243
252
|
|
|
244
253
|
const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
|
|
245
254
|
|
|
@@ -264,22 +273,19 @@ export const elementDefine =
|
|
|
264
273
|
for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
|
|
265
274
|
}
|
|
266
275
|
|
|
267
|
-
// Initialize @attribute fields
|
|
276
|
+
// Initialize @attribute fields
|
|
268
277
|
attributeList.forEach(meta => {
|
|
269
|
-
const attrName = meta.options.name || String(meta.propertyKey);
|
|
270
278
|
if (meta.options.connectedInitialize === true) {
|
|
271
|
-
// JS -> DOM (FORCE OVERWRITE with JS value)
|
|
272
279
|
(this as any).__swc_syncing_init = true;
|
|
273
280
|
try {
|
|
274
281
|
const memoryVal = (this as any)[meta.privateKey];
|
|
275
282
|
if (memoryVal !== undefined) {
|
|
276
|
-
(this as any)[meta.propertyKey] = memoryVal;
|
|
283
|
+
(this as any)[meta.propertyKey] = memoryVal;
|
|
277
284
|
}
|
|
278
285
|
} finally {
|
|
279
286
|
(this as any).__swc_syncing_init = false;
|
|
280
287
|
}
|
|
281
288
|
}
|
|
282
|
-
// else: Do NOT sync - Keep the default value from class initialization
|
|
283
289
|
});
|
|
284
290
|
|
|
285
291
|
if (connectedInnerHtmlList.length > 0) {
|
|
@@ -316,7 +322,6 @@ export const elementDefine =
|
|
|
316
322
|
}
|
|
317
323
|
});
|
|
318
324
|
|
|
319
|
-
// Group delegate listeners by (type, root) combination
|
|
320
325
|
const delegatesByTypeAndRoot = new Map<string, any[]>();
|
|
321
326
|
delegateListeners.forEach(meta => {
|
|
322
327
|
const r = meta.options.root || 'auto';
|
|
@@ -327,7 +332,6 @@ export const elementDefine =
|
|
|
327
332
|
delegatesByTypeAndRoot.get(rootKey)!.push(meta);
|
|
328
333
|
});
|
|
329
334
|
|
|
330
|
-
// Register unified handlers for delegate listeners
|
|
331
335
|
delegatesByTypeAndRoot.forEach((metaList, typeRootKey) => {
|
|
332
336
|
const [type, rStr] = typeRootKey.split(':');
|
|
333
337
|
const r = rStr === 'auto' ? 'auto' : rStr;
|
|
@@ -343,11 +347,10 @@ export const elementDefine =
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
bindRoots.forEach(br => {
|
|
346
|
-
// Sort: stopPropagation handlers first (more specific/terminal actions)
|
|
347
350
|
const sortedMetaList = [...metaList].sort((a, b) => {
|
|
348
351
|
const aStop = a.options.stopPropagation ? 1 : 0;
|
|
349
352
|
const bStop = b.options.stopPropagation ? 1 : 0;
|
|
350
|
-
return bStop - aStop;
|
|
353
|
+
return bStop - aStop;
|
|
351
354
|
});
|
|
352
355
|
|
|
353
356
|
const unifiedHandler = async (event: Event) => {
|
|
@@ -361,8 +364,6 @@ export const elementDefine =
|
|
|
361
364
|
const currentHostSet = SwcUtils.getHostSet(this as any);
|
|
362
365
|
const args = { event, ...currentHostSet, $el: matchedEl, $root: br };
|
|
363
366
|
await (this as any)[meta.propertyKey](event, currentHostSet, matchedEl, args);
|
|
364
|
-
|
|
365
|
-
// Stop processing if event propagation was stopped
|
|
366
367
|
if ((event as any).cancelBubble) break;
|
|
367
368
|
}
|
|
368
369
|
}
|
|
@@ -372,7 +373,6 @@ export const elementDefine =
|
|
|
372
373
|
});
|
|
373
374
|
});
|
|
374
375
|
|
|
375
|
-
// Process non-delegate listeners
|
|
376
376
|
nonDelegateListeners.forEach(meta => {
|
|
377
377
|
const { selector, type, options } = meta;
|
|
378
378
|
const opts = { capture: options.capture, once: options.once, passive: options.passive };
|
|
@@ -430,24 +430,6 @@ export const elementDefine =
|
|
|
430
430
|
});
|
|
431
431
|
});
|
|
432
432
|
|
|
433
|
-
addHostEventListenerList.forEach(meta => {
|
|
434
|
-
const { type, options } = meta;
|
|
435
|
-
const opts = { capture: options.capture, once: options.once, passive: options.passive };
|
|
436
|
-
|
|
437
|
-
const handler = async (event: Event) => {
|
|
438
|
-
if (options.stopPropagation) event.stopPropagation();
|
|
439
|
-
if (options.stopImmediatePropagation) event.stopImmediatePropagation();
|
|
440
|
-
if (options.preventDefault) event.preventDefault();
|
|
441
|
-
const currentHostSet = SwcUtils.getHostSet(this as any);
|
|
442
|
-
const args = { event, ...currentHostSet, $el: this, $root: this.getRootNode() };
|
|
443
|
-
await (this as any)[meta.propertyKey](event, currentHostSet, args);
|
|
444
|
-
};
|
|
445
|
-
this.addEventListener(type, handler, opts);
|
|
446
|
-
if (options.removeOnDisconnected === true) {
|
|
447
|
-
(this as any)._boundListeners.push({ target: this, type, handler, options: opts });
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
|
|
451
433
|
if (originalConnected) originalConnected.apply(this);
|
|
452
434
|
|
|
453
435
|
const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
|
|
@@ -509,7 +491,6 @@ export const elementDefine =
|
|
|
509
491
|
|
|
510
492
|
const hSet = SwcUtils.getHostSet(this as any);
|
|
511
493
|
|
|
512
|
-
// Handle swc-on-* events
|
|
513
494
|
if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
|
|
514
495
|
if (newVal !== null) {
|
|
515
496
|
const eventName = name.substring(7);
|
|
@@ -517,13 +498,11 @@ export const elementDefine =
|
|
|
517
498
|
}
|
|
518
499
|
}
|
|
519
500
|
|
|
520
|
-
// Handle @emitHostCustomEvent attribute changes
|
|
521
501
|
const hostCustomEventMeta = emitHostCustomEventList.find(it => (it.options as any).attributeName === name);
|
|
522
502
|
if (hostCustomEventMeta && newVal !== null) {
|
|
523
503
|
(this as any)._bindAttributeEvent(this as any, name, newVal, hostCustomEventMeta.type);
|
|
524
504
|
}
|
|
525
505
|
|
|
526
|
-
// Handle @changedAttribute callbacks
|
|
527
506
|
const mKeys = attrChangeMap.get(name);
|
|
528
507
|
if (mKeys && Array.isArray(mKeys)) {
|
|
529
508
|
for (const key of mKeys) (this as any)[key](newVal, old, name, hSet);
|
|
@@ -16,7 +16,7 @@ export interface EmitCustomEventMetadata {
|
|
|
16
16
|
options: (EmitCustomEventBaseOptions & SwcQueryOptions) | (EmitCustomEventBaseOptions & SwcQueryOptions & { attributeName?: string });
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const EMIT_CUSTOM_EVENT_METADATA_KEY = Symbol('simple-web-component:emit-custom-event');
|
|
19
|
+
export const EMIT_CUSTOM_EVENT_METADATA_KEY = Symbol.for('simple-web-component:emit-custom-event');
|
|
20
20
|
export function emitCustomEvent(target: SpecialSelector, type: string, options?: EmitCustomEventBaseOptions): MethodDecorator;
|
|
21
21
|
export function emitCustomEvent(selector: string, type: string, options?: EmitCustomEventBaseOptions & SwcQueryOptions): MethodDecorator;
|
|
22
22
|
/**
|
|
@@ -102,12 +102,15 @@ export const getEmitCustomEventMetadataList = (target: any): EmitCustomEventMeta
|
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
104
|
* @emitCustomEventHost decorator - simplified version of @emitCustomEvent for :host selector
|
|
105
|
-
* Usage: @emitCustomEventHost('navigate')
|
|
105
|
+
* Usage: @emitCustomEventHost('navigate') // default attributeName: 'on-emit-navigate'
|
|
106
106
|
* Usage: @emitCustomEventHost('navigate', { attributeName: 'on-navigate' })
|
|
107
107
|
*
|
|
108
108
|
* The attributeName option is used to automatically observe attributes for this event.
|
|
109
109
|
* For example, { attributeName: 'on-navigate' } will add 'on-navigate' to observedAttributes.
|
|
110
110
|
*/
|
|
111
|
-
export function emitCustomEventHost(type: string, options
|
|
111
|
+
export function emitCustomEventHost(type: string, options: EmitCustomEventBaseOptions & SwcQueryOptions & { attributeName?: string } = {}): MethodDecorator {
|
|
112
|
+
if (!options.attributeName) {
|
|
113
|
+
options.attributeName = `on-emit-${type}`;
|
|
114
|
+
}
|
|
112
115
|
return emitCustomEvent(':host', type, options);
|
|
113
116
|
}
|
package/src/decorators/index.ts
CHANGED
|
@@ -2,11 +2,11 @@ export * from './addEventListener';
|
|
|
2
2
|
export * from './attribute';
|
|
3
3
|
export * from './elementDefine';
|
|
4
4
|
export * from './changedAttributeHost';
|
|
5
|
-
export * from './setAttribute';
|
|
6
5
|
export * from './emitCustomEvent';
|
|
7
6
|
export * from './applyNode';
|
|
8
7
|
export * from './lifecycles';
|
|
9
8
|
export * from './query';
|
|
10
9
|
export * from './queryAll';
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
10
|
+
export * from './applyClass';
|
|
11
|
+
export * from './applyStyle';
|
|
12
|
+
export * from './applyAttribute';
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { ReflectUtils } from '@dooboostore/core';
|
|
2
|
-
import { ON_ATTRIBUTE_CHANGED_METADATA_KEY } from './changedAttributeHost';
|
|
3
|
-
import { SET_ATTRIBUTE_METADATA_KEY } from './setAttribute';
|
|
4
2
|
|
|
5
|
-
export const ON_CONSTRUCTOR_METADATA_KEY = Symbol('simple-web-component:on-constructor');
|
|
6
|
-
export const ON_BEFORE_CONNECTED_METADATA_KEY = Symbol('simple-web-component:on-before-connected');
|
|
7
|
-
export const ON_AFTER_CONNECTED_METADATA_KEY = Symbol('simple-web-component:on-after-connected');
|
|
8
|
-
export const ON_BEFORE_DISCONNECTED_METADATA_KEY = Symbol('simple-web-component:on-before-disconnected');
|
|
9
|
-
export const ON_AFTER_DISCONNECTED_METADATA_KEY = Symbol('simple-web-component:on-after-disconnected');
|
|
10
|
-
export const ON_BEFORE_ADOPTED_METADATA_KEY = Symbol('simple-web-component:on-before-adopted');
|
|
11
|
-
export const ON_AFTER_ADOPTED_METADATA_KEY = Symbol('simple-web-component:on-after-adopted');
|
|
12
|
-
export const ON_ADD_EVENT_LISTENER_METADATA_KEY = Symbol('simple-web-component:on-add-event-listener');
|
|
13
|
-
export const INNER_HTML_METADATA_KEY = Symbol('simple-web-component:inner-html');
|
|
3
|
+
export const ON_CONSTRUCTOR_METADATA_KEY = Symbol.for('simple-web-component:on-constructor');
|
|
4
|
+
export const ON_BEFORE_CONNECTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-connected');
|
|
5
|
+
export const ON_AFTER_CONNECTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-connected');
|
|
6
|
+
export const ON_BEFORE_DISCONNECTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-disconnected');
|
|
7
|
+
export const ON_AFTER_DISCONNECTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-disconnected');
|
|
8
|
+
export const ON_BEFORE_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-adopted');
|
|
9
|
+
export const ON_AFTER_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-adopted');
|
|
10
|
+
export const ON_ADD_EVENT_LISTENER_METADATA_KEY = Symbol.for('simple-web-component:on-add-event-listener');
|
|
11
|
+
export const INNER_HTML_METADATA_KEY = Symbol.for('simple-web-component:inner-html');
|
|
14
12
|
|
|
15
13
|
export const ATTRIBUTE_CHANGED_WILDCARD = '*';
|
|
16
14
|
|
package/src/decorators/query.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface QueryMetadata {
|
|
|
9
9
|
options: SwcQueryOptions;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const QUERY_METADATA_KEY = Symbol('simple-web-component:query');
|
|
12
|
+
export const QUERY_METADATA_KEY = Symbol.for('simple-web-component:query');
|
|
13
13
|
|
|
14
14
|
export function query(target: SpecialSelector): PropertyDecorator;
|
|
15
15
|
export function query(selector: string, options?: SwcQueryOptions): PropertyDecorator;
|
|
@@ -9,7 +9,7 @@ export interface QueryAllMetadata {
|
|
|
9
9
|
options: SwcQueryOptions;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const QUERY_ALL_METADATA_KEY = Symbol('simple-web-component:query-all');
|
|
12
|
+
export const QUERY_ALL_METADATA_KEY = Symbol.for('simple-web-component:query-all');
|
|
13
13
|
|
|
14
14
|
export function queryAll(target: SpecialSelector): PropertyDecorator;
|
|
15
15
|
export function queryAll(selector: string, options?: SwcQueryOptions): PropertyDecorator;
|
|
@@ -9,12 +9,19 @@ import { ConstructorType, OptionalType } from '@dooboostore/core';
|
|
|
9
9
|
import { FunctionUtils } from '@dooboostore/core';
|
|
10
10
|
import { SwcUtils } from '../utils/Utils';
|
|
11
11
|
|
|
12
|
+
import { SwcAppInterface } from '../types';
|
|
13
|
+
import {Intent} from "@dooboostore/simple-boot";
|
|
14
|
+
|
|
12
15
|
export type SwcConfigType = {
|
|
13
16
|
rootRouter: ConstructorType<any> | symbol;
|
|
14
17
|
routeType: 'path' | 'hash' | 'element';
|
|
15
18
|
connectMode?: 'direct' | 'swap';
|
|
19
|
+
container?: symbol;
|
|
16
20
|
path?: string;
|
|
17
21
|
window: Window;
|
|
22
|
+
onStarted?: (app: SwcAppInterface) => void;
|
|
23
|
+
onConnected?: (app: SwcAppInterface) => void;
|
|
24
|
+
onDisconnected?: (app: SwcAppInterface) => void;
|
|
18
25
|
};
|
|
19
26
|
|
|
20
27
|
export type SwcAttributeConfigType = OptionalType<SwcConfigType, 'routeType' | 'window'>;
|
|
@@ -24,9 +31,13 @@ export class SwcAppEngine {
|
|
|
24
31
|
public router?: Router;
|
|
25
32
|
private routerSubscription?: Subscription;
|
|
26
33
|
private _isInitialized = false;
|
|
34
|
+
private _config?: SwcConfigType;
|
|
27
35
|
|
|
28
36
|
constructor(private host: HTMLElement) {}
|
|
29
37
|
|
|
38
|
+
get config() {
|
|
39
|
+
return this._config;
|
|
40
|
+
}
|
|
30
41
|
async connect(config?: SwcAttributeConfigType) {
|
|
31
42
|
if (this._isInitialized) return;
|
|
32
43
|
|
|
@@ -37,10 +48,11 @@ export class SwcAppEngine {
|
|
|
37
48
|
const configStr = this.host.getAttribute('swc-get-application-config');
|
|
38
49
|
if (configStr) {
|
|
39
50
|
try {
|
|
51
|
+
// console.log('vvvvvvvvvvvvvvvv->>>>', SwcUtils.findNearestSwcHost(this.host), SwcUtils.getHostSet(this.host))
|
|
40
52
|
userConfig = FunctionUtils.executeReturn({
|
|
41
53
|
script: configStr,
|
|
42
54
|
context: this.host,
|
|
43
|
-
args: SwcUtils.getHelperAndHostSet(win, this.host)
|
|
55
|
+
args: SwcUtils.getHelperAndHostSet(win, SwcUtils.findNearestSwcHost(this.host))
|
|
44
56
|
});
|
|
45
57
|
} catch (e) {
|
|
46
58
|
console.error('[SWC-APP-ENGINE] Script execution failed:', e);
|
|
@@ -53,11 +65,12 @@ export class SwcAppEngine {
|
|
|
53
65
|
|
|
54
66
|
try {
|
|
55
67
|
if (userConfig.rootRouter) {
|
|
56
|
-
|
|
68
|
+
this._config = {
|
|
57
69
|
routeType: 'element',
|
|
58
70
|
window: win,
|
|
59
71
|
...userConfig
|
|
60
72
|
} as SwcConfigType;
|
|
73
|
+
const _config = this._config;
|
|
61
74
|
|
|
62
75
|
// Router Selection
|
|
63
76
|
if (_config.routeType === 'path') {
|
|
@@ -68,23 +81,34 @@ export class SwcAppEngine {
|
|
|
68
81
|
this.router = new ElementRouter({ window: _config.window, firstUrl: _config.path });
|
|
69
82
|
}
|
|
70
83
|
|
|
84
|
+
// console.log('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', this.router)
|
|
85
|
+
|
|
71
86
|
// Routing sync
|
|
72
87
|
if (this.router) {
|
|
73
88
|
this.routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
|
|
74
89
|
if (route.triggerPoint === 'end') {
|
|
75
|
-
|
|
90
|
+
const targetPath = (route.path || '/') + route.search;
|
|
91
|
+
const intent = new Intent(targetPath);
|
|
92
|
+
this.simpleApplication?.routing(intent);
|
|
76
93
|
}
|
|
77
94
|
});
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
|
|
81
98
|
// App start
|
|
82
|
-
|
|
99
|
+
const containerSymbol = _config.container || (this.host as any).getContainerSymbol?.();
|
|
100
|
+
this.simpleApplication = new SimpleApplication(new SimOption({
|
|
101
|
+
excludeProxys: [Node],
|
|
102
|
+
rootRouter: _config.rootRouter,
|
|
103
|
+
container: containerSymbol
|
|
104
|
+
}));
|
|
83
105
|
|
|
84
106
|
const otherInstanceSim = new Map<any, any>();
|
|
85
107
|
if (this.router) otherInstanceSim.set(Router, this.router);
|
|
86
108
|
this.simpleApplication.run(otherInstanceSim);
|
|
87
109
|
|
|
110
|
+
|
|
111
|
+
|
|
88
112
|
// Rendering
|
|
89
113
|
const data = this.simpleApplication.sim(_config.rootRouter);
|
|
90
114
|
if (data instanceof Node) {
|
|
@@ -94,12 +118,16 @@ export class SwcAppEngine {
|
|
|
94
118
|
}
|
|
95
119
|
|
|
96
120
|
if (_config.path) this.router?.go(_config.path);
|
|
121
|
+
if (_config.onStarted) {
|
|
122
|
+
_config.onStarted(this.host as unknown as SwcAppInterface);
|
|
123
|
+
}
|
|
97
124
|
}
|
|
98
125
|
} catch (e) {
|
|
99
126
|
console.error('[SWC-APP-ENGINE] Init failed:', e);
|
|
100
127
|
}
|
|
101
128
|
}
|
|
102
129
|
|
|
130
|
+
|
|
103
131
|
disconnect() {
|
|
104
132
|
this.routerSubscription?.unsubscribe();
|
|
105
133
|
}
|
|
@@ -51,12 +51,14 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
|
|
|
51
51
|
// @ts-ignore
|
|
52
52
|
if (super.connectedCallback) super.connectedCallback();
|
|
53
53
|
this.connect();
|
|
54
|
+
this.__swc_engine?.config?.onConnected?.(this);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
disconnectedCallback() {
|
|
57
58
|
// @ts-ignore
|
|
58
59
|
if (super.disconnectedCallback) super.disconnectedCallback();
|
|
59
60
|
this.__swc_engine.disconnect();
|
|
61
|
+
this.__swc_engine?.config?.onDisconnected?.(this);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
async routing(path: string) {
|
package/src/utils/Utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SwcAppInterface, HostSet, HelperSet, HelperHostSet } from '../types';
|
|
2
2
|
import {getElementConfig} from "../decorators";
|
|
3
3
|
|
|
4
|
-
export const SWC_NOT_FOUND = Symbol('
|
|
4
|
+
export const SWC_NOT_FOUND = Symbol.for('simple-web-component:not-found');
|
|
5
5
|
|
|
6
6
|
// DOM Creation Utilities
|
|
7
7
|
export const htmlFragment = (html: string, doc?: Document): DocumentFragment => {
|
|
@@ -187,6 +187,7 @@ export namespace SwcUtils {
|
|
|
187
187
|
*/
|
|
188
188
|
export const findNearestSwcHost = (el: HTMLElement | Node): HTMLElement | undefined => {
|
|
189
189
|
if ((el as any).__swc_host) return (el as any).__swc_host;
|
|
190
|
+
// if ((el as any).__swc_proto_setup) return (el as any).__swc_proto_setup;
|
|
190
191
|
|
|
191
192
|
let current: any = el.parentElement || (el.getRootNode?.() as any)?.host;
|
|
192
193
|
const doc = el.ownerDocument;
|