@marianmeres/stuic 3.134.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.
@@ -475,9 +475,29 @@ on submit (and round-trips on reopen). Single-select fields ignore the prop.
475
475
  ## FieldAssets
476
476
 
477
477
  Asset/image upload field with an inline thumbnail grid and a built-in lightbox preview
478
- (`AssetsPreview`). Files are added via the picker button or by dragging them onto the
479
- field; each shows as a thumbnail with its filename (and an upload progress indicator while
480
- processing).
478
+ (`AssetsPreview`). Files are added via the picker button, by dragging them onto the field,
479
+ or (opt-in) by pasting from the clipboard; each shows as a thumbnail with its filename (and
480
+ an upload progress indicator while processing).
481
+
482
+ ### Paste from the clipboard (`pasteable`)
483
+
484
+ Opt in with `pasteable` to let users paste image/file data from the clipboard (Ctrl/Cmd-V) —
485
+ a screenshot, a copied image, etc. It is **focus-scoped**: a paste is consumed only while the
486
+ field (or a control inside it) holds focus. Clicking anywhere in the field focuses it, so no
487
+ Tab is needed, and a `:focus-within` ring on the input box signals the paste-ready state.
488
+ Pasted files go through the same path as the picker and drag-and-drop, so `accept`,
489
+ `cardinality` and `processAssets` all apply. No-op unless `processAssets` is provided.
490
+
491
+ ```svelte
492
+ <FieldAssets
493
+ label="Screenshots"
494
+ name="screenshots"
495
+ bind:value
496
+ {processAssets}
497
+ accept="image/*"
498
+ pasteable
499
+ />
500
+ ```
481
501
 
482
502
  ### Ordering the assets (`ordered`)
483
503
 
@@ -529,6 +529,16 @@
529
529
  export function toggleMode(): void {
530
530
  toggleModeInternal();
531
531
  }
532
+ /**
533
+ * Imperatively run a toolbar command — same effect as clicking the matching
534
+ * toolbar button. Useful for wiring keyboard shortcuts (e.g. ⌘/Ctrl+B) from a
535
+ * host component. No-op while the backend is (re)loading. The `"|"` separator
536
+ * is not a command.
537
+ */
538
+ export function command(item: Exclude<ToolbarItem, "|">): void {
539
+ const btn = TOOLBAR_REGISTRY[item];
540
+ if (btn && activeHandle) btn.run(activeHandle.commands);
541
+ }
532
542
  </script>
533
543
 
534
544
  <InputWrap
@@ -99,6 +99,7 @@ declare const MarkdownEditor: import("svelte").Component<Props, {
99
99
  scrollIntoView: (opts?: ScrollIntoViewOptions) => void;
100
100
  getMarkdown: () => string;
101
101
  toggleMode: () => void;
102
+ command: (item: Exclude<ToolbarItem, "|">) => void;
102
103
  }, "value" | "input" | "mode">;
103
104
  type MarkdownEditor = ReturnType<typeof MarkdownEditor>;
104
105
  export default MarkdownEditor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.134.0",
3
+ "version": "3.136.0",
4
4
  "packageManager": "pnpm@11.5.0",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -1,24 +0,0 @@
1
- /**
2
- * Default Preview renderer for {@link CommentInput}: turns a markdown string into
3
- * **sanitized** HTML.
4
- *
5
- * `marked` and `dompurify` are declared as *optional* peer dependencies and are
6
- * imported dynamically the first time a Preview tab is opened — consumers who
7
- * never preview (or who pass their own `renderMarkdown`) don't pay for them, and
8
- * a consumer who hasn't installed them gets a caught error (handled by the
9
- * component) rather than a hard build failure. Mirrors the lazy-load convention
10
- * used by `MarkdownEditor` for its Milkdown/CodeMirror backends.
11
- *
12
- * Sanitization is non-negotiable here: comment text is untrusted user content and
13
- * `marked` emits raw HTML embedded in markdown verbatim (an XSS vector). Every
14
- * code path that returns HTML runs it through DOMPurify first.
15
- */
16
- /** A markdown-to-HTML renderer. Return value may be sync or async. */
17
- export type MarkdownRenderer = (markdown: string) => string | Promise<string>;
18
- /**
19
- * Render markdown to sanitized HTML using the bundled (lazy) marked + DOMPurify
20
- * pipeline. Throws if the optional peers aren't installed (the caller catches
21
- * this and shows a fallback). SSR-safe: returns an empty string off the DOM,
22
- * since DOMPurify needs a `window` to sanitize against.
23
- */
24
- export declare function renderMarkdownSafe(markdown: string): Promise<string>;
@@ -1,47 +0,0 @@
1
- /**
2
- * Default Preview renderer for {@link CommentInput}: turns a markdown string into
3
- * **sanitized** HTML.
4
- *
5
- * `marked` and `dompurify` are declared as *optional* peer dependencies and are
6
- * imported dynamically the first time a Preview tab is opened — consumers who
7
- * never preview (or who pass their own `renderMarkdown`) don't pay for them, and
8
- * a consumer who hasn't installed them gets a caught error (handled by the
9
- * component) rather than a hard build failure. Mirrors the lazy-load convention
10
- * used by `MarkdownEditor` for its Milkdown/CodeMirror backends.
11
- *
12
- * Sanitization is non-negotiable here: comment text is untrusted user content and
13
- * `marked` emits raw HTML embedded in markdown verbatim (an XSS vector). Every
14
- * code path that returns HTML runs it through DOMPurify first.
15
- */
16
- // Cache the resolved (marked + DOMPurify) pipeline so the dynamic imports and
17
- // DOMPurify instance creation happen at most once per page.
18
- let cached = null;
19
- async function load() {
20
- if (cached)
21
- return cached;
22
- const [{ marked }, dompurify] = await Promise.all([
23
- import("marked"),
24
- import("dompurify"),
25
- ]);
26
- // DOMPurify's default export is the instance in a browser/DOM context.
27
- const DOMPurify = dompurify.default ?? dompurify;
28
- cached = async (markdown) => {
29
- // GitHub-flavored markdown + soft line breaks → <br>, matching how comment
30
- // boxes (incl. GitHub's) treat single newlines.
31
- const html = await marked.parse(markdown ?? "", { gfm: true, breaks: true });
32
- return DOMPurify.sanitize(html);
33
- };
34
- return cached;
35
- }
36
- /**
37
- * Render markdown to sanitized HTML using the bundled (lazy) marked + DOMPurify
38
- * pipeline. Throws if the optional peers aren't installed (the caller catches
39
- * this and shows a fallback). SSR-safe: returns an empty string off the DOM,
40
- * since DOMPurify needs a `window` to sanitize against.
41
- */
42
- export async function renderMarkdownSafe(markdown) {
43
- if (typeof window === "undefined")
44
- return "";
45
- const render = await load();
46
- return render(markdown);
47
- }