@sveltia/ui 0.2.0 → 0.2.2
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/package/components/composite/calendar.svelte +239 -0
- package/package/components/composite/calendar.svelte.d.ts +27 -0
- package/package/components/composite/checkbox-group.svelte +43 -0
- package/package/components/composite/checkbox-group.svelte.d.ts +34 -0
- package/package/components/composite/combobox.svelte +208 -0
- package/package/components/composite/combobox.svelte.d.ts +47 -0
- package/package/components/composite/disclosure.svelte +60 -0
- package/package/components/composite/disclosure.svelte.d.ts +35 -0
- package/package/components/composite/grid.svelte +24 -0
- package/package/components/composite/grid.svelte.d.ts +31 -0
- package/package/components/composite/listbox.svelte +63 -0
- package/package/components/composite/listbox.svelte.d.ts +52 -0
- package/package/components/composite/menu-item-group.svelte +31 -0
- package/package/components/composite/menu-item-group.svelte.d.ts +33 -0
- package/package/components/composite/menu.svelte +44 -0
- package/package/components/composite/menu.svelte.d.ts +41 -0
- package/package/components/composite/radio-button-group.svelte +45 -0
- package/package/components/composite/radio-button-group.svelte.d.ts +36 -0
- package/package/components/composite/select-button-group.svelte +71 -0
- package/package/components/composite/select-button-group.svelte.d.ts +44 -0
- package/package/components/composite/select.svelte +34 -0
- package/package/components/composite/select.svelte.d.ts +38 -0
- package/package/components/composite/tab-list.svelte +76 -0
- package/package/components/composite/tab-list.svelte.d.ts +55 -0
- package/package/components/core/button.svelte +222 -0
- package/package/components/core/button.svelte.d.ts +109 -0
- package/package/components/core/checkbox.svelte +114 -0
- package/package/components/core/checkbox.svelte.d.ts +45 -0
- package/package/components/core/dialog.svelte +288 -0
- package/package/components/core/dialog.svelte.d.ts +73 -0
- package/package/components/core/drawer.svelte +338 -0
- package/package/components/core/drawer.svelte.d.ts +59 -0
- package/package/components/core/grid-cell.svelte +14 -0
- package/package/components/core/grid-cell.svelte.d.ts +29 -0
- package/package/components/core/group.svelte +31 -0
- package/package/components/core/group.svelte.d.ts +33 -0
- package/package/components/core/icon.svelte +21 -0
- package/package/components/core/icon.svelte.d.ts +27 -0
- package/package/components/core/menu-button.svelte +57 -0
- package/package/components/core/menu-button.svelte.d.ts +46 -0
- package/package/components/core/menu-item-checkbox.svelte +24 -0
- package/package/components/core/menu-item-checkbox.svelte.d.ts +34 -0
- package/package/components/core/menu-item-radio.svelte +19 -0
- package/package/components/core/menu-item-radio.svelte.d.ts +34 -0
- package/package/components/core/menu-item.svelte +113 -0
- package/package/components/core/menu-item.svelte.d.ts +44 -0
- package/package/components/core/number-input.svelte +112 -0
- package/package/components/core/number-input.svelte.d.ts +42 -0
- package/package/components/core/option.svelte +65 -0
- package/package/components/core/option.svelte.d.ts +60 -0
- package/package/components/core/password-input.svelte +81 -0
- package/package/components/core/password-input.svelte.d.ts +36 -0
- package/package/components/core/radio-button.svelte +93 -0
- package/package/components/core/radio-button.svelte.d.ts +37 -0
- package/package/components/core/row-group.svelte +14 -0
- package/package/components/core/row-group.svelte.d.ts +29 -0
- package/package/components/core/row.svelte +14 -0
- package/package/components/core/row.svelte.d.ts +33 -0
- package/package/components/core/search-bar.svelte +91 -0
- package/package/components/core/search-bar.svelte.d.ts +49 -0
- package/package/components/core/select-button.svelte +31 -0
- package/package/components/core/select-button.svelte.d.ts +52 -0
- package/package/components/core/separator.svelte +28 -0
- package/package/components/core/separator.svelte.d.ts +26 -0
- package/package/components/core/slider.svelte +271 -0
- package/package/components/core/slider.svelte.d.ts +51 -0
- package/package/components/core/spacer.svelte +22 -0
- package/package/components/core/spacer.svelte.d.ts +25 -0
- package/package/components/core/switch.svelte +86 -0
- package/package/components/core/switch.svelte.d.ts +37 -0
- package/package/components/core/tab-panel.svelte +23 -0
- package/package/components/core/tab-panel.svelte.d.ts +33 -0
- package/package/components/core/tab.svelte +22 -0
- package/package/components/core/tab.svelte.d.ts +45 -0
- package/package/components/core/text-area.svelte +90 -0
- package/package/components/core/text-area.svelte.d.ts +57 -0
- package/package/components/core/text-input.svelte +146 -0
- package/package/components/core/text-input.svelte.d.ts +71 -0
- package/package/components/core/toolbar.svelte +74 -0
- package/package/components/core/toolbar.svelte.d.ts +35 -0
- package/package/components/editor/markdown.svelte +78 -0
- package/package/components/editor/markdown.svelte.d.ts +25 -0
- package/package/components/helpers/group.d.ts +37 -0
- package/package/components/helpers/group.js +246 -0
- package/package/components/helpers/popup.d.ts +31 -0
- package/package/components/helpers/popup.js +165 -0
- package/package/components/helpers/util.d.ts +1 -0
- package/package/components/helpers/util.js +8 -0
- package/package/components/util/app-shell.svelte +354 -0
- package/package/components/util/app-shell.svelte.d.ts +38 -0
- package/package/components/util/misc.d.ts +2 -0
- package/package/components/util/misc.js +22 -0
- package/package/components/util/popup.svelte +155 -0
- package/package/components/util/popup.svelte.d.ts +53 -0
- package/package/components/util/portal.svelte +34 -0
- package/package/components/util/portal.svelte.d.ts +28 -0
- package/package/index.d.ts +43 -0
- package/package/index.js +68 -0
- package/package/locales/en.d.ts +42 -0
- package/package/locales/en.js +41 -0
- package/package/locales/ja.d.ts +42 -0
- package/package/locales/ja.js +41 -0
- package/package/styles/core.scss +134 -0
- package/package/styles/variables.scss +184 -0
- package/package/typedef.d.ts +0 -0
- package/package/typedef.js +0 -0
- package/package.json +2 -3
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
@see https://w3c.github.io/aria/#search
|
|
4
|
+
-->
|
|
5
|
+
<svelte:options accessors={true} />
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import { _ } from 'svelte-i18n';
|
|
9
|
+
import Button from './button.svelte';
|
|
10
|
+
import Icon from './icon.svelte';
|
|
11
|
+
import TextInput from './text-input.svelte';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* CSS class name on the button.
|
|
15
|
+
* @type {String}
|
|
16
|
+
*/
|
|
17
|
+
let className = '';
|
|
18
|
+
|
|
19
|
+
export { className as class };
|
|
20
|
+
|
|
21
|
+
/** @type {_SvelteComponent} */
|
|
22
|
+
let input;
|
|
23
|
+
|
|
24
|
+
export let value = '';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Move focus to the `<input>` element.
|
|
28
|
+
*/
|
|
29
|
+
export const focus = () => {
|
|
30
|
+
input?.element?.focus();
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div class="sui search-bar {className}" role="search">
|
|
35
|
+
<Icon name="search" />
|
|
36
|
+
<TextInput
|
|
37
|
+
bind:this={input}
|
|
38
|
+
bind:value
|
|
39
|
+
role="searchbox"
|
|
40
|
+
{...$$restProps}
|
|
41
|
+
on:input
|
|
42
|
+
on:keydown
|
|
43
|
+
on:keyup
|
|
44
|
+
on:keypress
|
|
45
|
+
on:change
|
|
46
|
+
/>
|
|
47
|
+
{#if value}
|
|
48
|
+
<Button
|
|
49
|
+
class="iconic"
|
|
50
|
+
on:click={() => {
|
|
51
|
+
value = '';
|
|
52
|
+
input.element.focus();
|
|
53
|
+
window.requestIdleCallback(() => {
|
|
54
|
+
input.element.dispatchEvent(new KeyboardEvent('input'));
|
|
55
|
+
input.element.dispatchEvent(new KeyboardEvent('keypress'));
|
|
56
|
+
input.element.dispatchEvent(new KeyboardEvent('change'));
|
|
57
|
+
});
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
<Icon slot="start-icon" name="close" label={$_('_sui._.clear')} />
|
|
61
|
+
</Button>
|
|
62
|
+
{/if}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<style>[role=search] {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
position: relative;
|
|
69
|
+
}
|
|
70
|
+
[role=search] :global(.icon) {
|
|
71
|
+
font-size: var(--font-size--xx-large);
|
|
72
|
+
opacity: 0.5;
|
|
73
|
+
}
|
|
74
|
+
[role=search] > :global(.icon) {
|
|
75
|
+
position: absolute;
|
|
76
|
+
inset: 8px auto auto 8px;
|
|
77
|
+
z-index: 2;
|
|
78
|
+
}
|
|
79
|
+
[role=search] > :global(button) {
|
|
80
|
+
position: absolute;
|
|
81
|
+
inset: 0 0 auto auto;
|
|
82
|
+
z-index: 2;
|
|
83
|
+
height: var(--button--medium--height);
|
|
84
|
+
}
|
|
85
|
+
[role=search] :global(.label) {
|
|
86
|
+
inset: 0 36px;
|
|
87
|
+
}
|
|
88
|
+
[role=search] :global(input) {
|
|
89
|
+
padding: 0 36px !important;
|
|
90
|
+
width: 100%;
|
|
91
|
+
}</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SearchBarProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SearchBarEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SearchBarSlots */
|
|
4
|
+
/** @see https://w3c.github.io/aria/#search */
|
|
5
|
+
export default class SearchBar extends SvelteComponentTyped<{
|
|
6
|
+
[x: string]: any;
|
|
7
|
+
focus?: () => void;
|
|
8
|
+
class?: string;
|
|
9
|
+
value?: string;
|
|
10
|
+
}, {
|
|
11
|
+
input: Event;
|
|
12
|
+
keydown: KeyboardEvent;
|
|
13
|
+
keyup: KeyboardEvent;
|
|
14
|
+
keypress: KeyboardEvent;
|
|
15
|
+
change: Event;
|
|
16
|
+
} & {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
}, {}> {
|
|
19
|
+
get focus(): () => void;
|
|
20
|
+
/**accessor*/
|
|
21
|
+
set class(arg: string);
|
|
22
|
+
get class(): string;
|
|
23
|
+
/**accessor*/
|
|
24
|
+
set value(arg: string);
|
|
25
|
+
get value(): string;
|
|
26
|
+
}
|
|
27
|
+
export type SearchBarProps = typeof __propDef.props;
|
|
28
|
+
export type SearchBarEvents = typeof __propDef.events;
|
|
29
|
+
export type SearchBarSlots = typeof __propDef.slots;
|
|
30
|
+
import { SvelteComponentTyped } from "svelte";
|
|
31
|
+
declare const __propDef: {
|
|
32
|
+
props: {
|
|
33
|
+
[x: string]: any;
|
|
34
|
+
focus?: () => void;
|
|
35
|
+
class?: string;
|
|
36
|
+
value?: string;
|
|
37
|
+
};
|
|
38
|
+
events: {
|
|
39
|
+
input: Event;
|
|
40
|
+
keydown: KeyboardEvent;
|
|
41
|
+
keyup: KeyboardEvent;
|
|
42
|
+
keypress: KeyboardEvent;
|
|
43
|
+
change: Event;
|
|
44
|
+
} & {
|
|
45
|
+
[evt: string]: CustomEvent<any>;
|
|
46
|
+
};
|
|
47
|
+
slots: {};
|
|
48
|
+
};
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
A variant of `<RadioButton>`, looking like a normal button.
|
|
4
|
+
@see https://w3c.github.io/aria/#radio
|
|
5
|
+
@see https://w3c.github.io/aria-practices/#radiobutton
|
|
6
|
+
-->
|
|
7
|
+
<script>
|
|
8
|
+
import Button from './button.svelte';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* CSS class name on the button.
|
|
12
|
+
* @type {String}
|
|
13
|
+
*/
|
|
14
|
+
let className = '';
|
|
15
|
+
|
|
16
|
+
export { className as class };
|
|
17
|
+
|
|
18
|
+
export let selected = false;
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<Button
|
|
22
|
+
class="sui select-button {className}"
|
|
23
|
+
role="radio"
|
|
24
|
+
aria-checked={selected}
|
|
25
|
+
{...$$restProps}
|
|
26
|
+
on:click
|
|
27
|
+
>
|
|
28
|
+
<slot name="start-icon" slot="start-icon" />
|
|
29
|
+
<slot />
|
|
30
|
+
<slot name="end-icon" slot="end-icon" />
|
|
31
|
+
</Button>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SelectButtonProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SelectButtonEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SelectButtonSlots */
|
|
4
|
+
/**
|
|
5
|
+
* A variant of `<RadioButton>`, looking like a normal button.
|
|
6
|
+
* @see https://w3c.github.io/aria/#radio
|
|
7
|
+
* @see https://w3c.github.io/aria-practices/#radiobutton
|
|
8
|
+
*/
|
|
9
|
+
export default class SelectButton extends SvelteComponentTyped<{
|
|
10
|
+
[x: string]: any;
|
|
11
|
+
class?: string;
|
|
12
|
+
selected?: boolean;
|
|
13
|
+
}, {
|
|
14
|
+
click: MouseEvent;
|
|
15
|
+
} & {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
}, {
|
|
18
|
+
'start-icon': {
|
|
19
|
+
slot: string;
|
|
20
|
+
};
|
|
21
|
+
default: {};
|
|
22
|
+
'end-icon': {
|
|
23
|
+
slot: string;
|
|
24
|
+
};
|
|
25
|
+
}> {
|
|
26
|
+
}
|
|
27
|
+
export type SelectButtonProps = typeof __propDef.props;
|
|
28
|
+
export type SelectButtonEvents = typeof __propDef.events;
|
|
29
|
+
export type SelectButtonSlots = typeof __propDef.slots;
|
|
30
|
+
import { SvelteComponentTyped } from "svelte";
|
|
31
|
+
declare const __propDef: {
|
|
32
|
+
props: {
|
|
33
|
+
[x: string]: any;
|
|
34
|
+
class?: string;
|
|
35
|
+
selected?: boolean;
|
|
36
|
+
};
|
|
37
|
+
events: {
|
|
38
|
+
click: MouseEvent;
|
|
39
|
+
} & {
|
|
40
|
+
[evt: string]: CustomEvent<any>;
|
|
41
|
+
};
|
|
42
|
+
slots: {
|
|
43
|
+
'start-icon': {
|
|
44
|
+
slot: string;
|
|
45
|
+
};
|
|
46
|
+
default: {};
|
|
47
|
+
'end-icon': {
|
|
48
|
+
slot: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
@see https://w3c.github.io/aria/#separator
|
|
4
|
+
-->
|
|
5
|
+
<script>
|
|
6
|
+
export let orientation = 'horizontal';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CSS class name on the button.
|
|
10
|
+
* @type {String}
|
|
11
|
+
*/
|
|
12
|
+
let className = '';
|
|
13
|
+
|
|
14
|
+
export { className as class };
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div role="separator" class="sui separator {className}" aria-orientation={orientation} />
|
|
18
|
+
|
|
19
|
+
<style>.separator {
|
|
20
|
+
flex: none;
|
|
21
|
+
background-color: var(--secondary-border-color);
|
|
22
|
+
}
|
|
23
|
+
.separator[aria-orientation=horizontal] {
|
|
24
|
+
height: 1px;
|
|
25
|
+
}
|
|
26
|
+
.separator[aria-orientation=vertical] {
|
|
27
|
+
width: 1px;
|
|
28
|
+
}</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SeparatorProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SeparatorEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SeparatorSlots */
|
|
4
|
+
/** @see https://w3c.github.io/aria/#separator */
|
|
5
|
+
export default class Separator extends SvelteComponentTyped<{
|
|
6
|
+
class?: string;
|
|
7
|
+
orientation?: string;
|
|
8
|
+
}, {
|
|
9
|
+
[evt: string]: CustomEvent<any>;
|
|
10
|
+
}, {}> {
|
|
11
|
+
}
|
|
12
|
+
export type SeparatorProps = typeof __propDef.props;
|
|
13
|
+
export type SeparatorEvents = typeof __propDef.events;
|
|
14
|
+
export type SeparatorSlots = typeof __propDef.slots;
|
|
15
|
+
import { SvelteComponentTyped } from "svelte";
|
|
16
|
+
declare const __propDef: {
|
|
17
|
+
props: {
|
|
18
|
+
class?: string;
|
|
19
|
+
orientation?: string;
|
|
20
|
+
};
|
|
21
|
+
events: {
|
|
22
|
+
[evt: string]: CustomEvent<any>;
|
|
23
|
+
};
|
|
24
|
+
slots: {};
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
@see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range
|
|
4
|
+
@see https://w3c.github.io/aria/#slider
|
|
5
|
+
@see https://www.w3.org/WAI/ARIA/apg/patterns/slider/
|
|
6
|
+
@see https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/
|
|
7
|
+
-->
|
|
8
|
+
<script>
|
|
9
|
+
import { createEventDispatcher, onMount } from 'svelte';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* CSS class name on the button.
|
|
13
|
+
* @type {String}
|
|
14
|
+
*/
|
|
15
|
+
let className = '';
|
|
16
|
+
|
|
17
|
+
export { className as class };
|
|
18
|
+
|
|
19
|
+
export let value = 0;
|
|
20
|
+
export let sliderLabel = '';
|
|
21
|
+
export let values = undefined;
|
|
22
|
+
export let sliderLabels = [];
|
|
23
|
+
export let min = 0;
|
|
24
|
+
export let max = 100;
|
|
25
|
+
export let step = 1;
|
|
26
|
+
export let optionLabels = [];
|
|
27
|
+
|
|
28
|
+
$: multiThumb = !!values;
|
|
29
|
+
|
|
30
|
+
const dispatch = createEventDispatcher();
|
|
31
|
+
/** @type {(HTMLElement|undefined)} */
|
|
32
|
+
let base = undefined;
|
|
33
|
+
let barWidth = 0;
|
|
34
|
+
let positionList = [];
|
|
35
|
+
let valueList = [];
|
|
36
|
+
let startX = 0;
|
|
37
|
+
let startScreenX = 0;
|
|
38
|
+
const sliderPositions = [0, 0];
|
|
39
|
+
let dragging = false;
|
|
40
|
+
let targetValueIndex = 0;
|
|
41
|
+
|
|
42
|
+
const dragSlider = (diff) => {
|
|
43
|
+
if (diff >= 0 && diff <= barWidth) {
|
|
44
|
+
const fromIndex = positionList.findLastIndex((s) => s <= diff);
|
|
45
|
+
const toIndex = positionList.findIndex((s) => diff <= s);
|
|
46
|
+
|
|
47
|
+
const index =
|
|
48
|
+
Math.abs(positionList[fromIndex] - diff) < Math.abs(positionList[toIndex] - diff)
|
|
49
|
+
? fromIndex
|
|
50
|
+
: toIndex;
|
|
51
|
+
|
|
52
|
+
if (
|
|
53
|
+
sliderPositions[targetValueIndex] === positionList[index] ||
|
|
54
|
+
(multiThumb &&
|
|
55
|
+
((targetValueIndex === 0 && sliderPositions[1] <= positionList[index]) ||
|
|
56
|
+
(targetValueIndex === 1 && sliderPositions[0] >= positionList[index])))
|
|
57
|
+
) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
sliderPositions[targetValueIndex] = positionList[index];
|
|
62
|
+
|
|
63
|
+
if (multiThumb) {
|
|
64
|
+
values[targetValueIndex] = valueList[index];
|
|
65
|
+
dispatch('change', { values });
|
|
66
|
+
} else {
|
|
67
|
+
value = valueList[index];
|
|
68
|
+
dispatch('change', { value });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const onKeyDown = (event, valueIndex = 0) => {
|
|
74
|
+
const { key, shiftKey, altKey, ctrlKey, metaKey } = event;
|
|
75
|
+
|
|
76
|
+
if (shiftKey || altKey || ctrlKey || metaKey) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let index = -1;
|
|
81
|
+
|
|
82
|
+
if (['ArrowDown', 'ArrowLeft'].includes(key)) {
|
|
83
|
+
if (value > min) {
|
|
84
|
+
index = valueList.indexOf(value) - 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
event.stopPropagation();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (['ArrowUp', 'ArrowRight'].includes(key)) {
|
|
92
|
+
if (value < max) {
|
|
93
|
+
index = valueList.indexOf(value) + 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
event.stopPropagation();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (index > -1) {
|
|
101
|
+
if (
|
|
102
|
+
multiThumb &&
|
|
103
|
+
((targetValueIndex === 0 && sliderPositions[1] <= positionList[index]) ||
|
|
104
|
+
(targetValueIndex === 1 && sliderPositions[0] >= positionList[index]))
|
|
105
|
+
) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
sliderPositions[valueIndex] = positionList[index];
|
|
110
|
+
|
|
111
|
+
if (multiThumb) {
|
|
112
|
+
values[valueIndex] = valueList[index];
|
|
113
|
+
dispatch('change', { values });
|
|
114
|
+
} else {
|
|
115
|
+
value = valueList[index];
|
|
116
|
+
dispatch('change', { value });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const onMouseDown = (event, valueIndex = 0) => {
|
|
122
|
+
const { clientX, screenX } = event;
|
|
123
|
+
|
|
124
|
+
dragging = true;
|
|
125
|
+
startX = clientX - base.getBoundingClientRect().x;
|
|
126
|
+
startScreenX = screenX;
|
|
127
|
+
targetValueIndex = valueIndex;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const onMouseMove = (event) => {
|
|
131
|
+
if (dragging) {
|
|
132
|
+
dragSlider(startX + (event.screenX - startScreenX));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const onClick = (event) => {
|
|
137
|
+
if (!multiThumb && !dragging) {
|
|
138
|
+
dragSlider(event.layerX);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (dragging) {
|
|
142
|
+
dragging = false;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
onMount(() => {
|
|
147
|
+
barWidth = base.clientWidth;
|
|
148
|
+
|
|
149
|
+
const stepCount = (max - min) / step + 1;
|
|
150
|
+
const stepWidth = barWidth / (stepCount - 1);
|
|
151
|
+
|
|
152
|
+
valueList = new Array(stepCount).fill(0).map((_, index) => index * step + min, 10);
|
|
153
|
+
positionList = new Array(stepCount).fill(0).map((_, index) => index * stepWidth);
|
|
154
|
+
|
|
155
|
+
if (multiThumb) {
|
|
156
|
+
sliderPositions[0] = positionList[valueList.indexOf(values[0])];
|
|
157
|
+
sliderPositions[1] = positionList[valueList.indexOf(values[1])];
|
|
158
|
+
} else {
|
|
159
|
+
sliderPositions[0] = positionList[valueList.indexOf(value)];
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
</script>
|
|
163
|
+
|
|
164
|
+
<svelte:body
|
|
165
|
+
on:mousemove={onMouseMove}
|
|
166
|
+
on:click={() => {
|
|
167
|
+
dragging = false;
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
|
|
171
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
172
|
+
<div class="sui slider {className}" on:click|preventDefault|stopPropagation>
|
|
173
|
+
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
174
|
+
<div
|
|
175
|
+
class="base"
|
|
176
|
+
bind:this={base}
|
|
177
|
+
on:click|preventDefault|stopPropagation={(event) => {
|
|
178
|
+
onClick(event);
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
<div
|
|
182
|
+
class="bar"
|
|
183
|
+
style:left="{multiThumb ? sliderPositions[0] : 0}px"
|
|
184
|
+
style:width="{multiThumb ? sliderPositions[1] - sliderPositions[0] : sliderPositions[0]}px"
|
|
185
|
+
/>
|
|
186
|
+
<div
|
|
187
|
+
role="slider"
|
|
188
|
+
tabindex="0"
|
|
189
|
+
aria-label={multiThumb ? sliderLabels[0] || '' : sliderLabel}
|
|
190
|
+
aria-valuemin={min}
|
|
191
|
+
aria-valuemax={max}
|
|
192
|
+
aria-valuenow={value}
|
|
193
|
+
style:left="{sliderPositions[0]}px"
|
|
194
|
+
on:mousedown={(event) => {
|
|
195
|
+
onMouseDown(event, 0);
|
|
196
|
+
}}
|
|
197
|
+
on:keydown={(event) => {
|
|
198
|
+
onKeyDown(event, 0);
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
{#if multiThumb}
|
|
202
|
+
<div
|
|
203
|
+
role="slider"
|
|
204
|
+
tabindex="0"
|
|
205
|
+
aria-label={sliderLabels[1] || ''}
|
|
206
|
+
aria-valuemin={min}
|
|
207
|
+
aria-valuemax={max}
|
|
208
|
+
aria-valuenow={value}
|
|
209
|
+
style:left="{sliderPositions[1]}px"
|
|
210
|
+
on:mousedown={(event) => {
|
|
211
|
+
onMouseDown(event, 1);
|
|
212
|
+
}}
|
|
213
|
+
on:keydown={(event) => {
|
|
214
|
+
onKeyDown(event, 1);
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
{/if}
|
|
218
|
+
{#if optionLabels.length}
|
|
219
|
+
{#each optionLabels as label, index}
|
|
220
|
+
<span
|
|
221
|
+
class="label"
|
|
222
|
+
role="presentation"
|
|
223
|
+
style:left="{(barWidth / (optionLabels.length - 1)) * index}px"
|
|
224
|
+
>
|
|
225
|
+
{label}
|
|
226
|
+
</span>
|
|
227
|
+
{/each}
|
|
228
|
+
{/if}
|
|
229
|
+
</div>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<style>.slider {
|
|
233
|
+
position: relative;
|
|
234
|
+
display: inline-block;
|
|
235
|
+
padding: 16px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.base {
|
|
239
|
+
position: relative;
|
|
240
|
+
width: var(--slider-base-width, 200px);
|
|
241
|
+
height: 8px;
|
|
242
|
+
border-radius: 8px;
|
|
243
|
+
background-color: var(--control-border-color);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.bar {
|
|
247
|
+
position: absolute;
|
|
248
|
+
top: 0;
|
|
249
|
+
height: 8px;
|
|
250
|
+
border-radius: 8px;
|
|
251
|
+
background-color: var(--primary-accent-color-lighter);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
[role=slider] {
|
|
255
|
+
position: absolute;
|
|
256
|
+
top: 0;
|
|
257
|
+
border: 2px solid var(--primary-accent-color-lighter);
|
|
258
|
+
border-radius: 8px;
|
|
259
|
+
width: 16px;
|
|
260
|
+
height: 16px;
|
|
261
|
+
background-color: var(--primary-accent-color-foreground);
|
|
262
|
+
cursor: pointer;
|
|
263
|
+
transform: translate(-8px, -4px);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.label {
|
|
267
|
+
position: absolute;
|
|
268
|
+
top: 12px;
|
|
269
|
+
transform: translateX(-50%);
|
|
270
|
+
font-size: var(--font-size--x-small);
|
|
271
|
+
}</style>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SliderProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SliderEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SliderSlots */
|
|
4
|
+
/**
|
|
5
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range
|
|
6
|
+
* @see https://w3c.github.io/aria/#slider
|
|
7
|
+
* @see https://www.w3.org/WAI/ARIA/apg/patterns/slider/
|
|
8
|
+
* @see https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/
|
|
9
|
+
*/
|
|
10
|
+
export default class Slider extends SvelteComponentTyped<{
|
|
11
|
+
class?: string;
|
|
12
|
+
value?: number;
|
|
13
|
+
min?: number;
|
|
14
|
+
max?: number;
|
|
15
|
+
step?: number;
|
|
16
|
+
sliderLabel?: string;
|
|
17
|
+
values?: any;
|
|
18
|
+
sliderLabels?: any[];
|
|
19
|
+
optionLabels?: any[];
|
|
20
|
+
}, {
|
|
21
|
+
click: MouseEvent;
|
|
22
|
+
change: CustomEvent<any>;
|
|
23
|
+
} & {
|
|
24
|
+
[evt: string]: CustomEvent<any>;
|
|
25
|
+
}, {}> {
|
|
26
|
+
}
|
|
27
|
+
export type SliderProps = typeof __propDef.props;
|
|
28
|
+
export type SliderEvents = typeof __propDef.events;
|
|
29
|
+
export type SliderSlots = typeof __propDef.slots;
|
|
30
|
+
import { SvelteComponentTyped } from "svelte";
|
|
31
|
+
declare const __propDef: {
|
|
32
|
+
props: {
|
|
33
|
+
class?: string;
|
|
34
|
+
value?: number;
|
|
35
|
+
min?: number;
|
|
36
|
+
max?: number;
|
|
37
|
+
step?: number;
|
|
38
|
+
sliderLabel?: string;
|
|
39
|
+
values?: any;
|
|
40
|
+
sliderLabels?: any[];
|
|
41
|
+
optionLabels?: any[];
|
|
42
|
+
};
|
|
43
|
+
events: {
|
|
44
|
+
click: MouseEvent;
|
|
45
|
+
change: CustomEvent<any>;
|
|
46
|
+
} & {
|
|
47
|
+
[evt: string]: CustomEvent<any>;
|
|
48
|
+
};
|
|
49
|
+
slots: {};
|
|
50
|
+
};
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
/**
|
|
3
|
+
* CSS class name on the button.
|
|
4
|
+
* @type {String}
|
|
5
|
+
*/
|
|
6
|
+
let className = '';
|
|
7
|
+
|
|
8
|
+
export { className as class };
|
|
9
|
+
|
|
10
|
+
/** @type {Boolean} */
|
|
11
|
+
export let flex = false;
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="sui spacer {className}" class:flex />
|
|
15
|
+
|
|
16
|
+
<style>.spacer.flex {
|
|
17
|
+
flex: auto;
|
|
18
|
+
}
|
|
19
|
+
.spacer:not(.flex) {
|
|
20
|
+
width: 8px;
|
|
21
|
+
height: 8px;
|
|
22
|
+
}</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} SpacerProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} SpacerEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} SpacerSlots */
|
|
4
|
+
export default class Spacer extends SvelteComponentTyped<{
|
|
5
|
+
class?: string;
|
|
6
|
+
flex?: boolean;
|
|
7
|
+
}, {
|
|
8
|
+
[evt: string]: CustomEvent<any>;
|
|
9
|
+
}, {}> {
|
|
10
|
+
}
|
|
11
|
+
export type SpacerProps = typeof __propDef.props;
|
|
12
|
+
export type SpacerEvents = typeof __propDef.events;
|
|
13
|
+
export type SpacerSlots = typeof __propDef.slots;
|
|
14
|
+
import { SvelteComponentTyped } from "svelte";
|
|
15
|
+
declare const __propDef: {
|
|
16
|
+
props: {
|
|
17
|
+
class?: string;
|
|
18
|
+
flex?: boolean;
|
|
19
|
+
};
|
|
20
|
+
events: {
|
|
21
|
+
[evt: string]: CustomEvent<any>;
|
|
22
|
+
};
|
|
23
|
+
slots: {};
|
|
24
|
+
};
|
|
25
|
+
export {};
|