@r2digisolutions/components 0.2.0 → 0.3.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.
Files changed (63) hide show
  1. package/dist/components/atoms/Playhead/Playhead.svelte +44 -5
  2. package/dist/components/atoms/Playhead/Playhead.svelte.d.ts +8 -0
  3. package/dist/components/atoms/TimeRuler/TimeRuler.svelte +75 -16
  4. package/dist/components/atoms/TimeRuler/TimeRuler.svelte.d.ts +7 -0
  5. package/dist/components/atoms/TimelineGrid/TimelineGrid.stories.js +8 -0
  6. package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte +39 -0
  7. package/dist/components/atoms/TimelineGrid/TimelineGrid.svelte.d.ts +11 -0
  8. package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte +7 -0
  9. package/dist/components/atoms/TimelineGrid/TimelineGridStory.svelte.d.ts +18 -0
  10. package/dist/components/molecules/ColorPicker/ColorPicker.svelte +45 -4
  11. package/dist/components/molecules/ColorPicker/ColorPicker.svelte.d.ts +2 -0
  12. package/dist/components/molecules/ContextMenu/ContextMenu.svelte +38 -11
  13. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte +17 -2
  14. package/dist/components/molecules/MediaAssetBrowser/MediaAssetBrowser.svelte.d.ts +5 -0
  15. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte +362 -52
  16. package/dist/components/molecules/MediaTimeline/MediaTimeline.svelte.d.ts +22 -2
  17. package/dist/components/molecules/PdfViewer/PdfViewer.svelte.d.ts +1 -1
  18. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte +751 -29
  19. package/dist/components/molecules/ProgramMonitor/ProgramMonitor.svelte.d.ts +14 -1
  20. package/dist/components/molecules/SplitPane/SplitPane.svelte +2 -2
  21. package/dist/components/molecules/TimelineClip/TimelineClip.svelte +95 -18
  22. package/dist/components/molecules/TimelineClip/TimelineClip.svelte.d.ts +3 -0
  23. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte +82 -12
  24. package/dist/components/molecules/TimelineTrack/TimelineTrack.svelte.d.ts +13 -2
  25. package/dist/components/molecules/TransportControls/TransportControls.svelte +84 -2
  26. package/dist/components/molecules/TransportControls/TransportControls.svelte.d.ts +13 -1
  27. package/dist/components/molecules/TransportControls/TransportControlsStory.svelte +33 -11
  28. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.stories.js +8 -0
  29. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte +213 -0
  30. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanel.svelte.d.ts +22 -0
  31. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte +7 -0
  32. package/dist/components/molecules/VideoAnimationsPanel/VideoAnimationsPanelStory.svelte.d.ts +18 -0
  33. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.stories.js +8 -0
  34. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte +524 -0
  35. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanel.svelte.d.ts +32 -0
  36. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte +7 -0
  37. package/dist/components/molecules/VideoComponentsPanel/VideoComponentsPanelStory.svelte.d.ts +18 -0
  38. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte +85 -32
  39. package/dist/components/molecules/VideoTrackHeader/VideoTrackHeader.svelte.d.ts +6 -0
  40. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.stories.js +8 -0
  41. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte +113 -0
  42. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanel.svelte.d.ts +18 -0
  43. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte +7 -0
  44. package/dist/components/molecules/VideoTransitionsPanel/VideoTransitionsPanelStory.svelte.d.ts +18 -0
  45. package/dist/components/organisms/AudioEditor/AudioEditor.svelte +52 -1
  46. package/dist/components/organisms/EditorShell/EditorShell.svelte +102 -92
  47. package/dist/components/organisms/FileUploader/FileUploader.stories.d.ts +10 -0
  48. package/dist/components/organisms/FileUploader/FileUploader.stories.js +21 -0
  49. package/dist/components/organisms/FileUploader/FileUploader.svelte +61 -21
  50. package/dist/components/organisms/FileUploader/FileUploader.svelte.d.ts +9 -0
  51. package/dist/components/organisms/FileUploader/FileUploaderStory.svelte +7 -1
  52. package/dist/components/organisms/FileUploader/FileUploaderStory.svelte.d.ts +3 -0
  53. package/dist/components/organisms/VideoEditor/VideoEditor.svelte +1457 -78
  54. package/dist/components/organisms/VideoEditor/VideoEditor.svelte.d.ts +2 -1
  55. package/dist/components/organisms/VideoEditor/VideoEditorStory.svelte +3 -2
  56. package/dist/index.d.ts +11 -3
  57. package/dist/index.js +6 -2
  58. package/dist/utils/mediaTime.d.ts +14 -4
  59. package/dist/utils/mediaTime.js +27 -8
  60. package/dist/utils/mediaTracks.d.ts +154 -0
  61. package/dist/utils/mediaTracks.js +697 -1
  62. package/dist/utils/videoSequence.js +35 -4
  63. package/package.json +1 -1
