@widgetic/design-system 0.5.15 → 0.5.17
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 +167 -0
- package/dist/components/CopyableHeader.svelte +25 -11
- package/dist/components/CopyableHeader.svelte.d.ts +4 -0
- package/dist/components/EmptyState.svelte +1 -1
- package/dist/components/PasswordInput.svelte +2 -2
- package/dist/components/WScrollArea.svelte +2 -2
- package/dist/components/ic/browser/BrowserInputController.svelte +2 -2
- package/dist/components/index.d.ts +1 -0
- package/dist/components/modals/ActionModal.svelte +3 -0
- package/dist/components/modals/ActionModal.svelte.d.ts +1 -0
- package/dist/components/modals/BaseModal.svelte +4 -2
- package/dist/components/modals/BaseModal.svelte.d.ts +1 -0
- package/dist/components/modals/NewItemDialog.svelte +48 -30
- package/dist/components/modals/NewItemDialog.svelte.d.ts +3 -0
- package/dist/components/modals/Portal.svelte +9 -1
- package/dist/components/modals/README.md +34 -1
- package/dist/components/modals/RenameDialog.svelte +29 -9
- package/dist/components/modals/RenameDialog.svelte.d.ts +3 -0
- package/dist/components/modals/messages.d.ts +39 -0
- package/dist/components/modals/messages.js +10 -0
- package/dist/components/navigation/Breadcrumbs.svelte +30 -17
- package/dist/components/navigation/Breadcrumbs.svelte.d.ts +4 -0
- package/dist/components/navigation/types.d.ts +8 -0
- package/dist/components/pdf/PDFViewer.svelte +17 -8
- package/dist/components/pdf/PDFViewer.svelte.d.ts +5 -0
- package/dist/components/search-input/SearchInput.svelte +3 -3
- package/dist/components/shad-editor/colorpicker.svelte +4 -1
- package/dist/components/shad-editor/custom/Extentions/ImageExtention.d.ts +20 -1
- package/dist/components/shad-editor/custom/Extentions/ImageExtention.js +4 -1
- package/dist/components/shad-editor/custom/code-extended.svelte +4 -2
- package/dist/components/shad-editor/custom/image-extended-component.svelte +54 -32
- package/dist/components/shad-editor/editor.css +5 -5
- package/dist/components/shad-editor/i18n/context.d.ts +6 -0
- package/dist/components/shad-editor/i18n/context.js +11 -0
- package/dist/components/shad-editor/i18n/index.d.ts +8 -0
- package/dist/components/shad-editor/i18n/index.js +11 -0
- package/dist/components/shad-editor/i18n/messages.d.ts +109 -0
- package/dist/components/shad-editor/i18n/messages.js +116 -0
- package/dist/components/shad-editor/icons/block-quote.svelte +3 -1
- package/dist/components/shad-editor/icons/bold.svelte +3 -1
- package/dist/components/shad-editor/icons/buttle-list.svelte +3 -1
- package/dist/components/shad-editor/icons/code.svelte +3 -1
- package/dist/components/shad-editor/icons/highlighter.svelte +5 -3
- package/dist/components/shad-editor/icons/image.svelte +7 -5
- package/dist/components/shad-editor/icons/italic.svelte +3 -1
- package/dist/components/shad-editor/icons/link.svelte +8 -6
- package/dist/components/shad-editor/icons/ordered-list.svelte +3 -1
- package/dist/components/shad-editor/icons/quickcolor.svelte +24 -22
- package/dist/components/shad-editor/icons/redo.svelte +3 -1
- package/dist/components/shad-editor/icons/search-replace.svelte +16 -14
- package/dist/components/shad-editor/icons/strikethrough.svelte +3 -1
- package/dist/components/shad-editor/icons/subscript.svelte +3 -1
- package/dist/components/shad-editor/icons/superscript.svelte +3 -1
- package/dist/components/shad-editor/icons/table.svelte +21 -19
- package/dist/components/shad-editor/icons/task-list.svelte +3 -1
- package/dist/components/shad-editor/icons/text.svelte +13 -11
- package/dist/components/shad-editor/icons/textalign.svelte +11 -9
- package/dist/components/shad-editor/icons/textcolor.svelte +5 -3
- package/dist/components/shad-editor/icons/underline.svelte +3 -1
- package/dist/components/shad-editor/icons/undo.svelte +3 -1
- package/dist/components/shad-editor/index.d.ts +1 -0
- package/dist/components/shad-editor/index.js +2 -0
- package/dist/components/shad-editor/shad-editor.svelte +32 -3
- package/dist/components/shad-editor/shad-editor.svelte.d.ts +12 -0
- package/dist/components/textDirection.d.ts +91 -0
- package/dist/components/textDirection.js +99 -0
- package/dist/components/toast/ToasterModal.svelte +49 -14
- package/dist/components/toast/ToasterModal.svelte.d.ts +9 -2
- package/dist/components/toast/toasterRoots.d.ts +23 -0
- package/dist/components/toast/toasterRoots.js +36 -0
- package/dist/components/ui/alert/index.d.ts +2 -2
- package/dist/components/ui/alert/index.js +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +1 -1
- package/dist/components/ui/calendar/calendar-next-button.svelte +21 -4
- package/dist/components/ui/calendar/calendar-next-button.svelte.d.ts +9 -2
- package/dist/components/ui/calendar/calendar-prev-button.svelte +21 -4
- package/dist/components/ui/calendar/calendar-prev-button.svelte.d.ts +9 -2
- package/dist/components/ui/calendar/calendar.svelte +18 -6
- package/dist/components/ui/calendar/calendar.svelte.d.ts +6 -1
- package/dist/components/ui/command/command-input.svelte +1 -1
- package/dist/components/ui/command/command-shortcut.svelte +1 -1
- package/dist/components/ui/dialog/dialog-content.svelte +5 -2
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +1 -0
- package/dist/components/ui/dialog/dialog-header.svelte +1 -1
- package/dist/components/ui/drawer/drawer-header.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +2 -2
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +6 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +2 -2
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +7 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
- package/dist/components/ui/hover-card/hover-card-content.svelte +6 -0
- package/dist/components/ui/input-otp/input-otp-slot.svelte +1 -1
- package/dist/components/ui/popover/popover-content.svelte +6 -0
- package/dist/components/ui/progress/progress.svelte +2 -2
- package/dist/components/ui/range-calendar/range-calendar-cell.svelte +1 -1
- package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +21 -4
- package/dist/components/ui/range-calendar/range-calendar-next-button.svelte.d.ts +9 -2
- package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +21 -4
- package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte.d.ts +9 -2
- package/dist/components/ui/range-calendar/range-calendar.svelte +18 -6
- package/dist/components/ui/range-calendar/range-calendar.svelte.d.ts +7 -2
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +1 -1
- package/dist/components/ui/scroll-area/scroll-area.svelte +6 -1
- package/dist/components/ui/select/select-content.svelte +6 -0
- package/dist/components/ui/select/select-group-heading.svelte +1 -1
- package/dist/components/ui/select/select-item.svelte +2 -2
- package/dist/components/ui/slider/slider.svelte +6 -0
- package/dist/components/ui/switch/switch.svelte +1 -1
- package/dist/components/ui/table/table-cell.svelte +1 -1
- package/dist/components/ui/table/table-head.svelte +1 -1
- package/dist/components/ui/tooltip/tooltip-content.svelte +6 -0
- package/dist/i18n/audit/catalogUsage.d.ts +36 -0
- package/dist/i18n/audit/catalogUsage.js +58 -0
- package/dist/i18n/audit/designSystemWords.d.ts +47 -0
- package/dist/i18n/audit/designSystemWords.js +137 -0
- package/dist/i18n/audit/hardCodedText.d.ts +40 -0
- package/dist/i18n/audit/hardCodedText.js +27 -0
- package/dist/i18n/audit/index.d.ts +19 -0
- package/dist/i18n/audit/index.js +19 -0
- package/dist/i18n/audit/messageCalls.d.ts +34 -0
- package/dist/i18n/audit/messageCalls.js +89 -0
- package/dist/i18n/audit/syntaxTree.d.ts +33 -0
- package/dist/i18n/audit/syntaxTree.js +90 -0
- package/dist/i18n/audit/visibleText.d.ts +57 -0
- package/dist/i18n/audit/visibleText.js +252 -0
- package/dist/i18n/createI18n.d.ts +63 -0
- package/dist/i18n/createI18n.js +72 -0
- package/dist/i18n/direction.d.ts +27 -0
- package/dist/i18n/direction.js +89 -0
- package/dist/i18n/index.d.ts +17 -0
- package/dist/i18n/index.js +16 -0
- package/dist/i18n/localeDate.d.ts +34 -0
- package/dist/i18n/localeDate.js +104 -0
- package/dist/i18n/splitMessages.d.ts +21 -0
- package/dist/i18n/splitMessages.js +33 -0
- package/dist/i18n/translator.d.ts +61 -0
- package/dist/i18n/translator.js +337 -0
- package/dist/rtl/audit/auditPhysicalPlacement.d.ts +36 -0
- package/dist/rtl/audit/auditPhysicalPlacement.js +58 -0
- package/dist/rtl/audit/index.d.ts +14 -0
- package/dist/rtl/audit/index.js +14 -0
- package/dist/rtl/audit/physicalPlacement.d.ts +64 -0
- package/dist/rtl/audit/physicalPlacement.js +444 -0
- package/dist/shad-editor/index.d.ts +1 -1
- package/dist/shad-editor/index.js +1 -1
- package/dist/styles/global.css +4 -4
- package/dist/utils/fillMessage.d.ts +8 -0
- package/dist/utils/fillMessage.js +10 -0
- package/dist/utils/itemName.d.ts +17 -0
- package/dist/utils/itemName.js +41 -0
- package/package.json +18 -1
|
@@ -22,6 +22,7 @@ The `ActionModal` component is a reusable confirmation modal that can be used ac
|
|
|
22
22
|
| `message` | string | `''` | Custom message for the modal (autogenerated if empty) |
|
|
23
23
|
| `confirmLabel` | string | `'Confirm'` | Label for the confirm button |
|
|
24
24
|
| `cancelLabel` | string | `'Cancel'` | Label for the cancel button |
|
|
25
|
+
| `closeLabel` | string | `'Close modal'` | The words a screen reader says for the close button |
|
|
25
26
|
| `width` | string | `'410px'` | Width of the modal |
|
|
26
27
|
| `height` | string | `'168px'` | Height of the modal |
|
|
27
28
|
| `modalId` | string | `'delete-confirmation-modal'` | ID for targeting the modal |
|
|
@@ -96,4 +97,36 @@ You can provide custom title and message for specific contexts:
|
|
|
96
97
|
confirmLabel="Delete Permanently"
|
|
97
98
|
on:confirm={handleDelete}
|
|
98
99
|
/>
|
|
99
|
-
```
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Words in another language
|
|
103
|
+
|
|
104
|
+
Every word a visitor can see or hear is a prop with an English default, so a page that shows the components in
|
|
105
|
+
another language passes its own words and nothing else changes.
|
|
106
|
+
|
|
107
|
+
| Component | Props with words |
|
|
108
|
+
|-----------|------------------|
|
|
109
|
+
| `BaseModal`, `ActionModal`, `RenameDialog`, `NewItemDialog` | `closeLabel` (screen reader name of the close button) |
|
|
110
|
+
| `ActionModal`, `RenameDialog`, `NewItemDialog` | `confirmLabel`, `cancelLabel` |
|
|
111
|
+
| `RenameDialog` | `messages`: `invalidTitle`, `enterName`, `enterDifferentName`, `enterValidName`, `tooShort`, `tooLong` (`{max}`), `renamed` (`{name}`), `failed` |
|
|
112
|
+
| `NewItemDialog` | `messages`: `invalidTitle`, `required`, `invalidCharacters`, `tooLong` (`{max}`). The English defaults are built from `itemType` ("Folder name is required"). |
|
|
113
|
+
| `Breadcrumbs` | `backLabel`, `forwardLabel`, `rootLabel`, `breadcrumbLabel` |
|
|
114
|
+
| `PDFViewer` | `loadingLabel`, `failedLabel`, `pageLabel` (`{page}`, `{total}`), `previousPageLabel`, `nextPageLabel` |
|
|
115
|
+
| `ToasterModal` (`components/toast`) | `containerAriaLabel` (the region that holds the toasts, "Notifications"; the library adds the key that moves focus to it), `closeButtonAriaLabel` ("Close toast"). The title and description of a toast are the words of whoever calls `showToast`. |
|
|
116
|
+
|
|
117
|
+
A key of `messages` that is left out keeps its English text. A message can hold the values named next to it in
|
|
118
|
+
curly braces: `tooLong: 'Der Name darf höchstens {max} Zeichen haben'`.
|
|
119
|
+
|
|
120
|
+
```svelte
|
|
121
|
+
<RenameDialog
|
|
122
|
+
bind:isOpen
|
|
123
|
+
itemName="Reisefotos"
|
|
124
|
+
confirmLabel="Umbenennen"
|
|
125
|
+
cancelLabel="Abbrechen"
|
|
126
|
+
closeLabel="Dialog schließen"
|
|
127
|
+
messages={{ enterName: 'Bitte einen Namen eingeben', tooLong: 'Höchstens {max} Zeichen' }}
|
|
128
|
+
/>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`NewItemDialog` accepts names made of letters, numbers and spaces **of any script** ("Ordner für Müller",
|
|
132
|
+
"写真", "Фото 2024"). Punctuation and symbols are still refused.
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
// import { toast } from '../ui/sonner';
|
|
8
8
|
import { showToast } from '../toast';
|
|
9
9
|
import BaseModal from './BaseModal.svelte';
|
|
10
|
+
// Words of the dialog and the helper that puts values into them
|
|
11
|
+
import type { RenameDialogMessages } from './messages';
|
|
12
|
+
import { fillMessage } from '../../utils/fillMessage';
|
|
10
13
|
|
|
11
14
|
// Props
|
|
12
15
|
let className = '';
|
|
@@ -21,6 +24,10 @@
|
|
|
21
24
|
export let placeholder = '';
|
|
22
25
|
export let confirmLabel = 'Rename';
|
|
23
26
|
export let cancelLabel = 'Cancel';
|
|
27
|
+
// The words a screen reader says for the close button (see BaseModal)
|
|
28
|
+
export let closeLabel = 'Close modal';
|
|
29
|
+
// The words of the errors and toasts; a key that is left out keeps its English text (see ./messages)
|
|
30
|
+
export let messages: Partial<RenameDialogMessages> = {};
|
|
24
31
|
export let width = '410px';
|
|
25
32
|
export let height = '168px';
|
|
26
33
|
export let target: string = 'rename-dialog'; // target for Portal
|
|
@@ -59,6 +66,18 @@
|
|
|
59
66
|
// Computed placeholder based on itemType
|
|
60
67
|
$: computedPlaceholder = placeholder || `${itemType} name...`;
|
|
61
68
|
|
|
69
|
+
// The words of the errors and toasts: the page's own, or English
|
|
70
|
+
$: text = {
|
|
71
|
+
invalidTitle: messages.invalidTitle ?? 'Invalid name',
|
|
72
|
+
enterName: messages.enterName ?? 'Please enter a name',
|
|
73
|
+
enterDifferentName: messages.enterDifferentName ?? 'Please enter a different name',
|
|
74
|
+
enterValidName: messages.enterValidName ?? 'Please enter a valid name',
|
|
75
|
+
tooShort: messages.tooShort ?? 'Name must be at least 1 character long',
|
|
76
|
+
tooLong: fillMessage(messages.tooLong ?? 'Name must be {max} characters or less', { max: maxLength }),
|
|
77
|
+
renamed: messages.renamed ?? 'Successfully renamed to {name}',
|
|
78
|
+
failed: messages.failed ?? 'Failed to rename item'
|
|
79
|
+
};
|
|
80
|
+
|
|
62
81
|
// Function to focus and select the input text
|
|
63
82
|
async function focusAndSelectInput() {
|
|
64
83
|
// Wait for the DOM to update
|
|
@@ -95,17 +114,17 @@
|
|
|
95
114
|
try {
|
|
96
115
|
// Validate input
|
|
97
116
|
if (!inputValue.trim() || inputValue.length < 1) {
|
|
98
|
-
showToast('error',
|
|
117
|
+
showToast('error', text.invalidTitle, { description: text.tooShort });
|
|
99
118
|
return;
|
|
100
119
|
}
|
|
101
120
|
|
|
102
121
|
if (inputValue.length > maxLength) {
|
|
103
|
-
showToast('error',
|
|
122
|
+
showToast('error', text.invalidTitle, { description: text.tooLong });
|
|
104
123
|
return;
|
|
105
124
|
}
|
|
106
125
|
|
|
107
126
|
if (inputValue === itemName) {
|
|
108
|
-
showToast('error',
|
|
127
|
+
showToast('error', text.invalidTitle, { description: text.enterDifferentName });
|
|
109
128
|
return;
|
|
110
129
|
}
|
|
111
130
|
|
|
@@ -124,17 +143,17 @@
|
|
|
124
143
|
// with a more generic approach
|
|
125
144
|
try {
|
|
126
145
|
// Simulate success
|
|
127
|
-
showToast('success',
|
|
146
|
+
showToast('success', fillMessage(text.renamed, { name: inputValue }));
|
|
128
147
|
dispatch('rename', { itemId, newName: inputValue, oldName: itemName });
|
|
129
148
|
isOpen = false;
|
|
130
149
|
} catch (error) {
|
|
131
150
|
console.error('Error during rename:', error);
|
|
132
|
-
showToast('error',
|
|
151
|
+
showToast('error', text.failed);
|
|
133
152
|
}
|
|
134
153
|
}
|
|
135
154
|
} catch (error) {
|
|
136
155
|
console.error('Error during rename:', error);
|
|
137
|
-
showToast('error',
|
|
156
|
+
showToast('error', text.failed);
|
|
138
157
|
}
|
|
139
158
|
}
|
|
140
159
|
|
|
@@ -172,6 +191,7 @@
|
|
|
172
191
|
width={width}
|
|
173
192
|
height={height}
|
|
174
193
|
titlePadding="small"
|
|
194
|
+
{closeLabel}
|
|
175
195
|
{modalType}
|
|
176
196
|
{modalData}
|
|
177
197
|
on:restore={handleRestore}
|
|
@@ -224,9 +244,9 @@
|
|
|
224
244
|
/>
|
|
225
245
|
{#if !isValid && hasAttemptedSubmit}
|
|
226
246
|
<div class="text-xs text-[hsl(var(--error))] mt-1">
|
|
227
|
-
{inputValue.trim().length === 0 ?
|
|
228
|
-
inputValue === itemName ?
|
|
229
|
-
|
|
247
|
+
{inputValue.trim().length === 0 ? text.enterName :
|
|
248
|
+
inputValue === itemName ? text.enterDifferentName :
|
|
249
|
+
text.enterValidName}
|
|
230
250
|
</div>
|
|
231
251
|
{/if}
|
|
232
252
|
</div>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenameDialogMessages } from './messages';
|
|
1
2
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
3
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
4
|
$$bindings?: Bindings;
|
|
@@ -22,6 +23,8 @@ declare const RenameDialog: $$__sveltets_2_IsomorphicComponent<{
|
|
|
22
23
|
placeholder?: string;
|
|
23
24
|
confirmLabel?: string;
|
|
24
25
|
cancelLabel?: string;
|
|
26
|
+
closeLabel?: string;
|
|
27
|
+
messages?: Partial<RenameDialogMessages>;
|
|
25
28
|
width?: string;
|
|
26
29
|
height?: string;
|
|
27
30
|
target?: string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words the dialogs say besides their title, placeholder and button labels.
|
|
3
|
+
*
|
|
4
|
+
* Every key is optional: a key that is left out keeps its English text. A message can hold named values in curly
|
|
5
|
+
* braces, for example `Name must be {max} characters or less`; the dialog says which ones it fills in (see
|
|
6
|
+
* `fillMessage` in utils).
|
|
7
|
+
* A page that shows the dialogs in another language passes its own words, for example
|
|
8
|
+
* `<RenameDialog messages={{ enterName: 'Bitte einen Namen eingeben' }} />`.
|
|
9
|
+
*/
|
|
10
|
+
/** Words of RenameDialog. */
|
|
11
|
+
export interface RenameDialogMessages {
|
|
12
|
+
/** Heading of the toast shown for a name that cannot be used. */
|
|
13
|
+
invalidTitle: string;
|
|
14
|
+
/** Under the field when it is empty. */
|
|
15
|
+
enterName: string;
|
|
16
|
+
/** Under the field and in the toast when the name has not changed. */
|
|
17
|
+
enterDifferentName: string;
|
|
18
|
+
/** Under the field when the name cannot be used for another reason. */
|
|
19
|
+
enterValidName: string;
|
|
20
|
+
/** Toast text for an empty name. */
|
|
21
|
+
tooShort: string;
|
|
22
|
+
/** Toast text for a name that is too long. Values: `{max}`, the longest name allowed. */
|
|
23
|
+
tooLong: string;
|
|
24
|
+
/** Toast when the dialog did the rename itself. Values: `{name}`, the new name. */
|
|
25
|
+
renamed: string;
|
|
26
|
+
/** Toast when the dialog did the rename itself and it failed. */
|
|
27
|
+
failed: string;
|
|
28
|
+
}
|
|
29
|
+
/** Words of NewItemDialog. The English defaults are built from the dialog's `itemType` ("Folder name is required"). */
|
|
30
|
+
export interface NewItemDialogMessages {
|
|
31
|
+
/** Heading of the toast shown for a name that cannot be used. */
|
|
32
|
+
invalidTitle: string;
|
|
33
|
+
/** Under the field when it is empty. */
|
|
34
|
+
required: string;
|
|
35
|
+
/** Under the field when the name has a character the dialog does not accept. */
|
|
36
|
+
invalidCharacters: string;
|
|
37
|
+
/** Under the field and in the toast when the name is too long. Values: `{max}`, the longest name allowed. */
|
|
38
|
+
tooLong: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words the dialogs say besides their title, placeholder and button labels.
|
|
3
|
+
*
|
|
4
|
+
* Every key is optional: a key that is left out keeps its English text. A message can hold named values in curly
|
|
5
|
+
* braces, for example `Name must be {max} characters or less`; the dialog says which ones it fills in (see
|
|
6
|
+
* `fillMessage` in utils).
|
|
7
|
+
* A page that shows the dialogs in another language passes its own words, for example
|
|
8
|
+
* `<RenameDialog messages={{ enterName: 'Bitte einen Namen eingeben' }} />`.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
import { IconArrowLeft, IconArrowRight } from '@tabler/icons-svelte';
|
|
13
13
|
|
|
14
14
|
// Types Import
|
|
15
|
-
import type { BreadcrumbsProps } from './types.
|
|
15
|
+
import type { BreadcrumbsProps } from './types.js';
|
|
16
|
+
import { dirForUserText, useTextDirection } from '../textDirection.js';
|
|
16
17
|
|
|
17
18
|
// Environment Import
|
|
18
19
|
// import { browser } from '$app/environment';
|
|
@@ -36,6 +37,11 @@
|
|
|
36
37
|
export let showNavigationButtons: BreadcrumbsProps['showNavigationButtons'] = true;
|
|
37
38
|
export let canGoBack: BreadcrumbsProps['canGoBack'] = false;
|
|
38
39
|
export let canGoForward: BreadcrumbsProps['canGoForward'] = false;
|
|
40
|
+
// words (tooltips and screen readers): a page that shows this in another language passes its own
|
|
41
|
+
export let backLabel: string = 'Back';
|
|
42
|
+
export let forwardLabel: string = 'Forward';
|
|
43
|
+
export let rootLabel: string = 'File browser';
|
|
44
|
+
export let breadcrumbLabel: string = 'breadcrumb';
|
|
39
45
|
// event handlers
|
|
40
46
|
export let onNavigate: BreadcrumbsProps['onNavigate'] = () => {};
|
|
41
47
|
export let onBack: BreadcrumbsProps['onBack'] = () => {};
|
|
@@ -43,6 +49,11 @@
|
|
|
43
49
|
// debug settings
|
|
44
50
|
export let showDebugVisualizer: boolean = false;
|
|
45
51
|
|
|
52
|
+
// A name a visitor wrote keeps a direction of its own on a right to left screen (a Latin folder name reads left to
|
|
53
|
+
// right inside it); on a left to right screen no attribute is written and nothing changes.
|
|
54
|
+
const textDirection = useTextDirection();
|
|
55
|
+
$: nameDirection = dirForUserText($textDirection);
|
|
56
|
+
|
|
46
57
|
/***
|
|
47
58
|
* COMPONENT STATE VARIABLES
|
|
48
59
|
**/
|
|
@@ -99,7 +110,7 @@
|
|
|
99
110
|
navButtons: showNavigationButtons
|
|
100
111
|
? navElement.querySelector('.nav-buttons')?.getBoundingClientRect()
|
|
101
112
|
: null,
|
|
102
|
-
rightContent: containerElement.querySelector('.pr-5, .right-content')?.getBoundingClientRect(),
|
|
113
|
+
rightContent: containerElement.querySelector('.pe-5, .pr-5, .right-content')?.getBoundingClientRect(),
|
|
103
114
|
breadcrumbs: breadcrumbsContainer.getBoundingClientRect()
|
|
104
115
|
};
|
|
105
116
|
|
|
@@ -179,7 +190,7 @@
|
|
|
179
190
|
<nav
|
|
180
191
|
bind:this={navElement}
|
|
181
192
|
bind:clientHeight
|
|
182
|
-
aria-label=
|
|
193
|
+
aria-label={breadcrumbLabel}
|
|
183
194
|
class="{className ? className + ' ' : ''}breadcrumbs-component flex items-center widgetic-colors h-[56px] bg-white border-b relative w-full"
|
|
184
195
|
style={style}
|
|
185
196
|
>
|
|
@@ -192,13 +203,14 @@
|
|
|
192
203
|
type="button"
|
|
193
204
|
class="breadcrumbs-nav-button inline-flex items-center justify-center w-6 h-6 border-0 bg-transparent p-0 focus:outline-none"
|
|
194
205
|
style="cursor: {canGoBack && !isLoading ? 'pointer' : 'default'}; opacity: {canGoBack && !isLoading ? 1 : 0.35};"
|
|
206
|
+
aria-label={backLabel}
|
|
195
207
|
aria-disabled={!canGoBack || isLoading}
|
|
196
208
|
on:mouseenter={() => { showBackTooltip = true; }}
|
|
197
209
|
on:mouseleave={() => { showBackTooltip = false; }}
|
|
198
210
|
on:click={() => { if (!isLoading) onBack(); }}
|
|
199
211
|
>
|
|
200
212
|
<IconArrowLeft
|
|
201
|
-
class="w-6 h-6 text-[hsl(var(--grey6))]"
|
|
213
|
+
class="w-6 h-6 text-[hsl(var(--grey6))] rtl:-scale-x-100"
|
|
202
214
|
style="min-width: 24px; min-height: 24px;"
|
|
203
215
|
/>
|
|
204
216
|
</button>
|
|
@@ -207,7 +219,7 @@
|
|
|
207
219
|
otherwise clips the tooltip at the header's bottom edge. -->
|
|
208
220
|
<Tooltip.Portal>
|
|
209
221
|
<Tooltip.Content side="bottom" sideOffset={6} class="bg-[hsl(var(--dark))] text-white caption px-2 py-1 rounded-md z-[200000]">
|
|
210
|
-
|
|
222
|
+
{backLabel}
|
|
211
223
|
</Tooltip.Content>
|
|
212
224
|
</Tooltip.Portal>
|
|
213
225
|
{/if}
|
|
@@ -216,22 +228,23 @@
|
|
|
216
228
|
<Tooltip.Root open={showForwardTooltip}>
|
|
217
229
|
<button
|
|
218
230
|
type="button"
|
|
219
|
-
class="breadcrumbs-nav-button
|
|
231
|
+
class="breadcrumbs-nav-button ms-4 inline-flex items-center justify-center w-6 h-6 border-0 bg-transparent p-0 focus:outline-none"
|
|
220
232
|
style="cursor: {canGoForward && !isLoading ? 'pointer' : 'default'}; opacity: {canGoForward && !isLoading ? 1 : 0.35};"
|
|
233
|
+
aria-label={forwardLabel}
|
|
221
234
|
aria-disabled={!canGoForward || isLoading}
|
|
222
235
|
on:mouseenter={() => { showForwardTooltip = true; }}
|
|
223
236
|
on:mouseleave={() => { showForwardTooltip = false; }}
|
|
224
237
|
on:click={() => { if (!isLoading) onForward(); }}
|
|
225
238
|
>
|
|
226
239
|
<IconArrowRight
|
|
227
|
-
class="w-6 h-6 text-[hsl(var(--grey6))]"
|
|
240
|
+
class="w-6 h-6 text-[hsl(var(--grey6))] rtl:-scale-x-100"
|
|
228
241
|
style="min-width: 24px; min-height: 24px;"
|
|
229
242
|
/>
|
|
230
243
|
</button>
|
|
231
244
|
{#if showForwardTooltip}
|
|
232
245
|
<Tooltip.Portal>
|
|
233
246
|
<Tooltip.Content side="bottom" sideOffset={6} class="bg-[hsl(var(--dark))] text-white caption px-2 py-1 rounded-md z-[200000]">
|
|
234
|
-
|
|
247
|
+
{forwardLabel}
|
|
235
248
|
</Tooltip.Content>
|
|
236
249
|
</Tooltip.Portal>
|
|
237
250
|
{/if}
|
|
@@ -241,8 +254,8 @@
|
|
|
241
254
|
{/if}
|
|
242
255
|
|
|
243
256
|
<!-- BREADCRUMBS CONTAINER -->
|
|
244
|
-
<div bind:this={breadcrumbsContainer} class="flex-1
|
|
245
|
-
<Breadcrumb.Root>
|
|
257
|
+
<div bind:this={breadcrumbsContainer} class="flex-1 ps-[18px] overflow-hidden min-w-0">
|
|
258
|
+
<Breadcrumb.Root aria-label={breadcrumbLabel}>
|
|
246
259
|
<Breadcrumb.List class="inline-flex items-center min-w-0 breadcrumbs-list">
|
|
247
260
|
<div class="inline-flex items-center min-w-0 min-h-[24px]">
|
|
248
261
|
<!-- Root Breadcrumb Item -->
|
|
@@ -257,7 +270,7 @@
|
|
|
257
270
|
on:click={(e) => handleClick(e, -1)}
|
|
258
271
|
on:keydown={(e) => handleKeyDown(e, -1)}
|
|
259
272
|
>
|
|
260
|
-
|
|
273
|
+
{rootLabel}
|
|
261
274
|
</span>
|
|
262
275
|
</Breadcrumb.Item>
|
|
263
276
|
|
|
@@ -277,7 +290,7 @@
|
|
|
277
290
|
{#each currentPath.slice(0, -itemsToShow + 1) as _, index}
|
|
278
291
|
<DropdownMenu.Item>
|
|
279
292
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
280
|
-
<span
|
|
293
|
+
<span dir={nameDirection}
|
|
281
294
|
role="link"
|
|
282
295
|
tabindex="0"
|
|
283
296
|
class="block w-full cursor-pointer"
|
|
@@ -296,12 +309,12 @@
|
|
|
296
309
|
<Breadcrumb.Separator class="h5 text-[hsl(var(--grey6))] shrink-0">/</Breadcrumb.Separator>
|
|
297
310
|
<Breadcrumb.Item class="shrink-0">
|
|
298
311
|
{#if index === itemsToShow - 2}
|
|
299
|
-
<span class="h5 text-[hsl(var(--grey3))]">
|
|
312
|
+
<span dir={nameDirection} class="h5 text-[hsl(var(--grey3))]">
|
|
300
313
|
{currentPathNames[currentPath.length - 1]}
|
|
301
314
|
</span>
|
|
302
315
|
{:else}
|
|
303
316
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
304
|
-
<span
|
|
317
|
+
<span dir={nameDirection}
|
|
305
318
|
role="link"
|
|
306
319
|
tabindex="0"
|
|
307
320
|
class="h5 text-[hsl(var(--grey6))] transition-colors hover:text-[hsl(var(--grey7))] hover:underline hover:decoration-[hsl(var(--grey7))] cursor-pointer"
|
|
@@ -320,12 +333,12 @@
|
|
|
320
333
|
<Breadcrumb.Separator class="h5 text-[hsl(var(--grey6))] shrink-0">/</Breadcrumb.Separator>
|
|
321
334
|
<Breadcrumb.Item class="shrink-0">
|
|
322
335
|
{#if index === currentPath.length - 1}
|
|
323
|
-
<span class="h5 text-[hsl(var(--grey3))]">
|
|
336
|
+
<span dir={nameDirection} class="h5 text-[hsl(var(--grey3))]">
|
|
324
337
|
{currentPathNames[index]}
|
|
325
338
|
</span>
|
|
326
339
|
{:else}
|
|
327
340
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
328
|
-
<span
|
|
341
|
+
<span dir={nameDirection}
|
|
329
342
|
role="link"
|
|
330
343
|
tabindex="0"
|
|
331
344
|
class="h5 text-[hsl(var(--grey6))] transition-colors hover:text-[hsl(var(--grey7))] hover:underline hover:decoration-[hsl(var(--grey7))] cursor-pointer"
|
|
@@ -347,7 +360,7 @@
|
|
|
347
360
|
</div>
|
|
348
361
|
|
|
349
362
|
{#if showDebugVisualizer}
|
|
350
|
-
<div class="absolute bottom-1
|
|
363
|
+
<div class="absolute bottom-1 end-1 text-xs text-blue-600 bg-white px-1 rounded shadow-2xs">
|
|
351
364
|
Available width: {Math.round(availableWidth)}px
|
|
352
365
|
<br>
|
|
353
366
|
Items to show: {itemsToShow}
|
|
@@ -24,6 +24,10 @@ declare const Breadcrumbs: $$__sveltets_2_IsomorphicComponent<{
|
|
|
24
24
|
showNavigationButtons?: BreadcrumbsProps["showNavigationButtons"];
|
|
25
25
|
canGoBack?: BreadcrumbsProps["canGoBack"];
|
|
26
26
|
canGoForward?: BreadcrumbsProps["canGoForward"];
|
|
27
|
+
backLabel?: string;
|
|
28
|
+
forwardLabel?: string;
|
|
29
|
+
rootLabel?: string;
|
|
30
|
+
breadcrumbLabel?: string;
|
|
27
31
|
onNavigate?: BreadcrumbsProps["onNavigate"];
|
|
28
32
|
onBack?: BreadcrumbsProps["onBack"];
|
|
29
33
|
onForward?: BreadcrumbsProps["onForward"];
|
|
@@ -9,4 +9,12 @@ export interface BreadcrumbsProps {
|
|
|
9
9
|
onForward: () => void;
|
|
10
10
|
showNavigationButtons?: boolean;
|
|
11
11
|
showDebugVisualizer?: boolean;
|
|
12
|
+
/** Tooltip and screen reader name of the back button. Default: "Back". */
|
|
13
|
+
backLabel?: string;
|
|
14
|
+
/** Tooltip and screen reader name of the forward button. Default: "Forward". */
|
|
15
|
+
forwardLabel?: string;
|
|
16
|
+
/** Name of the first item of the path. Default: "File browser". */
|
|
17
|
+
rootLabel?: string;
|
|
18
|
+
/** Screen reader name of the navigation. Default: "breadcrumb". */
|
|
19
|
+
breadcrumbLabel?: string;
|
|
12
20
|
}
|
|
@@ -43,6 +43,9 @@
|
|
|
43
43
|
|
|
44
44
|
// Import PDF cache store
|
|
45
45
|
import { pdfCache } from '../../stores/pdfCache';
|
|
46
|
+
|
|
47
|
+
// Puts the page numbers into the words of the page counter
|
|
48
|
+
import { fillMessage } from '../../utils/fillMessage';
|
|
46
49
|
|
|
47
50
|
// Component props
|
|
48
51
|
// class and style props
|
|
@@ -52,6 +55,12 @@
|
|
|
52
55
|
// data props
|
|
53
56
|
export let url = '';
|
|
54
57
|
export let enableCacheClearing: boolean = true; // Flag to enable/disable cache clearing shortcut
|
|
58
|
+
// words: a page that shows the viewer in another language passes its own
|
|
59
|
+
export let loadingLabel: string = 'Loading PDF...';
|
|
60
|
+
export let failedLabel: string = 'Failed to load PDF';
|
|
61
|
+
export let pageLabel: string = 'Page {page} of {total}'; // {total} is "?" until the page count is known
|
|
62
|
+
export let previousPageLabel: string = 'Previous page';
|
|
63
|
+
export let nextPageLabel: string = 'Next page';
|
|
55
64
|
|
|
56
65
|
// Consts
|
|
57
66
|
const initialContainerWidth = 500; // Default width during loading
|
|
@@ -531,11 +540,11 @@
|
|
|
531
540
|
<!-- Always render loading or error state on top of content -->
|
|
532
541
|
{#if !mounted || loading || (!isCanvasReady && !error)}
|
|
533
542
|
<div class="text-[hsl(var(--grey5))] p-6 absolute z-10 widgetic-colors flex items-center justify-center inset-0">
|
|
534
|
-
|
|
543
|
+
{loadingLabel}
|
|
535
544
|
</div>
|
|
536
545
|
{:else if error}
|
|
537
546
|
<div class="pdf-error-overlay bg-[hsl(var(--grey1))] text-[hsl(var(--grey2))] inset-4 px-4 absolute z-10 flex flex-col items-center justify-center">
|
|
538
|
-
<p class="text-[hsl(var(--error))] mb-2">
|
|
547
|
+
<p class="text-[hsl(var(--error))] mb-2">{failedLabel}</p>
|
|
539
548
|
<p class="text-[hsl(var(--grey5))] text-sm">{error}</p>
|
|
540
549
|
</div>
|
|
541
550
|
{/if}
|
|
@@ -546,18 +555,18 @@
|
|
|
546
555
|
<!-- Page Navigation Bar -->
|
|
547
556
|
<div class="page-navigation-bar flex items-center justify-center h-[54px] widgetic-colors border-b border-[hsl(var(--grey2))] w-full">
|
|
548
557
|
<div class="flex items-center gap-3 w-full max-w-[200px] justify-between px-0">
|
|
549
|
-
<button class="pdf-nav-button h-9 w-9 flex items-center justify-center rounded-small bg-white border-[hsl(var(--grey2))] transition-colors group disabled:cursor-not-allowed" on:click={onPrevPage} disabled={pageNum <= 1}>
|
|
558
|
+
<button class="pdf-nav-button h-9 w-9 flex items-center justify-center rounded-small bg-white border-[hsl(var(--grey2))] transition-colors group disabled:cursor-not-allowed" on:click={onPrevPage} disabled={pageNum <= 1} aria-label={previousPageLabel}>
|
|
550
559
|
<IconChevronLeft
|
|
551
|
-
class="!text-[hsl(var(--grey5))] group-hover:!text-[hsl(var(--grey7))]"
|
|
560
|
+
class="!text-[hsl(var(--grey5))] group-hover:!text-[hsl(var(--grey7))] rtl:-scale-x-100"
|
|
552
561
|
style="height: 20px !important; min-width: 20px !important; max-width: 20px !important; max-height: 20px !important;"
|
|
553
562
|
/>
|
|
554
563
|
</button>
|
|
555
564
|
|
|
556
|
-
<span class="subtext text-[hsl(var(--grey7))]">
|
|
565
|
+
<span class="subtext text-[hsl(var(--grey7))]">{fillMessage(pageLabel, { page: pageNum, total: pageCount || '?' })}</span>
|
|
557
566
|
|
|
558
|
-
<button class="pdf-nav-button h-9 w-9 flex items-center justify-center rounded-small bg-white border-[hsl(var(--grey2))] transition-colors group disabled:cursor-not-allowed" on:click={onNextPage} disabled={pageNum >= pageCount}>
|
|
567
|
+
<button class="pdf-nav-button h-9 w-9 flex items-center justify-center rounded-small bg-white border-[hsl(var(--grey2))] transition-colors group disabled:cursor-not-allowed" on:click={onNextPage} disabled={pageNum >= pageCount} aria-label={nextPageLabel}>
|
|
559
568
|
<IconChevronRight
|
|
560
|
-
class="!text-[hsl(var(--grey5))] group-hover:!text-[hsl(var(--grey7))]"
|
|
569
|
+
class="!text-[hsl(var(--grey5))] group-hover:!text-[hsl(var(--grey7))] rtl:-scale-x-100"
|
|
561
570
|
style="height: 20px !important; min-width: 20px !important; max-width: 20px !important; max-height: 20px !important;"
|
|
562
571
|
/>
|
|
563
572
|
</button>
|
|
@@ -591,7 +600,7 @@
|
|
|
591
600
|
content: '';
|
|
592
601
|
position: absolute;
|
|
593
602
|
top: 0;
|
|
594
|
-
|
|
603
|
+
inset-inline-start: 0;
|
|
595
604
|
width: 100%;
|
|
596
605
|
height: 100%;
|
|
597
606
|
border: 1px solid hsl(var(--grey2));
|
|
@@ -16,6 +16,11 @@ declare const PDFViewer: $$__sveltets_2_IsomorphicComponent<{
|
|
|
16
16
|
style?: string;
|
|
17
17
|
url?: string;
|
|
18
18
|
enableCacheClearing?: boolean;
|
|
19
|
+
loadingLabel?: string;
|
|
20
|
+
failedLabel?: string;
|
|
21
|
+
pageLabel?: string;
|
|
22
|
+
previousPageLabel?: string;
|
|
23
|
+
nextPageLabel?: string;
|
|
19
24
|
}, {
|
|
20
25
|
error: CustomEvent<{
|
|
21
26
|
message: string;
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<div class="group relative w-full">
|
|
63
63
|
<div class="relative overflow-hidden rounded-small border border-[hsl(var(--grey2))] bg-[hsl(var(--grey1))] transition-colors duration-200 hover:border-[hsl(var(--grey2))]">
|
|
64
64
|
<div class="relative w-full flex items-center">
|
|
65
|
-
<div class="absolute
|
|
65
|
+
<div class="absolute start-2 flex items-center pointer-events-none">
|
|
66
66
|
<IconSearch class="h-5 w-5 text-[hsl(var(--grey5))] transition-colors duration-300 {value ? 'text-[hsl(var(--grey7))]' : 'group-hover:text-[hsl(var(--grey7))] group-focus-within:text-[hsl(var(--grey7))]'}" />
|
|
67
67
|
</div>
|
|
68
68
|
<input
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
onKeydown(e);
|
|
80
80
|
}}
|
|
81
81
|
onpaste={onPaste}
|
|
82
|
-
class="w-full h-[38px] border-0 bg-transparent focus:outline-hidden focus:ring-0 focus-visible:ring-0
|
|
82
|
+
class="w-full h-[38px] border-0 bg-transparent focus:outline-hidden focus:ring-0 focus-visible:ring-0 ps-9 pe-8 subtext
|
|
83
83
|
transition-all duration-300
|
|
84
84
|
{value ? 'text-[hsl(var(--grey7))]' : 'text-[hsl(var(--grey3))] placeholder:text-[hsl(var(--grey3))] placeholder:transition-colors placeholder:duration-300 group-hover:text-[hsl(var(--grey7))] group-hover:placeholder:text-[hsl(var(--grey7))] group-focus-within:text-[hsl(var(--grey7))] group-focus-within:placeholder:text-[hsl(var(--grey7)))'}
|
|
85
85
|
{inputClass}"
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
{#if value}
|
|
88
88
|
<button
|
|
89
89
|
type="button"
|
|
90
|
-
class="absolute
|
|
90
|
+
class="absolute end-2 h-6 w-6 inline-flex items-center justify-center rounded-full hover:bg-[hsl(var(--grey2))] transition-all duration-300 widgetic-colors"
|
|
91
91
|
onclick={onClear}
|
|
92
92
|
>
|
|
93
93
|
<X class="h-4 w-4 text-[hsl(var(--grey7))] transition-colors duration-300 hover:text-[hsl(var(--grey7))] widgetic-colors" />
|
|
@@ -7,13 +7,16 @@
|
|
|
7
7
|
import { mode } from 'mode-watcher';
|
|
8
8
|
let { hex = $bindable() }: ColorpickerProps = $props();
|
|
9
9
|
import ColorPicker from 'svelte-awesome-color-picker';
|
|
10
|
+
import { useI18n } from './i18n/context.js';
|
|
11
|
+
|
|
12
|
+
const { t } = useI18n();
|
|
10
13
|
</script>
|
|
11
14
|
|
|
12
15
|
<div class:dark={$mode === 'dark'}>
|
|
13
16
|
<ColorPicker
|
|
14
17
|
bind:hex
|
|
15
18
|
sliderDirection="vertical"
|
|
16
|
-
label=
|
|
19
|
+
label={$t('shadEditor.colorPicker.label')}
|
|
17
20
|
isTextInput={false}
|
|
18
21
|
isAlpha
|
|
19
22
|
--picker-indicator-size="1rem"
|
|
@@ -1 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ImageOptions } from '@tiptap/extension-image';
|
|
2
|
+
import type { Readable } from 'svelte/store';
|
|
3
|
+
import type { Translate } from '../../../../i18n/index.js';
|
|
4
|
+
import type { ShadEditorMessageKey } from '../../i18n/messages.js';
|
|
5
|
+
import type { TextDirection } from '../../../textDirection.js';
|
|
6
|
+
export interface ImageExtensionOptions {
|
|
7
|
+
/**
|
|
8
|
+
* The words of the editor (`language.t` of the editor component). A node view is mounted by TipTap outside the
|
|
9
|
+
* editor's component tree, where Svelte's context does not reach, so the words travel in the options of the extension.
|
|
10
|
+
* English when left out.
|
|
11
|
+
*/
|
|
12
|
+
translate: Readable<Translate<ShadEditorMessageKey>> | null;
|
|
13
|
+
/**
|
|
14
|
+
* The way the screen around the editor is read (`textDirection` of the editor component). It travels in the options for
|
|
15
|
+
* the same reason as `translate`: the menu of the image bar is drawn by a component TipTap mounts outside the editor's
|
|
16
|
+
* tree, so it would not find the direction in Svelte's context. Left to right when left out.
|
|
17
|
+
*/
|
|
18
|
+
textDirection: Readable<TextDirection> | null;
|
|
19
|
+
}
|
|
20
|
+
export declare const ImageExtension: import("@tiptap/core").Node<ImageOptions & ImageExtensionOptions, any>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { SvelteNodeViewRenderer } from 'svelte-tiptap';
|
|
2
2
|
import ImageExtendedComponent from '../image-extended-component.svelte';
|
|
3
|
-
import Image from '@tiptap/extension-image';
|
|
3
|
+
import Image, {} from '@tiptap/extension-image';
|
|
4
4
|
export const ImageExtension = Image.extend({
|
|
5
|
+
addOptions() {
|
|
6
|
+
return { ...this.parent?.(), translate: null, textDirection: null };
|
|
7
|
+
},
|
|
5
8
|
addAttributes() {
|
|
6
9
|
return {
|
|
7
10
|
src: {
|
|
@@ -33,8 +33,10 @@
|
|
|
33
33
|
}
|
|
34
34
|
</script>
|
|
35
35
|
|
|
36
|
+
<!-- Code is read from left to right in every language, so a code block is a left to right island: its language and its copy button stay in the corners they are drawn in. -->
|
|
36
37
|
<NodeViewWrapper
|
|
37
38
|
class="code-wrapper group relative rounded bg-muted p-6 dark:bg-muted/20"
|
|
39
|
+
dir="ltr"
|
|
38
40
|
draggable
|
|
39
41
|
>
|
|
40
42
|
<DropdownMenu.Root>
|
|
@@ -44,7 +46,7 @@
|
|
|
44
46
|
variant: 'ghost',
|
|
45
47
|
size: 'sm',
|
|
46
48
|
class:
|
|
47
|
-
'absolute
|
|
49
|
+
'absolute start-2 top-2 h-4 rounded px-1 py-2 text-xs capitalize text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100'
|
|
48
50
|
})}
|
|
49
51
|
>{defaultLanguage}
|
|
50
52
|
<ChevronDown class="!size-3" />
|
|
@@ -67,7 +69,7 @@
|
|
|
67
69
|
</DropdownMenu.Root>
|
|
68
70
|
<Button
|
|
69
71
|
variant="ghost"
|
|
70
|
-
class="absolute
|
|
72
|
+
class="absolute end-2 top-2 size-4 p-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100"
|
|
71
73
|
onclick={copyCode}
|
|
72
74
|
>
|
|
73
75
|
{#if isCopying}
|