diff --git a/package.json b/package.json
index 362e872..052d076 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@togglecorp/toggle-ui",
- "version": "0.18.3",
+ "version": "0.18.4",
"description": "React component library by togglecorp",
"files": [
"/build"
diff --git a/src/components/GenericOption/index.tsx b/src/components/GenericOption/index.tsx
index a6abe76..4634c3f 100644
--- a/src/components/GenericOption/index.tsx
+++ b/src/components/GenericOption/index.tsx
@@ -1,5 +1,8 @@
import React, { useCallback, useRef, useEffect } from 'react';
-import { _cs } from '@togglecorp/fujs';
+import {
+ _cs,
+ isNotDefined,
+} from '@togglecorp/fujs';
import RawButton from '../RawButton';
@@ -15,6 +18,7 @@ export interface GenericOptionParams
>) => React.ReactNode;
contentRendererParam: (key: OK, opt: O) => P;
+ actionsSelector?: (props: O) => React.ReactNode;
option: O;
optionKey: OK;
onClick: (optionKey: OK, option: O) => void;
@@ -25,6 +29,7 @@ function GenericOption
({
optionContainerClassName,
contentRenderer,
contentRendererParam,
+ actionsSelector,
option,
onClick,
onFocus,
@@ -81,23 +86,41 @@ function GenericOption
({
[],
);
+ if (isNotDefined(actionsSelector)) {
+ return (
+
+ {contentRenderer(props)}
+
+ );
+ }
+
return (
-
- {contentRenderer(props)}
-
+
+ {contentRenderer(props)}
+
+ {actionsSelector(option)}
+
);
}
export default GenericOption;
diff --git a/src/components/GenericOption/styles.css b/src/components/GenericOption/styles.css
index c6b28ef..3d72c4b 100644
--- a/src/components/GenericOption/styles.css
+++ b/src/components/GenericOption/styles.css
@@ -2,3 +2,12 @@
padding: calc(var(--tui-spacing-large) - var(--tui-spacing-small));
text-align: left;
}
+.option-container {
+ display: flex;
+ align-items: center;
+ padding-right: var(--tui-spacing-small);
+
+ .option-renderer {
+ flex-grow: 1;
+ }
+}
diff --git a/src/components/MultiSelectInput/SearchMultiSelectInput.tsx b/src/components/MultiSelectInput/SearchMultiSelectInput.tsx
index 59f8f69..787ecdc 100644
--- a/src/components/MultiSelectInput/SearchMultiSelectInput.tsx
+++ b/src/components/MultiSelectInput/SearchMultiSelectInput.tsx
@@ -12,13 +12,12 @@ import { rankedSearchOnList } from '../../utils';
import styles from './styles.css';
interface OptionProps {
- actions?: React.ReactNode;
children: React.ReactNode;
isActive: boolean;
}
+
function Option(props: OptionProps) {
const {
- actions,
children,
isActive,
} = props;
@@ -31,9 +30,6 @@ function Option(props: OptionProps) {
{ children }
-
- {actions}
-
>
);
}
@@ -244,11 +240,10 @@ function SearchMultiSelectInput<
children: labelSelector(option),
containerClassName: _cs(styles.option, isActive && styles.active),
title: labelSelector(option),
- actions: actionsSelector?.(option),
isActive,
};
},
- [labelSelector, value, actionsSelector],
+ [labelSelector, value],
);
// FIXME: value should not be on dependency list, also try to pass options like in SelectInput
@@ -296,6 +291,7 @@ function SearchMultiSelectInput<
optionKeySelector={keySelector}
optionRenderer={Option}
optionRendererParams={optionRendererParams}
+ actionsSelector={actionsSelector}
optionContainerClassName={styles.optionContainer}
onOptionClick={handleOptionClick}
valueDisplay={valueDisplay}
diff --git a/src/components/SelectInput/SearchSelectInput.tsx b/src/components/SelectInput/SearchSelectInput.tsx
index 7d00378..f9b3813 100644
--- a/src/components/SelectInput/SearchSelectInput.tsx
+++ b/src/components/SelectInput/SearchSelectInput.tsx
@@ -12,12 +12,10 @@ import { rankedSearchOnList } from '../../utils';
import styles from './styles.css';
interface OptionProps {
- actions?: React.ReactNode;
children: React.ReactNode;
}
function Option(props: OptionProps) {
const {
- actions,
children,
} = props;
@@ -29,9 +27,6 @@ function Option(props: OptionProps) {
{ children }
-
- {actions}
-
>
);
}
@@ -237,12 +232,11 @@ function SearchSelectInput<
return {
children: labelSelector(option),
- actions: actionsSelector?.(option),
containerClassName: _cs(styles.option, isActive && styles.active),
title: labelSelector(option),
};
},
- [value, labelSelector, actionsSelector],
+ [value, labelSelector],
);
const handleOptionClick = useCallback(
@@ -283,6 +277,7 @@ function SearchSelectInput<
optionKeySelector={keySelector}
optionRenderer={Option}
optionRendererParams={optionRendererParams}
+ actionsSelector={actionsSelector}
optionContainerClassName={styles.optionContainer}
onOptionClick={handleOptionClick}
valueDisplay={valueDisplay}
diff --git a/src/components/SelectInputContainer/index.tsx b/src/components/SelectInputContainer/index.tsx
index 34335b0..370d1d4 100644
--- a/src/components/SelectInputContainer/index.tsx
+++ b/src/components/SelectInputContainer/index.tsx
@@ -61,6 +61,7 @@ export type SelectInputContainerProps<
optionKeySelector: (datum: O, index: number) => OK;
optionRenderer: (props: Pick>) => React.ReactNode;
optionRendererParams: (optionKey: OK, option: O) => P;
+ actionsSelector?: (option: O) => React.ReactNode;
totalOptionsCount?: number;
optionsPopupContentClassName?: string;
options: O[] | undefined | null;
@@ -112,6 +113,7 @@ function SelectInputContainer) {
- // NOTE: This intentionally breaks HTML semantics (link inside a button).
- // This workaround is to allow clickable links inside SelectInput options
- // where a button wrapper is required.
- e.stopPropagation();
- window.open('https://www.google.com/search?q=story', '_blank');
-}
-
export const WithActions = Template.bind({});
WithActions.args = {
actionsSelector: () => (
-
-
+
),
};
diff --git a/src/stories/SearchMultiSelectInput.stories.tsx b/src/stories/SearchMultiSelectInput.stories.tsx
index e943fb0..e26f546 100644
--- a/src/stories/SearchMultiSelectInput.stories.tsx
+++ b/src/stories/SearchMultiSelectInput.stories.tsx
@@ -3,7 +3,6 @@ import { Story } from '@storybook/react/types-6-0';
import { useArgs } from '@storybook/client-api';
import { IoOpenOutline } from 'react-icons/io5';
import SearchMultiSelectInput, { SearchMultiSelectInputProps } from '#components/MultiSelectInput/SearchMultiSelectInput';
-import QuickActionButton from '#components/QuickActionButton';
import useQuery, { entityListTransformer } from '../utils/useQuery';
export default {
@@ -190,24 +189,16 @@ const Template: Story) {
- // NOTE: This intentionally breaks HTML semantics (link inside a button).
- // This workaround is to allow clickable links inside SelectInput options
- // where a button wrapper is required.
- e.stopPropagation();
- window.open('https://www.google.com/search?q=story', '_blank');
-}
-
export const WithActions = Template.bind({});
WithActions.args = {
actionsSelector: () => (
-
-
+
),
};
diff --git a/src/stories/SearchSelectInput.stories.tsx b/src/stories/SearchSelectInput.stories.tsx
index 2f7555e..762a6d4 100644
--- a/src/stories/SearchSelectInput.stories.tsx
+++ b/src/stories/SearchSelectInput.stories.tsx
@@ -3,7 +3,6 @@ import { Story } from '@storybook/react/types-6-0';
import { useArgs } from '@storybook/client-api';
import { IoOpenOutline } from 'react-icons/io5';
import SearchSelectInput, { SearchSelectInputProps } from '#components/SelectInput/SearchSelectInput';
-import QuickActionButton from '#components/QuickActionButton';
import useQuery, { entityListTransformer } from '../utils/useQuery';
export default {
@@ -195,24 +194,16 @@ Default.args = {
value: '1',
};
-function handleClick(_:string | undefined, e: React.MouseEvent) {
- // NOTE: This intentionally breaks HTML semantics (link inside a button).
- // This workaround is to allow clickable links inside SelectInput options
- // where a button wrapper is required.
- e.stopPropagation();
- window.open('https://www.google.com/search?q=story', '_blank');
-}
-
export const WithActions = Template.bind({});
WithActions.args = {
actionsSelector: () => (
-
-
+
),
};
diff --git a/src/stories/SelectInput.stories.tsx b/src/stories/SelectInput.stories.tsx
index 4bc649a..e60d460 100644
--- a/src/stories/SelectInput.stories.tsx
+++ b/src/stories/SelectInput.stories.tsx
@@ -3,7 +3,6 @@ import { Story } from '@storybook/react/types-6-0';
import { useArgs } from '@storybook/client-api';
import { IoOpenOutline } from 'react-icons/io5';
import SelectInput, { SelectInputProps } from '#components/SelectInput';
-import QuickActionButton from '#components/QuickActionButton';
export default {
title: 'Input/SelectInput',
@@ -47,24 +46,16 @@ const Template: Story) {
- // NOTE: This intentionally breaks HTML semantics (link inside a button).
- // This workaround is to allow clickable links inside SelectInput options
- // where a button wrapper is required.
- e.stopPropagation();
- window.open('https://www.google.com/search?q=story', '_blank');
-}
-
export const WithActions = Template.bind({});
WithActions.args = {
actionsSelector: () => (
-
-
+
),
};