@sveltia/ui 0.78.3 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/alert/alert-content.svelte +51 -0
- package/dist/components/alert/alert-content.svelte.d.ts +39 -0
- package/dist/components/alert/alert.d.ts +3 -0
- package/dist/components/alert/alert.js +21 -0
- package/dist/components/alert/alert.svelte +6 -30
- package/dist/components/alert/infobar.svelte +7 -21
- package/dist/components/alert/infobar.svelte.d.ts +2 -2
- package/dist/components/button/button.svelte +11 -11
- package/dist/components/button/button.svelte.d.ts +2 -2
- package/dist/components/button/select-button.svelte +1 -1
- package/dist/components/button/select-button.svelte.d.ts +2 -2
- package/dist/components/button/split-button.svelte +1 -1
- package/dist/components/button/split-button.svelte.d.ts +3 -3
- package/dist/components/calendar/calendar.d.ts +2 -0
- package/dist/components/calendar/calendar.js +34 -0
- package/dist/components/calendar/calendar.svelte +49 -5
- package/dist/components/checkbox/checkbox.svelte +11 -4
- package/dist/components/checkbox/checkbox.svelte.d.ts +2 -2
- package/dist/components/dialog/alert-dialog.svelte +1 -1
- package/dist/components/dialog/alert-dialog.svelte.d.ts +2 -2
- package/dist/components/dialog/confirmation-dialog.svelte +1 -1
- package/dist/components/dialog/confirmation-dialog.svelte.d.ts +2 -2
- package/dist/components/dialog/dialog.svelte +8 -18
- package/dist/components/dialog/dialog.svelte.d.ts +2 -2
- package/dist/components/dialog/modal-close-button.svelte +50 -0
- package/dist/components/dialog/modal-close-button.svelte.d.ts +43 -0
- package/dist/components/dialog/prompt-dialog.svelte +1 -1
- package/dist/components/dialog/prompt-dialog.svelte.d.ts +4 -4
- package/dist/components/disclosure/disclosure.svelte +1 -1
- package/dist/components/drawer/drawer.svelte +12 -34
- package/dist/components/drawer/drawer.svelte.d.ts +1 -1
- package/dist/components/emoji/caret.d.ts +1 -1
- package/dist/components/emoji/caret.js +1 -1
- package/dist/components/emoji/emoji-suggestions.svelte +1 -1
- package/dist/components/emoji/emoji-suggestions.svelte.d.ts +3 -3
- package/dist/components/emoji/emoji.d.ts +2 -2
- package/dist/components/emoji/emoji.js +1 -1
- package/dist/components/emoji/position.d.ts +2 -2
- package/dist/components/emoji/position.js +1 -1
- package/dist/components/grid/grid-body.svelte +6 -2
- package/dist/components/grid/grid-cell.svelte +3 -9
- package/dist/components/grid/grid-col-header.svelte +3 -9
- package/dist/components/grid/grid-foot.svelte +4 -11
- package/dist/components/grid/grid-head.svelte +4 -11
- package/dist/components/grid/grid-row-header.svelte +3 -10
- package/dist/components/grid/grid-row.svelte +3 -16
- package/dist/components/listbox/listbox.svelte +1 -1
- package/dist/components/listbox/listbox.svelte.d.ts +1 -1
- package/dist/components/listbox/option.svelte +1 -1
- package/dist/components/listbox/option.svelte.d.ts +2 -2
- package/dist/components/menu/menu-button.svelte +2 -2
- package/dist/components/menu/menu-button.svelte.d.ts +4 -4
- package/dist/components/menu/menu-item-checkable.svelte +71 -0
- package/dist/components/menu/menu-item-checkable.svelte.d.ts +25 -0
- package/dist/components/menu/menu-item-checkbox.svelte +3 -36
- package/dist/components/menu/menu-item-checkbox.svelte.d.ts +3 -3
- package/dist/components/menu/menu-item-group.svelte +8 -5
- package/dist/components/menu/menu-item-group.svelte.d.ts +9 -1
- package/dist/components/menu/menu-item-radio.svelte +3 -36
- package/dist/components/menu/menu-item-radio.svelte.d.ts +3 -3
- package/dist/components/menu/menu-item.svelte +22 -6
- package/dist/components/menu/menu-item.svelte.d.ts +4 -4
- package/dist/components/radio/radio.svelte +12 -1
- package/dist/components/resizable-pane/resizable-handle.svelte +14 -18
- package/dist/components/resizable-pane/resizable-pane-group.svelte +9 -6
- package/dist/components/resizable-pane/resizable-pane.svelte +4 -4
- package/dist/components/resizable-pane/resizable-pane.svelte.d.ts +7 -6
- package/dist/components/resizable-pane/sizing.d.ts +5 -4
- package/dist/components/resizable-pane/sizing.js +84 -25
- package/dist/components/scroll/infinite-scroll.svelte +16 -21
- package/dist/components/select/combobox.svelte +43 -52
- package/dist/components/select/combobox.svelte.d.ts +2 -2
- package/dist/components/select/select-tags.svelte +7 -1
- package/dist/components/select/select.svelte +2 -22
- package/dist/components/select/select.svelte.d.ts +1 -1
- package/dist/components/slider/slider.d.ts +6 -0
- package/dist/components/slider/slider.js +55 -2
- package/dist/components/slider/slider.svelte +63 -32
- package/dist/components/table/table-cell.svelte +3 -9
- package/dist/components/table/table-col-header.svelte +3 -9
- package/dist/components/table/table-foot.svelte +4 -11
- package/dist/components/table/table-head.svelte +4 -11
- package/dist/components/table/table-part.svelte +69 -0
- package/dist/components/table/table-part.svelte.d.ts +48 -0
- package/dist/components/table/table-row-header.svelte +3 -10
- package/dist/components/table/table-row.svelte +3 -10
- package/dist/components/tabs/tab-list.svelte +12 -0
- package/dist/components/tabs/tab.svelte +1 -1
- package/dist/components/tabs/tab.svelte.d.ts +2 -2
- package/dist/components/text-editor/constants.d.ts +5 -5
- package/dist/components/text-editor/constants.js +1 -1
- package/dist/components/text-editor/core.d.ts +4 -5
- package/dist/components/text-editor/core.js +376 -273
- package/dist/components/text-editor/emoji-autocomplete.svelte +1 -1
- package/dist/components/text-editor/lexical-root.svelte +1 -1
- package/dist/components/text-editor/raw-markdown.d.ts +6 -33
- package/dist/components/text-editor/raw-markdown.js +63 -8
- package/dist/components/text-editor/shiki/facade.d.ts +1 -1
- package/dist/components/text-editor/shiki/facade.js +63 -48
- package/dist/components/text-editor/shiki/generated.d.ts +1 -1
- package/dist/components/text-editor/shiki/generated.js +1 -1
- package/dist/components/text-editor/shiki/highlighter.d.ts +6 -1
- package/dist/components/text-editor/shiki/highlighter.js +3 -4
- package/dist/components/text-editor/shiki/loader.d.ts +1 -1
- package/dist/components/text-editor/shiki/loader.js +1 -1
- package/dist/components/text-editor/shiki/version.d.ts +1 -1
- package/dist/components/text-editor/shiki/version.js +1 -1
- package/dist/components/text-editor/store.svelte.d.ts +1 -1
- package/dist/components/text-editor/store.svelte.js +5 -2
- package/dist/components/text-editor/text-editor.svelte +2 -2
- package/dist/components/text-editor/text-editor.svelte.d.ts +3 -3
- package/dist/components/text-editor/toolbar/code-language-switcher.svelte +24 -16
- package/dist/components/text-editor/toolbar/format-text-button.svelte +7 -31
- package/dist/components/text-editor/toolbar/format-text-button.svelte.d.ts +1 -1
- package/dist/components/text-editor/toolbar/insert-component.d.ts +3 -0
- package/dist/components/text-editor/toolbar/insert-component.js +34 -0
- package/dist/components/text-editor/toolbar/insert-item-button.svelte +4 -24
- package/dist/components/text-editor/toolbar/insert-item-button.svelte.d.ts +1 -1
- package/dist/components/text-editor/toolbar/insert-link-button.svelte +9 -25
- package/dist/components/text-editor/toolbar/insert-menu-button.svelte +4 -24
- package/dist/components/text-editor/toolbar/insert-menu-button.svelte.d.ts +1 -1
- package/dist/components/text-editor/toolbar/text-editor-toolbar.svelte +1 -1
- package/dist/components/text-editor/toolbar/toggle-block-menu-item.svelte +31 -35
- package/dist/components/text-editor/toolbar/toggle-block-menu-item.svelte.d.ts +1 -1
- package/dist/components/text-editor/toolbar/toolbar-wrapper.svelte +0 -10
- package/dist/components/text-editor/toolbar/toolbar-wrapper.svelte.d.ts +1 -11
- package/dist/components/text-editor/transformers/table.d.ts +0 -1
- package/dist/components/text-editor/transformers/table.js +1 -2
- package/dist/components/text-field/emoji-autocomplete.svelte +1 -1
- package/dist/components/text-field/masked-input.svelte +179 -0
- package/dist/components/text-field/masked-input.svelte.d.ts +42 -0
- package/dist/components/text-field/number-input.js +7 -1
- package/dist/components/text-field/number-input.svelte +13 -5
- package/dist/components/text-field/number-input.svelte.d.ts +3 -3
- package/dist/components/text-field/password-input.svelte +3 -116
- package/dist/components/text-field/password-input.svelte.d.ts +3 -3
- package/dist/components/text-field/search-bar.svelte +1 -1
- package/dist/components/text-field/search-bar.svelte.d.ts +3 -3
- package/dist/components/text-field/secret-input.svelte +3 -119
- package/dist/components/text-field/secret-input.svelte.d.ts +3 -3
- package/dist/components/text-field/text-area.svelte +1 -1
- package/dist/components/text-field/text-area.svelte.d.ts +3 -3
- package/dist/components/text-field/text-input.svelte +1 -1
- package/dist/components/text-field/text-input.svelte.d.ts +3 -3
- package/dist/components/toast/toast.svelte +11 -20
- package/dist/components/toast/toast.svelte.d.ts +1 -1
- package/dist/components/tree/tree-item.svelte +1 -1
- package/dist/components/tree/tree-item.svelte.d.ts +1 -1
- package/dist/components/tree/tree.svelte +1 -1
- package/dist/components/tree/tree.svelte.d.ts +1 -1
- package/dist/components/util/font-links.svelte +1 -0
- package/dist/components/util/modal.svelte +37 -1
- package/dist/components/util/modal.svelte.d.ts +1 -1
- package/dist/components/util/popup.svelte +2 -5
- package/dist/components/util/popup.svelte.d.ts +2 -2
- package/dist/components/util/visibility-observer.svelte +1 -0
- package/dist/locales/ar.yaml +1 -1
- package/dist/locales/sk.yaml +136 -0
- package/dist/services/group.svelte.d.ts +10 -1
- package/dist/services/group.svelte.js +361 -251
- package/dist/services/navigation.d.ts +19 -0
- package/dist/services/navigation.js +84 -0
- package/dist/services/popup-position.d.ts +90 -0
- package/dist/services/popup-position.js +275 -0
- package/dist/services/popup.svelte.d.ts +16 -17
- package/dist/services/popup.svelte.js +25 -169
- package/dist/services/scroll.d.ts +1 -0
- package/dist/services/scroll.js +17 -0
- package/dist/services/select.svelte.d.ts +2 -2
- package/dist/services/select.svelte.js +1 -1
- package/dist/services/text.d.ts +2 -0
- package/dist/services/text.js +28 -0
- package/dist/services/tree.svelte.d.ts +3 -11
- package/dist/services/tree.svelte.js +35 -77
- package/dist/services/type-ahead.d.ts +0 -4
- package/dist/services/type-ahead.js +3 -1
- package/dist/services/widget.d.ts +8 -0
- package/dist/services/widget.js +39 -0
- package/dist/shiki-engine.js +15 -15
- package/dist/styles/mixins.scss +126 -0
- package/package.json +38 -34
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { $createParagraphNode as createParagraphNode, $insertNodes as insertNodes } from 'lexical';
|
|
2
|
+
import { insertComponent } from '../raw-markdown.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @import { TextEditorComponent, TextEditorStore } from '../../../typedefs.js';
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Insert a new instance of the given editor component into the editor: its Markdown in the plain
|
|
10
|
+
* text mode, or its node in the rich text mode.
|
|
11
|
+
* @param {TextEditorStore} editorStore Editor store.
|
|
12
|
+
* @param {TextEditorComponent} component Editor component.
|
|
13
|
+
*/
|
|
14
|
+
export const insertEditorComponent = (editorStore, component) => {
|
|
15
|
+
const { textArea, useRichText } = editorStore;
|
|
16
|
+
|
|
17
|
+
// Insert the component’s Markdown in the plain text mode
|
|
18
|
+
if (!useRichText) {
|
|
19
|
+
// The toolbar is only enabled while the `<textarea>` is there
|
|
20
|
+
/* v8 ignore else */
|
|
21
|
+
if (textArea) {
|
|
22
|
+
insertComponent(textArea, component);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { createNode } = component;
|
|
29
|
+
|
|
30
|
+
editorStore.editor?.update(() => {
|
|
31
|
+
// Add an additional paragraph for easier editing
|
|
32
|
+
insertNodes([createNode(), createParagraphNode()]);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {
|
|
3
|
-
$createParagraphNode as createParagraphNode,
|
|
4
|
-
$insertNodes as insertNodes,
|
|
5
|
-
} from 'lexical';
|
|
6
2
|
import { getContext } from 'svelte';
|
|
7
3
|
import Button from '../../button/button.svelte';
|
|
8
4
|
import Icon from '../../icon/icon.svelte';
|
|
9
|
-
import {
|
|
5
|
+
import { insertEditorComponent } from './insert-component.js';
|
|
10
6
|
|
|
11
7
|
/**
|
|
12
|
-
* @import { TextEditorComponent, TextEditorStore } from '../../../typedefs';
|
|
8
|
+
* @import { TextEditorComponent, TextEditorStore } from '../../../typedefs.js';
|
|
13
9
|
*/
|
|
14
10
|
|
|
15
11
|
/**
|
|
@@ -27,7 +23,7 @@
|
|
|
27
23
|
/** @type {TextEditorStore} */
|
|
28
24
|
const editorStore = getContext('editorStore');
|
|
29
25
|
|
|
30
|
-
const { label, icon
|
|
26
|
+
const { label, icon } = $derived(component);
|
|
31
27
|
</script>
|
|
32
28
|
|
|
33
29
|
<Button
|
|
@@ -37,23 +33,7 @@
|
|
|
37
33
|
aria-label={label}
|
|
38
34
|
aria-controls={editorStore.controlId}
|
|
39
35
|
onclick={() => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Insert the component’s Markdown in the plain text mode
|
|
43
|
-
if (!useRichText) {
|
|
44
|
-
// The button is only enabled while the `<textarea>` is there
|
|
45
|
-
/* v8 ignore else */
|
|
46
|
-
if (textArea) {
|
|
47
|
-
insertComponent(textArea, component);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
editorStore.editor?.update(() => {
|
|
54
|
-
// Add an additional paragraph for easier editing
|
|
55
|
-
insertNodes([createNode(), createParagraphNode()]);
|
|
56
|
-
});
|
|
36
|
+
insertEditorComponent(editorStore, component);
|
|
57
37
|
}}
|
|
58
38
|
>
|
|
59
39
|
{#snippet startIcon()}
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
import { AVAILABLE_BUTTONS } from '../constants.js';
|
|
25
25
|
import { focusEditor, isSafeLinkURL } from '../core.js';
|
|
26
26
|
import {
|
|
27
|
-
|
|
27
|
+
editRawText,
|
|
28
28
|
getRawTextState,
|
|
29
29
|
insertLink,
|
|
30
|
-
|
|
30
|
+
registerRawTextShortcut,
|
|
31
31
|
} from '../raw-markdown.js';
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* @import { TextEditorStore } from '../../../typedefs';
|
|
34
|
+
* @import { TextEditorStore } from '../../../typedefs.js';
|
|
35
35
|
* @import { RangeSelection } from 'lexical';
|
|
36
36
|
*/
|
|
37
37
|
|
|
@@ -169,12 +169,8 @@
|
|
|
169
169
|
/* v8 ignore else */
|
|
170
170
|
if (textArea) {
|
|
171
171
|
if (event.detail.returnValue !== 'cancel') {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
insertLink(getRawTextState(textArea), {
|
|
175
|
-
url: anchorURL.trim(),
|
|
176
|
-
text: hasAnchor ? undefined : anchorText,
|
|
177
|
-
}),
|
|
172
|
+
editRawText(textArea, (state) =>
|
|
173
|
+
insertLink(state, { url: anchorURL.trim(), text: hasAnchor ? undefined : anchorText }),
|
|
178
174
|
);
|
|
179
175
|
} else {
|
|
180
176
|
textArea.focus();
|
|
@@ -249,22 +245,10 @@
|
|
|
249
245
|
return undefined;
|
|
250
246
|
}
|
|
251
247
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const onKeyDown = (event) => {
|
|
257
|
-
if (isRawTextEditable(textArea) && matchesShortcuts(event, isMac() ? 'Meta+K' : 'Ctrl+K')) {
|
|
258
|
-
event.preventDefault();
|
|
259
|
-
onButtonClick();
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
textArea.addEventListener('keydown', onKeyDown);
|
|
264
|
-
|
|
265
|
-
return () => {
|
|
266
|
-
textArea.removeEventListener('keydown', onKeyDown);
|
|
267
|
-
};
|
|
248
|
+
// Handle the keyboard shortcut in the plain text mode
|
|
249
|
+
return registerRawTextShortcut(textArea, 'K', () => {
|
|
250
|
+
onButtonClick();
|
|
251
|
+
});
|
|
268
252
|
});
|
|
269
253
|
|
|
270
254
|
$effect(() => {
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { _ } from '@sveltia/i18n';
|
|
3
|
-
import {
|
|
4
|
-
$createParagraphNode as createParagraphNode,
|
|
5
|
-
$insertNodes as insertNodes,
|
|
6
|
-
} from 'lexical';
|
|
7
3
|
import { getContext } from 'svelte';
|
|
8
4
|
import Icon from '../../icon/icon.svelte';
|
|
9
5
|
import MenuButton from '../../menu/menu-button.svelte';
|
|
10
6
|
import MenuItem from '../../menu/menu-item.svelte';
|
|
11
7
|
import Menu from '../../menu/menu.svelte';
|
|
12
|
-
import {
|
|
8
|
+
import { insertEditorComponent } from './insert-component.js';
|
|
13
9
|
|
|
14
10
|
/**
|
|
15
|
-
* @import { TextEditorComponent, TextEditorStore } from '../../../typedefs';
|
|
11
|
+
* @import { TextEditorComponent, TextEditorStore } from '../../../typedefs.js';
|
|
16
12
|
*/
|
|
17
13
|
|
|
18
14
|
/**
|
|
@@ -38,27 +34,11 @@
|
|
|
38
34
|
{#snippet popup()}
|
|
39
35
|
<Menu>
|
|
40
36
|
{#each components as component (component.id)}
|
|
41
|
-
{@const { label, icon
|
|
37
|
+
{@const { label, icon } = component}
|
|
42
38
|
<MenuItem
|
|
43
39
|
{label}
|
|
44
40
|
onclick={() => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Insert the component’s Markdown in the plain text mode
|
|
48
|
-
if (!useRichText) {
|
|
49
|
-
// The item is only clickable while the `<textarea>` is there
|
|
50
|
-
/* v8 ignore else */
|
|
51
|
-
if (textArea) {
|
|
52
|
-
insertComponent(textArea, component);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
editorStore.editor?.update(() => {
|
|
59
|
-
// Add an additional paragraph for easier editing
|
|
60
|
-
insertNodes([createNode(), createParagraphNode()]);
|
|
61
|
-
});
|
|
41
|
+
insertEditorComponent(editorStore, component);
|
|
62
42
|
}}
|
|
63
43
|
>
|
|
64
44
|
{#snippet startIcon()}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import ToolbarWrapper from './toolbar-wrapper.svelte';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* @import { TextEditorBlockType, TextEditorInlineType, TextEditorStore } from '../../../typedefs';
|
|
22
|
+
* @import { TextEditorBlockType, TextEditorInlineType, TextEditorStore } from '../../../typedefs.js';
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -16,13 +16,34 @@
|
|
|
16
16
|
import MenuItemCheckbox from '../../menu/menu-item-checkbox.svelte';
|
|
17
17
|
import { AVAILABLE_BUTTONS } from '../constants.js';
|
|
18
18
|
import { focusEditor } from '../core.js';
|
|
19
|
-
import {
|
|
19
|
+
import { editRawText, setBlockType } from '../raw-markdown.js';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* @import { TextEditorBlockType, TextEditorStore } from '../../../typedefs';
|
|
22
|
+
* @import { TextEditorBlockType, TextEditorStore } from '../../../typedefs.js';
|
|
23
23
|
* @import { HeadingTagType } from '@lexical/rich-text';
|
|
24
|
+
* @import { ElementNode, LexicalCommand } from 'lexical';
|
|
24
25
|
*/
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Node factories for the block types applied with `$setBlocksType()`, except headings, whose
|
|
29
|
+
* level is parsed from the type.
|
|
30
|
+
* @type {Record<string, () => ElementNode>}
|
|
31
|
+
*/
|
|
32
|
+
const NODE_FACTORIES = {
|
|
33
|
+
paragraph: createParagraphNode,
|
|
34
|
+
blockquote: createQuoteNode,
|
|
35
|
+
'code-block': createCodeNode,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Commands for the list block types, which are toggled by the list plugin instead.
|
|
40
|
+
* @type {Record<string, LexicalCommand<void>>}
|
|
41
|
+
*/
|
|
42
|
+
const LIST_COMMANDS = {
|
|
43
|
+
'bulleted-list': INSERT_UNORDERED_LIST_COMMAND,
|
|
44
|
+
'numbered-list': INSERT_ORDERED_LIST_COMMAND,
|
|
45
|
+
};
|
|
46
|
+
|
|
26
47
|
/**
|
|
27
48
|
* @typedef {object} Props
|
|
28
49
|
* @property {TextEditorBlockType} type Button type.
|
|
@@ -46,13 +67,8 @@
|
|
|
46
67
|
*/
|
|
47
68
|
const changeBlockType = async () => {
|
|
48
69
|
if (!editorStore.useRichText) {
|
|
49
|
-
const { textArea } = editorStore;
|
|
50
|
-
|
|
51
70
|
// The item is only clickable while the `<textarea>` is there
|
|
52
|
-
|
|
53
|
-
if (textArea) {
|
|
54
|
-
applyRawTextEdit(textArea, setBlockType(getRawTextState(textArea), type));
|
|
55
|
-
}
|
|
71
|
+
editRawText(editorStore.textArea, (state) => setBlockType(state, type));
|
|
56
72
|
|
|
57
73
|
return;
|
|
58
74
|
}
|
|
@@ -67,38 +83,18 @@
|
|
|
67
83
|
|
|
68
84
|
const [, headingLevel] = type.match(/^heading-(\d)$/) ?? [];
|
|
69
85
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
createHeadingNode(/** @type {HeadingTagType} */ (`h${headingLevel}`)),
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
86
|
+
const createNode = headingLevel
|
|
87
|
+
? () => createHeadingNode(/** @type {HeadingTagType} */ (`h${headingLevel}`))
|
|
88
|
+
: NODE_FACTORIES[type];
|
|
77
89
|
|
|
78
|
-
if (
|
|
90
|
+
if (createNode) {
|
|
79
91
|
editorStore.editor.update(() => {
|
|
80
|
-
setBlocksType(getSelection(),
|
|
92
|
+
setBlocksType(getSelection(), createNode);
|
|
81
93
|
});
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
if (type
|
|
85
|
-
editorStore.editor.dispatchCommand(
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (type === 'numbered-list') {
|
|
89
|
-
editorStore.editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (type === 'blockquote') {
|
|
93
|
-
editorStore.editor.update(() => {
|
|
94
|
-
setBlocksType(getSelection(), () => createQuoteNode());
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (type === 'code-block') {
|
|
99
|
-
editorStore.editor.update(() => {
|
|
100
|
-
setBlocksType(getSelection(), () => createCodeNode());
|
|
101
|
-
});
|
|
96
|
+
if (type in LIST_COMMANDS) {
|
|
97
|
+
editorStore.editor.dispatchCommand(LIST_COMMANDS[type], undefined);
|
|
102
98
|
}
|
|
103
99
|
};
|
|
104
100
|
</script>
|
|
@@ -9,8 +9,6 @@
|
|
|
9
9
|
* @typedef {object} Props
|
|
10
10
|
* @property {boolean} [disabled] Whether to disable the widget. An alias of the `aria-disabled`
|
|
11
11
|
* attribute.
|
|
12
|
-
* @property {boolean} [readonly] Whether to make the widget read-only. An alias of the
|
|
13
|
-
* `aria-readonly` attribute.
|
|
14
12
|
* @property {Snippet} [children] Primary slot content.
|
|
15
13
|
*/
|
|
16
14
|
|
|
@@ -19,8 +17,6 @@
|
|
|
19
17
|
*/
|
|
20
18
|
let {
|
|
21
19
|
/* eslint-disable prefer-const */
|
|
22
|
-
code = $bindable(''),
|
|
23
|
-
lang = $bindable('plain'),
|
|
24
20
|
disabled = false,
|
|
25
21
|
children,
|
|
26
22
|
...restProps
|
|
@@ -56,12 +52,6 @@
|
|
|
56
52
|
min-height: 40px;
|
|
57
53
|
background-color: var(--sui-tertiary-background-color);
|
|
58
54
|
}
|
|
59
|
-
@media (width < 768px) {
|
|
60
|
-
.wrapper :global([role=toolbar]) {
|
|
61
|
-
flex-wrap: wrap;
|
|
62
|
-
height: auto;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
55
|
.wrapper :global(.sui.menu-button) {
|
|
66
56
|
padding: 0 4px;
|
|
67
57
|
}
|
|
@@ -9,27 +9,17 @@ declare const ToolbarWrapper: import("svelte").Component<{
|
|
|
9
9
|
* attribute.
|
|
10
10
|
*/
|
|
11
11
|
disabled?: boolean | undefined;
|
|
12
|
-
/**
|
|
13
|
-
* Whether to make the widget read-only. An alias of the
|
|
14
|
-
* `aria-readonly` attribute.
|
|
15
|
-
*/
|
|
16
|
-
readonly?: boolean | undefined;
|
|
17
12
|
/**
|
|
18
13
|
* Primary slot content.
|
|
19
14
|
*/
|
|
20
15
|
children?: Snippet<[]> | undefined;
|
|
21
|
-
} & Record<string, any>, {}, "
|
|
16
|
+
} & Record<string, any>, {}, "">;
|
|
22
17
|
type Props = {
|
|
23
18
|
/**
|
|
24
19
|
* Whether to disable the widget. An alias of the `aria-disabled`
|
|
25
20
|
* attribute.
|
|
26
21
|
*/
|
|
27
22
|
disabled?: boolean | undefined;
|
|
28
|
-
/**
|
|
29
|
-
* Whether to make the widget read-only. An alias of the
|
|
30
|
-
* `aria-readonly` attribute.
|
|
31
|
-
*/
|
|
32
|
-
readonly?: boolean | undefined;
|
|
33
23
|
/**
|
|
34
24
|
* Primary slot content.
|
|
35
25
|
*/
|
|
@@ -44,11 +44,10 @@ export const getTableColumnsSize = (table) => {
|
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Creates a table cell with the given text content.
|
|
47
|
-
* @internal
|
|
48
47
|
* @param {string} textContent
|
|
49
48
|
* @returns {TableCellNode}
|
|
50
49
|
*/
|
|
51
|
-
|
|
50
|
+
const createTableCell = (textContent) => {
|
|
52
51
|
textContent = textContent.replace(/\\n/g, '\n');
|
|
53
52
|
|
|
54
53
|
const cell = createTableCellNode(TableCellHeaderStates.NO_STATUS);
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Internal base of `<PasswordInput>` and `<SecretInput>`: a text field whose value is masked, with a
|
|
4
|
+
Show/Hide button.
|
|
5
|
+
-->
|
|
6
|
+
<script>
|
|
7
|
+
import { _ } from '@sveltia/i18n';
|
|
8
|
+
import Button from '../button/button.svelte';
|
|
9
|
+
import Icon from '../icon/icon.svelte';
|
|
10
|
+
import TextInput from './text-input.svelte';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @import { Snippet } from 'svelte';
|
|
14
|
+
* @import { CommonEventHandlers, InputEventHandlers, TextInputProps } from '../../typedefs.js';
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {object} Props
|
|
19
|
+
* @property {'type' | 'css'} mask How to mask the value: `type` uses `type="password"`, while
|
|
20
|
+
* `css` uses `-webkit-text-security` so password managers don’t prompt to save the value.
|
|
21
|
+
* @property {string} [value] Input value.
|
|
22
|
+
* @property {Snippet} [visibilityIcon] Visibility icon slot content.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @type {TextInputProps & CommonEventHandlers & InputEventHandlers & Props & Record<string, any>}
|
|
27
|
+
*/
|
|
28
|
+
let {
|
|
29
|
+
/* eslint-disable prefer-const */
|
|
30
|
+
mask,
|
|
31
|
+
value = $bindable(),
|
|
32
|
+
flex = false,
|
|
33
|
+
monospace = true,
|
|
34
|
+
class: className,
|
|
35
|
+
hidden = false,
|
|
36
|
+
disabled = false,
|
|
37
|
+
readonly = false,
|
|
38
|
+
required = false,
|
|
39
|
+
invalid = false,
|
|
40
|
+
// Not rendered, but kept out of `restProps` so it isn’t spread onto the `<input>`
|
|
41
|
+
children,
|
|
42
|
+
visibilityIcon,
|
|
43
|
+
...restProps
|
|
44
|
+
/* eslint-enable prefer-const */
|
|
45
|
+
} = $props();
|
|
46
|
+
|
|
47
|
+
const id = $props.id();
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Reference to the `<input>` element.
|
|
51
|
+
* @type {HTMLInputElement | undefined}
|
|
52
|
+
*/
|
|
53
|
+
let inputElement = $state();
|
|
54
|
+
let show = $state(false);
|
|
55
|
+
|
|
56
|
+
const labels = $derived(
|
|
57
|
+
mask === 'type'
|
|
58
|
+
? {
|
|
59
|
+
show: '_sui.password_input.show_password',
|
|
60
|
+
hide: '_sui.password_input.hide_password',
|
|
61
|
+
}
|
|
62
|
+
: {
|
|
63
|
+
show: '_sui.secret_input.show_secret',
|
|
64
|
+
hide: '_sui.secret_input.hide_secret',
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
$effect(() => {
|
|
69
|
+
if (mask === 'type') {
|
|
70
|
+
inputElement?.setAttribute('type', show ? 'text' : 'password');
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<div
|
|
76
|
+
role="none"
|
|
77
|
+
class="sui {mask === 'type' ? 'password-input' : 'secret-input'} {className}"
|
|
78
|
+
class:flex
|
|
79
|
+
class:disabled
|
|
80
|
+
class:readonly
|
|
81
|
+
class:show={mask === 'css' && show}
|
|
82
|
+
{hidden}
|
|
83
|
+
>
|
|
84
|
+
<!-- With the `css` mask, the field is masked with CSS rather than `type="password"`, so opt out
|
|
85
|
+
of the features that would remember the secret, like autofill history and the keyboard’s learned
|
|
86
|
+
words -->
|
|
87
|
+
<TextInput
|
|
88
|
+
dir="ltr"
|
|
89
|
+
bind:element={inputElement}
|
|
90
|
+
{...mask === 'css' ? { autocomplete: 'off', autocapitalize: 'off', autocorrect: 'off' } : {}}
|
|
91
|
+
{...restProps}
|
|
92
|
+
{id}
|
|
93
|
+
bind:value
|
|
94
|
+
{...mask === 'type' ? { type: 'password' } : {}}
|
|
95
|
+
spellcheck="false"
|
|
96
|
+
{flex}
|
|
97
|
+
{monospace}
|
|
98
|
+
{hidden}
|
|
99
|
+
{disabled}
|
|
100
|
+
{readonly}
|
|
101
|
+
{required}
|
|
102
|
+
{invalid}
|
|
103
|
+
/>
|
|
104
|
+
<Button
|
|
105
|
+
iconic
|
|
106
|
+
disabled={disabled || readonly}
|
|
107
|
+
pressed={show}
|
|
108
|
+
aria-label={_(show ? labels.hide : labels.show)}
|
|
109
|
+
aria-controls={id}
|
|
110
|
+
onclick={() => {
|
|
111
|
+
show = !show;
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
{#snippet startIcon()}
|
|
115
|
+
{#if visibilityIcon}
|
|
116
|
+
{@render visibilityIcon()}
|
|
117
|
+
{:else}
|
|
118
|
+
<Icon name={show ? 'visibility_off' : 'visibility'} />
|
|
119
|
+
{/if}
|
|
120
|
+
{/snippet}
|
|
121
|
+
</Button>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<style>.password-input,
|
|
125
|
+
.secret-input {
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
margin: var(--sui-focus-ring-width);
|
|
129
|
+
min-width: var(--sui-textbox-singleline-min-width);
|
|
130
|
+
}
|
|
131
|
+
.password-input.flex:not([hidden]),
|
|
132
|
+
.secret-input.flex:not([hidden]) {
|
|
133
|
+
display: inline-flex;
|
|
134
|
+
width: -moz-available;
|
|
135
|
+
width: -webkit-fill-available;
|
|
136
|
+
width: stretch;
|
|
137
|
+
min-width: 0;
|
|
138
|
+
}
|
|
139
|
+
.password-input :global(.text-input),
|
|
140
|
+
.secret-input :global(.text-input) {
|
|
141
|
+
flex: auto;
|
|
142
|
+
margin: 0 !important;
|
|
143
|
+
width: 0;
|
|
144
|
+
min-width: 0 !important;
|
|
145
|
+
}
|
|
146
|
+
.password-input :global(input),
|
|
147
|
+
.secret-input :global(input) {
|
|
148
|
+
border-start-end-radius: 0;
|
|
149
|
+
border-end-end-radius: 0;
|
|
150
|
+
}
|
|
151
|
+
.password-input :global(button),
|
|
152
|
+
.secret-input :global(button) {
|
|
153
|
+
margin-block: 0;
|
|
154
|
+
margin-inline-end: 0;
|
|
155
|
+
flex: none;
|
|
156
|
+
margin-inline-start: -1px;
|
|
157
|
+
border-width: 1px;
|
|
158
|
+
border-color: var(--sui-textbox-border-color);
|
|
159
|
+
width: var(--sui-textbox-height);
|
|
160
|
+
aspect-ratio: 1/1;
|
|
161
|
+
}
|
|
162
|
+
.password-input :global(button:last-child),
|
|
163
|
+
.secret-input :global(button:last-child) {
|
|
164
|
+
border-start-start-radius: 0;
|
|
165
|
+
border-start-end-radius: 4px;
|
|
166
|
+
border-end-end-radius: 4px;
|
|
167
|
+
border-end-start-radius: 0;
|
|
168
|
+
}
|
|
169
|
+
.password-input :global(button) :global(.icon),
|
|
170
|
+
.secret-input :global(button) :global(.icon) {
|
|
171
|
+
font-size: var(--sui-font-size-xx-large);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.secret-input.show :global(input) {
|
|
175
|
+
-webkit-text-security: none;
|
|
176
|
+
}
|
|
177
|
+
.secret-input :global(input) {
|
|
178
|
+
-webkit-text-security: disc;
|
|
179
|
+
}</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export default MaskedInput;
|
|
2
|
+
type MaskedInput = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<TextInputProps & KeyboardEventHandlers & MouseEventHandlers & PointerEventHandlers & FocusEventHandlers & DragEventHandlers & InputEventHandlers & Props & Record<string, any>>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Internal base of `<PasswordInput>` and `<SecretInput>`: a text field whose value is masked, with a
|
|
8
|
+
* Show/Hide button.
|
|
9
|
+
*/
|
|
10
|
+
declare const MaskedInput: import("svelte").Component<TextInputProps & import("../../typedefs.js").KeyboardEventHandlers & import("../../typedefs.js").MouseEventHandlers & import("../../typedefs.js").PointerEventHandlers & import("../../typedefs.js").FocusEventHandlers & import("../../typedefs.js").DragEventHandlers & InputEventHandlers & {
|
|
11
|
+
/**
|
|
12
|
+
* How to mask the value: `type` uses `type="password"`, while
|
|
13
|
+
* `css` uses `-webkit-text-security` so password managers don’t prompt to save the value.
|
|
14
|
+
*/
|
|
15
|
+
mask: "type" | "css";
|
|
16
|
+
/**
|
|
17
|
+
* Input value.
|
|
18
|
+
*/
|
|
19
|
+
value?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Visibility icon slot content.
|
|
22
|
+
*/
|
|
23
|
+
visibilityIcon?: Snippet<[]> | undefined;
|
|
24
|
+
} & Record<string, any>, {}, "value">;
|
|
25
|
+
type Props = {
|
|
26
|
+
/**
|
|
27
|
+
* How to mask the value: `type` uses `type="password"`, while
|
|
28
|
+
* `css` uses `-webkit-text-security` so password managers don’t prompt to save the value.
|
|
29
|
+
*/
|
|
30
|
+
mask: "type" | "css";
|
|
31
|
+
/**
|
|
32
|
+
* Input value.
|
|
33
|
+
*/
|
|
34
|
+
value?: string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Visibility icon slot content.
|
|
37
|
+
*/
|
|
38
|
+
visibilityIcon?: Snippet<[]> | undefined;
|
|
39
|
+
};
|
|
40
|
+
import type { TextInputProps } from '../../typedefs.js';
|
|
41
|
+
import type { InputEventHandlers } from '../../typedefs.js';
|
|
42
|
+
import type { Snippet } from 'svelte';
|
|
@@ -9,7 +9,13 @@
|
|
|
9
9
|
* @param {number} step Step value.
|
|
10
10
|
* @returns {number} Number of fraction digits, `0` for an integer step.
|
|
11
11
|
*/
|
|
12
|
-
export const getMaximumFractionDigits = (step) =>
|
|
12
|
+
export const getMaximumFractionDigits = (step) => {
|
|
13
|
+
// A small step like `0.0000001` is stringified in exponent notation as `1e-7`
|
|
14
|
+
const [mantissa, exponent = '0'] = String(step).toLowerCase().split('e');
|
|
15
|
+
const digits = (mantissa.split('.')[1]?.length ?? 0) - Number(exponent);
|
|
16
|
+
|
|
17
|
+
return Math.max(digits, 0);
|
|
18
|
+
};
|
|
13
19
|
|
|
14
20
|
/**
|
|
15
21
|
* Parse the text entered in the field.
|