@nine-lab/nine-mu 0.1.307 → 0.1.309

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nine-lab/nine-mu",
3
- "version": "0.1.307",
3
+ "version": "0.1.309",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -804,8 +804,8 @@
804
804
  }
805
805
 
806
806
 
807
-
808
- :host(nine-diff-popup) {
807
+ :host(nine-diff-popup),
808
+ :host(nine-menu-diff-popup) {
809
809
 
810
810
  div.buttons {
811
811
  position: absolute;
@@ -862,6 +862,7 @@
862
862
  }
863
863
  }
864
864
 
865
+
865
866
  :host(nine-diff) {
866
867
  width: 100%;
867
868
  height: 100%;
@@ -166,6 +166,10 @@ export class NineDiff extends HTMLElement {
166
166
  #tobeEditorView;
167
167
  #asisEditorEl;
168
168
  #tobeEditorEl;
169
+ #isDirty = false;
170
+ #initialAsisSrc;
171
+ #initialTobeSrc;
172
+
169
173
 
170
174
  #languageCompartment = new Compartment();
171
175
 
@@ -181,6 +185,9 @@ export class NineDiff extends HTMLElement {
181
185
  return this.#tobeEditorView;
182
186
  }
183
187
 
188
+ get isDirty() {
189
+ return this.#isDirty;
190
+ }
184
191
 
185
192
  constructor() {
186
193
  super();
@@ -233,10 +240,19 @@ export class NineDiff extends HTMLElement {
233
240
  }
234
241
  }
235
242
 
243
+
236
244
  getContents = () => {
237
245
  return (this.#tobeEditorView) ? this.#tobeEditorView.state.doc.toString() : "";
238
246
  };
239
247
 
248
+ getAsisContents = () => {
249
+ return (this.#asisEditorView) ? this.#asisEditorView.state.doc.toString() : "";
250
+ };
251
+
252
+ getTobeContents = () => {
253
+ return (this.#tobeEditorView) ? this.#tobeEditorView.state.doc.toString() : "";
254
+ };
255
+
240
256
  #initCodeMirror = () => {
241
257
 
242
258
  let asisReady = false;
@@ -299,6 +315,10 @@ export class NineDiff extends HTMLElement {
299
315
  asisReady = true;
300
316
  checkAllReady(); // ASIS 준비 완료
301
317
  }
318
+
319
+ if (update.docChanged) {
320
+ this.#checkDirtyState();
321
+ }
302
322
  })
303
323
  ]
304
324
  }),
@@ -321,6 +341,10 @@ export class NineDiff extends HTMLElement {
321
341
  tobeReady = true;
322
342
  checkAllReady(); // ASIS 준비 완료
323
343
  }
344
+
345
+ if (update.docChanged) {
346
+ this.#checkDirtyState();
347
+ }
324
348
  })
325
349
  ]
326
350
  }),
@@ -330,6 +354,25 @@ export class NineDiff extends HTMLElement {
330
354
  this.#setupScrollSync();
331
355
  };
332
356
 
357
+ #checkDirtyState = () => {
358
+ const currentAsis = this.getAsisContents();
359
+ const currentTobe = this.getTobeContents();
360
+
361
+ // 원본 소스와 하나라도 다르면 dirty 상태로 판정
362
+ const nextDirty = (currentAsis !== this.#initialAsisSrc) || (currentTobe !== this.#initialTobeSrc);
363
+
364
+ // 상태가 바뀔 때만 이벤트를 디스패치해서 불필요한 이벤트 연발을 막음
365
+ if (this.#isDirty !== nextDirty) {
366
+ this.#isDirty = nextDirty;
367
+ this.dispatchEvent(new CustomEvent('change-dirty', {
368
+ detail: { isDirty: this.#isDirty },
369
+ bubbles: true,
370
+ composed: true
371
+ }));
372
+ trace.log(`[NineDiff] 상태 변경 - isDirty: ${this.#isDirty}`);
373
+ }
374
+ };
375
+
333
376
  #setupScrollSync = () => {
334
377
  if (this._asisScrollHandler) {
335
378
  this.#asisEditorView.scrollDOM.removeEventListener('scroll', this._asisScrollHandler);
@@ -497,6 +540,9 @@ export class NineDiff extends HTMLElement {
497
540
  //console.log(src1, src2, language);
498
541
 
499
542
  this.#isScrollSyncActive = false;
543
+ this.#isDirty = false;
544
+ this.#initialAsisSrc = src1 ?? "";
545
+ this.#initialTobeSrc = src2 ?? "";
500
546
 
501
547
  let langExtension;
502
548
  switch(language) {
@@ -48,8 +48,16 @@ export class NineMenuDiffPopup extends HTMLElement {
48
48
  this.#dialog = this.shadowRoot.querySelector('nine-dialog');
49
49
  this.#diffView = this.shadowRoot.querySelector('nine-diff');
50
50
 
51
- this.shadowRoot.querySelector('.btn-confirm').onclick = () => this.#handleConfirm();
51
+ const $btnConfirm = this.shadowRoot.querySelector('.btn-confirm');
52
+
53
+ $btnConfirm.onclick = () => this.#handleConfirm();
52
54
  this.shadowRoot.querySelector('.btn-cancel').onclick = () => this.#handleCancel();
55
+
56
+ this.#diffView.addEventListener('change-dirty', (e) => {
57
+ const { isDirty } = e.detail;
58
+ console.log(e);
59
+ $btnConfirm.disabled = !isDirty; // 수정되었을 때만 저장 버튼 활성화
60
+ });
53
61
  }
54
62
 
55
63
  popup() {
@@ -104,7 +112,7 @@ export class NineMenuDiffPopup extends HTMLElement {
104
112
 
105
113
  #handleConfirm() {
106
114
  // 에디터에서 직접 콘텐츠 추출
107
- const content = this.#diffView ? this.#diffView.getContents() : this.#asisBackup;
115
+ const content = this.#diffView ? this.#diffView.getAsisContents() : this.#asisBackup;
108
116
 
109
117
  const params = {
110
118
  packageName: this.#host.getAttribute('package-name'),