@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 +10 -0
- package/dist/components/MediaWorkbench.svelte +12 -1
- package/dist/components/MediaWorkbench.svelte.d.ts +9 -0
- package/dist/components/VideoPlayer.svelte +1592 -0
- package/dist/components/VideoPlayer.svelte.d.ts +72 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -0
- package/package.json +1 -1
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>;
|