@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.
Files changed (95) hide show
  1. package/README.md +25 -25
  2. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  3. package/dist/cjs/decorators/applyAttribute.js +36 -15
  4. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  5. package/dist/cjs/decorators/applyClass.js +53 -22
  6. package/dist/cjs/decorators/applyClass.js.map +2 -2
  7. package/dist/cjs/decorators/applyNode.js +54 -24
  8. package/dist/cjs/decorators/applyNode.js.map +2 -2
  9. package/dist/cjs/decorators/applyProperty.js +38 -17
  10. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  11. package/dist/cjs/decorators/applyStyle.js +53 -22
  12. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  13. package/dist/cjs/decorators/elementDefine.js +49 -33
  14. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  15. package/dist/cjs/decorators/emitCustomEvent.js +61 -47
  16. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  17. package/dist/cjs/decorators/lifecycles.js +11 -36
  18. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  19. package/dist/cjs/decorators/query.js +91 -56
  20. package/dist/cjs/decorators/query.js.map +2 -2
  21. package/dist/cjs/decorators/queryAll.js +104 -66
  22. package/dist/cjs/decorators/queryAll.js.map +2 -2
  23. package/dist/cjs/elements/SwcAppMixin.js +6 -2
  24. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  25. package/dist/cjs/types/window.d.js.map +1 -1
  26. package/dist/esm/decorators/addEventListener.js.map +2 -2
  27. package/dist/esm/decorators/applyAttribute.js +36 -15
  28. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  29. package/dist/esm/decorators/applyClass.js +53 -22
  30. package/dist/esm/decorators/applyClass.js.map +2 -2
  31. package/dist/esm/decorators/applyNode.js +54 -24
  32. package/dist/esm/decorators/applyNode.js.map +2 -2
  33. package/dist/esm/decorators/applyProperty.js +38 -17
  34. package/dist/esm/decorators/applyProperty.js.map +2 -2
  35. package/dist/esm/decorators/applyStyle.js +53 -22
  36. package/dist/esm/decorators/applyStyle.js.map +2 -2
  37. package/dist/esm/decorators/elementDefine.js +50 -34
  38. package/dist/esm/decorators/elementDefine.js.map +2 -2
  39. package/dist/esm/decorators/emitCustomEvent.js +61 -47
  40. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  41. package/dist/esm/decorators/lifecycles.js +11 -36
  42. package/dist/esm/decorators/lifecycles.js.map +2 -2
  43. package/dist/esm/decorators/query.js +91 -56
  44. package/dist/esm/decorators/query.js.map +2 -2
  45. package/dist/esm/decorators/queryAll.js +104 -66
  46. package/dist/esm/decorators/queryAll.js.map +2 -2
  47. package/dist/esm/elements/SwcAppMixin.js +6 -2
  48. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  49. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +572 -320
  50. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
  51. package/dist/types/decorators/addEventListener.d.ts +7 -6
  52. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  53. package/dist/types/decorators/applyAttribute.d.ts +13 -8
  54. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  55. package/dist/types/decorators/applyClass.d.ts +8 -7
  56. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  57. package/dist/types/decorators/applyNode.d.ts +18 -17
  58. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  59. package/dist/types/decorators/applyProperty.d.ts +14 -9
  60. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  61. package/dist/types/decorators/applyStyle.d.ts +6 -5
  62. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  63. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  64. package/dist/types/decorators/emitCustomEvent.d.ts +3 -2
  65. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  66. package/dist/types/decorators/lifecycles.d.ts +12 -13
  67. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  68. package/dist/types/decorators/query.d.ts +15 -5
  69. package/dist/types/decorators/query.d.ts.map +1 -1
  70. package/dist/types/decorators/queryAll.d.ts +15 -5
  71. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  72. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  73. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +572 -320
  74. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
  75. package/package.json +3 -3
  76. package/src/decorators/addEventListener.ts +9 -7
  77. package/src/decorators/applyAttribute.ts +60 -27
  78. package/src/decorators/applyClass.ts +78 -32
  79. package/src/decorators/applyNode.ts +118 -73
  80. package/src/decorators/applyProperty.ts +63 -30
  81. package/src/decorators/applyStyle.ts +76 -30
  82. package/src/decorators/elementDefine.ts +57 -37
  83. package/src/decorators/emitCustomEvent.ts +63 -39
  84. package/src/decorators/lifecycles.ts +53 -52
  85. package/src/decorators/query.ts +111 -49
  86. package/src/decorators/queryAll.ts +121 -61
  87. package/src/elements/SwcAppMixin.ts +7 -3
  88. package/src/types/window.d.ts +3 -0
  89. package/dist/cjs/examples/RxJSOperatorsExample.js +0 -285
  90. package/dist/cjs/examples/RxJSOperatorsExample.js.map +0 -7
  91. package/dist/esm/examples/RxJSOperatorsExample.js +0 -266
  92. package/dist/esm/examples/RxJSOperatorsExample.js.map +0 -7
  93. package/dist/types/examples/RxJSOperatorsExample.d.ts +0 -94
  94. package/dist/types/examples/RxJSOperatorsExample.d.ts.map +0 -1
  95. package/src/examples/RxJSOperatorsExample.ts +0 -279
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dooboostore/simple-web-component",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -93,9 +93,9 @@
93
93
  "webpack-cli": "^5.1.4",
