All pages
Powered by GitBook
1 of 25

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Create a Page Template

Page Templates help you standardise how multiple pages look/work

A Page Template is an essential component, any of our Marketplace Templates will come with at least one already but you can create them here:

One template already exists (Main) but you can create more if needed

SiteBuilder simply leverages the Page Templates functionality in Siteglide but builds it for you with useful options to save you time.

In the popup, choose:

  • A name e.g. "Main"

  • Default Page Template - optional

  • the Flowbite Theme (other SiteBuilder Themes will be available to download from Marketplace)

  • Optionally, add a Menu, but this is not neccesary for this tutorial

Themes automatically add any of the following to a Page Template:

  • CSS

  • JavaScript

  • Config Files

  • Standard Page Template HTML and Liquid

These will then be applied consistently to any Page the Page Template is attached to.

Once created, you can find your template in the SiteBuilder Page Templates tab and in the Siteglide Admin under SITE MANAGER > Templates. These Page Templates are fully editable and you can attach them to Siteglide Pages as normal.

Once you've created a Page Template, you'll unlock the PageBuilder, Layouts and Settings tabs.

Flowbite-specific options

The Flowbite template starts with a default Tailwind CSS file which allows most layouts to work out of the box, but if you want to start changing things, you'll need to follow the rest of these setup steps!

When creating your Page Template, you can select a Tailwind build method of either:

  • CLI

  • Preview

  • Use the default from the SiteBuilder Settings tab

When editing your Page Template later, you can modify the template_build_method parameter and set it to either 'cli', 'preview' or empty string ''.

You can learn more about , or continue to!

which build method to use here
set up our recommended CLI method

Quickstart: SiteBuilder

Get started with SiteBuilder in a few simple steps

Step 1: Create a Site or Install the Module

We recommend creating a Site from a Template to be able to fully follow our guides:

Create Site From Template

Alternatively you can install the SiteBuilder Module onto any existing Site:

Install SiteBuilder Module

Step 2: Setup CLI for Tailwind (optional)

CLI is primarily for developers, skip this if you don't need to customise the Tailwind CSS

Step 3: Editing Sites

Creat & Edit Pages:

Layouts are the main way to build out sites and functionality, they control the structure:

To edit the design and styling of the site you'll need to edit the Tailwind CSS:

Set Up Tailwind CSS with the recommended CLI method
Quickstart: Pages
Insert Static Layouts
Installing Dynamic Layouts
Editing Tailwind CSS using the recommended CLI method

Styling

Site Setup

Layouts

Editing Dynamic Layouts

About

About SiteBuilder and how it can help you rapidly build websites and applications

What is SiteBuilder?

SiteBuilder is a tool to help you build better websites, faster.

An end-to-end web design and development ecosystem to rapidly launch websites, portals, applications and much more.

Core Concepts

SiteBuilder offers 2 main things:

  1. Layouts: Build out sites with ready-made, best-practice sections in just a few clicks

  2. Builder: SiteBuilder will do the heavy lifting in Siteglide for you from a simple, intuitive UI

Sitebuilder does NOT limit what you can build, it's simply a starting point for rapid development that can then be completely customised.

How Does It Work?

Some code repositories require you to copy and paste code from the example into your site, but this can be fiddly if the code needs to go into lots of different folders and files.

SiteBuilder does the hard work for you and is plug & play!

When you choose one of our Layouts, all you have to do is give it a name and we'll create the required file structure automatically. The layout will be ready to use in your Siteglide site and, where supported, available in Toolbox!

Marketplace Themes & Templates

Page Templates

Pages

Layouts

Live Updates API

Licence

By using SiteBuilder you are bound by the terms detailed in our .

Where Should I Start?

Dynamic Layouts

What is a Dynamic Layout in SiteBuilder?

In Siteglide Module and WebApp layouts are called dynamic, because their content will change when the data in the WebApp or Module's database table changes. They use the Liquid templating language to pull dynamic data from the database into the HTML so it will be visible and functional on the front-end of a website.

Dynamic Layouts in SiteBuilder are categorised so that it's clear which Siteglide feature they provide a dynamic layout for: e.g.

  • Modules e.g. "Menu Module" and Sub-Modules e.g. "Headers".

  • WebApp

  • Forms

  • Pagination

  • Form Confirmation

When you're navigating PageBuilder and the Layouts view, you can filter by module to quickly find layouts depending on their functionality.

These categories are sometimes named "modules" in SiteBuilder because most are associated with a module available in the Siteglide Marketplace. Some modules in SiteBuilder e.g. Pagination and Forms do not correspond exactly to a specific Siteglide module, because they provide layouts for functionality which is built in to the Siteglide system.

Installing Dynamic Module Layouts onto your Site

Layouts in SiteBuilder often consist of multiple files. One of the benefits of SiteBuilder is that when you install a layout, we automatically create all the files you need in the correct folder structure. We also give you the recommended Liquid code needed to output the layout, though you may wish to modify this with additional parameters.

Note that the required Siteglide or Marketplace Module must be installed for any SiteBuilder module layouts to function correctly. However, you may install SiteBuilder module layouts first if you wish. Once the required module is installed, those layouts will be ready to use.

Head to the layouts tab in the Module navigation to find a wide range of layouts which can be filtered by Theme and by Module.

Finding more Module Layouts

Keep an eye out for new SiteBuilder compatible Modules and Themes which you can download from the Siteglide Marketplace. Once you install a module from the Marketplace, its layouts should appear.

It will now be possible for developers to create SiteBuilder-compatible layouts when they add a new module to the Siteglide marketplace. Module creators can . Theme creators can also .

Install SiteBuilder Module

The SiteBuilder Module must be installed to use SiteBuilder

Check if you have already installed the SiteBuilder Module on your site (click Install if not).

