@dooboostore/simple-web-component 1.0.31 → 1.0.32

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 (64) hide show
  1. package/dist/cjs/decorators/applyStyle.js +1 -1
  2. package/dist/cjs/decorators/applyStyle.js.map +2 -2
  3. package/dist/cjs/decorators/attribute.js +17 -1
  4. package/dist/cjs/decorators/attribute.js.map +2 -2
  5. package/dist/cjs/decorators/elementDefine.js +26 -9
  6. package/dist/cjs/decorators/elementDefine.js.map +3 -3
  7. package/dist/cjs/elements/SwcAppMixin.js +1 -1
  8. package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
  9. package/dist/cjs/elements/SwcAsync.js +69 -57
  10. package/dist/cjs/elements/SwcAsync.js.map +2 -2
  11. package/dist/cjs/elements/SwcChoose.js +66 -60
  12. package/dist/cjs/elements/SwcChoose.js.map +2 -2
  13. package/dist/cjs/elements/SwcIf.js +51 -66
  14. package/dist/cjs/elements/SwcIf.js.map +2 -2
  15. package/dist/cjs/elements/SwcLoop.js +58 -78
  16. package/dist/cjs/elements/SwcLoop.js.map +2 -2
  17. package/dist/cjs/elements/register.js +310 -335
  18. package/dist/cjs/elements/register.js.map +2 -2
  19. package/dist/cjs/types.js.map +1 -1
  20. package/dist/cjs/utils/Utils.js +7 -13
  21. package/dist/cjs/utils/Utils.js.map +2 -2
  22. package/dist/esm/decorators/applyStyle.js +1 -1
  23. package/dist/esm/decorators/applyStyle.js.map +2 -2
  24. package/dist/esm/decorators/attribute.js +18 -2
  25. package/dist/esm/decorators/attribute.js.map +2 -2
  26. package/dist/esm/decorators/elementDefine.js +24 -7
  27. package/dist/esm/decorators/elementDefine.js.map +3 -3
  28. package/dist/esm/elements/SwcAppMixin.js +1 -1
  29. package/dist/esm/elements/SwcAppMixin.js.map +2 -2
  30. package/dist/esm/elements/SwcAsync.js +70 -58
  31. package/dist/esm/elements/SwcAsync.js.map +2 -2
  32. package/dist/esm/elements/SwcChoose.js +67 -61
  33. package/dist/esm/elements/SwcChoose.js.map +2 -2
  34. package/dist/esm/elements/SwcIf.js +52 -67
  35. package/dist/esm/elements/SwcIf.js.map +2 -2
  36. package/dist/esm/elements/SwcLoop.js +59 -79
  37. package/dist/esm/elements/SwcLoop.js.map +2 -2
  38. package/dist/esm/elements/register.js +239 -264
  39. package/dist/esm/elements/register.js.map +2 -2
  40. package/dist/esm/types.js.map +1 -1
  41. package/dist/esm/utils/Utils.js +7 -13
  42. package/dist/esm/utils/Utils.js.map +2 -2
  43. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +2623 -2422
  44. package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
  45. package/dist/types/decorators/attribute.d.ts.map +1 -1
  46. package/dist/types/decorators/elementDefine.d.ts.map +1 -1
  47. package/dist/types/elements/register.d.ts.map +1 -1
  48. package/dist/types/types.d.ts +8 -1
  49. package/dist/types/types.d.ts.map +1 -1
  50. package/dist/types/utils/Utils.d.ts.map +1 -1
  51. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +2623 -2422
  52. package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
  53. package/package.json +1 -1
  54. package/src/decorators/applyStyle.ts +1 -1
  55. package/src/decorators/attribute.ts +35 -30
  56. package/src/decorators/elementDefine.ts +26 -7
  57. package/src/elements/SwcAppMixin.ts +1 -1
  58. package/src/elements/SwcAsync.ts +75 -69
  59. package/src/elements/SwcChoose.ts +67 -80
  60. package/src/elements/SwcIf.ts +51 -76
  61. package/src/elements/SwcLoop.ts +56 -87
  62. package/src/elements/register.ts +235 -307
  63. package/src/types.ts +6 -1
  64. package/src/utils/Utils.ts +11 -17
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/elements/SwcIf.ts"],
4
- "sourcesContent": ["import { changedAttributeHost } from '../decorators/changedAttributeHost';\nimport { SwcUtils } from '../utils/Utils';\nimport { FunctionUtils } from '@dooboostore/core';\n\nclass SwcIf extends HTMLTemplateElement {\n private _value = false;\n private _nodes: Node[] = [];\n\n get value(): boolean {\n return this._value;\n }\n set value(nv: any) {\n this._value = Boolean(nv);\n this.render();\n }\n\n private _executeCloneCallback(attr: string, args: any) {\n const script = this.getAttribute(attr);\n if (!script) return;\n FunctionUtils.execute({ script, context: this, args });\n }\n\n @changedAttributeHost('value')\n private refreshValue(valueAttr?: string | null) {\n valueAttr ??= this.getAttribute('value');\n if (valueAttr === null) {\n this.value = false;\n return;\n }\n\n // {{ }} 브레이스로 감싸진 값은 스크립트 실행\n if (valueAttr.startsWith('{{') && valueAttr.endsWith('}}')) {\n const script = valueAttr.slice(2, -2).trim();\n const win = this.ownerDocument?.defaultView || window;\n const result = FunctionUtils.executeReturn({\n script,\n context: this,\n args: SwcUtils.getHelperAndHostSet(win, this)\n });\n this.value = result;\n } else {\n // 일반 문자열 값\n this.value = Boolean(valueAttr);\n }\n }\n\n private render() {\n this.cleanup();\n const portal = this.parentElement;\n if (!portal) return;\n\n const win = this.ownerDocument?.defaultView || window;\n const helperSet = SwcUtils.getHelperAndHostSet(win, this);\n\n let targetTpl: HTMLTemplateElement | null = null;\n if (this._value) {\n targetTpl = this;\n } else {\n targetTpl = this.content.querySelector('template[is=\"swc-default\"]') as HTMLTemplateElement;\n }\n\n if (targetTpl) {\n const clone = targetTpl.content.cloneNode(true) as DocumentFragment;\n // If it's the host template, remove sub-templates from clone\n if (targetTpl === this) {\n clone.querySelectorAll('template[is^=\"swc-\"]').forEach(t => t.remove());\n }\n\n this._nodes = Array.from(clone.childNodes);\n const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];\n const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0] };\n\n // 부모 체인을 정상적으로 유지하기 위해 __swc_host 할당 제거\n this._nodes.forEach((node, nodeIdx) => {\n // if (node instanceof HTMLElement) (node as any).__swc_host = this; // 제거: 부모 체인 유지\n this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });\n\n // Attribute {{ }} 치환 - SwcChoose처럼 동적 치환\n if (node instanceof HTMLElement) {\n Array.from(node.attributes).forEach(attr => {\n const value = attr.value || '';\n if (value.startsWith('{{') && value.endsWith('}}')) {\n const script = value.slice(2, -2).trim();\n const result = FunctionUtils.executeReturn({\n script,\n context: node,\n args: { ...groupArgs, $value: this._value }\n });\n node.setAttribute(attr.name, String(result));\n }\n });\n }\n });\n\n this._executeCloneCallback('on-clone-nodes', groupArgs);\n\n portal.insertBefore(clone, this.nextSibling);\n }\n }\n\n private cleanup() {\n this._nodes.forEach(n => n.parentElement?.removeChild(n));\n this._nodes = [];\n }\n\n connectedCallback() {\n this.refreshValue();\n }\n disconnectedCallback() {\n this.cleanup();\n }\n}\n"],
5
- "mappings": "AAAA,kCAAqC;AACrC,mBAAyB;AACzB,kBAA8B;;;;;;;;;;AAE9B,MAAM,cAAc,oBAAmB;EAAvC,cAAA;;AACU,SAAA,SAAS;AACT,SAAA,SAAiB,CAAA;EAyG3B;EAvGE,IAAI,QAAK;AACP,WAAO,KAAK;EACd;EACA,IAAI,MAAM,IAAO;AACf,SAAK,SAAS,QAAQ,EAAE;AACxB,SAAK,OAAM;EACb;EAEQ,sBAAsB,MAAc,MAAS;AACnD,UAAM,SAAS,KAAK,aAAa,IAAI;AACrC,QAAI,CAAC;AAAQ;AACb,8BAAc,QAAQ,EAAE,QAAQ,SAAS,MAAM,KAAI,CAAE;EACvD;EAGQ,aAAa,WAAyB;AAC5C,kBAAA,YAAc,KAAK,aAAa,OAAO;AACvC,QAAI,cAAc,MAAM;AACtB,WAAK,QAAQ;AACb;IACF;AAGA,QAAI,UAAU,WAAW,IAAI,KAAK,UAAU,SAAS,IAAI,GAAG;AAC1D,YAAM,SAAS,UAAU,MAAM,GAAG,EAAE,EAAE,KAAI;AAC1C,YAAM,MAAM,KAAK,eAAe,eAAe;AAC/C,YAAM,SAAS,0BAAc,cAAc;QACzC;QACA,SAAS;QACT,MAAM,sBAAS,oBAAoB,KAAK,IAAI;OAC7C;AACD,WAAK,QAAQ;IACf,OAAO;AAEL,WAAK,QAAQ,QAAQ,SAAS;IAChC;EACF;EAEQ,SAAM;AACZ,SAAK,QAAO;AACZ,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC;AAAQ;AAEb,UAAM,MAAM,KAAK,eAAe,eAAe;AAC/C,UAAM,YAAY,sBAAS,oBAAoB,KAAK,IAAI;AAExD,QAAI,YAAwC;AAC5C,QAAI,KAAK,QAAQ;AACf,kBAAY;IACd,OAAO;AACL,kBAAY,KAAK,QAAQ,cAAc,4BAA4B;IACrE;AAEA,QAAI,WAAW;AACb,YAAM,QAAQ,UAAU,QAAQ,UAAU,IAAI;AAE9C,UAAI,cAAc,MAAM;AACtB,cAAM,iBAAiB,sBAAsB,EAAE,QAAQ,OAAK,EAAE,OAAM,CAAE;MACxE;AAEA,WAAK,SAAS,MAAM,KAAK,MAAM,UAAU;AACzC,YAAM,WAAW,KAAK,OAAO,OAAO,OAAK,EAAE,aAAa,CAAC;AACzD,YAAM,YAAY,EAAE,GAAG,WAAW,QAAQ,KAAK,QAAQ,QAAQ,KAAK,QAAQ,WAAW,UAAU,eAAe,SAAS,CAAC,EAAC;AAG3H,WAAK,OAAO,QAAQ,CAAC,MAAM,YAAW;AAEpC,aAAK,sBAAsB,iBAAiB,EAAE,GAAG,WAAW,OAAO,MAAM,YAAY,SAAS,YAAY,KAAK,aAAa,EAAC,CAAE;AAG/H,YAAI,gBAAgB,aAAa;AAC/B,gBAAM,KAAK,KAAK,UAAU,EAAE,QAAQ,UAAO;AACzC,kBAAM,QAAQ,KAAK,SAAS;AAC5B,gBAAI,MAAM,WAAW,IAAI,KAAK,MAAM,SAAS,IAAI,GAAG;AAClD,oBAAM,SAAS,MAAM,MAAM,GAAG,EAAE,EAAE,KAAI;AACtC,oBAAM,SAAS,0BAAc,cAAc;gBACzC;gBACA,SAAS;gBACT,MAAM,EAAE,GAAG,WAAW,QAAQ,KAAK,OAAM;eAC1C;AACD,mBAAK,aAAa,KAAK,MAAM,OAAO,MAAM,CAAC;YAC7C;UACF,CAAC;QACH;MACF,CAAC;AAED,WAAK,sBAAsB,kBAAkB,SAAS;AAEtD,aAAO,aAAa,OAAO,KAAK,WAAW;IAC7C;EACF;EAEQ,UAAO;AACb,SAAK,OAAO,QAAQ,OAAK,EAAE,eAAe,YAAY,CAAC,CAAC;AACxD,SAAK,SAAS,CAAA;EAChB;EAEA,oBAAiB;AACf,SAAK,aAAY;EACnB;EACA,uBAAoB;AAClB,SAAK,QAAO;EACd;;AAvFQ,WAAA;MADP,kDAAqB,OAAO;;;;;",
4
+ "sourcesContent": ["import { changedAttributeHost } from '../decorators/changedAttributeHost';\nimport { SwcUtils } from '../utils/Utils';\nimport { FunctionUtils, ActionExpression } from '@dooboostore/core';\nimport { ConvertUtils } from '@dooboostore/core-web';\nimport { SwcIfInterface } from '../types';\nimport { attributeHost } from '../decorators';\n\nclass SwcIf extends HTMLTemplateElement implements SwcIfInterface {\n @attributeHost('value')\n _value: any;\n\n @attributeHost('replace-wrap')\n _replaceWrap: string | null;\n\n private _nodes: Node[] = [];\n\n get value(): boolean {\n return this._value;\n }\n\n set value(nv: any) {\n // this._value = nv;\n this.refresh(nv);\n }\n\n private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {\n const config = wrap ? { wrapExpression: wrap } : undefined;\n const ae = new ActionExpression(html, config);\n const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';\n const win = this.ownerDocument?.defaultView || window;\n \n // @ts-ignore\n for (const expr of ae.getExpressions(filterOptions)) {\n try {\n const value = FunctionUtils.executeReturn({\n script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),\n context,\n args: groupArgs\n });\n ae.replace(expr, String(value));\n } catch (e) {\n console.error(`[SWC] Failed to execute ${expr.original}:`, e);\n }\n }\n return ae.getUnprocessedTemplate();\n }\n\n @changedAttributeHost('value')\n private setValue(valueAttr?: string | null) {\n this.refresh();\n }\n\n @changedAttributeHost('replace-wrap')\n private setReplaceWrap(replaceWrapAttr?: string | null) {\n this.refresh();\n }\n\n refresh(value = this._value) {\n this.cleanup();\n const portal = this.parentElement;\n if (!portal || !value) return;\n\n const win = this.ownerDocument?.defaultView || window;\n const helperSet = SwcUtils.getHelperAndHostSet(win, this);\n\n let htmlString = this.innerHTML;\n const groupArgs = { ...helperSet, $value: value };\n\n htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);\n\n const result = this.ownerDocument?.createElement('template') || document.createElement('template');\n result.innerHTML = htmlString;\n const processedFragment = result.content;\n\n this._nodes = Array.from(processedFragment.childNodes);\n portal.insertBefore(processedFragment, this.nextSibling);\n }\n\n private cleanup() {\n this._nodes.forEach(n => n.parentElement?.removeChild(n));\n this._nodes = [];\n }\n\n disconnectedCallback() {\n this.cleanup();\n }\n}\n"],
5
+ "mappings": "AAAA,kCAAqC;AACrC,mBAAyB;AACzB,kBAAgD;AAChD,sBAA6B;AAE7B,wBAA8B;;;;;;;;;;AAE9B,MAAM,cAAc,oBAAmB;EAAvC,cAAA;;AAOU,SAAA,SAAiB,CAAA;EAwE3B;EAtEE,IAAI,QAAK;AACP,WAAO,KAAK;EACd;EAEA,IAAI,MAAM,IAAO;AAEf,SAAK,QAAQ,EAAE;EACjB;EAEQ,mBAAmB,MAAc,WAAgB,SAAc,MAAoB;AACzF,UAAM,SAAS,OAAO,EAAE,gBAAgB,KAAI,IAAK;AACjD,UAAM,KAAK,IAAI,6BAAiB,MAAM,MAAM;AAC5C,UAAM,gBAAgB,OAAO,EAAE,MAAM,WAAoB,KAAI,IAAK;AAClE,UAAM,MAAM,KAAK,eAAe,eAAe;AAG/C,eAAW,QAAQ,GAAG,eAAe,aAAa,GAAG;AACnD,UAAI;AACF,cAAM,QAAQ,0BAAc,cAAc;UACxC,QAAQ,6BAAa,iBAAiB,KAAK,QAAQ,IAAI,QAAQ;UAC/D;UACA,MAAM;SACP;AACD,WAAG,QAAQ,MAAM,OAAO,KAAK,CAAC;MAChC,SAAS,GAAG;AACV,gBAAQ,MAAM,2BAA2B,KAAK,QAAQ,KAAK,CAAC;MAC9D;IACF;AACA,WAAO,GAAG,uBAAsB;EAClC;EAGQ,SAAS,WAAyB;AACxC,SAAK,QAAO;EACd;EAGQ,eAAe,iBAA+B;AACpD,SAAK,QAAO;EACd;EAEA,QAAQ,QAAQ,KAAK,QAAM;AACzB,SAAK,QAAO;AACZ,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,UAAU,CAAC;AAAO;AAEvB,UAAM,MAAM,KAAK,eAAe,eAAe;AAC/C,UAAM,YAAY,sBAAS,oBAAoB,KAAK,IAAI;AAExD,QAAI,aAAa,KAAK;AACtB,UAAM,YAAY,EAAE,GAAG,WAAW,QAAQ,MAAK;AAE/C,iBAAa,KAAK,mBAAmB,YAAY,WAAW,MAAM,KAAK,YAAY;AAEnF,UAAM,SAAS,KAAK,eAAe,cAAc,UAAU,KAAK,SAAS,cAAc,UAAU;AACjG,WAAO,YAAY;AACnB,UAAM,oBAAoB,OAAO;AAEjC,SAAK,SAAS,MAAM,KAAK,kBAAkB,UAAU;AACrD,WAAO,aAAa,mBAAmB,KAAK,WAAW;EACzD;EAEQ,UAAO;AACb,SAAK,OAAO,QAAQ,OAAK,EAAE,eAAe,YAAY,CAAC,CAAC;AACxD,SAAK,SAAS,CAAA;EAChB;EAEA,uBAAoB;AAClB,SAAK,QAAO;EACd;;AA5EA,WAAA;MADC,iCAAc,OAAO;;;AAItB,WAAA;MADC,iCAAc,cAAc;;;AAqCrB,WAAA;MADP,kDAAqB,OAAO;;;;;AAMrB,WAAA;MADP,kDAAqB,cAAc;;;;;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,8 @@
1
1
  var import_changedAttributeHost = require("../decorators/changedAttributeHost");
