@launchdarkly/toolbar 0.8.0 → 0.9.1
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/js/index.js +232 -29
- package/dist/ui/Toolbar/LaunchDarklyToolbar.d.ts +4 -5
- package/dist/ui/Toolbar/context/LaunchDarklyToolbarProvider.d.ts +4 -0
- package/dist/ui/Toolbar/hooks/index.d.ts +2 -0
- package/dist/ui/Toolbar/hooks/useKeyPressed.d.ts +1 -0
- package/dist/ui/Toolbar/hooks/useToolbarDrag.d.ts +10 -0
- package/dist/ui/Toolbar/hooks/useToolbarState.d.ts +1 -0
- package/dist/ui/Toolbar/types/toolbar.d.ts +2 -0
- package/dist/ui/Toolbar/utils/localStorage.d.ts +8 -0
- package/dist/utils/deepEqual.d.ts +8 -0
- package/dist/utils/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/js/index.js
CHANGED
|
@@ -2657,23 +2657,56 @@ class FlagStateManager {
|
|
|
2657
2657
|
this.listeners.clear();
|
|
2658
2658
|
}
|
|
2659
2659
|
}
|
|
2660
|
-
const
|
|
2660
|
+
const TAB_ORDER = [
|
|
2661
|
+
'flags',
|
|
2662
|
+
'settings'
|
|
2663
|
+
];
|
|
2664
|
+
const TOOLBAR_POSITIONS = [
|
|
2665
|
+
'left',
|
|
2666
|
+
'right'
|
|
2667
|
+
];
|
|
2668
|
+
const TOOLBAR_STORAGE_KEYS = {
|
|
2669
|
+
POSITION: 'ld-toolbar-position',
|
|
2670
|
+
DISABLED: 'ld-toolbar-disabled',
|
|
2671
|
+
PROJECT: 'ld-toolbar-project'
|
|
2672
|
+
};
|
|
2673
|
+
function saveToolbarPosition(position) {
|
|
2674
|
+
try {
|
|
2675
|
+
localStorage.setItem(TOOLBAR_STORAGE_KEYS.POSITION, position);
|
|
2676
|
+
} catch (error) {
|
|
2677
|
+
console.warn('Failed to save toolbar position to localStorage:', error);
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
function loadToolbarPosition() {
|
|
2681
|
+
try {
|
|
2682
|
+
const position = localStorage.getItem(TOOLBAR_STORAGE_KEYS.POSITION);
|
|
2683
|
+
return position && TOOLBAR_POSITIONS.includes(position) ? position : null;
|
|
2684
|
+
} catch (error) {
|
|
2685
|
+
console.warn('Failed to load toolbar position from localStorage:', error);
|
|
2686
|
+
return null;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
const STORAGE_KEY = TOOLBAR_STORAGE_KEYS.PROJECT;
|
|
2661
2690
|
const LaunchDarklyToolbarContext = /*#__PURE__*/ createContext(null);
|
|
2662
2691
|
const useToolbarContext = ()=>{
|
|
2663
2692
|
const context = useContext(LaunchDarklyToolbarContext);
|
|
2664
2693
|
if (!context) throw new Error('useToolbarContext must be used within LaunchDarklyToolbarProvider');
|
|
2665
2694
|
return context;
|
|
2666
2695
|
};
|
|
2667
|
-
const LaunchDarklyToolbarProvider = ({ children, config })=>{
|
|
2668
|
-
const [toolbarState, setToolbarState] = useState({
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2696
|
+
const LaunchDarklyToolbarProvider = ({ children, config, initialPosition })=>{
|
|
2697
|
+
const [toolbarState, setToolbarState] = useState(()=>{
|
|
2698
|
+
const savedPosition = loadToolbarPosition();
|
|
2699
|
+
return {
|
|
2700
|
+
flags: {},
|
|
2701
|
+
connectionStatus: 'disconnected',
|
|
2702
|
+
lastSyncTime: 0,
|
|
2703
|
+
isLoading: true,
|
|
2704
|
+
error: null,
|
|
2705
|
+
sourceEnvironmentKey: null,
|
|
2706
|
+
availableProjects: [],
|
|
2707
|
+
currentProjectKey: null,
|
|
2708
|
+
position: savedPosition || initialPosition || 'right'
|
|
2709
|
+
};
|
|
2677
2710
|
});
|
|
2678
2711
|
const devServerClient = useMemo(()=>new DevServerClient(config.devServerUrl, config.projectKey), [
|
|
2679
2712
|
config.devServerUrl,
|
|
@@ -2965,20 +2998,29 @@ const LaunchDarklyToolbarProvider = ({ children, config })=>{
|
|
|
2965
2998
|
flagStateManager,
|
|
2966
2999
|
toolbarState.availableProjects
|
|
2967
3000
|
]);
|
|
3001
|
+
const handlePositionChange = useCallback((newPosition)=>{
|
|
3002
|
+
setToolbarState((prev)=>({
|
|
3003
|
+
...prev,
|
|
3004
|
+
position: newPosition
|
|
3005
|
+
}));
|
|
3006
|
+
saveToolbarPosition(newPosition);
|
|
3007
|
+
}, []);
|
|
2968
3008
|
const value = useMemo(()=>({
|
|
2969
3009
|
state: toolbarState,
|
|
2970
3010
|
setOverride,
|
|
2971
3011
|
clearOverride,
|
|
2972
3012
|
clearAllOverrides,
|
|
2973
3013
|
refresh,
|
|
2974
|
-
switchProject
|
|
3014
|
+
switchProject,
|
|
3015
|
+
handlePositionChange
|
|
2975
3016
|
}), [
|
|
2976
3017
|
toolbarState,
|
|
2977
3018
|
setOverride,
|
|
2978
3019
|
clearOverride,
|
|
2979
3020
|
clearAllOverrides,
|
|
2980
3021
|
refresh,
|
|
2981
|
-
switchProject
|
|
3022
|
+
switchProject,
|
|
3023
|
+
handlePositionChange
|
|
2982
3024
|
]);
|
|
2983
3025
|
return /*#__PURE__*/ jsx(LaunchDarklyToolbarContext.Provider, {
|
|
2984
3026
|
value: value,
|
|
@@ -3219,6 +3261,22 @@ function GenericHelpText(props) {
|
|
|
3219
3261
|
]
|
|
3220
3262
|
});
|
|
3221
3263
|
}
|
|
3264
|
+
function deepEqual(a, b) {
|
|
3265
|
+
if (a === b) return true;
|
|
3266
|
+
if (null == a || null == b) return false;
|
|
3267
|
+
if (typeof a !== typeof b) return false;
|
|
3268
|
+
if ('object' == typeof a) {
|
|
3269
|
+
const keysA = Object.keys(a);
|
|
3270
|
+
const keysB = Object.keys(b);
|
|
3271
|
+
if (keysA.length !== keysB.length) return false;
|
|
3272
|
+
for (const key of keysA){
|
|
3273
|
+
if (!keysB.includes(key)) return false;
|
|
3274
|
+
if (!deepEqual(a[key], b[key])) return false;
|
|
3275
|
+
}
|
|
3276
|
+
return true;
|
|
3277
|
+
}
|
|
3278
|
+
return a === b;
|
|
3279
|
+
}
|
|
3222
3280
|
var _3CwGAAA_node_modules_pnpm_vanilla_extract_webpack_plugin_2_3_22_webpack_5_99_9_esbuild_0_25_5_node_modules_vanilla_extract_webpack_plugin_extracted = __webpack_require__("./node_modules/.pnpm/@rsbuild+core@1.4.12/node_modules/@rsbuild/core/compiled/css-loader/index.js??ruleSet[1].rules[2].use[1]!builtin:lightningcss-loader??ruleSet[1].rules[2].use[2]!./node_modules/.pnpm/@vanilla-extract+webpack-plugin@2.3.22_webpack@5.99.9_esbuild@0.25.5_/node_modules/@vanilla-extract/webpack-plugin/virtualFileLoader/dist/vanilla-extract-webpack-plugin-virtualFileLoader.cjs.js?{\"fileName\":\"src/ui/Toolbar/components/FlagControls.css.ts.vanilla.css\",\"source\":\"#H4sIAAAAAAAAA72UzXLCIBCA73mKvXSmPeAk0fqDxz5IhwRMdorAAJrYju/eCUYTrbXqtD2ywMfut8DgdaI3az+O4SMCWGjlicN3QSFJTT2PAHIttaWwZvaREGlIGJPCsg0ZxfHTPNpGg5aRBAZHZyTbUFhIEQhMYqEIerF0FHKhvLBNuGCGwrQ5pE+QLBMycDKWvxVWrxQnbQ7eMuUMs0L5/qb0pmObacLRityjVhSsrg7ZjHYlL1GRCrkvGwtxG2P1ITaOj7Me3pRAV9d5q7NgFSDTlgtLITE1OC2Rn109OVpNLOO4chTGu6xLgUXpKQzbZma6btqLqqD7HZmu91ooJAcV7QbDOEdVELvjpPcJGgVBF7jxBV97aBw/9JnPgdlyQsG7y/S/gvsPZvTjg0lbVs9fqFyvhV1IXVEokXOhmpgXtSfdhJASjUMXjJToBXGG5YKC0pVl5qSF1/f9ulvbaR8H7Uc9OXPc5afbS7UDT77t532Oezb+QneX+PTkt/pS7K2vZRaAv3wnOjw76uDJR7EfL1BKCvnKNkW8NHbn0fYTl/8/3CwGAAA=\"}!./node_modules/.pnpm/@vanilla-extract+webpack-plugin@2.3.22_webpack@5.99.9_esbuild@0.25.5_/node_modules/@vanilla-extract/webpack-plugin/extracted.js");
|
|
3223
3281
|
var _3CwGAAA_node_modules_pnpm_vanilla_extract_webpack_plugin_2_3_22_webpack_5_99_9_esbuild_0_25_5_node_modules_vanilla_extract_webpack_plugin_extracted_options = {};
|
|
3224
3282
|
_3CwGAAA_node_modules_pnpm_vanilla_extract_webpack_plugin_2_3_22_webpack_5_99_9_esbuild_0_25_5_node_modules_vanilla_extract_webpack_plugin_extracted_options.styleTagTransform = styleTagTransform_default();
|
|
@@ -3253,7 +3311,7 @@ function BooleanFlagControl(props) {
|
|
|
3253
3311
|
}
|
|
3254
3312
|
function MultivariateFlagControl(props) {
|
|
3255
3313
|
const { flag, onOverride, disabled = false } = props;
|
|
3256
|
-
const currentVariation = flag.availableVariations.find((v)=>v.value
|
|
3314
|
+
const currentVariation = flag.availableVariations.find((v)=>deepEqual(v.value, flag.currentValue));
|
|
3257
3315
|
return /*#__PURE__*/ jsxs(Select, {
|
|
3258
3316
|
selectedKey: currentVariation?._id,
|
|
3259
3317
|
onSelectionChange: (key)=>{
|
|
@@ -3631,6 +3689,45 @@ function ProjectSelector(props) {
|
|
|
3631
3689
|
]
|
|
3632
3690
|
});
|
|
3633
3691
|
}
|
|
3692
|
+
function PositionSelector(props) {
|
|
3693
|
+
const { currentPosition, onPositionChange } = props;
|
|
3694
|
+
function getPositionsDisplayName(position) {
|
|
3695
|
+
return position.charAt(0).toUpperCase() + position.slice(1);
|
|
3696
|
+
}
|
|
3697
|
+
const handlePositionSelect = (key)=>{
|
|
3698
|
+
if (key && 'string' == typeof key) {
|
|
3699
|
+
const position = key;
|
|
3700
|
+
if (position !== currentPosition) onPositionChange(position);
|
|
3701
|
+
}
|
|
3702
|
+
};
|
|
3703
|
+
return /*#__PURE__*/ jsxs(Select, {
|
|
3704
|
+
selectedKey: currentPosition,
|
|
3705
|
+
onSelectionChange: handlePositionSelect,
|
|
3706
|
+
"aria-label": "Select toolbar position",
|
|
3707
|
+
placeholder: "Select position",
|
|
3708
|
+
"data-theme": "dark",
|
|
3709
|
+
className: SettingsTab_css_select,
|
|
3710
|
+
children: [
|
|
3711
|
+
/*#__PURE__*/ jsxs(Button, {
|
|
3712
|
+
children: [
|
|
3713
|
+
/*#__PURE__*/ jsx(SelectValue, {}),
|
|
3714
|
+
/*#__PURE__*/ jsx(ChevronDownIcon, {
|
|
3715
|
+
className: SettingsTab_css_icon
|
|
3716
|
+
})
|
|
3717
|
+
]
|
|
3718
|
+
}),
|
|
3719
|
+
/*#__PURE__*/ jsx(Popover, {
|
|
3720
|
+
"data-theme": "dark",
|
|
3721
|
+
children: /*#__PURE__*/ jsx(ListBox, {
|
|
3722
|
+
children: TOOLBAR_POSITIONS.map((position)=>/*#__PURE__*/ jsx(ListBoxItem, {
|
|
3723
|
+
id: position,
|
|
3724
|
+
children: getPositionsDisplayName(position)
|
|
3725
|
+
}, position))
|
|
3726
|
+
})
|
|
3727
|
+
})
|
|
3728
|
+
]
|
|
3729
|
+
});
|
|
3730
|
+
}
|
|
3634
3731
|
function ConnectionStatusDisplay(props) {
|
|
3635
3732
|
const { status } = props;
|
|
3636
3733
|
const getStatusText = ()=>{
|
|
@@ -3657,8 +3754,9 @@ function ConnectionStatusDisplay(props) {
|
|
|
3657
3754
|
});
|
|
3658
3755
|
}
|
|
3659
3756
|
function SettingsTabContent() {
|
|
3660
|
-
const { state, switchProject } = useToolbarContext();
|
|
3757
|
+
const { state, switchProject, handlePositionChange } = useToolbarContext();
|
|
3661
3758
|
const { searchTerm } = useSearchContext();
|
|
3759
|
+
const position = state.position;
|
|
3662
3760
|
const handleProjectSwitch = async (projectKey)=>{
|
|
3663
3761
|
try {
|
|
3664
3762
|
await switchProject(projectKey);
|
|
@@ -3666,6 +3764,9 @@ function SettingsTabContent() {
|
|
|
3666
3764
|
console.error('Failed to switch project:', error);
|
|
3667
3765
|
}
|
|
3668
3766
|
};
|
|
3767
|
+
const handlePositionSelect = (newPosition)=>{
|
|
3768
|
+
handlePositionChange(newPosition);
|
|
3769
|
+
};
|
|
3669
3770
|
const settingsGroups = [
|
|
3670
3771
|
{
|
|
3671
3772
|
title: 'Configuration',
|
|
@@ -3676,6 +3777,12 @@ function SettingsTabContent() {
|
|
|
3676
3777
|
icon: 'folder',
|
|
3677
3778
|
isProjectSelector: true
|
|
3678
3779
|
},
|
|
3780
|
+
{
|
|
3781
|
+
id: 'position',
|
|
3782
|
+
name: 'Position',
|
|
3783
|
+
icon: 'move',
|
|
3784
|
+
isPositionSelector: true
|
|
3785
|
+
},
|
|
3679
3786
|
{
|
|
3680
3787
|
id: 'environment',
|
|
3681
3788
|
name: 'Environment',
|
|
@@ -3745,6 +3852,9 @@ function SettingsTabContent() {
|
|
|
3745
3852
|
currentProject: state.currentProjectKey,
|
|
3746
3853
|
onProjectChange: handleProjectSwitch,
|
|
3747
3854
|
isLoading: state.isLoading
|
|
3855
|
+
}) : item.isPositionSelector ? /*#__PURE__*/ jsx(PositionSelector, {
|
|
3856
|
+
currentPosition: position,
|
|
3857
|
+
onPositionChange: handlePositionSelect
|
|
3748
3858
|
}) : /*#__PURE__*/ jsx("span", {
|
|
3749
3859
|
className: settingValue,
|
|
3750
3860
|
children: item.value
|
|
@@ -3922,10 +4032,31 @@ function ExpandedToolbarContent(props) {
|
|
|
3922
4032
|
]
|
|
3923
4033
|
}, "toolbar-content");
|
|
3924
4034
|
}
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
4035
|
+
function useKeyPressed(targetKey) {
|
|
4036
|
+
const [keyPressed, setKeyPressed] = useState(false);
|
|
4037
|
+
useEffect(()=>{
|
|
4038
|
+
const downHandler = (event)=>{
|
|
4039
|
+
if (event.key === targetKey) setKeyPressed(true);
|
|
4040
|
+
};
|
|
4041
|
+
const upHandler = (event)=>{
|
|
4042
|
+
if (event.key === targetKey) setKeyPressed(false);
|
|
4043
|
+
};
|
|
4044
|
+
const blurHandler = ()=>{
|
|
4045
|
+
setKeyPressed(false);
|
|
4046
|
+
};
|
|
4047
|
+
window.addEventListener('keydown', downHandler);
|
|
4048
|
+
window.addEventListener('keyup', upHandler);
|
|
4049
|
+
window.addEventListener('blur', blurHandler);
|
|
4050
|
+
return ()=>{
|
|
4051
|
+
window.removeEventListener('keydown', downHandler);
|
|
4052
|
+
window.removeEventListener('keyup', upHandler);
|
|
4053
|
+
window.removeEventListener('blur', blurHandler);
|
|
4054
|
+
};
|
|
4055
|
+
}, [
|
|
4056
|
+
targetKey
|
|
4057
|
+
]);
|
|
4058
|
+
return keyPressed;
|
|
4059
|
+
}
|
|
3929
4060
|
function useToolbarState() {
|
|
3930
4061
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
3931
4062
|
const [isHovered, setIsHovered] = useState(false);
|
|
@@ -3935,10 +4066,14 @@ function useToolbarState() {
|
|
|
3935
4066
|
const [searchIsExpanded, setSearchIsExpanded] = useState(false);
|
|
3936
4067
|
const hasBeenExpandedRef = useRef(false);
|
|
3937
4068
|
const toolbarRef = useRef(null);
|
|
4069
|
+
const isMetaPressed = useKeyPressed('Meta');
|
|
4070
|
+
const isControlPressed = useKeyPressed('Control');
|
|
4071
|
+
const isDragModifierPressed = isMetaPressed || isControlPressed;
|
|
3938
4072
|
const { setSearchTerm } = useSearchContext();
|
|
3939
|
-
const showFullToolbar = useMemo(()=>isExpanded || isHovered && !isExpanded, [
|
|
4073
|
+
const showFullToolbar = useMemo(()=>isExpanded || isHovered && !isExpanded && !isDragModifierPressed, [
|
|
3940
4074
|
isExpanded,
|
|
3941
|
-
isHovered
|
|
4075
|
+
isHovered,
|
|
4076
|
+
isDragModifierPressed
|
|
3942
4077
|
]);
|
|
3943
4078
|
const slideDirection = useMemo(()=>{
|
|
3944
4079
|
if (!activeTab || !previousTab) return 1;
|
|
@@ -4012,6 +4147,7 @@ function useToolbarState() {
|
|
|
4012
4147
|
showFullToolbar,
|
|
4013
4148
|
slideDirection,
|
|
4014
4149
|
hasBeenExpanded: hasBeenExpandedRef.current,
|
|
4150
|
+
isDragModifierPressed,
|
|
4015
4151
|
toolbarRef,
|
|
4016
4152
|
handleTabChange,
|
|
4017
4153
|
handleMouseEnter,
|
|
@@ -4051,7 +4187,7 @@ function useToolbarAnimations(props) {
|
|
|
4051
4187
|
handleAnimationComplete
|
|
4052
4188
|
};
|
|
4053
4189
|
}
|
|
4054
|
-
const useToolbarVisibility_STORAGE_KEY =
|
|
4190
|
+
const useToolbarVisibility_STORAGE_KEY = TOOLBAR_STORAGE_KEYS.DISABLED;
|
|
4055
4191
|
function useToolbarVisibility() {
|
|
4056
4192
|
const [isDisabled, setIsDisabled] = useState(()=>{
|
|
4057
4193
|
if ('undefined' == typeof window) return true;
|
|
@@ -4097,22 +4233,90 @@ function useToolbarVisibility() {
|
|
|
4097
4233
|
}, []);
|
|
4098
4234
|
return !isDisabled;
|
|
4099
4235
|
}
|
|
4100
|
-
function
|
|
4101
|
-
const
|
|
4236
|
+
function useToolbarDrag({ enabled, onDragEnd, elementRef }) {
|
|
4237
|
+
const handleMouseDown = useCallback((event)=>{
|
|
4238
|
+
if (!enabled || !elementRef.current) return;
|
|
4239
|
+
event.preventDefault();
|
|
4240
|
+
const startPosition = {
|
|
4241
|
+
x: event.clientX,
|
|
4242
|
+
y: event.clientY
|
|
4243
|
+
};
|
|
4244
|
+
const boundingRect = elementRef.current.getBoundingClientRect();
|
|
4245
|
+
const initialPosition = {
|
|
4246
|
+
x: boundingRect.left,
|
|
4247
|
+
y: boundingRect.top
|
|
4248
|
+
};
|
|
4249
|
+
const updateElementPosition = (mouseEvent)=>{
|
|
4250
|
+
if (!elementRef.current) return;
|
|
4251
|
+
const offset = {
|
|
4252
|
+
x: mouseEvent.clientX - startPosition.x,
|
|
4253
|
+
y: mouseEvent.clientY - startPosition.y
|
|
4254
|
+
};
|
|
4255
|
+
const newPosition = {
|
|
4256
|
+
x: initialPosition.x + offset.x,
|
|
4257
|
+
y: initialPosition.y + offset.y
|
|
4258
|
+
};
|
|
4259
|
+
elementRef.current.style.left = `${newPosition.x}px`;
|
|
4260
|
+
elementRef.current.style.top = `${newPosition.y}px`;
|
|
4261
|
+
};
|
|
4262
|
+
const resetElementStyles = ()=>{
|
|
4263
|
+
if (elementRef.current) {
|
|
4264
|
+
elementRef.current.style.left = '';
|
|
4265
|
+
elementRef.current.style.top = '';
|
|
4266
|
+
elementRef.current.style.right = '';
|
|
4267
|
+
elementRef.current.style.bottom = '';
|
|
4268
|
+
elementRef.current.style.transform = '';
|
|
4269
|
+
elementRef.current.style.zIndex = '';
|
|
4270
|
+
}
|
|
4271
|
+
};
|
|
4272
|
+
const handleDragComplete = (upEvent)=>{
|
|
4273
|
+
document.removeEventListener('mousemove', updateElementPosition);
|
|
4274
|
+
document.removeEventListener('mouseup', handleDragComplete);
|
|
4275
|
+
resetElementStyles();
|
|
4276
|
+
onDragEnd(upEvent.clientX);
|
|
4277
|
+
};
|
|
4278
|
+
document.addEventListener('mousemove', updateElementPosition);
|
|
4279
|
+
document.addEventListener('mouseup', handleDragComplete);
|
|
4280
|
+
}, [
|
|
4281
|
+
enabled,
|
|
4282
|
+
onDragEnd,
|
|
4283
|
+
elementRef
|
|
4284
|
+
]);
|
|
4285
|
+
return {
|
|
4286
|
+
handleMouseDown
|
|
4287
|
+
};
|
|
4288
|
+
}
|
|
4289
|
+
function LdToolbar() {
|
|
4102
4290
|
const { searchTerm } = useSearchContext();
|
|
4291
|
+
const { state, handlePositionChange } = useToolbarContext();
|
|
4103
4292
|
const toolbarState = useToolbarState();
|
|
4104
|
-
const
|
|
4293
|
+
const position = state.position;
|
|
4294
|
+
const { isExpanded, activeTab, slideDirection, searchIsExpanded, showFullToolbar, hasBeenExpanded, toolbarRef, handleTabChange, handleMouseEnter, handleMouseLeave, handleClose, handleSearch, setSearchIsExpanded, setIsAnimating, isHovered, isDragModifierPressed } = toolbarState;
|
|
4105
4295
|
const toolbarAnimations = useToolbarAnimations({
|
|
4106
4296
|
showFullToolbar,
|
|
4107
|
-
isHovered
|
|
4297
|
+
isHovered,
|
|
4108
4298
|
setIsAnimating
|
|
4109
4299
|
});
|
|
4110
4300
|
const { containerAnimations, animationConfig, handleAnimationStart, handleAnimationComplete } = toolbarAnimations;
|
|
4301
|
+
const isDragEnabled = !showFullToolbar && isHovered && isDragModifierPressed;
|
|
4302
|
+
const handleDragEnd = useCallback((clientX)=>{
|
|
4303
|
+
const screenWidth = window.innerWidth;
|
|
4304
|
+
const newPosition = clientX < screenWidth / 2 ? 'left' : 'right';
|
|
4305
|
+
handlePositionChange(newPosition);
|
|
4306
|
+
}, [
|
|
4307
|
+
handlePositionChange
|
|
4308
|
+
]);
|
|
4309
|
+
const { handleMouseDown } = useToolbarDrag({
|
|
4310
|
+
enabled: isDragEnabled,
|
|
4311
|
+
onDragEnd: handleDragEnd,
|
|
4312
|
+
elementRef: toolbarRef
|
|
4313
|
+
});
|
|
4111
4314
|
return /*#__PURE__*/ jsxs(motion.div, {
|
|
4112
4315
|
ref: toolbarRef,
|
|
4113
4316
|
className: `${toolbarContainer} ${'left' === position ? positionLeft : positionRight} ${showFullToolbar ? toolbarExpanded : toolbarCircle}`,
|
|
4114
4317
|
onMouseEnter: handleMouseEnter,
|
|
4115
4318
|
onMouseLeave: handleMouseLeave,
|
|
4319
|
+
onMouseDown: handleMouseDown,
|
|
4116
4320
|
initial: false,
|
|
4117
4321
|
animate: containerAnimations,
|
|
4118
4322
|
transition: animationConfig,
|
|
@@ -4153,10 +4357,9 @@ function LaunchDarklyToolbar(props) {
|
|
|
4153
4357
|
devServerUrl,
|
|
4154
4358
|
pollIntervalInMs
|
|
4155
4359
|
},
|
|
4360
|
+
initialPosition: position,
|
|
4156
4361
|
children: /*#__PURE__*/ jsx(SearchProvider, {
|
|
4157
|
-
children: /*#__PURE__*/ jsx(LdToolbar, {
|
|
4158
|
-
position: position
|
|
4159
|
-
})
|
|
4362
|
+
children: /*#__PURE__*/ jsx(LdToolbar, {})
|
|
4160
4363
|
})
|
|
4161
4364
|
});
|
|
4162
4365
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export declare function LdToolbar(props: LdToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
-
export interface LaunchDarklyToolbarProps extends LdToolbarProps {
|
|
1
|
+
import { ToolbarPosition } from './types/toolbar';
|
|
2
|
+
export declare function LdToolbar(): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export interface LaunchDarklyToolbarProps {
|
|
6
4
|
devServerUrl?: string;
|
|
7
5
|
projectKey?: string;
|
|
8
6
|
pollIntervalInMs?: number;
|
|
7
|
+
position?: ToolbarPosition;
|
|
9
8
|
}
|
|
10
9
|
export declare function LaunchDarklyToolbar(props: LaunchDarklyToolbarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { LdToolbarConfig, ToolbarState } from '../../../types/devServer';
|
|
3
|
+
import { ToolbarPosition } from '../types/toolbar';
|
|
3
4
|
interface LaunchDarklyToolbarContextValue {
|
|
4
5
|
state: ToolbarState & {
|
|
5
6
|
availableProjects: string[];
|
|
6
7
|
currentProjectKey: string | null;
|
|
8
|
+
position: ToolbarPosition;
|
|
7
9
|
};
|
|
8
10
|
setOverride: (flagKey: string, value: any) => Promise<void>;
|
|
9
11
|
clearOverride: (flagKey: string) => Promise<void>;
|
|
10
12
|
clearAllOverrides: () => Promise<void>;
|
|
11
13
|
refresh: () => Promise<void>;
|
|
12
14
|
switchProject: (projectKey: string) => Promise<void>;
|
|
15
|
+
handlePositionChange: (position: ToolbarPosition) => void;
|
|
13
16
|
}
|
|
14
17
|
export declare const useToolbarContext: () => LaunchDarklyToolbarContextValue;
|
|
15
18
|
export interface LaunchDarklyToolbarProviderProps {
|
|
16
19
|
children: React.ReactNode;
|
|
17
20
|
config: LdToolbarConfig;
|
|
21
|
+
initialPosition?: ToolbarPosition;
|
|
18
22
|
}
|
|
19
23
|
export declare const LaunchDarklyToolbarProvider: React.FC<LaunchDarklyToolbarProviderProps>;
|
|
20
24
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { useToolbarState } from './useToolbarState';
|
|
2
2
|
export { useToolbarAnimations } from './useToolbarAnimations';
|
|
3
3
|
export { useToolbarVisibility } from './useToolbarVisibility';
|
|
4
|
+
export { useToolbarDrag } from './useToolbarDrag';
|
|
5
|
+
export { useKeyPressed } from './useKeyPressed';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useKeyPressed(targetKey: string): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface UseToolbarDragOptions {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
onDragEnd: (clientX: number) => void;
|
|
4
|
+
elementRef: React.RefObject<HTMLDivElement | null>;
|
|
5
|
+
}
|
|
6
|
+
interface UseToolbarDragReturn {
|
|
7
|
+
handleMouseDown: (event: React.MouseEvent) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function useToolbarDrag({ enabled, onDragEnd, elementRef }: UseToolbarDragOptions): UseToolbarDragReturn;
|
|
10
|
+
export {};
|
|
@@ -10,6 +10,7 @@ export interface UseToolbarStateReturn {
|
|
|
10
10
|
showFullToolbar: boolean;
|
|
11
11
|
slideDirection: number;
|
|
12
12
|
hasBeenExpanded: boolean;
|
|
13
|
+
isDragModifierPressed: boolean;
|
|
13
14
|
toolbarRef: React.RefObject<HTMLDivElement | null>;
|
|
14
15
|
handleTabChange: (tabId: string) => void;
|
|
15
16
|
handleMouseEnter: () => void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ToolbarPosition } from '../types/toolbar';
|
|
2
|
+
export declare const TOOLBAR_STORAGE_KEYS: {
|
|
3
|
+
readonly POSITION: "ld-toolbar-position";
|
|
4
|
+
readonly DISABLED: "ld-toolbar-disabled";
|
|
5
|
+
readonly PROJECT: "ld-toolbar-project";
|
|
6
|
+
};
|
|
7
|
+
export declare function saveToolbarPosition(position: ToolbarPosition): void;
|
|
8
|
+
export declare function loadToolbarPosition(): ToolbarPosition | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performs deep equality comparison for complex values including objects and arrays.
|
|
3
|
+
*
|
|
4
|
+
* @param a - First value to compare
|
|
5
|
+
* @param b - Second value to compare
|
|
6
|
+
* @returns true if values are deeply equal, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
export declare function deepEqual(a: any, b: any): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { deepEqual } from './deepEqual';
|
package/package.json
CHANGED