diff --git a/modules/edw_paragraphs_carousel/components/slider-item/slider-item.css b/modules/edw_paragraphs_carousel/components/slider-item/slider-item.css index 449a0e0..eb26119 100644 --- a/modules/edw_paragraphs_carousel/components/slider-item/slider-item.css +++ b/modules/edw_paragraphs_carousel/components/slider-item/slider-item.css @@ -17,6 +17,9 @@ .carousel-item--default .slide-item__media .field-media { height: 100%; } +.carousel-item--default .slide-item__media .field-media .contextual-region { + height: 100%; +} .carousel-item--default .slide-item__media img { z-index: -2; -o-object-fit: cover; @@ -24,11 +27,6 @@ width: 100%; height: 100%; } -.carousel-item--default .slide-item__media:before { - content: ""; - background: rgba(0, 0, 0, 0.5); - z-index: -1; -} .carousel-item--default .w-content { max-width: var(--container-mw); margin-inline: auto; @@ -51,3 +49,12 @@ .carousel-item--default .field-link { margin-top: 1.25rem; } +.slider:not(.full-width) .carousel-item--default { + padding-top: 0; +} +.slider:not(.full-width) .carousel-item--default .slide-item__media:before { + content: unset; +} +.slider:not(.full-width) .carousel-item--default .w-content { + display: none; +} \ No newline at end of file diff --git a/modules/edw_paragraphs_carousel/components/slider/slider.component.yml b/modules/edw_paragraphs_carousel/components/slider/slider.component.yml index 28d45ab..8385d59 100644 --- a/modules/edw_paragraphs_carousel/components/slider/slider.component.yml +++ b/modules/edw_paragraphs_carousel/components/slider/slider.component.yml @@ -36,6 +36,21 @@ props: title: Autoplay speed description: Autoplay speed in ms. default: true + slides_to_show: + type: integer + title: Slides to show + description: Number of slides to show, default -> 1. + default: 1 + slides_to_scroll: + type: integer + title: Slides to scroll + description: Number of slides to scroll, default -> 1. + default: 1 + extra_options: + type: string + title: Extra options + description: 'Extra options in JSON format, e.g., {"centerMode": true, "centerPadding": "60px"}.' + default: '' slider_classes: type: array @@ -49,6 +64,7 @@ props: title: Attributes description: A list of HTML attributes for the slider + slots: slide_slot_main: title: Main @@ -58,4 +74,3 @@ libraryOverrides: dependencies: - edw_paragraphs_carousel/carousel - core/once - diff --git a/modules/edw_paragraphs_carousel/components/slider/slider.css b/modules/edw_paragraphs_carousel/components/slider/slider.css index 4e37c7b..d71b6bc 100644 --- a/modules/edw_paragraphs_carousel/components/slider/slider.css +++ b/modules/edw_paragraphs_carousel/components/slider/slider.css @@ -139,3 +139,7 @@ } } } + +.slider:not(.full-width) .slick-slide { + height: 100%; +} \ No newline at end of file diff --git a/modules/edw_paragraphs_carousel/components/slider/slider.js b/modules/edw_paragraphs_carousel/components/slider/slider.js index a3dfa75..956139b 100644 --- a/modules/edw_paragraphs_carousel/components/slider/slider.js +++ b/modules/edw_paragraphs_carousel/components/slider/slider.js @@ -6,21 +6,40 @@ (function ($, Drupal, once) { Drupal.behaviors.carousel = { attach: function (context, settings) { + function safeJSONParse(str, fallback = {}) { + try { + return JSON.parse(str); + } catch (e) { + console.warn("Invalid JSON in data-extra-options:", str); + return fallback; + } + } once('carousel', '.slider', context).forEach(function (carousel) { const dots = JSON.parse(carousel.getAttribute('data-dots')); const arrows = JSON.parse(carousel.getAttribute('data-arrows')); const infinite = JSON.parse(carousel.getAttribute('data-infinite')); const fade = JSON.parse(carousel.getAttribute('data-fade')); const autoplay = JSON.parse(carousel.getAttribute('data-autoplay')); - const autoplaySpeed = JSON.parse(carousel.getAttribute('data-autoplay-speed')); + const slidesToShow = parseInt(carousel.getAttribute('data-slides-to-show'), 10); + const slidesToScroll = parseInt(carousel.getAttribute('data-slides-to-scroll'), 10); + const options = carousel.getAttribute('data-extra-options') + ? safeJSONParse(carousel.getAttribute('data-extra-options')) + : {}; - $('.slider').slick({ + + Object.assign(options, { dots: dots, autoplay: autoplay, - autoplaySpeed: parseInt(autoplaySpeed, 10), infinite: infinite, fade: fade, - arrows: arrows + arrows: arrows, + slidesToShow: slidesToShow, + slidesToScroll: slidesToScroll, + }); + + + $(carousel).not('.slick-initialized').slick({ + ...options, }); }); } diff --git a/modules/edw_paragraphs_carousel/components/slider/slider.twig b/modules/edw_paragraphs_carousel/components/slider/slider.twig index 6e5af0a..38cb2fb 100644 --- a/modules/edw_paragraphs_carousel/components/slider/slider.twig +++ b/modules/edw_paragraphs_carousel/components/slider/slider.twig @@ -38,6 +38,10 @@ {% set infinite = infinite ? 'true' : 'false' %} {% set fade = fade ? 'true' : 'false' %} +{% set slides_to_show = slides_to_show ? slides_to_show : 1 %} +{% set slides_to_scroll = slides_to_scroll ? slides_to_scroll : 1 %} +{% set banner = banner is not defined ? 'false' : (banner ? 'true' : 'false') %} +{% set extra_options = extra_options is not defined ? '' : extra_options %} {# Create attributres #} {% set slider_attributes = slider_attributes ?: create_attribute() %} @@ -48,6 +52,10 @@ 'full', ]|merge(slider_classes ?: []) %} +{% if slides_to_show == 1 %} + {% set slider_classes = slider_classes|merge(['full-width']) %} +{% endif %} + {# Add extra test #} {% set slider_attributes = slider_attributes.setAttribute('data-dots', dots) %} {% set slider_attributes = slider_attributes.setAttribute('data-infinite', infinite) %} @@ -55,11 +63,16 @@ {% set slider_attributes = slider_attributes.setAttribute('data-fade', fade) %} {% set slider_attributes = slider_attributes.setAttribute('data-autoplay', autoplay) %} {% set slider_attributes = slider_attributes.setAttribute('data-autoplay-speed', autoplaySpeed) %} +{% set slider_attributes = slider_attributes.setAttribute('data-slides-to-show', slides_to_show) %} +{% set slider_attributes = slider_attributes.setAttribute('data-slides-to-scroll', slides_to_scroll) %} +{% if extra_options %} + {% set slider_attributes = slider_attributes.setAttribute('data-extra-options', extra_options) %} +{% endif %} + +{# Render component #} -
- - {% block slide_slot_main %} - {{ content }} - {% endblock %} -
+ + {% block slide_slot_main %} + {{ content|without('field_dots', 'field_fade', 'field_autoplay', 'field_slides_to_show', 'field_slides_to_scroll', 'field_infinite', 'field_arrows', 'field_full_width', 'field_extra_options') }} + {% endblock %} diff --git a/modules/edw_paragraphs_carousel/config/install/core.entity_form_display.paragraph.edw_carousel.default.yml b/modules/edw_paragraphs_carousel/config/install/core.entity_form_display.paragraph.edw_carousel.default.yml index e64541e..1bea563 100644 --- a/modules/edw_paragraphs_carousel/config/install/core.entity_form_display.paragraph.edw_carousel.default.yml +++ b/modules/edw_paragraphs_carousel/config/install/core.entity_form_display.paragraph.edw_carousel.default.yml @@ -2,39 +2,175 @@ langcode: en status: true dependencies: config: + - field.field.paragraph.edw_carousel.field_arrows + - field.field.paragraph.edw_carousel.field_autoplay + - field.field.paragraph.edw_carousel.field_dots + - field.field.paragraph.edw_carousel.field_extra_options + - field.field.paragraph.edw_carousel.field_fade + - field.field.paragraph.edw_carousel.field_full_width + - field.field.paragraph.edw_carousel.field_infinite + - field.field.paragraph.edw_carousel.field_paragraphs + - field.field.paragraph.edw_carousel.field_slides_to_scroll + - field.field.paragraph.edw_carousel.field_slides_to_show - paragraphs.paragraphs_type.edw_carousel module: + - field_group + - field_layout + - layout_discovery - paragraphs +third_party_settings: + field_layout: + id: layout_onecol + settings: + label: '' + field_group: + group_tabs: + children: + - group_items + - group_settings + label: Tabs + region: content + parent_name: '' + weight: 0 + format_type: tabs + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + direction: horizontal + width_breakpoint: 640 + group_items: + children: + - field_paragraphs + label: Items + region: content + parent_name: group_tabs + weight: 3 + format_type: tab + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + formatter: open + description: '' + required_fields: true + group_settings: + children: + - field_full_width + - field_dots + - field_arrows + - field_slides_to_show + - field_fade + - field_infinite + - field_autoplay + - field_slides_to_scroll + - field_extra_options + label: Settings + region: content + parent_name: group_tabs + weight: 4 + format_type: tab + format_settings: + classes: '' + show_empty_fields: false + id: '' + label_as_html: false + formatter: closed + description: '' + required_fields: true +_core: + default_config_hash: Kkj8Hn5VPqIurDa1-w12X9nOIXVSpAak0BA6qpIxSzY id: paragraph.edw_carousel.default targetEntityType: paragraph bundle: edw_carousel mode: default content: + field_arrows: + type: boolean_checkbox + weight: 4 + region: content + settings: + display_label: true + third_party_settings: { } + field_autoplay: + type: boolean_checkbox + weight: 8 + region: content + settings: + display_label: true + third_party_settings: { } + field_dots: + type: boolean_checkbox + weight: 3 + region: content + settings: + display_label: true + third_party_settings: { } + field_extra_options: + type: string_textarea + weight: 10 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_fade: + type: boolean_checkbox + weight: 6 + region: content + settings: + display_label: true + third_party_settings: { } field_full_width: type: boolean_checkbox - weight: 0 + weight: 2 + region: content + settings: + display_label: true + third_party_settings: { } + field_infinite: + type: boolean_checkbox + weight: 7 region: content settings: display_label: true third_party_settings: { } field_paragraphs: type: paragraphs - weight: 0 + weight: 1 region: content settings: title: Paragraph title_plural: Paragraphs edit_mode: closed closed_mode: summary - autocollapse: none + autocollapse: all closed_mode_threshold: 0 - add_mode: dropdown + add_mode: button form_display_mode: default default_paragraph_type: edw_carousel_item features: + add_above: '0' collapse_edit_all: collapse_edit_all + convert: '0' duplicate: duplicate third_party_settings: { } + field_slides_to_scroll: + type: number + weight: 9 + region: content + settings: + placeholder: '' + third_party_settings: { } + field_slides_to_show: + type: number + weight: 5 + region: content + settings: + placeholder: '' + third_party_settings: { } hidden: created: true status: true diff --git a/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_carousel.default.yml b/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_carousel.default.yml index badf010..b9bdea7 100644 --- a/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_carousel.default.yml +++ b/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_carousel.default.yml @@ -2,14 +2,106 @@ langcode: en status: true dependencies: config: + - field.field.paragraph.edw_carousel.field_arrows + - field.field.paragraph.edw_carousel.field_autoplay + - field.field.paragraph.edw_carousel.field_dots + - field.field.paragraph.edw_carousel.field_extra_options + - field.field.paragraph.edw_carousel.field_fade + - field.field.paragraph.edw_carousel.field_full_width + - field.field.paragraph.edw_carousel.field_infinite + - field.field.paragraph.edw_carousel.field_paragraphs + - field.field.paragraph.edw_carousel.field_slides_to_scroll + - field.field.paragraph.edw_carousel.field_slides_to_show - paragraphs.paragraphs_type.edw_carousel module: - entity_reference_revisions + - sdc_display +third_party_settings: + sdc_display: + enabled: false + component: + machine_name: '' + mappings: + static: + props: { } + slots: { } + dynamic: + props: { } + slots: { } +_core: + default_config_hash: kyUy7i1rS3zGaL6TFshBj8ZPW14CM9z_3Xt2Ou0xXyM id: paragraph.edw_carousel.default targetEntityType: paragraph bundle: edw_carousel mode: default content: + field_arrows: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 2 + region: content + field_autoplay: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 6 + region: content + field_dots: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 1 + region: content + field_extra_options: + type: basic_string + label: above + settings: { } + third_party_settings: { } + weight: 8 + region: content + field_fade: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 4 + region: content + field_full_width: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 9 + region: content + field_infinite: + type: boolean + label: above + settings: + format: default + format_custom_false: '' + format_custom_true: '' + third_party_settings: { } + weight: 5 + region: content field_paragraphs: type: entity_reference_revisions_entity_view label: hidden @@ -19,5 +111,23 @@ content: third_party_settings: { } weight: 0 region: content + field_slides_to_scroll: + type: number_integer + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + weight: 7 + region: content + field_slides_to_show: + type: number_integer + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + weight: 3 + region: content hidden: - field_full_width: true + search_api_excerpt: true diff --git a/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_slider.default.yml b/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_slider.default.yml new file mode 100644 index 0000000..adcc6fc --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/core.entity_view_display.paragraph.edw_slider.default.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + config: + - field.field.paragraph.edw_slider.field_paragraphs + - field.field.paragraph.edw_slider.field_title + - paragraphs.paragraphs_type.edw_slider + module: + - entity_reference_revisions + - sdc_display +third_party_settings: + sdc_display: + enabled: false + component: + machine_name: '' + mappings: + static: + props: { } + slots: { } + dynamic: + props: { } + slots: { } +id: paragraph.edw_slider.default +targetEntityType: paragraph +bundle: edw_slider +mode: default +content: + field_paragraphs: + type: entity_reference_revisions_entity_view + label: above + settings: + view_mode: default + link: '' + third_party_settings: { } + weight: 1 + region: content + field_title: + type: string + label: hidden + settings: + link_to_entity: false + third_party_settings: { } + weight: 0 + region: content +hidden: + search_api_excerpt: true diff --git a/modules/edw_paragraphs_carousel/config/optional/field.field.paragraph.edw_carousel.field_full_width.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_arrows.yml similarity index 67% rename from modules/edw_paragraphs_carousel/config/optional/field.field.paragraph.edw_carousel.field_full_width.yml rename to modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_arrows.yml index 470bc2b..d650ea5 100644 --- a/modules/edw_paragraphs_carousel/config/optional/field.field.paragraph.edw_carousel.field_full_width.yml +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_arrows.yml @@ -2,13 +2,13 @@ langcode: en status: true dependencies: config: - - field.storage.paragraph.field_full_width + - field.storage.paragraph.field_arrows - paragraphs.paragraphs_type.edw_carousel -id: paragraph.edw_carousel.field_full_width -field_name: field_full_width +id: paragraph.edw_carousel.field_arrows +field_name: field_arrows entity_type: paragraph bundle: edw_carousel -label: 'Display as full width' +label: Arrows description: '' required: false translatable: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_autoplay.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_autoplay.yml new file mode 100644 index 0000000..2c37328 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_autoplay.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_autoplay + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_autoplay +field_name: field_autoplay +entity_type: paragraph +bundle: edw_carousel +label: Autoplay +description: '' +required: false +translatable: false +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_dots.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_dots.yml new file mode 100644 index 0000000..10416ab --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_dots.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_dots + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_dots +field_name: field_dots +entity_type: paragraph +bundle: edw_carousel +label: Dots +description: '' +required: false +translatable: false +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_extra_options.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_extra_options.yml new file mode 100644 index 0000000..9aa6b4b --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_extra_options.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_extra_options + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_extra_options +field_name: field_extra_options +entity_type: paragraph +bundle: edw_carousel +label: 'Extra options' +description: 'See https://kenwheeler.github.io/slick/ for documentation. Needs to be valid JSON.' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string_long diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_fade.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_fade.yml new file mode 100644 index 0000000..5f23cc6 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_fade.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_fade + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_fade +field_name: field_fade +entity_type: paragraph +bundle: edw_carousel +label: Fade +description: '' +required: false +translatable: false +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_infinite.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_infinite.yml new file mode 100644 index 0000000..696f1df --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_infinite.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_infinite + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_infinite +field_name: field_infinite +entity_type: paragraph +bundle: edw_carousel +label: Infinite +description: '' +required: false +translatable: false +default_value: + - + value: 0 +default_value_callback: '' +settings: + on_label: 'On' + off_label: 'Off' +field_type: boolean diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_scroll.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_scroll.yml new file mode 100644 index 0000000..769a0a8 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_scroll.yml @@ -0,0 +1,24 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_slides_to_scroll + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_slides_to_scroll +field_name: field_slides_to_scroll +entity_type: paragraph +bundle: edw_carousel +label: 'Slides to scroll' +description: '' +required: false +translatable: false +default_value: + - + value: 1 +default_value_callback: '' +settings: + min: 1 + max: 10 + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_show.yml b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_show.yml new file mode 100644 index 0000000..8e1bdc2 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.field.paragraph.edw_carousel.field_slides_to_show.yml @@ -0,0 +1,24 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.paragraph.field_slides_to_show + - paragraphs.paragraphs_type.edw_carousel +id: paragraph.edw_carousel.field_slides_to_show +field_name: field_slides_to_show +entity_type: paragraph +bundle: edw_carousel +label: 'Slides to show' +description: '' +required: false +translatable: false +default_value: + - + value: 1 +default_value_callback: '' +settings: + min: 1 + max: 10 + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_arrows.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_arrows.yml new file mode 100644 index 0000000..aff92f5 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_arrows.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_arrows +field_name: field_arrows +entity_type: paragraph +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_autoplay.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_autoplay.yml new file mode 100644 index 0000000..1257a7f --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_autoplay.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_autoplay +field_name: field_autoplay +entity_type: paragraph +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_dots.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_dots.yml new file mode 100644 index 0000000..bf7a657 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_dots.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_dots +field_name: field_dots +entity_type: paragraph +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_extra_options.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_extra_options.yml new file mode 100644 index 0000000..968e1b5 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_extra_options.yml @@ -0,0 +1,18 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_extra_options +field_name: field_extra_options +entity_type: paragraph +type: string_long +settings: + case_sensitive: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_fade.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_fade.yml new file mode 100644 index 0000000..d27b925 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_fade.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_fade +field_name: field_fade +entity_type: paragraph +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_infinite.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_infinite.yml new file mode 100644 index 0000000..efc2876 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_infinite.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_infinite +field_name: field_infinite +entity_type: paragraph +type: boolean +settings: { } +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_scroll.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_scroll.yml new file mode 100644 index 0000000..a4e1f32 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_scroll.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_slides_to_scroll +field_name: field_slides_to_scroll +entity_type: paragraph +type: integer +settings: + unsigned: false + size: normal +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_show.yml b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_show.yml new file mode 100644 index 0000000..f69ad61 --- /dev/null +++ b/modules/edw_paragraphs_carousel/config/install/field.storage.paragraph.field_slides_to_show.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - paragraphs +id: paragraph.field_slides_to_show +field_name: field_slides_to_show +entity_type: paragraph +type: integer +settings: + unsigned: false + size: normal +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.install b/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.install new file mode 100644 index 0000000..1666536 --- /dev/null +++ b/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.install @@ -0,0 +1,13 @@ +installDefaultConfig('module', 'edw_paragraphs_carousel'); +} diff --git a/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.module b/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.module index 5972bd3..fe05f1b 100644 --- a/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.module +++ b/modules/edw_paragraphs_carousel/edw_paragraphs_carousel.module @@ -5,7 +5,10 @@ * EDW Paragraphs Carousel module. */ +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\FieldableEntityInterface; /** * Implements hook_theme(). @@ -38,3 +41,89 @@ function edw_paragraphs_carousel_entity_bundle_field_info_alter(&$fields, Entity } } } + +/** + * Implements hook_entity_presave(). + */ +function edw_paragraphs_carousel_paragraph_presave(EntityInterface $entity) { + if ($entity->bundle() !== 'edw_carousel') { + return; + } + + if ($entity instanceof FieldableEntityInterface && $entity->hasField('field_extra_options') && !$entity->get('field_extra_options')->isEmpty()) { + $value = $entity->get('field_extra_options')->value; + + $value = trim($value); + $decoded = json_decode($value, TRUE); + if (json_last_error() !== JSON_ERROR_NONE) { + throw new EntityStorageException( + 'The field Extra Options must contain valid JSON. Error: ' . json_last_error_msg() + ); + } + + \Drupal::logger('edw_paragraphs_carousel')->notice('presave {s}', ['s' => print_r($decoded, TRUE)]); + if (is_array($decoded) && array_values($decoded) === $decoded) { + throw new EntityStorageException( + 'The JSON must be an object (enclosed in {}).' + ); + } + + _edw_paragraphs_carousel_validate_slick_options($decoded, ''); + } +} + +/** + * Recursively validate slick options. + * + * @param array $options + * The options to validate. + * @param string $path + * The current path in the options (for error messages). + * + * @throws \Drupal\Core\Entity\EntityStorageException + * Thrown when validation fails. + */ +function _edw_paragraphs_carousel_validate_slick_options(array $options, string $path) { + $booleanKeys = ['dots', 'infinite', 'autoplay', 'arrows', 'fade']; + $integerKeys = ['autoplaySpeed', 'slidesToShow', 'slidesToScroll', 'speed', 'rows']; + $stringKeys = ['cssEase', 'easing', 'centerMode']; + + if ($path === '' && !array_key_exists('responsive', $options)) { + throw new EntityStorageException("Missing required top-level key 'responsive'."); + } + + foreach ($options as $key => $val) { + $currentPath = $path === '' ? $key : "{$path}.{$key}"; + \Drupal::logger('edw_paragraphs_carousel')->notice('key {k} val {v}', ['k' => $currentPath, 'v' => print_r($val, TRUE)]); + + if (in_array($key, $booleanKeys, TRUE)) { + if (!is_bool($val)) { + throw new EntityStorageException("Slick option '{$currentPath}' must be a boolean."); + } + } + elseif (in_array($key, $integerKeys, TRUE)) { + if (!is_int($val)) { + throw new EntityStorageException("Slick option '{$currentPath}' must be an integer."); + } + } + elseif (in_array($key, $stringKeys, TRUE)) { + if (!is_string($val)) { + throw new EntityStorageException("Slick option '{$currentPath}' must be a string."); + } + } + elseif ($key === 'responsive') { + if (!is_array($val)) { + throw new EntityStorageException("Slick option '{$currentPath}' must be an array."); + } + foreach ($val as $index => $item) { + if (!isset($item['breakpoint'], $item['settings']) || !is_int($item['breakpoint']) || !is_array($item['settings'])) { + throw new EntityStorageException("Each {$currentPath}[{$index}] must have an integer 'breakpoint' and an object 'settings'."); + } + _edw_paragraphs_carousel_validate_slick_options($item['settings'], "{$currentPath}[{$index}].settings"); + } + } + else { + throw new EntityStorageException("Unknown slick option '{$currentPath}'."); + } + } +} diff --git a/modules/edw_paragraphs_carousel/templates/paragraph--edw-carousel.html.twig b/modules/edw_paragraphs_carousel/templates/paragraph--edw-carousel.html.twig index de83372..91fb0e4 100644 --- a/modules/edw_paragraphs_carousel/templates/paragraph--edw-carousel.html.twig +++ b/modules/edw_paragraphs_carousel/templates/paragraph--edw-carousel.html.twig @@ -8,5 +8,15 @@ {% extends "paragraph.html.twig" %} {% block content %} - {% include 'edw_paragraphs_carousel:slider' with {} %} + {% include 'edw_paragraphs_carousel:slider' with { + dots: paragraph.field_dots.value == 1, + fade: paragraph.field_fade.value == 1, + autoplay: paragraph.field_autoplay.value == 1, + slides_to_show: paragraph.field_slides_to_show.value * 1, + slides_to_scroll: paragraph.field_slides_to_scroll.value * 1, + infinite: paragraph.field_infinite.value == 1, + arrows: paragraph.field_arrows.value == 1, + banner: paragraph.field_full_width.value == 1, + extra_options: paragraph.field_extra_options.value, + } %} {% endblock %}