diff --git a/packages/components/frontend/autocomplete/AutoComplete.tsx b/packages/components/frontend/autocomplete/AutoComplete.tsx index bc12deff7..1148a5099 100644 --- a/packages/components/frontend/autocomplete/AutoComplete.tsx +++ b/packages/components/frontend/autocomplete/AutoComplete.tsx @@ -126,10 +126,8 @@ const AutoComplete = forwardRef(function Impl(props: AutoCompleteProps, re else onChange(selectedKeys.filter((v) => v?.trim().length).join(',')); }; - let first = !multi; useEffect(() => { - if (first) first = false; - else dispatchChange(); + dispatchChange(); if (!multi) return; // Load pre-selected items only in multi mode const ids = []; for (const key of selectedKeys) if (!valueCache[key]) ids.push(key); @@ -161,7 +159,6 @@ const AutoComplete = forwardRef(function Impl(props: AutoCompleteProps, re setSelectedKeys([key]); inputRef.current.value = key; } - dispatchChange(); if (!shouldKeepOpen) { setItemList([]); setCurrentItem(null); diff --git a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx index 788355117..04d50f0d8 100644 --- a/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx +++ b/packages/ui-default/components/autocomplete/components/UserSelectAutoComplete.tsx @@ -4,14 +4,14 @@ import PropTypes from 'prop-types'; import { forwardRef } from 'react'; import { api } from 'vj/utils'; -const UserSelectAutoComplete = forwardRef, AutoCompleteProps & { byId?: boolean }>((props, ref) => ( +const UserSelectAutoComplete = forwardRef, AutoCompleteProps>((props, ref) => ( ref={ref as any} cacheKey="user" queryItems={(query) => api('users', { search: query }, ['_id', 'uname', 'displayName', 'avatarUrl'])} fetchItems={(ids) => api('users', { auto: ids }, ['_id', 'uname', 'displayName'])} itemText={(user) => user.uname + (user.displayName ? ` (${user.displayName})` : '')} - itemKey={(user) => ((props.multi || props.byId || /^[+-]?\d+$/.test(user.uname.trim())) ? user._id.toString() : user.uname)} + itemKey={(user) => ((props.multi || /^[+-]?\d+$/.test(user.uname.trim())) ? user._id.toString() : user.uname)} renderItem={(user) => (
diff --git a/packages/ui-default/components/dialog/index.tsx b/packages/ui-default/components/dialog/index.tsx index 6d8b44819..b5b58866f 100644 --- a/packages/ui-default/components/dialog/index.tsx +++ b/packages/ui-default/components/dialog/index.tsx @@ -113,7 +113,7 @@ export class ConfirmDialog extends Dialog { } export interface Field { - type: 'text' | 'checkbox' | 'user' | 'domain'; + type: 'text' | 'checkbox' | 'user' | 'userId' | 'username' | 'domain'; placeholder?: string; label?: string; autofocus?: boolean; @@ -121,13 +121,23 @@ export interface Field { default?: string; } -export async function prompt(title: string, fields: Record) { - let valueCache: Record = {} as any; +type Result> = { + [K in keyof R]: ('text' | 'password' | 'username' | 'domain') extends R[K]['type'] ? string + : R[K]['type'] extends 'checkbox' ? boolean + : R[K]['type'] extends 'userId' ? number + : R[K]['type'] extends 'user' ? any + : never; +}; + +export async function prompt>(title: string, fields: R): Promise> { + let valueCache: Result = {} as any; const defaultValues = Object.fromEntries(Object.entries(fields) - .map(([name, field]: [T, Field]) => [name, field.default || ''])) as Record; + .map(([name, field]: [T, Field]) => [name, field.default || ''])) as Result; const Component = () => { const [values, setValues] = React.useState(defaultValues); + const [selected, setSelected] = React.useState>>({}); + const refs = React.useRef>>>({}); React.useEffect(() => { valueCache = values; @@ -139,23 +149,27 @@ export async function prompt(title: string, fields: Record
{Object.entries(fields).map(([name, field]: [string, Field]) =>
- {['text', 'user', 'domain'].includes(field.type) &&