atomic_view 0.4.0 → 0.4.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f37c405116dc18595f21f9f7b3a45223edef67c921c991a7c1523a93b594cf39
|
|
4
|
+
data.tar.gz: 3ce7216ee4b6327f57dec679651d507ba799023f4b2eb3b865ef61bfa3781c1a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a550e6749f5c77da2336b475b69d59d24d09be6e5dfb321bc9c2e73af3968d1b308e0d26962e728f8f0c5dfcd4a341e0d6e63a753ec5986943deba90db4223c7
|
|
7
|
+
data.tar.gz: 05477662ea7b03cd022ca121c0c1b30967cdf99feae9166209aabf64f531ef1902b3a5c746e76dca92cc107e2a7caa05705a36f91f2fd9bdb3e941270eb49e07
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
<% if linked? %>
|
|
3
3
|
<%= link_to "", path, class: "absolute inset-0", tabindex: (first ? 0 : -1), "aria-hidden": (first ? nil : "true"), "aria-label": (first ? label : nil), data: {row_link: true} %>
|
|
4
4
|
<% end %>
|
|
5
|
-
<%= tag.span(content, class:
|
|
5
|
+
<%= tag.span(content, class: content_class) %>
|
|
6
6
|
<% end %>
|
|
@@ -10,21 +10,25 @@ module AtomicView
|
|
|
10
10
|
# design. `first` and `clickable` are set by RowComponent's `cells`
|
|
11
11
|
# slot from the row itself, not passed by the caller.
|
|
12
12
|
#
|
|
13
|
-
# Visible content renders as a
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
13
|
+
# Visible content renders as a sibling of the (empty, transparent)
|
|
14
|
+
# stretched `<a>`, wrapped in a `pointer-events-none` span so plain
|
|
15
|
+
# content (the common case -- a name, a badge) doesn't sit in the
|
|
16
|
+
# way of clicks meant for the row-wide overlay underneath it. Pass
|
|
17
|
+
# `interactive: true` on a cell that renders a real, more specific
|
|
18
|
+
# link/button of its own (e.g. an "Edit" action) to flip that span
|
|
19
|
+
# back to `pointer-events-auto`, so that cell's own content takes
|
|
20
|
+
# the click instead of falling through to the row link.
|
|
18
21
|
class CellComponent < AtomicView::Component
|
|
19
|
-
attr_reader :path, :label, :first, :align, :clickable
|
|
22
|
+
attr_reader :path, :label, :first, :align, :clickable, :interactive
|
|
20
23
|
|
|
21
|
-
def initialize(path:, label:, first:, align: :left, clickable: true, **options)
|
|
24
|
+
def initialize(path:, label:, first:, align: :left, clickable: true, interactive: false, **options)
|
|
22
25
|
super()
|
|
23
26
|
@path = path
|
|
24
27
|
@label = label
|
|
25
28
|
@first = first
|
|
26
29
|
@align = align
|
|
27
30
|
@clickable = clickable
|
|
31
|
+
@interactive = interactive
|
|
28
32
|
@options = options
|
|
29
33
|
end
|
|
30
34
|
|
|
@@ -40,6 +44,10 @@ module AtomicView
|
|
|
40
44
|
@options.except(:class)
|
|
41
45
|
end
|
|
42
46
|
|
|
47
|
+
def content_class
|
|
48
|
+
interactive ? "relative pointer-events-auto" : "relative pointer-events-none"
|
|
49
|
+
end
|
|
50
|
+
|
|
43
51
|
private
|
|
44
52
|
|
|
45
53
|
def base_classes
|
|
@@ -24,32 +24,37 @@ module AtomicView
|
|
|
24
24
|
#
|
|
25
25
|
# `with_column` is an opt-in alternative to hand-building the <thead>:
|
|
26
26
|
# give it at least one column and TableComponent renders the header row
|
|
27
|
-
# itself, from `<th>`s built by TableComponent::ColumnComponent --
|
|
28
|
-
#
|
|
29
|
-
#
|
|
27
|
+
# itself, from `<th>`s built by TableComponent::ColumnComponent -- and
|
|
28
|
+
# wraps the block's return value in a <tbody> for you too, so the block
|
|
29
|
+
# only has to render rows (typically TableComponent::RowComponent),
|
|
30
|
+
# same as it would for a turbo_stream append/update elsewhere:
|
|
30
31
|
#
|
|
31
32
|
# <%= render AtomicView::Components::TableComponent.new(model: Booking) do |table| %>
|
|
32
33
|
# <% table.with_column(attribute: :camper_name) %>
|
|
33
34
|
# <% table.with_column(attribute: :status, align: :center) %>
|
|
34
35
|
# <% table.with_column(label: "") %>
|
|
35
36
|
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
# <% row.with_cell { render(LinkComponent.new(edit_booking_path(booking), variant: :outline)) { "Edit" } } %>
|
|
42
|
-
# <% end %>
|
|
37
|
+
# <% @bookings.each do |booking| %>
|
|
38
|
+
# <%= render(AtomicView::Components::TableComponent::RowComponent.new(record: booking, label: booking.camper_name, path: booking_path(booking))) do |row| %>
|
|
39
|
+
# <% row.with_cell { booking.camper_name } %>
|
|
40
|
+
# <% row.with_cell(align: :center) { render(BadgeComponent.new) { booking.status } } %>
|
|
41
|
+
# <% row.with_cell(interactive: true) { render(LinkComponent.new(edit_booking_path(booking), variant: :outline)) { "Edit" } } %>
|
|
43
42
|
# <% end %>
|
|
44
|
-
#
|
|
43
|
+
# <% end %>
|
|
45
44
|
# <% end %>
|
|
46
45
|
#
|
|
46
|
+
# The <tbody>'s `id` defaults to `model.model_name.plural` (e.g.
|
|
47
|
+
# "bookings") so a turbo_stream response can target it directly with
|
|
48
|
+
# no extra bookkeeping -- pass `body_id:` to override it (a nested
|
|
49
|
+
# resource sharing a differently-named frame, say).
|
|
50
|
+
#
|
|
47
51
|
# A table with no columns given renders exactly as before -- `with_column`
|
|
48
|
-
# is opt-in, not a second required API
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
52
|
+
# is opt-in, not a second required API, and in that raw mode you still
|
|
53
|
+
# own the whole `<thead>`/`<tbody>` yourself. `model:` is passed through
|
|
54
|
+
# to each column so `with_column(attribute: :camper_name)` can default
|
|
55
|
+
# its label via `model.human_attribute_name(:camper_name)`; a column
|
|
56
|
+
# with no backing attribute (like the blank "" header above, for an
|
|
57
|
+
# actions column) just passes `label:` directly instead.
|
|
53
58
|
class TableComponent < AtomicView::Component
|
|
54
59
|
HEAD_ROW_CLASSES = "text-left text-xs font-semibold uppercase tracking-wide text-muted-foreground border-b border-border"
|
|
55
60
|
BODY_ROW_CLASSES = "border-b border-border hover:bg-offset"
|
|
@@ -58,15 +63,20 @@ module AtomicView
|
|
|
58
63
|
|
|
59
64
|
attr_reader :model
|
|
60
65
|
|
|
61
|
-
def initialize(model: nil, **options)
|
|
66
|
+
def initialize(model: nil, body_id: nil, **options)
|
|
62
67
|
super()
|
|
63
68
|
@model = model
|
|
69
|
+
@body_id = body_id
|
|
64
70
|
@options = options
|
|
65
71
|
end
|
|
66
72
|
|
|
67
73
|
def call
|
|
68
74
|
tag.table(**@options.except(:class), class: class_names(base_classes, @options[:class])) do
|
|
69
|
-
|
|
75
|
+
if columns?
|
|
76
|
+
safe_join([columns_header, tag.tbody(content, id: body_id)])
|
|
77
|
+
else
|
|
78
|
+
content
|
|
79
|
+
end
|
|
70
80
|
end
|
|
71
81
|
end
|
|
72
82
|
|
|
@@ -89,6 +99,10 @@ module AtomicView
|
|
|
89
99
|
columns.any?
|
|
90
100
|
end
|
|
91
101
|
|
|
102
|
+
def body_id
|
|
103
|
+
@body_id || model&.model_name&.plural
|
|
104
|
+
end
|
|
105
|
+
|
|
92
106
|
def base_classes
|
|
93
107
|
"w-full text-sm"
|
|
94
108
|
end
|
data/lib/atomic_view/version.rb
CHANGED