@@ -9,6 +9,7 @@ const meta = {
9
9
  accept: { control: 'text' },
10
10
  variant: { control: 'select', options: ['multiple', 'single', 'avatar'] },
11
11
  view: { control: 'select', options: ['list', 'grid'] },
12
+ layout: { control: 'select', options: ['horizontal', 'vertical', 'compact'] },
12
13
  showViewToggle: { control: 'boolean' },
13
14
  maxSizeMb: { control: 'number' },
14
15
  disabled: { control: 'boolean' }
@@ -19,6 +20,7 @@ const meta = {
19
20
  accept: '*',
20
21
  variant: 'multiple',
21
22
  view: 'list',
23
+ layout: 'horizontal',
22
24
  showViewToggle: true,
23
25
  maxSizeMb: 10,
24
26
  disabled: false
@@ -37,10 +39,29 @@ export const GridView = {
37
39
  helperText: 'Images only · max 10MB'
38
40
  }
39
41
  };
42
+ export const VerticalSidebar = {
43
+ args: {
44
+ label: 'Upload',
45
+ variant: 'multiple',
46
+ layout: 'vertical',
47
+ accept: 'image/*,video/*,audio/*',
48
+ helperText: 'Image, video or audio',
49
+ showViewToggle: false
50
+ }
51
+ };
52
+ export const Compact = {
53
+ args: {
54
+ label: 'Add more',
55
+ variant: 'multiple',
56
+ layout: 'compact',
57
+ helperText: 'Drop or browse'
58
+ }
59
+ };
40
60
  export const SingleFile = {
41
61
  args: {
42
62
  label: 'Cover image',
43
63
  variant: 'single',
64
+ layout: 'vertical',
44
65
  accept: 'image/*',
45
66
  helperText: 'PNG or JPG · max 10MB'
46
67
  }
@@ -4,6 +4,8 @@
4
4
  type FileKind = 'image' | 'video' | 'audio' | 'pdf' | 'doc' | 'other';
5
5
  type UploaderVariant = 'multiple' | 'single' | 'avatar';
6
6
  type UploaderView = 'list' | 'grid';
7
+ /** Dropzone chrome layout (ignored for avatar / filled single preview). */
8
+ type UploaderLayout = 'horizontal' | 'vertical' | 'compact';
7
9
 
8
10
  interface FileItem {
9
11
  file: File;
@@ -21,6 +23,13 @@
21
23
  accept?: string;
22
24
  variant?: UploaderVariant;
23
25
  view?: UploaderView;
26
+ /**
27
+ * Empty dropzone orientation.
28
+ * - `horizontal` — icon + text in a row (default)
29
+ * - `vertical` — stacked, better for narrow sidebars
30
+ * - `compact` — tight horizontal strip
31
+ */
32
+ layout?: UploaderLayout;
24
33
  showViewToggle?: boolean;
25
34
  /** When false, only the dropzone is shown (parent owns the file list). */
26
35
  showFileList?: boolean;
@@ -46,6 +55,7 @@
46
55
  accept = 'image/*',
47
56
  variant = 'multiple',
48
57
  view = $bindable('list'),
58
+ layout = 'horizontal',
49
59
  showViewToggle = true,
50
60
  showFileList = true,
51
61
  maxSizeMb = 10,
@@ -89,6 +99,13 @@
89
99
  !!externalSrc &&
90
100
  (resolvedAccept.includes('video') || /\.(mp4|webm|mov|m4v)(\?|$)/i.test(externalSrc)))
91
101
  );
102
+ const singleIsAudio = $derived(
103
+ primaryFile?.kind === 'audio' ||
104
+ (!primaryFile &&
105
+ !!externalSrc &&
106
+ (resolvedAccept.includes('audio') || /\.(mp3|wav|ogg|m4a|aac|flac)(\?|$)/i.test(externalSrc)))
107
+ );
108
+ const dropLayout = $derived(layout === 'compact' ? 'compact' : layout);
92
109
 
93
110
  function formatBytes(bytes: number): string {
94
111
  if (bytes === 0) return '0 B';
@@ -289,7 +306,9 @@
289
306
  </div>
290
307
  {/snippet}
291
308
 
292
- {#snippet dropzone(compact = false)}
309
+ {#snippet dropzone(forceCompact = false)}
310
+ {@const compact = forceCompact || dropLayout === 'compact'}
311
+ {@const vertical = !compact && dropLayout === 'vertical'}
293
312
  <!-- svelte-ignore a11y_no_static_element_interactions -->
294
313
  <div
295
314
  role="button"
@@ -314,18 +333,27 @@
314
333
  class={[
315
334
  'relative overflow-hidden border border-dashed transition-colors duration-150 outline-none',
316
335
  'focus-visible:ring-2 focus-visible:ring-brand-500/30 focus-visible:border-brand-500',
317
- compact ? 'rounded-xl' : 'rounded-xl',
336
+ 'rounded-xl',
318
337
  isDragging
319
338
  ? 'border-brand-500 bg-brand-500/5 dark:bg-brand-950/40'
320
339
  : 'border-border bg-surface-elevated hover:border-border-strong hover:bg-surface-overlay/60',
321
340
  disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
322
341
  ]}
323
342
  >
324
- <div class={['flex items-center gap-4', compact ? 'px-4 py-3.5' : 'px-4 py-5 sm:px-5']}>
343
+ <div
344
+ class={[
345
+ 'flex',
346
+ vertical
347
+ ? 'flex-col items-center gap-2 px-3 py-5 text-center'
348
+ : compact
349
+ ? 'flex-row items-center gap-3 px-3 py-2.5'
350
+ : 'flex-row items-center gap-4 px-4 py-5 sm:px-5'
351
+ ]}
352
+ >
325
353
  <div
326
354
  class={[
327
355
  'flex shrink-0 items-center justify-center rounded-lg transition-colors duration-150',
328
- compact ? 'h-9 w-9' : 'h-11 w-11',
356
+ vertical ? 'h-10 w-10' : compact ? 'h-8 w-8' : 'h-11 w-11',
329
357
  isDragging
330
358
  ? 'bg-brand-600 text-white'
331
359
  : 'bg-brand-100 text-brand-700 dark:bg-brand-500/15 dark:text-brand-300'
@@ -333,7 +361,7 @@
333
361
  aria-hidden="true"
334
362
  >
335
363
  <svg
336
- class={compact ? 'h-4 w-4' : 'h-5 w-5'}
364
+ class={compact ? 'h-3.5 w-3.5' : 'h-5 w-5'}
337
365
  fill="none"
338
366
  viewBox="0 0 24 24"
339
367
  stroke="currentColor"
@@ -347,26 +375,35 @@
347
375
  </svg>
348
376
  </div>
349
377
 
350
- <div class="min-w-0 flex-1 text-left">
351
- <p class={['font-medium text-primary', compact ? 'text-xs' : 'text-sm']}>
378
+ <div class={['min-w-0', vertical ? 'w-full' : 'flex-1 text-left']}>
379
+ <p
380
+ class={[
381
+ 'font-medium text-primary',
382
+ compact || vertical ? 'text-xs' : 'text-sm',
383
+ vertical && 'text-center'
384
+ ]}
385
+ >
352
386
  {#if isDragging}
353
387
  Drop files to upload
354
388
  {:else}
355
- Drop files here or
389
+ Drop files or
356
390
  <span class="text-brand-700 dark:text-brand-300"> browse</span>
357
391
  {/if}
358
392
  </p>
359
393
  {#if helperText}
360
394
  <p
361
395
  id={helperId}
362
- class="mt-0.5 text-xs text-secondary leading-relaxed"
396
+ class={[
397
+ 'mt-0.5 text-[11px] leading-relaxed text-secondary',
398
+ vertical && 'text-center'
399
+ ]}
363
400
  >
364
401
  {helperText}
365
402
  </p>
366
403
  {/if}
367
404
  </div>
368
405
 
369
- {#if !disabled && !compact}
406
+ {#if !disabled && !compact && !vertical}
370
407
  <span
371
408
  class="hidden sm:inline-flex shrink-0 items-center rounded-lg border border-border bg-surface-elevated px-3 py-1.5 text-xs font-medium text-primary pointer-events-none"
372
409
  >
@@ -581,17 +618,20 @@
581
618
  aria-labelledby={label ? labelId : undefined}
582
619
  >
583
620
  <div class="relative aspect-video bg-surface-overlay">
584
- {#if singlePreviewUrl}
585
- {#if singleIsVideo}
586
- <video
587
- src={singlePreviewUrl}
588
- class="h-full w-full object-cover"
589
- muted
590
- playsinline
591
- ></video>
592
- {:else}
593
- <img src={singlePreviewUrl} alt="" class="h-full w-full object-cover" />
594
- {/if}
621
+ {#if singlePreviewUrl && singleIsVideo}
622
+ <video
623
+ src={singlePreviewUrl}
624
+ class="h-full w-full object-cover"
625
+ muted
626
+ playsinline
627
+ ></video>
628
+ {:else if singlePreviewUrl && singleIsAudio}
629
+ <div class="flex h-full w-full flex-col items-center justify-center gap-3 px-4">
630
+ {@render fileBadge('audio', 'h-14 w-14 rounded-xl text-xs')}
631
+ <audio src={singlePreviewUrl} controls class="w-full max-w-xs"></audio>
632
+ </div>
633
+ {:else if singlePreviewUrl}
634
+ <img src={singlePreviewUrl} alt="" class="h-full w-full object-cover" />
595
635
  {:else}
596
636
  <div class="flex h-full w-full flex-col items-center justify-center gap-2">
597
637
  {@render fileBadge(primaryFile?.kind ?? 'other', 'h-14 w-14 rounded-xl text-xs')}
@@ -1,5 +1,7 @@
1
1
  type UploaderVariant = 'multiple' | 'single' | 'avatar';
2
2
  type UploaderView = 'list' | 'grid';
3
+ /** Dropzone chrome layout (ignored for avatar / filled single preview). */
4
+ type UploaderLayout = 'horizontal' | 'vertical' | 'compact';
3
5
  interface FileUploaderProps {
4
6
  id?: string;
5
7
  label?: string;
@@ -7,6 +9,13 @@ interface FileUploaderProps {
7
9
  accept?: string;
8
10
  variant?: UploaderVariant;
9
11
  view?: UploaderView;
12
+ /**
13
+ * Empty dropzone orientation.
14
+ * - `horizontal` — icon + text in a row (default)
15
+ * - `vertical` — stacked, better for narrow sidebars
16
+ * - `compact` — tight horizontal strip
17
+ */
18
+ layout?: UploaderLayout;
10
19
  showViewToggle?: boolean;
11
20
  /** When false, only the dropzone is shown (parent owns the file list). */
12
21
  showFileList?: boolean;
@@ -7,21 +7,27 @@
7
7
  accept?: string;
8
8
  variant?: 'multiple' | 'single' | 'avatar';
9
9
  view?: 'list' | 'grid';
10
+ layout?: 'horizontal' | 'vertical' | 'compact';
10
11
  showViewToggle?: boolean;
11
12
  maxSizeMb?: number;
12
13
  disabled?: boolean;
14
+ src?: string;
15
+ srcName?: string;
13
16
  }>();
14
17
  </script>
15
18
 
16
- <div class="w-96 max-w-full">
19
+ <div class={['max-w-full', props.layout === 'vertical' ? 'w-64' : 'w-96']}>
17
20
  <FileUploader
18
21
  label={props.label ?? 'Project Attachments'}
19
22
  helperText={props.helperText ?? 'PNG, JPG, PDF or DOCX (max 10MB)'}
20
23
  accept={props.accept ?? '*'}
21
24
  variant={props.variant ?? 'multiple'}
22
25
  view={props.view ?? 'list'}
26
+ layout={props.layout ?? 'horizontal'}
23
27
  showViewToggle={props.showViewToggle ?? true}
24
28
  maxSizeMb={props.maxSizeMb ?? 10}
25
29
  disabled={props.disabled ?? false}
30
+ src={props.src ?? ''}
31
+ srcName={props.srcName ?? ''}
26
32
  />
27
33
  </div>
@@ -4,9 +4,12 @@ type $$ComponentProps = {
4
4
  accept?: string;
5
5
  variant?: 'multiple' | 'single' | 'avatar';
6
6
  view?: 'list' | 'grid';
7
+ layout?: 'horizontal' | 'vertical' | 'compact';
7
8
  showViewToggle?: boolean;
8
9
  maxSizeMb?: number;
9
10
  disabled?: boolean;
11
+ src?: string;
12
+ srcName?: string;
10
13
  };
11
14
  declare const FileUploaderStory: import("svelte").Component<$$ComponentProps, {}, "">;
12
15
  type FileUploaderStory = ReturnType<typeof FileUploaderStory>;