rails_modal_manager 1.0.15 → 1.0.17
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/README.md +16 -1
- data/app/assets/stylesheets/rails_modal_manager.css +27 -1
- data/app/javascript/rails_modal_manager/controllers/rmm_modal_controller.js +35 -0
- data/app/javascript/rails_modal_manager/controllers/rmm_sidebar_controller.js +31 -5
- data/app/javascript/rails_modal_manager/controllers/rmm_submenu_controller.js +29 -8
- data/app/views/rails_modal_manager/_header.html.erb +1 -1
- data/app/views/rails_modal_manager/_modal.html.erb +2 -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: ddf5144ec6b2d218fcd7dcce4525caeb858a563bf0c500598e2495fbacc9ac0d
|
|
4
|
+
data.tar.gz: 6e14143e1f18ea4f21df847705f4d660f69fccd1dc03df7d63512b9d4cc73b13
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 551384565588799321b3c4cd9431ec59ae66241b00ae80033972c808a393187f0ea6bcf297c13f04059c5b497706ff15969175a7b7bb7e725bbac5b411589c50
|
|
7
|
+
data.tar.gz: 58e4cbc16201e1524a439b54ca74a1311c3e67146ad6c0158d29bdbb5ba869b45cb89e8fae2c04fd7243ba91add145ec44e7977d7998be13f5182d0361e8cfdb
|
data/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Rails 애플리케이션을 위한 고급 모달 매니저입니다.
|
|
4
4
|
`@reshacs/react-modal-manager`에서 포팅되었습니다.
|
|
5
5
|
|
|
6
|
-
**Version:** 1.0.
|
|
6
|
+
**Version:** 1.0.17
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -789,6 +789,21 @@ MIT License
|
|
|
789
789
|
|
|
790
790
|
## 변경 이력
|
|
791
791
|
|
|
792
|
+
### v1.0.17
|
|
793
|
+
|
|
794
|
+
- **모바일 최대화 모달 사이드바 개선**: 최대화된 모달에서 사이드바가 접혔을 때 아이콘만 표시 (데스크톱과 동일한 UX)
|
|
795
|
+
- **모바일 기본크기 버튼 숨김**: 모바일에서 크기 컨트롤의 기본크기 버튼 숨김 처리
|
|
796
|
+
- **모바일 사이드바 리셋 개선**: 모달 닫힘 시 모바일에서 사이드바가 항상 접힌 상태로 리셋
|
|
797
|
+
- **mobile_default_maximized 옵션 수정**: ERB 템플릿에서 누락된 data 속성 추가
|
|
798
|
+
|
|
799
|
+
### v1.0.16
|
|
800
|
+
|
|
801
|
+
- **모달 상태 리셋 개선**: 모달 닫힘 시 사이드바와 서브메뉴가 첫 번째 항목으로 자동 리셋
|
|
802
|
+
|
|
803
|
+
### v1.0.13 ~ v1.0.15
|
|
804
|
+
|
|
805
|
+
- 내부 개선 및 버그 수정
|
|
806
|
+
|
|
792
807
|
### v1.0.12
|
|
793
808
|
|
|
794
809
|
- **최소화된 모달 자동 복원**: `openModal()` 호출 시 해당 모달이 이미 열려있고 최소화된 상태라면 자동으로 복원되도록 개선
|
|
@@ -696,6 +696,28 @@
|
|
|
696
696
|
opacity: 1;
|
|
697
697
|
visibility: visible;
|
|
698
698
|
}
|
|
699
|
+
|
|
700
|
+
/* When modal is maximized on mobile, show collapsed sidebar with icons only */
|
|
701
|
+
.rmm-modal.rmm-size-full .rmm-sidebar {
|
|
702
|
+
position: relative;
|
|
703
|
+
top: auto;
|
|
704
|
+
transform: none;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.rmm-modal.rmm-size-full .rmm-sidebar.rmm-sidebar-collapsed {
|
|
708
|
+
width: var(--rmm-sidebar-collapsed-width);
|
|
709
|
+
min-width: var(--rmm-sidebar-collapsed-width);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
.rmm-modal.rmm-size-full .rmm-sidebar:not(.rmm-sidebar-collapsed) {
|
|
713
|
+
width: var(--rmm-sidebar-width);
|
|
714
|
+
min-width: var(--rmm-sidebar-width);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/* Hide overlay for maximized modal since sidebar is inline */
|
|
718
|
+
.rmm-modal.rmm-size-full .rmm-sidebar-overlay {
|
|
719
|
+
display: none;
|
|
720
|
+
}
|
|
699
721
|
}
|
|
700
722
|
|
|
701
723
|
/* ============================================
|
|
@@ -1226,11 +1248,15 @@
|
|
|
1226
1248
|
height: 14px;
|
|
1227
1249
|
}
|
|
1228
1250
|
|
|
1229
|
-
/* Hide drag handle on mobile */
|
|
1251
|
+
/* Hide drag handle and default size button on mobile */
|
|
1230
1252
|
@media (max-width: 768px) {
|
|
1231
1253
|
.rmm-drag-handle {
|
|
1232
1254
|
display: none;
|
|
1233
1255
|
}
|
|
1256
|
+
|
|
1257
|
+
.rmm-default-size-btn {
|
|
1258
|
+
display: none;
|
|
1259
|
+
}
|
|
1234
1260
|
}
|
|
1235
1261
|
|
|
1236
1262
|
/* ============================================
|
|
@@ -345,6 +345,9 @@ export default class extends Controller {
|
|
|
345
345
|
const modal = this.element
|
|
346
346
|
const overlay = this.getOverlay()
|
|
347
347
|
|
|
348
|
+
// Reset sidebar and submenu to first item before hiding
|
|
349
|
+
this.resetSidebarAndSubmenu()
|
|
350
|
+
|
|
348
351
|
modal.classList.remove('rmm-active')
|
|
349
352
|
if (overlay) overlay.classList.remove('rmm-active')
|
|
350
353
|
|
|
@@ -359,6 +362,38 @@ export default class extends Controller {
|
|
|
359
362
|
}, this.animationDurationValue)
|
|
360
363
|
}
|
|
361
364
|
|
|
365
|
+
/**
|
|
366
|
+
* Reset sidebar and submenu controllers to first item
|
|
367
|
+
* Called when modal is closed to ensure clean state on next open
|
|
368
|
+
*/
|
|
369
|
+
resetSidebarAndSubmenu() {
|
|
370
|
+
const modal = this.element
|
|
371
|
+
|
|
372
|
+
// Reset sidebar controller
|
|
373
|
+
const sidebarElement = modal.querySelector('[data-controller*="rmm-sidebar"]')
|
|
374
|
+
if (sidebarElement) {
|
|
375
|
+
const sidebarController = this.application.getControllerForElementAndIdentifier(
|
|
376
|
+
sidebarElement,
|
|
377
|
+
'rmm-sidebar'
|
|
378
|
+
)
|
|
379
|
+
if (sidebarController && typeof sidebarController.resetToFirst === 'function') {
|
|
380
|
+
sidebarController.resetToFirst()
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Reset all submenu controllers
|
|
385
|
+
const submenuElements = modal.querySelectorAll('[data-controller*="rmm-submenu"]')
|
|
386
|
+
submenuElements.forEach(submenuElement => {
|
|
387
|
+
const submenuController = this.application.getControllerForElementAndIdentifier(
|
|
388
|
+
submenuElement,
|
|
389
|
+
'rmm-submenu'
|
|
390
|
+
)
|
|
391
|
+
if (submenuController && typeof submenuController.resetToFirst === 'function') {
|
|
392
|
+
submenuController.resetToFirst()
|
|
393
|
+
}
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
|
|
362
397
|
// ============================================
|
|
363
398
|
// Styles
|
|
364
399
|
// ============================================
|
|
@@ -40,14 +40,10 @@ export default class extends Controller {
|
|
|
40
40
|
this.element.classList.add('rmm-sidebar-collapsed')
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Find initial active item
|
|
43
|
+
// Find initial active item
|
|
44
44
|
const activeItem = this.element.querySelector('.rmm-sidebar-item.rmm-active')
|
|
45
45
|
if (activeItem) {
|
|
46
46
|
this.currentItemId = activeItem.dataset.itemId
|
|
47
|
-
// Restore panel and submenu state for the active item
|
|
48
|
-
// This ensures content is properly displayed when modal is reopened
|
|
49
|
-
this.switchPanel(activeItem)
|
|
50
|
-
this.switchSubmenuGroup(activeItem)
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
// Listen for toggle event from header button
|
|
@@ -205,4 +201,34 @@ export default class extends Controller {
|
|
|
205
201
|
this.collapsedValue = true
|
|
206
202
|
this.element.classList.add('rmm-sidebar-collapsed')
|
|
207
203
|
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Reset sidebar to first item
|
|
207
|
+
* Called by modal controller when modal is closed
|
|
208
|
+
*/
|
|
209
|
+
resetToFirst() {
|
|
210
|
+
const firstItem = this.element.querySelector('.rmm-sidebar-item')
|
|
211
|
+
if (!firstItem) return
|
|
212
|
+
|
|
213
|
+
// Remove active from all items
|
|
214
|
+
this.element.querySelectorAll('.rmm-sidebar-item').forEach(el => {
|
|
215
|
+
el.classList.remove('rmm-active')
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
// Add active to first item
|
|
219
|
+
firstItem.classList.add('rmm-active')
|
|
220
|
+
this.currentItemId = firstItem.dataset.itemId
|
|
221
|
+
|
|
222
|
+
// On mobile, ensure sidebar is collapsed
|
|
223
|
+
if (window.innerWidth < 768) {
|
|
224
|
+
this.collapsedValue = true
|
|
225
|
+
this.element.classList.add('rmm-sidebar-collapsed')
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Switch content panel
|
|
229
|
+
this.switchPanel(firstItem)
|
|
230
|
+
|
|
231
|
+
// Switch submenu group
|
|
232
|
+
this.switchSubmenuGroup(firstItem)
|
|
233
|
+
}
|
|
208
234
|
}
|
|
@@ -45,17 +45,10 @@ export default class extends Controller {
|
|
|
45
45
|
this.ajaxCache = new Map()
|
|
46
46
|
this.currentItemId = null
|
|
47
47
|
|
|
48
|
-
// Find initial active item
|
|
48
|
+
// Find initial active item
|
|
49
49
|
const activeItem = this.element.querySelector('.rmm-submenu-item.rmm-active')
|
|
50
50
|
if (activeItem) {
|
|
51
51
|
this.currentItemId = activeItem.dataset.itemId
|
|
52
|
-
// Restore panel state for the active item
|
|
53
|
-
// This ensures content is properly displayed when modal is reopened
|
|
54
|
-
if (this.loadModeValue === 'ajax') {
|
|
55
|
-
this.loadAjaxContent(activeItem)
|
|
56
|
-
} else {
|
|
57
|
-
this.switchPanel(activeItem)
|
|
58
|
-
}
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
@@ -235,4 +228,32 @@ export default class extends Controller {
|
|
|
235
228
|
}
|
|
236
229
|
}
|
|
237
230
|
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Reset submenu to first item
|
|
234
|
+
* Called by modal controller when modal is closed
|
|
235
|
+
*/
|
|
236
|
+
resetToFirst() {
|
|
237
|
+
const firstItem = this.element.querySelector('.rmm-submenu-item')
|
|
238
|
+
if (!firstItem) return
|
|
239
|
+
|
|
240
|
+
// Remove active from all items
|
|
241
|
+
this.element.querySelectorAll('.rmm-submenu-item').forEach(el => {
|
|
242
|
+
el.classList.remove('rmm-active')
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
// Add active to first item
|
|
246
|
+
firstItem.classList.add('rmm-active')
|
|
247
|
+
this.currentItemId = firstItem.dataset.itemId
|
|
248
|
+
|
|
249
|
+
// Switch panel
|
|
250
|
+
if (this.loadModeValue === 'ajax') {
|
|
251
|
+
this.loadAjaxContent(firstItem)
|
|
252
|
+
} else {
|
|
253
|
+
this.switchPanel(firstItem)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Clear AJAX cache
|
|
257
|
+
this.ajaxCache.clear()
|
|
258
|
+
}
|
|
238
259
|
}
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
<% if show_size_controls %>
|
|
94
94
|
<%# Default size button - restores to original size %>
|
|
95
95
|
<button type="button"
|
|
96
|
-
class="rmm-header-btn"
|
|
96
|
+
class="rmm-header-btn rmm-default-size-btn"
|
|
97
97
|
data-action="click->rmm-header#restoreDefaultSize"
|
|
98
98
|
title="기본 크기">
|
|
99
99
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
header_buttons ||= []
|
|
84
84
|
extra_class ||= ""
|
|
85
85
|
extra_data ||= {}
|
|
86
|
+
mobile_default_maximized ||= false
|
|
86
87
|
|
|
87
88
|
# Build CSS classes
|
|
88
89
|
modal_classes = ["rmm-modal", "rmm-size-#{size}", "rmm-position-#{position}"]
|
|
@@ -112,6 +113,7 @@
|
|
|
112
113
|
rmm_modal_min_height_value: min_height,
|
|
113
114
|
rmm_modal_height_value: height,
|
|
114
115
|
rmm_modal_animation_duration_value: animation_duration,
|
|
116
|
+
rmm_modal_mobile_default_maximized_value: mobile_default_maximized,
|
|
115
117
|
action: "click->rmm-modal#handleClick"
|
|
116
118
|
}
|
|
117
119
|
data_attrs[:rmm_modal_parent_modal_id_value] = parent_modal_id if parent_modal_id
|