rails_modal_manager 1.0.40 → 1.0.41

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: 0df266d9e80cbe4f6999522dfc7d42dd07614651f4e85fca57cd43bd59bd1f56
4
- data.tar.gz: fd760622af26da416a71bf8928ae5247db821de551111f6b60d54c9f9462b01b
3
+ metadata.gz: 5884364bb07444f45c08e4733c5623883a775592ba853a1275f5f2bd84bb5c03
4
+ data.tar.gz: 06a78be76359c81f55ec9e904488a1f3d961fdababf4bb8b31c24d0d19a8b7e1
5
5
  SHA512:
6
- metadata.gz: b121a1d40ea4d3f3f368e4f3cf69de017f2afa3fc999c3bc03377a376d0011912d970966e34d6d5310e42d5c65c2dc8aeeb1c5b398bfb7b53da14d5459d48a15
7
- data.tar.gz: 169d8b9067a9ea55f0749324e1a349a634f0741a42c776b30e9410478dc20e6d0f1be3f50d2f0c30a048a4a00a45ee2cc9db92f10e1759de3817294e2b2e2fde
6
+ metadata.gz: 985fca2add00de7fca1c9c5d05d66be9b8a6dbc208526de6811dad2c4b27977be9aa332dce1287d561d0fe04c3ec365768abbeeac89f582f07af8250aed843e2
7
+ data.tar.gz: ab10ad1ad3a86cd5a6ad64af536d015cbfeccc030523e03c980c74cb042cab25bd70bd936cd7247980097a18140d2c0969f18c9afb6c6df8fc66301c959c4232
@@ -11,7 +11,7 @@ export default class extends Controller {
11
11
  defaultSize: { type: String, default: "md" },
12
12
  }
13
13
 
14
- static targets = ["maximizeBtn", "sidebarToggle"]
14
+ static targets = ["maximizeBtn", "sidebarToggle", "title"]
15
15
 
16
16
  connect() {
17
17
  // Listen for sidebar toggled event to update icon
@@ -20,6 +20,17 @@ export default class extends Controller {
20
20
  if (modal) {
21
21
  modal.addEventListener('rmm-sidebar:toggled', this.handleSidebarToggled)
22
22
  }
23
+
24
+ // Title 더블클릭 이벤트 리스너 추가
25
+ this.setupTitleEdit()
26
+ }
27
+
28
+ setupTitleEdit() {
29
+ const titleEl = this.element.querySelector('.rmm-header-title')
30
+ if (titleEl) {
31
+ titleEl.addEventListener('dblclick', (e) => this.editTitle(e))
32
+ titleEl.style.cursor = 'default'
33
+ }
23
34
  }
24
35
 
25
36
  disconnect() {
@@ -173,4 +184,92 @@ export default class extends Controller {
173
184
  if (hiddenIcon) hiddenIcon.style.display = 'none'
174
185
  }
175
186
  }
187
+
188
+ // ============================================
189
+ // Title Edit (Double-click to edit)
190
+ // ============================================
191
+
192
+ editTitle(e) {
193
+ e.stopPropagation()
194
+ e.preventDefault()
195
+
196
+ const titleEl = e.currentTarget
197
+ if (!titleEl) return
198
+
199
+ // 이미 수정 중인 경우 무시
200
+ if (titleEl.querySelector('input')) return
201
+
202
+ const currentTitle = titleEl.textContent.trim()
203
+
204
+ // input 생성
205
+ const input = document.createElement('input')
206
+ input.type = 'text'
207
+ input.value = currentTitle
208
+ input.className = 'rmm-header-title-input'
209
+ input.style.cssText = `
210
+ width: 100%;
211
+ min-width: 100px;
212
+ max-width: 300px;
213
+ padding: 2px 6px;
214
+ border: 1px solid rgba(255,255,255,0.5);
215
+ border-radius: 4px;
216
+ font-size: inherit;
217
+ font-weight: inherit;
218
+ font-family: inherit;
219
+ background: rgba(0,0,0,0.2);
220
+ color: inherit;
221
+ outline: none;
222
+ `
223
+
224
+ // title 내용을 input으로 교체
225
+ titleEl.textContent = ''
226
+ titleEl.appendChild(input)
227
+ input.focus()
228
+ input.select()
229
+
230
+ // 저장 함수
231
+ const saveTitle = () => {
232
+ const newTitle = input.value.trim()
233
+ const finalTitle = newTitle || currentTitle
234
+
235
+ // title 업데이트
236
+ titleEl.textContent = finalTitle
237
+
238
+ // modalStore의 title도 업데이트
239
+ if (newTitle && newTitle !== currentTitle) {
240
+ this.updateModalTitle(finalTitle)
241
+ }
242
+ }
243
+
244
+ // blur 시 저장
245
+ input.addEventListener('blur', saveTitle, { once: true })
246
+
247
+ // Enter 시 저장, Escape 시 취소
248
+ input.addEventListener('keydown', (ke) => {
249
+ if (ke.key === 'Enter') {
250
+ ke.preventDefault()
251
+ input.blur()
252
+ } else if (ke.key === 'Escape') {
253
+ ke.preventDefault()
254
+ input.removeEventListener('blur', saveTitle)
255
+ titleEl.textContent = currentTitle
256
+ }
257
+ })
258
+ }
259
+
260
+ updateModalTitle(newTitle) {
261
+ const modal = this.getModalElement()
262
+ if (!modal) return
263
+
264
+ const modalId = modal.id || this.modalIdValue
265
+ if (!modalId) return
266
+
267
+ // modalStore에서 title 업데이트
268
+ import("rails_modal_manager/modal_store").then(module => {
269
+ const modalStore = module.default
270
+ if (modalStore && modalStore.updateModal) {
271
+ modalStore.updateModal(modalId, { title: newTitle })
272
+ }
273
+ })
274
+ }
176
275
  }
