@synopackageland/ui 0.17.9 → 0.17.10
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 +13 -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/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/upload-queue/UploadQueue.vue.d.ts +36 -0
- package/dist/components/composite/wizard/WizardStep.vue.d.ts +1 -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 +11143 -9907
- package/dist/json/catalog.d.ts +2 -2
- package/dist/json/registry.d.ts +34 -34
- package/dist/json-preview/preview.js +3436 -3004
- 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/theme-hooks.md +11 -2
- 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,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.10 (2026-10-30)
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
- `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.
|
|
8
|
+
- 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.
|
|
9
|
+
- `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`.
|
|
10
|
+
- Remove `MentionTextarea`, `mentionTokens` and `mentionText`. Comment boxes use the compact `RichTextEditor`.
|
|
11
|
+
- 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.
|
|
12
|
+
- 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.
|
|
13
|
+
- `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.
|
|
14
|
+
- New strings in all nine built-in languages for the editor, the file views and the upload queue.
|
|
15
|
+
|
|
3
16
|
## 0.17.9 (2026-10-30)
|
|
4
17
|
|
|
5
18
|
- 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;
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -20,5 +20,8 @@ export type FilePickerText = {
|
|
|
20
20
|
sizeRejected: string;
|
|
21
21
|
countRejected: string;
|
|
22
22
|
duplicateRejected: string;
|
|
23
|
+
/** With `paste`: the button that pastes from the clipboard, and what it says when the clipboard holds no file. */
|
|
24
|
+
paste: string;
|
|
25
|
+
pasteEmpty: string;
|
|
23
26
|
};
|
|
24
27
|
export declare const filePickerText: Record<UiLocale, FilePickerText>;
|
package/dist/i18n/text.d.ts
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import { UiLocale } from './locale';
|
|
2
2
|
export declare const englishUiText: {
|
|
3
|
+
readonly "{count} failed": "{count} failed";
|
|
4
|
+
readonly "{name} is not a JPEG, PNG, WebP or GIF image": "{name} is not a JPEG, PNG, WebP or GIF image";
|
|
5
|
+
readonly "{name}: {kind} images are not supported; on an iPhone, set Settings > Camera > Formats to Most Compatible": "{name}: {kind} images are not supported; on an iPhone, set Settings > Camera > Formats to Most Compatible";
|
|
6
|
+
readonly "You can add up to {count} images": "You can add up to {count} images";
|
|
7
|
+
readonly "Add image": "Add image";
|
|
8
|
+
readonly Bold: "Bold";
|
|
9
|
+
readonly "Bulleted list": "Bulleted list";
|
|
10
|
+
readonly "Can't show this file": "Can't show this file";
|
|
11
|
+
readonly "Cancel {name}": "Cancel {name}";
|
|
12
|
+
readonly "Cancel all": "Cancel all";
|
|
13
|
+
readonly "Code block": "Code block";
|
|
14
|
+
readonly Code: "Code";
|
|
15
|
+
readonly "File has changed": "File has changed";
|
|
16
|
+
readonly "File is missing": "File is missing";
|
|
17
|
+
readonly Formatting: "Formatting";
|
|
18
|
+
readonly Heading: "Heading";
|
|
19
|
+
readonly "Hide uploads": "Hide uploads";
|
|
20
|
+
readonly "Images from other websites are not pasted; save them first and add them as files": "Images from other websites are not pasted; save them first and add them as files";
|
|
21
|
+
readonly Images: "Images";
|
|
22
|
+
readonly Italic: "Italic";
|
|
23
|
+
readonly "Link address": "Link address";
|
|
24
|
+
readonly Link: "Link";
|
|
25
|
+
readonly "Links start with http://, https:// or mailto:": "Links start with http://, https:// or mailto:";
|
|
26
|
+
readonly "Mention someone": "Mention someone";
|
|
27
|
+
readonly "Next file": "Next file";
|
|
28
|
+
readonly "Numbered list": "Numbered list";
|
|
29
|
+
readonly "Open {name}": "Open {name}";
|
|
30
|
+
readonly "Previous file": "Previous file";
|
|
31
|
+
readonly "Processing {count}": "Processing {count}";
|
|
32
|
+
readonly Processing: "Processing";
|
|
33
|
+
readonly Quote: "Quote";
|
|
34
|
+
readonly "Remove link": "Remove link";
|
|
35
|
+
readonly "Retry {name}": "Retry {name}";
|
|
36
|
+
readonly "Retry all": "Retry all";
|
|
37
|
+
readonly Send: "Send";
|
|
38
|
+
readonly Sending: "Sending";
|
|
39
|
+
readonly "Show all {count} files": "Show all {count} files";
|
|
40
|
+
readonly "Show uploads": "Show uploads";
|
|
41
|
+
readonly Strikethrough: "Strikethrough";
|
|
42
|
+
readonly Subheading: "Subheading";
|
|
43
|
+
readonly "Upload failed": "Upload failed";
|
|
44
|
+
readonly "Uploaded {done} of {total}": "Uploaded {done} of {total}";
|
|
45
|
+
readonly Uploading: "Uploading";
|
|
46
|
+
readonly Uploads: "Uploads";
|
|
47
|
+
readonly "Wait for the images to finish uploading": "Wait for the images to finish uploading";
|
|
48
|
+
readonly Waiting: "Waiting";
|
|
49
|
+
readonly Uploaded: "Uploaded";
|
|
50
|
+
readonly Canceled: "Canceled";
|
|
3
51
|
readonly "Opens in a new tab": "Opens in a new tab";
|
|
4
52
|
readonly Download: "Download";
|
|
5
53
|
readonly Close: "Close";
|
package/dist/index.d.ts
CHANGED
|
@@ -131,12 +131,21 @@ export { default as StatTile } from './components/composite/stat-tile/StatTile.v
|
|
|
131
131
|
export type { StatTileTone } from './components/composite/stat-tile/StatTile.vue';
|
|
132
132
|
export { default as StatTileGroup } from './components/composite/stat-tile/StatTileGroup.vue';
|
|
133
133
|
export { default as CompletionToggle } from './components/composite/completion-toggle/CompletionToggle.vue';
|
|
134
|
-
export { default as MentionTextarea } from './components/composite/mention-textarea/MentionTextarea.vue';
|
|
135
134
|
export { default as CommentItem } from './components/composite/comment-item/CommentItem.vue';
|
|
136
|
-
export { mentionParts
|
|
135
|
+
export { mentionParts } from './lib/mentions';
|
|
136
|
+
export { default as MentionList } from './components/composite/mention-list/MentionList.vue';
|
|
137
137
|
export type { MentionCandidate, MentionPart } from './lib/mentions';
|
|
138
|
-
export {
|
|
139
|
-
export type {
|
|
138
|
+
export { richTextParts, richTextText, richTextFileIds } from './lib/richText';
|
|
139
|
+
export type { RichTextBlock, RichTextInline, RichTextList, RichTextListItem, RichTextOptions } from './lib/richText';
|
|
140
|
+
export { default as RichTextView } from './components/composite/rich-text-view/RichTextView.vue';
|
|
141
|
+
export { default as FileThumbs } from './components/composite/file-thumbs/FileThumbs.vue';
|
|
142
|
+
export { default as ImageLightbox } from './components/composite/image-lightbox/ImageLightbox.vue';
|
|
143
|
+
export { default as UploadQueue } from './components/composite/upload-queue/UploadQueue.vue';
|
|
144
|
+
export type { UploadQueueItem } from './components/composite/upload-queue/UploadQueue.vue';
|
|
145
|
+
export { useUploadQueue } from './lib/uploadQueue';
|
|
146
|
+
export type { UploadFunction, UploadQueueOptions, UploadStatus, UploadTask } from './lib/uploadQueue';
|
|
147
|
+
export { isPicture, isUnsupportedPicture } from './lib/files';
|
|
148
|
+
export type { FileItem, FileState } from './lib/files';
|
|
140
149
|
export type { DataTableColumn } from './components/composite/data-table/DataTable.vue';
|
|
141
150
|
export { default as DataGrid } from './components/composite/data-grid/DataGrid.vue';
|
|
142
151
|
export type { DataGridColumn, DataGridColumnWidths, DataGridLabels, ResolvedDataGridLabels, DataGridSort, DataGridGroup, DataGridExpandable, DataGridDraggable, DataGridReorder, DataGridCellUpdate, DataGridAdapter, DataGridCellSlotProps } from './components/composite/data-grid/DataGrid.vue';
|
|
@@ -246,6 +255,8 @@ export { default as OverflowToolbar } from './components/composite/overflow-tool
|
|
|
246
255
|
export { computeOverflowFit, ITEM_GAP } from './components/composite/overflow-toolbar/overflow';
|
|
247
256
|
export type { OverflowToolbarItem, OverflowToolbarMenuEntry, OverflowToolbarMoreMenu, OverflowToolbarMoreState, OverflowToolbarMoreText, } from './components/composite/overflow-toolbar/types';
|
|
248
257
|
export type { UiLocale } from './i18n/locale';
|
|
258
|
+
export { useUiText } from './i18n/text';
|
|
259
|
+
export type { UiTextKey } from './i18n/text';
|
|
249
260
|
export { filePickerText } from './i18n/filePicker';
|
|
250
261
|
export type { FilePickerText } from './i18n/filePicker';
|
|
251
262
|
export { default as Link } from './components/primitives/link/Link.vue';
|