ninegrid2 6.1252.0 → 6.1253.0

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.
@@ -121838,33 +121838,48 @@ class nxTitle extends HTMLElement {
121838
121838
 
121839
121839
  customElements.define("nx-title", nxTitle);
121840
121840
 
121841
- class nxDiv extends HTMLElement
121842
- {
121841
+ class nxDiv extends HTMLElement {
121843
121842
  originContents;
121844
121843
  #isInitialized = false;
121844
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
121845
121845
 
121846
- constructor () {
121846
+ constructor() {
121847
121847
  super();
121848
- this.attachShadow({ mode: 'open' });
121848
+ // 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
121849
+ const useShadow = this.getAttribute("use-shadow") !== "false";
121850
+
121851
+ if (useShadow) {
121852
+ this.attachShadow({ mode: 'open' });
121853
+ this.#root = this.shadowRoot;
121854
+ } else {
121855
+ this.#root = this;
121856
+ }
121849
121857
  }
121850
121858
 
121851
121859
  connectedCallback() {
121852
121860
  if (!this.#isInitialized) {
121853
121861
  this.#init();
121854
- this.#isInitialized = true; // 3. 초기화 후 플래그를 true로 변경합니다.
121862
+ this.#isInitialized = true;
121855
121863
  return true;
121856
121864
  }
121857
-
121858
121865
  return false;
121859
121866
  }
121860
121867
 
121868
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
121869
+ #getElements() {
121870
+ return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
121871
+ }
121872
+
121873
+ // 자식 클래스에서 접근할 수 있도록 getter 제공
121874
+ get root() {
121875
+ return this.#root;
121876
+ }
121877
+
121861
121878
  getData = () => {
121862
121879
  const jsonData = {};
121863
-
121864
- // Shadow DOM 내의 폼 요소만 선택
121865
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121880
+ this.#getElements().forEach(el => {
121866
121881
  const key = el.name;
121867
- if (!key) return; // name이 없는 요소는 건너뜁니다.
121882
+ if (!key) return;
121868
121883
 
121869
121884
  let value;
121870
121885
  if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
@@ -121873,50 +121888,40 @@ class nxDiv extends HTMLElement
121873
121888
  value = el.value;
121874
121889
  }
121875
121890
 
121876
- // 중복 name을 대비한 배열 처리
121877
121891
  if (jsonData[key]) {
121878
- if (!Array.isArray(jsonData[key])) {
121879
- jsonData[key] = [jsonData[key]];
121880
- }
121892
+ if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
121881
121893
  jsonData[key].push(value);
121882
121894
  } else {
121883
121895
  jsonData[key] = value;
121884
121896
  }
121885
121897
  });
121886
-
121887
121898
  return jsonData;
121888
121899
  };
121889
121900
 
121890
121901
  setData = (jsonData) => {
121891
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121892
- console.log("------", el);
121902
+ this.#getElements().forEach(el => {
121893
121903
  el.removeEventListener("input", this.#changeHandler);
121894
121904
  el.addEventListener("input", this.#changeHandler);
121895
121905
  });
121896
121906
 
121897
- if (!jsonData || typeof jsonData !== 'object') {
121898
- console.error("setData: Invalid data provided. Expected an object.");
121899
- return;
121900
- }
121907
+ if (!jsonData || typeof jsonData !== 'object') return;
121901
121908
 
121902
121909
  let bChanged = false;
121903
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121910
+ this.#getElements().forEach(el => {
121904
121911
  const key = el.name;
121905
121912
  if (!key || !jsonData.hasOwnProperty(key)) return;
121906
121913
 
121907
121914
  const value = jsonData[key];
121908
-
121909
- // 폼 요소에만 데이터를 설정합니다.
121910
121915
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
121911
121916
  if (el.type === "checkbox" || el.type === "radio") {
121912
- if (el.checked !== (el.value === String(value))) bChanged = true;
121913
- el.checked = (el.value === String(value));
121917
+ const isChecked = (String(el.value) === String(value));
121918
+ if (el.checked !== isChecked) bChanged = true;
121919
+ el.checked = isChecked;
121914
121920
  } else {
121915
121921
  if (el.value !== value) bChanged = true;
121916
121922
  el.value = value;
121917
121923
  }
121918
121924
  } else {
121919
- // 폼 요소가 아닌 경우, textContent를 사용합니다.
121920
121925
  if (el.textContent !== value) bChanged = true;
121921
121926
  el.textContent = value;
121922
121927
  }
