rails_modal_manager 1.0.19 → 1.0.20
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/assets/stylesheets/rails_modal_manager.css +9 -0
- data/app/javascript/rails_modal_manager/controllers/rmm_header_controller.js +19 -4
- data/app/javascript/rails_modal_manager/controllers/rmm_sidebar_controller.js +139 -7
- data/app/views/rails_modal_manager/_header.html.erb +6 -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: b16a0669fa5fe91e312533c15dcfa6f148427d727f873d16edec295b2a15249a
|
|
4
|
+
data.tar.gz: 6c6d80d7b5093a893860660d14acc22273d3caa09b5b65f68edc03522f6831ac
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 504b04ee86bd7a93ef97e49107545a436e04f7a6774679022bed2db5ab235f938a89ab4e37c6062b738c8bdbada7552d7b9670836582ebec8841cc9009e0effb
|
|
7
|
+
data.tar.gz: a2f12d82a5996a8e949f0881b1e1c2769e430b4f7f6668488b649bcaaa30a0871c1424c442b9fb09ed125852dede6d8ca2db026c9c89c878749eefc86adf4667
|
|
@@ -718,6 +718,15 @@
|
|
|
718
718
|
.rmm-modal.rmm-size-full .rmm-sidebar-overlay {
|
|
719
719
|
display: none;
|
|
720
720
|
}
|
|
721
|
+
|
|
722
|
+
/* 모바일+최대화 상태에서 사이드바 완전 숨김 모드 */
|
|
723
|
+
.rmm-modal.rmm-size-full .rmm-sidebar.rmm-sidebar-hidden {
|
|
724
|
+
width: 0;
|
|
725
|
+
min-width: 0;
|
|
726
|
+
padding: 0;
|
|
727
|
+
overflow: hidden;
|
|
728
|
+
border-right: none;
|
|
729
|
+
}
|
|
721
730
|
}
|
|
722
731
|
|
|
723
732
|
/* ============================================
|
|
@@ -151,11 +151,26 @@ export default class extends Controller {
|
|
|
151
151
|
handleSidebarToggled(e) {
|
|
152
152
|
if (!this.hasSidebarToggleTarget) return
|
|
153
153
|
|
|
154
|
-
const
|
|
154
|
+
const { collapsed, sidebarMode, isMobileMaximized } = e.detail
|
|
155
|
+
|
|
155
156
|
const collapseIcon = this.sidebarToggleTarget.querySelector('.rmm-icon-collapse')
|
|
156
157
|
const expandIcon = this.sidebarToggleTarget.querySelector('.rmm-icon-expand')
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
const hiddenIcon = this.sidebarToggleTarget.querySelector('.rmm-icon-hidden')
|
|
159
|
+
|
|
160
|
+
// 모바일+최대화 상태에서는 3단계 아이콘
|
|
161
|
+
if (isMobileMaximized && sidebarMode) {
|
|
162
|
+
if (collapseIcon) collapseIcon.style.display = sidebarMode === 'expanded' ? 'block' : 'none'
|
|
163
|
+
if (expandIcon) expandIcon.style.display = sidebarMode === 'icons' ? 'block' : 'none'
|
|
164
|
+
if (hiddenIcon) hiddenIcon.style.display = sidebarMode === 'hidden' ? 'block' : 'none'
|
|
165
|
+
|
|
166
|
+
// 툴팁 업데이트
|
|
167
|
+
const titles = { expanded: '아이콘으로', icons: '숨기기', hidden: '펼치기' }
|
|
168
|
+
this.sidebarToggleTarget.title = titles[sidebarMode] || ''
|
|
169
|
+
} else {
|
|
170
|
+
// 일반 상태: 기존 2단계 아이콘
|
|
171
|
+
if (collapseIcon) collapseIcon.style.display = collapsed ? 'none' : 'block'
|
|
172
|
+
if (expandIcon) expandIcon.style.display = collapsed ? 'block' : 'none'
|
|
173
|
+
if (hiddenIcon) hiddenIcon.style.display = 'none'
|
|
174
|
+
}
|
|
160
175
|
}
|
|
161
176
|
}
|
|
@@ -26,6 +26,8 @@ export default class extends Controller {
|
|
|
26
26
|
static values = {
|
|
27
27
|
modalId: String,
|
|
28
28
|
collapsed: { type: Boolean, default: false },
|
|
29
|
+
// 모바일+최대화 상태에서의 사이드바 모드: 'expanded' | 'icons' | 'hidden'
|
|
30
|
+
sidebarMode: { type: String, default: 'icons' },
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
connect() {
|
|
@@ -34,6 +36,11 @@ export default class extends Controller {
|
|
|
34
36
|
// 모바일 사이즈(768px 미만)에서는 기본적으로 사이드바를 닫힌 상태로 시작
|
|
35
37
|
if (window.innerWidth < 768) {
|
|
36
38
|
this.collapsedValue = true
|
|
39
|
+
// 모바일+최대화 상태 체크하여 초기 모드 설정
|
|
40
|
+
if (this.isMobileMaximized()) {
|
|
41
|
+
this.sidebarModeValue = 'icons'
|
|
42
|
+
this.applySidebarMode()
|
|
43
|
+
}
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
if (this.collapsedValue) {
|
|
@@ -56,6 +63,13 @@ export default class extends Controller {
|
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
toggle() {
|
|
66
|
+
// 모바일+최대화 상태에서는 3단계 토글
|
|
67
|
+
if (this.isMobileMaximized()) {
|
|
68
|
+
this.toggleMobileMaximized()
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// 일반 상태: 기존 2단계 토글
|
|
59
73
|
this.collapsedValue = !this.collapsedValue
|
|
60
74
|
this.element.classList.toggle('rmm-sidebar-collapsed', this.collapsedValue)
|
|
61
75
|
|
|
@@ -64,6 +78,9 @@ export default class extends Controller {
|
|
|
64
78
|
sidebarOpen: !this.collapsedValue,
|
|
65
79
|
})
|
|
66
80
|
|
|
81
|
+
// 아이콘 업데이트
|
|
82
|
+
this.updateToggleIcon()
|
|
83
|
+
|
|
67
84
|
// Dispatch toggled event so toggle button can update its icon
|
|
68
85
|
const modal = this.element.closest('.rmm-modal')
|
|
69
86
|
if (modal) {
|
|
@@ -74,6 +91,103 @@ export default class extends Controller {
|
|
|
74
91
|
}
|
|
75
92
|
}
|
|
76
93
|
|
|
94
|
+
/**
|
|
95
|
+
* 모바일+최대화 상태 여부 체크
|
|
96
|
+
*/
|
|
97
|
+
isMobileMaximized() {
|
|
98
|
+
const modal = this.element.closest('.rmm-modal')
|
|
99
|
+
if (!modal) return false
|
|
100
|
+
|
|
101
|
+
const isMobile = window.innerWidth <= 768
|
|
102
|
+
const isMaximized = modal.classList.contains('rmm-size-full')
|
|
103
|
+
|
|
104
|
+
return isMobile && isMaximized
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 모바일+최대화 상태에서의 3단계 토글
|
|
109
|
+
* expanded (펼침) → icons (아이콘) → hidden (숨김) → expanded
|
|
110
|
+
*/
|
|
111
|
+
toggleMobileMaximized() {
|
|
112
|
+
const modes = ['expanded', 'icons', 'hidden']
|
|
113
|
+
const currentIndex = modes.indexOf(this.sidebarModeValue)
|
|
114
|
+
const nextIndex = (currentIndex + 1) % modes.length
|
|
115
|
+
this.sidebarModeValue = modes[nextIndex]
|
|
116
|
+
|
|
117
|
+
this.applySidebarMode()
|
|
118
|
+
|
|
119
|
+
// Update store
|
|
120
|
+
modalStore.updateModal(this.modalIdValue, {
|
|
121
|
+
sidebarOpen: this.sidebarModeValue === 'expanded',
|
|
122
|
+
sidebarMode: this.sidebarModeValue,
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
// Dispatch toggled event with mode info
|
|
126
|
+
const modal = this.element.closest('.rmm-modal')
|
|
127
|
+
if (modal) {
|
|
128
|
+
modal.dispatchEvent(new CustomEvent('rmm-sidebar:toggled', {
|
|
129
|
+
detail: {
|
|
130
|
+
collapsed: this.sidebarModeValue !== 'expanded',
|
|
131
|
+
sidebarMode: this.sidebarModeValue,
|
|
132
|
+
isMobileMaximized: true,
|
|
133
|
+
},
|
|
134
|
+
bubbles: false
|
|
135
|
+
}))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 사이드바 모드에 따른 CSS 클래스 적용
|
|
141
|
+
*/
|
|
142
|
+
applySidebarMode() {
|
|
143
|
+
// 모든 모드 클래스 제거
|
|
144
|
+
this.element.classList.remove('rmm-sidebar-collapsed', 'rmm-sidebar-hidden')
|
|
145
|
+
|
|
146
|
+
switch (this.sidebarModeValue) {
|
|
147
|
+
case 'expanded':
|
|
148
|
+
this.collapsedValue = false
|
|
149
|
+
break
|
|
150
|
+
case 'icons':
|
|
151
|
+
this.collapsedValue = true
|
|
152
|
+
this.element.classList.add('rmm-sidebar-collapsed')
|
|
153
|
+
break
|
|
154
|
+
case 'hidden':
|
|
155
|
+
this.collapsedValue = true
|
|
156
|
+
this.element.classList.add('rmm-sidebar-hidden')
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 헤더의 사이드바 토글 아이콘도 직접 업데이트
|
|
161
|
+
this.updateToggleIcon()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 헤더의 사이드바 토글 버튼 아이콘 업데이트
|
|
166
|
+
*/
|
|
167
|
+
updateToggleIcon() {
|
|
168
|
+
const modal = this.element.closest('.rmm-modal')
|
|
169
|
+
if (!modal) return
|
|
170
|
+
|
|
171
|
+
const toggleBtn = modal.querySelector('.rmm-sidebar-toggle')
|
|
172
|
+
if (!toggleBtn) return
|
|
173
|
+
|
|
174
|
+
const collapseIcon = toggleBtn.querySelector('.rmm-icon-collapse')
|
|
175
|
+
const expandIcon = toggleBtn.querySelector('.rmm-icon-expand')
|
|
176
|
+
const hiddenIcon = toggleBtn.querySelector('.rmm-icon-hidden')
|
|
177
|
+
|
|
178
|
+
if (this.isMobileMaximized()) {
|
|
179
|
+
// 모바일+최대화: 3단계 아이콘
|
|
180
|
+
if (collapseIcon) collapseIcon.style.display = this.sidebarModeValue === 'expanded' ? 'block' : 'none'
|
|
181
|
+
if (expandIcon) expandIcon.style.display = this.sidebarModeValue === 'icons' ? 'block' : 'none'
|
|
182
|
+
if (hiddenIcon) hiddenIcon.style.display = this.sidebarModeValue === 'hidden' ? 'block' : 'none'
|
|
183
|
+
} else {
|
|
184
|
+
// 일반: 2단계 아이콘
|
|
185
|
+
if (collapseIcon) collapseIcon.style.display = this.collapsedValue ? 'none' : 'block'
|
|
186
|
+
if (expandIcon) expandIcon.style.display = this.collapsedValue ? 'block' : 'none'
|
|
187
|
+
if (hiddenIcon) hiddenIcon.style.display = 'none'
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
77
191
|
selectItem(e) {
|
|
78
192
|
e.preventDefault()
|
|
79
193
|
e.stopPropagation()
|
|
@@ -103,8 +217,14 @@ export default class extends Controller {
|
|
|
103
217
|
|
|
104
218
|
// On mobile, close sidebar after selection
|
|
105
219
|
if (window.innerWidth < 768) {
|
|
106
|
-
|
|
107
|
-
this.
|
|
220
|
+
// 모바일+최대화 상태에서는 아이콘 상태로 전환
|
|
221
|
+
if (this.isMobileMaximized()) {
|
|
222
|
+
this.sidebarModeValue = 'icons'
|
|
223
|
+
this.applySidebarMode()
|
|
224
|
+
} else {
|
|
225
|
+
this.collapsedValue = true
|
|
226
|
+
this.element.classList.add('rmm-sidebar-collapsed')
|
|
227
|
+
}
|
|
108
228
|
}
|
|
109
229
|
|
|
110
230
|
// Dispatch event
|
|
@@ -198,8 +318,14 @@ export default class extends Controller {
|
|
|
198
318
|
|
|
199
319
|
// Mobile overlay click
|
|
200
320
|
closeOverlay() {
|
|
201
|
-
|
|
202
|
-
this.
|
|
321
|
+
// 모바일+최대화 상태에서는 아이콘 상태로 전환
|
|
322
|
+
if (this.isMobileMaximized()) {
|
|
323
|
+
this.sidebarModeValue = 'icons'
|
|
324
|
+
this.applySidebarMode()
|
|
325
|
+
} else {
|
|
326
|
+
this.collapsedValue = true
|
|
327
|
+
this.element.classList.add('rmm-sidebar-collapsed')
|
|
328
|
+
}
|
|
203
329
|
}
|
|
204
330
|
|
|
205
331
|
/**
|
|
@@ -219,10 +345,16 @@ export default class extends Controller {
|
|
|
219
345
|
firstItem.classList.add('rmm-active')
|
|
220
346
|
this.currentItemId = firstItem.dataset.itemId
|
|
221
347
|
|
|
222
|
-
// On mobile, ensure sidebar is collapsed
|
|
348
|
+
// On mobile, ensure sidebar is collapsed/icons mode
|
|
223
349
|
if (window.innerWidth < 768) {
|
|
224
|
-
|
|
225
|
-
this.
|
|
350
|
+
// 모바일+최대화 상태에서는 아이콘 상태로 초기화
|
|
351
|
+
if (this.isMobileMaximized()) {
|
|
352
|
+
this.sidebarModeValue = 'icons'
|
|
353
|
+
this.applySidebarMode()
|
|
354
|
+
} else {
|
|
355
|
+
this.collapsedValue = true
|
|
356
|
+
this.element.classList.add('rmm-sidebar-collapsed')
|
|
357
|
+
}
|
|
226
358
|
}
|
|
227
359
|
|
|
228
360
|
// Switch content panel
|
|
@@ -67,12 +67,18 @@
|
|
|
67
67
|
data-rmm-header-target="sidebarToggle"
|
|
68
68
|
data-action="click->rmm-header#toggleSidebar"
|
|
69
69
|
title="사이드바 토글">
|
|
70
|
+
<%# 펼침 상태 -> 아이콘으로 (좌측 화살표) %>
|
|
70
71
|
<svg class="rmm-icon-collapse" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
71
72
|
<polyline points="15 18 9 12 15 6"></polyline>
|
|
72
73
|
</svg>
|
|
74
|
+
<%# 아이콘 상태 -> 펼치기 (우측 화살표) %>
|
|
73
75
|
<svg class="rmm-icon-expand" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
|
74
76
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
75
77
|
</svg>
|
|
78
|
+
<%# 숨김 상태 -> 보이기 (- 아이콘) - 모바일+최대화에서만 사용 %>
|
|
79
|
+
<svg class="rmm-icon-hidden" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="display: none;">
|
|
80
|
+
<line x1="5" y1="12" x2="19" y2="12"></line>
|
|
81
|
+
</svg>
|
|
76
82
|
</button>
|
|
77
83
|
<% end %>
|
|
78
84
|
<h2 id="<%= modal_id %>-title" class="rmm-header-title"><%= title %></h2>
|