@kwiz/fluentui
Version:
KWIZ common controls for FluentUI
94 lines • 4.39 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Dropdown, makeStyles, mergeClasses, Option } from '@fluentui/react-components';
import { CommonLogger, filterEmptyEntries, firstOrNull, isNotEmptyArray, isNotEmptyString, isNullOrUndefined } from '@kwiz/common';
import React, { useMemo, useState } from 'react';
import { useKWIZFluentContext } from '../helpers/context-internal';
import { useControlledStateTracker } from '../helpers/use-controlled-state-tracker';
const logger = new CommonLogger("DropdownEX");
const useStyles = makeStyles({
root: {
minWidth: "auto"
},
filter: {
position: "absolute",
zIndex: 1,
top: "-8px", right: 0
}
});
function cleanupValue(value) {
//netsuite sometimes puts in option values for padding
return value.replace(/ /g, ' ');
}
function $DropdownEX(props, ref) {
const classes = useStyles();
const ctx = useKWIZFluentContext();
const { valueToUse, setValue } = useControlledStateTracker({
name: "DropdownEX",
value: props.selected,
defaultValue: props.defaultSelected
});
//normalized as array
const selected = Array.isArray(valueToUse) ? valueToUse : isNullOrUndefined(valueToUse) ? [] : [valueToUse];
//sometimes control will lose value when re-rendered
//use case: public forms when editing other fields after the dropdown was set
//re-set the text value manually to fix
let text = useMemo(() => {
return filterEmptyEntries(selected.map(s => {
let v = firstOrNull(props.items, i => i.key === s);
return v ? cleanupValue(v.value) : '';
})).join(', ');
}, [selected, props.items]);
const [filter, setFilter] = useState("");
const items = useMemo(() => {
const itms = props.items;
if (isNotEmptyArray(itms)) {
if (isNotEmptyString(filter))
return itms.filter(i => i.value.toLowerCase().includes(filter));
}
return itms;
}, [props.items, filter]);
const itemOptions = useMemo(() => {
return items.map(i => {
let valueAsText = cleanupValue(i.value);
let padding = 0;
//replace any space or at start of valueAsText with padding.
while (valueAsText.startsWith(' ')) {
padding++;
valueAsText = valueAsText.slice(1);
}
return _jsx(Option, { value: i.key, text: valueAsText, children: i.option
? i.option
: _jsxs(_Fragment, { children: [padding > 0 ? _jsx("span", { style: { minWidth: `${4 * padding}px` } }) : undefined, valueAsText] }) }, i.key);
});
}, [items]);
return (_jsx(Dropdown, Object.assign({}, props, { onSelect: undefined, className: mergeClasses(classes.root, props.className), ref: ref, clearable: !props.required && !props.multiselect, appearance: ctx.inputAppearance, mountNode: ctx.mountNode,
//clear filter every time we open the dropdown
onOpenChange: () => { if (isNotEmptyString(filter))
setFilter(""); }, onKeyDown: (e) => {
if (e.key.match(/^[a-z0-9]$/i)) {
e.defaultPrevented = true;
setFilter(`${filter}${e.key}`.toLowerCase());
}
else if (e.key === "Backspace") {
setFilter(filter.slice(0, filter.length - 1));
}
}, selectedOptions: selected, value: text, onOptionSelect: (e, data) => {
let o = firstOrNull(props.items, i => i.key === data.optionValue);
if (props.multiselect) {
let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
setValue(current.map(o => o.key));
props.onSelect(o, current);
}
else {
setValue(o === null || o === void 0 ? void 0 : o.key);
props.onSelect(o);
}
}, children: itemOptions })));
}
export const DropdownEX = React.forwardRef($DropdownEX);
/** @deprecated use normal DropdownEX it is now generic */
export function getDropdownEX() {
logger.i.warn('getDropdownEX is deprecated. use DropdownEX it now supports generic types');
return React.forwardRef(($DropdownEX));
}
//# sourceMappingURL=dropdown.js.map