ninegrid2 6.874.0 → 6.876.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.
- package/dist/ai/aiMessage.js +67 -35
- package/dist/bundle.cjs.js +79 -35
- package/dist/bundle.esm.js +79 -35
- package/dist/nx/nxTab.js +12 -0
- package/package.json +1 -1
- package/src/ai/aiMessage.js +67 -35
- package/src/nx/nxTab.js +12 -0
package/dist/ai/aiMessage.js
CHANGED
|
@@ -231,9 +231,9 @@ class aiMyMessage extends HTMLElement
|
|
|
231
231
|
// aiProgressMessage 클래스 정의
|
|
232
232
|
// aiProgressMessage 클래스 정의 수정
|
|
233
233
|
class aiProgressMessage extends HTMLElement {
|
|
234
|
-
#progressData = [];
|
|
235
|
-
#progressElements = new Map();
|
|
236
|
-
#animationIntervals = new Map();
|
|
234
|
+
#progressData = [];
|
|
235
|
+
#progressElements = new Map();
|
|
236
|
+
#animationIntervals = new Map();
|
|
237
237
|
|
|
238
238
|
constructor() {
|
|
239
239
|
super();
|
|
@@ -257,14 +257,14 @@ class aiProgressMessage extends HTMLElement {
|
|
|
257
257
|
* @param {Array<Object>} data - [{id: 'step1', message: '분석중입니다.', completedMessage: '분석이 완료되었습니다.'}, ...]
|
|
258
258
|
*/
|
|
259
259
|
initialize(data) {
|
|
260
|
-
// 초기 상태는 'pending'으로 설정하고, 원본 메시지 저장 (애니메이션용)
|
|
261
260
|
this.#progressData = data.map(item => ({
|
|
262
261
|
...item,
|
|
263
262
|
status: 'pending',
|
|
264
|
-
originalMessage: item.message
|
|
263
|
+
originalMessage: item.message
|
|
265
264
|
}));
|
|
266
265
|
setTimeout(() => {
|
|
267
|
-
this.#renderProgress();
|
|
266
|
+
this.#renderProgress(); // 초기 렌더링 시 현재 진행 단계를 활성화
|
|
267
|
+
this.#updateCurrentActiveProgress(); // 초기 활성 단계 설정
|
|
268
268
|
}, 300);
|
|
269
269
|
}
|
|
270
270
|
|
|
@@ -276,50 +276,68 @@ class aiProgressMessage extends HTMLElement {
|
|
|
276
276
|
updateProgress(id, status) {
|
|
277
277
|
const itemIndex = this.#progressData.findIndex(item => item.id === id);
|
|
278
278
|
if (itemIndex > -1) {
|
|
279
|
-
// 기존 상태와 다를 경우에만 업데이트
|
|
280
279
|
if (this.#progressData[itemIndex].status !== status) {
|
|
281
280
|
this.#progressData[itemIndex].status = status;
|
|
282
|
-
this.#updateProgressItem(this.#progressData[itemIndex]);
|
|
281
|
+
this.#updateProgressItem(this.#progressData[itemIndex]); // 개별 항목 업데이트
|
|
282
|
+
this.#updateCurrentActiveProgress(); // 활성 진행 단계 재설정
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
// 현재 진행 중인 첫 번째 pending 항목을 찾아 'active' 상태로 만들고 애니메이션 시작
|
|
288
|
+
// 이전에 active였던 항목의 애니메이션은 중지
|
|
289
|
+
#updateCurrentActiveProgress() {
|
|
290
|
+
let foundActive = false;
|
|
291
|
+
this.#progressData.forEach(item => {
|
|
292
|
+
const li = this.#progressElements.get(item.id);
|
|
293
|
+
if (!li) return; // 요소가 아직 렌더링되지 않았으면 스킵
|
|
294
|
+
|
|
295
|
+
// 모든 항목에서 'active' 클래스 제거 및 애니메이션 중지
|
|
296
|
+
li.classList.remove('active');
|
|
297
|
+
if (this.#animationIntervals.has(item.id)) {
|
|
298
|
+
clearInterval(this.#animationIntervals.get(item.id));
|
|
299
|
+
this.#animationIntervals.delete(item.id);
|
|
300
|
+
li.querySelector(".animated-dots").textContent = ''; // 점 제거
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 첫 번째 pending 항목을 찾으면 'active'로 설정하고 애니메이션 시작
|
|
304
|
+
if (item.status === 'pending' && !foundActive) {
|
|
305
|
+
li.classList.add('active');
|
|
306
|
+
this.#startAnimation(item);
|
|
307
|
+
foundActive = true;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
287
312
|
#renderProgress() {
|
|
288
313
|
const progressList = this.shadowRoot.querySelector(".progress-list");
|
|
289
|
-
progressList.innerHTML = '';
|
|
290
|
-
this.#progressElements.clear();
|
|
291
|
-
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
314
|
+
progressList.innerHTML = '';
|
|
315
|
+
this.#progressElements.clear();
|
|
316
|
+
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
292
317
|
this.#animationIntervals.clear();
|
|
293
318
|
|
|
294
319
|
this.#progressData.forEach((item, index) => {
|
|
295
320
|
const li = document.createElement("li");
|
|
296
321
|
li.setAttribute("data-id", item.id);
|
|
297
322
|
li.classList.add("progress-item");
|
|
298
|
-
// 번호와 초기 메시지 설정
|
|
299
323
|
li.innerHTML = `
|
|
300
324
|
<span class="step-number">${index + 1}.</span>
|
|
301
|
-
<span class="text">${item.
|
|
325
|
+
<span class="text">${item.originalMessage}</span>
|
|
302
326
|
<span class="animated-dots"></span>
|
|
303
|
-
`;
|
|
327
|
+
`;
|
|
304
328
|
progressList.appendChild(li);
|
|
305
329
|
this.#progressElements.set(item.id, li);
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
this.#updateProgressItem(item);
|
|
330
|
+
// 초기 렌더링 시에는 'active' 상태는 `#updateCurrentActiveProgress`에서 처리
|
|
331
|
+
this.#updateProgressItemVisuals(item); // 텍스트만 업데이트
|
|
309
332
|
});
|
|
310
333
|
}
|
|
311
334
|
|
|
312
|
-
|
|
335
|
+
// 항목의 시각적 상태(텍스트, 완료 체크)만 업데이트
|
|
336
|
+
#updateProgressItemVisuals(item) {
|
|
313
337
|
const li = this.#progressElements.get(item.id);
|
|
314
338
|
if (li) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
clearInterval(this.#animationIntervals.get(item.id));
|
|
318
|
-
this.#animationIntervals.delete(item.id);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
li.classList.remove('pending', 'completed'); // 기존 클래스 제거
|
|
322
|
-
li.classList.add(item.status); // 새 상태 클래스 추가
|
|
339
|
+
li.classList.remove('pending', 'completed');
|
|
340
|
+
li.classList.add(item.status);
|
|
323
341
|
|
|
324
342
|
const textSpan = li.querySelector(".text");
|
|
325
343
|
const dotsSpan = li.querySelector(".animated-dots");
|
|
@@ -327,18 +345,32 @@ class aiProgressMessage extends HTMLElement {
|
|
|
327
345
|
if (item.status === 'completed') {
|
|
328
346
|
textSpan.textContent = item.completedMessage;
|
|
329
347
|
dotsSpan.textContent = ''; // 완료 시 점 제거
|
|
330
|
-
} else { // pending
|
|
331
|
-
textSpan.textContent = item.originalMessage;
|
|
332
|
-
|
|
333
|
-
// 애니메이션 시작
|
|
334
|
-
const intervalId = setInterval(() => {
|
|
335
|
-
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
336
|
-
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
337
|
-
}, 300); // 300ms마다 점 업데이트
|
|
338
|
-
this.#animationIntervals.set(item.id, intervalId);
|
|
348
|
+
} else { // pending 상태
|
|
349
|
+
textSpan.textContent = item.originalMessage;
|
|
350
|
+
// pending이지만 active가 아닌 경우 점 없음 (CSS의 role)
|
|
339
351
|
}
|
|
340
352
|
}
|
|
341
353
|
}
|
|
354
|
+
|
|
355
|
+
// 점 애니메이션 시작 함수
|
|
356
|
+
#startAnimation(item) {
|
|
357
|
+
const li = this.#progressElements.get(item.id);
|
|
358
|
+
if (li) {
|
|
359
|
+
const dotsSpan = li.querySelector(".animated-dots");
|
|
360
|
+
let dotsCount = 0;
|
|
361
|
+
const intervalId = setInterval(() => {
|
|
362
|
+
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
363
|
+
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
364
|
+
}, 300);
|
|
365
|
+
this.#animationIntervals.set(item.id, intervalId);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// 개별 항목의 상태 업데이트 (텍스트 변경, 클래스 추가/제거)
|
|
370
|
+
// 애니메이션 시작/중지는 `#updateCurrentActiveProgress`에서 담당
|
|
371
|
+
#updateProgressItem(item) {
|
|
372
|
+
this.#updateProgressItemVisuals(item); // 텍스트와 클래스 업데이트
|
|
373
|
+
}
|
|
342
374
|
}
|
|
343
375
|
|
|
344
376
|
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -121042,8 +121042,20 @@ class nxTab extends HTMLElement {
|
|
|
121042
121042
|
//this.shadowRoot.querySelector('.tab-pages').style.height = this.shadowRoot.querySelector('.tab-page').style.height;
|
|
121043
121043
|
|
|
121044
121044
|
this.switchTabHandler = this.#switchTab.bind(this);
|
|
121045
|
+
|
|
121046
|
+
|
|
121047
|
+
this.tappage = {
|
|
121048
|
+
hide: (v) => {
|
|
121049
|
+
this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
|
|
121050
|
+
if (el.innerText.trim() === v) {
|
|
121051
|
+
el.style.display = "none";
|
|
121052
|
+
}
|
|
121053
|
+
});
|
|
121054
|
+
}
|
|
121055
|
+
};
|
|
121045
121056
|
}
|
|
121046
121057
|
|
|
121058
|
+
|
|
121047
121059
|
connectedCallback() {
|
|
121048
121060
|
this.#init();
|
|
121049
121061
|
this.dispatchEvent(new CustomEvent(ninegrid.EVENT.TAB_LOAD, { bubbles: true, detail: {} }));
|
|
@@ -121868,9 +121880,9 @@ class aiMyMessage extends HTMLElement
|
|
|
121868
121880
|
// aiProgressMessage 클래스 정의
|
|
121869
121881
|
// aiProgressMessage 클래스 정의 수정
|
|
121870
121882
|
class aiProgressMessage extends HTMLElement {
|
|
121871
|
-
#progressData = [];
|
|
121872
|
-
#progressElements = new Map();
|
|
121873
|
-
#animationIntervals = new Map();
|
|
121883
|
+
#progressData = [];
|
|
121884
|
+
#progressElements = new Map();
|
|
121885
|
+
#animationIntervals = new Map();
|
|
121874
121886
|
|
|
121875
121887
|
constructor() {
|
|
121876
121888
|
super();
|
|
@@ -121894,14 +121906,14 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121894
121906
|
* @param {Array<Object>} data - [{id: 'step1', message: '분석중입니다.', completedMessage: '분석이 완료되었습니다.'}, ...]
|
|
121895
121907
|
*/
|
|
121896
121908
|
initialize(data) {
|
|
121897
|
-
// 초기 상태는 'pending'으로 설정하고, 원본 메시지 저장 (애니메이션용)
|
|
121898
121909
|
this.#progressData = data.map(item => ({
|
|
121899
121910
|
...item,
|
|
121900
121911
|
status: 'pending',
|
|
121901
|
-
originalMessage: item.message
|
|
121912
|
+
originalMessage: item.message
|
|
121902
121913
|
}));
|
|
121903
121914
|
setTimeout(() => {
|
|
121904
|
-
this.#renderProgress();
|
|
121915
|
+
this.#renderProgress(); // 초기 렌더링 시 현재 진행 단계를 활성화
|
|
121916
|
+
this.#updateCurrentActiveProgress(); // 초기 활성 단계 설정
|
|
121905
121917
|
}, 300);
|
|
121906
121918
|
}
|
|
121907
121919
|
|
|
@@ -121913,50 +121925,68 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121913
121925
|
updateProgress(id, status) {
|
|
121914
121926
|
const itemIndex = this.#progressData.findIndex(item => item.id === id);
|
|
121915
121927
|
if (itemIndex > -1) {
|
|
121916
|
-
// 기존 상태와 다를 경우에만 업데이트
|
|
121917
121928
|
if (this.#progressData[itemIndex].status !== status) {
|
|
121918
121929
|
this.#progressData[itemIndex].status = status;
|
|
121919
|
-
this.#updateProgressItem(this.#progressData[itemIndex]);
|
|
121930
|
+
this.#updateProgressItem(this.#progressData[itemIndex]); // 개별 항목 업데이트
|
|
121931
|
+
this.#updateCurrentActiveProgress(); // 활성 진행 단계 재설정
|
|
121920
121932
|
}
|
|
121921
121933
|
}
|
|
121922
121934
|
}
|
|
121923
121935
|
|
|
121936
|
+
// 현재 진행 중인 첫 번째 pending 항목을 찾아 'active' 상태로 만들고 애니메이션 시작
|
|
121937
|
+
// 이전에 active였던 항목의 애니메이션은 중지
|
|
121938
|
+
#updateCurrentActiveProgress() {
|
|
121939
|
+
let foundActive = false;
|
|
121940
|
+
this.#progressData.forEach(item => {
|
|
121941
|
+
const li = this.#progressElements.get(item.id);
|
|
121942
|
+
if (!li) return; // 요소가 아직 렌더링되지 않았으면 스킵
|
|
121943
|
+
|
|
121944
|
+
// 모든 항목에서 'active' 클래스 제거 및 애니메이션 중지
|
|
121945
|
+
li.classList.remove('active');
|
|
121946
|
+
if (this.#animationIntervals.has(item.id)) {
|
|
121947
|
+
clearInterval(this.#animationIntervals.get(item.id));
|
|
121948
|
+
this.#animationIntervals.delete(item.id);
|
|
121949
|
+
li.querySelector(".animated-dots").textContent = ''; // 점 제거
|
|
121950
|
+
}
|
|
121951
|
+
|
|
121952
|
+
// 첫 번째 pending 항목을 찾으면 'active'로 설정하고 애니메이션 시작
|
|
121953
|
+
if (item.status === 'pending' && !foundActive) {
|
|
121954
|
+
li.classList.add('active');
|
|
121955
|
+
this.#startAnimation(item);
|
|
121956
|
+
foundActive = true;
|
|
121957
|
+
}
|
|
121958
|
+
});
|
|
121959
|
+
}
|
|
121960
|
+
|
|
121924
121961
|
#renderProgress() {
|
|
121925
121962
|
const progressList = this.shadowRoot.querySelector(".progress-list");
|
|
121926
|
-
progressList.innerHTML = '';
|
|
121927
|
-
this.#progressElements.clear();
|
|
121928
|
-
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
121963
|
+
progressList.innerHTML = '';
|
|
121964
|
+
this.#progressElements.clear();
|
|
121965
|
+
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
121929
121966
|
this.#animationIntervals.clear();
|
|
121930
121967
|
|
|
121931
121968
|
this.#progressData.forEach((item, index) => {
|
|
121932
121969
|
const li = document.createElement("li");
|
|
121933
121970
|
li.setAttribute("data-id", item.id);
|
|
121934
121971
|
li.classList.add("progress-item");
|
|
121935
|
-
// 번호와 초기 메시지 설정
|
|
121936
121972
|
li.innerHTML = `
|
|
121937
121973
|
<span class="step-number">${index + 1}.</span>
|
|
121938
|
-
<span class="text">${item.
|
|
121974
|
+
<span class="text">${item.originalMessage}</span>
|
|
121939
121975
|
<span class="animated-dots"></span>
|
|
121940
|
-
`;
|
|
121976
|
+
`;
|
|
121941
121977
|
progressList.appendChild(li);
|
|
121942
121978
|
this.#progressElements.set(item.id, li);
|
|
121943
|
-
|
|
121944
|
-
//
|
|
121945
|
-
this.#updateProgressItem(item);
|
|
121979
|
+
// 초기 렌더링 시에는 'active' 상태는 `#updateCurrentActiveProgress`에서 처리
|
|
121980
|
+
this.#updateProgressItemVisuals(item); // 텍스트만 업데이트
|
|
121946
121981
|
});
|
|
121947
121982
|
}
|
|
121948
121983
|
|
|
121949
|
-
|
|
121984
|
+
// 항목의 시각적 상태(텍스트, 완료 체크)만 업데이트
|
|
121985
|
+
#updateProgressItemVisuals(item) {
|
|
121950
121986
|
const li = this.#progressElements.get(item.id);
|
|
121951
121987
|
if (li) {
|
|
121952
|
-
|
|
121953
|
-
|
|
121954
|
-
clearInterval(this.#animationIntervals.get(item.id));
|
|
121955
|
-
this.#animationIntervals.delete(item.id);
|
|
121956
|
-
}
|
|
121957
|
-
|
|
121958
|
-
li.classList.remove('pending', 'completed'); // 기존 클래스 제거
|
|
121959
|
-
li.classList.add(item.status); // 새 상태 클래스 추가
|
|
121988
|
+
li.classList.remove('pending', 'completed');
|
|
121989
|
+
li.classList.add(item.status);
|
|
121960
121990
|
|
|
121961
121991
|
const textSpan = li.querySelector(".text");
|
|
121962
121992
|
const dotsSpan = li.querySelector(".animated-dots");
|
|
@@ -121964,18 +121994,32 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121964
121994
|
if (item.status === 'completed') {
|
|
121965
121995
|
textSpan.textContent = item.completedMessage;
|
|
121966
121996
|
dotsSpan.textContent = ''; // 완료 시 점 제거
|
|
121967
|
-
} else { // pending
|
|
121968
|
-
textSpan.textContent = item.originalMessage;
|
|
121969
|
-
|
|
121970
|
-
// 애니메이션 시작
|
|
121971
|
-
const intervalId = setInterval(() => {
|
|
121972
|
-
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
121973
|
-
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
121974
|
-
}, 300); // 300ms마다 점 업데이트
|
|
121975
|
-
this.#animationIntervals.set(item.id, intervalId);
|
|
121997
|
+
} else { // pending 상태
|
|
121998
|
+
textSpan.textContent = item.originalMessage;
|
|
121999
|
+
// pending이지만 active가 아닌 경우 점 없음 (CSS의 role)
|
|
121976
122000
|
}
|
|
121977
122001
|
}
|
|
121978
122002
|
}
|
|
122003
|
+
|
|
122004
|
+
// 점 애니메이션 시작 함수
|
|
122005
|
+
#startAnimation(item) {
|
|
122006
|
+
const li = this.#progressElements.get(item.id);
|
|
122007
|
+
if (li) {
|
|
122008
|
+
const dotsSpan = li.querySelector(".animated-dots");
|
|
122009
|
+
let dotsCount = 0;
|
|
122010
|
+
const intervalId = setInterval(() => {
|
|
122011
|
+
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
122012
|
+
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
122013
|
+
}, 300);
|
|
122014
|
+
this.#animationIntervals.set(item.id, intervalId);
|
|
122015
|
+
}
|
|
122016
|
+
}
|
|
122017
|
+
|
|
122018
|
+
// 개별 항목의 상태 업데이트 (텍스트 변경, 클래스 추가/제거)
|
|
122019
|
+
// 애니메이션 시작/중지는 `#updateCurrentActiveProgress`에서 담당
|
|
122020
|
+
#updateProgressItem(item) {
|
|
122021
|
+
this.#updateProgressItemVisuals(item); // 텍스트와 클래스 업데이트
|
|
122022
|
+
}
|
|
121979
122023
|
}
|
|
121980
122024
|
|
|
121981
122025
|
|
package/dist/bundle.esm.js
CHANGED
|
@@ -121038,8 +121038,20 @@ class nxTab extends HTMLElement {
|
|
|
121038
121038
|
//this.shadowRoot.querySelector('.tab-pages').style.height = this.shadowRoot.querySelector('.tab-page').style.height;
|
|
121039
121039
|
|
|
121040
121040
|
this.switchTabHandler = this.#switchTab.bind(this);
|
|
121041
|
+
|
|
121042
|
+
|
|
121043
|
+
this.tappage = {
|
|
121044
|
+
hide: (v) => {
|
|
121045
|
+
this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
|
|
121046
|
+
if (el.innerText.trim() === v) {
|
|
121047
|
+
el.style.display = "none";
|
|
121048
|
+
}
|
|
121049
|
+
});
|
|
121050
|
+
}
|
|
121051
|
+
};
|
|
121041
121052
|
}
|
|
121042
121053
|
|
|
121054
|
+
|
|
121043
121055
|
connectedCallback() {
|
|
121044
121056
|
this.#init();
|
|
121045
121057
|
this.dispatchEvent(new CustomEvent(ninegrid.EVENT.TAB_LOAD, { bubbles: true, detail: {} }));
|
|
@@ -121864,9 +121876,9 @@ class aiMyMessage extends HTMLElement
|
|
|
121864
121876
|
// aiProgressMessage 클래스 정의
|
|
121865
121877
|
// aiProgressMessage 클래스 정의 수정
|
|
121866
121878
|
class aiProgressMessage extends HTMLElement {
|
|
121867
|
-
#progressData = [];
|
|
121868
|
-
#progressElements = new Map();
|
|
121869
|
-
#animationIntervals = new Map();
|
|
121879
|
+
#progressData = [];
|
|
121880
|
+
#progressElements = new Map();
|
|
121881
|
+
#animationIntervals = new Map();
|
|
121870
121882
|
|
|
121871
121883
|
constructor() {
|
|
121872
121884
|
super();
|
|
@@ -121890,14 +121902,14 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121890
121902
|
* @param {Array<Object>} data - [{id: 'step1', message: '분석중입니다.', completedMessage: '분석이 완료되었습니다.'}, ...]
|
|
121891
121903
|
*/
|
|
121892
121904
|
initialize(data) {
|
|
121893
|
-
// 초기 상태는 'pending'으로 설정하고, 원본 메시지 저장 (애니메이션용)
|
|
121894
121905
|
this.#progressData = data.map(item => ({
|
|
121895
121906
|
...item,
|
|
121896
121907
|
status: 'pending',
|
|
121897
|
-
originalMessage: item.message
|
|
121908
|
+
originalMessage: item.message
|
|
121898
121909
|
}));
|
|
121899
121910
|
setTimeout(() => {
|
|
121900
|
-
this.#renderProgress();
|
|
121911
|
+
this.#renderProgress(); // 초기 렌더링 시 현재 진행 단계를 활성화
|
|
121912
|
+
this.#updateCurrentActiveProgress(); // 초기 활성 단계 설정
|
|
121901
121913
|
}, 300);
|
|
121902
121914
|
}
|
|
121903
121915
|
|
|
@@ -121909,50 +121921,68 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121909
121921
|
updateProgress(id, status) {
|
|
121910
121922
|
const itemIndex = this.#progressData.findIndex(item => item.id === id);
|
|
121911
121923
|
if (itemIndex > -1) {
|
|
121912
|
-
// 기존 상태와 다를 경우에만 업데이트
|
|
121913
121924
|
if (this.#progressData[itemIndex].status !== status) {
|
|
121914
121925
|
this.#progressData[itemIndex].status = status;
|
|
121915
|
-
this.#updateProgressItem(this.#progressData[itemIndex]);
|
|
121926
|
+
this.#updateProgressItem(this.#progressData[itemIndex]); // 개별 항목 업데이트
|
|
121927
|
+
this.#updateCurrentActiveProgress(); // 활성 진행 단계 재설정
|
|
121916
121928
|
}
|
|
121917
121929
|
}
|
|
121918
121930
|
}
|
|
121919
121931
|
|
|
121932
|
+
// 현재 진행 중인 첫 번째 pending 항목을 찾아 'active' 상태로 만들고 애니메이션 시작
|
|
121933
|
+
// 이전에 active였던 항목의 애니메이션은 중지
|
|
121934
|
+
#updateCurrentActiveProgress() {
|
|
121935
|
+
let foundActive = false;
|
|
121936
|
+
this.#progressData.forEach(item => {
|
|
121937
|
+
const li = this.#progressElements.get(item.id);
|
|
121938
|
+
if (!li) return; // 요소가 아직 렌더링되지 않았으면 스킵
|
|
121939
|
+
|
|
121940
|
+
// 모든 항목에서 'active' 클래스 제거 및 애니메이션 중지
|
|
121941
|
+
li.classList.remove('active');
|
|
121942
|
+
if (this.#animationIntervals.has(item.id)) {
|
|
121943
|
+
clearInterval(this.#animationIntervals.get(item.id));
|
|
121944
|
+
this.#animationIntervals.delete(item.id);
|
|
121945
|
+
li.querySelector(".animated-dots").textContent = ''; // 점 제거
|
|
121946
|
+
}
|
|
121947
|
+
|
|
121948
|
+
// 첫 번째 pending 항목을 찾으면 'active'로 설정하고 애니메이션 시작
|
|
121949
|
+
if (item.status === 'pending' && !foundActive) {
|
|
121950
|
+
li.classList.add('active');
|
|
121951
|
+
this.#startAnimation(item);
|
|
121952
|
+
foundActive = true;
|
|
121953
|
+
}
|
|
121954
|
+
});
|
|
121955
|
+
}
|
|
121956
|
+
|
|
121920
121957
|
#renderProgress() {
|
|
121921
121958
|
const progressList = this.shadowRoot.querySelector(".progress-list");
|
|
121922
|
-
progressList.innerHTML = '';
|
|
121923
|
-
this.#progressElements.clear();
|
|
121924
|
-
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
121959
|
+
progressList.innerHTML = '';
|
|
121960
|
+
this.#progressElements.clear();
|
|
121961
|
+
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
121925
121962
|
this.#animationIntervals.clear();
|
|
121926
121963
|
|
|
121927
121964
|
this.#progressData.forEach((item, index) => {
|
|
121928
121965
|
const li = document.createElement("li");
|
|
121929
121966
|
li.setAttribute("data-id", item.id);
|
|
121930
121967
|
li.classList.add("progress-item");
|
|
121931
|
-
// 번호와 초기 메시지 설정
|
|
121932
121968
|
li.innerHTML = `
|
|
121933
121969
|
<span class="step-number">${index + 1}.</span>
|
|
121934
|
-
<span class="text">${item.
|
|
121970
|
+
<span class="text">${item.originalMessage}</span>
|
|
121935
121971
|
<span class="animated-dots"></span>
|
|
121936
|
-
`;
|
|
121972
|
+
`;
|
|
121937
121973
|
progressList.appendChild(li);
|
|
121938
121974
|
this.#progressElements.set(item.id, li);
|
|
121939
|
-
|
|
121940
|
-
//
|
|
121941
|
-
this.#updateProgressItem(item);
|
|
121975
|
+
// 초기 렌더링 시에는 'active' 상태는 `#updateCurrentActiveProgress`에서 처리
|
|
121976
|
+
this.#updateProgressItemVisuals(item); // 텍스트만 업데이트
|
|
121942
121977
|
});
|
|
121943
121978
|
}
|
|
121944
121979
|
|
|
121945
|
-
|
|
121980
|
+
// 항목의 시각적 상태(텍스트, 완료 체크)만 업데이트
|
|
121981
|
+
#updateProgressItemVisuals(item) {
|
|
121946
121982
|
const li = this.#progressElements.get(item.id);
|
|
121947
121983
|
if (li) {
|
|
121948
|
-
|
|
121949
|
-
|
|
121950
|
-
clearInterval(this.#animationIntervals.get(item.id));
|
|
121951
|
-
this.#animationIntervals.delete(item.id);
|
|
121952
|
-
}
|
|
121953
|
-
|
|
121954
|
-
li.classList.remove('pending', 'completed'); // 기존 클래스 제거
|
|
121955
|
-
li.classList.add(item.status); // 새 상태 클래스 추가
|
|
121984
|
+
li.classList.remove('pending', 'completed');
|
|
121985
|
+
li.classList.add(item.status);
|
|
121956
121986
|
|
|
121957
121987
|
const textSpan = li.querySelector(".text");
|
|
121958
121988
|
const dotsSpan = li.querySelector(".animated-dots");
|
|
@@ -121960,18 +121990,32 @@ class aiProgressMessage extends HTMLElement {
|
|
|
121960
121990
|
if (item.status === 'completed') {
|
|
121961
121991
|
textSpan.textContent = item.completedMessage;
|
|
121962
121992
|
dotsSpan.textContent = ''; // 완료 시 점 제거
|
|
121963
|
-
} else { // pending
|
|
121964
|
-
textSpan.textContent = item.originalMessage;
|
|
121965
|
-
|
|
121966
|
-
// 애니메이션 시작
|
|
121967
|
-
const intervalId = setInterval(() => {
|
|
121968
|
-
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
121969
|
-
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
121970
|
-
}, 300); // 300ms마다 점 업데이트
|
|
121971
|
-
this.#animationIntervals.set(item.id, intervalId);
|
|
121993
|
+
} else { // pending 상태
|
|
121994
|
+
textSpan.textContent = item.originalMessage;
|
|
121995
|
+
// pending이지만 active가 아닌 경우 점 없음 (CSS의 role)
|
|
121972
121996
|
}
|
|
121973
121997
|
}
|
|
121974
121998
|
}
|
|
121999
|
+
|
|
122000
|
+
// 점 애니메이션 시작 함수
|
|
122001
|
+
#startAnimation(item) {
|
|
122002
|
+
const li = this.#progressElements.get(item.id);
|
|
122003
|
+
if (li) {
|
|
122004
|
+
const dotsSpan = li.querySelector(".animated-dots");
|
|
122005
|
+
let dotsCount = 0;
|
|
122006
|
+
const intervalId = setInterval(() => {
|
|
122007
|
+
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
122008
|
+
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
122009
|
+
}, 300);
|
|
122010
|
+
this.#animationIntervals.set(item.id, intervalId);
|
|
122011
|
+
}
|
|
122012
|
+
}
|
|
122013
|
+
|
|
122014
|
+
// 개별 항목의 상태 업데이트 (텍스트 변경, 클래스 추가/제거)
|
|
122015
|
+
// 애니메이션 시작/중지는 `#updateCurrentActiveProgress`에서 담당
|
|
122016
|
+
#updateProgressItem(item) {
|
|
122017
|
+
this.#updateProgressItemVisuals(item); // 텍스트와 클래스 업데이트
|
|
122018
|
+
}
|
|
121975
122019
|
}
|
|
121976
122020
|
|
|
121977
122021
|
|
package/dist/nx/nxTab.js
CHANGED
|
@@ -19,8 +19,20 @@ class nxTab extends HTMLElement {
|
|
|
19
19
|
//this.shadowRoot.querySelector('.tab-pages').style.height = this.shadowRoot.querySelector('.tab-page').style.height;
|
|
20
20
|
|
|
21
21
|
this.switchTabHandler = this.#switchTab.bind(this);
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
this.tappage = {
|
|
25
|
+
hide: (v) => {
|
|
26
|
+
this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
|
|
27
|
+
if (el.innerText.trim() === v) {
|
|
28
|
+
el.style.display = "none";
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
}
|
|
22
33
|
}
|
|
23
34
|
|
|
35
|
+
|
|
24
36
|
connectedCallback() {
|
|
25
37
|
this.#init();
|
|
26
38
|
this.dispatchEvent(new CustomEvent(ninegrid.EVENT.TAB_LOAD, { bubbles: true, detail: {} }));
|
package/package.json
CHANGED
package/src/ai/aiMessage.js
CHANGED
|
@@ -231,9 +231,9 @@ class aiMyMessage extends HTMLElement
|
|
|
231
231
|
// aiProgressMessage 클래스 정의
|
|
232
232
|
// aiProgressMessage 클래스 정의 수정
|
|
233
233
|
class aiProgressMessage extends HTMLElement {
|
|
234
|
-
#progressData = [];
|
|
235
|
-
#progressElements = new Map();
|
|
236
|
-
#animationIntervals = new Map();
|
|
234
|
+
#progressData = [];
|
|
235
|
+
#progressElements = new Map();
|
|
236
|
+
#animationIntervals = new Map();
|
|
237
237
|
|
|
238
238
|
constructor() {
|
|
239
239
|
super();
|
|
@@ -257,14 +257,14 @@ class aiProgressMessage extends HTMLElement {
|
|
|
257
257
|
* @param {Array<Object>} data - [{id: 'step1', message: '분석중입니다.', completedMessage: '분석이 완료되었습니다.'}, ...]
|
|
258
258
|
*/
|
|
259
259
|
initialize(data) {
|
|
260
|
-
// 초기 상태는 'pending'으로 설정하고, 원본 메시지 저장 (애니메이션용)
|
|
261
260
|
this.#progressData = data.map(item => ({
|
|
262
261
|
...item,
|
|
263
262
|
status: 'pending',
|
|
264
|
-
originalMessage: item.message
|
|
263
|
+
originalMessage: item.message
|
|
265
264
|
}));
|
|
266
265
|
setTimeout(() => {
|
|
267
|
-
this.#renderProgress();
|
|
266
|
+
this.#renderProgress(); // 초기 렌더링 시 현재 진행 단계를 활성화
|
|
267
|
+
this.#updateCurrentActiveProgress(); // 초기 활성 단계 설정
|
|
268
268
|
}, 300);
|
|
269
269
|
}
|
|
270
270
|
|
|
@@ -276,50 +276,68 @@ class aiProgressMessage extends HTMLElement {
|
|
|
276
276
|
updateProgress(id, status) {
|
|
277
277
|
const itemIndex = this.#progressData.findIndex(item => item.id === id);
|
|
278
278
|
if (itemIndex > -1) {
|
|
279
|
-
// 기존 상태와 다를 경우에만 업데이트
|
|
280
279
|
if (this.#progressData[itemIndex].status !== status) {
|
|
281
280
|
this.#progressData[itemIndex].status = status;
|
|
282
|
-
this.#updateProgressItem(this.#progressData[itemIndex]);
|
|
281
|
+
this.#updateProgressItem(this.#progressData[itemIndex]); // 개별 항목 업데이트
|
|
282
|
+
this.#updateCurrentActiveProgress(); // 활성 진행 단계 재설정
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
286
|
|
|
287
|
+
// 현재 진행 중인 첫 번째 pending 항목을 찾아 'active' 상태로 만들고 애니메이션 시작
|
|
288
|
+
// 이전에 active였던 항목의 애니메이션은 중지
|
|
289
|
+
#updateCurrentActiveProgress() {
|
|
290
|
+
let foundActive = false;
|
|
291
|
+
this.#progressData.forEach(item => {
|
|
292
|
+
const li = this.#progressElements.get(item.id);
|
|
293
|
+
if (!li) return; // 요소가 아직 렌더링되지 않았으면 스킵
|
|
294
|
+
|
|
295
|
+
// 모든 항목에서 'active' 클래스 제거 및 애니메이션 중지
|
|
296
|
+
li.classList.remove('active');
|
|
297
|
+
if (this.#animationIntervals.has(item.id)) {
|
|
298
|
+
clearInterval(this.#animationIntervals.get(item.id));
|
|
299
|
+
this.#animationIntervals.delete(item.id);
|
|
300
|
+
li.querySelector(".animated-dots").textContent = ''; // 점 제거
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 첫 번째 pending 항목을 찾으면 'active'로 설정하고 애니메이션 시작
|
|
304
|
+
if (item.status === 'pending' && !foundActive) {
|
|
305
|
+
li.classList.add('active');
|
|
306
|
+
this.#startAnimation(item);
|
|
307
|
+
foundActive = true;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
287
312
|
#renderProgress() {
|
|
288
313
|
const progressList = this.shadowRoot.querySelector(".progress-list");
|
|
289
|
-
progressList.innerHTML = '';
|
|
290
|
-
this.#progressElements.clear();
|
|
291
|
-
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
314
|
+
progressList.innerHTML = '';
|
|
315
|
+
this.#progressElements.clear();
|
|
316
|
+
this.#animationIntervals.forEach(intervalId => clearInterval(intervalId));
|
|
292
317
|
this.#animationIntervals.clear();
|
|
293
318
|
|
|
294
319
|
this.#progressData.forEach((item, index) => {
|
|
295
320
|
const li = document.createElement("li");
|
|
296
321
|
li.setAttribute("data-id", item.id);
|
|
297
322
|
li.classList.add("progress-item");
|
|
298
|
-
// 번호와 초기 메시지 설정
|
|
299
323
|
li.innerHTML = `
|
|
300
324
|
<span class="step-number">${index + 1}.</span>
|
|
301
|
-
<span class="text">${item.
|
|
325
|
+
<span class="text">${item.originalMessage}</span>
|
|
302
326
|
<span class="animated-dots"></span>
|
|
303
|
-
`;
|
|
327
|
+
`;
|
|
304
328
|
progressList.appendChild(li);
|
|
305
329
|
this.#progressElements.set(item.id, li);
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
this.#updateProgressItem(item);
|
|
330
|
+
// 초기 렌더링 시에는 'active' 상태는 `#updateCurrentActiveProgress`에서 처리
|
|
331
|
+
this.#updateProgressItemVisuals(item); // 텍스트만 업데이트
|
|
309
332
|
});
|
|
310
333
|
}
|
|
311
334
|
|
|
312
|
-
|
|
335
|
+
// 항목의 시각적 상태(텍스트, 완료 체크)만 업데이트
|
|
336
|
+
#updateProgressItemVisuals(item) {
|
|
313
337
|
const li = this.#progressElements.get(item.id);
|
|
314
338
|
if (li) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
clearInterval(this.#animationIntervals.get(item.id));
|
|
318
|
-
this.#animationIntervals.delete(item.id);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
li.classList.remove('pending', 'completed'); // 기존 클래스 제거
|
|
322
|
-
li.classList.add(item.status); // 새 상태 클래스 추가
|
|
339
|
+
li.classList.remove('pending', 'completed');
|
|
340
|
+
li.classList.add(item.status);
|
|
323
341
|
|
|
324
342
|
const textSpan = li.querySelector(".text");
|
|
325
343
|
const dotsSpan = li.querySelector(".animated-dots");
|
|
@@ -327,18 +345,32 @@ class aiProgressMessage extends HTMLElement {
|
|
|
327
345
|
if (item.status === 'completed') {
|
|
328
346
|
textSpan.textContent = item.completedMessage;
|
|
329
347
|
dotsSpan.textContent = ''; // 완료 시 점 제거
|
|
330
|
-
} else { // pending
|
|
331
|
-
textSpan.textContent = item.originalMessage;
|
|
332
|
-
|
|
333
|
-
// 애니메이션 시작
|
|
334
|
-
const intervalId = setInterval(() => {
|
|
335
|
-
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
336
|
-
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
337
|
-
}, 300); // 300ms마다 점 업데이트
|
|
338
|
-
this.#animationIntervals.set(item.id, intervalId);
|
|
348
|
+
} else { // pending 상태
|
|
349
|
+
textSpan.textContent = item.originalMessage;
|
|
350
|
+
// pending이지만 active가 아닌 경우 점 없음 (CSS의 role)
|
|
339
351
|
}
|
|
340
352
|
}
|
|
341
353
|
}
|
|
354
|
+
|
|
355
|
+
// 점 애니메이션 시작 함수
|
|
356
|
+
#startAnimation(item) {
|
|
357
|
+
const li = this.#progressElements.get(item.id);
|
|
358
|
+
if (li) {
|
|
359
|
+
const dotsSpan = li.querySelector(".animated-dots");
|
|
360
|
+
let dotsCount = 0;
|
|
361
|
+
const intervalId = setInterval(() => {
|
|
362
|
+
dotsCount = (dotsCount + 1) % 4; // 0, 1, 2, 3 반복
|
|
363
|
+
dotsSpan.textContent = '.'.repeat(dotsCount);
|
|
364
|
+
}, 300);
|
|
365
|
+
this.#animationIntervals.set(item.id, intervalId);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// 개별 항목의 상태 업데이트 (텍스트 변경, 클래스 추가/제거)
|
|
370
|
+
// 애니메이션 시작/중지는 `#updateCurrentActiveProgress`에서 담당
|
|
371
|
+
#updateProgressItem(item) {
|
|
372
|
+
this.#updateProgressItemVisuals(item); // 텍스트와 클래스 업데이트
|
|
373
|
+
}
|
|
342
374
|
}
|
|
343
375
|
|
|
344
376
|
|
package/src/nx/nxTab.js
CHANGED
|
@@ -19,8 +19,20 @@ class nxTab extends HTMLElement {
|
|
|
19
19
|
//this.shadowRoot.querySelector('.tab-pages').style.height = this.shadowRoot.querySelector('.tab-page').style.height;
|
|
20
20
|
|
|
21
21
|
this.switchTabHandler = this.#switchTab.bind(this);
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
this.tappage = {
|
|
25
|
+
hide: (v) => {
|
|
26
|
+
this.shadowRoot.querySelectorAll(".tab-button").forEach((el, i) => {
|
|
27
|
+
if (el.innerText.trim() === v) {
|
|
28
|
+
el.style.display = "none";
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
}
|
|
22
33
|
}
|
|
23
34
|
|
|
35
|
+
|
|
24
36
|
connectedCallback() {
|
|
25
37
|
this.#init();
|
|
26
38
|
this.dispatchEvent(new CustomEvent(ninegrid.EVENT.TAB_LOAD, { bubbles: true, detail: {} }));
|