[TikiWiki-commits] [Git][tikiwiki/tiki][master] [NEW] PluginLottie: Add new plugin for Lottie animations
Benoit Grégoire (@benoitg) via TikiWiki-cvs <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <6967a2258c5e6_2c1818fc283da@gitlab-sidekiq-low-urgency-cpu-bound-v2-88785c6b5-9ljfw.mail> |
Benoit Grégoire pushed to branch master at Tiki Wiki CMS Groupware / Tiki
Commits:
8bca5ba2 by Moïse Nturubika at 2026-01-14T13:54:49+00:00
[NEW] PluginLottie: Add new plugin for Lottie animations
---
* [FIX] PluginLottie: Remove redundant static variable for script loading
* [ENH] PluginLottie: Add Lottie animation plugin with local bundling
* [NEW] PluginLottie: Add new plugin for Lottie animations
See merge request tikiwiki/tiki!9333
- - - - -
7 changed files:
- + lib/wiki-plugins/wikiplugin_lottie.php
- package-lock.json
- package.json
- path_js_importmap_generator.php
- + src/js/tiki-lottie/lottie.js
- + src/js/tiki-lottie/package.json
- src/js/vite.config.mjs
Changes:
=====================================
lib/wiki-plugins/wikiplugin_lottie.php
=====================================
@@ -0,0 +1,168 @@
+<?php
+
+// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
+//
+// All Rights Reserved. See copyright.txt for details and a complete list of authors.
+// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
+
+/**
+ * Wiki Plugin: Lottie
+ *
+ * Embeds a Lottie animation in a wiki page using the dotLottie Web Component.
+ * Supports both .json (legacy) and .lottie (compressed) formats.
+ *
+ * @see https://doc.tiki.org/PluginLottie
+ * @see https://github.com/LottieFiles/dotlottie-web
+ */
+
+function wikiplugin_lottie_info()
+{
+ return [
+ 'name' => tra('Lottie'),
+ 'documentation' => 'PluginLottie',
+ 'description' => tra('Embed a Lottie animation in a page'),
+ 'prefs' => ['wikiplugin_lottie'],
+ 'iconname' => 'video',
+ 'tags' => ['basic'],
+ 'params' => [
+ 'src' => [
+ 'required' => false,
+ 'name' => tra('Source URL'),
+ 'description' => tra('URL to the Lottie animation file (.json or .lottie). Use either src or fileId.'),
+ 'filter' => 'url',
+ 'default' => '',
+ ],
+ 'fileId' => [
+ 'required' => false,
+ 'name' => tra('File ID'),
+ 'description' => tra('ID of the Lottie file in the File Gallery. Use either fileId or src.'),
+ 'filter' => 'digits',
+ 'default' => '',
+ 'profile_reference' => 'file',
+ ],
+ 'loop' => [
+ 'required' => false,
+ 'name' => tra('Loop'),
+ 'description' => tra('Loop the animation continuously.'),
+ 'filter' => 'alpha',
+ 'default' => 'y',
+ 'options' => [
+ ['text' => tra('Yes'), 'value' => 'y'],
+ ['text' => tra('No'), 'value' => 'n'],
+ ],
+ ],
+ 'autoplay' => [
+ 'required' => false,
+ 'name' => tra('Autoplay'),
+ 'description' => tra('Start animation automatically when page loads.'),
+ 'filter' => 'alpha',
+ 'default' => 'y',
+ 'options' => [
+ ['text' => tra('Yes'), 'value' => 'y'],
+ ['text' => tra('No'), 'value' => 'n'],
+ ],
+ ],
+ 'speed' => [
+ 'required' => false,
+ 'name' => tra('Speed'),
+ 'description' => tra('Playback speed multiplier (e.g., 0.5 for half speed, 2 for double speed).'),
+ 'filter' => 'text',
+ 'default' => '1',
+ ],
+ 'mode' => [
+ 'required' => false,
+ 'name' => tra('Play Mode'),
+ 'description' => tra('Animation playback mode.'),
+ 'filter' => 'alpha',
+ 'default' => 'forward',
+ 'options' => [
+ ['text' => tra('Forward'), 'value' => 'forward'],
+ ['text' => tra('Reverse'), 'value' => 'reverse'],
+ ['text' => tra('Bounce'), 'value' => 'bounce'],
+ ['text' => tra('Reverse Bounce'), 'value' => 'reverse-bounce'],
+ ],
+ 'advanced' => true,
+ ],
+ 'width' => [
+ 'required' => false,
+ 'name' => tra('Width'),
+ 'description' => tra('Width of the animation container (e.g., 300px, 50%, auto).'),
+ 'filter' => 'text',
+ 'default' => '100%',
+ ],
+ 'height' => [
+ 'required' => false,
+ 'name' => tra('Height'),
+ 'description' => tra('Height of the animation container (e.g., 300px, auto).'),
+ 'filter' => 'text',
+ 'default' => 'auto',
+ ],
+ 'background' => [
+ 'required' => false,
+ 'name' => tra('Background'),
+ 'description' => tra('Background color of the animation container (e.g., transparent, #ffffff, rgb(0,0,0)).'),
+ 'filter' => 'text',
+ 'default' => 'transparent',
+ 'advanced' => true,
+ ],
+ ],
+ ];
+}
+
+function wikiplugin_lottie($data, $params)
+{
+ global $tikilib;
+
+ // Validate: either src or fileId must be provided
+ $src = $params['src'] ?? '';
+ $fileId = $params['fileId'] ?? '';
+
+ if (empty($src) && empty($fileId)) {
+ Feedback::error(tra('Plugin Lottie error: either src or fileId parameter is required.'));
+ return '<div class="alert alert-warning">'
+ . tra('Plugin Lottie error: either src or fileId parameter is required.')
+ . '</div>';
+ }
+
+ // If fileId is provided, generate the download URL
+ if (! empty($fileId)) {
+ $src = 'tiki-download_file.php?fileId=' . (int)$fileId;
+ }
+
+ // Validate URL format for external sources
+ if (strpos($src, 'http') === 0) {
+ $src = filter_var($src, FILTER_SANITIZE_URL);
+ if (! filter_var($src, FILTER_VALIDATE_URL)) {
+ Feedback::error(tra('Plugin Lottie error: Invalid URL provided.'));
+ return '<div class="alert alert-warning">'
+ . tra('Plugin Lottie error: Invalid URL provided.')
+ . '</div>';
+ }
+ }
+
+ // Parse parameters with defaults
+ $loop = ($params['loop'] ?? 'y') === 'y';
+ $autoplay = ($params['autoplay'] ?? 'y') === 'y';
+ $speed = floatval($params['speed'] ?? 1);
+ $mode = $params['mode'] ?? 'forward';
+ $width = $params['width'] ?? '100%';
+ $height = $params['height'] ?? 'auto';
+ $background = $params['background'] ?? 'transparent';
+
+ // Build HTML output
+ $loopAttr = $loop ? 'loop' : '';
+ $autoplayAttr = $autoplay ? 'autoplay' : '';
+
+ // Generate unique ID for this animation instance
+ static $instanceCount = 0;
+ $instanceCount++;
+ $elementId = 'tiki-lottie-' . $instanceCount;
+
+ TikiLib::lib('header')->add_js_module('import "@tiki-lottie";');
+
+ $html = '<div class="tiki-lottie-container" style="width: ' . htmlspecialchars($width) . '; height: ' . htmlspecialchars($height) . '; background: ' . htmlspecialchars($background) . ';">';
+ $html .= '<dotlottie-wc id="' . $elementId . '" src="' . htmlspecialchars($src) . '" ' . $loopAttr . ' ' . $autoplayAttr . ' speed="' . htmlspecialchars($speed) . '" mode="' . htmlspecialchars($mode) . '" style="width: 100%; height: 100%;"></dotlottie-wc>';
+ $html .= '</div>';
+
+ return '~np~' . $html . '~/np~';
+}
=====================================
package-lock.json
=====================================
@@ -14,6 +14,7 @@
"src/js/jquery-tiki",
"src/js/tiki-glightbox",
"src/js/tiki-html5-qrcode",
+ "src/js/tiki-lottie",
"src/js/tiki-mermaid",
"src/js/tiki-sentry-browser",
"src/js/tiki-figlet",
@@ -2251,7 +2252,6 @@
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.0.tgz",
"integrity": "sha512-HLomZXMmrCFHSRKESF5vklAKsDY7/fsT/ZhqCu3V0UoW/Qbv8wxmO4W9bx4KnCCF2Zak4yuk+AGraK/bPmI4kA==",
- "dev": true,
"license": "BSD-3-Clause"
},
"node_modules/@lit/react": {
@@ -2268,12 +2268,27 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.1.2.tgz",
"integrity": "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A==",
- "dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.5.0"
}
},
+ "node_modules/@lottiefiles/dotlottie-wc": {
+ "version": "0.8.13",
+ "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-wc/-/dotlottie-wc-0.8.13.tgz",
+ "integrity": "sha512-Pk6ceceKBbNOEG0a5Lholo3mQyDV5SKKpq9GYGpQ0/WdF+W6O447YHhIPe4DQMRpWSSRw/x/aZE8545rwMqZlw==",
+ "license": "MIT",
+ "dependencies": {
+ "@lottiefiles/dotlottie-web": "0.60.0",
+ "lit": "^3.2.1"
+ }
+ },
+ "node_modules/@lottiefiles/dotlottie-web": {
+ "version": "0.60.0",
+ "resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-web/-/dotlottie-web-0.60.0.tgz",
+ "integrity": "sha512-AbQYmyZ8ZihCGPwjdN0e7bJ7W7yVmHG24IXn8kxyFJJNJmSJEaarpOSivu/1KoFGiw86OMmiWcLXrPs1XjT6Qw==",
+ "license": "MIT"
+ },
"node_modules/@mapbox/geojson-rewind": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
@@ -4100,7 +4115,6 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/@types/web-bluetooth": {
@@ -11430,7 +11444,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz",
"integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==",
- "dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@lit/reactive-element": "^2.1.0",
@@ -11442,7 +11455,6 @@
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz",
"integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==",
- "dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.5.0",
@@ -11454,7 +11466,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz",
"integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==",
- "dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"@types/trusted-types": "^2.0.2"
@@ -15446,6 +15457,10 @@
"resolved": "src/js/tiki-iot",
"link": true
},
+ "node_modules/tiki-lottie": {
+ "resolved": "src/js/tiki-lottie",
+ "link": true
+ },
"node_modules/tiki-mermaid": {
"resolved": "src/js/tiki-mermaid",
"link": true
@@ -17177,6 +17192,12 @@
"npm": ">=7.0.0"
}
},
+ "src/js/tiki-lottie": {
+ "version": "1.0.0",
+ "dependencies": {
+ "@lottiefiles/dotlottie-wc": "^0.8.0"
+ }
+ },
"src/js/tiki-mermaid": {
"version": "1.0.0",
"license": "ISC",
=====================================
package.json
=====================================
@@ -131,6 +131,7 @@
"src/js/jquery-tiki",
"src/js/tiki-glightbox",
"src/js/tiki-html5-qrcode",
+ "src/js/tiki-lottie",
"src/js/tiki-mermaid",
"src/js/tiki-sentry-browser",
"src/js/tiki-figlet",
=====================================
path_js_importmap_generator.php
=====================================
@@ -82,6 +82,7 @@ function generateJsImportmapScripts(bool $useBaseUrl = false)
"@jquery-tiki/validate-alt-image" => $tikiUrl . JS_ASSETS_PATH . "/jquery-tiki/validate-alt-image.js",
"@tiki-modules/sentryBrowser" => $tikiUrl . JS_ASSETS_PATH . "/tiki-sentry-browser.js",
"@mermaidPack" => $tikiUrl . JS_ASSETS_PATH . "/tiki-mermaid.js",
+ "@tiki-lottie" => $tikiUrl . JS_ASSETS_PATH . "/tiki-lottie.js",
"@tiki-glightbox" => $tikiUrl . JS_ASSETS_PATH . "/tiki-glightbox.js",
"@tiki-figlet" => $tikiUrl . JS_ASSETS_PATH . "/tiki-figlet.js",
=====================================
src/js/tiki-lottie/lottie.js
=====================================
@@ -0,0 +1,35 @@
+/**
+ * Tiki Lottie - Local bundle wrapper for @lottiefiles/dotlottie-wc
+ *
+ * This module imports the dotLottie Web Component and provides
+ * initialization and click-to-play functionality for wiki pages.
+ */
+
+import "@lottiefiles/dotlottie-wc";
+
+/**
+ * Initialize click-to-play/pause functionality for all Lottie animations on the page.
+ * Call this function after the DOM is loaded.
+ */
+export function initLottieClickHandlers() {
+ document.querySelectorAll("dotlottie-wc").forEach((el) => {
+ el.style.cursor = "pointer";
+ el.addEventListener("click", function () {
+ const lottie = el.dotLottie;
+ if (lottie) {
+ if (lottie.isPlaying) {
+ lottie.pause();
+ } else {
+ lottie.play();
+ }
+ }
+ });
+ });
+}
+
+// Auto-initialize when DOM is ready
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", initLottieClickHandlers);
+} else {
+ initLottieClickHandlers();
+}
=====================================
src/js/tiki-lottie/package.json
=====================================
@@ -0,0 +1,8 @@
+{
+ "name": "tiki-lottie",
+ "version": "1.0.0",
+ "main": "lottie.js",
+ "dependencies": {
+ "@lottiefiles/dotlottie-wc": "^0.8.0"
+ }
+}
\ No newline at end of file
=====================================
src/js/vite.config.mjs
=====================================
@@ -136,6 +136,7 @@ export default defineConfig(({ command, mode }) => {
"tiki-iot-dashboard": resolve(__dirname, "tiki-iot/dashboard.js"),
"tiki-iot-dashboard-all": resolve(__dirname, "tiki-iot/dashboard-all.js"),
"tiki-mermaid": resolve(__dirname, "tiki-mermaid/mermaid.js"),
+ "tiki-lottie": resolve(__dirname, "tiki-lottie/lottie.js"),
"tiki-vue-sfc-loader": resolve(__dirname, "tiki-vue-sfc-loader/src/tiki-vue-sfc-loader.js"),
"tiki-toast-ui": resolve(__dirname, "tiki-toast-ui/toast-index.js"),
"@tiki/ui-utils": resolve(__dirname, "@tiki/ui-utils/index.js"),
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/8bca5ba2dd2fb22d6d8d604ad0d5e46873ae509c
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/8bca5ba2dd2fb22d6d8d604ad0d5e46873ae509c
You're receiving this email because of your account on gitlab.com.
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs