@marianmeres/stuic 1.13.0 → 1.15.0
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/dist/actions/focus-trap.js +26 -25
- package/dist/components/Button/Button.svelte +10 -1
- package/dist/components/Button/Button.svelte.d.ts +1 -0
- package/dist/components/Switch/Switch.svelte +128 -0
- package/dist/components/Switch/Switch.svelte.d.ts +63 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/package.json +2 -2
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
// copied from skeleton
|
|
1
|
+
// initially copied from skeleton, adjusted
|
|
2
2
|
const defaults = { enabled: true, autoFocusFirst: true };
|
|
3
|
-
// Action: Focus Trap
|
|
4
3
|
export function focusTrap(node, options = {}) {
|
|
5
4
|
let { enabled, autoFocusFirst } = { ...defaults, ...(options || {}) };
|
|
6
5
|
const focusableSelectors = [
|
|
7
|
-
'[contentEditable=true]
|
|
6
|
+
'[contentEditable=true]',
|
|
8
7
|
//
|
|
9
|
-
'button:not([disabled])
|
|
10
|
-
'input:not([disabled])
|
|
11
|
-
'select:not([disabled])
|
|
12
|
-
'textarea:not([disabled])
|
|
13
|
-
//
|
|
14
|
-
'a[href]:not([tabindex^="-"])',
|
|
15
|
-
'area[href]:not([tabindex^="-"])',
|
|
16
|
-
'details:not([tabindex^="-"])',
|
|
17
|
-
'iframe:not([tabindex^="-"])',
|
|
8
|
+
'button:not([disabled])',
|
|
9
|
+
'input:not([disabled])',
|
|
10
|
+
'select:not([disabled])',
|
|
11
|
+
'textarea:not([disabled])',
|
|
18
12
|
//
|
|
13
|
+
'a[href]',
|
|
14
|
+
'area[href]',
|
|
15
|
+
'details',
|
|
16
|
+
'iframe',
|
|
17
|
+
// see more below on tabindexes
|
|
19
18
|
'[tabindex]:not([tabindex^="-"])',
|
|
20
19
|
].join(',');
|
|
21
20
|
let first;
|
|
@@ -37,10 +36,13 @@ export function focusTrap(node, options = {}) {
|
|
|
37
36
|
const queryElements = (fromObserver) => {
|
|
38
37
|
if (enabled === false)
|
|
39
38
|
return;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// (
|
|
39
|
+
let maxTabindex = 0;
|
|
40
|
+
let focusable = [...node.querySelectorAll(focusableSelectors)]
|
|
41
|
+
// filter negative tabindexes (afaik there is no :not([disabled] OR [tabindex^="-"]))
|
|
43
42
|
.filter((e) => {
|
|
43
|
+
// reusing loop for a side job here... see sort below
|
|
44
|
+
maxTabindex = Math.max(maxTabindex, parseInt(e.getAttribute('tabindex') || '0'));
|
|
45
|
+
//
|
|
44
46
|
if (e.getAttribute('disabled') === '')
|
|
45
47
|
return false;
|
|
46
48
|
if ((e.getAttribute('tabindex') || '').startsWith('-'))
|
|
@@ -48,9 +50,11 @@ export function focusTrap(node, options = {}) {
|
|
|
48
50
|
return true;
|
|
49
51
|
})
|
|
50
52
|
// important to sort by tabindex, so the first/last will work as expected
|
|
53
|
+
// but must increase zero to max + 1 first, because browsers focus zeros as last...
|
|
54
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
|
|
51
55
|
.sort((e1, e2) => {
|
|
52
|
-
const a = parseInt(e1.getAttribute('tabindex') || '0');
|
|
53
|
-
const b = parseInt(e2.getAttribute('tabindex') || '0');
|
|
56
|
+
const a = parseInt(e1.getAttribute('tabindex') || '0') || maxTabindex + 1;
|
|
57
|
+
const b = parseInt(e2.getAttribute('tabindex') || '0') || maxTabindex + 1;
|
|
54
58
|
return a - b;
|
|
55
59
|
});
|
|
56
60
|
if (focusable.length) {
|
|
@@ -66,20 +70,17 @@ export function focusTrap(node, options = {}) {
|
|
|
66
70
|
};
|
|
67
71
|
queryElements(false);
|
|
68
72
|
function cleanup() {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (last)
|
|
72
|
-
last.removeEventListener('keydown', onLastElemKeydown);
|
|
73
|
+
first && first.removeEventListener('keydown', onFirstElemKeydown);
|
|
74
|
+
last && last.removeEventListener('keydown', onLastElemKeydown);
|
|
73
75
|
}
|
|
74
76
|
// When children of node are changed (added or removed)
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
+
const observer = new MutationObserver((mutations, observer) => {
|
|
78
|
+
if (mutations.length) {
|
|
77
79
|
cleanup();
|
|
78
80
|
queryElements(true);
|
|
79
81
|
}
|
|
80
82
|
return observer;
|
|
81
|
-
};
|
|
82
|
-
const observer = new MutationObserver(onObservationChange);
|
|
83
|
+
});
|
|
83
84
|
observer.observe(node, { childList: true, subtree: true });
|
|
84
85
|
// Lifecycle
|
|
85
86
|
return {
|
|
@@ -61,6 +61,7 @@ export let rounded = ButtonConfig.defaultRounded;
|
|
|
61
61
|
export let variant = ButtonConfig.defaultVariant;
|
|
62
62
|
export let square = false;
|
|
63
63
|
export let disabled = false;
|
|
64
|
+
export let value = void 0;
|
|
64
65
|
const _whitelist = ["xs", "sm", "md", "lg", "xl"];
|
|
65
66
|
export let size = ButtonConfig.defaultSize;
|
|
66
67
|
$:
|
|
@@ -81,7 +82,6 @@ $:
|
|
|
81
82
|
//
|
|
82
83
|
ButtonConfig.class,
|
|
83
84
|
//
|
|
84
|
-
// variant && ButtonConfig.variant?.[variant],
|
|
85
85
|
variant && `${variant || ""}`.split(" ").reduce((m, v) => {
|
|
86
86
|
m += ButtonConfig.variant?.[v] + " ";
|
|
87
87
|
return m;
|
|
@@ -99,6 +99,10 @@ $:
|
|
|
99
99
|
class={buttonClass}
|
|
100
100
|
{...$$restProps}
|
|
101
101
|
role="button"
|
|
102
|
+
data-size={size}
|
|
103
|
+
data-shadow={shadow}
|
|
104
|
+
data-rounded={rounded}
|
|
105
|
+
data-variant={variant}
|
|
102
106
|
on:click
|
|
103
107
|
on:change
|
|
104
108
|
on:keydown
|
|
@@ -116,6 +120,11 @@ $:
|
|
|
116
120
|
{type}
|
|
117
121
|
{disabled}
|
|
118
122
|
class={buttonClass}
|
|
123
|
+
{value}
|
|
124
|
+
data-size={size}
|
|
125
|
+
data-shadow={shadow}
|
|
126
|
+
data-rounded={rounded}
|
|
127
|
+
data-variant={variant}
|
|
119
128
|
{...$$restProps}
|
|
120
129
|
on:click
|
|
121
130
|
on:change
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<script context="module">import { twMerge } from "tailwind-merge";
|
|
2
|
+
export class SwitchConfig {
|
|
3
|
+
static defaultSize = "md";
|
|
4
|
+
static defaultVariant = void 0;
|
|
5
|
+
static presetBase = `
|
|
6
|
+
relative inline-flex flex-shrink-0 items-center
|
|
7
|
+
m-2
|
|
8
|
+
rounded-full cursor-pointer
|
|
9
|
+
transition-colors duration-100
|
|
10
|
+
|
|
11
|
+
hover:brightness-[1.05] active:brightness-[0.95]
|
|
12
|
+
disabled:!cursor-not-allowed disabled:!opacity-50 disabled:hover:brightness-100
|
|
13
|
+
|
|
14
|
+
bg-zinc-300 data-[checked=true]:bg-zinc-600
|
|
15
|
+
`.trim();
|
|
16
|
+
static presetsSize = {
|
|
17
|
+
xs: "h-4 w-7",
|
|
18
|
+
sm: "h-5 w-9",
|
|
19
|
+
md: "h-6 w-11",
|
|
20
|
+
lg: "h-7 w-14",
|
|
21
|
+
xl: "h-8 w-16"
|
|
22
|
+
};
|
|
23
|
+
static class = "";
|
|
24
|
+
// to be defined at consumer level...
|
|
25
|
+
static variant = {};
|
|
26
|
+
// DOT
|
|
27
|
+
static presetBaseDot = `
|
|
28
|
+
block flex items-center justify-center
|
|
29
|
+
translate-x-1 rounded-full
|
|
30
|
+
transition-all duration-100
|
|
31
|
+
shadow
|
|
32
|
+
bg-white
|
|
33
|
+
`.trim();
|
|
34
|
+
static presetsSizeDot = {
|
|
35
|
+
// size + translate-x = width
|
|
36
|
+
xs: "size-2 data-[checked=true]:translate-x-4",
|
|
37
|
+
sm: "size-3 data-[checked=true]:translate-x-5",
|
|
38
|
+
md: "size-4 data-[checked=true]:translate-x-6",
|
|
39
|
+
lg: "size-5 data-[checked=true]:translate-x-8",
|
|
40
|
+
xl: "size-6 data-[checked=true]:translate-x-9"
|
|
41
|
+
};
|
|
42
|
+
static classDot = "";
|
|
43
|
+
// to be defined at consumer level...
|
|
44
|
+
static variantDot = {};
|
|
45
|
+
}
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<script>import { createEventDispatcher } from "svelte";
|
|
49
|
+
let _class = "";
|
|
50
|
+
export { _class as class };
|
|
51
|
+
export let classDot = "";
|
|
52
|
+
export let label = "";
|
|
53
|
+
export let checked = false;
|
|
54
|
+
export let disabled = false;
|
|
55
|
+
export let tabindex = 0;
|
|
56
|
+
export let variant = SwitchConfig.defaultVariant;
|
|
57
|
+
export let stopPropagation = true;
|
|
58
|
+
export let preventDefault = false;
|
|
59
|
+
const _defaultNoopHook = () => Promise.resolve(void 0);
|
|
60
|
+
export let preHook = _defaultNoopHook;
|
|
61
|
+
const _whitelist = ["xs", "sm", "md", "lg", "xl"];
|
|
62
|
+
export let size = SwitchConfig.defaultSize;
|
|
63
|
+
$:
|
|
64
|
+
if (!_whitelist.includes(size))
|
|
65
|
+
size = SwitchConfig.defaultSize;
|
|
66
|
+
let switchClass;
|
|
67
|
+
$:
|
|
68
|
+
switchClass = twMerge(
|
|
69
|
+
SwitchConfig.presetBase,
|
|
70
|
+
SwitchConfig.presetsSize[size],
|
|
71
|
+
SwitchConfig.class,
|
|
72
|
+
variant && `${variant || ""}`.split(" ").reduce((m, v) => {
|
|
73
|
+
m += SwitchConfig.variant?.[v] + " ";
|
|
74
|
+
return m;
|
|
75
|
+
}, ""),
|
|
76
|
+
_class
|
|
77
|
+
);
|
|
78
|
+
let dotClass;
|
|
79
|
+
$:
|
|
80
|
+
dotClass = twMerge(
|
|
81
|
+
SwitchConfig.presetBaseDot,
|
|
82
|
+
SwitchConfig.presetsSizeDot[size],
|
|
83
|
+
SwitchConfig.classDot,
|
|
84
|
+
classDot
|
|
85
|
+
);
|
|
86
|
+
const dispatch = createEventDispatcher();
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<button
|
|
90
|
+
class={switchClass}
|
|
91
|
+
type="button"
|
|
92
|
+
role="switch"
|
|
93
|
+
aria-checked={checked}
|
|
94
|
+
class:checked
|
|
95
|
+
data-checked={checked}
|
|
96
|
+
data-size={size}
|
|
97
|
+
{tabindex}
|
|
98
|
+
{disabled}
|
|
99
|
+
on:click={async (e) => {
|
|
100
|
+
stopPropagation && e.stopPropagation();
|
|
101
|
+
preventDefault && e.preventDefault();
|
|
102
|
+
|
|
103
|
+
// ability to break execution (do the change) by returning explicit `false`
|
|
104
|
+
if (typeof preHook === 'function' && (await preHook(checked)) === false) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
checked = !checked;
|
|
109
|
+
dispatch('change', checked);
|
|
110
|
+
}}
|
|
111
|
+
on:click
|
|
112
|
+
on:keydown
|
|
113
|
+
on:keyup
|
|
114
|
+
on:touchstart|passive
|
|
115
|
+
on:touchend
|
|
116
|
+
on:touchcancel
|
|
117
|
+
on:mouseenter
|
|
118
|
+
on:mouseleave
|
|
119
|
+
>
|
|
120
|
+
{#if label}<span class="sr-only">{@html label}</span>{/if}
|
|
121
|
+
<span aria-hidden="true" data-checked={checked} data-size={size} class={dotClass}>
|
|
122
|
+
{#if checked}
|
|
123
|
+
<slot name="on" />
|
|
124
|
+
{:else}
|
|
125
|
+
<slot name="off" />
|
|
126
|
+
{/if}
|
|
127
|
+
</span>
|
|
128
|
+
</button>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
export declare class SwitchConfig {
|
|
3
|
+
static defaultSize: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
|
+
static defaultVariant: string | undefined;
|
|
5
|
+
static presetBase: string;
|
|
6
|
+
static presetsSize: {
|
|
7
|
+
xs: string;
|
|
8
|
+
sm: string;
|
|
9
|
+
md: string;
|
|
10
|
+
lg: string;
|
|
11
|
+
xl: string;
|
|
12
|
+
};
|
|
13
|
+
static class: string;
|
|
14
|
+
static variant: Record<string, string>;
|
|
15
|
+
static presetBaseDot: string;
|
|
16
|
+
static presetsSizeDot: {
|
|
17
|
+
xs: string;
|
|
18
|
+
sm: string;
|
|
19
|
+
md: string;
|
|
20
|
+
lg: string;
|
|
21
|
+
xl: string;
|
|
22
|
+
};
|
|
23
|
+
static classDot: string;
|
|
24
|
+
static variantDot: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
declare const __propDef: {
|
|
27
|
+
props: {
|
|
28
|
+
class?: string | undefined;
|
|
29
|
+
classDot?: string | undefined;
|
|
30
|
+
label?: string | undefined;
|
|
31
|
+
checked?: boolean | undefined;
|
|
32
|
+
disabled?: boolean | undefined;
|
|
33
|
+
tabindex?: number | undefined;
|
|
34
|
+
variant?: string | undefined;
|
|
35
|
+
stopPropagation?: boolean | undefined;
|
|
36
|
+
preventDefault?: boolean | undefined;
|
|
37
|
+
preHook?: ((oldValue: boolean) => Promise<void | boolean>) | undefined;
|
|
38
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | undefined;
|
|
39
|
+
};
|
|
40
|
+
events: {
|
|
41
|
+
click: MouseEvent;
|
|
42
|
+
keydown: KeyboardEvent;
|
|
43
|
+
keyup: KeyboardEvent;
|
|
44
|
+
touchstart: TouchEvent;
|
|
45
|
+
touchend: TouchEvent;
|
|
46
|
+
touchcancel: TouchEvent;
|
|
47
|
+
mouseenter: MouseEvent;
|
|
48
|
+
mouseleave: MouseEvent;
|
|
49
|
+
change: CustomEvent<any>;
|
|
50
|
+
} & {
|
|
51
|
+
[evt: string]: CustomEvent<any>;
|
|
52
|
+
};
|
|
53
|
+
slots: {
|
|
54
|
+
on: {};
|
|
55
|
+
off: {};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
export type SwitchProps = typeof __propDef.props;
|
|
59
|
+
export type SwitchEvents = typeof __propDef.events;
|
|
60
|
+
export type SwitchSlots = typeof __propDef.slots;
|
|
61
|
+
export default class Switch extends SvelteComponent<SwitchProps, SwitchEvents, SwitchSlots> {
|
|
62
|
+
}
|
|
63
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { default as LocalColorScheme } from './components/ColorScheme/LocalColor
|
|
|
6
6
|
export { ColorScheme } from './components/ColorScheme/color-scheme.js';
|
|
7
7
|
export { default as Drawer, createDrawerStore } from './components/Drawer/Drawer.svelte';
|
|
8
8
|
export { default as HoverExpandableWidth } from './components/HoverExpandableWidth/HoverExpandableWidth.svelte';
|
|
9
|
+
export { default as Switch } from './components/Switch/Switch.svelte';
|
|
9
10
|
export { default as X } from './components/X/X.svelte';
|
|
10
11
|
export { clickOutside } from './actions/click-outside.js';
|
|
11
12
|
export { focusTrap } from './actions/focus-trap.js';
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export { default as Drawer, createDrawerStore } from './components/Drawer/Drawer
|
|
|
14
14
|
//
|
|
15
15
|
export { default as HoverExpandableWidth } from './components/HoverExpandableWidth/HoverExpandableWidth.svelte';
|
|
16
16
|
//
|
|
17
|
+
export { default as Switch } from './components/Switch/Switch.svelte';
|
|
18
|
+
//
|
|
17
19
|
export { default as X } from './components/X/X.svelte';
|
|
18
20
|
// actions
|
|
19
21
|
export { clickOutside } from './actions/click-outside.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marianmeres/stuic",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run package && node ./scripts/date.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"svelte": "^4.0.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"@marianmeres/icons-fns": "^2.0
|
|
34
|
+
"@marianmeres/icons-fns": "^2.1.0",
|
|
35
35
|
"@marianmeres/parse-boolean": "^1.1.7",
|
|
36
36
|
"@marianmeres/random-human-readable": "^1.6.1",
|
|
37
37
|
"@marianmeres/release": "^1.1.2",
|