feat: implement custom CSS generator, improve code editor support, and add media picker and HTML tag management tools
This commit is contained in:
@@ -25,13 +25,13 @@
|
||||
}
|
||||
/*[[${themeModCustomCss}]]*/
|
||||
</style>
|
||||
<!-- Dedicated Page Custom CSS -->
|
||||
<style th:if="${page != null and page.customCss != null and !page.customCss.empty}" th:utext="${page.customCss}"></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Render Editor.js Blocks -->
|
||||
<div layout:fragment="content">
|
||||
<!-- Dedicated Page Custom CSS -->
|
||||
<style th:if="${page != null and page.customCss != null and !page.customCss.empty}" th:utext="${page.customCss}"></style>
|
||||
<th:block th:each="block : ${blocks}">
|
||||
<div
|
||||
th:class="${(block.data != null and block.data['stretched'] == true) or (block.data != null and block.data['stretched'] == null and block['stretched'] == true) ? 'sis-fullwidth-breakout' : ''}"
|
||||
@@ -387,8 +387,38 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</th:block>
|
||||
|
||||
<!-- 17. Dedicated Hover Cards Block -->
|
||||
<th:block th:if="${block['type'] == 'hovercard' or block['type'] == 'hover-card' or block['type'] == 'hoverCard'}">
|
||||
<div th:id="${block.data['globalId'] != null and !#strings.isEmpty(block.data['globalId']) ? block.data['globalId'] : null}"
|
||||
th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card-v2-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : '')) : ('sis-hover-card-section ' + (block.data['globalClass'] != null ? block.data['globalClass'] : ''))}">
|
||||
<div class="container py-4">
|
||||
<div class="row align-items-center">
|
||||
<th:block th:each="item, iterStat : ${block.data['items']}">
|
||||
<div th:class="${block.data['cols'] == 1 ? 'col-12 mb-4' : (block.data['cols'] == 2 ? 'col-md-6 col-12 mb-4' : (block.data['cols'] == 3 ? 'col-lg-4 col-md-6 col-12 mb-4' : (block.data['cols'] == 6 ? 'col-lg-2 col-md-4 col-6 mb-4' : 'col-lg-3 col-md-6 col-12 mb-4')))}">
|
||||
<div th:class="${(block.data['styleVariant'] == 'v2' or (block.data['globalClass'] != null and block.data['globalClass'].contains('v2'))) ? ('sis-hover-card sis-hover-card-v2 ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : '')) : ('sis-hover-card ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : ''))}">
|
||||
<div class="w-full flex flex-col items-center justify-center transition-all duration-500">
|
||||
<div class="sis-hover-card__icon" th:if="${item['imageUrl'] != null and !#strings.isEmpty(item['imageUrl'])}">
|
||||
<img th:src="${item['imageUrl']}" class="sis-hover-card__img-main" th:alt="${item['title']}" />
|
||||
<img th:if="${item['hoverImageUrl'] != null and !#strings.isEmpty(item['hoverImageUrl'])}" th:src="${item['hoverImageUrl']}" class="sis-hover-card__img-hover" th:alt="${item['title']}" />
|
||||
</div>
|
||||
<h3 class="sis-hover-card__title" th:utext="${item['title']}">Title</h3>
|
||||
</div>
|
||||
<p class="sis-hover-card__desc" th:utext="${item['description']}">Description</p>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<!-- 18. Custom HTML Tag Block (Opening or Closing Tag) -->
|
||||
<th:block th:if="${block['type'] == 'tag'}">
|
||||
<th:block th:if="${block.data['rawHtmlTag'] != null and !#strings.isEmpty(block.data['rawHtmlTag'])}"
|
||||
th:utext="${block.data['rawHtmlTag']}"></th:block>
|
||||
</th:block>
|
||||
|
||||
<!-- Shared Cell Content Renderer Fragment -->
|
||||
<th:block th:fragment="renderCell(type, i, blockData)">
|
||||
@@ -479,6 +509,37 @@
|
||||
</section>
|
||||
</th:block>
|
||||
|
||||
<!-- Nested Plugin: hovercard -->
|
||||
<th:block th:if="${(type == 'hovercard' or type == 'hover-card' or type == 'hoverCard') and blockData != null and blockData['col' + i] != null and blockData['col' + i] != '' and blockData['col' + i]['items'] != null}">
|
||||
<div th:id="${blockData['col' + i]['globalId'] != null and !#strings.isEmpty(blockData['col' + i]['globalId']) ? blockData['col' + i]['globalId'] : null}"
|
||||
th:class="${(blockData['col' + i]['styleVariant'] == 'v2' or (blockData['col' + i]['globalClass'] != null and blockData['col' + i]['globalClass'].contains('v2'))) ? ('sis-hover-card-v2-section ' + (blockData['col' + i]['globalClass'] != null ? blockData['col' + i]['globalClass'] : '')) : ('sis-hover-card-section ' + (blockData['col' + i]['globalClass'] != null ? blockData['col' + i]['globalClass'] : ''))}">
|
||||
<div class="container-fluid p-0">
|
||||
<div class="row align-items-center">
|
||||
<th:block th:each="item, iterStat : ${blockData['col' + i]['items']}">
|
||||
<div th:class="${blockData['col' + i]['cols'] == 1 ? 'col-12 mb-4' : (blockData['col' + i]['cols'] == 2 ? 'col-md-6 col-12 mb-4' : (blockData['col' + i]['cols'] == 3 ? 'col-lg-4 col-md-6 col-12 mb-4' : (blockData['col' + i]['cols'] == 6 ? 'col-lg-2 col-md-4 col-6 mb-4' : 'col-lg-3 col-md-6 col-12 mb-4')))}">
|
||||
<div th:class="${(blockData['col' + i]['styleVariant'] == 'v2' or (blockData['col' + i]['globalClass'] != null and blockData['col' + i]['globalClass'].contains('v2'))) ? ('sis-hover-card sis-hover-card-v2 ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : '')) : ('sis-hover-card ' + ((item['active'] == true or (item['active'] == null and iterStat.first)) ? 'active' : ''))}">
|
||||
<div class="w-full flex flex-col items-center justify-center transition-all duration-500">
|
||||
<div class="sis-hover-card__icon" th:if="${item['imageUrl'] != null and !#strings.isEmpty(item['imageUrl'])}">
|
||||
<img th:src="${item['imageUrl']}" class="sis-hover-card__img-main" th:alt="${item['title']}" />
|
||||
<img th:if="${item['hoverImageUrl'] != null and !#strings.isEmpty(item['hoverImageUrl'])}" th:src="${item['hoverImageUrl']}" class="sis-hover-card__img-hover" th:alt="${item['title']}" />
|
||||
</div>
|
||||
<h3 class="sis-hover-card__title" th:utext="${item['title']}">Title</h3>
|
||||
</div>
|
||||
<p class="sis-hover-card__desc" th:utext="${item['description']}">Description</p>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<!-- Nested Plugin: tag -->
|
||||
<th:block th:if="${type == 'tag' and blockData != null and blockData['col' + i] != null}">
|
||||
<th:block th:if="${blockData['col' + i]['rawHtmlTag'] != null and !#strings.isEmpty(blockData['col' + i]['rawHtmlTag'])}"
|
||||
th:utext="${blockData['col' + i]['rawHtmlTag']}"></th:block>
|
||||
</th:block>
|
||||
|
||||
<!-- Nested Plugin: grid (Recursive) -->
|
||||
<th:block th:if="${type == 'grid' and blockData != null and blockData['col' + i] != null and blockData['col' + i] != '' and blockData['col' + i]['cols'] != null}">
|
||||
<div th:id="${blockData['col' + i]['globalId'] != null and !#strings.isEmpty(blockData['col' + i]['globalId']) ? blockData['col' + i]['globalId'] : null}"
|
||||
@@ -630,6 +691,19 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Interactive Hover Cards — Mouseenter transfers active class to hovered card
|
||||
document.querySelectorAll('.sis-hover-card').forEach(function (card) {
|
||||
card.addEventListener('mouseenter', function () {
|
||||
var parentRow = card.closest('.row');
|
||||
if (parentRow) {
|
||||
parentRow.querySelectorAll('.sis-hover-card').forEach(function (c) {
|
||||
c.classList.remove('active');
|
||||
});
|
||||
}
|
||||
card.classList.add('active');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- Dedicated Page Custom JS -->
|
||||
|
||||
Reference in New Issue
Block a user