@sveltia/ui 0.7.4 → 0.8.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/package/components/alert/alert.svelte +4 -4
- package/package/components/alert/alert.svelte.d.ts +2 -2
- package/package/components/button/button.svelte +13 -3
- package/package/components/button/button.svelte.d.ts +11 -4
- package/package/components/button/select-button-group.svelte +12 -8
- package/package/components/button/select-button.svelte +5 -4
- package/package/components/button/select-button.svelte.d.ts +2 -0
- package/package/components/calendar/calendar.svelte +20 -14
- package/package/components/checkbox/checkbox-group.svelte +6 -5
- package/package/components/checkbox/checkbox.svelte +16 -9
- package/package/components/checkbox/checkbox.svelte.d.ts +2 -2
- package/package/components/dialog/alert-dialog.svelte +50 -0
- package/package/components/dialog/alert-dialog.svelte.d.ts +55 -0
- package/package/components/dialog/confirmation-dialog.svelte +55 -0
- package/package/components/dialog/confirmation-dialog.svelte.d.ts +57 -0
- package/package/components/dialog/dialog.svelte +164 -220
- package/package/components/dialog/dialog.svelte.d.ts +20 -12
- package/package/components/dialog/prompt-dialog.svelte +78 -0
- package/package/components/dialog/prompt-dialog.svelte.d.ts +72 -0
- package/package/components/disclosure/disclosure.svelte +3 -3
- package/package/components/divider/divider.svelte +1 -1
- package/package/components/divider/spacer.svelte +1 -12
- package/package/components/divider/spacer.svelte.d.ts +0 -2
- package/package/components/drawer/drawer.svelte +118 -208
- package/package/components/drawer/drawer.svelte.d.ts +12 -8
- package/package/components/grid/grid-body.svelte +51 -0
- package/package/components/grid/grid-body.svelte.d.ts +36 -0
- package/package/components/grid/grid-cell.svelte +22 -0
- package/package/components/grid/grid-cell.svelte.d.ts +34 -0
- package/package/components/grid/grid-col-header.svelte +22 -0
- package/package/components/grid/grid-col-header.svelte.d.ts +34 -0
- package/package/components/grid/grid-foot.svelte +27 -0
- package/package/components/grid/grid-foot.svelte.d.ts +34 -0
- package/package/components/grid/grid-head.svelte +27 -0
- package/package/components/grid/grid-head.svelte.d.ts +34 -0
- package/package/components/grid/grid-row-header.svelte +23 -0
- package/package/components/grid/grid-row-header.svelte.d.ts +34 -0
- package/package/components/grid/grid-row.svelte +37 -0
- package/package/components/grid/grid-row.svelte.d.ts +44 -0
- package/package/components/grid/grid.svelte +52 -0
- package/package/components/grid/grid.svelte.d.ts +42 -0
- package/package/components/icon/icon.svelte +6 -7
- package/package/components/icon/icon.svelte.d.ts +0 -2
- package/package/components/listbox/listbox.svelte +6 -6
- package/package/components/listbox/option-group.svelte +6 -5
- package/package/components/listbox/option.svelte +7 -28
- package/package/components/listbox/option.svelte.d.ts +2 -0
- package/package/components/menu/menu-button.svelte +26 -16
- package/package/components/menu/menu-button.svelte.d.ts +2 -2
- package/package/components/menu/menu-item-checkbox.svelte +5 -4
- package/package/components/menu/menu-item-checkbox.svelte.d.ts +2 -0
- package/package/components/menu/menu-item-group.svelte +4 -3
- package/package/components/menu/menu-item-radio.svelte +5 -4
- package/package/components/menu/menu-item-radio.svelte.d.ts +2 -0
- package/package/components/menu/menu-item.svelte +7 -5
- package/package/components/menu/menu-item.svelte.d.ts +4 -2
- package/package/components/menu/menu.svelte +1 -1
- package/package/components/radio/radio-group.svelte +8 -8
- package/package/components/radio/radio-group.svelte.d.ts +2 -2
- package/package/components/radio/radio.svelte +5 -2
- package/package/components/radio/radio.svelte.d.ts +2 -0
- package/package/components/select/combobox.svelte +55 -35
- package/package/components/select/combobox.svelte.d.ts +3 -2
- package/package/components/select/select.svelte +10 -9
- package/package/components/select/select.svelte.d.ts +4 -3
- package/package/components/slider/slider.svelte +15 -7
- package/package/components/switch/switch.svelte +9 -6
- package/package/components/switch/switch.svelte.d.ts +2 -2
- package/package/components/table/table-body.svelte +31 -3
- package/package/components/table/table-body.svelte.d.ts +2 -0
- package/package/components/table/table-cell.svelte +3 -4
- package/package/components/table/table-cell.svelte.d.ts +1 -1
- package/package/components/table/table-col-header.svelte +1 -2
- package/package/components/table/table-foot.svelte +7 -3
- package/package/components/table/table-head.svelte +7 -3
- package/package/components/table/table-row-header.svelte +1 -2
- package/package/components/table/table-row.svelte +1 -14
- package/package/components/table/table-row.svelte.d.ts +0 -8
- package/package/components/table/table.svelte +5 -17
- package/package/components/table/table.svelte.d.ts +1 -7
- package/package/components/tabs/tab-list.svelte +7 -5
- package/package/components/tabs/tab-panel.svelte +1 -1
- package/package/components/tabs/tab.svelte +2 -1
- package/package/components/tabs/tab.svelte.d.ts +2 -0
- package/package/components/text-field/markdown-editor.svelte +36 -9
- package/package/components/text-field/markdown-editor.svelte.d.ts +2 -0
- package/package/components/text-field/number-input.svelte +107 -43
- package/package/components/text-field/number-input.svelte.d.ts +2 -0
- package/package/components/text-field/password-input.svelte +43 -12
- package/package/components/text-field/password-input.svelte.d.ts +2 -0
- package/package/components/text-field/search-bar.svelte +43 -13
- package/package/components/text-field/search-bar.svelte.d.ts +5 -0
- package/package/components/text-field/text-area.svelte +26 -6
- package/package/components/text-field/text-area.svelte.d.ts +2 -0
- package/package/components/text-field/text-input.svelte +37 -7
- package/package/components/text-field/text-input.svelte.d.ts +14 -4
- package/package/components/toast/toast.svelte +6 -16
- package/package/components/toast/toast.svelte.d.ts +2 -2
- package/package/components/toolbar/toolbar.svelte +3 -4
- package/package/components/util/app-shell.svelte +34 -29
- package/package/components/util/group.svelte +2 -2
- package/package/components/util/modal.svelte +220 -0
- package/package/components/util/modal.svelte.d.ts +83 -0
- package/package/components/util/popup.svelte +80 -121
- package/package/components/util/popup.svelte.d.ts +22 -13
- package/package/components/util/portal.svelte +1 -1
- package/package/index.d.ts +12 -0
- package/package/index.js +12 -0
- package/package/locales/en.d.ts +1 -0
- package/package/locales/en.js +1 -0
- package/package/locales/ja.d.ts +1 -0
- package/package/locales/ja.js +1 -0
- package/package/services/group.js +67 -13
- package/package/services/popup.d.ts +5 -1
- package/package/services/popup.js +22 -19
- package/package/styles/core.scss +13 -26
- package/package/styles/variables.scss +14 -2
- package/package.json +107 -11
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
A generic modal top-layer helper based on the HTML `<dialog>` element.
|
|
4
|
+
-->
|
|
5
|
+
<svelte:options accessors={true} />
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import { createEventDispatcher, onMount } from 'svelte';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The `class` attribute on the `<dialog>` element.
|
|
12
|
+
* @type {string}
|
|
13
|
+
*/
|
|
14
|
+
let className = '';
|
|
15
|
+
export { className as class };
|
|
16
|
+
/**
|
|
17
|
+
* The `role` attribute on the `<dialog>` element.
|
|
18
|
+
* @type {'dialog' | 'alertdialog' | 'none'}
|
|
19
|
+
*/
|
|
20
|
+
export let role = 'dialog';
|
|
21
|
+
/**
|
|
22
|
+
* Whether to show the modal.
|
|
23
|
+
* @type {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export let open = false;
|
|
26
|
+
/**
|
|
27
|
+
* Whether to show the backdrop.
|
|
28
|
+
* @type {boolean}
|
|
29
|
+
*/
|
|
30
|
+
export let showBackdrop = false;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to close the modal when the backdrop (outside of the modal) is clicked.
|
|
33
|
+
* @type {boolean}
|
|
34
|
+
*/
|
|
35
|
+
export let lightDismiss = false;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to close the modal when the Escape key is pressed.
|
|
38
|
+
* @type {boolean}
|
|
39
|
+
*/
|
|
40
|
+
export let escapeDismiss = true;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to keep the content in the DOM tree when the modal is not displayed.
|
|
43
|
+
* @type {boolean}
|
|
44
|
+
*/
|
|
45
|
+
export let keepContent = false;
|
|
46
|
+
/**
|
|
47
|
+
* A reference to the `<dialog>` element.
|
|
48
|
+
* @type {HTMLDialogElement}
|
|
49
|
+
*/
|
|
50
|
+
export let dialog = undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Close the modal.
|
|
53
|
+
* @param {string} returnValue Return value to be used for `<dialog>`.
|
|
54
|
+
*/
|
|
55
|
+
export const close = (returnValue) => {
|
|
56
|
+
dialog.returnValue = returnValue;
|
|
57
|
+
open = false;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const dispatch = createEventDispatcher();
|
|
61
|
+
let setOpenClass = false;
|
|
62
|
+
let setActiveClass = false;
|
|
63
|
+
let showContent = false;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Resolve once the transition is complete.
|
|
67
|
+
* @returns {Promise<void>} Nothing.
|
|
68
|
+
*/
|
|
69
|
+
const waitForTransition = async () =>
|
|
70
|
+
new Promise((resolve) => {
|
|
71
|
+
/**
|
|
72
|
+
* @param {TransitionEvent} event `transition` event.
|
|
73
|
+
*/
|
|
74
|
+
const listener = (event) => {
|
|
75
|
+
if (event.target === dialog) {
|
|
76
|
+
dialog.removeEventListener('transitionend', listener);
|
|
77
|
+
resolve();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
dialog.addEventListener('transitionend', listener);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Show the modal.
|
|
86
|
+
*/
|
|
87
|
+
const openDialog = async () => {
|
|
88
|
+
dispatch('opening');
|
|
89
|
+
(document.querySelector('.sui.app-shell') ?? document.body).appendChild(dialog);
|
|
90
|
+
showContent = true;
|
|
91
|
+
dialog.showModal();
|
|
92
|
+
|
|
93
|
+
window.requestAnimationFrame(async () => {
|
|
94
|
+
dispatch('open');
|
|
95
|
+
setOpenClass = true;
|
|
96
|
+
await waitForTransition();
|
|
97
|
+
setActiveClass = true;
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Hide the modal.
|
|
103
|
+
*/
|
|
104
|
+
const closeDialog = async () => {
|
|
105
|
+
dispatch('closing');
|
|
106
|
+
setActiveClass = false;
|
|
107
|
+
setOpenClass = false;
|
|
108
|
+
await waitForTransition();
|
|
109
|
+
showContent = false;
|
|
110
|
+
dialog.close();
|
|
111
|
+
dialog.remove();
|
|
112
|
+
|
|
113
|
+
if (['ok', 'cancel'].includes(dialog?.returnValue)) {
|
|
114
|
+
dispatch(dialog?.returnValue);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
dispatch('close', dialog?.returnValue);
|
|
118
|
+
dialog.returnValue = undefined;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Toggle the modal.
|
|
123
|
+
*/
|
|
124
|
+
const toggleDialog = () => {
|
|
125
|
+
if (dialog) {
|
|
126
|
+
if (open) {
|
|
127
|
+
openDialog();
|
|
128
|
+
} else {
|
|
129
|
+
closeDialog();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
$: {
|
|
135
|
+
void open;
|
|
136
|
+
void dialog;
|
|
137
|
+
toggleDialog();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
onMount(() => {
|
|
141
|
+
dialog.remove();
|
|
142
|
+
|
|
143
|
+
// onUnmount
|
|
144
|
+
return () => {
|
|
145
|
+
dialog?.close();
|
|
146
|
+
dialog?.remove();
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
</script>
|
|
150
|
+
|
|
151
|
+
<dialog
|
|
152
|
+
{role}
|
|
153
|
+
class="sui modal {className}"
|
|
154
|
+
class:backdrop={showBackdrop}
|
|
155
|
+
class:open={setOpenClass}
|
|
156
|
+
class:active={setActiveClass}
|
|
157
|
+
{...$$restProps}
|
|
158
|
+
bind:this={dialog}
|
|
159
|
+
on:click={({ target }) => {
|
|
160
|
+
if (lightDismiss && /** @type {HTMLElement?} */ (target)?.matches('dialog')) {
|
|
161
|
+
dialog.returnValue = 'cancel';
|
|
162
|
+
open = false;
|
|
163
|
+
}
|
|
164
|
+
}}
|
|
165
|
+
on:cancel|preventDefault={() => {
|
|
166
|
+
// Escape key is pressed
|
|
167
|
+
if (escapeDismiss) {
|
|
168
|
+
open = false;
|
|
169
|
+
}
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<slot name="always-show" />
|
|
173
|
+
{#if showContent || keepContent}
|
|
174
|
+
<slot />
|
|
175
|
+
{/if}
|
|
176
|
+
</dialog>
|
|
177
|
+
|
|
178
|
+
<style>dialog {
|
|
179
|
+
position: fixed;
|
|
180
|
+
inset: 0;
|
|
181
|
+
display: flex;
|
|
182
|
+
justify-content: center;
|
|
183
|
+
align-items: center;
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
outline: 0;
|
|
186
|
+
margin: 0;
|
|
187
|
+
border: 0;
|
|
188
|
+
padding: 0;
|
|
189
|
+
width: 100dvw;
|
|
190
|
+
max-width: 100dvw;
|
|
191
|
+
height: 100dvh;
|
|
192
|
+
max-height: 100dvh;
|
|
193
|
+
color: var(--sui-primary-foreground-color);
|
|
194
|
+
background: transparent;
|
|
195
|
+
-webkit-user-select: none;
|
|
196
|
+
user-select: none;
|
|
197
|
+
touch-action: none;
|
|
198
|
+
pointer-events: all;
|
|
199
|
+
cursor: default;
|
|
200
|
+
}
|
|
201
|
+
dialog::backdrop {
|
|
202
|
+
background: transparent;
|
|
203
|
+
}
|
|
204
|
+
dialog.backdrop {
|
|
205
|
+
background-color: var(--sui-popup-backdrop-color);
|
|
206
|
+
}
|
|
207
|
+
dialog.open {
|
|
208
|
+
transition-duration: 200ms;
|
|
209
|
+
opacity: 1;
|
|
210
|
+
}
|
|
211
|
+
dialog:not(.open) {
|
|
212
|
+
transition-duration: 400ms;
|
|
213
|
+
opacity: 0;
|
|
214
|
+
}
|
|
215
|
+
dialog:not(.active) {
|
|
216
|
+
pointer-events: none !important;
|
|
217
|
+
}
|
|
218
|
+
dialog:not(.active) :global(*) {
|
|
219
|
+
pointer-events: none !important;
|
|
220
|
+
}</style>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} ModalProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} ModalEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} ModalSlots */
|
|
4
|
+
/** A generic modal top-layer helper based on the HTML `<dialog>` element. */
|
|
5
|
+
export default class Modal extends SvelteComponent<{
|
|
6
|
+
[x: string]: any;
|
|
7
|
+
class?: string;
|
|
8
|
+
close?: (returnValue: string) => void;
|
|
9
|
+
dialog?: HTMLDialogElement;
|
|
10
|
+
role?: "dialog" | "none" | "alertdialog";
|
|
11
|
+
open?: boolean;
|
|
12
|
+
showBackdrop?: boolean;
|
|
13
|
+
lightDismiss?: boolean;
|
|
14
|
+
escapeDismiss?: boolean;
|
|
15
|
+
keepContent?: boolean;
|
|
16
|
+
}, {
|
|
17
|
+
opening: CustomEvent<any>;
|
|
18
|
+
open: CustomEvent<any>;
|
|
19
|
+
closing: CustomEvent<any>;
|
|
20
|
+
close: CustomEvent<any>;
|
|
21
|
+
} & {
|
|
22
|
+
[evt: string]: CustomEvent<any>;
|
|
23
|
+
}, {
|
|
24
|
+
'always-show': {};
|
|
25
|
+
default: {};
|
|
26
|
+
}> {
|
|
27
|
+
get close(): (returnValue: string) => void;
|
|
28
|
+
/**accessor*/
|
|
29
|
+
set class(arg: string);
|
|
30
|
+
get class(): string;
|
|
31
|
+
/**accessor*/
|
|
32
|
+
set role(arg: "dialog" | "none" | "alertdialog");
|
|
33
|
+
get role(): "dialog" | "none" | "alertdialog";
|
|
34
|
+
/**accessor*/
|
|
35
|
+
set open(arg: boolean);
|
|
36
|
+
get open(): boolean;
|
|
37
|
+
/**accessor*/
|
|
38
|
+
set showBackdrop(arg: boolean);
|
|
39
|
+
get showBackdrop(): boolean;
|
|
40
|
+
/**accessor*/
|
|
41
|
+
set lightDismiss(arg: boolean);
|
|
42
|
+
get lightDismiss(): boolean;
|
|
43
|
+
/**accessor*/
|
|
44
|
+
set escapeDismiss(arg: boolean);
|
|
45
|
+
get escapeDismiss(): boolean;
|
|
46
|
+
/**accessor*/
|
|
47
|
+
set keepContent(arg: boolean);
|
|
48
|
+
get keepContent(): boolean;
|
|
49
|
+
/**accessor*/
|
|
50
|
+
set dialog(arg: HTMLDialogElement);
|
|
51
|
+
get dialog(): HTMLDialogElement;
|
|
52
|
+
}
|
|
53
|
+
export type ModalProps = typeof __propDef.props;
|
|
54
|
+
export type ModalEvents = typeof __propDef.events;
|
|
55
|
+
export type ModalSlots = typeof __propDef.slots;
|
|
56
|
+
import { SvelteComponent } from "svelte";
|
|
57
|
+
declare const __propDef: {
|
|
58
|
+
props: {
|
|
59
|
+
[x: string]: any;
|
|
60
|
+
class?: string;
|
|
61
|
+
close?: (returnValue: string) => void;
|
|
62
|
+
dialog?: HTMLDialogElement;
|
|
63
|
+
role?: 'dialog' | 'alertdialog' | 'none';
|
|
64
|
+
open?: boolean;
|
|
65
|
+
showBackdrop?: boolean;
|
|
66
|
+
lightDismiss?: boolean;
|
|
67
|
+
escapeDismiss?: boolean;
|
|
68
|
+
keepContent?: boolean;
|
|
69
|
+
};
|
|
70
|
+
events: {
|
|
71
|
+
opening: CustomEvent<any>;
|
|
72
|
+
open: CustomEvent<any>;
|
|
73
|
+
closing: CustomEvent<any>;
|
|
74
|
+
close: CustomEvent<any>;
|
|
75
|
+
} & {
|
|
76
|
+
[evt: string]: CustomEvent<any>;
|
|
77
|
+
};
|
|
78
|
+
slots: {
|
|
79
|
+
'always-show': {};
|
|
80
|
+
default: {};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export {};
|
|
@@ -9,35 +9,34 @@
|
|
|
9
9
|
import { writable } from 'svelte/store';
|
|
10
10
|
import { activatePopup } from '../../services/popup';
|
|
11
11
|
import { sleep } from '../../services/util';
|
|
12
|
+
import Modal from './modal.svelte';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* The `class` attribute on the
|
|
15
|
+
* The `class` attribute on the content element.
|
|
15
16
|
* @type {string}
|
|
16
17
|
*/
|
|
17
18
|
let className = '';
|
|
18
19
|
export { className as class };
|
|
19
|
-
|
|
20
|
-
/** @type {HTMLElement | undefined} */
|
|
21
|
-
export let anchor = undefined;
|
|
22
|
-
|
|
23
20
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @type {
|
|
21
|
+
* Whether to open the popup.
|
|
22
|
+
* @type {import('svelte/store').Writable<boolean>}
|
|
26
23
|
*/
|
|
27
|
-
export let
|
|
28
|
-
|
|
24
|
+
export let open = writable(false);
|
|
25
|
+
/**
|
|
26
|
+
* A reference to the anchor element that opens the popup. Typically a `<button>`.
|
|
27
|
+
* @type {HTMLElement}
|
|
28
|
+
*/
|
|
29
|
+
export let anchor;
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
-
* @type {HTMLElement
|
|
31
|
+
* A reference to the content element.
|
|
32
|
+
* @type {HTMLElement}
|
|
32
33
|
*/
|
|
33
34
|
export let content = undefined;
|
|
34
|
-
|
|
35
35
|
/**
|
|
36
|
-
* Where to show the
|
|
36
|
+
* Where to show the popup.
|
|
37
37
|
* @type {PopupPosition}
|
|
38
38
|
*/
|
|
39
39
|
export let position = 'bottom-left';
|
|
40
|
-
|
|
41
40
|
/**
|
|
42
41
|
* Whether to show the popup at the center of the screen on mobile/tablet and ignore the defined
|
|
43
42
|
* dropdown `position`.
|
|
@@ -45,14 +44,27 @@
|
|
|
45
44
|
*/
|
|
46
45
|
export let touchOptimized = false;
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
/**
|
|
48
|
+
* A reference to the modal component.
|
|
49
|
+
* @type {Modal}
|
|
50
|
+
*/
|
|
51
|
+
let modal;
|
|
52
|
+
/**
|
|
53
|
+
* Whether the touch is enabled on the user device.
|
|
54
|
+
* @type {boolean}
|
|
55
|
+
*/
|
|
52
56
|
let touchEnabled = false;
|
|
53
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* The type of the content displayed in the popup, defined with the `aria-haspopup` attribute on
|
|
59
|
+
* the anchor element.
|
|
60
|
+
* @type {string}
|
|
61
|
+
* @see https://w3c.github.io/aria/#aria-haspopup
|
|
62
|
+
*/
|
|
54
63
|
let contentType;
|
|
55
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Style to be applied to the content.
|
|
66
|
+
* @type {import('svelte/store').Writable<any>}
|
|
67
|
+
*/
|
|
56
68
|
let style = writable({
|
|
57
69
|
inset: undefined,
|
|
58
70
|
zIndex: undefined,
|
|
@@ -61,156 +73,103 @@
|
|
|
61
73
|
});
|
|
62
74
|
|
|
63
75
|
$: {
|
|
64
|
-
if (anchor && dialog) {
|
|
65
|
-
({ open, style } = activatePopup(anchor, dialog, position));
|
|
76
|
+
if (anchor && modal?.dialog) {
|
|
77
|
+
({ open, style } = activatePopup(anchor, modal.dialog, position));
|
|
66
78
|
contentType = anchor.getAttribute('aria-haspopup');
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
|
|
71
|
-
*
|
|
72
|
-
*/
|
|
73
|
-
const openDialog = () => {
|
|
74
|
-
(document.querySelector('.sui.app-shell') ?? document.body).appendChild(dialog);
|
|
75
|
-
showContent = true;
|
|
76
|
-
dialog.showModal();
|
|
77
|
-
|
|
78
|
-
window.requestAnimationFrame(async () => {
|
|
79
|
-
showDialog = true;
|
|
80
|
-
await sleep(100);
|
|
81
|
-
|
|
82
|
-
const target = /** @type {HTMLElement} */ (
|
|
83
|
-
content.querySelector('[tabindex]:not([aria-disabled="true"])')
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
if (target) {
|
|
87
|
-
target.focus();
|
|
88
|
-
} else {
|
|
89
|
-
content.tabIndex = -1;
|
|
90
|
-
content.focus();
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
*
|
|
97
|
-
*/
|
|
98
|
-
const closeDialog = async () => {
|
|
99
|
-
showDialog = false;
|
|
100
|
-
|
|
101
|
-
await new Promise((resolve) => {
|
|
102
|
-
content.addEventListener('transitionend', () => resolve(), { once: true });
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
showContent = false;
|
|
106
|
-
dialog?.close();
|
|
107
|
-
dialog?.remove();
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
*
|
|
112
|
-
*/
|
|
113
|
-
const toggleDialog = () => {
|
|
114
|
-
if (dialog) {
|
|
115
|
-
if ($open) {
|
|
116
|
-
openDialog();
|
|
117
|
-
} else {
|
|
118
|
-
closeDialog();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
$: {
|
|
124
|
-
void $open;
|
|
125
|
-
toggleDialog();
|
|
126
|
-
}
|
|
82
|
+
$: touch = touchOptimized && touchEnabled;
|
|
127
83
|
|
|
128
84
|
onMount(() => {
|
|
129
|
-
dialog.remove();
|
|
130
|
-
|
|
131
85
|
touchEnabled = window.matchMedia('(pointer: coarse)').matches;
|
|
132
|
-
|
|
133
|
-
// onUnmount
|
|
134
|
-
return () => {
|
|
135
|
-
dialog?.close();
|
|
136
|
-
dialog?.remove();
|
|
137
|
-
};
|
|
138
86
|
});
|
|
139
87
|
</script>
|
|
140
88
|
|
|
141
|
-
<
|
|
142
|
-
class="sui popup {className}"
|
|
89
|
+
<Modal
|
|
143
90
|
role="none"
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
91
|
+
class="popup"
|
|
92
|
+
bind:open={$open}
|
|
93
|
+
showBackdrop={touch}
|
|
94
|
+
lightDismiss={true}
|
|
95
|
+
keepContent={true}
|
|
96
|
+
bind:this={modal}
|
|
147
97
|
{...$$restProps}
|
|
98
|
+
on:opening
|
|
99
|
+
on:open
|
|
100
|
+
on:ok
|
|
101
|
+
on:cancel
|
|
102
|
+
on:closing
|
|
103
|
+
on:close
|
|
104
|
+
on:open={async () => {
|
|
105
|
+
await sleep(100);
|
|
106
|
+
|
|
107
|
+
const target = /** @type {HTMLElement} */ (
|
|
108
|
+
content.querySelector('[tabindex]:not([aria-disabled="true"])')
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
if (target) {
|
|
112
|
+
target.focus();
|
|
113
|
+
} else {
|
|
114
|
+
content.tabIndex = -1;
|
|
115
|
+
content.focus();
|
|
116
|
+
}
|
|
117
|
+
}}
|
|
148
118
|
>
|
|
149
119
|
<div
|
|
150
|
-
|
|
151
|
-
class="content {contentType}"
|
|
120
|
+
role="none"
|
|
121
|
+
class="content {className} {contentType}"
|
|
122
|
+
class:touch
|
|
152
123
|
style:inset={$style.inset}
|
|
153
124
|
style:z-index={$style.zIndex}
|
|
154
125
|
style:min-width={$style.width}
|
|
155
126
|
style:max-height={$style.height}
|
|
156
127
|
style:visibility={$style.inset ? undefined : 'hidden'}
|
|
128
|
+
bind:this={content}
|
|
157
129
|
>
|
|
158
|
-
|
|
159
|
-
<slot />
|
|
160
|
-
{/if}
|
|
130
|
+
<slot />
|
|
161
131
|
</div>
|
|
162
|
-
</
|
|
132
|
+
</Modal>
|
|
163
133
|
|
|
164
|
-
<style>.
|
|
165
|
-
display: flex;
|
|
166
|
-
align-items: center;
|
|
167
|
-
justify-content: center;
|
|
168
|
-
background-color: var(--sui-popup-backdrop-color);
|
|
169
|
-
}
|
|
170
|
-
.popup.touch .content {
|
|
134
|
+
<style>.content.touch {
|
|
171
135
|
position: static;
|
|
172
136
|
border-width: 0 !important;
|
|
173
137
|
border-radius: 4px !important;
|
|
174
138
|
padding: 8px;
|
|
175
139
|
min-width: 320px !important;
|
|
176
|
-
max-width: calc(
|
|
177
|
-
max-height: calc(
|
|
140
|
+
max-width: calc(100dvw - 32px) !important;
|
|
141
|
+
max-height: calc(100dvh - 32px) !important;
|
|
178
142
|
}
|
|
179
|
-
.
|
|
143
|
+
:global(dialog.open) .content.touch {
|
|
180
144
|
transform: scale(100%) !important;
|
|
181
145
|
}
|
|
182
|
-
|
|
146
|
+
:global(dialog:not(.open)) .content.touch {
|
|
183
147
|
transform: scale(90%);
|
|
184
148
|
}
|
|
185
|
-
.
|
|
149
|
+
.content.touch.combobox :global(.sui.listbox) {
|
|
186
150
|
gap: 4px;
|
|
187
151
|
padding: 8px 4px !important;
|
|
188
152
|
}
|
|
189
|
-
.
|
|
153
|
+
:global(dialog.open) .content {
|
|
154
|
+
transition-duration: 150ms;
|
|
190
155
|
opacity: 1;
|
|
191
156
|
transform: translateY(2px);
|
|
192
|
-
transition-duration: 100ms;
|
|
193
|
-
}
|
|
194
|
-
.popup:not(.open) {
|
|
195
|
-
pointer-events: none;
|
|
196
157
|
}
|
|
197
|
-
|
|
158
|
+
:global(dialog:not(.open)) .content {
|
|
159
|
+
transition-duration: 300ms;
|
|
198
160
|
opacity: 0;
|
|
199
161
|
transform: translateY(-8px);
|
|
200
|
-
pointer-events: none;
|
|
201
|
-
transition-duration: 200ms;
|
|
202
162
|
}
|
|
203
163
|
|
|
204
164
|
.content {
|
|
205
|
-
position:
|
|
165
|
+
position: absolute;
|
|
206
166
|
overflow-y: auto;
|
|
207
167
|
outline-width: 0 !important;
|
|
208
168
|
color: var(--sui-primary-foreground-color);
|
|
209
169
|
background-color: var(--sui-secondary-background-color-translucent);
|
|
170
|
+
box-shadow: 0 8px 16px var(--sui-popup-shadow-color);
|
|
210
171
|
-webkit-backdrop-filter: blur(16px);
|
|
211
172
|
backdrop-filter: blur(16px);
|
|
212
|
-
box-shadow: 0 8px 16px var(--sui-popup-shadow-color);
|
|
213
|
-
will-change: opacity, transform;
|
|
214
173
|
transition-property: opacity, transform;
|
|
215
174
|
}
|
|
216
175
|
.content.listbox, .content.menu {
|
|
@@ -4,14 +4,20 @@
|
|
|
4
4
|
/** Generic popup helper. */
|
|
5
5
|
export default class Popup extends SvelteComponent<{
|
|
6
6
|
[x: string]: any;
|
|
7
|
+
anchor: HTMLElement;
|
|
7
8
|
class?: string;
|
|
8
|
-
dialog?: HTMLDialogElement;
|
|
9
9
|
position?: PopupPosition;
|
|
10
|
-
|
|
10
|
+
open?: import("svelte/store").Writable<boolean>;
|
|
11
11
|
content?: HTMLElement;
|
|
12
12
|
touchOptimized?: boolean;
|
|
13
|
-
open?: import("svelte/store").Writable<boolean>;
|
|
14
13
|
}, {
|
|
14
|
+
opening: CustomEvent<any>;
|
|
15
|
+
open: CustomEvent<any>;
|
|
16
|
+
ok: CustomEvent<any>;
|
|
17
|
+
cancel: CustomEvent<any>;
|
|
18
|
+
closing: CustomEvent<any>;
|
|
19
|
+
close: CustomEvent<any>;
|
|
20
|
+
} & {
|
|
15
21
|
[evt: string]: CustomEvent<any>;
|
|
16
22
|
}, {
|
|
17
23
|
default: {};
|
|
@@ -20,12 +26,12 @@ export default class Popup extends SvelteComponent<{
|
|
|
20
26
|
set class(arg: string);
|
|
21
27
|
get class(): string;
|
|
22
28
|
/**accessor*/
|
|
29
|
+
set open(arg: import("svelte/store").Writable<boolean>);
|
|
30
|
+
get open(): import("svelte/store").Writable<boolean>;
|
|
31
|
+
/**accessor*/
|
|
23
32
|
set anchor(arg: HTMLElement);
|
|
24
33
|
get anchor(): HTMLElement;
|
|
25
34
|
/**accessor*/
|
|
26
|
-
set dialog(arg: HTMLDialogElement);
|
|
27
|
-
get dialog(): HTMLDialogElement;
|
|
28
|
-
/**accessor*/
|
|
29
35
|
set content(arg: HTMLElement);
|
|
30
36
|
get content(): HTMLElement;
|
|
31
37
|
/**accessor*/
|
|
@@ -34,9 +40,6 @@ export default class Popup extends SvelteComponent<{
|
|
|
34
40
|
/**accessor*/
|
|
35
41
|
set touchOptimized(arg: boolean);
|
|
36
42
|
get touchOptimized(): boolean;
|
|
37
|
-
/**accessor*/
|
|
38
|
-
set open(arg: import("svelte/store").Writable<boolean>);
|
|
39
|
-
get open(): import("svelte/store").Writable<boolean>;
|
|
40
43
|
}
|
|
41
44
|
export type PopupProps = typeof __propDef.props;
|
|
42
45
|
export type PopupEvents = typeof __propDef.events;
|
|
@@ -45,15 +48,21 @@ import { SvelteComponent } from "svelte";
|
|
|
45
48
|
declare const __propDef: {
|
|
46
49
|
props: {
|
|
47
50
|
[x: string]: any;
|
|
51
|
+
anchor: HTMLElement;
|
|
48
52
|
class?: string;
|
|
49
|
-
dialog?: HTMLDialogElement | undefined;
|
|
50
53
|
position?: PopupPosition;
|
|
51
|
-
|
|
52
|
-
content?: HTMLElement
|
|
54
|
+
open?: import('svelte/store').Writable<boolean>;
|
|
55
|
+
content?: HTMLElement;
|
|
53
56
|
touchOptimized?: boolean;
|
|
54
|
-
open?: import("svelte/store").Writable<boolean>;
|
|
55
57
|
};
|
|
56
58
|
events: {
|
|
59
|
+
opening: CustomEvent<any>;
|
|
60
|
+
open: CustomEvent<any>;
|
|
61
|
+
ok: CustomEvent<any>;
|
|
62
|
+
cancel: CustomEvent<any>;
|
|
63
|
+
closing: CustomEvent<any>;
|
|
64
|
+
close: CustomEvent<any>;
|
|
65
|
+
} & {
|
|
57
66
|
[evt: string]: CustomEvent<any>;
|
|
58
67
|
};
|
|
59
68
|
slots: {
|
package/package/index.d.ts
CHANGED
|
@@ -9,11 +9,22 @@ export { default as SelectButton } from "./components/button/select-button.svelt
|
|
|
9
9
|
export { default as Calendar } from "./components/calendar/calendar.svelte";
|
|
10
10
|
export { default as CheckboxGroup } from "./components/checkbox/checkbox-group.svelte";
|
|
11
11
|
export { default as Checkbox } from "./components/checkbox/checkbox.svelte";
|
|
12
|
+
export { default as AlertDialog } from "./components/dialog/alert-dialog.svelte";
|
|
13
|
+
export { default as ConfirmationDialog } from "./components/dialog/confirmation-dialog.svelte";
|
|
12
14
|
export { default as Dialog } from "./components/dialog/dialog.svelte";
|
|
15
|
+
export { default as PromptDialog } from "./components/dialog/prompt-dialog.svelte";
|
|
13
16
|
export { default as Disclosure } from "./components/disclosure/disclosure.svelte";
|
|
14
17
|
export { default as Divider } from "./components/divider/divider.svelte";
|
|
15
18
|
export { default as Spacer } from "./components/divider/spacer.svelte";
|
|
16
19
|
export { default as Drawer } from "./components/drawer/drawer.svelte";
|
|
20
|
+
export { default as GridBody } from "./components/grid/grid-body.svelte";
|
|
21
|
+
export { default as GridCell } from "./components/grid/grid-cell.svelte";
|
|
22
|
+
export { default as GridColHeader } from "./components/grid/grid-col-header.svelte";
|
|
23
|
+
export { default as GridFoot } from "./components/grid/grid-foot.svelte";
|
|
24
|
+
export { default as GridHead } from "./components/grid/grid-head.svelte";
|
|
25
|
+
export { default as GridRowHeader } from "./components/grid/grid-row-header.svelte";
|
|
26
|
+
export { default as GridRow } from "./components/grid/grid-row.svelte";
|
|
27
|
+
export { default as Grid } from "./components/grid/grid.svelte";
|
|
17
28
|
export { default as Icon } from "./components/icon/icon.svelte";
|
|
18
29
|
export { default as Listbox } from "./components/listbox/listbox.svelte";
|
|
19
30
|
export { default as OptionGroup } from "./components/listbox/option-group.svelte";
|
|
@@ -51,4 +62,5 @@ export { default as Toast } from "./components/toast/toast.svelte";
|
|
|
51
62
|
export { default as Toolbar } from "./components/toolbar/toolbar.svelte";
|
|
52
63
|
export { default as AppShell } from "./components/util/app-shell.svelte";
|
|
53
64
|
export { default as Group } from "./components/util/group.svelte";
|
|
65
|
+
export { default as Modal } from "./components/util/modal.svelte";
|
|
54
66
|
export * from "./services/util";
|