From 57df8a2ce6f03cc76ae217c12366aa2acf8dda1d Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Thu, 19 Jun 2025 15:53:19 +0300 Subject: [PATCH 1/3] OEL-3736: Moved bcl to oe_bt. --- .gitignore | 7 + bcl/bcl-builder.config.js | 190 ++ bcl/bootstrap/bin/build-plugins.js | 106 ++ bcl/bootstrap/bootstrap-icons.js | 1537 +++++++++++++++++ .../legacy/dependency/manipulator.js | 80 + bcl/bootstrap/legacy/dependency/util/index.js | 336 ++++ bcl/bootstrap/legacy/scrollspy-legacy.js | 294 ++++ bcl/bootstrap/package.json | 58 + bcl/bootstrap/replace-icons/twitter.svg | 3 + bcl/builder/README.md | 148 ++ bcl/builder/bin/build.js | 105 ++ bcl/builder/conf/svgoDefaultPlugins.js | 22 + bcl/builder/package.json | 43 + bcl/builder/scripts/colorScheme.js | 116 ++ bcl/builder/scripts/copy.js | 31 + bcl/builder/scripts/rename.js | 93 + bcl/builder/scripts/scripts.js | 85 + bcl/builder/scripts/sprite.js | 96 + bcl/builder/scripts/styles.js | 98 ++ bcl/package.json | 40 + bcl/src/icons/custom-icons.js | 8 + bcl/src/icons/custom-icons/email.svg | 3 + bcl/src/icons/custom-icons/flickr.svg | 3 + bcl/src/icons/custom-icons/pinterest.svg | 10 + bcl/src/icons/custom-icons/storify.svg | 10 + bcl/src/icons/custom-icons/yammer.svg | 3 + bcl/src/icons/icons.js | 358 ++++ .../js/accessible-toggle/accessible-toggle.js | 73 + .../js/accordion-toggle/accordion-toggle.js | 51 + bcl/src/js/gallery/gallery.js | 200 +++ bcl/src/js/index.esm.js | 42 + bcl/src/js/index.umd.js | 42 + bcl/src/scss/_accordion.scss | 11 + bcl/src/scss/_alert.scss | 8 + bcl/src/scss/_badge.scss | 68 + bcl/src/scss/_banners.scss | 223 +++ bcl/src/scss/_blockquote.scss | 4 + bcl/src/scss/_breadcrumb.scss | 9 + bcl/src/scss/_button.scss | 21 + bcl/src/scss/_card.scss | 13 + bcl/src/scss/_carousel.scss | 99 ++ bcl/src/scss/_circular-progress-bar.scss | 122 ++ bcl/src/scss/_collapse.scss | 8 + bcl/src/scss/_description_list.scss | 18 + bcl/src/scss/_footer.scss | 66 + bcl/src/scss/_gallery.scss | 270 +++ bcl/src/scss/_header.scss | 314 ++++ bcl/src/scss/_icon.scss | 76 + bcl/src/scss/_inpage-navigation.scss | 168 ++ bcl/src/scss/_input.scss | 117 ++ bcl/src/scss/_language-list.scss | 62 + bcl/src/scss/_multiselect-2.scss | 552 ++++++ bcl/src/scss/_multiselect.scss | 197 +++ bcl/src/scss/_pagination.scss | 57 + bcl/src/scss/_reset.scss | 14 + bcl/src/scss/_search-form.scss | 72 + bcl/src/scss/_spinners.scss | 9 + bcl/src/scss/_tabs.scss | 80 + bcl/src/scss/_timeline.scss | 80 + bcl/src/scss/base/_colors.scss | 49 + bcl/src/scss/base/_layout.scss | 38 + bcl/src/scss/base/_mixins.scss | 13 + bcl/src/scss/base/_utilities.scss | 159 ++ bcl/src/scss/base/_variables.scss | 112 ++ bcl/src/scss/color-scheme-variables.scss | 11 + bcl/src/scss/color-scheme.scss | 15 + bcl/src/scss/color_scheme/_alert.scss | 22 + bcl/src/scss/color_scheme/_background.scss | 23 + bcl/src/scss/color_scheme/_badges.scss | 69 + bcl/src/scss/color_scheme/_buttons.scss | 31 + bcl/src/scss/color_scheme/_link.scss | 6 + bcl/src/scss/color_scheme/_list_group.scss | 20 + bcl/src/scss/color_scheme/_text.scss | 29 + bcl/src/scss/color_scheme/_utilities.scss | 41 + bcl/src/scss/color_scheme/generator.scss | 25 + bcl/src/scss/functions | 0 bcl/src/scss/oe-bcl-default.scss | 88 + bcl/test.css | 17 + package.json | 22 +- 79 files changed, 7812 insertions(+), 7 deletions(-) create mode 100644 bcl/bcl-builder.config.js create mode 100755 bcl/bootstrap/bin/build-plugins.js create mode 100644 bcl/bootstrap/bootstrap-icons.js create mode 100644 bcl/bootstrap/legacy/dependency/manipulator.js create mode 100644 bcl/bootstrap/legacy/dependency/util/index.js create mode 100644 bcl/bootstrap/legacy/scrollspy-legacy.js create mode 100644 bcl/bootstrap/package.json create mode 100644 bcl/bootstrap/replace-icons/twitter.svg create mode 100644 bcl/builder/README.md create mode 100755 bcl/builder/bin/build.js create mode 100644 bcl/builder/conf/svgoDefaultPlugins.js create mode 100644 bcl/builder/package.json create mode 100644 bcl/builder/scripts/colorScheme.js create mode 100644 bcl/builder/scripts/copy.js create mode 100644 bcl/builder/scripts/rename.js create mode 100644 bcl/builder/scripts/scripts.js create mode 100644 bcl/builder/scripts/sprite.js create mode 100644 bcl/builder/scripts/styles.js create mode 100644 bcl/package.json create mode 100644 bcl/src/icons/custom-icons.js create mode 100644 bcl/src/icons/custom-icons/email.svg create mode 100644 bcl/src/icons/custom-icons/flickr.svg create mode 100644 bcl/src/icons/custom-icons/pinterest.svg create mode 100644 bcl/src/icons/custom-icons/storify.svg create mode 100644 bcl/src/icons/custom-icons/yammer.svg create mode 100644 bcl/src/icons/icons.js create mode 100644 bcl/src/js/accessible-toggle/accessible-toggle.js create mode 100644 bcl/src/js/accordion-toggle/accordion-toggle.js create mode 100644 bcl/src/js/gallery/gallery.js create mode 100644 bcl/src/js/index.esm.js create mode 100644 bcl/src/js/index.umd.js create mode 100644 bcl/src/scss/_accordion.scss create mode 100644 bcl/src/scss/_alert.scss create mode 100644 bcl/src/scss/_badge.scss create mode 100644 bcl/src/scss/_banners.scss create mode 100644 bcl/src/scss/_blockquote.scss create mode 100644 bcl/src/scss/_breadcrumb.scss create mode 100644 bcl/src/scss/_button.scss create mode 100644 bcl/src/scss/_card.scss create mode 100644 bcl/src/scss/_carousel.scss create mode 100644 bcl/src/scss/_circular-progress-bar.scss create mode 100644 bcl/src/scss/_collapse.scss create mode 100644 bcl/src/scss/_description_list.scss create mode 100644 bcl/src/scss/_footer.scss create mode 100644 bcl/src/scss/_gallery.scss create mode 100644 bcl/src/scss/_header.scss create mode 100644 bcl/src/scss/_icon.scss create mode 100644 bcl/src/scss/_inpage-navigation.scss create mode 100644 bcl/src/scss/_input.scss create mode 100644 bcl/src/scss/_language-list.scss create mode 100644 bcl/src/scss/_multiselect-2.scss create mode 100644 bcl/src/scss/_multiselect.scss create mode 100644 bcl/src/scss/_pagination.scss create mode 100644 bcl/src/scss/_reset.scss create mode 100644 bcl/src/scss/_search-form.scss create mode 100644 bcl/src/scss/_spinners.scss create mode 100644 bcl/src/scss/_tabs.scss create mode 100644 bcl/src/scss/_timeline.scss create mode 100644 bcl/src/scss/base/_colors.scss create mode 100644 bcl/src/scss/base/_layout.scss create mode 100644 bcl/src/scss/base/_mixins.scss create mode 100644 bcl/src/scss/base/_utilities.scss create mode 100644 bcl/src/scss/base/_variables.scss create mode 100644 bcl/src/scss/color-scheme-variables.scss create mode 100644 bcl/src/scss/color-scheme.scss create mode 100644 bcl/src/scss/color_scheme/_alert.scss create mode 100644 bcl/src/scss/color_scheme/_background.scss create mode 100644 bcl/src/scss/color_scheme/_badges.scss create mode 100644 bcl/src/scss/color_scheme/_buttons.scss create mode 100644 bcl/src/scss/color_scheme/_link.scss create mode 100644 bcl/src/scss/color_scheme/_list_group.scss create mode 100644 bcl/src/scss/color_scheme/_text.scss create mode 100644 bcl/src/scss/color_scheme/_utilities.scss create mode 100644 bcl/src/scss/color_scheme/generator.scss create mode 100644 bcl/src/scss/functions create mode 100644 bcl/src/scss/oe-bcl-default.scss create mode 100644 bcl/test.css diff --git a/.gitignore b/.gitignore index 367ff1796..af0178383 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,12 @@ .idea /vendor/ /node_modules/ +**/node_modules/ +bcl/bootstrap/plugins +bcl/bootstrap/js +bcl/bootstrap/scss +bcl/bootstrap/*.svg +bcl/bootstrap/icons/*.svg /build/ /npm-debug.log /grumphp.yml @@ -11,6 +17,7 @@ /runner.yml /.idea/ /package-lock.json +**/package-lock.json /phpunit.xml /.stylelintrc.json /docker-compose.*.yml diff --git a/bcl/bcl-builder.config.js b/bcl/bcl-builder.config.js new file mode 100644 index 000000000..a4d244ce2 --- /dev/null +++ b/bcl/bcl-builder.config.js @@ -0,0 +1,190 @@ +const path = require("path"); +const replace = require("@rollup/plugin-replace"); +const iconList = require("./src/icons/icons"); +const customIconList = require("./src/icons/custom-icons"); + +const outputFolder = '../assets'; +const nodeModules = "../node_modules"; + +// SCSS includePaths +const includePaths = [ + path.resolve(__dirname, 'src/scss'), + path.resolve(__dirname, '../node_modules'), +]; + +module.exports = { + scripts: [ + { + entry: path.resolve(__dirname, "src/js/index.esm.js"), + dest: path.resolve(outputFolder, "js/oe-bcl-default.esm.js"), + options: { + format: "esm", + globals: { "@popperjs/core": "Popper" }, + minify: true, + sourceMap: true, + minifyOptions: { + mangle: true, + format: { + comments: /^!/, + }, + compress: { + passes: 2, + }, + }, + external: ["@popperjs/core"], + }, + }, + { + entry: path.resolve(__dirname, "src/js/index.umd.js"), + dest: path.resolve(outputFolder, "js/oe-bcl-default.umd.js"), + options: { + name: "bootstrap", + minify: true, + sourceMap: true, + minifyOptions: { + mangle: true, + format: { + comments: /^!/, + }, + compress: { + passes: 2, + }, + }, + }, + }, + { + entry: path.resolve(__dirname, "src/js/index.umd.js"), + dest: path.resolve(outputFolder, "js/oe-bcl-default.bundle.js"), + options: { + name: "bootstrap", + minify: true, + sourceMap: true, + minifyOptions: { + mangle: true, + format: { + comments: /^!/, + }, + compress: { + passes: 2, + }, + }, + plugins: [ + replace({ + "process.env.NODE_ENV": '"production"', + preventAssignment: true, + }), + ], + }, + }, + ], + colorScheme: [ + { + entry: path.resolve(__dirname, "src/scss/color-scheme-variables.scss"), + dest: path.resolve(outputFolder, "css/color-scheme.min.css"), + options: { + includePaths, + minify: true, + sourceMap: "file", + importsFile: path.resolve(__dirname, "src/scss/color-scheme.scss"), + generatorFile: path.resolve(__dirname, "src/scss/color_scheme/generator.scss"), + }, + }, + ], + styles: [ + { + entry: path.resolve(__dirname, "src/scss/oe-bcl-default.scss"), + dest: path.resolve(outputFolder, "css/oe-bcl-default.css"), + options: { + includePaths, + sourceMap: "file", + }, + }, + { + entry: path.resolve(__dirname, "src/scss/oe-bcl-default.scss"), + dest: path.resolve(outputFolder, "css/oe-bcl-ckeditor5.min.css"), + options: { + prefixer: { + prefix: ".ck-content", + }, + includePaths, + sourceMap: "file", + minify: true, + }, + }, + { + entry: path.resolve(__dirname, "src/scss/oe-bcl-default.scss"), + dest: path.resolve(outputFolder, "css/oe-bcl-default.min.css"), + options: { + includePaths, + sourceMap: "file", + minify: true, + }, + }, + ], + sprite: [ + { + entry: [ + path.resolve(nodeModules, "@openeuropa/bcl-bootstrap/icons"), + path.resolve(__dirname, "src/icons/custom-icons"), + ], + dest: path.resolve(outputFolder, "icons/"), + options: { + list: [iconList, customIconList], + }, + }, + ], + copy: [ + { + from: [path.resolve(nodeModules, "slim-select/dist/slimselect.min.js")], + to: path.resolve(outputFolder, "js"), + options: { up: true }, + }, + { + from: [path.resolve(nodeModules, "slim-select-2/dist/slimselect.min.js")], + to: path.resolve(outputFolder, "js/slim-select-2"), + options: { up: true }, + }, + { + from: [ + path.resolve( + nodeModules, + "@openeuropa/bcl-bootstrap/bootstrap-icons.svg", + ), + ], + to: path.resolve(outputFolder, "icons"), + options: { up: true }, + }, + { + from: [ + path.resolve( + nodeModules, + "@ecl/resources-flag-icons/dist/sprites/icons-flag.svg", + ), + ], + to: path.resolve(outputFolder, "icons"), + options: { up: true }, + }, + { + from: [`${nodeModules}/flag-icons/flags/**/*.svg`], + to: path.resolve(outputFolder, "icons/world-flags"), + options: { up: 4 }, + }, + { + from: [`${nodeModules}/@ecl/resources-ec-logo/**/*.svg`], + to: path.resolve(outputFolder, "logos/ec"), + options: { up: 5 }, + }, + { + from: [`${nodeModules}/@ecl/resources-eu-logo/**/*.svg`], + to: path.resolve(outputFolder, "logos/eu"), + options: { up: 5 }, + }, + { + from: [ + `${nodeModules}/@openeuropa/bcl-twig-templates/templates/**/*.twig`, + ], + to: path.resolve(outputFolder, "templates"), + options: { up: 3 }, + }, + ], +}; diff --git a/bcl/bootstrap/bin/build-plugins.js b/bcl/bootstrap/bin/build-plugins.js new file mode 100755 index 000000000..9c7512bd4 --- /dev/null +++ b/bcl/bootstrap/bin/build-plugins.js @@ -0,0 +1,106 @@ +#!/usr/bin/env node + +/*! + * Script to build our plugins to use them separately. + * Copyright 2020-2021 The Bootstrap Authors + * Copyright 2020-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ + +'use strict' + +const path = require('path') +const rollup = require('rollup') +const { globSync } = require('glob') +const { babel } = require('@rollup/plugin-babel') + +const srcPath = path.resolve(__dirname, '../js/src/') +const jsFiles = globSync(srcPath + '/**/*.js') + +// Array which holds the resolved plugins +const resolvedPlugins = [] + +// Trims the "js" extension and uppercases => first letter, hyphens, backslashes & slashes +const filenameToEntity = filename => filename.replace('.js', '') + .replace(/(?:^|-|\/|\\)[a-z]/g, str => str.slice(-1).toUpperCase()) + +for (const file of jsFiles) { + resolvedPlugins.push({ + src: file.replace('.js', ''), + dist: file.replace('src', 'dist'), + fileName: path.basename(file), + className: filenameToEntity(path.basename(file)) + // safeClassName: filenameToEntity(path.relative(srcPath, file)) + }) +} + +const build = async plugin => { + const globals = {} + + console.log(plugin); + + const bundle = await rollup.rollup({ + input: plugin.src, + plugins: [ + babel({ + // Only transpile our source code + exclude: 'node_modules/**', + // Include the helpers in each file, at most one copy of each + babelHelpers: 'bundled' + }) + ], + external: source => { + // Pattern to identify local files + const pattern = /^(\.{1,2})\// + + // It's not a local file, e.g a Node.js package + if (!pattern.test(source)) { + globals[source] = source + return true + } + + const usedPlugin = resolvedPlugins.find(plugin => { + return plugin.src.includes(source.replace(pattern, '')) + }) + + if (!usedPlugin) { + // It’s just a local JS file (such as ../dom/event-handler.js). Bundle it in. + return false + } + + // We can change `Index` with `UtilIndex` etc if we use + // `safeClassName` instead of `className` everywhere + globals[path.normalize(usedPlugin.src)] = usedPlugin.className + return true + } + }) + + await bundle.write({ + format: 'umd', + name: plugin.className, + sourcemap: true, + globals, + generatedCode: 'es2015', + file: plugin.dist + }) + + console.log(`Built ${plugin.className}`) +} + +(async () => { + try { + const basename = path.basename(__filename) + const timeLabel = `[${basename}] finished` + + console.log('Building individual plugins...') + console.time(timeLabel) + + await Promise.all(Object.values(resolvedPlugins).map(plugin => build(plugin))) + + console.timeEnd(timeLabel) + } catch (error) { + console.error(error) + process.exit(1) + } +})() + \ No newline at end of file diff --git a/bcl/bootstrap/bootstrap-icons.js b/bcl/bootstrap/bootstrap-icons.js new file mode 100644 index 000000000..3b10b6c58 --- /dev/null +++ b/bcl/bootstrap/bootstrap-icons.js @@ -0,0 +1,1537 @@ +export default [ + "123", + "alarm-fill", + "alarm", + "align-bottom", + "align-center", + "align-end", + "align-middle", + "align-start", + "align-top", + "alt", + "app-indicator", + "app", + "archive-fill", + "archive", + "arrow-90deg-down", + "arrow-90deg-left", + "arrow-90deg-right", + "arrow-90deg-up", + "arrow-bar-down", + "arrow-bar-left", + "arrow-bar-right", + "arrow-bar-up", + "arrow-clockwise", + "arrow-counterclockwise", + "arrow-down-circle-fill", + "arrow-down-circle", + "arrow-down-left-circle-fill", + "arrow-down-left-circle", + "arrow-down-left-square-fill", + "arrow-down-left-square", + "arrow-down-left", + "arrow-down-right-circle-fill", + "arrow-down-right-circle", + "arrow-down-right-square-fill", + "arrow-down-right-square", + "arrow-down-right", + "arrow-down-short", + "arrow-down-square-fill", + "arrow-down-square", + "arrow-down-up", + "arrow-down", + "arrow-left-circle-fill", + "arrow-left-circle", + "arrow-left-right", + "arrow-left-short", + "arrow-left-square-fill", + "arrow-left-square", + "arrow-left", + "arrow-repeat", + "arrow-return-left", + "arrow-return-right", + "arrow-right-circle-fill", + "arrow-right-circle", + "arrow-right-short", + "arrow-right-square-fill", + "arrow-right-square", + "arrow-right", + "arrow-up-circle-fill", + "arrow-up-circle", + "arrow-up-left-circle-fill", + "arrow-up-left-circle", + "arrow-up-left-square-fill", + "arrow-up-left-square", + "arrow-up-left", + "arrow-up-right-circle-fill", + "arrow-up-right-circle", + "arrow-up-right-square-fill", + "arrow-up-right-square", + "arrow-up-right", + "arrow-up-short", + "arrow-up-square-fill", + "arrow-up-square", + "arrow-up", + "arrows-angle-contract", + "arrows-angle-expand", + "arrows-collapse", + "arrows-expand", + "arrows-fullscreen", + "arrows-move", + "aspect-ratio-fill", + "aspect-ratio", + "asterisk", + "at", + "award-fill", + "award", + "back", + "backspace-fill", + "backspace-reverse-fill", + "backspace-reverse", + "backspace", + "badge-3d-fill", + "badge-3d", + "badge-4k-fill", + "badge-4k", + "badge-8k-fill", + "badge-8k", + "badge-ad-fill", + "badge-ad", + "badge-ar-fill", + "badge-ar", + "badge-cc-fill", + "badge-cc", + "badge-hd-fill", + "badge-hd", + "badge-tm-fill", + "badge-tm", + "badge-vo-fill", + "badge-vo", + "badge-vr-fill", + "badge-vr", + "badge-wc-fill", + "badge-wc", + "bag-check-fill", + "bag-check", + "bag-dash-fill", + "bag-dash", + "bag-fill", + "bag-plus-fill", + "bag-plus", + "bag-x-fill", + "bag-x", + "bag", + "bar-chart-fill", + "bar-chart-line-fill", + "bar-chart-line", + "bar-chart-steps", + "bar-chart", + "basket-fill", + "basket", + "basket2-fill", + "basket2", + "basket3-fill", + "basket3", + "battery-charging", + "battery-full", + "battery-half", + "battery", + "bell-fill", + "bell", + "bezier", + "bezier2", + "bicycle", + "binoculars-fill", + "binoculars", + "blockquote-left", + "blockquote-right", + "book-fill", + "book-half", + "book", + "bookmark-check-fill", + "bookmark-check", + "bookmark-dash-fill", + "bookmark-dash", + "bookmark-fill", + "bookmark-heart-fill", + "bookmark-heart", + "bookmark-plus-fill", + "bookmark-plus", + "bookmark-star-fill", + "bookmark-star", + "bookmark-x-fill", + "bookmark-x", + "bookmark", + "bookmarks-fill", + "bookmarks", + "bookshelf", + "bootstrap-fill", + "bootstrap-reboot", + "bootstrap", + "border-all", + "border-bottom", + "border-center", + "border-inner", + "border-left", + "border-middle", + "border-outer", + "border-right", + "border-style", + "border-top", + "border-width", + "border", + "bounding-box-circles", + "bounding-box", + "box-arrow-down-left", + "box-arrow-down-right", + "box-arrow-down", + "box-arrow-in-down-left", + "box-arrow-in-down-right", + "box-arrow-in-down", + "box-arrow-in-left", + "box-arrow-in-right", + "box-arrow-in-up-left", + "box-arrow-in-up-right", + "box-arrow-in-up", + "box-arrow-left", + "box-arrow-right", + "box-arrow-up-left", + "box-arrow-up-right", + "box-arrow-up", + "box-seam", + "box", + "braces", + "bricks", + "briefcase-fill", + "briefcase", + "brightness-alt-high-fill", + "brightness-alt-high", + "brightness-alt-low-fill", + "brightness-alt-low", + "brightness-high-fill", + "brightness-high", + "brightness-low-fill", + "brightness-low", + "broadcast-pin", + "broadcast", + "brush-fill", + "brush", + "bucket-fill", + "bucket", + "bug-fill", + "bug", + "building", + "bullseye", + "calculator-fill", + "calculator", + "calendar-check-fill", + "calendar-check", + "calendar-date-fill", + "calendar-date", + "calendar-day-fill", + "calendar-day", + "calendar-event-fill", + "calendar-event", + "calendar-fill", + "calendar-minus-fill", + "calendar-minus", + "calendar-month-fill", + "calendar-month", + "calendar-plus-fill", + "calendar-plus", + "calendar-range-fill", + "calendar-range", + "calendar-week-fill", + "calendar-week", + "calendar-x-fill", + "calendar-x", + "calendar", + "calendar2-check-fill", + "calendar2-check", + "calendar2-date-fill", + "calendar2-date", + "calendar2-day-fill", + "calendar2-day", + "calendar2-event-fill", + "calendar2-event", + "calendar2-fill", + "calendar2-minus-fill", + "calendar2-minus", + "calendar2-month-fill", + "calendar2-month", + "calendar2-plus-fill", + "calendar2-plus", + "calendar2-range-fill", + "calendar2-range", + "calendar2-week-fill", + "calendar2-week", + "calendar2-x-fill", + "calendar2-x", + "calendar2", + "calendar3-event-fill", + "calendar3-event", + "calendar3-fill", + "calendar3-range-fill", + "calendar3-range", + "calendar3-week-fill", + "calendar3-week", + "calendar3", + "calendar4-event", + "calendar4-range", + "calendar4-week", + "calendar4", + "camera-fill", + "camera-reels-fill", + "camera-reels", + "camera-video-fill", + "camera-video-off-fill", + "camera-video-off", + "camera-video", + "camera", + "camera2", + "capslock-fill", + "capslock", + "card-checklist", + "card-heading", + "card-image", + "card-list", + "card-text", + "caret-down-fill", + "caret-down-square-fill", + "caret-down-square", + "caret-down", + "caret-left-fill", + "caret-left-square-fill", + "caret-left-square", + "caret-left", + "caret-right-fill", + "caret-right-square-fill", + "caret-right-square", + "caret-right", + "caret-up-fill", + "caret-up-square-fill", + "caret-up-square", + "caret-up", + "cart-check-fill", + "cart-check", + "cart-dash-fill", + "cart-dash", + "cart-fill", + "cart-plus-fill", + "cart-plus", + "cart-x-fill", + "cart-x", + "cart", + "cart2", + "cart3", + "cart4", + "cash-stack", + "cash", + "cast", + "chat-dots-fill", + "chat-dots", + "chat-fill", + "chat-left-dots-fill", + "chat-left-dots", + "chat-left-fill", + "chat-left-quote-fill", + "chat-left-quote", + "chat-left-text-fill", + "chat-left-text", + "chat-left", + "chat-quote-fill", + "chat-quote", + "chat-right-dots-fill", + "chat-right-dots", + "chat-right-fill", + "chat-right-quote-fill", + "chat-right-quote", + "chat-right-text-fill", + "chat-right-text", + "chat-right", + "chat-square-dots-fill", + "chat-square-dots", + "chat-square-fill", + "chat-square-quote-fill", + "chat-square-quote", + "chat-square-text-fill", + "chat-square-text", + "chat-square", + "chat-text-fill", + "chat-text", + "chat", + "check-all", + "check-circle-fill", + "check-circle", + "check-square-fill", + "check-square", + "check", + "check2-all", + "check2-circle", + "check2-square", + "check2", + "chevron-bar-contract", + "chevron-bar-down", + "chevron-bar-expand", + "chevron-bar-left", + "chevron-bar-right", + "chevron-bar-up", + "chevron-compact-down", + "chevron-compact-left", + "chevron-compact-right", + "chevron-compact-up", + "chevron-contract", + "chevron-double-down", + "chevron-double-left", + "chevron-double-right", + "chevron-double-up", + "chevron-down", + "chevron-expand", + "chevron-left", + "chevron-right", + "chevron-up", + "circle-fill", + "circle-half", + "circle-square", + "circle", + "clipboard-check", + "clipboard-data", + "clipboard-minus", + "clipboard-plus", + "clipboard-x", + "clipboard", + "clock-fill", + "clock-history", + "clock", + "cloud-arrow-down-fill", + "cloud-arrow-down", + "cloud-arrow-up-fill", + "cloud-arrow-up", + "cloud-check-fill", + "cloud-check", + "cloud-download-fill", + "cloud-download", + "cloud-drizzle-fill", + "cloud-drizzle", + "cloud-fill", + "cloud-fog-fill", + "cloud-fog", + "cloud-fog2-fill", + "cloud-fog2", + "cloud-hail-fill", + "cloud-hail", + "cloud-haze-1", + "cloud-haze-fill", + "cloud-haze", + "cloud-haze2-fill", + "cloud-lightning-fill", + "cloud-lightning-rain-fill", + "cloud-lightning-rain", + "cloud-lightning", + "cloud-minus-fill", + "cloud-minus", + "cloud-moon-fill", + "cloud-moon", + "cloud-plus-fill", + "cloud-plus", + "cloud-rain-fill", + "cloud-rain-heavy-fill", + "cloud-rain-heavy", + "cloud-rain", + "cloud-slash-fill", + "cloud-slash", + "cloud-sleet-fill", + "cloud-sleet", + "cloud-snow-fill", + "cloud-snow", + "cloud-sun-fill", + "cloud-sun", + "cloud-upload-fill", + "cloud-upload", + "cloud", + "clouds-fill", + "clouds", + "cloudy-fill", + "cloudy", + "code-slash", + "code-square", + "code", + "collection-fill", + "collection-play-fill", + "collection-play", + "collection", + "columns-gap", + "columns", + "command", + "compass-fill", + "compass", + "cone-striped", + "cone", + "controller", + "cpu-fill", + "cpu", + "credit-card-2-back-fill", + "credit-card-2-back", + "credit-card-2-front-fill", + "credit-card-2-front", + "credit-card-fill", + "credit-card", + "crop", + "cup-fill", + "cup-straw", + "cup", + "cursor-fill", + "cursor-text", + "cursor", + "dash-circle-dotted", + "dash-circle-fill", + "dash-circle", + "dash-square-dotted", + "dash-square-fill", + "dash-square", + "dash", + "diagram-2-fill", + "diagram-2", + "diagram-3-fill", + "diagram-3", + "diamond-fill", + "diamond-half", + "diamond", + "dice-1-fill", + "dice-1", + "dice-2-fill", + "dice-2", + "dice-3-fill", + "dice-3", + "dice-4-fill", + "dice-4", + "dice-5-fill", + "dice-5", + "dice-6-fill", + "dice-6", + "disc-fill", + "disc", + "discord", + "display-fill", + "display", + "distribute-horizontal", + "distribute-vertical", + "door-closed-fill", + "door-closed", + "door-open-fill", + "door-open", + "dot", + "download", + "droplet-fill", + "droplet-half", + "droplet", + "earbuds", + "easel-fill", + "easel", + "egg-fill", + "egg-fried", + "egg", + "eject-fill", + "eject", + "emoji-angry-fill", + "emoji-angry", + "emoji-dizzy-fill", + "emoji-dizzy", + "emoji-expressionless-fill", + "emoji-expressionless", + "emoji-frown-fill", + "emoji-frown", + "emoji-heart-eyes-fill", + "emoji-heart-eyes", + "emoji-laughing-fill", + "emoji-laughing", + "emoji-neutral-fill", + "emoji-neutral", + "emoji-smile-fill", + "emoji-smile-upside-down-fill", + "emoji-smile-upside-down", + "emoji-smile", + "emoji-sunglasses-fill", + "emoji-sunglasses", + "emoji-wink-fill", + "emoji-wink", + "envelope-fill", + "envelope-open-fill", + "envelope-open", + "envelope", + "eraser-fill", + "eraser", + "exclamation-circle-fill", + "exclamation-circle", + "exclamation-diamond-fill", + "exclamation-diamond", + "exclamation-octagon-fill", + "exclamation-octagon", + "exclamation-square-fill", + "exclamation-square", + "exclamation-triangle-fill", + "exclamation-triangle", + "exclamation", + "exclude", + "eye-fill", + "eye-slash-fill", + "eye-slash", + "eye", + "eyedropper", + "eyeglasses", + "facebook", + "file-arrow-down-fill", + "file-arrow-down", + "file-arrow-up-fill", + "file-arrow-up", + "file-bar-graph-fill", + "file-bar-graph", + "file-binary-fill", + "file-binary", + "file-break-fill", + "file-break", + "file-check-fill", + "file-check", + "file-code-fill", + "file-code", + "file-diff-fill", + "file-diff", + "file-earmark-arrow-down-fill", + "file-earmark-arrow-down", + "file-earmark-arrow-up-fill", + "file-earmark-arrow-up", + "file-earmark-bar-graph-fill", + "file-earmark-bar-graph", + "file-earmark-binary-fill", + "file-earmark-binary", + "file-earmark-break-fill", + "file-earmark-break", + "file-earmark-check-fill", + "file-earmark-check", + "file-earmark-code-fill", + "file-earmark-code", + "file-earmark-diff-fill", + "file-earmark-diff", + "file-earmark-easel-fill", + "file-earmark-easel", + "file-earmark-excel-fill", + "file-earmark-excel", + "file-earmark-fill", + "file-earmark-font-fill", + "file-earmark-font", + "file-earmark-image-fill", + "file-earmark-image", + "file-earmark-lock-fill", + "file-earmark-lock", + "file-earmark-lock2-fill", + "file-earmark-lock2", + "file-earmark-medical-fill", + "file-earmark-medical", + "file-earmark-minus-fill", + "file-earmark-minus", + "file-earmark-music-fill", + "file-earmark-music", + "file-earmark-person-fill", + "file-earmark-person", + "file-earmark-play-fill", + "file-earmark-play", + "file-earmark-plus-fill", + "file-earmark-plus", + "file-earmark-post-fill", + "file-earmark-post", + "file-earmark-ppt-fill", + "file-earmark-ppt", + "file-earmark-richtext-fill", + "file-earmark-richtext", + "file-earmark-ruled-fill", + "file-earmark-ruled", + "file-earmark-slides-fill", + "file-earmark-slides", + "file-earmark-spreadsheet-fill", + "file-earmark-spreadsheet", + "file-earmark-text-fill", + "file-earmark-text", + "file-earmark-word-fill", + "file-earmark-word", + "file-earmark-x-fill", + "file-earmark-x", + "file-earmark-zip-fill", + "file-earmark-zip", + "file-earmark", + "file-easel-fill", + "file-easel", + "file-excel-fill", + "file-excel", + "file-fill", + "file-font-fill", + "file-font", + "file-image-fill", + "file-image", + "file-lock-fill", + "file-lock", + "file-lock2-fill", + "file-lock2", + "file-medical-fill", + "file-medical", + "file-minus-fill", + "file-minus", + "file-music-fill", + "file-music", + "file-person-fill", + "file-person", + "file-play-fill", + "file-play", + "file-plus-fill", + "file-plus", + "file-post-fill", + "file-post", + "file-ppt-fill", + "file-ppt", + "file-richtext-fill", + "file-richtext", + "file-ruled-fill", + "file-ruled", + "file-slides-fill", + "file-slides", + "file-spreadsheet-fill", + "file-spreadsheet", + "file-text-fill", + "file-text", + "file-word-fill", + "file-word", + "file-x-fill", + "file-x", + "file-zip-fill", + "file-zip", + "file", + "files-alt", + "files", + "film", + "filter-circle-fill", + "filter-circle", + "filter-left", + "filter-right", + "filter-square-fill", + "filter-square", + "filter", + "flag-fill", + "flag", + "flower1", + "flower2", + "flower3", + "folder-check", + "folder-fill", + "folder-minus", + "folder-plus", + "folder-symlink-fill", + "folder-symlink", + "folder-x", + "folder", + "folder2-open", + "folder2", + "fonts", + "forward-fill", + "forward", + "front", + "fullscreen-exit", + "fullscreen", + "funnel-fill", + "funnel", + "gear-fill", + "gear-wide-connected", + "gear-wide", + "gear", + "gem", + "geo-alt-fill", + "geo-alt", + "geo-fill", + "geo", + "gift-fill", + "gift", + "github", + "globe", + "globe2", + "google", + "graph-down", + "graph-up", + "grid-1x2-fill", + "grid-1x2", + "grid-3x2-gap-fill", + "grid-3x2-gap", + "grid-3x2", + "grid-3x3-gap-fill", + "grid-3x3-gap", + "grid-3x3", + "grid-fill", + "grid", + "grip-horizontal", + "grip-vertical", + "hammer", + "hand-index-fill", + "hand-index-thumb-fill", + "hand-index-thumb", + "hand-index", + "hand-thumbs-down-fill", + "hand-thumbs-down", + "hand-thumbs-up-fill", + "hand-thumbs-up", + "handbag-fill", + "handbag", + "hash", + "hdd-fill", + "hdd-network-fill", + "hdd-network", + "hdd-rack-fill", + "hdd-rack", + "hdd-stack-fill", + "hdd-stack", + "hdd", + "headphones", + "headset", + "heart-fill", + "heart-half", + "heart", + "heptagon-fill", + "heptagon-half", + "heptagon", + "hexagon-fill", + "hexagon-half", + "hexagon", + "hourglass-bottom", + "hourglass-split", + "hourglass-top", + "hourglass", + "house-door-fill", + "house-door", + "house-fill", + "house", + "hr", + "hurricane", + "image-alt", + "image-fill", + "image", + "images", + "inbox-fill", + "inbox", + "inboxes-fill", + "inboxes", + "info-circle-fill", + "info-circle", + "info-square-fill", + "info-square", + "info", + "input-cursor-text", + "input-cursor", + "instagram", + "intersect", + "journal-album", + "journal-arrow-down", + "journal-arrow-up", + "journal-bookmark-fill", + "journal-bookmark", + "journal-check", + "journal-code", + "journal-medical", + "journal-minus", + "journal-plus", + "journal-richtext", + "journal-text", + "journal-x", + "journal", + "journals", + "joystick", + "justify-left", + "justify-right", + "justify", + "kanban-fill", + "kanban", + "key-fill", + "key", + "keyboard-fill", + "keyboard", + "ladder", + "lamp-fill", + "lamp", + "laptop-fill", + "laptop", + "layer-backward", + "layer-forward", + "layers-fill", + "layers-half", + "layers", + "layout-sidebar-inset-reverse", + "layout-sidebar-inset", + "layout-sidebar-reverse", + "layout-sidebar", + "layout-split", + "layout-text-sidebar-reverse", + "layout-text-sidebar", + "layout-text-window-reverse", + "layout-text-window", + "layout-three-columns", + "layout-wtf", + "life-preserver", + "lightbulb-fill", + "lightbulb-off-fill", + "lightbulb-off", + "lightbulb", + "lightning-charge-fill", + "lightning-charge", + "lightning-fill", + "lightning", + "link-45deg", + "link", + "linkedin", + "list-check", + "list-nested", + "list-ol", + "list-stars", + "list-task", + "list-ul", + "list", + "lock-fill", + "lock", + "mailbox", + "mailbox2", + "map-fill", + "map", + "markdown-fill", + "markdown", + "mask", + "megaphone-fill", + "megaphone", + "menu-app-fill", + "menu-app", + "menu-button-fill", + "menu-button-wide-fill", + "menu-button-wide", + "menu-button", + "menu-down", + "menu-up", + "mic-fill", + "mic-mute-fill", + "mic-mute", + "mic", + "minecart-loaded", + "minecart", + "moisture", + "moon-fill", + "moon-stars-fill", + "moon-stars", + "moon", + "mouse-fill", + "mouse", + "mouse2-fill", + "mouse2", + "mouse3-fill", + "mouse3", + "music-note-beamed", + "music-note-list", + "music-note", + "music-player-fill", + "music-player", + "newspaper", + "node-minus-fill", + "node-minus", + "node-plus-fill", + "node-plus", + "nut-fill", + "nut", + "octagon-fill", + "octagon-half", + "octagon", + "option", + "outlet", + "paint-bucket", + "palette-fill", + "palette", + "palette2", + "paperclip", + "paragraph", + "patch-check-fill", + "patch-check", + "patch-exclamation-fill", + "patch-exclamation", + "patch-minus-fill", + "patch-minus", + "patch-plus-fill", + "patch-plus", + "patch-question-fill", + "patch-question", + "pause-btn-fill", + "pause-btn", + "pause-circle-fill", + "pause-circle", + "pause-fill", + "pause", + "peace-fill", + "peace", + "pen-fill", + "pen", + "pencil-fill", + "pencil-square", + "pencil", + "pentagon-fill", + "pentagon-half", + "pentagon", + "people-fill", + "people", + "percent", + "person-badge-fill", + "person-badge", + "person-bounding-box", + "person-check-fill", + "person-check", + "person-circle", + "person-dash-fill", + "person-dash", + "person-fill", + "person-lines-fill", + "person-plus-fill", + "person-plus", + "person-square", + "person-x-fill", + "person-x", + "person", + "phone-fill", + "phone-landscape-fill", + "phone-landscape", + "phone-vibrate-fill", + "phone-vibrate", + "phone", + "pie-chart-fill", + "pie-chart", + "pin-angle-fill", + "pin-angle", + "pin-fill", + "pin", + "pip-fill", + "pip", + "play-btn-fill", + "play-btn", + "play-circle-fill", + "play-circle", + "play-fill", + "play", + "plug-fill", + "plug", + "plus-circle-dotted", + "plus-circle-fill", + "plus-circle", + "plus-square-dotted", + "plus-square-fill", + "plus-square", + "plus", + "power", + "printer-fill", + "printer", + "puzzle-fill", + "puzzle", + "question-circle-fill", + "question-circle", + "question-diamond-fill", + "question-diamond", + "question-octagon-fill", + "question-octagon", + "question-square-fill", + "question-square", + "question", + "rainbow", + "receipt-cutoff", + "receipt", + "reception-0", + "reception-1", + "reception-2", + "reception-3", + "reception-4", + "record-btn-fill", + "record-btn", + "record-circle-fill", + "record-circle", + "record-fill", + "record", + "record2-fill", + "record2", + "reply-all-fill", + "reply-all", + "reply-fill", + "reply", + "rss-fill", + "rss", + "rulers", + "save-fill", + "save", + "save2-fill", + "save2", + "scissors", + "screwdriver", + "search", + "segmented-nav", + "server", + "share-fill", + "share", + "shield-check", + "shield-exclamation", + "shield-fill-check", + "shield-fill-exclamation", + "shield-fill-minus", + "shield-fill-plus", + "shield-fill-x", + "shield-fill", + "shield-lock-fill", + "shield-lock", + "shield-minus", + "shield-plus", + "shield-shaded", + "shield-slash-fill", + "shield-slash", + "shield-x", + "shield", + "shift-fill", + "shift", + "shop-window", + "shop", + "shuffle", + "signpost-2-fill", + "signpost-2", + "signpost-fill", + "signpost-split-fill", + "signpost-split", + "signpost", + "sim-fill", + "sim", + "skip-backward-btn-fill", + "skip-backward-btn", + "skip-backward-circle-fill", + "skip-backward-circle", + "skip-backward-fill", + "skip-backward", + "skip-end-btn-fill", + "skip-end-btn", + "skip-end-circle-fill", + "skip-end-circle", + "skip-end-fill", + "skip-end", + "skip-forward-btn-fill", + "skip-forward-btn", + "skip-forward-circle-fill", + "skip-forward-circle", + "skip-forward-fill", + "skip-forward", + "skip-start-btn-fill", + "skip-start-btn", + "skip-start-circle-fill", + "skip-start-circle", + "skip-start-fill", + "skip-start", + "slack", + "slash-circle-fill", + "slash-circle", + "slash-square-fill", + "slash-square", + "slash", + "sliders", + "smartwatch", + "snow", + "snow2", + "snow3", + "sort-alpha-down-alt", + "sort-alpha-down", + "sort-alpha-up-alt", + "sort-alpha-up", + "sort-down-alt", + "sort-down", + "sort-numeric-down-alt", + "sort-numeric-down", + "sort-numeric-up-alt", + "sort-numeric-up", + "sort-up-alt", + "sort-up", + "soundwave", + "speaker-fill", + "speaker", + "speedometer", + "speedometer2", + "spellcheck", + "square-fill", + "square-half", + "square", + "stack", + "star-fill", + "star-half", + "star", + "stars", + "stickies-fill", + "stickies", + "sticky-fill", + "sticky", + "stop-btn-fill", + "stop-btn", + "stop-circle-fill", + "stop-circle", + "stop-fill", + "stop", + "stoplights-fill", + "stoplights", + "stopwatch-fill", + "stopwatch", + "subtract", + "suit-club-fill", + "suit-club", + "suit-diamond-fill", + "suit-diamond", + "suit-heart-fill", + "suit-heart", + "suit-spade-fill", + "suit-spade", + "sun-fill", + "sun", + "sunglasses", + "sunrise-fill", + "sunrise", + "sunset-fill", + "sunset", + "symmetry-horizontal", + "symmetry-vertical", + "table", + "tablet-fill", + "tablet-landscape-fill", + "tablet-landscape", + "tablet", + "tag-fill", + "tag", + "tags-fill", + "tags", + "telegram", + "telephone-fill", + "telephone-forward-fill", + "telephone-forward", + "telephone-inbound-fill", + "telephone-inbound", + "telephone-minus-fill", + "telephone-minus", + "telephone-outbound-fill", + "telephone-outbound", + "telephone-plus-fill", + "telephone-plus", + "telephone-x-fill", + "telephone-x", + "telephone", + "terminal-fill", + "terminal", + "text-center", + "text-indent-left", + "text-indent-right", + "text-left", + "text-paragraph", + "text-right", + "textarea-resize", + "textarea-t", + "textarea", + "thermometer-half", + "thermometer-high", + "thermometer-low", + "thermometer-snow", + "thermometer-sun", + "thermometer", + "three-dots-vertical", + "three-dots", + "toggle-off", + "toggle-on", + "toggle2-off", + "toggle2-on", + "toggles", + "toggles2", + "tools", + "tornado", + "trash-fill", + "trash", + "trash2-fill", + "trash2", + "tree-fill", + "tree", + "triangle-fill", + "triangle-half", + "triangle", + "trophy-fill", + "trophy", + "tropical-storm", + "truck-flatbed", + "truck", + "tsunami", + "tv-fill", + "tv", + "twitch", + "twitter", + "type-bold", + "type-h1", + "type-h2", + "type-h3", + "type-italic", + "type-strikethrough", + "type-underline", + "type", + "ui-checks-grid", + "ui-checks", + "ui-radios-grid", + "ui-radios", + "umbrella-fill", + "umbrella", + "union", + "unlock-fill", + "unlock", + "upc-scan", + "upc", + "upload", + "vector-pen", + "view-list", + "view-stacked", + "vinyl-fill", + "vinyl", + "voicemail", + "volume-down-fill", + "volume-down", + "volume-mute-fill", + "volume-mute", + "volume-off-fill", + "volume-off", + "volume-up-fill", + "volume-up", + "vr", + "wallet-fill", + "wallet", + "wallet2", + "watch", + "water", + "whatsapp", + "wifi-1", + "wifi-2", + "wifi-off", + "wifi", + "wind", + "window-dock", + "window-sidebar", + "window", + "wrench", + "x-circle-fill", + "x-circle", + "x-diamond-fill", + "x-diamond", + "x-octagon-fill", + "x-octagon", + "x-square-fill", + "x-square", + "x", + "youtube", + "zoom-in", + "zoom-out", + "bank", + "bank2", + "bell-slash-fill", + "bell-slash", + "cash-coin", + "check-lg", + "coin", + "currency-bitcoin", + "currency-dollar", + "currency-euro", + "currency-exchange", + "currency-pound", + "currency-yen", + "dash-lg", + "exclamation-lg", + "file-earmark-pdf-fill", + "file-earmark-pdf", + "file-pdf-fill", + "file-pdf", + "gender-ambiguous", + "gender-female", + "gender-male", + "gender-trans", + "headset-vr", + "info-lg", + "mastodon", + "messenger", + "piggy-bank-fill", + "piggy-bank", + "pin-map-fill", + "pin-map", + "plus-lg", + "question-lg", + "recycle", + "reddit", + "safe-fill", + "safe2-fill", + "safe2", + "sd-card-fill", + "sd-card", + "skype", + "slash-lg", + "translate", + "x-lg", + "safe", + "apple", + "microsoft", + "windows", + "behance", + "dribbble", + "line", + "medium", + "paypal", + "pinterest", + "signal", + "snapchat", + "spotify", + "stack-overflow", + "strava", + "wordpress", + "vimeo", + "activity", + "easel2-fill", + "easel2", + "easel3-fill", + "easel3", + "fan", + "fingerprint", + "graph-down-arrow", + "graph-up-arrow", + "hypnotize", + "magic", + "person-rolodex", + "person-video", + "person-video2", + "person-video3", + "person-workspace", + "radioactive", + "webcam-fill", + "webcam", + "yin-yang", + "bandaid-fill", + "bandaid", + "bluetooth", + "body-text", + "boombox", + "boxes", + "dpad-fill", + "dpad", + "ear-fill", + "ear", + "envelope-check-1", + "envelope-check-fill", + "envelope-check", + "envelope-dash-1", + "envelope-dash-fill", + "envelope-dash", + "envelope-exclamation-1", + "envelope-exclamation-fill", + "envelope-exclamation", + "envelope-plus-fill", + "envelope-plus", + "envelope-slash-1", + "envelope-slash-fill", + "envelope-slash", + "envelope-x-1", + "envelope-x-fill", + "envelope-x", + "explicit-fill", + "explicit", + "git", + "infinity", + "list-columns-reverse", + "list-columns", + "meta", + "mortorboard-fill", + "mortorboard", + "nintendo-switch", + "pc-display-horizontal", + "pc-display", + "pc-horizontal", + "pc", + "playstation", + "plus-slash-minus", + "projector-fill", + "projector", + "qr-code-scan", + "qr-code", + "quora", + "quote", + "robot", + "send-check-fill", + "send-check", + "send-dash-fill", + "send-dash", + "send-exclamation-1", + "send-exclamation-fill", + "send-exclamation", + "send-fill", + "send-plus-fill", + "send-plus", + "send-slash-fill", + "send-slash", + "send-x-fill", + "send-x", + "send", + "steam", + "terminal-dash-1", + "terminal-dash", + "terminal-plus", + "terminal-split", + "ticket-detailed-fill", + "ticket-detailed", + "ticket-fill", + "ticket-perferated-fill", + "ticket-perferated", + "ticket", + "tiktok", + "window-dash", + "window-desktop", + "window-fullscreen", + "window-plus", + "window-split", + "window-stack", + "window-x", + "xbox", + "ethernet", + "hdmi-fill", + "hdmi", + "usb-c-fill", + "usb-c", + "usb-fill", + "usb-plug-fill", + "usb-plug", + "usb-symbol", + "usb", + "boombox-fill", + "displayport-1", + "displayport", + "gpu-card", + "memory", + "modem-fill", + "modem", + "motherboard-fill", + "motherboard", + "optical-audio-fill", + "optical-audio", + "pci-card", + "router-fill", + "router", + "ssd-fill", + "ssd", + "thunderbolt-fill", + "thunderbolt", + "usb-drive-fill", + "usb-drive", + "usb-micro-fill", + "usb-micro", + "usb-mini-fill", + "usb-mini", + "cloud-haze2", + "device-hdd-fill", + "device-hdd", + "device-ssd-fill", + "device-ssd", + "displayport-fill", + "mortarboard-fill", + "mortarboard", + "terminal-x" +] diff --git a/bcl/bootstrap/legacy/dependency/manipulator.js b/bcl/bootstrap/legacy/dependency/manipulator.js new file mode 100644 index 000000000..bdec344f9 --- /dev/null +++ b/bcl/bootstrap/legacy/dependency/manipulator.js @@ -0,0 +1,80 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.3): dom/manipulator.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + + function normalizeData(val) { + if (val === 'true') { + return true + } + + if (val === 'false') { + return false + } + + if (val === Number(val).toString()) { + return Number(val) + } + + if (val === '' || val === 'null') { + return null + } + + return val +} + +function normalizeDataKey(key) { + return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`) +} + +const Manipulator = { + setDataAttribute(element, key, value) { + element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value) + }, + + removeDataAttribute(element, key) { + element.removeAttribute(`data-bs-${normalizeDataKey(key)}`) + }, + + getDataAttributes(element) { + if (!element) { + return {} + } + + const attributes = {} + + Object.keys(element.dataset) + .filter(key => key.startsWith('bs')) + .forEach(key => { + let pureKey = key.replace(/^bs/, '') + pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length) + attributes[pureKey] = normalizeData(element.dataset[key]) + }) + + return attributes + }, + + getDataAttribute(element, key) { + return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)) + }, + + offset(element) { + const rect = element.getBoundingClientRect() + + return { + top: rect.top + window.pageYOffset, + left: rect.left + window.pageXOffset + } + }, + + position(element) { + return { + top: element.offsetTop, + left: element.offsetLeft + } + } +} + +export default Manipulator diff --git a/bcl/bootstrap/legacy/dependency/util/index.js b/bcl/bootstrap/legacy/dependency/util/index.js new file mode 100644 index 000000000..297e57149 --- /dev/null +++ b/bcl/bootstrap/legacy/dependency/util/index.js @@ -0,0 +1,336 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.2.3): util/index.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + +const MAX_UID = 1_000_000 +const MILLISECONDS_MULTIPLIER = 1000 +const TRANSITION_END = 'transitionend' + +// Shout-out Angus Croll (https://goo.gl/pxwQGp) +const toType = object => { + if (object === null || object === undefined) { + return `${object}` + } + + return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase() +} + +/** + * Public Util API + */ + +const getUID = prefix => { + do { + prefix += Math.floor(Math.random() * MAX_UID) + } while (document.getElementById(prefix)) + + return prefix +} + +const getSelector = element => { + let selector = element.getAttribute('data-bs-target') + + if (!selector || selector === '#') { + let hrefAttribute = element.getAttribute('href') + + // The only valid content that could double as a selector are IDs or classes, + // so everything starting with `#` or `.`. If a "real" URL is used as the selector, + // `document.querySelector` will rightfully complain it is invalid. + // See https://github.com/twbs/bootstrap/issues/32273 + if (!hrefAttribute || (!hrefAttribute.includes('#') && !hrefAttribute.startsWith('.'))) { + return null + } + + // Just in case some CMS puts out a full URL with the anchor appended + if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { + hrefAttribute = `#${hrefAttribute.split('#')[1]}` + } + + selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null + } + + return selector +} + +const getSelectorFromElement = element => { + const selector = getSelector(element) + + if (selector) { + return document.querySelector(selector) ? selector : null + } + + return null +} + +const getElementFromSelector = element => { + const selector = getSelector(element) + + return selector ? document.querySelector(selector) : null +} + +const getTransitionDurationFromElement = element => { + if (!element) { + return 0 + } + + // Get transition-duration of the element + let { transitionDuration, transitionDelay } = window.getComputedStyle(element) + + const floatTransitionDuration = Number.parseFloat(transitionDuration) + const floatTransitionDelay = Number.parseFloat(transitionDelay) + + // Return 0 if element or transition duration is not found + if (!floatTransitionDuration && !floatTransitionDelay) { + return 0 + } + + // If multiple durations are defined, take the first + transitionDuration = transitionDuration.split(',')[0] + transitionDelay = transitionDelay.split(',')[0] + + return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER +} + +const triggerTransitionEnd = element => { + element.dispatchEvent(new Event(TRANSITION_END)) +} + +const isElement = object => { + if (!object || typeof object !== 'object') { + return false + } + + if (typeof object.jquery !== 'undefined') { + object = object[0] + } + + return typeof object.nodeType !== 'undefined' +} + +const getElement = object => { + // it's a jQuery object or a node element + if (isElement(object)) { + return object.jquery ? object[0] : object + } + + if (typeof object === 'string' && object.length > 0) { + return document.querySelector(object) + } + + return null +} + +const isVisible = element => { + if (!isElement(element) || element.getClientRects().length === 0) { + return false + } + + const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible' + // Handle `details` element as its content may falsie appear visible when it is closed + const closedDetails = element.closest('details:not([open])') + + if (!closedDetails) { + return elementIsVisible + } + + if (closedDetails !== element) { + const summary = element.closest('summary') + if (summary && summary.parentNode !== closedDetails) { + return false + } + + if (summary === null) { + return false + } + } + + return elementIsVisible +} + +const isDisabled = element => { + if (!element || element.nodeType !== Node.ELEMENT_NODE) { + return true + } + + if (element.classList.contains('disabled')) { + return true + } + + if (typeof element.disabled !== 'undefined') { + return element.disabled + } + + return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false' +} + +const findShadowRoot = element => { + if (!document.documentElement.attachShadow) { + return null + } + + // Can find the shadow root otherwise it'll return the document + if (typeof element.getRootNode === 'function') { + const root = element.getRootNode() + return root instanceof ShadowRoot ? root : null + } + + if (element instanceof ShadowRoot) { + return element + } + + // when we don't find a shadow root + if (!element.parentNode) { + return null + } + + return findShadowRoot(element.parentNode) +} + +const noop = () => {} + +/** + * Trick to restart an element's animation + * + * @param {HTMLElement} element + * @return void + * + * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation + */ +const reflow = element => { + element.offsetHeight // eslint-disable-line no-unused-expressions +} + +const getjQuery = () => { + if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { + return window.jQuery + } + + return null +} + +const DOMContentLoadedCallbacks = [] + +const onDOMContentLoaded = callback => { + if (document.readyState === 'loading') { + // add listener on the first call when the document is in loading state + if (!DOMContentLoadedCallbacks.length) { + document.addEventListener('DOMContentLoaded', () => { + for (const callback of DOMContentLoadedCallbacks) { + callback() + } + }) + } + + DOMContentLoadedCallbacks.push(callback) + } else { + callback() + } +} + +const isRTL = () => document.documentElement.dir === 'rtl' + +const defineJQueryPlugin = plugin => { + onDOMContentLoaded(() => { + const $ = getjQuery() + /* istanbul ignore if */ + if ($) { + const name = plugin.NAME + const JQUERY_NO_CONFLICT = $.fn[name] + $.fn[name] = plugin.jQueryInterface + $.fn[name].Constructor = plugin + $.fn[name].noConflict = () => { + $.fn[name] = JQUERY_NO_CONFLICT + return plugin.jQueryInterface + } + } + }) +} + +const execute = callback => { + if (typeof callback === 'function') { + callback() + } +} + +const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { + if (!waitForTransition) { + execute(callback) + return + } + + const durationPadding = 5 + const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding + + let called = false + + const handler = ({ target }) => { + if (target !== transitionElement) { + return + } + + called = true + transitionElement.removeEventListener(TRANSITION_END, handler) + execute(callback) + } + + transitionElement.addEventListener(TRANSITION_END, handler) + setTimeout(() => { + if (!called) { + triggerTransitionEnd(transitionElement) + } + }, emulatedDuration) +} + +/** + * Return the previous/next element of a list. + * + * @param {array} list The list of elements + * @param activeElement The active element + * @param shouldGetNext Choose to get next or previous element + * @param isCycleAllowed + * @return {Element|elem} The proper element + */ +const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { + const listLength = list.length + let index = list.indexOf(activeElement) + + // if the element does not exist in the list return an element + // depending on the direction and if cycle is allowed + if (index === -1) { + return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0] + } + + index += shouldGetNext ? 1 : -1 + + if (isCycleAllowed) { + index = (index + listLength) % listLength + } + + return list[Math.max(0, Math.min(index, listLength - 1))] +} + +export { + defineJQueryPlugin, + execute, + executeAfterTransition, + findShadowRoot, + getElement, + getElementFromSelector, + getjQuery, + getNextActiveElement, + getSelectorFromElement, + getTransitionDurationFromElement, + getUID, + isDisabled, + isElement, + isRTL, + isVisible, + noop, + onDOMContentLoaded, + reflow, + triggerTransitionEnd, + toType +} diff --git a/bcl/bootstrap/legacy/scrollspy-legacy.js b/bcl/bootstrap/legacy/scrollspy-legacy.js new file mode 100644 index 000000000..bfd9cfcff --- /dev/null +++ b/bcl/bootstrap/legacy/scrollspy-legacy.js @@ -0,0 +1,294 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v5.1.3): scrollspy.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + * -------------------------------------------------------------------------- + */ + +// Old versions +import Manipulator from './dependency/manipulator' + + import { + defineJQueryPlugin, + getElement, + getSelectorFromElement, +} from './dependency/util/index' +import EventHandler from './dom/event-handler' +import SelectorEngine from './dom/selector-engine' +import BaseComponent from './base-component' + +/** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + +const NAME = 'scrollspy' +const DATA_KEY = 'bs.scrollspy' +const EVENT_KEY = `.${DATA_KEY}` +const DATA_API_KEY = '.data-api' + +const Default = { + offset: 10, + method: 'auto', + target: '' +} + +const DefaultType = { + offset: 'number', + method: 'string', + target: '(string|element)' +} + +const EVENT_ACTIVATE = `activate${EVENT_KEY}` +const EVENT_SCROLL = `scroll${EVENT_KEY}` +const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}` + +const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item' +const CLASS_NAME_ACTIVE = 'active' + +const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]' +const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group' +const SELECTOR_NAV_LINKS = '.nav-link' +const SELECTOR_NAV_ITEMS = '.nav-item' +const SELECTOR_LIST_ITEMS = '.list-group-item' +const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}, .${CLASS_NAME_DROPDOWN_ITEM}` +const SELECTOR_DROPDOWN = '.dropdown' +const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle' + +const METHOD_OFFSET = 'offset' +const METHOD_POSITION = 'position' + +/** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + +class ScrollSpy extends BaseComponent { + constructor(element, config) { + super(element) + this._scrollElement = this._element.tagName === 'BODY' ? window : this._element + this._config = this._getConfig(config) + this._offsets = [] + this._targets = [] + this._activeTarget = null + this._scrollHeight = 0 + + EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process()) + + this.refresh() + this._process() + } + + // Getters + + static get Default() { + return Default + } + + static get NAME() { + return NAME + } + + // Public + + refresh() { + const autoMethod = this._scrollElement === this._scrollElement.window ? + METHOD_OFFSET : + METHOD_POSITION + + const offsetMethod = this._config.method === 'auto' ? + autoMethod : + this._config.method + + const offsetBase = offsetMethod === METHOD_POSITION ? + this._getScrollTop() : + 0 + + this._offsets = [] + this._targets = [] + this._scrollHeight = this._getScrollHeight() + + const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target) + + targets.map(element => { + const targetSelector = getSelectorFromElement(element) + const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null + + if (target) { + const targetBCR = target.getBoundingClientRect() + if (targetBCR.width || targetBCR.height) { + return [ + Manipulator[offsetMethod](target).top + offsetBase, + targetSelector + ] + } + } + + return null + }) + .filter(item => item) + .sort((a, b) => a[0] - b[0]) + .forEach(item => { + this._offsets.push(item[0]) + this._targets.push(item[1]) + }) + } + + dispose() { + EventHandler.off(this._scrollElement, EVENT_KEY) + super.dispose() + } + + // Private + + _getConfig(config) { + config = { + ...Default, + ...Manipulator.getDataAttributes(this._element), + ...(typeof config === 'object' && config ? config : {}) + } + + config.target = getElement(config.target) || document.documentElement + + return config + } + + _getScrollTop() { + return this._scrollElement === window ? + this._scrollElement.pageYOffset : + this._scrollElement.scrollTop + } + + _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max( + document.body.scrollHeight, + document.documentElement.scrollHeight + ) + } + + _getOffsetHeight() { + return this._scrollElement === window ? + window.innerHeight : + this._scrollElement.getBoundingClientRect().height + } + + _process() { + const scrollTop = this._getScrollTop() + this._config.offset + const scrollHeight = this._getScrollHeight() + const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight() + + if (this._scrollHeight !== scrollHeight) { + this.refresh() + } + + if (scrollTop >= maxScroll) { + const target = this._targets[this._targets.length - 1] + + if (this._activeTarget !== target) { + this._activate(target) + } + + return + } + + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null + this._clear() + return + } + + for (let i = this._offsets.length; i--;) { + const isActiveTarget = this._activeTarget !== this._targets[i] && + scrollTop >= this._offsets[i] && + (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]) + + if (isActiveTarget) { + this._activate(this._targets[i]) + } + } + } + + _activate(target) { + this._activeTarget = target + + this._clear() + + const queries = SELECTOR_LINK_ITEMS.split(',') + .map(selector => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`) + + const link = SelectorEngine.findOne(queries.join(','), this._config.target) + + link.classList.add(CLASS_NAME_ACTIVE) + if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { + SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, link.closest(SELECTOR_DROPDOWN)) + .classList.add(CLASS_NAME_ACTIVE) + } else { + SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP) + .forEach(listGroup => { + // Set triggered links parents as active + // With both + {% endif %} + {% if _tabs_content %} +
+ {%- block contents -%} + {% if _items is not empty and _items is iterable %} + {% for _item in _items %} + {% if _item.content is not empty %} + {% set _content_class = 'tab-pane fade' %} + {% if _item.active %} + {% set _content_class = _content_class ~ ' show active' %} + {% endif %} +
+ {{- _item.content -}} +
+ {% endif %} + {% endfor %} + {% endif %} + {%- endblock -%} +
+ {% endif %} +{% endapply %} +{% endmacro %} + +{{ navigation.render(items, pills, tabs, tabs_content, vertical, full_width, alignment, id, nav, navbar, attributes) }} + +{% endapply %} diff --git a/assets/bcl/bcl-offcanvas/bcl-offcanvas.html.twig b/assets/bcl/bcl-offcanvas/bcl-offcanvas.html.twig new file mode 100644 index 000000000..0b657ad05 --- /dev/null +++ b/assets/bcl/bcl-offcanvas/bcl-offcanvas.html.twig @@ -0,0 +1,119 @@ +{% apply spaceless %} + +{# Parameters: + - title: (string) (default: '') + - title_tag: (string) (default: 'h2') + - title_link: (link object) (default: {}) + - title_attributes (drupal attrs) + - placement (string) (default: '') (start, end, top, bottom) + - id (string) (default: '') + - body (string) (default: '') + - with_body_scroll (boolean) (default: false) + - with_backdrop (boolean) (default: true) + - with_close (boolean) (default: true) + - close_aria_label (default: '') + - extra_classes_body (string) (default: '') + - extra_classes_header (string) (default: '') + - extra_classes_close (string) (default: '') + - responsiveness (string) (default: '') + options: ['sm', 'md', 'lg', 'xl', 'xxl'] + - attributes (drupal attrs) +#} + +{% set _title = title|default('') %} +{% set _title_tag = title_tag|default('h2') %} +{% set _title_link = title_link|default({}) %} +{% set _title_attributes = title_attributes ?: create_attribute() %} +{% set _placement = placement|default('') %} +{% set _id = id|default('') %} +{% set _body = body|default('') %} +{% set _with_body_scroll = with_body_scroll ?? false %} +{% set _with_backdrop = with_backdrop ?? true %} +{% set _with_close = with_close ?? true %} +{% set _close_aria_label = close_aria_label|default('') %} +{% set _extra_classes_body = extra_classes_body|default('') %} +{% set _extra_classes_header = extra_classes_header|default('') %} +{% set _extra_classes_close = extra_classes_close|default('') %} +{% set _responsiveness = responsiveness|default('') %} + +{% if _responsiveness is not empty %} + {% set _classes = ['offcanvas-' ~ _responsiveness] %} +{% else %} + {% set _classes = ['offcanvas'] %} +{% endif %} + +{% set _class_body = 'offcanvas-body' ~ (_extra_classes_body ? ' ' ~ _extra_classes_body : '') %} +{% set _class_header = 'offcanvas-header' ~ (_extra_classes_header ? ' ' ~ _extra_classes_header : '') %} + +{% if _placement is not empty %} + {% set _classes = _classes|merge(['offcanvas-' ~ _placement]) %} +{% endif %} + +{% if _title is not empty %} + {% set _aria_labelled = _title.id|default('') %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% if _aria_labelled is defined and _aria_labelled is not empty %} + {% set attributes = attributes.setAttribute('aria-labelledby', _aria_labelled) %} +{% endif %} + +{% if _id is not empty %} + {% set attributes = attributes.setAttribute('id', _id) %} +{% endif %} + +{% if _with_body_scroll %} + {% set attributes = attributes.setAttribute('data-bs-scroll', 'true') %} +{% endif %} + +{% if not _with_backdrop %} + {% set attributes = attributes.setAttribute('data-bs-backdrop', 'false') %} +{% endif %} + +{% set attributes = attributes.setAttribute('tabindex', '-1').addClass(_classes) %} + +
+{% if _with_close or _title is not empty %} +
+ {% if _title is not empty %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _title, + title_tag: _title_tag, + title_link: _title_link, + attributes: _title_attributes.addClass(['offcanvas-title']), + } only %} + {% endif %} + {% if _with_close %} + {% set button_attributes = create_attribute() + .addClass(['btn-close', 'text-reset']) + .setAttribute('data-bs-dismiss', 'offcanvas') + .setAttribute('data-bs-target', '#' ~ _id) + .setAttribute('aria-label', _close_aria_label) + %} + {% if _extra_classes_close is not empty %} + {% set button_attributes = button_attributes.addClass(_extra_classes_close) %} + {% endif %} + {%- include '@oe-bcl/bcl-button/button.html.twig' with { + attributes: button_attributes, + clean_class: true + } only -%} + {% endif %} +
+{% endif %} +{%- if _body is not empty -%} +
+{%- endif -%} + {%- block body -%} + {{ _body }} + {%- endblock -%} +{%- if _body is not empty -%} +
+{%- endif -%} +
+ +{% endapply %} diff --git a/assets/bcl/bcl-page/bcl-page.html.twig b/assets/bcl/bcl-page/bcl-page.html.twig new file mode 100644 index 000000000..adb9041b7 --- /dev/null +++ b/assets/bcl/bcl-page/bcl-page.html.twig @@ -0,0 +1,45 @@ +{% extends '@oe-bcl/bcl-base-templates/content-type.html.twig' %} + +{% block sidebar %} + {% include '@oe-bcl/bcl-inpage-navigation/inpage-navigation.html.twig' with sidebar only %} +{% endblock %} + +{% block content %} +

