@dooboostore/simple-web-component 1.0.44 → 1.0.45

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 (75) 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 +51 -23
  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 +44 -25
  14. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  15. package/dist/cjs/decorators/emitCustomEvent.js +61 -47
  16. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  17. package/dist/cjs/decorators/query.js +91 -56
  18. package/dist/cjs/decorators/query.js.map +2 -2
  19. package/dist/cjs/decorators/queryAll.js +104 -66
  20. package/dist/cjs/decorators/queryAll.js.map +2 -2
  21. package/dist/cjs/types/window.d.js.map +1 -1
  22. package/dist/esm/decorators/addEventListener.js.map +2 -2
  23. package/dist/esm/decorators/applyAttribute.js +36 -15
  24. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  25. package/dist/esm/decorators/applyClass.js +53 -22
  26. package/dist/esm/decorators/applyClass.js.map +2 -2
  27. package/dist/esm/decorators/applyNode.js +51 -23
  28. package/dist/esm/decorators/applyNode.js.map +2 -2
  29. package/dist/esm/decorators/applyProperty.js +38 -17
  30. package/dist/esm/decorators/applyProperty.js.map +2 -2
  31. package/dist/esm/decorators/applyStyle.js +53 -22
  32. package/dist/esm/decorators/applyStyle.js.map +2 -2
  33. package/dist/esm/decorators/elementDefine.js +44 -25
  34. package/dist/esm/decorators/elementDefine.js.map +2 -2
  35. package/dist/esm/decorators/emitCustomEvent.js +61 -47
  36. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  37. package/dist/esm/decorators/query.js +91 -56
  38. package/dist/esm/decorators/query.js.map +2 -2
  39. package/dist/esm/decorators/queryAll.js +104 -66
  40. package/dist/esm/decorators/queryAll.js.map +2 -2
  41. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +531 -293
  42. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +3 -3
  43. package/dist/types/decorators/addEventListener.d.ts +7 -6
  44. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  45. package/dist/types/decorators/applyAttribute.d.ts +12 -8
  46. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  47. package/dist/types/decorators/applyClass.d.ts +8 -7
  48. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  49. package/dist/types/decorators/applyNode.d.ts +18 -17
  50. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  51. package/dist/types/decorators/applyProperty.d.ts +13 -9
  52. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  53. package/dist/types/decorators/applyStyle.d.ts +6 -5
  54. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  55. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  56. package/dist/types/decorators/emitCustomEvent.d.ts +3 -2
  57. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  58. package/dist/types/decorators/query.d.ts +15 -5
  59. package/dist/types/decorators/query.d.ts.map +1 -1
  60. package/dist/types/decorators/queryAll.d.ts +15 -5
  61. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  62. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +531 -293
  63. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +3 -3
  64. package/package.json +3 -3
  65. package/src/decorators/addEventListener.ts +9 -7
  66. package/src/decorators/applyAttribute.ts +59 -27
  67. package/src/decorators/applyClass.ts +78 -32
  68. package/src/decorators/applyNode.ts +115 -72
  69. package/src/decorators/applyProperty.ts +62 -30
  70. package/src/decorators/applyStyle.ts +76 -30
  71. package/src/decorators/elementDefine.ts +49 -26
  72. package/src/decorators/emitCustomEvent.ts +63 -39
  73. package/src/decorators/query.ts +111 -49
  74. package/src/decorators/queryAll.ts +121 -61
  75. package/src/types/window.d.ts +3 -0
@@ -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 { SpecialSelector, SwcQueryOptions, HelperHostSet } from '../types';
4
+ import { SwcQueryOptions, HelperHostSet } from '../types';
5
+
6
+ export interface QueryAllOptions 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 QueryAllMetadata {
7
15
  propertyKey: string | symbol;
8
- selector: string;
9
- options: SwcQueryOptions;
16
+ selector: string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null);
17
+ options: QueryAllOptions;
10
18
  }
11
19
 
12
20
  export const QUERY_ALL_METADATA_KEY = Symbol.for('simple-web-component:query-all');
13
21
 
14
22
  export function queryAll(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): PropertyDescriptor | void;
