@joewinke/jatui 0.36.3 → 0.38.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/artifact-blocks/AttachmentChip.svelte +66 -0
- package/dist/artifact-blocks/AttachmentChip.svelte.d.ts +7 -0
- package/dist/artifact-blocks/BlockComments.svelte +309 -0
- package/dist/artifact-blocks/BlockComments.svelte.d.ts +33 -0
- package/dist/artifact-blocks/BlockRenderer.svelte +674 -0
- package/dist/artifact-blocks/BlockRenderer.svelte.d.ts +55 -0
- package/dist/artifact-blocks/BlockVerdict.svelte +151 -0
- package/dist/artifact-blocks/BlockVerdict.svelte.d.ts +13 -0
- package/dist/artifact-blocks/BlocksArtifactView.svelte +1616 -0
- package/dist/artifact-blocks/BlocksArtifactView.svelte.d.ts +113 -0
- package/dist/artifact-blocks/CONTRACT.md +225 -0
- package/dist/artifact-blocks/CommentPill.svelte +49 -0
- package/dist/artifact-blocks/CommentPill.svelte.d.ts +16 -0
- package/dist/artifact-blocks/FoldedRounds.svelte +95 -0
- package/dist/artifact-blocks/FoldedRounds.svelte.d.ts +9 -0
- package/dist/artifact-blocks/Glyph.svelte +54 -0
- package/dist/artifact-blocks/Glyph.svelte.d.ts +10 -0
- package/dist/artifact-blocks/HistoryScrubber.svelte +500 -0
- package/dist/artifact-blocks/HistoryScrubber.svelte.d.ts +15 -0
- package/dist/artifact-blocks/Markdown.svelte +186 -0
- package/dist/artifact-blocks/Markdown.svelte.d.ts +30 -0
- package/dist/artifact-blocks/NoteComposer.svelte +31 -0
- package/dist/artifact-blocks/NoteComposer.svelte.d.ts +8 -0
- package/dist/artifact-blocks/PlainComposer.svelte +200 -0
- package/dist/artifact-blocks/PlainComposer.svelte.d.ts +15 -0
- package/dist/artifact-blocks/SectionTools.svelte +102 -0
- package/dist/artifact-blocks/SectionTools.svelte.d.ts +19 -0
- package/dist/artifact-blocks/adapter.d.ts +13 -0
- package/dist/artifact-blocks/adapter.js +31 -0
- package/dist/artifact-blocks/autoSend.d.ts +49 -0
- package/dist/artifact-blocks/autoSend.js +103 -0
- package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte +557 -0
- package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte.d.ts +48 -0
- package/dist/artifact-blocks/blocks/actions/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/actions/block.js +74 -0
- package/dist/artifact-blocks/blocks/actions/requests.d.ts +62 -0
- package/dist/artifact-blocks/blocks/actions/requests.js +26 -0
- package/dist/artifact-blocks/blocks/actions/schema.d.ts +168 -0
- package/dist/artifact-blocks/blocks/actions/schema.js +253 -0
- package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte +779 -0
- package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte.d.ts +40 -0
- package/dist/artifact-blocks/blocks/callout/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/callout/block.js +39 -0
- package/dist/artifact-blocks/blocks/callout/schema.d.ts +72 -0
- package/dist/artifact-blocks/blocks/callout/schema.js +115 -0
- package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte +875 -0
- package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte.d.ts +59 -0
- package/dist/artifact-blocks/blocks/chart/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/chart/block.js +70 -0
- package/dist/artifact-blocks/blocks/chart/schema.d.ts +171 -0
- package/dist/artifact-blocks/blocks/chart/schema.js +498 -0
- package/dist/artifact-blocks/blocks/chart/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/chart/thumb.js +201 -0
- package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte +1048 -0
- package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte.d.ts +16 -0
- package/dist/artifact-blocks/blocks/checklist/Icon.svelte +105 -0
- package/dist/artifact-blocks/blocks/checklist/Icon.svelte.d.ts +17 -0
- package/dist/artifact-blocks/blocks/checklist/block.d.ts +10 -0
- package/dist/artifact-blocks/blocks/checklist/block.js +63 -0
- package/dist/artifact-blocks/blocks/checklist/itemReview.d.ts +16 -0
- package/dist/artifact-blocks/blocks/checklist/itemReview.js +63 -0
- package/dist/artifact-blocks/blocks/checklist/labels.d.ts +62 -0
- package/dist/artifact-blocks/blocks/checklist/labels.js +96 -0
- package/dist/artifact-blocks/blocks/checklist/retest.d.ts +43 -0
- package/dist/artifact-blocks/blocks/checklist/retest.js +68 -0
- package/dist/artifact-blocks/blocks/checklist/schema.d.ts +84 -0
- package/dist/artifact-blocks/blocks/checklist/schema.js +91 -0
- package/dist/artifact-blocks/blocks/code/CodeBlock.svelte +128 -0
- package/dist/artifact-blocks/blocks/code/CodeBlock.svelte.d.ts +12 -0
- package/dist/artifact-blocks/blocks/code/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/code/block.js +31 -0
- package/dist/artifact-blocks/blocks/code/highlight.d.ts +34 -0
- package/dist/artifact-blocks/blocks/code/highlight.js +280 -0
- package/dist/artifact-blocks/blocks/code/schema.d.ts +32 -0
- package/dist/artifact-blocks/blocks/code/schema.js +39 -0
- package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte +290 -0
- package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte.d.ts +29 -0
- package/dist/artifact-blocks/blocks/collage/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/collage/block.js +29 -0
- package/dist/artifact-blocks/blocks/collage/schema.d.ts +52 -0
- package/dist/artifact-blocks/blocks/collage/schema.js +86 -0
- package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte +484 -0
- package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte.d.ts +25 -0
- package/dist/artifact-blocks/blocks/compare/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/compare/block.js +32 -0
- package/dist/artifact-blocks/blocks/compare/schema.d.ts +74 -0
- package/dist/artifact-blocks/blocks/compare/schema.js +148 -0
- package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte +392 -0
- package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte.d.ts +30 -0
- package/dist/artifact-blocks/blocks/diagram/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/diagram/block.js +50 -0
- package/dist/artifact-blocks/blocks/diagram/constants.d.ts +48 -0
- package/dist/artifact-blocks/blocks/diagram/constants.js +53 -0
- package/dist/artifact-blocks/blocks/diagram/schema.d.ts +161 -0
- package/dist/artifact-blocks/blocks/diagram/schema.js +621 -0
- package/dist/artifact-blocks/blocks/diagram/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/diagram/thumb.js +157 -0
- package/dist/artifact-blocks/blocks/diagram/types.d.ts +74 -0
- package/dist/artifact-blocks/blocks/diagram/types.js +1 -0
- package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte +81 -0
- package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte.d.ts +10 -0
- package/dist/artifact-blocks/blocks/diff/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/diff/block.js +36 -0
- package/dist/artifact-blocks/blocks/diff/schema.d.ts +18 -0
- package/dist/artifact-blocks/blocks/diff/schema.js +35 -0
- package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte +1055 -0
- package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/diff-review/block.d.ts +15 -0
- package/dist/artifact-blocks/blocks/diff-review/block.js +64 -0
- package/dist/artifact-blocks/blocks/diff-review/decisions.d.ts +57 -0
- package/dist/artifact-blocks/blocks/diff-review/decisions.js +80 -0
- package/dist/artifact-blocks/blocks/diff-review/schema.d.ts +13 -0
- package/dist/artifact-blocks/blocks/diff-review/schema.js +84 -0
- package/dist/artifact-blocks/blocks/diff-review/types.d.ts +35 -0
- package/dist/artifact-blocks/blocks/diff-review/types.js +1 -0
- package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte +145 -0
- package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/explainer/block.d.ts +8 -0
- package/dist/artifact-blocks/blocks/explainer/block.js +21 -0
- package/dist/artifact-blocks/blocks/explainer/schema.d.ts +26 -0
- package/dist/artifact-blocks/blocks/explainer/schema.js +69 -0
- package/dist/artifact-blocks/blocks/group-content.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-content.js +16 -0
- package/dist/artifact-blocks/blocks/group-data.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-data.js +7 -0
- package/dist/artifact-blocks/blocks/group-review.d.ts +10 -0
- package/dist/artifact-blocks/blocks/group-review.js +12 -0
- package/dist/artifact-blocks/blocks/group-visual.d.ts +17 -0
- package/dist/artifact-blocks/blocks/group-visual.js +14 -0
- package/dist/artifact-blocks/blocks/map/MapBlock.svelte +413 -0
- package/dist/artifact-blocks/blocks/map/MapBlock.svelte.d.ts +53 -0
- package/dist/artifact-blocks/blocks/map/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/map/block.js +62 -0
- package/dist/artifact-blocks/blocks/map/schema.d.ts +123 -0
- package/dist/artifact-blocks/blocks/map/schema.js +113 -0
- package/dist/artifact-blocks/blocks/map/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/map/thumb.js +69 -0
- package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte +33 -0
- package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte.d.ts +15 -0
- package/dist/artifact-blocks/blocks/markdown/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/markdown/block.js +28 -0
- package/dist/artifact-blocks/blocks/markdown/render.d.ts +17 -0
- package/dist/artifact-blocks/blocks/markdown/render.js +115 -0
- package/dist/artifact-blocks/blocks/markdown/schema.d.ts +10 -0
- package/dist/artifact-blocks/blocks/markdown/schema.js +23 -0
- package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte +2112 -0
- package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/media-picker/block.d.ts +24 -0
- package/dist/artifact-blocks/blocks/media-picker/block.js +137 -0
- package/dist/artifact-blocks/blocks/media-picker/choices.d.ts +28 -0
- package/dist/artifact-blocks/blocks/media-picker/choices.js +35 -0
- package/dist/artifact-blocks/blocks/media-picker/decisions.d.ts +51 -0
- package/dist/artifact-blocks/blocks/media-picker/decisions.js +75 -0
- package/dist/artifact-blocks/blocks/media-picker/schema.d.ts +7 -0
- package/dist/artifact-blocks/blocks/media-picker/schema.js +199 -0
- package/dist/artifact-blocks/blocks/media-picker/types.d.ts +92 -0
- package/dist/artifact-blocks/blocks/media-picker/types.js +1 -0
- package/dist/artifact-blocks/blocks/media-picker/versions.d.ts +51 -0
- package/dist/artifact-blocks/blocks/media-picker/versions.js +118 -0
- package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte +213 -0
- package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte.d.ts +5 -0
- package/dist/artifact-blocks/blocks/mockup/block.d.ts +26 -0
- package/dist/artifact-blocks/blocks/mockup/block.js +52 -0
- package/dist/artifact-blocks/blocks/mockup/doc.d.ts +24 -0
- package/dist/artifact-blocks/blocks/mockup/doc.js +44 -0
- package/dist/artifact-blocks/blocks/mockup/sandbox.d.ts +21 -0
- package/dist/artifact-blocks/blocks/mockup/sandbox.js +27 -0
- package/dist/artifact-blocks/blocks/mockup/schema.d.ts +7 -0
- package/dist/artifact-blocks/blocks/mockup/schema.js +90 -0
- package/dist/artifact-blocks/blocks/mockup/types.d.ts +36 -0
- package/dist/artifact-blocks/blocks/mockup/types.js +17 -0
- package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte +359 -0
- package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte.d.ts +32 -0
- package/dist/artifact-blocks/blocks/program/block.d.ts +35 -0
- package/dist/artifact-blocks/blocks/program/block.js +68 -0
- package/dist/artifact-blocks/blocks/program/schema.d.ts +132 -0
- package/dist/artifact-blocks/blocks/program/schema.js +268 -0
- package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte +315 -0
- package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte.d.ts +24 -0
- package/dist/artifact-blocks/blocks/stats/block.d.ts +7 -0
- package/dist/artifact-blocks/blocks/stats/block.js +49 -0
- package/dist/artifact-blocks/blocks/stats/schema.d.ts +82 -0
- package/dist/artifact-blocks/blocks/stats/schema.js +43 -0
- package/dist/artifact-blocks/blocks/stats/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/stats/thumb.js +102 -0
- package/dist/artifact-blocks/blocks/table/TableBlock.svelte +490 -0
- package/dist/artifact-blocks/blocks/table/TableBlock.svelte.d.ts +28 -0
- package/dist/artifact-blocks/blocks/table/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/table/block.js +100 -0
- package/dist/artifact-blocks/blocks/table/schema.d.ts +143 -0
- package/dist/artifact-blocks/blocks/table/schema.js +278 -0
- package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte +347 -0
- package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte.d.ts +42 -0
- package/dist/artifact-blocks/blocks/timeline/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/timeline/block.js +96 -0
- package/dist/artifact-blocks/blocks/timeline/constants.d.ts +26 -0
- package/dist/artifact-blocks/blocks/timeline/constants.js +27 -0
- package/dist/artifact-blocks/blocks/timeline/schema.d.ts +102 -0
- package/dist/artifact-blocks/blocks/timeline/schema.js +405 -0
- package/dist/artifact-blocks/blocks/timeline/thumb.d.ts +2 -0
- package/dist/artifact-blocks/blocks/timeline/thumb.js +117 -0
- package/dist/artifact-blocks/blocks/timeline/types.d.ts +66 -0
- package/dist/artifact-blocks/blocks/timeline/types.js +1 -0
- package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte +169 -0
- package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte.d.ts +26 -0
- package/dist/artifact-blocks/blocks/transcript/block.d.ts +9 -0
- package/dist/artifact-blocks/blocks/transcript/block.js +86 -0
- package/dist/artifact-blocks/blocks/transcript/schema.d.ts +114 -0
- package/dist/artifact-blocks/blocks/transcript/schema.js +126 -0
- package/dist/artifact-blocks/builtins.d.ts +40 -0
- package/dist/artifact-blocks/builtins.js +22 -0
- package/dist/artifact-blocks/contractBlocks.d.ts +92 -0
- package/dist/artifact-blocks/contractBlocks.js +279 -0
- package/dist/artifact-blocks/history.d.ts +140 -0
- package/dist/artifact-blocks/history.js +363 -0
- package/dist/artifact-blocks/index.d.ts +40 -0
- package/dist/artifact-blocks/index.js +46 -0
- package/dist/artifact-blocks/listen/context.d.ts +30 -0
- package/dist/artifact-blocks/listen/context.js +30 -0
- package/dist/artifact-blocks/liveData.d.ts +78 -0
- package/dist/artifact-blocks/liveData.js +137 -0
- package/dist/artifact-blocks/liveDataPoller.d.ts +41 -0
- package/dist/artifact-blocks/liveDataPoller.js +140 -0
- package/dist/artifact-blocks/openNav.d.ts +46 -0
- package/dist/artifact-blocks/openNav.js +106 -0
- package/dist/artifact-blocks/pageReviewKeys.d.ts +17 -0
- package/dist/artifact-blocks/pageReviewKeys.js +115 -0
- package/dist/artifact-blocks/params.d.ts +98 -0
- package/dist/artifact-blocks/params.js +159 -0
- package/dist/artifact-blocks/registry.d.ts +27 -0
- package/dist/artifact-blocks/registry.js +83 -0
- package/dist/artifact-blocks/review/BlockIcon.svelte +99 -0
- package/dist/artifact-blocks/review/BlockIcon.svelte.d.ts +17 -0
- package/dist/artifact-blocks/review/BulkRejectForm.svelte +94 -0
- package/dist/artifact-blocks/review/BulkRejectForm.svelte.d.ts +11 -0
- package/dist/artifact-blocks/review/BulkUndoBar.svelte +40 -0
- package/dist/artifact-blocks/review/BulkUndoBar.svelte.d.ts +9 -0
- package/dist/artifact-blocks/review/ItemNote.svelte +193 -0
- package/dist/artifact-blocks/review/ItemNote.svelte.d.ts +33 -0
- package/dist/artifact-blocks/review/NoteToggle.svelte +52 -0
- package/dist/artifact-blocks/review/NoteToggle.svelte.d.ts +12 -0
- package/dist/artifact-blocks/review/TeamChip.svelte +71 -0
- package/dist/artifact-blocks/review/TeamChip.svelte.d.ts +8 -0
- package/dist/artifact-blocks/review/attachments.d.ts +10 -0
- package/dist/artifact-blocks/review/attachments.js +37 -0
- package/dist/artifact-blocks/review/bulk.d.ts +52 -0
- package/dist/artifact-blocks/review/bulk.js +61 -0
- package/dist/artifact-blocks/review/itemReview.d.ts +33 -0
- package/dist/artifact-blocks/review/itemReview.js +112 -0
- package/dist/artifact-blocks/review/roundLines.d.ts +14 -0
- package/dist/artifact-blocks/review/roundLines.js +20 -0
- package/dist/artifact-blocks/review/rounds.d.ts +86 -0
- package/dist/artifact-blocks/review/rounds.js +302 -0
- package/dist/artifact-blocks/review/saver.d.ts +23 -0
- package/dist/artifact-blocks/review/saver.js +48 -0
- package/dist/artifact-blocks/review/team.d.ts +31 -0
- package/dist/artifact-blocks/review/team.js +42 -0
- package/dist/artifact-blocks/review/visualOrder.d.ts +29 -0
- package/dist/artifact-blocks/review/visualOrder.js +66 -0
- package/dist/artifact-blocks/review.d.ts +180 -0
- package/dist/artifact-blocks/review.js +716 -0
- package/dist/artifact-blocks/thumb-kit.d.ts +80 -0
- package/dist/artifact-blocks/thumb-kit.js +149 -0
- package/dist/artifact-blocks/types.d.ts +513 -0
- package/dist/artifact-blocks/types.js +1 -0
- package/dist/components/Button.svelte +8 -0
- package/dist/components/TextInput.svelte +39 -6
- package/dist/components/TextInput.svelte.d.ts +15 -7
- package/dist/components/basic/Checkbox.svelte +52 -14
- package/dist/components/basic/Checkbox.svelte.d.ts +11 -1
- package/package.json +11 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* AttachmentChip (jatui-vsuzi) — the default chip for one note attachment:
|
|
4
|
+
* a labelled link to the stored bytes (kind · name · size). Hosts with a
|
|
5
|
+
* richer chip (inline player, transcript) pass HostAdapter.attachmentChip.
|
|
6
|
+
* The URL is host-issued, but still policy-checked: an unsafe one renders
|
|
7
|
+
* the label as plain text.
|
|
8
|
+
*/
|
|
9
|
+
import { isSafeLinkUrl } from "./params.js"
|
|
10
|
+
import type { NoteAttachment } from "./types.js"
|
|
11
|
+
|
|
12
|
+
let { clip }: { clip: NoteAttachment } = $props()
|
|
13
|
+
|
|
14
|
+
const KIND_LABEL: Record<string, string> = {
|
|
15
|
+
screen: "Screen",
|
|
16
|
+
voice: "Voice",
|
|
17
|
+
audio: "Audio",
|
|
18
|
+
video: "Video",
|
|
19
|
+
image: "Image",
|
|
20
|
+
file: "File",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function size(bytes: number): string {
|
|
24
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return ""
|
|
25
|
+
if (bytes < 1024) return `${bytes} B`
|
|
26
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`
|
|
27
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function duration(s: number | null): string {
|
|
31
|
+
if (s == null || !Number.isFinite(s)) return ""
|
|
32
|
+
const m = Math.floor(s / 60)
|
|
33
|
+
const r = Math.round(s % 60)
|
|
34
|
+
return `${m}:${String(r).padStart(2, "0")}`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const name = $derived(clip.label ?? clip.name)
|
|
38
|
+
const meta = $derived(
|
|
39
|
+
[KIND_LABEL[clip.kind] ?? "File", duration(clip.durationSeconds) || size(clip.sizeBytes)]
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.join(" · "),
|
|
42
|
+
)
|
|
43
|
+
const href = $derived(typeof clip.url === "string" && isSafeLinkUrl(clip.url) ? clip.url : null)
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
{#if href}
|
|
47
|
+
<a
|
|
48
|
+
{href}
|
|
49
|
+
target="_blank"
|
|
50
|
+
rel="noopener noreferrer"
|
|
51
|
+
class="border-base-content/15 hover:border-primary inline-flex max-w-[16rem] items-center gap-1.5 rounded-field border px-2 py-0.5 text-xs"
|
|
52
|
+
title={clip.transcript ?? name}
|
|
53
|
+
data-attachment-chip
|
|
54
|
+
>
|
|
55
|
+
<span class="truncate">{name}</span>
|
|
56
|
+
{#if meta}<span class="text-base-content/50 shrink-0">{meta}</span>{/if}
|
|
57
|
+
</a>
|
|
58
|
+
{:else}
|
|
59
|
+
<span
|
|
60
|
+
class="border-base-content/15 inline-flex max-w-[16rem] items-center gap-1.5 rounded-field border px-2 py-0.5 text-xs"
|
|
61
|
+
data-attachment-chip
|
|
62
|
+
>
|
|
63
|
+
<span class="truncate">{name}</span>
|
|
64
|
+
{#if meta}<span class="text-base-content/50 shrink-0">{meta}</span>{/if}
|
|
65
|
+
</span>
|
|
66
|
+
{/if}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NoteAttachment } from "./types.js";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
clip: NoteAttachment;
|
|
4
|
+
};
|
|
5
|
+
declare const AttachmentChip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
6
|
+
type AttachmentChip = ReturnType<typeof AttachmentChip>;
|
|
7
|
+
export default AttachmentChip;
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* BlockComments (origin mos-kib2f) — the per-block comment thread: an icon
|
|
4
|
+
* + unresolved-count chip under each block that opens a small thread
|
|
5
|
+
* drawer.
|
|
6
|
+
*
|
|
7
|
+
* The drawer reads and posts through the host's CommentsService
|
|
8
|
+
* (HostAdapter.comments):
|
|
9
|
+
* - the thread restores on first open (`load`);
|
|
10
|
+
* - posting is the host's call (`post`) — a comment is attributable to a
|
|
11
|
+
* person, so a host should only offer it to a signed-in viewer;
|
|
12
|
+
* - the poster can resolve their OWN comment (`setResolved`) — the
|
|
13
|
+
* resolved flag is per-poster, never someone else's.
|
|
14
|
+
*
|
|
15
|
+
* No service, or a disabled surface → renders NOTHING (the read-only
|
|
16
|
+
* mode). Theming is token-only, radius tokens, light + dark + phone, and
|
|
17
|
+
* every animation sits under motion-safe.
|
|
18
|
+
*/
|
|
19
|
+
import CommentPill from "./CommentPill.svelte"
|
|
20
|
+
import NoteComposer from "./NoteComposer.svelte"
|
|
21
|
+
import AttachmentChip from "./AttachmentChip.svelte"
|
|
22
|
+
import { hostAdapter } from "./adapter.js"
|
|
23
|
+
import type { BlockComment, NoteAttachment } from "./types.js"
|
|
24
|
+
|
|
25
|
+
interface Props {
|
|
26
|
+
artifactId: string
|
|
27
|
+
version: number
|
|
28
|
+
blockId: string
|
|
29
|
+
/** The block's label (the block title / type) — the drawer's heading. */
|
|
30
|
+
blockLabel: string
|
|
31
|
+
/** Server-rendered unresolved count for THIS block (0 until first load). */
|
|
32
|
+
count?: number
|
|
33
|
+
/** A session member is viewing (false on the public share route). */
|
|
34
|
+
enabled: boolean
|
|
35
|
+
/**
|
|
36
|
+
* The block below breaks out of the reading column (a wide table).
|
|
37
|
+
* The trigger row then uses the SAME breakout — the pill must align
|
|
38
|
+
* with the block's actual right edge, never sit inboard of it, and
|
|
39
|
+
* never touch the block's chrome (mos-51g8l).
|
|
40
|
+
*/
|
|
41
|
+
wide?: boolean
|
|
42
|
+
/**
|
|
43
|
+
* The trigger lives elsewhere (mos-8fvt9): the block's heading row
|
|
44
|
+
* renders a CommentPill through SectionTools and drives `open`. This
|
|
45
|
+
* component then renders only the thread drawer — kept here, at the
|
|
46
|
+
* section level, where no block's `@container` can trap its
|
|
47
|
+
* position: fixed.
|
|
48
|
+
*/
|
|
49
|
+
hosted?: boolean
|
|
50
|
+
/** The drawer is open (bindable, so a hosted trigger can drive it). */
|
|
51
|
+
open?: boolean
|
|
52
|
+
/** Reports the live unresolved count to a hosted trigger. */
|
|
53
|
+
onunresolved?: (n: number) => void
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let {
|
|
57
|
+
artifactId,
|
|
58
|
+
version,
|
|
59
|
+
blockId,
|
|
60
|
+
blockLabel,
|
|
61
|
+
count = 0,
|
|
62
|
+
enabled,
|
|
63
|
+
wide = false,
|
|
64
|
+
hosted = false,
|
|
65
|
+
open = $bindable(false),
|
|
66
|
+
onunresolved = undefined,
|
|
67
|
+
}: Props = $props()
|
|
68
|
+
|
|
69
|
+
type CommentRow = BlockComment
|
|
70
|
+
|
|
71
|
+
const adapter = hostAdapter()
|
|
72
|
+
const service = adapter.comments
|
|
73
|
+
const Chip = adapter.attachmentChip ?? AttachmentChip
|
|
74
|
+
/** Live only with a service: no service is the read-only mode. */
|
|
75
|
+
const live = $derived(enabled && service !== undefined)
|
|
76
|
+
|
|
77
|
+
let loaded = $state(false)
|
|
78
|
+
/** The thread could not be read: say so, never "No comments yet". */
|
|
79
|
+
let loadFailed = $state(false)
|
|
80
|
+
let comments = $state<CommentRow[]>([])
|
|
81
|
+
let sending = $state(false)
|
|
82
|
+
let error = $state("")
|
|
83
|
+
|
|
84
|
+
/** The chip's number: unresolved, live-updated as the thread changes. */
|
|
85
|
+
const unresolved = $derived(
|
|
86
|
+
comments.length > 0
|
|
87
|
+
? comments.filter((c) => !c.resolved).length
|
|
88
|
+
: (count ?? 0),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
$effect(() => {
|
|
92
|
+
onunresolved?.(unresolved)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// The thread restores on first open, whoever opened it (own trigger or a
|
|
96
|
+
// hosted one).
|
|
97
|
+
$effect(() => {
|
|
98
|
+
if (open && !loaded && live) void load()
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
function close() {
|
|
102
|
+
open = false
|
|
103
|
+
error = ""
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function onKeydown(e: KeyboardEvent) {
|
|
107
|
+
if (e.key === "Escape" && open) close()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function toggle() {
|
|
111
|
+
if (open) close()
|
|
112
|
+
else open = true
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function load() {
|
|
116
|
+
if (!service) return
|
|
117
|
+
loaded = true
|
|
118
|
+
loadFailed = false
|
|
119
|
+
try {
|
|
120
|
+
comments = (await service.load({ artifactId, version, blockId })) ?? []
|
|
121
|
+
} catch {
|
|
122
|
+
loadFailed = true
|
|
123
|
+
// History is a convenience; a failed GET must not block commenting.
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function post(payload: { text: string; clips: NoteAttachment[] }) {
|
|
128
|
+
const text = payload.text
|
|
129
|
+
if (sending) return
|
|
130
|
+
if (!text && payload.clips.length === 0) return
|
|
131
|
+
sending = true
|
|
132
|
+
error = ""
|
|
133
|
+
try {
|
|
134
|
+
if (!service) throw new Error("Comments are not available here")
|
|
135
|
+
const comment = await service.post({
|
|
136
|
+
artifactId,
|
|
137
|
+
version,
|
|
138
|
+
blockId,
|
|
139
|
+
body: text,
|
|
140
|
+
attachments: payload.clips,
|
|
141
|
+
})
|
|
142
|
+
comments = [...comments, comment]
|
|
143
|
+
} catch (e) {
|
|
144
|
+
error = e instanceof Error ? e.message : "Could not comment right now"
|
|
145
|
+
// The composer keeps the draft; it surfaces the failure.
|
|
146
|
+
throw e
|
|
147
|
+
} finally {
|
|
148
|
+
sending = false
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function toggleResolved(c: CommentRow) {
|
|
153
|
+
if (!c.mine) return // only the poster flips their own flag
|
|
154
|
+
const next = !c.resolved
|
|
155
|
+
try {
|
|
156
|
+
if (!service) throw new Error("Could not update the comment")
|
|
157
|
+
await service.setResolved({ artifactId, commentId: c.id, resolved: next })
|
|
158
|
+
comments = comments.map((row) =>
|
|
159
|
+
row.id === c.id ? { ...row, resolved: next } : row,
|
|
160
|
+
)
|
|
161
|
+
} catch (e) {
|
|
162
|
+
error = e instanceof Error ? e.message : "Could not update the comment"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const timeFmt = new Intl.DateTimeFormat("en-US", {
|
|
167
|
+
month: "short",
|
|
168
|
+
day: "numeric",
|
|
169
|
+
hour: "numeric",
|
|
170
|
+
minute: "2-digit",
|
|
171
|
+
})
|
|
172
|
+
function when(iso: string): string {
|
|
173
|
+
const d = new Date(iso)
|
|
174
|
+
return Number.isFinite(d.getTime()) ? timeFmt.format(d) : ""
|
|
175
|
+
}
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<svelte:window onkeydown={onKeydown} />
|
|
179
|
+
|
|
180
|
+
{#if live}
|
|
181
|
+
<!-- mb-2: the trigger NEVER touches block chrome (a pill kissing a wide
|
|
182
|
+
table's filter box). Matches the failed-save strip's mb-2, so chrome
|
|
183
|
+
rows read at one rhythm. -->
|
|
184
|
+
{#if !hosted}
|
|
185
|
+
<div class="mb-2 flex justify-end" class:bc-wide={wide}>
|
|
186
|
+
<CommentPill label={blockLabel} {unresolved} {open} onclick={toggle} />
|
|
187
|
+
</div>
|
|
188
|
+
{/if}
|
|
189
|
+
|
|
190
|
+
{#if open}
|
|
191
|
+
<div
|
|
192
|
+
role="dialog"
|
|
193
|
+
aria-label="Comments on {blockLabel}"
|
|
194
|
+
class="border-base-content/10 bg-base-100 fixed inset-x-2 bottom-16 z-40 flex max-h-[60vh] flex-col rounded-box border shadow-xl sm:inset-x-auto sm:right-4 sm:w-[22rem]"
|
|
195
|
+
>
|
|
196
|
+
<header
|
|
197
|
+
class="border-base-content/10 flex items-center gap-2 border-b px-4 py-3"
|
|
198
|
+
>
|
|
199
|
+
<h2 class="min-w-0 truncate text-sm font-semibold">{blockLabel}</h2>
|
|
200
|
+
<span class="text-base-content/50 shrink-0 text-xs">comments</span>
|
|
201
|
+
<button
|
|
202
|
+
type="button"
|
|
203
|
+
class="btn btn-ghost btn-xs btn-circle ml-auto"
|
|
204
|
+
aria-label="Close comments"
|
|
205
|
+
onclick={close}
|
|
206
|
+
>
|
|
207
|
+
✕
|
|
208
|
+
</button>
|
|
209
|
+
</header>
|
|
210
|
+
|
|
211
|
+
<div class="flex-1 overflow-y-auto px-4 py-3" tabindex="-1">
|
|
212
|
+
{#if error}
|
|
213
|
+
<p role="alert" class="text-error-content text-sm">{error}</p>
|
|
214
|
+
{/if}
|
|
215
|
+
|
|
216
|
+
{#if loadFailed}
|
|
217
|
+
<p class="text-base-content/60 text-sm" data-comments-load-failed>
|
|
218
|
+
Couldn't load earlier comments.
|
|
219
|
+
<button
|
|
220
|
+
type="button"
|
|
221
|
+
class="link link-primary"
|
|
222
|
+
onclick={() => void load()}>Try again</button
|
|
223
|
+
>
|
|
224
|
+
</p>
|
|
225
|
+
{:else if comments.length === 0}
|
|
226
|
+
<p class="text-base-content/50 text-sm">No comments yet.</p>
|
|
227
|
+
{/if}
|
|
228
|
+
|
|
229
|
+
<ul class="flex flex-col gap-3">
|
|
230
|
+
{#each comments as c (c.id)}
|
|
231
|
+
<li
|
|
232
|
+
class="rounded-field border border-base-content/10 px-3 py-2 {c.resolved
|
|
233
|
+
? 'opacity-60'
|
|
234
|
+
: ''}"
|
|
235
|
+
>
|
|
236
|
+
{#if c.body}
|
|
237
|
+
<p
|
|
238
|
+
class="text-sm {c.resolved
|
|
239
|
+
? 'line-through'
|
|
240
|
+
: ''} whitespace-pre-wrap"
|
|
241
|
+
>
|
|
242
|
+
{c.body}
|
|
243
|
+
</p>
|
|
244
|
+
{/if}
|
|
245
|
+
{#if c.attachments && c.attachments.length > 0}
|
|
246
|
+
<ul
|
|
247
|
+
class="mt-1.5 flex flex-wrap items-center gap-1.5"
|
|
248
|
+
aria-label="Comment attachments"
|
|
249
|
+
>
|
|
250
|
+
{#each c.attachments as a (a.name)}
|
|
251
|
+
<li><Chip clip={a} /></li>
|
|
252
|
+
{/each}
|
|
253
|
+
</ul>
|
|
254
|
+
{/if}
|
|
255
|
+
<div
|
|
256
|
+
class="text-base-content/40 mt-1 flex items-center gap-2 text-2xs"
|
|
257
|
+
>
|
|
258
|
+
<span>{when(c.created_at)}</span>
|
|
259
|
+
{#if c.mine}
|
|
260
|
+
<button
|
|
261
|
+
type="button"
|
|
262
|
+
class="link link-hover text-base-content/60"
|
|
263
|
+
onclick={() => toggleResolved(c)}
|
|
264
|
+
>
|
|
265
|
+
{c.resolved ? "unresolve" : "resolve"}
|
|
266
|
+
</button>
|
|
267
|
+
{/if}
|
|
268
|
+
</div>
|
|
269
|
+
</li>
|
|
270
|
+
{/each}
|
|
271
|
+
</ul>
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
<footer class="border-base-content/10 border-t px-4 py-3">
|
|
275
|
+
<!-- The ONE composer (the host's, else jatui's text composer). Its
|
|
276
|
+
submit row posts; a failed post keeps the draft. -->
|
|
277
|
+
<NoteComposer
|
|
278
|
+
{artifactId}
|
|
279
|
+
submitLabel="Comment"
|
|
280
|
+
onSubmit={post}
|
|
281
|
+
busy={sending}
|
|
282
|
+
{error}
|
|
283
|
+
placeholder="Comment on this block…"
|
|
284
|
+
label="Your comment on {blockLabel}"
|
|
285
|
+
rows={2}
|
|
286
|
+
maxLength={20000}
|
|
287
|
+
autofocus
|
|
288
|
+
/>
|
|
289
|
+
</footer>
|
|
290
|
+
</div>
|
|
291
|
+
{/if}
|
|
292
|
+
{/if}
|
|
293
|
+
|
|
294
|
+
<style>
|
|
295
|
+
/* Wide block (mos-51g8l): the trigger row breaks out with the SAME
|
|
296
|
+
formula the wide block itself uses (`.tb-wide` in TableBlock.svelte) —
|
|
297
|
+
centred on the reading column, capped at 80rem, kept 1.5rem inside the
|
|
298
|
+
page view (--artifact-page-w is the page's MEASURED width, so an admin
|
|
299
|
+
sidebar host stays correct). The two edges move together, so the pill's
|
|
300
|
+
right edge sits on the block's right edge instead of inboard of it.
|
|
301
|
+
Only the /a page opts in — pinned/embedded hosts (no
|
|
302
|
+
[data-artifact-page]) keep the column, and there the formula degrades
|
|
303
|
+
to 100% anyway (min(100% - 3rem, 80rem) < 100%). */
|
|
304
|
+
:global([data-artifact-page]) .bc-wide {
|
|
305
|
+
--bc-w: max(100%, min(var(--artifact-page-w, 100%) - 3rem, 80rem));
|
|
306
|
+
width: var(--bc-w);
|
|
307
|
+
margin-inline: calc((100% - var(--bc-w)) / 2);
|
|
308
|
+
}
|
|
309
|
+
</style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
artifactId: string;
|
|
3
|
+
version: number;
|
|
4
|
+
blockId: string;
|
|
5
|
+
/** The block's label (the block title / type) — the drawer's heading. */
|
|
6
|
+
blockLabel: string;
|
|
7
|
+
/** Server-rendered unresolved count for THIS block (0 until first load). */
|
|
8
|
+
count?: number;
|
|
9
|
+
/** A session member is viewing (false on the public share route). */
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* The block below breaks out of the reading column (a wide table).
|
|
13
|
+
* The trigger row then uses the SAME breakout — the pill must align
|
|
14
|
+
* with the block's actual right edge, never sit inboard of it, and
|
|
15
|
+
* never touch the block's chrome (mos-51g8l).
|
|
16
|
+
*/
|
|
17
|
+
wide?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The trigger lives elsewhere (mos-8fvt9): the block's heading row
|
|
20
|
+
* renders a CommentPill through SectionTools and drives `open`. This
|
|
21
|
+
* component then renders only the thread drawer — kept here, at the
|
|
22
|
+
* section level, where no block's `@container` can trap its
|
|
23
|
+
* position: fixed.
|
|
24
|
+
*/
|
|
25
|
+
hosted?: boolean;
|
|
26
|
+
/** The drawer is open (bindable, so a hosted trigger can drive it). */
|
|
27
|
+
open?: boolean;
|
|
28
|
+
/** Reports the live unresolved count to a hosted trigger. */
|
|
29
|
+
onunresolved?: (n: number) => void;
|
|
30
|
+
}
|
|
31
|
+
declare const BlockComments: import("svelte").Component<Props, {}, "open">;
|
|
32
|
+
type BlockComments = ReturnType<typeof BlockComments>;
|
|
33
|
+
export default BlockComments;
|