@dooboostore/simple-web-component 1.0.23 → 1.0.25

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 (149) hide show
  1. package/README.md +64 -3212
  2. package/dist/cjs/decorators/addEventListener.js +1 -1
  3. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  4. package/dist/cjs/decorators/applyAttribute.js +148 -0
  5. package/dist/cjs/decorators/applyAttribute.js.map +7 -0
  6. package/dist/cjs/decorators/applyClass.js +164 -0
  7. package/dist/cjs/decorators/applyClass.js.map +7 -0
  8. package/dist/cjs/decorators/applyNode.js +97 -109
  9. package/dist/cjs/decorators/applyNode.js.map +2 -2
  10. package/dist/cjs/decorators/applyStyle.js +135 -0
  11. package/dist/cjs/decorators/applyStyle.js.map +7 -0
  12. package/dist/cjs/decorators/attribute.js +24 -11
  13. package/dist/cjs/decorators/attribute.js.map +2 -2
  14. package/dist/cjs/decorators/changedAttributeHost.js +1 -1
  15. package/dist/cjs/decorators/changedAttributeHost.js.map +2 -2
  16. package/dist/cjs/decorators/elementDefine.js +14 -23
  17. package/dist/cjs/decorators/elementDefine.js.map +2 -2
  18. package/dist/cjs/decorators/emitCustomEvent.js +5 -2
  19. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  20. package/dist/cjs/decorators/index.js +3 -3
  21. package/dist/cjs/decorators/index.js.map +2 -2
  22. package/dist/cjs/decorators/lifecycles.js +9 -9
  23. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  24. package/dist/cjs/decorators/query.js +78 -3
  25. package/dist/cjs/decorators/query.js.map +2 -2
  26. package/dist/cjs/decorators/queryAll.js +78 -3
  27. package/dist/cjs/decorators/queryAll.js.map +2 -2
  28. package/dist/cjs/elements/SwcAppEngine.js +19 -4
  29. package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
  30. package/dist/cjs/elements/SwcAppMixin.js +2 -0
  31. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  32. package/dist/cjs/index.js +4 -4
  33. package/dist/cjs/index.js.map +2 -2
  34. package/dist/cjs/utils/Utils.js +141 -2
  35. package/dist/cjs/utils/Utils.js.map +2 -2
  36. package/dist/esm/decorators/addEventListener.js +1 -1
  37. package/dist/esm/decorators/addEventListener.js.map +2 -2
  38. package/dist/esm/decorators/applyAttribute.js +129 -0
  39. package/dist/esm/decorators/applyAttribute.js.map +7 -0
  40. package/dist/esm/decorators/applyClass.js +145 -0
  41. package/dist/esm/decorators/applyClass.js.map +7 -0
  42. package/dist/esm/decorators/applyNode.js +97 -109
  43. package/dist/esm/decorators/applyNode.js.map +2 -2
  44. package/dist/esm/decorators/applyStyle.js +116 -0
  45. package/dist/esm/decorators/applyStyle.js.map +7 -0
  46. package/dist/esm/decorators/attribute.js +24 -11
  47. package/dist/esm/decorators/attribute.js.map +2 -2
  48. package/dist/esm/decorators/changedAttributeHost.js +1 -1
  49. package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
  50. package/dist/esm/decorators/elementDefine.js +14 -23
  51. package/dist/esm/decorators/elementDefine.js.map +2 -2
  52. package/dist/esm/decorators/emitCustomEvent.js +5 -2
  53. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  54. package/dist/esm/decorators/index.js +3 -3
  55. package/dist/esm/decorators/index.js.map +1 -1
  56. package/dist/esm/decorators/lifecycles.js +9 -9
  57. package/dist/esm/decorators/lifecycles.js.map +2 -2
  58. package/dist/esm/decorators/query.js +78 -3
  59. package/dist/esm/decorators/query.js.map +2 -2
  60. package/dist/esm/decorators/queryAll.js +78 -3
  61. package/dist/esm/decorators/queryAll.js.map +2 -2
  62. package/dist/esm/elements/SwcAppEngine.js +19 -4
  63. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  64. package/dist/esm/elements/SwcAppMixin.js +2 -0
  65. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  66. package/dist/esm/index.js +4 -4
  67. package/dist/esm/index.js.map +2 -2
  68. package/dist/esm/utils/Utils.js +141 -2
  69. package/dist/esm/utils/Utils.js.map +2 -2
  70. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +3191 -506
  71. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  72. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  73. package/dist/types/decorators/applyAttribute.d.ts +22 -0
  74. package/dist/types/decorators/applyAttribute.d.ts.map +1 -0
  75. package/dist/types/decorators/applyClass.d.ts +65 -0
  76. package/dist/types/decorators/applyClass.d.ts.map +1 -0
  77. package/dist/types/decorators/applyNode.d.ts +18 -104
  78. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  79. package/dist/types/decorators/applyStyle.d.ts +21 -0
  80. package/dist/types/decorators/applyStyle.d.ts.map +1 -0
  81. package/dist/types/decorators/attribute.d.ts +12 -14
  82. package/dist/types/decorators/attribute.d.ts.map +1 -1
  83. package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
  84. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  85. package/dist/types/decorators/emitCustomEvent.d.ts +1 -1
  86. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  87. package/dist/types/decorators/index.d.ts +3 -3
  88. package/dist/types/decorators/index.d.ts.map +1 -1
  89. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  90. package/dist/types/decorators/query.d.ts +68 -4
  91. package/dist/types/decorators/query.d.ts.map +1 -1
  92. package/dist/types/decorators/queryAll.d.ts +70 -1
  93. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  94. package/dist/types/elements/SwcAppEngine.d.ts +7 -0
  95. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  96. package/dist/types/elements/SwcAppMixin.d.ts +1 -1
  97. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  98. package/dist/types/index.d.ts +1 -2
  99. package/dist/types/index.d.ts.map +1 -1
  100. package/dist/types/utils/Utils.d.ts +49 -0
  101. package/dist/types/utils/Utils.d.ts.map +1 -1
  102. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +3191 -506
  103. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  104. package/package.json +3 -3
  105. package/src/decorators/addEventListener.ts +1 -1
  106. package/src/decorators/applyAttribute.ts +147 -0
  107. package/src/decorators/applyClass.ts +158 -0
  108. package/src/decorators/applyNode.ts +126 -225
  109. package/src/decorators/applyStyle.ts +128 -0
  110. package/src/decorators/attribute.ts +42 -43
  111. package/src/decorators/changedAttributeHost.ts +2 -2
  112. package/src/decorators/elementDefine.ts +18 -39
  113. package/src/decorators/emitCustomEvent.ts +6 -3
  114. package/src/decorators/index.ts +3 -3
  115. package/src/decorators/lifecycles.ts +9 -11
  116. package/src/decorators/query.ts +148 -6
  117. package/src/decorators/queryAll.ts +149 -3
  118. package/src/elements/SwcAppEngine.ts +32 -4
  119. package/src/elements/SwcAppMixin.ts +2 -0
  120. package/src/index.ts +6 -6
  121. package/src/utils/Utils.ts +146 -1
  122. package/dist/cjs/decorators/classList.js +0 -134
  123. package/dist/cjs/decorators/classList.js.map +0 -7
  124. package/dist/cjs/decorators/setAttribute.js +0 -111
  125. package/dist/cjs/decorators/setAttribute.js.map +0 -7
  126. package/dist/cjs/decorators/style.js +0 -114
  127. package/dist/cjs/decorators/style.js.map +0 -7
  128. package/dist/cjs/utils/TemplateUtils.js +0 -109
  129. package/dist/cjs/utils/TemplateUtils.js.map +0 -7
  130. package/dist/esm/decorators/classList.js +0 -115
  131. package/dist/esm/decorators/classList.js.map +0 -7
  132. package/dist/esm/decorators/setAttribute.js +0 -92
  133. package/dist/esm/decorators/setAttribute.js.map +0 -7
  134. package/dist/esm/decorators/style.js +0 -95
  135. package/dist/esm/decorators/style.js.map +0 -7
  136. package/dist/esm/utils/TemplateUtils.js +0 -90
  137. package/dist/esm/utils/TemplateUtils.js.map +0 -7
  138. package/dist/types/decorators/classList.d.ts +0 -61
  139. package/dist/types/decorators/classList.d.ts.map +0 -1
  140. package/dist/types/decorators/setAttribute.d.ts +0 -23
  141. package/dist/types/decorators/setAttribute.d.ts.map +0 -1
  142. package/dist/types/decorators/style.d.ts +0 -49
  143. package/dist/types/decorators/style.d.ts.map +0 -1
  144. package/dist/types/utils/TemplateUtils.d.ts +0 -59
  145. package/dist/types/utils/TemplateUtils.d.ts.map +0 -1
  146. package/src/decorators/classList.ts +0 -172
  147. package/src/decorators/setAttribute.ts +0 -113
  148. package/src/decorators/style.ts +0 -140
  149. package/src/utils/TemplateUtils.ts +0 -92
