@functionalcms/svelte-components 2.33.1 → 2.34.1
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/components/Link.svelte +290 -290
- package/dist/components/agnostic/Alert/Alert.svelte +310 -0
- package/dist/components/agnostic/Alert/Alert.svelte.d.ts +31 -0
- package/dist/components/agnostic/Avatar/Avatar.svelte +123 -0
- package/dist/components/agnostic/Avatar/Avatar.svelte.d.ts +26 -0
- package/dist/components/agnostic/Avatar/AvatarGroup.svelte +106 -0
- package/dist/components/agnostic/Avatar/AvatarGroup.svelte.d.ts +29 -0
- package/dist/components/agnostic/Breadcrumb/Breadcrumb.svelte +56 -0
- package/dist/components/agnostic/Breadcrumb/Breadcrumb.svelte.d.ts +20 -0
- package/dist/components/agnostic/Breadcrumb/api.d.ts +4 -0
- package/dist/components/agnostic/Breadcrumb/api.js +1 -0
- package/dist/components/agnostic/Button/Button.svelte +345 -0
- package/dist/components/agnostic/Button/Button.svelte.d.ts +43 -0
- package/dist/components/agnostic/Button/ButtonGroup.svelte +20 -0
- package/dist/components/agnostic/Button/ButtonGroup.svelte.d.ts +23 -0
- package/dist/components/agnostic/Button/button-base.css +12 -0
- package/dist/components/agnostic/Button/button-core.css +237 -0
- package/dist/components/agnostic/Button/button-empty.css +31 -0
- package/dist/components/agnostic/Button/button-group.css +8 -0
- package/dist/components/agnostic/Card/Card.svelte +133 -0
- package/dist/components/agnostic/Card/Card.svelte.d.ts +31 -0
- package/dist/components/agnostic/ChoiceInput/ChoiceInput.svelte +337 -0
- package/dist/components/agnostic/ChoiceInput/ChoiceInput.svelte.d.ts +37 -0
- package/dist/components/agnostic/ChoiceInput/api.d.ts +7 -0
- package/dist/components/agnostic/ChoiceInput/api.js +1 -0
- package/dist/components/agnostic/Close/Close.svelte +120 -0
- package/dist/components/agnostic/Close/Close.svelte.d.ts +23 -0
- package/dist/components/agnostic/Close/api.d.ts +1 -0
- package/dist/components/agnostic/Close/api.js +1 -0
- package/dist/components/agnostic/Dialog/Dialog.svelte +265 -0
- package/dist/components/agnostic/Dialog/Dialog.svelte.d.ts +39 -0
- package/dist/components/agnostic/Disclose/Disclose.svelte +102 -0
- package/dist/components/agnostic/Disclose/Disclose.svelte.d.ts +23 -0
- package/dist/components/agnostic/Divider/Divider.svelte +139 -0
- package/dist/components/agnostic/Divider/Divider.svelte.d.ts +25 -0
- package/dist/components/agnostic/Divider/api.d.ts +3 -0
- package/dist/components/agnostic/Divider/api.js +1 -0
- package/dist/components/agnostic/Drawer/Drawer.svelte +30 -0
- package/dist/components/agnostic/Drawer/Drawer.svelte.d.ts +28 -0
- package/dist/components/agnostic/Drawer/api.d.ts +1 -0
- package/dist/components/agnostic/Drawer/api.js +1 -0
- package/dist/components/agnostic/EmptyState/EmptyState.svelte +46 -0
- package/dist/components/agnostic/EmptyState/EmptyState.svelte.d.ts +23 -0
- package/dist/components/agnostic/Header/Header.svelte +104 -0
- package/dist/components/agnostic/Header/Header.svelte.d.ts +26 -0
- package/dist/components/agnostic/Header/HeaderNav.svelte +28 -0
- package/dist/components/agnostic/Header/HeaderNav.svelte.d.ts +20 -0
- package/dist/components/agnostic/Header/HeaderNavItem.svelte +30 -0
- package/dist/components/agnostic/Header/HeaderNavItem.svelte.d.ts +20 -0
- package/dist/components/agnostic/Icon/Icon.svelte +180 -0
- package/dist/components/agnostic/Icon/Icon.svelte.d.ts +23 -0
- package/dist/components/agnostic/Icon/api.d.ts +2 -0
- package/dist/components/agnostic/Icon/api.js +1 -0
- package/dist/components/agnostic/Input/Input.svelte +415 -0
- package/dist/components/agnostic/Input/Input.svelte.d.ts +45 -0
- package/dist/components/agnostic/Input/InputAddonItem.svelte +42 -0
- package/dist/components/agnostic/Input/InputAddonItem.svelte.d.ts +33 -0
- package/dist/components/agnostic/Loader/Loader.svelte +113 -0
- package/dist/components/agnostic/Loader/Loader.svelte.d.ts +20 -0
- package/dist/components/agnostic/Menu/Menu.svelte +466 -0
- package/dist/components/agnostic/Menu/Menu.svelte.d.ts +31 -0
- package/dist/components/agnostic/Menu/MenuItem.svelte +117 -0
- package/dist/components/agnostic/Menu/MenuItem.svelte.d.ts +29 -0
- package/dist/components/agnostic/Progress/Progress.svelte +50 -0
- package/dist/components/agnostic/Progress/Progress.svelte.d.ts +20 -0
- package/dist/components/agnostic/Select/Select.svelte +141 -0
- package/dist/components/agnostic/Select/Select.svelte.d.ts +32 -0
- package/dist/components/agnostic/Spinner/Spinner.svelte +105 -0
- package/dist/components/agnostic/Spinner/Spinner.svelte.d.ts +19 -0
- package/dist/components/agnostic/Switch/Switch.svelte +275 -0
- package/dist/components/agnostic/Switch/Switch.svelte.d.ts +45 -0
- package/dist/components/agnostic/Table/Table.svelte +508 -0
- package/dist/components/agnostic/Table/Table.svelte.d.ts +36 -0
- package/dist/components/agnostic/Table/TableCustomRenderComponent.svelte +13 -0
- package/dist/components/agnostic/Table/TableCustomRenderComponent.svelte.d.ts +25 -0
- package/dist/components/agnostic/Tabs/TabButtonCustom.svelte +65 -0
- package/dist/components/agnostic/Tabs/TabButtonCustom.svelte.d.ts +35 -0
- package/dist/components/agnostic/Tabs/Tabs.svelte +330 -0
- package/dist/components/agnostic/Tabs/Tabs.svelte.d.ts +34 -0
- package/dist/components/agnostic/Tabs/api.d.ts +10 -0
- package/dist/components/agnostic/Tabs/api.js +1 -0
- package/dist/components/agnostic/Tag/Tag.svelte +74 -0
- package/dist/components/agnostic/Tag/Tag.svelte.d.ts +23 -0
- package/dist/components/agnostic/Tag/TagSlots.svelte +51 -0
- package/dist/components/agnostic/Tag/TagSlots.svelte.d.ts +16 -0
- package/dist/components/agnostic/Toasts/Toasts.svelte +46 -0
- package/dist/components/agnostic/Toasts/Toasts.svelte.d.ts +22 -0
- package/dist/components/agnostic/Tooltip/Tooltip.svelte +103 -0
- package/dist/components/agnostic/Tooltip/Tooltip.svelte.d.ts +23 -0
- package/dist/components/agnostic/Tooltip/TooltipSlots.svelte +81 -0
- package/dist/components/agnostic/Tooltip/TooltipSlots.svelte.d.ts +16 -0
- package/dist/components/agnostic/Tooltip/api.d.ts +1 -0
- package/dist/components/agnostic/Tooltip/api.js +1 -0
- package/dist/components/agnostic/animation.css +37 -0
- package/dist/components/files/utils.js +1 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +30 -1
- package/package.json +1 -4
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.select,
|
|
3
|
+
.select-base {
|
|
4
|
+
display: block;
|
|
5
|
+
width: 100%;
|
|
6
|
+
/* stylelint-disable-next-line property-no-vendor-prefix */
|
|
7
|
+
-webkit-appearance: none;
|
|
8
|
+
/* stylelint-disable-next-line property-no-vendor-prefix */
|
|
9
|
+
-moz-appearance: none;
|
|
10
|
+
appearance: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.select,
|
|
14
|
+
.select-skin {
|
|
15
|
+
padding: var(--fluid-6) var(--fluid-32) var(--fluid-6) var(--fluid-12);
|
|
16
|
+
-moz-padding-start: calc(var(--fluid-12) - 3px);
|
|
17
|
+
font-size: var(--fluid-16);
|
|
18
|
+
font-weight: 400;
|
|
19
|
+
line-height: 1.5;
|
|
20
|
+
color: var(--functional-dark);
|
|
21
|
+
border: 1px solid var(--functional-select-border-color, var(--functional-gray-light));
|
|
22
|
+
border-radius: var(--functional-radius);
|
|
23
|
+
transition:
|
|
24
|
+
border-color var(--functional-timing-fast) ease-in-out,
|
|
25
|
+
box-shadow var(--functional-timing-fast) ease-in-out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Only shows the down arrow SVG if in single mode */
|
|
29
|
+
.select:not([multiple]) {
|
|
30
|
+
background-color: inherit;
|
|
31
|
+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23333330' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
|
|
32
|
+
background-repeat: no-repeat;
|
|
33
|
+
background-position: right var(--fluid-12) center;
|
|
34
|
+
background-size: var(--fluid-16) var(--fluid-12);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.select:focus {
|
|
38
|
+
border-color: var(--functional-focus-ring-color);
|
|
39
|
+
box-shadow: 0 0 0 var(--functional-focus-ring-outline-width) var(--functional-focus-ring-color);
|
|
40
|
+
|
|
41
|
+
/* Needed for High Contrast mode */
|
|
42
|
+
outline:
|
|
43
|
+
var(--functional-focus-ring-outline-width) var(--functional-focus-ring-outline-style)
|
|
44
|
+
var(--functional-focus-ring-outline-color);
|
|
45
|
+
transition: box-shadow var(--functional-timing-fast) ease-out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.select-base,
|
|
49
|
+
.select:disabled {
|
|
50
|
+
background-color: var(--functional-disabled-bg);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.select-base,
|
|
54
|
+
.select:-moz-focusring {
|
|
55
|
+
color: transparent;
|
|
56
|
+
text-shadow: 0 0 0 var(--functional-dark);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (prefers-reduced-motion), (update: slow) {
|
|
60
|
+
.select,
|
|
61
|
+
.select-base,
|
|
62
|
+
.select:focus {
|
|
63
|
+
transition: none;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.select-small {
|
|
68
|
+
padding-top: var(--fluid-4);
|
|
69
|
+
padding-bottom: var(--fluid-4);
|
|
70
|
+
padding-left: var(--fluid-8);
|
|
71
|
+
font-size: var(--fluid-14);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.select-large {
|
|
75
|
+
padding-top: var(--fluid-8);
|
|
76
|
+
padding-bottom: var(--fluid-8);
|
|
77
|
+
padding-left: var(--fluid-16);
|
|
78
|
+
font-size: var(--fluid-18);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
</style>
|
|
82
|
+
|
|
83
|
+
<script>import { createEventDispatcher } from "svelte";
|
|
84
|
+
export let uniqueId = "";
|
|
85
|
+
export let name = "";
|
|
86
|
+
export let labelCopy = "";
|
|
87
|
+
export let options = [];
|
|
88
|
+
export let size = "";
|
|
89
|
+
export let multipleSize = 1;
|
|
90
|
+
export let isMultiple = false;
|
|
91
|
+
export let defaultOptionLabel = "Please select an option";
|
|
92
|
+
export let isDisabled = false;
|
|
93
|
+
export let isSkinned = true;
|
|
94
|
+
export let css = "";
|
|
95
|
+
export let singleSelected = "";
|
|
96
|
+
export let multiSelected = [];
|
|
97
|
+
const dispatch = createEventDispatcher();
|
|
98
|
+
const changeHandler = () => {
|
|
99
|
+
dispatch("selected", isMultiple ? multiSelected : singleSelected);
|
|
100
|
+
};
|
|
101
|
+
$: disable = isDisabled;
|
|
102
|
+
$: classes = [
|
|
103
|
+
isSkinned ? "select" : "select-base",
|
|
104
|
+
size ? `select-${size}` : "",
|
|
105
|
+
css ? `${css}` : ""
|
|
106
|
+
].filter((cl) => cl).join(" ");
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
<label class="screenreader-only" for={uniqueId}> {labelCopy} </label>
|
|
110
|
+
{#if isMultiple}
|
|
111
|
+
<select
|
|
112
|
+
id={uniqueId}
|
|
113
|
+
class={classes}
|
|
114
|
+
name={name}
|
|
115
|
+
disabled={disable}
|
|
116
|
+
multiple
|
|
117
|
+
size={multipleSize}
|
|
118
|
+
bind:value={multiSelected}
|
|
119
|
+
on:change={changeHandler}
|
|
120
|
+
>
|
|
121
|
+
{#each options as { value, label }}
|
|
122
|
+
<option value={value}>{label}</option>
|
|
123
|
+
{/each}
|
|
124
|
+
</select>
|
|
125
|
+
{:else}
|
|
126
|
+
<select
|
|
127
|
+
id={uniqueId}
|
|
128
|
+
class={classes}
|
|
129
|
+
name={name}
|
|
130
|
+
disabled={disable}
|
|
131
|
+
bind:value={singleSelected}
|
|
132
|
+
on:change={changeHandler}
|
|
133
|
+
>
|
|
134
|
+
<option value="" disabled selected>
|
|
135
|
+
{defaultOptionLabel}
|
|
136
|
+
</option>
|
|
137
|
+
{#each options as { value, label }}
|
|
138
|
+
<option value={value}>{label}</option>
|
|
139
|
+
{/each}
|
|
140
|
+
</select>
|
|
141
|
+
{/if}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
uniqueId?: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
labelCopy?: string;
|
|
7
|
+
options?: any[];
|
|
8
|
+
size?: "small" | "large" | "";
|
|
9
|
+
multipleSize?: number;
|
|
10
|
+
isMultiple?: boolean;
|
|
11
|
+
defaultOptionLabel?: string;
|
|
12
|
+
isDisabled?: boolean;
|
|
13
|
+
isSkinned?: boolean;
|
|
14
|
+
css?: string;
|
|
15
|
+
singleSelected?: string;
|
|
16
|
+
multiSelected?: any[];
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
selected: CustomEvent<any>;
|
|
20
|
+
} & {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {};
|
|
24
|
+
exports?: {} | undefined;
|
|
25
|
+
bindings?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
export type SelectProps = typeof __propDef.props;
|
|
28
|
+
export type SelectEvents = typeof __propDef.events;
|
|
29
|
+
export type SelectSlots = typeof __propDef.slots;
|
|
30
|
+
export default class Select extends SvelteComponent<SelectProps, SelectEvents, SelectSlots> {
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.spinner {
|
|
3
|
+
--spinner-color: var(--functional-spinner-color, var(--functional-dark));
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Inspiration to utilize grid for this from
|
|
7
|
+
* https://dockyard.com/blog/2020/03/02/accessible-loading-indicatorswith-no-extra-elements
|
|
8
|
+
*/
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template: "content" 100% / auto;
|
|
11
|
+
place-items: center;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.spinner::before,
|
|
16
|
+
.spinner::after {
|
|
17
|
+
grid-area: content;
|
|
18
|
+
width: var(--fluid-32);
|
|
19
|
+
height: var(--fluid-32);
|
|
20
|
+
content: "";
|
|
21
|
+
display: block;
|
|
22
|
+
border-radius: 50%;
|
|
23
|
+
border-width: 3px;
|
|
24
|
+
border-style: solid;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.spinner-small::before,
|
|
28
|
+
.spinner-small::after {
|
|
29
|
+
width: var(--fluid-24);
|
|
30
|
+
height: var(--fluid-24);
|
|
31
|
+
border-width: var(--fluid-2);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.spinner-large::before,
|
|
35
|
+
.spinner-large::after {
|
|
36
|
+
width: var(--fluid-40);
|
|
37
|
+
height: var(--fluid-40);
|
|
38
|
+
border-width: var(--fluid-4);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.spinner-xlarge::before,
|
|
42
|
+
.spinner-xlarge::after {
|
|
43
|
+
width: var(--fluid-56);
|
|
44
|
+
height: var(--fluid-56);
|
|
45
|
+
border-width: var(--fluid-6);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Before is the muted background
|
|
50
|
+
*/
|
|
51
|
+
.spinner::before {
|
|
52
|
+
opacity: 0%;
|
|
53
|
+
border-color: var(--spinner-color);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* After is the inner "snake"
|
|
58
|
+
*/
|
|
59
|
+
.spinner::after {
|
|
60
|
+
opacity: 0%;
|
|
61
|
+
border-color: transparent var(--spinner-color) transparent transparent;
|
|
62
|
+
transition: opacity 0.1s;
|
|
63
|
+
pointer-events: none;
|
|
64
|
+
animation: loading-circle 1s ease-in-out infinite;
|
|
65
|
+
|
|
66
|
+
/* TODO Research the whole null transform hack. It is quite confusing to figure out if it
|
|
67
|
+
is beneficial or detrimental: See
|
|
68
|
+
https://newbedev.com/css-keyframe-animation-cpu-usage-is-high-should-it-be-this-way
|
|
69
|
+
transform: translateZ(0);
|
|
70
|
+
will-change: transform; */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Setting aria-busy to true results in corresponding opacity change to visually show spinner.
|
|
75
|
+
*/
|
|
76
|
+
.spinner[aria-busy="true"]::before {
|
|
77
|
+
opacity: 12%;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.spinner[aria-busy="true"]::after {
|
|
81
|
+
opacity: 100%;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@keyframes loading-circle {
|
|
85
|
+
to {
|
|
86
|
+
transform: rotate(360deg);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@media (prefers-reduced-motion), (update: slow) {
|
|
91
|
+
.spinner::after {
|
|
92
|
+
transition-duration: 0.001ms !important;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
</style>
|
|
97
|
+
|
|
98
|
+
<script>export let ariaLabel = "Loading\u2026";
|
|
99
|
+
export let size = "";
|
|
100
|
+
$: spinnerClasses = ["spinner", size ? `spinner-${size}` : ""].filter((c) => c).join(" ");
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<div class={spinnerClasses} role="status" aria-live="polite" aria-busy="true">
|
|
104
|
+
<span class="screenreader-only">{ariaLabel}</span>
|
|
105
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
ariaLabel?: string;
|
|
5
|
+
size?: "small" | "large" | "xlarge" | "";
|
|
6
|
+
};
|
|
7
|
+
events: {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
};
|
|
10
|
+
slots: {};
|
|
11
|
+
exports?: {} | undefined;
|
|
12
|
+
bindings?: string | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type SpinnerProps = typeof __propDef.props;
|
|
15
|
+
export type SpinnerEvents = typeof __propDef.events;
|
|
16
|
+
export type SpinnerSlots = typeof __propDef.slots;
|
|
17
|
+
export default class Spinner extends SvelteComponent<SpinnerProps, SpinnerEvents, SpinnerSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
/**
|
|
3
|
+
* Switch
|
|
4
|
+
*
|
|
5
|
+
* This switch is inspired by Scott Ohara's checkbox switch:
|
|
6
|
+
* https://scottaohara.github.io/a11y_styled_form_controls/src/checkbox--switch/
|
|
7
|
+
*/
|
|
8
|
+
.switch-container {
|
|
9
|
+
display: block;
|
|
10
|
+
|
|
11
|
+
/* TODO: Hopefully this doesn't become a problem but since we use absolute
|
|
12
|
+
positioning extensively, we need some way to have adjacent spaced lines */
|
|
13
|
+
min-height: 2.25rem;
|
|
14
|
+
width: 100%;
|
|
15
|
+
padding: 0.5rem;
|
|
16
|
+
position: relative;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.switch-container:hover {
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* using the before/after pseudo elements of the span to create the "switch" */
|
|
24
|
+
.switch::before,
|
|
25
|
+
.switch::after {
|
|
26
|
+
border: 1px solid var(--functional-gray-mid-dark);
|
|
27
|
+
content: "";
|
|
28
|
+
position: absolute;
|
|
29
|
+
top: 50%;
|
|
30
|
+
transform: translateY(-50%);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* styling specific to the knob of the switch */
|
|
34
|
+
.switch::after {
|
|
35
|
+
background: #fff;
|
|
36
|
+
border-radius: 100%;
|
|
37
|
+
width: 1.4rem;
|
|
38
|
+
height: 1.4rem;
|
|
39
|
+
right: 1.4rem;
|
|
40
|
+
transition: right var(--functional-timing-fast) ease-in-out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* styling specific to the knob "container" */
|
|
44
|
+
.switch::before {
|
|
45
|
+
background: #eee;
|
|
46
|
+
border-radius: 1.75rem;
|
|
47
|
+
width: 2.75rem;
|
|
48
|
+
height: 1.75rem;
|
|
49
|
+
right: 0.25rem;
|
|
50
|
+
transition: background var(--functional-timing-medium) ease-in-out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Sizes */
|
|
54
|
+
.switch-small::after {
|
|
55
|
+
width: 1.25rem;
|
|
56
|
+
height: 1.25rem;
|
|
57
|
+
right: 1.125rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.switch-small::before {
|
|
61
|
+
width: 2.25rem;
|
|
62
|
+
height: 1.5rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.switch-large::after {
|
|
66
|
+
width: 1.65rem;
|
|
67
|
+
height: 1.65rem;
|
|
68
|
+
right: 1.65rem;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.switch-large::before {
|
|
72
|
+
width: 3.25rem;
|
|
73
|
+
height: 2rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.switch-border::before {
|
|
77
|
+
border: 1px solid var(--functional-primary);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.switch-action.switch-border::before {
|
|
81
|
+
border: 1px solid var(--functional-action);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Switch label on right */
|
|
85
|
+
|
|
86
|
+
/* We have to flip the positioning when the label is on the right of switch */
|
|
87
|
+
.switch-right .switch::before {
|
|
88
|
+
right: initial;
|
|
89
|
+
left: 0.25rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.switch-right .switch::after {
|
|
93
|
+
right: initial;
|
|
94
|
+
left: 1.4rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Switch sizes w/label on right -- I expect SMACSS so .switch .switch-small
|
|
98
|
+
classes should both exist so the right: initial was taken care of above :) */
|
|
99
|
+
.switch-right .switch-small::after {
|
|
100
|
+
left: 1.125rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.switch-right .switch-large::after {
|
|
104
|
+
left: 1.65rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* ---- CHECKED STATE ----- */
|
|
108
|
+
|
|
109
|
+
/* change the position of the knob to indicate it has been checked */
|
|
110
|
+
|
|
111
|
+
.switch-input:checked + .switch-small::after {
|
|
112
|
+
right: 0.425rem;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.switch-input:checked + .switch::after {
|
|
116
|
+
right: 0.5em;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.switch-right .switch-label {
|
|
120
|
+
position: absolute;
|
|
121
|
+
right: 0;
|
|
122
|
+
|
|
123
|
+
/* Flips transition target to left to preserve our smooth transitions */
|
|
124
|
+
transition: left var(--functional-timing-fast) ease-in-out;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.switch-right .switch-input:checked + .switch::after {
|
|
128
|
+
right: initial;
|
|
129
|
+
left: 0.5em;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.switch-right .switch-input:checked + .switch-small::after {
|
|
133
|
+
right: initial;
|
|
134
|
+
left: 0.425rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* From: https://scottaohara.github.io/a11y_styled_form_controls/src/checkbox--switch/
|
|
138
|
+
hide the actual checkbox from view, but not from keyboards or ATs.
|
|
139
|
+
Instead of standard visually hidden styling, instead set opacity to
|
|
140
|
+
almost 0 (not zero for ChomeVox legacy bug), pointer-events none, and
|
|
141
|
+
then set to full height/width of container element so that VO focus
|
|
142
|
+
ring outlines the component, instead of a tiny box within the component
|
|
143
|
+
*/
|
|
144
|
+
.switch-input {
|
|
145
|
+
margin: 0;
|
|
146
|
+
opacity: 0.01%;
|
|
147
|
+
position: absolute;
|
|
148
|
+
left: 0;
|
|
149
|
+
top: 0;
|
|
150
|
+
width: 100%;
|
|
151
|
+
height: 100%;
|
|
152
|
+
pointer-events: none;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.switch-input:focus + .switch::before {
|
|
156
|
+
box-shadow: 0 0 0 var(--functional-focus-ring-outline-width) var(--functional-focus-ring-color);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* update the color of the "container" to further visually indicate state */
|
|
160
|
+
.switch-input:checked + .switch:not(.switch-border)::before {
|
|
161
|
+
background: var(--functional-primary);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.switch-input:checked + .switch-action:not(.switch-border)::before {
|
|
165
|
+
background: var(--functional-action);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Border switch on checked the thumb gets primary or action bg respectively */
|
|
169
|
+
.switch-input:checked + .switch-border::after {
|
|
170
|
+
background: var(--functional-primary);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.switch-input:checked + .switch-action.switch-border::after {
|
|
174
|
+
background: var(--functional-action);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Disabled aka :disabled is not actually supported for <label>
|
|
178
|
+
element so we use attribute selector for that:
|
|
179
|
+
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled#:~:text=The%20disabled%20attribute%20is%20supported,control%20or%20its%20descendant%20controls.
|
|
180
|
+
*/
|
|
181
|
+
.switch-input[disabled] + .switch,
|
|
182
|
+
.switch-input[disabled] + .switch-label,
|
|
183
|
+
.switch-container.disabled {
|
|
184
|
+
color: var(--functional-input-disabled-color, var(--functional-disabled-color)) !important;
|
|
185
|
+
appearance: none !important;
|
|
186
|
+
box-shadow: none !important;
|
|
187
|
+
cursor: not-allowed !important;
|
|
188
|
+
opacity: 80% !important;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@media screen and (-ms-high-contrast: active) {
|
|
192
|
+
.switch::after {
|
|
193
|
+
background-color: windowText;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* High contrast mode outline hacks */
|
|
197
|
+
.switch-input[disabled] + .switch-label,
|
|
198
|
+
.switch-container.disabled {
|
|
199
|
+
outline: 2px solid transparent;
|
|
200
|
+
outline-offset: -2px;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@media (prefers-reduced-motion), (update: slow) {
|
|
205
|
+
.switch::after,
|
|
206
|
+
.switch::before {
|
|
207
|
+
transition-duration: 0.001ms !important;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
</style>
|
|
212
|
+
|
|
213
|
+
<script>
|
|
214
|
+
export let id = "";
|
|
215
|
+
export let label = "";
|
|
216
|
+
export let css = "";
|
|
217
|
+
export let labelPosition = "left";
|
|
218
|
+
export let size = "";
|
|
219
|
+
export let isChecked = false;
|
|
220
|
+
export let isBordered = false;
|
|
221
|
+
export let isAction = false;
|
|
222
|
+
export let isDisabled = false;
|
|
223
|
+
|
|
224
|
+
$: switchContainer = [
|
|
225
|
+
"switch-container",
|
|
226
|
+
labelPosition === "right" ? "switch-right" : "",
|
|
227
|
+
css ? css : "",
|
|
228
|
+
isDisabled ? "disabled" : "",
|
|
229
|
+
].filter(c => c).join(" ");
|
|
230
|
+
|
|
231
|
+
const switchSpan = () => {
|
|
232
|
+
let klasses = [
|
|
233
|
+
"switch",
|
|
234
|
+
isBordered ? "switch-border" : "",
|
|
235
|
+
isAction ? "switch-action" : "",
|
|
236
|
+
size ? `switch-${size}` : "",
|
|
237
|
+
];
|
|
238
|
+
klasses = klasses.filter((klass) => klass.length);
|
|
239
|
+
return klasses.join(" ");
|
|
240
|
+
};
|
|
241
|
+
const handleClick = (evt) => {
|
|
242
|
+
const el = evt.target;
|
|
243
|
+
if (el.getAttribute("aria-checked") == "true") {
|
|
244
|
+
el.setAttribute("aria-checked", "false");
|
|
245
|
+
} else {
|
|
246
|
+
el.setAttribute("aria-checked", "true");
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const handleKeypress = (evt) => {
|
|
250
|
+
const keyCode = evt.keyCode || evt.which;
|
|
251
|
+
switch (keyCode) {
|
|
252
|
+
case 13:
|
|
253
|
+
evt.preventDefault();
|
|
254
|
+
evt.target.click();
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
<label class={switchContainer} for={id}>
|
|
261
|
+
{#if labelPosition === "left"}<span class="switch-label">{label}</span>{/if}
|
|
262
|
+
<input
|
|
263
|
+
type="checkbox"
|
|
264
|
+
class="switch-input"
|
|
265
|
+
id={id}
|
|
266
|
+
bind:checked={isChecked}
|
|
267
|
+
disabled={isDisabled}
|
|
268
|
+
on:change
|
|
269
|
+
on:click={handleClick}
|
|
270
|
+
on:keypress={handleKeypress}
|
|
271
|
+
role="switch"
|
|
272
|
+
/>
|
|
273
|
+
<span class={switchSpan()} aria-hidden="true"></span>
|
|
274
|
+
{#if labelPosition === "right"}<span class="switch-label">{label}</span>{/if}
|
|
275
|
+
</label>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SwitchProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SwitchEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SwitchSlots */
|
|
4
|
+
export default class Switch extends SvelteComponent<{
|
|
5
|
+
size?: string | undefined;
|
|
6
|
+
css?: string | undefined;
|
|
7
|
+
id?: string | undefined;
|
|
8
|
+
isBordered?: boolean | undefined;
|
|
9
|
+
isDisabled?: boolean | undefined;
|
|
10
|
+
label?: string | undefined;
|
|
11
|
+
labelPosition?: string | undefined;
|
|
12
|
+
isChecked?: boolean | undefined;
|
|
13
|
+
isAction?: boolean | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
change: Event;
|
|
16
|
+
} & {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
}, {}> {
|
|
19
|
+
}
|
|
20
|
+
export type SwitchProps = typeof __propDef.props;
|
|
21
|
+
export type SwitchEvents = typeof __propDef.events;
|
|
22
|
+
export type SwitchSlots = typeof __propDef.slots;
|
|
23
|
+
import { SvelteComponent } from "svelte";
|
|
24
|
+
declare const __propDef: {
|
|
25
|
+
props: {
|
|
26
|
+
size?: string | undefined;
|
|
27
|
+
css?: string | undefined;
|
|
28
|
+
id?: string | undefined;
|
|
29
|
+
isBordered?: boolean | undefined;
|
|
30
|
+
isDisabled?: boolean | undefined;
|
|
31
|
+
label?: string | undefined;
|
|
32
|
+
labelPosition?: string | undefined;
|
|
33
|
+
isChecked?: boolean | undefined;
|
|
34
|
+
isAction?: boolean | undefined;
|
|
35
|
+
};
|
|
36
|
+
events: {
|
|
37
|
+
change: Event;
|
|
38
|
+
} & {
|
|
39
|
+
[evt: string]: CustomEvent<any>;
|
|
40
|
+
};
|
|
41
|
+
slots: {};
|
|
42
|
+
exports?: undefined;
|
|
43
|
+
bindings?: undefined;
|
|
44
|
+
};
|
|
45
|
+
export {};
|