@dooboostore/simple-web-component 1.0.44 → 1.0.46
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 +25 -25
- package/dist/cjs/decorators/addEventListener.js.map +2 -2
- package/dist/cjs/decorators/applyAttribute.js +36 -15
- package/dist/cjs/decorators/applyAttribute.js.map +2 -2
- package/dist/cjs/decorators/applyClass.js +53 -22
- package/dist/cjs/decorators/applyClass.js.map +2 -2
- package/dist/cjs/decorators/applyNode.js +54 -24
- package/dist/cjs/decorators/applyNode.js.map +2 -2
- package/dist/cjs/decorators/applyProperty.js +38 -17
- package/dist/cjs/decorators/applyProperty.js.map +2 -2
- package/dist/cjs/decorators/applyStyle.js +53 -22
- package/dist/cjs/decorators/applyStyle.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +49 -33
- package/dist/cjs/decorators/elementDefine.js.map +3 -3
- package/dist/cjs/decorators/emitCustomEvent.js +61 -47
- package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
- package/dist/cjs/decorators/lifecycles.js +11 -36
- package/dist/cjs/decorators/lifecycles.js.map +2 -2
- package/dist/cjs/decorators/query.js +91 -56
- package/dist/cjs/decorators/query.js.map +2 -2
- package/dist/cjs/decorators/queryAll.js +104 -66
- package/dist/cjs/decorators/queryAll.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +6 -2
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/types/window.d.js.map +1 -1
- package/dist/esm/decorators/addEventListener.js.map +2 -2
- package/dist/esm/decorators/applyAttribute.js +36 -15
- package/dist/esm/decorators/applyAttribute.js.map +2 -2
- package/dist/esm/decorators/applyClass.js +53 -22
- package/dist/esm/decorators/applyClass.js.map +2 -2
- package/dist/esm/decorators/applyNode.js +54 -24
- package/dist/esm/decorators/applyNode.js.map +2 -2
- package/dist/esm/decorators/applyProperty.js +38 -17
- package/dist/esm/decorators/applyProperty.js.map +2 -2
- package/dist/esm/decorators/applyStyle.js +53 -22
- package/dist/esm/decorators/applyStyle.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +50 -34
- package/dist/esm/decorators/elementDefine.js.map +2 -2
- package/dist/esm/decorators/emitCustomEvent.js +61 -47
- package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
- package/dist/esm/decorators/lifecycles.js +11 -36
- package/dist/esm/decorators/lifecycles.js.map +2 -2
- package/dist/esm/decorators/query.js +91 -56
- package/dist/esm/decorators/query.js.map +2 -2
- package/dist/esm/decorators/queryAll.js +104 -66
- package/dist/esm/decorators/queryAll.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +6 -2
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +572 -320
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
- package/dist/types/decorators/addEventListener.d.ts +7 -6
- package/dist/types/decorators/addEventListener.d.ts.map +1 -1
- package/dist/types/decorators/applyAttribute.d.ts +13 -8
- package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
- package/dist/types/decorators/applyClass.d.ts +8 -7
- package/dist/types/decorators/applyClass.d.ts.map +1 -1
- package/dist/types/decorators/applyNode.d.ts +18 -17
- package/dist/types/decorators/applyNode.d.ts.map +1 -1
- package/dist/types/decorators/applyProperty.d.ts +14 -9
- package/dist/types/decorators/applyProperty.d.ts.map +1 -1
- package/dist/types/decorators/applyStyle.d.ts +6 -5
- package/dist/types/decorators/applyStyle.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/decorators/emitCustomEvent.d.ts +3 -2
- package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
- package/dist/types/decorators/lifecycles.d.ts +12 -13
- package/dist/types/decorators/lifecycles.d.ts.map +1 -1
- package/dist/types/decorators/query.d.ts +15 -5
- package/dist/types/decorators/query.d.ts.map +1 -1
- package/dist/types/decorators/queryAll.d.ts +15 -5
- package/dist/types/decorators/queryAll.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +572 -320
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
- package/package.json +3 -3
- package/src/decorators/addEventListener.ts +9 -7
- package/src/decorators/applyAttribute.ts +60 -27
- package/src/decorators/applyClass.ts +78 -32
- package/src/decorators/applyNode.ts +118 -73
- package/src/decorators/applyProperty.ts +63 -30
- package/src/decorators/applyStyle.ts +76 -30
- package/src/decorators/elementDefine.ts +57 -37
- package/src/decorators/emitCustomEvent.ts +63 -39
- package/src/decorators/lifecycles.ts +53 -52
- package/src/decorators/query.ts +111 -49
- package/src/decorators/queryAll.ts +121 -61
- package/src/elements/SwcAppMixin.ts +7 -3
- package/src/types/window.d.ts +3 -0
- package/dist/cjs/examples/RxJSOperatorsExample.js +0 -285
- package/dist/cjs/examples/RxJSOperatorsExample.js.map +0 -7
- package/dist/esm/examples/RxJSOperatorsExample.js +0 -266
- package/dist/esm/examples/RxJSOperatorsExample.js.map +0 -7
- package/dist/types/examples/RxJSOperatorsExample.d.ts +0 -94
- package/dist/types/examples/RxJSOperatorsExample.d.ts.map +0 -1
- package/src/examples/RxJSOperatorsExample.ts +0 -279
|
@@ -3,6 +3,8 @@ import { SpecialSelector, SwcQueryOptions, HelperHostSet } from '../types';
|
|
|
3
3
|
import {ensureInit, getElementConfig} from './elementDefine';
|
|
4
4
|
import {SwcUtils} from '../utils/Utils';
|
|
5
5
|
|
|
6
|
+
export type EmitCustomEventSelector = string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
|
|
7
|
+
|
|
6
8
|
export interface EmitCustomEventBaseOptions {
|
|
7
9
|
bubbles?: boolean;
|
|
8
10
|
composed?: boolean;
|
|
@@ -30,7 +32,7 @@ type Options = (EmitCustomEventBaseOptions & SwcQueryOptions) | (EmitCustomEvent
|
|
|
30
32
|
|
|
31
33
|
export interface EmitCustomEventMetadata {
|
|
32
34
|
propertyKey: string | symbol;
|
|
33
|
-
selector:
|
|
35
|
+
selector: EmitCustomEventSelector;
|
|
34
36
|
type: string;
|
|
35
37
|
options: Options;
|
|
36
38
|
}
|
|
@@ -38,7 +40,7 @@ export interface EmitCustomEventMetadata {
|
|
|
38
40
|
export const EMIT_CUSTOM_EVENT_METADATA_KEY = Symbol.for('simple-web-component:emit-custom-event');
|
|
39
41
|
|
|
40
42
|
export function emitCustomEvent(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
|
|
41
|
-
export function emitCustomEvent(selector:
|
|
43
|
+
export function emitCustomEvent(selector: EmitCustomEventSelector, type: string, options?: Options): MethodDecorator;
|
|
42
44
|
export function emitCustomEvent(type: string, options?: Options): MethodDecorator;
|
|
43
45
|
/**
|
|
44
46
|
* @emitCustomEvent decorator to dispatch custom events to a target.
|
|
@@ -46,6 +48,7 @@ export function emitCustomEvent(type: string, options?: Options): MethodDecorato
|
|
|
46
48
|
* Usage:
|
|
47
49
|
* - @emitCustomEvent('$this', 'event-name', options) - Emit from $this
|
|
48
50
|
* - @emitCustomEvent('$appHost', 'event-name', options) - Emit from $appHost
|
|
51
|
+
* - @emitCustomEvent((this, helper) => '.button', 'event-name', options) - Function-based selector
|
|
49
52
|
* - @emitCustomEvent('event-name', options) - Emit from $this (defaults to $this)
|
|
50
53
|
* - @emitCustomEvent('event-name') - Emit from $this with no options
|
|
51
54
|
*/
|
|
@@ -56,7 +59,7 @@ export function emitCustomEvent(selectorOrTarget: any, typeOrPropertyKey?: any,
|
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
// Case 2: With selector and type - @emitCustomEvent('selector', 'event-name', options)
|
|
59
|
-
if (typeof selectorOrTarget === 'string' && typeof typeOrPropertyKey === 'string') {
|
|
62
|
+
if ((typeof selectorOrTarget === 'string' || typeof selectorOrTarget === 'function') && typeof typeOrPropertyKey === 'string') {
|
|
60
63
|
return createEmitDecorator(selectorOrTarget, typeOrPropertyKey, optionsOrDescriptor as Options);
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -69,7 +72,7 @@ export function emitCustomEvent(selectorOrTarget: any, typeOrPropertyKey?: any,
|
|
|
69
72
|
throw new Error('Invalid @emitCustomEvent usage');
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
function createEmitDecorator(selector:
|
|
75
|
+
function createEmitDecorator(selector: EmitCustomEventSelector, type: string, options?: Options) {
|
|
73
76
|
return (targetObj: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
|
|
74
77
|
const constructor = targetObj.constructor;
|
|
75
78
|
|
|
@@ -98,47 +101,68 @@ function createEmitDecorator(selector: string, type: string, options?: Options)
|
|
|
98
101
|
cancelable: fullOptions.cancelable
|
|
99
102
|
});
|
|
100
103
|
|
|
101
|
-
const hostSet = SwcUtils.getHostSet(this as any);
|
|
102
104
|
const conf = getElementConfig(this);
|
|
103
105
|
const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
|
|
106
|
+
const hostSet = SwcUtils.getHelperAndHostSet(currentWin, this as any);
|
|
104
107
|
|
|
105
108
|
const eventTargets: EventTarget[] = [];
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
} else if (
|
|
117
|
-
|
|
118
|
-
} else if (
|
|
119
|
-
|
|
120
|
-
} else if (
|
|
121
|
-
|
|
122
|
-
} else if (selector === '$hosts') {
|
|
123
|
-
hostSet.$hosts.forEach(h => eventTargets.push(h));
|
|
124
|
-
} else if (selector === '$appHosts') {
|
|
125
|
-
hostSet.$appHosts.forEach(h => eventTargets.push(h));
|
|
126
|
-
} else if (selector === '$this' || !selector) {
|
|
127
|
-
eventTargets.push(this as any);
|
|
109
|
+
|
|
110
|
+
// Resolve selector if it's a function
|
|
111
|
+
let resolvedSelector: string | Element | NodeList | Element[] | null = selector as any;
|
|
112
|
+
if (typeof selector === 'function') {
|
|
113
|
+
resolvedSelector = selector(this, hostSet);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// If selector function returned elements directly, use them
|
|
117
|
+
if (resolvedSelector instanceof currentWin.Element) {
|
|
118
|
+
eventTargets.push(resolvedSelector as EventTarget);
|
|
119
|
+
} else if (resolvedSelector instanceof currentWin.NodeList) {
|
|
120
|
+
eventTargets.push(...Array.from(resolvedSelector as EventTarget[]));
|
|
121
|
+
} else if (Array.isArray(resolvedSelector)) {
|
|
122
|
+
eventTargets.push(...(resolvedSelector as EventTarget[]));
|
|
123
|
+
} else if (resolvedSelector === null) {
|
|
124
|
+
// No targets
|
|
128
125
|
} else {
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
else if (
|
|
134
|
-
else if (
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
// Handle string selector
|
|
127
|
+
const stringSelector = resolvedSelector as string;
|
|
128
|
+
|
|
129
|
+
if (stringSelector === '$window') eventTargets.push(currentWin);
|
|
130
|
+
else if (stringSelector === '$document') eventTargets.push(currentWin.document);
|
|
131
|
+
else if (stringSelector === '$host') {
|
|
132
|
+
if (hostSet.$host) eventTargets.push(hostSet.$host);
|
|
133
|
+
} else if (stringSelector === '$parentHost') {
|
|
134
|
+
if (hostSet.$parentHost) eventTargets.push(hostSet.$parentHost);
|
|
135
|
+
} else if (stringSelector === '$appHost') {
|
|
136
|
+
if (hostSet.$appHost) eventTargets.push(hostSet.$appHost);
|
|
137
|
+
} else if (stringSelector === '$firstHost') {
|
|
138
|
+
if (hostSet.$firstHost) eventTargets.push(hostSet.$firstHost);
|
|
139
|
+
} else if (stringSelector === '$lastHost') {
|
|
140
|
+
if (hostSet.$lastHost) eventTargets.push(hostSet.$lastHost);
|
|
141
|
+
} else if (stringSelector === '$firstAppHost') {
|
|
142
|
+
if (hostSet.$firstAppHost) eventTargets.push(hostSet.$firstAppHost);
|
|
143
|
+
} else if (stringSelector === '$lastAppHost') {
|
|
144
|
+
if (hostSet.$lastAppHost) eventTargets.push(hostSet.$lastAppHost);
|
|
145
|
+
} else if (stringSelector === '$hosts') {
|
|
146
|
+
hostSet.$hosts.forEach(h => eventTargets.push(h));
|
|
147
|
+
} else if (stringSelector === '$appHosts') {
|
|
148
|
+
hostSet.$appHosts.forEach(h => eventTargets.push(h));
|
|
149
|
+
} else if (stringSelector === '$this' || !stringSelector) {
|
|
150
|
+
eventTargets.push(this as any);
|
|
151
|
+
} else {
|
|
152
|
+
const r = fullOptions.root || 'auto';
|
|
153
|
+
const searchRoots: (HTMLElement | ShadowRoot)[] = [];
|
|
154
|
+
if (r === 'auto') searchRoots.push(this.shadowRoot || (this as any));
|
|
155
|
+
else if (r === 'light') searchRoots.push(this as any);
|
|
156
|
+
else if (r === 'shadow' && this.shadowRoot) searchRoots.push(this.shadowRoot);
|
|
157
|
+
else if (r === 'all') {
|
|
158
|
+
searchRoots.push(this as any);
|
|
159
|
+
if (this.shadowRoot) searchRoots.push(this.shadowRoot);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
searchRoots.forEach(sr => {
|
|
163
|
+
sr.querySelectorAll(stringSelector).forEach(el => eventTargets.push(el));
|
|
164
|
+
});
|
|
137
165
|
}
|
|
138
|
-
|
|
139
|
-
searchRoots.forEach(sr => {
|
|
140
|
-
sr.querySelectorAll(selector).forEach(el => eventTargets.push(el));
|
|
141
|
-
});
|
|
142
166
|
}
|
|
143
167
|
|
|
144
168
|
eventTargets.forEach(t => {
|
|
@@ -8,24 +8,25 @@ export const ON_AFTER_DISCONNECTED_METADATA_KEY = Symbol.for('simple-web-compone
|
|
|
8
8
|
export const ON_BEFORE_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-before-adopted');
|
|
9
9
|
export const ON_AFTER_ADOPTED_METADATA_KEY = Symbol.for('simple-web-component:on-after-adopted');
|
|
10
10
|
export const ON_ADD_EVENT_LISTENER_METADATA_KEY = Symbol.for('simple-web-component:on-add-event-listener');
|
|
11
|
-
export const
|
|
11
|
+
export const ON_CONNECTED_BODY_METADATA_KEY = Symbol.for('simple-web-component:on-connected-body');
|
|
12
12
|
export const ON_CONNECTED_SWC_APP_METADATA_KEY = Symbol.for('simple-web-component:on-connected-swc-app');
|
|
13
13
|
export const ON_CONNECTED_COMPLETED_METADATA_KEY = Symbol.for('simple-web-component:on-completed');
|
|
14
14
|
|
|
15
15
|
export const ATTRIBUTE_CHANGED_WILDCARD = '*';
|
|
16
16
|
|
|
17
|
-
export interface
|
|
18
|
-
ssrFirst?: boolean;
|
|
17
|
+
export interface OnConnectedAppendChildOptions {
|
|
18
|
+
// ssrFirst?: boolean;
|
|
19
19
|
// replaceWrap?:{ start: string, end:string},
|
|
20
20
|
useShadow?: boolean;
|
|
21
|
+
order?: number;
|
|
21
22
|
}
|
|
22
|
-
export interface
|
|
23
|
+
export interface OnConnectedAppendChildOptionsMetadata {
|
|
23
24
|
propertyKey: string | symbol;
|
|
24
|
-
options:
|
|
25
|
+
options: OnConnectedAppendChildOptions;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export interface OnConnectedOptions {
|
|
28
|
-
ssrFirst?: boolean;
|
|
29
|
+
// ssrFirst?: boolean;
|
|
29
30
|
order?: number;
|
|
30
31
|
}
|
|
31
32
|
export interface OnConnectedMetadata {
|
|
@@ -87,33 +88,33 @@ export function onConnectedAfter(arg1?: OnConnectedOptions | Object, arg2?: stri
|
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
|
|
90
|
-
function createLifecycleDecorator(metadataKey: symbol): ((options?: LifecycleOptions) => MethodDecorator) & MethodDecorator {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
91
|
+
// function createLifecycleDecorator(metadataKey: symbol): ((options?: LifecycleOptions) => MethodDecorator) & MethodDecorator {
|
|
92
|
+
// const decorator = (options?: LifecycleOptions): MethodDecorator => {
|
|
93
|
+
// return (target: Object, propertyKey: string | symbol) => {
|
|
94
|
+
// const constructor = target.constructor;
|
|
95
|
+
// let list = ReflectUtils.getOwnMetadata(metadataKey, constructor) as LifecycleMetadata[];
|
|
96
|
+
// if (!list) {
|
|
97
|
+
// list = [];
|
|
98
|
+
// ReflectUtils.defineMetadata(metadataKey, list, constructor);
|
|
99
|
+
// }
|
|
100
|
+
// list.push({ propertyKey, order: options?.order ?? 0 });
|
|
101
|
+
// };
|
|
102
|
+
// };
|
|
103
|
+
//
|
|
104
|
+
// // Support both @decorator and @decorator() syntax
|
|
105
|
+
// return Object.assign(
|
|
106
|
+
// (target: Object, propertyKey: string | symbol) => {
|
|
107
|
+
// const constructor = target.constructor;
|
|
108
|
+
// let list = ReflectUtils.getOwnMetadata(metadataKey, constructor) as LifecycleMetadata[];
|
|
109
|
+
// if (!list) {
|
|
110
|
+
// list = [];
|
|
111
|
+
// ReflectUtils.defineMetadata(metadataKey, list, constructor);
|
|
112
|
+
// }
|
|
113
|
+
// list.push({ propertyKey, order: 0 });
|
|
114
|
+
// },
|
|
115
|
+
// { __isDecorator: true, __decorator: decorator }
|
|
116
|
+
// ) as any;
|
|
117
|
+
// }
|
|
117
118
|
|
|
118
119
|
// Helper to handle both @decorator and @decorator() syntax
|
|
119
120
|
function createLifecycleDecoratorWithOptions(metadataKey: symbol) {
|
|
@@ -193,19 +194,19 @@ export function onConnectedCompleted(optionOrTarget?: LifecycleOptions | Object,
|
|
|
193
194
|
|
|
194
195
|
|
|
195
196
|
|
|
196
|
-
const decorator = (options:
|
|
197
|
+
const decorator = (options: OnConnectedAppendChildOptions, target: Object, propertyKey: string | symbol) => {
|
|
197
198
|
const constructor = target.constructor;
|
|
198
|
-
let list = ReflectUtils.getMetadata<
|
|
199
|
+
let list = ReflectUtils.getMetadata<OnConnectedAppendChildOptionsMetadata[]>(ON_CONNECTED_BODY_METADATA_KEY, constructor);
|
|
199
200
|
if (!list) {
|
|
200
201
|
list = [];
|
|
201
|
-
ReflectUtils.defineMetadata(
|
|
202
|
+
ReflectUtils.defineMetadata(ON_CONNECTED_BODY_METADATA_KEY, list, constructor);
|
|
202
203
|
}
|
|
203
204
|
list.push({ propertyKey, options });
|
|
204
205
|
};
|
|
205
206
|
|
|
206
|
-
export function
|
|
207
|
-
export function
|
|
208
|
-
export function
|
|
207
|
+
export function onConnectedBodyShadow(options: Omit<OnConnectedAppendChildOptions, 'useShadow'>): MethodDecorator; // 파라미터있음
|
|
208
|
+
export function onConnectedBodyShadow(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void; // 파라미터없음
|
|
209
|
+
export function onConnectedBodyShadow(optionOrTarget: Omit<OnConnectedAppendChildOptions, 'useShadow'> | Object, propertyKey?: string | symbol, arg3?: PropertyDescriptor): MethodDecorator | void {
|
|
209
210
|
if (propertyKey) { // no parameter option @decorator
|
|
210
211
|
return decorator({useShadow: true}, optionOrTarget!, propertyKey);
|
|
211
212
|
}
|
|
@@ -215,9 +216,9 @@ export function onConnectedShadow(optionOrTarget: Omit<InnerHtmlOptions, 'useSha
|
|
|
215
216
|
};
|
|
216
217
|
}
|
|
217
218
|
|
|
218
|
-
export function
|
|
219
|
-
export function
|
|
220
|
-
export function
|
|
219
|
+
export function onConnectedBodyLight(options: Omit<OnConnectedAppendChildOptions, 'useShadow'>): MethodDecorator; // 파라미터있음
|
|
220
|
+
export function onConnectedBodyLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void; // 파라미터없음
|
|
221
|
+
export function onConnectedBodyLight(optionOrTarget: Omit<OnConnectedAppendChildOptions, 'useShadow'> | Object, propertyKey?: string | symbol, arg3?: PropertyDescriptor): MethodDecorator | void {
|
|
221
222
|
if (propertyKey) { // no parameter option @decorator
|
|
222
223
|
return decorator({useShadow: false}, optionOrTarget!, propertyKey);
|
|
223
224
|
}
|
|
@@ -226,15 +227,15 @@ export function onConnectedLight(optionOrTarget: Omit<InnerHtmlOptions, 'useShad
|
|
|
226
227
|
decorator({...optionOrTarget??{}, useShadow: false}, target, propertyKey);
|
|
227
228
|
};
|
|
228
229
|
}
|
|
229
|
-
export function
|
|
230
|
-
export function
|
|
231
|
-
export function
|
|
230
|
+
export function onConnectedBody(options: OnConnectedAppendChildOptions): MethodDecorator;
|
|
231
|
+
export function onConnectedBody(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void;
|
|
232
|
+
export function onConnectedBody(optionOrTarget: OnConnectedAppendChildOptions | Object, propertyKey?: string | symbol, arg3?: PropertyDescriptor): MethodDecorator | void {
|
|
232
233
|
if (propertyKey) { // no parameter option @decorator
|
|
233
234
|
return decorator({}, optionOrTarget!, propertyKey);
|
|
234
235
|
}
|
|
235
236
|
// parameter option @decorator()
|
|
236
237
|
return (target: Object, propertyKey: string | symbol) => {
|
|
237
|
-
decorator((optionOrTarget as
|
|
238
|
+
decorator((optionOrTarget as OnConnectedAppendChildOptions) || {}, target, propertyKey);
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
241
|
|
|
@@ -248,27 +249,27 @@ export const findAllLifecycleMetadata = (target: any, metadataKey: symbol): Life
|
|
|
248
249
|
return [...results].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
249
250
|
};
|
|
250
251
|
|
|
251
|
-
export const findAllOnConnectedMetadata = (target: any):
|
|
252
|
+
export const findAllOnConnectedMetadata = (target: any): OnConnectedAppendChildOptionsMetadata[] => {
|
|
252
253
|
const constructor = target instanceof Function ? target : target.constructor;
|
|
253
|
-
const results = ReflectUtils.getMetadata(
|
|
254
|
+
const results = ReflectUtils.getMetadata<OnConnectedAppendChildOptionsMetadata[]>(ON_CONNECTED_BODY_METADATA_KEY, constructor) ?? [];
|
|
254
255
|
// Sort by order (default 0 if not specified)
|
|
255
256
|
return [...results].sort((a, b) => {
|
|
256
|
-
const orderA =
|
|
257
|
-
const orderB =
|
|
257
|
+
const orderA = a.options?.order ?? 0;
|
|
258
|
+
const orderB = b.options?.order ?? 0;
|
|
258
259
|
return orderA - orderB;
|
|
259
260
|
});
|
|
260
261
|
};
|
|
261
262
|
|
|
262
263
|
export const findAllOnConnectedBeforeMetadata = (target: any): OnConnectedMetadata[] => {
|
|
263
264
|
const constructor = target instanceof Function ? target : target.constructor;
|
|
264
|
-
const results = ReflectUtils.getMetadata(ON_BEFORE_CONNECTED_METADATA_KEY, constructor) ?? [];
|
|
265
|
+
const results = ReflectUtils.getMetadata<OnConnectedMetadata[]>(ON_BEFORE_CONNECTED_METADATA_KEY, constructor) ?? [];
|
|
265
266
|
// Sort by order
|
|
266
267
|
return [...results].sort((a, b) => (a.options?.order ?? 0) - (b.options?.order ?? 0));
|
|
267
268
|
};
|
|
268
269
|
|
|
269
270
|
export const findAllOnConnectedAfterMetadata = (target: any): OnConnectedMetadata[] => {
|
|
270
271
|
const constructor = target instanceof Function ? target : target.constructor;
|
|
271
|
-
const results = ReflectUtils.getMetadata(ON_AFTER_CONNECTED_METADATA_KEY, constructor) ?? [];
|
|
272
|
+
const results = ReflectUtils.getMetadata<OnConnectedMetadata[]>(ON_AFTER_CONNECTED_METADATA_KEY, constructor) ?? [];
|
|
272
273
|
// Sort by order
|
|
273
274
|
return [...results].sort((a, b) => (a.options?.order ?? 0) - (b.options?.order ?? 0));
|
|
274
275
|
};
|
package/src/decorators/query.ts
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
1
|
import { ReflectUtils } from '@dooboostore/core';
|
|
2
2
|
import { getElementConfig, ensureInit } from './elementDefine';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
|
-
import {
|
|
4
|
+
import { SwcQueryOptions, HelperHostSet } from '../types';
|
|
5
|
+
|
|
6
|
+
export interface QueryOptions extends SwcQueryOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Filter function to determine whether to include the element.
|
|
9
|
+
* If it returns false, the element is skipped.
|
|
10
|
+
*/
|
|
11
|
+
filter?: (target: HTMLElement, meta: { currentThis: any, helper: HelperHostSet }) => boolean;
|
|
12
|
+
}
|
|
5
13
|
|
|
6
14
|
export interface QueryMetadata {
|
|
7
15
|
propertyKey: string | symbol;
|
|
8
|
-
selector: string;
|
|
9
|
-
options:
|
|
16
|
+
selector: string | ((currentThis: any, helper: HelperHostSet) => Node | NodeList | Element | Element[] | null);
|
|
17
|
+
options: QueryOptions ;
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
export const QUERY_METADATA_KEY = Symbol.for('simple-web-component:query');
|
|
13
21
|
|
|
14
22
|
export function query(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): PropertyDescriptor | void;
|
|
15
|
-
export function query(selector: string, options?:
|
|
16
|
-
export function query(options?:
|
|
23
|
+
export function query(selector: string | ((currentThis: any, helper: HelperHostSet) => Node | NodeList | Element | Element[] | null), options?: QueryOptions): PropertyDecorator;
|
|
24
|
+
export function query(options?: QueryOptions): PropertyDecorator;
|
|
17
25
|
/**
|
|
18
26
|
* @query decorator to inject a single element into a class property.
|
|
27
|
+
*
|
|
28
|
+
* Supports both string selectors and function-based selectors:
|
|
29
|
+
* - String selector: @query('#my-element')
|
|
30
|
+
* - Function selector: @query((currentThis, helper) => currentThis.shadowRoot?.querySelector('.item'))
|
|
31
|
+
*
|
|
32
|
+
* Supports filtering:
|
|
33
|
+
* - @query('#my-element', { filter: (target, meta) => target.hasAttribute('active') })
|
|
19
34
|
*/
|
|
20
|
-
export function query(selectorOrTarget?: string | Object, optionsOrPropertyKey?:
|
|
35
|
+
export function query(selectorOrTarget?: string | ((currentThis: any, helper: HelperHostSet) => Node | NodeList | Element | Element[] | null) | Object, optionsOrPropertyKey?: QueryOptions | string | symbol, descriptor?: PropertyDescriptor): any {
|
|
21
36
|
// Bare decorator: @query
|
|
22
37
|
if (descriptor !== undefined && (typeof optionsOrPropertyKey === 'string' || typeof optionsOrPropertyKey === 'symbol')) {
|
|
23
38
|
throw new Error(`@query decorator cannot be used on methods. (Method: ${String(optionsOrPropertyKey)})`);
|
|
24
39
|
}
|
|
25
40
|
// With selector
|
|
26
|
-
if (typeof selectorOrTarget === 'string') {
|
|
41
|
+
if (typeof selectorOrTarget === 'string' || typeof selectorOrTarget === 'function') {
|
|
27
42
|
return (targetObj: Object, propertyKey: string | symbol, descriptor?: never): void => {
|
|
28
43
|
if (descriptor !== undefined) {
|
|
29
44
|
throw new Error(`@query decorator cannot be used on methods. (Method: ${String(propertyKey)})`);
|
|
@@ -35,67 +50,114 @@ export function query(selectorOrTarget?: string | Object, optionsOrPropertyKey?:
|
|
|
35
50
|
queries = [];
|
|
36
51
|
ReflectUtils.defineMetadata(QUERY_METADATA_KEY, queries, constructor);
|
|
37
52
|
}
|
|
38
|
-
queries.push({ propertyKey, selector: selectorOrTarget, options: optionsOrPropertyKey as
|
|
53
|
+
queries.push({ propertyKey, selector: selectorOrTarget as any, options: optionsOrPropertyKey as QueryOptions || {} });
|
|
39
54
|
|
|
40
55
|
Object.defineProperty(targetObj, propertyKey, {
|
|
41
56
|
get(this: HTMLElement) {
|
|
42
57
|
ensureInit(this);
|
|
43
|
-
const selector = selectorOrTarget;
|
|
44
|
-
|
|
45
|
-
const r = (optionsOrPropertyKey as SwcQueryOptions)?.root || 'auto';
|
|
46
|
-
const applyRoot = (t: any) => {
|
|
47
|
-
if (!t || !(t instanceof HTMLElement)) return t;
|
|
48
|
-
if (r === 'auto') return t.shadowRoot || t;
|
|
49
|
-
if (r === 'shadow') return t.shadowRoot;
|
|
50
|
-
if (r === 'light') return t;
|
|
51
|
-
if (r === 'all') return t.shadowRoot || t;
|
|
52
|
-
return t;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// --- Special Selectors: HostSet ---
|
|
56
|
-
const hostSet = SwcUtils.getHostSet(this);
|
|
57
|
-
if (selector === '$this') return applyRoot(this);
|
|
58
|
-
if (selector === '$host') return applyRoot(hostSet.$host);
|
|
59
|
-
if (selector === '$parentHost') return applyRoot(hostSet.$parentHost);
|
|
60
|
-
if (selector === '$appHost') return applyRoot(hostSet.$appHost);
|
|
61
|
-
if (selector === '$firstHost') return applyRoot(hostSet.$firstHost);
|
|
62
|
-
if (selector === '$lastHost') return applyRoot(hostSet.$lastHost);
|
|
63
|
-
if (selector === '$firstAppHost') return applyRoot(hostSet.$firstAppHost);
|
|
64
|
-
if (selector === '$lastAppHost') return applyRoot(hostSet.$lastAppHost);
|
|
65
|
-
|
|
66
|
-
// --- Special Selectors: Env ---
|
|
67
58
|
const config = getElementConfig(this);
|
|
68
59
|
const win = config?.window || window;
|
|
69
|
-
|
|
70
|
-
|
|
60
|
+
const hostSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
61
|
+
|
|
62
|
+
// Resolve selector - can be string or function
|
|
63
|
+
let resolvedSelector: string;
|
|
64
|
+
let resolvedElement: HTMLElement | null = null;
|
|
65
|
+
|
|
66
|
+
if (typeof selectorOrTarget === 'function') {
|
|
67
|
+
const result = (selectorOrTarget as any)(this, hostSet);
|
|
68
|
+
// If function returns a Node/Element, return it directly
|
|
69
|
+
if (result instanceof win.Node || result instanceof win.Element) {
|
|
70
|
+
resolvedElement = result instanceof win.HTMLElement ? (result as HTMLElement) : null;
|
|
71
|
+
}
|
|
72
|
+
// If function returns NodeList or Element[], return first element
|
|
73
|
+
else if (result instanceof win.NodeList || Array.isArray(result)) {
|
|
74
|
+
resolvedElement = result.length > 0 && result[0] instanceof win.HTMLElement ? (result[0] as HTMLElement) : null;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
resolvedSelector = selectorOrTarget;
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const r = (optionsOrPropertyKey as QueryOptions)?.root || 'auto';
|
|
80
|
+
const applyRoot = (t: any) => {
|
|
81
|
+
if (!t || !(t instanceof HTMLElement)) return t;
|
|
82
|
+
if (r === 'auto') return t.shadowRoot || t;
|
|
83
|
+
if (r === 'shadow') return t.shadowRoot;
|
|
84
|
+
if (r === 'light') return t;
|
|
85
|
+
if (r === 'all') return t.shadowRoot || t;
|
|
86
|
+
return t;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// --- Special Selectors: HostSet ---
|
|
90
|
+
if (resolvedSelector === '$this') resolvedElement = applyRoot(this);
|
|
91
|
+
else if (resolvedSelector === '$host') resolvedElement = applyRoot(hostSet.$host);
|
|
92
|
+
else if (resolvedSelector === '$parentHost') resolvedElement = applyRoot(hostSet.$parentHost);
|
|
93
|
+
else if (resolvedSelector === '$appHost') resolvedElement = applyRoot(hostSet.$appHost);
|
|
94
|
+
else if (resolvedSelector === '$firstHost') resolvedElement = applyRoot(hostSet.$firstHost);
|
|
95
|
+
else if (resolvedSelector === '$lastHost') resolvedElement = applyRoot(hostSet.$lastHost);
|
|
96
|
+
else if (resolvedSelector === '$firstAppHost') resolvedElement = applyRoot(hostSet.$firstAppHost);
|
|
97
|
+
else if (resolvedSelector === '$lastAppHost') resolvedElement = applyRoot(hostSet.$lastAppHost);
|
|
98
|
+
// --- Special Selectors: Env ---
|
|
99
|
+
else if (resolvedSelector === '$window') return win;
|
|
100
|
+
else if (resolvedSelector === '$document') return win.document;
|
|
101
|
+
// --- Standard Selectors ---
|
|
102
|
+
else {
|
|
103
|
+
if (r === 'shadow') resolvedElement = this.shadowRoot ? (this.shadowRoot.querySelector(resolvedSelector) as HTMLElement | null) : null;
|
|
104
|
+
else if (r === 'light') resolvedElement = this.querySelector(resolvedSelector) as HTMLElement | null;
|
|
105
|
+
else if (r === 'all') {
|
|
106
|
+
const shadowMatch = this.shadowRoot ? (this.shadowRoot.querySelector(resolvedSelector) as HTMLElement | null) : null;
|
|
107
|
+
resolvedElement = shadowMatch || (this.querySelector(resolvedSelector) as HTMLElement | null);
|
|
108
|
+
}
|
|
109
|
+
else resolvedElement = ((this.shadowRoot || this).querySelector(resolvedSelector) as HTMLElement | null);
|
|
110
|
+
}
|
|
78
111
|
}
|
|
79
|
-
|
|
112
|
+
|
|
113
|
+
// Apply filter if provided
|
|
114
|
+
if (resolvedElement instanceof win.HTMLElement && (optionsOrPropertyKey as QueryOptions)?.filter) {
|
|
115
|
+
const shouldInclude = (optionsOrPropertyKey as QueryOptions).filter!(resolvedElement, { currentThis: this, helper: hostSet });
|
|
116
|
+
if (!shouldInclude) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return resolvedElement;
|
|
80
122
|
},
|
|
81
123
|
set(this: HTMLElement, nv: any) {
|
|
82
124
|
ensureInit(this);
|
|
83
125
|
if (nv === null || nv === undefined) {
|
|
84
|
-
const
|
|
85
|
-
|
|
126
|
+
const config = getElementConfig(this);
|
|
127
|
+
const win = config?.window || window;
|
|
128
|
+
const hostSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
129
|
+
|
|
130
|
+
// Resolve selector - can be string or function
|
|
131
|
+
if (typeof selectorOrTarget === 'function') {
|
|
132
|
+
// Get the element from function and remove it
|
|
133
|
+
const result = (selectorOrTarget as any)(this, hostSet);
|
|
134
|
+
if (result instanceof win.Element) {
|
|
135
|
+
(result as Element).remove();
|
|
136
|
+
} else if (result instanceof win.NodeList || Array.isArray(result)) {
|
|
137
|
+
const el = result.length > 0 ? result[0] : null;
|
|
138
|
+
if (el instanceof win.Element) {
|
|
139
|
+
(el as Element).remove();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const resolvedSelector = selectorOrTarget;
|
|
146
|
+
|
|
147
|
+
if (resolvedSelector.startsWith('$') && resolvedSelector !== '$this') return;
|
|
86
148
|
|
|
87
|
-
const r = (optionsOrPropertyKey as
|
|
149
|
+
const r = (optionsOrPropertyKey as QueryOptions)?.root || 'auto';
|
|
88
150
|
const targets: Element[] = [];
|
|
89
151
|
|
|
90
152
|
if (r === 'shadow') {
|
|
91
|
-
if (this.shadowRoot?.querySelector(
|
|
153
|
+
if (this.shadowRoot?.querySelector(resolvedSelector)) targets.push(this.shadowRoot.querySelector(resolvedSelector)!);
|
|
92
154
|
} else if (r === 'light') {
|
|
93
|
-
if (this.querySelector(
|
|
155
|
+
if (this.querySelector(resolvedSelector)) targets.push(this.querySelector(resolvedSelector)!);
|
|
94
156
|
} else if (r === 'all') {
|
|
95
|
-
if (this.shadowRoot?.querySelector(
|
|
96
|
-
if (this.querySelector(
|
|
157
|
+
if (this.shadowRoot?.querySelector(resolvedSelector)) targets.push(this.shadowRoot.querySelector(resolvedSelector)!);
|
|
158
|
+
if (this.querySelector(resolvedSelector)) targets.push(this.querySelector(resolvedSelector)!);
|
|
97
159
|
} else {
|
|
98
|
-
const el = (this.shadowRoot || this).querySelector(
|
|
160
|
+
const el = (this.shadowRoot || this).querySelector(resolvedSelector);
|
|
99
161
|
if (el) targets.push(el);
|
|
100
162
|
}
|
|
101
163
|
|