@@ -1,26 +1,23 @@
1
- import { ReflectUtils } from '@dooboostore/core';
2
- import { ensureInit, getElementConfig } from './elementDefine';
3
- import { SwcUtils } from '../utils/Utils';
4
- import { SpecialSelector, SwcQueryOptions } from '../types';
1
+ import {ReflectUtils} from '@dooboostore/core';
2
+ import {ensureInit, getElementConfig} from './elementDefine';
3
+ import {SwcUtils} from '../utils/Utils';
4
+ import {SpecialSelector, SwcQueryOptions} from '../types';
5
5
 
6
- export interface AttributeOptions extends SwcQueryOptions {
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 AttributeMetadata {
12
+ export interface AttributeFieldMetadata {
13
13
  propertyKey: string | symbol;
14
14
  selector: string;
15
- options: AttributeOptions;
16
- privateKey: symbol; // Added to bypass getter during initialization
15
+ options: AttributeFieldOptions;
16
+ privateKey: symbol;
17
17
  }
18
18
 
19
- export const ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:attribute');
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: AttributeOptions = {}): PropertyDecorator {
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(ATTRIBUTE_METADATA_KEY, constructor) as AttributeMetadata[];
87
+ let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_FIELD_METADATA_KEY, constructor) as AttributeFieldMetadata[];
96
88
  if (!metaList) {
97
89
  metaList = [];
98
- ReflectUtils.defineMetadata(ATTRIBUTE_METADATA_KEY, metaList, constructor);
90
+ ReflectUtils.defineMetadata(ATTRIBUTE_FIELD_METADATA_KEY, metaList, constructor);
99
91
  }
100
- metaList.push({ propertyKey, selector, options, privateKey });
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,15 +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
- * @hostAttribute decorator - simplified version of @attribute for :host selector
187
- * Usage: @hostAttribute('data-product-id')
188
- * Usage: @hostAttribute('disabled', { type: Boolean })
162
+ * @attributeHost decorator to sync a field value with the :host element's attribute.
189
163
  */
190
- export function attributeHost(attrName: string, options: AttributeOptions = {}): PropertyDecorator {
191
- return attribute(':host', { ...options, name: attrName });
164
+ export function attributeHost(target: Object, propertyKey: string | symbol): void;
165
+ export function attributeHost(options: AttributeFieldOptions): PropertyDecorator;
166
+ export function attributeHost(attrName: string): PropertyDecorator;
167
+ export function attributeHost(attrName: string, options: AttributeFieldOptions): PropertyDecorator;
168
+ export function attributeHost(targetOrAttrOrOptions?: any, propertyKeyOrOptions?: any): any {
169
+ if (propertyKeyOrOptions !== undefined && (typeof propertyKeyOrOptions === 'string' || typeof propertyKeyOrOptions === 'symbol')) {
170
+ return attribute(':host', { name: String(propertyKeyOrOptions) })(targetOrAttrOrOptions, propertyKeyOrOptions);
171
+ }
172
+
173
+ if (typeof targetOrAttrOrOptions === 'string') {
174
+ const attrName = targetOrAttrOrOptions;
175
+ const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as AttributeFieldOptions;
176
+ return attribute(':host', { ...options, name: attrName });
177
+ } else if (typeof targetOrAttrOrOptions === 'object') {
178
+ const options = targetOrAttrOrOptions as AttributeFieldOptions;
179
+ return (target: Object, propertyKey: string | symbol) => {
180
+ return attribute(':host', { ...options, name: String(propertyKey) })(target, propertyKey);
181
+ };
182
+ } else {
183
+ return (target: Object, propertyKey: string | symbol) => {
184
+ return attribute(':host', { name: String(propertyKey) })(target, propertyKey);
185
+ };
186
+ }
192
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
- import { ReflectUtils } from '@dooboostore/core';
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 { findAllSetAttributeMetadata } from './setAttribute';
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 mergedObservedAttributes = [...new Set([...(metadata.observedAttributes ?? []), ...attrChangeMap.keys(), ...Array.from(findAllSetAttributeMetadata(constructor).values()).map(it => it.name), ...attributeList.map(it => it.options.name || String(it.propertyKey)), ...emitHostCustomEventList.map(it => (it.options as any).attributeName).filter(Boolean), ...swcLifecycleAttributes, ...swcOnEvents])];
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 (DOM <-> JS Sync)
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; // Trigger setter to update DOM
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; // stopPropagation: true comes first
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?: EmitCustomEventBaseOptions & SwcQueryOptions & { attributeName?: string }): MethodDecorator {
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
  }
@@ -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 './classList';
12
- export * from './style';
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
 
@@ -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;
@@ -108,10 +108,152 @@ export const getQueryMetadata = (target: any): QueryMetadata[] | undefined => {
108
108
  };
109
109
 
110
110
  /**
111
- * @hostQuery decorator - simplified version of @query for :host selector
112
- * Usage: @hostQuery()
113
- * Usage: @hostQuery({ root: 'shadow' })
111
+ * @queryHost decorator - simplified version of @query for :host selector
112
+ * Usage: @queryHost testzzs: HTMLElement | undefined;
113
+ * Usage: @queryHost() testzzs: HTMLElement | undefined;
114
+ * Usage: @queryHost({ root: 'shadow' }) testzzs: HTMLElement | undefined;
114
115
  */
115
- export function queryHost(options?: SwcQueryOptions): PropertyDecorator {
116
- return query(':host', options);
116
+ export function queryHost(target: Object, propertyKey: string | symbol): void;
117
+ export function queryHost(): PropertyDecorator;
118
+ export function queryHost(options: SwcQueryOptions): PropertyDecorator;
119
+ export function queryHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
120
+ // Direct decorator usage: @queryHost (no parentheses)
121
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
122
+ return query(':host', {})(targetOrOptions, propertyKey);
123
+ }
124
+
125
+ // @queryHost() or @queryHost(options)
126
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
127
+ return query(':host', targetOrOptions as SwcQueryOptions);
128
+ } else {
129
+ return query(':host', {});
130
+ }
131
+ }
132
+
133
+ /**
134
+ * @host - Alias for @queryHost decorator
135
+ * Usage: @host element: HTMLElement | undefined;
136
+ * Usage: @host() element: HTMLElement | undefined;
137
+ * Usage: @host({ root: 'shadow' }) element: HTMLElement | undefined;
138
+ */
139
+ export const host = queryHost;
140
+
141
+ /**
142
+ * @parentHost - Query :parentHost (Direct parent SWC component)
143
+ * Usage: @parentHost parent: HTMLElement | undefined;
144
+ * Usage: @parentHost() parent: HTMLElement | undefined;
145
+ * Usage: @parentHost({ root: 'shadow' }) parent: HTMLElement | undefined;
146
+ */
147
+ export function parentHost(target: Object, propertyKey: string | symbol): void;
148
+ export function parentHost(): PropertyDecorator;
149
+ export function parentHost(options: SwcQueryOptions): PropertyDecorator;
150
+ export function parentHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
151
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
152
+ return query(':parentHost', {})(targetOrOptions, propertyKey);
153
+ }
154
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
155
+ return query(':parentHost', targetOrOptions as SwcQueryOptions);
156
+ } else {
157
+ return query(':parentHost', {});
158
+ }
159
+ }
160
+
161
+ /**
162
+ * @appHost - Query :appHost (Nearest <swc-app>)
163
+ * Usage: @appHost app: SwcAppInterface | undefined;
164
+ * Usage: @appHost() app: SwcAppInterface | undefined;
165
+ * Usage: @appHost({ root: 'shadow' }) app: SwcAppInterface | undefined;
166
+ */
167
+ export function appHost(target: Object, propertyKey: string | symbol): void;
168
+ export function appHost(): PropertyDecorator;
169
+ export function appHost(options: SwcQueryOptions): PropertyDecorator;
170
+ export function appHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
171
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
172
+ return query(':appHost', {})(targetOrOptions, propertyKey);
173
+ }
174
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
175
+ return query(':appHost', targetOrOptions as SwcQueryOptions);
176
+ } else {
177
+ return query(':appHost', {});
178
+ }
179
+ }
180
+
181
+ /**
182
+ * @firstHost - Query :firstHost (First component in hierarchy)
183
+ * Usage: @firstHost first: HTMLElement | undefined;
184
+ * Usage: @firstHost() first: HTMLElement | undefined;
185
+ * Usage: @firstHost({ root: 'shadow' }) first: HTMLElement | undefined;
186
+ */
187
+ export function firstHost(target: Object, propertyKey: string | symbol): void;
188
+ export function firstHost(): PropertyDecorator;
189
+ export function firstHost(options: SwcQueryOptions): PropertyDecorator;
190
+ export function firstHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
191
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
192
+ return query(':firstHost', {})(targetOrOptions, propertyKey);
193
+ }
194
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
195
+ return query(':firstHost', targetOrOptions as SwcQueryOptions);
196
+ } else {
197
+ return query(':firstHost', {});
198
+ }
199
+ }
200
+
201
+ /**
202
+ * @lastHost - Query :lastHost (Last component in hierarchy)
203
+ * Usage: @lastHost last: HTMLElement | undefined;
204
+ * Usage: @lastHost() last: HTMLElement | undefined;
205
+ * Usage: @lastHost({ root: 'shadow' }) last: HTMLElement | undefined;
206
+ */
207
+ export function lastHost(target: Object, propertyKey: string | symbol): void;
208
+ export function lastHost(): PropertyDecorator;
209
+ export function lastHost(options: SwcQueryOptions): PropertyDecorator;
210
+ export function lastHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
211
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
212
+ return query(':lastHost', {})(targetOrOptions, propertyKey);
213
+ }
214
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
215
+ return query(':lastHost', targetOrOptions as SwcQueryOptions);
216
+ } else {
217
+ return query(':lastHost', {});
218
+ }
219
+ }
220
+
221
+ /**
222
+ * @firstAppHost - Query :firstAppHost (First <swc-app> in hierarchy)
223
+ * Usage: @firstAppHost app: SwcAppInterface | undefined;
224
+ * Usage: @firstAppHost() app: SwcAppInterface | undefined;
225
+ * Usage: @firstAppHost({ root: 'shadow' }) app: SwcAppInterface | undefined;
226
+ */
227
+ export function firstAppHost(target: Object, propertyKey: string | symbol): void;
228
+ export function firstAppHost(): PropertyDecorator;
229
+ export function firstAppHost(options: SwcQueryOptions): PropertyDecorator;
230
+ export function firstAppHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
231
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
232
+ return query(':firstAppHost', {})(targetOrOptions, propertyKey);
233
+ }
234
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
235
+ return query(':firstAppHost', targetOrOptions as SwcQueryOptions);
236
+ } else {
237
+ return query(':firstAppHost', {});
238
+ }
239
+ }
240
+
241
+ /**
242
+ * @lastAppHost - Query :lastAppHost (Last <swc-app> in hierarchy)
243
+ * Usage: @lastAppHost app: SwcAppInterface | undefined;
244
+ * Usage: @lastAppHost() app: SwcAppInterface | undefined;
245
+ * Usage: @lastAppHost({ root: 'shadow' }) app: SwcAppInterface | undefined;
246
+ */
247
+ export function lastAppHost(target: Object, propertyKey: string | symbol): void;
248
+ export function lastAppHost(): PropertyDecorator;
249
+ export function lastAppHost(options: SwcQueryOptions): PropertyDecorator;
250
+ export function lastAppHost(targetOrOptions?: any, propertyKey?: string | symbol): any {
251
+ if (propertyKey !== undefined && (typeof propertyKey === 'string' || typeof propertyKey === 'symbol')) {
252
+ return query(':lastAppHost', {})(targetOrOptions, propertyKey);
253
+ }
254
+ if (typeof targetOrOptions === 'object' && targetOrOptions !== null) {
255
+ return query(':lastAppHost', targetOrOptions as SwcQueryOptions);
256
+ } else {
257
+ return query(':lastAppHost', {});
258
+ }
117
259
  }