jvetrau-ds 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/index.cjs +520 -218
  2. package/index.cjs.map +1 -1
  3. package/index.d.cts +63 -2
  4. package/index.d.ts +63 -2
  5. package/index.js +494 -201
  6. package/index.js.map +1 -1
  7. package/logo-symbol-JDC3ZGUQ.svg +20 -0
  8. package/logo-wordmark-XQV4UJSX.svg +3 -0
  9. package/package.json +1 -1
  10. package/patterns.cjs +67 -0
  11. package/patterns.cjs.map +1 -1
  12. package/patterns.d.cts +24 -1
  13. package/patterns.d.ts +24 -1
  14. package/patterns.js +64 -0
  15. package/patterns.js.map +1 -1
  16. package/styles.css +265 -46
  17. package/themes/base/desktop.css +3 -0
  18. package/themes/base/desktop.md +3 -0
  19. package/themes/base/desktop.scoped.css +3 -0
  20. package/themes/base/diagram.css +3 -0
  21. package/themes/base/diagram.md +3 -0
  22. package/themes/base/diagram.scoped.css +3 -0
  23. package/themes/base/mobile.css +3 -0
  24. package/themes/base/mobile.md +3 -0
  25. package/themes/base/mobile.scoped.css +3 -0
  26. package/themes/brandcopilot/desktop.css +3 -0
  27. package/themes/brandcopilot/desktop.md +3 -0
  28. package/themes/brandcopilot/desktop.scoped.css +3 -0
  29. package/themes/brandcopilot/diagram.css +3 -0
  30. package/themes/brandcopilot/diagram.md +3 -0
  31. package/themes/brandcopilot/diagram.scoped.css +3 -0
  32. package/themes/brandcopilot/mobile.css +3 -0
  33. package/themes/brandcopilot/mobile.md +3 -0
  34. package/themes/brandcopilot/mobile.scoped.css +3 -0
  35. package/themes/dmpatterns/desktop.css +3 -0
  36. package/themes/dmpatterns/desktop.md +3 -0
  37. package/themes/dmpatterns/desktop.scoped.css +3 -0
  38. package/themes/dmpatterns/diagram.css +3 -0
  39. package/themes/dmpatterns/diagram.md +3 -0
  40. package/themes/dmpatterns/diagram.scoped.css +3 -0
  41. package/themes/dmpatterns/mobile.css +3 -0
  42. package/themes/dmpatterns/mobile.md +3 -0
  43. package/themes/dmpatterns/mobile.scoped.css +3 -0
  44. package/themes/pdigest/desktop.css +3 -0
  45. package/themes/pdigest/desktop.md +3 -0
  46. package/themes/pdigest/desktop.scoped.css +3 -0
  47. package/themes/pdigest/diagram.css +3 -0
  48. package/themes/pdigest/diagram.md +3 -0
  49. package/themes/pdigest/diagram.scoped.css +3 -0
  50. package/themes/pdigest/mobile.css +3 -0
  51. package/themes/pdigest/mobile.md +3 -0
  52. package/themes/pdigest/mobile.scoped.css +3 -0
  53. package/themes/redesigntrack/desktop.css +3 -0
  54. package/themes/redesigntrack/desktop.md +3 -0
  55. package/themes/redesigntrack/desktop.scoped.css +3 -0
  56. package/themes/redesigntrack/diagram.css +3 -0
  57. package/themes/redesigntrack/diagram.md +3 -0
  58. package/themes/redesigntrack/diagram.scoped.css +3 -0
  59. package/themes/redesigntrack/mobile.css +3 -0
  60. package/themes/redesigntrack/mobile.md +3 -0
  61. package/themes/redesigntrack/mobile.scoped.css +3 -0
  62. package/tokens.cjs +360 -0
  63. package/tokens.cjs.map +1 -1
  64. package/tokens.js +360 -0
  65. package/tokens.js.map +1 -1
package/index.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var React4 = require('react');
3
+ var React3 = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var Hls = require('hls.js');
6
6
 
7
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
- var React4__default = /*#__PURE__*/_interopDefault(React4);
9
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
10
10
  var Hls__default = /*#__PURE__*/_interopDefault(Hls);
11
11
 
12
12
  // src/components/button/button.tsx
@@ -194,9 +194,9 @@ var Button = ({
194
194
  "button--icon-only": isIconOnly
195
195
  });
196
196
  let resolvedIcon = icon;