2
2
  var import_Utils = require("../utils/Utils");
3
3
  var import_core = require("@dooboostore/core");
4
+ var import_core_web = require("@dooboostore/core-web");
5
+ var import_decorators = require("../decorators");
4
6
  var __decorate = function(decorators, target, key, desc) {
5
7
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6
8
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -13,110 +15,88 @@ var __metadata = function(k, v) {
13
15
  class SwcLoop extends HTMLTemplateElement {
14
16
  constructor() {
15
17
  super(...arguments);
16
- this._value = [];
17
18
  this._nodeGroups = [];
18
19
  }
19
20
  get value() {
20
21
  return this._value;
21
22
  }
22
23
  set value(nv) {
23
- this._value = Array.isArray(nv) ? [...nv] : [];
24
- this.render();
24
+ this.refresh(nv);
25
25
  }
26
- _executeCloneCallback(attr, args) {
27
- const script = this.getAttribute(attr);
28
- if (!script)
29
- return;
30
- import_core.FunctionUtils.execute({ script, context: this, args });
26
+ setValue() {
27
+ this.refresh();
31
28
  }
32
- _cleanup() {
33
- this._nodeGroups.forEach((nodes) => nodes.forEach((n) => n.parentElement?.removeChild(n)));
34
- this._nodeGroups = [];
29
+ setReplaceWrap() {
30
+ this.refresh();
35
31
  }
36
- refreshValue() {
37
- let script = this.getAttribute("value");
38
- if (!script) {
39
- this.value = [];
40
- return;
41
- }
42
- if (script.startsWith("{{") && script.endsWith("}}")) {
43
- script = script.slice(2, -2).trim();
44
- }
32
+ replaceExpressions(html, groupArgs, context, wrap) {
33
+ const config = wrap ? { wrapExpression: wrap } : void 0;
34
+ const ae = new import_core.ActionExpression(html, config);
35
+ const filterOptions = wrap ? { type: "replace", wrap } : "replace";
45
36
  const win = this.ownerDocument?.defaultView || window;
46
- const res = import_core.FunctionUtils.executeReturn({
47
- script,
48
- context: this,
49
- args: import_Utils.SwcUtils.getHelperAndHostSet(win, this)
50
- });
51
- if (res instanceof Promise) {
52
- res.then((v) => this.value = v).catch(() => this.value = []);
53
- } else {
54
- this.value = res;
37
+ for (const expr of ae.getExpressions(filterOptions)) {
38
+ try {
39
+ const value = import_core.FunctionUtils.executeReturn({
40
+ script: import_core_web.ConvertUtils.decodeHtmlEntity(expr.script, win.document),
41
+ context,
42
+ args: groupArgs
43
+ });
44
+ ae.replace(expr, String(value));
45
+ } catch (e) {
46
+ console.error(`[SWC] Failed to execute ${expr.original}:`, e);
47
+ }
55
48
  }
49
+ return ae.getUnprocessedTemplate();
56
50
  }
57
- render() {
58
- this._cleanup();
51
+ refresh(value = this._value) {
52
+ this.cleanup();
53
+ if (value?.length <= 0)
54
+ return;
59
55
  const portal = this.parentElement;
60
56
  if (!portal)
61
57
  return;
62
58
  const win = this.ownerDocument?.defaultView || window;
63
59
  const helperSet = import_Utils.SwcUtils.getHelperAndHostSet(win, this);
64
60
  const fragment = win.document.createDocumentFragment();
65
- if (this._value.length === 0) {
66
- const defaultTpl = this.content.querySelector('template[is="swc-default"]');
67
- if (defaultTpl) {
68
- const clone = defaultTpl.content.cloneNode(true);
69
- const nodes = Array.from(clone.childNodes);
70
- this._nodeGroups.push(nodes);
71
- fragment.appendChild(clone);
72
- }
73
- } else {
74
- this._value.forEach((item, index) => {
75
- const clone = this.content.cloneNode(true);
76
- const subTemplates = clone.querySelectorAll('template[is^="swc-"]');
77
- subTemplates.forEach((t) => t.remove());
78
- const nodes = Array.from(clone.childNodes);
79
- const elements = nodes.filter((n) => n.nodeType === 1);
80
- const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value, $nodes: nodes, $elements: elements, $firstElement: elements[0] };
81
- nodes.forEach((node, nodeIdx) => {
82
- this._executeCloneCallback("on-clone-node", { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });
83
- if (node instanceof HTMLElement) {
84
- Array.from(node.attributes).forEach((attr) => {
85
- const value = attr.value || "";
86
- if (value.startsWith("{{") && value.endsWith("}}")) {
87
- const script = value.slice(2, -2).trim();
88
- const result = import_core.FunctionUtils.executeReturn({
89
- script,
90
- context: node,
91
- args: groupArgs
92
- });
93
- node.setAttribute(attr.name, String(result));
94
- }
95
- });
96
- }
97
- });
98
- this._executeCloneCallback("on-clone-nodes", groupArgs);
99
- this._nodeGroups.push(nodes);
100
- fragment.appendChild(clone);
101
- });
102
- }
103
- if (portal === this.parentElement) {
104
- portal.insertBefore(fragment, this.nextSibling);
105
- } else {
106
- portal.appendChild(fragment);
107
- }
61
+ value.forEach((item, index) => {
62
+ let htmlString = this.innerHTML;
63
+ const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value };
64
+ htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
65
+ const temp = this.ownerDocument?.createElement("template") || document.createElement("template");
66
+ temp.innerHTML = htmlString;
67
+ const content = temp.content;
68
+ const nodes = Array.from(content.childNodes);
69
+ this._nodeGroups.push(nodes);
70
+ fragment.appendChild(content);
71
+ });
72
+ portal.insertBefore(fragment, this.nextSibling);
108
73
  }
109
- connectedCallback() {
110
- this.refreshValue();
74
+ cleanup() {
75
+ this._nodeGroups.forEach((nodes) => nodes.forEach((n) => n.parentElement?.removeChild(n)));
76
+ this._nodeGroups = [];
111
77
  }
112
78
  disconnectedCallback() {
113
- this._cleanup();
79
+ this.cleanup();
114
80
  }
115
81
  }
82
+ __decorate([
83
+ (0, import_decorators.attributeHost)("value"),
84
+ __metadata("design:type", Array)
85
+ ], SwcLoop.prototype, "_value", void 0);
86
+ __decorate([
87
+ (0, import_decorators.attributeHost)("replace-wrap"),
88
+ __metadata("design:type", String)
89
+ ], SwcLoop.prototype, "_replaceWrap", void 0);
116
90
  __decorate([
117
91
  (0, import_changedAttributeHost.changedAttributeHost)("value"),
118
92
  __metadata("design:type", Function),
119
93
  __metadata("design:paramtypes", []),
120
94
  __metadata("design:returntype", void 0)
121
- ], SwcLoop.prototype, "refreshValue", null);
95
+ ], SwcLoop.prototype, "setValue", null);
96
+ __decorate([
97
+ (0, import_changedAttributeHost.changedAttributeHost)("replace-wrap"),
98
+ __metadata("design:type", Function),
99
+ __metadata("design:paramtypes", []),
100
+ __metadata("design:returntype", void 0)
101
+ ], SwcLoop.prototype, "setReplaceWrap", null);
122
102
  //# sourceMappingURL=SwcLoop.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/elements/SwcLoop.ts"],
4
- "sourcesContent": ["import { changedAttributeHost } from '../decorators/changedAttributeHost';\nimport { SwcUtils } from '../utils/Utils';\nimport { FunctionUtils } from '@dooboostore/core';\n\nclass SwcLoop extends HTMLTemplateElement {\n private _value: any[] = [];\n private _nodeGroups: Node[][] = [];\n\n get value(): any[] {\n return this._value;\n }\n set value(nv: any[]) {\n this._value = Array.isArray(nv) ? [...nv] : [];\n this.render();\n }\n\n\n\n private _executeCloneCallback(attr: string, args: any) {\n const script = this.getAttribute(attr);\n if (!script) return;\n FunctionUtils.execute({ script, context: this, args });\n }\n\n private _cleanup() {\n this._nodeGroups.forEach(nodes => nodes.forEach(n => n.parentElement?.removeChild(n)));\n this._nodeGroups = [];\n }\n\n @changedAttributeHost('value')\n private refreshValue() {\n let script = this.getAttribute('value');\n if (!script) {\n this.value = [];\n return;\n }\n // Parse {{ }} braces\n if (script.startsWith('{{') && script.endsWith('}}')) {\n script = script.slice(2, -2).trim();\n }\n const win = this.ownerDocument?.defaultView || window;\n const res = FunctionUtils.executeReturn({\n script,\n context: this,\n args: SwcUtils.getHelperAndHostSet(win, this)\n });\n\n if (res instanceof Promise) {\n res.then(v => (this.value = v)).catch(() => (this.value = []));\n } else {\n this.value = res;\n }\n }\n\n render() {\n this._cleanup();\n const portal = this.parentElement;\n if (!portal) return;\n\n const win = this.ownerDocument?.defaultView || window;\n const helperSet = SwcUtils.getHelperAndHostSet(win, this);\n const fragment = win.document.createDocumentFragment();\n\n if (this._value.length === 0) {\n const defaultTpl = this.content.querySelector('template[is=\"swc-default\"]') as HTMLTemplateElement;\n if (defaultTpl) {\n const clone = defaultTpl.content.cloneNode(true);\n const nodes = Array.from(clone.childNodes);\n this._nodeGroups.push(nodes);\n fragment.appendChild(clone);\n }\n } else {\n this._value.forEach((item, index) => {\n const clone = this.content.cloneNode(true) as DocumentFragment;\n // Filter out sub-templates\n const subTemplates = clone.querySelectorAll('template[is^=\"swc-\"]');\n subTemplates.forEach(t => t.remove());\n\n const nodes = Array.from(clone.childNodes);\n const elements = nodes.filter(n => n.nodeType === 1) as HTMLElement[];\n\n const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value, $nodes: nodes, $elements: elements, $firstElement: elements[0] };\n\n nodes.forEach((node, nodeIdx) => {\n this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });\n\n // Attribute {{ }} 치환 - SwcChoose처럼 동적 치환\n if (node instanceof HTMLElement) {\n Array.from(node.attributes).forEach(attr => {\n const value = attr.value || '';\n if (value.startsWith('{{') && value.endsWith('}}')) {\n const script = value.slice(2, -2).trim();\n const result = FunctionUtils.executeReturn({\n script,\n context: node,\n args: groupArgs\n });\n node.setAttribute(attr.name, String(result));\n }\n });\n }\n });\n\n this._executeCloneCallback('on-clone-nodes', groupArgs);\n this._nodeGroups.push(nodes);\n fragment.appendChild(clone);\n });\n }\n\n if (portal === this.parentElement) {\n portal.insertBefore(fragment, this.nextSibling);\n } else {\n portal.appendChild(fragment);\n }\n }\n\n connectedCallback() {\n this.refreshValue();\n }\n disconnectedCallback() {\n this._cleanup();\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { changedAttributeHost } from '../decorators/changedAttributeHost';\nimport { SwcUtils } from '../utils/Utils';\nimport { FunctionUtils, ActionExpression } from '@dooboostore/core';\nimport { ConvertUtils } from '@dooboostore/core-web';\nimport { attributeHost } from '../decorators';\n\nclass SwcLoop extends HTMLTemplateElement {\n @attributeHost('value')\n _value: any[];\n\n @attributeHost('replace-wrap')\n _replaceWrap: string | null;\n\n private _nodeGroups: Node[][] = [];\n\n get value(): any[] {\n return this._value;\n }\n set value(nv: any[]) {\n // this._value = Array.isArray(nv) ? [...nv] : [];\n this.refresh(nv);\n }\n\n @changedAttributeHost('value')\n private setValue() {\n this.refresh();\n }\n\n @changedAttributeHost('replace-wrap')\n private setReplaceWrap() {\n this.refresh();\n }\n\n private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {\n const config = wrap ? { wrapExpression: wrap } : undefined;\n const ae = new ActionExpression(html, config);\n const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';\n const win = this.ownerDocument?.defaultView || window;\n\n // @ts-ignore\n for (const expr of ae.getExpressions(filterOptions)) {\n try {\n const value = FunctionUtils.executeReturn({\n script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),\n context,\n args: groupArgs\n });\n ae.replace(expr, String(value));\n } catch (e) {\n console.error(`[SWC] Failed to execute ${expr.original}:`, e);\n }\n }\n return ae.getUnprocessedTemplate();\n }\n\n refresh(value = this._value) {\n this.cleanup();\n if (value?.length<=0) return;\n const portal = this.parentElement;\n if (!portal) return;\n\n const win = this.ownerDocument?.defaultView || window;\n const helperSet = SwcUtils.getHelperAndHostSet(win, this);\n const fragment = win.document.createDocumentFragment();\n\n value.forEach((item, index) => {\n let htmlString = this.innerHTML;\n const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value };\n\n htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);\n\n const temp = this.ownerDocument?.createElement('template') || document.createElement('template');\n temp.innerHTML = htmlString;\n\n const content = temp.content;\n const nodes = Array.from(content.childNodes);\n this._nodeGroups.push(nodes);\n fragment.appendChild(content);\n });\n\n portal.insertBefore(fragment, this.nextSibling);\n }\n\n private cleanup() {\n this._nodeGroups.forEach(nodes => nodes.forEach(n => n.parentElement?.removeChild(n)));\n this._nodeGroups = [];\n }\n\n disconnectedCallback() {\n this.cleanup();\n }\n}\n"],
5
+ "mappings": "AAAA,kCAAqC;AACrC,mBAAyB;AACzB,kBAAgD;AAChD,sBAA6B;AAC7B,wBAA8B;;;;;;;;;;AAE9B,MAAM,gBAAgB,oBAAmB;EAAzC,cAAA;;AAOU,SAAA,cAAwB,CAAA;EA8ElC;EA5EE,IAAI,QAAK;AACP,WAAO,KAAK;EACd;EACA,IAAI,MAAM,IAAS;AAEjB,SAAK,QAAQ,EAAE;EACjB;EAGQ,WAAQ;AACd,SAAK,QAAO;EACd;EAGQ,iBAAc;AACpB,SAAK,QAAO;EACd;EAEQ,mBAAmB,MAAc,WAAgB,SAAc,MAAoB;AACzF,UAAM,SAAS,OAAO,EAAE,gBAAgB,KAAI,IAAK;AACjD,UAAM,KAAK,IAAI,6BAAiB,MAAM,MAAM;AAC5C,UAAM,gBAAgB,OAAO,EAAE,MAAM,WAAoB,KAAI,IAAK;AAClE,UAAM,MAAM,KAAK,eAAe,eAAe;AAG/C,eAAW,QAAQ,GAAG,eAAe,aAAa,GAAG;AACnD,UAAI;AACF,cAAM,QAAQ,0BAAc,cAAc;UACxC,QAAQ,6BAAa,iBAAiB,KAAK,QAAQ,IAAI,QAAQ;UAC/D;UACA,MAAM;SACP;AACD,WAAG,QAAQ,MAAM,OAAO,KAAK,CAAC;MAChC,SAAS,GAAG;AACV,gBAAQ,MAAM,2BAA2B,KAAK,QAAQ,KAAK,CAAC;MAC9D;IACF;AACA,WAAO,GAAG,uBAAsB;EAClC;EAEA,QAAQ,QAAQ,KAAK,QAAM;AACzB,SAAK,QAAO;AACZ,QAAI,OAAO,UAAQ;AAAG;AACtB,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC;AAAQ;AAEb,UAAM,MAAM,KAAK,eAAe,eAAe;AAC/C,UAAM,YAAY,sBAAS,oBAAoB,KAAK,IAAI;AACxD,UAAM,WAAW,IAAI,SAAS,uBAAsB;AAEpD,UAAM,QAAQ,CAAC,MAAM,UAAS;AAC5B,UAAI,aAAa,KAAK;AACtB,YAAM,YAAY,EAAE,GAAG,WAAW,OAAO,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAM;AAEjF,mBAAa,KAAK,mBAAmB,YAAY,WAAW,MAAM,KAAK,YAAY;AAEnF,YAAM,OAAO,KAAK,eAAe,cAAc,UAAU,KAAK,SAAS,cAAc,UAAU;AAC/F,WAAK,YAAY;AAEjB,YAAM,UAAU,KAAK;AACrB,YAAM,QAAQ,MAAM,KAAK,QAAQ,UAAU;AAC3C,WAAK,YAAY,KAAK,KAAK;AAC3B,eAAS,YAAY,OAAO;IAC9B,CAAC;AAED,WAAO,aAAa,UAAU,KAAK,WAAW;EAChD;EAEQ,UAAO;AACb,SAAK,YAAY,QAAQ,WAAS,MAAM,QAAQ,OAAK,EAAE,eAAe,YAAY,CAAC,CAAC,CAAC;AACrF,SAAK,cAAc,CAAA;EACrB;EAEA,uBAAoB;AAClB,SAAK,QAAO;EACd;;AAlFA,WAAA;MADC,iCAAc,OAAO;;;AAItB,WAAA;MADC,iCAAc,cAAc;;;AAcrB,WAAA;MADP,kDAAqB,OAAO;;;;;AAMrB,WAAA;MADP,kDAAqB,cAAc;;;;;",
6
6
  "names": []
7
7
  }