flowbite-svelte 0.22.21 → 0.22.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/alerts/Alert.svelte +5 -5
- package/badges/Badge.svelte +22 -4
- package/badges/Badge.svelte.d.ts +2 -0
- package/forms/Checkbox.svelte +1 -0
- package/forms/Checkbox.svelte.d.ts +1 -0
- package/forms/Toggle.svelte +1 -1
- package/forms/Toggle.svelte.d.ts +1 -0
- package/modals/Modal.svelte +8 -7
- package/package.json +2 -1
- package/utils/CloseButton.svelte +18 -2
- package/utils/CloseButton.svelte.d.ts +1 -0
- package/utils/focusTrap.js +61 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.22.24](https://github.com/themesberg/flowbite-svelte/compare/v0.22.23...v0.22.24) (2022-07-29)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* badges new features ([775ecbc](https://github.com/themesberg/flowbite-svelte/commit/775ecbc04df58cd7c2517d103c963e7add92b5f6))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* pink color ([e4551b5](https://github.com/themesberg/flowbite-svelte/commit/e4551b54e0b56c07bae45d2bddb1b2930a20fe72))
|
|
16
|
+
|
|
17
|
+
### [0.22.23](https://github.com/themesberg/flowbite-svelte/compare/v0.22.22...v0.22.23) (2022-07-29)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* minor fixes / fine tuning ([57c1cf7](https://github.com/themesberg/flowbite-svelte/commit/57c1cf7f1bd461c417be1fd925766c045d72c015))
|
|
23
|
+
|
|
24
|
+
### [0.22.22](https://github.com/themesberg/flowbite-svelte/compare/v0.22.21...v0.22.22) (2022-07-28)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
* focus trap for modals ([08604ac](https://github.com/themesberg/flowbite-svelte/commit/08604ac3475f28a5a35c037e47ecfc13ee13b877))
|
|
30
|
+
|
|
5
31
|
### [0.22.21](https://github.com/themesberg/flowbite-svelte/compare/v0.22.20...v0.22.21) (2022-07-28)
|
|
6
32
|
|
|
7
33
|
|
package/alerts/Alert.svelte
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
<script>import
|
|
1
|
+
<script>import { setContext } from 'svelte';
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
import { createEventDispatcher } from 'svelte';
|
|
3
4
|
import CloseButton from '../utils/CloseButton.svelte';
|
|
4
5
|
const dispatch = createEventDispatcher();
|
|
6
|
+
setContext('background', true);
|
|
5
7
|
export let color = 'blue';
|
|
6
8
|
export let icon = null;
|
|
7
9
|
export let dismissable = false;
|
|
@@ -48,13 +50,11 @@ const textColors = {
|
|
|
48
50
|
dark: 'text-gray-700 dark:text-gray-300'
|
|
49
51
|
};
|
|
50
52
|
let divClass;
|
|
51
|
-
$: divClass = classNames('flex flex-col p-4 mb-4 gap-2 ', bgClasses[color] ?? bgClasses.blue, accent && (borderAccentClasses[color] ?? borderAccentClasses.blue), rounded && 'rounded-lg ', accent && 'border-t-4 ', $$props.class);
|
|
52
|
-
let textColor;
|
|
53
|
-
$: textColor = textColors[color] ?? textColors.blue;
|
|
53
|
+
$: divClass = classNames('flex flex-col p-4 mb-4 gap-2 ', bgClasses[color] ?? bgClasses.blue, accent && (borderAccentClasses[color] ?? borderAccentClasses.blue), rounded && 'rounded-lg ', accent && 'border-t-4 ', textColors[color], $$props.class);
|
|
54
54
|
</script>
|
|
55
55
|
|
|
56
56
|
<div id={$$props.id} class:hidden class={divClass} role="alert">
|
|
57
|
-
<div class="flex items-center
|
|
57
|
+
<div class="flex items-center">
|
|
58
58
|
{#if icon}
|
|
59
59
|
<svelte:component this={icon} class="flex-shrink-0 w-5 h-5 mr-3" />
|
|
60
60
|
{/if}
|
package/badges/Badge.svelte
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script>import classNames from 'classnames';
|
|
2
|
+
import CloseButton from '../utils/CloseButton.svelte';
|
|
2
3
|
export let color = 'blue';
|
|
3
4
|
export let large = false;
|
|
4
5
|
export let href = undefined;
|
|
5
6
|
export let rounded = false;
|
|
6
|
-
let
|
|
7
|
+
export let index = false;
|
|
8
|
+
export let dismissable = false;
|
|
9
|
+
let hidden = false;
|
|
7
10
|
const colors = {
|
|
8
11
|
blue: 'bg-blue-100 text-blue-800 dark:bg-blue-200 dark:text-blue-800',
|
|
9
12
|
dark: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300',
|
|
@@ -12,7 +15,15 @@ const colors = {
|
|
|
12
15
|
yellow: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-200 dark:text-yellow-900',
|
|
13
16
|
indigo: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-200 dark:text-indigo-900',
|
|
14
17
|
purple: 'bg-purple-100 text-purple-800 dark:bg-purple-200 dark:text-purple-900',
|
|
15
|
-
pink: 'bg-pink-100 text-pink-800 dark:bg-pink-200 dark:text-pink-900'
|
|
18
|
+
pink: 'bg-pink-100 text-pink-800 dark:bg-pink-200 dark:text-pink-900',
|
|
19
|
+
['!blue']: 'bg-blue-500 text-blue-100',
|
|
20
|
+
['!dark']: 'bg-gray-500 text-gray-100',
|
|
21
|
+
['!red']: 'bg-red-500 text-white',
|
|
22
|
+
['!green']: 'bg-green-500 text-green-100',
|
|
23
|
+
['!yellow']: 'bg-yellow-300 text-yellow-800',
|
|
24
|
+
['!indigo']: 'bg-indigo-500 text-indigo-100',
|
|
25
|
+
['!purple']: 'bg-purple-500 text-purple-100',
|
|
26
|
+
['!pink']: 'bg-pink-500 text-pink-100'
|
|
16
27
|
};
|
|
17
28
|
const hovers = {
|
|
18
29
|
blue: 'hover:bg-blue-200 dark:hover:bg-blue-300',
|
|
@@ -24,9 +35,16 @@ const hovers = {
|
|
|
24
35
|
purple: 'hover:bg-purple-200 dark:hover:bg-purple-300',
|
|
25
36
|
pink: 'hover:bg-pink-200 dark:hover:bg-pink-300'
|
|
26
37
|
};
|
|
27
|
-
|
|
38
|
+
let badgeClass;
|
|
39
|
+
$: badgeClass = classNames('inline-flex items-center justify-center -mb-0.5', large ? 'text-sm font-medium' : 'text-xs font-semibold', colors[color], href && (hovers[color] ?? hovers.blue), rounded ? 'rounded-full p-1' : 'rounded px-2.5 py-0.5', index && 'absolute font-bold border-2 border-white dark:border-gray-900', index && (large ? 'w-7 h-7 -top-3 -right-3' : 'w-6 h-6 -top-2 -right-2'), $$props.class);
|
|
40
|
+
const handleHide = () => {
|
|
41
|
+
hidden = !hidden;
|
|
42
|
+
};
|
|
28
43
|
</script>
|
|
29
44
|
|
|
30
|
-
<svelte:element this={href ? 'a' : 'span'} {href} {...$$restProps} class={badgeClass}>
|
|
45
|
+
<svelte:element this={href ? 'a' : 'span'} {href} {...$$restProps} class={badgeClass} class:hidden>
|
|
31
46
|
<slot />
|
|
47
|
+
{#if dismissable}
|
|
48
|
+
<CloseButton {color} on:click={handleHide} size={large ? 'sm' : 'xs'} class="ml-1.5 -mr-1.5" />
|
|
49
|
+
{/if}
|
|
32
50
|
</svelte:element>
|
package/badges/Badge.svelte.d.ts
CHANGED
package/forms/Checkbox.svelte
CHANGED
package/forms/Toggle.svelte
CHANGED
|
@@ -26,7 +26,7 @@ let divClass;
|
|
|
26
26
|
$: divClass = classNames(common, background ? 'dark:bg-gray-600 dark:border-gray-500' : 'dark:bg-gray-700 dark:border-gray-600', colors[$$restProps.color ?? 'blue'], sizes[size], 'relative');
|
|
27
27
|
</script>
|
|
28
28
|
|
|
29
|
-
<Checkbox custom {...$$restProps} class={$$props.class}
|
|
29
|
+
<Checkbox custom {...$$restProps} class={$$props.class} {value} bind:checked bind:group on:click on:change>
|
|
30
30
|
<div class={divClass} />
|
|
31
31
|
<slot />
|
|
32
32
|
</Checkbox>
|
package/forms/Toggle.svelte.d.ts
CHANGED
package/modals/Modal.svelte
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>import { createEventDispatcher } from 'svelte';
|
|
2
2
|
import { setContext } from 'svelte';
|
|
3
3
|
import CloseButton from '../utils/CloseButton.svelte';
|
|
4
|
+
import focusTrap from '../utils/focusTrap';
|
|
4
5
|
export let open = false;
|
|
5
6
|
export let title = undefined;
|
|
6
7
|
export let size = 'md';
|
|
@@ -18,15 +19,14 @@ const allPlacementClasses = [
|
|
|
18
19
|
'items-end'
|
|
19
20
|
];
|
|
20
21
|
let backdropEl;
|
|
21
|
-
function init(node,
|
|
22
|
+
function init(node, _open) {
|
|
22
23
|
getPlacementClasses().map((c) => node.classList.add(c));
|
|
23
|
-
|
|
24
|
-
createBackdrop(node);
|
|
24
|
+
_open && createBackdrop(node);
|
|
25
25
|
return {
|
|
26
|
-
update(
|
|
26
|
+
update(_open) {
|
|
27
27
|
allPlacementClasses.map((c) => node.classList.remove(c));
|
|
28
28
|
getPlacementClasses().map((c) => node.classList.add(c));
|
|
29
|
-
|
|
29
|
+
_open ? createBackdrop(node) : destroyBackdrop(node);
|
|
30
30
|
},
|
|
31
31
|
destroy() {
|
|
32
32
|
destroyBackdrop(node);
|
|
@@ -44,17 +44,17 @@ function createBackdrop(node) {
|
|
|
44
44
|
const body = document.querySelector('body');
|
|
45
45
|
body.append(backdropEl);
|
|
46
46
|
body.style.overflow = 'hidden';
|
|
47
|
-
|
|
47
|
+
document.addEventListener('keydown', handleEscape, true);
|
|
48
48
|
}
|
|
49
49
|
dispatch('show', node);
|
|
50
50
|
}
|
|
51
51
|
function destroyBackdrop(node) {
|
|
52
52
|
const body = document.querySelector('body');
|
|
53
53
|
body.style.overflow = 'auto';
|
|
54
|
-
body.removeEventListener('keydown', handleEscape, true);
|
|
55
54
|
if (backdropEl)
|
|
56
55
|
backdropEl.remove();
|
|
57
56
|
backdropEl = undefined;
|
|
57
|
+
document.removeEventListener('keydown', handleEscape, true);
|
|
58
58
|
dispatch('hide', node);
|
|
59
59
|
}
|
|
60
60
|
function getPlacementClasses() {
|
|
@@ -110,6 +110,7 @@ function hide() {
|
|
|
110
110
|
aria-modal={open ? 'true' : undefined}
|
|
111
111
|
role={open ? 'dialog' : undefined}
|
|
112
112
|
use:init={open}
|
|
113
|
+
use:focusTrap={open}
|
|
113
114
|
on:click={onButtonsClick}
|
|
114
115
|
>
|
|
115
116
|
<div class="relative p-4 w-full {sizes[size]} h-full md:h-auto">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flowbite-svelte",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.24",
|
|
4
4
|
"description": "Flowbite components for Svelte",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": {
|
|
@@ -236,6 +236,7 @@
|
|
|
236
236
|
"./utils/CloseButton.svelte": "./utils/CloseButton.svelte",
|
|
237
237
|
"./utils/OptsButton.svelte": "./utils/OptsButton.svelte",
|
|
238
238
|
"./utils/clickOutside": "./utils/clickOutside.js",
|
|
239
|
+
"./utils/focusTrap": "./utils/focusTrap.js",
|
|
239
240
|
"./utils/generateId": "./utils/generateId.js"
|
|
240
241
|
},
|
|
241
242
|
"svelte": "./index.js"
|
package/utils/CloseButton.svelte
CHANGED
|
@@ -3,6 +3,7 @@ import classNames from 'classnames';
|
|
|
3
3
|
const background = getContext('background');
|
|
4
4
|
export let color = 'default';
|
|
5
5
|
export let name = 'Close';
|
|
6
|
+
export let size = 'md';
|
|
6
7
|
const colors = {
|
|
7
8
|
gray: 'focus:ring-gray-400 hover:bg-gray-200 dark:hover:bg-gray-300',
|
|
8
9
|
red: 'focus:ring-red-400 hover:bg-red-200 dark:hover:bg-red-300',
|
|
@@ -14,17 +15,32 @@ const colors = {
|
|
|
14
15
|
blue: 'focus:ring-blue-400 hover:bg-blue-200 dark:hover:bg-blue-300',
|
|
15
16
|
default: 'focus:ring-gray-300 '
|
|
16
17
|
};
|
|
18
|
+
const sizing = {
|
|
19
|
+
xs: 'm-0.5 rounded focus:ring-1 p-0.5',
|
|
20
|
+
sm: 'm-0.5 rounded focus:ring-1 p-0.5',
|
|
21
|
+
md: '-mx-1 -my-1.5 rounded-lg focus:ring-2 p-1.5'
|
|
22
|
+
};
|
|
17
23
|
let buttonClass = '';
|
|
18
|
-
$: buttonClass = classNames('ml-auto
|
|
24
|
+
$: buttonClass = classNames('ml-auto focus:outline-none', sizing[size], colors[color], color === 'default' &&
|
|
19
25
|
(background
|
|
20
26
|
? 'hover:bg-gray-100 dark:hover:bg-gray-600'
|
|
21
27
|
: 'hover:bg-gray-100 dark:hover:bg-gray-700'), $$props.class);
|
|
28
|
+
const svgSizes = {
|
|
29
|
+
xs: 'w-3 h-3',
|
|
30
|
+
sm: 'w-3.5 h-3.5',
|
|
31
|
+
md: 'w-5 h-5'
|
|
32
|
+
};
|
|
22
33
|
</script>
|
|
23
34
|
|
|
24
35
|
<button on:click type="button" class={buttonClass} aria-label="Close">
|
|
25
36
|
<slot>
|
|
26
37
|
<span class="sr-only">{name}</span>
|
|
27
|
-
<svg
|
|
38
|
+
<svg
|
|
39
|
+
class={svgSizes[size]}
|
|
40
|
+
fill="currentColor"
|
|
41
|
+
viewBox="0 0 20 20"
|
|
42
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
43
|
+
>
|
|
28
44
|
<path
|
|
29
45
|
fill-rule="evenodd"
|
|
30
46
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Focus trap copied from https://uxdesign.cc/how-to-trap-focus-inside-modal-to-make-it-ada-compliant-6a50f9a70700
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// add all the elements inside modal which you want to make focusable
|
|
6
|
+
const focusableElements =
|
|
7
|
+
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
8
|
+
|
|
9
|
+
function getFocusable(node) {
|
|
10
|
+
const focusableContent = node.querySelectorAll(focusableElements);
|
|
11
|
+
return [focusableContent[0], focusableContent[focusableContent.length - 1]];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function focusTrap(node, _open) {
|
|
15
|
+
let firstFocusableElement, lastFocusableElement; // first and last element to be focused inside modal
|
|
16
|
+
|
|
17
|
+
function handleFocusTrap(e) {
|
|
18
|
+
let isTabPressed = e.key === 'Tab' || e.keyCode === 9;
|
|
19
|
+
|
|
20
|
+
if (!isTabPressed) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (e.shiftKey) {
|
|
25
|
+
// if shift key pressed for shift + tab combination
|
|
26
|
+
if (document.activeElement === firstFocusableElement) {
|
|
27
|
+
lastFocusableElement.focus(); // add focus for the last focusable element
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
// if tab key is pressed
|
|
32
|
+
if (document.activeElement === lastFocusableElement) {
|
|
33
|
+
// if focused has reached to last focusable element then focus first focusable element after pressing tab
|
|
34
|
+
firstFocusableElement.focus(); // add focus for the first focusable element
|
|
35
|
+
e.preventDefault();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (_open) {
|
|
41
|
+
[firstFocusableElement, lastFocusableElement] = getFocusable(node);
|
|
42
|
+
document.addEventListener('keydown', handleFocusTrap, true);
|
|
43
|
+
firstFocusableElement.focus();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
update(_open) {
|
|
48
|
+
if (_open) {
|
|
49
|
+
[firstFocusableElement, lastFocusableElement] = getFocusable(node);
|
|
50
|
+
document.addEventListener('keydown', handleFocusTrap, true);
|
|
51
|
+
firstFocusableElement.focus();
|
|
52
|
+
} else {
|
|
53
|
+
document.removeEventListener('keydown', handleFocusTrap, true);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
destroy() {
|
|
58
|
+
document.removeEventListener('keydown', handleFocusTrap, true);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|