Skip to content

Commit

Permalink
remove old combobox
Browse files Browse the repository at this point in the history
  • Loading branch information
heswell committed May 13, 2024
1 parent 4627833 commit 6cfcb9d
Show file tree
Hide file tree
Showing 36 changed files with 206 additions and 1,630 deletions.
@@ -1,5 +1,5 @@
import type { ColumnDescriptor } from "@finos/vuu-table-types";
import { ExpandoComboboxSalt } from "./ExpandoComboboxSalt";
import { ExpandoCombobox } from "./ExpandoCombobox";
import { ComboBoxProps, Option } from "@salt-ds/core";
import { ForwardedRef, SyntheticEvent, forwardRef } from "react";

Expand All @@ -23,7 +23,7 @@ export const ColumnPicker = forwardRef(function ColumnPicker(
};

return (
<ExpandoComboboxSalt
<ExpandoCombobox
inputProps={inputProps}
className={className}
data-field="column"
Expand All @@ -35,6 +35,6 @@ export const ColumnPicker = forwardRef(function ColumnPicker(
{columns.map(({ name }) => (
<Option value={name} key={name} />
))}
</ExpandoComboboxSalt>
</ExpandoCombobox>
);
});
67 changes: 32 additions & 35 deletions vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.css
@@ -1,59 +1,56 @@
.vuuExpandoCombobox {
--expando-combobox-height: var(--vuuExpandoCombobox-height, var(--salt-size-base));
--expando-combobox-fontSize: var(--vuuExpandoCombobox-fontSize, 12px);

--saltInput-outline: none;
--saltInput-fontSize: var(--expando-combobox-fontSize);
--saltInput-height: var(--expando-combobox-height);
--saltInput-minWidth: 4px;
--saltInput-paddingLeft: 0px;
--saltInput-paddingRight: 0px;

display: inline-flex;
flex-direction: column;
height: var(--expando-combobox-height);
min-width: 4px;
padding: 0;

}

.vuuExpandoCombobox .saltInput {
background-color: transparent;
position: absolute;
}
.saltPill {
height: 100%;
padding-block: 0px;
}

.saltPillInput {
min-height: var(--expando-combobox-height);
min-width: 0px;
}


.saltPillInput-inputWrapper {
height: 100%;
min-width: max(var(--salt-spacing-800), 100%);
padding: 0;
}
.saltPillInput-input {
width: 0;
}

.saltPillInput-endAdornmentContainer {
display: none;
}
.saltPillInput-activationIndicator {
display: none;
}

.vuuExpandoCombobox .vuuDropdown {
height: 100%;
}

/** double up the selector just to increase specificity, won't need when we use cascade layers */
.vuuExpandoCombobox-Input.saltInput {
border: none;
left: 0px;
margin: 0;
min-height: 100%;
padding: 0;
right: 0px;
width: auto;
.vuuExpandoOption {
min-width: calc(var(--salt-size-base) * 2);
padding-left: var(--salt-spacing-200);
padding-right: var(--salt-spacing-200);
}

.vuuExpandoCombobox .saltInput-input {
border: none;
box-sizing: content-box;
display: block;
flex: 1;
font: inherit;
margin: 0;
min-width: 0;
outline: none;
padding: 0;
}

.vuuExpandoCombobox:before {
content: attr(data-text);
display: block;
font-size: var(--expando-combobox-fontSize);
height: 0px;
overflow: hidden;
/* visibility: hidden; */
white-space: pre-wrap;
/* position: absolute; */
}
228 changes: 73 additions & 155 deletions vuu-ui/packages/vuu-filters/src/filter-clause/ExpandoCombobox.tsx
@@ -1,196 +1,114 @@
import { itemToString as defaultToString } from "@finos/vuu-utils";
import {
ComboBox,
ComboBoxProps,
MultiSelectionHandler,
SelectionStrategy,
SingleSelectionHandler,
} from "@finos/vuu-ui-controls";
import { useComponentCssInjection } from "@salt-ds/styles";
import { useWindow } from "@salt-ds/window";
import cx from "clsx";
import { ComboBox, ComboBoxProps } from "@salt-ds/core";
import {
FormEvent,
ChangeEvent,
ForwardedRef,
Ref,
SyntheticEvent,
forwardRef,
ReactElement,
useCallback,
useMemo,
useRef,
useState,
} from "react";
import { useComponentCssInjection } from "@salt-ds/styles";
import { useWindow } from "@salt-ds/window";

import expandoBoxCss from "./ExpandoCombobox.css";
import expandoComboboxCss from "./ExpandoCombobox.css";

const classBase = "vuuExpandoCombobox";

const NO_INPUT_PROPS = {};

export interface ExpandoComboboxProps<
Item = string,
S extends SelectionStrategy = "default"
> extends Omit<ComboBoxProps<Item, S>, "itemToString" | "value"> {
itemToString?: (item: unknown) => string;
onInputChange?: (evt: FormEvent<HTMLInputElement>) => void;
value?: string | string[];
export interface ExpandoComboboxProps<Item = string>
extends ComboBoxProps<Item> {
itemToString?: (item: Item) => string;
}

const defaultItemToString = (item: unknown) => {
if (typeof item === "string") {
return item;
} else {
return item?.toString() ?? "";
}
};
export const ExpandoCombobox = forwardRef(function ExpandoCombobox<
Item = string,
S extends SelectionStrategy = "default"
Item = string
>(
{
className: classNameProp,
InputProps: InputPropsProp = NO_INPUT_PROPS,
ListProps: ListPropsProp,
onInputChange,
children,
className,
inputProps: inputPropsProp,
itemToString = defaultItemToString,
multiselect,
onChange,
onSelectionChange,
selectionStrategy,
source,
style,
title,
value = "",
value: valueProp,
...props
}: ExpandoComboboxProps<Item, S>,
}: ExpandoComboboxProps<Item>,
forwardedRef: ForwardedRef<HTMLDivElement>
) {
const targetWindow = useWindow();
useComponentCssInjection({
testId: "vuu-expando-combobox",
css: expandoBoxCss,
css: expandoComboboxCss,
window: targetWindow,
});

const [text, setText] = useState(value);
const { itemToString = defaultToString } = props;
const initialValue = useRef(value);

const itemsToString = useCallback<<I = Item>(items: I[]) => string>(
(items) => {
const [first, ...rest] = items;
if (rest.length) {
return `${itemToString(first)} + ${rest.length}`;
} else {
return itemToString(first);
}
},
[itemToString]
const [open, setOpen] = useState(false);
const [value, setValue] = useState(
valueProp === undefined ? "" : valueProp.toString()
);

const handleInputChange = useCallback(
(evt: FormEvent<HTMLInputElement>) => {
const { value } = evt.target as HTMLInputElement;
setText(value);
onInputChange?.(evt);
},
[onInputChange]
);

const handleSetSelectedText = useCallback((text: string) => {
setText(text);
}, []);

const [InputProps, ListProps] = useMemo<
[
ComboBoxProps["InputProps"],
Omit<ComboBoxProps["ListProps"], "defaultSelected">
]
>(() => {
const { inputProps, ...restInputProps } = InputPropsProp;
return [
{
...restInputProps,
className: `${classBase}-Input`,
endAdornment: null,
inputProps: {
...inputProps,
autoComplete: "off",
onInput: handleInputChange,
},
},
{
...ListPropsProp,
className: cx("vuuMenuList", ListPropsProp?.className),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
"data-mode": "light",
displayedItemCount: 10,
itemHeight: 22,
maxWidth: 300,
minWidth: 80,
width: "content-width",
},
];
}, [InputPropsProp, handleInputChange, ListPropsProp]);

const handleSelectionChange = useCallback(
(_, selected) => {
if (Array.isArray(selected)) {
(onSelectionChange as MultiSelectionHandler<Item>)?.(
null,
selected as Item[]
);
} else if (selected) {
setText(itemToString(selected));
(onSelectionChange as SingleSelectionHandler<Item>)?.(
null,
selected as Item
);
}
},
[itemToString, onSelectionChange]
);
const handleChange = (evt: ChangeEvent<HTMLInputElement>) => {
const value = evt.target.value;
onChange?.(evt);
setValue(value);
};

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const getSelected = (): any => {
if (initialValue.current === undefined) {
return undefined;
} else if (Array.isArray(initialValue.current)) {
return source?.filter((item) =>
initialValue.current.includes(itemToString(item))
);
const handleSelectionChange = (evt: SyntheticEvent, newSelected: Item[]) => {
if (multiselect) {
onSelectionChange?.(evt, newSelected);
} else {
return source?.find(
(item) => itemToString(item) === initialValue.current
);
const [selectedValue] = newSelected;
onSelectionChange?.(evt, newSelected);
setValue(itemToString(selectedValue));
}
};

const popupProps = {
minWidth: "fit-content",
};
const inputProps = useMemo<ComboBoxProps<Item>["inputProps"]>(() => {
return {
autoComplete: "off",
...inputPropsProp,
onFocus: (evt) => {
inputPropsProp?.onFocus?.(evt);
setTimeout(() => {
setOpen(true);
}, 100);
},
};
}, [inputPropsProp]);

// const matchingValues = values.filter((val) =>
// val.toLowerCase().startsWith(value.trim().toLowerCase())
// );

return (
<div
className={cx(classBase, classNameProp)}
data-text={text}
className={cx(classBase, className)}
data-text={value}
ref={forwardedRef}
style={style}
>
<ComboBox<Item, S>
<ComboBox<Item>
{...props}
PopupProps={popupProps}
// allowEnterCommitsText
className="vuuEmbedded"
defaultSelected={getSelected()}
defaultValue={
Array.isArray(initialValue.current)
? itemsToString<string>(initialValue.current)
: initialValue.current
}
fullWidth
ListProps={ListProps}
InputProps={InputProps}
itemsToString={itemsToString}
inputProps={inputProps}
multiselect={multiselect}
onChange={handleChange}
onOpenChange={setOpen}
onSelectionChange={handleSelectionChange}
onSetSelectedText={handleSetSelectedText}
selectionStrategy={selectionStrategy}
source={source}
/>
open={open}
value={value}
>
{children}
</ComboBox>
</div>
);
}) as <Item, S extends SelectionStrategy = "default">(
props: ExpandoComboboxProps<Item, S> & {
ref?: ForwardedRef<HTMLDivElement>;
}
) => ReactElement<ExpandoComboboxProps<Item, S>>;
}) as <Item = string>(
props: ExpandoComboboxProps<Item> & { ref?: Ref<HTMLDivElement> }
) => JSX.Element;

0 comments on commit 6cfcb9d

Please sign in to comment.