diff --git a/packages/geoview-core/src/core/components/layers/layers-panel.tsx b/packages/geoview-core/src/core/components/layers/layers-panel.tsx index 3dc6493e1eb..5e3fa839806 100644 --- a/packages/geoview-core/src/core/components/layers/layers-panel.tsx +++ b/packages/geoview-core/src/core/components/layers/layers-panel.tsx @@ -9,6 +9,8 @@ import { logger } from '@/core/utils/logger'; import { ResponsiveGridLayout, ResponsiveGridLayoutExposedMethods } from '@/core/components/common/responsive-grid-layout'; import { Typography } from '@/ui/typography/typography'; import { TypeContainerBox } from '@/core/types/global-types'; +import { useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; +import { TypeLegendLayer } from './types'; interface TypeLayersPanel { containerType?: TypeContainerBox; @@ -21,31 +23,24 @@ export function LayersPanel({ containerType }: TypeLayersPanel): JSX.Element { const selectedLayer = useSelectedLayer(); // get store value const displayState = useLayerDisplayState(); - const { setSelectedLayerPath } = useLayerStoreActions(); const [isLayoutEnlarged, setIsLayoutEnlarged] = useState(false); - const responsiveLayoutRef = useRef(null); - - /* - // Using helpers - const helpers = useLegendHelpers(); - useEffect(() => { - // Log - logger.logTraceUseEffect('LAYERS-PANEL - mount'); + const { setSelectedLayerPath } = useLayerStoreActions(); + const { setSelectedFooterLayerListItem } = useUIStoreActions(); - helpers.populateLegendStoreWithFakeData(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - */ + const responsiveLayoutRef = useRef(null); - const showLayerDetailsPanel = (): void => { + const showLayerDetailsPanel = (layer: TypeLegendLayer): void => { responsiveLayoutRef.current?.setIsRightPanelVisible(true); + responsiveLayoutRef.current?.setRightPanelFocus(); + // set the focus item when layer item clicked. + setSelectedFooterLayerListItem(`${layer.layerId}`); }; const leftPanel = (): JSX.Element => { return ( - - + + ); }; diff --git a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx index 23f57a0cc91..f61292ba536 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/add-new-layer/add-new-layer.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; +import React, { ChangeEvent, useEffect, useRef, useState, KeyboardEvent } from 'react'; import { useTranslation } from 'react-i18next'; import { SelectChangeEvent, useTheme } from '@mui/material'; import { @@ -84,6 +84,10 @@ export function AddNewLayer(): JSX.Element { const [stepButtonDisable, setStepButtonDisable] = useState(true); const dragPopover = useRef(null); + const uploadBtnRef = useRef(null); + const serviceTypeRef = useRef(null); + const isMultipleRef = useRef(null); + const isMultipleTextFieldRef = useRef(null); // get values from store const mapId = useGeoViewMapId(); @@ -1015,6 +1019,29 @@ export function AddNewLayer(): JSX.Element { if (activeStep === 2 && layerEntries.length > 0) setStepButtonDisable(false); }, [layerName, activeStep, layerEntries]); + useEffect(() => { + if (activeStep === 0) { + uploadBtnRef.current?.focus(); + } + if (activeStep === 1) { + (serviceTypeRef.current?.getElementsByTagName('input')[0].previousSibling as HTMLDivElement).focus(); + } + if (activeStep === 2) { + if (isMultipleRef.current) { + // handle is Multiple fields focus + const id = isMultipleRef.current?.dataset?.id; + const elem = isMultipleRef.current?.querySelector('#service-layer-label') as HTMLInputElement; + if (id === 'autocomplete' && elem) { + elem.focus(); + } else { + isMultipleTextFieldRef.current?.getElementsByTagName('input')[0]?.focus(); + } + } + } + if (activeStep === 3) { + isMultipleTextFieldRef.current?.getElementsByTagName('input')[0]?.focus(); + } + }, [activeStep]); /** * Handle file dragged into dropzone * @@ -1069,6 +1096,13 @@ export function AddNewLayer(): JSX.Element { } }; + const handleKeyDown = (e: KeyboardEvent): void => { + if (e.key === 'Enter') { + handleBack(); + e.preventDefault(); + } + }; + /** * Creates a set of Continue / Back buttons * @@ -1095,7 +1129,14 @@ export function AddNewLayer(): JSX.Element { {isLast ? t('layers.finish') : t('layers.continue')} {!isFirst && ( - )} @@ -1168,6 +1209,7 @@ export function AddNewLayer(): JSX.Element { type="text" onClick={() => document.getElementById('fileUpload')?.click()} className="buttonOutlineFilled" + ref={uploadBtnRef} > {t('layers.upload')} @@ -1207,6 +1249,7 @@ export function AddNewLayer(): JSX.Element { inputLabel={{ id: 'service-type-label', }} + ref={serviceTypeRef} menuItems={layerOptions.map(([value, label]) => ({ key: value, item: { @@ -1228,7 +1271,13 @@ export function AddNewLayer(): JSX.Element { children: ( <> {layerList.length === 0 && ( - + )} {layerList.length > 1 && (layerList[0] as TypeLayerEntryConfig).layerName && ( `${option.layerName!.en} (${option.layerId})`} + getOptionLabel={(option) => + `${(option as TypeLayerEntryConfig).layerName!.en} (${(option as TypeLayerEntryConfig).layerId})` + } renderOption={(props, option, { selected }) => ( -
  • +
  • - {option.layerName!.en} + {(option as TypeLayerEntryConfig).layerName!.en}
  • )} // eslint-disable-next-line @typescript-eslint/no-explicit-any onChange={handleSelectLayer as any} + ref={isMultipleRef} renderInput={(params) => } /> )} @@ -1257,16 +1309,19 @@ export function AddNewLayer(): JSX.Element { disableClearable={!isMultiple()} id="service-layer-label" options={layerList as TypeGeoviewLayerConfig[]} - getOptionLabel={(option) => `${option.geoviewLayerName!.en} (${option.geoviewLayerId})`} + getOptionLabel={(option) => + `${(option as TypeGeoviewLayerConfig).geoviewLayerName!.en} (${(option as TypeGeoviewLayerConfig).geoviewLayerId})` + } disableCloseOnSelect renderOption={(props, option, { selected }) => ( -
  • +
  • - {option.geoviewLayerName!.en} + {(option as TypeGeoviewLayerConfig).geoviewLayerName!.en}
  • )} // eslint-disable-next-line @typescript-eslint/no-explicit-any onChange={handleSelectLayer as any} + ref={isMultipleRef} renderInput={(params) => } /> )} @@ -1290,6 +1345,7 @@ export function AddNewLayer(): JSX.Element { variant="standard" value={layerName} onChange={handleNameLayer} + ref={isMultipleTextFieldRef} />
    diff --git a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx index 24af7f35baa..1618c3b5f6b 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/delete-undo-button.tsx @@ -1,10 +1,11 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, KeyboardEvent } from 'react'; import { Box, CircularProgressBase, DeleteOutlineIcon, IconButton, UndoIcon } from '@/ui'; import { TypeLegendLayer } from '@/core/components/layers/types'; import { useLayerStoreActions } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { useMapStoreActions } from '@/core/stores/store-interface-and-intial-values/map-state'; import { logger } from '@/core/utils/logger'; import { LAYER_STATUS } from '@/core/utils/constant'; +import { useUIStoreActions } from '@/core/stores/store-interface-and-intial-values/ui-state'; interface DeleteUndoButtonProps { layer: TypeLegendLayer; @@ -13,13 +14,14 @@ interface DeleteUndoButtonProps { interface UndoButtonProps { progressValue: number; onUndo: () => void; + handleKeyDown: (e: KeyboardEvent) => void; } function UndoButtonWithProgress(props: UndoButtonProps): JSX.Element { // Log logger.logTraceRender('components/layers/left-panel/delete-undo-button/UndoButtonWithProgress'); - const { progressValue, onUndo } = props; + const { progressValue, onUndo, handleKeyDown } = props; return ( @@ -35,7 +37,7 @@ function UndoButtonWithProgress(props: UndoButtonProps): JSX.Element { justifyContent: 'center', }} > - + handleKeyDown(e)}> @@ -55,6 +57,7 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { // get store actions const { deleteLayer, setLayerDeleteInProgress, getLayerDeleteInProgress } = useLayerStoreActions(); const { getVisibilityFromOrderedLayerInfo, setOrToggleLayerVisibility } = useMapStoreActions(); + const { setSelectedFooterLayerListItem } = useUIStoreActions(); const handleDeleteClick = (): void => { if (getVisibilityFromOrderedLayerInfo(layer.layerPath)) setOrToggleLayerVisibility(layer.layerPath); @@ -68,6 +71,22 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { setLayerDeleteInProgress(false); }; + const handleDeleteKeyDown = (e: KeyboardEvent): void => { + if (e.key === 'Enter') { + e.preventDefault(); + handleDeleteClick(); + setSelectedFooterLayerListItem(layer.layerId); + } + }; + + const handleUndoDeleteKeyDown = (e: KeyboardEvent): void => { + if (e.key === 'Enter') { + handleUndoClick(); + setSelectedFooterLayerListItem(''); + e.preventDefault(); + } + }; + useEffect(() => { if (progress === 100) { deleteLayer(layer.layerPath); @@ -96,7 +115,7 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { } if (!inUndoState && layer.controls?.remove !== false && !getLayerDeleteInProgress()) { return ( - + handleDeleteKeyDown(e)}> ); @@ -108,5 +127,5 @@ export function DeleteUndoButton(props: DeleteUndoButtonProps): JSX.Element { ); } - return ; + return ; } diff --git a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx index a79dfbac5f0..b12040b775b 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/layers-list.tsx @@ -1,26 +1,27 @@ -import { Dispatch, SetStateAction } from 'react'; import { useTheme } from '@mui/material/styles'; import { SingleLayer } from './single-layer'; import { getSxClasses } from './left-panel-styles'; import { Box } from '@/ui'; -import { useMapStoreActions } from '@/core/stores/'; +import { useGeoViewMapId, useMapStoreActions } from '@/core/stores'; import { logger } from '@/core/utils/logger'; import { TypeLegendLayer } from '@/core/components/layers/types'; +import { TABS } from '@/core/utils/constant'; interface LayerListProps { depth: number; layersList: TypeLegendLayer[]; - setIsLayersListPanelVisible: Dispatch>; + showLayerDetailsPanel: (layer: TypeLegendLayer) => void; isLayoutEnlarged: boolean; } -export function LayersList({ layersList, setIsLayersListPanelVisible, isLayoutEnlarged, depth }: LayerListProps): JSX.Element { +export function LayersList({ layersList, showLayerDetailsPanel, isLayoutEnlarged, depth }: LayerListProps): JSX.Element { // Log logger.logTraceRender('components/layers/left-panel/layers-list'); const theme = useTheme(); const sxClasses = getSxClasses(theme); + const mapId = useGeoViewMapId(); const { getIndexFromOrderedLayerInfo } = useMapStoreActions(); const sortedLayers = layersList.sort((a, b) => @@ -49,12 +50,13 @@ export function LayersList({ layersList, setIsLayersListPanelVisible, isLayoutEn const legendItems = sortedLayers.map((details, index) => { const isFirst = index === 0; const isLast = index === sortedLayers.length - 1; + return ( >; + showLayerDetailsPanel: (layer: TypeLegendLayer) => void; isLayoutEnlarged: boolean; } -export function LeftPanel({ setIsLayersListPanelVisible, isLayoutEnlarged }: LeftPanelProps): JSX.Element { +export function LeftPanel({ showLayerDetailsPanel, isLayoutEnlarged }: LeftPanelProps): JSX.Element { // Log logger.logTraceRender('components/layers/left-panel/left-panel'); @@ -51,11 +51,12 @@ export function LeftPanel({ setIsLayersListPanelVisible, isLayoutEnlarged }: Lef if (displayState === 'add') { return ; } + return ( ); diff --git a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx index 452118943b7..d227147ddbd 100644 --- a/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx +++ b/packages/geoview-core/src/core/components/layers/left-panel/single-layer.tsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction } from 'react'; +import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import _ from 'lodash'; import { animated, useSpring } from '@react-spring/web'; @@ -23,6 +23,8 @@ import { useLayerStoreActions, useLayerDisplayState, useLayerSelectedLayerPath, + useSelectedLayerSortingArrowId, + useLayerLegendLayers, } from '@/core/stores/store-interface-and-intial-values/layer-state'; import { useMapStoreActions } from '@/core/stores/store-interface-and-intial-values/map-state'; import { DeleteUndoButton } from './delete-undo-button'; @@ -32,11 +34,13 @@ import { logger } from '@/core/utils/logger'; import { useDataTableLayerSettings, useDataTableStoreActions } from '@/core/stores/store-interface-and-intial-values/data-table-state'; import { ArrowDownwardIcon, ArrowUpIcon, TableViewIcon } from '@/ui/icons'; import { Divider } from '@/ui/divider/divider'; +import { useGeoViewMapId } from '@/core/stores/geoview-store'; +import { useUISelectedFooterLayerListItem } from '@/core/stores/store-interface-and-intial-values/ui-state'; interface SingleLayerProps { layer: TypeLegendLayer; depth: number; - setIsLayersListPanelVisible: Dispatch>; + showLayerDetailsPanel: (layer: TypeLegendLayer) => void; index: number; isFirst: boolean; isLast: boolean; @@ -46,7 +50,7 @@ interface SingleLayerProps { export function SingleLayer({ depth, layer, - setIsLayersListPanelVisible, + showLayerDetailsPanel, index, isFirst, isLast, @@ -58,7 +62,7 @@ export function SingleLayer({ const { t } = useTranslation(); // Get store states - const { setSelectedLayerPath } = useLayerStoreActions(); + const { setSelectedLayerPath, setSelectedLayerSortingArrowId } = useLayerStoreActions(); const { getVisibilityFromOrderedLayerInfo, setOrToggleLayerVisibility, @@ -66,9 +70,14 @@ export function SingleLayer({ setLegendCollapsed, reorderLayer, } = useMapStoreActions(); + + const mapId = useGeoViewMapId(); const selectedLayerPath = useLayerSelectedLayerPath(); const displayState = useLayerDisplayState(); const datatableSettings = useDataTableLayerSettings(); + const selectedLayerSortingArrowId = useSelectedLayerSortingArrowId(); + const selectedFooterLayerListItem = useUISelectedFooterLayerListItem(); + const legendLayers = useLayerLegendLayers(); useDataTableStoreActions(); @@ -154,15 +163,11 @@ export function SingleLayer({ } setSelectedLayerPath(layer.layerPath); - if (setIsLayersListPanelVisible) { - setIsLayersListPanelVisible(true); + if (showLayerDetailsPanel) { + showLayerDetailsPanel(layer); } }; - const handleLayerKeyDown = (e: React.KeyboardEvent): void => { - if (e.key === 'Enter') handleLayerClick(); - }; - const handleToggleVisibility = (): void => { setOrToggleLayerVisibility(layer.layerPath); }; @@ -186,10 +191,36 @@ export function SingleLayer({ flexItem /> )} - reorderLayer(layer.layerPath, -1)}> + reorderLayer(layer.layerPath, -1)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-up-order`); + reorderLayer(layer.layerPath, -1); + e.preventDefault(); + } + }} + > - reorderLayer(layer.layerPath, 1)}> + { + if (e.key === 'Enter') { + setSelectedLayerSortingArrowId(`${mapId}-${layer.layerPath}-down-order`); + reorderLayer(layer.layerPath, 1); + e.preventDefault(); + } + }} + onClick={() => reorderLayer(layer.layerPath, 1)} + > @@ -260,7 +291,7 @@ export function SingleLayer({ depth={1 + depth} layersList={layer.children} isLayoutEnlarged={isLayoutEnlarged} - setIsLayersListPanelVisible={setIsLayersListPanelVisible} + showLayerDetailsPanel={showLayerDetailsPanel} /> ); @@ -291,12 +322,46 @@ export function SingleLayer({ to: { opacity: 1 }, }); + useEffect(() => { + // Manually set the focus after sorting is done. + if (selectedLayerSortingArrowId.length) { + const elem = document.getElementById(selectedLayerSortingArrowId) as HTMLButtonElement; + if (elem?.disabled) { + if (selectedLayerSortingArrowId.split('-').includes('up')) { + (elem?.nextSibling as HTMLButtonElement)?.focus(); + } else { + (elem?.previousSibling as HTMLButtonElement)?.focus(); + } + } else { + elem?.focus(); + } + } + }, [selectedLayerSortingArrowId]); + + useEffect(() => { + // set the focus to first layer, after layer has been deleted. + if (displayState === 'remove' && selectedFooterLayerListItem.length) { + const firstLayer = document.getElementById('layers-left-panel'); + if (firstLayer?.getElementsByTagName('li')) { + const listItems = firstLayer?.getElementsByTagName('li'); + listItems[0]?.focus(); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [legendLayers, displayState]); + const AnimatedPaper = animated(Paper); return ( - handleLayerKeyDown(e)}> + e.key === 'Enter' && e.currentTarget === e.target && handleLayerClick()} + > void; @@ -41,6 +42,7 @@ export interface ILayerState { setSelectedLayerPath: (layerPath: string) => void; toggleItemVisibility: (layerPath: string, item: TypeLegendItem) => void; zoomToLayerExtent: (layerPath: string) => Promise; + setSelectedLayerSortingArrowId: (layerId: string) => void; }; setterActions: { @@ -49,6 +51,7 @@ export interface ILayerState { setLayerDeleteInProgress: (newVal: boolean) => void; setLegendLayers: (legendLayers: TypeLegendLayer[]) => void; setSelectedLayerPath: (layerPath: string) => void; + setSelectedLayerSortingArrowId: (arrowId: string) => void; }; } @@ -65,7 +68,7 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay selectedLayerPath: null, displayState: 'view', layerDeleteInProgress: false, - + selectedLayerSortingArrowId: '', // #region ACTIONS actions: { /** @@ -201,6 +204,10 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay // Failed return Promise.resolve(); }, + setSelectedLayerSortingArrowId: (arrowId: string) => { + // Redirect to setter + get().layerState.setterActions.setSelectedLayerSortingArrowId(arrowId); + }, }, setterActions: { @@ -272,6 +279,14 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay }, }); }, + setSelectedLayerSortingArrowId: (arrowId: string) => { + set({ + layerState: { + ...get().layerState, + selectedLayerSortingArrowId: arrowId, + }, + }); + }, }, // #endregion ACTIONS } as ILayerState; @@ -304,6 +319,8 @@ export const useLayerSelectedLayer = (): TypeLegendLayer => useStore(useGeoViewS export const useLayerSelectedLayerPath = (): string | null | undefined => useStore(useGeoViewStore(), (state) => state.layerState.selectedLayerPath); export const useLayerDisplayState = (): TypeLayersViewDisplayState => useStore(useGeoViewStore(), (state) => state.layerState.displayState); +export const useSelectedLayerSortingArrowId = (): string => + useStore(useGeoViewStore(), (state) => state.layerState.selectedLayerSortingArrowId); export const useLayerStoreActions = (): LayerActions => useStore(useGeoViewStore(), (state) => state.layerState.actions); diff --git a/packages/geoview-core/src/ui/autocomplete/autocomplete.tsx b/packages/geoview-core/src/ui/autocomplete/autocomplete.tsx index 5ed8482a48c..8c7ff5fc103 100644 --- a/packages/geoview-core/src/ui/autocomplete/autocomplete.tsx +++ b/packages/geoview-core/src/ui/autocomplete/autocomplete.tsx @@ -1,4 +1,5 @@ import { Autocomplete as MaterialAutocomplete, AutocompleteProps, FormControl } from '@mui/material'; +import { forwardRef, Ref } from 'react'; /** * Customized Material UI Autocomplete properties @@ -18,17 +19,20 @@ export interface TypeAutocompleteProps< * @param {TypeAutocompleteProps} props custom autocomplete properties * @returns {JSX.Element} the auto complete ui component */ -export function Autocomplete< +function MUIAutocomplete< T, Multiple extends boolean | undefined = undefined, DisableClearable extends boolean | undefined = undefined, FreeSolo extends boolean | undefined = undefined ->(props: TypeAutocompleteProps): JSX.Element { +>(props: TypeAutocompleteProps, ref: Ref): JSX.Element { const { fullWidth, ...autoCompleteProps } = props; return ( - + ); } + +// Export the Autocomplete using forwardRef so that passing ref is permitted and functional in the react standards +export const Autocomplete = forwardRef(MUIAutocomplete); diff --git a/packages/geoview-core/src/ui/button/button.tsx b/packages/geoview-core/src/ui/button/button.tsx index ba7bb7a27c9..142c4215b8b 100644 --- a/packages/geoview-core/src/ui/button/button.tsx +++ b/packages/geoview-core/src/ui/button/button.tsx @@ -1,3 +1,4 @@ +import { forwardRef, Ref } from 'react'; import { useTranslation } from 'react-i18next'; import { useTheme } from '@mui/material/styles'; @@ -15,7 +16,7 @@ export type ButtonProps = { * @param {ButtonProps} props the properties of the Button UI element * @returns {JSX.Element} the new UI element */ -export function Button(props: ButtonProps): JSX.Element { +function MaterialBtn(props: ButtonProps, ref: Ref): JSX.Element { const { id, sx, @@ -33,6 +34,7 @@ export function Button(props: ButtonProps): JSX.Element { size, makeResponsive, fullWidth, + onKeyDown, 'aria-label': ariaLabel, } = props; @@ -57,6 +59,8 @@ export function Button(props: ButtonProps): JSX.Element { startIcon={startIcon} endIcon={endIcon} aria-label={ariaLabel} + {...(onKeyDown && { onKeyDown })} + ref={ref} > {!(makeResponsive && mobileView) ? children : null} @@ -72,3 +76,6 @@ export function Button(props: ButtonProps): JSX.Element { ); } + +// Export the Button using forwardRef so that passing ref is permitted and functional in the react standards +export const Button = forwardRef(MaterialBtn); diff --git a/packages/geoview-core/src/ui/select/select.tsx b/packages/geoview-core/src/ui/select/select.tsx index 1c0e104f007..d9318175e50 100644 --- a/packages/geoview-core/src/ui/select/select.tsx +++ b/packages/geoview-core/src/ui/select/select.tsx @@ -1,4 +1,4 @@ -/* eslint-disable react/require-default-props */ +import { Ref, forwardRef } from 'react'; import { FormControl, InputLabel, @@ -39,7 +39,7 @@ export interface TypeMenuItemProps { * @param {TypeSelectProps} props custom select properties * @returns {JSX.Element} the auto complete ui component */ -export function Select(props: TypeSelectProps): JSX.Element { +function MUISelect(props: TypeSelectProps, ref: Ref): JSX.Element { const { fullWidth, inputLabel, menuItems, formControlProps = {}, container, ...selectProps } = props; const theme = useTheme(); @@ -52,7 +52,7 @@ export function Select(props: TypeSelectProps): JSX.Element { {selectProps.label} )} - + {menuItems.map((menuItem: TypeMenuItemProps, index) => { if (menuItem) { if (menuItem.type === 'header') { @@ -70,3 +70,6 @@ export function Select(props: TypeSelectProps): JSX.Element { ); } + +// Export the Select using forwardRef so that passing ref is permitted and functional in the react standards +export const Select = forwardRef(MUISelect); diff --git a/packages/geoview-core/src/ui/text-field/text-field.tsx b/packages/geoview-core/src/ui/text-field/text-field.tsx index a53326c9308..3d99bc245d0 100644 --- a/packages/geoview-core/src/ui/text-field/text-field.tsx +++ b/packages/geoview-core/src/ui/text-field/text-field.tsx @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { forwardRef, Ref } from 'react'; import { useTranslation } from 'react-i18next'; @@ -12,17 +12,19 @@ import { TypeTextFieldProps } from '@/ui/panel/panel-types'; * @param {TypeTextFieldProps} props custom textfield properties * @returns {JSX.Element} the text field ui component */ -export function TextField(props: TypeTextFieldProps): JSX.Element { +function MUITextField(props: TypeTextFieldProps, ref: Ref): JSX.Element { const { tooltip, tooltipPlacement, ...rest } = props; const { t } = useTranslation(); // internal state - const textRef = useRef(null); + // const textRef = useRef(null); return ( - - + + ); } + +export const TextField = forwardRef(MUITextField);