@mieweb/ui 0.11.0-dev.36 → 0.11.0-dev.38

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 (103) hide show
  1. package/agent/README.md +1 -1
  2. package/agent/agents/mieweb-ui-design.agent.md +12 -7
  3. package/agent/agents/mieweb-ui-migration.agent.md +144 -0
  4. package/agent/skills/mieweb-ui-catalog/SKILL.md +8 -6
  5. package/agent/skills/mieweb-ui-catalog/selection-guidance.md +9 -5
  6. package/dist/{chunk-TUYWCUKH.js → chunk-4LKAZW2W.js} +7 -3
  7. package/dist/chunk-4LKAZW2W.js.map +1 -0
  8. package/dist/{chunk-MNXIN4MS.js → chunk-5WA6IYZD.js} +60 -2
  9. package/dist/chunk-5WA6IYZD.js.map +1 -0
  10. package/dist/{chunk-DT3X3RBM.js → chunk-7U7SONM5.js} +3 -3
  11. package/dist/{chunk-DT3X3RBM.js.map → chunk-7U7SONM5.js.map} +1 -1
  12. package/dist/{chunk-OGFSFUIX.cjs → chunk-AHYDJN4H.cjs} +501 -120
  13. package/dist/chunk-AHYDJN4H.cjs.map +1 -0
  14. package/dist/{chunk-C4GEPUE7.js → chunk-CKECOCYJ.js} +2 -2
  15. package/dist/{chunk-C4GEPUE7.js.map → chunk-CKECOCYJ.js.map} +1 -1
  16. package/dist/{chunk-V5VPECJI.js → chunk-CRR7AE5D.js} +11 -7
  17. package/dist/chunk-CRR7AE5D.js.map +1 -0
  18. package/dist/chunk-D3FNZMOB.cjs +4 -0
  19. package/dist/{chunk-GLXTVCHN.cjs.map → chunk-D3FNZMOB.cjs.map} +1 -1
  20. package/dist/{chunk-ZK2R6UGF.cjs → chunk-DCV34MEF.cjs} +4 -4
  21. package/dist/{chunk-ZK2R6UGF.cjs.map → chunk-DCV34MEF.cjs.map} +1 -1
  22. package/dist/chunk-G4VQEQGW.js +3 -0
  23. package/dist/{chunk-RISZWWEQ.js.map → chunk-G4VQEQGW.js.map} +1 -1
  24. package/dist/{chunk-S3LTUSO5.cjs → chunk-GG3IK5TL.cjs} +7 -7
  25. package/dist/{chunk-S3LTUSO5.cjs.map → chunk-GG3IK5TL.cjs.map} +1 -1
  26. package/dist/{chunk-QHCAWDMG.cjs → chunk-HDZQLTBP.cjs} +7 -3
  27. package/dist/chunk-HDZQLTBP.cjs.map +1 -0
  28. package/dist/chunk-JCIQIR5V.js +546 -0
  29. package/dist/chunk-JCIQIR5V.js.map +1 -0
  30. package/dist/{chunk-AIO2GCTL.js → chunk-JUY2JLFL.js} +501 -120
  31. package/dist/chunk-JUY2JLFL.js.map +1 -0
  32. package/dist/{chunk-2S76TRBJ.cjs → chunk-JUYBJLPI.cjs} +4 -4
  33. package/dist/{chunk-2S76TRBJ.cjs.map → chunk-JUYBJLPI.cjs.map} +1 -1
  34. package/dist/{chunk-UDUYZDTA.js → chunk-JWMMWNTT.js} +3 -3
  35. package/dist/{chunk-UDUYZDTA.js.map → chunk-JWMMWNTT.js.map} +1 -1
  36. package/dist/{chunk-RM4CBS7Y.js → chunk-LQ22CY7X.js} +4 -4
  37. package/dist/{chunk-RM4CBS7Y.js.map → chunk-LQ22CY7X.js.map} +1 -1
  38. package/dist/{chunk-AKMTPCLC.cjs → chunk-LTCHD3K5.cjs} +2 -2
  39. package/dist/{chunk-AKMTPCLC.cjs.map → chunk-LTCHD3K5.cjs.map} +1 -1
  40. package/dist/{chunk-GDKOYVX3.cjs → chunk-NZUQL42A.cjs} +11 -7
  41. package/dist/chunk-NZUQL42A.cjs.map +1 -0
  42. package/dist/chunk-QAEAC7HO.cjs +4 -0
  43. package/dist/chunk-QAEAC7HO.cjs.map +1 -0
  44. package/dist/chunk-SCGXD334.js +3 -0
  45. package/dist/chunk-SCGXD334.js.map +1 -0
  46. package/dist/chunk-TZKBW4GA.cjs +578 -0
  47. package/dist/chunk-TZKBW4GA.cjs.map +1 -0
  48. package/dist/{chunk-47AOS5EC.cjs → chunk-XX6PNPF2.cjs} +60 -2
  49. package/dist/chunk-XX6PNPF2.cjs.map +1 -0
  50. package/dist/components/AudioPlayer/index.cjs +7 -6
  51. package/dist/components/AudioPlayer/index.js +2 -1
  52. package/dist/components/MediaEditor/index.cjs +10 -9
  53. package/dist/components/MediaEditor/index.js +5 -4
  54. package/dist/components/MediaFeed/index.cjs +8 -5
  55. package/dist/components/MediaFeed/index.d.cts +33 -0
  56. package/dist/components/MediaFeed/index.d.ts +33 -0
  57. package/dist/components/MediaFeed/index.js +7 -4
  58. package/dist/components/MediaPlayer/index.cjs +13 -6
  59. package/dist/components/MediaPlayer/index.d.cts +103 -5
  60. package/dist/components/MediaPlayer/index.d.ts +103 -5
  61. package/dist/components/MediaPlayer/index.js +6 -3
  62. package/dist/components/Slider/index.cjs +5 -5
  63. package/dist/components/Slider/index.d.cts +6 -0
  64. package/dist/components/Slider/index.d.ts +6 -0
  65. package/dist/components/Slider/index.js +1 -1
  66. package/dist/components/SliderCalculator/index.cjs +4 -4
  67. package/dist/components/SliderCalculator/index.js +2 -2
  68. package/dist/components/SuperChat/index.cjs +16 -14
  69. package/dist/components/SuperChat/index.cjs.map +1 -1
  70. package/dist/components/SuperChat/index.d.cts +2 -2
  71. package/dist/components/SuperChat/index.d.ts +2 -2
  72. package/dist/components/SuperChat/index.js +8 -6
  73. package/dist/components/SuperChat/index.js.map +1 -1
  74. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  75. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  76. package/dist/hooks/index.cjs +2 -2
  77. package/dist/hooks/index.js +1 -1
  78. package/dist/index.cjs +73 -68
  79. package/dist/index.cjs.map +1 -1
  80. package/dist/index.d.cts +187 -90
  81. package/dist/index.d.ts +187 -90
  82. package/dist/index.js +14 -13
  83. package/dist/index.js.map +1 -1
  84. package/dist/styles.css +1 -1
  85. package/dist/tailwind-preset.cjs +4 -4
  86. package/dist/tailwind-preset.js +1 -1
  87. package/dist/{types-DSWbrVkM.d.cts → types-BfVolads.d.cts} +33 -0
  88. package/dist/{types-DSWbrVkM.d.ts → types-BfVolads.d.ts} +33 -0
  89. package/package.json +1 -1
  90. package/dist/chunk-47AOS5EC.cjs.map +0 -1
  91. package/dist/chunk-AIO2GCTL.js.map +0 -1
  92. package/dist/chunk-ECKIFQSD.cjs +0 -183
  93. package/dist/chunk-ECKIFQSD.cjs.map +0 -1
  94. package/dist/chunk-GDKOYVX3.cjs.map +0 -1
  95. package/dist/chunk-GLXTVCHN.cjs +0 -4
  96. package/dist/chunk-MNXIN4MS.js.map +0 -1
  97. package/dist/chunk-OGFSFUIX.cjs.map +0 -1
  98. package/dist/chunk-QHCAWDMG.cjs.map +0 -1
  99. package/dist/chunk-R5P7NAJQ.js +0 -159
  100. package/dist/chunk-R5P7NAJQ.js.map +0 -1
  101. package/dist/chunk-RISZWWEQ.js +0 -3
  102. package/dist/chunk-TUYWCUKH.js.map +0 -1
  103. package/dist/chunk-V5VPECJI.js.map +0 -1
