@dooboostore/simple-web-component 1.0.49 → 1.0.51

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 (251) hide show
  1. package/README.md +790 -337
  2. package/dist/cjs/SwcAppEngine.js.map +2 -2
  3. package/dist/cjs/decorators/addEventListener.js +1925 -22
  4. package/dist/cjs/decorators/addEventListener.js.map +2 -2
  5. package/dist/cjs/decorators/applyAttribute.js +41 -47
  6. package/dist/cjs/decorators/applyAttribute.js.map +2 -2
  7. package/dist/cjs/decorators/applyClass.js +14 -11
  8. package/dist/cjs/decorators/applyClass.js.map +2 -2
  9. package/dist/cjs/decorators/applyNode.js +19 -21
  10. package/dist/cjs/decorators/applyNode.js.map +2 -2
  11. package/dist/cjs/decorators/applyProperty.js +24 -48
  12. package/dist/cjs/decorators/applyProperty.js.map +2 -2
  13. package/dist/cjs/decorators/applySlot.js +9 -8
  14. package/dist/cjs/decorators/applySlot.js.map +2 -2
  15. package/dist/cjs/decorators/applyStyle.js +14 -11
  16. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  17. package/dist/cjs/decorators/around.js +124 -0
  18. package/dist/cjs/decorators/around.js.map +7 -0
  19. package/dist/cjs/decorators/changedAttribute.js +61 -24
  20. package/dist/cjs/decorators/changedAttribute.js.map +2 -2
  21. package/dist/cjs/decorators/elementDefine.js +240 -196
  22. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  23. package/dist/cjs/decorators/emitCustomEvent.js +14 -12
  24. package/dist/cjs/decorators/emitCustomEvent.js.map +2 -2
  25. package/dist/cjs/decorators/eventMedia.js +112 -0
  26. package/dist/cjs/decorators/eventMedia.js.map +7 -0
  27. package/dist/cjs/decorators/fetch.js +278 -0
  28. package/dist/cjs/decorators/fetch.js.map +7 -0
  29. package/dist/cjs/decorators/index.js +8 -2
  30. package/dist/cjs/decorators/index.js.map +2 -2
  31. package/dist/cjs/decorators/intersectionObserver.js +76 -65
  32. package/dist/cjs/decorators/intersectionObserver.js.map +2 -2
  33. package/dist/cjs/decorators/lifecycles.js +11 -11
  34. package/dist/cjs/decorators/lifecycles.js.map +2 -2
  35. package/dist/cjs/decorators/mutationObserver.js +97 -90
  36. package/dist/cjs/decorators/mutationObserver.js.map +3 -3
  37. package/dist/cjs/decorators/parameter.js +156 -0
  38. package/dist/cjs/decorators/parameter.js.map +7 -0
  39. package/dist/cjs/decorators/publishSwcAppMessage.js +2 -2
  40. package/dist/cjs/decorators/publishSwcAppMessage.js.map +2 -2
  41. package/dist/cjs/decorators/query.js +11 -5
  42. package/dist/cjs/decorators/query.js.map +2 -2
  43. package/dist/cjs/decorators/requestAnimationFrame.js +115 -0
  44. package/dist/cjs/decorators/requestAnimationFrame.js.map +7 -0
  45. package/dist/cjs/decorators/resizeObserver.js +84 -69
  46. package/dist/cjs/decorators/resizeObserver.js.map +3 -3
  47. package/dist/cjs/decorators/setInterval.js +65 -22
  48. package/dist/cjs/decorators/setInterval.js.map +2 -2
  49. package/dist/cjs/decorators/setTimeout.js +68 -22
  50. package/dist/cjs/decorators/setTimeout.js.map +2 -2
  51. package/dist/cjs/decorators/state.js +13 -10
  52. package/dist/cjs/decorators/state.js.map +2 -2
  53. package/dist/cjs/decorators/{subscribeSwcAppMessageWhileConnected.js → subscribeSwcAppMessage.js} +20 -21
  54. package/dist/cjs/decorators/subscribeSwcAppMessage.js.map +7 -0
  55. package/dist/cjs/decorators/{subscribeSwcAppRouteChangeWhileConnected.js → subscribeSwcAppRouteChange.js} +23 -19
  56. package/dist/cjs/decorators/subscribeSwcAppRouteChange.js.map +7 -0
  57. package/dist/cjs/decorators/swcAppRoute.js +149 -0
  58. package/dist/cjs/decorators/swcAppRoute.js.map +7 -0
  59. package/dist/cjs/elements/SwcApp.js +70 -0
  60. package/dist/cjs/elements/SwcApp.js.map +2 -2
  61. package/dist/cjs/elements/SwcAppMixin.js +256 -67
  62. package/dist/cjs/elements/SwcAppMixin.js.map +3 -3
  63. package/dist/cjs/types/index.js +5 -1
  64. package/dist/cjs/types/index.js.map +2 -2
  65. package/dist/cjs/types/window.d.js.map +1 -1
  66. package/dist/cjs/utils/Utils.js +36 -15
  67. package/dist/cjs/utils/Utils.js.map +2 -2
  68. package/dist/esm/SwcAppEngine.js.map +2 -2
  69. package/dist/esm/decorators/addEventListener.js +1925 -22
  70. package/dist/esm/decorators/addEventListener.js.map +2 -2
  71. package/dist/esm/decorators/applyAttribute.js +41 -47
  72. package/dist/esm/decorators/applyAttribute.js.map +2 -2
  73. package/dist/esm/decorators/applyClass.js +14 -11
  74. package/dist/esm/decorators/applyClass.js.map +2 -2
  75. package/dist/esm/decorators/applyNode.js +20 -22
  76. package/dist/esm/decorators/applyNode.js.map +2 -2
  77. package/dist/esm/decorators/applyProperty.js +24 -48
  78. package/dist/esm/decorators/applyProperty.js.map +2 -2
  79. package/dist/esm/decorators/applySlot.js +9 -8
  80. package/dist/esm/decorators/applySlot.js.map +2 -2
  81. package/dist/esm/decorators/applyStyle.js +14 -11
  82. package/dist/esm/decorators/applyStyle.js.map +2 -2
  83. package/dist/esm/decorators/around.js +105 -0
  84. package/dist/esm/decorators/around.js.map +7 -0
  85. package/dist/esm/decorators/changedAttribute.js +61 -24
  86. package/dist/esm/decorators/changedAttribute.js.map +2 -2
  87. package/dist/esm/decorators/elementDefine.js +238 -194
  88. package/dist/esm/decorators/elementDefine.js.map +3 -3
  89. package/dist/esm/decorators/emitCustomEvent.js +15 -13
  90. package/dist/esm/decorators/emitCustomEvent.js.map +2 -2
  91. package/dist/esm/decorators/eventMedia.js +94 -0
  92. package/dist/esm/decorators/eventMedia.js.map +7 -0
  93. package/dist/esm/decorators/fetch.js +259 -0
  94. package/dist/esm/decorators/fetch.js.map +7 -0
  95. package/dist/esm/decorators/index.js +8 -2
  96. package/dist/esm/decorators/index.js.map +2 -2
  97. package/dist/esm/decorators/intersectionObserver.js +76 -65
  98. package/dist/esm/decorators/intersectionObserver.js.map +2 -2
  99. package/dist/esm/decorators/lifecycles.js +11 -11
  100. package/dist/esm/decorators/lifecycles.js.map +2 -2
  101. package/dist/esm/decorators/mutationObserver.js +97 -90
  102. package/dist/esm/decorators/mutationObserver.js.map +3 -3
  103. package/dist/esm/decorators/parameter.js +137 -0
  104. package/dist/esm/decorators/parameter.js.map +7 -0
  105. package/dist/esm/decorators/publishSwcAppMessage.js +2 -2
  106. package/dist/esm/decorators/publishSwcAppMessage.js.map +2 -2
  107. package/dist/esm/decorators/query.js +11 -5
  108. package/dist/esm/decorators/query.js.map +2 -2
  109. package/dist/esm/decorators/requestAnimationFrame.js +96 -0
  110. package/dist/esm/decorators/requestAnimationFrame.js.map +7 -0
  111. package/dist/esm/decorators/resizeObserver.js +84 -69
  112. package/dist/esm/decorators/resizeObserver.js.map +2 -2
  113. package/dist/esm/decorators/setInterval.js +65 -23
  114. package/dist/esm/decorators/setInterval.js.map +2 -2
  115. package/dist/esm/decorators/setTimeout.js +68 -23
  116. package/dist/esm/decorators/setTimeout.js.map +2 -2
  117. package/dist/esm/decorators/state.js +13 -10
  118. package/dist/esm/decorators/state.js.map +2 -2
  119. package/dist/esm/decorators/subscribeSwcAppMessage.js +53 -0
  120. package/dist/esm/decorators/subscribeSwcAppMessage.js.map +7 -0
  121. package/dist/esm/decorators/{subscribeSwcAppRouteChangeWhileConnected.js → subscribeSwcAppRouteChange.js} +20 -16
  122. package/dist/esm/decorators/subscribeSwcAppRouteChange.js.map +7 -0
  123. package/dist/esm/decorators/swcAppRoute.js +130 -0
  124. package/dist/esm/decorators/swcAppRoute.js.map +7 -0
  125. package/dist/esm/elements/SwcApp.js +70 -0
  126. package/dist/esm/elements/SwcApp.js.map +2 -2
  127. package/dist/esm/elements/SwcAppMixin.js +258 -69
  128. package/dist/esm/elements/SwcAppMixin.js.map +3 -3
  129. package/dist/esm/types/index.js +5 -1
  130. package/dist/esm/types/index.js.map +2 -2
  131. package/dist/esm/utils/Utils.js +36 -15
  132. package/dist/esm/utils/Utils.js.map +2 -2
  133. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +4395 -1266
  134. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  135. package/dist/types/SwcAppEngine.d.ts +1 -0
  136. package/dist/types/SwcAppEngine.d.ts.map +1 -1
  137. package/dist/types/decorators/addEventListener.d.ts +936 -11
  138. package/dist/types/decorators/addEventListener.d.ts.map +1 -1
  139. package/dist/types/decorators/applyAttribute.d.ts +27 -37
  140. package/dist/types/decorators/applyAttribute.d.ts.map +1 -1
  141. package/dist/types/decorators/applyClass.d.ts +2 -2
  142. package/dist/types/decorators/applyClass.d.ts.map +1 -1
  143. package/dist/types/decorators/applyNode.d.ts +16 -16
  144. package/dist/types/decorators/applyNode.d.ts.map +1 -1
  145. package/dist/types/decorators/applyProperty.d.ts +28 -44
  146. package/dist/types/decorators/applyProperty.d.ts.map +1 -1
  147. package/dist/types/decorators/applySlot.d.ts.map +1 -1
  148. package/dist/types/decorators/applyStyle.d.ts +2 -2
  149. package/dist/types/decorators/applyStyle.d.ts.map +1 -1
  150. package/dist/types/decorators/around.d.ts +87 -0
  151. package/dist/types/decorators/around.d.ts.map +1 -0
  152. package/dist/types/decorators/changedAttribute.d.ts +22 -4
  153. package/dist/types/decorators/changedAttribute.d.ts.map +1 -1
  154. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  155. package/dist/types/decorators/emitCustomEvent.d.ts +0 -1
  156. package/dist/types/decorators/emitCustomEvent.d.ts.map +1 -1
  157. package/dist/types/decorators/eventMedia.d.ts +48 -0
  158. package/dist/types/decorators/eventMedia.d.ts.map +1 -0
  159. package/dist/types/decorators/fetch.d.ts +139 -0
  160. package/dist/types/decorators/fetch.d.ts.map +1 -0
  161. package/dist/types/decorators/index.d.ts +8 -2
  162. package/dist/types/decorators/index.d.ts.map +1 -1
  163. package/dist/types/decorators/intersectionObserver.d.ts +32 -10
  164. package/dist/types/decorators/intersectionObserver.d.ts.map +1 -1
  165. package/dist/types/decorators/lifecycles.d.ts +8 -7
  166. package/dist/types/decorators/lifecycles.d.ts.map +1 -1
  167. package/dist/types/decorators/mutationObserver.d.ts +34 -12
  168. package/dist/types/decorators/mutationObserver.d.ts.map +1 -1
  169. package/dist/types/decorators/parameter.d.ts +113 -0
  170. package/dist/types/decorators/parameter.d.ts.map +1 -0
  171. package/dist/types/decorators/publishSwcAppMessage.d.ts +0 -1
  172. package/dist/types/decorators/publishSwcAppMessage.d.ts.map +1 -1
  173. package/dist/types/decorators/query.d.ts +7 -7
  174. package/dist/types/decorators/query.d.ts.map +1 -1
  175. package/dist/types/decorators/requestAnimationFrame.d.ts +47 -0
  176. package/dist/types/decorators/requestAnimationFrame.d.ts.map +1 -0
  177. package/dist/types/decorators/resizeObserver.d.ts +34 -12
  178. package/dist/types/decorators/resizeObserver.d.ts.map +1 -1
  179. package/dist/types/decorators/setInterval.d.ts +27 -5
  180. package/dist/types/decorators/setInterval.d.ts.map +1 -1
  181. package/dist/types/decorators/setTimeout.d.ts +27 -5
  182. package/dist/types/decorators/setTimeout.d.ts.map +1 -1
  183. package/dist/types/decorators/state.d.ts.map +1 -1
  184. package/dist/types/decorators/subscribeSwcAppMessage.d.ts +44 -0
  185. package/dist/types/decorators/subscribeSwcAppMessage.d.ts.map +1 -0
  186. package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts +60 -0
  187. package/dist/types/decorators/subscribeSwcAppRouteChange.d.ts.map +1 -0
  188. package/dist/types/decorators/swcAppRoute.d.ts +94 -0
  189. package/dist/types/decorators/swcAppRoute.d.ts.map +1 -0
  190. package/dist/types/elements/SwcApp.d.ts.map +1 -1
  191. package/dist/types/elements/SwcAppMixin.d.ts +423 -388
  192. package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
  193. package/dist/types/types/index.d.ts +43 -4
  194. package/dist/types/types/index.d.ts.map +1 -1
  195. package/dist/types/utils/Utils.d.ts +15 -5
  196. package/dist/types/utils/Utils.d.ts.map +1 -1
  197. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +4395 -1266
  198. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  199. package/package.json +8 -6
  200. package/src/SwcAppEngine.ts +1 -0
  201. package/src/decorators/addEventListener.ts +1086 -28
  202. package/src/decorators/applyAttribute.ts +82 -134
  203. package/src/decorators/applyClass.ts +14 -10
  204. package/src/decorators/applyNode.ts +39 -37
  205. package/src/decorators/applyProperty.ts +72 -100
  206. package/src/decorators/applySlot.ts +9 -8
  207. package/src/decorators/applyStyle.ts +14 -10
  208. package/src/decorators/around.ts +196 -0
  209. package/src/decorators/changedAttribute.ts +65 -26
  210. package/src/decorators/elementDefine.ts +298 -220
  211. package/src/decorators/emitCustomEvent.ts +17 -13
  212. package/src/decorators/eventMedia.ts +119 -0
  213. package/src/decorators/fetch.ts +454 -0
  214. package/src/decorators/index.ts +8 -2
  215. package/src/decorators/intersectionObserver.ts +108 -78
  216. package/src/decorators/lifecycles.ts +24 -22
  217. package/src/decorators/mutationObserver.ts +140 -104
  218. package/src/decorators/parameter.ts +212 -0
  219. package/src/decorators/publishSwcAppMessage.ts +3 -4
  220. package/src/decorators/query.ts +22 -14
  221. package/src/decorators/requestAnimationFrame.ts +149 -0
  222. package/src/decorators/resizeObserver.ts +119 -82
  223. package/src/decorators/setInterval.ts +90 -23
  224. package/src/decorators/setTimeout.ts +93 -23
  225. package/src/decorators/state.ts +19 -13
  226. package/src/decorators/subscribeSwcAppMessage.ts +106 -0
  227. package/src/decorators/subscribeSwcAppRouteChange.ts +131 -0
  228. package/src/decorators/swcAppRoute.ts +231 -0
  229. package/src/elements/SwcApp.ts +40 -10
  230. package/src/elements/SwcAppMixin.ts +329 -85
  231. package/src/types/index.ts +38 -5
  232. package/src/types/window.d.ts +2 -18
  233. package/src/utils/Utils.ts +50 -18
  234. package/dist/cjs/decorators/subscribeSwcAppMessageWhileConnected.js.map +0 -7
  235. package/dist/cjs/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +0 -7
  236. package/dist/cjs/examples/RxJSOperatorsExample.js +0 -285
  237. package/dist/cjs/examples/RxJSOperatorsExample.js.map +0 -7
  238. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js +0 -54
  239. package/dist/esm/decorators/subscribeSwcAppMessageWhileConnected.js.map +0 -7
  240. package/dist/esm/decorators/subscribeSwcAppRouteChangeWhileConnected.js.map +0 -7
  241. package/dist/esm/examples/RxJSOperatorsExample.js +0 -266
  242. package/dist/esm/examples/RxJSOperatorsExample.js.map +0 -7
  243. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts +0 -23
  244. package/dist/types/decorators/subscribeSwcAppMessageWhileConnected.d.ts.map +0 -1
  245. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts +0 -31
  246. package/dist/types/decorators/subscribeSwcAppRouteChangeWhileConnected.d.ts.map +0 -1
  247. package/dist/types/examples/RxJSOperatorsExample.d.ts +0 -94
  248. package/dist/types/examples/RxJSOperatorsExample.d.ts.map +0 -1
  249. package/src/decorators/subscribeSwcAppMessageWhileConnected.ts +0 -91
  250. package/src/decorators/subscribeSwcAppRouteChangeWhileConnected.ts +0 -107
  251. package/src/examples/RxJSOperatorsExample.ts +0 -279
