@djangocfg/ui-tools 2.1.209 → 2.1.210
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/{chunk-CDP3K6BI.mjs → chunk-52WXASRO.mjs} +29 -16
- package/dist/chunk-52WXASRO.mjs.map +1 -0
- package/dist/{chunk-HJMDAPQH.cjs → chunk-DF6ORMTF.cjs} +29 -16
- package/dist/chunk-DF6ORMTF.cjs.map +1 -0
- package/dist/{components-F2ZYYCH4.cjs → components-4Z2JIRZI.cjs} +12 -12
- package/dist/{components-3RJ5Y3TB.mjs.map → components-4Z2JIRZI.cjs.map} +1 -1
- package/dist/{components-3RJ5Y3TB.mjs → components-YWYUZQIH.mjs} +3 -3
- package/dist/{components-F2ZYYCH4.cjs.map → components-YWYUZQIH.mjs.map} +1 -1
- package/dist/index.cjs +39 -39
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +4 -4
- package/package.json +6 -6
- package/src/tools/AudioPlayer/AudioPlayer.story.tsx +11 -0
- package/src/tools/AudioPlayer/README.md +1 -0
- package/src/tools/AudioPlayer/components/HybridCompactPlayer.tsx +12 -2
- package/src/tools/AudioPlayer/components/HybridWaveform.tsx +19 -12
- package/dist/chunk-CDP3K6BI.mjs.map +0 -1
- package/dist/chunk-HJMDAPQH.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkDF6ORMTF_cjs = require('./chunk-DF6ORMTF.cjs');
|
|
4
4
|
var chunk46VDB3BJ_cjs = require('./chunk-46VDB3BJ.cjs');
|
|
5
5
|
require('./chunk-F2N7P5XU.cjs');
|
|
6
6
|
var chunkIPRNIM7L_cjs = require('./chunk-IPRNIM7L.cjs');
|
|
@@ -791,21 +791,21 @@ function AudioLoadingFallback() {
|
|
|
791
791
|
}
|
|
792
792
|
chunkWGEGR3DF_cjs.__name(AudioLoadingFallback, "AudioLoadingFallback");
|
|
793
793
|
var LazyHybridAudioPlayer = createLazyComponent(
|
|
794
|
-
() => import('./components-
|
|
794
|
+
() => import('./components-4Z2JIRZI.cjs').then((mod) => ({ default: mod.HybridAudioPlayer })),
|
|
795
795
|
{
|
|
796
796
|
displayName: "LazyHybridAudioPlayer",
|
|
797
797
|
fallback: /* @__PURE__ */ jsxRuntime.jsx(AudioLoadingFallback, {})
|
|
798
798
|
}
|
|
799
799
|
);
|
|
800
800
|
var LazyHybridSimplePlayer = createLazyComponent(
|
|
801
|
-
() => import('./components-
|
|
801
|
+
() => import('./components-4Z2JIRZI.cjs').then((mod) => ({ default: mod.HybridSimplePlayer })),
|
|
802
802
|
{
|
|
803
803
|
displayName: "LazyHybridSimplePlayer",
|
|
804
804
|
fallback: /* @__PURE__ */ jsxRuntime.jsx(AudioLoadingFallback, {})
|
|
805
805
|
}
|
|
806
806
|
);
|
|
807
807
|
var LazyHybridCompactPlayer = createLazyComponent(
|
|
808
|
-
() => import('./components-
|
|
808
|
+
() => import('./components-4Z2JIRZI.cjs').then((mod) => ({ default: mod.HybridCompactPlayer })),
|
|
809
809
|
{
|
|
810
810
|
displayName: "LazyHybridCompactPlayer",
|
|
811
811
|
fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 h-8 px-1 animate-pulse", children: [
|
|
@@ -906,143 +906,143 @@ chunkWGEGR3DF_cjs.__name(CronSchedulerFallback, "CronSchedulerFallback");
|
|
|
906
906
|
|
|
907
907
|
Object.defineProperty(exports, "AudioReactiveCover", {
|
|
908
908
|
enumerable: true,
|
|
909
|
-
get: function () { return
|
|
909
|
+
get: function () { return chunkDF6ORMTF_cjs.AudioReactiveCover; }
|
|
910
910
|
});
|
|
911
911
|
Object.defineProperty(exports, "COLOR_SCHEMES", {
|
|
912
912
|
enumerable: true,
|
|
913
|
-
get: function () { return
|
|
913
|
+
get: function () { return chunkDF6ORMTF_cjs.COLOR_SCHEMES; }
|
|
914
914
|
});
|
|
915
915
|
Object.defineProperty(exports, "COLOR_SCHEME_INFO", {
|
|
916
916
|
enumerable: true,
|
|
917
|
-
get: function () { return
|
|
917
|
+
get: function () { return chunkDF6ORMTF_cjs.COLOR_SCHEME_INFO; }
|
|
918
918
|
});
|
|
919
919
|
Object.defineProperty(exports, "EFFECT_ANIMATIONS", {
|
|
920
920
|
enumerable: true,
|
|
921
|
-
get: function () { return
|
|
921
|
+
get: function () { return chunkDF6ORMTF_cjs.EFFECT_ANIMATIONS; }
|
|
922
922
|
});
|
|
923
923
|
Object.defineProperty(exports, "GlowEffect", {
|
|
924
924
|
enumerable: true,
|
|
925
|
-
get: function () { return
|
|
925
|
+
get: function () { return chunkDF6ORMTF_cjs.GlowEffect; }
|
|
926
926
|
});
|
|
927
927
|
Object.defineProperty(exports, "HybridAudioPlayer", {
|
|
928
928
|
enumerable: true,
|
|
929
|
-
get: function () { return
|
|
929
|
+
get: function () { return chunkDF6ORMTF_cjs.HybridAudioPlayer; }
|
|
930
930
|
});
|
|
931
931
|
Object.defineProperty(exports, "HybridAudioProvider", {
|
|
932
932
|
enumerable: true,
|
|
933
|
-
get: function () { return
|
|
933
|
+
get: function () { return chunkDF6ORMTF_cjs.HybridAudioProvider; }
|
|
934
934
|
});
|
|
935
935
|
Object.defineProperty(exports, "HybridSimplePlayer", {
|
|
936
936
|
enumerable: true,
|
|
937
|
-
get: function () { return
|
|
937
|
+
get: function () { return chunkDF6ORMTF_cjs.HybridSimplePlayer; }
|
|
938
938
|
});
|
|
939
939
|
Object.defineProperty(exports, "HybridWaveform", {
|
|
940
940
|
enumerable: true,
|
|
941
|
-
get: function () { return
|
|
941
|
+
get: function () { return chunkDF6ORMTF_cjs.HybridWaveform; }
|
|
942
942
|
});
|
|
943
943
|
Object.defineProperty(exports, "INTENSITY_CONFIG", {
|
|
944
944
|
enumerable: true,
|
|
945
|
-
get: function () { return
|
|
945
|
+
get: function () { return chunkDF6ORMTF_cjs.INTENSITY_CONFIG; }
|
|
946
946
|
});
|
|
947
947
|
Object.defineProperty(exports, "INTENSITY_INFO", {
|
|
948
948
|
enumerable: true,
|
|
949
|
-
get: function () { return
|
|
949
|
+
get: function () { return chunkDF6ORMTF_cjs.INTENSITY_INFO; }
|
|
950
950
|
});
|
|
951
951
|
Object.defineProperty(exports, "MeshEffect", {
|
|
952
952
|
enumerable: true,
|
|
953
|
-
get: function () { return
|
|
953
|
+
get: function () { return chunkDF6ORMTF_cjs.MeshEffect; }
|
|
954
954
|
});
|
|
955
955
|
Object.defineProperty(exports, "OrbsEffect", {
|
|
956
956
|
enumerable: true,
|
|
957
|
-
get: function () { return
|
|
957
|
+
get: function () { return chunkDF6ORMTF_cjs.OrbsEffect; }
|
|
958
958
|
});
|
|
959
959
|
Object.defineProperty(exports, "SpotlightEffect", {
|
|
960
960
|
enumerable: true,
|
|
961
|
-
get: function () { return
|
|
961
|
+
get: function () { return chunkDF6ORMTF_cjs.SpotlightEffect; }
|
|
962
962
|
});
|
|
963
963
|
Object.defineProperty(exports, "VARIANT_INFO", {
|
|
964
964
|
enumerable: true,
|
|
965
|
-
get: function () { return
|
|
965
|
+
get: function () { return chunkDF6ORMTF_cjs.VARIANT_INFO; }
|
|
966
966
|
});
|
|
967
967
|
Object.defineProperty(exports, "VisualizationProvider", {
|
|
968
968
|
enumerable: true,
|
|
969
|
-
get: function () { return
|
|
969
|
+
get: function () { return chunkDF6ORMTF_cjs.VisualizationProvider; }
|
|
970
970
|
});
|
|
971
971
|
Object.defineProperty(exports, "calculateGlowLayers", {
|
|
972
972
|
enumerable: true,
|
|
973
|
-
get: function () { return
|
|
973
|
+
get: function () { return chunkDF6ORMTF_cjs.calculateGlowLayers; }
|
|
974
974
|
});
|
|
975
975
|
Object.defineProperty(exports, "calculateMeshGradients", {
|
|
976
976
|
enumerable: true,
|
|
977
|
-
get: function () { return
|
|
977
|
+
get: function () { return chunkDF6ORMTF_cjs.calculateMeshGradients; }
|
|
978
978
|
});
|
|
979
979
|
Object.defineProperty(exports, "calculateOrbs", {
|
|
980
980
|
enumerable: true,
|
|
981
|
-
get: function () { return
|
|
981
|
+
get: function () { return chunkDF6ORMTF_cjs.calculateOrbs; }
|
|
982
982
|
});
|
|
983
983
|
Object.defineProperty(exports, "calculateSpotlight", {
|
|
984
984
|
enumerable: true,
|
|
985
|
-
get: function () { return
|
|
985
|
+
get: function () { return chunkDF6ORMTF_cjs.calculateSpotlight; }
|
|
986
986
|
});
|
|
987
987
|
Object.defineProperty(exports, "formatTime", {
|
|
988
988
|
enumerable: true,
|
|
989
|
-
get: function () { return
|
|
989
|
+
get: function () { return chunkDF6ORMTF_cjs.formatTime; }
|
|
990
990
|
});
|
|
991
991
|
Object.defineProperty(exports, "getColors", {
|
|
992
992
|
enumerable: true,
|
|
993
|
-
get: function () { return
|
|
993
|
+
get: function () { return chunkDF6ORMTF_cjs.getColors; }
|
|
994
994
|
});
|
|
995
995
|
Object.defineProperty(exports, "getEffectConfig", {
|
|
996
996
|
enumerable: true,
|
|
997
|
-
get: function () { return
|
|
997
|
+
get: function () { return chunkDF6ORMTF_cjs.getEffectConfig; }
|
|
998
998
|
});
|
|
999
999
|
Object.defineProperty(exports, "prepareEffectColors", {
|
|
1000
1000
|
enumerable: true,
|
|
1001
|
-
get: function () { return
|
|
1001
|
+
get: function () { return chunkDF6ORMTF_cjs.prepareEffectColors; }
|
|
1002
1002
|
});
|
|
1003
1003
|
Object.defineProperty(exports, "useAudioBus", {
|
|
1004
1004
|
enumerable: true,
|
|
1005
|
-
get: function () { return
|
|
1005
|
+
get: function () { return chunkDF6ORMTF_cjs.useAudioBus; }
|
|
1006
1006
|
});
|
|
1007
1007
|
Object.defineProperty(exports, "useAudioBusStore", {
|
|
1008
1008
|
enumerable: true,
|
|
1009
|
-
get: function () { return
|
|
1009
|
+
get: function () { return chunkDF6ORMTF_cjs.useAudioBusStore; }
|
|
1010
1010
|
});
|
|
1011
1011
|
Object.defineProperty(exports, "useAudioVisualization", {
|
|
1012
1012
|
enumerable: true,
|
|
1013
|
-
get: function () { return
|
|
1013
|
+
get: function () { return chunkDF6ORMTF_cjs.useAudioVisualization; }
|
|
1014
1014
|
});
|
|
1015
1015
|
Object.defineProperty(exports, "useHybridAudio", {
|
|
1016
1016
|
enumerable: true,
|
|
1017
|
-
get: function () { return
|
|
1017
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudio; }
|
|
1018
1018
|
});
|
|
1019
1019
|
Object.defineProperty(exports, "useHybridAudioAnalysis", {
|
|
1020
1020
|
enumerable: true,
|
|
1021
|
-
get: function () { return
|
|
1021
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudioAnalysis; }
|
|
1022
1022
|
});
|
|
1023
1023
|
Object.defineProperty(exports, "useHybridAudioContext", {
|
|
1024
1024
|
enumerable: true,
|
|
1025
|
-
get: function () { return
|
|
1025
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudioContext; }
|
|
1026
1026
|
});
|
|
1027
1027
|
Object.defineProperty(exports, "useHybridAudioControls", {
|
|
1028
1028
|
enumerable: true,
|
|
1029
|
-
get: function () { return
|
|
1029
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudioControls; }
|
|
1030
1030
|
});
|
|
1031
1031
|
Object.defineProperty(exports, "useHybridAudioLevels", {
|
|
1032
1032
|
enumerable: true,
|
|
1033
|
-
get: function () { return
|
|
1033
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudioLevels; }
|
|
1034
1034
|
});
|
|
1035
1035
|
Object.defineProperty(exports, "useHybridAudioState", {
|
|
1036
1036
|
enumerable: true,
|
|
1037
|
-
get: function () { return
|
|
1037
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridAudioState; }
|
|
1038
1038
|
});
|
|
1039
1039
|
Object.defineProperty(exports, "useHybridWebAudio", {
|
|
1040
1040
|
enumerable: true,
|
|
1041
|
-
get: function () { return
|
|
1041
|
+
get: function () { return chunkDF6ORMTF_cjs.useHybridWebAudio; }
|
|
1042
1042
|
});
|
|
1043
1043
|
Object.defineProperty(exports, "useVisualization", {
|
|
1044
1044
|
enumerable: true,
|
|
1045
|
-
get: function () { return
|
|
1045
|
+
get: function () { return chunkDF6ORMTF_cjs.useVisualization; }
|
|
1046
1046
|
});
|
|
1047
1047
|
Object.defineProperty(exports, "NativeProvider", {
|
|
1048
1048
|
enumerable: true,
|
package/dist/index.d.cts
CHANGED
|
@@ -842,6 +842,8 @@ interface HybridCompactPlayerProps {
|
|
|
842
842
|
waveformMode?: 'frequency' | 'static';
|
|
843
843
|
/** Show timer */
|
|
844
844
|
showTimer?: boolean;
|
|
845
|
+
/** Button size — 'sm' (h-6 w-6) | 'md' (h-8 w-8, default) */
|
|
846
|
+
buttonSize?: 'sm' | 'md';
|
|
845
847
|
/** Additional class name */
|
|
846
848
|
className?: string;
|
|
847
849
|
/** Callbacks */
|
package/dist/index.d.ts
CHANGED
|
@@ -842,6 +842,8 @@ interface HybridCompactPlayerProps {
|
|
|
842
842
|
waveformMode?: 'frequency' | 'static';
|
|
843
843
|
/** Show timer */
|
|
844
844
|
showTimer?: boolean;
|
|
845
|
+
/** Button size — 'sm' (h-6 w-6) | 'md' (h-8 w-8, default) */
|
|
846
|
+
buttonSize?: 'sm' | 'md';
|
|
845
847
|
/** Additional class name */
|
|
846
848
|
className?: string;
|
|
847
849
|
/** Callbacks */
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AudioReactiveCover, COLOR_SCHEMES, COLOR_SCHEME_INFO, EFFECT_ANIMATIONS, GlowEffect, HybridAudioPlayer, HybridAudioProvider, HybridSimplePlayer, HybridWaveform, INTENSITY_CONFIG, INTENSITY_INFO, MeshEffect, OrbsEffect, SpotlightEffect, VARIANT_INFO, VisualizationProvider, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, formatTime, getColors, getEffectConfig, prepareEffectColors, useAudioBus, useAudioBusStore, useAudioVisualization, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useVisualization } from './chunk-
|
|
1
|
+
export { AudioReactiveCover, COLOR_SCHEMES, COLOR_SCHEME_INFO, EFFECT_ANIMATIONS, GlowEffect, HybridAudioPlayer, HybridAudioProvider, HybridSimplePlayer, HybridWaveform, INTENSITY_CONFIG, INTENSITY_INFO, MeshEffect, OrbsEffect, SpotlightEffect, VARIANT_INFO, VisualizationProvider, calculateGlowLayers, calculateMeshGradients, calculateOrbs, calculateSpotlight, formatTime, getColors, getEffectConfig, prepareEffectColors, useAudioBus, useAudioBusStore, useAudioVisualization, useHybridAudio, useHybridAudioAnalysis, useHybridAudioContext, useHybridAudioControls, useHybridAudioLevels, useHybridAudioState, useHybridWebAudio, useVisualization } from './chunk-52WXASRO.mjs';
|
|
2
2
|
export { NativeProvider, StreamProvider, VideoControls, VideoErrorFallback, VideoPlayer, VideoPlayerProvider, VidstackProvider, createVideoErrorFallback, isSimpleStreamSource, resolveFileSource, resolvePlayerMode, resolveStreamSource, useVideoPlayerContext } from './chunk-QKG4LERV.mjs';
|
|
3
3
|
import './chunk-JWB2EWQO.mjs';
|
|
4
4
|
export { ImageViewer } from './chunk-BEURMR25.mjs';
|
|
@@ -767,21 +767,21 @@ function AudioLoadingFallback() {
|
|
|
767
767
|
}
|
|
768
768
|
__name(AudioLoadingFallback, "AudioLoadingFallback");
|
|
769
769
|
var LazyHybridAudioPlayer = createLazyComponent(
|
|
770
|
-
() => import('./components-
|
|
770
|
+
() => import('./components-YWYUZQIH.mjs').then((mod) => ({ default: mod.HybridAudioPlayer })),
|
|
771
771
|
{
|
|
772
772
|
displayName: "LazyHybridAudioPlayer",
|
|
773
773
|
fallback: /* @__PURE__ */ jsx(AudioLoadingFallback, {})
|
|
774
774
|
}
|
|
775
775
|
);
|
|
776
776
|
var LazyHybridSimplePlayer = createLazyComponent(
|
|
777
|
-
() => import('./components-
|
|
777
|
+
() => import('./components-YWYUZQIH.mjs').then((mod) => ({ default: mod.HybridSimplePlayer })),
|
|
778
778
|
{
|
|
779
779
|
displayName: "LazyHybridSimplePlayer",
|
|
780
780
|
fallback: /* @__PURE__ */ jsx(AudioLoadingFallback, {})
|
|
781
781
|
}
|
|
782
782
|
);
|
|
783
783
|
var LazyHybridCompactPlayer = createLazyComponent(
|
|
784
|
-
() => import('./components-
|
|
784
|
+
() => import('./components-YWYUZQIH.mjs').then((mod) => ({ default: mod.HybridCompactPlayer })),
|
|
785
785
|
{
|
|
786
786
|
displayName: "LazyHybridCompactPlayer",
|
|
787
787
|
fallback: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 h-8 px-1 animate-pulse", children: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-tools",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.210",
|
|
4
4
|
"description": "Heavy React tools with lazy loading - for Electron, Vite, CRA, Next.js apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-tools",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"check": "tsc --noEmit"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@djangocfg/i18n": "^2.1.
|
|
82
|
-
"@djangocfg/ui-core": "^2.1.
|
|
81
|
+
"@djangocfg/i18n": "^2.1.210",
|
|
82
|
+
"@djangocfg/ui-core": "^2.1.210",
|
|
83
83
|
"lucide-react": "^0.545.0",
|
|
84
84
|
"react": "^19.0.0",
|
|
85
85
|
"react-dom": "^19.0.0",
|
|
@@ -112,10 +112,10 @@
|
|
|
112
112
|
"@maplibre/maplibre-gl-geocoder": "^1.7.0"
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
115
|
-
"@djangocfg/i18n": "^2.1.
|
|
115
|
+
"@djangocfg/i18n": "^2.1.210",
|
|
116
116
|
"@djangocfg/playground": "workspace:*",
|
|
117
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
118
|
-
"@djangocfg/ui-core": "^2.1.
|
|
117
|
+
"@djangocfg/typescript-config": "^2.1.210",
|
|
118
|
+
"@djangocfg/ui-core": "^2.1.210",
|
|
119
119
|
"@types/mapbox__mapbox-gl-draw": "^1.4.8",
|
|
120
120
|
"@types/node": "^24.7.2",
|
|
121
121
|
"@types/react": "^19.1.0",
|
|
@@ -121,3 +121,14 @@ export const CompactNoTimer = () => (
|
|
|
121
121
|
/>
|
|
122
122
|
</div>
|
|
123
123
|
);
|
|
124
|
+
|
|
125
|
+
export const CompactSmall = () => (
|
|
126
|
+
<div className="max-w-sm space-y-2">
|
|
127
|
+
<p className="text-sm text-muted-foreground mb-3">
|
|
128
|
+
Small button size — for inline use in lists and cards.
|
|
129
|
+
</p>
|
|
130
|
+
<HybridCompactPlayer src={AUDIO_SAMPLES.sample1} title="Track 1" buttonSize="sm" />
|
|
131
|
+
<HybridCompactPlayer src={AUDIO_SAMPLES.sample2} title="Track 2" buttonSize="sm" waveformMode="static" />
|
|
132
|
+
<HybridCompactPlayer src={AUDIO_SAMPLES.sample3} title="Track 3" buttonSize="sm" showTimer={false} />
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
@@ -179,6 +179,7 @@ Single-row player — play/pause + waveform + timer. No cover art, no volume sli
|
|
|
179
179
|
| `title` | `string` | - | Tooltip / aria-label |
|
|
180
180
|
| `waveformMode` | `'frequency' \| 'static'` | `'frequency'` | Visualization mode |
|
|
181
181
|
| `showTimer` | `boolean` | `true` | Show current/total time |
|
|
182
|
+
| `buttonSize` | `'sm' \| 'md'` | `'md'` | Play button size (`sm` = h-6 w-6, `md` = h-8 w-8) |
|
|
182
183
|
| `autoPlay` | `boolean` | `false` | Auto-play on load |
|
|
183
184
|
| `loop` | `boolean` | `false` | Loop playback |
|
|
184
185
|
| `initialVolume` | `number` | `1` | Initial volume 0-1 |
|
|
@@ -43,6 +43,8 @@ export interface HybridCompactPlayerProps {
|
|
|
43
43
|
waveformMode?: 'frequency' | 'static';
|
|
44
44
|
/** Show timer */
|
|
45
45
|
showTimer?: boolean;
|
|
46
|
+
/** Button size — 'sm' (h-6 w-6) | 'md' (h-8 w-8, default) */
|
|
47
|
+
buttonSize?: 'sm' | 'md';
|
|
46
48
|
/** Additional class name */
|
|
47
49
|
className?: string;
|
|
48
50
|
/** Callbacks */
|
|
@@ -64,6 +66,7 @@ export function HybridCompactPlayer({
|
|
|
64
66
|
initialVolume = 1,
|
|
65
67
|
waveformMode = 'frequency',
|
|
66
68
|
showTimer = true,
|
|
69
|
+
buttonSize = 'md',
|
|
67
70
|
className,
|
|
68
71
|
onPlay,
|
|
69
72
|
onPause,
|
|
@@ -85,6 +88,7 @@ export function HybridCompactPlayer({
|
|
|
85
88
|
title={title}
|
|
86
89
|
waveformMode={waveformMode}
|
|
87
90
|
showTimer={showTimer}
|
|
91
|
+
buttonSize={buttonSize}
|
|
88
92
|
className={className}
|
|
89
93
|
/>
|
|
90
94
|
</HybridAudioProvider>
|
|
@@ -95,14 +99,20 @@ export function HybridCompactPlayer({
|
|
|
95
99
|
// INNER (needs context)
|
|
96
100
|
// =============================================================================
|
|
97
101
|
|
|
102
|
+
const BUTTON_SIZE = {
|
|
103
|
+
sm: 'h-6 w-6',
|
|
104
|
+
md: 'h-8 w-8',
|
|
105
|
+
} as const;
|
|
106
|
+
|
|
98
107
|
interface InnerProps {
|
|
99
108
|
title?: string;
|
|
100
109
|
waveformMode: 'frequency' | 'static';
|
|
101
110
|
showTimer: boolean;
|
|
111
|
+
buttonSize: 'sm' | 'md';
|
|
102
112
|
className?: string;
|
|
103
113
|
}
|
|
104
114
|
|
|
105
|
-
function HybridCompactPlayerInner({ title, waveformMode, showTimer, className }: InnerProps) {
|
|
115
|
+
function HybridCompactPlayerInner({ title, waveformMode, showTimer, buttonSize, className }: InnerProps) {
|
|
106
116
|
const { state, controls } = useHybridAudioContext();
|
|
107
117
|
const isLoading = !state.isReady;
|
|
108
118
|
|
|
@@ -112,7 +122,7 @@ function HybridCompactPlayerInner({ title, waveformMode, showTimer, className }:
|
|
|
112
122
|
<Button
|
|
113
123
|
variant="outline"
|
|
114
124
|
size="icon"
|
|
115
|
-
className=
|
|
125
|
+
className={cn(BUTTON_SIZE[buttonSize], 'flex-shrink-0')}
|
|
116
126
|
onClick={controls.togglePlay}
|
|
117
127
|
disabled={!state.isReady && !isLoading}
|
|
118
128
|
title={title ?? (state.isPlaying ? 'Pause' : 'Play')}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { useRef, useEffect, useCallback, memo } from 'react';
|
|
17
17
|
import { useHybridAudioContext } from '../context/HybridAudioProvider';
|
|
18
18
|
import { cn } from '@djangocfg/ui-core/lib';
|
|
19
|
+
import { useThemeColor } from '@djangocfg/ui-core/styles/palette';
|
|
19
20
|
|
|
20
21
|
// =============================================================================
|
|
21
22
|
// TYPES
|
|
@@ -54,12 +55,18 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
54
55
|
barWidth = 3,
|
|
55
56
|
barGap = 2,
|
|
56
57
|
barRadius = 2,
|
|
57
|
-
progressColor
|
|
58
|
-
waveColor
|
|
59
|
-
bufferedColor
|
|
58
|
+
progressColor,
|
|
59
|
+
waveColor,
|
|
60
|
+
bufferedColor,
|
|
60
61
|
className,
|
|
61
62
|
onSeek,
|
|
62
63
|
}: HybridWaveformProps) {
|
|
64
|
+
const themePrimary = useThemeColor('primary');
|
|
65
|
+
const themePrimaryWave = useThemeColor('primary', 0.3);
|
|
66
|
+
const themePrimaryBuffered = useThemeColor('primary', 0.15);
|
|
67
|
+
const resolvedProgressColor = progressColor ?? themePrimary;
|
|
68
|
+
const resolvedWaveColor = waveColor ?? themePrimaryWave;
|
|
69
|
+
const resolvedBufferedColor = bufferedColor ?? themePrimaryBuffered;
|
|
63
70
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
64
71
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
65
72
|
const animationRef = useRef<number | null>(null);
|
|
@@ -106,7 +113,7 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
106
113
|
|
|
107
114
|
// Draw buffered regions at bottom
|
|
108
115
|
if (state.buffered && state.duration > 0) {
|
|
109
|
-
ctx.fillStyle =
|
|
116
|
+
ctx.fillStyle = resolvedBufferedColor;
|
|
110
117
|
for (let i = 0; i < state.buffered.length; i++) {
|
|
111
118
|
const start = (state.buffered.start(i) / state.duration) * width;
|
|
112
119
|
const end = (state.buffered.end(i) / state.duration) * width;
|
|
@@ -136,7 +143,7 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
136
143
|
const x = i * (barWidth + barGap) * dpr;
|
|
137
144
|
const y = (canvasHeight - barHeight) / 2;
|
|
138
145
|
|
|
139
|
-
ctx.fillStyle = x < progressX ?
|
|
146
|
+
ctx.fillStyle = x < progressX ? resolvedProgressColor : resolvedWaveColor;
|
|
140
147
|
|
|
141
148
|
// Draw rounded rect
|
|
142
149
|
const radius = barRadius * dpr;
|
|
@@ -159,9 +166,9 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
159
166
|
barWidth,
|
|
160
167
|
barGap,
|
|
161
168
|
barRadius,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
resolvedProgressColor,
|
|
170
|
+
resolvedWaveColor,
|
|
171
|
+
resolvedBufferedColor,
|
|
165
172
|
]);
|
|
166
173
|
|
|
167
174
|
// Render static progress bar
|
|
@@ -179,7 +186,7 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
179
186
|
|
|
180
187
|
// Draw buffered regions
|
|
181
188
|
if (state.buffered && state.duration > 0) {
|
|
182
|
-
ctx.fillStyle =
|
|
189
|
+
ctx.fillStyle = resolvedBufferedColor;
|
|
183
190
|
for (let i = 0; i < state.buffered.length; i++) {
|
|
184
191
|
const start = (state.buffered.start(i) / state.duration) * width;
|
|
185
192
|
const end = (state.buffered.end(i) / state.duration) * width;
|
|
@@ -192,11 +199,11 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
192
199
|
const progressWidth = width * progress;
|
|
193
200
|
|
|
194
201
|
// Background
|
|
195
|
-
ctx.fillStyle =
|
|
202
|
+
ctx.fillStyle = resolvedWaveColor;
|
|
196
203
|
ctx.fillRect(0, canvasHeight / 2 - 2 * dpr, width, 4 * dpr);
|
|
197
204
|
|
|
198
205
|
// Progress
|
|
199
|
-
ctx.fillStyle =
|
|
206
|
+
ctx.fillStyle = resolvedProgressColor;
|
|
200
207
|
ctx.fillRect(0, canvasHeight / 2 - 2 * dpr, progressWidth, 4 * dpr);
|
|
201
208
|
|
|
202
209
|
// Handle
|
|
@@ -205,7 +212,7 @@ export const HybridWaveform = memo(function HybridWaveform({
|
|
|
205
212
|
ctx.arc(progressWidth, canvasHeight / 2, 6 * dpr, 0, Math.PI * 2);
|
|
206
213
|
ctx.fill();
|
|
207
214
|
}
|
|
208
|
-
}, [state.buffered, state.duration, state.currentTime,
|
|
215
|
+
}, [state.buffered, state.duration, state.currentTime, resolvedProgressColor, resolvedWaveColor, resolvedBufferedColor]);
|
|
209
216
|
|
|
210
217
|
// Resize canvas to match container
|
|
211
218
|
useEffect(() => {
|