@@ -40,6 +40,24 @@ interface MediaFeedLabels {
40
40
  next: string;
41
41
  play: string;
42
42
  pause: string;
43
+ /** The player's own controls in the `overlay` layout. */
44
+ mute: string;
45
+ unmute: string;
46
+ seek: string;
47
+ playerFullscreen: string;
48
+ exitPlayerFullscreen: string;
49
+ pictureInPicture: string;
50
+ exitPictureInPicture: string;
51
+ /** The player's elapsed and total time, already formatted. */
52
+ time: (current: string, duration: string) => string;
53
+ /** The player's speed button: its text for a rate, and its name. */
54
+ playerRate: (rate: number) => string;
55
+ playerSpeed: (rate: string) => string;
56
+ showCaptions: string;
57
+ hideCaptions: string;
58
+ /** The overlay's toggle for a title or caption that doesn't fit. */
59
+ showMore: string;
60
+ showLess: string;
43
61
  blockedAutoplay: string;
44
62
  mediaError: string;
45
63
  openSource: string;
@@ -73,6 +91,21 @@ interface MediaFeedProps<T> extends Omit<React.HTMLAttributes<HTMLDivElement>, '
73
91
  getAuthor?: (item: T) => MediaFeedAuthor;
74
92
  /** Host-owned actions, such as reactions or opening a conversation. */
75
93
  renderActions?: (item: T) => React.ReactNode;
94
+ /**
95
+ * `stacked` (default): each item is a card, its details under the media.
96
+ * `overlay`: the media fills each item edge to edge on a dark stage, with
97
+ * the details at its foot as short-video apps place them (author, title and
98
+ * caption at the start, actions in a column at the end), Previous/Next on
99
+ * the end edge, and the player's touch-first overlay controls. Suits a phone
100
+ * or a full-height pane, upright or sideways.
101
+ */
102
+ layout?: 'stacked' | 'overlay';
103
+ /**
104
+ * Offer the full-screen viewer, an expand button on each item. Defaults to
105
+ * `true` for `stacked` and `false` for `overlay`, where the feed already
106
+ * fills its space and the player has its own full screen.
107
+ */
108
+ allowFullscreen?: boolean;
76
109
  /** Replace the built-in player, respecting its active playback boundary. */
77
110
  renderMedia?: (media: MediaFeedMedia, context: MediaFeedRenderContext<T>) => React.ReactNode;
78
111
  /** Controlled selection. Changes scroll the selected record into view. */
@@ -40,6 +40,24 @@ interface MediaFeedLabels {
40
40
  next: string;
41
41
  play: string;
42
42
  pause: string;
43
+ /** The player's own controls in the `overlay` layout. */
44
+ mute: string;
45
+ unmute: string;
46
+ seek: string;
47
+ playerFullscreen: string;
48
+ exitPlayerFullscreen: string;
49
+ pictureInPicture: string;
50
+ exitPictureInPicture: string;
51
+ /** The player's elapsed and total time, already formatted. */
52
+ time: (current: string, duration: string) => string;
53
+ /** The player's speed button: its text for a rate, and its name. */
54
+ playerRate: (rate: number) => string;
55
+ playerSpeed: (rate: string) => string;
56
+ showCaptions: string;
57
+ hideCaptions: string;
58
+ /** The overlay's toggle for a title or caption that doesn't fit. */
59
+ showMore: string;
60
+ showLess: string;
43
61
  blockedAutoplay: string;
44
62
  mediaError: string;
45
63
  openSource: string;
@@ -73,6 +91,21 @@ interface MediaFeedProps<T> extends Omit<React.HTMLAttributes<HTMLDivElement>, '
73
91
  getAuthor?: (item: T) => MediaFeedAuthor;
74
92
  /** Host-owned actions, such as reactions or opening a conversation. */
75
93
  renderActions?: (item: T) => React.ReactNode;
94
+ /**
95
+ * `stacked` (default): each item is a card, its details under the media.
96
+ * `overlay`: the media fills each item edge to edge on a dark stage, with
97
+ * the details at its foot as short-video apps place them (author, title and
98
+ * caption at the start, actions in a column at the end), Previous/Next on
99
+ * the end edge, and the player's touch-first overlay controls. Suits a phone
100
+ * or a full-height pane, upright or sideways.
101
+ */
102
+ layout?: 'stacked' | 'overlay';
103
+ /**
104
+ * Offer the full-screen viewer, an expand button on each item. Defaults to
105
+ * `true` for `stacked` and `false` for `overlay`, where the feed already
106
+ * fills its space and the player has its own full screen.
107
+ */
108
+ allowFullscreen?: boolean;
76
109
  /** Replace the built-in player, respecting its active playback boundary. */
77
110
  renderMedia?: (media: MediaFeedMedia, context: MediaFeedRenderContext<T>) => React.ReactNode;
78
111
  /** Controlled selection. Changes scroll the selected record into view. */
@@ -1,7 +1,9 @@
1
- export { MediaFeed } from '../../chunk-AIO2GCTL.js';
2
- import '../../chunk-RISZWWEQ.js';
3
- import '../../chunk-R5P7NAJQ.js';
4
- import '../../chunk-TUYWCUKH.js';
1
+ export { MediaFeed } from '../../chunk-JUY2JLFL.js';
2
+ import '../../chunk-SCGXD334.js';
3
+ import '../../chunk-JCIQIR5V.js';
4
+ import '../../chunk-CRR7AE5D.js';
5
+ import '../../chunk-CKECOCYJ.js';
6
+ import '../../chunk-4LKAZW2W.js';
5
7
  import '../../chunk-H2Y7HZV5.js';
6
8
  import '../../chunk-DVDT7TX7.js';
7
9
  import '../../chunk-TI3TQQ7F.js';
@@ -10,6 +12,7 @@ import '../../chunk-4SMSH4OY.js';
10
12
  import '../../chunk-VSQF22GL.js';
11
13
  import '../../chunk-T4ME7QCT.js';
12
14
  import '../../chunk-XDU65GLW.js';
15
+ import '../../chunk-YVKBXNPK.js';
13
16
  import '../../chunk-N5JDL4VE.js';
14
17
  import '../../chunk-WX2XB6FP.js';
15
18
  import '../../chunk-VP3XNLUL.js';
@@ -1,8 +1,11 @@
1
1
  'use strict';
2
2
 
3
- require('../../chunk-GLXTVCHN.cjs');
4
- var chunkECKIFQSD_cjs = require('../../chunk-ECKIFQSD.cjs');
5
- require('../../chunk-QHCAWDMG.cjs');
3
+ require('../../chunk-D3FNZMOB.cjs');
4
+ var chunkTZKBW4GA_cjs = require('../../chunk-TZKBW4GA.cjs');
5
+ require('../../chunk-NZUQL42A.cjs');
6
+ require('../../chunk-LTCHD3K5.cjs');
7
+ require('../../chunk-HDZQLTBP.cjs');
8
+ require('../../chunk-Z3WMDVMR.cjs');
6
9
  require('../../chunk-EACNRR3C.cjs');
7
10
  require('../../chunk-FSARTLUE.cjs');
8
11
  require('../../chunk-HGJHWI7W.cjs');
@@ -11,17 +14,21 @@ require('../../chunk-EUAMEVVI.cjs');
11
14
 
12
15
 
13
16
 
17
+ Object.defineProperty(exports, "MediaControls", {
18
+ enumerable: true,
19
+ get: function () { return chunkTZKBW4GA_cjs.MediaControls; }
20
+ });
14
21
  Object.defineProperty(exports, "MediaPlayer", {
15
22
  enumerable: true,
16
- get: function () { return chunkECKIFQSD_cjs.MediaPlayer; }
23
+ get: function () { return chunkTZKBW4GA_cjs.MediaPlayer; }
17
24
  });
18
25
  Object.defineProperty(exports, "inferMediaKind", {
19
26
  enumerable: true,
20
- get: function () { return chunkECKIFQSD_cjs.inferMediaKind; }
27
+ get: function () { return chunkTZKBW4GA_cjs.inferMediaKind; }
21
28
  });
22
29
  Object.defineProperty(exports, "mediaPlayerVariants", {
23
30
  enumerable: true,
24
- get: function () { return chunkECKIFQSD_cjs.mediaPlayerVariants; }
31
+ get: function () { return chunkTZKBW4GA_cjs.mediaPlayerVariants; }
25
32
  });
26
33
  //# sourceMappingURL=index.cjs.map
27
34
  //# sourceMappingURL=index.cjs.map
@@ -2,6 +2,95 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
2
2
  import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
+ type MediaTransportState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
6
+ interface UseMediaTransportReturn {
7
+ /**
8
+ * Callback ref for the `<audio>`/`<video>` element to control. Pass this to
9
+ * the element's `ref` (or call it imperatively). Transport listeners attach
10
+ * when an element mounts and detach when it unmounts.
11
+ */
12
+ setMediaElement: (element: HTMLMediaElement | null) => void;
13
+ /** The currently attached media element, or `null`. */
14
+ mediaElement: HTMLMediaElement | null;
15
+ /** Derived transport state. */
16
+ state: MediaTransportState;
17
+ /** Current playback position in milliseconds. */
18
+ currentTimeMs: number;
19
+ /** Media duration in milliseconds (`0` until known / non-finite). */
20
+ durationMs: number;
21
+ /** Current playback rate. */
22
+ playbackRate: number;
23
+ /** `true` while `state === 'playing'`. */
24
+ isPlaying: boolean;
25
+ /** `true` while `state === 'loading'`. */
26
+ isLoading: boolean;
27
+ /** Start playback. */
28
+ play: () => void;
29
+ /** Pause playback. */
30
+ pause: () => void;
31
+ /** Toggle between play and pause. */
32
+ togglePlay: () => void;
33
+ /** Seek to a position in milliseconds. */
34
+ seekToMs: (timeMs: number) => void;
35
+ /** Set the playback rate multiplier. */
36
+ setPlaybackRate: (rate: number) => void;
37
+ /** Read the current position in milliseconds. */
38
+ getCurrentTimeMs: () => number;
39
+ /** Read the duration in milliseconds (`0` when unknown). */
40
+ getDurationMs: () => number;
41
+ /** Whether playback is currently paused (reads the element directly). */
42
+ isPaused: () => boolean;
43
+ }
44
+
45
+ /** Every string the controls show or announce, for the host to localize. */
46
+ interface MediaControlsLabels {
47
+ play: string;
48
+ pause: string;
49
+ mute: string;
50
+ unmute: string;
51
+ seek: string;
52
+ fullscreen: string;
53
+ exitFullscreen: string;
54
+ pictureInPicture: string;
55
+ exitPictureInPicture: string;
56
+ /** The elapsed and total time, already formatted (`1:05`, `4:30`). */
57
+ time: (current: string, duration: string) => string;
58
+ /** The speed button's text for a rate (`1.5×`). */
59
+ rate: (rate: number) => string;
60
+ /** The speed button's accessible name, given its text. */
61
+ speed: (rate: string) => string;
62
+ showCaptions: string;
63
+ hideCaptions: string;
64
+ }
65
+ interface MediaControlsProps extends React.HTMLAttributes<HTMLDivElement> {
66
+ /** The transport attached to the `<video>` these controls drive. */
67
+ transport: UseMediaTransportReturn;
68
+ /**
69
+ * The box that goes full screen with the controls (the video and these
70
+ * controls' shared parent). Where the browser can't take an element full
71
+ * screen (an iPhone), the video opens in the system's own player instead.
72
+ */
73
+ fullscreenTarget?: React.RefObject<HTMLElement | null>;
74
+ /** Localized text for every control; English by default. */
75
+ labels?: Partial<MediaControlsLabels>;
76
+ /** The speeds the speed button cycles through (default `[1, 1.5, 2]`). */
77
+ playbackRates?: readonly number[];
78
+ }
79
+ /**
80
+ * Touch-first controls laid over a `<video>`, in place of the browser's own.
81
+ * A tap on the picture plays or pauses it, a round ▶ shows while it's paused,
82
+ * and a bar along the bottom has play/pause, the time, a seek bar, playback
83
+ * speed, captions on/off when the video has a caption track, mute, and
84
+ * picture in picture and full screen where the browser supports them.
85
+ *
86
+ * `MediaPlayer` renders it for `controlsStyle="overlay"`. To use it directly,
87
+ * render it in a positioned box with the video, attach
88
+ * `transport.setMediaElement` to the video's `ref` and give the video
89
+ * `playsInline` (without it, an iPhone plays it in the system player, away
90
+ * from these controls).
91
+ */
92
+ declare const MediaControls: React.ForwardRefExoticComponent<MediaControlsProps & React.RefAttributes<HTMLDivElement>>;
93
+
5
94
  type MediaPlayerState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
6
95
  type MediaKind = 'video' | 'audio';
7
96
  /** Ref handle for controlling {@link MediaPlayer} programmatically. */
@@ -32,9 +121,16 @@ interface MediaPlayerProps extends VariantProps<typeof mediaPlayerVariants> {
32
121
  src: string;
33
122
  /** Force the media kind; when omitted it is inferred from the src extension. */
34
123
  kind?: MediaKind;
35
- /** Whether to show native controls (default `true`). */
124
+ /** Whether to show controls (default `true`). */
36
125
  controls?: boolean;
37
- /** Begin muted; native controls can still change the volume. */
126
+ /**
127
+ * Which controls a video gets (default `'native'`, the browser's own).
128
+ * `'overlay'` lays touch-first controls over it ({@link MediaControls}),
129
+ * the same in every browser and in a mobile app's web view. Audio always uses
130
+ * the browser's.
131
+ */
132
+ controlsStyle?: 'native' | 'overlay';
133
+ /** Begin muted; the controls can still unmute it. */
38
134
  muted?: boolean;
39
135
  /** Repeat playback when the media ends. */
40
136
  loop?: boolean;
@@ -45,11 +141,13 @@ interface MediaPlayerProps extends VariantProps<typeof mediaPlayerVariants> {
45
141
  /** Caption/subtitle `<track>` elements. The `src` attribute is always set
46
142
  * on the media element, so alternative `<source>` children are ignored. */
47
143
  children?: React.ReactNode;
48
- /** Localized load-error and retry text. */
144
+ /** The speeds the overlay controls' speed button cycles through (default `[1, 1.5, 2]`). */
145
+ playbackRates?: readonly number[];
146
+ /** Localized load-error and retry text, and the overlay controls' labels. */
49
147
  labels?: {
50
148
  error?: string;
51
149
  retry?: string;
52
- };
150
+ } & Partial<MediaControlsLabels>;
53
151
  /** Callback when playback state changes. */
54
152
  onStateChange?: (state: MediaPlayerState) => void;
55
153
  /** Callback when playback ends. */
@@ -86,4 +184,4 @@ declare function inferMediaKind(src: string): MediaKind;
86
184
  */
87
185
  declare const MediaPlayer: React.ForwardRefExoticComponent<MediaPlayerProps & React.RefAttributes<MediaPlayerRef>>;
88
186
 
89
- export { type MediaKind, MediaPlayer, type MediaPlayerProps, type MediaPlayerRef, type MediaPlayerState, inferMediaKind, mediaPlayerVariants };
187
+ export { MediaControls, type MediaControlsLabels, type MediaControlsProps, type MediaKind, MediaPlayer, type MediaPlayerProps, type MediaPlayerRef, type MediaPlayerState, inferMediaKind, mediaPlayerVariants };
@@ -2,6 +2,95 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
2
2
  import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
+ type MediaTransportState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
6
+ interface UseMediaTransportReturn {
7
+ /**
8
+ * Callback ref for the `<audio>`/`<video>` element to control. Pass this to
9
+ * the element's `ref` (or call it imperatively). Transport listeners attach
10
+ * when an element mounts and detach when it unmounts.
11
+ */
12
+ setMediaElement: (element: HTMLMediaElement | null) => void;
13
+ /** The currently attached media element, or `null`. */
14
+ mediaElement: HTMLMediaElement | null;
15
+ /** Derived transport state. */
16
+ state: MediaTransportState;
17
+ /** Current playback position in milliseconds. */
18
+ currentTimeMs: number;
19
+ /** Media duration in milliseconds (`0` until known / non-finite). */
20
+ durationMs: number;
21
+ /** Current playback rate. */
22
+ playbackRate: number;
23
+ /** `true` while `state === 'playing'`. */
24
+ isPlaying: boolean;
25
+ /** `true` while `state === 'loading'`. */
26
+ isLoading: boolean;
27
+ /** Start playback. */
28
+ play: () => void;
29
+ /** Pause playback. */
30
+ pause: () => void;
31
+ /** Toggle between play and pause. */
32
+ togglePlay: () => void;
33
+ /** Seek to a position in milliseconds. */
34
+ seekToMs: (timeMs: number) => void;
35
+ /** Set the playback rate multiplier. */
36
+ setPlaybackRate: (rate: number) => void;
37
+ /** Read the current position in milliseconds. */
38
+ getCurrentTimeMs: () => number;
39
+ /** Read the duration in milliseconds (`0` when unknown). */
40
+ getDurationMs: () => number;
41
+ /** Whether playback is currently paused (reads the element directly). */
42
+ isPaused: () => boolean;
43
+ }
44
+
45
+ /** Every string the controls show or announce, for the host to localize. */
46
+ interface MediaControlsLabels {
47
+ play: string;
48
+ pause: string;
49
+ mute: string;
50
+ unmute: string;
51
+ seek: string;
52
+ fullscreen: string;
53
+ exitFullscreen: string;
54
+ pictureInPicture: string;
55
+ exitPictureInPicture: string;
56
+ /** The elapsed and total time, already formatted (`1:05`, `4:30`). */
57
+ time: (current: string, duration: string) => string;
58
+ /** The speed button's text for a rate (`1.5×`). */
59
+ rate: (rate: number) => string;
60
+ /** The speed button's accessible name, given its text. */
61
+ speed: (rate: string) => string;
62
+ showCaptions: string;
63
+ hideCaptions: string;
64
+ }
65
+ interface MediaControlsProps extends React.HTMLAttributes<HTMLDivElement> {
66
+ /** The transport attached to the `<video>` these controls drive. */
67
+ transport: UseMediaTransportReturn;
68
+ /**
69
+ * The box that goes full screen with the controls (the video and these
70
+ * controls' shared parent). Where the browser can't take an element full
71
+ * screen (an iPhone), the video opens in the system's own player instead.
72
+ */
73
+ fullscreenTarget?: React.RefObject<HTMLElement | null>;
74
+ /** Localized text for every control; English by default. */
75
+ labels?: Partial<MediaControlsLabels>;
76
+ /** The speeds the speed button cycles through (default `[1, 1.5, 2]`). */
77
+ playbackRates?: readonly number[];
78
+ }
79
+ /**
80
+ * Touch-first controls laid over a `<video>`, in place of the browser's own.
81
+ * A tap on the picture plays or pauses it, a round ▶ shows while it's paused,
82
+ * and a bar along the bottom has play/pause, the time, a seek bar, playback
83
+ * speed, captions on/off when the video has a caption track, mute, and
84
+ * picture in picture and full screen where the browser supports them.
85
+ *
86
+ * `MediaPlayer` renders it for `controlsStyle="overlay"`. To use it directly,
87
+ * render it in a positioned box with the video, attach
88
+ * `transport.setMediaElement` to the video's `ref` and give the video
89
+ * `playsInline` (without it, an iPhone plays it in the system player, away
90
+ * from these controls).
91
+ */
92
+ declare const MediaControls: React.ForwardRefExoticComponent<MediaControlsProps & React.RefAttributes<HTMLDivElement>>;
93
+
5
94
  type MediaPlayerState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
6
95
  type MediaKind = 'video' | 'audio';
7
96
  /** Ref handle for controlling {@link MediaPlayer} programmatically. */
@@ -32,9 +121,16 @@ interface MediaPlayerProps extends VariantProps<typeof mediaPlayerVariants> {
32
121
  src: string;
33
122
  /** Force the media kind; when omitted it is inferred from the src extension. */
34
123
  kind?: MediaKind;
35
- /** Whether to show native controls (default `true`). */
124
+ /** Whether to show controls (default `true`). */
36
125
  controls?: boolean;
37
- /** Begin muted; native controls can still change the volume. */
126
+ /**
127
+ * Which controls a video gets (default `'native'`, the browser's own).
128
+ * `'overlay'` lays touch-first controls over it ({@link MediaControls}),
129
+ * the same in every browser and in a mobile app's web view. Audio always uses
130
+ * the browser's.
131
+ */
132
+ controlsStyle?: 'native' | 'overlay';
133
+ /** Begin muted; the controls can still unmute it. */
38
134
  muted?: boolean;
39
135
  /** Repeat playback when the media ends. */
40
136
  loop?: boolean;
@@ -45,11 +141,13 @@ interface MediaPlayerProps extends VariantProps<typeof mediaPlayerVariants> {
45
141
  /** Caption/subtitle `<track>` elements. The `src` attribute is always set
46
142
  * on the media element, so alternative `<source>` children are ignored. */
47
143
  children?: React.ReactNode;
48
- /** Localized load-error and retry text. */
144
+ /** The speeds the overlay controls' speed button cycles through (default `[1, 1.5, 2]`). */
145
+ playbackRates?: readonly number[];
146
+ /** Localized load-error and retry text, and the overlay controls' labels. */
49
147
  labels?: {
50
148
  error?: string;
51
149
  retry?: string;
52
- };
150
+ } & Partial<MediaControlsLabels>;
53
151
  /** Callback when playback state changes. */
54
152
  onStateChange?: (state: MediaPlayerState) => void;
55
153
  /** Callback when playback ends. */
@@ -86,4 +184,4 @@ declare function inferMediaKind(src: string): MediaKind;
86
184
  */
87
185
  declare const MediaPlayer: React.ForwardRefExoticComponent<MediaPlayerProps & React.RefAttributes<MediaPlayerRef>>;
88
186
 
89
- export { type MediaKind, MediaPlayer, type MediaPlayerProps, type MediaPlayerRef, type MediaPlayerState, inferMediaKind, mediaPlayerVariants };
187
+ export { MediaControls, type MediaControlsLabels, type MediaControlsProps, type MediaKind, MediaPlayer, type MediaPlayerProps, type MediaPlayerRef, type MediaPlayerState, inferMediaKind, mediaPlayerVariants };
@@ -1,6 +1,9 @@
1
- import '../../chunk-RISZWWEQ.js';
2
- export { MediaPlayer, inferMediaKind, mediaPlayerVariants } from '../../chunk-R5P7NAJQ.js';
3
- import '../../chunk-TUYWCUKH.js';
1
+ import '../../chunk-SCGXD334.js';
2
+ export { MediaControls, MediaPlayer, inferMediaKind, mediaPlayerVariants } from '../../chunk-JCIQIR5V.js';
3
+ import '../../chunk-CRR7AE5D.js';
4
+ import '../../chunk-CKECOCYJ.js';
5
+ import '../../chunk-4LKAZW2W.js';
6
+ import '../../chunk-YVKBXNPK.js';
4
7
  import '../../chunk-N5JDL4VE.js';
5
8
  import '../../chunk-WX2XB6FP.js';
6
9
  import '../../chunk-VP3XNLUL.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkGDKOYVX3_cjs = require('../../chunk-GDKOYVX3.cjs');
3
+ var chunkNZUQL42A_cjs = require('../../chunk-NZUQL42A.cjs');
4
4
  require('../../chunk-Z3WMDVMR.cjs');
5
5
  require('../../chunk-S5RVSXDV.cjs');
6
6
  require('../../chunk-EUAMEVVI.cjs');
@@ -9,19 +9,19 @@ require('../../chunk-EUAMEVVI.cjs');
9
9
 
10
10
  Object.defineProperty(exports, "Slider", {
11
11
  enumerable: true,
12
- get: function () { return chunkGDKOYVX3_cjs.Slider; }
12
+ get: function () { return chunkNZUQL42A_cjs.Slider; }
13
13
  });
14
14
  Object.defineProperty(exports, "sliderRangeVariants", {
15
15
  enumerable: true,
16
- get: function () { return chunkGDKOYVX3_cjs.sliderRangeVariants; }
16
+ get: function () { return chunkNZUQL42A_cjs.sliderRangeVariants; }
17
17
  });
18
18
  Object.defineProperty(exports, "sliderThumbVariants", {
19
19
  enumerable: true,
20
- get: function () { return chunkGDKOYVX3_cjs.sliderThumbVariants; }
20
+ get: function () { return chunkNZUQL42A_cjs.sliderThumbVariants; }
21
21
  });
22
22
  Object.defineProperty(exports, "sliderTrackVariants", {
23
23
  enumerable: true,
24
- get: function () { return chunkGDKOYVX3_cjs.sliderTrackVariants; }
24
+ get: function () { return chunkNZUQL42A_cjs.sliderTrackVariants; }
25
25
  });
26
26
  //# sourceMappingURL=index.cjs.map
27
27
  //# sourceMappingURL=index.cjs.map
@@ -23,6 +23,12 @@ interface SliderProps extends VariantProps<typeof sliderTrackVariants>, VariantP
23
23
  max?: number;
24
24
  /** Step increment */
25
25
  step?: number;
26
+ /**
27
+ * How far an arrow key moves the value (default `step`). Use it when the
28
+ * pointer needs fine steps but the keyboard should move in bigger ones,
29
+ * e.g. a media seek bar.
30
+ */
31
+ keyboardStep?: number;
26
32
  /** Callback when value changes */
27
33
  onValueChange?: (value: number) => void;
28
34
  /** Callback when interaction ends (mouseup / touchend) */
@@ -23,6 +23,12 @@ interface SliderProps extends VariantProps<typeof sliderTrackVariants>, VariantP
23
23
  max?: number;
24
24
  /** Step increment */
25
25
  step?: number;
26
+ /**
27
+ * How far an arrow key moves the value (default `step`). Use it when the
28
+ * pointer needs fine steps but the keyboard should move in bigger ones,
29
+ * e.g. a media seek bar.
30
+ */
31
+ keyboardStep?: number;
26
32
  /** Callback when value changes */
27
33
  onValueChange?: (value: number) => void;
28
34
  /** Callback when interaction ends (mouseup / touchend) */
@@ -1,4 +1,4 @@
1
- export { Slider, sliderRangeVariants, sliderThumbVariants, sliderTrackVariants } from '../../chunk-V5VPECJI.js';
1
+ export { Slider, sliderRangeVariants, sliderThumbVariants, sliderTrackVariants } from '../../chunk-CRR7AE5D.js';
2
2
  import '../../chunk-YVKBXNPK.js';
3
3
  import '../../chunk-TQONQSJO.js';
4
4
  import '../../chunk-PX6F3LHL.js';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk2S76TRBJ_cjs = require('../../chunk-2S76TRBJ.cjs');
4
- require('../../chunk-GDKOYVX3.cjs');
3
+ var chunkJUYBJLPI_cjs = require('../../chunk-JUYBJLPI.cjs');
4
+ require('../../chunk-NZUQL42A.cjs');
5
5
  require('../../chunk-YW2AKBLS.cjs');
6
6
  require('../../chunk-Z3WMDVMR.cjs');
7
7
  require('../../chunk-S5RVSXDV.cjs');
@@ -11,11 +11,11 @@ require('../../chunk-EUAMEVVI.cjs');
11
11
 
12
12
  Object.defineProperty(exports, "AnimatedNumber", {
13
13
  enumerable: true,
14
- get: function () { return chunk2S76TRBJ_cjs.AnimatedNumber; }
14
+ get: function () { return chunkJUYBJLPI_cjs.AnimatedNumber; }
15
15
  });
16
16
  Object.defineProperty(exports, "SliderCalculator", {
17
17
  enumerable: true,
18
- get: function () { return chunk2S76TRBJ_cjs.SliderCalculator; }
18
+ get: function () { return chunkJUYBJLPI_cjs.SliderCalculator; }
19
19
  });
20
20
  //# sourceMappingURL=index.cjs.map
21
21
  //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,5 @@
1
- export { AnimatedNumber, SliderCalculator } from '../../chunk-DT3X3RBM.js';
2
- import '../../chunk-V5VPECJI.js';
1
+ export { AnimatedNumber, SliderCalculator } from '../../chunk-7U7SONM5.js';
2
+ import '../../chunk-CRR7AE5D.js';
3
3
  import '../../chunk-XDU65GLW.js';
4
4
  import '../../chunk-YVKBXNPK.js';
5
5
  import '../../chunk-TQONQSJO.js';
@@ -1,15 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkJFLC7SHM_cjs = require('../../chunk-JFLC7SHM.cjs');
4
- var chunkZK2R6UGF_cjs = require('../../chunk-ZK2R6UGF.cjs');
4
+ var chunkDCV34MEF_cjs = require('../../chunk-DCV34MEF.cjs');
5
5
  var chunk2GBVJHWN_cjs = require('../../chunk-2GBVJHWN.cjs');
6
- var chunkOGFSFUIX_cjs = require('../../chunk-OGFSFUIX.cjs');
7
- require('../../chunk-GLXTVCHN.cjs');
8
- var chunkECKIFQSD_cjs = require('../../chunk-ECKIFQSD.cjs');
9
- require('../../chunk-AKMTPCLC.cjs');
6
+ var chunkAHYDJN4H_cjs = require('../../chunk-AHYDJN4H.cjs');
7
+ require('../../chunk-D3FNZMOB.cjs');
8
+ var chunkTZKBW4GA_cjs = require('../../chunk-TZKBW4GA.cjs');
9
+ require('../../chunk-NZUQL42A.cjs');
10
+ require('../../chunk-QAEAC7HO.cjs');
11
+ require('../../chunk-LTCHD3K5.cjs');
10
12
  require('../../chunk-VBWRH4UW.cjs');
11
13
  var chunkVPTASZ2O_cjs = require('../../chunk-VPTASZ2O.cjs');
12
- require('../../chunk-QHCAWDMG.cjs');
14
+ require('../../chunk-HDZQLTBP.cjs');
13
15
  require('../../chunk-P22YCUVM.cjs');
14
16
  require('../../chunk-Q3YVLO52.cjs');
15
17
  var chunkGKDHMNUA_cjs = require('../../chunk-GKDHMNUA.cjs');
@@ -98,7 +100,7 @@ function MessageMedia({
98
100
  // An opaque themed surface: the player's semi-transparent states
99
101
  // (error, loading) must never compose onto a colored chat bubble.
100
102
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-background overflow-hidden rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
101
- chunkECKIFQSD_cjs.MediaPlayer,
103
+ chunkTZKBW4GA_cjs.MediaPlayer,
102
104
  {
103
105
  src: attachment.src,
104
106
  kind: attachment.kind,
@@ -227,7 +229,7 @@ function ParticipantAvatar({
227
229
  src: participant?.avatar,
228
230
  alt: "",
229
231
  name: participant?.name ?? "?",
230
- fallback: isAgent ? /* @__PURE__ */ jsxRuntime.jsx(chunkZK2R6UGF_cjs.SparklesIcon, { size: "sm" }) : void 0,
232
+ fallback: isAgent ? /* @__PURE__ */ jsxRuntime.jsx(chunkDCV34MEF_cjs.SparklesIcon, { size: "sm" }) : void 0,
231
233
  style: { backgroundColor },
232
234
  "aria-hidden": "true",
233
235
  className: "shrink-0"
@@ -763,7 +765,7 @@ ${block.text}
763
765
  isSelf ? "flex-row-reverse" : "flex-row"
764
766
  ),
765
767
  children: /* @__PURE__ */ jsxRuntime.jsx(
766
- chunkZK2R6UGF_cjs.ChatBubble,
768
+ chunkDCV34MEF_cjs.ChatBubble,
767
769
  {
768
770
  ref: bubbleRef,
769
771
  "data-slot": "superchat-bubble",
@@ -827,7 +829,7 @@ ${block.text}
827
829
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
828
830
  message.content?.map((block, i) => {
829
831
  if (block.type === "tool_use" && block.toolCall) {
830
- return /* @__PURE__ */ jsxRuntime.jsx(chunkZK2R6UGF_cjs.MCPToolCallDisplay, { toolCall: block.toolCall }, i);
832
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkDCV34MEF_cjs.MCPToolCallDisplay, { toolCall: block.toolCall }, i);
831
833
  }
832
834
  if ((block.type === "text" || block.type === "thinking") && block.text) {
833
835
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -880,7 +882,7 @@ ${block.text}
880
882
  },
881
883
  attachment.id
882
884
  )),
883
- streaming && !hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(chunkZK2R6UGF_cjs.AITypingIndicator, {}) })
885
+ streaming && !hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(chunkDCV34MEF_cjs.AITypingIndicator, {}) })
884
886
  ] })
885
887
  }
886
888
  )