197
- if (React4.isValidElement(icon) && icon.type === icon_default) {
197
+ if (React3.isValidElement(icon) && icon.type === icon_default) {
198
198
  const iconElement = icon;
199
- resolvedIcon = React4.cloneElement(iconElement, {
199
+ resolvedIcon = React3.cloneElement(iconElement, {
200
200
  size: iconElement.props.size ?? "s",
201
201
  className: classnames("button__icon", iconElement.props.className),
202
202
  "aria-hidden": iconElement.props["aria-hidden"] ?? true,
@@ -323,9 +323,9 @@ var Dropdown = ({
323
323
  className = "",
324
324
  ...props
325
325
  }) => {
326
- const dropdownRef = React4.useRef(null);
327
- const [isOpen, setIsOpen] = React4.useState(false);
328
- const [internalValue, setInternalValue] = React4.useState(defaultValue);
326
+ const dropdownRef = React3.useRef(null);
327
+ const [isOpen, setIsOpen] = React3.useState(false);
328
+ const [internalValue, setInternalValue] = React3.useState(defaultValue);
329
329
  const selectedValue = value ?? internalValue;
330
330
  const classes = classnames("dropdown", className, {
331
331
  "dropdown--open": isOpen,
@@ -339,7 +339,7 @@ var Dropdown = ({
339
339
  "dropdown__trigger",
340
340
  triggerElement.props.className
341
341
  );
342
- const resolvedTrigger = React4.cloneElement(triggerElement, {
342
+ const resolvedTrigger = React3.cloneElement(triggerElement, {
343
343
  className: triggerClasses,
344
344
  "aria-haspopup": "menu",
345
345
  "aria-expanded": isOpen,
@@ -358,7 +358,7 @@ var Dropdown = ({
358
358
  onChange?.(option.value);
359
359
  setIsOpen(false);
360
360
  };
361
- React4.useEffect(() => {
361
+ React3.useEffect(() => {
362
362
  if (!isOpen) {
363
363
  return;
364
364
  }
@@ -512,23 +512,93 @@ var Field = ({
512
512
  ] });
513
513
  };
514
514
  var field_default = Field;
515
+ function getInitialValue(value, defaultValue, items) {
516
+ if (value !== void 0) {
517
+ return value;
518
+ }
519
+ if (defaultValue !== void 0) {
520
+ return defaultValue;
521
+ }
522
+ return items[0]?.value;
523
+ }
515
524
  var Menu = ({
516
- state = "default",
525
+ items,
526
+ value,
527
+ defaultValue,
528
+ label = "Menu",
517
529
  className = "",
518
- children,
519
- // disabled = false,
530
+ onValueChange,
520
531
  ...props
521
532
  }) => {
522
- const classes = classnames("menu", className, {
523
- error: state === "error",
524
- success: state === "success"
525
- });
533
+ const [internalValue, setInternalValue] = React3__default.default.useState(
534
+ getInitialValue(value, defaultValue, items)
535
+ );
536
+ const currentValue = value ?? internalValue;
537
+ React3__default.default.useEffect(() => {
538
+ if (value !== void 0) {
539
+ return;
540
+ }
541
+ setInternalValue(getInitialValue(value, defaultValue, items));
542
+ }, [value, defaultValue, items]);
543
+ const handleItemClick = (itemValue, disabled) => {
544
+ if (disabled) {
545
+ return;
546
+ }
547
+ if (value === void 0) {
548
+ setInternalValue(itemValue);
549
+ }
550
+ onValueChange?.(itemValue);
551
+ };
552
+ const classes = classnames("menu", className, {});
526
553
  return /* @__PURE__ */ jsxRuntime.jsx(
527
- "div",
554
+ "nav",
528
555
  {
529
556
  className: classes,
557
+ "aria-label": label,
530
558
  ...props,
531
- children
559
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "menu__list", children: items.map((item) => {
560
+ const isActive = item.value === currentValue;
561
+ const itemClasses = classnames("menu__control", {
562
+ "menu__control--active": isActive,
563
+ "menu__control--disabled": item.disabled
564
+ });
565
+ return /* @__PURE__ */ jsxRuntime.jsx(
566
+ "li",
567
+ {
568
+ className: "menu__item",
569
+ children: item.href ? /* @__PURE__ */ jsxRuntime.jsx(
570
+ "a",
571
+ {
572
+ className: itemClasses,
573
+ href: item.href,
574
+ "aria-current": isActive ? "page" : void 0,
575
+ "aria-disabled": item.disabled || void 0,
576
+ onClick: (event) => {
577
+ if (item.disabled) {
578
+ event.preventDefault();
579
+ return;
580
+ }
581
+ handleItemClick(item.value);
582
+ },
583
+ children: item.label
584
+ }
585
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
586
+ "button",
587
+ {
588
+ className: itemClasses,
589
+ type: "button",
590
+ disabled: item.disabled,
591
+ onClick: () => handleItemClick(
592
+ item.value,
593
+ item.disabled
594
+ ),
595
+ children: item.label
596
+ }
597
+ )
598
+ },
599
+ item.value
600
+ );
601
+ }) })
532
602
  }
533
603
  );
534
604
  };
@@ -607,7 +677,7 @@ var ProgressBar = ({
607
677
  onValueCommit,
608
678
  ...props
609
679
  }) => {
610
- const trackRef = React4.useRef(null);
680
+ const trackRef = React3.useRef(null);
611
681
  const safeValue = getClampedValue(
612
682
  value,
613
683
  max
@@ -752,29 +822,20 @@ var ProgressBar = ({
752
822
  };
753
823
  var progressbar_default = ProgressBar;
754
824
  function getClampedValue2(value, min, max) {
755
- return Math.min(
756
- Math.max(value, min),
757
- max
758
- );
825
+ return Math.min(Math.max(value, min), max);
759
826
  }
760
827
  function formatTime(value) {
761
- if (!Number.isFinite(value)) {
762
- return "0:00";
763
- }
828
+ if (!Number.isFinite(value)) return "0:00";
764
829
  const minutes = Math.floor(value / 60);
765
830
  const seconds = Math.floor(value % 60);
766
831
  return `${minutes}:${String(seconds).padStart(2, "0")}`;
767
832
  }
768
833
  function getBufferedEnd(video) {
769
- if (video.buffered.length === 0) {
770
- return 0;
771
- }
834
+ if (video.buffered.length === 0) return 0;
772
835
  return video.buffered.end(video.buffered.length - 1);
773
836
  }
774
837
  function getVideoSource(src, qualities, selectedQuality) {
775
- const selectedQualityItem = qualities.find(
776
- (quality) => quality.value === selectedQuality
777
- );
838
+ const selectedQualityItem = qualities.find((quality) => quality.value === selectedQuality);
778
839
  return selectedQualityItem?.src ?? src;
779
840
  }
780
841
  function getQualityOptions(qualities) {
@@ -784,28 +845,26 @@ function getQualityOptions(qualities) {
784
845
  disabled: quality.disabled
785
846
  }));
786
847
  }
787
- var defaultQualities = [
788
- {
789
- value: "360p",
790
- label: "360p"
791
- },
792
- {
793
- value: "720p",
794
- label: "720p"
795
- },
796
- {
797
- value: "1080p",
798
- label: "1080p"
799
- }
800
- ];
848
+ function getVideoProgressState(video) {
849
+ const duration = video.duration || 0;
850
+ const currentTime = video.currentTime || 0;
851
+ return {
852
+ currentTime,
853
+ duration,
854
+ completed: video.ended || duration > 0 && currentTime >= duration * 0.9
855
+ };
856
+ }
857
+ var defaultQualities = [];
801
858
  var Video = ({
802
859
  src,
803
860
  cover,
804
861
  qualities = defaultQualities,
805
- defaultQuality = "1080p",
862
+ defaultQuality = "",
806
863
  label = "Video player",
807
864
  initialVolume = 1,
808
865
  initialMuted = false,
866
+ initialTime = 0,
867
+ progressCommitIntervalSec = 15,
809
868
  className = "",
810
869
  autoPlay,
811
870
  loop,
@@ -815,32 +874,36 @@ var Video = ({
815
874
  onQualityChange,
816
875
  onPlay,
817
876
  onPause,
877
+ onEnded,
818
878
  onLoadedMetadata,
819
879
  onTimeUpdate,
820
880
  onProgress,
821
881
  onVolumeChange,
882
+ onProgressCommit,
822
883
  children,
823
884
  ...props
824
885
  }) => {
825
- const videoRef = React4.useRef(null);
826
- const [isPlaying, setIsPlaying] = React4.useState(false);
827
- const [isVolumeOpen, setIsVolumeOpen] = React4.useState(false);
828
- const [selectedQuality, setSelectedQuality] = React4.useState(defaultQuality);
829
- const [currentTime, setCurrentTime] = React4.useState(0);
830
- const [duration, setDuration] = React4.useState(0);
831
- const [buffered, setBuffered] = React4.useState(0);
832
- const [volume, setVolume] = React4.useState(initialVolume);
833
- const [isMuted, setIsMuted] = React4.useState(muted ?? initialMuted);
834
- const videoSrc = getVideoSource(
835
- src,
836
- qualities,
837
- selectedQuality
838
- );
839
- React4__default.default.useEffect(() => {
886
+ const videoRef = React3.useRef(null);
887
+ const [isPlaying, setIsPlaying] = React3.useState(false);
888
+ const [isVolumeOpen, setIsVolumeOpen] = React3.useState(false);
889
+ const [selectedQuality, setSelectedQuality] = React3.useState(defaultQuality);
890
+ const [currentTime, setCurrentTime] = React3.useState(0);
891
+ const [duration, setDuration] = React3.useState(0);
892
+ const [buffered, setBuffered] = React3.useState(0);
893
+ const [volume, setVolume] = React3.useState(initialVolume);
894
+ const [isMuted, setIsMuted] = React3.useState(muted ?? initialMuted);
895
+ const hasAppliedInitialTimeRef = React3.useRef(false);
896
+ const lastProgressCommitAtRef = React3.useRef(0);
897
+ const videoSrc = getVideoSource(src, qualities, selectedQuality);
898
+ const qualityOptions = getQualityOptions(qualities);
899
+ const hasQualityOptions = qualityOptions.length > 0;
900
+ React3.useEffect(() => {
840
901
  const video = videoRef.current;
841
- if (!video || !videoSrc) {
842
- return;
843
- }
902
+ hasAppliedInitialTimeRef.current = false;
903
+ lastProgressCommitAtRef.current = 0;
904
+ if (!video || !videoSrc) return;
905
+ video.removeAttribute("src");
906
+ video.load();
844
907
  if (video.canPlayType("application/vnd.apple.mpegurl")) {
845
908
  video.src = videoSrc;
846
909
  return;
@@ -859,9 +922,6 @@ var Video = ({
859
922
  hls.destroy();
860
923
  };
861
924
  }, [videoSrc]);
862
- const qualityOptions = getQualityOptions(
863
- qualities
864
- );
865
925
  const hasStarted = currentTime > 0 || isPlaying;
866
926
  const hasControls = hasStarted;
867
927
  const hasVolume = isVolumeOpen;
@@ -871,9 +931,7 @@ var Video = ({
871
931
  });
872
932
  const syncMediaState = () => {
873
933
  const video = videoRef.current;
874
- if (!video) {
875
- return;
876
- }
934
+ if (!video) return;
877
935
  setCurrentTime(video.currentTime);
878
936
  setDuration(video.duration || 0);
879
937
  setBuffered(getBufferedEnd(video));
@@ -881,39 +939,45 @@ var Video = ({
881
939
  setIsMuted(video.muted);
882
940
  setIsPlaying(!video.paused);
883
941
  };
884
- const handlePlayToggle = () => {
885
- const video = videoRef.current;
886
- if (!video) {
942
+ const commitProgress = (video) => {
943
+ if (!onProgressCommit) {
887
944
  return;
888
945
  }
946
+ onProgressCommit(
947
+ getVideoProgressState(video)
948
+ );
949
+ };
950
+ const handlePlayToggle = async () => {
951
+ const video = videoRef.current;
952
+ if (!video) return;
953
+ console.log("play click", {
954
+ paused: video.paused,
955
+ readyState: video.readyState,
956
+ src: video.currentSrc,
957
+ networkState: video.networkState,
958
+ error: video.error
959
+ });
889
960
  if (video.paused) {
890
- video.play().catch(() => void 0);
961
+ try {
962
+ await video.play();
963
+ console.log("play success");
964
+ } catch (error) {
965
+ console.error("play failed", error);
966
+ }
891
967
  return;
892
968
  }
893
969
  video.pause();
894
970
  };
895
971
  const handleSeek = (nextValue) => {
896
972
  const video = videoRef.current;
897
- if (!video) {
898
- return;
899
- }
900
- video.currentTime = getClampedValue2(
901
- nextValue,
902
- 0,
903
- duration
904
- );
973
+ if (!video) return;
974
+ video.currentTime = getClampedValue2(nextValue, 0, duration);
905
975
  setCurrentTime(video.currentTime);
906
976
  };
907
977
  const handleVolumeChange = (nextValue) => {
908
978
  const video = videoRef.current;
909
- if (!video) {
910
- return;
911
- }
912
- const nextVolume = getClampedValue2(
913
- nextValue,
914
- 0,
915
- 1
916
- );
979
+ if (!video) return;
980
+ const nextVolume = getClampedValue2(nextValue, 0, 1);
917
981
  video.volume = nextVolume;
918
982
  video.muted = nextVolume === 0;
919
983
  setVolume(nextVolume);
@@ -921,17 +985,13 @@ var Video = ({
921
985
  };
922
986
  const handleSoundToggle = () => {
923
987
  const video = videoRef.current;
924
- if (!video) {
925
- return;
926
- }
988
+ if (!video) return;
927
989
  video.muted = !video.muted;
928
990
  setIsMuted(video.muted);
929
991
  };
930
992
  const handleFullscreen = () => {
931
993
  const video = videoRef.current;
932
- if (!video) {
933
- return;
934
- }
994
+ if (!video) return;
935
995
  video.requestFullscreen?.();
936
996
  };
937
997
  const handleQualityChange = (quality) => {
@@ -939,11 +999,24 @@ var Video = ({
939
999
  onQualityChange?.(quality);
940
1000
  };
941
1001
  const handleLoadedMetadata = (event) => {
1002
+ const video = event.currentTarget;
1003
+ if (!hasAppliedInitialTimeRef.current && initialTime > 0) {
1004
+ video.currentTime = Math.min(
1005
+ initialTime,
1006
+ video.duration || initialTime
1007
+ );
1008
+ hasAppliedInitialTimeRef.current = true;
1009
+ }
942
1010
  syncMediaState();
943
1011
  onLoadedMetadata?.(event);
944
1012
  };
945
1013
  const handleTimeUpdate = (event) => {
1014
+ const video = event.currentTarget;
946
1015
  syncMediaState();
1016
+ if (onProgressCommit && video.currentTime - lastProgressCommitAtRef.current >= progressCommitIntervalSec) {
1017
+ lastProgressCommitAtRef.current = video.currentTime;
1018
+ commitProgress(video);
1019
+ }
947
1020
  onTimeUpdate?.(event);
948
1021
  };
949
1022
  const handleProgress = (event) => {
@@ -956,133 +1029,122 @@ var Video = ({
956
1029
  };
957
1030
  const handlePause = (event) => {
958
1031
  setIsPlaying(false);
1032
+ commitProgress(event.currentTarget);
959
1033
  onPause?.(event);
960
1034
  };
1035
+ const handleEnded = (event) => {
1036
+ syncMediaState();
1037
+ commitProgress(event.currentTarget);
1038
+ onEnded?.(event);
1039
+ };
961
1040
  const handleNativeVolumeChange = (event) => {
962
1041
  syncMediaState();
963
1042
  onVolumeChange?.(event);
964
1043
  };
965
- return /* @__PURE__ */ jsxRuntime.jsxs(
966
- "div",
967
- {
968
- className: classes,
969
- "aria-label": label,
970
- children: [
971
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "video__surface", children: [
972
- /* @__PURE__ */ jsxRuntime.jsx(
973
- "video",
974
- {
975
- ...props,
976
- ref: videoRef,
977
- className: "video__media",
978
- poster: cover,
979
- autoPlay,
980
- loop,
981
- muted: isMuted,
982
- playsInline,
983
- preload,
984
- controls: false,
985
- onLoadedMetadata: handleLoadedMetadata,
986
- onTimeUpdate: handleTimeUpdate,
987
- onProgress: handleProgress,
988
- onPlay: handlePlay,
989
- onPause: handlePause,
990
- onVolumeChange: handleNativeVolumeChange,
991
- children
992
- }
993
- ),
994
- !hasStarted && /* @__PURE__ */ jsxRuntime.jsx(
995
- button_icon_default,
996
- {
997
- className: "video__main-action",
998
- icon: "play",
999
- label: "Play video",
1000
- onClick: handlePlayToggle
1001
- }
1002
- )
1003
- ] }),
1004
- hasControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "video__controls", children: [
1005
- /* @__PURE__ */ jsxRuntime.jsx(
1006
- button_icon_default,
1007
- {
1008
- icon: isPlaying ? "pause" : "play",
1009
- label: isPlaying ? "Pause video" : "Play video",
1010
- onClick: handlePlayToggle
1011
- }
1012
- ),
1013
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video__time", children: formatTime(currentTime) }),
1014
- /* @__PURE__ */ jsxRuntime.jsx(
1015
- progressbar_default,
1016
- {
1017
- className: "video__progress",
1018
- mode: "player",
1019
- value: currentTime,
1020
- buffered,
1021
- max: duration || 1,
1022
- step: 1,
1023
- label: "Video progress",
1024
- onValueChange: handleSeek
1025
- }
1026
- ),
1027
- /* @__PURE__ */ jsxRuntime.jsx(
1028
- button_icon_default,
1029
- {
1030
- icon: "fullscreen",
1031
- label: "Fullscreen",
1032
- onClick: handleFullscreen
1033
- }
1034
- ),
1035
- /* @__PURE__ */ jsxRuntime.jsxs(
1036
- "div",
1037
- {
1038
- className: "video__sound-control",
1039
- onMouseLeave: () => setIsVolumeOpen(false),
1040
- children: [
1041
- /* @__PURE__ */ jsxRuntime.jsx(
1042
- button_icon_default,
1043
- {
1044
- icon: isMuted ? "sound-off" : "sound",
1045
- label: isMuted ? "Unmute video" : "Mute video",
1046
- onClick: handleSoundToggle,
1047
- onMouseEnter: () => setIsVolumeOpen(true),
1048
- onFocus: () => setIsVolumeOpen(true)
1049
- }
1050
- ),
1051
- hasVolume && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video__volume", children: /* @__PURE__ */ jsxRuntime.jsx(
1052
- progressbar_default,
1053
- {
1054
- mode: "level",
1055
- value: isMuted ? 0 : volume,
1056
- max: 1,
1057
- step: 0.05,
1058
- label: "Volume",
1059
- onValueChange: handleVolumeChange
1060
- }
1061
- ) })
1062
- ]
1063
- }
1064
- ),
1065
- /* @__PURE__ */ jsxRuntime.jsx(
1066
- dropdown_default,
1067
- {
1068
- align: "top-end",
1069
- value: selectedQuality,
1070
- options: qualityOptions,
1071
- label: "Video quality",
1072
- onChange: handleQualityChange,
1073
- trigger: /* @__PURE__ */ jsxRuntime.jsx(
1074
- button_icon_default,
1075
- {
1076
- icon: "settings",
1077
- label: "Video quality"
1078
- }
1079
- )
1080
- }
1081
- )
1082
- ] })
1083
- ]
1084
- }
1085
- );
1044
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classes, "aria-label": label, children: [
1045
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "video__surface", children: [
1046
+ cover && !hasStarted ? /* @__PURE__ */ jsxRuntime.jsx(
1047
+ "img",
1048
+ {
1049
+ className: "video__cover",
1050
+ src: cover,
1051
+ alt: "",
1052
+ "aria-hidden": "true"
1053
+ }
1054
+ ) : null,
1055
+ /* @__PURE__ */ jsxRuntime.jsx(
1056
+ "video",
1057
+ {
1058
+ ...props,
1059
+ ref: videoRef,
1060
+ className: "video__media",
1061
+ poster: cover,
1062
+ autoPlay,
1063
+ loop,
1064
+ muted: isMuted,
1065
+ playsInline,
1066
+ preload,
1067
+ controls: false,
1068
+ onLoadedMetadata: handleLoadedMetadata,
1069
+ onTimeUpdate: handleTimeUpdate,
1070
+ onProgress: handleProgress,
1071
+ onPlay: handlePlay,
1072
+ onPause: handlePause,
1073
+ onEnded: handleEnded,
1074
+ onVolumeChange: handleNativeVolumeChange,
1075
+ children
1076
+ }
1077
+ ),
1078
+ !hasStarted && /* @__PURE__ */ jsxRuntime.jsx(
1079
+ button_icon_default,
1080
+ {
1081
+ className: "video__main-action",
1082
+ icon: "play",
1083
+ label: "Play video",
1084
+ onClick: handlePlayToggle
1085
+ }
1086
+ )
1087
+ ] }),
1088
+ hasControls && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "video__controls", children: [
1089
+ /* @__PURE__ */ jsxRuntime.jsx(
1090
+ button_icon_default,
1091
+ {
1092
+ icon: isPlaying ? "pause" : "play",
1093
+ label: isPlaying ? "Pause video" : "Play video",
1094
+ onClick: handlePlayToggle
1095
+ }
1096
+ ),
1097
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video__time", children: formatTime(currentTime) }),
1098
+ /* @__PURE__ */ jsxRuntime.jsx(
1099
+ progressbar_default,
1100
+ {
1101
+ className: "video__progress",
1102
+ mode: "player",
1103
+ value: currentTime,
1104
+ buffered,
1105
+ max: duration || 1,
1106
+ step: 1,
1107
+ label: "Video progress",
1108
+ onValueChange: handleSeek
1109
+ }
1110
+ ),
1111
+ /* @__PURE__ */ jsxRuntime.jsx(button_icon_default, { icon: "fullscreen", label: "Fullscreen", onClick: handleFullscreen }),
1112
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "video__sound-control", onMouseLeave: () => setIsVolumeOpen(false), children: [
1113
+ /* @__PURE__ */ jsxRuntime.jsx(
1114
+ button_icon_default,
1115
+ {
1116
+ icon: isMuted ? "sound-off" : "sound",
1117
+ label: isMuted ? "Unmute video" : "Mute video",
1118
+ onClick: handleSoundToggle,
1119
+ onMouseEnter: () => setIsVolumeOpen(true),
1120
+ onFocus: () => setIsVolumeOpen(true)
1121
+ }
1122
+ ),
1123
+ hasVolume && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "video__volume", children: /* @__PURE__ */ jsxRuntime.jsx(
1124
+ progressbar_default,
1125
+ {
1126
+ mode: "level",
1127
+ value: isMuted ? 0 : volume,
1128
+ max: 1,
1129
+ step: 0.05,
1130
+ label: "Volume",
1131
+ onValueChange: handleVolumeChange
1132
+ }
1133
+ ) })
1134
+ ] }),
1135
+ hasQualityOptions && /* @__PURE__ */ jsxRuntime.jsx(
1136
+ dropdown_default,
1137
+ {
1138
+ align: "top-end",
1139
+ value: selectedQuality,
1140
+ options: qualityOptions,
1141
+ label: "Video quality",
1142
+ onChange: handleQualityChange,
1143
+ trigger: /* @__PURE__ */ jsxRuntime.jsx(button_icon_default, { icon: "settings", label: "Video quality" })
1144
+ }
1145
+ )
1146
+ ] })
1147
+ ] });
1086
1148
  };
1087
1149
  var video_default = Video;
1088
1150
  var Search = ({
@@ -1171,18 +1233,258 @@ var Card = ({
1171
1233
  );
1172
1234
  };
1173
1235
  var card_default = Card;
1236
+ var Panel = ({
1237
+ layout = "card",
1238
+ heading,
1239
+ description,
1240
+ className = "",
1241
+ children,
1242
+ ...props
1243
+ }) => {
1244
+ const classes = classnames("panel", className, {
1245
+ "panel--transparent": layout === "transparent"
1246
+ });
1247
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1248
+ "section",
1249
+ {
1250
+ className: classes,
1251
+ ...props,
1252
+ children: [
1253
+ (heading || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel__header", children: [
1254
+ heading && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "panel__heading", children: heading }),
1255
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "panel__description", children: description })
1256
+ ] }),
1257
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel__content", children })
1258
+ ]
1259
+ }
1260
+ );
1261
+ };
1262
+ var panel_default = Panel;
1263
+
1264
+ // src/components/logo/assets/logo-symbol.svg
1265
+ var logo_symbol_default = "./logo-symbol-JDC3ZGUQ.svg";
1266
+
1267
+ // src/components/logo/assets/logo-wordmark.svg
1268
+ var logo_wordmark_default = "./logo-wordmark-XQV4UJSX.svg";
1269
+ var Logo = ({
1270
+ mode = "full",
1271
+ label = "\u041F\u0430\u0442\u0442\u0435\u0440\u043D\u044B \u0434\u0438\u0437\u0430\u0439\u043D-\u043C\u0435\u043D\u0435\u0434\u0436\u043C\u0435\u043D\u0442\u0430",
1272
+ className = "",
1273
+ ...props
1274
+ }) => {
1275
+ const classes = classnames("logo", className, {
1276
+ "logo--symbol": mode === "symbol"
1277
+ });
1278
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1279
+ "div",
1280
+ {
1281
+ className: classes,
1282
+ "aria-label": label,
1283
+ ...props,
1284
+ children: [
1285
+ /* @__PURE__ */ jsxRuntime.jsx(
1286
+ "img",
1287
+ {
1288
+ className: "logo__symbol",
1289
+ src: logo_symbol_default,
1290
+ alt: "",
1291
+ "aria-hidden": "true"
1292
+ }
1293
+ ),
1294
+ mode === "full" && /* @__PURE__ */ jsxRuntime.jsx(
1295
+ "img",
1296
+ {
1297
+ className: "logo__wordmark",
1298
+ src: logo_wordmark_default,
1299
+ alt: "",
1300
+ "aria-hidden": "true"
1301
+ }
1302
+ )
1303
+ ]
1304
+ }
1305
+ );
1306
+ };
1307
+ var logo_default = Logo;
1308
+ var Avatar = ({
1309
+ src,
1310
+ alt = "",
1311
+ initials,
1312
+ className = "",
1313
+ ...props
1314
+ }) => {
1315
+ const classes = classnames("avatar", className, {});
1316
+ return /* @__PURE__ */ jsxRuntime.jsx(
1317
+ "div",
1318
+ {
1319
+ className: classes,
1320
+ "aria-label": alt,
1321
+ ...props,
1322
+ children: src ? /* @__PURE__ */ jsxRuntime.jsx(
1323
+ "img",
1324
+ {
1325
+ className: "avatar__image",
1326
+ src,
1327
+ alt
1328
+ }
1329
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "avatar__initials", children: initials })
1330
+ }
1331
+ );
1332
+ };
1333
+ var avatar_default = Avatar;
1334
+ var Header = ({
1335
+ logo,
1336
+ menu,
1337
+ avatar,
1338
+ children,
1339
+ ...props
1340
+ }) => {
1341
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1342
+ "header",
1343
+ {
1344
+ className: "header",
1345
+ ...props,
1346
+ children: [
1347
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "header__logo", children: logo }),
1348
+ (menu || children) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "header__menu", children: menu || children }),
1349
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "header__avatar", children: avatar })
1350
+ ]
1351
+ }
1352
+ );
1353
+ };
1354
+ var header_default = Header;
1355
+ var Footer = ({
1356
+ copyright,
1357
+ links,
1358
+ secondaryLinks,
1359
+ children,
1360
+ ...props
1361
+ }) => {
1362
+ return /* @__PURE__ */ jsxRuntime.jsxs("footer", { className: "footer", ...props, children: [
1363
+ copyright && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "footer__copyright", children: copyright }),
1364
+ (links || children) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "footer__links", children: links || children }),
1365
+ secondaryLinks && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "footer__links footer__links--secondary", children: secondaryLinks })
1366
+ ] });
1367
+ };
1368
+ var footer_default = Footer;
1369
+ var ScreenHeader = ({
1370
+ eyebrow,
1371
+ title,
1372
+ description,
1373
+ tabs,
1374
+ children,
1375
+ ...props
1376
+ }) => {
1377
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1378
+ "section",
1379
+ {
1380
+ className: "screen-header",
1381
+ ...props,
1382
+ children: [
1383
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "screen-header__heading", children: [
1384
+ eyebrow && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "screen-header__section", children: eyebrow }),
1385
+ title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "screen-header__title", children: title }),
1386
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "screen-header__description", children: description })
1387
+ ] }),
1388
+ (tabs || children) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "screen-header__tabs", children: tabs || children })
1389
+ ]
1390
+ }
1391
+ );
1392
+ };
1393
+ var screen_header_default = ScreenHeader;
1394
+ var LayoutFoundation = ({
1395
+ width = "default",
1396
+ className = "",
1397
+ children,
1398
+ ...props
1399
+ }) => {
1400
+ const classes = classnames("layout-foundation", className, {
1401
+ "layout-foundation--narrow": width === "narrow",
1402
+ "layout-foundation--wide": width === "wide",
1403
+ "layout-foundation--full": width === "full"
1404
+ });
1405
+ return /* @__PURE__ */ jsxRuntime.jsx(
1406
+ "div",
1407
+ {
1408
+ className: classes,
1409
+ ...props,
1410
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-foundation__grid", children })
1411
+ }
1412
+ );
1413
+ };
1414
+ var foundation_default = LayoutFoundation;
1415
+ var LayoutBase = ({
1416
+ width = "default",
1417
+ header,
1418
+ footer,
1419
+ children,
1420
+ className = "",
1421
+ ...props
1422
+ }) => {
1423
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1424
+ foundation_default,
1425
+ {
1426
+ width,
1427
+ className,
1428
+ ...props,
1429
+ children: [
1430
+ header && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-base__header", children: header }),
1431
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "layout-base__main", children }),
1432
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-base__footer", children: footer })
1433
+ ]
1434
+ }
1435
+ );
1436
+ };
1437
+ var base_default = LayoutBase;
1438
+ var LayoutSidebar = ({
1439
+ width = "wide",
1440
+ header,
1441
+ screenHeader,
1442
+ sidebar,
1443
+ footer,
1444
+ children,
1445
+ className = "",
1446
+ ...props
1447
+ }) => {
1448
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1449
+ foundation_default,
1450
+ {
1451
+ width,
1452
+ className,
1453
+ ...props,
1454
+ children: [
1455
+ header && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-sidebar__header", children: header }),
1456
+ screenHeader && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-sidebar__screen-header", children: screenHeader }),
1457
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "layout-sidebar__body", children: [
1458
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "layout-sidebar__main", children }),
1459
+ sidebar && /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "layout-sidebar__side", children: sidebar })
1460
+ ] }),
1461
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "layout-sidebar__footer", children: footer })
1462
+ ]
1463
+ }
1464
+ );
1465
+ };
1466
+ var sidebar_default = LayoutSidebar;
1174
1467
 
1468
+ exports.Avatar = avatar_default;
1175
1469
  exports.Button = button_default;
1176
1470
  exports.ButtonIcon = button_icon_default;
1177
1471
  exports.Card = card_default;
1178
1472
  exports.Checkbox = checkbox_default;
1179
1473
  exports.Dropdown = dropdown_default;
1180
1474
  exports.Field = field_default;
1475
+ exports.Footer = footer_default;
1476
+ exports.Header = header_default;
1181
1477
  exports.Input = input_default;
1478
+ exports.LayoutBase = base_default;
1479
+ exports.LayoutFoundation = foundation_default;
1480
+ exports.LayoutSidebar = sidebar_default;
1481
+ exports.Logo = logo_default;
1182
1482
  exports.Menu = menu_default;
1483
+ exports.Panel = panel_default;
1183
1484
  exports.ProgressBar = progressbar_default;
1184
1485
  exports.Radio = radio_default;
1185
1486
  exports.RichEdit = richedit_default;
1487
+ exports.ScreenHeader = screen_header_default;
1186
1488
  exports.Search = search_default;
1187
1489
  exports.Select = select_default;
1188
1490
  exports.Tabs = tabs_default;