feat: add DropdownMenuInput and use as view name input in board (#1680)
Closes #1510
This commit is contained in:
@ -3,7 +3,7 @@ import { useRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { currentPipelineState } from '@/pipeline/states/currentPipelineState';
|
import { currentPipelineState } from '@/pipeline/states/currentPipelineState';
|
||||||
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -106,7 +106,7 @@ export const CompanyProgressPicker = ({
|
|||||||
{selectedPipelineStage?.name}
|
{selectedPipelineStage?.name}
|
||||||
</DropdownMenuHeader>
|
</DropdownMenuHeader>
|
||||||
<StyledDropdownMenuSeparator />
|
<StyledDropdownMenuSeparator />
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleSearchFilterChange}
|
onChange={handleSearchFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import debounce from 'lodash.debounce';
|
|||||||
import { ReadonlyDeep } from 'type-fest';
|
import { ReadonlyDeep } from 'type-fest';
|
||||||
|
|
||||||
import type { SelectOption } from '@/spreadsheet-import/types';
|
import type { SelectOption } from '@/spreadsheet-import/types';
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -120,7 +120,7 @@ export const MatchColumnSelect = ({
|
|||||||
ref={dropdownContainerRef}
|
ref={dropdownContainerRef}
|
||||||
width={refs.domReference.current?.clientWidth}
|
width={refs.domReference.current?.clientWidth}
|
||||||
>
|
>
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleFilterChange}
|
onChange={handleFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
|
import { useResetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
|
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
|
||||||
|
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
|
||||||
|
|
||||||
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
|
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
|
||||||
|
|
||||||
@ -17,6 +20,8 @@ export const BoardOptionsDropdown = ({
|
|||||||
customHotkeyScope,
|
customHotkeyScope,
|
||||||
onStageAdd,
|
onStageAdd,
|
||||||
}: BoardOptionsDropdownProps) => {
|
}: BoardOptionsDropdownProps) => {
|
||||||
|
const resetViewEditMode = useResetRecoilState(viewEditModeState);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
buttonComponents={<BoardOptionsDropdownButton />}
|
buttonComponents={<BoardOptionsDropdownButton />}
|
||||||
@ -28,6 +33,7 @@ export const BoardOptionsDropdown = ({
|
|||||||
}
|
}
|
||||||
dropdownHotkeyScope={customHotkeyScope}
|
dropdownHotkeyScope={customHotkeyScope}
|
||||||
dropdownId={BoardOptionsDropdownKey}
|
dropdownId={BoardOptionsDropdownKey}
|
||||||
|
onClickOutside={resetViewEditMode}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,18 @@
|
|||||||
import { useContext, useRef, useState } from 'react';
|
import { useContext, useRef, useState } from 'react';
|
||||||
import { useTheme } from '@emotion/react';
|
import {
|
||||||
import styled from '@emotion/styled';
|
useRecoilCallback,
|
||||||
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
|
useRecoilState,
|
||||||
|
useRecoilValue,
|
||||||
|
useResetRecoilState,
|
||||||
|
} from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
||||||
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
|
import { DropdownMenuInputContainer } from '@/ui/dropdown/components/DropdownMenuInputContainer';
|
||||||
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -16,7 +21,6 @@ import {
|
|||||||
IconChevronLeft,
|
IconChevronLeft,
|
||||||
IconLayoutKanban,
|
IconLayoutKanban,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
IconSettings,
|
|
||||||
IconTag,
|
IconTag,
|
||||||
} from '@/ui/icon';
|
} from '@/ui/icon';
|
||||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||||
@ -28,6 +32,7 @@ import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoi
|
|||||||
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
||||||
import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
|
import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
|
||||||
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
|
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
|
||||||
|
import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector';
|
||||||
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
|
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
|
||||||
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
|
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
|
||||||
|
|
||||||
@ -45,10 +50,6 @@ export type BoardOptionsDropdownContentProps = {
|
|||||||
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
|
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledIconSettings = styled(IconSettings)`
|
|
||||||
margin-right: ${({ theme }) => theme.spacing(1)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
type BoardOptionsMenu = 'fields' | 'stage-creation' | 'stages';
|
type BoardOptionsMenu = 'fields' | 'stage-creation' | 'stages';
|
||||||
|
|
||||||
type ColumnForCreate = {
|
type ColumnForCreate = {
|
||||||
@ -62,10 +63,7 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
customHotkeyScope,
|
customHotkeyScope,
|
||||||
onStageAdd,
|
onStageAdd,
|
||||||
}: BoardOptionsDropdownContentProps) => {
|
}: BoardOptionsDropdownContentProps) => {
|
||||||
const theme = useTheme();
|
const { BoardRecoilScopeContext } = useContext(BoardContext);
|
||||||
|
|
||||||
const BoardRecoilScopeContext =
|
|
||||||
useContext(BoardContext).BoardRecoilScopeContext;
|
|
||||||
|
|
||||||
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
|
const boardRecoilScopeId = useRecoilScopeId(BoardRecoilScopeContext);
|
||||||
|
|
||||||
@ -93,7 +91,12 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
viewsByIdScopedSelector,
|
viewsByIdScopedSelector,
|
||||||
BoardRecoilScopeContext, // TODO: replace with ViewBarRecoilScopeContext
|
BoardRecoilScopeContext, // TODO: replace with ViewBarRecoilScopeContext
|
||||||
);
|
);
|
||||||
|
const currentView = useRecoilScopedValue(
|
||||||
|
currentViewScopedSelector,
|
||||||
|
BoardRecoilScopeContext,
|
||||||
|
);
|
||||||
const viewEditMode = useRecoilValue(viewEditModeState);
|
const viewEditMode = useRecoilValue(viewEditModeState);
|
||||||
|
const resetViewEditMode = useResetRecoilState(viewEditModeState);
|
||||||
|
|
||||||
const handleStageSubmit = () => {
|
const handleStageSubmit = () => {
|
||||||
if (currentMenu !== 'stage-creation' || !stageInputRef?.current?.value)
|
if (currentMenu !== 'stage-creation' || !stageInputRef?.current?.value)
|
||||||
@ -148,6 +151,7 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
Key.Escape,
|
Key.Escape,
|
||||||
() => {
|
() => {
|
||||||
|
resetViewEditMode();
|
||||||
closeDropdownButton();
|
closeDropdownButton();
|
||||||
},
|
},
|
||||||
customHotkeyScope.scope,
|
customHotkeyScope.scope,
|
||||||
@ -158,6 +162,7 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
() => {
|
() => {
|
||||||
handleStageSubmit();
|
handleStageSubmit();
|
||||||
handleViewNameSubmit();
|
handleViewNameSubmit();
|
||||||
|
resetViewEditMode();
|
||||||
closeDropdownButton();
|
closeDropdownButton();
|
||||||
},
|
},
|
||||||
customHotkeyScope.scope,
|
customHotkeyScope.scope,
|
||||||
@ -167,25 +172,24 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
<StyledDropdownMenu>
|
<StyledDropdownMenu>
|
||||||
{!currentMenu && (
|
{!currentMenu && (
|
||||||
<>
|
<>
|
||||||
{!!viewEditMode.mode ? (
|
<DropdownMenuInputContainer>
|
||||||
<DropdownMenuInput
|
<DropdownMenuInput
|
||||||
ref={viewEditInputRef}
|
ref={viewEditInputRef}
|
||||||
autoFocus
|
autoFocus={
|
||||||
|
viewEditMode.mode === 'create' || !!viewEditMode.viewId
|
||||||
|
}
|
||||||
placeholder={
|
placeholder={
|
||||||
viewEditMode.mode === 'create' ? 'New view' : 'View name'
|
viewEditMode.mode === 'create' ? 'New view' : 'View name'
|
||||||
}
|
}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
viewEditMode.viewId
|
viewEditMode.mode === 'create'
|
||||||
|
? ''
|
||||||
|
: viewEditMode.viewId
|
||||||
? viewsById[viewEditMode.viewId]?.name
|
? viewsById[viewEditMode.viewId]?.name
|
||||||
: undefined
|
: currentView?.name
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
</DropdownMenuInputContainer>
|
||||||
<DropdownMenuHeader>
|
|
||||||
<StyledIconSettings size={theme.icon.size.md} />
|
|
||||||
Settings
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
)}
|
|
||||||
<StyledDropdownMenuSeparator />
|
<StyledDropdownMenuSeparator />
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuItemsContainer>
|
||||||
<MenuItemNavigate
|
<MenuItemNavigate
|
||||||
@ -217,7 +221,7 @@ export const BoardOptionsDropdownContent = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{currentMenu === 'stage-creation' && (
|
{currentMenu === 'stage-creation' && (
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
placeholder="New stage"
|
placeholder="New stage"
|
||||||
ref={stageInputRef}
|
ref={stageInputRef}
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { userEvent, within } from '@storybook/testing-library';
|
||||||
|
|
||||||
|
import { BoardContext } from '@/companies/states/contexts/BoardContext';
|
||||||
|
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
|
||||||
|
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
|
||||||
|
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||||
|
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
|
||||||
|
|
||||||
|
import { BoardOptionsDropdown } from '../BoardOptionsDropdown';
|
||||||
|
|
||||||
|
const meta: Meta<typeof BoardOptionsDropdown> = {
|
||||||
|
title: 'UI/Board/Options/BoardOptionsDropdown',
|
||||||
|
component: BoardOptionsDropdown,
|
||||||
|
decorators: [
|
||||||
|
(Story, { parameters }) => (
|
||||||
|
<BoardContext.Provider
|
||||||
|
value={{
|
||||||
|
BoardRecoilScopeContext: parameters.customRecoilScopeContext,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ViewBarContext.Provider
|
||||||
|
value={{
|
||||||
|
ViewBarRecoilScopeContext: parameters.customRecoilScopeContext,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
|
||||||
|
<Story />
|
||||||
|
</RecoilScope>
|
||||||
|
</ViewBarContext.Provider>
|
||||||
|
</BoardContext.Provider>
|
||||||
|
),
|
||||||
|
ComponentWithRecoilScopeDecorator,
|
||||||
|
ComponentDecorator,
|
||||||
|
],
|
||||||
|
parameters: {
|
||||||
|
customRecoilScopeContext: CompanyBoardRecoilScopeContext,
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
customHotkeyScope: { scope: 'scope' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof BoardOptionsDropdown>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
play: async ({ canvasElement }) => {
|
||||||
|
const canvas = within(canvasElement);
|
||||||
|
|
||||||
|
const dropdownButton = canvas.getByText('Options');
|
||||||
|
|
||||||
|
await userEvent.click(dropdownButton);
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -1,43 +1,23 @@
|
|||||||
import { forwardRef, InputHTMLAttributes } from 'react';
|
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { rgba } from '@/ui/theme/constants/colors';
|
||||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
const StyledDropdownMenuInputContainer = styled.div`
|
const StyledViewNameInput = styled.input`
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
|
||||||
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
height: calc(36px - 2 * var(--vertical-padding));
|
|
||||||
padding: var(--vertical-padding) 0;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledInput = styled.input`
|
|
||||||
${textInputStyle}
|
${textInputStyle}
|
||||||
|
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
|
height: 32px;
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&[type='number']::-webkit-outer-spin-button,
|
&:focus {
|
||||||
&[type='number']::-webkit-inner-spin-button {
|
border-color: ${({ theme }) => theme.color.blue};
|
||||||
-webkit-appearance: none;
|
box-shadow: 0px 0px 0px 3px ${({ theme }) => rgba(theme.color.blue, 0.1)};
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[type='number'] {
|
|
||||||
-moz-appearance: textfield;
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const DropdownMenuInput = forwardRef<
|
export { StyledViewNameInput as DropdownMenuInput };
|
||||||
HTMLInputElement,
|
|
||||||
InputHTMLAttributes<HTMLInputElement>
|
|
||||||
>((props, ref) => (
|
|
||||||
<StyledDropdownMenuInputContainer>
|
|
||||||
<StyledInput autoComplete="off" placeholder="Search" {...props} ref={ref} />
|
|
||||||
</StyledDropdownMenuInputContainer>
|
|
||||||
));
|
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
const StyledInputContainer = styled.div`
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: ${({ theme }) => theme.spacing(1)};
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export { StyledInputContainer as DropdownMenuInputContainer };
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import { forwardRef, InputHTMLAttributes } from 'react';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { textInputStyle } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
|
const StyledDropdownMenuSearchInputContainer = styled.div`
|
||||||
|
--vertical-padding: ${({ theme }) => theme.spacing(1)};
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: calc(36px - 2 * var(--vertical-padding));
|
||||||
|
padding: var(--vertical-padding) 0;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledInput = styled.input`
|
||||||
|
${textInputStyle}
|
||||||
|
|
||||||
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&[type='number']::-webkit-outer-spin-button,
|
||||||
|
&[type='number']::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[type='number'] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DropdownMenuSearchInput = forwardRef<
|
||||||
|
HTMLInputElement,
|
||||||
|
InputHTMLAttributes<HTMLInputElement>
|
||||||
|
>((props, ref) => (
|
||||||
|
<StyledDropdownMenuSearchInputContainer>
|
||||||
|
<StyledInput autoComplete="off" placeholder="Search" {...props} ref={ref} />
|
||||||
|
</StyledDropdownMenuSearchInputContainer>
|
||||||
|
));
|
||||||
@ -1,8 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
import { IconPlus, IconUser } from '@/ui/icon';
|
|
||||||
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
|
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
|
||||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||||
import { MenuItemMultiSelectAvatar } from '@/ui/menu-item/components/MenuItemMultiSelectAvatar';
|
import { MenuItemMultiSelectAvatar } from '@/ui/menu-item/components/MenuItemMultiSelectAvatar';
|
||||||
@ -12,6 +11,8 @@ import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
|||||||
|
|
||||||
import { DropdownMenuHeader } from '../DropdownMenuHeader';
|
import { DropdownMenuHeader } from '../DropdownMenuHeader';
|
||||||
import { DropdownMenuInput } from '../DropdownMenuInput';
|
import { DropdownMenuInput } from '../DropdownMenuInput';
|
||||||
|
import { DropdownMenuInputContainer } from '../DropdownMenuInputContainer';
|
||||||
|
import { DropdownMenuSearchInput } from '../DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '../StyledDropdownMenu';
|
import { StyledDropdownMenu } from '../StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '../StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '../StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '../StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '../StyledDropdownMenuSeparator';
|
||||||
@ -23,7 +24,9 @@ const meta: Meta<typeof StyledDropdownMenu> = {
|
|||||||
decorators: [ComponentDecorator],
|
decorators: [ComponentDecorator],
|
||||||
argTypes: {
|
argTypes: {
|
||||||
as: { table: { disable: true } },
|
as: { table: { disable: true } },
|
||||||
|
children: { control: false },
|
||||||
theme: { table: { disable: true } },
|
theme: { table: { disable: true } },
|
||||||
|
width: { type: 'number', defaultValue: undefined },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,21 +125,22 @@ const FakeSelectableMenuItemList = ({ hasAvatar }: { hasAvatar?: boolean }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FakeCheckableMenuItemList = ({ hasAvatar }: { hasAvatar?: boolean }) => {
|
const FakeCheckableMenuItemList = ({ hasAvatar }: { hasAvatar?: boolean }) => {
|
||||||
const [selectedItems, setSelectedItems] = useState<string[]>([]);
|
const [selectedItemsById, setSelectedItemsById] = useState<
|
||||||
|
Record<string, boolean>
|
||||||
|
>({});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{mockSelectArray.map((item) => (
|
{mockSelectArray.map((item) => (
|
||||||
<MenuItemMultiSelectAvatar
|
<MenuItemMultiSelectAvatar
|
||||||
key={item.id}
|
key={item.id}
|
||||||
selected={selectedItems.includes(item.id)}
|
selected={selectedItemsById[item.id]}
|
||||||
onSelectChange={(checked) => {
|
onSelectChange={(checked) =>
|
||||||
if (checked) {
|
setSelectedItemsById((previous) => ({
|
||||||
setSelectedItems([...selectedItems, item.id]);
|
...previous,
|
||||||
} else {
|
[item.id]: checked,
|
||||||
setSelectedItems(selectedItems.filter((id) => id !== item.id));
|
}))
|
||||||
}
|
}
|
||||||
}}
|
|
||||||
avatar={
|
avatar={
|
||||||
hasAvatar ? (
|
hasAvatar ? (
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -154,165 +158,96 @@ const FakeCheckableMenuItemList = ({ hasAvatar }: { hasAvatar?: boolean }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const WithContentBelowDecorator: Decorator = (Story) => (
|
||||||
|
<StyledFakeBelowContainer>
|
||||||
|
<FakeContentBelow />
|
||||||
|
<StyledMenuAbsolutePositionWrapper>
|
||||||
|
<Story />
|
||||||
|
</StyledMenuAbsolutePositionWrapper>
|
||||||
|
</StyledFakeBelowContainer>
|
||||||
|
);
|
||||||
|
|
||||||
export const Empty: Story = {
|
export const Empty: Story = {
|
||||||
render: (args) => (
|
args: { children: <StyledFakeMenuContent /> },
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledFakeMenuContent />
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithContentBelow: Story = {
|
|
||||||
...Empty,
|
|
||||||
decorators: [
|
|
||||||
(Story) => (
|
|
||||||
<StyledFakeBelowContainer>
|
|
||||||
<FakeContentBelow />
|
|
||||||
<StyledMenuAbsolutePositionWrapper>
|
|
||||||
<Story />
|
|
||||||
</StyledMenuAbsolutePositionWrapper>
|
|
||||||
</StyledFakeBelowContainer>
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SimpleMenuItem: Story = {
|
|
||||||
...WithContentBelow,
|
|
||||||
render: (args) => (
|
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
|
||||||
{mockSelectArray.map(({ name }) => (
|
|
||||||
<MenuItem text={name} />
|
|
||||||
))}
|
|
||||||
</StyledDropdownMenuItemsContainer>
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WithHeaders: Story = {
|
export const WithHeaders: Story = {
|
||||||
...WithContentBelow,
|
decorators: [WithContentBelowDecorator],
|
||||||
render: (args) => (
|
args: {
|
||||||
<StyledDropdownMenu {...args}>
|
children: (
|
||||||
<DropdownMenuHeader>Header</DropdownMenuHeader>
|
<>
|
||||||
<StyledDropdownMenuSeparator />
|
<DropdownMenuHeader>Header</DropdownMenuHeader>
|
||||||
<StyledDropdownMenuSubheader>Subheader 1</StyledDropdownMenuSubheader>
|
<StyledDropdownMenuSeparator />
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuSubheader>Subheader 1</StyledDropdownMenuSubheader>
|
||||||
{mockSelectArray.slice(0, 3).map(({ name }) => (
|
<StyledDropdownMenuItemsContainer>
|
||||||
<MenuItem text={name} />
|
{mockSelectArray.slice(0, 3).map(({ name }) => (
|
||||||
))}
|
<MenuItem text={name} />
|
||||||
</StyledDropdownMenuItemsContainer>
|
))}
|
||||||
<StyledDropdownMenuSeparator />
|
</StyledDropdownMenuItemsContainer>
|
||||||
<StyledDropdownMenuSubheader>Subheader 2</StyledDropdownMenuSubheader>
|
<StyledDropdownMenuSeparator />
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuSubheader>Subheader 2</StyledDropdownMenuSubheader>
|
||||||
{mockSelectArray.slice(3).map(({ name }) => (
|
<StyledDropdownMenuItemsContainer>
|
||||||
<MenuItem text={name} />
|
{mockSelectArray.slice(3).map(({ name }) => (
|
||||||
))}
|
<MenuItem text={name} />
|
||||||
</StyledDropdownMenuItemsContainer>
|
))}
|
||||||
</StyledDropdownMenu>
|
</StyledDropdownMenuItemsContainer>
|
||||||
),
|
</>
|
||||||
};
|
),
|
||||||
|
|
||||||
export const WithIcons: Story = {
|
|
||||||
...WithContentBelow,
|
|
||||||
render: (args) => (
|
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
|
||||||
{mockSelectArray.map(({ name }) => (
|
|
||||||
<MenuItem text={name} LeftIcon={IconUser} />
|
|
||||||
))}
|
|
||||||
</StyledDropdownMenuItemsContainer>
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const WithActions: Story = {
|
|
||||||
...WithContentBelow,
|
|
||||||
render: (args) => (
|
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
|
||||||
{mockSelectArray.map(({ name }, index) => (
|
|
||||||
<MenuItem
|
|
||||||
className={index === 0 ? 'hover' : undefined}
|
|
||||||
iconButtons={[{ Icon: IconUser }, { Icon: IconPlus }]}
|
|
||||||
text={name}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</StyledDropdownMenuItemsContainer>
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
parameters: {
|
|
||||||
pseudo: { hover: ['.hover'] },
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LoadingMenu: Story = {
|
export const SearchWithLoadingMenu: Story = {
|
||||||
...WithContentBelow,
|
decorators: [WithContentBelowDecorator],
|
||||||
render: () => (
|
args: {
|
||||||
<StyledDropdownMenu>
|
children: (
|
||||||
<DropdownMenuInput value={'query'} autoFocus />
|
<>
|
||||||
<StyledDropdownMenuSeparator />
|
<DropdownMenuSearchInput value="query" autoFocus />
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
<StyledDropdownMenuSeparator />
|
||||||
<DropdownMenuSkeletonItem />
|
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
||||||
</StyledDropdownMenuItemsContainer>
|
<DropdownMenuSkeletonItem />
|
||||||
</StyledDropdownMenu>
|
</StyledDropdownMenuItemsContainer>
|
||||||
),
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Search: Story = {
|
export const WithInput: Story = {
|
||||||
...WithContentBelow,
|
decorators: [WithContentBelowDecorator],
|
||||||
render: (args) => (
|
args: {
|
||||||
<StyledDropdownMenu {...args}>
|
children: (
|
||||||
<DropdownMenuInput />
|
<>
|
||||||
<StyledDropdownMenuSeparator />
|
<DropdownMenuInputContainer>
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuInput defaultValue="Lorem ipsum" autoFocus />
|
||||||
{mockSelectArray.map(({ name }) => (
|
</DropdownMenuInputContainer>
|
||||||
<MenuItem text={name} />
|
<StyledDropdownMenuSeparator />
|
||||||
))}
|
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
||||||
</StyledDropdownMenuItemsContainer>
|
{mockSelectArray.map(({ name }) => (
|
||||||
</StyledDropdownMenu>
|
<MenuItem text={name} />
|
||||||
),
|
))}
|
||||||
};
|
</StyledDropdownMenuItemsContainer>
|
||||||
|
</>
|
||||||
export const SelectableMenuItem: Story = {
|
),
|
||||||
...WithContentBelow,
|
},
|
||||||
render: (args) => (
|
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
|
||||||
<FakeSelectableMenuItemList />
|
|
||||||
</StyledDropdownMenuItemsContainer>
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SelectableMenuItemWithAvatar: Story = {
|
export const SelectableMenuItemWithAvatar: Story = {
|
||||||
...WithContentBelow,
|
decorators: [WithContentBelowDecorator],
|
||||||
render: (args) => (
|
args: {
|
||||||
<StyledDropdownMenu {...args}>
|
children: (
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
||||||
<FakeSelectableMenuItemList hasAvatar />
|
<FakeSelectableMenuItemList hasAvatar />
|
||||||
</StyledDropdownMenuItemsContainer>
|
</StyledDropdownMenuItemsContainer>
|
||||||
</StyledDropdownMenu>
|
),
|
||||||
),
|
},
|
||||||
};
|
|
||||||
|
|
||||||
export const CheckableMenuItem: Story = {
|
|
||||||
...WithContentBelow,
|
|
||||||
render: (args) => (
|
|
||||||
<StyledDropdownMenu {...args}>
|
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
|
||||||
<FakeCheckableMenuItemList />
|
|
||||||
</StyledDropdownMenuItemsContainer>
|
|
||||||
</StyledDropdownMenu>
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CheckableMenuItemWithAvatar: Story = {
|
export const CheckableMenuItemWithAvatar: Story = {
|
||||||
...WithContentBelow,
|
decorators: [WithContentBelowDecorator],
|
||||||
render: (args) => (
|
args: {
|
||||||
<StyledDropdownMenu {...args}>
|
children: (
|
||||||
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
<StyledDropdownMenuItemsContainer hasMaxHeight>
|
||||||
<FakeCheckableMenuItemList hasAvatar />
|
<FakeCheckableMenuItemList hasAvatar />
|
||||||
</StyledDropdownMenuItemsContainer>
|
</StyledDropdownMenuItemsContainer>
|
||||||
</StyledDropdownMenu>
|
),
|
||||||
),
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { DropdownMenuInput } from '../DropdownMenuInput';
|
||||||
|
|
||||||
|
const meta: Meta<typeof DropdownMenuInput> = {
|
||||||
|
title: 'UI/Dropdown/DropdownMenuInput',
|
||||||
|
component: DropdownMenuInput,
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
args: { defaultValue: 'Lorem ipsum' },
|
||||||
|
argTypes: {
|
||||||
|
as: { table: { disable: true } },
|
||||||
|
theme: { table: { disable: true } },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof DropdownMenuInput>;
|
||||||
|
|
||||||
|
export const Default: Story = {};
|
||||||
|
|
||||||
|
export const Focused: Story = {
|
||||||
|
args: { autoFocus: true },
|
||||||
|
};
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import debounce from 'lodash.debounce';
|
import debounce from 'lodash.debounce';
|
||||||
|
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -73,7 +73,7 @@ export const MultipleEntitySelect = <
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledDropdownMenu ref={containerRef}>
|
<StyledDropdownMenu ref={containerRef}>
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleFilterChange}
|
onChange={handleFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -65,7 +65,7 @@ export const SingleEntitySelect = <
|
|||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
width={width}
|
width={width}
|
||||||
>
|
>
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleSearchFilterChange}
|
onChange={handleSearchFilterChange}
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
import { useCallback, useContext, useRef, useState } from 'react';
|
import { useCallback, useContext, useRef, useState } from 'react';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
import { OnDragEndResponder } from '@hello-pangea/dnd';
|
||||||
import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
|
import { useRecoilCallback, useRecoilValue, useResetRecoilState } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
|
||||||
|
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
||||||
|
import { DropdownMenuInputContainer } from '@/ui/dropdown/components/DropdownMenuInputContainer';
|
||||||
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
|
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
|
||||||
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/icon';
|
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/icon';
|
||||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||||
import { rgba } from '@/ui/theme/constants/colors';
|
|
||||||
import { textInputStyle } from '@/ui/theme/constants/effects';
|
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||||
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
|
||||||
@ -34,29 +33,6 @@ import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
|
|||||||
|
|
||||||
type TableOptionsMenu = 'fields';
|
type TableOptionsMenu = 'fields';
|
||||||
|
|
||||||
const StyledInputContainer = styled.div`
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: ${({ theme }) => theme.spacing(1)};
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledViewNameInput = styled.input`
|
|
||||||
${textInputStyle}
|
|
||||||
|
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
|
||||||
height: 32px;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: ${({ theme }) => theme.color.blue};
|
|
||||||
box-shadow: 0px 0px 0px 3px ${({ theme }) => rgba(theme.color.blue, 0.1)};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const TableOptionsDropdownContent = () => {
|
export const TableOptionsDropdownContent = () => {
|
||||||
const scopeId = useRecoilScopeId(TableRecoilScopeContext);
|
const scopeId = useRecoilScopeId(TableRecoilScopeContext);
|
||||||
|
|
||||||
@ -158,8 +134,8 @@ export const TableOptionsDropdownContent = () => {
|
|||||||
<StyledDropdownMenu>
|
<StyledDropdownMenu>
|
||||||
{!currentMenu && (
|
{!currentMenu && (
|
||||||
<>
|
<>
|
||||||
<StyledInputContainer>
|
<DropdownMenuInputContainer>
|
||||||
<StyledViewNameInput
|
<DropdownMenuInput
|
||||||
ref={viewEditInputRef}
|
ref={viewEditInputRef}
|
||||||
autoFocus={
|
autoFocus={
|
||||||
viewEditMode.mode === 'create' || !!viewEditMode.viewId
|
viewEditMode.mode === 'create' || !!viewEditMode.viewId
|
||||||
@ -175,7 +151,7 @@ export const TableOptionsDropdownContent = () => {
|
|||||||
: currentView?.name
|
: currentView?.name
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledInputContainer>
|
</DropdownMenuInputContainer>
|
||||||
<StyledDropdownMenuSeparator />
|
<StyledDropdownMenuSeparator />
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuItemsContainer>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
|
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
|
||||||
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
|
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
|
||||||
@ -30,7 +30,7 @@ export const FilterDropdownEntitySearchInput = () => {
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
type="text"
|
type="text"
|
||||||
value={filterDropdownSearchInput}
|
value={filterDropdownSearchInput}
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|
||||||
import { useRemoveFilter } from '../hooks/useRemoveFilter';
|
import { useRemoveFilter } from '../hooks/useRemoveFilter';
|
||||||
@ -28,7 +28,7 @@ export const FilterDropdownNumberSearchInput = () => {
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
type="number"
|
type="number"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { ChangeEvent } from 'react';
|
import { ChangeEvent } from 'react';
|
||||||
|
|
||||||
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
|
import { DropdownMenuSearchInput } from '@/ui/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
|
||||||
|
|
||||||
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
import { useFilterCurrentlyEdited } from '../hooks/useFilterCurrentlyEdited';
|
||||||
@ -38,7 +38,7 @@ export const FilterDropdownTextSearchInput = () => {
|
|||||||
return (
|
return (
|
||||||
filterDefinitionUsedInDropdown &&
|
filterDefinitionUsedInDropdown &&
|
||||||
selectedOperandInDropdown && (
|
selectedOperandInDropdown && (
|
||||||
<DropdownMenuInput
|
<DropdownMenuSearchInput
|
||||||
type="text"
|
type="text"
|
||||||
placeholder={filterDefinitionUsedInDropdown.label}
|
placeholder={filterDefinitionUsedInDropdown.label}
|
||||||
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
value={filterCurrentlyEdited?.value ?? filterDropdownSearchInput}
|
||||||
|
|||||||
Reference in New Issue
Block a user