@dooboostore/simple-web-component 1.0.19 → 1.0.21

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 (146) hide show
  1. package/README.md +2028 -146
  2. package/dist/cjs/decorators/addEventListener.js +4 -4
  3. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  4. package/dist/cjs/decorators/appendChild.js +4 -4
  5. package/dist/cjs/decorators/appendChild.js.map +2 -2
  6. package/dist/cjs/decorators/attribute.js +141 -0
  7. package/dist/cjs/decorators/attribute.js.map +7 -0
  8. package/dist/cjs/decorators/changedAttribute.js +5 -5
  9. package/dist/cjs/decorators/changedAttribute.js.map +2 -2
  10. package/dist/cjs/decorators/classList.js +4 -4
  11. package/dist/cjs/decorators/classList.js.map +2 -2
  12. package/dist/cjs/decorators/elementDefine.js +36 -9
  13. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  14. package/dist/cjs/decorators/emitCustomEvent.js +4 -4
  15. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  16. package/dist/cjs/decorators/index.js +1 -0
  17. package/dist/cjs/decorators/index.js.map +2 -2
  18. package/dist/cjs/decorators/lifecycles.js +4 -4
  19. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  20. package/dist/cjs/decorators/onConnectedInnerHtml.js +4 -4
  21. package/dist/cjs/decorators/onConnectedInnerHtml.js.map +2 -2
  22. package/dist/cjs/decorators/query.js +4 -4
  23. package/dist/cjs/decorators/query.js.map +2 -2
  24. package/dist/cjs/decorators/queryAll.js +4 -4
  25. package/dist/cjs/decorators/queryAll.js.map +2 -2
  26. package/dist/cjs/decorators/replaceChildren.js +5 -5
  27. package/dist/cjs/decorators/replaceChildren.js.map +2 -2
  28. package/dist/cjs/decorators/setAttribute.js +46 -20
  29. package/dist/cjs/decorators/setAttribute.js.map +2 -2
  30. package/dist/cjs/decorators/style.js +4 -4
  31. package/dist/cjs/decorators/style.js.map +2 -2
  32. package/dist/cjs/elements/SwcAppEngine.js +8 -8
  33. package/dist/cjs/elements/SwcAppEngine.js.map +3 -3
  34. package/dist/cjs/elements/SwcAppMixin.js +28 -1
  35. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  36. package/dist/cjs/elements/SwcAsync.js +4 -4
  37. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  38. package/dist/cjs/elements/SwcChoose.js +4 -4
  39. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  40. package/dist/cjs/elements/SwcIf.js +4 -4
  41. package/dist/cjs/elements/SwcIf.js.map +2 -2
  42. package/dist/cjs/elements/SwcLoop.js +4 -4
  43. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  44. package/dist/cjs/elements/register.js +13 -13
  45. package/dist/cjs/elements/register.js.map +2 -2
  46. package/dist/cjs/index.js +1 -0
  47. package/dist/cjs/index.js.map +2 -2
  48. package/dist/cjs/router/ElementRouter.js +7 -7
  49. package/dist/cjs/router/ElementRouter.js.map +2 -2
  50. package/dist/cjs/types.js.map +1 -1
  51. package/dist/esm/decorators/addEventListener.js +1 -1
  52. package/dist/esm/decorators/addEventListener.js.map +1 -1
  53. package/dist/esm/decorators/appendChild.js +1 -1
  54. package/dist/esm/decorators/appendChild.js.map +1 -1
  55. package/dist/esm/decorators/attribute.js +122 -0
  56. package/dist/esm/decorators/attribute.js.map +7 -0
  57. package/dist/esm/decorators/changedAttribute.js +1 -1
  58. package/dist/esm/decorators/changedAttribute.js.map +1 -1
  59. package/dist/esm/decorators/classList.js +1 -1
  60. package/dist/esm/decorators/classList.js.map +1 -1
  61. package/dist/esm/decorators/elementDefine.js +31 -4
  62. package/dist/esm/decorators/elementDefine.js.map +2 -2
  63. package/dist/esm/decorators/emitCustomEvent.js +1 -1
  64. package/dist/esm/decorators/emitCustomEvent.js.map +1 -1
  65. package/dist/esm/decorators/index.js +1 -0
  66. package/dist/esm/decorators/index.js.map +2 -2
  67. package/dist/esm/decorators/lifecycles.js +1 -1
  68. package/dist/esm/decorators/lifecycles.js.map +1 -1
  69. package/dist/esm/decorators/onConnectedInnerHtml.js +1 -1
  70. package/dist/esm/decorators/onConnectedInnerHtml.js.map +1 -1
  71. package/dist/esm/decorators/query.js +1 -1
  72. package/dist/esm/decorators/query.js.map +1 -1
  73. package/dist/esm/decorators/queryAll.js +1 -1
  74. package/dist/esm/decorators/queryAll.js.map +1 -1
  75. package/dist/esm/decorators/replaceChildren.js +1 -1
  76. package/dist/esm/decorators/replaceChildren.js.map +1 -1
  77. package/dist/esm/decorators/setAttribute.js +42 -16
  78. package/dist/esm/decorators/setAttribute.js.map +2 -2
  79. package/dist/esm/decorators/style.js +1 -1
  80. package/dist/esm/decorators/style.js.map +1 -1
  81. package/dist/esm/elements/SwcAppEngine.js +4 -4
  82. package/dist/esm/elements/SwcAppEngine.js.map +2 -2
  83. package/dist/esm/elements/SwcAppMixin.js +28 -1
  84. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  85. package/dist/esm/elements/SwcAsync.js +1 -1
  86. package/dist/esm/elements/SwcAsync.js.map +1 -1
  87. package/dist/esm/elements/SwcChoose.js +1 -1
  88. package/dist/esm/elements/SwcChoose.js.map +1 -1
  89. package/dist/esm/elements/SwcIf.js +1 -1
  90. package/dist/esm/elements/SwcIf.js.map +1 -1
  91. package/dist/esm/elements/SwcLoop.js +1 -1
  92. package/dist/esm/elements/SwcLoop.js.map +1 -1
  93. package/dist/esm/elements/register.js +1 -1
  94. package/dist/esm/elements/register.js.map +1 -1
  95. package/dist/esm/index.js +1 -0
  96. package/dist/esm/index.js.map +2 -2
  97. package/dist/esm/router/ElementRouter.js +2 -2
  98. package/dist/esm/router/ElementRouter.js.map +1 -1
  99. package/dist/esm/types.js.map +1 -1
  100. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +5910 -3839
  101. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  102. package/dist/types/decorators/attribute.d.ts +23 -0
  103. package/dist/types/decorators/attribute.d.ts.map +1 -0
  104. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  105. package/dist/types/decorators/index.d.ts +1 -0
  106. package/dist/types/decorators/index.d.ts.map +1 -1
  107. package/dist/types/decorators/setAttribute.d.ts +3 -0
  108. package/dist/types/decorators/setAttribute.d.ts.map +1 -1
  109. package/dist/types/elements/SwcAppEngine.d.ts +5 -4
  110. package/dist/types/elements/SwcAppEngine.d.ts.map +1 -1
  111. package/dist/types/elements/SwcAppMixin.d.ts +1 -1
  112. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  113. package/dist/types/index.d.ts +1 -0
  114. package/dist/types/index.d.ts.map +1 -1
  115. package/dist/types/router/ElementRouter.d.ts +1 -1
  116. package/dist/types/router/ElementRouter.d.ts.map +1 -1
  117. package/dist/types/types.d.ts +2 -1
  118. package/dist/types/types.d.ts.map +1 -1
  119. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +5910 -3839
  120. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  121. package/package.json +10 -5
  122. package/src/decorators/addEventListener.ts +1 -1
  123. package/src/decorators/appendChild.ts +1 -1
  124. package/src/decorators/attribute.ts +158 -0
  125. package/src/decorators/changedAttribute.ts +1 -1
  126. package/src/decorators/classList.ts +1 -1
  127. package/src/decorators/elementDefine.ts +38 -5
  128. package/src/decorators/emitCustomEvent.ts +1 -1
  129. package/src/decorators/index.ts +1 -0
  130. package/src/decorators/lifecycles.ts +1 -1
  131. package/src/decorators/onConnectedInnerHtml.ts +1 -1
  132. package/src/decorators/query.ts +1 -1
  133. package/src/decorators/queryAll.ts +1 -1
  134. package/src/decorators/replaceChildren.ts +1 -1
  135. package/src/decorators/setAttribute.ts +49 -17
  136. package/src/decorators/style.ts +1 -1
  137. package/src/elements/SwcAppEngine.ts +9 -8
  138. package/src/elements/SwcAppMixin.ts +32 -1
  139. package/src/elements/SwcAsync.ts +1 -1
  140. package/src/elements/SwcChoose.ts +1 -1
  141. package/src/elements/SwcIf.ts +1 -1
  142. package/src/elements/SwcLoop.ts +1 -1
  143. package/src/elements/register.ts +1 -1
  144. package/src/index.ts +3 -2
  145. package/src/router/ElementRouter.ts +2 -2
  146. package/src/types.ts +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dooboostore/simple-web-component",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -54,6 +54,11 @@
