@ezuikit/player-theme 3.1.2-beta.3 → 3.1.2-beta.4

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/dist/constant.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.2-beta.3
3
- * Copyright (c) 2026-08-14 08:18:55 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.2-beta.4
3
+ * Copyright (c) 2026-08-16 15:20:04 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  /**
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.2-beta.3
3
- * Copyright (c) 2026-08-14 08:18:55 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.2-beta.4
3
+ * Copyright (c) 2026-08-16 15:20:04 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  'use strict';
@@ -295,7 +295,7 @@ function _set_prototype_of$y(o, p) {
295
295
  function Control(options) {
296
296
  var _this;
297
297
  var _this___options;
298
- _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '';
298
+ _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '', /** click 监听引用,销毁时需显式移除 */ _this._onClickHandler = null;
299
299
  _this.__options = options;
300
300
  _this.locale = getLocale(_this.__options.locales, _this.__options.language);
301
301
  _this._camelCaseName = _this.__options.classNameSuffix ? _this.__options.classNameSuffix.replace(/[-_\s]+(.)?/g, function(_, c) {
@@ -384,6 +384,12 @@ function _set_prototype_of$y(o, p) {
384
384
  this.emit("Control." + this._camelCaseName + "Destroy");
385
385
  }
386
386
  if (((_this___options = this.__options) == null ? void 0 : _this___options.controlType) !== 'block') this.$container.removeEventListener('dblclick', this._onDBlClick);
387
+ // 移除 click 监听
388
+ if (this._onClickHandler) {
389
+ var _this_$container1;
390
+ (_this_$container1 = this.$container) == null ? void 0 : _this_$container1.removeEventListener('click', this._onClickHandler);
391
+ this._onClickHandler = null;
392
+ }
387
393
  this._active = false;
388
394
  this.removeAllListeners();
389
395
  (_this_$container = this.$container) == null ? void 0 : (_this_$container_remove = _this_$container.remove) == null ? void 0 : _this_$container_remove.call(_this_$container);
@@ -412,14 +418,16 @@ function _set_prototype_of$y(o, p) {
412
418
  * 当点击 Control 时 触发子类的 _onControlClick
413
419
  */ _proto._onClick = function _onClick() {
414
420
  var _this = this;
415
- this.$container.addEventListener('click', function(e) {
421
+ // 使用具名 handler 便于在 destroy 时精确移除,避免匿名监听残留
422
+ this._onClickHandler = function(e) {
416
423
  var _this_$container;
417
424
  // prettier-ignore
418
425
  if (!((_this_$container = _this.$container) == null ? void 0 : _this_$container.classList.contains("" + PREFIX_CLASS + "-disabled"))) {
419
426
  // _onControlClick 来源自子类中
420
427
  _this._onControlClick == null ? void 0 : _this._onControlClick.call(_this, e);
421
428
  }
422
- });
429
+ };
430
+ this.$container.addEventListener('click', this._onClickHandler);
423
431
  };
424
432
  _proto._onDBlClick = function _onDBlClick(e) {
425
433
  e.stopPropagation();
@@ -4609,8 +4617,14 @@ function debounce(func, wait) {
4609
4617
  }
4610
4618
  // 播放地址切换后同步 Live/RecDropdown 激活状态
4611
4619
  // changePlayUrl 后 urlInfo 已更新,firstFrameDisplay 表示新地址播放成功
4620
+ // 注意:_controlEventemitter 每次 _renderTheme 都会执行,这里的监听挂在 theme 上,
4621
+ // 必须先移除上一次的引用,避免 changeTheme 反复切换导致监听器无限累积(内存泄漏 + 重复执行)。
4622
+ if (theme._onFirstFrameSync) {
4623
+ theme.removeListener(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
4624
+ theme._onFirstFrameSync = null;
4625
+ }
4612
4626
  if (((_theme_controls11 = theme.controls) == null ? void 0 : _theme_controls11.liveControl) || ((_theme_controls12 = theme.controls) == null ? void 0 : _theme_controls12.recDropdownControl)) {
4613
- theme.on(EVENTS.firstFrameDisplay, function() {
4627
+ theme._onFirstFrameSync = function() {
4614
4628
  var _theme_controls, _theme_controls1;
4615
4629
  var urlInfo = theme.urlInfo;
4616
4630
  if ((_theme_controls = theme.controls) == null ? void 0 : _theme_controls.liveControl) {
@@ -4619,7 +4633,8 @@ function debounce(func, wait) {
4619
4633
  if ((_theme_controls1 = theme.controls) == null ? void 0 : _theme_controls1.recDropdownControl) {
4620
4634
  theme.controls.recDropdownControl._syncActiveByUrlInfo(urlInfo);
4621
4635
  }
4622
- });
4636
+ };
4637
+ theme.on(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
4623
4638
  }
4624
4639
  // 缩放控件
4625
4640
  if ((_theme_controls13 = theme.controls) == null ? void 0 : _theme_controls13.zoomControl) {
@@ -5192,15 +5207,20 @@ function _ts_generator$6(thisArg, body) {
5192
5207
  * @returns
5193
5208
  */ function getThemeDataByTemplate(theme, id) {
5194
5209
  return _async_to_generator$6(function() {
5195
- var _theme_options_token_httpToken, _theme_options_token, url;
5210
+ var _theme_options_token_httpToken, _theme_options_token, // 中止上一个在途请求,并为本次请求创建可中止的信号(destroy 时会 abort)
5211
+ _theme__templateAbortController, url, controller;
5196
5212
  return _ts_generator$6(this, function(_state) {
5197
5213
  switch(_state.label){
5198
5214
  case 0:
5199
5215
  url = theme.options.env.domain + "/api/service/media/template/getDetail?accessToken=" + (theme.options.accessToken || ((_theme_options_token = theme.options.token) == null ? void 0 : (_theme_options_token_httpToken = _theme_options_token.httpToken) == null ? void 0 : _theme_options_token_httpToken.url)) + "&id=" + id;
5216
+ (_theme__templateAbortController = theme._templateAbortController) == null ? void 0 : _theme__templateAbortController.abort();
5217
+ controller = new AbortController();
5218
+ theme._templateAbortController = controller;
5200
5219
  return [
5201
5220
  4,
5202
5221
  fetch(url, {
5203
- method: 'GET'
5222
+ method: 'GET',
5223
+ signal: controller == null ? void 0 : controller.signal
5204
5224
  }).then(function(response) {
5205
5225
  return _async_to_generator$6(function() {
5206
5226
  return _ts_generator$6(this, function(_state) {
@@ -5504,7 +5524,7 @@ function _filterLeftRightControls(btnList) {
5504
5524
  * @returns
5505
5525
  */ function getThemeData(theme, data) {
5506
5526
  return _async_to_generator$5(function() {
5507
- var themeData, _theme_logger, template;
5527
+ var themeData, _theme_logger, template, e;
5508
5528
  return _ts_generator$5(this, function(_state) {
5509
5529
  switch(_state.label){
5510
5530
  case 0:
@@ -5550,13 +5570,23 @@ function _filterLeftRightControls(btnList) {
5550
5570
  2,
5551
5571
  template
5552
5572
  ];
5573
+ // 请求返回前已销毁则静默返回,不在已释放的 theme 上派发事件
5574
+ if (theme.destroyed) return [
5575
+ 2,
5576
+ null
5577
+ ];
5553
5578
  theme.emit(EVENTS.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
5554
5579
  return [
5555
5580
  2,
5556
5581
  null
5557
5582
  ];
5558
5583
  case 4:
5559
- _state.sent();
5584
+ e = _state.sent();
5585
+ // 请求被中止(destroy/重新渲染)或已销毁:静默返回
5586
+ if (theme.destroyed || (e == null ? void 0 : e.name) === 'AbortError') return [
5587
+ 2,
5588
+ null
5589
+ ];
5560
5590
  theme.emit(EVENTS.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
5561
5591
  return [
5562
5592
  2,
@@ -9246,6 +9276,11 @@ var _unmountedControls = function(theme) {
9246
9276
  if (theme._onPauseTimingFunc) {
9247
9277
  theme._onPauseTimingFunc = null;
9248
9278
  }
9279
+ // 移除首帧同步监听(挂在 theme 上,需显式解绑,避免 changeTheme 累积)
9280
+ if (theme._onFirstFrameSync) {
9281
+ theme.removeListener(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
9282
+ theme._onFirstFrameSync = null;
9283
+ }
9249
9284
  if (hasControls) {
9250
9285
  theme.emit(EVENTS.control.unmountedControls);
9251
9286
  }
@@ -9516,6 +9551,10 @@ function _renderTheme(theme, data) {
9516
9551
  ];
9517
9552
  case 1:
9518
9553
  themeData = _state.sent();
9554
+ // 异步获取主题数据期间可能已 destroy(),避免在已释放的 theme 上继续渲染/emit
9555
+ if (theme.destroyed) return [
9556
+ 2
9557
+ ];
9519
9558
  _unmountedControls(theme);
9520
9559
  if (Object.prototype.toString.call(themeData) !== '[object Object]') {
9521
9560
  // 主题空
@@ -10178,7 +10217,15 @@ var THEME_DEFAULT_OPTIONS = {
10178
10217
  // _recMonthObj: Record<string, string[]> = {};
10179
10218
  /**
10180
10219
  * 录像回放的月份列表 @private
10181
- */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
10220
+ */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /**
10221
+ * 首帧同步 Live/RecDropdown 激活态的监听器引用。
10222
+ * 每次 `_renderTheme` 重新绑定前需先移除旧引用,避免 changeTheme 累积监听。
10223
+ * @private
10224
+ */ _this._onFirstFrameSync = null, /**
10225
+ * 模板请求(getDetail)的中止控制器。
10226
+ * 重新渲染或销毁时中止在途请求,避免请求返回后在已销毁/已切换的 theme 上继续操作。
10227
+ * @private
10228
+ */ _this._templateAbortController = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
10182
10229
  _this._initOptions(options);
10183
10230
  if (_this.options.type === 'ezopen') {
10184
10231
  var _this_urlInfo_searchParams1, _this_urlInfo1, _this_urlInfo2;
@@ -10433,12 +10480,15 @@ var THEME_DEFAULT_OPTIONS = {
10433
10480
  * ```
10434
10481
  */ _proto.destroy = function destroy() {
10435
10482
  var _this = this;
10436
- var _this_contentControl, _this_$container;
10483
+ var // 中止在途的模板请求,避免其回调在已销毁的 theme 上继续执行
10484
+ _this__templateAbortController, _this_contentControl, _this_$container;
10437
10485
  if (!this.$container || this.destroyed) {
10438
10486
  // 防止多次销毁
10439
10487
  return;
10440
10488
  }
10441
10489
  this.emit(EVENTS.theme.beforeDestroy);
10490
+ (_this__templateAbortController = this._templateAbortController) == null ? void 0 : _this__templateAbortController.abort();
10491
+ this._templateAbortController = null;
10442
10492
  this._removeEventListener();
10443
10493
  _unmountedControls(this);
10444
10494
  (_this_contentControl = this.contentControl) == null ? void 0 : _this_contentControl.destroy();
@@ -10473,7 +10523,12 @@ var THEME_DEFAULT_OPTIONS = {
10473
10523
  /** 初始化配置项 */ _proto._initOptions = function _initOptions(options) {
10474
10524
  if (options === void 0) options = {};
10475
10525
  var _this_options_loggerOptions, _this_options_definitionOptions_list, _this_options_definitionOptions, _this_options_videoLevelList;
10476
- this.options = deepmerge(THEME_DEFAULT_OPTIONS, options, {
10526
+ // 先对模块级默认配置做一次深拷贝,得到全新的嵌套对象/数组,
10527
+ // 避免 this.options 与 THEME_DEFAULT_OPTIONS(如 mobileExtendOptions.controls、env、loggerOptions)
10528
+ // 共享引用而在多实例间相互污染。
10529
+ // 仍对用户 options 使用 clone:false —— container 可能是 DOM 节点/函数,深拷贝会破坏它。
10530
+ var defaults = deepmerge({}, THEME_DEFAULT_OPTIONS);
10531
+ this.options = deepmerge(defaults, options, {
10477
10532
  clone: false
10478
10533
  });
10479
10534
  this._url = this.options.url;
@@ -10508,10 +10563,12 @@ var THEME_DEFAULT_OPTIONS = {
10508
10563
  this.logger.log('[options] \n', this.options);
10509
10564
  }
10510
10565
  var language = this.options.language || 'zh';
10511
- var locales = deepmerge({
10566
+ // 深拷贝内置语言包,避免与模块级 zh/en 常量共享引用(I18n 若对其做合并/修改会污染全局)
10567
+ var baseLocales = deepmerge({}, {
10512
10568
  zh: zh,
10513
10569
  en: en
10514
- }, this.options.locales || {}, {
10570
+ });
10571
+ var locales = deepmerge(baseLocales, this.options.locales || {}, {
10515
10572
  clone: false
10516
10573
  });
10517
10574
  // prettier-ignore
@@ -11529,7 +11586,7 @@ var THEME_DEFAULT_OPTIONS = {
11529
11586
  zh: zh,
11530
11587
  en: en
11531
11588
  };
11532
- /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.3';
11589
+ /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.4';
11533
11590
 
11534
11591
  exports.Control = Control;
11535
11592
  exports.EVENTS = EVENTS;
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.2-beta.3
3
- * Copyright (c) 2026-08-14 08:18:55 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.2-beta.4
3
+ * Copyright (c) 2026-08-16 15:20:04 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  import EventEmitter from 'eventemitter3';
@@ -293,7 +293,7 @@ function _set_prototype_of$y(o, p) {
293
293
  function Control(options) {
294
294
  var _this;
295
295
  var _this___options;
296
- _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '';
296
+ _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '', /** click 监听引用,销毁时需显式移除 */ _this._onClickHandler = null;
297
297
  _this.__options = options;
298
298
  _this.locale = getLocale(_this.__options.locales, _this.__options.language);
299
299
  _this._camelCaseName = _this.__options.classNameSuffix ? _this.__options.classNameSuffix.replace(/[-_\s]+(.)?/g, function(_, c) {
@@ -382,6 +382,12 @@ function _set_prototype_of$y(o, p) {
382
382
  this.emit("Control." + this._camelCaseName + "Destroy");
383
383
  }
384
384
  if (((_this___options = this.__options) == null ? void 0 : _this___options.controlType) !== 'block') this.$container.removeEventListener('dblclick', this._onDBlClick);
385
+ // 移除 click 监听
386
+ if (this._onClickHandler) {
387
+ var _this_$container1;
388
+ (_this_$container1 = this.$container) == null ? void 0 : _this_$container1.removeEventListener('click', this._onClickHandler);
389
+ this._onClickHandler = null;
390
+ }
385
391
  this._active = false;
386
392
  this.removeAllListeners();
387
393
  (_this_$container = this.$container) == null ? void 0 : (_this_$container_remove = _this_$container.remove) == null ? void 0 : _this_$container_remove.call(_this_$container);
@@ -410,14 +416,16 @@ function _set_prototype_of$y(o, p) {
410
416
  * 当点击 Control 时 触发子类的 _onControlClick
411
417
  */ _proto._onClick = function _onClick() {
412
418
  var _this = this;
413
- this.$container.addEventListener('click', function(e) {
419
+ // 使用具名 handler 便于在 destroy 时精确移除,避免匿名监听残留
420
+ this._onClickHandler = function(e) {
414
421
  var _this_$container;
415
422
  // prettier-ignore
416
423
  if (!((_this_$container = _this.$container) == null ? void 0 : _this_$container.classList.contains("" + PREFIX_CLASS + "-disabled"))) {
417
424
  // _onControlClick 来源自子类中
418
425
  _this._onControlClick == null ? void 0 : _this._onControlClick.call(_this, e);
419
426
  }
420
- });
427
+ };
428
+ this.$container.addEventListener('click', this._onClickHandler);
421
429
  };
422
430
  _proto._onDBlClick = function _onDBlClick(e) {
423
431
  e.stopPropagation();
@@ -4607,8 +4615,14 @@ function debounce(func, wait) {
4607
4615
  }
4608
4616
  // 播放地址切换后同步 Live/RecDropdown 激活状态
4609
4617
  // changePlayUrl 后 urlInfo 已更新,firstFrameDisplay 表示新地址播放成功
4618
+ // 注意:_controlEventemitter 每次 _renderTheme 都会执行,这里的监听挂在 theme 上,
4619
+ // 必须先移除上一次的引用,避免 changeTheme 反复切换导致监听器无限累积(内存泄漏 + 重复执行)。
4620
+ if (theme._onFirstFrameSync) {
4621
+ theme.removeListener(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
4622
+ theme._onFirstFrameSync = null;
4623
+ }
4610
4624
  if (((_theme_controls11 = theme.controls) == null ? void 0 : _theme_controls11.liveControl) || ((_theme_controls12 = theme.controls) == null ? void 0 : _theme_controls12.recDropdownControl)) {
4611
- theme.on(EVENTS.firstFrameDisplay, function() {
4625
+ theme._onFirstFrameSync = function() {
4612
4626
  var _theme_controls, _theme_controls1;
4613
4627
  var urlInfo = theme.urlInfo;
4614
4628
  if ((_theme_controls = theme.controls) == null ? void 0 : _theme_controls.liveControl) {
@@ -4617,7 +4631,8 @@ function debounce(func, wait) {
4617
4631
  if ((_theme_controls1 = theme.controls) == null ? void 0 : _theme_controls1.recDropdownControl) {
4618
4632
  theme.controls.recDropdownControl._syncActiveByUrlInfo(urlInfo);
4619
4633
  }
4620
- });
4634
+ };
4635
+ theme.on(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
4621
4636
  }
4622
4637
  // 缩放控件
4623
4638
  if ((_theme_controls13 = theme.controls) == null ? void 0 : _theme_controls13.zoomControl) {
@@ -5190,15 +5205,20 @@ function _ts_generator$6(thisArg, body) {
5190
5205
  * @returns
5191
5206
  */ function getThemeDataByTemplate(theme, id) {
5192
5207
  return _async_to_generator$6(function() {
5193
- var _theme_options_token_httpToken, _theme_options_token, url;
5208
+ var _theme_options_token_httpToken, _theme_options_token, // 中止上一个在途请求,并为本次请求创建可中止的信号(destroy 时会 abort)
5209
+ _theme__templateAbortController, url, controller;
5194
5210
  return _ts_generator$6(this, function(_state) {
5195
5211
  switch(_state.label){
5196
5212
  case 0:
5197
5213
  url = theme.options.env.domain + "/api/service/media/template/getDetail?accessToken=" + (theme.options.accessToken || ((_theme_options_token = theme.options.token) == null ? void 0 : (_theme_options_token_httpToken = _theme_options_token.httpToken) == null ? void 0 : _theme_options_token_httpToken.url)) + "&id=" + id;
5214
+ (_theme__templateAbortController = theme._templateAbortController) == null ? void 0 : _theme__templateAbortController.abort();
5215
+ controller = new AbortController();
5216
+ theme._templateAbortController = controller;
5198
5217
  return [
5199
5218
  4,
5200
5219
  fetch(url, {
5201
- method: 'GET'
5220
+ method: 'GET',
5221
+ signal: controller == null ? void 0 : controller.signal
5202
5222
  }).then(function(response) {
5203
5223
  return _async_to_generator$6(function() {
5204
5224
  return _ts_generator$6(this, function(_state) {
@@ -5502,7 +5522,7 @@ function _filterLeftRightControls(btnList) {
5502
5522
  * @returns
5503
5523
  */ function getThemeData(theme, data) {
5504
5524
  return _async_to_generator$5(function() {
5505
- var themeData, _theme_logger, template;
5525
+ var themeData, _theme_logger, template, e;
5506
5526
  return _ts_generator$5(this, function(_state) {
5507
5527
  switch(_state.label){
5508
5528
  case 0:
@@ -5548,13 +5568,23 @@ function _filterLeftRightControls(btnList) {
5548
5568
  2,
5549
5569
  template
5550
5570
  ];
5571
+ // 请求返回前已销毁则静默返回,不在已释放的 theme 上派发事件
5572
+ if (theme.destroyed) return [
5573
+ 2,
5574
+ null
5575
+ ];
5551
5576
  theme.emit(EVENTS.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
5552
5577
  return [
5553
5578
  2,
5554
5579
  null
5555
5580
  ];
5556
5581
  case 4:
5557
- _state.sent();
5582
+ e = _state.sent();
5583
+ // 请求被中止(destroy/重新渲染)或已销毁:静默返回
5584
+ if (theme.destroyed || (e == null ? void 0 : e.name) === 'AbortError') return [
5585
+ 2,
5586
+ null
5587
+ ];
5558
5588
  theme.emit(EVENTS.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
5559
5589
  return [
5560
5590
  2,
@@ -9244,6 +9274,11 @@ var _unmountedControls = function(theme) {
9244
9274
  if (theme._onPauseTimingFunc) {
9245
9275
  theme._onPauseTimingFunc = null;
9246
9276
  }
9277
+ // 移除首帧同步监听(挂在 theme 上,需显式解绑,避免 changeTheme 累积)
9278
+ if (theme._onFirstFrameSync) {
9279
+ theme.removeListener(EVENTS.firstFrameDisplay, theme._onFirstFrameSync);
9280
+ theme._onFirstFrameSync = null;
9281
+ }
9247
9282
  if (hasControls) {
9248
9283
  theme.emit(EVENTS.control.unmountedControls);
9249
9284
  }
@@ -9514,6 +9549,10 @@ function _renderTheme(theme, data) {
9514
9549
  ];
9515
9550
  case 1:
9516
9551
  themeData = _state.sent();
9552
+ // 异步获取主题数据期间可能已 destroy(),避免在已释放的 theme 上继续渲染/emit
9553
+ if (theme.destroyed) return [
9554
+ 2
9555
+ ];
9517
9556
  _unmountedControls(theme);
9518
9557
  if (Object.prototype.toString.call(themeData) !== '[object Object]') {
9519
9558
  // 主题空
@@ -10176,7 +10215,15 @@ var THEME_DEFAULT_OPTIONS = {
10176
10215
  // _recMonthObj: Record<string, string[]> = {};
10177
10216
  /**
10178
10217
  * 录像回放的月份列表 @private
10179
- */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
10218
+ */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /**
10219
+ * 首帧同步 Live/RecDropdown 激活态的监听器引用。
10220
+ * 每次 `_renderTheme` 重新绑定前需先移除旧引用,避免 changeTheme 累积监听。
10221
+ * @private
10222
+ */ _this._onFirstFrameSync = null, /**
10223
+ * 模板请求(getDetail)的中止控制器。
10224
+ * 重新渲染或销毁时中止在途请求,避免请求返回后在已销毁/已切换的 theme 上继续操作。
10225
+ * @private
10226
+ */ _this._templateAbortController = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
10180
10227
  _this._initOptions(options);
10181
10228
  if (_this.options.type === 'ezopen') {
10182
10229
  var _this_urlInfo_searchParams1, _this_urlInfo1, _this_urlInfo2;
@@ -10431,12 +10478,15 @@ var THEME_DEFAULT_OPTIONS = {
10431
10478
  * ```
10432
10479
  */ _proto.destroy = function destroy() {
10433
10480
  var _this = this;
10434
- var _this_contentControl, _this_$container;
10481
+ var // 中止在途的模板请求,避免其回调在已销毁的 theme 上继续执行
10482
+ _this__templateAbortController, _this_contentControl, _this_$container;
10435
10483
  if (!this.$container || this.destroyed) {
10436
10484
  // 防止多次销毁
10437
10485
  return;
10438
10486
  }
10439
10487
  this.emit(EVENTS.theme.beforeDestroy);
10488
+ (_this__templateAbortController = this._templateAbortController) == null ? void 0 : _this__templateAbortController.abort();
10489
+ this._templateAbortController = null;
10440
10490
  this._removeEventListener();
10441
10491
  _unmountedControls(this);
10442
10492
  (_this_contentControl = this.contentControl) == null ? void 0 : _this_contentControl.destroy();
@@ -10471,7 +10521,12 @@ var THEME_DEFAULT_OPTIONS = {
10471
10521
  /** 初始化配置项 */ _proto._initOptions = function _initOptions(options) {
10472
10522
  if (options === void 0) options = {};
10473
10523
  var _this_options_loggerOptions, _this_options_definitionOptions_list, _this_options_definitionOptions, _this_options_videoLevelList;
10474
- this.options = deepmerge(THEME_DEFAULT_OPTIONS, options, {
10524
+ // 先对模块级默认配置做一次深拷贝,得到全新的嵌套对象/数组,
10525
+ // 避免 this.options 与 THEME_DEFAULT_OPTIONS(如 mobileExtendOptions.controls、env、loggerOptions)
10526
+ // 共享引用而在多实例间相互污染。
10527
+ // 仍对用户 options 使用 clone:false —— container 可能是 DOM 节点/函数,深拷贝会破坏它。
10528
+ var defaults = deepmerge({}, THEME_DEFAULT_OPTIONS);
10529
+ this.options = deepmerge(defaults, options, {
10475
10530
  clone: false
10476
10531
  });
10477
10532
  this._url = this.options.url;
@@ -10506,10 +10561,12 @@ var THEME_DEFAULT_OPTIONS = {
10506
10561
  this.logger.log('[options] \n', this.options);
10507
10562
  }
10508
10563
  var language = this.options.language || 'zh';
10509
- var locales = deepmerge({
10564
+ // 深拷贝内置语言包,避免与模块级 zh/en 常量共享引用(I18n 若对其做合并/修改会污染全局)
10565
+ var baseLocales = deepmerge({}, {
10510
10566
  zh: zh,
10511
10567
  en: en
10512
- }, this.options.locales || {}, {
10568
+ });
10569
+ var locales = deepmerge(baseLocales, this.options.locales || {}, {
10513
10570
  clone: false
10514
10571
  });
10515
10572
  // prettier-ignore
@@ -11527,6 +11584,6 @@ var THEME_DEFAULT_OPTIONS = {
11527
11584
  zh: zh,
11528
11585
  en: en
11529
11586
  };
11530
- /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.3';
11587
+ /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.4';
11531
11588
 
11532
11589
  export { Control, EVENTS, Fullscreen, Loading, Message, Play, Poster, Rec, Theme, Utils, Volume };
package/dist/index.umd.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.2-beta.3
3
- * Copyright (c) 2026-08-14 08:18:55 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.2-beta.4
3
+ * Copyright (c) 2026-08-16 15:20:04 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  (function (global, factory) {
@@ -641,7 +641,7 @@
641
641
  function Control(options) {
642
642
  var _this;
643
643
  var _this___options;
644
- _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '';
644
+ _this = EventEmitter.call(this) || this, /** 具体语言对应的值 */ _this.locale = null, _this.__options = {}, _this._disabled = false, _this._active = false, _this._camelCaseName = '', /** click 监听引用,销毁时需显式移除 */ _this._onClickHandler = null;
645
645
  _this.__options = options;
646
646
  _this.locale = getLocale(_this.__options.locales, _this.__options.language);
647
647
  _this._camelCaseName = _this.__options.classNameSuffix ? _this.__options.classNameSuffix.replace(/[-_\s]+(.)?/g, function(_, c) {
@@ -730,6 +730,12 @@
730
730
  this.emit("Control." + this._camelCaseName + "Destroy");
731
731
  }
732
732
  if (((_this___options = this.__options) == null ? void 0 : _this___options.controlType) !== 'block') this.$container.removeEventListener('dblclick', this._onDBlClick);
733
+ // 移除 click 监听
734
+ if (this._onClickHandler) {
735
+ var _this_$container1;
736
+ (_this_$container1 = this.$container) == null ? void 0 : _this_$container1.removeEventListener('click', this._onClickHandler);
737
+ this._onClickHandler = null;
738
+ }
733
739
  this._active = false;
734
740
  this.removeAllListeners();
735
741
  (_this_$container = this.$container) == null ? void 0 : (_this_$container_remove = _this_$container.remove) == null ? void 0 : _this_$container_remove.call(_this_$container);
@@ -758,14 +764,16 @@
758
764
  * 当点击 Control 时 触发子类的 _onControlClick
759
765
  */ _proto._onClick = function _onClick() {
760
766
  var _this = this;
761
- this.$container.addEventListener('click', function(e) {
767
+ // 使用具名 handler 便于在 destroy 时精确移除,避免匿名监听残留
768
+ this._onClickHandler = function(e) {
762
769
  var _this_$container;
763
770
  // prettier-ignore
764
771
  if (!((_this_$container = _this.$container) == null ? void 0 : _this_$container.classList.contains("" + PREFIX_CLASS + "-disabled"))) {
765
772
  // _onControlClick 来源自子类中
766
773
  _this._onControlClick == null ? void 0 : _this._onControlClick.call(_this, e);
767
774
  }
768
- });
775
+ };
776
+ this.$container.addEventListener('click', this._onClickHandler);
769
777
  };
770
778
  _proto._onDBlClick = function _onDBlClick(e) {
771
779
  e.stopPropagation();
@@ -6097,8 +6105,14 @@
6097
6105
  }
6098
6106
  // 播放地址切换后同步 Live/RecDropdown 激活状态
6099
6107
  // changePlayUrl 后 urlInfo 已更新,firstFrameDisplay 表示新地址播放成功
6108
+ // 注意:_controlEventemitter 每次 _renderTheme 都会执行,这里的监听挂在 theme 上,
6109
+ // 必须先移除上一次的引用,避免 changeTheme 反复切换导致监听器无限累积(内存泄漏 + 重复执行)。
6110
+ if (theme._onFirstFrameSync) {
6111
+ theme.removeListener(EVENTS$2.firstFrameDisplay, theme._onFirstFrameSync);
6112
+ theme._onFirstFrameSync = null;
6113
+ }
6100
6114
  if (((_theme_controls11 = theme.controls) == null ? void 0 : _theme_controls11.liveControl) || ((_theme_controls12 = theme.controls) == null ? void 0 : _theme_controls12.recDropdownControl)) {
6101
- theme.on(EVENTS$2.firstFrameDisplay, function() {
6115
+ theme._onFirstFrameSync = function() {
6102
6116
  var _theme_controls, _theme_controls1;
6103
6117
  var urlInfo = theme.urlInfo;
6104
6118
  if ((_theme_controls = theme.controls) == null ? void 0 : _theme_controls.liveControl) {
@@ -6107,7 +6121,8 @@
6107
6121
  if ((_theme_controls1 = theme.controls) == null ? void 0 : _theme_controls1.recDropdownControl) {
6108
6122
  theme.controls.recDropdownControl._syncActiveByUrlInfo(urlInfo);
6109
6123
  }
6110
- });
6124
+ };
6125
+ theme.on(EVENTS$2.firstFrameDisplay, theme._onFirstFrameSync);
6111
6126
  }
6112
6127
  // 缩放控件
6113
6128
  if ((_theme_controls13 = theme.controls) == null ? void 0 : _theme_controls13.zoomControl) {
@@ -6687,15 +6702,20 @@
6687
6702
  * @returns
6688
6703
  */ function getThemeDataByTemplate(theme, id) {
6689
6704
  return _async_to_generator$7(function() {
6690
- var _theme_options_token_httpToken, _theme_options_token, url;
6705
+ var _theme_options_token_httpToken, _theme_options_token, // 中止上一个在途请求,并为本次请求创建可中止的信号(destroy 时会 abort)
6706
+ _theme__templateAbortController, url, controller;
6691
6707
  return _ts_generator$7(this, function(_state) {
6692
6708
  switch(_state.label){
6693
6709
  case 0:
6694
6710
  url = theme.options.env.domain + "/api/service/media/template/getDetail?accessToken=" + (theme.options.accessToken || ((_theme_options_token = theme.options.token) == null ? void 0 : (_theme_options_token_httpToken = _theme_options_token.httpToken) == null ? void 0 : _theme_options_token_httpToken.url)) + "&id=" + id;
6711
+ (_theme__templateAbortController = theme._templateAbortController) == null ? void 0 : _theme__templateAbortController.abort();
6712
+ controller = new AbortController();
6713
+ theme._templateAbortController = controller;
6695
6714
  return [
6696
6715
  4,
6697
6716
  fetch(url, {
6698
- method: 'GET'
6717
+ method: 'GET',
6718
+ signal: controller == null ? void 0 : controller.signal
6699
6719
  }).then(function(response) {
6700
6720
  return _async_to_generator$7(function() {
6701
6721
  return _ts_generator$7(this, function(_state) {
@@ -6999,7 +7019,7 @@
6999
7019
  * @returns
7000
7020
  */ function getThemeData(theme, data) {
7001
7021
  return _async_to_generator$6(function() {
7002
- var themeData, _theme_logger, template;
7022
+ var themeData, _theme_logger, template, e;
7003
7023
  return _ts_generator$6(this, function(_state) {
7004
7024
  switch(_state.label){
7005
7025
  case 0:
@@ -7045,13 +7065,23 @@
7045
7065
  2,
7046
7066
  template
7047
7067
  ];
7068
+ // 请求返回前已销毁则静默返回,不在已释放的 theme 上派发事件
7069
+ if (theme.destroyed) return [
7070
+ 2,
7071
+ null
7072
+ ];
7048
7073
  theme.emit(EVENTS$2.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
7049
7074
  return [
7050
7075
  2,
7051
7076
  null
7052
7077
  ];
7053
7078
  case 4:
7054
- _state.sent();
7079
+ e = _state.sent();
7080
+ // 请求被中止(destroy/重新渲染)或已销毁:静默返回
7081
+ if (theme.destroyed || (e == null ? void 0 : e.name) === 'AbortError') return [
7082
+ 2,
7083
+ null
7084
+ ];
7055
7085
  theme.emit(EVENTS$2.message, theme.i18n.t('FETCH_THEME_FAILED'), 'themeError');
7056
7086
  return [
7057
7087
  2,
@@ -11590,6 +11620,11 @@
11590
11620
  if (theme._onPauseTimingFunc) {
11591
11621
  theme._onPauseTimingFunc = null;
11592
11622
  }
11623
+ // 移除首帧同步监听(挂在 theme 上,需显式解绑,避免 changeTheme 累积)
11624
+ if (theme._onFirstFrameSync) {
11625
+ theme.removeListener(EVENTS$2.firstFrameDisplay, theme._onFirstFrameSync);
11626
+ theme._onFirstFrameSync = null;
11627
+ }
11593
11628
  if (hasControls) {
11594
11629
  theme.emit(EVENTS$2.control.unmountedControls);
11595
11630
  }
@@ -11860,6 +11895,10 @@
11860
11895
  ];
11861
11896
  case 1:
11862
11897
  themeData = _state.sent();
11898
+ // 异步获取主题数据期间可能已 destroy(),避免在已释放的 theme 上继续渲染/emit
11899
+ if (theme.destroyed) return [
11900
+ 2
11901
+ ];
11863
11902
  _unmountedControls(theme);
11864
11903
  if (Object.prototype.toString.call(themeData) !== '[object Object]') {
11865
11904
  // 主题空
@@ -12522,7 +12561,15 @@
12522
12561
  // _recMonthObj: Record<string, string[]> = {};
12523
12562
  /**
12524
12563
  * 录像回放的月份列表 @private
12525
- */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
12564
+ */ _this.recMonth = [], /** 清理 header/footer 动画 定时器 @private */ _this._onPauseTimingFunc = null, /**
12565
+ * 首帧同步 Live/RecDropdown 激活态的监听器引用。
12566
+ * 每次 `_renderTheme` 重新绑定前需先移除旧引用,避免 changeTheme 累积监听。
12567
+ * @private
12568
+ */ _this._onFirstFrameSync = null, /**
12569
+ * 模板请求(getDetail)的中止控制器。
12570
+ * 重新渲染或销毁时中止在途请求,避免请求返回后在已销毁/已切换的 theme 上继续操作。
12571
+ * @private
12572
+ */ _this._templateAbortController = null, /** 销毁标识 @readonly */ _this.destroyed = false, _this.scaleMode = 0, _this._videoInfo = {};
12526
12573
  _this._initOptions(options);
12527
12574
  if (_this.options.type === 'ezopen') {
12528
12575
  var _this_urlInfo_searchParams1, _this_urlInfo1, _this_urlInfo2;
@@ -12777,12 +12824,15 @@
12777
12824
  * ```
12778
12825
  */ _proto.destroy = function destroy() {
12779
12826
  var _this = this;
12780
- var _this_contentControl, _this_$container;
12827
+ var // 中止在途的模板请求,避免其回调在已销毁的 theme 上继续执行
12828
+ _this__templateAbortController, _this_contentControl, _this_$container;
12781
12829
  if (!this.$container || this.destroyed) {
12782
12830
  // 防止多次销毁
12783
12831
  return;
12784
12832
  }
12785
12833
  this.emit(EVENTS$2.theme.beforeDestroy);
12834
+ (_this__templateAbortController = this._templateAbortController) == null ? void 0 : _this__templateAbortController.abort();
12835
+ this._templateAbortController = null;
12786
12836
  this._removeEventListener();
12787
12837
  _unmountedControls(this);
12788
12838
  (_this_contentControl = this.contentControl) == null ? void 0 : _this_contentControl.destroy();
@@ -12817,7 +12867,12 @@
12817
12867
  /** 初始化配置项 */ _proto._initOptions = function _initOptions(options) {
12818
12868
  if (options === void 0) options = {};
12819
12869
  var _this_options_loggerOptions, _this_options_definitionOptions_list, _this_options_definitionOptions, _this_options_videoLevelList;
12820
- this.options = deepmerge(THEME_DEFAULT_OPTIONS, options, {
12870
+ // 先对模块级默认配置做一次深拷贝,得到全新的嵌套对象/数组,
12871
+ // 避免 this.options 与 THEME_DEFAULT_OPTIONS(如 mobileExtendOptions.controls、env、loggerOptions)
12872
+ // 共享引用而在多实例间相互污染。
12873
+ // 仍对用户 options 使用 clone:false —— container 可能是 DOM 节点/函数,深拷贝会破坏它。
12874
+ var defaults = deepmerge({}, THEME_DEFAULT_OPTIONS);
12875
+ this.options = deepmerge(defaults, options, {
12821
12876
  clone: false
12822
12877
  });
12823
12878
  this._url = this.options.url;
@@ -12852,10 +12907,12 @@
12852
12907
  this.logger.log('[options] \n', this.options);
12853
12908
  }
12854
12909
  var language = this.options.language || 'zh';
12855
- var locales = deepmerge({
12910
+ // 深拷贝内置语言包,避免与模块级 zh/en 常量共享引用(I18n 若对其做合并/修改会污染全局)
12911
+ var baseLocales = deepmerge({}, {
12856
12912
  zh: zh,
12857
12913
  en: en
12858
- }, this.options.locales || {}, {
12914
+ });
12915
+ var locales = deepmerge(baseLocales, this.options.locales || {}, {
12859
12916
  clone: false
12860
12917
  });
12861
12918
  // prettier-ignore
@@ -13873,7 +13930,7 @@
13873
13930
  zh: zh,
13874
13931
  en: en
13875
13932
  };
13876
- /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.3';
13933
+ /** 版本号 @since 0.0.1 */ Theme.THEME_VERSION = '3.1.2-beta.4';
13877
13934
 
13878
13935
  // 不要动这里的代码, 这个出口是为了编译成 umd 规范的文件
13879
13936
 
package/dist/style.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
- * @ezuikit/player-theme v3.1.2-beta.3
3
- * Copyright (c) 2026-08-14 08:18:55 Ezviz-OpenBiz
2
+ * @ezuikit/player-theme v3.1.2-beta.4
3
+ * Copyright (c) 2026-08-16 15:20:04 Ezviz-OpenBiz
4
4
  * Released under the MIT License.
5
5
  */
6
6
  require("./style.css");
@@ -342,6 +342,8 @@ declare class Control extends EventEmitter {
342
342
  protected _disabled: boolean;
343
343
  protected _active: boolean;
344
344
  private readonly _camelCaseName;
345
+ /** click 监听引用,销毁时需显式移除 */
346
+ private _onClickHandler;
345
347
  constructor(options: Partial<ControlOptions>);
346
348
  /**
347
349
  * 是否激活
@@ -1888,6 +1890,11 @@ declare class Theme extends EventEmitter {
1888
1890
  SET_FEC_PARAMS: string;
1889
1891
  GET_FEC_PARAMS: string;
1890
1892
  SET_FEC_PARAMS_FAILED: string;
1893
+ /**
1894
+ * 模板请求(getDetail)的中止控制器。
1895
+ * 重新渲染或销毁时中止在途请求,避免请求返回后在已销毁/已切换的 theme 上继续操作。
1896
+ * @private
1897
+ */
1891
1898
  GET_FEC_PARAMS_FAILED: string;
1892
1899
  GET_FEC_PARAMS_SUPPORT_VERSION: string;
1893
1900
  SET_WATERMARK: string;
@@ -2067,8 +2074,11 @@ declare class Theme extends EventEmitter {
2067
2074
  CHANGE_VIDEO_LEVEL_FAIL: string;
2068
2075
  GET_VIDEO_LEVEL_LIST: string;
2069
2076
  /**
2070
- * 视频分辨率 高
2077
+ * 视频信息
2071
2078
  * @version 3.1.2
2079
+ * ```ts
2080
+ * theme.videoInfo // ThemeVideoInfo
2081
+ * ```
2072
2082
  */
2073
2083
  PLEASE_INPUT_RIGHT_VIDEO_LEVEL: string;
2074
2084
  VIDEO_LEVEL_NOT_SUPPORT: string;
@@ -2076,11 +2086,19 @@ declare class Theme extends EventEmitter {
2076
2086
  VIDEO_LEVEL_FLUENT: string;
2077
2087
  VIDEO_LEVEL_STANDARD: string;
2078
2088
  VIDEO_LEVEL_HEIGH: string;
2079
- VIDEO_LEVEL_SUPER: string;
2089
+ VIDEO_LEVEL_SUPER: string; /**
2090
+ * 视频分辨率 高
2091
+ * @version 3.1.2
2092
+ */
2080
2093
  VIDEO_LEVEL_EXTREME: string;
2081
2094
  VIDEO_LEVEL_3K: string;
2082
2095
  VIDEO_LEVEL_4k: string;
2083
- RESET_THEME: string;
2096
+ RESET_THEME: string; /**
2097
+ * 当前播放状态
2098
+ * ```ts
2099
+ * theme.playing // boolean
2100
+ * ```
2101
+ */
2084
2102
  BTN_PLAY: string;
2085
2103
  BTN_PAUSE: string;
2086
2104
  BTN_VOLUME: string;
@@ -2117,11 +2135,14 @@ declare class Theme extends EventEmitter {
2117
2135
  DEVICE_ID: string;
2118
2136
  CAPTURE_SUCCESS: string;
2119
2137
  CAPTURE_FAILED: string;
2120
- START_RECORD_SUCCESS: string;
2121
- START_RECORD_FAILED: string;
2122
- /**
2123
- * 音量值
2138
+ START_RECORD_SUCCESS: string; /**
2139
+ * 加载状态
2140
+ * ```ts
2141
+ * // 事件监听
2142
+ * theme.on(Theme.EVENTS.loading, (loading: boolean) => {})
2143
+ * ```
2124
2144
  */
2145
+ START_RECORD_FAILED: string;
2125
2146
  STOP_RECORD_SUCCESS: string;
2126
2147
  STOP_RECORD_FAILED: string;
2127
2148
  RECORD_TIPS: string;
@@ -2138,10 +2159,6 @@ declare class Theme extends EventEmitter {
2138
2159
  ZOOM_SUB_MIN: string;
2139
2160
  ZOOM_LIMIT_MAX: string;
2140
2161
  ZOOM_LIMIT_MIN: string;
2141
- /**
2142
- * 静音
2143
- *
2144
- */
2145
2162
  ZOOM_NOT_ENABLED: string;
2146
2163
  '3D_ZOOM': string;
2147
2164
  '3D_ZOOM_DISABLE': string;
@@ -2302,6 +2319,18 @@ declare class Theme extends EventEmitter {
2302
2319
  recMonth: string[];
2303
2320
  /** 清理 header/footer 动画 定时器 @private */
2304
2321
  _onPauseTimingFunc: ((open: boolean) => void) | null;
2322
+ /**
2323
+ * 首帧同步 Live/RecDropdown 激活态的监听器引用。
2324
+ * 每次 `_renderTheme` 重新绑定前需先移除旧引用,避免 changeTheme 累积监听。
2325
+ * @private
2326
+ */
2327
+ _onFirstFrameSync: (() => void) | null;
2328
+ /**
2329
+ * 模板请求(getDetail)的中止控制器。
2330
+ * 重新渲染或销毁时中止在途请求,避免请求返回后在已销毁/已切换的 theme 上继续操作。
2331
+ * @private
2332
+ */
2333
+ _templateAbortController: AbortController | null;
2305
2334
  /** 销毁标识 @readonly */
2306
2335
  destroyed: boolean;
2307
2336
  scaleMode: ThemeOptions['scaleMode'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezuikit/player-theme",
3
- "version": "3.1.2-beta.3",
3
+ "version": "3.1.2-beta.4",
4
4
  "description": "player theme",
5
5
  "title": "theme",
6
6
  "main": "dist/index.cjs",