-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
## Pie Chart
Pie charts are a simple and effective way to visualize proportions and ratios. They are commonly used to represent data as percentages of a whole, making them ideal for displaying parts of a dataset. Below is an example of a pie chart showcasing distribution across categories:
-{% capture html -%}
-
-
- {% include "ui/chart.html" chart-id="demo-pie" height=15 %}
+
+
-
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
## Heatmap Chart
Heatmaps provide a graphical representation of data where individual values are represented by color intensity. They are particularly useful for identifying patterns or anomalies within large datasets. Here's an example of a heatmap chart to visualize data distributions:
-{% capture html -%}
-
-
- {% include "ui/chart-heatmap.html" chart-id="demo-heatmap" height=15 %}
+
+
-
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
## Advanced example
For more complex data visualizations, you can create advanced charts with multiple series and custom configurations. Below is an example of a social media referrals chart combining data from Facebook, Twitter, and Dribbble:
-{% capture html -%}
-
-
- {% include "ui/chart.html" chart-id="social-referrals" height=15 %}
+
+
-
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
diff --git a/docs/content/ui/components/countup.md b/docs/pages/ui/components/countup.mdx
similarity index 57%
rename from docs/content/ui/components/countup.md
rename to docs/pages/ui/components/countup.mdx
index 11bab230b..02eed9918 100644
--- a/docs/content/ui/components/countup.md
+++ b/docs/pages/ui/components/countup.mdx
@@ -3,7 +3,9 @@ title: Countup
summary: A countup element is used to display numerical data in an interesting way and make the interface more interactive.
docs-libs: countup
description: Display numbers dynamically with a countup.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
The countup component is used to display numbers dynamically. It is a great way to make the interface more interactive and engaging. The countup component is a simple and easy way to animate numbers in your application.
@@ -21,21 +23,17 @@ To create a countup, add `data-countup` to any HTML text tag and specify the num
The results can be seen in the example below.
-{% capture html -%}
+
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html centered %}
+
## Duration
Set the `duration` to determine how long the animation should take. By default, the duration is set to 2 seconds, but you can modify it as you wish.
-{% capture html -%}
-
30000
-
30000
-
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+30000 30000 30000
+
## Starting value
@@ -43,80 +41,62 @@ By default the countup will start from zero. If you want to set a different star
You can also set the start value to be greater than the final value, so that it counts down instead of up.
To see how the starting value affects the animation, look at the example below.
-{% capture html -%}
-
30000
-
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+30000 30000
+
## Decimal places
Set how many decimal numbers should be displayed using `decimalPlaces`. By default, the number of decimal places is set to 0.
-{% capture html -%}
-
3.123
-
3.123
-
3.123
-
3.123
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+3.123 3.123 3.123 3.123
+
## Easing
Disable easing using `"useEasing": false`. Easing is set to `true` by default, so that the animation speed changes over the course of its duration. Easing can be disabled to make the animation linear.
-{% capture html -%}
-
30000
-
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+30000 30000
+
## Use grouping
Disable grouping using `"useGrouping": false`. Grouping is set to `true` by default, so that the number is displayed with a separator.
-{% capture html -%}
-
30000
-
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+30000 30000
+
## Separator
You can change the default separator using `separator` and specifying the one you wish to use.
-{% capture html -%}
-
3000000
-
3000000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+3000000 3000000
+
## Decimal separator
You can change the default decimal separator using `decimal` and specifying the one you wish to use.
-{% capture html -%}
-
3.12
-
3.12
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+3.12 3.12
+
## Prefix
Set the countup prefix using `prefix` and specifying the prefix you want to add, for instance a currency symbol.
-{% capture html -%}
-
30000
-
30000
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+30000 30000
+
## Suffix
Set the countup suffix using `suffix` and specifying the suffix you want to add, for instance a percentage symbol.
-{% capture html -%}
-
300
-
300
-{%- endcapture %}
-{% include "docs/example.html" html=html vertical separated %}
+
+300 300
+
diff --git a/docs/pages/ui/components/datagrid.mdx b/docs/pages/ui/components/datagrid.mdx
new file mode 100644
index 000000000..4da456d69
--- /dev/null
+++ b/docs/pages/ui/components/datagrid.mdx
@@ -0,0 +1,18 @@
+---
+title: Data grid
+summary: Use the data grid component to display detailed information about your product. The data is displayed as a column of items consisting of a title and content.
+description: Detailed product information in grids.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+
+ Longer description
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+
+
+You can adjust the datagrid to your needs by setting the values of variables:
+
+| Variable | Description | Default |
+|----------|-------------|---------|
+| `--tblr-datagrid-item-width` | Width of the datagrid item | `15rem` |
+| `--tblr-datagrid-padding` | Gap between the datagrid items | `1.5rem` |
diff --git a/docs/pages/ui/components/divider.mdx b/docs/pages/ui/components/divider.mdx
new file mode 100644
index 000000000..16942c337
--- /dev/null
+++ b/docs/pages/ui/components/divider.mdx
@@ -0,0 +1,31 @@
+---
+title: Divider
+summary: Dividers help organize content and make the interface layout clear and uncluttered. Greater clarity adds up to better user experience and enhanced interaction with a website or app.
+description: Separate content with clear dividers.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Use dividers to visually separate content into parts. You can use a line only or add text that will be centered by default.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias, dolore dolores doloribus est ex.
See also
Dicta error hic illo iure necessitatibus nihil officiis omnis perferendis, praesentium repellendus rerum, saepe sed, sit!
+
+
+## Text position
+
+You can modify the position of the text which is to be included in a separator and make it left- or right-aligned. Otherwise, the text will remain centered.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias, dolore dolores doloribus est ex.
Start divider
Dicta error hic illo iure necessitatibus nihil officiis omnis perferendis, praesentium repellendus rerum, saepe sed, sit!
Centered divider
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias, dolore dolores doloribus est ex.
End divider
Dicta error hic illo iure necessitatibus nihil officiis omnis perferendis, praesentium repellendus rerum, saepe sed, sit!
+
+
+## Divider color
+
+Customize the color of dividers to make them go well with your design. See the [full list of available colors](/ui/base/colors) for more details.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias, dolore dolores doloribus est ex.
Green divider
Dicta error hic illo iure necessitatibus nihil officiis omnis perferendis, praesentium repellendus rerum, saepe sed, sit!
Red divider
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Alias, dolore dolores doloribus est ex.
Primary divider
Dicta error hic illo iure necessitatibus nihil officiis omnis perferendis, praesentium repellendus rerum, saepe sed, sit!
+
diff --git a/docs/pages/ui/components/dropdown.mdx b/docs/pages/ui/components/dropdown.mdx
new file mode 100644
index 000000000..8d9c19eee
--- /dev/null
+++ b/docs/pages/ui/components/dropdown.mdx
@@ -0,0 +1,96 @@
+---
+title: Dropdown
+summary: A dropdown is used to display a list of options or include more items in a menu without overwhelming users with too many buttons and long lists. It improves interaction with your website or software and keeps the interface clear.
+bootstrapLink: components/dropdowns
+description: Organize options with a dropdown menu.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default dropdown
+
+With small markup changes, you can turn any `.btn` into a dropdown toggle and use it to display more options for users to choose from. Start with the default dropdown and then use additional classes to make your dropdown more user-friendly.
+
+
+
+
+
+## Dropdown divider
+
+Use dropdown dividers to separate groups of dropdown items for greater clarity.
+
+
+
+
+
+## Active state
+
+Make a dropdown item look active, so that it highlights when a user hovers over a given option.
+
+
+
+
+
+## Disabled state
+
+Make a dropdown item look disabled to display options which are currently not available but can activate once certain conditions are met.
+
+
+
+
+
+## Dropdown header
+
+Add a dropdown header to group dropdown items into sections and name them accordingly.
+
+
+
+
+
+## Dropdown with icons
+
+Use icons in your dropdowns to add more visual content and make the options easy to identify for users.
+
+
+
+
+
+## Dropdown with arrow
+
+Add an arrow that points at the dropdown button.
+
+
+
+
+
+## Dropdown with badge
+
+Add a badge to your dropdown items to show additional information related to an item or distinguish it from other elements.
+
+
+
+
+
+## Dropdown with checkboxes
+
+Use dropdowns with checkboxes to allow users to select options from a predefined list. Dropdowns with checkboxes are particularly useful for filtering.
+
+
+
+
+
+## Dark dropdown
+
+Make your dropdown suit the dark mode of your website or software.
+
+
+
+
+
+## Dropdown with card content
+
+Use a dropdown with card content to make it easy for users to get more information on a given subject and avoid ovewhelming them with too much content at once.
+
+
+
+
diff --git a/docs/content/ui/components/dropzone.md b/docs/pages/ui/components/dropzone.mdx
similarity index 66%
rename from docs/content/ui/components/dropzone.md
rename to docs/pages/ui/components/dropzone.mdx
index 8060cf012..53bcd422d 100644
--- a/docs/content/ui/components/dropzone.md
+++ b/docs/pages/ui/components/dropzone.mdx
@@ -3,7 +3,9 @@ title: Dropzone
summary: Dropzone is a simple JavaScript library that helps you add file drag and drop functionality to your web forms. It is one of the most popular drag and drop libraries on the web and is used by millions of people.
description: Drag-and-drop file upload tool.
docs-libs: dropzone
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
## Basic usage
@@ -20,28 +22,16 @@ The basic implementation of Dropzone allows you to quickly enable drag-and-drop
To initialize the Dropzone form, you need to create a new instance of the Dropzone class and pass the form element as an argument. Here’s how you can do it:
```html
-
+ });`}
```
The Dropzone form will now be active and ready to accept file uploads. When a user drags and drops a file onto the form, the file will be uploaded to the server automatically.
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Add multiple files
@@ -53,40 +43,16 @@ To allow users to upload multiple files at once, you can enable the `multiple` a
By adding the `multiple` attribute to the input field, users can select multiple files from their local storage and upload them all at once. The Dropzone form will handle the file uploads automatically.
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Custom Dropzone
You can further enhance the user experience by customizing the Dropzone interface. For instance, you can modify the drop area with custom messages or styles to make the file upload process more engaging and user-friendly. Below is an example of a custom Dropzone configuration:
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
-By customizing the drop area, you can align the file upload process with your application’s branding or specific requirements.
\ No newline at end of file
+By customizing the drop area, you can align the file upload process with your application’s branding or specific requirements.
diff --git a/docs/pages/ui/components/empty.mdx b/docs/pages/ui/components/empty.mdx
new file mode 100644
index 000000000..3f4a7a592
--- /dev/null
+++ b/docs/pages/ui/components/empty.mdx
@@ -0,0 +1,34 @@
+---
+title: Empty State
+summary: An empty state or blank page is commonly used as a placeholder for first-use, empty data, or an error screen. Its goal is to engage users when there is no content to display, which makes its design important for the overall user experience of your website or app.
+description: Engage users in an empty or error screen.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Illustration from '@shared/components/ui/Illustration.astro';
+
+## Default markup
+
+Use the default empty state to engage users in the critical moments of their experience with your website or app. A good empty state screen should let users know what is happening and what they should do next as well as encourage them to take action.
+
+
+ No results found
Try adjusting your search or filter to find what you're looking for.
+
+
+## Empty state with illustration
+
+Make your empty state screen more attractive and engaging by adding an illustration. Thanks to a more personalized design, you will improve your brand image and make your website or app more user friendly.
+
+Do you need an illustration to enhance your web designs? We've got something for you! Check out our premium SVG [illustrations](https://tabler.io/illustrations).
+
+
+
Invoices are managed from here
Try adjusting your search or filter to find what you're looking for.
+
+
+## Empty state with header
+
+Instead of adding an icon or illustration you can simply give the text:
+
+
+ Oops… You just found an error page
Try adjusting your search or filter to find what you're looking for.
+
diff --git a/docs/pages/ui/components/icon.mdx b/docs/pages/ui/components/icon.mdx
new file mode 100644
index 000000000..c10ec8103
--- /dev/null
+++ b/docs/pages/ui/components/icon.mdx
@@ -0,0 +1,57 @@
+---
+title: Icon
+summary: Use an icon from over 5000 options created specifically for Tabler to make your dashboard more attractive. Each icon is available under the MIT license, so it can be used in both private and commercial projects.
+banner: icons
+description: Enhance a dashboard with a custom icon.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+If you need to add icons to your website, you can use the [Tabler Icons library](https://tabler.io/icons). It contains over 5000 icons that you can use in your projects. All icons are under the MIT license, so you can use them without any problem both in private and commercial projects.
+
+## Base icon
+
+To add an icon to your code copy the SVG code from the Tabler Icons website and paste it into your HTML file.
+
+```html
+
+```
+
+Results can be seen in the example below.
+
+
+
+
+
+## Filled icons
+
+To use filled icons, you need to copy the SVG code of the selected filled Icon from the [Tabler Icons website](https://tabler.io/icons) and paste it into your HTML file.
+
+
+
+
+
+## Icon colors
+
+To change the color of the icon, you need to add the `text-*` class to the parent element of the icon. See the [full list of available colors](/ui/base/colors) for more details. Color classes can be used with any HTML element.
+
+```html
+
+
+
+```
+
+Look at the example below to see how the color of the icon changes.
+
+
+
+
+
+## Icon animations
+
+To add an animation to the icon, you need to add the `icon-pulse`, `icon-tada`, or `icon-rotate` class to the SVG element.
+
+
+
+
diff --git a/docs/content/ui/components/index.md b/docs/pages/ui/components/index.mdx
similarity index 87%
rename from docs/content/ui/components/index.md
rename to docs/pages/ui/components/index.mdx
index 18c42b6a0..f67c6d555 100644
--- a/docs/content/ui/components/index.md
+++ b/docs/pages/ui/components/index.mdx
@@ -3,4 +3,5 @@ title: Components
order: 4
description: Various components to enhance UI.
summary: Tabler UI includes a variety of components to help you build web applications that are both functional and visually appealing. From buttons and cards to modals and navigation, these components provide a wide range of features to enhance your site.
----
\ No newline at end of file
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
diff --git a/docs/content/ui/components/inline-player.md b/docs/pages/ui/components/inline-player.mdx
similarity index 68%
rename from docs/content/ui/components/inline-player.md
rename to docs/pages/ui/components/inline-player.mdx
index f6143c328..d245537c1 100644
--- a/docs/content/ui/components/inline-player.md
+++ b/docs/pages/ui/components/inline-player.mdx
@@ -3,8 +3,9 @@ title: Inline player
docs-libs: plyr
summary: A simple, lightweight, accessible and customizable HTML5, YouTube and Vimeo media player that supports modern browsers.
description: Lightweight media player for websites.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
-
+import Example from '@shared/components/docs/Example.astro';
## Overview
@@ -15,38 +16,24 @@ The Inline Player is a versatile, modern media player designed for seamless inte
To use the Inline Player, you need to include the Plyr library in your project. You can install it via npm or include it directly from a CDN. The following example demonstrates how to include the Plyr library from a CDN:
```html
-
+
```
## YouTube video
Integrating the Inline Player into your website is straightforward. Below is a sample implementation for a YouTube video:
-{% capture html -%}
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Vimeo file
For the Vimeo video you just need to change the `data-plyr-provider`.
-{% capture html -%}
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## HTML5 video and audio
@@ -60,4 +47,4 @@ The Inline Player uses the primary color as the default color scheme. You can cu
--plyr-color-main: #ff0000; /* Change to your desired color */
```
-For more customization options, refer to the [Customizing the CSS](https://github.com/sampotts/plyr?tab=readme-ov-file#customizing-the-css) section in the Plyr documentation.
\ No newline at end of file
+For more customization options, refer to the [Customizing the CSS](https://github.com/sampotts/plyr?tab=readme-ov-file#customizing-the-css) section in the Plyr documentation.
diff --git a/docs/pages/ui/components/modal.mdx b/docs/pages/ui/components/modal.mdx
new file mode 100644
index 000000000..067b66948
--- /dev/null
+++ b/docs/pages/ui/components/modal.mdx
@@ -0,0 +1,52 @@
+---
+title: Modal
+summary: Use Bootstrap’s JavaScript modal plugin to add dialogs to your site for lightboxes, user notifications, or completely custom content.
+description: Dialogs for notifications and content.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+Modals are built with HTML, CSS, and JavaScript. They’re positioned over everything else in the document and remove scroll from the `` so that modal content scrolls instead.
+
+## Default markup
+
+To create a modal, you need to add a `.modal` element to the document. Inside the `.modal`, you need to add a `.modal-dialog` element, which contains a `.modal-content` element. The `.modal-content` element contains the modal’s header, body, and footer.
+
+```html
+
+```
+
+Look at the example below to see how the modal looks.
+
+
+ Launch demo modal Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci animi beatae delectus deleniti dolorem eveniet facere fuga iste nemo nesciunt nihil odio perspiciatis, quia quis reprehenderit sit tempora totam unde.
+
+
+## Prompt and alert
+
+You can use the modal to create a prompt or alert. Look at the example below to see how the prompt and alert look.
+
+
+
Are you sure? Do you really want to remove 84 files? What you've done cannot be undone.
+
+
+
+
Payment succeeded Your payment of $290 has been successfully submitted. Your invoice has been sent to support@tabler.io.
+
+
+## Modal with form
+
+You can use the modal to create a form. Look at the example below to see how the form looks.
+
+
+
+
diff --git a/docs/pages/ui/components/offcanvas.mdx b/docs/pages/ui/components/offcanvas.mdx
new file mode 100644
index 000000000..7476d2574
--- /dev/null
+++ b/docs/pages/ui/components/offcanvas.mdx
@@ -0,0 +1,29 @@
+---
+title: Offcanvas
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+Offcanvas is a sidebar component that can be toggled via JavaScript to appear from the left, right, top, or bottom edge of the viewport. Buttons or anchors are used as triggers that are attached to specific elements you toggle, and `data` attributes are used to invoke our JavaScript.
+
+## Basic usage
+
+To create an offcanvas, add the `.offcanvas` class to a container element. You can also add the `.offcanvas-start`, `.offcanvas-end`, `.offcanvas-top`, or `.offcanvas-bottom` class to specify the position of the offcanvas. The `.show` class is used to display the offcanvas.
+
+
+ Content for the offcanvas goes here. You can place just about any Tabler component or custom elements here.
+
+
+## Cookies banner
+
+The offcanvas component is used to display a cookies banner. It is a great way to inform users about the use of cookies on your website and to get their consent.
+
+
+ Do you like cookies? 🍪 We use cookies to ensure you get the best experience on our website.
Learn more Essential Cookies Only
Allow All Cookies
+
+
+
diff --git a/docs/content/ui/components/pagination.md b/docs/pages/ui/components/pagination.mdx
similarity index 61%
rename from docs/content/ui/components/pagination.md
rename to docs/pages/ui/components/pagination.mdx
index 18614304f..dbe50c92e 100644
--- a/docs/content/ui/components/pagination.md
+++ b/docs/pages/ui/components/pagination.mdx
@@ -1,59 +1,55 @@
---
title: Pagination
summary: Pagination is a user interface element that allows users to navigate through a set of data or content that is divided into multiple pages. It is commonly used in web applications, blogs, and e-commerce sites to display large amounts of information in a manageable way.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
+import Pagination from '@shared/components/ui/Pagination.astro';
## Basic Example
Use slightly customized pagination with previous and next icon links:
-{% capture html -%}
-{% include "ui/pagination.html" %}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical %}
+
+
+
## With First and Last links
When you have a lot of pages, you can use first and last links to quickly navigate to the beginning or end of the pagination.
-{% capture html -%}
-{% include "ui/pagination.html" first-last %}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical %}
+
+
+
## Offset
If the count of pages is too large, you can use offset to show only a few pages at a time.
-{% capture html -%}
-{% include "ui/pagination.html" offset=3 count=20 %}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical %}
+
+
+
## Button With Text
When you want to use pagination with text, you can use text buttons. This will give you a more traditional look and feel, which is great for applications where you want to keep the focus on the content rather than the navigation.
-{% capture html -%}
-{% include "ui/pagination.html" text %}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical %}
+
+
+
## Outline version
If you want to use an outline version of the pagination, you can use the `.pagination-outline` class. This will give you a more subtle look and feel, which is great for applications where you want to keep the focus on the content rather than the navigation.
-{% capture html -%}
-{% include "ui/pagination.html" class="pagination-outline" %}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical %}
+
+
+
## Circle version
If you want to use a circle version of the pagination, you can use the `.pagination-circle` class. This will give you a more subtle look and feel, which is great for applications where you want to keep the focus on the content rather than the navigation. This can also be combined with the `.pagination-outline` class for a more prominent look.
-{% capture html -%}
-{% include "ui/pagination.html" class="pagination-circle" %}
-{% include "ui/pagination.html" class="pagination-circle pagination-outline" -%}
-{%- endcapture %}
-{% include "docs/example.html" html=html centered vertical separated %}
\ No newline at end of file
+
+
+
diff --git a/docs/pages/ui/components/placeholder.mdx b/docs/pages/ui/components/placeholder.mdx
new file mode 100644
index 000000000..153215eba
--- /dev/null
+++ b/docs/pages/ui/components/placeholder.mdx
@@ -0,0 +1,89 @@
+---
+title: Placeholder
+summary: Placeholder is used to reserve space for content that will soon appear in a layout.
+description: Reserve space for upcoming content.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Placeholder line
+
+Placeholder lines can contain lines of text. Their length is different and depends on the `col-` class.
+
+
+
+
+
+However, it may be useful to specify the full width in order to fit the content more effectively.
+
+
+
+
+
+You can also move the lines to the right or center them:
+
+
+
+
+
+## Placeholder heading
+
+A placeholder can also contain an element that looks like a header:
+
+
+
+
+
+## Placeholder avatar
+
+You can use a placeholder that will look like an avatar. You can use the `avatar` component, and get the image in the right proportions.
+
+
+
+
+
+You can also use the `avatar` component with different sizes. Look at the example below to see how the avatar placeholder looks.
+
+
+
+
+
+## Placeholder image
+
+You can use a placeholder that will look like a picture. You can use the `ratio` component, and get the image in the right proportions.
+
+
+
+
+
+## Placeholder color
+
+By default, the placeholder uses `currentColor`. This can be overridden with a custom color or utility class. Full color classes are available for background colors.
+
+
+
+
+
+## Placeholder sizing
+
+The sizes of placeholders are based on the typographic style of the parent element. Customize them with sizing modifiers: `.placeholder-lg`, `.placeholder-sm`, or `.placeholder-xs`.
+
+
+
+
+
+## Animation
+
+Animate placeholders with `.placeholder-glow` or `.placeholder-wave` to better convey the perception of something being actively loaded.
+
+
+
+
+
+## Live examples
+
+See in the following examples how else you can use the placeholder component
+
+
+
+
diff --git a/docs/pages/ui/components/popover.mdx b/docs/pages/ui/components/popover.mdx
new file mode 100644
index 000000000..5a6a1c2fb
--- /dev/null
+++ b/docs/pages/ui/components/popover.mdx
@@ -0,0 +1,32 @@
+---
+title: Popover
+summary: A popover is used to provide additional information for elements where a simple tooltip is not sufficient.
+bootstrapLink: components/popovers
+description: Provide extra information with a popover.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+To create a default popover use:
+
+
+ Click to toggle popover
+
+
+## Four directions
+
+Four options are available: `top`, `right`, `bottom`, and `left` aligned. Directions are mirrored when using Bootstrap in RTL.
+
+
+ Popover on top Popover on right Popover on bottom Popover on left
+
+
+## Popover on hover
+
+Popover can be triggered in one or more of the following styles: `manual`, with a `click`, on `focus`, and on `hover`. This one reacts on hover. See more details on the Popover component page of [Bootstrap's documentation](https://getbootstrap.com/docs)
+
+
+ Hover to toggle popover
+
diff --git a/docs/pages/ui/components/progress-step.mdx b/docs/pages/ui/components/progress-step.mdx
new file mode 100644
index 000000000..d5a0a93f4
--- /dev/null
+++ b/docs/pages/ui/components/progress-step.mdx
@@ -0,0 +1,61 @@
+---
+title: Progress Steps
+summary: A progress step helps users track their place in a short process by breaking it into clear, simple steps. This makes flows like setup or onboarding easier to follow and finish.
+new: true
+description: Use progress steps to display compact onboarding, checkout, and setup progress.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import ProgressSteps from '@shared/components/ui/ProgressSteps.astro';
+
+## Default markup
+
+Use `.progress-steps` as the container and `.progress-steps-item` for each segment. These two classes are enough to create the base component structure.
+
+```html
+
+
+
+
+
+```
+
+The example below shows the default progress step structure.
+
+
+
+
+
+## Variants
+
+### Current and completed step
+
+Use color classes to mark completed steps. Set `aria-current="step"` on the current item.
+
+
+
+
+
+### Custom labels
+
+Use hidden labels so assistive technologies can announce meaningful step names.
+
+
+
+
+
+### Color state
+
+Use contextual background classes on completed and current items. This helps match state color to your flow semantics.
+
+
+
+
+
+### Width and layout utilities
+
+Use utility classes on `.progress-steps` to control width and placement in layouts.
+
+
+
+
diff --git a/docs/pages/ui/components/progress.mdx b/docs/pages/ui/components/progress.mdx
new file mode 100644
index 000000000..b9744853f
--- /dev/null
+++ b/docs/pages/ui/components/progress.mdx
@@ -0,0 +1,124 @@
+---
+title: Progress Bar
+summary: A progress bar is used to provide feedback on an action status and inform users about current progress. Although it is a small interface element, it is extremely helpful in managing user expectations and preventing abandonment of an initiated process.
+bootstrapLink: components/progress
+description: Track and display progress with a progress bar.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import ProgressBg from '@shared/components/ui/ProgressBg.astro';
+
+## Default markup
+
+To create a default progress bar, add a `.progress` class to a `
` element. Thanks to that, you will be able to notify users how long they have to wait for a process to complete.
+
+
+
+
+
+## Progress size
+
+Using Bootstrap’s typical naming structure, you can create a standard progress bar or scale it up or down to different sizes based on what’s needed.
+
+```html
+
...
+```
+
+Look at the example below to see how it works:
+
+
+
+
+
+## Progress with value
+
+If you want to display the numeric value inside the bar, place the percentage text directly in the `.progress-bar`.
+
+
+
+
+
+## Indeterminate progress
+
+You can create a progress bar which shows indeterminate progress by adding `.progress-bar-indeterminate` to the `.progress-bar` element.
+
+
+
+
+
+## Native progress element
+
+You can also use the native HTML5 `
` element. It is a great way to create a progress bar without the need for additional HTML elements. This is what it looks like:
+
+
+
+
+
+## Progress color
+
+You can change the color of the progress bar by adding a color class to the `.progress-bar` element. You can use the color classes like `.bg-primary`, `.bg-success`, etc. to change the color of the progress bar.
+
+See the [full list of available colors](/ui/base/colors) for more details.
+
+
+
+
+
+## Multiple progress bars
+
+You can stack multiple progress bars on top of each other to create a visually appealing design. This can be done by adding multiple `.progress` elements inside a `.progress-stacked` container.
+
+```html
+
+```
+
+This is how it looks:
+
+
+
+
+
+## Striped progress
+
+You can create a striped progress bar by adding the `.progress-bar-striped` class to the `.progress-bar` element.
+
+
+
+
+
+## Animated progress
+
+To animate stripes, add the `.progress-bar-animated` class to a striped progress bar.
+
+
+
+
+
+## Separated progress
+
+Use `.progress-separated` to make stacked segments easier to read when values are close to each other.
+
+
+
+
+
+## Progress background
+
+By using a progress bar component as a background element, designers can create a dynamic and engaging visual experience for users. For example, the progress bar could be used to represent the completion of a long-term goal or project, such as a fundraising campaign or construction project. As users interact with the
+page, the progress bar could gradually fill up, creating a sense of momentum and progress.
+
+Thanks to this you can create a nice looking statistics section:
+
+
+
+
+
+## Progress background colors
+
+You can combine progress background with contextual light colors to better separate categories.
+
+
+
+
diff --git a/docs/content/ui/components/range-slider.md b/docs/pages/ui/components/range-slider.mdx
similarity index 56%
rename from docs/content/ui/components/range-slider.md
rename to docs/pages/ui/components/range-slider.mdx
index 851520e47..3437fab4f 100644
--- a/docs/content/ui/components/range-slider.md
+++ b/docs/pages/ui/components/range-slider.mdx
@@ -3,29 +3,16 @@ title: Range slider
docs-libs: nouislider
description: Adjust values with a range slider.
summary: A range slider allows users to select a range of values by adjusting two handles along a track, providing an intuitive and space-efficient input method.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
To be able to use the range slider in your application you will need to install the noUiSlider dependency with `npm install nouislider`.
## Basic range slider
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
For more details on customizing a noUiSlider element, see the documentation on the [noUiSlider website](https://refreshless.com/nouislider/).
diff --git a/docs/pages/ui/components/ribbon.mdx b/docs/pages/ui/components/ribbon.mdx
new file mode 100644
index 000000000..3ae8d74ed
--- /dev/null
+++ b/docs/pages/ui/components/ribbon.mdx
@@ -0,0 +1,55 @@
+---
+title: Ribbon
+summary: A ribbon is a graphical element that attracts user attention to a given interface element and makes it stand out.
+description: Highlight an element with a graphical ribbon.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+## Default markup
+
+Use the `ribbon` class to add the default ribbon to any section of your interface.
+
+
+
+
+
+## Ribbon position
+
+You can change the position of a ribbon by adding one of the following classes to the element:
+
+- `ribbon-top` - moves it to the top
+- `ribbon-end` - moves it to the right
+- `ribbon-bottom` - moves it to the bottom
+- `ribbon-start` - moves it to the left
+
+Using multiple classes at once will give you more position options. For example, the following class: `.ribbon.ribbon-top.ribbon-left` will move the ribbon to the top left corner.
+
+
+
+
+
+## Ribbon color
+
+Customize the ribbon's background color. See the [full list of available colors](/ui/base/colors) for more details.
+
+
+
+
+
+## Ribbon text
+
+Add your own text to a ribbon to display any additional information and make it easy to spot for users.
+
+
+
+
+
+## Bookmark ribbon
+
+Use the `.ribbon-bookmark` class to create a bookmark ribbon. It is a special style of ribbon that is used to highlight important elements in your interface.
+
+
+
+
diff --git a/docs/pages/ui/components/segmented-control.mdx b/docs/pages/ui/components/segmented-control.mdx
new file mode 100644
index 000000000..fefe1e820
--- /dev/null
+++ b/docs/pages/ui/components/segmented-control.mdx
@@ -0,0 +1,72 @@
+---
+title: Segmented Control
+summary: A segmented control is a set of two or more segments, each of which functions as a mutually exclusive button. A segmented control is used to display a set of mutually exclusive options.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+To create a segmented control, use the `nav` element with the `nav-segmented` class. Inside the `nav` element, add `button` or `a` elements with the `nav-link` class. The `nav-link` class is used to style the buttons as links.
+
+
+ First Second Disabled
+
+
+## Full width
+
+To make the segmented control full width, add the `w-100` class to the `nav` element. It will take up the full width of its parent container.
+
+```html
+...
+```
+
+The results can be seen in the example below.
+
+
+ Daily Weekly Monthly Quarterly Yearly
+
+
+## With emojis
+
+You can also use emojis in the segmented control. To do this, add the emoji inside the `button` element.
+
+
+ 👦 👦🏿 👦🏾 👦🏽 👦🏼 👦🏻
+
+
+## With icons
+
+You can also use icons in the segmented control. To do this, add the icon inside the `button` element.
+
+
+
+ List Kanban Calendar Files
+
+
+## Vertical direction
+
+To create a vertical segmented control, add the `nav-segmented-vertical` class to the `nav` element.
+
+```html
+...
+```
+
+The results can be seen in the example below.
+
+
+ List Kanban Calendar Files
+
+
+## Sizes
+
+You can also change the size of the segmented control. To do this, add the `nav-sm` or `nv-lg` class to the `nav` element. The `nav-sm` class will make the segmented control smaller, while the `nav-lg` class will make it larger.
+
+```html
+...
+```
+
+The results can be seen in the examples below.
+
+
+ List Kanban Calendar Files List Kanban Calendar Files
+
diff --git a/docs/pages/ui/components/spinner.mdx b/docs/pages/ui/components/spinner.mdx
new file mode 100644
index 000000000..c732d24c7
--- /dev/null
+++ b/docs/pages/ui/components/spinner.mdx
@@ -0,0 +1,69 @@
+---
+title: Spinner
+summary: A spinner is used to show the loading state of a component or page. It provides feedback for an action that takes longer to complete.
+bootstrapLink: components/spinners/
+description: Indicate loading state with a spinner.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Use the default spinner to notify users that an action they have taken is in progress, helping them avoid confusion.
+
+
+
+
+
+
+## Colors
+
+Choose one of the available colors to customize the spinner and make it suit your design. Full list of available colors can be found in the [Colors](/ui/base/colors) section.
+
+
+
+
+
+## Size
+
+Choose the size of your spinner. You can use the default size or use the `spinner-border-sm` class to display a smaller spinner.
+
+
+
+
+
+## Growing spinner
+
+Use the growing spinner, if you are looking for a more original design than a border spinner. The spinner grows to show the loading state.
+
+
+
+
+
+Growing spinners also come in a variety of colors to choose from.
+
+
+
+
+
+## Button with spinner
+
+Use buttons with spinners to notify users that an action they have taken by clicking the button is in progress and prevent them from clicking multiple times or giving up.
+
+
+ Button Button Button Button Button
+
+
+## Animated dots
+
+Use animated dots to show the loading state of a component. They provide feedback for an action a user has taken, when it takes a bit longer to complete. To do it you need to use the `.animated-dots` class on a `span` element.
+
+
+Loading
+
+
+Use buttons with animated dots to notify users that an action they have taken by clicking the button is in progress and prevent them from clicking multiple times or giving up.
+
+
+ Loading Loading
+
diff --git a/docs/pages/ui/components/star-rating.mdx b/docs/pages/ui/components/star-rating.mdx
new file mode 100644
index 000000000..aa0ff2efe
--- /dev/null
+++ b/docs/pages/ui/components/star-rating.mdx
@@ -0,0 +1,64 @@
+---
+title: Star Rating
+summary: Use star rating to show score values with static stars or interactive star states.
+description: Build star rating UI with stars classes and data-star-rating state selectors.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+## Overview
+
+Use `.stars` as the container and `.star` for each icon.
+This creates an inline star row with spacing and base color.
+
+
+
+
+
+## Variants
+
+### Static value rows
+
+Use `.stars` for read-only values in lists and cards.
+Color only the active stars and keep the rest in default color.
+
+
+
+
+
+### Data-star-rating states
+
+The vendor styles also target `[data-star-rating]`.
+Use `.gl-active` and `.gl-star-full` to control active and inactive star color.
+
+
+
+
+
+### Custom rating colors
+
+Use CSS custom properties from vendor styles to change star colors.
+You can set active and inactive colors per instance.
+
+
+
+
+
+## Examples
+
+### Summary rating block
+
+Combine stars with text to show score and vote count.
+This pattern works for cards, reviews, and product lists.
+
+
+
+
+
+## Accessibility
+
+- Add a text label near stars, for example `4.0 out of 5`.
+- For read-only stars, keep the value visible in text.
+- For interactive ratings, ensure keyboard focus and clear selected state.
+- Do not rely on color alone; pair color with a numeric value.
diff --git a/docs/pages/ui/components/status.mdx b/docs/pages/ui/components/status.mdx
new file mode 100644
index 000000000..9b344a0c7
--- /dev/null
+++ b/docs/pages/ui/components/status.mdx
@@ -0,0 +1,68 @@
+---
+title: Status
+summary: A status dot is particularly useful when you want to make an interface element more noticeable in limited space.
+description: Highlight an interface element with a status dot.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Use the default status to notify users about the status of a component or page, helping them avoid confusion. Full list of available colors can be found in the [Colors](/ui/base/colors) section.
+
+
+Blue Azure Indigo Purple Pink Red Orange Yellow Lime Green Teal Cyan
+
+
+
+## Status with dot
+
+You can add a dot to the status to make it more noticeable. To do this, use the `.status-dot` element inside the `.status` element.
+
+
+ Blue Azure Indigo Purple Pink Red Orange Yellow Lime Green Teal Cyan
+
+
+### Animated dot
+
+You can also animate the dot to make it more noticeable. To do this, add a `.status-dot-animated` class to the `.status-dot` element.
+
+
+ Blue Azure Indigo Purple Pink Red Orange Yellow Lime Green Teal Cyan
+
+
+## Lite status
+
+Use the lite status to make the status less noticeable. To do this, add a `.status-lite` class to the `.status` element.
+
+
+ Blue Azure Indigo Purple Pink Red Orange Yellow Lime Green Teal Cyan
+
+
+## Status dots
+
+If you need only dot status, you can use the `.status-dot` class.
+
+
+
+
+
+The dots can also be animated. To do this, add the `.status-dot-animated` class.
+
+```html
+
+```
+
+The animated status dots can be used in the same way as the regular status dots.
+
+
+
+
+
+## Status indicator
+
+Use the status indicator to show the status of a component or page. The status indicator can be animated. To do this, also add the `.status-indicator-animated` class.
+
+
+
+
diff --git a/docs/pages/ui/components/step.mdx b/docs/pages/ui/components/step.mdx
new file mode 100644
index 000000000..f6bfe07f2
--- /dev/null
+++ b/docs/pages/ui/components/step.mdx
@@ -0,0 +1,88 @@
+---
+title: Step
+summary: A step is used to guide users through a complex process and make it easier to complete. Breaking a multi-step process into smaller parts and tracking progress along the way helps users finish it successfully.
+new: true
+description: Simplify a complex process with a step.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Steps provide a clear visual representation of a user’s progress through a multi-step process. By showing what has been completed and what remains, steps enhance usability and encourage task completion.
+
+To create a default progress tracker, use the `.steps` class and define each step as a `.step-item`. The active step clearly indicates the current position in the process.
+
+```html
+
+```
+
+The example below demonstrates a simple progress tracker with four steps, where the third step is active.
+
+
+
+
+
+## Tooltips
+
+Add tooltips if you want to provide users with additional information about the steps they are expected to complete. Tooltips are displayed when a user hovers over a given step and help clarify what might not be clear from the interface.
+
+To add a tooltip, use the `data-bs-toggle="tooltip"` attribute and specify the tooltip content with the `title` attribute.
+
+```html
+
+ Step 1
+
+```
+
+The example below demonstrates a progress tracker with tooltips for each step.
+
+
+
+
+
+## Color
+
+You can customize the default progress indicator by changing the color to one that better suits your design. See the [full list of available colors](/ui/base/colors) for more details.
+
+```html
+...
+```
+
+The example below demonstrates a progress tracker with two different color schemes.
+
+
+
+
+
+## Steps without title
+
+For designs with limited space, use progress indicators without titles and add tooltips to provide the necessary details.
+
+
+
+
+
+## Steps with numbers
+
+Use the `steps-counter` class to create a progress tracker with numbers instead of titles and change the color to customize it.
+
+```html
+...
+```
+
+The example below demonstrates a progress tracker with numbers and a different color scheme.
+
+
+
+
diff --git a/docs/pages/ui/components/switch-icon.mdx b/docs/pages/ui/components/switch-icon.mdx
new file mode 100644
index 000000000..25d97f5a1
--- /dev/null
+++ b/docs/pages/ui/components/switch-icon.mdx
@@ -0,0 +1,25 @@
+---
+title: Switch icon
+summary: The Switch Icon component is used to create a transition between two icons. You can use any icon, both line and filled version.
+banner: icons
+description: Transition between two icons smoothly.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+## Default markup
+
+The icon transition is triggered by adding an `.active` class to the `switch-icon` component.
+
+
+
+
+
+## Switch animations
+
+You can also add a fancy animation to add variety to your button. See demo below:
+
+
+
+
diff --git a/docs/pages/ui/components/tab.mdx b/docs/pages/ui/components/tab.mdx
new file mode 100644
index 000000000..559950b01
--- /dev/null
+++ b/docs/pages/ui/components/tab.mdx
@@ -0,0 +1,49 @@
+---
+title: Tab
+summary: A tab allows users to alternate between equally important views within the same context. By dividing content into meaningful sections, it improves organization and makes navigation easier.
+bootstrapLink: components/navs/
+description: Organize content with an interactive tab.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+## Default markup
+
+Use tabs to let users access different sections within one context quickly and with ease. In the default design, the current tab is highlighted, which makes the interface clear and user-friendly.
+
+
+ Home tab Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
Profile tab Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
+
+
+## Tabs with icons
+
+Add icons to your tab labels, if you want to use a visual element and make the tab content easier to identify.
+
+
+ Home tab Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
Profile tab Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
Settings tab Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus
+
+
+## Tabs only with icons
+
+Use tabs without label names to save space and make the tab content easy to recognize for international users.
+
+
+ Home tab Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
Profile tab Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
Settings tab Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus
+
+
+## Tabs with dropdown
+
+Make one or more of your tabs into a dropdown to add more options within one element.
+
+
+ Home tab Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
Profile tab Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
+
+
+## Full-width tabs
+
+Add the `.nav-fill` class to make the tabs take up the full space of the parent element.
+
+
+ Home tab Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
Profile tab Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
Activity tab Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus
+
diff --git a/docs/pages/ui/components/table.mdx b/docs/pages/ui/components/table.mdx
new file mode 100644
index 000000000..bc7efa3fd
--- /dev/null
+++ b/docs/pages/ui/components/table.mdx
@@ -0,0 +1,46 @@
+---
+title: Table
+summary: A table is a useful interface element that lets you visualize data and arrange it clearly. It allows users to browse a lot of information at once, and a good table design improves readability.
+bootstrapLink: content/tables/
+description: Visualize data clearly with a table.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Basic Table
+
+The basic table design has light padding and the presented data is separated with horizontal dividers. It helps provide users with all the necessary information, without overwhelming them with visuals.
+
+The `.table` class adds basic styling to a table:
+
+
+
+
+
+## Responsive tables
+
+Use the `.table-responsive` class across each breakpoint for horizontal scrolling tables. If you want to create responsive tables up to a specific breakpoint, use `.table-responsive{-sm|-md|-lg|-xl}`. From that breakpoint and up, the table will behave normally, rather than scroll horizontally.
+
+
+ # Heading 1 Heading 2 Heading 3 Heading 4 Heading 5 Heading 6 Heading 7 Heading 8 Heading 9 Heading 10 1 Cell Cell Cell Cell Cell Cell Cell Cell Cell Cell 2 Cell Cell Cell Cell Cell Cell Cell Cell Cell Cell
+
+
+## No wrap
+
+If you don't want the table cell content to wrap to another line, use the `table-nowrap` class.
+
+
+ Name Title Email Role Paweł Kuna UI Designer, Training paweluna@howstuffworks.com User Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi, commodi cupiditate debitis deserunt expedita hic incidunt iste modi molestiae nesciunt non nostrum perferendis perspiciatis placeat praesentium quaerat quo repellendus, voluptates. Edit
+
+
+## Table Variants
+
+
+ Class Heading Heading Default Cell Cell Primary Cell Cell Secondary Cell Cell Success Cell Cell Danger Cell Cell Warning Cell Cell Info Cell Cell Light Cell Cell Dark Cell Cell
+
+
+## Table with sticky header
+
+
+ Class Heading Heading Default Cell Cell Primary Cell Cell Secondary Cell Cell Success Cell Cell Danger Cell Cell Warning Cell Cell Info Cell Cell Light Cell Cell Dark Cell Cell Default Cell Cell Primary Cell Cell Secondary Cell Cell Success Cell Cell Danger Cell Cell Warning Cell Cell Info Cell Cell Light Cell Cell Dark Cell Cell
+
diff --git a/docs/pages/ui/components/tag.mdx b/docs/pages/ui/components/tag.mdx
new file mode 100644
index 000000000..84bf7ef63
--- /dev/null
+++ b/docs/pages/ui/components/tag.mdx
@@ -0,0 +1,69 @@
+---
+title: Tag
+summary: Use tags to show compact metadata values with optional media, badges, and remove actions.
+description: Build inline tag elements with the tag class API and related tag part classes.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Flag from '@shared/components/ui/Flag.astro';
+import Icon from '@shared/components/Icon.astro';
+import Payment from '@shared/components/ui/Payment.astro';
+
+## Overview
+
+Use `.tag` for one inline tag item. The base style supports text and an optional `.btn-close` remove action.
+
+
+ Label
+
+
+## Variants
+
+### With icon
+
+Use `.tag-icon` for a leading icon inside a tag. The icon uses compact size and secondary text color.
+
+
+ Featured
+
+
+### With avatar, flag, or payment
+
+Use `.tag-avatar`, `.tag-flag`, or `.tag-payment` to add media at the start of the tag. These classes keep spacing aligned with tag content.
+
+
+
+
+
+### With badge
+
+Use `.tag-badge` for small numeric or status counters. The badge variant keeps compact padding for tag layout.
+
+
+ Notifications 12
+
+
+### With checkbox
+
+Use `.tag-check` on a checkbox when the tag should be selectable. This variant is useful for filter sets and selectable labels.
+
+
+ Selected
+
+
+## Examples
+
+### Tags list
+
+Use `.tags-list` for groups of tags. It applies consistent spacing and wrapping between items.
+
+
+
+
+
+## Accessibility
+
+- Keep tag labels short and meaningful.
+- Add `aria-label` to every close button action.
+- Keep selectable tags keyboard reachable when using `.tag-check`.
+- Ensure icon or media tags still include readable text.
diff --git a/docs/content/ui/components/timeline.md b/docs/pages/ui/components/timeline.mdx
similarity index 76%
rename from docs/content/ui/components/timeline.md
rename to docs/pages/ui/components/timeline.mdx
index 15fa00954..c2adcecd6 100644
--- a/docs/content/ui/components/timeline.md
+++ b/docs/pages/ui/components/timeline.mdx
@@ -2,23 +2,23 @@
title: Timeline
summary: A timeline is a perfect way to visualize processes and projects, as it's easy to read and attractive for users. You can use it to give an overview of events, present an agenda or point out important points in time.
description: Visualize events and processes clearly.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
+import Timeline from '@shared/components/ui/Timeline.astro';
## Timeline
The available timeline design is composed of many components that will help you visualize a process or show an outline of events. Thanks to the possibility of adding icons, avatars and links and the way of presenting the elements of content, your timeline will be clear for users and will make your website or app more attractive.
-{% capture html -%}
-{% include "ui/timeline.html" %}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Simple timeline
Use a simplified version of the timeline, if it suits your design better. You can still make use of all the available timeline components.
-{% capture html -%}
-{% include "ui/timeline.html" simple %}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
-
+
+
+
diff --git a/docs/pages/ui/components/toast.mdx b/docs/pages/ui/components/toast.mdx
new file mode 100644
index 000000000..d8982d3f7
--- /dev/null
+++ b/docs/pages/ui/components/toast.mdx
@@ -0,0 +1,32 @@
+---
+title: Toast
+summary: A toast is a lightweight alert box that displays for a few seconds after a user action to communicate state or outcome. It is useful after actions like clicking a button or submitting a form, where feedback is needed without prompting another action.
+bootstrapLink: components/toasts/
+description: Display a lightweight alert notification with a toast.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Use the default toast message to inform users of the outcome of their action and provide additional information. It contains an `x` close button to make it possible for users to close the toast if they wish.
+
+
+ Hello, world! This is a toast message.
+
+
+## Translucent
+
+Toasts blend over the elements they appear over. If a browser supports the `backdrop-filter` CSS property, the elements under a toast will be blurred.
+
+
+ Hello, world! This is a toast message.
+
+
+## Stacking toasts
+
+Stack multiple toasts together by putting them within one `.toast-container`.
+
+
+ Hello, world! This is a toast message.
This is another toast message.
+
diff --git a/docs/pages/ui/components/tooltip.mdx b/docs/pages/ui/components/tooltip.mdx
new file mode 100644
index 000000000..ef55cdfed
--- /dev/null
+++ b/docs/pages/ui/components/tooltip.mdx
@@ -0,0 +1,24 @@
+---
+title: Tooltip
+summary: A tooltip is a text label that appears when a user hovers over an interface element. It explains unclear elements and guides users when they need help. When used properly, it can significantly enhance user experience and add value to your website or software.
+bootstrapLink: components/tooltips/
+description: Guide users with an informative tooltip.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Use the default markup to create tooltips that will help users understand particular elements of your interface. You can decide where the text label is to be displayed - at the top, bottom or on either side of the element.
+
+
+ Tooltip on top Tooltip on right Tooltip on bottom Tooltip on left
+
+
+## Tooltip with HTML
+
+If the default tooltip is not enough, you can add the option to use HTML code in the text to highlight particular bits of information and make the content more attractive.
+
+
+ Tooltip with HTML
+
diff --git a/docs/pages/ui/components/tracking.mdx b/docs/pages/ui/components/tracking.mdx
new file mode 100644
index 000000000..22630a56e
--- /dev/null
+++ b/docs/pages/ui/components/tracking.mdx
@@ -0,0 +1,21 @@
+---
+title: Tracking
+summary: Component for visualizing activity logs or other monitoring-related data. With its ability to show data in a visually appealing and easily understandable way, the tracking component is an essential tool for any organization that relies on data monitoring and analysis to optimize performance and user experience.
+description: Monitor data activity visually.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Basic example
+
+
+
+
+
+## Tracking inside a card
+
+You can add a tracking component inside the cards to give your reports a fresh look and visualize the status of your system in an attractive way. If you want to read how to add other elements to a card it is worth reading [documentation of card](/img/components/cards).
+
+
+
+
diff --git a/docs/content/ui/components/vector-map.md b/docs/pages/ui/components/vector-map.mdx
similarity index 70%
rename from docs/content/ui/components/vector-map.md
rename to docs/pages/ui/components/vector-map.mdx
index 34aeee9d1..1b75a021f 100644
--- a/docs/content/ui/components/vector-map.md
+++ b/docs/pages/ui/components/vector-map.mdx
@@ -3,8 +3,12 @@ title: Vector Map
docs-libs: [jsvectormap]
description: Interactive guide to creating a vector map with jsVectorMap.
summary: A vector map is a great way to display geographical data in an interactive and visually appealing way. Learn how to create a vector map with jsVectorMap.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import MapVector from '@shared/components/ui/MapVector.astro'
+
## Installation
To use vector maps in your project, you need to include the jsVectorMap library in your project. You can install it via npm or include it directly from a CDN. The following example demonstrates how to include the jsVectorMap library from a CDN:
@@ -18,37 +22,30 @@ To use vector maps in your project, you need to include the jsVectorMap library
Integrating the vector map into your website is straightforward. Below is a sample implementation for a world map:
-```html
-{% include "ui/map-vector.html" map-id="empty" %}
-{{ script }}
-```
+
+
+
## Sample demo
Look at the example below to see how the vector map works with a world map.
-{% capture html -%}
-{% include "ui/map-vector.html" map-id="world" %}
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Markers
You can add markers to the map to highlight specific locations. Below is a sample implementation for a world map with markers:
-{% capture html -%}
-{% include "ui/map-vector.html" map-id="world-markers" %}
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
-## Lines
+## Lines
You can also draw lines on the map to represent routes or connections between different locations. Below is a sample implementation for a world map with lines:
-{% capture html -%}
-{% include "ui/map-vector.html" map-id="world-lines" %}
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
\ No newline at end of file
+
+
+
diff --git a/docs/content/ui/components/wysiwyg.md b/docs/pages/ui/components/wysiwyg.mdx
similarity index 73%
rename from docs/content/ui/components/wysiwyg.md
rename to docs/pages/ui/components/wysiwyg.mdx
index 4cd85316a..7aed73edc 100644
--- a/docs/content/ui/components/wysiwyg.md
+++ b/docs/pages/ui/components/wysiwyg.mdx
@@ -3,16 +3,18 @@ title: WYSIWYG editor
docs-libs: [hugerte]
summary: The WYSIWYG editor that is flexible, customizable, and designed with the user in mind. HugeRTE can handle any challenge, from the most simple implementation through to the most complex use case.
description: Flexible WYSIWYG editor for content.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import Wysiwyg from '@shared/components/ui/Wysiwyg.astro'
+
[HugeRTE](https://hugerte.org/) documentation.
## Default text editor
Initialize HugeRTE on any element (or elements) on the web page by passing an object containing a selector value to `hugerte.init()`. The selector value can be any valid CSS selector.
-{% capture html -%}
-{% include "ui/wysiwyg.html" %}
-{{ script }}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
diff --git a/docs/content/ui/forms/form-color-check.md b/docs/pages/ui/forms/form-color-check.mdx
similarity index 73%
rename from docs/content/ui/forms/form-color-check.md
rename to docs/pages/ui/forms/form-color-check.mdx
index da48c6a03..6215febe0 100644
--- a/docs/content/ui/forms/form-color-check.md
+++ b/docs/pages/ui/forms/form-color-check.mdx
@@ -2,8 +2,12 @@
title: Color check
summary: The color check is a great way to make your form more user-friendly and engaging. You can use the color check to create a visually appealing form that will help users make decisions quickly and easily.
description: Enhance forms with color checks.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import InputColor from '@shared/components/parts/form/InputColor.astro'
+
Your input controls can come in a variety of colors, depending on your preferences. See the [full list of available colors](/ui/base/colors) for more details.
```html
@@ -15,23 +19,22 @@ Your input controls can come in a variety of colors, depending on your preferenc
There is also an example of a color input:
-{% capture html -%}
-{% include "parts/form/input-color.html" type="checkbox" %}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
If you need to select only one color, you can use the radio input type:
-{% capture html -%}
-{% include "parts/form/input-color.html" name="color-rounded" rounded=true %}
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Input color picker
Add an color picker to your form to let users customize it according to their preferences.
-{% capture html -%}
+
+
Color picker
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
-
+
diff --git a/docs/pages/ui/forms/form-elements.mdx b/docs/pages/ui/forms/form-elements.mdx
new file mode 100644
index 000000000..9d0d907c0
--- /dev/null
+++ b/docs/pages/ui/forms/form-elements.mdx
@@ -0,0 +1,166 @@
+---
+title: Form elements
+summary: Forms are one of the most important types of interaction with a website or app. Since their aim is to enable users to make a purchase, subscribe to a service or sign up to create an account, it's important to make sure they are easy to complete and help increase conversion rates. Use the available elements to create forms which are well-structured and user-friendly.
+bootstrapLink: components/forms/
+docs-libs: nouislider
+description: Design user-friendly and effective forms.
+order: 1
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Classic inputs
+
+Use classic, user-friendly inputs, label them appropriately and include input placeholders that will help users avoid confusion when completing a form. Add the `form-control` class to style your input controls.
+
+```html
+
+```
+
+All variants of the input control are available in the examples below:
+
+
+ Text
Password
Disabled
Readonly
+
+
+## Form control rounded
+
+Use the `form-control-rounded` class if you prefer form controls with rounded corners.
+
+
+
+
+
+## Form control flush
+
+You can remove borders from your form control by adding the `form-control-flush` class.
+
+
+Form control flush
+
+
+## Input with icon
+
+Add icons to your input controls to suggest users what they should enter or inform them of the current state of a form element.
+
+
+
+
+
+## Separated inputs
+
+Include an additional element in your input section, such as a button which can be used to submit the information entered in the input control.
+
+
+
+
+
+## Textarea and select
+
+Use a multi-line text input control to enable users to enter longer pieces of text. The control will automatically adjust to the length of the text entered.
+
+Add one of the available selects - either a dropdown or a multiple choice select - to let users choose from a predefined set of options.
+
+
+ Textarea
Select multiple
One Two Three
+
+
+## Input size
+
+Choose the size of an input control that will go well with your form design. Besides the default size, you can also use small and large input controls.
+
+
+ Input sizing
+
+
+## Datalists
+
+Use the `datalist` element to add an autocomplete feature to your input control. The list of available options will display once a user starts to type and will make it quicker to complete form sections.
+
+
+ Datalist example
+
+
+## Toggle switches
+
+Use toggle switches for the elements of your form which require choosing between two opposing states.
+
+
+
+
+
+## Radios
+
+Use radio buttons for the parts of your form which require users to choose one option from a set of two or more mutually exclusive options.
+
+
+
+
+
+
+
+
+
+## Checkboxes
+
+Use checkboxes if you want to allow users to select more than one option from a set of predefined options or to turn an option on or off.
+
+
+
+
+
+## Range input
+
+Add a range slider to make it possible for users to set a value or range, such as a price range or a time frame.
+
+
+
+
+
+## Input group
+
+Create a group of input controls and place add-ons on either side of an input.
+
+
+
+
+
+## Input with checkboxes or radios
+
+Add checkboxes or radio buttons on either side of your input control.
+
+
+
+
+
+## Input with prepended or appended text
+
+Add text to your input control, either before or after the text which is to be entered by a user.
+
+
+
+
+
+## Input with appended link
+
+Include a link in your input control to add a clickable element within the control.
+
+
+
+
+
+## Input with appended kbd
+
+Include a `` in your input control to add a shortcut hint to the control.
+
+
+
+
+
+## Input with appended icon links
+
+Add an icon link which you want to display at the end of your input control to visually represent actions which a user can take.
+
+
+ Input with appended icon links
+
diff --git a/docs/pages/ui/forms/form-fieldset.mdx b/docs/pages/ui/forms/form-fieldset.mdx
new file mode 100644
index 000000000..0ea258be8
--- /dev/null
+++ b/docs/pages/ui/forms/form-fieldset.mdx
@@ -0,0 +1,15 @@
+---
+title: Form fieldset
+summary: By grouping form elements together with the fieldset element, you can improve the organization and accessibility of your forms, making it easier for users to understand the purpose of each input and provide accurate information.
+description: Group form elements for clarity.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+Group parts of your form to make it well-structured and clearer for users, using the `fieldset` element.
+
+
+ Full name
Company
Email
Phone number
I agree to the Terms & Conditions
+
diff --git a/docs/pages/ui/forms/form-helpers.mdx b/docs/pages/ui/forms/form-helpers.mdx
new file mode 100644
index 000000000..0b64cd7b9
--- /dev/null
+++ b/docs/pages/ui/forms/form-helpers.mdx
@@ -0,0 +1,58 @@
+---
+title: Form helpers
+summary: Use form helpers to provide additional information about a form element. You can use input help, required field, form hint, and additional info inside the label.
+description: Provide additional guidance in forms.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Input help
+
+Use an input helper to display additional information about a form element. The text label will appear once a user hovers over the helper. To add an input helper, use the `.form-help` class.
+
+```html
+?
+```
+
+Look at the example below to see how the input help works:
+
+
+ ZIP Code ?
+
+
+## Required field
+
+Use the `.required` class to indicate that a field is required. It will add a red asterisk to the label.
+
+
+ Required
+
+
+## Form hint
+
+Use a form hint to provide users with additional information about a form element. The text will appear below the input field. To add a form hint, use the `.form-hint` class.
+
+```html
+We'll never share your email with anyone else.
+```
+
+Look at the example below to see how the form hint works:
+
+
+
+
+
+## Additional info inside label
+
+Use the `.form-label-description` class to add additional information to the label. The text will appear next to the label. You can use it to add for example a character counter.
+
+
+ Textarea 56/100
+
diff --git a/docs/pages/ui/forms/form-image-check.mdx b/docs/pages/ui/forms/form-image-check.mdx
new file mode 100644
index 000000000..1bbef75a7
--- /dev/null
+++ b/docs/pages/ui/forms/form-image-check.mdx
@@ -0,0 +1,42 @@
+---
+title: Image check
+summary: The image check is a great way to make your form more user-friendly and engaging. You can use the image check to create a visually appealing form that will help users make decisions quickly and easily.
+description: Add visual appeal to forms with images.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Default markup
+
+To build an image check, you need to use the `.form-imagecheck` class and the `.form-imagecheck-input` class for the input element. You can also use the `.form-imagecheck-figure` class to display the custom checkbox and the `.form-imagecheck-image` class to style the image itself.
+
+```html
+
+
+
+
+
+
+```
+
+Look at the examples below to see how the image check works:
+
+
+
+
+
+## Radio buttons
+
+If you want to use the image check as a radio button, you can change the input type to `radio`.
+
+
+
+
+
+## Avatars
+
+If you want to use the image check with avatars, you can use an [avatar component](/ui/components/avatar) instead of an image.
+
+
+
+
diff --git a/docs/content/ui/forms/form-input-mask.md b/docs/pages/ui/forms/form-input-mask.mdx
similarity index 66%
rename from docs/content/ui/forms/form-input-mask.md
rename to docs/pages/ui/forms/form-input-mask.mdx
index c1cacf18a..976de22cf 100644
--- a/docs/content/ui/forms/form-input-mask.md
+++ b/docs/pages/ui/forms/form-input-mask.mdx
@@ -3,18 +3,22 @@ title: Input mask
summary: An input mask is used to clarify the input format required in a given field and is helpful for users, removing confusion and reducing the number of validation errors.
description: Clarify input formats for users.
docs-libs: imask
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import TabsPackage from '@shared/components/docs/TabsPackage.astro'
+
## Installation
To be able to use the input mask in your application you will need to install the imask dependency. You can do this by running the following command:
-{% include "docs/tabs-package.html" name="imask" %}
+
And import or require:
```javascript
-import IMask from 'imask';
+import IMask from 'imask'
```
You can also use the CDN link to include the script in your project:
@@ -32,32 +36,16 @@ Use an input mask in the fields where users have to enter their phone number, to
To create an input mask, add the `data-mask` attribute to the input element:
```html
-
+
```
Look at the example below to see how the input mask works:
-{% capture html -%}
-Telephone mask
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+ Telephone mask
+
+
## More examples
-If you need more examples of input masks, you can find them in the [IMask documentation](https://imask.js.org/guide.html#masked-input).
\ No newline at end of file
+If you need more examples of input masks, you can find them in the [IMask documentation](https://imask.js.org/guide.html#masked-input).
diff --git a/docs/pages/ui/forms/form-selectboxes.mdx b/docs/pages/ui/forms/form-selectboxes.mdx
new file mode 100644
index 000000000..0e06f5164
--- /dev/null
+++ b/docs/pages/ui/forms/form-selectboxes.mdx
@@ -0,0 +1,88 @@
+---
+title: Form selectgroup
+summary: Use selectgroup to make your form more intuitive by providing users with a set of options to choose from. You can add simple selectgroup with a label, use icons only or icons with labels. Alternatively, you can use pill selectgroup if they go well with your design.
+description: Improve form UX with select groups.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Simple selectgroup
+
+To create a simple selectgroup, use the `.form-selectgroup` class. You should add a label to the selectgroup by using the `.form-selectgroup-item` class for the input element and the `.form-selectgroup-label` class for the label.
+
+```html
+
+
+ ...
+
+```
+
+Look at the example below to see how the simple selectgroup works:
+
+
+
+
+
+## Multiple choices
+
+You can also create a selectgroup with multiple choices. To do this, change the `type` attribute of the input element to `checkbox`.
+
+```html
+
+
+ ...
+
+```
+
+Look at the example below to see how the multiple choices selectgroup works:
+
+
+
+
+
+## Icon input
+
+To create an icon input, use the `.form-selectgroup` class. You should add a label to the selectgroup by using the `.form-selectgroup-item` class for the input element and the `.form-selectgroup-label` class for the label. You can use the `.icon` class to style the icon.
+
+```html
+
+
+
+ ...
+
+
+```
+
+We recommend you use Tabler Icons for the best experience. You can find 123 free icons in the [Tabler Icons](https://tabler-icons.io/) library. Just copy the SVG code and paste it into your project.
+
+
+
+
+
+You can also add text to the element. Look at the example below to see how it works:
+
+
+ Selectgroup with icons and text
+
+
+## Pill selectgroup
+
+If you want to use pill selectgroup, use the `.form-selectgroup-pills` class. All the other classes are the same as in the simple selectgroup.
+
+```html
+...
+```
+
+Look at the example below to see how the pill selectgroup works:
+
+
+
+
+
+## Advanced selectboxes
+
+Use more advanced selectboxes to display the range of available options. You can choose selectboxes with radio buttons if you want users to select only one option, or with checkboxes if they are allowed to choose multiple options.
+
+
+
+
diff --git a/docs/content/ui/forms/form-validation.md b/docs/pages/ui/forms/form-validation.mdx
similarity index 59%
rename from docs/content/ui/forms/form-validation.md
rename to docs/pages/ui/forms/form-validation.mdx
index e34d0de7a..331a4b50e 100644
--- a/docs/content/ui/forms/form-validation.md
+++ b/docs/pages/ui/forms/form-validation.mdx
@@ -2,7 +2,9 @@
title: Validation states
summary: To inform users whether the entered value is correct or not, use either of the validation states. Thanks to that, users will immediately know which form elements they need to correct and, if the state displays as invalid, why the value is incorrect.
description: Indicate valid or invalid inputs.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
## Validation states
@@ -10,35 +12,23 @@ To inform users whether the entered value is correct or not, use either of the v
To apply the validation state to the form control, use the `.is-valid` and `.is-invalid` classes.
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Validation feedback
To provide users with additional information about the validation state, you can use the `.valid-feedback` and `.invalid-feedback` classes.
-{% capture html -%}
-
-
City
-
-
Please provide a valid city.
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
You can also use the `.valid-feedback` to provide users with positive feedback.
-{% capture html -%}
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
## Subtle validation states
@@ -46,8 +36,6 @@ If you prefer a more subtle manner of informing users of the input control valid
To do this, use the `.is-valid-lite` and `.is-invalid-lite` classes.
-{% capture html -%}
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
diff --git a/docs/content/ui/forms/index.md b/docs/pages/ui/forms/index.mdx
similarity index 83%
rename from docs/content/ui/forms/index.md
rename to docs/pages/ui/forms/index.mdx
index 0b784c6f1..d43abc1d6 100644
--- a/docs/content/ui/forms/index.md
+++ b/docs/pages/ui/forms/index.mdx
@@ -3,4 +3,5 @@ title: Forms
order: 5
description: Build and manage web forms.
summary: The forms section provides a collection of components and tools for creating user-friendly and accessible forms, enhancing user interaction and improving data collection.
----
\ No newline at end of file
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
diff --git a/docs/content/ui/getting-started/browser-support.md b/docs/pages/ui/getting-started/browser-support.mdx
similarity index 92%
rename from docs/content/ui/getting-started/browser-support.md
rename to docs/pages/ui/getting-started/browser-support.mdx
index 5eea39e7b..a1deabd05 100644
--- a/docs/content/ui/getting-started/browser-support.md
+++ b/docs/pages/ui/getting-started/browser-support.mdx
@@ -2,7 +2,9 @@
title: Browser Support
description: Check browser compatibility for Tabler.
summary: Learn about the supported browsers and compatibility guidelines for using Tabler UI components to ensure a consistent experience across different devices and platforms.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
Tabler is fully optimized for all modern browsers, including the latest versions of Chrome, Firefox, Edge, Safari, and Opera. These browsers ensure a seamless and responsive experience, allowing users to enjoy Tabler's advanced UI components without compatibility issues.
@@ -32,4 +34,4 @@ Samsung Internet|Samsung 23+
## Unsupported Browsers
-Internet Explorer 11 and earlier versions are not supported. KaiOS 2.5 and earlier versions are also not supported.
\ No newline at end of file
+Internet Explorer 11 and earlier versions are not supported. KaiOS 2.5 and earlier versions are also not supported.
diff --git a/docs/content/ui/getting-started/customize.md b/docs/pages/ui/getting-started/customize.mdx
similarity index 94%
rename from docs/content/ui/getting-started/customize.md
rename to docs/pages/ui/getting-started/customize.mdx
index 337a777c1..da4716a6c 100644
--- a/docs/content/ui/getting-started/customize.md
+++ b/docs/pages/ui/getting-started/customize.mdx
@@ -1,8 +1,10 @@
---
title: Customize Tabler
summary: Tabler has been designed so that it can be adjusted to your needs and requirements as much as possible. You can customize your own fonts, colors, font sizes, etc in it.
-description: Adjust fonts, colors, and styles.
+description: Adjust fonts, colors, and styles.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
## Custom Google Font
diff --git a/docs/content/ui/getting-started/download.md b/docs/pages/ui/getting-started/download.mdx
similarity index 73%
rename from docs/content/ui/getting-started/download.md
rename to docs/pages/ui/getting-started/download.mdx
index 076620ac5..dd3033b20 100644
--- a/docs/content/ui/getting-started/download.md
+++ b/docs/pages/ui/getting-started/download.mdx
@@ -2,8 +2,11 @@
title: Download
summary: Download Tabler to get the compiled CSS and JavaScript, source code, or include it with your favorite package managers like npm, yarn and more.
description: Get Tabler CSS, JS, and source code.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import TabsPackage from '@shared/components/docs/TabsPackage.astro'
+
## CDN via jsDelivr
All files included in the `@tabler/core` npm package are available over a jsDelivr CDN. Use it to deliver cached versions of Tabler’s compiled CSS and JS to your project.
@@ -26,11 +29,9 @@ You can also include additional Tabler plugins:
Install Tabler in your Node.js powered apps with the npm package:
-{% include "docs/tabs-package.html" name="@tabler/core" %}
+
## 3rd-party Libraries
-Tabler uses other packages to enhance its functionality - for example, charts and input masks. These are not automatically installed to avoid huge
-dependency trees and need to be installed by using `npm install`. The full list of recommended libraries is available on the
-[3rd-party Libraries & Resources](/ui/getting-started/references) page.
-For the most recent list of supported packages, you can also check the [libs.json](https://github.com/tabler/tabler/blob/dev/core/libs.json) file.
\ No newline at end of file
+Tabler uses other packages to enhance its functionality - for example, charts and input masks. These are not automatically installed to avoid huge dependency trees and need to be installed by using `npm install`. The full list of recommended libraries is available on the
+[3rd-party Libraries & Resources](/ui/getting-started/references) page. For the most recent list of supported packages, you can also check the [libs.json](https://github.com/tabler/tabler/blob/dev/core/libs.json) file.
diff --git a/docs/content/ui/getting-started/faq.md b/docs/pages/ui/getting-started/faq.mdx
similarity index 84%
rename from docs/content/ui/getting-started/faq.md
rename to docs/pages/ui/getting-started/faq.mdx
index 0da64919a..4152d413b 100644
--- a/docs/content/ui/getting-started/faq.md
+++ b/docs/pages/ui/getting-started/faq.mdx
@@ -3,7 +3,9 @@ title: FAQ
summary: Answers to the most frequently asked questions.
description: Common questions and answers.
order: 12
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
## I found an issue, what can I do?
@@ -19,7 +21,7 @@ Yes, absolutely.
## Can I use Tabler in commercial projects?
-Of course! Tabler is under MIT license, so you can confidently use it in commercial projects. However, remember to include a note that your project uses Tabler. You can read about our license here: [License]({{ site.homepage }}/license).
+Of course! Tabler is under MIT license, so you can confidently use it in commercial projects. However, remember to include a note that your project uses Tabler. You can read about our license here: [License](https://tabler.io/license).
## Can Tabler be used with WordPress?
@@ -27,4 +29,4 @@ Tabler is an HTML template that can be used for any purpose. However, it is not
## How do I get notified of new Tabler versions?
-You may watch [the releases on GitHub](https://github.com/tabler/tabler/releases), follow us on [X](https://x.com/tabler_io) or stay up to date with our [changelog]({{ site.homepage }}/changelog).
+You may watch [the releases on GitHub](https://github.com/tabler/tabler/releases), follow us on [X](https://x.com/tabler_io) or stay up to date with our [changelog](https://tabler.io/changelog).
diff --git a/docs/content/ui/getting-started/how-to-contribute.md b/docs/pages/ui/getting-started/how-to-contribute.mdx
similarity index 94%
rename from docs/content/ui/getting-started/how-to-contribute.md
rename to docs/pages/ui/getting-started/how-to-contribute.mdx
index 7c7917be6..5ac369c21 100644
--- a/docs/content/ui/getting-started/how-to-contribute.md
+++ b/docs/pages/ui/getting-started/how-to-contribute.mdx
@@ -2,7 +2,9 @@
title: How to Contribute
summary: This guide explains how to contribute to Tabler, from setting up a development environment to making and testing changes. It covers essential steps like forking the repository, installing dependencies, and submitting a pull request to help improve Tabler's features and functionality.
description: Guide to contributing to Tabler and setting up for development.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
Contributions are always welcome and highly encouraged! Whether you're new to open source or a seasoned contributor, your input helps make Tabler better for everyone. If you're new to open source, we recommend reading a [how to contribute](https://opensource.guide/how-to-contribute/) guide to learn more about contributing.
@@ -82,4 +84,4 @@ Before submitting a pull request, ensure your changes are properly compiled and
## Submitting Your Contribution
-Once your changes are ready, create a pull request (PR) on GitHub. Make sure to include a clear and concise description of the changes and their purpose. Thank you for contributing to Tabler!
\ No newline at end of file
+Once your changes are ready, create a pull request (PR) on GitHub. Make sure to include a clear and concise description of the changes and their purpose. Thank you for contributing to Tabler!
diff --git a/docs/content/ui/getting-started/index.md b/docs/pages/ui/getting-started/index.mdx
similarity index 96%
rename from docs/content/ui/getting-started/index.md
rename to docs/pages/ui/getting-started/index.mdx
index 71f495c09..233ef670f 100644
--- a/docs/content/ui/getting-started/index.md
+++ b/docs/pages/ui/getting-started/index.mdx
@@ -3,6 +3,7 @@ title: Introduction
summary: Free and open-source HTML Dashboard UI Kit built on Bootstrap
order: 1
description: Overview of Tabler UI Kit.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
## What is Tabler?
diff --git a/docs/content/ui/getting-started/installation.md b/docs/pages/ui/getting-started/installation.mdx
similarity index 78%
rename from docs/content/ui/getting-started/installation.md
rename to docs/pages/ui/getting-started/installation.mdx
index 7fbd045ce..69515f054 100644
--- a/docs/content/ui/getting-started/installation.md
+++ b/docs/pages/ui/getting-started/installation.mdx
@@ -3,7 +3,9 @@ title: Installation
order: 1
summary: Learn how to set up Tabler in your project by creating a basic HTML file, adding Tabler’s CSS and JavaScript, and exploring its powerful components to build responsive and visually stunning web applications.
description: "Set up Tabler: HTML, CSS, JS, and build stunning UIs."
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
This guide will take you through the essential steps to set up Tabler in your project, from creating a basic HTML file to incorporating Tabler’s styles and scripts. Let’s dive in!
@@ -11,7 +13,7 @@ This guide will take you through the essential steps to set up Tabler in your pr
### Create a Basic HTML File
-Begin by creating a new `index.html` file in the root of your project. This file will serve as the foundation for your Tabler-based interface. Include the basic HTML structure and a ` ` tag for proper responsiveness:
+Begin by creating a new `index.html` file in the root of your project. This file will serve as the foundation for your Tabler-based interface. Include the basic HTML structure and a ` ` tag for proper responsiveness:
```html
@@ -32,8 +34,8 @@ Begin by creating a new `index.html` file in the root of your project. This file
Enhance your page by including Tabler's CSS and JavaScript files. Use the following links to load the core Tabler styles and scripts from the CDN:
```html
-
-
+
+
```
Update your HTML file to include these resources:
@@ -45,11 +47,11 @@ Update your HTML file to include these resources:
Tabler Demo
-
+
Hello, Tabler!
-
+
```
@@ -64,4 +66,4 @@ Save the file and open it in your browser. You should see your first Tabler-powe
-With these simple steps, you're ready to explore Tabler's features and build stunning web interfaces. For inspiration and guidance, you can view live demos at [preview.tabler.io](https://preview.tabler.io) and consult our [official documentation](https://docs.tabler.io) for detailed instructions and examples.
\ No newline at end of file
+With these simple steps, you're ready to explore Tabler's features and build stunning web interfaces. For inspiration and guidance, you can view live demos at [preview.tabler.io](https://preview.tabler.io) and consult our [official documentation](https://docs.tabler.io) for detailed instructions and examples.
diff --git a/docs/content/ui/getting-started/license.md b/docs/pages/ui/getting-started/license.mdx
similarity index 92%
rename from docs/content/ui/getting-started/license.md
rename to docs/pages/ui/getting-started/license.mdx
index 0c552b1c1..dc7046df9 100644
--- a/docs/content/ui/getting-started/license.md
+++ b/docs/pages/ui/getting-started/license.mdx
@@ -2,7 +2,9 @@
title: Tabler License
summary: The MIT license grants you the flexibility to use Tabler in commercial or personal projects, modify its code, and distribute it freely. Ensure you include the required license and copyright notices to stay compliant with the terms.
description: "Tabler's MIT license: freedom to use, modify, and share."
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
Tabler is an open-source project licensed under the **MIT license**, giving you extensive freedom to use, modify, and distribute the software. This license ensures that you can adapt Tabler to your needs while maintaining the required attributions. While attribution is not required, it is greatly appreciated to acknowledge the hard work of the developers.
@@ -27,4 +29,4 @@ When using Tabler, you must:
For more details, please refer to the full [Tabler License](https://github.com/tabler/tabler/blob/main/LICENSE).
-By adhering to these requirements, you help ensure the continued openness and usability of Tabler for everyone. Thank you for supporting open-source software!
\ No newline at end of file
+By adhering to these requirements, you help ensure the continued openness and usability of Tabler for everyone. Thank you for supporting open-source software!
diff --git a/docs/pages/ui/getting-started/references.mdx b/docs/pages/ui/getting-started/references.mdx
new file mode 100644
index 000000000..ccde83aa0
--- /dev/null
+++ b/docs/pages/ui/getting-started/references.mdx
@@ -0,0 +1,10 @@
+---
+title: 3rd-party Libraries & Resources
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+
+import OpenSourceResources from '@shared/components/docs/OpenSourceResources.astro'
+
+Tabler uses the following open source resources:
+
+
diff --git a/docs/content/ui/index.md b/docs/pages/ui/index.mdx
similarity index 89%
rename from docs/content/ui/index.md
rename to docs/pages/ui/index.mdx
index d971980b7..6a36e2cb0 100644
--- a/docs/content/ui/index.md
+++ b/docs/pages/ui/index.mdx
@@ -3,9 +3,9 @@ title: Tabler UI
order: 1
description: Free and open source web application UI kit based on Bootstrap
summary: Tabler UI is a carefully crafted collection of modern and responsive user interface components. Built on top of Bootstrap, it helps developers create stunning and functional web applications quickly and efficiently.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
# Tabler UI

-
diff --git a/docs/content/ui/layout/index.md b/docs/pages/ui/layout/index.mdx
similarity index 83%
rename from docs/content/ui/layout/index.md
rename to docs/pages/ui/layout/index.mdx
index 7166d579c..deabd7c6c 100644
--- a/docs/content/ui/layout/index.md
+++ b/docs/pages/ui/layout/index.mdx
@@ -3,4 +3,5 @@ title: Layout
order: 3
description: Structure your UI effectively.
summary: The layout section covers essential tools and techniques for structuring content and organizing UI elements, helping you build visually appealing and functional designs.
----
\ No newline at end of file
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
diff --git a/docs/pages/ui/layout/navbars.mdx b/docs/pages/ui/layout/navbars.mdx
new file mode 100644
index 000000000..5bbd6e4b0
--- /dev/null
+++ b/docs/pages/ui/layout/navbars.mdx
@@ -0,0 +1,91 @@
+---
+title: Navbars
+summary: A navbar serves as a central navigation tool, offering users quick and easy access to key sections of a website or application, improving usability and enhancing the overall user experience.
+description: Create and customize responsive navigation bars with ease.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+
+import Example from '@shared/components/docs/Example.astro'
+import NavbarLogo from '@shared/components/NavbarLogo.astro'
+import Icon from '@shared/components/Icon.astro'
+
+The navbar is a core component of any website or application, serving as the primary navigation tool. It provides users with quick access to key sections, enhancing usability and improving the overall user experience. Positioned typically at the top of the page, the navbar can contain links, buttons, branding elements,
+and even interactive components like dropdown menus or search bars.
+
+With Tabler's utility classes, creating and customizing a responsive navbar is straightforward. Whether you’re building a simple site or a complex dashboard, Tabler’s navbar utilities offer the flexibility to design navigation that aligns perfectly with your project’s requirements.
+
+## Sample navbar
+
+To create a navbar, use the `.navbar` class. The navbar is a horizontal bar that contains links to different sections of a website. It is typically placed at the top of the page and is used to provide navigation to the rest of the site.
+
+```html
+
+```
+
+The navbar can contain links, buttons, and other elements. You can customize the appearance of the navbar by adding classes to the elements inside it.
+
+
+
+
diff --git a/docs/pages/ui/layout/navs-tabs.mdx b/docs/pages/ui/layout/navs-tabs.mdx
new file mode 100644
index 000000000..35f6eddc1
--- /dev/null
+++ b/docs/pages/ui/layout/navs-tabs.mdx
@@ -0,0 +1,97 @@
+---
+title: Navs and tabs
+summary: This guide covers the basics of creating different types of navigation bars and tabs, including horizontal, vertical, pill-shaped, and underline-styled navs.
+description: "Essential guide to nav styles: tabs, pills, dropdowns, and more."
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+Navigation bars are essential components of modern web applications, providing users with intuitive ways to navigate between different sections and content. This guide explores various types of navigation bars and tabs that can be easily implemented using predefined classes in HTML and CSS. Each type serves specific use cases, from horizontal and vertical layouts to tabbed interfaces and dropdown menus. By utilizing these examples, developers can enhance the usability and aesthetics of their web projects.
+
+## Horizontal nav
+
+If you want to create a horizontal navigation bar, you can use the `.nav` class. The `.nav-item` class is used to style each item within the navigation bar, and `.nav-link` is applied to the links. The `.active` class highlights the current active link, while the `.disabled` class styles non-clickable links.
+
+Look at the example below to see how the horizontal navigation bar is displayed.
+
+
+
+
+
+## Vertical nav
+
+To create a vertical navigation bar, add the `.flex-column` class to the `.nav` element. This arranges the navigation items in a column instead of a row, making it suitable for sidebars or vertical menus.
+
+```html
+
+```
+
+There is an example below to see how the vertical navigation bar is displayed.
+
+
+
+
+
+## Tabs
+
+To create a tabbed navigation interface, use the `.nav-tabs` class. This is ideal for displaying different content sections within a single interface, where each tab represents a section.
+
+```html
+
+```
+
+The example below shows how the tabbed navigation interface is displayed.
+
+
+
+
+
+## Pills
+
+For a pill-shaped navigation style, use the `.nav-pills` class. This is a great choice for a sleek, modern look, especially in the interactive UI components.
+
+
+
+
+
+## Underline
+
+To create a navigation bar with an underline effect for active links, use the `.nav-underline` class. This provides a clean and minimalistic style.
+
+
+
+
+
+## Tabs with Dropdown
+
+You can enhance tabs by adding dropdown menus using the `.dropdown` class inside a `.nav-tabs` structure. This allows for additional options under a single tab, improving the navigation experience.
+
+```html
+
+```
+
+Example below shows how tabs with dropdown menus are displayed.
+
+
+
+
diff --git a/docs/pages/ui/layout/page-headers.mdx b/docs/pages/ui/layout/page-headers.mdx
new file mode 100644
index 000000000..ea9513a1d
--- /dev/null
+++ b/docs/pages/ui/layout/page-headers.mdx
@@ -0,0 +1,44 @@
+---
+title: Page headers
+summary: Page heading examples for Tabler
+description: Examples of Tabler page headers.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+import Icon from '@shared/components/Icon.astro';
+
+## Simple header
+
+
+
+
+
+## With meta, avatar and actions
+
+
+
+
+
+## With meta, search and actions
+
+
+
+
+
+## Bordered header
+
+A page header with a border to separate content is an effective way to organize and present information in a clear and visually appealing way.
+
+
+
+
+
+## Header with breadcrumb and actions
+
+A page header with breadcrumb and actions is a common design element found in many websites and applications. The header typically appears at the top of the page and includes a breadcrumb trail, which shows the user the path they have taken to reach the current page. The breadcrumb can be clickable, allowing the user to navigate back to previous pages.
+
+In addition to the breadcrumb, the header often includes actions or buttons that allow the user to perform common tasks related to the current page. These actions may include things like adding a new item, editing existing content, or deleting items.
+
+
+
+
diff --git a/docs/content/ui/layout/page-layouts.md b/docs/pages/ui/layout/page-layouts.mdx
similarity index 94%
rename from docs/content/ui/layout/page-layouts.md
rename to docs/pages/ui/layout/page-layouts.mdx
index d4d0fdaff..28158c12a 100644
--- a/docs/content/ui/layout/page-layouts.md
+++ b/docs/pages/ui/layout/page-layouts.mdx
@@ -2,17 +2,19 @@
title: Page layouts
summary: Learn how to build a sample version of the dashboard
description: Learn to design dashboard layouts.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
-{% callout %}
- Before you start with this section, make sure you have followed the [installation guideline](/ui/getting-started/installation).
-{% endcallout %}
+import Example from '@shared/components/docs/Example.astro'
+
+Before you start with this section, make sure you have followed the [installation guideline](/ui/getting-started/installation).
## Sample layout
To create a sample version of the dashboard, you can use the following code snippet. This code snippet will help you to create a dashboard layout with a header.
-{% capture html -%}
+
+
@@ -72,16 +74,15 @@ To create a sample version of the dashboard, you can use the following code snip
-{%- endcapture %}
-{% include "docs/example.html" html=html raw %}
+
## Sidebar layout
To create a sidebar layout, you can use the following code snippet. This code snippet will help you to create a sidebar layout with a header.
-{% capture html -%}
+
+
-
@@ -211,5 +212,4 @@ To create a sidebar layout, you can use the following code snippet. This code sn
-{%- endcapture %}
-{% include "docs/example.html" html=html raw %}
\ No newline at end of file
+
diff --git a/docs/content/ui/plugins/flags.md b/docs/pages/ui/plugins/flags.mdx
similarity index 63%
rename from docs/content/ui/plugins/flags.md
rename to docs/pages/ui/plugins/flags.mdx
index 66cb3e527..2424939f6 100644
--- a/docs/content/ui/plugins/flags.md
+++ b/docs/pages/ui/plugins/flags.mdx
@@ -4,8 +4,12 @@ summary: Thanks to the Tabler flags plugin, you can create flags to visually rep
plugin: flags
docs-libs: tabler-flags
description: Visual representation of countries/languages.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import Flags from '@shared/components/docs/Flags.astro'
+
## Installation
This part of Tabler is distributed as a plugin. To enable it you should include `tabler-flags.css` or `tabler-flags.min.css` file in your page.
@@ -20,39 +24,34 @@ You can also include the plugin via CDN:
To create a flag, add the `flag` class to a component and choose the country whose flag you want to use.
-{% capture html -%}
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
-
+
+
+
## Country flags
To use the flag of a particular country, add the `flag-country-(country name)` class. For example, to create a flag of Andorra, you should use the following class: `.flag-country-ad`. The full list of countries can be found at the end of this page.
-{% capture html -%}
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
+
+
## Flag sizes
Using Bootstrap’s typical naming structure, you can create a standard flag, or scale it up or down to different sizes based on what’s needed.
-{% capture html -%}
-
-
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+
+
+
+
+
+
## Flags list
The full list of countries can be found below.
-{% include "docs/flags.html" %}
-
+
diff --git a/docs/content/ui/plugins/index.md b/docs/pages/ui/plugins/index.mdx
similarity index 83%
rename from docs/content/ui/plugins/index.md
rename to docs/pages/ui/plugins/index.mdx
index 1bd605ded..84404efb2 100644
--- a/docs/content/ui/plugins/index.md
+++ b/docs/pages/ui/plugins/index.mdx
@@ -3,4 +3,5 @@ title: Plugins
order: 7
description: Enhance Tabler UI with useful plugins.
summary: Tabler plugins extend the functionality of the framework, providing additional tools and features to enhance your projects and streamline the development process.
----
\ No newline at end of file
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
diff --git a/docs/content/ui/plugins/payments.md b/docs/pages/ui/plugins/payments.mdx
similarity index 61%
rename from docs/content/ui/plugins/payments.md
rename to docs/pages/ui/plugins/payments.mdx
index 606198dc5..33a802a68 100644
--- a/docs/content/ui/plugins/payments.md
+++ b/docs/pages/ui/plugins/payments.mdx
@@ -3,8 +3,12 @@ title: Payments
summary: The Tabler payments plug-in will let you use a set of payment provider icons to facilitate the payment process and make it more user-friendly.
plugin: payments
description: User-friendly payment provider icons.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import Payments from '@shared/components/docs/Payments.astro'
+
## Installation
This part of Tabler is distributed as a plugin. To enable it you should include `tabler-payments.css` or `tabler-payments.min.css` file in your page.
@@ -19,28 +23,26 @@ You can also include the plugin via CDN:
To create a payment provider icon, add the `payment` class to a component and specify the payment provider with the `payment-provider-*` class. The full list of payment providers can be found at the end of this page.
-{% capture html -%}
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html centered %}
+
+
+
+
+
## Payment sizes
Using Bootstrap’s typical naming structure, you can create a standard payment, or scale it up or down to different sizes based on what’s needed.
-{% capture html -%}
-
-
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html centered %}
+
+
+
+
+
+
+
## List of available payment providers
Select an icon from the list of payment providers. Each icon comes in two color variants - light and dark, so you can choose the one that goes well with your design.
-{% include "docs/payments.html" %}
+
diff --git a/docs/content/ui/plugins/social-icons.md b/docs/pages/ui/plugins/social-icons.mdx
similarity index 83%
rename from docs/content/ui/plugins/social-icons.md
rename to docs/pages/ui/plugins/social-icons.mdx
index b71931eda..580f71708 100644
--- a/docs/content/ui/plugins/social-icons.md
+++ b/docs/pages/ui/plugins/social-icons.mdx
@@ -4,8 +4,12 @@ summary: Social icons are a great way to make your website more engaging and use
plugin: socials
docs-libs: tabler-socials
description: Connect users to your social profiles.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro'
+import Socials from '@shared/components/docs/Socials.astro'
+
## Installation
This part of Tabler is distributed as a plugin. To enable it you should include `tabler-socials.css` or `tabler-socials.min.css` file in your page.
@@ -20,15 +24,15 @@ You can also include the plugin via CDN:
To create a social icon, add the `social` class to a component and provide the class `social-app-*` with the social app whose icon you want to use.
-{% capture html -%}
+
+
-{%- endcapture %}
-{% include "docs/example.html" html=html centered %}
+
## Social apps list
Here is a list of all available social apps:
-{% include "docs/socials.html" %}
\ No newline at end of file
+
diff --git a/docs/content/ui/utilities/background-patterns.md b/docs/pages/ui/utilities/background-patterns.mdx
similarity index 64%
rename from docs/content/ui/utilities/background-patterns.md
rename to docs/pages/ui/utilities/background-patterns.mdx
index 3356977c4..d19bd2be6 100644
--- a/docs/content/ui/utilities/background-patterns.md
+++ b/docs/pages/ui/utilities/background-patterns.mdx
@@ -4,9 +4,14 @@ summary: Use background pattern utilities to add subtle textures to elements. Co
description: Add decorative background patterns with utility classes.
added-in: '1.4.0'
source-css: 'ui/_patterns.scss'
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
-{% assign patterns = "diagonal,diagonal-2,dots,rectangles,lines,lines-vertical,grid,grid-diagonal,blueprint,cross-dots,circles,diagonal-stripes,diagonal-stripes-2,zigzag,vertical-stripes,horizontal-stripes" | split: "," %}
+import Example from '@shared/components/docs/Example.astro'
+import Illustration from '@shared/components/ui/Illustration.astro'
+import site from '@data/site.json'
+export const patterns = ['diagonal', 'diagonal-2', 'dots', 'rectangles', 'lines', 'lines-vertical', 'grid', 'grid-diagonal', 'blueprint', 'cross-dots', 'circles', 'diagonal-stripes', 'diagonal-stripes-2', 'zigzag', 'vertical-stripes', 'horizontal-stripes']
+export const colors = Object.entries(site.colors)
## Overview
@@ -22,66 +27,65 @@ Background pattern utilities let you apply decorative, repeatable textures to el
Use one of the available pattern classes to define the shape and direction of the texture:
-{% for pattern in patterns %}
-- `.bg-pattern-{{ pattern }}`
-{% endfor %}
+
+ {patterns.map((pattern) => (
+
+ .bg-pattern-{pattern}
+
+ ))}
+
Here are the available pattern types:
-{% capture html -%}
+
- {% for pattern in patterns %}
-
-
-
.bg-pattern-{{ pattern }}
-
- {% endfor %}
+ {patterns.map((pattern, i) => {
+ return (
+
+
+
.bg-pattern-{ pattern }
+
+ )
+ })}
-{%- endcapture %}
-{% capture code %}
-{% for pattern in patterns -%}
-
-{% endfor %}
-{% endcapture %}
-{% include "docs/example.html" html=html code=code bg="surface-primary" %}
+
+
+ {patterns.map((pattern) => (
+
+ ))}
+
## Pattern colors
Combine any pattern with color modifiers using `.bg-pattern-{color}`. See the [full list of available colors](/ui/base/colors) for all color names.
-{% capture html -%}
+
- {% for color in site.colors %}
-
-
-
.bg-pattern-{{ color[0] }}
-
- {% endfor %}
+
+{colors.map((color) => (
))}
+
-{%- endcapture %}
-{% capture code %}
-{% for color in site.colors -%}
-
-{% endfor %}
-{% endcapture %}
-{% include "docs/example.html" html=html code=code bg="surface-primary" %}
+
+
+ {colors.map((color) => (
+
+ ))}
+
## Transparent pattern utility
-Use `.bg-pattern-transparent` when you need a checkerboard-style transparent background.
-This utility comes from the generic background utilities and can be combined with spacing and border classes.
+Use `.bg-pattern-transparent` when you need a checkerboard-style transparent background. This utility comes from the generic background utilities and can be combined with spacing and border classes.
-{% capture html -%}
-{% include "ui/illustration.html" image="boy-with-key.svg" class="d-block mx-auto mw-100" height=200 %}
-{%- endcapture %}
-{% capture code %}
-
-
-
-{% endcapture %}
-{% include "docs/example.html" html=html code=code bg="pattern-rectangles" column %}
+
+
+
+
+
+
+
+
## Pattern sizes
@@ -94,7 +98,7 @@ Use size utilities to control pattern density:
Look at the following examples to see how the pattern sizes work:
-{% capture html -%}
+
@@ -114,14 +118,13 @@ Look at the following examples to see how the pattern sizes work:
.bg-pattern-xl
-{%- endcapture %}
-{% capture code %}
+
+
-{% endcapture %}
-{% include "docs/example.html" html=html code=code bg="surface-primary" %}
+
## Examples
@@ -131,22 +134,21 @@ Look at the following examples to see how background patterns can be used in rea
Card with a background pattern in the body can be used to add a decorative touch to the card. This is useful when you want to add a subtle pattern to the card without affecting the readability of the content.
-{% capture html -%}
+
Here is example of a card with a background pattern.
-{%- endcapture %}
-{% capture code %}
+
+
-{% endcapture %}
-{% include "docs/example.html" html=html code=code bg="pattern-diagonal" column %}
+
## Accessibility
diff --git a/docs/pages/ui/utilities/borders.mdx b/docs/pages/ui/utilities/borders.mdx
new file mode 100644
index 000000000..e0aaaee94
--- /dev/null
+++ b/docs/pages/ui/utilities/borders.mdx
@@ -0,0 +1,107 @@
+---
+title: Borders
+summary: Use border utilities to quickly style the border and border-radius of an element. Great for images, buttons, or any other element.
+description: Style elements with border utilities.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Border direction
+
+Borders can be applied to specific sides of an element using utility classes. This is particularly useful for styling individual sides of a box, such as highlighting the top border for emphasis or applying a separator between elements. Below are examples of how to set borders for each side of an element.
+
+```html
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+```
+
+
+ 1
2
3
4
5
6
7
+
+
+
+## Border size
+
+Border size utilities allow you to control the thickness of borders, providing flexibility to suit different design needs. You can add no border, a standard border, or a wide border for a more prominent effect. These classes are especially useful for creating visual hierarchy or highlighting specific elements.
+
+```html
+
1
+
2
+
3
+```
+
+
+ 1
2
3
+
+
+## Remove border
+
+If you want to selectively remove borders from specific sides of an element, you can use border removal utilities. This feature simplifies styling tasks, such as creating a seamless connection between elements or achieving minimalistic designs.
+
+```html
+
1
+
2
+
3
+
4
+
5
+
6
+```
+
+
+ 1
2
3
4
5
6
+
+
+
+## Border color
+
+Customizing the border color helps to enhance the visual appeal and consistency of your design. With utility classes, you can easily apply specific colors to borders, allowing for greater flexibility in creating visually distinct sections.
+
+```html
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+```
+
+
+ 1
2
3
4
5
6
7
8
+
+
+## Border radius
+
+Adding border radius gives elements smooth, rounded edges, which can make designs feel more modern and approachable. You can choose from various levels of rounding, including full circles, using the available utility classes.
+
+```html
+
1
+
2
+
3
+
4
+
5
+
6
+```
+
+
+ 1
2
3
4
5
6
+
+
+
+## Border opacity
+
+You can adjust the opacity of borders to create subtle visual effects or to blend elements seamlessly into the background. By using border opacity utilities, you can control the transparency of borders, allowing for more creative and visually appealing designs. To change the opacity of a border, add the `border-opacity-*` class to the element.
+
+```html
+
This is 50% opacity success border
+```
+
+
+This is default success border
This is 75% opacity success border
This is 50% opacity success border
This is 25% opacity success border
This is 10% opacity success border
+
diff --git a/docs/content/ui/utilities/cursors.md b/docs/pages/ui/utilities/cursors.mdx
similarity index 62%
rename from docs/content/ui/utilities/cursors.md
rename to docs/pages/ui/utilities/cursors.mdx
index 6aff17ea1..58c31a8ee 100644
--- a/docs/content/ui/utilities/cursors.md
+++ b/docs/pages/ui/utilities/cursors.mdx
@@ -2,7 +2,9 @@
title: Cursors
summary: You can use different cursors to reflect the intended user interaction with particular elements of an interface. The cursor will change when a user hovers over a given element to indicate the action which can be performed.
description: Custom cursors for enhanced interaction.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
## Cursor utilities
@@ -44,23 +46,6 @@ Use one of the available cursor utilities depending on the action you want to in
The results can be seen in the example below.
-{% capture html -%}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html hide-code %}
\ No newline at end of file
+
+
+
diff --git a/docs/pages/ui/utilities/gradients.mdx b/docs/pages/ui/utilities/gradients.mdx
new file mode 100644
index 000000000..8bfecf475
--- /dev/null
+++ b/docs/pages/ui/utilities/gradients.mdx
@@ -0,0 +1,142 @@
+---
+title: Gradients
+summary: Use gradient utilities to build directional color backgrounds with from, via, and to color stops.
+description: Create directional gradients with utility classes.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+
+import Example from '@shared/components/docs/Example.astro'
+import site from '@data/site.json'
+export const colors = [...Object.keys(site.colors), 'white', 'transparent']
+
+## Default gradient
+
+Use `.bg-gradient` to enable gradient background rendering on an element. Then combine it with color stop utilities to define the final look.
+
+```html
+
+```
+
+
+
+
+
+## Gradient directions
+
+Use direction utilities to control gradient flow:
+
+- `.bg-gradient-to-t`
+- `.bg-gradient-to-te`
+- `.bg-gradient-to-e`
+- `.bg-gradient-to-be`
+- `.bg-gradient-to-b`
+- `.bg-gradient-to-bs`
+- `.bg-gradient-to-s`
+- `.bg-gradient-to-ts`
+
+
+
+
+
+
+
+ ...
+ ...
+ ...
+ ...
+ ...
+ ...
+ ...
+ ...
+
+
+## Gradient color stops
+
+Use color stop utilities to control where a gradient starts, transitions, and ends. You can choose any color from [full list of available colors](/ui/base/colors).
+
+Here is a list of classes:
+
+- `.bg-gradient-from-{color}`
+- `.bg-gradient-via-{color}` (optional middle stop for smoother blending)
+- `.bg-gradient-to-{color}`
+
+
+
+
+
+
.bg-gradient-from-purple .bg-gradient-to-transparent
+
+
+
+
.bg-gradient-from-pink .bg-gradient-via-orange .bg-gradient-to-yellow
+
+
+
+
+
+ ...
+ ...
+
+
+## Available colors
+
+You can use any project color token with `from`, `via`, and `to` utilities. See the [full list of available colors](/ui/base/colors) for all color names.
+
+
+
+
+ {colors.map((color) => (
+
+
+
.bg-gradient-from-{ color }
+
+ ))}
+
+
+
+ {colors.map((color) => (
+ ...
+ ))}
+
+
+## Examples
+
+### Card header gradient
+
+Use gradient utilities on card sections to highlight key content areas.
+
+
+
+
+
Performance
+
Weekly trend overview
+
+
+
+
+
+
+
+### Badge-like highlight
+
+Use short gradients on compact UI elements for subtle emphasis.
+
+
+
+
+ Success trend
+ Warning trend
+ New feature
+
+
diff --git a/docs/pages/ui/utilities/index.mdx b/docs/pages/ui/utilities/index.mdx
new file mode 100644
index 000000000..49c791098
--- /dev/null
+++ b/docs/pages/ui/utilities/index.mdx
@@ -0,0 +1,7 @@
+---
+title: Utilities
+order: 6
+description: Helper classes for layout and design.
+summary: The utilities section provides a collection of helper classes for layout and design, helping you build visually appealing and functional designs.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
diff --git a/docs/pages/ui/utilities/interactions.mdx b/docs/pages/ui/utilities/interactions.mdx
new file mode 100644
index 000000000..9b4ac2e58
--- /dev/null
+++ b/docs/pages/ui/utilities/interactions.mdx
@@ -0,0 +1,23 @@
+---
+title: Interactions
+summary: Utility classes that change how users interact with contents of a website.
+description: Modify user interactions efficiently.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+## Text selection
+
+Change the way in which the content is selected when the user interacts with it.
+
+
+This paragraph will be entirely selected when clicked by the user.
This paragraph has default select behavior.
This paragraph will not be selectable when clicked by the user.
+
+
+## Pointer events
+
+Tabler provides `.pe-none` and `.pe-auto` classes to prevent or add element interactions.
+
+
+ This link can be clicked (this is default behavior).
+
diff --git a/docs/pages/ui/utilities/margins.mdx b/docs/pages/ui/utilities/margins.mdx
new file mode 100644
index 000000000..30462e78d
--- /dev/null
+++ b/docs/pages/ui/utilities/margins.mdx
@@ -0,0 +1,136 @@
+---
+title: Margins
+summary: Use margin utilities to control the space between elements.
+description: Control the space between elements with margin utilities.
+layout: '@shared/layouts/DocsMdxLayout.astro'
+---
+import Example from '@shared/components/docs/Example.astro';
+
+Margin utilities allow you to control the space between elements, providing flexibility to suit different design needs. These utilities are especially useful for creating spacing between components or aligning them consistently. Below are examples of how to use margin utilities for various directions and sizes.
+
+
+### Margin size
+
+In the table below you can see the available margin sizes.
+
+Name|Value
+-|-
+0|0
+1|0.25rem
+2|0.5rem
+3|1rem
+4|1.5rem
+5|2rem
+6|3rem
+7|5rem
+8|8rem
+
+
+### Margin
+
+Use the `.m-*` utilities to control the margin of an element. Margin utilities are used to create consistent spacing around an element, ensuring that the layout is visually balanced.
+
+
+
+
+
+### Start margin
+
+Start margins control the spacing to the left of an element, helping to create consistent horizontal gaps between elements. Start margin class names are prefixed with `ms-`.
+
+```html
+
...
+```
+
+
+
+
+
+### End margin
+
+End margins control the spacing on the right side of an element. These utilities are helpful for creating visual separation between elements that flow horizontally. End margin class names are prefixed with `me-`.
+
+```html
+
...
+```
+
+
+
+
+
+### Top margin
+
+Top margins define the spacing above an element. This is useful for separating stacked components or creating vertical spacing between sections. Top margin class names are prefixed with `mt-`.
+
+```html
+
...
+```
+
+
+
+
+
+### Bottom margin
+
+Bottom margins control the spacing below an element, helping to create consistent vertical gaps between stacked elements. Bottom margin class names are prefixed with `mb-`.
+
+```html
+
...
+```
+
+
+
+
+
+### Horizontal margin
+
+Use the `mx-*` utilities to control the horizontal margin of an element. Horizontal margin utilities are used to create consistent spacing between elements that flow horizontally.
+
+```html
+
...
+```
+
+
+
+
+
+
+### Vertical margin
+
+Use the `my-*` utilities to control the vertical margin of an element. Vertical margin utilities are used to create consistent spacing between elements that flow vertically.
+
+```html
+
...
+```
+
+
+
+
+
+## Horizontal centering
+
+Additionally, Tabler also includes an `.mx-auto` class for horizontally centering fixed-width block level content — that is, content that has `display: block` and a width set — by setting the horizontal margins to `auto`.
+
+```html
+
...
+```
+
+
+
+
+
+## Gap
+
+Use the `.gap-*` utilities to control the space between elements in a grid layout. The gap utilities are used to create consistent spacing between grid items, ensuring that the layout is visually balanced.
+
+```html
+
...
+```
+
+```html example
+
+
Grid item 1
+
Grid item 2
+
Grid item 3
+
+```
diff --git a/docs/content/ui/utilities/vertical-align.md b/docs/pages/ui/utilities/vertical-align.mdx
similarity index 54%
rename from docs/content/ui/utilities/vertical-align.md
rename to docs/pages/ui/utilities/vertical-align.mdx
index f53461571..1e32daa29 100644
--- a/docs/content/ui/utilities/vertical-align.md
+++ b/docs/pages/ui/utilities/vertical-align.mdx
@@ -2,7 +2,9 @@
title: Vertical align
description: Quickly and easily align elements vertically with utility classes.
summary: Easily modify the vertical alignment of elements such as inline, inline-block, inline-table, and table-cell to ensure proper positioning and alignment within their parent containers, allowing for more precise control over your layout and design.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
Choose from `.align-baseline`, `.align-top`, `.align-middle`, `.align-bottom`, `.align-text-bottom`, and `.align-text-top` as needed.
@@ -10,34 +12,14 @@ Choose from `.align-baseline`, `.align-top`, `.align-middle`, `.align-bottom`, `
Use vertical alignment utilities to align inline-level elements relative to their surrounding text or baseline. These classes are particularly useful for aligning small inline elements like icons or badges alongside text.
-{% capture html -%}
-
- baseline
- top
- middle
- bottom
- text-top
- text-bottom
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
+
+ baseline top middle bottom text-top text-bottom
+
## Table cells
Vertical alignment utilities are also applicable to table cells, allowing you to control the alignment of content within a cell. This is especially useful for creating well-structured and visually appealing tables where the content aligns consistently across rows and columns.
-{% capture html -%}
-
-
-
- baseline
- top
- middle
- bottom
- text-top
- text-bottom
-
-
-
-{%- endcapture %}
-{% include "docs/example.html" html=html %}
\ No newline at end of file
+
+ baseline top middle bottom text-top text-bottom
+
diff --git a/docs/content/ui/utilities/visually-hidden.md b/docs/pages/ui/utilities/visually-hidden.mdx
similarity index 88%
rename from docs/content/ui/utilities/visually-hidden.md
rename to docs/pages/ui/utilities/visually-hidden.mdx
index 56e21b1ea..fd3b500f3 100644
--- a/docs/content/ui/utilities/visually-hidden.md
+++ b/docs/pages/ui/utilities/visually-hidden.mdx
@@ -1,7 +1,9 @@
---
title: Visually hidden
summary: Use these helpers to visually hide elements but keep them accessible to assistive technologies.
+layout: '@shared/layouts/DocsMdxLayout.astro'
---
+import Example from '@shared/components/docs/Example.astro';
Visually hide an element while still allowing it to be exposed to assistive technologies (such as screen readers) with `.visually-hidden`. Use `.visually-hidden-focusable` to visually hide an element by default, but to display it when it's focused (e.g. by a keyboard-only user). `.visually-hidden-focusable` can also be applied to a container – thanks to `:focus-within`, the container will be displayed when any child element of the container receives focus.
@@ -9,4 +11,4 @@ Visually hide an element while still allowing it to be exposed to assistive tech
Title for screen readers
Skip to main content
-```
\ No newline at end of file
+```
diff --git a/docs/public/img/banner-carbon.png b/docs/public/img/banner-carbon.png
deleted file mode 100644
index efd24facb..000000000
Binary files a/docs/public/img/banner-carbon.png and /dev/null differ
diff --git a/docs/public/img/browsers/brave.svg b/docs/public/img/browsers/brave.svg
deleted file mode 100644
index 0bb889329..000000000
--- a/docs/public/img/browsers/brave.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/chrome.svg b/docs/public/img/browsers/chrome.svg
deleted file mode 100644
index 67a40c205..000000000
--- a/docs/public/img/browsers/chrome.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/edge.svg b/docs/public/img/browsers/edge.svg
deleted file mode 100644
index 12f3661cc..000000000
--- a/docs/public/img/browsers/edge.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/electron.svg b/docs/public/img/browsers/electron.svg
deleted file mode 100644
index f7ee7316e..000000000
--- a/docs/public/img/browsers/electron.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/firefox.svg b/docs/public/img/browsers/firefox.svg
deleted file mode 100644
index b36a75b9d..000000000
--- a/docs/public/img/browsers/firefox.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/internet-explorer.svg b/docs/public/img/browsers/internet-explorer.svg
deleted file mode 100644
index ff1896d46..000000000
--- a/docs/public/img/browsers/internet-explorer.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/opera.svg b/docs/public/img/browsers/opera.svg
deleted file mode 100644
index b5a958b79..000000000
--- a/docs/public/img/browsers/opera.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/safari.svg b/docs/public/img/browsers/safari.svg
deleted file mode 100644
index d1b51a95b..000000000
--- a/docs/public/img/browsers/safari.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/browsers/vivaldi.svg b/docs/public/img/browsers/vivaldi.svg
deleted file mode 100644
index ab698abd2..000000000
--- a/docs/public/img/browsers/vivaldi.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/public/img/cover-illustrations-dark.png b/docs/public/img/cover-illustrations-dark.png
deleted file mode 100644
index d124edf6c..000000000
Binary files a/docs/public/img/cover-illustrations-dark.png and /dev/null differ
diff --git a/docs/public/img/cover-illustrations.png b/docs/public/img/cover-illustrations.png
deleted file mode 100644
index 9cca0212c..000000000
Binary files a/docs/public/img/cover-illustrations.png and /dev/null differ
diff --git a/docs/public/img/cover-tabler-dark.png b/docs/public/img/cover-tabler-dark.png
deleted file mode 100644
index a2a1d167a..000000000
Binary files a/docs/public/img/cover-tabler-dark.png and /dev/null differ
diff --git a/docs/public/img/cover-tabler.png b/docs/public/img/cover-tabler.png
deleted file mode 100644
index bf54b6b53..000000000
Binary files a/docs/public/img/cover-tabler.png and /dev/null differ
diff --git a/docs/public/img/icons/figma-plugin.png b/docs/public/img/icons/figma-plugin.png
deleted file mode 100644
index 76d315fed..000000000
Binary files a/docs/public/img/icons/figma-plugin.png and /dev/null differ
diff --git a/docs/public/img/icons/package-angular-dark.png b/docs/public/img/icons/package-angular-dark.png
deleted file mode 100644
index 756374a5e..000000000
Binary files a/docs/public/img/icons/package-angular-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-angular.png b/docs/public/img/icons/package-angular.png
deleted file mode 100644
index 00aa353fb..000000000
Binary files a/docs/public/img/icons/package-angular.png and /dev/null differ
diff --git a/docs/public/img/icons/package-eps-dark.png b/docs/public/img/icons/package-eps-dark.png
deleted file mode 100644
index ce65a2f42..000000000
Binary files a/docs/public/img/icons/package-eps-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-eps.png b/docs/public/img/icons/package-eps.png
deleted file mode 100644
index 48fc0e178..000000000
Binary files a/docs/public/img/icons/package-eps.png and /dev/null differ
diff --git a/docs/public/img/icons/package-js-dark.png b/docs/public/img/icons/package-js-dark.png
deleted file mode 100644
index 3ee1f5a2a..000000000
Binary files a/docs/public/img/icons/package-js-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-js.png b/docs/public/img/icons/package-js.png
deleted file mode 100644
index 1b5aac4a9..000000000
Binary files a/docs/public/img/icons/package-js.png and /dev/null differ
diff --git a/docs/public/img/icons/package-pdf-dark.png b/docs/public/img/icons/package-pdf-dark.png
deleted file mode 100644
index 67fc56ad6..000000000
Binary files a/docs/public/img/icons/package-pdf-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-pdf.png b/docs/public/img/icons/package-pdf.png
deleted file mode 100644
index 04e45e429..000000000
Binary files a/docs/public/img/icons/package-pdf.png and /dev/null differ
diff --git a/docs/public/img/icons/package-png-dark.png b/docs/public/img/icons/package-png-dark.png
deleted file mode 100644
index 48b85de40..000000000
Binary files a/docs/public/img/icons/package-png-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-png.png b/docs/public/img/icons/package-png.png
deleted file mode 100644
index be429b43f..000000000
Binary files a/docs/public/img/icons/package-png.png and /dev/null differ
diff --git a/docs/public/img/icons/package-preact-dark.png b/docs/public/img/icons/package-preact-dark.png
deleted file mode 100644
index 33d539abf..000000000
Binary files a/docs/public/img/icons/package-preact-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-preact.png b/docs/public/img/icons/package-preact.png
deleted file mode 100644
index 983917c04..000000000
Binary files a/docs/public/img/icons/package-preact.png and /dev/null differ
diff --git a/docs/public/img/icons/package-react-dark.png b/docs/public/img/icons/package-react-dark.png
deleted file mode 100644
index 38d3db390..000000000
Binary files a/docs/public/img/icons/package-react-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-react-native-dark.png b/docs/public/img/icons/package-react-native-dark.png
deleted file mode 100644
index a59db969a..000000000
Binary files a/docs/public/img/icons/package-react-native-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-react-native.png b/docs/public/img/icons/package-react-native.png
deleted file mode 100644
index 6b9245a22..000000000
Binary files a/docs/public/img/icons/package-react-native.png and /dev/null differ
diff --git a/docs/public/img/icons/package-react.png b/docs/public/img/icons/package-react.png
deleted file mode 100644
index 9d99f9b2e..000000000
Binary files a/docs/public/img/icons/package-react.png and /dev/null differ
diff --git a/docs/public/img/icons/package-solidjs-dark.png b/docs/public/img/icons/package-solidjs-dark.png
deleted file mode 100644
index 3b0bafa25..000000000
Binary files a/docs/public/img/icons/package-solidjs-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-solidjs.png b/docs/public/img/icons/package-solidjs.png
deleted file mode 100644
index 69e9295fb..000000000
Binary files a/docs/public/img/icons/package-solidjs.png and /dev/null differ
diff --git a/docs/public/img/icons/package-sprite-dark.png b/docs/public/img/icons/package-sprite-dark.png
deleted file mode 100644
index 2825e542b..000000000
Binary files a/docs/public/img/icons/package-sprite-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-sprite.png b/docs/public/img/icons/package-sprite.png
deleted file mode 100644
index 12dde6d2c..000000000
Binary files a/docs/public/img/icons/package-sprite.png and /dev/null differ
diff --git a/docs/public/img/icons/package-svelte-dark.png b/docs/public/img/icons/package-svelte-dark.png
deleted file mode 100644
index 7f1db2ef1..000000000
Binary files a/docs/public/img/icons/package-svelte-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-svelte.png b/docs/public/img/icons/package-svelte.png
deleted file mode 100644
index 1c9503532..000000000
Binary files a/docs/public/img/icons/package-svelte.png and /dev/null differ
diff --git a/docs/public/img/icons/package-svg-dark.png b/docs/public/img/icons/package-svg-dark.png
deleted file mode 100644
index 236e8f9d3..000000000
Binary files a/docs/public/img/icons/package-svg-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-svg.png b/docs/public/img/icons/package-svg.png
deleted file mode 100644
index 24703977f..000000000
Binary files a/docs/public/img/icons/package-svg.png and /dev/null differ
diff --git a/docs/public/img/icons/package-vue-dark.png b/docs/public/img/icons/package-vue-dark.png
deleted file mode 100644
index f368f040f..000000000
Binary files a/docs/public/img/icons/package-vue-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-vue.png b/docs/public/img/icons/package-vue.png
deleted file mode 100644
index aeffcd3bd..000000000
Binary files a/docs/public/img/icons/package-vue.png and /dev/null differ
diff --git a/docs/public/img/icons/package-webfont-dark.png b/docs/public/img/icons/package-webfont-dark.png
deleted file mode 100644
index 0811758f5..000000000
Binary files a/docs/public/img/icons/package-webfont-dark.png and /dev/null differ
diff --git a/docs/public/img/icons/package-webfont.png b/docs/public/img/icons/package-webfont.png
deleted file mode 100644
index 30758748a..000000000
Binary files a/docs/public/img/icons/package-webfont.png and /dev/null differ
diff --git a/docs/public/img/tabler-dark.png b/docs/public/img/tabler-dark.png
deleted file mode 100644
index 6c8c98b72..000000000
Binary files a/docs/public/img/tabler-dark.png and /dev/null differ
diff --git a/docs/public/img/tabler.png b/docs/public/img/tabler.png
deleted file mode 100644
index ea15f3789..000000000
Binary files a/docs/public/img/tabler.png and /dev/null differ
diff --git a/docs/scss/docs.scss b/docs/scss/docs.scss
deleted file mode 100644
index 0e5d10697..000000000
--- a/docs/scss/docs.scss
+++ /dev/null
@@ -1,136 +0,0 @@
-@use "@docsearch/css/dist/style.css";
-
-:root {
- --docsearch-primary-color: var(--tblr-primary);
- --docsearch-searchbox-background: var(--tblr-bg-surface);
- --docsearch-searchbox-focus-background: var(--tblr-bg-surface);
- --docsearch-text-color: var(--tblr-body-text);
- --docsearch-key-shadow: 0 0 0 1px var(--tblr-border-color);
- --docsearch-key-gradient: var(--tblr-bg-surface-secondary);
-}
-
-.col-docs {
- width: 15rem;
-}
-
-.bg-docs-gradient {
- @media (min-width: 992px) {
- background: radial-gradient(circle at 0 0, color-mix(in srgb, var(--tblr-primary) 4%, transparent), transparent 80%) no-repeat 0 0 / 800px 800px !important;
- }
-}
-
-.DocSearch-Button {
- width: 100%;
- box-shadow: 0 0 0 1px var(--tblr-border-color);
- font-weight: var(--tblr-font-weight-normal);
- transition: all 0.2s ease-in-out;
-}
-
-.DocSearch-SearchBar {
- display: flex;
- padding: var(--docsearch-spacing) var(--docsearch-spacing) 0;
- background-color: var(--tblr-bg-surface) !important;
-}
-
-.DocSearch-Hit-source {
- background: none !important;
-}
-
-.DocSearch-Dropdown {
- background-color: var(--tblr-bg-surface) !important;
-}
-
-.DocSearch-Hit a {
- background-color: var(--tblr-bg-surface-secondary) !important;
- border: 1px solid var(--tblr-border-color) !important;
- color: var(--tblr-body-color) !important;
- box-shadow: none !important;
-
- &:hover {
- background-color: var(--tblr-bg-surface-tertiary) !important;
- border-color: var(--tblr-border-color-active) !important;
- }
-}
-
-.DocSearch-Hit-Container {
- color: var(--tblr-body-color) !important;
-}
-
-.DocSearch-Hit-title {
- color: var(--tblr-body-color) !important;
-}
-
-.DocSearch-Hit-path {
- color: var(--tblr-muted) !important;
-}
-
-.DocSearch-Hit[aria-selected="true"] a {
- background-color: var(--tblr-primary) !important;
- border-color: var(--tblr-primary) !important;
- color: var(--tblr-primary-fg) !important;
-}
-
-.DocSearch-Hit[aria-selected="true"] .DocSearch-Hit-Container,
-.DocSearch-Hit[aria-selected="true"] .DocSearch-Hit-title,
-.DocSearch-Hit[aria-selected="true"] .DocSearch-Hit-path {
- color: var(--tblr-primary-fg) !important;
-}
-
-.DocSearch-Modal {
- background-color: var(--tblr-bg-surface) !important;
- box-shadow: var(--tblr-shadow-dropdown) !important;
-}
-
-.DocSearch-Form {
- background-color: var(--tblr-bg-surface-secondary) !important;
- border: 1px solid var(--tblr-border-color) !important;
-}
-
-.DocSearch-Input {
- color: var(--tblr-body-color) !important;
-
- &::placeholder {
- color: var(--tblr-muted) !important;
- }
-}
-
-.DocSearch-Footer {
- background-color: var(--tblr-bg-surface) !important;
- border-top: 1px solid var(--tblr-border-color) !important;
- box-shadow: none !important;
-}
-
-.DocSearch-Button-Key {
- top: 0;
-}
-
-.DocSearch-Container {
- z-index: 10000;
-}
-
-.no-transition {
- * {
- transition: none !important;
- }
-}
-
-.example > .modal,
-.example > .offcanvas {
- display: block !important;
- position: relative !important;
-}
-
-.example > .offcanvas-backdrop {
- position: absolute !important;
-}
-
-.shiki {
- background: var(--tblr-gray-900) !important;
- color: var(--tblr-gray-300) !important;
-}
-
-code {
- ::selection {
- background: var(--tblr-primary);
- }
-}
diff --git a/docs/static b/docs/static
deleted file mode 120000
index 36b10cebf..000000000
--- a/docs/static
+++ /dev/null
@@ -1 +0,0 @@
-../shared/static
\ No newline at end of file
diff --git a/docs/tsconfig.json b/docs/tsconfig.json
new file mode 100644
index 000000000..6e6e86002
--- /dev/null
+++ b/docs/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "extends": "astro/tsconfigs/strict",
+ "include": [
+ ".astro/types.d.ts",
+ "**/*"
+ ],
+ "exclude": [
+ "dist"
+ ],
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@data/*": [
+ "../shared/data/*"
+ ],
+ "@shared/*": [
+ "../shared/astro/*"
+ ]
+ }
+ }
+}
diff --git a/docs/vercel.json b/docs/vercel.json
deleted file mode 100644
index a9833a9a6..000000000
--- a/docs/vercel.json
+++ /dev/null
@@ -1,122 +0,0 @@
-{
- "trailingSlash": false,
- "rewrites": [
- {
- "source": "/stats/js/script.js",
- "destination": "https://plausible.io/js/script.js"
- },
- {
- "source": "/stats/event",
- "destination": "https://plausible.io/api/event"
- },
- {
- "source": "/eat/static/:path(.*)",
- "destination": "https://eu-assets.i.posthog.com/static/:path*"
- },
- {
- "source": "/eat/:path(.*)",
- "destination": "https://eu.i.posthog.com/:path*"
- },
- {
- "source": "/((?!robots\\.txt|sitemap\\.xml).*)",
- "destination": "/error-404.html"
- }
- ],
- "redirects": [
- {
- "source": "/ui/components/alerts",
- "destination": "/ui/components/alert",
- "permanent": true
- },
- {
- "source": "/ui/components/avatars",
- "destination": "/ui/components/avatar",
- "permanent": true
- },
- {
- "source": "/ui/components/badges",
- "destination": "/ui/components/badge",
- "permanent": true
- },
- {
- "source": "/ui/components/buttons",
- "destination": "/ui/components/button",
- "permanent": true
- },
- {
- "source": "/ui/components/cards",
- "destination": "/ui/components/card",
- "permanent": true
- },
- {
- "source": "/ui/components/charts",
- "destination": "/ui/components/chart",
- "permanent": true
- },
- {
- "source": "/ui/components/dropdowns",
- "destination": "/ui/components/dropdown",
- "permanent": true
- },
- {
- "source": "/ui/components/icons",
- "destination": "/ui/components/icon",
- "permanent": true
- },
- {
- "source": "/ui/components/modals",
- "destination": "/ui/components/modal",
- "permanent": true
- },
- {
- "source": "/ui/components/ribbons",
- "destination": "/ui/components/ribbon",
- "permanent": true
- },
- {
- "source": "/ui/components/spinners",
- "destination": "/ui/components/spinner",
- "permanent": true
- },
- {
- "source": "/ui/components/statuses",
- "destination": "/ui/components/status",
- "permanent": true
- },
- {
- "source": "/ui/components/steps",
- "destination": "/ui/components/step",
- "permanent": true
- },
- {
- "source": "/ui/components/tabs",
- "destination": "/ui/components/tab",
- "permanent": true
- },
- {
- "source": "/ui/components/tables",
- "destination": "/ui/components/table",
- "permanent": true
- },
- {
- "source": "/ui/components/timelines",
- "destination": "/ui/components/timeline",
- "permanent": true
- },
- {
- "source": "/ui/components/toasts",
- "destination": "/ui/components/toast",
- "permanent": true
- },
- {
- "source": "/ui/components/tooltips",
- "destination": "/ui/components/tooltip",
- "permanent": true
- },
- {
- "source": "/ui/components/vector-maps",
- "destination": "/ui/components/vector-map",
- "permanent": true
- }
- ]
-}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9dc3c1e1a..7f3ced016 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -202,88 +202,166 @@ importers:
'@tabler/core':
specifier: workspace:*
version: link:../core
- devDependencies:
- '@11ty/eleventy':
- specifier: 3.1.6
- version: 3.1.6(supports-color@5.5.0)
- '@docsearch/css':
- specifier: ^4.6.3
- version: 4.6.3
- '@docsearch/js':
- specifier: ^4.6.3
- version: 4.6.3
- flat-cache:
- specifier: ^6.1.23
- version: 6.1.23
+ astro:
+ specifier: ^7.0.9
+ version: 7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
shiki:
specifier: ^4.3.1
version: 4.3.1
+ devDependencies:
+ '@astrojs/mdx':
+ specifier: ^7.0.3
+ version: 7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ '@tabler/preview':
+ specifier: workspace:*
+ version: link:../preview
+ '@types/node':
+ specifier: ^26.1.1
+ version: 26.1.1
+ js-beautify:
+ specifier: ^2.0.3
+ version: 2.0.3
+ shx:
+ specifier: ^0.4.0
+ version: 0.4.0
preview:
dependencies:
'@tabler/core':
specifier: workspace:*
version: link:../core
- '@tabler/icons':
- specifier: ^3.40.0
- version: 3.44.0
+ astro:
+ specifier: ^7.0.7
+ version: 7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
devDependencies:
- '@11ty/eleventy':
- specifier: 3.1.2
- version: 3.1.2(supports-color@5.5.0)
- imageoptim-cli:
- specifier: ^3.1.9
- version: 3.1.9
- request:
- specifier: ^2.88.2
- version: 2.88.2
+ '@astrojs/mdx':
+ specifier: ^7.0.2
+ version: 7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ js-beautify:
+ specifier: ^2.0.3
+ version: 2.0.3
+ prettier:
+ specifier: ^3.9.5
+ version: 3.9.5
+ shiki:
+ specifier: ^4.3.1
+ version: 4.3.1
+ shx:
+ specifier: ^0.4.0
+ version: 0.4.0
+
+ shared/astro:
+ dependencies:
+ '@tabler/core':
+ specifier: workspace:*
+ version: link:../../core
+ js-beautify:
+ specifier: ^2.0.3
+ version: 2.0.3
+ markdown-it:
+ specifier: ^14.3.0
+ version: 14.3.0
+ shiki:
+ specifier: ^4.3.1
+ version: 4.3.1
packages:
- '@11ty/dependency-tree-esm@2.0.4':
- resolution: {integrity: sha512-MYKC0Ac77ILr1HnRJalzKDlb9Z8To3kXQCltx299pUXXUFtJ1RIONtULlknknqW8cLe19DLVgmxVCtjEFm7h0A==}
-
- '@11ty/dependency-tree@4.0.2':
- resolution: {integrity: sha512-RTF6VTZHatYf7fSZBUN3RKwiUeJh5dhWV61gDPrHhQF2/gzruAkYz8yXuvGLx3w3ZBKreGrR+MfYpSVkdbdbLA==}
-
- '@11ty/eleventy-dev-server@2.0.8':
- resolution: {integrity: sha512-15oC5M1DQlCaOMUq4limKRYmWiGecDaGwryr7fTE/oM9Ix8siqMvWi+I8VjsfrGr+iViDvWcH/TVI6D12d93mA==}
- engines: {node: '>=18'}
- hasBin: true
-
- '@11ty/eleventy-plugin-bundle@3.0.7':
- resolution: {integrity: sha512-QK1tRFBhQdZASnYU8GMzpTdsMMFLVAkuU0gVVILqNyp09xJJZb81kAS3AFrNrwBCsgLxTdWHJ8N64+OTTsoKkA==}
- engines: {node: '>=18'}
-
- '@11ty/eleventy-utils@2.0.7':
- resolution: {integrity: sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==}
- engines: {node: '>=18'}
-
- '@11ty/eleventy@3.1.2':
- resolution: {integrity: sha512-IcsDlbXnBf8cHzbM1YBv3JcTyLB35EK88QexmVyFdVJVgUU6bh9g687rpxryJirHzo06PuwnYaEEdVZQfIgRGg==}
- engines: {node: '>=18'}
- hasBin: true
-
- '@11ty/eleventy@3.1.6':
- resolution: {integrity: sha512-ZlSiR1PLdS2lv7TelBgWAhcvMiLNZkPBlLEb+lh7kGYZ+Mk0bo9qcYgVsewvw9W7Em0RH3wd01h5fAstNDh0zA==}
- engines: {node: '>=18'}
- hasBin: true
-
- '@11ty/lodash-custom@4.17.21':
- resolution: {integrity: sha512-Mqt6im1xpb1Ykn3nbcCovWXK3ggywRJa+IXIdoz4wIIK+cvozADH63lexcuPpGS/gJ6/m2JxyyXDyupkMr5DHw==}
- engines: {node: '>=14'}
-
- '@11ty/posthtml-urls@1.0.3':
- resolution: {integrity: sha512-1YvhnkaNlFnnJic1rBMWmTC2adbuy+JQiBfl1Hecr1Wjjik1pQZmGyk/eC9zKX/FQv52s2Nht1Gi/UwhYqrBeg==}
- engines: {node: '>= 6'}
-
- '@11ty/recursive-copy@4.0.4':
- resolution: {integrity: sha512-oI7m8pa7/IAU/3lqRU9vjBbs20iKFo7x+1K9kT3aVira6scc1X9MjBdgLCHzLJeJ7iB6wydioA+kr9/qPnvmlQ==}
- engines: {node: '>=18'}
-
'@adobe/css-tools@4.5.0':
resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==}
+ '@astrojs/compiler-binding-darwin-arm64@0.3.1':
+ resolution: {integrity: sha512-IEmEF2fUIlTHtpeE/isyEGVOB14cEyh/LZOFYt6wn3jNyVpdC8aR5OZ+RzFUR/f+8ZDM1LaMwZKvoA7eMyJeFw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@astrojs/compiler-binding-darwin-x64@0.3.1':
+ resolution: {integrity: sha512-GF2kIxjpPDLsn94zbZNMsxEmkU828QqnmM7kiQJnaooS3jmI+I7kk6+oI6EpwOsK3femCMdcm+wmOsEqtGrmjQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1':
+ resolution: {integrity: sha512-XJL3SDmOtVrqFhCirNcHwE91+IesJqlgNo23I4qW9QUYfwzm/TBZuH61fgqsb1ttgR1mMYz6ooPWs0JDhwMqpQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@astrojs/compiler-binding-linux-arm64-musl@0.3.1':
+ resolution: {integrity: sha512-xqE8BVbDoBueK/B47w30PtkVofUWJKGkwoMVE+EOMLf11rnoANxIAdA9FPqY+rng4oNI5ndHGsri1yPj2k8vZQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@astrojs/compiler-binding-linux-x64-gnu@0.3.1':
+ resolution: {integrity: sha512-1y0StU1qiCuDFH3rmbRJXcxdfHxFPrES1Rd+RLffosvUR7I2cH5SF5SFnBN9vXpzpkmyElZm3Yr47iJBPN7vVA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@astrojs/compiler-binding-linux-x64-musl@0.3.1':
+ resolution: {integrity: sha512-16q0fYf7kpbmdObZEeZJEup8hQv/whgNwVjrSvT8umrKwLDSnNIWiQpm09lQQu6bweZB0XyIvHwlPitvJhC+hg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@astrojs/compiler-binding-wasm32-wasi@0.3.1':
+ resolution: {integrity: sha512-cB456shIwDv/PrVT+2QG7LFndpHkVge5HjqADKZgGaAc9JHVktCtjSrcdkRQ+3tbkPazNKaTLRjXLIiz2NIx9g==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1':
+ resolution: {integrity: sha512-ur/9+If/yTE69mmeX5MqSZndL0HOyx67GeNZUy3N7wVdWpLz9UTJXwyWS4UR2PUQHitghjsM5xoX0Ge56WRVQQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@astrojs/compiler-binding-win32-x64-msvc@0.3.1':
+ resolution: {integrity: sha512-k0W+kDBzDkNZOqu4kElDvCOIbKw5Ut9S1WZ1Krj3KTgNuBERNKXsMMsRLLcbgfdMdbe7bTekQLshZrrvmYpmwA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@astrojs/compiler-binding@0.3.1':
+ resolution: {integrity: sha512-DaAUj29AIBU2XdJ8uwcab8lW5O2pk9pY8AXkcMw0sw77nVa3oeTYRcO+Dvbbpoexf6ThMc0FMWYCQ/wN1/T7oQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+
+ '@astrojs/compiler-rs@0.3.1':
+ resolution: {integrity: sha512-aT7xkgsbNoS6nriY5qKpbihK43slFHO41iqgHCTdOvn1ifaQxLCc5yXy+6GzAtiafoaC1zA7OwVXCXMsvUZOkg==}
+ engines: {node: '>=22.12.0'}
+
+ '@astrojs/internal-helpers@0.10.1':
+ resolution: {integrity: sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q==}
+
+ '@astrojs/markdown-remark@7.2.1':
+ resolution: {integrity: sha512-jPVNIqTvk+yKviikszv/Y1U4jGUSKpp/Nw48QZV4qjWgp70j4Lkq3lhSDRbWwCfgKvEyO9GHuVbV1dM2WYXy1w==}
+
+ '@astrojs/markdown-satteri@0.3.4':
+ resolution: {integrity: sha512-6Lvt/bQZEBW+zzdhPblvfZEy5PGEYJaUsUqaCgwHeRPxZJL1gc9I+DRLKWJjjYTWDzVUTzXlMq4WwSK+X34CVw==}
+
+ '@astrojs/mdx@7.0.3':
+ resolution: {integrity: sha512-RxyIwU0uFam5ftwqKOjpIdhnFxZ/kEikeimLyQy3eGXbHT8WgRGzzesOIHVU8+m9TY8ag5WVOyvV24/GyqPdPQ==}
+ engines: {node: '>=22.12.0'}
+ peerDependencies:
+ '@astrojs/markdown-satteri': ^0.3.1
+ astro: ^7.0.0
+ peerDependenciesMeta:
+ '@astrojs/markdown-satteri':
+ optional: true
+
+ '@astrojs/prism@4.0.2':
+ resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==}
+ engines: {node: '>=22.12.0'}
+
+ '@astrojs/telemetry@3.3.3':
+ resolution: {integrity: sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==}
+ engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+
'@babel/code-frame@7.29.7':
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
engines: {node: '>=6.9.0'}
@@ -362,11 +440,58 @@ packages:
'@blazediff/core@1.9.1':
resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==}
- '@cacheable/memory@2.2.0':
- resolution: {integrity: sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==}
+ '@bruits/satteri-darwin-arm64@0.9.5':
+ resolution: {integrity: sha512-iw4nZgx9v30lWo/MTngQqi1pI78KI0DnkSm+lVJGYdmPLgAyDNJigVhpG42/Iq55A6c1Ll8q66ljyyRiQUxwow==}
+ cpu: [arm64]
+ os: [darwin]
- '@cacheable/utils@2.5.0':
- resolution: {integrity: sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==}
+ '@bruits/satteri-darwin-x64@0.9.5':
+ resolution: {integrity: sha512-6T26Z5Kf3cFW2PSlk9p7zT7yVxvuBSiJvYyz9u8KjYwMTqZyIDOj2wDyNpxKV4+6yUVG7rddq2QwvG/8LJA2+Q==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@bruits/satteri-linux-arm64-gnu@0.9.5':
+ resolution: {integrity: sha512-u51id17uJwNEMK9nBlICsq6U31c+XVqQueVBkwRIzZG+gMpS8TOJctt5h5Wz33Z8xnMdTd+adtACVz0yHgGuOA==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@bruits/satteri-linux-arm64-musl@0.9.5':
+ resolution: {integrity: sha512-v39HxiwGC5Rqm01HksP6+5Y+xKLPlsuVFgIgpEAo+SiQ22c+mJVhS3u7Z6ePAKdhL5NJoK1xq70kLz3L13AhpQ==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@bruits/satteri-linux-x64-gnu@0.9.5':
+ resolution: {integrity: sha512-F3uO8uFp3pAP5ZGXttwvh57GS7s0lL953tnNdyI2gRyP4kOOkp6pyGojNJzCjkDvWI2Cvb9iNrKok3aqQPauAw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@bruits/satteri-linux-x64-musl@0.9.5':
+ resolution: {integrity: sha512-bicEqglLlz++mWyADaZoP0JY20s4vDfLjaPYgQqC+NI4zZLTOOg1T4GB8aqtc822Pqji8SQBmSrTb7CrP8i08Q==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@bruits/satteri-wasm32-wasi@0.9.5':
+ resolution: {integrity: sha512-zauAuMwfPnKPUkd4AFixRFpXdgKwP2mKgxrIIo2gJzW0/ZneF9dbHnLkojSpaBnCCp7VUL1hIi5WWZvB1CqmAQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@bruits/satteri-win32-arm64-msvc@0.9.5':
+ resolution: {integrity: sha512-SrfE7NEsgZjBvU3c+RR6oQRu0ToXY5uVJEbieXEF0YTctIV2zAVlbaMjWLts074QCgh3a+XHWkR/lWh2VH2LUg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@bruits/satteri-win32-x64-msvc@0.9.5':
+ resolution: {integrity: sha512-5Kw9ZAtTGS8WHizyn+CJhjjfIQrw+7jcZodpmpXJjefnO15M8UexIi6JR2E5thyvsmHyhL6ZDDMUNR4bKJPd4g==}
+ cpu: [x64]
+ os: [win32]
+
+ '@capsizecss/unpack@4.0.1':
+ resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==}
+ engines: {node: '>=18'}
'@changesets/apply-release-plan@7.1.1':
resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==}
@@ -429,11 +554,13 @@ packages:
'@changesets/write@0.4.0':
resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
- '@docsearch/css@4.6.3':
- resolution: {integrity: sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==}
+ '@clack/core@1.4.3':
+ resolution: {integrity: sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ==}
+ engines: {node: '>= 20.12.0'}
- '@docsearch/js@4.6.3':
- resolution: {integrity: sha512-qUIX2b4Apew3tv4F0qhmgShsl/Lfw4m6mqv/5/5dWNxwTcDdLMp2s3YwZ+NMGh3IKCg0pBaXm7Q5VdyU5Rj+cQ==}
+ '@clack/prompts@1.7.0':
+ resolution: {integrity: sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A==}
+ engines: {node: '>= 20.12.0'}
'@emnapi/core@1.11.1':
resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==}
@@ -832,21 +959,15 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
- '@keyv/bigmap@1.3.1':
- resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==}
- engines: {node: '>= 18'}
- peerDependencies:
- keyv: ^5.6.0
-
- '@keyv/serialize@1.1.1':
- resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==}
-
'@manypkg/find-root@1.1.0':
resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
+ '@mdx-js/mdx@3.1.1':
+ resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==}
+
'@melloware/coloris@0.25.0':
resolution: {integrity: sha512-RBWVFLjWbup7GRkOXb9g3+ZtR9AevFtJinrRz2cYPLjZ3TCkNRGMWuNbmQWbZ5cF3VU7aQDZwUsYgIY/bGrh2g==}
@@ -932,6 +1053,9 @@ packages:
'@orchidjs/unicode-variants@1.1.2':
resolution: {integrity: sha512-5DobW1CHgnBROOEpFlEXytED5OosEWESFvg/VYmH0143oXcijYTprRYJTs+55HzGM4IqxiLFSuqEzu9mPNwVsA==}
+ '@oslojs/encoding@1.1.0':
+ resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
+
'@oxc-project/types@0.138.0':
resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==}
@@ -1127,6 +1251,15 @@ packages:
'@rolldown/pluginutils@1.0.1':
resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+ '@rollup/pluginutils@5.4.0':
+ resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
+ peerDependenciesMeta:
+ rollup:
+ optional: true
+
'@shikijs/core@4.3.1':
resolution: {integrity: sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==}
engines: {node: '>=20'}
@@ -1161,14 +1294,6 @@ packages:
'@sinclair/typebox@0.34.52':
resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==}
- '@sindresorhus/slugify@2.2.1':
- resolution: {integrity: sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==}
- engines: {node: '>=12'}
-
- '@sindresorhus/transliterate@1.6.0':
- resolution: {integrity: sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==}
- engines: {node: '>=12'}
-
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
@@ -1178,9 +1303,6 @@ packages:
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
- '@tabler/icons@3.44.0':
- resolution: {integrity: sha512-Wn0AOZG9sg0L+bjfMqq4eNhC6pQjIrk94LvvWYNYkY8KH8wC3YILRzQlrnVJc4FUeMxH/AK97QsYCX35H3LndA==}
-
'@turbo/darwin-64@2.10.3':
resolution: {integrity: sha512-guuiO2kKc7yUQFU2jhWyM/BrYGD/brqb0+JvJIXTQ/QI1NlWfHZ1id50kkkOWqxmBiDc8DgW2orfY85pQIc7gw==}
cpu: [x64]
@@ -1223,6 +1345,9 @@ packages:
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
@@ -1235,15 +1360,24 @@ packages:
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+ '@types/mdx@2.0.14':
+ resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==}
+
'@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+ '@types/nlcst@2.0.3':
+ resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==}
+
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
'@types/node@26.1.0':
resolution: {integrity: sha512-O0A1G3xPGy4w7AgQdAQYUlQ+BKk2Oovw8eRpofyp5KdBZULnbe+WqaOVNrm705SHphCiG4XHsACrSmPu1f+Kgw==}
+ '@types/node@26.1.1':
+ resolution: {integrity: sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==}
+
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
@@ -1301,16 +1435,14 @@ packages:
'@vitest/utils@4.1.9':
resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==}
- a-sync-waterfall@1.0.1:
- resolution: {integrity: sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==}
-
abbrev@5.0.0:
resolution: {integrity: sha512-/XrFJgzQQQHpti1raDJC6m4ws6aNktmjBlhk8Fdlk7LwCEuDoieEJJY9OFHjfiFJFFRM2tK+Ky/IsfbbmlMu1w==}
engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
- acorn-walk@8.3.5:
- resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==}
- engines: {node: '>=0.4.0'}
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
acorn@8.17.0:
resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==}
@@ -1321,8 +1453,9 @@ packages:
resolution: {integrity: sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==}
engines: {node: '>=12.0'}
- ajv@6.15.0:
- resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
+ am-i-vibing@0.4.0:
+ resolution: {integrity: sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg==}
+ hasBin: true
ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
@@ -1361,24 +1494,35 @@ packages:
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ array-iterate@2.0.1:
+ resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
+
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
- asap@2.0.6:
- resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
-
- asn1@0.2.6:
- resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
-
- assert-plus@1.0.0:
- resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
- engines: {node: '>=0.8'}
-
assertion-error@2.0.1:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
+ astring@1.9.0:
+ resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
+ hasBin: true
+
+ astro@7.1.1:
+ resolution: {integrity: sha512-yfKhuvbz+DORHihJRL1DHcxyLcX9uTrxvz2nCSTzHH54k2DdACBfuOu2OAAAhdUC9xlu2IRXAiagqcPL3DftCg==}
+ engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'}
+ hasBin: true
+ peerDependencies:
+ '@astrojs/markdown-remark': 7.2.1
+ peerDependenciesMeta:
+ '@astrojs/markdown-remark':
+ optional: true
+
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -1392,15 +1536,16 @@ packages:
autosize@6.0.1:
resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==}
- aws-sign2@0.7.0:
- resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
-
- aws4@1.13.2:
- resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
-
axios@0.31.1:
resolution: {integrity: sha512-Ef8DUZSZQP6igY48mjGaoEjwhely97lserep0IFJifBH4YdKvwH5eMLniy3kig2HQoBNR8EkZpDjowxwTJcmbg==}
+ axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -1413,18 +1558,6 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
- bcp-47-match@2.0.3:
- resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==}
-
- bcp-47-normalize@2.3.0:
- resolution: {integrity: sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==}
-
- bcp-47@2.1.1:
- resolution: {integrity: sha512-KLw+H/gd2p4zly1X7Yh/qziuyae5/w/QFnvTng9eZL5fvszL7Whl3MBoWF8yxL7ksUjBfOD+OxkytiqbBpG+Fw==}
-
- bcrypt-pbkdf@1.0.2:
- resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
-
better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
@@ -1433,6 +1566,9 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
+ boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+
brace-expansion@1.1.15:
resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==}
@@ -1461,9 +1597,6 @@ packages:
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
engines: {node: '>= 0.8'}
- cacheable@2.5.0:
- resolution: {integrity: sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==}
-
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
@@ -1471,9 +1604,6 @@ packages:
caniuse-lite@1.0.30001800:
resolution: {integrity: sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==}
- caseless@0.12.0:
- resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
-
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -1518,6 +1648,10 @@ packages:
ci-env@1.17.0:
resolution: {integrity: sha512-NtTjhgSEqv4Aj90TUYHQLxHdnCPXnjdtuGG1X8lTfp/JqeXTdw0FTWl/vUAPuvbWZTF8QVpv6ASe/XacE+7R2A==}
+ ci-info@4.4.0:
+ resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==}
+ engines: {node: '>=8'}
+
clean-css-cli@5.6.3:
resolution: {integrity: sha512-MUAta8pEqA/d2DKQwtZU5nm0Og8TCyAglOx3GlWwjhGdKBwY4kVF6E5M6LU/jmmuswv+HbYqG/dKKkq5p1dD0A==}
engines: {node: '>= 10.12.0'}
@@ -1541,6 +1675,13 @@ packages:
resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==}
engines: {node: '>=20'}
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
+ collapse-white-space@2.1.0:
+ resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -1555,12 +1696,8 @@ packages:
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
- commander@10.0.1:
- resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
- engines: {node: '>=14'}
-
- commander@11.0.0:
- resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==}
+ commander@11.1.0:
+ resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
commander@12.1.0:
@@ -1590,6 +1727,10 @@ packages:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
+ common-ancestor-path@2.0.0:
+ resolution: {integrity: sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==}
+ engines: {node: '>= 18'}
+
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -1604,15 +1745,19 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie-es@1.2.3:
+ resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==}
+
+ cookie@1.1.1:
+ resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
+ engines: {node: '>=18'}
+
core-js-pure@3.49.0:
resolution: {integrity: sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==}
core-js@3.49.0:
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
- core-util-is@1.0.2:
- resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
-
countup.js@2.10.1:
resolution: {integrity: sha512-UHW/BsPDgVZfN919D4iu2HPv+jJxZUuaR3EhT0ScFZaD446GiQtkMTgOnOyJXdA2AewdlyUk9UvERlTHTbVpcw==}
@@ -1629,24 +1774,34 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ crossws@0.3.5:
+ resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
+
+ css-select@5.2.2:
+ resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==}
+
+ css-tree@2.2.1:
+ resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
+ css-tree@3.2.1:
+ resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
+
+ css-what@6.2.2:
+ resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
+ engines: {node: '>= 6'}
+
+ csso@5.0.5:
+ resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
+ engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
+
custom-event-polyfill@1.0.7:
resolution: {integrity: sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==}
- dashdash@1.14.1:
- resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
- engines: {node: '>=0.10'}
-
dataloader@1.4.0:
resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==}
- debug@2.6.9:
- resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -1663,6 +1818,9 @@ packages:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
+ defu@6.1.7:
+ resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
+
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -1670,10 +1828,6 @@ packages:
delegate@3.2.0:
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
- depd@2.0.0:
- resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
- engines: {node: '>= 0.8'}
-
dependency-graph@1.0.0:
resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==}
engines: {node: '>=4'}
@@ -1682,6 +1836,9 @@ packages:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
+ destr@2.0.5:
+ resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
+
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
@@ -1693,25 +1850,32 @@ packages:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ devalue@5.8.1:
+ resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==}
+
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+ diff@8.0.4:
+ resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
+ engines: {node: '>=0.3.1'}
+
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
- dom-serializer@1.4.1:
- resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+ dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
domelementtype@2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
- domhandler@4.3.1:
- resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+ domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
- domutils@2.8.0:
- resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+ domutils@3.2.2:
+ resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
@@ -1723,6 +1887,10 @@ packages:
dropzone@6.0.0-beta.2:
resolution: {integrity: sha512-k44yLuFFhRk53M8zP71FaaNzJYIzr99SKmpbO/oZKNslDjNXQsBTdfLs+iONd0U0L94zzlFzRnFdqbLcs7h9fQ==}
+ dset@3.1.4:
+ resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
+ engines: {node: '>=4'}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
@@ -1730,17 +1898,11 @@ packages:
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
- ecc-jsbn@0.1.2:
- resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
-
editorconfig@3.0.2:
resolution: {integrity: sha512-T0ix8GhtxyKVfUFEcvdNDt3YGqlwkFHbD4/5bgFUDgFmxhI/cSRAeJ87/Sz//Cq8Eam6JX/e23RkoFO71P7aAA==}
engines: {node: '>=20'}
hasBin: true
- ee-first@1.1.1:
- resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
-
electron-to-chromium@1.5.387:
resolution: {integrity: sha512-TaxwufTFDufvPEoXdhwVrA3UdFWBeWGkYoJ1K8ldF1xe6gKfth6iRNS5lTQ5JPNOHdGQm8PT1QYKUqFLCiUefQ==}
@@ -1750,10 +1912,6 @@ packages:
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
- encodeurl@2.0.0:
- resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
- engines: {node: '>= 0.8'}
-
end-of-stream@1.4.5:
resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
@@ -1761,13 +1919,6 @@ packages:
resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
engines: {node: '>=8.6'}
- entities@2.2.0:
- resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
-
- entities@3.0.1:
- resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
- engines: {node: '>=0.12'}
-
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -1776,10 +1927,6 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
- errno@1.0.0:
- resolution: {integrity: sha512-3zV5mFS1E8/1bPxt/B0xxzI1snsg3uSCIh6Zo1qKg6iMw93hzPANk9oBFzSFBFrwuVoQuE3rLoouAUfwOAj1wQ==}
- hasBin: true
-
error-ex@1.3.4:
resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
@@ -1802,6 +1949,12 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
+ esast-util-from-estree@2.0.0:
+ resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==}
+
+ esast-util-from-js@2.0.1:
+ resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
+
esbuild@0.28.1:
resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==}
engines: {node: '>=18'}
@@ -1811,31 +1964,41 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
- escape-html@1.0.3:
- resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
-
escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
- esm-import-transformer@3.0.5:
- resolution: {integrity: sha512-1GKLvfuMnnpI75l8c6sHoz0L3Z872xL5akGuBudgqTDPv4Vy6f2Ec7jEMKTxlqWl/3kSvNbHELeimJtnqgYniw==}
-
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
hasBin: true
+ estree-util-attach-comments@3.0.0:
+ resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==}
+
+ estree-util-build-jsx@3.0.1:
+ resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==}
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
+ estree-util-scope@1.0.0:
+ resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==}
+
+ estree-util-to-js@2.0.0:
+ resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==}
+
+ estree-util-visit@2.0.0:
+ resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==}
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
- etag@1.8.1:
- resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
- engines: {node: '>= 0.6'}
-
- evaluate-value@2.0.0:
- resolution: {integrity: sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==}
- engines: {node: '>= 8'}
+ eventemitter3@5.0.4:
+ resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==}
execa@1.0.0:
resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==}
@@ -1845,36 +2008,28 @@ packages:
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
engines: {node: '>=10'}
- expect-more@1.3.0:
- resolution: {integrity: sha512-HnXT5nJb9V3DMnr5RgA1TiKbu5kRaJ0GD1JkuhZvnr1Qe3HJq+ESnrcl/jmVUZ8Ycnl3Sp0OTYUhmO36d2+zow==}
-
expect-type@1.4.0:
resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
engines: {node: '>=12.0.0'}
- extend-shallow@2.0.1:
- resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
- engines: {node: '>=0.10.0'}
-
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
extendable-error@0.1.7:
resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
- extsprintf@1.3.0:
- resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
- engines: {'0': node >=0.6.0}
-
- fast-deep-equal@3.1.3:
- resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
-
fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
- fast-json-stable-stringify@2.1.0:
- resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ fast-string-truncated-width@3.0.3:
+ resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==}
+
+ fast-string-width@3.0.2:
+ resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==}
+
+ fast-wrap-ansi@0.2.2:
+ resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==}
fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
@@ -1888,18 +2043,10 @@ packages:
picomatch:
optional: true
- filesize@10.1.6:
- resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==}
- engines: {node: '>= 10.4.0'}
-
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
- finalhandler@1.3.2:
- resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==}
- engines: {node: '>= 0.8'}
-
find-unused-sass-variables@6.2.1:
resolution: {integrity: sha512-OUqVUadL/MO7H3FxMG7p4LZqbn78e/+MgcRqCKNXJksWe+J6VZ1l8EB76ilBBtVUMiARR3zc8d4soOuX1LLppA==}
engines: {node: '>=18'}
@@ -1909,14 +2056,12 @@ packages:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
- flat-cache@6.1.23:
- resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==}
-
flatpickr@4.6.13:
resolution: {integrity: sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==}
- flatted@3.4.2:
- resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
+ flattie@1.1.1:
+ resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==}
+ engines: {node: '>=8'}
follow-redirects@1.16.0:
resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
@@ -1927,12 +2072,12 @@ packages:
debug:
optional: true
- forever-agent@0.6.1:
- resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
+ fontace@0.4.1:
+ resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==}
- form-data@2.3.3:
- resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
- engines: {node: '>= 0.12'}
+ fontkitten@1.0.3:
+ resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
+ engines: {node: '>=20'}
form-data@4.0.6:
resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==}
@@ -1941,10 +2086,6 @@ packages:
fraction.js@5.3.4:
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
- fresh@2.0.0:
- resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
- engines: {node: '>= 0.8'}
-
fs-extra@11.3.6:
resolution: {integrity: sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==}
engines: {node: '>=14.14'}
@@ -2016,8 +2157,12 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
- getpass@0.1.7:
- resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
+ get-tsconfig@5.0.0-beta.4:
+ resolution: {integrity: sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==}
+ engines: {node: '>=20.20.0'}
+
+ github-slugger@2.0.0:
+ resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@@ -2045,22 +2190,12 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- gray-matter@4.0.3:
- resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
- engines: {node: '>=6.0'}
-
gzip-size@6.0.0:
resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
engines: {node: '>=10'}
- har-schema@2.0.0:
- resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
- engines: {node: '>=4'}
-
- har-validator@5.1.5:
- resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
- engines: {node: '>=6'}
- deprecated: this library is no longer supported
+ h3@1.15.11:
+ resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==}
has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
@@ -2078,25 +2213,45 @@ packages:
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
engines: {node: '>= 0.4'}
- hashery@1.5.1:
- resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==}
- engines: {node: '>=20'}
-
hasown@2.0.4:
resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
engines: {node: '>= 0.4'}
+ hast-util-from-html@2.0.3:
+ resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==}
+
+ hast-util-from-parse5@8.0.3:
+ resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
+
+ hast-util-is-element@3.0.0:
+ resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==}
+
+ hast-util-parse-selector@4.0.0:
+ resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
+
+ hast-util-raw@9.1.0:
+ resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}
+
+ hast-util-to-estree@3.1.3:
+ resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==}
+
hast-util-to-html@9.0.5:
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-to-parse5@8.0.1:
+ resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}
+
+ hast-util-to-text@4.0.2:
+ resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==}
+
hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
- hookified@1.15.1:
- resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==}
-
- hookified@2.2.0:
- resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==}
+ hastscript@9.0.1:
+ resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
hosted-git-info@2.8.9:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
@@ -2104,23 +2259,14 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-escaper@3.0.3:
+ resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
+
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
- htmlparser2@7.2.0:
- resolution: {integrity: sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==}
-
- http-equiv-refresh@2.0.1:
- resolution: {integrity: sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==}
- engines: {node: '>= 6'}
-
- http-errors@2.0.1:
- resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
- engines: {node: '>= 0.8'}
-
- http-signature@1.2.0:
- resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
- engines: {node: '>=0.8', npm: '>=1.3.7'}
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
hugerte@1.0.12:
resolution: {integrity: sha512-/JDCdJy1C83a7+RjlfWx6EjRvxqmmHFA5Pzcq8Y0ngdBESiC+2xa4ogsqnRPeadF04Cs95YfTd1SKquDdksjRw==}
@@ -2148,11 +2294,6 @@ packages:
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
- imageoptim-cli@3.1.9:
- resolution: {integrity: sha512-6XkOM1UJOB9Prt5NXwGxEgCkYWICcJkJ8CBRvxYvFyY8RVmkjiF7bbD90ekXU8mQyfJxPhYO0EVYqgyGFAclCw==}
- engines: {node: '>=18'}
- hasBin: true
-
imask@7.6.1:
resolution: {integrity: sha512-sJlIFM7eathUEMChTh9Mrfw/IgiWgJqBKq2VNbyXvBZ7ev/IlO6/KQTKlV/Fm+viQMLrFLG/zCuudrLIwgK2dg==}
engines: {npm: '>=4.0.0'}
@@ -2174,10 +2315,16 @@ packages:
resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
interpret@1.4.0:
resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
engines: {node: '>= 0.10'}
+ iron-webcrypto@1.2.1:
+ resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
+
is-alphabetical@2.0.1:
resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
@@ -2198,9 +2345,10 @@ packages:
is-decimal@2.0.1:
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
- is-extendable@0.1.1:
- resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
- engines: {node: '>=0.10.0'}
+ is-docker@4.0.0:
+ resolution: {integrity: sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==}
+ engines: {node: '>=20'}
+ hasBin: true
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
@@ -2217,13 +2365,14 @@ packages:
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
- is-json@2.0.1:
- resolution: {integrity: sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==}
-
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
is-stream@1.1.0:
resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==}
engines: {node: '>=0.10.0'}
@@ -2236,9 +2385,6 @@ packages:
resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
engines: {node: '>=4'}
- is-typedarray@1.0.0:
- resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
-
is-windows@1.0.2:
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
engines: {node: '>=0.10.0'}
@@ -2246,13 +2392,6 @@ packages:
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
- iso-639-1@3.1.6:
- resolution: {integrity: sha512-ZFar/L4ngX7wZh2QX+Fiftmuf0igWJsrJtfizrovWifF1gAWkfmRa5Z1m0LQZbm0hKCHRDYhLRSLFrSqNe4EJA==}
- engines: {node: '>=6.0'}
-
- isstream@0.1.2:
- resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
-
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
@@ -2292,9 +2431,6 @@ packages:
resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==}
hasBin: true
- jsbn@0.1.1:
- resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
-
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -2303,15 +2439,6 @@ packages:
json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
- json-schema-traverse@0.4.1:
- resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
-
- json-schema@0.4.0:
- resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
-
- json-stringify-safe@5.0.1:
- resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
-
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
@@ -2333,17 +2460,9 @@ packages:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
- jsprim@1.4.2:
- resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
- engines: {node: '>=0.6.0'}
-
jsvectormap@1.7.0:
resolution: {integrity: sha512-8VmL3Uuen08Es9xb2N6Wdc32TrQDGPXYCIdTB126jAhTJsYd/4r4Mc63VQA3qHxG0p4zeCI8sFO5XRsdjljMJg==}
- junk@3.1.0:
- resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==}
- engines: {node: '>=8'}
-
just-extend@5.1.1:
resolution: {integrity: sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==}
@@ -2351,17 +2470,6 @@ packages:
resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==}
hasBin: true
- keyv@5.6.0:
- resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==}
-
- kind-of@6.0.3:
- resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
- engines: {node: '>=0.10.0'}
-
- kleur@4.1.5:
- resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
- engines: {node: '>=6'}
-
lightningcss-android-arm64@1.32.0:
resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
engines: {node: '>= 12.0.0'}
@@ -2446,14 +2554,6 @@ packages:
linkify-it@5.0.2:
resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==}
- liquidjs@10.27.1:
- resolution: {integrity: sha512-ylE+1q2kSef1UxAyxqbyuWM3FRWS1v48JK1Y3CoW3bD6TSNXZh0+GsVnihujEpKyR+Jejx2aRAFfC3AHm9rElg==}
- engines: {node: '>=16'}
- hasBin: true
-
- list-to-array@1.1.0:
- resolution: {integrity: sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==}
-
list.js@2.3.1:
resolution: {integrity: sha512-jnmm7DYpKtH3DxtO1E2VNCC9Gp7Wrp/FWA2JxQrZUhVJ2RCQBd57pCN6W5w6jpsfWZV0PCAbTX2NOPgyFeeZZg==}
engines: {node: ^6.0 || ^8.0 || ^10.0 || ^12.0 || >=14}
@@ -2477,6 +2577,9 @@ packages:
lodash@4.18.1:
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
lru-cache@11.5.1:
resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==}
engines: {node: 20 || >=22}
@@ -2484,10 +2587,6 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
- luxon@3.7.2:
- resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
- engines: {node: '>=12'}
-
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -2498,6 +2597,10 @@ packages:
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
engines: {node: '>=10'}
+ markdown-extensions@2.0.0:
+ resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==}
+ engines: {node: '>=16'}
+
markdown-it@14.2.0:
resolution: {integrity: sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==}
hasBin: true
@@ -2506,6 +2609,9 @@ packages:
resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==}
hasBin: true
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
markdownlint-cli@0.49.0:
resolution: {integrity: sha512-vS5tWq5W91Gg33LD4pyAaXPclnz/sRvo6/RGOyDQjQ3eds2DkK6H4szUuE0M9TiRB/u/VBx1gtd9Ktrtx5WlSA==}
engines: {node: '>=22'}
@@ -2519,9 +2625,63 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-definitions@6.0.0:
+ resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
+
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.3:
+ resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdx@3.0.0:
+ resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
mdast-util-to-hast@13.2.1:
resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
+ mdn-data@2.0.28:
+ resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
+
+ mdn-data@2.27.1:
+ resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==}
+
mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
@@ -2544,18 +2704,48 @@ packages:
micromark-extension-gfm-footnote@2.1.0:
resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
micromark-extension-gfm-table@2.1.1:
resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
micromark-extension-math@3.1.0:
resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==}
+ micromark-extension-mdx-expression@3.0.1:
+ resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==}
+
+ micromark-extension-mdx-jsx@3.0.2:
+ resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==}
+
+ micromark-extension-mdx-md@2.0.0:
+ resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==}
+
+ micromark-extension-mdxjs@3.0.0:
+ resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==}
+
micromark-factory-destination@2.0.1:
resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
micromark-factory-label@2.0.1:
resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+ micromark-factory-mdx-expression@2.0.3:
+ resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==}
+
micromark-factory-space@2.0.1:
resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
@@ -2580,9 +2770,15 @@ packages:
micromark-util-decode-numeric-character-reference@2.0.2:
resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
micromark-util-encode@2.0.1:
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+ micromark-util-events-to-acorn@2.0.3:
+ resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==}
+
micromark-util-html-tag-name@2.0.1:
resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
@@ -2615,23 +2811,10 @@ packages:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
- mime-db@1.54.0:
- resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
- engines: {node: '>= 0.6'}
-
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
- mime-types@3.0.2:
- resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
- engines: {node: '>=18'}
-
- mime@3.0.0:
- resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
- engines: {node: '>=10.0.0'}
- hasBin: true
-
mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
@@ -2650,15 +2833,6 @@ packages:
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
engines: {node: '>=16 || 14 >=14.17'}
- moo@0.5.2:
- resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==}
-
- moo@0.5.3:
- resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==}
-
- morphdom@2.7.8:
- resolution: {integrity: sha512-D/fR4xgGUyVRbdMGU6Nejea1RFzYxYtyurG4Fbv2Fi/daKlWKuXGLOdXtl+3eIwL110cI2hz1ZojGICjjFLgTg==}
-
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -2667,9 +2841,6 @@ packages:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
- ms@2.0.0:
- resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
-
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -2678,6 +2849,10 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ neotraverse@0.6.18:
+ resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==}
+ engines: {node: '>= 10'}
+
next@16.2.10:
resolution: {integrity: sha512-2som5AVXb3kE6Yjine3/mNbBayYF58eguBWIVVUdr1y/L426xyVEgYxgBG+1QC34P2x5E+tcDup6XkuOAX3dCA==}
engines: {node: '>=20.9.0'}
@@ -2702,9 +2877,15 @@ packages:
nice-try@1.0.5:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
+ nlcst-to-string@4.0.0:
+ resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+ node-fetch-native@1.6.7:
+ resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
+
node-fetch@2.7.0:
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
engines: {node: 4.x || >=6.0.0}
@@ -2714,13 +2895,13 @@ packages:
encoding:
optional: true
+ node-mock-http@1.0.4:
+ resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==}
+
node-releases@2.0.50:
resolution: {integrity: sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==}
engines: {node: '>=18'}
- node-retrieve-globals@6.0.1:
- resolution: {integrity: sha512-j0DeFuZ/Wg3VlklfbxUgZF/mdHMTEiEipBb3q0SpMMbHaV3AVfoUQF8UGxh1s/yjqO0TgRZd4Pi/x2yRqoQ4Eg==}
-
nodemon@3.1.14:
resolution: {integrity: sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==}
engines: {node: '>=10'}
@@ -2749,26 +2930,18 @@ packages:
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
engines: {node: '>=8'}
- nunjucks@3.2.4:
- resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==}
- engines: {node: '>= 6.9.0'}
- hasBin: true
- peerDependencies:
- chokidar: ^3.3.0
- peerDependenciesMeta:
- chokidar:
- optional: true
-
- oauth-sign@0.9.0:
- resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
+ nth-check@2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
obug@2.1.3:
resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==}
engines: {node: '>=12.20.0'}
- on-finished@2.4.1:
- resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
- engines: {node: '>= 0.8'}
+ ofetch@1.5.1:
+ resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==}
+
+ ohash@2.0.11:
+ resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@@ -2798,6 +2971,10 @@ packages:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
+ p-limit@7.3.0:
+ resolution: {integrity: sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==}
+ engines: {node: '>=20'}
+
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@@ -2806,6 +2983,14 @@ packages:
resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
engines: {node: '>=6'}
+ p-queue@9.3.1:
+ resolution: {integrity: sha512-POWdiIPmsUPGwb4FeQ4OBg46aqmcInSWe45CKDsGHiOBiVQM9chqfQTuqhuTzcg2Vz9faTI65at0KkVyVEiCHw==}
+ engines: {node: '>=20'}
+
+ p-timeout@7.0.1:
+ resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==}
+ engines: {node: '>=20'}
+
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -2813,6 +2998,9 @@ packages:
package-manager-detector@0.2.11:
resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
+ package-manager-detector@1.7.0:
+ resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==}
+
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
@@ -2820,12 +3008,11 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
- parse-srcset@1.0.2:
- resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
+ parse-latin@7.0.0:
+ resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==}
- parseurl@1.3.3:
- resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
- engines: {node: '>= 0.8'}
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
@@ -2857,8 +3044,8 @@ packages:
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
- performance-now@2.1.0:
- resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
+ piccolore@0.1.3:
+ resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -2889,9 +3076,6 @@ packages:
engines: {node: '>=18'}
hasBin: true
- please-upgrade-node@3.2.0:
- resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==}
-
plyr@3.8.4:
resolution: {integrity: sha512-DrzLbK9Wol3zeiuZCleD9aUOl0KAaBHR9H6WVVVYPZ4Ya+LYxUFTgSF1jooHcMQCv96Ws96wCaZzIoP3bES8pQ==}
@@ -2949,24 +3133,6 @@ packages:
resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==}
engines: {node: ^10 || ^12 || >=14}
- posthtml-match-helper@2.0.3:
- resolution: {integrity: sha512-p9oJgTdMF2dyd7WE54QI1LvpBIkNkbSiiECKezNnDVYhGhD1AaOnAkw0Uh0y5TW+OHO8iBdSqnd8Wkpb6iUqmw==}
- engines: {node: '>=18'}
- peerDependencies:
- posthtml: ^0.16.6
-
- posthtml-parser@0.11.0:
- resolution: {integrity: sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==}
- engines: {node: '>=12'}
-
- posthtml-render@3.0.0:
- resolution: {integrity: sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==}
- engines: {node: '>=12'}
-
- posthtml@0.16.7:
- resolution: {integrity: sha512-7Hc+IvlQ7hlaIfQFZnxlRl0jnpWq2qwibORBhQYIb0QbNtuicc5ZxvKkVT71HJ4Py1wSZ/3VR1r8LfkCtoCzhw==}
- engines: {node: '>=12.0.0'}
-
preact@10.12.1:
resolution: {integrity: sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==}
@@ -2980,9 +3146,10 @@ packages:
engines: {node: '>=14'}
hasBin: true
- pretty-bytes@5.6.0:
- resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
- engines: {node: '>=6'}
+ prettier@3.9.5:
+ resolution: {integrity: sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==}
+ engines: {node: '>=14'}
+ hasBin: true
pretty-format@30.4.1:
resolution: {integrity: sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==}
@@ -2992,6 +3159,14 @@ packages:
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
engines: {node: '>= 0.8'}
+ prismjs@1.30.0:
+ resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==}
+ engines: {node: '>=6'}
+
+ process-ancestry@0.1.0:
+ resolution: {integrity: sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==}
+ engines: {node: '>=18.0.0'}
+
property-information@7.2.0:
resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==}
@@ -3001,12 +3176,6 @@ packages:
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
- prr@1.0.1:
- resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
-
- psl@1.15.0:
- resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
-
pstree.remy@1.1.8:
resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==}
@@ -3017,27 +3186,14 @@ packages:
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
engines: {node: '>=6'}
- punycode@2.3.1:
- resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
- engines: {node: '>=6'}
-
- qified@0.10.1:
- resolution: {integrity: sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==}
- engines: {node: '>=20'}
-
- qs@6.5.5:
- resolution: {integrity: sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==}
- engines: {node: '>=0.6'}
-
quansync@0.2.11:
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
- range-parser@1.3.0:
- resolution: {integrity: sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==}
- engines: {node: '>= 0.6'}
+ radix3@1.1.2:
+ resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
rangetouch@2.0.1:
resolution: {integrity: sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==}
@@ -3084,6 +3240,20 @@ packages:
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
engines: {node: '>= 0.10'}
+ recma-build-jsx@1.0.0:
+ resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
+
+ recma-jsx@1.0.1:
+ resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ recma-parse@1.0.0:
+ resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==}
+
+ recma-stringify@1.0.0:
+ resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
+
regex-recursion@6.0.2:
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
@@ -3093,10 +3263,33 @@ packages:
regex@6.1.0:
resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==}
- request@2.88.2:
- resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
- engines: {node: '>= 6'}
- deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
+ rehype-raw@7.0.0:
+ resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
+
+ rehype-recma@1.0.0:
+ resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==}
+
+ rehype-stringify@10.0.1:
+ resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==}
+
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-mdx@3.1.1:
+ resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-smartypants@3.0.2:
+ resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==}
+ engines: {node: '>=16.0.0'}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
@@ -3106,11 +3299,26 @@ packages:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
resolve@1.22.12:
resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
engines: {node: '>= 0.4'}
hasBin: true
+ retext-latin@4.0.0:
+ resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==}
+
+ retext-smartypants@6.2.0:
+ resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==}
+
+ retext-stringify@4.0.0:
+ resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==}
+
+ retext@9.0.0:
+ resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -3135,9 +3343,6 @@ packages:
rxjs@7.8.2:
resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==}
- safe-buffer@5.2.1:
- resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
-
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
@@ -3158,19 +3363,19 @@ packages:
engines: {node: '>=20.19.0'}
hasBin: true
+ satteri@0.9.5:
+ resolution: {integrity: sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w==}
+
+ sax@1.6.0:
+ resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==}
+ engines: {node: '>=11.0.0'}
+
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
- section-matter@1.0.0:
- resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
- engines: {node: '>=4'}
-
select@1.1.2:
resolution: {integrity: sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==}
- semver-compare@1.0.0:
- resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
-
semver@5.7.2:
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
hasBin: true
@@ -3184,13 +3389,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- send@1.2.1:
- resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
- engines: {node: '>= 18'}
-
- setprototypeof@1.2.0:
- resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
-
sharp@0.34.5:
resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -3254,6 +3452,9 @@ packages:
resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
engines: {node: '>=18'}
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -3262,10 +3463,6 @@ packages:
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
engines: {node: '>=14.16'}
- slugify@1.6.9:
- resolution: {integrity: sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==}
- engines: {node: '>=8.0.0'}
-
smol-toml@1.6.1:
resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==}
engines: {node: '>= 18'}
@@ -3284,6 +3481,10 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ source-map@0.7.6:
+ resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
+ engines: {node: '>= 12'}
+
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
@@ -3305,25 +3506,12 @@ packages:
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
- sshpk@1.18.0:
- resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
- engines: {node: '>=0.10.0'}
- hasBin: true
-
- ssri@11.0.0:
- resolution: {integrity: sha512-aZpUoMN/Jj2MqA4vMCeiKGnc/8SuSyHbGSBdgFbZxP8OJGF/lFkIuElzPxsN0q8TQQ+prw3P4EDfB3TBHHgfXw==}
- engines: {node: ^16.14.0 || >=18.0.0}
-
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
star-rating.js@4.3.1:
resolution: {integrity: sha512-ynf+5eyXIn1HKCoKy5gc5Cmu8l1mvw+bYhogzEMLNqZ2AAh7MLP51ZmJnt98/AzO3DZ5h2i/RgkbVPlBhDGebQ==}
- statuses@2.0.2:
- resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
- engines: {node: '>= 0.8'}
-
std-env@4.1.0:
resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==}
@@ -3353,10 +3541,6 @@ packages:
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
engines: {node: '>=12'}
- strip-bom-string@1.0.0:
- resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
- engines: {node: '>=0.10.0'}
-
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
@@ -3373,6 +3557,12 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
styled-jsx@5.1.6:
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
engines: {node: '>= 12.0.0'}
@@ -3402,6 +3592,11 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ svgo@4.0.1:
+ resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==}
+ engines: {node: '>=16'}
+ hasBin: true
+
term-size@2.2.1:
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
engines: {node: '>=8'}
@@ -3417,9 +3612,16 @@ packages:
tiny-emitter@2.1.0:
resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==}
+ tiny-inflate@1.0.3:
+ resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+ tinyclip@0.1.15:
+ resolution: {integrity: sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A==}
+ engines: {node: ^16.14.0 || >= 17.3.0}
+
tinyexec@1.2.4:
resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==}
engines: {node: '>=18'}
@@ -3436,10 +3638,6 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
- toidentifier@1.0.1:
- resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
- engines: {node: '>=0.6'}
-
tom-select@2.6.1:
resolution: {integrity: sha512-d/1kngVOQTGcI/2pVDfDLYjtjUgSSd3fSgkYUpi0y+yRtQQu2kzljj3aUdqMfqc45cjPvDEpfDt/hSX4awDFTg==}
@@ -3451,10 +3649,6 @@ packages:
resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==}
hasBin: true
- tough-cookie@2.5.0:
- resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
- engines: {node: '>=0.8'}
-
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
@@ -3465,6 +3659,9 @@ packages:
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -3473,16 +3670,10 @@ packages:
engines: {node: '>=18.0.0'}
hasBin: true
- tunnel-agent@0.6.0:
- resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
-
turbo@2.10.3:
resolution: {integrity: sha512-uZIqzfgtWbyqu1Tqwdd0giRnPGgL0ejbcdF8eZLJhtTTVSrOgArZGzYeXTD6XNcc7ANgdhqex11Y9bHBeyiQLQ==}
hasBin: true
- tweetnacl@0.14.5:
- resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
-
type-fest@0.6.0:
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
engines: {node: '>=8'}
@@ -3502,21 +3693,51 @@ packages:
uc.micro@2.1.0:
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
+ ufo@1.6.4:
+ resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==}
+
+ ultrahtml@1.7.0:
+ resolution: {integrity: sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==}
+
+ uncrypto@0.1.3:
+ resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
+
undefsafe@2.0.5:
resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==}
undici-types@8.3.0:
resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==}
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unifont@0.7.4:
+ resolution: {integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==}
+
+ unist-util-find-after@5.0.0:
+ resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
+
unist-util-is@6.0.1:
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+ unist-util-modify-children@4.0.0:
+ resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==}
+
+ unist-util-position-from-estree@2.0.0:
+ resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
+
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+ unist-util-remove-position@5.0.0:
+ resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}
+
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+ unist-util-visit-children@3.0.0:
+ resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==}
+
unist-util-visit-parents@6.0.2:
resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
@@ -3531,9 +3752,67 @@ packages:
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
engines: {node: '>= 10.0.0'}
- unpipe@1.0.0:
- resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
- engines: {node: '>= 0.8'}
+ unstorage@1.17.5:
+ resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==}
+ peerDependencies:
+ '@azure/app-configuration': ^1.8.0
+ '@azure/cosmos': ^4.2.0
+ '@azure/data-tables': ^13.3.0
+ '@azure/identity': ^4.6.0
+ '@azure/keyvault-secrets': ^4.9.0
+ '@azure/storage-blob': ^12.26.0
+ '@capacitor/preferences': ^6 || ^7 || ^8
+ '@deno/kv': '>=0.9.0'
+ '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0
+ '@planetscale/database': ^1.19.0
+ '@upstash/redis': ^1.34.3
+ '@vercel/blob': '>=0.27.1'
+ '@vercel/functions': ^2.2.12 || ^3.0.0
+ '@vercel/kv': ^1 || ^2 || ^3
+ aws4fetch: ^1.0.20
+ db0: '>=0.2.1'
+ idb-keyval: ^6.2.1
+ ioredis: ^5.4.2
+ uploadthing: ^7.4.4
+ peerDependenciesMeta:
+ '@azure/app-configuration':
+ optional: true
+ '@azure/cosmos':
+ optional: true
+ '@azure/data-tables':
+ optional: true
+ '@azure/identity':
+ optional: true
+ '@azure/keyvault-secrets':
+ optional: true
+ '@azure/storage-blob':
+ optional: true
+ '@capacitor/preferences':
+ optional: true
+ '@deno/kv':
+ optional: true
+ '@netlify/blobs':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@upstash/redis':
+ optional: true
+ '@vercel/blob':
+ optional: true
+ '@vercel/functions':
+ optional: true
+ '@vercel/kv':
+ optional: true
+ aws4fetch:
+ optional: true
+ db0:
+ optional: true
+ idb-keyval:
+ optional: true
+ ioredis:
+ optional: true
+ uploadthing:
+ optional: true
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
@@ -3541,26 +3820,14 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
- uri-js@4.4.1:
- resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
-
url-polyfill@1.1.14:
resolution: {integrity: sha512-p4f3TTAG6ADVF3mwbXw7hGw+QJyw5CnNGvYh5fCuQQZIiuKUswqcznyV3pGDP9j0TSmC4UvRKm8kl1QsX1diiQ==}
- urlpattern-polyfill@10.1.0:
- resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==}
-
- uuid@3.4.0:
- resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
- deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
- hasBin: true
-
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
- verror@1.10.0:
- resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
- engines: {'0': node >=0.6.0}
+ vfile-location@5.0.3:
+ resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
vfile-message@4.0.3:
resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
@@ -3611,6 +3878,14 @@ packages:
yaml:
optional: true
+ vitefu@1.1.3:
+ resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==}
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
vitest@4.1.9:
resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==}
engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0}
@@ -3652,6 +3927,9 @@ packages:
jsdom:
optional: true
+ web-namespaces@2.0.1:
+ resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
+
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -3695,6 +3973,9 @@ packages:
utf-8-validate:
optional: true
+ xxhash-wasm@1.1.0:
+ resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -3723,150 +4004,148 @@ packages:
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==}
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
+ yocto-queue@1.2.2:
+ resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
+ engines: {node: '>=12.20'}
+
+ zod@4.4.3:
+ resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
+
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
snapshots:
- '@11ty/dependency-tree-esm@2.0.4':
- dependencies:
- '@11ty/eleventy-utils': 2.0.7
- acorn: 8.17.0
- dependency-graph: 1.0.0
- normalize-path: 3.0.0
-
- '@11ty/dependency-tree@4.0.2':
- dependencies:
- '@11ty/eleventy-utils': 2.0.7
-
- '@11ty/eleventy-dev-server@2.0.8(supports-color@5.5.0)':
- dependencies:
- '@11ty/eleventy-utils': 2.0.7
- chokidar: 3.6.0
- debug: 4.4.3(supports-color@5.5.0)
- finalhandler: 1.3.2
- mime: 3.0.0
- minimist: 1.2.8
- morphdom: 2.7.8
- please-upgrade-node: 3.2.0
- send: 1.2.1(supports-color@5.5.0)
- ssri: 11.0.0
- urlpattern-polyfill: 10.1.0
- ws: 8.21.0
- transitivePeerDependencies:
- - bufferutil
- - supports-color
- - utf-8-validate
-
- '@11ty/eleventy-plugin-bundle@3.0.7(posthtml@0.16.7)(supports-color@5.5.0)':
- dependencies:
- '@11ty/eleventy-utils': 2.0.7
- debug: 4.4.3(supports-color@5.5.0)
- posthtml-match-helper: 2.0.3(posthtml@0.16.7)
- transitivePeerDependencies:
- - posthtml
- - supports-color
-
- '@11ty/eleventy-utils@2.0.7': {}
-
- '@11ty/eleventy@3.1.2(supports-color@5.5.0)':
- dependencies:
- '@11ty/dependency-tree': 4.0.2
- '@11ty/dependency-tree-esm': 2.0.4
- '@11ty/eleventy-dev-server': 2.0.8(supports-color@5.5.0)
- '@11ty/eleventy-plugin-bundle': 3.0.7(posthtml@0.16.7)(supports-color@5.5.0)
- '@11ty/eleventy-utils': 2.0.7
- '@11ty/lodash-custom': 4.17.21
- '@11ty/posthtml-urls': 1.0.3
- '@11ty/recursive-copy': 4.0.4
- '@sindresorhus/slugify': 2.2.1
- bcp-47-normalize: 2.3.0
- chokidar: 3.6.0
- debug: 4.4.3(supports-color@5.5.0)
- dependency-graph: 1.0.0
- entities: 6.0.1
- filesize: 10.1.6
- gray-matter: 4.0.3
- iso-639-1: 3.1.6
- js-yaml: 4.3.0
- kleur: 4.1.5
- liquidjs: 10.27.1
- luxon: 3.7.2
- markdown-it: 14.3.0
- minimist: 1.2.8
- moo: 0.5.3
- node-retrieve-globals: 6.0.1
- nunjucks: 3.2.4(chokidar@3.6.0)
- picomatch: 4.0.5
- please-upgrade-node: 3.2.0
- posthtml: 0.16.7
- posthtml-match-helper: 2.0.3(posthtml@0.16.7)
- semver: 7.8.5
- slugify: 1.6.9
- tinyglobby: 0.2.17
- transitivePeerDependencies:
- - bufferutil
- - supports-color
- - utf-8-validate
-
- '@11ty/eleventy@3.1.6(supports-color@5.5.0)':
- dependencies:
- '@11ty/dependency-tree': 4.0.2
- '@11ty/dependency-tree-esm': 2.0.4
- '@11ty/eleventy-dev-server': 2.0.8(supports-color@5.5.0)
- '@11ty/eleventy-plugin-bundle': 3.0.7(posthtml@0.16.7)(supports-color@5.5.0)
- '@11ty/eleventy-utils': 2.0.7
- '@11ty/lodash-custom': 4.17.21
- '@11ty/posthtml-urls': 1.0.3
- '@11ty/recursive-copy': 4.0.4
- '@sindresorhus/slugify': 2.2.1
- bcp-47-normalize: 2.3.0
- chokidar: 3.6.0
- debug: 4.4.3(supports-color@5.5.0)
- dependency-graph: 1.0.0
- entities: 6.0.1
- filesize: 10.1.6
- gray-matter: 4.0.3
- iso-639-1: 3.1.6
- js-yaml: 4.3.0
- kleur: 4.1.5
- liquidjs: 10.27.1
- luxon: 3.7.2
- markdown-it: 14.3.0
- minimist: 1.2.8
- moo: 0.5.2
- node-retrieve-globals: 6.0.1
- nunjucks: 3.2.4(chokidar@3.6.0)
- picomatch: 4.0.5
- please-upgrade-node: 3.2.0
- posthtml: 0.16.7
- posthtml-match-helper: 2.0.3(posthtml@0.16.7)
- semver: 7.8.5
- slugify: 1.6.9
- tinyglobby: 0.2.17
- transitivePeerDependencies:
- - bufferutil
- - supports-color
- - utf-8-validate
-
- '@11ty/lodash-custom@4.17.21': {}
-
- '@11ty/posthtml-urls@1.0.3':
- dependencies:
- evaluate-value: 2.0.0
- http-equiv-refresh: 2.0.1
- list-to-array: 1.1.0
- parse-srcset: 1.0.2
-
- '@11ty/recursive-copy@4.0.4':
- dependencies:
- errno: 1.0.0
- junk: 3.1.0
- minimatch: 3.1.5
- slash: 3.0.0
-
'@adobe/css-tools@4.5.0': {}
+ '@astrojs/compiler-binding-darwin-arm64@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-darwin-x64@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-linux-arm64-gnu@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-linux-arm64-musl@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-linux-x64-gnu@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-linux-x64-musl@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-wasm32-wasi@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
+ dependencies:
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ optional: true
+
+ '@astrojs/compiler-binding-win32-arm64-msvc@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding-win32-x64-msvc@0.3.1':
+ optional: true
+
+ '@astrojs/compiler-binding@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
+ optionalDependencies:
+ '@astrojs/compiler-binding-darwin-arm64': 0.3.1
+ '@astrojs/compiler-binding-darwin-x64': 0.3.1
+ '@astrojs/compiler-binding-linux-arm64-gnu': 0.3.1
+ '@astrojs/compiler-binding-linux-arm64-musl': 0.3.1
+ '@astrojs/compiler-binding-linux-x64-gnu': 0.3.1
+ '@astrojs/compiler-binding-linux-x64-musl': 0.3.1
+ '@astrojs/compiler-binding-wasm32-wasi': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ '@astrojs/compiler-binding-win32-arm64-msvc': 0.3.1
+ '@astrojs/compiler-binding-win32-x64-msvc': 0.3.1
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
+ '@astrojs/compiler-rs@0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
+ dependencies:
+ '@astrojs/compiler-binding': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
+ '@astrojs/internal-helpers@0.10.1':
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ js-yaml: 4.3.0
+ picomatch: 4.0.5
+ retext-smartypants: 6.2.0
+ shiki: 4.3.1
+ smol-toml: 1.6.1
+ unified: 11.0.5
+
+ '@astrojs/markdown-remark@7.2.1':
+ dependencies:
+ '@astrojs/internal-helpers': 0.10.1
+ '@astrojs/prism': 4.0.2
+ github-slugger: 2.0.0
+ hast-util-from-html: 2.0.3
+ hast-util-to-text: 4.0.2
+ mdast-util-definitions: 6.0.0
+ rehype-raw: 7.0.0
+ rehype-stringify: 10.0.1
+ remark-gfm: 4.0.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ remark-smartypants: 3.0.2
+ unified: 11.0.5
+ unist-util-remove-position: 5.0.0
+ unist-util-visit: 5.1.0
+ unist-util-visit-parents: 6.0.2
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/markdown-satteri@0.3.4':
+ dependencies:
+ '@astrojs/internal-helpers': 0.10.1
+ '@astrojs/prism': 4.0.2
+ github-slugger: 2.0.0
+ hast-util-from-html: 2.0.3
+ satteri: 0.9.5
+
+ '@astrojs/mdx@7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))':
+ dependencies:
+ '@astrojs/internal-helpers': 0.10.1
+ '@astrojs/markdown-remark': 7.2.1
+ '@mdx-js/mdx': 3.1.1
+ acorn: 8.17.0
+ astro: 7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ es-module-lexer: 2.3.0
+ estree-util-visit: 2.0.0
+ hast-util-to-html: 9.0.5
+ piccolore: 0.1.3
+ rehype-raw: 7.0.0
+ remark-gfm: 4.0.1
+ remark-smartypants: 3.0.2
+ source-map: 0.7.6
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ optionalDependencies:
+ '@astrojs/markdown-satteri': 0.3.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@astrojs/prism@4.0.2':
+ dependencies:
+ prismjs: 1.30.0
+
+ '@astrojs/telemetry@3.3.3':
+ dependencies:
+ ci-info: 4.4.0
+ dset: 3.1.4
+ is-docker: 4.0.0
+ package-manager-detector: 1.7.0
+
'@babel/code-frame@7.29.7':
dependencies:
'@babel/helper-validator-identifier': 7.29.7
@@ -3975,17 +4254,40 @@ snapshots:
'@blazediff/core@1.9.1': {}
- '@cacheable/memory@2.2.0':
- dependencies:
- '@cacheable/utils': 2.5.0
- '@keyv/bigmap': 1.3.1(keyv@5.6.0)
- hookified: 1.15.1
- keyv: 5.6.0
+ '@bruits/satteri-darwin-arm64@0.9.5':
+ optional: true
- '@cacheable/utils@2.5.0':
+ '@bruits/satteri-darwin-x64@0.9.5':
+ optional: true
+
+ '@bruits/satteri-linux-arm64-gnu@0.9.5':
+ optional: true
+
+ '@bruits/satteri-linux-arm64-musl@0.9.5':
+ optional: true
+
+ '@bruits/satteri-linux-x64-gnu@0.9.5':
+ optional: true
+
+ '@bruits/satteri-linux-x64-musl@0.9.5':
+ optional: true
+
+ '@bruits/satteri-wasm32-wasi@0.9.5':
dependencies:
- hashery: 1.5.1
- keyv: 5.6.0
+ '@emnapi/core': 1.11.1
+ '@emnapi/runtime': 1.11.1
+ '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ optional: true
+
+ '@bruits/satteri-win32-arm64-msvc@0.9.5':
+ optional: true
+
+ '@bruits/satteri-win32-x64-msvc@0.9.5':
+ optional: true
+
+ '@capsizecss/unpack@4.0.1':
+ dependencies:
+ fontkitten: 1.0.3
'@changesets/apply-release-plan@7.1.1':
dependencies:
@@ -4145,9 +4447,17 @@ snapshots:
human-id: 4.2.0
prettier: 2.8.8
- '@docsearch/css@4.6.3': {}
+ '@clack/core@1.4.3':
+ dependencies:
+ fast-wrap-ansi: 0.2.2
+ sisteransi: 1.0.5
- '@docsearch/js@4.6.3': {}
+ '@clack/prompts@1.7.0':
+ dependencies:
+ '@clack/core': 1.4.3
+ fast-string-width: 3.0.2
+ fast-wrap-ansi: 0.2.2
+ sisteransi: 1.0.5
'@emnapi/core@1.11.1':
dependencies:
@@ -4411,14 +4721,6 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
- '@keyv/bigmap@1.3.1(keyv@5.6.0)':
- dependencies:
- hashery: 1.5.1
- hookified: 1.15.1
- keyv: 5.6.0
-
- '@keyv/serialize@1.1.1': {}
-
'@manypkg/find-root@1.1.0':
dependencies:
'@babel/runtime': 7.29.7
@@ -4435,6 +4737,36 @@ snapshots:
globby: 11.1.0
read-yaml-file: 1.1.0
+ '@mdx-js/mdx@3.1.1':
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdx': 2.0.14
+ acorn: 8.17.0
+ collapse-white-space: 2.1.0
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-util-scope: 1.0.0
+ estree-walker: 3.0.3
+ hast-util-to-jsx-runtime: 2.3.6
+ markdown-extensions: 2.0.0
+ recma-build-jsx: 1.0.0
+ recma-jsx: 1.0.1(acorn@8.17.0)
+ recma-stringify: 1.0.0
+ rehype-recma: 1.0.0
+ remark-mdx: 3.1.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ source-map: 0.7.6
+ unified: 11.0.5
+ unist-util-position-from-estree: 2.0.0
+ unist-util-stringify-position: 4.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
+
'@melloware/coloris@0.25.0': {}
'@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)':
@@ -4490,6 +4822,8 @@ snapshots:
'@orchidjs/unicode-variants@1.1.2': {}
+ '@oslojs/encoding@1.1.0': {}
+
'@oxc-project/types@0.138.0': {}
'@parcel/watcher-android-arm64@2.5.6':
@@ -4608,6 +4942,12 @@ snapshots:
'@rolldown/pluginutils@1.0.1': {}
+ '@rollup/pluginutils@5.4.0':
+ dependencies:
+ '@types/estree': 1.0.9
+ estree-walker: 2.0.2
+ picomatch: 4.0.5
+
'@shikijs/core@4.3.1':
dependencies:
'@shikijs/primitive': 4.3.1
@@ -4650,15 +4990,6 @@ snapshots:
'@sinclair/typebox@0.34.52': {}
- '@sindresorhus/slugify@2.2.1':
- dependencies:
- '@sindresorhus/transliterate': 1.6.0
- escape-string-regexp: 5.0.0
-
- '@sindresorhus/transliterate@1.6.0':
- dependencies:
- escape-string-regexp: 5.0.0
-
'@standard-schema/spec@1.1.0': {}
'@swc/helpers@0.2.14': {}
@@ -4667,8 +4998,6 @@ snapshots:
dependencies:
tslib: 2.8.1
- '@tabler/icons@3.44.0': {}
-
'@turbo/darwin-64@2.10.3':
optional: true
@@ -4703,6 +5032,10 @@ snapshots:
'@types/deep-eql@4.0.2': {}
+ '@types/estree-jsx@1.0.5':
+ dependencies:
+ '@types/estree': 1.0.9
+
'@types/estree@1.0.9': {}
'@types/hast@3.0.4':
@@ -4715,14 +5048,24 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ '@types/mdx@2.0.14': {}
+
'@types/ms@2.1.0': {}
+ '@types/nlcst@2.0.3':
+ dependencies:
+ '@types/unist': 3.0.3
+
'@types/node@12.20.55': {}
'@types/node@26.1.0':
dependencies:
undici-types: 8.3.0
+ '@types/node@26.1.1':
+ dependencies:
+ undici-types: 8.3.0
+
'@types/normalize-package-data@2.4.4': {}
'@types/unist@2.0.11': {}
@@ -4818,11 +5161,9 @@ snapshots:
convert-source-map: 2.0.0
tinyrainbow: 3.1.0
- a-sync-waterfall@1.0.1: {}
-
abbrev@5.0.0: {}
- acorn-walk@8.3.5:
+ acorn-jsx@5.3.2(acorn@8.17.0):
dependencies:
acorn: 8.17.0
@@ -4830,12 +5171,9 @@ snapshots:
adm-zip@0.5.18: {}
- ajv@6.15.0:
+ am-i-vibing@0.4.0:
dependencies:
- fast-deep-equal: 3.1.3
- fast-json-stable-stringify: 2.1.0
- json-schema-traverse: 0.4.1
- uri-js: 4.4.1
+ process-ancestry: 0.1.0
ansi-colors@4.1.3: {}
@@ -4864,18 +5202,109 @@ snapshots:
argparse@2.0.1: {}
+ aria-query@5.3.2: {}
+
+ array-iterate@2.0.1: {}
+
array-union@2.1.0: {}
- asap@2.0.6: {}
-
- asn1@0.2.6:
- dependencies:
- safer-buffer: 2.1.2
-
- assert-plus@1.0.0: {}
-
assertion-error@2.0.1: {}
+ astring@1.9.0: {}
+
+ astro@7.1.1(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@types/node@26.1.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0):
+ dependencies:
+ '@astrojs/compiler-rs': 0.3.1(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)
+ '@astrojs/internal-helpers': 0.10.1
+ '@astrojs/markdown-satteri': 0.3.4
+ '@astrojs/telemetry': 3.3.3
+ '@capsizecss/unpack': 4.0.1
+ '@clack/prompts': 1.7.0
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.4.0
+ am-i-vibing: 0.4.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ ci-info: 4.4.0
+ clsx: 2.1.1
+ common-ancestor-path: 2.0.0
+ cookie: 1.1.1
+ devalue: 5.8.1
+ diff: 8.0.4
+ dset: 3.1.4
+ es-module-lexer: 2.3.0
+ esbuild: 0.28.1
+ flattie: 1.1.1
+ fontace: 0.4.1
+ get-tsconfig: 5.0.0-beta.4
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ js-yaml: 4.3.0
+ jsonc-parser: 3.3.1
+ magic-string: 0.30.21
+ magicast: 0.5.3
+ mrmime: 2.0.1
+ neotraverse: 0.6.18
+ obug: 2.1.3
+ p-limit: 7.3.0
+ p-queue: 9.3.1
+ package-manager-detector: 1.7.0
+ piccolore: 0.1.3
+ picomatch: 4.0.5
+ semver: 7.8.5
+ shiki: 4.3.1
+ smol-toml: 1.6.1
+ svgo: 4.0.1
+ tinyclip: 0.1.15
+ tinyexec: 1.2.4
+ tinyglobby: 0.2.17
+ ultrahtml: 1.7.0
+ unifont: 0.7.4
+ unstorage: 1.17.5
+ vite: 8.1.3(@types/node@26.1.1)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ vitefu: 1.1.3(vite@8.1.3(@types/node@26.1.1)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 22.0.0
+ zod: 4.4.3
+ optionalDependencies:
+ '@astrojs/markdown-remark': 7.2.1
+ sharp: 0.34.5
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - '@vitejs/devtools'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - terser
+ - tsx
+ - uploadthing
+ - yaml
+
asynckit@0.4.0: {}
autoprefixer@10.5.2(postcss@8.5.16):
@@ -4889,10 +5318,6 @@ snapshots:
autosize@6.0.1: {}
- aws-sign2@0.7.0: {}
-
- aws4@1.13.2: {}
-
axios@0.31.1:
dependencies:
follow-redirects: 1.16.0
@@ -4901,35 +5326,24 @@ snapshots:
transitivePeerDependencies:
- debug
+ axobject-query@4.1.0: {}
+
+ bail@2.0.2: {}
+
balanced-match@1.0.2: {}
balanced-match@4.0.4: {}
baseline-browser-mapping@2.10.42: {}
- bcp-47-match@2.0.3: {}
-
- bcp-47-normalize@2.3.0:
- dependencies:
- bcp-47: 2.1.1
- bcp-47-match: 2.0.3
-
- bcp-47@2.1.1:
- dependencies:
- is-alphabetical: 2.0.1
- is-alphanumerical: 2.0.1
- is-decimal: 2.0.1
-
- bcrypt-pbkdf@1.0.2:
- dependencies:
- tweetnacl: 0.14.5
-
better-path-resolve@1.0.0:
dependencies:
is-windows: 1.0.2
binary-extensions@2.3.0: {}
+ boolbase@1.0.0: {}
+
brace-expansion@1.1.15:
dependencies:
balanced-match: 1.0.2
@@ -4970,14 +5384,6 @@ snapshots:
bytes@3.1.2: {}
- cacheable@2.5.0:
- dependencies:
- '@cacheable/memory': 2.2.0
- '@cacheable/utils': 2.5.0
- hookified: 1.15.1
- keyv: 5.6.0
- qified: 0.10.1
-
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
@@ -4985,8 +5391,6 @@ snapshots:
caniuse-lite@1.0.30001800: {}
- caseless@0.12.0: {}
-
ccount@2.0.1: {}
chai@6.2.2: {}
@@ -5030,6 +5434,8 @@ snapshots:
ci-env@1.17.0: {}
+ ci-info@4.4.0: {}
+
clean-css-cli@5.6.3:
dependencies:
chokidar: 3.6.0
@@ -5061,6 +5467,10 @@ snapshots:
strip-ansi: 7.2.0
wrap-ansi: 9.0.2
+ clsx@2.1.1: {}
+
+ collapse-white-space@2.1.0: {}
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@@ -5073,9 +5483,7 @@ snapshots:
comma-separated-tokens@2.0.3: {}
- commander@10.0.1: {}
-
- commander@11.0.0: {}
+ commander@11.1.0: {}
commander@12.1.0: {}
@@ -5091,6 +5499,8 @@ snapshots:
commander@8.3.0: {}
+ common-ancestor-path@2.0.0: {}
+
concat-map@0.0.1: {}
concurrently@10.0.3:
@@ -5109,12 +5519,14 @@ snapshots:
convert-source-map@2.0.0: {}
+ cookie-es@1.2.3: {}
+
+ cookie@1.1.1: {}
+
core-js-pure@3.49.0: {}
core-js@3.49.0: {}
- core-util-is@1.0.2: {}
-
countup.js@2.10.1: {}
cross-env@10.1.0:
@@ -5136,18 +5548,38 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ crossws@0.3.5:
+ dependencies:
+ uncrypto: 0.1.3
+
+ css-select@5.2.2:
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.2.2
+ domhandler: 5.0.3
+ domutils: 3.2.2
+ nth-check: 2.1.1
+
+ css-tree@2.2.1:
+ dependencies:
+ mdn-data: 2.0.28
+ source-map-js: 1.2.1
+
+ css-tree@3.2.1:
+ dependencies:
+ mdn-data: 2.27.1
+ source-map-js: 1.2.1
+
+ css-what@6.2.2: {}
+
+ csso@5.0.5:
+ dependencies:
+ css-tree: 2.2.1
+
custom-event-polyfill@1.0.7: {}
- dashdash@1.14.1:
- dependencies:
- assert-plus: 1.0.0
-
dataloader@1.4.0: {}
- debug@2.6.9:
- dependencies:
- ms: 2.0.0
-
debug@4.4.3(supports-color@5.5.0):
dependencies:
ms: 2.1.3
@@ -5160,47 +5592,53 @@ snapshots:
deep-extend@0.6.0: {}
+ defu@6.1.7: {}
+
delayed-stream@1.0.0: {}
delegate@3.2.0: {}
- depd@2.0.0: {}
-
dependency-graph@1.0.0: {}
dequal@2.0.3: {}
+ destr@2.0.5: {}
+
detect-indent@6.1.0: {}
detect-it@4.0.1: {}
detect-libc@2.1.2: {}
+ devalue@5.8.1: {}
+
devlop@1.1.0:
dependencies:
dequal: 2.0.3
+ diff@8.0.4: {}
+
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
- dom-serializer@1.4.1:
+ dom-serializer@2.0.0:
dependencies:
domelementtype: 2.3.0
- domhandler: 4.3.1
- entities: 2.2.0
+ domhandler: 5.0.3
+ entities: 4.5.0
domelementtype@2.3.0: {}
- domhandler@4.3.1:
+ domhandler@5.0.3:
dependencies:
domelementtype: 2.3.0
- domutils@2.8.0:
+ domutils@3.2.2:
dependencies:
- dom-serializer: 1.4.1
+ dom-serializer: 2.0.0
domelementtype: 2.3.0
- domhandler: 4.3.1
+ domhandler: 5.0.3
dotenv@8.6.0: {}
@@ -5211,6 +5649,8 @@ snapshots:
'@swc/helpers': 0.2.14
just-extend: 5.1.1
+ dset@3.1.4: {}
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -5219,11 +5659,6 @@ snapshots:
duplexer@0.1.2: {}
- ecc-jsbn@0.1.2:
- dependencies:
- jsbn: 0.1.1
- safer-buffer: 2.1.2
-
editorconfig@3.0.2:
dependencies:
'@one-ini/wasm': 0.2.1
@@ -5231,16 +5666,12 @@ snapshots:
minimatch: 10.2.5
semver: 7.8.5
- ee-first@1.1.1: {}
-
electron-to-chromium@1.5.387: {}
emoji-regex@10.6.0: {}
emoji-regex@8.0.0: {}
- encodeurl@2.0.0: {}
-
end-of-stream@1.4.5:
dependencies:
once: 1.4.0
@@ -5250,18 +5681,10 @@ snapshots:
ansi-colors: 4.1.3
strip-ansi: 6.0.1
- entities@2.2.0: {}
-
- entities@3.0.1: {}
-
entities@4.5.0: {}
entities@6.0.1: {}
- errno@1.0.0:
- dependencies:
- prr: 1.0.1
-
error-ex@1.3.4:
dependencies:
is-arrayish: 0.2.1
@@ -5283,6 +5706,20 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.4
+ esast-util-from-estree@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ unist-util-position-from-estree: 2.0.0
+
+ esast-util-from-js@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ acorn: 8.17.0
+ esast-util-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
esbuild@0.28.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.28.1
@@ -5314,23 +5751,46 @@ snapshots:
escalade@3.2.0: {}
- escape-html@1.0.3: {}
-
escape-string-regexp@5.0.0: {}
- esm-import-transformer@3.0.5:
- dependencies:
- acorn: 8.17.0
-
esprima@4.0.1: {}
+ estree-util-attach-comments@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+
+ estree-util-build-jsx@3.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ estree-walker: 3.0.3
+
+ estree-util-is-identifier-name@3.0.0: {}
+
+ estree-util-scope@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ devlop: 1.1.0
+
+ estree-util-to-js@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ astring: 1.9.0
+ source-map: 0.7.6
+
+ estree-util-visit@2.0.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/unist': 3.0.3
+
+ estree-walker@2.0.2: {}
+
estree-walker@3.0.3:
dependencies:
'@types/estree': 1.0.9
- etag@1.8.1: {}
-
- evaluate-value@2.0.0: {}
+ eventemitter3@5.0.4: {}
execa@1.0.0:
dependencies:
@@ -5354,22 +5814,12 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
- expect-more@1.3.0: {}
-
expect-type@1.4.0: {}
- extend-shallow@2.0.1:
- dependencies:
- is-extendable: 0.1.1
-
extend@3.0.2: {}
extendable-error@0.1.7: {}
- extsprintf@1.3.0: {}
-
- fast-deep-equal@3.1.3: {}
-
fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -5378,7 +5828,15 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.8
- fast-json-stable-stringify@2.1.0: {}
+ fast-string-truncated-width@3.0.3: {}
+
+ fast-string-width@3.0.2:
+ dependencies:
+ fast-string-truncated-width: 3.0.3
+
+ fast-wrap-ansi@0.2.2:
+ dependencies:
+ fast-string-width: 3.0.2
fastq@1.20.1:
dependencies:
@@ -5388,24 +5846,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.5
- filesize@10.1.6: {}
-
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
- finalhandler@1.3.2:
- dependencies:
- debug: 2.6.9
- encodeurl: 2.0.0
- escape-html: 1.0.3
- on-finished: 2.4.1
- parseurl: 1.3.3
- statuses: 2.0.2
- unpipe: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
find-unused-sass-variables@6.2.1:
dependencies:
commander: 12.1.0
@@ -5420,25 +5864,19 @@ snapshots:
locate-path: 5.0.0
path-exists: 4.0.0
- flat-cache@6.1.23:
- dependencies:
- cacheable: 2.5.0
- flatted: 3.4.2
- hookified: 1.15.1
-
flatpickr@4.6.13: {}
- flatted@3.4.2: {}
+ flattie@1.1.1: {}
follow-redirects@1.16.0: {}
- forever-agent@0.6.1: {}
-
- form-data@2.3.3:
+ fontace@0.4.1:
dependencies:
- asynckit: 0.4.0
- combined-stream: 1.0.8
- mime-types: 2.1.35
+ fontkitten: 1.0.3
+
+ fontkitten@1.0.3:
+ dependencies:
+ tiny-inflate: 1.0.3
form-data@4.0.6:
dependencies:
@@ -5450,8 +5888,6 @@ snapshots:
fraction.js@5.3.4: {}
- fresh@2.0.0: {}
-
fs-extra@11.3.6:
dependencies:
graceful-fs: 4.2.11
@@ -5527,9 +5963,11 @@ snapshots:
get-stream@6.0.1: {}
- getpass@0.1.7:
+ get-tsconfig@5.0.0-beta.4:
dependencies:
- assert-plus: 1.0.0
+ resolve-pkg-maps: 1.0.0
+
+ github-slugger@2.0.0: {}
glob-parent@5.1.2:
dependencies:
@@ -5567,23 +6005,21 @@ snapshots:
graceful-fs@4.2.11: {}
- gray-matter@4.0.3:
- dependencies:
- js-yaml: 3.15.0
- kind-of: 6.0.3
- section-matter: 1.0.0
- strip-bom-string: 1.0.0
-
gzip-size@6.0.0:
dependencies:
duplexer: 0.1.2
- har-schema@2.0.0: {}
-
- har-validator@5.1.5:
+ h3@1.15.11:
dependencies:
- ajv: 6.15.0
- har-schema: 2.0.0
+ cookie-es: 1.2.3
+ crossws: 0.3.5
+ defu: 6.1.7
+ destr: 2.0.5
+ iron-webcrypto: 1.2.1
+ node-mock-http: 1.0.4
+ radix3: 1.1.2
+ ufo: 1.6.4
+ uncrypto: 0.1.3
has-flag@3.0.0: {}
@@ -5595,14 +6031,75 @@ snapshots:
dependencies:
has-symbols: 1.1.0
- hashery@1.5.1:
- dependencies:
- hookified: 1.15.1
-
hasown@2.0.4:
dependencies:
function-bind: 1.1.2
+ hast-util-from-html@2.0.3:
+ dependencies:
+ '@types/hast': 3.0.4
+ devlop: 1.1.0
+ hast-util-from-parse5: 8.0.3
+ parse5: 7.3.0
+ vfile: 6.0.3
+ vfile-message: 4.0.3
+
+ hast-util-from-parse5@8.0.3:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ hastscript: 9.0.1
+ property-information: 7.2.0
+ vfile: 6.0.3
+ vfile-location: 5.0.3
+ web-namespaces: 2.0.1
+
+ hast-util-is-element@3.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-parse-selector@4.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-raw@9.1.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ '@ungap/structured-clone': 1.3.2
+ hast-util-from-parse5: 8.0.3
+ hast-util-to-parse5: 8.0.1
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ parse5: 7.3.0
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-to-estree@3.1.3:
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-attach-comments: 3.0.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ zwitch: 2.0.4
+ transitivePeerDependencies:
+ - supports-color
+
hast-util-to-html@9.0.5:
dependencies:
'@types/hast': 3.0.4
@@ -5617,42 +6114,64 @@ snapshots:
stringify-entities: 4.0.4
zwitch: 2.0.4
+ hast-util-to-jsx-runtime@2.3.6:
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-parse5@8.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-to-text@4.0.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ hast-util-is-element: 3.0.0
+ unist-util-find-after: 5.0.0
+
hast-util-whitespace@3.0.0:
dependencies:
'@types/hast': 3.0.4
- hookified@1.15.1: {}
-
- hookified@2.2.0: {}
+ hastscript@9.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ hast-util-parse-selector: 4.0.0
+ property-information: 7.2.0
+ space-separated-tokens: 2.0.2
hosted-git-info@2.8.9: {}
html-escaper@2.0.2: {}
+ html-escaper@3.0.3: {}
+
html-void-elements@3.0.0: {}
- htmlparser2@7.2.0:
- dependencies:
- domelementtype: 2.3.0
- domhandler: 4.3.1
- domutils: 2.8.0
- entities: 3.0.1
-
- http-equiv-refresh@2.0.1: {}
-
- http-errors@2.0.1:
- dependencies:
- depd: 2.0.0
- inherits: 2.0.4
- setprototypeof: 1.2.0
- statuses: 2.0.2
- toidentifier: 1.0.1
-
- http-signature@1.2.0:
- dependencies:
- assert-plus: 1.0.0
- jsprim: 1.4.2
- sshpk: 1.18.0
+ http-cache-semantics@4.2.0: {}
hugerte@1.0.12: {}
@@ -5670,14 +6189,6 @@ snapshots:
ignore@7.0.5: {}
- imageoptim-cli@3.1.9:
- dependencies:
- chalk: 4.1.2
- commander: 11.0.0
- expect-more: 1.3.0
- globby: 11.1.0
- pretty-bytes: 5.6.0
-
imask@7.6.1:
dependencies:
'@babel/runtime-corejs3': 7.29.7
@@ -5695,8 +6206,12 @@ snapshots:
ini@4.1.3: {}
+ inline-style-parser@0.2.7: {}
+
interpret@1.4.0: {}
+ iron-webcrypto@1.2.1: {}
+
is-alphabetical@2.0.1: {}
is-alphanumerical@2.0.1:
@@ -5716,7 +6231,7 @@ snapshots:
is-decimal@2.0.1: {}
- is-extendable@0.1.1: {}
+ is-docker@4.0.0: {}
is-extglob@2.1.1: {}
@@ -5728,10 +6243,10 @@ snapshots:
is-hexadecimal@2.0.1: {}
- is-json@2.0.1: {}
-
is-number@7.0.0: {}
+ is-plain-obj@4.1.0: {}
+
is-stream@1.1.0: {}
is-stream@2.0.1: {}
@@ -5740,16 +6255,10 @@ snapshots:
dependencies:
better-path-resolve: 1.0.0
- is-typedarray@1.0.0: {}
-
is-windows@1.0.2: {}
isexe@2.0.0: {}
- iso-639-1@3.1.6: {}
-
- isstream@0.1.2: {}
-
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-report@3.0.1:
@@ -5795,18 +6304,10 @@ snapshots:
dependencies:
argparse: 2.0.1
- jsbn@0.1.1: {}
-
jsesc@3.1.0: {}
json-parse-even-better-errors@2.3.1: {}
- json-schema-traverse@0.4.1: {}
-
- json-schema@0.4.0: {}
-
- json-stringify-safe@5.0.1: {}
-
json5@2.2.3: {}
jsonc-parser@3.3.1: {}
@@ -5825,31 +6326,14 @@ snapshots:
jsonpointer@5.0.1: {}
- jsprim@1.4.2:
- dependencies:
- assert-plus: 1.0.0
- extsprintf: 1.3.0
- json-schema: 0.4.0
- verror: 1.10.0
-
jsvectormap@1.7.0: {}
- junk@3.1.0: {}
-
just-extend@5.1.1: {}
katex@0.16.47:
dependencies:
commander: 8.3.0
- keyv@5.6.0:
- dependencies:
- '@keyv/serialize': 1.1.1
-
- kind-of@6.0.3: {}
-
- kleur@4.1.5: {}
-
lightningcss-android-arm64@1.32.0:
optional: true
@@ -5907,12 +6391,6 @@ snapshots:
dependencies:
uc.micro: 2.1.0
- liquidjs@10.27.1:
- dependencies:
- commander: 10.0.1
-
- list-to-array@1.1.0: {}
-
list.js@2.3.1:
dependencies:
string-natural-compare: 2.0.3
@@ -5931,14 +6409,14 @@ snapshots:
lodash@4.18.1: {}
+ longest-streak@3.1.0: {}
+
lru-cache@11.5.1: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
- luxon@3.7.2: {}
-
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -5953,6 +6431,8 @@ snapshots:
dependencies:
semver: 7.8.5
+ markdown-extensions@2.0.0: {}
+
markdown-it@14.2.0:
dependencies:
argparse: 2.0.1
@@ -5971,6 +6451,8 @@ snapshots:
punycode.js: 2.3.1
uc.micro: 2.1.0
+ markdown-table@3.0.4: {}
+
markdownlint-cli@0.49.0(supports-color@5.5.0):
dependencies:
commander: 15.0.0
@@ -6004,6 +6486,147 @@ snapshots:
math-intrinsics@1.1.0: {}
+ mdast-util-definitions@6.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.1.0
+
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.3:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2(supports-color@5.5.0)
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0
+ mdast-util-gfm-strikethrough: 2.0.0
+ mdast-util-gfm-table: 2.0.0
+ mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx@3.0.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
mdast-util-to-hast@13.2.1:
dependencies:
'@types/hast': 3.0.4
@@ -6016,6 +6639,26 @@ snapshots:
unist-util-visit: 5.1.0
vfile: 6.0.3
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.1.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
+ mdn-data@2.0.28: {}
+
+ mdn-data@2.27.1: {}
+
mdurl@2.0.0: {}
merge-stream@2.0.0: {}
@@ -6069,6 +6712,15 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
micromark-extension-gfm-table@2.1.1:
dependencies:
devlop: 1.1.0
@@ -6077,6 +6729,29 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
micromark-extension-math@3.1.0:
dependencies:
'@types/katex': 0.16.8
@@ -6087,6 +6762,57 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
+ micromark-extension-mdx-expression@3.0.1:
+ dependencies:
+ '@types/estree': 1.0.9
+ devlop: 1.1.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdx-jsx@3.0.2:
+ dependencies:
+ '@types/estree': 1.0.9
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ micromark-factory-mdx-expression: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
+ micromark-extension-mdx-md@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-mdxjs-esm@3.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
+ micromark-extension-mdxjs@3.0.0:
+ dependencies:
+ acorn: 8.17.0
+ acorn-jsx: 5.3.2(acorn@8.17.0)
+ micromark-extension-mdx-expression: 3.0.1
+ micromark-extension-mdx-jsx: 3.0.2
+ micromark-extension-mdx-md: 2.0.0
+ micromark-extension-mdxjs-esm: 3.0.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
micromark-factory-destination@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@@ -6100,6 +6826,18 @@ snapshots:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.2
+ micromark-factory-mdx-expression@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-events-to-acorn: 2.0.3
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-position-from-estree: 2.0.0
+ vfile-message: 4.0.3
+
micromark-factory-space@2.0.1:
dependencies:
micromark-util-character: 2.1.1
@@ -6143,8 +6881,25 @@ snapshots:
dependencies:
micromark-util-symbol: 2.0.1
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
micromark-util-encode@2.0.1: {}
+ micromark-util-events-to-acorn@2.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ estree-util-visit: 2.0.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ vfile-message: 4.0.3
+
micromark-util-html-tag-name@2.0.1: {}
micromark-util-normalize-identifier@2.0.1:
@@ -6201,18 +6956,10 @@ snapshots:
mime-db@1.52.0: {}
- mime-db@1.54.0: {}
-
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
- mime-types@3.0.2:
- dependencies:
- mime-db: 1.54.0
-
- mime@3.0.0: {}
-
mimic-fn@2.1.0: {}
minimatch@10.2.5:
@@ -6227,22 +6974,16 @@ snapshots:
minipass@7.1.3: {}
- moo@0.5.2: {}
-
- moo@0.5.3: {}
-
- morphdom@2.7.8: {}
-
mri@1.2.0: {}
mrmime@2.0.1: {}
- ms@2.0.0: {}
-
ms@2.1.3: {}
nanoid@3.3.15: {}
+ neotraverse@0.6.18: {}
+
next@16.2.10(@babel/core@7.29.7(supports-color@5.5.0))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(sass@1.101.0):
dependencies:
'@next/env': 16.2.10
@@ -6270,20 +7011,22 @@ snapshots:
nice-try@1.0.5: {}
+ nlcst-to-string@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+
node-addon-api@7.1.1:
optional: true
+ node-fetch-native@1.6.7: {}
+
node-fetch@2.7.0:
dependencies:
whatwg-url: 5.0.0
- node-releases@2.0.50: {}
+ node-mock-http@1.0.4: {}
- node-retrieve-globals@6.0.1:
- dependencies:
- acorn: 8.17.0
- acorn-walk: 8.3.5
- esm-import-transformer: 3.0.5
+ node-releases@2.0.50: {}
nodemon@3.1.14:
dependencies:
@@ -6321,21 +7064,19 @@ snapshots:
dependencies:
path-key: 3.1.1
- nunjucks@3.2.4(chokidar@3.6.0):
+ nth-check@2.1.1:
dependencies:
- a-sync-waterfall: 1.0.1
- asap: 2.0.6
- commander: 5.1.0
- optionalDependencies:
- chokidar: 3.6.0
-
- oauth-sign@0.9.0: {}
+ boolbase: 1.0.0
obug@2.1.3: {}
- on-finished@2.4.1:
+ ofetch@1.5.1:
dependencies:
- ee-first: 1.1.1
+ destr: 2.0.5
+ node-fetch-native: 1.6.7
+ ufo: 1.6.4
+
+ ohash@2.0.11: {}
once@1.4.0:
dependencies:
@@ -6365,18 +7106,31 @@ snapshots:
dependencies:
p-try: 2.2.0
+ p-limit@7.3.0:
+ dependencies:
+ yocto-queue: 1.2.2
+
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
p-map@2.1.0: {}
+ p-queue@9.3.1:
+ dependencies:
+ eventemitter3: 5.0.4
+ p-timeout: 7.0.1
+
+ p-timeout@7.0.1: {}
+
p-try@2.2.0: {}
package-manager-detector@0.2.11:
dependencies:
quansync: 0.2.11
+ package-manager-detector@1.7.0: {}
+
parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
@@ -6394,9 +7148,18 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
- parse-srcset@1.0.2: {}
+ parse-latin@7.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ '@types/unist': 3.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-modify-children: 4.0.0
+ unist-util-visit-children: 3.0.0
+ vfile: 6.0.3
- parseurl@1.3.3: {}
+ parse5@7.3.0:
+ dependencies:
+ entities: 6.0.1
path-exists@4.0.0: {}
@@ -6417,7 +7180,7 @@ snapshots:
pathe@2.0.3: {}
- performance-now@2.1.0: {}
+ piccolore@0.1.3: {}
picocolors@1.1.1: {}
@@ -6437,10 +7200,6 @@ snapshots:
optionalDependencies:
fsevents: 2.3.2
- please-upgrade-node@3.2.0:
- dependencies:
- semver-compare: 1.0.0
-
plyr@3.8.4:
dependencies:
core-js: 3.49.0
@@ -6503,30 +7262,13 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
- posthtml-match-helper@2.0.3(posthtml@0.16.7):
- dependencies:
- posthtml: 0.16.7
-
- posthtml-parser@0.11.0:
- dependencies:
- htmlparser2: 7.2.0
-
- posthtml-render@3.0.0:
- dependencies:
- is-json: 2.0.1
-
- posthtml@0.16.7:
- dependencies:
- posthtml-parser: 0.11.0
- posthtml-render: 3.0.0
-
preact@10.12.1: {}
prettier@2.8.8: {}
prettier@3.9.4: {}
- pretty-bytes@5.6.0: {}
+ prettier@3.9.5: {}
pretty-format@30.4.1:
dependencies:
@@ -6537,18 +7279,16 @@ snapshots:
pretty-hrtime@1.0.3: {}
+ prismjs@1.30.0: {}
+
+ process-ancestry@0.1.0: {}
+
property-information@7.2.0: {}
proto-list@1.2.4: {}
proxy-from-env@1.1.0: {}
- prr@1.0.1: {}
-
- psl@1.15.0:
- dependencies:
- punycode: 2.3.1
-
pstree.remy@1.1.8: {}
pump@3.0.4:
@@ -6558,19 +7298,11 @@ snapshots:
punycode.js@2.3.1: {}
- punycode@2.3.1: {}
-
- qified@0.10.1:
- dependencies:
- hookified: 2.2.0
-
- qs@6.5.5: {}
-
quansync@0.2.11: {}
queue-microtask@1.2.3: {}
- range-parser@1.3.0: {}
+ radix3@1.1.2: {}
rangetouch@2.0.1: {}
@@ -6619,6 +7351,35 @@ snapshots:
dependencies:
resolve: 1.22.12
+ recma-build-jsx@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ estree-util-build-jsx: 3.0.1
+ vfile: 6.0.3
+
+ recma-jsx@1.0.1(acorn@8.17.0):
+ dependencies:
+ acorn: 8.17.0
+ acorn-jsx: 5.3.2(acorn@8.17.0)
+ estree-util-to-js: 2.0.0
+ recma-parse: 1.0.0
+ recma-stringify: 1.0.0
+ unified: 11.0.5
+
+ recma-parse@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ esast-util-from-js: 2.0.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ recma-stringify@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ estree-util-to-js: 2.0.0
+ unified: 11.0.5
+ vfile: 6.0.3
+
regex-recursion@6.0.2:
dependencies:
regex-utilities: 2.3.0
@@ -6629,33 +7390,80 @@ snapshots:
dependencies:
regex-utilities: 2.3.0
- request@2.88.2:
+ rehype-raw@7.0.0:
dependencies:
- aws-sign2: 0.7.0
- aws4: 1.13.2
- caseless: 0.12.0
- combined-stream: 1.0.8
- extend: 3.0.2
- forever-agent: 0.6.1
- form-data: 2.3.3
- har-validator: 5.1.5
- http-signature: 1.2.0
- is-typedarray: 1.0.0
- isstream: 0.1.2
- json-stringify-safe: 5.0.1
- mime-types: 2.1.35
- oauth-sign: 0.9.0
- performance-now: 2.1.0
- qs: 6.5.5
- safe-buffer: 5.2.1
- tough-cookie: 2.5.0
- tunnel-agent: 0.6.0
- uuid: 3.4.0
+ '@types/hast': 3.0.4
+ hast-util-raw: 9.1.0
+ vfile: 6.0.3
+
+ rehype-recma@1.0.0:
+ dependencies:
+ '@types/estree': 1.0.9
+ '@types/hast': 3.0.4
+ hast-util-to-estree: 3.1.3
+ transitivePeerDependencies:
+ - supports-color
+
+ rehype-stringify@10.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-to-html: 9.0.5
+ unified: 11.0.5
+
+ remark-gfm@4.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-mdx@3.1.1:
+ dependencies:
+ mdast-util-mdx: 3.0.0
+ micromark-extension-mdxjs: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-smartypants@3.0.2:
+ dependencies:
+ retext: 9.0.0
+ retext-smartypants: 6.2.0
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
+
+ remark-stringify@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
require-directory@2.1.1: {}
resolve-from@5.0.0: {}
+ resolve-pkg-maps@1.0.0: {}
+
resolve@1.22.12:
dependencies:
es-errors: 1.3.0
@@ -6663,6 +7471,31 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ retext-latin@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ parse-latin: 7.0.0
+ unified: 11.0.5
+
+ retext-smartypants@6.2.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unist-util-visit: 5.1.0
+
+ retext-stringify@4.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ nlcst-to-string: 4.0.0
+ unified: 11.0.5
+
+ retext@9.0.0:
+ dependencies:
+ '@types/nlcst': 2.0.3
+ retext-latin: 4.0.0
+ retext-stringify: 4.0.0
+ unified: 11.0.5
+
reusify@1.1.0: {}
rolldown@1.1.4:
@@ -6708,8 +7541,6 @@ snapshots:
dependencies:
tslib: 2.8.1
- safe-buffer@5.2.1: {}
-
safer-buffer@2.1.2: {}
sass-true@9.0.0(sass@1.101.0):
@@ -6728,41 +7559,35 @@ snapshots:
optionalDependencies:
'@parcel/watcher': 2.5.6
+ satteri@0.9.5:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ optionalDependencies:
+ '@bruits/satteri-darwin-arm64': 0.9.5
+ '@bruits/satteri-darwin-x64': 0.9.5
+ '@bruits/satteri-linux-arm64-gnu': 0.9.5
+ '@bruits/satteri-linux-arm64-musl': 0.9.5
+ '@bruits/satteri-linux-x64-gnu': 0.9.5
+ '@bruits/satteri-linux-x64-musl': 0.9.5
+ '@bruits/satteri-wasm32-wasi': 0.9.5
+ '@bruits/satteri-win32-arm64-msvc': 0.9.5
+ '@bruits/satteri-win32-x64-msvc': 0.9.5
+
+ sax@1.6.0: {}
+
scheduler@0.27.0: {}
- section-matter@1.0.0:
- dependencies:
- extend-shallow: 2.0.1
- kind-of: 6.0.3
-
select@1.1.2: {}
- semver-compare@1.0.0: {}
-
semver@5.7.2: {}
semver@6.3.1: {}
semver@7.8.5: {}
- send@1.2.1(supports-color@5.5.0):
- dependencies:
- debug: 4.4.3(supports-color@5.5.0)
- encodeurl: 2.0.0
- escape-html: 1.0.3
- etag: 1.8.1
- fresh: 2.0.0
- http-errors: 2.0.1
- mime-types: 3.0.2
- ms: 2.1.3
- on-finished: 2.4.1
- range-parser: 1.3.0
- statuses: 2.0.2
- transitivePeerDependencies:
- - supports-color
-
- setprototypeof@1.2.0: {}
-
sharp@0.34.5:
dependencies:
'@img/colour': 1.1.0
@@ -6855,12 +7680,12 @@ snapshots:
mrmime: 2.0.1
totalist: 3.0.1
+ sisteransi@1.0.5: {}
+
slash@3.0.0: {}
slash@5.1.0: {}
- slugify@1.6.9: {}
-
smol-toml@1.6.1: {}
sortablejs@1.15.7: {}
@@ -6874,6 +7699,8 @@ snapshots:
source-map@0.6.1: {}
+ source-map@0.7.6: {}
+
space-separated-tokens@2.0.2: {}
spawndamnit@3.0.1:
@@ -6897,30 +7724,12 @@ snapshots:
sprintf-js@1.0.3: {}
- sshpk@1.18.0:
- dependencies:
- asn1: 0.2.6
- assert-plus: 1.0.0
- bcrypt-pbkdf: 1.0.2
- dashdash: 1.14.1
- ecc-jsbn: 0.1.2
- getpass: 0.1.7
- jsbn: 0.1.1
- safer-buffer: 2.1.2
- tweetnacl: 0.14.5
-
- ssri@11.0.0:
- dependencies:
- minipass: 7.1.3
-
stackback@0.0.2: {}
star-rating.js@4.3.1:
dependencies:
detect-it: 4.0.1
- statuses@2.0.2: {}
-
std-env@4.1.0: {}
string-natural-compare@2.0.3: {}
@@ -6955,8 +7764,6 @@ snapshots:
dependencies:
ansi-regex: 6.2.2
- strip-bom-string@1.0.0: {}
-
strip-bom@3.0.0: {}
strip-eof@1.0.0: {}
@@ -6965,6 +7772,14 @@ snapshots:
strip-json-comments@3.1.1: {}
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@5.5.0))(react@19.2.7):
dependencies:
client-only: 0.0.1
@@ -6984,6 +7799,16 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ svgo@4.0.1:
+ dependencies:
+ commander: 11.1.0
+ css-select: 5.2.2
+ css-tree: 3.2.1
+ css-what: 6.2.2
+ csso: 5.0.5
+ picocolors: 1.1.1
+ sax: 1.6.0
+
term-size@2.2.1: {}
terser@5.48.0:
@@ -6997,8 +7822,12 @@ snapshots:
tiny-emitter@2.1.0: {}
+ tiny-inflate@1.0.3: {}
+
tinybench@2.9.0: {}
+ tinyclip@0.1.15: {}
+
tinyexec@1.2.4: {}
tinyglobby@0.2.17:
@@ -7012,8 +7841,6 @@ snapshots:
dependencies:
is-number: 7.0.0
- toidentifier@1.0.1: {}
-
tom-select@2.6.1:
dependencies:
'@orchidjs/sifter': 1.1.0
@@ -7023,17 +7850,14 @@ snapshots:
touch@3.1.1: {}
- tough-cookie@2.5.0:
- dependencies:
- psl: 1.15.0
- punycode: 2.3.1
-
tr46@0.0.3: {}
tree-kill@1.2.2: {}
trim-lines@3.0.1: {}
+ trough@2.2.0: {}
+
tslib@2.8.1: {}
tsx@4.23.0:
@@ -7042,10 +7866,6 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
- tunnel-agent@0.6.0:
- dependencies:
- safe-buffer: 5.2.1
-
turbo@2.10.3:
optionalDependencies:
'@turbo/darwin-64': 2.10.3
@@ -7055,8 +7875,6 @@ snapshots:
'@turbo/windows-64': 2.10.3
'@turbo/windows-arm64': 2.10.3
- tweetnacl@0.14.5: {}
-
type-fest@0.6.0: {}
type-fest@0.8.1: {}
@@ -7067,22 +7885,67 @@ snapshots:
uc.micro@2.1.0: {}
+ ufo@1.6.4: {}
+
+ ultrahtml@1.7.0: {}
+
+ uncrypto@0.1.3: {}
+
undefsafe@2.0.5: {}
undici-types@8.3.0: {}
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unifont@0.7.4:
+ dependencies:
+ css-tree: 3.2.1
+ ofetch: 1.5.1
+ ohash: 2.0.11
+
+ unist-util-find-after@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
unist-util-is@6.0.1:
dependencies:
'@types/unist': 3.0.3
+ unist-util-modify-children@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ array-iterate: 2.0.1
+
+ unist-util-position-from-estree@2.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
unist-util-position@5.0.0:
dependencies:
'@types/unist': 3.0.3
+ unist-util-remove-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-visit: 5.1.0
+
unist-util-stringify-position@4.0.0:
dependencies:
'@types/unist': 3.0.3
+ unist-util-visit-children@3.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
unist-util-visit-parents@6.0.2:
dependencies:
'@types/unist': 3.0.3
@@ -7098,7 +7961,16 @@ snapshots:
universalify@2.0.1: {}
- unpipe@1.0.0: {}
+ unstorage@1.17.5:
+ dependencies:
+ anymatch: 3.1.3
+ chokidar: 5.0.0
+ destr: 2.0.5
+ h3: 1.15.11
+ lru-cache: 11.5.1
+ node-fetch-native: 1.6.7
+ ofetch: 1.5.1
+ ufo: 1.6.4
update-browserslist-db@1.2.3(browserslist@4.28.5):
dependencies:
@@ -7106,26 +7978,17 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
- uri-js@4.4.1:
- dependencies:
- punycode: 2.3.1
-
url-polyfill@1.1.14: {}
- urlpattern-polyfill@10.1.0: {}
-
- uuid@3.4.0: {}
-
validate-npm-package-license@3.0.4:
dependencies:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
- verror@1.10.0:
+ vfile-location@5.0.3:
dependencies:
- assert-plus: 1.0.0
- core-util-is: 1.0.2
- extsprintf: 1.3.0
+ '@types/unist': 3.0.3
+ vfile: 6.0.3
vfile-message@4.0.3:
dependencies:
@@ -7153,6 +8016,26 @@ snapshots:
tsx: 4.23.0
yaml: 2.9.0
+ vite@8.1.3(@types/node@26.1.1)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0):
+ dependencies:
+ lightningcss: 1.32.0
+ picomatch: 4.0.5
+ postcss: 8.5.16
+ rolldown: 1.1.4
+ tinyglobby: 0.2.17
+ optionalDependencies:
+ '@types/node': 26.1.1
+ esbuild: 0.28.1
+ fsevents: 2.3.3
+ sass: 1.101.0
+ terser: 5.48.0
+ tsx: 4.23.0
+ yaml: 2.9.0
+
+ vitefu@1.1.3(vite@8.1.3(@types/node@26.1.1)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)):
+ optionalDependencies:
+ vite: 8.1.3(@types/node@26.1.1)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+
vitest@4.1.9(@types/node@26.1.0)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-istanbul@4.1.9)(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.1)(sass@1.101.0)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)):
dependencies:
'@vitest/expect': 4.1.9
@@ -7182,6 +8065,8 @@ snapshots:
transitivePeerDependencies:
- msw
+ web-namespaces@2.0.1: {}
+
webidl-conversions@3.0.1: {}
whatwg-url@5.0.0:
@@ -7218,6 +8103,8 @@ snapshots:
ws@8.21.0: {}
+ xxhash-wasm@1.1.0: {}
+
y18n@5.0.8: {}
yallist@3.1.1: {}
@@ -7247,4 +8134,8 @@ snapshots:
y18n: 5.0.8
yargs-parser: 22.0.0
+ yocto-queue@1.2.2: {}
+
+ zod@4.4.3: {}
+
zwitch@2.0.4: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 2cdffb991..c466af40c 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,7 +1,9 @@
packages:
- core
- preview
+ - preview-astro
- docs
+ - docs-astro
- 'shared/*'
allowBuilds:
diff --git a/preview/.build/copy-assets.mjs b/preview/.build/copy-assets.mjs
new file mode 100644
index 000000000..6a476450e
--- /dev/null
+++ b/preview/.build/copy-assets.mjs
@@ -0,0 +1,75 @@
+// Equivalent of the Eleventy passthrough copies: static assets are generated
+// into public/ before dev/build (public/ is fully generated — see .gitignore).
+import { cpSync, existsSync, mkdirSync, copyFileSync, rmSync } from 'node:fs'
+import { dirname, join } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+const root = join(dirname(fileURLToPath(import.meta.url)), '..')
+const repo = join(root, '..')
+
+const copies = [
+ // @tabler/core dist (css/js/fonts/img/libs) — same as the Eleventy passthrough
+ {
+ from: join(root, 'node_modules', '@tabler', 'core', 'dist'),
+ to: join(root, 'public', 'dist'),
+ required: true,
+ allowDestinationFallback: true,
+ },
+ // demo css/js built by this package's sass/vite pipeline
+ { from: join(root, 'dist', 'preview'), to: join(root, 'public', 'preview'), required: true },
+ // docs.css built by the @tabler/docs sass pipeline (used by docs pages)
+ { from: join(repo, 'docs', 'dist', 'css'), to: join(root, 'public', 'css'), required: false },
+ // static assets (photos, avatars, tracks, brand svgs...).
+ // Use the real source because preview/static is a symlink that may not survive deployment packaging.
+ { from: join(repo, 'shared', 'static'), to: join(root, 'public', 'static'), required: true },
+ // favicons (source assets of @tabler/preview)
+ { from: join(root, 'assets', 'favicon.ico'), to: join(root, 'public', 'favicon.ico'), required: true },
+ { from: join(root, 'assets', 'favicon-dev.ico'), to: join(root, 'public', 'favicon-dev.ico'), required: true },
+]
+
+for (const { from, to, required, allowDestinationFallback } of copies) {
+ if (!existsSync(from)) {
+ const message = `copy-assets: missing ${from}`
+ if (allowDestinationFallback && existsSync(to)) {
+ console.warn(`${message} (using existing ${to})`)
+ continue
+ }
+ if (required) throw new Error(`${message} — run the build of that package first`)
+ console.warn(`${message} (skipped — build @tabler/preview or @tabler/docs to get it)`)
+ continue
+ }
+ mkdirSync(dirname(to), { recursive: true })
+ if (from.endsWith('.ico')) {
+ copyFileSync(from, to)
+ } else {
+ // dereference: sources may be symlinks (e.g. preview/static → shared/static).
+ // For fallback-enabled copies (core dist), keep existing destination as a safety net
+ // in case source files disappear mid-copy during parallel clean/build tasks.
+ if (!allowDestinationFallback) {
+ // remove the target first so a stale symlink never survives
+ try {
+ rmSync(to, { recursive: true, force: true })
+ } catch (error) {
+ if (!(error && typeof error === 'object' && error.code === 'ENOTEMPTY')) {
+ throw error
+ }
+ }
+ }
+ try {
+ cpSync(from, to, {
+ recursive: true,
+ dereference: true,
+ filter: (src) => !src.includes('/.vscode') && !src.includes('\\.vscode'),
+ })
+ } catch (error) {
+ // In turbo dev, @tabler/core can clean dist while we copy it.
+ // If fallback is allowed and destination exists, keep current assets.
+ if (allowDestinationFallback && error && typeof error === 'object' && error.code === 'ENOENT' && existsSync(to)) {
+ console.warn(`copy-assets: source changed during copy ${from} (using existing ${to})`)
+ continue
+ }
+ throw error
+ }
+ }
+}
+console.log('copy-assets: done')
diff --git a/preview/.build/download-images.mjs b/preview/.build/download-images.mjs
deleted file mode 100644
index ea7063047..000000000
--- a/preview/.build/download-images.mjs
+++ /dev/null
@@ -1,59 +0,0 @@
-// #!/usr/bin/env node
-
-// import { readFileSync, createWriteStream, existsSync, writeFileSync } from 'node:fs'
-// import { join, dirname } from 'node:path'
-// import request, { head } from 'request'
-// import { fileURLToPath } from 'node:url';
-
-// const __dirname = dirname(fileURLToPath(import.meta.url))
-
-// const filePath = join(__dirname, '..', 'preview', 'pages', '_data', 'photos.json')
-
-// const photos = JSON.parse(readFileSync(filePath, 'utf8'))
-
-// const urlTitle = (str) => {
-// str = str
-// .toLowerCase()
-// .replaceAll('&', 'and')
-// .replace(/[^[a-z0-9-]/g, '-')
-// .replace(/-+/g, '-')
-
-// return str
-// }
-
-// const download = function (uri, filename, callback, error) {
-// head(uri, function (err, res, body) {
-// request(uri).pipe(createWriteStream(filename))
-// .on('close', callback)
-// .on('error', error)
-// })
-// }
-
-// async function downloadPhotos() {
-// for (const key in photos) {
-// const photo = photos[key]
-
-// let filename, i = 1;
-
-// do {
-// filename = `${urlTitle(photo['title'])}${i > 1 ? `-${i}` : ''}.jpg`
-// i++
-// } while (existsSync(join(__dirname, `../preview/static/photos/${filename}`)))
-
-// await new Promise((resolve, reject) => {
-// download(photo['path'], join(__dirname, `../preview/static/photos/${filename}`), function () {
-// resolve()
-// }, function () {
-// reject()
-// });
-// })
-
-// photos[key]['file'] = filename
-// photos[key]['horizontal'] = photo['width'] > photo['height']
-// }
-
-// writeFileSync(filePath, JSON.stringify(photos))
-// }
-
-// downloadPhotos();
-
diff --git a/preview/.build/import-icons.mjs b/preview/.build/import-icons.mjs
deleted file mode 100644
index 0cc0e8b07..000000000
--- a/preview/.build/import-icons.mjs
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env node
-
-import { readFileSync, writeFileSync } from 'node:fs';
-import { join, dirname } from 'node:path';
-import { fileURLToPath } from 'node:url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url))
-
-const iconsTags = JSON.parse(readFileSync(join(__dirname, '../node_modules/@tabler/icons/icons.json'), 'utf8'));
-const { version } = JSON.parse(readFileSync(join(__dirname, '../node_modules/@tabler/icons/package.json'), 'utf8'))
-
-const prepareSvgFile = (svg) => {
- return svg.replace(/\n/g, '').replace(/>\s+<').replace(/\s+/g, ' ')
-}
-
-let svgList = {}
-for (let iconName in iconsTags) {
- let iconData = iconsTags[iconName]
- svgList[iconName] = {
- name: iconName,
- svg: {
- outline: iconData.styles.outline ? prepareSvgFile(readFileSync(join(__dirname, `../node_modules/@tabler/icons/icons/outline/${iconName}.svg`), 'utf8')) : null,
- filled: iconData.styles.filled ? prepareSvgFile(readFileSync(join(__dirname, `../node_modules/@tabler/icons/icons/filled/${iconName}.svg`), 'utf8')) : null,
- }
- }
-}
-
-writeFileSync(
- join(__dirname, `../../shared/data/icons-info.json`),
- JSON.stringify({
- version,
- count: Object.values(svgList).reduce((acc, icon) => {
- return acc + (icon.svg.outline ? 1 : 0) + (icon.svg.filled ? 1 : 0)
- }, 0)
- })
-)
-
-writeFileSync(join(__dirname, `../../shared/data/icons.json`), JSON.stringify(svgList))
\ No newline at end of file
diff --git a/preview/.build/import-illustrations.mjs b/preview/.build/import-illustrations.mjs
deleted file mode 100644
index 8872975e3..000000000
--- a/preview/.build/import-illustrations.mjs
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env node
-
-import { writeFileSync } from 'node:fs';
-import { join, basename, dirname } from 'node:path';
-import { sync } from 'glob';
-import { fileURLToPath } from 'node:url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url))
-
-const illustrations = sync(join(__dirname, `../../shared/static/illustrations/light/*.png`))
- .map((file) => {
- return basename(file, '.png')
- })
- .sort((a, b) => a.localeCompare(b));
-
-writeFileSync(
- join(__dirname, `../../shared/data/illustrations.json`),
- JSON.stringify(illustrations)
-)
\ No newline at end of file
diff --git a/preview/.build/remove-prettier-ignore.mjs b/preview/.build/remove-prettier-ignore.mjs
deleted file mode 100644
index 5de104a32..000000000
--- a/preview/.build/remove-prettier-ignore.mjs
+++ /dev/null
@@ -1,25 +0,0 @@
-// remove-prettier-ignore.js
-import { readFileSync, writeFileSync } from 'fs';
-import { sync } from 'glob';
-
-const patterns = [
- /\/\/ prettier-ignore[\s]*/g,
-];
-
-sync('dist/**/*.html').forEach(file => {
- let content = readFileSync(file, 'utf8');
- let modified = false;
-
- patterns.forEach(pattern => {
- const newContent = content.replace(pattern, '');
- if (newContent !== content) {
- content = newContent;
- modified = true;
- }
- });
-
- if (modified) {
- writeFileSync(file, content);
- console.log(`Cleaned: ${file}`);
- }
-});
diff --git a/preview/.build/unused-files.mjs b/preview/.build/unused-files.mjs
deleted file mode 100644
index 06e1d807c..000000000
--- a/preview/.build/unused-files.mjs
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env node
-
-import { sync } from 'glob';
-import { readFileSync } from 'node:fs';
-import { join, dirname } from 'node:path';
-import { fileURLToPath } from 'node:url';
-
-const __dirname = dirname(fileURLToPath(import.meta.url))
-
-const srcDir = join(__dirname, '..')
-
-let foundFiles = []
-sync(`${srcDir}/pages/**/*.{html,md}`).forEach((file) => {
- let fileContent = readFileSync(file)
-
- fileContent.toString().replace(/\{% include(_cached)? "([a-z0-9\/_-]+\.html)"/g, (f, c, filename) => {
- filename = `${srcDir}/pages/includes/${filename}`
-
- if (!foundFiles.includes(filename)) {
- foundFiles.push(filename)
- }
- })
-})
-
-let includeFiles = sync(`${srcDir}/pages/includes/**/*.html`)
-
-includeFiles.forEach((file) => {
- if (!foundFiles.includes(file)) {
- console.log('file', file)
- }
-})
\ No newline at end of file
diff --git a/preview/.build/vite.config.mts b/preview/.build/vite.config.mts
index d485563d0..6a44c7b00 100644
--- a/preview/.build/vite.config.mts
+++ b/preview/.build/vite.config.mts
@@ -4,19 +4,14 @@ import { createViteConfig } from '../../.build/vite.config.helper'
import getBanner from '../../shared/banner/index.mjs'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
-
-const bannerText = getBanner('Demo')
-
-const entryPath = path.resolve(__dirname, '../js/demo')
-const entry = `${entryPath}.ts`
+const entry = path.resolve(__dirname, '../js/demo.ts')
export default createViteConfig({
- entry: entry,
+ entry,
name: 'demo',
fileName: () => 'demo.js',
formats: ['es'],
outDir: path.resolve(__dirname, '../dist/preview/js'),
- banner: bannerText,
- minify: false
+ banner: getBanner('Demo'),
+ minify: false,
})
-
diff --git a/preview/.eleventyignore b/preview/.eleventyignore
deleted file mode 100644
index e69de29bb..000000000
diff --git a/preview/.gitignore b/preview/.gitignore
new file mode 100644
index 000000000..38c7d5058
--- /dev/null
+++ b/preview/.gitignore
@@ -0,0 +1,9 @@
+# build output
+dist/
+.astro/
+
+# public/ is fully generated by .build/copy-assets.mjs
+public/
+
+# parity gate reference cache
+.parity/
diff --git a/preview/.prettierrc b/preview/.prettierrc
new file mode 100644
index 000000000..875e86d6e
--- /dev/null
+++ b/preview/.prettierrc
@@ -0,0 +1,20 @@
+{
+ "bracketSpacing": true,
+ "jsxSingleQuote": false,
+ "printWidth": 320,
+ "proseWrap": "always",
+ "semi": false,
+ "singleQuote": true,
+ "quoteProps": "consistent",
+ "tabWidth": 2,
+ "useTabs": false,
+ "trailingComma": "all",
+ "overrides": [
+ {
+ "files": "*.scss",
+ "options": {
+ "parser": "scss"
+ }
+ }
+ ]
+}
diff --git a/preview/CHANGELOG.md b/preview/CHANGELOG.md
deleted file mode 100644
index 105e1d93e..000000000
--- a/preview/CHANGELOG.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# @tabler/preview
-
-## 1.4.0
-
-### Patch Changes
-
-- 6c38a48: Update Bootstrap to v5.3.7
-- Updated dependencies [6c4dd36]
-- Updated dependencies [6fec73a]
-- Updated dependencies [9951fe9]
-- Updated dependencies [db6200a]
-- Updated dependencies [e96f055]
-- Updated dependencies [a200d30]
-- Updated dependencies [6c38a48]
-- Updated dependencies [2a12f72]
-- Updated dependencies [49ab9ea]
-- Updated dependencies [666a296]
-- Updated dependencies [cfd4cb6]
- - @tabler/core@1.4.0
-
-## 1.3.2
-
-### Patch Changes
-
-- Updated dependencies [446c34e]
- - @tabler/core@1.3.2
-
-## 1.3.1
-
-### Patch Changes
-
-- Updated dependencies [a7f73d7]
- - @tabler/core@1.3.1
-
-## 1.3.0
-
-### Patch Changes
-
-- 8850f61: Enhance pagination component with new styles
diff --git a/preview/pages/favicon-dev.ico b/preview/assets/favicon-dev.ico
similarity index 100%
rename from preview/pages/favicon-dev.ico
rename to preview/assets/favicon-dev.ico
diff --git a/preview/pages/favicon.ico b/preview/assets/favicon.ico
similarity index 100%
rename from preview/pages/favicon.ico
rename to preview/assets/favicon.ico
diff --git a/preview/astro.config.mjs b/preview/astro.config.mjs
new file mode 100644
index 000000000..dd987d7ca
--- /dev/null
+++ b/preview/astro.config.mjs
@@ -0,0 +1,94 @@
+// @ts-check
+import { defineConfig } from 'astro/config';
+import mdx from '@astrojs/mdx';
+import beautify from 'js-beautify';
+import { execFileSync } from 'node:child_process';
+import { fileURLToPath } from 'node:url';
+
+/**
+ * Equivalent of the Eleventy "html-prettify" step (@tabler/preview): the
+ * generated HTML is the product (users copy it 1:1), so after the build we
+ * format it with prettier per .prettierrc.
+ * @returns {import('astro').AstroIntegration}
+ */
+function prettifyHtml() {
+ return {
+ name: 'prettify-html',
+ hooks: {
+ 'astro:build:done': async ({ dir, logger }) => {
+ const outDir = fileURLToPath(dir);
+ // Astro appends "overflow-x: auto" to the shiki
style — the
+ // Eleventy pipeline doesn't have it and HTML is the product: restore 1:1.
+ const { globSync } = await import('node:fs');
+ const { readFileSync, writeFileSync } = await import('node:fs');
+ for (const file of globSync(`${outDir}**/*.html`)) {
+ const content = readFileSync(file, 'utf8');
+ const cleaned = content.replaceAll('; overflow-x: auto;', '');
+ if (cleaned !== content) writeFileSync(file, cleaned);
+ }
+ execFileSync('npx', ['prettier', '--write', '--parser', 'html', `${outDir}**/*.html`], {
+ stdio: 'inherit',
+ });
+ logger.info('HTML formatted with prettier');
+ },
+ },
+ };
+}
+
+// https://astro.build/config
+export default defineConfig({
+ // pages live at the package root (./pages) — all components/lib/data are
+ // shared (see the @shared alias)
+ srcDir: '.',
+ vite: {
+ // InlineScript.astro renders nothing here — scripts go through the
+ // addPageScript() registry and the drain (Eleventy model)
+ define: {
+ 'import.meta.env.INLINE_PAGE_SCRIPTS': 'false',
+ },
+ resolve: {
+ alias: {
+ // demo data lives in the monorepo's shared/data — single source of
+ // truth shared with the Eleventy packages (no copies in src/data)
+ '@data': fileURLToPath(new URL('../shared/data', import.meta.url)),
+ // Astro components/lib shared with docs-astro (single source of truth)
+ '@shared': fileURLToPath(new URL('../shared/astro', import.meta.url)),
+ // this package's pages dir — used by @shared/lib/docs-children's glob
+ '@pages': fileURLToPath(new URL('./pages', import.meta.url)),
+ },
+ },
+ },
+ build: {
+ // emit sign-in.html instead of sign-in/index.html — matches the Eleventy
+ // preview package layout, where the HTML files are the distributed product
+ format: 'file',
+ },
+ // Do not collapse whitespace in the output — the HTML must stay readable
+ // (like the Eleventy build); prettier finalizes formatting after the build.
+ compressHTML: false,
+ integrations: [mdx(), prettifyHtml()],
+ markdown: {
+ // markdown-it in Eleventy does not produce typographic quotes — neither do we
+ smartypants: false,
+ shikiConfig: {
+ theme: 'github-dark',
+ transformers: [
+ {
+ // The Eleventy docs pipeline beautifies html fences before highlighting
+ preprocess(code) {
+ if (this.options.lang === 'html') {
+ return beautify.html(code, { indent_size: 2, wrap_line_length: 80 });
+ }
+ },
+ // Eleventy docs emits raw shiki output: .
+ // Astro adds its own astro-code class and data-language — restore the
+ // exact markdown-it + shiki pipeline markup.
+ pre(node) {
+ node.properties.class = 'shiki github-dark';
+ delete node.properties.dataLanguage;
+ },
+ },
+ ],
+ },
+ },
+});
diff --git a/preview/eleventy.config.mjs b/preview/eleventy.config.mjs
deleted file mode 100644
index 1589ad52c..000000000
--- a/preview/eleventy.config.mjs
+++ /dev/null
@@ -1,117 +0,0 @@
-import { readFileSync } from 'node:fs';
-import { EleventyRenderPlugin } from "@11ty/eleventy";
-import { join } from 'node:path';
-import { sync } from 'glob';
-import { appFilters } from "../shared/e11ty/filters.mjs";
-import { appData } from "../shared/e11ty/data.mjs"
-import { appConfig } from "../shared/e11ty/config.mjs"
-
-/** @type {import('@11ty/eleventy').LocalConfig} */
-export default function (eleventyConfig) {
- const environment = process.env.NODE_ENV || "production";
- const currentDir = process.cwd();
-
- appConfig(eleventyConfig);
- appFilters(eleventyConfig);
- appData(eleventyConfig);
-
- eleventyConfig.addPassthroughCopy({
- "node_modules/@tabler/core/dist": "dist",
- "pages/favicon.ico": "favicon.ico",
- "pages/favicon-dev.ico": "favicon-dev.ico",
- "static": "static",
- });
-
- eleventyConfig.addPlugin(EleventyRenderPlugin, {
- accessGlobalData: true,
- });
-
- /**
- * Data
- */
- eleventyConfig.addGlobalData("environment", environment);
- eleventyConfig.addGlobalData("readme", readFileSync(join("..", "README.md"), "utf-8"));
- eleventyConfig.addGlobalData("license", readFileSync(join("..", "LICENSE"), "utf-8"));
-
- // PostHog Analytics Environment Variables
- eleventyConfig.addGlobalData("posthogApiKey", process.env.NEXT_PUBLIC_POSTHOG_KEY);
- eleventyConfig.addGlobalData("posthogHost", process.env.NEXT_PUBLIC_POSTHOG_HOST);
-
- eleventyConfig.addGlobalData("pages", () => {
- return sync('pages/**/*.html').filter((file) => {
- return !file.includes('pages/_') && !file.includes('pages/docs/index.html');
- }).map((file) => {
- return {
- url: file.replace(/^pages\//, '/')
- }
- });
- });
-
-
- /**
- * Shortcodes
- */
- const tags = ["highlight", "endhighlight"];
- tags.forEach(tag => {
- eleventyConfig.addLiquidTag(tag, function (liquidEngine) {
- return {
- parse: function (tagToken, remainingTokens) {
- this.str = tagToken.args;
- },
- render: function (scope, hash) {
- return "";
- },
- };
- });
- });
-
- let _CAPTURES = {};
-
- eleventyConfig.on('beforeBuild', () => {
- _CAPTURES = {};
- });
-
- ['script', 'modal'].forEach((tag) => {
- eleventyConfig.addPairedShortcode(`capture_${tag}`, function (content, inline) {
- if (inline) {
- return content;
- }
-
- if (!_CAPTURES[tag]) {
- _CAPTURES[tag] = []
- }
-
- if (!_CAPTURES[tag][this.page.inputPath]) {
- _CAPTURES[tag][this.page.inputPath] = [];
- }
-
- _CAPTURES[tag][this.page.inputPath].push(content);
-
- return ''
- })
-
- eleventyConfig.addShortcode(`${tag}s`, function () {
- if (_CAPTURES[tag] && _CAPTURES[tag][this.page.inputPath]) {
- return _CAPTURES[tag][this.page.inputPath] ? `\n${_CAPTURES[tag][this.page.inputPath].join('\n').trim()}\n` : '';
- }
-
- return ''
- });
- });
-
- /**
- * Transforms
- */
- if (environment !== "development") {
- function prettifyHTML(content, outputPath) {
- return outputPath.endsWith('.html')
- ? content
- .replace(/\/\/ @formatter:(on|off)\n+/gm, '')
- // remove empty lines
- .replace(/^\s*[\r\n]/gm, '')
- : content
- }
-
- eleventyConfig.addTransform('htmlformat', prettifyHTML)
- }
-};
\ No newline at end of file
diff --git a/preview/js/demo.ts b/preview/js/demo.ts
index 042e747df..447ea0d45 100644
--- a/preview/js/demo.ts
+++ b/preview/js/demo.ts
@@ -1,4 +1,3 @@
-// Setting items
interface SettingItem {
localStorage: string
default: string
@@ -17,14 +16,12 @@ const items: SettingsItems = {
},
}
-// Theme config
const config: Record = {}
for (const [key, params] of Object.entries(items)) {
const lsParams = localStorage.getItem(params.localStorage)
config[key] = lsParams ? lsParams : params.default
}
-// Parse url params
const parseUrl = (): void => {
const search = window.location.search.substring(1)
const params = search.split("&")
@@ -35,18 +32,14 @@ const parseUrl = (): void => {
const value = arr[1]
if (!!items[key]) {
- // Save to localStorage
localStorage.setItem(items[key].localStorage, value)
-
- // Update local variables
config[key] = value
}
}
}
-// Toggle form controls
const toggleFormControls = (form: HTMLFormElement): void => {
- for (const [key, params] of Object.entries(items)) {
+ for (const [key] of Object.entries(items)) {
const elem = form.querySelector(
`[name="settings-${key}"][value="${config[key]}"]`,
) as HTMLInputElement | null
@@ -57,44 +50,33 @@ const toggleFormControls = (form: HTMLFormElement): void => {
}
}
-// Submit form
const submitForm = (form: HTMLFormElement): void => {
- // Save data to localStorage
for (const [key, params] of Object.entries(items)) {
- // Save to localStorage
const checkedInput = form.querySelector(`[name="settings-${key}"]:checked`) as HTMLInputElement
if (checkedInput) {
const value = checkedInput.value
localStorage.setItem(params.localStorage, value)
-
- // Update local variables
config[key] = value
}
}
window.dispatchEvent(new Event("resize"))
- // Bootstrap is available globally
- const bootstrap = (window as any).bootstrap
+ const bootstrap = (window as Window & { bootstrap?: { Offcanvas: new (form: HTMLFormElement) => { hide(): void } } }).bootstrap
if (bootstrap) {
new bootstrap.Offcanvas(form).hide()
}
}
-// Parse url
parseUrl()
-// Elements
const form = document.querySelector("#offcanvas-settings") as HTMLFormElement | null
-// Toggle form controls
if (form) {
- form.addEventListener("submit", function (e) {
- e.preventDefault()
-
+ form.addEventListener("submit", function (event) {
+ event.preventDefault()
submitForm(form)
})
toggleFormControls(form)
}
-
diff --git a/preview/package.json b/preview/package.json
index 1acb6182c..53db6d9f7 100644
--- a/preview/package.json
+++ b/preview/package.json
@@ -1,49 +1,29 @@
{
"name": "@tabler/preview",
- "version": "1.4.0",
"private": true,
- "scripts": {
- "build": "pnpm run clean && pnpm run build-assets && pnpm run html",
- "build-assets": "concurrently \"pnpm run css\" \"pnpm run js\"",
- "dev": "pnpm run clean && pnpm run watch",
- "watch": "concurrently \"pnpm run watch-html\" \"pnpm run watch-css\" \"pnpm run watch-js\"",
- "watch-html": "cross-env NODE_ENV=development eleventy --serve --port=3000 --watch --incremental",
- "watch-js": "nodemon --watch js/ --ext js --exec \"pnpm run js\"",
- "watch-css": "nodemon --watch scss/ --ext scss --exec \"pnpm run css\"",
- "css": "pnpm run css-build && pnpm run css-prefix && pnpm run css-minify",
- "css-build": "sass scss/:dist/preview/css/ --no-source-map --load-path=node_modules",
- "css-prefix": "postcss --config .build/postcss.config.mjs --replace \"dist/preview/css/*.css\" \"!dist/preview/css/*.rtl*.css\" \"!dist/preview/css/*.min.css\"",
- "css-minify": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/preview/css/ --batch --batch-suffix \".min\" \"dist/preview/css/*.css\" \"!dist/preview/css/*.min.css\" \"!dist/preview/css/*rtl*.css\"",
- "js": "pnpm run js-build && pnpm run js-build-min",
- "js-build": "vite build --config .build/vite.config.mts",
- "js-build-min": "pnpm run js-build-min-demo",
- "js-build-min-demo": "terser dist/preview/js/demo.js --module --compress --mangle --comments '/@license|@preserve|^!/' --source-map \"content=dist/preview/js/demo.js.map,filename=dist/preview/js/demo.min.js.map,url=demo.min.js.map\" -o dist/preview/js/demo.min.js",
- "clean": "shx rm -rf dist demo",
- "html": "pnpm run html-build && pnpm run html-prettify && pnpm run html-remove-prettier-ignore",
- "html-build": "eleventy",
- "html-prettify": "prettier --write \"dist/**/*.html\" \"!dist/dist/**\"",
- "html-remove-prettier-ignore": "node .build/remove-prettier-ignore.mjs",
- "svg-optimize": "svgo -f svg/brand --pretty",
- "unused-files": "node .build/unused-files.mjs",
- "download-images": "node .build/download-images.mjs",
- "optimize-images": "for i in ./src/static/photos/*.jpg; do convert \"$i\" -quality 80% \"${i%.jpg}.jpg\"; done",
- "svg-icons": "node .build/import-icons.mjs",
- "import-illustrations": "node .build/import-illustrations.mjs",
- "import-icons": "git checkout dev && BRANCH_NAME=\"dev-tabler-icons-`pnpm info @tabler/icons version`\" && git branch $BRANCH_NAME && git checkout $BRANCH_NAME && ncu -u @tabler/icons && pnpm install && pnpm run svg-icons && git add . && git commit -am \"update icons to v`pnpm info @tabler/icons version`\" && git push origin $BRANCH_NAME && git checkout dev",
- "zip": "mkdir -p packages-zip && zip -r packages-zip/tabler-$(node -p \"require('./package.json').version\").zip demo/*"
+ "type": "module",
+ "version": "0.0.1",
+ "engines": {
+ "node": ">=22.12.0"
},
- "devDependencies": {
- "@11ty/eleventy": "3.1.2",
- "imageoptim-cli": "^3.1.9",
- "request": "^2.88.2"
+ "scripts": {
+ "assets": "pnpm run css && pnpm run js && node .build/copy-assets.mjs",
+ "css": "sass --no-source-map --load-path=node_modules --style expanded scss/:dist/preview/css/ && postcss --config ../core/.build/postcss.config.mjs --replace \"dist/preview/css/*.css\" \"!dist/preview/css/*.min.css\" && cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/preview/css/ --batch --batch-suffix \".min\" \"dist/preview/css/*.css\" \"!dist/preview/css/*.min.css\"",
+ "js": "vite build --config .build/vite.config.mts && terser dist/preview/js/demo.js --module --compress --mangle --comments '/@license|@preserve|^!/' --source-map \"content=dist/preview/js/demo.js.map,filename=dist/preview/js/demo.min.js.map,url=demo.min.js.map\" -o dist/preview/js/demo.min.js",
+ "dev": "pnpm run assets && astro dev",
+ "build": "pnpm run assets && astro build",
+ "preview": "astro preview",
+ "clean": "shx rm -rf dist public/dist public/preview public/css .astro"
},
"dependencies": {
"@tabler/core": "workspace:*",
- "@tabler/icons": "^3.40.0"
+ "astro": "^7.0.7"
},
- "prettier": {
- "tabWidth": 2,
- "useTabs": false,
- "printWidth": 160
+ "devDependencies": {
+ "@astrojs/mdx": "^7.0.2",
+ "js-beautify": "^2.0.3",
+ "prettier": "^3.9.5",
+ "shiki": "^4.3.1",
+ "shx": "^0.4.0"
}
-}
\ No newline at end of file
+}
diff --git a/preview/pages/2-step-verification-code.astro b/preview/pages/2-step-verification-code.astro
new file mode 100644
index 000000000..7eec7b89b
--- /dev/null
+++ b/preview/pages/2-step-verification-code.astro
@@ -0,0 +1,87 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import Button from '@shared/components/Button.astro';
+import { addPageScript } from '@shared/lib/page-scripts';
+
+addPageScript(``);
+---
+
+
+
+
+
+ It may take a minute to receive your code. Haven't received it?
Resend a new code.
+
+
diff --git a/preview/pages/2-step-verification-code.html b/preview/pages/2-step-verification-code.html
deleted file mode 100644
index f9faeadfa..000000000
--- a/preview/pages/2-step-verification-code.html
+++ /dev/null
@@ -1,79 +0,0 @@
----
-title: "2-Step Verification"
-layout: single
-permalink: 2-step-verification-code.html
----
-
-
-
-
- It may take a minute to receive your code. Haven't received it?
Resend a new code.
-
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/preview/pages/2-step-verification.astro b/preview/pages/2-step-verification.astro
new file mode 100644
index 000000000..77fcec62b
--- /dev/null
+++ b/preview/pages/2-step-verification.astro
@@ -0,0 +1,47 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import Button from '@shared/components/Button.astro';
+import flags from '@data/flags.json';
+
+// Liquid: {% if country.code == 'US' %} selected{% endif %} — flags.json entries
+// have no `code` property, so the reference renders value="" and never `selected`.
+// We mirror that output exactly.
+---
+
+
+
+
diff --git a/preview/pages/2-step-verification.html b/preview/pages/2-step-verification.html
deleted file mode 100644
index a47050a7b..000000000
--- a/preview/pages/2-step-verification.html
+++ /dev/null
@@ -1,43 +0,0 @@
----
-title: 2-Step Verification
-layout: single
-permalink: 2-step-verification.html
----
-
-
\ No newline at end of file
diff --git a/preview/pages/accordion.astro b/preview/pages/accordion.astro
new file mode 100644
index 000000000..7df6ef049
--- /dev/null
+++ b/preview/pages/accordion.astro
@@ -0,0 +1,50 @@
+---
+// Port of preview/pages/accordion.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Accordion from '@shared/components/ui/Accordion.astro';
+---
+
+
+
+
diff --git a/preview/pages/accordion.html b/preview/pages/accordion.html
deleted file mode 100644
index 176368b38..000000000
--- a/preview/pages/accordion.html
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: Accordion
-page-header: Accordion
-page-menu: base.accordion
-layout: default
-permalink: accordion.html
----
-
-
-
-
-
- {% include "ui/accordion.html" %}
-
-
-
-
-
- {% include "ui/accordion.html" type="flush" id="flush" %}
-
-
-
-
-
- {% include "ui/accordion.html" type="tabs" id="tabs" %}
-
-
-
-
-
-
- {% include "ui/accordion.html" type="inverted" id="inverted" %}
-
-
-
-
-
-
- {% include "ui/accordion.html" id="inverted-plus" type="inverted,plus" toggle-icon="plus" %}
-
-
-
-
-
-
- {% include "ui/accordion.html" id="icons" show-icon %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/activity.astro b/preview/pages/activity.astro
new file mode 100644
index 000000000..699b0f257
--- /dev/null
+++ b/preview/pages/activity.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/activity.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import ActivityPart from '@shared/components/ui/ActivityPart.astro';
+---
+
+
+
+
diff --git a/preview/pages/activity.html b/preview/pages/activity.html
deleted file mode 100644
index 39a5e5735..000000000
--- a/preview/pages/activity.html
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: Activity
-page-header: Activity
-page-menu: extra.activity
-layout: default
-permalink: activity.html
----
-
-
-
-
-
- {% include "parts/activity.html" %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/alerts.astro b/preview/pages/alerts.astro
new file mode 100644
index 000000000..8c8c73ef4
--- /dev/null
+++ b/preview/pages/alerts.astro
@@ -0,0 +1,108 @@
+---
+// Port of preview/pages/alerts.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Alert from '@shared/components/Alert.astro';
+---
+
+
+
+
+
+
+
+
Alerts with action
+
+
+
+
+
+
+
+
+
+
+
Dismissible alerts
+
+
+
+
+
+
+
+
+
+
+
Alert with a description
+
+
+
+
+
+
+
+
+
+
+
Important alerts
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/alerts.html b/preview/pages/alerts.html
deleted file mode 100644
index 473c4e5b8..000000000
--- a/preview/pages/alerts.html
+++ /dev/null
@@ -1,76 +0,0 @@
----
-title: Alerts
-page-menu: base.alerts
-page-header: Alerts
-layout: default
-permalink: alerts.html
----
-
-
-
-
-
-
Basic alerts
- {% include "ui/alert.html" type="danger" title="An error occurred!" %}
- {% include "ui/alert.html" type="warning" title="Some information is missing!" %}
- {% include "ui/alert.html" type="success" title="Completed successfully!" %}
- {% include "ui/alert.html" type="info" title="Just a quick note!" %}
-
-
-
-
-
-
-
Alerts with action
- {% include "ui/alert.html" show-close action="Link" type="danger" title="An error occurred!" %}
- {% include "ui/alert.html" show-close action="Link" type="warning" title="Some information is missing!" %}
- {% include "ui/alert.html" show-close action="Link" type="success" title="Completed successfully!" %}
- {% include "ui/alert.html" show-close action="Link" type="info" title="Just a quick note!" %}
-
-
-
-
-
-
-
Dismissible alerts
- {% include "ui/alert.html" show-close type="danger" title="An error occurred!" %}
- {% include "ui/alert.html" show-close type="warning" title="Some information is missing!" %}
- {% include "ui/alert.html" show-close type="success" title="Completed successfully!" %}
- {% include "ui/alert.html" show-close type="info" title="Just a quick note!" %}
-
-
-
-
-
-
-
Alert with a description
- {% include "ui/alert.html" show-close type="danger" title="Password does not meet requirements:" list="Minimum 8 characters,Include a special character" %}
- {% include "ui/alert.html" show-close type="warning" title="Some information is missing!" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close type="success" title="Completed successfully!" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close type="info" title="Just a quick note!" description="This is a custom alert box with a description." %}
-
-
-
-
-
-
-
Important alerts
- {% include "ui/alert.html" show-close important=true type="danger" title="Password does not meet requirements:" list="Minimum 8 characters,Include a special character" %}
- {% include "ui/alert.html" show-close important=true type="success" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close important=true type="warning" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close important=true type="info" description="This is a custom alert box with a description." %}
-
-
-
-
-
-
-
Minor alerts
- {% include "ui/alert.html" show-close minor=true type="danger" title="Password does not meet requirements:" list="Minimum 8 characters,Include a special character" %}
- {% include "ui/alert.html" show-close minor=true type="success" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close minor=true type="warning" description="This is a custom alert box with a description." %}
- {% include "ui/alert.html" show-close minor=true type="info" description="This is a custom alert box with a description." %}
-
-
-
-
diff --git a/preview/pages/all-elements.astro b/preview/pages/all-elements.astro
new file mode 100644
index 000000000..9c5dce23e
--- /dev/null
+++ b/preview/pages/all-elements.astro
@@ -0,0 +1,925 @@
+---
+// Port of preview/pages/all-elements.html — a kitchen-sink of every component.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import Alert from '@shared/components/Alert.astro';
+import Badge from '@shared/components/ui/Badge.astro';
+import Progress from '@shared/components/ui/Progress.astro';
+import Select from '@shared/components/ui/Select.astro';
+import Check from '@shared/components/ui/form/Check.astro';
+import Nav from '@shared/components/ui/Nav.astro';
+import Breadcrumb from '@shared/components/ui/Breadcrumb.astro';
+import Pagination from '@shared/components/ui/Pagination.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Icon from '@shared/components/Icon.astro';
+import Dropdown from '@shared/components/ui/Dropdown.astro';
+import Accordion from '@shared/components/ui/Accordion.astro';
+import Spinner from '@shared/components/ui/Spinner.astro';
+import Rating from '@shared/components/ui/Rating.astro';
+import Steps from '@shared/components/ui/Steps.astro';
+import StatusDot from '@shared/components/ui/StatusDot.astro';
+import Toast from '@shared/components/ui/Toast.astro';
+import InputIcon from '@shared/components/ui/form/InputIcon.astro';
+import InputGroup from '@shared/components/InputGroup.astro';
+import Range from '@shared/components/ui/Range.astro';
+import Tag from '@shared/components/ui/Tag.astro';
+import Ribbon from '@shared/components/ui/Ribbon.astro';
+import Flag from '@shared/components/ui/Flag.astro';
+import Payment from '@shared/components/ui/Payment.astro';
+import Timeline from '@shared/components/ui/Timeline.astro';
+import Empty from '@shared/components/ui/Empty.astro';
+import NavSegmented from '@shared/components/ui/NavSegmented.astro';
+
+// Code-block content lives in the frontmatter so Astro does not try to evaluate
+// its `${name}` / `{ }` as expressions; injected verbatim via set:html.
+const codeExample = `// JavaScript example
+function greetUser(name) {
+ console.log(\`Hello, \${name}!\`);
+ return true;
+}`;
+---
+
+
+
+
+
+
+
+
+
+
+
Heading 1
+ Heading 2
+ Heading 3
+ Heading 4
+ Heading 5
+ Heading 6
+
+
+
This is a lead paragraph with larger text.
+
This is a regular paragraph with bold text , italic text , and
+ underlined text .
+
This is small muted text.
+
Primary text color
+
Success text color
+
Danger text color
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Standard Buttons
+
+
+
+
+
+
+
+
+
+
+
+
Button Sizes
+
+
+
+
+
+
+
Icon Buttons
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This is a simple card with header and body content.
+
+
+
+
+
+
+
+
+
This card includes a footer section.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Text Input
+
+
+
+ Email Input
+
+
+
+ Password Input
+
+
+
+ Select Dropdown
+
+
+
+
+
+ Textarea
+
+
+
+ Checkboxes
+
+
+
+
+ Radio Buttons
+
+
+
+
+ Switch
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Tabs
+
+
+
+
+
Pills Navigation
+
+
+
+
+
Breadcrumb
+
+
+
+
Pagination
+ {/* active-item="2" is a STRING in Liquid; `i == "2"` never matches the
+ integer index, so no page renders active — reproduced by passing a string. */}
+
+
+
Pagination with Text
+
+
+
+
+
+
+
+
+
+
+
+
+
Unordered List
+
+ First item
+ Second item
+ Third item
+
+
+
Ordered List
+
+ First item
+ Second item
+ Third item
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+ Email
+ Status
+
+
+
+
+ John Doe
+ john@example.com
+
+
+
+ Jane Smith
+ jane@example.com
+
+
+
+ Bob Johnson
+ bob@example.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Spinners
+
+
+
Rating
+
+
+
+
+
Steps
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Status Dots
+
+
+
+
+
+
+
+
Toast Notifications
+
+
+
+
+
+
+
+
+
+
+
+
+
Input with Icons
+
+
+
+
+
+
+
+
Input Groups
+
+
+
+
+
+
+
+
Range Slider
+
+
+
+
+
+
+
+
+
+
+
+
+
Tags
+
+
+
+
+
+
+
Ribbons
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Flags
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Payment Icons
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open Modal
+
+
+ Success Modal
+
+
+
+
+
+
+
+
+
+
This is a sample modal dialog. You can put any content here.
+
+
+
+
+
+
+
+
+
+
+
+
+
Success!
+
Your action was completed successfully.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Basic Button Group
+
+ Left
+ Middle
+ Right
+
+
+
Button Toolbar
+
+
+
Vertical Button Group
+
+ Top
+ Middle
+ Bottom
+
+
+
+
+
+
+
+
+
+
+
Basic Segmented
+
+
+
+
+
With Icons
+
+
+
+
+
With Emojis
+
+
+
+
+
With Icons and Text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Basic Collapse
+
+ Toggle Collapse
+
+
+
+ This is collapsed content that can be toggled. It's hidden by default and shown when the button is clicked.
+
+
+
+
+
Multiple Targets
+
+
+ Toggle First
+
+
+ Toggle Second
+
+
+
+
+ First collapsible content.
+
+
+
+
+ Second collapsible content.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Tooltips
+
+
+ Top
+
+
+ Right
+
+
+ Bottom
+
+
+ Left
+
+
+
+
+
Popovers
+
+
+ Top Popover
+
+
+ Right Popover
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Home
+
+
+
+ Active item
+
+
+
+ Settings
+
+
+
+ Profile
+
+
+
+ Disabled item
+
+
+
+
+
+
+
+
+
+
+
+
Blockquote
+
+ This is a blockquote example with some sample text to demonstrate the styling.
+
+
+
+
Code Block
+
+
+
Inline Elements
+
This paragraph contains inline code, Ctrl + S keyboard shortcut, and highlighted text .
+
+
+
+
+
diff --git a/preview/pages/all-elements.html b/preview/pages/all-elements.html
deleted file mode 100644
index 81a385815..000000000
--- a/preview/pages/all-elements.html
+++ /dev/null
@@ -1,884 +0,0 @@
----
-title: All Elements - Kitchen Sink
-page-header: All Elements
-page-menu: base.all-elements
-page-libs: [nouislider, star-rating.js, tabler-flags, tabler-payments, tom-select]
-layout: default
-permalink: all-elements.html
----
-
-
-
-
-
-
-
-
-
-
Heading 1
- Heading 2
- Heading 3
- Heading 4
- Heading 5
- Heading 6
-
-
-
This is a lead paragraph with larger text.
-
This is a regular paragraph with bold text , italic text , and
- underlined text .
-
This is small muted text.
-
Primary text color
-
Success text color
-
Danger text color
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Standard Buttons
-
- {% include "ui/button.html" text="Default" %}
- {% include "ui/button.html" text="Primary" color="primary" icon="star" %}
- {% include "ui/button.html" text="Secondary" color="secondary" %}
- {% include "ui/button.html" text="Success" color="success" icon="check" %}
- {% include "ui/button.html" text="Warning" color="warning" %}
- {% include "ui/button.html" text="Danger" color="danger" icon="x" %}
- {% include "ui/button.html" text="Info" color="info" %}
-
-
-
-
Button Sizes
-
- {% include "ui/button.html" text="Small" size="sm" %}
- {% include "ui/button.html" text="Default"%}
- {% include "ui/button.html" text="Large" size="lg" %}
-
-
-
Icon Buttons
-
- {% include "ui/button.html" icon="heart" icon-only=true %}
- {% include "ui/button.html" icon="star" icon-only=true %}
- {% include "ui/button.html" icon="check" icon-only=true %}
-
-
-
-
-
-
-
-
-
-
-
-
-
This is a simple card with header and body content.
-
-
-
-
-
-
-
-
-
This card includes a footer section.
-
-
-
-
-
-
-
-
-
-
- {% include "ui/alert.html" type="info" title="This is a primary alert with an icon." %}
- {% include "ui/alert.html" type="success" title="This is a success alert message." %}
- {% include "ui/alert.html" type="warning" title="This is a warning alert message." %}
- {% include "ui/alert.html" type="danger" title="This is a danger alert message." %}
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/badge.html" text="Default" %}
- {% include "ui/badge.html" text="Primary" color="primary" %}
- {% include "ui/badge.html" text="Secondary" color="secondary" %}
- {% include "ui/badge.html" text="Success" color="success" %}
- {% include "ui/badge.html" text="Warning" color="warning" %}
- {% include "ui/badge.html" text="Danger" color="danger" %}
-
-
- {% include "ui/badge.html" text="With Icon" color="primary" icon="star" %}
- {% include "ui/badge.html" text="Light Badge" color="primary" light=true %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/progress.html" value="25" %}
-
-
- {% include "ui/progress.html" value="50" color="success" %}
-
-
- {% include "ui/progress.html" value="75" color="warning" %}
-
-
- {% include "ui/progress.html" value="90" color="danger" show-value=true %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Text Input
-
-
-
- Email Input
-
-
-
- Password Input
-
-
-
- Select Dropdown
- {% include "ui/select.html" id="demo-select" values="Option 1,Option 2,Option 3" %}
-
-
-
-
- Textarea
-
-
-
- Checkboxes
- {% include "ui/form/check.html" title="Option 1" type="checkbox" %}
- {% include "ui/form/check.html" title="Option 2" type="checkbox" checked=true %}
-
-
- Radio Buttons
- {% include "ui/form/check.html" title="Option 1" type="radio" name="radio-demo" %}
- {% include "ui/form/check.html" title="Option 2" type="radio" name="radio-demo" checked=true %}
-
-
- Switch
- {% include "ui/form/check.html" title="Enable notifications" switch=true %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Tabs
-
- {% include "ui/nav.html" tabs=true class="mb-4" %}
-
-
-
Pills Navigation
-
- {% include "ui/nav.html" pills=true class="mb-4" %}
-
-
-
Breadcrumb
- {% include "ui/breadcrumb.html" pages="Home,Library,Data" home-icon=true %}
-
-
-
Pagination
- {% include "ui/pagination.html" count="5" active-item="2" class="mb-4" %}
-
- Pagination with Text
- {% include "ui/pagination.html" count="3" text=true %}
-
-
-
-
-
-
-
-
-
-
-
-
Unordered List
-
- First item
- Second item
- Third item
-
-
-
Ordered List
-
- First item
- Second item
- Third item
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Name
- Email
- Status
-
-
-
-
- John Doe
- john@example.com
- {% include "ui/badge.html" text="Active" color="success" %}
-
-
- Jane Smith
- jane@example.com
- {% include "ui/badge.html" text="Pending" color="warning" %}
-
-
- Bob Johnson
- bob@example.com
- {% include "ui/badge.html" text="Inactive" color="danger" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/avatar.html" placeholder="JD" size="sm" %}
- {% include "ui/avatar.html" placeholder="JS" %}
- {% include "ui/avatar.html" placeholder="BJ" size="lg" %}
- {% include "ui/avatar.html" placeholder="AB" size="xl" %}
-
-
- {% include "ui/avatar.html" placeholder="RD" shape="avatar-rounded" %}
- {% include "ui/avatar.html" placeholder="PR" color="primary" shape="avatar-rounded" %}
- {% include "ui/avatar.html" placeholder="SC" color="success" shape="avatar-rounded" %}
-
-
- {% include "ui/avatar.html" icon="user" %}
- {% include "ui/avatar.html" icon="star" color="warning" %}
- {% include "ui/avatar.html" placeholder="ST" status="success" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="home" %}
- {% include "ui/icon.html" icon="user" %}
- {% include "ui/icon.html" icon="settings" %}
- {% include "ui/icon.html" icon="heart" %}
- {% include "ui/icon.html" icon="star" %}
- {% include "ui/icon.html" icon="bell" %}
- {% include "ui/icon.html" icon="mail" %}
- {% include "ui/icon.html" icon="phone" %}
- {% include "ui/icon.html" icon="calendar" %}
- {% include "ui/icon.html" icon="clock" %}
- {% include "ui/icon.html" icon="map-pin" %}
- {% include "ui/icon.html" icon="camera" %}
- {% include "ui/icon.html" icon="plus" %}
- {% include "ui/icon.html" icon="minus" %}
- {% include "ui/icon.html" icon="edit" %}
- {% include "ui/icon.html" icon="trash" %}
- {% include "ui/icon.html" icon="download" %}
- {% include "ui/icon.html" icon="upload" %}
- {% include "ui/icon.html" icon="search" %}
- {% include "ui/icon.html" icon="filter" %}
- {% include "ui/icon.html" icon="refresh" %}
- {% include "ui/icon.html" icon="share" %}
- {% include "ui/icon.html" icon="copy" %}
- {% include "ui/icon.html" icon="external-link" %}
-
-
- {% include "ui/icon.html" icon="check" %}
- {% include "ui/icon.html" icon="circle-check" %}
- {% include "ui/icon.html" icon="alert-triangle" %}
- {% include "ui/icon.html" icon="alert-circle" %}
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/dropdown.html" main-btn="Primary Dropdown" options="Action, Another action, Something else
- here" %}
- {% include "ui/dropdown.html" main-btn="Secondary Dropdown" options="Edit, Copy, Delete" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
Accordion
-
- {% include "ui/accordion.html" count="3" id="demo-accordion" %}
-
-
-
-
Spinners
-
-
- {% include "ui/spinner.html" type="border" color="primary" %}
- {% include "ui/spinner.html" type="border" color="success" size="sm" %}
- {% include "ui/spinner.html" type="grow" color="warning" %}
- {% include "ui/spinner.html" type="grow" color="danger" size="sm" %}
-
-
-
-
Rating
-
- {% include "ui/rating.html" id="demo-rating" value="4" %}
-
-
-
Steps
-
- {% include "ui/steps.html" count="4" active="2" %}
-
-
- {% include "ui/steps.html" count="4" active="3" numbers=true %}
-
-
-
-
-
-
-
-
-
-
-
-
-
Status Dots
-
- {% include "ui/status-dot.html" color="success" %}
- {% include "ui/status-dot.html" color="warning" %}
- {% include "ui/status-dot.html" color="danger" %}
- {% include "ui/status-dot.html" color="info" animated=true %}
-
-
-
Toast Notifications
-
- {% include "ui/toast.html" toast-id="demo-toast" show=true text="This is a sample toast message!" %}
-
-
-
-
-
-
-
-
-
-
-
Input with Icons
-
- {% include "ui/form/input-icon.html" placeholder="Search..." icon="search" %}
-
-
- {% include "ui/form/input-icon.html" placeholder="Loading..." loader=true %}
-
-
-
Input Groups
-
- {% include "ui/form/input-group.html" prepend="@" placeholder="Username" %}
-
-
- {% include "ui/form/input-group.html" append=".00" prepend="$" placeholder="Price" %}
-
-
-
Range Slider
-
- {% include "ui/range.html" id="demo-range" min="0" max="100" value="50" %}
-
-
-
-
-
-
-
-
-
-
-
Tags
-
- {% include "ui/tag.html" text="Primary Tag" icon="star" %}
- {% include "ui/tag.html" text="Success Tag" status="success" %}
- {% include "ui/tag.html" text="Warning Tag" status="warning" %}
-
-
-
Ribbons
-
- {% include "ui/ribbon.html" text="New" color="success" %}
-
-
- {% include "ui/ribbon.html" text="Sale" color="danger" top=true %}
-
-
-
-
-
-
-
-
-
-
-
Flags
-
-
- {% include "ui/flag.html" flag="us" %}
- {% include "ui/flag.html" flag="gb" %}
- {% include "ui/flag.html" flag="de" %}
- {% include "ui/flag.html" flag="fr" %}
- {% include "ui/flag.html" flag="pl" %}
- {% include "ui/flag.html" flag="es" %}
- {% include "ui/flag.html" flag="it" %}
- {% include "ui/flag.html" flag="nl" %}
- {% include "ui/flag.html" flag="ca" %}
- {% include "ui/flag.html" flag="au" %}
-
-
-
-
Payment Icons
-
-
- {% include "ui/payment.html" payment="visa" %}
- {% include "ui/payment.html" payment="mastercard" %}
- {% include "ui/payment.html" payment="paypal" %}
- {% include "ui/payment.html" payment="americanexpress" %}
- {% include "ui/payment.html" payment="applepay" %}
- {% include "ui/payment.html" payment="google-pay" %}
- {% include "ui/payment.html" payment="stripe" %}
- {% include "ui/payment.html" payment="discover" %}
- {% include "ui/payment.html" payment="jcb" %}
- {% include "ui/payment.html" payment="maestro" %}
- {% include "ui/payment.html" payment="dinersclub" %}
- {% include "ui/payment.html" payment="bitcoin" %}
- {% include "ui/payment.html" payment="ethereum" %}
- {% include "ui/payment.html" payment="klarna" %}
- {% include "ui/payment.html" payment="venmo" %}
- {% include "ui/payment.html" payment="square" %}
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/timeline.html" %}
-
-
-
-
-
-
-
-
-
- {% include "ui/empty.html" title="No data found" subtitle="Try adjusting your search or filter to find what
- you're looking for." illustration="boy-girl.svg" button-text="Add new item" button-icon="plus" %}
-
-
-
-
-
-
-
-
-
-
-
- Open Modal
-
-
- Success Modal
-
-
-
-
-
-
-
-
-
-
This is a sample modal dialog. You can put any content here.
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="circle-check" color="success" size="xl" class="mb-2" %}
-
Success!
-
Your action was completed successfully.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Basic Button Group
-
- Left
- Middle
- Right
-
-
-
Button Toolbar
-
-
-
Vertical Button Group
-
- Top
- Middle
- Bottom
-
-
-
-
-
-
-
-
-
-
-
Basic Segmented
-
- {% include "ui/nav-segmented.html" items="Home,Profile,Settings" %}
-
-
-
With Icons
-
- {% include "ui/nav-segmented.html" icons="home,user,settings" %}
-
-
-
With Emojis
-
- {% include "ui/nav-segmented.html" items="👦,👦🏿,👦🏾,👦🏽,👦🏼,👦🏻" %}
-
-
-
With Icons and Text
-
- {% include "ui/nav-segmented.html" items="Home,Profile,Settings" icons="home,user,settings" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
Basic Collapse
-
- Toggle Collapse
-
-
-
- This is collapsed content that can be toggled. It's hidden by default and shown when the button is clicked.
-
-
-
-
-
Multiple Targets
-
-
- Toggle First
-
-
- Toggle Second
-
-
-
-
- First collapsible content.
-
-
-
-
- Second collapsible content.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Tooltips
-
-
- Top
-
-
- Right
-
-
- Bottom
-
-
- Left
-
-
-
-
-
Popovers
-
-
- Top Popover
-
-
- Right Popover
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="home" class="me-2" %}
- Home
-
-
- {% include "ui/icon.html" icon="star" class="me-2" %}
- Active item
-
-
- {% include "ui/icon.html" icon="settings" class="me-2" %}
- Settings
-
-
- {% include "ui/icon.html" icon="user" class="me-2" %}
- Profile
-
-
- {% include "ui/icon.html" icon="lock" class="me-2" %}
- Disabled item
-
-
-
-
-
-
-
-
-
-
-
-
Blockquote
-
- This is a blockquote example with some sample text to demonstrate the styling.
-
-
-
-
Code Block
-
// JavaScript example
-function greetUser(name) {
- console.log(`Hello, ${name}!`);
- return true;
-}
-
-
Inline Elements
-
This paragraph contains inline code, Ctrl + S keyboard shortcut, and highlighted text .
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/auth-lock.astro b/preview/pages/auth-lock.astro
new file mode 100644
index 000000000..8097e9c3b
--- /dev/null
+++ b/preview/pages/auth-lock.astro
@@ -0,0 +1,10 @@
+---
+// Port of preview/pages/auth-lock.html (layout: single; the front matter
+// title really is "Forgot password" in the Liquid source)
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import AuthLockCard from '@shared/components/cards/AuthLockCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/auth-lock.html b/preview/pages/auth-lock.html
deleted file mode 100644
index 6257f3d91..000000000
--- a/preview/pages/auth-lock.html
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: Forgot password
-layout: single
-page-menu: base.authentication.auth-lock
-permalink: auth-lock.html
----
-
-{% include "cards/auth-lock.html" show-header="1" %}
diff --git a/preview/pages/avatars.astro b/preview/pages/avatars.astro
new file mode 100644
index 000000000..5692a64b2
--- /dev/null
+++ b/preview/pages/avatars.astro
@@ -0,0 +1,168 @@
+---
+// Port of preview/pages/avatars.html (layout: default)
+// Note: the `description` front matter key is inert in the dev build (no
+// in the reference output), so it is not ported.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import AvatarUpload from '@shared/components/ui/AvatarUpload.astro';
+import people from '@data/people.json';
+import { site } from '@shared/lib/site';
+
+const iconIcons = ['user', 'settings', 'car', 'balloon', 'users', 'users-group', 'apps', 'ghost'];
+
+// Liquid: {% for color in site.colors %} — the iterated keys match site.themeColors
+// (blue..cyan), confirmed against the reference output.
+const colors = site.themeColors;
+
+// equivalent of the first_letters filter
+const firstLetters = (s: string) => s.split(' ').map((w) => w.charAt(0)).join('');
+
+const people8 = people.slice(0, 8);
+const people5 = people.slice(0, 5);
+const sizes = ['xxs', 'xs', 'sm', 'md', 'lg', 'xl'];
+const listSizes = ['xxs', 'xs', 'sm', 'md', 'lg'];
+const uploadSizes = ['xxs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl'];
+const statusColors = ['red', 'green', 'blue', 'yellow', 'secondary'];
+const brands = ['netflix', 'amazon', 'messenger', 'figma', 'twitch'];
+---
+
+
+
+
+
+
+
+
Avatar with icon
+
+
+ {iconIcons.map((icon) =>
)}
+
+
+
+
+
+
+
+
Avatar with icon
+
+
+ {colors.map((color) =>
)}
+
+
+
+
+
+
+
+
Simple avatar
+
+ {people8.map((person) =>
)}
+
+
+
+
+
+
+
+
Avatar placeholder
+
+ {people8.map((person) =>
)}
+
+
+
+
+
+
+
+
+
Avatar sizes
+
+
+
+ {sizes.map((size) =>
)}
+
+
+
+
+ {sizes.map((size) =>
)}
+
+
+
+
+
+
+
+
+
+
Avatar lists
+
+ {
+ listSizes.map((size) => (
+ <>
+
+
+ {people5.map((person) => (
+
+ ))}
+
+
+
+
+
+ {people5.map((person) => (
+
+ ))}
+
+
+
+ >
+ ))
+ }
+
+
+
+
+
+
+
+
Avatar placeholder
+ {uploadSizes.map((size) =>
)}
+
+
+
+
+
+
+
Avatar statuses
+ {statusColors.map((color, i) =>
)}
+
+
+
+
+
+
+
Avatar brands
+ {brands.map((brand, i) =>
)}
+
+
+
+
+
diff --git a/preview/pages/avatars.html b/preview/pages/avatars.html
deleted file mode 100644
index c9a95f695..000000000
--- a/preview/pages/avatars.html
+++ /dev/null
@@ -1,173 +0,0 @@
----
-title: Avatars
-layout: default
-description: A page showcasing different avatar styles and examples.
-permalink: /avatars.html
-page-menu: base.avatars
-page-header: Avatars
----
-
-
-
-
-
-
Default avatar
- {% include "ui/avatar.html" %}
-
-
-
-
-
-
-
Avatar with icon
-
- {% assign icon-icons = "user,settings,car,balloon,users,users-group,apps,ghost" | split: "," %}
-
- {% for icon in icon-icons %}
- {% include "ui/avatar.html" icon=icon %}
- {% endfor %}
-
-
-
-
-
-
-
-
Avatar with icon
-
-
- {% for color in site.colors %}
- {% include "ui/avatar.html" icon="user" color=color[0] %}
- {% endfor %}
-
-
-
-
-
-
-
-
Simple avatar
-
- {% for person in people limit: 8 -%}
- {% include "ui/avatar.html" person=person %}
- {%- endfor %}
-
-
-
-
-
-
-
-
Avatar placeholder
-
- {% for person in people limit: 8 %}
- {% assign placeholder = person.full_name | first_letters %}
- {% include "ui/avatar.html" placeholder=placeholder %}
- {% endfor %}
-
-
-
-
-
-
-
-
Avatar shapes
-
- {% include "ui/avatar.html" %}
- {% include "ui/avatar.html" class="rounded-circle" %}
- {% include "ui/avatar.html" class="rounded-0" %}
-
-
-
-
-
-
-
-
Avatar sizes
-
-
-
- {% include "ui/avatar.html" size="xxs" %}
- {% include "ui/avatar.html" size="xs" %}
- {% include "ui/avatar.html" size="sm" %}
- {% include "ui/avatar.html" size="md" %}
- {% include "ui/avatar.html" size="lg" %}
- {% include "ui/avatar.html" size="xl" %}
-
-
-
-
- {% include "ui/avatar.html" placeholder="PK" size="xxs" %}
- {% include "ui/avatar.html" placeholder="PK" size="xs" %}
- {% include "ui/avatar.html" placeholder="PK" size="sm" %}
- {% include "ui/avatar.html" placeholder="PK" size="md" %}
- {% include "ui/avatar.html" placeholder="PK" size="lg" %}
- {% include "ui/avatar.html" placeholder="PK" size="xl" %}
-
-
-
-
-
-
-
-
-
-
Avatar lists
-
- {% assign sizes = "xxs,xs,sm,md,lg" | split: "," %}
- {% for size in sizes %}
-
-
- {% for person in people limit: 5 %}
- {% include "ui/avatar.html" person=person %}
- {% endfor %}
- {% include "ui/avatar.html" icon="plus" link %}
-
-
-
-
- {% for person in people limit: 5 %}
- {% include "ui/avatar.html" person=person class="rounded-circle" %}
- {% endfor %}
- {% include "ui/avatar.html" icon="plus" link class="rounded-circle" %}
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
Avatar placeholder
- {% assign sizes = "xxs,xs,sm,md,lg,xl,2xl" | split: "," %}
- {% for size in sizes %}
- {% include "ui/avatar-upload.html" size=size %}
- {% endfor %}
-
-
-
-
-
-
-
Avatar statuses
- {% assign colors = "red,green,blue,yellow,secondary" | split: "," %}
- {% for color in colors %}
- {% include "ui/avatar.html" person-id=forloop.index class="rounded-circle" status=color %}
- {% endfor %}
-
-
-
-
-
-
-
Avatar brands
- {% assign brands = "netflix,amazon,messenger,figma,twitch" | split: "," %}
- {% for brand in brands %}
- {% include "ui/avatar.html" person-id=forloop.index brand=brand %}
- {% endfor %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/badges.astro b/preview/pages/badges.astro
new file mode 100644
index 000000000..5595437de
--- /dev/null
+++ b/preview/pages/badges.astro
@@ -0,0 +1,202 @@
+---
+// Port of preview/pages/badges.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import DropdownMenu from '@shared/components/ui/DropdownMenu.astro';
+import site from '@data/site.json';
+
+// Liquid: colors = ['default'] + site.colors keys + ['dark', 'light']
+const colors = ['default', ...Object.keys(site.colors), 'dark', 'light'];
+const sizes = ['sm', 'md', 'lg'];
+
+// Liquid uc_first filter
+const ucFirst = (value: string) => value.charAt(0).toUpperCase() + value.slice(1);
+---
+
+
+
+
+
+
+
+
+
Example heading New
+ Example heading New
+ Example heading New
+ Example heading New
+ Example heading New
+ Example heading New
+
+
+
+
+
+
+
Badge sizes
+
+
+ {
+ sizes.map((size) => (
+
+ Default
+
+ Left icon
+
+
+ Right icon
+
+
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+
Positioned badges
+
+
+ Notifications 4
+
+
+ Inbox
+
+ 9+
+ unread messages
+
+
+
+
+ Profile
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Basic badges
+
+ {colors.map((color) => {ucFirst(color)} )}
+
+
+
+
+
+
+
+
Light badges
+
+ {colors.map((color) => {ucFirst(color)} )}
+
+
+
+
+
+
+
+
Outline badges
+
+ {colors.map((color) => {ucFirst(color)} )}
+
+
+
+
+
+
+
+
Badges with icons
+
+ {
+ colors.map((color) => (
+
+ {' '}
+ {ucFirst(color)}{' '}
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ colors.map((color, index) => (
+
+ {ucFirst(color)} badge {index + 1}
+
+ ))
+ }
+
+
+
+
+
+
+
+
+ {
+ colors.map((color, index) => (
+
+ {ucFirst(color)} badge{' '}
+ {index + 1}
+
+ ))
+ }
+
+
+
+
+
+
+
+
+ {
+ colors.map((color) => (
+
+ {ucFirst(color)} badge
+
+ ))
+ }
+
+
+
+
+
+
+
+
diff --git a/preview/pages/badges.html b/preview/pages/badges.html
deleted file mode 100644
index d8151afc8..000000000
--- a/preview/pages/badges.html
+++ /dev/null
@@ -1,191 +0,0 @@
----
-title: Badges
-page-header: Badges
-page-menu: base.badges
-layout: default
-permalink: badges.html
----
-
-{% assign colors = "" | split: "," %} {% assign colors = colors | push: "default" %} {% for color in site.colors %} {%
-assign colors = colors | push: color[0]
-%} {% endfor %} {% assign colors = colors | push: "dark" | push: "light" %}
-
-
-
-
-
-
-
-
Example heading New
- Example heading New
- Example heading New
- Example heading New
- Example heading New
- Example heading New
-
-
-
-
-
-
-
Badge sizes
-
-
- {% assign sizes = "sm,md,lg" | split: "," %} {% for size in sizes %}
-
- Default
- {% include "ui/icon.html"
- icon="check" %} Left icon
-
- Right icon{% include "ui/icon.html"
- icon="arrow-right" %}
-
- {% include
- "ui/icon.html" icon="star" type="filled" %}
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
Positioned badges
-
-
- Notifications 4
-
-
- Inbox
-
- 9+
- unread messages
-
-
-
-
- Profile
-
-
-
-
- Settings
-
-
-
-
- {% include "ui/icon.html" icon="bell" %}
-
-
-
-
- {% include "ui/icon.html" icon="bell" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Basic badges
-
- {% for color in colors %}
- {{ color | uc_first }}
- {% endfor %}
-
-
-
-
-
-
-
-
Light badges
-
- {% for color in colors %}
- {{ color | uc_first }}
- {% endfor %}
-
-
-
-
-
-
-
-
Outline badges
-
- {% for color in colors %}
- {{ color | uc_first }}
- {% endfor %}
-
-
-
-
-
-
-
-
Badges with icons
-
- {% for color in colors %}
- {% include "ui/icon.html" icon="star"
- type="filled" %} {{ color | uc_first }}
- {% endfor %}
-
-
-
-
-
-
-
{% include "ui/dropdown-menu.html" show=true badge=true arrow=true %}
-
-
-
-
-
-
- {% for color in colors %}
- {{ color | uc_first }} badge {{ forloop.index }}
- {% endfor %}
-
-
-
-
-
-
-
-
- {% for color in colors %}
-
- {{ color | uc_first }} badge {{ forloop.index }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
- {% for color in colors %}
-
- {{ color | uc_first }} badge
-
- {% endfor %}
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/blank.astro b/preview/pages/blank.astro
new file mode 100644
index 000000000..ac5611262
--- /dev/null
+++ b/preview/pages/blank.astro
@@ -0,0 +1,11 @@
+---
+// Port of preview/pages/blank.html (layout: default). The `blank: true`
+// front matter is inert in the Liquid templates (never referenced) — the
+// empty page header comes from the missing `page-header` key.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Empty from '@shared/components/ui/Empty.astro';
+---
+
+
+
+
diff --git a/preview/pages/blank.html b/preview/pages/blank.html
deleted file mode 100644
index f53ee0aac..000000000
--- a/preview/pages/blank.html
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: Blank page
-blank: true
-page-menu: base.blank
-page-container-centered: true
-layout: default
-permalink: blank.html
----
-
-{% include "ui/empty.html" button-text="Add your first client" button-icon="plus" illustration="computer-fix.svg" %}
diff --git a/preview/pages/buttons.astro b/preview/pages/buttons.astro
new file mode 100644
index 000000000..dcb8e9cd3
--- /dev/null
+++ b/preview/pages/buttons.astro
@@ -0,0 +1,210 @@
+---
+// Port of preview/pages/buttons.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import Button from '@shared/components/Button.astro';
+import site from '@data/site.json';
+
+type ColorEntry = [string, { title: string; icon?: string }];
+
+// Liquid iterates the site.json objects as [key, value] pairs.
+// themeColors/colors entries have no icon — ui/icon.html renders nothing there.
+const themeColors = Object.entries(site.themeColors) as ColorEntry[];
+const colors = Object.entries(site.colors) as ColorEntry[];
+const socialColors = Object.entries(site.socialColors) as ColorEntry[];
+
+const actions = ['edit', 'copy', 'settings', 'clipboard', 'x'];
+const sizes = ['sm', 'md', 'lg', 'xl'];
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ actions.map((action) => (
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ sizes.map((size) => (
+
+
+
+
+
+
+ ))
+ }
+
+
+
+
+
+
diff --git a/preview/pages/buttons.html b/preview/pages/buttons.html
deleted file mode 100644
index 5a8223eea..000000000
--- a/preview/pages/buttons.html
+++ /dev/null
@@ -1,184 +0,0 @@
----
-title: Buttons
-page-header: Buttons
-page-menu: base.buttons
-layout: default
-permalink: buttons.html
----
-
-
-
-
-
-
-
-
-
-
- {% assign actions = 'edit,copy,settings,clipboard,x' | split: ',' %}
-
-
-
-
-
-
-
- {% assign sizes = 'sm,md,lg,xl' | split: ',' %}
- {% for size in sizes %}
-
- {% include "ui/button.html" size=size text="Button" %}
- {% include "ui/button.html" size=size icon="star" icon-only %}
- {% include "ui/button.html" size=size icon="star" text="Button" %}
- {% include "ui/button.html" size=size icon-end="star" text="Button" %}
-
- {% endfor %}
-
-
-
-
-
diff --git a/preview/pages/card-actions.astro b/preview/pages/card-actions.astro
new file mode 100644
index 000000000..75be93b49
--- /dev/null
+++ b/preview/pages/card-actions.astro
@@ -0,0 +1,152 @@
+---
+// Port of preview/pages/card-actions.html.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import BodyPlaceholder from '@shared/components/cards/BodyPlaceholder.astro';
+import Button from '@shared/components/Button.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Icon from '@shared/components/Icon.astro';
+import people from '@data/people.json';
+
+const person0 = people[0];
+const person3 = people[3];
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/card-actions.html b/preview/pages/card-actions.html
deleted file mode 100644
index 96e41e92e..000000000
--- a/preview/pages/card-actions.html
+++ /dev/null
@@ -1,147 +0,0 @@
----
-title: Card actions
-page-header: Card actions
-page-menu: base.cards.actions
-layout: default
-permalink: card-actions.html
----
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
- {% assign person = people[0] %}
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
- {% assign person = people[3] %}
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
-
-
-
- {% include "cards/body-placeholder.html" %}
-
-
-
diff --git a/preview/pages/card-gradients.astro b/preview/pages/card-gradients.astro
new file mode 100644
index 000000000..35994754d
--- /dev/null
+++ b/preview/pages/card-gradients.astro
@@ -0,0 +1,92 @@
+---
+// Port of preview/pages/card-gradients.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Welcome from '@shared/components/cards/Welcome.astro';
+import DeleteConfirm from '@shared/components/cards/DeleteConfirm.astro';
+import SuccessMessage from '@shared/components/cards/SuccessMessage.astro';
+import PricingPlan from '@shared/components/cards/PricingPlan.astro';
+import StatGradient from '@shared/components/cards/StatGradient.astro';
+import HappyBirthday from '@shared/components/cards/HappyBirthday.astro';
+import YouWin from '@shared/components/cards/YouWin.astro';
+import Weather from '@shared/components/cards/Weather.astro';
+import ProfileContact from '@shared/components/cards/ProfileContact.astro';
+import SmallStats from '@shared/components/cards/SmallStats.astro';
+import people from '@data/people.json';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/card-gradients.html b/preview/pages/card-gradients.html
deleted file mode 100644
index c0634c649..000000000
--- a/preview/pages/card-gradients.html
+++ /dev/null
@@ -1,97 +0,0 @@
----
-title: Card Gradients
-page-header: Card Gradients
-page-menu: base.cards.gradients
-layout: default
-permalink: card-gradients.html
-page-libs: [apexcharts]
----
-
-{% assign gradients = 'sunset,rainbow,ocean,mellow,disco,psychedelic' | split: ',' %}
-
-
-
-
-
- {% include "cards/welcome.html" %}
-
-
-
-
-
-
- {% include "cards/delete-confirm.html" %}
-
-
- {% include "cards/success-message.html" %}
-
-
-
-
-
-
- {% include "cards/pricing-plan.html" %}
-
-
- {% include "cards/stat-gradient.html" title="Earned" value="$2,847" icon="credit-card" color="success"
- progress=75 %}
-
-
- {% include "cards/stat-gradient.html" title="Pending Orders" value="47" icon="clock" color="yellow"
- progress=38 %}
-
-
- {% include "cards/stat-gradient.html" title="Cancelled Orders" value="12" icon="shopping-cart-x" color="red"
- progress=8 %}
-
-
-
-
-
-
-
-
-
-
- {% include "cards/happy-birthday.html" %}
-
-
- {% include "cards/you-win.html" %}
-
-
-
-
-
-
-
- {% include "cards/weather.html" city="Warsaw, PL" temperature=3 color="rain" icon="cloud-rain"
- description="Cloudy morning" %}
-
-
- {% include "cards/weather.html" city="Oslo, NO" temperature="-5" color="snow" icon="cloud"
- description="Snowy day" %}
-
-
- {% include "cards/weather.html" city="Dubai, AE" temperature="32" color="sun" icon="sun" description="Sunny
- day" %}
-
-
- {% include "cards/profile-contact.html" person=people[6] %}
-
-
- {% include "cards/small-stats.html" chart-type="line" chart-data="11,16,13,20,17,24,19,23,16,20,13,17,11,19"
- color="primary" id="chart1" class="card-gradient card-gradient-end card-gradient-primary" %}
-
-
- {% include "cards/small-stats.html" id="sales" icon="arrow-up" color="green" title="$5,256.99"
- description="Revenue last 30 days" description-value="+4%" class="card-gradient card-gradient-end
- card-gradient-green" %}
-
-
- {% include "cards/small-stats.html" id="orders" icon="arrow-down" color="red" title="342" description="Sales
- last 30 days" description-value="-4.3%" description-value-color="red" class="card-gradient card-gradient-end
- card-gradient-red" %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/cards-masonry.astro b/preview/pages/cards-masonry.astro
new file mode 100644
index 000000000..a9e6af096
--- /dev/null
+++ b/preview/pages/cards-masonry.astro
@@ -0,0 +1,29 @@
+---
+// Port of preview/pages/cards-masonry.html.
+// The masonry library is loaded via page-libs=[masonry] (BaseLayout emits the
+// CDN
+
diff --git a/preview/pages/colors.html b/preview/pages/colors.html
deleted file mode 100644
index b977fc86c..000000000
--- a/preview/pages/colors.html
+++ /dev/null
@@ -1,240 +0,0 @@
----
-title: Colors
-page-header: Colors
-page-menu: base.colors
-layout: default
-permalink: colors.html
----
-
-{% assign colors = '' | split: '' %}
-{% for color in site.colors %}
-{% assign colors = colors | push: color[0] %}
-{% endfor %}
-
-
-
-
-
-
-
- {% for color in site.colors %}
-
-
-
-
- {{ color[1].abbr }}
-
-
-
- {{ color[1].title }}
- {{ color[1].hex }}
-
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
- {% for color in site.lightColors %}
-
-
-
-
- {{ color[1].abbr }}
-
-
-
- {{ color[1].title }}
- {{ color[1].hex }}
-
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
- {% for color in site.grayColors %}
-
-
-
-
- {{ color[1].abbr }}
-
-
-
- {{ color[1].title }}
- {{ color[1].hex }}
-
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
- {% for color in site.socialColors %}
-
-
-
-
- {% include "ui/icon.html" icon=color[1].icon %}
-
-
-
- {{ color[1].title }}
- {{ color[1].hex }}
-
-
-
- {% endfor %}
-
-
-
-
-
- {% assign colors = colors | push: 'inverted' %}
- {% assign colors = colors | push: 'white' %}
- {% assign colors = colors | push: 'transparent' %}
-
-
-
-
-
-
-
-
- {% for color in colors %}
-
-
- {% endfor %}
-
-
-
-
- {% for color in colors %}
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/cookie-banner.astro b/preview/pages/cookie-banner.astro
new file mode 100644
index 000000000..3fd997dc8
--- /dev/null
+++ b/preview/pages/cookie-banner.astro
@@ -0,0 +1,35 @@
+---
+// Port of preview/pages/cookie-banner.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+---
+
+
+
+
+
+
+
+
Do you like cookies? 🍪 We use cookies to ensure you get the best experience on our website.
+
Learn more
+
+
+
+ Essential Cookies Only
+
+
+
+
+ Allow All Cookies
+
+
+
+
+
+
+
diff --git a/preview/pages/cookie-banner.html b/preview/pages/cookie-banner.html
deleted file mode 100644
index 9a934fedc..000000000
--- a/preview/pages/cookie-banner.html
+++ /dev/null
@@ -1,29 +0,0 @@
----
-page-header: Cookie banner
-title: Cookie banner
-page-menu: extra.cookie-banner
-layout: default
-permalink: cookie-banner.html
----
-
-
-
-
-
-
-
Do you like cookies? 🍪 We use cookies to ensure you get the best experience on our website.
Learn more
-
-
-
- Essential Cookies Only
-
-
-
-
- Allow All Cookies
-
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/dashboard-crm.astro b/preview/pages/dashboard-crm.astro
new file mode 100644
index 000000000..692ae7ec0
--- /dev/null
+++ b/preview/pages/dashboard-crm.astro
@@ -0,0 +1,84 @@
+---
+// Port of preview/pages/dashboard-crm.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import CrmStats from '@shared/components/cards/CrmStats.astro';
+import MrrOverview from '@shared/components/cards/charts/MrrOverview.astro';
+import PipelineFunnel from '@shared/components/cards/charts/PipelineFunnel.astro';
+import TopDeals from '@shared/components/cards/TopDeals.astro';
+import RecentActivity from '@shared/components/cards/RecentActivity.astro';
+import TasksDue from '@shared/components/cards/TasksDue.astro';
+import TeamLeaderboard from '@shared/components/cards/TeamLeaderboard.astro';
+import ChurnRisk from '@shared/components/cards/ChurnRisk.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/dashboard-crm.html b/preview/pages/dashboard-crm.html
deleted file mode 100644
index 101faee6e..000000000
--- a/preview/pages/dashboard-crm.html
+++ /dev/null
@@ -1,81 +0,0 @@
----
-title: CRM Dashboard
-page-header: CRM Dashboard
-page-header-description: Welcome back — here's your CRM overview for today.
-page-menu: dashboards.crm
-page-libs: [apexcharts]
-layout: default
-permalink: dashboard-crm.html
----
-
-
-
-
-
- {% include "cards/crm-stats.html" color="primary" icon="currency-dollar" lt=true
- title="MRR" description="$92.4K" change-value="+9.5" %}
-
-
- {% include "cards/crm-stats.html" color="azure" icon="filter" lt=true
- title="Pipeline" description="$2.4M" change-value="+14" %}
-
-
- {% include "cards/crm-stats.html" color="green" icon="circle-check" lt=true
- title="Deals won" description="74" change-value="+8" %}
-
-
- {% include "cards/crm-stats.html" color="purple" icon="percentage" lt=true
- title="Conversion" description="5.97%" change-value="+0.4" %}
-
-
- {% include "cards/crm-stats.html" color="yellow" icon="activity" lt=true
- title="Activities" description="318" change-value="+22" %}
-
-
- {% include "cards/crm-stats.html" color="red" icon="clock" lt=true
- title="Tasks due" description="12" change-value="-3" change-value-unit=" urgent" %}
-
-
- {% include "cards/crm-stats.html" color="cyan" icon="user-plus" lt=true
- title="Leads added" description="148" change-value="+31" %}
-
-
- {% include "cards/crm-stats.html" color="green" icon="trending-up" lt=true
- title="Churn rate" description="1.8%" change-value="-0.3" %}
-
-
-
-
-
- {% include "cards/charts/mrr-overview.html" %}
-
-
-
- {% include "cards/top-deals.html" %}
-
-
-
-
-
-
-
- {% include "cards/charts/pipeline-funnel.html" %}
-
-
- {% include "cards/recent-activity.html" %}
-
-
-
-
-
- {% include "cards/tasks-due.html" %}
-
-
- {% include "cards/team-leaderboard.html" %}
-
-
- {% include "cards/churn-risk.html" %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/dashboard-crypto.astro b/preview/pages/dashboard-crypto.astro
new file mode 100644
index 000000000..79f1a80b7
--- /dev/null
+++ b/preview/pages/dashboard-crypto.astro
@@ -0,0 +1,334 @@
+---
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Trending from '@shared/components/ui/Trending.astro';
+import CardDropdown from '@shared/components/ui/CardDropdown.astro';
+import NavSegmented from '@shared/components/ui/NavSegmented.astro';
+import Chart from '@shared/components/Chart.astro';
+import SwitchIcon from '@shared/components/ui/SwitchIcon.astro';
+import cryptoCurrencies from '@data/crypto-currencies.json';
+import cryptoMarkets from '@data/crypto-markets.json';
+import cryptoOrders from '@data/crypto-orders.json';
+
+interface Currency {
+ symbol: string;
+ price: string;
+ p24h: number;
+ 'volume-24h': string;
+}
+
+const currencies = cryptoCurrencies as Currency[];
+const find = (symbol: string) => currencies.find((c) => c.symbol === symbol)!;
+const btc = find('BTC');
+const ltc = find('LTC');
+const eth = find('ETH');
+const xmr = find('XMR');
+
+const btcBalance = 2.3;
+const num = (s: string) => parseFloat(s.replace(/[$,]/g, ''));
+const btcPriceNum = num(btc.price);
+const totalUsd = Math.round(btcPriceNum * btcBalance).toLocaleString('en-US');
+// Liquid `divided_by` then `round: 8` (trailing zeros dropped by number output)
+const r8 = (x: number) => parseFloat(x.toFixed(8));
+const ltcBtc = r8(num(ltc.price) / btcPriceNum);
+const ethBtc = r8(num(eth.price) / btcPriceNum);
+const xmrBtc = r8(num(xmr.price) / btcPriceNum);
+
+const markets = (cryptoMarkets as { coin: string; price: string; volume: string; change: string }[]).slice(0, 10);
+const orders = cryptoOrders as { sell_orders: { price: string; btc: string; sum: string }[]; buy_orders: { price: string; btc: string; sum: string }[] };
+const operationCurrencies = currencies.slice(0, 20);
+---
+
+
+
+
+
+
+
+
+
+
+ ${totalUsd}
+ {btcBalance} {btc.symbol}
+
+
+
+ Since last week
+
+
+
+
+
+
+
+
+
+
+ {btc.price}
+ {btc.price}
+
+
+ Volume: {btc['volume-24h']}
+
+
+
+
+
+
+
+
+
+
+ {ltcBtc}
+ {ltc.price}
+
+
+ Volume: {ltc['volume-24h'].replace('$', '')}
+
+
+
+
+
+
+
+
+
+
+ {ethBtc}
+ {eth.price}
+
+
+ Volume: {eth['volume-24h'].replace('$', '')}
+
+
+
+
+
+
+
+
+
+
+ {xmrBtc}
+ {xmr.price}
+
+
+ Volume: {xmr['volume-24h'].replace('$', '')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Coin
+ Price
+ Volume
+ Change
+
+
+
+ {
+ markets.map((market) => (
+
+
+
+
+ {market.coin}
+ {market.price}
+ {market.volume}
+
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Place new order:
+
+
+ Amount
+
+ {
+ operationCurrencies.map((currency, i) => (
+
+ {currency.symbol}
+
+ ))
+ }
+
+
+
+
+
+ Price
+
+ $
+
+
+
+ Total
+
+ $
+
+
+
+ Process to wallet
+
+
+
The final amount could change depending on current market conditions.
+
+
+
+
+
+
+
+
+
+
+ Price
+ BTC
+ Sum(BTC)
+
+
+
+ {
+ orders.sell_orders.map((order) => (
+
+ {order.price}
+ {order.btc}
+ {order.sum}
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+
+ Price
+ BTC
+ Sum(BTC)
+
+
+
+ {
+ orders.buy_orders.map((order) => (
+
+ {order.price}
+ {order.btc}
+ {order.sum}
+
+ ))
+ }
+
+
+
+
+
+
+
+
diff --git a/preview/pages/dashboard-crypto.html b/preview/pages/dashboard-crypto.html
deleted file mode 100644
index b17148e0c..000000000
--- a/preview/pages/dashboard-crypto.html
+++ /dev/null
@@ -1,301 +0,0 @@
----
-title: Crypto Dashboard
-page-header: Crypto Dashboard
-page-menu: dashboards.crypto
-page-libs: [apexcharts]
-layout: default
-permalink: dashboard-crypto.html
----
-
-{% assign btc = crypto-currencies | where: "symbol", "BTC" | first %}
-{% assign ltc = crypto-currencies | where: "symbol", "LTC" | first %}
-{% assign eth = crypto-currencies | where: "symbol", "ETH" | first %}
-{% assign xmr = crypto-currencies | where: "symbol", "XMR" | first %}
-{% assign btc_balance = 2.30 %}
-{% assign btc_price_num = btc.price | remove: "$" | remove: "," | plus: 0 %}
-{% assign total_usd_raw = btc_price_num | times: btc_balance %}
-{% assign ltc_price_num = ltc.price | remove: "$" | remove: "," | plus: 0 %}
-{% assign eth_price_num = eth.price | remove: "$" | remove: "," | plus: 0 %}
-{% assign xmr_price_num = xmr.price | remove: "$" | remove: "," | plus: 0 %}
-{% assign ltc_btc = ltc_price_num | divided_by: btc_price_num %}
-{% assign eth_btc = eth_price_num | divided_by: btc_price_num %}
-{% assign xmr_btc = xmr_price_num | divided_by: btc_price_num %}
-
-
-
-
-
-
-
-
-
-
Total balance
-
-
- {% include "ui/avatar.html" icon="currency-dollar" %}
-
-
-
- ${{ total_usd_raw | round | format_number }}
- {{ btc_balance }} {{ btc.symbol }}
-
-
- {% include "ui/trending.html" value=btc.p24h %}
- Since last week
-
-
-
-
-
-
-
-
-
-
-
USD/BTC
-
-
- {% include "ui/avatar.html" icon="currency-bitcoin" %}
-
-
-
- {{ btc.price }}
- {{ btc.price}}
-
-
- Volume: {{ btc.volume-24h }}
-
-
-
-
-
-
-
-
-
-
-
LTC/BTC
-
-
- {% include "ui/avatar.html" icon="currency-litecoin" %}
-
-
-
- {{ ltc_btc | round: 8 }}
- {{ ltc.price }}
-
-
- Volume: {{ ltc.volume-24h | remove: "$" }}
-
-
-
-
-
-
-
-
-
-
-
ETH/BTC
-
-
- {% include "ui/avatar.html" icon="currency-ethereum" %}
-
-
-
- {{ eth_btc | round: 8 }}
- {{ eth.price }}
-
-
- Volume: {{ eth.volume-24h | remove: "$" }}
-
-
-
-
-
-
-
-
-
-
-
XMR/BTC
-
-
- {% include "ui/avatar.html" icon="currency-monero" %}
-
-
-
- {{ xmr_btc | round: 8 }}
- {{ xmr.price }}
-
-
- Volume: {{ xmr.volume-24h | remove: "$" }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/switch-icon.html" icon="star" icon-b-color="yellow" variant="slide-up" %}
-
- Coin
- Price
- Volume
- Change
-
-
-
- {% for market in crypto-markets limit: 10 %}
-
-
- {% include "ui/switch-icon.html" icon="star" icon-b-color="yellow" variant="slide-up" %}
-
- {{ market.coin }}
- {{ market.price }}
- {{ market.volume }}
-
- {% include "ui/trending.html" value=market.change %}
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
- {% include "ui/chart.html" chart-id="dashboard-crypto-candlestick" height=28 %}
-
-
-
-
-
-
-
-
-
-
-
-
-
Place new order:
-
-
- Amount
-
- {% for currency in crypto-currencies limit: 20 %}
- {{ currency.symbol }}
- {% endfor %}
-
-
-
-
-
- Price
-
- $
-
-
-
- Total
-
- $
-
-
-
- Process to wallet
-
-
-
The final amount could change depending on current market conditions.
-
-
-
-
-
-
-
-
-
-
- Price
- BTC
- Sum(BTC)
-
-
-
- {% for order in crypto-orders.sell_orders %}
-
- {{ order.price }}
- {{ order.btc }}
- {{ order.sum }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
- Price
- BTC
- Sum(BTC)
-
-
-
- {% for order in crypto-orders.buy_orders %}
-
- {{ order.price }}
- {{ order.btc }}
- {{ order.sum }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
diff --git a/preview/pages/datagrid.astro b/preview/pages/datagrid.astro
new file mode 100644
index 000000000..4ce84e098
--- /dev/null
+++ b/preview/pages/datagrid.astro
@@ -0,0 +1,16 @@
+---
+// Port of preview/pages/datagrid.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Datagrid from '@shared/components/parts/Datagrid.astro';
+---
+
+
+
+
diff --git a/preview/pages/datagrid.html b/preview/pages/datagrid.html
deleted file mode 100644
index 07b1e9442..000000000
--- a/preview/pages/datagrid.html
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: Data grid
-page-header: Data grid
-page-menu: base.datagrid
-layout: default
-permalink: datagrid.html
----
-
-
-
-
- {% include "parts/datagrid.html" %}
-
-
diff --git a/preview/pages/datatables.astro b/preview/pages/datatables.astro
new file mode 100644
index 000000000..e62c5a6d7
--- /dev/null
+++ b/preview/pages/datatables.astro
@@ -0,0 +1,84 @@
+---
+// Port of preview/pages/datatables.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import { liquidUnixSeconds, liquidLongDate } from '@shared/lib/liquid-date';
+import Progress from '@shared/components/ui/Progress.astro';
+import TablerList from '@shared/components/js/TablerList.astro';
+import rollercoasters from '@data/rollercoasters.json';
+
+const id = 'default';
+
+// Equivalent of the random_number / random_date filters from shared/e11ty/filters.mjs.
+function randomNumber(x: number, min = 0, max = 100): number {
+ let value =
+ ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) + min;
+ value = value > max ? max : value;
+ value = value < min ? min : value;
+ return Math.floor(value);
+}
+
+function randomDate(x: number): Date {
+ const start = new Date('2024-01-01').getTime() / 1000;
+ const end = new Date('2024-12-30').getTime() / 1000;
+ return new Date(randomNumber(x, start, end) * 1000);
+}
+
+
+const rows = (rollercoasters as Record[]).map((rc, i) => {
+ const index = i + 1;
+ const progress = randomNumber(index, 0, 100);
+ const date = randomDate(index);
+ return {
+ rc,
+ progress,
+ quantity: randomNumber(index, 1, 200),
+ dateSeconds: liquidUnixSeconds(date),
+ dateLabel: liquidLongDate(date),
+ };
+});
+
+const parameters =
+ "[ 'sort-name', 'sort-type', 'sort-city', 'sort-score', { attr: 'data-date', name: 'sort-date' }, { attr: 'data-progress', name: 'sort-progress' }, 'sort-quantity' ]";
+---
+
+
+
+
+
+
+
+
+ Name
+ City
+ Type
+ Score
+ Date
+ Quantity
+ Progress
+
+
+
+ {rows.map(({ rc, progress, quantity, dateSeconds, dateLabel }) => (
+
+ {rc.name}
+ {rc.city}
+ {rc.type}
+ {rc.score}
+ {dateLabel}
+ {quantity}
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
diff --git a/preview/pages/datatables.html b/preview/pages/datatables.html
deleted file mode 100644
index eed93fe07..000000000
--- a/preview/pages/datatables.html
+++ /dev/null
@@ -1,52 +0,0 @@
----
-title: Datatables
-page-header: Datatables
-page-libs: [lists]
-page-menu: plugins.datatables
-layout: default
-permalink: datatables.html
----
-
-{% assign id = include.map-id | default: 'default' %}
-
-
- {% assign products = 'Tabler,Tabler Icons,Tabler Emails,Tabler Components,Tabler Illustrations,Bootstrap' | split: ',' %}
- {% assign techs = 'brand-apple,brand-windows,brand-debian,brand-android' | split: ',' %}
-
-
-
-
- Name
- City
- Type
- Score
- Date
- Quantity
- Progress
-
-
-
- {% for rc in rollercoasters %}
- {% assign progress = forloop.index | random_number %}
-
- {{ rc.name }}
- {{ rc.city }}
- {{ rc.type }}
- {{ rc.score }}
- {{ forloop.index | random_date | date: '%B %d, %Y' }}
- {{ forloop.index | random_number: 1, 200 }}
-
-
-
{{ progress }}%
-
{% include "ui/progress.html" value=progress width="5rem" %}
-
-
-
- {% endfor %}
-
-
-
-
-
-
-{% include "js/tabler-list.html", parameters="[ 'sort-name', 'sort-type', 'sort-city', 'sort-score', { attr: 'data-date', name: 'sort-date' }, { attr: 'data-progress', name: 'sort-progress' }, 'sort-quantity' ]" %}
\ No newline at end of file
diff --git a/preview/pages/docs/index.html b/preview/pages/docs/index.html
deleted file mode 100644
index 293f11966..000000000
--- a/preview/pages/docs/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
----
-layout: redirect
-redirect:
- to: https://tabler.io/docs
-permalink: docs/index.html
----
\ No newline at end of file
diff --git a/preview/pages/dropdowns.astro b/preview/pages/dropdowns.astro
new file mode 100644
index 000000000..ca8162c3d
--- /dev/null
+++ b/preview/pages/dropdowns.astro
@@ -0,0 +1,42 @@
+---
+// Port of preview/pages/dropdowns.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import DropdownMenu from '@shared/components/ui/DropdownMenu.astro';
+import DropdownMenuAll from '@shared/components/ui/DropdownMenuAll.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/dropdowns.html b/preview/pages/dropdowns.html
deleted file mode 100644
index 1733476bf..000000000
--- a/preview/pages/dropdowns.html
+++ /dev/null
@@ -1,44 +0,0 @@
----
-title: Dropdowns
-page-header: Dropdowns
-page-menu: base.dropdowns
-layout: default
-permalink: dropdowns.html
----
-
-
-
- {% include "ui/dropdown-menu-all.html" show=true %}
-
-
- {% include "ui/dropdown-menu.html" show=true %}
- {% include "ui/dropdown-menu.html" show=true separated=true %}
- {% include "ui/dropdown-menu.html" show=true active=true %}
- {% include "ui/dropdown-menu.html" show=true disabled=true %}
- {% include "ui/dropdown-menu.html" show=true header=true %}
- {% include "ui/dropdown-menu.html" show=true icons=true header=true %}
- {% include "ui/dropdown-menu.html" show=true arrow=true %}
-
-
- {% include "ui/dropdown-menu.html" show=true %}
- {% include "ui/dropdown-menu.html" show=true separated=true %}
- {% include "ui/dropdown-menu.html" show=true active=true %}
- {% include "ui/dropdown-menu.html" show=true disabled=true %}
- {% include "ui/dropdown-menu.html" show=true header=true %}
- {% include "ui/dropdown-menu.html" show=true icons=true %}
- {% include "ui/dropdown-menu.html" show=true badge=true %}
-
-
- {% include "ui/dropdown-menu.html" show=true dark=true %}
- {% include "ui/dropdown-menu.html" show=true dark=true separated=true %}
- {% include "ui/dropdown-menu.html" show=true arrow=true right=true dark=true %}
- {% include "ui/dropdown-menu.html" show=true arrow=true right=true dark=true icons=true %}
- {% include "ui/dropdown-menu.html" show=true check=true %}
- {% include "ui/dropdown-menu.html" show=true radio=true %}
- {% include "ui/dropdown-menu.html" show=true people=true %}
- {% include "ui/dropdown-menu.html" show=true flag=true %}
-
-
-
-
-
diff --git a/preview/pages/dropzone.astro b/preview/pages/dropzone.astro
new file mode 100644
index 000000000..01b6a82cf
--- /dev/null
+++ b/preview/pages/dropzone.astro
@@ -0,0 +1,44 @@
+---
+// Port of preview/pages/dropzone.html (layout: default).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Dropzone from '@shared/components/ui/Dropzone.astro';
+---
+
+
+
+
+
+
+
+
Multiple File Upload
+
+
+
+
+
+
+
+
Custom Dropzone
+
+
+
+
+
+
diff --git a/preview/pages/dropzone.html b/preview/pages/dropzone.html
deleted file mode 100644
index 21947cc17..000000000
--- a/preview/pages/dropzone.html
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: Dropzone
-page-header: Dropzone
-page-menu: plugins.dropzone
-page-libs: [dropzone]
-layout: default
-permalink: dropzone.html
----
-
-
-
-
-
-
Basic Usage
- {% include "ui/dropzone.html" id="default" %}
-
-
-
-
-
-
-
Multiple File Upload
- {% include "ui/dropzone.html" id="multiple" multiple=true %}
-
-
-
-
-
-
-
Custom Dropzone
- {% include "ui/dropzone.html" id="custom" custom=true text="Your text here" description="Your custom description here" %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/email-inbox.astro b/preview/pages/email-inbox.astro
new file mode 100644
index 000000000..0296e61bc
--- /dev/null
+++ b/preview/pages/email-inbox.astro
@@ -0,0 +1,201 @@
+---
+// Port of preview/pages/email-inbox.html.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import Icon from '@shared/components/Icon.astro';
+import Progress from '@shared/components/ui/Progress.astro';
+import Modal from '@shared/components/modals/Modal.astro';
+import NewEmailModalContent from '@shared/components/modals/NewEmailModalContent.astro';
+import mails from '@data/mails.json';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ More
+
+
+
+
+
+
+
+ {mails && mails.length > 0 ? (
+ mails.map((mail) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))
+ ) : (
+ No emails
+ )}
+
+
+
+
+
+ Showing 1 - {mails.length} of {mails.length}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/email-inbox.html b/preview/pages/email-inbox.html
deleted file mode 100644
index 2765bcf7e..000000000
--- a/preview/pages/email-inbox.html
+++ /dev/null
@@ -1,193 +0,0 @@
----
-title: Email inbox
-page-header: Inbox
-page-menu: extra.email-inbox
-layout: default
-permalink: email-inbox.html
-page-libs: [ hugerte]
----
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="menu-2" %}
-
-
-
-
- {% include "ui/button.html" icon="archive" icon-only=true %}
- {% include "ui/button.html" icon="alert-octagon" icon-only=true %}
- {% include "ui/button.html" icon="trash" icon-only=true %}
-
-
-
-
- {% include "ui/icon.html" icon="folder" %}
-
-
-
-
-
-
- {% include "ui/icon.html" icon="tag" %}
-
-
-
-
-
-
- {% include "ui/icon.html" icon="dots" %} More
-
-
-
-
-
-
-
- {% if mails and mails.size > 0 %}
- {% for mail in mails %}
-
-
-
-
-
-
-
- {% endfor %}
- {% else %}
- No emails
- {% endif %}
-
-
-
-
-
- Showing 1 - {{ mails | size }} of {{ mails | size }}
-
-
-
- {% include "ui/icon.html" icon="chevron-left"
- %}
- {% include "ui/icon.html" icon="chevron-right"
- %}
-
-
-
-
-
-
-
-
-{% include "ui/modal.html" modal-id="new-email" %}
\ No newline at end of file
diff --git a/preview/pages/emails.astro b/preview/pages/emails.astro
new file mode 100644
index 000000000..ed7cb3e60
--- /dev/null
+++ b/preview/pages/emails.astro
@@ -0,0 +1,111 @@
+---
+// Port of preview/pages/emails.html.
+// Masonry auto-inits from the data-masonry attribute (page-lib, no init script,
+// like cards-masonry.astro); fslightbox is a pure page-lib (no init script).
+// The show.bs.modal handler is captured via {% capture_script %} → addPageScript.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import { site } from '@shared/lib/site';
+import { addPageScript } from '@shared/lib/page-scripts';
+import emails from '@data/emails.json';
+
+const emailEntries = Object.entries(emails);
+
+addPageScript(``);
+---
+
+
+
+
+
+
+
+
+
+
Tabler Emails
+
+ {emailEntries.length} eye-catching, customizable and responsive email templates to improve your email communication. No coding skills needed.
+
+
+
+
+
+
+
+
+
+ {emailEntries.map(([key, email]) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/emails.html b/preview/pages/emails.html
deleted file mode 100644
index e295266e2..000000000
--- a/preview/pages/emails.html
+++ /dev/null
@@ -1,101 +0,0 @@
----
-page-header: Email templates
-page-menu: addons.emails
-page-libs: [masonry, fslightbox]
-layout: default
-permalink: emails.html
----
-
-
-
-
-
-
- {% include "ui/icon.html" icon="mail" %}
-
-
-
-
-
-
Tabler Emails
-
- {{ emails | size }} eye-catching, customizable and responsive email templates to improve your email communication. No coding skills needed.
-
-
-
-
-
-
-
-
-
- {% for email in emails %}
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-{% capture_script %}
-
-{% endcapture_script %}
diff --git a/preview/pages/empty.astro b/preview/pages/empty.astro
new file mode 100644
index 000000000..a150ea7cc
--- /dev/null
+++ b/preview/pages/empty.astro
@@ -0,0 +1,8 @@
+---
+// Port of preview/pages/empty.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+---
+
+
+
+
diff --git a/preview/pages/empty.html b/preview/pages/empty.html
deleted file mode 100644
index 18934eed4..000000000
--- a/preview/pages/empty.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-title: Empty page
-page-menu: extra.empty
-page-header: Empty page
-layout: default
-permalink: empty.html
----
-
-
\ No newline at end of file
diff --git a/preview/pages/error-404.astro b/preview/pages/error-404.astro
new file mode 100644
index 000000000..0e317056f
--- /dev/null
+++ b/preview/pages/error-404.astro
@@ -0,0 +1,5 @@
+---
+import ErrorLayout from '@shared/layouts/ErrorLayout.astro';
+---
+
+
diff --git a/preview/pages/error-404.html b/preview/pages/error-404.html
deleted file mode 100644
index bf6024fc8..000000000
--- a/preview/pages/error-404.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Page 404
-layout: error
-page-error: 404
-page-menu: base.error.404
-permalink: error-404.html
----
diff --git a/preview/pages/error-500.astro b/preview/pages/error-500.astro
new file mode 100644
index 000000000..7fb554c8b
--- /dev/null
+++ b/preview/pages/error-500.astro
@@ -0,0 +1,5 @@
+---
+import ErrorLayout from '@shared/layouts/ErrorLayout.astro';
+---
+
+
diff --git a/preview/pages/error-500.html b/preview/pages/error-500.html
deleted file mode 100644
index e909c146f..000000000
--- a/preview/pages/error-500.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Page 500
-layout: error
-page-error: 500
-page-menu: base.error.500
-permalink: error-500.html
----
diff --git a/preview/pages/error-maintenance.astro b/preview/pages/error-maintenance.astro
new file mode 100644
index 000000000..d7f48ca48
--- /dev/null
+++ b/preview/pages/error-maintenance.astro
@@ -0,0 +1,5 @@
+---
+import ErrorLayout from '@shared/layouts/ErrorLayout.astro';
+---
+
+
diff --git a/preview/pages/error-maintenance.html b/preview/pages/error-maintenance.html
deleted file mode 100644
index 1e3204b2f..000000000
--- a/preview/pages/error-maintenance.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Maintenance mode
-layout: error
-page-error: maintenance
-page-menu: base.error.maintenance
-permalink: error-maintenance.html
----
diff --git a/preview/pages/faq.astro b/preview/pages/faq.astro
new file mode 100644
index 000000000..2b768de97
--- /dev/null
+++ b/preview/pages/faq.astro
@@ -0,0 +1,73 @@
+---
+// Port of preview/pages/faq.html.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import faq from '@data/faq.json';
+
+const categories = faq as { name: string; questions: { question: string }[] }[];
+---
+
+
+
+
+
+ {
+ categories.map((category, ci) => (
+
+
+ {ci + 1}. {category.name}
+
+
+ {category.questions.map((question, qi) => (
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+ Accusantium alias dignissimos dolorum ea est eveniet, excepturi
+ illum in iste iure maiores nemo recusandae rerum saepe sed, sunt
+ totam! Explicabo, ipsa?
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit.
+ Accusantium alias dignissimos dolorum ea est eveniet, excepturi
+ illum in iste iure maiores nemo recusandae rerum saepe sed, sunt
+ totam! Explicabo, ipsa?
+
+
+
+
+
+ ))}
+
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/faq.html b/preview/pages/faq.html
deleted file mode 100644
index 5eea4b7c8..000000000
--- a/preview/pages/faq.html
+++ /dev/null
@@ -1,43 +0,0 @@
----
-page-header: Frequently Asked Questions
-page-header-actions: breadcrumb
-page-menu: extra.faq
-layout: default
-permalink: faq.html
----
-
-
-
-
- {% for category in faq %}
- {% assign categories-loop = forloop %}
-
-
{{ categories-loop.index }}. {{ category.name }}
-
- {% for question in category.questions %}
- {% assign questions-loop = forloop %}
-
-
-
-
-
-
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium alias dignissimos dolorum ea est eveniet, excepturi illum in iste iure maiores nemo recusandae rerum saepe sed, sunt totam! Explicabo, ipsa?
-
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium alias dignissimos dolorum ea est eveniet, excepturi illum in iste iure maiores nemo recusandae rerum saepe sed, sunt totam! Explicabo, ipsa?
-
-
-
-
- {% endfor %}
-
-
- {% endfor %}
-
-
-
\ No newline at end of file
diff --git a/preview/pages/flags.astro b/preview/pages/flags.astro
new file mode 100644
index 000000000..c3e721104
--- /dev/null
+++ b/preview/pages/flags.astro
@@ -0,0 +1,35 @@
+---
+// Port of preview/pages/flags.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import flags from '@data/flags.json';
+
+// Liquid: {% for icon in (0..20) %}
{% endfor %} — 21 filler divs
+const fillers = Array.from({ length: 21 });
+---
+
+
+
+
+
+
+
+ {
+ flags.map((country) => (
+
+
+
+ ))
+ }
+ {fillers.map(() =>
)}
+
+
+
+
+
diff --git a/preview/pages/flags.html b/preview/pages/flags.html
deleted file mode 100644
index be7a37e87..000000000
--- a/preview/pages/flags.html
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: Flags
-page-header: Flags
-page-menu: addons.flags
-layout: default
-permalink: flags.html
----
-
-
-
-
-
-
- {% for country in flags %}
-
-
-
- {% endfor %}
- {% for icon in (0..20) %}
-
- {% endfor %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/forgot-password.astro b/preview/pages/forgot-password.astro
new file mode 100644
index 000000000..0dcddde99
--- /dev/null
+++ b/preview/pages/forgot-password.astro
@@ -0,0 +1,9 @@
+---
+// Port of preview/pages/forgot-password.html (layout: single)
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import ForgotPasswordCard from '@shared/components/cards/ForgotPasswordCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/forgot-password.html b/preview/pages/forgot-password.html
deleted file mode 100644
index 1a3b29eea..000000000
--- a/preview/pages/forgot-password.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Forgot password
-layout: single
-permalink: forgot-password.html
----
-
-{% include "cards/forgot-password.html" show-header="1" %}
diff --git a/preview/pages/form-elements.astro b/preview/pages/form-elements.astro
new file mode 100644
index 000000000..b867ed367
--- /dev/null
+++ b/preview/pages/form-elements.astro
@@ -0,0 +1,246 @@
+---
+// Port of preview/pages/form-elements.html
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import FormElements1 from '@shared/components/forms/FormElements1.astro';
+import FormElements2 from '@shared/components/forms/FormElements2.astro';
+import FormElements3 from '@shared/components/forms/FormElements3.astro';
+import FormElements4 from '@shared/components/forms/FormElements4.astro';
+import FormElements5 from '@shared/components/forms/FormElements5.astro';
+import FormElements6 from '@shared/components/forms/FormElements6.astro';
+import Layout from '@shared/components/cards/form/Layout.astro';
+import InputIcon from '@shared/components/ui/form/InputIcon.astro';
+import InputMask from '@shared/components/ui/form/InputMask.astro';
+import Button from '@shared/components/Button.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import people from '@data/people.json';
+
+const httpMethods = ['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'PATCH'];
+const comparisons = [
+ ['EQUALS', 'Equals'], ['NOT_EQUALS', 'Not equals'], ['HAS_KEY', 'Has key'],
+ ['NOT_HAS_KEY', 'Not has key'], ['HAS_VALUE', 'Has value'], ['NOT_HAS_VALUE', 'Not has value'],
+ ['IS_EMPTY', 'Is empty'], ['NOT_EMPTY', 'Is not empty'], ['GREATER_THAN', 'Greater than'],
+ ['LESS_THAN', 'Less than'],
+];
+const sources = [
+ ['STATUS_CODE', 'Status code'], ['JSON_BODY', 'JSON body'], ['HEADERS', 'Headers'],
+ ['TEXT_BODY', 'Text body'], ['RESPONSE_TIME', 'Response time'],
+];
+// assertion rows: [sourceSel, targetVal, comparisonSel]
+const rows = [
+ { source: 'STATUS_CODE', comparison: 'EQUALS', target: '200', prop: '' },
+ { source: 'JSON_BODY', comparison: 'HAS_VALUE', target: 'string', prop: 'parameters.alt.type' },
+ { source: 'RESPONSE_TIME', comparison: 'LESS_THAN', target: '500', prop: '' },
+ { source: 'HEADERS', comparison: 'EQUALS', target: 'application/json; charset=UTF-8', prop: 'content-type' },
+];
+---
+
+
+
+
+
+
+
+
+
Project ID
+
Used when interacting with the API.
+
+
+
+
+
+
+
+
+
+
Node.js Version
+
+ The version of Node.js that is used in the Build Step and for Serverless Functions. A new Deployment is required for your changes to take effect.
+
+
+ 14.x
+ 12.x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Date
+
Hour
+
Date & Hour
+
ZIP Code
+
Money
+
Telephone
+
Telephone with Code Area
+
IP Address
+
+
+
+
+
+
+
+
+
+
+
+
+
Edit Profile
+
+
+
+
+
+
+
+
+
+
+
+
+ About Me
+ Oh so, your weak rhyme
+You doubt I'll bother, reading into it
+I'll probably won't, left to my own devices
+But that's the difference in our opinions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Method
+
+ {httpMethods.map((m) => {m} )}
+
+
+
+ URL
+
+
+
+
Assertions
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/form-elements.html b/preview/pages/form-elements.html
deleted file mode 100644
index 9f110c743..000000000
--- a/preview/pages/form-elements.html
+++ /dev/null
@@ -1,422 +0,0 @@
----
-title: Form elements
-page-header: Form elements
-page-menu: form.elements
-page-libs: [nouislider, autosize, tabler-flags, tabler-payments, litepicker, tom-select, imask]
-layout: default
-permalink: form-elements.html
----
-
-
-
-
-
-
-
-
-
-
{% include "forms/form-elements-1.html" %}
-
{% include "forms/form-elements-2.html" %}
-
-
-
-
-
{% include "forms/form-elements-3.html" %}
-
{% include "forms/form-elements-4.html" %}
-
-
-
-
-
{% include "forms/form-elements-5.html" %}
-
{% include "forms/form-elements-6.html" %}
-
-
-
-
-
-
-
-
-
-
-
-
Project ID
-
Used when interacting with the API.
- {% include "ui/form/input-icon.html" icon="files" value="prj_5ae74426fe935327a8fa178b07d84ad9" readonly=true
- %}
-
-
-
-
-
-
-
-
-
Node.js Version
-
The version of Node.js that is used in the Build Step and for Serverless Functions.
- A new Deployment is required for your changes to take effect.
-
- 14.x
- 12.x
-
-
-
-
-
-
-
- {% include "cards/form/layout.html" %}
-
-
-
-
-
-
-
-
-
- Date
- {% include "ui/form/input-mask.html" mask="00/00/0000" visible=true %}
-
-
- Hour
- {% include "ui/form/input-mask.html" mask="00:00:00" visible=true %}
-
-
- Date & Hour
- {% include "ui/form/input-mask.html" mask="00/00/0000 00:00:00" visible=true %}
-
-
- ZIP Code
- {% include "ui/form/input-mask.html" mask="00000-000" visible=true %}
-
-
- Money
- {% include "ui/form/input-mask.html" mask="000.000.000.000.000,00" visible=true reverse=true %}
-
-
- Telephone
- {% include "ui/form/input-mask.html" mask="0000-0000" visible=true %}
-
-
- Telephone with Code Area
- {% include "ui/form/input-mask.html" mask="(00) 0000-0000" visible=true %}
-
-
- IP Address
- {% include "ui/form/input-mask.html" mask="099.099.099.099" placeholder="000.000.000.000" visible=true %}
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/avatar.html" person-id=3 size="md" %}
-
-
-
-
-
- Bio
- Big belly rude boy, million dollar hustler. Unemployed.
-
-
- Email-Address
-
-
-
- Password
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Edit Profile
-
-
-
-
-
-
-
-
-
-
-
- Country
-
- Germany
-
-
-
-
-
- About Me
- Oh so, your weak rhyme
-You doubt I'll bother, reading into it
-I'll probably won't, left to my own devices
-But that's the difference in our opinions.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method
-
- GET
- POST
- PUT
- HEAD
- DELETE
- PATCH
-
-
-
- URL
-
-
-
-
Assertions
-
-
-
-
-
-
-
-
diff --git a/preview/pages/form-layout.astro b/preview/pages/form-layout.astro
new file mode 100644
index 000000000..7d542246f
--- /dev/null
+++ b/preview/pages/form-layout.astro
@@ -0,0 +1,204 @@
+---
+// Port of preview/pages/form-layout.html
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import InputIcon from '@shared/components/ui/form/InputIcon.astro';
+import Check from '@shared/components/ui/form/Check.astro';
+import Icon from '@shared/components/Icon.astro';
+import Datepicker from '@shared/components/ui/Datepicker.astro';
+import Layout from '@shared/components/cards/form/Layout.astro';
+import Payment from '@shared/components/cards/form/Payment.astro';
+import flags from '@data/flags.json';
+
+const countries = flags as { name: string }[];
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+ First Name
+
+
+
+ Last Name
+
+
+
+ Email
+
+
+
+ Select Subject
+
+ Option 1 Option 2 Option 3 Option 4
+
+
+
+ Message
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Personal Info
+
+
+ First Name
+
+
+
+ Last Name
+
+
+
+
Gender
+
Male Female Others
+
+
+
+
+
Category
+
Category 1 Category 2 Category 3
+
+
Address
+
+ Street
+
+
+
+
City
+
State
+
Post Code
+
+
Country
+
+
+ --Select Country--
+ {countries.map((country) => {country.name} )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/form-layout.html b/preview/pages/form-layout.html
deleted file mode 100644
index 48c4af7eb..000000000
--- a/preview/pages/form-layout.html
+++ /dev/null
@@ -1,367 +0,0 @@
----
-title: Form layout
-page-header: Form Layout
-page-menu: form.layout
-layout: default
-permalink: form-layout.html
-page-libs: [litepicker]
----
-
-
-
-
-
-
-
-
-
-
-
-
-
- First Name
-
-
-
-
-
-
- Last Name
-
-
-
-
-
-
- Email
-
-
-
-
-
-
- Select Subject
-
-
-
- Option 1
-
-
- Option 2
-
-
- Option 3
-
-
- Option 4
-
-
-
-
-
-
- Message
-
-
-
-
-
- {% include "ui/button.html" color="primary" block text="Send Message" icon-end="arrow-right" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/form/input-icon.html" icon="user" placeholder="Username" prepend %}
-
-
-
- {% include "ui/form/input-icon.html" icon="mail" placeholder="Email address" prepend type="mail" %}
-
-
-
- {% include "ui/form/input-icon.html" icon="lock" placeholder="Password" prepend type="password" %}
-
-
-
- {% include "ui/form/input-icon.html" icon="lock" placeholder="Confirm Password" prepend type="password" %}
-
-
-
-
-
- {% include "ui/form/check.html" title="Remember me" class="m-0" %}
-
-
- {% include "ui/button.html" color="primary" text="Create Account" icon-end="arrow-right" %}
-
-
-
-
-
-
-
-
-
-
-
- {% include "cards/form/layout.html" horizontal=true title="Horizontal form" %}
-
-
-
-
-
-
-
-
-
-
- Personal Info
-
-
-
-
-
-
- First Name
-
-
-
-
-
-
- Last Name
-
-
-
-
-
-
- Gender
-
-
-
-
- Male
-
-
- Female
-
-
- Others
-
-
-
-
-
-
-
- Date of Birth
-
-
-
- {% include "ui/datepicker.html" layout="icon" id="birth-date" %}
-
-
-
-
-
-
- Category
-
-
-
-
- Category 1
-
-
- Category 2
-
-
- Category 3
-
-
-
-
-
-
-
- Address
-
-
-
-
-
- Street
-
-
-
-
-
-
-
- City
-
-
-
-
-
-
- State
-
-
-
-
-
-
- Post Code
-
-
-
-
-
-
- Country
-
-
-
-
- --Select Country--
-
- {% for country in flags %}
-
- {{ country.name }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
- Membership
-
-
-
- {% include "ui/form/check.html" title="Free" type="radio" name="membership" checked=true %}
- {% include "ui/form/check.html" title="Paid" type="radio" name="membership" %}
-
-
-
-
-
- {% include "ui/button.html" text="Cancel" %}
- {% include "ui/button.html" color="primary" text="Save Changes" %}
-
-
-
-
-
-
-
-
-
-
- {% include "cards/form/payment.html" %}
-
-
\ No newline at end of file
diff --git a/preview/pages/fullcalendar.astro b/preview/pages/fullcalendar.astro
new file mode 100644
index 000000000..931d88726
--- /dev/null
+++ b/preview/pages/fullcalendar.astro
@@ -0,0 +1,18 @@
+---
+// Port of preview/pages/fullcalendar.html (layout: default).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Fullcalendar from '@shared/components/ui/Fullcalendar.astro';
+---
+
+
+
+
diff --git a/preview/pages/fullcalendar.html b/preview/pages/fullcalendar.html
deleted file mode 100644
index 0c07a2b16..000000000
--- a/preview/pages/fullcalendar.html
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: Fullcalendar
-page-header: Fullcalendar
-page-menu: plugins.fullcalendar
-layout: default
-permalink: fullcalendar.html
-page-libs: [fullcalendar]
----
-
-
-
- {% include "ui/fullcalendar.html" sample-events %}
-
-
\ No newline at end of file
diff --git a/preview/pages/gallery.astro b/preview/pages/gallery.astro
new file mode 100644
index 000000000..ff6aa1360
--- /dev/null
+++ b/preview/pages/gallery.astro
@@ -0,0 +1,33 @@
+---
+// Port of preview/pages/gallery.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import GalleryPhoto from '@shared/components/cards/GalleryPhoto.astro';
+import Pagination from '@shared/components/ui/Pagination.astro';
+import photos from '@data/photos.json';
+import people from '@data/people.json';
+
+// Liquid: photos | where: "horizontal", true — limit: 15; person = people[forloop.index0]
+const galleryPhotos = photos.filter((photo) => photo.horizontal).slice(0, 15);
+---
+
+
+
+ {
+ galleryPhotos.map((photo, index) => (
+
+
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/gallery.html b/preview/pages/gallery.html
deleted file mode 100644
index 9597c58f4..000000000
--- a/preview/pages/gallery.html
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: Gallery
-page-header: Gallery
-page-header-description: 1-15 of 241 photos
-page-header-actions: photos
-page-menu: extra.gallery
-layout: default
-permalink: gallery.html
----
-
-{% assign filtered-photos = photos | where: "horizontal", true %}
-
-
- {% for photo in filtered-photos limit: 15 %}
- {% assign person = people[forloop.index0] %}
-
- {% include "cards/gallery-photo.html" person=person %}
-
- {% endfor %}
-
-
-
- {% include "ui/pagination.html" class="ms-auto" %}
-
diff --git a/preview/pages/icons.astro b/preview/pages/icons.astro
new file mode 100644
index 000000000..a229ecafb
--- /dev/null
+++ b/preview/pages/icons.astro
@@ -0,0 +1,24 @@
+---
+// Port of preview/pages/icons.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import IconsBanner from '@shared/components/cards/IconsBanner.astro';
+import Icons from '@shared/components/cards/Icons.astro';
+---
+
+
+
+
diff --git a/preview/pages/icons.html b/preview/pages/icons.html
deleted file mode 100644
index d1d503857..000000000
--- a/preview/pages/icons.html
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Icons
-page-header: Icons
-page-menu: addons.icons
-layout: default
-permalink: icons.html
----
-
-
-
- {% include "cards/icons-banner.html" %}
-
-
-
-
- {% include "cards/icons.html" title="Interface icons" type="outline" %}
-
-
- {% include "cards/icons.html" title="Filled icons" type="filled" %}
-
-
-
-
diff --git a/preview/pages/illustrations.astro b/preview/pages/illustrations.astro
new file mode 100644
index 000000000..e9e715071
--- /dev/null
+++ b/preview/pages/illustrations.astro
@@ -0,0 +1,217 @@
+---
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import freeIllustrations from '@data/free-illustrations.json';
+import illustrationsList from '@data/illustrations.json';
+import siteData from '@data/site.json';
+import { addPageScript } from '@shared/lib/page-scripts';
+
+const autodark = (freeIllustrations as { autodark: Record }).autodark;
+const autodarkEntries = Object.entries(autodark);
+
+// first-illustration: the Liquid loop overwrites each pass → last value wins.
+const firstIllustration = autodarkEntries.length
+ ? autodarkEntries[autodarkEntries.length - 1][1]
+ : '';
+
+// Page-local transform: replace: ' svg.replaceAll(';
+const skinColors = siteData.skinColors as Record;
+const colorEntries = Object.values(colors);
+const skinEntries = Object.values(skinColors);
+
+// skinColor = site.skinColors | first → the first value object (Rose).
+const skinFirst = skinEntries[0];
+const buyLink = (siteData.illustrations as { buy_link: string }).buy_link;
+
+// {{ illustrations | size | minus: 4 }}
+const moreCount = illustrationsList.length - 4;
+
+// {% capture_script %} — build the illustrations JS map from the same data.
+// skin_color / color[1].prop resolve to empty in Liquid → literal "var()".
+const illustrationsJs = autodarkEntries
+ .map(([key, svg]) => ` "${key}": {\n svg: '${withClass(svg)}',\n },`)
+ .join('\n \n');
+
+addPageScript(``);
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Primary color
+
+
+
Skin color
+
+ {
+ skinEntries.map((color, i) => (
+
+
+
+
+
+
+ ))
+ }
+
+
+
Select SVG illustration
+
+ {
+ autodarkEntries.map(([key, svg], i) => (
+
+
+
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {moreCount} more SVG Illustrations
+
+
+
+
+
+
+
+
+
+
Tabler Illustrations
+
+ Access a wide range of SVG illustrations for various projects. Effortlessly customize any illustration to align perfectly with your chosen color scheme!
+
+
+
+
+
+
+
+
+
+ {
+ illustrationsList.map((illustration) => (
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/illustrations.html b/preview/pages/illustrations.html
deleted file mode 100644
index 956a70a1b..000000000
--- a/preview/pages/illustrations.html
+++ /dev/null
@@ -1,184 +0,0 @@
----
-title: SVG Illustrations
-page-header: SVG Illustrations
-page-menu: addons.illustrations
-layout: default
-permalink: illustrations.html
----
-
-{% assign first-illustration = '' %}
-{% for illustration in free-illustrations.autodark %}
- {% assign first-illustration = illustration[1] %}
-{% endfor %}
-
-{% assign skinColor = site.skinColors | first %}
-{% assign color = site.colors | first %}
-
-
-
-
-
-
-
-
-
{{ first-illustration | replace: '
-
-
-
-
-
-
-
-
-
-
Primary color
-
-
-
Skin color
-
- {% for color in site.skinColors %}
-
-
-
-
-
-
- {% endfor %}
-
-
-
Select SVG illustration
-
- {% for illustration in free-illustrations.autodark %}
-
-
-
-
- {{ illustration[1] | replace: '
-
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ illustrations | size | minus: 4 }} more SVG Illustrations
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="brand-figma" %}
-
-
-
-
-
-
Tabler Illustrations
-
- Access a wide range of SVG illustrations for various projects. Effortlessly customize any illustration to align perfectly with your chosen color scheme!
-
-
-
-
-
-
-
-
-
- {% for illustration in illustrations %}
-
- {% endfor %}
-
-
-
-
-
-{% capture_script %}
-
-{% endcapture_script %}
diff --git a/preview/pages/index.astro b/preview/pages/index.astro
new file mode 100644
index 000000000..84f25334b
--- /dev/null
+++ b/preview/pages/index.astro
@@ -0,0 +1,16 @@
+---
+// Port preview/pages/index.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/index.html b/preview/pages/index.html
deleted file mode 100644
index a168fc7e9..000000000
--- a/preview/pages/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
----
-page-menu: dashboards.default
-layout: homepage
-permalink: index.html
----
-
diff --git a/preview/pages/inline-player.astro b/preview/pages/inline-player.astro
new file mode 100644
index 000000000..627fd4185
--- /dev/null
+++ b/preview/pages/inline-player.astro
@@ -0,0 +1,32 @@
+---
+// Port of preview/pages/inline-player.html (layout: default).
+// Liquid: {% for provider in inline-players %} → one card per provider.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import InlinePlayer from '@shared/components/ui/InlinePlayer.astro';
+import players from '@data/inline-players.json';
+
+type Provider = { title: string; type: string; id: string; 'embed-id': string | number };
+---
+
+
+
+ {
+ (players as Provider[]).map((provider) => (
+
+
+
+
{provider.title}
+
+
+
+
+
+ ))
+ }
+
+
diff --git a/preview/pages/inline-player.html b/preview/pages/inline-player.html
deleted file mode 100644
index 2f491a6a4..000000000
--- a/preview/pages/inline-player.html
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Inline Player
-page-header: Inline Player
-page-menu: plugins.plyr
-page-libs: [plyr]
-layout: default
-permalink: inline-player.html
----
-
-
- {% for provider in inline-players %}
-
-
-
-
-
{{ provider.title }}
-
- {% include "ui/inline-player.html" id=provider.id type=provider.type embed-id=provider.embed-id %}
-
-
-
- {% endfor %}
-
\ No newline at end of file
diff --git a/preview/pages/invoice.astro b/preview/pages/invoice.astro
new file mode 100644
index 000000000..773553e45
--- /dev/null
+++ b/preview/pages/invoice.astro
@@ -0,0 +1,9 @@
+---
+// Port of preview/pages/invoice.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import InvoiceCard from '@shared/components/cards/InvoiceCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/invoice.html b/preview/pages/invoice.html
deleted file mode 100644
index 0a330c7bc..000000000
--- a/preview/pages/invoice.html
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: Invoice
-layout: default
-page-menu: extra.invoice
-page-header: Invoice
-page-header-actions: print
-permalink: invoice.html
----
-
-{% include "cards/invoice.html" %}
diff --git a/preview/pages/job-listing.astro b/preview/pages/job-listing.astro
new file mode 100644
index 000000000..73525232c
--- /dev/null
+++ b/preview/pages/job-listing.astro
@@ -0,0 +1,153 @@
+---
+// Port of preview/pages/job-listing.html (layout: default)
+// NOTE: page-header-actions "add-job" requires PageHeader.astro to dispatch it
+// to HeaderActionsAddJob — see the migration report (PageHeader.astro is a
+// shared component and was not modified here).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+import Check from '@shared/components/ui/form/Check.astro';
+import jobsData from '@data/jobs.json';
+
+interface Job {
+ company: string;
+ location: string;
+ title: string;
+ type: string;
+ image: string;
+ salary?: string;
+ tags: string[];
+}
+
+const jobs = jobsData as Job[];
+
+const types = ['Programming', 'Design', 'Management / Finance', 'Customer Support', 'Sales / Marketing'];
+const salaries = ['$20K - $50K', '$50K - $100K', '> $100K', 'Drawing / Painting'];
+---
+
+
+
+
+
+ Job Types
+
+ {
+ types.map((type, i) => (
+
+
+ {type}
+
+ ))
+ }
+
+
+ Remote
+
+
+
+
+ Salary Range
+
+ {
+ salaries.map((salary, i) => (
+
+
+ {salary}
+
+ ))
+ }
+
+
+ Immigration
+
+
+
+
Only show companies that can sponsor a visa
+
+
+ Location
+
+
+ Anywhere
+ London
+ San Francisco
+ New York
+ Berlin
+
+
+
+
+
+
+
+
+
+ {
+ jobs.map((job) => (
+
+
+
+
+
+
+
+ {job.salary &&
{job.salary}
}
+
+
+
+
+
+ {job.company}
+
+
+ {job.type}
+
+
+ {job.location}
+
+
+
+
+ {job.company}
+
+
+ {job.type}
+
+
+ {job.location}
+
+
+
+
+
+ {job.tags.map((tag) => (
+
{tag}
+ ))}
+
+
+
+
+
+
+
+ ))
+ }
+
+
+
+
+
diff --git a/preview/pages/job-listing.html b/preview/pages/job-listing.html
deleted file mode 100644
index aecded73d..000000000
--- a/preview/pages/job-listing.html
+++ /dev/null
@@ -1,117 +0,0 @@
----
-title: Search for Jobs
-page-header: Search for Jobs
-page-header-actions: add-job
-page-menu: extra.job-listing
-layout: default
-permalink: job-listing.html
----
-
-{% assign types = 'Programming,Design,Management / Finance,Customer Support,Sales / Marketing' | split: ',' %}
-{% assign salaries = '$20K - $50K,$50K - $100K,> $100K,Drawing / Painting' | split: ',' %}
-
-
-
-
-
- Job Types
-
- {% for type in types %}
-
-
- {{ type }}
-
- {% endfor %}
-
-
- Remote
-
- {% include "ui/form/check.html" switch=true title-on="On" title-off="Off" %}
-
-
- Salary Range
-
- {% for salary in salaries %}
-
-
- {{ salary }}
-
- {% endfor %}
-
-
- Immigration
-
- {% include "ui/form/check.html" switch=true title-on="On" title-off="Off" %}
-
-
Only show companies that can sponsor a visa
-
-
- Location
-
-
- Anywhere
- London
- San Francisco
- New York
- Berlin
-
-
-
-
-
-
-
-
-
-
- {% for job in jobs %}
-
-
-
-
-
-
-
- {% if job.salary %}
{{ job.salary }}
{% endif %}
-
-
-
-
-
{% include "ui/icon.html" icon="building-community" class="icon-inline" %} {{ job.company }}
-
{% include "ui/icon.html" icon="license" class="icon-inline" %} {{ job.type }}
-
{% include "ui/icon.html" icon="map-pin" class="icon-inline" %} {{ job.location }}
-
-
-
{% include "ui/icon.html" icon="building-community" class="icon-inline" %} {{ job.company }}
-
{% include "ui/icon.html" icon="license" class="icon-inline" %} {{ job.type }}
-
{% include "ui/icon.html" icon="map-pin" class="icon-inline" %} {{ job.location }}
-
-
-
-
- {% for tag in job.tags %}
-
{{ tag }}
- {% endfor %}
-
-
-
-
-
-
-
- {% endfor %}
-
-
-
-
diff --git a/preview/pages/layout-boxed.astro b/preview/pages/layout-boxed.astro
new file mode 100644
index 000000000..4b476c87e
--- /dev/null
+++ b/preview/pages/layout-boxed.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-boxed.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-boxed.html b/preview/pages/layout-boxed.html
deleted file mode 100644
index 665e648a6..000000000
--- a/preview/pages/layout-boxed.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-page-header: Boxed layout
-page-menu: layout.boxed
-body-class: layout-boxed
-layout: homepage
-permalink: layout-boxed.html
----
diff --git a/preview/pages/layout-combo.astro b/preview/pages/layout-combo.astro
new file mode 100644
index 000000000..6fe8f1d6d
--- /dev/null
+++ b/preview/pages/layout-combo.astro
@@ -0,0 +1,21 @@
+---
+// Port of preview/pages/layout-combo.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-combo.html b/preview/pages/layout-combo.html
deleted file mode 100644
index c7f9aba7f..000000000
--- a/preview/pages/layout-combo.html
+++ /dev/null
@@ -1,12 +0,0 @@
----
-page-header: Combo layout
-page-menu: layout.combo
-layout-sidebar: true
-layout-sidebar-dark: true
-layout-navbar-hide-brand: true
-layout-navbar-hide-page-menu: true
-layout-navbar-class: "d-none d-lg-flex"
-layout-navbar-condensed: true
-layout: homepage
-permalink: layout-combo.html
----
\ No newline at end of file
diff --git a/preview/pages/layout-condensed.astro b/preview/pages/layout-condensed.astro
new file mode 100644
index 000000000..2bce0cb87
--- /dev/null
+++ b/preview/pages/layout-condensed.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-condensed.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-condensed.html b/preview/pages/layout-condensed.html
deleted file mode 100644
index 06f0557f5..000000000
--- a/preview/pages/layout-condensed.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-page-header: Condensed layout
-page-menu: layout.condensed
-layout-navbar-condensed: true
-layout: homepage
-permalink: layout-condensed.html
----
\ No newline at end of file
diff --git a/preview/pages/layout-fluid-vertical.astro b/preview/pages/layout-fluid-vertical.astro
new file mode 100644
index 000000000..e959486cf
--- /dev/null
+++ b/preview/pages/layout-fluid-vertical.astro
@@ -0,0 +1,20 @@
+---
+// Port of preview/pages/layout-fluid-vertical.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-fluid-vertical.html b/preview/pages/layout-fluid-vertical.html
deleted file mode 100644
index b41c32a7d..000000000
--- a/preview/pages/layout-fluid-vertical.html
+++ /dev/null
@@ -1,10 +0,0 @@
----
-page-header: Fluid vertical layout
-page-menu: layout.fluid-vertical
-body-class: layout-fluid
-layout-sidebar: true
-layout-sidebar-dark: true
-layout-hide-topbar: true
-layout: homepage
-permalink: layout-fluid-vertical.html
----
diff --git a/preview/pages/layout-fluid.astro b/preview/pages/layout-fluid.astro
new file mode 100644
index 000000000..1a4bf8790
--- /dev/null
+++ b/preview/pages/layout-fluid.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-fluid.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-fluid.html b/preview/pages/layout-fluid.html
deleted file mode 100644
index b973d9675..000000000
--- a/preview/pages/layout-fluid.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-page-header: Fluid layout
-page-menu: layout.fluid
-body-class: layout-fluid
-layout: homepage
-permalink: layout-fluid.html
----
diff --git a/preview/pages/layout-horizontal.astro b/preview/pages/layout-horizontal.astro
new file mode 100644
index 000000000..00a27216a
--- /dev/null
+++ b/preview/pages/layout-horizontal.astro
@@ -0,0 +1,16 @@
+---
+// Port of preview/pages/layout-horizontal.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-horizontal.html b/preview/pages/layout-horizontal.html
deleted file mode 100644
index c0594789b..000000000
--- a/preview/pages/layout-horizontal.html
+++ /dev/null
@@ -1,6 +0,0 @@
----
-page-header: Horizontal layout
-page-menu: layout.horizontal
-layout: homepage
-permalink: layout-horizontal.html
----
\ No newline at end of file
diff --git a/preview/pages/layout-navbar-dark.astro b/preview/pages/layout-navbar-dark.astro
new file mode 100644
index 000000000..9cb4abfca
--- /dev/null
+++ b/preview/pages/layout-navbar-dark.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-navbar-dark.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-navbar-dark.html b/preview/pages/layout-navbar-dark.html
deleted file mode 100644
index a273a8d7c..000000000
--- a/preview/pages/layout-navbar-dark.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-page-header: Navbar dark
-page-menu: layout.navbar-dark
-layout-navbar-dark: true
-layout: homepage
-permalink: layout-navbar-dark.html
----
\ No newline at end of file
diff --git a/preview/pages/layout-navbar-overlap.astro b/preview/pages/layout-navbar-overlap.astro
new file mode 100644
index 000000000..a06926903
--- /dev/null
+++ b/preview/pages/layout-navbar-overlap.astro
@@ -0,0 +1,19 @@
+---
+// Port of preview/pages/layout-navbar-overlap.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-navbar-overlap.html b/preview/pages/layout-navbar-overlap.html
deleted file mode 100644
index 0020fb545..000000000
--- a/preview/pages/layout-navbar-overlap.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-page-header: Navbar overlap layout
-page-menu: layout.navbar-overlap
-layout-navbar-overlap: true
-layout-navbar-condensed: true
-layout-navbar-dark: true
-layout: homepage
-permalink: layout-navbar-overlap.html
----
diff --git a/preview/pages/layout-navbar-sticky.astro b/preview/pages/layout-navbar-sticky.astro
new file mode 100644
index 000000000..037f597f6
--- /dev/null
+++ b/preview/pages/layout-navbar-sticky.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-navbar-sticky.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-navbar-sticky.html b/preview/pages/layout-navbar-sticky.html
deleted file mode 100644
index bf3e6c150..000000000
--- a/preview/pages/layout-navbar-sticky.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-page-header: Navbar sticky
-page-menu: layout.navbar-sticky
-layout-navbar-sticky: true
-layout: homepage
-permalink: layout-navbar-sticky.html
----
\ No newline at end of file
diff --git a/preview/pages/layout-rtl.astro b/preview/pages/layout-rtl.astro
new file mode 100644
index 000000000..bbe7741b2
--- /dev/null
+++ b/preview/pages/layout-rtl.astro
@@ -0,0 +1,17 @@
+---
+// Port of preview/pages/layout-rtl.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-rtl.html b/preview/pages/layout-rtl.html
deleted file mode 100644
index f369e0655..000000000
--- a/preview/pages/layout-rtl.html
+++ /dev/null
@@ -1,8 +0,0 @@
----
-page-header: RTL mode
-page-menu: home
-layout-rtl: true
-title: RTL mode
-layout: homepage
-permalink: layout-rtl.html
----
diff --git a/preview/pages/layout-vertical-right.astro b/preview/pages/layout-vertical-right.astro
new file mode 100644
index 000000000..3a4318669
--- /dev/null
+++ b/preview/pages/layout-vertical-right.astro
@@ -0,0 +1,19 @@
+---
+// Port of preview/pages/layout-vertical-right.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-vertical-right.html b/preview/pages/layout-vertical-right.html
deleted file mode 100644
index 7688db60b..000000000
--- a/preview/pages/layout-vertical-right.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-page-header: Right vertical layout
-page-menu: layout.vertical-end
-layout-sidebar: true
-layout-sidebar-end: true
-layout-hide-topbar: true
-layout: homepage
-permalink: layout-vertical-right.html
----
diff --git a/preview/pages/layout-vertical-transparent.astro b/preview/pages/layout-vertical-transparent.astro
new file mode 100644
index 000000000..2cd7e2746
--- /dev/null
+++ b/preview/pages/layout-vertical-transparent.astro
@@ -0,0 +1,19 @@
+---
+// Port of preview/pages/layout-vertical-transparent.html (layout: homepage)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-vertical-transparent.html b/preview/pages/layout-vertical-transparent.html
deleted file mode 100644
index b1bb6ba5e..000000000
--- a/preview/pages/layout-vertical-transparent.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-page-header: Vertical transparent layout
-page-menu: layout.vertical-transparent
-layout-sidebar: true
-layout-navbar-transparent: true
-layout-hide-topbar: true
-layout: homepage
-permalink: layout-vertical-transparent.html
----
diff --git a/preview/pages/layout-vertical.astro b/preview/pages/layout-vertical.astro
new file mode 100644
index 000000000..ce49d9eca
--- /dev/null
+++ b/preview/pages/layout-vertical.astro
@@ -0,0 +1,21 @@
+---
+// Port preview/pages/layout-vertical.html:
+// layout-sidebar: true, layout-sidebar-dark: true, layout-hide-topbar: true,
+// layout: homepage (page-header overridden by the page front matter)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import HomepageContent from '@shared/components/HomepageContent.astro';
+---
+
+
+
+
diff --git a/preview/pages/layout-vertical.html b/preview/pages/layout-vertical.html
deleted file mode 100644
index 5b7f3cad1..000000000
--- a/preview/pages/layout-vertical.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-page-header: Vertical layout
-page-menu: layout.vertical
-layout-sidebar: true
-layout-sidebar-dark: true
-layout-hide-topbar: true
-layout: homepage
-permalink: layout-vertical.html
----
diff --git a/preview/pages/license.astro b/preview/pages/license.astro
new file mode 100644
index 000000000..60c0efd59
--- /dev/null
+++ b/preview/pages/license.astro
@@ -0,0 +1,99 @@
+---
+// Port of preview/pages/license.html (layout: default)
+// The prose is shared/includes/license.md rendered via `renderContent: "md"`
+// (markdown-it). The rendered HTML is inlined verbatim from the reference build
+// to guarantee a 1:1 DOM match — Astro's markdown pipeline (remark + smartypants)
+// would produce different quote characters and structure.
+// TODO: source of truth remains shared/includes/license.md; regenerate this
+// block if the markdown changes.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+
+const licenseHtml = `
+
This is a legal agreement between you, the Purchaser, and Tabler. Purchasing or downloading of any Tabler product (Tabler Free, Tabler PRO, Tabler Email), constitutes your acceptance of the terms of this license, Tabler terms of service and Tabler private policy .
+
A license grants you a non-exclusive and non-transferable right to use and incorporate the item in your personal or commercial projects.
+
Tabler Free License
+
Tabler Free is available under MIT License
+
Copyright 2026 Tabler
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
Tabler PRO and Tabler Email License
+
After Purchasing you are granted the use products under the conditions featured belowed.
+
Rights
+
+You have rights to use our resources for any or all of your personal and commercial projects.
+You may modify the resources according to your requirements.
+You are not required to attribute or link to Tabler in any of your projects.
+
+
Restrictions
+
+You do not have the rights to redistribute, resell, lease, license, sub-license or offer the file downloaded to any third party.
+For any resalable web applications or software programs, you cannot include our graphic resources as an additional attachment.
+You cannot redistribute any of the software, or products created with Tabler paid products.
+You cannot add our source code to any open source repository.
+The source code may not be placed on any website in a complete or archived downloadable format.
+
+`;
+---
+
+
+
+
+
+
+
+
+
+
+
+
+ tabler/tabler is licensed under the
+
MIT License
+
+
+
+
+ A short and simple permissive license with conditions only requiring preservation of copyright and
+ license notices. Licensed works, modifications, and larger works may be distributed under different terms
+ and without source code.
+
+
+
+
Permissions
+
+
+ Commercial use
+ Modification
+ Distribution
+ Private use
+
+
+
+
Limitations
+
+
+
Conditions
+
+ License and copyright notice
+
+
+
+
+
+
+
diff --git a/preview/pages/license.html b/preview/pages/license.html
deleted file mode 100644
index f8e4ad429..000000000
--- a/preview/pages/license.html
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: License
-page-header: Tabler License
-page-menu: extra.license
-layout: default
-permalink: license.html
----
-
-
-
-
-
-
- {% capture license %}{% include "license.md" %}{%- endcapture %}
- {{ license | renderContent: "md" }}
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="scale" size="md" %}
-
-
- tabler/tabler is licensed under the
-
MIT License
-
-
-
-
- A short and simple permissive license with conditions only requiring preservation of copyright and
- license notices. Licensed works, modifications, and larger works may be distributed under different terms
- and without source code.
-
-
-
-
Permissions
-
-
- {% include "ui/icon.html" icon="check" class="text-green" %} Commercial use
- {% include "ui/icon.html" icon="check" class="text-green" %} Modification
- {% include "ui/icon.html" icon="check" class="text-green" %} Distribution
- {% include "ui/icon.html" icon="check" class="text-green" %} Private use
-
-
-
-
Limitations
-
- {% include "ui/icon.html" icon="x" class="text-red" %} Liability
- {% include "ui/icon.html" icon="x" class="text-red" %} Warranty
-
-
-
Conditions
-
- {% include "ui/icon.html" icon="info-circle" class="text-blue" %} License and copyright notice
-
-
-
-
-
-
diff --git a/preview/pages/lightbox.astro b/preview/pages/lightbox.astro
new file mode 100644
index 000000000..9d901f826
--- /dev/null
+++ b/preview/pages/lightbox.astro
@@ -0,0 +1,29 @@
+---
+// Port of preview/pages/lightbox.html (layout: default).
+// Liquid: photos | where: "horizontal", true — the gallery iterates the filtered
+// list for both the fslightbox href and the Photo include.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Photo from '@shared/components/ui/Photo.astro';
+import photos from '@data/photos.json';
+
+const filteredPhotos = photos.filter((photo) => photo.horizontal);
+---
+
+
+
+ {
+ filteredPhotos.map((photo) => (
+
+ ))
+ }
+
+
diff --git a/preview/pages/lightbox.html b/preview/pages/lightbox.html
deleted file mode 100644
index 7a873eb6f..000000000
--- a/preview/pages/lightbox.html
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: Lightbox
-page-header: Lightbox
-page-libs: [fslightbox]
-page-menu: plugins.lightbox
-layout: default
-permalink: lightbox.html
----
-
-{% assign filtered-photos = photos | where: "horizontal", true %}
-
-
- {% for photo in filtered-photos %}
-
- {% endfor %}
-
diff --git a/preview/pages/lists.astro b/preview/pages/lists.astro
new file mode 100644
index 000000000..0f10771d0
--- /dev/null
+++ b/preview/pages/lists.astro
@@ -0,0 +1,48 @@
+---
+// Port of preview/pages/lists.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import UsersList from '@shared/components/cards/UsersList.astro';
+import UsersList2 from '@shared/components/cards/UsersList2.astro';
+import UsersListHeaders from '@shared/components/cards/UsersListHeaders.astro';
+---
+
+
+
+
diff --git a/preview/pages/lists.html b/preview/pages/lists.html
deleted file mode 100644
index 5c1e990b1..000000000
--- a/preview/pages/lists.html
+++ /dev/null
@@ -1,46 +0,0 @@
----
-page-menu: base.lists
-title: Lists
-page-header: Lists
-layout: default
-permalink: lists.html
----
-
-
-
-
-
- {% include "cards/users-list-2.html" %}
-
-
- {% include "cards/users-list.html" offset=8 checkbox=true hover=true checked-ids="2,5,8" title="Contacts" %}
-
-
-
-
-
-
-
- {% include "cards/users-list.html" hoverable=true %}
-
-
- {% include "cards/users-list-headers.html" %}
-
-
-
-
diff --git a/preview/pages/logs.astro b/preview/pages/logs.astro
new file mode 100644
index 000000000..b9928ea61
--- /dev/null
+++ b/preview/pages/logs.astro
@@ -0,0 +1,69 @@
+---
+// Port of preview/pages/logs.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Badge from '@shared/components/ui/Badge.astro';
+import { site } from '@shared/lib/site';
+---
+
+
+
+
+
+
+
+ Checked URL
+
+
+
+
Request Timing
+
+
Effective URL {site.previewUrl} Redirect count 0 Name lookup time 3.4e-05 Connect time 0.000521 Pre-transfer time 0.0 Start-transfer time 0.0 App connect time 0.0 Redirect time 0.0 Total time 28.000601 Response code 0 Return keyword operation_timedout
+
+
+
Response Headers
+
+
HTTP/1.1 200 Connection established
+
+
+
+
+
+
+
+
+
+ Application Log
+
+
+
2024-01-15 14:23:45 [INFO] Application started successfully
+2024-01-15 14:23:46 [DEBUG] Database connection established
+2024-01-15 14:23:47 [INFO] User authentication successful: user_id=12345
+2024-01-15 14:23:48 [WARNING] Rate limit approaching: 85% of quota used
+2024-01-15 14:23:49 [ERROR] Failed to process payment: transaction_id=tx_789
+2024-01-15 14:23:50 [INFO] Cache cleared: keys=1523
+2024-01-15 14:23:51 [DEBUG] API request completed: endpoint=/api/users, duration=234ms
+
+
+
Log Levels
+
+
+
+
+
+
+
diff --git a/preview/pages/logs.html b/preview/pages/logs.html
deleted file mode 100644
index 8b620a226..000000000
--- a/preview/pages/logs.html
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: Logs
-page-header: Logs
-page-menu: extra.logs
-layout: default
-permalink: logs.html
----
-
-
-
-
-
-
- Checked URL
-
-
-
-
Request Timing
-
-
Effective URL {{ site.previewUrl }} Redirect count 0 Name lookup time 3.4e-05 Connect time 0.000521 Pre-transfer time 0.0 Start-transfer time 0.0 App connect time 0.0 Redirect time 0.0 Total time 28.000601 Response code 0 Return keyword operation_timedout
-
-
-
Response Headers
-
-
HTTP/1.1 200 Connection established
-
-
-
-
-
-
-
-
-
- Application Log
-
-
-
2024-01-15 14:23:45 [INFO] Application started successfully
-2024-01-15 14:23:46 [DEBUG] Database connection established
-2024-01-15 14:23:47 [INFO] User authentication successful: user_id=12345
-2024-01-15 14:23:48 [WARNING] Rate limit approaching: 85% of quota used
-2024-01-15 14:23:49 [ERROR] Failed to process payment: transaction_id=tx_789
-2024-01-15 14:23:50 [INFO] Cache cleared: keys=1523
-2024-01-15 14:23:51 [DEBUG] API request completed: endpoint=/api/users, duration=234ms
-
-
-
Log Levels
-
-
- {% include "ui/badge.html" text="INFO" color="success" %}
- {% include "ui/badge.html" text="WARNING" color="warning" %}
- {% include "ui/badge.html" text="ERROR" color="disabled" %}
- {% include "ui/badge.html" text="DEBUG" color="disabled" %}
-
-
-
-
-
-
-
diff --git a/preview/pages/map-fullsize.astro b/preview/pages/map-fullsize.astro
new file mode 100644
index 000000000..72e4c0e52
--- /dev/null
+++ b/preview/pages/map-fullsize.astro
@@ -0,0 +1,41 @@
+---
+// Port of preview/pages/map-fullsize.html.
+// Front matter: layout-wrapper-full + layout-sidebar + layout-hide-topbar,
+// page-libs: [google-maps], page-menu: plugins.map-fullsize. No title / no
+// page-header (the page-header block renders empty in the reference).
+//
+// {% assign map-id = 'google' %} → id="map-google".
+// The {% capture_script %} block is registered synchronously (before any await).
+// We mirror the development build (environment == 'development'), so the
+// `window.tabler_map` bookkeeping lines are emitted (as in the reference).
+//
+// REQUIRES DefaultLayout `wrapperFull` support (see report): page-wrapper-full
+// class + slot rendered WITHOUT the .container-xl wrapper. Not implemented in
+// the shared DefaultLayout yet — flagged rather than modified here.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import { addPageScript } from '@shared/lib/page-scripts';
+
+addPageScript(``);
+---
+
+
+
+
diff --git a/preview/pages/map-fullsize.html b/preview/pages/map-fullsize.html
deleted file mode 100644
index 2babeaf6a..000000000
--- a/preview/pages/map-fullsize.html
+++ /dev/null
@@ -1,29 +0,0 @@
----
-layout: default
-page-libs: [google-maps]
-layout-wrapper-full: true
-layout-sidebar: true
-layout-hide-topbar: true
-page-menu: plugins.map-fullsize
-permalink: map-fullsize.html
----
-
-{% assign map-id = 'google' %}
-
-
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/preview/pages/maps-vector.astro b/preview/pages/maps-vector.astro
new file mode 100644
index 000000000..dc8597124
--- /dev/null
+++ b/preview/pages/maps-vector.astro
@@ -0,0 +1,39 @@
+---
+// Port of preview/pages/maps-vector.html (layout: default).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import MapVector from '@shared/components/ui/MapVector.astro';
+---
+
+
+
+
+
+
+
+
Map with markers
+
+
+
+
+
+
+
+
Map with markers and lines
+
+
+
+
+
+
diff --git a/preview/pages/maps-vector.html b/preview/pages/maps-vector.html
deleted file mode 100644
index cdaa40b0c..000000000
--- a/preview/pages/maps-vector.html
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: Vector Maps
-page-header: Vector Maps
-page-menu: plugins.maps-vector
-page-libs: [jsvectormap]
-layout: default
-permalink: maps-vector.html
----
-
-
-
-
-
-
World map
- {% include "ui/map-vector.html" map-id="world-merc" %}
-
-
-
-
-
-
-
Map with markers
- {% include "ui/map-vector.html" map-id="world-markers" %}
-
-
-
-
-
-
-
Map with markers and lines
- {% include "ui/map-vector.html" map-id="world-lines" %}
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/maps.astro b/preview/pages/maps.astro
new file mode 100644
index 000000000..7a40f4bee
--- /dev/null
+++ b/preview/pages/maps.astro
@@ -0,0 +1,36 @@
+---
+// Port of preview/pages/maps.html (layout: default).
+// Liquid: {% for map in maps %} — card maps span a full-width column with no
+// card-body; non-card maps get a card-body with a title.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Map from '@shared/components/ui/Map.astro';
+import maps from '@data/maps.json';
+
+type MapData = { title?: string; card?: boolean };
+const mapEntries = Object.entries(maps as Record
);
+---
+
+
+
+ {
+ mapEntries.map(([mapId, data]) =>
+ data.card ? (
+
+ ) : (
+
+ ),
+ )
+ }
+
+
diff --git a/preview/pages/maps.html b/preview/pages/maps.html
deleted file mode 100644
index 8dceab12b..000000000
--- a/preview/pages/maps.html
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: Maps
-page-header: Maps
-page-menu: plugins.maps
-page-libs: [mapbox]
-layout: default
-permalink: maps.html
----
-
-
- {% for map in maps %}
- {% assign map-id = map[0] %}
- {% if map[1].card %}
-
-
- {% include "ui/map.html" map-id=map-id ratio="21x9" %}
-
-
- {% else %}
-
-
-
-
{{ map[1].title }}
- {% include "ui/map.html" map-id=map-id %}
-
-
-
- {% endif %}
- {% endfor %}
-
\ No newline at end of file
diff --git a/preview/pages/markdown.astro b/preview/pages/markdown.astro
new file mode 100644
index 000000000..3b44c2005
--- /dev/null
+++ b/preview/pages/markdown.astro
@@ -0,0 +1,11 @@
+---
+import RedirectLayout from '@shared/layouts/RedirectLayout.astro';
+
+// Front matter in preview/pages/markdown.html sets `redirect.to: prose.html`,
+// but shared/includes/redirect.html reads `page.redirect.to` — and in Eleventy
+// `page` is the built-in page object (no front matter), so the include gets an
+// empty url. The reference build (markdown.html) therefore redirects to the
+// relative root ".". We reproduce that exactly by passing no url.
+---
+
+
diff --git a/preview/pages/markdown.html b/preview/pages/markdown.html
deleted file mode 100644
index c873c622c..000000000
--- a/preview/pages/markdown.html
+++ /dev/null
@@ -1,6 +0,0 @@
----
-layout: redirect
-redirect:
- to: prose.html
-permalink: markdown.html
----
diff --git a/preview/pages/marketing/about.astro b/preview/pages/marketing/about.astro
new file mode 100644
index 000000000..f6b9f19c3
--- /dev/null
+++ b/preview/pages/marketing/about.astro
@@ -0,0 +1,45 @@
+---
+// Port of preview/pages/marketing/about.html (title: About).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+---
+
+
+
+
+
About Us
+
Tabler is a digital firm specializing in website development. Our themes are employed by businesses of all scales, ranging from emerging startups to established public companies, to construct and oversee their online presence.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/marketing/about.html b/preview/pages/marketing/about.html
deleted file mode 100644
index cb788e352..000000000
--- a/preview/pages/marketing/about.html
+++ /dev/null
@@ -1,45 +0,0 @@
----
-title: About
-layout: marketing
-permalink: marketing/about.html
----
-
-
-
-
About Us
-
Tabler is a digital firm specializing in website development. Our themes are employed by businesses of all scales, ranging from emerging startups to established public companies, to construct and oversee their online presence.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/preview/pages/marketing/hero.astro b/preview/pages/marketing/hero.astro
new file mode 100644
index 000000000..f8ed4adc8
--- /dev/null
+++ b/preview/pages/marketing/hero.astro
@@ -0,0 +1,36 @@
+---
+// Port of preview/pages/marketing/hero.html (title: Hero, page-libs: [typed.js]).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+import Side from '@shared/components/marketing/hero/Side.astro';
+import Companies from '@shared/components/marketing/sections/Companies.astro';
+import Features from '@shared/components/marketing/sections/Features.astro';
+import Features2 from '@shared/components/marketing/sections/Features2.astro';
+import Cta from '@shared/components/marketing/sections/Cta.astro';
+import Features3 from '@shared/components/marketing/sections/Features3.astro';
+import Testimonials from '@shared/components/marketing/sections/Testimonials.astro';
+import Counters from '@shared/components/marketing/sections/Counters.astro';
+import Subscribe from '@shared/components/marketing/sections/Subscribe.astro';
+import Faq2 from '@shared/components/marketing/sections/Faq2.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/marketing/hero.html b/preview/pages/marketing/hero.html
deleted file mode 100644
index 8cd9310f4..000000000
--- a/preview/pages/marketing/hero.html
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: Hero
-layout: marketing
-page-libs: [typed.js]
-permalink: marketing/hero.html
----
-
-{% include "marketing/hero/side.html" %}
-
-{% include "marketing/sections/companies.html" background="light" class="mt-4 pt-4" divider="waves" %}
-
-{% include "marketing/sections/features.html" %}
-
-{% include "marketing/sections/features-2.html" background="light" %}
-
-{% include "marketing/sections/cta.html" %}
-
-{% include "marketing/sections/features-3.html" background="light" %}
-
-{% include "marketing/sections/testimonials.html" limit=9 %}
-
-{% include "marketing/sections/counters.html" background="light" %}
-
-{% include "marketing/sections/subscribe.html" %}
-
-{% include "marketing/sections/faq-2.html" background="light"%}
\ No newline at end of file
diff --git a/preview/pages/marketing/index.astro b/preview/pages/marketing/index.astro
new file mode 100644
index 000000000..1dbb4c6eb
--- /dev/null
+++ b/preview/pages/marketing/index.astro
@@ -0,0 +1,36 @@
+---
+// Port of preview/pages/marketing/index.html (permalink marketing/index.html).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+import Browser from '@shared/components/marketing/hero/Browser.astro';
+import Companies from '@shared/components/marketing/sections/Companies.astro';
+import Features from '@shared/components/marketing/sections/Features.astro';
+import Features2 from '@shared/components/marketing/sections/Features2.astro';
+import Cta from '@shared/components/marketing/sections/Cta.astro';
+import Features3 from '@shared/components/marketing/sections/Features3.astro';
+import Testimonials from '@shared/components/marketing/sections/Testimonials.astro';
+import Counters from '@shared/components/marketing/sections/Counters.astro';
+import Subscribe from '@shared/components/marketing/sections/Subscribe.astro';
+import Faq2 from '@shared/components/marketing/sections/Faq2.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/marketing/index.html b/preview/pages/marketing/index.html
deleted file mode 100644
index 88c58e559..000000000
--- a/preview/pages/marketing/index.html
+++ /dev/null
@@ -1,25 +0,0 @@
----
-layout: marketing
-redirect_from: marketing.html
-permalink: marketing/index.html
----
-
-{% include "marketing/hero/browser.html" %}
-
-{% include "marketing/sections/companies.html" background="light" class="mt-n12 pt-12" divider="waves" %}
-
-{% include "marketing/sections/features.html" %}
-
-{% include "marketing/sections/features-2.html" background="light" %}
-
-{% include "marketing/sections/cta.html" %}
-
-{% include "marketing/sections/features-3.html" background="light" %}
-
-{% include "marketing/sections/testimonials.html" limit=9 %}
-
-{% include "marketing/sections/counters.html" background="light" %}
-
-{% include "marketing/sections/subscribe.html" %}
-
-{% include "marketing/sections/faq-2.html" background="light"%}
\ No newline at end of file
diff --git a/preview/pages/marketing/pricing.astro b/preview/pages/marketing/pricing.astro
new file mode 100644
index 000000000..10e2678ec
--- /dev/null
+++ b/preview/pages/marketing/pricing.astro
@@ -0,0 +1,22 @@
+---
+// Port of preview/pages/marketing/pricing.html (title: Pricing).
+// The `description` front matter is not emitted by the base layout (no
+// page-specific in the reference build) — no prop.
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+import Pricing from '@shared/components/marketing/sections/Pricing.astro';
+import PricingBanner from '@shared/components/marketing/sections/PricingBanner.astro';
+import Faq from '@shared/components/marketing/sections/Faq.astro';
+---
+
+
+
+
+
+
+
+
diff --git a/preview/pages/marketing/pricing.html b/preview/pages/marketing/pricing.html
deleted file mode 100644
index 7a94cd408..000000000
--- a/preview/pages/marketing/pricing.html
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: Pricing
-description: Pricing page for Tabler UI Kit
-layout: marketing
-permalink: marketing/pricing.html
----
-
-
-
-{% include "marketing/sections/pricing.html" class="pt-0" %}
-{% include "marketing/sections/pricing-banner.html" %}
-{% include "marketing/sections/faq.html" background="light" %}
diff --git a/preview/pages/marketing/real-estate.astro b/preview/pages/marketing/real-estate.astro
new file mode 100644
index 000000000..edf430f72
--- /dev/null
+++ b/preview/pages/marketing/real-estate.astro
@@ -0,0 +1,80 @@
+---
+// Port of preview/pages/marketing/real-estate.html (no title front matter).
+// Uses the `real-estate` global data (imported from @data/real-estate.json).
+// Asset base is "../" (page|relative for the one-level-deep marketing pages).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+import SectionDivider from '@shared/components/marketing/SectionDivider.astro';
+import Icon from '@shared/components/Icon.astro';
+import realEstate from '@data/real-estate.json';
+
+interface Building {
+ name: string;
+ address: string;
+ baths: number;
+ bedrooms: number;
+ image: string;
+ price: string;
+}
+
+const buildings = realEstate as Building[];
+---
+
+
+
+
+
+
Find your forever home
+
It's time to find the home of your dreams, and you search begins here. We make it easy to find the property that fits your needs and budget.
+
+
+
+
+
+
+
+
+
+ {
+ buildings.map((building) => (
+
+
+
+
+
+
+
+
{building.price}
+
+
{building.address}, California USA
+
+
+
+
+ {building.bedrooms} beds
+
+
+
+ {building.baths} baths
+
+
+
+
See details
+
+
+
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/marketing/real-estate.html b/preview/pages/marketing/real-estate.html
deleted file mode 100644
index cfbbfe237..000000000
--- a/preview/pages/marketing/real-estate.html
+++ /dev/null
@@ -1,60 +0,0 @@
----
-layout: marketing
-permalink: marketing/real-estate.html
----
-
-
-
-
-
Find your forever home
-
It's time to find the home of your dreams, and you search begins here. We make it easy to find the property that fits your needs and budget.
-
-
-
-
-
-
- {% include "marketing/section-divider.html" divider="arc" %}
-
-
- {% for building in real-estate %}
-
-
-
-
-
-
-
-
{{ building.price }}
-
-
{{ building.address }}, California USA
-
-
-
- {% include "ui/icon.html" icon="bed" class="me-1" %}
- {{ building.bedrooms }} beds
-
-
- {% include "ui/icon.html" icon="bath" class="me-1" %}
- {{ building.baths }} baths
-
-
-
-
See details
-
-
-
-
- {% endfor %}
-
-
-
diff --git a/preview/pages/marketing/testimonials.astro b/preview/pages/marketing/testimonials.astro
new file mode 100644
index 000000000..456fc2caa
--- /dev/null
+++ b/preview/pages/marketing/testimonials.astro
@@ -0,0 +1,16 @@
+---
+// Port of preview/pages/marketing/testimonials.html (title: Testimonials).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+import Testimonials from '@shared/components/marketing/sections/Testimonials.astro';
+---
+
+
+
+
+
+
diff --git a/preview/pages/marketing/testimonials.html b/preview/pages/marketing/testimonials.html
deleted file mode 100644
index 67ad352d4..000000000
--- a/preview/pages/marketing/testimonials.html
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: Testimonials
-layout: marketing
-permalink: marketing/testimonials.html
----
-
-
-
-{% include "marketing/sections/testimonials.html" hide-header=true class="pt-0" %}
diff --git a/preview/pages/marketing/text.astro b/preview/pages/marketing/text.astro
new file mode 100644
index 000000000..737fbe095
--- /dev/null
+++ b/preview/pages/marketing/text.astro
@@ -0,0 +1,44 @@
+---
+// Port of preview/pages/marketing/text.html (title: Text).
+import MarketingLayout from '@shared/layouts/MarketingLayout.astro';
+---
+
+
+
+
+
Who's that then?
+
Why do you think that she is a witch? How do you know she is a witch? And the hat. She's a witch! The swallow may fly south with the sun, and the house martin or the plover may seek warmer climes in winter, yet these are not strangers to our land.
+
+
+
+
+
+
+
Why? Be quiet! We shall say 'Ni' again to you, if you do not appease us. The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
+
Oh, ow!
+
Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed! It's only a model. Well, what do you want? And this isn't my nose. This is a false one. We found them.
+
+ Did you dress her up like this? We shall say 'Ni' again to you, if you do not appease us. I am your king.
+
+
+
Camelot!
+
I have to push the pram a lot. We want a shrubbery!! And the hat. She's a witch! Burn her! The nose?
+
+ We found them. Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! Be quiet!
+
+
+
The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king. Shut up! Will you shut up?!
+
Bring her forward! What do you mean? Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
+
Who's that then? Why do you think that she is a witch? …Are you suggesting that coconuts migrate? Ah, now we see the violence inherent in the system! I have to push the pram a lot.
+
Well, what do you want? The nose? He hasn't got shit all over him. We shall say 'Ni' again to you, if you do not appease us. What do you mean?
+
Where'd you get the coconuts? Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. No, no, no! Yes, yes. A bit. But she's got a wart. Bring her forward!
+
Why do you think that she is a witch? Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! We found them. Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed!
+
Well, she turned me into a newt. The nose? The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
+
The nose? Burn her anyway! What a strange person. Where'd you get the coconuts? Camelot!
+
Why do you think that she is a witch? Well, we did do the nose. Where'd you get the coconuts? He hasn't got shit all over him.
+
Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony. Where'd you get the coconuts?
+
A newt? The nose? Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! I'm not a witch. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time!
+
+
+
+
diff --git a/preview/pages/marketing/text.html b/preview/pages/marketing/text.html
deleted file mode 100644
index c6825e313..000000000
--- a/preview/pages/marketing/text.html
+++ /dev/null
@@ -1,43 +0,0 @@
----
-title: Text
-layout: marketing
-permalink: marketing/text.html
----
-
-
-
-
Who's that then?
-
Why do you think that she is a witch? How do you know she is a witch? And the hat. She's a witch! The swallow may fly south with the sun, and the house martin or the plover may seek warmer climes in winter, yet these are not strangers to our land.
-
-
-
-
-
-
-
Why? Be quiet! We shall say 'Ni' again to you, if you do not appease us. The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
-
Oh, ow!
-
Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed! It's only a model. Well, what do you want? And this isn't my nose. This is a false one. We found them.
-
- Did you dress her up like this? We shall say 'Ni' again to you, if you do not appease us. I am your king.
-
-
-
Camelot!
-
I have to push the pram a lot. We want a shrubbery!! And the hat. She's a witch! Burn her! The nose?
-
- We found them. Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! Be quiet!
-
-
-
The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king. Shut up! Will you shut up?!
-
Bring her forward! What do you mean? Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-
Who's that then? Why do you think that she is a witch? …Are you suggesting that coconuts migrate? Ah, now we see the violence inherent in the system! I have to push the pram a lot.
-
Well, what do you want? The nose? He hasn't got shit all over him. We shall say 'Ni' again to you, if you do not appease us. What do you mean?
-
Where'd you get the coconuts? Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. No, no, no! Yes, yes. A bit. But she's got a wart. Bring her forward!
-
Why do you think that she is a witch? Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! We found them. Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed!
-
Well, she turned me into a newt. The nose? The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
-
The nose? Burn her anyway! What a strange person. Where'd you get the coconuts? Camelot!
-
Why do you think that she is a witch? Well, we did do the nose. Where'd you get the coconuts? He hasn't got shit all over him.
-
Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony. Where'd you get the coconuts?
-
A newt? The nose? Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! I'm not a witch. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time!
-
-
-
\ No newline at end of file
diff --git a/preview/pages/modals.astro b/preview/pages/modals.astro
new file mode 100644
index 000000000..36b79efca
--- /dev/null
+++ b/preview/pages/modals.astro
@@ -0,0 +1,168 @@
+---
+// Port of preview/pages/modals.html.
+// Every modal is rendered inline (`{% include "ui/modal.html" ... inline show %}`)
+// via ModalInline (renders in place, unlike Modal.astro which drains to ).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import ModalInline from '@shared/components/modals/ModalInline.astro';
+import SimpleModalContent from '@shared/components/modals/SimpleModalContent.astro';
+import LargeModalContent from '@shared/components/modals/LargeModalContent.astro';
+import SmallModalContent from '@shared/components/modals/SmallModalContent.astro';
+import FullWidthModalContent from '@shared/components/modals/FullWidthModalContent.astro';
+import ScrollableModalContent from '@shared/components/modals/ScrollableModalContent.astro';
+import ReportModalContent from '@shared/components/modals/ReportModalContent.astro';
+import SuccessModalContent from '@shared/components/modals/SuccessModalContent.astro';
+import DangerModalContent from '@shared/components/modals/DangerModalContent.astro';
+import TeamModalContent from '@shared/components/modals/TeamModalContent.astro';
+import SignatureModalContent from '@shared/components/modals/SignatureModalContent.astro';
+import NewEmailModalContent from '@shared/components/modals/NewEmailModalContent.astro';
+import NewEventModalContent from '@shared/components/modals/NewEventModalContent.astro';
+import NewTaskModalContent from '@shared/components/modals/NewTaskModalContent.astro';
+import EditProfileModalContent from '@shared/components/modals/EditProfileModalContent.astro';
+import ConfirmDeleteModalContent from '@shared/components/modals/ConfirmDeleteModalContent.astro';
+import ChangePasswordModalContent from '@shared/components/modals/ChangePasswordModalContent.astro';
+import AddTaskModalContent from '@shared/components/modals/AddTaskModalContent.astro';
+
+const cardClass = 'position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0';
+// add-task bakes `show` into the class string (no `show` flag) → aria-hidden="true".
+const addTaskClass = 'position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0';
+---
+
+
+
+
+
+
+
+
+
+
Simple modal
+
+
+
+
+
+
Large modal
+
+
+
+
+
+
Small modal
+
+
+
+
+
+
Full width modal
+
+
+
+
+
+
Scrollable modal
+
+
+
+
+
+
Modal with form
+
+
+
+
+
+
Success modal
+
+
+
+
+
+
Danger modal
+
+
+
+
+
+
Modal with simple form
+
+
+
+
+
+
Modal with signature form
+
+
+
+
+
+
New email modal
+
+
+
+
+
+
New event modal
+
+
+
+
+
+
New task modal
+
+
+
+
+
+
Edit profile modal
+
+
+
+
+
+
Confirm delete modal
+
+
+
+
+
+
Change password modal
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/modals.html b/preview/pages/modals.html
deleted file mode 100644
index 9f5693a1a..000000000
--- a/preview/pages/modals.html
+++ /dev/null
@@ -1,107 +0,0 @@
----
-title: Modals
-page-header: Modals
-page-menu: base.modals
-layout: default
-permalink: modals.html
-page-libs: [signature_pad, hugerte, litepicker]
----
-
-
-
-
-
-
-
-
-
Simple modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="simple" inline show %}
-
-
-
Large modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="large" size="lg" inline show %}
-
-
-
Small modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="small" size="sm" inline show %}
-
-
-
Full width modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="full-width" size="full-width" inline show %}
-
-
-
Scrollable modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="scrollable" scrollable=true style="max-height: 30rem" inline show %}
-
-
-
Modal with form
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="report" size="lg" inline show %}
-
-
-
Success modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="success" size="sm" inline show %}
-
-
-
Danger modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="danger" size="sm" inline show %}
-
-
-
Modal with simple form
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="team" inline show %}
-
-
-
Modal with signature form
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="signature" inline show %}
-
-
-
New email modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="new-email" inline show %}
-
-
-
New event modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="new-event" inline show %}
-
-
-
New task modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="new-task" inline show %}
-
-
-
Edit profile modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="edit-profile" size="lg" inline show %}
-
-
-
Confirm delete modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="confirm-delete" size="sm" inline show %}
-
-
-
Change password modal
- {% include "ui/modal.html" class="position-relative rounded d-block bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="change-password" inline show %}
-
-
-
Add task modal
- {% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="add-task" inline %}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/music.astro b/preview/pages/music.astro
new file mode 100644
index 000000000..69deb1690
--- /dev/null
+++ b/preview/pages/music.astro
@@ -0,0 +1,30 @@
+---
+// Port of preview/pages/music.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import TracksList from '@shared/components/cards/music/TracksList.astro';
+import TrackInfo from '@shared/components/cards/music/TrackInfo.astro';
+
+// Liquid: {% for i in (8..13) %}
+const topTrackIds = [8, 9, 10, 11, 12, 13];
+---
+
+
+
+
+
+
+
+
Top tracks
+
+
+ {
+ topTrackIds.map((trackId) => (
+
+
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/music.html b/preview/pages/music.html
deleted file mode 100644
index e7f4c7ad3..000000000
--- a/preview/pages/music.html
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: Music components
-page-header: Music components
-page-menu: extra.music
-layout: default
-permalink: music.html
----
-
-
-
- {% include "cards/music/tracks-list.html" %}
-
-
-
Top tracks
-
-
- {% for i in (8..13) %}
-
- {% include "cards/music/track-info.html" track-id=i %}
-
- {% endfor %}
-
-
-
diff --git a/preview/pages/navigation.astro b/preview/pages/navigation.astro
new file mode 100644
index 000000000..df2e32f54
--- /dev/null
+++ b/preview/pages/navigation.astro
@@ -0,0 +1,52 @@
+---
+// Port of preview/pages/navigation.html — seven layout/navbar.html includes
+// with variant params, rendered with the shared Navbar component.
+//
+// Note: fluid-search (variant 5) is a no-op — the search block in the Liquid
+// condensed branch is dead code (`unless condensed` inside `if condensed`);
+// the prop exists on Navbar only to mirror the include signature.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Navbar from '@shared/components/navbar/Navbar.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/navigation.html b/preview/pages/navigation.html
deleted file mode 100644
index ccdfd2935..000000000
--- a/preview/pages/navigation.html
+++ /dev/null
@@ -1,37 +0,0 @@
----
-page-menu: base.navigation
-title: Navigation
-page-header: Navigation
-layout: default
-permalink: navigation.html
----
-
-
-
- {% include "layout/navbar.html" sample=true condensed=true transparent=true person-id=3 %}
-
-
-
- {% include "layout/navbar.html" sample=true condensed=true person-id=4 %}
-
-
-
- {% include "layout/navbar.html" sample=true condensed=true dark=true hide-logo=true show-title=true hide-icons=true hide-username=true person-id=5 %}
-
-
-
- {% include "layout/navbar.html" sample=true condensed=true dark=true small-logo=true background-color="#7952b3" hide-search=true person-id=6 %}
-
-
-
- {% include "layout/navbar.html" sample=true condensed=true dark=true background="primary" hide-brand=true hide-icons=true fluid-search=true hide-username=true person-id=7 %}
-
-
-
- {% include "layout/navbar.html" sample=true small-logo=true show-title=true person-id=8 %}
-
-
-
- {% include "layout/navbar.html" sample=true dark=true person-id=9 %}
-
-
\ No newline at end of file
diff --git a/preview/pages/offcanvas.astro b/preview/pages/offcanvas.astro
new file mode 100644
index 000000000..0205af77a
--- /dev/null
+++ b/preview/pages/offcanvas.astro
@@ -0,0 +1,59 @@
+---
+// Port of preview/pages/offcanvas.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+
+const directions = ['start', 'end', 'top', 'bottom'];
+
+// Liquid `capitalize` filter.
+const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
+---
+
+
+
+
+ {
+ directions.map((direction) => (
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab assumenda ea est, eum exercitationem fugiat
+ illum itaque laboriosam magni necessitatibus, nemo nisi numquam quae reiciendis repellat sit soluta unde.
+ Aut!
+
+
+
+ Close offcanvas
+
+
+
+
+ ))
+ }
+
diff --git a/preview/pages/offcanvas.html b/preview/pages/offcanvas.html
deleted file mode 100644
index dcae79dde..000000000
--- a/preview/pages/offcanvas.html
+++ /dev/null
@@ -1,38 +0,0 @@
----
-page-menu: base.offcanvas
-title: Offcanvas
-page-header: Offcanvas
-layout: default
-permalink: offcanvas.html
----
-
-{% assign directions = 'start,end,top,bottom' | split: ',' %}
-
-
-
-{% for direction in directions %}
-
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab assumenda ea est, eum exercitationem fugiat illum itaque laboriosam magni necessitatibus, nemo nisi numquam quae reiciendis repellat sit soluta unde. Aut!
-
-
-
- Close offcanvas
-
-
-
-
-{% endfor %}
\ No newline at end of file
diff --git a/preview/pages/onboarding.astro b/preview/pages/onboarding.astro
new file mode 100644
index 000000000..90e692599
--- /dev/null
+++ b/preview/pages/onboarding.astro
@@ -0,0 +1,133 @@
+---
+// Port of preview/pages/onboarding.html (layout: base).
+// NOTE: the Liquid source passes `current=2` to ui/progress-steps.html, but that
+// include reads `active` (not `current`) — so the arg is a no-op and only the
+// first step is active. The reference reflects this (Step 1 = bg-primary).
+import BaseLayout from '@shared/layouts/BaseLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+import ProgressSteps from '@shared/components/ui/ProgressSteps.astro';
+import Button from '@shared/components/Button.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+ Full name
+
+
+
+ Company name
+
+
+
+ Role
+
+ Select your role
+ Developer
+ Designer
+ Manager
+ Founder
+ Other
+
+
+
+
+
+
+
+
+ Send me product updates and tips via email
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/onboarding.html b/preview/pages/onboarding.html
deleted file mode 100644
index cb2230625..000000000
--- a/preview/pages/onboarding.html
+++ /dev/null
@@ -1,149 +0,0 @@
----
-layout: base
-title: Onboarding
-permalink: onboarding.html
----
-
-
-
-
-
- {% include "layout/navbar-logo.html" class="logo-gray" %}
-
-
- {% include "ui/progress-steps.html" count=5 current=2 %}
-
-
-
-
-
-
-
-
-
-
-
-
- Full name
-
-
-
- Company name
-
-
-
- Role
-
- Select your role
- Developer
- Designer
- Manager
- Founder
- Other
-
-
-
-
-
-
-
-
-
- Send me product updates and tips via email
-
-
-
-
-
-
-
- {% include "ui/button.html" text="Back" color="link link-secondary" %}
- {% include "ui/button.html" text="Continue" color="primary" %}
-
-
-
-
diff --git a/preview/pages/page-loader.astro b/preview/pages/page-loader.astro
new file mode 100644
index 000000000..a0805e631
--- /dev/null
+++ b/preview/pages/page-loader.astro
@@ -0,0 +1,16 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import Progress from '@shared/components/ui/Progress.astro';
+---
+
+
+
+
+
+
+
Preparing application
+
+
+
diff --git a/preview/pages/page-loader.html b/preview/pages/page-loader.html
deleted file mode 100644
index f82c9d5f2..000000000
--- a/preview/pages/page-loader.html
+++ /dev/null
@@ -1,14 +0,0 @@
----
-layout: single
-container-size: slim
-hide-logo: true
-permalink: page-loader.html
----
-
-
-
-
-
-
Preparing application
- {% include "ui/progress.html" indeterminate=true size="sm" %}
-
\ No newline at end of file
diff --git a/preview/pages/pagination.astro b/preview/pages/pagination.astro
new file mode 100644
index 000000000..1f55a356d
--- /dev/null
+++ b/preview/pages/pagination.astro
@@ -0,0 +1,25 @@
+---
+// Port of preview/pages/pagination.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Pagination from '@shared/components/ui/Pagination.astro';
+---
+
+
+
+
diff --git a/preview/pages/pagination.html b/preview/pages/pagination.html
deleted file mode 100644
index b955c4df5..000000000
--- a/preview/pages/pagination.html
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: Pagination
-page-header: Pagination
-page-menu: base.pagination
-layout: default
-permalink: pagination.html
----
-
-
-
-
-
- {% include "ui/pagination.html" %}
- {% include "ui/pagination.html" text=true %}
-
-
-
-
-
-
- {% include "ui/pagination.html" count=0 prev-description="Getting started" next-description="Breadcrumbs" %}
-
-
-
-
diff --git a/preview/pages/patterns.astro b/preview/pages/patterns.astro
new file mode 100644
index 000000000..32c8b54dc
--- /dev/null
+++ b/preview/pages/patterns.astro
@@ -0,0 +1,82 @@
+---
+// Port of preview/pages/patterns.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import site from '@data/site.json';
+
+const patternColors = Object.keys(site.colors);
+const patternSizes = ['sm', 'md', 'lg', 'xl'];
+
+const patterns = [
+ 'bg-pattern-diagonal',
+ 'bg-pattern-diagonal-2',
+ 'bg-pattern-dots',
+ 'bg-pattern-rectangles',
+ 'bg-pattern-lines',
+ 'bg-pattern-lines-vertical',
+ 'bg-pattern-grid',
+ 'bg-pattern-grid-diagonal',
+ 'bg-pattern-blueprint',
+ 'bg-pattern-circles',
+ 'bg-pattern-diagonal-stripes',
+ 'bg-pattern-diagonal-stripes-2',
+ 'bg-pattern-zigzag',
+ 'bg-pattern-vertical-stripes',
+ 'bg-pattern-horizontal-stripes',
+];
+---
+
+
+
+
+
+
+
Pattern types
+
+ {
+ patterns.map((pattern) => (
+
+ ))
+ }
+
+
+
+
+
+
+
+
Pattern colors
+
+ {
+ patternColors.map((color) => (
+
+
+
.bg-pattern-{color}
+
+ ))
+ }
+
+
+
+
+
+
+
+
Pattern sizes
+
+ {
+ patternSizes.map((size) => (
+
+ ))
+ }
+
+
+
+
+
+
diff --git a/preview/pages/patterns.html b/preview/pages/patterns.html
deleted file mode 100644
index 40d3d3d72..000000000
--- a/preview/pages/patterns.html
+++ /dev/null
@@ -1,58 +0,0 @@
----
-layout: default
-title: Patterns
-page-header: Patterns
-page-menu: base.patterns
-permalink: patterns.html
----
-
-{% assign patterns = "bg-pattern-diagonal,bg-pattern-diagonal-2,bg-pattern-dots,bg-pattern-rectangles,bg-pattern-lines,bg-pattern-lines-vertical,bg-pattern-grid,bg-pattern-grid-diagonal,bg-pattern-blueprint,bg-pattern-circles,bg-pattern-diagonal-stripes,bg-pattern-diagonal-stripes-2,bg-pattern-zigzag,bg-pattern-vertical-stripes,bg-pattern-horizontal-stripes" | split: "," %}
-{% assign pattern-sizes = "sm,md,lg,xl" | split: "," %}
-
-
-
-
-
-
Pattern types
-
- {% for pattern in patterns %}
-
- {% endfor %}
-
-
-
-
-
-
-
-
Pattern colors
-
- {% for color in site.colors %}
-
-
-
.bg-pattern-{{ color[0] }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
Pattern sizes
-
- {% for size in pattern-sizes %}
-
-
-
.bg-pattern-{{ size }}
-
- {% endfor %}
-
-
-
-
-
diff --git a/preview/pages/pay.astro b/preview/pages/pay.astro
new file mode 100644
index 000000000..2dd795253
--- /dev/null
+++ b/preview/pages/pay.astro
@@ -0,0 +1,141 @@
+---
+// Port of preview/pages/pay.html (layout: pay).
+// page-libs [tabler-payments, imask]: `tabler-payments` is not a key in
+// core/libs.json, so it resolves to nothing (only imask emits a
+`);
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Animated with JavaScript
+
+
+
+ 0%
+ 10%
+ 50%
+ 100%
+ -10%
+ +10%
+
+
+
+
+
+
+
+
+
+ Progress Background
+
+
+
+
+
+
+
+
+
+ Progress Background Colors
+
+
+
+
+
+
+
+
+
+ Progress Description
+
+
+
+
+
+
+
+
+
+ Progress Description Sizes
+
+
+
+
+
+
+
diff --git a/preview/pages/progress.html b/preview/pages/progress.html
deleted file mode 100644
index 822fc0fb6..000000000
--- a/preview/pages/progress.html
+++ /dev/null
@@ -1,270 +0,0 @@
----
-layout: default
-title: Progress
-page-header: Progress
-page-menu: base.progress
-permalink: progress.html
----
-
-
-
-
-
-
Default
-
- {% include "ui/progress.html" value="0" %}
- {% include "ui/progress.html" value="20" %}
- {% include "ui/progress.html" value="40" %}
- {% include "ui/progress.html" value="100" %}
-
-
-
-
-
-
-
-
With value
-
- {% include "ui/progress.html" value="10" show-value size="lg" %}
- {% include "ui/progress.html" value="20" show-value size="lg" %}
- {% include "ui/progress.html" value="90" show-value size="lg" %}
-
-
-
-
-
-
-
-
Colors
-
- {% include "ui/progress.html" color="blue" value="20" %}
- {% include "ui/progress.html" color="green" value="40" %}
- {% include "ui/progress.html" color="yellow" value="60" %}
- {% include "ui/progress.html" color="red" value="80" %}
-
-
-
-
-
-
-
-
Sizes
-
- {% include "ui/progress.html" value="20" size="sm" %}
- {% include "ui/progress.html" value="40" %}
- {% include "ui/progress.html" value="60" size="lg" %}
- {% include "ui/progress.html" value="80" size="xl" %}
-
-
-
-
-
-
-
-
Indeterminate
-
- {% include "ui/progress.html" indeterminate=true %}
-
-
-
-
-
-
-
-
Multiple values
-
- {% include "ui/progress.html" values="20,30,10" %}
- {% include "ui/progress.html" values="10,20,30,40" class="progress-separated" %}
-
-
-
-
-
-
-
-
Striped
-
- {% include "ui/progress.html" color="blue" value="20" striped %}
- {% include "ui/progress.html" color="green" value="40" striped %}
- {% include "ui/progress.html" color="yellow" value="60" striped %}
- {% include "ui/progress.html" color="red" value="80" striped %}
-
-
-
-
-
-
-
-
Animated
-
- {% include "ui/progress.html" value="20" striped animated %}
- {% include "ui/progress.html" value="40" color="green" striped animated %}
- {% include "ui/progress.html" value="60" color="yellow" striped animated %}
- {% include "ui/progress.html" value="80" color="red" striped animated %}
-
-
-
-
-
-
-
-
- Animated with JavaScript
-
-
-
- {% include "ui/progress.html" value="0" id="progress-animated" %}
-
-
- 0%
-
-
-
- 0%
- 10%
- 50%
- 100%
- -10%
- +10%
-
-
-
-
-
-
-
-
- Steps Progress
-
-
- {% include "ui/progress-steps.html" count=3 %}
- {% include "ui/progress-steps.html" count=5 active=4 %}
- {% include "ui/progress-steps.html" count=10 color="red" %}
- {% include "ui/progress-steps.html" count=8 color="green" active=8 %}
-
-
-
-
-
-
-
-
- Progress Background
-
-
- {% include "ui/progressbg.html" value="85" text="Poland" show-value=true %}
- {% include "ui/progressbg.html" value="65" text="Germany" show-value=true %}
- {% include "ui/progressbg.html" value="45" text="United States" show-value=true %}
- {% include "ui/progressbg.html" value="25" text="France" show-value=true %}
-
-
-
-
-
-
-
-
- Progress Background Colors
-
-
- {% include "ui/progressbg.html" value="75" text="Success" color="success-lt" show-value=true %}
- {% include "ui/progressbg.html" value="60" text="Warning" color="warning-lt" show-value=true %}
- {% include "ui/progressbg.html" value="40" text="Danger" color="danger-lt" show-value=true %}
- {% include "ui/progressbg.html" value="90" text="Info" color="info-lt" show-value=true %}
-
-
-
-
-
-
-
-
- Progress Description
-
-
- {% include "ui/progress-description.html" label="Project completion" value="85" color="green" %}
- {% include "ui/progress-description.html" label="Storage usage" description="2.4GB of 5GB" value="48" color="blue" %}
- {% include "ui/progress-description.html" label="Download progress" value="75" color="yellow" %}
- {% include "ui/progress-description.html" label="Skills assessment" description="HTML/CSS" value="92" color="red" %}
-
-
-
-
-
-
-
-
- Progress Description Sizes
-
-
- {% include "ui/progress-description.html" label="Small progress" value="60" size="sm" color="blue" %}
- {% include "ui/progress-description.html" label="Default progress" value="70" color="green" %}
- {% include "ui/progress-description.html" label="Large progress" value="80" size="lg" color="orange" %}
- {% include "ui/progress-description.html" label="Extra large" value="90" size="xl" color="purple" %}
-
-
-
-
-
-
-{% capture_script -%}
-
-
-
-{%- endcapture_script -%}
\ No newline at end of file
diff --git a/preview/pages/prose.md b/preview/pages/prose.md
deleted file mode 100644
index 0fa71a771..000000000
--- a/preview/pages/prose.md
+++ /dev/null
@@ -1,140 +0,0 @@
----
-title: Prose
-page-header: Prose
-page-menu: base.prose
-layout: prose
-permalink: prose.html
----
-
-# Who's that then?
-
-Well, she turned me into a newt. Burn her! We want a shrubbery!! Well, I got better. Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-
-Listen. __Strange women lying in ponds distributing swords is no basis for a system of government.__ *Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.* The swallow may fly south with the sun, and the house martin or the plover may seek warmer climes in winter, yet these are not strangers to our land.
-
-
-## Well, Mercia's a temperate zone!
-
-You don't frighten us, English pig-dogs! Go and boil your bottoms, sons of a silly person! I blow my nose at you, so-called Ah-thoor Keeng, you and all your silly English K-n-n-n-n-n-n-n-niggits! A newt?
-
-1. Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-2. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time!
-3. We found them.
-
-
-### What do you mean?
-
-Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed! The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
-
-* The Knights Who Say Ni demand a sacrifice!
-* Be quiet!
-* Bloody Peasant!
-
-Well, I got better. Camelot! A newt? We want a shrubbery!! The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
-
-Shut up! …Are you suggesting that coconuts migrate? I'm not a witch. Well, we did do the nose.
-
-Well, how'd you become king, then? Shut up! Ni! Ni! Ni! Ni! Well, Mercia's a temperate zone! I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time!
-
-```scss
-$extra-colors: (
- "blue": $blue,
- "azure": $azure,
- "indigo": $indigo,
- "purple": $purple,
- "pink": $pink,
- "red": $red,
- "orange": $orange,
- "yellow": $yellow,
- "lime": $lime,
- "green": $green,
- "teal": $teal,
- "cyan": $cyan,
- "gray": $gray-600,
- "gray-dark": $gray-800,
- "dark": $dark
-) !default;
-```
-
-You can't expect to wield supreme power just 'cause some watery tart threw a sword at you! You don't frighten us, English pig-dogs! Go and boil your bottoms, sons of a silly person! I blow my nose at you, so-called Ah-thoor Keeng, you and all your silly English K-n-n-n-n-n-n-n-niggits!
-
-What do you mean? Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-
-
-
-Well, how'd you become king, then? You can't expect to wield supreme power just 'cause some watery tart threw a sword at you! The Lady of the Lake, her arm clad in the purest shimmering samite, held aloft Excalibur from the bosom of the water, signifying by divine providence that I, Arthur, was to carry Excalibur. That is why I am your king.
-
-Well, I got better. Shut up! Will you shut up?! Well, I got better. I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time!
-
----
-
-# Typographic elements
-
-
-## Emphasis
-
-**This is bold text**
-
-__This is bold text__
-
-*This is italic text*
-
-_This is italic text_
-
-~~Strikethrough~~
-
-## Blockquotes
-
-> Blockquotes can also be nested...
->> ...by using additional greater-than signs right next to each other...
-> > > ...or with spaces between arrows.
-
-Bloody Peasant! What do you mean? It's only a model. Well, Mercia's a temperate zone!
-
-I am your king. Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot! Ni! Ni! Ni! Ni! Who's that then? Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-
-## Lists
-
-Unordered
-
-+ Create a list by starting a line with `+`, `-`, or `*`
-+ Sub-lists are made by indenting 2 spaces:
- - Marker character change forces new list start:
- * Ac tristique libero volutpat at
- + Facilisis in pretium nisl aliquet
- - Nulla volutpat aliquam velit
-+ Very easy!
-
-Ordered
-
-1. Lorem ipsum dolor sit amet
-2. Consectetur adipiscing elit
-3. Integer molestie lorem at massa
-
-## Code
-
-Inline `code`
-
-Indented code
-
- // Some comments
- line 1 of code
- line 2 of code
- line 3 of code
-
-
-Block code "fences"
-
-```
-Sample text here...
-```
-
-Syntax highlighting
-
-``` js
-var foo = function (bar) {
- return bar++;
-};
-
-console.log(foo(5));
-```
diff --git a/preview/pages/robots.liquid b/preview/pages/robots.liquid
deleted file mode 100644
index c652cc481..000000000
--- a/preview/pages/robots.liquid
+++ /dev/null
@@ -1,13 +0,0 @@
----
-layout: null
-permalink: robots.txt
----
-Sitemap: {% if environment != 'development' %}{{ site.previewUrl }}{% endif %}/sitemap.xml
-
-{% if environment == 'preview' %}
-User-agent: *
-Disallow:
-{% else %}
-User-agent: *
-Disallow: /
-{% endif %}
\ No newline at end of file
diff --git a/preview/pages/robots.txt.ts b/preview/pages/robots.txt.ts
new file mode 100644
index 000000000..e2028691f
--- /dev/null
+++ b/preview/pages/robots.txt.ts
@@ -0,0 +1,23 @@
+import type { APIRoute } from 'astro';
+import { site } from '@shared/lib/site';
+
+export const prerender = true;
+
+// Port of preview/pages/robots.liquid: the sitemap URL is absolute outside
+// development, and crawling is allowed only in the preview environment.
+export const GET: APIRoute = () => {
+ const environment = process.env.NODE_ENV || 'production';
+ const sitemapBase = environment !== 'development' ? site.previewUrl : '';
+ const body = `Sitemap: ${sitemapBase}/sitemap.xml
+
+
+User-agent: *
+Disallow:${environment === 'preview' ? '' : ' /'}
+`;
+
+ return new Response(body, {
+ headers: {
+ 'Content-Type': 'text/plain; charset=utf-8',
+ },
+ });
+};
diff --git a/preview/pages/screenshot.astro b/preview/pages/screenshot.astro
new file mode 100644
index 000000000..3d486225e
--- /dev/null
+++ b/preview/pages/screenshot.astro
@@ -0,0 +1,79 @@
+---
+// Port of preview/pages/screenshot.html (layout: base, page-libs [signature_pad]).
+// The Liquid `{% for color in site.colors %}` swatches map to site.themeColors
+// (blue…cyan), matching the reference bg-gradient-from-{color} output.
+// The large `{% comment %}…{% endcomment %}` prose/nav-segmented block in the
+// source is a Liquid comment (not rendered) — intentionally omitted.
+import BaseLayout from '@shared/layouts/BaseLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+import { site } from '@shared/lib/site';
+---
+
+
+
+
+
+
+
+
+
+
+
+ {
+ site.themeColors.map((color) => (
+
+ ))
+ }
+
+
+
+
+
+
+
+ Light
+ Light
+ Dark
+ Dark
+
+
+
diff --git a/preview/pages/scroll-spy.astro b/preview/pages/scroll-spy.astro
new file mode 100644
index 000000000..862e33278
--- /dev/null
+++ b/preview/pages/scroll-spy.astro
@@ -0,0 +1,39 @@
+---
+// Port of preview/pages/scroll-spy.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+
+const headers = ['Home', 'Profile', 'Messages', 'Settings', 'About', 'Contact', 'Services', 'Team', 'Work'];
+
+// Liquid `slugify`: lowercase; these single words reduce to lowercase.
+const slug = (text: string) => text.toLowerCase();
+
+const lorem =
+ 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. A accusantium, alias autem beatae blanditiis corporis debitis eligendi, enim error excepturi exercitationem odit porro quasi reiciendis saepe sapiente veritatis? Aliquam assumenda beatae, cumque delectus dolorem enim, eveniet facere fugit harum illum iure magnam nemo neque nisi omnis, pariatur tenetur vel? Accusantium aut cum deleniti dolor doloribus eum, molestiae nulla officiis quasi. At cupiditate dolor explicabo id nesciunt placeat unde voluptates. Asperiores cum doloremque esse fugit labore quia reprehenderit similique. Architecto est ipsum maiores odio perferendis quibusdam tempore velit? Accusantium aliquid consequatur corporis dignissimos distinctio eos eum fugiat impedit nam obcaecati officiis, porro, quia quibusdam repellendus sapiente suscipit temporibus ullam velit vitae voluptates? Aliquam consectetur consequatur consequuntur deleniti dicta dolores ducimus, excepturi ipsam iure molestias necessitatibus numquam optio quaerat quasi quo repudiandae sed. Ad aliquam animi beatae culpa delectus esse excepturi in incidunt ipsam iusto labore laboriosam minima, nam, nemo nisi nobis, nulla praesentium provident quae quaerat qui quia quibusdam quis quisquam quos repellendus sint suscipit tempora vero vitae! Animi assumenda dolorum eaque, explicabo laborum officia praesentium quia repudiandae. Aliquam asperiores cupiditate deserunt nobis nostrum reprehenderit voluptates? Dolorem doloremque ducimus magni, maxime sint tenetur totam. Accusamus atque beatae consequatur corporis, dignissimos dolore dolores dolorum earum error eum eveniet, facere impedit incidunt minima molestias nemo non nostrum placeat quasi qui ratione repudiandae suscipit tenetur ullam vel velit voluptatibus. Accusantium alias assumenda blanditiis consectetur cupiditate delectus dolor dolores dolorum, ducimus eaque enim, error esse eum fugiat fugit id ipsam ipsum laboriosam laudantium minus modi molestias mollitia necessitatibus nihil odio officia praesentium quaerat quis quisquam quos reiciendis tempora tempore ut velit vitae voluptas voluptatem! Accusantium adipisci architecto assumenda atque aut consectetur consequuntur cum, deserunt doloribus ea excepturi exercitationem expedita explicabo facere fuga fugit impedit iste iusto laboriosam molestiae nihil officiis perferendis porro possimus provident quae quaerat qui quibusdam quos reiciendis repellendus vel vero, voluptatem! Ab amet aperiam assumenda aut error eveniet, id inventore laudantium molestias mollitia natus neque nulla officiis, porro quam quas quisquam repellendus repudiandae saepe sapiente ut voluptas, voluptate. Ab ad alias, aliquam atque consequatur culpa deserunt distinctio eius, enim est ex exercitationem facere facilis itaque magni maiores modi nemo neque perferendis placeat quam quas quia quis quod quos reiciendis sequi sunt tempore vero vitae! Earum explicabo nam quaerat quam quos sed voluptatem. Asperiores debitis dolorum, eaque eligendi optio ullam velit? Aperiam beatae cumque earum et explicabo maxime modi molestias odit, omnis placeat quasi quibusdam, ratione sapiente vel voluptas? A, aliquid beatae dolore eaque eos excepturi expedita facere facilis fugit ipsam iure molestiae molestias natus necessitatibus, nesciunt nulla, numquam obcaecati officia officiis pariatur quaerat quas quisquam rerum sapiente veniam. A aperiam beatae distinctio et illum laboriosam necessitatibus obcaecati porro sed vero. Accusantium at aut consequatur corporis culpa cupiditate delectus dolores eius eligendi, enim error esse est, et excepturi fugit id ipsam ipsum itaque modi mollitia necessitatibus neque non nulla obcaecati officia placeat qui quia saepe sit temporibus totam ut voluptas voluptatibus? Ad consectetur eos est illum laboriosam minus molestiae officia placeat quas tenetur.';
+---
+
+
+
+
+
+
Menu
+
+ {headers.map((header) => {header} )}
+
+
+
+
+
+
+ {
+ headers.map((header) => (
+
+
+ {lorem}
+
+ ))
+ }
+
+
+
+
+
diff --git a/preview/pages/scroll-spy.html b/preview/pages/scroll-spy.html
deleted file mode 100644
index 594f7e81b..000000000
--- a/preview/pages/scroll-spy.html
+++ /dev/null
@@ -1,49 +0,0 @@
----
-title: Scroll Spy
-layout: default
-permalink: scroll-spy.html
-page-header: Scroll Spy
----
-
-{% assign headers = "Home,Profile,Messages,Settings,About,Contact,Services,Team,Work" | split: "," %}
-
-
-
-
-
Menu
-
- {% for header in headers %}
- {{ header }}
- {% endfor %}
-
-
-
-
-
-
- {% for header in headers %}
-
-
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. A accusantium, alias autem beatae blanditiis corporis debitis eligendi, enim error excepturi exercitationem odit porro quasi reiciendis saepe sapiente veritatis? Aliquam
- assumenda beatae, cumque delectus dolorem enim, eveniet facere fugit harum illum iure magnam nemo neque nisi omnis, pariatur tenetur vel? Accusantium aut cum deleniti dolor doloribus eum, molestiae nulla officiis quasi. At
- cupiditate dolor explicabo id nesciunt placeat unde voluptates. Asperiores cum doloremque esse fugit labore quia reprehenderit similique. Architecto est ipsum maiores odio perferendis quibusdam tempore velit? Accusantium aliquid
- consequatur corporis dignissimos distinctio eos eum fugiat impedit nam obcaecati officiis, porro, quia quibusdam repellendus sapiente suscipit temporibus ullam velit vitae voluptates? Aliquam consectetur consequatur consequuntur
- deleniti dicta dolores ducimus, excepturi ipsam iure molestias necessitatibus numquam optio quaerat quasi quo repudiandae sed. Ad aliquam animi beatae culpa delectus esse excepturi in incidunt ipsam iusto labore laboriosam minima,
- nam, nemo nisi nobis, nulla praesentium provident quae quaerat qui quia quibusdam quis quisquam quos repellendus sint suscipit tempora vero vitae! Animi assumenda dolorum eaque, explicabo laborum officia praesentium quia
- repudiandae. Aliquam asperiores cupiditate deserunt nobis nostrum reprehenderit voluptates? Dolorem doloremque ducimus magni, maxime sint tenetur totam. Accusamus atque beatae consequatur corporis, dignissimos dolore dolores
- dolorum earum error eum eveniet, facere impedit incidunt minima molestias nemo non nostrum placeat quasi qui ratione repudiandae suscipit tenetur ullam vel velit voluptatibus. Accusantium alias assumenda blanditiis consectetur
- cupiditate delectus dolor dolores dolorum, ducimus eaque enim, error esse eum fugiat fugit id ipsam ipsum laboriosam laudantium minus modi molestias mollitia necessitatibus nihil odio officia praesentium quaerat quis quisquam quos
- reiciendis tempora tempore ut velit vitae voluptas voluptatem! Accusantium adipisci architecto assumenda atque aut consectetur consequuntur cum, deserunt doloribus ea excepturi exercitationem expedita explicabo facere fuga fugit
- impedit iste iusto laboriosam molestiae nihil officiis perferendis porro possimus provident quae quaerat qui quibusdam quos reiciendis repellendus vel vero, voluptatem! Ab amet aperiam assumenda aut error eveniet, id inventore
- laudantium molestias mollitia natus neque nulla officiis, porro quam quas quisquam repellendus repudiandae saepe sapiente ut voluptas, voluptate. Ab ad alias, aliquam atque consequatur culpa deserunt distinctio eius, enim est ex
- exercitationem facere facilis itaque magni maiores modi nemo neque perferendis placeat quam quas quia quis quod quos reiciendis sequi sunt tempore vero vitae! Earum explicabo nam quaerat quam quos sed voluptatem. Asperiores
- debitis dolorum, eaque eligendi optio ullam velit? Aperiam beatae cumque earum et explicabo maxime modi molestias odit, omnis placeat quasi quibusdam, ratione sapiente vel voluptas? A, aliquid beatae dolore eaque eos excepturi
- expedita facere facilis fugit ipsam iure molestiae molestias natus necessitatibus, nesciunt nulla, numquam obcaecati officia officiis pariatur quaerat quas quisquam rerum sapiente veniam. A aperiam beatae distinctio et illum
- laboriosam necessitatibus obcaecati porro sed vero. Accusantium at aut consequatur corporis culpa cupiditate delectus dolores eius eligendi, enim error esse est, et excepturi fugit id ipsam ipsum itaque modi mollitia
- necessitatibus neque non nulla obcaecati officia placeat qui quia saepe sit temporibus totam ut voluptas voluptatibus? Ad consectetur eos est illum laboriosam minus molestiae officia placeat quas tenetur.
-
- {% endfor %}
-
-
-
-
diff --git a/preview/pages/search-results.astro b/preview/pages/search-results.astro
new file mode 100644
index 000000000..0343b9a68
--- /dev/null
+++ b/preview/pages/search-results.astro
@@ -0,0 +1,34 @@
+---
+// Port of preview/pages/search-results.html (layout: default; no title in
+// front matter — only page-header)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import NavAside from '@shared/components/parts/NavAside.astro';
+import GalleryPhoto from '@shared/components/cards/GalleryPhoto.astro';
+import photos from '@data/photos.json';
+import people from '@data/people.json';
+
+const resultPhotos = photos.filter((photo) => photo.horizontal).slice(0, 18);
+---
+
+
+
+
+
+
+
+
+ {
+ resultPhotos.map((photo, index) => (
+
+
+
+ ))
+ }
+
+
+
+
diff --git a/preview/pages/search-results.html b/preview/pages/search-results.html
deleted file mode 100644
index 4bf6c6e13..000000000
--- a/preview/pages/search-results.html
+++ /dev/null
@@ -1,25 +0,0 @@
----
-page-header: Search results
-page-header-description: About 2,410 result (0.19 seconds)
-page-menu: extra.search-results
-layout: default
-permalink: search-results.html
----
-
-
-
- {% include "parts/nav/nav-aside.html" %}
-
-
-
- {% assign filtered-photos = photos | where: "horizontal", true %}
-
- {% for photo in filtered-photos limit: 18 %}
- {% assign person = people[forloop.index0] %}
-
- {% include "cards/gallery-photo.html" person=person hide-likes=true %}
-
- {% endfor %}
-
-
-
diff --git a/preview/pages/segmented-control.astro b/preview/pages/segmented-control.astro
new file mode 100644
index 000000000..21486ef67
--- /dev/null
+++ b/preview/pages/segmented-control.astro
@@ -0,0 +1,109 @@
+---
+// Port of preview/pages/segmented-control.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import NavSegmented from '@shared/components/ui/NavSegmented.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/segmented-control.html b/preview/pages/segmented-control.html
deleted file mode 100644
index 263732040..000000000
--- a/preview/pages/segmented-control.html
+++ /dev/null
@@ -1,109 +0,0 @@
----
-layout: default
-title: Segmented control
-permalink: /segmented-control.html
-page-header: Segmented control
-page-menu: base.segmented-control
----
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="1,2,3,4" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="👦,👦🏿,👦🏾,👦🏽,👦🏼,👦🏻" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" icons="home,star,clock,ghost,bold,italic,underline" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" icons="list,layout,calendar,files" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" icons="list,layout,calendar,files" vertical %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" icons="home,star,clock,ghost,bold,italic,underline" vertical disabled="3" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="Daily,Weekly,Monthly,Quarterly,Yearly" disabled="4,5" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="Daily,Weekly,Monthly,Quarterly,Yearly" vertical=true %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="Daily,Weekly,Monthly,Quarterly,Yearly" name="checkbox" %}
-
-
-
-
-
-
- {% include "ui/nav-segmented.html" items="Daily,Weekly,Monthly,Quarterly,Yearly" full-width=true %}
-
-
-
-
-
-
-
-
{% include "ui/nav-segmented.html" items="Overview,Analytics,Reports,Notifications" full-width=true %}
-
{% include "ui/nav-segmented.html" items="Account,Password" full-width=true %}
-
-
-
-
-
-
-
-
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" disabled="3,5" size="sm" %}
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" disabled="3,5" %}
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" disabled="3,5" size="lg" %}
-
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" icons="list,layout,calendar,files" disabled="3,5" size="sm" %}
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" icons="list,layout,calendar,files" disabled="3,5" %}
-
{% include "ui/nav-segmented.html" items="List,Kanban,Calendar,Files" icons="list,layout,calendar,files" disabled="3,5" size="lg" %}
-
-
{% include "ui/nav-segmented.html" icons="list,layout,calendar,files" disabled="3,5" size="sm" %}
-
{% include "ui/nav-segmented.html" icons="list,layout,calendar,files" disabled="3,5" %}
-
{% include "ui/nav-segmented.html" icons="list,layout,calendar,files" disabled="3,5" size="lg" %}
-
-
-
-
-
diff --git a/preview/pages/settings-plan.astro b/preview/pages/settings-plan.astro
new file mode 100644
index 000000000..5eac9c078
--- /dev/null
+++ b/preview/pages/settings-plan.astro
@@ -0,0 +1,29 @@
+---
+// Port of preview/pages/settings-plan.html (layout: settings).
+import SettingsLayout from '@shared/layouts/SettingsLayout.astro';
+import PricingCard from '@shared/components/cards/PricingCard.astro';
+import PricingCardEnterprise from '@shared/components/cards/PricingCardEnterprise.astro';
+---
+
+
+
+
Plans
+
+
This workspace’s Basic Plan is set to $34 per month and will renew on June 19, 2022.
+
+
+
+
diff --git a/preview/pages/settings-plan.html b/preview/pages/settings-plan.html
deleted file mode 100644
index e03105d2e..000000000
--- a/preview/pages/settings-plan.html
+++ /dev/null
@@ -1,26 +0,0 @@
----
-layout: settings
-title: Settings
-permalink: settings-plan.html
----
-
-
-
Plans
-
-
This workspace’s Basic Plan is set to $34 per month and will renew on June 19, 2022.
-
-
-
- {% include "cards/pricing-card.html" price="0" users=3 category="Free" %}
-
-
- {% include "cards/pricing-card.html" price="49" users=10 category="Premium" features="1100" featured-color="green" %}
-
-
- {% include "cards/pricing-card.html" price="99" category="Enterprise" users=100 features="1110" %}
-
-
- {% include "cards/pricing-card-enterprise.html" %}
-
-
-
\ No newline at end of file
diff --git a/preview/pages/settings.astro b/preview/pages/settings.astro
new file mode 100644
index 000000000..2da4bec93
--- /dev/null
+++ b/preview/pages/settings.astro
@@ -0,0 +1,76 @@
+---
+// Port of preview/pages/settings.html (layout: settings).
+import SettingsLayout from '@shared/layouts/SettingsLayout.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Button from '@shared/components/Button.astro';
+import Check from '@shared/components/ui/form/Check.astro';
+import people from '@data/people.json';
+
+const person = people[0];
+---
+
+
+
+
My Account
+
+
Profile Details
+
+
+
+
+
Business Profile
+
+
+
+
Email
+
This contact will be shown to others publicly, so choose it carefully.
+
+
+
+
Password
+
You can set a permanent password if you don't want to use temporary login codes.
+
+
+
+
+
Public profile
+
+ Making your profile public means that anyone on the Dashkit network will be able to find
+ you.
+
+
+
+
+
+
+
diff --git a/preview/pages/settings.html b/preview/pages/settings.html
deleted file mode 100644
index 3ec25b84a..000000000
--- a/preview/pages/settings.html
+++ /dev/null
@@ -1,68 +0,0 @@
----
-layout: settings
-permalink: settings.html
----
-
-
-
My Account
-
-
Profile Details
-
-
-
{% include "ui/avatar.html" size="xl" person-id="1" %}
-
{% include "ui/button.html" text="Change avatar" %}
-
{% include "ui/button.html" text="Delete avatar" color="danger" ghost=true %}
-
-
-
-
Business Profile
-
-
-
-
Email
-
This contact will be shown to others publicly, so choose it carefully.
-
-
-
-
- Email
-
-
-
{% include "ui/button.html" text="Change" %}
-
-
-
-
Password
-
You can set a permanent password if you don't want to use temporary login codes.
-
- {% include "ui/button.html" text="Set new password" %}
-
-
-
Public profile
-
Making your profile public means that anyone on the Dashkit network will be able to find
- you.
-
- {% include "ui/form/check.html" switch=true size="lg" title-on="You're currently visible" title-off="You're
- currently invisible" %}
-
-
-
\ No newline at end of file
diff --git a/preview/pages/sign-in-cover.astro b/preview/pages/sign-in-cover.astro
new file mode 100644
index 000000000..9ee91aea5
--- /dev/null
+++ b/preview/pages/sign-in-cover.astro
@@ -0,0 +1,33 @@
+---
+// Port of preview/pages/sign-in-cover.html (layout: base).
+// Photo id=11 → the 12th entry of the unfiltered photos list (Liquid
+// filtered-photos[11]); no `horizontal` filter is applied here.
+import BaseLayout from '@shared/layouts/BaseLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+import SignInForm from '@shared/components/SignInForm.astro';
+import Photo from '@shared/components/ui/Photo.astro';
+import photos from '@data/photos.json';
+---
+
+
+
+
+
+
+
+
+
+
Login to your account
+
+
+
+
+ Don't have account yet?
Sign up
+
+
+
+
+
+
diff --git a/preview/pages/sign-in-cover.html b/preview/pages/sign-in-cover.html
deleted file mode 100644
index c4322d96c..000000000
--- a/preview/pages/sign-in-cover.html
+++ /dev/null
@@ -1,29 +0,0 @@
----
-layout: base
-title: Sign in with cover
-body-class: d-flex flex-column bg-white
-permalink: sign-in-cover.html
----
-
-
-
-
-
- {% include "layout/navbar-logo.html" %}
-
-
-
- Login to your account
-
-
- {% include "forms/sign-in.html" %}
-
-
- Don't have account yet?
Sign up
-
-
-
-
- {% include "ui/photo.html" id=11 class="bg-cover h-100 min-vh-100" background=true %}
-
-
\ No newline at end of file
diff --git a/preview/pages/sign-in-illustration.astro b/preview/pages/sign-in-illustration.astro
new file mode 100644
index 000000000..6aee3e607
--- /dev/null
+++ b/preview/pages/sign-in-illustration.astro
@@ -0,0 +1,26 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+import SignInCard from '@shared/components/SignInCard.astro';
+import Illustration from '@shared/components/ui/Illustration.astro';
+
+// Liquid passes show-header="1" to cards/sign-in.html, but the include renders
+// the header unconditionally — SignInCard.astro mirrors that (no prop needed).
+---
+
+
+
+
diff --git a/preview/pages/sign-in-illustration.html b/preview/pages/sign-in-illustration.html
deleted file mode 100644
index cfe208d54..000000000
--- a/preview/pages/sign-in-illustration.html
+++ /dev/null
@@ -1,24 +0,0 @@
----
-layout: single
-title: Sign in with illustration
-container-size: normal
-hide-logo: true
-permalink: sign-in-illustration.html
----
-
-
-
-
-
- {% include "layout/navbar-logo.html" %}
-
-
- {% include "cards/sign-in.html" show-header="1" %}
-
-
-
- {% include "ui/illustration.html" image="boy-with-key.svg" class="d-block mx-auto" height=400 %}
-
-
-
-
diff --git a/preview/pages/sign-in-link.astro b/preview/pages/sign-in-link.astro
new file mode 100644
index 000000000..a3ecdca11
--- /dev/null
+++ b/preview/pages/sign-in-link.astro
@@ -0,0 +1,25 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+
+// TODO: Liquid uses {{ site.email }} — add `email` to src/lib/site.ts once it is
+// safe to touch shared files (kept local here to avoid cross-agent conflicts).
+const siteEmail = 'support@tabler.io';
+---
+
+
+
+
+
Check your inbox
+
+
+ We've sent you a magic link to {siteEmail} .
+ Please click the link to confirm your address.
+
+
+
+
+ Can't see the email? Please check the spam folder.
+ Wrong email? Please
re-enter your address .
+
+
+
diff --git a/preview/pages/sign-in-link.html b/preview/pages/sign-in-link.html
deleted file mode 100644
index add3093b0..000000000
--- a/preview/pages/sign-in-link.html
+++ /dev/null
@@ -1,21 +0,0 @@
----
-layout: single
-title: Sign in link
-permalink: sign-in-link.html
----
-
-
-
-
Check your inbox
-
-
- We've sent you a magic link to {{ site.email }} .
- Please click the link to confirm your address.
-
-
-
-
- Can't see the email? Please check the spam folder.
- Wrong email? Please
re-enter your address .
-
-
\ No newline at end of file
diff --git a/preview/pages/sign-in.astro b/preview/pages/sign-in.astro
new file mode 100644
index 000000000..9c1d34903
--- /dev/null
+++ b/preview/pages/sign-in.astro
@@ -0,0 +1,8 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import SignInCard from '@shared/components/SignInCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/sign-in.html b/preview/pages/sign-in.html
deleted file mode 100644
index 0f41ad474..000000000
--- a/preview/pages/sign-in.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-layout: single
-title: Sign in
-permalink: sign-in.html
----
-
-{% include "cards/sign-in.html" show-header="1" %}
diff --git a/preview/pages/sign-up.astro b/preview/pages/sign-up.astro
new file mode 100644
index 000000000..6aba280aa
--- /dev/null
+++ b/preview/pages/sign-up.astro
@@ -0,0 +1,9 @@
+---
+// Port of preview/pages/sign-up.html (layout: single)
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import SignUpCard from '@shared/components/cards/SignUpCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/sign-up.html b/preview/pages/sign-up.html
deleted file mode 100644
index f2c84fefc..000000000
--- a/preview/pages/sign-up.html
+++ /dev/null
@@ -1,7 +0,0 @@
----
-layout: single
-title: Sign up
-permalink: sign-up.html
----
-
-{% include "cards/sign-up.html" %}
diff --git a/preview/pages/signatures.astro b/preview/pages/signatures.astro
new file mode 100644
index 000000000..e84cf76a0
--- /dev/null
+++ b/preview/pages/signatures.astro
@@ -0,0 +1,156 @@
+---
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Signature from '@shared/components/ui/Signature.astro';
+import Button from '@shared/components/Button.astro';
+import CaptureModal from '@shared/components/modals/CaptureModal.astro';
+
+// {% capture simple-js %} / {% capture advanced-js %} — raw JS passed as the
+// signature include's extra-js param (appended inside the SignaturePad init).
+const simpleJs = `signaturePad.fromDataURL("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA1OTIgMjAwIj4KICA8ZyBjbGlwLXBhdGg9InVybCgjYSkiPgogICAgPHBhdGggZmlsbD0iIzAwMCIgZD0iTTEzMi4wOTIgNzkuMDY1YzAgLjMwNC0uMzU1IDEuNDAzLTEuMDYzIDMuMjk4LS42OTQgMS44OTQtMS4xNDIgMy4wMjItMS4zNDUgMy4zODQtMi4zNDIgMy44NDctNi43NiA3LjE4LTEzLjI1MiAxMC4wMDEtNS4zNjUgMi4yMjctMTMuNDU1IDUuNTktMjQuMjcgMTAuMDg4YTE0OC4xOSAxNDguMTkgMCAwIDAtMTAuMzQ3IDMuMTI0Yy0yLjY5Ljg4Mi02LjU4NiAyLjk1LTExLjY5IDYuMjA0YTE4Ny42NiAxODcuNjYgMCAwIDAtMS4wNjMgMTAuMTk2IDQwNy40OSA0MDcuNDkgMCAwIDEtMS40MzIgMTUuMzM4Yy0uODgyIDEuMTg2LTEuOTg4IDEuNzc5LTMuMzE4IDEuNzc5LjExNSAwIC4xNzMtLjAxNS4xNzMtLjA0NC0uMjAyLS4xMDEtLjg5Ni0uMjgyLTIuMDgyLS41NDJ2LTIuODg1YzAtMi43MDUuMjMxLTUuNDYuNjk0LTguMjY2IDAtLjA1Ny4yNTMtLjc3My43Ni0yLjE0Ny41MDUtMS4zMzEuNzU4LTIuMTQxLjc1OC0yLjQzIDAtMS42MDUtLjI5Ni0zLjI0LS44ODktNC45MDMtLjM5IDEuMTI4LTEuMTEzIDEuODU5LTIuMTY5IDIuMTkxLTEuMjQ0LS43MjMtMS44NjUtMS45ODgtMS44NjUtMy43OTYgMC0uMjAzIDEuMDQ4LTEuNzI5IDMuMTQ1LTQuNTc4IDIuMTQtMi45NjUgMy4zODMtNS4wMDQgMy43My02LjExNy4yNzUtLjgxLjc2Ny0zLjQ1IDEuNDc1LTcuOTE5IDEuMDQxLTYuNjEgMS45Ni0xMS40NCAyLjc1NS0xNC40OTEgMS42OTItNi42MzkgMy42OTQtMTAuODYyIDYuMDA4LTEyLjY3bDIuNDMgMS44MjN2MS44NjVjLTEuNTA1IDEuMTU3LTIuNTY3IDMuMjYyLTMuMTkgNi4zMTMtLjE4Ny45NC0uNjM2IDMuMzQxLTEuMzQ0IDcuMjAzLS4xNDUuNzA4LS43MjMgMi41NDUtMS43MzUgNS41MS0uOTExIDIuNjAzLTEuMzY3IDQuMTg3LTEuMzY3IDQuNzUxdjUuNDI0Yy4yNi4yNDUuNS4zNjguNzE2LjM2OCAxLjIxNSAwIDMuMTA5LS41MDYgNS42ODMtMS41MTggMy4wOC0xLjE1NyA1LjAxNy0xLjg1MSA1LjgxMy0yLjA4MyAxMy4wNzEtMy4zODQgMjMuMTUtNy4yMzggMzAuMjM1LTExLjU2MyA2LjIxOC0zLjc0NiA5Ljk5Mi02LjI5OCAxMS4zMjItNy42NTggMS41NzYtMS41NjIgMi4zNjQtMy42NjYgMi4zNjQtNi4zMTMgMC00LjY3MS0yLjEwNC04LjU2OS02LjMxMi0xMS42OTMtMy44Ni0yLjkwNy04LjE5MS00LjM2LTEyLjk5Mi00LjM2LTMuNzg4IDAtOC4yNzEuNDYyLTEzLjQ0NyAxLjM4OC02LjY2NiAxLjIxNS0xMi45MiAyLjkwNy0xOC43NjIgNS4wNzYtOC44NjQgMy4yODQtMTMuNzM2IDYuODM0LTE0LjYxOCAxMC42NTJsLTEuMDg1LjgwM0M1OC44MzkgNzguNDIyIDU4IDc3LjA2MiA1OCA3NS43OWMwLTEuODA4IDEuODgtNC4wMTQgNS42NC02LjYxNyAzLjA4LTIuMTQgNS44Mi0zLjU2NSA4LjIyLTQuMjc0IDE1Ljk0OS00LjkxNyAyNy44NjQtNy4zNzYgMzUuNzQ0LTcuMzc2IDcuNDYxIDAgMTMuNDEyIDEuOTUzIDE3Ljg1MSA1Ljg1NyA0LjQyNCAzLjg2MiA2LjYzNyA5LjA5IDYuNjM3IDE1LjY4NVptMzIuMjk1IDU1LjQwN3YxLjkwOWMtLjU5Mi44MjQtMS4yNDMgMS4yMzYtMS45NTIgMS4yMzYtLjQ0OCAwLTEuOTczLTEuMzU5LTQuNTc2LTQuMDc4LTIuNjAzLTIuNzMzLTQuMzM4LTQuMS01LjIwNi00LjEgMCAuMDU4LTMuMDggMS4yNDQtOS4yMzkgMy41NTgtNi4zMDUgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg2LS42OTQtNC43MDctMi4wODMtMS43Mi0xLjM3NC0yLjU4MS0yLjY2OC0yLjU4MS0zLjg4MyAwLTMuMTM4IDMuNDM0LTYuNzk3IDEwLjMwMy0xMC45NzcgNi40MzQtMy45NjMgMTEuMzQzLTUuOTQ0IDE0LjcyNy01Ljk0NCAxLjQxNyAwIDIuNjkuODEgMy44MTcgMi40M3YxLjgyMmMtLjU2NC44MS0xLjIxNCAxLjIxNS0xLjk1MiAxLjIxNS0uMTMgMC0uNjE0LS4xODEtMS40NTMtLjU0My0uODM5LS4zNzYtMS4zMzctLjU2NC0xLjQ5Ni0uNTY0LTEuMTI4IDAtMy43MTcgMS4xNjUtNy43NjUgMy40OTMtMy44MzIgMi4xNjktNi4zOTkgMy43ODktNy43IDQuODYtMS4zMDIgMS4xMjgtMi4xMzMgMi40MTUtMi40OTQgMy44NjEuOTgzLjkyNiAyLjE1NCAxLjM4OCAzLjUxMyAxLjM4OC43MDkgMCA0LjEwNy0xLjE3MSAxMC4xOTQtMy41MTQgNi4wNzMtMi4zNzIgOS43NDYtMy41NTggMTEuMDE5LTMuNTU4IDEuODY1IDAgMy4yMS40NyA0LjAzNCAxLjQxLjE4OC4yMTcuOTA0IDEuNDkgMi4xNDcgMy44MThhMjEuOTAyIDIxLjkwMiAwIDAgMCAzLjQwNSA0LjczWm02OS44ODQtMTkuNzQydjEuOTUzYy0yLjk5MyAyLjQ1OC01Ljg5OSA1LjIxMy04LjcxOSA4LjI2NS04Ljc2MiA5LjQ1OS0xNC42NjIgMTQuMTg4LTE3LjY5OSAxNC4xODgtMi40NTggMC01LjE5OC0yLjIyLTguMjItNi42NmwtNi41MjgtOS42NTRjLTEuMjQ0LjIwMy0zLjQ5MiAyLjQ2Ni02Ljc0NiA2Ljc5LTMuMDUxIDQuMTIyLTUuODQyIDYuMTgzLTguMzcyIDYuMTgzbC0xLjE5My0uNjI5Yy0uODgyLTEuNjItMi41MzgtNS4xNy00Ljk2Ny0xMC42NTItMi42NDYtNS45MjktMy45NjktOS4zMDYtMy45NjktMTAuMTMxIDAtMS40MzIuODQ2LTIuNjE4IDIuNTM4LTMuNTU4IDEuNjkxIDIuMDQgMy4zNTQgNC44NjcgNC45ODggOC40ODMgMi40NTggNS4zMzYgMy44NzUgOC4zMyA0LjI1MSA4Ljk4MWgyLjA2MWMuNTY0LTEuMDQxIDEuODk0LTIuNjU0IDMuOTkxLTQuODM4LjczNy0xLjEyOCAxLjgyMi0yLjY5IDMuMjUzLTQuNjg2IDEuNjc3LTIuMzcyIDMuMDk1LTMuNTU3IDQuMjUxLTMuNTU3IDEuMDcgMCAxLjk3NC41OTIgMi43MTEgMS43NzggMS4wNzEgMS42OTMgMi45ODYgNC43MyA1Ljc0OCA5LjExMiAzLjA1MSA0Ljc0NCA1LjMgNy4xMTYgNi43NDYgNy4xMTYgMS4wNyAwIDUuMDgyLTMuMDgxIDEyLjAzNy05LjI0MiA2Ljk3LTYuMTYxIDEwLjc5NS05LjI0MiAxMS40NzQtOS4yNDJoMi4zNjRabTQ0LjU3MyAxOS41MjVjLTEuMDQyIDEuMjQ0LTIuNDAxIDEuODY2LTQuMDc4IDEuODY2aC0xNC45ODhjLTMuNDcgMC03LjMzOC0uNTIxLTExLjYwNC0xLjU2Mi01LjU5NS0xLjM2LTguNzYyLTMuMDY3LTkuNS01LjEyLS44MDktMi4zMTQtMS4yMTQtNC41MzQtMS4yMTQtNi42NiAwLTQuMjY3IDEuODM2LTcuNTQzIDUuNTA5LTkuODI4IDMuMDk0LTEuOTgxIDYuODc2LTIuOTcyIDExLjM0NC0yLjk3MiAzLjg0NiAwIDYuODk3LjgzMiA5LjE1MyAyLjQ5NSAyLjI1NSAxLjY0OSAzLjM4MyAzLjg5OCAzLjM4MyA2Ljc0NyAwIDEuNTkxLTIuNzExIDMuMzI2LTguMTMzIDUuMjA2LTQuNDgzIDEuNjItNy43NDQgMi40My05Ljc4MiAyLjQzYTQuNDkgNC40OSAwIDAgMS0uNjczLS4wNDNjMCAuMzktLjMxMS44NjgtLjkzMiAxLjQzMi4zMzIuNTY0IDEuOTgxIDEuMjE0IDQuOTQ1IDEuOTUyIDIuNjYuNjggNC41NTUgMS4wMiA1LjY4MiAxLjAyaDEzLjQ3YzAgLjAyOSAxLjY5OS4yODIgNS4wOTcuNzU5IDEuMDcuNjggMS44NDMgMS40MzkgMi4zMjEgMi4yNzhabS0xNy40NjEtMTYuOWMtMS41NzYtMS42MDUtNC4xMTMtMi40MDgtNy42MTMtMi40MDgtMi40NTggMC00LjczNS40NzctNi44MzIgMS40MzItMi43MDQgMS4yNDQtNC4wNTYgMi45MjktNC4wNTYgNS4wNTUgMCAuNzUyLjI1MyAxLjI4Ny43NTkgMS42MDVoMi43MTFjLjk1NSAwIDMuNTUtLjgwMyA3Ljc4Ny0yLjQwOCA0LjIzNy0xLjYyIDYuNjUyLTIuNzEyIDcuMjQ0LTMuMjc2Wm0zMi40OTEtNTMuMzAyLTIuNDA3IDUzLjU2M2MtLjE0NS4xMTUtLjIxNy40NTUtLjIxNyAxLjAxOSAwIC41NjQuMDcyIDEuMzM4LjIxNyAyLjMyMS4zMDQgMi42NjIgMS4wNDEgNy42OTUgMi4yMTIgMTUuMDk5LS4wNTguMjQ2LS41NDIuNTI4LTEuNDUzLjg0N2EyLjkyIDIuOTIgMCAwIDEtLjQ1NS4wNDNjLTIuOTY1IDAtNC44ODgtMy40MjEtNS43Ny0xMC4yNjEtLjAyOS0uMTQ1LS4wNDMtLjQyNy0uMDQzLS44NDYgMC0xLjMzMS4wNzItNC4wNTcuMjE3LTguMTc5LjIwMi01LjMwOC40NDEtMTAuODYyLjcxNS0xNi42NjEuMDg3LTIuMTk4LjQxMi02LjI5MS45NzYtMTIuMjc5LjUzNS01LjQ4MS44MDMtOS41NTIuODAzLTEyLjIxNCAwLTguMDk5LjUzNS0xMy43NiAxLjYwNS0xNi45ODZsLjY1MS0uMDQzaC4xOTVjLjk2OSAwIDEuNjE5LjUzNSAxLjk1MiAxLjYwNS4yNi43MDkuNTI4IDEuNy44MDIgMi45NzJabTExNC4yMTggNjguMTg0Yy0uNjggMS4zMDItMS41MTEgMS45NTMtMi40OTQgMS45NTMtLjQ5MiAwLTEuNjQyLS4zNjktMy40NDktMS4xMDctMi4xNjktLjg4Mi0zLjQzNC0xLjM4MS0zLjc5Ni0xLjQ5Ny0xLjU5LS4zOS0zLjk3Ni0uNzM3LTcuMTU3LTEuMDQxLTMuODQ3LS4zNzYtNi4yMzItLjY4Ny03LjE1OC0uOTMzLTQuNDk3LTEuMTEzLTEwLjAyLTIuNC0xNi41NzEtMy44NjEtMy4wOC0uNjgtNy4wMi0yLjMyMS0xMS44MjEtNC45MjUtNS44Ny0zLjE4Mi04LjgwNi01LjgwNy04LjgwNi03Ljg3NSAwLS40MTkgMy42OC0zLjgxMSAxMS4wNC0xMC4xNzQgOC4wMjYtNi45MTMgMTIuMjc3LTEwLjYwOSAxMi43NTQtMTEuMDg2LjQ2My0uNzA5IDEuMi0xLjcxNCAyLjIxMi0zLjAxNS4yNzUtLjI2IDIuNTc0LTIuMzY1IDYuODk4LTYuMzEzIDMuNDg0LTMuMTk3IDYuMzY5LTUuNzEzIDguNjU0LTcuNTUgMy41NTctMi44NzggNi43MTYtNC45NjggOS40NzgtNi4yNy40MDUuMzc3Ljg0Ni41ODYgMS4zMjMuNjN2My4xMDJsLS4zOS4yMTdhNTkuMDEgNTkuMDEgMCAwIDAtNi4zMTIgNC40NDdjLTYuOTEyIDUuNjI2LTE5LjczIDE3LjgwNC0zOC40NTYgMzYuNTMzIDUuNTM4IDMuOTQ4IDEzLjE3MyA2Ljg4NCAyMi45MDUgOC44MDggMS4wMjYuMTg4IDcuMTg2IDEuNzI4IDE4LjQ3OSA0LjYyMSAxLjM4OC4zMzIgNC4wNDIuOTc2IDcuOTYgMS45My4yODkuMDg3IDEuODU4IDEuMjIyIDQuNzA3IDMuNDA2Wm0tNTguNTQtNTMuMzQ1LTYuNjU5IDU3LjIyOWMtLjQ0OC40NjItMS4yNjUuNjk0LTIuNDUxLjY5NC0yLjAxIDAtMy4wMTUtLjcyMy0zLjAxNS0yLjE3IDAtLjU2NC40NDEtNC4yODEgMS4zMjMtMTEuMTUuMzYyLTIuNTYgMS40NDYtOS45NzIgMy4yNTQtMjIuMjM3LjMxOC0yLjUxNi45MTEtNy4wMjEgMS43NzgtMTMuNTE1LjczOC01LjEyIDEuOC05LjUxIDMuMTg5LTEzLjE2OCAxLjc0OS4zNjEgMi42MjQgMS41MTggMi42MjQgMy40NyAwIC4zMDQtLjAxNC41ODYtLjA0My44NDdabTk5LjQyNSAzMy43MTJjMCAxLjE4Ni0yLjE0NyA0LjE1OC02LjQ0MiA4LjkxNi0zLjc4OCA0LjE4LTYuNjAxIDYuOTQzLTguNDM3IDguMjg4LS45MjYuNjc5LTIuOTE0IDIuMTU1LTUuOTY1IDQuNDI1LTEuMjcyLjg5Ny0zLjIyNCAxLjc4Ni01Ljg1NiAyLjY2OS0yLjY3NS44NjctNC43NzkgMS4zMDEtNi4zMTIgMS4zMDEtMi44NzcgMC01LjI2My0xLjg1MS03LjE1Ny01LjU1NC0xLjU0OC0zLjAyMi0yLjMyMS02LjE2OC0yLjMyMS05LjQzNiAwLTIuNzE5LjU2NC01LjUwMyAxLjY5Mi04LjM1My40MTkgMCAuODUzLS4xOTUgMS4zMDEtLjU4NS41MzUuMzAzIDEuMjcyLjg5NiAyLjIxMiAxLjc3OS0uMjg5IDIuMjI3LS40MzMgNC4xNzItLjQzMyA1LjgzNSAwIDYuODQxIDIuMjE5IDEwLjI2MiA2LjY1OCAxMC4yNjIgNC4yOTUgMCA5LjQ1LTIuNjY5IDE1LjQ2NS04LjAwNi45NTQtLjg1MyA1LjQ3My01LjA3NiAxMy41NTYtMTIuNjY5aC42NzJjLjkxMSAwIDEuMzY3LjM3NiAxLjM2NyAxLjEyOFptMzguNDEyIDEuMDJjMCAuNTkzLS4yOTYgMy45Ny0uODg5IDEwLjEzMWE3MjIuMzI4IDcyMi4zMjggMCAwIDEtMS44NjUgMTYuNzA0Yy0uMDU4LjQ0OS0uNTA3LjY3My0xLjM0NS42NzMtMS4wOTkgMC0yLjAwMy0xLjM4OS0yLjcxMS00LjE2NS0uNTM1LTIuMTEyLS44MDMtMy45ODUtLjgwMy01LjYxOSAwLS42MjIuMzU0LTIuODU3IDEuMDYzLTYuNzA0LjcyMy0zLjgzMiAxLjA4NC02LjA1MiAxLjA4NC02LjY2IDAtMS42NjMtLjQ0OC0yLjQ5NC0xLjM0NC0yLjQ5NC0xLjE1NyAwLTMuNjMgMS4wMDUtNy40MTggMy4wMTUtMy4yODMgMS43NS01LjY2OSAzLjE3NS03LjE1OCA0LjI3NC0yLjg0OCAyLjA5Ny02LjA4IDUuMjUtOS42OTUgOS40NTgtLjU5My42OC0xLjc1NyAxLjk3NC0zLjQ5MiAzLjg4NC0uNjY1LjcwOC0yLjAwMyAxLjA3Ny00LjAxMyAxLjEwNnYtMi44NDJjMC0xLjMxNiAyLjU5Ni00LjIzOCA3Ljc4Ny04Ljc2NGExMTMuMjg2IDExMy4yODYgMCAwIDEgMTMuMDU3LTkuODI4YzYuMzc3LTQuMTUxIDExLjEyLTYuMjI2IDE0LjIyOC02LjIyNi44MjUgMCAxLjYxMy40NDggMi4zNjUgMS4zNDUuNzY2LjkxMSAxLjE0OSAxLjgxNSAxLjE0OSAyLjcxMlpNNTM0IDEzNC40NzJ2MS45MDljLS41OTMuODI0LTEuMjQzIDEuMjM2LTEuOTUyIDEuMjM2LS40NDggMC0xLjk3NC0xLjM1OS00LjU3Ny00LjA3OC0yLjYwMi0yLjczMy00LjMzNy00LjEtNS4yMDUtNC4xIDAgLjA1OC0zLjA4IDEuMjQ0LTkuMjQgMy41NTgtNi4zMDQgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg1LS42OTQtNC43MDYtMi4wODMtMS43MjEtMS4zNzQtMi41ODEtMi42NjgtMi41ODEtMy44ODMgMC0zLjEzOCAzLjQzNC02Ljc5NyAxMC4zMDItMTAuOTc3IDYuNDM1LTMuOTYzIDExLjM0NC01Ljk0NCAxNC43MjgtNS45NDQgMS40MTcgMCAyLjY4OS44MSAzLjgxNyAyLjQzdjEuODIyYy0uNTY0LjgxLTEuMjE1IDEuMjE1LTEuOTUyIDEuMjE1LS4xMyAwLS42MTUtLjE4MS0xLjQ1My0uNTQzLS44MzktLjM3Ni0xLjMzOC0uNTY0LTEuNDk3LS41NjQtMS4xMjggMC0zLjcxNiAxLjE2NS03Ljc2NSAzLjQ5My0zLjgzMiAyLjE2OS02LjM5OCAzLjc4OS03LjcgNC44Ni0xLjMwMSAxLjEyOC0yLjEzMiAyLjQxNS0yLjQ5NCAzLjg2MS45ODMuOTI2IDIuMTU1IDEuMzg4IDMuNTE0IDEuMzg4LjcwOCAwIDQuMTA2LTEuMTcxIDEwLjE5NC0zLjUxNCA2LjA3My0yLjM3MiA5Ljc0Ni0zLjU1OCAxMS4wMTgtMy41NTggMS44NjYgMCAzLjIxLjQ3IDQuMDM1IDEuNDEuMTg3LjIxNy45MDMgMS40OSAyLjE0NyAzLjgxOGEyMS45MDIgMjEuOTAyIDAgMCAwIDMuNDA1IDQuNzNaIi8+CiAgPC9nPgogIDxkZWZzPgogICAgPGNsaXBQYXRoIGlkPSJhIj4KICAgICAgPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTU4IDQ5aDQ3NnYxMDJINTh6Ii8+CiAgICA8L2NsaXBQYXRoPgogIDwvZGVmcz4KPC9zdmc+");`;
+
+const advancedJs = `function download(dataURL, filename) {
+ const blob = dataURLToBlob(dataURL);
+ const url = window.URL.createObjectURL(blob);
+
+ const a = document.createElement("a");
+ a.style = "display: none";
+ a.href = url;
+ a.download = filename;
+
+ document.body.appendChild(a);
+ a.click();
+
+ window.URL.revokeObjectURL(url);
+}
+
+function dataURLToBlob(dataURL) {
+ const parts = dataURL.split(';base64,');
+ const contentType = parts[0].split(":")[1];
+ const raw = window.atob(parts[1]);
+ const rawLength = raw.length;
+ const uInt8Array = new Uint8Array(rawLength);
+
+ for (let i = 0; i < rawLength; ++i) {
+ uInt8Array[i] = raw.charCodeAt(i);
+ }
+
+ return new Blob([uInt8Array], { type: contentType });
+}
+
+document.querySelector("#signature-advanced-color").addEventListener("input", function (e) {
+ signaturePad.penColor = e.target.value;
+});
+
+document.querySelector("#signature-advanced-svg").addEventListener("click", function () {
+ const dataURL = signaturePad.toDataURL('image/svg+xml');
+ download(dataURL, "signature.svg");
+});
+
+document.querySelector("#signature-advanced-png").addEventListener("click", function () {
+ const dataURL = signaturePad.toDataURL();
+ download(dataURL, "signature.png");
+});`;
+---
+
+
+
+
+
+
+
Confirm transfer
+
Please confirm the transfer of funds by signing below.
+
+
+ First name
+
+
+
+ Last name
+
+
+
+ Signature
+
+
+
+
+ I agree that the signature and initials will be the electronic representation of my signature and initials for all purposes when I (or my agent) use
+ them on documents, including legally binding contracts - just the same as a pen-and-paper signature or initial.
+
+
+
+
+ Cancel
+ Confirm transfer
+
+
+
+
+
+
+
+
+
+
+
+
Advanced demo
+
+
+
+
+
+
+ Pen color
+
+
+
+ Download SVG
+
+
+ Download PNG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Save your signature
+
+
+
+ I agree that the signature and initials will be the electronic representation of my signature and initials for all
+ purposes when I (or my agent) use
+ them on documents, including legally binding contracts - just the same as a pen-and-paper signature or initial.
+
+
+
+
+
+
+
+
diff --git a/preview/pages/signatures.html b/preview/pages/signatures.html
deleted file mode 100644
index ab6ce856c..000000000
--- a/preview/pages/signatures.html
+++ /dev/null
@@ -1,156 +0,0 @@
----
-title: Signatures
-layout: default
-permalink: signatures.html
-page-header: Signatures
-page-libs: [signature_pad]
-page-menu: extra.signatures
----
-
-{% capture simple-js %}
-signaturePad.fromDataURL("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA1OTIgMjAwIj4KICA8ZyBjbGlwLXBhdGg9InVybCgjYSkiPgogICAgPHBhdGggZmlsbD0iIzAwMCIgZD0iTTEzMi4wOTIgNzkuMDY1YzAgLjMwNC0uMzU1IDEuNDAzLTEuMDYzIDMuMjk4LS42OTQgMS44OTQtMS4xNDIgMy4wMjItMS4zNDUgMy4zODQtMi4zNDIgMy44NDctNi43NiA3LjE4LTEzLjI1MiAxMC4wMDEtNS4zNjUgMi4yMjctMTMuNDU1IDUuNTktMjQuMjcgMTAuMDg4YTE0OC4xOSAxNDguMTkgMCAwIDAtMTAuMzQ3IDMuMTI0Yy0yLjY5Ljg4Mi02LjU4NiAyLjk1LTExLjY5IDYuMjA0YTE4Ny42NiAxODcuNjYgMCAwIDAtMS4wNjMgMTAuMTk2IDQwNy40OSA0MDcuNDkgMCAwIDEtMS40MzIgMTUuMzM4Yy0uODgyIDEuMTg2LTEuOTg4IDEuNzc5LTMuMzE4IDEuNzc5LjExNSAwIC4xNzMtLjAxNS4xNzMtLjA0NC0uMjAyLS4xMDEtLjg5Ni0uMjgyLTIuMDgyLS41NDJ2LTIuODg1YzAtMi43MDUuMjMxLTUuNDYuNjk0LTguMjY2IDAtLjA1Ny4yNTMtLjc3My43Ni0yLjE0Ny41MDUtMS4zMzEuNzU4LTIuMTQxLjc1OC0yLjQzIDAtMS42MDUtLjI5Ni0zLjI0LS44ODktNC45MDMtLjM5IDEuMTI4LTEuMTEzIDEuODU5LTIuMTY5IDIuMTkxLTEuMjQ0LS43MjMtMS44NjUtMS45ODgtMS44NjUtMy43OTYgMC0uMjAzIDEuMDQ4LTEuNzI5IDMuMTQ1LTQuNTc4IDIuMTQtMi45NjUgMy4zODMtNS4wMDQgMy43My02LjExNy4yNzUtLjgxLjc2Ny0zLjQ1IDEuNDc1LTcuOTE5IDEuMDQxLTYuNjEgMS45Ni0xMS40NCAyLjc1NS0xNC40OTEgMS42OTItNi42MzkgMy42OTQtMTAuODYyIDYuMDA4LTEyLjY3bDIuNDMgMS44MjN2MS44NjVjLTEuNTA1IDEuMTU3LTIuNTY3IDMuMjYyLTMuMTkgNi4zMTMtLjE4Ny45NC0uNjM2IDMuMzQxLTEuMzQ0IDcuMjAzLS4xNDUuNzA4LS43MjMgMi41NDUtMS43MzUgNS41MS0uOTExIDIuNjAzLTEuMzY3IDQuMTg3LTEuMzY3IDQuNzUxdjUuNDI0Yy4yNi4yNDUuNS4zNjguNzE2LjM2OCAxLjIxNSAwIDMuMTA5LS41MDYgNS42ODMtMS41MTggMy4wOC0xLjE1NyA1LjAxNy0xLjg1MSA1LjgxMy0yLjA4MyAxMy4wNzEtMy4zODQgMjMuMTUtNy4yMzggMzAuMjM1LTExLjU2MyA2LjIxOC0zLjc0NiA5Ljk5Mi02LjI5OCAxMS4zMjItNy42NTggMS41NzYtMS41NjIgMi4zNjQtMy42NjYgMi4zNjQtNi4zMTMgMC00LjY3MS0yLjEwNC04LjU2OS02LjMxMi0xMS42OTMtMy44Ni0yLjkwNy04LjE5MS00LjM2LTEyLjk5Mi00LjM2LTMuNzg4IDAtOC4yNzEuNDYyLTEzLjQ0NyAxLjM4OC02LjY2NiAxLjIxNS0xMi45MiAyLjkwNy0xOC43NjIgNS4wNzYtOC44NjQgMy4yODQtMTMuNzM2IDYuODM0LTE0LjYxOCAxMC42NTJsLTEuMDg1LjgwM0M1OC44MzkgNzguNDIyIDU4IDc3LjA2MiA1OCA3NS43OWMwLTEuODA4IDEuODgtNC4wMTQgNS42NC02LjYxNyAzLjA4LTIuMTQgNS44Mi0zLjU2NSA4LjIyLTQuMjc0IDE1Ljk0OS00LjkxNyAyNy44NjQtNy4zNzYgMzUuNzQ0LTcuMzc2IDcuNDYxIDAgMTMuNDEyIDEuOTUzIDE3Ljg1MSA1Ljg1NyA0LjQyNCAzLjg2MiA2LjYzNyA5LjA5IDYuNjM3IDE1LjY4NVptMzIuMjk1IDU1LjQwN3YxLjkwOWMtLjU5Mi44MjQtMS4yNDMgMS4yMzYtMS45NTIgMS4yMzYtLjQ0OCAwLTEuOTczLTEuMzU5LTQuNTc2LTQuMDc4LTIuNjAzLTIuNzMzLTQuMzM4LTQuMS01LjIwNi00LjEgMCAuMDU4LTMuMDggMS4yNDQtOS4yMzkgMy41NTgtNi4zMDUgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg2LS42OTQtNC43MDctMi4wODMtMS43Mi0xLjM3NC0yLjU4MS0yLjY2OC0yLjU4MS0zLjg4MyAwLTMuMTM4IDMuNDM0LTYuNzk3IDEwLjMwMy0xMC45NzcgNi40MzQtMy45NjMgMTEuMzQzLTUuOTQ0IDE0LjcyNy01Ljk0NCAxLjQxNyAwIDIuNjkuODEgMy44MTcgMi40M3YxLjgyMmMtLjU2NC44MS0xLjIxNCAxLjIxNS0xLjk1MiAxLjIxNS0uMTMgMC0uNjE0LS4xODEtMS40NTMtLjU0My0uODM5LS4zNzYtMS4zMzctLjU2NC0xLjQ5Ni0uNTY0LTEuMTI4IDAtMy43MTcgMS4xNjUtNy43NjUgMy40OTMtMy44MzIgMi4xNjktNi4zOTkgMy43ODktNy43IDQuODYtMS4zMDIgMS4xMjgtMi4xMzMgMi40MTUtMi40OTQgMy44NjEuOTgzLjkyNiAyLjE1NCAxLjM4OCAzLjUxMyAxLjM4OC43MDkgMCA0LjEwNy0xLjE3MSAxMC4xOTQtMy41MTQgNi4wNzMtMi4zNzIgOS43NDYtMy41NTggMTEuMDE5LTMuNTU4IDEuODY1IDAgMy4yMS40NyA0LjAzNCAxLjQxLjE4OC4yMTcuOTA0IDEuNDkgMi4xNDcgMy44MThhMjEuOTAyIDIxLjkwMiAwIDAgMCAzLjQwNSA0LjczWm02OS44ODQtMTkuNzQydjEuOTUzYy0yLjk5MyAyLjQ1OC01Ljg5OSA1LjIxMy04LjcxOSA4LjI2NS04Ljc2MiA5LjQ1OS0xNC42NjIgMTQuMTg4LTE3LjY5OSAxNC4xODgtMi40NTggMC01LjE5OC0yLjIyLTguMjItNi42NmwtNi41MjgtOS42NTRjLTEuMjQ0LjIwMy0zLjQ5MiAyLjQ2Ni02Ljc0NiA2Ljc5LTMuMDUxIDQuMTIyLTUuODQyIDYuMTgzLTguMzcyIDYuMTgzbC0xLjE5My0uNjI5Yy0uODgyLTEuNjItMi41MzgtNS4xNy00Ljk2Ny0xMC42NTItMi42NDYtNS45MjktMy45NjktOS4zMDYtMy45NjktMTAuMTMxIDAtMS40MzIuODQ2LTIuNjE4IDIuNTM4LTMuNTU4IDEuNjkxIDIuMDQgMy4zNTQgNC44NjcgNC45ODggOC40ODMgMi40NTggNS4zMzYgMy44NzUgOC4zMyA0LjI1MSA4Ljk4MWgyLjA2MWMuNTY0LTEuMDQxIDEuODk0LTIuNjU0IDMuOTkxLTQuODM4LjczNy0xLjEyOCAxLjgyMi0yLjY5IDMuMjUzLTQuNjg2IDEuNjc3LTIuMzcyIDMuMDk1LTMuNTU3IDQuMjUxLTMuNTU3IDEuMDcgMCAxLjk3NC41OTIgMi43MTEgMS43NzggMS4wNzEgMS42OTMgMi45ODYgNC43MyA1Ljc0OCA5LjExMiAzLjA1MSA0Ljc0NCA1LjMgNy4xMTYgNi43NDYgNy4xMTYgMS4wNyAwIDUuMDgyLTMuMDgxIDEyLjAzNy05LjI0MiA2Ljk3LTYuMTYxIDEwLjc5NS05LjI0MiAxMS40NzQtOS4yNDJoMi4zNjRabTQ0LjU3MyAxOS41MjVjLTEuMDQyIDEuMjQ0LTIuNDAxIDEuODY2LTQuMDc4IDEuODY2aC0xNC45ODhjLTMuNDcgMC03LjMzOC0uNTIxLTExLjYwNC0xLjU2Mi01LjU5NS0xLjM2LTguNzYyLTMuMDY3LTkuNS01LjEyLS44MDktMi4zMTQtMS4yMTQtNC41MzQtMS4yMTQtNi42NiAwLTQuMjY3IDEuODM2LTcuNTQzIDUuNTA5LTkuODI4IDMuMDk0LTEuOTgxIDYuODc2LTIuOTcyIDExLjM0NC0yLjk3MiAzLjg0NiAwIDYuODk3LjgzMiA5LjE1MyAyLjQ5NSAyLjI1NSAxLjY0OSAzLjM4MyAzLjg5OCAzLjM4MyA2Ljc0NyAwIDEuNTkxLTIuNzExIDMuMzI2LTguMTMzIDUuMjA2LTQuNDgzIDEuNjItNy43NDQgMi40My05Ljc4MiAyLjQzYTQuNDkgNC40OSAwIDAgMS0uNjczLS4wNDNjMCAuMzktLjMxMS44NjgtLjkzMiAxLjQzMi4zMzIuNTY0IDEuOTgxIDEuMjE0IDQuOTQ1IDEuOTUyIDIuNjYuNjggNC41NTUgMS4wMiA1LjY4MiAxLjAyaDEzLjQ3YzAgLjAyOSAxLjY5OS4yODIgNS4wOTcuNzU5IDEuMDcuNjggMS44NDMgMS40MzkgMi4zMjEgMi4yNzhabS0xNy40NjEtMTYuOWMtMS41NzYtMS42MDUtNC4xMTMtMi40MDgtNy42MTMtMi40MDgtMi40NTggMC00LjczNS40NzctNi44MzIgMS40MzItMi43MDQgMS4yNDQtNC4wNTYgMi45MjktNC4wNTYgNS4wNTUgMCAuNzUyLjI1MyAxLjI4Ny43NTkgMS42MDVoMi43MTFjLjk1NSAwIDMuNTUtLjgwMyA3Ljc4Ny0yLjQwOCA0LjIzNy0xLjYyIDYuNjUyLTIuNzEyIDcuMjQ0LTMuMjc2Wm0zMi40OTEtNTMuMzAyLTIuNDA3IDUzLjU2M2MtLjE0NS4xMTUtLjIxNy40NTUtLjIxNyAxLjAxOSAwIC41NjQuMDcyIDEuMzM4LjIxNyAyLjMyMS4zMDQgMi42NjIgMS4wNDEgNy42OTUgMi4yMTIgMTUuMDk5LS4wNTguMjQ2LS41NDIuNTI4LTEuNDUzLjg0N2EyLjkyIDIuOTIgMCAwIDEtLjQ1NS4wNDNjLTIuOTY1IDAtNC44ODgtMy40MjEtNS43Ny0xMC4yNjEtLjAyOS0uMTQ1LS4wNDMtLjQyNy0uMDQzLS44NDYgMC0xLjMzMS4wNzItNC4wNTcuMjE3LTguMTc5LjIwMi01LjMwOC40NDEtMTAuODYyLjcxNS0xNi42NjEuMDg3LTIuMTk4LjQxMi02LjI5MS45NzYtMTIuMjc5LjUzNS01LjQ4MS44MDMtOS41NTIuODAzLTEyLjIxNCAwLTguMDk5LjUzNS0xMy43NiAxLjYwNS0xNi45ODZsLjY1MS0uMDQzaC4xOTVjLjk2OSAwIDEuNjE5LjUzNSAxLjk1MiAxLjYwNS4yNi43MDkuNTI4IDEuNy44MDIgMi45NzJabTExNC4yMTggNjguMTg0Yy0uNjggMS4zMDItMS41MTEgMS45NTMtMi40OTQgMS45NTMtLjQ5MiAwLTEuNjQyLS4zNjktMy40NDktMS4xMDctMi4xNjktLjg4Mi0zLjQzNC0xLjM4MS0zLjc5Ni0xLjQ5Ny0xLjU5LS4zOS0zLjk3Ni0uNzM3LTcuMTU3LTEuMDQxLTMuODQ3LS4zNzYtNi4yMzItLjY4Ny03LjE1OC0uOTMzLTQuNDk3LTEuMTEzLTEwLjAyLTIuNC0xNi41NzEtMy44NjEtMy4wOC0uNjgtNy4wMi0yLjMyMS0xMS44MjEtNC45MjUtNS44Ny0zLjE4Mi04LjgwNi01LjgwNy04LjgwNi03Ljg3NSAwLS40MTkgMy42OC0zLjgxMSAxMS4wNC0xMC4xNzQgOC4wMjYtNi45MTMgMTIuMjc3LTEwLjYwOSAxMi43NTQtMTEuMDg2LjQ2My0uNzA5IDEuMi0xLjcxNCAyLjIxMi0zLjAxNS4yNzUtLjI2IDIuNTc0LTIuMzY1IDYuODk4LTYuMzEzIDMuNDg0LTMuMTk3IDYuMzY5LTUuNzEzIDguNjU0LTcuNTUgMy41NTctMi44NzggNi43MTYtNC45NjggOS40NzgtNi4yNy40MDUuMzc3Ljg0Ni41ODYgMS4zMjMuNjN2My4xMDJsLS4zOS4yMTdhNTkuMDEgNTkuMDEgMCAwIDAtNi4zMTIgNC40NDdjLTYuOTEyIDUuNjI2LTE5LjczIDE3LjgwNC0zOC40NTYgMzYuNTMzIDUuNTM4IDMuOTQ4IDEzLjE3MyA2Ljg4NCAyMi45MDUgOC44MDggMS4wMjYuMTg4IDcuMTg2IDEuNzI4IDE4LjQ3OSA0LjYyMSAxLjM4OC4zMzIgNC4wNDIuOTc2IDcuOTYgMS45My4yODkuMDg3IDEuODU4IDEuMjIyIDQuNzA3IDMuNDA2Wm0tNTguNTQtNTMuMzQ1LTYuNjU5IDU3LjIyOWMtLjQ0OC40NjItMS4yNjUuNjk0LTIuNDUxLjY5NC0yLjAxIDAtMy4wMTUtLjcyMy0zLjAxNS0yLjE3IDAtLjU2NC40NDEtNC4yODEgMS4zMjMtMTEuMTUuMzYyLTIuNTYgMS40NDYtOS45NzIgMy4yNTQtMjIuMjM3LjMxOC0yLjUxNi45MTEtNy4wMjEgMS43NzgtMTMuNTE1LjczOC01LjEyIDEuOC05LjUxIDMuMTg5LTEzLjE2OCAxLjc0OS4zNjEgMi42MjQgMS41MTggMi42MjQgMy40NyAwIC4zMDQtLjAxNC41ODYtLjA0My44NDdabTk5LjQyNSAzMy43MTJjMCAxLjE4Ni0yLjE0NyA0LjE1OC02LjQ0MiA4LjkxNi0zLjc4OCA0LjE4LTYuNjAxIDYuOTQzLTguNDM3IDguMjg4LS45MjYuNjc5LTIuOTE0IDIuMTU1LTUuOTY1IDQuNDI1LTEuMjcyLjg5Ny0zLjIyNCAxLjc4Ni01Ljg1NiAyLjY2OS0yLjY3NS44NjctNC43NzkgMS4zMDEtNi4zMTIgMS4zMDEtMi44NzcgMC01LjI2My0xLjg1MS03LjE1Ny01LjU1NC0xLjU0OC0zLjAyMi0yLjMyMS02LjE2OC0yLjMyMS05LjQzNiAwLTIuNzE5LjU2NC01LjUwMyAxLjY5Mi04LjM1My40MTkgMCAuODUzLS4xOTUgMS4zMDEtLjU4NS41MzUuMzAzIDEuMjcyLjg5NiAyLjIxMiAxLjc3OS0uMjg5IDIuMjI3LS40MzMgNC4xNzItLjQzMyA1LjgzNSAwIDYuODQxIDIuMjE5IDEwLjI2MiA2LjY1OCAxMC4yNjIgNC4yOTUgMCA5LjQ1LTIuNjY5IDE1LjQ2NS04LjAwNi45NTQtLjg1MyA1LjQ3My01LjA3NiAxMy41NTYtMTIuNjY5aC42NzJjLjkxMSAwIDEuMzY3LjM3NiAxLjM2NyAxLjEyOFptMzguNDEyIDEuMDJjMCAuNTkzLS4yOTYgMy45Ny0uODg5IDEwLjEzMWE3MjIuMzI4IDcyMi4zMjggMCAwIDEtMS44NjUgMTYuNzA0Yy0uMDU4LjQ0OS0uNTA3LjY3My0xLjM0NS42NzMtMS4wOTkgMC0yLjAwMy0xLjM4OS0yLjcxMS00LjE2NS0uNTM1LTIuMTEyLS44MDMtMy45ODUtLjgwMy01LjYxOSAwLS42MjIuMzU0LTIuODU3IDEuMDYzLTYuNzA0LjcyMy0zLjgzMiAxLjA4NC02LjA1MiAxLjA4NC02LjY2IDAtMS42NjMtLjQ0OC0yLjQ5NC0xLjM0NC0yLjQ5NC0xLjE1NyAwLTMuNjMgMS4wMDUtNy40MTggMy4wMTUtMy4yODMgMS43NS01LjY2OSAzLjE3NS03LjE1OCA0LjI3NC0yLjg0OCAyLjA5Ny02LjA4IDUuMjUtOS42OTUgOS40NTgtLjU5My42OC0xLjc1NyAxLjk3NC0zLjQ5MiAzLjg4NC0uNjY1LjcwOC0yLjAwMyAxLjA3Ny00LjAxMyAxLjEwNnYtMi44NDJjMC0xLjMxNiAyLjU5Ni00LjIzOCA3Ljc4Ny04Ljc2NGExMTMuMjg2IDExMy4yODYgMCAwIDEgMTMuMDU3LTkuODI4YzYuMzc3LTQuMTUxIDExLjEyLTYuMjI2IDE0LjIyOC02LjIyNi44MjUgMCAxLjYxMy40NDggMi4zNjUgMS4zNDUuNzY2LjkxMSAxLjE0OSAxLjgxNSAxLjE0OSAyLjcxMlpNNTM0IDEzNC40NzJ2MS45MDljLS41OTMuODI0LTEuMjQzIDEuMjM2LTEuOTUyIDEuMjM2LS40NDggMC0xLjk3NC0xLjM1OS00LjU3Ny00LjA3OC0yLjYwMi0yLjczMy00LjMzNy00LjEtNS4yMDUtNC4xIDAgLjA1OC0zLjA4IDEuMjQ0LTkuMjQgMy41NTgtNi4zMDQgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg1LS42OTQtNC43MDYtMi4wODMtMS43MjEtMS4zNzQtMi41ODEtMi42NjgtMi41ODEtMy44ODMgMC0zLjEzOCAzLjQzNC02Ljc5NyAxMC4zMDItMTAuOTc3IDYuNDM1LTMuOTYzIDExLjM0NC01Ljk0NCAxNC43MjgtNS45NDQgMS40MTcgMCAyLjY4OS44MSAzLjgxNyAyLjQzdjEuODIyYy0uNTY0LjgxLTEuMjE1IDEuMjE1LTEuOTUyIDEuMjE1LS4xMyAwLS42MTUtLjE4MS0xLjQ1My0uNTQzLS44MzktLjM3Ni0xLjMzOC0uNTY0LTEuNDk3LS41NjQtMS4xMjggMC0zLjcxNiAxLjE2NS03Ljc2NSAzLjQ5My0zLjgzMiAyLjE2OS02LjM5OCAzLjc4OS03LjcgNC44Ni0xLjMwMSAxLjEyOC0yLjEzMiAyLjQxNS0yLjQ5NCAzLjg2MS45ODMuOTI2IDIuMTU1IDEuMzg4IDMuNTE0IDEuMzg4LjcwOCAwIDQuMTA2LTEuMTcxIDEwLjE5NC0zLjUxNCA2LjA3My0yLjM3MiA5Ljc0Ni0zLjU1OCAxMS4wMTgtMy41NTggMS44NjYgMCAzLjIxLjQ3IDQuMDM1IDEuNDEuMTg3LjIxNy45MDMgMS40OSAyLjE0NyAzLjgxOGEyMS45MDIgMjEuOTAyIDAgMCAwIDMuNDA1IDQuNzNaIi8+CiAgPC9nPgogIDxkZWZzPgogICAgPGNsaXBQYXRoIGlkPSJhIj4KICAgICAgPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTU4IDQ5aDQ3NnYxMDJINTh6Ii8+CiAgICA8L2NsaXBQYXRoPgogIDwvZGVmcz4KPC9zdmc+");
-{%- endcapture %}
-
-
-{% capture advanced-js %}
-
-function download(dataURL, filename) {
- const blob = dataURLToBlob(dataURL);
- const url = window.URL.createObjectURL(blob);
-
- const a = document.createElement("a");
- a.style = "display: none";
- a.href = url;
- a.download = filename;
-
- document.body.appendChild(a);
- a.click();
-
- window.URL.revokeObjectURL(url);
-}
-
-function dataURLToBlob(dataURL) {
- const parts = dataURL.split(';base64,');
- const contentType = parts[0].split(":")[1];
- const raw = window.atob(parts[1]);
- const rawLength = raw.length;
- const uInt8Array = new Uint8Array(rawLength);
-
- for (let i = 0; i < rawLength; ++i) {
- uInt8Array[i] = raw.charCodeAt(i);
- }
-
- return new Blob([uInt8Array], { type: contentType });
-}
-
-document.querySelector("#signature-advanced-color").addEventListener("input", function (e) {
- signaturePad.penColor = e.target.value;
-});
-
-document.querySelector("#signature-advanced-svg").addEventListener("click", function () {
- const dataURL = signaturePad.toDataURL('image/svg+xml');
- download(dataURL, "signature.svg");
-});
-
-document.querySelector("#signature-advanced-png").addEventListener("click", function () {
- const dataURL = signaturePad.toDataURL();
- download(dataURL, "signature.png");
-});
-{%- endcapture %}
-
-
-
-
-
-
Confirm transfer
-
Please confirm the transfer of funds by signing below.
-
-
- First name
-
-
-
- Last name
-
-
-
- Signature
- {% include "ui/signature.html" sample clear extra-js=simple-js %}
-
-
-
- I agree that the signature and initials will be the electronic representation of my signature and initials for all purposes when I (or my agent) use
- them on documents, including legally binding contracts - just the same as a pen-and-paper signature or initial.
-
-
-
-
- Cancel
- Confirm transfer
-
-
-
-
-
-
-
-
-
-
-
-
Advanced demo
-
- {% include "ui/signature.html" id="advanced" clear extra-js=advanced-js %}
-
-
-
-
- Pen color
-
-
-
- Download SVG
-
-
- Download PNG
-
-
-
-
-
-
-
-
-
-
- {% include "ui/button.html" text="Open signature modal" modal-id="signature" %}
-
-
-
-
-
-
-
-
-{% capture_modal %}
-
-
-
-
-
Save your signature
- {% include "ui/signature.html" id="modal" clear event="shown.bs.modal" %}
-
-
- I agree that the signature and initials will be the electronic representation of my signature and initials for all
- purposes when I (or my agent) use
- them on documents, including legally binding contracts - just the same as a pen-and-paper signature or initial.
-
-
-
-
-
-
-{% endcapture_modal %}
diff --git a/preview/pages/sitemap.liquid b/preview/pages/sitemap.liquid
deleted file mode 100644
index 5cccb6c2e..000000000
--- a/preview/pages/sitemap.liquid
+++ /dev/null
@@ -1,14 +0,0 @@
----
-layout: null
-permalink: sitemap.xml
----
-
-
-
-{% for page in pages %}
-
- {% if environment != 'development' %}{{ site.previewUrl }}{% endif %}{{ page.url | replace: 'index.html', '' | xml_escape }}
- {{ page.last_modified_at | default: 'now' | date_to_xmlschema }}
-
-{% endfor %}
-
\ No newline at end of file
diff --git a/preview/pages/sitemap.xml.ts b/preview/pages/sitemap.xml.ts
new file mode 100644
index 000000000..045b1ac3b
--- /dev/null
+++ b/preview/pages/sitemap.xml.ts
@@ -0,0 +1,60 @@
+import type { APIRoute } from 'astro';
+import { site } from '@shared/lib/site';
+
+export const prerender = true;
+
+// Port of preview/pages/sitemap.liquid: one entry per page, file-style URLs
+// (build.format 'file'), index pages collapse to their directory URL.
+// Entry order mirrors the Eleventy `pages` collection: top-level pages first,
+// then nested ones, each group in reverse-alphabetical order.
+const pages = import.meta.glob('./**/*.astro');
+
+const urls = Object.keys(pages)
+ .map((file) => file.replace(/^\.\//, '').replace(/\.astro$/, '.html'))
+ .sort((a, b) => {
+ const depthA = a.split('/').length;
+ const depthB = b.split('/').length;
+ if (depthA !== depthB) return depthA - depthB;
+ // byte-wise, descending — matches the Eleventy `pages` collection order
+ return a < b ? 1 : -1;
+ })
+ .map((path) => {
+ if (path === 'index.html') return '/';
+ if (path.endsWith('/index.html')) return `/${path.slice(0, -'index.html'.length)}`;
+ return `/${path}`;
+ });
+
+const escapeXml = (value: string) =>
+ value
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''');
+
+export const GET: APIRoute = () => {
+ const environment = process.env.NODE_ENV || 'production';
+ const baseUrl = environment !== 'development' ? site.previewUrl : '';
+ // same shape as Liquid's `'now' | date_to_xmlschema` (UTC, +00:00 suffix)
+ const lastModified = new Date().toISOString().replace(/\.\d{3}Z$/, '+00:00');
+ const entries = urls
+ .map(
+ (url) => `
+ ${escapeXml(`${baseUrl}${url}`)}
+ ${lastModified}
+ `,
+ )
+ .join('\n');
+ const body = `
+
+
+${entries}
+
+`;
+
+ return new Response(body, {
+ headers: {
+ 'Content-Type': 'application/xml; charset=utf-8',
+ },
+ });
+};
diff --git a/preview/pages/social-icons.astro b/preview/pages/social-icons.astro
new file mode 100644
index 000000000..81a27450e
--- /dev/null
+++ b/preview/pages/social-icons.astro
@@ -0,0 +1,103 @@
+---
+// Port of preview/pages/social-icons.html (layout: default)
+// Note: the Liquid front matter `plugins: ['social']` is inert for the output —
+// the `.social` styles ship in tabler-socials.css which is loaded globally on
+// every page; no extra page lib is emitted. So no pageLibs is passed.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Trending from '@shared/components/ui/Trending.astro';
+import socialTiles from '@data/social-tiles.json';
+import socials from '@data/socials.json';
+
+interface SocialTile {
+ icon: string;
+ title: string;
+ description: string;
+ trending: number;
+}
+
+interface Social {
+ name: string;
+ file: string;
+}
+
+const tiles = socialTiles as SocialTile[];
+const socialList = socials as Social[];
+const fillers = Array.from({ length: 21 });
+---
+
+
+
+
+
+ {
+ tiles.map((tile) => (
+
+
+
+
+
+
+
+
+
{tile.title}
+
{tile.description}
+
+
+
+
+
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+ {
+ socialList.map((social) => (
+
+
+ Sign in with {social.name}
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+
+
+ {
+ socialList.map((social) => (
+
+
+
+ ))
+ }
+ {fillers.map(() =>
)}
+
+
+
+
+
+
+
diff --git a/preview/pages/social-icons.html b/preview/pages/social-icons.html
deleted file mode 100644
index c048dcef1..000000000
--- a/preview/pages/social-icons.html
+++ /dev/null
@@ -1,74 +0,0 @@
----
-title: Social icons
-page-header: Social icons
-page-menu: base.social
-plugins: ['social']
-layout: default
-permalink: social-icons.html
----
-
-
-
-
- {% for tile in social-tiles %}
-
-
-
-
-
-
-
-
-
{{ tile.title }}
-
{{ tile.description }}
-
-
- {% include "ui/trending.html" value=tile.trending %}
-
-
-
-
-
- {% endfor %}
-
-
-
-
-
-
-
- {% for social in socials %}
-
-
- Sign in with {{ social.name }}
-
- {% endfor %}
-
-
-
-
-
-
-
-
-
-
-
- {% for social in socials %}
-
-
-
- {% endfor %}
- {% for icon in (0..20) %}
-
- {% endfor %}
-
-
-
-
-
-
diff --git a/preview/pages/sortable.astro b/preview/pages/sortable.astro
new file mode 100644
index 000000000..f48ecb359
--- /dev/null
+++ b/preview/pages/sortable.astro
@@ -0,0 +1,49 @@
+---
+// Port of preview/pages/sortable.html (layout: default, page-libs: [sortablejs]).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+---
+
+
+
+
+
+
+
+
+ Element A
+ Element B
+ Element C
+ Element D
+
+
+
+
+
+
+
+
+
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+
+
+ Item A
+ Item B
+ Item C
+
+
+
+
+
+
+
+
diff --git a/preview/pages/sortable.html b/preview/pages/sortable.html
deleted file mode 100644
index f6fdb92ee..000000000
--- a/preview/pages/sortable.html
+++ /dev/null
@@ -1,53 +0,0 @@
----
-title: Sortable
-page-header: SortableJS
-page-menu: plugins.sortable
-page-libs: [sortablejs]
-layout: default
-permalink: sortable.html
----
-
-
-
-
-
-
-
- Element A
- Element B
- Element C
- Element D
-
-
-
-
-
-
-
-
-
-
-
- Item 1
- Item 2
- Item 3
-
-
-
-
- Item A
- Item B
- Item C
-
-
-
-
-
-
-
-
-
diff --git a/preview/pages/stars-rating.astro b/preview/pages/stars-rating.astro
new file mode 100644
index 000000000..cbe562fc0
--- /dev/null
+++ b/preview/pages/stars-rating.astro
@@ -0,0 +1,66 @@
+---
+// Port of preview/pages/stars-rating.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Rating from '@shared/components/ui/Rating.astro';
+---
+
+
+
+
+
+
+
+
+
+
Different icon
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Custom colors
+
+
+
+
+
+
+
+
+
+
+
+
+
Custom sizes
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/stars-rating.html b/preview/pages/stars-rating.html
deleted file mode 100644
index ed59dd86d..000000000
--- a/preview/pages/stars-rating.html
+++ /dev/null
@@ -1,62 +0,0 @@
----
-title: Star Ratings
-page-header: Star Ratings
-page-libs: [tabler-flags, star-rating.js]
-page-menu: base.stars-rating
-layout: default
-permalink: stars-rating.html
----
-
-
-
-
-
-
-
-
Basic
-
{% include "ui/rating.html" value=4 %}
-
-
-
-
-
-
-
Different icon
-
- {% include "ui/rating.html" value=4 %}
- {% include "ui/rating.html" icon="heart" value=4 color="red" %}
- {% include "ui/rating.html" icon="ghost" value=4 color="azure" %}
- {% include "ui/rating.html" icon="circle" value=4 color="green" %}
-
-
-
-
-
-
-
-
-
-
Custom colors
-
- {% include "ui/rating.html" id="color" value=3 %}
- {% include "ui/rating.html" id="color-primary" color="primary" value=3 %}
- {% include "ui/rating.html" id="color-red" color="red" value=3 %}
- {% include "ui/rating.html" id="color-lime" color="lime" value=3 %}
-
-
-
-
-
-
-
-
Custom sizes
-
- {% include "ui/rating.html" id="size-sm" value=3 size="sm" %}
- {% include "ui/rating.html" id="size-primary" value=3 %}
- {% include "ui/rating.html" id="size-md" value=3 size="md" %}
- {% include "ui/rating.html" id="size-lg" value=3 size="lg" %}
-
-
-
-
-
diff --git a/preview/pages/steps.astro b/preview/pages/steps.astro
new file mode 100644
index 000000000..85136663f
--- /dev/null
+++ b/preview/pages/steps.astro
@@ -0,0 +1,96 @@
+---
+// Port of preview/pages/steps.html (layout: default).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+---
+
+
+
+
+
+
+
+
+
+ Cart
+ Billing Information
+ Confirmation
+
+
+
+
+
+
+
+
+
+
+
+
Steps vertical
+
+
+ Order received
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus culpa cum expedita ipsam laborum nam ratione reprehenderit sed sint tenetur!
+
+
+ Order received
+ Lorem ipsum dolor sit amet.
+
+
+ Out for delivery
+ Lorem ipsum dolor sit amet.
+
+
+ Finalized
+ Lorem ipsum dolor sit amet.
+
+
+
+
+
+ Step one
+ Step two
+ Step three
+ Step four
+ Step five
+
+
+
+
+
+
diff --git a/preview/pages/steps.html b/preview/pages/steps.html
deleted file mode 100644
index 844a1da37..000000000
--- a/preview/pages/steps.html
+++ /dev/null
@@ -1,97 +0,0 @@
----
-title: Steps
-page-header: Steps
-page-menu: base.steps
-layout: default
-permalink: steps.html
----
-
-
-
-
-
-
-
-
- Cart
- Billing Information
- Confirmation
-
-
-
-
-
-
-
-
-
-
-
-
Steps vertical
-
-
- Order received
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus culpa cum expedita ipsam laborum nam ratione reprehenderit sed sint tenetur!
-
-
- Order received
- Lorem ipsum dolor sit amet.
-
-
- Out for delivery
- Lorem ipsum dolor sit amet.
-
-
- Finalized
- Lorem ipsum dolor sit amet.
-
-
-
-
-
- Step one
- Step two
- Step three
- Step four
- Step five
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/tables.astro b/preview/pages/tables.astro
new file mode 100644
index 000000000..aee85230d
--- /dev/null
+++ b/preview/pages/tables.astro
@@ -0,0 +1,48 @@
+---
+// Port of preview/pages/tables.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Table from '@shared/components/ui/Table.astro';
+import Progressbg from '@shared/components/cards/tables/Progressbg.astro';
+import Invoices from '@shared/components/cards/Invoices.astro';
+import AdvancedTable from '@shared/components/ui/AdvancedTable.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/tables.html b/preview/pages/tables.html
deleted file mode 100644
index 09ff02ce8..000000000
--- a/preview/pages/tables.html
+++ /dev/null
@@ -1,45 +0,0 @@
----
-page-header: Tables
-page-menu: base.tables
-layout: default
-page-libs: [lists]
-permalink: tables.html
----
-
-
-
-
- {% include "ui/table.html" card=true limit=8 %}
-
-
-
-
- {% include "cards/tables/progressbg.html" %}
-
-
-
-
- {% include "ui/table.html" card=true stripped=true offset=5 %}
-
-
-
-
-
- {% include "ui/table.html" card=true avatars=true offset=10 %}
-
-
-
-
-
- {% include "ui/table.html" card=true mobile=true avatars=true offset=15 buttons=true %}
-
-
-
-
- {% include "cards/invoices.html" %}
-
-
-
- {% include "ui/advanced-table.html" %}
-
-
\ No newline at end of file
diff --git a/preview/pages/tabs.astro b/preview/pages/tabs.astro
new file mode 100644
index 000000000..b078d4149
--- /dev/null
+++ b/preview/pages/tabs.astro
@@ -0,0 +1,18 @@
+---
+// Port of preview/pages/tabs.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import TabsCard from '@shared/components/cards/TabsCard.astro';
+---
+
+
+
+
diff --git a/preview/pages/tabs.html b/preview/pages/tabs.html
deleted file mode 100644
index bd27c2100..000000000
--- a/preview/pages/tabs.html
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: Tabs
-page-header: Tabs
-page-menu: base.tabs
-layout: default
-permalink: tabs.html
----
-
-
-
{% include "cards/tabs.html" id="1" settings=true %}
-
{% include "cards/tabs.html" id="2" reverse=true settings=true %}
-
{% include "cards/tabs.html" id="3" icons=true %}
-
{% include "cards/tabs.html" id="4" dropdown=true %}
-
{% include "cards/tabs.html" id="5" justified=true activity=true %}
-
{% include "cards/tabs.html" id="6" justified=true disabled=true %}
-
{% include "cards/tabs.html" id="7" justified=true icons=true activity=true %}
-
{% include "cards/tabs.html" id="8" animation=true activity=true %}
-
diff --git a/preview/pages/tags.astro b/preview/pages/tags.astro
new file mode 100644
index 000000000..5e5732aad
--- /dev/null
+++ b/preview/pages/tags.astro
@@ -0,0 +1,112 @@
+---
+// Port of preview/pages/tags.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Tag from '@shared/components/ui/Tag.astro';
+import people from '@data/people.json';
+import flags from '@data/flags.json';
+import siteData from '@data/site.json';
+
+const tagIcons = ['bold', 'italic', 'underline', 'copy', 'scissors', 'file-plus', 'file-minus', 'ghost', 'star', 'script', 'photo', 'dog', 'piano'];
+
+const range = (a: number, b: number) => Array.from({ length: b - a + 1 }, (_, i) => a + i);
+
+const flags9 = flags.slice(0, 9);
+const people8 = people.slice(0, 8);
+
+// site.colors is an object keyed by colour name; the Liquid loop yields the
+// value objects with .class / .title.
+const colors = Object.values(siteData.colors) as { class: string; title: string }[];
+---
+
+
+
+
+
+
+
Default tags
+
+ {range(1, 14).map((i) => )}
+
+
+
+
+
+
+
+
+
Tags with flag
+
+ {flags9.map((country) => )}
+
+
+
+
+
+
+
+
+
Tags with icon
+
+ {tagIcons.map((icon) => )}
+
+
+
+
+
+
+
+
+
Tags with avatar
+
+ {people8.map((person) => )}
+
+
+
+
+
+
+
+
+
Tags with status
+
+ {colors.map((color) => )}
+
+
+
+
+
+
+
+
+
Tags with legend
+
+ {colors.map((color) => )}
+
+
+
+
+
+
+
+
+
Default tags
+
+ {range(1, 6).map((i) => )}
+ {range(7, 12).map((i) => )}
+
+
+
+
+
+
+
+
+
Default tags
+
+ {range(1, 12).map((i) => )}
+
+
+
+
+
+
diff --git a/preview/pages/tags.html b/preview/pages/tags.html
deleted file mode 100644
index 918040dc6..000000000
--- a/preview/pages/tags.html
+++ /dev/null
@@ -1,125 +0,0 @@
----
-title: Tags
-page-header: Tags
-page-menu: base.tags
-layout: default
-permalink: tags.html
----
-
-{% assign tag-icons = "bold,italic,underline,copy,scissors,file-plus,file-minus,ghost,star,script,photo,dog,piano" | split: "," %}
-
-
-
-
-
-
Default tags
-
- {% for i in (1..14) %}
- {% capture text %}Label {{ i }}{%- endcapture %}
- {% include "ui/tag.html" text=text %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Tags with flag
-
- {% for country in flags limit: 9 %}
- {% include "ui/tag.html" text=country.name flag=country.code %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Tags with icon
-
- {% for icon in tag-icons %}
- {% include "ui/tag.html" text=icon icon=icon %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Tags with avatar
-
- {% for person in people limit: 8 %}
- {% include "ui/tag.html" text=person.full_name person=person %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Tags with status
-
- {% for color in site.colors %}
- {% capture status %}{{ color[1].class }}{%- endcapture %}
- {% capture text %}{{ color[1].title }}{%- endcapture %}
- {% include "ui/tag.html" text=text status=status %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Tags with legend
-
- {% for color in site.colors %}
- {% capture status %}{{ color[1].class }}{%- endcapture %}
- {% capture text %}{{ color[1].title }}{%- endcapture %}
- {% include "ui/tag.html" text=text legend=status %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Default tags
-
- {% for i in (1..6) %}
- {% capture text %}Label {{ i }}{%- endcapture %}
- {% include "ui/tag.html" text=text checkbox=true %}
- {% endfor %}
- {% for i in (7..12) %}
- {% capture text %}Label {{ i }}{%- endcapture %}
- {% include "ui/tag.html" text=text checkbox=true checked=true %}
- {% endfor %}
-
-
-
-
-
-
-
-
-
Default tags
-
- {% for i in (1..12) %}
- {% include "ui/tag.html" text="Label" badge=i %}
- {% endfor %}
-
-
-
-
-
\ No newline at end of file
diff --git a/preview/pages/tasks-list.astro b/preview/pages/tasks-list.astro
new file mode 100644
index 000000000..92db57385
--- /dev/null
+++ b/preview/pages/tasks-list.astro
@@ -0,0 +1,181 @@
+---
+// Port of preview/pages/tasks-list.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import Icon from '@shared/components/Icon.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Badge from '@shared/components/ui/Badge.astro';
+import Modal from '@shared/components/modals/Modal.astro';
+import tasks from '@data/tasks.json';
+import people from '@data/people.json';
+
+interface Person {
+ id?: string;
+ full_name?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Task {
+ name?: string;
+ assigned_to?: number;
+ due_date?: string;
+ 'due-date'?: string;
+ priority?: string;
+ [key: string]: unknown;
+}
+
+interface Column {
+ name: string;
+ tasks: Task[];
+}
+
+const columns = (tasks as { columns: Column[] }).columns;
+const peopleList = people as Person[];
+
+// add-task modal: assignable people (parts/modals/add-task.html — "5,6,2,3")
+const selectedPeople = [5, 6, 2, 3].map((id) => peopleList[id - 1]);
+---
+
+
+
+
+ {
+ columns.map((section) => (
+
+ ))
+ }
+
+
+
+
+
+
+
+
+
+ Name
+
+
+
+ Assigned To
+
+ Select person
+ {
+ selectedPeople.map((person) => (
+ {person.full_name}
+ ))
+ }
+
+
+
+ Priority
+
+ Low
+ Medium
+ High
+
+
+
+ Description
+
+
+
+
+
+
+
+
diff --git a/preview/pages/tasks-list.html b/preview/pages/tasks-list.html
deleted file mode 100644
index 13a80ed79..000000000
--- a/preview/pages/tasks-list.html
+++ /dev/null
@@ -1,93 +0,0 @@
----
-title: Task List
-page-header: Task List
-page-menu: extra.tasks.list
-layout: default
-permalink: tasks-list.html
----
-
-
-
- {% for section in tasks.columns %}
-
- {% endfor %}
-
-
-
-{% include "ui/modal.html" modal-id="add-task" %}
\ No newline at end of file
diff --git a/preview/pages/tasks.astro b/preview/pages/tasks.astro
new file mode 100644
index 000000000..ed6db264c
--- /dev/null
+++ b/preview/pages/tasks.astro
@@ -0,0 +1,20 @@
+---
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Tasks from '@shared/components/parts/Tasks.astro';
+---
+
+
+
+
+
+
diff --git a/preview/pages/tasks.html b/preview/pages/tasks.html
deleted file mode 100644
index 8b974c568..000000000
--- a/preview/pages/tasks.html
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Tasks
-page-header: Tabler Inc. Tasks
-page-header-actions: add-board
-page-menu: extra.tasks.kanban
-layout: default
-permalink: tasks.html
----
-
-
-
-
-{% include "parts/tasks.html" %}
\ No newline at end of file
diff --git a/preview/pages/terms-of-service.astro b/preview/pages/terms-of-service.astro
new file mode 100644
index 000000000..abb91d893
--- /dev/null
+++ b/preview/pages/terms-of-service.astro
@@ -0,0 +1,58 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+
+// Liquid renders shared/includes/terms-of-service.md via `renderContent: "md"`
+// (markdown-it). The rendered HTML below is inlined verbatim from the reference
+// build to guarantee a 1:1 DOM match — Astro's markdown pipeline (remark +
+// smartypants) would produce different quote characters and list structure.
+// TODO: source of truth remains shared/includes/terms-of-service.md; regenerate
+// this block if the markdown changes.
+//
+// The card title is empty on purpose: the Liquid template prints {{ page.title }},
+// which is Eleventy's `page` object (no `title` property) — the reference output
+// is an empty .
+---
+
+
+
+
+
+
+
We (the folks at Tabler) run a website hosting platform called tabler.io and would love for you to use it. Tabler.io's basic service is free, and we offer paid upgrades for advanced features. Our service is designed to give you as much control and ownership over what goes on your website as possible. However, be responsible in what you publish. In particular, make sure that none of the prohibited items (like spam, viruses, or serious threats of violence) appear in your content.
+
+
The following terms and conditions govern all use of the tabler.io website and all content, services, and products available at or through the website. Our Services are offered subject to your acceptance without modification of all of the terms and conditions contained herein and all other operating rules, policies (including, without limitation, Tabler's Privacy Policy and procedures that may be published from time to time by Tabler (collectively, the "Agreement"). You agree that we may automatically upgrade our Services, and these terms will apply to any upgrades.
+
Please read this Agreement carefully before accessing or using our Services. By accessing or using any part of our services, you agree to become bound by the terms and conditions of this agreement. If you do not agree to all the terms and conditions of this agreement, then you may not access or use any of our services. If these terms and conditions are considered an offer by Tabler, acceptance is expressly limited to these terms.
+
Our Services are not directed to users younger than 16, and access and use of our Services is only offered to users 16 years of age or older. If you are under 16 years old, please do not register to use our Services. Any person who registers as a user or provides their personal information to our Services represents that they are 16 years of age or older. Use of our Services requires a tabler.io account. You agree to provide us with complete and accurate information when you register for an account. You will be solely responsible and liable for any activity that occurs under your username. You are responsible for keeping your password secure.
+
1. tabler.io.
+
+
+ Responsibility of Contributors. If you post material to tabler.io, post links on tabler.io, or otherwise make (or allow any third party to make) material available (any such material, "Content"), you are entirely responsible for the content of, and any harm resulting from, that Content or your conduct. That is the case regardless of what form the Content takes, which includes, but is not limited to text, photo, video, audio, or code. By using tabler.io, you represent and warrant that your Content and conduct do not violate these terms. By submitting Content to Tabler for inclusion on your account, you grant Tabler a world-wide, royalty-free, and non-exclusive license to reproduce, modify, adapt and publish the Content solely for the purpose of displaying, distributing, and promoting your changelog. If you delete Content, Tabler will use reasonable efforts to remove it from tabler.io, but you acknowledge that caching or references to the Content may not be made immediately unavailable. Without limiting any of those representations or warranties, Tabler has the right (though not the obligation) to, in Tabler's sole discretion, (i) reclaim your username or website's URL due to prolonged inactivity, (ii) refuse or remove any content that, in Tabler's reasonable opinion, violates any tabler policy or is in any way harmful or objectionable, or (iii) terminate or deny access to and use of Tabler.io to any individual or entity for any reason. Tabler will have no obligation to provide a refund of any amounts previously paid.
+
+
+ HTTPS. We offer free HTTPS on all tabler.io accounts by default.
+
+
+
2. Responsibility of Visitors.
+
Tabler has not reviewed, and cannot review, all of the material, including computer software, posted to our Services, and cannot therefore be responsible for that material's content, use or effects. By operating our Services, Tabler does not represent or imply that it endorses the material there posted, or that it believes such material to be accurate, useful, or non-harmful. You are responsible for taking precautions as necessary to protect yourself and your computer systems from viruses, worms, Trojan horses, and other harmful or destructive content. Our Services may contain content that is offensive, indecent, or otherwise objectionable, as well as content containing technical inaccuracies, typographical mistakes, and other errors. Our Services may also contain material that violates the privacy or publicity rights, or infringes the intellectual property and other proprietary rights, of third parties, or the downloading, copying or use of which is subject to additional terms and conditions, stated or unstated. Tabler disclaims any responsibility for any harm resulting from the use by visitors of our Services, or from any downloading by those visitors of content there posted.
+
3. Content Posted on Other Websites.
+
We have not reviewed, and cannot review, all of the material, including computer software, made available through the websites and webpages to which Tabler links, and that link to Tabler. Tabler does not have any control over those non-tabler websites, and is not responsible for their contents or their use. By linking to a non-tabler website, Tabler does not represent or imply that it endorses such website. You are responsible for taking precautions as necessary to protect yourself and your computer systems from viruses, worms, Trojan horses, and other harmful or destructive content. Tabler disclaims any responsibility for any harm resulting from your use of non-tabler websites and webpages.
+
5. Copyright Infringement and DMCA Policy.
+
As Tabler asks others to respect its intellectual property rights, it respects the intellectual property rights of others. If you believe that material located on or linked to by tabler.io violates your copyright, you are encouraged to notify Tabler in accordance with Tabler's Digital Millennium Copyright Act ("DMCA") Policy. Tabler will respond to all such notices, including as required or appropriate by removing the infringing material or disabling all links to the infringing material. Tabler will terminate a visitor's access to and use of the Website if, under appropriate circumstances, the visitor is determined to be a repeat infringer of the copyrights or other intellectual property rights of Tabler or others. In the case of such termination, Tabler will have no obligation to provide a refund of any amounts previously paid to Tabler.
+
6. Intellectual Property.
+
This Agreement does not transfer from Tabler to you any Tabler or third party intellectual property, and all right, title, and interest in and to such property will remain (as between the parties) solely with Tabler. Tabler, tabler.io, the tabler.io logo, and all other trademarks, service marks, graphics and logos used in connection with tabler.io or our Services, are trademarks or registered trademarks of Tabler or Tabler's licensors. Other trademarks, service marks, graphics and logos used in connection with our Services may be the trademarks of other third parties. Your use of our Services grants you no right or license to reproduce or otherwise use any Tabler or third-party trademarks.
+
7. Changes.
+
We are constantly updating our Services, and that means sometimes we have to change the legal terms under which our Services are offered. If we make changes that are material, we will let you know by posting on our changelog, or by sending you an email or other communication before the changes take effect. The notice will designate a reasonable period of time after which the new terms will take effect.
+
8. Disclaimer of Warranties.
+
Our Services are provided "as is." Tabler and its suppliers and licensors hereby disclaim all warranties of any kind, express or implied, including, without limitation, the warranties of merchantability, fitness for a particular purpose and non-infringement. Neither Tabler nor its suppliers and licensors, makes any warranty that our Services will be error free or that access thereto will be continuous or uninterrupted.
+
9. License.
+
By using Tabler, You are acknowledging that You have read and have agreed to Tabler's License , so please read them carefully.
+
10. General Representation and Warranty.
+
You represent and warrant that (i) your use of our Services will be in strict accordance with the Tabler Privacy Policy, with this Agreement, and with all applicable laws and regulations (including without limitation any local laws or regulations in your country, state, city, or other governmental area, regarding online conduct and acceptable content, and including all applicable laws regarding the transmission of technical data exported from the United States or the country in which you reside) and (ii) your use of our Services will not infringe or misappropriate the intellectual property rights of any third party.
+
12. Refund Policy.
+
Payments for Tabler are not refundable for any reason.
+
13. Translation.
+
These Terms of Service were originally written in English (US). We may translate these terms into other languages. In the event of a conflict between a translated version of these Terms of Service and the English version, the English version will control.
+
+
+
+
diff --git a/preview/pages/terms-of-service.html b/preview/pages/terms-of-service.html
deleted file mode 100644
index b9edc7989..000000000
--- a/preview/pages/terms-of-service.html
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: Terms of service
-layout: single
-container-size: narrow
-permalink: terms-of-service.html
----
-
-
-
-
{{ page.title }}
-
- {% capture license %}{% include "terms-of-service.md" %}{%- endcapture %}
- {{ license | renderContent: "md" }}
-
-
-
\ No newline at end of file
diff --git a/preview/pages/text-features.astro b/preview/pages/text-features.astro
new file mode 100644
index 000000000..752dc639d
--- /dev/null
+++ b/preview/pages/text-features.astro
@@ -0,0 +1,84 @@
+---
+// Port of preview/pages/text-features.html (layout: default).
+// The right column renders headings h1..h6 via a Liquid {% for i in (1..6) %}
+// loop → dynamic tag name here. {{ site.homepage }} → @data/site.json homepage.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import siteData from '@data/site.json';
+
+const homepage = siteData.homepage;
+---
+
+
+
+
+
+
+
+
Text features
+
+
HTML provides various tags to format text and add meaning. For example, important words can be highlighted, and emphasized text can be italicized.
+
+
If you want to visit an interesting website, check out this page .
+
+
The term HTML is widely used in web development.
+
+
Previously, the instruction said "Do not include images." However, "You may now add images."
+
+
"The best way to predict the future is to create it." – Peter Drucker
+
+
Sometimes, highlighting important text can improve readability.
+
+
In JavaScript, you can log messages using the following code: console.log('Hello, world!');
+
+
To copy text on Windows, use Ctrl + C . On macOS, use Cmd + C .
+
+
Water is written chemically as H2 O, while Einstein’s famous equation is E = mc2 .
+
+
Many people mistakenly spell "recieve" instead of "receive" .
+
+
The correct way to write the date format is "February 12, 2026" , not "12th February, 2026" in American English.
+
+
+ If you need select text, you can use your mouse or keyboard. To select text using your mouse, click and drag the cursor over the text you want to highlight .
+
+
+
Disclaimer: This text is for demonstration purposes only.
+
+
+
+
+
+
+
+
+ {
+ [1, 2, 3, 4, 5, 6].map((i) => {
+ const Heading = `h${i}`;
+ return (
+
+ Heading {i} by @ JohnDoe
+
+ );
+ })
+ }
+
+
+ Tabler is a modern UI framework which provide developers with a lot of pre-build components and customizable options. It is
+ build on Bootstrap, making it easy to integrate into existing projects. The design is clean, responsive, and accessible, ensuring that user can navigate
+ through interface easily. Tabler also support all modern browsers, but some features may not work properly on Internet Explorer. With
+ it's lightweight structure and optimized performance, Tabler helps developers create stunning web applications faster.
+
+
+
Hey @ JohnDoe , have you seen the latest updates on #WebDevelopment16 ? @ JaneSmith just shared an interesting article about Messenger and Netflix !
+
+
+ The sky is #066fd1 , the grass is rgb(47, 179, 68) , fire trucks are often red , oranges are hsl(24deg, 94.49%, 49.8%) . Some flowers are hwb(288.35deg, 24.31%, 21.18%) .
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/text-features.html b/preview/pages/text-features.html
deleted file mode 100644
index c976a19dc..000000000
--- a/preview/pages/text-features.html
+++ /dev/null
@@ -1,73 +0,0 @@
----
-title: Text features
-page-header: Text features
-page-menu: extra.text-features
-layout: default
-permalink: text-features.html
----
-
-
-
-
-
-
-
Text features
-
-
HTML provides various tags to format text and add meaning. For example, important words can be highlighted, and emphasized text can be italicized.
-
-
If you want to visit an interesting website, check out this page .
-
-
The term HTML is widely used in web development.
-
-
Previously, the instruction said "Do not include images." However, "You may now add images."
-
-
"The best way to predict the future is to create it." – Peter Drucker
-
-
Sometimes, highlighting important text can improve readability.
-
-
In JavaScript, you can log messages using the following code: console.log('Hello, world!');
-
-
To copy text on Windows, use Ctrl + C . On macOS, use Cmd + C .
-
-
Water is written chemically as H2 O, while Einstein’s famous equation is E = mc2 .
-
-
Many people mistakenly spell "recieve" instead of "receive" .
-
-
The correct way to write the date format is "February 12, 2026" , not "12th February, 2026" in American English.
-
-
- If you need select text, you can use your mouse or keyboard. To select text using your mouse, click and drag the cursor over the text you want to highlight .
-
-
-
Disclaimer: This text is for demonstration purposes only.
-
-
-
-
-
-
-
-
- {% for i in (1..6) %}
-
Heading {{ i }} by @ JohnDoe
- {% endfor %}
-
-
- Tabler is a modern UI framework which provide developers with a lot of pre-build components and customizable options. It is
- build on Bootstrap, making it easy to integrate into existing projects. The design is clean, responsive, and accessible, ensuring that user can navigate
- through interface easily. Tabler also support all modern browsers, but some features may not work properly on Internet Explorer. With
- it's lightweight structure and optimized performance, Tabler helps developers create stunning web applications faster.
-
-
-
Hey @ JohnDoe , have you seen the latest updates on #WebDevelopment16 ? @ JaneSmith just shared an interesting article about Messenger and Netflix !
-
-
- The sky is #066fd1 , the grass is rgb(47, 179, 68) , fire trucks are often red , oranges are hsl(24deg, 94.49%, 49.8%) . Some flowers are hwb(288.35deg, 24.31%, 21.18%) .
-
-
-
-
-
-
-
-
diff --git a/preview/pages/toasts.astro b/preview/pages/toasts.astro
new file mode 100644
index 000000000..2759d6ce9
--- /dev/null
+++ b/preview/pages/toasts.astro
@@ -0,0 +1,22 @@
+---
+// Port of preview/pages/toasts.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import Toast from '@shared/components/ui/Toast.astro';
+---
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/toasts.html b/preview/pages/toasts.html
deleted file mode 100644
index db1fa4029..000000000
--- a/preview/pages/toasts.html
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: Toasts
-page-header: Toasts
-page-menu: base.toasts
-layout: default
-permalink: toasts.html
----
-
-
-
-
- {% include "ui/button.html" text="Simple toast" toast-id="simple" %}
- {% include "ui/button.html" text="Cookies toast" toast-id="cookies" %}
-
-
-
-
-
-
- {% include "ui/toast.html" toast-id="simple" show=false %}
- {% include "ui/toast.html" toast-id="cookies" show=false cookies=true %}
-
\ No newline at end of file
diff --git a/preview/pages/tour.astro b/preview/pages/tour.astro
new file mode 100644
index 000000000..5d0686731
--- /dev/null
+++ b/preview/pages/tour.astro
@@ -0,0 +1,227 @@
+---
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Button from '@shared/components/Button.astro';
+import Badge from '@shared/components/ui/Badge.astro';
+import Icon from '@shared/components/Icon.astro';
+---
+
+
+
+
+
+
+
+
+ Click the "Start Tour" button to begin an interactive tour of this page.
+ The tour will guide you through different elements and features.
+
+
+
+
+
+
+
+
+
This is the first card in our tour. It demonstrates how Driver.js highlights elements on the page.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
This is a full-width card that demonstrates how the tour works with larger elements.
+
+
+
+
+ Name
+ Status
+ Role
+
+
+
+
+
+ John Doe
+
+ Developer
+
+
+
+
+
+ Jane Smith
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Settings
+
Configure your application settings here.
+
+
+
+
+
+
+
+
+
+
+
Users
+
Manage your team members and permissions.
+
+
+
+
+
+
+
+
+
+
+
Analytics
+
View your application statistics and reports.
+
+
+
+
+
+
+
diff --git a/preview/pages/tour.html b/preview/pages/tour.html
deleted file mode 100644
index 6f92ec6e8..000000000
--- a/preview/pages/tour.html
+++ /dev/null
@@ -1,223 +0,0 @@
----
-title: Driver Tour
-page-header: Driver Tour
-page-libs: [driver.js]
-page-menu: plugins.tour
-layout: default
-permalink: tour.html
----
-
-
-
-
-
-
-
- Click the "Start Tour" button to begin an interactive tour of this page.
- The tour will guide you through different elements and features.
-
-
-
-
-
-
-
-
-
This is the first card in our tour. It demonstrates how Driver.js highlights elements on the page.
-
- {% include "ui/button.html" text="Action Button" color="primary" element="button" %}
- {% include "ui/button.html" text="Secondary" element="button" %}
-
-
-
-
-
-
-
-
-
-
-
This is a full-width card that demonstrates how the tour works with larger elements.
-
-
-
-
- Name
- Status
- Role
-
-
-
-
-
- John Doe
- {% include "ui/badge.html" text="Active" color="success" %}
- Developer
-
- {% include "ui/button.html" text="Edit" size="sm" href="#" %}
-
-
-
- Jane Smith
- {% include "ui/badge.html" text="Pending" color="warning" %}
- Designer
-
- {% include "ui/button.html" text="Edit" size="sm" href="#" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="settings" size="48" %}
-
-
Settings
-
Configure your application settings here.
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="users" size="48" %}
-
-
Users
-
Manage your team members and permissions.
-
-
-
-
-
-
-
-
- {% include "ui/icon.html" icon="chart-bar" size="48" %}
-
-
Analytics
-
View your application statistics and reports.
-
-
-
-
-
-
-
diff --git a/preview/pages/trial-ended.astro b/preview/pages/trial-ended.astro
new file mode 100644
index 000000000..67dde8777
--- /dev/null
+++ b/preview/pages/trial-ended.astro
@@ -0,0 +1,50 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import Icon from '@shared/components/Icon.astro';
+---
+
+
+
+
+
Your free trial period has expired!
+
+
+ If you want to continue to benefit from Tabler, it's time to upgrade your plan.
+
+
+
+
+
+
+ Over 800+ productions
+ Unlimited movies, TV shows and more.
+
+
+
+
+
+ Watch everywhere
+ Watch on smart TVs, PlayStation, Xbox, Apple TV, Blu-ray players and more.
+
+
+
+
+
+ Personalize
+ Choose your own style, watch what you like.
+
+
+
+
+
+
+
+ If you need to get a trial extension please feel free to contact us .
+
+
+
+
diff --git a/preview/pages/trial-ended.html b/preview/pages/trial-ended.html
deleted file mode 100644
index 403477900..000000000
--- a/preview/pages/trial-ended.html
+++ /dev/null
@@ -1,48 +0,0 @@
----
-layout: single
-permalink: trial-ended.html
----
-
-
-
-
Your free trial period has expired!
-
-
- If you want to continue to benefit from Tabler, it's time to upgrade your plan.
-
-
-
-
- {% include "ui/icon.html" icon="check" class="me-1 text-success" %}
-
- Over 800+ productions
- Unlimited movies, TV shows and more.
-
-
-
- {% include "ui/icon.html" icon="check" class="me-1 text-success" %}
-
- Watch everywhere
- Watch on smart TVs, PlayStation, Xbox, Apple TV, Blu-ray players and more.
-
-
-
- {% include "ui/icon.html" icon="check" class="me-1 text-success" %}
-
- Personalize
- Choose your own style, watch what you like.
-
-
-
-
-
-
-
- If you need to get a trial extension please feel free to contact us .
-
-
-
\ No newline at end of file
diff --git a/preview/pages/turbo-loader.html b/preview/pages/turbo-loader.astro
similarity index 52%
rename from preview/pages/turbo-loader.html
rename to preview/pages/turbo-loader.astro
index f60de2b93..e991c215d 100644
--- a/preview/pages/turbo-loader.html
+++ b/preview/pages/turbo-loader.astro
@@ -1,27 +1,13 @@
---
-permalink: turbo-loader.html
-layout: default
-page-libs: [turbo]
-page-menu: plugins.turbo
----
+// Port of preview/pages/turbo-loader.html (layout: default, page-libs: [turbo]).
+// The {% capture_script %} block is registered synchronously (before any await).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import { addPageScript } from '@shared/lib/page-scripts';
-
-
-
- Show loader
- Hide loader
- Set 10%
- Set 50%
- Set 100%
-
-
-
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
+`);
+---
+
+
+
+
+
+ Show loader
+ Hide loader
+ Set 10%
+ Set 50%
+ Set 100%
+
+
+
+
diff --git a/preview/pages/typography.astro b/preview/pages/typography.astro
new file mode 100644
index 000000000..2bcf3db7f
--- /dev/null
+++ b/preview/pages/typography.astro
@@ -0,0 +1,144 @@
+---
+// Port of preview/pages/typography.html (layout: default)
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+---
+
+
+
+
+
+
+
1/1 Text
+
I'm not a witch. Now, look here, my good man. Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed! Well, I didn't vote for you. You can't expect to wield supreme power just 'cause some watery tart threw a sword at you! Bring her forward! He hasn't got shit all over him. He hasn't got shit all over him. We shall say 'Ni' again to you, if you do not appease us.
+
Well, we did do the nose. Why? Now, look here, my good man. Be quiet! Well, what do you want?
+
+
+
+
1/2 Text
+
What do you mean? We shall say 'Ni' again to you, if you do not appease us. I have to push the pram a lot. No, no, no! Yes, yes. A bit. But she's got a wart. What a strange person.
+
+
+
+
1/2 Text
+
And this isn't my nose. This is a false one. We found them. Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
+
+
+
+
+
1/3 Text
+
Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. Why? Well, what do you want? …Are you suggesting that coconuts migrate?
+
+
+
2/3 Text
+
Well, I got better. Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. Found them? In Mercia?! The coconut's tropical! A newt? …Are you suggesting that coconuts migrate?
+
+
+
+
I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! We want a shrubbery!!
+
Well, how'd you become king, then? Found them? In Mercia?! The coconut's tropical! Oh, ow! I am your king.
+
+
+
+
Small Text
+
Well, Mercia's a temperate zone! You don't vote for kings. Now, look here, my good man.
+
Who's that then? Well, we did do the nose.
+
+
+
+
+
Unordered list
+
+ lorem ipsum doloret
+ lorem ipsum doloret
+
+ lorem ipsum doloret
+ lorem ipsum doloret
+
+
+ lorem ipsum doloret
+ lorem ipsum doloret
+
+
+
+
+
Ordered list
+
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+
+
+
+
+
Unstyled list
+
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+ lorem ipsum doloret
+
+
+
+
+
+
Blockquote
+
+
+ I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! The nose?
+
+
+
+
+
+
Text elements
+
+
You can use the mark tag to highlight text.
+
This line of text is meant to be treated as deleted
+
This line of text will render as underlined.
+
This line of text is meant to be treated as fine print.
+
The following snippet of text is rendered as bold text.
+
The following snippet of text is rendered as italicized text.
+
The following snippet of text show useful keyboard shortcut: ⌘ + C or ctrl + C .
+
+
+
+
Text color
+
This is an example of primary text.
+
This is an example of secondary text.
+
This is an example of body text.
+
This is an example of success text.
+
This is an example of info text.
+
This is an example of warning text.
+
This is an example of danger text.
+
This is an example of pink text.
+
+
+
+
Addresses
+
Twitter, Inc. 1355 Market Street, Suite 900
+ San Francisco, CA 94103 P: (123) 456 7890
+
+
Full name first.last@example.com
+
+
+
+
Typography
+
+
+ {
+ [1, 2, 3, 4, 5, 6].map((i) => {
+ const Heading = `h${i}` as keyof HTMLElementTagNameMap;
+ return H{i} Lorem ipsum dolor sit amet ;
+ })
+ }
+
+
+
+
+
+
diff --git a/preview/pages/typography.html b/preview/pages/typography.html
deleted file mode 100644
index 5e6bba964..000000000
--- a/preview/pages/typography.html
+++ /dev/null
@@ -1,143 +0,0 @@
----
-title: Typography
-page-header: Typography
-page-menu: base.typography
-layout: default
-permalink: typography.html
----
-
-
-
-
-
-
1/1 Text
-
I'm not a witch. Now, look here, my good man. Oh! Come and see the violence inherent in the system! Help, help, I'm being repressed! Well, I didn't vote for you. You can't expect to wield supreme power just 'cause some watery tart threw a sword at you! Bring her forward! He hasn't got shit all over him. He hasn't got shit all over him. We shall say 'Ni' again to you, if you do not appease us.
-
Well, we did do the nose. Why? Now, look here, my good man. Be quiet! Well, what do you want?
-
-
-
-
1/2 Text
-
What do you mean? We shall say 'Ni' again to you, if you do not appease us. I have to push the pram a lot. No, no, no! Yes, yes. A bit. But she's got a wart. What a strange person.
-
-
-
-
1/2 Text
-
And this isn't my nose. This is a false one. We found them. Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.
-
-
-
-
-
1/3 Text
-
Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. Why? Well, what do you want? …Are you suggesting that coconuts migrate?
-
-
-
2/3 Text
-
Well, I got better. Knights of Ni, we are but simple travelers who seek the enchanter who lives beyond these woods. Found them? In Mercia?! The coconut's tropical! A newt? …Are you suggesting that coconuts migrate?
-
-
-
-
I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! We want a shrubbery!!
-
Well, how'd you become king, then? Found them? In Mercia?! The coconut's tropical! Oh, ow! I am your king.
-
-
-
-
Small Text
-
Well, Mercia's a temperate zone! You don't vote for kings. Now, look here, my good man.
-
Who's that then? Well, we did do the nose.
-
-
-
-
-
Unordered list
-
- lorem ipsum doloret
- lorem ipsum doloret
-
- lorem ipsum doloret
- lorem ipsum doloret
-
-
- lorem ipsum doloret
- lorem ipsum doloret
-
-
-
-
-
Ordered list
-
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
-
-
-
-
-
Unstyled list
-
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
- lorem ipsum doloret
-
-
-
-
-
-
Blockquote
-
-
- I don't want to talk to you no more, you empty-headed animal food trough water! I fart in your general direction! Your mother was a hamster and your father smelt of elderberries! Now leave before I am forced to taunt you a second time! The nose?
-
-
-
-
-
-
Text elements
-
-
You can use the mark tag to highlight text.
-
This line of text is meant to be treated as deleted
-
This line of text will render as underlined.
-
This line of text is meant to be treated as fine print.
-
The following snippet of text is rendered as bold text.
-
The following snippet of text is rendered as italicized text.
-
The following snippet of text show useful keyboard shortcut: ⌘ + C or ctrl + C .
-
-
-
-
Text color
-
This is an example of primary text.
-
This is an example of secondary text.
-
This is an example of body text.
-
This is an example of success text.
-
This is an example of info text.
-
This is an example of warning text.
-
This is an example of danger text.
-
This is an example of pink text.
-
-
-
-
Addresses
-
Twitter, Inc. 1355 Market Street, Suite 900
- San Francisco, CA 94103 P: (123) 456 7890
-
-
Full name first.last@example.com
-
-
-
-
Typography
-
-
- {% for i in (1..6) %}
- H{{ i }} Lorem ipsum dolor sit amet
- {% endfor %}
-
-
-
-
-
-
diff --git a/preview/pages/uptime.astro b/preview/pages/uptime.astro
new file mode 100644
index 000000000..600e004d5
--- /dev/null
+++ b/preview/pages/uptime.astro
@@ -0,0 +1,109 @@
+---
+// Port of preview/pages/uptime.html.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Chart from '@shared/components/Chart.astro';
+---
+
+
+
+
+
+
+
+
14 days 2 hours 54 mins 34 seconds
+
+
+
+
+
+
+
+
+
Response times across regions in the last day
+
+
+
+
+
+
+
+
Uptime incidents per day
+
+
+
+
+
+
+
+
+
+
+ Time period
+ Availability
+ Downtime
+ Incidents
+ Longest incident
+ Avg. incident
+
+
+
+ Today
+ 98.9533%
+ 1 minute
+ 1
+ 1 minute
+ 1 minute
+
+
+ Last 7 days
+ 98.9533%
+ 1 minute
+ 1
+ 1 minute
+ 1 minute
+
+
+ Last 30 days
+ 98.9533%
+ 1 minute
+ 1
+ 1 minute
+ 1 minute
+
+
+ Last 365 days
+ 98.9533%
+ 1 minute
+ 1
+ 1 minute
+ 1 minute
+
+
+ All time
+ 98.9533%
+ 1 minute
+ 1
+ 1 minute
+ 1 minute
+
+
+
+
+
+
+
+
diff --git a/preview/pages/uptime.html b/preview/pages/uptime.html
deleted file mode 100644
index e06bd0244..000000000
--- a/preview/pages/uptime.html
+++ /dev/null
@@ -1,110 +0,0 @@
----
-page-header-file: uptime
-page-libs: [apexcharts]
-page-menu: extra.uptime
-layout: default
-permalink: uptime.html
----
-
-
-
-
-
-
-
14 days 2 hours 54 mins 34 seconds
-
-
-
-
-
-
-
-
-
Response times across regions in the last day
- {% include "ui/chart.html" chart-id="uptime" height=15 %}
-
-
-
-
-
-
-
Uptime incidents per day
- {% include "ui/chart.html" chart-id="uptime-incidents" height=15 %}
-
-
-
-
-
-
-
-
-
- Time period
- Availability
- Downtime
- Incidents
- Longest incident
- Avg. incident
-
-
-
- Today
- 98.9533%
- 1 minute
- 1
- 1 minute
- 1 minute
-
-
- Last 7 days
- 98.9533%
- 1 minute
- 1
- 1 minute
- 1 minute
-
-
- Last 30 days
- 98.9533%
- 1 minute
- 1
- 1 minute
- 1 minute
-
-
- Last 365 days
- 98.9533%
- 1 minute
- 1
- 1 minute
- 1 minute
-
-
- All time
- 98.9533%
- 1 minute
- 1
- 1 minute
- 1 minute
-
-
-
-
-
-
-
-
diff --git a/preview/pages/users.astro b/preview/pages/users.astro
new file mode 100644
index 000000000..2ea8061f8
--- /dev/null
+++ b/preview/pages/users.astro
@@ -0,0 +1,70 @@
+---
+// Port of preview/pages/users.html (layout: default)
+// Note: the Liquid template assigns `progress` and `online_counter` per person
+// but never renders them — omitted here.
+// Note: the avatar include passes `rounded=true`, which ui/avatar.html ignores
+// (no such param) — omitted; Avatar.astro has no `rounded` prop.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Avatar from '@shared/components/ui/Avatar.astro';
+import Icon from '@shared/components/Icon.astro';
+import Pagination from '@shared/components/ui/Pagination.astro';
+import people from '@data/people.json';
+
+interface Person {
+ full_name?: string;
+ job_title?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+const users = (people as Person[]).slice(0, 18);
+---
+
+
+
+ {
+ users.map((person, idx) => {
+ const index = idx + 1;
+ return (
+
+
+
+
+
+
{person.job_title}
+
+
+ {index === 1 ? (
+ Owner
+ ) : index < 5 ? (
+ Admin
+ ) : null}
+
+
+
+
+
+ );
+ })
+ }
+
+
+
+
diff --git a/preview/pages/users.html b/preview/pages/users.html
deleted file mode 100644
index da4160093..000000000
--- a/preview/pages/users.html
+++ /dev/null
@@ -1,41 +0,0 @@
----
-layout: default
-title: Users list
-page-header: Users
-page-header-actions: users
-page-header-description: 1-18 of 413 people
-page-menu: extra.users
-permalink: users.html
----
-
-
- {% for person in people limit: 18 %}
- {% assign progress = forloop.index | random_number: 4, 95 %}
- {% assign online_counter = forloop.index | random_number: 1, 10 %}
-
-
-
- {% include "ui/avatar.html" size="xl" rounded=true person=person class="mb-3" %}
-
-
{{ person.job_title }}
-
-
- {% if forloop.index == 1 %}
- Owner
- {% elsif forloop.index < 5 %}
- Admin
- {% endif %}
-
-
-
-
-
- {% endfor %}
-
-
-
- {% include "ui/pagination.html" class="ms-auto" %}
-
diff --git a/preview/pages/widgets.astro b/preview/pages/widgets.astro
new file mode 100644
index 000000000..5170f2f2f
--- /dev/null
+++ b/preview/pages/widgets.astro
@@ -0,0 +1,129 @@
+---
+// Port of preview/pages/widgets.html (layout: default).
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import StatCard from '@shared/components/cards/StatCard.astro';
+import ProjectProgress from '@shared/components/cards/ProjectProgress.astro';
+import UserCard from '@shared/components/cards/UserCard.astro';
+import UserCardBig from '@shared/components/cards/UserCardBig.astro';
+import UserCardBg from '@shared/components/cards/UserCardBg.astro';
+import Subscribe from '@shared/components/cards/Subscribe.astro';
+import SmallStats from '@shared/components/cards/SmallStats.astro';
+import Code from '@shared/components/cards/Code.astro';
+import ProjectSummary from '@shared/components/cards/ProjectSummary.astro';
+import ProjectKanban from '@shared/components/cards/ProjectKanban.astro';
+import UserInfo from '@shared/components/cards/UserInfo.astro';
+import Configuration from '@shared/components/cards/Configuration.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/preview/pages/widgets.html b/preview/pages/widgets.html
deleted file mode 100644
index 9e0adad95..000000000
--- a/preview/pages/widgets.html
+++ /dev/null
@@ -1,130 +0,0 @@
----
-title: Widgets
-page-header: Widgets
-page-menu: extra.widgets
-page-libs: [apexcharts]
-layout: default
-permalink: widgets.html
----
-
-
-
- {% include "cards/stat-card.html" title="Earned" value="$2,847" icon="credit-card" %}
-
-
- {% include "cards/stat-card.html" title="Hours logged" value="42.7 hrs" icon="clock" %}
-
-
- {% include "cards/stat-card.html" title="Avg. time" value="3:28 hrs" icon="slideshow" %}
-
-
- {% include "cards/stat-card.html" title="Weekly growth" value="18.4%" icon="discount" %}
-
-
-
- {% include "cards/project-progress.html" %}
-
-
- {% include "cards/project-progress.html" project-id=2 progress=76 days-ago=7 %}
-
-
-
{% include "cards/user-card.html" person-id=5 %}
-
{% include "cards/user-card.html" person-id=6 %}
-
{% include "cards/user-card.html" person-id=7 right=true %}
-
{% include "cards/user-card.html" person-id=8 right=true %}
-
-
{% include "cards/user-card-big.html" person-id=15 %}
-
{% include "cards/user-card-big.html" person-id=16 %}
-
{% include "cards/user-card-big.html" person-id=17 %}
-
{% include "cards/user-card-big.html" person-id=18 %}
-
-
{% include "cards/user-card-bg.html" person-id=25 %}
-
{% include "cards/user-card-bg.html" person-id=26 %}
-
{% include "cards/user-card-bg.html" person-id=27 blurred=true %}
-
{% include "cards/user-card-bg.html" person-id=28 blurred=true %}
-
-
-
- {% include "cards/subscribe.html" person-id=0 %}
-
-
- {% include "cards/subscribe.html" person-id=2 %}
-
-
-
- {% include "cards/small-stats.html" id="currency" icon="currency-dollar" color="primary" title="132 Sales"
- description="12 waiting payments" %}
-
-
- {% include "cards/small-stats.html" id="shopping-cart" icon="shopping-cart" color="green" title="78 Orders"
- description="32 shipped" %}
-
-
- {% include "cards/small-stats.html" id="user" icon="user" color="red" title="1352 Members" description="163
- registered today" %}
-
-
- {% include "cards/small-stats.html" id="message" icon="message" color="yellow" title="132 Comments"
- description="16 waitings" %}
-
-
-
{% include "cards/small-stats.html" id="sales" chart-position="left"
- chart-type="donut" chart-data="56" color="primary" title="132 Sales" description="12 waiting payments" %}
-
-
{% include "cards/small-stats.html" id="orders" chart-position="left"
- chart-type="donut" chart-data="56" color="green" title="78 Orders" description="32 shipped" %}
-
-
{% include "cards/small-stats.html" id="members" chart-position="left"
- chart-type="donut" chart-data="56" color="red" title="1352 Members" description="163 registered today" %}
-
-
{% include "cards/small-stats.html" id="comments" chart-position="left"
- chart-type="donut" chart-data="56" color="yellow" title="132 Comments" description="16 waitings" %}
-
-
-
{% include "cards/small-stats.html" id="sales" icon="arrow-up" color="green" lt=true
- title="$5,256.99" description="Revenue last 30 days" description-value="+4%" %}
-
-
{% include "cards/small-stats.html" id="orders" icon="arrow-down" color="red" lt=true
- title="342" description="Sales last 30 days" description-value="-4.3%" description-value-color="red" %}
-
-
{% include "cards/small-stats.html" id="members" icon="arrow-up" color="green" lt=true
- title="132" description="Customers last 30 days" description-value="+6.8%" %}
-
-
{% include "cards/small-stats.html" id="comments" icon="arrow-down" color="red"
- lt=true title="78" description="Members registered today" description-value="-2%" description-value-color="red" %}
-
-
-
-
-
{% include "cards/small-stats.html" chart-type="line" chart-data="20,0,40,30,40,30,80,60"
- %}
-
{% include "cards/small-stats.html" chart-type="bar" chart-data="20,40,30,10,40,60,80,70"
- color="red" icon="heart" %}
-
{% include "cards/small-stats.html" chart-type="bar"
- chart-data="20,40,20,-10,-30,10,40,60,80,70" color="green" icon="brand-github" %}
-
{% include "cards/small-stats.html" chart-type="donut" chart-data="12" person-id=10 %}
-
-
{% include "cards/small-stats.html" chart-type="donut" chart-data="12" person-id=11 %}
-
-
{% include "cards/small-stats.html" chart-type="donut" chart-data="56" person-id=1 %}
-
{% include "cards/small-stats.html" color="green" person-id=4 %}
-
{% include "cards/small-stats.html" small-icon="trending-down" color="red" person-id=3 %}
-
-
{% include "cards/code.html" %}
-
-
-
-
-
{% include "cards/project-summary.html" stage-color="red" %}
-
-
-
-
-
{% include "cards/project-kanban.html" title="Tabler UI" badge="v1.0" value=30
- percentage-color="red" limit=4 offset=0 due="72 days" %}
-
{% include "cards/project-kanban.html" title="Tabler React" value=80 offset=20 %}
-
{% include "cards/user-info.html" %}
-
{% include "cards/configuration.html" %}
-
-
-
\ No newline at end of file
diff --git a/preview/pages/wizard.astro b/preview/pages/wizard.astro
new file mode 100644
index 000000000..9c2a8432d
--- /dev/null
+++ b/preview/pages/wizard.astro
@@ -0,0 +1,61 @@
+---
+import SingleLayout from '@shared/layouts/SingleLayout.astro';
+import Button from '@shared/components/Button.astro';
+import HrText from '@shared/components/HrText.astro';
+import InputGroup from '@shared/components/InputGroup.astro';
+import Illustration from '@shared/components/ui/Illustration.astro';
+import Progress from '@shared/components/ui/Progress.astro';
+import { site } from '@shared/lib/site';
+import timezones from '@data/timezones.json';
+
+// TODO: front matter `page-menu: extra.wizard` is not ported — it is only read
+// by layout/navbar-menu.html, which the `single` layout does not include.
+---
+
+
+
+
+
+
Welcome to Tabler!
+
{site.description}
+
+
+
+
+
+
+
Create your Tabler URL
+
+
+ Choose a URL that describes you or your business in a concise way. Make it short and easy
+ to remember so you can share links with ease.
+
+
+
+
+ Timezone
+
+ {
+ timezones.map((timezone) => (
+
+ {timezone.text}
+
+ ))
+ }
+
+
+
+
+
+
+
diff --git a/preview/pages/wizard.html b/preview/pages/wizard.html
deleted file mode 100644
index 044f3c252..000000000
--- a/preview/pages/wizard.html
+++ /dev/null
@@ -1,46 +0,0 @@
----
-title: Wizard
-layout: single
-page-menu: extra.wizard
-permalink: wizard.html
----
-
-
-
- {% include "ui/illustration.html" image="boy-girl.svg" height="200" class="mb-n2" %}
-
Welcome to Tabler!
-
{{ site.description }}
-
-
- {% include "ui/hr.html" text="your data" position="center" class="hr-text-spaceless" %}
-
-
-
-
Create your Tabler URL
- {% include "ui/form/input-group.html" prepend="https://tabler.io/" input-class="ps-1" flat=true %}
-
Choose a URL that describes you or your business in a concise way. Make it short and easy to remember so you can share links with ease.
-
-
-
- Timezone
-
- {% for timezone in timezones %}
- {{ timezone.text }}
- {% endfor %}
-
-
-
-
-
-
-
- {% include "ui/progress.html" value=25 %}
-
-
-
- {% include "ui/button.html" text="Set up later" color="link link-secondary" %}
- {% include "ui/button.html" text="Continue" color="primary" %}
-
-
-
-
diff --git a/preview/pages/wysiwyg.astro b/preview/pages/wysiwyg.astro
new file mode 100644
index 000000000..d0202cfcb
--- /dev/null
+++ b/preview/pages/wysiwyg.astro
@@ -0,0 +1,22 @@
+---
+// Port of preview/pages/wysiwyg.html (layout: default).
+// The front matter uses `menu: base.wysiwyg` (not `page-menu`), so no pageMenu prop.
+import DefaultLayout from '@shared/layouts/DefaultLayout.astro';
+import Wysiwyg from '@shared/components/ui/Wysiwyg.astro';
+---
+
+
+
+
+
+ Your name
+
+
+
+
+ Description
+
+
+
+
+
diff --git a/preview/pages/wysiwyg.html b/preview/pages/wysiwyg.html
deleted file mode 100644
index 7896cb157..000000000
--- a/preview/pages/wysiwyg.html
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: HugeRTE
-page-header: HugeRTE
-menu: base.wysiwyg
-page-libs: [hugerte]
-permalink: /wysiwyg.html
-layout: default
----
-
-
-
-
-
- Your name
-
-
-
-
- Description
- {% include "ui/wysiwyg.html" %}
-
-
-
\ No newline at end of file
diff --git a/preview/scss/demo.scss b/preview/scss/demo.scss
index 645e48aad..c2aea4fc5 100644
--- a/preview/scss/demo.scss
+++ b/preview/scss/demo.scss
@@ -22,12 +22,6 @@ $prefix: "tblr-";
stroke-width: 1.5;
margin: 0 auto;
display: block;
-
- // @include media-breakpoint-down(sm) {
- // width: 10rem;
- // height: 10rem;
- // font-size: 10rem;
- // }
}
}
@@ -86,4 +80,4 @@ $demo-icon-size: 4rem;
&:hover {
text-decoration: none;
}
-}
\ No newline at end of file
+}
diff --git a/preview/static b/preview/static
deleted file mode 120000
index 36b10cebf..000000000
--- a/preview/static
+++ /dev/null
@@ -1 +0,0 @@
-../shared/static
\ No newline at end of file
diff --git a/preview/tsconfig.json b/preview/tsconfig.json
new file mode 100644
index 000000000..3d9ffcc97
--- /dev/null
+++ b/preview/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "extends": "astro/tsconfigs/strict",
+ "include": [
+ ".astro/types.d.ts",
+ "**/*"
+ ],
+ "exclude": [
+ "dist"
+ ],
+ "compilerOptions": {
+ "paths": {
+ "@data/*": [
+ "../shared/data/*"
+ ],
+ "@shared/*": [
+ "../shared/astro/*"
+ ]
+ },
+ "baseUrl": "."
+ }
+}
diff --git a/preview/vercel.json b/preview/vercel.json
index 683aa92d8..c01656139 100644
--- a/preview/vercel.json
+++ b/preview/vercel.json
@@ -1,66 +1,5 @@
{
- "rewrites": [
- {
- "source": "/stats/js/script.js",
- "destination": "https://plausible.io/js/script.js"
- },
- {
- "source": "/stats/event",
- "destination": "https://plausible.io/api/event"
- },
- {
- "source": "/eat/static/:path(.*)",
- "destination": "https://eu-assets.i.posthog.com/static/:path*"
- },
- {
- "source": "/eat/:path(.*)",
- "destination": "https://eu.i.posthog.com/:path*"
- },
- {
- "source": "/(.*)",
- "destination": "/error-404.html"
- }
- ],
"redirects": [
- {
- "source": "/docs",
- "destination": "https://tabler.io/docs",
- "permanent": true
- },
- {
- "source": "/docs/:name(colors|typography?).html",
- "destination": "https://tabler.io/docs/base/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(alerts|autosize|avatars|badges|breadcrumb|buttons|cards|carousel|charts|countup|datagrid|divider|dropdowns|dropzone|empty|icons|inline-player|modals|placeholder|popover|progress|progressbg|range-slider|ribbons|spinners|statuses|steps|switch-icon|tables|tabs|timelines|tinymce|toasts|tooltips|tracking?).html",
- "destination": "https://tabler.io/docs/components/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(form-color-check|form-elements|form-fieldset|form-helpers|form-image-check|form-input-mask|form-selectboxes|form-validation?).html",
- "destination": "https://tabler.io/docs/forms/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(browser-support|customize|download|faq?).html",
- "destination": "https://tabler.io/docs/getting-started/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(page-headers?).html",
- "destination": "https://tabler.io/docs/layout/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(flags|payments?).html",
- "destination": "https://tabler.io/docs/plugins/:name",
- "permanent": true
- },
- {
- "source": "/docs/:name(borders|cursors|interactions?).html",
- "destination": "https://tabler.io/docs/plugins/:name",
- "permanent": true
- }
+ { "source": "/marketing", "destination": "/marketing.html", "permanent": true }
]
-}
\ No newline at end of file
+}
diff --git a/shared/astro/components/Alert.astro b/shared/astro/components/Alert.astro
new file mode 100644
index 000000000..c21958a96
--- /dev/null
+++ b/shared/astro/components/Alert.astro
@@ -0,0 +1,99 @@
+---
+// Port ui/alert.html
+import Icon from './Icon.astro';
+
+interface Props {
+ type?: string;
+ icon?: string;
+ important?: boolean;
+ minor?: boolean;
+ showClose?: boolean;
+ avatar?: boolean;
+ class?: string;
+ title?: string;
+ description?: string;
+ /** comma-separated list of items (the list param in Liquid) */
+ list?: string;
+ action?: string;
+ link?: string;
+ buttons?: boolean;
+}
+
+const {
+ type = 'success',
+ icon: iconProp,
+ important,
+ minor,
+ showClose,
+ avatar,
+ class: className,
+ title = 'This is a custom alert box!',
+ description,
+ list,
+ action,
+ link,
+ buttons,
+} = Astro.props;
+
+const defaultIcons: Record = {
+ success: 'check',
+ warning: 'alert-triangle',
+ danger: 'alert-circle',
+ info: 'info-circle',
+};
+const icon = iconProp ?? defaultIcons[type];
+
+const classes = [
+ 'alert',
+ important ? 'alert-important' : minor ? 'alert-minor' : undefined,
+ `alert-${type}`,
+ showClose && 'alert-dismissible',
+ avatar && 'alert-avatar',
+ className,
+]
+ .filter(Boolean)
+ .join(' ');
+
+const listItems = (list ?? '').split(',').filter(Boolean);
+---
+
+
+
{icon && }
+ {
+ description || list ? (
+
+ {/* Liquid doesn't escape {{ include.title }} — set:html preserves entities like … */}
+
+
+
+ {listItems.length > 0 && (
+
+ {listItems.map((item) => (
+ {item}
+ ))}
+
+ )}
+
+
+ ) : (
+
+
+ {/* prettier-ignore — anchor on one line as in Liquid (whitespace ends up in the code panel) */}
+ {action ? (
+ {action}
+ ) : link ? (
+ {link}
+ ) : null}
+
+ )
+ }
+ {
+ buttons && (
+
+ )
+ }
+ {showClose &&
}
+
diff --git a/shared/astro/components/Button.astro b/shared/astro/components/Button.astro
new file mode 100644
index 000000000..96c13390e
--- /dev/null
+++ b/shared/astro/components/Button.astro
@@ -0,0 +1,116 @@
+---
+// Port of ui/button.html.
+// TODO: spinner param (needs a ui/spinner.html port — no Spinner.astro yet).
+// TODO: provider param (assigned in ui/button.html but never used in its markup).
+// TODO: color=false special case (Liquid resets color to null; pass no color instead).
+import Icon from './Icon.astro';
+
+interface Props {
+ text?: string;
+ href?: string;
+ /** raw href + target="_blank" rel="noreferrer" (external param in ui/button.html) */
+ external?: boolean;
+ element?: 'a' | 'button';
+ type?: string;
+ id?: string;
+ color?: string;
+ outline?: boolean;
+ ghost?: boolean;
+ /** btn-{height} right after btn (height param in ui/button.html) */
+ height?: string;
+ size?: string;
+ block?: boolean;
+ disabled?: boolean;
+ square?: boolean;
+ loading?: boolean;
+ action?: boolean;
+ pill?: boolean;
+ /** btn-link (link param in ui/button.html) */
+ link?: boolean;
+ class?: string;
+ icon?: string;
+ iconColor?: string;
+ iconEnd?: string;
+ iconOnly?: boolean;
+ /** after the text (dots param in ui/button.html) */
+ dots?: boolean;
+ /** data-bs-toggle="modal" data-bs-target="#modal-{modalId}" (modal-id param) */
+ modalId?: string;
+ /** data-bs-toggle="toast" data-bs-target="#toast-{toastId}" (toast-id param) */
+ toastId?: string;
+ /** data-bs-dismiss="modal" (dismiss param in ui/button.html) */
+ dismiss?: boolean;
+}
+
+const {
+ text = 'Button',
+ href,
+ external,
+ element: Element = 'a',
+ type,
+ id,
+ color,
+ outline,
+ ghost,
+ height,
+ size,
+ block,
+ disabled,
+ square,
+ loading,
+ action,
+ pill,
+ link,
+ class: className,
+ icon,
+ iconColor,
+ iconEnd,
+ iconOnly,
+ dots,
+ modalId,
+ toastId,
+ dismiss,
+} = Astro.props;
+
+// ui/button.html: href defaults to '#'; with external the href stays raw,
+// without external it is prefixed with site.base + '/' (site.base is undefined
+// in Eleventy, so it comes out as '/{href}').
+const resolvedHref = href ? (external ? href : `/${href}`) : '#';
+
+// Class token order exactly as in ui/button.html.
+const classes = [
+ 'btn',
+ height && `btn-${height}`,
+ color && `btn-${outline ? 'outline-' : ghost ? 'ghost-' : ''}${color}`,
+ disabled && 'disabled',
+ square && 'btn-square',
+ loading && 'btn-loading',
+ action && 'btn-action',
+ pill && 'btn-pill',
+ size && `btn-${size}`,
+ className,
+ block && 'w-100',
+ link && 'btn-link',
+ iconOnly && 'btn-icon',
+]
+ .filter(Boolean)
+ .join(' ');
+---
+
+
+ {icon && }
+ {!iconOnly && text}
+ {!iconOnly && dots && }
+ {!iconOnly && iconEnd && }
+
diff --git a/shared/astro/components/Chart.astro b/shared/astro/components/Chart.astro
new file mode 100644
index 000000000..7282e7fc0
--- /dev/null
+++ b/shared/astro/components/Chart.astro
@@ -0,0 +1,48 @@
+---
+import charts from '@data/charts.json';
+import { addPageScript } from '@shared/lib/page-scripts';
+import { chartSnippet, type ChartData } from '@shared/lib/chart-script';
+import InlineScript from '@shared/components/InlineScript.astro';
+
+interface Props {
+ chartId: string;
+ id?: string;
+ size?: 'sm' | 'lg';
+ class?: string;
+ height?: number;
+}
+
+const { chartId, id = chartId, size, class: classProp, height: heightProp } = Astro.props;
+
+const chartsData = charts as Record;
+let data = chartsData[chartId];
+
+let className = classProp;
+let height = heightProp ?? data?.height ?? 10;
+
+if (size === 'sm') {
+ className = `${classProp ?? ''} chart-sm`.trim();
+ height = 2.5;
+} else if (size === 'lg') {
+ className = `${classProp ?? ''} chart-lg`.trim();
+ height = 15;
+}
+
+if (data?.extend) {
+ data = { ...chartsData[data.extend], ...chartsData[chartId] };
+}
+
+const script = data ? chartSnippet({ id, chartId, data, height }) : '';
+if (data) {
+ addPageScript(script);
+}
+---
+
+{
+ data && (
+
+
+
+
+ )
+}
diff --git a/shared/astro/components/HomepageContent.astro b/shared/astro/components/HomepageContent.astro
new file mode 100644
index 000000000..22bb722d0
--- /dev/null
+++ b/shared/astro/components/HomepageContent.astro
@@ -0,0 +1,117 @@
+---
+// Port of shared/includes/layout/homepage.html — the homepage card grid,
+// shared by index.astro and layout-vertical.astro.
+import Chart from './Chart.astro';
+import MapVectorCard from './cards/MapVectorCard.astro';
+import Welcome from './cards/Welcome.astro';
+import TotalUsers from './cards/charts/TotalUsers.astro';
+import ActiveUsers2 from './cards/charts/ActiveUsers2.astro';
+import Sales from './cards/charts/Sales.astro';
+import Revenue from './cards/charts/Revenue.astro';
+import NewClients from './cards/charts/NewClients.astro';
+import ActiveUsers from './cards/charts/ActiveUsers.astro';
+import SmallStats from './cards/SmallStats.astro';
+import StorageUsage from './cards/StorageUsage.astro';
+import ActivityCard from './cards/ActivityCard.astro';
+import DevelopmentActivity from './cards/DevelopmentActivity.astro';
+import IconsBanner from './cards/IconsBanner.astro';
+import MostVisitedPages from './cards/MostVisitedPages.astro';
+import Sponsor from './cards/Sponsor.astro';
+import SocialTraffic from './cards/SocialTraffic.astro';
+import Tasks from './cards/Tasks.astro';
+import Invoices from './cards/Invoices.astro';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Traffic summary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/components/HrText.astro b/shared/astro/components/HrText.astro
new file mode 100644
index 000000000..2a87cc23b
--- /dev/null
+++ b/shared/astro/components/HrText.astro
@@ -0,0 +1,21 @@
+---
+interface Props {
+ text?: string;
+ position?: string;
+ color?: string;
+ class?: string;
+}
+
+const { text = 'Label', position, color, class: className } = Astro.props;
+
+const classes = [
+ 'hr-text',
+ position && `hr-text-${position.toLowerCase()}`,
+ color && `text-${color}`,
+ className,
+]
+ .filter(Boolean)
+ .join(' ');
+---
+
+{text}
diff --git a/shared/astro/components/Icon.astro b/shared/astro/components/Icon.astro
new file mode 100644
index 000000000..4b12efa08
--- /dev/null
+++ b/shared/astro/components/Icon.astro
@@ -0,0 +1,32 @@
+---
+import icons from '@data/icons.json';
+
+interface Props {
+ name: string;
+ type?: 'outline' | 'filled';
+ class?: string;
+ color?: string;
+ size?: string;
+ inline?: boolean;
+}
+
+const { name, type = 'outline', class: className, color, size, inline } = Astro.props;
+
+const icon = (icons as Record }>)[name];
+
+const classes = [
+ 'icon',
+ className,
+ color && `text-${color}`,
+ inline && 'icon-inline',
+ size && `icon-${size}`,
+]
+ .filter(Boolean)
+ .join(' ');
+
+let svg = icon?.svg?.[type] ?? '';
+svg = svg.replace(' ', '');
+svg = svg.replace(/class="[^"]+"/, `aria-hidden="true" focusable="false" class="${classes}"`);
+---
+
+{icon && \n\t${svg}`} />}
diff --git a/shared/astro/components/InlineScript.astro b/shared/astro/components/InlineScript.astro
new file mode 100644
index 000000000..29a08b47e
--- /dev/null
+++ b/shared/astro/components/InlineScript.astro
@@ -0,0 +1,17 @@
+---
+// Single shared implementation of the script emission point. The consuming
+// package selects the behavior via the INLINE_PAGE_SCRIPTS vite define in its
+// astro.config:
+// - preview (false): renders nothing — scripts are registered via
+// addPageScript() and drained by at the end of ,
+// mirroring Eleventy's {% capture_script %} model (parity gate).
+// - docs (true): emits the script inline at the component site — the docs
+// layout has no drain; example markup carries its own scripts.
+interface Props {
+ code: string;
+}
+
+const { code } = Astro.props;
+---
+
+{import.meta.env.INLINE_PAGE_SCRIPTS && }
diff --git a/shared/astro/components/InputGroup.astro b/shared/astro/components/InputGroup.astro
new file mode 100644
index 000000000..ebb8ef1e0
--- /dev/null
+++ b/shared/astro/components/InputGroup.astro
@@ -0,0 +1,67 @@
+---
+import Icon from './Icon.astro';
+
+interface Props {
+ type?: string;
+ placeholder?: string;
+ value?: string;
+ flat?: boolean;
+ class?: string;
+ inputClass?: string;
+ id?: string;
+ prepend?: string;
+ append?: string;
+ /** comma-separated list of "icon:description" pairs, same as the Liquid include */
+ appendButton?: string;
+}
+
+const {
+ type = 'text',
+ placeholder,
+ value,
+ flat,
+ class: className,
+ inputClass,
+ id,
+ prepend,
+ append,
+ appendButton,
+} = Astro.props;
+
+const appendButtons = (appendButton ?? '')
+ .split(',')
+ .filter(Boolean)
+ .map((button) => {
+ const [icon, description] = button.split(':');
+ return { icon, description };
+ });
+---
+
+
diff --git a/shared/includes/layout/navbar-logo.html b/shared/astro/components/NavbarLogo.astro
similarity index 57%
rename from shared/includes/layout/navbar-logo.html
rename to shared/astro/components/NavbarLogo.astro
index a62746f37..0cb464a42 100644
--- a/shared/includes/layout/navbar-logo.html
+++ b/shared/astro/components/NavbarLogo.astro
@@ -1,33 +1,58 @@
-
-{%- assign prefix = include.prefix | default: 'navbar' -%}
-{%- assign breakpoint = include.breakpoint | default: 'lg' -%}
-{%- capture class-attr %} class="{{ prefix }}-brand {{ prefix }}-brand-autodark{% if include.class %} {{ include.class }}{% endif %}"{%- endcapture -%}
-{%- if include.header -%}
-
-{%- else -%}
-
-{%- endif -%}
-
\ No newline at end of file
+---
+// Port of layout/navbar-logo.html.
+// TODO: unported Liquid params: prefix (the "sidebar-brand" variant, used only
+// in layouts with a sidebar), breakpoint (assigned in Liquid but unused in the
+// markup), href ("/{href}" appended to page|relative — no ported page passes
+// it).
+import { site } from '@shared/lib/site';
+
+interface Props {
+ href?: string;
+ class?: string;
+ /** wraps the logo in (header=true param) */
+ header?: boolean;
+ smallLogo?: boolean;
+ hideLogo?: boolean;
+ showTitle?: boolean;
+}
+
+const {
+ href = '.',
+ class: className,
+ header = false,
+ smallLogo = false,
+ hideLogo = false,
+ showTitle = false,
+} = Astro.props;
+
+const brandClasses = ['navbar-brand navbar-brand-autodark', className].filter(Boolean).join(' ');
+const logoClass = `navbar-brand-image${showTitle ? ' me-3' : ''}`;
+
+const logoMark =
+ ' ';
+
+const logoText =
+ ' ';
+
+const logoSvg = smallLogo
+ ? `${logoMark} `
+ : `${logoMark}${logoText} `;
+---
+
+{
+ header ? (
+
+
+
+ ) : (
+
+ {!hideLogo && }{showTitle && 'Dashboard'}
+
+ )
+}
diff --git a/shared/astro/components/PageModals.astro b/shared/astro/components/PageModals.astro
new file mode 100644
index 000000000..b01c5cdfe
--- /dev/null
+++ b/shared/astro/components/PageModals.astro
@@ -0,0 +1,18 @@
+---
+// Separate component so drainPageModals() executes only at this point of the
+// render stream (after the page content render has STARTED — registrations are
+// synchronous, modal content may be a promise).
+import { drainPageModals } from '@shared/lib/page-modals';
+
+const modals = await Promise.all(drainPageModals());
+---
+
+{
+ modals.length > 0 && (
+
+ '} />
+
+ '} />
+
+ )
+}
diff --git a/shared/astro/components/PageScripts.astro b/shared/astro/components/PageScripts.astro
new file mode 100644
index 000000000..d0d7efbd6
--- /dev/null
+++ b/shared/astro/components/PageScripts.astro
@@ -0,0 +1,9 @@
+---
+// Separate component so drainPageScripts() executes only at this point of the
+// render stream (after the page content has been rendered).
+import { drainPageScripts } from '@shared/lib/page-scripts';
+
+const scripts = drainPageScripts();
+---
+
+
diff --git a/shared/astro/components/SignInCard.astro b/shared/astro/components/SignInCard.astro
new file mode 100644
index 000000000..a873250e2
--- /dev/null
+++ b/shared/astro/components/SignInCard.astro
@@ -0,0 +1,30 @@
+---
+import Button from './Button.astro';
+import HrText from './HrText.astro';
+import SignInForm from './SignInForm.astro';
+---
+
+
+
+
Login to your account
+
+
+
+
+
+
+
+
+
+
+ Don't have account yet?
Sign up
+
diff --git a/shared/includes/forms/sign-in.html b/shared/astro/components/SignInForm.astro
similarity index 56%
rename from shared/includes/forms/sign-in.html
rename to shared/astro/components/SignInForm.astro
index c528d4758..18f3c891b 100644
--- a/shared/includes/forms/sign-in.html
+++ b/shared/astro/components/SignInForm.astro
@@ -1,20 +1,24 @@
-
+---
+import InputGroup from './InputGroup.astro';
+---
+
+
Email address
-
+
Password
- I forgot password
-
+ I forgot password
+
- {% include "ui/form/input-group.html" type="password" append-button="eye:Show password" flat=true placeholder="Your password" %}
+
-
+
Remember me on this device
@@ -22,4 +26,4 @@
-
\ No newline at end of file
+
diff --git a/shared/astro/components/ThemeSettings.astro b/shared/astro/components/ThemeSettings.astro
new file mode 100644
index 000000000..d26716b22
--- /dev/null
+++ b/shared/astro/components/ThemeSettings.astro
@@ -0,0 +1,179 @@
+---
+// The offcanvas behavior script lives in BaseLayout (page scripts render after
+// the global scripts, mirroring the Eleventy {% scripts %} capture).
+import Icon from './Icon.astro';
+import { site } from '@shared/lib/site';
+
+const defaults = {
+ theme: 'light',
+ 'theme-base': 'gray',
+ 'theme-font': 'sans-serif',
+ 'theme-primary': 'blue',
+ 'theme-radius': '1',
+};
+---
+
+
+
+
+
+
+
+
+
+
+
+
Color mode
+
Choose the color mode for your app.
+ {
+ ['light', 'dark', 'auto'].map((mode) => (
+
+
+
+ ))
+ }
+
+
+
+
Color scheme
+
The perfect color mode for your app.
+
+
+
+
+
+
Font family
+
Choose the font family that fits your app.
+
+
+ {
+ site.themeFonts.map((font) => (
+
+
+
+ ))
+ }
+
+
+
+
+
Theme base
+
Choose the gray shade for your app.
+
+
+ {
+ site.themeBases.map((base) => (
+
+
+
+ ))
+ }
+
+
+
+
+
Corner Radius
+
Choose the border radius factor for your app.
+
+
+ {
+ site.themeRadiuses.map((radius) => (
+
+
+
+ ))
+ }
+
+
+
+
+
+
+
+ Reset changes
+
+
Save
+
+
+
+
+
diff --git a/shared/includes/cards/activity.html b/shared/astro/components/cards/ActivityCard.astro
similarity index 51%
rename from shared/includes/cards/activity.html
rename to shared/astro/components/cards/ActivityCard.astro
index 6720fd767..e0cb1ce58 100644
--- a/shared/includes/cards/activity.html
+++ b/shared/astro/components/cards/ActivityCard.astro
@@ -1,5 +1,10 @@
+---
+// Port cards/activity.html
+import ActivityPart from '../ui/ActivityPart.astro';
+---
+
- {% include "parts/activity.html" %}
+
-
\ No newline at end of file
+
diff --git a/shared/astro/components/cards/AuthLockCard.astro b/shared/astro/components/cards/AuthLockCard.astro
new file mode 100644
index 000000000..42c7a5f03
--- /dev/null
+++ b/shared/astro/components/cards/AuthLockCard.astro
@@ -0,0 +1,30 @@
+---
+// Equivalent of cards/auth-lock.html
+import Button from '../Button.astro';
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+
+const person = people[0];
+---
+
+
+
+
+
Account Locked
+
Please enter your password to unlock your account
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/components/cards/BodyPlaceholder.astro b/shared/astro/components/cards/BodyPlaceholder.astro
new file mode 100644
index 000000000..80102b66c
--- /dev/null
+++ b/shared/astro/components/cards/BodyPlaceholder.astro
@@ -0,0 +1,30 @@
+---
+// Equivalent of cards/body-placeholder.html (ui/svg.html inlined).
+// TODO: the ui/svg.html `border` branch (rect + inline style) is not ported —
+// body-placeholder.html never sets it (the "border" token in the class
+// list is just a CSS class).
+interface Props {
+ width?: number;
+ height?: number;
+ ratio?: string;
+ class?: string;
+}
+
+const { width = 400, height = 200, ratio, class: className } = Astro.props;
+---
+
+
+
+
+
+
+
diff --git a/shared/astro/components/cards/Card.astro b/shared/astro/components/cards/Card.astro
new file mode 100644
index 000000000..e69da2b06
--- /dev/null
+++ b/shared/astro/components/cards/Card.astro
@@ -0,0 +1,252 @@
+---
+// Equivalent of cards/card.html
+// TODO: ui/nav.html is inlined here only in its header variant (tabs/pills
+// inside .card-header) — the standalone nav variants are not ported.
+// TODO: ui/photo.html is inlined only in its ratio branch with the fixed
+// photo ids from the Liquid source (img-top → id=7, img-bottom → id=11;
+// the `id=img-id` argument in card.html is always undefined and the
+// trailing literal id wins).
+// TODO: ui/form/check.html is inlined only in the empty+checked (switch)
+// variants used by footer-elements; other check params are not ported.
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+import Empty from '../ui/Empty.astro';
+import Progress from '../ui/Progress.astro';
+import photos from '@data/photos.json';
+import people from '@data/people.json';
+
+interface Props {
+ link?: boolean;
+ active?: boolean;
+ inactive?: boolean;
+ class?: string;
+ empty?: boolean;
+ imgTop?: boolean;
+ imgBottom?: boolean;
+ statusTop?: string;
+ statusBottom?: string;
+ statusStart?: string;
+ header?: boolean;
+ headerTitle?: string;
+ headerTabs?: boolean;
+ headerPills?: boolean;
+ alert?: string;
+ alertType?: string;
+ title?: string;
+ subtitle?: boolean;
+ body?: string;
+ button?: boolean;
+ footer?: boolean;
+ footerButton?: boolean;
+ footerButtons?: boolean;
+ /** comma-separated list; a ">" prefix pushes the element (and, per the
+ * Liquid loop-variable leak, every following one) to the right */
+ footerElements?: string;
+ progress?: boolean;
+}
+
+const {
+ link = false,
+ active,
+ inactive,
+ class: className,
+ empty,
+ imgTop,
+ imgBottom,
+ statusTop,
+ statusBottom,
+ statusStart,
+ header,
+ headerTitle,
+ headerTabs,
+ headerPills,
+ alert,
+ alertType = 'success',
+ title,
+ subtitle,
+ body,
+ button,
+ footer,
+ footerButton,
+ footerButtons,
+ footerElements,
+ progress,
+} = Astro.props;
+
+const Element = link ? 'a' : 'div';
+
+const classes = [
+ 'card',
+ active && 'card-active',
+ inactive && 'card-inactive',
+ className,
+]
+ .filter(Boolean)
+ .join(' ');
+
+// footer-elements parsing — mirrors the Liquid loop, including the fact that
+// `right` is never reset once set (Liquid assign leaks across iterations).
+let right = false;
+const footerEls = (footerElements ?? '')
+ .split(',')
+ .filter(Boolean)
+ .map((element) => {
+ let el = element;
+ if (el.slice(0, 1) === '>') {
+ right = true;
+ el = element.slice(1);
+ }
+ return { el, right };
+ });
+
+const hasHeader = header || headerTitle || headerTabs || headerPills;
+const hasFooter = footer || footerButton || footerButtons || footerElements;
+
+const imgTopPhoto = (photos as { file: string; title: string }[])[7];
+const imgBottomPhoto = (photos as { file: string; title: string }[])[11];
+const avatarPeople = (people as { full_name?: string; photo?: string }[]).slice(0, 5);
+---
+
+
+ {
+ empty ? (
+
+ ) : (
+
+ {imgTop && (
+
+
+
+
+ )}
+
+ {statusTop ? (
+
+ ) : statusBottom ? (
+
+ ) : statusStart ? (
+
+ ) : null}
+
+ {hasHeader && (
+
+ )}
+
+ {alert &&
}
+
+ {title &&
}
+ {subtitle &&
Card subtitle
}
+
+ {body ? (
+
+ ) : (
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti fugit incidunt, iste, itaque
+ minima neque pariatur perferendis sed suscipit velit vitae voluptatem.
+
+ )}
+
+ {button && (
+
+ )}
+
+
+ {hasFooter && (
+
+
+
+
+ )}
+
+ {imgBottom && (
+
+
+
+
+ )}
+
+ {progress && }
+
+ )
+ }
+
diff --git a/shared/astro/components/cards/CardBackgroundIcon.astro b/shared/astro/components/cards/CardBackgroundIcon.astro
new file mode 100644
index 000000000..3bf4610ad
--- /dev/null
+++ b/shared/astro/components/cards/CardBackgroundIcon.astro
@@ -0,0 +1,19 @@
+---
+// Equivalent of cards/card-background-icon.html
+import Icon from '../Icon.astro';
+---
+
+
+
+
+
Card with background and icon
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto at consectetur culpa ducimus eum fuga fugiat,
+ ipsa iusto, modi nostrum recusandae reiciendis saepe.
+
+
+
diff --git a/shared/astro/components/cards/CardImage.astro b/shared/astro/components/cards/CardImage.astro
new file mode 100644
index 000000000..2fbc9a880
--- /dev/null
+++ b/shared/astro/components/cards/CardImage.astro
@@ -0,0 +1,35 @@
+---
+// Equivalent of cards/card-image.html
+// TODO: ui/photo.html is inlined only in its plain branch (no
+// background/ratio params are used by card-image.html).
+import photos from '@data/photos.json';
+
+interface Props {
+ title?: string;
+ right?: boolean;
+ imgId?: number;
+}
+
+const { title, right, imgId = 1 } = Astro.props;
+
+const photo = (photos as { file: string; title: string }[])[imgId];
+const imgClass = `w-100 h-100 object-cover ${right ? 'card-img-end' : 'card-img-start'}`;
+---
+
+
+
+
+
+
+
+
+
+ {title &&
}
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam deleniti fugit incidunt, iste, itaque minima
+ neque pariatur perferendis sed suscipit velit vitae voluptatem.
+
+
+
+
+
diff --git a/shared/astro/components/cards/CardRibbonText.astro b/shared/astro/components/cards/CardRibbonText.astro
new file mode 100644
index 000000000..01a65b728
--- /dev/null
+++ b/shared/astro/components/cards/CardRibbonText.astro
@@ -0,0 +1,14 @@
+---
+// Equivalent of cards/card-ribbon-text.html
+---
+
+
+
NEW
+
+
Card with text ribbon
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto at consectetur culpa ducimus eum fuga fugiat,
+ ipsa iusto, modi nostrum recusandae reiciendis saepe.
+
+
+
diff --git a/shared/astro/components/cards/CardRibbonTop.astro b/shared/astro/components/cards/CardRibbonTop.astro
new file mode 100644
index 000000000..89ec71c73
--- /dev/null
+++ b/shared/astro/components/cards/CardRibbonTop.astro
@@ -0,0 +1,15 @@
+---
+// Equivalent of cards/card-ribbon-top.html
+import Icon from '../Icon.astro';
+---
+
+
+
+
+
Card with top ribbon
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto at consectetur culpa ducimus eum fuga fugiat,
+ ipsa iusto, modi nostrum recusandae reiciendis saepe.
+
+
+
diff --git a/shared/astro/components/cards/CardTabs.astro b/shared/astro/components/cards/CardTabs.astro
new file mode 100644
index 000000000..38301093a
--- /dev/null
+++ b/shared/astro/components/cards/CardTabs.astro
@@ -0,0 +1,61 @@
+---
+// Equivalent of cards/card-tabs.html
+// The tabs/content blocks are built as HTML strings to mirror the Liquid
+// {% capture %} blocks (they are emitted in a different order for `bottom`).
+interface Props {
+ /** present in the Liquid source (tabs-count) but never used there */
+ count?: number;
+ id?: string;
+ bottom?: boolean;
+ borderless?: boolean;
+}
+
+const { id = 'top', bottom, borderless } = Astro.props;
+
+const tabs = ['Activity', 'Profile', 'Settings'];
+
+const tabsHtml = `
+
+
+${tabs
+ .map(
+ (tab, i) =>
+ ` ${tab} `,
+ )
+ .join('\n')}
+ `;
+
+const tabsContentHtml = `
+
+${tabs
+ .map(
+ (tab, i) => `
+
+
+
${tab}
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Adipisci, alias aliquid distinctio dolorem expedita, fugiat hic magni molestiae molestias odit.
+
+
+
`,
+ )
+ .join('\n')}
+
`;
+---
+
+
+
+ {
+ bottom ? (
+
+
+
+
+ ) : (
+
+
+
+
+ )
+ }
+
diff --git a/shared/astro/components/cards/CarouselCard.astro b/shared/astro/components/cards/CarouselCard.astro
new file mode 100644
index 000000000..f4d4f17f4
--- /dev/null
+++ b/shared/astro/components/cards/CarouselCard.astro
@@ -0,0 +1,104 @@
+---
+// Port of shared/includes/cards/carousel.html + inlined ui/carousel.html.
+// ui/carousel.html is inlined here (not a shared component in this task's
+// scope). Photos are filtered to horizontal=true, then sliced by offset/limit.
+import photos from '@data/photos.json';
+
+interface Props {
+ id?: string;
+ title?: string;
+ indicators?: boolean;
+ indicatorsThumb?: boolean;
+ indicatorsThumbRatio?: boolean;
+ indicatorsDot?: boolean;
+ indicatorsVertical?: boolean;
+ controls?: boolean;
+ captions?: boolean;
+ offset?: number;
+ limit?: number;
+ fade?: boolean;
+}
+
+const {
+ id: idProp,
+ title = 'Carousel',
+ indicators,
+ indicatorsThumb,
+ indicatorsThumbRatio,
+ indicatorsDot,
+ indicatorsVertical,
+ controls,
+ captions,
+ offset = 0,
+ limit = 5,
+ fade,
+} = Astro.props;
+
+const carouselId = idProp ?? 'carousel';
+const filteredPhotos = (photos as { file: string; horizontal?: boolean }[]).filter((p) => p.horizontal);
+const slides = filteredPhotos.slice(offset, offset + limit);
+---
+
+
+
+
+
+ {
+ indicators && (
+
+ {slides.map((photo, i) => (
+
+ ))}
+
+ )
+ }
+
+
+ {
+ slides.map((photo, i) => (
+
+
+
+ {captions && (
+
+
+
+
Slide label
+
Nulla vitae elit libero, a pharetra augue mollis interdum.
+
+
+ )}
+
+ ))
+ }
+
+
+ {
+ controls && (
+
+
+
+ Previous
+
+
+
+ Next
+
+
+ )
+ }
+
+
+
diff --git a/shared/astro/components/cards/ChurnRisk.astro b/shared/astro/components/cards/ChurnRisk.astro
new file mode 100644
index 000000000..7ae88396f
--- /dev/null
+++ b/shared/astro/components/cards/ChurnRisk.astro
@@ -0,0 +1,37 @@
+---
+// Port of cards/churn-risk.html
+import Icon from '../Icon.astro';
+import Badge from '../ui/Badge.astro';
+import crmDashboard from '@data/crm-dashboard.json';
+
+const churn = crmDashboard.churn_risk;
+---
+
+
+
+
+
+ {
+ churn.items.map((item) => (
+
+
+
+
{item.company}
+
Last contact: {item.last_contact}
+
+
{item.level}
+
{item.amount}
+
+
+ ))
+ }
+
+
diff --git a/shared/astro/components/cards/Code.astro b/shared/astro/components/cards/Code.astro
new file mode 100644
index 000000000..886d07222
--- /dev/null
+++ b/shared/astro/components/cards/Code.astro
@@ -0,0 +1,21 @@
+---
+// Port of shared/includes/cards/code.html.
+// The `{% highlight css %}` block emits the raw CSS text (no highlight markup in
+// the dev build), rendered here as a text node inside .card-code.
+const code = `
+.card-footer {
+ background: transparent;
+
+ &:last-child {
+ border-radius: 0 0 1 2;
+ }
+}
+`;
+---
+
+
diff --git a/shared/includes/cards/configuration.html b/shared/astro/components/cards/Configuration.astro
similarity index 72%
rename from shared/includes/cards/configuration.html
rename to shared/astro/components/cards/Configuration.astro
index 046d87f44..d637b7542 100644
--- a/shared/includes/cards/configuration.html
+++ b/shared/astro/components/cards/Configuration.astro
@@ -1,3 +1,9 @@
+---
+// Port of shared/includes/cards/configuration.html.
+import Icon from '../Icon.astro';
+import Flag from '../ui/Flag.astro';
+---
+
@@ -18,7 +24,7 @@
tabler
Location:
-
{% include "ui/flag.html" flag="pl" size="xxs" %} Poland
+
Poland
IP Address:
46.113.11.3
diff --git a/shared/astro/components/cards/CreditCard.astro b/shared/astro/components/cards/CreditCard.astro
new file mode 100644
index 000000000..ddafa1d75
--- /dev/null
+++ b/shared/astro/components/cards/CreditCard.astro
@@ -0,0 +1,61 @@
+---
+// Equivalent of cards/credit-card.html
+// TODO: ui/form/input-mask.html is inlined only with the params used here
+// (mask + visible; placeholder falls back to the mask value).
+import Button from '../Button.astro';
+
+const months = Array.from({ length: 12 }, (_, i) => i + 1);
+const years = Array.from({ length: 11 }, (_, i) => 2020 + i);
+---
+
+
+
+
+
+
+
+
+
+
+
Expiration date
+
+
+
+ {months.map((month) => {month} )}
+
+
+
+
+ {years.map((year) => {year} )}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/components/cards/CrmStats.astro b/shared/astro/components/cards/CrmStats.astro
new file mode 100644
index 000000000..f5954a9b6
--- /dev/null
+++ b/shared/astro/components/cards/CrmStats.astro
@@ -0,0 +1,63 @@
+---
+// Port of cards/crm-stats.html (only the branches used by dashboard-crm).
+// TODO: unported ui/crm-stats.html branches (unused on dashboard-crm):
+// person-id (avatar), chart-data + chart-position/chart-label/chart-label-icon
+// (sparkline), small-icon, description-value/description-value-color, trending,
+// button, chart-type/chart-color.
+import Icon from '../Icon.astro';
+import Trending from '../ui/Trending.astro';
+
+interface Props {
+ color?: string;
+ icon?: string;
+ /** lt — light avatar background (bg-{color}-lt) instead of bg-{color} text-white */
+ lt?: boolean;
+ title?: string;
+ description?: string;
+ /** change-value — passed straight to ui/trending.html (keeps its +/- sign) */
+ changeValue?: string;
+ /** change-value-unit — trending unit; defaults to '%' in Trending when unset */
+ changeValueUnit?: string;
+ class?: string;
+}
+
+const {
+ color,
+ icon,
+ lt,
+ title = '1700',
+ description = 'Users',
+ changeValue,
+ changeValueUnit,
+ class: className,
+} = Astro.props;
+
+const avatarClass = `${color ? `bg-${color}${lt ? '-lt' : ' text-white'}` : ''} avatar avatar-square`;
+---
+
+
+
+
+ {
+ icon && (
+
+
+
+ )
+ }
+
+
+
+
+
+
+
+
+
diff --git a/shared/includes/cards/delete-confirm.html b/shared/astro/components/cards/DeleteConfirm.astro
similarity index 66%
rename from shared/includes/cards/delete-confirm.html
rename to shared/astro/components/cards/DeleteConfirm.astro
index dcf48ab32..841e81de5 100644
--- a/shared/includes/cards/delete-confirm.html
+++ b/shared/astro/components/cards/DeleteConfirm.astro
@@ -1,12 +1,16 @@
+---
+// Port of cards/delete-confirm.html
+import Button from '../Button.astro';
+---
+
Are you sure to delete this card?
If you delete this card, you will not be able to recover it.
- {% include "ui/button.html" text="Yes, delete it" color="danger" %}
- {% include "ui/button.html" text="Cancel" %}
+
+
-
diff --git a/shared/astro/components/cards/DevelopmentActivity.astro b/shared/astro/components/cards/DevelopmentActivity.astro
new file mode 100644
index 000000000..62a9a9dd0
--- /dev/null
+++ b/shared/astro/components/cards/DevelopmentActivity.astro
@@ -0,0 +1,69 @@
+---
+// Port cards/development-activity.html
+import Chart from '../Chart.astro';
+import ChartSparkline from '../ui/ChartSparkline.astro';
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+import commits from '@data/commits.json';
+
+interface Commit {
+ hash: string;
+ short_hash: string;
+ author: string;
+ date: string;
+ description: string;
+}
+
+// Equivalent of the Liquid date_to_string filter ("Thu Nov 28 08:48:33 2025 +0100" → "28 Nov 2025")
+const dateToString = (date: string) => {
+ const m = date.match(/^\w+ (\w+) (\d+) [\d:]+ (\d+)/);
+ return m ? `${m[2]} ${m[1]} ${m[3]}` : date;
+};
+
+const rows = (commits as Commit[]).slice(0, 5);
+---
+
+
+
+
+
+
+
+
+
Today's Earning: $4,262.40
+
+5% more than yesterday
+
+
+
+
+
+
+
+
+
+
+ User
+ Commit
+ Date
+
+
+
+ {rows.map((commit, index) => (
+
+
+
+
+
+
+ {commit.description}
+
+
+ {dateToString(commit.date)}
+
+ ))}
+
+
+
+
diff --git a/shared/astro/components/cards/EmptyTeam.astro b/shared/astro/components/cards/EmptyTeam.astro
new file mode 100644
index 000000000..180394234
--- /dev/null
+++ b/shared/astro/components/cards/EmptyTeam.astro
@@ -0,0 +1,25 @@
+---
+// Equivalent of cards/empty-team.html
+// ui/avatar-list.html is inlined (stacked, no explicit size — the `avatar-1`
+// class in the Eleventy output is the include['size'] bug and is skipped).
+import Avatar from '../ui/Avatar.astro';
+import Button from '../Button.astro';
+import people from '@data/people.json';
+
+const avatarPeople = (people as { full_name?: string; photo?: string }[]).slice(0, 5);
+---
+
+
+
+
+
+ {avatarPeople.map((person) =>
)}
+
+
+
No Team Members
+
Invite your team to collaborate on this project.
+
+
+
+
+
diff --git a/shared/astro/components/cards/ForgotPasswordCard.astro b/shared/astro/components/cards/ForgotPasswordCard.astro
new file mode 100644
index 000000000..1a53fd14f
--- /dev/null
+++ b/shared/astro/components/cards/ForgotPasswordCard.astro
@@ -0,0 +1,25 @@
+---
+// Equivalent of cards/forgot-password.html
+import Button from '../Button.astro';
+---
+
+
+
+
Forgot password
+
+
+ Enter your email address and your password will be reset and emailed to you.
+
+
+
+ Email address
+
+
+
+
+
+
+ Forget it,
send me back to the sign in screen.
+
diff --git a/shared/astro/components/cards/GalleryPhoto.astro b/shared/astro/components/cards/GalleryPhoto.astro
new file mode 100644
index 000000000..2c3ec5132
--- /dev/null
+++ b/shared/astro/components/cards/GalleryPhoto.astro
@@ -0,0 +1,78 @@
+---
+// Equivalent of cards/gallery-photo.html.
+// The Liquid include reads `photo` and `forloop.index` from the parent loop scope —
+// in Astro they are passed explicitly as the `photo` and `index` props.
+import Avatar from '../ui/Avatar.astro';
+import Icon from '../Icon.astro';
+
+interface Photo {
+ file: string;
+ [key: string]: unknown;
+}
+
+interface Person {
+ full_name?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ photo: Photo;
+ person: Person;
+ /** 1-based loop index (forloop.index in Liquid) — seeds the deterministic pseudo-random values */
+ index: number;
+ hideLikes?: boolean;
+}
+
+const { photo, person, index, hideLikes } = Astro.props;
+
+// Equivalent of the random_number filter from shared/e11ty/filters.mjs (deterministic).
+function randomNumber(x: number, min = 0, max = 100): number {
+ let value =
+ ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) +
+ min;
+
+ value = value > max ? max : value;
+ value = value < min ? min : value;
+
+ return Math.floor(value);
+}
+
+// Equivalent of `forloop.index | random_date_ago: 10 | timeago` — a date N days ago
+// (N = randomNumber(index, 0, 10)) formatted by timeago gives "now" / "N day(s) ago".
+function timeagoLabel(index: number): string {
+ const days = randomNumber(index, 0, 10);
+ if (days === 0) return 'now';
+ return `${days} day${days > 1 ? 's' : ''} ago`;
+}
+
+// Liquid: {% if forloop.index > 2 and forloop.index < 9 or forloop.index == 10 %}
+const heartClass = (index > 2 && index < 9) || index === 10 ? 'icon-filled text-red' : undefined;
+---
+
+
+
+
+
+
+
+
{person.full_name}
+
{timeagoLabel(index)}
+
+ {
+ !hideLikes && (
+
+ )
+ }
+
+
+
diff --git a/shared/includes/cards/happy-birthday.html b/shared/astro/components/cards/HappyBirthday.astro
similarity index 79%
rename from shared/includes/cards/happy-birthday.html
rename to shared/astro/components/cards/HappyBirthday.astro
index 7ff27b975..40f42a64b 100644
--- a/shared/includes/cards/happy-birthday.html
+++ b/shared/astro/components/cards/HappyBirthday.astro
@@ -1,3 +1,8 @@
+---
+// Port of cards/happy-birthday.html
+import Button from '../Button.astro';
+---
+
🍾 🎉
@@ -5,8 +10,7 @@
We truly hope your day is brimming with joy, laughter, and countless moments that bring a smile to your face!
To celebrate your special day, here's a discount code just for you: NWYR20 . Enjoy 20% off your next purchase!
- {% include "ui/button.html" text="Grab my special deal" icon="gift" color="primary" %}
+
-
diff --git a/shared/astro/components/cards/Icons.astro b/shared/astro/components/cards/Icons.astro
new file mode 100644
index 000000000..69a5e75ea
--- /dev/null
+++ b/shared/astro/components/cards/Icons.astro
@@ -0,0 +1,55 @@
+---
+// Port of cards/icons.html.
+import Icon from '../Icon.astro';
+import icons from '@data/icons.json';
+
+interface Props {
+ title?: string;
+ type?: 'outline' | 'filled';
+}
+
+const { title, type = 'outline' } = Astro.props;
+
+// Liquid: limit is Infinity, but 20 when environment == 'development'.
+// The PoC mirrors the development build (see BaseLayout), so limit = 20.
+// NOTE: the limit applies to the ITERATION, before the svg[type] filter —
+// the "filled" card therefore shows only the filled icons among the first 20.
+const limit = 20;
+
+const entries = Object.entries(icons as Record
}>).slice(
+ 0,
+ limit,
+);
+---
+
+
+
+
+
+
+ {
+ entries.map(
+ ([iconName, icon]) =>
+ icon.svg?.[type] && (
+
+
+
+ ),
+ )
+ }
+ {/* Liquid: {% for icon in (0..20) %} → 21 empty divs (flexbox filler). */}
+ {Array.from({ length: 21 }).map(() =>
)}
+
+
+
+
diff --git a/shared/astro/components/cards/IconsBanner.astro b/shared/astro/components/cards/IconsBanner.astro
new file mode 100644
index 000000000..91a91c820
--- /dev/null
+++ b/shared/astro/components/cards/IconsBanner.astro
@@ -0,0 +1,37 @@
+---
+// Port cards/icons-banner.html
+import Icon from '../Icon.astro';
+import { site } from '@shared/lib/site';
+
+interface Props {
+ class?: string;
+}
+
+const { class: className } = Astro.props;
+---
+
+
+
+
+
+
+
Tabler Icons
+
+ All icons come from the Tabler Icons set and are MIT-licensed. Visit
+
Tabler Icons Website ,
+ download any of the {site.iconsCount} icons in SVG, PNG or React and use them in your favourite design tools.
+
+
+
+
+
+
diff --git a/shared/includes/cards/invoice.html b/shared/astro/components/cards/InvoiceCard.astro
similarity index 70%
rename from shared/includes/cards/invoice.html
rename to shared/astro/components/cards/InvoiceCard.astro
index c4744a0d4..0587b3b08 100644
--- a/shared/includes/cards/invoice.html
+++ b/shared/astro/components/cards/InvoiceCard.astro
@@ -1,21 +1,25 @@
+---
+// Equivalent of cards/invoice.html (static markup, no parameters)
+---
+
Company
- Street Address
- State, City
- Region, Postal Code
+ Street Address
+ State, City
+ Region, Postal Code
ltd@example.com
Client
- Street Address
- State, City
- Region, Postal Code
+ Street Address
+ State, City
+ Region, Postal Code
ctr@example.com
@@ -27,13 +31,13 @@
-
-
- Product
- Qnt
- Unit
- Amount
-
+
+
+ Product
+ Qnt
+ Unit
+ Amount
+
1
@@ -41,9 +45,7 @@
Logo Creation
Logo and business cards design
-
- 1
-
+ 1
$1.800,00
$1.800,00
@@ -53,9 +55,7 @@
Online Store Design & Development
Design/Development for all popular modern browsers
-
- 1
-
+ 1
$20.000,00
$20.000,00
@@ -65,9 +65,7 @@
App Design
Promotional mobile application
-
- 1
-
+ 1
$3.200,00
$3.200,00
@@ -89,7 +87,8 @@
-
Thank you very much for doing business with us. We look forward to working with
- you again!
+
+ Thank you very much for doing business with us. We look forward to working with you again!
+
diff --git a/shared/astro/components/cards/Invoices.astro b/shared/astro/components/cards/Invoices.astro
new file mode 100644
index 000000000..1b4dd5a33
--- /dev/null
+++ b/shared/astro/components/cards/Invoices.astro
@@ -0,0 +1,91 @@
+---
+// Port cards/invoices.html
+import Icon from '../Icon.astro';
+import Flag from '../ui/Flag.astro';
+import DropdownMenu from '../ui/DropdownMenu.astro';
+import Pagination from '../ui/Pagination.astro';
+import invoices from '@data/invoices.json';
+---
+
+
diff --git a/shared/astro/components/cards/MapVectorCard.astro b/shared/astro/components/cards/MapVectorCard.astro
new file mode 100644
index 000000000..5797cb8f5
--- /dev/null
+++ b/shared/astro/components/cards/MapVectorCard.astro
@@ -0,0 +1,18 @@
+---
+// Port cards/map-vector.html
+import MapVector from '../ui/MapVector.astro';
+
+interface Props {
+ title?: string;
+ map?: string;
+}
+
+const { title, map = 'world' } = Astro.props;
+---
+
+
+
+ {title &&
{title} }
+
+
+
diff --git a/shared/astro/components/cards/MostVisitedPages.astro b/shared/astro/components/cards/MostVisitedPages.astro
new file mode 100644
index 000000000..104100e53
--- /dev/null
+++ b/shared/astro/components/cards/MostVisitedPages.astro
@@ -0,0 +1,44 @@
+---
+// Port cards/most-visited-pages.html
+import Icon from '../Icon.astro';
+import ChartSparkline from '../ui/ChartSparkline.astro';
+import urls from '@data/urls.json';
+
+// equivalent of the format_number filter from shared/e11ty/filters.mjs
+const formatNumber = (value: number) => value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+---
+
+
+
+
+
+
+
+
+ Page name
+ Visitors
+ Unique
+ Bounce rate
+
+
+
+ {urls.slice(0, 6).map((url, index) => (
+
+
+ {url.uri}
+
+
+ {formatNumber(url.visitors)}
+ {formatNumber(url.unique)}
+ {url.bounce}
+
+
+
+
+ ))}
+
+
+
+
diff --git a/shared/astro/components/cards/PricingCard.astro b/shared/astro/components/cards/PricingCard.astro
new file mode 100644
index 000000000..c5a140ad1
--- /dev/null
+++ b/shared/astro/components/cards/PricingCard.astro
@@ -0,0 +1,59 @@
+---
+// Port of shared/includes/cards/pricing-card.html.
+// The feature names are the fixed list from the Liquid source; the
+// `features` string is split per-character into a 1/0 availability mask.
+// ui/ribbon.html is inlined here in its bookmark+top+color variant (the only
+// one used by this card); its star icon renders as the outline `star`
+// (ui/icon.html ignores the `use-svg`/`filled` args).
+import Icon from '../Icon.astro';
+
+interface Props {
+ price?: string;
+ users?: string | number;
+ category?: string;
+ features?: string;
+ /** featured-color — ribbon + button color (e.g. "green") */
+ featuredColor?: string;
+}
+
+const { price = '79', users = 10, category = 'Enterprise', features = '1000', featuredColor } = Astro.props;
+
+const featureNames = ['Sharing Tools', 'Design Tools', 'Private Messages', 'Twitter API'];
+const availableFeatures = features.split('');
+---
+
+
+ {
+ featuredColor && (
+
+
+
+ )
+ }
+
+
+
{category}
+
+
${price}
+
+
+ {users} Users
+ {
+ featureNames.map((feature, i) => (
+
+ {availableFeatures[i] === '1' ? (
+
+ ) : (
+
+ )}
+ {feature}
+
+ ))
+ }
+
+
+
+
+
diff --git a/shared/astro/components/cards/PricingCardEnterprise.astro b/shared/astro/components/cards/PricingCardEnterprise.astro
new file mode 100644
index 000000000..e55f0750a
--- /dev/null
+++ b/shared/astro/components/cards/PricingCardEnterprise.astro
@@ -0,0 +1,20 @@
+---
+// Port of shared/includes/cards/pricing-card-enterprise.html.
+import Button from '../Button.astro';
+---
+
+
+
+
+
+
Enterprise-ready. Reach out for a custom quote.
+
+ Tabler is designed to work great for large enterprises. Take a look at our feature comparison.
+
+
+
+
+
+
+
+
diff --git a/shared/includes/cards/pricing-plan.html b/shared/astro/components/cards/PricingPlan.astro
similarity index 71%
rename from shared/includes/cards/pricing-plan.html
rename to shared/astro/components/cards/PricingPlan.astro
index f467d01e3..e87358e1d 100644
--- a/shared/includes/cards/pricing-plan.html
+++ b/shared/astro/components/cards/PricingPlan.astro
@@ -1,3 +1,9 @@
+---
+// Port of cards/pricing-plan.html
+import Icon from '../Icon.astro';
+import Button from '../Button.astro';
+---
+
Featured
@@ -12,26 +18,25 @@
- {% include "ui/icon.html" icon="check" color="success" %}
+
Unlimited Target Audience
- {% include "ui/icon.html" icon="check" color="success" %}
+
1 User Account
- {% include "ui/icon.html" icon="check" color="success" %}
+
100+ Video Tuts
- {% include "ui/icon.html" icon="x" color="secondary" %}
+
Public Displays
This plan is perfect for small businesses and startups. It includes all the features you need to get started.
- {% include "ui/button.html" text="Purchase Now" color="pink" block %}
+
-
diff --git a/shared/astro/components/cards/ProfileContact.astro b/shared/astro/components/cards/ProfileContact.astro
new file mode 100644
index 000000000..79582a330
--- /dev/null
+++ b/shared/astro/components/cards/ProfileContact.astro
@@ -0,0 +1,40 @@
+---
+// Port of cards/profile-contact.html
+// TODO: Liquid default `person = include.person | default: people[1]` — the
+// no-person fallback branch is unused on card-gradients (person is always
+// passed), so `person` is required here.
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+
+interface Person {
+ full_name?: string;
+ job_title?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ person: Person;
+ color?: string;
+}
+
+const { person, color = 'yellow' } = Astro.props;
+---
+
+
+
+
+
+
{person.full_name}
+
{person.job_title}
+
+
+
+
diff --git a/shared/astro/components/cards/ProjectKanban.astro b/shared/astro/components/cards/ProjectKanban.astro
new file mode 100644
index 000000000..230f50e15
--- /dev/null
+++ b/shared/astro/components/cards/ProjectKanban.astro
@@ -0,0 +1,51 @@
+---
+// Port of shared/includes/cards/project-kanban.html.
+// NOTE: the widgets page passes a `value=` argument, but the Liquid source only
+// reads `percentage` (default 20) for the progress bar — `value` is never used.
+// It is accepted here for signature parity but intentionally ignored.
+import Progress from '../ui/Progress.astro';
+import AvatarList from '../ui/AvatarList.astro';
+import Icon from '../Icon.astro';
+
+interface Props {
+ title?: string;
+ badge?: string;
+ offset?: number;
+ limit?: number;
+ percentage?: number | string;
+ percentageColor?: string;
+ due?: string;
+ /** unused — see note above */
+ value?: number | string;
+}
+
+const {
+ title = 'Task Title',
+ badge,
+ offset = 40,
+ limit = 7,
+ percentage = 20,
+ percentageColor = 'green',
+ due = '2 days',
+} = Astro.props;
+---
+
+
+
+
+
+ {title}
+ {badge && {badge} }
+
+
+
+
+
+
+
+ 5/10
+
+
Due {due}
+
+
+
diff --git a/shared/astro/components/cards/ProjectProgress.astro b/shared/astro/components/cards/ProjectProgress.astro
new file mode 100644
index 000000000..14c188298
--- /dev/null
+++ b/shared/astro/components/cards/ProjectProgress.astro
@@ -0,0 +1,55 @@
+---
+// Port of shared/includes/cards/project-progress.html.
+// NOTE: the `days-ago` param is assigned in the Liquid source but never rendered
+// ("Updated 2 hours ago" is hardcoded) — accepted here but unused.
+import Progress from '../ui/Progress.astro';
+import CardDropdown from '../ui/CardDropdown.astro';
+import projects from '@data/projects.json';
+
+interface Project {
+ title?: string;
+ image?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ projectId?: number;
+ progress?: number;
+ daysAgo?: number;
+}
+
+const { projectId = 0, progress = 25 } = Astro.props;
+const project = (projects as Project[])[projectId];
+---
+
+
+
+
+
+
+
+
+
+
+ Updated 2 hours ago
+
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/components/cards/ProjectSummary.astro b/shared/astro/components/cards/ProjectSummary.astro
new file mode 100644
index 000000000..ac9d84df3
--- /dev/null
+++ b/shared/astro/components/cards/ProjectSummary.astro
@@ -0,0 +1,45 @@
+---
+// Port of shared/includes/cards/project-summary.html.
+import Avatar from '../ui/Avatar.astro';
+import AvatarList from '../ui/AvatarList.astro';
+import Progress from '../ui/Progress.astro';
+
+interface Props {
+ title?: string;
+ date?: string;
+ stageColor?: string;
+ stage?: string;
+ projectColor?: string;
+ percentage?: number | string;
+ percentageColor?: string;
+ avatarOffset?: number;
+ avatarLimit?: number;
+}
+
+const {
+ title = 'New website',
+ date = '28 Aug 2019',
+ stageColor = 'green',
+ stage = 'Waiting',
+ projectColor,
+ percentage,
+ percentageColor,
+ avatarOffset,
+ avatarLimit,
+} = Astro.props;
+---
+
+
+
+
+
{title}
+
Due to: {date}
+
+ {stage}
+
+
+
+
+
diff --git a/shared/astro/components/cards/RecentActivity.astro b/shared/astro/components/cards/RecentActivity.astro
new file mode 100644
index 000000000..56ca098a0
--- /dev/null
+++ b/shared/astro/components/cards/RecentActivity.astro
@@ -0,0 +1,41 @@
+---
+// Port of cards/recent-activity.html
+// NOTE: the Liquid source passes class="icon text-{{ item.icon_color }}" as an
+// include argument to ui/icon.html; Liquid does NOT re-interpolate include-arg
+// strings, so the reference output contains the LITERAL text
+// `icon text-{{ item.icon_color }}` in the icon class. We reproduce it verbatim.
+import Icon from '../Icon.astro';
+import crmDashboard from '@data/crm-dashboard.json';
+
+const activity = crmDashboard.recent_activity;
+---
+
+
+
+
+
+ {
+ activity.items.map((item) => (
+
+
+
+
+
+
+
+
+
{item.text}
+
{item.time}
+
+
+
+ ))
+ }
+
+
+
diff --git a/shared/includes/cards/sign-up.html b/shared/astro/components/cards/SignUpCard.astro
similarity index 57%
rename from shared/includes/cards/sign-up.html
rename to shared/astro/components/cards/SignUpCard.astro
index 8473155e5..c2bf45f09 100644
--- a/shared/includes/cards/sign-up.html
+++ b/shared/astro/components/cards/SignUpCard.astro
@@ -1,23 +1,28 @@
-
+---
+// Equivalent of cards/sign-up.html
+import InputGroup from '../InputGroup.astro';
+---
+
+
Create new account
Name
-
+
Email address
-
+
Password
- {% include "ui/form/input-group.html" type="password" append-button="eye:Show password" flat=true placeholder="Password" %}
+
@@ -28,5 +33,5 @@
- Already have account?
Sign in
+ Already have account?
Sign in
diff --git a/shared/astro/components/cards/SmallStats.astro b/shared/astro/components/cards/SmallStats.astro
new file mode 100644
index 000000000..439cb2026
--- /dev/null
+++ b/shared/astro/components/cards/SmallStats.astro
@@ -0,0 +1,112 @@
+---
+// Port of cards/small-stats.html (full parity).
+// Covers: icon / person-id / chart-data (left/right) / small-icon /
+// description-value / trending / button branches.
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+import ChartSparkline from '../ui/ChartSparkline.astro';
+import Trending from '../ui/Trending.astro';
+import Button from '../Button.astro';
+
+interface Props {
+ icon?: string;
+ color?: string;
+ lt?: boolean;
+ title?: string | number;
+ description?: string;
+ class?: string;
+ id?: string;
+ personId?: number;
+ chartType?: string;
+ chartPosition?: string;
+ chartData?: string | number;
+ chartLabel?: string;
+ chartLabelIcon?: string;
+ smallIcon?: string;
+ descriptionValue?: string;
+ descriptionValueColor?: string;
+ trending?: number;
+ button?: string;
+}
+
+const {
+ icon,
+ color,
+ lt,
+ title,
+ description,
+ class: className,
+ id,
+ personId,
+ chartType = 'line',
+ chartPosition = 'right',
+ chartData,
+ smallIcon,
+ descriptionValue,
+ descriptionValueColor,
+ trending,
+ button,
+} = Astro.props;
+
+const chartColor = color ?? 'primary';
+const avatarClass = `${color ? `bg-${color}${lt ? '-lt' : ' text-white'}` : ''} avatar avatar-square`;
+---
+
+
+
+
+ {
+ icon ? (
+
+
+
+ ) : personId ? (
+
+ ) : chartData && chartPosition === 'left' ? (
+
+
+
+ ) : null
+ }
+
+
+
+ {title ?? 1700}
+ {smallIcon && }
+ {descriptionValue && (
+ {descriptionValue}
+ )}
+
+
+ {description ?? 'Users'}
+
+
+
+ {
+ chartData && chartPosition === 'right' && (
+
+
+
+ )
+ }
+
+ {
+ trending && (
+
+
+
+ )
+ }
+
+ {
+ button && (
+
+
+
+ )
+ }
+
+
+
diff --git a/shared/astro/components/cards/SocialTraffic.astro b/shared/astro/components/cards/SocialTraffic.astro
new file mode 100644
index 000000000..e5b38fbf1
--- /dev/null
+++ b/shared/astro/components/cards/SocialTraffic.astro
@@ -0,0 +1,40 @@
+---
+// Port cards/social-traffic.html
+const services = 'Instagram:3550,Twitter:1798,Facebook:1245,TikTok:986,Pinterest:854,VK:650,Pinterest:420'
+ .split(',')
+ .map((service) => {
+ const [name, visitors] = service.split(':');
+ return { name, visitors: Number(visitors) };
+ });
+
+// equivalent of the format_number filter from shared/e11ty/filters.mjs
+const formatNumber = (value: number) => value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+---
+
+
+
+
+
+
+ Network
+ Visitors
+
+
+
+ {services.map((service) => (
+
+ {service.name}
+ {formatNumber(service.visitors)}
+
+
+
+
+ ))}
+
+
+
diff --git a/shared/includes/cards/sponsor.html b/shared/astro/components/cards/Sponsor.astro
similarity index 99%
rename from shared/includes/cards/sponsor.html
rename to shared/astro/components/cards/Sponsor.astro
index 0a2f4e979..4a96a9158 100644
--- a/shared/includes/cards/sponsor.html
+++ b/shared/astro/components/cards/Sponsor.astro
@@ -1,4 +1,10 @@
-
+---
+// Port cards/sponsor.html
+import Icon from '../Icon.astro';
+import { site } from '@shared/lib/site';
+---
+
+
@@ -69,7 +75,7 @@
Sponsor Tabler and help us make a difference!
- {% include "ui/icon.html" icon="heart" type="filled" color="pink" %}
+
Become a Sponsor
diff --git a/shared/astro/components/cards/StatCard.astro b/shared/astro/components/cards/StatCard.astro
new file mode 100644
index 000000000..64f6f0ba2
--- /dev/null
+++ b/shared/astro/components/cards/StatCard.astro
@@ -0,0 +1,26 @@
+---
+// Port of shared/includes/cards/stat-card.html.
+import Avatar from '../ui/Avatar.astro';
+
+interface Props {
+ title?: string;
+ value?: string;
+ icon?: string;
+}
+
+const { title = 'Title', value = '', icon = 'user' } = Astro.props;
+---
+
+
diff --git a/shared/astro/components/cards/StatGradient.astro b/shared/astro/components/cards/StatGradient.astro
new file mode 100644
index 000000000..a70f0d5c4
--- /dev/null
+++ b/shared/astro/components/cards/StatGradient.astro
@@ -0,0 +1,38 @@
+---
+// Port of cards/stat-gradient.html
+import Avatar from '../ui/Avatar.astro';
+import Progress from '../ui/Progress.astro';
+
+interface Props {
+ color?: string;
+ icon?: string;
+ title?: string;
+ value?: string;
+ progress?: number;
+}
+
+const {
+ color = 'primary',
+ icon = 'trending-up',
+ title = 'Total',
+ value = '0',
+ progress = 0,
+} = Astro.props;
+---
+
+
diff --git a/shared/includes/cards/storage-usage.html b/shared/astro/components/cards/StorageUsage.astro
similarity index 95%
rename from shared/includes/cards/storage-usage.html
rename to shared/astro/components/cards/StorageUsage.astro
index 55caadd14..824ebf76c 100644
--- a/shared/includes/cards/storage-usage.html
+++ b/shared/astro/components/cards/StorageUsage.astro
@@ -1,3 +1,7 @@
+---
+// Port of cards/storage-usage.html (a fully static card)
+---
+
Using Storage 6854.45 MB of 8 GB
@@ -30,4 +34,3 @@
-
diff --git a/shared/astro/components/cards/Subscribe.astro b/shared/astro/components/cards/Subscribe.astro
new file mode 100644
index 000000000..c5f1b7b8a
--- /dev/null
+++ b/shared/astro/components/cards/Subscribe.astro
@@ -0,0 +1,49 @@
+---
+// Port of shared/includes/cards/subscribe.html.
+import Avatar from '../ui/Avatar.astro';
+import CardDropdown from '../ui/CardDropdown.astro';
+import people from '@data/people.json';
+
+interface Person {
+ full_name?: string;
+ company?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ personId?: number;
+}
+
+const { personId = 0 } = Astro.props;
+const person = (people as Person[])[personId];
+---
+
+
+
+
+
+
+
+
+ Working in {person.company}
+
+
+ Online
+
+
+
+
+
+
+
+
+
diff --git a/shared/includes/cards/success-message.html b/shared/astro/components/cards/SuccessMessage.astro
similarity index 57%
rename from shared/includes/cards/success-message.html
rename to shared/astro/components/cards/SuccessMessage.astro
index 863c526b3..63f5504c6 100644
--- a/shared/includes/cards/success-message.html
+++ b/shared/astro/components/cards/SuccessMessage.astro
@@ -1,14 +1,19 @@
+---
+// Port of cards/success-message.html
+import Icon from '../Icon.astro';
+import Button from '../Button.astro';
+---
+
- {% include "ui/icon.html" icon="circle-check" class="icon-lg" color="success" %}
+
Success!
Your changes have been saved successfully.
- {% include "ui/button.html" text="Continue" color="success" %}
+
-
diff --git a/shared/astro/components/cards/TabsCard.astro b/shared/astro/components/cards/TabsCard.astro
new file mode 100644
index 000000000..ff65aff15
--- /dev/null
+++ b/shared/astro/components/cards/TabsCard.astro
@@ -0,0 +1,97 @@
+---
+// Port cards/tabs.html
+import Icon from '../Icon.astro';
+import DropdownMenu from '../ui/DropdownMenu.astro';
+
+interface Props {
+ id: string;
+ icons?: boolean;
+ /** hide-text param; not exercised on tabs.html, ported 1:1 from the Liquid source */
+ hideText?: boolean;
+ reverse?: boolean;
+ justified?: boolean;
+ activity?: boolean;
+ disabled?: boolean;
+ dropdown?: boolean;
+ settings?: boolean;
+ animation?: boolean;
+}
+
+const {
+ id,
+ icons,
+ hideText,
+ reverse = false,
+ justified,
+ activity,
+ disabled,
+ dropdown,
+ settings,
+ animation,
+} = Astro.props;
+
+const iconClass = hideText ? undefined : 'me-2';
+const navClass = `nav nav-tabs card-header-tabs${reverse ? ' flex-row-reverse' : ''}${justified ? ' nav-fill' : ''}`;
+const paneClass = `tab-pane${animation ? ' fade' : ''}`;
+---
+
+
+
+
+
+
+
Home tab
+
Cursus turpis vestibulum, dui in pharetra vulputate id sed non turpis ultricies fringilla at sed facilisis lacus pellentesque purus nibh
+
+
+
Profile tab
+
Fringilla egestas nunc quis tellus diam rhoncus ultricies tristique enim at diam, sem nunc amet, pellentesque id egestas velit sed
+
+ {settings && (
+
+
Settings tab
+
Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus
+
+ )}
+ {activity && (
+
+
Activity tab
+
Donec ac vitae diam amet vel leo egestas consequat rhoncus in luctus amet, facilisi sit mauris accumsan nibh habitant senectus
+
+ )}
+
+
+
diff --git a/shared/astro/components/cards/Tasks.astro b/shared/astro/components/cards/Tasks.astro
new file mode 100644
index 000000000..bb2465971
--- /dev/null
+++ b/shared/astro/components/cards/Tasks.astro
@@ -0,0 +1,89 @@
+---
+// Port cards/tasks.html
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+import tasksList from '@data/tasks-list.json';
+
+// Equivalent of the random_number / random_date filters from shared/e11ty/filters.mjs
+// (deterministic pseudo-random depending on the loop index).
+function randomNumber(x: number, min = 0, max = 100, round = 0): number {
+ let value =
+ ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) + min;
+
+ value = value > max ? max : value;
+ value = value < min ? min : value;
+
+ if (round !== 0) {
+ value = parseFloat(value.toFixed(round));
+ } else {
+ value = Math.floor(value);
+ }
+
+ return value;
+}
+
+function randomDate(x: number): Date {
+ const start = new Date('2024-01-01').getTime() / 1000;
+ const end = new Date('2024-12-30').getTime() / 1000;
+
+ return new Date(randomNumber(x, start, end) * 1000);
+}
+
+// equivalent of the Liquid date: '%B %d, %Y'
+const months = [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December',
+];
+const formatDate = (date: Date) =>
+ `${months[date.getMonth()]} ${String(date.getDate()).padStart(2, '0')}, ${date.getFullYear()}`;
+---
+
+
diff --git a/shared/astro/components/cards/TasksDue.astro b/shared/astro/components/cards/TasksDue.astro
new file mode 100644
index 000000000..09c63b70c
--- /dev/null
+++ b/shared/astro/components/cards/TasksDue.astro
@@ -0,0 +1,43 @@
+---
+// Port of cards/tasks-due.html
+import Icon from '../Icon.astro';
+import crmDashboard from '@data/crm-dashboard.json';
+
+const tasks = crmDashboard.tasks_due;
+---
+
+
+
+
+
+ {
+ tasks.items.map((item) => (
+
+
+
+
+
+
+
+
+ {item.due}
+
+
+
+ ))
+ }
+
+
diff --git a/shared/astro/components/cards/TeamLeaderboard.astro b/shared/astro/components/cards/TeamLeaderboard.astro
new file mode 100644
index 000000000..cc26d46d6
--- /dev/null
+++ b/shared/astro/components/cards/TeamLeaderboard.astro
@@ -0,0 +1,40 @@
+---
+// Port of cards/team-leaderboard.html
+import Avatar from '../ui/Avatar.astro';
+import Progress from '../ui/Progress.astro';
+import crmDashboard from '@data/crm-dashboard.json';
+
+const leaderboard = crmDashboard.leaderboard;
+---
+
+
+
+
+
+ {
+ leaderboard.items.map((item, index) => (
+
+
+
{index + 1}
+
+
+
+
{item.amount}
+
{item.deals} deals - {item.score}%
+
+
+
+ ))
+ }
+
+
diff --git a/shared/astro/components/cards/TopDeals.astro b/shared/astro/components/cards/TopDeals.astro
new file mode 100644
index 000000000..d502e74b8
--- /dev/null
+++ b/shared/astro/components/cards/TopDeals.astro
@@ -0,0 +1,64 @@
+---
+// Port of cards/top-deals.html
+import Icon from '../Icon.astro';
+import Avatar from '../ui/Avatar.astro';
+import Progress from '../ui/Progress.astro';
+import crmDashboard from '@data/crm-dashboard.json';
+
+const deals = crmDashboard.top_deals;
+---
+
+
+
+
+
+
+
+
+ {deals.columns.map((column) => {column} )}
+
+
+
+
+ {
+ deals.items.map((item) => (
+
+
+ {item.company}
+ {item.contact}
+
+ {item.stage}
+ {item.value}
+
+
+
+
{item.probability}%
+
+
+
+
+
+
+
+
+
+ ))
+ }
+
+
+
+
diff --git a/shared/astro/components/cards/UserCard.astro b/shared/astro/components/cards/UserCard.astro
new file mode 100644
index 000000000..e57b98675
--- /dev/null
+++ b/shared/astro/components/cards/UserCard.astro
@@ -0,0 +1,42 @@
+---
+// Port of shared/includes/cards/user-card.html.
+// person = people[person-id] (no -1: the object is passed straight to Avatar).
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+
+interface Person {
+ full_name?: string;
+ job_title?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ personId?: number;
+ right?: boolean;
+}
+
+const { personId = 0, right } = Astro.props;
+const person = (people as Person[])[personId];
+---
+
+
+
+
+ {!right && (
+
+ )}
+
+
{person.full_name}
+
{person.job_title}
+
+ {right && (
+
+ )}
+
+
+
diff --git a/shared/astro/components/cards/UserCardBg.astro b/shared/astro/components/cards/UserCardBg.astro
new file mode 100644
index 000000000..e1f378760
--- /dev/null
+++ b/shared/astro/components/cards/UserCardBg.astro
@@ -0,0 +1,43 @@
+---
+// Port of shared/includes/cards/user-card-bg.html.
+// person = people[person-id]; the cover photo is photos[person-id].file.
+// Base card-cover already carries `card-cover-blurred`; `blurred` adds it a 2nd time
+// (faithful to the Liquid source).
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+import photos from '@data/photos.json';
+
+interface Person {
+ full_name?: string;
+ job_title?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Photo {
+ file?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ personId?: number;
+ blurred?: boolean;
+}
+
+const { personId = 0, blurred } = Astro.props;
+const person = (people as Person[])[personId];
+const photo = (photos as Photo[])[personId];
+---
+
+
+
+
+
{person.full_name}
+
{person.job_title}
+
+
diff --git a/shared/astro/components/cards/UserCardBig.astro b/shared/astro/components/cards/UserCardBig.astro
new file mode 100644
index 000000000..00e421daa
--- /dev/null
+++ b/shared/astro/components/cards/UserCardBig.astro
@@ -0,0 +1,31 @@
+---
+// Port of shared/includes/cards/user-card-big.html.
+// person = people[person-id] (object passed to Avatar; `rounded` is a no-op in avatar.html).
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+
+interface Person {
+ full_name?: string;
+ job_title?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ personId?: number;
+}
+
+const { personId = 0 } = Astro.props;
+const person = (people as Person[])[personId];
+---
+
+
diff --git a/shared/astro/components/cards/UserInfo.astro b/shared/astro/components/cards/UserInfo.astro
new file mode 100644
index 000000000..315fc4f88
--- /dev/null
+++ b/shared/astro/components/cards/UserInfo.astro
@@ -0,0 +1,56 @@
+---
+// Port of shared/includes/cards/user-info.html.
+// person = people[person-id - 1] (Liquid default person-id = 25 → people[24]).
+import Icon from '../Icon.astro';
+import Flag from '../ui/Flag.astro';
+import people from '@data/people.json';
+
+interface Person {
+ university?: string;
+ company?: string;
+ city?: string;
+ country?: string;
+ country_code?: string;
+ birth_date?: string;
+ time_zone?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ title?: string;
+ personId?: number;
+}
+
+const { title = 'Basic info', personId = 25 } = Astro.props;
+const person = (people as Person[])[personId - 1];
+---
+
+
+
+
{title}
+
+
+ Went to: {person.university}
+
+
+
+ Worked at: {person.company}
+
+
+
+ Lives in: {person.city}, {person.country}
+
+
+
+ From: {person.country}
+
+
+
+ Birth date: {person.birth_date}
+
+
+
+ Time zone: {person.time_zone}
+
+
+
diff --git a/shared/astro/components/cards/UsersList.astro b/shared/astro/components/cards/UsersList.astro
new file mode 100644
index 000000000..87a9a146c
--- /dev/null
+++ b/shared/astro/components/cards/UsersList.astro
@@ -0,0 +1,112 @@
+---
+// Equivalent of cards/users-list.html
+import Avatar from '../ui/Avatar.astro';
+import Icon from '../Icon.astro';
+import people from '@data/people.json';
+import commits from '@data/commits.json';
+
+interface Person {
+ full_name?: string;
+ photo?: string;
+ last_name?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ limit?: number;
+ offset?: number;
+ hoverable?: boolean;
+ checkbox?: boolean;
+ /** checked-ids — comma separated 1-based indices, e.g. "2,5,8" */
+ checkedIds?: string;
+ title?: string;
+ class?: string;
+ /**
+ * Inert. The lists.html Contacts card passes `hover=true`, but
+ * users-list.html never reads it — only `hoverable` toggles the star column.
+ * Declared so the call site can mirror the Liquid source faithfully.
+ */
+ hover?: boolean;
+}
+
+const {
+ limit = 8,
+ offset = 0,
+ hoverable = false,
+ checkbox,
+ checkedIds = '',
+ title = 'Last commits',
+ class: className,
+} = Astro.props;
+
+// Equivalent of the random_number filter from shared/e11ty/filters.mjs (deterministic).
+function randomNumber(x: number, min = 0, max = 100): number {
+ let value =
+ ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) +
+ min;
+ value = value > max ? max : value;
+ value = value < min ? min : value;
+ return Math.floor(value);
+}
+
+const colors = 'green,red,yellow,x,x'.split(',');
+const checkedIdList = checkedIds.split(',');
+const commitList = commits as { description: string }[];
+
+const rows = (people as Person[]).slice(offset, offset + limit).map((person, idx) => {
+ const index = idx + 1; // forloop.index (1-based)
+ const color = colors[randomNumber(index + 5, 0, colors.length - 1)];
+ const indexStr = String(index);
+ const checked = checkedIdList.includes(indexStr);
+ const i = index + offset;
+ return {
+ person,
+ color,
+ checked,
+ description: commitList[i]?.description,
+ starColor: checked ? 'text-yellow' : 'text-secondary',
+ };
+});
+---
+
+
+
+
+ {
+ rows.map((row) => (
+
+
+ {checkbox ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+
{row.person.full_name}
+
{row.description}
+
+ {hoverable && (
+
+ )}
+
+
+ ))
+ }
+
+
diff --git a/shared/astro/components/cards/UsersList2.astro b/shared/astro/components/cards/UsersList2.astro
new file mode 100644
index 000000000..0f4081f04
--- /dev/null
+++ b/shared/astro/components/cards/UsersList2.astro
@@ -0,0 +1,73 @@
+---
+// Equivalent of cards/users-list-2.html
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+
+interface Person {
+ full_name?: string;
+ photo?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ limit?: number;
+ offset?: number;
+ title?: string;
+ class?: string;
+}
+
+const { limit = 10, offset = 0, title = 'Top users', class: className } = Astro.props;
+
+// Equivalent of the random_number filter from shared/e11ty/filters.mjs (deterministic).
+function randomNumber(x: number, min = 0, max = 100): number {
+ let value =
+ ((x * x * Math.PI * Math.E * (max + 1) * (Math.sin(x) / Math.cos(x * x))) % (max + 1 - min)) +
+ min;
+ value = value > max ? max : value;
+ value = value < min ? min : value;
+ return Math.floor(value);
+}
+
+// Equivalent of `forloop.index | random_date_ago: 6 | timeago`.
+function timeagoLabel(index: number): string {
+ const days = randomNumber(index, 0, 6);
+ if (days === 0) return 'now';
+ return `${days} day${days > 1 ? 's' : ''} ago`;
+}
+
+const colors = 'green,red,yellow,x,x'.split(',');
+
+const rows = (people as Person[]).slice(offset, offset + limit).map((person, idx) => {
+ const index = idx + 1; // forloop.index (1-based)
+ return {
+ person,
+ status: colors[randomNumber(index + 5, 0, colors.length - 1)],
+ timeago: timeagoLabel(index),
+ };
+});
+---
+
+
+
+
+
+ {
+ rows.map((row) => (
+
+ ))
+ }
+
+
+
diff --git a/shared/astro/components/cards/UsersListHeaders.astro b/shared/astro/components/cards/UsersListHeaders.astro
new file mode 100644
index 000000000..2b59cbdc3
--- /dev/null
+++ b/shared/astro/components/cards/UsersListHeaders.astro
@@ -0,0 +1,70 @@
+---
+// Equivalent of cards/users-list-headers.html
+import Avatar from '../ui/Avatar.astro';
+import people from '@data/people.json';
+import commits from '@data/commits.json';
+
+interface Person {
+ full_name?: string;
+ photo?: string;
+ last_name?: string;
+ [key: string]: unknown;
+}
+
+interface Props {
+ title?: string;
+}
+
+const { title = 'People' } = Astro.props;
+
+const commitList = commits as { description: string }[];
+
+// Equivalent of `people | sort: 'last_name'` (LiquidJS case-sensitive sort).
+const sorted = [...(people as Person[])].sort((a, b) => {
+ const l = a.last_name ?? '';
+ const r = b.last_name ?? '';
+ return l < r ? -1 : l > r ? 1 : 0;
+});
+
+// offset is unset in the include, so `forloop.index | plus: offset` == forloop.index.
+let prevLetter = '';
+const rows = sorted.map((person, idx) => {
+ const index = idx + 1; // forloop.index (1-based)
+ const firstLetter = (person.last_name ?? '').slice(0, 1);
+ let header: string | null = null;
+ if (prevLetter !== firstLetter) {
+ prevLetter = firstLetter;
+ header = firstLetter;
+ }
+ return { person, header, description: commitList[index]?.description };
+});
+---
+
+
+
+
+
+ {
+ rows.map((row) => (
+ <>
+ {row.header && }
+
+ >
+ ))
+ }
+
+
diff --git a/shared/astro/components/cards/Weather.astro b/shared/astro/components/cards/Weather.astro
new file mode 100644
index 000000000..70489717e
--- /dev/null
+++ b/shared/astro/components/cards/Weather.astro
@@ -0,0 +1,43 @@
+---
+// Port of cards/weather.html
+import Icon from '../Icon.astro';
+
+interface Props {
+ city?: string;
+ temperature?: string | number;
+ color?: string;
+ icon?: string;
+ description?: string;
+}
+
+const {
+ city = 'Warsaw',
+ temperature = 20,
+ color = 'blue',
+ icon = 'cloud-rain',
+ description = 'Cloudy morning',
+} = Astro.props;
+---
+
+
diff --git a/shared/includes/cards/welcome.html b/shared/astro/components/cards/Welcome.astro
similarity index 98%
rename from shared/includes/cards/welcome.html
rename to shared/astro/components/cards/Welcome.astro
index d4708fe91..d4d5208f3 100644
--- a/shared/includes/cards/welcome.html
+++ b/shared/astro/components/cards/Welcome.astro
@@ -1,3 +1,9 @@
+---
+// Port cards/welcome.html
+import Trending from '../ui/Trending.astro';
+import Progress from '../ui/Progress.astro';
+---
+
@@ -11,10 +17,10 @@
6,782
- {% include "ui/trending.html" value=7 %}
+
- {% include "ui/progress.html" value=75 color="success" size="sm" %}
+
@@ -22,17 +28,17 @@
78,4%
- {% include "ui/trending.html" value=-1 %}
+
- {% include "ui/progress.html" value=78 color="danger" size="sm" %}
+
-
+
-
+
+
+
+
+ Skip to main content
+
+
+
+
+
+
+
+ {/* equivalent of {% modals %}: modals registered by the page components */}
+
+
+
+
+ {
+ libJsFiles(false).length > 0 && (
+
+
+ {libJsFiles(false).map((src) => (
+
+ ))}
+
+
+ )
+ }
+
+
+
+
+
+
+
+
+ {/* equivalent of {% scripts %}: snippets registered by the page components */}
+
+
+
+
+
+
diff --git a/shared/astro/layouts/DefaultLayout.astro b/shared/astro/layouts/DefaultLayout.astro
new file mode 100644
index 000000000..15865d040
--- /dev/null
+++ b/shared/astro/layouts/DefaultLayout.astro
@@ -0,0 +1,152 @@
+---
+// Port of shared/layouts/default.html.
+// TODO: no-container (-less body) — unused so far.
+// Note: the `blank: true` front matter (blank.html) is inert — it is not
+// referenced by any template or Eleventy config; the empty page header on that
+// page comes purely from `page-header` being unset. No prop for it.
+import BaseLayout from './BaseLayout.astro';
+import Navbar from '@shared/components/navbar/Navbar.astro';
+import Sidebar from '@shared/components/navbar/Sidebar.astro';
+import PageHeader from '@shared/components/layout/PageHeader.astro';
+import Footer from '@shared/components/layout/Footer.astro';
+
+interface Props {
+ title?: string;
+ /** page-libs from the Eleventy front matter — passed down to BaseLayout */
+ pageLibs?: string[];
+ /** page-header — the title in the page header */
+ pageHeader?: string;
+ /** page-header-file — renders a layout/headers/{file} component instead of the title block */
+ pageHeaderFile?: string;
+ /** page-header-pretitle */
+ pretitle?: string;
+ /** page-header-description */
+ description?: string;
+ /** page-header-actions, e.g. "buttons" */
+ actions?: string;
+ /** page-menu from the front matter, e.g. "layout.vertical" — active menu entry */
+ pageMenu?: string;
+ /** layout-sidebar */
+ sidebar?: boolean;
+ /** layout-sidebar-dark */
+ sidebarDark?: boolean;
+ /** layout-hide-topbar */
+ hideTopbar?: boolean;
+ /** page-container-centered — adds my-auto to the .container-xl */
+ containerCentered?: boolean;
+ /** layout-wrapper-full — page-wrapper-full + no .container-xl around the body */
+ wrapperFull?: boolean;
+ /** page-container-class — extra classes appended to the .container-xl */
+ containerClass?: string;
+ /** body-class front matter (e.g. "layout-boxed"/"layout-fluid") → passed to BaseLayout */
+ bodyClass?: string;
+ /** layout-rtl → passed to BaseLayout (dir="rtl" + RTL stylesheets) */
+ rtl?: boolean;
+ /** layout-sidebar-end */
+ sidebarEnd?: boolean;
+ /** layout-navbar-transparent (sidebar variant) */
+ navbarTransparent?: boolean;
+ /** layout-navbar-condensed */
+ navbarCondensed?: boolean;
+ /** layout-navbar-dark */
+ navbarDark?: boolean;
+ /** layout-navbar-overlap */
+ navbarOverlap?: boolean;
+ /** layout-navbar-sticky */
+ navbarSticky?: boolean;
+ /** layout-navbar-hide-brand */
+ navbarHideBrand?: boolean;
+ /** layout-navbar-class */
+ navbarClass?: string;
+}
+
+const {
+ title,
+ pageLibs,
+ pageHeader,
+ pageHeaderFile,
+ pretitle,
+ description,
+ actions,
+ pageMenu,
+ sidebar,
+ sidebarDark,
+ hideTopbar,
+ containerCentered,
+ wrapperFull,
+ containerClass,
+ bodyClass,
+ rtl,
+ sidebarEnd,
+ navbarTransparent,
+ navbarCondensed,
+ navbarDark,
+ navbarOverlap,
+ navbarSticky,
+ navbarHideBrand,
+ navbarClass,
+} = Astro.props;
+---
+
+
+
+ {
+ sidebar && (
+
+
+
+
+
+ )
+ }
+
+ {
+ !hideTopbar && (
+
+
+
+
+
+ )
+ }
+
+
+
+
+
+
+
+
+ {
+ wrapperFull ? (
+
+ ) : (
+
+
+
+ )
+ }
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/layouts/DocsLayout.astro b/shared/astro/layouts/DocsLayout.astro
new file mode 100644
index 000000000..db4d40355
--- /dev/null
+++ b/shared/astro/layouts/DocsLayout.astro
@@ -0,0 +1,305 @@
+---
+// Docs layout — port of shared/layouts/docs/default.html (the @tabler/docs app).
+// Standalone layout with its own ; does NOT use BaseLayout.astro.
+// Development uses the unminified assets; production additionally emits the SEO metadata.
+import { site } from '@shared/lib/site';
+import libs from '@tabler/core/libs.json';
+import docs from '@shared/data/docs.json';
+import Icon from '@shared/components/Icon.astro';
+import DocsNavbar from '@shared/components/docs/DocsNavbar.astro';
+import DocsMenu from '@shared/components/docs/DocsMenu.astro';
+import DocsToc from '@shared/components/docs/DocsToc.astro';
+import type { TocItem } from '@shared/components/docs/DocsToc.astro';
+import DocsPagination from '@shared/components/docs/DocsPagination.astro';
+
+interface Props {
+ /** front matter: the page's h1 heading */
+ title: string;
+ /** front matter: optional SEO title override */
+ seoTitle?: string;
+ /** front matter: lead below the title (p.text-secondary.fs-3.lh-3) */
+ summary?: string;
+ /** front matter: SEO description */
+ description?: string;
+ /** front matter: optional SEO description override */
+ seoDescription?: string;
+ /**
+ * front matter: path to the Bootstrap docs (e.g. "components/alerts/").
+ * Unused by the layout or any docs include — it doesn't appear in the
+ * reference output either; accepted for front matter parity.
+ */
+ bootstrapLink?: string;
+ /** front matter `added-in`: renders the "Added in X" badge next to the h1 */
+ addedIn?: string;
+ /** table of contents (h2/h3 from the markdown content) — see DocsToc.astro */
+ toc?: TocItem[];
+ /**
+ * Page URL in the docs namespace (equivalent of Eleventy's page.url), e.g.
+ * "/ui/components/alert/". By default derived from Astro.url.pathname by
+ * stripping the /docs prefix. Drives the active menu entry, pagination,
+ * the "Edit this page" link, and the relative favicon path.
+ */
+ url?: string;
+ /** front matter `docs-libs`: extra libraries from src/data/libs.json (css+js) */
+ docsLibs?: string[];
+}
+
+const {
+ title,
+ seoTitle,
+ summary,
+ description,
+ seoDescription,
+ addedIn,
+ toc = [],
+ docsLibs = [],
+} = Astro.props;
+const environment = process.env.NODE_ENV || 'production';
+
+// URL in the docs namespace: /docs/ui/components/alert(.html) -> /ui/components/alert/
+const docsUrl =
+ Astro.props.url ??
+ (() => {
+ let p = Astro.url.pathname.replace(/^\/docs(?=\/|$)/, '').replace(/\.html$/, '');
+ if (!p.endsWith('/')) p += '/';
+ return p;
+ })();
+
+const pageSection = docsUrl.startsWith('/ui/')
+ ? 'UI'
+ : docsUrl.startsWith('/icons/')
+ ? 'Icons'
+ : docsUrl.startsWith('/illustrations/')
+ ? 'Illustrations'
+ : docsUrl.startsWith('/emails/')
+ ? 'Emails'
+ : '';
+const metaTitle = seoTitle ?? title;
+const metaDescription = seoDescription ?? description;
+const siteName = pageSection ? `Tabler ${pageSection} Documentation` : 'Tabler Documentation';
+const canonicalUrl = new URL(docsUrl, Astro.site ?? site.docsUrl).href;
+
+// Equivalent of `{{ page | relative }}`: for /ui/components/alert/ -> "../../.."
+const depth = docsUrl.split('/').filter(Boolean).length;
+const relative = depth === 0 ? '.' : '../'.repeat(depth).slice(0, -1);
+
+// Equivalent of page.inputPath: ./content/ui/components/alert.md
+const inputPath = `./content${docsUrl.replace(/\/$/, '')}.md`;
+
+// JS/CSS libraries as in Eleventy: docs-libs + clipboard (always included).
+// In dev file names stay unchanged (e.g. dist/clipboard.min.js keeps .min — the reference has it so).
+type Lib = { npm?: string; js?: string[]; css?: string[] };
+const libEntries = Object.entries(libs as Record
);
+const libUrl = (lib: Lib, file: string) =>
+ file.startsWith('http://') || file.startsWith('https://')
+ ? file
+ : `/dist/libs/${lib.npm}/${file}`;
+const docsLibCss = libEntries
+ .filter(([name]) => docsLibs.includes(name))
+ .flatMap(([, lib]) => (lib.css ?? []).map((file) => libUrl(lib, file)));
+const docsLibJs = libEntries
+ .filter(([name]) => docsLibs.includes(name) || name === 'clipboard')
+ .flatMap(([, lib]) => (lib.js ?? []).map((file) => libUrl(lib, file)));
+
+// Eventually belongs in src/lib/site.ts (out of scope for this task).
+const opencollectiveUrl = 'https://opencollective.com/tabler';
+const xUrl = 'https://x.com/tabler_io';
+const linkedinUrl = 'https://www.linkedin.com/company/tabler-io';
+
+const year = new Date().getFullYear();
+
+type DocsLink = { title: string; url: string; icon: string };
+const docsLinks = docs.links as DocsLink[];
+---
+
+
+
+
+
+
+
+ {metaTitle} | {siteName}
+ {
+ environment === 'production' && (
+
+ {metaDescription && }
+
+
+
+
+
+ {metaDescription && }
+
+
+
+
+
+ {metaDescription && }
+
+ )
+ }
+
+ {
+ environment === 'development' && (
+
+
+
+
+ )
+ }
+
+
+ {site.cssPlugins.map((plugin) => )}
+
+ {docsLibCss.map((href) => )}
+
+ {/* is:inline — see MIGRATION.md (without it Astro adds data-astro-cid-*) */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {title}
+
+
+ {
+ addedIn && (
+
+ {/* equivalent of ui/badge.html color="primary" light=true */}
+ Added in {addedIn}
+
+ )
+ }
+
+
+
{summary}
+
+ {/* markdown content; equivalent of {{ content | headings-id }} — the consuming
+ page must supply headings with ids (MDX does this by default) */}
+
+
+
+
+
+
+
+
+
+
+ © {year} Tabler. All rights reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {docsLibJs.map((src) => )}
+
+
+
+
+
+
+
diff --git a/shared/astro/layouts/DocsMdxLayout.astro b/shared/astro/layouts/DocsMdxLayout.astro
new file mode 100644
index 000000000..c4ddfc88d
--- /dev/null
+++ b/shared/astro/layouts/DocsMdxLayout.astro
@@ -0,0 +1,54 @@
+---
+// Adapter: MDX (layout in frontmatter) → DocsLayout.
+// Astro passes { frontmatter, headings, url } to the MDX layout — we map it
+// onto DocsLayout props, computing the TOC from the headings (equivalent of the `toc` filter).
+import DocsLayout from './DocsLayout.astro';
+
+interface MdxHeading {
+ depth: number;
+ slug: string;
+ text: string;
+}
+
+interface MdxFrontmatter {
+ title?: string;
+ seoTitle?: string;
+ summary?: string;
+ description?: string;
+ seoDescription?: string;
+ bootstrapLink?: string;
+ 'added-in'?: string;
+ 'docs-libs'?: string[];
+}
+
+const { frontmatter, headings = [], url } = Astro.props as {
+ frontmatter: MdxFrontmatter;
+ headings: MdxHeading[];
+ url?: string;
+};
+
+const docsLibs = frontmatter['docs-libs'] ?? [];
+
+const toc = headings
+ .filter((heading) => heading.depth === 2 || heading.depth === 3)
+ .map((heading) => ({
+ level: heading.depth as 2 | 3,
+ text: heading.text,
+ id: heading.slug,
+ }));
+---
+
+
+
+
diff --git a/shared/astro/layouts/ErrorLayout.astro b/shared/astro/layouts/ErrorLayout.astro
new file mode 100644
index 000000000..cda019638
--- /dev/null
+++ b/shared/astro/layouts/ErrorLayout.astro
@@ -0,0 +1,44 @@
+---
+// Port of shared/layouts/error.html (layout: base + body-class
+// "border-top-wide border-primary", a .page-center container and ui/empty.html
+// fed from the errors.json entry keyed by the `page-error` front matter).
+import BaseLayout from './BaseLayout.astro';
+import Empty from '@shared/components/ui/Empty.astro';
+import errors from '@data/errors.json';
+
+interface Props {
+ title?: string;
+ /** page-error front matter — key into errors.json ("404" | "500" | "maintenance" | …) */
+ pageError: string;
+}
+
+const { title, pageError } = Astro.props;
+
+type ErrorEntry = {
+ illustration?: string;
+ title?: string | number;
+ header?: string;
+ description?: string;
+};
+
+// {% assign error = errors[page-error] %}
+const error = (errors as Record)[pageError] ?? {};
+// {% assign header = error.header | default: 'Oops… You just found an error page' %}
+const header = error.header ?? 'Oops… You just found an error page';
+---
+
+
+
+
diff --git a/shared/astro/layouts/MarketingLayout.astro b/shared/astro/layouts/MarketingLayout.astro
new file mode 100644
index 000000000..26294c200
--- /dev/null
+++ b/shared/astro/layouts/MarketingLayout.astro
@@ -0,0 +1,185 @@
+---
+// Port of shared/layouts/marketing.html (layout: base, body-class
+// "body-marketing body-gradient", plugins: marketing).
+// The `plugins: marketing` front matter is already covered by site.cssPlugins
+// (which includes 'marketing'), so no extra handling is needed here.
+// The footer (products/support/tabler columns, payment icons, socials, and the
+// copyright bar) lives inline in this layout, exactly as in the Liquid source.
+import BaseLayout from './BaseLayout.astro';
+import MarketingNavbar from '@shared/components/marketing/MarketingNavbar.astro';
+import Payment from '@shared/components/ui/Payment.astro';
+import Icon from '@shared/components/Icon.astro';
+import { site } from '@shared/lib/site';
+
+interface Props {
+ title?: string;
+ /** page-libs from the Eleventy front matter, e.g. ['typed.js'] */
+ pageLibs?: string[];
+}
+
+const { title, pageLibs } = Astro.props;
+
+// site.base is undefined in the Eleventy build → the product links resolve to
+// an empty href (href="").
+const base = '';
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shared/astro/layouts/PayLayout.astro b/shared/astro/layouts/PayLayout.astro
new file mode 100644
index 000000000..e2fc6cec2
--- /dev/null
+++ b/shared/astro/layouts/PayLayout.astro
@@ -0,0 +1,32 @@
+---
+// Port of shared/layouts/pay.html (layout: base).
+// Minimal navbar (small logo + close button) then a .page with the content.
+import BaseLayout from './BaseLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+
+interface Props {
+ title?: string;
+ /** page-libs from the Eleventy front matter — passed down to BaseLayout */
+ pageLibs?: string[];
+ /** body-class front matter — passed down to BaseLayout */
+ bodyClass?: string;
+}
+
+const { title, pageLibs, bodyClass } = Astro.props;
+---
+
+
+
+
+
+
+
+
diff --git a/shared/astro/layouts/ProseLayout.astro b/shared/astro/layouts/ProseLayout.astro
new file mode 100644
index 000000000..023fd2ab1
--- /dev/null
+++ b/shared/astro/layouts/ProseLayout.astro
@@ -0,0 +1,27 @@
+---
+// Port of shared/layouts/prose.html (layout: default + a
+// card.card-lg > card-body.prose wrapper around the page content).
+import DefaultLayout from './DefaultLayout.astro';
+
+interface Props {
+ title?: string;
+ /** page-header — the title in the page header */
+ pageHeader?: string;
+ /** page-menu — active menu entry, passed through to DefaultLayout */
+ pageMenu?: string;
+}
+
+const { title, pageHeader, pageMenu } = Astro.props;
+---
+
+
+
+
diff --git a/shared/astro/layouts/RedirectLayout.astro b/shared/astro/layouts/RedirectLayout.astro
new file mode 100644
index 000000000..c3792417b
--- /dev/null
+++ b/shared/astro/layouts/RedirectLayout.astro
@@ -0,0 +1,40 @@
+---
+// Port of shared/layouts/redirect.html → shared/includes/redirect.html
+// (a bare meta-refresh document).
+//
+// The include computes:
+// {% if url contains 'http://' or 'https://' %}{{ url }}
+// {% else %}{{ page | relative }}{{ url }}{% endif %}
+// For root-level pages `{{ page | relative }}` resolves to ".".
+
+interface Props {
+ /**
+ * include.url — the raw redirect target. NOTE: shared/layouts/redirect.html
+ * passes `page.redirect.to`, but in Eleventy `page` is the built-in page
+ * object (no front matter), so `page.redirect` is undefined and the include
+ * receives an empty url → the target collapses to the relative root ".".
+ * The reference build (markdown.html) redirects to "." for this reason.
+ */
+ url?: string;
+ /**
+ * `{{ page | relative }}` — the relative path to the site root from this
+ * page. Defaults to "." (root-level pages); nested pages pass e.g. "../../..".
+ */
+ base?: string;
+}
+
+const { url = '', base = '.' } = Astro.props;
+const isAbsolute = url.includes('http://') || url.includes('https://');
+const target = isAbsolute ? url : `${base}${url}`;
+---
+
+
+
+
+ Redirecting…
+
+
+
+ Click here if you are not redirected.
+
+
diff --git a/shared/astro/layouts/SettingsLayout.astro b/shared/astro/layouts/SettingsLayout.astro
new file mode 100644
index 000000000..a7c247242
--- /dev/null
+++ b/shared/astro/layouts/SettingsLayout.astro
@@ -0,0 +1,56 @@
+---
+// Port of shared/layouts/settings.html (layout: default).
+// Wraps the page body in a card with a left settings-nav column; the active
+// nav item is driven by the `active` prop (Liquid used page.fileSlug).
+import DefaultLayout from './DefaultLayout.astro';
+
+interface Props {
+ /** current page slug for the active nav item: 'settings' | 'settings-plan' */
+ active?: string;
+}
+
+const { active } = Astro.props;
+---
+
+
+
+
+
+
diff --git a/shared/astro/layouts/SingleLayout.astro b/shared/astro/layouts/SingleLayout.astro
new file mode 100644
index 000000000..4fffa78fe
--- /dev/null
+++ b/shared/astro/layouts/SingleLayout.astro
@@ -0,0 +1,28 @@
+---
+import BaseLayout from './BaseLayout.astro';
+import NavbarLogo from '@shared/components/NavbarLogo.astro';
+
+interface Props {
+ title?: string;
+ containerSize?: string;
+ hideLogo?: boolean;
+}
+
+const { title, containerSize = 'tight', hideLogo } = Astro.props;
+---
+
+
+
+
+ {
+ !hideLogo && (
+
+
+
+ )
+ }
+
+
+
+
+
diff --git a/shared/astro/lib/chart-script.ts b/shared/astro/lib/chart-script.ts
new file mode 100644
index 000000000..d2c95b93a
--- /dev/null
+++ b/shared/astro/lib/chart-script.ts
@@ -0,0 +1,339 @@
+// Port of ui/chart.html (Liquid) — generator of the `;
+
+ // --- config ---
+ const config: Record = {};
+
+ config.chart = {
+ type,
+ fontFamily: 'inherit',
+ height: height * 16,
+ ...(data.sparkline
+ ? { sparkline: { enabled: true } }
+ : { parentHeightOffset: 0, toolbar: { show: Boolean(data.toolbar) } }),
+ animations: data.animations ? undefined : { enabled: false },
+ stacked: data.stacked ? true : undefined,
+ };
+
+ if (type === 'bar') {
+ config.plotOptions = {
+ bar: data.horizontal ? { barHeight: '50%', horizontal: true } : { columnWidth: '50%' },
+ };
+ }
+
+ if (type === 'radialBar') {
+ config.plotOptions = {
+ radialBar: {
+ startAngle: data['radial-start-angle'] ?? -120,
+ endAngle: data['radial-end-angle'] ?? 120,
+ hollow: {
+ margin: data['radial-hollow-margin'] ?? 16,
+ size: data['radial-hollow-size'] ?? '50%',
+ },
+ dataLabels: {
+ show: data['radial-labels-show'] !== false,
+ name: {
+ show: Boolean(data['radial-name-show']),
+ offsetY: data['radial-name-offset-y'] ?? 0,
+ fontSize: data['radial-name-font-size'] ?? '16px',
+ color: data['radial-name-color'] ?? 'inherit',
+ },
+ value: {
+ offsetY: data['radial-value-offset-y'] ?? -8,
+ fontSize: data['radial-value-font-size'] ?? '24px',
+ fontWeight: data['radial-value-font-weight'] ?? 600,
+ },
+ },
+ },
+ };
+ }
+
+ if (type === 'bar' || type === 'area') {
+ config.dataLabels = { enabled: Boolean(data.datalabels) };
+ }
+
+ if (data['fill-type']) {
+ config.fill = {
+ type: data['fill-type'],
+ gradient:
+ data['fill-type'] === 'gradient'
+ ? {
+ shade: data['fill-gradient-shade'] ?? 'light',
+ type: data['fill-gradient-type'] ?? 'horizontal',
+ shadeIntensity: data['fill-gradient-shade-intensity'] ?? 0.5,
+ gradientToColors: [data['fill-gradient-to-color'] ?? '#9ec2fb'],
+ inverseColors: Boolean(data['fill-gradient-inverse-colors']),
+ opacityFrom: data['fill-gradient-opacity-from'] ?? 1,
+ opacityTo: data['fill-gradient-opacity-to'] ?? 1,
+ stops: data['fill-gradient-stops'] ?? [0, 100],
+ }
+ : undefined,
+ };
+ } else if (type === 'area') {
+ config.fill = {
+ colors: [`var(--chart-${id}-fill-0)`, `var(--chart-${id}-fill-1)`],
+ type: 'solid',
+ };
+ }
+
+ if (data.title) {
+ config.title = {
+ text: escapeHtml(data.title),
+ margin: 0,
+ floating: true,
+ offsetX: 10,
+ style: { fontSize: '18px' },
+ };
+ }
+
+ if (type === 'radialBar' && data['stroke-linecap']) {
+ config.stroke = { lineCap: data['stroke-linecap'] };
+ } else if (type === 'area' || type === 'line') {
+ config.stroke = {
+ width: data['stroke-width'] ?? 2,
+ dashArray: data['stroke-dash'],
+ lineCap: 'round',
+ curve: data['stroke-curve'] ?? 'smooth',
+ };
+ }
+
+ if (series.length > 0) {
+ if (isRound) {
+ config.series = series.map((s) => s.data);
+ config.labels = series.map((s) => s.name ?? '');
+ } else {
+ config.series = series.map((s) => ({
+ name: s.name ?? '',
+ data: s['candlestick-data']
+ ? s['candlestick-data'].map((c) => ({ x: c.x, y: c.y }))
+ : (s.data as number[]),
+ }));
+ }
+ }
+
+ config.tooltip = { theme: 'dark' };
+
+ config.grid = {
+ padding: data.sparkline ? undefined : { top: -20, right: 0, left: -4, bottom: -4 },
+ show: data['hide-grid'] ? false : undefined,
+ strokeDashArray: data['hide-grid'] ? undefined : 4,
+ xaxis: !data['hide-grid'] && data['show-x'] ? { lines: { show: true } } : undefined,
+ };
+
+ if (data['show-data-labels']) {
+ config['dataLabels//2'] = { enabled: true };
+ }
+
+ if (data.categories || data.datetime) {
+ config.xaxis = {
+ labels: {
+ padding: 0,
+ formatter: data['x-formatter']
+ ? raw(`function (val) { return ${data['x-formatter']} }`)
+ : undefined,
+ },
+ tooltip: { enabled: false },
+ axisBorder: type === 'area' || type === 'bar' ? { show: false } : undefined,
+ categories: data.categories?.map(String),
+ type: data.datetime ? 'datetime' : undefined,
+ };
+ }
+
+ if (!isRound) {
+ config.yaxis = {
+ labels: { padding: 4 },
+ max: data['y-max'],
+ title: data['y-title'] ? { text: escapeHtml(data['y-title']) } : undefined,
+ tooltip: data['y-tooltip'] ? { enabled: true } : undefined,
+ };
+ }
+
+ if (data.datetime) {
+ const count = Array.isArray(series[0]?.data) ? (series[0].data as number[]).length : 0;
+ config.labels = datetimeLabels(data['start-date'] ?? '2020-06-20', count);
+ }
+
+ if (data.colors) {
+ config.colors = data.colors;
+ } else if (series.length > 0) {
+ config.colors = series.map((_, i) => `var(--chart-${id}-color-${i})`);
+ }
+
+ config.legend = data.legend
+ ? {
+ show: true,
+ position: 'bottom',
+ offsetY: 12,
+ markers: { width: 10, height: 10, radius: 100 },
+ itemMargin: { horizontal: 8, vertical: 8 },
+ }
+ : { show: false };
+
+ if (data['hide-tooltip'] || type === 'pie' || type === 'donut') {
+ config['tooltip//2'] = {
+ enabled: data['hide-tooltip'] ? false : undefined,
+ fillSeriesColor: type === 'pie' || type === 'donut' ? false : undefined,
+ };
+ }
+
+ if (data['hide-points']) {
+ config.point = { show: false };
+ }
+
+ if (data['show-markers']) {
+ config.markers = { size: 2 };
+ }
+
+ // environment === 'development' → window.tabler_chart registry
+ const script = ``;
+
+ return `${style}\n${script}`;
+}
diff --git a/shared/astro/lib/code-example.ts b/shared/astro/lib/code-example.ts
new file mode 100644
index 000000000..74e2728ac
--- /dev/null
+++ b/shared/astro/lib/code-example.ts
@@ -0,0 +1,43 @@
+// Docs code-block pipeline: js-beautify + shiki (github-dark) — exactly the
+// same options as in docs/eleventy.config.mjs (markdown-it highlight hook).
+import beautify from 'js-beautify';
+import { createHighlighter, type Highlighter } from 'shiki';
+
+let highlighterPromise: Promise | undefined;
+
+function getHighlighter(): Promise {
+ highlighterPromise ??= createHighlighter({
+ themes: ['github-dark'],
+ langs: ['html', 'yaml', 'js', 'ts', 'shell', 'diff', 'scss', 'css'],
+ });
+ return highlighterPromise;
+}
+
+export function beautifyHtml(code: string): string {
+ return beautify.html(code, {
+ indent_size: 2,
+ wrap_line_length: 80,
+ });
+}
+
+export async function highlightCode(code: string, lang = 'html'): Promise {
+ const highlighter = await getHighlighter();
+ return highlighter.codeToHtml(code, { lang, theme: 'github-dark' });
+}
+
+/** Equivalent of the escape_attribute filter (data-clipboard-text). */
+export function escapeAttribute(text: string): string {
+ return text
+ .replace(/&/g, '&')
+ .replace(/'/g, ''')
+ .replace(/"/g, '"')
+ .replace(//g, '>')
+ .replace(/\r\n/g, '
')
+ .replace(/[\r\n]/g, '
');
+}
+
+/** Equivalent of the remove-href filter. */
+export function removeHref(content: string): string {
+ return content.replace(/href="#"/g, 'href="javascript:void(0)"');
+}
diff --git a/shared/astro/lib/docs-children.ts b/shared/astro/lib/docs-children.ts
new file mode 100644
index 000000000..3617d9bd3
--- /dev/null
+++ b/shared/astro/lib/docs-children.ts
@@ -0,0 +1,77 @@
+type DocsPageFrontmatter = {
+ title?: string;
+ description?: string;
+ icon?: string;
+ order?: number;
+};
+
+export type DocsChildPage = {
+ url: string;
+ title: string;
+ description: string;
+ icon?: string;
+ order: number;
+};
+
+// Both page conventions are supported: `foo/index.mdx` and flat `foo.mdx`
+// produce the same route (/foo/) with the default 'directory' build format.
+// `@pages` is a per-package vite alias (preview: ./src/pages, docs: ./pages) —
+// that's what lets this file live in shared/ despite import.meta.glob being
+// resolved relative to the importer.
+const pageModules = import.meta.glob('@pages/**/*.mdx', { eager: true });
+
+function getFrontmatter(mod: unknown): DocsPageFrontmatter | null {
+ if (!mod || typeof mod !== 'object') return null;
+
+ if ('frontmatter' in mod && mod.frontmatter && typeof mod.frontmatter === 'object') {
+ return mod.frontmatter as DocsPageFrontmatter;
+ }
+
+ return null;
+}
+
+function urlFromGlobPath(path: string): string {
+ // glob keys for alias patterns are resolved paths — derive the route from
+ // the segment after the pages dir
+ const marker = path.indexOf('/pages/');
+ const rel = (marker === -1 ? path : path.slice(marker + '/pages/'.length))
+ .replace(/(?:^|\/)index\.mdx$/, '')
+ .replace(/\.mdx$/, '');
+ return rel ? `/${rel}/` : '/';
+}
+
+function normalizeUrl(url: string): string {
+ const parts = url.split('/').filter(Boolean);
+ return parts.length ? `/${parts.join('/')}/` : '/';
+}
+
+/** Direct child pages of a docs index URL (equivalent of Eleventy's collection-children). */
+export function getDocsChildren(parentUrl: string): DocsChildPage[] {
+ const parentParts = normalizeUrl(parentUrl).split('/').filter(Boolean);
+
+ return Object.entries(pageModules)
+ .map(([path, mod]) => {
+ const pageUrl = urlFromGlobPath(path);
+ const parts = pageUrl.split('/').filter(Boolean);
+ const isDirectChild =
+ parts.length === parentParts.length + 1 &&
+ parts.slice(0, -1).join('/') === parentParts.join('/');
+
+ if (!isDirectChild) return null;
+
+ const fm = getFrontmatter(mod);
+ if (!fm?.title) return null;
+
+ return {
+ url: pageUrl,
+ title: String(fm.title),
+ description: String(fm.description ?? ''),
+ icon: fm.icon ? String(fm.icon) : undefined,
+ order: Number(fm.order ?? 999),
+ };
+ })
+ .filter((page): page is DocsChildPage => page !== null)
+ // if a route exists in both conventions (foo.mdx AND foo/index.mdx), count it once
+ .filter((page, i, all) => all.findIndex((p) => p.url === page.url) === i)
+ .sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
+}
diff --git a/shared/astro/lib/liquid-date.ts b/shared/astro/lib/liquid-date.ts
new file mode 100644
index 000000000..c12b86ade
--- /dev/null
+++ b/shared/astro/lib/liquid-date.ts
@@ -0,0 +1,20 @@
+// Replicates the Eleventy Liquid `date` filter under `timezoneOffset: 0`
+// (shared/e11ty/config.mjs). Two quirks matter for parity:
+// - `%s` (Unix seconds) is shifted by the local timezone offset, so it is NOT
+// the true epoch (LiquidJS renders the wall clock, then reads its seconds).
+// - `%B %d, %Y` uses the UTC wall-clock components of the original timestamp.
+// Both are reproduced against the reference build on the same machine/timezone.
+const MONTHS = [
+ 'January', 'February', 'March', 'April', 'May', 'June',
+ 'July', 'August', 'September', 'October', 'November', 'December',
+];
+
+/** Equivalent of `{{ date | date: '%s' }}` with timezoneOffset: 0. */
+export function liquidUnixSeconds(date: Date): number {
+ return Math.floor(date.getTime() / 1000) + date.getTimezoneOffset() * 60;
+}
+
+/** Equivalent of `{{ date | date: '%B %d, %Y' }}` with timezoneOffset: 0. */
+export function liquidLongDate(date: Date): string {
+ return `${MONTHS[date.getUTCMonth()]} ${String(date.getUTCDate()).padStart(2, '0')}, ${date.getUTCFullYear()}`;
+}
diff --git a/shared/astro/lib/page-modals.ts b/shared/astro/lib/page-modals.ts
new file mode 100644
index 000000000..e9eb2504e
--- /dev/null
+++ b/shared/astro/lib/page-modals.ts
@@ -0,0 +1,21 @@
+// Equivalent of eleventy {% capture_modal %} / {% modals %}: modals declared
+// in the page content render at the end of , before the settings panel.
+//
+// A string OR a promise of a string is registered: the Modal component must
+// register itself SYNCHRONOUSLY in its frontmatter (before it first yields
+// control via await), because Astro renders siblings concurrently and
+// PageModals may drain the registry before the asynchronous render of the
+// modal's slot completes.
+const modals: Array> = [];
+
+export function addPageModal(html: string | Promise): void {
+ if (!modals.includes(html)) {
+ modals.push(html);
+ }
+}
+
+export function drainPageModals(): Array> {
+ const out = [...modals];
+ modals.length = 0;
+ return out;
+}
diff --git a/shared/astro/lib/page-scripts.ts b/shared/astro/lib/page-scripts.ts
new file mode 100644
index 000000000..afeaf85d8
--- /dev/null
+++ b/shared/astro/lib/page-scripts.ts
@@ -0,0 +1,18 @@
+// Equivalent of eleventy {% capture_script %} / {% scripts %}: components in the
+// page content register snippets (
-
-
-{% endremoveemptylines %} {%- endcapture %} {% capture_script %} {{ script }} {% endcapture_script %} {% endif %} {% endremoveemptylines %}
diff --git a/shared/includes/ui/chat.html b/shared/includes/ui/chat.html
deleted file mode 100644
index 6f87f1ffe..000000000
--- a/shared/includes/ui/chat.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
- {% for message in chats %}
- {% assign person = people[message.person-id] %}
- {% capture chat-avatar %}
-
{% include "ui/avatar.html" person=person %}
- {%- endcapture %}
- {% capture chat-message %}
-
-
- {% unless message.loading %}
-
-
-
{{ person.full_name }}
-
{{ message.timestamp }}
-
-
- {% endunless %}
-
- {% if message.loading %}
-
typing
- {% else %}
-
{{ message.message }}
- {% endif %}
-
- {% if message.gif %}
-
-
-
- {% endif %}
-
-
-
- {%- endcapture %}
-
-
{% if message.person-id == 0 %} {{ chat-message }} {{ chat-avatar }} {% else %} {{ chat-avatar }} {{ chat-message }} {% endif %}
-
- {% endfor %}
-
-
\ No newline at end of file
diff --git a/shared/includes/ui/colorpicker.html b/shared/includes/ui/colorpicker.html
deleted file mode 100644
index 1ed4fa431..000000000
--- a/shared/includes/ui/colorpicker.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% assign id = include.id | default: 'default' %}
-{% assign alpha = include.alpha | default: false %}
-{% assign format = include.format | default: false %}
-
-
-
-{% capture_script %}
-
-{% endcapture_script %}
diff --git a/shared/includes/ui/datepicker.html b/shared/includes/ui/datepicker.html
deleted file mode 100644
index f33a109bd..000000000
--- a/shared/includes/ui/datepicker.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% assign value = include.value | default: '2020-06-20' %}
-{% assign placeholder = include.placeholder | default: 'Select a date' %}
-
-{% if include.id %}
-
-{% capture input %}
-
-{%- endcapture %}
-
-
-{% if include.inline %}
-
-{% elsif include.layout == 'icon' %}
-
- {{ input | replace: include.class, '' }}
- {% include "ui/icon.html" icon="calendar" %}
-
-{% elsif include.layout == 'icon-prepend' %}
-
- {% include "ui/icon.html" icon="calendar" %}
- {{ input | replace: include.class, '' }}
-
-{% else %}
- {{ input }}
-{% endif %}
-
-{% capture script %}
-
-{%- endcapture %}
-
-{% if include.show-scripts %}
-{{ script }}
-{% else %}
-{% capture_script %}
-{{ script }}
-{% endcapture_script %}
-{% endif %}
-
-{% endif %}
\ No newline at end of file
diff --git a/shared/includes/ui/dropdown-menu.html b/shared/includes/ui/dropdown-menu.html
deleted file mode 100644
index e0704c61c..000000000
--- a/shared/includes/ui/dropdown-menu.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
diff --git a/shared/includes/ui/dropdown.html b/shared/includes/ui/dropdown.html
deleted file mode 100644
index cd2444245..000000000
--- a/shared/includes/ui/dropdown.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% assign optionsArray = include.options | split: ", " %}
-
-
\ No newline at end of file
diff --git a/shared/includes/ui/dropzone.html b/shared/includes/ui/dropzone.html
deleted file mode 100644
index 4d808d27c..000000000
--- a/shared/includes/ui/dropzone.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% assign id = include.id %}
-{% assign text = include.text | default: "Text"%}
-{% assign description = include.description | default: "Description" %}
-
-
-
-
-
- {% if include.custom %}
-
-
{{text}}
- {{description}}
-
- {% endif %}
-
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/shared/includes/ui/empty.html b/shared/includes/ui/empty.html
deleted file mode 100644
index bb9f0797e..000000000
--- a/shared/includes/ui/empty.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% assign icon = include.icon | default: "mood-sad" %}
-{% assign height = include.height | default: 256 %}
-
-
- {% if include.illustration %}
- {% assign illustration = include.illustration | default: 'boy-girl.svg' %}
-
{% include "ui/illustration.html" image=illustration height=height %}
- {% elsif include.icon-text %}
-
- {% else %}
-
{% include "ui/icon.html" icon=icon %}
- {% endif %}
-
-
-
{{ include.title | default: "No results found" }}
-
- {{ include.subtitle | default: "Try adjusting your search or filter to find what you're looking for." }}
-
-
- {% assign button-text = include.button-text | default: "Search again" %}
- {% assign button-icon = include.button-icon | default: "search" %}
- {% include "ui/button.html" text=button-text color="primary" icon=button-icon href="." %}
-
-
diff --git a/shared/includes/ui/flag.html b/shared/includes/ui/flag.html
deleted file mode 100644
index 96d6f5989..000000000
--- a/shared/includes/ui/flag.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/shared/includes/ui/form/check.html b/shared/includes/ui/form/check.html
deleted file mode 100644
index fd0fcde7e..000000000
--- a/shared/includes/ui/form/check.html
+++ /dev/null
@@ -1,25 +0,0 @@
-{% assign type = include.type | default: 'checkbox' %}
-{% assign checked = include.checked | default: false %}
-{% assign disabled = include.disabled | default: false %}
-{% assign switch = include.switch | default: false %}
-{% assign title = include.title | default: false %}
-{% assign name = include.name | default: false %}
-{% assign is_empty = include['empty'] | default: false %}
-{% unless title %}
-{% assign title = '' %}
-{% if disabled %}{% assign title = title | append: ' disabled' %}{% endif %}
-{% if checked %}{% assign title = title | append: ' checked' %}{% endif %}
-{% if switch %}{% assign title = title | append: ' switch' %}{% endif %}
-{% assign title = title | append: ' ' | append: type %}
-{% assign title = title | append: ' input' | lstrip | capitalize %}
-{% endunless %}
-
-
- {% if include.title-on and include.title-off %}
- {{include.title-on }}
- {{include.title-off }}
- {% else %}
- {% unless is_empty %}{{ title }} {% endunless %}
- {% endif %}
-
diff --git a/shared/includes/ui/form/input-file.html b/shared/includes/ui/form/input-file.html
deleted file mode 100644
index 71af9cc71..000000000
--- a/shared/includes/ui/form/input-file.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/shared/includes/ui/form/input-group.html b/shared/includes/ui/form/input-group.html
deleted file mode 100644
index 2303e18b9..000000000
--- a/shared/includes/ui/form/input-group.html
+++ /dev/null
@@ -1,48 +0,0 @@
-
diff --git a/shared/includes/ui/form/input-icon.html b/shared/includes/ui/form/input-icon.html
deleted file mode 100644
index 4512b1f8d..000000000
--- a/shared/includes/ui/form/input-icon.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% capture addon %}
- {% if include.loader %}
-
- {% include "ui/spinner.html" class="text-secondary" size="sm" %}
-
- {% else %}
- {% assign icon = include.icon | default: 'search' %}
-
- {% include "ui/icon.html" icon=icon %}
-
- {% endif %}
-{%- endcapture %}
-
-
- {% if include.prepend %}
- {{ addon }}
- {% endif %}
-
-
-
- {% unless include.prepend %}
- {{ addon }}
- {% endunless %}
-
diff --git a/shared/includes/ui/form/input-mask.html b/shared/includes/ui/form/input-mask.html
deleted file mode 100644
index 48e60bab5..000000000
--- a/shared/includes/ui/form/input-mask.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/shared/includes/ui/form/input-selectgroup.html b/shared/includes/ui/form/input-selectgroup.html
deleted file mode 100644
index 73bacc665..000000000
--- a/shared/includes/ui/form/input-selectgroup.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% assign values = include.values | default: "One,Two,Three" | split: ',' %}
-{% assign default = include.default | default: values[0] %}
-{% assign type = include.type | default: "checkbox" %}
-{% assign name = include.name | default: "name" %}
-
- {% for value in values %}
-
- {% assign s = value | split: "i:" %}
- {% if include.with-text %}
- {% assign icon-class = "me-1" %}
- {% endif %}
-
- {% if s.size == 2 %}{% assign icon = s[1] %}{% include "ui/icon.html" icon=icon class=icon-class use-svg=true %}{% if include.with-text %} {{ icon | capitalize }}{% endif %}{% else %}{{ value }}{% endif %}
-
- {% endfor %}
-
diff --git a/shared/includes/ui/form/textarea-autosize.html b/shared/includes/ui/form/textarea-autosize.html
deleted file mode 100644
index 22f735b3e..000000000
--- a/shared/includes/ui/form/textarea-autosize.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/shared/includes/ui/hr.html b/shared/includes/ui/hr.html
deleted file mode 100644
index 95c5fee81..000000000
--- a/shared/includes/ui/hr.html
+++ /dev/null
@@ -1 +0,0 @@
-{{ include.text | default: 'Label' }}
diff --git a/shared/includes/ui/icon.html b/shared/includes/ui/icon.html
deleted file mode 100644
index 2b4dabf96..000000000
--- a/shared/includes/ui/icon.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{%- assign icon-name = include.icon -%}
-{%- assign icon-type = include.type | default: "outline" -%}
-
-{%- assign replace-to = "icon" -%}
-
-{%- if include.class -%}
-{%- assign replace-to = replace-to | append: ' ' | append: include.class -%}
-{%- endif -%}
-
-{%- if include.color -%}
-{%- assign replace-to = replace-to | append: ' text-' | append: include.color -%}
-{%- endif %}
-
-{%- if include.inline -%}
-{%- assign replace-to = replace-to | append: ' icon-inline' -%}
-{%- endif -%}
-
-{%- if include['size'] -%}
-{%- assign replace-to = replace-to | append: ' icon-' | append: include['size'] -%}
-{%- endif -%}
-
-{%- assign replace-to = 'class="' | append: replace-to | append: '"' -%}
-
-{%- if site.useIconfont -%}
-
-{%- elsif icons[icon-name] -%}
-
- {% assign svg-icon = icons[icon-name].svg[icon-type] | default: '' -%}
- {%- assign svg-icon = svg-icon | replace: ' ', '' -%}
- {{ svg-icon | replace_regex: 'class=\"[^"]+\"', replace-to | replace: 'class="', 'aria-hidden="true" focusable="false" class="' }}
-{%- endif -%}
diff --git a/shared/includes/ui/illustration.html b/shared/includes/ui/illustration.html
deleted file mode 100644
index b72702c9a..000000000
--- a/shared/includes/ui/illustration.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% removeemptylines %}
-{% assign image = include.image | replace: '.svg', '' %}
-{% assign height = include.height | default: 128 %}
-
-{% assign illustration = free-illustrations.autodark[image] %}
-
-{% assign replace-to = '
-
-{% capture_script %}
-
-{% endcapture_script %}
-
-{% endif %}
\ No newline at end of file
diff --git a/shared/includes/ui/map-vector.html b/shared/includes/ui/map-vector.html
deleted file mode 100644
index 5af62ec95..000000000
--- a/shared/includes/ui/map-vector.html
+++ /dev/null
@@ -1,117 +0,0 @@
-{% removeemptylines %}
-{% assign id = include.map-id %}
-{% assign data = maps-vector[id] %}
-{% assign color = include.color | default: data.color | default: 'primary' %}
-
-{% if data %}
-
-
-{% capture script %}
-{% removeemptylines %}
-
-{%- endcapture %}
-
-{% capture_script %}
- {{ script }}
-{% endcapture_script %}
-{% endif %}
-{% endremoveemptylines %}
\ No newline at end of file
diff --git a/shared/includes/ui/map.html b/shared/includes/ui/map.html
deleted file mode 100644
index 36ff35213..000000000
--- a/shared/includes/ui/map.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% assign id = include.map-id %}
-{% assign data = maps[id] %}
-
-{% if data %}
-
-
- {% capture_script %}
-
- {% endcapture_script %}
-{% endif %}
\ No newline at end of file
diff --git a/shared/includes/ui/marketing/browser.html b/shared/includes/ui/marketing/browser.html
deleted file mode 100644
index 9ca08ce06..000000000
--- a/shared/includes/ui/marketing/browser.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- {% include "ui/responsive-image.html" src="static/marketing/preview.png" width=1040 height=760 %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/modal.html b/shared/includes/ui/modal.html
deleted file mode 100644
index 93b4ffd96..000000000
--- a/shared/includes/ui/modal.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-{% assign modal-id = include.modal-id | default: 'simple' %}
-{% assign size = include['size'] %}
-{% assign inline = include.inline | default: false %}
-
-{% capture_modal inline %}
-
-{% endcapture_modal %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/modal/close.html b/shared/includes/ui/modal/close.html
deleted file mode 100644
index 3d2836587..000000000
--- a/shared/includes/ui/modal/close.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/shared/includes/ui/modal/header.html b/shared/includes/ui/modal/header.html
deleted file mode 100644
index 835636ddb..000000000
--- a/shared/includes/ui/modal/header.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
\ No newline at end of file
diff --git a/shared/includes/ui/nav-segmented.html b/shared/includes/ui/nav-segmented.html
deleted file mode 100644
index 159532554..000000000
--- a/shared/includes/ui/nav-segmented.html
+++ /dev/null
@@ -1,30 +0,0 @@
-{% assign segmented-icons = include.icons | default: "" | split: "," %}
-{% assign segmented-items = include.items | default: "" | split: "," %}
-{% assign segmented-disabled = include.disabled | default: "" | split: "," %}
-{% assign segmented-hover = include.hover | default: "" %}
-{% assign segmented-default = include.default | default: 1 | plus: 0 %}
-
-{% assign segmented-items-count = segmented-items | size %}
-{% assign segmented-icons-count = segmented-icons | size %}
-{% assign segmented-all-count = segmented-items-count %}
-
-{% if segmented-icons-count > segmented-all-count %}{% assign segmented-all-count = segmented-icons-count %}{% endif %}
-
-
- {% for i in (1..segmented-all-count) %}
- {% assign index = forloop.index | append: "" %}
- {% assign disabled = segmented-disabled | contains: index %}
- {% assign is-default = forloop.index == segmented-default %}
-
- {% if include.name %} {% endif %}
-
- <{% if include.name %}label for="segmented-{{include.name }}-{{ index }}"{% else %}button{% endif %} class="nav-link{% if disabled %} disabled{% endif %}{% if is-default and not include.name %} active{% endif %}{% if segmented-hover == index %} hover{% endif %}" role="tab"{% unless include.name %} data-bs-toggle="tab"{% endunless %} aria-selected="{% if is-default %}true{% else %}false{% endif %}" {% if disabled %} aria-disabled="true"{% endif %}{% if is-default %} aria-current="page"{% endif %}>
- {% if segmented-icons[forloop.index0] %}
- {% include "ui/icon.html" icon=segmented-icons[forloop.index0] class="nav-link-icon" %}
- {% endif %}
- {% if segmented-items[forloop.index0] %}
- {{ segmented-items[forloop.index0] }}
- {% endif %}
- {% if include.name %}label{% else %}button{% endif %}>
- {% endfor %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/nav.html b/shared/includes/ui/nav.html
deleted file mode 100644
index 432941588..000000000
--- a/shared/includes/ui/nav.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
diff --git a/shared/includes/ui/pagination.html b/shared/includes/ui/pagination.html
deleted file mode 100644
index 997da8c41..000000000
--- a/shared/includes/ui/pagination.html
+++ /dev/null
@@ -1,57 +0,0 @@
-{% assign count = include.count | default: 5 -%}
-{% assign offset = include.offset | default: count -%}
-{% assign count-offset = count | minus: offset | plus: 1 -%}
-{% assign active-item = include.active-item | default: 3 -%}
-
-
-
diff --git a/shared/includes/ui/payment.html b/shared/includes/ui/payment.html
deleted file mode 100644
index a75061db7..000000000
--- a/shared/includes/ui/payment.html
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/shared/includes/ui/photo.html b/shared/includes/ui/photo.html
deleted file mode 100644
index c187c7b06..000000000
--- a/shared/includes/ui/photo.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
-{% if include.id %}
-{% assign id = include.id | default: 1 %}
-{% if include.horizontal %}
-{% assign filtered-photos = photos | where: 'horizontal', true %}
-{% else %}
-{% assign filtered-photos = photos %}
-{% endif %}
-
-{% assign photo = filtered-photos[id] %}
-
-{% if include.background %}
-
-{% elsif include.ratio %}
-
-{% else %}
-
-{% endif %}
-
-{% else %}
-{% include "ui/svg.html" width=640 height=480 border=true class=include.class %}
-{% endif %}
\ No newline at end of file
diff --git a/shared/includes/ui/progress-description.html b/shared/includes/ui/progress-description.html
deleted file mode 100644
index cbacfcc7c..000000000
--- a/shared/includes/ui/progress-description.html
+++ /dev/null
@@ -1,13 +0,0 @@
-{% assign size = include['size'] | default: 'sm' %}
-{% assign color = include.color | default: 'blue' %}
-
-
-
-
{{ include.label | default: 'Label' }}
- {% if include.description %}
-
{{ include.description }}
- {% endif %}
-
{{ include.value }}%
-
- {% include "ui/progress.html" size=size value=include.value color=color %}
-
diff --git a/shared/includes/ui/progress-steps.html b/shared/includes/ui/progress-steps.html
deleted file mode 100644
index 5eb1492af..000000000
--- a/shared/includes/ui/progress-steps.html
+++ /dev/null
@@ -1,18 +0,0 @@
-{% assign count = include.count | default: 3 %}
-{% assign labels = '' | split: ',' %}
-{% if include.labels %}
-{% assign labels = include.labels | split: ',' %}
-{% assign count = labels | size %}
-{% endif %}
-{% assign active = include.active | default: 1 %}
-{% assign color = include.color | default: 'primary' %}
-
-{% for i in (1..count) %}{% assign default = 'Step ' | append: i %}{% assign label = labels[forloop.index0] | default: default %}
-
-
- {{ label }}
-
-
- {% endfor %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/progress.html b/shared/includes/ui/progress.html
deleted file mode 100644
index 1be24732c..000000000
--- a/shared/includes/ui/progress.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% assign percentage = include.value | replace: '%', '' | default: 38 %}
-{% assign colors = include.colors | default: include.color | default: 'blue,red,green,yellow,dark' | split: ',' %}
-
- {% if include.indeterminate %}
-
- {% elsif include.values %}
- {% assign values = include.values | split: ',' %}
- {% for value in values %}
-
- {% endfor %}
- {% else %}
-
- {% if include.show-value %}
- {{ percentage }}%
- {% else %}
- {{ percentage }}% Complete
- {% endif %}
-
- {% endif %}
-
diff --git a/shared/includes/ui/progressbg.html b/shared/includes/ui/progressbg.html
deleted file mode 100644
index 431ae47e8..000000000
--- a/shared/includes/ui/progressbg.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% assign percentage = include.value | replace: '%', '' | default: 0 %}
-{% assign color = include.color | default: 'primary-lt' %}
-
- {% include "ui/progress.html" value=percentage class="progressbg-progress" color=color %}
- {% if include.text %}
{% if include.flag %}{% include "ui/flag.html" flag=include.flag class="me-2" size="xs" %}{% endif %}{{ include.text }}
{% endif %}
- {% if include.show-value %}
{{ percentage }}%
{% endif %}
-
diff --git a/shared/includes/ui/range.html b/shared/includes/ui/range.html
deleted file mode 100644
index f640a3b96..000000000
--- a/shared/includes/ui/range.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{% assign min = include.min | default: 0 %}
-{% assign max = include.max | default: 100 %}
-{% assign step = include.step | default: 10 %}
-{% assign value = include.value | default: 50 %}
-{% assign id = include.id %}
-
-{% if id %}
-
-
- {% capture_script %}
-
- {% endcapture_script %}
-{% else %}
-
-{% endif %}
\ No newline at end of file
diff --git a/shared/includes/ui/rating.html b/shared/includes/ui/rating.html
deleted file mode 100644
index 9533db67b..000000000
--- a/shared/includes/ui/rating.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{% assign id = include.id | default: include.icon | default: 'default' %}
-{% assign icon = include.icon | default: 'star' %}
-{% assign color = include.color %}
-{% assign size = include.size | default: false %}
-{% assign value = include.value %}
-
-
- Select a rating
- Excellent
- Very Good
- Average
- Poor
- Terrible
-
-
-{% capture star %}
-{% include "ui/icon.html" class="gl-star-full" icon=icon color=color type="filled" size=size %}
-{%- endcapture %}
-{% assign star = star | replace_regex: "[\t\s]+\n", "" | strip %}
-{% assign star = star | replace_regex: "[\n\t]{2,}", " " | strip %}
-{% assign star = star | replace_regex: "", "" | strip %}
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/shared/includes/ui/responsive-image.html b/shared/includes/ui/responsive-image.html
deleted file mode 100644
index 9d35e807d..000000000
--- a/shared/includes/ui/responsive-image.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% assign src = include.src %}
-{% assign width = include.width | default: 507 %}
-
-
-
diff --git a/shared/includes/ui/ribbon.html b/shared/includes/ui/ribbon.html
deleted file mode 100644
index 86b3d1e32..000000000
--- a/shared/includes/ui/ribbon.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- {% if include.text %}{{ include.text }}{% else %}{% include "ui/icon.html" icon="star" use-svg=true filled=include.filled %}{% endif %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/select.html b/shared/includes/ui/select.html
deleted file mode 100644
index 97fef533c..000000000
--- a/shared/includes/ui/select.html
+++ /dev/null
@@ -1,102 +0,0 @@
-{% assign id = include.id | default: include.key %}
-{% assign value = include.value %}
-
-{% if id %}
-{% assign key = include.key | default: 'people' %}
-{% assign data = selects[key] %}
-
-
- {% if include.values %}
- {% assign values = include.values | split: ',' %}
-
- {% for value in values %}
- {{ value }}
- {% endfor %}
- {% else %}
-
- {% assign options = data.options %}
-
- {% if data.data == 'people' %}
- {% for person in people limit: 20 %}
- {{ person.full_name }}
- {% endfor %}
-
- {% elsif data.data == 'optgroup' %}
- {% for group in options %}
-
- {% for option in group.options %}
- {{ option }}
- {% endfor %}
-
- {% endfor %}
-
- {% else %}
- {% for option in options %}
- {% if option.first %}
- {% if include.indicator == 'flag' %}
- {% capture indicator-html %}
- {% assign country = option[1].flag %}
- {% include "ui/flag.html" size="xs" flag=country %}
- {%- endcapture %}
- {% elsif include.indicator == 'label' %}
- {% capture indicator-html %}
- {% assign label = option[1].label %}
- {{ label }}
- {%- endcapture %}
- {% endif %}
- {{ option[1].name }}
- {% else %}
- {{ option }}
- {% endif %}
- {% endfor %}
- {% endif %}
- {% endif %}
-
-
-
-{% capture script %}
-
-{%- endcapture %}
-
-
-{% if include.show-scripts %}
-{{ script }}
-{% else %}
-{% capture_script %}
-{{ script }}
-{% endcapture_script %}
-{% endif %}
-
-{% endif %}
diff --git a/shared/includes/ui/shape.html b/shared/includes/ui/shape.html
deleted file mode 100644
index 8fed99904..000000000
--- a/shared/includes/ui/shape.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- {% include "ui/icon.html" icon=include.icon %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/signature.html b/shared/includes/ui/signature.html
deleted file mode 100644
index 57cb25be5..000000000
--- a/shared/includes/ui/signature.html
+++ /dev/null
@@ -1,52 +0,0 @@
-{% assign id = include.id | default: 'default' %}
-
-
- {% if include.clear %}
-
-
- {% include "ui/icon.html" icon="trash" %}
-
-
- {% endif %}
-
-
-
-{% capture_script %}
-
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/shared/includes/ui/spinner.html b/shared/includes/ui/spinner.html
deleted file mode 100644
index 73d8b1122..000000000
--- a/shared/includes/ui/spinner.html
+++ /dev/null
@@ -1,2 +0,0 @@
-{% assign elem = include.element | default: 'div' %}
-<{{ elem }} class="spinner-{{ include.type | default: 'border' }}{% if include.color %} text-{{ include.color }}{% endif %}{% if include['size'] %} spinner-{{ include.type | default: 'border' }}-{{ include['size'] }}{% endif %}{% if include.class %} {{ include.class }}{% endif %}" role="status">{{ elem }}>
diff --git a/shared/includes/ui/stars.html b/shared/includes/ui/stars.html
deleted file mode 100644
index 28a34407d..000000000
--- a/shared/includes/ui/stars.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% assign count = include.count | default: 5 %}
-{% assign rate = include.rate | default: 4 %}
-{% assign icon = include.icon | default: 'star' %}
-{% assign class = include.color | default: 'yellow' | prepend: 'text-' %}
-{% assign filled = include.filled | default: false %}
-
- {% for i in (1..5) %}
-
- {% include "ui/icon.html" icon=icon %}
-
- {% endfor %}
-
diff --git a/shared/includes/ui/status-dot.html b/shared/includes/ui/status-dot.html
deleted file mode 100644
index d44561f8d..000000000
--- a/shared/includes/ui/status-dot.html
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/shared/includes/ui/status-indicator.html b/shared/includes/ui/status-indicator.html
deleted file mode 100644
index ccf4024a1..000000000
--- a/shared/includes/ui/status-indicator.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/shared/includes/ui/status.html b/shared/includes/ui/status.html
deleted file mode 100644
index ef87a9367..000000000
--- a/shared/includes/ui/status.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
- {% if include.dot %}
-
- {% endif %}
- {{ include.text | default: 'Status' }}
-
\ No newline at end of file
diff --git a/shared/includes/ui/steps.html b/shared/includes/ui/steps.html
deleted file mode 100644
index 844c856c2..000000000
--- a/shared/includes/ui/steps.html
+++ /dev/null
@@ -1,11 +0,0 @@
-{% assign count = include.count | default: 4 %}
-{% assign active = include.active | default: 3 %}
-
- {% for i in (1..count) %}
- {% assign elem = 'a' %}
- {% if i > active %}{% assign elem = 'span' %}{% endif %}
- <{{ elem }} href="#" class="step-item{% if i == active %} active{% endif %}"{% if include.show-tooltip %} data-bs-toggle="tooltip" title="Step {{ i }} description"{% endif %}>{% if include.show-title %}
- Step {{ i }}
- {% endif %}{{ elem }}>
- {% endfor %}
-
diff --git a/shared/includes/ui/svg.html b/shared/includes/ui/svg.html
deleted file mode 100644
index 3a05876ce..000000000
--- a/shared/includes/ui/svg.html
+++ /dev/null
@@ -1,7 +0,0 @@
-{% assign width = include.width | default: include.size | default: 20 %}
-{% assign height = include.height | default: include.size | default: 20 %}
-
- {% if include.border %} {% endif %}
-
-
-
diff --git a/shared/includes/ui/switch-icon.html b/shared/includes/ui/switch-icon.html
deleted file mode 100644
index d68d3d7c6..000000000
--- a/shared/includes/ui/switch-icon.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% assign icon = include.icon | default: 'heart' %}
-{% assign icon-b = include.icon-b | default: icon | default: 'heart' %}
-{% assign icon-a-color = include.icon-a-color | default: 'muted' %}
-{% assign icon-b-color = include.icon-b-color | default: 'red' %}
-
-{% if icon == 'star' or icon == 'heart' %}
- {% assign icon-b-class = 'icon-filled' %}
-{% else %}
- {% assign icon-b-class = include.icon-b-class %}
-{% endif %}
-
-
-
- {% include "ui/icon.html" icon=icon %}
-
-
- {% include "ui/icon.html" icon=icon-b class=icon-b-class %}
-
-
\ No newline at end of file
diff --git a/shared/includes/ui/table.html b/shared/includes/ui/table.html
deleted file mode 100644
index c0531067f..000000000
--- a/shared/includes/ui/table.html
+++ /dev/null
@@ -1,90 +0,0 @@
-{% assign roles = 'User,Admin,Owner' | split: ',' %}
-{% assign limit = include.limit | default: 5 %}
-
-
-
-
- Name
- Title
-
- {% unless include.avatars %}
- Email
- {% endunless %}
-
- Role
-
- {% if include.nowrap %}
-
- {% endif %}
-
-
-
-
-
- {% for person in people limit: limit offset: include.offset %}
-
- {% if include.avatars %}
-
-
- {% include "ui/avatar.html" person-id=person.id class="me-2" %}
-
-
{{ person.full_name }}
-
-
-
-
- {% else %}
- {{ person.full_name }}
- {% endif %}
-
-
- {% if include.avatars %}
-
- {{ person.job_title }}
- {{ person.department }}
-
- {% else %}
-
- {{ person.job_title }}, {{ person.department }}
-
- {% endif %}
-
- {% unless include.avatars %}
- {{
- person.email }}
- {% endunless %}
-
-
-
- {% assign role-id = forloop.index | random_number: 0, 2 %}
- {{ roles[role-id] }}
-
-
- {% if include.nowrap %}
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi, commodi cupiditate debitis deserunt
- expedita hic incidunt iste modi molestiae nesciunt non nostrum perferendis perspiciatis placeat praesentium
- quaerat quo repellendus, voluptates.
-
- {% endif %}
-
-
- {% if include.buttons %}
-
- {% include "ui/button.html" text="Edit" %}
-
-
- Actions
-
- {% include "ui/dropdown-menu.html" right=true %}
-
-
- {% else %}
- Edit
- {% endif %}
-
-
- {% endfor %}
-
-
-
diff --git a/shared/includes/ui/tag.html b/shared/includes/ui/tag.html
deleted file mode 100644
index 5e885954f..000000000
--- a/shared/includes/ui/tag.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
- {% if include.flag %}
- {% include "ui/flag.html" flag=include.flag size="xxs" class="tag-flag" %}
- {% elsif include.icon %}
- {% include "ui/icon.html" icon=include.icon size="xxs" class="tag-icon" %}
- {% elsif include.person %}
- {% include "ui/avatar.html" person=include.person size="xxs" class="tag-avatar" %}
- {% elsif include.person-id %}
- {% include "ui/avatar.html" person-id=include.person-id size="xxs" class="tag-avatar" %}
- {% elsif include.payment %}
- {% include "ui/payment.html" provider=include.payment size="xxs" class="tag-payment" %}
- {% elsif include.status %}
- {% include "ui/badge.html" color=include.status class="tag-status badge-dot" text="" %}
- {% elsif include.legend %}
-
- {% elsif include.checkbox %}
-
- {% endif %}
- {{ include.text }}
- {% if include.badge %}
- {% include "ui/badge.html" color=include.status class="tag-badge" text=include.badge size="sm" %}
- {% endif %}
-
-
-
\ No newline at end of file
diff --git a/shared/includes/ui/toast.html b/shared/includes/ui/toast.html
deleted file mode 100644
index 0dc137d48..000000000
--- a/shared/includes/ui/toast.html
+++ /dev/null
@@ -1,24 +0,0 @@
-{% assign toast-id = include.toast-id | default: 'simple' %}
-{% assign person-id = include.person-id | default: 2 %}
-{% assign person = people[person-id] %}
-
- {% unless include.hide-header %}
-
- {% endunless %}
-
- {% if include.cookies %}
- 🍪 Our site uses cookies. By continuing to use our site, you agree to our Cookie Policy.
-
-
- {% else %}
- {{ include.text | default: 'Hello, world! This is a toast message.' }}
- {% endif %}
-
-
diff --git a/shared/includes/ui/tracking.html b/shared/includes/ui/tracking.html
deleted file mode 100644
index 8d7ee0bf4..000000000
--- a/shared/includes/ui/tracking.html
+++ /dev/null
@@ -1,14 +0,0 @@
-{% assign blocks = include.blocks | default: 30 %}
-
- {% for i in (1..blocks) %}
- {% if i == 5 or i == 18 %}
-
- {% elsif i == 22 or i == 23 %}
-
- {% elsif i == 14 %}
-
- {% else %}
-
- {% endif %}
- {% endfor %}
-
\ No newline at end of file
diff --git a/shared/includes/ui/trending.html b/shared/includes/ui/trending.html
deleted file mode 100644
index 4db5ae603..000000000
--- a/shared/includes/ui/trending.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% assign value = include.value | default: 25 %}
-{% if value > 0 %}
- {% assign trending-color = 'green' %}
- {% assign trending-icon = 'arrow-up' %}
-{% elsif value == 0 %}
- {% assign trending-color = 'muted' %}
- {% assign trending-icon = 'minus' %}
-{% else %}
- {% assign trending-color = 'red' %}
- {% assign trending-icon = 'arrow-down' %}
-{% endif %}
-
-
- {{ value }}{{ include.unit | default: "%" }} {% include "ui/icon.html" icon=trending-icon class="ms-0" size="sm" %}
-
diff --git a/shared/includes/ui/typed.html b/shared/includes/ui/typed.html
deleted file mode 100644
index 32a37c7e8..000000000
--- a/shared/includes/ui/typed.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% assign strings = include.strings | split: '|' %}
-{% assign id = include.id | default: "typed" %}
-{{ strings | first }}
-
-{% capture_script %}
-
-{% endcapture_script %}
\ No newline at end of file
diff --git a/shared/layouts/base.html b/shared/layouts/base.html
deleted file mode 100644
index 7e7e01a47..000000000
--- a/shared/layouts/base.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% assign layout-dark = page.layout-dark | default: site.layout-dark -%}
-
-{% include "layout/banner.html" %}
-{% assign title = title | default: layout.title %}
-
-
-
-
-
-
- {% if title %}{{ title }} - {% endif %}{% if site.title %}{{ site.title }} - {% endif %}{{ site.descriptionShort }}
-
- {% if environment == 'preview' %}
- {% include "layout/analytics.html" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "layout/og.html" %}
- {% elsif environment == 'development' %}
-
-
- {% endif %}
-
-
- {% include "layout/css.html" %}
- {% include "layout/js-libs.html" head %}
-
-
-
-
-
-
-{% assign layout-dark = layout-dark | default: site.layoutDark %}
-
- {% include "layout/skip-link.html" %}
-
-
-
-
- {{ content }}
-
- {% modals %}
-
- {% include "settings.html" %}
-
- {% include "layout/js.html" %}
-
-
diff --git a/shared/layouts/card.html b/shared/layouts/card.html
deleted file mode 100644
index a2a2b6a83..000000000
--- a/shared/layouts/card.html
+++ /dev/null
@@ -1,9 +0,0 @@
----
-layout: default
----
-
-
\ No newline at end of file
diff --git a/shared/layouts/default.html b/shared/layouts/default.html
deleted file mode 100644
index 876fc4cc4..000000000
--- a/shared/layouts/default.html
+++ /dev/null
@@ -1,46 +0,0 @@
----
-layout: base
----
-
-{% assign no-container = page.no-container | default: layout.no-container %}
-
-
- {% if layout-sidebar %}
-
- {% include "layout/sidebar.html" dark=layout-sidebar-dark end=layout-sidebar-end transparent=layout-navbar-transparent breakpoint="lg" %}
-
- {% endif %}
-
- {% unless layout-hide-topbar %}
-
- {% include "layout/navbar.html" condensed=layout-navbar-condensed overlap=layout-navbar-overlap dark=layout-navbar-dark hide-brand=layout-navbar-hide-brand hide-menu=layout-navbar-hide-menu sticky=layout-navbar-sticky transparent=layout-topbar-transparent class=layout-navbar-class hide-search=true %}
-
- {% endunless %}
-
-
-
- {% include "layout/page-header.html" %}
-
-
-
-
- {% if layout-wrapper-full %}
- {{ content }}
- {% else %}
- {% unless no-container %}
-
- {% endunless %}
- {{ content }}
- {% unless no-container %}
-
- {% endunless %}
-
- {% endif %}
-
-
-
-
- {% include "layout/footer.html" %}
-
-
-
\ No newline at end of file
diff --git a/shared/layouts/docs/default.html b/shared/layouts/docs/default.html
deleted file mode 100644
index 09bb3e633..000000000
--- a/shared/layouts/docs/default.html
+++ /dev/null
@@ -1,227 +0,0 @@
-
-
-
-
-
-
-
- {% assign pageSection = "" %}
- {% if page.url contains "/ui/" %}
- {% assign pageSection = "UI" %}
- {% elsif page.url contains "/icons/" %}
- {% assign pageSection = "Icons" %}
- {% elsif page.url contains "/illustrations/" %}
- {% assign pageSection = "Illustrations" %}
- {% elsif page.url contains "/emails/" %}
- {% assign pageSection = "Emails" %}
- {% endif %}
-
- {% assign metaTitle = title %}
- {% if seoTitle %}
- {% assign metaTitle = seoTitle %}
- {% endif %}
-
- {% assign metaDescription = description %}
- {% if seoDescription %}
- {% assign metaDescription = seoDescription %}
- {% endif %}
-
- {% assign siteName = "Tabler Documentation" %}
- {% if pageSection != "" %}
- {% assign siteName = "Tabler " | append: pageSection | append: " Documentation" %}
- {% endif %}
-
- {{ metaTitle }} | {{ siteName }}
- {% if environment == 'production' %}
- {% if metaDescription %} {% endif %}
-
-
-
-
-
- {% if metaDescription %} {% endif %}
-
-
-
-
-
- {% if metaDescription %} {% endif %}
-
- {% elsif environment == 'development' %}
-
-
- {% endif %}
-
- {% if environment == 'production' %}
- {% include "layout/analytics.html" %}
- {% endif %}
-
-
- {% for plugin in site.cssPlugins %}
-
- {% endfor %}
-
- {% if docs-libs -%}
- {% for lib in libs -%}
- {% if docs-libs contains lib[0] -%}
- {% for file in lib[1].css -%}
-
- {% endfor -%}
- {% endif -%}
- {% endfor -%}
- {% endif %}
-
-
-
-
-
-
-
-
-
- {% include "docs/navbar.html" %}
-
-
-
-
-
-
-
-
-
-
-
- {% include "docs/menu.html" %}
-
-
-
-
-
-
-
-
-
-
- {{ title }}
-
-
- {% if added-in %}
- {% assign added-in-label = "Added in " | append: added-in %}
-
- {% include "ui/badge.html" color="primary" light=true text=added-in-label %}
-
- {% endif %}
-
-
-
-
{{ summary }}
-
- {{ content | headings-id }}
-
- {% include "docs/pagination.html" %}
-
-
-
-
-
-
-
- © {% year %} Tabler. All rights reserved.
-
-
-
-
-
-
-
-
-
-
-
-
- {% include "docs/toc.html" %}
-
-
-
-
-
-
-
- {% for lib in libs -%}
- {% if docs-libs contains lib[0] or libs.global-libs contains lib[0] or lib[0] == "clipboard" -%}
- {% for file in lib[1].js -%}
-
- {% endfor -%}
- {% endif -%}
- {% endfor -%}
-
-
-
-
-
-
- {% if environment == 'production' %}
-
- {% endif %}
-
-
diff --git a/shared/layouts/error.html b/shared/layouts/error.html
deleted file mode 100644
index 142fb4e1f..000000000
--- a/shared/layouts/error.html
+++ /dev/null
@@ -1,12 +0,0 @@
----
-layout: base
-body-class: border-top-wide border-primary
----
-
-
-
- {% assign error = errors[page-error] %}
- {% assign header = error.header | default: 'Oops… You just found an error page' %}
- {% include "ui/empty.html" icon="settings" illustration=error.illustration icon-text=error.title title=header subtitle=error.description button-icon="arrow-left" button-text="Take me home" %}
-
-
diff --git a/shared/layouts/homepage.html b/shared/layouts/homepage.html
deleted file mode 100644
index 50d4030b3..000000000
--- a/shared/layouts/homepage.html
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: Dashboard
-layout: default
-page-header: Dashboard
-page-header-pretitle: Overview
-page-header-actions: buttons
-page-libs: [apexcharts, jsvectormap]
----
-
-{% unless site.layoutOnly %}
-{% include "layout/homepage.html" %}
-{% endunless %}
diff --git a/shared/layouts/marketing.html b/shared/layouts/marketing.html
deleted file mode 100644
index 435bab79f..000000000
--- a/shared/layouts/marketing.html
+++ /dev/null
@@ -1,173 +0,0 @@
----
-layout: base
-body-class: body-marketing body-gradient
-plugins: marketing
----
-
-
-{% include "marketing/navbar.html" %}
-
-
-
-
-
-{{ content }}
-
-
-
-
-
-
-
-
diff --git a/shared/layouts/pay.html b/shared/layouts/pay.html
deleted file mode 100644
index e5dab9160..000000000
--- a/shared/layouts/pay.html
+++ /dev/null
@@ -1,17 +0,0 @@
----
-layout: base
----
-
-
-
-
- {{ content }}
-
\ No newline at end of file
diff --git a/shared/layouts/prose.html b/shared/layouts/prose.html
deleted file mode 100644
index 8755eec46..000000000
--- a/shared/layouts/prose.html
+++ /dev/null
@@ -1,13 +0,0 @@
----
-layout: default
----
-
-
diff --git a/shared/layouts/redirect.html b/shared/layouts/redirect.html
deleted file mode 100644
index 35504b4ad..000000000
--- a/shared/layouts/redirect.html
+++ /dev/null
@@ -1 +0,0 @@
-{% include "redirect.html" url=page.redirect.to %}
diff --git a/shared/layouts/settings.html b/shared/layouts/settings.html
deleted file mode 100644
index 19e3f11be..000000000
--- a/shared/layouts/settings.html
+++ /dev/null
@@ -1,34 +0,0 @@
----
-layout: default
-title: Settings
-page-header: Account Settings
----
-
-
-
-
\ No newline at end of file
diff --git a/shared/layouts/single.html b/shared/layouts/single.html
deleted file mode 100644
index e0ef8bb2c..000000000
--- a/shared/layouts/single.html
+++ /dev/null
@@ -1,16 +0,0 @@
----
-layout: base
----
-
-
-
- {% unless hide-logo %}
-
- {% include "layout/navbar-logo.html" %}
-
- {% endunless %}
-
- {{ content }}
-
-
-