54
54
  "import": "./dist/esm/index.js",
55
55
  "require": "./dist/cjs/index.js"
56
56
  },
57
+ "./bundle-entry": {
58
+ "types": "./dist/types/bundle-entry.d.ts",
59
+ "import": "./dist/esm/bundle-entry.js",
60
+ "require": "./dist/cjs/bundle-entry.js"
61
+ },
57
62
  "./*": {
58
63
  "types": "./dist/types/*.d.ts",
59
64
  "import": "./dist/esm/*.js",
@@ -87,10 +92,10 @@
87
92
  "webpack": "^5.93.0",
88
93
  "webpack-cli": "^5.1.4",
89
94
  "webpack-dev-server": "^5.2.0",
90
- "@dooboostore/core": "1.0.28",
91
- "@dooboostore/core-node": "1.0.10",
92
- "@dooboostore/core-web": "1.0.9",
93
- "@dooboostore/simple-boot": "1.0.53"
95
+ "@dooboostore/core": "1.0.30",
96
+ "@dooboostore/core-node": "1.0.12",
97
+ "@dooboostore/simple-boot": "1.0.54",
98
+ "@dooboostore/core-web": "1.0.10"
94
99
  },
95
100
  "scripts": {
96
101
  "clean": "rm -rf dist",
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { SpecialSelector, SwcQueryOptions } from '../types';
3
3
 
4
4
  export interface AddEventListenerBaseOptions extends EventListenerOptions {
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ensureInit, getElementConfig } from './elementDefine';
3
3
 
4
4
  export type AppendChildPosition = 'beforeBegin' | 'afterBegin' | 'beforeEnd' | 'afterEnd';
@@ -0,0 +1,158 @@
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
+
6
+ export interface AttributeOptions extends SwcQueryOptions {
7
+ name?: string;
8
+ connectedInitialize?: boolean;
9
+ type?: typeof Number | typeof Boolean | typeof String;
10
+ }
11
+
12
+ export interface AttributeMetadata {
13
+ propertyKey: string | symbol;
14
+ selector: string;
15
+ options: AttributeOptions;
16
+ privateKey: symbol; // Added to bypass getter during initialization
17
+ }
18
+
19
+ export const ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:attribute');
20
+
21
+ /**
22
+ * Helper to perform type conversion from string to target type
23
+ */
24
+ const convertValue = (val: string | null, type: any): any => {
25
+ if (val === null || val === undefined) return val;
26
+ if (type === Number) return Number(val);
27
+ if (type === Boolean) return val === 'false' || val === '0' ? false : true;
28
+ return val;
29
+ };
30
+
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[] => {
35
+ const r = options.root || 'auto';
36
+ const results: HTMLElement[] = [];
37
+
38
+ const applyRoot = (target: any) => {
39
+ if (!target) return;
40
+ 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
+ results.push(target);
44
+ } else {
45
+ if (r === 'light' || r === 'all') results.push(target);
46
+ if ((r === 'shadow' || r === 'all') && target.shadowRoot) results.push(target.shadowRoot);
47
+ }
48
+ };
49
+
50
+ if (selector === ':host' || !selector) {
51
+ applyRoot(inst);
52
+ } else if (selector === ':window') {
53
+ results.push(currentWin);
54
+ } else if (selector === ':document') {
55
+ results.push(currentWin.document);
56
+ } else {
57
+ const hostSet = SwcUtils.getHostSet(inst);
58
+ if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
59
+ else if (selector === ':appHost') applyRoot(hostSet.$appHost as any);
60
+ else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
61
+ else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
62
+ else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost as any);
63
+ else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost as any);
64
+ else {
65
+ if (r === 'shadow') {
66
+ const found = inst.shadowRoot?.querySelectorAll(selector);
67
+ if (found) results.push(...found);
68
+ } else if (r === 'light') {
69
+ const found = inst.querySelectorAll(selector);
70
+ if (found) results.push(...found);
71
+ } else if (r === 'all') {
72
+ const sMatch = inst.shadowRoot?.querySelectorAll(selector);
73
+ const lMatch = inst.querySelectorAll(selector);
74
+ if (sMatch) results.push(...sMatch);
75
+ if (lMatch) results.push(...lMatch);
76
+ } else {
77
+ const found = (inst.shadowRoot || inst).querySelectorAll(selector);
78
+ if (found) results.push(...found);
79
+ }
80
+ }
81
+ }
82
+ return results;
83
+ };
84
+
85
+ /**
86
+ * @attribute decorator to sync a field value with an element's attribute.
87
+ */
88
+ export function attribute(selector: string, options: AttributeOptions = {}): PropertyDecorator {
89
+ return (target: Object, propertyKey: string | symbol) => {
90
+ const constructor = target.constructor;
91
+ const privateKey = Symbol(String(propertyKey));
92
+
93
+ const designType = (Reflect as any).getMetadata('design:type', target, propertyKey);
94
+
95
+ let metaList = ReflectUtils.getOwnMetadata(ATTRIBUTE_METADATA_KEY, constructor) as AttributeMetadata[];
96
+ if (!metaList) {
97
+ metaList = [];
98
+ ReflectUtils.defineMetadata(ATTRIBUTE_METADATA_KEY, metaList, constructor);
99
+ }
100
+ metaList.push({ propertyKey, selector, options, privateKey });
101
+
102
+ Object.defineProperty(target, propertyKey, {
103
+ get(this: any) {
104
+ const attrName = options.name || String(propertyKey);
105
+ const conf = getElementConfig(this);
106
+ const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
107
+ const targetType = options.type || designType;
108
+
109
+ console.log('type-->', propertyKey, targetType);
110
+ // During early init phase, if syncing memory to DOM, return memory.
111
+ if (this.__swc_syncing_init || (options.connectedInitialize && !this.__swc_connected)) {
112
+ return convertValue(this[privateKey], targetType);
113
+ }
114
+
115
+ const targets = resolveTargetEls(this, selector, options, currentWin);
116
+ const primaryTarget = targets[0];
117
+
118
+ if (primaryTarget && typeof (primaryTarget as any).hasAttribute === 'function') {
119
+ if ((primaryTarget as any).hasAttribute(attrName)) {
120
+ const domVal = (primaryTarget as any).getAttribute(attrName);
121
+ return convertValue(domVal, targetType);
122
+ }
123
+ return null;
124
+ }
125
+
126
+ return convertValue(this[privateKey], targetType);
127
+ },
128
+ set(this: any, nv: any) {
129
+ const targetType = options.type || designType;
130
+ // const convertedValue = convertValue(nv, targetType);
131
+ // console.log('---set', propertyKey, targetType, nv, convertedValue);
132
+
133
+ const attrName = options.name || String(propertyKey);
134
+ const conf = getElementConfig(this);
135
+ const currentWin = this._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
136
+ const targets = resolveTargetEls(this, selector, options, currentWin);
137
+ targets.forEach(it => {
138
+ console.log('----->', it)
139
+ if (it && typeof (it as any).setAttribute === 'function') {
140
+ if (nv === null) {
141
+ (it as any).removeAttribute(attrName);
142
+ } else {
143
+ (it as any).setAttribute(attrName, String(nv));
144
+ }
145
+ } else {
146
+ this[privateKey] = nv;
147
+ }
148
+ })
149
+ },
150
+ enumerable: true,
151
+ configurable: true
152
+ });
153
+ };
154
+ }
155
+
156
+ export const findAllAttributeMetadata = (target: any): AttributeMetadata[] => {
157
+ return ReflectUtils.findAllMetadata<AttributeMetadata[]>(ATTRIBUTE_METADATA_KEY, target).flat();
158
+ };
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
 