@@ -121943,22 +121948,33 @@ class nxDiv extends HTMLElement
121943
121948
  }
121944
121949
 
121945
121950
  #init = () => {
121946
-
121947
- //console.log(this);
121948
- //console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
121949
-
121950
- /**
121951
- * css style 적용
121952
- */
121951
+ // 1. CSS Style 적용
121953
121952
  for (const attr of this.attributes) {
121954
121953
  if (attr.name.startsWith("css-")) {
121955
- // "css-" 접두사를 제거하고 CSS 속성명으로 변환
121956
121954
  this.style.setProperty(attr.name.substring(4), attr.value);
121957
121955
  }
121958
121956
  }
121959
121957
 
121958
+ // 2. 이미 초기화가 완료되었거나 내용이 옮겨졌는지 확인
121959
+ if (this.shadowRoot && this.shadowRoot.innerHTML.trim() !== "") {
121960
+ return; // 이미 내용이 있으면 중복 실행 방지
121961
+ }
121962
+
121963
+ // 3. HTML 내용 처리
121960
121964
  this.originContents = this.innerHTML.trim();
121961
- this.innerHTML = ""; // 기존 내부 HTML 제거
121965
+
121966
+ if (this.shadowRoot) {
121967
+ // Shadow DOM 모드일 때
121968
+ // 만약 자식 클래스에서 별도 템플릿을 그린다면 여기서는 비워두거나
121969
+ // 기본 뼈대만 잡아야 합니다.
121970
+ if (this.shadowRoot.innerHTML === "") {
121971
+ this.shadowRoot.innerHTML = this.originContents;
121972
+ }
121973
+
121974
+ // 중요: React가 다시 자식을 채우지 않도록 비우되,
121975
+ // 하위 클래스에서 처리할 수 있도록 보존만 합니다.
121976
+ this.innerHTML = "";
121977
+ }
121962
121978
  };
121963
121979
  }
121964
121980
 
@@ -121834,33 +121834,48 @@ class nxTitle extends HTMLElement {
121834
121834
 
121835
121835
  customElements.define("nx-title", nxTitle);
121836
121836
 
121837
- class nxDiv extends HTMLElement
121838
- {
121837
+ class nxDiv extends HTMLElement {
121839
121838
  originContents;
121840
121839
  #isInitialized = false;
121840
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
121841
121841
 
121842
- constructor () {
121842
+ constructor() {
121843
121843
  super();
121844
- this.attachShadow({ mode: 'open' });
121844
+ // 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
121845
+ const useShadow = this.getAttribute("use-shadow") !== "false";
121846
+
121847
+ if (useShadow) {
121848
+ this.attachShadow({ mode: 'open' });
121849
+ this.#root = this.shadowRoot;
121850
+ } else {
121851
+ this.#root = this;
121852
+ }
121845
121853
  }
121846
121854
 
121847
121855
  connectedCallback() {
121848
121856
  if (!this.#isInitialized) {
121849
121857
  this.#init();
121850
- this.#isInitialized = true; // 3. 초기화 후 플래그를 true로 변경합니다.
121858
+ this.#isInitialized = true;
121851
121859
  return true;
121852
121860
  }
121853
-
121854
121861
  return false;
121855
121862
  }
121856
121863
 
121864
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
121865
+ #getElements() {
121866
+ return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
121867
+ }
121868
+
121869
+ // 자식 클래스에서 접근할 수 있도록 getter 제공
121870
+ get root() {
121871
+ return this.#root;
121872
+ }
121873
+
121857
121874
  getData = () => {
121858
121875
  const jsonData = {};
121859
-
121860
- // Shadow DOM 내의 폼 요소만 선택
121861
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121876
+ this.#getElements().forEach(el => {
121862
121877
  const key = el.name;
121863
- if (!key) return; // name이 없는 요소는 건너뜁니다.
121878
+ if (!key) return;
121864
121879
 
121865
121880
  let value;
121866
121881
  if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
@@ -121869,50 +121884,40 @@ class nxDiv extends HTMLElement
121869
121884
  value = el.value;
121870
121885
  }
121871
121886
 
121872
- // 중복 name을 대비한 배열 처리
121873
121887
  if (jsonData[key]) {
121874
- if (!Array.isArray(jsonData[key])) {
121875
- jsonData[key] = [jsonData[key]];
121876
- }
121888
+ if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
121877
121889
  jsonData[key].push(value);
121878
121890
  } else {
121879
121891
  jsonData[key] = value;
121880
121892
  }
121881
121893
  });
121882
-
121883
121894
  return jsonData;
121884
121895
  };
