Compare commits

...

42 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] e3c004db3c Combine original z-index content with approach content
Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-11-15 06:06:22 +00:00
copilot-swe-agent[bot] e736432734 Move z-index approach content to layout/z-index page
Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-11-15 05:56:00 +00:00
copilot-swe-agent[bot] fec9b021dc Remove Extend section from documentation
Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-11-15 05:41:40 +00:00
copilot-swe-agent[bot] 63a03e0bc2 Initial plan 2025-11-15 05:36:43 +00:00
Mark Otto 14c1a4e0a1 Remove RTLCSS dependency, update docs and CSS to use native RTL (#41858)
* Remove RTLCSS dependency, update docs and CSS to use native RTL

* Rewrite more RTL stuff, was too verbose
2025-11-14 19:08:01 -08:00
Mark Otto a40f420eca v6: More logical properties (#41857)
* Logical properties for borders

* More logical properties for text, position, and more

* More logical for the docs
2025-11-14 12:07:45 -08:00
Mark Otto 995a74b708 v6: Switch to logical properties (#41854)
* Convert remaining utilities to all logical properties

* Move to logical properties

* Fix linter errors, bump bundlewatch
2025-11-14 12:07:45 -08:00
Mark Otto 1a2ac90d7d v6: Cleanup utilities (#41818)
* Split font utilities, update API to do more pseudo classes, drop display type classes

* Improve display docs, remove print display utils

* Document gap and grid utils, rename a couple classes

* better url

* Fix color-mix

* Undo utilities API change for now

* fix api changes

* Bundlewatch

* Linter cleanup

* Massive utilities update

- Split several utilities across smaller pages
- New underline thickness utility
- Updated text-wrap utility to use `text-wrap` property, removes white-space utils
- Adds a dozen new width utilities for now—TBD if we keep this, they're not documented yet
- Redoes the color utilities—color, background color, border color, link color—to use color-mix without attribute selectors. Faster, simpler, better support for overriding other components.
- Redesigns margin, padding, gap utils pages—shoutout Tailwind for having a better visualization here. Cribbed their approach to emphasize spacing utilities.
- Fixed up a lot of usages of color utilities, likely more to do
- Fixed up a lot of broken links, probably also more to do

* New details component, simpler a11y color contrast warning, updated docs bottom nav, updated ref tables

* Avoid name collision, update to demo thickness hover

* Rename $new-font-sizes to $font-sizes

* Update width and height docs

* Few cleanup tweaks

* Remove unused attribute selector for borders

* Fixes

* more bundle

* fixes

* spelling

* add json
2025-11-14 12:07:45 -08:00
Mark Otto db59235797 v6: Drop component variants for global .theme-* classes (#41789)
* New theme classes, revamped buttons

* bundle, lint, more cleanup

* update checks and radios

* Improve table theme variant usage

* remove table-border-factor
2025-11-14 12:07:45 -08:00
Mark Otto 08df8eb648 v6: Move some Getting Started content into new Guides section (#41797)
* Move some docs content around

* Update links
2025-11-14 12:07:45 -08:00
Mark Otto 1f768360b8 Add .prose class (#41791) 2025-11-14 12:07:45 -08:00
Mark Otto 41a1d9bdd0 v6: Range media queries (#41786)
* wip

Co-Authored-By: mdo <98681+mdo@users.noreply.github.com>

* linty linterton

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-11-14 12:07:45 -08:00
Mark Otto 19effcdc50 Follow up: custom switches get themes 2025-11-14 12:07:45 -08:00
Mark Otto 77a5c263bd Scope docs CSS to custom layer 2025-11-14 12:07:45 -08:00
Mark Otto d2e1fcc15e v6: Update colors and theme (#41763)
* new colors

* WIP: Redo some theming

* Fix sass warnings on unquoted map keys

* Revamp colors, update docs, couple new utils

* Remove key attributes

* Bump bundlewatch

* Bundlewatch

* Fix some things up

* Clean up tables, more color changes

* Fix more table color generation, simplify markup with new Table component prop

* More docs improvements, including utilities API, and checkbox and radio theme variants
2025-11-14 12:07:45 -08:00
Mark Otto b92d380b34 New validator (#41775)
* New validator

* update

* remove

* update
2025-11-14 12:07:44 -08:00
Mark Otto 7157c3eb5b Fix instances of 2xl, fix utilities generation (#41774) 2025-11-14 12:07:23 -08:00
Mark Otto 3ef010c876 v6: New lg, xl, and 2xl breakpoints, plus some renaming (#41770)
* Update xxl breakpoint and container, rename xxl to 2xl for better scaling

Co-Authored-By: mdo <98681+mdo@users.noreply.github.com>

* note for lg

* bump bundlewatch

---------

Co-authored-by: mdo <98681+mdo@users.noreply.github.com>
2025-11-14 12:07:23 -08:00
Mark Otto 5444ac5f64 Start to redo generate-utility() (#41769)
* Start to redo generate-utility()

* fixes

* bundlewatch
2025-11-14 12:07:23 -08:00
Mark Otto cd4bb6711e WIP: New form controls (#41740)
* New form controls

* Split Sass, update docs

* More migration docs

* basic migration, update changelog

* Bring back btn-check for now, but move to button stylesheet

* note

* Fix link

* lint
2025-11-14 12:07:23 -08:00
Mark Otto 31bb0fe027 Use @forward instead of @use for proper customization (#41762)
* Use `@forward` instead of `@use` for proper customization

* linty linterson

* woof
2025-11-14 12:07:23 -08:00
Mark Otto c80861e9c8 v6 Migration guide (#41683)
* wip

* More updates
2025-11-14 12:07:23 -08:00
Mark Otto 5a417dc9b7 v6: Add sub-groups to Utilities docs (#41758)
* Split the flex.mdx file into separate pages

* Add subgroups to docs utils nav

* More new groups, split pages

* Update MDX linter

* fixes
2025-11-14 12:07:23 -08:00
Mark Otto cc0ac410fa v6: justify-items and place-items utilities (#41757)
* Add utilities for place-items and justify-items

* bump
2025-11-14 12:07:23 -08:00
Mark Otto 8872e950f6 Remove !important from utilities, make it opt-in per utility (#41755)
* Remove !important from utilities, make it opt-in per utility

* package-lock

* Fix test
2025-11-14 12:07:23 -08:00
Mark Otto 2487ccf8cd v6: Add reference tables to utilities docs, add community links to some pages (MDN, CSS Tricks) (#41749)
* wip

* improve

* Add more utility refs

* Remove important flag from the utilities

* update

* Start on helpers

* fixes

* fix links
2025-11-14 12:07:23 -08:00
Mark Otto b6d459b095 New forms and buttons (#41708) 2025-11-14 12:07:23 -08:00
Mark Otto 160b3b4519 Colocate Sass vars in their respective files (#41706)
* Co-locate Sass variables in most files

* another

* fix

* Don't bring tables into reboot, temp remove some sass vars so we don't need the co-dependency

* Move vars

* bundlewatch

* scssdocs

* Fix scssdocs
2025-11-14 12:07:23 -08:00
Mark Otto 04b8fe71d6 Refactor accordion button to use mask, remove some Sass vars and dark mode styles (#41703) 2025-11-14 12:07:23 -08:00
Mark Otto b3ae589888 Restore both grids , enable CSS grid by default, and update mixins (#41702)
* Restore both grids and update mixins

* Bundlewatch
2025-11-14 12:07:22 -08:00
Mark Otto 5e83674516 First pass at CSS layers (#41701)
* First pass at CSS layers

* bundlewatch

* more bundlewatch
2025-11-14 12:07:22 -08:00
Mark Otto 9699052db1 Migrate to Sass modules (#41512)
* Reorganize scss folder

* Migrate to Sass modules

* Migrate docs to Sass modules, comment out docs grid CSS

* Give helpers folder an index.scss, migrate ratio helper to aspect-ratio utility

* Delete node sass Action

* Modify Sass tests to pass for new Sass modules implementation

* Don't disallow calc()

* Move heading classes back to Reboot to prevent a dependency

* Utilities, some helpers, and theme colors

* Temporary fix of docs compilation

* Temporary Bundlewatch fix

* docs fix import to use

* Restyle docs callouts

* Fix docs colors

* Revert typo

* Reintroduce `css-lint-vars` npm script

* Bump to Sass v1.90.x

* Fixes

* more

* Remove

---------

Co-authored-by: Julien Déramond <juderamond@gmail.com>
2025-11-14 12:07:22 -08:00
Mark Otto e214ce62e4 Co-locate heading and some type styles in Reboot to avoid some extends and extra dependencies once we migrate to Sass modules (#41697) 2025-11-14 12:07:14 -08:00
Mark Otto eedd6cfe36 Remove added badges from docs pages (#41694)
* Remove added badges from docs pages

* Remove AddedIn
2025-11-14 12:07:14 -08:00
Mark Otto d82c983ccf Clean up deprecated Sass (#41693)
* Remove all deprecated Sass variables and deprecation notices from docs components

* Fix linter error

* fix
2025-11-14 12:07:14 -08:00
Mark Otto e398044ab3 Drop -prefix (#41692) 2025-11-14 12:07:14 -08:00
Mark Otto 23bcf39ce2 Rename mh-* and mw-* to max-h/w-*, add additional width and height va… (#41687)
* Rename mh-* and mw-* to max-h/w-*, add additional width and height values

Fixes #41330, fixes #40674.

* Bump bundlewatch
2025-11-14 12:07:14 -08:00
Mark Otto c726175119 Drop clearfix for display: flow-root (#41686)
* Drop clearfix for display: flow-root

* Fix links
2025-11-14 12:07:14 -08:00
Mark Otto 51f33728bf Add Markdownlint for our MDX (#41685) 2025-11-14 12:07:14 -08:00
Mark Otto 5bc6737fc2 Remove jQuery support in plugins (#41682) 2025-11-14 12:07:13 -08:00
Mark Otto 91f28cfc38 Move ratio from helpers to utilties (#41684)
* Convert .ratio helper to new .ratio utility

* Fix up

* Fix links for now, even though they'll be deleted
2025-11-14 12:06:13 -08:00
Mark Otto a3f251e38a v6: Don't disallow calc (#41681)
* Don't disallow calc()

* Remove disables that aren't needed

* Remove custom subtract and add functions

* Remove more disables

* keep it here
2025-11-14 12:06:13 -08:00
418 changed files with 18925 additions and 17090 deletions
+8 -8
View File
@@ -2,35 +2,35 @@
"files": [
{
"path": "./dist/css/bootstrap-grid.css",
"maxSize": "6.5 kB"
"maxSize": "10.0 kB"
},
{
"path": "./dist/css/bootstrap-grid.min.css",
"maxSize": "6.0 kB"
"maxSize": "9.0 kB"
},
{
"path": "./dist/css/bootstrap-reboot.css",
"maxSize": "3.5 kB"
"maxSize": "5.5 kB"
},
{
"path": "./dist/css/bootstrap-reboot.min.css",
"maxSize": "3.25 kB"
"maxSize": "4.5 kB"
},
{
"path": "./dist/css/bootstrap-utilities.css",
"maxSize": "11.75 kB"
"maxSize": "15.25 kB"
},
{
"path": "./dist/css/bootstrap-utilities.min.css",
"maxSize": "10.75 kB"
"maxSize": "13.5 kB"
},
{
"path": "./dist/css/bootstrap.css",
"maxSize": "32.5 kB"
"maxSize": "37.5 kB"
},
{
"path": "./dist/css/bootstrap.min.css",
"maxSize": "30.25 kB"
"maxSize": "33.75 kB"
},
{
"path": "./dist/js/bootstrap.bundle.js",
+3
View File
@@ -21,6 +21,7 @@
"callout",
"callouts",
"camelCase",
"checkgroup",
"clearfix",
"Codesniffer",
"combinator",
@@ -29,6 +30,7 @@
"Crossfade",
"crossfading",
"cssgrid",
"csstricks",
"Csvg",
"Datalists",
"Deque",
@@ -46,6 +48,7 @@
"favicons",
"fieldsets",
"flexbox",
"frontmatter",
"fullscreen",
"getbootstrap",
"Grayscale",
+1 -3
View File
@@ -30,8 +30,6 @@ jobs:
node-version: "${{ env.NODE }}"
cache: npm
- run: java -version
- name: Install npm dependencies
run: npm ci
@@ -39,7 +37,7 @@ jobs:
run: npm run docs-build
- name: Validate HTML
run: npm run docs-vnu
run: npm run docs-html-validate
- name: Run linkinator
uses: JustinBeckwith/linkinator-action@af984b9f30f63e796ae2ea5be5e07cb587f1bbd9 # v2.3
-49
View File
@@ -1,49 +0,0 @@
name: CSS (node-sass)
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
env:
FORCE_COLOR: 2
NODE: 22
permissions:
contents: read
jobs:
css:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: "${{ env.NODE }}"
- name: Build CSS with node-sass
run: |
npx --package node-sass@latest node-sass --version
npx --package node-sass@latest node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 scss/ -o dist-sass/css/
ls -Al dist-sass/css
- name: Check built CSS files for Sass variables
shell: bash
run: |
SASS_VARS_FOUND=$(find "dist-sass/css/" -type f -name "*.css" -print0 | xargs -0 --no-run-if-empty grep -F "\$" || true)
if [[ -z "$SASS_VARS_FOUND" ]]; then
echo "All good, no Sass variables found!"
exit 0
else
echo "Found $(echo "$SASS_VARS_FOUND" | wc -l | bc) Sass variables:"
echo "$SASS_VARS_FOUND"
exit 1
fi
+1
View File
@@ -18,6 +18,7 @@
.cache
.DS_Store
.idea
.nvmrc
.project
.settings
.tmproj
+18
View File
@@ -0,0 +1,18 @@
{
"default": true,
"MD004": { "style": "dash" },
"MD011": false,
"MD013": false,
"MD024": false,
"MD025": false,
"MD026": false,
"MD031": false,
"MD033": false,
"MD034": false,
"MD037": false,
"MD038": false,
"MD041": false,
"MD046": false,
"line-length": false,
"no-inline-html": false
}
-1
View File
@@ -13,7 +13,6 @@
"outline": "none"
},
"function-disallowed-list": [
"calc",
"lighten",
"darken"
],
+2 -18
View File
@@ -87,34 +87,18 @@ Within the download youll find the following directories and files, logically
│ ├── bootstrap-grid.css.map
│ ├── bootstrap-grid.min.css
│ ├── bootstrap-grid.min.css.map
│ ├── bootstrap-grid.rtl.css
│ ├── bootstrap-grid.rtl.css.map
│ ├── bootstrap-grid.rtl.min.css
│ ├── bootstrap-grid.rtl.min.css.map
│ ├── bootstrap-reboot.css
│ ├── bootstrap-reboot.css.map
│ ├── bootstrap-reboot.min.css
│ ├── bootstrap-reboot.min.css.map
│ ├── bootstrap-reboot.rtl.css
│ ├── bootstrap-reboot.rtl.css.map
│ ├── bootstrap-reboot.rtl.min.css
│ ├── bootstrap-reboot.rtl.min.css.map
│ ├── bootstrap-utilities.css
│ ├── bootstrap-utilities.css.map
│ ├── bootstrap-utilities.min.css
│ ├── bootstrap-utilities.min.css.map
│ ├── bootstrap-utilities.rtl.css
│ ├── bootstrap-utilities.rtl.css.map
│ ├── bootstrap-utilities.rtl.min.css
│ ├── bootstrap-utilities.rtl.min.css.map
│ ├── bootstrap.css
│ ├── bootstrap.css.map
│ ├── bootstrap.min.css
── bootstrap.min.css.map
│ ├── bootstrap.rtl.css
│ ├── bootstrap.rtl.css.map
│ ├── bootstrap.rtl.min.css
│ └── bootstrap.rtl.min.css.map
── bootstrap.min.css.map
└── js/
├── bootstrap.bundle.js
├── bootstrap.bundle.js.map
@@ -131,7 +115,7 @@ Within the download youll find the following directories and files, logically
```
</details>
We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/).
We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/). All CSS files work for both LTR and RTL layouts thanks to logical properties—simply set `dir="rtl"` on your HTML element.
## Bugs and feature requests
-4
View File
@@ -29,10 +29,6 @@ const files = [
file: 'dist/css/bootstrap.min.css',
configPropertyName: 'css_hash'
},
{
file: 'dist/css/bootstrap.rtl.min.css',
configPropertyName: 'css_rtl_hash'
},
{
file: 'dist/js/bootstrap.min.js',
configPropertyName: 'js_hash'
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env node
/**
* Generate utilities metadata JSON from Sass
* This script compiles a special Sass file that outputs utility information as CSS comments,
* then extracts and saves it as JSON for documentation use.
*/
import { readFileSync, writeFileSync, unlinkSync } from 'node:fs'
import { execSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const rootDir = path.join(__dirname, '..')
// Compile the metadata generator SCSS file
console.log('Compiling utilities metadata...')
try {
execSync(
'sass --style expanded --no-source-map build/generate-utilities-metadata.scss:dist/css/utilities-metadata.tmp.css',
{ cwd: rootDir, stdio: 'inherit' }
)
} catch {
console.error('Failed to compile metadata SCSS')
process.exit(1)
}
// Read the compiled CSS
const cssPath = path.join(rootDir, 'dist/css/utilities-metadata.tmp.css')
const cssContent = readFileSync(cssPath, 'utf8')
// Extract JSON from the CSS comment
const startMarker = 'BOOTSTRAP-UTILITIES-METADATA-START'
const endMarker = 'BOOTSTRAP-UTILITIES-METADATA-END'
const startIndex = cssContent.indexOf(startMarker)
const endIndex = cssContent.indexOf(endMarker)
if (startIndex === -1 || endIndex === -1) {
console.error('Could not find metadata markers in compiled CSS')
process.exit(1)
}
// Extract JSON content between markers
const jsonContent = cssContent
.slice(startIndex + startMarker.length, endIndex)
.trim()
// Validate JSON
try {
const parsed = JSON.parse(jsonContent)
console.log(`✓ Extracted metadata for ${Object.keys(parsed.utilities).length} utilities`)
// Write to JSON file
const outputPath = path.join(rootDir, 'dist/css/bootstrap-utilities.metadata.json')
writeFileSync(outputPath, JSON.stringify(parsed, null, 2))
console.log(`✓ Wrote metadata to ${outputPath}`)
// Clean up temporary CSS files
try {
unlinkSync(cssPath)
} catch {
// File may not exist
}
// Also clean up any other temporary variants that may have been created
const tempFiles = [
'dist/css/utilities-metadata.tmp.min.css',
'dist/css/utilities-metadata.tmp.min.css.map'
]
for (const file of tempFiles) {
try {
unlinkSync(path.join(rootDir, file))
} catch {
// File may not exist, ignore
}
}
console.log('✓ Cleaned up temporary files')
} catch (error) {
console.error('Failed to parse extracted JSON:', error.message)
console.error('Extracted content:', jsonContent.slice(0, 500))
process.exit(1)
}
+112
View File
@@ -0,0 +1,112 @@
// Generate utilities metadata JSON for documentation
// This file is compiled to extract utility information without generating CSS
@use "sass:map";
@use "sass:list";
@use "sass:string";
@use "sass:meta";
@use "../scss/config" as *;
@use "../scss/colors" as *;
@use "../scss/variables" as *;
@use "../scss/functions" as *;
@use "../scss/theme" as *;
@use "../scss/utilities" as *;
// Access the utilities map
$utilities-map: $utilities !default;
// Start JSON output
$json: '{"utilities":{' !default;
$utility-count: 0 !default;
$total-utilities: list.length(map.keys($utilities-map)) !default;
@each $key, $utility in $utilities-map {
$utility-count: $utility-count + 1;
// Skip if utility is null or false (disabled)
@if $utility {
// Extract class prefix
$class: if(map.has-key($utility, "class"), map.get($utility, "class"), $key);
// Extract property
$property: if(map.has-key($utility, "property"), map.get($utility, "property"), null);
// Extract values
$values: if(map.has-key($utility, "values"), map.get($utility, "values"), null);
// Generate class list
$classes: "";
@if $values {
@if meta.type-of($values) == "map" {
$value-keys: map.keys($values);
$first: true;
@each $value-key in $value-keys {
@if not $first {
$classes: $classes + ", ";
}
$class-name: if($value-key == "null" or $value-key == null, $class, "#{$class}-#{$value-key}");
$classes: $classes + '"' + $class-name + '"';
$first: false;
}
} @else if meta.type-of($values) == "list" {
$first: true;
@each $value in $values {
@if not $first {
$classes: $classes + ", ";
}
$class-name: "#{$class}-#{$value}";
$classes: $classes + '"' + $class-name + '"';
$first: false;
}
}
}
// Build JSON entry
$json: $json + '"' + $key + '":{"class":"' + $class + '"';
@if $property {
@if meta.type-of($property) == "string" {
$json: $json + ',"property":"' + $property + '"';
} @else if meta.type-of($property) == "list" {
$property-str: "";
$first: true;
@each $prop in $property {
@if not $first {
$property-str: $property-str + " ";
}
$property-str: $property-str + $prop;
$first: false;
}
$json: $json + ',"property":"' + $property-str + '"';
}
// Skip map properties as they're complex and don't translate to JSON well
}
@if $classes != "" {
$json: $json + ',"classes":[' + $classes + "]";
} @else {
$json: $json + ',"classes":[]';
}
$json: $json + "}";
@if $utility-count < $total-utilities {
$json: $json + ",";
}
}
}
// stylelint-disable-next-line scss/dollar-variable-default
$json: $json + "}}";
// Output as CSS comment so it appears in compiled file
/*! BOOTSTRAP-UTILITIES-METADATA-START
#{$json}
BOOTSTRAP-UTILITIES-METADATA-END */
// Prevent any actual CSS output
.bootstrap-utilities-metadata-generator {
content: "This file should not generate CSS, only metadata comments";
}
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env node
/*!
* Script to run html-validate for HTML validation.
*
* This replaces the Java-based vnu-jar validator with a faster, Node.js-only solution.
* Benefits:
* - No Java dependency required
* - Faster execution (no JVM startup time)
* - Easy to configure with rule-based system
* - Better integration with Node.js build tools
*
* Copyright 2017-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
import { HtmlValidate } from 'html-validate'
import { globby } from 'globby'
const htmlValidate = new HtmlValidate({
rules: {
// Allow autocomplete on buttons (Bootstrap specific)
'attribute-allowed-values': 'off',
// Allow aria-disabled on links (Bootstrap specific)
'aria-label-misuse': 'off',
// Allow modern CSS syntax
'valid-id': 'off',
// Allow void elements with trailing slashes (Astro)
'void-style': 'off',
// Allow custom attributes
'no-unknown-elements': 'off',
'attribute-boolean-style': 'off',
'no-inline-style': 'off',
// KEEP duplicate ID checking enabled (this is important for HTML validity)
'no-dup-id': 'error'
},
elements: [
'html5',
{
// Allow custom attributes for Astro/framework compatibility
'*': {
attributes: {
'is:raw': { boolean: true },
switch: { boolean: true },
autocomplete: { enum: ['on', 'off', 'new-password', 'current-password'] }
}
}
}
]
})
async function validateHTML() {
try {
console.log('Running html-validate validation...')
// Find all HTML files
const files = await globby([
'_site/**/*.html',
'js/tests/**/*.html'
], {
ignore: ['**/node_modules/**']
})
console.log(`Validating ${files.length} HTML files...`)
let hasErrors = false
// Validate all files in parallel to avoid await-in-loop
const validationPromises = files.map(file =>
htmlValidate.validateFile(file).then(report => ({ file, report }))
)
const validationResults = await Promise.all(validationPromises)
// Process results and check for errors
for (const { file, report } of validationResults) {
if (!report.valid) {
hasErrors = true
console.error(`\nErrors in ${file}:`)
// Extract error messages with reduced nesting
const errorMessages = report.results.flatMap(result =>
result.messages.filter(message => message.severity === 2)
)
for (const message of errorMessages) {
console.error(` Line ${message.line}:${message.column} - ${message.message} (${message.ruleId})`)
}
}
}
if (hasErrors) {
console.error('\nHTML validation failed!')
process.exit(1)
} else {
console.log('✓ All HTML files are valid!')
}
} catch (error) {
console.error('HTML validation error:', error)
process.exit(1)
}
}
validateHTML()
+1 -2
View File
@@ -10,8 +10,7 @@ export default context => {
plugins: {
autoprefixer: {
cascade: false
},
rtlcss: context.env === 'RTL'
}
}
}
}
-66
View File
@@ -1,66 +0,0 @@
#!/usr/bin/env node
/*!
* Script to run vnu-jar if Java is available.
* Copyright 2017-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
import { execFile, spawn } from 'node:child_process'
import vnu from 'vnu-jar'
execFile('java', ['-version'], (error, stdout, stderr) => {
if (error) {
console.error('Skipping vnu-jar test; Java is probably missing.')
console.error(error)
return
}
console.log('Running vnu-jar validation...')
const is32bitJava = !/64-Bit/.test(stderr)
// vnu-jar accepts multiple ignores joined with a `|`.
// Also note that the ignores are string regular expressions.
const ignores = [
// "autocomplete" is included in <button> and checkboxes and radio <input>s due to
// Firefox's non-standard autocomplete behavior - see https://bugzilla.mozilla.org/show_bug.cgi?id=654072
'Attribute “autocomplete” is only allowed when the input type is.*',
'Attribute “autocomplete” not allowed on element “button” at this point.',
// Per https://www.w3.org/TR/html-aria/#docconformance having "aria-disabled" on a link is
// NOT RECOMMENDED, but it's still valid - we explain in the docs that it's not ideal,
// and offer more robust alternatives, but also need to show a less-than-ideal example
'An “aria-disabled” attribute whose value is “true” should not be specified on an “a” element that has an “href” attribute.',
// A `code` element with the `is:raw` attribute coming from remark-prismjs (Astro upstream possible bug)
'Attribute “is:raw” is not serializable as XML 1.0.',
'Attribute “is:raw” not allowed on element “code” at this point.',
// Astro's expecting trailing slashes on HTML tags such as <br />
'Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.',
// Allow `switch` attribute.
'Attribute “switch” not allowed on element “input” at this point.'
].join('|')
const args = [
'-jar',
`"${vnu}"`,
'--asciiquotes',
'--skip-non-html',
'--Werror',
`--filterpattern "${ignores}"`,
'_site/',
'js/tests/'
]
// For the 32-bit Java we need to pass `-Xss512k`
if (is32bitJava) {
args.splice(0, 0, '-Xss512k')
}
console.log(`command used: java ${args.join(' ')}`)
return spawn('java', args, {
shell: true,
stdio: 'inherit'
})
.on('exit', process.exit)
})
-2
View File
@@ -36,8 +36,6 @@ cdn:
# See https://www.srihash.org for info on how to generate the hashes
css: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
css_hash: "sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
css_rtl: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.rtl.min.css"
css_rtl_hash: "sha384-CfCrinSRH2IR6a4e6fy2q6ioOX7O6Mtm1L9vRvFZ1trBncWmMePhzvafv7oIcWiW"
js: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.min.js"
js_hash: "sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
File diff suppressed because it is too large Load Diff
+206 -511
View File
@@ -57,252 +57,6 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement$1 = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement$1(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement$1(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -310,7 +64,6 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -479,33 +232,11 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles,
bubbles: true,
cancelable: true
}), args);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
element.dispatchEvent(evt);
return evt;
}
};
@@ -582,6 +313,210 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement$1 = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement$1(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement$1(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -867,20 +802,6 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -889,12 +810,6 @@
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -930,16 +845,6 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -953,12 +858,6 @@
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1395,23 +1294,6 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1446,12 +1328,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1645,23 +1521,6 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1680,12 +1539,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
var top = 'top';
var bottom = 'bottom';
var right = 'right';
@@ -3796,20 +3649,6 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -3885,12 +3724,6 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -4463,20 +4296,6 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -4510,12 +4329,6 @@
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -4684,20 +4497,6 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -4741,12 +4540,6 @@
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -5468,28 +5261,8 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -5549,28 +5322,8 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -5799,20 +5552,6 @@
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -5825,12 +5564,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -6057,20 +5790,6 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -6095,11 +5814,6 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -6257,19 +5971,6 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -6278,12 +5979,6 @@
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
/**
* --------------------------------------------------------------------------
* Bootstrap index.umd.js
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+206 -511
View File
@@ -53,252 +53,6 @@ const Data = {
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -306,7 +60,6 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -475,33 +228,11 @@ const EventHandler = {
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles,
bubbles: true,
cancelable: true
}), args);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
element.dispatchEvent(evt);
return evt;
}
};
@@ -578,6 +309,210 @@ const Manipulator = {
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -863,20 +798,6 @@ class Alert extends BaseComponent {
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -885,12 +806,6 @@ class Alert extends BaseComponent {
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -926,16 +841,6 @@ class Button extends BaseComponent {
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -949,12 +854,6 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1391,23 +1290,6 @@ class Carousel extends BaseComponent {
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1442,12 +1324,6 @@ EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => {
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1641,23 +1517,6 @@ class Collapse extends BaseComponent {
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1676,12 +1535,6 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, functi
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
/**
* --------------------------------------------------------------------------
* Bootstrap dropdown.js
@@ -1955,20 +1808,6 @@ class Dropdown extends BaseComponent {
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -2044,12 +1883,6 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, functi
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -2622,20 +2455,6 @@ class Modal extends BaseComponent {
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -2669,12 +2488,6 @@ EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, functi
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -2843,20 +2656,6 @@ class Offcanvas extends BaseComponent {
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -2900,12 +2699,6 @@ EventHandler.on(window, EVENT_RESIZE, () => {
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -3627,28 +3420,8 @@ class Tooltip extends BaseComponent {
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -3708,28 +3481,8 @@ class Popover extends Tooltip {
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -3958,20 +3711,6 @@ class ScrollSpy extends BaseComponent {
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -3984,12 +3723,6 @@ EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => {
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -4216,20 +3949,6 @@ class Tab extends BaseComponent {
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -4254,11 +3973,6 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -4416,19 +4130,6 @@ class Toast extends BaseComponent {
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -4437,11 +4138,5 @@ class Toast extends BaseComponent {
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
export { Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip };
//# sourceMappingURL=bootstrap.esm.js.map
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+206 -511
View File
@@ -76,252 +76,6 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
// add listener on the first call when the document is in loading state
if (!DOMContentLoadedCallbacks.length) {
document.addEventListener('DOMContentLoaded', () => {
for (const callback of DOMContentLoadedCallbacks) {
callback();
}
});
}
DOMContentLoadedCallbacks.push(callback);
} else {
callback();
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap dom/event-handler.js
@@ -329,7 +83,6 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -498,33 +251,11 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles,
bubbles: true,
cancelable: true
}), args);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
element.dispatchEvent(evt);
return evt;
}
};
@@ -601,6 +332,210 @@
}
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/index.js
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* --------------------------------------------------------------------------
*/
const MAX_UID = 1000000;
const MILLISECONDS_MULTIPLIER = 1000;
const TRANSITION_END = 'transitionend';
/**
* Properly escape IDs selectors to handle weird IDs
* @param {string} selector
* @returns {string}
*/
const parseSelector = selector => {
if (selector && window.CSS && window.CSS.escape) {
// document.querySelector needs escaping to handle IDs (html5+) containing for instance /
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
}
return selector;
};
// Shout-out Angus Croll (https://goo.gl/pxwQGp)
const toType = object => {
if (object === null || object === undefined) {
return `${object}`;
}
return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
};
/**
* Public Util API
*/
const getUID = prefix => {
do {
prefix += Math.floor(Math.random() * MAX_UID);
} while (document.getElementById(prefix));
return prefix;
};
const getTransitionDurationFromElement = element => {
if (!element) {
return 0;
}
// Get transition-duration of the element
let {
transitionDuration,
transitionDelay
} = window.getComputedStyle(element);
const floatTransitionDuration = Number.parseFloat(transitionDuration);
const floatTransitionDelay = Number.parseFloat(transitionDelay);
// Return 0 if element or transition duration is not found
if (!floatTransitionDuration && !floatTransitionDelay) {
return 0;
}
// If multiple durations are defined, take the first
transitionDuration = transitionDuration.split(',')[0];
transitionDelay = transitionDelay.split(',')[0];
return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
};
const triggerTransitionEnd = element => {
element.dispatchEvent(new Event(TRANSITION_END));
};
const isElement = object => {
if (!object || typeof object !== 'object') {
return false;
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
if (isElement(object)) {
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
}
return null;
};
const isVisible = element => {
if (!isElement(element) || element.getClientRects().length === 0) {
return false;
}
const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
// Handle `details` element as its content may falsie appear visible when it is closed
const closedDetails = element.closest('details:not([open])');
if (!closedDetails) {
return elementIsVisible;
}
if (closedDetails !== element) {
const summary = element.closest('summary');
if (summary && summary.parentNode !== closedDetails) {
return false;
}
if (summary === null) {
return false;
}
}
return elementIsVisible;
};
const isDisabled = element => {
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
return true;
}
if (element.classList.contains('disabled')) {
return true;
}
if (typeof element.disabled !== 'undefined') {
return element.disabled;
}
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
};
const findShadowRoot = element => {
if (!document.documentElement.attachShadow) {
return null;
}
// Can find the shadow root otherwise it'll return the document
if (typeof element.getRootNode === 'function') {
const root = element.getRootNode();
return root instanceof ShadowRoot ? root : null;
}
if (element instanceof ShadowRoot) {
return element;
}
// when we don't find a shadow root
if (!element.parentNode) {
return null;
}
return findShadowRoot(element.parentNode);
};
const noop = () => {};
/**
* Trick to restart an element's animation
*
* @param {HTMLElement} element
* @return void
*
* @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
*/
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const isRTL = () => document.documentElement.dir === 'rtl';
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
if (!waitForTransition) {
execute(callback);
return;
}
const durationPadding = 5;
const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
let called = false;
const handler = ({
target
}) => {
if (target !== transitionElement) {
return;
}
called = true;
transitionElement.removeEventListener(TRANSITION_END, handler);
execute(callback);
};
transitionElement.addEventListener(TRANSITION_END, handler);
setTimeout(() => {
if (!called) {
triggerTransitionEnd(transitionElement);
}
}, emulatedDuration);
};
/**
* Return the previous/next element of a list.
*
* @param {array} list The list of elements
* @param activeElement The active element
* @param shouldGetNext Choose to get next or previous element
* @param isCycleAllowed
* @return {Element|elem} The proper element
*/
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
const listLength = list.length;
let index = list.indexOf(activeElement);
// if the element does not exist in the list return an element
// depending on the direction and if cycle is allowed
if (index === -1) {
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
}
index += shouldGetNext ? 1 : -1;
if (isCycleAllowed) {
index = (index + listLength) % listLength;
}
return list[Math.max(0, Math.min(index, listLength - 1))];
};
/**
* --------------------------------------------------------------------------
* Bootstrap util/config.js
@@ -886,20 +821,6 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -908,12 +829,6 @@
enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
defineJQueryPlugin(Alert);
/**
* --------------------------------------------------------------------------
* Bootstrap button.js
@@ -949,16 +864,6 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -972,12 +877,6 @@
data.toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Button);
/**
* --------------------------------------------------------------------------
* Bootstrap util/swipe.js
@@ -1414,23 +1313,6 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1465,12 +1347,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Carousel);
/**
* --------------------------------------------------------------------------
* Bootstrap collapse.js
@@ -1664,23 +1540,6 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -1699,12 +1558,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(Collapse);
/**
* --------------------------------------------------------------------------
* Bootstrap dropdown.js
@@ -1978,20 +1831,6 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
return;
@@ -2067,12 +1906,6 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
defineJQueryPlugin(Dropdown);
/**
* --------------------------------------------------------------------------
* Bootstrap util/backdrop.js
@@ -2645,20 +2478,6 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -2692,12 +2511,6 @@
});
enableDismissTrigger(Modal);
/**
* jQuery
*/
defineJQueryPlugin(Modal);
/**
* --------------------------------------------------------------------------
* Bootstrap offcanvas.js
@@ -2866,20 +2679,6 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -2923,12 +2722,6 @@
});
enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas);
/**
* --------------------------------------------------------------------------
* Bootstrap util/sanitizer.js
@@ -3650,28 +3443,8 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip);
/**
* --------------------------------------------------------------------------
* Bootstrap popover.js
@@ -3731,28 +3504,8 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover);
/**
* --------------------------------------------------------------------------
* Bootstrap scrollspy.js
@@ -3981,20 +3734,6 @@
node.classList.remove(CLASS_NAME_ACTIVE$1);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -4007,12 +3746,6 @@
}
});
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy);
/**
* --------------------------------------------------------------------------
* Bootstrap tab.js
@@ -4239,20 +3972,6 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -4277,11 +3996,6 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
defineJQueryPlugin(Tab);
/**
* --------------------------------------------------------------------------
@@ -4439,19 +4153,6 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -4460,12 +4161,6 @@
enableDismissTrigger(Toast);
/**
* jQuery
*/
defineJQueryPlugin(Toast);
/**
* --------------------------------------------------------------------------
* Bootstrap index.umd.js
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -24
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/component-functions.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/component-functions', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Alert = factory(global.BaseComponent, global.EventHandler, global.ComponentFunctions, global.Index));
})(this, (function (BaseComponent, EventHandler, componentFunctions_js, index_js) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/component-functions.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/component-functions'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Alert = factory(global.BaseComponent, global.EventHandler, global.ComponentFunctions));
})(this, (function (BaseComponent, EventHandler, componentFunctions_js) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -56,20 +56,6 @@
EventHandler.trigger(this._element, EVENT_CLOSED);
this.dispose();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -78,12 +64,6 @@
componentFunctions_js.enableDismissTrigger(Alert, 'close');
/**
* jQuery
*/
index_js.defineJQueryPlugin(Alert);
return Alert;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"alert.js","sources":["../src/alert.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Alert.getOrCreateInstance(this)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config](this)\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Alert)\n\nexport default Alert\n"],"names":["NAME","DATA_KEY","EVENT_KEY","EVENT_CLOSE","EVENT_CLOSED","CLASS_NAME_FADE","CLASS_NAME_SHOW","Alert","BaseComponent","close","closeEvent","EventHandler","trigger","_element","defaultPrevented","classList","remove","isAnimated","contains","_queueCallback","_destroyElement","dispose","jQueryInterface","config","each","data","getOrCreateInstance","undefined","startsWith","TypeError","enableDismissTrigger","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAOA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,OAAO;EACpB,MAAMC,QAAQ,GAAG,UAAU;EAC3B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAEhC,MAAME,WAAW,GAAG,CAAA,KAAA,EAAQD,SAAS,CAAA,CAAE;EACvC,MAAME,YAAY,GAAG,CAAA,MAAA,EAASF,SAAS,CAAA,CAAE;EACzC,MAAMG,eAAe,GAAG,MAAM;EAC9B,MAAMC,eAAe,GAAG,MAAM;;EAE9B;EACA;EACA;;EAEA,MAAMC,KAAK,SAASC,aAAa,CAAC;EAChC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,KAAKA,GAAG;MACN,MAAMC,UAAU,GAAGC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEV,WAAW,CAAC;MAEnE,IAAIO,UAAU,CAACI,gBAAgB,EAAE;EAC/B,MAAA;EACF,IAAA;MAEA,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACC,MAAM,CAACV,eAAe,CAAC;MAE/C,MAAMW,UAAU,GAAG,IAAI,CAACJ,QAAQ,CAACE,SAAS,CAACG,QAAQ,CAACb,eAAe,CAAC;EACpE,IAAA,IAAI,CAACc,cAAc,CAAC,MAAM,IAAI,CAACC,eAAe,EAAE,EAAE,IAAI,CAACP,QAAQ,EAAEI,UAAU,CAAC;EAC9E,EAAA;;EAEA;EACAG,EAAAA,eAAeA,GAAG;EAChB,IAAA,IAAI,CAACP,QAAQ,CAACG,MAAM,EAAE;MACtBL,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAET,YAAY,CAAC;MACjD,IAAI,CAACiB,OAAO,EAAE;EAChB,EAAA;;EAEA;IACA,OAAOC,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;EAC3B,MAAA,MAAMC,IAAI,GAAGlB,KAAK,CAACmB,mBAAmB,CAAC,IAAI,CAAC;EAE5C,MAAA,IAAI,OAAOH,MAAM,KAAK,QAAQ,EAAE;EAC9B,QAAA;EACF,MAAA;EAEA,MAAA,IAAIE,IAAI,CAACF,MAAM,CAAC,KAAKI,SAAS,IAAIJ,MAAM,CAACK,UAAU,CAAC,GAAG,CAAC,IAAIL,MAAM,KAAK,aAAa,EAAE;EACpF,QAAA,MAAM,IAAIM,SAAS,CAAC,CAAA,iBAAA,EAAoBN,MAAM,GAAG,CAAC;EACpD,MAAA;EAEAE,MAAAA,IAAI,CAACF,MAAM,CAAC,CAAC,IAAI,CAAC;EACpB,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;AAEAO,4CAAoB,CAACvB,KAAK,EAAE,OAAO,CAAC;;EAEpC;EACA;EACA;;AAEAwB,6BAAkB,CAACxB,KAAK,CAAC;;;;;;;;"}
{"version":3,"file":"alert.js","sources":["../src/alert.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { enableDismissTrigger } from './util/component-functions.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'alert'\nconst DATA_KEY = 'bs.alert'\nconst EVENT_KEY = `.${DATA_KEY}`\n\nconst EVENT_CLOSE = `close${EVENT_KEY}`\nconst EVENT_CLOSED = `closed${EVENT_KEY}`\nconst CLASS_NAME_FADE = 'fade'\nconst CLASS_NAME_SHOW = 'show'\n\n/**\n * Class definition\n */\n\nclass Alert extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n close() {\n const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE)\n\n if (closeEvent.defaultPrevented) {\n return\n }\n\n this._element.classList.remove(CLASS_NAME_SHOW)\n\n const isAnimated = this._element.classList.contains(CLASS_NAME_FADE)\n this._queueCallback(() => this._destroyElement(), this._element, isAnimated)\n }\n\n // Private\n _destroyElement() {\n this._element.remove()\n EventHandler.trigger(this._element, EVENT_CLOSED)\n this.dispose()\n }\n}\n\n/**\n * Data API implementation\n */\n\nenableDismissTrigger(Alert, 'close')\n\nexport default Alert\n"],"names":["NAME","DATA_KEY","EVENT_KEY","EVENT_CLOSE","EVENT_CLOSED","CLASS_NAME_FADE","CLASS_NAME_SHOW","Alert","BaseComponent","close","closeEvent","EventHandler","trigger","_element","defaultPrevented","classList","remove","isAnimated","contains","_queueCallback","_destroyElement","dispose","enableDismissTrigger"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAMA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,OAAO;EACpB,MAAMC,QAAQ,GAAG,UAAU;EAC3B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAEhC,MAAME,WAAW,GAAG,CAAA,KAAA,EAAQD,SAAS,CAAA,CAAE;EACvC,MAAME,YAAY,GAAG,CAAA,MAAA,EAASF,SAAS,CAAA,CAAE;EACzC,MAAMG,eAAe,GAAG,MAAM;EAC9B,MAAMC,eAAe,GAAG,MAAM;;EAE9B;EACA;EACA;;EAEA,MAAMC,KAAK,SAASC,aAAa,CAAC;EAChC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,KAAKA,GAAG;MACN,MAAMC,UAAU,GAAGC,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAEV,WAAW,CAAC;MAEnE,IAAIO,UAAU,CAACI,gBAAgB,EAAE;EAC/B,MAAA;EACF,IAAA;MAEA,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACC,MAAM,CAACV,eAAe,CAAC;MAE/C,MAAMW,UAAU,GAAG,IAAI,CAACJ,QAAQ,CAACE,SAAS,CAACG,QAAQ,CAACb,eAAe,CAAC;EACpE,IAAA,IAAI,CAACc,cAAc,CAAC,MAAM,IAAI,CAACC,eAAe,EAAE,EAAE,IAAI,CAACP,QAAQ,EAAEI,UAAU,CAAC;EAC9E,EAAA;;EAEA;EACAG,EAAAA,eAAeA,GAAG;EAChB,IAAA,IAAI,CAACP,QAAQ,CAACG,MAAM,EAAE;MACtBL,YAAY,CAACC,OAAO,CAAC,IAAI,CAACC,QAAQ,EAAET,YAAY,CAAC;MACjD,IAAI,CAACiB,OAAO,EAAE;EAChB,EAAA;EACF;;EAEA;EACA;EACA;;AAEAC,4CAAoB,CAACf,KAAK,EAAE,OAAO,CAAC;;;;;;;;"}
+4 -20
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Button = factory(global.BaseComponent, global.EventHandler, global.Index));
})(this, (function (BaseComponent, EventHandler, index_js) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./base-component.js'), require('./dom/event-handler.js')) :
typeof define === 'function' && define.amd ? define(['./base-component', './dom/event-handler'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Button = factory(global.BaseComponent, global.EventHandler));
})(this, (function (BaseComponent, EventHandler) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -44,16 +44,6 @@
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE));
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this);
if (config === 'toggle') {
data[config]();
}
});
}
}
/**
@@ -67,12 +57,6 @@
data.toggle();
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Button);
return Button;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"button.js","sources":["../src/button.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Button.getOrCreateInstance(this)\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Button)\n\nexport default Button\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","CLASS_NAME_ACTIVE","SELECTOR_DATA_TOGGLE","EVENT_CLICK_DATA_API","Button","BaseComponent","toggle","_element","setAttribute","classList","jQueryInterface","config","each","data","getOrCreateInstance","EventHandler","on","document","event","preventDefault","button","target","closest","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAMA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,QAAQ;EACrB,MAAMC,QAAQ,GAAG,WAAW;EAC5B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAChC,MAAME,YAAY,GAAG,WAAW;EAEhC,MAAMC,iBAAiB,GAAG,QAAQ;EAClC,MAAMC,oBAAoB,GAAG,2BAA2B;EACxD,MAAMC,oBAAoB,GAAG,CAAA,KAAA,EAAQJ,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;;EAE/D;EACA;EACA;;EAEA,MAAMI,MAAM,SAASC,aAAa,CAAC;EACjC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,MAAMA,GAAG;EACP;EACA,IAAA,IAAI,CAACC,QAAQ,CAACC,YAAY,CAAC,cAAc,EAAE,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACH,MAAM,CAACL,iBAAiB,CAAC,CAAC;EAC/F,EAAA;;EAEA;IACA,OAAOS,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;EAC3B,MAAA,MAAMC,IAAI,GAAGT,MAAM,CAACU,mBAAmB,CAAC,IAAI,CAAC;QAE7C,IAAIH,MAAM,KAAK,QAAQ,EAAE;EACvBE,QAAAA,IAAI,CAACF,MAAM,CAAC,EAAE;EAChB,MAAA;EACF,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;EAEAI,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAEd,oBAAoB,EAAED,oBAAoB,EAAEgB,KAAK,IAAI;IAC7EA,KAAK,CAACC,cAAc,EAAE;IAEtB,MAAMC,MAAM,GAAGF,KAAK,CAACG,MAAM,CAACC,OAAO,CAACpB,oBAAoB,CAAC;EACzD,EAAA,MAAMW,IAAI,GAAGT,MAAM,CAACU,mBAAmB,CAACM,MAAM,CAAC;IAE/CP,IAAI,CAACP,MAAM,EAAE;EACf,CAAC,CAAC;;EAEF;EACA;EACA;;AAEAiB,6BAAkB,CAACnB,MAAM,CAAC;;;;;;;;"}
{"version":3,"file":"button.js","sources":["../src/button.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport BaseComponent from './base-component.js'\nimport EventHandler from './dom/event-handler.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'button'\nconst DATA_KEY = 'bs.button'\nconst EVENT_KEY = `.${DATA_KEY}`\nconst DATA_API_KEY = '.data-api'\n\nconst CLASS_NAME_ACTIVE = 'active'\nconst SELECTOR_DATA_TOGGLE = '[data-bs-toggle=\"button\"]'\nconst EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`\n\n/**\n * Class definition\n */\n\nclass Button extends BaseComponent {\n // Getters\n static get NAME() {\n return NAME\n }\n\n // Public\n toggle() {\n // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method\n this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))\n }\n}\n\n/**\n * Data API implementation\n */\n\nEventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {\n event.preventDefault()\n\n const button = event.target.closest(SELECTOR_DATA_TOGGLE)\n const data = Button.getOrCreateInstance(button)\n\n data.toggle()\n})\n\nexport default Button\n"],"names":["NAME","DATA_KEY","EVENT_KEY","DATA_API_KEY","CLASS_NAME_ACTIVE","SELECTOR_DATA_TOGGLE","EVENT_CLICK_DATA_API","Button","BaseComponent","toggle","_element","setAttribute","classList","EventHandler","on","document","event","preventDefault","button","target","closest","data","getOrCreateInstance"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAKA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,QAAQ;EACrB,MAAMC,QAAQ,GAAG,WAAW;EAC5B,MAAMC,SAAS,GAAG,CAAA,CAAA,EAAID,QAAQ,CAAA,CAAE;EAChC,MAAME,YAAY,GAAG,WAAW;EAEhC,MAAMC,iBAAiB,GAAG,QAAQ;EAClC,MAAMC,oBAAoB,GAAG,2BAA2B;EACxD,MAAMC,oBAAoB,GAAG,CAAA,KAAA,EAAQJ,SAAS,CAAA,EAAGC,YAAY,CAAA,CAAE;;EAE/D;EACA;EACA;;EAEA,MAAMI,MAAM,SAASC,aAAa,CAAC;EACjC;IACA,WAAWR,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAS,EAAAA,MAAMA,GAAG;EACP;EACA,IAAA,IAAI,CAACC,QAAQ,CAACC,YAAY,CAAC,cAAc,EAAE,IAAI,CAACD,QAAQ,CAACE,SAAS,CAACH,MAAM,CAACL,iBAAiB,CAAC,CAAC;EAC/F,EAAA;EACF;;EAEA;EACA;EACA;;EAEAS,YAAY,CAACC,EAAE,CAACC,QAAQ,EAAET,oBAAoB,EAAED,oBAAoB,EAAEW,KAAK,IAAI;IAC7EA,KAAK,CAACC,cAAc,EAAE;IAEtB,MAAMC,MAAM,GAAGF,KAAK,CAACG,MAAM,CAACC,OAAO,CAACf,oBAAoB,CAAC;EACzD,EAAA,MAAMgB,IAAI,GAAGd,MAAM,CAACe,mBAAmB,CAACJ,MAAM,CAAC;IAE/CG,IAAI,CAACZ,MAAM,EAAE;EACf,CAAC,CAAC;;;;;;;;"}
-23
View File
@@ -325,23 +325,6 @@
}
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config);
if (typeof config === 'number') {
data.to(config);
return;
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -376,12 +359,6 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Carousel);
return Carousel;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
-23
View File
@@ -202,23 +202,6 @@
element.setAttribute('aria-expanded', isOpen);
}
}
// Static
static jQueryInterface(config) {
const _config = {};
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false;
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
}
});
}
}
/**
@@ -237,12 +220,6 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Collapse);
return Collapse;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+6 -29
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('../util/index.js')) :
typeof define === 'function' && define.amd ? define(['../util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.EventHandler = factory(global.Index));
})(this, (function (index_js) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.EventHandler = factory());
})(this, (function () { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -16,7 +16,6 @@
* --------------------------------------------------------------------------
*/
/**
* Constants
*/
@@ -185,33 +184,11 @@
if (typeof event !== 'string' || !element) {
return null;
}
const $ = index_js.getjQuery();
const typeEvent = getTypeEvent(event);
const inNamespace = event !== typeEvent;
let jQueryEvent = null;
let bubbles = true;
let nativeDispatch = true;
let defaultPrevented = false;
if (inNamespace && $) {
jQueryEvent = $.Event(event, args);
$(element).trigger(jQueryEvent);
bubbles = !jQueryEvent.isPropagationStopped();
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
defaultPrevented = jQueryEvent.isDefaultPrevented();
}
const evt = hydrateObj(new Event(event, {
bubbles,
bubbles: true,
cancelable: true
}), args);
if (defaultPrevented) {
evt.preventDefault();
}
if (nativeDispatch) {
element.dispatchEvent(evt);
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault();
}
element.dispatchEvent(evt);
return evt;
}
};
+1 -1
View File
File diff suppressed because one or more lines are too long
-20
View File
@@ -301,20 +301,6 @@
// allow cycling to get the last item in case key equals ARROW_UP_KEY
index_js.getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus();
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY) {
return;
@@ -390,12 +376,6 @@
Dropdown.getOrCreateInstance(this).toggle();
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Dropdown);
return Dropdown;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
-20
View File
@@ -261,20 +261,6 @@
this._element.style.paddingLeft = '';
this._element.style.paddingRight = '';
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](relatedTarget);
});
}
}
/**
@@ -308,12 +294,6 @@
});
componentFunctions_js.enableDismissTrigger(Modal);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Modal);
return Modal;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
-20
View File
@@ -177,20 +177,6 @@
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
});
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
});
}
}
/**
@@ -234,12 +220,6 @@
});
componentFunctions_js.enableDismissTrigger(Offcanvas);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Offcanvas);
return Offcanvas;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+4 -24
View File
@@ -4,10 +4,10 @@
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./tooltip.js'), require('./util/index.js')) :
typeof define === 'function' && define.amd ? define(['./tooltip', './util/index'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Popover = factory(global.Tooltip, global.Index));
})(this, (function (Tooltip, index_js) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('./tooltip.js')) :
typeof define === 'function' && define.amd ? define(['./tooltip'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Popover = factory(global.Tooltip));
})(this, (function (Tooltip) { 'use strict';
/**
* --------------------------------------------------------------------------
@@ -68,28 +68,8 @@
_getContent() {
return this._resolvePossibleFunction(this._config.content);
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
index_js.defineJQueryPlugin(Popover);
return Popover;
}));
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"popover.js","sources":["../src/popover.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\nimport { defineJQueryPlugin } from './util/index.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '<div class=\"popover\" role=\"tooltip\">' +\n '<div class=\"popover-arrow\"></div>' +\n '<h3 class=\"popover-header\"></h3>' +\n '<div class=\"popover-body\"></div>' +\n '</div>',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n\n // Static\n static jQueryInterface(config) {\n return this.each(function () {\n const data = Popover.getOrCreateInstance(this, config)\n\n if (typeof config !== 'string') {\n return\n }\n\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n\n data[config]()\n })\n }\n}\n\n/**\n * jQuery\n */\n\ndefineJQueryPlugin(Popover)\n\nexport default Popover\n"],"names":["NAME","SELECTOR_TITLE","SELECTOR_CONTENT","Default","Tooltip","content","offset","placement","template","trigger","DefaultType","Popover","_isWithContent","_getTitle","_getContent","_getContentForTemplate","_resolvePossibleFunction","_config","jQueryInterface","config","each","data","getOrCreateInstance","TypeError","defineJQueryPlugin"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAKA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,SAAS;EAEtB,MAAMC,cAAc,GAAG,iBAAiB;EACxC,MAAMC,gBAAgB,GAAG,eAAe;EAExC,MAAMC,OAAO,GAAG;IACd,GAAGC,OAAO,CAACD,OAAO;EAClBE,EAAAA,OAAO,EAAE,EAAE;EACXC,EAAAA,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACdC,EAAAA,SAAS,EAAE,OAAO;IAClBC,QAAQ,EAAE,sCAAsC,GAC9C,mCAAmC,GACnC,kCAAkC,GAClC,kCAAkC,GAClC,QAAQ;EACVC,EAAAA,OAAO,EAAE;EACX,CAAC;EAED,MAAMC,WAAW,GAAG;IAClB,GAAGN,OAAO,CAACM,WAAW;EACtBL,EAAAA,OAAO,EAAE;EACX,CAAC;;EAED;EACA;EACA;;EAEA,MAAMM,OAAO,SAASP,OAAO,CAAC;EAC5B;IACA,WAAWD,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWO,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWV,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAY,EAAAA,cAAcA,GAAG;MACf,OAAO,IAAI,CAACC,SAAS,EAAE,IAAI,IAAI,CAACC,WAAW,EAAE;EAC/C,EAAA;;EAEA;EACAC,EAAAA,sBAAsBA,GAAG;MACvB,OAAO;EACL,MAAA,CAACd,cAAc,GAAG,IAAI,CAACY,SAAS,EAAE;EAClC,MAAA,CAACX,gBAAgB,GAAG,IAAI,CAACY,WAAW;OACrC;EACH,EAAA;EAEAA,EAAAA,WAAWA,GAAG;MACZ,OAAO,IAAI,CAACE,wBAAwB,CAAC,IAAI,CAACC,OAAO,CAACZ,OAAO,CAAC;EAC5D,EAAA;;EAEA;IACA,OAAOa,eAAeA,CAACC,MAAM,EAAE;EAC7B,IAAA,OAAO,IAAI,CAACC,IAAI,CAAC,YAAY;QAC3B,MAAMC,IAAI,GAAGV,OAAO,CAACW,mBAAmB,CAAC,IAAI,EAAEH,MAAM,CAAC;EAEtD,MAAA,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;EAC9B,QAAA;EACF,MAAA;EAEA,MAAA,IAAI,OAAOE,IAAI,CAACF,MAAM,CAAC,KAAK,WAAW,EAAE;EACvC,QAAA,MAAM,IAAII,SAAS,CAAC,CAAA,iBAAA,EAAoBJ,MAAM,GAAG,CAAC;EACpD,MAAA;EAEAE,MAAAA,IAAI,CAACF,MAAM,CAAC,EAAE;EAChB,IAAA,CAAC,CAAC;EACJ,EAAA;EACF;;EAEA;EACA;EACA;;AAEAK,6BAAkB,CAACb,OAAO,CAAC;;;;;;;;"}
{"version":3,"file":"popover.js","sources":["../src/popover.js"],"sourcesContent":["/**\n * --------------------------------------------------------------------------\n * Bootstrap popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nimport Tooltip from './tooltip.js'\n\n/**\n * Constants\n */\n\nconst NAME = 'popover'\n\nconst SELECTOR_TITLE = '.popover-header'\nconst SELECTOR_CONTENT = '.popover-body'\n\nconst Default = {\n ...Tooltip.Default,\n content: '',\n offset: [0, 8],\n placement: 'right',\n template: '<div class=\"popover\" role=\"tooltip\">' +\n '<div class=\"popover-arrow\"></div>' +\n '<h3 class=\"popover-header\"></h3>' +\n '<div class=\"popover-body\"></div>' +\n '</div>',\n trigger: 'click'\n}\n\nconst DefaultType = {\n ...Tooltip.DefaultType,\n content: '(null|string|element|function)'\n}\n\n/**\n * Class definition\n */\n\nclass Popover extends Tooltip {\n // Getters\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n static get NAME() {\n return NAME\n }\n\n // Overrides\n _isWithContent() {\n return this._getTitle() || this._getContent()\n }\n\n // Private\n _getContentForTemplate() {\n return {\n [SELECTOR_TITLE]: this._getTitle(),\n [SELECTOR_CONTENT]: this._getContent()\n }\n }\n\n _getContent() {\n return this._resolvePossibleFunction(this._config.content)\n }\n}\n\nexport default Popover\n"],"names":["NAME","SELECTOR_TITLE","SELECTOR_CONTENT","Default","Tooltip","content","offset","placement","template","trigger","DefaultType","Popover","_isWithContent","_getTitle","_getContent","_getContentForTemplate","_resolvePossibleFunction","_config"],"mappings":";;;;;;;;;;;EAAA;EACA;EACA;EACA;EACA;EACA;;;EAIA;EACA;EACA;;EAEA,MAAMA,IAAI,GAAG,SAAS;EAEtB,MAAMC,cAAc,GAAG,iBAAiB;EACxC,MAAMC,gBAAgB,GAAG,eAAe;EAExC,MAAMC,OAAO,GAAG;IACd,GAAGC,OAAO,CAACD,OAAO;EAClBE,EAAAA,OAAO,EAAE,EAAE;EACXC,EAAAA,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;EACdC,EAAAA,SAAS,EAAE,OAAO;IAClBC,QAAQ,EAAE,sCAAsC,GAC9C,mCAAmC,GACnC,kCAAkC,GAClC,kCAAkC,GAClC,QAAQ;EACVC,EAAAA,OAAO,EAAE;EACX,CAAC;EAED,MAAMC,WAAW,GAAG;IAClB,GAAGN,OAAO,CAACM,WAAW;EACtBL,EAAAA,OAAO,EAAE;EACX,CAAC;;EAED;EACA;EACA;;EAEA,MAAMM,OAAO,SAASP,OAAO,CAAC;EAC5B;IACA,WAAWD,OAAOA,GAAG;EACnB,IAAA,OAAOA,OAAO;EAChB,EAAA;IAEA,WAAWO,WAAWA,GAAG;EACvB,IAAA,OAAOA,WAAW;EACpB,EAAA;IAEA,WAAWV,IAAIA,GAAG;EAChB,IAAA,OAAOA,IAAI;EACb,EAAA;;EAEA;EACAY,EAAAA,cAAcA,GAAG;MACf,OAAO,IAAI,CAACC,SAAS,EAAE,IAAI,IAAI,CAACC,WAAW,EAAE;EAC/C,EAAA;;EAEA;EACAC,EAAAA,sBAAsBA,GAAG;MACvB,OAAO;EACL,MAAA,CAACd,cAAc,GAAG,IAAI,CAACY,SAAS,EAAE;EAClC,MAAA,CAACX,gBAAgB,GAAG,IAAI,CAACY,WAAW;OACrC;EACH,EAAA;EAEAA,EAAAA,WAAWA,GAAG;MACZ,OAAO,IAAI,CAACE,wBAAwB,CAAC,IAAI,CAACC,OAAO,CAACZ,OAAO,CAAC;EAC5D,EAAA;EACF;;;;;;;;"}
-20
View File
@@ -237,20 +237,6 @@
node.classList.remove(CLASS_NAME_ACTIVE);
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -263,12 +249,6 @@
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(ScrollSpy);
return ScrollSpy;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
-19
View File
@@ -235,20 +235,6 @@
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this);
if (typeof config !== 'string') {
return;
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
@@ -273,11 +259,6 @@
Tab.getOrCreateInstance(element);
}
});
/**
* jQuery
*/
index_js.defineJQueryPlugin(Tab);
return Tab;
+1 -1
View File
File diff suppressed because one or more lines are too long
-19
View File
@@ -165,19 +165,6 @@
clearTimeout(this._timeout);
this._timeout = null;
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config);
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config](this);
}
});
}
}
/**
@@ -186,12 +173,6 @@
componentFunctions_js.enableDismissTrigger(Toast);
/**
* jQuery
*/
index_js.defineJQueryPlugin(Toast);
return Toast;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
-20
View File
@@ -518,28 +518,8 @@
this.tip = null;
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config);
if (typeof config !== 'string') {
return;
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`);
}
data[config]();
});
}
}
/**
* jQuery
*/
index_js.defineJQueryPlugin(Tooltip);
return Tooltip;
}));
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -29
View File
@@ -81,15 +81,11 @@
if (!object || typeof object !== 'object') {
return false;
}
if (typeof object.jquery !== 'undefined') {
object = object[0];
}
return typeof object.nodeType !== 'undefined';
};
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object;
return object;
}
if (typeof object === 'string' && object.length > 0) {
return document.querySelector(parseSelector(object));
@@ -162,12 +158,6 @@
const reflow = element => {
element.offsetHeight; // eslint-disable-line no-unused-expressions
};
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery;
}
return null;
};
const DOMContentLoadedCallbacks = [];
const onDOMContentLoaded = callback => {
if (document.readyState === 'loading') {
@@ -185,22 +175,6 @@
}
};
const isRTL = () => document.documentElement.dir === 'rtl';
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery();
/* istanbul ignore if */
if ($) {
const name = plugin.NAME;
const JQUERY_NO_CONFLICT = $.fn[name];
$.fn[name] = plugin.jQueryInterface;
$.fn[name].Constructor = plugin;
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT;
return plugin.jQueryInterface;
};
}
});
};
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
};
@@ -255,7 +229,6 @@
return list[Math.max(0, Math.min(index, listLength - 1))];
};
exports.defineJQueryPlugin = defineJQueryPlugin;
exports.execute = execute;
exports.executeAfterTransition = executeAfterTransition;
exports.findShadowRoot = findShadowRoot;
@@ -263,7 +236,6 @@
exports.getNextActiveElement = getNextActiveElement;
exports.getTransitionDurationFromElement = getTransitionDurationFromElement;
exports.getUID = getUID;
exports.getjQuery = getjQuery;
exports.isDisabled = isDisabled;
exports.isElement = isElement;
exports.isRTL = isRTL;
+1 -1
View File
File diff suppressed because one or more lines are too long
-24
View File
@@ -8,7 +8,6 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { enableDismissTrigger } from './util/component-functions.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -53,23 +52,6 @@ class Alert extends BaseComponent {
EventHandler.trigger(this._element, EVENT_CLOSED)
this.dispose()
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Alert.getOrCreateInstance(this)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
})
}
}
/**
@@ -78,10 +60,4 @@ class Alert extends BaseComponent {
enableDismissTrigger(Alert, 'close')
/**
* jQuery
*/
defineJQueryPlugin(Alert)
export default Alert
-18
View File
@@ -7,7 +7,6 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -37,17 +36,6 @@ class Button extends BaseComponent {
// Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Button.getOrCreateInstance(this)
if (config === 'toggle') {
data[config]()
}
})
}
}
/**
@@ -63,10 +51,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
data.toggle()
})
/**
* jQuery
*/
defineJQueryPlugin(Button)
export default Button
-27
View File
@@ -10,7 +10,6 @@ import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
getNextActiveElement,
isRTL,
isVisible,
@@ -403,26 +402,6 @@ class Carousel extends BaseComponent {
return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Carousel.getOrCreateInstance(this, config)
if (typeof config === 'number') {
data.to(config)
return
}
if (typeof config === 'string') {
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
}
})
}
}
/**
@@ -465,10 +444,4 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
}
})
/**
* jQuery
*/
defineJQueryPlugin(Carousel)
export default Carousel
-27
View File
@@ -9,7 +9,6 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
getElement,
reflow
} from './util/index.js'
@@ -251,26 +250,6 @@ class Collapse extends BaseComponent {
element.setAttribute('aria-expanded', isOpen)
}
}
// Static
static jQueryInterface(config) {
const _config = {}
if (typeof config === 'string' && /show|hide/.test(config)) {
_config.toggle = false
}
return this.each(function () {
const data = Collapse.getOrCreateInstance(this, _config)
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
}
})
}
}
/**
@@ -288,10 +267,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
}
})
/**
* jQuery
*/
defineJQueryPlugin(Collapse)
export default Collapse
+2 -34
View File
@@ -5,8 +5,6 @@
* --------------------------------------------------------------------------
*/
import { getjQuery } from '../util/index.js'
/**
* Constants
*/
@@ -261,38 +259,8 @@ const EventHandler = {
return null
}
const $ = getjQuery()
const typeEvent = getTypeEvent(event)
const inNamespace = event !== typeEvent
let jQueryEvent = null
let bubbles = true
let nativeDispatch = true
let defaultPrevented = false
if (inNamespace && $) {
jQueryEvent = $.Event(event, args)
$(element).trigger(jQueryEvent)
bubbles = !jQueryEvent.isPropagationStopped()
nativeDispatch = !jQueryEvent.isImmediatePropagationStopped()
defaultPrevented = jQueryEvent.isDefaultPrevented()
}
const evt = hydrateObj(new Event(event, { bubbles, cancelable: true }), args)
if (defaultPrevented) {
evt.preventDefault()
}
if (nativeDispatch) {
element.dispatchEvent(evt)
}
if (evt.defaultPrevented && jQueryEvent) {
jQueryEvent.preventDefault()
}
const evt = hydrateObj(new Event(event, { bubbles: true, cancelable: true }), args)
element.dispatchEvent(evt)
return evt
}
}
-24
View File
@@ -11,7 +11,6 @@ import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin,
execute,
getElement,
getNextActiveElement,
@@ -336,23 +335,6 @@ class Dropdown extends BaseComponent {
getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus()
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Dropdown.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
static clearMenus(event) {
if (event.button === RIGHT_MOUSE_BUTTON || (event.type === 'keyup' && event.key !== TAB_KEY)) {
return
@@ -446,10 +428,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
Dropdown.getOrCreateInstance(this).toggle()
})
/**
* jQuery
*/
defineJQueryPlugin(Dropdown)
export default Dropdown
+1 -24
View File
@@ -12,7 +12,7 @@ import Backdrop from './util/backdrop.js'
import { enableDismissTrigger } from './util/component-functions.js'
import FocusTrap from './util/focustrap.js'
import {
defineJQueryPlugin, isRTL, isVisible, reflow
isRTL, isVisible, reflow
} from './util/index.js'
import ScrollBarHelper from './util/scrollbar.js'
@@ -313,23 +313,6 @@ class Modal extends BaseComponent {
this._element.style.paddingLeft = ''
this._element.style.paddingRight = ''
}
// Static
static jQueryInterface(config, relatedTarget) {
return this.each(function () {
const data = Modal.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config](relatedTarget)
})
}
}
/**
@@ -369,10 +352,4 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (
enableDismissTrigger(Modal)
/**
* jQuery
*/
defineJQueryPlugin(Modal)
export default Modal
-24
View File
@@ -12,7 +12,6 @@ import Backdrop from './util/backdrop.js'
import { enableDismissTrigger } from './util/component-functions.js'
import FocusTrap from './util/focustrap.js'
import {
defineJQueryPlugin,
isDisabled,
isVisible
} from './util/index.js'
@@ -206,23 +205,6 @@ class Offcanvas extends BaseComponent {
EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED)
})
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Offcanvas.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
})
}
}
/**
@@ -273,10 +255,4 @@ EventHandler.on(window, EVENT_RESIZE, () => {
enableDismissTrigger(Offcanvas)
/**
* jQuery
*/
defineJQueryPlugin(Offcanvas)
export default Offcanvas
-24
View File
@@ -6,7 +6,6 @@
*/
import Tooltip from './tooltip.js'
import { defineJQueryPlugin } from './util/index.js'
/**
* Constants
@@ -69,29 +68,6 @@ class Popover extends Tooltip {
_getContent() {
return this._resolvePossibleFunction(this._config.content)
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Popover.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
* jQuery
*/
defineJQueryPlugin(Popover)
export default Popover
+1 -24
View File
@@ -9,7 +9,7 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import {
defineJQueryPlugin, getElement, isDisabled, isVisible
getElement, isDisabled, isVisible
} from './util/index.js'
/**
@@ -258,23 +258,6 @@ class ScrollSpy extends BaseComponent {
node.classList.remove(CLASS_NAME_ACTIVE)
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = ScrollSpy.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
@@ -287,10 +270,4 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
}
})
/**
* jQuery
*/
defineJQueryPlugin(ScrollSpy)
export default ScrollSpy
+1 -23
View File
@@ -8,7 +8,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import SelectorEngine from './dom/selector-engine.js'
import { defineJQueryPlugin, getNextActiveElement, isDisabled } from './util/index.js'
import { getNextActiveElement, isDisabled } from './util/index.js'
/**
* Constants
@@ -263,23 +263,6 @@ class Tab extends BaseComponent {
_getOuterElement(elem) {
return elem.closest(SELECTOR_OUTER) || elem
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tab.getOrCreateInstance(this)
if (typeof config !== 'string') {
return
}
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
@@ -306,10 +289,5 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
Tab.getOrCreateInstance(element)
}
})
/**
* jQuery
*/
defineJQueryPlugin(Tab)
export default Tab
+1 -22
View File
@@ -8,7 +8,7 @@
import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import { enableDismissTrigger } from './util/component-functions.js'
import { defineJQueryPlugin, reflow } from './util/index.js'
import { reflow } from './util/index.js'
/**
* Constants
@@ -192,21 +192,6 @@ class Toast extends BaseComponent {
clearTimeout(this._timeout)
this._timeout = null
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Toast.getOrCreateInstance(this, config)
if (typeof config === 'string') {
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config](this)
}
})
}
}
/**
@@ -215,10 +200,4 @@ class Toast extends BaseComponent {
enableDismissTrigger(Toast)
/**
* jQuery
*/
defineJQueryPlugin(Toast)
export default Toast
+1 -25
View File
@@ -10,7 +10,7 @@ import BaseComponent from './base-component.js'
import EventHandler from './dom/event-handler.js'
import Manipulator from './dom/manipulator.js'
import {
defineJQueryPlugin, execute, findShadowRoot, getElement, getUID, isRTL, noop
execute, findShadowRoot, getElement, getUID, isRTL, noop
} from './util/index.js'
import { DefaultAllowlist } from './util/sanitizer.js'
import TemplateFactory from './util/template-factory.js'
@@ -605,29 +605,5 @@ class Tooltip extends BaseComponent {
this.tip = null
}
}
// Static
static jQueryInterface(config) {
return this.each(function () {
const data = Tooltip.getOrCreateInstance(this, config)
if (typeof config !== 'string') {
return
}
if (typeof data[config] === 'undefined') {
throw new TypeError(`No method named "${config}"`)
}
data[config]()
})
}
}
/**
* jQuery
*/
defineJQueryPlugin(Tooltip)
export default Tooltip
+1 -33
View File
@@ -76,17 +76,12 @@ const isElement = object => {
return false
}
if (typeof object.jquery !== 'undefined') {
object = object[0]
}
return typeof object.nodeType !== 'undefined'
}
const getElement = object => {
// it's a jQuery object or a node element
if (isElement(object)) {
return object.jquery ? object[0] : object
return object
}
if (typeof object === 'string' && object.length > 0) {
@@ -176,14 +171,6 @@ const reflow = element => {
element.offsetHeight // eslint-disable-line no-unused-expressions
}
const getjQuery = () => {
if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
return window.jQuery
}
return null
}
const DOMContentLoadedCallbacks = []
const onDOMContentLoaded = callback => {
@@ -205,23 +192,6 @@ const onDOMContentLoaded = callback => {
const isRTL = () => document.documentElement.dir === 'rtl'
const defineJQueryPlugin = plugin => {
onDOMContentLoaded(() => {
const $ = getjQuery()
/* istanbul ignore if */
if ($) {
const name = plugin.NAME
const JQUERY_NO_CONFLICT = $.fn[name]
$.fn[name] = plugin.jQueryInterface
$.fn[name].Constructor = plugin
$.fn[name].noConflict = () => {
$.fn[name] = JQUERY_NO_CONFLICT
return plugin.jQueryInterface
}
}
})
}
const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue
}
@@ -284,12 +254,10 @@ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed
}
export {
defineJQueryPlugin,
execute,
executeAfterTransition,
findShadowRoot,
getElement,
getjQuery,
getNextActiveElement,
getTransitionDurationFromElement,
getUID,
-10
View File
@@ -27,16 +27,6 @@ export const createEvent = (eventName, parameters = {}) => {
return new Event(eventName, parameters)
}
export const jQueryMock = {
elements: undefined,
fn: {},
each(fn) {
for (const element of this.elements) {
fn.call(element)
}
}
}
export const clearBodyAndDocument = () => {
const attributes = ['data-bs-padding-right', 'style']
+1 -17
View File
@@ -11,7 +11,6 @@ const { browsers } = require('./browsers.js')
const ENV = process.env
const BROWSERSTACK = Boolean(ENV.BROWSERSTACK)
const DEBUG = Boolean(ENV.DEBUG)
const JQUERY_TEST = Boolean(ENV.JQUERY)
const frameworks = [
'jasmine'
@@ -61,7 +60,7 @@ const config = {
files: [
'node_modules/hammer-simulator/index.js',
{
pattern: 'js/tests/unit/**/!(jquery).spec.js',
pattern: 'js/tests/unit/**/*.spec.js',
watched: !BROWSERSTACK
}
],
@@ -111,21 +110,6 @@ if (BROWSERSTACK) {
config.customLaunchers = browsers
config.browsers = Object.keys(browsers)
reporters.push('BrowserStack', 'kjhtml')
} else if (JQUERY_TEST) {
frameworks.push('detectBrowsers')
plugins.push(
'karma-chrome-launcher',
'karma-firefox-launcher',
'karma-detect-browsers'
)
config.detectBrowsers = detectBrowsers
config.files = [
'node_modules/jquery/dist/jquery.slim.min.js',
{
pattern: 'js/tests/unit/jquery.spec.js',
watched: false
}
]
} else {
frameworks.push('detectBrowsers')
plugins.push(
+1 -75
View File
@@ -1,6 +1,6 @@
import Alert from '../../src/alert.js'
import { getTransitionDurationFromElement } from '../../src/util/index.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
describe('Alert', () => {
let fixtureEl
@@ -141,80 +141,6 @@ describe('Alert', () => {
})
})
describe('jQueryInterface', () => {
it('should handle config passed and toggle existing alert', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
const alert = new Alert(alertEl)
const spy = spyOn(alert, 'close')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
jQueryMock.fn.alert.call(jQueryMock, 'close')
expect(spy).toHaveBeenCalled()
})
it('should create new alert instance and call close', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
expect(Alert.getInstance(alertEl)).toBeNull()
jQueryMock.fn.alert.call(jQueryMock, 'close')
expect(fixtureEl.querySelector('.alert')).toBeNull()
})
it('should just create an alert instance without calling close', () => {
fixtureEl.innerHTML = '<div class="alert"></div>'
const alertEl = fixtureEl.querySelector('.alert')
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [alertEl]
jQueryMock.fn.alert.call(jQueryMock)
expect(Alert.getInstance(alertEl)).not.toBeNull()
expect(fixtureEl.querySelector('.alert')).not.toBeNull()
})
it('should throw an error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.alert.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw an error on protected method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = '_getConfig'
jQueryMock.fn.alert = Alert.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.alert.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return alert instance', () => {
fixtureEl.innerHTML = '<div></div>'
+1 -8
View File
@@ -124,18 +124,11 @@ describe('Base Component', () => {
expect(DummyClass.getInstance(element)).toBeInstanceOf(DummyClass)
})
it('should accept element, either passed as a CSS selector, jQuery element, or DOM element', () => {
it('should accept element, either passed as a CSS selector or DOM element', () => {
createInstance()
expect(DummyClass.getInstance('#foo')).toEqual(instance)
expect(DummyClass.getInstance(element)).toEqual(instance)
const fakejQueryObject = {
0: element,
jquery: 'foo'
}
expect(DummyClass.getInstance(fakejQueryObject)).toEqual(instance)
})
it('should return null when there is no instance', () => {
+1 -47
View File
@@ -1,5 +1,5 @@
import Button from '../../src/button.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
describe('Button', () => {
let fixtureEl
@@ -93,52 +93,6 @@ describe('Button', () => {
})
})
describe('jQueryInterface', () => {
it('should handle config passed and toggle existing button', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
const button = new Button(btnEl)
const spy = spyOn(button, 'toggle')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock, 'toggle')
expect(spy).toHaveBeenCalled()
})
it('should create new button instance and call toggle', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock, 'toggle')
expect(Button.getInstance(btnEl)).not.toBeNull()
expect(btnEl).toHaveClass('active')
})
it('should just create a button instance without calling toggle', () => {
fixtureEl.innerHTML = '<button class="btn" data-bs-toggle="button"></button>'
const btnEl = fixtureEl.querySelector('.btn')
jQueryMock.fn.button = Button.jQueryInterface
jQueryMock.elements = [btnEl]
jQueryMock.fn.button.call(jQueryMock)
expect(Button.getInstance(btnEl)).not.toBeNull()
expect(btnEl).not.toHaveClass('active')
})
})
describe('getInstance', () => {
it('should return button instance', () => {
fixtureEl.innerHTML = '<div></div>'
+1 -61
View File
@@ -3,7 +3,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import { isRTL, noop } from '../../src/util/index.js'
import Swipe from '../../src/util/swipe.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Carousel', () => {
@@ -1379,66 +1379,6 @@ describe('Carousel', () => {
})
})
describe('jQueryInterface', () => {
it('should create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).not.toBeNull()
})
it('should not re create a carousel', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock)
expect(Carousel.getInstance(div)).toEqual(carousel)
})
it('should call to if the config is a number', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const carousel = new Carousel(div)
const slideTo = 2
const spy = spyOn(carousel, 'to')
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.carousel.call(jQueryMock, slideTo)
expect(spy).toHaveBeenCalledWith(slideTo)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.carousel = Carousel.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.carousel.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('data-api', () => {
it('should init carousels with data-bs-ride="carousel" on load', () => {
fixtureEl.innerHTML = '<div data-bs-ride="carousel"></div>'
+2 -68
View File
@@ -1,6 +1,6 @@
import Collapse from '../../src/collapse.js'
import EventHandler from '../../src/dom/event-handler.js'
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
describe('Collapse', () => {
let fixtureEl
@@ -43,30 +43,7 @@ describe('Collapse', () => {
expect(collapseByElement._element).toEqual(collapseEl)
})
it('should allow jquery object in parent config', () => {
fixtureEl.innerHTML = [
'<div class="my-collapse">',
' <div class="item">',
' <a data-bs-toggle="collapse" href="#">Toggle item</a>',
' <div class="collapse">Lorem ipsum</div>',
' </div>',
'</div>'
].join('')
const collapseEl = fixtureEl.querySelector('div.collapse')
const myCollapseEl = fixtureEl.querySelector('.my-collapse')
const fakejQueryObject = {
0: myCollapseEl,
jquery: 'foo'
}
const collapse = new Collapse(collapseEl, {
parent: fakejQueryObject
})
expect(collapse._config.parent).toEqual(myCollapseEl)
})
it('should allow non jquery object in parent config', () => {
it('should allow object in parent config', () => {
fixtureEl.innerHTML = [
'<div class="my-collapse">',
' <div class="item">',
@@ -943,49 +920,6 @@ describe('Collapse', () => {
})
})
describe('jQueryInterface', () => {
it('should create a collapse', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.collapse.call(jQueryMock)
expect(Collapse.getInstance(div)).not.toBeNull()
})
it('should not re create a collapse', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const collapse = new Collapse(div)
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.collapse.call(jQueryMock)
expect(Collapse.getInstance(div)).toEqual(collapse)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.collapse = Collapse.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.collapse.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return collapse instance', () => {
fixtureEl.innerHTML = '<div></div>'
+1 -70
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Dropdown from '../../src/dropdown.js'
import { noop } from '../../src/util/index.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Dropdown', () => {
@@ -508,32 +508,6 @@ describe('Dropdown', () => {
})
})
it('should toggle a dropdown with a jquery object reference', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
'<div class="dropdown">',
' <button class="btn dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</button>',
' <div class="dropdown-menu">',
' <a class="dropdown-item" href="#">Secondary link</a>',
' </div>',
'</div>'
].join('')
const btnDropdown = fixtureEl.querySelector('[data-bs-toggle="dropdown"]')
const dropdown = new Dropdown(btnDropdown, {
reference: { 0: fixtureEl, jquery: 'jQuery' }
})
btnDropdown.addEventListener('shown.bs.dropdown', () => {
expect(btnDropdown).toHaveClass('show')
expect(btnDropdown.getAttribute('aria-expanded')).toEqual('true')
resolve()
})
dropdown.toggle()
})
})
it('should toggle a dropdown with a valid virtual element reference', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
@@ -2218,49 +2192,6 @@ describe('Dropdown', () => {
})
})
describe('jQueryInterface', () => {
it('should create a dropdown', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.dropdown.call(jQueryMock)
expect(Dropdown.getInstance(div)).not.toBeNull()
})
it('should not re create a dropdown', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const dropdown = new Dropdown(div)
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.dropdown.call(jQueryMock)
expect(Dropdown.getInstance(div)).toEqual(dropdown)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.dropdown = Dropdown.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.dropdown.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return dropdown instance', () => {
fixtureEl.innerHTML = '<div></div>'
-60
View File
@@ -1,60 +0,0 @@
/* eslint-env jquery */
import Alert from '../../src/alert.js'
import Button from '../../src/button.js'
import Carousel from '../../src/carousel.js'
import Collapse from '../../src/collapse.js'
import Dropdown from '../../src/dropdown.js'
import Modal from '../../src/modal.js'
import Offcanvas from '../../src/offcanvas.js'
import Popover from '../../src/popover.js'
import ScrollSpy from '../../src/scrollspy.js'
import Tab from '../../src/tab.js'
import Toast from '../../src/toast.js'
import Tooltip from '../../src/tooltip.js'
import { clearFixture, getFixture } from '../helpers/fixture.js'
describe('jQuery', () => {
let fixtureEl
beforeAll(() => {
fixtureEl = getFixture()
})
afterEach(() => {
clearFixture()
})
it('should add all plugins in jQuery', () => {
expect(Alert.jQueryInterface).toEqual(jQuery.fn.alert)
expect(Button.jQueryInterface).toEqual(jQuery.fn.button)
expect(Carousel.jQueryInterface).toEqual(jQuery.fn.carousel)
expect(Collapse.jQueryInterface).toEqual(jQuery.fn.collapse)
expect(Dropdown.jQueryInterface).toEqual(jQuery.fn.dropdown)
expect(Modal.jQueryInterface).toEqual(jQuery.fn.modal)
expect(Offcanvas.jQueryInterface).toEqual(jQuery.fn.offcanvas)
expect(Popover.jQueryInterface).toEqual(jQuery.fn.popover)
expect(ScrollSpy.jQueryInterface).toEqual(jQuery.fn.scrollspy)
expect(Tab.jQueryInterface).toEqual(jQuery.fn.tab)
expect(Toast.jQueryInterface).toEqual(jQuery.fn.toast)
expect(Tooltip.jQueryInterface).toEqual(jQuery.fn.tooltip)
})
it('should use jQuery event system', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = [
'<div class="alert">',
' <button type="button" data-bs-dismiss="alert">x</button>',
'</div>'
].join('')
$(fixtureEl).find('.alert')
.one('closed.bs.alert', () => {
expect($(fixtureEl).find('.alert')).toHaveSize(0)
resolve()
})
$(fixtureEl).find('button').trigger('click')
})
})
})
+1 -91
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Modal from '../../src/modal.js'
import ScrollBarHelper from '../../src/util/scrollbar.js'
import {
clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock
clearBodyAndDocument, clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Modal', () => {
@@ -1162,96 +1162,6 @@ describe('Modal', () => {
})
})
})
describe('jQueryInterface', () => {
it('should create a modal', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock)
expect(Modal.getInstance(div)).not.toBeNull()
})
it('should create a modal with given config', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock, { keyboard: false })
const spy = spyOn(Modal.prototype, 'constructor')
expect(spy).not.toHaveBeenCalledWith(div, { keyboard: false })
const modal = Modal.getInstance(div)
expect(modal).not.toBeNull()
expect(modal._config.keyboard).toBeFalse()
})
it('should not re create a modal', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const modal = new Modal(div)
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.modal.call(jQueryMock)
expect(Modal.getInstance(div)).toEqual(modal)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.modal.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should call show method', () => {
fixtureEl.innerHTML = '<div class="modal"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
const modal = new Modal(div)
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
const spy = spyOn(modal, 'show')
jQueryMock.fn.modal.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
it('should not call show method', () => {
fixtureEl.innerHTML = '<div class="modal" data-bs-show="false"><div class="modal-dialog"></div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.modal = Modal.jQueryInterface
jQueryMock.elements = [div]
const spy = spyOn(Modal.prototype, 'show')
jQueryMock.fn.modal.call(jQueryMock)
expect(spy).not.toHaveBeenCalled()
})
})
describe('getInstance', () => {
it('should return modal instance', () => {
+1 -101
View File
@@ -3,7 +3,7 @@ import Offcanvas from '../../src/offcanvas.js'
import { isVisible } from '../../src/util/index.js'
import ScrollBarHelper from '../../src/util/scrollbar.js'
import {
clearBodyAndDocument, clearFixture, createEvent, getFixture, jQueryMock
clearBodyAndDocument, clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Offcanvas', () => {
@@ -738,106 +738,6 @@ describe('Offcanvas', () => {
})
})
describe('jQueryInterface', () => {
it('should create an offcanvas', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock)
expect(Offcanvas.getInstance(div)).not.toBeNull()
})
it('should not re create an offcanvas', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const offCanvas = new Offcanvas(div)
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock)
expect(Offcanvas.getInstance(div)).toEqual(offCanvas)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error on protected method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = '_getConfig'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error if method "constructor" is being called', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'constructor'
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.offcanvas.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should call offcanvas method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const spy = spyOn(Offcanvas.prototype, 'show')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
it('should create a offcanvas with given config', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.offcanvas = Offcanvas.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.offcanvas.call(jQueryMock, { scroll: true })
const offcanvas = Offcanvas.getInstance(div)
expect(offcanvas).not.toBeNull()
expect(offcanvas._config.scroll).toBeTrue()
})
})
describe('getInstance', () => {
it('should return offcanvas instance', () => {
fixtureEl.innerHTML = '<div></div>'
+1 -75
View File
@@ -1,7 +1,7 @@
import EventHandler from '../../src/dom/event-handler.js'
import Popover from '../../src/popover.js'
import {
clearFixture, getFixture, jQueryMock, createEvent
clearFixture, getFixture, createEvent
} from '../helpers/fixture.js'
describe('Popover', () => {
@@ -361,80 +361,6 @@ describe('Popover', () => {
})
})
describe('jQueryInterface', () => {
it('should create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover.getInstance(popoverEl)).not.toBeNull()
})
it('should create a popover with a config object', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock, {
content: 'Popover content'
})
expect(Popover.getInstance(popoverEl)).not.toBeNull()
})
it('should not re create a popover', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
jQueryMock.fn.popover.call(jQueryMock)
expect(Popover.getInstance(popoverEl)).toEqual(popover)
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const action = 'undefinedMethod'
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
expect(() => {
jQueryMock.fn.popover.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should should call show method', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl)
jQueryMock.fn.popover = Popover.jQueryInterface
jQueryMock.elements = [popoverEl]
const spy = spyOn(popover, 'show')
jQueryMock.fn.popover.call(jQueryMock, 'show')
expect(spy).toHaveBeenCalled()
})
})
describe('getInstance', () => {
it('should return popover instance', () => {
fixtureEl.innerHTML = '<a href="#" title="Popover" data-bs-content="https://x.com/getbootstrap">BS X</a>'
+1 -106
View File
@@ -1,7 +1,7 @@
import EventHandler from '../../src/dom/event-handler.js'
import ScrollSpy from '../../src/scrollspy.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('ScrollSpy', () => {
@@ -648,111 +648,6 @@ describe('ScrollSpy', () => {
})
})
describe('jQueryInterface', () => {
it('should create a scrollspy', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, { target: '#navBar' })
expect(ScrollSpy.getInstance(div)).not.toBeNull()
})
it('should create a scrollspy with given config', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, { rootMargin: '100px' })
const spy = spyOn(ScrollSpy.prototype, 'constructor')
expect(spy).not.toHaveBeenCalledWith(div, { rootMargin: '100px' })
const scrollspy = ScrollSpy.getInstance(div)
expect(scrollspy).not.toBeNull()
expect(scrollspy._config.rootMargin).toEqual('100px')
})
it('should not re create a scrollspy', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const scrollSpy = new ScrollSpy(div)
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock)
expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy)
})
it('should call a scrollspy method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const scrollSpy = new ScrollSpy(div)
const spy = spyOn(scrollSpy, 'refresh')
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.scrollspy.call(jQueryMock, 'refresh')
expect(ScrollSpy.getInstance(div)).toEqual(scrollSpy)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = 'undefinedMethod'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error on protected method', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = '_getConfig'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
it('should throw error if method "constructor" is being called', () => {
fixtureEl.innerHTML = getDummyFixture()
const div = fixtureEl.querySelector('.content')
const action = 'constructor'
jQueryMock.fn.scrollspy = ScrollSpy.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.scrollspy.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return scrollspy instance', () => {
fixtureEl.innerHTML = getDummyFixture()
+1 -61
View File
@@ -1,6 +1,6 @@
import Tab from '../../src/tab.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Tab', () => {
@@ -827,66 +827,6 @@ describe('Tab', () => {
})
})
describe('jQueryInterface', () => {
it('should create a tab', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock)
expect(Tab.getInstance(div)).not.toBeNull()
})
it('should not re create a tab', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const tab = new Tab(div)
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock)
expect(Tab.getInstance(div)).toEqual(tab)
})
it('should call a tab method', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const tab = new Tab(div)
const spy = spyOn(tab, 'show')
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tab.call(jQueryMock, 'show')
expect(Tab.getInstance(div)).toEqual(tab)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div class="nav"><div class="nav-link"></div></div>'
const div = fixtureEl.querySelector('.nav > div')
const action = 'undefinedMethod'
jQueryMock.fn.tab = Tab.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.tab.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return null if there is no instance', () => {
expect(Tab.getInstance(fixtureEl)).toBeNull()
+1 -61
View File
@@ -1,6 +1,6 @@
import Toast from '../../src/toast.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Toast', () => {
@@ -536,66 +536,6 @@ describe('Toast', () => {
})
})
describe('jQueryInterface', () => {
it('should create a toast', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock)
expect(Toast.getInstance(div)).not.toBeNull()
})
it('should not re create a toast', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const toast = new Toast(div)
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock)
expect(Toast.getInstance(div)).toEqual(toast)
})
it('should call a toast method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const toast = new Toast(div)
const spy = spyOn(toast, 'show')
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.toast.call(jQueryMock, 'show')
expect(Toast.getInstance(div)).toEqual(toast)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.toast = Toast.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.toast.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
describe('getInstance', () => {
it('should return a toast instance', () => {
fixtureEl.innerHTML = '<div></div>'
+1 -101
View File
@@ -2,7 +2,7 @@ import EventHandler from '../../src/dom/event-handler.js'
import Tooltip from '../../src/tooltip.js'
import { noop } from '../../src/util/index.js'
import {
clearFixture, createEvent, getFixture, jQueryMock
clearFixture, createEvent, getFixture
} from '../helpers/fixture.js'
describe('Tooltip', () => {
@@ -582,27 +582,6 @@ describe('Tooltip', () => {
})
})
it('should show a tooltip with a jquery element container', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl, {
container: {
0: fixtureEl,
jquery: 'jQuery'
}
})
tooltipEl.addEventListener('shown.bs.tooltip', () => {
expect(fixtureEl.querySelector('.tooltip')).not.toBeNull()
resolve()
})
tooltip.show()
})
})
it('should show a tooltip with a selector in container', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
@@ -1243,25 +1222,6 @@ describe('Tooltip', () => {
expect().nothing()
})
it('should add the content as a child of the element for jQuery elements', () => {
fixtureEl.innerHTML = [
'<a href="#" rel="tooltip" title="Another tooltip">',
' <div id="childContent"></div>',
'</a>'
].join('')
const tooltipEl = fixtureEl.querySelector('a')
const childContent = fixtureEl.querySelector('div')
const tooltip = new Tooltip(tooltipEl, {
html: true
})
tooltip.setContent({ '.tooltip': { 0: childContent, jquery: 'jQuery' } })
tooltip.show()
expect(childContent.parentNode).toEqual(tooltip._getTipElement())
})
it('should add the child text content in the element', () => {
fixtureEl.innerHTML = [
'<a href="#" rel="tooltip" title="Another tooltip">',
@@ -1522,64 +1482,4 @@ describe('Tooltip', () => {
expect(tooltip2._getTitle()).toEqual('nothing')
})
})
describe('jQueryInterface', () => {
it('should create a tooltip', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock)
expect(Tooltip.getInstance(div)).not.toBeNull()
})
it('should not re create a tooltip', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const tooltip = new Tooltip(div)
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock)
expect(Tooltip.getInstance(div)).toEqual(tooltip)
})
it('should call a tooltip method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const tooltip = new Tooltip(div)
const spy = spyOn(tooltip, 'show')
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
jQueryMock.fn.tooltip.call(jQueryMock, 'show')
expect(Tooltip.getInstance(div)).toEqual(tooltip)
expect(spy).toHaveBeenCalled()
})
it('should throw error on undefined method', () => {
fixtureEl.innerHTML = '<div></div>'
const div = fixtureEl.querySelector('div')
const action = 'undefinedMethod'
jQueryMock.fn.tooltip = Tooltip.jQueryInterface
jQueryMock.elements = [div]
expect(() => {
jQueryMock.fn.tooltip.call(jQueryMock, action)
}).toThrowError(TypeError, `No method named "${action}"`)
})
})
})
-78
View File
@@ -72,18 +72,6 @@ describe('Util', () => {
expect(Util.isElement({})).toBeFalse()
expect(Util.isElement(fixtureEl.querySelectorAll('.test'))).toBeFalse()
})
it('should detect jQuery element', () => {
fixtureEl.innerHTML = '<div></div>'
const el = fixtureEl.querySelector('div')
const fakejQuery = {
0: el,
jquery: 'foo'
}
expect(Util.isElement(fakejQuery)).toBeTrue()
})
})
describe('getElement', () => {
@@ -103,13 +91,6 @@ describe('Util', () => {
expect(Util.getElement()).toBeNull()
expect(Util.getElement(null)).toBeNull()
expect(Util.getElement(fixtureEl.querySelectorAll('.test'))).toBeNull()
const fakejQueryObject = {
0: el,
jquery: 'foo'
}
expect(Util.getElement(fakejQueryObject)).toEqual(el)
})
})
@@ -425,39 +406,6 @@ describe('Util', () => {
})
})
describe('getjQuery', () => {
const fakejQuery = { trigger() {} }
beforeEach(() => {
Object.defineProperty(window, 'jQuery', {
value: fakejQuery,
writable: true
})
})
afterEach(() => {
window.jQuery = undefined
})
it('should return jQuery object when present', () => {
expect(Util.getjQuery()).toEqual(fakejQuery)
})
it('should not return jQuery object when present if data-bs-no-jquery', () => {
document.body.setAttribute('data-bs-no-jquery', '')
expect(window.jQuery).toEqual(fakejQuery)
expect(Util.getjQuery()).toBeNull()
document.body.removeAttribute('data-bs-no-jquery')
})
it('should not return jQuery if not present', () => {
window.jQuery = undefined
expect(Util.getjQuery()).toBeNull()
})
})
describe('onDOMContentLoaded', () => {
it('should execute callbacks when DOMContentLoaded is fired and should not add more than one listener', () => {
const spy = jasmine.createSpy()
@@ -486,32 +434,6 @@ describe('Util', () => {
})
})
describe('defineJQueryPlugin', () => {
const fakejQuery = { fn: {} }
beforeEach(() => {
Object.defineProperty(window, 'jQuery', {
value: fakejQuery,
writable: true
})
})
afterEach(() => {
window.jQuery = undefined
})
it('should define a plugin on the jQuery instance', () => {
const pluginMock = Util.noop
pluginMock.NAME = 'test'
pluginMock.jQueryInterface = Util.noop
Util.defineJQueryPlugin(pluginMock)
expect(fakejQuery.fn.test).toEqual(pluginMock.jQueryInterface)
expect(fakejQuery.fn.test.Constructor).toEqual(pluginMock)
expect(fakejQuery.fn.test.noConflict).toEqual(jasmine.any(Function))
})
})
describe('execute', () => {
it('should execute if arg is function', () => {
const spy = jasmine.createSpy('spy')
+1083 -138
View File
File diff suppressed because it is too large Load Diff
+13 -17
View File
@@ -41,19 +41,17 @@
"scripts": {
"start": "npm-run-all --parallel watch docs-serve",
"bundlewatch": "bundlewatch --config .bundlewatch.config.json",
"css": "npm-run-all css-compile css-prefix css-rtl css-minify",
"css-compile": "sass --style expanded --source-map --embed-sources --no-error-css scss/:dist/css/",
"css-rtl": "cross-env NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"dist/css\" --ext \".rtl.css\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.rtl.css\"",
"css": "npm-run-all css-compile css-prefix css-minify css-docs",
"css-compile": "sass --style expanded --source-map --embed-sources --no-error-css scss/bootstrap.scss:dist/css/bootstrap.css scss/bootstrap-grid.scss:dist/css/bootstrap-grid.css scss/bootstrap-reboot.scss:dist/css/bootstrap-reboot.css scss/bootstrap-utilities.scss:dist/css/bootstrap-utilities.css",
"css-docs": "node build/generate-utilities-json.mjs",
"css-lint": "npm-run-all --aggregate-output --continue-on-error --parallel css-lint-*",
"css-lint-stylelint": "stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache",
"css-lint-vars": "fusv scss/ site/src/scss/",
"css-minify": "npm-run-all --aggregate-output --parallel css-minify-*",
"css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*rtl*.css\"",
"css-minify-rtl": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*rtl.css\" \"!dist/css/*.min.css\"",
"css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.tmp.css\"",
"css-prefix": "npm-run-all --aggregate-output --parallel css-prefix-*",
"css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.rtl*.css\" \"!dist/css/*.min.css\"",
"css-prefix-main": "postcss --config build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.tmp.css\"",
"css-prefix-examples": "postcss --config build/postcss.config.mjs --replace \"site/src/assets/examples/**/*.css\"",
"css-prefix-examples-rtl": "cross-env-shell NODE_ENV=RTL postcss --config build/postcss.config.mjs --dir \"site/src/assets/examples/\" --ext \".rtl.css\" --base \"site/src/assets/examples/\" \"site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.css\" \"!site/src/assets/examples/{blog,carousel,dashboard,cheatsheet}/*.rtl.css\"",
"css-test": "jasmine --config=scss/tests/jasmine.js",
"js": "npm-run-all js-compile js-minify",
"js-compile": "npm-run-all --aggregate-output --parallel js-compile-*",
@@ -66,19 +64,19 @@
"js-minify-standalone": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\" --output dist/js/bootstrap.min.js dist/js/bootstrap.js",
"js-minify-standalone-esm": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.esm.js.map,includeSources,url=bootstrap.esm.min.js.map\" --output dist/js/bootstrap.esm.min.js dist/js/bootstrap.esm.js",
"js-minify-bundle": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js",
"js-test": "npm-run-all --aggregate-output --parallel js-test-karma js-test-jquery js-test-integration-*",
"js-test": "npm-run-all --aggregate-output --parallel js-test-karma js-test-integration-*",
"js-debug": "cross-env DEBUG=true npm run js-test-karma",
"js-test-karma": "karma start js/tests/karma.conf.js",
"js-test-integration-bundle": "rollup --config js/tests/integration/rollup.bundle.js",
"js-test-integration-modularity": "rollup --config js/tests/integration/rollup.bundle-modularity.js",
"js-test-cloud": "cross-env BROWSERSTACK=true npm run js-test-karma",
"js-test-jquery": "cross-env JQUERY=true npm run js-test-karma",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel js-lint css-lint lockfile-lint",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel js-lint css-lint lockfile-lint lint-mdx",
"lint-mdx": "markdownlint \"site/src/content/**/*.mdx\"",
"docs": "npm-run-all docs-build docs-lint",
"docs-build": "npm run astro-build",
"docs-compile": "npm run docs-build",
"docs-vnu": "node build/vnu-jar.mjs",
"docs-lint": "npm-run-all docs-prettier-check docs-vnu",
"docs-html-validate": "node build/html-validate.mjs",
"docs-lint": "npm-run-all docs-prettier-check docs-html-validate",
"docs-prettier-check": "prettier --config site/.prettierrc.json -c --cache site",
"docs-prettier-format": "prettier --config site/.prettierrc.json --write --cache site",
"docs-serve": "npm run astro-dev",
@@ -95,7 +93,6 @@
"netlify": "npm-run-all dist release-sri astro-build",
"watch": "npm-run-all --parallel watch-*",
"watch-css-main": "nodemon --watch scss/ --ext scss --exec \"npm-run-all css-lint css-compile css-prefix\"",
"watch-css-dist": "nodemon --watch dist/css/ --ext css --ignore \"dist/css/*.rtl.*\" --exec \"npm run css-rtl\"",
"watch-css-docs": "nodemon --watch site/src/scss/ --ext scss --exec \"npm run css-lint\"",
"watch-css-test": "nodemon --watch scss/ --ext scss,js --exec \"npm run css-test\"",
"watch-js-main": "nodemon --watch js/src/ --ext js --exec \"npm-run-all js-lint js-compile\"",
@@ -143,11 +140,11 @@
"github-slugger": "^2.0.0",
"globby": "^15.0.0",
"hammer-simulator": "0.0.1",
"html-validate": "^8.24.1",
"htmlparser2": "^10.0.0",
"image-size": "^2.0.2",
"ip": "^2.0.1",
"jasmine": "^5.12.0",
"jquery": "^3.7.1",
"js-yaml": "^4.1.1",
"karma": "^6.4.4",
"karma-browserstack-launcher": "1.4.0",
@@ -159,6 +156,7 @@
"karma-jasmine-html-reporter": "^2.1.0",
"karma-rollup-preprocessor": "7.0.7",
"lockfile-lint": "^4.14.1",
"markdownlint-cli": "^0.45.0",
"mime": "^4.1.0",
"nodemon": "^3.1.11",
"npm-run-all2": "^8.0.4",
@@ -171,15 +169,13 @@
"remark-html": "^16.0.1",
"rollup": "^4.53.2",
"rollup-plugin-istanbul": "^5.0.0",
"rtlcss": "^4.3.0",
"sass": "1.78.0",
"sass": "^1.90.0",
"sass-true": "^9.0.0",
"shelljs": "^0.10.0",
"stylelint": "^16.25.0",
"stylelint-config-twbs-bootstrap": "^16.1.0",
"terser": "^5.44.1",
"unist-util-visit": "^5.0.0",
"vnu-jar": "25.11.8",
"zod": "^4.1.12"
},
"files": [
+163 -130
View File
@@ -1,153 +1,186 @@
//
// Base styles
//
@use "config" as *;
@use "variables" as *;
@use "functions" as *;
@use "vendor/rfs" as *;
@use "mixins/border-radius" as *;
@use "mixins/transition" as *;
@use "mixins/box-shadow" as *;
@use "mixins/color-mode" as *;
.accordion {
// scss-docs-start accordion-css-vars
--#{$prefix}accordion-color: #{$accordion-color};
--#{$prefix}accordion-bg: #{$accordion-bg};
--#{$prefix}accordion-transition: #{$accordion-transition};
--#{$prefix}accordion-border-color: #{$accordion-border-color};
--#{$prefix}accordion-border-width: #{$accordion-border-width};
--#{$prefix}accordion-border-radius: #{$accordion-border-radius};
--#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius};
--#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x};
--#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y};
--#{$prefix}accordion-btn-color: #{$accordion-button-color};
--#{$prefix}accordion-btn-bg: #{$accordion-button-bg};
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)};
--#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width};
--#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform};
--#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition};
--#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon)};
--#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow};
--#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x};
--#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y};
--#{$prefix}accordion-active-color: #{$accordion-button-active-color};
--#{$prefix}accordion-active-bg: #{$accordion-button-active-bg};
// scss-docs-end accordion-css-vars
}
// scss-docs-start accordion-variables
$accordion-padding-y: 1rem !default;
$accordion-padding-x: 1.25rem !default;
$accordion-color: var(--#{$prefix}color-body) !default;
$accordion-bg: var(--#{$prefix}bg-body) !default;
$accordion-border-width: var(--#{$prefix}border-width) !default;
$accordion-border-color: var(--#{$prefix}border-color) !default;
$accordion-border-radius: var(--#{$prefix}border-radius-lg) !default;
$accordion-inner-border-radius: calc(#{$accordion-border-radius} - #{$accordion-border-width}) !default;
.accordion-button {
position: relative;
display: flex;
align-items: center;
width: 100%;
padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x);
@include font-size($font-size-base);
color: var(--#{$prefix}accordion-btn-color);
text-align: left; // Reset button style
background-color: var(--#{$prefix}accordion-btn-bg);
border: 0;
@include border-radius(0);
overflow-anchor: none;
@include transition(var(--#{$prefix}accordion-transition));
$accordion-body-padding-y: $accordion-padding-y !default;
$accordion-body-padding-x: $accordion-padding-x !default;
&:not(.collapsed) {
color: var(--#{$prefix}accordion-active-color);
background-color: var(--#{$prefix}accordion-active-bg);
box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color); // stylelint-disable-line function-disallowed-list
$accordion-button-padding-y: $accordion-padding-y !default;
$accordion-button-padding-x: $accordion-padding-x !default;
$accordion-button-color: var(--#{$prefix}fg-2) !default;
$accordion-button-bg: var(--#{$prefix}accordion-bg) !default;
$accordion-transition: $btn-transition, border-radius .15s ease !default;
$accordion-button-active-bg: var(--#{$prefix}bg-2) !default;
$accordion-button-active-color: var(--#{$prefix}fg) !default;
&::after {
background-image: var(--#{$prefix}accordion-btn-active-icon);
transform: var(--#{$prefix}accordion-btn-icon-transform);
}
$accordion-button-focus-box-shadow: $btn-focus-box-shadow !default;
$accordion-icon-width: 1.25rem !default;
$accordion-icon-transition: transform .2s ease-in-out !default;
$accordion-icon-transform: rotate(-180deg) !default;
$accordion-button-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='#000' stroke-linecap='round' stroke-linejoin='round'><path d='m2 5 6 6 6-6'/></svg>") !default;
// scss-docs-end accordion-variables
@layer componenents {
.accordion {
// scss-docs-start accordion-css-vars
--#{$prefix}accordion-color: #{$accordion-color};
--#{$prefix}accordion-bg: #{$accordion-bg};
--#{$prefix}accordion-transition: #{$accordion-transition};
--#{$prefix}accordion-border-color: #{$accordion-border-color};
--#{$prefix}accordion-border-width: #{$accordion-border-width};
--#{$prefix}accordion-border-radius: #{$accordion-border-radius};
--#{$prefix}accordion-inner-border-radius: #{$accordion-inner-border-radius};
--#{$prefix}accordion-btn-padding-x: #{$accordion-button-padding-x};
--#{$prefix}accordion-btn-padding-y: #{$accordion-button-padding-y};
--#{$prefix}accordion-btn-color: #{$accordion-button-color};
--#{$prefix}accordion-btn-bg: #{$accordion-button-bg};
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon)};
--#{$prefix}accordion-btn-icon-width: #{$accordion-icon-width};
--#{$prefix}accordion-btn-icon-transform: #{$accordion-icon-transform};
--#{$prefix}accordion-btn-icon-transition: #{$accordion-icon-transition};
--#{$prefix}accordion-btn-focus-box-shadow: #{$accordion-button-focus-box-shadow};
--#{$prefix}accordion-body-padding-x: #{$accordion-body-padding-x};
--#{$prefix}accordion-body-padding-y: #{$accordion-body-padding-y};
--#{$prefix}accordion-active-color: #{$accordion-button-active-color};
--#{$prefix}accordion-active-bg: #{$accordion-button-active-bg};
// scss-docs-end accordion-css-vars
}
// Accordion icon
&::after {
flex-shrink: 0;
width: var(--#{$prefix}accordion-btn-icon-width);
height: var(--#{$prefix}accordion-btn-icon-width);
margin-left: auto;
content: "";
background-image: var(--#{$prefix}accordion-btn-icon);
background-repeat: no-repeat;
background-size: var(--#{$prefix}accordion-btn-icon-width);
@include transition(var(--#{$prefix}accordion-btn-icon-transition));
}
.accordion-button {
position: relative;
display: flex;
align-items: center;
width: 100%;
padding: var(--#{$prefix}accordion-btn-padding-y) var(--#{$prefix}accordion-btn-padding-x);
@include font-size($font-size-base);
color: var(--#{$prefix}accordion-btn-color);
text-align: start; // Reset button style
background-color: var(--#{$prefix}accordion-btn-bg);
border: 0;
@include border-radius(0);
overflow-anchor: none;
@include transition(var(--#{$prefix}accordion-transition));
&:hover {
z-index: 2;
}
&:not(.collapsed) {
color: var(--#{$prefix}accordion-active-color);
background-color: var(--#{$prefix}accordion-active-bg);
box-shadow: inset 0 calc(-1 * var(--#{$prefix}accordion-border-width)) 0 var(--#{$prefix}accordion-border-color);
&:focus {
z-index: 3;
outline: 0;
box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow);
}
}
.accordion-header {
margin-bottom: 0;
}
.accordion-item {
color: var(--#{$prefix}accordion-color);
background-color: var(--#{$prefix}accordion-bg);
border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color);
&:first-of-type {
@include border-top-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
@include border-top-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
&:not(:first-of-type) {
border-top: 0;
}
// Only set a border-radius on the last item if the accordion is collapsed
&:last-of-type {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
&.collapsed {
@include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius));
&::after {
background-image: var(--#{$prefix}accordion-btn-active-icon);
transform: var(--#{$prefix}accordion-btn-icon-transform);
}
}
> .accordion-collapse {
// Accordion icon
&::after {
flex-shrink: 0;
width: var(--#{$prefix}accordion-btn-icon-width);
height: var(--#{$prefix}accordion-btn-icon-width);
margin-inline-start: auto;
content: "";
background-color: var(--#{$prefix}accordion-btn-color);
mask: var(--#{$prefix}accordion-btn-icon) no-repeat center 100%;
@include transition(var(--#{$prefix}accordion-btn-icon-transition));
}
&:hover {
z-index: 2;
}
&:focus {
z-index: 3;
outline: 0;
box-shadow: var(--#{$prefix}accordion-btn-focus-box-shadow);
}
}
.accordion-header {
margin-bottom: 0;
}
.accordion-item {
color: var(--#{$prefix}accordion-color);
background-color: var(--#{$prefix}accordion-bg);
border: var(--#{$prefix}accordion-border-width) solid var(--#{$prefix}accordion-border-color);
&:first-of-type {
@include border-top-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
@include border-top-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
&:not(:first-of-type) {
border-block-start: 0;
}
// Only set a border-radius on the last item if the accordion is collapsed
&:last-of-type {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
> .accordion-header .accordion-button {
&.collapsed {
@include border-bottom-radius(var(--#{$prefix}accordion-inner-border-radius));
}
}
> .accordion-collapse {
@include border-bottom-radius(var(--#{$prefix}accordion-border-radius));
}
}
}
}
.accordion-body {
padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x);
}
.accordion-body {
padding: var(--#{$prefix}accordion-body-padding-y) var(--#{$prefix}accordion-body-padding-x);
}
// Flush accordion items
//
// Remove borders and border-radius to keep accordion items edge-to-edge.
// Flush accordion items
//
// Remove borders and border-radius to keep accordion items edge-to-edge.
.accordion-flush {
> .accordion-item {
border-right: 0;
border-left: 0;
@include border-radius(0);
&:first-child { border-top: 0; }
&:last-child { border-bottom: 0; }
// stylelint-disable selector-max-class
> .accordion-collapse,
> .accordion-header .accordion-button,
> .accordion-header .accordion-button.collapsed {
.accordion-flush {
> .accordion-item {
border-inline: 0;
@include border-radius(0);
}
// stylelint-enable selector-max-class
}
}
@if $enable-dark-mode {
@include color-mode(dark) {
.accordion-button::after {
--#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)};
--#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)};
&:first-child { border-block-start: 0; }
&:last-child { border-block-end: 0; }
// stylelint-disable selector-max-class
> .accordion-collapse,
> .accordion-header .accordion-button,
> .accordion-header .accordion-button.collapsed {
@include border-radius(0);
}
// stylelint-enable selector-max-class
}
}
// @if $enable-dark-mode {
// @include color-mode(dark) {
// .accordion-button::after {
// --#{$prefix}accordion-btn-icon: #{escape-svg($accordion-button-icon-dark)};
// --#{$prefix}accordion-btn-active-icon: #{escape-svg($accordion-button-active-icon-dark)};
// }
// }
// }
}
+59 -58
View File
@@ -1,68 +1,69 @@
//
// Base styles
//
@use "sass:map";
@use "config" as *;
@use "theme" as *;
@use "variables" as *;
@use "mixins/border-radius" as *;
.alert {
// scss-docs-start alert-css-vars
--#{$prefix}alert-bg: transparent;
--#{$prefix}alert-padding-x: #{$alert-padding-x};
--#{$prefix}alert-padding-y: #{$alert-padding-y};
--#{$prefix}alert-margin-bottom: #{$alert-margin-bottom};
--#{$prefix}alert-color: inherit;
--#{$prefix}alert-border-color: transparent;
--#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}alert-border-color);
--#{$prefix}alert-border-radius: #{$alert-border-radius};
--#{$prefix}alert-link-color: inherit;
// scss-docs-end alert-css-vars
// scss-docs-start alert-variables
$alert-padding-y: $spacer !default;
$alert-padding-x: $spacer !default;
$alert-margin-bottom: 1rem !default;
$alert-border-radius: var(--#{$prefix}border-radius) !default;
$alert-link-font-weight: $font-weight-bold !default;
$alert-border-width: var(--#{$prefix}border-width) !default;
$alert-dismissible-padding-r: $alert-padding-x * 3 !default; // 3x covers width of x plus default padding on either side
// scss-docs-end alert-variables
position: relative;
padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x);
margin-bottom: var(--#{$prefix}alert-margin-bottom);
color: var(--#{$prefix}alert-color);
background-color: var(--#{$prefix}alert-bg);
border: var(--#{$prefix}alert-border);
@include border-radius(var(--#{$prefix}alert-border-radius));
}
@layer components {
.alert {
// scss-docs-start alert-css-vars
--#{$prefix}alert-bg: var(--#{$prefix}theme-bg-subtle, transparent);
--#{$prefix}alert-padding-x: #{$alert-padding-x};
--#{$prefix}alert-padding-y: #{$alert-padding-y};
--#{$prefix}alert-margin-bottom: #{$alert-margin-bottom};
--#{$prefix}alert-color: var(--#{$prefix}theme-text, inherit);
--#{$prefix}alert-border-color: transparent;
--#{$prefix}alert-border: #{$alert-border-width} solid var(--#{$prefix}theme-border, var(--#{$prefix}alert-border-color));
--#{$prefix}alert-border-radius: #{$alert-border-radius};
--#{$prefix}alert-link-color: inherit;
// scss-docs-end alert-css-vars
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
position: relative;
padding: var(--#{$prefix}alert-padding-y) var(--#{$prefix}alert-padding-x);
// margin-bottom: var(--#{$prefix}alert-margin-bottom);
color: var(--#{$prefix}alert-color);
background-color: var(--#{$prefix}alert-bg);
border: var(--#{$prefix}alert-border);
@include border-radius(var(--#{$prefix}alert-border-radius));
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
color: var(--#{$prefix}alert-link-color);
}
// Headings for larger alerts
.alert-heading {
// Specified to prevent conflicts of changing $headings-color
color: inherit;
}
// Provide class for links that match alerts
.alert-link {
font-weight: $alert-link-font-weight;
color: var(--#{$prefix}alert-link-color);
}
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible {
padding-right: $alert-dismissible-padding-r;
.alert-dismissible {
padding-inline-end: $alert-dismissible-padding-r;
// Adjust close link position
.btn-close {
position: absolute;
top: 0;
right: 0;
z-index: $stretched-link-z-index + 1;
padding: $alert-padding-y * 1.25 $alert-padding-x;
// Adjust close link position
.btn-close {
position: absolute;
top: 0;
right: 0;
z-index: $stretched-link-z-index + 1;
padding: $alert-padding-y * 1.25 $alert-padding-x;
}
}
}
// scss-docs-start alert-modifiers
// Generate contextual modifier classes for colorizing the alert
@each $state in map-keys($theme-colors) {
.alert-#{$state} {
--#{$prefix}alert-color: var(--#{$prefix}#{$state}-text-emphasis);
--#{$prefix}alert-bg: var(--#{$prefix}#{$state}-bg-subtle);
--#{$prefix}alert-border-color: var(--#{$prefix}#{$state}-border-subtle);
--#{$prefix}alert-link-color: var(--#{$prefix}#{$state}-text-emphasis);
}
}
// scss-docs-end alert-modifiers
+54 -33
View File
@@ -1,38 +1,59 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
@use "config" as *;
@use "colors" as *;
@use "variables" as *;
@use "theme" as *;
@use "mixins/border-radius" as *;
@use "mixins/gradients" as *;
@use "vendor/rfs" as *;
.badge {
// scss-docs-start badge-css-vars
--#{$prefix}badge-padding-x: #{$badge-padding-x};
--#{$prefix}badge-padding-y: #{$badge-padding-y};
@include rfs($badge-font-size, --#{$prefix}badge-font-size);
--#{$prefix}badge-font-weight: #{$badge-font-weight};
--#{$prefix}badge-color: #{$badge-color};
--#{$prefix}badge-border-radius: #{$badge-border-radius};
// scss-docs-end badge-css-vars
// scss-docs-start badge-variables
$badge-font-size: .75em !default;
$badge-font-weight: $font-weight-bold !default;
$badge-color: inherit !default;
$badge-padding-y: .35em !default;
$badge-padding-x: .5em !default;
$badge-border-radius: var(--#{$prefix}border-radius) !default;
// scss-docs-end badge-variables
display: inline-block;
padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x);
@include font-size(var(--#{$prefix}badge-font-size));
font-weight: var(--#{$prefix}badge-font-weight);
line-height: 1;
color: var(--#{$prefix}badge-color);
text-align: center;
white-space: nowrap;
vertical-align: baseline;
@include border-radius(var(--#{$prefix}badge-border-radius));
@include gradient-bg();
@layer components {
.badge {
// scss-docs-start badge-css-vars
--#{$prefix}badge-padding-x: #{$badge-padding-x};
--#{$prefix}badge-padding-y: #{$badge-padding-y};
@include rfs($badge-font-size, --#{$prefix}badge-font-size);
--#{$prefix}badge-font-weight: #{$badge-font-weight};
--#{$prefix}badge-color: var(--#{$prefix}theme-contrast, #{$badge-color});
--#{$prefix}badge-bg: var(--#{$prefix}theme-bg, var(--#{$prefix}bg-2));
--#{$prefix}badge-border-radius: #{$badge-border-radius};
// scss-docs-end badge-css-vars
// Empty badges collapse automatically
&:empty {
display: none;
display: inline-block;
padding: var(--#{$prefix}badge-padding-y) var(--#{$prefix}badge-padding-x);
@include font-size(var(--#{$prefix}badge-font-size));
font-weight: var(--#{$prefix}badge-font-weight);
line-height: 1;
color: var(--#{$prefix}badge-color);
text-align: center;
white-space: nowrap;
vertical-align: baseline;
background-color: var(--#{$prefix}badge-bg);
@include border-radius(var(--#{$prefix}badge-border-radius));
@include gradient-bg();
// Empty badges collapse automatically
&:empty {
display: none;
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
.badge-subtle {
--#{$prefix}badge-color: var(--#{$prefix}theme-text);
--#{$prefix}badge-bg: var(--#{$prefix}theme-bg-subtle);
}
}
// Quick fix for badges in buttons
.btn .badge {
position: relative;
top: -1px;
}
+7
View File
@@ -0,0 +1,7 @@
$file: "" !default;
/*!
* Bootstrap #{$file} v6.0.0-dev (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
+61 -34
View File
@@ -1,40 +1,67 @@
.breadcrumb {
// scss-docs-start breadcrumb-css-vars
--#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x};
--#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y};
--#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom};
@include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size);
--#{$prefix}breadcrumb-bg: #{$breadcrumb-bg};
--#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius};
--#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color};
--#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x};
--#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color};
// scss-docs-end breadcrumb-css-vars
@use "sass:string";
@use "config" as *;
@use "variables" as *;
@use "functions" as *;
@use "mixins/border-radius" as *;
@use "vendor/rfs" as *;
display: flex;
flex-wrap: wrap;
padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x);
margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom);
@include font-size(var(--#{$prefix}breadcrumb-font-size));
list-style: none;
background-color: var(--#{$prefix}breadcrumb-bg);
@include border-radius(var(--#{$prefix}breadcrumb-border-radius));
}
// scss-docs-start breadcrumb-variables
$breadcrumb-font-size: null !default;
$breadcrumb-padding-y: 0 !default;
$breadcrumb-padding-x: 0 !default;
$breadcrumb-item-padding-x: .5rem !default;
$breadcrumb-margin-bottom: 1rem !default;
$breadcrumb-bg: null !default;
$breadcrumb-divider-color: var(--#{$prefix}secondary-color) !default;
$breadcrumb-active-color: var(--#{$prefix}secondary-color) !default;
$breadcrumb-divider: string.quote("/") !default;
$breadcrumb-divider-flipped: $breadcrumb-divider !default;
$breadcrumb-border-radius: null !default;
// scss-docs-end breadcrumb-variables
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-left: var(--#{$prefix}breadcrumb-item-padding-x);
@layer components {
.breadcrumb {
// scss-docs-start breadcrumb-css-vars
--#{$prefix}breadcrumb-padding-x: #{$breadcrumb-padding-x};
--#{$prefix}breadcrumb-padding-y: #{$breadcrumb-padding-y};
--#{$prefix}breadcrumb-margin-bottom: #{$breadcrumb-margin-bottom};
@include rfs($breadcrumb-font-size, --#{$prefix}breadcrumb-font-size);
--#{$prefix}breadcrumb-bg: #{$breadcrumb-bg};
--#{$prefix}breadcrumb-border-radius: #{$breadcrumb-border-radius};
--#{$prefix}breadcrumb-divider-color: #{$breadcrumb-divider-color};
--#{$prefix}breadcrumb-item-padding-x: #{$breadcrumb-item-padding-x};
--#{$prefix}breadcrumb-item-active-color: #{$breadcrumb-active-color};
// scss-docs-end breadcrumb-css-vars
&::before {
float: left; // Suppress inline spacings and underlining of the separator
padding-right: var(--#{$prefix}breadcrumb-item-padding-x);
color: var(--#{$prefix}breadcrumb-divider-color);
content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider)) #{"/* rtl:"} var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped)) #{"*/"};
display: flex;
flex-wrap: wrap;
padding: var(--#{$prefix}breadcrumb-padding-y) var(--#{$prefix}breadcrumb-padding-x);
margin-bottom: var(--#{$prefix}breadcrumb-margin-bottom);
@include font-size(var(--#{$prefix}breadcrumb-font-size));
list-style: none;
background-color: var(--#{$prefix}breadcrumb-bg);
@include border-radius(var(--#{$prefix}breadcrumb-border-radius));
}
.breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item {
padding-inline-start: var(--#{$prefix}breadcrumb-item-padding-x);
&::before {
float: inline-start; // Suppress inline spacings and underlining of the separator
padding-inline-end: var(--#{$prefix}breadcrumb-item-padding-x);
color: var(--#{$prefix}breadcrumb-divider-color);
content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider));
}
}
[dir="rtl"] &:not(:first-child)::before {
content: var(--#{$prefix}breadcrumb-divider, escape-svg($breadcrumb-divider-flipped));
}
&.active {
color: var(--#{$prefix}breadcrumb-item-active-color);
}
}
&.active {
color: var(--#{$prefix}breadcrumb-item-active-color);
}
}
-147
View File
@@ -1,147 +0,0 @@
// Make the div behave like a button
.btn-group,
.btn-group-vertical {
position: relative;
display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above
> .btn {
position: relative;
flex: 1 1 auto;
}
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
> .btn-check:checked + .btn,
> .btn-check:focus + .btn,
> .btn:hover,
> .btn:focus,
> .btn:active,
> .btn.active {
z-index: 1;
}
}
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.input-group {
width: auto;
}
}
.btn-group {
@include border-radius($btn-border-radius);
// Prevent double borders when buttons are next to each other
> :not(.btn-check:first-child) + .btn,
> .btn-group:not(:first-child) {
margin-left: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn.dropdown-toggle-split:first-child,
> .btn-group:not(:last-child) > .btn {
@include border-end-radius(0);
}
// The left radius should be 0 if the button is:
// - the "third or more" child
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
// - part of a btn-group which isn't the first child
> .btn:nth-child(n + 3),
> :not(.btn-check) + .btn,
> .btn-group:not(:first-child) > .btn {
@include border-start-radius(0);
}
}
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; }
//
// Split button dropdowns
//
.dropdown-toggle-split {
padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75;
&::after,
.dropup &::after,
.dropend &::after {
margin-left: 0;
}
.dropstart &::before {
margin-right: 0;
}
}
.btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75;
}
.btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75;
}
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link {
@include box-shadow(none);
}
}
//
// Vertical button groups
//
.btn-group-vertical {
flex-direction: column;
align-items: flex-start;
justify-content: center;
> .btn,
> .btn-group {
width: 100%;
}
> .btn:not(:first-child),
> .btn-group:not(:first-child) {
margin-top: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
}
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0);
}
// The top radius should be 0 if the button is:
// - the "third or more" child
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
// - part of a btn-group which isn't the first child
> .btn:nth-child(n + 3),
> :not(.btn-check) + .btn,
> .btn-group:not(:first-child) > .btn {
@include border-top-radius(0);
}
}
-216
View File
@@ -1,216 +0,0 @@
//
// Base styles
//
.btn {
// scss-docs-start btn-css-vars
--#{$prefix}btn-padding-x: #{$btn-padding-x};
--#{$prefix}btn-padding-y: #{$btn-padding-y};
--#{$prefix}btn-font-family: #{$btn-font-family};
@include rfs($btn-font-size, --#{$prefix}btn-font-size);
--#{$prefix}btn-font-weight: #{$btn-font-weight};
--#{$prefix}btn-line-height: #{$btn-line-height};
--#{$prefix}btn-color: #{$btn-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-width: #{$btn-border-width};
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-border-radius: #{$btn-border-radius};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-box-shadow: #{$btn-box-shadow};
--#{$prefix}btn-disabled-opacity: #{$btn-disabled-opacity};
--#{$prefix}btn-focus-box-shadow: 0 0 0 #{$btn-focus-width} rgba(var(--#{$prefix}btn-focus-shadow-rgb), .5);
// scss-docs-end btn-css-vars
display: inline-block;
padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x);
font-family: var(--#{$prefix}btn-font-family);
@include font-size(var(--#{$prefix}btn-font-size));
font-weight: var(--#{$prefix}btn-font-weight);
line-height: var(--#{$prefix}btn-line-height);
color: var(--#{$prefix}btn-color);
text-align: center;
text-decoration: if($link-decoration == none, null, none);
white-space: $btn-white-space;
vertical-align: middle;
cursor: if($enable-button-pointers, pointer, null);
user-select: none;
border: var(--#{$prefix}btn-border-width) solid var(--#{$prefix}btn-border-color);
@include border-radius(var(--#{$prefix}btn-border-radius));
@include gradient-bg(var(--#{$prefix}btn-bg));
@include box-shadow(var(--#{$prefix}btn-box-shadow));
@include transition($btn-transition);
&:hover {
color: var(--#{$prefix}btn-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
background-color: var(--#{$prefix}btn-hover-bg);
border-color: var(--#{$prefix}btn-hover-border-color);
}
.btn-check + &:hover {
// override for the checkbox/radio buttons
color: var(--#{$prefix}btn-color);
background-color: var(--#{$prefix}btn-bg);
border-color: var(--#{$prefix}btn-border-color);
}
&:focus-visible {
color: var(--#{$prefix}btn-hover-color);
@include gradient-bg(var(--#{$prefix}btn-hover-bg));
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:focus-visible + & {
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
.btn-check:checked + &,
:not(.btn-check) + &:active,
&:first-child:active,
&.active,
&.show {
color: var(--#{$prefix}btn-active-color);
background-color: var(--#{$prefix}btn-active-bg);
// Remove CSS gradients if they're enabled
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-active-border-color);
@include box-shadow(var(--#{$prefix}btn-active-shadow));
&:focus-visible {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
}
.btn-check:checked:focus-visible + & {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
&:disabled,
&.disabled,
fieldset:disabled & {
color: var(--#{$prefix}btn-disabled-color);
pointer-events: none;
background-color: var(--#{$prefix}btn-disabled-bg);
background-image: if($enable-gradients, none, null);
border-color: var(--#{$prefix}btn-disabled-border-color);
opacity: var(--#{$prefix}btn-disabled-opacity);
@include box-shadow(none);
}
}
//
// Alternate buttons
//
// scss-docs-start btn-variant-loops
@each $color, $value in $theme-colors {
.btn-#{$color} {
@if $color == "light" {
@include button-variant(
$value,
$value,
$hover-background: shade-color($value, $btn-hover-bg-shade-amount),
$hover-border: shade-color($value, $btn-hover-border-shade-amount),
$active-background: shade-color($value, $btn-active-bg-shade-amount),
$active-border: shade-color($value, $btn-active-border-shade-amount)
);
} @else if $color == "dark" {
@include button-variant(
$value,
$value,
$hover-background: tint-color($value, $btn-hover-bg-tint-amount),
$hover-border: tint-color($value, $btn-hover-border-tint-amount),
$active-background: tint-color($value, $btn-active-bg-tint-amount),
$active-border: tint-color($value, $btn-active-border-tint-amount)
);
} @else {
@include button-variant($value, $value);
}
}
}
@each $color, $value in $theme-colors {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
// scss-docs-end btn-variant-loops
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link {
--#{$prefix}btn-font-weight: #{$font-weight-normal};
--#{$prefix}btn-color: #{$btn-link-color};
--#{$prefix}btn-bg: transparent;
--#{$prefix}btn-border-color: transparent;
--#{$prefix}btn-hover-color: #{$btn-link-hover-color};
--#{$prefix}btn-hover-border-color: transparent;
--#{$prefix}btn-active-color: #{$btn-link-hover-color};
--#{$prefix}btn-active-border-color: transparent;
--#{$prefix}btn-disabled-color: #{$btn-link-disabled-color};
--#{$prefix}btn-disabled-border-color: transparent;
--#{$prefix}btn-box-shadow: 0 0 0 #000; // Can't use `none` as keyword negates all values when used with multiple shadows
--#{$prefix}btn-focus-shadow-rgb: #{$btn-link-focus-shadow-rgb};
text-decoration: $link-decoration;
@if $enable-gradients {
background-image: none;
}
&:hover,
&:focus-visible {
text-decoration: $link-hover-decoration;
}
&:focus-visible {
color: var(--#{$prefix}btn-color);
}
&:hover {
color: var(--#{$prefix}btn-hover-color);
}
// No need for an active state here
}
//
// Button Sizes
//
.btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $btn-font-size-lg, $btn-border-radius-lg);
}
.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm);
}
+220 -205
View File
@@ -1,235 +1,250 @@
//
// Base styles
//
@use "config" as *;
@use "variables" as *;
@use "mixins/border-radius" as *;
@use "mixins/box-shadow" as *;
@use "layout/breakpoints" as *;
.card {
// scss-docs-start card-css-vars
--#{$prefix}card-spacer-y: #{$card-spacer-y};
--#{$prefix}card-spacer-x: #{$card-spacer-x};
--#{$prefix}card-title-spacer-y: #{$card-title-spacer-y};
--#{$prefix}card-title-color: #{$card-title-color};
--#{$prefix}card-subtitle-color: #{$card-subtitle-color};
--#{$prefix}card-border-width: #{$card-border-width};
--#{$prefix}card-border-color: #{$card-border-color};
--#{$prefix}card-border-radius: #{$card-border-radius};
--#{$prefix}card-box-shadow: #{$card-box-shadow};
--#{$prefix}card-inner-border-radius: #{$card-inner-border-radius};
--#{$prefix}card-cap-padding-y: #{$card-cap-padding-y};
--#{$prefix}card-cap-padding-x: #{$card-cap-padding-x};
--#{$prefix}card-cap-bg: #{$card-cap-bg};
--#{$prefix}card-cap-color: #{$card-cap-color};
--#{$prefix}card-height: #{$card-height};
--#{$prefix}card-color: #{$card-color};
--#{$prefix}card-bg: #{$card-bg};
--#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding};
--#{$prefix}card-group-margin: #{$card-group-margin};
// scss-docs-end card-css-vars
// scss-docs-start card-variables
$card-spacer-y: $spacer !default;
$card-spacer-x: $spacer !default;
$card-title-spacer-y: $spacer * .5 !default;
$card-title-color: null !default;
$card-subtitle-color: null !default;
$card-border-width: var(--#{$prefix}border-width) !default;
$card-border-color: var(--#{$prefix}border-color-translucent) !default;
$card-border-radius: var(--#{$prefix}border-radius) !default;
$card-box-shadow: null !default;
$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;
$card-cap-padding-y: $card-spacer-y * .5 !default;
$card-cap-padding-x: $card-spacer-x !default;
$card-cap-bg: rgba(var(--#{$prefix}body-color-rgb), .03) !default;
$card-cap-color: null !default;
$card-height: null !default;
$card-color: null !default;
$card-bg: var(--#{$prefix}bg-body) !default;
$card-img-overlay-padding: $spacer !default;
$card-group-margin: $grid-gutter-width * .5 !default;
// scss-docs-end card-variables
position: relative;
display: flex;
flex-direction: column;
min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
height: var(--#{$prefix}card-height);
color: var(--#{$prefix}body-color);
word-wrap: break-word;
background-color: var(--#{$prefix}card-bg);
background-clip: border-box;
border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
@include border-radius(var(--#{$prefix}card-border-radius));
@include box-shadow(var(--#{$prefix}card-box-shadow));
@layer components {
.card {
// scss-docs-start card-css-vars
--#{$prefix}card-spacer-y: #{$card-spacer-y};
--#{$prefix}card-spacer-x: #{$card-spacer-x};
--#{$prefix}card-title-spacer-y: #{$card-title-spacer-y};
--#{$prefix}card-title-color: #{$card-title-color};
--#{$prefix}card-subtitle-color: #{$card-subtitle-color};
--#{$prefix}card-border-width: #{$card-border-width};
--#{$prefix}card-border-color: #{$card-border-color};
--#{$prefix}card-border-radius: #{$card-border-radius};
--#{$prefix}card-box-shadow: #{$card-box-shadow};
--#{$prefix}card-inner-border-radius: #{$card-inner-border-radius};
--#{$prefix}card-cap-padding-y: #{$card-cap-padding-y};
--#{$prefix}card-cap-padding-x: #{$card-cap-padding-x};
--#{$prefix}card-cap-bg: #{$card-cap-bg};
--#{$prefix}card-cap-color: #{$card-cap-color};
--#{$prefix}card-height: #{$card-height};
--#{$prefix}card-color: #{$card-color};
--#{$prefix}card-bg: #{$card-bg};
--#{$prefix}card-img-overlay-padding: #{$card-img-overlay-padding};
--#{$prefix}card-group-margin: #{$card-group-margin};
// scss-docs-end card-css-vars
> hr {
margin-right: 0;
margin-left: 0;
position: relative;
display: flex;
flex-direction: column;
min-width: 0; // See https://github.com/twbs/bootstrap/pull/22740#issuecomment-305868106
height: var(--#{$prefix}card-height);
color: var(--#{$prefix}color-body);
word-wrap: break-word;
background-color: var(--#{$prefix}card-bg);
background-clip: border-box;
border: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
@include border-radius(var(--#{$prefix}card-border-radius));
@include box-shadow(var(--#{$prefix}card-box-shadow));
> hr {
margin-inline: 0;
}
> .list-group {
border-block: inherit;
&:first-child {
border-block-start-width: 0;
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
&:last-child {
border-block-end-width: 0;
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
}
// Due to specificity of the above selector (`.card > .list-group`), we must
// use a child selector here to prevent double borders.
> .card-header + .list-group,
> .list-group + .card-footer {
border-block-start: 0;
}
}
> .list-group {
border-top: inherit;
border-bottom: inherit;
.card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x);
color: var(--#{$prefix}card-color);
}
.card-title {
margin-bottom: var(--#{$prefix}card-title-spacer-y);
color: var(--#{$prefix}card-title-color);
}
.card-subtitle {
margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y));
margin-bottom: 0;
color: var(--#{$prefix}card-subtitle-color);
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link {
&:hover {
text-decoration: none;
}
+ .card-link {
margin-inline-start: var(--#{$prefix}card-spacer-x);
}
}
//
// Optional textual caps
//
.card-header {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
margin-bottom: 0; // Removes the default margin-bottom of <hN>
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-block-end: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:first-child {
border-top-width: 0;
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
&:last-child {
border-bottom-width: 0;
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
@include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0);
}
}
// Due to specificity of the above selector (`.card > .list-group`), we must
// use a child selector here to prevent double borders.
> .card-header + .list-group,
> .list-group + .card-footer {
border-top: 0;
}
}
.card-footer {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-block-start: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
.card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto;
padding: var(--#{$prefix}card-spacer-y) var(--#{$prefix}card-spacer-x);
color: var(--#{$prefix}card-color);
}
.card-title {
margin-bottom: var(--#{$prefix}card-title-spacer-y);
color: var(--#{$prefix}card-title-color);
}
.card-subtitle {
margin-top: calc(-.5 * var(--#{$prefix}card-title-spacer-y)); // stylelint-disable-line function-disallowed-list
margin-bottom: 0;
color: var(--#{$prefix}card-subtitle-color);
}
.card-text:last-child {
margin-bottom: 0;
}
.card-link {
&:hover {
text-decoration: if($link-hover-decoration == underline, none, null);
&:last-child {
@include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius));
}
}
+ .card-link {
margin-left: var(--#{$prefix}card-spacer-x);
}
}
//
// Optional textual caps
//
//
// Header navs
//
.card-header {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
margin-bottom: 0; // Removes the default margin-bottom of <hN>
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-bottom: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
.card-header-tabs {
margin-inline: calc(-.5 * var(--#{$prefix}card-cap-padding-x));
margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y));
border-block-end: 0;
&:first-child {
@include border-radius(var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius) 0 0);
}
}
.card-footer {
padding: var(--#{$prefix}card-cap-padding-y) var(--#{$prefix}card-cap-padding-x);
color: var(--#{$prefix}card-cap-color);
background-color: var(--#{$prefix}card-cap-bg);
border-top: var(--#{$prefix}card-border-width) solid var(--#{$prefix}card-border-color);
&:last-child {
@include border-radius(0 0 var(--#{$prefix}card-inner-border-radius) var(--#{$prefix}card-inner-border-radius));
}
}
//
// Header navs
//
.card-header-tabs {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-bottom: calc(-1 * var(--#{$prefix}card-cap-padding-y)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
border-bottom: 0;
.nav-link.active {
background-color: var(--#{$prefix}card-bg);
border-bottom-color: var(--#{$prefix}card-bg);
}
}
.card-header-pills {
margin-right: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
margin-left: calc(-.5 * var(--#{$prefix}card-cap-padding-x)); // stylelint-disable-line function-disallowed-list
}
// Card image
.card-img-overlay {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: var(--#{$prefix}card-img-overlay-padding);
@include border-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-top,
.card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
}
.card-img,
.card-img-top {
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-bottom {
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
//
// Card groups
//
.card-group {
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
margin-bottom: var(--#{$prefix}card-group-margin);
.nav-link.active {
background-color: var(--#{$prefix}card-bg);
border-block-end-color: var(--#{$prefix}card-bg);
}
}
@include media-breakpoint-up(sm) {
display: flex;
flex-flow: row wrap;
.card-header-pills {
margin-inline: calc(-.5 * var(--#{$prefix}card-cap-padding-x));
}
// Card image
.card-img-overlay {
position: absolute;
inset: 0;
padding: var(--#{$prefix}card-img-overlay-padding);
@include border-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-top,
.card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
}
.card-img,
.card-img-top {
@include border-top-radius(var(--#{$prefix}card-inner-border-radius));
}
.card-img,
.card-img-bottom {
@include border-bottom-radius(var(--#{$prefix}card-inner-border-radius));
}
//
// Card groups
//
.card-group {
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
flex: 1 0 0;
margin-bottom: 0;
margin-bottom: var(--#{$prefix}card-group-margin);
}
+ .card {
margin-left: 0;
border-left: 0;
}
@include media-breakpoint-up(sm) {
display: flex;
flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card {
flex: 1 0 0;
margin-bottom: 0;
// Handle rounded corners
@if $enable-rounded {
&:not(:last-child) {
@include border-end-radius(0);
> .card-img-top,
> .card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-right-radius: 0;
}
> .card-img-bottom,
> .card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-right-radius: 0;
}
+ .card {
margin-inline-start: 0;
border-inline-start: 0;
}
&:not(:first-child) {
@include border-start-radius(0);
// Handle rounded corners
@if $enable-rounded {
&:not(:last-child) {
@include border-end-radius(0);
> .card-img-top,
> .card-header {
// stylelint-disable-next-line property-disallowed-list
border-top-left-radius: 0;
> .card-img-top,
> .card-header {
border-start-end-radius: 0;
}
> .card-img-bottom,
> .card-footer {
border-end-end-radius: 0;
}
}
> .card-img-bottom,
> .card-footer {
// stylelint-disable-next-line property-disallowed-list
border-bottom-left-radius: 0;
&:not(:first-child) {
@include border-start-radius(0);
> .card-img-top,
> .card-header {
border-start-start-radius: 0;
}
> .card-img-bottom,
> .card-footer {
border-end-start-radius: 0;
}
}
}
}
+231 -181
View File
@@ -1,3 +1,48 @@
@use "config" as *;
@use "colors" as *;
@use "variables" as *;
@use "mixins/transition" as *;
@use "mixins/gradients" as *;
@use "mixins/color-mode" as *;
@use "vendor/rfs" as *;
// scss-docs-start carousel-variables
$carousel-control-color: $white !default;
$carousel-control-width: 15% !default;
$carousel-control-opacity: .5 !default;
$carousel-control-hover-opacity: .9 !default;
$carousel-control-transition: opacity .15s ease !default;
$carousel-control-icon-filter: null !default;
$carousel-indicator-width: 30px !default;
$carousel-indicator-height: 3px !default;
$carousel-indicator-hit-area-height: 10px !default;
$carousel-indicator-spacer: 3px !default;
$carousel-indicator-opacity: .5 !default;
$carousel-indicator-active-bg: $white !default;
$carousel-indicator-active-opacity: 1 !default;
$carousel-indicator-transition: opacity .6s ease !default;
$carousel-caption-width: 70% !default;
$carousel-caption-color: $white !default;
$carousel-caption-padding-y: 1.25rem !default;
$carousel-caption-spacer: 1.25rem !default;
$carousel-control-icon-width: 2rem !default;
$carousel-control-prev-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/></svg>") !default;
$carousel-control-next-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/></svg>") !default;
$carousel-transition-duration: .6s !default;
$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
// scss-docs-end carousel-variables
// scss-docs-start carousel-dark-variables
$carousel-indicator-active-bg-dark: $black !default;
$carousel-caption-color-dark: $black !default;
$carousel-control-icon-filter-dark: invert(1) grayscale(100) !default;
// scss-docs-end carousel-dark-variables
// Notes on the classes:
//
// 1. .carousel.pointer-event should ideally be pan-y (to allow for users to scroll vertically)
@@ -11,216 +56,221 @@
// 5. .carousel-item-next.carousel-item-start and .carousel-item-prev.carousel-item-end
// is the upcoming slide in transition.
.carousel {
position: relative;
}
@layer components {
.carousel {
position: relative;
}
.carousel.pointer-event {
touch-action: pan-y;
}
.carousel.pointer-event {
touch-action: pan-y;
}
.carousel-inner {
position: relative;
width: 100%;
overflow: hidden;
@include clearfix();
}
.carousel-inner {
position: relative;
display: flow-root;
width: 100%;
overflow: hidden;
}
.carousel-item {
position: relative;
display: none;
float: left;
width: 100%;
margin-right: -100%;
backface-visibility: hidden;
@include transition($carousel-transition);
}
.carousel-item.active,
.carousel-item-next,
.carousel-item-prev {
display: block;
}
.carousel-item-next:not(.carousel-item-start),
.active.carousel-item-end {
transform: translateX(100%);
}
.carousel-item-prev:not(.carousel-item-end),
.active.carousel-item-start {
transform: translateX(-100%);
}
//
// Alternate transitions
//
.carousel-fade {
.carousel-item {
opacity: 0;
transition-property: opacity;
transform: none;
position: relative;
display: none;
float: inline-start;
width: 100%;
margin-inline-end: -100%;
backface-visibility: hidden;
@include transition($carousel-transition);
}
.carousel-item.active,
.carousel-item-next.carousel-item-start,
.carousel-item-prev.carousel-item-end {
z-index: 1;
opacity: 1;
.carousel-item-next,
.carousel-item-prev {
display: block;
}
.active.carousel-item-start,
.carousel-item-next:not(.carousel-item-start),
.active.carousel-item-end {
z-index: 0;
opacity: 0;
@include transition(opacity 0s $carousel-transition-duration);
transform: translateX(100%);
}
}
//
// Left/right controls for nav
//
.carousel-control-prev,
.carousel-control-next {
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
// Use flex for alignment (1-3)
display: flex; // 1. allow flex styles
align-items: center; // 2. vertically center contents
justify-content: center; // 3. horizontally center contents
width: $carousel-control-width;
padding: 0;
color: $carousel-control-color;
text-align: center;
background: none;
filter: var(--#{$prefix}carousel-control-icon-filter);
border: 0;
opacity: $carousel-control-opacity;
@include transition($carousel-control-transition);
// Hover/focus state
&:hover,
&:focus {
color: $carousel-control-color;
text-decoration: none;
outline: 0;
opacity: $carousel-control-hover-opacity;
.carousel-item-prev:not(.carousel-item-end),
.active.carousel-item-start {
transform: translateX(-100%);
}
}
.carousel-control-prev {
left: 0;
background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null);
}
.carousel-control-next {
right: 0;
background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null);
}
// Icons for within
.carousel-control-prev-icon,
.carousel-control-next-icon {
display: inline-block;
width: $carousel-control-icon-width;
height: $carousel-control-icon-width;
background-repeat: no-repeat;
background-position: 50%;
background-size: 100% 100%;
}
.carousel-control-prev-icon {
background-image: escape-svg($carousel-control-prev-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-next-icon-bg) + "*/"};
}
.carousel-control-next-icon {
background-image: escape-svg($carousel-control-next-icon-bg) #{"/*rtl:" + escape-svg($carousel-control-prev-icon-bg) + "*/"};
}
//
// Alternate transitions
//
// Optional indicator pips/controls
//
// Add a container (such as a list) with the following class and add an item (ideally a focusable control,
// like a button) with data-bs-target for each slide your carousel holds.
.carousel-fade {
.carousel-item {
opacity: 0;
transition-property: opacity;
transform: none;
}
.carousel-indicators {
position: absolute;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: flex;
justify-content: center;
padding: 0;
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width;
margin-bottom: 1rem;
margin-left: $carousel-control-width;
.carousel-item.active,
.carousel-item-next.carousel-item-start,
.carousel-item-prev.carousel-item-end {
z-index: 1;
opacity: 1;
}
[data-bs-target] {
box-sizing: content-box;
flex: 0 1 auto;
width: $carousel-indicator-width;
height: $carousel-indicator-height;
.active.carousel-item-start,
.active.carousel-item-end {
z-index: 0;
opacity: 0;
@include transition(opacity 0s $carousel-transition-duration);
}
}
//
// Left/right controls for nav
//
.carousel-control-prev,
.carousel-control-next {
position: absolute;
inset-block: 0;
z-index: 1;
// Use flex for alignment (1-3)
display: flex; // 1. allow flex styles
align-items: center; // 2. vertically center contents
justify-content: center; // 3. horizontally center contents
width: $carousel-control-width;
padding: 0;
margin-right: $carousel-indicator-spacer;
margin-left: $carousel-indicator-spacer;
text-indent: -999px;
cursor: pointer;
background-color: var(--#{$prefix}carousel-indicator-active-bg);
background-clip: padding-box;
color: $carousel-control-color;
text-align: center;
background: none;
filter: var(--#{$prefix}carousel-control-icon-filter);
border: 0;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-top: $carousel-indicator-hit-area-height solid transparent;
border-bottom: $carousel-indicator-hit-area-height solid transparent;
opacity: $carousel-indicator-opacity;
@include transition($carousel-indicator-transition);
opacity: $carousel-control-opacity;
@include transition($carousel-control-transition);
// Hover/focus state
&:hover,
&:focus {
color: $carousel-control-color;
text-decoration: none;
outline: 0;
opacity: $carousel-control-hover-opacity;
}
}
.carousel-control-prev {
inset-inline-start: 0;
background-image: if($enable-gradients, linear-gradient(90deg, rgba($black, .25), rgba($black, .001)), null);
}
.carousel-control-next {
inset-inline-end: 0;
background-image: if($enable-gradients, linear-gradient(270deg, rgba($black, .25), rgba($black, .001)), null);
}
.active {
opacity: $carousel-indicator-active-opacity;
// Icons for within
.carousel-control-prev-icon,
.carousel-control-next-icon {
display: inline-block;
width: $carousel-control-icon-width;
height: $carousel-control-icon-width;
background-repeat: no-repeat;
background-position: 50%;
background-size: 100% 100%;
}
.carousel-control-prev-icon {
background-image: escape-svg($carousel-control-prev-icon-bg);
}
[dir="rtl"] .carousel-control-prev-icon {
background-image: escape-svg($carousel-control-next-icon-bg);
}
.carousel-control-next-icon {
background-image: escape-svg($carousel-control-next-icon-bg);
}
[dir="rtl"] .carousel-control-next-icon {
background-image: escape-svg($carousel-control-prev-icon-bg);
}
// Optional indicator pips/controls
//
// Add a container (such as a list) with the following class and add an item (ideally a focusable control,
// like a button) with data-bs-target for each slide your carousel holds.
.carousel-indicators {
position: absolute;
inset: auto 0 0;
z-index: 2;
display: flex;
justify-content: center;
padding: 0;
// Use the .carousel-control's width as margin so we don't overlay those
margin-inline: $carousel-control-width;
margin-bottom: 1rem;
[data-bs-target] {
box-sizing: content-box;
flex: 0 1 auto;
width: $carousel-indicator-width;
height: $carousel-indicator-height;
padding: 0;
margin-inline: $carousel-indicator-spacer;
text-indent: -999px;
cursor: pointer;
background-color: var(--#{$prefix}carousel-indicator-active-bg);
background-clip: padding-box;
border: 0;
// Use transparent borders to increase the hit area by 10px on top and bottom.
border-block: $carousel-indicator-hit-area-height solid transparent;
opacity: $carousel-indicator-opacity;
@include transition($carousel-indicator-transition);
}
.active {
opacity: $carousel-indicator-active-opacity;
}
}
}
// Optional captions
//
//
// Optional captions
//
//
.carousel-caption {
position: absolute;
right: (100% - $carousel-caption-width) * .5;
bottom: $carousel-caption-spacer;
left: (100% - $carousel-caption-width) * .5;
padding-top: $carousel-caption-padding-y;
padding-bottom: $carousel-caption-padding-y;
color: var(--#{$prefix}carousel-caption-color);
text-align: center;
}
.carousel-caption {
position: absolute;
right: (100% - $carousel-caption-width) * .5;
bottom: $carousel-caption-spacer;
left: (100% - $carousel-caption-width) * .5;
padding-top: $carousel-caption-padding-y;
padding-bottom: $carousel-caption-padding-y;
color: var(--#{$prefix}carousel-caption-color);
text-align: center;
}
// Dark mode carousel
// Dark mode carousel
@mixin carousel-dark() {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg-dark};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color-dark};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter-dark};
}
@mixin carousel-dark() {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg-dark};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color-dark};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter-dark};
}
.carousel-dark {
@include carousel-dark();
}
:root,
[data-bs-theme="light"] {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter};
}
@if $enable-dark-mode {
@include color-mode(dark, true) {
.carousel-dark {
@include carousel-dark();
}
:root,
[data-bs-theme="light"] {
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg};
--#{$prefix}carousel-caption-color: #{$carousel-caption-color};
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter};
}
@if $enable-dark-mode {
@include color-mode(dark, true) {
@include carousel-dark();
}
}
}
-66
View File
@@ -1,66 +0,0 @@
// Transparent background and border properties included for button version.
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
.btn-close {
// scss-docs-start close-css-vars
--#{$prefix}btn-close-color: #{$btn-close-color};
--#{$prefix}btn-close-bg: #{ escape-svg($btn-close-bg) };
--#{$prefix}btn-close-opacity: #{$btn-close-opacity};
--#{$prefix}btn-close-hover-opacity: #{$btn-close-hover-opacity};
--#{$prefix}btn-close-focus-shadow: #{$btn-close-focus-shadow};
--#{$prefix}btn-close-focus-opacity: #{$btn-close-focus-opacity};
--#{$prefix}btn-close-disabled-opacity: #{$btn-close-disabled-opacity};
// scss-docs-end close-css-vars
box-sizing: content-box;
width: $btn-close-width;
height: $btn-close-height;
padding: $btn-close-padding-y $btn-close-padding-x;
color: var(--#{$prefix}btn-close-color);
background: transparent var(--#{$prefix}btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements
filter: var(--#{$prefix}btn-close-filter);
border: 0; // for button elements
@include border-radius();
opacity: var(--#{$prefix}btn-close-opacity);
// Override <a>'s hover style
&:hover {
color: var(--#{$prefix}btn-close-color);
text-decoration: none;
opacity: var(--#{$prefix}btn-close-hover-opacity);
}
&:focus {
outline: 0;
box-shadow: var(--#{$prefix}btn-close-focus-shadow);
opacity: var(--#{$prefix}btn-close-focus-opacity);
}
&:disabled,
&.disabled {
pointer-events: none;
user-select: none;
opacity: var(--#{$prefix}btn-close-disabled-opacity);
}
}
@mixin btn-close-white() {
--#{$prefix}btn-close-filter: #{$btn-close-filter-dark};
}
.btn-close-white {
@include btn-close-white();
}
:root,
[data-bs-theme="light"] {
--#{$prefix}btn-close-filter: #{$btn-close-filter};
}
@if $enable-dark-mode {
@include color-mode(dark, true) {
@include btn-close-white();
}
}
+61
View File
@@ -0,0 +1,61 @@
@use "config" as *;
// stylelint-disable hue-degree-notation, @stylistic/number-leading-zero
// Easily convert colors to oklch() with https://oklch.com/
$new-blue: oklch(60% 0.24 258) !default;
$new-indigo: oklch(56% 0.26 288) !default;
$new-violet: oklch(56% 0.24 300) !default;
$new-purple: oklch(56% 0.24 320) !default;
$new-pink: oklch(60% 0.22 4) !default;
$new-red: oklch(60% 0.22 20) !default;
$new-orange: oklch(70% 0.22 52) !default;
$new-amber: oklch(79% 0.2 78) !default;
$new-yellow: oklch(88% 0.24 88) !default;
$new-lime: oklch(65% 0.24 135) !default;
$new-green: oklch(64% 0.22 160) !default;
$new-teal: oklch(68% 0.22 190) !default;
$new-cyan: oklch(69% 0.22 220) !default;
$new-brown: oklch(60% 0.12 54) !default;
$new-gray: oklch(60% 0.02 245) !default;
$new-pewter: oklch(65% 0.01 290) !default;
$hues: (
"blue": $new-blue,
"indigo": $new-indigo,
"violet": $new-violet,
"purple": $new-purple,
"pink": $new-pink,
"red": $new-red,
"orange": $new-orange,
"amber": $new-amber,
"yellow": $new-yellow,
"lime": $new-lime,
"green": $new-green,
"teal": $new-teal,
"cyan": $new-cyan,
"brown": $new-brown,
"gray": $new-gray,
"pewter": $new-pewter
) !default;
:root {
@each $color, $hue in $hues {
--#{$prefix}#{$color}-025: color-mix(in lab, #fff 94%, #{$hue});
--#{$prefix}#{$color}-050: color-mix(in lab, #fff 90%, #{$hue});
--#{$prefix}#{$color}-100: color-mix(in lab, #fff 80%, #{$hue});
--#{$prefix}#{$color}-200: color-mix(in lab, #fff 60%, #{$hue});
--#{$prefix}#{$color}-300: color-mix(in lab, #fff 40%, #{$hue});
--#{$prefix}#{$color}-400: color-mix(in lab, #fff 20%, #{$hue});
--#{$prefix}#{$color}-500: #{$hue};
--#{$prefix}#{$color}-600: color-mix(in lab, #000 16%, #{$hue});
--#{$prefix}#{$color}-700: color-mix(in lab, #000 32%, #{$hue});
--#{$prefix}#{$color}-800: color-mix(in lab, #000 48%, #{$hue});
--#{$prefix}#{$color}-900: color-mix(in lab, #000 64%, #{$hue});
--#{$prefix}#{$color}-950: color-mix(in lab, #000 76%, #{$hue});
--#{$prefix}#{$color}-975: color-mix(in lab, #000 88%, #{$hue});
}
}
$white: #fff !default;
$black: #000 !default;

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