maglevcms 3.0.0.beta2 → 3.0.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/README.md +16 -53
- data/Rakefile +3 -1
- data/app/assets/builds/maglev/tailwind.css +681 -11670
- data/app/assets/config/maglev_manifest.js +3 -2
- data/app/assets/javascripts/maglev/client/dom-operations.js +5 -5
- data/app/assets/javascripts/maglev/client/iframe-decorator.js +24 -0
- data/app/assets/javascripts/maglev/client/incoming-messages.js +13 -3
- data/app/assets/javascripts/maglev/client/index.js +3 -2
- data/app/assets/javascripts/maglev/client/utils.js +22 -0
- data/app/assets/javascripts/maglev/editor/controllers/app/forms/section_form_controller.js +4 -3
- data/app/assets/javascripts/maglev/editor/controllers/app/forms/style_form_controller.js +2 -1
- data/app/assets/javascripts/maglev/editor/controllers/app/page_preview_controller.js +96 -5
- data/app/assets/javascripts/maglev/editor/controllers/app/preview_notification_center_controller.js +105 -23
- data/app/assets/javascripts/maglev/editor/controllers/app/setting_controller.js +3 -2
- data/app/assets/javascripts/maglev/editor/controllers/shared/copy_to_clipboard_controller.js +2 -1
- data/app/assets/javascripts/maglev/editor/controllers/shared/submit_button_controller.js +29 -5
- data/app/assets/javascripts/maglev/editor/controllers/utils.js +38 -0
- data/app/assets/javascripts/maglev/editor/index.js +5 -44
- data/app/assets/javascripts/maglev/editor/patches/page_renderer_patch.js +47 -0
- data/app/assets/javascripts/maglev/editor/patches/turbo_delayed_streams.js +35 -0
- data/app/assets/javascripts/maglev/editor/patches/turbo_stream_patch.js +50 -0
- data/app/assets/stylesheets/maglev/application.css +0 -2
- data/app/assets/stylesheets/maglev/tailwind.css.erb +11 -2
- data/app/components/maglev/content/link.rb +1 -1
- data/app/components/maglev/editor/settings/link/link_component.rb +7 -1
- data/app/components/maglev/section_component.rb +11 -1
- data/app/components/maglev/uikit/app_layout/sidebar/link_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/sidebar/link_component.rb +35 -5
- data/app/components/maglev/uikit/app_layout/sidebar_component.html.erb +3 -4
- data/app/components/maglev/uikit/app_layout/topbar/logo_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar/page_info_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar_component.html.erb +1 -1
- data/app/components/maglev/uikit/app_layout/topbar_component.rb +1 -1
- data/app/components/maglev/uikit/button_group_component/button_group_component.html.erb +5 -0
- data/app/components/maglev/uikit/button_group_component.rb +70 -0
- data/app/components/maglev/uikit/device_toggler_component.rb +10 -1
- data/app/components/maglev/uikit/dropdown_component/dropdown_component.html.erb +2 -2
- data/app/components/maglev/uikit/dropdown_component/dropdown_controller.js +6 -1
- data/app/components/maglev/uikit/dropdown_component.rb +6 -1
- data/app/components/maglev/uikit/form/color_field_component.html.erb +1 -1
- data/app/components/maglev/uikit/form/combobox_component.html.erb +1 -0
- data/app/components/maglev/uikit/form/link_component.rb +5 -1
- data/app/components/maglev/uikit/form/richtext_controller.js +5 -4
- data/app/components/maglev/uikit/form/search_form_component.html.erb +1 -0
- data/app/components/maglev/uikit/icon_component.rb +3 -0
- data/app/components/maglev/uikit/image_library/uploader_controller.js +3 -2
- data/app/components/maglev/uikit/list/list_item_component.html.erb +36 -19
- data/app/components/maglev/uikit/list/list_item_component.rb +19 -5
- data/app/components/maglev/uikit/locale_switcher_component/locale_switcher_component.html.erb +6 -10
- data/app/components/maglev/uikit/menu_dropdown_component/menu_dropdown_component.html.erb +6 -2
- data/app/components/maglev/uikit/menu_dropdown_component.rb +244 -7
- data/app/components/maglev/uikit/page_actions_dropdown_component/page_actions_dropdown_component.html.erb +39 -46
- data/app/components/maglev/uikit/pagination_component/pagination_component.html.erb +9 -12
- data/app/components/maglev/uikit/pagination_component.rb +6 -1
- data/app/components/maglev/uikit/section_toolbar/bottom_component.html.erb +1 -1
- data/app/components/maglev/uikit/tabs_component/tabs_component.html.erb +7 -4
- data/app/components/maglev/uikit/tabs_component.rb +23 -4
- data/app/components/maglev/uikit/well/simple_well_component.html.erb +15 -0
- data/app/components/maglev/uikit/well/simple_well_component.rb +13 -0
- data/app/controllers/concerns/maglev/editor/errors_concern.rb +9 -9
- data/app/controllers/concerns/maglev/editor/preview_urls_concern.rb +32 -0
- data/app/controllers/concerns/maglev/editor/turbo_concern.rb +29 -0
- data/app/controllers/concerns/maglev/errors_concern.rb +17 -0
- data/app/controllers/concerns/maglev/flash_i18n_concern.rb +1 -0
- data/app/controllers/maglev/application_controller.rb +2 -1
- data/app/controllers/maglev/assets/active_storage_proxy_controller.rb +2 -1
- data/app/controllers/maglev/editor/assets_controller.rb +1 -1
- data/app/controllers/maglev/editor/base_controller.rb +6 -32
- data/app/controllers/maglev/editor/pages/clone_controller.rb +22 -0
- data/app/controllers/maglev/editor/pages/discard_draft_controller.rb +17 -0
- data/app/controllers/maglev/editor/pages_controller.rb +26 -7
- data/app/controllers/maglev/editor/section_blocks_controller.rb +13 -9
- data/app/controllers/maglev/editor/sections_controller.rb +26 -7
- data/app/controllers/maglev/published_page_preview_controller.rb +4 -0
- data/app/controllers/maglev/site_controller.rb +15 -0
- data/app/helpers/maglev/application_helper.rb +26 -8
- data/app/helpers/maglev/editor/section_blocks_helper.rb +2 -2
- data/app/models/maglev/page/publishable_concern.rb +69 -0
- data/app/models/maglev/page.rb +3 -0
- data/app/models/maglev/section/block.rb +4 -0
- data/app/models/maglev/section/content_concern.rb +3 -1
- data/app/models/maglev/section.rb +21 -1
- data/app/models/maglev/sections_content_store.rb +1 -3
- data/app/models/maglev/site.rb +5 -0
- data/app/services/concerns/maglev/content/helpers_concern.rb +5 -8
- data/app/services/maglev/app_container.rb +4 -2
- data/app/services/maglev/discard_page_draft_service.rb +45 -0
- data/app/services/maglev/fetch_section_screenshot_url.rb +12 -1
- data/app/services/maglev/fetch_site.rb +3 -1
- data/app/services/maglev/get_published_page_sections_service.rb +1 -1
- data/app/services/maglev/has_unpublished_changes.rb +21 -0
- data/app/services/maglev/publish_service.rb +18 -2
- data/app/views/layouts/maglev/editor/_sidebar.html.erb +8 -2
- data/app/views/layouts/maglev/editor/_topbar.html.erb +6 -23
- data/app/views/layouts/maglev/editor/application.html.erb +6 -0
- data/app/views/layouts/maglev/editor/topbar/_page_info.html.erb +11 -0
- data/app/views/layouts/maglev/editor/topbar/_publish_button.html.erb +35 -0
- data/app/views/maglev/editor/assets/index.html.erb +1 -0
- data/app/views/maglev/editor/home/index.html.erb +1 -1
- data/app/views/maglev/editor/links/edit/_email.html.erb +1 -1
- data/app/views/maglev/editor/links/edit/_url.html.erb +1 -1
- data/app/views/maglev/editor/pages/_list.html.erb +25 -21
- data/app/views/maglev/editor/pages/_preview.html.erb +6 -6
- data/app/views/maglev/editor/pages/_preview_empty_message.html.erb +13 -10
- data/app/views/maglev/editor/pages/discard_draft/create.turbo_stream.erb +16 -0
- data/app/views/maglev/editor/pages/index.html.erb +8 -1
- data/app/views/maglev/editor/publication/create.turbo_stream.erb +3 -1
- data/app/views/maglev/editor/section_blocks/_form.html.erb +5 -13
- data/app/views/maglev/editor/section_blocks/_form_with_tabs.html.erb +15 -0
- data/app/views/maglev/editor/section_blocks/_new.html.erb +1 -1
- data/app/views/maglev/editor/section_blocks/edit.html.erb +2 -2
- data/app/views/maglev/editor/section_blocks/index/_list.html.erb +2 -2
- data/app/views/maglev/editor/section_blocks/index/_tree.html.erb +1 -1
- data/app/views/maglev/editor/section_blocks/update.turbo_stream.erb +9 -1
- data/app/views/maglev/editor/sections/_form.html.erb +6 -20
- data/app/views/maglev/editor/sections/_form_with_tabs.html.erb +21 -0
- data/app/views/maglev/editor/sections/_list.html.erb +1 -1
- data/app/views/maglev/editor/sections/edit.html.erb +3 -3
- data/app/views/maglev/editor/sections/index.html.erb +1 -1
- data/app/views/maglev/editor/sections/new.html.erb +18 -1
- data/app/views/maglev/editor/sections/theme/_empty_list.html.erb +3 -0
- data/app/views/maglev/editor/sections/theme/_list.html.erb +35 -0
- data/app/views/maglev/editor/sections/theme/_screenshot_placeholder.html.erb +6 -0
- data/app/views/maglev/editor/sections/theme/_search.html.erb +22 -0
- data/app/views/maglev/editor/sections/update.turbo_stream.erb +9 -1
- data/app/views/maglev/editor/shared/_button_label.html.erb +4 -4
- data/app/views/maglev/editor/style/edit.html.erb +1 -0
- data/app/views/maglev/errors/site_not_found.html.erb +33 -0
- data/config/editor_importmap.rb +16 -13
- data/config/locales/editor.ar.yml +12 -4
- data/config/locales/editor.en.yml +31 -23
- data/config/locales/editor.es.yml +12 -4
- data/config/locales/editor.fr.yml +12 -4
- data/config/locales/editor.pt-BR.yml +12 -4
- data/config/routes/maglev/assets.rb +4 -0
- data/config/routes/maglev/editor.rb +38 -0
- data/config/routes/maglev/preview.rb +8 -0
- data/config/routes/maglev/public_preview.rb +6 -0
- data/config/routes.rb +8 -44
- data/db/migrate/20211013210954_translate_section_content.rb +1 -0
- data/db/migrate/20251116171603_add_published_at_to_sites_and_pages.rb +6 -0
- data/db/migrate/20260114112058_add_published_payload_to_pages.rb +14 -0
- data/exe/tailwind-cli +1 -1
- data/lib/generators/maglev/install_generator.rb +9 -7
- data/lib/generators/maglev/templates/install/config/initializers/maglev.rb +10 -3
- data/lib/maglev/active_storage/serving_blob.rb +29 -0
- data/lib/maglev/active_storage.rb +2 -0
- data/lib/maglev/config.rb +22 -3
- data/lib/maglev/engine.rb +15 -10
- data/lib/maglev/errors.rb +1 -0
- data/lib/maglev/version.rb +1 -1
- data/lib/maglev.rb +18 -3
- data/lib/tasks/db_test_all.rake +290 -0
- data/lib/tasks/maglev/tailwindcss.rake +1 -0
- metadata +55 -19
- data/app/controllers/maglev/editor/page_clone_controller.rb +0 -20
- data/app/views/maglev/editor/sections/_theme_list.html.erb +0 -32
- /data/vendor/javascript/{@floating-ui--core.js → maglev/@floating-ui--core.js} +0 -0
- /data/vendor/javascript/{@floating-ui--dom.js → maglev/@floating-ui--dom.js} +0 -0
- /data/vendor/javascript/{@floating-ui--utils--dom.js → maglev/@floating-ui--utils--dom.js} +0 -0
- /data/vendor/javascript/{@floating-ui--utils.js → maglev/@floating-ui--utils.js} +0 -0
- /data/vendor/javascript/{@hotwired--stimulus.js → maglev/@hotwired--stimulus.js} +0 -0
- /data/vendor/javascript/{@hotwired--turbo-rails.js → maglev/@hotwired--turbo-rails.js} +0 -0
- /data/vendor/javascript/{@hotwired--turbo.js → maglev/@hotwired--turbo.js} +0 -0
- /data/vendor/javascript/{@rails--actioncable--src.js → maglev/@rails--actioncable--src.js} +0 -0
- /data/vendor/javascript/{@rails--request.js.js → maglev/@rails--request.js.js} +0 -0
- /data/vendor/javascript/{@shopify--draggable.js → maglev/@shopify--draggable.js} +0 -0
- /data/vendor/javascript/{el-transition.js → maglev/el-transition.js} +0 -0
- /data/vendor/javascript/{stimulus-use.js → maglev/stimulus-use.js} +0 -0
- /data/vendor/javascript/{tiptap.bundle.js → maglev/tiptap.bundle.js} +0 -0
|
@@ -47,7 +47,12 @@ export default class extends Controller {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
disconnect() {
|
|
50
|
-
this.cleanup()
|
|
50
|
+
this.cleanup() // clean up the observer for the floating element
|
|
51
|
+
|
|
52
|
+
// fix issue: https://github.com/stimulus-use/stimulus-use/issues/500
|
|
53
|
+
this.enter = null
|
|
54
|
+
this.leave = null
|
|
55
|
+
this.toggleTransition = null
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
clickOutside() {
|
|
@@ -7,9 +7,14 @@ module Maglev
|
|
|
7
7
|
|
|
8
8
|
attr_reader :placement
|
|
9
9
|
|
|
10
|
-
def initialize(placement: 'bottom-start')
|
|
10
|
+
def initialize(placement: 'bottom-start', wrapper_classes: nil)
|
|
11
|
+
@wrapper_classes = wrapper_classes
|
|
11
12
|
@placement = placement
|
|
12
13
|
end
|
|
14
|
+
|
|
15
|
+
def wrapper_classes
|
|
16
|
+
helpers.class_names('relative', @wrapper_classes)
|
|
17
|
+
end
|
|
13
18
|
end
|
|
14
19
|
end
|
|
15
20
|
end
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
placeholder: placeholder || t('maglev.uikit.form.combobox.placeholder'),
|
|
34
34
|
value: selected_label,
|
|
35
35
|
aria: { controls: 'options', expanded: 'false' },
|
|
36
|
+
autocomplete: 'off',
|
|
36
37
|
data: {
|
|
37
38
|
'uikit-form-combobox-target' => 'input',
|
|
38
39
|
'uikit-dropdown-target' => 'button',
|
|
@@ -59,7 +59,7 @@ module Maglev
|
|
|
59
59
|
|
|
60
60
|
def self.link_type_component(input_name:, value:, path:)
|
|
61
61
|
# Default to url if the link type is not found (shouldn't happen)
|
|
62
|
-
klass = link_type_klasses_map.fetch(value[:link_type]
|
|
62
|
+
klass = link_type_klasses_map.fetch(value[:link_type]&.to_sym, default_link_type_klass)
|
|
63
63
|
|
|
64
64
|
return unless klass
|
|
65
65
|
|
|
@@ -74,6 +74,10 @@ module Maglev
|
|
|
74
74
|
static_page: Maglev::Uikit::Form::Link::StaticPageLinkComponent
|
|
75
75
|
}
|
|
76
76
|
end
|
|
77
|
+
|
|
78
|
+
def self.default_link_type_klass
|
|
79
|
+
Maglev::Uikit::Form::Link::UrlLinkComponent
|
|
80
|
+
end
|
|
77
81
|
end
|
|
78
82
|
end
|
|
79
83
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
|
2
2
|
import { Editor, Document, Text, Paragraph, Heading, Blockquote, CodeBlock, History, Bold, Italic, Underline, Strike, Superscript, HardBreak, Link, ListItem, BulletList, OrderedList } from 'tiptap'
|
|
3
|
+
import { log } from 'maglev-controllers/utils'
|
|
3
4
|
|
|
4
5
|
const MaglevLink = Link.extend({
|
|
5
6
|
addAttributes() {
|
|
@@ -205,11 +206,11 @@ export default class extends Controller {
|
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
openLinkModal(event) {
|
|
208
|
-
|
|
209
|
+
log('toggleLink', event)
|
|
209
210
|
const url = new URL(this.editLinkPathValue, window.location.origin)
|
|
210
211
|
const link = this.editor.getAttributes('link')
|
|
211
212
|
|
|
212
|
-
|
|
213
|
+
log('toggleLink,build link from', link)
|
|
213
214
|
|
|
214
215
|
url.searchParams.set('input_name', this.inputNameValue)
|
|
215
216
|
url.searchParams.set('link[href]', link.href ?? '')
|
|
@@ -230,8 +231,8 @@ export default class extends Controller {
|
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
setLink(event) {
|
|
233
|
-
const link = JSON.parse(event.detail)
|
|
234
|
-
|
|
234
|
+
const link = typeof event.detail === 'string' ? JSON.parse(event.detail) : event.detail
|
|
235
|
+
log('setLink, link=', link)
|
|
235
236
|
this.editor.commands.setLink({
|
|
236
237
|
href: link.href,
|
|
237
238
|
target: link.open_new_window ? '_blank' : '',
|
|
@@ -68,6 +68,7 @@ module Maglev
|
|
|
68
68
|
arrow_down: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="fill-current"><path fill="none" d="M0 0h24v24H0z"></path><path d="m12 13.172 4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"></path></svg>',
|
|
69
69
|
arrow_left: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M10.8284 12.0007L15.7782 16.9504L14.364 18.3646L8 12.0007L14.364 5.63672L15.7782 7.05093L10.8284 12.0007Z"></path></svg>',
|
|
70
70
|
arrow_right: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M13.1717 12.0007L8.22192 7.05093L9.63614 5.63672L16.0001 12.0007L9.63614 18.3646L8.22192 16.9504L13.1717 12.0007Z"></path></svg>',
|
|
71
|
+
arrow_right_long: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M1.99974 13.0001L1.9996 11.0002L18.1715 11.0002L14.2218 7.05044L15.636 5.63623L22 12.0002L15.636 18.3642L14.2218 16.9499L18.1716 13.0002L1.99974 13.0001Z"></path></svg>',
|
|
71
72
|
|
|
72
73
|
image: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M4.828 21l-.02.02-.021-.02H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H4.828zM20 15V5H4v14L14 9l6 6zm0 2.828l-6-6L6.828 19H20v-1.172zM8 11a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" fill="#000"/></svg>',
|
|
73
74
|
|
|
@@ -131,6 +132,8 @@ module Maglev
|
|
|
131
132
|
|
|
132
133
|
logout: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 22a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v3h-2V4H6v16h12v-2h2v3a1 1 0 0 1-1 1H5zm13-6v-3h-7v-2h7V8l5 4-5 4z"/></svg>',
|
|
133
134
|
|
|
135
|
+
history: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12H4C4 16.4183 7.58172 20 12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C9.25022 4 6.82447 5.38734 5.38451 7.50024L8 7.5V9.5H2V3.5H4L3.99989 5.99918C5.82434 3.57075 8.72873 2 12 2ZM13 7L12.9998 11.585L16.2426 14.8284L14.8284 16.2426L10.9998 12.413L11 7H13Z"></path></svg>',
|
|
136
|
+
|
|
134
137
|
# Spinners
|
|
135
138
|
spinner: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M18.364 5.63604L16.9497 7.05025C15.683 5.7835 13.933 5 12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19C15.866 19 19 15.866 19 12H21C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C14.4853 3 16.7353 4.00736 18.364 5.63604Z"></path></svg>'
|
|
136
139
|
}.with_indifferent_access.freeze
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus'
|
|
2
2
|
import { FetchRequest } from '@rails/request.js'
|
|
3
|
+
import { log } from 'maglev-controllers/utils'
|
|
3
4
|
|
|
4
5
|
export default class extends Controller {
|
|
5
6
|
static targets = ['button', 'fileInput']
|
|
@@ -11,7 +12,7 @@ export default class extends Controller {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
connect() {
|
|
14
|
-
|
|
15
|
+
log('UploaderController connected')
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
openFileDialog() {
|
|
@@ -64,7 +65,7 @@ export default class extends Controller {
|
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
reloadFrameTag() {
|
|
67
|
-
|
|
68
|
+
log('reloadFrameTag', this.refreshPathValue)
|
|
68
69
|
const frame = document.querySelector(`turbo-frame#modal-dialog`)
|
|
69
70
|
if (frame) {
|
|
70
71
|
frame.src = this.refreshPathValue
|
|
@@ -1,29 +1,48 @@
|
|
|
1
1
|
<%= tag.div(data: { sortable_target: sortable_target, item_id: id, item_index: index }) do %>
|
|
2
|
-
<%=
|
|
2
|
+
<%= content_tag(wrapper_tag_name.to_sym, class: wrapper_classes) do %>
|
|
3
|
+
<%= content if content? %>
|
|
3
4
|
|
|
4
5
|
<%= tag.div(class: 'flex items-center cursor-move', data: { sortable_target: sortable_handle }) do %>
|
|
5
6
|
<%= render Maglev::Uikit::IconComponent.new(name: "draggable") %>
|
|
6
7
|
<% end if handle? %>
|
|
7
8
|
|
|
8
9
|
<% item_body = capture do %>
|
|
9
|
-
<% if
|
|
10
|
-
<div class="
|
|
11
|
-
|
|
10
|
+
<% if icon? %>
|
|
11
|
+
<div class="grid grid-cols-[auto_1fr_auto] flex flex-1 items-center">
|
|
12
|
+
<div class="mr-2">
|
|
13
|
+
<%= icon %>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="text-gray-800 truncate"><%= title %></div>
|
|
16
|
+
<% if sub_title? %>
|
|
17
|
+
<div class="col-start-2 text-gray-500 text-xs"><%= sub_title %></div>
|
|
18
|
+
<% end %>
|
|
12
19
|
</div>
|
|
13
|
-
<%
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
<% else %>
|
|
21
|
+
<% if image? %>
|
|
22
|
+
<div class="h-8 w-8 bg-gray-400">
|
|
23
|
+
<%= image %>
|
|
24
|
+
</div>
|
|
25
|
+
<% end %>
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<div class="text-gray-500 text-xs"><%= pre_title %></div>
|
|
22
|
-
<div class="text-gray-800 truncate"><%= title %></div>
|
|
23
|
-
<% else %>
|
|
24
|
-
<div class="truncate"><%= title %></div>
|
|
27
|
+
<% if big_image? %>
|
|
28
|
+
<%= big_image %>
|
|
25
29
|
<% end %>
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
<div class="flex flex-col overflow-hidden">
|
|
32
|
+
<% if pre_title? %>
|
|
33
|
+
<div class="text-gray-500 text-xs"><%= pre_title %></div>
|
|
34
|
+
<div class="text-gray-800 truncate"><%= title %></div>
|
|
35
|
+
<% if sub_title? %>
|
|
36
|
+
<div class="text-gray-500 text-xs"><%= sub_title %></div>
|
|
37
|
+
<% end %>
|
|
38
|
+
<% else %>
|
|
39
|
+
<div class="truncate"><%= title %></div>
|
|
40
|
+
<% if sub_title? %>
|
|
41
|
+
<div class="text-gray-500 text-xs"><%= sub_title %></div>
|
|
42
|
+
<% end %>
|
|
43
|
+
<% end %>
|
|
44
|
+
</div>
|
|
45
|
+
<% end %>
|
|
27
46
|
<% end %>
|
|
28
47
|
|
|
29
48
|
<% if link? %>
|
|
@@ -41,7 +60,5 @@
|
|
|
41
60
|
<%= action %>
|
|
42
61
|
</div>
|
|
43
62
|
<% end %>
|
|
44
|
-
<% end %>
|
|
45
|
-
|
|
46
|
-
<%= content if content? %>
|
|
63
|
+
<% end %>
|
|
47
64
|
<% end %>
|
|
@@ -7,16 +7,20 @@ module Maglev
|
|
|
7
7
|
renders_one :handle
|
|
8
8
|
renders_one :image
|
|
9
9
|
renders_one :big_image
|
|
10
|
+
renders_one :icon
|
|
10
11
|
renders_one :pre_title
|
|
12
|
+
renders_one :sub_title
|
|
11
13
|
renders_one :title
|
|
12
14
|
renders_one :action
|
|
13
15
|
|
|
14
|
-
attr_reader :link, :index, :options
|
|
16
|
+
attr_reader :link, :index, :options, :variant, :wrapper_tag_name
|
|
15
17
|
|
|
16
18
|
def initialize(id: nil, link: nil, options: {})
|
|
17
19
|
@id = id
|
|
18
20
|
@link = link
|
|
21
|
+
@variant = options.fetch(:variant, :filled).to_sym
|
|
19
22
|
@custom_wrapper_classes = options[:wrapper_classes]
|
|
23
|
+
@wrapper_tag_name = options[:wrapper_tag] || :div
|
|
20
24
|
@index = options[:index]
|
|
21
25
|
@options = options
|
|
22
26
|
end
|
|
@@ -37,18 +41,28 @@ module Maglev
|
|
|
37
41
|
link[:data] || {}
|
|
38
42
|
end
|
|
39
43
|
|
|
44
|
+
# rubocop:disable Metrics/MethodLength
|
|
40
45
|
def wrapper_classes
|
|
41
46
|
class_variants(
|
|
42
|
-
base: '
|
|
43
|
-
|
|
47
|
+
base: 'rounded-md flex text-gray-800',
|
|
48
|
+
variants: {
|
|
49
|
+
variant: {
|
|
50
|
+
filled: 'bg-gray-100',
|
|
51
|
+
ghost: 'hover:bg-gray-50 transition-colors duration-200'
|
|
52
|
+
},
|
|
53
|
+
padding: { default: 'p-2', medium: 'p-3' }
|
|
54
|
+
},
|
|
55
|
+
default: { variant: :filled, padding: :default }
|
|
56
|
+
).render(variant: variant, padding: big_image? ? :medium : :default, class: @custom_wrapper_classes)
|
|
44
57
|
end
|
|
58
|
+
# rubocop:enable Metrics/MethodLength
|
|
45
59
|
|
|
46
60
|
def content_classes
|
|
47
61
|
class_variants(
|
|
48
|
-
base: 'flex flex-1
|
|
62
|
+
base: 'flex flex-1 gap-3 overflow-hidden',
|
|
49
63
|
variants: {
|
|
50
64
|
disposition: {
|
|
51
|
-
row: 'flex-row items-center',
|
|
65
|
+
row: 'flex-row items-center px-2',
|
|
52
66
|
col: 'flex-col'
|
|
53
67
|
}
|
|
54
68
|
},
|
data/app/components/maglev/uikit/locale_switcher_component/locale_switcher_component.html.erb
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
<%= render(Maglev::Uikit::MenuDropdownComponent.new) do |dropdown| %>
|
|
2
2
|
<% dropdown.with_trigger do %>
|
|
3
|
-
|
|
4
|
-
class="flex-1 h-full w-full px-6 hover:bg-gray-100 transition-colors duration-200 flex items-center focus:outline-none focus:none cursor-pointer space-x-2"
|
|
5
|
-
data-action="click->uikit-dropdown#toggle"
|
|
6
|
-
data-uikit-dropdown-target="button">
|
|
3
|
+
<%= tag.button class: helpers.maglev_button_classes(color: :secondary, class: 'space-x-2'), data: { action: 'click->uikit-dropdown#toggle', 'uikit-dropdown-target': 'button' } do %>
|
|
7
4
|
<%= render Maglev::Uikit::IconComponent.new(name: 'global') %>
|
|
8
5
|
<span class="whitespace-nowrap">
|
|
9
6
|
<%= current_locale_label %>
|
|
10
7
|
</span>
|
|
11
8
|
<%= render Maglev::Uikit::IconComponent.new(name: 'arrow_down') %>
|
|
12
|
-
|
|
9
|
+
<% end %>
|
|
13
10
|
<% end %>
|
|
14
11
|
|
|
15
12
|
<% locales.each do |locale| %>
|
|
16
|
-
<% dropdown.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<% end %>
|
|
13
|
+
<% dropdown.with_item_link_to(locale[:path], data: locale[:data_attributes]) do |menu_item| %>
|
|
14
|
+
<% menu_item.with_label_content(locale[:label]) %>
|
|
15
|
+
<% menu_item.with_icon_content('check') if locale[:value] == current_locale %>
|
|
16
|
+
<% end %>
|
|
21
17
|
<% end %>
|
|
22
18
|
<% end %>
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
<%= render Maglev::Uikit::DropdownComponent.new(placement: placement) do |component| %>
|
|
1
|
+
<%= render Maglev::Uikit::DropdownComponent.new(placement: placement, wrapper_classes: wrapper_classes) do |component| %>
|
|
2
2
|
<% component.with_trigger do %>
|
|
3
3
|
<% if trigger.present? %>
|
|
4
4
|
<%= trigger %>
|
|
5
|
+
<% elsif trigger_classes.present? && icon_name.present? %>
|
|
6
|
+
<%= button_tag class: trigger_classes, data: { action: "click->uikit-dropdown#toggle", 'uikit-dropdown-target': 'button' } do %>
|
|
7
|
+
<%= render Maglev::Uikit::IconComponent.new(name: icon_name) %>
|
|
8
|
+
<% end %>
|
|
5
9
|
<% else %>
|
|
6
10
|
<%= render Maglev::Uikit::IconButtonComponent.new(icon_name: icon_name, data: { action: "click->uikit-dropdown#toggle", 'uikit-dropdown-target': 'button' }) %>
|
|
7
11
|
<% end %>
|
|
8
12
|
<% end %>
|
|
9
13
|
|
|
10
|
-
<div class="
|
|
14
|
+
<div class="<%= list_item_classes %>">
|
|
11
15
|
<% items.each do |item| %>
|
|
12
16
|
<%= item %>
|
|
13
17
|
<% end %>
|
|
@@ -3,30 +3,267 @@
|
|
|
3
3
|
module Maglev
|
|
4
4
|
module Uikit
|
|
5
5
|
class MenuDropdownComponent < Maglev::Uikit::BaseComponent
|
|
6
|
+
module RenderPolymorphicItems
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
renders_many :items, types: {
|
|
11
|
+
button: lambda { |options = nil|
|
|
12
|
+
Maglev::Uikit::MenuDropdownComponent::ButtonItemComponent.new(options, parent: self)
|
|
13
|
+
},
|
|
14
|
+
link_to: lambda { |options = nil, html_options = nil|
|
|
15
|
+
Maglev::Uikit::MenuDropdownComponent::LinkToItemComponent.new(options, html_options, parent: self)
|
|
16
|
+
},
|
|
17
|
+
button_to: lambda { |options = nil, html_options = nil|
|
|
18
|
+
Maglev::Uikit::MenuDropdownComponent::ButtonToItemComponent.new(options, html_options, parent: self)
|
|
19
|
+
},
|
|
20
|
+
text: lambda { |options = nil|
|
|
21
|
+
Maglev::Uikit::MenuDropdownComponent::TextItemComponent.new(options, parent: self)
|
|
22
|
+
},
|
|
23
|
+
nested_menu: lambda { |placement:|
|
|
24
|
+
Maglev::Uikit::MenuDropdownComponent::NestedMenuComponent.new(placement: placement, parent: self)
|
|
25
|
+
},
|
|
26
|
+
wrapper: lambda { |options = nil|
|
|
27
|
+
Maglev::Uikit::MenuDropdownComponent::WrapperItemComponent.new(options, parent: self)
|
|
28
|
+
},
|
|
29
|
+
divider: -> { Maglev::Uikit::MenuDropdownComponent::DividerItemComponent.new(parent: self) }
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
6
34
|
renders_one :trigger
|
|
7
|
-
|
|
35
|
+
include RenderPolymorphicItems
|
|
8
36
|
|
|
9
|
-
attr_reader :icon_name, :placement
|
|
37
|
+
attr_reader :icon_name, :placement, :wrapper_classes, :trigger_classes
|
|
10
38
|
|
|
11
|
-
def initialize(icon_name: nil, placement: 'bottom-start')
|
|
39
|
+
def initialize(icon_name: nil, placement: 'bottom-start', wrapper_classes: nil, trigger_classes: nil)
|
|
12
40
|
@icon_name = icon_name
|
|
13
41
|
@placement = placement
|
|
42
|
+
@wrapper_classes = wrapper_classes
|
|
43
|
+
@trigger_classes = trigger_classes
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def list_item_classes
|
|
47
|
+
'text-gray-800 grid grid-cols-[auto_1fr_auto] min-w-[12rem] my-1'
|
|
14
48
|
end
|
|
15
49
|
|
|
50
|
+
# rubocop:disable Metrics/MethodLength
|
|
16
51
|
def item_classes(...)
|
|
17
52
|
class_variants(
|
|
18
53
|
base: %(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
54
|
+
col-span-3 grid grid-cols-subgrid
|
|
55
|
+
flex flex-1 items-center px-2 py-3 w-full mx-1 rounded-sm text-left
|
|
56
|
+
transition-colors duration-200 focus:outline-none cursor-pointer
|
|
57
|
+
),
|
|
58
|
+
variants: {
|
|
59
|
+
danger: 'text-red-600 hover:bg-red-100',
|
|
60
|
+
'!danger': 'hover:bg-gray-100',
|
|
61
|
+
subdued: 'text-gray-400'
|
|
62
|
+
},
|
|
63
|
+
defaults: { danger: false, subdued: false }
|
|
22
64
|
).render(...)
|
|
23
65
|
end
|
|
66
|
+
# rubocop:enable Metrics/MethodLength
|
|
24
67
|
|
|
25
68
|
def form_item_classes(...)
|
|
26
69
|
class_variants(
|
|
27
|
-
base:
|
|
70
|
+
base: %w[
|
|
71
|
+
col-span-3 grid grid-cols-subgrid
|
|
72
|
+
flex items-center focus:outline-none cursor-pointer
|
|
73
|
+
]
|
|
28
74
|
).render(...)
|
|
29
75
|
end
|
|
76
|
+
|
|
77
|
+
class ItemComponent < ViewComponent::Base
|
|
78
|
+
renders_one :icon
|
|
79
|
+
renders_one :label
|
|
80
|
+
renders_one :sub_label
|
|
81
|
+
renders_one :right_icon
|
|
82
|
+
|
|
83
|
+
def self.inner_content
|
|
84
|
+
<<-ERB
|
|
85
|
+
<%= render Maglev::Uikit::IconComponent.new(name: icon.to_s, size: '1.15rem', class_names: 'mr-2 shrink-0') if icon? %>
|
|
86
|
+
<span class="<%= 'col-start-2' unless icon? %> whitespace-nowrap whitespace-nowrap truncate overflow-hidden">
|
|
87
|
+
<%= label %>
|
|
88
|
+
</span>
|
|
89
|
+
<%= render Maglev::Uikit::IconComponent.new(name: 'arrow_right', size: '1.15rem', class_names: 'ml-2 shrink-0') if right_arrow? %>
|
|
90
|
+
<span class="col-start-2 whitespace-nowrap whitespace-nowrap truncate overflow-hidden text-xs text-gray-500">
|
|
91
|
+
<%= sub_label %>
|
|
92
|
+
</span>
|
|
93
|
+
ERB
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def right_arrow?
|
|
97
|
+
false
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class TextItemComponent < ItemComponent
|
|
102
|
+
attr_reader :options, :parent_component, :variant
|
|
103
|
+
|
|
104
|
+
def initialize(options = nil, parent: nil)
|
|
105
|
+
@parent_component = parent
|
|
106
|
+
@options = options || {}
|
|
107
|
+
@variant = @options.delete(:variant)
|
|
108
|
+
|
|
109
|
+
apply_parent_classes
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
erb_template <<-ERB
|
|
113
|
+
<%= tag.span(**options) do %>
|
|
114
|
+
#{inner_content}
|
|
115
|
+
<% end %>
|
|
116
|
+
ERB
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def apply_parent_classes
|
|
121
|
+
options[:class] = parent_component.item_classes(subdued: variant == 'subdued', class: options[:class])
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
class LinkToItemComponent < ItemComponent
|
|
126
|
+
attr_reader :options, :html_options, :parent_component, :variant
|
|
127
|
+
|
|
128
|
+
def initialize(options = nil, html_options = nil, parent: nil)
|
|
129
|
+
@parent_component = parent
|
|
130
|
+
@options = options
|
|
131
|
+
@html_options = html_options || {}
|
|
132
|
+
@variant = @html_options.delete(:variant)
|
|
133
|
+
|
|
134
|
+
apply_parent_classes
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
erb_template <<-ERB
|
|
138
|
+
<%= link_to options, html_options do %>
|
|
139
|
+
#{inner_content}
|
|
140
|
+
<% end %>
|
|
141
|
+
ERB
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
def apply_parent_classes
|
|
146
|
+
html_options[:class] = parent_component.item_classes(danger: variant == 'danger', class: html_options[:class])
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
class ButtonItemComponent < ItemComponent
|
|
151
|
+
attr_reader :options, :parent_component
|
|
152
|
+
|
|
153
|
+
def initialize(options = nil, parent: nil)
|
|
154
|
+
@parent_component = parent
|
|
155
|
+
@options = (options || {}).merge(type: 'button')
|
|
156
|
+
|
|
157
|
+
apply_parent_classes
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
erb_template <<-ERB
|
|
161
|
+
<%= button_tag options do %>
|
|
162
|
+
#{inner_content}
|
|
163
|
+
<% end %>
|
|
164
|
+
ERB
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
def apply_parent_classes
|
|
169
|
+
options[:class] = parent_component.item_classes(class: options[:class])
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
class ButtonToItemComponent < LinkToItemComponent
|
|
174
|
+
erb_template <<-ERB
|
|
175
|
+
<%= button_to options, html_options do %>
|
|
176
|
+
#{inner_content}
|
|
177
|
+
<% end %>
|
|
178
|
+
ERB
|
|
179
|
+
|
|
180
|
+
private
|
|
181
|
+
|
|
182
|
+
def apply_parent_classes
|
|
183
|
+
super
|
|
184
|
+
html_options[:form_class] = parent_component.form_item_classes(class: html_options[:form_class])
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
class NestedMenuComponent < ItemComponent
|
|
189
|
+
include RenderPolymorphicItems
|
|
190
|
+
|
|
191
|
+
attr_reader :placement, :parent_component
|
|
192
|
+
|
|
193
|
+
delegate :list_item_classes, :item_classes, :form_item_classes, to: :parent_component
|
|
194
|
+
|
|
195
|
+
alias wrapper_classes form_item_classes
|
|
196
|
+
|
|
197
|
+
def initialize(placement:, parent:)
|
|
198
|
+
@placement = placement
|
|
199
|
+
@parent_component = parent
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
erb_template <<-ERB
|
|
203
|
+
<%= render Maglev::Uikit::DropdownComponent.new(placement: placement, wrapper_classes: wrapper_classes) do |dropdown| %>
|
|
204
|
+
<% dropdown.with_trigger do %>
|
|
205
|
+
<%= button_tag class: item_classes, data: { action: 'click->uikit-dropdown#toggle', 'uikit-dropdown-target': 'button' } do %>
|
|
206
|
+
#{inner_content}#{' '}
|
|
207
|
+
<% end %>
|
|
208
|
+
<% end %>
|
|
209
|
+
|
|
210
|
+
<div class="<%= list_item_classes %>">
|
|
211
|
+
<% items.each do |item| %>
|
|
212
|
+
<%= item %>
|
|
213
|
+
<% end %>
|
|
214
|
+
</div>
|
|
215
|
+
<% end %>
|
|
216
|
+
ERB
|
|
217
|
+
|
|
218
|
+
def right_arrow?
|
|
219
|
+
true
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
class WrapperItemComponent < Maglev::Uikit::BaseComponent
|
|
224
|
+
include RenderPolymorphicItems
|
|
225
|
+
|
|
226
|
+
attr_reader :options, :parent_component
|
|
227
|
+
|
|
228
|
+
delegate :item_classes, :form_item_classes, to: :parent_component
|
|
229
|
+
|
|
230
|
+
def initialize(options, parent: nil)
|
|
231
|
+
@parent_component = parent
|
|
232
|
+
@options = options || {}
|
|
233
|
+
|
|
234
|
+
apply_parent_classes
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
erb_template <<-ERB
|
|
238
|
+
<%= tag.div(**options) do %>
|
|
239
|
+
<% items.each do |item| %>
|
|
240
|
+
<%= item %>
|
|
241
|
+
<% end %>
|
|
242
|
+
<% end %>
|
|
243
|
+
ERB
|
|
244
|
+
|
|
245
|
+
private
|
|
246
|
+
|
|
247
|
+
def apply_parent_classes
|
|
248
|
+
options[:class] = parent_component.form_item_classes(class: options[:class])
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
class DividerItemComponent < ItemComponent
|
|
253
|
+
attr_reader :parent_component
|
|
254
|
+
|
|
255
|
+
def initialize(parent:)
|
|
256
|
+
@parent_component = parent
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def item_classes(...)
|
|
260
|
+
parent_component.form_item_classes(class: 'border-t border-gray-200 my-1 px-0!')
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
erb_template <<-ERB
|
|
264
|
+
<%= tag.hr class: item_classes %>
|
|
265
|
+
ERB
|
|
266
|
+
end
|
|
30
267
|
end
|
|
31
268
|
end
|
|
32
269
|
end
|