3
3
  export const ON_ATTRIBUTE_CHANGED_METADATA_KEY = Symbol('simple-web-component:on-attribute-changed');
4
4
 
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ensureInit } from './elementDefine';
3
3
  import { SwcUtils } from '../utils/Utils';
4
4
 
@@ -1,5 +1,5 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
2
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
+ import { FunctionUtils } from '@dooboostore/core';
3
3
  import { getOnConnectedInnerHtmlMetadata } from './onConnectedInnerHtml';
4
4
  import { getAddEventListenerMetadata } from './addEventListener';
5
5
  import { 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 } from './lifecycles';
@@ -10,12 +10,13 @@ import { findAllReplaceChildrenMetadata } from './replaceChildren';
10
10
  import { findAllAppendChildMetadata } from './appendChild';
11
11
  import { findAllClassListMetadata } from './classList';
12
12
  import { findAllStyleMetadata } from './style';
13
+ import { findAllAttributeMetadata } from './attribute';
13
14
  import { SwcUtils } from '../utils/Utils';
14
15
  import { HTML_TAG_ENTRIES, DOM_EVENT_NAMES } from '../config/config';
15
16
  import { SituationTypeContainer, SituationTypeContainers } from '@dooboostore/simple-boot/decorators/inject/Inject';
16
17
  import { InjectSituationType, HostSet } from '../types';