@@ -69,9 +69,21 @@ export default class extends Controller {
69
69
  const closeAllBtn = groups.length >= 2 ? this.renderCloseAllButton() : ''
70
70
  const items = groups.map((group, index) => this.renderTaskbarItem(group, index)).join('')
71
71
  this.itemsTarget.innerHTML = closeAllBtn + items
72
+
73
+ // 복구된 상태의 아이템에 더블클릭 이벤트 직접 추가
74
+ this.attachTitleEditListeners()
72
75
  }
73
76
  }
74
77
 
78
+ attachTitleEditListeners() {
79
+ const disabledItems = this.element.querySelectorAll('.rmm-taskbar-item-disabled')
80
+ disabledItems.forEach(item => {
81
+ // 기존 리스너 제거를 위해 새 함수 참조 저장
82
+ item._dblclickHandler = (e) => this.editTitle(e, item)
83
+ item.addEventListener('dblclick', item._dblclickHandler)
84
+ })
85
+ }
86
+
75
87
  renderCloseAllButton() {
76
88
  return `
77
89
  <button type="button" class="rmm-taskbar-close-all" data-action="click->rmm-taskbar#closeAll" title="최소화된 모달 모두 닫기">
@@ -89,6 +101,7 @@ export default class extends Controller {
89
101
  const disabledClass = isRestored ? ' rmm-taskbar-item-disabled' : ''
90
102
 
91
103
  // 드래그 이벤트 + 클릭 이벤트 (복구된 상태가 아닐 때만 클릭 이벤트 추가)
104
+ // 복구된 상태에서는 더블클릭으로 title 수정 가능 (attachTitleEditListeners에서 처리)
92
105
  const dragEvents = 'dragstart->rmm-taskbar#dragStart dragend->rmm-taskbar#dragEnd dragover->rmm-taskbar#dragOver drop->rmm-taskbar#drop dragenter->rmm-taskbar#dragEnter dragleave->rmm-taskbar#dragLeave'
93
106
  const clickEvent = isRestored ? '' : ' click->rmm-taskbar#restoreItem'
94
107
  const dataAction = `data-action="${dragEvents}${clickEvent}"`
@@ -270,6 +283,79 @@ export default class extends Controller {
270
283
  }
271
284
  }
272
285
 
286
+ // ============================================
287
+ // Title Edit (Double-click on disabled/restored item)
288
+ // ============================================
289
+
290
+ editTitle(e, itemElement = null) {
291
+ e.stopPropagation()
292
+ e.preventDefault()
293
+
294
+ const item = itemElement || e.currentTarget
295
+ const titleSpan = item.querySelector('.rmm-taskbar-item-title')
296
+ const rootModalId = item.dataset.rootId
297
+
298
+ if (!titleSpan || !rootModalId) return
299
+
300
+ // 이미 수정 중인 경우 무시
301
+ if (titleSpan.querySelector('input')) return
302
+
303
+ const currentTitle = titleSpan.textContent
304
+ const originalWidth = titleSpan.offsetWidth
305
+
306
+ // input 생성
307
+ const input = document.createElement('input')
308
+ input.type = 'text'
309
+ input.value = currentTitle
310
+ input.className = 'rmm-taskbar-title-input'
311
+ input.style.cssText = `
312
+ width: ${Math.max(originalWidth, 80)}px;
313
+ min-width: 80px;
314
+ max-width: 200px;
315
+ padding: 2px 4px;
316
+ border: 1px solid #60a5fa;
317
+ border-radius: 3px;
318
+ font-size: inherit;
319
+ font-family: inherit;
320
+ background: #1e293b;
321
+ color: #f1f5f9;
322
+ outline: none;
323
+ `
324
+
325
+ // title 내용을 input으로 교체
326
+ titleSpan.textContent = ''
327
+ titleSpan.appendChild(input)
328
+ input.focus()
329
+ input.select()
330
+
331
+ // 저장 함수
332
+ const saveTitle = () => {
333
+ const newTitle = input.value.trim()
334
+ if (newTitle && newTitle !== currentTitle) {
335
+ // taskbar title만 업데이트 (모달 title은 유지)
336
+ modalStore.updateTaskbarTitle(rootModalId, newTitle)
337
+ }
338
+ // input을 text로 다시 변경
339
+ titleSpan.textContent = newTitle || currentTitle
340
+ }
341
+
342
+ // blur 시 저장
343
+ input.addEventListener('blur', saveTitle, { once: true })
344
+
345
+ // Enter 시 저장, Escape 시 취소
346
+ input.addEventListener('keydown', (ke) => {
347
+ if (ke.key === 'Enter') {
348
+ ke.preventDefault()
349
+ input.blur()
350
+ } else if (ke.key === 'Escape') {
351
+ ke.preventDefault()
352
+ // blur 이벤트 제거하고 원래 title로 복원
353
+ input.removeEventListener('blur', saveTitle)
354
+ titleSpan.textContent = currentTitle
355
+ }
356
+ })
357
+ }
358
+
273
359
  escapeHtml(text) {
274
360
  const div = document.createElement('div')
275
361
  div.textContent = text
@@ -141,6 +141,19 @@ class ModalStore {
141
141
  this.notify();
142
142
  }
143
143
 
144
+ /**
145
+ * Update taskbar-only title for a modal group
146
+ * This does NOT change the actual modal title, only the taskbar display
147
+ * @param {string} rootModalId - Root modal ID of the group
148
+ * @param {string} newTitle - New title to display in taskbar
149
+ */
150
+ updateTaskbarTitle(rootModalId, newTitle) {
151
+ if (!this.activeModals[rootModalId]) return;
152
+
153
+ this.activeModals[rootModalId].taskbarTitle = newTitle;
154
+ this.notify();
155
+ }
156
+
144
157
  bringToFront(modalId) {
145
158
  if (!this.activeModals[modalId]) return;
146
159
  if (this.modalOrder[this.modalOrder.length - 1] === modalId) return;
@@ -626,10 +639,13 @@ class ModalStore {
626
639
  const leafConfig = this.activeModals[leafModalId];
627
640
  const rootConfig = this.activeModals[rootId];
628
641
 
642
+ // taskbarTitle이 있으면 우선 사용 (모달 title과 별도로 관리)
643
+ const displayTitle = rootConfig?.taskbarTitle || leafConfig?.title || leafModalId;
644
+
629
645
  return {
630
646
  rootModalId: rootId,
631
647
  leafModalId,
632
- title: leafConfig?.title || leafModalId,
648
+ title: displayTitle,
633
649
  groupSize: allModalIds.length,
634
650
  zIndex: leafConfig?.zIndex || 0,
635
651
  modalIds: allModalIds,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsModalManager
4
- VERSION = "1.0.40"
4
+ VERSION = "1.0.41"
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.40
4
+ version: 1.0.41
5
5
  platform: ruby
6
6
  authors:
7
7
  - reshacs