@@ -1763,7 +1765,7 @@ function SuperChat({
1763
1765
  onClick: () => onConversationClosed(conversation),
1764
1766
  "aria-label": "Close conversation",
1765
1767
  className: "rounded-md p-1 text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800",
1766
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkZK2R6UGF_cjs.CloseIcon, {})
1768
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkDCV34MEF_cjs.CloseIcon, {})
1767
1769
  }
1768
1770
  )
1769
1771
  ]
@@ -1796,7 +1798,7 @@ function SuperChat({
1796
1798
  }
1797
1799
  ) }) }),
1798
1800
  /* @__PURE__ */ React3.createElement(
1799
- chunkOGFSFUIX_cjs.MediaFeed,
1801
+ chunkAHYDJN4H_cjs.MediaFeed,
1800
1802
  {
1801
1803
  ...mediaFeedProps,
1802
1804
  ref: mediaFeedRef,
@@ -1884,7 +1886,7 @@ function SuperChat({
1884
1886
  mode: "presence",
1885
1887
  className: "absolute inset-x-0 bottom-0 z-20",
1886
1888
  children: /* @__PURE__ */ jsxRuntime.jsx(
1887
- chunkZK2R6UGF_cjs.JumpToBottomButton,
1889
+ chunkDCV34MEF_cjs.JumpToBottomButton,
1888
1890
  {
1889
1891
  dataSlot: "superchat-jump-to-bottom",
1890
1892
  hasNewMessages: hasNewBelow,