94
94
  "webpack-dev-server": "^5.2.0",
95
95
  "@dooboostore/core": "1.0.32",
96
- "@dooboostore/core-web": "1.0.12",
96
+ "@dooboostore/core-node": "1.0.12",
97
97
  "@dooboostore/simple-boot": "1.0.56",
98
- "@dooboostore/core-node": "1.0.12"
98
+ "@dooboostore/core-web": "1.0.12"
99
99
  },
100
100
  "scripts": {
101
101
  "clean": "rm -rf dist",
@@ -17,9 +17,11 @@ export interface AddEventListenerBaseOptions<TEvent extends Event = Event> exten
17
17
  distinctUntilChanged?: boolean | ((prev: TEvent, curr: TEvent) => boolean);
18
18
  }
19
19
 
20
+ export type EventListenerSelector = string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
21
+
20
22
  export interface AddEventListenerMetadata<TEvent extends Event = Event> {
21
23
  propertyKey: string | symbol;
22
- selector: string;
24
+ selector: EventListenerSelector;
23
25
  type: string;
24
26
  options: AddEventListenerBaseOptions<TEvent> & SwcQueryOptions & { delegate?: boolean };
25
27
  }
@@ -27,11 +29,11 @@ export interface AddEventListenerMetadata<TEvent extends Event = Event> {
27
29
  export const ADD_EVENT_LISTENER_METADATA_KEY = Symbol.for('simple-web-component:add-event-listener');
28
30
 
29
31
  export function addEventListener<TEvent extends Event = Event>(target: SpecialSelector, type: string, options?: AddEventListenerBaseOptions<TEvent>): MethodDecorator;
30
- export function addEventListener<TEvent extends Event = Event>(selector: string, type: string, options?: AddEventListenerBaseOptions<TEvent> & SwcQueryOptions & { delegate?: boolean }): MethodDecorator;
32
+ export function addEventListener<TEvent extends Event = Event>(selector: EventListenerSelector, type: string, options?: AddEventListenerBaseOptions<TEvent> & SwcQueryOptions & { delegate?: boolean }): MethodDecorator;
31
33
  /**
32
34
  * @addEventListener decorator to bind events to elements.
33
35
  */
34
- export function addEventListener<TEvent extends Event = Event>(selectorOrTarget: string, type: string, options: any = {}): MethodDecorator {
36
+ export function addEventListener<TEvent extends Event = Event>(selectorOrTarget: EventListenerSelector, type: string, options: any = {}): MethodDecorator {
35
37
  return (targetObj: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
36
38
  const constructor = targetObj.constructor;
37
39
 
@@ -46,17 +48,17 @@ export function addEventListener<TEvent extends Event = Event>(selectorOrTarget:
46
48
  }
47
49
 
48
50
 
49
- export function addEventListenerDelegateLightDom<TEvent extends Event = Event>(selector: string, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
51
+ export function addEventListenerDelegateLightDom<TEvent extends Event = Event>(selector: EventListenerSelector, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
50
52
  return addEventListener<TEvent>(selector, type, {...options??{}, root:'light', delegate: true});
51
53
  }
52
54
 
53
- export function addEventListenerDelegateShadowDom<TEvent extends Event = Event>(selector: string, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
55
+ export function addEventListenerDelegateShadowDom<TEvent extends Event = Event>(selector: EventListenerSelector, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
54
56
  return addEventListener<TEvent>(selector, type, {...options??{}, root:'shadow', delegate: true});
55
57
  }
56
- export function addEventListenerDelegateAllDom<TEvent extends Event = Event>(selector: string, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
58
+ export function addEventListenerDelegateAllDom<TEvent extends Event = Event>(selector: EventListenerSelector, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
57
59
  return addEventListener<TEvent>(selector, type, {...options??{}, root:'all', delegate: true});
58
60
  }
59
- export function addEventListenerDelegate<TEvent extends Event = Event>(selector: string, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
61
+ export function addEventListenerDelegate<TEvent extends Event = Event>(selector: EventListenerSelector, type: string, options?: Omit<AddEventListenerBaseOptions<TEvent>, 'delegate'>): MethodDecorator {
60
62
  return addEventListener<TEvent>(selector, type, {...options??{}, root:'auto', delegate: true});
61
63
  }
62
64
 
@@ -40,9 +40,11 @@ export interface AttributeOptions extends SwcQueryOptions {
40
40
  valueKey?: symbol | string;
41
41
  }
42
42
 
43
+ export type AttributeSelector = string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
44
+
43
45
  export interface AttributeMetadata {
44
46
  propertyKey: string | symbol;
45
- selector: string;
47
+ selector: AttributeSelector;
46
48
  targetAttributeName: string;
47
49
  options: AttributeOptions;
48
50
  type: 'property' | 'method';
@@ -93,7 +95,7 @@ const convertValue = (val: string | null, type: any): any => {
93
95
 
94
96
  export {convertValue};
95
97
 
96
- export const getAttributeValue = (inst: any, attrName: string, options?: AttributeOptions & { selector?: string }): any => {
98
+ export const getAttributeValue = (inst: any, attrName: string, options?: AttributeOptions & { selector?: AttributeSelector }): any => {
97
99
  const conf = getElementConfig(inst);
98
100
  const currentWin = inst._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
99
101
 
@@ -131,15 +133,42 @@ export const getAttributeValue = (inst: any, attrName: string, options?: Attribu
131
133
 
132
134
  /**
133
135
  * Resolve target elements based on selector and options
134
- * Handles special selectors ($this, $host, etc.) and CSS selectors
136
+ * Handles special selectors ($this, $host, etc.), CSS selectors, and function-based selectors
135
137
  * Returns HTMLElement[] for attribute operations
136
138
  */
137
- export const resolveAttributeTargets = (inst: any, selector: string, options: AttributeOptions): HTMLElement[] => {
139
+ export const resolveAttributeTargets = (inst: any, selector: AttributeSelector, options: AttributeOptions): HTMLElement[] => {
138
140
  const conf = getElementConfig(inst);
139
141
  const currentWin = conf.window;
140
142
  const r = options.root || 'auto';
141
143
  const results: HTMLElement[] = [];
142
144
 
145
+ // Resolve selector if it's a function
146
+ let resolvedSelector: string | Element | NodeList | Element[] | null = selector as any;
147
+ if (typeof selector === 'function') {
148
+ const hostSet = SwcUtils.getHelperAndHostSet(currentWin, inst);
149
+ resolvedSelector = selector(inst, hostSet);
150
+ }
151
+
152
+ // If selector function returned elements directly, use them
153
+ if (resolvedSelector instanceof currentWin.Element) {
154
+ results.push(resolvedSelector as HTMLElement);
155
+ return results;
156
+ }
157
+ if (resolvedSelector instanceof currentWin.NodeList) {
158
+ results.push(...(Array.from(resolvedSelector) as HTMLElement[]));
159
+ return results;
160
+ }
161
+ if (Array.isArray(resolvedSelector)) {
162
+ results.push(...(resolvedSelector as HTMLElement[]));
163
+ return results;
164
+ }
165
+ if (resolvedSelector === null) {
166
+ return results;
167
+ }
168
+
169
+ // Handle string selector
170
+ const stringSelector = resolvedSelector as string;
171
+
143
172
  const applyRoot = (target: any) => {
144
173
  if (!target) return;
145
174
  if (r === 'auto') {
@@ -150,33 +179,33 @@ export const resolveAttributeTargets = (inst: any, selector: string, options: At
150
179
  }
151
180
  };
152
181
 
153
- if (selector === '$this' || !selector) {
182
+ if (stringSelector === '$this' || !stringSelector) {
154
183
  applyRoot(inst);
155
184
  } else {
156
185
  const hostSet = SwcUtils.getHostSet(inst);
157
- if (selector === '$host') applyRoot(hostSet.$host);
158
- else if (selector === '$parentHost') applyRoot(hostSet.$parentHost);
159
- else if (selector === '$appHost') applyRoot(hostSet.$appHost as any);
160
- else if (selector === '$firstHost') applyRoot(hostSet.$firstHost);
161
- else if (selector === '$lastHost') applyRoot(hostSet.$lastHost);
162
- else if (selector === '$firstAppHost') applyRoot(hostSet.$firstAppHost as any);
163
- else if (selector === '$lastAppHost') applyRoot(hostSet.$lastAppHost as any);
164
- else if (selector === '$hosts') hostSet.$hosts.forEach(applyRoot);
165
- else if (selector === '$appHosts') hostSet.$appHosts.forEach(applyRoot);
186
+ if (stringSelector === '$host') applyRoot(hostSet.$host);
187
+ else if (stringSelector === '$parentHost') applyRoot(hostSet.$parentHost);
188
+ else if (stringSelector === '$appHost') applyRoot(hostSet.$appHost as any);
189
+ else if (stringSelector === '$firstHost') applyRoot(hostSet.$firstHost);
190
+ else if (stringSelector === '$lastHost') applyRoot(hostSet.$lastHost);
191
+ else if (stringSelector === '$firstAppHost') applyRoot(hostSet.$firstAppHost as any);
192
+ else if (stringSelector === '$lastAppHost') applyRoot(hostSet.$lastAppHost as any);
193
+ else if (stringSelector === '$hosts') hostSet.$hosts.forEach(applyRoot);
194
+ else if (stringSelector === '$appHosts') hostSet.$appHosts.forEach(applyRoot);
166
195
  else {
167
196
  if (r === 'shadow') {
168
- const found = inst.shadowRoot?.querySelectorAll(selector);
197
+ const found = inst.shadowRoot?.querySelectorAll(stringSelector);
169
198
  if (found) results.push(...found);
170
199
  } else if (r === 'light') {
171
- const found = inst.querySelectorAll(selector);
200
+ const found = inst.querySelectorAll(stringSelector);
172
201
  if (found) results.push(...found);
173
202
  } else if (r === 'all') {
174
- const sMatch = inst.shadowRoot?.querySelectorAll(selector);
175
- const lMatch = inst.querySelectorAll(selector);
203
+ const sMatch = inst.shadowRoot?.querySelectorAll(stringSelector);
204
+ const lMatch = inst.querySelectorAll(stringSelector);
176
205
  if (sMatch) results.push(...sMatch);
177
206
  if (lMatch) results.push(...lMatch);
178
207
  } else {
179
- const found = (inst.shadowRoot || inst).querySelectorAll(selector);
208
+ const found = (inst.shadowRoot || inst).querySelectorAll(stringSelector);
180
209
  if (found) results.push(...found);
181
210
  }
182
211
  }
@@ -191,11 +220,12 @@ export const resolveAttributeTargets = (inst: any, selector: string, options: At
191
220
  * - @applyAttribute('selector', 'attrName') - Set attribute with explicit name
192
221
  * - @applyAttribute('selector') - Use property name as attribute name
193
222
  * - @applyAttribute('selector', { name: 'attrName' }) - Set attribute via options
223
+ * - @applyAttribute((this, helper) => 'selector', 'attrName') - Function-based selector
194
224
  * - Return null to remove attribute
195
225
  */
196
- export function applyAttribute(selector: string, targetAttributeName: string, options?: AttributeOptions): MethodDecorator & PropertyDecorator;
197
- export function applyAttribute(selector: string, options?: AttributeOptions): MethodDecorator & PropertyDecorator;
198
- export function applyAttribute(selector: string, targetAttributeNameOrOptions?: string | AttributeOptions, options?: AttributeOptions): MethodDecorator & PropertyDecorator {
226
+ export function applyAttribute(selector: AttributeSelector, targetAttributeName: string, options?: AttributeOptions): MethodDecorator & PropertyDecorator;
227
+ export function applyAttribute(selector: AttributeSelector, options?: AttributeOptions): MethodDecorator & PropertyDecorator;
228
+ export function applyAttribute(selector: AttributeSelector, targetAttributeNameOrOptions?: string | AttributeOptions, options?: AttributeOptions): MethodDecorator & PropertyDecorator {
199
229
  return (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => {
200
230
  // ensureInit(target as any);
201
231
 
@@ -228,7 +258,7 @@ export function applyAttribute(selector: string, targetAttributeNameOrOptions?:
228
258
  }
229
259
  metaList.push({
230
260
  propertyKey,
231
- selector,
261
+ selector: selector as AttributeSelector,
232
262
  targetAttributeName,
233
263
  options: finalOptions,
234
264
  type: metaType
@@ -346,14 +376,16 @@ export function applyAttribute(selector: string, targetAttributeNameOrOptions?:
346
376
  * - @attribute('#user', 'product-id') - Attribute name on selector
347
377
  * - @attribute('product-id', options) - Attribute name on $this with options
348
378
  * - @attribute('#user', 'product-id', options) - Attribute name on selector with options
379
+ * - @attribute((this, helper) => 'selector', 'product-id') - Function-based selector
349
380
  * - @attribute - Bare decorator (uses property name as attribute on $this)
350
381
  *
351
382
  * Note: This decorator is for FIELDS ONLY. For methods, use @setAttribute.
352
383
  */
384
+ export function attribute(target: Object, propertyKey: string | symbol): void;
353
385
  export function attribute(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
354
386
  export function attribute(attributeName: string, options?: AttributeOptions): PropertyDecorator;
355
- export function attribute(selector: string, attributeName: string, options?: AttributeOptions): PropertyDecorator;
356
- export function attribute(selectorOrAttributeOrTarget?: string | Object, attributeNameOrOptions?: any, optionsOrDescriptor?: any): any {
387
+ export function attribute(selector: AttributeSelector, attributeName: string, options?: AttributeOptions): PropertyDecorator;
388
+ export function attribute(selectorOrAttributeOrTarget?: AttributeSelector | Object, attributeNameOrOptions?: any, optionsOrDescriptor?: any): any {
357
389
  // Bare decorator: @attribute
358
390
  if (optionsOrDescriptor !== undefined && (typeof attributeNameOrOptions === 'string' || typeof attributeNameOrOptions === 'symbol')) {
359
391
  return applyAttribute('$this', undefined as any, {})(selectorOrAttributeOrTarget as Object, attributeNameOrOptions, optionsOrDescriptor as PropertyDescriptor);
@@ -391,6 +423,7 @@ export function attribute(selectorOrAttributeOrTarget?: string | Object, attribu
391
423
  * - @setAttribute('#user', 'data-id') - Attribute name on selector
392
424
  * - @setAttribute('data-id', options) - Attribute name on $this with options
393
425
  * - @setAttribute('#user', 'data-id', options) - Attribute name on selector with options
426
+ * - @setAttribute((this, helper) => 'selector', 'data-id') - Function-based selector
394
427
  * - @setAttribute - Bare decorator (uses method name as attribute on $this)
395
428
  *
396
429
  * Note: This decorator is for METHODS ONLY. For fields, use @attribute.
@@ -401,9 +434,9 @@ export function attribute(selectorOrAttributeOrTarget?: string | Object, attribu
401
434
  * return 'active';
402
435
  * }
403
436
  */
404
- export function setAttribute(selector: string, attributeName: string, options?: AttributeOptions): MethodDecorator;
437
+ export function setAttribute(selector: AttributeSelector, attributeName: string, options?: AttributeOptions): MethodDecorator;
405
438
  export function setAttribute(attributeName: string, options?: AttributeOptions): MethodDecorator;
406
- export function setAttribute(selectorOrAttributeOrOptions?: string | AttributeOptions, attributeNameOrOptions?: any, optionsOrUndefined?: AttributeOptions): MethodDecorator {
439
+ export function setAttribute(selectorOrAttributeOrOptions?: AttributeSelector | AttributeOptions, attributeNameOrOptions?: any, optionsOrUndefined?: AttributeOptions): MethodDecorator {
407
440
  // With string as first parameter
408
441
  if (typeof selectorOrAttributeOrOptions === 'string') {
409
442
  // Check if first parameter is a CSS selector or attribute name
@@ -7,6 +7,73 @@ export const CLASS_METADATA_KEY = Symbol.for('simple-web-component:class');
7
7
 
8
8
  export type ClassAction = 'set' | 'update' | 'add' | 'remove' | 'toggle';
9
9
 
10
+ /**
11
+ * Resolve selector to string or elements
12
+ * Handles function-based selectors and returns elements if applicable
13
+ */
14
+ const resolveSelector = (selector: ClassSelector, inst: any, win: Window): string | HTMLElement[] => {
15
+ if (typeof selector === 'function') {
16
+ const hostSet = SwcUtils.getHelperAndHostSet(win, inst);
17
+ const result = selector(inst, hostSet);
18
+
19
+ if (result instanceof win.Element) {
20
+ return [result as HTMLElement];
21
+ }
22
+ if (result instanceof win.NodeList) {
23
+ return Array.from(result) as HTMLElement[];
24
+ }
25
+ if (Array.isArray(result)) {
26
+ return result as HTMLElement[];
27
+ }
28
+ if (result === null) {
29
+ return [];
30
+ }
31
+ return result as string;
32
+ }
33
+ return selector as string;
34
+ };
35
+
36
+ /**
37
+ * Get target elements from selector
38
+ */
39
+ const getTargetElements = (selector: ClassSelector, inst: any, win: Window, root: string): HTMLElement[] => {
40
+ const resolved = resolveSelector(selector, inst, win);
41
+
42
+ if (Array.isArray(resolved)) {
43
+ return resolved;
44
+ }
45
+
46
+ const stringSelector = resolved as string;
47
+ const targetEls: HTMLElement[] = [];
48
+ const host = inst as unknown as HTMLElement;
49
+ const hostSet = SwcUtils.getHelperAndHostSet(win, inst);
50
+
51
+ const applyRoot = (t: any) => {
52
+ if (!t || !(t instanceof win.HTMLElement)) return;
53
+ targetEls.push(t);
54
+ };
55
+
56
+ if (stringSelector === '$this' || !stringSelector) applyRoot(host);
57
+ else if (stringSelector === '$host') applyRoot(hostSet.$host);
58
+ else if (stringSelector === '$parentHost') applyRoot(hostSet.$parentHost);
59
+ else if (stringSelector === '$appHost') applyRoot(hostSet.$appHost);
60
+ else if (stringSelector === '$firstHost') applyRoot(hostSet.$firstHost);
61
+ else if (stringSelector === '$lastHost') applyRoot(hostSet.$lastHost);
62
+ else if (stringSelector === '$firstAppHost') applyRoot(hostSet.$firstAppHost);
63
+ else if (stringSelector === '$lastAppHost') applyRoot(hostSet.$lastAppHost);
64
+ else if (stringSelector === '$hosts') hostSet.$hosts.forEach(applyRoot);
65
+ else if (stringSelector === '$appHosts') hostSet.$appHosts.forEach(applyRoot);
66
+ else {
67
+ const targetRoot = root === 'auto' ? (host.shadowRoot || host) : (root === 'shadow' ? host.shadowRoot : host);
68
+ if (targetRoot) {
69
+ const found = targetRoot.querySelectorAll(stringSelector);
70
+ if (found) targetEls.push(...(Array.from(found) as HTMLElement[]));
71
+ }
72
+ }
73
+
74
+ return targetEls;
75
+ };
76
+
10
77
  export interface ClassApplyOptions extends SwcQueryOptions {
11
78
  filter?: (target: HTMLElement, value: any, meta: {currentThis: any, helper: HelperHostSet}) => boolean;
12
79
  /**
@@ -17,15 +84,17 @@ export interface ClassApplyOptions extends SwcQueryOptions {
17
84
  valueKey?: symbol | string;
18
85
  }
19
86
 
87
+ export type ClassSelector = string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
88
+
20
89
  export interface ClassApplyMetadata {
21
90
  propertyKey: string | symbol;
22
- selector: string;
91
+ selector: ClassSelector;
23
92
  action: ClassAction;
24
93
  options: ClassApplyOptions;
25
94
  }
26
95
 
27
96
  function createClassDecorator(action: ClassAction) {
28
- return (selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options: ClassApplyOptions = {}): MethodDecorator => {
97
+ return (selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options: ClassApplyOptions = {}): MethodDecorator => {
29
98
  return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
30
99
  const constructor = target.constructor;
31
100
  let metaList = ReflectUtils.getOwnMetadata(CLASS_METADATA_KEY, constructor) as Map<string | symbol, ClassApplyMetadata>;
@@ -72,30 +141,7 @@ function createClassDecorator(action: ClassAction) {
72
141
  const host = this as unknown as HTMLElement;
73
142
  const hostSet = { ...SwcUtils.getHelperAndHostSet(win, host), $this: this };
74
143
  const r = finalOptions.root || 'auto';
75
- const targetEls: HTMLElement[] = [];
76
-
77
- const applyRoot = (t: any) => {
78
- if (!t || !(t instanceof win.HTMLElement)) return;
79
- targetEls.push(t);
80
- };
81
-
82
- if (selector === '$this' || !selector) applyRoot(host);
83
- else if (selector === '$host') applyRoot(hostSet.$host);
84
- else if (selector === '$parentHost') applyRoot(hostSet.$parentHost);
85
- else if (selector === '$appHost') applyRoot(hostSet.$appHost);
86
- else if (selector === '$firstHost') applyRoot(hostSet.$firstHost);
87
- else if (selector === '$lastHost') applyRoot(hostSet.$lastHost);
88
- else if (selector === '$firstAppHost') applyRoot(hostSet.$firstAppHost);
89
- else if (selector === '$lastAppHost') applyRoot(hostSet.$lastAppHost);
90
- else if (selector === '$hosts') hostSet.$hosts.forEach(applyRoot);
91
- else if (selector === '$appHosts') hostSet.$appHosts.forEach(applyRoot);
92
- else {
93
- const targetRoot = r === 'auto' ? (host.shadowRoot || host) : (r === 'shadow' ? host.shadowRoot : host);
94
- if (targetRoot) {
95
- const found = targetRoot.querySelectorAll(selector);
96
- if (found) targetEls.push(...(Array.from(found) as HTMLElement[]));
97
- }
98
- }
144
+ const targetEls = getTargetElements(selector, this, win, r);
99
145
 
100
146
  targetEls.forEach(targetEl => {
101
147
  if (finalOptions.filter && !finalOptions.filter(targetEl, resolvedValue, {currentThis: this, helper: hostSet})) {
@@ -164,7 +210,7 @@ function createClassDecorator(action: ClassAction) {
164
210
  }
165
211
 
166
212
  export function applyClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
167
- export function applyClass(selector: string, action?: ClassAction, options?: ClassApplyOptions): MethodDecorator;
213
+ export function applyClass(selector: ClassSelector, action?: ClassAction, options?: ClassApplyOptions): MethodDecorator;
168
214
  export function applyClass(selectorOrTarget?: any, actionOrPropertyKey?: any, optionsOrDescriptor?: any): any {
169
215
  // Bare decorator: @applyClass
170
216
  if (optionsOrDescriptor !== undefined && (typeof actionOrPropertyKey === 'string' || typeof actionOrPropertyKey === 'symbol')) {
@@ -183,7 +229,7 @@ export function applyClass(selectorOrTarget?: any, actionOrPropertyKey?: any, op
183
229
  }
184
230
 
185
231
  export function setClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
186
- export function setClass(selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
232
+ export function setClass(selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
187
233
  export function setClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?: any, optionsOrDescriptor?: any): any {
188
234
  // Bare decorator: @setClass
189
235
  if (optionsOrDescriptor !== undefined && (typeof classMapOrOptionsOrPropertyKey === 'string' || typeof classMapOrOptionsOrPropertyKey === 'symbol')) {
@@ -198,7 +244,7 @@ export function setClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?
198
244
  }
199
245
 
200
246
  export function updateClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
201
- export function updateClass(selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
247
+ export function updateClass(selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
202
248
  export function updateClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?: any, optionsOrDescriptor?: any): any {
203
249
  // Bare decorator: @updateClass
204
250
  if (optionsOrDescriptor !== undefined && (typeof classMapOrOptionsOrPropertyKey === 'string' || typeof classMapOrOptionsOrPropertyKey === 'symbol')) {
@@ -213,7 +259,7 @@ export function updateClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyK
213
259
  }
214
260
 
215
261
  export function addClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
216
- export function addClass(selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
262
+ export function addClass(selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
217
263
  export function addClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?: any, optionsOrDescriptor?: any): any {
218
264
  // Bare decorator: @addClass
219
265
  if (optionsOrDescriptor !== undefined && (typeof classMapOrOptionsOrPropertyKey === 'string' || typeof classMapOrOptionsOrPropertyKey === 'symbol')) {
@@ -228,7 +274,7 @@ export function addClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?
228
274
  }
229
275
 
230
276
  export function removeClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
231
- export function removeClass(selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
277
+ export function removeClass(selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
232
278
  export function removeClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?: any, optionsOrDescriptor?: any): any {
233
279
  // Bare decorator: @removeClass
234
280
  if (optionsOrDescriptor !== undefined && (typeof classMapOrOptionsOrPropertyKey === 'string' || typeof classMapOrOptionsOrPropertyKey === 'symbol')) {
@@ -243,7 +289,7 @@ export function removeClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyK
243
289
  }
244
290
 
245
291
  export function toggleClass(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
246
- export function toggleClass(selector: string, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
292
+ export function toggleClass(selector: ClassSelector, classMapOrOptions?: string | { [className: string]: (el: HTMLElement, value: any, helper: HelperHostSet & { $this: any }) => boolean } | ClassApplyOptions, options?: ClassApplyOptions): MethodDecorator;
247
293
  export function toggleClass(selectorOrTarget?: any, classMapOrOptionsOrPropertyKey?: any, optionsOrDescriptor?: any): any {
248
294
  // Bare decorator: @toggleClass
249
295
  if (optionsOrDescriptor !== undefined && (typeof classMapOrOptionsOrPropertyKey === 'string' || typeof classMapOrOptionsOrPropertyKey === 'symbol')) {