17
18
 
18
- // --- Core Interfaces & Types (Moved back from base.ts) ---
19
+ // --- Core Interfaces & Types ---
19
20
 
20
21
  export const ELEMENT_CONFIG_KEY = Symbol('simple-web-component:element-config');
21
22
 
@@ -221,12 +222,13 @@ export const elementDefine =
221
222
  const emitCustomEventList = getEmitCustomEventMetadataList(constructor) || [];
222
223
  const addEventListenerList = getAddEventListenerMetadata(constructor) || [];
223
224
  const attrChangeMap = findAllAttributeChangedMetadata(constructor);
225
+ const attributeList = findAllAttributeMetadata(constructor);
224
226
 
225
227
  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'];
226
228
  const swcOnEvents = DOM_EVENT_NAMES.map(e => `swc-on-${e}`);
227
229
 
228
230
  // Collect all observed attributes from all decorators
229
- const mergedObservedAttributes = [...new Set([...(metadata.observedAttributes ?? []), ...attrChangeMap.keys(), ...Array.from(findAllSetAttributeMetadata(constructor).values()).map(it => it.name), ...emitCustomEventList.map(it => it.options.attributeName!), ...swcLifecycleAttributes, ...swcOnEvents])];
231
+ 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)), ...emitCustomEventList.map(it => it.options.attributeName!), ...swcLifecycleAttributes, ...swcOnEvents])];
230
232
 
