sceyt-chat-react-uikit 1.8.0-beta.4 → 1.8.0-beta.6

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/index.modern.js CHANGED
@@ -12578,12 +12578,14 @@ var ThemeReducer = (function (state, _ref) {
12578
12578
  switch (type) {
12579
12579
  case SET_THEME:
12580
12580
  {
12581
+ console.log('SET_THEME', payload);
12581
12582
  var theme = payload.theme;
12582
12583
  newState.theme = theme;
12583
12584
  return newState;
12584
12585
  }
12585
12586
  case SET_THEME_NEW:
12586
12587
  {
12588
+ console.log('SET_THEME_NEW', payload);
12587
12589
  var _theme = payload.theme;
12588
12590
  newState.newTheme = _theme;
12589
12591
  return newState;
@@ -24399,12 +24401,20 @@ function useOnScreen(ref, rootElement) {
24399
24401
  return isIntersecting;
24400
24402
  }
24401
24403
 
24404
+ var newThemeSelector = function newThemeSelector(store) {
24405
+ var _store$ThemeReducer;
24406
+ return store === null || store === void 0 ? void 0 : (_store$ThemeReducer = store.ThemeReducer) === null || _store$ThemeReducer === void 0 ? void 0 : _store$ThemeReducer.newTheme;
24407
+ };
24408
+ var themeSelector = function themeSelector(store) {
24409
+ var _store$ThemeReducer2;
24410
+ return store === null || store === void 0 ? void 0 : (_store$ThemeReducer2 = store.ThemeReducer) === null || _store$ThemeReducer2 === void 0 ? void 0 : _store$ThemeReducer2.theme;
24411
+ };
24412
+
24402
24413
  var useColors = function useColors() {
24403
- var themeReducer = useSelector(function (state) {
24404
- return state.ThemeReducer;
24405
- });
24406
- var currentThemeMode = (themeReducer === null || themeReducer === void 0 ? void 0 : themeReducer.theme) || defaultThemeMode;
24407
- var theme = (themeReducer === null || themeReducer === void 0 ? void 0 : themeReducer.newTheme) || defaultTheme;
24414
+ var newTheme = useSelector(newThemeSelector);
24415
+ var themeMode = useSelector(themeSelector);
24416
+ var currentThemeMode = themeMode || defaultThemeMode;
24417
+ var theme = newTheme || defaultTheme;
24408
24418
  return useMemo(function () {
24409
24419
  var colorsWithMode = {};
24410
24420
  Object.keys(theme.colors).forEach(function (colorKey) {
@@ -24544,11 +24554,6 @@ function SvgAvatar(props) {
24544
24554
  })));
24545
24555
  }
24546
24556
 
24547
- var themeSelector = function themeSelector(store) {
24548
- var _store$ThemeReducer;
24549
- return store === null || store === void 0 ? void 0 : (_store$ThemeReducer = store.ThemeReducer) === null || _store$ThemeReducer === void 0 ? void 0 : _store$ThemeReducer.theme;
24550
- };
24551
-
24552
24557
  var ATTACHMENTS_CACHE = 'attachments-cache';
24553
24558
  var isBrowser = typeof window !== 'undefined';
24554
24559
  var cacheAvailable;
@@ -25801,7 +25806,6 @@ var ChannelMessageText = function ChannelMessageText(_ref2) {
25801
25806
  var Channel = function Channel(_ref3) {
25802
25807
  var _channel$members, _channel$members$, _channel$members$2;
25803
25808
  var channel = _ref3.channel,
25804
- theme = _ref3.theme,
25805
25809
  _ref3$showAvatar = _ref3.showAvatar,
25806
25810
  showAvatar = _ref3$showAvatar === void 0 ? true : _ref3$showAvatar,
25807
25811
  avatarBorderRadius = _ref3.avatarBorderRadius,
@@ -25999,7 +26003,6 @@ var Channel = function Channel(_ref3) {
25999
26003
  }
26000
26004
  }, [channel, activeChannel.id, setSelectedChannel]);
26001
26005
  return /*#__PURE__*/React__default.createElement(Container$3, {
26002
- theme: theme,
26003
26006
  backgroundColor: background,
26004
26007
  selectedChannel: channel.id === activeChannel.id,
26005
26008
  selectedChannelLeftBorder: selectedChannelLeftBorder,
@@ -26027,7 +26030,6 @@ var Channel = function Channel(_ref3) {
26027
26030
  backgroundColor: onlineStatus,
26028
26031
  borderColor: background
26029
26032
  })))), /*#__PURE__*/React__default.createElement(ChannelInfo, {
26030
- theme: theme,
26031
26033
  avatar: showAvatar,
26032
26034
  isMuted: channel.muted,
26033
26035
  isPinned: !!channel.pinnedAt,
@@ -26308,7 +26310,6 @@ var _templateObject$8, _templateObject2$7, _templateObject3$6, _templateObject4$
26308
26310
  var ContactItem = function ContactItem(_ref) {
26309
26311
  var contact = _ref.contact,
26310
26312
  createChatWithContact = _ref.createChatWithContact,
26311
- theme = _ref.theme,
26312
26313
  _ref$showAvatar = _ref.showAvatar,
26313
26314
  showAvatar = _ref$showAvatar === void 0 ? true : _ref$showAvatar,
26314
26315
  avatarBorderRadius = _ref.avatarBorderRadius,
@@ -26328,7 +26329,6 @@ var ContactItem = function ContactItem(_ref) {
26328
26329
  var getFromContacts = getShowOnlyContactUsers();
26329
26330
  var contactUserName = makeUsername(contact, undefined, getFromContacts);
26330
26331
  return /*#__PURE__*/React__default.createElement(Container$4, {
26331
- theme: theme,
26332
26332
  channelsPaddings: channelsPaddings,
26333
26333
  channelsMargin: channelsMargin,
26334
26334
  onClick: function onClick() {
@@ -26346,7 +26346,6 @@ var ContactItem = function ContactItem(_ref) {
26346
26346
  backgroundColor: online,
26347
26347
  borderColor: background
26348
26348
  })))), /*#__PURE__*/React__default.createElement(ChannelInfo$1, {
26349
- theme: theme,
26350
26349
  avatar: showAvatar,
26351
26350
  subjectFontSize: channelSubjectFontSize,
26352
26351
  subjectLineHeight: channelSubjectLineHeight,
@@ -27137,8 +27136,7 @@ function getRadianAngle(degreeValue) {
27137
27136
 
27138
27137
  var _templateObject$c, _templateObject2$b;
27139
27138
  var ImageCrop = function ImageCrop(_ref) {
27140
- var theme = _ref.theme,
27141
- image = _ref.image,
27139
+ var image = _ref.image,
27142
27140
  onAccept = _ref.onAccept,
27143
27141
  handleClosePopup = _ref.handleClosePopup;
27144
27142
  var _useState = useState(null),
@@ -27192,7 +27190,6 @@ var ImageCrop = function ImageCrop(_ref) {
27192
27190
  }
27193
27191
  }, [area]);
27194
27192
  return /*#__PURE__*/React__default.createElement(PopupContainer, null, /*#__PURE__*/React__default.createElement(Popup, {
27195
- theme: theme,
27196
27193
  backgroundColor: background,
27197
27194
  minWidth: '500px',
27198
27195
  maxWidth: '600px',
@@ -27292,7 +27289,6 @@ function CreateChannel(_ref) {
27292
27289
  var uriRegexp = /^[A-Za-z0-9]*$/;
27293
27290
  var fileUploader = useRef(null);
27294
27291
  var uriPrefixRef = useRef(null);
27295
- var theme = useSelector(themeSelector);
27296
27292
  var _useState = useState(false),
27297
27293
  usersPopupVisible = _useState[0],
27298
27294
  setUsersPopupVisible = _useState[1];
@@ -27543,7 +27539,6 @@ function CreateChannel(_ref) {
27543
27539
  value: subjectValue,
27544
27540
  onChange: handleTypeSubject,
27545
27541
  placeholder: "Enter " + (createGroupChannel ? 'group' : 'channel') + " name",
27546
- theme: theme,
27547
27542
  color: textPrimary,
27548
27543
  errorColor: warningColor,
27549
27544
  placeholderColor: textFootnote,
@@ -27557,7 +27552,6 @@ function CreateChannel(_ref) {
27557
27552
  value: metadataValue,
27558
27553
  onChange: handleTypeMetadata,
27559
27554
  placeholder: "Enter " + (createGroupChannel ? 'group' : 'channel') + " description",
27560
- theme: theme,
27561
27555
  color: textPrimary,
27562
27556
  errorColor: warningColor,
27563
27557
  placeholderColor: textFootnote,
@@ -27578,7 +27572,6 @@ function CreateChannel(_ref) {
27578
27572
  onBlur: checkURIRegexp,
27579
27573
  placeholder: 'chan12',
27580
27574
  error: !!wrongUri,
27581
- theme: theme,
27582
27575
  color: textPrimary,
27583
27576
  errorColor: warningColor,
27584
27577
  placeholderColor: textFootnote,
@@ -27682,7 +27675,6 @@ var DropDown = function DropDown(_ref) {
27682
27675
  watchToggleState = _ref.watchToggleState,
27683
27676
  height = _ref.height,
27684
27677
  children = _ref.children,
27685
- theme = _ref.theme,
27686
27678
  order = _ref.order,
27687
27679
  zIndex = _ref.zIndex;
27688
27680
  var _useColor = useColors(),
@@ -27735,7 +27727,6 @@ var DropDown = function DropDown(_ref) {
27735
27727
  }
27736
27728
  }, [dropDownState]);
27737
27729
  return /*#__PURE__*/React__default.createElement(DropDownContainer, {
27738
- theme: theme,
27739
27730
  order: order,
27740
27731
  margin: margin,
27741
27732
  className: 'dropdown-wrapper',
@@ -27765,7 +27756,6 @@ var DropDown = function DropDown(_ref) {
27765
27756
  var _templateObject$f;
27766
27757
  var CreateChannelButton = function CreateChannelButton(_ref) {
27767
27758
  var showSearch = _ref.showSearch,
27768
- theme = _ref.theme,
27769
27759
  uriPrefixOnCreateChannel = _ref.uriPrefixOnCreateChannel,
27770
27760
  createChannelIcon = _ref.createChannelIcon,
27771
27761
  newChannelIcon = _ref.newChannelIcon,
@@ -27797,7 +27787,6 @@ var CreateChannelButton = function CreateChannelButton(_ref) {
27797
27787
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(DropDown, {
27798
27788
  forceClose: showAddMemberPopup || !!showCreateChannel,
27799
27789
  position: 'center',
27800
- theme: theme,
27801
27790
  zIndex: '300',
27802
27791
  trigger: /*#__PURE__*/React__default.createElement(CreateDropdownButton, {
27803
27792
  hoverBackground: backgroundHovered,
@@ -28203,7 +28192,6 @@ var ChannelList = function ChannelList(_ref) {
28203
28192
  surface2 = _useColor[THEME_COLORS.SURFACE_2];
28204
28193
  var dispatch = useDispatch();
28205
28194
  var getFromContacts = getShowOnlyContactUsers();
28206
- var theme = useSelector(themeSelector);
28207
28195
  var channelListRef = useRef(null);
28208
28196
  var channelsScrollRef = useRef(null);
28209
28197
  var _useState = useState(''),
@@ -28447,7 +28435,6 @@ var ChannelList = function ChannelList(_ref) {
28447
28435
  })) : ChannelsTitle || /*#__PURE__*/React__default.createElement(ChatsTitle, {
28448
28436
  color: textPrimary
28449
28437
  }, "Chats"), showCreateChannelIcon && (CreateChannel || (/*#__PURE__*/React__default.createElement(CreateChannelButton, {
28450
- theme: theme,
28451
28438
  newChannelIcon: newChannelIcon,
28452
28439
  newGroupIcon: newGroupIcon,
28453
28440
  newChatIcon: newChatIcon,
@@ -28457,7 +28444,6 @@ var ChannelList = function ChannelList(_ref) {
28457
28444
  uriPrefixOnCreateChannel: uriPrefixOnCreateChannel
28458
28445
  })))), showSearch && searchChannelsPosition === 'bottom' && (/*#__PURE__*/React__default.createElement(ChannelSearch, {
28459
28446
  searchValue: searchValue,
28460
- theme: theme,
28461
28447
  width: channelSearchWidth,
28462
28448
  borderRadius: searchInputBorderRadius,
28463
28449
  handleSearchValueChange: handleSearchValueChange,
@@ -28478,7 +28464,6 @@ var ChannelList = function ChannelList(_ref) {
28478
28464
  setSelectedChannel: setSelectedChannel,
28479
28465
  key: channel.id
28480
28466
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28481
- theme: theme,
28482
28467
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28483
28468
  selectedChannelBackground: selectedChannelBackground,
28484
28469
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28516,7 +28501,6 @@ var ChannelList = function ChannelList(_ref) {
28516
28501
  setSelectedChannel: setSelectedChannel,
28517
28502
  key: channel.id
28518
28503
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28519
- theme: theme,
28520
28504
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28521
28505
  selectedChannelBackground: selectedChannelBackground,
28522
28506
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28555,7 +28539,6 @@ var ChannelList = function ChannelList(_ref) {
28555
28539
  setSelectedChannel: setSelectedChannel,
28556
28540
  key: contact.id
28557
28541
  })) : (/*#__PURE__*/React__default.createElement(ContactItem, {
28558
- theme: theme,
28559
28542
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28560
28543
  selectedChannelBackground: selectedChannelBackground,
28561
28544
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28586,7 +28569,6 @@ var ChannelList = function ChannelList(_ref) {
28586
28569
  setSelectedChannel: setSelectedChannel,
28587
28570
  key: channel.id
28588
28571
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28589
- theme: theme,
28590
28572
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28591
28573
  selectedChannelBackground: selectedChannelBackground,
28592
28574
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28637,7 +28619,6 @@ var ChannelList = function ChannelList(_ref) {
28637
28619
  setSelectedChannel: setSelectedChannel,
28638
28620
  key: channel.id
28639
28621
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28640
- theme: theme,
28641
28622
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28642
28623
  selectedChannelBackground: selectedChannelBackground,
28643
28624
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28678,7 +28659,6 @@ var ChannelList = function ChannelList(_ref) {
28678
28659
  setSelectedChannel: setSelectedChannel,
28679
28660
  key: channel.id
28680
28661
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28681
- theme: theme,
28682
28662
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28683
28663
  selectedChannelBackground: selectedChannelBackground,
28684
28664
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28716,7 +28696,6 @@ var ChannelList = function ChannelList(_ref) {
28716
28696
  setSelectedChannel: setSelectedChannel,
28717
28697
  key: channel.id
28718
28698
  })) : (/*#__PURE__*/React__default.createElement(Channel, {
28719
- theme: theme,
28720
28699
  selectedChannelLeftBorder: selectedChannelLeftBorder,
28721
28700
  selectedChannelBackground: selectedChannelBackground,
28722
28701
  selectedChannelBorderRadius: selectedChannelBorderRadius,
@@ -28982,7 +28961,6 @@ function ChatHeader(_ref) {
28982
28961
  var user = ChatClient.user;
28983
28962
  var getFromContacts = getShowOnlyContactUsers();
28984
28963
  var activeChannel = useSelector(activeChannelSelector);
28985
- var theme = useSelector(themeSelector);
28986
28964
  var showChannelDetails = getShowChannelDetails();
28987
28965
  var channelListHidden = useSelector(channelListHiddenSelector);
28988
28966
  var channelDetailsIsOpen = useSelector(channelInfoIsOpenSelector, shallowEqual);
@@ -29040,7 +29018,6 @@ function ChatHeader(_ref) {
29040
29018
  setDefaultAvatar: isDirectChannel
29041
29019
  }))), /*#__PURE__*/React__default.createElement(ChannelName, null, /*#__PURE__*/React__default.createElement(SectionHeader, {
29042
29020
  color: titleColor || textPrimary,
29043
- theme: theme,
29044
29021
  fontSize: titleFontSize,
29045
29022
  uppercase: directChannelUser && hideUserPresence && hideUserPresence(directChannelUser),
29046
29023
  lineHeight: titleLineHeight
@@ -29308,7 +29285,6 @@ function MessageDivider(_ref) {
29308
29285
  newMessagesSeparatorSpaceColor = _ref.newMessagesSeparatorSpaceColor,
29309
29286
  noMargin = _ref.noMargin,
29310
29287
  marginTop = _ref.marginTop,
29311
- theme = _ref.theme,
29312
29288
  marginBottom = _ref.marginBottom,
29313
29289
  chatBackgroundColor = _ref.chatBackgroundColor;
29314
29290
  var _useColor = useColors(),
@@ -29326,7 +29302,6 @@ function MessageDivider(_ref) {
29326
29302
  }, [textRef]);
29327
29303
  return /*#__PURE__*/React__default.createElement(Container$a, {
29328
29304
  className: unread ? 'unread' : 'divider',
29329
- theme: theme,
29330
29305
  marginTop: marginTop,
29331
29306
  dividerVisibility: !visibility || unread,
29332
29307
  dateDividerFontSize: dateDividerFontSize || newMessagesSeparatorFontSize,
@@ -30297,7 +30272,6 @@ var _templateObject$p, _templateObject2$m;
30297
30272
  function ConfirmPopup(_ref) {
30298
30273
  var title = _ref.title,
30299
30274
  description = _ref.description,
30300
- theme = _ref.theme,
30301
30275
  buttonText = _ref.buttonText,
30302
30276
  buttonTextColor = _ref.buttonTextColor,
30303
30277
  buttonBackground = _ref.buttonBackground,
@@ -30342,7 +30316,6 @@ function ConfirmPopup(_ref) {
30342
30316
  setInitialRender(false);
30343
30317
  }, []);
30344
30318
  return /*#__PURE__*/React__default.createElement(PopupContainer, null, /*#__PURE__*/React__default.createElement(Popup, {
30345
- theme: theme,
30346
30319
  backgroundColor: background,
30347
30320
  maxWidth: '520px',
30348
30321
  minWidth: '520px',
@@ -32214,15 +32187,16 @@ class EventEmitter {
32214
32187
  if (!this.listeners[event]) {
32215
32188
  this.listeners[event] = new Set();
32216
32189
  }
32217
- this.listeners[event].add(listener);
32218
32190
  if (options === null || options === void 0 ? void 0 : options.once) {
32219
- const unsubscribeOnce = () => {
32220
- this.un(event, unsubscribeOnce);
32221
- this.un(event, listener);
32191
+ // Create a wrapper that removes itself after being called once
32192
+ const onceWrapper = (...args) => {
32193
+ this.un(event, onceWrapper);
32194
+ listener(...args);
32222
32195
  };
32223
- this.on(event, unsubscribeOnce);
32224
- return unsubscribeOnce;
32196
+ this.listeners[event].add(onceWrapper);
32197
+ return () => this.un(event, onceWrapper);
32225
32198
  }
32199
+ this.listeners[event].add(listener);
32226
32200
  return () => this.un(event, listener);
32227
32201
  }
32228
32202
  /** Unsubscribe from an event */
@@ -32292,8 +32266,13 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
32292
32266
  function decode(audioData, sampleRate) {
32293
32267
  return __awaiter(this, void 0, void 0, function* () {
32294
32268
  const audioCtx = new AudioContext({ sampleRate });
32295
- const decode = audioCtx.decodeAudioData(audioData);
32296
- return decode.finally(() => audioCtx.close());
32269
+ try {
32270
+ return yield audioCtx.decodeAudioData(audioData);
32271
+ }
32272
+ finally {
32273
+ // Ensure AudioContext is always closed, even on synchronous errors
32274
+ audioCtx.close();
32275
+ }
32297
32276
  });
32298
32277
  }
32299
32278
  /** Normalize peaks to -1..1 */
@@ -32317,17 +32296,36 @@ function normalize(channelData) {
32317
32296
  }
32318
32297
  /** Create an audio buffer from pre-decoded audio data */
32319
32298
  function createBuffer(channelData, duration) {
32299
+ // Validate inputs
32300
+ if (!channelData || channelData.length === 0) {
32301
+ throw new Error('channelData must be a non-empty array');
32302
+ }
32303
+ if (duration <= 0) {
32304
+ throw new Error('duration must be greater than 0');
32305
+ }
32320
32306
  // If a single array of numbers is passed, make it an array of arrays
32321
32307
  if (typeof channelData[0] === 'number')
32322
32308
  channelData = [channelData];
32309
+ // Validate channel data after conversion
32310
+ if (!channelData[0] || channelData[0].length === 0) {
32311
+ throw new Error('channelData must contain non-empty channel arrays');
32312
+ }
32323
32313
  // Normalize to -1..1
32324
32314
  normalize(channelData);
32315
+ // Convert to Float32Array for consistency
32316
+ const float32Channels = channelData.map((channel) => channel instanceof Float32Array ? channel : Float32Array.from(channel));
32325
32317
  return {
32326
32318
  duration,
32327
- length: channelData[0].length,
32328
- sampleRate: channelData[0].length / duration,
32329
- numberOfChannels: channelData.length,
32330
- getChannelData: (i) => channelData === null || channelData === void 0 ? void 0 : channelData[i],
32319
+ length: float32Channels[0].length,
32320
+ sampleRate: float32Channels[0].length / duration,
32321
+ numberOfChannels: float32Channels.length,
32322
+ getChannelData: (i) => {
32323
+ const channel = float32Channels[i];
32324
+ if (!channel) {
32325
+ throw new Error(`Channel ${i} not found`);
32326
+ }
32327
+ return channel;
32328
+ },
32331
32329
  copyFromChannel: AudioBuffer.prototype.copyFromChannel,
32332
32330
  copyToChannel: AudioBuffer.prototype.copyToChannel,
32333
32331
  };
@@ -32396,28 +32394,26 @@ function watchProgress(response, progressCallback) {
32396
32394
  const contentLength = Number(response.headers.get('Content-Length')) || 0;
32397
32395
  let receivedLength = 0;
32398
32396
  // Process the data
32399
- const processChunk = (value) => __awaiter$1(this, void 0, void 0, function* () {
32397
+ const processChunk = (value) => {
32400
32398
  // Add to the received length
32401
32399
  receivedLength += (value === null || value === void 0 ? void 0 : value.length) || 0;
32402
32400
  const percentage = Math.round((receivedLength / contentLength) * 100);
32403
32401
  progressCallback(percentage);
32404
- });
32405
- const read = () => __awaiter$1(this, void 0, void 0, function* () {
32406
- let data;
32407
- try {
32408
- data = yield reader.read();
32409
- }
32410
- catch (_a) {
32411
- // Ignore errors because we can only handle the main response
32412
- return;
32413
- }
32414
- // Continue reading data until done
32415
- if (!data.done) {
32402
+ };
32403
+ // Use iteration instead of recursion to avoid stack issues
32404
+ try {
32405
+ while (true) {
32406
+ const data = yield reader.read();
32407
+ if (data.done) {
32408
+ break;
32409
+ }
32416
32410
  processChunk(data.value);
32417
- yield read();
32418
32411
  }
32419
- });
32420
- read();
32412
+ }
32413
+ catch (err) {
32414
+ // Ignore errors because we can only handle the main response
32415
+ console.warn('Progress tracking error:', err);
32416
+ }
32421
32417
  });
32422
32418
  }
32423
32419
  function fetchBlob(url, progressCallback, requestInit) {
@@ -32436,6 +32432,121 @@ const Fetcher = {
32436
32432
  fetchBlob,
32437
32433
  };
32438
32434
 
32435
+ /**
32436
+ * Reactive primitives for managing state in WaveSurfer
32437
+ *
32438
+ * This module provides signal-based reactivity similar to SolidJS signals.
32439
+ * Signals are reactive values that notify subscribers when they change.
32440
+ */
32441
+ /**
32442
+ * Create a reactive signal that notifies subscribers when its value changes
32443
+ *
32444
+ * @example
32445
+ * ```typescript
32446
+ * const count = signal(0)
32447
+ * count.subscribe(val => console.log('Count:', val))
32448
+ * count.set(5) // Logs: Count: 5
32449
+ * ```
32450
+ */
32451
+ function signal(initialValue) {
32452
+ let _value = initialValue;
32453
+ const subscribers = new Set();
32454
+ return {
32455
+ get value() {
32456
+ return _value;
32457
+ },
32458
+ set(newValue) {
32459
+ // Only update and notify if value actually changed
32460
+ if (!Object.is(_value, newValue)) {
32461
+ _value = newValue;
32462
+ subscribers.forEach((fn) => fn(_value));
32463
+ }
32464
+ },
32465
+ update(fn) {
32466
+ this.set(fn(_value));
32467
+ },
32468
+ subscribe(callback) {
32469
+ subscribers.add(callback);
32470
+ return () => subscribers.delete(callback);
32471
+ },
32472
+ };
32473
+ }
32474
+ /**
32475
+ * Create a computed value that automatically updates when its dependencies change
32476
+ *
32477
+ * @example
32478
+ * ```typescript
32479
+ * const count = signal(0)
32480
+ * const doubled = computed(() => count.value * 2, [count])
32481
+ * console.log(doubled.value) // 0
32482
+ * count.set(5)
32483
+ * console.log(doubled.value) // 10
32484
+ * ```
32485
+ */
32486
+ function computed(fn, dependencies) {
32487
+ const result = signal(fn());
32488
+ // Subscribe to all dependencies immediately
32489
+ // This ensures the computed value stays in sync even if no one is subscribed to it
32490
+ dependencies.forEach((dep) => dep.subscribe(() => {
32491
+ const newValue = fn();
32492
+ // Update the result signal, which will notify our subscribers if value changed
32493
+ if (!Object.is(result.value, newValue)) {
32494
+ result.set(newValue);
32495
+ }
32496
+ }));
32497
+ // Return a read-only signal that proxies the result
32498
+ return {
32499
+ get value() {
32500
+ return result.value;
32501
+ },
32502
+ subscribe(callback) {
32503
+ // Just subscribe to result changes
32504
+ return result.subscribe(callback);
32505
+ },
32506
+ };
32507
+ }
32508
+ /**
32509
+ * Run a side effect automatically when dependencies change
32510
+ *
32511
+ * @param fn - Effect function. Can return a cleanup function.
32512
+ * @param dependencies - Signals that trigger the effect when they change
32513
+ * @returns Unsubscribe function that stops the effect and runs cleanup
32514
+ *
32515
+ * @example
32516
+ * ```typescript
32517
+ * const count = signal(0)
32518
+ * effect(() => {
32519
+ * console.log('Count is:', count.value)
32520
+ * return () => console.log('Cleanup')
32521
+ * }, [count])
32522
+ * count.set(5) // Logs: Cleanup, Count is: 5
32523
+ * ```
32524
+ */
32525
+ function effect(fn, dependencies) {
32526
+ let cleanup;
32527
+ const run = () => {
32528
+ // Run cleanup from previous execution
32529
+ if (cleanup) {
32530
+ cleanup();
32531
+ cleanup = undefined;
32532
+ }
32533
+ // Run effect and capture new cleanup
32534
+ cleanup = fn();
32535
+ };
32536
+ // Subscribe to all dependencies
32537
+ const unsubscribes = dependencies.map((dep) => dep.subscribe(run));
32538
+ // Run effect immediately
32539
+ run();
32540
+ // Return function that unsubscribes and runs cleanup
32541
+ return () => {
32542
+ if (cleanup) {
32543
+ cleanup();
32544
+ cleanup = undefined;
32545
+ }
32546
+ unsubscribes.forEach((unsub) => unsub());
32547
+ };
32548
+ }
32549
+
32439
32550
  var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
32440
32551
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
32441
32552
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -32446,9 +32557,33 @@ var __awaiter$2 = (undefined && undefined.__awaiter) || function (thisArg, _argu
32446
32557
  });
32447
32558
  };
32448
32559
  class Player extends EventEmitter {
32560
+ // Expose reactive state as writable signals
32561
+ // These are writable to allow WaveSurfer to compose them into centralized state
32562
+ get isPlayingSignal() {
32563
+ return this._isPlaying;
32564
+ }
32565
+ get currentTimeSignal() {
32566
+ return this._currentTime;
32567
+ }
32568
+ get durationSignal() {
32569
+ return this._duration;
32570
+ }
32571
+ get volumeSignal() {
32572
+ return this._volume;
32573
+ }
32574
+ get mutedSignal() {
32575
+ return this._muted;
32576
+ }
32577
+ get playbackRateSignal() {
32578
+ return this._playbackRate;
32579
+ }
32580
+ get seekingSignal() {
32581
+ return this._seeking;
32582
+ }
32449
32583
  constructor(options) {
32450
32584
  super();
32451
32585
  this.isExternalMedia = false;
32586
+ this.reactiveMediaEventCleanups = [];
32452
32587
  if (options.media) {
32453
32588
  this.media = options.media;
32454
32589
  this.isExternalMedia = true;
@@ -32456,6 +32591,16 @@ class Player extends EventEmitter {
32456
32591
  else {
32457
32592
  this.media = document.createElement('audio');
32458
32593
  }
32594
+ // Initialize reactive state
32595
+ this._isPlaying = signal(false);
32596
+ this._currentTime = signal(0);
32597
+ this._duration = signal(0);
32598
+ this._volume = signal(this.media.volume);
32599
+ this._muted = signal(this.media.muted);
32600
+ this._playbackRate = signal(this.media.playbackRate || 1);
32601
+ this._seeking = signal(false);
32602
+ // Setup reactive media event handlers
32603
+ this.setupReactiveMediaEvents();
32459
32604
  // Controls
32460
32605
  if (options.mediaControls) {
32461
32606
  this.media.controls = true;
@@ -32473,6 +32618,48 @@ class Player extends EventEmitter {
32473
32618
  }, { once: true });
32474
32619
  }
32475
32620
  }
32621
+ /**
32622
+ * Setup reactive media event handlers that update signals
32623
+ * This bridges the imperative HTMLMediaElement API to reactive state
32624
+ */
32625
+ setupReactiveMediaEvents() {
32626
+ // Playing state
32627
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('play', () => {
32628
+ this._isPlaying.set(true);
32629
+ }));
32630
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('pause', () => {
32631
+ this._isPlaying.set(false);
32632
+ }));
32633
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('ended', () => {
32634
+ this._isPlaying.set(false);
32635
+ }));
32636
+ // Time tracking
32637
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('timeupdate', () => {
32638
+ this._currentTime.set(this.media.currentTime);
32639
+ }));
32640
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('durationchange', () => {
32641
+ this._duration.set(this.media.duration || 0);
32642
+ }));
32643
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('loadedmetadata', () => {
32644
+ this._duration.set(this.media.duration || 0);
32645
+ }));
32646
+ // Seeking state
32647
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('seeking', () => {
32648
+ this._seeking.set(true);
32649
+ }));
32650
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('seeked', () => {
32651
+ this._seeking.set(false);
32652
+ }));
32653
+ // Volume and muted
32654
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('volumechange', () => {
32655
+ this._volume.set(this.media.volume);
32656
+ this._muted.set(this.media.muted);
32657
+ }));
32658
+ // Playback rate
32659
+ this.reactiveMediaEventCleanups.push(this.onMediaEvent('ratechange', () => {
32660
+ this._playbackRate.set(this.media.playbackRate);
32661
+ }));
32662
+ }
32476
32663
  onMediaEvent(event, callback, options) {
32477
32664
  this.media.addEventListener(event, callback, options);
32478
32665
  return () => this.media.removeEventListener(event, callback, options);
@@ -32509,17 +32696,27 @@ class Player extends EventEmitter {
32509
32696
  }
32510
32697
  }
32511
32698
  destroy() {
32699
+ // Cleanup reactive media event listeners
32700
+ this.reactiveMediaEventCleanups.forEach((cleanup) => cleanup());
32701
+ this.reactiveMediaEventCleanups = [];
32512
32702
  if (this.isExternalMedia)
32513
32703
  return;
32514
32704
  this.media.pause();
32515
- this.media.remove();
32516
32705
  this.revokeSrc();
32517
32706
  this.media.removeAttribute('src');
32518
32707
  // Load resets the media element to its initial state
32519
32708
  this.media.load();
32709
+ // Remove from DOM after cleanup
32710
+ this.media.remove();
32520
32711
  }
32521
32712
  setMediaElement(element) {
32713
+ // Cleanup reactive event listeners from old media element
32714
+ this.reactiveMediaEventCleanups.forEach((cleanup) => cleanup());
32715
+ this.reactiveMediaEventCleanups = [];
32716
+ // Set new media element
32522
32717
  this.media = element;
32718
+ // Reinitialize reactive event listeners on new media element
32719
+ this.setupReactiveMediaEvents();
32523
32720
  }
32524
32721
  /** Start playing the audio */
32525
32722
  play() {
@@ -32599,23 +32796,312 @@ class Player extends EventEmitter {
32599
32796
  }
32600
32797
  }
32601
32798
 
32602
- function makeDraggable(element, onDrag, onStart, onEnd, threshold = 3, mouseButton = 0, touchDelay = 100) {
32603
- if (!element)
32604
- return () => void 0;
32799
+ const DEFAULT_HEIGHT = 128;
32800
+ const MAX_CANVAS_WIDTH = 8000;
32801
+ const MAX_NODES = 10;
32802
+ function clampToUnit(value) {
32803
+ if (value < 0)
32804
+ return 0;
32805
+ if (value > 1)
32806
+ return 1;
32807
+ return value;
32808
+ }
32809
+ function calculateBarRenderConfig({ width, height, length, options, pixelRatio, }) {
32810
+ const halfHeight = height / 2;
32811
+ const barWidth = options.barWidth ? options.barWidth * pixelRatio : 1;
32812
+ const barGap = options.barGap ? options.barGap * pixelRatio : options.barWidth ? barWidth / 2 : 0;
32813
+ const barRadius = options.barRadius || 0;
32814
+ const barMinHeight = options.barMinHeight ? options.barMinHeight * pixelRatio : 0;
32815
+ const spacing = barWidth + barGap || 1;
32816
+ const barIndexScale = length > 0 ? width / spacing / length : 0;
32817
+ return {
32818
+ halfHeight,
32819
+ barWidth,
32820
+ barGap,
32821
+ barRadius,
32822
+ barMinHeight,
32823
+ barIndexScale,
32824
+ barSpacing: spacing,
32825
+ };
32826
+ }
32827
+ function calculateBarHeights({ maxTop, maxBottom, halfHeight, vScale, barMinHeight = 0, barAlign, }) {
32828
+ let topHeight = Math.round(maxTop * halfHeight * vScale);
32829
+ const bottomHeight = Math.round(maxBottom * halfHeight * vScale);
32830
+ let totalHeight = topHeight + bottomHeight || 1;
32831
+ if (totalHeight < barMinHeight) {
32832
+ totalHeight = barMinHeight;
32833
+ if (!barAlign) {
32834
+ topHeight = totalHeight / 2;
32835
+ }
32836
+ }
32837
+ return { topHeight, totalHeight };
32838
+ }
32839
+ function resolveBarYPosition({ barAlign, halfHeight, topHeight, totalHeight, canvasHeight, }) {
32840
+ if (barAlign === 'top')
32841
+ return 0;
32842
+ if (barAlign === 'bottom')
32843
+ return canvasHeight - totalHeight;
32844
+ return halfHeight - topHeight;
32845
+ }
32846
+ function calculateBarSegments({ channelData, barIndexScale, barSpacing, barWidth, halfHeight, vScale, canvasHeight, barAlign, barMinHeight, }) {
32847
+ const topChannel = channelData[0] || [];
32848
+ const bottomChannel = channelData[1] || topChannel;
32849
+ const length = topChannel.length;
32850
+ const segments = [];
32851
+ let prevX = 0;
32852
+ let maxTop = 0;
32853
+ let maxBottom = 0;
32854
+ for (let i = 0; i <= length; i++) {
32855
+ const x = Math.round(i * barIndexScale);
32856
+ if (x > prevX) {
32857
+ const { topHeight, totalHeight } = calculateBarHeights({
32858
+ maxTop,
32859
+ maxBottom,
32860
+ halfHeight,
32861
+ vScale,
32862
+ barMinHeight,
32863
+ barAlign,
32864
+ });
32865
+ const y = resolveBarYPosition({
32866
+ barAlign,
32867
+ halfHeight,
32868
+ topHeight,
32869
+ totalHeight,
32870
+ canvasHeight,
32871
+ });
32872
+ segments.push({
32873
+ x: prevX * barSpacing,
32874
+ y,
32875
+ width: barWidth,
32876
+ height: totalHeight,
32877
+ });
32878
+ prevX = x;
32879
+ maxTop = 0;
32880
+ maxBottom = 0;
32881
+ }
32882
+ const magnitudeTop = Math.abs(topChannel[i] || 0);
32883
+ const magnitudeBottom = Math.abs(bottomChannel[i] || 0);
32884
+ if (magnitudeTop > maxTop)
32885
+ maxTop = magnitudeTop;
32886
+ if (magnitudeBottom > maxBottom)
32887
+ maxBottom = magnitudeBottom;
32888
+ }
32889
+ return segments;
32890
+ }
32891
+ function getRelativePointerPosition(rect, clientX, clientY) {
32892
+ const x = clientX - rect.left;
32893
+ const y = clientY - rect.top;
32894
+ const relativeX = x / rect.width;
32895
+ const relativeY = y / rect.height;
32896
+ return [relativeX, relativeY];
32897
+ }
32898
+ function resolveChannelHeight({ optionsHeight, optionsSplitChannels, parentHeight, numberOfChannels, defaultHeight = DEFAULT_HEIGHT, }) {
32899
+ if (optionsHeight == null)
32900
+ return defaultHeight;
32901
+ const numericHeight = Number(optionsHeight);
32902
+ if (!isNaN(numericHeight))
32903
+ return numericHeight;
32904
+ if (optionsHeight === 'auto') {
32905
+ const height = parentHeight || defaultHeight;
32906
+ if (optionsSplitChannels === null || optionsSplitChannels === void 0 ? void 0 : optionsSplitChannels.every((channel) => !channel.overlay)) {
32907
+ return height / numberOfChannels;
32908
+ }
32909
+ return height;
32910
+ }
32911
+ return defaultHeight;
32912
+ }
32913
+ function getPixelRatio(devicePixelRatio) {
32914
+ return Math.max(1, devicePixelRatio || 1);
32915
+ }
32916
+ function shouldRenderBars(options) {
32917
+ return Boolean(options.barWidth || options.barGap || options.barAlign);
32918
+ }
32919
+ function resolveColorValue(color, devicePixelRatio, canvasHeight) {
32920
+ if (!Array.isArray(color))
32921
+ return color || '';
32922
+ if (color.length === 0)
32923
+ return '#999';
32924
+ if (color.length < 2)
32925
+ return color[0] || '';
32926
+ const canvasElement = document.createElement('canvas');
32927
+ const ctx = canvasElement.getContext('2d');
32928
+ const gradientHeight = canvasHeight !== null && canvasHeight !== void 0 ? canvasHeight : canvasElement.height * devicePixelRatio;
32929
+ const gradient = ctx.createLinearGradient(0, 0, 0, gradientHeight || devicePixelRatio);
32930
+ const colorStopPercentage = 1 / (color.length - 1);
32931
+ color.forEach((value, index) => {
32932
+ gradient.addColorStop(index * colorStopPercentage, value);
32933
+ });
32934
+ return gradient;
32935
+ }
32936
+ function calculateWaveformLayout({ duration, minPxPerSec = 0, parentWidth, fillParent, pixelRatio, }) {
32937
+ const scrollWidth = Math.ceil(duration * minPxPerSec);
32938
+ const isScrollable = scrollWidth > parentWidth;
32939
+ const useParentWidth = Boolean(fillParent && !isScrollable);
32940
+ const width = (useParentWidth ? parentWidth : scrollWidth) * pixelRatio;
32941
+ return {
32942
+ scrollWidth,
32943
+ isScrollable,
32944
+ useParentWidth,
32945
+ width,
32946
+ };
32947
+ }
32948
+ function clampWidthToBarGrid(width, options) {
32949
+ if (!shouldRenderBars(options))
32950
+ return width;
32951
+ const barWidth = options.barWidth || 0.5;
32952
+ const barGap = options.barGap || barWidth / 2;
32953
+ const totalBarWidth = barWidth + barGap;
32954
+ if (totalBarWidth === 0)
32955
+ return width;
32956
+ return Math.floor(width / totalBarWidth) * totalBarWidth;
32957
+ }
32958
+ function calculateSingleCanvasWidth({ clientWidth, totalWidth, options, }) {
32959
+ const baseWidth = Math.min(MAX_CANVAS_WIDTH, clientWidth, totalWidth);
32960
+ return clampWidthToBarGrid(baseWidth, options);
32961
+ }
32962
+ function sliceChannelData({ channelData, offset, clampedWidth, totalWidth, }) {
32963
+ return channelData.map((channel) => {
32964
+ const start = Math.floor((offset / totalWidth) * channel.length);
32965
+ const end = Math.floor(((offset + clampedWidth) / totalWidth) * channel.length);
32966
+ return channel.slice(start, end);
32967
+ });
32968
+ }
32969
+ function shouldClearCanvases(currentNodeCount) {
32970
+ return currentNodeCount > MAX_NODES;
32971
+ }
32972
+ function getLazyRenderRange({ scrollLeft, totalWidth, numCanvases, }) {
32973
+ if (totalWidth === 0)
32974
+ return [0];
32975
+ const viewPosition = scrollLeft / totalWidth;
32976
+ const startCanvas = Math.floor(viewPosition * numCanvases);
32977
+ return [startCanvas - 1, startCanvas, startCanvas + 1];
32978
+ }
32979
+ function calculateVerticalScale({ channelData, barHeight, normalize, maxPeak, }) {
32980
+ var _a;
32981
+ const baseScale = barHeight || 1;
32982
+ if (!normalize)
32983
+ return baseScale;
32984
+ const firstChannel = channelData[0];
32985
+ if (!firstChannel || firstChannel.length === 0)
32986
+ return baseScale;
32987
+ // Use fixed max peak if provided, otherwise calculate from data
32988
+ let max = maxPeak !== null && maxPeak !== void 0 ? maxPeak : 0;
32989
+ if (!maxPeak) {
32990
+ for (let i = 0; i < firstChannel.length; i++) {
32991
+ const value = (_a = firstChannel[i]) !== null && _a !== void 0 ? _a : 0;
32992
+ const magnitude = Math.abs(value);
32993
+ if (magnitude > max)
32994
+ max = magnitude;
32995
+ }
32996
+ }
32997
+ if (!max)
32998
+ return baseScale;
32999
+ return baseScale / max;
33000
+ }
33001
+ function calculateLinePaths({ channelData, width, height, vScale, }) {
33002
+ const halfHeight = height / 2;
33003
+ const primaryChannel = channelData[0] || [];
33004
+ const secondaryChannel = channelData[1] || primaryChannel;
33005
+ const channels = [primaryChannel, secondaryChannel];
33006
+ return channels.map((channel, index) => {
33007
+ const length = channel.length;
33008
+ const hScale = length ? width / length : 0;
33009
+ const baseY = halfHeight;
33010
+ const direction = index === 0 ? -1 : 1;
33011
+ const path = [{ x: 0, y: baseY }];
33012
+ let prevX = 0;
33013
+ let max = 0;
33014
+ for (let i = 0; i <= length; i++) {
33015
+ const x = Math.round(i * hScale);
33016
+ if (x > prevX) {
33017
+ const heightDelta = Math.round(max * halfHeight * vScale) || 1;
33018
+ const y = baseY + heightDelta * direction;
33019
+ path.push({ x: prevX, y });
33020
+ prevX = x;
33021
+ max = 0;
33022
+ }
33023
+ const value = Math.abs(channel[i] || 0);
33024
+ if (value > max)
33025
+ max = value;
33026
+ }
33027
+ path.push({ x: prevX, y: baseY });
33028
+ return path;
33029
+ });
33030
+ }
33031
+ function roundToHalfAwayFromZero(value) {
33032
+ const scaled = value * 2;
33033
+ const rounded = scaled < 0 ? Math.floor(scaled) : Math.ceil(scaled);
33034
+ return rounded / 2;
33035
+ }
33036
+
33037
+ /**
33038
+ * Event stream utilities for converting DOM events to reactive signals
33039
+ *
33040
+ * These utilities allow composing event handling using reactive primitives.
33041
+ */
33042
+ /**
33043
+ * Cleanup a stream created with event stream utilities
33044
+ *
33045
+ * This removes event listeners and unsubscribes from sources.
33046
+ */
33047
+ function cleanup(stream) {
33048
+ const cleanupFn = stream._cleanup;
33049
+ if (typeof cleanupFn === 'function') {
33050
+ cleanupFn();
33051
+ }
33052
+ }
33053
+
33054
+ /**
33055
+ * Reactive drag stream utilities
33056
+ *
33057
+ * Provides declarative drag handling using reactive streams.
33058
+ * Automatically handles mouseup cleanup and supports constraints.
33059
+ */
33060
+ /**
33061
+ * Create a reactive drag stream from an element
33062
+ *
33063
+ * Emits drag events (start, move, end) as the user drags the element.
33064
+ * Automatically handles pointer capture, multi-touch prevention, and cleanup.
33065
+ *
33066
+ * @example
33067
+ * ```typescript
33068
+ * const dragSignal = createDragStream(element)
33069
+ *
33070
+ * effect(() => {
33071
+ * const drag = dragSignal.value
33072
+ * if (drag?.type === 'move') {
33073
+ * console.log('Dragging:', drag.deltaX, drag.deltaY)
33074
+ * }
33075
+ * }, [dragSignal])
33076
+ * ```
33077
+ *
33078
+ * @param element - Element to make draggable
33079
+ * @param options - Drag configuration options
33080
+ * @returns Signal emitting drag events and cleanup function
33081
+ */
33082
+ function createDragStream(element, options = {}) {
33083
+ const { threshold = 3, mouseButton = 0, touchDelay = 100 } = options;
33084
+ const dragSignal = signal(null);
33085
+ const activePointers = new Map();
32605
33086
  const isTouchDevice = matchMedia('(pointer: coarse)').matches;
32606
33087
  let unsubscribeDocument = () => void 0;
32607
33088
  const onPointerDown = (event) => {
32608
33089
  if (event.button !== mouseButton)
32609
33090
  return;
32610
- event.preventDefault();
32611
- event.stopPropagation();
33091
+ activePointers.set(event.pointerId, event);
33092
+ if (activePointers.size > 1) {
33093
+ return;
33094
+ }
32612
33095
  let startX = event.clientX;
32613
33096
  let startY = event.clientY;
32614
33097
  let isDragging = false;
32615
33098
  const touchStartTime = Date.now();
33099
+ const rect = element.getBoundingClientRect();
33100
+ const { left, top } = rect;
32616
33101
  const onPointerMove = (event) => {
32617
- event.preventDefault();
32618
- event.stopPropagation();
33102
+ if (event.defaultPrevented || activePointers.size > 1) {
33103
+ return;
33104
+ }
32619
33105
  if (isTouchDevice && Date.now() - touchStartTime < touchDelay)
32620
33106
  return;
32621
33107
  const x = event.clientX;
@@ -32623,29 +33109,45 @@ function makeDraggable(element, onDrag, onStart, onEnd, threshold = 3, mouseButt
32623
33109
  const dx = x - startX;
32624
33110
  const dy = y - startY;
32625
33111
  if (isDragging || Math.abs(dx) > threshold || Math.abs(dy) > threshold) {
32626
- const rect = element.getBoundingClientRect();
32627
- const { left, top } = rect;
33112
+ event.preventDefault();
33113
+ event.stopPropagation();
32628
33114
  if (!isDragging) {
32629
- onStart === null || onStart === void 0 ? void 0 : onStart(startX - left, startY - top);
33115
+ // Emit start event
33116
+ dragSignal.set({
33117
+ type: 'start',
33118
+ x: startX - left,
33119
+ y: startY - top,
33120
+ });
32630
33121
  isDragging = true;
32631
33122
  }
32632
- onDrag(dx, dy, x - left, y - top);
33123
+ // Emit move event
33124
+ dragSignal.set({
33125
+ type: 'move',
33126
+ x: x - left,
33127
+ y: y - top,
33128
+ deltaX: dx,
33129
+ deltaY: dy,
33130
+ });
32633
33131
  startX = x;
32634
33132
  startY = y;
32635
33133
  }
32636
33134
  };
32637
33135
  const onPointerUp = (event) => {
33136
+ activePointers.delete(event.pointerId);
32638
33137
  if (isDragging) {
32639
33138
  const x = event.clientX;
32640
33139
  const y = event.clientY;
32641
- const rect = element.getBoundingClientRect();
32642
- const { left, top } = rect;
32643
- onEnd === null || onEnd === void 0 ? void 0 : onEnd(x - left, y - top);
33140
+ // Emit end event
33141
+ dragSignal.set({
33142
+ type: 'end',
33143
+ x: x - left,
33144
+ y: y - top,
33145
+ });
32644
33146
  }
32645
33147
  unsubscribeDocument();
32646
33148
  };
32647
33149
  const onPointerLeave = (e) => {
32648
- // Listen to events only on the document and not on inner elements
33150
+ activePointers.delete(e.pointerId);
32649
33151
  if (!e.relatedTarget || e.relatedTarget === document.documentElement) {
32650
33152
  onPointerUp(e);
32651
33153
  }
@@ -32657,6 +33159,9 @@ function makeDraggable(element, onDrag, onStart, onEnd, threshold = 3, mouseButt
32657
33159
  }
32658
33160
  };
32659
33161
  const onTouchMove = (event) => {
33162
+ if (event.defaultPrevented || activePointers.size > 1) {
33163
+ return;
33164
+ }
32660
33165
  if (isDragging) {
32661
33166
  event.preventDefault();
32662
33167
  }
@@ -32679,9 +33184,114 @@ function makeDraggable(element, onDrag, onStart, onEnd, threshold = 3, mouseButt
32679
33184
  };
32680
33185
  };
32681
33186
  element.addEventListener('pointerdown', onPointerDown);
32682
- return () => {
33187
+ const cleanupFn = () => {
32683
33188
  unsubscribeDocument();
32684
33189
  element.removeEventListener('pointerdown', onPointerDown);
33190
+ activePointers.clear();
33191
+ cleanup(dragSignal);
33192
+ };
33193
+ return {
33194
+ signal: dragSignal,
33195
+ cleanup: cleanupFn,
33196
+ };
33197
+ }
33198
+
33199
+ /**
33200
+ * Reactive scroll stream utilities
33201
+ *
33202
+ * Provides declarative scroll handling using reactive streams.
33203
+ * Automatically handles scroll event optimization and cleanup.
33204
+ */
33205
+ // ============================================================================
33206
+ // Pure Scroll Calculation Functions
33207
+ // ============================================================================
33208
+ /**
33209
+ * Calculate visible percentages from scroll data
33210
+ * Pure function - no side effects
33211
+ *
33212
+ * @param scrollData - Current scroll dimensions
33213
+ * @returns Start and end positions as percentages (0-1)
33214
+ */
33215
+ function calculateScrollPercentages(scrollData) {
33216
+ const { scrollLeft, scrollWidth, clientWidth } = scrollData;
33217
+ if (scrollWidth === 0) {
33218
+ return { startX: 0, endX: 1 };
33219
+ }
33220
+ const startX = scrollLeft / scrollWidth;
33221
+ const endX = (scrollLeft + clientWidth) / scrollWidth;
33222
+ return {
33223
+ startX: Math.max(0, Math.min(1, startX)),
33224
+ endX: Math.max(0, Math.min(1, endX)),
33225
+ };
33226
+ }
33227
+ /**
33228
+ * Calculate scroll bounds in pixels
33229
+ * Pure function - no side effects
33230
+ *
33231
+ * @param scrollData - Current scroll dimensions
33232
+ * @returns Left and right scroll bounds in pixels
33233
+ */
33234
+ function calculateScrollBounds(scrollData) {
33235
+ return {
33236
+ left: scrollData.scrollLeft,
33237
+ right: scrollData.scrollLeft + scrollData.clientWidth,
33238
+ };
33239
+ }
33240
+ /**
33241
+ * Create a reactive scroll stream from an element
33242
+ *
33243
+ * Emits scroll data as the user scrolls the element.
33244
+ * Automatically computes derived values (percentages, bounds).
33245
+ *
33246
+ * @example
33247
+ * ```typescript
33248
+ * const scrollStream = createScrollStream(container)
33249
+ *
33250
+ * effect(() => {
33251
+ * const { startX, endX } = scrollStream.percentages.value
33252
+ * console.log('Visible:', startX, 'to', endX)
33253
+ * }, [scrollStream.percentages])
33254
+ *
33255
+ * scrollStream.cleanup()
33256
+ * ```
33257
+ *
33258
+ * @param element - Scrollable element
33259
+ * @returns Scroll stream with signals and cleanup
33260
+ */
33261
+ function createScrollStream(element) {
33262
+ // Create signals
33263
+ const scrollData = signal({
33264
+ scrollLeft: element.scrollLeft,
33265
+ scrollWidth: element.scrollWidth,
33266
+ clientWidth: element.clientWidth,
33267
+ });
33268
+ // Computed derived values
33269
+ const percentages = computed(() => {
33270
+ return calculateScrollPercentages(scrollData.value);
33271
+ }, [scrollData]);
33272
+ const bounds = computed(() => {
33273
+ return calculateScrollBounds(scrollData.value);
33274
+ }, [scrollData]);
33275
+ // Update scroll data on scroll event
33276
+ const onScroll = () => {
33277
+ scrollData.set({
33278
+ scrollLeft: element.scrollLeft,
33279
+ scrollWidth: element.scrollWidth,
33280
+ clientWidth: element.clientWidth,
33281
+ });
33282
+ };
33283
+ // Attach scroll listener
33284
+ element.addEventListener('scroll', onScroll, { passive: true });
33285
+ // Cleanup function
33286
+ const cleanupFn = () => {
33287
+ element.removeEventListener('scroll', onScroll);
33288
+ cleanup(scrollData);
33289
+ };
33290
+ return {
33291
+ scrollData,
33292
+ percentages,
33293
+ bounds,
33294
+ cleanup: cleanupFn,
32685
33295
  };
32686
33296
  }
32687
33297
 
@@ -32716,6 +33326,8 @@ class Renderer extends EventEmitter {
32716
33326
  this.isDragging = false;
32717
33327
  this.subscriptions = [];
32718
33328
  this.unsubscribeOnScroll = [];
33329
+ this.dragStream = null;
33330
+ this.scrollStream = null;
32719
33331
  this.subscriptions = [];
32720
33332
  this.options = options;
32721
33333
  const parent = this.parentFromOptionsContainer(options.container);
@@ -32747,35 +33359,30 @@ class Renderer extends EventEmitter {
32747
33359
  return parent;
32748
33360
  }
32749
33361
  initEvents() {
32750
- const getClickPosition = (e) => {
32751
- const rect = this.wrapper.getBoundingClientRect();
32752
- const x = e.clientX - rect.left;
32753
- const y = e.clientY - rect.top;
32754
- const relativeX = x / rect.width;
32755
- const relativeY = y / rect.height;
32756
- return [relativeX, relativeY];
32757
- };
32758
33362
  // Add a click listener
32759
33363
  this.wrapper.addEventListener('click', (e) => {
32760
- const [x, y] = getClickPosition(e);
33364
+ const rect = this.wrapper.getBoundingClientRect();
33365
+ const [x, y] = getRelativePointerPosition(rect, e.clientX, e.clientY);
32761
33366
  this.emit('click', x, y);
32762
33367
  });
32763
33368
  // Add a double click listener
32764
33369
  this.wrapper.addEventListener('dblclick', (e) => {
32765
- const [x, y] = getClickPosition(e);
33370
+ const rect = this.wrapper.getBoundingClientRect();
33371
+ const [x, y] = getRelativePointerPosition(rect, e.clientX, e.clientY);
32766
33372
  this.emit('dblclick', x, y);
32767
33373
  });
32768
33374
  // Drag
32769
33375
  if (this.options.dragToSeek === true || typeof this.options.dragToSeek === 'object') {
32770
33376
  this.initDrag();
32771
33377
  }
32772
- // Add a scroll listener
32773
- this.scrollContainer.addEventListener('scroll', () => {
32774
- const { scrollLeft, scrollWidth, clientWidth } = this.scrollContainer;
32775
- const startX = scrollLeft / scrollWidth;
32776
- const endX = (scrollLeft + clientWidth) / scrollWidth;
32777
- this.emit('scroll', startX, endX, scrollLeft, scrollLeft + clientWidth);
32778
- });
33378
+ // Add a scroll listener using reactive stream
33379
+ this.scrollStream = createScrollStream(this.scrollContainer);
33380
+ const unsubscribeScroll = effect(() => {
33381
+ const { startX, endX } = this.scrollStream.percentages.value;
33382
+ const { left, right } = this.scrollStream.bounds.value;
33383
+ this.emit('scroll', startX, endX, left, right);
33384
+ }, [this.scrollStream.percentages, this.scrollStream.bounds]);
33385
+ this.subscriptions.push(unsubscribeScroll);
32779
33386
  // Re-render the waveform on container resize
32780
33387
  if (typeof ResizeObserver === 'function') {
32781
33388
  const delay = this.createDelay(100);
@@ -32793,39 +33400,32 @@ class Renderer extends EventEmitter {
32793
33400
  return;
32794
33401
  this.lastContainerWidth = width;
32795
33402
  this.reRender();
33403
+ this.emit('resize');
32796
33404
  }
32797
33405
  initDrag() {
32798
- this.subscriptions.push(makeDraggable(this.wrapper,
32799
- // On drag
32800
- (_, __, x) => {
32801
- this.emit('drag', Math.max(0, Math.min(1, x / this.wrapper.getBoundingClientRect().width)));
32802
- },
32803
- // On start drag
32804
- (x) => {
32805
- this.isDragging = true;
32806
- this.emit('dragstart', Math.max(0, Math.min(1, x / this.wrapper.getBoundingClientRect().width)));
32807
- },
32808
- // On end drag
32809
- (x) => {
32810
- this.isDragging = false;
32811
- this.emit('dragend', Math.max(0, Math.min(1, x / this.wrapper.getBoundingClientRect().width)));
32812
- }));
32813
- }
32814
- getHeight(optionsHeight, optionsSplitChannel) {
32815
- var _a;
32816
- const defaultHeight = 128;
32817
- const numberOfChannels = ((_a = this.audioData) === null || _a === void 0 ? void 0 : _a.numberOfChannels) || 1;
32818
- if (optionsHeight == null)
32819
- return defaultHeight;
32820
- if (!isNaN(Number(optionsHeight)))
32821
- return Number(optionsHeight);
32822
- if (optionsHeight === 'auto') {
32823
- const height = this.parent.clientHeight || defaultHeight;
32824
- if (optionsSplitChannel === null || optionsSplitChannel === void 0 ? void 0 : optionsSplitChannel.every((channel) => !channel.overlay))
32825
- return height / numberOfChannels;
32826
- return height;
32827
- }
32828
- return defaultHeight;
33406
+ // Don't initialize drag if it's already set up
33407
+ if (this.dragStream)
33408
+ return;
33409
+ this.dragStream = createDragStream(this.wrapper);
33410
+ const unsubscribeDrag = effect(() => {
33411
+ const drag = this.dragStream.signal.value;
33412
+ if (!drag)
33413
+ return;
33414
+ const width = this.wrapper.getBoundingClientRect().width;
33415
+ const relX = clampToUnit(drag.x / width);
33416
+ if (drag.type === 'start') {
33417
+ this.isDragging = true;
33418
+ this.emit('dragstart', relX);
33419
+ }
33420
+ else if (drag.type === 'move') {
33421
+ this.emit('drag', relX);
33422
+ }
33423
+ else if (drag.type === 'end') {
33424
+ this.isDragging = false;
33425
+ this.emit('dragend', relX);
33426
+ }
33427
+ }, [this.dragStream.signal]);
33428
+ this.subscriptions.push(unsubscribeDrag);
32829
33429
  }
32830
33430
  initHtml() {
32831
33431
  const div = document.createElement('div');
@@ -32862,6 +33462,7 @@ class Renderer extends EventEmitter {
32862
33462
  }
32863
33463
  :host .canvases {
32864
33464
  min-height: ${this.getHeight(this.options.height, this.options.splitChannels)}px;
33465
+ pointer-events: none;
32865
33466
  }
32866
33467
  :host .canvases > div {
32867
33468
  position: relative;
@@ -32938,150 +33539,134 @@ class Renderer extends EventEmitter {
32938
33539
  this.setScroll(scrollStart);
32939
33540
  }
32940
33541
  destroy() {
32941
- var _a, _b;
33542
+ var _a;
32942
33543
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
32943
33544
  this.container.remove();
32944
- (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
32945
- (_b = this.unsubscribeOnScroll) === null || _b === void 0 ? void 0 : _b.forEach((unsubscribe) => unsubscribe());
33545
+ if (this.resizeObserver) {
33546
+ this.resizeObserver.disconnect();
33547
+ this.resizeObserver = null;
33548
+ }
33549
+ (_a = this.unsubscribeOnScroll) === null || _a === void 0 ? void 0 : _a.forEach((unsubscribe) => unsubscribe());
32946
33550
  this.unsubscribeOnScroll = [];
33551
+ if (this.dragStream) {
33552
+ this.dragStream.cleanup();
33553
+ this.dragStream = null;
33554
+ }
33555
+ if (this.scrollStream) {
33556
+ this.scrollStream.cleanup();
33557
+ this.scrollStream = null;
33558
+ }
32947
33559
  }
32948
33560
  createDelay(delayMs = 10) {
32949
33561
  let timeout;
32950
- let reject;
33562
+ let rejectFn;
32951
33563
  const onClear = () => {
32952
- if (timeout)
33564
+ if (timeout) {
32953
33565
  clearTimeout(timeout);
32954
- if (reject)
32955
- reject();
33566
+ timeout = undefined;
33567
+ }
33568
+ if (rejectFn) {
33569
+ rejectFn();
33570
+ rejectFn = undefined;
33571
+ }
32956
33572
  };
32957
33573
  this.timeouts.push(onClear);
32958
33574
  return () => {
32959
- return new Promise((resolveFn, rejectFn) => {
33575
+ return new Promise((resolve, reject) => {
33576
+ // Clear any pending delay
32960
33577
  onClear();
32961
- reject = rejectFn;
33578
+ // Store reject function for cleanup
33579
+ rejectFn = reject;
33580
+ // Set new timeout
32962
33581
  timeout = setTimeout(() => {
32963
33582
  timeout = undefined;
32964
- reject = undefined;
32965
- resolveFn();
33583
+ rejectFn = undefined;
33584
+ resolve();
32966
33585
  }, delayMs);
32967
33586
  });
32968
33587
  };
32969
33588
  }
32970
- // Convert array of color values to linear gradient
32971
- convertColorValues(color) {
32972
- if (!Array.isArray(color))
32973
- return color || '';
32974
- if (color.length < 2)
32975
- return color[0] || '';
32976
- const canvasElement = document.createElement('canvas');
32977
- const ctx = canvasElement.getContext('2d');
32978
- const gradientHeight = canvasElement.height * (window.devicePixelRatio || 1);
32979
- const gradient = ctx.createLinearGradient(0, 0, 0, gradientHeight);
32980
- const colorStopPercentage = 1 / (color.length - 1);
32981
- color.forEach((color, index) => {
32982
- const offset = index * colorStopPercentage;
32983
- gradient.addColorStop(offset, color);
33589
+ getHeight(optionsHeight, optionsSplitChannel) {
33590
+ var _a;
33591
+ const numberOfChannels = ((_a = this.audioData) === null || _a === void 0 ? void 0 : _a.numberOfChannels) || 1;
33592
+ return resolveChannelHeight({
33593
+ optionsHeight,
33594
+ optionsSplitChannels: optionsSplitChannel,
33595
+ parentHeight: this.parent.clientHeight,
33596
+ numberOfChannels,
33597
+ defaultHeight: DEFAULT_HEIGHT,
32984
33598
  });
32985
- return gradient;
33599
+ }
33600
+ convertColorValues(color, ctx) {
33601
+ return resolveColorValue(color, this.getPixelRatio(), ctx === null || ctx === void 0 ? void 0 : ctx.canvas.height);
32986
33602
  }
32987
33603
  getPixelRatio() {
32988
- return Math.max(1, window.devicePixelRatio || 1);
33604
+ return getPixelRatio(window.devicePixelRatio);
32989
33605
  }
32990
33606
  renderBarWaveform(channelData, options, ctx, vScale) {
32991
- const topChannel = channelData[0];
32992
- const bottomChannel = channelData[1] || channelData[0];
32993
- const length = topChannel.length;
32994
33607
  const { width, height } = ctx.canvas;
32995
- const halfHeight = height / 2;
32996
- const pixelRatio = this.getPixelRatio();
32997
- const barWidth = options.barWidth ? options.barWidth * pixelRatio : 1;
32998
- const barGap = options.barGap ? options.barGap * pixelRatio : options.barWidth ? barWidth / 2 : 0;
32999
- const barRadius = options.barRadius || 0;
33000
- const barIndexScale = width / (barWidth + barGap) / length;
33001
- const rectFn = barRadius && 'roundRect' in ctx ? 'roundRect' : 'rect';
33608
+ const { halfHeight, barWidth, barRadius, barIndexScale, barSpacing, barMinHeight } = calculateBarRenderConfig({
33609
+ width,
33610
+ height,
33611
+ length: (channelData[0] || []).length,
33612
+ options,
33613
+ pixelRatio: this.getPixelRatio(),
33614
+ });
33615
+ const segments = calculateBarSegments({
33616
+ channelData,
33617
+ barIndexScale,
33618
+ barSpacing,
33619
+ barWidth,
33620
+ halfHeight,
33621
+ vScale,
33622
+ canvasHeight: height,
33623
+ barAlign: options.barAlign,
33624
+ barMinHeight,
33625
+ });
33002
33626
  ctx.beginPath();
33003
- let prevX = 0;
33004
- let maxTop = 0;
33005
- let maxBottom = 0;
33006
- for (let i = 0; i <= length; i++) {
33007
- const x = Math.round(i * barIndexScale);
33008
- if (x > prevX) {
33009
- const topBarHeight = Math.round(maxTop * halfHeight * vScale);
33010
- const bottomBarHeight = Math.round(maxBottom * halfHeight * vScale);
33011
- const barHeight = topBarHeight + bottomBarHeight || 1;
33012
- // Vertical alignment
33013
- let y = halfHeight - topBarHeight;
33014
- if (options.barAlign === 'top') {
33015
- y = 0;
33016
- }
33017
- else if (options.barAlign === 'bottom') {
33018
- y = height - barHeight;
33019
- }
33020
- ctx[rectFn](prevX * (barWidth + barGap), y, barWidth, barHeight, barRadius);
33021
- prevX = x;
33022
- maxTop = 0;
33023
- maxBottom = 0;
33627
+ for (const segment of segments) {
33628
+ if (barRadius && 'roundRect' in ctx) {
33629
+ ctx.roundRect(segment.x, segment.y, segment.width, segment.height, barRadius);
33630
+ }
33631
+ else {
33632
+ ctx.rect(segment.x, segment.y, segment.width, segment.height);
33024
33633
  }
33025
- const magnitudeTop = Math.abs(topChannel[i] || 0);
33026
- const magnitudeBottom = Math.abs(bottomChannel[i] || 0);
33027
- if (magnitudeTop > maxTop)
33028
- maxTop = magnitudeTop;
33029
- if (magnitudeBottom > maxBottom)
33030
- maxBottom = magnitudeBottom;
33031
33634
  }
33032
33635
  ctx.fill();
33033
33636
  ctx.closePath();
33034
33637
  }
33035
33638
  renderLineWaveform(channelData, _options, ctx, vScale) {
33036
- const drawChannel = (index) => {
33037
- const channel = channelData[index] || channelData[0];
33038
- const length = channel.length;
33039
- const { height } = ctx.canvas;
33040
- const halfHeight = height / 2;
33041
- const hScale = ctx.canvas.width / length;
33042
- ctx.moveTo(0, halfHeight);
33043
- let prevX = 0;
33044
- let max = 0;
33045
- for (let i = 0; i <= length; i++) {
33046
- const x = Math.round(i * hScale);
33047
- if (x > prevX) {
33048
- const h = Math.round(max * halfHeight * vScale) || 1;
33049
- const y = halfHeight + h * (index === 0 ? -1 : 1);
33050
- ctx.lineTo(prevX, y);
33051
- prevX = x;
33052
- max = 0;
33053
- }
33054
- const value = Math.abs(channel[i] || 0);
33055
- if (value > max)
33056
- max = value;
33057
- }
33058
- ctx.lineTo(prevX, halfHeight);
33059
- };
33639
+ const { width, height } = ctx.canvas;
33640
+ const paths = calculateLinePaths({ channelData, width, height, vScale });
33060
33641
  ctx.beginPath();
33061
- drawChannel(0);
33062
- drawChannel(1);
33642
+ for (const path of paths) {
33643
+ if (!path.length)
33644
+ continue;
33645
+ ctx.moveTo(path[0].x, path[0].y);
33646
+ for (let i = 1; i < path.length; i++) {
33647
+ const point = path[i];
33648
+ ctx.lineTo(point.x, point.y);
33649
+ }
33650
+ }
33063
33651
  ctx.fill();
33064
33652
  ctx.closePath();
33065
33653
  }
33066
33654
  renderWaveform(channelData, options, ctx) {
33067
- ctx.fillStyle = this.convertColorValues(options.waveColor);
33068
- // Custom rendering function
33655
+ ctx.fillStyle = this.convertColorValues(options.waveColor, ctx);
33069
33656
  if (options.renderFunction) {
33070
33657
  options.renderFunction(channelData, ctx);
33071
33658
  return;
33072
33659
  }
33073
- // Vertical scaling
33074
- let vScale = options.barHeight || 1;
33075
- if (options.normalize) {
33076
- const max = Array.from(channelData[0]).reduce((max, value) => Math.max(max, Math.abs(value)), 0);
33077
- vScale = max ? 1 / max : 1;
33078
- }
33079
- // Render waveform as bars
33080
- if (options.barWidth || options.barGap || options.barAlign) {
33660
+ const vScale = calculateVerticalScale({
33661
+ channelData,
33662
+ barHeight: options.barHeight,
33663
+ normalize: options.normalize,
33664
+ maxPeak: options.maxPeak,
33665
+ });
33666
+ if (shouldRenderBars(options)) {
33081
33667
  this.renderBarWaveform(channelData, options, ctx, vScale);
33082
33668
  return;
33083
33669
  }
33084
- // Render waveform as a polyline
33085
33670
  this.renderLineWaveform(channelData, options, ctx, vScale);
33086
33671
  }
33087
33672
  renderSingleCanvas(data, options, width, height, offset, canvasContainer, progressContainer) {
@@ -33094,7 +33679,13 @@ class Renderer extends EventEmitter {
33094
33679
  canvas.style.left = `${Math.round(offset)}px`;
33095
33680
  canvasContainer.appendChild(canvas);
33096
33681
  const ctx = canvas.getContext('2d');
33097
- this.renderWaveform(data, options, ctx);
33682
+ if (options.renderFunction) {
33683
+ ctx.fillStyle = this.convertColorValues(options.waveColor, ctx);
33684
+ options.renderFunction(data, ctx);
33685
+ }
33686
+ else {
33687
+ this.renderWaveform(data, options, ctx);
33688
+ }
33098
33689
  // Draw a progress canvas
33099
33690
  if (canvas.width > 0 && canvas.height > 0) {
33100
33691
  const progressCanvas = canvas.cloneNode();
@@ -33102,7 +33693,7 @@ class Renderer extends EventEmitter {
33102
33693
  progressCtx.drawImage(canvas, 0, 0);
33103
33694
  // Set the composition method to draw only where the waveform is drawn
33104
33695
  progressCtx.globalCompositeOperation = 'source-in';
33105
- progressCtx.fillStyle = this.convertColorValues(options.progressColor);
33696
+ progressCtx.fillStyle = this.convertColorValues(options.progressColor, progressCtx);
33106
33697
  // This rectangle acts as a mask thanks to the composition method
33107
33698
  progressCtx.fillRect(0, 0, canvas.width, canvas.height);
33108
33699
  progressContainer.appendChild(progressCanvas);
@@ -33112,17 +33703,8 @@ class Renderer extends EventEmitter {
33112
33703
  const pixelRatio = this.getPixelRatio();
33113
33704
  const { clientWidth } = this.scrollContainer;
33114
33705
  const totalWidth = width / pixelRatio;
33115
- let singleCanvasWidth = Math.min(Renderer.MAX_CANVAS_WIDTH, clientWidth, totalWidth);
33706
+ const singleCanvasWidth = calculateSingleCanvasWidth({ clientWidth, totalWidth, options });
33116
33707
  let drawnIndexes = {};
33117
- // Adjust width to avoid gaps between canvases when using bars
33118
- if (options.barWidth || options.barGap) {
33119
- const barWidth = options.barWidth || 0.5;
33120
- const barGap = options.barGap || barWidth / 2;
33121
- const totalBarWidth = barWidth + barGap;
33122
- if (singleCanvasWidth % totalBarWidth !== 0) {
33123
- singleCanvasWidth = Math.floor(singleCanvasWidth / totalBarWidth) * totalBarWidth;
33124
- }
33125
- }
33126
33708
  // Nothing to render
33127
33709
  if (singleCanvasWidth === 0)
33128
33710
  return;
@@ -33136,24 +33718,15 @@ class Renderer extends EventEmitter {
33136
33718
  const offset = index * singleCanvasWidth;
33137
33719
  let clampedWidth = Math.min(totalWidth - offset, singleCanvasWidth);
33138
33720
  // Clamp the width to the bar grid to avoid empty canvases at the end
33139
- if (options.barWidth || options.barGap) {
33140
- const barWidth = options.barWidth || 0.5;
33141
- const barGap = options.barGap || barWidth / 2;
33142
- const totalBarWidth = barWidth + barGap;
33143
- clampedWidth = Math.floor(clampedWidth / totalBarWidth) * totalBarWidth;
33144
- }
33721
+ clampedWidth = clampWidthToBarGrid(clampedWidth, options);
33145
33722
  if (clampedWidth <= 0)
33146
33723
  return;
33147
- const data = channelData.map((channel) => {
33148
- const start = Math.floor((offset / totalWidth) * channel.length);
33149
- const end = Math.floor(((offset + clampedWidth) / totalWidth) * channel.length);
33150
- return channel.slice(start, end);
33151
- });
33724
+ const data = sliceChannelData({ channelData, offset, clampedWidth, totalWidth });
33152
33725
  this.renderSingleCanvas(data, options, clampedWidth, height, offset, canvasContainer, progressContainer);
33153
33726
  };
33154
33727
  // Clear canvases to avoid too many DOM nodes
33155
33728
  const clearCanvases = () => {
33156
- if (Object.keys(drawnIndexes).length > Renderer.MAX_NODES) {
33729
+ if (shouldClearCanvases(Object.keys(drawnIndexes).length)) {
33157
33730
  canvasContainer.innerHTML = '';
33158
33731
  progressContainer.innerHTML = '';
33159
33732
  drawnIndexes = {};
@@ -33169,21 +33742,18 @@ class Renderer extends EventEmitter {
33169
33742
  return;
33170
33743
  }
33171
33744
  // Lazy rendering
33172
- const viewPosition = this.scrollContainer.scrollLeft / totalWidth;
33173
- const startCanvas = Math.floor(viewPosition * numCanvases);
33174
- // Draw the canvases in the viewport first
33175
- draw(startCanvas - 1);
33176
- draw(startCanvas);
33177
- draw(startCanvas + 1);
33745
+ const initialRange = getLazyRenderRange({
33746
+ scrollLeft: this.scrollContainer.scrollLeft,
33747
+ totalWidth,
33748
+ numCanvases,
33749
+ });
33750
+ initialRange.forEach((index) => draw(index));
33178
33751
  // Subscribe to the scroll event to draw additional canvases
33179
33752
  if (numCanvases > 1) {
33180
33753
  const unsubscribe = this.on('scroll', () => {
33181
33754
  const { scrollLeft } = this.scrollContainer;
33182
- const canvasIndex = Math.floor((scrollLeft / totalWidth) * numCanvases);
33183
33755
  clearCanvases();
33184
- draw(canvasIndex - 1);
33185
- draw(canvasIndex);
33186
- draw(canvasIndex + 1);
33756
+ getLazyRenderRange({ scrollLeft, totalWidth, numCanvases }).forEach((index) => draw(index));
33187
33757
  });
33188
33758
  this.unsubscribeOnScroll.push(unsubscribe);
33189
33759
  }
@@ -33222,12 +33792,15 @@ class Renderer extends EventEmitter {
33222
33792
  // Determine the width of the waveform
33223
33793
  const pixelRatio = this.getPixelRatio();
33224
33794
  const parentWidth = this.scrollContainer.clientWidth;
33225
- const scrollWidth = Math.ceil(audioData.duration * (this.options.minPxPerSec || 0));
33795
+ const { scrollWidth, isScrollable, useParentWidth, width } = calculateWaveformLayout({
33796
+ duration: audioData.duration,
33797
+ minPxPerSec: this.options.minPxPerSec || 0,
33798
+ parentWidth,
33799
+ fillParent: this.options.fillParent,
33800
+ pixelRatio,
33801
+ });
33226
33802
  // Whether the container should scroll
33227
- this.isScrollable = scrollWidth > parentWidth;
33228
- const useParentWidth = this.options.fillParent && !this.isScrollable;
33229
- // Width of the waveform in pixels
33230
- const width = (useParentWidth ? parentWidth : scrollWidth) * pixelRatio;
33803
+ this.isScrollable = isScrollable;
33231
33804
  // Set the width of the wrapper
33232
33805
  this.wrapper.style.width = useParentWidth ? '100%' : `${scrollWidth}px`;
33233
33806
  // Set additional styles
@@ -33270,12 +33843,7 @@ class Renderer extends EventEmitter {
33270
33843
  // Adjust the scroll position so that the cursor stays in the same place
33271
33844
  if (this.isScrollable && scrollWidth !== this.scrollContainer.scrollWidth) {
33272
33845
  const { right: after } = this.progressWrapper.getBoundingClientRect();
33273
- let delta = after - before;
33274
- // to limit compounding floating-point drift
33275
- // we need to round to the half px furthest from 0
33276
- delta *= 2;
33277
- delta = delta < 0 ? Math.floor(delta) : Math.ceil(delta);
33278
- delta /= 2;
33846
+ const delta = roundToHalfAwayFromZero(after - before);
33279
33847
  this.scrollContainer.scrollLeft += delta;
33280
33848
  }
33281
33849
  }
@@ -33306,16 +33874,9 @@ class Renderer extends EventEmitter {
33306
33874
  // Keep the cursor centered when playing
33307
33875
  const center = progressWidth - scrollLeft - middle;
33308
33876
  if (isPlaying && this.options.autoCenter && center > 0) {
33309
- this.scrollContainer.scrollLeft += Math.min(center, 10);
33877
+ this.scrollContainer.scrollLeft += center;
33310
33878
  }
33311
33879
  }
33312
- // Emit the scroll event
33313
- {
33314
- const newScroll = this.scrollContainer.scrollLeft;
33315
- const startX = newScroll / scrollWidth;
33316
- const endX = (newScroll + clientWidth) / scrollWidth;
33317
- this.emit('scroll', startX, endX, newScroll, newScroll + clientWidth);
33318
- }
33319
33880
  }
33320
33881
  renderProgress(progress, isPlaying) {
33321
33882
  if (isNaN(progress))
@@ -33327,7 +33888,8 @@ class Renderer extends EventEmitter {
33327
33888
  this.cursor.style.transform = this.options.cursorWidth
33328
33889
  ? `translateX(-${progress * this.options.cursorWidth}px)`
33329
33890
  : '';
33330
- if (this.isScrollable && this.options.autoScroll) {
33891
+ // Only scroll if we have valid audio data to prevent race conditions during loading
33892
+ if (this.isScrollable && this.options.autoScroll && this.audioData && this.audioData.duration > 0) {
33331
33893
  this.scrollIntoView(progress, isPlaying);
33332
33894
  }
33333
33895
  }
@@ -33358,27 +33920,39 @@ class Renderer extends EventEmitter {
33358
33920
  });
33359
33921
  }
33360
33922
  }
33361
- Renderer.MAX_CANVAS_WIDTH = 8000;
33362
- Renderer.MAX_NODES = 10;
33363
33923
 
33364
33924
  class Timer extends EventEmitter {
33365
33925
  constructor() {
33366
33926
  super(...arguments);
33367
- this.unsubscribe = () => undefined;
33927
+ this.animationFrameId = null;
33928
+ this.isRunning = false;
33368
33929
  }
33369
33930
  start() {
33370
- this.unsubscribe = this.on('tick', () => {
33371
- requestAnimationFrame(() => {
33372
- this.emit('tick');
33373
- });
33374
- });
33375
- this.emit('tick');
33931
+ // Prevent multiple simultaneous loops
33932
+ if (this.isRunning)
33933
+ return;
33934
+ this.isRunning = true;
33935
+ const tick = () => {
33936
+ // Only continue if timer is still running
33937
+ if (!this.isRunning)
33938
+ return;
33939
+ this.emit('tick');
33940
+ // Schedule next frame
33941
+ this.animationFrameId = requestAnimationFrame(tick);
33942
+ };
33943
+ // Start the loop
33944
+ tick();
33376
33945
  }
33377
33946
  stop() {
33378
- this.unsubscribe();
33947
+ this.isRunning = false;
33948
+ // Cancel any pending animation frame
33949
+ if (this.animationFrameId !== null) {
33950
+ cancelAnimationFrame(this.animationFrameId);
33951
+ this.animationFrameId = null;
33952
+ }
33379
33953
  }
33380
33954
  destroy() {
33381
- this.unsubscribe();
33955
+ this.stop();
33382
33956
  }
33383
33957
  }
33384
33958
 
@@ -33393,6 +33967,10 @@ var __awaiter$4 = (undefined && undefined.__awaiter) || function (thisArg, _argu
33393
33967
  };
33394
33968
  /**
33395
33969
  * A Web Audio buffer player emulating the behavior of an HTML5 Audio element.
33970
+ *
33971
+ * Note: This class does not manage blob: URLs. If you pass a blob: URL to setSrc(),
33972
+ * you are responsible for revoking it when done. The Player class (player.ts) handles
33973
+ * blob URL lifecycle management automatically.
33396
33974
  */
33397
33975
  class WebAudioPlayer extends EventEmitter {
33398
33976
  constructor(audioContext = new AudioContext()) {
@@ -33453,14 +34031,21 @@ class WebAudioPlayer extends EventEmitter {
33453
34031
  this.emit('canplay');
33454
34032
  if (this.autoplay)
33455
34033
  this.play();
34034
+ })
34035
+ .catch((err) => {
34036
+ // Emit error for proper error handling
34037
+ console.error('WebAudioPlayer load error:', err);
33456
34038
  });
33457
34039
  }
33458
34040
  _play() {
33459
- var _a;
33460
34041
  if (!this.paused)
33461
34042
  return;
33462
34043
  this.paused = false;
33463
- (_a = this.bufferNode) === null || _a === void 0 ? void 0 : _a.disconnect();
34044
+ // Clean up old buffer node completely before creating new one
34045
+ if (this.bufferNode) {
34046
+ this.bufferNode.onended = null;
34047
+ this.bufferNode.disconnect();
34048
+ }
33464
34049
  this.bufferNode = this.audioContext.createBufferSource();
33465
34050
  if (this.buffer) {
33466
34051
  this.bufferNode.buffer = this.buffer;
@@ -33616,6 +34201,239 @@ class WebAudioPlayer extends EventEmitter {
33616
34201
  }
33617
34202
  }
33618
34203
 
34204
+ /**
34205
+ * Centralized reactive state for WaveSurfer
34206
+ *
34207
+ * This module provides a single source of truth for all WaveSurfer state.
34208
+ * State is managed using reactive signals that automatically notify subscribers.
34209
+ */
34210
+ /**
34211
+ * Create a new WaveSurfer state instance
34212
+ *
34213
+ * @param playerSignals - Optional signals from Player to compose with WaveSurfer state
34214
+ *
34215
+ * @example
34216
+ * ```typescript
34217
+ * // Without Player signals (standalone)
34218
+ * const { state, actions } = createWaveSurferState()
34219
+ *
34220
+ * // With Player signals (composed)
34221
+ * const { state, actions } = createWaveSurferState({
34222
+ * isPlaying: player.isPlayingSignal,
34223
+ * currentTime: player.currentTimeSignal,
34224
+ * // ...
34225
+ * })
34226
+ *
34227
+ * // Read state
34228
+ * console.log(state.isPlaying.value)
34229
+ *
34230
+ * // Update state
34231
+ * actions.setPlaying(true)
34232
+ *
34233
+ * // Subscribe to changes
34234
+ * state.isPlaying.subscribe(playing => {
34235
+ * console.log('Playing:', playing)
34236
+ * })
34237
+ * ```
34238
+ */
34239
+ function createWaveSurferState(playerSignals) {
34240
+ var _a, _b, _c, _d, _e, _f;
34241
+ // Use Player signals if provided, otherwise create new ones
34242
+ const currentTime = (_a = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.currentTime) !== null && _a !== void 0 ? _a : signal(0);
34243
+ const duration = (_b = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.duration) !== null && _b !== void 0 ? _b : signal(0);
34244
+ const isPlaying = (_c = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.isPlaying) !== null && _c !== void 0 ? _c : signal(false);
34245
+ const isSeeking = (_d = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.isSeeking) !== null && _d !== void 0 ? _d : signal(false);
34246
+ const volume = (_e = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.volume) !== null && _e !== void 0 ? _e : signal(1);
34247
+ const playbackRate = (_f = playerSignals === null || playerSignals === void 0 ? void 0 : playerSignals.playbackRate) !== null && _f !== void 0 ? _f : signal(1);
34248
+ // WaveSurfer-specific signals (not in Player)
34249
+ const audioBuffer = signal(null);
34250
+ const peaks = signal(null);
34251
+ const url = signal('');
34252
+ const zoom = signal(0);
34253
+ const scrollPosition = signal(0);
34254
+ // Computed values (derived state)
34255
+ const isPaused = computed(() => !isPlaying.value, [isPlaying]);
34256
+ const canPlay = computed(() => audioBuffer.value !== null, [audioBuffer]);
34257
+ const isReady = computed(() => {
34258
+ return canPlay.value && duration.value > 0;
34259
+ }, [canPlay, duration]);
34260
+ const progress = computed(() => currentTime.value, [currentTime]);
34261
+ const progressPercent = computed(() => {
34262
+ return duration.value > 0 ? currentTime.value / duration.value : 0;
34263
+ }, [currentTime, duration]);
34264
+ // Public read-only state
34265
+ const state = {
34266
+ currentTime,
34267
+ duration,
34268
+ isPlaying,
34269
+ isPaused,
34270
+ isSeeking,
34271
+ volume,
34272
+ playbackRate,
34273
+ audioBuffer,
34274
+ peaks,
34275
+ url,
34276
+ zoom,
34277
+ scrollPosition,
34278
+ canPlay,
34279
+ isReady,
34280
+ progress,
34281
+ progressPercent,
34282
+ };
34283
+ // Actions that modify state
34284
+ const actions = {
34285
+ setCurrentTime: (time) => {
34286
+ const clampedTime = Math.max(0, Math.min(duration.value || Infinity, time));
34287
+ currentTime.set(clampedTime);
34288
+ },
34289
+ setDuration: (d) => {
34290
+ duration.set(Math.max(0, d));
34291
+ },
34292
+ setPlaying: (playing) => {
34293
+ isPlaying.set(playing);
34294
+ },
34295
+ setSeeking: (seeking) => {
34296
+ isSeeking.set(seeking);
34297
+ },
34298
+ setVolume: (v) => {
34299
+ const clampedVolume = Math.max(0, Math.min(1, v));
34300
+ volume.set(clampedVolume);
34301
+ },
34302
+ setPlaybackRate: (rate) => {
34303
+ const clampedRate = Math.max(0.1, Math.min(16, rate));
34304
+ playbackRate.set(clampedRate);
34305
+ },
34306
+ setAudioBuffer: (buffer) => {
34307
+ audioBuffer.set(buffer);
34308
+ if (buffer) {
34309
+ duration.set(buffer.duration);
34310
+ }
34311
+ },
34312
+ setPeaks: (p) => {
34313
+ peaks.set(p);
34314
+ },
34315
+ setUrl: (u) => {
34316
+ url.set(u);
34317
+ },
34318
+ setZoom: (z) => {
34319
+ zoom.set(Math.max(0, z));
34320
+ },
34321
+ setScrollPosition: (pos) => {
34322
+ scrollPosition.set(Math.max(0, pos));
34323
+ },
34324
+ };
34325
+ return { state, actions };
34326
+ }
34327
+
34328
+ /**
34329
+ * State-driven event emission utilities
34330
+ *
34331
+ * Automatically emit events when reactive state changes.
34332
+ * Ensures events are always in sync with state and removes manual emit() calls.
34333
+ */
34334
+ /**
34335
+ * Setup automatic event emission from state changes
34336
+ *
34337
+ * This function subscribes to all relevant state signals and automatically
34338
+ * emits corresponding events when state changes. This ensures:
34339
+ * - Events are always in sync with state
34340
+ * - No manual emit() calls needed
34341
+ * - Can't forget to emit an event
34342
+ * - Clear event sources (state changes)
34343
+ *
34344
+ * @example
34345
+ * ```typescript
34346
+ * const { state } = createWaveSurferState()
34347
+ * const wavesurfer = new WaveSurfer()
34348
+ *
34349
+ * const cleanup = setupStateEventEmission(state, wavesurfer)
34350
+ *
34351
+ * // Now state changes automatically emit events
34352
+ * state.isPlaying.set(true) // → wavesurfer.emit('play')
34353
+ * ```
34354
+ *
34355
+ * @param state - Reactive state to observe
34356
+ * @param emitter - Event emitter to emit events on
34357
+ * @returns Cleanup function that removes all subscriptions
34358
+ */
34359
+ function setupStateEventEmission(state, emitter) {
34360
+ const cleanups = [];
34361
+ // ============================================================================
34362
+ // Play/Pause Events
34363
+ // ============================================================================
34364
+ // Emit play/pause events when playing state changes
34365
+ cleanups.push(effect(() => {
34366
+ const isPlaying = state.isPlaying.value;
34367
+ emitter.emit(isPlaying ? 'play' : 'pause');
34368
+ }, [state.isPlaying]));
34369
+ // ============================================================================
34370
+ // Time Update Events
34371
+ // ============================================================================
34372
+ // Emit timeupdate when current time changes
34373
+ cleanups.push(effect(() => {
34374
+ const currentTime = state.currentTime.value;
34375
+ emitter.emit('timeupdate', currentTime);
34376
+ // Also emit audioprocess when playing
34377
+ if (state.isPlaying.value) {
34378
+ emitter.emit('audioprocess', currentTime);
34379
+ }
34380
+ }, [state.currentTime, state.isPlaying]));
34381
+ // ============================================================================
34382
+ // Seeking Events
34383
+ // ============================================================================
34384
+ // Emit seeking event when seeking state changes to true
34385
+ cleanups.push(effect(() => {
34386
+ const isSeeking = state.isSeeking.value;
34387
+ if (isSeeking) {
34388
+ emitter.emit('seeking', state.currentTime.value);
34389
+ }
34390
+ }, [state.isSeeking, state.currentTime]));
34391
+ // ============================================================================
34392
+ // Ready Event
34393
+ // ============================================================================
34394
+ // Emit ready when state becomes ready
34395
+ let wasReady = false;
34396
+ cleanups.push(effect(() => {
34397
+ const isReady = state.isReady.value;
34398
+ if (isReady && !wasReady) {
34399
+ wasReady = true;
34400
+ emitter.emit('ready', state.duration.value);
34401
+ }
34402
+ }, [state.isReady, state.duration]));
34403
+ // ============================================================================
34404
+ // Finish Event
34405
+ // ============================================================================
34406
+ // Emit finish when playback ends (reached duration and stopped)
34407
+ let wasPlayingAtEnd = false;
34408
+ cleanups.push(effect(() => {
34409
+ const isPlaying = state.isPlaying.value;
34410
+ const currentTime = state.currentTime.value;
34411
+ const duration = state.duration.value;
34412
+ // Check if we're at the end
34413
+ const isAtEnd = duration > 0 && currentTime >= duration;
34414
+ // Emit finish when we were playing at end and now stopped
34415
+ if (wasPlayingAtEnd && !isPlaying && isAtEnd) {
34416
+ emitter.emit('finish');
34417
+ }
34418
+ // Track if we're playing at the end
34419
+ wasPlayingAtEnd = isPlaying && isAtEnd;
34420
+ }, [state.isPlaying, state.currentTime, state.duration]));
34421
+ // ============================================================================
34422
+ // Zoom Events
34423
+ // ============================================================================
34424
+ // Emit zoom when zoom level changes
34425
+ cleanups.push(effect(() => {
34426
+ const zoom = state.zoom.value;
34427
+ if (zoom > 0) {
34428
+ emitter.emit('zoom', zoom);
34429
+ }
34430
+ }, [state.zoom]));
34431
+ // Return cleanup function
34432
+ return () => {
34433
+ cleanups.forEach((cleanup) => cleanup());
34434
+ };
34435
+ }
34436
+
33619
34437
  var __awaiter$5 = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
33620
34438
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
33621
34439
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -33642,6 +34460,14 @@ class WaveSurfer extends Player {
33642
34460
  static create(options) {
33643
34461
  return new WaveSurfer(options);
33644
34462
  }
34463
+ /** Get the reactive state for advanced use cases */
34464
+ getState() {
34465
+ return this.wavesurferState;
34466
+ }
34467
+ /** Get the renderer instance for plugin access to reactive streams */
34468
+ getRenderer() {
34469
+ return this.renderer;
34470
+ }
33645
34471
  /** Create a new WaveSurfer instance */
33646
34472
  constructor(options) {
33647
34473
  const media = options.media ||
@@ -33658,13 +34484,27 @@ class WaveSurfer extends Player {
33658
34484
  this.subscriptions = [];
33659
34485
  this.mediaSubscriptions = [];
33660
34486
  this.abortController = null;
34487
+ this.reactiveCleanups = [];
33661
34488
  this.options = Object.assign({}, defaultOptions, options);
34489
+ // Initialize reactive state
34490
+ // Pass Player signals to compose them into WaveSurferState
34491
+ const { state, actions } = createWaveSurferState({
34492
+ isPlaying: this.isPlayingSignal,
34493
+ currentTime: this.currentTimeSignal,
34494
+ duration: this.durationSignal,
34495
+ volume: this.volumeSignal,
34496
+ playbackRate: this.playbackRateSignal,
34497
+ isSeeking: this.seekingSignal,
34498
+ });
34499
+ this.wavesurferState = state;
34500
+ this.wavesurferActions = actions;
33662
34501
  this.timer = new Timer();
33663
34502
  const audioElement = media ? undefined : this.getMediaElement();
33664
34503
  this.renderer = new Renderer(this.options, audioElement);
33665
34504
  this.initPlayerEvents();
33666
34505
  this.initRendererEvents();
33667
34506
  this.initTimerEvents();
34507
+ this.initReactiveState();
33668
34508
  this.initPlugins();
33669
34509
  // Read the initial URL before load has been called
33670
34510
  const initialUrl = this.options.url || this.getSrc() || '';
@@ -33677,7 +34517,10 @@ class WaveSurfer extends Player {
33677
34517
  if (initialUrl || (peaks && duration)) {
33678
34518
  // Swallow async errors because they cannot be caught from a constructor call.
33679
34519
  // Subscribe to the wavesurfer's error event to handle them.
33680
- this.load(initialUrl, peaks, duration).catch(() => null);
34520
+ this.load(initialUrl, peaks, duration).catch((err) => {
34521
+ // Emit error event for proper error handling
34522
+ this.emit('error', err instanceof Error ? err : new Error(String(err)));
34523
+ });
33681
34524
  }
33682
34525
  });
33683
34526
  }
@@ -33699,6 +34542,12 @@ class WaveSurfer extends Player {
33699
34542
  }
33700
34543
  }));
33701
34544
  }
34545
+ initReactiveState() {
34546
+ // Bridge reactive state to EventEmitter for backwards compatibility
34547
+ this.reactiveCleanups.push(setupStateEventEmission(this.wavesurferState, {
34548
+ emit: this.emit.bind(this),
34549
+ }));
34550
+ }
33702
34551
  initPlayerEvents() {
33703
34552
  if (this.isPlaying()) {
33704
34553
  this.emit('play');
@@ -33763,33 +34612,44 @@ class WaveSurfer extends Player {
33763
34612
  // DragEnd
33764
34613
  this.renderer.on('dragend', (relativeX) => {
33765
34614
  this.emit('dragend', relativeX);
34615
+ }),
34616
+ // Resize
34617
+ this.renderer.on('resize', () => {
34618
+ this.emit('resize');
33766
34619
  }));
33767
34620
  // Drag
33768
34621
  {
33769
34622
  let debounce;
33770
- this.subscriptions.push(this.renderer.on('drag', (relativeX) => {
34623
+ const unsubscribeDrag = this.renderer.on('drag', (relativeX) => {
34624
+ var _a;
33771
34625
  if (!this.options.interact)
33772
34626
  return;
33773
34627
  // Update the visual position
33774
34628
  this.renderer.renderProgress(relativeX);
33775
34629
  // Set the audio position with a debounce
33776
34630
  clearTimeout(debounce);
33777
- let debounceTime;
34631
+ let debounceTime = 0;
34632
+ const dragToSeek = this.options.dragToSeek;
33778
34633
  if (this.isPlaying()) {
33779
34634
  debounceTime = 0;
33780
34635
  }
33781
- else if (this.options.dragToSeek === true) {
34636
+ else if (dragToSeek === true) {
33782
34637
  debounceTime = 200;
33783
34638
  }
33784
- else if (typeof this.options.dragToSeek === 'object' && this.options.dragToSeek !== undefined) {
33785
- debounceTime = this.options.dragToSeek['debounceTime'];
34639
+ else if (dragToSeek && typeof dragToSeek === 'object') {
34640
+ debounceTime = (_a = dragToSeek.debounceTime) !== null && _a !== void 0 ? _a : 200;
33786
34641
  }
33787
34642
  debounce = setTimeout(() => {
33788
34643
  this.seekTo(relativeX);
33789
34644
  }, debounceTime);
33790
34645
  this.emit('interaction', relativeX * this.getDuration());
33791
34646
  this.emit('drag', relativeX);
33792
- }));
34647
+ });
34648
+ // Clear debounce timeout on destroy
34649
+ this.subscriptions.push(() => {
34650
+ clearTimeout(debounce);
34651
+ unsubscribeDrag();
34652
+ });
33793
34653
  }
33794
34654
  }
33795
34655
  initPlugins() {
@@ -33876,12 +34736,15 @@ class WaveSurfer extends Player {
33876
34736
  this.pause();
33877
34737
  this.decodedData = null;
33878
34738
  this.stopAtPosition = null;
34739
+ // Abort any ongoing fetch before starting a new one
34740
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
34741
+ this.abortController = null;
33879
34742
  // Fetch the entire audio as a blob if pre-decoded data is not provided
33880
34743
  if (!blob && !channelData) {
33881
34744
  const fetchParams = this.options.fetchParams || {};
33882
34745
  if (window.AbortController && !fetchParams.signal) {
33883
34746
  this.abortController = new AbortController();
33884
- fetchParams.signal = (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal;
34747
+ fetchParams.signal = this.abortController.signal;
33885
34748
  }
33886
34749
  const onProgress = (percentage) => this.emit('loading', percentage);
33887
34750
  blob = yield Fetcher.fetchBlob(url, onProgress, fetchParams);
@@ -33971,8 +34834,8 @@ class WaveSurfer extends Player {
33971
34834
  const channel = this.decodedData.getChannelData(i);
33972
34835
  const data = [];
33973
34836
  const sampleSize = channel.length / maxLength;
33974
- for (let i = 0; i < maxLength; i++) {
33975
- const sample = channel.slice(Math.floor(i * sampleSize), Math.ceil((i + 1) * sampleSize));
34837
+ for (let j = 0; j < maxLength; j++) {
34838
+ const sample = channel.slice(Math.floor(j * sampleSize), Math.ceil((j + 1) * sampleSize));
33976
34839
  let max = 0;
33977
34840
  for (let x = 0; x < sample.length; x++) {
33978
34841
  const n = sample[x];
@@ -34005,7 +34868,7 @@ class WaveSurfer extends Player {
34005
34868
  this.updateProgress(time);
34006
34869
  this.emit('timeupdate', time);
34007
34870
  }
34008
- /** Seek to a percentage of audio as [0..1] (0 = beginning, 1 = end) */
34871
+ /** Seek to a ratio of audio as [0..1] (0 = beginning, 1 = end) */
34009
34872
  seekTo(progress) {
34010
34873
  const time = this.getDuration() * progress;
34011
34874
  this.setTime(time);
@@ -34069,6 +34932,8 @@ class WaveSurfer extends Player {
34069
34932
  this.plugins.forEach((plugin) => plugin.destroy());
34070
34933
  this.subscriptions.forEach((unsubscribe) => unsubscribe());
34071
34934
  this.unsubscribePlayerEvents();
34935
+ this.reactiveCleanups.forEach((cleanup) => cleanup());
34936
+ this.reactiveCleanups = [];
34072
34937
  this.timer.destroy();
34073
34938
  this.renderer.destroy();
34074
34939
  super.destroy();
@@ -35251,7 +36116,6 @@ var Attachment = function Attachment(_ref) {
35251
36116
  })), sizeProgress && !isRepliedMessage && (/*#__PURE__*/React__default.createElement(SizeProgress, {
35252
36117
  color: textOnPrimary
35253
36118
  }, bytesToSize(sizeProgress.loaded, 1), " / ", bytesToSize(sizeProgress.total, 1)))))))) : null, /*#__PURE__*/React__default.createElement(VideoPreview, {
35254
- theme: theme,
35255
36119
  width: isRepliedMessage ? '40px' : isDetailsView ? '100%' : (renderWidth || videoAttachmentMaxWidth || 420) + "px",
35256
36120
  height: isRepliedMessage ? '40px' : isDetailsView ? '100%' : (renderHeight || videoAttachmentMaxHeight || 240) + "px",
35257
36121
  file: attachment,
@@ -35287,7 +36151,11 @@ var Attachment = function Attachment(_ref) {
35287
36151
  channelId: channelId,
35288
36152
  incoming: incoming,
35289
36153
  viewOnce: viewOnce,
35290
- setViewOnceVoiceModalOpen: setViewOnceVoiceModalOpen
36154
+ setViewOnceVoiceModalOpen: viewOnce ? function () {
36155
+ if (connectionStatus === CONNECTION_STATUS.CONNECTED) {
36156
+ setViewOnceVoiceModalOpen(true);
36157
+ }
36158
+ } : undefined
35291
36159
  })) : attachment.type === attachmentTypes.link ? null : (
35292
36160
  /*#__PURE__*/
35293
36161
  React__default.createElement(AttachmentFile$1, {
@@ -35572,7 +36440,7 @@ var RepliedMessage = function RepliedMessage(_ref) {
35572
36440
  }) : parentNotLinkAttachment && (message.parentMessage.attachments[0].type === attachmentTypes.image ? 'Photo' : message.parentMessage.attachments[0].type === attachmentTypes.video ? 'Video' : message.parentMessage.attachments[0].type === attachmentTypes.voice ? ' Voice' : 'File'))));
35573
36441
  };
35574
36442
  var RepliedMessage$1 = /*#__PURE__*/React__default.memo(RepliedMessage, function (prevProps, nextProps) {
35575
- return prevProps.theme === nextProps.theme && prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.selectionIsActive === nextProps.selectionIsActive && prevProps.contactsMap === nextProps.contactsMap;
36443
+ return prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.selectionIsActive === nextProps.selectionIsActive && prevProps.contactsMap === nextProps.contactsMap;
35576
36444
  });
35577
36445
  var ReplyMessageContainer = styled.div(_templateObject$z || (_templateObject$z = _taggedTemplateLiteralLoose(["\n display: flex;\n border-left: 2px solid ", ";\n padding: 4px 6px;\n position: relative;\n //margin: ", ";\n margin: ", ";\n background-color: ", ";\n border-radius: 0 4px 4px 0;\n margin-top: ", ";\n cursor: pointer;\n"])), function (props) {
35578
36446
  return props.leftBorderColor || '#b8b9c2';
@@ -37696,7 +38564,6 @@ var MessageBody = function MessageBody(_ref) {
37696
38564
  fixEmojiCategoriesTitleOnTop = _ref.fixEmojiCategoriesTitleOnTop,
37697
38565
  selectedMessagesMap = _ref.selectedMessagesMap,
37698
38566
  contactsMap = _ref.contactsMap,
37699
- theme = _ref.theme,
37700
38567
  messageTextFontSize = _ref.messageTextFontSize,
37701
38568
  messageTextLineHeight = _ref.messageTextLineHeight,
37702
38569
  handleToggleForwardMessagePopup = _ref.handleToggleForwardMessagePopup,
@@ -38061,7 +38928,6 @@ var MessageBody = function MessageBody(_ref) {
38061
38928
  infoIconOrder: infoIconOrder
38062
38929
  }))), message.parentMessage && message.parentMessage.id && !isThreadMessage && (/*#__PURE__*/React__default.createElement(RepliedMessage$1, {
38063
38930
  message: message,
38064
- theme: theme,
38065
38931
  isPendingMessage: isPendingMessage,
38066
38932
  handleScrollToRepliedMessage: handleScrollToRepliedMessage,
38067
38933
  ownMessageOnRightSide: ownMessageOnRightSide,
@@ -38091,7 +38957,6 @@ var MessageBody = function MessageBody(_ref) {
38091
38957
  leftPadding: message.incoming ? (incomingMessageStyles === null || incomingMessageStyles === void 0 ? void 0 : incomingMessageStyles.background) !== 'inherit' : (outgoingMessageStyles === null || outgoingMessageStyles === void 0 ? void 0 : outgoingMessageStyles.background) !== 'inherit',
38092
38958
  color: accentColor
38093
38959
  }, /*#__PURE__*/React__default.createElement(SvgForward, null), "Forwarded message")), /*#__PURE__*/React__default.createElement(MessageText, {
38094
- theme: theme,
38095
38960
  draggable: false,
38096
38961
  color: textPrimary,
38097
38962
  fontSize: messageTextFontSize,
@@ -38269,7 +39134,7 @@ var MessageBody = function MessageBody(_ref) {
38269
39134
  };
38270
39135
  var MessageBody$1 = /*#__PURE__*/React__default.memo(MessageBody, function (prevProps, nextProps) {
38271
39136
  var _prevProps$ogMetadata, _nextProps$ogMetadata, _prevProps$ogMetadata2, _nextProps$ogMetadata2, _prevProps$ogMetadata3, _nextProps$ogMetadata3, _prevProps$ogMetadata4, _nextProps$ogMetadata4, _prevProps$ogMetadata5, _nextProps$ogMetadata5, _prevProps$ogMetadata6, _nextProps$ogMetadata6;
38272
- return !!(prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.prevMessage === nextProps.prevMessage && prevProps.nextMessage === nextProps.nextMessage && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.contactsMap === nextProps.contactsMap && prevProps.connectionStatus === nextProps.connectionStatus && prevProps.openedMessageMenuId === nextProps.openedMessageMenuId && prevProps.ownMessageOnRightSide === nextProps.ownMessageOnRightSide && prevProps.showSenderNameOnDirectChannel === nextProps.showSenderNameOnDirectChannel && prevProps.showSenderNameOnGroupChannel === nextProps.showSenderNameOnGroupChannel && prevProps.showSenderNameOnOwnMessages === nextProps.showSenderNameOnOwnMessages && prevProps.messageStatusAndTimePosition === nextProps.messageStatusAndTimePosition && prevProps.messageStatusDisplayingType === nextProps.messageStatusDisplayingType && prevProps.outgoingMessageStyles === nextProps.outgoingMessageStyles && prevProps.incomingMessageStyles === nextProps.incomingMessageStyles && prevProps.ownRepliedMessageBackground === nextProps.ownRepliedMessageBackground && prevProps.incomingRepliedMessageBackground === nextProps.incomingRepliedMessageBackground && prevProps.showMessageStatus === nextProps.showMessageStatus && prevProps.showMessageTimeAndStatusOnlyOnHover === nextProps.showMessageTimeAndStatusOnlyOnHover && prevProps.showMessageTime === nextProps.showMessageTime && prevProps.showMessageStatusForEachMessage === nextProps.showMessageStatusForEachMessage && prevProps.showMessageTimeForEachMessage === nextProps.showMessageTimeForEachMessage && prevProps.messageReaction === nextProps.messageReaction && prevProps.editMessage === nextProps.editMessage && prevProps.copyMessage === nextProps.copyMessage && prevProps.replyMessage === nextProps.replyMessage && prevProps.replyMessageInThread === nextProps.replyMessageInThread && prevProps.forwardMessage === nextProps.forwardMessage && prevProps.deleteMessage === nextProps.deleteMessage && prevProps.selectMessage === nextProps.selectMessage && prevProps.allowEditDeleteIncomingMessage === nextProps.allowEditDeleteIncomingMessage && prevProps.reportMessage === nextProps.reportMessage && prevProps.reactionIcon === nextProps.reactionIcon && prevProps.editIcon === nextProps.editIcon && prevProps.copyIcon === nextProps.copyIcon && prevProps.replyIcon === nextProps.replyIcon && prevProps.replyInThreadIcon === nextProps.replyInThreadIcon && prevProps.forwardIcon === nextProps.forwardIcon && prevProps.deleteIcon === nextProps.deleteIcon && prevProps.selectIcon === nextProps.selectIcon && prevProps.starIcon === nextProps.starIcon && prevProps.staredIcon === nextProps.staredIcon && prevProps.reportIcon === nextProps.reportIcon && prevProps.fixEmojiCategoriesTitleOnTop === nextProps.fixEmojiCategoriesTitleOnTop && prevProps.emojisCategoryIconsPosition === nextProps.emojisCategoryIconsPosition && prevProps.emojisContainerBorderRadius === nextProps.emojisContainerBorderRadius && prevProps.reactionIconOrder === nextProps.reactionIconOrder && prevProps.editIconOrder === nextProps.editIconOrder && prevProps.copyIconOrder === nextProps.copyIconOrder && prevProps.replyIconOrder === nextProps.replyIconOrder && prevProps.replyInThreadIconOrder === nextProps.replyInThreadIconOrder && prevProps.forwardIconOrder === nextProps.forwardIconOrder && prevProps.deleteIconOrder === nextProps.deleteIconOrder && prevProps.selectIconOrder === nextProps.selectIconOrder && prevProps.starIconOrder === nextProps.starIconOrder && prevProps.reportIconOrder === nextProps.reportIconOrder && prevProps.reactionIconTooltipText === nextProps.reactionIconTooltipText && prevProps.editIconTooltipText === nextProps.editIconTooltipText && prevProps.copyIconTooltipText === nextProps.copyIconTooltipText && prevProps.replyIconTooltipText === nextProps.replyIconTooltipText && prevProps.replyInThreadIconTooltipText === nextProps.replyInThreadIconTooltipText && prevProps.forwardIconTooltipText === nextProps.forwardIconTooltipText && prevProps.deleteIconTooltipText === nextProps.deleteIconTooltipText && prevProps.selectIconTooltipText === nextProps.selectIconTooltipText && prevProps.starIconTooltipText === nextProps.starIconTooltipText && prevProps.reportIconTooltipText === nextProps.reportIconTooltipText && prevProps.messageActionIconsColor === nextProps.messageActionIconsColor && prevProps.inlineReactionIcon === nextProps.inlineReactionIcon && prevProps.messageStatusSize === nextProps.messageStatusSize && prevProps.messageStatusColor === nextProps.messageStatusColor && prevProps.messageReadStatusColor === nextProps.messageReadStatusColor && prevProps.messageStateFontSize === nextProps.messageStateFontSize && prevProps.messageStateColor === nextProps.messageStateColor && prevProps.messageTimeFontSize === nextProps.messageTimeFontSize && prevProps.messageTimeColor === nextProps.messageTimeColor && prevProps.messageStatusAndTimeLineHeight === nextProps.messageStatusAndTimeLineHeight && prevProps.fileAttachmentsBoxWidth === nextProps.fileAttachmentsBoxWidth && prevProps.fileAttachmentsBoxBackground === nextProps.fileAttachmentsBoxBackground && prevProps.fileAttachmentsBoxBorder === nextProps.fileAttachmentsBoxBorder && prevProps.fileAttachmentsTitleColor === nextProps.fileAttachmentsTitleColor && prevProps.fileAttachmentsSizeColor === nextProps.fileAttachmentsSizeColor && prevProps.fileAttachmentsIcon === nextProps.fileAttachmentsIcon && prevProps.imageAttachmentMaxWidth === nextProps.imageAttachmentMaxWidth && prevProps.imageAttachmentMaxHeight === nextProps.imageAttachmentMaxHeight && prevProps.videoAttachmentMaxWidth === nextProps.videoAttachmentMaxWidth && prevProps.videoAttachmentMaxHeight === nextProps.videoAttachmentMaxHeight && prevProps.theme === nextProps.theme && prevProps.messageTextFontSize === nextProps.messageTextFontSize && prevProps.messageTextLineHeight === nextProps.messageTextLineHeight && prevProps.messageActionsShow === nextProps.messageActionsShow && prevProps.emojisPopupOpen === nextProps.emojisPopupOpen && prevProps.emojisPopupPosition === nextProps.emojisPopupPosition && prevProps.frequentlyEmojisOpen === nextProps.frequentlyEmojisOpen && (((_prevProps$ogMetadata = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata === void 0 ? void 0 : _prevProps$ogMetadata.ogLayoutOrder) || 'og-first') === (((_nextProps$ogMetadata = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata === void 0 ? void 0 : _nextProps$ogMetadata.ogLayoutOrder) || 'og-first') && ((_prevProps$ogMetadata2 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata2 === void 0 ? void 0 : _prevProps$ogMetadata2.ogShowUrl) === ((_nextProps$ogMetadata2 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata2 === void 0 ? void 0 : _nextProps$ogMetadata2.ogShowUrl) && ((_prevProps$ogMetadata3 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata3 === void 0 ? void 0 : _prevProps$ogMetadata3.ogShowTitle) === ((_nextProps$ogMetadata3 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata3 === void 0 ? void 0 : _nextProps$ogMetadata3.ogShowTitle) && ((_prevProps$ogMetadata4 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata4 === void 0 ? void 0 : _prevProps$ogMetadata4.ogShowDescription) === ((_nextProps$ogMetadata4 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata4 === void 0 ? void 0 : _nextProps$ogMetadata4.ogShowDescription) && ((_prevProps$ogMetadata5 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata5 === void 0 ? void 0 : _prevProps$ogMetadata5.ogShowFavicon) === ((_nextProps$ogMetadata5 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata5 === void 0 ? void 0 : _nextProps$ogMetadata5.ogShowFavicon) && ((_prevProps$ogMetadata6 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata6 === void 0 ? void 0 : _prevProps$ogMetadata6.order) === ((_nextProps$ogMetadata6 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata6 === void 0 ? void 0 : _nextProps$ogMetadata6.order) && prevProps.collapsedCharacterLimit === nextProps.collapsedCharacterLimit);
39137
+ return !!(prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.prevMessage === nextProps.prevMessage && prevProps.nextMessage === nextProps.nextMessage && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.contactsMap === nextProps.contactsMap && prevProps.connectionStatus === nextProps.connectionStatus && prevProps.openedMessageMenuId === nextProps.openedMessageMenuId && prevProps.ownMessageOnRightSide === nextProps.ownMessageOnRightSide && prevProps.showSenderNameOnDirectChannel === nextProps.showSenderNameOnDirectChannel && prevProps.showSenderNameOnGroupChannel === nextProps.showSenderNameOnGroupChannel && prevProps.showSenderNameOnOwnMessages === nextProps.showSenderNameOnOwnMessages && prevProps.messageStatusAndTimePosition === nextProps.messageStatusAndTimePosition && prevProps.messageStatusDisplayingType === nextProps.messageStatusDisplayingType && prevProps.outgoingMessageStyles === nextProps.outgoingMessageStyles && prevProps.incomingMessageStyles === nextProps.incomingMessageStyles && prevProps.ownRepliedMessageBackground === nextProps.ownRepliedMessageBackground && prevProps.incomingRepliedMessageBackground === nextProps.incomingRepliedMessageBackground && prevProps.showMessageStatus === nextProps.showMessageStatus && prevProps.showMessageTimeAndStatusOnlyOnHover === nextProps.showMessageTimeAndStatusOnlyOnHover && prevProps.showMessageTime === nextProps.showMessageTime && prevProps.showMessageStatusForEachMessage === nextProps.showMessageStatusForEachMessage && prevProps.showMessageTimeForEachMessage === nextProps.showMessageTimeForEachMessage && prevProps.messageReaction === nextProps.messageReaction && prevProps.editMessage === nextProps.editMessage && prevProps.copyMessage === nextProps.copyMessage && prevProps.replyMessage === nextProps.replyMessage && prevProps.replyMessageInThread === nextProps.replyMessageInThread && prevProps.forwardMessage === nextProps.forwardMessage && prevProps.deleteMessage === nextProps.deleteMessage && prevProps.selectMessage === nextProps.selectMessage && prevProps.allowEditDeleteIncomingMessage === nextProps.allowEditDeleteIncomingMessage && prevProps.reportMessage === nextProps.reportMessage && prevProps.reactionIcon === nextProps.reactionIcon && prevProps.editIcon === nextProps.editIcon && prevProps.copyIcon === nextProps.copyIcon && prevProps.replyIcon === nextProps.replyIcon && prevProps.replyInThreadIcon === nextProps.replyInThreadIcon && prevProps.forwardIcon === nextProps.forwardIcon && prevProps.deleteIcon === nextProps.deleteIcon && prevProps.selectIcon === nextProps.selectIcon && prevProps.starIcon === nextProps.starIcon && prevProps.staredIcon === nextProps.staredIcon && prevProps.reportIcon === nextProps.reportIcon && prevProps.fixEmojiCategoriesTitleOnTop === nextProps.fixEmojiCategoriesTitleOnTop && prevProps.emojisCategoryIconsPosition === nextProps.emojisCategoryIconsPosition && prevProps.emojisContainerBorderRadius === nextProps.emojisContainerBorderRadius && prevProps.reactionIconOrder === nextProps.reactionIconOrder && prevProps.editIconOrder === nextProps.editIconOrder && prevProps.copyIconOrder === nextProps.copyIconOrder && prevProps.replyIconOrder === nextProps.replyIconOrder && prevProps.replyInThreadIconOrder === nextProps.replyInThreadIconOrder && prevProps.forwardIconOrder === nextProps.forwardIconOrder && prevProps.deleteIconOrder === nextProps.deleteIconOrder && prevProps.selectIconOrder === nextProps.selectIconOrder && prevProps.starIconOrder === nextProps.starIconOrder && prevProps.reportIconOrder === nextProps.reportIconOrder && prevProps.reactionIconTooltipText === nextProps.reactionIconTooltipText && prevProps.editIconTooltipText === nextProps.editIconTooltipText && prevProps.copyIconTooltipText === nextProps.copyIconTooltipText && prevProps.replyIconTooltipText === nextProps.replyIconTooltipText && prevProps.replyInThreadIconTooltipText === nextProps.replyInThreadIconTooltipText && prevProps.forwardIconTooltipText === nextProps.forwardIconTooltipText && prevProps.deleteIconTooltipText === nextProps.deleteIconTooltipText && prevProps.selectIconTooltipText === nextProps.selectIconTooltipText && prevProps.starIconTooltipText === nextProps.starIconTooltipText && prevProps.reportIconTooltipText === nextProps.reportIconTooltipText && prevProps.messageActionIconsColor === nextProps.messageActionIconsColor && prevProps.inlineReactionIcon === nextProps.inlineReactionIcon && prevProps.messageStatusSize === nextProps.messageStatusSize && prevProps.messageStatusColor === nextProps.messageStatusColor && prevProps.messageReadStatusColor === nextProps.messageReadStatusColor && prevProps.messageStateFontSize === nextProps.messageStateFontSize && prevProps.messageStateColor === nextProps.messageStateColor && prevProps.messageTimeFontSize === nextProps.messageTimeFontSize && prevProps.messageTimeColor === nextProps.messageTimeColor && prevProps.messageStatusAndTimeLineHeight === nextProps.messageStatusAndTimeLineHeight && prevProps.fileAttachmentsBoxWidth === nextProps.fileAttachmentsBoxWidth && prevProps.fileAttachmentsBoxBackground === nextProps.fileAttachmentsBoxBackground && prevProps.fileAttachmentsBoxBorder === nextProps.fileAttachmentsBoxBorder && prevProps.fileAttachmentsTitleColor === nextProps.fileAttachmentsTitleColor && prevProps.fileAttachmentsSizeColor === nextProps.fileAttachmentsSizeColor && prevProps.fileAttachmentsIcon === nextProps.fileAttachmentsIcon && prevProps.imageAttachmentMaxWidth === nextProps.imageAttachmentMaxWidth && prevProps.imageAttachmentMaxHeight === nextProps.imageAttachmentMaxHeight && prevProps.videoAttachmentMaxWidth === nextProps.videoAttachmentMaxWidth && prevProps.videoAttachmentMaxHeight === nextProps.videoAttachmentMaxHeight && prevProps.messageTextFontSize === nextProps.messageTextFontSize && prevProps.messageTextLineHeight === nextProps.messageTextLineHeight && prevProps.messageActionsShow === nextProps.messageActionsShow && prevProps.emojisPopupOpen === nextProps.emojisPopupOpen && prevProps.emojisPopupPosition === nextProps.emojisPopupPosition && prevProps.frequentlyEmojisOpen === nextProps.frequentlyEmojisOpen && (((_prevProps$ogMetadata = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata === void 0 ? void 0 : _prevProps$ogMetadata.ogLayoutOrder) || 'og-first') === (((_nextProps$ogMetadata = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata === void 0 ? void 0 : _nextProps$ogMetadata.ogLayoutOrder) || 'og-first') && ((_prevProps$ogMetadata2 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata2 === void 0 ? void 0 : _prevProps$ogMetadata2.ogShowUrl) === ((_nextProps$ogMetadata2 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata2 === void 0 ? void 0 : _nextProps$ogMetadata2.ogShowUrl) && ((_prevProps$ogMetadata3 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata3 === void 0 ? void 0 : _prevProps$ogMetadata3.ogShowTitle) === ((_nextProps$ogMetadata3 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata3 === void 0 ? void 0 : _nextProps$ogMetadata3.ogShowTitle) && ((_prevProps$ogMetadata4 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata4 === void 0 ? void 0 : _prevProps$ogMetadata4.ogShowDescription) === ((_nextProps$ogMetadata4 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata4 === void 0 ? void 0 : _nextProps$ogMetadata4.ogShowDescription) && ((_prevProps$ogMetadata5 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata5 === void 0 ? void 0 : _prevProps$ogMetadata5.ogShowFavicon) === ((_nextProps$ogMetadata5 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata5 === void 0 ? void 0 : _nextProps$ogMetadata5.ogShowFavicon) && ((_prevProps$ogMetadata6 = prevProps.ogMetadataProps) === null || _prevProps$ogMetadata6 === void 0 ? void 0 : _prevProps$ogMetadata6.order) === ((_nextProps$ogMetadata6 = nextProps.ogMetadataProps) === null || _nextProps$ogMetadata6 === void 0 ? void 0 : _nextProps$ogMetadata6.order) && prevProps.collapsedCharacterLimit === nextProps.collapsedCharacterLimit);
38273
39138
  });
38274
39139
  var ForwardedTitle = styled.h3(_templateObject$I || (_templateObject$I = _taggedTemplateLiteralLoose(["\n display: flex;\n align-items: center;\n font-weight: 500;\n font-size: 13px;\n line-height: 16px;\n color: ", ";\n // margin: ", ";\n margin: 0;\n padding: ", ";\n padding-top: ", ";\n padding-bottom: ", ";\n\n & > svg {\n margin-right: 4px;\n width: 16px;\n height: 16px;\n color: ", ";\n }\n"])), function (props) {
38275
39140
  return props.color;
@@ -39037,7 +39902,6 @@ var Message$1 = function Message(_ref) {
39037
39902
  openedMessageMenuId = _ref.openedMessageMenuId,
39038
39903
  tabIsActive = _ref.tabIsActive,
39039
39904
  connectionStatus = _ref.connectionStatus,
39040
- theme = _ref.theme,
39041
39905
  messageTextFontSize = _ref.messageTextFontSize,
39042
39906
  messageTextLineHeight = _ref.messageTextLineHeight,
39043
39907
  messageTimeColorOnAttachment = _ref.messageTimeColorOnAttachment,
@@ -39558,7 +40422,6 @@ var Message$1 = function Message(_ref) {
39558
40422
  contactsMap: contactsMap,
39559
40423
  openedMessageMenuId: openedMessageMenuId,
39560
40424
  connectionStatus: connectionStatus,
39561
- theme: theme,
39562
40425
  messageTextFontSize: messageTextFontSize,
39563
40426
  messageTextLineHeight: messageTextLineHeight,
39564
40427
  messageActionsShow: messageActionsShow,
@@ -39695,7 +40558,7 @@ var Message$1 = function Message(_ref) {
39695
40558
  })));
39696
40559
  };
39697
40560
  var Message$2 = /*#__PURE__*/React__default.memo(Message$1, function (prevProps, nextProps) {
39698
- return prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.metadata === nextProps.message.metadata && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.message.pollDetails === nextProps.message.pollDetails && prevProps.prevMessage === nextProps.prevMessage && prevProps.nextMessage === nextProps.nextMessage && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.contactsMap === nextProps.contactsMap && prevProps.connectionStatus === nextProps.connectionStatus && prevProps.openedMessageMenuId === nextProps.openedMessageMenuId && prevProps.theme === nextProps.theme;
40561
+ return prevProps.message.deliveryStatus === nextProps.message.deliveryStatus && prevProps.message.state === nextProps.message.state && prevProps.message.userReactions === nextProps.message.userReactions && prevProps.message.body === nextProps.message.body && prevProps.message.reactionTotals === nextProps.message.reactionTotals && prevProps.message.attachments === nextProps.message.attachments && prevProps.message.metadata === nextProps.message.metadata && prevProps.message.userMarkers === nextProps.message.userMarkers && prevProps.message.pollDetails === nextProps.message.pollDetails && prevProps.prevMessage === nextProps.prevMessage && prevProps.nextMessage === nextProps.nextMessage && prevProps.selectedMessagesMap === nextProps.selectedMessagesMap && prevProps.contactsMap === nextProps.contactsMap && prevProps.connectionStatus === nextProps.connectionStatus && prevProps.openedMessageMenuId === nextProps.openedMessageMenuId;
39699
40562
  });
39700
40563
  var MessageReactionKey = styled.span(_templateObject$K || (_templateObject$K = _taggedTemplateLiteralLoose(["\n display: inline-flex;\n align-items: center;\n font-family:\n apple color emoji,\n segoe ui emoji,\n noto color emoji,\n android emoji,\n emojisymbols,\n emojione mozilla,\n twemoji mozilla,\n segoe ui symbol;\n"])));
39701
40564
  var ReactionItemCount = styled.span(_templateObject2$F || (_templateObject2$F = _taggedTemplateLiteralLoose(["\n margin-left: 2px;\n font-family: Inter, sans-serif;\n font-weight: 400;\n font-size: 14px;\n line-height: 16px;\n color: ", ";\n"])), function (props) {
@@ -39812,7 +40675,6 @@ var CreateMessageDateDivider = function CreateMessageDateDivider(_ref) {
39812
40675
  dateDividerBackgroundColor = _ref.dateDividerBackgroundColor,
39813
40676
  dateDividerBorderRadius = _ref.dateDividerBorderRadius,
39814
40677
  noMargin = _ref.noMargin,
39815
- theme = _ref.theme,
39816
40678
  marginBottom = _ref.marginBottom,
39817
40679
  marginTop = _ref.marginTop,
39818
40680
  chatBackgroundColor = _ref.chatBackgroundColor;
@@ -39826,7 +40688,6 @@ var CreateMessageDateDivider = function CreateMessageDateDivider(_ref) {
39826
40688
  dividerText = moment().year() === moment(current).year() ? current.format('MMMM D') : current.format('MMMM D YYYY');
39827
40689
  }
39828
40690
  return !differentDays ? null : (/*#__PURE__*/React__default.createElement(MessageDivider, {
39829
- theme: theme,
39830
40691
  dividerText: dividerText,
39831
40692
  visibility: messagesHasNext && lastIndex,
39832
40693
  dateDividerFontSize: dateDividerFontSize,
@@ -40008,7 +40869,6 @@ var MessageList = function MessageList(_ref2) {
40008
40869
  var ChatClient = getClient();
40009
40870
  var user = ChatClient.user;
40010
40871
  var dispatch = useDispatch();
40011
- var theme = useSelector(themeSelector);
40012
40872
  var channel = useSelector(activeChannelSelector);
40013
40873
  var _useState = useState(false),
40014
40874
  scrollIntoView = _useState[0],
@@ -40683,7 +41543,6 @@ var MessageList = function MessageList(_ref2) {
40683
41543
  key: message.id || message.tid
40684
41544
  }, /*#__PURE__*/React__default.createElement(CreateMessageDateDivider, {
40685
41545
  noMargin: !isUnreadMessage && prevMessage && prevMessage.type === MESSAGE_TYPE.SYSTEM && message.type !== MESSAGE_TYPE.SYSTEM,
40686
- theme: theme,
40687
41546
  lastIndex: false,
40688
41547
  currentMessageDate: message.createdAt,
40689
41548
  nextMessageDate: prevMessage && prevMessage.createdAt,
@@ -40718,7 +41577,6 @@ var MessageList = function MessageList(_ref2) {
40718
41577
  highlightBg: incomingMessageBackgroundX
40719
41578
  }, /*#__PURE__*/React__default.createElement(Message$2, {
40720
41579
  message: message,
40721
- theme: theme,
40722
41580
  channel: channel,
40723
41581
  stopScrolling: setStopScrolling,
40724
41582
  handleMediaItemClick: function handleMediaItemClick(attachment) {
@@ -40855,7 +41713,6 @@ var MessageList = function MessageList(_ref2) {
40855
41713
  ogMetadataProps: ogMetadataProps,
40856
41714
  collapsedCharacterLimit: collapsedCharacterLimit
40857
41715
  }))), isUnreadMessage ? (/*#__PURE__*/React__default.createElement(MessageDivider, {
40858
- theme: theme,
40859
41716
  newMessagesSeparatorTextColor: newMessagesSeparatorTextColor,
40860
41717
  newMessagesSeparatorFontSize: newMessagesSeparatorFontSize,
40861
41718
  newMessagesSeparatorWidth: newMessagesSeparatorWidth,
@@ -44454,7 +45311,6 @@ var SendMessageInput = function SendMessageInput(_ref3) {
44454
45311
  var ChatClient = getClient();
44455
45312
  var user = ChatClient.user;
44456
45313
  var channelDetailsIsOpen = useSelector(channelInfoIsOpenSelector, shallowEqual);
44457
- var theme = useSelector(themeSelector);
44458
45314
  var getFromContacts = getShowOnlyContactUsers();
44459
45315
  var activeChannel = useSelector(activeChannelSelector);
44460
45316
  var messageToEdit = useSelector(messageToEditSelector);
@@ -45896,7 +46752,6 @@ var SendMessageInput = function SendMessageInput(_ref3) {
45896
46752
  color: viewOnce ? accentColor : iconInactive,
45897
46753
  textColor: viewOnce ? textOnPrimary : iconInactive
45898
46754
  }, viewOnce ? ViewOnceSelectedSVGIcon || /*#__PURE__*/React__default.createElement(SvgViewOnceSelected, null) : ViewOnceNotSelectedSVGIcon || /*#__PURE__*/React__default.createElement(SvgViewOnceNotSelected, null))), showAddAttachments && addAttachmentByMenu && !messageToEdit ? (/*#__PURE__*/React__default.createElement(DropDown, {
45899
- theme: theme,
45900
46755
  forceClose: showChooseAttachmentType,
45901
46756
  position: addAttachmentsInRightSide ? 'top' : 'topRight',
45902
46757
  margin: 'auto 0 0',
@@ -46516,8 +47371,7 @@ function SvgUsers(props) {
46516
47371
 
46517
47372
  var _templateObject$T, _templateObject2$O, _templateObject3$H;
46518
47373
  function NetworkErrorPopup(_ref) {
46519
- var theme = _ref.theme,
46520
- togglePopup = _ref.togglePopup;
47374
+ var togglePopup = _ref.togglePopup;
46521
47375
  var colors = useColors();
46522
47376
  var accentColor = colors[THEME_COLORS.ACCENT],
46523
47377
  background = colors[THEME_COLORS.BACKGROUND],
@@ -46526,7 +47380,6 @@ function NetworkErrorPopup(_ref) {
46526
47380
  iconPrimary = colors[THEME_COLORS.ICON_PRIMARY],
46527
47381
  textOnPrimary = colors[THEME_COLORS.TEXT_ON_PRIMARY];
46528
47382
  return /*#__PURE__*/React__default.createElement(PopupContainer, null, /*#__PURE__*/React__default.createElement(Popup, {
46529
- theme: theme,
46530
47383
  backgroundColor: background,
46531
47384
  maxWidth: '522px',
46532
47385
  minWidth: '522px',
@@ -46576,8 +47429,7 @@ var TIMER_OPTIONS = [{
46576
47429
  label: '1 month'
46577
47430
  }];
46578
47431
  function DisappearingMessagesPopup(_ref) {
46579
- var theme = _ref.theme,
46580
- togglePopup = _ref.togglePopup,
47432
+ var togglePopup = _ref.togglePopup,
46581
47433
  handleSetTimer = _ref.handleSetTimer,
46582
47434
  currentTimer = _ref.currentTimer;
46583
47435
  var colors = useColors();
@@ -46687,11 +47539,9 @@ function DisappearingMessagesPopup(_ref) {
46687
47539
  })) === null || _CUSTOM_OPTIONS$find === void 0 ? void 0 : _CUSTOM_OPTIONS$find.label) || '2 days';
46688
47540
  }, [customValue, CUSTOM_OPTIONS]);
46689
47541
  if (showNetworkError) return /*#__PURE__*/React__default.createElement(NetworkErrorPopup, {
46690
- theme: theme,
46691
47542
  togglePopup: handleCloseNetworkError
46692
47543
  });
46693
47544
  return /*#__PURE__*/React__default.createElement(PopupContainer, null, /*#__PURE__*/React__default.createElement(Popup, {
46694
- theme: theme,
46695
47545
  backgroundColor: background,
46696
47546
  maxWidth: '522px',
46697
47547
  minWidth: '522px',
@@ -46767,7 +47617,6 @@ function DisappearingMessagesPopup(_ref) {
46767
47617
  maxWidth: '474px'
46768
47618
  }, /*#__PURE__*/React__default.createElement(DropDown, {
46769
47619
  withIcon: true,
46770
- theme: theme,
46771
47620
  isSelect: true,
46772
47621
  position: 'top',
46773
47622
  trigger: /*#__PURE__*/React__default.createElement(CustomSelectTriggerStyled, {
@@ -46775,7 +47624,6 @@ function DisappearingMessagesPopup(_ref) {
46775
47624
  }, selectedCustomLabel),
46776
47625
  watchToggleState: setDropdownOpen
46777
47626
  }, /*#__PURE__*/React__default.createElement(CustomDropdownOptionsUl, {
46778
- theme: theme,
46779
47627
  accentColor: accentColor
46780
47628
  }, CUSTOM_OPTIONS.map(function (o) {
46781
47629
  return /*#__PURE__*/React__default.createElement(CustomDropdownOptionLi, {
@@ -46877,8 +47725,7 @@ var MutualChannelItem = function MutualChannelItem(_ref) {
46877
47725
  })));
46878
47726
  };
46879
47727
  var GroupsInCommonPopup = function GroupsInCommonPopup(_ref2) {
46880
- var theme = _ref2.theme,
46881
- togglePopup = _ref2.togglePopup,
47728
+ var togglePopup = _ref2.togglePopup,
46882
47729
  user = _ref2.user;
46883
47730
  var ChatClient = getClient();
46884
47731
  var currentUser = ChatClient.user;
@@ -46929,7 +47776,6 @@ var GroupsInCommonPopup = function GroupsInCommonPopup(_ref2) {
46929
47776
  };
46930
47777
  }, [dispatch]);
46931
47778
  return /*#__PURE__*/React__default.createElement(PopupContainer, null, /*#__PURE__*/React__default.createElement(Popup, {
46932
- theme: theme,
46933
47779
  backgroundColor: background,
46934
47780
  maxWidth: '520px',
46935
47781
  minWidth: '520px',
@@ -47003,7 +47849,6 @@ var Actions = function Actions(_ref) {
47003
47849
  var setActionsHeight = _ref.setActionsHeight,
47004
47850
  channel = _ref.channel,
47005
47851
  actionMenuOpen = _ref.actionMenuOpen,
47006
- theme = _ref.theme,
47007
47852
  menuIsOpen = _ref.menuIsOpen,
47008
47853
  toggleable = _ref.toggleable,
47009
47854
  _ref$showMuteUnmuteNo = _ref.showMuteUnmuteNotifications,
@@ -47235,7 +48080,6 @@ var Actions = function Actions(_ref) {
47235
48080
  }, [containerRef.current, showMuteUnmuteNotifications, showStarredMessages, showPinChannel, showMarkAsReadUnread, showLeaveChannel, showBlockAndLeaveChannel, showBlockUser, showReportChannel, showDeleteChannel, showClearHistory]);
47236
48081
  return /*#__PURE__*/React__default.createElement(Container$n, {
47237
48082
  isDirect: isDirectChannel,
47238
- theme: theme,
47239
48083
  borderColor: borderColor || surface1,
47240
48084
  ref: containerRef
47241
48085
  }, toggleable && (/*#__PURE__*/React__default.createElement(ActionHeader, {
@@ -47260,7 +48104,6 @@ var Actions = function Actions(_ref) {
47260
48104
  fontSize: actionItemsFontSize
47261
48105
  }, /*#__PURE__*/React__default.createElement(React__default.Fragment, null, muteNotificationIcon || /*#__PURE__*/React__default.createElement(DefaultMutedIcon, null), " Unmute notifications"))) : (/*#__PURE__*/React__default.createElement(DropDown, {
47262
48106
  isSelect: true,
47263
- theme: theme,
47264
48107
  height: 'auto',
47265
48108
  position: 'left',
47266
48109
  order: muteUnmuteNotificationsOrder,
@@ -47510,12 +48353,10 @@ var Actions = function Actions(_ref) {
47510
48353
  description: channel.type === DEFAULT_CHANNEL_TYPE.DIRECT ? 'Once you clear the history, the messages in this chat will be permanently removed for you.' : channel.type === DEFAULT_CHANNEL_TYPE.GROUP || channel.type === DEFAULT_CHANNEL_TYPE.PRIVATE ? 'Once you clear the history it will be permanently removed for you.' : channel.type === DEFAULT_CHANNEL_TYPE.BROADCAST || channel.type === DEFAULT_CHANNEL_TYPE.PUBLIC ? 'Once you clear the history, the messages in this channel will be permanently removed for all the subscribers.' : 'Are you sure you want to delete all messages? This action cannot be undone.',
47511
48354
  title: popupTitle
47512
48355
  })), disappearingMessagesPopupOpen && (/*#__PURE__*/React__default.createElement(DisappearingMessagesPopup, {
47513
- theme: theme,
47514
48356
  togglePopup: handleToggleDisappearingMessagesPopup,
47515
48357
  handleSetTimer: handleSetDisappearingMessagesTimer,
47516
48358
  currentTimer: channel.messageRetentionPeriod
47517
48359
  })), groupsInCommonPopupOpen && (/*#__PURE__*/React__default.createElement(GroupsInCommonPopup, {
47518
- theme: theme,
47519
48360
  togglePopup: handleToggleGroupsInCommonPopup,
47520
48361
  user: channel.members.find(function (member) {
47521
48362
  return member.id !== user.id;
@@ -48278,8 +49119,7 @@ function SvgMoreVert(props) {
48278
49119
 
48279
49120
  var _templateObject$12, _templateObject2$W, _templateObject3$O;
48280
49121
  var ChangeMemberRole = function ChangeMemberRole(_ref) {
48281
- var theme = _ref.theme,
48282
- channelId = _ref.channelId,
49122
+ var channelId = _ref.channelId,
48283
49123
  member = _ref.member,
48284
49124
  handleClosePopup = _ref.handleClosePopup;
48285
49125
  var connectionStatus = useSelector(connectionStatusSelector, shallowEqual);
@@ -48346,14 +49186,11 @@ var ChangeMemberRole = function ChangeMemberRole(_ref) {
48346
49186
  disabledColor: surface1
48347
49187
  }, /*#__PURE__*/React__default.createElement(DropDown, {
48348
49188
  withIcon: true,
48349
- theme: theme,
48350
49189
  isSelect: true,
48351
49190
  trigger: /*#__PURE__*/React__default.createElement(CustomSelectTrigger, {
48352
49191
  color: textPrimary
48353
49192
  }, selectedRole || member.role || 'Select')
48354
- }, /*#__PURE__*/React__default.createElement(DropdownOptionsUl, {
48355
- theme: theme
48356
- }, !!roles.length && roles.map(function (role) {
49193
+ }, /*#__PURE__*/React__default.createElement(DropdownOptionsUl, null, !!roles.length && roles.map(function (role) {
48357
49194
  return /*#__PURE__*/React__default.createElement(DropdownOptionLi, {
48358
49195
  hoverBackground: backgroundHovered,
48359
49196
  key: role.name,
@@ -48438,7 +49275,6 @@ function InviteLinkModal(_ref) {
48438
49275
  border = _useColor[THEME_COLORS.BORDER],
48439
49276
  iconPrimary = _useColor[THEME_COLORS.ICON_PRIMARY],
48440
49277
  tooltipBackground = _useColor[THEME_COLORS.TOOLTIP_BACKGROUND];
48441
- var theme = useSelector(themeSelector) || 'light';
48442
49278
  var connectionStatus = useSelector(connectionStatusSelector, shallowEqual);
48443
49279
  var channelsInviteKeys = useSelector(channelInviteKeysSelector, shallowEqual);
48444
49280
  var dispatch = useDispatch();
@@ -48771,7 +49607,6 @@ function InviteLinkModal(_ref) {
48771
49607
  },
48772
49608
  inviteUrl: inviteUrl,
48773
49609
  channelId: channelId,
48774
- theme: theme,
48775
49610
  colors: {
48776
49611
  accentColor: accentColor,
48777
49612
  textPrimary: textPrimary,
@@ -48956,7 +49791,6 @@ var Members = function Members(_ref) {
48956
49791
  var _members$find;
48957
49792
  var channel = _ref.channel,
48958
49793
  members = _ref.members,
48959
- theme = _ref.theme,
48960
49794
  checkActionPermission = _ref.checkActionPermission,
48961
49795
  _ref$showChangeMember = _ref.showChangeMemberRole,
48962
49796
  showChangeMemberRole = _ref$showChangeMember === void 0 ? true : _ref$showChangeMember,
@@ -49123,9 +49957,7 @@ var Members = function Members(_ref) {
49123
49957
  var currentUserRole = (_members$find = members.find(function (member) {
49124
49958
  return member.id === user.id;
49125
49959
  })) === null || _members$find === void 0 ? void 0 : _members$find.role;
49126
- return /*#__PURE__*/React__default.createElement(Container$s, {
49127
- theme: theme
49128
- }, /*#__PURE__*/React__default.createElement(ActionsMenu$1, null, /*#__PURE__*/React__default.createElement(MembersList, null, checkActionPermission('addMember') && (currentUserRole === 'owner' || currentUserRole === 'admin') && (/*#__PURE__*/React__default.createElement(MemberItem$1, {
49960
+ return /*#__PURE__*/React__default.createElement(Container$s, null, /*#__PURE__*/React__default.createElement(ActionsMenu$1, null, /*#__PURE__*/React__default.createElement(MembersList, null, checkActionPermission('addMember') && (currentUserRole === 'owner' || currentUserRole === 'admin') && (/*#__PURE__*/React__default.createElement(MemberItem$1, {
49129
49961
  key: 1,
49130
49962
  onClick: handleAddMemberPopup,
49131
49963
  color: textPrimary,
@@ -49163,7 +49995,6 @@ var Members = function Members(_ref) {
49163
49995
  margin: '1px 0 0',
49164
49996
  fontSize: memberPresenceFontSize
49165
49997
  }, member.presence && member.presence.state === USER_PRESENCE_STATUS.ONLINE ? 'Online' : member.presence && member.presence.lastActiveAt && userLastActiveDateFormat(member.presence.lastActiveAt))), !noMemberEditPermissions && member.role !== 'owner' && currentUserRole && (rolesMap === null || rolesMap === void 0 ? void 0 : (_rolesMap$member$role = rolesMap[member.role]) === null || _rolesMap$member$role === void 0 ? void 0 : _rolesMap$member$role.priority) && (rolesMap === null || rolesMap === void 0 ? void 0 : (_rolesMap$currentUser = rolesMap[currentUserRole]) === null || _rolesMap$currentUser === void 0 ? void 0 : _rolesMap$currentUser.priority) && (rolesMap === null || rolesMap === void 0 ? void 0 : (_rolesMap$member$role2 = rolesMap[member.role]) === null || _rolesMap$member$role2 === void 0 ? void 0 : _rolesMap$member$role2.priority) < (rolesMap === null || rolesMap === void 0 ? void 0 : (_rolesMap$currentUser2 = rolesMap[currentUserRole]) === null || _rolesMap$currentUser2 === void 0 ? void 0 : _rolesMap$currentUser2.priority) && member.id !== user.id && (/*#__PURE__*/React__default.createElement(DropDown, {
49166
- theme: theme,
49167
49998
  isSelect: true,
49168
49999
  forceClose: !!(closeMenu && closeMenu !== member.id),
49169
50000
  watchToggleState: function watchToggleState(state) {
@@ -49212,21 +50043,18 @@ var Members = function Members(_ref) {
49212
50043
  }
49213
50044
  }, "Remove and Block member"))))));
49214
50045
  }))), kickMemberPopupOpen && (/*#__PURE__*/React__default.createElement(ConfirmPopup, {
49215
- theme: theme,
49216
50046
  handleFunction: handleKickMember,
49217
50047
  togglePopup: toggleKickMemberPopup,
49218
50048
  buttonText: 'Remove',
49219
50049
  title: channel.type === DEFAULT_CHANNEL_TYPE.GROUP || channel.type === DEFAULT_CHANNEL_TYPE.PRIVATE ? 'Remove member' : 'Remove subscriber',
49220
50050
  description: /*#__PURE__*/React__default.createElement("span", null, "Are you sure to remove", !!selectedMember && (/*#__PURE__*/React__default.createElement(BoltText, null, " ", makeUsername(contactsMap[selectedMember.id], selectedMember, getFromContacts), " ")), "from this", ' ', channel.type === DEFAULT_CHANNEL_TYPE.BROADCAST || channel.type === DEFAULT_CHANNEL_TYPE.PUBLIC ? 'channel' : 'group', "?")
49221
50051
  })), blockMemberPopupOpen && (/*#__PURE__*/React__default.createElement(ConfirmPopup, {
49222
- theme: theme,
49223
50052
  handleFunction: handleBlockMember,
49224
50053
  togglePopup: toggleBlockMemberPopup,
49225
50054
  buttonText: 'Block',
49226
50055
  description: "Block and remove member - " + (selectedMember && (selectedMember.firstName || selectedMember.lastName || selectedMember.id)),
49227
50056
  title: 'Block and remove user'
49228
50057
  })), makeAdminPopup && (/*#__PURE__*/React__default.createElement(ConfirmPopup, {
49229
- theme: theme,
49230
50058
  handleFunction: handleMakeAdmin,
49231
50059
  togglePopup: function togglePopup() {
49232
50060
  return toggleMakeAdminPopup(undefined, false);
@@ -49242,10 +50070,8 @@ var Members = function Members(_ref) {
49242
50070
  },
49243
50071
  buttonText: 'Revoke',
49244
50072
  title: 'Revoke admin',
49245
- theme: theme,
49246
50073
  description: /*#__PURE__*/React__default.createElement("span", null, "Are you sure you want to revoke", /*#__PURE__*/React__default.createElement(BoltText, null, " \u201CAdmin\u201D "), "rights from user:", selectedMember && (/*#__PURE__*/React__default.createElement(BoltText, null, " ", makeUsername(contactsMap[selectedMember.id], selectedMember, getFromContacts), " ")), "?")
49247
50074
  })), changeMemberRolePopup && (/*#__PURE__*/React__default.createElement(ChangeMemberRole, {
49248
- theme: theme,
49249
50075
  channelId: channel.id,
49250
50076
  member: selectedMember,
49251
50077
  handleClosePopup: toggleChangeRolePopup
@@ -49299,7 +50125,6 @@ var RoleBadge = styled.span(_templateObject9$n || (_templateObject9$n = _taggedT
49299
50125
  var _templateObject$15, _templateObject2$Z;
49300
50126
  var DetailsTab = function DetailsTab(_ref) {
49301
50127
  var channel = _ref.channel,
49302
- theme = _ref.theme,
49303
50128
  activeTab = _ref.activeTab,
49304
50129
  checkActionPermission = _ref.checkActionPermission,
49305
50130
  setActiveTab = _ref.setActiveTab,
@@ -49369,9 +50194,7 @@ var DetailsTab = function DetailsTab(_ref) {
49369
50194
  setActiveTab(channelDetailsTabs.member);
49370
50195
  }
49371
50196
  }, [showMembers]);
49372
- return /*#__PURE__*/React__default.createElement(Container$t, {
49373
- theme: theme
49374
- }, /*#__PURE__*/React__default.createElement(DetailsTabHeader, {
50197
+ return /*#__PURE__*/React__default.createElement(Container$t, null, /*#__PURE__*/React__default.createElement(DetailsTabHeader, {
49375
50198
  color: textSecondary,
49376
50199
  activeTabColor: accentColor,
49377
50200
  borderColor: borderColor || border,
@@ -49404,7 +50227,6 @@ var DetailsTab = function DetailsTab(_ref) {
49404
50227
  key: key
49405
50228
  }, /*#__PURE__*/React__default.createElement("span", null, channelDetailsTabs[tabKey]));
49406
50229
  })), showMembers && activeTab === channelDetailsTabs.member && (/*#__PURE__*/React__default.createElement(Members, {
49407
- theme: theme,
49408
50230
  members: members,
49409
50231
  channel: channel,
49410
50232
  checkActionPermission: checkActionPermission,
@@ -49423,7 +50245,6 @@ var DetailsTab = function DetailsTab(_ref) {
49423
50245
  channel: channel
49424
50246
  }), activeTab === channelDetailsTabs.file && (/*#__PURE__*/React__default.createElement(Files, {
49425
50247
  channelId: channel.id,
49426
- theme: theme,
49427
50248
  filePreviewIcon: filePreviewIcon,
49428
50249
  filePreviewHoverIcon: filePreviewHoverIcon,
49429
50250
  filePreviewTitleColor: filePreviewTitleColor,
@@ -49484,7 +50305,6 @@ var DropDownWrapper = styled.div(_templateObject3$R || (_templateObject3$R = _ta
49484
50305
  var EditChannelFooter = styled(ButtonBlock)(_templateObject4$J || (_templateObject4$J = _taggedTemplateLiteralLoose(["\n margin-top: 24px;\n\n & > button {\n margin-left: 12px;\n }\n"])));
49485
50306
  var EditChannel = function EditChannel(_ref) {
49486
50307
  var channel = _ref.channel,
49487
- theme = _ref.theme,
49488
50308
  handleToggleEditMode = _ref.handleToggleEditMode,
49489
50309
  editChannelSaveButtonBackgroundColor = _ref.editChannelSaveButtonBackgroundColor,
49490
50310
  editChannelSaveButtonTextColor = _ref.editChannelSaveButtonTextColor,
@@ -49639,7 +50459,6 @@ var EditChannel = function EditChannel(_ref) {
49639
50459
  active: isEditMode,
49640
50460
  backgroundColor: background
49641
50461
  }, /*#__PURE__*/React__default.createElement(AvatarCont, null, /*#__PURE__*/React__default.createElement(DropDownWrapper, null, !isDirectChannel && channel.userRole && (/*#__PURE__*/React__default.createElement(DropDown, {
49642
- theme: theme,
49643
50462
  position: 'center',
49644
50463
  iconColor: iconPrimary,
49645
50464
  trigger: getUploadImageIcon() || /*#__PURE__*/React__default.createElement(SvgCameraIcon, null)
@@ -49671,7 +50490,6 @@ var EditChannel = function EditChannel(_ref) {
49671
50490
  color: textPrimary
49672
50491
  }, " Name "), /*#__PURE__*/React__default.createElement(CustomInput, {
49673
50492
  error: subjectIsWrong,
49674
- theme: theme,
49675
50493
  color: textPrimary,
49676
50494
  borderColor: borderColor,
49677
50495
  errorColor: warningColor,
@@ -49689,7 +50507,6 @@ var EditChannel = function EditChannel(_ref) {
49689
50507
  color: textPrimary
49690
50508
  }, " Description "), /*#__PURE__*/React__default.createElement(CustomInput, {
49691
50509
  error: descriptionIsWrong,
49692
- theme: theme,
49693
50510
  color: textPrimary,
49694
50511
  errorColor: warningColor,
49695
50512
  borderColor: borderColor,
@@ -49718,7 +50535,6 @@ var EditChannel = function EditChannel(_ref) {
49718
50535
  backgroundColor: editChannelSaveButtonBackgroundColor || accentColor,
49719
50536
  onClick: handleSave
49720
50537
  }, "Save"))), cropPopup && (/*#__PURE__*/React__default.createElement(ImageCrop, {
49721
- theme: theme,
49722
50538
  image: {
49723
50539
  name: newAvatar.name,
49724
50540
  url: selectedImageUrl
@@ -49872,7 +50688,6 @@ var Details = function Details(_ref) {
49872
50688
  var dispatch = useDispatch();
49873
50689
  var ChatClient = getClient();
49874
50690
  var user = ChatClient.user;
49875
- var theme = useSelector(themeSelector);
49876
50691
  var getFromContacts = getShowOnlyContactUsers();
49877
50692
  var _useState = useState(false),
49878
50693
  mounted = _useState[0],
@@ -49990,7 +50805,6 @@ var Details = function Details(_ref) {
49990
50805
  backgroundColor: backgroundColor,
49991
50806
  mounted: mounted,
49992
50807
  size: size,
49993
- theme: theme,
49994
50808
  borderColor: bordersColor || borderThemeColor
49995
50809
  }, /*#__PURE__*/React__default.createElement(ChannelDetailsHeader, {
49996
50810
  borderColor: bordersColor || borderThemeColor
@@ -50010,7 +50824,6 @@ var Details = function Details(_ref) {
50010
50824
  color: accentColor,
50011
50825
  onClick: handleDetailsClose
50012
50826
  })))), editMode && (/*#__PURE__*/React__default.createElement(EditChannel, {
50013
- theme: theme,
50014
50827
  channel: activeChannel,
50015
50828
  handleToggleEditMode: setEditMode,
50016
50829
  editChannelSaveButtonBackgroundColor: editChannelSaveButtonBackgroundColor,
@@ -50077,7 +50890,6 @@ var Details = function Details(_ref) {
50077
50890
  color: textPrimary
50078
50891
  }, channelMetadata !== null && channelMetadata !== void 0 && channelMetadata.d ? channelMetadata === null || channelMetadata === void 0 ? void 0 : channelMetadata.d : '')))), activeChannel && activeChannel.userRole && (/*#__PURE__*/React__default.createElement(Actions, {
50079
50892
  setActionsHeight: setActionsHeight,
50080
- theme: theme,
50081
50893
  showMuteUnmuteNotifications: showMuteUnmuteNotifications,
50082
50894
  muteUnmuteNotificationsOrder: muteUnmuteNotificationsOrder,
50083
50895
  unmuteNotificationIcon: unmuteNotificationIcon,
@@ -50144,7 +50956,6 @@ var Details = function Details(_ref) {
50144
50956
  commonGroupsTextColor: commonGroupsTextColor,
50145
50957
  showGroupsInCommon: showGroupsInCommon
50146
50958
  })), !(activeChannel && activeChannel.isMockChannel) && (/*#__PURE__*/React__default.createElement(DetailsTab, {
50147
- theme: theme,
50148
50959
  channel: activeChannel,
50149
50960
  activeTab: activeTab,
50150
50961
  setActiveTab: setActiveTab,
@@ -50527,7 +51338,6 @@ var MessagesScrollToBottomButton = function MessagesScrollToBottomButton(_ref) {
50527
51338
  backgroundSections = _useColor[THEME_COLORS.BACKGROUND_SECTIONS];
50528
51339
  var dispatch = useDispatch();
50529
51340
  var channel = useSelector(activeChannelSelector);
50530
- var theme = useSelector(themeSelector);
50531
51341
  var sendMessageInputHeight = useSelector(sendMessageInputHeightSelector);
50532
51342
  var showScrollToNewMessageButton = useSelector(showScrollToNewMessageButtonSelector);
50533
51343
  var messages = useSelector(activeChannelMessagesSelector) || [];
@@ -50566,7 +51376,6 @@ var MessagesScrollToBottomButton = function MessagesScrollToBottomButton(_ref) {
50566
51376
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(BottomButton, {
50567
51377
  show: !!showScrollToNewMessageButton,
50568
51378
  animateFrom: animateFrom,
50569
- theme: theme,
50570
51379
  width: buttonWidth,
50571
51380
  height: buttonHeight,
50572
51381
  border: buttonBorder,
@@ -50664,7 +51473,6 @@ var MessagesScrollToUnreadMentionsButton = function MessagesScrollToUnreadMentio
50664
51473
  backgroundSections = _useColor[THEME_COLORS.BACKGROUND_SECTIONS];
50665
51474
  var dispatch = useDispatch();
50666
51475
  var channel = useSelector(activeChannelSelector);
50667
- var theme = useSelector(themeSelector);
50668
51476
  var sendMessageInputHeight = useSelector(sendMessageInputHeightSelector);
50669
51477
  var showScrollToNewMessageButton = useSelector(showScrollToNewMessageButtonSelector);
50670
51478
  var messages = useSelector(activeChannelMessagesSelector) || [];
@@ -50758,7 +51566,6 @@ var MessagesScrollToUnreadMentionsButton = function MessagesScrollToUnreadMentio
50758
51566
  }
50759
51567
  }, [channel.newMentionCount]);
50760
51568
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(BottomButton$1, {
50761
- theme: theme,
50762
51569
  animateFrom: animateFrom,
50763
51570
  show: !!channel.newMentionCount,
50764
51571
  width: buttonWidth,