@joewinke/jatui 0.2.28 → 0.2.30

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/CLAUDE.md CHANGED
@@ -73,6 +73,16 @@ Then import:
73
73
  | Component | Purpose | Key Props |
74
74
  |-----------|---------|-----------|
75
75
  | `MediaWorkbench` | Full-featured image editor modal — upload, AI generate, AI edit, background removal, annotation canvas. **Preferred over `SmartImageEditor` for new image fields.** Two-column modal: preview left, 4 action tabs right (Generate, Edit, Remove BG, Annotate). Save uploads blob to `uploadEndpoint` or emits `onComplete`. Requires proxy endpoints from jst-23w1l.2. | `value` (bindable `string \| null`), `uploadEndpoint?` (default `/api/media`), `onComplete?`, `accept?` |
76
+ | `VideoPlayer` | **The default video surface — reach for this over a bare `<video controls>`.** One timeline band carrying a waveform-envelope scrubber, chapter flags (top edge), bookmark diamonds (bottom edge), diarized speaker colouring and scroll-to-zoom, plus an optional transcript pane (click to seek, active line auto-scroll, solo/skip per speaker) and talk-time legend. **Every intelligence prop is optional** — a bare mp4 still gets the scrubber, hover-time card, wheel volume and keyboard map, and each pane lights up as its data arrives (nothing shifts layout when diarization lands late). Wheel means volume over the video (shift = seek) and zoom over the band. | `src`, `chapters?`, `speakers?`, `transcript?`, `bookmarks?`, `waveform?`, `talkTime?`, `startAt?`, `poster?`, `captionsSrc?`, `transcriptPosition?` (`'below' \| 'side'`), `onTimeUpdate?`, `onAddBookmark?`, `onBookmarkContext?` |
77
+
78
+ **`VideoPlayer` vs `TranscriptPlayer`:** VideoPlayer is the generalization — it does everything TranscriptPlayer does plus the timeline band, and its props are structurally compatible with TranscriptPlayer's (`TranscriptSegment[]`, `TranscriptChapter[]`, `TranscriptBookmark[]`, `TranscriptSpeakerTalkTime[]` all pass straight through). `TranscriptPlayer` stays exported and unchanged for the existing meeting-recordings viewer; use `VideoPlayer` for anything new.
79
+
80
+ ```svelte
81
+ <VideoPlayer src={url} /> <!-- bare mp4, still a real player -->
82
+ <VideoPlayer src={url} {chapters} {speakers} {transcript} {waveform} />
83
+ ```
84
+
85
+ **Types:** `VideoChapter`, `VideoSpeakerTurn`, `VideoTranscriptSegment`, `VideoBookmark`, `VideoWaveform`, `VideoSpeakerTalkTime`. `VideoWaveform.peaks` normalise against their own max, so 0–1, 0–99 and 0–255 arrays all work.
76
86
 
77
87
  ### Meetings (subpath: `jatui/meet`)
78
88
 
@@ -85,11 +85,21 @@
85
85
  uploadEndpoint = "/api/media",
86
86
  onComplete = undefined,
87
87
  accept = "image/png,image/jpeg,image/webp,image/gif",
88
+ assetId = undefined,
88
89
  } = $props<{
89
90
  value?: string | null
90
91
  uploadEndpoint?: string
91
92
  onComplete?: (url: string) => void
92
93
  accept?: string
94
+ /**
95
+ * Identifies the existing asset-store row being edited, if any. Forwarded
96
+ * to /api/media/edit and /api/media/remove-bg so the host app's
97
+ * kind='record' safety check (assets that must never be AI pixel-edited)
98
+ * can run server-side. Omit for generate-only or non-asset-store usage —
99
+ * the check is skipped entirely when absent, matching every call site
100
+ * that predates this prop.
101
+ */
102
+ assetId?: string
93
103
  }>()
94
104
 
95
105
  let open = $state(false)
@@ -355,7 +365,7 @@
355
365
  const res = await fetch("/api/media/edit", {
356
366
  method: "POST",
357
367
  headers: { "Content-Type": "application/json" },
358
- body: JSON.stringify({ imageUrl: sourceUrl, instruction: editInstruction }),
368
+ body: JSON.stringify({ imageUrl: sourceUrl, instruction: editInstruction, assetId }),
359
369
  })
360
370
  const body = await res.json().catch(() => ({})) as { error?: string; url?: string }
361
371
  if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`)
@@ -379,6 +389,7 @@
379
389
  const blob = await imgRes.blob()
380
390
  const fd = new FormData()
381
391
  fd.append("image", blob, "source.png")
392
+ if (assetId) fd.append("assetId", assetId)
382
393
  const res = await fetch("/api/media/remove-bg", { method: "POST", body: fd })
383
394
  if (!res.ok) {
384
395
  const msg = await res.text().catch(() => res.statusText)
@@ -3,6 +3,15 @@ type $$ComponentProps = {
3
3
  uploadEndpoint?: string;
4
4
  onComplete?: (url: string) => void;
5
5
  accept?: string;
6
+ /**
7
+ * Identifies the existing asset-store row being edited, if any. Forwarded
8
+ * to /api/media/edit and /api/media/remove-bg so the host app's
9
+ * kind='record' safety check (assets that must never be AI pixel-edited)
10
+ * can run server-side. Omit for generate-only or non-asset-store usage —
11
+ * the check is skipped entirely when absent, matching every call site
12
+ * that predates this prop.
13
+ */
14
+ assetId?: string;
6
15
  };
7
16
  declare const MediaWorkbench: import("svelte").Component<$$ComponentProps, {}, "value">;
8
17
  type MediaWorkbench = ReturnType<typeof MediaWorkbench>;