@x-plat/design-system 0.5.4 → 0.5.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/dist/index.css CHANGED
@@ -3609,6 +3609,7 @@
3609
3609
  width: 100%;
3610
3610
  height: 100%;
3611
3611
  position: relative;
3612
+ overflow: auto;
3612
3613
  }
3613
3614
  .lib-xplat-table-wrapper > .lib-xplat-table {
3614
3615
  width: 100%;
@@ -3681,6 +3682,20 @@
3681
3682
  min-width: 80px;
3682
3683
  padding: var(--spacing-space-2);
3683
3684
  vertical-align: middle;
3685
+ word-break: keep-all;
3686
+ overflow-wrap: anywhere;
3687
+ }
3688
+ .lib-xplat-table-wrapper > .lib-xplat-table > thead > tr > td.nowrap,
3689
+ .lib-xplat-table-wrapper > .lib-xplat-table > thead > tr > th.nowrap,
3690
+ .lib-xplat-table-wrapper > .lib-xplat-table > tbody > tr > td.nowrap,
3691
+ .lib-xplat-table-wrapper > .lib-xplat-table > tbody > tr > th.nowrap {
3692
+ white-space: nowrap;
3693
+ overflow-wrap: normal;
3694
+ }
3695
+ .lib-xplat-table-wrapper > .lib-xplat-table > thead > tr > td,
3696
+ .lib-xplat-table-wrapper > .lib-xplat-table > thead > tr > th,
3697
+ .lib-xplat-table-wrapper > .lib-xplat-table > tbody > tr > td,
3698
+ .lib-xplat-table-wrapper > .lib-xplat-table > tbody > tr > th {
3684
3699
  transition: background-color 0.28s cubic-bezier(0.25, 0.46, 0.45, 0.94);
3685
3700
  }
3686
3701
  .lib-xplat-table-wrapper > .lib-xplat-table > thead > tr > td.clickable,
@@ -4064,11 +4079,9 @@
4064
4079
  max-height: 100%;
4065
4080
  object-fit: contain;
4066
4081
  vertical-align: middle;
4067
- }
4068
- .lib-xplat-video.custom-overlay > video {
4069
4082
  cursor: pointer;
4070
4083
  }
