[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.