121885
121896
 
121886
121897
  setData = (jsonData) => {
121887
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121888
- console.log("------", el);
121898
+ this.#getElements().forEach(el => {
121889
121899
  el.removeEventListener("input", this.#changeHandler);
121890
121900
  el.addEventListener("input", this.#changeHandler);
121891
121901
  });
121892
121902
 
121893
- if (!jsonData || typeof jsonData !== 'object') {
121894
- console.error("setData: Invalid data provided. Expected an object.");
121895
- return;
121896
- }
121903
+ if (!jsonData || typeof jsonData !== 'object') return;
121897
121904
 
121898
121905
  let bChanged = false;
121899
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
121906
+ this.#getElements().forEach(el => {
121900
121907
  const key = el.name;
121901
121908
  if (!key || !jsonData.hasOwnProperty(key)) return;
121902
121909
 
121903
121910
  const value = jsonData[key];
121904
-
121905
- // 폼 요소에만 데이터를 설정합니다.
121906
121911
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
121907
121912
  if (el.type === "checkbox" || el.type === "radio") {
121908
- if (el.checked !== (el.value === String(value))) bChanged = true;
121909
- el.checked = (el.value === String(value));
121913
+ const isChecked = (String(el.value) === String(value));
121914
+ if (el.checked !== isChecked) bChanged = true;
121915
+ el.checked = isChecked;
121910
121916
  } else {
121911
121917
  if (el.value !== value) bChanged = true;
121912
121918
  el.value = value;
121913
121919
  }
121914
121920
  } else {
121915
- // 폼 요소가 아닌 경우, textContent를 사용합니다.
121916
121921
  if (el.textContent !== value) bChanged = true;
121917
121922
  el.textContent = value;
121918
121923
  }
@@ -121939,22 +121944,33 @@ class nxDiv extends HTMLElement
121939
121944
  }
121940
121945
 
121941
121946
  #init = () => {
121942
-
121943
- //console.log(this);
121944
- //console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
121945
-
121946
- /**
121947
- * css style 적용
121948
- */
121947
+ // 1. CSS Style 적용
121949
121948
  for (const attr of this.attributes) {
121950
121949
  if (attr.name.startsWith("css-")) {
121951
- // "css-" 접두사를 제거하고 CSS 속성명으로 변환
121952
121950
  this.style.setProperty(attr.name.substring(4), attr.value);
121953
121951
  }
121954
121952
  }
121955
121953
 
121954
+ // 2. 이미 초기화가 완료되었거나 내용이 옮겨졌는지 확인
121955
+ if (this.shadowRoot && this.shadowRoot.innerHTML.trim() !== "") {
121956
+ return; // 이미 내용이 있으면 중복 실행 방지
121957
+ }
121958
+
121959
+ // 3. HTML 내용 처리
121956
121960
  this.originContents = this.innerHTML.trim();
121957
- this.innerHTML = ""; // 기존 내부 HTML 제거
121961
+
121962
+ if (this.shadowRoot) {
121963
+ // Shadow DOM 모드일 때
121964
+ // 만약 자식 클래스에서 별도 템플릿을 그린다면 여기서는 비워두거나
121965
+ // 기본 뼈대만 잡아야 합니다.
121966
+ if (this.shadowRoot.innerHTML === "") {
121967
+ this.shadowRoot.innerHTML = this.originContents;
121968
+ }
121969
+
121970
+ // 중요: React가 다시 자식을 채우지 않도록 비우되,
121971
+ // 하위 클래스에서 처리할 수 있도록 보존만 합니다.
121972
+ this.innerHTML = "";
121973
+ }
121958
121974
  };
