rails_modal_manager 1.0.38 → 1.0.40
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.
- checksums.yaml +4 -4
- data/app/javascript/rails_modal_manager/controllers/rmm_modal_controller.js +46 -1
- data/app/javascript/rails_modal_manager/controllers/rmm_taskbar_controller.js +13 -3
- data/app/javascript/rails_modal_manager/modal_store.js +23 -0
- data/lib/rails_modal_manager/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0df266d9e80cbe4f6999522dfc7d42dd07614651f4e85fca57cd43bd59bd1f56
|
|
4
|
+
data.tar.gz: fd760622af26da416a71bf8928ae5247db821de551111f6b60d54c9f9462b01b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b121a1d40ea4d3f3f368e4f3cf69de017f2afa3fc999c3bc03377a376d0011912d970966e34d6d5310e42d5c65c2dc8aeeb1c5b398bfb7b53da14d5459d48a15
|
|
7
|
+
data.tar.gz: 169d8b9067a9ea55f0749324e1a349a634f0741a42c776b30e9410478dc20e6d0f1be3f50d2f0c30a048a4a00a45ee2cc9db92f10e1759de3817294e2b2e2fde
|
|
@@ -48,6 +48,8 @@ export default class extends Controller {
|
|
|
48
48
|
this.previousFocus = null
|
|
49
49
|
this.isDragging = false
|
|
50
50
|
this.isResizing = false
|
|
51
|
+
this.isClosing = false
|
|
52
|
+
this.closeTimeout = null
|
|
51
53
|
this.dragStart = { x: 0, y: 0 }
|
|
52
54
|
this.initialPos = { top: 0, left: 0 }
|
|
53
55
|
this.resizeDirection = null
|
|
@@ -107,6 +109,12 @@ export default class extends Controller {
|
|
|
107
109
|
open() {
|
|
108
110
|
const modalId = this.effectiveModalId
|
|
109
111
|
|
|
112
|
+
// 닫기 애니메이션 중이면 취소하고 다시 열기
|
|
113
|
+
if (this.isClosing) {
|
|
114
|
+
this.cancelClose()
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
110
118
|
if (modalStore.getModalConfig(modalId)) {
|
|
111
119
|
return // Already open
|
|
112
120
|
}
|
|
@@ -177,6 +185,12 @@ export default class extends Controller {
|
|
|
177
185
|
close(source = 'button') {
|
|
178
186
|
const modalId = this.effectiveModalId
|
|
179
187
|
|
|
188
|
+
// 이미 닫는 중이면 무시
|
|
189
|
+
if (this.isClosing) return
|
|
190
|
+
|
|
191
|
+
// store에 없으면 이미 닫힌 상태
|
|
192
|
+
if (!modalStore.getModalConfig(modalId)) return
|
|
193
|
+
|
|
180
194
|
// Allow closing from programmatic source, footer button, or if closable is true
|
|
181
195
|
if (!this.closableValue && source !== 'programmatic' && source !== 'footer') {
|
|
182
196
|
return
|
|
@@ -188,6 +202,9 @@ export default class extends Controller {
|
|
|
188
202
|
return
|
|
189
203
|
}
|
|
190
204
|
|
|
205
|
+
// 닫기 시작
|
|
206
|
+
this.isClosing = true
|
|
207
|
+
|
|
191
208
|
// Get all descendants to close them too
|
|
192
209
|
const descendants = modalStore.getAllDescendants(modalId)
|
|
193
210
|
|
|
@@ -402,7 +419,13 @@ export default class extends Controller {
|
|
|
402
419
|
modal.classList.remove('rmm-active')
|
|
403
420
|
if (overlay) overlay.classList.remove('rmm-active')
|
|
404
421
|
|
|
405
|
-
|
|
422
|
+
// 타이머 저장 (취소 가능하도록)
|
|
423
|
+
this.closeTimeout = setTimeout(() => {
|
|
424
|
+
this.closeTimeout = null
|
|
425
|
+
|
|
426
|
+
// 닫기가 취소되었으면 콜백 실행 안 함
|
|
427
|
+
if (!this.isClosing) return
|
|
428
|
+
|
|
406
429
|
// 애니메이션 완료 후 드래그로 인한 커스텀 위치 클래스 및 인라인 스타일 제거
|
|
407
430
|
modal.classList.remove('rmm-custom-position')
|
|
408
431
|
modal.classList.remove('rmm-dragging')
|
|
@@ -416,10 +439,32 @@ export default class extends Controller {
|
|
|
416
439
|
this.openValue = false
|
|
417
440
|
this._closingProgrammatically = false
|
|
418
441
|
|
|
442
|
+
// 닫기 완료
|
|
443
|
+
this.isClosing = false
|
|
444
|
+
|
|
419
445
|
if (callback) callback()
|
|
420
446
|
}, this.animationDurationValue)
|
|
421
447
|
}
|
|
422
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Cancel ongoing close animation and restore modal visibility
|
|
451
|
+
* Called when open() is triggered during close animation
|
|
452
|
+
*/
|
|
453
|
+
cancelClose() {
|
|
454
|
+
if (this.closeTimeout) {
|
|
455
|
+
clearTimeout(this.closeTimeout)
|
|
456
|
+
this.closeTimeout = null
|
|
457
|
+
}
|
|
458
|
+
this.isClosing = false
|
|
459
|
+
|
|
460
|
+
// UI 다시 활성화
|
|
461
|
+
const modal = this.element
|
|
462
|
+
const overlay = this.getOverlay()
|
|
463
|
+
|
|
464
|
+
modal.classList.add('rmm-active')
|
|
465
|
+
if (overlay) overlay.classList.add('rmm-active')
|
|
466
|
+
}
|
|
467
|
+
|
|
423
468
|
/**
|
|
424
469
|
* Reset sidebar and submenu controllers to first item
|
|
425
470
|
* Called when modal is closed to ensure clean state on next open
|
|
@@ -240,9 +240,19 @@ export default class extends Controller {
|
|
|
240
240
|
e.stopPropagation()
|
|
241
241
|
const modalId = e.currentTarget.dataset.modalId
|
|
242
242
|
if (modalId) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
// 해당 그룹이 복구된 상태인지 확인
|
|
244
|
+
const groups = modalStore.getMinimizedModalGroups()
|
|
245
|
+
const group = groups.find(g => g.rootModalId === modalId)
|
|
246
|
+
|
|
247
|
+
if (group && group.isRestored) {
|
|
248
|
+
// 복구된 상태: taskbar에서만 제거, 모달은 유지
|
|
249
|
+
modalStore.clearMinimizedStateGroup(modalId)
|
|
250
|
+
} else {
|
|
251
|
+
// 최소화 상태: 확인 후 모달 닫기
|
|
252
|
+
const confirmed = window.confirm('이 모달을 닫으시겠습니까?')
|
|
253
|
+
if (confirmed) {
|
|
254
|
+
modalStore.closeModalWithDescendants(modalId)
|
|
255
|
+
}
|
|
246
256
|
}
|
|
247
257
|
}
|
|
248
258
|
}
|
|
@@ -575,6 +575,29 @@ class ModalStore {
|
|
|
575
575
|
this.notify();
|
|
576
576
|
}
|
|
577
577
|
|
|
578
|
+
/**
|
|
579
|
+
* Clear minimized state for a modal group (remove from taskbar but keep modal open)
|
|
580
|
+
* Used when closing taskbar item for a restored (visible) modal
|
|
581
|
+
* @param {string} modalId - Any modal ID in the group
|
|
582
|
+
*/
|
|
583
|
+
clearMinimizedStateGroup(modalId) {
|
|
584
|
+
const rootId = this.getRootModal(modalId);
|
|
585
|
+
const descendants = this.getAllDescendants(rootId);
|
|
586
|
+
const allModalIds = [rootId, ...descendants];
|
|
587
|
+
|
|
588
|
+
// isMinimized와 isRestored 모두 false로 설정 (taskbar에서 제거, 모달은 유지)
|
|
589
|
+
allModalIds.forEach(id => {
|
|
590
|
+
if (this.activeModals[id]) {
|
|
591
|
+
this.activeModals[id].isMinimized = false;
|
|
592
|
+
this.activeModals[id].isRestored = false;
|
|
593
|
+
delete this.activeModals[id].minimizedAt;
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
this.updateBodyScroll();
|
|
598
|
+
this.notify();
|
|
599
|
+
}
|
|
600
|
+
|
|
578
601
|
getMinimizedModalGroups() {
|
|
579
602
|
const minimizedRoots = new Set();
|
|
580
603
|
const processedModals = new Set();
|