phlex_kit 0.11.0 → 0.13.0
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/components/phlex_kit/alert_dialog/alert_dialog.css +3 -1
- data/app/components/phlex_kit/alert_dialog/alert_dialog_content.rb +13 -2
- data/app/components/phlex_kit/alert_dialog/alert_dialog_controller.js +35 -7
- data/app/components/phlex_kit/attachment/attachment.css +15 -0
- data/app/components/phlex_kit/attachment/attachment_trigger.rb +3 -0
- data/app/components/phlex_kit/breadcrumb/breadcrumb.css +1 -0
- data/app/components/phlex_kit/calendar/calendar_controller.js +37 -9
- data/app/components/phlex_kit/carousel/carousel_controller.js +36 -2
- data/app/components/phlex_kit/chart/chart.rb +6 -4
- data/app/components/phlex_kit/chart/chart_controller.js +37 -8
- data/app/components/phlex_kit/checkbox/checkbox.rb +15 -1
- data/app/components/phlex_kit/codeblock/codeblock.rb +5 -1
- data/app/components/phlex_kit/combobox/combobox.css +1 -1
- data/app/components/phlex_kit/combobox/combobox_controller.js +61 -2
- data/app/components/phlex_kit/command/command_controller.js +77 -2
- data/app/components/phlex_kit/command/command_dialog_content.rb +5 -0
- data/app/components/phlex_kit/command/command_input.rb +3 -2
- data/app/components/phlex_kit/context_menu/context_menu.css +3 -0
- data/app/components/phlex_kit/context_menu/context_menu.rb +9 -1
- data/app/components/phlex_kit/context_menu/context_menu_controller.js +75 -12
- data/app/components/phlex_kit/data_table/data_table.css +1 -1
- data/app/components/phlex_kit/data_table/data_table_controller.js +7 -1
- data/app/components/phlex_kit/data_table/data_table_pagination.rb +4 -1
- data/app/components/phlex_kit/data_table/data_table_per_page_select.rb +8 -3
- data/app/components/phlex_kit/data_table/data_table_search.rb +7 -2
- data/app/components/phlex_kit/data_table/data_table_selection_summary.rb +12 -3
- data/app/components/phlex_kit/date_picker/date_picker.rb +13 -2
- data/app/components/phlex_kit/date_picker/date_picker_controller.js +26 -0
- data/app/components/phlex_kit/dialog/dialog_controller.js +3 -0
- data/app/components/phlex_kit/drawer/drawer.rb +1 -1
- data/app/components/phlex_kit/drawer/drawer_content.rb +10 -3
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu.css +4 -0
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu.rb +5 -1
- data/app/components/phlex_kit/dropdown_menu/dropdown_menu_controller.js +78 -18
- data/app/components/phlex_kit/form_field/form_field_controller.js +32 -24
- data/app/components/phlex_kit/hover_card/hover_card.css +6 -0
- data/app/components/phlex_kit/hover_card/hover_card_controller.js +24 -0
- data/app/components/phlex_kit/icon/icon.rb +1 -1
- data/app/components/phlex_kit/input/input.css +0 -1
- data/app/components/phlex_kit/input_otp/input_otp.rb +6 -3
- data/app/components/phlex_kit/input_otp/input_otp_controller.js +24 -2
- data/app/components/phlex_kit/item/item.css +2 -1
- data/app/components/phlex_kit/kbd/kbd.css +2 -1
- data/app/components/phlex_kit/label/label.css +1 -1
- data/app/components/phlex_kit/link/link.rb +11 -1
- data/app/components/phlex_kit/marker/marker.css +2 -1
- data/app/components/phlex_kit/menubar/menubar.css +3 -0
- data/app/components/phlex_kit/menubar/menubar.rb +3 -1
- data/app/components/phlex_kit/menubar/menubar_controller.js +66 -16
- data/app/components/phlex_kit/native_select/native_select.css +14 -0
- data/app/components/phlex_kit/navigation_menu/navigation_menu_link.rb +8 -1
- data/app/components/phlex_kit/popover/popover_controller.js +19 -0
- data/app/components/phlex_kit/progress/progress.css +19 -0
- data/app/components/phlex_kit/progress/progress.rb +29 -13
- data/app/components/phlex_kit/scroll_area/scroll_area.rb +2 -15
- data/app/components/phlex_kit/select/select_controller.js +22 -0
- data/app/components/phlex_kit/select/select_trigger.rb +4 -1
- data/app/components/phlex_kit/sheet/sheet_content.rb +13 -3
- data/app/components/phlex_kit/sheet/sheet_content_controller.js +36 -0
- data/app/components/phlex_kit/sheet/sheet_controller.js +17 -2
- data/app/components/phlex_kit/spinner/spinner.rb +6 -3
- data/app/components/phlex_kit/switch/switch.rb +6 -0
- data/app/components/phlex_kit/tabs/tabs_controller.js +8 -2
- data/app/components/phlex_kit/toast/toast_action.rb +1 -1
- data/app/components/phlex_kit/toast/toast_close.rb +6 -3
- data/app/components/phlex_kit/toast/toast_controller.js +37 -16
- data/app/components/phlex_kit/toast/toast_item.rb +11 -7
- data/app/components/phlex_kit/toast/toast_region.rb +12 -3
- data/app/components/phlex_kit/toast/toaster_controller.js +35 -5
- data/app/components/phlex_kit/toggle_group/toggle_group.rb +16 -1
- data/app/components/phlex_kit/toggle_group/toggle_group_controller.js +11 -8
- data/app/components/phlex_kit/toggle_group/toggle_group_item.rb +15 -5
- data/app/javascript/phlex_kit/controllers/index.js +2 -0
- data/lib/phlex_kit/base_component.rb +22 -3
- data/lib/phlex_kit/version.rb +1 -1
- data/lib/phlex_kit.rb +1 -0
- metadata +2 -1
|
@@ -63,12 +63,26 @@ export default class extends Controller {
|
|
|
63
63
|
// _setExpanded's state change left auto-dismiss running under the cursor.
|
|
64
64
|
this._onPointerEnter = () => { this._setPaused(true); this._setExpanded(true) }
|
|
65
65
|
this._onPointerLeave = () => { this._setPaused(false); if (!this.expandValue) this._setExpanded(false) }
|
|
66
|
-
this._onWindowToast = (e) =>
|
|
66
|
+
this._onWindowToast = (e) => {
|
|
67
|
+
const detail = e.detail || {}
|
|
68
|
+
// Routing: toast(msg, { region: "<id>" }) targets the region whose
|
|
69
|
+
// wrapper or list carries that id. Without region only the page's
|
|
70
|
+
// FIRST region spawns — the event is a window broadcast, so every
|
|
71
|
+
// region hears it and an unguarded spawn would duplicate the toast
|
|
72
|
+
// once per region.
|
|
73
|
+
if (!this._handlesRegion(detail.region)) return
|
|
74
|
+
this._spawn(detail)
|
|
75
|
+
}
|
|
67
76
|
this._onWindowDismissAll = () => this._dismissById(null)
|
|
77
|
+
// Dismiss-by-id is a broadcast too: _dismissById only acts on a toast in
|
|
78
|
+
// its OWN list, so whichever region owns the id handles it — the api
|
|
79
|
+
// registration (last region wins) no longer has to be the owner.
|
|
80
|
+
this._onWindowDismissId = (e) => this._dismissById(e.detail?.id)
|
|
68
81
|
this._onKey = this._onKey.bind(this)
|
|
69
82
|
|
|
70
83
|
window.addEventListener("phlex-kit:toast", this._onWindowToast)
|
|
71
84
|
window.addEventListener("phlex-kit:toast:dismiss-all", this._onWindowDismissAll)
|
|
85
|
+
window.addEventListener("phlex-kit:toast:dismiss", this._onWindowDismissId)
|
|
72
86
|
this._listEl.addEventListener("pointerenter", this._onPointerEnter)
|
|
73
87
|
this._listEl.addEventListener("pointerleave", this._onPointerLeave)
|
|
74
88
|
document.addEventListener("keydown", this._onKey)
|
|
@@ -81,6 +95,7 @@ export default class extends Controller {
|
|
|
81
95
|
disconnect() {
|
|
82
96
|
window.removeEventListener("phlex-kit:toast", this._onWindowToast)
|
|
83
97
|
window.removeEventListener("phlex-kit:toast:dismiss-all", this._onWindowDismissAll)
|
|
98
|
+
window.removeEventListener("phlex-kit:toast:dismiss", this._onWindowDismissId)
|
|
84
99
|
this._listEl?.removeEventListener("pointerenter", this._onPointerEnter)
|
|
85
100
|
this._listEl?.removeEventListener("pointerleave", this._onPointerLeave)
|
|
86
101
|
document.removeEventListener("keydown", this._onKey)
|
|
@@ -165,6 +180,15 @@ export default class extends Controller {
|
|
|
165
180
|
return node.id
|
|
166
181
|
}
|
|
167
182
|
|
|
183
|
+
// True when this region should act on a toast event carrying `region`
|
|
184
|
+
// (the list's base id or the wrapper's "<id>-region" both match). Without
|
|
185
|
+
// an explicit region, only the page's first region in DOM order handles
|
|
186
|
+
// the broadcast — single-region pages are unaffected.
|
|
187
|
+
_handlesRegion(region) {
|
|
188
|
+
if (region) return region === this.element.id || region === this._listEl?.id
|
|
189
|
+
return this.element === document.querySelector("[data-controller~='phlex-kit--toaster']")
|
|
190
|
+
}
|
|
191
|
+
|
|
168
192
|
_dismissById(id) {
|
|
169
193
|
if (!id) {
|
|
170
194
|
this.toastTargets.forEach((el) =>
|
|
@@ -172,6 +196,7 @@ export default class extends Controller {
|
|
|
172
196
|
)
|
|
173
197
|
return
|
|
174
198
|
}
|
|
199
|
+
if (!this._listEl) return
|
|
175
200
|
const el = this._listEl.querySelector(`#${CSS.escape(id)}`)
|
|
176
201
|
if (el) el.dispatchEvent(new CustomEvent("phlex-kit:toast:force-dismiss", { bubbles: true }))
|
|
177
202
|
}
|
|
@@ -310,12 +335,14 @@ export default class extends Controller {
|
|
|
310
335
|
api.info = (m, o) => fire("info", m, o)
|
|
311
336
|
api.loading = (m, o = {}) => fire("loading", m, { ...o, duration: o.duration ?? 0 })
|
|
312
337
|
api.dismiss = (id) => {
|
|
313
|
-
|
|
338
|
+
// Both broadcasts: whichever region owns the id dismisses it — the
|
|
339
|
+
// api may be registered by a different region than the owner.
|
|
340
|
+
if (id) window.dispatchEvent(new CustomEvent("phlex-kit:toast:dismiss", { detail: { id } }))
|
|
314
341
|
else window.dispatchEvent(new CustomEvent("phlex-kit:toast:dismiss-all"))
|
|
315
342
|
}
|
|
316
343
|
api.promise = (p, msgs = {}) => {
|
|
317
344
|
const id = `toast-${this._uuid()}`
|
|
318
|
-
fire("loading", typeof msgs.loading === "function" ? msgs.loading() : (msgs.loading || "Loading..."), { id, duration: 0 })
|
|
345
|
+
fire("loading", typeof msgs.loading === "function" ? msgs.loading() : (msgs.loading || "Loading..."), { id, duration: 0, region: msgs.region })
|
|
319
346
|
Promise.resolve(p).then(
|
|
320
347
|
(val) => this._mutate(id, "success", typeof msgs.success === "function" ? msgs.success(val) : msgs.success),
|
|
321
348
|
(err) => this._mutate(id, "error", typeof msgs.error === "function" ? msgs.error(err) : msgs.error)
|
|
@@ -329,8 +356,11 @@ export default class extends Controller {
|
|
|
329
356
|
}
|
|
330
357
|
|
|
331
358
|
_mutate(id, variant, text) {
|
|
332
|
-
|
|
333
|
-
|
|
359
|
+
// Document-scoped: promise()'s loading toast spawns in whichever region
|
|
360
|
+
// the broadcast routed it to, which need not be the region that
|
|
361
|
+
// registered the api this closure belongs to.
|
|
362
|
+
const el = document.getElementById(id)
|
|
363
|
+
if (!el || !el.closest(".pk-toast-list")) return
|
|
334
364
|
el.dataset.variant = variant
|
|
335
365
|
el.setAttribute("role", variant === "error" ? "alert" : "status")
|
|
336
366
|
this._swapIcon(el, variant)
|
|
@@ -28,13 +28,28 @@ module PhlexKit
|
|
|
28
28
|
|
|
29
29
|
def item_context
|
|
30
30
|
{ type: @type, variant: @variant, size: @size, disabled: @disabled,
|
|
31
|
-
selected_values: selected_values, spacing: @spacing, orientation: @orientation
|
|
31
|
+
selected_values: selected_values, spacing: @spacing, orientation: @orientation,
|
|
32
|
+
group: self }
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def ToggleGroupItem(**kwargs, &block)
|
|
35
36
|
render PhlexKit::ToggleGroupItem.new(group_context: item_context, **kwargs), &block
|
|
36
37
|
end
|
|
37
38
|
|
|
39
|
+
# Roving-tabindex initial stop (single-type, nothing selected): the FIRST
|
|
40
|
+
# enabled item claims tabindex="0" server-side, mirroring what
|
|
41
|
+
# toggle_group_controller.js's reconcile() computes at runtime
|
|
42
|
+
# (`pressed || enabledItems()[0]`). Items call this once each, in render
|
|
43
|
+
# order, as they're constructed — a single-threaded sequential claim, not
|
|
44
|
+
# a lookahead over siblings not yet rendered.
|
|
45
|
+
def claim_tab_stop(item_disabled)
|
|
46
|
+
return false unless selected_values.empty?
|
|
47
|
+
return false if item_disabled
|
|
48
|
+
return false if @tab_stop_claimed
|
|
49
|
+
@tab_stop_claimed = true
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
38
53
|
private
|
|
39
54
|
|
|
40
55
|
def selected_values
|
|
@@ -33,14 +33,17 @@ export default class extends Controller {
|
|
|
33
33
|
if (items.length === 0) return
|
|
34
34
|
const currentIndex = items.indexOf(event.currentTarget)
|
|
35
35
|
let nextIndex = currentIndex
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
// In RTL the horizontal arrows mirror (physical LEFT = next); Up/Down are
|
|
37
|
+
// unaffected. Runtime dir check is reliable after a dynamic flip.
|
|
38
|
+
const rtl = getComputedStyle(this.element).direction === "rtl"
|
|
39
|
+
const fwd = rtl ? "ArrowLeft" : "ArrowRight"
|
|
40
|
+
const back = rtl ? "ArrowRight" : "ArrowLeft"
|
|
41
|
+
if (event.key === fwd || event.key === "ArrowDown") nextIndex = (currentIndex + 1) % items.length
|
|
42
|
+
else if (event.key === back || event.key === "ArrowUp") nextIndex = (currentIndex - 1 + items.length) % items.length
|
|
43
|
+
else if (event.key === "Home") nextIndex = 0
|
|
44
|
+
else if (event.key === "End") nextIndex = items.length - 1
|
|
45
|
+
else if (event.key === " " || event.key === "Enter") { event.preventDefault(); event.currentTarget.click(); return }
|
|
46
|
+
else return
|
|
44
47
|
event.preventDefault()
|
|
45
48
|
const next = items[nextIndex]
|
|
46
49
|
this.updateRovingTabindex(next)
|
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
module PhlexKit
|
|
2
2
|
class ToggleGroupItem < Toggle
|
|
3
3
|
def initialize(value:, group_context:, variant: nil, size: nil, **attrs)
|
|
4
|
-
# Toggle kwargs this item renders no markup for
|
|
5
|
-
#
|
|
6
|
-
|
|
4
|
+
# Toggle kwargs this item renders no markup for, or that the group
|
|
5
|
+
# derives itself (pressed: comes from the group's selected_values) —
|
|
6
|
+
# inheriting them silently discarded the caller's input.
|
|
7
|
+
unsupported = attrs.keys & %i[wrapper name unpressed_value pressed]
|
|
7
8
|
if unsupported.any?
|
|
8
9
|
raise ArgumentError, "ToggleGroupItem does not support #{unsupported.join(", ")} (group items render a bare button)"
|
|
9
10
|
end
|
|
10
11
|
@item_value = value.to_s
|
|
11
12
|
@group_context = group_context
|
|
12
13
|
pressed = group_context[:selected_values].include?(@item_value)
|
|
14
|
+
item_disabled = attrs.key?(:disabled) ? attrs.delete(:disabled) : group_context[:disabled]
|
|
15
|
+
# Roving tabindex initial stop: when nothing is selected yet, the first
|
|
16
|
+
# enabled item claims tabindex="0" (see ToggleGroup#claim_tab_stop).
|
|
17
|
+
# group_context[:group] is nil for a hand-built context (bypassing
|
|
18
|
+
# ToggleGroup#item_context) — treat that as "no tab-stop claim" rather
|
|
19
|
+
# than raising, since standalone tests construct contexts by hand.
|
|
20
|
+
@is_first_tab_stop = group_context[:group]&.claim_tab_stop(item_disabled) || false
|
|
13
21
|
super(pressed: pressed, name: nil, value: @item_value,
|
|
14
22
|
variant: variant || group_context[:variant],
|
|
15
23
|
size: size || group_context[:size],
|
|
16
|
-
disabled:
|
|
24
|
+
disabled: item_disabled, **attrs)
|
|
17
25
|
end
|
|
18
26
|
|
|
19
27
|
def view_template(&block)
|
|
@@ -34,7 +42,9 @@ module PhlexKit
|
|
|
34
42
|
a[:aria] = { checked: @pressed.to_s }
|
|
35
43
|
# A disabled button can't take focus — giving the tab stop to a
|
|
36
44
|
# pressed-but-disabled item made the whole group Tab-unreachable.
|
|
37
|
-
|
|
45
|
+
# When nothing is selected, the first enabled item claims the initial
|
|
46
|
+
# roving-tabindex stop instead of every item defaulting to -1.
|
|
47
|
+
a[:tabindex] = (@pressed && !@disabled) || @is_first_tab_stop ? "0" : "-1"
|
|
38
48
|
else
|
|
39
49
|
a[:aria] = { pressed: @pressed.to_s }
|
|
40
50
|
a[:tabindex] = "0"
|
|
@@ -24,6 +24,7 @@ import ContextMenuController from "phlex_kit/controllers/context_menu_controller
|
|
|
24
24
|
import DataTableController from "phlex_kit/controllers/data_table_controller"
|
|
25
25
|
import DataTableColumnVisibilityController from "phlex_kit/controllers/data_table_column_visibility_controller"
|
|
26
26
|
import DataTableSearchController from "phlex_kit/controllers/data_table_search_controller"
|
|
27
|
+
import DatePickerController from "phlex_kit/controllers/date_picker_controller"
|
|
27
28
|
import DialogController from "phlex_kit/controllers/dialog_controller"
|
|
28
29
|
import DropdownMenuController from "phlex_kit/controllers/dropdown_menu_controller"
|
|
29
30
|
import FormFieldController from "phlex_kit/controllers/form_field_controller"
|
|
@@ -65,6 +66,7 @@ export function registerPhlexKitControllers(application) {
|
|
|
65
66
|
application.register("phlex-kit--data-table", DataTableController)
|
|
66
67
|
application.register("phlex-kit--data-table-column-visibility", DataTableColumnVisibilityController)
|
|
67
68
|
application.register("phlex-kit--data-table-search", DataTableSearchController)
|
|
69
|
+
application.register("phlex-kit--date-picker", DatePickerController)
|
|
68
70
|
application.register("phlex-kit--dialog", DialogController)
|
|
69
71
|
application.register("phlex-kit--dropdown-menu", DropdownMenuController)
|
|
70
72
|
application.register("phlex-kit--form-field", FormFieldController)
|
|
@@ -31,17 +31,36 @@ module PhlexKit
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
# True when the caller supplied their own value for a plain attribute in
|
|
35
|
+
# @attrs — symbol or string spelling. A component with a generated default
|
|
36
|
+
# for that attribute must skip it then: `mix` merges duplicate attrs
|
|
37
|
+
# (role="dialog region") instead of overriding. Aria attributes have their
|
|
38
|
+
# own check (aria_key_set?) covering the aria: hash spelling too.
|
|
39
|
+
def attr_set?(key)
|
|
40
|
+
@attrs.key?(key) || @attrs.key?(key.to_s)
|
|
41
|
+
end
|
|
42
|
+
|
|
34
43
|
# True when the caller supplied an accessible name in @attrs — via the
|
|
35
44
|
# aria: hash or flat aria_label/aria-label(ledby) keys. Components with a
|
|
36
45
|
# generated default label must skip it then: `mix` merges duplicate string
|
|
37
46
|
# attrs ("pagination Résultats") instead of overriding.
|
|
38
47
|
def aria_labelled?
|
|
48
|
+
aria_key_set?(:label) || aria_key_set?(:labelledby)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# True when the caller already supplied their own value for a given aria
|
|
52
|
+
# attribute — via the aria: hash (aria: { <key>: ... }) or the flat
|
|
53
|
+
# "aria-<key>"/aria_<key> spelling. A component with a generated default
|
|
54
|
+
# for that attribute must skip it then: `mix` merges duplicate attrs
|
|
55
|
+
# (aria-modal="true false") instead of overriding.
|
|
56
|
+
def aria_key_set?(key)
|
|
39
57
|
aria = @attrs[:aria] || @attrs["aria"]
|
|
40
58
|
if aria.is_a?(Hash)
|
|
41
|
-
return true if
|
|
59
|
+
return true if aria.key?(key) || aria.key?(key.to_s)
|
|
42
60
|
end
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
dashed = "aria-#{key}"
|
|
62
|
+
underscored = "aria_#{key}"
|
|
63
|
+
[ dashed.to_sym, dashed, underscored.to_sym, underscored ].any? { |k| @attrs[k] }
|
|
45
64
|
end
|
|
46
65
|
end
|
|
47
66
|
end
|
data/lib/phlex_kit/version.rb
CHANGED
data/lib/phlex_kit.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "json" # Carousel serializes its options value standalone (no Rails to_json)
|
|
4
4
|
require "securerandom" # DatePicker generates a default input id
|
|
5
5
|
require "cgi" # DataTable sort/pagination build query strings standalone
|
|
6
|
+
require "date" # Phlex 2.4's attribute type-dispatch references Date on every render
|
|
6
7
|
# phlex-rails references ActiveSupport::SafeBuffer at require time; in a Rails
|
|
7
8
|
# app it's already loaded, but a bare `require "phlex_kit"` (script/console)
|
|
8
9
|
# crashes with "uninitialized constant Phlex::ActiveSupport" without these.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: phlex_kit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Kennedy
|
|
@@ -306,6 +306,7 @@ files:
|
|
|
306
306
|
- app/components/phlex_kit/data_table/data_table_toolbar.rb
|
|
307
307
|
- app/components/phlex_kit/date_picker/date_picker.css
|
|
308
308
|
- app/components/phlex_kit/date_picker/date_picker.rb
|
|
309
|
+
- app/components/phlex_kit/date_picker/date_picker_controller.js
|
|
309
310
|
- app/components/phlex_kit/dialog/dialog.css
|
|
310
311
|
- app/components/phlex_kit/dialog/dialog.rb
|
|
311
312
|
- app/components/phlex_kit/dialog/dialog_close.rb
|