@marianmeres/stuic 3.135.0 → 3.136.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CommentInput/CommentInput.svelte +186 -348
- package/dist/components/CommentInput/CommentInput.svelte.d.ts +42 -44
- package/dist/components/CommentInput/README.md +104 -77
- package/dist/components/CommentInput/index.css +29 -259
- package/dist/components/CommentInput/index.d.ts +1 -2
- package/dist/components/CommentInput/index.js +1 -1
- package/dist/components/MarkdownEditor/MarkdownEditor.svelte +10 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.svelte.d.ts +1 -0
- package/package.json +1 -1
- package/dist/components/CommentInput/_internal/render.d.ts +0 -24
- package/dist/components/CommentInput/_internal/render.js +0 -47
|
@@ -1,61 +1,62 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
|
-
import type {
|
|
3
|
-
import type { ValidateOptions } from "../../actions/validate.svelte.js";
|
|
2
|
+
import type { ValidateOptions, ValidationResult } from "../../actions/validate.svelte.js";
|
|
4
3
|
import type { THC } from "../Thc/Thc.svelte";
|
|
5
4
|
import type { InputWrapClassProps } from "../Input/types.js";
|
|
6
|
-
import type {
|
|
5
|
+
import type { MarkdownEditorMode, ToolbarItem, PromptFn } from "../MarkdownEditor/index.js";
|
|
7
6
|
type SnippetWithId = Snippet<[{
|
|
8
7
|
id: string;
|
|
9
8
|
}]>;
|
|
10
|
-
/** Active
|
|
11
|
-
export type CommentInputMode =
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
/** Active editing surface of the comment box (mirrors `MarkdownEditor`). */
|
|
10
|
+
export type CommentInputMode = MarkdownEditorMode;
|
|
11
|
+
/**
|
|
12
|
+
* Minimal default toolbar for the comment box — kept intentionally light
|
|
13
|
+
* (GitHub-composer feel). Pass your own `toolbar` array to customize.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DEFAULT_COMMENT_TOOLBAR: ToolbarItem[];
|
|
16
|
+
export interface Props extends InputWrapClassProps {
|
|
17
|
+
/** Comment content (markdown). Bindable. */
|
|
14
18
|
value?: string;
|
|
15
|
-
/** Active
|
|
19
|
+
/** Active editing surface. Bindable. Default `"source"` (opens on raw markdown). */
|
|
16
20
|
mode?: CommentInputMode;
|
|
17
|
-
/** The
|
|
18
|
-
input?:
|
|
19
|
-
/** Name attribute of the
|
|
21
|
+
/** The editor surface wrapper element. Bindable (read). */
|
|
22
|
+
input?: HTMLDivElement;
|
|
23
|
+
/** Name attribute of the hidden input, for native form submission. */
|
|
20
24
|
name?: string;
|
|
21
25
|
label?: SnippetWithId | THC;
|
|
22
26
|
description?: SnippetWithId | THC;
|
|
23
27
|
class?: string;
|
|
24
28
|
id?: string;
|
|
25
|
-
tabindex?: number;
|
|
26
29
|
renderSize?: "sm" | "md" | "lg" | string;
|
|
27
30
|
required?: boolean;
|
|
28
31
|
disabled?: boolean;
|
|
29
32
|
placeholder?: string;
|
|
30
33
|
validate?: boolean | Omit<ValidateOptions, "setValidationResult">;
|
|
31
|
-
/** Trim surrounding whitespace on blur. Default `true`. */
|
|
32
|
-
useTrim?: boolean;
|
|
33
|
-
/** Grow the textarea with its content (up to `max`). Default `true`. */
|
|
34
|
-
useAutogrow?: boolean | {
|
|
35
|
-
enabled?: boolean;
|
|
36
|
-
max?: number;
|
|
37
|
-
};
|
|
38
|
-
/** Show the Write/Preview tabs. Default `true`. Set `false` for a plain markdown textarea. */
|
|
39
|
-
showTabs?: boolean;
|
|
40
|
-
/** Label for the "write" tab. Default `"Write"`. */
|
|
41
|
-
writeLabel?: string;
|
|
42
|
-
/** Label for the "preview" tab. Default `"Preview"`. */
|
|
43
|
-
previewLabel?: string;
|
|
44
|
-
/** Show the subtle "Markdown supported" hint in the tab bar. Default `true`. */
|
|
45
|
-
showMarkdownHint?: boolean;
|
|
46
|
-
/** Text of the markdown hint. Default `"Markdown supported"`. */
|
|
47
|
-
markdownHintLabel?: string;
|
|
48
|
-
/** Placeholder shown in the Preview tab when there is nothing to render. */
|
|
49
|
-
previewEmptyLabel?: string;
|
|
50
|
-
/** Text shown in the Preview tab while the renderer is (lazy-)loading. */
|
|
51
|
-
previewLoadingLabel?: string;
|
|
52
34
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* is used (lazy-loaded; requires the optional `marked` / `dompurify` peers).
|
|
35
|
+
* Formatting toolbar. `true` shows {@link DEFAULT_COMMENT_TOOLBAR}, `false`
|
|
36
|
+
* hides it, or pass an ordered array of {@link ToolbarItem}s (`"|"` for a
|
|
37
|
+
* separator). Default {@link DEFAULT_COMMENT_TOOLBAR}.
|
|
57
38
|
*/
|
|
58
|
-
|
|
39
|
+
toolbar?: boolean | ToolbarItem[];
|
|
40
|
+
/** Toolbar used on mobile / touch devices. Same shape as `toolbar`. */
|
|
41
|
+
mobileToolbar?: boolean | ToolbarItem[];
|
|
42
|
+
/** Start in source mode on mobile / touch devices. Default `true`. */
|
|
43
|
+
autoSourceOnMobile?: boolean;
|
|
44
|
+
/** Media query defining "mobile". Default `"(pointer: coarse) and (max-width: 640px)"`. */
|
|
45
|
+
mobileQuery?: string;
|
|
46
|
+
/** URL prompt used by the link/image buttons. Defaults to `window.prompt`. */
|
|
47
|
+
prompt?: PromptFn;
|
|
48
|
+
/** Cap the editing surface height (long content scrolls inside). Default `32rem`. */
|
|
49
|
+
maxHeight?: number | string;
|
|
50
|
+
/** Also cap the surface to the parent's available height. Default `true`. */
|
|
51
|
+
capToParent?: boolean;
|
|
52
|
+
/** Show the WYSIWYG/Source mode toggle. Default `true`. */
|
|
53
|
+
showModeToggle?: boolean;
|
|
54
|
+
/** Toggle label while in WYSIWYG mode (switches to source). Default `"Source"`. */
|
|
55
|
+
sourceLabel?: string;
|
|
56
|
+
/** Toggle label while in source mode (switches to WYSIWYG). Default `"Preview"`. */
|
|
57
|
+
previewLabel?: string;
|
|
58
|
+
/** Wire ⌘/Ctrl+B / I / K to bold / italic / link. Default `true`. */
|
|
59
|
+
useShortcuts?: boolean;
|
|
59
60
|
/**
|
|
60
61
|
* Submit handler. Receives the current value. May be async — the submit
|
|
61
62
|
* button shows a spinner and the box is disabled while it resolves.
|
|
@@ -73,7 +74,7 @@ export interface Props extends Omit<HTMLTextareaAttributes, "value" | "class" |
|
|
|
73
74
|
showSubmit?: boolean;
|
|
74
75
|
/** Show the cancel button. Defaults to `true` when `onCancel` is set. */
|
|
75
76
|
showCancel?: boolean;
|
|
76
|
-
/** Submit on ⌘/Ctrl+Enter while the
|
|
77
|
+
/** Submit on ⌘/Ctrl+Enter while the editor is focused. Default `true`. */
|
|
77
78
|
submitOnModEnter?: boolean;
|
|
78
79
|
/** Clear the value after a successful submit. Default `true`. */
|
|
79
80
|
clearOnSubmit?: boolean;
|
|
@@ -90,17 +91,14 @@ export interface Props extends Omit<HTMLTextareaAttributes, "value" | "class" |
|
|
|
90
91
|
avatar?: SnippetWithId | THC;
|
|
91
92
|
/** Extra content rendered in the footer, left of the buttons (e.g. attach). */
|
|
92
93
|
footer?: Snippet;
|
|
93
|
-
/** Classes for the
|
|
94
|
+
/** Classes for the editor surface element (forwarded to MarkdownEditor). */
|
|
94
95
|
classInput?: string;
|
|
95
|
-
/** Classes for the
|
|
96
|
+
/** Classes for the toolbar bar (forwarded to MarkdownEditor's `classToolbar`). */
|
|
96
97
|
classBar?: string;
|
|
97
|
-
/** Classes for the preview panel. */
|
|
98
|
-
classPreview?: string;
|
|
99
98
|
/** Classes for the footer (button row). */
|
|
100
99
|
classFooter?: string;
|
|
101
100
|
style?: string;
|
|
102
101
|
}
|
|
103
|
-
import { type ValidationResult } from "../../actions/validate.svelte.js";
|
|
104
102
|
declare const CommentInput: import("svelte").Component<Props, {
|
|
105
103
|
validate: () => ValidationResult | undefined;
|
|
106
104
|
clearValidation: () => void;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# CommentInput
|
|
2
2
|
|
|
3
|
-
A GitHub-style comment
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
A GitHub-style **comment composer** built on top of [`MarkdownEditor`](../MarkdownEditor/README.md).
|
|
4
|
+
It pairs a rich **WYSIWYG / source** markdown editor (a minimal formatting toolbar
|
|
5
|
+
plus a built-in **Source** toggle) with an optional avatar gutter and a
|
|
6
|
+
submit / cancel footer. Field chrome (label / description / validation / sizing /
|
|
7
|
+
theming) comes from the same `InputWrap` scaffold as the `Field*` family, so it
|
|
8
|
+
matches the rest of the form family.
|
|
9
|
+
|
|
10
|
+
Where `MarkdownEditor` is the full-featured editor, `CommentInput` is the
|
|
11
|
+
lightweight, opinionated wrapper for the common "leave a comment / reply" use
|
|
12
|
+
case: a clean minimal toolbar, an avatar, a submit button, and
|
|
13
|
+
⌘/Ctrl+Enter-to-send — without you having to wire any of it up.
|
|
11
14
|
|
|
12
15
|
```svelte
|
|
13
16
|
<script>
|
|
@@ -28,90 +31,114 @@ comments, replies and short discussion input.
|
|
|
28
31
|
/>
|
|
29
32
|
```
|
|
30
33
|
|
|
31
|
-
##
|
|
34
|
+
## Dependencies
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
Because the editing surface **is** `MarkdownEditor`, `CommentInput` inherits its
|
|
37
|
+
**optional peer dependencies** — Milkdown (WYSIWYG) and CodeMirror (source) — which
|
|
38
|
+
are **lazy-loaded** the first time the editor mounts:
|
|
36
39
|
|
|
37
40
|
```sh
|
|
38
|
-
npm i
|
|
41
|
+
npm i @milkdown/core @milkdown/ctx @milkdown/plugin-history \
|
|
42
|
+
@milkdown/plugin-listener @milkdown/preset-commonmark @milkdown/preset-gfm \
|
|
43
|
+
@milkdown/prose @milkdown/transformer @milkdown/utils \
|
|
44
|
+
@codemirror/commands @codemirror/lang-markdown @codemirror/language \
|
|
45
|
+
@codemirror/language-data @codemirror/state @codemirror/view
|
|
39
46
|
```
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
This is the same peer set as `MarkdownEditor` — see its README for the
|
|
49
|
+
authoritative list. If they aren't installed, the surface stays empty and a
|
|
50
|
+
console error explains why.
|
|
51
|
+
|
|
52
|
+
## Toolbar
|
|
53
|
+
|
|
54
|
+
`toolbar` accepts `true` (the minimal default), `false` (hidden), or an ordered
|
|
55
|
+
array of items (`"|"` for a separator):
|
|
43
56
|
|
|
44
57
|
```svelte
|
|
45
|
-
|
|
58
|
+
<!-- Minimal default: ["bold", "italic", "link", "codeBlock"] -->
|
|
59
|
+
<CommentInput bind:value onSubmit={post} />
|
|
60
|
+
|
|
61
|
+
<!-- Custom set -->
|
|
62
|
+
<CommentInput
|
|
63
|
+
bind:value
|
|
64
|
+
toolbar={["bold", "italic", "|", "bulletList", "orderedList", "|", "link"]}
|
|
65
|
+
onSubmit={post}
|
|
66
|
+
/>
|
|
67
|
+
|
|
68
|
+
<!-- No toolbar (still WYSIWYG, drives via shortcuts / the Source toggle) -->
|
|
69
|
+
<CommentInput bind:value toolbar={false} onSubmit={post} />
|
|
46
70
|
```
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
72
|
+
Available items: `bold`, `italic`, `heading1`–`heading6`, `link`, `image`,
|
|
73
|
+
`bulletList`, `orderedList`, `blockquote`, `codeBlock`, `hr`, `hardBreak`, `undo`,
|
|
74
|
+
`redo` (and `"|"`). The default is exported as `DEFAULT_COMMENT_TOOLBAR`.
|
|
75
|
+
|
|
76
|
+
## Keyboard
|
|
77
|
+
|
|
78
|
+
| Shortcut | Action | Prop |
|
|
79
|
+
| ------------------ | -------------------- | ------------------ |
|
|
80
|
+
| ⌘/Ctrl + Enter | Submit | `submitOnModEnter` |
|
|
81
|
+
| ⌘/Ctrl + B / I / K | Bold / Italic / Link | `useShortcuts` |
|
|
51
82
|
|
|
52
83
|
## Props
|
|
53
84
|
|
|
54
|
-
| Prop | Type
|
|
55
|
-
| ------------------------- |
|
|
56
|
-
| `value` | `string` (bindable)
|
|
57
|
-
| `mode` | `"
|
|
58
|
-
| `input` | `
|
|
59
|
-
| `name` | `string`
|
|
60
|
-
| `label` | `THC \| Snippet`
|
|
61
|
-
| `description` | `THC \| Snippet`
|
|
62
|
-
| `placeholder` | `string`
|
|
63
|
-
| `renderSize` | `"sm" \| "md" \| "lg" \| string`
|
|
64
|
-
| `required` | `boolean`
|
|
65
|
-
| `disabled` | `boolean`
|
|
66
|
-
| `validate` | `boolean \| ValidateOptions`
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
85
|
+
| Prop | Type | Default | Description |
|
|
86
|
+
| ------------------------- | ------------------------------------------ | ------------------------- | --------------------------------------------------------- |
|
|
87
|
+
| `value` | `string` (bindable) | `""` | Comment content (markdown). |
|
|
88
|
+
| `mode` | `"wysiwyg" \| "source"` (bindable) | `"source"` | Active editing surface (opens on raw markdown). |
|
|
89
|
+
| `input` | `HTMLDivElement` (bindable) | — | The editor surface wrapper element. |
|
|
90
|
+
| `name` | `string` | — | Hidden input `name`, for native form submission. |
|
|
91
|
+
| `label` | `THC \| Snippet` | `""` | Field label (via InputWrap). |
|
|
92
|
+
| `description` | `THC \| Snippet` | — | Collapsible hint below the box. |
|
|
93
|
+
| `placeholder` | `string` | — | Editor placeholder. |
|
|
94
|
+
| `renderSize` | `"sm" \| "md" \| "lg" \| string` | `"md"` | Size variant. |
|
|
95
|
+
| `required` | `boolean` | `false` | Mark required + enforce on validation. |
|
|
96
|
+
| `disabled` | `boolean` | `false` | Disable the whole box. |
|
|
97
|
+
| `validate` | `boolean \| ValidateOptions` | — | Enable validation (same contract as `MarkdownEditor`). |
|
|
98
|
+
| `toolbar` | `boolean \| ToolbarItem[]` | `DEFAULT_COMMENT_TOOLBAR` | Formatting toolbar config. |
|
|
99
|
+
| `mobileToolbar` | `boolean \| ToolbarItem[]` | MarkdownEditor default | Toolbar on touch devices. |
|
|
100
|
+
| `autoSourceOnMobile` | `boolean` | `true` | Start in source mode on mobile. |
|
|
101
|
+
| `mobileQuery` | `string` | `(pointer: coarse) …` | Media query defining "mobile". |
|
|
102
|
+
| `prompt` | `PromptFn` | `window.prompt` | URL prompt used by the link/image buttons. |
|
|
103
|
+
| `maxHeight` | `number \| string` | `32rem` | Cap the editing surface height (scrolls inside). |
|
|
104
|
+
| `capToParent` | `boolean` | `true` | Also cap the surface to the parent's available height. |
|
|
105
|
+
| `showModeToggle` | `boolean` | `true` | Show the WYSIWYG/Source toggle. |
|
|
106
|
+
| `sourceLabel` | `string` | `"Source"` | Toggle label while in WYSIWYG mode. |
|
|
107
|
+
| `previewLabel` | `string` | `"Preview"` | Toggle label while in source mode. |
|
|
108
|
+
| `useShortcuts` | `boolean` | `true` | Wire ⌘/Ctrl+B / I / K to bold / italic / link. |
|
|
109
|
+
| `onSubmit` | `(value: string) => void \| Promise<void>` | — | Submit handler. Async → spinner + disabled while pending. |
|
|
110
|
+
| `onCancel` | `() => void` | — | Cancel handler. |
|
|
111
|
+
| `onChange` | `(value: string) => void` | — | Fired on every edit. |
|
|
112
|
+
| `submitLabel` | `string` | `"Comment"` | Submit button label. |
|
|
113
|
+
| `cancelLabel` | `string` | `"Cancel"` | Cancel button label. |
|
|
114
|
+
| `showSubmit` | `boolean` | `!!onSubmit` | Show the submit button. |
|
|
115
|
+
| `showCancel` | `boolean` | `!!onCancel` | Show the cancel button. |
|
|
116
|
+
| `submitOnModEnter` | `boolean` | `true` | Submit on ⌘/Ctrl+Enter. |
|
|
117
|
+
| `clearOnSubmit` | `boolean` | `true` | Clear value after a successful submit. |
|
|
118
|
+
| `submitDisabledWhenEmpty` | `boolean` | `true` | Disable submit when empty/whitespace. |
|
|
119
|
+
| `busy` | `boolean` | `false` | External busy state (disables box + submit). |
|
|
120
|
+
| `avatar` | `THC \| Snippet` | — | Optional gutter to the left of the box. |
|
|
121
|
+
| `footer` | `Snippet` | — | Extra footer content, left of the buttons. |
|
|
90
122
|
|
|
91
123
|
Plus the standard `InputWrap` layout props (`labelAfter`, `below`, `labelLeft`,
|
|
92
|
-
`labelLeftWidth`, `labelLeftBreakpoint`) and `class*` props (`classInput
|
|
93
|
-
`classBar
|
|
124
|
+
`labelLeftWidth`, `labelLeftBreakpoint`) and `class*` props (`classInput` →
|
|
125
|
+
editor surface, `classBar` → toolbar, `classFooter` → button row, and the shared
|
|
126
|
+
`InputWrapClassProps`).
|
|
94
127
|
|
|
95
128
|
## Imperative API
|
|
96
129
|
|
|
97
130
|
Bind the component (`bind:this`) to call: `validate()`, `clearValidation()`,
|
|
98
|
-
`getValidation()`, `focus()`, `scrollIntoView()`, `submit()`.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
| `--stuic-comment-input-
|
|
110
|
-
| `--stuic-comment-input-
|
|
111
|
-
| `--stuic-comment-input-
|
|
112
|
-
| `--stuic-comment-input-padding-y` | `--stuic-input-padding-y-*` |
|
|
113
|
-
| `--stuic-comment-input-font-size` | `--stuic-input-font-size-*` |
|
|
114
|
-
| `--stuic-comment-input-min-height` | `5rem` (`4rem` sm / `7rem` lg) |
|
|
115
|
-
| `--stuic-comment-input-gap` | `0.625rem` |
|
|
116
|
-
| `--stuic-comment-input-tab-active-bg` | subtle overlay |
|
|
117
|
-
| `--stuic-comment-input-code-bg` | subtle overlay |
|
|
131
|
+
`getValidation()`, `focus()`, `scrollIntoView()`, `submit()`. All delegate to the
|
|
132
|
+
embedded `MarkdownEditor`.
|
|
133
|
+
|
|
134
|
+
## Theming
|
|
135
|
+
|
|
136
|
+
The editor card, toolbar and field chrome are themed via the
|
|
137
|
+
`--stuic-markdown-editor-*` and shared `--stuic-input-*` tokens (see the
|
|
138
|
+
`MarkdownEditor` README). `CommentInput` adds only its own layout tokens:
|
|
139
|
+
|
|
140
|
+
| Variable | Default | Description |
|
|
141
|
+
| ---------------------------------- | ---------- | ------------------------------------------ |
|
|
142
|
+
| `--stuic-comment-input-gap` | `0.625rem` | Gap between the avatar and the box. |
|
|
143
|
+
| `--stuic-comment-input-footer-gap` | `0.5rem` | Gap between the editor and the footer. |
|
|
144
|
+
| `--stuic-comment-input-min-height` | `5rem` | Editor min-height (`4rem` sm / `7rem` lg). |
|