@@ -43,48 +43,19 @@ export const ATTRIBUTE_METADATA_KEY = Symbol.for('simple-web-component:attribute
43
43
  // Utilities
44
44
  // ============================================
45
45
 
46
- /**
47
- * Determine if a string is a CSS selector or an attribute name
48
- *
49
- * CSS selectors typically:
50
- * - Start with: #, ., [, :, >, +, ~
51
- * - Contain special chars: >, +, ~, :, [, ]
52
- * - Are special keywords: $this, $host, $parentHost, etc.
53
- *
54
- * Attribute names are typically:
55
- * - kebab-case (lowercase with hyphens)
56
- * - No special selector syntax
57
- *
58
- * @param str - String to check
59
- * @returns true if it's a CSS selector, false if it's an attribute name
60
- */
61
- const isCssSelector = (str: string): boolean => {
62
- if (!str) return false;
63
-
64
- // Special keywords
65
- if (str.startsWith('$')) return true;
66
-
67
- // CSS selector syntax
68
- if (/^[#.\[\:>+~]/.test(str)) return true;
69
-
70
- // Contains CSS combinator or pseudo-selector syntax
71
- if (/[>+~:\[\]]/.test(str)) return true;
72
-
73
- return false;
74
- };
75
46
 
76
- const convertValue = (val: string | null, type: any): any => {
47
+ // 문자열(attribute 원문)은 'false'/'0' 만 false. {{= }} 결과처럼 이미 JS 값이면 그 값의 참/거짓을 따른다
48
+ const convertValue = (val: any, type: any): any => {
77
49
  if (val === null || val === undefined) return val;
78
50
  if (type === Number) return Number(val);
79
- if (type === Boolean) return val === 'false' || val === '0' ? false : true;
51
+ if (type === Boolean) return typeof val === 'string' ? !(val === 'false' || val === '0') : Boolean(val);
80
52
  return val;
81
53
  };
82
54
 
83
55
  export {convertValue};
84
56
 
85
57
  export const getAttributeValue = (inst: any, attrName: string, options?: AttributeOptions & { selector?: AttributeSelector }): any => {
86
- const conf = getElementConfig(inst);
87
- const currentWin = inst._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as any);
58
+ const currentWin = SwcUtils.resolveWindow(inst);
88
59
 
89
60
  // If selector is not provided, use inst itself
90
61
  const targets = options?.selector ? resolveAttributeTargets(inst, options.selector, options) : [inst];
@@ -102,7 +73,7 @@ export const getAttributeValue = (inst: any, attrName: string, options?: Attribu
102
73
  const result = FunctionUtils.executeReturn({
103
74
  script: ConvertUtils.decodeHtmlEntity(expr.script, currentWin.document),
104
75
  context: inst,
105
- args: SwcUtils.getHelperAndHostSet(currentWin, inst)
76
+ args: SwcUtils.getHelperAndHostSet(inst)
106
77
  });
107
78
  return convertValue(result, options?.type);
108
79
  } catch (err) {
@@ -132,7 +103,7 @@ export const resolveAttributeTargets = (inst: any, selector: AttributeSelector,
132
103
  // Resolve selector if it's a function
133
104
  let resolvedSelector: string | Node | Element | NodeList | Element[] | null = selector as any;
134
105
  if (typeof selector === 'function') {
135
- const hostSet = SwcUtils.getHelperAndHostSet(currentWin, inst);
106
+ const hostSet = SwcUtils.getHelperAndHostSet(inst);
136
107
  resolvedSelector = selector(inst, hostSet);
137
108
  }
138
109
 
@@ -253,10 +224,8 @@ export function applyAttribute(selector: AttributeSelector, targetAttributeNameO
253
224
 
254
225
  // Helper: Apply resolved value to targets
255
226
  const applyValueToTargets = (inst: any, resolvedValue: any) => {
256
- const conf = getElementConfig(inst);
257
- const currentWin = conf.window;
258
227
  const targetEls = resolveAttributeTargets(inst, selector, finalOptions);
259
- const hostSet = SwcUtils.getHelperAndHostSet(currentWin, inst);
228
+ const hostSet = SwcUtils.getHelperAndHostSet(inst);
260
229
 
261
230
  targetEls.forEach(targetEl => {
262
231
  // Apply filter if provided
@@ -292,8 +261,8 @@ export function applyAttribute(selector: AttributeSelector, targetAttributeNameO
292
261
  * Uses valueKey from options if provided, otherwise uses ATTRIBUTE_METADATA_KEY.
293
262
  *
294
263
  * Example:
295
- * @setAttribute('selector1', { valueKey: 'attr1' })
296
- * @setAttribute('selector2', { valueKey: 'attr2' })
264
+ * @attribute('selector1', 'attr1-name', { valueKey: 'attr1' })
265
+ * @attribute('selector2', 'attr2-name', { valueKey: 'attr2' })
297
266
  * myMethod() {
298
267
  * return {
299
268
  * attr1: 'attribute-value1',
@@ -354,102 +323,79 @@ export function applyAttribute(selector: AttributeSelector, targetAttributeNameO
354
323
  // ============================================
355
324
 
356
325
  /**
357
- * @attribute - Field decorator for binding element attributes (read/write)
358
- *
359
- * Intelligently distinguishes between attribute names and CSS selectors:
360
- *
361
- * Usage patterns:
362
- * - @attribute('product-id') - Attribute name on $this (auto-detected)
363
- * - @attribute('#user', 'product-id') - Attribute name on selector
364
- * - @attribute('product-id', options) - Attribute name on $this with options
365
- * - @attribute('#user', 'product-id', options) - Attribute name on selector with options
366
- * - @attribute((this, helper) => 'selector', 'product-id') - Function-based selector
367
- * - @attribute - Bare decorator (uses property name as attribute on $this)
368
- *
369
- * Note: This decorator is for FIELDS ONLY. For methods, use @setAttribute.
326
+ * @attribute - 필드/메서드 공용. 붙은 곳에 따라 동작이 갈린다.
327
+ * - 필드: 엘리먼트 attribute 를 읽고 쓰는 getter/setter
328
+ * - 메서드: 리턴값을 엘리먼트 attribute 에 적용 (null 이면 제거, undefined 면 무시)
329
+ *
330
+ * 문자열이 하나면 자기 자신($this)의 attribute 이름, 둘이면 (셀렉터, attribute 이름).
331
+ * - @attribute - $this 의 attribute, 이름은 필드/메서드 이름
332
+ * - @attribute('product-id') / @attribute('product-id', options) - $this 의 product-id
333
+ * - @attribute('#user', 'product-id', options?) - 셀렉터 대상의 product-id
334
+ * - @attribute((this, helper) => el, 'product-id') - 함수 셀렉터
335
+ * - @attribute(options) - $this, 이름은 options.name 또는 필드/메서드 이름
336
+ *
337
+ * Example:
338
+ * @attribute('product-id') productId: string;
339
+ *
340
+ * @attribute('.card', 'data-status')
341
+ * updateStatus() { return 'active'; }
370
342
  */
371
- export function attribute(target: Object, propertyKey: string | symbol): void;
343
+ export function attribute(attributeName: string, options?: AttributeQueryOptions): MethodDecorator & PropertyDecorator;
344
+ export function attribute(selector: string, attributeName: string, options?: AttributeQueryOptions): MethodDecorator & PropertyDecorator;
345
+ export function attribute(selector: AttributeFnSelector, attributeName: string, options?: AttributeNonQueryOptions): MethodDecorator & PropertyDecorator;
346
+ export function attribute(options: AttributeOptions): MethodDecorator & PropertyDecorator;
347
+ // bare(@attribute) 시그니처는 맨 뒤 — 앞에 있으면 문자열 두 개짜리 호출이 (target, key) 로 먼저 잡혀 TS1240
348
+ export function attribute(target: Object, propertyKey: string | symbol): void;
372
349
  export function attribute(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
373
- export function attribute(attributeName: string, options?: AttributeQueryOptions): PropertyDecorator;
374
- export function attribute(selector: string, attributeName: string, options?: AttributeQueryOptions): PropertyDecorator;
375
- export function attribute(selector: AttributeFnSelector, attributeName: string, options?: AttributeNonQueryOptions): PropertyDecorator;
376
- export function attribute(selectorOrAttributeOrTarget?: AttributeSelector | Object, attributeNameOrOptions?: any, optionsOrDescriptor?: any): any {
377
- // Bare decorator: @attribute
378
- if (optionsOrDescriptor !== undefined && (typeof attributeNameOrOptions === 'string' || typeof attributeNameOrOptions === 'symbol')) {
379
- return applyAttribute('$this', undefined as any, {})(selectorOrAttributeOrTarget as Object, attributeNameOrOptions, optionsOrDescriptor as PropertyDescriptor);
380
- }
381
-
382
- // With string as first parameter
350
+ export function attribute(selectorOrAttributeOrTarget?: AttributeSelector | AttributeOptions | Object, attributeNameOrOptions?: any, optionsOrDescriptor?: any): any {
351
+ // 문자열: 하나면 $this 의 attribute 이름, 둘이면 (셀렉터, attribute 이름)
383
352
  if (typeof selectorOrAttributeOrTarget === 'string') {
384
- // Check if first parameter is a CSS selector or attribute name
385
- const isSelector = isCssSelector(selectorOrAttributeOrTarget);
386
-
387
- if (isSelector) {
388
- // First param is a selector: @attribute('#user', 'product-id', options?)
389
- return applyAttribute(selectorOrAttributeOrTarget, attributeNameOrOptions as any, optionsOrDescriptor as AttributeOptions);
390
- } else {
391
- // First param is an attribute name: @attribute('product-id', options?)
392
- // Treat as attribute name on $this
393
- const options = (typeof attributeNameOrOptions === 'object' && attributeNameOrOptions !== null)
394
- ? attributeNameOrOptions
395
- : {};
396
- return applyAttribute('$this', selectorOrAttributeOrTarget, options);
353
+ if (typeof attributeNameOrOptions !== 'string') {
354
+ return applyAttribute('$this', selectorOrAttributeOrTarget, attributeNameOrOptions as AttributeOptions);
397
355
  }
356
+ return applyAttribute(selectorOrAttributeOrTarget, attributeNameOrOptions, optionsOrDescriptor as AttributeOptions);
357
+ }
358
+ // 함수 셀렉터
359
+ if (typeof selectorOrAttributeOrTarget === 'function') {
360
+ return applyAttribute(selectorOrAttributeOrTarget as AttributeFnSelector, attributeNameOrOptions, optionsOrDescriptor as AttributeOptions);
398
361
  }
399
-
400
- // Without selector (defaults to $this with options)
401
- return applyAttribute('$this', undefined as any, selectorOrAttributeOrTarget as AttributeOptions);
362
+ // bare: @attribute — 데코레이터로 바로 호출됨 (target=prototype, key[, descriptor])
363
+ if (selectorOrAttributeOrTarget && (typeof attributeNameOrOptions === 'string' || typeof attributeNameOrOptions === 'symbol')) {
364
+ return applyAttribute('$this', {})(selectorOrAttributeOrTarget as Object, attributeNameOrOptions, optionsOrDescriptor as PropertyDescriptor);
365
+ }
366
+ // 옵션만: $this
367
+ return applyAttribute('$this', selectorOrAttributeOrTarget as AttributeOptions);
402
368
  }
403
369
 
404
370
  /**
405
- * @setAttribute - Method decorator for setting element attributes from method return value
406
- *
407
- * Intelligently distinguishes between attribute names and CSS selectors:
408
- *
409
- * Usage patterns:
410
- * - @setAttribute('data-id') - Attribute name on $this (auto-detected)
411
- * - @setAttribute('#user', 'data-id') - Attribute name on selector
412
- * - @setAttribute('data-id', options) - Attribute name on $this with options
413
- * - @setAttribute('#user', 'data-id', options) - Attribute name on selector with options
414
- * - @setAttribute((this, helper) => 'selector', 'data-id') - Function-based selector
415
- * - @setAttribute - Bare decorator (uses method name as attribute on $this)
416
- *
417
- * Note: This decorator is for METHODS ONLY. For fields, use @attribute.
418
- *
419
- * Example:
420
- * @setAttribute('data-status')
421
- * updateStatus() {
422
- * return 'active';
423
- * }
371
+ * @removeAttribute - 메서드 실행 시 엘리먼트 속성 제거 (반환값 그대로 통과).
372
+ * 라우트 구독처럼 값을 리턴하면 안 되는 곳에서 @attribute 에 null 을 리턴하는 대신 명시적으로 사용.
373
+ *
374
+ * Usage:
375
+ * - @removeAttribute('nav', 'href') - Remove attribute from selector
376
+ * - @removeAttribute('$this', 'href') - Remove attribute from $this
424
377
  */
425
- export function setAttribute(selector: string, attributeName: string, options?: AttributeQueryOptions): MethodDecorator;
426
- export function setAttribute(selector: AttributeFnSelector, attributeName: string, options?: AttributeNonQueryOptions): MethodDecorator;
427
- export function setAttribute(attributeName: string, options?: AttributeQueryOptions): MethodDecorator;
428
- export function setAttribute(selectorOrAttributeOrOptions?: AttributeSelector | AttributeOptions, attributeNameOrOptions?: any, optionsOrUndefined?: AttributeOptions): MethodDecorator {
429
- // Function selector: @setAttribute((c, helper) => ..., 'attr', options?)
430
- if (typeof selectorOrAttributeOrOptions === 'function') {
431
- return applyAttribute(selectorOrAttributeOrOptions as AttributeSelector, attributeNameOrOptions as any, optionsOrUndefined as AttributeOptions) as MethodDecorator;
432
- }
433
- // With string as first parameter
434
- if (typeof selectorOrAttributeOrOptions === 'string') {
435
- // Check if first parameter is a CSS selector or attribute name
436
- const isSelector = isCssSelector(selectorOrAttributeOrOptions);
437
-
438
- if (isSelector) {
439
- // First param is a selector: @setAttribute('#user', 'data-id', options?)
440
- return applyAttribute(selectorOrAttributeOrOptions, attributeNameOrOptions as any, optionsOrUndefined as AttributeOptions) as MethodDecorator;
441
- } else {
442
- // First param is an attribute name: @setAttribute('data-id', options?)
443
- // Treat as attribute name on $this
444
- const options = (typeof attributeNameOrOptions === 'object' && attributeNameOrOptions !== null)
445
- ? attributeNameOrOptions
446
- : {};
447
- return applyAttribute('$this', selectorOrAttributeOrOptions, options) as MethodDecorator;
448
- }
449
- }
450
-
451
- // Without selector (defaults to $this with options)
452
- return applyAttribute('$this', undefined as any, selectorOrAttributeOrOptions as AttributeOptions) as MethodDecorator;
378
+ export function removeAttribute(selector: string, attributeName: string, options?: AttributeQueryOptions): MethodDecorator;
379
+ export function removeAttribute(selector: AttributeFnSelector, attributeName: string, options?: AttributeNonQueryOptions): MethodDecorator;
380
+ export function removeAttribute(selector: AttributeSelector, attributeName: string, options?: AttributeOptions): MethodDecorator {
381
+ return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
382
+ const original = descriptor.value;
383
+ descriptor.value = function (...args: any[]) {
384
+ const res = (original as any).apply(this, args);
385
+ const doRemove = () => {
386
+ resolveAttributeTargets(this, selector, options ?? {}).forEach((el) => el.removeAttribute(attributeName));
387
+ };
388
+ if (res instanceof Promise) {
389
+ return res.then((v: any) => {
390
+ doRemove();
391
+ return v;
392
+ });
393
+ }
394
+ doRemove();
395
+ return res;
396
+ };
397
+ return descriptor;
398
+ };
453
399
  }
454
400
 
455
401
  // ============================================
@@ -457,7 +403,7 @@ export function setAttribute(selectorOrAttributeOrOptions?: AttributeSelector |
457
403
  // ============================================
458
404
 
459
405
  export const findAllAttributeMetadata = (target: any): AttributeMetadata[] => {
460
- const actualTarget = target instanceof Function ? target : target.constructor;
406
+ const actualTarget = typeof target === 'function' ? target : target.constructor;
461
407
  return ReflectUtils.findAllMetadata<AttributeMetadata[]>(ATTRIBUTE_METADATA_KEY, actualTarget).flat();
462
408
  };
463
409
 
@@ -471,16 +417,18 @@ export const findAllAttributeApplyMetadata = (target: any): Map<string | symbol,
471
417
  };
472
418
 
473
419
  // ─── Aliases ───
474
- // attribute(필드) / setAttribute(메서드)와 구분되는 일반 데코레이터 단축명
420
+ // applyAttribute 단축명
475
421
  export const attr = applyAttribute;
476
422
 
477
423
  // ─── 편의 헬퍼 (selector/root 생략) ───
478
424
 
479
- export function attrThis(targetAttributeName?: string, options?: AttributeQueryOptions): MethodDecorator {
480
- return applyAttribute('$this', targetAttributeName, options);
481
- }
482
- export function attrAppHost(targetAttributeName?: string, options?: AttributeQueryOptions): MethodDecorator {
483
- return applyAttribute('$appHost', targetAttributeName, options);
425
+ export function attrAppHost(targetAttributeName: string, options?: AttributeQueryOptions): MethodDecorator;
426
+ export function attrAppHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
427
+ export function attrAppHost(targetAttributeNameOrTarget?: string | Object, optionsOrPropertyKey?: AttributeQueryOptions | string | symbol, descriptor?: PropertyDescriptor): any {
428
+ if ((typeof optionsOrPropertyKey === 'string' || typeof optionsOrPropertyKey === 'symbol') && descriptor !== undefined) {
429
+ return (applyAttribute('$appHost', undefined as any, {}) as any)(targetAttributeNameOrTarget, optionsOrPropertyKey, descriptor);
430
+ }
431
+ return applyAttribute('$appHost', targetAttributeNameOrTarget as any, optionsOrPropertyKey as AttributeQueryOptions);
484
432
  }
485
433
  export function attrLight(selector: string, targetAttributeName?: string, options?: Omit<AttributeQueryOptions, 'root'>): MethodDecorator {
486
434
  return applyAttribute(selector, targetAttributeName, {...options ?? {}, root: 'light'});
@@ -13,7 +13,7 @@ export type ClassAction = 'set' | 'update' | 'add' | 'remove' | 'toggle';
13
13
  */
14
14
  const resolveSelector = (selector: ClassSelector, inst: any, win: Window): string | HTMLElement[] => {
15
15
  if (typeof selector === 'function') {
16
- const hostSet = SwcUtils.getHelperAndHostSet(win, inst);
16
+ const hostSet = SwcUtils.getHelperAndHostSet(inst);
17
17
  const result = selector(inst, hostSet);
18
18
 
19
19
  if (result instanceof win.Element) {
@@ -49,7 +49,7 @@ const getTargetElements = (selector: ClassSelector, inst: any, win: Window, root
49
49
  const stringSelector = resolved as string;
50
50
  const targetEls: HTMLElement[] = [];
51
51
  const host = inst as unknown as HTMLElement;
52
- const hostSet = SwcUtils.getHelperAndHostSet(win, inst);
52
+ const hostSet = SwcUtils.getHelperAndHostSet(inst);
53
53
 
54
54
  const applyRoot = (t: any) => {
55
55
  if (!t || !(t instanceof win.HTMLElement)) return;
@@ -149,7 +149,7 @@ function createClassDecorator(action: ClassAction) {
149
149
  if (resolvedValue !== undefined) {
150
150
  const win = (this as any).ownerDocument?.defaultView || window;
151
151
  const host = this as unknown as HTMLElement;
152
- const hostSet = { ...SwcUtils.getHelperAndHostSet(win, host), $this: this };
152
+ const hostSet = { ...SwcUtils.getHelperAndHostSet(host), $this: this };
153
153
  const r = finalOptions.root || 'auto';
154
154
  const targetEls = getTargetElements(selector, this, win, r);
155
155
 
@@ -209,9 +209,11 @@ function createClassDecorator(action: ClassAction) {
209
209
  };
210
210
 
211
211
  if (res instanceof Promise) {
212
- return res.then((v: any) => handleResult(extractValue(v)));
212
+ // 자기 몫(valueKey)만 적용하고 원래 반환값은 그대로 위로 넘긴다 — 위에 쌓인 다른 아웃풋도 자기 키를 찾게
213
+ return res.then((v: any) => { handleResult(extractValue(v)); return v; });
213
214
  } else {
214
- return handleResult(extractValue(res));
215
+ handleResult(extractValue(res));
216
+ return res;
215
217
  }
216
218
  };
217
219
  return descriptor;
@@ -325,11 +327,13 @@ export const cls = applyClass;
325
327
 
326
328
  // ─── 편의 헬퍼 (selector/root 생략) ───
327
329
 
328
- export function clsThis(action?: ClassAction, options?: ClassQueryOptions): MethodDecorator {
329
- return applyClass('$this', action, options);
330
- }
331
- export function clsAppHost(action?: ClassAction, options?: ClassQueryOptions): MethodDecorator {
332
- return applyClass('$appHost', action, options);
330
+ export function clsAppHost(action: ClassAction, options?: ClassQueryOptions): MethodDecorator;
331
+ export function clsAppHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
332
+ export function clsAppHost(actionOrTarget?: ClassAction | Object, optionsOrPropertyKey?: ClassQueryOptions | string | symbol, descriptor?: PropertyDescriptor): any {
333
+ if ((typeof optionsOrPropertyKey === 'string' || typeof optionsOrPropertyKey === 'symbol') && descriptor !== undefined) {
334
+ return (applyClass('$appHost', undefined as any, {}) as any)(actionOrTarget, optionsOrPropertyKey, descriptor);
335
+ }
336
+ return applyClass('$appHost', actionOrTarget as any, optionsOrPropertyKey as ClassQueryOptions);
333
337
  }
334
338
  export function clsLight(selector: string, action?: ClassAction, options?: Omit<ClassQueryOptions, 'root'>): MethodDecorator;
335
339
  export function clsLight(selector: string, options?: Omit<ClassQueryOptions, 'root'>): MethodDecorator;
@@ -1,5 +1,5 @@
1
1
  import { ReflectUtils } from '@dooboostore/core';
2
- import { ensureInit, getElementConfig } from './elementDefine';
2
+ import { ensureInit } from './elementDefine';
3
3
  import {SpecialSelector, SwcQueryOptions, SwcFnSelector, SwcSelector, HelperHostSet, SwcRootType} from '../types';
4
4
  import { SwcUtils} from "../utils/Utils";
5
5
  import {findAllStateMetadata} from "./state";
@@ -49,7 +49,7 @@ export const APPLY_NODE_METADATA_KEY = Symbol.for('simple-web-component:apply-no
49
49
  */
50
50
  const resolveSelector = (selector: ApplyNodeSelector, inst: any, win: Window): string | HTMLElement | null => {
51
51
  if (typeof selector === 'function') {
52
- const hostSet = SwcUtils.getHelperAndHostSet(win, inst);
52
+ const hostSet = SwcUtils.getHelperAndHostSet(inst);
53
53
  const result = selector(inst, hostSet);
54
54
 
55
55
  if (result instanceof win.Element) {
@@ -78,7 +78,7 @@ const resolveSelector = (selector: ApplyNodeSelector, inst: any, win: Window): s
78
78
  // });
79
79
  // };
80
80
 
81
- const applyToDom = (currentThis: any, targetEl: HTMLElement, res: Node | string, pos: ApplyNodePosition, win: Window, host?: any) => {
81
+ const applyToDom = (currentThis: any, targetEl: HTMLElement, res: Node | string | (Node | string)[] | NodeList, pos: ApplyNodePosition, win: Window, host?: any) => {
82
82
  if (!targetEl) return;
83
83
 
84
84
  // Handle clearChildren - ignore return value and always clear
@@ -88,20 +88,21 @@ const applyToDom = (currentThis: any, targetEl: HTMLElement, res: Node | string,
88
88
  }
89
89
 
90
90
  const doc = win.document;
91
- const hostSet = SwcUtils.getHelperAndHostSet(win, currentThis);
91
+ const hostSet = SwcUtils.getHelperAndHostSet(currentThis);
92
92
  const id = currentThis._swcId;
93
93
 
94
- const nodes: Node[] = [];
95
-
96
- if (res instanceof win.Node) {
97
- nodes.push(res);
98
- } else if (typeof res === 'string' && pos === 'innerHtml') {
99
- const t = win.document.createElement('template');
100
- t.innerHTML = res;
101
- nodes.push(...Array.from(t.content.childNodes));
102
- } else if (typeof res === 'string' && pos === 'innerText') {
103
- nodes.push(win.document.createTextNode(res));
104
- }
94
+ // 리턴값 → 노드: Node 그대로 / 문자열은 innerText 면 텍스트, 그 외 위치는 HTML / 배열·NodeList 는 항목마다.
95
+ // Node 판단은 nodeType 으로 — 다른 window(iframe) 에서 만든 노드는 instanceof win.Node 가 false 라서.
96
+ const toNodes = (v: any): Node[] => {
97
+ if (v === null || v === undefined || v === false) return [];
98
+ if (typeof v === 'object' && typeof v.nodeType === 'number') return [v];
99
+ if (typeof v === 'object' && typeof v.length === 'number') return Array.from(v as ArrayLike<any>).flatMap(toNodes);
100
+ if (pos === 'innerText') return [doc.createTextNode(String(v))];
101
+ const t = doc.createElement('template');
102
+ t.innerHTML = String(v);
103
+ return Array.from(t.content.childNodes);
104
+ };
105
+ const nodes: Node[] = toNodes(res);
105
106
 
106
107
  SwcUtils.projectProcessHtml(id, nodes, doc);
107
108
 
@@ -170,10 +171,9 @@ export function applyNode(selectorOrOptions: ApplyNodeSelector | ApplyNodeOption
170
171
  descriptor.value = function (...args: any[]) {
171
172
  ensureInit(this);
172
173
 
173
- const conf = getElementConfig(this);
174
- const currentWin = (this as any)._resolveWindow?.(conf) || ((typeof window !== 'undefined' ? window : undefined) as Window);
174
+ const currentWin = SwcUtils.resolveWindow(this);
175
175
  const currentDoc = currentWin.document;
176
- const hostSet = SwcUtils.getHelperAndHostSet(currentWin, this);
176
+ const hostSet = SwcUtils.getHelperAndHostSet(this);
177
177
 
178
178
  const getTarget = () => {
179
179
  const r = options.root || 'auto';
@@ -306,7 +306,7 @@ export function replaceChildren(selectorOrOptions?: ApplyNodeSelector | Omit<App
306
306
  * - @clearChildrenNode - Bare decorator, clears children of $this
307
307
  */
308
308
  export function clearChildrenNode(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
309
- export function clearChildrenNode(options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
309
+ export function clearChildrenNode(options: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
310
310
  export function clearChildrenNode(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
311
311
  export function clearChildrenNode(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
312
312
  // Bare decorator usage: @clearChildrenNode
@@ -332,7 +332,7 @@ export const clearNode = clearChildrenNode;
332
332
  * - @innerHtmlNode - Bare decorator, sets innerHTML of $this
333
333
  */
334
334
  export function innerHtml(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
335
- export function innerHtml(options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
335
+ export function innerHtml(options: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
336
336
  export function innerHtml(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
337
337
  export function innerHtml(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
338
338
  // Bare decorator usage: @innerHtmlNode
@@ -358,7 +358,7 @@ export function innerHtml(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNode
358
358
  * - @innerHtmlLightNode - Bare decorator, sets innerHTML of $this in light DOM
359
359
  */
360
360
  export function innerHtmlLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
361
- export function innerHtmlLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
361
+ export function innerHtmlLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
362
362
  export function innerHtmlLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
363
363
  export function innerHtmlLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
364
364
  // Bare decorator usage: @innerHtmlLightNode
@@ -382,7 +382,7 @@ export function innerHtmlLight(selectorOrOptions?: ApplyNodeSelector | Omit<Appl
382
382
  * - @innerHtmlShadowNode - Bare decorator, sets innerHTML of $this in shadow DOM
383
383
  */
384
384
  export function innerHtmlShadow(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
385
- export function innerHtmlShadow(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
385
+ export function innerHtmlShadow(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
386
386
  export function innerHtmlShadow(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
387
387
  export function innerHtmlShadow(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
388
388
  // Bare decorator usage: @innerHtmlShadowNode
@@ -406,7 +406,7 @@ export function innerHtmlShadow(selectorOrOptions?: ApplyNodeSelector | Omit<App
406
406
  * - @innerTextNode - Bare decorator, sets innerText of $this
407
407
  */
408
408
  export function innerText(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
409
- export function innerText(options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
409
+ export function innerText(options: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
410
410
  export function innerText(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
411
411
  export function innerText(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
412
412
  // Bare decorator usage: @innerTextNode
@@ -430,7 +430,7 @@ export function innerText(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNode
430
430
  * - @innerTextLightNode - Bare decorator, sets innerText of $this in light DOM
431
431
  */
432
432
  export function innerTextLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
433
- export function innerTextLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
433
+ export function innerTextLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
434
434
  export function innerTextLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
435
435
  export function innerTextLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
436
436
  // Bare decorator usage: @innerTextLightNode
@@ -453,7 +453,7 @@ export function innerTextLight(selectorOrOptions?: ApplyNodeSelector | Omit<Appl
453
453
  * - @innerTextShadowNode - Bare decorator, sets innerText of $this in shadow DOM
454
454
  */
455
455
  export function innerTextShadow(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
456
- export function innerTextShadow(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
456
+ export function innerTextShadow(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
457
457
  export function innerTextShadow(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
458
458
  export function innerTextShadow(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
459
459
  // Bare decorator usage: @innerTextShadowNode
@@ -476,7 +476,7 @@ export function innerTextShadow(selectorOrOptions?: ApplyNodeSelector | Omit<App
476
476
  * - @beforeEndNode - Bare decorator, appends to $this
477
477
  */
478
478
  export function insertBeforeEnd(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
479
- export function insertBeforeEnd(options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
479
+ export function insertBeforeEnd(options: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
480
480
  export function insertBeforeEnd(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
481
481
  export function insertBeforeEnd(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
482
482
  // Bare decorator usage: @beforeEndNode
@@ -500,7 +500,7 @@ export function insertBeforeEnd(selectorOrOptions?: ApplyNodeSelector | Omit<App
500
500
  * - @beforeEndLightNode - Bare decorator, appends to $this in light DOM
501
501
  */
502
502
  export function insertBeforeEndLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
503
- export function insertBeforeEndLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
503
+ export function insertBeforeEndLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
504
504
  export function insertBeforeEndLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
505
505
  export function insertBeforeEndLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
506
506
  // Bare decorator usage: @beforeEndLightNode
@@ -524,7 +524,7 @@ export function insertBeforeEndLight(selectorOrOptions?: ApplyNodeSelector | Omi
524
524
  * - @beforeEndShadowNode - Bare decorator, appends to $this in shadow DOM
525
525
  */
526
526
  export function insertBeforeEndShadow(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
527
- export function insertBeforeEndShadow(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
527
+ export function insertBeforeEndShadow(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
528
528
  export function insertBeforeEndShadow(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
529
529
  export function insertBeforeEndShadow(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
530
530
  // Bare decorator usage: @beforeEndShadowNode
@@ -548,7 +548,7 @@ export function insertBeforeEndShadow(selectorOrOptions?: ApplyNodeSelector | Om
548
548
  * - @afterBeginNode - Bare decorator, prepends to $this
549
549
  */
550
550
  export function insertAfterBegin(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
551
- export function insertAfterBegin(options?: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
551
+ export function insertAfterBegin(options: Omit<ApplyNodeOptions, 'position'>): MethodDecorator;
552
552
  export function insertAfterBegin(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
553
553
  export function insertAfterBegin(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
554
554
  // Bare decorator usage: @afterBeginNode
@@ -572,7 +572,7 @@ export function insertAfterBegin(selectorOrOptions?: ApplyNodeSelector | Omit<Ap
572
572
  * - @afterBeginLightNode - Bare decorator, prepends to $this in light DOM
573
573
  */
574
574
  export function insertAfterBeginLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
575
- export function insertAfterBeginLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
575
+ export function insertAfterBeginLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
576
576
  export function insertAfterBeginLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
577
577
  export function insertAfterBeginLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
578
578
  // Bare decorator usage: @afterBeginLightNode
@@ -596,7 +596,7 @@ export function insertAfterBeginLight(selectorOrOptions?: ApplyNodeSelector | Om
596
596
  * - @replaceChildrenLightNode - Bare decorator, replaces children of $this in light DOM
597
597
  */
598
598
  export function replaceChildrenLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
599
- export function replaceChildrenLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
599
+ export function replaceChildrenLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
600
600
  export function replaceChildrenLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
601
601
  export function replaceChildrenLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
602
602
  // Bare decorator usage: @replaceChildrenLightNode
@@ -619,7 +619,7 @@ export function replaceChildrenLight(selectorOrOptions?: ApplyNodeSelector | Omi
619
619
  * - @clearChildrenLightNode - Bare decorator, clears children of $this in light DOM
620
620
  */
621
621
  export function clearChildrenLight(selector: ApplyNodeSelector, options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
622
- export function clearChildrenLight(options?: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
622
+ export function clearChildrenLight(options: Omit<ApplyNodeOptions, 'position' | 'root'>): MethodDecorator;
623
623
  export function clearChildrenLight(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
624
624
  export function clearChildrenLight(selectorOrOptions?: ApplyNodeSelector | Omit<ApplyNodeOptions, 'position' | 'root'> | Object, maybeOptions?: Omit<ApplyNodeOptions, 'position' | 'root'> | string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
625
625
  // Bare decorator usage: @clearChildrenLightNode
@@ -642,11 +642,13 @@ export const node = applyNode;
642
642
 
643
643
  // ─── 편의 헬퍼 (selector/root 생략) ───
644
644
 
645
- export function applyThis(options?: ApplyNodeQueryOptions): MethodDecorator {
646
- return applyNode('$this', options);
647
- }
648
- export function applyAppHost(options?: ApplyNodeQueryOptions): MethodDecorator {
649
- return applyNode('$appHost', options);
645
+ export function applyAppHost(options: ApplyNodeQueryOptions): MethodDecorator;
646
+ export function applyAppHost(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor | void;
647
+ export function applyAppHost(optionsOrTarget?: ApplyNodeQueryOptions | Object, propertyKey?: string | symbol, descriptor?: PropertyDescriptor): MethodDecorator | PropertyDescriptor | void {
648
+ if ((typeof propertyKey === 'string' || typeof propertyKey === 'symbol') && descriptor !== undefined) {
649
+ return (applyNode('$appHost', {}) as any)(optionsOrTarget, propertyKey, descriptor);
650
+ }
651
+ return applyNode('$appHost', optionsOrTarget as ApplyNodeQueryOptions);
650
652
  }
651
653
  export function applyLight(selector: string, options?: Omit<ApplyNodeQueryOptions, 'root'>): MethodDecorator {
652
654
  return applyNode(selector, {...options ?? {}, root: 'light'});