@sveltia/ui 0.11.1 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/package/components/button/button.svelte +4 -1
  2. package/package/components/button/button.svelte.d.ts +4 -4
  3. package/package/components/button/select-button-group.svelte.d.ts +4 -4
  4. package/package/components/button/select-button.svelte.d.ts +4 -4
  5. package/package/components/button/split-button.svelte +2 -5
  6. package/package/components/button/split-button.svelte.d.ts +4 -4
  7. package/package/components/calendar/calendar.svelte +1 -1
  8. package/package/components/checkbox/checkbox.svelte +2 -2
  9. package/package/components/checkbox/checkbox.svelte.d.ts +6 -6
  10. package/package/components/dialog/dialog.svelte +2 -2
  11. package/package/components/dialog/dialog.svelte.d.ts +2 -2
  12. package/package/components/dialog/prompt-dialog.svelte +7 -1
  13. package/package/components/dialog/prompt-dialog.svelte.d.ts +2 -0
  14. package/package/components/disclosure/disclosure.svelte +2 -2
  15. package/package/components/disclosure/disclosure.svelte.d.ts +2 -2
  16. package/package/components/drawer/drawer.svelte +2 -2
  17. package/package/components/drawer/drawer.svelte.d.ts +2 -2
  18. package/package/components/grid/grid-body.svelte +2 -2
  19. package/package/components/grid/grid.svelte.d.ts +2 -2
  20. package/package/components/icon/icon.svelte +6 -0
  21. package/package/components/listbox/listbox.svelte.d.ts +8 -8
  22. package/package/components/listbox/option-group.svelte +2 -2
  23. package/package/components/listbox/option-group.svelte.d.ts +2 -2
  24. package/package/components/menu/menu-button.svelte +0 -8
  25. package/package/components/menu/menu-button.svelte.d.ts +4 -4
  26. package/package/components/menu/menu-item-checkbox.svelte.d.ts +4 -4
  27. package/package/components/menu/menu-item-group.svelte +2 -2
  28. package/package/components/menu/menu-item-group.svelte.d.ts +2 -2
  29. package/package/components/menu/menu-item-radio.svelte.d.ts +4 -4
  30. package/package/components/menu/menu-item.svelte +1 -1
  31. package/package/components/menu/menu-item.svelte.d.ts +2 -2
  32. package/package/components/radio/radio-group.svelte.d.ts +4 -4
  33. package/package/components/radio/radio.svelte +2 -2
  34. package/package/components/radio/radio.svelte.d.ts +4 -4
  35. package/package/components/select/combobox.svelte +3 -3
  36. package/package/components/select/combobox.svelte.d.ts +4 -4
  37. package/package/components/select/select.svelte.d.ts +4 -4
  38. package/package/components/slider/slider.svelte +1 -1
  39. package/package/components/slider/slider.svelte.d.ts +8 -8
  40. package/package/components/switch/switch.svelte.d.ts +6 -6
  41. package/package/components/table/table-body.svelte +2 -2
  42. package/package/components/tabs/tab-list.svelte +1 -1
  43. package/package/components/text-editor/core.d.ts +2 -0
  44. package/package/components/text-editor/core.js +206 -0
  45. package/package/components/text-editor/index.d.ts +23 -0
  46. package/package/components/text-editor/index.js +102 -0
  47. package/package/components/text-editor/lexical-root.svelte +123 -0
  48. package/package/components/text-editor/lexical-root.svelte.d.ts +27 -0
  49. package/package/components/text-editor/text-editor.svelte +154 -0
  50. package/package/components/{text-field/markdown-editor.svelte.d.ts → text-editor/text-editor.svelte.d.ts} +16 -12
  51. package/package/components/text-editor/toolbar/editor-toolbar.svelte +150 -0
  52. package/package/components/text-editor/toolbar/editor-toolbar.svelte.d.ts +25 -0
  53. package/package/components/text-editor/toolbar/format-text-button.svelte +33 -0
  54. package/package/components/text-editor/toolbar/format-text-button.svelte.d.ts +23 -0
  55. package/package/components/text-editor/toolbar/insert-link-button.svelte +231 -0
  56. package/package/components/text-editor/toolbar/insert-link-button.svelte.d.ts +23 -0
  57. package/package/components/text-editor/toolbar/toggle-block-menu-item.svelte +83 -0
  58. package/package/components/text-editor/toolbar/toggle-block-menu-item.svelte.d.ts +23 -0
  59. package/package/components/text-field/number-input.svelte +2 -2
  60. package/package/components/text-field/number-input.svelte.d.ts +10 -10
  61. package/package/components/text-field/password-input.svelte +2 -2
  62. package/package/components/text-field/password-input.svelte.d.ts +4 -4
  63. package/package/components/text-field/search-bar.svelte +3 -3
  64. package/package/components/text-field/search-bar.svelte.d.ts +4 -4
  65. package/package/components/text-field/text-area.svelte +3 -0
  66. package/package/components/text-field/text-area.svelte.d.ts +4 -4
  67. package/package/components/text-field/text-input.svelte +2 -2
  68. package/package/components/text-field/text-input.svelte.d.ts +4 -4
  69. package/package/components/toast/toast.svelte +2 -2
  70. package/package/components/util/app-shell.svelte +56 -4
  71. package/package/components/util/modal.svelte +3 -3
  72. package/package/components/util/modal.svelte.d.ts +4 -4
  73. package/package/components/util/popup.svelte +2 -2
  74. package/package/index.d.ts +1 -2
  75. package/package/index.js +9 -4
  76. package/package/locales/en.d.ts +25 -7
  77. package/package/locales/en.js +25 -6
  78. package/package/locales/ja.d.ts +25 -7
  79. package/package/locales/ja.js +25 -6
  80. package/package/services/events.js +2 -2
  81. package/package/services/group.js +7 -6
  82. package/package/services/popup.js +2 -2
  83. package/package/styles/core.scss +51 -2
  84. package/package/styles/variables.scss +3 -1
  85. package/package/typedef.d.ts +48 -0
  86. package/package/typedef.js +36 -0
  87. package/package.json +22 -18
  88. package/package/components/text-field/markdown-editor.svelte +0 -141
  89. package/package/services/util.d.ts +0 -3
  90. package/package/services/util.js +0 -35