231
233
  const connectedInnerHtmlList = getOnConnectedInnerHtmlMetadata(constructor) || [];
232
234
 
@@ -251,7 +253,33 @@ export const elementDefine =
251
253
  for (const m of bMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
252
254
  }
253
255
 
254
- if (typeof (this as any).initCore === 'function') (this as any).initCore();
256
+ // Initialize @attribute fields (DOM <-> JS Sync)
257
+ attributeList.forEach(meta => {
258
+ const attrName = meta.options.name || String(meta.propertyKey);
259
+ if (meta.options.connectedInitialize) {
260
+ // JS -> DOM (FORCE OVERWRITE)
261
+ const memoryVal = (this as any)[meta.privateKey];
262
+ if (memoryVal !== undefined) {
263
+ (this as any).__swc_syncing_init = true;
264
+ try {
265
+ (this as any)[meta.propertyKey] = memoryVal; // Trigger setter to update DOM
266
+ } finally {
267
+ (this as any).__swc_syncing_init = false;
268
+ }
269
+ }
270
+ } else if (meta.selector === ':host' || !meta.selector) {
271
+ // DOM -> JS (Pull from HTML)
272
+ const domVal = this.getAttribute(attrName);
273
+ if (domVal !== null) {
274
+ (this as any).__swc_syncing_init = true;
275
+ try {
276
+ (this as any)[meta.propertyKey] = domVal; // Update memory with DOM value
277
+ } finally {
278
+ (this as any).__swc_syncing_init = false;
279
+ }
280
+ }
281
+ }
282
+ });
255
283
 
256
284
  if (connectedInnerHtmlList.length > 0) {
257
285
  let sContent = '',
@@ -360,12 +388,14 @@ export const elementDefine =
360
388
  });
361
389
 
362
390
  if (originalConnected) originalConnected.apply(this);
391
+
363
392
  const aMethods = findAllLifecycleMetadata(this, ON_AFTER_CONNECTED_METADATA_KEY);
364
393
  if (aMethods) {
365
394
  for (const m of aMethods) (this as any)._invokeLifecycleMethod(m, hostSet);
366
395
  }
367
396
  (this as any)._executeSwcScript('swc-on-connected', hostSet);
368
397
  (this as any)._executeSwcScript('swc-on-after-connected', hostSet);
398
+ (this as any).__swc_connected = true;
369
399
  };
370
400
 
371
401
  const originalDisconnected = proto.disconnectedCallback;
@@ -390,6 +420,7 @@ export const elementDefine =
390
420
  }
391
421
  (this as any)._executeSwcScript('swc-on-disconnected', hostSet);
392
422
  (this as any)._executeSwcScript('swc-on-after-disconnected', hostSet);
423
+ (this as any).__swc_connected = false;
393
424
  };
394
425
 
395
426
  const originalAdopted = proto.adoptedCallback;
