feat: add image gallery content element with configurable columns and backend preview
This commit is contained in:
@@ -9,7 +9,7 @@ RTE {
|
|||||||
TCEFORM {
|
TCEFORM {
|
||||||
tt_content {
|
tt_content {
|
||||||
CType {
|
CType {
|
||||||
keepItems = cloonar_text,cloonar_textimage,cloonar_hero,cloonar_cards,form_formframework
|
keepItems = cloonar_text,cloonar_textimage,cloonar_hero,cloonar_cards,cloonar_imagegallery,form_formframework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
name: cloonar/imagegallery
|
||||||
|
typeName: cloonar_imagegallery
|
||||||
|
group: default
|
||||||
|
prefixFields: false
|
||||||
|
fields:
|
||||||
|
- identifier: header
|
||||||
|
useExistingField: true
|
||||||
|
- identifier: image
|
||||||
|
type: File
|
||||||
|
properties:
|
||||||
|
allowed: [jpg, jpeg, png, gif, webp]
|
||||||
|
multiple: true
|
||||||
|
useExistingField: true
|
||||||
|
- identifier: columns
|
||||||
|
type: Select
|
||||||
|
renderType: selectSingle
|
||||||
|
default: 1
|
||||||
|
items:
|
||||||
|
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.1
|
||||||
|
value: 1
|
||||||
|
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.2
|
||||||
|
value: 2
|
||||||
|
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.3
|
||||||
|
value: 3
|
||||||
|
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.5
|
||||||
|
value: 5
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
|
<file datatype="plaintext" original="labels.xlf" source-language="en" product-name="cloonar/imagegallery">
|
||||||
|
<header/>
|
||||||
|
<body>
|
||||||
|
<trans-unit id="title">
|
||||||
|
<source>Image Gallery</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="description">
|
||||||
|
<source>A gallery of images with configurable columns</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="columns.1">
|
||||||
|
<source>1 Column</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="columns.2">
|
||||||
|
<source>2 Columns</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="columns.3">
|
||||||
|
<source>3 Columns</source>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="columns.5">
|
||||||
|
<source>5 Columns</source>
|
||||||
|
</trans-unit>
|
||||||
|
</body>
|
||||||
|
</file>
|
||||||
|
</xliff>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<html
|
||||||
|
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
|
||||||
|
data-namespace-typo3-fluid="true"
|
||||||
|
>
|
||||||
|
<f:layout name="Preview"/>
|
||||||
|
|
||||||
|
<f:section name="Header">
|
||||||
|
<be:link.editRecord uid="{data.uid}" table="{data.mainType}">
|
||||||
|
<f:if condition="{data.header}">
|
||||||
|
<f:then><strong>{data.header}</strong></f:then>
|
||||||
|
</f:if>
|
||||||
|
</be:link.editRecord>
|
||||||
|
</f:section>
|
||||||
|
|
||||||
|
<f:section name="Content">
|
||||||
|
<f:if condition="{data.image}">
|
||||||
|
<div class="row">
|
||||||
|
<f:for each="{data.image}" as="image" iteration="iterator">
|
||||||
|
<f:if condition="{iterator.index} < 3">
|
||||||
|
<div class="col-4">
|
||||||
|
<f:image image="{image}" width="100" height="auto" treatIdAsReference="1" alt="Preview image" />
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
</f:for>
|
||||||
|
</div>
|
||||||
|
<f:if condition="{data.image -> f:count()} > 3">
|
||||||
|
<p>+ {f:math.subtract(a: '{data.image -> f:count()}', b: '3')} more images</p>
|
||||||
|
</f:if>
|
||||||
|
<p>
|
||||||
|
<f:switch expression="{data.columns}">
|
||||||
|
<f:case value="2">2 Columns</f:case>
|
||||||
|
<f:case value="3">3 Columns</f:case>
|
||||||
|
<f:case value="5">5 Columns</f:case>
|
||||||
|
<f:defaultCase>1 Column</f:defaultCase>
|
||||||
|
</f:switch>
|
||||||
|
</p>
|
||||||
|
</f:if>
|
||||||
|
</f:section>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<f:layout name="Default" />
|
||||||
|
<f:section name="Header"></f:section>
|
||||||
|
<f:section name="Main">
|
||||||
|
<f:if condition="{data.header}">
|
||||||
|
<h2 class="text-center mb-8">{data.header}</h2>
|
||||||
|
</f:if>
|
||||||
|
|
||||||
|
<f:if condition="{data.image}">
|
||||||
|
<f:variable name="columnClass">
|
||||||
|
<f:switch expression="{data.columns}">
|
||||||
|
<f:case value="2">md:grid-cols-2</f:case>
|
||||||
|
<f:case value="3">md:grid-cols-3</f:case>
|
||||||
|
<f:case value="5">md:grid-cols-5</f:case>
|
||||||
|
<f:defaultCase>md:grid-cols-1</f:defaultCase>
|
||||||
|
</f:switch>
|
||||||
|
</f:variable>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 {columnClass} gap-6 md:gap-8">
|
||||||
|
<f:for each="{data.image}" as="image">
|
||||||
|
<div class="relative">
|
||||||
|
<f:if condition="{image.link}">
|
||||||
|
<f:then>
|
||||||
|
<f:link.typolink parameter="{image.link}" class="block w-full h-full">
|
||||||
|
<picture class="block w-full h-full">
|
||||||
|
<source
|
||||||
|
type="image/webp"
|
||||||
|
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default', fileExtension:'webp')} 320w,
|
||||||
|
{f:uri.image(image:image, width:'768', cropVariant:'default', fileExtension:'webp')} 768w"
|
||||||
|
sizes="(max-width: 767px) 90vw, 33vw" />
|
||||||
|
<img
|
||||||
|
src="{f:uri.image(image:image, width:'768', cropVariant:'default')}"
|
||||||
|
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default')} 320w,
|
||||||
|
{f:uri.image(image:image, width:'768', cropVariant:'default')} 768w"
|
||||||
|
sizes="(max-width: 767px) 90vw, 33vw"
|
||||||
|
alt="{image.alternative}"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
|
</f:link.typolink>
|
||||||
|
</f:then>
|
||||||
|
<f:else>
|
||||||
|
<picture class="block w-full h-full">
|
||||||
|
<source
|
||||||
|
type="image/webp"
|
||||||
|
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default', fileExtension:'webp')} 320w,
|
||||||
|
{f:uri.image(image:image, width:'768', cropVariant:'default', fileExtension:'webp')} 768w"
|
||||||
|
sizes="(max-width: 767px) 90vw, 33vw" />
|
||||||
|
<img
|
||||||
|
src="{f:uri.image(image:image, width:'768', cropVariant:'default')}"
|
||||||
|
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default')} 320w,
|
||||||
|
{f:uri.image(image:image, width:'768', cropVariant:'default')} 768w"
|
||||||
|
sizes="(max-width: 767px) 90vw, 33vw"
|
||||||
|
alt="{image.alternative}"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
</picture>
|
||||||
|
</f:else>
|
||||||
|
</f:if>
|
||||||
|
</div>
|
||||||
|
</f:for>
|
||||||
|
</div>
|
||||||
|
</f:if>
|
||||||
|
</f:section>
|
||||||
Reference in New Issue
Block a user