@dooboostore/simple-web-component 1.0.24 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +162 -33
  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 +87 -194
  9. package/dist/cjs/decorators/applyNode.js.map +2 -2
  10. package/dist/cjs/decorators/{style.js → applyStyle.js} +50 -60
  11. package/dist/cjs/decorators/applyStyle.js.map +7 -0
  12. package/dist/cjs/decorators/attribute.js +10 -16
  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 +1 -1
  25. package/dist/cjs/decorators/query.js.map +2 -2
  26. package/dist/cjs/decorators/queryAll.js +1 -1
  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/utils/Utils.js +1 -1
  33. package/dist/cjs/utils/Utils.js.map +2 -2
  34. package/dist/esm/decorators/addEventListener.js +1 -1
  35. package/dist/esm/decorators/addEventListener.js.map +2 -2
  36. package/dist/esm/decorators/applyAttribute.js +129 -0
  37. package/dist/esm/decorators/applyAttribute.js.map +7 -0
  38. package/dist/esm/decorators/applyClass.js +145 -0
  39. package/dist/esm/decorators/applyClass.js.map +7 -0
  40. package/dist/esm/decorators/applyNode.js +87 -194
  41. package/dist/esm/decorators/applyNode.js.map +2 -2
  42. package/dist/esm/decorators/{style.js → applyStyle.js} +47 -57
  43. package/dist/esm/decorators/applyStyle.js.map +7 -0
  44. package/dist/esm/decorators/attribute.js +10 -16
  45. package/dist/esm/decorators/attribute.js.map +2 -2
  46. package/dist/esm/decorators/changedAttributeHost.js +1 -1
  47. package/dist/esm/decorators/changedAttributeHost.js.map +2 -2
  48. package/dist/esm/decorators/elementDefine.js +14 -23
  49. package/dist/esm/decorators/elementDefine.js.map +2 -2
  50. package/dist/esm/decorators/emitCustomEvent.js +5 -2
  51. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  52. package/dist/esm/decorators/index.js +3 -3
  53. package/dist/esm/decorators/index.js.map +1 -1
  54. package/dist/esm/decorators/lifecycles.js +9 -9
  55. package/dist/esm/decorators/lifecycles.js.map +2 -2
  56. package/dist/esm/decorators/query.js +1 -1
  57. package/dist/esm/decorators/query.js.map +2 -2
  58. package/dist/esm/decorators/queryAll.js +1 -1
  59. package/dist/esm/decorators/queryAll.js.map +2 -2
  60. package/dist/esm/elements/SwcAppEngine.js +19 -4
  61. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  62. package/dist/esm/elements/SwcAppMixin.js +2 -0
  63. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  64. package/dist/esm/utils/Utils.js +1 -1
  65. package/dist/esm/utils/Utils.js.map +2 -2
  66. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +2853 -574
  67. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  68. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  69. package/dist/types/decorators/applyAttribute.d.ts +22 -0
  70. package/dist/types/decorators/applyAttribute.d.ts.map +1 -0
  71. package/dist/types/decorators/applyClass.d.ts +65 -0
  72. package/dist/types/decorators/applyClass.d.ts.map +1 -0
  73. package/dist/types/decorators/applyNode.d.ts +15 -123
  74. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  75. package/dist/types/decorators/applyStyle.d.ts +21 -0
  76. package/dist/types/decorators/applyStyle.d.ts.map +1 -0
  77. package/dist/types/decorators/attribute.d.ts +10 -19
  78. package/dist/types/decorators/attribute.d.ts.map +1 -1
  79. package/dist/types/decorators/changedAttributeHost.d.ts.map +1 -1
  80. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  81. package/dist/types/decorators/emitCustomEvent.d.ts +1 -1
  82. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  83. package/dist/types/decorators/index.d.ts +3 -3
  84. package/dist/types/decorators/index.d.ts.map +1 -1
  85. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  86. package/dist/types/decorators/query.d.ts.map +1 -1
  87. package/dist/types/decorators/queryAll.d.ts.map +1 -1
  88. package/dist/types/elements/SwcAppEngine.d.ts +7 -0
  89. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  90. package/dist/types/elements/SwcAppMixin.d.ts +1 -1
  91. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  92. package/dist/types/utils/Utils.d.ts.map +1 -1
  93. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +2853 -574
  94. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  95. package/package.json +2 -2
  96. package/src/decorators/addEventListener.ts +1 -1
  97. package/src/decorators/applyAttribute.ts +147 -0
  98. package/src/decorators/applyClass.ts +158 -0
  99. package/src/decorators/applyNode.ts +112 -330
  100. package/src/decorators/applyStyle.ts +128 -0
  101. package/src/decorators/attribute.ts +21 -55
  102. package/src/decorators/changedAttributeHost.ts +1 -1
  103. package/src/decorators/elementDefine.ts +18 -39
  104. package/src/decorators/emitCustomEvent.ts +6 -3
  105. package/src/decorators/index.ts +3 -3
  106. package/src/decorators/lifecycles.ts +9 -11
  107. package/src/decorators/query.ts +1 -1
  108. package/src/decorators/queryAll.ts +1 -1
  109. package/src/elements/SwcAppEngine.ts +32 -4
  110. package/src/elements/SwcAppMixin.ts +2 -0
  111. package/src/utils/Utils.ts +2 -1
  112. package/dist/cjs/decorators/classList.js +0 -177
  113. package/dist/cjs/decorators/classList.js.map +0 -7
  114. package/dist/cjs/decorators/setAttribute.js +0 -111
  115. package/dist/cjs/decorators/setAttribute.js.map +0 -7
  116. package/dist/cjs/decorators/style.js.map +0 -7
  117. package/dist/esm/decorators/classList.js +0 -158
  118. package/dist/esm/decorators/classList.js.map +0 -7
  119. package/dist/esm/decorators/setAttribute.js +0 -92
  120. package/dist/esm/decorators/setAttribute.js.map +0 -7
  121. package/dist/esm/decorators/style.js.map +0 -7
  122. package/dist/types/decorators/classList.d.ts +0 -71
  123. package/dist/types/decorators/classList.d.ts.map +0 -1
  124. package/dist/types/decorators/setAttribute.d.ts +0 -23
  125. package/dist/types/decorators/setAttribute.d.ts.map +0 -1
  126. package/dist/types/decorators/style.d.ts +0 -58
  127. package/dist/types/decorators/style.d.ts.map +0 -1
  128. package/src/decorators/classList.ts +0 -234
  129. package/src/decorators/setAttribute.ts +0 -114
  130. package/src/decorators/style.ts +0 -185