@@ -415,6 +446,7 @@ export const elementDefine =
415
446
  proto.attributeChangedCallback = function (name: string, old: string | null, newVal: string | null) {
416
447
  if (originalAttributeChanged) originalAttributeChanged.apply(this, [name, old, newVal]);
417
448
 
449
+ // Handle swc-on-* events
418
450
  if (name.startsWith('swc-on-') && !swcLifecycleAttributes.includes(name)) {
419
451
  if (newVal !== null) {
420
452
  const customEventMeta = emitCustomEventList.find(it => it.options.attributeName === name);
@@ -423,6 +455,7 @@ export const elementDefine =
423
455
  }
424
456
  }
425
457
 
458
+ // Handle @changedAttribute callbacks
426
459
  const mKeys = attrChangeMap.get(name);
427
460
  if (mKeys && Array.isArray(mKeys)) {
428
461
  const hSet = SwcUtils.getHostSet(this as any);
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { SpecialSelector, SwcQueryOptions } from '../types';
3
3
  import { ensureInit, getElementConfig } from './elementDefine';
4
4
  import { SwcUtils } from '../utils/Utils';
@@ -1,4 +1,5 @@
1
1
  export * from './addEventListener';
2
+ export * from './attribute';
2
3
  export * from './elementDefine';
3
4
  export * from './changedAttribute';
4
5
  export * from './setAttribute';
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ON_ATTRIBUTE_CHANGED_METADATA_KEY } from './changedAttribute';
3
3
  import { SET_ATTRIBUTE_METADATA_KEY } from './setAttribute';
4
4
 
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
 
3
3
  export interface InnerHtmlOptions {
4
4
  useShadow?: boolean;
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { getElementConfig, ensureInit } from './elementDefine';
3
3
  import { SwcUtils } from '../utils/Utils';
4
4
  import { SpecialSelector, SwcQueryOptions } from '../types';
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { getElementConfig, ensureInit } from './elementDefine';
3
3
  import { SwcUtils } from '../utils/Utils';
4
4
  import { SpecialSelector, SwcQueryOptions } from '../types';
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ensureInit, getElementConfig } from './elementDefine';
3
3
 
4
4
  export const REPLACE_CHILDREN_METADATA_KEY = Symbol('simple-web-component:replace-children');
@@ -1,11 +1,13 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ensureInit, getElementConfig } from './elementDefine';
3
3
  import { SwcUtils } from '../utils/Utils';
4
+ import { SwcQueryOptions } from '../types';
4
5
 
5
6
  export interface SetAttributeMetadata {
6
7
  propertyKey: string | symbol;
7
8
  selector: string;
8
9
  name: string;
10
+ options: SwcQueryOptions;
9
11
  }
10
12
 
11
13
  export const SET_ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:set-attribute');