The version should be at least 4.11.2 (we'd recommend updating to the latest version).

The SiteBuilder Module comes with the Free Flowbite Theme automatically.

If the download does not show as Installed after some time, try refreshing the page and trying again - it is a large package of files.

Next Steps:

You'll need to create a Page Template:

Marketplace Themes & Templates

SiteBuilder Themes help you to find content for your site which uses a consistent CSS and JS framework.

A Theme becomes active when you create a Page Template in SiteBuilder using that Theme in the Page Templates tab.

Choosing a Theme

Each Theme will have a different combination of features:

Create Site From Template

Build a Site using a SiteBuilder Template

From the Siteglide Portal on either the Dashboard page or the Sites page you should see a button to create a new site. It will open a modal to select either a Template or Custom Site.

Step 1: Select a Template

This will take you to the Marketplace where you can select a category of templates. You can choose between all of our Flowbite layout templates or a couple of Bootstrap 5 options. It's recommended to use Flowbite, especially if you're familiar with Tailwind.

Insert Static Layouts

Build out Pages with Static Layouts

Static Layouts are sections of pre-built HTML code that you can add to your pages in the Siteglide Admin. They do not generally contain any Liquid templating, so won't pull in any dynamic content from the server or CMS. Instead, you can use Siteglide's Studio tab to edit their content directly in the page.

Insert Static Layouts from Studio Sidebar

Navigate to CMS > Pages, select a page and then from the right hand side bar you can click the blue button and insert various static layouts.

Marketplace Themes & Templates
Create a Page Template
Insert Static Layouts
Dynamic Layouts
Static and Dynamic Form Layouts
SiteBuilder Live Updates API
EULA
Quickstart: SiteBuilder
create module layouts for any theme
create layouts for existing modules

About Layouts

CSS or JavaScript Framework e.g. Bootstrap / Tailwind
  • The selection of Modules supported

  • The selection of Dynamic and Static Layouts available

  • We recommend using the Flowbite TailwindCSS Theme, SiteBuilder is setup to work best with Flowbite and you will find more layouts and features available for Flowbite than other Themes.

    Take these into consideration and choose a Theme which is the best fit for your project.

    More Themes are available on the Siteglide Marketplace. Any Themes which you decide not to use can be safely uninstalled from your Site, except for any that ship with the main SiteBuilder Module.

    SiteBuilder Marketplace Templates

    Marketplace Templates help you get started quickly without having to build a site from scratch. Templates will generally be based on a specific Theme (Flowbite or Bootstrap5 typically).

    Why not test it out by creating a site from a template?

    Quickstart: Create a Site
    Insert Static Layouts From Other Sources

    You can essentially use any TailwindCSS Layouts or code blocks. A few ideas of how to extend beyond the Layouts you'll find in Studio:

    Flowbite website: Flowbite are constantly releasing new layouts that may not yet be available in Siteglide.

    Flowbite Chat GPT: Create your own AI generated layouts/sections in seconds!

    Ready to Install Dynamic Layouts?

    Use Siteglide's prebuilt Modules (Blog, Events etc) or build your own with WebApps. SiteBuilder helps you quickly install layouts that will handle the dynamic code for you.

    Installing Dynamic Layouts
    Step 2: Choose the Appropriate Template

    We recommend starting with the Landing Page or the Marketing Site Template. Choose the Marketing Site if you want to see more Siteglide functionality or the Landing Page if you'd rather just learn the basics first.

    Step 3: Create the Site

    Finally, give your site a name and click 'Create Site'.

    And that's it! You've successfully created a new site, you will need to wait for it to be ready to use. You will receive an email when it's done but can also find it under the Sites area:

    Once you get the email confirming it's ready you will need to refresh this page or click the link from the email

    Next Steps:

    Continue with our Quickstart guide?

    Quickstart: SiteBuilder
    Create a Page Template

    Tailwind CSS - Preview Mode

    Preview Mode is not recommended for Live Sites. We recommend only using CLI to compile Tailwind which will load the minimum CSS possible and maximise performance.

    Our Preview Mode is designed to keep the convenience of Tailwind code which "just works out of the box" without the drawbacks of needing to recalculate the Tailwind CSS every time you view the Page.

    Preview Mode is designed so it can be used on its own, or in combination with the recommended CLI method. See below!

    Why is it needed?

    Options such as the (or our now deprecated JIT method) generate CSS at runtime, so they cannot see classes which are needed for different states of Liquid logic, for example if you log in or out of a secure zone.

    Page Template Level Control

    In the past, we used SiteBuilder module settings to let you pick your preferred build method. Now this can also be set on the Page Template level. This allows you to, use a CLI method for faster live pages, and a Preview method for pages which are still in development.

    You can set Preview Mode on a Page Template either when you create a Page Template in SiteBuilder:

    Or, by editing the Page Template code:

    Preview Mode On

    CLI build only

    SiteBuilder automatically checks if a custom Tailwind CLI build exists. If you have one, providing a path, even to the default location, you can improve page speed, whether preview mode is on or off.

    If no custom CLI build can be found and no path is provided, preview mode will be used automatically, even if CLI build is selected as a preference.

    How does it work? A custom build with fallbacks

    The Preview mode starts by adding two CSS files from CDNs to your Page Template's <head>:

    1. A CSS file distributed by Flowbite containing Tailwind classes to support the vast majority of their blocks and components

    2. A CSS file from the SiteBuilder Module containing Tailwind classes used by our version of the Tailwind blocks - this may differ slightly from Flowbite's as we support Liquid logic, meaning we may need to support both a login button's logged in and logged out states for example. This also supports "primary" colour variables which we use instead of "blue".

    Together these CSS files create a set of fallbacks which allow Flowbite Layouts to look how Flowbite and SiteBuilder intended out of the box, should these classes not be included elsewhere. However, they won't have any of your branded variables set, like colours or fonts. The extra load time for these CSS files is also the reason why it's not generally recommended to use Preview Page for pages in Production.

    1. To get a more consistent look and to apply your brand variables, Preview mode can also pull in a custom CLI Tailwind build underneath the other two. Where this 3rd CSS file contains the same class as one of the other 2 files, e.g. `bg-blue-700` it will overwrite it with the correct variables e.g. the correct shade of blue. Where the custom build does not yet support a class, the original Flowbite variables will be used as a fallback. Unlike a purely CLI-based approach, you don't need to spin up the CLI every time you make a change to the HTML, as you can use the fallbacks while developing and rebuild the custom CSS later, e.g. when you finish a page.

    Safelist

    If you know you wish to support more classes using your brand variables in future, you can consider adding them to the in your custom CLI Tailwind Config. Just bear in mind that this can make a template which is only using the CLI CSS less efficient as it can use less tree-shaking.

    Use Cases

    Clients working in Studio

    If you are building a site where you want clients to be able to build out Pages themselves using the Studio tab, you could consider creating a Page Template for them with Preview Mode enabled.

    This allows clients to drag in blocks from SiteBuilder and to use them out of the box.

    However, you can support them by running a CLI Tailwind build as well, either:

    1. At the end of each day or week, to tidy up inconsistencies and add brand variables to Pages still using Preview Mode which may be missing them. Clients can continue using Preview mode but every time you rebuild the Tailwind, more and more common classes are covered by consistent variables.

    2. When the Client finishes a Page or set of Pages and are ready to put them live and they let you know they are ready to "publish". You run a Tailwind CLI build and switch the Page Template to one with preview mode turned off, giving site visitors a faster experience. Note that by default preview mode templates are still visible to site visitors. If using this workflow, you may wish to add Liquid logic to the Page Template which either requires a visitor to be viewing in the Studio tab or to enter a `?preview=true` at the end of the URL in the browser:

    Installing Dynamic Layouts

    Easily insert dynamic layouts for Siteglide Modules via SiteBuilder

    Looking for Static Layouts? They don't need to be installed, see: Insert Static Layouts

    Modules and Dynamic Layouts

    Once you've installed a Page Template, the other tabs will be available including the Layouts tab. Here you can toggle the Module on the right hand side and view all the different dynamic layouts available.

    When you find a layout you want to use just click Add to Site, in the modal you will need to give the layout a name and there might be some additional settings to complete depending on the Module:

    Once installed you can copy the include code that you just insert into your chosen HTML page.

    You can insert it via CLI or via the Admin. Simply paste in where you want it to display:

    Dynamic Form Layouts

    A really powerful part of SiteBuilder is the Dynamic Form Layouts that automatically update to reflect any changes to forms. For example you could add or edit fields in the form and the layout will update automatically!

    Here's a video that walks through the basics:

    More information on Form Layout options with SiteBuilder:

    More info on Dynamic Layouts:

    Next Steps:

    Want to add more Modules to your site?

    Want to edit the Module Layouts themselves? We recommend doing this via CLI but you can also do it in Admin:

    Set Up Tailwind CSS with the recommended CLI method

    Working with Tailwind via our CLI

    Before You Start

    You must already have a Site with SiteBuilder installed and have our CLI installed

    Tailwind CSS Themes - Choosing a Build Method

    Tailwind CSS is accelerating in popularity with its bold new approach to writing CSS for the web. You’re probably wondering how you can harness this new framework on a Siteglide site?

    Tailwind’s approach to performance means it provides a huge range of utility classes, but to prevent it from slowing down your site with classes you don’t need, it builds a smaller CSS file containing just the subset of classes that you’re actually using in your project.

    There are a few alternatives to consider when it comes to generating a Tailwind CSS file for your Siteglide site:

    1. A Command Line Interface (CLI) Compilation on your machine (recommended)

    2. Preview Mode

    SiteBuilder

    SiteBuilder is the quickest way to get started with Siteglide

    New to Siteglide and/or SiteBuilder?

    SiteBuilder is definitely the best way to get started but it's so much more than that...it can help you streamline ANY project without limiting what you can create.

    Check out our Quickstart guide:

    Want to install the Module on an existing site?
    Quickstart: SiteBuilder
    Install SiteBuilder Module
    Tailwind Play CDN
    https://cdn.jsdelivr.net/npm/[email protected]/dist/flowbite.min.css
    safelist
    
    {% include 'modules/module_86/tailwind/head', template_build_method: 'preview', optional_path_to_cli_css: 'css/tailwind.min.css' %}
    
    {% include 'modules/module_86/tailwind/head', optional_path_to_cli_css: 'css/tailwind.min.css' %}
    
    
    {% if context.headers.HTTP_USER_AGENT contains "node-fetch" or context.params.preview == true %}
        {{content_for_layout}}
    {% else %}
        {% response_status 404 %}
        {% redirect_to '/404' %}
    {% endif %}
    Introduction

    If you don't have the Siteglide CLI installed or need help with the CLI follow our Quickstart guide:

    Using the Command Line Interface (CLI) to build a Tailwind CSS file allows you to:

    • Use the latest versions of TailwindCSS and its various 1st and 3rd party plugins.

    • Get the best performance front-end as Tailwind can scan your entire codebase to carry out "tree-shaking" to only include utility classes you actually need

    • Faster development performance as you can rebuild your CSS faster, and therefore build things faster

    Each time you start working on a new project, you will need to follow these steps, however, the setup time is worth it as it will give you a much smoother experience going forward.

    Step by Step Guide

    Step 1) Check Your SiteBuilder Tailwind Settings are Set to CLI Build

    Older versions of SiteBuilder would have defaulted to use the JIT option as a default. Make sure it's set to CLI!

    Step 2) Set up Project Folder in a Code Editor and Connect it with your Siteglide Site Using Siteglide CLI

    You will need to install Siteglide CLI- if you haven't or are not sure if you have, head here first:

    Next you'll need to follow the steps to create a project folder for your new Site and setup Siteglide CLI for this new Site:

    Once you've pulled the Codebase for the new Site down into your project folder, continue to the next step.

    Step 5) Move the Tailwind Files to the Correct Folders

    We'll be using npm (Node Package Manager) to install the software and settings we need to run Tailwind on your machine. This is the same tool you will have used to install the Siteglide-CLI.

    We've built files in the Site Template which contain the instructions npm needs to set you up automatically.

    Find the files in the folder:

    And copy and paste these two files package.json and package-lock.json into the root project folder (next to- but not inside - marketplace_builder).

    Next, move the tailwind.config.js and tailwind.css files from the copy_and_paste_my_files_into_the_src_folder folder to the marketplace_builder/assets/modules/module_86/src folder:

    Step 6) Use NPM to Automatically Install Dependencies

    Using your integrated terminal from step 2, which is already open in your project directory, run the command:

    You may be given some warnings and information by npm at this stage. For the sake of this tutorial most are safe to ignore for now and come back to later.

    Step 7) Run Commands to Build your tailwind.min.css File and Sync it

    Split your terminal in two. We'll need one window to build our Tailwind CSS and a second one to sync our changes to the Site:

    Use this command to build your Tailwind's CSS (we'll look at this in more detail in a minute):

    In the other terminal window, use this command to sync changes to the Site with Siteglide-CLI (replace &lt;env&gt; with your environment name from step 2):

    Both commands will keep running indefinately and will watch your files for changes. Every time you change a Liquid file the Tailwind will re-compile the CSS if it needs to!

    You can now start building your Site using Tailwind CSS!

    Next

    Head to the next article to understand in more depth:

    • The Tailwind Config File

    • The Tailwind source CSS file

    • The Tailwind distributable CSS file

    Quickstart: CLI
    About
    Site Setup
    Editing Tailwind CSS using the recommended CLI method

    Just In Time (JIT) Compilation in the Browser (deprecated)

    Which one is right for me?

    That depends!

    Both methods have their advantages, which we'll look at here, but it also depends on the preference of the developer and the type of project you're working on.

    Question
    Tailwind CLI
    Preview Mode
    JIT CDN (deprecated)

    Will it support CSS classes that sit inside Secure Zones or other Liquid logical statements?

    ✔️

    ✔️ So long as it uses Flowbite blocks or components.

    ❌ See for possible workarounds and recommendations

    Can I use the latest version of Tailwind?

    ✔️

    ✔️

    Not yet. You can use most features from version 2.0 of Tailwind. We rely on Open Source code to provide the JIT method and it is not possible to keep it fully up to date as Tailwind brings out new versions.

    Can I use 3rd party Tailwind Plugins?

    ✔️

    ✔️only when used in combination with a CLI build.

    In the end, it depends on your preference and the way your clients wish to use your site.

    If you use the Siteglide-CLI already to take advantage of modern code editing tools, you'll be right at home with our recommended method: Tailwind CLI.

    If you, or your client, wish to build and preview your Pages in the Siteglide Admin without frequent use of the Siteglide CLI, Preview Mode may be for you. We still recommend using the Tailwind CLI now and again to set up your brand variables and to set them consistently across all of your pages at once, but this does not need to be done every time you make a change in Admin, allowing for a potentially smoother experience for clients and development.

    Choosing a Build Method
    Set Up Tailwind CSS with the recommended CLI method
    Editing Tailwind CSS using the recommended CLI method
    Tailwind CSS - Preview Mode
    Static and Dynamic Form Layouts
    Dynamic Layouts
    Install & Manage Modules

    Reference

    Reference

    This page is intended to document the themes and modules that are built into SiteBuilder, to help you reference those IDs in your own modules and build onto that content.

    If you want the community to collaborate with you on what you build, we suggest you make similar documentation of your own!

    Themes Reference

    Theme
    ID

    Modules Reference

    Module
    ID
    Submodules
    Submodule IDs

    If a module that has no sub-modules is given a sub-module in an update, the sub_module 0 which was previously default will be renamed to miscellaneous. Layouts referencing that sub_module will be displayed in the miscellaneous group until they are updated to reference one of the new sub_modules.

    Editing Tailwind CSS using the recommended CLI method

    Before you Start

    This article assumes you have completed the setup steps:

    Set Up Tailwind CSS with the recommended CLI method

    Introduction

    Having set up your local Project Folder with:

    • A Text Editor for viewing your Folder Structure inside a Project Folder

    • A Siteglide-CLI environment which connects your Project Folder to a Site

    • An npm script which runs a Tailwind compilation process

    This article will delve a little deeper into the files you can modify to take full control of your Tailwind build!

    Useful Tools for this Topic

    • We recommend if you are using VSCode that you download and enable this extension, which will help VSCode understand Tailwind's syntax and give you tips on things like colours:

    • Also if you are using VS Code, this extension is useful for creating shortcuts to your favourite project folders:

    • This tool is really helpful for fetching colours with all the shades you need generated for you:

    A Recommended Day-to-Day Workflow

    (For Editing a Siteglide Site Which Uses a Tailwind Theme.)

    1. Open up the Project Folder for your Site

    2. In case your team have made any changes while you've been away, run siteglide-cli pull <env>

    3. Split your terminal and simultaneously run:

      1. siteglide-cli sync <env>

    What does each Tailwind related File Actually Do?

    🌳 Folder Structure

    Source Files

    src is short for source. These files are not designed to be seen by the browser. Instead think of them as the recipe for a final Tailwind CSS file.

    When you sync these files, they are still pushed to your Site because they are inside the marketplace_builder folder. This allows you to share changes with other users on the Site (or yourself on different machines).

    The tailwind.config.js File

    This file is a configuration file and a Tailwind CSS feature which can be used to:

    • Create and modify Tailwind Variables e.g. Colour, Spacing

    • Include Plugins, for example we by default include the Flowbite plugin

    You can learn all about Tailwind CSS configuration files here:

    You can find an example of default config variables here: If you leave any variables blank, default values from this file will be used.

    The tailwind.css File

    This file can be used to write ordinary CSS, or you can use Tailwind's documented features. The file should not be linked to on a website, instead it will be compiled into a new production-ready CSS file when you save it and run the npm run tailwind build process.

    Often with Tailwind CSS, you will find you will not need to enter this file often, as you can achieve most of the styling you want by using existing:

    • Utility Classes

    • Arbitrary Values in Utility Classes

    • Prefixes instead of Media Queries

    However, if you do want to write your own CSS, you will not find yourself limited!

    See here to understand how to insert your CSS into one of Tailwind's layers:

    See here to understand how to add custom classes which combine existing Tailwind utility classes:

    The tailwind.min.css Final CSS File

    See the folder structure above to find this file. You should not need to create it or edit it manually. The npm run tailwind command will compile it automatically from the src files.

    It should be linked in your Page Template, but by default a SiteBuilder Page Template will do this via a tailwind/head Liquid include. You could optionally replace this with a &lt;link&gt; tag instead.

    When you make changes to any of the following while npm run tailwind is running in your terminal:

    • Your HTML (adding or removing new Tailwind classes)

    • Your JavaScript (adding or removing new Tailwind classes) (in case classes will be added via JavaScript, e.g. when a Flowbite Component changes state.

    • Your tailwind.config.js file

    • Your tailwind.css

    A new version of the tailwind.min.css file will be generated. Use the Siteglide CLI to sync or deploy this to your Site to see your changes applied:

    Tailwind uses tree-shaking so that any classes which aren't used by the files referenced above will be removed from the final CSS file to make it as fast as possible. It will also be minified.

    Sliders

    Introduction

    Add responsive, navigable sliders and carousels to your Site with SiteBuilder's layouts for the Siteglide Slider module.

    We'll also add layouts with slider functionality to other modules, where suitable, and this document will also cover them.

    Layouts Utilising the open-source Swiper.js Library

    Any developer can contribute layouts to SiteBuilder, so it's possible to add slider layouts using any front-end JavaScript library.

    Having said that, Sitegurus' preferred library for this functionality at the current time is Swiper.js and we'll be using it for slider-like layouts on all of the Themes which we contribute to.

    Swiper.JS

    The sitegurus_sliders_javascript_api is a script which allows multiple layouts on the same page to run fully responsive sliders powered by Swiper.js.

    We chose Swiper.js because it's a well maintained library, which has a very wide range of configuration options, allowing all sorts of slider effects.

    SiteBuilder layouts can use any front-end JS library, so using this API is completely optional. However, for those layouts which do use it, this article aims to help you make the most of the benefits.

    Read more about the Slider Module here](/documentation/sitebuilder/modules_and_more/sliders).

    How Swiper.js is initiated

    Each of the layouts which uses this script will include the following code for loading the script and setting up the configuration for the slider:

    Copy

    This code is included inside the layout in order to allow some level of configuration by developers, while maximising performance:

    1. It loads asynchronously along with its dependencies, and includes Liquid logic to ensure it only runs once.

    2. It allows multiple slider layouts to be initialised on the same page, each with different settings, without conflicts.

    3. It allows the developer to configure the settings and write JS which manipulates the sliders after initialisation, should they wish.

    This is achieved mainly through creating a globally-scoped variable window.sitebuilderSwiperConfig. Each inidivudal slider is added to this object with a unique name and important properties are stored against it. Once the JavaScript is loaded, it reads this variable and initialises the sliders.

    How to update the configuration

    You will see inside the layout a config object:

    Copy

    This contains the configuration settings required to acheive the Swiper.js effects the layout has out of the box, but it can be edited as per the in the Swiper.js docs.

    For example, changing slidesPerView to 2 would show 2 slides on the page at a time.

    Note that some properties, for example pagination, may require you to add to the HTML alongside your changes to the JS object.

    Only the config property directly maps to the Swiper.js documentation, the initiated and onInit properties are used by Sitegurus behind the scenes.

    How to programatically update the Slider

    Under the configuration, you can define a callback function in the onInit property. This will allow you to run your own JavaScript when you can be confident that the Slider has initiated. The function will provide you a reference to the initiated slider which you can use to run any from the documentation:

    In the example below, we show you how to add a button to manipulate the slider once it is ready.

    Copy

    The references to each initialised slider are also stored inside the window.sitebuilderSwiperConfig object.

    Tailwind's JIT Compiler Via CDN (deprecated)

    Before you Start

    This is a deprecated feature - not recommended for Production

    └───marketplace_builder
        └───assets
            └───modules
                └───module_86
                    └───src
                        │   readme.md
                        └───open_me_to_set_up_tailwind_1st_time
                            ├───copy_and_paste_my_files_into_the_root_project_folder
                            │   package-lock.json
                            │   package.json
                            └───copy_and_paste_my_files_into_the_src_folder
                                tailwind.config.js
                                tailwind.css
    │   package-lock.json
    │   package.json
    └───marketplace_builder
        └───assets
            └───modules
                └───module_86
                    └───src
                        │   readme.md
                        └───open_me_to_set_up_tailwind_1st_time
                            ├───copy_and_paste_my_files_into_the_root_project_folder
                            │   package-lock.json
                            │   package.json
                            └───copy_and_paste_my_files_into_the_src_folder
                                tailwind.config.js
                                tailwind.css
    │   package-lock.json
    │   package.json
    └───marketplace_builder
        └───assets
            └───modules
                └───module_86
                    └───src
                        │   readme.md
                        │   tailwind.config.js
                        │   tailwind.css
                        └───open_me_to_set_up_tailwind_1st_time
                            ├───copy_and_paste_my_files_into_the_root_project_folder
                            │   package-lock.json
                            │   package.json
                            └───copy_and_paste_my_files_into_the_src_folder
                                tailwind.config.js
                                tailwind.css
    npm i
    npm run tailwind
    siteglide-cli sync <env>

    Secure Zones

    module_5

    Login Forms, Logout Buttons, User Form Submissions

    1, 2, 3

    Authors / Team

    module_6

    Standard

    1

    Testimonials

    module_8

    Default

    0

    FAQ

    module_10

    Default

    0

    Events

    module_12

    Default

    0

    eCommerce

    module_14

    Product List, Product Detail, Cart, Order Detail, Currency Changer, Tax Code Changer

    1, 2, 3, 4, 5, 6

    Forms

    module_s1

    Default

    0

    Pagination

    module_s2

    Default

    0

    Form Confirmation

    module_s3

    Default

    0

    Cookie Preferences

    module_s4

    Cookie Popup, Cookie Settings Page Section

    1, 2

    Categories

    module_s5

    Full Categories List, Category Detail Layouts

    1, 2

    WebApp

    webapp

    Standard, Swiper, Tables, WebApp with Update and Delete

    1, 2, 4, 5

    Flowbite

    theme_01

    Flowbite Pro

    theme_111

    Bootstrap 5 Design System

    theme_113

    Menu

    module_2

    Headers, Footers, Sidebars

    1, 2, 3

    Blog

    module_3

    Default

    0

    Slider

    module_4

    Default

    0

    to push any code changes to the site
  • npm run tailwind to watch for code changes and re-compile your Tailwind build (see Editing Tailwind CSS using the recommended CLI method)

  • Make the necessary changes to your code.

  • file
    bradlc.vscode-tailwindcss
    https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager
    https://uicolors.app/create
    https://tailwindcss.com/docs/configuration
    https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/config.full.js
    https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer
    https://tailwindcss.com/docs/functions-and-directives#apply
    Reference
    parameters
    markup
    methods
    └───marketplace_builder
        └───assets
            |   └───css
            |       tailwind.min.css
            └───modules
                └───module_86
                    └───src
                            readme.md
                            tailwind.config.js
                            tailwind.css
    <script>
      if(!window.sitebuilderSwiperConfig ) {
        window.sitebuilderSwiperConfig  = {};
      }
      window.sitebuilderSwiperConfig[''] = {
        initiated: false,
        //Choose any configuration from the docs here: https://swiperjs.com/swiper-api
        config: {
          slidesPerView: 1
        }
      }
      if(typeof window.sitebuilderSwiperInit == 'function') {
        //In case script is loaded already. Run initiation again. Sliders in the config will only be initiated if initiated property is set to false.
        window.sitebuilderSwiperInit();
      }
    </script>
    
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css"/>
      <script async src="https://uploads.prod01.london.platform-os.com/instances/668/assets/modules/module_86/js/sitegurus_sliders_javascript_api.1.js?updated=1695044531"></script>
    
    window.sitebuilderSwiperConfig[''] = {
      initiated: false,
      config: {
        slidesPerView: 1
      }
    }
    <button id="reset">Back to start</button>
    <script>
      window.sitebuilderSwiperConfig[''] = {
        initiated: false,
        config: {
    
        },
        onInit: callbackFn
      }
      function callbackFn(instance) {
        //When the slider (stored in instance parameter) is ready, initialise the custom reset button.
        var btn = document.querySelector('#reset');
        btn.addEventListener('click', function() {
          instance.slideTo(0, 0.3, true);
        });
      }
    
    </script>

    Check Choosing a Build Method first to choose which option suits you best.

    Introduction

    A quick way to use Tailwind from within the Siteglide Admin

    With special thanks to the folks at Beyond Code, we’ve adapted their open-source Tailwinds JIT compiler via CDN to optimise it for the Siteglide Admin and the SiteBuilder libraries. We've also added caching for better performance. Later in this article, we may abbreviate the name of this tool to "the JIT Compiler" or simply "JIT".

    Quick Start

    1. Switch to JIT Mode in SiteBuilder Tailwind Settings

      Enter the Module Admin and Scroll past the libraries to the Tailwind Settings Card and click the gear icon.

      Tailwind Settings

      Then select “JIT”.

      JIT
    2. Create a Page Template

      Create a Page Template for your Library using SiteBuilder and add it to the Pages you're working on in the Siteglide Admin.

      And that's it; you're ready to start work! When your Page is loaded in the browser a new inline <style> tag will be created including all the Tailwind classes your page needs.

      Next, learn more about how the JIT compiler works by reading the rest of this article, including:

      • Where to theme and configure your Tailwind Build

      • Using caching to boost performance and how to update the cache when you make changes.

      • How to handle classes which show conditionally e.g. on user-interaction or after JavaScript events.

    How to Theme your JIT Tailwind CSS

    The JIT Compiler uses a version of the Tailwind Config file that lies within <script> tags in the <head> of the page, inside the Page Template. This is because the JIT method runs in the browser and wouldn't be able to access the standard tailwind-config.js file on the root of a project.

    You can edit the config file for the JIT method at the following default path in code editor: modules/module_86/layouts/tailwind/jit_tailwind_config_v4_0_0. This path can be changed in the Page Template by adding the optional_path_to_jit_config parameter to our Tailwind Liquid tag (using the platformOS format for partial paths)[https://documentation.platformos.com/developer-guide/pages/reusing-code-across-multiple-pages#step-2-include-the-partial]:

    On page rendering, this will be inserted into a <script> tag in the Page Template. For older versions of SiteBuilder the config could be edited directly in the Page Template.

    By default, we set up the Tailwind config file the way the library you’re using recommends in its documentation.

    Since the JIT Tailwind Compiler uses Tailwind version 2.0, you can use most of the configuration options from that version of Tailwind. See here: Tailwind CSS Version 2.0 Documentation

    However, there are some exceptions, for example plugins which work a little differently. See the BeyondCode team’s blog for details: Beyond Code Blog - Tailwind's JIT Compiler Via CDN

    Getting Ready for Production - Performance and Caching

    Wait! My web pages are loading really slowly!

    There’s another setting in the Tailwind Settings menu in SiteBuilder called Cache CSS.

    Just In Time Tailwind Compilation is designed to be convenient for Developers. A developer adds new code to their site containing new Tailwind classes and those classes are instantly added to the CSS on the page. However, this convenience would normally come at a cost: the work being done by the JavaScript would slow the page down.

    In production however, there is no need to rebuild the CSS on every page reload, we only need to do this after an update has been made.

    Turning caching on in your Tailwind Settings menu turns on caching for Tailwind CSS across the site. The CSS is saved (base64 encoded) in your pages’ metadata once generated and when the page is loaded, the server will generate a <style> tag based on that at the top of the document.

    Caching Turned On

    With caching on, the page will load lightning fast. Furthermore, since we optimise the CSS for that page only, it only needs to contain the clases on that page, rather than the entire site, so could even have speed advantages against an ordinary CLI Tailwind build.

    Making Changes After Turning On Caching

    If you add new Tailwind classes to a page, you can regenerate that page’s Tailwind by adding the query parameter ?tailwind=regenerate at the end of the URL. (see URL Search Parameters for details).

    Adding URL parameters to regenerate the Tailwind CSS

    After this, the page will load slowly for the developer once while this is calculated, but then the CSS against the page’s metadata will be updated and everyone else will experience the newly improved page at fast speeds.

    Safelisting Classes Which Are Added Via User Interaction

    What if my page shows different content depending on user-interaction, or depending on the user’s session? For example a button which either shows “login” or “logout” depending on the situation?

    In this case, you may find that the content which changes is missing vital CSS because the Tailwind was only generated for the initial state the components were in.

    Since the CDN runs after Liquid has rendered, this includes any classes which sit inside a Liquid if statement, as well as any JavaScript or XHR requests which might add classes to the DOM after initial page load.

    One option is to add classes to the safelist in your Tailwind Congfig file: https://v2.tailwindcss.com/docs/optimizing-for-production#safelisting-specific-classes

    Safelisting

    Another possibility, if you find that your site has a lot of user-interaction and your safelist is getting quite long, might be that your site is better suited to a Using the Tailwind CLI with Siteglide instead!

    Alternatively, you may wish to consider using the JIT mode for quick development now for convenience and then switching to a CLI build when the site goes live for reliability.

    ✔️ See Beyond Code - Tailwind's JIT Tailwind Compiler Via CDN for details. The 1st party plugins will work well but we cannot guarantee that all 3rd party plugins will.

    Can I add Flowbite blocks from the SiteBuilder Module and have them look right out of the box?

    ❌ You will need to use CLI to pull your site to your machine, rebuild Tailwind and sync the new CSS file.

    ✔️ But if you're changing brand variables, or adding new Tailwind classes not used by Flowbite, you will need to complement with a CLI.

    ✔️

    Is it optimised for performance?

    ✔️ CSS is ready to go before user visits the page.

    ❌While an improvement on JIT or Tailwind Play CDN, extra CSS files will be slower than CLI build only.

    ❌ See the JIT section for more details on caching to optimise performance.

    Safelisting classes which are added via user-interaction

    Theme Presets

    Theme Presets are a Way to change a Theme's CSS variables, like colour and font, giving your site an interesting new look without needing to make big changes to HTML or CSS classes.

    Pre-Requisites

    • You have ready for use on a Site

    • You understand Siteglide-CLI

    {% include 'modules/module_86/tailwind/head', optional_path_to_jit_config: 'tailwind/custom_config_file' %}
    and
    commands
  • You have created a Flowbite* Page Template from the SiteBuilder Module (or are using a Site Template where this has been done already)

  • You have set up your project ready to use Tailwind CSS via CLI with the SiteBuilder module's recommended file structure Example Tailwind Project Setup

  • About Presets

    Theme Presets are a Way to change a Theme's CSS variables, like colour and font, giving your site an distinctive new look without needing to make changes to HTML or CSS classes. They should be compatible with all our existing Flowbite layouts*.

    They are useful for:

    • Create new sites using the SiteBuilder layouts, and give them a distinctive look from step one.

    • Take an existing site and try it out with different Presets to help you or your client visualise different design choices with the real content.

    How it Works

    Our Presets use Tailwind CSS Presets and Plugins behind the scenes.

    To allow you to change the currently selected preset from the SiteBuilder Settings tab, we use a small, boilerplate preset called sitebuilder_preset_settings.js. When the SiteBuilder settings are updated to select a new preset, this file is modified to point at the Preset you have selected.

    Small Plugins are included within Presets in order to enable them to set global styling like fonts as well as changing variables which affect existing utility classes.

    *Our first release of Theme Skins only supports Tailwind-based Themes, since we are able to leverage the powerful presets feature provided by Tailwind.

    Getting Started - Coming Soon

    The easiest way to get started with a Theme Preset will be to install a site from one of our Site Templates:

    • https://admin.siteglide.com/#/portal/community/marketplace?module_id=951980

    • https://admin.siteglide.com/#/portal/community/marketplace?module_id=951981

    Existing layouts will already have the preset applied.

    Newly added layouts may usually have the majority of classes applied, though to get your site looking perfect, we recommend you rebuild Tailwind reguarly.

    Before going live, we also recommend you remove the "safelist" in the configuration file, for much better client-side performance.

    Usage - Via SiteBuilder Settings

    1. Open the Modules / SiteBuilder Module

    2. Navigate to the Settings tab.

    3. Select a Preset from the options.

    4. Each Preset may have different versions. To get started, keep the default selected version.

    5. Save your settings. This will save the setting and modify settings files on your site, but your Tailwind distributable CSS file will still need to be compiled using the Siteglide CLI - more on that next.

    6. Next, go to your code editor and open a terminal window. Close any sync commands that are currently running and run a siteglide-cli pull command. This will pull down the files for each Preset in the module and the newly-updated sitebuilder_preset_settings.js file.

    Do not directly modify either the sitebuilder_preset_settings.js file or other files in the modules/module_86/public folder since the module settings may overwrite your changes.

    1. Check your Tailwind CSS config (normally at path marketplace_builder\assets\modules\module_86\src\tailwind.config.js) and your Tailwind CSS source file, normally at path: marketplace_builder\assets\modules\module_86\src\tailwind.css.

      1. Set the presets option in your config to point at the sitebuilder_presets_settings file:

      2. Variables in your config will merge with variables in the Preset. If you wish for the Preset to change specific variables, you may wish to selectively comment-out parts of your Preset which set the same variables.

      3. CSS rules in your CSS source file may override the Preset's plugins, which might for example be setting fonts. If you wish for the Preset to set these rules, you may wish to selectively comment-out CSS rules.

    The newer default config and source CSS files we provide will start with a leaner initial config than in previous SiteBuilder versions. These new versions of the files will already point to the sitebuilder_presets_settings.js and will override less variables with Flowbite defaults so these steps will not normally be necessary on a new site.

    1. Start a siteglide-cli sync command.

    2. Start a npm run tailwind command. A new tailwind.min.css file will be created and synced, using the new Preset and your existing CSS rules.

    That's it! Any Pages which are using a Page Template which links to this new CSS file will be restyled to use this Preset's variables.

    Troubleshooting

    1. Make sure the Page you are testing with uses a Flowbite Page Template. (We will support other Themes in future, but currently Presets are only available on Themes which use Tailwind, of which Flowbite is the only one currently).

    2. Make sure the SiteBuilder settings have either Preview Mode or CLI Mode selected. JIT mode should not be selected as this does not support Presets.

    3. Check the Tailwind Docs for more information about how Presets handle conflicts with your own config and source CSS. You may be expecting the Site's appearance to change, but your own variables may be preventing that change.

    4. Check that any classes you are testing are present in the layouts you are using. Tailwind CSS's tree shaking means that if an element does not have the class bg-accent-500 that class won't be included in the tailwind.min.css file even if the preset defines this colour.

    5. Try manually then saving and syncing the tailwind.min.css file to confirm it has uploaded since making changes.

    6. Make sure you are not directly modifying files in the modules/module_86/public folder. These can be overridden by the module, so your changes could be lost.

    Modifying Default Behaviour and Disabling Features

    We have designed the Presets feature to strike a balance between convenience and flexibility. To a large extent, reading the Tailwind documentation on:

    • Configuration

    • Presets

    • Plugins

    And referencing the preset JS files in the modules/module_86/public/assets/presets directory will allow you to modify behaviours to suit your needs. We will just cover a few common use-cases relevant to using this feature with Siteglide.

    Preventing SiteBuilder Settings from Changing Preset

    Once you've experiemented with Presets and have made a decision on whether to use a specific preset, no presets or a preset from a third party, you may no longer wish to allow the SiteBuilder module's settings to change the preset. If so, you can change your configuation to stop pointing at:

    ...and instead point directly at your chosen Preset's file location, or set presets to an empty array [] to completely disable all presets including Tailwind's default settings or remove the presets key completely to remove presets but keep Tailwind's defaults.

    Preset Versions

    This allows a Preset creator to make changes without affecting your live sites, since your site can continue to safely use an older version without maintenance and updates.

    We don't anticipate that it will be common practice to update a version of a Preset on a live site, but it is an option that's open to you.

    If you're starting a project from the beginning, it will probably make sense to use the latest version unless you are avoiding specific known issues in the newest version.\

    set up the Siteglide CLI
    Pull
    Sync
    module.exports = {
      // Pointing Presets at the router file will allow the SiteBuilder module to change theme skin defaults. Anything you write in the "theme" object can override this.
      presets: [
        require('tailwindcss/../../modules/module_86/public/assets/css/presets/sitebuilder_preset_settings')
      ],
      ...
    }
    require('tailwindcss/../../modules/module_86/public/assets/css/presets/sitebuilder_preset_settings')
    Step-by-step guide to setting up Tailwind via CLI

    Static and Dynamic Form Layouts

    Introduction

    Form Layouts are designed to supercharge your experience of setting up forms in Siteglide with these key objectives:

    • Get started quicker. No need to copy and paste fields from the default layout into a custom layout anymore in order to add styling. With a click, you can have a styled form layout ready to go.

    • Get consistent styles across your forms - Form layouts are modular, using component layouts to style individual UI-controls. This makes it easier to apply consistent styles between your contact form and secure zone signup form without editing every line individually. Just add the code for each component to that form's layout once.

    • Low Maintenance - No need to change your form layout every time a new field is added or removed in the Admin. By choosing the dynamic option, your layout will automatically adapt to any changes in the Admin and display them in the form.

    Currently Supported Siteglide Form Features

    These are the currently supported form features out of the box. Feel free to add more to your Static Layouts (see more about static vs. dynamic layouts below) and we may add more if there is popular demand.

    Types of Layout

    The Form Layouts are organised into sections based on the Siteglide feature they provide layouts for:

    • CMS Forms

    • WebApp Item Create Forms

    • WebApp Item Update Forms

    • Delete Forms

    Click to learn more about and .

    Layout Installation

    The Form layouts can be installed in the same way as other SiteBuilder layouts, but with a few differences:

    Note that it's recommended to output Update and Delete Forms for WebApps and Modules inside a WebApp Layout so that they inherit the correct ID and other data. This is why these layouts are not available directly on PageBuilder yet.

    Choosing a Form

    Siteglide stores form layouts in folders according to their form ID e.g. form_1 or form_2. When you install a form layout, we ask you which folder you want to install the layout into based on the form_id/ name. If you are installing a WebApp or Module CRUD form, the ID of the WebApp or Module will be used instead.

    With dynamic layouts though, the form is not restricted to working on a single one of your forms. A contact form layout can be copied and pasted into another form folder and will work out of the box. We'll look more at static vs. dynamic layouts next.

    Static or Dynamic?

    When you install a SiteBuilder form layout, you must choose whether you need a static or a dynamic layout.

    In summary, the main benefit of dynamic layouts is that they take very little code maintenance compared to traditional Siteglide form layouts. All features are controlled via the Siteglide Admin.

    The main reason to choose static forms might be if you want full control over the order of your fields or the functionality in your form. In this case, you're using the power of SiteBuilder form layouts to get you started fast, then you're able to change anything you like from there-on-out.

    If you're not sure, why not start with dynamic form layouts, then switch to static form layouts if you need to later.

    Editing the Layouts

    🌳 Folder Structure

    All form layouts have a main layout file, or wrapper, which takes the name you gave the layout and a subfolder of component layouts named after the layout, but with _components at the end. See the example below:

    This file structure will be exactly the same whether you opt for a static or dynamic wrapper. The main difference between the two types of form layout will be the contents of the wrapper.

    Static Wrapper

    A static wrapper contains

    liquid tags for each component in your form and passes them the data they need via parameters. These parameters may appear to be hardcoded, however, it was dynamically generated at the time the layout was created by SiteBuilder- it will just need editing if there are any subsequent changes in Admin.

    Alternatively, after making changes to the form configuration, you can always use SiteBuilder to re-generate a new version of the layout with a new name and new parameters.

    Dynamic Wrapper

    A dynamic wrapper does not include components directly; instead it includes this include tag which runs the dynamic SiteBuilder script for fetching the latest configuration of the form:

    This tag can be passed parameters to modify its behaviour. Any of the parameters below can alternatively be added directly to the Siteglide {% include %} tag and the form_layout_fields include will inherit their values.

    The collection Parameter

    Setting collection: 'false' means the fields will be outputted in the HTML exactly in the place of the

    tag.

    Setting collection: 'true' allows you to re-position key groups of fields within your wrapper.

    See below.

    Outputting field groups on the page while using collection='true'

    The available field groups are:

    Siteglide and Custom Form Fields

    This contains all Siteglide and all Custom Fields in the Form:

    Hidden Fields

    This contains hidden fields needed to run the form:

    Address Fields

    This is an array which contains all CRM addresses added to the form, if any are present:

    The code here will loop over them all and output them all, but you can edit this if you want to display Billing and Shipping addresses separately.

    reCaptcha

    This contains the hCaptcha or reCaptcha, if present:

    Note that Siteglide recommends using hCaptcha with forms. This file however, continues to be named reCaptcha for backwards-compatibility reasons.

    Payment Gateway

    This contains the payment gateway and payment fields, if present:

    The disable_fields Parameter

    disable_fields: can be passed a comma-separated string of field names to hide from the form. In the example above, the field called Name from the addresses is hidden.

    The name field for the User's name and other mandatory Siteglide fields are exceptions. It cannot be removed from the form using this method.

    The defer_fields Parameter

    The defer_fields: parameter is useful where you want to use the advantages of dynamic form layouts for most of your fields, but also want to manually move a few key fields out of the main field output and into a separate section within the form.

    To do this, first add the fields' names to a comma separated list in the defer_fields: parameter.

    Then, you can output the individual field where you would like it using the following code:

    In fact, the full range of deferred fields are available as an array here:

    Developers can use this to loop over the fields if they wish. The additional filters in the example above help to find the item in the array with the field name you need, access the HTML needed to output the field and finally bypass platformOS's sanitization so that the HTML is output as intended (see Form Layout Sanitization section for details).

    This feature could also be useful if you wish to hide and show some fields conditionally and therefore require greater control over these.

    The hide_name_while_logged_in and hide_email_while_logged_in Parameters

    These parameters exist primarily for the use-case of implementing a form with multiple parts or sections, where each section is actually a form in its own right. Siteglide mandates the inclusion of the name and email fields in every form that outputs, but this solution allows you to hide these fields on the 2nd, 3rd etc. sections of the form while the user is logged in and their values are auto-filled behind the scenes (and is still submitted along with the form). This use-case is demonstrated on the Flowbite Demo Site:

    For both parameters, the default is 'false' and turning on the feature is 'true'.

    If the user is not logged in, the fields will show as normal, as they are awaiting user input.

    Important note: this functionality relies on the name_field and email components to contain code which will hide these fields, because the fields need to output, but hidden. If your component does not contain this code, you can add the example from below:

    Parameters for editing email and password

    Fields to edit email and password are not part of the Siteglide Form Configuration and are instead added by parameters.

    Set include_email_editor to 'true' to include the edit_email component in the form.

    Set include_password_editor to 'true' to include the edit_password component in the form.

    Authorizing the Change

    Including either of these parameters will also cause the current password component to display, as this is needed to authorise the change.

    Validation

    Siteglide provides server-side validation to ensure the security of this functionality.

    On most form layouts we provide, the default behaviour for client-side validation is that if an edit_email or edit_password component is displayed on the form, it is required. This is the simplest behaviour to implement and makes sense if you have an account area with separate small forms for each possible action. If you have one large form and you want editing email/password to be optional, it might be sensible to add JavaScript to remove the required classes from the fields if they are empty, or to change this directly in the component layouts. You would also need to remove the required class from the password field in the situation that neither an attempt to change email, nor password was attempted.

    Adding Confirmation Validation

    Set confirm_email_password to 'true' and any email or password edit field will come along with a confirmation field for validation. This comes with client-side and server-side validation.

    Troubleshooting Edit Email & Password

    A form must have a secure zone set against it for this feature to work properly.

    Editing Email & Password on Static Form Layouts

    For Static Layouts, follow the Siteglide Documentation for . You can include the relevant components and pass the components the paramters above if you like.

    The custom_form_redirect parameter

    This is a quick way to override the form_redirect path that's set in the Siteglide Admin for a specific form. One common use case would be to set the form to redirect to the current page:

    Prior to v. 4.6.3 this was already possible in hidden fields, so this parameter just adds the convenience of setting this at a higher level in the code. It relies on the new versions of the form layout's hidden

    Components

    Components are files within the layout which are re-usable. This helps speed up development and achieve consistency as a string component need only have classes added once to re-style all <input type="text"> elements in the form. Components are used by both Static and Dynamic forms of each layout. Below is an example string.liquid component (the classList for the <input> has been simplified for the sake of readability!):

    There is a component for each Siteglide field type that is available on standard forms. There are also components for additional features such as Secure Zones or eCommerce which can be used if required. Most layouts will include these extra fields as an option even if the layout design might not appear to need it, in case these are required in future. Once installed, the layout is yours and you can delete any components which are not needed.

    Some Siteglide field types are available only for CRM fields at the moment. We will provide a component file for all of these, but it may be empty if we don't support that field type in your library yet.

    The main components available are as follows:

    More components may be added in future.

    The main Liquid parameters passed into form layout components are as follows:

    Re-ordering fields in a Dynamic Form Layout using Siteglide CLI

    Using Siteglide-CLI, it is possible to give your Form's custom fields an order property. This will affect the order they appear in the Siteglide Admin, default form layout and SiteBuilder Form Layouts. For dynamic SiteBuilder form layouts, changes in order will appear immediately, however for static form layouts, the order will only affect the initial install of the layout.

    1. Firstly, pull the site using .

    2. Next find the table's JSON file. The tables directory is at marketplace_builder/views/partials/tables/. Within that, you can find directories for forms, webapps and modules, with each one containing files numbered by IDs.

    3. (Optional) Convert the minified JSON into human-readable JSON. If using VSCode, you can use an extension like or a similar equivalent for your IDE. 4.Inside the JSON file, find your custom field under custom_fields, e.g. form_field_1_1. If the order

    Default system field order

    Since it is not currently possible to edit the orders of system fields e.g. name, email, using the above method, it's useful to note that we now assign default orders to these fields. We use negative values with large gaps between them deliberately, so that these fields default to the beginning of the form, but there is ample room for custom fields to be ordered before, between and after them.

    • name: -40

    • email: -30

    • password: -20

    • Categories: -10 (This refers to WebApp and Module item categories)

    This is a breaking change in 4.3.0, so older sites which update to this version may need their fields re-ordered using the documented method.

    Form Layout Sanitization

    When outputting user-submitted values on a web-page e.g. the value attribute in a form field, there is a chance of a malicious user introducing executable code into that value by submitting it in a form field.

    platformOS will automatically sanitize fields when values are outputted in {{ }} Liquid tags, unless the | html_safe filter is used. Since the html_safe filter is recommended in the main part of your Form Layouts, you may be re-assured to know that the value attribute will have been already outputted at the stage of your form components being rendered from Liquid to HTML by the server. This means the user-submitted values will have already been sanitized and you can use html_safe safely where we recommend it.

    Enabling fields for controlling webapp visibility

    On WebApps, fields like enabled, release_date and expiry_date were originally hidden away in hidden fields. We needed them to be there and inheriting default values, but didn't yet have UI support for them.

    If you want users to be able to edit them, you can add custom code to the hidden field component and make them visible there.

    Proper support for these fields will be added in a future update.

    ✔️

    eCommerce Subscription Form

    ✔️ Partial Support

    CRM Address Book - Choose an existing Address

    ❌ Not yet. Awaiting: https://roadmap.siteglide.com/core-platform/p/crm-update-existing-addresses

    CRM Companies

    ❌

    Change Email / Change Password

    ✔️

    Custom Field Sets

    ❌

    WebApp & Module Front End Item Create/Edit/Delete Forms

    ✔️

    Module Item Create Forms
  • Module Item Update Forms etc.

  • ✔️

    ❌See the defer_fields parameter for options.

    Can re-order fields in the file marketplace_builder/views/partials/tables/forms/.liquid in Siteglide-CLI using the order property for weighting.

    ❌

    ✔️

    textarea.liquid

    select_multi.liquid

    select.liquid

    file.liquid

    Components with Unique Functionality

    hidden_fields.liquid

    This contains hidden fields which are most likely to be edited, e.g. to override the form redirect.

    email.liquid

    Mandatory.

    name_field.liquid

    Mandatory.

    password.liquid

    Appears if Secure Zones are activated for the Form and right conditions are met.

    recaptcha.liquid

    Appears if reCaptcha is enabled for the form.

    subheading.liquid

    Only used if collection is set to false.

    basic_payment.liquid

    For eCommerce forms, the correct component will be included depending on the form's payment settings.

    checkout_standard.liquid

    quote_only.liquid

    subscription_detail.liquid

    An array of options for this component, where needed. For example for a component.

    {{form_redirect}}

    Pulls in the default form redirect URL.

    {{form_payment_amount}}

    Pulls in the default amount for Basic Payment Forms.

    {{form_payment_currency}}

    Pulls in the default currency for Basic Payment Forms.

    {{include_email_editor}}

    If true, the password component should display in order to allow the user to confirm their current password. This is necessary to confirm they have the required permissions to change their email address in another component. Inherited value.

    {{include_password_editor}}

    If true, the password component should display in order to allow the user to confirm their current password. This is necessary to confirm they have the required permissions to change their email password in another component. Inherited value.

    {{confirm_email_password}}

    If true, the edit_password and edit_email components should also display an additional confirmation field. Inherited value.

    {{hide_email_while_logged_in}}

    This value is inherited from:

    {{hide_name_while_logged_in}}

    This value is inherited from:

    property already exists, edit it to a new number. Fields are ordered in ascending order, so the higher the number, the earlier in the form it will appear. Negative and decimal numbers are allowed.
  • (Optional) If you carried out step 3, minify your JSON file.

  • Sync the JSON file to the site.

  • Save the form in the Siteglide Admin. This copies the changes from the JSON file into the Form Configuration automatically. (Previously we recomended making changes to order in the form configuration directly, however, the method stated above is now the only reliable method.)

  • Find the form_configuration file for your form at marketplace_builder/form_configurations find the same custom fields there and add the same order properties. (This is actually the most important step. Previous steps are mainly to avoid the table overwriting your changes in form_configurations in the future).

  • Feature

    Supported?

    User CRM fields

    ✔️

    CRM Address Book - Add Addresses and if applicable store against a checkout order.

    ✔️

    Secure Zones Signup

    ✔️

    eCommerce Checkout Form

    ✔️

    eCommerce Basic Payment Form

    ✔️

    eCommerce Quote Form

    ✔️

    Static Layout

    Dynamic Layout

    Modular, component-based layouts for editing markup and styles consistently.

    ✔️

    ✔️

    Quickly get started with a ready styled layout for your form.

    ✔️

    ✔️

    Form layout files will work on any form without needing code changes.

    ❌ Re-install the layout from SiteBuilder to create a version which will work on the new form.

    ✔️

    No need to change your layout code when a new field or feature is added to the form in Admin. The liquid code dynamically updates the HTML when the page is loaded by reading the fields defined in the Siteglide Admin form configuration.

    ❌ Re-install the layout from SiteBuilder to create a version which will work with the new features.

    ✔️

    Field Type Components

    string.liquid

    boolean.liquid

    input_checkbox.liquid

    input_radio.liquid

    datasource_multi.liquid

    datasource.liquid

    Parameters

    {{name}}

    The name attribute's value.

    {{value}}

    The value attribute's value.

    {{attributes}}

    This normally adds the data-attributes needed to allow the Siteglide CRM to work correctly, where appropriate.

    {{validation}}

    Normally contains either . or required as required. For Siteglide, this needs to be included within the class list of the element (or in some cases e.g. checkbox groups, within the parent element's classList). For libraries which use Bootstrap (or another library which relies on native HTML validation to some extent), it can also be useful to add the {{validation}} inside the element so that it also adds the required attribute to the element where required.

    {{field_id}}

    The field's ID.

    {{label}}

    The human-readable name of the field. Useful for labels.

    WebApp CRUD Forms
    Module CRUD Forms
    available field groups
    editing emails & passwords
    Siteglide CLI
    JSON tools
    Installing a Form Layout
    Multi Part Forms on Demo Site

    reCaptcha or hCaptcha

    Full control over re-ordering fields in the Layout Code.

    date.liquid

    {{options}}

    ├───forms
    │   ├───form_1
    │   │   │   flowbite-contact-1-3.liquid
    │   │   │
    │   │   └───flowbite-contact-1-3_components
    │   │           array_custom.liquid
    │   │           basic_payment.liquid
    │   │           boolean.liquid
    │   │           checkout_standard.liquid
    │   │           datasource.liquid
    │   │           datasource_multi.liquid
    │   │           date.liquid
    │   │           email.liquid
    │   │           file.liquid
    │   │           folder.liquid
    │   │           heading.liquid
    │   │           hidden_fields.liquid
    │   │           image.liquid
    │   │           image_array.liquid
    │   │           input_checkbox.liquid
    │   │           input_radio.liquid
    │   │           name_field.liquid
    │   │           number_float.liquid
    │   │           number_integer.liquid
    │   │           password.liquid
    │   │           quote_only.liquid
    │   │           recaptcha.liquid
    │   │           select.liquid
    │   │           select_multi.liquid
    │   │           string.liquid
    │   │           subheading.liquid
    │   │           subscription_detail.liquid
    │   │           textarea.liquid
    {% include %}
    
    
    {% include "modules/module_86/form_layout_fields", collection: 'true' %}
    
    {% include 'form_layout_fields' %}
    
    
    {{context.exports.sitegurus_ui.form_fields | html_safe: raw_text: true }}
    
    {{context.exports.sitegurus_ui.form_hidden | html_safe: raw_text: true }}
    
    {% assign form_addresses = context.exports.sitegurus_ui.form_addresses | parse_json %}
    {% for address in form_addresses %}
      <h3 class="h4 mb-5">{{address[0]}}</h3>
      <div class="row">
        {{address[1].html | html_safe: raw_text: true}}
      </div>
    {% endfor %}
    
    
    {{context.exports.sitegurus_ui.form_recaptcha | html_safe: raw_text: true }}
    
    {{context.exports.sitegurus_ui.form_payment | html_safe: raw_text: true }}
    
    {{context.exports.module_86.form_fields_deferred | detect: name: 'Example Field Name' | dig: 'html' | html_safe: raw_text: true }}
    
    {{context.exports.module_86.form_fields_deferred}}
    
    {% include "modules/module_86/form_layout_fields", collection: 'true', hide_name_while_logged_in: 'false', hide_email_while_logged_in: 'true' %}
    
    
    <div class="
    {% if context.current_user.id != blank and hide_email_while_logged_in == 'true' %} absolute w-0 h-0 invisible  {% endif %}
    
    " >
      <!-- Add rest of email component here. -->
    </div>
    
    <div class="
    {% if context.current_user.id != blank and hide_name_while_logged_in == 'true' %} absolute w-0 h-0 invisible  {% endif %}
    
    
    
    
    ">
      <!-- Add rest of name_field component here. -->
    </div>
    
    </div>
    {% include 'form_layout_fields', custom_form_redirect: context.location.href %}
    
    <div class="col-span-6 sm:col-span-3">
      <div class="">
        <label class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300" for="{{name}}">{{label}}</label>
        <input {{attributes}} {{validation}} id="{{name}}" name="{{name}}" class="..." type="text" value="{{value}}">
      </div>
    </div>
    hide_email_while_logged_in
    hide_name_while_logged_in

    Example Tailwind Project Setup

    Example setup for Tailwind Projects. We will update this when a new version is released. The module itself will only update new sites, not existing sites when there is a breaking change.

    Note, Siteglide Studio uses the Tailwind Play CDN out of the box, meaning learning these setup steps is no longer required, however, for best practice it is worth following these on production.

    About

    We ship a folder named open_me_to_setup_tailwind_first_time to distribute our recommended template for setting up Tailwind on a new site, however, to avoid causing conflict issues, we don't update this in the Site itself when you update the module. Instead, we will add examples of our recommended configuration here.

    Configuration Version Control

    We recommend you update the open_me_to_setup_tailwind_first_time folder at the same time as you make changes to the configuration on your site, or use Github to track your changes. This is so other developers, or yourself on a different machine load the same configuration as you and build Tailwind in a consistent way!

    Troubleshooting and Customising

    Note, for this configuration to work, you may need to run npm i to install node module dependencies and siteglide-cli pull to fetch dependencies like presets.

    If you already use npm on your project, do not copy the package and package-lock files and instead install the dev dependencies and scripts used in package.json manually.

    Example Setup

    marketplace_builder/assets/css/modules/module_86/src/tailwind.config.js

    marketplace_builder/assets/css/modules/module_86/src/tailwind.css

    package.json

    package-lock.json

    /** @type {import('tailwindcss').Config} */
    
    const defaultTheme = require('tailwindcss/defaultTheme');
    const colors = require('tailwindcss/colors')
    /* Run watch command: ```json
    npx tailwindcss -c ./admin_tailwind.config.js -i ./tailwind_src/admin.css -o ./modules/module_86/private/assets/css/tailwind-admin.min.css --watch --minify
    ``` */
    
    module.exports = {
      //Pointing at sitebuilder_preset_settings will apply the changes from SiteBuilder settings. If you don't want to use these preset settings, you can remove this preset, or overwrite individual settings in theme.
      presets: [
        require('tailwindcss/../../modules/module_86/public/assets/css/presets/sitebuilder_preset_settings')
      ],
      content: [
        "./marketplace_builder/**/*.{html,js,min.js,liquid}",
        "./modules/**/*.{html,js,min.js,liquid}",
        "./node_modules/flowbite/**/*.js"
      ],
      //See an example with all of the default Tailwind settings here: https://github.com/tailwindlabs/tailwindcss/blob/main/stubs/config.full.js
      //SiteBuilder presets will also extend by creating new colours: primary, secondary, accent, info, success, danger, warning.
      theme: {
        extend: {
          
        }
      },
      plugins: [
        require('flowbite/../../modules/module_86/public/assets/css/presets/flowbite_plugin_fork_colors_disabled'),
        require('flowbite-typography')
      ],
      darkMode: 'class',
      safelist: []
    }
    
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
    /* See https://tailwindcss.com/docs/adding-custom-styles#using-css-and-layer */
    
    @layer base {
      /* The base layer is for things like reset rules or default styles applied to plain HTML elements.*/
    
    }
    
    @layer components {
      /*The components layer is for class-based styles that you want to be able to override with utilities. */
    
    }
    
    @layer utilities {
      /* The utilities layer is for small, single-purpose classes that should always take precedence over any other styles. */
    }
    {
      "name": "SiteBuilder Tailwind Template for Siteglide",
      "version": "1.0.0",
      "description": "A template for getting started using the CLI with Siteglide, SiteBuilder Module, Tailwind and the Flowbite Library.",
      "main": "tailwind.config.js",
      "scripts": {
        "tailwind": "npx tailwindcss -c ./marketplace_builder/assets/modules/module_86/src/tailwind.config.js -i ./marketplace_builder/assets/modules/module_86/src/tailwind.css -o ./marketplace_builder/assets/css/tailwind.min.css --watch --minify"
      },
      "keywords": [],
      "author": "SiteGurus",
      "devDependencies": {
        "flowbite": "^2.5.2",
        "flowbite-typography": "^1.0.3",
        "tailwindcss": "^3.4.3"
      }
    }
    {
      "name": "SiteBuilder Tailwind Template for Siteglide",
      "version": "1.0.0",
      "lockfileVersion": 2,
      "requires": true,
      "packages": {
        "": {
          "name": "SiteBuilder Tailwind Template for Siteglide",
          "version": "1.0.0",
          "devDependencies": {
            "flowbite": "^2.5.2",
            "flowbite-typography": "^1.0.3",
            "tailwindcss": "^3.4.3"
          }
        },
        "node_modules/@alloc/quick-lru": {
          "version": "5.2.0",
          "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
          "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
          "dev": true,
          "engines": {
            "node": ">=10"
          },
          "funding": {
            "url": "https://github.com/sponsors/sindresorhus"
          }
        },
        "node_modules/@jridgewell/gen-mapping": {
          "version": "0.3.3",
          "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
          "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
          "dev": true,
          "dependencies": {
            "@jridgewell/set-array": "^1.0.1",
            "@jridgewell/sourcemap-codec": "^1.4.10",
            "@jridgewell/trace-mapping": "^0.3.9"
          },
          "engines": {
            "node": ">=6.0.0"
          }
        },
        "node_modules/@jridgewell/resolve-uri": {
          "version": "3.1.0",
          "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
          "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
          "dev": true,
          "engines": {
            "node": ">=6.0.0"
          }
        },
        "node_modules/@jridgewell/set-array": {
          "version": "1.1.2",
          "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
          "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
          "dev": true,
          "engines": {
            "node": ">=6.0.0"
          }
        },
        "node_modules/@jridgewell/sourcemap-codec": {
          "version": "1.4.15",
          "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
          "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
          "dev": true
        },
        "node_modules/@jridgewell/trace-mapping": {
          "version": "0.3.18",
          "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
          "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
          "dev": true,
          "dependencies": {
            "@jridgewell/resolve-uri": "3.1.0",
            "@jridgewell/sourcemap-codec": "1.4.14"
          }
        },
        "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
          "version": "1.4.14",
          "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
          "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
          "dev": true
        },
        "node_modules/@nodelib/fs.scandir": {
          "version": "2.1.5",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
          "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
          "dev": true,
          "dependencies": {
            "@nodelib/fs.stat": "2.0.5",
            "run-parallel": "^1.1.9"
          },
          "engines": {
            "node": ">= 8"
          }
        },
        "node_modules/@nodelib/fs.stat": {
          "version": "2.0.5",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
          "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
          "dev": true,
          "engines": {
            "node": ">= 8"
          }
        },
        "node_modules/@nodelib/fs.walk": {
          "version": "1.2.8",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
          "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
          "dev": true,
          "dependencies": {
            "@nodelib/fs.scandir": "2.1.5",
            "fastq": "^1.6.0"
          },
          "engines": {
            "node": ">= 8"
          }
        },
        "node_modules/@popperjs/core": {
          "version": "2.11.5",
          "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
          "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
          "dev": true,
          "funding": {
            "type": "opencollective",
            "url": "https://opencollective.com/popperjs"
          }
        },
        "node_modules/any-promise": {
          "version": "1.3.0",
          "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
          "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
          "dev": true
        },
        "node_modules/anymatch": {
          "version": "3.1.2",
          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
          "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
          "dev": true,
          "dependencies": {
            "normalize-path": "^3.0.0",
            "picomatch": "^2.0.4"
          },
          "engines": {
            "node": ">= 8"
          }
        },
        "node_modules/arg": {
          "version": "5.0.2",
          "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
          "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
          "dev": true
        },
        "node_modules/balanced-match": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
          "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
          "dev": true
        },
        "node_modules/binary-extensions": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
          "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
          "dev": true,
          "engines": {
            "node": ">=8"
          }
        },
        "node_modules/brace-expansion": {
          "version": "1.1.11",
          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
          "dev": true,
          "dependencies": {
            "balanced-match": "^1.0.0",
            "concat-map": "0.0.1"
          }
        },
        "node_modules/braces": {
          "version": "3.0.2",
          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
          "dev": true,
          "dependencies": {
            "fill-range": "^7.0.1"
          },
          "engines": {
            "node": ">=8"
          }
        },
        "node_modules/camelcase-css": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
          "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
          "dev": true,
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/chokidar": {
          "version": "3.5.3",
          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
          "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
          "dev": true,
          "funding": [
            {
              "type": "individual",
              "url": "https://paulmillr.com/funding/"
            }
          ],
          "dependencies": {
            "anymatch": "~3.1.2",
            "braces": "~3.0.2",
            "glob-parent": "~5.1.2",
            "is-binary-path": "~2.1.0",
            "is-glob": "~4.0.1",
            "normalize-path": "~3.0.0",
            "readdirp": "~3.6.0"
          },
          "engines": {
            "node": ">= 8.10.0"
          },
          "optionalDependencies": {
            "fsevents": "~2.3.2"
          }
        },
        "node_modules/chokidar/node_modules/glob-parent": {
          "version": "5.1.2",
          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
          "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
          "dev": true,
          "dependencies": {
            "is-glob": "^4.0.1"
          },
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/commander": {
          "version": "4.1.1",
          "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
          "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
          "dev": true,
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/concat-map": {
          "version": "0.0.1",
          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
          "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
          "dev": true
        },
        "node_modules/cssesc": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
          "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
          "dev": true,
          "bin": {
            "cssesc": "bin/cssesc"
          },
          "engines": {
            "node": ">=4"
          }
        },
        "node_modules/didyoumean": {
          "version": "1.2.2",
          "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
          "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
          "dev": true
        },
        "node_modules/dlv": {
          "version": "1.1.3",
          "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
          "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
          "dev": true
        },
        "node_modules/fast-glob": {
          "version": "3.3.2",
          "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
          "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
          "dev": true,
          "dependencies": {
            "@nodelib/fs.stat": "^2.0.2",
            "@nodelib/fs.walk": "^1.2.3",
            "glob-parent": "^5.1.2",
            "merge2": "^1.3.0",
            "micromatch": "^4.0.4"
          },
          "engines": {
            "node": ">=8.6.0"
          }
        },
        "node_modules/fast-glob/node_modules/glob-parent": {
          "version": "5.1.2",
          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
          "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
          "dev": true,
          "dependencies": {
            "is-glob": "^4.0.1"
          },
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/fastq": {
          "version": "1.17.1",
          "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
          "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
          "dev": true,
          "dependencies": {
            "reusify": "^1.0.4"
          }
        },
        "node_modules/fill-range": {
          "version": "7.0.1",
          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
          "dev": true,
          "dependencies": {
            "to-regex-range": "^5.0.1"
          },
          "engines": {
            "node": ">=8"
          }
        },
        "node_modules/flowbite": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.3.0.tgz",
          "integrity": "sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==",
          "dev": true,
          "dependencies": {
            "@popperjs/core": "^2.9.3",
            "mini-svg-data-uri": "^1.4.3"
          }
        },
        "node_modules/flowbite-typography": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/flowbite-typography/-/flowbite-typography-1.0.2.tgz",
          "integrity": "sha512-jRN0NJFG/p0nQNAdysyoKJp++0feQ6jHWCE+tJTBlw46/tFOYW99eKDHJOnvXPNik85crhkm+voWC4ifO1+HSw==",
          "dev": true,
          "dependencies": {
            "lodash.castarray": "^4.4.0",
            "lodash.isplainobject": "^4.0.6",
            "lodash.merge": "^4.6.2"
          },
          "peerDependencies": {
            "tailwindcss": ">=3.0.0 || insiders"
          }
        },
        "node_modules/fs.realpath": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
          "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
          "dev": true
        },
        "node_modules/fsevents": {
          "version": "2.3.2",
          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
          "dev": true,
          "hasInstallScript": true,
          "optional": true,
          "os": [
            "darwin"
          ],
          "engines": {
            "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
          }
        },
        "node_modules/function-bind": {
          "version": "1.1.1",
          "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
          "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
          "dev": true
        },
        "node_modules/glob": {
          "version": "7.1.6",
          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
          "dev": true,
          "dependencies": {
            "fs.realpath": "^1.0.0",
            "inflight": "^1.0.4",
            "inherits": "2",
            "minimatch": "^3.0.4",
            "once": "^1.3.0",
            "path-is-absolute": "^1.0.0"
          },
          "engines": {
            "node": "*"
          },
          "funding": {
            "url": "https://github.com/sponsors/isaacs"
          }
        },
        "node_modules/glob-parent": {
          "version": "6.0.2",
          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
          "dev": true,
          "dependencies": {
            "is-glob": "^4.0.3"
          },
          "engines": {
            "node": ">=10.13.0"
          }
        },
        "node_modules/has": {
          "version": "1.0.3",
          "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
          "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
          "dev": true,
          "dependencies": {
            "function-bind": "^1.1.1"
          },
          "engines": {
            "node": ">= 0.4.0"
          }
        },
        "node_modules/inflight": {
          "version": "1.0.6",
          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
          "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
          "dev": true,
          "dependencies": {
            "once": "^1.3.0",
            "wrappy": "1"
          }
        },
        "node_modules/inherits": {
          "version": "2.0.4",
          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
          "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
          "dev": true
        },
        "node_modules/is-binary-path": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
          "dev": true,
          "dependencies": {
            "binary-extensions": "^2.0.0"
          },
          "engines": {
            "node": ">=8"
          }
        },
        "node_modules/is-core-module": {
          "version": "2.12.1",
          "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
          "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
          "dev": true,
          "dependencies": {
            "has": "^1.0.3"
          },
          "funding": {
            "url": "https://github.com/sponsors/ljharb"
          }
        },
        "node_modules/is-extglob": {
          "version": "2.1.1",
          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
          "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/is-glob": {
          "version": "4.0.3",
          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
          "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
          "dev": true,
          "dependencies": {
            "is-extglob": "^2.1.1"
          },
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/is-number": {
          "version": "7.0.0",
          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
          "dev": true,
          "engines": {
            "node": ">=0.12.0"
          }
        },
        "node_modules/jiti": {
          "version": "1.21.0",
          "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
          "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
          "dev": true,
          "bin": {
            "jiti": "bin/jiti.js"
          }
        },
        "node_modules/lilconfig": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
          "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
          "dev": true,
          "engines": {
            "node": ">=10"
          }
        },
        "node_modules/lines-and-columns": {
          "version": "1.2.4",
          "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
          "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
          "dev": true
        },
        "node_modules/lodash.castarray": {
          "version": "4.4.0",
          "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
          "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
          "dev": true
        },
        "node_modules/lodash.isplainobject": {
          "version": "4.0.6",
          "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
          "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
          "dev": true
        },
        "node_modules/lodash.merge": {
          "version": "4.6.2",
          "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
          "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
          "dev": true
        },
        "node_modules/merge2": {
          "version": "1.4.1",
          "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
          "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
          "dev": true,
          "engines": {
            "node": ">= 8"
          }
        },
        "node_modules/micromatch": {
          "version": "4.0.5",
          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
          "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
          "dev": true,
          "dependencies": {
            "braces": "^3.0.2",
            "picomatch": "^2.3.1"
          },
          "engines": {
            "node": ">=8.6"
          }
        },
        "node_modules/mini-svg-data-uri": {
          "version": "1.4.4",
          "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
          "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
          "dev": true,
          "bin": {
            "mini-svg-data-uri": "cli.js"
          }
        },
        "node_modules/minimatch": {
          "version": "3.1.2",
          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
          "dev": true,
          "dependencies": {
            "brace-expansion": "^1.1.7"
          },
          "engines": {
            "node": "*"
          }
        },
        "node_modules/mz": {
          "version": "2.7.0",
          "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
          "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
          "dev": true,
          "dependencies": {
            "any-promise": "^1.0.0",
            "object-assign": "^4.0.1",
            "thenify-all": "^1.0.0"
          }
        },
        "node_modules/nanoid": {
          "version": "3.3.6",
          "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
          "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
          "dev": true,
          "funding": [
            {
              "type": "github",
              "url": "https://github.com/sponsors/ai"
            }
          ],
          "bin": {
            "nanoid": "bin/nanoid.cjs"
          },
          "engines": {
            "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
          }
        },
        "node_modules/normalize-path": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/object-assign": {
          "version": "4.1.1",
          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
          "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/object-hash": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
          "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
          "dev": true,
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/once": {
          "version": "1.4.0",
          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
          "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
          "dev": true,
          "dependencies": {
            "wrappy": "1"
          }
        },
        "node_modules/path-is-absolute": {
          "version": "1.0.1",
          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
          "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/path-parse": {
          "version": "1.0.7",
          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
          "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
          "dev": true
        },
        "node_modules/picocolors": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
          "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
          "dev": true
        },
        "node_modules/picomatch": {
          "version": "2.3.1",
          "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
          "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
          "dev": true,
          "engines": {
            "node": ">=8.6"
          },
          "funding": {
            "url": "https://github.com/sponsors/jonschlinkert"
          }
        },
        "node_modules/pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/pirates": {
          "version": "4.0.5",
          "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
          "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
          "dev": true,
          "engines": {
            "node": ">= 6"
          }
        },
        "node_modules/postcss": {
          "version": "8.4.23",
          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
          "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
          "dev": true,
          "funding": [
            {
              "type": "opencollective",
              "url": "https://opencollective.com/postcss/"
            },
            {
              "type": "tidelift",
              "url": "https://tidelift.com/funding/github/npm/postcss"
            },
            {
              "type": "github",
              "url": "https://github.com/sponsors/ai"
            }
          ],
          "dependencies": {
            "nanoid": "^3.3.6",
            "picocolors": "^1.0.0",
            "source-map-js": "^1.0.2"
          },
          "engines": {
            "node": "^10 || ^12 || >=14"
          }
        },
        "node_modules/postcss-import": {
          "version": "15.1.0",
          "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
          "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
          "dev": true,
          "dependencies": {
            "postcss-value-parser": "^4.0.0",
            "read-cache": "^1.0.0",
            "resolve": "^1.1.7"
          },
          "engines": {
            "node": ">=14.0.0"
          },
          "peerDependencies": {
            "postcss": "^8.0.0"
          }
        },
        "node_modules/postcss-js": {
          "version": "4.0.1",
          "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
          "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
          "dev": true,
          "dependencies": {
            "camelcase-css": "^2.0.1"
          },
          "engines": {
            "node": "^12 || ^14 || >= 16"
          },
          "funding": {
            "type": "opencollective",
            "url": "https://opencollective.com/postcss/"
          },
          "peerDependencies": {
            "postcss": "^8.4.21"
          }
        },
        "node_modules/postcss-load-config": {
          "version": "4.0.1",
          "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
          "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
          "dev": true,
          "dependencies": {
            "lilconfig": "^2.0.5",
            "yaml": "^2.1.1"
          },
          "engines": {
            "node": ">= 14"
          },
          "funding": {
            "type": "opencollective",
            "url": "https://opencollective.com/postcss/"
          },
          "peerDependencies": {
            "postcss": ">=8.0.9",
            "ts-node": ">=9.0.0"
          },
          "peerDependenciesMeta": {
            "postcss": {
              "optional": true
            },
            "ts-node": {
              "optional": true
            }
          }
        },
        "node_modules/postcss-nested": {
          "version": "6.0.1",
          "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
          "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
          "dev": true,
          "dependencies": {
            "postcss-selector-parser": "^6.0.11"
          },
          "engines": {
            "node": ">=12.0"
          },
          "funding": {
            "type": "opencollective",
            "url": "https://opencollective.com/postcss/"
          },
          "peerDependencies": {
            "postcss": "^8.2.14"
          }
        },
        "node_modules/postcss-selector-parser": {
          "version": "6.0.13",
          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
          "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
          "dev": true,
          "dependencies": {
            "cssesc": "^3.0.0",
            "util-deprecate": "^1.0.2"
          },
          "engines": {
            "node": ">=4"
          }
        },
        "node_modules/postcss-value-parser": {
          "version": "4.2.0",
          "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
          "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
          "dev": true
        },
        "node_modules/queue-microtask": {
          "version": "1.2.3",
          "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
          "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
          "dev": true,
          "funding": [
            {
              "type": "github",
              "url": "https://github.com/sponsors/feross"
            },
            {
              "type": "patreon",
              "url": "https://www.patreon.com/feross"
            },
            {
              "type": "consulting",
              "url": "https://feross.org/support"
            }
          ]
        },
        "node_modules/read-cache": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
          "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
          "dev": true,
          "dependencies": {
            "pify": "^2.3.0"
          }
        },
        "node_modules/readdirp": {
          "version": "3.6.0",
          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
          "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
          "dev": true,
          "dependencies": {
            "picomatch": "^2.2.1"
          },
          "engines": {
            "node": ">=8.10.0"
          }
        },
        "node_modules/resolve": {
          "version": "1.22.2",
          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
          "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
          "dev": true,
          "dependencies": {
            "is-core-module": "^2.11.0",
            "path-parse": "^1.0.7",
            "supports-preserve-symlinks-flag": "^1.0.0"
          },
          "bin": {
            "resolve": "bin/resolve"
          },
          "funding": {
            "url": "https://github.com/sponsors/ljharb"
          }
        },
        "node_modules/reusify": {
          "version": "1.0.4",
          "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
          "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
          "dev": true,
          "engines": {
            "iojs": ">=1.0.0",
            "node": ">=0.10.0"
          }
        },
        "node_modules/run-parallel": {
          "version": "1.2.0",
          "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
          "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
          "dev": true,
          "funding": [
            {
              "type": "github",
              "url": "https://github.com/sponsors/feross"
            },
            {
              "type": "patreon",
              "url": "https://www.patreon.com/feross"
            },
            {
              "type": "consulting",
              "url": "https://feross.org/support"
            }
          ],
          "dependencies": {
            "queue-microtask": "^1.2.2"
          }
        },
        "node_modules/source-map-js": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
          "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
          "dev": true,
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/sucrase": {
          "version": "3.32.0",
          "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
          "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==",
          "dev": true,
          "dependencies": {
            "@jridgewell/gen-mapping": "^0.3.2",
            "commander": "^4.0.0",
            "glob": "7.1.6",
            "lines-and-columns": "^1.1.6",
            "mz": "^2.7.0",
            "pirates": "^4.0.1",
            "ts-interface-checker": "^0.1.9"
          },
          "bin": {
            "sucrase": "bin/sucrase",
            "sucrase-node": "bin/sucrase-node"
          },
          "engines": {
            "node": ">=8"
          }
        },
        "node_modules/supports-preserve-symlinks-flag": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
          "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
          "dev": true,
          "engines": {
            "node": ">= 0.4"
          },
          "funding": {
            "url": "https://github.com/sponsors/ljharb"
          }
        },
        "node_modules/tailwindcss": {
          "version": "3.4.3",
          "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
          "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
          "dev": true,
          "dependencies": {
            "@alloc/quick-lru": "^5.2.0",
            "arg": "^5.0.2",
            "chokidar": "^3.5.3",
            "didyoumean": "^1.2.2",
            "dlv": "^1.1.3",
            "fast-glob": "^3.3.0",
            "glob-parent": "^6.0.2",
            "is-glob": "^4.0.3",
            "jiti": "^1.21.0",
            "lilconfig": "^2.1.0",
            "micromatch": "^4.0.5",
            "normalize-path": "^3.0.0",
            "object-hash": "^3.0.0",
            "picocolors": "^1.0.0",
            "postcss": "^8.4.23",
            "postcss-import": "^15.1.0",
            "postcss-js": "^4.0.1",
            "postcss-load-config": "^4.0.1",
            "postcss-nested": "^6.0.1",
            "postcss-selector-parser": "^6.0.11",
            "resolve": "^1.22.2",
            "sucrase": "^3.32.0"
          },
          "bin": {
            "tailwind": "lib/cli.js",
            "tailwindcss": "lib/cli.js"
          },
          "engines": {
            "node": ">=14.0.0"
          }
        },
        "node_modules/thenify": {
          "version": "3.3.1",
          "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
          "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
          "dev": true,
          "dependencies": {
            "any-promise": "^1.0.0"
          }
        },
        "node_modules/thenify-all": {
          "version": "1.6.0",
          "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
          "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
          "dev": true,
          "dependencies": {
            "thenify": ">= 3.1.0 < 4"
          },
          "engines": {
            "node": ">=0.8"
          }
        },
        "node_modules/to-regex-range": {
          "version": "5.0.1",
          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
          "dev": true,
          "dependencies": {
            "is-number": "^7.0.0"
          },
          "engines": {
            "node": ">=8.0"
          }
        },
        "node_modules/ts-interface-checker": {
          "version": "0.1.13",
          "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
          "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
          "dev": true
        },
        "node_modules/util-deprecate": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
          "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
          "dev": true
        },
        "node_modules/wrappy": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
          "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
          "dev": true
        },
        "node_modules/yaml": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.0.tgz",
          "integrity": "sha512-8/1wgzdKc7bc9E6my5wZjmdavHLvO/QOmLG1FBugblEvY4IXrLjlViIOmL24HthU042lWTDRO90Fz1Yp66UnMw==",
          "dev": true,
          "engines": {
            "node": ">= 14",
            "npm": ">= 7"
          }
        }
      },
      "dependencies": {
        "@alloc/quick-lru": {
          "version": "5.2.0",
          "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
          "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
          "dev": true
        },
        "@jridgewell/gen-mapping": {
          "version": "0.3.3",
          "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
          "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
          "dev": true,
          "requires": {
            "@jridgewell/set-array": "^1.0.1",
            "@jridgewell/sourcemap-codec": "^1.4.10",
            "@jridgewell/trace-mapping": "^0.3.9"
          }
        },
        "@jridgewell/resolve-uri": {
          "version": "3.1.0",
          "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
          "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
          "dev": true
        },
        "@jridgewell/set-array": {
          "version": "1.1.2",
          "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
          "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
          "dev": true
        },
        "@jridgewell/sourcemap-codec": {
          "version": "1.4.15",
          "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
          "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
          "dev": true
        },
        "@jridgewell/trace-mapping": {
          "version": "0.3.18",
          "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
          "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
          "dev": true,
          "requires": {
            "@jridgewell/resolve-uri": "3.1.0",
            "@jridgewell/sourcemap-codec": "1.4.14"
          },
          "dependencies": {
            "@jridgewell/sourcemap-codec": {
              "version": "1.4.14",
              "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
              "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
              "dev": true
            }
          }
        },
        "@nodelib/fs.scandir": {
          "version": "2.1.5",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
          "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
          "dev": true,
          "requires": {
            "@nodelib/fs.stat": "2.0.5",
            "run-parallel": "^1.1.9"
          }
        },
        "@nodelib/fs.stat": {
          "version": "2.0.5",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
          "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
          "dev": true
        },
        "@nodelib/fs.walk": {
          "version": "1.2.8",
          "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
          "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
          "dev": true,
          "requires": {
            "@nodelib/fs.scandir": "2.1.5",
            "fastq": "^1.6.0"
          }
        },
        "@popperjs/core": {
          "version": "2.11.5",
          "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
          "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
          "dev": true
        },
        "any-promise": {
          "version": "1.3.0",
          "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
          "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
          "dev": true
        },
        "anymatch": {
          "version": "3.1.2",
          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
          "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
          "dev": true,
          "requires": {
            "normalize-path": "^3.0.0",
            "picomatch": "^2.0.4"
          }
        },
        "arg": {
          "version": "5.0.2",
          "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
          "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
          "dev": true
        },
        "balanced-match": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
          "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
          "dev": true
        },
        "binary-extensions": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
          "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
          "dev": true
        },
        "brace-expansion": {
          "version": "1.1.11",
          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
          "dev": true,
          "requires": {
            "balanced-match": "^1.0.0",
            "concat-map": "0.0.1"
          }
        },
        "braces": {
          "version": "3.0.2",
          "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
          "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
          "dev": true,
          "requires": {
            "fill-range": "^7.0.1"
          }
        },
        "camelcase-css": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
          "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
          "dev": true
        },
        "chokidar": {
          "version": "3.5.3",
          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
          "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
          "dev": true,
          "requires": {
            "anymatch": "~3.1.2",
            "braces": "~3.0.2",
            "fsevents": "~2.3.2",
            "glob-parent": "~5.1.2",
            "is-binary-path": "~2.1.0",
            "is-glob": "~4.0.1",
            "normalize-path": "~3.0.0",
            "readdirp": "~3.6.0"
          },
          "dependencies": {
            "glob-parent": {
              "version": "5.1.2",
              "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
              "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
              "dev": true,
              "requires": {
                "is-glob": "^4.0.1"
              }
            }
          }
        },
        "commander": {
          "version": "4.1.1",
          "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
          "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
          "dev": true
        },
        "concat-map": {
          "version": "0.0.1",
          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
          "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
          "dev": true
        },
        "cssesc": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
          "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
          "dev": true
        },
        "didyoumean": {
          "version": "1.2.2",
          "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
          "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
          "dev": true
        },
        "dlv": {
          "version": "1.1.3",
          "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
          "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
          "dev": true
        },
        "fast-glob": {
          "version": "3.3.2",
          "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
          "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
          "dev": true,
          "requires": {
            "@nodelib/fs.stat": "^2.0.2",
            "@nodelib/fs.walk": "^1.2.3",
            "glob-parent": "^5.1.2",
            "merge2": "^1.3.0",
            "micromatch": "^4.0.4"
          },
          "dependencies": {
            "glob-parent": {
              "version": "5.1.2",
              "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
              "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
              "dev": true,
              "requires": {
                "is-glob": "^4.0.1"
              }
            }
          }
        },
        "fastq": {
          "version": "1.17.1",
          "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
          "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
          "dev": true,
          "requires": {
            "reusify": "^1.0.4"
          }
        },
        "fill-range": {
          "version": "7.0.1",
          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
          "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
          "dev": true,
          "requires": {
            "to-regex-range": "^5.0.1"
          }
        },
        "flowbite": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.3.0.tgz",
          "integrity": "sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==",
          "dev": true,
          "requires": {
            "@popperjs/core": "^2.9.3",
            "mini-svg-data-uri": "^1.4.3"
          }
        },
        "flowbite-typography": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/flowbite-typography/-/flowbite-typography-1.0.2.tgz",
          "integrity": "sha512-jRN0NJFG/p0nQNAdysyoKJp++0feQ6jHWCE+tJTBlw46/tFOYW99eKDHJOnvXPNik85crhkm+voWC4ifO1+HSw==",
          "dev": true,
          "requires": {
            "lodash.castarray": "^4.4.0",
            "lodash.isplainobject": "^4.0.6",
            "lodash.merge": "^4.6.2"
          }
        },
        "fs.realpath": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
          "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
          "dev": true
        },
        "fsevents": {
          "version": "2.3.2",
          "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
          "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
          "dev": true,
          "optional": true
        },
        "function-bind": {
          "version": "1.1.1",
          "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
          "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
          "dev": true
        },
        "glob": {
          "version": "7.1.6",
          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
          "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
          "dev": true,
          "requires": {
            "fs.realpath": "^1.0.0",
            "inflight": "^1.0.4",
            "inherits": "2",
            "minimatch": "^3.0.4",
            "once": "^1.3.0",
            "path-is-absolute": "^1.0.0"
          }
        },
        "glob-parent": {
          "version": "6.0.2",
          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
          "dev": true,
          "requires": {
            "is-glob": "^4.0.3"
          }
        },
        "has": {
          "version": "1.0.3",
          "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
          "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
          "dev": true,
          "requires": {
            "function-bind": "^1.1.1"
          }
        },
        "inflight": {
          "version": "1.0.6",
          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
          "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
          "dev": true,
          "requires": {
            "once": "^1.3.0",
            "wrappy": "1"
          }
        },
        "inherits": {
          "version": "2.0.4",
          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
          "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
          "dev": true
        },
        "is-binary-path": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
          "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
          "dev": true,
          "requires": {
            "binary-extensions": "^2.0.0"
          }
        },
        "is-core-module": {
          "version": "2.12.1",
          "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
          "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
          "dev": true,
          "requires": {
            "has": "^1.0.3"
          }
        },
        "is-extglob": {
          "version": "2.1.1",
          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
          "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
          "dev": true
        },
        "is-glob": {
          "version": "4.0.3",
          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
          "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
          "dev": true,
          "requires": {
            "is-extglob": "^2.1.1"
          }
        },
        "is-number": {
          "version": "7.0.0",
          "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
          "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
          "dev": true
        },
        "jiti": {
          "version": "1.21.0",
          "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
          "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
          "dev": true
        },
        "lilconfig": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
          "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
          "dev": true
        },
        "lines-and-columns": {
          "version": "1.2.4",
          "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
          "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
          "dev": true
        },
        "lodash.castarray": {
          "version": "4.4.0",
          "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
          "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
          "dev": true
        },
        "lodash.isplainobject": {
          "version": "4.0.6",
          "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
          "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
          "dev": true
        },
        "lodash.merge": {
          "version": "4.6.2",
          "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
          "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
          "dev": true
        },
        "merge2": {
          "version": "1.4.1",
          "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
          "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
          "dev": true
        },
        "micromatch": {
          "version": "4.0.5",
          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
          "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
          "dev": true,
          "requires": {
            "braces": "^3.0.2",
            "picomatch": "^2.3.1"
          }
        },
        "mini-svg-data-uri": {
          "version": "1.4.4",
          "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
          "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
          "dev": true
        },
        "minimatch": {
          "version": "3.1.2",
          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
          "dev": true,
          "requires": {
            "brace-expansion": "^1.1.7"
          }
        },
        "mz": {
          "version": "2.7.0",
          "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
          "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
          "dev": true,
          "requires": {
            "any-promise": "^1.0.0",
            "object-assign": "^4.0.1",
            "thenify-all": "^1.0.0"
          }
        },
        "nanoid": {
          "version": "3.3.6",
          "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
          "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
          "dev": true
        },
        "normalize-path": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
          "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
          "dev": true
        },
        "object-assign": {
          "version": "4.1.1",
          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
          "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
          "dev": true
        },
        "object-hash": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
          "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
          "dev": true
        },
        "once": {
          "version": "1.4.0",
          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
          "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
          "dev": true,
          "requires": {
            "wrappy": "1"
          }
        },
        "path-is-absolute": {
          "version": "1.0.1",
          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
          "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
          "dev": true
        },
        "path-parse": {
          "version": "1.0.7",
          "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
          "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
          "dev": true
        },
        "picocolors": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
          "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
          "dev": true
        },
        "picomatch": {
          "version": "2.3.1",
          "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
          "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
          "dev": true
        },
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
          "dev": true
        },
        "pirates": {
          "version": "4.0.5",
          "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
          "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
          "dev": true
        },
        "postcss": {
          "version": "8.4.23",
          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz",
          "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==",
          "dev": true,
          "requires": {
            "nanoid": "^3.3.6",
            "picocolors": "^1.0.0",
            "source-map-js": "^1.0.2"
          }
        },
        "postcss-import": {
          "version": "15.1.0",
          "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
          "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
          "dev": true,
          "requires": {
            "postcss-value-parser": "^4.0.0",
            "read-cache": "^1.0.0",
            "resolve": "^1.1.7"
          }
        },
        "postcss-js": {
          "version": "4.0.1",
          "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
          "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
          "dev": true,
          "requires": {
            "camelcase-css": "^2.0.1"
          }
        },
        "postcss-load-config": {
          "version": "4.0.1",
          "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
          "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
          "dev": true,
          "requires": {
            "lilconfig": "^2.0.5",
            "yaml": "^2.1.1"
          }
        },
        "postcss-nested": {
          "version": "6.0.1",
          "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
          "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
          "dev": true,
          "requires": {
            "postcss-selector-parser": "^6.0.11"
          }
        },
        "postcss-selector-parser": {
          "version": "6.0.13",
          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
          "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
          "dev": true,
          "requires": {
            "cssesc": "^3.0.0",
            "util-deprecate": "^1.0.2"
          }
        },
        "postcss-value-parser": {
          "version": "4.2.0",
          "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
          "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
          "dev": true
        },
        "queue-microtask": {
          "version": "1.2.3",
          "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
          "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
          "dev": true
        },
        "read-cache": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
          "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
          "dev": true,
          "requires": {
            "pify": "^2.3.0"
          }
        },
        "readdirp": {
          "version": "3.6.0",
          "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
          "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
          "dev": true,
          "requires": {
            "picomatch": "^2.2.1"
          }
        },
        "resolve": {
          "version": "1.22.2",
          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
          "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
          "dev": true,
          "requires": {
            "is-core-module": "^2.11.0",
            "path-parse": "^1.0.7",
            "supports-preserve-symlinks-flag": "^1.0.0"
          }
        },
        "reusify": {
          "version": "1.0.4",
          "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
          "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
          "dev": true
        },
        "run-parallel": {
          "version": "1.2.0",
          "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
          "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
          "dev": true,
          "requires": {
            "queue-microtask": "^1.2.2"
          }
        },
        "source-map-js": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
          "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
          "dev": true
        },
        "sucrase": {
          "version": "3.32.0",
          "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
          "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==",
          "dev": true,
          "requires": {
            "@jridgewell/gen-mapping": "^0.3.2",
            "commander": "^4.0.0",
            "glob": "7.1.6",
            "lines-and-columns": "^1.1.6",
            "mz": "^2.7.0",
            "pirates": "^4.0.1",
            "ts-interface-checker": "^0.1.9"
          }
        },
        "supports-preserve-symlinks-flag": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
          "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
          "dev": true
        },
        "tailwindcss": {
          "version": "3.4.3",
          "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
          "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
          "dev": true,
          "requires": {
            "@alloc/quick-lru": "^5.2.0",
            "arg": "^5.0.2",
            "chokidar": "^3.5.3",
            "didyoumean": "^1.2.2",
            "dlv": "^1.1.3",
            "fast-glob": "^3.3.0",
            "glob-parent": "^6.0.2",
            "is-glob": "^4.0.3",
            "jiti": "^1.21.0",
            "lilconfig": "^2.1.0",
            "micromatch": "^4.0.5",
            "normalize-path": "^3.0.0",
            "object-hash": "^3.0.0",
            "picocolors": "^1.0.0",
            "postcss": "^8.4.23",
            "postcss-import": "^15.1.0",
            "postcss-js": "^4.0.1",
            "postcss-load-config": "^4.0.1",
            "postcss-nested": "^6.0.1",
            "postcss-selector-parser": "^6.0.11",
            "resolve": "^1.22.2",
            "sucrase": "^3.32.0"
          }
        },
        "thenify": {
          "version": "3.3.1",
          "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
          "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
          "dev": true,
          "requires": {
            "any-promise": "^1.0.0"
          }
        },
        "thenify-all": {
          "version": "1.6.0",
          "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
          "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
          "dev": true,
          "requires": {
            "thenify": ">= 3.1.0 < 4"
          }
        },
        "to-regex-range": {
          "version": "5.0.1",
          "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
          "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
          "dev": true,
          "requires": {
            "is-number": "^7.0.0"
          }
        },
        "ts-interface-checker": {
          "version": "0.1.13",
          "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
          "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
          "dev": true
        },
        "util-deprecate": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
          "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
          "dev": true
        },
        "wrappy": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
          "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
          "dev": true
        },
        "yaml": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.0.tgz",
          "integrity": "sha512-8/1wgzdKc7bc9E6my5wZjmdavHLvO/QOmLG1FBugblEvY4IXrLjlViIOmL24HthU042lWTDRO90Fz1Yp66UnMw==",
          "dev": true
        }
      }
    }