121959
121975
  }
121960
121976
 
package/dist/nx/_nxDiv.js CHANGED
@@ -1,32 +1,47 @@
1
1
  import ninegrid from "../index.js";
2
2
 
3
- export class nxDiv extends HTMLElement
4
- {
3
+ export class nxDiv extends HTMLElement {
5
4
  originContents;
6
5
  #isInitialized = false;
6
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
7
7
 
8
- constructor () {
8
+ constructor() {
9
9
  super();
10
- this.attachShadow({ mode: 'open' });
10
+ // 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
11
+ const useShadow = this.getAttribute("use-shadow") !== "false";
12
+
13
+ if (useShadow) {
14
+ this.attachShadow({ mode: 'open' });
15
+ this.#root = this.shadowRoot;
16
+ } else {
17
+ this.#root = this;
18
+ }
11
19
  }
12
20
 
13
21
  connectedCallback() {
14
22
  if (!this.#isInitialized) {
15
23
  this.#init();
16
- this.#isInitialized = true; // 3. 초기화 후 플래그를 true로 변경합니다.
24
+ this.#isInitialized = true;
17
25
  return true;
18
26
  }
19
-
20
27
  return false;
21
28
  }
22
29
 
30
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
31
+ #getElements() {
32
+ return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
33
+ }
34
+
35
+ // 자식 클래스에서 접근할 수 있도록 getter 제공
36
+ get root() {
37
+ return this.#root;
38
+ }
39
+
23
40
  getData = () => {
24
41
  const jsonData = {};
25
-
26
- // Shadow DOM 내의 폼 요소만 선택
27
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
42
+ this.#getElements().forEach(el => {
28
43
  const key = el.name;
29
- if (!key) return; // name이 없는 요소는 건너뜁니다.
44
+ if (!key) return;
30
45
 
31
46
  let value;
32
47
  if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
@@ -35,50 +50,40 @@ export class nxDiv extends HTMLElement
35
50
  value = el.value;
36
51
  }
37
52
 
38
- // 중복 name을 대비한 배열 처리
39
53
  if (jsonData[key]) {
40
- if (!Array.isArray(jsonData[key])) {
41
- jsonData[key] = [jsonData[key]];
42
- }
54
+ if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
43
55
  jsonData[key].push(value);
44
56
  } else {
45
57
  jsonData[key] = value;
46
58
  }
47
59
  });
48
-
49
60
  return jsonData;
50
61
  };
51
62
 
52
63
  setData = (jsonData) => {
53
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
54
- console.log("------", el);
64
+ this.#getElements().forEach(el => {
55
65
  el.removeEventListener("input", this.#changeHandler);
56
66
  el.addEventListener("input", this.#changeHandler);
57
67
  });
58
68
 
59
- if (!jsonData || typeof jsonData !== 'object') {
60
- console.error("setData: Invalid data provided. Expected an object.");
61
- return;
62
- }
69
+ if (!jsonData || typeof jsonData !== 'object') return;
63
70
 
64
71
  let bChanged = false;
65
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
72
+ this.#getElements().forEach(el => {
66
73
  const key = el.name;
67
74
  if (!key || !jsonData.hasOwnProperty(key)) return;
68
75
 
69
76
  const value = jsonData[key];
70
-
71
- // 폼 요소에만 데이터를 설정합니다.
72
77
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
73
78
  if (el.type === "checkbox" || el.type === "radio") {
74
- if (el.checked !== (el.value === String(value))) bChanged = true;
75
- el.checked = (el.value === String(value));
79
+ const isChecked = (String(el.value) === String(value));
80
+ if (el.checked !== isChecked) bChanged = true;
81
+ el.checked = isChecked;
76
82
  } else {
77
83
  if (el.value !== value) bChanged = true;
78
84
  el.value = value;
79
85
  }
80
86
  } else {
81
- // 폼 요소가 아닌 경우, textContent를 사용합니다.
82
87
  if (el.textContent !== value) bChanged = true;
83
88
  el.textContent = value;
84
89
  }
