rails_modal_manager 1.0.35 → 1.0.37
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 +14 -1
- data/app/assets/stylesheets/rails_modal_manager.css +60 -56
- data/app/javascript/rails_modal_manager/controllers/rmm_modal_controller.js +45 -12
- data/app/views/rails_modal_manager/_modal.html.erb +3 -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: ed4634070e4b9c7e76f0f1e884c88ce98641828e3bc7e7bf59db8a402365029a
|
|
4
|
+
data.tar.gz: 4656c4b397fecedf19b386e104ac81173365ab59cc5266a32e0bf0a38f0505e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 82fa5ef91503bf5476c50e41f3479d25b896ced5af72ab064fbffe4ce7b1c5fe431bbfa17a7d67ad8eee077dae139be36f5d774785e0006975b2d38f17478852
|
|
7
|
+
data.tar.gz: e70cb55620dc62d709ea81ba20950b4b98626816a1792f96e9fece6faee8b0301c3b953ed68d39cc598edc94c3f3cfeba0fe8d788122de19f70829a92518298a
|
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.37
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -798,6 +798,19 @@ MIT License
|
|
|
798
798
|
|
|
799
799
|
## 변경 이력
|
|
800
800
|
|
|
801
|
+
### v1.0.37
|
|
802
|
+
|
|
803
|
+
- **커스텀 헤더 색상 옵션 추가**:
|
|
804
|
+
- `header_bg`: 헤더 배경색 (단색 또는 그라디언트)
|
|
805
|
+
- `header_text`: 타이틀, 버튼 아이콘, 드래그 핸들 색상
|
|
806
|
+
- `header_border`: 헤더 하단 보더 색상
|
|
807
|
+
- `header_close_btn_hover`: 닫기 버튼 hover 시 배경색
|
|
808
|
+
- **기본 Depth별 헤더 색상 변경** (라이트 모드):
|
|
809
|
+
- Depth 0 (부모): `#3b82f6` (파란색, 그라디언트 제거)
|
|
810
|
+
- Depth 1 (자식): `#0ea5e9` (하늘색)
|
|
811
|
+
- Depth 2 (손자): `#06b6d4` (청록색)
|
|
812
|
+
- Depth 3+ (증손자): `#64748B` (회색)
|
|
813
|
+
|
|
801
814
|
### v1.0.33
|
|
802
815
|
|
|
803
816
|
- **Taskbar 기능 대폭 개선**:
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
--rmm-header-height: 56px;
|
|
25
25
|
|
|
26
26
|
/* Header - Depth Colors (Parent/Child/Grandchild) */
|
|
27
|
-
--rmm-header-bg-depth-0:
|
|
27
|
+
--rmm-header-bg-depth-0: #3b82f6;
|
|
28
28
|
--rmm-header-text-depth-0: #ffffff;
|
|
29
|
-
--rmm-header-bg-depth-1:
|
|
29
|
+
--rmm-header-bg-depth-1: #0ea5e9;
|
|
30
30
|
--rmm-header-text-depth-1: #ffffff;
|
|
31
|
-
--rmm-header-bg-depth-2:
|
|
31
|
+
--rmm-header-bg-depth-2: #06b6d4;
|
|
32
32
|
--rmm-header-text-depth-2: #ffffff;
|
|
33
|
-
--rmm-header-bg-depth-3:
|
|
33
|
+
--rmm-header-bg-depth-3: #64748B;
|
|
34
34
|
--rmm-header-text-depth-3: #ffffff;
|
|
35
35
|
|
|
36
36
|
/* Footer */
|
|
@@ -639,6 +639,10 @@
|
|
|
639
639
|
background: var(--rmm-custom-header-btn-hover, rgba(255, 255, 255, 0.15));
|
|
640
640
|
}
|
|
641
641
|
|
|
642
|
+
.rmm-modal.rmm-custom-header .rmm-header-btn.rmm-close-btn:hover {
|
|
643
|
+
background: var(--rmm-custom-header-close-btn-hover, rgba(239, 68, 68, 0.9));
|
|
644
|
+
}
|
|
645
|
+
|
|
642
646
|
.rmm-modal.rmm-custom-header .rmm-drag-handle {
|
|
643
647
|
color: var(--rmm-custom-header-text, var(--rmm-header-text));
|
|
644
648
|
}
|
|
@@ -1561,58 +1565,6 @@
|
|
|
1561
1565
|
}
|
|
1562
1566
|
}
|
|
1563
1567
|
|
|
1564
|
-
/* MD, LG, XL 사이즈는 768px이 아닌 각자의 min-width 기준으로 모바일 스타일 적용
|
|
1565
|
-
- MD: 960px 이상에서는 데스크톱 스타일 유지
|
|
1566
|
-
- LG: 1152px 이상에서는 데스크톱 스타일 유지
|
|
1567
|
-
- XL: 1344px 이상에서는 데스크톱 스타일 유지
|
|
1568
|
-
*/
|
|
1569
|
-
@media (min-width: 769px) {
|
|
1570
|
-
/* MD: 769px ~ 960px 범위에서도 min-width 적용 */
|
|
1571
|
-
.rmm-modal.rmm-size-md {
|
|
1572
|
-
width: 50% !important;
|
|
1573
|
-
min-width: min(960px, calc(100vw - 40px)) !important;
|
|
1574
|
-
max-width: calc(100vw - 40px) !important;
|
|
1575
|
-
left: 50% !important;
|
|
1576
|
-
right: auto !important;
|
|
1577
|
-
}
|
|
1578
|
-
.rmm-modal.rmm-size-md.rmm-position-center {
|
|
1579
|
-
transform: translate(-50%, -50%) !important;
|
|
1580
|
-
}
|
|
1581
|
-
.rmm-modal.rmm-size-md.rmm-position-center.rmm-active {
|
|
1582
|
-
transform: translate(-50%, -50%) scale(1) !important;
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
/* LG: 769px ~ 1152px 범위에서도 min-width 적용 */
|
|
1586
|
-
.rmm-modal.rmm-size-lg {
|
|
1587
|
-
width: 60% !important;
|
|
1588
|
-
min-width: min(1152px, calc(100vw - 40px)) !important;
|
|
1589
|
-
max-width: calc(100vw - 40px) !important;
|
|
1590
|
-
left: 50% !important;
|
|
1591
|
-
right: auto !important;
|
|
1592
|
-
}
|
|
1593
|
-
.rmm-modal.rmm-size-lg.rmm-position-center {
|
|
1594
|
-
transform: translate(-50%, -50%) !important;
|
|
1595
|
-
}
|
|
1596
|
-
.rmm-modal.rmm-size-lg.rmm-position-center.rmm-active {
|
|
1597
|
-
transform: translate(-50%, -50%) scale(1) !important;
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
/* XL: 769px ~ 1344px 범위에서도 min-width 적용 */
|
|
1601
|
-
.rmm-modal.rmm-size-xl {
|
|
1602
|
-
width: 70% !important;
|
|
1603
|
-
min-width: min(1344px, calc(100vw - 40px)) !important;
|
|
1604
|
-
max-width: calc(100vw - 40px) !important;
|
|
1605
|
-
left: 50% !important;
|
|
1606
|
-
right: auto !important;
|
|
1607
|
-
}
|
|
1608
|
-
.rmm-modal.rmm-size-xl.rmm-position-center {
|
|
1609
|
-
transform: translate(-50%, -50%) !important;
|
|
1610
|
-
}
|
|
1611
|
-
.rmm-modal.rmm-size-xl.rmm-position-center.rmm-active {
|
|
1612
|
-
transform: translate(-50%, -50%) scale(1) !important;
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
1568
|
/* ============================================
|
|
1617
1569
|
Drag Handle
|
|
1618
1570
|
============================================ */
|
|
@@ -1732,3 +1684,55 @@
|
|
|
1732
1684
|
opacity: 0.5;
|
|
1733
1685
|
transition: opacity 0.2s ease;
|
|
1734
1686
|
}
|
|
1687
|
+
|
|
1688
|
+
/* ============================================
|
|
1689
|
+
PC Size Fixes (min-width: 769px)
|
|
1690
|
+
- 중간 크기 브라우저에서도 min-width 적용
|
|
1691
|
+
- :not(.rmm-dragging):not(.rmm-custom-position)으로 드래그 중/후 제외
|
|
1692
|
+
============================================ */
|
|
1693
|
+
@media (min-width: 769px) {
|
|
1694
|
+
/* MD: 769px ~ 960px 범위에서도 min-width 적용 */
|
|
1695
|
+
.rmm-modal.rmm-size-md:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1696
|
+
width: 50% !important;
|
|
1697
|
+
min-width: min(960px, calc(100vw - 40px)) !important;
|
|
1698
|
+
max-width: calc(100vw - 40px) !important;
|
|
1699
|
+
left: 50% !important;
|
|
1700
|
+
right: auto !important;
|
|
1701
|
+
}
|
|
1702
|
+
.rmm-modal.rmm-size-md.rmm-position-center:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1703
|
+
transform: translate(-50%, -50%) !important;
|
|
1704
|
+
}
|
|
1705
|
+
.rmm-modal.rmm-size-md.rmm-position-center.rmm-active:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1706
|
+
transform: translate(-50%, -50%) scale(1) !important;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/* LG: 769px ~ 1152px 범위에서도 min-width 적용 */
|
|
1710
|
+
.rmm-modal.rmm-size-lg:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1711
|
+
width: 60% !important;
|
|
1712
|
+
min-width: min(1152px, calc(100vw - 40px)) !important;
|
|
1713
|
+
max-width: calc(100vw - 40px) !important;
|
|
1714
|
+
left: 50% !important;
|
|
1715
|
+
right: auto !important;
|
|
1716
|
+
}
|
|
1717
|
+
.rmm-modal.rmm-size-lg.rmm-position-center:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1718
|
+
transform: translate(-50%, -50%) !important;
|
|
1719
|
+
}
|
|
1720
|
+
.rmm-modal.rmm-size-lg.rmm-position-center.rmm-active:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1721
|
+
transform: translate(-50%, -50%) scale(1) !important;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
/* XL: 769px ~ 1344px 범위에서도 min-width 적용 */
|
|
1725
|
+
.rmm-modal.rmm-size-xl:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1726
|
+
width: 70% !important;
|
|
1727
|
+
min-width: min(1344px, calc(100vw - 40px)) !important;
|
|
1728
|
+
max-width: calc(100vw - 40px) !important;
|
|
1729
|
+
left: 50% !important;
|
|
1730
|
+
right: auto !important;
|
|
1731
|
+
}
|
|
1732
|
+
.rmm-modal.rmm-size-xl.rmm-position-center:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1733
|
+
transform: translate(-50%, -50%) !important;
|
|
1734
|
+
}
|
|
1735
|
+
.rmm-modal.rmm-size-xl.rmm-position-center.rmm-active:not(.rmm-dragging):not(.rmm-custom-position) {
|
|
1736
|
+
transform: translate(-50%, -50%) scale(1) !important;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
@@ -41,6 +41,7 @@ export default class extends Controller {
|
|
|
41
41
|
headerBg: String, // Custom header background color (e.g., "#3b82f6" or "linear-gradient(135deg, #667eea, #764ba2)")
|
|
42
42
|
headerText: String, // Custom header text color (e.g., "#ffffff")
|
|
43
43
|
headerBorder: String, // Custom header border color (e.g., "#2563eb")
|
|
44
|
+
headerCloseBtnHover: String, // Custom close button hover background color (e.g., "rgba(239, 68, 68, 0.9)")
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
connect() {
|
|
@@ -365,7 +366,7 @@ export default class extends Controller {
|
|
|
365
366
|
modal.classList.remove('rmm-depth-0', 'rmm-depth-1', 'rmm-depth-2', 'rmm-depth-3')
|
|
366
367
|
|
|
367
368
|
// Check for custom header colors
|
|
368
|
-
const hasCustomHeader = this.hasHeaderBgValue || this.hasHeaderTextValue || this.hasHeaderBorderValue
|
|
369
|
+
const hasCustomHeader = this.hasHeaderBgValue || this.hasHeaderTextValue || this.hasHeaderBorderValue || this.hasHeaderCloseBtnHoverValue
|
|
369
370
|
|
|
370
371
|
if (hasCustomHeader) {
|
|
371
372
|
// Apply custom header colors via CSS variables
|
|
@@ -380,6 +381,9 @@ export default class extends Controller {
|
|
|
380
381
|
if (this.hasHeaderBorderValue && this.headerBorderValue) {
|
|
381
382
|
modal.style.setProperty('--rmm-custom-header-border', this.headerBorderValue)
|
|
382
383
|
}
|
|
384
|
+
if (this.hasHeaderCloseBtnHoverValue && this.headerCloseBtnHoverValue) {
|
|
385
|
+
modal.style.setProperty('--rmm-custom-header-close-btn-hover', this.headerCloseBtnHoverValue)
|
|
386
|
+
}
|
|
383
387
|
} else {
|
|
384
388
|
// Apply depth class (only if no custom header colors)
|
|
385
389
|
const depthClass = `rmm-depth-${Math.min(depth, 3)}`
|
|
@@ -394,10 +398,18 @@ export default class extends Controller {
|
|
|
394
398
|
// Reset sidebar and submenu to first item before hiding
|
|
395
399
|
this.resetSidebarAndSubmenu()
|
|
396
400
|
|
|
401
|
+
// 닫기 애니메이션 시작 (현재 위치에서 닫힘)
|
|
397
402
|
modal.classList.remove('rmm-active')
|
|
398
403
|
if (overlay) overlay.classList.remove('rmm-active')
|
|
399
404
|
|
|
400
405
|
setTimeout(() => {
|
|
406
|
+
// 애니메이션 완료 후 드래그로 인한 커스텀 위치 클래스 및 인라인 스타일 제거
|
|
407
|
+
modal.classList.remove('rmm-custom-position')
|
|
408
|
+
modal.classList.remove('rmm-dragging')
|
|
409
|
+
modal.style.top = ''
|
|
410
|
+
modal.style.left = ''
|
|
411
|
+
modal.style.transform = ''
|
|
412
|
+
|
|
401
413
|
// Reset openValue to false so modal can be reopened
|
|
402
414
|
// Use a flag to prevent openValueChanged from triggering close again
|
|
403
415
|
this._closingProgrammatically = true
|
|
@@ -464,17 +476,34 @@ export default class extends Controller {
|
|
|
464
476
|
|
|
465
477
|
// For full size, explicitly set full screen styles
|
|
466
478
|
if (config.size === 'full' || config.isMaximized) {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
modal.style.
|
|
477
|
-
modal.style.
|
|
479
|
+
// 최소화된 모달이 있는지 store에서 확인하여 taskbar 높이 계산
|
|
480
|
+
const minimizedGroups = modalStore.getMinimizedModalGroups()
|
|
481
|
+
const hasMinimizedModals = minimizedGroups.length > 0
|
|
482
|
+
// CSS 변수에서 taskbar 높이 가져오기 (기본값 48px)
|
|
483
|
+
const taskbarHeight = hasMinimizedModals
|
|
484
|
+
? parseInt(getComputedStyle(document.documentElement).getPropertyValue('--rmm-taskbar-height') || '48', 10)
|
|
485
|
+
: 0
|
|
486
|
+
|
|
487
|
+
// CSS !important를 덮어쓰기 위해 setProperty 사용
|
|
488
|
+
modal.style.setProperty('width', '100%', 'important')
|
|
489
|
+
modal.style.setProperty('min-width', '100%', 'important')
|
|
490
|
+
modal.style.setProperty('top', '0', 'important')
|
|
491
|
+
modal.style.setProperty('left', '0', 'important')
|
|
492
|
+
modal.style.setProperty('right', '0', 'important')
|
|
493
|
+
modal.style.setProperty('transform', 'none', 'important')
|
|
494
|
+
modal.style.setProperty('border-radius', '0', 'important')
|
|
495
|
+
modal.style.setProperty('margin', '0', 'important')
|
|
496
|
+
|
|
497
|
+
if (taskbarHeight > 0) {
|
|
498
|
+
// taskbar가 있으면 그 위까지만 표시
|
|
499
|
+
modal.style.setProperty('height', `calc(100% - ${taskbarHeight}px)`, 'important')
|
|
500
|
+
modal.style.setProperty('max-height', `calc(100% - ${taskbarHeight}px)`, 'important')
|
|
501
|
+
modal.style.setProperty('bottom', `${taskbarHeight}px`, 'important')
|
|
502
|
+
} else {
|
|
503
|
+
modal.style.setProperty('height', '100%', 'important')
|
|
504
|
+
modal.style.setProperty('max-height', '100%', 'important')
|
|
505
|
+
modal.style.setProperty('bottom', '0', 'important')
|
|
506
|
+
}
|
|
478
507
|
} else {
|
|
479
508
|
// Reset full-size specific styles
|
|
480
509
|
modal.style.borderRadius = ''
|
|
@@ -595,6 +624,7 @@ export default class extends Controller {
|
|
|
595
624
|
historyStackManager.moveToTop('modal', this.effectiveModalId)
|
|
596
625
|
}
|
|
597
626
|
this.isDragging = true
|
|
627
|
+
this.element.classList.add('rmm-dragging')
|
|
598
628
|
|
|
599
629
|
const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX
|
|
600
630
|
const clientY = e.type.includes('touch') ? e.touches[0].clientY : e.clientY
|
|
@@ -637,6 +667,9 @@ export default class extends Controller {
|
|
|
637
667
|
|
|
638
668
|
handleDragEnd() {
|
|
639
669
|
this.isDragging = false
|
|
670
|
+
this.element.classList.remove('rmm-dragging')
|
|
671
|
+
// 드래그 후 위치 유지를 위해 custom-position 클래스 추가
|
|
672
|
+
this.element.classList.add('rmm-custom-position')
|
|
640
673
|
|
|
641
674
|
this.element.style.transition = ''
|
|
642
675
|
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
header_bg: String - Custom header background (e.g., "#3b82f6" or "linear-gradient(135deg, #667eea, #764ba2)")
|
|
46
46
|
header_text: String - Custom header text color (e.g., "#ffffff")
|
|
47
47
|
header_border: String - Custom header border color (e.g., "#2563eb")
|
|
48
|
+
header_close_btn_hover: String - Custom close button hover background color (e.g., "rgba(239, 68, 68, 0.9)")
|
|
48
49
|
%>
|
|
49
50
|
<%
|
|
50
51
|
# Default values
|
|
@@ -92,6 +93,7 @@
|
|
|
92
93
|
header_bg ||= nil
|
|
93
94
|
header_text ||= nil
|
|
94
95
|
header_border ||= nil
|
|
96
|
+
header_close_btn_hover ||= nil
|
|
95
97
|
|
|
96
98
|
# Build CSS classes
|
|
97
99
|
modal_classes = ["rmm-modal", "rmm-size-#{size}", "rmm-position-#{position}"]
|
|
@@ -131,6 +133,7 @@
|
|
|
131
133
|
data_attrs[:rmm_modal_header_bg_value] = header_bg if header_bg
|
|
132
134
|
data_attrs[:rmm_modal_header_text_value] = header_text if header_text
|
|
133
135
|
data_attrs[:rmm_modal_header_border_value] = header_border if header_border
|
|
136
|
+
data_attrs[:rmm_modal_header_close_btn_hover_value] = header_close_btn_hover if header_close_btn_hover
|
|
134
137
|
data_attrs.merge!(extra_data)
|
|
135
138
|
%>
|
|
136
139
|
|