pulse_view_components 0.3.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 +7 -0
- data/CHANGELOG.md +88 -0
- data/LICENSE.txt +22 -0
- data/README.md +78 -0
- data/app/assets/builds/js/pulse_view_components.js +9543 -0
- data/app/assets/builds/js/pulse_view_components.js.map +7 -0
- data/app/assets/builds/pulse_view_components.css +1 -0
- data/app/assets/config/manifest.js +2 -0
- data/app/assets/images/pulse_view_components/icons/alert.svg +3 -0
- data/app/assets/images/pulse_view_components/icons/archive.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-both.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-down.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-left.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-right.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-switch.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/arrow-up.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/beaker.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/bell-slash.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/bell.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/bookmark-slash.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/bookmark.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/calendar.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/check-circle.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/check.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/chevron-down.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/circle.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/clock.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/close.svg +9 -0
- data/app/assets/images/pulse_view_components/icons/cloud.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/comment-discussion.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/comment.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/copy.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/database.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/dot.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/dots-outline.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/download.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/duplicate.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/eye.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/file-added.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/file-directory.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/file-media.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/file.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/filter.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/flame.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/gear.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/gift.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/globe.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/goal.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/graph.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/heart-fill.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/heart.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/history.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/home.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/hourglass.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/image.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/inbox.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/info.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/issue.svg +3 -0
- data/app/assets/images/pulse_view_components/icons/key.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/law.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/link-external.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/link.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/location.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/log.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/mail.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/mark-github.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/mark-jira.svg +3 -0
- data/app/assets/images/pulse_view_components/icons/megaphone.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/no-entry.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/note.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/organization.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/package.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/paintbrush.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/paperclip.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/paste.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/pencil.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/people.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/person-add.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/person.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/pin-slash.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/pin.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/play.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/plus-circle.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/plus.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/project.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/pulse.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/question.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/redo.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/reply.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/report.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/rss.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/ruby.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/search.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/share.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/shield.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sliders.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/smiley.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sort.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sort_asc.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sort_desc.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/stack.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/star-fill.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/star.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/stopwatch.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sun.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/sync.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/table.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/tag.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/tasklist.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/telescope.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/three-bars.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/thumbsdown.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/thumbsup.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/tools.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/trash.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/trophy.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/undo.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/unlink.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/upload.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/x-circle.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/x.svg +1 -0
- data/app/assets/images/pulse_view_components/icons/zap.svg +1 -0
- data/app/assets/javascripts/pulse_view_components.js +0 -0
- data/app/assets/stylesheets/pulse_view_components/application.tailwind.css +10 -0
- data/app/components/pulse/action_list/divider.rb +35 -0
- data/app/components/pulse/action_list/form_wrapper.html.slim +9 -0
- data/app/components/pulse/action_list/form_wrapper.rb +63 -0
- data/app/components/pulse/action_list/heading.rb +52 -0
- data/app/components/pulse/action_list/item.html.slim +43 -0
- data/app/components/pulse/action_list/item.rb +319 -0
- data/app/components/pulse/action_list.css +568 -0
- data/app/components/pulse/action_list.rb +261 -0
- data/app/components/pulse/badge.rb +59 -0
- data/app/components/pulse/base_component.rb +36 -0
- data/app/components/pulse/blank_slate.html.slim +10 -0
- data/app/components/pulse/blank_slate.rb +19 -0
- data/app/components/pulse/blank_slate.yml +2 -0
- data/app/components/pulse/border_box/header.html.slim +4 -0
- data/app/components/pulse/border_box/header.rb +48 -0
- data/app/components/pulse/border_box.html.slim +10 -0
- data/app/components/pulse/border_box.rb +124 -0
- data/app/components/pulse/box.rb +17 -0
- data/app/components/pulse/breadcrumb_item.rb +40 -0
- data/app/components/pulse/breadcrumbs.html.slim +9 -0
- data/app/components/pulse/breadcrumbs.rb +17 -0
- data/app/components/pulse/button.rb +148 -0
- data/app/components/pulse/component.rb +99 -0
- data/app/components/pulse/conditional_wrapper.rb +21 -0
- data/app/components/pulse/content.rb +11 -0
- data/app/components/pulse/counter.css +10 -0
- data/app/components/pulse/counter.rb +107 -0
- data/app/components/pulse/flash.html.slim +9 -0
- data/app/components/pulse/flash.rb +52 -0
- data/app/components/pulse/forms/error_explanation.html.slim +8 -0
- data/app/components/pulse/forms/error_explanation.rb +36 -0
- data/app/components/pulse/icon.rb +30 -0
- data/app/components/pulse/label.html.slim +5 -0
- data/app/components/pulse/label.rb +42 -0
- data/app/components/pulse/layout.css +239 -0
- data/app/components/pulse/layout.html.slim +7 -0
- data/app/components/pulse/layout.rb +141 -0
- data/app/components/pulse/link.html.slim +7 -0
- data/app/components/pulse/link.rb +52 -0
- data/app/components/pulse/modal.html.slim +51 -0
- data/app/components/pulse/modal.rb +64 -0
- data/app/components/pulse/modal_controller.js +77 -0
- data/app/components/pulse/nav_link.html.slim +16 -0
- data/app/components/pulse/nav_link.rb +25 -0
- data/app/components/pulse/nav_list/divider.rb +13 -0
- data/app/components/pulse/nav_list/group.html.slim +6 -0
- data/app/components/pulse/nav_list/group.rb +110 -0
- data/app/components/pulse/nav_list/heading.rb +36 -0
- data/app/components/pulse/nav_list/item.rb +171 -0
- data/app/components/pulse/nav_list.html.slim +11 -0
- data/app/components/pulse/nav_list.rb +225 -0
- data/app/components/pulse/popover.html.slim +5 -0
- data/app/components/pulse/popover.rb +88 -0
- data/app/components/pulse/progress_bar.html.slim +5 -0
- data/app/components/pulse/progress_bar.rb +23 -0
- data/app/components/pulse/progress_bar.yml +2 -0
- data/app/components/pulse/table/cell.html.slim +10 -0
- data/app/components/pulse/table/cell.rb +90 -0
- data/app/components/pulse/table/cell.yml +5 -0
- data/app/components/pulse/table/column.rb +22 -0
- data/app/components/pulse/table.html.slim +50 -0
- data/app/components/pulse/table.rb +111 -0
- data/app/components/pulse/table.yml +2 -0
- data/app/components/pulse/text.rb +72 -0
- data/app/components/pulse/toast.html.slim +14 -0
- data/app/components/pulse/toast.rb +85 -0
- data/app/components/pulse/toast_controller.js +32 -0
- data/app/javascript/pulse_view_components/application.js +24 -0
- data/app/javascript/pulse_view_components.js +4 -0
- data/app/lib/pulse/attributes_helper.rb +107 -0
- data/app/lib/pulse/fetch_or_fallback_helper.rb +53 -0
- data/app/lib/pulse/svg_helper.rb +28 -0
- data/lib/pulse/view_components/engine.rb +74 -0
- data/lib/pulse/view_components/version.rb +17 -0
- data/lib/pulse/view_components.rb +14 -0
- data/lib/pulse_view_components.rb +3 -0
- data/lib/tasks/pulse_view_components_tasks.rake +8 -0
- data/previews/pulse/badge_preview.rb +51 -0
- data/previews/pulse/blank_slate_preview.rb +14 -0
- data/previews/pulse/border_box_preview.rb +48 -0
- data/previews/pulse/breadcrumbs_preview.rb +13 -0
- data/previews/pulse/button_preview.rb +137 -0
- data/previews/pulse/counter_preview.rb +14 -0
- data/previews/pulse/flash_preview.rb +85 -0
- data/previews/pulse/icon_preview.rb +12 -0
- data/previews/pulse/label_preview.rb +10 -0
- data/previews/pulse/layout_preview.rb +34 -0
- data/previews/pulse/link_preview.rb +55 -0
- data/previews/pulse/modal_preview.rb +48 -0
- data/previews/pulse/nav_link_preview.rb +48 -0
- data/previews/pulse/nav_list_preview.rb +138 -0
- data/previews/pulse/popover_preview.rb +77 -0
- data/previews/pulse/progress_bar_preview.rb +23 -0
- data/previews/pulse/table_preview.rb +168 -0
- data/previews/pulse/text_preview.rb +102 -0
- data/previews/pulse/toast_preview.rb +67 -0
- metadata +344 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/* Layout */
|
|
2
|
+
|
|
3
|
+
@define-mixin flow-as-row {
|
|
4
|
+
grid-auto-flow: row;
|
|
5
|
+
grid-template-columns: 1fr !important;
|
|
6
|
+
|
|
7
|
+
& .Layout-sidebar,
|
|
8
|
+
& .Layout-divider,
|
|
9
|
+
& .Layout-main {
|
|
10
|
+
@apply pulse-w-full pulse-col-[1];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
&.Layout--sidebarPosition-flowRow-start {
|
|
14
|
+
& .Layout-sidebar {
|
|
15
|
+
@apply pulse-row-[1];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
& .Layout-main {
|
|
19
|
+
@apply pulse-row-[2_/_span_2];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&.Layout--sidebarPosition-flowRow-end {
|
|
24
|
+
& .Layout-sidebar {
|
|
25
|
+
@apply pulse-row-[2_/_span_2];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
& .Layout-main {
|
|
29
|
+
@apply pulse-row-[1];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.Layout--sidebarPosition-flowRow-none {
|
|
34
|
+
& .Layout-sidebar {
|
|
35
|
+
@apply pulse-hidden;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&.Layout--divided {
|
|
40
|
+
@mixin flow-as-row-divider;
|
|
41
|
+
|
|
42
|
+
& .Layout-main {
|
|
43
|
+
@apply pulse-row-[3_/_span_1];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&.Layout--sidebarPosition-flowRow-end {
|
|
47
|
+
& .Layout-sidebar {
|
|
48
|
+
@apply pulse-row-[3_/_span_1];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
& .Layout-main {
|
|
52
|
+
@apply pulse-row-[1];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@define-mixin flow-as-row-divider {
|
|
59
|
+
--Layout-gutter: 0;
|
|
60
|
+
|
|
61
|
+
& .Layout-divider {
|
|
62
|
+
@apply pulse-h-px pulse-row-[2];
|
|
63
|
+
|
|
64
|
+
&.Layout-divider--flowRow-hidden {
|
|
65
|
+
@apply pulse-hidden;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&.Layout-divider--flowRow-shallow {
|
|
69
|
+
@apply pulse-h-2 pulse-border-[color:var(--borderColor-default)] pulse-border-[var(--borderWidth-thin)_0] pulse-mr-0 pulse-border-solid;
|
|
70
|
+
background: var(--bgColor-inset);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.Layout {
|
|
76
|
+
@apply pulse-grid pulse-grid-flow-col pulse-grid-cols-[auto_0_minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))] pulse-gap-[var(--Layout-gutter)];
|
|
77
|
+
--Layout-sidebar-width: 220px;
|
|
78
|
+
--Layout-gutter: 16px;
|
|
79
|
+
}
|
|
80
|
+
@media (max-width: calc(544px - 0.02px)) {
|
|
81
|
+
.Layout {
|
|
82
|
+
@mixin flow-as-row;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
@media (max-width: calc(768px - 0.02px)) {
|
|
86
|
+
.Layout.Layout--flowRow-until-md {
|
|
87
|
+
@mixin flow-as-row;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
@media (max-width: calc(1012px - 0.02px)) {
|
|
91
|
+
.Layout.Layout--flowRow-until-lg {
|
|
92
|
+
@mixin flow-as-row;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Flow as column */
|
|
97
|
+
|
|
98
|
+
/* sidebar column, separator, main column */
|
|
99
|
+
.Layout .Layout-sidebar {
|
|
100
|
+
@apply pulse-col-[1];
|
|
101
|
+
}
|
|
102
|
+
.Layout .Layout-divider {
|
|
103
|
+
@apply pulse-hidden;
|
|
104
|
+
}
|
|
105
|
+
.Layout .Layout-main {
|
|
106
|
+
@apply pulse-col-[2_/_span_2];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Gutter spacing */
|
|
110
|
+
@media (min-width: 1012px) {
|
|
111
|
+
.Layout {
|
|
112
|
+
--Layout-gutter: 24px;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
.Layout.Layout--gutter-none {
|
|
116
|
+
/* stylelint-disable-next-line length-zero-no-unit */
|
|
117
|
+
--Layout-gutter: 0px;
|
|
118
|
+
|
|
119
|
+
/* Neds px in value */
|
|
120
|
+
}
|
|
121
|
+
.Layout.Layout--gutter-condensed {
|
|
122
|
+
--Layout-gutter: 16px;
|
|
123
|
+
}
|
|
124
|
+
@media (min-width: 1012px) {
|
|
125
|
+
.Layout.Layout--gutter-spacious {
|
|
126
|
+
--Layout-gutter: 32px;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
@media (min-width: 1280px) {
|
|
130
|
+
.Layout.Layout--gutter-spacious {
|
|
131
|
+
--Layout-gutter: 40px;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Sidebar width */
|
|
136
|
+
@media (min-width: 544px) {
|
|
137
|
+
.Layout {
|
|
138
|
+
--Layout-sidebar-width: 220px;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
@media (min-width: 768px) {
|
|
142
|
+
.Layout {
|
|
143
|
+
--Layout-sidebar-width: 256px;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
@media (min-width: 1012px) {
|
|
147
|
+
.Layout {
|
|
148
|
+
--Layout-sidebar-width: 296px;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
@media (min-width: 768px) {
|
|
152
|
+
.Layout.Layout--sidebar-narrow {
|
|
153
|
+
--Layout-sidebar-width: 240px;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
@media (min-width: 1012px) {
|
|
157
|
+
.Layout.Layout--sidebar-narrow {
|
|
158
|
+
--Layout-sidebar-width: 256px;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
@media (min-width: 1012px) {
|
|
162
|
+
.Layout.Layout--sidebar-wide {
|
|
163
|
+
--Layout-sidebar-width: 320px;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
@media (min-width: 1280px) {
|
|
167
|
+
.Layout.Layout--sidebar-wide {
|
|
168
|
+
--Layout-sidebar-width: 336px;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Sidebar position */
|
|
173
|
+
.Layout.Layout--sidebarPosition-start .Layout-sidebar {
|
|
174
|
+
@apply pulse-col-[1];
|
|
175
|
+
}
|
|
176
|
+
.Layout.Layout--sidebarPosition-start .Layout-main {
|
|
177
|
+
@apply pulse-col-[2_/_span_2];
|
|
178
|
+
}
|
|
179
|
+
.Layout.Layout--sidebarPosition-end {
|
|
180
|
+
@apply pulse-grid-cols-[minmax(0,calc(100%_-_var(--Layout-sidebar-width)_-_var(--Layout-gutter)))_0_auto];
|
|
181
|
+
}
|
|
182
|
+
.Layout.Layout--sidebarPosition-end .Layout-main {
|
|
183
|
+
@apply pulse-col-[1];
|
|
184
|
+
}
|
|
185
|
+
.Layout.Layout--sidebarPosition-end .Layout-sidebar {
|
|
186
|
+
@apply pulse-col-[2_/_span_2];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Sidebar divider */
|
|
190
|
+
.Layout.Layout--divided .Layout-divider {
|
|
191
|
+
@apply pulse-block pulse-col-[2] pulse-w-px -pulse-mr-px;
|
|
192
|
+
background: var(--borderColor-default);
|
|
193
|
+
}
|
|
194
|
+
.Layout.Layout--divided .Layout-main {
|
|
195
|
+
@apply pulse-col-[3_/_span_1];
|
|
196
|
+
}
|
|
197
|
+
.Layout.Layout--divided.Layout--sidebarPosition-end .Layout-sidebar {
|
|
198
|
+
@apply pulse-col-[3_/_span_1];
|
|
199
|
+
}
|
|
200
|
+
.Layout.Layout--divided.Layout--sidebarPosition-end .Layout-main {
|
|
201
|
+
@apply pulse-col-[1];
|
|
202
|
+
}
|
|
203
|
+
.Layout-divider {
|
|
204
|
+
@apply pulse-hidden pulse-w-px;
|
|
205
|
+
}
|
|
206
|
+
.Layout-sidebar {
|
|
207
|
+
@apply pulse-w-[var(--Layout-sidebar-width)];
|
|
208
|
+
}
|
|
209
|
+
.Layout-main {
|
|
210
|
+
@apply pulse-min-w-0;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Centered main column
|
|
214
|
+
** FIXME: right-aligned sidebar */
|
|
215
|
+
.Layout-main .Layout-main-centered-md,
|
|
216
|
+
.Layout-main .Layout-main-centered-lg,
|
|
217
|
+
.Layout-main .Layout-main-centered-xl {
|
|
218
|
+
@apply pulse-mx-auto;
|
|
219
|
+
}
|
|
220
|
+
.Layout-main .Layout-main-centered-md > .container-md,
|
|
221
|
+
.Layout-main .Layout-main-centered-md > .container-lg,
|
|
222
|
+
.Layout-main .Layout-main-centered-md > .container-xl,
|
|
223
|
+
.Layout-main .Layout-main-centered-lg > .container-md,
|
|
224
|
+
.Layout-main .Layout-main-centered-lg > .container-lg,
|
|
225
|
+
.Layout-main .Layout-main-centered-lg > .container-xl,
|
|
226
|
+
.Layout-main .Layout-main-centered-xl > .container-md,
|
|
227
|
+
.Layout-main .Layout-main-centered-xl > .container-lg,
|
|
228
|
+
.Layout-main .Layout-main-centered-xl > .container-xl {
|
|
229
|
+
@apply pulse-ml-0;
|
|
230
|
+
}
|
|
231
|
+
.Layout-main .Layout-main-centered-md {
|
|
232
|
+
@apply pulse-max-w-[calc(var(--breakpoint-medium)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
|
|
233
|
+
}
|
|
234
|
+
.Layout-main .Layout-main-centered-lg {
|
|
235
|
+
@apply pulse-max-w-[calc(var(--breakpoint-large)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
|
|
236
|
+
}
|
|
237
|
+
.Layout-main .Layout-main-centered-xl {
|
|
238
|
+
@apply pulse-max-w-[calc(var(--breakpoint-xlarge)_+_var(--Layout-sidebar-width)_+_var(--Layout-gutter))];
|
|
239
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pulse
|
|
4
|
+
# Renders a two-column page layout
|
|
5
|
+
class Layout < Pulse::Component
|
|
6
|
+
FIRST_IN_SOURCE_DEFAULT = :sidebar
|
|
7
|
+
FIRST_IN_SOURCE_OPTIONS = [FIRST_IN_SOURCE_DEFAULT, :main].freeze
|
|
8
|
+
|
|
9
|
+
GUTTER_DEFAULT = :default
|
|
10
|
+
GUTTER_MAPPINGS = {
|
|
11
|
+
# :none => "Layout--gutter-none",
|
|
12
|
+
# :condensed => "Layout--gutter-condensed",
|
|
13
|
+
# :spacious => "Layout--gutter-spacious",
|
|
14
|
+
GUTTER_DEFAULT => ''
|
|
15
|
+
}.freeze
|
|
16
|
+
GUTTER_OPTIONS = GUTTER_MAPPINGS.keys.freeze
|
|
17
|
+
|
|
18
|
+
SIDEBAR_WIDTH_DEFAULT = :default
|
|
19
|
+
SIDEBAR_WIDTH_MAPPINGS = {
|
|
20
|
+
SIDEBAR_WIDTH_DEFAULT => ''
|
|
21
|
+
# :narrow => "Layout--sidebar-narrow",
|
|
22
|
+
# :wide => "Layout--sidebar-wide"
|
|
23
|
+
}.freeze
|
|
24
|
+
SIDEBAR_WIDTH_OPTIONS = SIDEBAR_WIDTH_MAPPINGS.keys.freeze
|
|
25
|
+
|
|
26
|
+
# The layout's main content.
|
|
27
|
+
#
|
|
28
|
+
# @param width [Symbol] <%= one_of(Layout::Main::WIDTH_OPTIONS) %>
|
|
29
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
|
30
|
+
renders_one :main, 'Pulse::Layout::Main'
|
|
31
|
+
|
|
32
|
+
# The layout's sidebar.
|
|
33
|
+
#
|
|
34
|
+
# @param width [Symbol] <%= one_of(Layout::SIDEBAR_WIDTH_OPTIONS) %>
|
|
35
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
|
36
|
+
renders_one :sidebar, lambda { |
|
|
37
|
+
width: SIDEBAR_WIDTH_DEFAULT,
|
|
38
|
+
**system_arguments
|
|
39
|
+
|
|
|
40
|
+
# These classes have to be set in the parent `Layout` element, so we modify its system arguments.
|
|
41
|
+
@system_arguments[:classes] = merge_classes(
|
|
42
|
+
@system_arguments[:classes],
|
|
43
|
+
SIDEBAR_WIDTH_MAPPINGS[fetch_or_fallback(SIDEBAR_WIDTH_OPTIONS, width,
|
|
44
|
+
SIDEBAR_WIDTH_DEFAULT)]
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
Pulse::Layout::Sidebar.new(**system_arguments)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# @param first_in_source [Symbol] Which element to render first in the HTML. This will change the keyboard navigation order. <%= one_of(Layout::FIRST_IN_SOURCE_OPTIONS) %>
|
|
51
|
+
# @param gutter [Symbol] The amount of space between the main section and the sidebar. <%= one_of(Layout::GUTTER_OPTIONS) %>
|
|
52
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
|
53
|
+
def initialize(first_in_source: FIRST_IN_SOURCE_DEFAULT, gutter: :default,
|
|
54
|
+
**system_arguments)
|
|
55
|
+
@first_in_source = fetch_or_fallback(
|
|
56
|
+
FIRST_IN_SOURCE_OPTIONS,
|
|
57
|
+
first_in_source,
|
|
58
|
+
FIRST_IN_SOURCE_OPTIONS
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
@system_arguments = system_arguments
|
|
62
|
+
@system_arguments[:tag] = :div
|
|
63
|
+
@system_arguments[:classes] = merge_classes(
|
|
64
|
+
'pulse-grid pulse-grid-flow-col',
|
|
65
|
+
'pulse-grid-cols-[auto_0_minmax(0,calc(100%_-_var(--pulse-layout' \
|
|
66
|
+
'-sidebar-width)_-_var(--pulse-layout-gutter)))]',
|
|
67
|
+
'pulse-gap-[var(--pulse-layout-gutter)]',
|
|
68
|
+
GUTTER_MAPPINGS[fetch_or_fallback(GUTTER_OPTIONS, gutter,
|
|
69
|
+
GUTTER_DEFAULT)],
|
|
70
|
+
system_arguments[:classes]
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def render?
|
|
75
|
+
main? && sidebar?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# The layout's main content.
|
|
79
|
+
class Main < Pulse::Component
|
|
80
|
+
WIDTH_DEFAULT = :full
|
|
81
|
+
WIDTH_OPTIONS = [WIDTH_DEFAULT, :md, :lg, :xl].freeze
|
|
82
|
+
|
|
83
|
+
TAG_DEFAULT = :div
|
|
84
|
+
TAG_OPTIONS = [TAG_DEFAULT, :main].freeze
|
|
85
|
+
|
|
86
|
+
# @param width [Symbol] <%= one_of(Layout::Main::WIDTH_OPTIONS) %>
|
|
87
|
+
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
|
88
|
+
def initialize(tag: TAG_DEFAULT, width: WIDTH_DEFAULT, **system_arguments)
|
|
89
|
+
@width = fetch_or_fallback(WIDTH_OPTIONS, width, WIDTH_DEFAULT)
|
|
90
|
+
|
|
91
|
+
@system_arguments = system_arguments
|
|
92
|
+
@system_arguments[:tag] =
|
|
93
|
+
fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
|
|
94
|
+
@system_arguments[:classes] = merge_classes(
|
|
95
|
+
'pulse-col-[2_/_span_2]',
|
|
96
|
+
system_arguments[:classes]
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def call
|
|
101
|
+
render(Pulse::BaseComponent.new(**@system_arguments)) do
|
|
102
|
+
if @width == :full
|
|
103
|
+
content
|
|
104
|
+
else
|
|
105
|
+
render(
|
|
106
|
+
Pulse::BaseComponent.new(
|
|
107
|
+
tag: :div,
|
|
108
|
+
classes: "pulse-mx-auto Layout-main-centered-#{@width}"
|
|
109
|
+
)
|
|
110
|
+
) do
|
|
111
|
+
render(Pulse::BaseComponent.new(tag: :div, container: @width)) do
|
|
112
|
+
content
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# The layout's sidebar content.
|
|
121
|
+
class Sidebar < Pulse::Component
|
|
122
|
+
TAG_DEFAULT = :div
|
|
123
|
+
TAG_OPTIONS = [TAG_DEFAULT, :aside, :nav, :section].freeze
|
|
124
|
+
|
|
125
|
+
def initialize(tag: TAG_DEFAULT, **system_arguments)
|
|
126
|
+
@system_arguments = system_arguments
|
|
127
|
+
|
|
128
|
+
@system_arguments[:tag] =
|
|
129
|
+
fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
|
|
130
|
+
@system_arguments[:classes] = merge_classes(
|
|
131
|
+
'pulse-col-[1]',
|
|
132
|
+
@system_arguments[:classes]
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def call
|
|
137
|
+
render(Pulse::BaseComponent.new(**@system_arguments)) { content }
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pulse
|
|
4
|
+
# Use `Link` for navigating from one page to another.
|
|
5
|
+
# `Link` styles anchor tags with default styling and hover
|
|
6
|
+
# text-decoration.
|
|
7
|
+
class Link < Pulse::Component
|
|
8
|
+
DEFAULT_SCHEME = :tertiary
|
|
9
|
+
SCHEME_MAPPINGS = {
|
|
10
|
+
primary: 'pulse-text-primary hover:pulse-text-primary',
|
|
11
|
+
secondary: 'pulse-text-secondary hover:pulse-text-secondary',
|
|
12
|
+
tertiary: 'pulse-text-tertiary hover:pulse-text-tertiary',
|
|
13
|
+
reversed: 'pulse-text-gray-300 hover:pulse-text-gray-300 ' \
|
|
14
|
+
'focus:pulse-text-gray-300'
|
|
15
|
+
}.freeze
|
|
16
|
+
SCHEME_OPTIONS = SCHEME_MAPPINGS.keys.freeze
|
|
17
|
+
|
|
18
|
+
renders_one :leading_visual, types: {
|
|
19
|
+
icon: lambda { |**options|
|
|
20
|
+
Pulse::Icon.new(**options)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def initialize(href: nil, scheme: DEFAULT_SCHEME, bold: false,
|
|
25
|
+
underline: true, condition: true, **options)
|
|
26
|
+
@condition = condition
|
|
27
|
+
@options = options
|
|
28
|
+
@options[:tag] = condition ? :a : :span
|
|
29
|
+
@options[:href] = href if condition
|
|
30
|
+
@options[:classes] = merge_classes(
|
|
31
|
+
SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_MAPPINGS.keys, scheme,
|
|
32
|
+
DEFAULT_SCHEME)],
|
|
33
|
+
@options[:classes],
|
|
34
|
+
'pulse-font-bold': bold,
|
|
35
|
+
'pulse-underline hover:pulse-no-underline': condition && underline
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def before_render
|
|
40
|
+
if @options[:href].nil? && @condition && !Rails.env.production?
|
|
41
|
+
raise ArgumentError, 'href is required'
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
return unless leading_visual
|
|
45
|
+
|
|
46
|
+
@options[:classes] = class_names(
|
|
47
|
+
@options[:classes],
|
|
48
|
+
'pulse-flex pulse-items-center pulse-gap-1.5'
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
= turbo_frame_tag 'pulse_modal' do
|
|
2
|
+
= render Pulse::BaseComponent.new(**@system_arguments) do
|
|
3
|
+
- unless auto_close
|
|
4
|
+
div class="pulse-flex pulse-items-center pulse-justify-center pulse-min-h-screen pulse-p-6 pulse-box-border"
|
|
5
|
+
/! bg overlay
|
|
6
|
+
div{
|
|
7
|
+
data-pulse--modal-target="wrapper" data-action="#{close_on_overlay_click ? 'click->pulse--modal#close' : ''}" aria-hidden="true"
|
|
8
|
+
data-transition-enter="pulse-ease-out pulse-duration-300"
|
|
9
|
+
data-transition-enter-start="pulse-opacity-0"
|
|
10
|
+
data-transition-enter-end="pulse-opacity-100"
|
|
11
|
+
data-transition-leave="pulse-ease-in pulse-duration-200"
|
|
12
|
+
data-transition-leave-start="pulse-opacity-100"
|
|
13
|
+
data-transition-leave-end="pulse-opacity-0"
|
|
14
|
+
class="pulse-fixed pulse-inset-0 pulse-bg-neutral-700/75 pulse-transition-opacity" }
|
|
15
|
+
|
|
16
|
+
/! modal
|
|
17
|
+
div{
|
|
18
|
+
data-pulse--modal-target="body"
|
|
19
|
+
data-transition-enter="pulse-ease-out pulse-duration-300"
|
|
20
|
+
data-transition-enter-start="pulse-opacity-0 pulse-translate-y-4 sm:pulse-translate-y-0 sm:pulse-scale-95"
|
|
21
|
+
data-transition-enter-end="pulse-opacity-100 pulse-translate-y-0 sm:pulse-scale-100"
|
|
22
|
+
data-transition-leave="pulse-ease-in pulse-duration-200"
|
|
23
|
+
data-transition-leave-start="pulse-opacity-100 pulse-translate-y-0 sm:pulse-scale-100"
|
|
24
|
+
data-transition-leave-end="pulse-opacity-0 pulse-translate-y-4 sm:pulse-translate-y-0 sm:pulse-scale-95"
|
|
25
|
+
class="pulse-relative pulse-z-50 pulse-bg-white pulse-shadow-xl pulse-rounded-lg pulse-transition-all #{modal_classes}"
|
|
26
|
+
role="dialog"
|
|
27
|
+
aria-modal="true"}
|
|
28
|
+
|
|
29
|
+
/! header
|
|
30
|
+
div class="pulse-flex pulse-items-center pulse-justify-between pulse-gap-4 pulse-p-4 md:pulse-p-5 pulse-border-b"
|
|
31
|
+
- if title?
|
|
32
|
+
= render Pulse::Text.new(type: :h4, el_tag: :h2, classes: 'pulse-tracking-tight pulse-text-gray pulse-truncate')
|
|
33
|
+
= title
|
|
34
|
+
|
|
35
|
+
- if close_button
|
|
36
|
+
button{
|
|
37
|
+
class="pulse-ms-auto pulse-inline-flex pulse-items-center pulse-justify-center pulse-w-10 pulse-h-7 pulse-bg-transparent pulse-border-none pulse-text-gray"
|
|
38
|
+
data-action="pulse--modal#close"
|
|
39
|
+
aria-label="Close Modal"}
|
|
40
|
+
|
|
41
|
+
= render Pulse::Icon.new(icon: :close, width: 16, height: 16)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
/! body
|
|
45
|
+
div class="pulse-p-4 md:pulse-p-5 #{'pulse-mb-4' unless footer}"
|
|
46
|
+
= content
|
|
47
|
+
|
|
48
|
+
/! footer
|
|
49
|
+
- if footer
|
|
50
|
+
div class="pulse-flex pulse-items-center pulse-p-4 md:pulse-p-5 pulse-border-t pulse-border-gray-300"
|
|
51
|
+
= footer
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pulse
|
|
4
|
+
# Renders a modal component targetable by turbo frame
|
|
5
|
+
class Modal < Pulse::Component
|
|
6
|
+
include Turbo::FramesHelper
|
|
7
|
+
|
|
8
|
+
renders_one :title
|
|
9
|
+
renders_one :footer
|
|
10
|
+
|
|
11
|
+
DEFAULT_SIZE = :md
|
|
12
|
+
SIZE_MAPPINGS = {
|
|
13
|
+
sm: 'pulse-max-w-md',
|
|
14
|
+
md: 'pulse-max-w-2xl',
|
|
15
|
+
lg: 'pulse-max-w-4xl',
|
|
16
|
+
xl: 'pulse-max-w-5xl',
|
|
17
|
+
xxl: 'pulse-max-w-6xl'
|
|
18
|
+
}.freeze
|
|
19
|
+
SIZE_OPTIONS = SIZE_MAPPINGS.keys.freeze
|
|
20
|
+
|
|
21
|
+
def initialize(size: DEFAULT_SIZE, close_button: true,
|
|
22
|
+
close_on_esc: true, close_on_overlay_click: true,
|
|
23
|
+
close_on_submit: true, auto_close: false, **system_arguments)
|
|
24
|
+
@size = fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)
|
|
25
|
+
@system_arguments = system_arguments
|
|
26
|
+
@modal_classes = merge_classes(
|
|
27
|
+
'pulse-w-full',
|
|
28
|
+
SIZE_MAPPINGS[@size],
|
|
29
|
+
@system_arguments.delete(:classes)
|
|
30
|
+
)
|
|
31
|
+
@close_button = close_button
|
|
32
|
+
@close_on_esc = close_on_esc
|
|
33
|
+
@close_on_overlay_click = close_on_overlay_click
|
|
34
|
+
@close_on_submit = close_on_submit
|
|
35
|
+
@auto_close = auto_close
|
|
36
|
+
|
|
37
|
+
@system_arguments[:'aria-labelledby'] = 'modal-title'
|
|
38
|
+
@system_arguments[:'aria-modal'] = true
|
|
39
|
+
@system_arguments[:classes] = 'pulse-fixed pulse-z-9999 pulse-inset-0 ' \
|
|
40
|
+
'pulse-overflow-y-auto'
|
|
41
|
+
@system_arguments[:data] = data_attributes
|
|
42
|
+
@system_arguments[:role] = 'dialog'
|
|
43
|
+
@system_arguments[:tabindex] = 0
|
|
44
|
+
@system_arguments[:tag] = :div
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
attr_reader :modal_classes, :close_button, :close_on_esc,
|
|
50
|
+
:close_on_overlay_click, :close_on_submit, :auto_close
|
|
51
|
+
|
|
52
|
+
def data_attributes
|
|
53
|
+
merge_attributes(
|
|
54
|
+
@system_arguments[:data],
|
|
55
|
+
{
|
|
56
|
+
controller: 'pulse--modal',
|
|
57
|
+
'pulse--modal-close-on-esc-value': close_on_esc,
|
|
58
|
+
'pulse--modal-close-on-submit-value': close_on_submit,
|
|
59
|
+
'pulse--modal-auto-close-value': auto_close
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
import { enter, leave } from "el-transition"
|
|
3
|
+
|
|
4
|
+
// Connects to data-controller="pulse--modal"
|
|
5
|
+
export default class extends Controller {
|
|
6
|
+
static targets = ["wrapper", "body"]
|
|
7
|
+
static values = {
|
|
8
|
+
closeOnEsc: { type: Boolean, default: true },
|
|
9
|
+
closeOnSubmit: { type: Boolean, default: true },
|
|
10
|
+
autoClose: { type: Boolean, default: false },
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
connect() {
|
|
14
|
+
if (!this.autoCloseValue) {
|
|
15
|
+
document.addEventListener("keydown", this.handleKeyDown)
|
|
16
|
+
|
|
17
|
+
if (this.closeOnSubmitValue) {
|
|
18
|
+
document.addEventListener("turbo:submit-end", this.handleSubmit)
|
|
19
|
+
}
|
|
20
|
+
this.lastFocusedElement = null
|
|
21
|
+
this.open()
|
|
22
|
+
} else {
|
|
23
|
+
this.autoClose()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
disconnect() {
|
|
28
|
+
document.removeEventListener("keydown", this.handleKeyDown)
|
|
29
|
+
|
|
30
|
+
if (this.closeOnSubmitValue) {
|
|
31
|
+
document.removeEventListener("turbo:submit-end", this.handleSubmit)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
handleKeyDown = e => {
|
|
36
|
+
if (this.closeOnEscValue && e.key === "Escape") {
|
|
37
|
+
e.stopPropagation()
|
|
38
|
+
this.close()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
open() {
|
|
43
|
+
this.lastFocusedElement = document.activeElement
|
|
44
|
+
enter(this.wrapperTarget)
|
|
45
|
+
enter(this.bodyTarget)
|
|
46
|
+
document.body.classList.add("pulse-overflow-hidden")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
close(e) {
|
|
50
|
+
leave(this.wrapperTarget)
|
|
51
|
+
leave(this.bodyTarget).then(() => {
|
|
52
|
+
// Remove the modal element after the fade out so it doesn't blanket the
|
|
53
|
+
// screen
|
|
54
|
+
this.element.remove()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
document.body.classList.remove("pulse-overflow-hidden")
|
|
58
|
+
|
|
59
|
+
// Return focus to the last focused element
|
|
60
|
+
if (this.lastFocusedElement) this.lastFocusedElement.focus()
|
|
61
|
+
|
|
62
|
+
// Remove src reference from parent frame element
|
|
63
|
+
// Without this, turbo won't re-open the modal on subsequent clicks
|
|
64
|
+
this.element.closest("turbo-frame").src = undefined
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
autoClose(e) {
|
|
68
|
+
this.element.remove()
|
|
69
|
+
document.body.classList.remove("pulse-overflow-hidden")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
handleSubmit = e => {
|
|
73
|
+
if (e.detail.success) {
|
|
74
|
+
this.close()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/! components/pulse/nav_link
|
|
2
|
+
= render Pulse::BaseComponent.new(**@system_arguments) do
|
|
3
|
+
- if @variant == :desktop
|
|
4
|
+
= active_link_to @path, active: @active_mode,
|
|
5
|
+
class_active: 'pulse-text-white hover:pulse-text-white hover:pulse-no-underline pulse-px-3 pulse-py-2 pulse-font-medium pulse-relative pulse-group pulse-is-active',
|
|
6
|
+
class_inactive: 'pulse-text-white hover:pulse-text-white hover:pulse-no-underline pulse-px-3 pulse-py-2 pulse-font-medium pulse-relative pulse-group' do
|
|
7
|
+
= @label
|
|
8
|
+
span class="pulse-absolute -pulse-bottom-0.5 pulse-left-1/2 pulse-w-0 pulse-h-0.5 pulse-bg-gray-300 group-hover:pulse-w-1/2 group-hover:pulse-transition-all pulse-duration-200"
|
|
9
|
+
span class="pulse-absolute -pulse-bottom-0.5 pulse-right-1/2 pulse-w-0 pulse-h-0.5 pulse-bg-gray-300 group-hover:pulse-w-1/2 group-hover:pulse-transition-all pulse-duration-200"
|
|
10
|
+
span class="pulse-absolute -pulse-bottom-0.5 pulse-start-0 pulse-w-full pulse-h-0.5 pulse-bg-primary pulse-hidden group-[.pulse-is-active]:pulse-block"
|
|
11
|
+
- else
|
|
12
|
+
= active_link_to @path, active: @active_mode,
|
|
13
|
+
class_active: 'pulse-text-primary-800 hover:pulse-no-underline pulse-block pulse-px-3 pulse-py-2',
|
|
14
|
+
class_inactive: 'pulse-text-gray hover:pulse-no-underline pulse-block pulse-px-3 pulse-py-2',
|
|
15
|
+
data: { action: 'dropdown#toggle' } do
|
|
16
|
+
= @label
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pulse
|
|
4
|
+
# Links in navbars
|
|
5
|
+
class NavLink < Pulse::Component
|
|
6
|
+
DEFAULT_VARIANT = :desktop
|
|
7
|
+
VARIANT_MAPPINGS = {
|
|
8
|
+
desktop: 'pulse-px-3 pulse-py-2',
|
|
9
|
+
mobile: 'pulse-px-3 pulse-py-2'
|
|
10
|
+
}.freeze
|
|
11
|
+
VARIANT_OPTIONS = VARIANT_MAPPINGS.keys.freeze
|
|
12
|
+
|
|
13
|
+
delegate :active_link_to, to: :helpers
|
|
14
|
+
|
|
15
|
+
def initialize(label:, path:, active_mode: :inclusive, variant: :desktop,
|
|
16
|
+
**system_arguments)
|
|
17
|
+
@label = label
|
|
18
|
+
@path = path
|
|
19
|
+
@active_mode = active_mode
|
|
20
|
+
@variant = variant
|
|
21
|
+
@system_arguments = system_arguments
|
|
22
|
+
@system_arguments[:tag] ||= :div
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|