@twick/studio 0.15.3 → 0.15.5
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.d.ts +88 -11
- package/dist/index.js +228 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +79 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
package/dist/index.d.ts
CHANGED
|
@@ -45,22 +45,99 @@ export * from './helpers/generate-subtitles.service';
|
|
|
45
45
|
export * from './helpers/constant';
|
|
46
46
|
export * from './types';
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* ============================================================================
|
|
49
|
+
* RE-EXPORTS FROM DEPENDENCY PACKAGES
|
|
50
|
+
* ============================================================================
|
|
49
51
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* are automatically installed when you install @twick/studio.
|
|
52
|
+
* The @twick/studio package re-exports components, hooks, types, and utilities
|
|
53
|
+
* from its dependency packages (@twick/video-editor, @twick/timeline, @twick/live-player).
|
|
53
54
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* -
|
|
55
|
+
* This provides a single entry point for developers using the Twick SDK.
|
|
56
|
+
*
|
|
57
|
+
* Benefits:
|
|
58
|
+
* - Install only `@twick/studio` instead of multiple packages
|
|
59
|
+
* - Import everything from a single package: `import { ... } from '@twick/studio'`
|
|
60
|
+
* - All dependencies are automatically installed and version-matched
|
|
61
|
+
* - Simpler package management and fewer version conflicts
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```jsx
|
|
65
|
+
* // Before: Multiple package imports
|
|
66
|
+
* import { TwickStudio } from '@twick/studio';
|
|
67
|
+
* import { LivePlayer, LivePlayerProvider } from '@twick/live-player';
|
|
68
|
+
* import { TimelineProvider, TimelineEditor } from '@twick/timeline';
|
|
69
|
+
* import { VideoEditor } from '@twick/video-editor';
|
|
70
|
+
*
|
|
71
|
+
* // After: Single package import
|
|
72
|
+
* import {
|
|
73
|
+
* TwickStudio,
|
|
74
|
+
* LivePlayer,
|
|
75
|
+
* LivePlayerProvider,
|
|
76
|
+
* TimelineProvider,
|
|
77
|
+
* TimelineEditor,
|
|
78
|
+
* VideoEditor
|
|
79
|
+
* } from '@twick/studio';
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
/**
|
|
83
|
+
* Main video editor component and related types
|
|
58
84
|
*/
|
|
59
85
|
export { default as VideoEditor } from '@twick/video-editor';
|
|
60
|
-
export type { VideoEditorProps, VideoEditorConfig } from '@twick/video-editor';
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
export type { VideoEditorProps, VideoEditorConfig, TimelineTickConfig, TimelineZoomConfig, PlayerControlsProps } from '@twick/video-editor';
|
|
87
|
+
/**
|
|
88
|
+
* Video editor hooks for custom implementations
|
|
89
|
+
*/
|
|
90
|
+
export { usePlayerControl, useEditorManager, useTimelineControl } from '@twick/video-editor';
|
|
91
|
+
/**
|
|
92
|
+
* Video editor components
|
|
93
|
+
*/
|
|
94
|
+
export { PlayerControls, TimelineManager } from '@twick/video-editor';
|
|
95
|
+
/**
|
|
96
|
+
* Media management utilities
|
|
97
|
+
*/
|
|
98
|
+
export { BrowserMediaManager, BaseMediaManager } from '@twick/video-editor';
|
|
99
|
+
/**
|
|
100
|
+
* Animation and text effect constants
|
|
101
|
+
*/
|
|
102
|
+
export { ANIMATIONS, TEXT_EFFECTS } from '@twick/video-editor';
|
|
103
|
+
/**
|
|
104
|
+
* Editor utility functions and types
|
|
105
|
+
*/
|
|
106
|
+
export { animationGifs, getAnimationGif, setElementColors } from '@twick/video-editor';
|
|
107
|
+
export type { MediaItem, PaginationOptions, SearchOptions, Animation, TextEffect, ElementColors } from '@twick/video-editor';
|
|
108
|
+
/**
|
|
109
|
+
* Live player components and context
|
|
110
|
+
*/
|
|
111
|
+
export { LivePlayerProvider, LivePlayer, useLivePlayerContext } from '@twick/live-player';
|
|
112
|
+
/**
|
|
113
|
+
* Player constants and utilities
|
|
114
|
+
*/
|
|
115
|
+
export { PLAYER_STATE, getBaseProject, generateId } from '@twick/live-player';
|
|
116
|
+
/**
|
|
117
|
+
* Timeline provider and editor
|
|
118
|
+
*/
|
|
119
|
+
export { TimelineProvider, TimelineEditor, INITIAL_TIMELINE_DATA } from '@twick/timeline';
|
|
63
120
|
export type { TimelineProviderProps } from '@twick/timeline';
|
|
121
|
+
/**
|
|
122
|
+
* Timeline element classes
|
|
123
|
+
*/
|
|
124
|
+
export { Track, TrackElement, TextElement, VideoElement, ImageElement, AudioElement, CircleElement, RectElement, IconElement, CaptionElement, ElementAnimation, ElementFrameEffect, ElementTextEffect } from '@twick/timeline';
|
|
125
|
+
/**
|
|
126
|
+
* Timeline visitor pattern classes for element manipulation
|
|
127
|
+
*/
|
|
128
|
+
export { ElementSerializer, ElementDeserializer, ElementValidator, ElementAdder, ElementRemover, ElementUpdater, ElementSplitter, ElementCloner } from '@twick/timeline';
|
|
129
|
+
/**
|
|
130
|
+
* Timeline utilities and helpers
|
|
131
|
+
*/
|
|
132
|
+
export { generateShortUuid, getTotalDuration, getCurrentElements, isTrackId, isElementId, TIMELINE_ELEMENT_TYPE } from '@twick/timeline';
|
|
133
|
+
/**
|
|
134
|
+
* Timeline types
|
|
135
|
+
*/
|
|
136
|
+
export type { ProjectJSON, Size, Position, Frame, ElementJSON, TrackJSON, VideoProps, AudioProps, ImageProps, TextProps, RectProps, CircleProps, IconProps, TextEffect as TimelineTextEffect, FrameEffect, FrameEffectProps, Animation as TimelineAnimation, ObjectFit, TextAlign, BaseMediaProps } from '@twick/timeline';
|
|
137
|
+
/**
|
|
138
|
+
* Timeline constants
|
|
139
|
+
*/
|
|
140
|
+
export { CAPTION_STYLE, CAPTION_STYLE_OPTIONS, CAPTION_FONT, CAPTION_COLOR, WORDS_PER_PHRASE, TIMELINE_ACTION, PROCESS_STATE } from '@twick/timeline';
|
|
64
141
|
/**
|
|
65
142
|
* Default export: TwickStudio (full editor component)
|
|
66
143
|
*/
|
package/dist/index.js
CHANGED
|
@@ -2833,11 +2833,25 @@ function PropsToolbar({
|
|
|
2833
2833
|
}) });
|
|
2834
2834
|
}
|
|
2835
2835
|
function ElementProps({ selectedElement, updateElement }) {
|
|
2836
|
-
const
|
|
2837
|
-
const
|
|
2838
|
-
const
|
|
2836
|
+
const opacity = (selectedElement == null ? void 0 : selectedElement.getOpacity()) || 1;
|
|
2837
|
+
const rotation = (selectedElement == null ? void 0 : selectedElement.getRotation()) || 0;
|
|
2838
|
+
const position = (selectedElement == null ? void 0 : selectedElement.getPosition()) || { x: 0, y: 0 };
|
|
2839
|
+
const handleRotationChange = (rotation2) => {
|
|
2839
2840
|
if (selectedElement) {
|
|
2840
|
-
|
|
2841
|
+
selectedElement.setRotation(rotation2);
|
|
2842
|
+
updateElement == null ? void 0 : updateElement(selectedElement);
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
const handleOpacityChange = (opacity2) => {
|
|
2846
|
+
if (selectedElement) {
|
|
2847
|
+
selectedElement.setOpacity(opacity2);
|
|
2848
|
+
updateElement == null ? void 0 : updateElement(selectedElement);
|
|
2849
|
+
}
|
|
2850
|
+
};
|
|
2851
|
+
const handlePositionChange = (props) => {
|
|
2852
|
+
if (selectedElement) {
|
|
2853
|
+
selectedElement.setPosition({ x: props.x ?? 0, y: props.y ?? 0 });
|
|
2854
|
+
updateElement == null ? void 0 : updateElement(selectedElement);
|
|
2841
2855
|
}
|
|
2842
2856
|
};
|
|
2843
2857
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-container", children: [
|
|
@@ -2851,8 +2865,8 @@ function ElementProps({ selectedElement, updateElement }) {
|
|
|
2851
2865
|
"input",
|
|
2852
2866
|
{
|
|
2853
2867
|
type: "number",
|
|
2854
|
-
value: x ?? 0,
|
|
2855
|
-
onChange: (e) =>
|
|
2868
|
+
value: position.x ?? 0,
|
|
2869
|
+
onChange: (e) => handlePositionChange({ x: Number(e.target.value) }),
|
|
2856
2870
|
className: "input-dark"
|
|
2857
2871
|
}
|
|
2858
2872
|
)
|
|
@@ -2863,8 +2877,8 @@ function ElementProps({ selectedElement, updateElement }) {
|
|
|
2863
2877
|
"input",
|
|
2864
2878
|
{
|
|
2865
2879
|
type: "number",
|
|
2866
|
-
value: y ?? 0,
|
|
2867
|
-
onChange: (e) =>
|
|
2880
|
+
value: position.y ?? 0,
|
|
2881
|
+
onChange: (e) => handlePositionChange({ y: Number(e.target.value) }),
|
|
2868
2882
|
className: "input-dark"
|
|
2869
2883
|
}
|
|
2870
2884
|
)
|
|
@@ -2881,7 +2895,7 @@ function ElementProps({ selectedElement, updateElement }) {
|
|
|
2881
2895
|
min: "0",
|
|
2882
2896
|
max: "100",
|
|
2883
2897
|
value: (opacity ?? 1) * 100,
|
|
2884
|
-
onChange: (e) =>
|
|
2898
|
+
onChange: (e) => handleOpacityChange(Number(e.target.value) / 100),
|
|
2885
2899
|
className: "slider-purple"
|
|
2886
2900
|
}
|
|
2887
2901
|
),
|
|
@@ -2901,7 +2915,7 @@ function ElementProps({ selectedElement, updateElement }) {
|
|
|
2901
2915
|
min: "0",
|
|
2902
2916
|
max: "360",
|
|
2903
2917
|
value: rotation ?? 0,
|
|
2904
|
-
onChange: (e) =>
|
|
2918
|
+
onChange: (e) => handleRotationChange(Number(e.target.value)),
|
|
2905
2919
|
className: "slider-purple"
|
|
2906
2920
|
}
|
|
2907
2921
|
),
|
|
@@ -3747,15 +3761,203 @@ function TwickStudio({ studioConfig }) {
|
|
|
3747
3761
|
] })
|
|
3748
3762
|
] }) });
|
|
3749
3763
|
}
|
|
3764
|
+
Object.defineProperty(exports, "AudioElement", {
|
|
3765
|
+
enumerable: true,
|
|
3766
|
+
get: () => timeline.AudioElement
|
|
3767
|
+
});
|
|
3768
|
+
Object.defineProperty(exports, "CAPTION_COLOR", {
|
|
3769
|
+
enumerable: true,
|
|
3770
|
+
get: () => timeline.CAPTION_COLOR
|
|
3771
|
+
});
|
|
3772
|
+
Object.defineProperty(exports, "CAPTION_FONT", {
|
|
3773
|
+
enumerable: true,
|
|
3774
|
+
get: () => timeline.CAPTION_FONT
|
|
3775
|
+
});
|
|
3776
|
+
Object.defineProperty(exports, "CAPTION_STYLE", {
|
|
3777
|
+
enumerable: true,
|
|
3778
|
+
get: () => timeline.CAPTION_STYLE
|
|
3779
|
+
});
|
|
3780
|
+
Object.defineProperty(exports, "CAPTION_STYLE_OPTIONS", {
|
|
3781
|
+
enumerable: true,
|
|
3782
|
+
get: () => timeline.CAPTION_STYLE_OPTIONS
|
|
3783
|
+
});
|
|
3784
|
+
Object.defineProperty(exports, "CaptionElement", {
|
|
3785
|
+
enumerable: true,
|
|
3786
|
+
get: () => timeline.CaptionElement
|
|
3787
|
+
});
|
|
3788
|
+
Object.defineProperty(exports, "CircleElement", {
|
|
3789
|
+
enumerable: true,
|
|
3790
|
+
get: () => timeline.CircleElement
|
|
3791
|
+
});
|
|
3792
|
+
Object.defineProperty(exports, "ElementAdder", {
|
|
3793
|
+
enumerable: true,
|
|
3794
|
+
get: () => timeline.ElementAdder
|
|
3795
|
+
});
|
|
3796
|
+
Object.defineProperty(exports, "ElementAnimation", {
|
|
3797
|
+
enumerable: true,
|
|
3798
|
+
get: () => timeline.ElementAnimation
|
|
3799
|
+
});
|
|
3800
|
+
Object.defineProperty(exports, "ElementCloner", {
|
|
3801
|
+
enumerable: true,
|
|
3802
|
+
get: () => timeline.ElementCloner
|
|
3803
|
+
});
|
|
3804
|
+
Object.defineProperty(exports, "ElementDeserializer", {
|
|
3805
|
+
enumerable: true,
|
|
3806
|
+
get: () => timeline.ElementDeserializer
|
|
3807
|
+
});
|
|
3808
|
+
Object.defineProperty(exports, "ElementFrameEffect", {
|
|
3809
|
+
enumerable: true,
|
|
3810
|
+
get: () => timeline.ElementFrameEffect
|
|
3811
|
+
});
|
|
3812
|
+
Object.defineProperty(exports, "ElementRemover", {
|
|
3813
|
+
enumerable: true,
|
|
3814
|
+
get: () => timeline.ElementRemover
|
|
3815
|
+
});
|
|
3816
|
+
Object.defineProperty(exports, "ElementSerializer", {
|
|
3817
|
+
enumerable: true,
|
|
3818
|
+
get: () => timeline.ElementSerializer
|
|
3819
|
+
});
|
|
3820
|
+
Object.defineProperty(exports, "ElementSplitter", {
|
|
3821
|
+
enumerable: true,
|
|
3822
|
+
get: () => timeline.ElementSplitter
|
|
3823
|
+
});
|
|
3824
|
+
Object.defineProperty(exports, "ElementTextEffect", {
|
|
3825
|
+
enumerable: true,
|
|
3826
|
+
get: () => timeline.ElementTextEffect
|
|
3827
|
+
});
|
|
3828
|
+
Object.defineProperty(exports, "ElementUpdater", {
|
|
3829
|
+
enumerable: true,
|
|
3830
|
+
get: () => timeline.ElementUpdater
|
|
3831
|
+
});
|
|
3832
|
+
Object.defineProperty(exports, "ElementValidator", {
|
|
3833
|
+
enumerable: true,
|
|
3834
|
+
get: () => timeline.ElementValidator
|
|
3835
|
+
});
|
|
3750
3836
|
Object.defineProperty(exports, "INITIAL_TIMELINE_DATA", {
|
|
3751
3837
|
enumerable: true,
|
|
3752
3838
|
get: () => timeline.INITIAL_TIMELINE_DATA
|
|
3753
3839
|
});
|
|
3840
|
+
Object.defineProperty(exports, "IconElement", {
|
|
3841
|
+
enumerable: true,
|
|
3842
|
+
get: () => timeline.IconElement
|
|
3843
|
+
});
|
|
3844
|
+
Object.defineProperty(exports, "ImageElement", {
|
|
3845
|
+
enumerable: true,
|
|
3846
|
+
get: () => timeline.ImageElement
|
|
3847
|
+
});
|
|
3848
|
+
Object.defineProperty(exports, "PROCESS_STATE", {
|
|
3849
|
+
enumerable: true,
|
|
3850
|
+
get: () => timeline.PROCESS_STATE
|
|
3851
|
+
});
|
|
3852
|
+
Object.defineProperty(exports, "RectElement", {
|
|
3853
|
+
enumerable: true,
|
|
3854
|
+
get: () => timeline.RectElement
|
|
3855
|
+
});
|
|
3856
|
+
Object.defineProperty(exports, "TIMELINE_ACTION", {
|
|
3857
|
+
enumerable: true,
|
|
3858
|
+
get: () => timeline.TIMELINE_ACTION
|
|
3859
|
+
});
|
|
3860
|
+
Object.defineProperty(exports, "TIMELINE_ELEMENT_TYPE", {
|
|
3861
|
+
enumerable: true,
|
|
3862
|
+
get: () => timeline.TIMELINE_ELEMENT_TYPE
|
|
3863
|
+
});
|
|
3864
|
+
Object.defineProperty(exports, "TextElement", {
|
|
3865
|
+
enumerable: true,
|
|
3866
|
+
get: () => timeline.TextElement
|
|
3867
|
+
});
|
|
3868
|
+
Object.defineProperty(exports, "TimelineEditor", {
|
|
3869
|
+
enumerable: true,
|
|
3870
|
+
get: () => timeline.TimelineEditor
|
|
3871
|
+
});
|
|
3754
3872
|
Object.defineProperty(exports, "TimelineProvider", {
|
|
3755
3873
|
enumerable: true,
|
|
3756
3874
|
get: () => timeline.TimelineProvider
|
|
3757
3875
|
});
|
|
3876
|
+
Object.defineProperty(exports, "Track", {
|
|
3877
|
+
enumerable: true,
|
|
3878
|
+
get: () => timeline.Track
|
|
3879
|
+
});
|
|
3880
|
+
Object.defineProperty(exports, "TrackElement", {
|
|
3881
|
+
enumerable: true,
|
|
3882
|
+
get: () => timeline.TrackElement
|
|
3883
|
+
});
|
|
3884
|
+
Object.defineProperty(exports, "VideoElement", {
|
|
3885
|
+
enumerable: true,
|
|
3886
|
+
get: () => timeline.VideoElement
|
|
3887
|
+
});
|
|
3888
|
+
Object.defineProperty(exports, "WORDS_PER_PHRASE", {
|
|
3889
|
+
enumerable: true,
|
|
3890
|
+
get: () => timeline.WORDS_PER_PHRASE
|
|
3891
|
+
});
|
|
3892
|
+
Object.defineProperty(exports, "generateShortUuid", {
|
|
3893
|
+
enumerable: true,
|
|
3894
|
+
get: () => timeline.generateShortUuid
|
|
3895
|
+
});
|
|
3896
|
+
Object.defineProperty(exports, "getCurrentElements", {
|
|
3897
|
+
enumerable: true,
|
|
3898
|
+
get: () => timeline.getCurrentElements
|
|
3899
|
+
});
|
|
3900
|
+
Object.defineProperty(exports, "getTotalDuration", {
|
|
3901
|
+
enumerable: true,
|
|
3902
|
+
get: () => timeline.getTotalDuration
|
|
3903
|
+
});
|
|
3904
|
+
Object.defineProperty(exports, "isElementId", {
|
|
3905
|
+
enumerable: true,
|
|
3906
|
+
get: () => timeline.isElementId
|
|
3907
|
+
});
|
|
3908
|
+
Object.defineProperty(exports, "isTrackId", {
|
|
3909
|
+
enumerable: true,
|
|
3910
|
+
get: () => timeline.isTrackId
|
|
3911
|
+
});
|
|
3912
|
+
Object.defineProperty(exports, "ANIMATIONS", {
|
|
3913
|
+
enumerable: true,
|
|
3914
|
+
get: () => VideoEditor.ANIMATIONS
|
|
3915
|
+
});
|
|
3916
|
+
Object.defineProperty(exports, "BaseMediaManager", {
|
|
3917
|
+
enumerable: true,
|
|
3918
|
+
get: () => VideoEditor.BaseMediaManager
|
|
3919
|
+
});
|
|
3920
|
+
Object.defineProperty(exports, "BrowserMediaManager", {
|
|
3921
|
+
enumerable: true,
|
|
3922
|
+
get: () => VideoEditor.BrowserMediaManager
|
|
3923
|
+
});
|
|
3924
|
+
Object.defineProperty(exports, "PlayerControls", {
|
|
3925
|
+
enumerable: true,
|
|
3926
|
+
get: () => VideoEditor.PlayerControls
|
|
3927
|
+
});
|
|
3928
|
+
Object.defineProperty(exports, "TEXT_EFFECTS", {
|
|
3929
|
+
enumerable: true,
|
|
3930
|
+
get: () => VideoEditor.TEXT_EFFECTS
|
|
3931
|
+
});
|
|
3932
|
+
Object.defineProperty(exports, "TimelineManager", {
|
|
3933
|
+
enumerable: true,
|
|
3934
|
+
get: () => VideoEditor.TimelineManager
|
|
3935
|
+
});
|
|
3758
3936
|
exports.VideoEditor = VideoEditor;
|
|
3937
|
+
Object.defineProperty(exports, "animationGifs", {
|
|
3938
|
+
enumerable: true,
|
|
3939
|
+
get: () => VideoEditor.animationGifs
|
|
3940
|
+
});
|
|
3941
|
+
Object.defineProperty(exports, "getAnimationGif", {
|
|
3942
|
+
enumerable: true,
|
|
3943
|
+
get: () => VideoEditor.getAnimationGif
|
|
3944
|
+
});
|
|
3945
|
+
Object.defineProperty(exports, "setElementColors", {
|
|
3946
|
+
enumerable: true,
|
|
3947
|
+
get: () => VideoEditor.setElementColors
|
|
3948
|
+
});
|
|
3949
|
+
Object.defineProperty(exports, "useEditorManager", {
|
|
3950
|
+
enumerable: true,
|
|
3951
|
+
get: () => VideoEditor.useEditorManager
|
|
3952
|
+
});
|
|
3953
|
+
Object.defineProperty(exports, "usePlayerControl", {
|
|
3954
|
+
enumerable: true,
|
|
3955
|
+
get: () => VideoEditor.usePlayerControl
|
|
3956
|
+
});
|
|
3957
|
+
Object.defineProperty(exports, "useTimelineControl", {
|
|
3958
|
+
enumerable: true,
|
|
3959
|
+
get: () => VideoEditor.useTimelineControl
|
|
3960
|
+
});
|
|
3759
3961
|
Object.defineProperty(exports, "LivePlayer", {
|
|
3760
3962
|
enumerable: true,
|
|
3761
3963
|
get: () => livePlayer.LivePlayer
|
|
@@ -3764,6 +3966,22 @@ Object.defineProperty(exports, "LivePlayerProvider", {
|
|
|
3764
3966
|
enumerable: true,
|
|
3765
3967
|
get: () => livePlayer.LivePlayerProvider
|
|
3766
3968
|
});
|
|
3969
|
+
Object.defineProperty(exports, "PLAYER_STATE", {
|
|
3970
|
+
enumerable: true,
|
|
3971
|
+
get: () => livePlayer.PLAYER_STATE
|
|
3972
|
+
});
|
|
3973
|
+
Object.defineProperty(exports, "generateId", {
|
|
3974
|
+
enumerable: true,
|
|
3975
|
+
get: () => livePlayer.generateId
|
|
3976
|
+
});
|
|
3977
|
+
Object.defineProperty(exports, "getBaseProject", {
|
|
3978
|
+
enumerable: true,
|
|
3979
|
+
get: () => livePlayer.getBaseProject
|
|
3980
|
+
});
|
|
3981
|
+
Object.defineProperty(exports, "useLivePlayerContext", {
|
|
3982
|
+
enumerable: true,
|
|
3983
|
+
get: () => livePlayer.useLivePlayerContext
|
|
3984
|
+
});
|
|
3767
3985
|
exports.AudioPanel = AudioPanel;
|
|
3768
3986
|
exports.CAPTION_PROPS = CAPTION_PROPS;
|
|
3769
3987
|
exports.CirclePanel = CirclePanel;
|