@@ -0,0 +1,123 @@
1
+ <script>
2
+ import { getContext, onMount } from 'svelte';
3
+
4
+ /**
5
+ * Whether to disable the widget. An alias of the `aria-disabled` attribute.
6
+ * @type {boolean}
7
+ */
8
+ export let disabled = false;
9
+ /**
10
+ * Whether to disable the widget. An alias of `aria-readonly` attribute.
11
+ * @type {boolean}
12
+ */
13
+ export let readonly = false;
14
+ /**
15
+ * Input value.
16
+ * @type {string | undefined}
17
+ */
18
+ export let value = undefined;
19
+
20
+ /**
21
+ * Text editor state.
22
+ * @type {TextEditorState}
23
+ */
24
+ const {
25
+ editor,
26
+ editorId,
27
+ selectionBlockType,
28
+ selectionInlineTypes,
29
+ useRichText,
30
+ hasConverterError,
31
+ } = getContext('state');
32
+
33
+ /**
34
+ * Reference to the Lexical editor root element.
35
+ * @type {HTMLElement | undefined}
36
+ */
37
+ let lexicalRoot = undefined;
38
+
39
+ $: editable = !(disabled || readonly);
40
+ $: $editor.setEditable(editable);
41
+
42
+ /**
43
+ * Update {@link value} and other state variables whenever the editor content is updated.
44
+ * @param {Event} event - `Update` custom event.
45
+ */
46
+ const onUpdate = (event) => {
47
+ if ($hasConverterError) {
48
+ return;
49
+ }
50
+
51
+ const { detail } = /** @type {CustomEvent} */ (event);
52
+ const newValue = detail.value;
53
+
54
+ if (value !== newValue) {
55
+ value = newValue;
56
+ }
57
+
58
+ $selectionBlockType = detail.selectionBlockType;
59
+ $selectionInlineTypes = detail.selectionInlineTypes;
60
+ };
61
+
62
+ /**
63
+ * Listen to `click` events on the editor. Ignore a click on a link.
64
+ * @param {MouseEvent} event - `click` event.
65
+ */
66
+ const onClick = (event) => {
67
+ if (/** @type {HTMLElement} */ (event.target)?.matches('a')) {
68
+ event.preventDefault();
69
+ }
70
+ };
71
+
72
+ onMount(() => {
73
+ if (lexicalRoot) {
74
+ $editor.setRootElement(lexicalRoot);
75
+ lexicalRoot.addEventListener('Update', onUpdate);
76
+ lexicalRoot.addEventListener('click', onClick);
77
+ }
78
+
79
+ return () => {
80
+ lexicalRoot?.removeEventListener('Update', onUpdate);
81
+ lexicalRoot?.removeEventListener('click', onClick);
82
+ };
83
+ });
84
+ </script>
85
+
86
+ <div
87
+ role="textbox"
88
+ aria-multiline="true"
89
+ aria-disabled={disabled}
90
+ aria-readonly={readonly}
91
+ class="lexical-root"
92
+ id="{$editorId}-lexical-root"
93
+ contenteditable={editable}
94
+ bind:this={lexicalRoot}
95
+ hidden={!$useRichText}
96
+ />
97
+
98
+ <style>.lexical-root {
99
+ border: 1px solid var(--sui-textbox-border-color);
100
+ border-radius: 0 0 var(--sui-textbox-border-radius) var(--sui-textbox-border-radius) !important;
101
+ padding: 16px;
102
+ min-height: 8em;
103
+ color: var(--sui-textbox-foreground-color);
104
+ background-color: var(--sui-textbox-background-color);
105
+ font-family: var(--sui-textbox-font-family);
106
+ font-size: var(--sui-textbox-font-size);
107
+ line-height: var(--sui-textbox-multiline-line-height);
108
+ }
109
+ .lexical-root:focus-visible {
110
+ outline: 0;
111
+ }
112
+ .lexical-root > :global(:first-child) {
113
+ margin-top: 0;
114
+ }
115
+ .lexical-root > :global(:last-child) {
116
+ margin-bottom: 0;
117
+ }
118
+ .lexical-root :global(strong.italic) {
119
+ font-style: italic;
120
+ }
121
+ .lexical-root :global([data-lexical-text="true"]) {
122
+ cursor: text;
123
+ }</style>
@@ -0,0 +1,27 @@
1
+ /** @typedef {typeof __propDef.props} LexicalRootProps */
2
+ /** @typedef {typeof __propDef.events} LexicalRootEvents */
3
+ /** @typedef {typeof __propDef.slots} LexicalRootSlots */
4
+ export default class LexicalRoot extends SvelteComponent<{
5
+ disabled?: boolean | undefined;
6
+ value?: string | undefined;
7
+ readonly?: boolean | undefined;
8
+ }, {
9
+ [evt: string]: CustomEvent<any>;
10
+ }, {}> {
11
+ }
12
+ export type LexicalRootProps = typeof __propDef.props;
13
+ export type LexicalRootEvents = typeof __propDef.events;
14
+ export type LexicalRootSlots = typeof __propDef.slots;
15
+ import { SvelteComponent } from "svelte";
16
+ declare const __propDef: {
17
+ props: {
18
+ disabled?: boolean | undefined;
19
+ value?: string | undefined;
20
+ readonly?: boolean | undefined;
21
+ };
22
+ events: {
23
+ [evt: string]: CustomEvent<any>;
24
+ };
25
+ slots: {};
26
+ };
27
+ export {};
@@ -0,0 +1,154 @@
1
+ <!--
2
+ @component
3
+ A rich text editor based on Lexical.
4
+ -->
5
+ <script>
6
+ import { generateElementId } from '@sveltia/utils/element';
7
+ import { onMount, setContext } from 'svelte';
8
+ import { _ } from 'svelte-i18n';
9
+ import { writable } from 'svelte/store';
10
+ import Alert from '../alert/alert.svelte';
11
+ import { blockButtonTypes, inlineButtonTypes } from './';
12
+ import {
13
+ convertMarkdown as convertMarkdownToLexical,
14
+ initEditor,
15
+ } from './core';
16
+ import LexicalRoot from './lexical-root.svelte';
17
+ import EditorToolbar from './toolbar/editor-toolbar.svelte';
18
+ import TextArea from '../text-field/text-area.svelte';
19
+ import Toast from '../toast/toast.svelte';
20
+
21
+ /**
22
+ * Make the text input container flexible.
23
+ * @type {boolean}
24
+ */
25
+ export let flex = false;
26
+ /**
27
+ * Whether to hide the widget. An alias of the `aria-hidden` attribute.
28
+ * @type {boolean | undefined}
29
+ */
30
+ export let hidden = undefined;
31
+ /**
32
+ * Whether to disable the widget. An alias of the `aria-disabled` attribute.
33
+ * @type {boolean}
34
+ */
35
+ export let disabled = false;
36
+ /**
37
+ * Whether to disable the widget. An alias of `aria-readonly` attribute.
38
+ * @type {boolean}
39
+ */
40
+ export let readonly = false;
41
+ /**
42
+ * Whether to mark the widget required. An alias of the `aria-required` attribute.
43
+ * @type {boolean}
44
+ */
45
+ export let required = false;
46
+ /**
47
+ * Whether to mark the widget invalid. An alias of the `aria-invalid` attribute.
48
+ * @type {boolean}
49
+ */
50
+ export let invalid = false;
51
+ /**
52
+ * Input value.
53
+ * @type {string | undefined}
54
+ */
55
+ export let value = undefined;
56
+ /**
57
+ * Enabled modes.
58
+ * @type {TextEditorMode[]}
59
+ */
60
+ export let modes = ['rich-text', 'plain-text'];
61
+ /**
62
+ * Enabled buttons.
63
+ * @type {(TextEditorBlockType | TextEditorInlineType)[]}
64
+ */
65
+ export let buttons = [...inlineButtonTypes, ...blockButtonTypes];
66
+
67
+ const editor = writable(initEditor());
68
+ const selectionBlockType = writable('paragraph');
69
+ const selectionInlineTypes = writable([]);
70
+ const editorId = writable(generateElementId('editor'));
71
+ const useRichText = writable(modes.includes('rich-text'));
72
+ const hasConverterError = writable(false);
73
+ let showConverterError = false;
74
+
75
+ /**
76
+ * Convert the Markdown {@link value} to Lexical nodes. Disable the rich text mode and restore the
77
+ * original value when there is an error while conversion.
78
+ */
79
+ const convertMarkdown = async () => {
80
+ const originalValue = value;
81
+
82
+ try {
83
+ // We should avoid an empty editor; there should be at least one `<p>`, so give it an empty
84
+ // string if the `value` is `undefined`
85
+ // @see https://github.com/facebook/lexical/issues/2308
86
+ await convertMarkdownToLexical($editor, value ?? '');
87
+ } catch {
88
+ $hasConverterError = true;
89
+ value = originalValue;
90
+ }
91
+ };
92
+
93
+ $: {
94
+ if ($hasConverterError) {
95
+ $useRichText = false;
96
+ showConverterError = true;
97
+ }
98
+ }
99
+
100
+ setContext(
101
+ 'state',
102
+ /** @type {TextEditorState} */ ({
103
+ editor,
104
+ editorId,
105
+ selectionBlockType,
106
+ selectionInlineTypes,
107
+ modes,
108
+ useRichText,
109
+ hasConverterError,
110
+ enabledButtons: buttons,
111
+ convertMarkdown,
112
+ }),
113
+ );
114
+
115
+ onMount(() => {
116
+ if ($useRichText) {
117
+ convertMarkdown();
118
+ }
119
+ });
120
+ </script>
121
+
122
+ <div role="none" class="sui text-editor" hidden={hidden || undefined} {...$$restProps}>
123
+ <EditorToolbar {disabled} {readonly} />
124
+ <LexicalRoot {disabled} {readonly} bind:value />
125
+ <TextArea
126
+ autoResize={true}
127
+ bind:value
128
+ {flex}
129
+ hidden={$useRichText || hidden}
130
+ {disabled}
131
+ {readonly}
132
+ {required}
133
+ {invalid}
134
+ />
135
+ </div>
136
+
137
+ {#if showConverterError}
138
+ <Toast bind:show={showConverterError}>
139
+ <Alert status="error">{$_('_sui.text_editor.converter_error')}</Alert>
140
+ </Toast>
141
+ {/if}
142
+
143
+ <style>.text-editor {
144
+ margin: var(--sui-focus-ring-width);
145
+ width: calc(100% - var(--sui-focus-ring-width) * 2);
146
+ }
147
+ .text-editor :global(.sui.text-area) {
148
+ margin: 0 !important;
149
+ width: 100% !important;
150
+ min-width: auto;
151
+ }
152
+ .text-editor :global(.sui.text-area) :global(textarea) {
153
+ border-radius: 0 0 var(--sui-textbox-border-radius) var(--sui-textbox-border-radius) !important;
154
+ }</style>
@@ -1,34 +1,38 @@
1
- /** @typedef {typeof __propDef.props} MarkdownEditorProps */
2
- /** @typedef {typeof __propDef.events} MarkdownEditorEvents */
3
- /** @typedef {typeof __propDef.slots} MarkdownEditorSlots */
4
- /** A Markdown text editor. */
5
- export default class MarkdownEditor extends SvelteComponent<{
1
+ /** @typedef {typeof __propDef.props} TextEditorProps */
2
+ /** @typedef {typeof __propDef.events} TextEditorEvents */
3
+ /** @typedef {typeof __propDef.slots} TextEditorSlots */
4
+ /** A rich text editor based on Lexical. */
5
+ export default class TextEditor extends SvelteComponent<{
6
6
  [x: string]: any;
7
- disabled?: boolean | undefined;
8
7
  invalid?: boolean | undefined;
9
- required?: boolean | undefined;
8
+ disabled?: boolean | undefined;
10
9
  value?: string | undefined;
11
10
  hidden?: boolean | undefined;
12
11
  readonly?: boolean | undefined;
13
12
  flex?: boolean | undefined;
13
+ required?: boolean | undefined;
14
+ modes?: TextEditorMode[] | undefined;
15
+ buttons?: (TextEditorInlineType | TextEditorBlockType)[] | undefined;
14
16
  }, {
15
17
  [evt: string]: CustomEvent<any>;
16
18
  }, {}> {
17
19
  }
18
- export type MarkdownEditorProps = typeof __propDef.props;
19
- export type MarkdownEditorEvents = typeof __propDef.events;
20
- export type MarkdownEditorSlots = typeof __propDef.slots;
20
+ export type TextEditorProps = typeof __propDef.props;
21
+ export type TextEditorEvents = typeof __propDef.events;
22
+ export type TextEditorSlots = typeof __propDef.slots;
21
23
  import { SvelteComponent } from "svelte";
22
24
  declare const __propDef: {
23
25
  props: {
24
26
  [x: string]: any;
25
- disabled?: boolean | undefined;
26
27
  invalid?: boolean | undefined;
27
- required?: boolean | undefined;
28
+ disabled?: boolean | undefined;
28
29
  value?: string | undefined;
29
30
  hidden?: boolean | undefined;
30
31
  readonly?: boolean | undefined;
31
32
  flex?: boolean | undefined;
33
+ required?: boolean | undefined;
34
+ modes?: TextEditorMode[] | undefined;
35
+ buttons?: (TextEditorInlineType | TextEditorBlockType)[] | undefined;
32
36
  };
33
37
  events: {
34
38
  [evt: string]: CustomEvent<any>;
@@ -0,0 +1,150 @@
1
+ <script>
2
+ import { getContext, tick } from 'svelte';
3
+ import { _ } from 'svelte-i18n';
4
+ import ButtonGroup from '../../button/button-group.svelte';
5
+ import Divider from '../../divider/divider.svelte';
6
+ import Spacer from '../../divider/spacer.svelte';
7
+ import Icon from '../../icon/icon.svelte';
8
+ import MenuButton from '../../menu/menu-button.svelte';
9
+ import MenuItemCheckbox from '../../menu/menu-item-checkbox.svelte';
10
+ import Menu from '../../menu/menu.svelte';
11
+ import {
12
+ availableButtons,
13
+ blockButtonTypes,
14
+ inlineButtonTypes,
15
+ } from '..';
16
+ import FormatTextButton from './format-text-button.svelte';
17
+ import InsertLinkButton from './insert-link-button.svelte';
18
+ import ToggleBlockMenuItem from './toggle-block-menu-item.svelte';
19
+ import Toolbar from '../../toolbar/toolbar.svelte';
20
+
21
+ /**
22
+ * Whether to disable the widget. An alias of the `aria-disabled` attribute.
23
+ * @type {boolean}
24
+ */
25
+ export let disabled = false;
26
+ /**
27
+ * Whether to disable the widget. An alias of `aria-readonly` attribute.
28
+ * @type {boolean}
29
+ */
30
+ export let readonly = false;
31
+
32
+ /**
33
+ * Text editor state.
34
+ * @type {TextEditorState}
35
+ */
36
+ const {
37
+ editorId,
38
+ selectionBlockType,
39
+ modes,
40
+ useRichText,
41
+ hasConverterError,
42
+ enabledButtons,
43
+ convertMarkdown,
44
+ } = getContext('state');
45
+
46
+ /**
47
+ * Enabled block level buttons.
48
+ */
49
+ $: blockLevelButtons = Array.from(
50
+ new Set(
51
+ /** @type {TextEditorBlockType[]} */ ([
52
+ 'paragraph', // Always needed
53
+ ...enabledButtons.filter((type) => blockButtonTypes.includes(/** @type {any} */ (type))),
54
+ ]),
55
+ ),
56
+ );
57
+
58
+ /**
59
+ * Enabled inline level buttons.
60
+ */
61
+ $: inlineLevelButtons = Array.from(
62
+ new Set(
63
+ /** @type {TextEditorInlineType[]} */ ([
64
+ ...enabledButtons.filter((type) => inlineButtonTypes.includes(/** @type {any} */ (type))),
65
+ ]),
66
+ ),
67
+ );
68
+ </script>
69
+
70
+ <div role="none" class="wrapper">
71
+ <Toolbar disabled={disabled || readonly} aria-label={$_('_sui.text_editor.text_editor')}>
72
+ <MenuButton
73
+ disabled={!$useRichText}
74
+ aria-label={$_('_sui.text_editor.show_text_style_options')}
75
+ aria-controls="{$editorId}-lexical-root"
76
+ >
77
+ <Icon
78
+ slot="start-icon"
79
+ name={availableButtons[$selectionBlockType]?.icon ?? 'format_paragraph'}
80
+ />
81
+ <Icon slot="end-icon" name="arrow_drop_down" class="small-arrow" />
82
+ <Menu slot="popup" aria-label={$_('_sui.text_editor.text_style_options')}>
83
+ {#each blockLevelButtons as type (type)}
84
+ <ToggleBlockMenuItem {type} />
85
+ {/each}
86
+ </Menu>
87
+ </MenuButton>
88
+ {#if inlineLevelButtons.length}
89
+ <Divider orientation="vertical" />
90
+ <ButtonGroup>
91
+ {#each inlineLevelButtons as type (type)}
92
+ {#if type === 'link'}
93
+ <InsertLinkButton />
94
+ {:else}
95
+ <FormatTextButton {type} />
96
+ {/if}
97
+ {/each}
98
+ </ButtonGroup>
99
+ {/if}
100
+ <Spacer flex />
101
+ {#if modes.length > 1}
102
+ <MenuButton
103
+ variant="ghost"
104
+ iconic
105
+ disabled={$hasConverterError}
106
+ popupPosition="bottom-right"
107
+ aria-label={$_('_sui.text_editor.show_edit_options')}
108
+ >
109
+ <Icon slot="start-icon" name="more_vert" />
110
+ <Menu slot="popup" aria-label={$_('_sui.text_editor.edit_options')}>
111
+ <MenuItemCheckbox
112
+ label={$_('_sui.text_editor.use_rich_text')}
113
+ bind:checked={$useRichText}
114
+ on:change={async () => {
115
+ // Wait for `$useRichText` to be updated
116
+ await tick();
117
+
118
+ if ($useRichText) {
119
+ convertMarkdown();
120
+ }
121
+ }}
122
+ />
123
+ </Menu>
124
+ </MenuButton>
125
+ {/if}
126
+ </Toolbar>
127
+ </div>
128
+
129
+ <style>.wrapper {
130
+ display: contents;
131
+ }
132
+ .wrapper :global([role="toolbar"]) {
133
+ position: sticky;
134
+ top: 0;
135
+ display: flex;
136
+ gap: 8px;
137
+ border-width: 1px 1px 0;
138
+ border-style: solid;
139
+ border-color: var(--sui-textbox-border-color);
140
+ border-radius: var(--sui-textbox-border-radius) var(--sui-textbox-border-radius) 0 0;
141
+ padding: 8px;
142
+ background-color: var(--sui-tertiary-background-color);
143
+ }
144
+ .wrapper :global(button) {
145
+ flex: none;
146
+ margin: 0 !important;
147
+ }
148
+ .wrapper :global(.sui.button-group) {
149
+ gap: 4px;
150
+ }</style>
@@ -0,0 +1,25 @@
1
+ /** @typedef {typeof __propDef.props} EditorToolbarProps */
2
+ /** @typedef {typeof __propDef.events} EditorToolbarEvents */
3
+ /** @typedef {typeof __propDef.slots} EditorToolbarSlots */
4
+ export default class EditorToolbar extends SvelteComponent<{
5
+ disabled?: boolean | undefined;
6
+ readonly?: boolean | undefined;
7
+ }, {
8
+ [evt: string]: CustomEvent<any>;
9
+ }, {}> {
10
+ }
11
+ export type EditorToolbarProps = typeof __propDef.props;
12
+ export type EditorToolbarEvents = typeof __propDef.events;
13
+ export type EditorToolbarSlots = typeof __propDef.slots;
14
+ import { SvelteComponent } from "svelte";
15
+ declare const __propDef: {
16
+ props: {
17
+ disabled?: boolean | undefined;
18
+ readonly?: boolean | undefined;
19
+ };
20
+ events: {
21
+ [evt: string]: CustomEvent<any>;
22
+ };
23
+ slots: {};
24
+ };
25
+ export {};
@@ -0,0 +1,33 @@
1
+ <script>
2
+ import { FORMAT_TEXT_COMMAND } from 'lexical';
3
+ import { getContext } from 'svelte';
4
+ import { _ } from 'svelte-i18n';
5
+ import Button from '../../button/button.svelte';
6
+ import Icon from '../../icon/icon.svelte';
7
+ import { availableButtons } from '..';
8
+
9
+ /**
10
+ * Button type.
11
+ * @type {TextEditorFormatType}
12
+ */
13
+ export let type;
14
+
15
+ /**
16
+ * Text editor state.
17
+ * @type {TextEditorState}
18
+ */
19
+ const { editor, editorId, selectionInlineTypes, useRichText } = getContext('state');
20
+ </script>
21
+
22
+ <Button
23
+ iconic
24
+ aria-label={$_(`_sui.text_editor.${availableButtons[type].labelKey}`)}
25
+ aria-controls="{$editorId}-lexical-root"
26
+ disabled={!$useRichText}
27
+ pressed={$selectionInlineTypes.includes(type)}
28
+ on:click={() => {
29
+ $editor.dispatchCommand(FORMAT_TEXT_COMMAND, type);
30
+ }}
31
+ >
32
+ <Icon slot="start-icon" name={availableButtons[type].icon} />
33
+ </Button>
@@ -0,0 +1,23 @@
1
+ /** @typedef {typeof __propDef.props} FormatTextButtonProps */
2
+ /** @typedef {typeof __propDef.events} FormatTextButtonEvents */
3
+ /** @typedef {typeof __propDef.slots} FormatTextButtonSlots */
4
+ export default class FormatTextButton extends SvelteComponent<{
5
+ type: TextEditorFormatType;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type FormatTextButtonProps = typeof __propDef.props;
11
+ export type FormatTextButtonEvents = typeof __propDef.events;
12
+ export type FormatTextButtonSlots = typeof __propDef.slots;
13
+ import { SvelteComponent } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ type: TextEditorFormatType;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ };
23
+ export {};