@@ -3,24 +3,21 @@ import {ensureInit, getElementConfig} from './elementDefine';
3
3
  import {SwcUtils} from '../utils/Utils';
4
4
  import {SpecialSelector, SwcQueryOptions} from '../types';
5
5
 
6
- export interface 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
92
  metaList.push({propertyKey, selector, options, privateKey});
101
93
 
102
- // Helper function to apply setAttribute to targets
103
94
  const applySetAttribute = (inst: any, targets: HTMLElement[], attrName: string, nv: any) => {
104
95
  targets.forEach(it => {
105
- console.log('----->', it)
106
96
  if (it && typeof (it as any).setAttribute === 'function') {
107
97
  if (nv === null) {
108
98
  (it as any).removeAttribute(attrName);
@@ -122,8 +112,6 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
122
112
  const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
123
113
  const targetType = options.type || designType;
124
114
 
125
- console.log('type-->', propertyKey, targetType);
126
- // During early init phase, if syncing memory to DOM, return memory.
127
115
  if (this.__swc_syncing_init || (options.connectedInitialize && !this.__swc_connected)) {
128
116
  return convertValue(this[privateKey], targetType);
129
117
  }
@@ -142,33 +130,25 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
142
130
  return convertValue(this[privateKey], targetType);
143
131
  },
144
132
  set(this: any, nv: any) {
145
- const targetType = options.type || designType;
146
- // console.log('---set', propertyKey, targetType, nv, this, this.__swc_syncing_init);
147
-
148
133
  const attrName = options.name || String(propertyKey);
149
134
  const conf = getElementConfig(this);
150
135
  const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
151
136
 
152
- // During initialization/syncing phase
153
137
  if (this.__swc_syncing_init) {
154
- // If connectedInitialize is enabled, force setAttribute (JS -> DOM)
155
138
  if (options.connectedInitialize === true) {
156
139
  const targets = resolveTargetEls(this, selector, options, currentWin);
157
140
  applySetAttribute(this, targets, attrName, nv);
158
141
  } else {
159
- // Otherwise just update memory
160
142
  this[privateKey] = nv;
161
143
  }
162
144
  return;
163
145
  }
164
146
 
165
- // Before connected, save to memory only
166
147
  if (!this.__swc_connected) {
167
148
  this[privateKey] = nv;
168
149
  return;
169
150
  }
170
151
 
171
- // After connected, normal setAttribute
172
152
  const targets = resolveTargetEls(this, selector, options, currentWin);
173
153
  applySetAttribute(this, targets, attrName, nv);
174
154
  },
@@ -178,48 +158,34 @@ export function attribute(selector: string, options: AttributeOptions = {}): Pro
178
158
  };
179
159
  }
180
160
 
181
- export const findAllAttributeMetadata = (target: any): AttributeMetadata[] => {
182
- return ReflectUtils.findAllMetadata<AttributeMetadata[]>(ATTRIBUTE_METADATA_KEY, target).flat();
183
- };
184
-
185
161
  /**
186
- * @attributeHost decorator - simplified version of @attribute for :host selector
187
- * Usage: @attributeHost - uses field name as attribute name
188
- * Usage: @attributeHost() - uses field name as attribute name
189
- * Usage: @attributeHost('data-id') - uses custom attribute name
190
- * Usage: @attributeHost({ type: Boolean }) - uses field name with options
191
- * Usage: @attributeHost('data-id', { type: Boolean }) - uses custom name with options
162
+ * @attributeHost decorator to sync a field value with the :host element's attribute.
192
163
  */
193
164
  export function attributeHost(target: Object, propertyKey: string | symbol): void;
194
- export function attributeHost(): PropertyDecorator;
195
- export function attributeHost(options: AttributeOptions): PropertyDecorator;
165
+ export function attributeHost(options: AttributeFieldOptions): PropertyDecorator;
196
166
  export function attributeHost(attrName: string): PropertyDecorator;
197
- export function attributeHost(attrName: string, options: AttributeOptions): PropertyDecorator;
167
+ export function attributeHost(attrName: string, options: AttributeFieldOptions): PropertyDecorator;
198
168
  export function attributeHost(targetOrAttrOrOptions?: any, propertyKeyOrOptions?: any): any {
199
- // Direct decorator usage: @attributeHost (no parentheses)
200
169
  if (propertyKeyOrOptions !== undefined && (typeof propertyKeyOrOptions === 'string' || typeof propertyKeyOrOptions === 'symbol')) {
201
- const fieldName = String(propertyKeyOrOptions);
202
- return attribute(':host', { name: fieldName })(targetOrAttrOrOptions, propertyKeyOrOptions);
170
+ return attribute(':host', { name: String(propertyKeyOrOptions) })(targetOrAttrOrOptions, propertyKeyOrOptions);
203
171
  }
204
172
 
205
- // @attributeHost() or @attributeHost(options) or @attributeHost('name')
206
173
  if (typeof targetOrAttrOrOptions === 'string') {
207
- // @attributeHost('customName') or @attributeHost('customName', options)
208
174
  const attrName = targetOrAttrOrOptions;
209
- const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as AttributeOptions;
175
+ const options = (typeof propertyKeyOrOptions === 'object' ? propertyKeyOrOptions : {}) as AttributeFieldOptions;
210
176
  return attribute(':host', { ...options, name: attrName });
211
177
  } else if (typeof targetOrAttrOrOptions === 'object') {
212
- // @attributeHost(options) - use field name as attribute name
213
- const options = targetOrAttrOrOptions as AttributeOptions;
178
+ const options = targetOrAttrOrOptions as AttributeFieldOptions;
214
179
  return (target: Object, propertyKey: string | symbol) => {
215
- const fieldName = String(propertyKey);
216
- return attribute(':host', { ...options, name: fieldName })(target, propertyKey);
180
+ return attribute(':host', { ...options, name: String(propertyKey) })(target, propertyKey);
217
181
  };
218
182
  } else {
219
- // @attributeHost() - use field name as attribute name
220
183
  return (target: Object, propertyKey: string | symbol) => {
221
- const fieldName = String(propertyKey);
222
- return attribute(':host', { name: fieldName })(target, propertyKey);
184
+ return attribute(':host', { name: String(propertyKey) })(target, propertyKey);
223
185
  };
224
186
  }
225
187
  }
188
+
189
+ export const findAllAttributeMetadata = (target: any): AttributeFieldMetadata[] => {
190
+ return ReflectUtils.findAllMetadata<AttributeFieldMetadata[]>(ATTRIBUTE_FIELD_METADATA_KEY, target).flat();
191
+ };
@@ -1,6 +1,6 @@
1
1
  import {ReflectUtils} from '@dooboostore/core';
2
2
 
3
- export const ON_ATTRIBUTE_CHANGED_METADATA_KEY = Symbol('simple-web-component:on-attribute-changed');
3
+ export const ON_ATTRIBUTE_CHANGED_METADATA_KEY = Symbol.for('simple-web-component:on-attribute-changed');
4
4
 
5
5
  /**
6
6
  * @changedAttributeHost decorator - fires when any attribute on :host changes
@@ -4,7 +4,7 @@ import { getAddEventListenerMetadata } from './addEventListener';
4
4
  import { ON_CONSTRUCTOR_METADATA_KEY, ON_BEFORE_CONNECTED_METADATA_KEY, ON_AFTER_CONNECTED_METADATA_KEY, ON_BEFORE_DISCONNECTED_METADATA_KEY, ON_AFTER_DISCONNECTED_METADATA_KEY, ON_BEFORE_ADOPTED_METADATA_KEY, ON_AFTER_ADOPTED_METADATA_KEY, findAllLifecycleMetadata, getOnConnectedInnerHtmlMetadata } from './lifecycles';
5
5
  import { getEmitCustomEventMetadataList } from './emitCustomEvent';
6
6
  import { findAllAttributeChangedMetadata } from './changedAttributeHost';
7
- import { 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;
@@ -9,7 +9,7 @@ export interface QueryAllMetadata {
9
9
  options: SwcQueryOptions;
10
10
  }
11
11
 
12
- export const QUERY_ALL_METADATA_KEY = Symbol('simple-web-component:query-all');
12
+ export const QUERY_ALL_METADATA_KEY = Symbol.for('simple-web-component:query-all');
13
13
 
14
14
  export function queryAll(target: SpecialSelector): PropertyDecorator;
15
15
  export function queryAll(selector: string, options?: SwcQueryOptions): PropertyDecorator;
@@ -9,12 +9,19 @@ import { ConstructorType, OptionalType } from '@dooboostore/core';
9
9
  import { FunctionUtils } from '@dooboostore/core';
10
10
  import { SwcUtils } from '../utils/Utils';
11
11
 
12
+ import { SwcAppInterface } from '../types';
13
+ import {Intent} from "@dooboostore/simple-boot";
14
+
12
15
  export type SwcConfigType = {
13
16
  rootRouter: ConstructorType<any> | symbol;
14
17
  routeType: 'path' | 'hash' | 'element';
15
18
  connectMode?: 'direct' | 'swap';
19
+ container?: symbol;
16
20
  path?: string;
17
21
  window: Window;
22
+ onStarted?: (app: SwcAppInterface) => void;
23
+ onConnected?: (app: SwcAppInterface) => void;
24
+ onDisconnected?: (app: SwcAppInterface) => void;
18
25
  };
19
26
 
20
27
  export type SwcAttributeConfigType = OptionalType<SwcConfigType, 'routeType' | 'window'>;
@@ -24,9 +31,13 @@ export class SwcAppEngine {
24
31
  public router?: Router;
25
32
  private routerSubscription?: Subscription;
26
33
  private _isInitialized = false;
34
+ private _config?: SwcConfigType;
27
35
 
28
36
  constructor(private host: HTMLElement) {}
29
37
 
38
+ get config() {
39
+ return this._config;
40
+ }
30
41
  async connect(config?: SwcAttributeConfigType) {
31
42
  if (this._isInitialized) return;
32
43
 
@@ -37,10 +48,11 @@ export class SwcAppEngine {
37
48
  const configStr = this.host.getAttribute('swc-get-application-config');
38
49
  if (configStr) {
39
50
  try {
51
+ // console.log('vvvvvvvvvvvvvvvv->>>>', SwcUtils.findNearestSwcHost(this.host), SwcUtils.getHostSet(this.host))
40
52
  userConfig = FunctionUtils.executeReturn({
41
53
  script: configStr,
42
54
  context: this.host,
43
- args: SwcUtils.getHelperAndHostSet(win, this.host)
55
+ args: SwcUtils.getHelperAndHostSet(win, SwcUtils.findNearestSwcHost(this.host))
44
56
  });
45
57
  } catch (e) {
46
58
  console.error('[SWC-APP-ENGINE] Script execution failed:', e);
@@ -53,11 +65,12 @@ export class SwcAppEngine {
53
65
 
54
66
  try {
55
67
  if (userConfig.rootRouter) {
56
- const _config: SwcConfigType = {
68
+ this._config = {
57
69
  routeType: 'element',
58
70
  window: win,
59
71
  ...userConfig
60
72
  } as SwcConfigType;
73
+ const _config = this._config;
61
74
 
62
75
  // Router Selection
63
76
  if (_config.routeType === 'path') {
@@ -68,23 +81,34 @@ export class SwcAppEngine {
68
81
  this.router = new ElementRouter({ window: _config.window, firstUrl: _config.path });
69
82
  }
70
83
 
84
+ // console.log('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv', this.router)
85
+
71
86
  // Routing sync
72
87
  if (this.router) {
73
88
  this.routerSubscription = this.router.observable.subscribe((route: RouterEventType) => {
74
89
  if (route.triggerPoint === 'end') {
75
- this.simpleApplication?.routing(route.path);
90
+ const targetPath = (route.path || '/') + route.search;
91
+ const intent = new Intent(targetPath);
92
+ this.simpleApplication?.routing(intent);
76
93
  }
77
94
  });
78
95
  }
79
96
 
80
97
 
81
98
  // App start
82
- this.simpleApplication = new SimpleApplication(new SimOption({ excludeProxys: [Node], rootRouter: _config.rootRouter }));
99
+ const containerSymbol = _config.container || (this.host as any).getContainerSymbol?.();
100
+ this.simpleApplication = new SimpleApplication(new SimOption({
101
+ excludeProxys: [Node],
102
+ rootRouter: _config.rootRouter,
103
+ container: containerSymbol
104
+ }));
83
105
 
84
106
  const otherInstanceSim = new Map<any, any>();
85
107
  if (this.router) otherInstanceSim.set(Router, this.router);
86
108
  this.simpleApplication.run(otherInstanceSim);
87
109
 
110
+
111
+
88
112
  // Rendering
89
113
  const data = this.simpleApplication.sim(_config.rootRouter);
90
114
  if (data instanceof Node) {
@@ -94,12 +118,16 @@ export class SwcAppEngine {
94
118
  }
95
119
 
96
120
  if (_config.path) this.router?.go(_config.path);
121
+ if (_config.onStarted) {
122
+ _config.onStarted(this.host as unknown as SwcAppInterface);
123
+ }
97
124
  }
98
125
  } catch (e) {
99
126
  console.error('[SWC-APP-ENGINE] Init failed:', e);
100
127
  }
101
128
  }
102
129
 
130
+
103
131
  disconnect() {
104
132
  this.routerSubscription?.unsubscribe();
105
133
  }
@@ -51,12 +51,14 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
51
51
  // @ts-ignore
52
52
  if (super.connectedCallback) super.connectedCallback();
53
53
  this.connect();
54
+ this.__swc_engine?.config?.onConnected?.(this);
54
55
  }
55
56
 
56
57
  disconnectedCallback() {
57
58
  // @ts-ignore
58
59
  if (super.disconnectedCallback) super.disconnectedCallback();
59
60
  this.__swc_engine.disconnect();
61
+ this.__swc_engine?.config?.onDisconnected?.(this);
60
62
  }
61
63
 
62
64
  async routing(path: string) {
@@ -1,7 +1,7 @@
1
1
  import { SwcAppInterface, HostSet, HelperSet, HelperHostSet } from '../types';
2
2
  import {getElementConfig} from "../decorators";
3
3
 
4
- export const SWC_NOT_FOUND = Symbol('SWC_NOT_FOUND');
4
+ export const SWC_NOT_FOUND = Symbol.for('simple-web-component:not-found');
5
5
 
6
6
  // DOM Creation Utilities
7
7
  export const htmlFragment = (html: string, doc?: Document): DocumentFragment => {
@@ -187,6 +187,7 @@ export namespace SwcUtils {
187
187
  */
188
188
  export const findNearestSwcHost = (el: HTMLElement | Node): HTMLElement | undefined => {
189
189
  if ((el as any).__swc_host) return (el as any).__swc_host;
190
+ // if ((el as any).__swc_proto_setup) return (el as any).__swc_proto_setup;
190
191
 
191
192
  let current: any = el.parentElement || (el.getRootNode?.() as any)?.host;
192
193
  const doc = el.ownerDocument;