@@ -15,7 +17,9 @@ export const SET_ATTRIBUTE_METADATA_KEY = Symbol('simple-web-component:set-attri
15
17
  * Usage: @setAttribute(':host', 'count')
16
18
  * Usage: @setAttribute('#child', 'disabled')
17
19
  */
18
- export function setAttribute(selector: string, name: string): MethodDecorator {
20
+ export function setAttribute(selector: string, name: string): MethodDecorator;
21
+ export function setAttribute(selector: string, name: string, options?: SwcQueryOptions): MethodDecorator;
22
+ export function setAttribute(selector: string, name: string, options: SwcQueryOptions = {}): MethodDecorator {
19
23
  return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
20
24
  const constructor = target.constructor;
21
25
  let metaList = ReflectUtils.getOwnMetadata(SET_ATTRIBUTE_METADATA_KEY, constructor) as Map<string | symbol, SetAttributeMetadata>;
@@ -23,7 +27,7 @@ export function setAttribute(selector: string, name: string): MethodDecorator {
23
27
  metaList = new Map<string | symbol, SetAttributeMetadata>();
24
28
  ReflectUtils.defineMetadata(SET_ATTRIBUTE_METADATA_KEY, metaList, constructor);
25
29
  }
26
- metaList.set(propertyKey, { propertyKey, selector, name });
30
+ metaList.set(propertyKey, { propertyKey, selector, name, options });
27
31
 
28
32
  const original = descriptor.value;
29
33
  descriptor.value = async function (...args: any[]) {
@@ -34,22 +38,50 @@ export function setAttribute(selector: string, name: string): MethodDecorator {
34
38
  const conf = getElementConfig(this);
35
39
  const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
36
40
 
37
- let targetEl: HTMLElement | null = null;
38
- if (selector === ':host' || !selector) targetEl = this as any;
39
- else if (selector === ':window') targetEl = currentWin as any;
40
- else if (selector === ':document') targetEl = currentWin.document as any;
41
- else if (selector === ':parentHost') targetEl = hostSet.$parentHost;
42
- else if (selector === ':appHost') targetEl = hostSet.$appHost;
43
- else if (selector === ':firstHost') targetEl = hostSet.$firstHost;
44
- else if (selector === ':lastHost') targetEl = hostSet.$lastHost;
45
- else if (selector === ':firstAppHost') targetEl = hostSet.$firstAppHost;
46
- else if (selector === ':lastAppHost') targetEl = hostSet.$lastAppHost;
47
- else targetEl = (this.shadowRoot || (this as any)).querySelector(selector);
41
+ const targetEls: any[] = [];
42
+ const r = options.root || 'auto';
48
43
 
49
- if (targetEl) {
50
- if (res === null) targetEl.removeAttribute(name);
51
- else targetEl.setAttribute(name, String(res));
44
+ const applyRoot = (t: any) => {
45
+ if (!t) return;
46
+ if (r === 'auto') {
47
+ targetEls.push((t as any).shadowRoot || t);
48
+ return;
49
+ }
50
+ if (r === 'light' || r === 'all') targetEls.push(t);
51
+ if ((r === 'shadow' || r === 'all') && (t as any).shadowRoot) targetEls.push((t as any).shadowRoot);
52
+ };
53
+
54
+ if (selector === ':window') targetEls.push(currentWin);
55
+ else if (selector === ':document') targetEls.push(currentWin.document as any);
56
+ else if (selector === ':parentHost') applyRoot(hostSet.$parentHost);
57
+ else if (selector === ':appHost') applyRoot(hostSet.$appHost);
58
+ else if (selector === ':firstHost') applyRoot(hostSet.$firstHost);
59
+ else if (selector === ':lastHost') applyRoot(hostSet.$lastHost);
60
+ else if (selector === ':firstAppHost') applyRoot(hostSet.$firstAppHost);
61
+ else if (selector === ':lastAppHost') applyRoot(hostSet.$lastAppHost);
62
+ else if (selector === ':hosts') hostSet.$hosts.forEach(applyRoot);
63
+ else if (selector === ':appHosts') hostSet.$appHosts.forEach(applyRoot);
64
+ else if (selector === ':host' || !selector) applyRoot(this);
65
+ else {
66
+ const roots: any[] = [];
67
+ if (r === 'shadow') {
68
+ if ((this as any).shadowRoot) roots.push((this as any).shadowRoot);
69
+ } else if (r === 'light') {
70
+ roots.push(this as any);
71
+ } else if (r === 'all') {
72
+ roots.push(this as any);
73
+ if ((this as any).shadowRoot) roots.push((this as any).shadowRoot);
74
+ } else {
75
+ roots.push((this as any).shadowRoot || (this as any));
76
+ }
77
+ roots.forEach(root => targetEls.push(...root.querySelectorAll(selector)));
52
78
  }
79
+
80
+ targetEls.forEach(targetEl => {
81
+ if (!targetEl || typeof (targetEl as any).setAttribute !== 'function') return;
82
+ if (res === null) (targetEl as any).removeAttribute(name);
83
+ else (targetEl as any).setAttribute(name, String(res));
84
+ })
53
85
  }
54
86
  return res;
55
87
  };
@@ -1,4 +1,4 @@
1
- import { ReflectUtils } from '@dooboostore/core/reflect/ReflectUtils';
1
+ import { ReflectUtils } from '@dooboostore/core';
2
2
  import { ensureInit } from './elementDefine';
3
3
  import { SwcUtils } from '../utils/Utils';
4
4
 
@@ -1,22 +1,23 @@
1
1
  import { SimpleApplication } from '@dooboostore/simple-boot/SimpleApplication';
2
- import { PathRouter } from '@dooboostore/core-web/routers/PathRouter';
3
- import { HashRouter } from '@dooboostore/core-web/routers/HashRouter';
2
+ import { PathRouter } from '@dooboostore/core-web';
3
+ import { HashRouter } from '@dooboostore/core-web';
4
4
  import { ElementRouter } from '../router/ElementRouter';
5
5
  import { SimOption } from '@dooboostore/simple-boot/SimOption';
6
- import { Router, RouterEventType } from '@dooboostore/core-web/routers/Router';
7
- import { Subscription } from '@dooboostore/core/message/Subscription';
8
- import { ConstructorType, Optional } from '@dooboostore/core/types';
9
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
6
+ import { Router, RouterEventType } from '@dooboostore/core-web';
7
+ import { Subscription } from '@dooboostore/core';
8
+ import { ConstructorType, OptionalType } from '@dooboostore/core';
9
+ import { FunctionUtils } from '@dooboostore/core';
10
10
  import { SwcUtils } from '../utils/Utils';
11
11
 
12
12
  export type SwcConfigType = {
13
- rootRouter: ConstructorType<any> | Symbol;
13
+ rootRouter: ConstructorType<any> | symbol;
14
14
  routeType: 'path' | 'hash' | 'element';
15
+ connectMode?: 'direct' | 'swap';
15
16
  path?: string;
16
17
  window: Window;
17
18
  };
18
19
 
19
- export type SwcAttributeConfigType = Optional<SwcConfigType, 'routeType' | 'window'>;
20
+ export type SwcAttributeConfigType = OptionalType<SwcConfigType, 'routeType' | 'window'>;
20
21
 
21
22
  export class SwcAppEngine {
22
23
  public simpleApplication?: SimpleApplication;
@@ -12,7 +12,38 @@ export function SwcAppMixin<T extends { new (...args: any[]): HTMLElement }>(Bas
12
12
  }
13
13
 
14
14
  async connect(config?: SwcAttributeConfigType) {
15
- await this.__swc_engine.connect(config);
15
+ const mode = config?.connectMode || 'direct';
16
+
17
+ if (mode !== 'swap') {
18
+ await this.__swc_engine.connect(config);
19
+ this.setAttribute('swc-connect-mode', 'direct');
20
+ return;
21
+ }
22
+
23
+ const parent = this.parentNode;
24
+ if (!parent) {
25
+ await this.__swc_engine.connect(config);
26
+ this.setAttribute('swc-connect-mode', 'direct');
27
+ return;
28
+ }
29
+
30
+ const clonedApp = this.cloneNode(true) as any;
31
+ clonedApp.style.display = 'none';
32
+ parent.insertBefore(clonedApp, this.nextSibling);
33
+
34
+ try {
35
+ await clonedApp.connect({ ...(config || {}), connectMode: 'direct' });
36
+ if (this.parentNode) {
37
+ this.parentNode.removeChild(this);
38
+ }
39
+ clonedApp.setAttribute('swc-connect-mode', 'swap');
40
+ clonedApp.style.display = '';
41
+ } catch (e) {
42
+ if (clonedApp.parentNode) {
43
+ clonedApp.parentNode.removeChild(clonedApp);
44
+ }
45
+ throw e;
46
+ }
16
47
  }
17
48
 
18
49
  connectedCallback() {
@@ -1,6 +1,6 @@
1
1
  import { changedAttribute } from '../decorators/changedAttribute';
2
2
  import { SwcUtils } from '../utils/Utils';
3
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
3
+ import { FunctionUtils } from '@dooboostore/core';
4
4
 
5
5
  export class SwcAsync extends HTMLTemplateElement {
6
6
  private _nodes: Node[] = [];
@@ -1,6 +1,6 @@
1
1
  import { changedAttribute } from '../decorators/changedAttribute';
2
2
  import { SwcUtils } from '../utils/Utils';
3
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
3
+ import { FunctionUtils } from '@dooboostore/core';
4
4
 
5
5
  export class SwcChoose extends HTMLTemplateElement {
6
6
  private _nodes: Node[] = [];
@@ -1,6 +1,6 @@
1
1
  import { changedAttribute } from '../decorators/changedAttribute';
2
2
  import { SwcUtils } from '../utils/Utils';
3
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
3
+ import { FunctionUtils } from '@dooboostore/core';
4
4
 
5
5
  export class SwcIf extends HTMLTemplateElement {
6
6
  private _value = false;
@@ -1,6 +1,6 @@
1
1
  import { changedAttribute } from '../decorators/changedAttribute';
2
2
  import { SwcUtils } from '../utils/Utils';
3
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
3
+ import { FunctionUtils } from '@dooboostore/core';
4
4
 
5
5
  export class SwcLoop extends HTMLTemplateElement {
6
6
  private _value: any[] = [];
@@ -1,7 +1,7 @@
1
1
  import { elementDefine } from '../decorators/elementDefine';
2
2
  import { SwcAppMixin } from './SwcAppMixin';
3
3
  import { SwcUtils } from '../utils/Utils';
4
- import { FunctionUtils } from '@dooboostore/core/function/FunctionUtils';
4
+ import { FunctionUtils } from '@dooboostore/core';
5
5
  import { changedAttribute } from '../decorators/changedAttribute';
6
6
 
7
7
  export const registerAllElements = (w: any) => {
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import { registerAllElements } from './elements/register';
3
3
 
4
4
  // Decorators
5
5
  export * from './decorators/elementDefine';
6
+ export * from './decorators/attribute';
6
7
  export * from './decorators/setAttribute';
7
8
  export * from './decorators/changedAttribute';
8
9
  export { onConnectedInnerHtml } from './decorators/onConnectedInnerHtml';
@@ -27,9 +28,9 @@ export * from './utils/TemplateUtils';
27
28
  export * from './config/config';
28
29
 
29
30
  // Registration Factory
30
- export default (w: Window, other?: ((w:Window)=>void)[]): void => {
31
+ export default (w: Window, other?: ((w: Window) => void)[]): void => {
31
32
  registerAllElements(w);
32
33
  other?.forEach(fn => {
33
- fn(w);
34
+ fn(w);
34
35
  });
35
36
  };
@@ -1,5 +1,5 @@
1
- import { ChangeStateConfig, ChangeStateResult, RouteAction, Router, RouterConfig, RouterMethodOptions } from '@dooboostore/core-web/routers/Router';
2
- import { UrlUtils } from '@dooboostore/core/url/UrlUtils';
1
+ import { ChangeStateConfig, ChangeStateResult, RouteAction, Router, RouterConfig, RouterMethodOptions } from '@dooboostore/core-web';
2
+ import { UrlUtils } from '@dooboostore/core';
3
3
 
4
4
  export class ElementRouter extends Router {
5
5
  private _history: { url: string; data: any; title?: string }[] = [];