4071
- .lib-xplat-video.custom-overlay > .play-overlay {
4084
+ .lib-xplat-video > .center-play {
4072
4085
  position: absolute;
4073
4086
  top: 0;
4074
4087
  left: 0;
@@ -4082,9 +4095,10 @@
4082
4095
  cursor: pointer;
4083
4096
  padding: 0;
4084
4097
  color: var(--semantic-icon-inverse);
4085
- transition: opacity 0.2s ease, background-color 0.2s ease;
4098
+ transition: opacity 0.2s ease;
4099
+ pointer-events: none;
4086
4100
  }
4087
- .lib-xplat-video.custom-overlay > .play-overlay::before {
4101
+ .lib-xplat-video > .center-play::before {
4088
4102
  content: "";
4089
4103
  position: absolute;
4090
4104
  inset: 0;
@@ -4092,34 +4106,217 @@
4092
4106
  opacity: 0;
4093
4107
  transition: opacity 0.2s ease;
4094
4108
  }
4095
- .lib-xplat-video.custom-overlay > .play-overlay:hover::before,
4096
- .lib-xplat-video.custom-overlay > .play-overlay:focus-visible::before {
4097
- opacity: 1;
4098
- }
4099
- .lib-xplat-video.custom-overlay > .play-overlay:focus-visible {
4100
- outline: 2px solid var(--semantic-interaction-focus-ring);
4101
- outline-offset: 2px;
4102
- }
4103
- .lib-xplat-video.custom-overlay > .play-overlay > .play-icon {
4109
+ .lib-xplat-video > .center-play > .center-play-icon {
4104
4110
  position: relative;
4105
4111
  z-index: 1;
4106
4112
  display: flex;
4107
- align-items: center;
4108
- justify-content: center;
4109
4113
  font-size: 64px;
4110
4114
  filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.4));
4111
4115
  }
4112
- .lib-xplat-video.custom-overlay > .play-overlay.is-playing {
4116
+ .lib-xplat-video > .center-play.is-playing {
4113
4117
  opacity: 0;
4114
- pointer-events: none;
4115
4118
  }
4116
- .lib-xplat-video.custom-overlay > .play-overlay.is-loading .play-icon {
4119
+ .lib-xplat-video > .center-play.is-loading .center-play-icon {
4117
4120
  opacity: 0.6;
4118
4121
  }
4119
- .lib-xplat-video.custom-overlay:hover > .play-overlay.is-playing {
4122
+ .lib-xplat-video > .controls {
4123
+ position: absolute;
4124
+ left: 0;
4125
+ right: 0;
4126
+ bottom: 0;
4127
+ padding: var(--spacing-space-2) var(--spacing-space-3);
4128
+ display: flex;
4129
+ flex-direction: column;
4130
+ gap: var(--spacing-space-1);
4131
+ background:
4132
+ linear-gradient(
4133
+ to top,
4134
+ rgba(0, 0, 0, 0.7),
4135
+ rgba(0, 0, 0, 0));
4136
+ color: var(--semantic-icon-inverse);
4137
+ opacity: 0;
4138
+ transition: opacity 0.2s ease;
4139
+ pointer-events: none;
4140
+ }
4141
+ .lib-xplat-video:hover > .controls,
4142
+ .lib-xplat-video:focus-within > .controls {
4120
4143
  opacity: 1;
4121
4144
  pointer-events: auto;
4122
4145
  }
4146
+ .lib-xplat-video .controls-row {
4147
+ display: flex;
4148
+ align-items: center;
4149
+ gap: var(--spacing-space-2);
4150
+ }
4151
+ .lib-xplat-video .control-btn {
4152
+ display: inline-flex;
4153
+ align-items: center;
4154
+ justify-content: center;
4155
+ width: 32px;
4156
+ height: 32px;
4157
+ padding: 0;
4158
+ border: none;
4159
+ background: transparent;
4160
+ color: inherit;
4161
+ cursor: pointer;
4162
+ border-radius: var(--spacing-radius-sm);
4163
+ transition: background-color 0.15s ease;
4164
+ }
4165
+ .lib-xplat-video .control-btn:hover {
4166
+ background-color: rgba(255, 255, 255, 0.15);
4167
+ }
4168
+ .lib-xplat-video .control-btn:focus-visible {
4169
+ outline: 2px solid var(--semantic-interaction-focus-ring);
4170
+ outline-offset: 2px;
4171
+ }
4172
+ .lib-xplat-video .controls-spacer {
4173
+ margin-left: auto;
4174
+ }
4175
+ .lib-xplat-video .control-btn.is-active {
4176
+ background-color: rgba(255, 255, 255, 0.25);
4177
+ }
4178
+ .lib-xplat-video .rate-group {
4179
+ position: relative;
4180
+ }
4181
+ .lib-xplat-video .rate-group .rate-btn {
4182
+ width: auto;
4183
+ padding: 0 var(--spacing-space-2);
4184
+ font-size: 12px;
4185
+ font-weight: 600;
4186
+ font-variant-numeric: tabular-nums;
4187
+ }
4188
+ .lib-xplat-video .rate-group .rate-menu {
4189
+ position: absolute;
4190
+ bottom: calc(100% + var(--spacing-space-1));
4191
+ right: 0;
4192
+ margin: 0;
4193
+ padding: var(--spacing-space-1);
4194
+ list-style: none;
4195
+ background-color: rgba(0, 0, 0, 0.85);
4196
+ border-radius: var(--spacing-radius-sm);
4197
+ min-width: 64px;
4198
+ }
4199
+ .lib-xplat-video .rate-group .rate-menu .rate-item {
4200
+ width: 100%;
4201
+ padding: var(--spacing-space-1) var(--spacing-space-2);
4202
+ border: none;
4203
+ background: transparent;
4204
+ color: inherit;
4205
+ text-align: left;
4206
+ cursor: pointer;
4207
+ border-radius: var(--spacing-radius-xs);
4208
+ font-size: 12px;
4209
+ font-variant-numeric: tabular-nums;
4210
+ }
4211
+ .lib-xplat-video .rate-group .rate-menu .rate-item:hover {
4212
+ background-color: rgba(255, 255, 255, 0.15);
4213
+ }
4214
+ .lib-xplat-video .rate-group .rate-menu .rate-item.is-active {
4215
+ color: var(--semantic-surface-brand-default);
4216
+ font-weight: 600;
4217
+ }
4218
+ .lib-xplat-video .time {
4219
+ font-size: 12px;
4220
+ font-variant-numeric: tabular-nums;
4221
+ white-space: nowrap;
4222
+ }
4223
+ .lib-xplat-video .volume-group {
4224
+ display: flex;
4225
+ align-items: center;
4226
+ }
4227
+ .lib-xplat-video .volume-group .volume-slider {
4228
+ width: 0;
4229
+ opacity: 0;
4230
+ transition: width 0.2s ease, opacity 0.2s ease;
4231
+ }
4232
+ .lib-xplat-video .volume-group:hover .volume-slider,
4233
+ .lib-xplat-video .volume-group:focus-within .volume-slider {
4234
+ width: 80px;
4235
+ opacity: 1;
4236
+ margin-left: var(--spacing-space-1);
4237
+ }
4238
+ .lib-xplat-video .seekbar,
4239
+ .lib-xplat-video .volume-slider {
4240
+ -webkit-appearance: none;
4241
+ appearance: none;
4242
+ background: transparent;
4243
+ cursor: pointer;
4244
+ }
4245
+ .lib-xplat-video .seekbar:focus,
4246
+ .lib-xplat-video .volume-slider:focus {
4247
+ outline: none;
4248
+ }
4249
+ .lib-xplat-video .seekbar::-webkit-slider-thumb,
4250
+ .lib-xplat-video .volume-slider::-webkit-slider-thumb {
4251
+ -webkit-appearance: none;
4252
+ appearance: none;
4253
+ width: 12px;
4254
+ height: 12px;
4255
+ border-radius: 50%;
4256
+ background: #fff;
4257
+ border: none;
4258
+ cursor: pointer;
4259
+ }
4260
+ .lib-xplat-video .seekbar::-moz-range-thumb,
4261
+ .lib-xplat-video .volume-slider::-moz-range-thumb {
4262
+ width: 12px;
4263
+ height: 12px;
4264
+ border-radius: 50%;
4265
+ background: #fff;
4266
+ border: none;
4267
+ cursor: pointer;
4268
+ }
4269
+ .lib-xplat-video .seekbar {
4270
+ width: 100%;
4271
+ height: 4px;
4272
+ }
4273
+ .lib-xplat-video .seekbar::-webkit-slider-runnable-track {
4274
+ height: 4px;
4275
+ border-radius: 2px;
4276
+ background:
4277
+ linear-gradient(
4278
+ to right,
4279
+ var(--semantic-surface-brand-default) 0%,
4280
+ var(--semantic-surface-brand-default) var(--progress, 0%),
4281
+ rgba(255, 255, 255, 0.4) var(--progress, 0%),
4282
+ rgba(255, 255, 255, 0.4) var(--buffered, 0%),
4283
+ rgba(255, 255, 255, 0.2) var(--buffered, 0%),
4284
+ rgba(255, 255, 255, 0.2) 100%);
4285
+ }
4286
+ .lib-xplat-video .seekbar::-moz-range-track {
4287
+ height: 4px;
4288
+ border-radius: 2px;
4289
+ background: rgba(255, 255, 255, 0.2);
4290
+ }
4291
+ .lib-xplat-video .seekbar::-moz-range-progress {
4292
+ height: 4px;
4293
+ border-radius: 2px;
4294
+ background: var(--semantic-surface-brand-default);
4295
+ }
4296
+ .lib-xplat-video .volume-slider {
4297
+ height: 4px;
4298
+ }
4299
+ .lib-xplat-video .volume-slider::-webkit-slider-runnable-track {
4300
+ height: 4px;
4301
+ border-radius: 2px;
4302
+ background:
4303
+ linear-gradient(
4304
+ to right,
4305
+ #fff 0%,
4306
+ #fff var(--volume, 0%),
4307
+ rgba(255, 255, 255, 0.3) var(--volume, 0%),
4308
+ rgba(255, 255, 255, 0.3) 100%);
4309
+ }
4310
+ .lib-xplat-video .volume-slider::-moz-range-track {
4311
+ height: 4px;
4312
+ border-radius: 2px;
4313
+ background: rgba(255, 255, 255, 0.3);
4314
+ }
4315
+ .lib-xplat-video .volume-slider::-moz-range-progress {
4316
+ height: 4px;
4317
+ border-radius: 2px;
4318
+ background: #fff;
4319
+ }
4123
4320
 
4124
4321
  /* src/layout/Grid/FullGrid/fullgrid.scss */
4125
4322
  .lib-xplat-full-grid {
package/dist/index.js CHANGED
@@ -8577,6 +8577,8 @@ var TableCell = React33.memo((props) => {
8577
8577
  children,
8578
8578
  align = "center",
8579
8579
  isSticky = false,
8580
+ width,
8581
+ nowrap = false,
8580
8582
  onClick
8581
8583
  } = props;
8582
8584
  const { registerStickyCell, stickyCells } = useTableRowContext();
@@ -8620,9 +8622,13 @@ var TableCell = React33.memo((props) => {
8620
8622
  isSticky && "table-sticky",
8621
8623
  isLastSticky && stickyShadow && "right-shadow",
8622
8624
  onClick && "clickable",
8623
- enableHover && "cell-hover"
8625
+ enableHover && "cell-hover",
8626
+ nowrap && "nowrap"
8624
8627
  ),
8625
- style: isSticky ? { left } : void 0,
8628
+ style: {
8629
+ ...isSticky ? { left } : null,
8630
+ ...width != null ? { width: typeof width === "number" ? `${width}px` : width } : null
8631
+ },
8626
8632
  onClick,
8627
8633
  children
8628
8634
  }
@@ -8878,6 +8884,16 @@ var Tooltip_default = Tooltip;
8878
8884
  // src/components/Video/Video.tsx
8879
8885
  import React38 from "react";
8880
8886
  import { jsx as jsx346, jsxs as jsxs221 } from "react/jsx-runtime";
8887
+ var PipIcon = () => /* @__PURE__ */ jsxs221("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
8888
+ /* @__PURE__ */ jsx346("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
8889
+ /* @__PURE__ */ jsx346("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
8890
+ ] });
8891
+ var formatTime = (sec) => {
8892
+ if (!Number.isFinite(sec) || sec < 0) return "0:00";
8893
+ const m = Math.floor(sec / 60);
8894
+ const s = Math.floor(sec % 60);
8895
+ return `${m}:${s.toString().padStart(2, "0")}`;
8896
+ };
8881
8897
  var Video = React38.forwardRef((props, ref) => {
8882
8898
  const {
8883
8899
  src,
@@ -8886,13 +8902,36 @@ var Video = React38.forwardRef((props, ref) => {
8886
8902
  muted,
8887
8903
  loop,
8888
8904
  playsInline,
8905
+ showControls = true,
8906
+ showCenterPlay = true,
8907
+ playbackRates,
8908
+ showCaptions = false,
8909
+ showPip = false,
8910
+ showDownload = false,
8911
+ downloadFileName,
8889
8912
  onPlay,
8890
8913
  onPause,
8914
+ onTimeUpdate,
8915
+ onVolumeChange,
8916
+ onLoadedMetadata,
8917
+ onRateChange,
8918
+ children,
8891
8919
  ...rest
8892
8920
  } = props;
8921
+ const containerRef = React38.useRef(null);
8893
8922
  const videoRef = React38.useRef(null);
8894
8923
  const [isPlaying, setIsPlaying] = React38.useState(Boolean(autoPlay));
8895
8924
  const [isLoaded, setIsLoaded] = React38.useState(false);
8925
+ const [currentTime, setCurrentTime] = React38.useState(0);
8926
+ const [duration, setDuration] = React38.useState(0);
8927
+ const [buffered, setBuffered] = React38.useState(0);
8928
+ const [volume, setVolume] = React38.useState(1);
8929
+ const [isMuted, setIsMuted] = React38.useState(Boolean(muted));
8930
+ const [isFullscreen, setIsFullscreen] = React38.useState(false);
8931
+ const [playbackRate, setPlaybackRate] = React38.useState(1);
8932
+ const [rateMenuOpen, setRateMenuOpen] = React38.useState(false);
8933
+ const [captionsOn, setCaptionsOn] = React38.useState(false);
8934
+ const [isPip, setIsPip] = React38.useState(false);
8896
8935
  const setRefs = React38.useCallback(
8897
8936
  (el) => {
8898
8937
  videoRef.current = el;
@@ -8901,6 +8940,25 @@ var Video = React38.forwardRef((props, ref) => {
8901
8940
  },
8902
8941
  [ref]
8903
8942
  );
8943
+ React38.useEffect(() => {
8944
+ const onFsChange = () => {
8945
+ setIsFullscreen(document.fullscreenElement === containerRef.current);
8946
+ };
8947
+ document.addEventListener("fullscreenchange", onFsChange);
8948
+ return () => document.removeEventListener("fullscreenchange", onFsChange);
8949
+ }, []);
8950
+ React38.useEffect(() => {
8951
+ const v = videoRef.current;
8952
+ if (!v) return;
8953
+ const onEnter = () => setIsPip(true);
8954
+ const onLeave = () => setIsPip(false);
8955
+ v.addEventListener("enterpictureinpicture", onEnter);
8956
+ v.addEventListener("leavepictureinpicture", onLeave);
8957
+ return () => {
8958
+ v.removeEventListener("enterpictureinpicture", onEnter);
8959
+ v.removeEventListener("leavepictureinpicture", onLeave);
8960
+ };
8961
+ }, []);
8904
8962
  const handlePlay = (e) => {
8905
8963
  setIsPlaying(true);
8906
8964
  onPlay?.(e);
@@ -8909,50 +8967,278 @@ var Video = React38.forwardRef((props, ref) => {
8909
8967
  setIsPlaying(false);
8910
8968
  onPause?.(e);
8911
8969
  };
8912
- const handleLoadedData = () => {
8970
+ const handleLoadedMetadata = (e) => {
8971
+ const v = e.currentTarget;
8972
+ setDuration(v.duration);
8913
8973
  setIsLoaded(true);
8974
+ onLoadedMetadata?.(e);
8975
+ };
8976
+ const handleTimeUpdate = (e) => {
8977
+ const v = e.currentTarget;
8978
+ setCurrentTime(v.currentTime);
8979
+ if (v.buffered.length > 0) {
8980
+ setBuffered(v.buffered.end(v.buffered.length - 1));
8981
+ }
8982
+ onTimeUpdate?.(e);
8983
+ };
8984
+ const handleVolumeChange = (e) => {
8985
+ const v = e.currentTarget;
8986
+ setVolume(v.volume);
8987
+ setIsMuted(v.muted);
8988
+ onVolumeChange?.(e);
8989
+ };
8990
+ const handleRateChange = (e) => {
8991
+ setPlaybackRate(e.currentTarget.playbackRate);
8992
+ onRateChange?.(e);
8914
8993
  };
8915
8994
  const togglePlay = () => {
8916
- if (!videoRef.current) return;
8917
- if (isPlaying) {
8918
- videoRef.current.pause();
8995
+ const v = videoRef.current;
8996
+ if (!v) return;
8997
+ if (v.paused) v.play();
8998
+ else v.pause();
8999
+ };
9000
+ const toggleMute = () => {
9001
+ const v = videoRef.current;
9002
+ if (!v) return;
9003
+ v.muted = !v.muted;
9004
+ };
9005
+ const toggleFullscreen = () => {
9006
+ const el = containerRef.current;
9007
+ if (!el) return;
9008
+ if (document.fullscreenElement === el) {
9009
+ document.exitFullscreen();
8919
9010
  } else {
8920
- videoRef.current.play();
9011
+ el.requestFullscreen?.();
8921
9012
  }
8922
9013
  };
8923
- return /* @__PURE__ */ jsxs221("div", { className: "lib-xplat-video custom-overlay", children: [
8924
- /* @__PURE__ */ jsx346(
8925
- "video",
8926
- {
8927
- ref: setRefs,
8928
- src,
8929
- poster,
8930
- autoPlay,
8931
- muted,
8932
- loop,
8933
- playsInline: playsInline ?? true,
8934
- onPlay: handlePlay,
8935
- onPause: handlePause,
8936
- onLoadedData: handleLoadedData,
8937
- onClick: togglePlay,
8938
- ...rest
9014
+ const togglePip = async () => {
9015
+ const v = videoRef.current;
9016
+ if (!v) return;
9017
+ try {
9018
+ if (document.pictureInPictureElement === v) {
9019
+ await document.exitPictureInPicture?.();
9020
+ } else {
9021
+ await v.requestPictureInPicture?.();
8939
9022
  }
8940
- ),
8941
- /* @__PURE__ */ jsx346(
8942
- "button",
8943
- {
8944
- type: "button",
8945
- className: clsx_default(
8946
- "play-overlay",
8947
- isPlaying && "is-playing",
8948
- !isLoaded && "is-loading"
8949
- ),
8950
- onClick: togglePlay,
8951
- "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
8952
- children: isPlaying ? /* @__PURE__ */ jsx346(PauseIcon_default, {}) : /* @__PURE__ */ jsx346("span", { className: "play-icon", children: /* @__PURE__ */ jsx346(PlayCircleIcon_default, {}) })
9023
+ } catch {
9024
+ }
9025
+ };
9026
+ const toggleCaptions = () => {
9027
+ const v = videoRef.current;
9028
+ if (!v) return;
9029
+ const next = !captionsOn;
9030
+ for (let i = 0; i < v.textTracks.length; i++) {
9031
+ const t = v.textTracks[i];
9032
+ if (t.kind === "captions" || t.kind === "subtitles") {
9033
+ t.mode = next ? "showing" : "hidden";
8953
9034
  }
8954
- )
8955
- ] });
9035
+ }
9036
+ setCaptionsOn(next);
9037
+ };
9038
+ const selectRate = (rate) => {
9039
+ const v = videoRef.current;
9040
+ if (!v) return;
9041
+ v.playbackRate = rate;
9042
+ setRateMenuOpen(false);
9043
+ };
9044
+ const handleSeek = (e) => {
9045
+ const v = videoRef.current;
9046
+ if (!v) return;
9047
+ const next = Number(e.target.value);
9048
+ v.currentTime = next;
9049
+ setCurrentTime(next);
9050
+ };
9051
+ const handleVolumeSlider = (e) => {
9052
+ const v = videoRef.current;
9053
+ if (!v) return;
9054
+ const next = Number(e.target.value);
9055
+ v.volume = next;
9056
+ if (next > 0 && v.muted) v.muted = false;
9057
+ if (next === 0) v.muted = true;
9058
+ };
9059
+ const progressPct = duration > 0 ? currentTime / duration * 100 : 0;
9060
+ const bufferedPct = duration > 0 ? buffered / duration * 100 : 0;
9061
+ const volumePct = (isMuted ? 0 : volume) * 100;
9062
+ const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
9063
+ const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
9064
+ return /* @__PURE__ */ jsxs221(
9065
+ "div",
9066
+ {
9067
+ ref: containerRef,
9068
+ className: clsx_default("lib-xplat-video", showControls && "has-controls"),
9069
+ children: [
9070
+ /* @__PURE__ */ jsx346(
9071
+ "video",
9072
+ {
9073
+ ref: setRefs,
9074
+ src,
9075
+ poster,
9076
+ autoPlay,
9077
+ muted,
9078
+ loop,
9079
+ playsInline: playsInline ?? true,
9080
+ onPlay: handlePlay,
9081
+ onPause: handlePause,
9082
+ onLoadedMetadata: handleLoadedMetadata,
9083
+ onTimeUpdate: handleTimeUpdate,
9084
+ onVolumeChange: handleVolumeChange,
9085
+ onRateChange: handleRateChange,
9086
+ onClick: togglePlay,
9087
+ ...rest,
9088
+ children
9089
+ }
9090
+ ),
9091
+ showCenterPlay && /* @__PURE__ */ jsx346(
9092
+ "button",
9093
+ {
9094
+ type: "button",
9095
+ className: clsx_default(
9096
+ "center-play",
9097
+ isPlaying && "is-playing",
9098
+ !isLoaded && "is-loading"
9099
+ ),
9100
+ onClick: togglePlay,
9101
+ "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
9102
+ tabIndex: -1,
9103
+ children: /* @__PURE__ */ jsx346("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx346(PlayCircleIcon_default, {}) })
9104
+ }
9105
+ ),
9106
+ showControls && /* @__PURE__ */ jsxs221("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
9107
+ /* @__PURE__ */ jsx346(
9108
+ "input",
9109
+ {
9110
+ type: "range",
9111
+ className: "seekbar",
9112
+ min: 0,
9113
+ max: duration || 0,
9114
+ step: 0.1,
9115
+ value: currentTime,
9116
+ onChange: handleSeek,
9117
+ "aria-label": "\uC7AC\uC0DD \uC704\uCE58",
9118
+ style: {
9119
+ ["--progress"]: `${progressPct}%`,
9120
+ ["--buffered"]: `${bufferedPct}%`
9121
+ }
9122
+ }
9123
+ ),
9124
+ /* @__PURE__ */ jsxs221("div", { className: "controls-row", children: [
9125
+ /* @__PURE__ */ jsx346(
9126
+ "button",
9127
+ {
9128
+ type: "button",
9129
+ className: "control-btn",
9130
+ onClick: togglePlay,
9131
+ "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
9132
+ children: isPlaying ? /* @__PURE__ */ jsx346(PauseIcon_default, {}) : /* @__PURE__ */ jsx346(PlayIcon_default, {})
9133
+ }
9134
+ ),
9135
+ /* @__PURE__ */ jsxs221("div", { className: "volume-group", children: [
9136
+ /* @__PURE__ */ jsx346(
9137
+ "button",
9138
+ {
9139
+ type: "button",
9140
+ className: "control-btn",
9141
+ onClick: toggleMute,
9142
+ "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
9143
+ children: /* @__PURE__ */ jsx346(VolumeGlyph, {})
9144
+ }
9145
+ ),
9146
+ /* @__PURE__ */ jsx346(
9147
+ "input",
9148
+ {
9149
+ type: "range",
9150
+ className: "volume-slider",
9151
+ min: 0,
9152
+ max: 1,
9153
+ step: 0.05,
9154
+ value: isMuted ? 0 : volume,
9155
+ onChange: handleVolumeSlider,
9156
+ "aria-label": "\uBCFC\uB968",
9157
+ style: { ["--volume"]: `${volumePct}%` }
9158
+ }
9159
+ )
9160
+ ] }),
9161
+ /* @__PURE__ */ jsxs221("span", { className: "time", children: [
9162
+ formatTime(currentTime),
9163
+ " / ",
9164
+ formatTime(duration)
9165
+ ] }),
9166
+ /* @__PURE__ */ jsx346("div", { className: "controls-spacer" }),
9167
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs221("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
9168
+ /* @__PURE__ */ jsxs221(
9169
+ "button",
9170
+ {
9171
+ type: "button",
9172
+ className: "control-btn rate-btn",
9173
+ onClick: () => setRateMenuOpen((o) => !o),
9174
+ "aria-label": "\uC7AC\uC0DD \uC18D\uB3C4",
9175
+ "aria-expanded": rateMenuOpen,
9176
+ children: [
9177
+ playbackRate,
9178
+ "x"
9179
+ ]
9180
+ }
9181
+ ),
9182
+ rateMenuOpen && /* @__PURE__ */ jsx346("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx346("li", { children: /* @__PURE__ */ jsxs221(
9183
+ "button",
9184
+ {
9185
+ type: "button",
9186
+ role: "menuitem",
9187
+ className: clsx_default("rate-item", r2 === playbackRate && "is-active"),
9188
+ onClick: () => selectRate(r2),
9189
+ children: [
9190
+ r2,
9191
+ "x"
9192
+ ]
9193
+ }
9194
+ ) }, r2)) })
9195
+ ] }),
9196
+ showCaptions && /* @__PURE__ */ jsx346(
9197
+ "button",
9198
+ {
9199
+ type: "button",
9200
+ className: clsx_default("control-btn", captionsOn && "is-active"),
9201
+ onClick: toggleCaptions,
9202
+ "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
9203
+ "aria-pressed": captionsOn,
9204
+ children: /* @__PURE__ */ jsx346(TypeIcon_default, {})
9205
+ }
9206
+ ),
9207
+ showPip && pipSupported && /* @__PURE__ */ jsx346(
9208
+ "button",
9209
+ {
9210
+ type: "button",
9211
+ className: clsx_default("control-btn", isPip && "is-active"),
9212
+ onClick: togglePip,
9213
+ "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
9214
+ children: /* @__PURE__ */ jsx346(PipIcon, {})
9215
+ }
9216
+ ),
9217
+ showDownload && /* @__PURE__ */ jsx346(
9218
+ "a",
9219
+ {
9220
+ className: "control-btn",
9221
+ href: src,
9222
+ download: downloadFileName ?? true,
9223
+ "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
9224
+ children: /* @__PURE__ */ jsx346(DownloadIcon_default, {})
9225
+ }
9226
+ ),
9227
+ /* @__PURE__ */ jsx346(
9228
+ "button",
9229
+ {
9230
+ type: "button",
9231
+ className: "control-btn",
9232
+ onClick: toggleFullscreen,
9233
+ "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
9234
+ children: isFullscreen ? /* @__PURE__ */ jsx346(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx346(MaximizeIcon_default, {})
9235
+ }
9236
+ )
9237
+ ] })
9238
+ ] })
9239
+ ]
9240
+ }
9241
+ );
8956
9242
  });
8957
9243
  Video.displayName = "Video";
8958
9244
  var Video_default = Video;