{{ get_dummy_text(6) }} +

+

Section 1

+ {% if featured_item %} + {% include '@oe-bcl/bcl-featured-media/featured-media.html.twig' with featured_item only %} + {% endif %} + + {% if page_banner %} + {% include '@oe-bcl/bcl-banner/banner.html.twig' with page_banner only %} + {% endif %} + + {% if listing %} + {% include '@oe-bcl/bcl-listing/listing.html.twig' with listing only %} + {% endif %} + +

Section 2

+ + {{ get_dummy_text(6, true) }} + + {% if blockquote %} + {% include '@oe-bcl/bcl-blockquote/blockquote.html.twig' with blockquote only %} + {% endif %} + {% if accordion %} + {% include '@oe-bcl/bcl-accordion/accordion.html.twig' with accordion only %} + {% endif %} + {% if timeline %} + {% include '@oe-bcl/bcl-timeline/timeline.html.twig' with timeline only %} + {% endif %} + + {{ get_dummy_text(8, true) }} + +

Section 3

+ + {{ get_dummy_text(4, true) }} + + {% include '@oe-bcl/bcl-file/file.html.twig' with files[0] only %} + {% include '@oe-bcl/bcl-file/file.html.twig' with files[1] only %} +{% endblock %} diff --git a/assets/bcl/bcl-pagination/bcl-pagination-item.html.twig b/assets/bcl/bcl-pagination/bcl-pagination-item.html.twig new file mode 100644 index 000000000..76e6ec9d9 --- /dev/null +++ b/assets/bcl/bcl-pagination/bcl-pagination-item.html.twig @@ -0,0 +1,73 @@ +{% apply spaceless %} + +{# Parameters: + - path (string) (default: '') + - label (string) (default: '') + - disabled (boolean) (default: false) + - active (boolean) (default: false) + - aria_label (string) (default: '') - deprecated, use attributes + - icon (icon object) (default: {}) + - attributes (drupal attrs) +#} + +{% set _path = path|default('') %} +{% set _label = label|default('') %} +{% set _disabled = disabled ?? false %} +{% set _active = active ?? false %} +{% set _aria_label = aria_label|default('') %} +{% set _icon = icon|default({}) %} +{% set _icon_path = icon_path|default('') %} +{% set _icon_name = icon_name|default('') %} +{% set _icon_html = icon_html|default('') %} +{% set _classes = ['page-link'] %} + +{% if _icon_path is not empty and _icon is empty %} + {% if _icon_name is not empty %} + {% set _icon = _icon|merge({ + name: _icon_name, + path: _icon_path, + size: "fluid" + }) %} + {% set _label = "" %} + {% endif %} +{% else %} + {% if _icon_html is not empty %} + {% set _label %} + + {% endset %} + {% endif %} +{% endif %} + +{% if _icon is not empty %} + {% set _icon = _icon|merge({ + path: _icon_path, + }) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% if _aria_label is not empty %} + {% set attributes = attributes.setAttribute('aria-label', _aria_label ) %} +{% endif %} + +{% if _active %} + {% set attributes = attributes.setAttribute('aria-current', 'page' ) %} +{% endif %} + +{% set attributes = attributes.addClass(_classes) %} + +{% if _path %} + {%- include '@oe-bcl/bcl-link/link.html.twig' with { + label: _label, + path: _path, + disabled: _disabled, + icon: _icon, + attributes: attributes, + } only -%} +{% else %} +
{{- _label -}}
+{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-pagination/bcl-pagination.html.twig b/assets/bcl/bcl-pagination/bcl-pagination.html.twig new file mode 100644 index 000000000..9a3117cde --- /dev/null +++ b/assets/bcl/bcl-pagination/bcl-pagination.html.twig @@ -0,0 +1,161 @@ +{% apply spaceless %} + +{# Parameters: + - size (string) (default: '') + - options ['sm', 'lg'] + - alignment (string) (default: '') + - options ['end', 'center'] + - variant: (string) (default: '') + - options: ['glossary'] + - aria_label (string) (default: '') - deprecated, use attributes + - enable_prev_next_icon (boolean) (default: false) + - enable_first_last_icon (boolean) (default: true) + - ellipsis_before (boolean) (default: false) + - ellipsis_after (boolean) (default: false) + - first (pagination Item object) (default: {}) + - prev (pagination Item object) (default: {}) + - next (pagination Item object) (default: {}) + - last (pagination Item object) (default: {}) + - items (pagination item[]) (default: []) + format: [ + { + - path (string) (default: '') + - label (string) (default: '') + - disabled (boolean) (default: false) + - active (boolean) (default: false) + - aria_label (string) (default: '') - deprecated, use attributes + - icon (Icon component) (default: {}) + - attributes (drupal attrs) + } + - icon_path (string) (default: '') + - attributes (drupal attrs) + - list_attributes (drupal attrs) +#} + +{% set _size = size|default('') %} +{% set _alignment = alignment|default('') %} +{% set _variant = variant|default('') %} +{% set _aria_label = aria_label|default('') %} +{% set _enable_prev_next_icon = enable_prev_next_icon ?? false %} +{% set _enable_first_last_icon = enable_first_last_icon ?? true %} +{% set _ellipsis_before = ellipsis_before ?? false %} +{% set _ellipsis_after = ellipsis_after ?? false %} +{% set _first = first|default({}) %} +{% set _prev = prev|default({}) %} +{% set _next = next|default({}) %} +{% set _last = last|default({}) %} +{% set _items = items|default([]) %} +{% set _icon_path = icon_path|default('') %} +{% set _internal_items = [] %} + +{% if _enable_first_last_icon %} + {% if _first is not empty %} + {% set _first = _first|merge({ + icon_html: "«", + icon_name: "chevron-double-left", + }) %} + {% endif %} + {% if _last is not empty %} + {% set _last = _last|merge({ + icon_html: '»', + icon_name: "chevron-double-right", + }) %} + {% endif %} +{% endif %} + +{% if _enable_prev_next_icon %} + {% if _prev is not empty %} + {% set _prev = _prev|merge({ + icon_html: "‹", + icon_name: "chevron-left", + }) %} + {% endif %} + {% if _next is not empty %} + {% set _next = _next|merge({ + icon_html: "›", + icon_name: "chevron-right", + }) %} + {% endif %} +{% endif %} + + +{% set _internal_items = _internal_items|merge([_first, _prev]) %} + +{% set _ellipsis_markup %} … {% endset %} + +{% if _ellipsis_before %} + {% set _ellipsis_before_item = { + icon_html: _ellipsis_markup, + icon_path: "", + } %} + {% set _internal_items = _internal_items|merge([_ellipsis_before_item]) %} +{% endif %} + +{% set _internal_items = _internal_items|merge(_items) %} + +{% if _ellipsis_after %} + {% set _ellipsis_after_item = { + icon_html: _ellipsis_markup, + icon_path: "", + } %} + {% set _internal_items = _internal_items|merge([_ellipsis_after_item]) %} +{% endif %} + +{% set _internal_items = _internal_items|merge([_next, _last]) %} + +{% if list_attributes is empty %} + {% set list_attributes = create_attribute() %} +{% endif %} + +{% set list_attributes = list_attributes.addClass('pagination') %} +{% if _size is not empty %} + {% set list_attributes = list_attributes.addClass('pagination-' ~ _size) %} +{% endif %} +{% if _variant is not empty %} + {% set list_attributes = list_attributes.addClass('pagination--' ~ _variant) %} +{% endif %} +{% if _alignment is not empty %} + {% set list_attributes = list_attributes.addClass('justify-content-' ~ _alignment) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.setAttribute('role', 'navigation') %} + +{% if _variant == 'glossary' %} + {% set attributes = attributes.addClass(['bcl-glossary']) %} +{% endif %} + +{% if _aria_label is not empty %} + {% set attributes = attributes.setAttribute('aria-label', aria_label) %} +{% endif %} + + + +{% if _internal_items is not empty and _internal_items is iterable %} + {% for _item in _internal_items %} + {% if _item is not empty %} + {% set _item_class = ['page-item'] %} + {% if _item.disabled %} + {% set _item_class = _item_class|merge(['disabled']) %} + {% endif %} + {% if _item.active %} + {% set _item_class = _item_class|merge(['active']) %} + {% endif %} +
  • + {% if _item.icon_path is not defined %} + {% set _item = _item|merge({ + icon_path: _icon_path, + }) %} + {% endif %} + {% include '@oe-bcl/bcl-pagination/pagination-item.html.twig' with _item only %} +
  • + {% endif %} + {% endfor %} +{% endif %} + + + +{% endapply %} diff --git a/assets/bcl/bcl-person/bcl-person.html.twig b/assets/bcl/bcl-person/bcl-person.html.twig new file mode 100644 index 000000000..17c0462ac --- /dev/null +++ b/assets/bcl/bcl-person/bcl-person.html.twig @@ -0,0 +1,29 @@ +{% extends '@oe-bcl/bcl-base-templates/content-type.html.twig' %} + +{% block sidebar %} + {% include '@oe-bcl/bcl-inpage-navigation/inpage-navigation.html.twig' with sidebar only %} +{% endblock %} + +{% block content %} + {% if information.main_title is not empty %} +

    {{- information.main_title -}}

    + {% endif %} + {% if information.content is not empty %} +
    + {{- information.content -}} +
    + {% endif %} + + {% if files.main_title is not empty %} +

    {{- files.main_title -}}

    + {% endif %} + {% if files.listing is defined and files.listing is not empty %} + {% for file in files.listing %} + {% include '@oe-bcl/bcl-file/file.html.twig' with file only %} + {% endfor %} + {% endif %} +{% endblock %} diff --git a/assets/bcl/bcl-placeholder/bcl-placeholder.html.twig b/assets/bcl/bcl-placeholder/bcl-placeholder.html.twig new file mode 100644 index 000000000..d299ac654 --- /dev/null +++ b/assets/bcl/bcl-placeholder/bcl-placeholder.html.twig @@ -0,0 +1,45 @@ +{% apply spaceless %} + +{# Parameters: + - width (int) (default: 0) - between 0-100 + - variant (string) (default: '') + - options ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'] + - size (string) (default: '') + - options ['xs', 'lg'] + - animation (string) (default: '') + - options ['glow', 'wave'] + - attributes (drupal attrs) +#} + +{% set _width = width|default(0) %} +{% set _variant = variant|default('') %} +{% set _size = size|default('') %} +{% set _animation = animation|default('') %} + +{% set _classes = ['placeholder'] %} + +{% if _size is not empty %} + {% set _classes = _classes|merge(['placeholder-' ~ _size]) %} +{% endif %} + +{% if _variant is not empty %} + {% set _classes = _classes|merge(['text-bg-' ~ _variant]) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes) %} +{% set attributes = attributes.setAttribute('style', 'width: ' ~ _width ~ '%;') %} + +{% if _animation is not empty %} +

    +{% endif %} + + +{% if _animation is not empty %} +

    +{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-progress/bcl-progress.html.twig b/assets/bcl/bcl-progress/bcl-progress.html.twig new file mode 100644 index 000000000..3e1ec2011 --- /dev/null +++ b/assets/bcl/bcl-progress/bcl-progress.html.twig @@ -0,0 +1,73 @@ +{% apply spaceless %} + +{# Parameters: + - progress (int) (default: 0) + - min (int) (default: 0) + - max (int) (default: 100) + - striped (boolean) (default: false) + - animated (boolean) (default: false) + - hidden_label (boolean) (default: false) + - label (string) (default: '') + - bar_label (string) (default: '') + - variant (string) (default: '') + - message (string) (default: '') + - attributes (drupal attrs) +#} + +{% set _progress = progress|default(0) %} +{% set _min = min|default(0) %} +{% set _max = max|default(100) %} +{% set _striped = striped ?? false %} +{% set _animated = animated ?? false %} +{% set _hidden_label = hidden_label ?? false %} +{% set _label = label|default('') %} +{% set _bar_label = bar_label|default('') %} +{% set _variant = variant|default('') %} +{% set _message = message|default('') %} + +{% set _classes = 'progress-bar' %} +{% if _striped is not empty %} + {% set _classes = _classes ~ ' progress-bar-striped' %} +{% endif %} +{% if _animated is not empty %} + {% set _classes = _classes ~ ' progress-bar-animated' %} +{% endif %} +{% if _variant is not empty %} + {% set _classes = _classes ~ ' text-bg-' ~ _variant %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(['progress']) %} + +{% if _bar_label is empty %} + {% set _bar_label = _progress ~ '%' %} +{% endif %} + +{% if _label is not empty %} + +{% endif %} +
    +
    + {%- if not _hidden_label -%} + {{- _bar_label -}} + {%- endif -%} +
    +
    +{% if _message is not empty %} + {{ _message }} +{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-project-status/bcl-project-contributions.html.twig b/assets/bcl/bcl-project-status/bcl-project-contributions.html.twig new file mode 100644 index 000000000..362a4c3cb --- /dev/null +++ b/assets/bcl/bcl-project-status/bcl-project-contributions.html.twig @@ -0,0 +1,56 @@ +{% apply spaceless %} + +{# Parameters: + - corporate_contributions (string) (default: '') // value every 5 percent + - legend (description list object) (default: {}) + - chart (boolean) (default: false) + + Blocks - + project_status_contrib_chart + project_status_contrib_legend +#} + +{% set _corporate_contributions = corporate_contributions|default('') %} +{% set _legend = legend|default({}) %} +{% set _chart = chart ?? false %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass([ + 'bcl-project-contributions', + 'border-bottom', + 'pb-4', + 'mb-4' +]) %} + +
    +
    + + {% if _chart is not empty %} +
    + {% block project_status_contrib_chart %} +
    + + + + + + +
    + {% endblock %} +
    + {% endif %} + + {% if _legend is not empty %} +
    + {% block project_status_contrib_legend %} + {% include '@oe-bcl/bcl-description-list/description-list.html.twig' with _legend only %} + {% endblock %} +
    + {% endif %} +
    +
    + +{% endapply %} diff --git a/assets/bcl/bcl-project-status/bcl-project-status.html.twig b/assets/bcl/bcl-project-status/bcl-project-status.html.twig new file mode 100644 index 000000000..ed48ff127 --- /dev/null +++ b/assets/bcl/bcl-project-status/bcl-project-status.html.twig @@ -0,0 +1,99 @@ +{% apply spaceless %} + +{# Parameters: + - label (string) (default: '') + - status (string) (default: 'planned') + - badge (string) (default: '') + - start_date (string) (default: '') + - start_label (string) (default: '') + - end_date (string) (default: '') + - end_label (string) (default: '') + - progress (string) (default: '') + - attributes (drupal attrs) +#} + +{% set _label = label|default('') %} +{% set _status = status|default('planned') %} +{% set _badge = badge|default('') %} +{% set _start_date = start_date|default('') %} +{% set _start_label = start_label|default('') %} +{% set _end_date = end_date|default('') %} +{% set _end_label = end_label|default('') %} +{% set _progress = progress|default('') %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass([ + 'bcl-project-status', + 'border-bottom', + 'pb-4', + 'mb-4' +]) %} + +{% set _bgs = { + ongoing: 'info', + closed: 'dark', + planned: 'secondary', + } %} +{% set _bg = _bgs[_status]|default('secondary') %} + +
    +
    +
    + {% if _label is not empty %} +

    {{ _label }}

    + {% endif %} + + {% if _badge is not empty %} + {% include '@oe-bcl/bcl-badge/badge.html.twig' with { + label: _badge, + rounded_pill: true, + background: _bg, + attributes: create_attribute().addClass(['mb-3', 'mb-md-0']), + } only %} + {% endif %} + +
    + +
    +
    + + {% if _start_date is not empty and _start_label is not empty %} +

    + {{- _start_label -}}
    + + {{- _start_date -}} + +

    + {% endif %} + + {% if _end_date is not empty and _end_label is not empty %} +

    + {{- _end_label -}}
    + + {{- _end_date -}} + +

    + {% endif %} +
    + + {% if _progress is not empty or _status != 'ongoing' %} + {% if _progress is empty %} + {% set _progress = _status == 'closed' ? 100 : 0 %} + {% endif %} + {% include '@oe-bcl/bcl-progress/progress.html.twig' with { + variant: _bg, + hidden_label: true, + progress: _progress, + } only %} + {% endif %} + +
    +
    +
    + + + +{% endapply %} diff --git a/assets/bcl/bcl-project/bcl-project-lists.html.twig b/assets/bcl/bcl-project/bcl-project-lists.html.twig new file mode 100644 index 000000000..1e8e3cfb1 --- /dev/null +++ b/assets/bcl/bcl-project/bcl-project-lists.html.twig @@ -0,0 +1,73 @@ +{% apply spaceless %} + + +{# + Parameters: + - title: (string) (default: '') + - title_tag: (string) (default: 'h2') + - title_link: (link object) (default: {}) + - title_attributes (drupal attrs) + - items (array) (default: []) + { + title: (heading object), + content: [ + description list object + ] + } +#} + +{% set _title = title|default('') %} +{% set _title_tag = title_tag|default('h2') %} +{% set _title_link = title_link|default({}) %} +{% set _title_attributes = title_attributes ?: create_attribute() %} +{% set _items = items|default([]) %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set _title_classes = ['my-4-5'] %} +{% set _title_attributes = _title_attributes.addClass(_title_classes) %} + +
    +{% if _title is not empty %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _title, + title_tag: _title_tag, + title_link: _title_link, + attributes: _title_attributes, + } only %} +{% endif %} +{% if _items is defined and _items is not empty %} + {% for _item in _items %} + {% if _item.title is not empty %} + {% set _item_title_attributes = _item.title_attributes ?: create_attribute() %} + {% set _item_title_attributes = _item_title_attributes.addClass(['mb-3']) %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _item.title, + title_tag: _item.title_tag|default('h3'), + title_link: _item.title_link|default({}), + attributes: _item_title_attributes, + } only %} + {% endif %} + {% for _list in _item.content %} + {% if _list.attributes is empty %} + {% set _list = _list|merge({ + attributes: create_attribute() + }) %} + {% endif %} + {% if not loop.last %} + {% set _list = _list|merge({ + attributes: _list.attributes.addClass(['border-bottom', 'mb-3']) + }) + %} + {% endif %} + {% include '@oe-bcl/bcl-description-list/description-list.html.twig' with _list only %} + {% endfor %} + {% endfor %} +{% endif %} +
    + +{% endapply %} diff --git a/assets/bcl/bcl-project/bcl-project.html.twig b/assets/bcl/bcl-project/bcl-project.html.twig new file mode 100644 index 000000000..6284657dc --- /dev/null +++ b/assets/bcl/bcl-project/bcl-project.html.twig @@ -0,0 +1,72 @@ +{% extends '@oe-bcl/bcl-base-templates/content-type.html.twig' %} + +{% block sidebar %} + {% include '@oe-bcl/bcl-inpage-navigation/inpage-navigation.html.twig' with sidebar only %} +{% endblock %} + +{% block content %} + {% if project_status is not empty %} + {% if project_status_title is not empty %} + {% set _project_title_attributes = create_attribute().addClass(['mb-4']) %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: project_status_title, + title_tag: 'h2', + attributes: create_attribute().setAttribute('id', project_status_id), + } only %} + {% endif %} + {% include '@oe-bcl/bcl-project-status/project-status.html.twig' with project_status %} + {% if project_contributions is not empty %} + {% include '@oe-bcl/bcl-project-status/project-contributions.html.twig' with project_contributions %} + {% endif %} + {% if status_lists is not empty %} + {% include '@oe-bcl/bcl-project/project-lists.html.twig' with status_lists only %} + {% endif %} + {% endif %} + + {% if first_paragraphs is defined and first_paragraphs is not empty %} + {% for _paragraph in first_paragraphs %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _paragraph.title, + title_tag: 'h2', + attributes: create_attribute().addClass(['mb-4', 'pt-3']) + .setAttribute('id', _paragraph.title_id), + } only %} + {{- _paragraph.content -}} + {% endfor %} + {% endif %} + + {% if featured_lists is not empty %} + {% include '@oe-bcl/bcl-project/project-lists.html.twig' with featured_lists only %} + {% endif %} + + {% if content_lists is not empty %} + {% include '@oe-bcl/bcl-project/project-lists.html.twig' with content_lists only %} + {% endif %} + + {% if second_paragraphs is defined and second_paragraphs is not empty %} + {% for _paragraph in second_paragraphs %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _paragraph.title, + title_tag: 'h2', + attributes: create_attribute().addClass(['mb-4', 'pt-3']) + .setAttribute('id', _paragraph.title_id), + } only %} + {{- _paragraph.content -}} + {% endfor %} + {% endif %} + + {% if gallery is not empty %} +
    + {% include '@oe-bcl/bcl-gallery/gallery.html.twig' with gallery only %} +
    + {% endif %} + + {% if social_block is not empty %} + {% block social_block %} + {{ social_buttons }} + {% include '@oe-bcl/bcl-button/button.html.twig' with button_social_modal only %} + {% include '@oe-bcl/bcl-modal/modal.html.twig' with social_modal only %} + {% endblock %} + {% endif %} + +{% endblock %} diff --git a/assets/bcl/bcl-recent-activities/bcl-recent-activities.html.twig b/assets/bcl/bcl-recent-activities/bcl-recent-activities.html.twig new file mode 100644 index 000000000..bc6873c46 --- /dev/null +++ b/assets/bcl/bcl-recent-activities/bcl-recent-activities.html.twig @@ -0,0 +1,63 @@ +{% apply spaceless %} + +{# Parameters: + - activities (object[]) (default: []) + format: [ + { + image: { + path: "", + alt: "", + class: "", + }, + content: "", + meta: [ + { + icon (icon object): {}, + label: "" + } + ] + }, + ... + ] +#} + +{% set _activities = activities|default([]) %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +
    +{% if _activities is not empty and _activities is iterable %} + {% for _activity in _activities %} +
    + {% if _activity.image is not empty %} +
    + {{- _activity.image -}} +
    + {% endif %} + {% if _activity.content is not empty and _activity.meta is not empty %} +
    + {%- if _activity.content is not empty -%} +

    {{- _activity.content -}}

    + {%- endif -%} + {%- if _activity.meta is not empty and _activity.meta is iterable -%} + {%- for _meta in _activity.meta -%} +

    + {%- if _meta.icon is not empty -%} + {% include '@oe-bcl/bcl-icon/icon.html.twig' with _meta.icon only %} + {%- endif -%} + {{- _meta.label -}} +

    + {%- endfor -%} + {%- endif -%} +
    + {%- endif -%} +
    + {% endfor %} +{% endif %} +
    + +{% endapply %} diff --git a/assets/bcl/bcl-search-form/bcl-search-form.html.twig b/assets/bcl/bcl-search-form/bcl-search-form.html.twig new file mode 100644 index 000000000..b28acb98c --- /dev/null +++ b/assets/bcl/bcl-search-form/bcl-search-form.html.twig @@ -0,0 +1,53 @@ +{% apply spaceless %} + +{# Parameters: + - pill (boolean) (default: false) + - icon (icon Object) (default: {}) + - submit (button Object) (default: {}) + - input (form input Object) (default: {}) + - attributes (drupal attrs) + ] +#} + +{% set _pill = pill ?? false %} +{% set _icon = icon|default({}) %} +{% set _submit = submit|default({}) %} +{% set _input = input|default({}) %} + +{% set _classes = ['bcl-search-form'] %} + +{% if _pill %} + {% set _classes = _classes|merge(['rounded']) %} +{% endif %} + +{% if _submit is not empty %} + {% set _classes = _classes|merge(['submittable']) %} +{% endif %} + +{% if _icon is not empty %} + {% set _input = _input|merge({ + attributes: _input.attributes.addClass("ps-5") + }) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass( _classes ) %} + +
    +
    + {% if _icon is not empty %} + {% include '@oe-bcl/bcl-icon/icon.html.twig' with _icon only %} + {% endif %} + {% include '@oe-bcl/bcl-form-input/form-input.html.twig' with _input only %} + {% if _submit is not empty %} + {% include '@oe-bcl/bcl-button/button.html.twig' with _submit only %} + {% endif %} +
    +
    + +{% endapply %} diff --git a/assets/bcl/bcl-search/bcl-search.html.twig b/assets/bcl/bcl-search/bcl-search.html.twig new file mode 100644 index 000000000..6301860cc --- /dev/null +++ b/assets/bcl/bcl-search/bcl-search.html.twig @@ -0,0 +1,22 @@ +{% extends "@oe-bcl/bcl-base-templates/listing-page.html.twig" %} + +{% block banner %} +{% if banner.search_bar is defined %} +
    +
    +
    +
    + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: main_title, + title_tag: "h1", + attributes: create_attribute().addClass(['mb-3', 'mb-lg-0']), + } only %} +
    +
    + {% include '@oe-bcl/bcl-search-form/search-form.html.twig' with banner.search_bar only %} +
    +
    +
    +
    +{% endif %} +{% endblock %} diff --git a/assets/bcl/bcl-select/bcl-select.html.twig b/assets/bcl/bcl-select/bcl-select.html.twig new file mode 100644 index 000000000..636f482d2 --- /dev/null +++ b/assets/bcl/bcl-select/bcl-select.html.twig @@ -0,0 +1,184 @@ +{% apply spaceless %} + +{# + Parameters: + - id (string) (default: '') + - label (string) (default: '') + - label_extra_classes (string) (default: '') + - hidden_label (boolean) (default: false) + - helper_text (string) (default: '') + - helper_text_id (string) (default: '') + - disabled (boolean) (default: false) + - invalid (boolean) (default: false) + - valid (boolean) (default: false) + - invalid_feedback (string) (default: '') + - valid_feedback (string) (default: '') + - required (boolean) (default: false) + - multiple (boolean) (default: false) + - options (object[]) (default: []) + format: [ + { + selected (boolean, optional) + disabled (boolean, optional) + label (string) + hidden (boolean, optional) + options (object[], optional) + format: [{ + selected (boolean, optional) + disabled (boolean, optional) + label (string) + }] + } + ] + - aria_label (string) (default: '') + - clean_class (boolean) (default: false) - removes 'form-select' class + - attributes (drupal attrs) +#} + +{% set _id = id|default('') %} +{% set _label = label|default('') %} +{% set _label_extra_classes = label_extra_classes|default('') %} +{% set _hidden_label = hidden_label ?? false %} +{% set _helper_text = helper_text|default('') %} +{% set _helper_text_id = helper_text_id|default('') %} +{% set _disabled = disabled ?? false %} +{% set _invalid = invalid ?? false %} +{% set _valid = valid ?? false %} +{% set _invalid_feedback = invalid_feedback|default('') %} +{% set _valid_feedback = valid_feedback|default('') %} +{% set _required = required ?? false %} +{% set _multiple = multiple ?? false %} +{% set _options = options|default([]) %} +{% set _aria_label = aria_label|default('') %} +{% set _clean_class = clean_class ?? false %} + +{% set _classes = ['form-select'] %} +{% set _label_class = 'form-label' %} + +{% if _clean_class %} + {% set _classes = [] %} +{% endif %} + +{% if _invalid %} + {% set _classes = _classes|merge(['is-invalid']) %} +{% endif %} + +{% if _valid %} + {% set _classes = _classes|merge(['is-valid']) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% if _label_extra_classes is not empty %} + {% set _label_class = _label_class ~ ' ' ~ _label_extra_classes %} +{% endif %} + +{% if _aria_label is not empty %} + {% set attributes = attributes.setAttribute('aria-label', _aria_label) %} +{% endif %} + +{% if _id is not empty %} + {% set attributes = attributes.setAttribute('id', _id) %} +{% endif %} + +{% if _disabled %} + {% set attributes = attributes.setAttribute('disabled', true) %} +{% endif %} + +{% if _multiple %} + {% set attributes = attributes.setAttribute('multiple', true) %} +{% endif %} + +{% if _required %} + {% set attributes = attributes.setAttribute('required', true) %} +{% endif %} + +{% if _hidden_label %} + {% set _label_class = _label_class ~ ' visually-hidden' %} +{% endif %} + +{% if _classes is not empty %} + {% set attributes = attributes.addClass(_classes) %} +{% endif %} + +{% if _label is not empty %} + {% set _label_block %} + + {% endset %} +{% endif %} + +{% if _label_block is defined %} + {{ _label_block|raw }} +{% endif %} + +{% if _invalid_feedback is not empty %} +
    + {{- _invalid_feedback -}} +
    +{% endif %} +{% if _valid_feedback is not empty %} +
    + {{- _valid_feedback -}} +
    +{% endif %} +{% if _helper_text is not empty %} +
    + {{- _helper_text -}} +
    +{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-spinner/bcl-spinner.html.twig b/assets/bcl/bcl-spinner/bcl-spinner.html.twig new file mode 100644 index 000000000..9ec2e32cb --- /dev/null +++ b/assets/bcl/bcl-spinner/bcl-spinner.html.twig @@ -0,0 +1,40 @@ +{% apply spaceless %} + +{# Parameters: + - type (string) (default: 'border') + - options ['border', 'grow'] + - variant (string) (default: '') + - size (string) (default: '') + - options ['sm', 'lg'] + - assistive_text (string) (default: '') + - attributes (drupal attrs) +#} + +{% set _type = type|default('border') %} +{% set _variant = variant|default('') %} +{% set _size = size|default('') %} +{% set _assistive_text = assistive_text|default('') %} + +{% set _classes = ['spinner-' ~ _type] %} +{% if _size is not empty %} + {% set _classes = _classes|merge(['spinner-' ~ _type ~ '-' ~ _size]) %} +{% endif %} +{% if _variant is not empty %} + {% set _classes = _classes|merge(['text-' ~ _variant]) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes).setAttribute('role', 'status') %} + +
    +{% if _assistive_text is not empty %} + {{ _assistive_text }} +{% endif %} +
    + +{% endapply %} diff --git a/assets/bcl/bcl-subscription-block/bcl-subscription-block.html.twig b/assets/bcl/bcl-subscription-block/bcl-subscription-block.html.twig new file mode 100644 index 000000000..8138ffd94 --- /dev/null +++ b/assets/bcl/bcl-subscription-block/bcl-subscription-block.html.twig @@ -0,0 +1,38 @@ +{% apply spaceless %} + +{# Parameters: + - title: (string) (default: '') + - content: (string) (default: '') + - button: (button Object) (default: {}) + - attributes (drupal attrs) +#} + +{% set _title = title|default('') %} +{% set _content = content|default('') %} +{% set _button = button|default({}) %} + +{% set _classes = ['bcl-subscription-block', 'text-bg-light', 'px-4-5', 'pt-4', 'pb-4-5'] %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes) %} + +
    + {% if _title is not empty %} +
    {{ _title }}
    + {% endif %} + {% if _content is not empty %} + {{ _content }} + {% endif %} + {% if _button is not empty %} +
    + {% include '@oe-bcl/bcl-button/button.html.twig' with _button only %} +
    + {% endif %} +
    + +{% endapply %} diff --git a/assets/bcl/bcl-subscription/bcl-subscription-modal.html.twig b/assets/bcl/bcl-subscription/bcl-subscription-modal.html.twig new file mode 100644 index 000000000..7a8cd3dd6 --- /dev/null +++ b/assets/bcl/bcl-subscription/bcl-subscription-modal.html.twig @@ -0,0 +1,24 @@ +{% extends "@oe-bcl/bcl-modal/modal.html.twig" %} + +{# Parameters: + - form: (form object) (default: {}) + - success_alert: (alert object) (default: {}) + - error_alert: (alert Object) (default: {}) + + Blocks: + - body + - messages +#} + +{% set _form = form|default({}) %} +{% set _success_alert = success_alert|default({}) %} +{% set _error_alert = error_alert|default({}) %} + +{% block body %} + {% include '@oe-bcl/bcl-form/form.html.twig' with _form only %} +{% endblock %} + +{% block messages %} + {% include '@oe-bcl/bcl-alert/alert.html.twig' with _success_alert only %} + {% include '@oe-bcl/bcl-alert/alert.html.twig' with _error_alert only %} +{% endblock %} diff --git a/assets/bcl/bcl-subscription/bcl-subscription.html.twig b/assets/bcl/bcl-subscription/bcl-subscription.html.twig new file mode 100644 index 000000000..e6b401a91 --- /dev/null +++ b/assets/bcl/bcl-subscription/bcl-subscription.html.twig @@ -0,0 +1,10 @@ +{% extends '@oe-bcl/bcl-base-templates/content-type.html.twig' %} + +{% block sidebar %} + {% include '@oe-bcl/bcl-inpage-navigation/inpage-navigation.html.twig' with sidebar only %} +{% endblock %} + +{% block content_bottom %} + {% include '@oe-bcl/bcl-subscription-block/subscription-block.html.twig' with subscription only %} + {% include '@oe-bcl/bcl-subscription/subscription-modal.html.twig' with modal only %} +{% endblock %} diff --git a/assets/bcl/bcl-table/bcl-table.html.twig b/assets/bcl/bcl-table/bcl-table.html.twig new file mode 100644 index 000000000..d2b9efa0f --- /dev/null +++ b/assets/bcl/bcl-table/bcl-table.html.twig @@ -0,0 +1,195 @@ +{% apply spaceless %} + +{# Parameters: + - striped (boolean) (default: false) + - hoverable (boolean) (default: false) + - table_responsive (string) (default: '') + - options ['all', 'sm', 'md', 'lg', 'xl', 'xxl'] + - variant (string) (default: '') + - options ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'] + - small (boolean) (default: false) + - alignment (string) (default: '') + - options ['bottom', 'middle', 'top'] + - caption (string) (default: '') + - caption_top (boolean) (default: false) + - border (string) (default: '') + - options ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'] + - borderless (boolean) (default: false) + - table_footer (object[]) (default: {}) + format: [ + { + - col_span + - content + } + ] + - table_head (object[]) (default: {}) + format: [ + { + - col_span + - content + } + ] + - rows (object[]) (default: []) + format: [ + { + - active + - alignment + - variant + - cells: [ + { + - col_span + - content + } + ] + } + ] + - attributes (drupal attrs) +#} + +{% set _striped = striped ?? false %} +{% set _hoverable = hoverable ?? false %} +{% set _table_responsive = table_responsive|default('') %} +{% set _variant = variant|default('') %} +{% set _small = small ?? false %} +{% set _alignment = alignment|default('') %} +{% set _caption = caption|default('') %} +{% set _caption_top = caption_top ?? false %} +{% set _border = border|default('') %} +{% set _borderless = borderless ?? false %} +{% set _table_footer = table_footer|default({}) %} +{% set _table_head = table_head|default({}) %} +{% set _rows = rows|default([]) %} + +{% set _classes = ['table'] %} +{% if _striped %} + {% set _classes = _classes|merge(['table-striped']) %} +{% endif %} +{% if _hoverable %} + {% set _classes = _classes|merge(['table-hover']) %} +{% endif %} +{% if _alignment is not empty %} + {% set _classes = _classes|merge(['align-' ~ _alignment]) %} +{% endif %} +{% if _variant is not empty %} + {% set _classes = _classes|merge(['table-' ~ _variant]) %} +{% endif %} +{% if _small %} + {% set _classes = _classes|merge(['table-sm']) %} +{% endif %} +{% if _border is not empty %} + {% set _classes = _classes|merge(['table-bordered', 'border-' ~ _border]) %} +{% endif %} +{% if _borderless %} + {% set _classes = _classes|merge(['table-borderless']) %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes) %} + +{% if _table_responsive is not empty %} + {% set _responsive_class = 'table-responsive' %} + {% if _table_responsive != 'all' %} + {% set _responsive_class = _responsive_class ~ '-' ~ _table_responsive %} + {% endif %} +
    +{% endif %} + + +{%- if _caption is not empty -%} + +{%- endif -%} +{% if _table_head is not empty %} + + {% if _table_head.cells is not empty and _table_head.cells is iterable %} + + {% for _cell in _table_head.cells %} + + {% endfor %} + + {% endif %} + +{% endif %} + +{% if _rows is not empty and _rows is iterable %} + + {% for _row in _rows %} + {% set _row_class = '' %} + {% if _row.active %} + {% set _row_class = 'table-active' %} + {% endif %} + {% if _row.alignment is not empty %} + {% if _row_class is not empty %} + {% set _row_class = _row_class ~ ' align-' ~ _row.alignment %} + {% else %} + {% set _row_class = 'align-' ~ _row.alignment %} + {% endif %} + {% endif %} + {% if _row.variant is not empty %} + {% if _row_class is not empty %} + {% set _row_class = _row_class ~ ' table-' ~ _row.variant %} + {% else %} + {% set _row_class = 'table-' ~ _row.variant %} + {% endif %} + {% endif %} + + {% if _row.cells is defined and _row.cells is not empty and _row.cells is iterable %} + {% for _cell in _row.cells %} + + {% endfor %} + {% endif %} + + {% endfor %} + +{% endif %} + +{% if _table_footer is not empty %} + + {% if _table_footer.cells is not empty and _table_footer.cells is iterable %} + + {% for _cell in _table_footer.cells %} + + {% endfor %} + + {% endif %} + +{% endif %} +
    + {{- _caption -}} +
    + {{- _cell.content -}} +
    + {{- _cell.content -}} +
    + {{- _cell.content -}} +
    + +{% if _table_responsive is not empty %} +
    +{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-textarea/bcl-textarea.html.twig b/assets/bcl/bcl-textarea/bcl-textarea.html.twig new file mode 100644 index 000000000..b9816700a --- /dev/null +++ b/assets/bcl/bcl-textarea/bcl-textarea.html.twig @@ -0,0 +1,149 @@ +{% apply spaceless %} + +{# + Parameters: + - id (string) (default: '') + - label (string) (default: '') + - required (boolean) (default: false) + - disabled (boolean) (default: false) + - readonly (boolean) (default: false) + - invalid (boolean) (default: false) + - valid (boolean) (default: false) + - invalid_feedback (string) (default: '') + - valid_feedback (string) (default: '') + - helper_text (string) (default: '') + - helper_text_id (string) (default: '') + - hidden_label (boolean) (default: false) + - text (string) (default: '') + - rows (int) (default: 4) + - floating (boolean) (default: false) + - horizontal (boolean) (default: false) + - horizontal_class (string) (default: col-sm-10) + - horizontal_label_class (string) (default: col-sm-2) + - attributes (drupal attrs) +#} + +{% set _id = id|default('') %} +{% set _label = label|default('') %} +{% set _required = required ?? false %} +{% set _disabled = disabled ?? false %} +{% set _readonly = readonly ?? false %} +{% set _invalid = invalid ?? false %} +{% set _valid = valid ?? false %} +{% set _invalid_feedback = invalid_feedback|default('') %} +{% set _valid_feedback = valid_feedback|default('') %} +{% set _helper_text = helper_text|default('') %} +{% set _helper_text_id = helper_text_id|default('') %} +{% set _hidden_label = hidden_label ?? false %} +{% set _text = text|default('') %} +{% set _rows = rows|default('4') %} +{% set _floating = floating ?? false %} +{% set _horizontal = horizontal ?? false %} +{% set _horizontal_class = horizontal_class|default('col-sm-10') %} +{% set _horizontal_label_class = horizontal_label_class|default('col-sm-2') %} + +{% set _label_block = false %} +{% set _label_class = 'form-label' %} +{% set _classes = ['form-control'] %} + +{% if _invalid is not empty %} + {% set _classes = _classes|merge(['is-invalid']) %} +{% endif %} +{% if _valid is not empty %} + {% set _classes = _classes|merge(['is-valid']) %} +{% endif %} +{% set _placeholder = placeholder|default('') %} +{% if _horizontal %} + {% set _label_class = 'col-form-label ' ~ _horizontal_label_class %} +{% endif %} +{% if _hidden_label %} + {% set _label_class = _label_class ~ ' visually-hidden' %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes).setAttribute('rows', _rows) %} + +{% if _id %} + {% set attributes = attributes.setAttribute('id', _id) %} +{% endif %} + +{% if _required %} + {% set attributes = attributes.setAttribute('required', true) %} +{% endif %} + +{% if _disabled %} + {% set attributes = attributes.setAttribute('disabled', true) %} +{% endif %} + +{% if _readonly %} + {% set attributes = attributes.setAttribute('readonly', true) %} +{% endif %} + +{% if _placeholder is not empty %} + {% set attributes = attributes.setAttribute('placeholder', _placeholder) %} +{% endif %} + +{% if _helper_text_id is not empty %} + {% set attributes = attributes.setAttribute('aria-describedby', _helper_text_id) %} +{% endif %} + +{% if _floating or _horizontal %} +{% set _wrapper_class = _floating ? 'form-floating' : 'row' %} +
    +{% endif %} +{% if _label is not empty %} + {% set _label_block %} + + {% endset %} +{% endif %} + +{% if _label_block and _floating == false %} + {{ _label_block|raw }} +{% endif %} +{% if _horizontal and floating == false %} +
    +{% endif %} + +{% if _horizontal and floating == false %} +
    +{% endif %} +{% if _label_block and _floating %} + {{ _label_block|raw }} +{% endif %} +{% if _invalid_feedback is not empty %} +
    + {{- _invalid_feedback -}} +
    +{% endif %} +{% if _valid_feedback is not empty %} +
    + {{- _valid_feedback -}} +
    +{% endif %} +{% if _helper_text is not empty %} +
    + {{- _helper_text -}} +
    +{% endif %} +{% if _floating or _horizontal %} +
    +{% endif %} +{% endapply %} diff --git a/assets/bcl/bcl-timeline/bcl-timeline-item.html.twig b/assets/bcl/bcl-timeline/bcl-timeline-item.html.twig new file mode 100644 index 000000000..40596e814 --- /dev/null +++ b/assets/bcl/bcl-timeline/bcl-timeline-item.html.twig @@ -0,0 +1,34 @@ +{% apply spaceless %} + +{# Parameters: + - id (string) (default: '') + - label (string) (default: '') + - title (string) (default: '') + - content (string) (default: '') +#} + +{% set _id = id|default('') %} +{% set _label = label|default('') %} +{% set _title = title|default('') %} +{% set _content = content|default('') %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% if _id is not empty %} + {% set attributes = attributes.setAttribute('id', _id) %} +{% endif %} + +
  • +

    {{ _label }}

    + {% if _title is not empty %} +

    {{ _title }}

    + {% endif %} + {% if _content is not empty %} +
    {{ _content }}
    + {% endif %} +
  • + +{% endapply %} diff --git a/assets/bcl/bcl-timeline/bcl-timeline.html.twig b/assets/bcl/bcl-timeline/bcl-timeline.html.twig new file mode 100644 index 000000000..cab57aea3 --- /dev/null +++ b/assets/bcl/bcl-timeline/bcl-timeline.html.twig @@ -0,0 +1,115 @@ +{% apply spaceless %} + +{# +Parameters: + - id: (integer) (default: random(10000)) + - title: (string) (default: '') + - title_tag: (string) (default: 'h2') + - title_link: (link object) (default: {}) + - title_attributes (drupal attrs) + - toggle_collapsed: (string) (default: '') + - toggle_expanded: (string) (default: '') + - items (array) (default: []): [ + { + id: (string) (default: '') + label: (string) (default: '') + title: (string) (default: '') + content: (block) (default: '') + } + ] + - hide: (object) + format: { + from (integer) (default: items.length) + to (integer) (default: items.length) + } + - icon_path (string) (default: ''): file containing the svg icons +#} + +{% set _id = id|default(random(10000)) %} +{% set _title = title|default('') %} +{% set _title_tag = title_tag|default('h2') %} +{% set _title_link = title_link|default({}) %} +{% set _title_attributes = title_attributes ?: create_attribute() %} +{% set _toggle_collapsed = toggle_collapsed|default('') %} +{% set _toggle_expanded = toggle_expanded|default('') %} +{% set _items = items|default([]) %} +{% set _hide_from = hide.from|default(items|length) %} +{% set _hide_to = hide.to|default(items|length) %} +{% set _icon_path = icon_path|default('') %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass('bcl-timeline') %} + +{# Internal logic - Process properties #} + +{% set _display_amount = items|length %} +{% set _hide_amount = 0 %} +{% set _bottom_amount = 0 %} + +{% if _hide_from > 0 %} + {% if _hide_to > 0 %} + {% set _bottom_amount = _display_amount - _hide_to %} + {% else %} + {% set _bottom_amount = _hide_to|abs %} + {% endif %} + {% set _countbase = items|length - _bottom_amount %} + {% set _display_amount = _hide_from %} + {% set _hide_amount = _countbase - _display_amount %} + {% set _toggle_collapsed = _toggle_collapsed|replace({'%d': _hide_amount}) %} + {% set _toggle_expanded = _toggle_expanded|replace({'%d': _hide_amount}) %} +{% endif %} + +{% if _title is not empty %} + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: _title, + title_tag: _title_tag, + title_link: _title_link, + attributes: _title_attributes, + } only %} +{% endif %} + +{# Print the result #} +
      + {% if _items is not empty %} + {% for _item in _items %} + {# Decide on per item if it should display. #} + {% if _item.attributes is empty %} + {% set _item = _item|merge({ + attributes: create_attribute() + }) %} + {% endif %} + {% if loop.index > _display_amount and loop.revindex > _bottom_amount %} + {% set _item = _item|merge({ + attributes: _item.attributes.addClass('collapse', 'collapse-' ~ _id) + }) %} + {% endif %} + {% include '@oe-bcl/bcl-timeline/timeline-item.html.twig' with _item only %} + {# Display the show more button if required. #} + {% if (_hide_amount > 0 and loop.revindex == _bottom_amount + 1) or (_hide_amount > 0 and _hide_to == 0 and loop.revindex == 1) %} +
    1. + +
    2. + {% endif %} + {% endfor %} + {% endif %} +
    + +{% endapply %} diff --git a/assets/bcl/bcl-toast/bcl-toasts.html.twig b/assets/bcl/bcl-toast/bcl-toasts.html.twig new file mode 100644 index 000000000..63a4bc9a0 --- /dev/null +++ b/assets/bcl/bcl-toast/bcl-toasts.html.twig @@ -0,0 +1,123 @@ +{% apply spaceless %} + +{# + Parameters: + - with_wrapper (boolean) (default: false) + - wrapper_classes (string) (default: '') + - wrapper_aria_live (string) (default: '') + - with_container (boolean) (default: false) + - container_classes (string) (default: '') + - toasts (object[]) format: [ + { + - body (string) (default: '') + - role (string) (default: 'alert') + - with_close (boolean) (default: true) + - autohide (boolean) (default: false) + - with_body_wrapper (boolean) (default: false) + - body_wrapper_classes (string) (default: '') + - attributes (drupal object) (default: undefined) + } + ] + - attributes (drupal attrs) +#} + +{% set _with_wrapper = with_wrapper ?? false %} +{% set _wrapper_classes = wrapper_classes|default('') %} +{% set _wrapper_aria_live = wrapper_aria_live|default('') %} +{% set _with_container = with_container ?? false %} +{% set _toasts = toasts|default([]) %} + +{% set _container_classes = 'toast-container' %} + +{% if container_classes %} + {% set _container_classes = _container_classes ~ ' ' ~ container_classes %} +{% endif %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{# wrapper #} +{% if _with_wrapper %} + {% set attributes = attributes.setAttribute('aria-atomic', "true") %} + {% if _wrapper_aria_live %} + {% set attributes = attributes.setAttribute('aria-live', _wrapper_aria_live) %} + {% endif %} + {% if _wrapper_classes %} + {% set attributes = attributes.addClass(_wrapper_classes|split(' ')) %} + {% endif %} + +
    + +{% endif %} +{# container #} +{% if _with_container %} +
    +{% endif %} +{# toasts #} +{% if _toasts is not empty %} + {% for _toast in _toasts %} + {% set _classes = ['toast'] %} + {% set _body = _toast.body|default('') %} + {% set _role = _toast.role|default('') %} + {% set _with_close = _toast.with_close ?? true %} + {% set _aria_live = _toast.aria_live|default('') %} + {% set _autohide = _toast.autohide ?? true %} + {% set _with_body_wrapper = _toast.with_body_wrapper ?? false %} + {% set _body_wrapper_classes = _toast.body_wrapper_classes|default('') %} + {% set _toast_attributes = _toast.attributes ?: create_attribute() %} + {% set _toast_attributes = _toast_attributes.addClass(_classes).setAttribute('aria-atomic', 'true') %} + {% if _aria_live is not empty %} + {% set _toast_attributes = _toast_attributes.setAttribute('aria-live', _aria_live) %} + {% endif %} + {% if _role is not empty %} + {% set _toast_attributes = _toast_attributes.setAttribute('role', _role) %} + {% endif %} + {% if not _autohide %} + {% set _toast_attributes = _toast_attributes.setAttribute('data-bs-autohide', 'false') %} + {% endif %} +
    + {% if _with_close or + (_toast.header is defined and _toast.header is not empty) + %} +
    + {{- _toast.header|default('') -}} + {% if _with_close %} + {% set button_attributes = create_attribute() + .addClass(['btn-close']) + .setAttribute('aria-label', 'close') + .setAttribute('data-bs-dismiss', 'toast') + %} + {%- include '@oe-bcl/bcl-button/button.html.twig' with { + attributes: button_attributes, + clean_class: true + } only -%} + {% endif %} +
    + {% endif %} + {% if _with_body_wrapper %} +
    + {% endif %} +
    + {{- _body -}} +
    + {% if _with_body_wrapper %} +
    + {% endif %} +
    + {% endfor %} +{% endif %} +{% if _with_container %} +
    +{% endif %} +{% if _with_wrapper %} +
    +{% endif %} + +{% endapply %} diff --git a/assets/bcl/bcl-user/bcl-user-compact.html.twig b/assets/bcl/bcl-user/bcl-user-compact.html.twig new file mode 100644 index 000000000..3aee6364d --- /dev/null +++ b/assets/bcl/bcl-user/bcl-user-compact.html.twig @@ -0,0 +1,64 @@ +{% apply spaceless %} + +{# Parameters: + - picture (object) (default: {}) + format: { + - path (string) (default: '') + - alt (string) (default: '') + - classes (string) (default: '') + } + - name (object) (default: {}) + format: { + - text (string) (default: '') + - link (string) (default: '') + } + - infos (string[]) (default: []) +#} + +{% set _picture = picture|default({}) %} +{% set _name = name|default({}) %} +{% set _infos = infos|default([]) %} + +{% set _picture_classes = 'rounded-pill' %} +{% set _classes = ['bcl-user-compact', 'd-flex', 'mb-3'] %} + +{% if attributes is empty %} + {% set attributes = create_attribute() %} +{% endif %} + +{% set attributes = attributes.addClass(_classes) %} + +{% if _picture is not empty and _picture.classes is not empty %} + {% set _picture_classes = _picture_classes ~ ' ' ~ _picture.classes %} +{% endif %} + +
    +
    + {{ _picture.alt }} +
    +
    + {% if _name.link is not empty %} + {{ _name.text }} + {% else %} +

    {{ _name.text }}

    + {% endif %} + + {% if _infos is not empty %} +
    + {% for _info in _infos %} + {% if _info is not empty %} + {{ _info }} + {% endif %} + {% endfor %} +
    + {% endif %} +
    +
    + +{% endapply %} diff --git a/assets/bcl/bcl-user/bcl-user-terms.html.twig b/assets/bcl/bcl-user/bcl-user-terms.html.twig new file mode 100644 index 000000000..0905d60a3 --- /dev/null +++ b/assets/bcl/bcl-user/bcl-user-terms.html.twig @@ -0,0 +1,11 @@ +{% extends "@oe-bcl/bcl-base-templates/content-type.html.twig" %} + +{% block content %} + {{ get_dummy_text(4, true) }} +
      +
    • {{ get_dummy_text() }}
    • +
    • {{ get_dummy_text() }}
    • +
    • {{ get_dummy_text() }}
    • +
    + {% include '@oe-bcl/bcl-form/form.html.twig' with terms_form only %} +{% endblock %} diff --git a/assets/bcl/bcl-user/bcl-user.html.twig b/assets/bcl/bcl-user/bcl-user.html.twig new file mode 100644 index 000000000..112ea4c29 --- /dev/null +++ b/assets/bcl/bcl-user/bcl-user.html.twig @@ -0,0 +1,137 @@ +{% extends "@oe-bcl/bcl-base-templates/content-type.html.twig" %} + +{% block content %} + {% include "@oe-bcl/bcl-navigation/navigation.html.twig" with navigation only %} +
    +
    + {% include '@oe-bcl/bcl-content-banner/content-banner.html.twig' with view.banner only %} +
    + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: 'Personal information', + title_tag: 'h2', + attributes: create_attribute().addClass(['mb-4']), + } only %} +
    +
    +
    +
    +

    Gender:

    +
    +
    +

    Male

    +
    +
    +
    +
    +

    Nationality:

    +
    +
    +

    German

    +
    +
    +
    +
    +

    Date of birth:

    +
    +
    +

    22/01/1972

    +
    +
    +
    +
    +
    +
    +

    Country:

    +
    +
    +

    Germany

    +
    +
    +
    +
    +

    City:

    +
    +
    +

    Düsseldorf

    +
    +
    +
    +
    +
    +
    + {% include '@oe-bcl/bcl-heading/heading.html.twig' with { + title: 'Professional information', + title_tag: 'h2', + attributes: create_attribute().addClass(['mb-4']), + } only %} +
    +
    +
    +
    +

    Organisation:

    +
    +
    +

    DG Test

    +
    +
    +
    +
    +

    Position:

    +
    +
    +

    Director

    +
    +
    +
    +
    +
    +
    +

    Working languages:

    +
    +
    +

    English, German

    +
    +
    +
    +
    +
    +
    +
    +

    Edit my profile

    +

    Profile image

    +
    +
    + profile-image +
    +
    +
    + {% include '@oe-bcl/bcl-form-input/form-input.html.twig' with edit.image_upload_input only %} +
    + {% include '@oe-bcl/bcl-button/button.html.twig' with edit.remove_image_button only %} +
    +
    +
    +
    +
    +
    + {% include '@oe-bcl/bcl-form/form.html.twig' with edit.profile_information only %} +
    +
    +
    +
    +

    Privacy settings

    +

    Who can consult my data

    + {% include '@oe-bcl/bcl-form/form.html.twig' with privacy.settings only %} +
    +
    +

    Visibility settings

    +

    Select what information should be displayed to your profile.

    + {% include '@oe-bcl/bcl-form/form.html.twig' with privacy.public_profile_content only %} +
    +
    +

    Are you sure you want to cancel your account?

    +

    When cancelling your account

    + {% include '@oe-bcl/bcl-form/form.html.twig' with cancel.form only %} +
    +
    +{% endblock %} From b91c74a9b4521dd6ea2580ba0822521b5a43f690 Mon Sep 17 00:00:00 2001 From: Tiberiu Dumitru Date: Thu, 19 Jun 2025 16:27:59 +0300 Subject: [PATCH 3/3] OEL-3736: Cleanup. --- bcl-builder.config.js | 30 ---------------- bcl/bcl-builder.config.js | 16 ++++----- bcl/test.css | 17 --------- package.json | 3 -- patches/npm/.gitkeep | 0 .../@openeuropa+bcl-theme-default+1.2.0.patch | 36 ------------------- 6 files changed, 7 insertions(+), 95 deletions(-) delete mode 100644 bcl/test.css delete mode 100644 patches/npm/.gitkeep delete mode 100644 patches/npm/@openeuropa+bcl-theme-default+1.2.0.patch diff --git a/bcl-builder.config.js b/bcl-builder.config.js index bb760d9e4..a934d5361 100644 --- a/bcl-builder.config.js +++ b/bcl-builder.config.js @@ -39,35 +39,5 @@ module.exports = { to: path.resolve(outputFolder, "assets/icons"), options: { up: true }, }, - { - from: ["node_modules/@openeuropa/bcl-theme-default/templates/**/*.twig"], - to: path.resolve(outputFolder, "assets/bcl"), - options: { up: 4 }, - }, - { - from: ["node_modules/@openeuropa/bcl-theme-default/logos/ec/positive/*.svg"], - to: path.resolve(outputFolder, "assets/logos/ec"), - options: { up: true }, - }, - { - from: ["node_modules/@openeuropa/bcl-theme-default/logos/eu/standard-version/**"], - to: path.resolve(outputFolder, "assets/logos/eu"), - options: { up: true }, - }, - { - from: ["node_modules/@openeuropa/bcl-theme-default/logos/eu/condensed-version/**"], - to: path.resolve(outputFolder, "assets/logos/eu/mobile"), - options: { up: true }, - }, - ], - "rename": [ - { - from: path.resolve(outputFolder, "assets/bcl/**/*"), - to: "bcl-", - options: { - search: "!(bcl-)*.html.twig", - operation: "prefix", - }, - }, ], }; diff --git a/bcl/bcl-builder.config.js b/bcl/bcl-builder.config.js index a4d244ce2..0ed626ebf 100644 --- a/bcl/bcl-builder.config.js +++ b/bcl/bcl-builder.config.js @@ -170,21 +170,19 @@ module.exports = { options: { up: 4 }, }, { - from: [`${nodeModules}/@ecl/resources-ec-logo/**/*.svg`], + from: [`${nodeModules}/@ecl/resources-ec-logo/dist/positive/*.svg`], to: path.resolve(outputFolder, "logos/ec"), - options: { up: 5 }, + options: { up: true }, }, { - from: [`${nodeModules}/@ecl/resources-eu-logo/**/*.svg`], + from: [`${nodeModules}/@ecl/resources-eu-logo/dist/standard-version/**`], to: path.resolve(outputFolder, "logos/eu"), - options: { up: 5 }, + options: { up: true }, }, { - from: [ - `${nodeModules}/@openeuropa/bcl-twig-templates/templates/**/*.twig`, - ], - to: path.resolve(outputFolder, "templates"), - options: { up: 3 }, + from: [`${nodeModules}/@ecl/resources-eu-logo/dist/condensed-version/**`], + to: path.resolve(outputFolder, "logos/eu/mobile"), + options: { up: true }, }, ], }; diff --git a/bcl/test.css b/bcl/test.css deleted file mode 100644 index 9fe7ba018..000000000 --- a/bcl/test.css +++ /dev/null @@ -1,17 +0,0 @@ -/* Error: Can't find stylesheet to import. - * , - * 2 | @import "@openeuropa/bcl-bootstrap/scss/functions"; - * | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * ' - * src/scss/oe-bcl-default.scss 2:9 root stylesheet */ - -body::before { - font-family: "Source Code Pro", "SF Mono", Monaco, Inconsolata, "Fira Mono", - "Droid Sans Mono", monospace, monospace; - white-space: pre; - display: block; - padding: 1em; - margin-bottom: 1em; - border-bottom: 2px solid black; - content: "Error: Can't find stylesheet to import.\a \2577 \a 2 \2502 @import \"@openeuropa/bcl-bootstrap/scss/functions\";\a \2502 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\a \2575 \a src/scss/oe-bcl-default.scss 2:9 root stylesheet"; -} diff --git a/package.json b/package.json index 807b70bd6..0e918185a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "build:bcl": "npm --workspace bcl run build", "build:styles": "cross-env ./bcl/builder/bin/build.js styles", "build:copy": "cross-env ./bcl/builder/bin/build.js copy", - "build:rename": "cross-env ./bcl/builder/bin/build.js rename", "watch:styles": "chokidar \"./resources/sass/**/*.scss\" -i \"/node_modules/\" -c \"npm run build:styles\"", "watch": "npm-run-all --parallel watch:* -ln", "postinstall": "patch-package --patch-dir=patches/npm", @@ -18,8 +17,6 @@ "production": "npm run build" }, "devDependencies": { - "@openeuropa/bcl-builder": "^1.11", - "@openeuropa/bcl-theme-default": "^1.11", "bootstrap-ie11": "5.0.2", "chokidar-cli": "^3.0.0", "copyfiles": "2.4.1", diff --git a/patches/npm/.gitkeep b/patches/npm/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/patches/npm/@openeuropa+bcl-theme-default+1.2.0.patch b/patches/npm/@openeuropa+bcl-theme-default+1.2.0.patch deleted file mode 100644 index 00f2ff48a..000000000 --- a/patches/npm/@openeuropa+bcl-theme-default+1.2.0.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/node_modules/@openeuropa/bcl-theme-default/templates/bcl-link/link.html.twig b/node_modules/@openeuropa/bcl-theme-default/templates/bcl-link/link.html.twig -index 171972f..aa94eb3 100644 ---- a/node_modules/@openeuropa/bcl-theme-default/templates/bcl-link/link.html.twig -+++ b/node_modules/@openeuropa/bcl-theme-default/templates/bcl-link/link.html.twig -@@ -70,17 +70,17 @@ - {% if _classes is not empty %} - {%- set attributes = attributes.addClass(_classes) %} - {% endif %} --{% set attributes = attributes.setAttribute('href', _path) -%} -- -- -- {%- if _icon_position == 'before' and _icon_markup is defined -%} -- {{ _icon_markup }} -- {%- endif -%} -- {{- _label -}} -- {%- if _icon_position == 'after' and _icon_markup is defined -%} -- {{ _icon_markup }} -- {%- endif -%} -- --{#--#} -+{% if _icon_markup is defined %} -+ {%- set _label -%} -+ {%- if _icon_position == 'before' -%} -+ {{ _icon_markup }} -+ {%- endif -%} -+ {{- _label -}} -+ {%- if _icon_position == 'after' -%} -+ {{ _icon_markup }} -+ {%- endif -%} -+ {%- endset -%} -+{%- endif -%} -+ -+{{ bcl_link(_label, _path, attributes) }} -+{#--#}