@@ -105,21 +110,32 @@ export class nxDiv extends HTMLElement
105
110
  }
106
111
 
107
112
  #init = () => {
108
-
109
- //console.log(this);
110
- //console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
111
-
112
- /**
113
- * css style 적용
114
- */
113
+ // 1. CSS Style 적용
115
114
  for (const attr of this.attributes) {
116
115
  if (attr.name.startsWith("css-")) {
117
- // "css-" 접두사를 제거하고 CSS 속성명으로 변환
118
116
  this.style.setProperty(attr.name.substring(4), attr.value);
119
117
  }
120
118
  }
121
119
 
120
+ // 2. 이미 초기화가 완료되었거나 내용이 옮겨졌는지 확인
121
+ if (this.shadowRoot && this.shadowRoot.innerHTML.trim() !== "") {
122
+ return; // 이미 내용이 있으면 중복 실행 방지
123
+ }
124
+
125
+ // 3. HTML 내용 처리
122
126
  this.originContents = this.innerHTML.trim();
123
- this.innerHTML = ""; // 기존 내부 HTML 제거
127
+
128
+ if (this.shadowRoot) {
129
+ // Shadow DOM 모드일 때
130
+ // 만약 자식 클래스에서 별도 템플릿을 그린다면 여기서는 비워두거나
131
+ // 기본 뼈대만 잡아야 합니다.
132
+ if (this.shadowRoot.innerHTML === "") {
133
+ this.shadowRoot.innerHTML = this.originContents;
134
+ }
135
+
136
+ // 중요: React가 다시 자식을 채우지 않도록 비우되,
137
+ // 하위 클래스에서 처리할 수 있도록 보존만 합니다.
138
+ this.innerHTML = "";
139
+ }
124
140
  };
125
141
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ninegrid2",
3
3
  "type": "module",
