@geoffcox/sterling-svelte 2.0.1 → 2.0.3
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/README.md +1 -1
- package/dist/Button.svelte +18 -14
- package/dist/Button.svelte.d.ts +0 -1
- package/dist/Callout.svelte +162 -96
- package/dist/Callout.svelte.d.ts +1 -2
- package/dist/Checkbox.svelte +34 -15
- package/dist/Checkbox.svelte.d.ts +0 -1
- package/dist/Dialog.svelte +121 -71
- package/dist/Dialog.svelte.d.ts +1 -1
- package/dist/Dropdown.svelte +106 -56
- package/dist/Dropdown.svelte.d.ts +8 -3
- package/dist/Input.svelte +54 -29
- package/dist/Input.svelte.d.ts +1 -2
- package/dist/Label.svelte +99 -55
- package/dist/Label.svelte.d.ts +4 -4
- package/dist/Link.svelte +20 -14
- package/dist/Link.svelte.d.ts +0 -1
- package/dist/List.svelte +181 -126
- package/dist/List.svelte.d.ts +0 -1
- package/dist/ListItem.svelte +36 -21
- package/dist/ListItem.svelte.d.ts +0 -1
- package/dist/Menu.svelte +67 -45
- package/dist/Menu.svelte.d.ts +0 -1
- package/dist/MenuBar.svelte +96 -65
- package/dist/MenuBar.svelte.d.ts +0 -1
- package/dist/MenuButton.svelte +102 -62
- package/dist/MenuButton.svelte.d.ts +1 -1
- package/dist/MenuItem.svelte +332 -243
- package/dist/MenuItem.svelte.d.ts +3 -3
- package/dist/MenuSeparator.svelte +7 -7
- package/dist/MenuSeparator.svelte.d.ts +0 -1
- package/dist/Pagination.svelte +267 -0
- package/dist/Pagination.svelte.d.ts +4 -0
- package/dist/Pagination.types.d.ts +24 -0
- package/dist/Pagination.types.js +1 -0
- package/dist/Popover.svelte +114 -60
- package/dist/Popover.svelte.d.ts +1 -2
- package/dist/Portal.types.d.ts +1 -4
- package/dist/Progress.svelte +40 -15
- package/dist/Progress.svelte.d.ts +0 -1
- package/dist/Radio.svelte +37 -25
- package/dist/Radio.svelte.d.ts +0 -1
- package/dist/Select.svelte +191 -125
- package/dist/Select.svelte.d.ts +8 -2
- package/dist/Slider.svelte +120 -71
- package/dist/Slider.svelte.d.ts +0 -1
- package/dist/Switch.svelte +51 -20
- package/dist/Switch.svelte.d.ts +1 -1
- package/dist/Tab.svelte +39 -24
- package/dist/Tab.svelte.d.ts +0 -1
- package/dist/TabList.svelte +176 -125
- package/dist/TabList.svelte.d.ts +0 -1
- package/dist/TextArea.svelte +83 -41
- package/dist/TextArea.svelte.d.ts +2 -3
- package/dist/Tooltip.svelte +68 -36
- package/dist/Tree.svelte +52 -24
- package/dist/Tree.svelte.d.ts +0 -1
- package/dist/TreeChevron.svelte +24 -12
- package/dist/TreeChevron.svelte.d.ts +0 -1
- package/dist/TreeItem.svelte +292 -225
- package/dist/TreeItem.svelte.d.ts +1 -1
- package/dist/actions/extraClass.d.ts +1 -0
- package/dist/actions/extraClass.js +1 -0
- package/dist/idGenerator.d.ts +1 -0
- package/dist/idGenerator.js +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/mediaQueries/prefersColorSchemeDark.d.ts +0 -1
- package/dist/mediaQueries/prefersReducedMotion.d.ts +0 -1
- package/dist/mediaQueries/usingKeyboard.d.ts +0 -1
- package/package.json +21 -22
package/dist/Dialog.svelte
CHANGED
|
@@ -1,65 +1,109 @@
|
|
|
1
1
|
<svelte:options runes={true} />
|
|
2
2
|
|
|
3
|
-
<script lang="ts">
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import { writable } from 'svelte/store';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import { onMount, setContext, tick, type Snippet } from 'svelte';
|
|
5
|
+
import type { FormEventHandler, HTMLDialogAttributes } from 'svelte/elements';
|
|
6
|
+
import { writable } from 'svelte/store';
|
|
7
|
+
import Button from './Button.svelte';
|
|
8
|
+
import { STERLING_PORTAL_CONTEXT_ID } from './Portal.constants';
|
|
9
|
+
import type { PortalContext } from './Portal.types';
|
|
10
|
+
|
|
11
|
+
const dialogFadeDuration = 250;
|
|
12
|
+
|
|
13
|
+
type Props = HTMLDialogAttributes & {
|
|
14
|
+
backdropCloses?: boolean | null | undefined;
|
|
15
|
+
body?: Snippet;
|
|
16
|
+
content?: Snippet;
|
|
17
|
+
footer?: Snippet;
|
|
18
|
+
header?: Snippet;
|
|
19
|
+
returnValue?: string;
|
|
20
|
+
headerTitle?: string | Snippet;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
let {
|
|
24
|
+
backdropCloses = false,
|
|
25
|
+
open = $bindable(false),
|
|
26
|
+
body,
|
|
27
|
+
class: _class,
|
|
28
|
+
content,
|
|
29
|
+
footer,
|
|
30
|
+
header,
|
|
31
|
+
returnValue = $bindable(''),
|
|
32
|
+
headerTitle,
|
|
33
|
+
...rest
|
|
34
|
+
}: Props = $props();
|
|
35
|
+
|
|
36
|
+
let dialogRef: HTMLDialogElement;
|
|
37
|
+
let contentRef: HTMLDivElement;
|
|
38
|
+
let formRef: HTMLFormElement;
|
|
39
|
+
|
|
40
|
+
// svelte-ignore non_reactive_update
|
|
41
|
+
let closing = false;
|
|
42
|
+
|
|
43
|
+
let portalHost: HTMLElement | undefined = $state(undefined);
|
|
44
|
+
|
|
45
|
+
let portalContext: PortalContext = {
|
|
46
|
+
get portalHost() {
|
|
47
|
+
return portalHost;
|
|
48
|
+
},
|
|
49
|
+
set portalHost(host: HTMLElement | undefined) {
|
|
50
|
+
portalHost = host;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ----- Context ----- //
|
|
55
|
+
setContext<PortalContext>(STERLING_PORTAL_CONTEXT_ID, portalContext);
|
|
56
|
+
|
|
57
|
+
// ----- Event Handlers ----- //
|
|
58
|
+
|
|
59
|
+
const onDocumentClick = (event: MouseEvent) => {
|
|
19
60
|
// as tracking clicks outside the dialog is only active while the dialog is open
|
|
20
61
|
// the clickOutside action is not used and reimplemented here.
|
|
21
|
-
const targetNode = event?.target;
|
|
62
|
+
const targetNode = event?.target as Node;
|
|
22
63
|
// the content must be used as the container because dialog::backdrop is considered
|
|
23
64
|
// part of the HTMLDialogElement
|
|
24
65
|
if (targetNode && !contentRef?.contains(targetNode) && backdropCloses) {
|
|
25
|
-
|
|
66
|
+
open = false;
|
|
26
67
|
}
|
|
27
|
-
};
|
|
28
|
-
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const showDialog = () => {
|
|
29
71
|
if (dialogRef?.open === false) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
72
|
+
// when open, track clicks outside the dialog (use capture = true)
|
|
73
|
+
document.addEventListener('click', onDocumentClick, true);
|
|
74
|
+
returnValue = '';
|
|
75
|
+
dialogRef.showModal();
|
|
34
76
|
}
|
|
35
77
|
open = true;
|
|
36
|
-
};
|
|
37
|
-
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const closeDialog = async () => {
|
|
38
81
|
if (dialogRef?.open === true) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
closing = false;
|
|
48
|
-
}, dialogFadeDuration);
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
82
|
+
// when closed, stop tracking clicks outside the dialog
|
|
83
|
+
document.removeEventListener('click', onDocumentClick);
|
|
84
|
+
|
|
85
|
+
// to allow time for the CSS transition animation, closing the dialog is delayed
|
|
86
|
+
closing = true;
|
|
87
|
+
await tick();
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
dialogRef.close(returnValue);
|
|
51
90
|
open = false;
|
|
91
|
+
closing = false;
|
|
92
|
+
}, dialogFadeDuration);
|
|
93
|
+
} else {
|
|
94
|
+
open = false;
|
|
52
95
|
}
|
|
53
|
-
};
|
|
54
|
-
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const updateDialog = (open: boolean | null | undefined) => {
|
|
55
99
|
if (open) {
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
closeDialog();
|
|
100
|
+
showDialog();
|
|
101
|
+
} else {
|
|
102
|
+
closeDialog();
|
|
60
103
|
}
|
|
61
|
-
};
|
|
62
|
-
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const onCancel = (event: Event) => {
|
|
63
107
|
// Cancelling a dialog instantly hides the dialog.
|
|
64
108
|
// To allow animation with closeDialog, this event is canceled.
|
|
65
109
|
event.preventDefault();
|
|
@@ -67,48 +111,54 @@ const onCancel = (event) => {
|
|
|
67
111
|
returnValue = '';
|
|
68
112
|
closeDialog();
|
|
69
113
|
return false;
|
|
70
|
-
};
|
|
71
|
-
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const onSubmit: FormEventHandler<HTMLFormElement> = (event) => {
|
|
72
117
|
// Submitting a form instantly hides the dialog.
|
|
73
118
|
// The dialog.close event is not cancellable, but form.submit is.
|
|
74
119
|
// To allow animation with closeDialog, this event is canceled.
|
|
75
120
|
// The form is resubmitted after the dialog closes to ensure the form is in the correct state.
|
|
76
|
-
const anyEvent = event;
|
|
121
|
+
const anyEvent = event as unknown as any;
|
|
77
122
|
if (anyEvent?.submitter.type === 'submit') {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
event.preventDefault();
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
123
|
+
if (dialogRef.open) {
|
|
124
|
+
const eventSubmitter = anyEvent?.submitter;
|
|
125
|
+
returnValue = eventSubmitter?.value ?? '';
|
|
126
|
+
closeDialog();
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
formRef.requestSubmit(eventSubmitter);
|
|
129
|
+
}, dialogFadeDuration);
|
|
90
130
|
event.preventDefault();
|
|
91
131
|
return false;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
return false;
|
|
92
136
|
}
|
|
93
|
-
};
|
|
94
|
-
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
$effect(() => {
|
|
95
140
|
updateDialog(open);
|
|
96
|
-
});
|
|
97
|
-
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
onMount(() => {
|
|
98
144
|
updateDialog(open);
|
|
145
|
+
|
|
99
146
|
// Use the dialog for any element portals
|
|
100
|
-
|
|
147
|
+
portalContext.portalHost = dialogRef;
|
|
148
|
+
|
|
101
149
|
dialogRef.addEventListener('cancel', onCancel);
|
|
150
|
+
|
|
102
151
|
return () => {
|
|
103
|
-
|
|
104
|
-
|
|
152
|
+
dialogRef?.removeEventListener('cancel', onCancel);
|
|
153
|
+
|
|
154
|
+
portalContext.portalHost = undefined;
|
|
105
155
|
};
|
|
106
|
-
});
|
|
156
|
+
});
|
|
107
157
|
</script>
|
|
108
158
|
|
|
109
159
|
<dialog
|
|
110
160
|
bind:this={dialogRef}
|
|
111
|
-
class={
|
|
161
|
+
class={['sterling-dialog', _class]}
|
|
112
162
|
class:open
|
|
113
163
|
class:closing
|
|
114
164
|
{...rest}
|
|
@@ -132,7 +182,7 @@ onMount(() => {
|
|
|
132
182
|
{/if}
|
|
133
183
|
</div>
|
|
134
184
|
<div class="close">
|
|
135
|
-
<Button class=
|
|
185
|
+
<Button class="circular tool" onclick={() => closeDialog()}>
|
|
136
186
|
<div class="close-x"></div>
|
|
137
187
|
</Button>
|
|
138
188
|
</div>
|
package/dist/Dialog.svelte.d.ts
CHANGED
package/dist/Dropdown.svelte
CHANGED
|
@@ -1,73 +1,125 @@
|
|
|
1
1
|
<svelte:options runes={true} />
|
|
2
2
|
|
|
3
|
-
<script lang="ts">
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { usingKeyboard } from './mediaQueries/usingKeyboard';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import { type Snippet } from 'svelte';
|
|
5
|
+
import type { HTMLAttributes, KeyboardEventHandler, MouseEventHandler } from 'svelte/elements';
|
|
6
|
+
import { slide, type SlideParams, type TransitionConfig } from 'svelte/transition';
|
|
7
|
+
import { clickOutside } from './actions/clickOutside';
|
|
8
|
+
import { prefersReducedMotion } from './mediaQueries/prefersReducedMotion';
|
|
9
|
+
import { usingKeyboard } from './mediaQueries/usingKeyboard';
|
|
10
|
+
import Popover from './Popover.svelte';
|
|
11
|
+
|
|
12
|
+
const uuid = $props.id();
|
|
13
|
+
|
|
14
|
+
const popoverId = `Dropdown-Popover-${uuid}`;
|
|
15
|
+
|
|
16
|
+
type DeprecatedProps = {
|
|
17
|
+
/** @deprecated Use icon instead. */
|
|
18
|
+
button?: Snippet;
|
|
19
|
+
/** @deprecated Use icon instead. */
|
|
20
|
+
buttonIcon?: Snippet;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type Props = HTMLAttributes<HTMLDivElement> &
|
|
24
|
+
DeprecatedProps & {
|
|
25
|
+
disabled?: boolean | null | undefined;
|
|
26
|
+
open?: boolean | null | undefined;
|
|
27
|
+
stayOpenOnClickAway?: boolean | null | undefined;
|
|
28
|
+
onOpen?: (open: boolean | null | undefined) => void;
|
|
29
|
+
icon?: Snippet;
|
|
30
|
+
value?: string | Snippet;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
let {
|
|
34
|
+
button,
|
|
35
|
+
buttonIcon,
|
|
36
|
+
class: _class,
|
|
37
|
+
children,
|
|
38
|
+
disabled = false,
|
|
39
|
+
icon,
|
|
40
|
+
open = $bindable(false),
|
|
41
|
+
onOpen,
|
|
42
|
+
stayOpenOnClickAway = false,
|
|
43
|
+
value,
|
|
44
|
+
...rest
|
|
45
|
+
}: Props = $props();
|
|
46
|
+
|
|
47
|
+
icon = icon || buttonIcon || button;
|
|
48
|
+
|
|
49
|
+
// svelte-ignore non_reactive_update
|
|
50
|
+
let dropdownRef: HTMLDivElement | undefined = $state(undefined);
|
|
51
|
+
|
|
52
|
+
// svelte-ignore non_reactive_update
|
|
53
|
+
let popupContentRef: HTMLDivElement | undefined = $state(undefined);
|
|
54
|
+
|
|
55
|
+
// ----- Reactions ----- //
|
|
56
|
+
|
|
57
|
+
$effect(() => {
|
|
18
58
|
onOpen?.(open);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ----- Methods ----- //
|
|
62
|
+
|
|
63
|
+
export const click = () => {
|
|
22
64
|
dropdownRef?.click();
|
|
23
|
-
};
|
|
24
|
-
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const blur = () => {
|
|
25
68
|
dropdownRef?.blur();
|
|
26
|
-
};
|
|
27
|
-
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const focus = (options?: FocusOptions) => {
|
|
28
72
|
dropdownRef?.focus(options);
|
|
29
|
-
};
|
|
30
|
-
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const onClick: MouseEventHandler<HTMLDivElement> = (event) => {
|
|
31
76
|
if (!disabled) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
77
|
+
open = !open;
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
event.stopPropagation();
|
|
35
80
|
}
|
|
81
|
+
|
|
36
82
|
rest.onclick?.(event);
|
|
37
|
-
};
|
|
38
|
-
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const onKeydown: KeyboardEventHandler<HTMLDivElement> = (event) => {
|
|
39
86
|
if (!event.altKey && !event.ctrlKey && !event.shiftKey) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
87
|
+
switch (event.key) {
|
|
88
|
+
case ' ':
|
|
89
|
+
open = !open;
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
case 'Escape':
|
|
93
|
+
open = false;
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
}
|
|
50
97
|
}
|
|
98
|
+
|
|
51
99
|
rest.onkeydown?.(event);
|
|
52
|
-
};
|
|
53
|
-
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const onClickOutside = (event: MouseEvent) => {
|
|
54
103
|
if (!stayOpenOnClickAway) {
|
|
55
|
-
|
|
104
|
+
open = false;
|
|
56
105
|
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// ----- Animation ----- //
|
|
109
|
+
|
|
110
|
+
const slideNoOp = (node: Element, params?: SlideParams): TransitionConfig => {
|
|
60
111
|
return { delay: 0, duration: 0 };
|
|
61
|
-
};
|
|
62
|
-
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
let slideMotion = $derived(!$prefersReducedMotion ? slide : slideNoOp);
|
|
63
115
|
</script>
|
|
64
116
|
|
|
65
117
|
<div
|
|
66
118
|
bind:this={dropdownRef}
|
|
67
|
-
aria-controls={
|
|
119
|
+
aria-controls={popoverId}
|
|
68
120
|
aria-haspopup={true}
|
|
69
121
|
aria-expanded={open}
|
|
70
|
-
class={
|
|
122
|
+
class={['sterling-dropdown', _class]}
|
|
71
123
|
class:disabled
|
|
72
124
|
class:open
|
|
73
125
|
class:using-keyboard={$usingKeyboard}
|
|
@@ -87,19 +139,17 @@ let slideMotion = $derived(!$prefersReducedMotion ? slide : slideNoOp);
|
|
|
87
139
|
{/if}
|
|
88
140
|
{/if}
|
|
89
141
|
</div>
|
|
90
|
-
<div class="button">
|
|
91
|
-
{#if
|
|
92
|
-
{@render
|
|
93
|
-
{:else if buttonIcon}
|
|
94
|
-
{@render buttonIcon()}
|
|
142
|
+
<div class="button icon">
|
|
143
|
+
{#if icon}
|
|
144
|
+
{@render icon()}
|
|
95
145
|
{:else}
|
|
96
146
|
<div class="chevron"></div>
|
|
97
147
|
{/if}
|
|
98
148
|
</div>
|
|
99
149
|
|
|
100
|
-
<Popover reference={dropdownRef} open={!disabled && open} placement="bottom-start">
|
|
150
|
+
<Popover id={popoverId} reference={dropdownRef} open={!disabled && open} placement="bottom-start">
|
|
101
151
|
<div
|
|
102
|
-
class={
|
|
152
|
+
class={['sterling-dropdown-popup-content', 'sterling-dropdown-content', _class]}
|
|
103
153
|
transition:slideMotion|global={{ duration: 200 }}
|
|
104
154
|
bind:this={popupContentRef}
|
|
105
155
|
>
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { type Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
type
|
|
3
|
+
type DeprecatedProps = {
|
|
4
|
+
/** @deprecated Use icon instead. */
|
|
5
|
+
button?: Snippet;
|
|
6
|
+
/** @deprecated Use icon instead. */
|
|
7
|
+
buttonIcon?: Snippet;
|
|
8
|
+
};
|
|
9
|
+
type Props = HTMLAttributes<HTMLDivElement> & DeprecatedProps & {
|
|
4
10
|
disabled?: boolean | null | undefined;
|
|
5
11
|
open?: boolean | null | undefined;
|
|
6
12
|
stayOpenOnClickAway?: boolean | null | undefined;
|
|
7
13
|
onOpen?: (open: boolean | null | undefined) => void;
|
|
8
|
-
|
|
9
|
-
buttonIcon?: Snippet;
|
|
14
|
+
icon?: Snippet;
|
|
10
15
|
value?: string | Snippet;
|
|
11
16
|
};
|
|
12
17
|
declare const Dropdown: import("svelte").Component<Props, {
|
package/dist/Input.svelte
CHANGED
|
@@ -1,49 +1,74 @@
|
|
|
1
1
|
<svelte:options runes={true} />
|
|
2
2
|
|
|
3
|
-
<script lang="ts">
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
$
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
5
|
+
import { usingKeyboard } from './mediaQueries/usingKeyboard';
|
|
6
|
+
|
|
7
|
+
const uuid = $props.id();
|
|
8
|
+
|
|
9
|
+
type Props = HTMLInputAttributes;
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
id,
|
|
13
|
+
children,
|
|
14
|
+
class: _class,
|
|
15
|
+
disabled = false,
|
|
16
|
+
value = $bindable(undefined),
|
|
17
|
+
...rest
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
|
|
20
|
+
let inputRef: HTMLInputElement;
|
|
21
|
+
|
|
22
|
+
$effect(() => {
|
|
8
23
|
if (children && id === undefined) {
|
|
9
|
-
|
|
24
|
+
id = `Input-${uuid}`;
|
|
10
25
|
}
|
|
11
|
-
});
|
|
12
|
-
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const blur = () => {
|
|
13
29
|
inputRef?.blur();
|
|
14
|
-
};
|
|
15
|
-
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const click = () => {
|
|
16
33
|
inputRef?.click();
|
|
17
|
-
};
|
|
18
|
-
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const focus = (options?: FocusOptions) => {
|
|
19
37
|
inputRef?.focus();
|
|
20
|
-
};
|
|
21
|
-
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const select = () => {
|
|
22
41
|
inputRef?.select();
|
|
23
|
-
};
|
|
24
|
-
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const setSelectionRange = (
|
|
45
|
+
start: number | null,
|
|
46
|
+
end: number | null,
|
|
47
|
+
direction?: 'forward' | 'backward' | 'none'
|
|
48
|
+
) => {
|
|
25
49
|
inputRef?.setSelectionRange(start, end, direction);
|
|
26
|
-
};
|
|
27
|
-
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const setRangeText = (
|
|
53
|
+
replacement: string,
|
|
54
|
+
start?: number,
|
|
55
|
+
end?: number,
|
|
56
|
+
selectionMode?: SelectionMode
|
|
57
|
+
) => {
|
|
28
58
|
if (start && end) {
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
inputRef?.setRangeText(replacement);
|
|
59
|
+
inputRef?.setRangeText(replacement, start, end, selectionMode);
|
|
60
|
+
} else {
|
|
61
|
+
inputRef?.setRangeText(replacement);
|
|
33
62
|
}
|
|
34
|
-
};
|
|
63
|
+
};
|
|
35
64
|
</script>
|
|
36
65
|
|
|
37
66
|
{#if children}
|
|
38
|
-
<label class={['sterling-input-label', _class]
|
|
67
|
+
<label class={['sterling-input-label', _class]} class:disabled for={id}>
|
|
39
68
|
{@render children()}
|
|
40
69
|
</label>
|
|
41
70
|
{/if}
|
|
42
|
-
<div
|
|
43
|
-
class={['sterling-input', _class].filter(Boolean).join(' ')}
|
|
44
|
-
class:disabled
|
|
45
|
-
class:using-keyboard={$usingKeyboard}
|
|
46
|
-
>
|
|
71
|
+
<div class={['sterling-input', _class]} class:disabled class:using-keyboard={$usingKeyboard}>
|
|
47
72
|
<input
|
|
48
73
|
bind:this={inputRef}
|
|
49
74
|
class:using-keyboard={$usingKeyboard}
|
package/dist/Input.svelte.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
1
|
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
3
2
|
declare const Input: import("svelte").Component<HTMLInputAttributes, {
|
|
4
3
|
blur: () => void;
|
|
5
4
|
click: () => void;
|
|
6
5
|
focus: (options?: FocusOptions) => void;
|
|
7
6
|
select: () => void;
|
|
8
|
-
setSelectionRange: (start: number | null, end: number | null, direction?:
|
|
7
|
+
setSelectionRange: (start: number | null, end: number | null, direction?: "forward" | "backward" | "none") => void;
|
|
9
8
|
setRangeText: (replacement: string, start?: number, end?: number, selectionMode?: SelectionMode) => void;
|
|
10
9
|
}, "value">;
|
|
11
10
|
type Input = ReturnType<typeof Input>;
|