@synopackageland/ui 0.17.9 → 0.17.11
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/CHANGELOG.md +23 -0
- package/README.md +51 -17
- package/dist/components/composite/comment-item/CommentItem.vue.d.ts +5 -1
- package/dist/components/composite/copy-button/CopyButton.vue.d.ts +2 -2
- package/dist/components/composite/file-picker/FilePicker.vue.d.ts +5 -2
- package/dist/components/composite/file-thumbs/FileThumbs.vue.d.ts +24 -0
- package/dist/components/composite/form/FormItem.vue.d.ts +1 -1
- package/dist/components/composite/form-note/FormNote.vue.d.ts +6 -2
- package/dist/components/composite/image-lightbox/ImageLightbox.vue.d.ts +19 -0
- package/dist/components/composite/mention-list/MentionList.vue.d.ts +31 -0
- package/dist/components/composite/rich-text-view/RichTextBlocks.vue.d.ts +14 -0
- package/dist/components/composite/rich-text-view/RichTextImage.vue.d.ts +12 -0
- package/dist/components/composite/rich-text-view/RichTextInline.vue.d.ts +23 -0
- package/dist/components/composite/rich-text-view/RichTextView.vue.d.ts +28 -0
- package/dist/components/composite/stat-tile/StatTile.vue.d.ts +1 -1
- package/dist/components/composite/upload-queue/UploadQueue.vue.d.ts +36 -0
- package/dist/components/composite/wizard/WizardStep.vue.d.ts +1 -1
- package/dist/components/containers/fieldset/Fieldset.vue.d.ts +6 -2
- package/dist/components/primitives/input/Input.vue.d.ts +13 -1
- package/dist/components/rich-text-editor/RichTextEditor.vue.d.ts +83 -0
- package/dist/components/rich-text-editor/extensions.d.ts +30 -0
- package/dist/components/rich-text-editor/markdown.d.ts +22 -0
- package/dist/i18n/filePicker.d.ts +3 -0
- package/dist/i18n/text.d.ts +48 -0
- package/dist/index.d.ts +15 -4
- package/dist/index.js +11305 -10025
- package/dist/json/catalog.d.ts +2 -2
- package/dist/json/registry.d.ts +34 -34
- package/dist/json-preview/preview.js +3608 -3161
- package/dist/lib/files.d.ts +28 -0
- package/dist/lib/mentions.d.ts +0 -10
- package/dist/lib/richText.d.ts +66 -0
- package/dist/lib/uploadQueue.d.ts +39 -0
- package/dist/reka-runtime.json +1 -1
- package/dist/rich-text.d.ts +3 -0
- package/dist/rich-text.js +1075 -0
- package/dist/theme.css +1 -1
- package/dist/themes/dsm7-embedded-theme.css +1 -1
- package/dist/themes/dsm7-embedded.css +1 -1
- package/dist/themes/dsm7.css +1 -1
- package/docs/layout-rules.md +7 -3
- package/docs/theme-hooks.md +14 -3
- package/package.json +14 -1
- package/dist/components/composite/comment-item/CommentInlineParts.vue.d.ts +0 -7
- package/dist/components/composite/mention-textarea/MentionTextarea.vue.d.ts +0 -52
- package/dist/lib/commentMarkdown.d.ts +0 -34
- /package/dist/components/composite/{mention-textarea → comment-item}/PersonInitials.vue.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.11 (2026-10-30)
|
|
4
|
+
|
|
5
|
+
Settings forms follow DSM's own Control Panel layout by default. Two DOM changes: `Fieldset`'s chevron points up while open and down while collapsed (it was down and right), and a `password` `Input` is now an outer `<span>` (layout attrs) around an inner one holding the field and its toggle.
|
|
6
|
+
|
|
7
|
+
- `Fieldset` takes `description` (or `#description`): one line under the title across the whole section width (`data-fieldset-description`).
|
|
8
|
+
- `Input` takes `unit` (or `#unit`): text such as s, MB or characters right after the field, a number's too, dimmed while disabled (`data-ui-input-unit`).
|
|
9
|
+
- A `text-only` `FormItem` sets its value level with the label, so a read-only value and an `#after` button (Edit) line up with the rows around it.
|
|
10
|
+
- `FormNote` with one remark reads "Note: …" on one line; two or more `items` keep the heading over a list. `inset` starts it on the field column (inside a `FormGroup` too), one field gap under the field it is about (`data-inset`).
|
|
11
|
+
- docs/layout-rules.md describes the whole settings page: section description, read-only value with Edit, dependent options in a `FormGroup`, section buttons inside the group, units, notes and one Apply in the footer. The Control Panel story adds Network > General.
|
|
12
|
+
|
|
13
|
+
## 0.17.10 (2026-10-30)
|
|
14
|
+
|
|
15
|
+
Breaking, with no compatibility layer: the comment Markdown functions are renamed, `MentionTextarea` is gone, and comment bodies read a little differently. A stored body that relied on the old reading needs a one-time conversion; the library keeps no old names or fallback.
|
|
16
|
+
|
|
17
|
+
- `commentMarkdownParts` and `commentMarkdownText` are renamed `richTextParts(body, { people, headings })` and `richTextText`, with no alias; `CommentBlock` and `CommentInline` are now `RichTextBlock` and `RichTextInline`. A list item is `{ parts, list? }` instead of an array of parts. Add `richTextFileIds`, the image files a body uses.
|
|
18
|
+
- The restricted Markdown grows: `~~strike~~`, `1. ` numbered lists (from any start), lists two levels deep, `> ` quotes, fenced code (a longer fence holds ``` lines), `## ` and `### ` headings with `headings`, and `` images of stored files (any other address stays as typed). A blank line now starts a new paragraph. A backslash keeps the punctuation after it as typed, and `<`, `>`, `&` and ` ` read as their characters. `**` closes next to CJK punctuation, as in `**「引號」**後面`. Link addresses may hold one level of parentheses. HTML, tables and `---` still show as typed.
|
|
19
|
+
- `CommentItem` renders its body with the new `RichTextView` and takes `files(id)` to show images. Its inner hooks are renamed: `data-ui-comment-mention`, `-link`, `-code` and `-list` are now `data-ui-rich-mention`, `-link`, `-code` and `-list`; paragraphs are `data-ui-rich-paragraph`.
|
|
20
|
+
- Remove `MentionTextarea`, `mentionTokens` and `mentionText`. Comment boxes use the compact `RichTextEditor`.
|
|
21
|
+
- Add the `@synopackageland/ui/rich-text` entry with `RichTextEditor`, a Tiptap 3 editor (MIT parts only) that reads and writes the restricted Markdown, plus `markdownToDoc` and `docToMarkdown`. `variant="full"` has a toolbar that stays at the top and moves what does not fit into More; `variant="compact"` is a comment box that grows from one line, with Markdown as you type, Ctrl/⌘+B, I and K, a toolbar over selected text with a mouse, an "Aa" row of formats (one box at a time, Escape closes it), Ctrl/⌘+Enter or the send button to `submit`, and images under the text. Pasted, dropped and chosen images upload through the app's `upload`; HEIC, HEIF and AVIF are refused with a note, images from other websites are left out with a note, and the box cannot send while an image uploads (`pending`). Tiptap is a dependency loaded only by this entry.
|
|
22
|
+
- Add `RichTextView`, `FileThumbs` (thumbnails and +N), `ImageLightbox` (full-size files with arrow keys and swipes), `UploadQueue` (progress, retry, cancel) with `useUploadQueue`, `MentionList`, `FileItem`, `isPicture` and `isUnsupportedPicture`. `useUiText` is exported for companion entries.
|
|
23
|
+
- `FilePicker` takes pasted files with `paste`: a paste on the picker, or its Paste button where the browser can read the clipboard. A pasted screenshot is named after the time it was pasted.
|
|
24
|
+
- New strings in all nine built-in languages for the editor, the file views and the upload queue.
|
|
25
|
+
|
|
3
26
|
## 0.17.9 (2026-10-30)
|
|
4
27
|
|
|
5
28
|
- A `CommentItem` body with many unmatched `*` or `**` no longer slows down: each line is read in one pass, so a 70,000-character comment of unclosed stars takes milliseconds instead of seconds. What the comment shows is unchanged.
|
package/README.md
CHANGED
|
@@ -621,7 +621,7 @@ touch keyboard is open; set `hidden` while a full-screen drawer covers the page.
|
|
|
621
621
|
</AppLayout>
|
|
622
622
|
```
|
|
623
623
|
|
|
624
|
-
### Collaboration: CompletionToggle,
|
|
624
|
+
### Collaboration: CompletionToggle, CommentItem, rich text and files
|
|
625
625
|
|
|
626
626
|
`CompletionToggle` is the round done toggle of a task row, card or detail
|
|
627
627
|
header: a `role="checkbox"` with a 44px touch target. Show the new state at
|
|
@@ -629,24 +629,58 @@ once, set `pending` while it saves, and on failure put the old state back and
|
|
|
629
629
|
set `error`. Its click does not reach the row, so it never also opens the item.
|
|
630
630
|
Name it after the item: `label="Done: Send the quote"`.
|
|
631
631
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
`
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
`
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
632
|
+
Comments and rich text fields store one restricted Markdown: `**bold**`,
|
|
633
|
+
`*italic*`, `~~strike~~`, `` `code` ``, `[text](https://…)` or `mailto:`,
|
|
634
|
+
`@[id]` mentions, `` images of stored files, `- ` and `1. `
|
|
635
|
+
lists two levels deep, `> ` quotes, fenced code and, in a field, `## ` and
|
|
636
|
+
`### ` headings. A backslash keeps punctuation as typed; HTML, tables and
|
|
637
|
+
`---` always show as typed. `richTextParts(body, { people, headings })` reads it
|
|
638
|
+
into blocks of parts, never HTML; `richTextText` gives plain text for a
|
|
639
|
+
notification or a search; `richTextFileIds` lists the image files a body uses.
|
|
640
|
+
|
|
641
|
+
`RichTextView` shows a body: mentions as names, safe links, images that keep
|
|
642
|
+
their shape while they load and open in an `ImageLightbox`. The app passes
|
|
643
|
+
`files(id)`, which describes a stored file (`FileItem`: name, type, `thumb`,
|
|
644
|
+
`preview`, `url`, `width`, `height`, `dominant` colour and a `state` of
|
|
645
|
+
`processing`, `missing` or `changed`). `CommentItem` shows one comment with a
|
|
646
|
+
`RichTextView` body: avatar, author, the time as the app formats it; `edited`,
|
|
647
|
+
`deleted` and `highlighted` (a one-time flash for a comment opened from a
|
|
648
|
+
notification) cover the rest; edit and delete controls go in `#actions`.
|
|
649
|
+
|
|
650
|
+
`RichTextEditor` comes from its own entry, `@synopackageland/ui/rich-text`, so
|
|
651
|
+
an app that only shows rich text never loads Tiptap; load it when an editor
|
|
652
|
+
first opens. Both looks write the same Markdown:
|
|
653
|
+
|
|
654
|
+
- `variant="full"`, for a rich text field: a toolbar that stays at the top, with
|
|
655
|
+
what does not fit in a More menu; images sit in the text.
|
|
656
|
+
- `variant="compact"`, for a comment box (as in Slack, Linear and GitHub): one
|
|
657
|
+
line that grows, Markdown as you type, Ctrl/⌘+B, I and K, a toolbar over
|
|
658
|
+
selected text with a mouse, and an "Aa" button that opens one row of formats
|
|
659
|
+
(the only one on a touch screen). Enter starts a line; Ctrl/⌘+Enter or the
|
|
660
|
+
send button emits `submit`. Images line up under the text, and the box does
|
|
661
|
+
not send while one uploads.
|
|
662
|
+
|
|
663
|
+
The editor knows nothing of the server. `upload(file, { signal, onProgress })`
|
|
664
|
+
sends one file and resolves with its id; pasted, dropped and chosen JPEG, PNG,
|
|
665
|
+
WebP and GIF images go through it, and HEIC is refused with a note (the picker
|
|
666
|
+
names its types, so iOS hands over JPEG). `pending` reports images still
|
|
667
|
+
uploading or failed: a form should not save while there are any. `@` opens the
|
|
668
|
+
people in `candidates`; answer `search` and turn `filter` off when the server
|
|
669
|
+
already matched them. With `maxlength` the box counts characters near and over
|
|
670
|
+
the limit and never cuts text.
|
|
671
|
+
|
|
672
|
+
`FileThumbs` shows a few thumbnails and "+N", `ImageLightbox` shows files full
|
|
673
|
+
size (arrow keys and swipes), and `UploadQueue` lists uploads with progress,
|
|
674
|
+
retry and cancel. `useUploadQueue(upload, { concurrency, retries })` runs the
|
|
675
|
+
uploads it shows. `FilePicker` takes pasted files with `paste`.
|
|
646
676
|
|
|
647
677
|
```vue
|
|
648
|
-
<CommentItem v-for="c in comments" :key="c.id" :author="c.author.name" :time="c.when" :body="c.body" :mentions="
|
|
649
|
-
<
|
|
678
|
+
<CommentItem v-for="c in comments" :key="c.id" :author="c.author.name" :time="c.when" :body="c.body" :mentions="people" :files="fileById" :edited="!!c.editedAt" :deleted="c.deleted" />
|
|
679
|
+
<RichTextEditor v-model="text" variant="compact" :candidates="people" :filter="false" :maxlength="4000" :upload="sendFile" :files="fileById" @search="findPeople" @submit="post" />
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
```ts
|
|
683
|
+
const RichTextEditor = defineAsyncComponent(() => import('@synopackageland/ui/rich-text').then(module => module.RichTextEditor))
|
|
650
684
|
```
|
|
651
685
|
|
|
652
686
|
### Status: StatusDot, StepList, ConnectionTopology
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MentionCandidate } from '../../../lib/mentions';
|
|
2
|
+
import { FileItem } from '../../../lib/files';
|
|
2
3
|
type __VLS_Props = {
|
|
3
4
|
author: string;
|
|
4
5
|
/** Keeps the avatar colour stable across renamed accounts. */
|
|
@@ -9,10 +10,12 @@ type __VLS_Props = {
|
|
|
9
10
|
time?: string;
|
|
10
11
|
/** The same time for machines (`<time datetime>`), such as an ISO string. */
|
|
11
12
|
datetime?: string;
|
|
12
|
-
/**
|
|
13
|
+
/** Restricted Markdown with `@[id]` mention tokens and `` images (see `richTextParts`). */
|
|
13
14
|
body?: string;
|
|
14
15
|
/** Names for the mention tokens; an unknown id shows as itself. */
|
|
15
16
|
mentions?: MentionCandidate[];
|
|
17
|
+
/** The file behind an image's id. */
|
|
18
|
+
files?: (id: string) => FileItem | undefined;
|
|
16
19
|
edited?: boolean;
|
|
17
20
|
deleted?: boolean;
|
|
18
21
|
highlighted?: boolean;
|
|
@@ -30,6 +33,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
30
33
|
time: string;
|
|
31
34
|
avatar: string;
|
|
32
35
|
mentions: MentionCandidate[];
|
|
36
|
+
files: (id: string) => FileItem | undefined;
|
|
33
37
|
authorId: string;
|
|
34
38
|
datetime: string;
|
|
35
39
|
edited: boolean;
|
|
@@ -18,11 +18,11 @@ type __VLS_Props = {
|
|
|
18
18
|
disabled?: boolean;
|
|
19
19
|
};
|
|
20
20
|
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
21
|
-
copied: (text: string) => any;
|
|
22
21
|
failed: (text: string) => any;
|
|
22
|
+
copied: (text: string) => any;
|
|
23
23
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
24
|
-
onCopied?: ((text: string) => any) | undefined;
|
|
25
24
|
onFailed?: ((text: string) => any) | undefined;
|
|
25
|
+
onCopied?: ((text: string) => any) | undefined;
|
|
26
26
|
}>, {
|
|
27
27
|
label: string;
|
|
28
28
|
size: "sm" | "md";
|
|
@@ -15,17 +15,19 @@ type __VLS_Props = {
|
|
|
15
15
|
directory?: boolean;
|
|
16
16
|
showList?: boolean;
|
|
17
17
|
variant?: 'dropzone' | 'compact';
|
|
18
|
+
/** Takes files pasted while the picker has focus, and adds a Paste button where the browser can read the clipboard (an iPhone has no keyboard to paste with). */
|
|
19
|
+
paste?: boolean;
|
|
18
20
|
locale?: UiLocale;
|
|
19
21
|
text?: Partial<FilePickerText>;
|
|
20
22
|
title?: string;
|
|
21
23
|
description?: string;
|
|
22
24
|
};
|
|
23
|
-
declare var
|
|
25
|
+
declare var __VLS_53: {
|
|
24
26
|
file: File;
|
|
25
27
|
index: number;
|
|
26
28
|
};
|
|
27
29
|
type __VLS_Slots = {} & {
|
|
28
|
-
'file-actions'?: (props: typeof
|
|
30
|
+
'file-actions'?: (props: typeof __VLS_53) => any;
|
|
29
31
|
};
|
|
30
32
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
31
33
|
"update:modelValue": (files: File[]) => any;
|
|
@@ -38,6 +40,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
38
40
|
disabled: boolean;
|
|
39
41
|
modelValue: File[];
|
|
40
42
|
multiple: boolean;
|
|
43
|
+
paste: boolean;
|
|
41
44
|
maxFiles: number;
|
|
42
45
|
maxSize: number;
|
|
43
46
|
directory: boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FileItem } from '../../../lib/files';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
items: FileItem[];
|
|
4
|
+
/** Thumbnails shown before "+N"; 0 shows them all. */
|
|
5
|
+
max?: number;
|
|
6
|
+
/** `sm` (28px) fits a table row; `md` (64px) a form or a comment box. */
|
|
7
|
+
size?: 'sm' | 'md';
|
|
8
|
+
removable?: boolean;
|
|
9
|
+
lightbox?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
12
|
+
open: (index: number, item: FileItem) => any;
|
|
13
|
+
remove: (item: FileItem) => any;
|
|
14
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
15
|
+
onOpen?: ((index: number, item: FileItem) => any) | undefined;
|
|
16
|
+
onRemove?: ((item: FileItem) => any) | undefined;
|
|
17
|
+
}>, {
|
|
18
|
+
size: "sm" | "md";
|
|
19
|
+
max: number;
|
|
20
|
+
removable: boolean;
|
|
21
|
+
lightbox: boolean;
|
|
22
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
23
|
+
declare const _default: typeof __VLS_export;
|
|
24
|
+
export default _default;
|
|
@@ -40,7 +40,7 @@ type __VLS_Props = {
|
|
|
40
40
|
defaultValidateTrigger?: ValidateTrigger;
|
|
41
41
|
/** Validates once on mount. */
|
|
42
42
|
immediateValidate?: boolean;
|
|
43
|
-
/** The slot content is plain text, not a control. */
|
|
43
|
+
/** The slot content is plain text, not a control: a read-only value, set level with the label. An `#after` button follows the field column. */
|
|
44
44
|
textOnly?: boolean;
|
|
45
45
|
/** Indentation level (multiples of 28px) or any CSS length. */
|
|
46
46
|
indent?: string | number;
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
/** Replaces the "Note:" heading. */
|
|
3
3
|
title?: string;
|
|
4
|
-
/** One bullet each; the default slot follows them. */
|
|
4
|
+
/** One bullet each; a single item reads inline after the heading. The default slot follows them. */
|
|
5
5
|
items?: string[];
|
|
6
|
+
/** Starts the note on the field column, past the label column (inside a FormGroup too). */
|
|
7
|
+
inset?: boolean;
|
|
6
8
|
};
|
|
7
|
-
declare var __VLS_1: {};
|
|
9
|
+
declare var __VLS_1: {}, __VLS_3: {};
|
|
8
10
|
type __VLS_Slots = {} & {
|
|
9
11
|
default?: (props: typeof __VLS_1) => any;
|
|
12
|
+
} & {
|
|
13
|
+
default?: (props: typeof __VLS_3) => any;
|
|
10
14
|
};
|
|
11
15
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
12
16
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FileItem } from '../../../lib/files';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
items: FileItem[];
|
|
4
|
+
open?: boolean;
|
|
5
|
+
/** The file shown, from 0. */
|
|
6
|
+
index?: number;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
9
|
+
"update:open": (open: boolean) => any;
|
|
10
|
+
"update:index": (index: number) => any;
|
|
11
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
|
+
"onUpdate:open"?: ((open: boolean) => any) | undefined;
|
|
13
|
+
"onUpdate:index"?: ((index: number) => any) | undefined;
|
|
14
|
+
}>, {
|
|
15
|
+
open: boolean;
|
|
16
|
+
index: number;
|
|
17
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MentionCandidate } from '../../../lib/mentions';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
open: boolean;
|
|
4
|
+
/** Where the list opens, such as the caret's box. */
|
|
5
|
+
reference: {
|
|
6
|
+
getBoundingClientRect: () => DOMRect;
|
|
7
|
+
} | null;
|
|
8
|
+
people: readonly MentionCandidate[];
|
|
9
|
+
active?: number;
|
|
10
|
+
/** The listbox id; each option is `${id}-${index}`. */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Shows "Loading…" while the list is empty. */
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
/** An element inside the app, which keeps the list within the app's window. */
|
|
15
|
+
boundary?: HTMLElement;
|
|
16
|
+
};
|
|
17
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
18
|
+
choose: (person: MentionCandidate) => any;
|
|
19
|
+
close: () => any;
|
|
20
|
+
hover: (index: number) => any;
|
|
21
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
22
|
+
onChoose?: ((person: MentionCandidate) => any) | undefined;
|
|
23
|
+
onClose?: (() => any) | undefined;
|
|
24
|
+
onHover?: ((index: number) => any) | undefined;
|
|
25
|
+
}>, {
|
|
26
|
+
loading: boolean;
|
|
27
|
+
active: number;
|
|
28
|
+
boundary: HTMLElement;
|
|
29
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
30
|
+
declare const _default: typeof __VLS_export;
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RichTextBlock } from '../../../lib/richText';
|
|
2
|
+
import { FileItem } from '../../../lib/files';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
blocks: RichTextBlock[];
|
|
5
|
+
file: (id: string, alt: string) => FileItem;
|
|
6
|
+
imageHeight: number;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
9
|
+
open: (id: string) => any;
|
|
10
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onOpen?: ((id: string) => any) | undefined;
|
|
12
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
13
|
+
declare const _default: typeof __VLS_export;
|
|
14
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FileItem } from '../../../lib/files';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
item: FileItem;
|
|
4
|
+
height: number;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
7
|
+
open: () => any;
|
|
8
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
9
|
+
onOpen?: (() => any) | undefined;
|
|
10
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const _default: typeof __VLS_export;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RichTextInline } from '../../../lib/richText';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
parts: RichTextInline[];
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_1: {
|
|
6
|
+
image: {
|
|
7
|
+
type: "image";
|
|
8
|
+
id: string;
|
|
9
|
+
alt: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
type __VLS_Slots = {} & {
|
|
13
|
+
image?: (props: typeof __VLS_1) => any;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
19
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
20
|
+
new (): {
|
|
21
|
+
$slots: S;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MentionCandidate } from '../../../lib/mentions';
|
|
2
|
+
import { FileItem } from '../../../lib/files';
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
body?: string;
|
|
5
|
+
/** Names for the mention tokens; an unknown id shows as itself. */
|
|
6
|
+
mentions?: MentionCandidate[];
|
|
7
|
+
/** Reads `## ` and `### ` as headings, as a rich text field does. */
|
|
8
|
+
headings?: boolean;
|
|
9
|
+
/** The file behind an image's id; an unknown id shows as missing. */
|
|
10
|
+
files?: (id: string) => FileItem | undefined;
|
|
11
|
+
/** Tallest an image is drawn, in px, before it opens full size. */
|
|
12
|
+
imageHeight?: number;
|
|
13
|
+
lightbox?: boolean;
|
|
14
|
+
};
|
|
15
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
16
|
+
"open-image": (id: string, index: number) => any;
|
|
17
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
18
|
+
"onOpen-image"?: ((id: string, index: number) => any) | undefined;
|
|
19
|
+
}>, {
|
|
20
|
+
body: string;
|
|
21
|
+
imageHeight: number;
|
|
22
|
+
mentions: MentionCandidate[];
|
|
23
|
+
headings: boolean;
|
|
24
|
+
files: (id: string) => FileItem | undefined;
|
|
25
|
+
lightbox: boolean;
|
|
26
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
27
|
+
declare const _default: typeof __VLS_export;
|
|
28
|
+
export default _default;
|
|
@@ -28,8 +28,8 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
28
28
|
disabled: boolean;
|
|
29
29
|
value: string | number;
|
|
30
30
|
modelValue: boolean;
|
|
31
|
-
tone: StatTileTone;
|
|
32
31
|
unit: string;
|
|
32
|
+
tone: StatTileTone;
|
|
33
33
|
note: string;
|
|
34
34
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
35
35
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { UploadStatus } from '../../../lib/uploadQueue';
|
|
2
|
+
export type UploadQueueItem = {
|
|
3
|
+
key: string;
|
|
4
|
+
name: string;
|
|
5
|
+
size: number;
|
|
6
|
+
loaded: number;
|
|
7
|
+
status: UploadStatus;
|
|
8
|
+
error?: string;
|
|
9
|
+
};
|
|
10
|
+
type __VLS_Props = {
|
|
11
|
+
tasks: UploadQueueItem[];
|
|
12
|
+
/** Files the server is still making thumbnails for, added to the summary. */
|
|
13
|
+
processing?: number;
|
|
14
|
+
collapsible?: boolean;
|
|
15
|
+
/** Shows a close button once nothing waits or sends. */
|
|
16
|
+
closable?: boolean;
|
|
17
|
+
};
|
|
18
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
19
|
+
cancel: (key: string) => any;
|
|
20
|
+
close: () => any;
|
|
21
|
+
retry: (key: string) => any;
|
|
22
|
+
retryAll: () => any;
|
|
23
|
+
cancelAll: () => any;
|
|
24
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
25
|
+
onCancel?: ((key: string) => any) | undefined;
|
|
26
|
+
onClose?: (() => any) | undefined;
|
|
27
|
+
onRetry?: ((key: string) => any) | undefined;
|
|
28
|
+
onRetryAll?: (() => any) | undefined;
|
|
29
|
+
onCancelAll?: (() => any) | undefined;
|
|
30
|
+
}>, {
|
|
31
|
+
collapsible: boolean;
|
|
32
|
+
closable: boolean;
|
|
33
|
+
processing: number;
|
|
34
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
35
|
+
declare const _default: typeof __VLS_export;
|
|
36
|
+
export default _default;
|
|
@@ -11,11 +11,11 @@ declare const __VLS_base: import('vue').DefineComponent<WizardStepProps, {
|
|
|
11
11
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<WizardStepProps> & Readonly<{}>, {
|
|
12
12
|
footer: boolean;
|
|
13
13
|
type: import('./types').WizardStepType;
|
|
14
|
+
lazy: boolean;
|
|
14
15
|
headline: string;
|
|
15
16
|
nextDisabled: boolean;
|
|
16
17
|
showNext: boolean;
|
|
17
18
|
showBack: boolean;
|
|
18
|
-
lazy: boolean;
|
|
19
19
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
20
20
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
21
21
|
declare const _default: typeof __VLS_export;
|
|
@@ -5,6 +5,8 @@ export type FieldsetTitle = string | {
|
|
|
5
5
|
export type FieldsetCollapseTrigger = 'click' | 'dblclick' | 'none';
|
|
6
6
|
type __VLS_Props = {
|
|
7
7
|
title?: FieldsetTitle;
|
|
8
|
+
/** One line under the title, across the whole width (DSM's "Enter the server name, ..."). */
|
|
9
|
+
description?: string;
|
|
8
10
|
collapsible?: boolean;
|
|
9
11
|
/** Mouse gesture that toggles; Enter/Space always works on the header. */
|
|
10
12
|
collapseTriggerEvent?: FieldsetCollapseTrigger;
|
|
@@ -12,7 +14,7 @@ type __VLS_Props = {
|
|
|
12
14
|
/** Bound with `v-model:collapsed`; defaults to expanded when left unbound. */
|
|
13
15
|
collapsed?: boolean;
|
|
14
16
|
};
|
|
15
|
-
declare var __VLS_1: {}, __VLS_8: {}, __VLS_10: {}, __VLS_12: {};
|
|
17
|
+
declare var __VLS_1: {}, __VLS_8: {}, __VLS_10: {}, __VLS_12: {}, __VLS_14: {};
|
|
16
18
|
type __VLS_Slots = {} & {
|
|
17
19
|
'collapse-icon'?: (props: typeof __VLS_1) => any;
|
|
18
20
|
} & {
|
|
@@ -20,7 +22,9 @@ type __VLS_Slots = {} & {
|
|
|
20
22
|
} & {
|
|
21
23
|
title?: (props: typeof __VLS_10) => any;
|
|
22
24
|
} & {
|
|
23
|
-
|
|
25
|
+
description?: (props: typeof __VLS_12) => any;
|
|
26
|
+
} & {
|
|
27
|
+
default?: (props: typeof __VLS_14) => any;
|
|
24
28
|
};
|
|
25
29
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
26
30
|
isCollapsed: import('vue').ComputedRef<boolean>;
|
|
@@ -10,8 +10,14 @@ type __VLS_Props = {
|
|
|
10
10
|
name?: string;
|
|
11
11
|
ariaLabel?: string;
|
|
12
12
|
ariaLabelledby?: string;
|
|
13
|
+
/** Text right after the field, such as s, MB or characters; the `#unit` slot replaces it. */
|
|
14
|
+
unit?: string;
|
|
13
15
|
};
|
|
14
|
-
declare
|
|
16
|
+
declare var __VLS_11: {};
|
|
17
|
+
type __VLS_Slots = {} & {
|
|
18
|
+
unit?: (props: typeof __VLS_11) => any;
|
|
19
|
+
};
|
|
20
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
15
21
|
"update:modelValue": (value: string) => any;
|
|
16
22
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
23
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
@@ -23,5 +29,11 @@ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {
|
|
|
23
29
|
readonly: boolean;
|
|
24
30
|
invalid: boolean;
|
|
25
31
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
32
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
26
33
|
declare const _default: typeof __VLS_export;
|
|
27
34
|
export default _default;
|
|
35
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
36
|
+
new (): {
|
|
37
|
+
$slots: S;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { FileItem, MentionCandidate, UploadFunction } from '../../index';
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
4
|
+
declare const __VLS_export: import('vue').DefineComponent<{
|
|
5
|
+
modelValue?: string;
|
|
6
|
+
variant?: "compact" | "full";
|
|
7
|
+
/** `## ` and `### ` headings; on by default in `full` only. */
|
|
8
|
+
headings?: boolean;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
invalid?: boolean;
|
|
12
|
+
id?: string;
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
/** Characters the stored body may hold; the count shows from 90% and over, and a body over it cannot be sent. */
|
|
15
|
+
maxlength?: number;
|
|
16
|
+
/** Images one body may hold: 20 in `compact`, 50 in `full` by default. */
|
|
17
|
+
maxImages?: number;
|
|
18
|
+
/** Sends one file and resolves with its stored id; without it the box takes no images. */
|
|
19
|
+
upload?: UploadFunction<string>;
|
|
20
|
+
/** The file behind a stored image's id. */
|
|
21
|
+
files?: (id: string) => FileItem | undefined;
|
|
22
|
+
/** People to offer for the text typed after `@`. */
|
|
23
|
+
candidates?: MentionCandidate[];
|
|
24
|
+
/** Narrows `candidates` by the query here; turn off when the server already did. */
|
|
25
|
+
filter?: boolean;
|
|
26
|
+
/** Shows "Loading…" in the list of people while the app fetches. */
|
|
27
|
+
loading?: boolean;
|
|
28
|
+
/** `compact` only: the send button shows a spinner and the box cannot send again. */
|
|
29
|
+
sending?: boolean;
|
|
30
|
+
}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
31
|
+
search: (query: string) => any;
|
|
32
|
+
submit: (body: string) => any;
|
|
33
|
+
pending: (count: number) => any;
|
|
34
|
+
"update:modelValue": (body: string) => any;
|
|
35
|
+
}, string, import('vue').PublicProps, Readonly<{
|
|
36
|
+
modelValue?: string;
|
|
37
|
+
variant?: "compact" | "full";
|
|
38
|
+
/** `## ` and `### ` headings; on by default in `full` only. */
|
|
39
|
+
headings?: boolean;
|
|
40
|
+
placeholder?: string;
|
|
41
|
+
disabled?: boolean;
|
|
42
|
+
invalid?: boolean;
|
|
43
|
+
id?: string;
|
|
44
|
+
ariaLabel?: string;
|
|
45
|
+
/** Characters the stored body may hold; the count shows from 90% and over, and a body over it cannot be sent. */
|
|
46
|
+
maxlength?: number;
|
|
47
|
+
/** Images one body may hold: 20 in `compact`, 50 in `full` by default. */
|
|
48
|
+
maxImages?: number;
|
|
49
|
+
/** Sends one file and resolves with its stored id; without it the box takes no images. */
|
|
50
|
+
upload?: UploadFunction<string>;
|
|
51
|
+
/** The file behind a stored image's id. */
|
|
52
|
+
files?: (id: string) => FileItem | undefined;
|
|
53
|
+
/** People to offer for the text typed after `@`. */
|
|
54
|
+
candidates?: MentionCandidate[];
|
|
55
|
+
/** Narrows `candidates` by the query here; turn off when the server already did. */
|
|
56
|
+
filter?: boolean;
|
|
57
|
+
/** Shows "Loading…" in the list of people while the app fetches. */
|
|
58
|
+
loading?: boolean;
|
|
59
|
+
/** `compact` only: the send button shows a spinner and the box cannot send again. */
|
|
60
|
+
sending?: boolean;
|
|
61
|
+
}> & Readonly<{
|
|
62
|
+
onSearch?: ((query: string) => any) | undefined;
|
|
63
|
+
onSubmit?: ((body: string) => any) | undefined;
|
|
64
|
+
onPending?: ((count: number) => any) | undefined;
|
|
65
|
+
"onUpdate:modelValue"?: ((body: string) => any) | undefined;
|
|
66
|
+
}>, {
|
|
67
|
+
filter: boolean;
|
|
68
|
+
variant: "compact" | "full";
|
|
69
|
+
loading: boolean;
|
|
70
|
+
disabled: boolean;
|
|
71
|
+
id: string;
|
|
72
|
+
modelValue: string;
|
|
73
|
+
placeholder: string;
|
|
74
|
+
invalid: boolean;
|
|
75
|
+
ariaLabel: string;
|
|
76
|
+
headings: boolean;
|
|
77
|
+
files: (id: string) => FileItem | undefined;
|
|
78
|
+
upload: UploadFunction<string>;
|
|
79
|
+
maxlength: number;
|
|
80
|
+
maxImages: number;
|
|
81
|
+
candidates: MentionCandidate[];
|
|
82
|
+
sending: boolean;
|
|
83
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Node, AnyExtension } from '@tiptap/core';
|
|
2
|
+
import { SuggestionOptions } from '@tiptap/suggestion';
|
|
3
|
+
import { FileItem, MentionCandidate } from '../../index';
|
|
4
|
+
export type ImageView = {
|
|
5
|
+
/** The file behind a stored image's id. */
|
|
6
|
+
file: (id: string) => FileItem | undefined;
|
|
7
|
+
labels: {
|
|
8
|
+
uploading: string;
|
|
9
|
+
failed: string;
|
|
10
|
+
missing: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* An image of a stored file, a block of its own. `id` is the stored file;
|
|
15
|
+
* `upload` names an image still being sent, drawn from the local `src`, with
|
|
16
|
+
* its `progress` from 0 to 1, or -1 once it failed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fileImage(view: ImageView): Node<any, any>;
|
|
19
|
+
export type ExtensionOptions = {
|
|
20
|
+
headings: boolean;
|
|
21
|
+
placeholder: string;
|
|
22
|
+
image: ImageView;
|
|
23
|
+
mention: Omit<SuggestionOptions<MentionCandidate>, 'editor' | 'char'>;
|
|
24
|
+
/** Ctrl+Enter or Cmd+Enter; returns whether it was taken. Never while an input method composes. */
|
|
25
|
+
submit?: () => boolean;
|
|
26
|
+
/** Ctrl+K or Cmd+K. */
|
|
27
|
+
link: () => boolean;
|
|
28
|
+
escape: () => boolean;
|
|
29
|
+
};
|
|
30
|
+
export declare function extensions(options: ExtensionOptions): AnyExtension[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { JSONContent } from '@tiptap/core';
|
|
2
|
+
import { MentionCandidate } from '../../index';
|
|
3
|
+
export type MarkdownOptions = {
|
|
4
|
+
people?: readonly MentionCandidate[];
|
|
5
|
+
headings?: boolean;
|
|
6
|
+
/** Leaves images out of the document and returns their ids, for a comment box that lists them under the text. */
|
|
7
|
+
imagesApart?: boolean;
|
|
8
|
+
};
|
|
9
|
+
/** A stored body → the editor's document, and the file ids of its images when `imagesApart`. */
|
|
10
|
+
export declare function markdownToDoc(body: string, options?: MarkdownOptions): {
|
|
11
|
+
doc: JSONContent;
|
|
12
|
+
images: {
|
|
13
|
+
id: string;
|
|
14
|
+
alt: string;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
export type SerializeOptions = {
|
|
18
|
+
/** Between top-level blocks: a blank line by default; a comment box uses a single line break. */
|
|
19
|
+
blockSeparator?: string;
|
|
20
|
+
};
|
|
21
|
+
/** The editor's document → the stored body. Images still uploading (no `id`) are left out. */
|
|
22
|
+
export declare function docToMarkdown(doc: JSONContent, options?: SerializeOptions): string;
|