rails_modal_manager 1.0.12 → 1.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3731afb3a3d006cd6256e0e19780bb24e433153ca2f459807137ef52e0cfaf7
4
- data.tar.gz: 6acd94d81d76b5490185a8675b8ddacd3a2759fe5f039f765ed23e31f17d4020
3
+ metadata.gz: b5a9a0c23b9c295ce794dca604668be79268eab2b0ef9aa3a72bce9f31642d37
4
+ data.tar.gz: f341afe4a3bcf1661a80a60fbbd8ad2c34b187f6fe15d04df16c57f9273bafdc
5
5
  SHA512:
6
- metadata.gz: e81f5871bc33494bd283ac5adb41ca84571bfb9e3f9a23597e8a1b37ab1dfd62cd4033958030d2aaca80becc305593a68a0762d92d3d88c394d3ae80b693e22d
7
- data.tar.gz: d87f1982e1dd5cb3df4c50f3ceea6a9fe1605ea789711528a89e942de5533d25fbdb8673d55a2d4b2e06ebc3305d9aeed27f58307c285887135f20bb873dd1ea
6
+ metadata.gz: 4213097d0638e6e1656a3bab74608e7ab6adcc1aa521532fefbb0fc74e8d248d0e6a5a672f60f9d7a1b0a7a3dd345acdf6f5112ec74ea8a7a97fc3762cc8f913
7
+ data.tar.gz: 5c9bd6533b30f62eae37e28d6ae6532ed7942f74cb45d8d62db8dc6d31c35797322fb83db2e9c258599ef0b78c8ee16f565ae827bc2080a329019719c2a30e56
@@ -1109,6 +1109,7 @@
1109
1109
  white-space: nowrap;
1110
1110
  cursor: pointer;
1111
1111
  transition: background-color 0.15s;
1112
+ user-select: none;
1112
1113
  }
1113
1114
 