15
- export function queryAll(selector: string, options?: SwcQueryOptions): PropertyDecorator;
16
- export function queryAll(options?: SwcQueryOptions): PropertyDecorator;
23
+ export function queryAll(selector: string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null), options?: QueryAllOptions): PropertyDecorator;
24
+ export function queryAll(options?: QueryAllOptions): PropertyDecorator;
17
25
  /**
18
26
  * @queryAll decorator to inject a list of elements into a class property.
27
+ *
28
+ * Supports both string selectors and function-based selectors:
29
+ * - String selector: @queryAll('.item')
30
+ * - Function selector: @queryAll((currentThis, helper) => currentThis.shadowRoot?.querySelectorAll('.item'))
31
+ *
32
+ * Supports filtering:
33
+ * - @queryAll('.item', { filter: (target, meta) => target.hasAttribute('active') })
19
34
  */
20
- export function queryAll(selectorOrTarget?: string | Object, optionsOrPropertyKey?: SwcQueryOptions | string | symbol, descriptor?: PropertyDescriptor): any {
35
+ export function queryAll(selectorOrTarget?: string | ((currentThis: any, helper: HelperHostSet) => NodeList | Element | Element[] | null) | Object, optionsOrPropertyKey?: QueryAllOptions | string | symbol, descriptor?: PropertyDescriptor): any {
21
36
  // Bare decorator: @queryAll
22
37
  if (descriptor !== undefined && (typeof optionsOrPropertyKey === 'string' || typeof optionsOrPropertyKey === 'symbol')) {
23
38
  throw new Error(`@queryAll 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(`@queryAll decorator cannot be used on methods. (Method: ${String(propertyKey)})`);
@@ -35,78 +50,123 @@ export function queryAll(selectorOrTarget?: string | Object, optionsOrPropertyKe
35
50
  queries = [];
36
51
  ReflectUtils.defineMetadata(QUERY_ALL_METADATA_KEY, queries, constructor);
37
52
  }
38
- queries.push({ propertyKey, selector: selectorOrTarget, options: optionsOrPropertyKey as SwcQueryOptions || {} });
53
+ queries.push({ propertyKey, selector: selectorOrTarget as any, options: optionsOrPropertyKey as QueryAllOptions || {} });
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): any[] => {
47
- if (!t) return [];
48
- const items = Array.isArray(t) ? t : [t];
49
- const results: any[] = [];
50
- items.forEach(it => {
51
- if (!(it instanceof HTMLElement)) {
52
- results.push(it);
53
- return;
54
- }
55
- if (r === 'auto') results.push(it.shadowRoot || it);
56
- else {
57
- if (r === 'light' || r === 'all') results.push(it);
58
- if ((r === 'shadow' || r === 'all') && it.shadowRoot) results.push(it.shadowRoot);
59
- }
60
- });
61
- return results;
62
- };
63
-
64
- // --- Special Selectors: HostSet ---
65
- const hostSet = SwcUtils.getHostSet(this);
66
- if (selector === '$hosts') return applyRoot(hostSet.$hosts);
67
- if (selector === '$appHosts') return applyRoot(hostSet.$appHosts);
68
- if (selector === '$host') return applyRoot(hostSet.$host);
69
- if (selector === '$parentHost') return applyRoot(hostSet.$parentHost);
70
- if (selector === '$appHost') return applyRoot(hostSet.$appHost);
71
- if (selector === '$firstHost') return applyRoot(hostSet.$firstHost);
72
- if (selector === '$lastHost') return applyRoot(hostSet.$lastHost);
73
- if (selector === '$firstAppHost') return applyRoot(hostSet.$firstAppHost);
74
- if (selector === '$lastAppHost') return applyRoot(hostSet.$lastAppHost);
75
-
76
- // --- Special Selectors: Env ---
77
58
  const config = getElementConfig(this);
78
59
  const win = config?.window || window;
79
- if (selector === '$window') return [win];
80
- if (selector === '$document') return [win.document];
81
- if (selector === '$this') return applyRoot(this);
60
+ const hostSet = SwcUtils.getHelperAndHostSet(win, this);
61
+
62
+ // Resolve selector - can be string or function
63
+ let resolvedSelector: string;
64
+ let resolvedElements: HTMLElement[] = [];
65
+
66
+ if (typeof selectorOrTarget === 'function') {
67
+ const result = (selectorOrTarget as any)(this, hostSet);
68
+ // If function returns NodeList or Element[], convert to array
69
+ if (result instanceof win.NodeList) {
70
+ resolvedElements = Array.from(result).filter(el => el instanceof win.HTMLElement) as HTMLElement[];
71
+ } else if (Array.isArray(result)) {
72
+ resolvedElements = result.filter(el => el instanceof win.HTMLElement) as HTMLElement[];
73
+ }
74
+ } else {
75
+ resolvedSelector = selectorOrTarget;
82
76
 
83
- // --- Standard Selectors ---
84
- if (r === 'shadow') return this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(selector)) : [];
85
- if (r === 'light') return Array.from(this.querySelectorAll(selector));
86
- if (r === 'all') {
87
- const sNodes = this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(selector)) : [];
88
- const lNodes = Array.from(this.querySelectorAll(selector));
89
- return [...sNodes, ...lNodes];
77
+ const r = (optionsOrPropertyKey as QueryAllOptions)?.root || 'auto';
78
+ const applyRoot = (t: any): any[] => {
79
+ if (!t) return [];
80
+ const items = Array.isArray(t) ? t : [t];
81
+ const results: any[] = [];
82
+ items.forEach(it => {
83
+ if (!(it instanceof HTMLElement)) {
84
+ results.push(it);
85
+ return;
86
+ }
87
+ if (r === 'auto') results.push(it.shadowRoot || it);
88
+ else {
89
+ if (r === 'light' || r === 'all') results.push(it);
90
+ if ((r === 'shadow' || r === 'all') && it.shadowRoot) results.push(it.shadowRoot);
91
+ }
92
+ });
93
+ return results;
94
+ };
95
+
96
+ // --- Special Selectors: HostSet ---
97
+ if (resolvedSelector === '$hosts') resolvedElements = applyRoot(hostSet.$hosts).filter(el => el instanceof HTMLElement);
98
+ else if (resolvedSelector === '$appHosts') resolvedElements = applyRoot(hostSet.$appHosts).filter(el => el instanceof HTMLElement);
99
+ else if (resolvedSelector === '$host') resolvedElements = applyRoot(hostSet.$host).filter(el => el instanceof HTMLElement);
100
+ else if (resolvedSelector === '$parentHost') resolvedElements = applyRoot(hostSet.$parentHost).filter(el => el instanceof HTMLElement);
101
+ else if (resolvedSelector === '$appHost') resolvedElements = applyRoot(hostSet.$appHost).filter(el => el instanceof HTMLElement);
102
+ else if (resolvedSelector === '$firstHost') resolvedElements = applyRoot(hostSet.$firstHost).filter(el => el instanceof HTMLElement);
103
+ else if (resolvedSelector === '$lastHost') resolvedElements = applyRoot(hostSet.$lastHost).filter(el => el instanceof HTMLElement);
104
+ else if (resolvedSelector === '$firstAppHost') resolvedElements = applyRoot(hostSet.$firstAppHost).filter(el => el instanceof HTMLElement);
105
+ else if (resolvedSelector === '$lastAppHost') resolvedElements = applyRoot(hostSet.$lastAppHost).filter(el => el instanceof HTMLElement);
106
+ // --- Special Selectors: Env ---
107
+ else if (resolvedSelector === '$window') return [win];
108
+ else if (resolvedSelector === '$document') return [win.document];
109
+ else if (resolvedSelector === '$this') resolvedElements = applyRoot(this).filter(el => el instanceof HTMLElement);
110
+ // --- Standard Selectors ---
111
+ else {
112
+ if (r === 'shadow') resolvedElements = this.shadowRoot ? (Array.from(this.shadowRoot.querySelectorAll(resolvedSelector)) as HTMLElement[]) : [];
113
+ else if (r === 'light') resolvedElements = Array.from(this.querySelectorAll(resolvedSelector)) as HTMLElement[];
114
+ else if (r === 'all') {
115
+ const sNodes = this.shadowRoot ? (Array.from(this.shadowRoot.querySelectorAll(resolvedSelector)) as HTMLElement[]) : [];
116
+ const lNodes = Array.from(this.querySelectorAll(resolvedSelector)) as HTMLElement[];
117
+ resolvedElements = [...sNodes, ...lNodes];
118
+ }
119
+ else resolvedElements = (Array.from((this.shadowRoot || this).querySelectorAll(resolvedSelector)) as HTMLElement[]);
120
+ }
90
121
  }
91
- const root = this.shadowRoot || this;
92
- return Array.from(root.querySelectorAll(selector));
122
+
123
+ // Apply filter if provided
124
+ if ((optionsOrPropertyKey as QueryAllOptions)?.filter) {
125
+ resolvedElements = resolvedElements.filter(el => {
126
+ if (!(el instanceof win.HTMLElement)) return true;
127
+ return (optionsOrPropertyKey as QueryAllOptions).filter!(el, { currentThis: this, helper: hostSet });
128
+ });
129
+ }
130
+
131
+ return resolvedElements;
93
132
  },
94
133
  set(this: HTMLElement, nv: any) {
95
134
  ensureInit(this);
96
135
  if (nv === null || nv === undefined || (Array.isArray(nv) && nv.length === 0)) {
97
- const selector = selectorOrTarget;
98
- if (selector.startsWith('$') && selector !== '$this') return;
136
+ const config = getElementConfig(this);
137
+ const win = config?.window || window;
138
+ const hostSet = SwcUtils.getHelperAndHostSet(win, this);
139
+
140
+ // Resolve selector - can be string or function
141
+ if (typeof selectorOrTarget === 'function') {
142
+ // Get elements from function and remove them
143
+ const result = (selectorOrTarget as any)(this, hostSet);
144
+ if (result instanceof win.NodeList) {
145
+ Array.from(result).forEach(el => {
146
+ if (el instanceof win.Element) (el as Element).remove();
147
+ });
148
+ } else if (Array.isArray(result)) {
149
+ result.forEach(el => {
150
+ if (el instanceof win.Element) (el as Element).remove();
151
+ });
152
+ }
153
+ return;
154
+ }
155
+
156
+ const resolvedSelector = selectorOrTarget;
157
+
158
+ if (resolvedSelector.startsWith('$') && resolvedSelector !== '$this') return;
99
159
 
100
160
  const r = (optionsOrPropertyKey as SwcQueryOptions)?.root || 'auto';
101
161
  let targets: (Element | Node)[] = [];
102
- if (r === 'shadow') targets = this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(selector)) : [];
103
- else if (r === 'light') targets = Array.from(this.querySelectorAll(selector));
162
+ if (r === 'shadow') targets = this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(resolvedSelector)) : [];
163
+ else if (r === 'light') targets = Array.from(this.querySelectorAll(resolvedSelector));
104
164
  else if (r === 'all') {
105
- const sNodes = this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(selector)) : [];
106
- const lNodes = Array.from(this.querySelectorAll(selector));
165
+ const sNodes = this.shadowRoot ? Array.from(this.shadowRoot.querySelectorAll(resolvedSelector)) : [];
166
+ const lNodes = Array.from(this.querySelectorAll(resolvedSelector));
107
167
  targets = [...sNodes, ...lNodes];
108
168
  } else {
109
- targets = Array.from((this.shadowRoot || this).querySelectorAll(selector));
169
+ targets = Array.from((this.shadowRoot || this).querySelectorAll(resolvedSelector));
110
170
  }
111
171
  targets.forEach(t => (t as Element).remove());
112
172
  }
@@ -5,6 +5,9 @@ import {HTMLDialogElement} from "@dooboostore/dom-parser";
5
5
  */
6
6
  declare global {
7
7
  interface Window {
8
+ Node: typeof Node;
9
+ NodeList: typeof NodeList;
10
+ Element: typeof Element;
8
11
  HTMLElement: typeof HTMLElement;
9
12
  HTMLDivElement: typeof HTMLDivElement;
10
13
  HTMLButtonElement: typeof HTMLButtonElement;