4
- "version": "6.1252.0",
4
+ "version": "6.1253.0",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {
package/src/nx/_nxDiv.js CHANGED
@@ -1,32 +1,47 @@
1
1
  import ninegrid from "../index.js";
2
2
 
3
- export class nxDiv extends HTMLElement
4
- {
3
+ export class nxDiv extends HTMLElement {
5
4
  originContents;
6
5
  #isInitialized = false;
6
+ #root; // Shadow DOM 사용 여부에 따라 shadowRoot 또는 this를 가리킴
7
7
 
8
- constructor () {
8
+ constructor() {
9
9
  super();
10
- this.attachShadow({ mode: 'open' });
10
+ // 1. 'use-shadow' 속성이 "false"가 아니면 기본적으로 Shadow DOM을 사용하도록 설정
11
+ const useShadow = this.getAttribute("use-shadow") !== "false";
12
+
13
+ if (useShadow) {
14
+ this.attachShadow({ mode: 'open' });
15
+ this.#root = this.shadowRoot;
16
+ } else {
17
+ this.#root = this;
18
+ }
11
19
  }
12
20
 
13
21
  connectedCallback() {
14
22
  if (!this.#isInitialized) {
15
23
  this.#init();
16
- this.#isInitialized = true; // 3. 초기화 후 플래그를 true로 변경합니다.
24
+ this.#isInitialized = true;
17
25
  return true;
18
26
  }
19
-
20
27
  return false;
21
28
  }
22
29
 
30
+ // 공통 쿼리 함수: 현재 root(Shadow 또는 Light DOM)에서 요소를 찾음
31
+ #getElements() {
32
+ return ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.#root);
33
+ }
34
+
35
+ // 자식 클래스에서 접근할 수 있도록 getter 제공
36
+ get root() {
37
+ return this.#root;
38
+ }
39
+
23
40
  getData = () => {
24
41
  const jsonData = {};
25
-
26
- // Shadow DOM 내의 폼 요소만 선택
27
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
42
+ this.#getElements().forEach(el => {
28
43
  const key = el.name;
29
- if (!key) return; // name이 없는 요소는 건너뜁니다.
44
+ if (!key) return;
30
45
 
31
46
  let value;
32
47
  if (el.tagName === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
@@ -35,50 +50,40 @@ export class nxDiv extends HTMLElement
35
50
  value = el.value;
36
51
  }
37
52
 
38
- // 중복 name을 대비한 배열 처리
39
53
  if (jsonData[key]) {
40
- if (!Array.isArray(jsonData[key])) {
41
- jsonData[key] = [jsonData[key]];
42
- }
54
+ if (!Array.isArray(jsonData[key])) jsonData[key] = [jsonData[key]];
43
55
  jsonData[key].push(value);
44
56
  } else {
45
57
  jsonData[key] = value;
46
58
  }
47
59
  });
48
-
49
60
  return jsonData;
50
61
  };
51
62
 
52
63
  setData = (jsonData) => {
53
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
54
- console.log("------", el);
64
+ this.#getElements().forEach(el => {
55
65
  el.removeEventListener("input", this.#changeHandler);
56
66
  el.addEventListener("input", this.#changeHandler);
57
67
  });
58
68
 
59
- if (!jsonData || typeof jsonData !== 'object') {
60
- console.error("setData: Invalid data provided. Expected an object.");
61
- return;
62
- }
69
+ if (!jsonData || typeof jsonData !== 'object') return;
63
70
 
64
71
  let bChanged = false;
65
- ninegrid.querySelectorAll("input[name], textarea[name], select[name]", this.shadowRoot).forEach(el => {
72
+ this.#getElements().forEach(el => {
66
73
  const key = el.name;
67
74
  if (!key || !jsonData.hasOwnProperty(key)) return;
68
75
 
69
76
  const value = jsonData[key];
70
-
71
- // 폼 요소에만 데이터를 설정합니다.
72
77
  if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
73
78
  if (el.type === "checkbox" || el.type === "radio") {
74
- if (el.checked !== (el.value === String(value))) bChanged = true;
75
- el.checked = (el.value === String(value));
79
+ const isChecked = (String(el.value) === String(value));
80
+ if (el.checked !== isChecked) bChanged = true;
81
+ el.checked = isChecked;
76
82
  } else {
77
83
  if (el.value !== value) bChanged = true;
78
84
  el.value = value;
79
85
  }
80
86
  } else {
81
- // 폼 요소가 아닌 경우, textContent를 사용합니다.
82
87
  if (el.textContent !== value) bChanged = true;
83
88
  el.textContent = value;
84
89
  }
@@ -105,21 +110,32 @@ export class nxDiv extends HTMLElement
105
110
  }
106
111
 
107
112
  #init = () => {
108
-
109
- //console.log(this);
110
- //console.log(this.querySelectorAll("input[name], textarea[name], select[name]"));
111
-
112
- /**
113
- * css style 적용
114
- */
113
+ // 1. CSS Style 적용
115
114
  for (const attr of this.attributes) {
116
115
  if (attr.name.startsWith("css-")) {
117
- // "css-" 접두사를 제거하고 CSS 속성명으로 변환
118
116
  this.style.setProperty(attr.name.substring(4), attr.value);
119
117
  }
120
118
  }
121
119
 
120
+ // 2. 이미 초기화가 완료되었거나 내용이 옮겨졌는지 확인
121
+ if (this.shadowRoot && this.shadowRoot.innerHTML.trim() !== "") {
122
+ return; // 이미 내용이 있으면 중복 실행 방지
123
+ }
124
+
125
+ // 3. HTML 내용 처리
122
126
  this.originContents = this.innerHTML.trim();
123
- this.innerHTML = ""; // 기존 내부 HTML 제거
127
+
128
+ if (this.shadowRoot) {
129
+ // Shadow DOM 모드일 때
130
+ // 만약 자식 클래스에서 별도 템플릿을 그린다면 여기서는 비워두거나
131
+ // 기본 뼈대만 잡아야 합니다.
132
+ if (this.shadowRoot.innerHTML === "") {
133
+ this.shadowRoot.innerHTML = this.originContents;
134
+ }
135
+
136
+ // 중요: React가 다시 자식을 채우지 않도록 비우되,
137
+ // 하위 클래스에서 처리할 수 있도록 보존만 합니다.
138
+ this.innerHTML = "";
139
+ }
124
140
  };
125
141
  }