@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 CHANGED
@@ -2657,23 +2657,56 @@ class FlagStateManager {
2657
2657
  this.listeners.clear();
2658
2658
  }
2659
2659
  }
2660
- const STORAGE_KEY = 'launchdarkly-toolbar-project';
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
- flags: {},
2670
- connectionStatus: 'disconnected',
2671
- lastSyncTime: 0,
2672
- isLoading: true,
2673
- error: null,
2674
- sourceEnvironmentKey: null,
2675
- availableProjects: [],
2676
- currentProjectKey: null
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 === flag.currentValue);
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
- const TAB_ORDER = [
3926
- 'flags',
3927
- 'settings'
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 = 'ld-toolbar-disabled';
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 LdToolbar(props) {
4101
- const { position = 'right' } = props;
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 { isExpanded, activeTab, slideDirection, searchIsExpanded, showFullToolbar, hasBeenExpanded, toolbarRef, handleTabChange, handleMouseEnter, handleMouseLeave, handleClose, handleSearch, setSearchIsExpanded, setIsAnimating } = toolbarState;
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: toolbarState.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
- export interface LdToolbarProps {
2
- position?: 'left' | 'right';
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;
@@ -10,3 +10,5 @@ export interface FeatureFlag {
10
10
  lastModified?: Date;
11
11
  environment?: string;
12
12
  }
13
+ export declare const TOOLBAR_POSITIONS: readonly ["left", "right"];
14
+ export type ToolbarPosition = (typeof TOOLBAR_POSITIONS)[number];
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchdarkly/toolbar",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "A React component that provides a developer-friendly toolbar for interacting with LaunchDarkly during development",
5
5
  "keywords": [
6
6
  "launchdarkly",