1114
1115
  .rmm-taskbar-item:hover {
@@ -147,6 +147,9 @@ export default class extends Controller {
147
147
  // Register close callback
148
148
  modalStore.registerCloseCallback(modalId, () => this.close('programmatic'))
149
149
 
150
+ // Move to persistent container (outside Turbo Frame) to survive navigation
151
+ this.moveToChildModalsContainer()
152
+
150
153
  // Add to history stack
151
154
  if (this.enableHistoryStackValue && !historyStackManager.hasHisData('modal', modalId)) {
152
155
  historyStackManager.addHisData('modal', modalId, () => this.close('history'))
@@ -499,6 +502,10 @@ export default class extends Controller {
499
502
  if (!config || config.isMaximized) return
500
503
 
501
504
  modalStore.bringToFront(this.effectiveModalId)
505
+ // 히스토리 스택 순서도 동기화
506
+ if (this.enableHistoryStackValue) {
507
+ historyStackManager.moveToTop('modal', this.effectiveModalId)
508
+ }
502
509
  this.isDragging = true
503
510
 
504
511
  const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX
@@ -562,6 +569,10 @@ export default class extends Controller {
562
569
  if (!config || config.isMaximized) return
563
570
 
564
571
  modalStore.bringToFront(this.effectiveModalId)
572
+ // 히스토리 스택 순서도 동기화
573
+ if (this.enableHistoryStackValue) {
574
+ historyStackManager.moveToTop('modal', this.effectiveModalId)
575
+ }
565
576
  this.isResizing = true
566
577
  this.resizeDirection = direction
567
578
 
@@ -682,9 +693,48 @@ export default class extends Controller {
682
693
  historyStackManager.removeMultipleHisData('modal', allModalIds)
683
694
  }
684
695
 
696
+ // Move modal DOM to persistent container (outside Turbo Frame)
697
+ // This ensures minimized modals survive Turbo Frame navigation
698
+ this.moveToChildModalsContainer()
699
+
685
700
  this.dispatch('minimize', { detail: { modalId: modalId } })
686
701
  }
687
702
 
703
+ /**
704
+ * Move modal (with wrapper if exists) to #child-modals-container
705
+ * This prevents DOM removal when Turbo Frame content is replaced
706
+ */
707
+ moveToChildModalsContainer() {
708
+ const container = document.getElementById('child-modals-container')
709
+ if (!container) return
710
+
711
+ const overlay = this.getOverlay()
712
+ const parent = this.element.parentElement
713
+
714
+ // Determine what to move: wrapper (if exists) or just modal
715
+ let elementToMove = this.element
716
+
717
+ // Check if parent is a wrapper (has data-controller and is not body/frame/container)
718
+ if (parent &&
719
+ parent.dataset.controller &&
720
+ parent.id !== 'child-modals-container' &&
721
+ parent.tagName !== 'TURBO-FRAME' &&
722
+ parent.tagName !== 'BODY') {
723
+ elementToMove = parent
724
+ }
725
+
726
+ // Skip if already in container
727
+ if (elementToMove.parentElement === container) return
728
+
729
+ // If overlay is outside the element to move, move it first
730
+ if (overlay && !elementToMove.contains(overlay) && overlay.parentElement !== container) {
731
+ container.appendChild(overlay)
732
+ }
733
+
734
+ // Move the element (modal or wrapper including overlay)
735
+ container.appendChild(elementToMove)
736
+ }
737
+
688
738
  maximize() {
689
739
  const modalId = this.effectiveModalId
690
740
  const config = modalStore.getModalConfig(modalId)
@@ -756,6 +806,10 @@ export default class extends Controller {
756
806
 
757
807
  handleClick() {
758
808
  modalStore.bringToFront(this.effectiveModalId)
809
+ // 히스토리 스택 순서도 동기화 (뒤로가기 시 현재 최상위 모달이 닫히도록)
810
+ if (this.enableHistoryStackValue) {
811
+ historyStackManager.moveToTop('modal', this.effectiveModalId)
812
+ }
759
813
  }
760
814
 
761
815
  // ============================================
@@ -777,7 +831,18 @@ export default class extends Controller {
777
831
  // ============================================
778
832
 
779
833
  getOverlay() {
780
- return document.getElementById(`${this.effectiveModalId}-overlay`)
834
+ const overlayId = `${this.effectiveModalId}-overlay`
835
+
836
+ // If this modal is inside child-modals-container, search there first
837
+ // This prevents finding duplicate overlays in turbo-frame
838
+ const container = document.getElementById('child-modals-container')
839
+ if (container && container.contains(this.element)) {
840
+ const overlayInContainer = container.querySelector(`#${overlayId}`)
841
+ if (overlayInContainer) return overlayInContainer
842
+ }
843
+
844
+ // Fallback to document-level search
845
+ return document.getElementById(overlayId)
781
846
  }
782
847
 
783
848
  hasAttribute(attr) {
@@ -31,6 +31,11 @@ export default class extends Controller {
31
31
  connect() {
32
32
  this.currentItemId = null
33
33
 
34
+ // 모바일 사이즈(768px 미만)에서는 기본적으로 사이드바를 닫힌 상태로 시작
35
+ if (window.innerWidth < 768) {
36
+ this.collapsedValue = true
37
+ }
38
+
34
39
  if (this.collapsedValue) {
35
40
  this.element.classList.add('rmm-sidebar-collapsed')
36
41
  }
@@ -285,6 +285,37 @@ function hasHisData(type, id) {
285
285
  return hisData.some((item) => item.type === type && item.id === id);
286
286
  }
287
287
 
288
+ /**
289
+ * Move specific item to the top of the history stack
290
+ * - Used when a modal is brought to front (clicked/focused)
291
+ * - Does not affect browser history, only reorders the internal stack
292
+ *
293
+ * @param {string} type - Target type
294
+ * @param {string} id - Target's unique ID
295
+ * @returns {boolean} Whether move was successful
296
+ */
297
+ function moveToTop(type, id) {
298
+ if (typeof window === 'undefined') return false;
299
+ if (!isEnabledForDevice(type)) return false;
300
+
301
+ const hisData = loadHisData();
302
+ const index = hisData.findIndex(
303
+ (item) => item.type === type && item.id === id
304
+ );
305
+
306
+ if (index === -1) return false;
307
+
308
+ // Already at top
309
+ if (index === hisData.length - 1) return true;
310
+
311
+ // Remove item from current position and add to end
312
+ const [item] = hisData.splice(index, 1);
313
+ hisData.push(item);
314
+ saveHisData(hisData);
315
+
316
+ return true;
317
+ }
318
+
288
319
  /**
289
320
  * Return current stack size
290
321
  * @returns {number} Stack size
@@ -362,6 +393,7 @@ const historyStackManager = {
362
393
  removeMultipleHisData,
363
394
  silentRemoveHisData,
364
395
  popHisData,
396
+ moveToTop,
365
397
 
366
398
  // Utilities
367
399
  hasHisData,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsModalManager
4
- VERSION = "1.0.12"
4
+ VERSION = "1.0.14"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_modal_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 1.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - reshacs