1
0
mirror of https://github.com/tabler/tabler.git synced 2025-12-22 01:44:25 +04:00

Compare commits

..

28 Commits

Author SHA1 Message Date
codecalm
54ded26b95 feat: enhance sidebar and layout options in theme settings 2025-09-22 23:09:55 +02:00
codecalm
fcb38a4059 update changelog 2025-09-19 23:48:17 +02:00
Paweł Kuna
9c5d729e6d Add progress page (#2494)
Co-authored-by: ethancrawford <ethan_jc@hotmail.com>
2025-09-19 23:06:55 +02:00
Paweł Kuna
f8dee0a4bb Update Bootstrap to 5.3.8 (#2490) 2025-09-18 23:50:09 +02:00
Resul Elezi
9a3361f8ba Fixes issue #1619 (#2482)
Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>
2025-09-18 18:19:24 +02:00
codecalm
f763e3b1dd fix: set default limit for activity loop to 40 2025-09-18 17:59:27 +02:00
Paweł Kuna
9997893b40 Add pnpm caching to Node.js setup in workflows (#2492) 2025-09-17 19:54:02 +02:00
dependabot[bot]
58ad1008c9 chore(deps): bump actions/stale from 9 to 10 (#2481)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-17 17:18:43 +02:00
dependabot[bot]
c0e757e252 chore(deps): bump actions/setup-node from 4 to 5 (#2480)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-17 17:17:19 +02:00
Paweł Kuna
5e119d4c06 Add Pay page & layout (#2476) 2025-09-17 16:35:23 +02:00
Vedang Shelatkar
c860288558 Fix icon alignment for btn-sm and btn-xl sizes #2474 (#2478)
Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>
2025-09-17 16:35:13 +02:00
Paweł Kuna
596237e8cc Accessibility and semantic improvements (#2488) 2025-09-17 16:34:36 +02:00
Paweł Kuna
736e60408b Migrate SASS to module API (#2477) 2025-09-12 17:48:31 +02:00
codecalm
212d560a87 Init sortable library 2025-09-09 01:05:18 +02:00
codecalm
0ee3c0a3b4 new emails page 2025-08-28 23:32:04 +02:00
codecalm
bddacee9ad Cursor rules update 2025-08-28 21:39:34 +02:00
dependabot[bot]
2c3efda2bd chore(deps): bump actions/checkout from 4 to 5 (#2469)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-28 21:34:52 +02:00
Paweł Kuna
4834022361 Config improvements (#2472) 2025-08-28 21:34:31 +02:00
Paweł Kuna
e16457fd2e Generate random data to demos (#2473) 2025-08-28 20:18:08 +02:00
codecalm
8b12ba0b01 new Cursor rules 2025-08-28 17:21:48 +02:00
codecalm
d2c812e023 new Cursor rules 2025-08-28 17:20:31 +02:00
Paweł Kuna
8947d7c7b7 Update activity messages in JSON data (#2452) 2025-07-23 19:16:47 +02:00
Paweł Kuna
399a5c59f9 Update icons to v3.34.1 (75 new icons) (#2451) 2025-07-23 19:16:36 +02:00
Valentine Frolov
ad22d046c3 Add a color palette in the signing component #2373 (#2448)
Co-authored-by: Valentine <valentine@pop-os.Dlink>
Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>
2025-07-23 19:15:14 +02:00
Paweł Kuna
b8b63d7e94 Fix mixed declarations in SCSS (#2450) 2025-07-23 19:13:46 +02:00
Koray Tuncer
ab8009b771 fix : Docs search not adjusted to dark mode (#2381) (#2443)
Co-authored-by: codecalm <codecalm@gmail.com>
Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>
2025-07-23 19:13:04 +02:00
Koray Tuncer
bd35fd39cf fix: Some forms on the new 'Form Elements' page don't lay out neatly … (#2444)
Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>
2025-07-23 19:12:47 +02:00
codecalm
4b65380293 fix: update environment condition from preview to production in default.html 2025-07-16 22:27:51 +02:00
136 changed files with 4817 additions and 3218 deletions

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": minor
"@tabler/preview": minor
---
Added Pay page with dedicated layout, navigation link, and card/PayPal payment form.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": minor
---
Added `.btn-ghost` button variant with transparent background and hover effects.

View File

@@ -0,0 +1,5 @@
---
"@tabler/preview": minor
---
Added color palette to signing component.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Fixed icon alignment for `.btn-sm` and `.btn-xl` sizes.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Fixed mixed declarations in SCSS.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Updated `stroke-width` for `.icon-sm` from `1` to `1.5` for better visibility.

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": patch
"@tabler/preview": patch
---
Added `bg-blur` utility and increased `container-tight` width for layout flexibility.

View File

@@ -0,0 +1,5 @@
---
"@tabler/preview": patch
---
Updated icons to v3.34.1 with 75 new icons.

View File

@@ -0,0 +1,5 @@
---
"@tabler/preview": patch
---
Updated activity messages.

View File

@@ -0,0 +1,5 @@
---
"@tabler/preview": minor
---
Added new onboarding page with progress indicator and navigation layout.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Fixed double bottom border in tables.

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": minor
"@tabler/preview": minor
---
Added Progress Background component with text labels and value display.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": minor
---
Added `.progress-lg` and `.progress-xl` size variants for the progress component.

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": minor
"@tabler/preview": minor
---
Added Progress Steps component for step-by-step navigation indicators.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Added smooth transitions for progress bar `width` and `background-color` changes.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Updated skip-link to use `visually-hidden` for improved accessibility.

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Updated deprecated global Sass functions to module equivalents (`map.merge`, `string.slice`, `math.percentage`, etc.).

View File

@@ -0,0 +1,5 @@
---
"@tabler/core": patch
---
Updated Bootstrap to v5.3.8.

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": patch
"@tabler/preview": patch
---
Updated trending component to use `arrow-up`/`arrow-down` instead of `trending-up`/`trending-down`.

View File

@@ -0,0 +1,5 @@
---
"@tabler/docs": patch
---
Fixed Docs search display in dark mode.

View File

@@ -0,0 +1,5 @@
---
"@tabler/preview": patch
---
Fixed responsive layouts on the Form Elements page.

100
.cursor/rules/changelog.mdc Normal file
View File

@@ -0,0 +1,100 @@
---
description: Cursor Rules for Tabler Changesets
globs:
alwaysApply: true
---
### File Structure
- Each change must be in a separate changeset file in `.changeset/` directory
- Use descriptive kebab-case filenames (e.g., `progress-sizes.md`, `button-ghost.md`)
- Follow the standard changeset format with frontmatter and description
### Change Description Format
- **One sentence per changeset** - keep descriptions concise and focused
- Use **backticks for code elements**: classes (`.btn-ghost`), properties (`stroke-width`), values (`1.5`), icons (`arrow-up`)
- Start with action verbs: "Added", "Updated", "Fixed", "Removed"
- Be specific about what was changed
### Version Bump Guidelines
- **Major**: Breaking changes, complete rewrites
- **Minor**: New features, new components, new pages, significant enhancements
- **Patch**: Bug fixes, small improvements, style updates, accessibility fixes
### Package Selection
- `"@tabler/core"`: Changes to SCSS, core functionality, CSS classes
- `"@tabler/preview"`: New pages, demo updates, preview-specific changes
- `"@tabler/docs"`: Documentation updates
- Use multiple packages when change affects multiple areas
### Examples
#### New Feature (Minor)
```md
---
"@tabler/core": minor
"@tabler/preview": minor
---
Added Progress Steps component for step-by-step navigation indicators.
```
#### Bug Fix (Patch)
```md
---
"@tabler/core": patch
---
Updated `stroke-width` for `.icon-sm` from `1` to `1.5` for better visibility.
```
#### New Page (Minor)
```md
---
"@tabler/preview": minor
---
Added new onboarding page with progress indicator and navigation layout.
```
#### Style Enhancement (Patch)
```md
---
"@tabler/core": patch
---
Added smooth transitions for progress bar width and background color changes.
```
### Code Formatting Rules
- Class names: `.btn-ghost`, `.progress-lg`, `.icon-sm`
- CSS properties: `stroke-width`, `background-color`, `width`
- Values: `1.5`, `transparent`, `100%`
- Icon names: `arrow-up`, `arrow-down`, `trending-up`
- HTML attributes: `aria-label`, `role`, `data-*`
- JavaScript functions: `addEventListener()`, `querySelector()`
### Common Patterns
- **Component additions**: "Added [ComponentName] component for [purpose]"
- **Size variants**: "Added [size] size variant for [component] (`.class-size`)"
- **Style fixes**: "Fixed [issue] in [component/element]"
- **Icon updates**: "Updated [component] to use `new-icon` instead of `old-icon`"
- **Accessibility**: "Improved accessibility by [specific change]"
### Commit Message Format
Use English for commit messages following conventional commit format when possible:
- `feat: add progress steps component`
- `fix: update icon stroke width for better visibility`
- `style: add smooth transitions to progress bars`

View File

@@ -0,0 +1,171 @@
---
description: Tabler Project HTML Elements Guidelines
globs: ["**/*.html", "**/*.liquid", "**/*.md"]
alwaysApply: true
---
## HTML Elements Guidelines
### 1. Icons
When you need to use an icon, always use the Tabler icon include syntax:
```html
{% include "ui/icon.html" icon="ICON_NAME" %}
```
**Examples:**
- `{% include "ui/icon.html" icon="home" %}`
- `{% include "ui/icon.html" icon="building-community" %}`
- `{% include "ui/icon.html" icon="map-pin" %}`
### 2. Page Links
When linking to other pages, always use the relative page syntax:
```html
href="{{ page | relative }}/url.html"
```
**Examples:**
- `href="{{ page | relative }}/job-post.html"`
- `href="{{ page | relative }}/job-listing.html"`
- `href="{{ page | relative }}/marketing/index.html"`
### 3. Static Generation
All pages are statically generated to HTML using Eleventy (11ty). Keep this in mind when:
- Writing frontmatter (must be static YAML, no Liquid templating)
- Creating dynamic content (use Liquid templating in the body, not frontmatter)
- Linking between pages (use relative paths)
### 4. Additional Guidelines
#### Frontmatter Rules
- Frontmatter must be static YAML
- Cannot use Liquid templating in frontmatter
- Use static values for title, permalink, etc.
#### Liquid Templating
- Use Liquid templating only in the HTML body
- Access data using `{{ variable }}` syntax
- Use `{% for %}` loops for dynamic content
- Use `{% if %}` conditions for conditional rendering
#### File Structure
- Pages go in `preview/pages/`
- Includes go in `shared/includes/`
- Data files go in `shared/data/`
- Documentation goes in `docs/content/`
#### CSS Classes
- Use Bootstrap 5 classes
- Use Tabler's custom CSS classes
- Follow the pattern: `--#{$prefix}component-property`
#### Accessibility
- Include proper ARIA labels
- Use semantic HTML elements
- Ensure proper heading hierarchy
- Add alt text for images
### 5. Component Usage
#### Cards
- Use `card` class for main containers
- Use `card-body` for content areas
- Use `card-header` for card headers
- Use `card-title` for card title
#### Buttons
- Use `btn` class for all buttons
- Use `btn-primary` for primary actions
- Use `btn` for secondary actions, don't use `btn-outline-secondary`
- Use `btn-sm` for smaller buttons
- Use `w-100` for full-width buttons
#### Forms
- Use `form-control` for input fields
- Use `form-label` for labels
- Use `form-check` for checkboxes/radio buttons
- Use `form-select` for dropdowns
#### Layout
- Use Bootstrap grid system (`row`, `col-*`)
- Use `container-xl` for main containers
- Use `page-wrapper` for page structure
- Use `page-body` for main content area
#### Badges
- Use `badge` class for badges
- Don't use `badge-outline` for badges, use `badge` class instead
- Don't use `badge-primary` for badges, use `badge` class instead
- Don't change the text color of badges
#### Markdown
- Use `markdown` class for markdown content
- Apply to containers that render markdown content
- Example: `<div class="markdown">...</div>`
#### Rest of the rules
- Read the rest of the rules in the `docs/content/ui/` folder
### 6. Data Integration
#### Using JSON Data
```liquid
{% for item in items %}
<div>{{ item.name }}</div>
{% endfor %}
```
#### Conditional Rendering
```liquid
{% if condition %}
<div>Content</div>
{% endif %}
```
#### Including Components
```liquid
{% include "ui/button.html" color="primary" text="Click me" %}
```
### 7. Best Practices
#### Performance
- Minimize nested loops
- Use `limit` filters when iterating large datasets
- Optimize images for web use
#### Code Organization
- Keep components modular and reusable
- Use consistent naming conventions
- Comment complex logic
- Group related functionality together
#### Error Handling
- Always check if data exists before using it
- Provide fallback content for missing data
- Use `{% if %}` guards for optional content

View File

@@ -26,7 +26,7 @@ jobs:
if: false
steps:
- name: Clone repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Cache turbo build setup
uses: actions/cache@v4
@@ -36,14 +36,15 @@ jobs:
restore-keys: |
${{ runner.os }}-turbo-
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE }}"
- name: Install PNPM
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "${{ env.NODE }}"
cache: 'pnpm'
- name: Get installed Playwright version
id: playwright-version
run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package.json').devDependencies['@playwright/test'])")" >> $GITHUB_ENV

View File

@@ -17,7 +17,7 @@ jobs:
steps:
- name: Clone repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Cache turbo build setup
uses: actions/cache@v4
@@ -27,14 +27,15 @@ jobs:
restore-keys: |
${{ runner.os }}-turbo-
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE }}"
- name: Install PNPM
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "${{ env.NODE }}"
cache: 'pnpm'
- name: Set up Bundler
uses: ruby/setup-ruby@v1
with:

View File

@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
persist-credentials: false

View File

@@ -11,7 +11,7 @@ jobs:
pull-requests: write
issues: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
days-before-issue-stale: 360
days-before-issue-close: 14

View File

@@ -12,7 +12,7 @@ jobs:
name: Verify lock file integrity
steps:
- name: Clone Tabler
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Prevent lock file change
uses: xalvarez/prevent-file-change-action@v2
with:

View File

@@ -21,16 +21,17 @@ jobs:
pull-requests: write # to create pull request
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup Node.js 18
uses: actions/setup-node@v4
with:
node-version: 20
uses: actions/checkout@v5
- name: Install PNPM
uses: pnpm/action-setup@v4
- name: Setup Node.js 18
uses: actions/setup-node@v5
with:
node-version: "${{ env.NODE }}"
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Cache turbo build setup
uses: actions/cache@v4
@@ -24,14 +24,15 @@ jobs:
restore-keys: |
${{ runner.os }}-turbo-
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "${{ env.NODE }}"
- name: Install PNPM
uses: pnpm/action-setup@v4
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "${{ env.NODE }}"
cache: 'pnpm'
- run: node --version
- name: Install pnpm dependencies

25
core/js/src/sortable.js Normal file
View File

@@ -0,0 +1,25 @@
// SortableJS plugin
// Initializes Sortable on elements marked with [data-sortable]
// Allows options via JSON in data attribute: data-sortable='{"animation":150}'
const sortableElements = document.querySelectorAll('[data-sortable]');
if (sortableElements.length) {
sortableElements.forEach(function (element) {
let options = {};
try {
const rawOptions = element.getAttribute('data-sortable');
options = rawOptions ? JSON.parse(rawOptions) : {};
} catch (e) {
// ignore invalid JSON
}
if (window.Sortable) {
// eslint-disable-next-line no-new
new window.Sortable(element, options);
}
});
}

View File

@@ -9,6 +9,9 @@ const themeConfig = {
"theme-font": "sans-serif",
"theme-primary": "blue",
"theme-radius": "1",
"sidebar-position": "left",
"sidebar-behavior": "sticky",
"layout": "container",
}
const params = new Proxy(new URLSearchParams(window.location.search), {

View File

@@ -7,6 +7,7 @@ import "./src/popover"
import "./src/switch-icon"
import "./src/tab"
import "./src/toast"
import "./src/sortable"
export * as bootstrap from "bootstrap"
export * as tabler from "./src/tabler"

View File

@@ -38,6 +38,12 @@
"dist/list.min.js"
]
},
"sortablejs": {
"npm": "sortablejs",
"js": [
"Sortable.min.js"
]
},
"masonry": {
"js": [
"https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js"

View File

@@ -146,7 +146,7 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"bootstrap": "5.3.7"
"bootstrap": "5.3.8"
},
"devDependencies": {
"@hotwired/turbo": "^8.0.13",
@@ -158,16 +158,17 @@
"countup.js": "^2.9.0",
"dropzone": "^6.0.0-beta.2",
"flatpickr": "^4.6.13",
"fslightbox": "^3.6.1",
"fullcalendar": "^6.1.18",
"fslightbox": "^3.7.4",
"fullcalendar": "^6.1.19",
"hugerte": "^1.0.9",
"imask": "^7.6.1",
"jsvectormap": "^1.7.0",
"list.js": "^2.3.1",
"litepicker": "^2.0.12",
"nouislider": "^15.8.1",
"plyr": "^3.7.8",
"signature_pad": "^5.0.10",
"plyr": "^3.8.3",
"signature_pad": "^5.1.1",
"sortablejs": "^1.15.6",
"star-rating.js": "^4.3.1",
"tom-select": "^2.4.3",
"typed.js": "^2.1.0"

View File

@@ -1,5 +1,4 @@
// Config
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";

View File

@@ -1,3 +1,5 @@
@use "sass:color";
@mixin caret($direction: down) {
$selector: "after";
@@ -74,5 +76,5 @@
// TODO: remove when https://github.com/twbs/bootstrap/pull/37425/ will be released
//
@function opaque($background, $foreground) {
@return mix(rgba($foreground, 1), $background, opacity($foreground) * 100%);
@return color.mix(rgba($foreground, 1), $background, color.alpha($foreground) * 100%);
}

View File

@@ -1,4 +1,4 @@
@import "bootstrap/scss/functions";
@import "mixins";
@import "variables";

View File

@@ -1,3 +1,4 @@
@use "sass:map";
@import "config";
:root,
@@ -30,7 +31,7 @@
--#{$prefix}brand: #{$primary};
/** Theme colors */
@each $name, $color in map-merge($theme-colors, $social-colors) {
@each $name, $color in map.merge($theme-colors, $social-colors) {
--#{$prefix}#{$name}: #{$color};
--#{$prefix}#{$name}-rgb: #{to-rgb($color)};
--#{$prefix}#{$name}-fg: #{if(contrast-ratio($color) > $min-contrast-ratio, var(--#{$prefix}light), var(--#{$prefix}dark))};

View File

@@ -1,6 +1,8 @@
@use "sass:map";
$negative-spacers-extra: if(
$enable-negative-margins,
negativify-map(map-merge($spacers, $spacers-extra)),
negativify-map(map.merge($spacers, $spacers-extra)),
null
);

View File

@@ -110,6 +110,13 @@ $utilities: (
null: linear-gradient(var(--#{$prefix}gradient-direction, to right), var(--#{$prefix}gradient-stops, var(--#{$prefix}gradient-from, transparent), var(--#{$prefix}gradient-to, transparent))) no-repeat,
),
),
"bg-blur": (
property: backdrop-filter,
class: bg-blur,
values: (
null: blur($backdrop-blur)
)
),
"bg-gradient-direction": (
property: --#{$prefix}gradient-direction,
class: bg-gradient,

View File

@@ -1,3 +1,8 @@
@use "sass:string";
@use "sass:math";
@use "sass:map";
@use "sass:color";
$prefix: "tblr-" !default;
// BASE CONFIG
@@ -23,8 +28,8 @@ $font-google-monospaced: null !default;
$font-local: null !default;
$font-icons: () !default;
$font-family-sans-serif: unquote("#{if($font-local, "#{$font-local}, ", ' ')}#{if($font-google, "#{$font-google}, ", ' ')}") 'Inter Var', Inter, -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif !default;
$font-family-monospace: unquote("#{if($font-google-monospaced, "#{$font-google-monospaced}, ", '')}") Monaco, Consolas, Liberation Mono, Courier New, monospace !default;
$font-family-sans-serif: string.unquote("#{if($font-local, "#{$font-local}, ", ' ')}#{if($font-google, "#{$font-google}, ", ' ')}") 'Inter Var', Inter, -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif !default;
$font-family-monospace: string.unquote("#{if($font-google-monospaced, "#{$font-google-monospaced}, ", '')}") Monaco, Consolas, Liberation Mono, Courier New, monospace !default;
$font-family-serif: "Georgia", "Times New Roman", times, serif !default;
$font-family-comic: "Comic Sans MS", "Comic Sans", "Chalkboard SE", "Comic Neue", sans-serif, cursive !default;
@@ -200,7 +205,7 @@ $border-color-translucent: rgba(4, 32, 69, 0.1);
$border-dark-color: $gray-400 !default;
$border-dark-color-translucent: rgba(4, 32, 69, 0.27);
$border-active-color: mix($text-secondary, #ffffff, percentage($border-active-opacity)) !default;
$border-active-color: color.mix($text-secondary, #ffffff, math.percentage($border-active-opacity)) !default;
$border-active-color-translucent: rgba($text-secondary, $border-active-opacity) !default;
$active-bg: rgba(var(--#{$prefix}primary-rgb), 0.04) !default;
@@ -282,18 +287,18 @@ $gray-colors: (
gray-950: $gray-950,
) !default;
$theme-colors: map-merge($theme-colors, map-merge($extra-colors, ()));
$theme-colors: map.merge($theme-colors, map.merge($extra-colors, ()));
// BACKDROPS
$backdrop-opacity: 24% !default;
$backdrop-opacity: .32 !default;
$backdrop-blur: 4px !default;
$backdrop-bg: var(--#{$prefix}gray-800) !default;
$backdrop-bg: light-dark(var(--#{$prefix}gray-800), var(--#{$prefix}black)) !default;
$backdrops: (
dark: color-mix(in srgb, var(--#{$prefix}color-dark), transparent var(--#{$prefix}backdrop-opacity)),
light: color-mix(in srgb, var(--#{$prefix}color-light), transparent var(--#{$prefix}backdrop-opacity)),
) !default;
// Borders
// Borders
$border-width: 1px !default;
$border-width-wide: 2px !default;
@@ -427,7 +432,7 @@ $grid-gutter-width: 1rem !default;
$container-variations: (
slim: 16rem,
tight: 30rem,
tight: 32rem,
narrow: 61.875rem,
) !default;
@@ -477,7 +482,7 @@ $size-spacers: (
full: 100%,
) !default;
$size-values: map-merge(
$size-values: map.merge(
$spacers,
(
25: 25%,
@@ -670,7 +675,7 @@ $card-border-color: var(--#{$prefix}border-color-translucent) !default;
$card-border-radius: var(--#{$prefix}border-radius-lg) !default;
$card-spacer-x: 1.25rem !default;
$card-spacer-y: 1rem !default;
$card-spacer-y: 1.25rem !default;
$card-cap-bg: var(--#{$prefix}bg-surface-tertiary) !default;
$card-cap-color: inherit !default;
@@ -749,9 +754,9 @@ $list-group-item-padding-y: $card-cap-padding-y !default;
$list-group-item-padding-x: $card-cap-padding-x !default;
// Modals
$modal-backdrop-opacity: 0.24 !default;
$modal-backdrop-opacity: $backdrop-opacity !default;
$modal-backdrop-bg: $backdrop-bg !default;
$modal-backdrop-blur: 4px !default;
$modal-backdrop-blur: $backdrop-blur !default;
$modal-fade-transform: translate(0, -1rem) !default;
@@ -847,6 +852,7 @@ $navbar-active-border-color: var(--#{$prefix}primary) !default;
// Sidebar
$sidebar-width: 15rem !default;
$sidebar-narrow-width: 4rem !default;
// Page
$page-title-font-size: var(--#{$prefix}font-size-h2) !default;

View File

@@ -1,3 +1,5 @@
@use "sass:map";
//
// Clearfix
//
@@ -86,7 +88,7 @@
}
// Responsive sticky top and bottom
@each $breakpoint in map-keys($grid-breakpoints) {
@each $breakpoint in map.keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);

View File

@@ -1,3 +1,5 @@
@use "sass:map";
// stylelint-disable property-no-vendor-prefix
body {
letter-spacing: $body-letter-spacing;
@@ -17,46 +19,4 @@ body {
}
}
@include scrollbar;
//
// Fluid container
//
.layout-fluid {
.container,
[class^="container-"],
[class*=" container-"] {
max-width: 100%;
}
}
//
// Boxed container
//
.layout-boxed {
--#{$prefix}theme-boxed-border-radius: 0;
--#{$prefix}theme-boxed-width: #{map-get($container-max-widths, xxl)};
@include media-breakpoint-up(md) {
background: $dark linear-gradient(to right, rgba(#fff, .1), transparent) fixed;
padding: 1rem;
--#{$prefix}theme-boxed-border-radius: #{$border-radius};
}
.page {
margin: 0 auto;
max-width: var(--#{$prefix}theme-boxed-width);
border-radius: var(--#{$prefix}theme-boxed-border-radius);
color: var(--#{$prefix}body-color);
@include media-breakpoint-up(md) {
border: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
background: var(--#{$prefix}body-bg);
}
> .navbar:first-child {
border-top-left-radius: var(--#{$prefix}theme-boxed-border-radius);
border-top-right-radius: var(--#{$prefix}theme-boxed-border-radius);
}
}
}
@include scrollbar;

View File

@@ -1,3 +1,5 @@
@use "sass:map";
@mixin navbar-vertical-nav {
.navbar-collapse {
flex-direction: column;
@@ -124,7 +126,7 @@ Navbar
}
.navbar-expand {
@each $breakpoint in map-keys($grid-breakpoints) {
@each $breakpoint in map.keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
@@ -165,22 +167,6 @@ Navbar
box-shadow: inset calc(1 * var(--#{$prefix}navbar-border-width)) 0 0 0 var(--#{$prefix}navbar-border-color);
}
}
&.navbar-vertical {
~ .navbar,
~ .page-wrapper {
margin-left: $sidebar-width;
}
}
&.navbar-vertical.navbar-right,
&.navbar-vertical.navbar-end {
~ .navbar,
~ .page-wrapper {
margin-left: 0;
margin-right: $sidebar-width;
}
}
}
}
}
@@ -221,14 +207,14 @@ Navbar toggler
width: 1.25em;
background: currentColor;
border-radius: 10px;
position: relative;
@include transition(
top $navbar-toggler-animation-time $navbar-toggler-animation-time,
bottom $navbar-toggler-animation-time $navbar-toggler-animation-time,
transform $navbar-toggler-animation-time,
opacity 0s $navbar-toggler-animation-time
);
position: relative;
&:before,
&:after {
content: "";
@@ -306,8 +292,12 @@ Navbar vertical
*/
@if $enable-navbar-vertical {
.navbar-vertical {
@at-root .page:has(>#{&}) {
margin-left: $sidebar-width;
}
&.navbar-expand {
@each $breakpoint in map-keys($grid-breakpoints) {
@each $breakpoint in map.keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
@@ -320,9 +310,9 @@ Navbar vertical
bottom: 0;
z-index: $zindex-fixed;
align-items: flex-start;
@include transition(transform $transition-time);
overflow-y: scroll;
padding: 0;
@include transition(transform $transition-time);
&.navbar-right,
&.navbar-end {
@@ -378,6 +368,97 @@ Navbar vertical
}
}
}
// Narrow sidebar implementation
&.navbar-narrow {
@at-root .page:has(>#{&}) {
margin-left: $sidebar-narrow-width;
}
&.navbar-expand {
@each $breakpoint in map.keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
&#{$infix} {
@include media-breakpoint-up($next) {
width: $sidebar-narrow-width;
.navbar-brand {
.navbar-brand-image {
width: 1.5rem;
height: 1.5rem;
}
}
.navbar-nav {
.nav-link {
justify-content: center;
padding-left: 0.5rem;
padding-right: 0.5rem;
.nav-link-title {
display: none;
}
.nav-link-icon {
margin-right: 0;
}
}
.dropdown-menu {
position: fixed !important;
left: $sidebar-narrow-width;
top: auto;
margin-left: 0.25rem;
background: var(--#{$prefix}bg-surface);
border: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
box-shadow: var(--#{$prefix}shadow);
border-radius: var(--#{$prefix}border-radius);
min-width: 12rem;
.dropdown-item {
padding: 0.5rem 1rem;
color: var(--#{$prefix}body-color);
background: transparent;
&:hover,
&:focus {
background: var(--#{$prefix}gray-100);
}
&.active {
background: var(--#{$prefix}primary);
color: var(--#{$prefix}white);
}
}
}
}
~ .page {
padding-left: $sidebar-narrow-width;
}
&.navbar-right ~ .page,
&.navbar-end ~ .page {
padding-left: 0;
padding-right: $sidebar-narrow-width;
}
}
}
}
}
}
}
}
/**
Navbar narrow tooltips
*/
.navbar-narrow-tooltip {
.tooltip-inner {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
}
}

View File

@@ -1,3 +1,5 @@
@use "sass:map";
.shape {
--#{$prefix}shape-size: #{$avatar-size};
--#{$prefix}shape-icon-size: #{$avatar-icon-size};
@@ -18,8 +20,8 @@
@each $avatar-size, $size in $avatar-sizes {
.shape-#{$avatar-size} {
--#{$prefix}shape-size: #{map-get($size, size)};
--#{$prefix}shape-icon-size: #{map-get($size, icon-size)};
--#{$prefix}shape-size: #{map.get($size, size)};
--#{$prefix}shape-icon-size: #{map.get($size, icon-size)};
}
}

View File

@@ -1,5 +1,12 @@
@use "sass:math";
@use "sass:string";
@use "sass:list";
@use "sass:map";
@use "sass:color";
@use "sass:meta";
@function theme-color-lighter($color, $background: #fff) {
@return mix($color, $background, 10%);
@return color.mix($color, $background, 10%);
}
@function theme-color-darker($color) {
@@ -10,10 +17,10 @@
// Replace all occurrences of a substring within a string.
//
@function str-replace($string, $search, $replace: "") {
$index: str-index($string, $search);
$index: string.index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
@return string.slice($string, 1, $index - 1) + $replace + str-replace(string.slice($string, $index + string.length($search)), $search, $replace);
}
@return $string;
@@ -37,23 +44,23 @@
}
}
@function breakpoint-prev($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
@function breakpoint-prev($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map.keys($breakpoints)) {
$n: index($breakpoint-names, $name);
@if not $n {
@error "breakpoint `#{$name}` not found in `#{$breakpoints}`";
}
@return if($n > 1, nth($breakpoint-names, $n - 1), null);
@return if($n > 1, list.nth($breakpoint-names, $n - 1), null);
}
//
// Escape SVG strings.
//
@function escape-svg($string) {
@if str-index($string, "data:image/svg+xml") {
@if string.index($string, "data:image/svg+xml") {
@each $char, $encoded in $escaped-characters {
// Do not escape the url brackets
@if str-index($string, "url(") == 1 {
$string: url("#{str-replace(str-slice($string, 6, -3), $char, $encoded)}");
@if string.index($string, "url(") == 1 {
$string: url("#{str-replace(string.slice($string, 6, -3), $char, $encoded)}");
} @else {
$string: str-replace($string, $char, $encoded);
}
@@ -70,7 +77,7 @@
* @return {String} - The percentage representation of the value.
*/
@function to-percentage($value) {
@return if(unitless($value), percentage($value), $value);
@return if(math.is-unitless($value), math.percentage($value), $value);
}
/**
@@ -93,4 +100,307 @@
$svg: str-replace($svg, '<svg', '<svg xmlns="http://www.w3.org/2000/svg"');
@return url('data:image/svg+xml;charset=UTF-8,#{$svg}');
}
// Bootstrap functions
//
// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.
// Ascending
// Used to evaluate Sass maps like our grid breakpoints.
@mixin _assert-ascending($map, $map-name) {
$prev-key: null;
$prev-num: null;
@each $key, $num in $map {
@if $prev-num == null or math.unit($num) == "%" or math.unit($prev-num) == "%" {
// Do nothing
} @else if not math.compatible($prev-num, $num) {
@warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
} @else if $prev-num >= $num {
@warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !";
}
$prev-key: $key;
$prev-num: $num;
}
}
// Starts at zero
// Used to ensure the min-width of the lowest breakpoint starts at 0.
@mixin _assert-starts-at-zero($map, $map-name: "$grid-breakpoints") {
@if list.length($map) > 0 {
$values: map.values($map);
$first-value: list.nth($values, 1);
@if $first-value != 0 {
@warn "First breakpoint in #{$map-name} must start at 0, but starts at #{$first-value}.";
}
}
}
// Colors
@function to-rgb($value) {
@return color.channel($value, "red", $space: rgb), color.channel($value, "green", $space: rgb), color.channel($value, "blue", $space: rgb);
}
// stylelint-disable scss/dollar-variable-pattern
@function rgba-css-var($identifier, $target) {
@if $identifier == "body" and $target == "bg" {
@return rgba(var(--#{$prefix}#{$identifier}-bg-rgb), var(--#{$prefix}#{$target}-opacity));
} @if $identifier == "body" and $target == "text" {
@return rgba(var(--#{$prefix}#{$identifier}-color-rgb), var(--#{$prefix}#{$target}-opacity));
} @else {
@return rgba(var(--#{$prefix}#{$identifier}-rgb), var(--#{$prefix}#{$target}-opacity));
}
}
@function map-loop($map, $func, $args...) {
$_map: ();
@each $key, $value in $map {
// allow to pass the $key and $value of the map as an function argument
$_args: ();
@each $arg in $args {
$_args: list.append($_args, if($arg == "$key", $key, if($arg == "$value", $value, $arg)));
}
$_map: map.merge($_map, ($key: meta.call(meta.get-function($func), $_args...)));
}
@return $_map;
}
// stylelint-enable scss/dollar-variable-pattern
@function varify($list) {
$result: null;
@each $entry in $list {
$result: list.append($result, var(--#{$prefix}#{$entry}), space);
}
@return $result;
}
// Internal Bootstrap function to turn maps into its negative variant.
// It prefixes the keys with `n` and makes the value negative.
@function negativify-map($map) {
$result: ();
@each $key, $value in $map {
@if $key != 0 {
$result: map.merge($result, ("n" + $key: (-$value)));
}
}
@return $result;
}
// Get multiple keys from a sass map
@function map-get-multiple($map, $values) {
$result: ();
@each $key, $value in $map {
@if (index($values, $key) != null) {
$result: map.merge($result, ($key: $value));
}
}
@return $result;
}
// Merge multiple maps
@function map-merge-multiple($maps...) {
$merged-maps: ();
@each $map in $maps {
$merged-maps: map.merge($merged-maps, $map);
}
@return $merged-maps;
}
// Replace `$search` with `$replace` in `$string`
// Used on our SVG icon backgrounds for custom forms.
//
// @author Kitty Giraudel
// @param {String} $string - Initial string
// @param {String} $search - Substring to replace
// @param {String} $replace ('') - New value
// @return {String} - Updated string
@function str-replace($string, $search, $replace: "") {
$index: string.index($string, $search);
@if $index {
@return string.slice($string, 1, $index - 1) + $replace + str-replace(string.slice($string, $index + string.length($search)), $search, $replace);
}
@return $string;
}
// See https://codepen.io/kevinweber/pen/dXWoRw
//
// Requires the use of quotes around data URIs.
@function escape-svg($string) {
@if string.index($string, "data:image/svg+xml") {
@each $char, $encoded in $escaped-characters {
// Do not escape the url brackets
@if string.index($string, "url(") == 1 {
$string: url("#{str-replace(string.slice($string, 6, -3), $char, $encoded)}");
} @else {
$string: str-replace($string, $char, $encoded);
}
}
}
@return $string;
}
// Color contrast
// See https://github.com/twbs/bootstrap/pull/30168
// A list of pre-calculated numbers of pow(divide((divide($value, 255) + .055), 1.055), 2.4). (from 0 to 255)
// stylelint-disable-next-line scss/dollar-variable-default, scss/dollar-variable-pattern
$_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003 .0033 .0037 .004 .0044 .0048 .0052 .0056 .006 .0065 .007 .0075 .008 .0086 .0091 .0097 .0103 .011 .0116 .0123 .013 .0137 .0144 .0152 .016 .0168 .0176 .0185 .0194 .0203 .0212 .0222 .0232 .0242 .0252 .0262 .0273 .0284 .0296 .0307 .0319 .0331 .0343 .0356 .0369 .0382 .0395 .0409 .0423 .0437 .0452 .0467 .0482 .0497 .0513 .0529 .0545 .0561 .0578 .0595 .0612 .063 .0648 .0666 .0685 .0704 .0723 .0742 .0762 .0782 .0802 .0823 .0844 .0865 .0887 .0908 .0931 .0953 .0976 .0999 .1022 .1046 .107 .1095 .1119 .1144 .117 .1195 .1221 .1248 .1274 .1301 .1329 .1356 .1384 .1413 .1441 .147 .15 .1529 .1559 .159 .162 .1651 .1683 .1714 .1746 .1779 .1812 .1845 .1878 .1912 .1946 .1981 .2016 .2051 .2086 .2122 .2159 .2195 .2232 .227 .2307 .2346 .2384 .2423 .2462 .2502 .2542 .2582 .2623 .2664 .2705 .2747 .2789 .2831 .2874 .2918 .2961 .3005 .305 .3095 .314 .3185 .3231 .3278 .3325 .3372 .3419 .3467 .3515 .3564 .3613 .3663 .3712 .3763 .3813 .3864 .3916 .3968 .402 .4072 .4125 .4179 .4233 .4287 .4342 .4397 .4452 .4508 .4564 .4621 .4678 .4735 .4793 .4851 .491 .4969 .5029 .5089 .5149 .521 .5271 .5333 .5395 .5457 .552 .5583 .5647 .5711 .5776 .5841 .5906 .5972 .6038 .6105 .6172 .624 .6308 .6376 .6445 .6514 .6584 .6654 .6724 .6795 .6867 .6939 .7011 .7084 .7157 .7231 .7305 .7379 .7454 .7529 .7605 .7682 .7758 .7835 .7913 .7991 .807 .8148 .8228 .8308 .8388 .8469 .855 .8632 .8714 .8796 .8879 .8963 .9047 .9131 .9216 .9301 .9387 .9473 .956 .9647 .9734 .9823 .9911 1;
@function color-contrast($background, $color-contrast-dark: $color-contrast-dark, $color-contrast-light: $color-contrast-light, $min-contrast-ratio: $min-contrast-ratio) {
$foregrounds: $color-contrast-light, $color-contrast-dark, $white, $black;
$max-ratio: 0;
$max-ratio-color: null;
@each $color in $foregrounds {
$contrast-ratio: contrast-ratio($background, $color);
@if $contrast-ratio >= $min-contrast-ratio {
@return $color;
} @else if $contrast-ratio > $max-ratio {
$max-ratio: $contrast-ratio;
$max-ratio-color: $color;
}
}
@warn "Found no color leading to #{$min-contrast-ratio}:1 contrast ratio against #{$background}...";
@return $max-ratio-color;
}
@function contrast-ratio($background, $foreground: $color-contrast-light) {
$l1: luminance($background);
$l2: luminance(opaque($background, $foreground));
@return if($l1 > $l2, divide($l1 + .05, $l2 + .05), divide($l2 + .05, $l1 + .05));
}
// Return WCAG2.2 relative luminance
// See https://www.w3.org/TR/WCAG/#dfn-relative-luminance
// See https://www.w3.org/TR/WCAG/#dfn-contrast-ratio
@function luminance($color) {
$rgb: (
"r": math.round(color.channel($color, "red", $space: rgb)),
"g": math.round(color.channel($color, "green", $space: rgb)),
"b": math.round(color.channel($color, "blue", $space: rgb))
);
@each $name, $value in $rgb {
$value: if(divide($value, 255) < .04045, divide(divide($value, 255), 12.92), list.nth($_luminance-list, $value + 1));
$rgb: map.merge($rgb, ($name: $value));
}
@return (map.get($rgb, "r") * .2126) + (map.get($rgb, "g") * .7152) + (map.get($rgb, "b") * .0722);
}
// Return opaque color
// opaque(#fff, rgba(0, 0, 0, .5)) => #808080
@function opaque($background, $foreground) {
@return color.mix(rgba($foreground, 1), $background, color.opacity($foreground) * 100%);
}
// scss-docs-start color-functions
// Tint a color: mix a color with white
@function tint-color($color, $weight) {
@return color.mix(white, $color, $weight);
}
// Shade a color: mix a color with black
@function shade-color($color, $weight) {
@return color.mix(black, $color, $weight);
}
// Shade the color if the weight is positive, else tint it
@function shift-color($color, $weight) {
@return if($weight > 0, shade-color($color, $weight), tint-color($color, -$weight));
}
// scss-docs-end color-functions
// Return valid calc
@function add($value1, $value2, $return-calc: true) {
@if $value1 == null {
@return $value2;
}
@if $value2 == null {
@return $value1;
}
@if meta.type-of($value1) == number and meta.type-of($value2) == number and math.compatible($value1, $value2) {
@return $value1 + $value2;
}
@return if($return-calc == true, calc(#{$value1} + #{$value2}), $value1 + string.unquote(" + ") + $value2);
}
@function subtract($value1, $value2, $return-calc: true) {
@if $value1 == null and $value2 == null {
@return null;
}
@if $value1 == null {
@return -$value2;
}
@if $value2 == null {
@return $value1;
}
@if meta.type-of($value1) == number and meta.type-of($value2) == number and math.compatible($value1, $value2) {
@return $value1 - $value2;
}
@if meta.type-of($value2) != number {
$value2: string.unquote("(") + $value2 + string.unquote(")");
}
@return if($return-calc == true, calc(#{$value1} - #{$value2}), $value1 + string.unquote(" - ") + $value2);
}
@function divide($dividend, $divisor, $precision: 10) {
$sign: if($dividend > 0 and $divisor > 0 or $dividend < 0 and $divisor < 0, 1, -1);
$dividend: math.abs($dividend);
$divisor: math.abs($divisor);
@if $dividend == 0 {
@return 0;
}
@if $divisor == 0 {
@error "Cannot divide by 0";
}
$remainder: $dividend;
$result: 0;
$factor: 10;
@while ($remainder > 0 and $precision >= 0) {
$quotient: 0;
@while ($remainder >= $divisor) {
$remainder: $remainder - $divisor;
$quotient: $quotient + 1;
}
$result: $result * 10 + $quotient;
$factor: $factor * .1;
$remainder: $remainder * 10;
$precision: $precision - 1;
@if ($precision < 0 and $remainder >= $divisor * 5) {
$result: $result + 1;
}
}
$result: $result * $factor * $sign;
$dividend-unit: math.unit($dividend);
$divisor-unit: math.unit($divisor);
$unit-map: (
"px": 1px,
"rem": 1rem,
"em": 1em,
"%": 1%
);
@if ($dividend-unit != $divisor-unit and map.has-key($unit-map, $dividend-unit)) {
$result: $result * map.get($unit-map, $dividend-unit);
}
@return $result;
}

View File

@@ -1,3 +1,4 @@
@use "sass:map";
@import "config";
[data-bs-theme-base="slate"] {
@@ -119,3 +120,49 @@
}
}
}
//
// Fluid container
//
[data-bs-layout="fluid"] {
.container,
[class^="container-"],
[class*=" container-"] {
max-width: 100%;
}
}
//
// Boxed container
//
[data-bs-layout="boxed"] {
--#{$prefix}theme-boxed-border-radius: 0;
--#{$prefix}theme-boxed-width: #{map.get($container-max-widths, xxl)};
@include media-breakpoint-up(md) {
background: $dark linear-gradient(to right, rgba(#fff, .1), transparent) fixed;
padding: 1rem;
--#{$prefix}theme-boxed-border-radius: #{$border-radius};
}
body {
background: transparent;
}
.page {
margin: 0 auto;
max-width: var(--#{$prefix}theme-boxed-width);
border-radius: var(--#{$prefix}theme-boxed-border-radius);
color: var(--#{$prefix}body-color);
@include media-breakpoint-up(md) {
border: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
background: var(--#{$prefix}body-bg);
}
> .navbar:first-child {
border-top-left-radius: var(--#{$prefix}theme-boxed-border-radius);
border-top-right-radius: var(--#{$prefix}theme-boxed-border-radius);
}
}
}

View File

@@ -1,3 +1,5 @@
@use "sass:map";
.avatar {
--#{$prefix}avatar-size: var(--#{$prefix}avatar-list-size, #{$avatar-size});
--#{$prefix}avatar-status-size: #{$avatar-status-size};
@@ -55,15 +57,15 @@
@each $avatar-size, $size in $avatar-sizes {
.avatar-#{$avatar-size} {
--#{$prefix}avatar-size: #{map-get($size, size)};
--#{$prefix}avatar-status-size: #{map-get($size, status-size)};
--#{$prefix}avatar-font-size: #{map-get($size, font-size)};
--#{$prefix}avatar-icon-size: #{map-get($size, icon-size)};
--#{$prefix}avatar-brand-size: #{map-get($size, brand-size)};
--#{$prefix}avatar-size: #{map.get($size, size)};
--#{$prefix}avatar-status-size: #{map.get($size, status-size)};
--#{$prefix}avatar-font-size: #{map.get($size, font-size)};
--#{$prefix}avatar-icon-size: #{map.get($size, icon-size)};
--#{$prefix}avatar-brand-size: #{map.get($size, brand-size)};
.badge:empty {
width: map-get($size, status-size);
height: map-get($size, status-size);
width: map.get($size, status-size);
height: map.get($size, status-size);
}
}
}
@@ -94,7 +96,7 @@
@each $avatar-size, $size in $avatar-sizes {
.avatar-list-#{$avatar-size} {
--#{$prefix}avatar-list-size: #{map-get($size, size)};
--#{$prefix}avatar-list-size: #{map.get($size, size)};
}
}

View File

@@ -1,4 +1,5 @@
@use "sass:color";
@use "sass:map";
//
// Button
@@ -23,7 +24,6 @@
position: relative;
min-width: calc((var(--#{$prefix}btn-line-height) * 1) + (var(--#{$prefix}btn-padding-y) * 2) + (var(--#{$prefix}btn-border-width) * 2));
min-height: calc((var(--#{$prefix}btn-line-height) * 1) + (var(--#{$prefix}btn-padding-y) * 2) + (var(--#{$prefix}btn-border-width) * 2));
.icon {
width: var(--#{$prefix}btn-icon-size);
@@ -76,7 +76,7 @@
//
// Button color variations
//
@each $color, $value in map-merge($theme-colors, $social-colors) {
@each $color, $value in map.merge($theme-colors, $social-colors) {
.btn-#{$color} {
@if $color == "dark" {
--#{$prefix}btn-border-color: var(--#{$prefix}dark-mode-border-color);
@@ -114,6 +114,15 @@
--#{$prefix}btn-disabled-border-color: var(--#{$prefix}#{$color});
}
.btn-ghost {
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-box-shadow: none;
--#{$prefix}btn-hover-bg: var(--#{$prefix}bg-surface-secondary);
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-hover-color: var(--#{$prefix}body-color);
}
.btn-ghost-#{$color},
.btn-ghost.btn-#{$color} {
--#{$prefix}btn-color: var(--#{$prefix}#{$color});
@@ -186,6 +195,10 @@
.icon {
margin: calc(-1 * var(--#{$prefix}btn-padding-x));
}
//[BUG] btn-sm and btn-xl with an icon looks broken
//issue #2470 fixed
min-width: calc(var(--#{$prefix}btn-icon-size) + (var(--#{$prefix}btn-padding-x) * 2));
min-height: calc(var(--#{$prefix}btn-icon-size) + (var(--#{$prefix}btn-padding-y) * 2));
}
//
@@ -202,7 +215,7 @@
position: fixed;
z-index: $zindex-fixed;
bottom: 1rem;
left: 1rem;
right: 1rem;
box-shadow: var(--#{$prefix}shadow-dropdown);
}

View File

@@ -111,11 +111,11 @@
justify-content: center;
padding: $card-spacer-y $card-spacer-x;
text-align: center;
@include transition(background $transition-time);
border-top: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
flex: 1;
color: inherit;
font-weight: var(--#{$prefix}font-weight-medium);
@include transition(background $transition-time);
&:hover {
text-decoration: none;
@@ -438,6 +438,23 @@ Card table
}
}
tbody {
tr {
&:last-child {
td {
border-bottom: 0;
}
}
}
}
tfoot {
tr {
&:last-child {
border-bottom: 0;
}
}
}
.card-body + & {
border-top: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}table-border-color);
}

View File

@@ -24,6 +24,7 @@
color: var(--#{$prefix}btn-close-color);
text-decoration: none;
opacity: var(--#{$prefix}btn-close-hover-opacity);
background-color: var(--#{$prefix}btn-close-color);
}
&:focus {

View File

@@ -1,3 +1,5 @@
@use "sass:map";
$countries: (
'ad', 'af', 'ae', 'afrun', 'ag', 'ai', 'al', 'am', 'ao', 'aq', 'ar', 'as', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bl', 'bm', 'bn', 'bo', 'bq-bo', 'bq-sa', 'bq-se', 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cc', 'cd', 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'cr', 'cu', 'cv', 'cw', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do', 'dz', 'ec', 'ee', 'eg', 'eh', 'er', 'es', 'et', 'eu', 'fi', 'fj', 'fk', 'fm', 'fo', 'fr', 'ga', 'gb-eng', 'gb-sct', 'gb', 'gb-wls', 'gb-nir', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gl', 'gm', 'gn', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il', 'im', 'in', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm', 'jo', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kp', 'kr', 'kw', 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu', 'lv', 'ly', 'ma', 'mc', 'md', 'me', 'mf', 'mg', 'mh', 'mk', 'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz', 'na', 'nc', 'ne', 'nf', 'ng', 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'pa', 'pe', 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'ps', 'pt', 'pw', 'py', 'qa', 'rainbow', 're', 'ro', 'rs', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd', 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr', 'ss', 'st', 'sv', 'sx', 'sy', 'sz', 'tc', 'td', 'tf', 'tg', 'th', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tr', 'tt', 'tv', 'tw', 'tz', 'ua', 'ug', 'um', 'unasur', 'us', 'uy', 'uz', 'va', 'vc', 've', 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'za', 'zm', 'zw'
);
@@ -26,6 +28,6 @@ $countries: (
@each $flag-size, $size in $flag-sizes {
.flag-#{$flag-size} {
height: map-get($size, size);
height: map.get($size, size);
}
}

View File

@@ -15,7 +15,7 @@ Form label
&.required {
&:after {
content: "*";
margin-left: .25rem;
margin-left: 0.25rem;
color: $red;
}
}
@@ -39,17 +39,17 @@ Form hint
}
& + .form-control {
margin-top: .25rem;
margin-top: 0.25rem;
}
.form-label + & {
margin-top: -.25rem;
margin-top: -0.25rem;
}
.input-group + &,
.form-control + &,
.form-select + & {
margin-top: .5rem;
margin-top: 0.5rem;
color: $form-secondary-color;
}
}
@@ -90,18 +90,18 @@ Form control
}
.form-control-dark {
background-color: rgba($black, .1);
background-color: rgba($black, 0.1);
color: $white;
border-color: transparent;
&:focus {
background-color: rgba($black, .1);
background-color: rgba($black, 0.1);
box-shadow: none;
border-color: rgba($white, .24);
border-color: rgba($white, 0.24);
}
&::placeholder {
color: rgba($white, .6);
color: rgba($white, 0.6);
}
}
@@ -144,7 +144,7 @@ Form help
justify-content: center;
width: 1.125rem;
height: 1.125rem;
font-size: .75rem;
font-size: 0.75rem;
color: $form-secondary-color;
text-align: center;
text-decoration: none;
@@ -161,8 +161,6 @@ Form help
}
}
/**
Input group
*/
@@ -208,19 +206,21 @@ Input group
.input-group-text {
background: $form-check-input-bg;
z-index: 10;
@include transition($input-transition);
&:first-child {
padding-right: 0;
border-right: 0;
}
&:last-child {
padding-left: 0;
border-left: 0;
}
}
}
/**
Upload files
*/
@@ -248,4 +248,4 @@ Forms on mobile devices
@include media-breakpoint-down(sm) {
font-size: 1rem;
}
}
}

View File

@@ -1,3 +1,5 @@
@use "sass:map";
.row > * {
min-width: 0;
}
@@ -54,7 +56,7 @@
}
}
@each $name, $size in map-merge((null: $spacer), $spacers) {
@each $name, $size in map.merge((null: $spacer), $spacers) {
$name-prefixed: if($name == null, null, '-#{$name}');
.space-y#{$name-prefixed} {
@@ -69,7 +71,7 @@
}
}
@each $name, $size in map-merge((null: $spacer), $spacers) {
@each $name, $size in map.merge((null: $spacer), $spacers) {
$name-prefixed: if($name == null, null, '-#{$name}');
.divide-y#{$name-prefixed} {

View File

@@ -37,7 +37,7 @@
//
.icon-sm {
--#{$prefix}icon-size: 1rem;
stroke-width: 1;
stroke-width: 1.5;
}
.icon-md {

View File

@@ -1,5 +1,7 @@
@use "sass:math";
.img-responsive {
--#{$prefix}img-responsive-ratio: #{percentage(.75)};
--#{$prefix}img-responsive-ratio: #{math.percentage(.75)};
background: no-repeat center/cover;
padding-top: var(--#{$prefix}img-responsive-ratio);
}

View File

@@ -65,8 +65,8 @@
.nav-link {
display: flex;
@include transition(color $transition-time, background-color $transition-time);
align-items: center;
@include transition(color $transition-time, background-color $transition-time);
&:hover,
&:focus {

View File

@@ -1,3 +1,5 @@
@use "sass:map";
$payment-icons: ("2c2p", "2checkout", "adyen", "affirm", "alipay-plus", "alipay", "allegro-pay", "amazon-pay", "amazon", "americanexpress", "applepay", "authorize", "autopay", "bancontact", "binance-usd", "bitcoin", "bitpay", "bkash", "blik", "braintree", "cash-app", "chime", "cirrus", "clickandbuy", "coinkite", "dinersclub", "directdebit", "discover", "dotpay", "dwolla", "easypaisa", "ebay", "elo", "epayco", "esewa", "ethereum", "eway", "fonepay", "giropay", "google-pay", "googlewallet", "hubspot", "ingenico", "ideal", "imepay", "jcb", "khalti", "klarna", "laser", "litecoin", "maestro", "mastercard", "mercado-pago", "metamask", "mir", "monero", "moneygram", "neteller", "ogone", "okpay", "opensea", "paybox", "payconiq", "payka", "payline", "paymill", "payone", "payoneer", "paypal", "paypo", "paysafe", "paysafecard", "payu", "payza", "poli", "przelewy24", "revolut-pay", "ripple", "sage", "samsung-pay", "sepa", "shop-pay", "shopify", "skrill", "solana", "solo", "spingo", "square", "stax", "stripe", "switch", "tether", "tpay", "troy", "true-usd", "ukash", "unionpay", "venmo", "verifone", "verisign", "visa", "we-chat-pay", "webmoney", "westernunion", "wise", "worldpay", "zelle");
.payment {
@@ -23,6 +25,6 @@ $payment-icons: ("2c2p", "2checkout", "adyen", "affirm", "alipay-plus", "alipay"
@each $payment-size, $size in $payment-sizes {
.payment-#{$payment-size} {
height: map-get($size, size);
height: map.get($size, size);
}
}

View File

@@ -42,11 +42,20 @@ Progress
height: .25rem;
}
.progress-lg {
height: .75rem;
}
.progress-xl {
height: 1rem;
}
/**
Progress bar
*/
.progress-bar {
height: 100%;
@include transition(width $transition-time, background $transition-time);
}
.progress-bar-indeterminate {
@@ -104,4 +113,32 @@ Progressbg
font-weight: var(--#{$prefix}font-weight-medium);
margin-left: auto;
padding-left: 2rem;
}
/**
Progress steps
*/
.progress-steps {
display: flex;
flex-wrap: nowrap;
width: 100%;
padding: 0;
margin: 0;
list-style: none;
gap: .25rem;
}
.progress-steps-item {
flex: 1 1 0;
min-height: .25rem;
margin-top: 0;
color: inherit;
text-align: center;
cursor: default;
background-color: var(--tblr-border-color);
border-radius: var(--#{$prefix}border-radius-pill);
@at-root a#{&} {
cursor: pointer;
}
}

View File

@@ -1,3 +1,5 @@
@use "sass:map";
$apps: (
"apple",
"discord",
@@ -47,6 +49,6 @@ $apps: (
@each $flag-size, $size in $flag-sizes {
.social-#{$flag-size} {
height: map-get($size, size);
height: map.get($size, size);
}
}

View File

@@ -18,10 +18,6 @@
.table {
margin-bottom: 0;
}
+ .card-footer {
border-top: 0;
}
}
.table-transparent {
@@ -112,10 +108,9 @@ Table sort
display: block;
width: 100%;
text-align: inherit;
@include transition(color $transition-time);
margin: calc(-1 * $table-th-padding-y) calc(-1 * $table-th-padding-x);
padding: $table-th-padding-y $table-th-padding-x;
@include transition(color $transition-time);
&:hover,
&.asc,

View File

@@ -3,11 +3,12 @@ Select group
*/
.form-selectgroup {
display: inline-flex;
margin: 0 -.5rem -.5rem 0;
margin: 0;
flex-wrap: wrap;
gap: 0.5rem;
.form-selectgroup-item {
margin: 0 .5rem .5rem 0;
margin: 0;
}
}

View File

@@ -1,5 +1,7 @@
@use "sass:map";
// All colors
@each $color, $value in map-merge($theme-colors, ( white: $white)) {
@each $color, $value in map.merge($theme-colors, ( white: $white)) {
.bg-#{"" + $color} {
background-color: color-mix(in srgb, var(--#{$prefix}#{$color}) calc(var(--#{$prefix}bg-opacity, 1) * 100%), transparent) !important;
}

View File

@@ -170,40 +170,10 @@ By using a progress bar component as a background element, designers can create
Thanks to this you can create a nice looking statistics section:
{% capture html -%}
<div class="progressbg">
<div class="progress progressbg-progress">
<div class="progress-bar bg-primary-lt" style="width: 65%"></div>
</div>
<div class="progressbg-text">Poland</div>
<div class="progressbg-value">65%</div>
</div>
<div class="progressbg">
<div class="progress progressbg-progress">
<div class="progress-bar bg-primary-lt" style="width: 35%"></div>
</div>
<div class="progressbg-text">Germany</div>
<div class="progressbg-value">35%</div>
</div>
<div class="progressbg">
<div class="progress progressbg-progress">
<div class="progress-bar bg-primary-lt" style="width: 28%"></div>
</div>
<div class="progressbg-text">United Stated</div>
<div class="progressbg-value">28%</div>
</div>
<div class="progressbg">
<div class="progress progressbg-progress">
<div class="progress-bar bg-primary-lt" style="width: 20%"></div>
</div>
<div class="progressbg-text">United Kingdom</div>
<div class="progressbg-value">20%</div>
</div>
<div class="progressbg">
<div class="progress progressbg-progress">
<div class="progress-bar bg-primary-lt" style="width: 15%"></div>
</div>
<div class="progressbg-text">France</div>
<div class="progressbg-value">15%</div>
</div>
{% include "ui/progressbg.html" value="65" text="Poland" show-value=true %}
{% include "ui/progressbg.html" value="35" text="Germany" show-value=true %}
{% include "ui/progressbg.html" value="28" text="United Stated" show-value=true %}
{% include "ui/progressbg.html" value="20" text="United Kingdom" show-value=true %}
{% include "ui/progressbg.html" value="15" text="France" show-value=true %}
{%- endcapture %}
{% include "docs/example.html" html=html vertical card %}

View File

@@ -1,5 +1,6 @@
import { appFilters } from "../shared/e11ty/filters.mjs"
import { appData } from "../shared/e11ty/data.mjs";
import { appConfig } from "../shared/e11ty/config.mjs";
import { readFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url'
import { join, dirname } from 'node:path';
@@ -13,6 +14,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
export default function (eleventyConfig) {
const environment = process.env.NODE_ENV || "production";
appConfig(eleventyConfig);
appFilters(eleventyConfig);
appData(eleventyConfig);
@@ -29,11 +31,6 @@ export default function (eleventyConfig) {
});
eleventyConfig.setInputDirectory("content");
eleventyConfig.setOutputDirectory("dist");
eleventyConfig.setLayoutsDirectory("../../shared/layouts");
eleventyConfig.setIncludesDirectory("../../shared/includes");
eleventyConfig.setDataDirectory("../../shared/data");
eleventyConfig.amendLibrary('md', () => { });

View File

@@ -25,7 +25,7 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@11ty/eleventy": "^3.1.2",
"@11ty/eleventy": "3.1.0",
"@docsearch/css": "^3.9.0",
"@docsearch/js": "^3.9.0",
"flat-cache": "^6.1.11",

View File

@@ -3,6 +3,7 @@
: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);
@@ -25,6 +26,80 @@
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;
}

View File

@@ -37,7 +37,7 @@
"glob": "^11.0.3",
"js-beautify": "^1.15.4",
"nodemon": "^3.1.10",
"pnpm": "10.6.5",
"pnpm": "^10.6.5",
"postcss": "^8.5.6",
"postcss-cli": "^11.0.1",
"prettier": "^3.6.2",
@@ -49,4 +49,4 @@
"terser": "^5.43.1",
"turbo": "^2.5.4"
}
}
}

170
pnpm-lock.yaml generated
View File

@@ -67,7 +67,7 @@ importers:
specifier: ^3.1.10
version: 3.1.10
pnpm:
specifier: 10.6.5
specifier: ^10.6.5
version: 10.6.5
postcss:
specifier: ^8.5.6
@@ -106,8 +106,8 @@ importers:
specifier: ^2.11.8
version: 2.11.8
bootstrap:
specifier: 5.3.7
version: 5.3.7(@popperjs/core@2.11.8)
specifier: 5.3.8
version: 5.3.8(@popperjs/core@2.11.8)
devDependencies:
'@hotwired/turbo':
specifier: ^8.0.13
@@ -137,11 +137,11 @@ importers:
specifier: ^4.6.13
version: 4.6.13
fslightbox:
specifier: ^3.6.1
version: 3.6.1
specifier: ^3.7.4
version: 3.7.4
fullcalendar:
specifier: ^6.1.18
version: 6.1.18
specifier: ^6.1.19
version: 6.1.19
hugerte:
specifier: ^1.0.9
version: 1.0.9
@@ -161,11 +161,14 @@ importers:
specifier: ^15.8.1
version: 15.8.1
plyr:
specifier: ^3.7.8
version: 3.7.8
specifier: ^3.8.3
version: 3.8.3
signature_pad:
specifier: ^5.0.10
version: 5.0.10
specifier: ^5.1.1
version: 5.1.1
sortablejs:
specifier: ^1.15.6
version: 1.15.6
star-rating.js:
specifier: ^4.3.1
version: 4.3.1
@@ -183,8 +186,8 @@ importers:
version: link:../core
devDependencies:
'@11ty/eleventy':
specifier: ^3.1.2
version: 3.1.2
specifier: 3.1.0
version: 3.1.0
'@docsearch/css':
specifier: ^3.9.0
version: 3.9.0
@@ -204,12 +207,12 @@ importers:
specifier: workspace:*
version: link:../core
'@tabler/icons':
specifier: ^3.31.0
version: 3.31.0
specifier: ^3.34.1
version: 3.34.1
devDependencies:
'@11ty/eleventy':
specifier: ^3.1.1
version: 3.1.2
specifier: 3.1.0
version: 3.1.0
imageoptim-cli:
specifier: ^3.1.9
version: 3.1.9
@@ -238,8 +241,8 @@ packages:
resolution: {integrity: sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==}
engines: {node: '>=18'}
'@11ty/eleventy@3.1.2':
resolution: {integrity: sha512-IcsDlbXnBf8cHzbM1YBv3JcTyLB35EK88QexmVyFdVJVgUU6bh9g687rpxryJirHzo06PuwnYaEEdVZQfIgRGg==}
'@11ty/eleventy@3.1.0':
resolution: {integrity: sha512-yR8zE+i5GKXTlR4I6Aj8dywI7f2/6uGhJPwgbH4vgh+XcZQ9zba9UMS/1Lyvkbl3UySRSAmlzeYiXi1ypV6oZg==}
engines: {node: '>=18'}
hasBin: true
@@ -509,33 +512,33 @@ packages:
'@emnapi/runtime@1.4.3':
resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
'@fullcalendar/core@6.1.18':
resolution: {integrity: sha512-cD7XtZIZZ87Cg2+itnpsONCsZ89VIfLLDZ22pQX4IQVWlpYUB3bcCf878DhWkqyEen6dhi5ePtBoqYgm5K+0fQ==}
'@fullcalendar/core@6.1.19':
resolution: {integrity: sha512-z0aVlO5e4Wah6p6mouM0UEqtRf1MZZPt4mwzEyU6kusaNL+dlWQgAasF2cK23hwT4cmxkEmr4inULXgpyeExdQ==}
'@fullcalendar/daygrid@6.1.18':
resolution: {integrity: sha512-s452Zle1SdMEzZDw+pDczm8m3JLIZzS9ANMThXTnqeqJewW1gqNFYas18aHypJSgF9Fh9rDJjTSUw04BpXB/Mg==}
'@fullcalendar/daygrid@6.1.19':
resolution: {integrity: sha512-IAAfnMICnVWPjpT4zi87i3FEw0xxSza0avqY/HedKEz+l5MTBYvCDPOWDATpzXoLut3aACsjktIyw9thvIcRYQ==}
peerDependencies:
'@fullcalendar/core': ~6.1.18
'@fullcalendar/core': ~6.1.19
'@fullcalendar/interaction@6.1.18':
resolution: {integrity: sha512-f/mD5RTjzw+Q6MGTMZrLCgIrQLIUUO9NV/58aM2J6ZBQZeRlNizDqmqldqyG+j49zj2vFhUfZibPrVKWm5yA4Q==}
'@fullcalendar/interaction@6.1.19':
resolution: {integrity: sha512-GOciy79xe8JMVp+1evAU3ytdwN/7tv35t5i1vFkifiuWcQMLC/JnLg/RA2s4sYmQwoYhTw/p4GLcP0gO5B3X5w==}
peerDependencies:
'@fullcalendar/core': ~6.1.18
'@fullcalendar/core': ~6.1.19
'@fullcalendar/list@6.1.18':
resolution: {integrity: sha512-XPZI50mq3HXyDQ5sT3jmqQUuwG8zQb5H14dQIUAmOHAIFRA3WpkxlzrXO0U1SrosvGySMPyyNNxvMKI1Q/jL7A==}
'@fullcalendar/list@6.1.19':
resolution: {integrity: sha512-knZHpAVF0LbzZpSJSUmLUUzF0XlU/MRGK+Py2s0/mP93bCtno1k2L3XPs/kzh528hSjehwLm89RgKTSfW1P6cA==}
peerDependencies:
'@fullcalendar/core': ~6.1.18
'@fullcalendar/core': ~6.1.19
'@fullcalendar/multimonth@6.1.18':
resolution: {integrity: sha512-4WSqtheJgWQMcJZjDDwTCYHe1JWTGZyJdCbIs84DuKbwZWH96g07Kr/3xDwsxiHgVX0iFlwljtkp2OmtMxQoDA==}
'@fullcalendar/multimonth@6.1.19':
resolution: {integrity: sha512-YYP8o/tjNLFRKhelwiq5ja3Jm3WDf3bfOUHf32JvAWwfotCvZjD7tYv66Nj02mQ8OWWJINa2EQGJxFHgIs14aA==}
peerDependencies:
'@fullcalendar/core': ~6.1.18
'@fullcalendar/core': ~6.1.19
'@fullcalendar/timegrid@6.1.18':
resolution: {integrity: sha512-T/ouhs+T1tM8JcW7Cjx+KiohL/qQWKqvRITwjol8ktJ1e1N/6noC40/obR1tyolqOxMRWHjJkYoj9fUqfoez9A==}
'@fullcalendar/timegrid@6.1.19':
resolution: {integrity: sha512-OuzpUueyO9wB5OZ8rs7TWIoqvu4v3yEqdDxZ2VcsMldCpYJRiOe7yHWKr4ap5Tb0fs7Rjbserc/b6Nt7ol6BRg==}
peerDependencies:
'@fullcalendar/core': ~6.1.18
'@fullcalendar/core': ~6.1.19
'@hotwired/turbo@8.0.13':
resolution: {integrity: sha512-M7qXUqcGab6G5PKOiwhgbByTtrPgKPFCTMNQ52QhzUEXEqmp0/ApEguUesh/FPiUjrmFec+3lq98KsWnYY2C7g==}
@@ -996,8 +999,8 @@ packages:
'@swc/helpers@0.2.14':
resolution: {integrity: sha512-wpCQMhf5p5GhNg2MmGKXzUNwxe7zRiCsmqYsamez2beP7mKPCSiu+BjZcdN95yYSzO857kr0VfQewmGpS77nqA==}
'@tabler/icons@3.31.0':
resolution: {integrity: sha512-dblAdeKY3+GA1U+Q9eziZ0ooVlZMHsE8dqP0RkwvRtEsAULoKOYaCUOcJ4oW1DjWegdxk++UAt2SlQVnmeHv+g==}
'@tabler/icons@3.34.1':
resolution: {integrity: sha512-9gTnUvd7Fd/DmQgr3MKY+oJLa1RfNsQo8c/ir3TJAWghOuZXodbtbVp0QBY2DxWuuvrSZFys0HEbv1CoiI5y6A==}
'@types/estree@1.0.7':
resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
@@ -1170,8 +1173,8 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
bootstrap@5.3.7:
resolution: {integrity: sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==}
bootstrap@5.3.8:
resolution: {integrity: sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==}
peerDependencies:
'@popperjs/core': ^2.11.8
@@ -1336,8 +1339,8 @@ packages:
core-js-pure@3.42.0:
resolution: {integrity: sha512-007bM04u91fF4kMgwom2I5cQxAFIy8jVulgr9eozILl/SZE53QOqnW/+vviC+wQWLv+AunBG+8Q0TLoeSsSxRQ==}
core-js@3.42.0:
resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==}
core-js@3.45.1:
resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==}
core-util-is@1.0.2:
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
@@ -1704,11 +1707,11 @@ packages:
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
fslightbox@3.6.1:
resolution: {integrity: sha512-iuKZS7Wm8AF6sJtn9iMsvtrNRZ9zR1WfktwoKnvH+IHWyPMnbBptlvSLTka7fAWAW9uI17MOWkbjbrer9LrX+Q==}
fslightbox@3.7.4:
resolution: {integrity: sha512-zQqMHxiYkR0W/xrWQlchoO626C5KCM6rabpMWiJsy+MZCMHo7zlywsGAOGeOahRUqBZzXT9OeMddiVSfW77gaA==}
fullcalendar@6.1.18:
resolution: {integrity: sha512-jwZrCleBhY78j+uBf97FW2rgzjH6nmCpfx0p0m+XSNPZrKWbsk759ri1QWXS3PoISrHjcU5wFM4dRPP9inp5Pg==}
fullcalendar@6.1.19:
resolution: {integrity: sha512-/DsMLYyU1kdOVojaV+ITNH2cHlHtyt6X3m4P6hhH0kwfHZpQbXajJnDbnFIufu/BdE9YcknMRPJj3R7FbPkg1A==}
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -2440,8 +2443,8 @@ packages:
please-upgrade-node@3.2.0:
resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==}
plyr@3.7.8:
resolution: {integrity: sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==}
plyr@3.8.3:
resolution: {integrity: sha512-0+iI5uw0WRvtKBpgPCkmQQv7ucHVQKTEo6UFJjgJ8cy/JZhy0dQqshHQVitHXV6l2O3MzhgnuvQ95VSkWcWeSw==}
pnpm@10.6.5:
resolution: {integrity: sha512-zfko/KIIMs1Z7FOCZJK33CXcUk1DcLa0rb9lgD0y76psHIgUfArk6NV5psnuxxV1e1DU+jXuoXnYaOraTtBDrw==}
@@ -2748,8 +2751,8 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
signature_pad@5.0.10:
resolution: {integrity: sha512-t7rLjpAtxYAIrTHr7EKfY8ulTWF+G/LFMto502a61KZvZNWZSwhTPeLE6171YMDd2sSYRBwQ17ENK5huAi9Rsg==}
signature_pad@5.1.1:
resolution: {integrity: sha512-BT5JJygS5BS0oV+tffPRorIud6q17bM7v/1LdQwd0o6mTqGoI25yY1NjSL99OqkekWltS4uon6p52Y8j1Zqu7g==}
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
@@ -2770,6 +2773,9 @@ packages:
resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==}
engines: {node: '>=8.0.0'}
sortablejs@1.15.6:
resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==}
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -3169,7 +3175,7 @@ snapshots:
dependencies:
'@11ty/eleventy-utils': 2.0.7
chokidar: 3.6.0
debug: 4.4.0(supports-color@5.5.0)
debug: 4.4.1
finalhandler: 1.3.1
mime: 3.0.0
minimist: 1.2.8
@@ -3187,7 +3193,7 @@ snapshots:
'@11ty/eleventy-plugin-bundle@3.0.6(posthtml@0.16.6)':
dependencies:
'@11ty/eleventy-utils': 2.0.7
debug: 4.4.0(supports-color@5.5.0)
debug: 4.4.1
posthtml-match-helper: 2.0.3(posthtml@0.16.6)
transitivePeerDependencies:
- posthtml
@@ -3195,7 +3201,7 @@ snapshots:
'@11ty/eleventy-utils@2.0.7': {}
'@11ty/eleventy@3.1.2':
'@11ty/eleventy@3.1.0':
dependencies:
'@11ty/dependency-tree': 4.0.0
'@11ty/dependency-tree-esm': 2.0.0
@@ -3685,31 +3691,31 @@ snapshots:
tslib: 2.8.1
optional: true
'@fullcalendar/core@6.1.18':
'@fullcalendar/core@6.1.19':
dependencies:
preact: 10.12.1
'@fullcalendar/daygrid@6.1.18(@fullcalendar/core@6.1.18)':
'@fullcalendar/daygrid@6.1.19(@fullcalendar/core@6.1.19)':
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/core': 6.1.19
'@fullcalendar/interaction@6.1.18(@fullcalendar/core@6.1.18)':
'@fullcalendar/interaction@6.1.19(@fullcalendar/core@6.1.19)':
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/core': 6.1.19
'@fullcalendar/list@6.1.18(@fullcalendar/core@6.1.18)':
'@fullcalendar/list@6.1.19(@fullcalendar/core@6.1.19)':
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/core': 6.1.19
'@fullcalendar/multimonth@6.1.18(@fullcalendar/core@6.1.18)':
'@fullcalendar/multimonth@6.1.19(@fullcalendar/core@6.1.19)':
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/daygrid': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/core': 6.1.19
'@fullcalendar/daygrid': 6.1.19(@fullcalendar/core@6.1.19)
'@fullcalendar/timegrid@6.1.18(@fullcalendar/core@6.1.18)':
'@fullcalendar/timegrid@6.1.19(@fullcalendar/core@6.1.19)':
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/daygrid': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/core': 6.1.19
'@fullcalendar/daygrid': 6.1.19(@fullcalendar/core@6.1.19)
'@hotwired/turbo@8.0.13': {}
@@ -4095,7 +4101,7 @@ snapshots:
'@swc/helpers@0.2.14': {}
'@tabler/icons@3.31.0': {}
'@tabler/icons@3.34.1': {}
'@types/estree@1.0.7': {}
@@ -4270,7 +4276,7 @@ snapshots:
binary-extensions@2.3.0: {}
bootstrap@5.3.7(@popperjs/core@2.11.8):
bootstrap@5.3.8(@popperjs/core@2.11.8):
dependencies:
'@popperjs/core': 2.11.8
@@ -4454,7 +4460,7 @@ snapshots:
core-js-pure@3.42.0: {}
core-js@3.42.0: {}
core-js@3.45.1: {}
core-util-is@1.0.2: {}
@@ -4793,16 +4799,16 @@ snapshots:
fsevents@2.3.3:
optional: true
fslightbox@3.6.1: {}
fslightbox@3.7.4: {}
fullcalendar@6.1.18:
fullcalendar@6.1.19:
dependencies:
'@fullcalendar/core': 6.1.18
'@fullcalendar/daygrid': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/interaction': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/list': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/multimonth': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/timegrid': 6.1.18(@fullcalendar/core@6.1.18)
'@fullcalendar/core': 6.1.19
'@fullcalendar/daygrid': 6.1.19(@fullcalendar/core@6.1.19)
'@fullcalendar/interaction': 6.1.19(@fullcalendar/core@6.1.19)
'@fullcalendar/list': 6.1.19(@fullcalendar/core@6.1.19)
'@fullcalendar/multimonth': 6.1.19(@fullcalendar/core@6.1.19)
'@fullcalendar/timegrid': 6.1.19(@fullcalendar/core@6.1.19)
function-bind@1.1.2: {}
@@ -5477,9 +5483,9 @@ snapshots:
dependencies:
semver-compare: 1.0.0
plyr@3.7.8:
plyr@3.8.3:
dependencies:
core-js: 3.42.0
core-js: 3.45.1
custom-event-polyfill: 1.0.7
loadjs: 4.3.0
rangetouch: 2.0.1
@@ -5747,7 +5753,7 @@ snapshots:
send@1.2.0:
dependencies:
debug: 4.4.0(supports-color@5.5.0)
debug: 4.4.1
encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
@@ -5835,7 +5841,7 @@ snapshots:
signal-exit@4.1.0: {}
signature_pad@5.0.10: {}
signature_pad@5.1.1: {}
simple-swizzle@0.2.2:
dependencies:
@@ -5851,6 +5857,8 @@ snapshots:
slugify@1.6.6: {}
sortablejs@1.15.6: {}
source-map-js@1.2.1: {}
source-map-support@0.5.21:

View File

@@ -4,21 +4,17 @@ 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.setInputDirectory("pages");
eleventyConfig.setOutputDirectory("dist");
eleventyConfig.setLayoutsDirectory("../../shared/layouts");
eleventyConfig.setIncludesDirectory("../../shared/includes");
eleventyConfig.setDataDirectory("../../shared/data");
eleventyConfig.addPassthroughCopy({
"node_modules/@tabler/core/dist": "dist",
"pages/favicon.ico": "favicon.ico",
@@ -47,170 +43,7 @@ export default function (eleventyConfig) {
});
});
/**
* Filters
*/
eleventyConfig.addFilter("miliseconds_to_minutes", function (value) {
// Raturn 3:45 time format
const minutes = Math.floor(value / 60000);
const seconds = ((value % 60000) / 1000).toFixed(0);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
});
eleventyConfig.addFilter("relative", (page) => {
const segments = (page.url || '').replace(/^\//).split('/');
if (segments.length === 1) {
return '.';
} else {
return '../'.repeat(segments.length - 1).slice(0, -1);
}
});
eleventyConfig.addFilter("contains", (items, item) => {
return items && Array.isArray(items) && items.includes(item);
});
eleventyConfig.addFilter("concat_objects", function (object, object2) {
if (
object &&
object2 &&
typeof object === 'object' &&
typeof object2 === 'object' &&
!Array.isArray(object) &&
!Array.isArray(object2)
) {
return { ...object, ...object2 };
}
return object;
});
eleventyConfig.addFilter("replace_regex", function (input, regStr, replStr) {
const regex = new RegExp(regStr, 'gm');
return input.replace(regex, replStr);
});
eleventyConfig.addFilter("timestamp_to_date", function (timestamp) {
const date = new Date(timestamp * 1000); // Convert timestamp to milliseconds
return date.toISOString().split('T')[0]; // Extract the date in 'YYYY-MM-DD' format
});
eleventyConfig.addFilter("split_to_n", function (arr, n) {
const chunkSize = Math.round(arr.length / n);
const result = [];
for (let i = 0; i < arr.length; i += chunkSize) {
result.push(arr.slice(i, i + chunkSize));
}
return result;
})
eleventyConfig.addFilter("format_number", function (value) {
return value.toString()
.split('')
.reverse()
.reduce((acc, char, index) => {
if (index > 0 && index % 3 === 0) {
acc.push(',');
}
acc.push(char);
return acc;
}, [])
.reverse()
.join('');
});
function randomNumber(x, min = 0, max = 100, round = 0) {
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;
}
eleventyConfig.addFilter("random_date_ago", function (x, daysAgo = 100) {
const today = new Date();
const randomDaysAgo = randomNumber(x, 0, daysAgo);
today.setDate(today.getDate() - randomDaysAgo);
return today;
});
eleventyConfig.addFilter("random_date", function (x, startDate = null, endDate = null) {
const start = new Date(startDate ? startDate : '2024-01-01').getTime() / 1000;
const end = new Date(endDate ? endDate : '2024-12-30').getTime() / 1000;
const randomTimestamp = randomNumber(x, start, end);
return new Date(randomTimestamp * 1000);
});
eleventyConfig.addFilter("random_item", function (x, items) {
const index = randomNumber(x, 0, items.length - 1);
return items[index];
});
eleventyConfig.addFilter("random_number", randomNumber);
eleventyConfig.addFilter("first_letters", function capitalizeFirstLetter(string) {
return string.split(' ').map(word => word.charAt(0)).join('');
})
eleventyConfig.addFilter("uc_first", function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
})
eleventyConfig.addFilter("size", function (elem) {
if (elem instanceof Object) {
return Object.keys(elem).length;
}
return elem.length;
})
eleventyConfig.addFilter("first", function (elem) {
if (elem instanceof Object) {
return elem[Object.keys(elem)[0]];
}
return elem[0];
})
// time ago from today
eleventyConfig.addFilter("timeago", function (date) {
const seconds = Math.floor((new Date() - date) / 1000);
let interval = Math.floor(seconds / 31536000);
if (interval > 1) {
return interval + " years ago";
}
interval = Math.floor(seconds / 2592000);
if (interval > 1) {
return interval + " months ago";
}
interval = Math.floor(seconds / 86400);
if (interval > 1) {
return interval + " days ago";
}
interval = Math.floor(seconds / 3600);
if (interval > 1) {
return interval + " hours ago";
}
interval = Math.floor(seconds / 60);
if (interval > 1) {
return interval + " minutes ago";
}
if (seconds > 0) {
return Math.floor(seconds) + " seconds ago";
}
return "now";
})
/**
* Shortcodes
*/

View File

@@ -6,7 +6,7 @@
"build": "pnpm run clean && pnpm run css && pnpm run js && pnpm run html",
"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 --incremental",
"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-compile && pnpm run css-prefix && pnpm run css-minify",
@@ -31,13 +31,13 @@
"zip": "mkdir -p packages-zip && zip -r packages-zip/tabler-$(node -p \"require('./package.json').version\").zip demo/*"
},
"devDependencies": {
"@11ty/eleventy": "^3.1.1",
"@11ty/eleventy": "3.1.0",
"imageoptim-cli": "^3.1.9",
"request": "^2.88.2"
},
"dependencies": {
"@tabler/core": "workspace:*",
"@tabler/icons": "^3.31.0"
"@tabler/icons": "^3.34.1"
},
"prettier": {
"tabWidth": 2,

View File

@@ -6,12 +6,12 @@ layout: default
permalink: activity.html
---
<div class="row justify-content-center">
<div class="row">
<div class="col-8">
<div class="card">
<div class="card-body">
{% include "parts/activity.html" %}
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,193 @@
---
title: Email inbox
page-header: Inbox
page-menu: extra.email-inbox
layout: default
permalink: email-inbox.html
page-libs: [ hugerte]
---
<div class="card">
<div class="row g-0">
<div class="col-xxl-3 email-border border-end">
<div class="offcanvas-xxl offcanvas-start h-100 file-offcanvas" tabindex="-1" id="emailSidebaroffcanvas">
<div class="card-body h-100">
<div>
{% include "ui/button.html" icon="pencil" text="Compose" color="primary" class="d-none d-sm-block"
modal-id="new-email" %}
</div>
<div class="mt-3 nav nav-vertical">
<a href="#" class="nav-link text-danger fw-bold">
{% include "ui/icon.html" icon="inbox" class="me-2" %}
Inbox<span class="badge badge-danger ms-auto">{{ mails | size }}</span>
</a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="star" class="me-2" %}Starred</a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="clock" class="me-2" %}Snoozed</a>
<a href="#" class="nav-link ">{% include "ui/icon.html" icon="file" class="me-2" %}Draft<span class="badge badge-info ms-auto">32</span></a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="mail-up" class="me-2" %}Sent Mail</a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="trash" class="me-2" %}Trash</a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="tag" class="me-2" %}Important</a>
<a href="#" class="nav-link">{% include "ui/icon.html" icon="alert-octagon" class="me-2" %}Spam</a>
</div>
<div class="mt-4">
<h6 class="subheader">Labels</h6>
<div class="mt-2 nav nav-vertical">
<a href="#" class="nav-link">
<div class="badge bg-info me-2"></div> Updates
</a>
<a href="#" class="nav-link">
<div class="badge bg-warning me-2"></div> Friends
</a>
<a href="#" class="nav-link">
<div class="badge bg-success me-2"></div> Family
</a>
<a href="#" class="nav-link">
<div class="badge bg-primary me-2"></div> Social
</a>
<a href="#" class="nav-link">
<div class="badge bg-danger me-2"></div> Important
</a>
<a href="#" class="nav-link">
<div class="badge bg-purple me-2"></div> Promotions
</a>
</div>
</div>
<div class="mt-5">
<h6 class="subheader">Storage</h6>
{% include "ui/progress.html" value=46 max=100 class="my-2" %}
<p class="text-muted font-13 mb-0">7.02 GB (46%) of 15 GB used</p>
</div>
</div>
</div>
</div>
<div class="col-xxl-9">
<div class="card-body">
<div class="d-flex flex-wrap align-items-center gap-2">
<div class="d-xxl-none d-inline-flex">
<button class="btn btn-icon" type="button" data-bs-toggle="offcanvas"
data-bs-target="#emailSidebaroffcanvas" aria-controls="emailSidebaroffcanvas">
{% include "ui/icon.html" icon="menu-2" %}
</button>
</div>
<div class="btn-group">
{% 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 %}
</div>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
{% include "ui/icon.html" icon="folder" %}
</button>
<div class="dropdown-menu">
<span class="dropdown-header">Move to</span>
<a class="dropdown-item" href="#">Social</a>
<a class="dropdown-item" href="#">Promotions</a>
<a class="dropdown-item" href="#">Updates</a>
<a class="dropdown-item" href="#">Forums</a>
</div>
</div>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
{% include "ui/icon.html" icon="tag" %}
</button>
<div class="dropdown-menu">
<span class="dropdown-header">Label as:</span>
<a class="dropdown-item" href="#">Updates</a>
<a class="dropdown-item" href="#">Social</a>
<a class="dropdown-item" href="#">Promotions</a>
<a class="dropdown-item" href="#">Forums</a>
</div>
</div>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
{% include "ui/icon.html" icon="dots" %} More
</button>
<div class="dropdown-menu">
<span class="dropdown-header">More Options :</span>
<a class="dropdown-item" href="#">Mark as Unread</a>
<a class="dropdown-item" href="#">Add to Tasks</a>
<a class="dropdown-item" href="#">Add Star</a>
<a class="dropdown-item" href="#">Mute</a>
</div>
</div>
</div>
<div class="mt-3">
<ul class="email-list">
{% if mails and mails.size > 0 %}
{% for mail in mails %}
<li>
<div class="email-sender-info">
<div class="checkbox-wrapper-mail">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="mail-{{ mail.id }}">
<label class="form-check-label" for="mail-{{ mail.id }}"></label>
</div>
</div>
<span class="star-toggle">{% include "ui/icon.html" icon="star" %}</span>
<a href="#" class="email-title">{{ mail.sender }}</a>
</div>
<div class="email-content">
<a href="#" class="email-subject">{{ mail.subject }} &nbsp;&nbsp;
<span>{{ mail.preview }}</span>
</a>
<div class="email-date">{{ mail.date }}</div>
</div>
<div class="email-action-icons">
<ul class="list-inline">
<li class="list-inline-item">
<a href="#">{% include "ui/icon.html" icon="archive" %}</a>
</li>
<li class="list-inline-item">
<a href="#">{% include "ui/icon.html" icon="trash" %}</a>
</li>
<li class="list-inline-item">
<a href="#">
{% include "ui/icon.html" icon="mail-opened" class="email-action-icons-item" %}
</a>
</li>
<li class="list-inline-item">
<a href="#">{% include "ui/icon.html" icon="clock" %}</a>
</li>
</ul>
</div>
</li>
{% endfor %}
{% else %}
<li class="text-muted">No emails</li>
{% endif %}
</ul>
</div>
<div class="row">
<div class="col-7 mt-1">
Showing 1 - {{ mails | size }} of {{ mails | size }}
</div> <!-- end col-->
<div class="col-5">
<div class="btn-group float-end">
<button type="button" class="btn btn-icon">{% include "ui/icon.html" icon="chevron-left"
%}</button>
<button type="button" class="btn btn-icon">{% include "ui/icon.html" icon="chevron-right"
%}</button>
</div>
</div> <!-- end col-->
</div> <!-- end row-->
</div>
</div>
</div>
</div>
{% include "ui/modal.html" modal-id="new-email" %}

View File

@@ -45,7 +45,7 @@ permalink: form-elements.html
</div>
<div class="col-md-6">
<div class="card">
<div class="card h-100">
<div class="card-body">
<h3 class="card-title">Project ID</h3>
<p class="card-subtitle">Used when interacting with the API.</p>
@@ -80,13 +80,13 @@ permalink: form-elements.html
</div>
</div>
<div class="col-md-6">
<div class="col-12 col-lg-4">
{% include "cards/form/layout.html" %}
</div>
<div class="col-lg-4">
<div class="col-lg-8">
<div class="row row-cards">
<div class="col-12">
<div class="col-12 col-lg-6">
<div class="card">
<div class="card-header">
<h3 class="card-title">Input mask</h3>
@@ -127,8 +127,8 @@ permalink: form-elements.html
</div>
</div>
</div>
<div class="col-12">
<form class="card">
<div class="col-12 col-lg-6">
<form class="card h-100">
<div class="card-header">
<h3 class="card-title">My Profile</h3>
</div>
@@ -168,9 +168,9 @@ permalink: form-elements.html
</div>
</div>
<div class="col-lg-8">
<div class="col-lg-12">
<div class="row row-cards">
<div class="col-12">
<div class="col-12 col-lg-6">
<form class="card">
<div class="card-body">
<h3 class="card-title">Edit Profile</h3>
@@ -234,7 +234,7 @@ permalink: form-elements.html
</div>
</div>
<div class="col-md-12">
<div class="mb-3 mb-0">
<div class="mb-0">
<label class="form-label">About Me</label>
<textarea rows="5" class="form-control" placeholder="Here can be your description"
value="Mike">Oh so, your weak rhyme
@@ -250,8 +250,8 @@ But that's the difference in our opinions.</textarea>
</div>
</form>
</div>
<div class="col-12">
<div class="card">
<div class="col-12 col-lg-6">
<div class="card h-100">
<div class="card-header">
<h3 class="card-title">HTTP Request</h3>
</div>

View File

@@ -21,20 +21,24 @@ page-libs: [litepicker]
<form class="space-y">
<div class="row">
<div class="col-6">
<input type="text" placeholder="Name" class="form-control" />
<label class="form-label visually-hidden" for="basic-name">Name</label>
<input type="text" placeholder="Name" class="form-control" id="basic-name" name="name" />
</div>
<div class="col-6">
<input type="email" placeholder="Email address" class="form-control" />
<label class="form-label visually-hidden" for="basic-email">Email address</label>
<input type="email" placeholder="Email address" class="form-control" id="basic-email" name="email" />
</div>
</div>
<div>
<input type="password" placeholder="Password" class="form-control" />
<label class="form-label visually-hidden" for="basic-password">Password</label>
<input type="password" placeholder="Password" class="form-control" id="basic-password" name="password" />
</div>
<div>
<input type="password" placeholder="Confirm Password" class="form-control" />
<label class="form-label visually-hidden" for="basic-password-confirm">Confirm Password</label>
<input type="password" placeholder="Confirm Password" class="form-control" id="basic-password-confirm" name="password_confirm" />
</div>
<div>
@@ -55,31 +59,31 @@ page-libs: [litepicker]
<form>
<div class="space-y">
<div>
<label class="form-label">
<label class="form-label" for="example-first-name">
First Name
</label>
<input type="text" placeholder="Enter first name" class="form-control">
<input type="text" placeholder="Enter first name" class="form-control" id="example-first-name" name="first_name">
</div>
<div>
<label class="form-label">
<label class="form-label" for="example-last-name">
Last Name
</label>
<input type="text" placeholder="Enter last name" class="form-control">
<input type="text" placeholder="Enter last name" class="form-control" id="example-last-name" name="last_name">
</div>
<div>
<label class="form-label">
<label class="form-label" for="example-email">
Email
</label>
<input type="email" placeholder="Enter email address" class="form-control">
<input type="email" placeholder="Enter email address" class="form-control" id="example-email" name="email">
</div>
<div>
<label class="form-label">
<label class="form-label" for="example-subject">
Select Subject
</label>
<select class="form-select">
<select class="form-select" id="example-subject" name="subject">
<option>
Option 1
</option>
@@ -96,10 +100,10 @@ page-libs: [litepicker]
</div>
<div>
<label class="form-label">
<label class="form-label" for="example-message">
Message
</label>
<textarea placeholder="Enter your message" rows="6" class="form-control"></textarea>
<textarea placeholder="Enter your message" rows="6" class="form-control" id="example-message" name="message"></textarea>
</div>
<div>

View File

@@ -1,5 +1,6 @@
---
page-menu: home
layout: homepage
permalink: index.html
---

View File

@@ -46,9 +46,9 @@ permalink: job-listing.html
<div class="small text-secondary">Only show companies that can sponsor a visa</div>
</div>
<div class="form-label">Location</div>
<label class="form-label" for="job-location">Location</label>
<div class="mb-4">
<select class="form-select">
<select class="form-select" id="job-location" name="location">
<option>Anywhere</option>
<option>London</option>
<option>San Francisco</option>

View File

@@ -0,0 +1,9 @@
---
page-header: Narrow sidebar layout
page-menu: layout.sidebar-narrow
layout-sidebar: true
layout-sidebar-narrow: true
layout-hide-topbar: true
layout: homepage
permalink: layout-sidebar-narrow.html
---

View File

@@ -12,7 +12,7 @@ permalink: marketing/real-estate.html
<div class="col-xl-6 col-lg-8 text-center">
<form novalidate="" class="row row-cols-1 row-cols-md-auto g-3 align-items-center">
<div class="col flex-grow-1">
<input id="inputEmail" type="text" placeholder="Search properties near you..." class="form-control form-control-solid" />
<input id="inputEmail" type="text" placeholder="Search properties near you..." class="form-control form-control-solid" aria-label="Search properties near you" />
</div>
<div class="col"><button type="submit" class="btn btn-teal fw-500">Search</button></div>
</form>

View File

@@ -4,7 +4,7 @@ page-header: Modals
page-menu: base.modals
layout: default
permalink: modals.html
page-libs: [signature_pad]
page-libs: [signature_pad, hugerte]
---
<div class="card">
@@ -22,49 +22,54 @@ page-libs: [signature_pad]
<a href="#modal-danger" class="nav-link">Danger modal</a>
<a href="#modal-team" class="nav-link">Modal with simple form</a>
<a href="#modal-signature" class="nav-link">Modal with signature form</a>
<a href="#modal-new-email" class="nav-link">New email modal</a>
</div>
</div>
<div class="col">
<div class="space-y-6">
<div>
<h3>Simple modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="simple" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="simple" inline %}
</div>
<div>
<h3>Large modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="large" size="lg" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="large" size="lg" inline %}
</div>
<div>
<h3>Small modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="small" size="sm" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="small" size="sm" inline %}
</div>
<div>
<h3>Full width modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="full-width" size="full-width" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="full-width" size="full-width" inline %}
</div>
<div>
<h3>Scrollable modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="scrollable" scrollable=true style="max-height: 30rem" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="scrollable" scrollable=true style="max-height: 30rem" inline %}
</div>
<div>
<h3>Modal with form</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="report" size="lg" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="report" size="lg" inline %}
</div>
<div>
<h3>Success modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="success" size="sm" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="success" size="sm" inline %}
</div>
<div>
<h3>Danger modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="danger" size="sm" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="danger" size="sm" inline %}
</div>
<div>
<h3>Modal with simple form</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="team" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="team" inline %}
</div>
<div>
<h3>Modal with signature form</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto" modal-id="signature" inline %}
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="signature" inline %}
</div>
<div>
<h3>New email modal</h3>
{% include "ui/modal.html" class="position-relative rounded d-block show bg-surface-backdrop py-6 w-auto h-auto z-0" modal-id="new-email" inline %}
</div>
</div>
</div>

View File

@@ -0,0 +1,149 @@
---
layout: base
title: Onboarding
permalink: onboarding.html
---
<nav class="navbar">
<div class="container">
<div class="row w-100 align-items-center">
<div class="col me-auto">
{% include "layout/navbar-logo.html" class="logo-gray" %}
</div>
<div class="col-2">
{% include "ui/progress-steps.html" count=5 current=2 %}
</div>
<div class="col text-end">
<a href="{{ page.url | relative }}" class="btn btn-ghost">Skip<span class="d-none d-md-inline">&nbsp;to dashboard</span></a>
</div>
</div>
</div>
</nav>
<main class="py-5">
<div class="container container-tight">
<div class="page-header">
<h1 class="page-title">
Let's set up your account
</h1>
</div>
<div class="card mt-5">
<div class="card-body space-y-4">
<div>
<label class="form-label">Full name</label>
<input type="text" class="form-control" placeholder="Enter your full name">
</div>
<div>
<label class="form-label">Company name</label>
<input type="text" class="form-control" placeholder="Enter your company name">
</div>
<div>
<label class="form-label">Role</label>
<select class="form-select">
<option value="">Select your role</option>
<option value="developer">Developer</option>
<option value="designer">Designer</option>
<option value="manager">Manager</option>
<option value="founder">Founder</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label class="form-label">Team size</label>
<div class="form-selectgroup">
<label class="form-selectgroup-item">
<input type="radio" name="team-size" value="1" class="form-selectgroup-input" checked>
<span class="form-selectgroup-label">Just me</span>
</label>
<label class="form-selectgroup-item">
<input type="radio" name="team-size" value="2-10" class="form-selectgroup-input">
<span class="form-selectgroup-label">2-10 people</span>
</label>
<label class="form-selectgroup-item">
<input type="radio" name="team-size" value="11-50" class="form-selectgroup-input">
<span class="form-selectgroup-label">11-50 people</span>
</label>
<label class="form-selectgroup-item">
<input type="radio" name="team-size" value="50+" class="form-selectgroup-input">
<span class="form-selectgroup-label">50+ people</span>
</label>
</div>
</div>
<div>
<label class="form-label">What are you planning to use this for?</label>
<div class="form-check">
<input class="form-check-input" type="radio" value="personal" id="use-personal" checked>
<label class="form-check-label" for="use-personal">
Personal projects
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="business" id="use-business">
<label class="form-check-label" for="use-business">
Business applications
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="client" id="use-client">
<label class="form-check-label" for="use-client">
Client work
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" value="learning" id="use-learning">
<label class="form-check-label" for="use-learning">
Learning and experimentation
</label>
</div>
</div>
<div>
<label class="form-label">How did you hear about us?</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="referral" value="search" id="ref-search">
<label class="form-check-label" for="ref-search">
Search engine
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="referral" value="social" id="ref-social">
<label class="form-check-label" for="ref-social">
Social media
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="referral" value="friend" id="ref-friend">
<label class="form-check-label" for="ref-friend">
Friend or colleague
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="referral" value="blog" id="ref-blog">
<label class="form-check-label" for="ref-blog">
Blog or article
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="referral" value="other" id="ref-other">
<label class="form-check-label" for="ref-other">
Other
</label>
</div>
</div>
<div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="notifications" checked>
<label class="form-check-label" for="notifications">
Send me product updates and tips via email
</label>
</div>
</div>
</div>
</div>
<div class="btn-list justify-content-between mt-4">
{% include "ui/button.html" text="Back" color="link link-secondary" %}
{% include "ui/button.html" text="Continue" color="primary" %}
</div>
</div>
</main>

106
preview/pages/pay.html Normal file
View File

@@ -0,0 +1,106 @@
---
title: Pay
page-header: Pay
layout: pay
permalink: pay.html
page-libs: [tabler-payments, imask]
---
<div class="bg-dark bg-cover" style="background-image: url({{ page | relative }}/static/bg-cover.jpg)">
<div class="bg-dark bg-opacity-75 pt-5 bg-blur">
<div class="container container-tight bg-overlay">
<img src="{{ page | relative }}/static/bg-cover.jpg" alt="" class="img-fluid rounded-lg rounded-top">
</div>
</div>
</div>
<div class="container container-tight">
<div class="card rounded-top-0 border-top-0">
<div class="card-body pt-0">
<div class="mb-3 text-center">
{% include "ui/avatar.html" person-id=1 size="xl" rounded class="avatar-cover rounded-circle mb-3" %}
<div class="mb-4">
<h2 class="h2">Front-End Learning</h2>
<div class="text-secondary">Learn to build web apps with HTML & CSS. Get started quickly with included templates.
</div>
</div>
</div>
<nav class="nav nav-segmented w-100 mb-4" role="tablist">
<button href="#tab-card" class="nav-link active" data-bs-toggle="tab" role="tab" aria-controls="tab-card"
aria-selected="true">
{% include "ui/icon.html" icon="credit-card" %}
<span>Pay With Card</span>
</button>
<button href="#tab-paypal" class="nav-link" data-bs-toggle="tab" role="tab" aria-controls="tab-paypal"
aria-selected="false">
{% include "ui/icon.html" icon="brand-paypal" %}
<span>Pay With PayPal</span>
</button>
</nav>
<div class="tab-content">
<div class="tab-pane active show" id="tab-card" role="tabpanel">
<form>
<div class="space-y">
<div>
<label class="form-label" for="card-number">Card Number</label>
{% capture html -%}
{% include "ui/payment.html" payment="visa" size="xs" %}
{%- endcapture %}
{% include "ui/form/input-group.html" id="card-number-addon" prepend-html=html flat=true placeholder="0000 0000 0000 0000" %}
</div>
<div class="row g-3">
<div class="col-sm-6">
<label class="form-label" for="card-expiry">Expiry Date</label>
<input type="text" class="form-control" id="card-expiry" placeholder="MM/YY"
inputmode="numeric" aria-required="true" maxlength="5"/>
</div>
<div class="col-sm-6">
<label class="form-label" for="card-cvc">CVC</label>
<input type="text" class="form-control" id="card-cvc" placeholder="CVC" inputmode="numeric"
aria-required="true" maxlength="3"/>
</div>
</div>
<div>
<label class="form-label" for="card-name">Name on Card</label>
<input type="text" class="form-control" id="card-name" placeholder="Full name"
aria-required="true" />
</div>
<div>
<label class="form-label" for="card-email">Email</label>
<input type="email" class="form-control" id="card-email" placeholder="you@example.com"
aria-required="true" />
</div>
<div>
<button type="button" class="btn btn-primary w-100">
Pay $253
</button>
<div class="text-secondary text-center small mt-3">You'll be charged $253, including
$48 for VAT in Poland</div>
</div>
</div>
</form>
</div>
<div class="tab-pane" id="tab-paypal" role="tabpanel">
<button type="button" class="btn btn-primary w-100">
{% include "ui/icon.html" icon="brand-paypal" %}
<span class="ms-2">Pay with PayPal - $253</span>
</button>
<div class="text-secondary text-center small mt-3">You'll be charged $253, including $48 for VAT in
Poland</div>
</div>
</div>
</div>
</div>
</div>

270
preview/pages/progress.html Normal file
View File

@@ -0,0 +1,270 @@
---
layout: default
title: Progress
page-header: Progress
page-menu: base.progress
permalink: progress.html
---
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-3">
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Default</h3>
<div class="space-y">
{% include "ui/progress.html" value="0" %}
{% include "ui/progress.html" value="20" %}
{% include "ui/progress.html" value="40" %}
{% include "ui/progress.html" value="100" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">With value</h3>
<div class="space-y">
{% 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" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Colors</h3>
<div class="space-y">
{% 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" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Sizes</h3>
<div class="space-y">
{% 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" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Indeterminate</h3>
<div class="space-y">
{% include "ui/progress.html" indeterminate=true %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Multiple values</h3>
<div class="space-y">
{% include "ui/progress.html" values="20,30,10" %}
{% include "ui/progress.html" values="10,20,30,40" class="progress-separated" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Striped</h3>
<div class="space-y">
{% 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 %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">Animated</h3>
<div class="space-y">
{% 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 %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Animated with JavaScript
</h3>
<div class="row align-items-center g-0">
<div class="col">
{% include "ui/progress.html" value="0" id="progress-animated" %}
</div>
<div class="col-2 text-end" id="progress-animated-value">
0%
</div>
</div>
<div class="btn-list mt-3">
<button class="btn btn-sm" id="progress-animated-0">0%</button>
<button class="btn btn-sm" id="progress-animated-10">10%</button>
<button class="btn btn-sm" id="progress-animated-50">50%</button>
<button class="btn btn-sm" id="progress-animated-100">100%</button>
<button class="btn btn-sm ms-3" id="progress-animated-minus-10">-10%</button>
<button class="btn btn-sm" id="progress-animated-add-10">+10%</button>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Steps Progress
</h3>
<div class="space-y">
{% 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 %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Progress Background
</h3>
<div class="space-y">
{% 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 %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Progress Background Colors
</h3>
<div class="space-y">
{% 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 %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Progress Description
</h3>
<div class="space-y">
{% 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" %}
</div>
</div>
</div>
</div>
<div class="col">
<div class="card">
<div class="card-body">
<h3 class="card-title">
Progress Description Sizes
</h3>
<div class="space-y">
{% 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" %}
</div>
</div>
</div>
</div>
</div>
{% capture_script -%}
<!-- BEGIN SCRIPT OF ANIMATION -->
<script>
/*
This script is for animation of the last progress bar
It increases the progress bar value by a random amount every 2 seconds until it reaches 100%
When it reaches 100%, it changes the color to green and stops the animation
This is just a demo script to show how to animate the progress bar. You can modify it as needed.
*/
document.addEventListener("DOMContentLoaded", function () {
var width = 0;
var setWidth = function(w) {
width = Math.min(Math.max(w, 0), 100);
progress.querySelector('.progress-bar').style.width = width + '%';
progress.querySelector('.progress-bar').setAttribute('aria-valuenow', width);
document.getElementById('progress-animated-value').innerText = width + '%';
if (width >= 100) {
progress.querySelector('.progress-bar').classList.add('bg-green');
} else {
progress.querySelector('.progress-bar').classList.remove('bg-green');
}
}
var progress = document.getElementById('progress-animated');
var increment = 0;
var interval = setInterval(function () {
increment = Math.ceil(Math.random() * 10);
setWidth(width + increment);
if (width >= 100) {
clearInterval(interval);
}
}, 2000);
document.getElementById('progress-animated-0').addEventListener('click', function() {
setWidth(0);
});
document.getElementById('progress-animated-add-10').addEventListener('click', function() {
setWidth(width + 10);
});
document.getElementById('progress-animated-minus-10').addEventListener('click', function() {
setWidth(width - 10);
});
document.getElementById('progress-animated-100').addEventListener('click', function() {
setWidth(100);
});
});
</script>
<!-- END SCRIPT OF ANIMATION -->
{%- endcapture_script -%}

View File

@@ -19,16 +19,16 @@ permalink: settings.html
<div class="row g-3">
<div class="col-md">
<div class="form-label">Business Name</div>
<input type="text" class="form-control" value="{{ people[0].company }}">
<label class="form-label" for="business-name">Business Name</label>
<input type="text" class="form-control" id="business-name" name="business-name" value="{{ people[0].company }}">
</div>
<div class="col-md">
<div class="form-label">Business ID</div>
<input type="text" class="form-control" value="560afc32">
<label class="form-label" for="business-id">Business ID</label>
<input type="text" class="form-control" id="business-id" name="business-id" value="560afc32">
</div>
<div class="col-md">
<div class="form-label">Location</div>
<input type="text" class="form-control"
<label class="form-label" for="location">Location</label>
<input type="text" class="form-control" id="location" name="location"
value="{{ people[0].city }}, {{ people[0].country }}">
</div>
</div>
@@ -39,7 +39,8 @@ permalink: settings.html
<div>
<div class="row g-2">
<div class="col-auto">
<input type="text" class="form-control w-auto" value="{{ people[0].email }}">
<label for="email" class="form-label visually-hidden">Email</label>
<input type="text" class="form-control w-auto" id="email" name="email" value="{{ people[0].email }}">
</div>
<div class="col-auto">{% include "ui/button.html" text="Change" %}</div>
</div>

View File

@@ -13,12 +13,6 @@ signaturePad.fromDataURL("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3
{% capture advanced-js %}
function randomColor() {
const r = Math.round(Math.random() * 255);
const g = Math.round(Math.random() * 255);
const b = Math.round(Math.random() * 255);
return `rgb(${r},${g},${b})`;
}
function download(dataURL, filename) {
const blob = dataURLToBlob(dataURL);
@@ -49,9 +43,8 @@ function dataURLToBlob(dataURL) {
return new Blob([uInt8Array], { type: contentType });
}
document.querySelector("#signature-advanced-color").addEventListener("click", function () {
signaturePad.penColor = randomColor();
document.querySelector("#signature-advanced-color").addEventListener("input", function (e) {
signaturePad.penColor = e.target.value;
});
document.querySelector("#signature-advanced-svg").addEventListener("click", function () {
@@ -73,12 +66,12 @@ document.querySelector("#signature-advanced-png").addEventListener("click", func
<p class="card-subtitle">Please confirm the transfer of funds by signing below.</p>
<form action="">
<div class="mb-3">
<label class="form-label required">First name</label>
<input type="text" class="form-control" />
<label class="form-label required" for="signature-first-name">First name</label>
<input type="text" class="form-control" id="signature-first-name" name="first_name" />
</div>
<div class="mb-3">
<label class="form-label required">Last name</label>
<input type="text" class="form-control" />
<label class="form-label required" for="signature-last-name">Last name</label>
<input type="text" class="form-control" id="signature-last-name" name="last_name" />
</div>
<div class="mb-3">
<label class="form-label required">Signature</label>
@@ -112,7 +105,8 @@ document.querySelector("#signature-advanced-png").addEventListener("click", func
<div class="mt-4">
<div class="row">
<div class="col">
<button href="" class="btn w-100" id="signature-advanced-color">Change color</button>
<label for="signature-advanced-color" class="form-label visually-hidden">Pen color</label>
<input href="" type="color" id="signature-advanced-color" class="w-100 form-control form-control-color" />
</div>
<div class="col">
<button href="" class="btn w-100" id="signature-advanced-svg">Download SVG</button>

View File

@@ -0,0 +1,53 @@
---
title: Sortable
page-header: SortableJS
page-menu: plugins.sortable
page-libs: [sortablejs]
layout: default
permalink: sortable.html
---
<div class="row row-cards">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title">Podstawowe użycie</h3>
</div>
<div class="card-body">
<ul class="list-group" data-sortable='{"animation":150}'>
<li class="list-group-item">Element A</li>
<li class="list-group-item">Element B</li>
<li class="list-group-item">Element C</li>
<li class="list-group-item">Element D</li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h3 class="card-title">Dwie listy z przenoszeniem</h3>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-sm-6">
<ul class="list-group" data-sortable='{"group":"shared","animation":150}'>
<li class="list-group-item">Item 1</li>
<li class="list-group-item">Item 2</li>
<li class="list-group-item">Item 3</li>
</ul>
</div>
<div class="col-sm-6">
<ul class="list-group" data-sortable='{"group":"shared","animation":150}'>
<li class="list-group-item">Item A</li>
<li class="list-group-item">Item B</li>
<li class="list-group-item">Item C</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,56 +1,250 @@
[
{
"text": "<strong>%p</strong> commented on your <strong>\"I'm not a witch.\"</strong> post."
"text": "<strong>%p</strong> commented on your post: <strong>Not everything is what it seems</strong>",
"icon": "message-circle"
},
{
"text": "It's <strong>%p</strong>'s birthday. Wish him well!"
"text": "It's <strong>%p</strong>'s birthday today",
"icon": "cake"
},
{
"text": "<strong>%p</strong> posted <strong>\"Well, what do you want?\"</strong>."
"text": "<strong>%p</strong> posted a status: <strong>Trying to figure things out one step at a time.</strong>",
"icon": "pencil"
},
{
"text": "<strong>%p</strong> created a new project <strong>Morning alarm clock</strong>."
"text": "<strong>%p</strong> created a new project: <strong>Smart Morning Alarm</strong>",
"icon": "alarm"
},
{
"text": "<strong>%p</strong> liked your photo."
"text": "<strong>%p</strong> liked your photo",
"icon": "heart"
},
{
"text": "<strong>%p</strong> registered new client as <strong>%c</strong>."
"text": "<strong>%p</strong> registered a new client: <strong>Trilia Solutions</strong>",
"icon": "user-plus"
},
{
"text": "<strong>%p</strong> closed a new deal on project <strong>Pen Pineapple Apple Pen</strong>."
"text": "<strong>%p</strong> closed a new deal on project: <strong>PPAP Campaign Strategy</strong>",
"icon": "handshake"
},
{
"text": "<strong>%p</strong> created a new project for <strong>%c</strong>."
"text": "<strong>%p</strong> created a new project: <strong>Wikibox Knowledge Platform</strong>",
"icon": "folder-plus"
},
{
"text": "<strong>%p</strong> change status of <strong>Tabler Icons</strong> from <strong>open</strong> to <strong>closed</strong>."
"text": "<strong>%p</strong> changed project status of <strong>Tabler Icons</strong> from <strong>open</strong> to <strong>closed</strong>",
"icon": "check"
},
{
"text": "<strong>%p</strong> liked <strong>Tabler UI Kit</strong>."
"text": "<strong>%p</strong> liked the <strong>Tabler UI Kit</strong>",
"icon": "thumb-up"
},
{
"text": "<strong>%p</strong> posted new video."
"text": "<strong>%p</strong> shared a new video: <strong>Design Tips for Busy Creators</strong>",
"icon": "video"
},
{
"text": "<strong>%p</strong> and 3 others followed you."
"text": "<strong>%p</strong> and <strong>3 others</strong> followed you",
"icon": "user-plus"
},
{
"text": "<strong>%p</strong> upload 3 new photos to category <strong>Inspirations</strong>."
"text": "<strong>%p</strong> uploaded <strong>3 new photos</strong> to category: <strong>Creative Inspirations</strong>",
"icon": "photo"
},
{
"text": "<strong>%p</strong> made a <strong>$10</strong> donation."
"text": "<strong>%p</strong> made a <strong>$10 donation</strong>",
"icon": "coin"
},
{
"text": "<strong>%p</strong> created a profile."
"text": "<strong>%p</strong> created a profile",
"icon": "id"
},
{
"text": "<strong>%p</strong> hosted the event <strong>Tabler UI Birthday</strong>."
"text": "<strong>%p</strong> hosted the event: <strong>Tabler UI Anniversary</strong>",
"icon": "calendar-event"
},
{
"text": "<strong>%p</strong> mentioned you on <strong>Best of 2020</strong>."
"text": "<strong>%p</strong> mentioned you in <strong>Best of 2020 Highlights</strong>",
"icon": "at"
},
{
"text": "<strong>%p</strong> sent a Review Request to <strong>Amanda Blake</strong>."
"text": "<strong>%p</strong> sent a review request to <strong>Amanda Blake</strong>",
"icon": "send"
},
{
"text": "<strong>%p</strong> posted a photo from her vacation in <strong>Tuscany</strong>",
"icon": "camera"
},
{
"text": "<strong>%p</strong> shared an article: <strong>Top 10 productivity hacks</strong>",
"icon": "book"
},
{
"text": "<strong>%p</strong> commented on your photo",
"icon": "message-circle"
},
{
"text": "<strong>%p</strong> joined the group: <strong>UX Designers Hub</strong>",
"icon": "users"
},
{
"text": "<strong>%p</strong> uploaded new design mockups",
"icon": "layout"
},
{
"text": "<strong>%p</strong> reacted with ❤️ to your story",
"icon": "emoji-heart-eyes"
},
{
"text": "<strong>%p</strong> posted a video: <strong>Building Better Dashboards</strong>",
"icon": "video"
},
{
"text": "<strong>%p</strong> joined your webinar: <strong>Intro to TypeScript</strong>",
"icon": "presentation"
},
{
"text": "<strong>%p</strong> commented: <strong>This is so helpful!</strong>",
"icon": "message-circle"
},
{
"text": "<strong>%p</strong> updated her profile photo",
"icon": "user-edit"
},
{
"text": "<strong>%p</strong> posted a job listing: <strong>Frontend Developer</strong>",
"icon": "briefcase"
},
{
"text": "<strong>%p</strong> started following your project: <strong>Clean Code Patterns</strong>",
"icon": "code"
},
{
"text": "<strong>%p</strong> gave feedback on your latest design",
"icon": "message-check"
},
{
"text": "<strong>%p</strong> shared a playlist: <strong>Coding Flow</strong>",
"icon": "music"
},
{
"text": "<strong>%p</strong> joined the event: <strong>Night UI Meetup</strong>",
"icon": "calendar-plus"
},
{
"text": "<strong>%p</strong> shared a memory: <strong>2 years at Tabler!</strong>",
"icon": "history"
},
{
"text": "<strong>%p</strong> retweeted your latest post",
"icon": "repeat"
},
{
"text": "<strong>%p</strong> shared your story to their network",
"icon": "share"
},
{
"text": "<strong>%p</strong> invited you to collaborate on her workspace",
"icon": "user-plus"
},
{
"text": "<strong>%p</strong> published a new blog post: <strong>Dark Mode for All</strong>",
"icon": "article"
},
{
"text": "<strong>%p</strong> mentioned you in a comment",
"icon": "at"
},
{
"text": "<strong>%p</strong> shared a new design: <strong>Modern Dashboard UI</strong>",
"icon": "layout"
},
{
"text": "<strong>%p</strong> completed the course: <strong>Advanced React Patterns</strong>",
"icon": "certificate"
},
{
"text": "<strong>%p</strong> started a new discussion: <strong>Best practices for mobile UI</strong>",
"icon": "message-square"
},
{
"text": "<strong>%p</strong> reached <strong>1000 followers</strong> milestone",
"icon": "trophy"
},
{
"text": "<strong>%p</strong> published a tutorial: <strong>Building Responsive Components</strong>",
"icon": "book-open"
},
{
"text": "<strong>%p</strong> organized a workshop: <strong>Design System Fundamentals</strong>",
"icon": "users-group"
},
{
"text": "<strong>%p</strong> contributed to <strong>Open Source Project</strong>",
"icon": "git-branch"
},
{
"text": "<strong>%p</strong> received a <strong>5-star review</strong> on their latest work",
"icon": "star"
},
{
"text": "<strong>%p</strong> launched a new product: <strong>TaskFlow Pro</strong>",
"icon": "rocket"
},
{
"text": "<strong>%p</strong> joined the mentorship program",
"icon": "graduation-cap"
},
{
"text": "<strong>%p</strong> created a design challenge: <strong>Minimalist Dashboard</strong>",
"icon": "target"
},
{
"text": "<strong>%p</strong> won the <strong>Design Award 2024</strong>",
"icon": "award"
},
{
"text": "<strong>%p</strong> started a podcast: <strong>Design & Development</strong>",
"icon": "microphone"
},
{
"text": "<strong>%p</strong> completed a <strong>30-day design challenge</strong>",
"icon": "calendar-check"
},
{
"text": "<strong>%p</strong> became a <strong>verified designer</strong>",
"icon": "badge-check"
},
{
"text": "<strong>%p</strong> published a case study: <strong>Redesigning E-commerce UX</strong>",
"icon": "file-text"
},
{
"text": "<strong>%p</strong> hosted a live stream: <strong>Design Q&A Session</strong>",
"icon": "video-plus"
},
{
"text": "<strong>%p</strong> created a design system: <strong>Component Library v2.0</strong>",
"icon": "library"
},
{
"text": "<strong>%p</strong> reached <strong>50k downloads</strong> on their template",
"icon": "download"
},
{
"text": "<strong>%p</strong> started a newsletter: <strong>Weekly Design Insights</strong>",
"icon": "mail"
},
{
"text": "<strong>%p</strong> collaborated on <strong>Community Design Project</strong>",
"icon": "users"
},
{
"text": "<strong>%p</strong> published a research paper: <strong>UI/UX Trends 2024</strong>",
"icon": "file-search"
},
{
"text": "<strong>%p</strong> became a <strong>featured creator</strong>",
"icon": "crown"
}
]

View File

@@ -1,44 +1,332 @@
[
{
"title": "And this isn't my nose. This is a false one.",
"description": "Look, my liege! The Knights Who Say Ni demand a sacrifice! …Are you suggesting that coconuts migrate? Well, I got better.",
"title": "How to Build a Modern Web App with Vue 3",
"description": "Learn the fundamentals of Vue 3 and Composition API by creating a fully functional, modern web application from scratch.",
"tags": [
"vue",
"javascript",
"frontend"
],
"image": 14,
"author": 3
"author": 10
},
{
"title": "Well, I didn't vote for you.",
"description": "Well, we did do the nose. Why? Shut up! Will you shut up?! 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!",
"image": 15,
"author": 4
"title": "10 UX Principles Every Designer Should Know",
"description": "A concise guide to user experience best practices, helping you design more intuitive and user-friendly interfaces.",
"tags": [
"ux",
"design",
"usability"
],
"image": 5,
"author": 8
},
{
"title": "How do you know she is a witch?",
"description": "Are you suggesting that coconuts migrate? No, no, no! Yes, yes. A bit. But she's got a wart. You don't vote for kings. Ah, now we see the violence inherent in the system!",
"title": "Optimizing JavaScript Performance in Large-Scale Projects",
"description": "Explore techniques and tools to improve the speed and maintainability of your JavaScript applications at scale.",
"tags": [
"javascript",
"performance",
"best-practices"
],
"image": 19,
"author": 14
},
{
"title": "The Future of CSS: What's Coming in 2025",
"description": "Get an early look at the next generation of CSS features and how they'll transform modern web development.",
"tags": [
"css",
"future",
"web-development"
],
"image": 3,
"author": 11
},
{
"title": "Understanding TypeScript: A Beginner's Guide",
"description": "This article walks you through the basics of TypeScript, helping you write safer and more scalable JavaScript code.",
"tags": [
"typescript",
"javascript",
"beginner"
],
"image": 16,
"author": 5
},
{
"title": "Shut up!",
"description": "Burn her! How do you know she is a witch? 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!",
"image": 17,
"title": "Building a Design System with Tailwind CSS",
"description": "Learn how to create a consistent, reusable design system using utility-first CSS with Tailwind.",
"tags": [
"tailwind",
"design-system",
"css"
],
"image": 22,
"author": 6
},
{
"title": "Weaseling out of things is important to learn.",
"description": "Please do not offer my god a peanut. That's why I love elementary school, Edna. The children believe anything you tell them. Brace yourselves gentlemen. According to the gas chromatograph, the secret ingredient is… Love!? Who's been screwing with this thing?",
"title": "5 Mistakes to Avoid in Web Accessibility",
"description": "Avoid common accessibility pitfalls and make your website inclusive for all users.",
"tags": [
"a11y",
"accessibility",
"html"
],
"image": 12,
"author": 7
},
{
"title": "Deploying Your App with Vercel and GitHub Actions",
"description": "A step-by-step guide to automating your deployment process using GitHub Actions and Vercel.",
"tags": [
"devops",
"vercel",
"ci/cd"
],
"image": 2,
"author": 15
},
{
"title": "A Dive into Reactive Programming with RxJS",
"description": "Understand the core concepts of reactive programming and learn how to use RxJS in real-world scenarios.",
"tags": [
"rxjs",
"reactive",
"javascript"
],
"image": 17,
"author": 4
},
{
"title": "Creating Stunning Data Visualizations with D3.js",
"description": "Learn how to transform complex data into interactive, beautiful charts using D3.js.",
"tags": [
"d3",
"data-viz",
"charts"
],
"image": 8,
"author": 12
},
{
"title": "State Management in Vue 3 with Pinia",
"description": "Pinia is the new official store library for Vue—here's how to use it effectively.",
"tags": [
"vue",
"pinia",
"state-management"
],
"image": 21,
"author": 3
},
{
"title": "Dark Mode in CSS: Best Practices",
"description": "Implementing dark mode isn't just about switching colors. Learn how to do it right with CSS variables and media queries.",
"tags": [
"css",
"dark-mode",
"ui"
],
"image": 7,
"author": 13
},
{
"title": "Next.js vs Nuxt 3: A Head-to-Head Comparison",
"description": "Comparing the most popular frameworks for React and Vue. Which one should you choose?",
"tags": [
"nextjs",
"nuxt",
"frameworks"
],
"image": 15,
"author": 6
},
{
"title": "Progressive Web Apps: How to Make Your Website Installable",
"description": "Turn your web project into a PWA and reach users offline or on mobile devices.",
"tags": [
"pwa",
"web-apps",
"offline"
],
"image": 11,
"author": 9
},
{
"title": "Using Figma for Developer Handoff",
"description": "Bridge the gap between designers and developers by mastering Figma's handoff features.",
"tags": [
"figma",
"design",
"workflow"
],
"image": 9,
"author": 14
},
{
"title": "Improving Lighthouse Scores with Modern Techniques",
"description": "A practical guide to fixing common issues and optimizing your site for better Lighthouse results.",
"tags": [
"performance",
"seo",
"lighthouse"
],
"image": 6,
"author": 2
},
{
"title": "Animating Interfaces with Framer Motion",
"description": "Bring your UI to life with simple, declarative animations using Framer Motion.",
"tags": [
"react",
"animations",
"framer-motion"
],
"image": 1,
"author": 7
},
{
"title": "GraphQL vs REST: Which Should You Choose?",
"description": "Breaking down the pros and cons of GraphQL and REST to help you pick the right API design.",
"tags": [
"graphql",
"rest",
"api"
],
"image": 13,
"author": 16
},
{
"title": "Building a Blog with Astro and Markdown",
"description": "Leverage Astro's performance and use Markdown to create a fast, flexible blog.",
"tags": [
"astro",
"markdown",
"static-sites"
],
"image": 10,
"author": 5
},
{
"title": "Why You Should Use CSS Container Queries",
"description": "The long-awaited feature is here. Learn how to use container queries to write smarter, more responsive CSS.",
"tags": [
"css",
"container-queries",
"responsive"
],
"image": 18,
"author": 11
},
{
"title": "Mastering React Server Components: A Complete Guide",
"description": "Dive deep into React Server Components and learn how to build faster, more efficient applications with this revolutionary feature.",
"tags": [
"react",
"server-components",
"performance"
],
"image": 4,
"author": 8
},
{
"title": "Building Micro-Frontends with Module Federation",
"description": "Learn how to break down monolithic frontend applications into smaller, independently deployable micro-frontends.",
"tags": [
"micro-frontends",
"webpack",
"architecture"
],
"image": 20,
"author": 12
},
{
"title": "You don't like your job, you don't strike.",
"description": "But, Aquaman, you cannot marry a woman without gills. You're from two different worlds… Oh, I've wasted my life. Son, when you participate in sporting events, it's not whether you win or lose: it's how drunk you get.",
"image": 21,
"title": "The Complete Guide to CSS Grid Layout",
"description": "Master CSS Grid Layout with practical examples and real-world use cases for modern web layouts.",
"tags": [
"css",
"grid",
"layout"
],
"image": 23,
"author": 9
},
{
"title": "Testing React Applications with Vitest and Testing Library",
"description": "Set up a modern testing environment for React applications using Vitest and React Testing Library.",
"tags": [
"react",
"testing",
"vitest"
],
"image": 24,
"author": 15
},
{
"title": "Building Scalable APIs with Fastify and TypeScript",
"description": "Create high-performance APIs using Fastify and TypeScript with best practices for production applications.",
"tags": [
"fastify",
"typescript",
"api"
],
"image": 25,
"author": 6
},
{
"title": "Implementing Authentication with NextAuth.js",
"description": "Add secure authentication to your Next.js applications with NextAuth.js and multiple provider support.",
"tags": [
"nextjs",
"authentication",
"security"
],
"image": 26,
"author": 11
},
{
"title": "Optimizing Images for the Web: A Developer's Guide",
"description": "Learn modern techniques for optimizing images, including WebP, AVIF, and responsive image strategies.",
"tags": [
"images",
"performance",
"webp"
],
"image": 27,
"author": 14
},
{
"title": "Building Interactive Maps with Mapbox and React",
"description": "Create stunning, interactive maps for your web applications using Mapbox GL JS and React.",
"tags": [
"maps",
"react",
"mapbox"
],
"image": 28,
"author": 7
},
{
"title": "Mastering CSS Custom Properties and Theming",
"description": "Build flexible design systems with CSS custom properties and create dynamic theming solutions.",
"tags": [
"css",
"theming",
"design-system"
],
"image": 29,
"author": 13
},
{
"title": "I hope I didn't brain my damage.",
"description": "I don't like being outdoors, Smithers. For one thing, there's too many fat children. Oh, loneliness and cheeseburgers are a dangerous mix. Jesus must be spinning in his grave! I hope this has taught you kids a lesson: kids never learn.",
"image": 22,
"author": 14
"title": "Building Real-Time Applications with Socket.io",
"description": "Create real-time features like chat, notifications, and live updates using Socket.io and Node.js.",
"tags": [
"socket.io",
"real-time",
"nodejs"
],
"image": 30,
"author": 10
}
]

132
shared/data/channels.json Normal file
View File

@@ -0,0 +1,132 @@
[
{
"channel": "Facebook",
"icon": "brand-facebook",
"visitors": 11873,
"revenues": 8423.78,
"sales": 336,
"conversion": 2.83,
"bounceRate": 45.6,
"sessionDuration": 183,
"pagesPerSession": 3.1,
"costPerAcquisition": 7.22,
"clickThroughRate": 1.8
},
{
"channel": "Github",
"icon": "brand-github",
"visitors": 5372,
"revenues": 4876.12,
"sales": 188,
"conversion": 3.50,
"bounceRate": 32.4,
"sessionDuration": 246,
"pagesPerSession": 4.5,
"costPerAcquisition": 5.75,
"clickThroughRate": 2.1
},
{
"channel": "Twitter",
"icon": "brand-twitter",
"visitors": 7941,
"revenues": 6184.39,
"sales": 272,
"conversion": 3.42,
"bounceRate": 39.1,
"sessionDuration": 174,
"pagesPerSession": 3.3,
"costPerAcquisition": 6.90,
"clickThroughRate": 1.6
},
{
"channel": "LinkedIn",
"icon": "brand-linkedin",
"visitors": 3127,
"revenues": 2748.56,
"sales": 121,
"conversion": 3.87,
"bounceRate": 28.9,
"sessionDuration": 209,
"pagesPerSession": 4.0,
"costPerAcquisition": 6.10,
"clickThroughRate": 2.3
},
{
"channel": "Instagram",
"icon": "brand-instagram",
"visitors": 9442,
"revenues": 7632.91,
"sales": 308,
"conversion": 3.26,
"bounceRate": 41.2,
"sessionDuration": 192,
"pagesPerSession": 3.4,
"costPerAcquisition": 6.15,
"clickThroughRate": 1.9
},
{
"channel": "Reddit",
"icon": "brand-reddit",
"visitors": 4347,
"revenues": 3311.34,
"sales": 147,
"conversion": 3.38,
"bounceRate": 46.8,
"sessionDuration": 167,
"pagesPerSession": 2.9,
"costPerAcquisition": 7.10,
"clickThroughRate": 1.5
},
{
"channel": "YouTube",
"icon": "brand-youtube",
"visitors": 14856,
"revenues": 10573.44,
"sales": 393,
"conversion": 2.64,
"bounceRate": 38.7,
"sessionDuration": 221,
"pagesPerSession": 3.6,
"costPerAcquisition": 6.55,
"clickThroughRate": 2.0
},
{
"channel": "Pinterest",
"icon": "brand-pinterest",
"visitors": 3879,
"revenues": 2824.07,
"sales": 132,
"conversion": 3.40,
"bounceRate": 36.2,
"sessionDuration": 195,
"pagesPerSession": 3.7,
"costPerAcquisition": 6.00,
"clickThroughRate": 1.7
},
{
"channel": "TikTok",
"icon": "brand-tiktok",
"visitors": 8749,
"revenues": 6887.63,
"sales": 293,
"conversion": 3.35,
"bounceRate": 43.0,
"sessionDuration": 181,
"pagesPerSession": 3.2,
"costPerAcquisition": 6.40,
"clickThroughRate": 1.8
},
{
"channel": "Dribbble",
"icon": "brand-dribbble",
"visitors": 2623,
"revenues": 2113.28,
"sales": 99,
"conversion": 3.78,
"bounceRate": 29.6,
"sessionDuration": 204,
"pagesPerSession": 4.1,
"costPerAcquisition": 5.90,
"clickThroughRate": 2.2
}
]

View File

@@ -4,5 +4,15 @@
"She is so damn beautiful OMG i love her!!! does somebody knows what kind of music is this? sorry xD",
"Did anyone go camping in Oshkosh Wisconsin last month?",
"Hey i am subbed but i didnt get the notification how?",
"This is the best by far! I laughed for the hole sticking time 😂"
"This is the best by far! I laughed for the hole sticking time 😂",
"Can't stop watching this! The vibes are immaculate ✨",
"Who else is here from the algorithm? This popped up and I'm obsessed now 🔥",
"The editing in this is absolutely insane! How do you do it? 🤯",
"Finally found my new favorite channel! Subscribed immediately 💯",
"This gives me such good memories from last summer... anyone else? 🌞",
"The way you captured that moment is pure magic! Love it so much 🥰",
"Can we get a part 2? I need more of this content in my life! 🙏",
"This is exactly what I needed today, thank you for sharing! 💖",
"The quality is amazing! What camera do you use? 📸",
"This made my day so much better, sending good vibes back! ✌️"
]

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
{"version":"3.31.0","count":5880}
{"version":"3.34.1","count":5945}

File diff suppressed because one or more lines are too long

202
shared/data/mails.json Normal file
View File

@@ -0,0 +1,202 @@
[
{
"id": "e1",
"sender": "Lucas, me (4)",
"senderEmail": "lucas@example.com",
"subject": "Direct message on Twitter",
"preview": "@LucasKriebel - Very cool :) You have a new direct message. Open Twitter to read and reply now.",
"labels": ["Social"],
"starred": true,
"date": "2025-08-27T11:49:00Z"
},
{
"id": "e2",
"sender": "Acme Support",
"senderEmail": "support@acme.io",
"subject": "Your ticket #48213 has been updated",
"preview": "Hi, we've added a detailed note to your request regarding billing. Please review the update and let us know if anything looks off.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-26T09:15:00Z"
},
{
"id": "e3",
"sender": "Marketing Weekly",
"senderEmail": "news@marketingweekly.com",
"subject": "10 growth tactics you can try today",
"preview": "We curated a list of actionable ideas from top marketers to boost acquisition, retention, and activation this quarter.",
"labels": ["Promotions"],
"starred": false,
"date": "2025-08-25T17:02:00Z"
},
{
"id": "e4",
"sender": "GitHub",
"senderEmail": "noreply@github.com",
"subject": "[tabler] New issue assigned to you",
"preview": "Issue #3294: Update email inbox page to use data file. Please triage, add labels, and provide an estimate.",
"labels": ["Important", "Updates"],
"starred": true,
"date": "2025-08-25T08:41:00Z"
},
{
"id": "e5",
"sender": "me (2), Stripe",
"senderEmail": "no-reply@stripe.com",
"subject": "Payout scheduled",
"preview": "A payout of $1,248.32 is scheduled for tomorrow. Funds typically arrive within 2 business days.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-24T12:30:00Z"
},
{
"id": "e6",
"sender": "Figma",
"senderEmail": "team@figma.com",
"subject": "You were invited to a file",
"preview": "Anna shared Inbox redesign v3 with you. Review the latest components and leave feedback in comments.",
"labels": ["Social"],
"starred": false,
"date": "2025-08-24T07:58:00Z"
},
{
"id": "e7",
"sender": "Calendly",
"senderEmail": "no-reply@calendly.com",
"subject": "Event confirmed for Fri 3 PM",
"preview": "Your meeting with Chris is confirmed for this Friday at 3 PM. A calendar invite with the video link was attached.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-23T14:21:00Z"
},
{
"id": "e8",
"sender": "Twitter",
"senderEmail": "notify@twitter.com",
"subject": "New followers this week",
"preview": "You gained 27 new followers. See who followed you and engage with their posts to grow reach.",
"labels": ["Social"],
"starred": false,
"date": "2025-08-23T06:12:00Z"
},
{
"id": "e9",
"sender": "Product Hunt",
"senderEmail": "hello@producthunt.com",
"subject": "Today's top launches",
"preview": "Catch up on trending products you might like. Today's list features tools for design and developer productivity.",
"labels": ["Promotions"],
"starred": false,
"date": "2025-08-22T19:33:00Z"
},
{
"id": "e10",
"sender": "Notion",
"senderEmail": "team@notion.so",
"subject": "Weekly summary: Inbox project",
"preview": "3 tasks completed, 2 comments, 1 new page added. Click through to see highlights and next steps.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-22T08:00:00Z"
},
{
"id": "e11",
"sender": "AWS",
"senderEmail": "no-reply@aws.amazon.com",
"subject": "Billing alert threshold reached",
"preview": "Your usage exceeded the alert threshold for this month. Consider upgrading your plan or adjusting limits.",
"labels": ["Important"],
"starred": true,
"date": "2025-08-21T18:45:00Z"
},
{
"id": "e12",
"sender": "LinkedIn",
"senderEmail": "messages-noreply@linkedin.com",
"subject": "Someone viewed your profile",
"preview": "See who looked at your profile this week. Strengthen your network by following up with recent viewers.",
"labels": ["Social"],
"starred": false,
"date": "2025-08-21T10:27:00Z"
},
{
"id": "e13",
"sender": "Google Alerts",
"senderEmail": "noreply-alerts@google.com",
"subject": "Alert for: Tabler UI",
"preview": "New articles mentioning Tabler UI were found. Skim the summaries and set alerts for related keywords.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-20T16:14:00Z"
},
{
"id": "e14",
"sender": "Medium",
"senderEmail": "noreply@medium.com",
"subject": "Stories you might like",
"preview": "Handpicked stories based on your reading history. Discover deep dives on design systems and UX workflows.",
"labels": ["Promotions"],
"starred": false,
"date": "2025-08-20T07:05:00Z"
},
{
"id": "e15",
"sender": "Slack",
"senderEmail": "feedback@slack.com",
"subject": "Missed messages in #design",
"preview": "You have 14 unread messages across 3 channels. Catch up now to keep the conversation moving.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-19T21:43:00Z"
},
{
"id": "e16",
"sender": "Sentry",
"senderEmail": "alerts@sentry.io",
"subject": "New error: TypeError in preview",
"preview": "Tabler preview threw TypeError: cannot read properties of undefined. Investigate stack trace and recent commits.",
"labels": ["Important", "Updates"],
"starred": true,
"date": "2025-08-19T11:20:00Z"
},
{
"id": "e17",
"sender": "Dribbble",
"senderEmail": "no-reply@dribbble.com",
"subject": "New shots from designers you follow",
"preview": "A fresh batch of inspiration is here. Explore new shots and save your favorites to collections.",
"labels": ["Social"],
"starred": false,
"date": "2025-08-18T15:37:00Z"
},
{
"id": "e18",
"sender": "Airbnb",
"senderEmail": "express@airbnb.com",
"subject": "Plan your next getaway",
"preview": "Deals on stays you'll love this fall. Flexible dates and free cancellation on many options.",
"labels": ["Promotions"],
"starred": false,
"date": "2025-08-18T06:50:00Z"
},
{
"id": "e19",
"sender": "Google Calendar",
"senderEmail": "calendar-notification@google.com",
"subject": "Reminder: Standup in 10 minutes",
"preview": "Daily standup starts at 9:30 AM. Share yesterday's progress, today's plan, and blockers.",
"labels": ["Updates"],
"starred": false,
"date": "2025-08-17T09:20:00Z"
},
{
"id": "e20",
"sender": "Superstore",
"senderEmail": "offers@superstore.com",
"subject": "Exclusive 25% off for you",
"preview": "Save big on electronics this weekend only. Limited quantities—use code WEEKEND25 at checkout.",
"labels": ["Promotions"],
"starred": false,
"date": "2025-08-16T13:00:00Z"
}
]

View File

@@ -159,6 +159,11 @@
"url": "placeholder.html",
"title": "Placeholder"
},
"progress": {
"url": "progress.html",
"title": "Progress",
"badge": "New"
},
"segmented-control": {
"title": "Segmented control",
"url": "segmented-control.html",
@@ -231,6 +236,11 @@
"title": "Chat",
"url": "chat.html"
},
"email-inbox": {
"title": "Email inbox",
"url": "email-inbox.html",
"badge": "New"
},
"cookie-banner": {
"title": "Cookie banner",
"url": "cookie-banner.html"
@@ -251,6 +261,10 @@
"title": "Invoice",
"url": "invoice.html"
},
"pay": {
"title": "Pay",
"url": "pay.html"
},
"job-listing": {
"title": "Job listing",
"url": "job-listing.html"
@@ -410,6 +424,10 @@
"title": "Dropzone",
"url": "dropzone.html"
},
"sortable": {
"title": "Sortable",
"url": "sortable.html"
},
"fullcalendar": {
"url": "fullcalendar.html",
"title": "Fullcalendar"

View File

@@ -0,0 +1,170 @@
[
{
"id": "1",
"title": "New order received",
"description": "Order #12345 has been placed by John Doe",
"type": "order",
"status": "unread",
"priority": "high",
"icon": "shopping-cart",
"color": "success",
"timestamp": "2025-01-15T10:30:00Z",
"user_id": "123",
"action_url": "/orders/12345",
"is_important": true
},
{
"id": "2",
"title": "Payment failed",
"description": "Payment for order #12340 failed. Please review payment details.",
"type": "payment",
"status": "unread",
"priority": "critical",
"icon": "alert-triangle",
"color": "danger",
"timestamp": "2025-01-15T09:15:00Z",
"user_id": "456",
"action_url": "/payments/12340",
"is_important": true
},
{
"id": "3",
"title": "System maintenance",
"description": "Scheduled maintenance will begin in 2 hours. Expected downtime: 30 minutes.",
"type": "system",
"status": "unread",
"priority": "medium",
"icon": "settings",
"color": "warning",
"timestamp": "2025-01-15T08:45:00Z",
"user_id": null,
"action_url": "/maintenance",
"is_important": false
},
{
"id": "4",
"title": "New customer registered",
"description": "Sarah Johnson has created a new account",
"type": "user",
"status": "read",
"priority": "low",
"icon": "user-plus",
"color": "info",
"timestamp": "2025-01-15T07:20:00Z",
"user_id": "789",
"action_url": "/customers/789",
"is_important": false
},
{
"id": "5",
"title": "Inventory alert",
"description": "Product 'Premium Widget' is running low on stock (5 items remaining)",
"type": "inventory",
"status": "unread",
"priority": "high",
"icon": "package",
"color": "warning",
"timestamp": "2025-01-15T06:30:00Z",
"user_id": null,
"action_url": "/inventory/premium-widget",
"is_important": true
},
{
"id": "6",
"title": "Support ticket resolved",
"description": "Ticket #TKT-2025-001 has been resolved by support team",
"type": "support",
"status": "read",
"priority": "medium",
"icon": "message-circle",
"color": "success",
"timestamp": "2025-01-15T05:45:00Z",
"user_id": "234",
"action_url": "/support/tickets/TKT-2025-001",
"is_important": false
},
{
"id": "7",
"title": "Security alert",
"description": "Unusual login activity detected from new location",
"type": "security",
"status": "unread",
"priority": "critical",
"icon": "shield",
"color": "danger",
"timestamp": "2025-01-15T04:15:00Z",
"user_id": "567",
"action_url": "/security/activity",
"is_important": true
},
{
"id": "8",
"title": "Backup completed",
"description": "Daily backup has been completed successfully",
"type": "system",
"status": "read",
"priority": "low",
"icon": "database",
"color": "success",
"timestamp": "2025-01-15T03:00:00Z",
"user_id": null,
"action_url": "/system/backups",
"is_important": false
},
{
"id": "9",
"title": "New review received",
"description": "5-star review received for product 'Deluxe Package'",
"type": "review",
"status": "unread",
"priority": "medium",
"icon": "star",
"color": "success",
"timestamp": "2025-01-15T02:30:00Z",
"user_id": "890",
"action_url": "/reviews/deluxe-package",
"is_important": false
},
{
"id": "10",
"title": "API rate limit warning",
"description": "API usage is approaching the rate limit (85% used)",
"type": "system",
"status": "unread",
"priority": "medium",
"icon": "activity",
"color": "warning",
"timestamp": "2025-01-15T01:45:00Z",
"user_id": null,
"action_url": "/api/usage",
"is_important": true
},
{
"id": "11",
"title": "Refund processed",
"description": "Refund for order #12335 has been processed and sent to customer",
"type": "refund",
"status": "read",
"priority": "medium",
"icon": "refresh-ccw",
"color": "info",
"timestamp": "2025-01-15T00:20:00Z",
"user_id": "345",
"action_url": "/refunds/12335",
"is_important": false
},
{
"id": "12",
"title": "New feature available",
"description": "Advanced analytics dashboard is now available for all users",
"type": "feature",
"status": "unread",
"priority": "low",
"icon": "bar-chart",
"color": "info",
"timestamp": "2025-01-14T23:10:00Z",
"user_id": null,
"action_url": "/features/analytics",
"is_important": false
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,22 @@
{
"css": "sha384-LUZmhPrA9DuvV+PENAthWDl8vR3wEHZ2mxCp6V4VEbbCIDjvxx2RlvvYjfSZZ+Fe",
"css-rtl": "sha384-R+1hmp3uvF0kkOZyoxDNAnLplv2bfSkdzNMujFi7fbvcu+l5L15NMKg50UT7SHD0",
"css-flags": "sha384-H7p4Cgh2RM3r9apL63WdIpPu9BtIhbGngx0f3WrqyCpunfY+X7M4apXpQQcZqA5c",
"css-flags-rtl": "sha384-tzddSAu/YEPdL4FEjR4HwaKan3DhU5kQ+ifJOWa0kR7eb1RUmPKr8PHEx1Hmgx+t",
"css-marketing": "sha384-jdZv/iHkc5OuAPy1SD9QancYje5FHhs4s1GL7AOvKdb6ZMiC+Zwya8pCGDBb7tIf",
"css-marketing-rtl": "sha384-MfCU8754hWY2IAkf1SVH5helVjarYxM1zeyxecKh2AuQcacQzKz+7dxQoWN074ca",
"css-payments": "sha384-sCkGfjP5FkkIIL7H3FNIhYK1ZvUwMQeOLVSfOblaDQoKZX8k71BHZk1LMHMPRjbx",
"css-payments-rtl": "sha384-gZtxDQ2AdE1j/+cmuiPWY+AJ0jtnsk2C3Z65u+uyzQkqfISW1V7Blezfumdm/mfj",
"css-socials": "sha384-bujgRtkeNSwK8hFfCUO6SyIyWngJuWblefHIViyjq5XbDAEeCi1YRlIqggw9Vcqu",
"css-socials-rtl": "sha384-SIYJowkbADF1DNCVS7QnO0WDOPI7xOulE2iUJ5do1VveCIHslxNnE7lYyXbHMqtH",
"css-props": "sha384-eFBhxMcWpvjSKfWwkdzIeMzXUt2j6d0od1+xwAYsUAtAlBK0SK/tZl9xbx624xxx",
"css-props-rtl": "sha384-ifUxJ+Cmg0A/0cl51AAiC0TsP2kvHrBMyGxIsHWT3sPmZzu0PGHf0Pc3YwmoUWkT",
"css-themes": "sha384-EWgzD0j3PnZ9hhq/YFnSNV/Hm54BB0hWYSSCEj6OR1YxP0BVDEM7Enp+UAJDMqBx",
"css-themes-rtl": "sha384-rzVwsvFoVNK25vTMMkUuO71ndLJIhoMtvnaA9BKDBa2s+lboMuDmnHX/ikLmdgqv",
"css-vendors-rtl": "sha384-bD4REzS6v/hyJgKgmqVmDd/HSu5y3dsZ4hQYcdYQqEOKQDLUEyqiWAWYq/NObB8B",
"css-vendors": "sha384-yYQlhpXu43M9F6EsDV1V/GQBPy9gQSKTTkvRiSnKEbUjI3/RhmpARqgI9pUTU6Z9",
"js": "sha384-2WdYXbwTs+5LXi+OUvcthfGsTS1s8P9lt6uUbrglmYVhAsPSh1ItGCmXkpzSR34u",
"js-theme": "sha384-owIUMWnQZ6WJM5sJcZYopxE42XrqqKivlpxysxQYM+RXYbaHGAWVo2aniM4Wyhxq",
"css": "sha384-b08Yxo9kzlsLLcHA4bMBkC8EAIBeP3G8rhhIT584owzLn88bcWJkSVtGZMc78Rax",
"css-rtl": "sha384-EVH/sV9+QVa/y7Vl1JFsVYjru0/gKkqDf8zBqdfu2R8t84BwCBeV7jsu7kQ93abg",
"css-flags": "sha384-kmvP0hkBXZ2hMSZlbvE1Q2HIXzPCQRL3ijUeqNiwaPd2nl2Aks+s3gW+V5fAHOX9",
"css-flags-rtl": "sha384-Q/h6koANGclsGnwB8rvF8h84H54NKHDeNWFj6yiE4WLLEXyHcz+Zu6Afkh2ssYTC",
"css-marketing": "sha384-4dAlYnPzCom9yeC/5++PFq2FG/szJRlUPsDSrjZ3EWP8IAzK7g7rrsnSfqrS67Se",
"css-marketing-rtl": "sha384-c6gNhuNYjp+lqluSdArbL8ciLEBq7IVU00XnPM2Eogj8RAjMapccvOM/pGhk3vV6",
"css-payments": "sha384-xWIXbKxPLGG/ZEGUKxDjJn3xmUgd2PC2CSZUKJ4PyTse49DiuvJx2WT5wSNJRyw9",
"css-payments-rtl": "sha384-69CxgA+uEPtM07SLA8MMAdnBmwtVGndDJf8nIPdfvNrDayBfPqOK3wS3nvV5yyk+",
"css-socials": "sha384-eWmz8gyiLzrDw3JcT/PJxjGyKizQjvByfHqocjrMMkIrbKFCnOuP/qMwAz3bHmsC",
"css-socials-rtl": "sha384-yobKDIyTOxB1z7t/uZ2ImuXrcKWF24vDYg2vR1n7x2msF09iWnvyIxQtfEl9+OFl",
"css-props": "sha384-HpzBfAj1xJcNLtdedYZunJBHqgdO12KqrCrc6/7pmKDiP8YmUF71cm+iGBtVawWM",
"css-props-rtl": "sha384-/vKK+yuQsAI8lJmR4uothydKQAHFK+fp1QrbJnfk2deAzII9WUj3h5rXUxZPyUAo",
"css-themes": "sha384-jTe/MdN6BlY4S3eYe6Qw++yTjuezmVnxWp/l7GAG1qXGC+jttphHqsAN/bGPvJOk",
"css-themes-rtl": "sha384-WTp4aZ+OGqnkNR6Xe0sJwwfd0JHGq3dZTLU2ITKxTK2zjcJTBUMY/+Z4eXgm8ipF",
"css-vendors-rtl": "sha384-V555LUGE2xyN4wNbzdVMgsajsKmJdlLFm20Ws72jEyPiSsTXXITV0PebNzVeBjnb",
"css-vendors": "sha384-+X7+c/noY2B9ieq9daEaVStkUhIFyJTO5T6Occ6jZisx57sbECetvloLqcvGahUv",
"js": "sha384-pku3birjgGovaJ9ngF7SaxKkF/eYUvBjiMJ+jTtWbNesIj2Rud2K63+4JD7EF4gk",
"js-theme": "sha384-SoDJmj40r6f9Rfxi6Fq+bNS8ofhlZMyxHk9dq9Y8e1M17PZGkBRN/XUpx8swn0i5",
"demo-css": "sha384-BUDq2P684xwRBf0GDlySvob+KJg4ko8y2K7njgvYBscmEuqoVVqJ75zcTDozwkFA",
"demo-js": "sha384-UcTgbM9IZSOPHHuFa0R9H4TegQWoZkJKpeTjLV5hjem2k0CZ67Q4/bW2rT/Edf4Z"
}

View File

@@ -0,0 +1,422 @@
[
{
"id": "1",
"counterparty": "Form Builder CP",
"counterparty_logo": "static/brands/form-builder.svg",
"payment_date": "2025-01-22",
"status_name": "pending",
"status": "warning",
"amount": -1299.22,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual subscription renewal",
"reference": "FB-2025-001"
},
{
"id": "2",
"counterparty": "Imperial Hotel ****",
"counterparty_logo": "static/brands/hotel.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -1029.77,
"currency": "USD",
"transaction_type": "hotel",
"category": "travel",
"description": "Hotel accommodation for business trip",
"reference": "IH-2025-002"
},
{
"id": "3",
"counterparty": "Aprilynne Pills",
"counterparty_logo": "static/avatars/000m.jpg",
"payment_date": "2025-01-22",
"status_name": "pending",
"status": "warning",
"amount": 499.99,
"currency": "USD",
"transaction_type": "refund",
"category": "healthcare",
"description": "Refund for cancelled prescription",
"reference": "AP-2025-003"
},
{
"id": "4",
"counterparty": "Google Limited UK",
"counterparty_logo": "static/brands/google.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -1029.77,
"currency": "USD",
"transaction_type": "advertising",
"category": "marketing",
"description": "Google Ads campaign payment",
"reference": "GL-2025-004"
},
{
"id": "5",
"counterparty": "Acme LTD UK",
"counterparty_logo": "static/brands/acme.svg",
"payment_date": "2025-01-22",
"status_name": "pending",
"status": "warning",
"amount": 2179.36,
"currency": "USD",
"transaction_type": "payment",
"category": "business",
"description": "Payment received for consulting services",
"reference": "AL-2025-005"
},
{
"id": "6",
"counterparty": "Google Limited UK",
"counterparty_logo": "static/brands/google.svg",
"payment_date": "2025-01-22",
"status_name": "canceled",
"status": "danger",
"amount": -1029.77,
"currency": "USD",
"transaction_type": "advertising",
"category": "marketing",
"description": "Cancelled Google Ads campaign",
"reference": "GL-2025-006"
},
{
"id": "7",
"counterparty": "Uber",
"counterparty_logo": "static/brands/uber.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -272.88,
"currency": "USD",
"transaction_type": "transport",
"category": "travel",
"description": "Ride sharing service",
"reference": "UB-2025-007"
},
{
"id": "8",
"counterparty": "PublicOne Inc.",
"counterparty_logo": "static/brands/publicone.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -199.87,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Monthly software subscription",
"reference": "PO-2025-008"
},
{
"id": "9",
"counterparty": "Github Inc.",
"counterparty_logo": "static/brands/github.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -42.87,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "GitHub Pro subscription",
"reference": "GH-2025-009"
},
{
"id": "10",
"counterparty": "Form Builder PRO",
"counterparty_logo": "static/brands/form-builder-pro.svg",
"payment_date": "2025-01-22",
"status_name": "completed",
"status": "success",
"amount": -112.44,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Premium form builder subscription",
"reference": "FBP-2025-010"
},
{
"id": "11",
"counterparty": "Netflix",
"counterparty_logo": "static/brands/netflix.svg",
"payment_date": "2025-01-21",
"status_name": "completed",
"status": "success",
"amount": -15.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "entertainment",
"description": "Monthly streaming subscription",
"reference": "NF-2025-011"
},
{
"id": "12",
"counterparty": "Amazon",
"counterparty_logo": "static/brands/amazon.svg",
"payment_date": "2025-01-21",
"status_name": "completed",
"status": "success",
"amount": -89.99,
"currency": "USD",
"transaction_type": "purchase",
"category": "shopping",
"description": "Office supplies purchase",
"reference": "AMZ-2025-012"
},
{
"id": "13",
"counterparty": "Starbucks",
"counterparty_logo": "static/brands/starbucks.svg",
"payment_date": "2025-01-21",
"status_name": "completed",
"status": "success",
"amount": -4.75,
"currency": "USD",
"transaction_type": "food",
"category": "dining",
"description": "Coffee purchase",
"reference": "SB-2025-013"
},
{
"id": "14",
"counterparty": "Microsoft",
"counterparty_logo": "static/brands/microsoft.svg",
"payment_date": "2025-01-21",
"status_name": "pending",
"status": "warning",
"amount": -299.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Microsoft 365 Business subscription",
"reference": "MS-2025-014"
},
{
"id": "15",
"counterparty": "TechCorp Solutions",
"counterparty_logo": "static/brands/techcorp.svg",
"payment_date": "2025-01-21",
"status_name": "completed",
"status": "success",
"amount": 1500.00,
"currency": "USD",
"transaction_type": "payment",
"category": "business",
"description": "Payment for web development services",
"reference": "TCS-2025-015"
},
{
"id": "16",
"counterparty": "Spotify",
"counterparty_logo": "static/brands/spotify.svg",
"payment_date": "2025-01-20",
"status_name": "completed",
"status": "success",
"amount": -9.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "entertainment",
"description": "Premium music subscription",
"reference": "SP-2025-016"
},
{
"id": "17",
"counterparty": "Zoom",
"counterparty_logo": "static/brands/zoom.svg",
"payment_date": "2025-01-20",
"status_name": "completed",
"status": "success",
"amount": -149.90,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Zoom Pro subscription",
"reference": "ZM-2025-017"
},
{
"id": "18",
"counterparty": "Slack",
"counterparty_logo": "static/brands/slack.svg",
"payment_date": "2025-01-20",
"status_name": "completed",
"status": "success",
"amount": -67.50,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Monthly Slack workspace subscription",
"reference": "SL-2025-018"
},
{
"id": "19",
"counterparty": "Dropbox",
"counterparty_logo": "static/brands/dropbox.svg",
"payment_date": "2025-01-20",
"status_name": "pending",
"status": "warning",
"amount": -119.88,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual cloud storage subscription",
"reference": "DB-2025-019"
},
{
"id": "20",
"counterparty": "Digital Marketing Agency",
"counterparty_logo": "static/brands/dma.svg",
"payment_date": "2025-01-19",
"status_name": "completed",
"status": "success",
"amount": 2500.00,
"currency": "USD",
"transaction_type": "payment",
"category": "business",
"description": "Payment for marketing campaign",
"reference": "DMA-2025-020"
},
{
"id": "21",
"counterparty": "Apple",
"counterparty_logo": "static/brands/apple.svg",
"payment_date": "2025-01-19",
"status_name": "completed",
"status": "success",
"amount": -99.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Apple Developer Program",
"reference": "APL-2025-021"
},
{
"id": "22",
"counterparty": "LinkedIn",
"counterparty_logo": "static/brands/linkedin.svg",
"payment_date": "2025-01-19",
"status_name": "completed",
"status": "success",
"amount": -29.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "business",
"description": "LinkedIn Premium subscription",
"reference": "LI-2025-022"
},
{
"id": "23",
"counterparty": "Canva",
"counterparty_logo": "static/brands/canva.svg",
"payment_date": "2025-01-18",
"status_name": "completed",
"status": "success",
"amount": -119.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Canva Pro subscription",
"reference": "CV-2025-023"
},
{
"id": "24",
"counterparty": "Figma",
"counterparty_logo": "static/brands/figma.svg",
"payment_date": "2025-01-18",
"status_name": "completed",
"status": "success",
"amount": -144.00,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Figma Professional subscription",
"reference": "FG-2025-024"
},
{
"id": "25",
"counterparty": "Notion",
"counterparty_logo": "static/brands/notion.svg",
"payment_date": "2025-01-18",
"status_name": "pending",
"status": "warning",
"amount": -96.00,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Notion Team subscription",
"reference": "NT-2025-025"
},
{
"id": "26",
"counterparty": "Salesforce",
"counterparty_logo": "static/brands/salesforce.svg",
"payment_date": "2025-01-17",
"status_name": "completed",
"status": "success",
"amount": -150.00,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Monthly Salesforce subscription",
"reference": "SF-2025-026"
},
{
"id": "27",
"counterparty": "HubSpot",
"counterparty_logo": "static/brands/hubspot.svg",
"payment_date": "2025-01-17",
"status_name": "completed",
"status": "success",
"amount": -89.00,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Monthly HubSpot Marketing subscription",
"reference": "HS-2025-027"
},
{
"id": "28",
"counterparty": "Mailchimp",
"counterparty_logo": "static/brands/mailchimp.svg",
"payment_date": "2025-01-17",
"status_name": "completed",
"status": "success",
"amount": -59.99,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Monthly email marketing subscription",
"reference": "MC-2025-028"
},
{
"id": "29",
"counterparty": "Trello",
"counterparty_logo": "static/brands/trello.svg",
"payment_date": "2025-01-16",
"status_name": "completed",
"status": "success",
"amount": -59.88,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Trello Business Class",
"reference": "TR-2025-029"
},
{
"id": "30",
"counterparty": "Asana",
"counterparty_logo": "static/brands/asana.svg",
"payment_date": "2025-01-16",
"status_name": "completed",
"status": "success",
"amount": -131.88,
"currency": "USD",
"transaction_type": "subscription",
"category": "software",
"description": "Annual Asana Premium subscription",
"reference": "AS-2025-030"
}
]

Some files were not shown because too many files have changed in this diff Show More